%pip install --upgrade langchain-text-splitters langchain-upstage from langchain_community.document_loaders import Docx2txtLoader from langchain_text_splitters import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, chunk_overlap=100 ) #loader = Docx2txtLoader('./tax_with_table.docx') loader = Docx2txtLoader('./tax_with_markdown.docx') documents_list = loader.load_and_split(text_splitter=text_splitter) documents_list1=documents_list[len(documents_list)//2:] documents_list2=documents_list[:len(documents_list)//2] from langchain_upstage import UpstageEmbeddings from dotenv import load_dotenv load_dotenv() embedding = UpstageEmbeddings(model="solar-embedding-1-large") import os from pinecone import Pinecone from langchain_pinecone import PineconeVectorStore pinecone_api_key = os.environ.get("PINECONE_API_KEY") pc = Pinecone(api_key=pinecone_api_key) index_name = "tax-markdown-index" vector_store = PineconeVectorStore.from_documents(documents_list1, embedding, index_name=index_name) vector_store.add_documents(documents_list2) query = "연봉 5천만원인 직장인의 소득세는 얼마인가요?" #retrieved_docs = database.similarity_search(query) from langchain_upstage import ChatUpstage llm = ChatUpstage() # prompt = f""" # - 당신은 최고의 한국 소득세 전문가입니다 # - [Context]를 참고해서 아용자의 질문에 답변해주세요 # [Context] # {retrieved_docs} # Question: {query} # """ # ai_message = llm.invoke(prompt) from langchain import hub prompt = hub.pull("rlm/rag-prompt") # retriever = vector_store.as_retriever() # retriever.invoke("연봉 5천만원인 거주자의 소득세는 얼마인가요?") from langchain.chains import RetrievalQA qa_chain = RetrievalQA.from_chain_type( llm=llm, retriever=vector_store.as_retriever(), chain_type_kwargs={"prompt": prompt} ) query = "연봉 5천만원인 직장인의 소득세는 얼마인가요? 2024년도 소득 기준으로 하고 인적공제는 혼자고 공제항목은 평균정도로 잡아봐." ai_message = qa_chain({"query":query}) ai_message from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate dictionary = ["사람을 나타내는 표현 -> 거주자"] prompt = ChatPromptTemplate.from_template(f""" 사용자의 질문을 보고 우리의 사전을 참고해서 사용자의 질문을 변경해주세요. 만약 변경할 필요가 없다고 판단된다면 사용자의 질문을 변경하지 않아도 됩니다. 사전 : {dictionary} """) dictionary_chain = prompt | llm | StrOutputParser() dictionary_chain.invoke({"question": "연봉 5천만원인 직장인의 소득세는 얼마인가요?"}) tax_chain = {"query": dictionary_chain} | qa_chain ai_response = tax_chain.invoke({"question": "연봉 5천만원인 직장인의 소득세는 얼마인가요?"}) ai_response 이 상황에서 dictionary_chain.invoke({"question":"연봉 5천만원인 직장인의 소득세는 얼마인가요?"})를 했을때 직장인을 거주자로 바꾸는게 아니라 답변을 아래와같이줍니다 ㅜㅜ '사용자의 질문을 사람을 나타내는 표현을 우리의 사전을 참고하여 "거주자"로 변경해보겠습니다. 그러나 사용자가 질문을 아직 제출하지 않았으므로, 가상의 질문을 만들어 변경해보겠습니다.\n\n가상의 사용자 질문: "사람들이 자주 방문하는 관광지는 어디인가요?"\n\n변경된 질문: "거주자들이 자주 방문하는 관광지는 어디인가요?"\n\n만약 사용자의 질문이 이미 적절하거나 변경이 필요하지 않다고 판단되면 질문을 변경하지 않습니다. 실제 사용자 질문을 알려주시면 그에 맞게 도움을 드리겠습니다.' 그 결과 최종 response도 아래와같이 나와버리네요 ㅠㅠ ['e9f858cf-0c76-4887-9556-22c5f32eadf4', '40a151b4-ee72-4f3c-ab61-055114344dd9', '6072bcb7-4ea0-4fbc-8828-e74cb883d162', 'a6a9fc0d-eb7a-482d-8b9d-e12073ea6dce', '9d16b74e-557b-475d-b536-8f37e77306a8', '5ad3b09f-8afa-42b6-8cec-a77a525e6f4b', 'a678eb3b-1b5d-4106-888f-bdf3302ac84c', '57a9b7e1-9511-4a34-822d-7f2a0ae710fc', '4ecd54b8-fac0-459b-ae14-4985f2dd0a20', 'bc50c84a-4770-4756-a8d4-06985387f03b', '65a1116f-93c3-4a5b-8a17-3018ccbd26b0', 'cfde5547-ee30-417c-b2dd-ed0c7f7a602d', '5f9a45e2-0279-4363-bb7c-b0fe85cc0595', '907860e1-e1c4-410d-8fa2-8eb82808f008', '682389cf-f2ad-45df-9db8-a1b6b046f43d', '76395c00-dffa-4d26-9f5e-fd910228538c', '136528f9-c253-406f-a5c8-c8fcd4fad21f', '5f6c5158-cd35-4b74-ae75-ec1f34c35394', 'b8cb52ec-e324-48c1-83a1-31c02e4d202d', '98dfe4bc-c0de-4f7e-996e-bf20416915dc', 'c9018194-109e-443c-8dd0-af5607de3c6f', '2120a161-f0f4-4c91-9759-5bb0aebb995d', '96948c3b-5937-44c1-ad84-04ed923e695b', '490a568c-d378-4cbb-aa69-bf195e41371b', '14e8fcec-7c2c-45d6-ac7b-14c009a6acc5', ... '84802efa-23df-4a84-b311-577933f09c51', 'a22be767-fa83-4325-a605-498647daa19e', '879e0a7f-50ed-4cf1-8b6e-f4dbd2a498fc', 'e275ec53-9664-4a18-a813-d40b0e130a23', 'fbde51af-1fbb-445b-8c59-68d61b9bfa2d'] Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings... /Users/arang/.pyenv/versions/3.13.2/envs/inflearn-llm-application/lib/python3.13/site-packages/langsmith/client.py:272 : LangSmithMissingAPIKeyWarning: API key must be provided when using hosted LangSmith API warnings.warn( {'query': '연봉 5천만원인 직장인의 소득세는 얼마인가요? 2024년도 소득 기준으로 하고 인적공제는 혼자고 공제항목은 평균정도로 잡아봐.', 'result': '연봉 5천만원의 직장인의 경우, 2024년도 소득 기준으로 산출세액은 552만원입니다. 여기에 근로소득세액공제 29만원을 적용하면, 최종 소득세는 523만원이 됩니다.'} {'query': '사용자의 질문이 "사람을 나타내는 표현은 무엇인가요?"라면, 우리의 사전을 참고하여 질문을 변경하면 다음과 같습니다: "거주자를 나타내는 표현은 무엇인가요?" \n\n만약 사용자의 질문이 다른 주제나 내용을 다루고 있다면, 해당 질문에 맞게 사전을 참고하여 변경할 수 있습니다. 만약 질문이 이미 명확하고 변경할 필요가 없다고 판단된다면, 질문을 그대로 유지할 수 있습니다.', 'result': '사용자의 질문이 "사람을 나타내는 표현은 무엇인가요?"라면, 우리의 사전을 참고하여 질문을 변경하면 다음과 같습니다: "거주자를 나타내는 표현은 무엇인가요?" 사전에서 "거주자"는 국내에 주소를 두거나 183일 이상의 거소를 둔 개인을 의미합니다.'}
안녕하세요 강사님. 08-14 강의 도입부에서 FormView는 ModelForm클래스가 아닌 Form클래스에 대한 일반적인 패턴을 구현하는데 사용한다고 말씀 주셨고 코드에서도 db저장 로직을 직접 구현해 주셨는데요. FormView에서도 form_class를 ModelForm으로 지정하면 좀 더 간결한 것 같은데 혹시 FormView에서 ModelForm을 사용하면 안되는 이유가 있을까요? [코드 예시] ㄴ강의 내 #1. FormView 활용에 나오는 오른쪽 코드에서 form_class를 ModelForm으로 만들어 form_valid를 오버라이딩 하였습니다. class PostCreateView(FormView): form_class = PostForm template_name = "blog/post_new.html" success_url = "/admin/" def form_valid(self, form): form.save() return super(PostCreateView, self).form_valid(form)
서버로부터 받아오는 Posts를 <PostList/> 컴포넌트에서 상태로 관리하는데, 이것은 전역 상태로 관리하지 않는 이유가 있을까요? postStore에서 getTotalPages를 할때, 고정된 값 100을 사용했는데, 실제 서비스라면 어떻게 처리해야하나요? postStore에서 posts.length와 같은 전체 개수를 알아야할것같은데.
Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
안녕하세요, 잘 학습하고 있는 학생입니다. 강의 따라가면서, streaming 파트는 다 적용을 했습니다. 소개 탭에서 홈 탭으로 이동 시에 태그목록과 포스트리스트도 skeleton 로딩페이지 잘 적용됩니다. '홈'을 눌렀을때, 기존의 '로딩 되는 중에 아무 변화 없이 사용자를 마냥 기다리게 함'에서 현재의 '로딩 되는 중에 skeleton 보여줌으로써 로딩되고 있음을 나타내줌'으로의 개선은 사용자 경험에 있어서, 정말 효과적인 방법이라고 느꼈습니다. 다만, 문제가 있습니다. '홈' 을 눌러 이동하는 경우말고, 태그 목록에서 나머지 'css'태그, 'git'태그 등등 이를 직접 클릭해서 이동하는 경우에는 streaming 이 적용되지 않습니다. 예를 들어, 홈을 클릭한 상황에서는 skeleton ui가 잘 나타나지만, 그렇게 홈으로 이동한 상황에서 다른 태그(css,Git 등)로 다시 이동하는 상황에서는 적용되지 않고 그대로입니다. 이를 해결하기 위해선 어떻게 해야 하나요?
안녕하세요 강사님 좋은 강의 잘 듣고 있습니다! useSuspenseQuery를 사용 중에 고민이 생겨서 질문 드립니다. 제가 구현하고 있는 프로젝트의 대부분 API는 인증이 필요합니다. refresh token 은 http only 쿠키로 관리하고, access token 은 쿠키에 저장하고, 요청 헤더에 넣어 인증을 하고 있습니다. useSuspenseQuery 를 사용하는 페이지에서 SSR 단계에 401 에러가 발생합니다. 이후 CSR 전환 시에는 정상적으로 데이터를 불러와 화면은 최종적으로 렌더링됩니다. 해당 페이지를 dynamic import 로 CSR 강제하면 401이 발생하지 않습니다. 제가 추정한 원인은 클라이언트 컴포넌트 내부라도 초기 렌더링 시 SSR 패스에서 useSuspenseQuery 가 실행되어 서버에서 API 요청이 발생. 이때 공통 axios 인스턴스가 클라이언트 전용 방식으로 쿠키를 읽어 헤더에 토큰을 주입하도록 구현되어 있어, 서버 환경에서는 토큰을 읽지 못해 401이 발생하는 것으로 판단했습니다. 해결을 위해 시도한 방법 prefetchQuery + useSuspenseQuery 조합으로, prefetchQuery 단계에서 next/headers 를 통해 서버 환경에서 토큰을 읽어 주입하면 401이 사라졌습니다. 다만, 모든 useSuspenseQuery 호출 지점마다 prefetchQuery 를 추가하는 것은 과도하다고 느껴 대안을 모색 중입니다. 질문 사항 왜 SSR에서 실행되나요? 클라이언트 컴포넌트 내부에서 호출하는데도 useSuspenseQuery 가 SSR 렌더링 단계에서 동작하는 메커니즘을 정확히 이해하고 싶습니다. useSuspenseQuery 의 단점/주의점 강의에서는 주 사용을 권장해 주셨는데, 모든 데이터 관리에 useQuery 대신 useSuspenseQuery 사용하는게 좋은건지 실제 서비스에서 고려해야 할 단점이나 주의사항이 궁금합니다. 401을 피하는 권장 패턴 제 환경처럼 서버에서 토큰을 읽지 못해 401이 나는 경우, 제가 시도한 방법 인 prefetchQuery 적용 외에 권장되는 표준 패턴이 있을까요? prefetchQuery 를 여러 곳에서 사용할 때의 리스크 여러 페이지/쿼리에서 prefetchQuery 를 널리 적용하면 TTFB 지연, 직렬화된 캐시의 HTML 페이로드 증가, 중복 호출 등의 문제가 커질 수 있을까요? 그렇다면 적절한 적용 기준이나 완화 전략이 궁금합니다. 그리고 어떤 기준으로 prefetchQuery 를 적용하면 좋을지도 궁금합니다. 문서와 블로그, GPT 등을 찾아봤지만 명확히 정리하기 어렵고, 제가 질문을 드릴 수 있는 최고 전문가라고 생각하여 의견을 여쭙니다. 긴글 읽어주셔서 감사합니다! 아래 에러가 발생하는 예시 코드 첨부 드립니다. (APage를 CSR로 강제하면 에러 미발생) import Spinner from "@/components/common/spinner/Spinner"; import A from "@/components/pages/A"; import { Suspense } from "react"; import { ErrorBoundary } from "react-error-boundary"; interface APageProps { params: { id: string; }; } export default async function APage({ params, }: APageProps) { const { id } = params; const parsedId = parseInt(id); return ( <ErrorBoundary fallback={<div>에러가 발생했습니다</div>}> <Suspense fallback={<Spinner fullscreen />}> <A id={parsedId} /> </Suspense> </ErrorBoundary> ); } "use client"; import { useGetAList } from "@/api/A/queries/useGetAList"; interface AProps { id: number; } export default function A ({ id }: AProps) { const { data: probiomeList } = useGetAList(id); // 생략 import { queryKeys } from "@/constants/queryKeys"; import { UseSuspenseQueryCustomOptions } from "@/types"; import { useSuspenseQuery } from "@tanstack/react-query"; import { getAList } from "../A"; import { AList } from "@/types/A"; export function useGetAList( id: number, queryOptions?: UseSuspenseQueryCustomOptions<AList> ) { return useSuspenseQuery({ queryFn: () => getAList(id), queryKey: [ queryKeys.A.BASE, queryKeys.A.GET_A_LIST, id, ], ...queryOptions, }); }
어떤 강의에 대한 질문인지 자세하게 알려주시면 답변을 드리는데 도움이 됩니다. 스크린샷 윈도우키 + 쉬프트키 + S(윈도우) 을 자세히 첨부하시면 답변 드리는데 많은 도움이 됩니다. 동영상 재생 관련 같은 인프런 서비스 관련 문의는 1:1 문의하기를 이용해 주세요. 안녕하세요 강의를 아주 잘 듣고 있는 학생중 한명입니다. webhook 만들고 있는데요 응답 timeout 이 있어서 시간을 체크해서 3초 이내로 ai agent 가 응답을 만들었으면 webhook 으로 리턴해주고 아니면 응답 대기 메세지를 리턴하고 callback url 로 메세지를 보내는걸 만드려고 하는데요 문제는 code 노드에서 두갈래로 병렬 처리가 안되는 문제 가 있습니다. 원래 n8n 이 순차적으로 처리하게 만들어서 안된다고 하는거 같은데요 해결 할 수 있는 방법이 있는지 문의 드립니다.
첫번쨰 dag 실행시 링크로 가쟈오는 csv 파일이 xml 파일로 읽어드리면서 에러로 띄우네요?? 도커에서 csv 파일을 읽을떄 에러메세지를 xml로 리턴하는거같은데 우선 csv 파일자체를 넣어서 하드코딩했습니다. 혹시 도커로 사용시 외부 파일받아올때 보안적인 부분에서 해제해야되는경우가있나요?
💡 질문하기 전에 먼저 확인해보세요! 답변을 기다리는 동안, 아래 항목들을 먼저 확인해보시면 문제가 해결될 수도 있어요. 강의 내용 다시 보기: 혹시 놓친 부분이 없는지 해당 챕터의 강의를 한 번 더 돌려보셨나요? 오타 및 들여쓰기 확인: 파이썬은 특히 들여쓰기에 민감해요. 코드에 오타나 잘못된 들여쓰기는 없는지 꼼꼼히 확인해주세요. 에러 메시지 검색: 빨간색 에러 메시지가 떴다면, 메시지 전체를 복사해서 구글에 그대로 붙여넣기 해보세요. 전 세계 개발자들이 비슷한 문제를 겪고 해결책을 공유해두었을 확률이 높습니다. Q&A 게시판 검색: 혹시 다른 분이 먼저 비슷한 질문을 올렸는지 게시판을 한번 살펴보는 것도 좋은 방법이에요.
🚨 필독) 질문하시기 전에 꼭 읽어주세요 (10초 소요) 제목을 구체적으로 작성해 주세요 ✅ 좋은 예 : 감정일기장 Home 구현중 xx 이슈가 발생합니다. ⛔ ️ 나쁜 예 : 이거 왜 안되나요?, 오류나요 도와주세요 등 비슷한 궁금함을 갖고 계신 분들께 도움이 될 수 있어요! 코드의 이슈는 전체 프로젝트를 "링크 형태"로 올려주셔야 원인을 파악할 수 있습니다. 깃허브, 구글드라이브 등의 수단을 통해 링크 형태로 전달해주세요 직접 실행해보며 원인을 파악해야 하기 때문에 텍스트 형태로 붙여넣는건 삼가해주세요 🥲 답변이 도움이 되셨다면 답글 or 해결완료 버튼을 클릭해주세요 비슷한 궁금함을 갖고 계신 분들께 도움이 될 수 있어요! 제 답변이 여러분께 도움이 되었는지 저도 알고 싶어요 🥲 강의 내용에 궁금한 점이 있다면 몇 챕터의 몇 분 몇 초인지 알려주시면 더 좋아요 더 빠른 답변이 가능합니다!