여러 문서에서 찾아서 답변하는 챗봇 만들기
!pip install -q langchain langchain-openai openai tiktoken chromadb langchain-community
|
!unzip data
|
Archive: data.zip inflating: 1.txt inflating: 10.txt inflating: 11.txt inflating: 12.txt inflating: 13.txt inflating: 14.txt inflating: 15.txt inflating: 16.txt inflating: 17.txt inflating: 18.txt inflating: 19.txt inflating: 2.txt inflating: 20.txt inflating: 21.txt inflating: 22.txt inflating: 23.txt inflating: 24.txt inflating: 25.txt inflating: 26.txt inflating: 27.txt inflating: 28.txt inflating: 29.txt inflating: 3.txt inflating: 30.txt inflating: 31.txt inflating: 32.txt inflating: 33.txt inflating: 34.txt inflating: 35.txt inflating: 36.txt inflating: 37.txt inflating: 38.txt inflating: 39.txt inflating: 4.txt inflating: 40.txt inflating: 41.txt inflating: 42.txt inflating: 43.txt inflating: 44.txt inflating: 45.txt inflating: 46.txt inflating: 47.txt inflating: 48.txt inflating: 49.txt inflating: 5.txt inflating: 50.txt inflating: 51.txt inflating: 52.txt inflating: 53.txt inflating: 54.txt inflating: 55.txt inflating: 56.txt inflating: 57.txt inflating: 6.txt inflating: 7.txt inflating: 8.txt inflating: 9.txt inflating: embedding.csv |
Setting up LangChain
OpenAI API Key
https://platform.openai.com/account/api-keys
import os
os.environ["OPENAI_API_KEY"] = "여러분의 Key 값"
|
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.document_loaders import TextLoader
from langchain.document_loaders import DirectoryLoader
from collections import Counter
|
Load multiple and process documents
DirectoryLoader()는 디렉토리 내의 모든 문서들을 로드하는 역할을 합니다. 이때 glob는 해당 디렉토리 내의 어떤 확장자를 가진 파일들을 로드할 것인지를 결정합니다. 예를 들어 *.txt를 매개변수로 사용하면, 해당 디렉토리 내의 모든 txt 파일을 로드합니다. 현재 경로에 있는 모든 txt 파일을 로드하고 txt 파일의 본문은 documents라는 파이썬 리스트의 각 원소로 할당하겠습니다.
loader = DirectoryLoader('.', glob="*.txt", loader_cls=TextLoader)
documents = loader.load()
print('문서의 개수 :', len(documents))
|
문서의 개수 : 57
파이썬 리스트에 해당하는 documents에서 임의로 1번 문서와 21번 문서를 출력해보겠습니다.
print('1번 문서 :', documents[1])
print('-' * 20)
print('21번 문서 :', documents[21])
print('-' * 20)
|
1번 문서 : page_content='정책이름: 서울희망 직업전문학교 장학금 서울시 교육정책과에서 주관하는 교육 정책으로, 직업전문학교에서 경제적인 걱정 없이 학업을 수행할 수 있도록 등록금을 지원하는 장학금이 있습니다. 이 정책은 2023년 3월 1일부터 2023년 12월 31일까지 운영됩니다. 학기별로 100만원이 지원되며, 총 300명에게 지원될 예정입니다. 신청 자격은 19세 이상 100세 이하의 연령을 가진 서울 소재 직업전문학교 재학생으로서 학점은행제를 실시하는 기관에 재학 중인 자입니다. 또한, 기초생활수급자나 차상위계층에 속하며, 등록금 실납입액이 100만원 이상인 경우에 지원받을 수 있습니다. 추가적으로, 신청 시 12학점 이상을 신청한 자 및 대학 재학 중인 자격을 갖추고 있어야 합니다. 학력이나 전공에 대한 요건은 없으며, 취업 상태에 제한은 없지만 저소득층에 해당하는 자를 우대합니다. 다만 등록금 초과로 장학금 중복 수혜자는 참여가 제한됩니다. 신청은 홈페이지를 통해 신청할 수 있으며, 심사를 거쳐 최종 선발 결과가 발표됩니다. 신청서와 함께 소득증빙서류를 제출해야 합니다. 이 정책은 서울장학재단에서 운영되며, 자세한 내용은 https://www.hissf.or.kr에서 확인하실 수 있습니다.' metadata={'source': '18.txt'} -------------------- 21번 문서 : page_content='정책이름: 청년 전월세보증보험료 지원 서울시청 미래청년기획단에서 주관하는 주거 정책으로, 무주택 세대주인 청년 임차인이 가입하고 납부한 보증보험료를 지원하는 정책이 있습니다. 이 정책은 2023년 1월 1일부터 2023년 12월 31일까지 운영됩니다. 지원 내용은 보증보험료 지원이며, 총 1,000명에게 지원될 예정입니다. 신청 자격은 19세부터 39세까지의 연령을 가진 무주택 청년 가구입니다. 학력이나 전공에 대한 요건은 없으며, 취업 상태나 특화 분야에도 제한이 없습니다. 다만 주택을 소유한 자 등은 참여가 제한됩니다. 신청은 청년몽땅정보통 웹사이트에서 온라인으로 신청할 수 있습니다. 신청서류로는 가입보증서 등이 제출되어야 합니다. 접수된 신청서는 심사를 거쳐 최종 발표는 2023년 12월에 예정되어 있습니다. 이 정책은 서울시청 미래청년기획단에서 운영되며, 자세한 내용은 https://youth.seoul.go.kr에서 확인하실 수 있습니다. ' metadata={'source': '20.txt'} ------------------ |
documents 리스트의 각 원소의 구조를 살펴보면 page_content의 값으로 본문이 들어가고, metadata 안의 source의 값으로 해당 문서의 원본 파일의 이름이 기재되어져 있습니다.
Split texts
Langchain의 RecursiveCharacterTextSplitter()는 주어진 문서들을 더 작은 단위의 텍스트 뭉치(chunk)로 잘라주는 역할을 합니다.
chunk_size는 텍스트의 분할 기준이 되는 길이를 설정하고, chunk_overlap은 텍스트를 분할할 경우 텍스트의 내용을 얼만큼 겹치게 할 것인지를 의미합니다. 위에서 총 57개의 문서 파일을 로드한 documents를 입력으로 사용하여 분할된 텍스트 리스트를 texts에 저장합니다.
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
texts = text_splitter.split_documents(documents)
print('분할된 텍스트의 개수 :', len(texts))
|
분할된 텍스트의 개수 : 64
57개의 문서가 총 64개의 텍스트로 분할되었습니다. 그 중 임의로 첫번째 문서를 출력해보겠습니다.
texts[0]
|
Document(metadata={'source': '15.txt'}, page_content='정책제목: 서울시 고립ㆍ은둔청년 지원사업\n\n서울시청 미래청년기획단에서 주최하는 마음건강 정책은 고립청년과 은둔청년의 사회성 향상과 자아 회복을 위해 심리상담 및 다양한 맞춤형 프로그램을 지원하는 것입니다. 이 정책은 심리상담과 전문기관 치료 연계를 지원하며, 자기 이해, 관계 형성, 공동 생활, 취미 체험, 예술 활동 등의 맞춤형 프로그램을 제공합니다.\n\n이 사업은 2023년 4월 25일부터 2023년 12월 31일까지 운영됩니다. 사업 신청 기간은 2023년 4월 25일부터 2023년 11월 3일까지이며, 지원 규모는 500명입니다. 관련 사이트에 대한 정보는 제공되지 않았습니다.\n\n신청자격은 19세부터 39세까지의 서울시 거주 고립은둔 청년들입니다. 신청자의 고립 여부는 척도 및 초기 상담을 통해 판단됩니다. 학력, 전공, 취업 상태, 특화 분야에 대한 요건은 없습니다.\n\n신청은 https://youth.seoul.go.kr 사이트에서 청년몽땅정보통 로그인 후 온라인 접수를 진행해야 합니다. 심사 및 발표에 대한 자세한 정보는 공고를 참조하시기 바랍니다. 제출해야 할 서류는 공고에 명시되어 있습니다.\n\n이 사업은 민간 보조 사업자가 운영합니다. 추가적인 사항에 대한 정보는 제공되지 않았으므로, 해당 기관으로 문의하시기 바랍니다.')
형식은 documents 원소에서 확인하였을 때와 동일하며 page_content에는 분할된 텍스트이 본문이 저장되어져 있고, source에는 해당 본문의 원본 파일의 이름이 저장되어져 있습니다. 57개의 문서가 64개의 텍스트로 분할되었다는 것은 일부 문서는 추가적으로 분할되었음을 의미합니다.
metadata 안의 source의 값을 이용하여 어떤 문서들을 추가적으로 분할되었는지 확인해보겠습니다. texts의 각 원소들의 source 값을 모두 체크하였을 때 source 값이 중복되어 등장한다면 해당 문서는 추가적으로 분할되었음을 의미합니다.
source_lst = []
for i in range(0, len(texts)):
source_lst.append(texts[i].metadata['source'])
element_counts = Counter(source_lst)
filtered_counts = {key: value for key, value in element_counts.items() if value >= 2}
print('2개 이상으로 분할된 문서 :', filtered_counts)
print('분할된 텍스트의 개수 :', len(documents) + len(filtered_counts))
|
2개 이상으로 분할된 문서 : {'31.txt': 2, '36.txt': 2, '22.txt': 2, '49.txt': 2, '48.txt': 2, '40.txt': 2, '23.txt': 2}
분할된 텍스트의 개수 : 64
확인 결과 48번 문서, 23번 문서, 31번 문서, 49번 문서, 36번 문서, 22번 문서, 40번 문서가 2개의 텍스트로 추가적으로 분할되었습니다. 총 57개의 문서 중 7개의 문서가 2개의 텍스트로 분할되었음으로 총 합 64개의 텍스트가 생기게 됩니다.
Create Chroma DB
OpenAI Embedding API를 이용하여 텍스트를 임베딩하고, 코사인 유사도를 통해 유사한 텍스트를 가져오는 실습을 진행한 바 있습니다.
Chroma DB는 이 과정들을 기능 별로 이미 구현하여 사용자가 벡터를 좀 더 쉽게 다룰 수 있도록 도와주는 편리한 벡터 응용 도구입니다.
Chroma.from_documents()를 통해 벡터 도구 객체를 선언합니다. 이때 documents에는 벡터화의 단위가 될 텍스트 리스트를 매개변수로 사용하고, embedding에는 어떤 종류의 임베딩을 사용할 것인지를 기재해줍니다.
embedding = OpenAIEmbeddings()
vectordb = Chroma.from_documents(
documents=texts,
embedding=embedding)
|
ipython-input-11-2a3c4b183c37>:1: LangChainDeprecationWarning: The class `OpenAIEmbeddings` was deprecated in LangChain 0.0.9 and will be removed in 1.0. An updated version of the class exists in the :class:`~langchain-openai package and should be used instead. To use it run `pip install -U :class:`~langchain-openai` and import as `from :class:`~langchain_openai import OpenAIEmbeddings``. embedding = OpenAIEmbeddings()
Make a retriever
벡터 도구 객체를 선언하고 나면 as_retriever()를 통해서 입력된 텍스트로부터 유사한 텍스트를 찾아주는 retriever를 선언할 수 있습니다.
retriever를 선언 후 get_relevant_documents()를 통해 입력된 텍스트와 유사한 문서들을 찾아서 반환합니다.
벡터의 유사도를 구하는 과정을 별도의 추가 구현없이 손쉽게 사용할 수 있게 됩니다.
retriever = vectordb.as_retriever()
|
docs = retriever.get_relevant_documents("신혼 부부를 위한 정책이 있어?")
print('유사 문서 개수 :', len(docs))
print('--' * 20)
print('첫번째 유사 문서 :', docs[0])
print('--' * 20)
print('각 유사 문서의 문서 출처 :')
for doc in docs:
print(doc.metadata["source"])
|
<ipython-input-13-de40e72fab8b>:1: LangChainDeprecationWarning: The method `BaseRetriever.get_relevant_documents` was deprecated in langchain-core 0.1.46 and will be removed in 1.0. Use :meth:`~invoke` instead.
docs = retriever.get_relevant_documents("신혼 부부를 위한 정책이 있어?")
유사 문서 개수 : 4
----------------------------------------
첫번째 유사 문서 : page_content='이 정책은 주거마련에 대한 부담을 완화하여 혼인수 감소와 출산기피 현상을 해결하고, 더 나은 주거환경을 제공하기 위해 서울시에서 운영하는 정책입니다. 대상 가구는 총 8,000가구로 제한되며, 지원 기간은 2023년 1월 1일부터 2023년 12월 31일까지입니다.
이 정책에 참여하기 위해서는 다음의 신청자격을 충족해야 합니다. 먼저, 서울시민이거나 대출 후 1개월 이내에 서울로 전입 예정이어야 합니다. 또한 혼인신고일 기준으로 7년 이내의 신혼부부이거나 서울시 추천서 신청일로부터 6개월 이내에 결혼식 예정인 예비신혼부부여야 합니다. 부부의 합산 연소득은 9천 7백만원 이하여야 하며, 본인 및 배우자는 무주택자여야 합니다. 또한, 특정 주택 조건을 충족하는 주택의 임대차계약을 체결한 자에게 대출이 지원됩니다.
이 정책은 서울주거포털(https://housing.seoul.go.kr)을 통해 온라인으로 신청할 수 있습니다. 필요한 제출서류로는 주민등록등본, 가족관계증명서, 혼인관계증명서, 그리고 임대차계약서가 있습니다.
이 정책은 서울시청 주택정책과에서 운영되며, 자세한 사항은 해당 사이트(https://housing.seoul.go.kr)에서 확인하실 수 있습니다.' metadata={'source': '23.txt'}
----------------------------------------
각 유사 문서의 문서 출처 :
23.txt
23.txt
40.txt
39.txt
결과를 k개 반환
만약 유사한 문서의 개수를 임의로 지정하고 싶다면 retriever 선언 시에 search_kwargs={"k": <문서의 개수>}를 추가적으로 입력으로 넣어주면 됩니다. 다음의 코드는 유사한 텍스트가 2개만 출력되는 모습을 보여줍니다.
retriever = vectordb.as_retriever(search_kwargs={"k": 2})
|
docs = retriever.get_relevant_documents("신혼 부부를 위한 정책이 있어?")
for doc in docs:
print(doc.metadata["source"])
|
23.txt
23.txt
Make a chain
이제 ChatGPT API와 이미 만들어진 Prompt를 통해서 간단히 챗봇을 구현해봅시다.
RetrievalQA.from_chain_type()의 llm 매개변수의 값으로 초기에 임포트한 OpenAI()를 사용할 경우, 기본값으로 ChatGPT API를 사용합니다.
chain_type의 매개변수의 값으로 "stuff"를 사용할 경우, 사용자의 눈에는 보이지 않지만 자동으로 아래의 프롬프트를 사용하여 챗봇을 구현합니다.
Use the following pieces of context to answer the users question. If you don't know the answer, just say that you don't know, don't try to make up an answer. ---------------- {텍스트} {질문} |
{텍스트}에는 사용자의 질문으로부터 높은 유사도를 가진 텍스트가 들어가게 되고, {질문} 부분은 사용자의 질문이 들어가게 됩니다.
retriever는 입력된 사용자의 질문으로부터 유사도를 계산하는 도구를 구현하여 매개변수의 값으로 넘겨주면 됩니다. 앞서 이미 Chroma를 통해 벡터 도구 객체로부터 구현한 retreiver를 사용합니다.
return_source_documents는 챗봇의 답변에 사용된 텍스트들의 출처를 표시할 것인지를 의미합니다. return_source_documents의 값을 False로 할 경우, 챗봇의 답변이 어떤 텍스트에 근거하였는지 알 수 없습니다. 여기서는 뒤에서 근거가 되는 텍스트의 출처를 확인할 것이므로 True를 사용합니다.
qa_chain = RetrievalQA.from_chain_type(
llm=ChatOpenAI(model_name="gpt-4o", temperature=0),
chain_type="stuff",
retriever=retriever,
return_source_documents=True)
|
Query
이제 qa_chain을 통해 사용자의 입력으로부터 서울 청년 정책과 관련된 챗봇의 답변을 얻을 수 있습니다. 임의의 "대출과 관련된 정책이 궁금합니다"라는 텍스트를 입력하여 qa_chain의 반환 결과를 확인해봅시다.
input_text = "대출과 관련된 정책이 궁금합니다"
chatbot_response = qa_chain(input_text)
print(chatbot_response)
|
<ipython-input-17-be3ea85e9b61>:2: LangChainDeprecationWarning: The method `Chain.__call__` was deprecated in langchain 0.1.0 and will be removed in 1.0. Use :meth:`~invoke` instead.
chatbot_response = qa_chain(input_text)
{'query': '대출과 관련된 정책이 궁금합니다', 'result': '서울시에서 운영하는 대출 관련 정책으로는 "서울시 학자금대출 신용회복 지원사업"이 있습니다. 이 정책은 학자금 대출로 인해 신용이 떨어져 어려움을 겪고 있는 청년층을 위한 신용회복 지원을 목적으로 합니다. 서울에 거주하는 19세부터 39세까지의 청년 중 학자금 대출로 인한 신용유의자를 대상으로 하며, 분할상환약정 체결을 지원하고 초입금을 제공하여 신용유의자 등록을 해제하는 내용을 포함하고 있습니다. 신청은 서울청년포털을 통해 가능하며, 자세한 내용은 관련 사이트를 참고하시면 됩니다.', 'source_documents': [Document(metadata={'source': '35.txt'}, page_content='정책내용: 서울시 학자금대출 신용회복 지원사업\n서울특별시 미래청년기획단이 주최하는 금융 정책으로, 학자금 대출로 인해 신용이 떨어져 어려움을 겪고 있는 청년층을 위한 신용회복 지원입니다. 이 정책은 분할상환약정 체결을 지원하고 초입금을 제공함으로써 신용유의자 등록을 해제하는 내용을 포함하고 있습니다. 추가적인 자부담 없이 약정을 체결할 수 있도록 합니다.\n\n지원 대상은 서울에 거주하며 학자금 대출로 인한 신용유의자인 19세부터 39세까지의 청년들이며, 약 200여명을 지원합니다. 2018년부터 2022년에 지원을 받은 사람은 2023년 지원 대상에서 제외됩니다.\n\n신청은 서울청년포털(youth.seoul.go.kr)을 통해 신청할 수 있으며, 심사 및 발표는 매월 1~2회 선정되며, 신청인원에 따라 주기가 변동할 수 있습니다.\n\n이 정책은 서울시 미래청년기획단이 운영하며, 자세한 내용은 관련 사이트를 참고하시기 바랍니다.\n\n[참고사이트]\n신용회복 신청 안내: https://youth.seoul.go.kr/site/main/board/notice/27789?baCategory1=basic&baCommSelec=true\n신청사이트: https://youth.seoul.go.kr/site/main/applyLoanCredit/step1'), Document(metadata={'source': '39.txt'}, page_content='정책제목: 역세권청년주택 주거비지원\n서울시 전략주택공급과에서는 청년과 신혼부부의 주거비 부담을 경감하기 위해 임차보증금 대출을 지원하는 정책을 운영하고 있습니다. 이 정책은 혼인 감소 및 출산율 감소 문제를 해결하기 위한 것으로, 임차보증금에 대해 무이자 지원을 제공합니다.\n\n지원 내용은 다음과 같습니다:\n임차보증금이 1억원을 초과하는 경우: 보증금의 30% 지원 (청년 최대 4,500만원, 신혼부부 최대 6,000만원)\n임차보증금이 1억원 이하인 경우: 보증금의 50% 지원 (청년 및 신혼부부 최대 4,500만원)\n신청 자격은 19세에서 39세까지이며, 임차보증금 무이자 지원을 받을 수 있는 대상입니다. 학력 전공, 취업 상태 등 제한은 없습니다. 다만, 서울시 임차보증금 및 이자 지원과 중복 신청은 불가능하며, 타 금융기관의 전세자금 대출과는 중복 가능하나 대출 가능 여부는 해당 금융기관에 문의해야 합니다.\n\n신청은 신청서 및 필요한 서류를 제출한 후 대상자가 선정되고 통보됩니다. 이후 임대차 계약 체결과 주거비지원 약정서 체결이 이루어진 후, 지원금액이 임대인 계좌로 입금됩니다.\n\n자세한 신청 방법과 필요한 서류는 서울시 소셜공동체 온라인 포털에서 확인하실 수 있습니다. 추가적인 사항은 참고사이트1를 참고하시기 바랍니다.')]}
qa_chain의 결과를 chatbot_response에 저장하고 출력하면 'query', 'result', source_documents 세 개의 key값을 갖고 있습니다. 이 중 source_documents의 경우 내부적으로 앞서 확인한 형식인 page_content와 meta_data의 값을 가집니다.
'query'의 경우 현재 입력된 사용자의 질문을 의미합니다. 이때 qa_chain은 앞서 구현한 retriever을 통해서 내부적으로 '대출과 관련된 정책이 궁금합니다'와 유사도가 높은 텍스트 2개를 찾아냅니다. metadata 내의 source의 값에 따르면 해당 텍스트는 35.txt 파일과 39.txt 파일의 본문에 해당되며 두 본문(여기서는 page_content의 값)을 통해서 앞서 위에서 확인한 stuff 프롬프트를 통하여 챗봇은 답변을 작성합니다. 해당 챗봇의 답변은 결과적으로 'result'의 값에 해당됩니다.
현재 chatbot_response의 값은 너무 복잡합니다. 실제 사용자가 사용하는 챗봇을 가정하기 위해 chatbot_response로부터 실제 챗봇 답변에 해당하는 'result' 부분만 꺼내오고, 또한 답변에 사용된 출처를 확인하기 위해 metadata 내의 source의 값을 추가적으로 출력하는 get_chatbot_response() 함수를 구현합니다.
def get_chatbot_response(chatbot_response):
print(chatbot_response['result'].strip())
print('\n문서 출처:')
for source in chatbot_response["source_documents"]:
print(source.metadata['source'])
|
"신혼 부부의 신혼집 마련을 위한 정책이 있을까?"라는 임의의 입력에 대해서 챗봇의 답변을 확인해보겠습니다.
input_text = "신혼 부부의 신혼집 마련을 위한 정책이 있을까?"
chatbot_response = qa_chain(input_text)
get_chatbot_response(chatbot_response)
|
네, 서울시에서 운영하는 "신혼부부 임차보증금 지원" 정책이 있습니다. 이 정책은 주거마련에 대한 부담을 완화하여 혼인수 감소와 출산기피 현상을 해결하고, 더 나은 주거환경을 제공하기 위해 마련되었습니다. 지원 대상은 서울시민이거나 대출 후 1개월 이내에 서울로 전입 예정인 자로, 혼인신고일 기준으로 7년 이내의 신혼부부이거나 서울시 추천서 신청일로부터 6개월 이내에 결혼식 예정인 예비신혼부부입니다. 부부의 합산 연소득은 9천 7백만원 이하여야 하며, 본인 및 배우자는 무주택자여야 합니다. 대출은 임차보증금의 90% 이내 또는 2억원 중 작은 금액이며, 최대 연 3.6% 이차보전 및 최장 10년까지 지원됩니다. 신청은 서울주거포털을 통해 온라인으로 가능합니다.
문서 출처:
23.txt
23.txt
신혼부부 임차 보증금 지원 정책을 소개합니다. 텍스트의 출처가 23.txt가 두 번 출력됩니다. 이는 앞서 text_splitter.split_documents()가 57개의 문서를 64개의 텍스트로 분할하는 가정에서 23.txt가 두 개의 텍스트로 분할되었기 때문입니다. chatbot_response의 값을 출력해보겠습니다.
# print(chatbot_response)
chatbot_response
|
{'query': '신혼 부부의 신혼집 마련을 위한 정책이 있을까?', 'result': '네, 서울시에서 운영하는 "신혼부부 임차보증금 지원" 정책이 있습니다. 이 정책은 주거마련에 대한 부담을 완화하여 혼인수 감소와 출산기피 현상을 해결하고, 더 나은 주거환경을 제공하기 위해 마련되었습니다. 지원 대상은 서울시민이거나 대출 후 1개월 이내에 서울로 전입 예정인 자로, 혼인신고일 기준으로 7년 이내의 신혼부부이거나 서울시 추천서 신청일로부터 6개월 이내에 결혼식 예정인 예비신혼부부입니다. 부부의 합산 연소득은 9천 7백만원 이하여야 하며, 본인 및 배우자는 무주택자여야 합니다. 대출은 임차보증금의 90% 이내 또는 2억원 중 작은 금액이며, 최대 연 3.6% 이차보전 및 최장 10년까지 지원됩니다. 신청은 서울주거포털을 통해 온라인으로 가능합니다.', 'source_documents': [Document(metadata={'source': '23.txt'}, page_content='이 정책은 주거마련에 대한 부담을 완화하여 혼인수 감소와 출산기피 현상을 해결하고, 더 나은 주거환경을 제공하기 위해 서울시에서 운영하는 정책입니다. 대상 가구는 총 8,000가구로 제한되며, 지원 기간은 2023년 1월 1일부터 2023년 12월 31일까지입니다.\n\n이 정책에 참여하기 위해서는 다음의 신청자격을 충족해야 합니다. 먼저, 서울시민이거나 대출 후 1개월 이내에 서울로 전입 예정이어야 합니다. 또한 혼인신고일 기준으로 7년 이내의 신혼부부이거나 서울시 추천서 신청일로부터 6개월 이내에 결혼식 예정인 예비신혼부부여야 합니다. 부부의 합산 연소득은 9천 7백만원 이하여야 하며, 본인 및 배우자는 무주택자여야 합니다. 또한, 특정 주택 조건을 충족하는 주택의 임대차계약을 체결한 자에게 대출이 지원됩니다.\n\n이 정책은 서울주거포털(https://housing.seoul.go.kr)을 통해 온라인으로 신청할 수 있습니다. 필요한 제출서류로는 주민등록등본, 가족관계증명서, 혼인관계증명서, 그리고 임대차계약서가 있습니다.\n\n이 정책은 서울시청 주택정책과에서 운영되며, 자세한 사항은 해당 사이트(https://housing.seoul.go.kr)에서 확인하실 수 있습니다.'), Document(metadata={'source': '23.txt'}, page_content='정책제목: 신혼부부 임차보증금 지원\n정부에서는 주거 관련 정책을 통해 부담을 완화하여 더 나은 주거환경을 제공하고자 합니다. 현재 주거마련에 대한 부담으로 인해 혼인수가 감소하고 출산기피 현상이 발생하고 있습니다. 따라서 주거비 부담을 완화하여 이러한 문제를 해결하고, 좋은 주거환경을 제공하고자 합니다.\n\n이 정책은 서울시청 주택정책과에서 주관하며, 주거 마련에 대한 부담을 완화하기 위한 내용을 포함하고 있습니다. 지원 대상은 관내 임차보증금 7억 이내의 주택 또는 주거용 오피스텔에 대해 해당하는 서울시민이나 서울로 전입 예정인 자입니다. 대출한도는 임차보증금의 90% 이내 또는 2억원 중 작은 금액이며, 대출금의 최대 연 3.6% 이차보전 및 최장 10년까지 지원됩니다.\n\n주택조건과 대출형식은 한국주택금융공사 보증 및 협약은행(국민, 하나, 신한) 대출, 그리고 서울시 이차보전이 적용됩니다. 이 정책은 2023년 1월 1일부터 2023년 12월 31일까지 운영되며, 신청자격은 1세부터 100세까지의 연령을 가진 사람들이 해당합니다.\n\n대출을 받기 위한 추가 요건으로는 혼인신고일 기준으로 7년 이내의 신혼부부이거나 서울시 추천서 신청일로부터 6개월 이내에 결혼식 예정인 예비신혼부부여야 합니다. 또한 부부합산 연소득이 9천 7백만원 이하이고 본인 및 배우자가 무주택자여야 합니다. 대출을 받을 주택은 특정 조건을 충족하는 주택의 임대차계약을 체결한 사람들을 대상으로 합니다.\n\n이 정책은 서울주거포털(https://housing.seoul.go.kr)에서 온라인으로 신청할 수 있습니다. 필요한 서류로는 주민등록등본, 가족관계증명서, 혼인관계증명서, 그리고 임대차계약서가 제출되어야 합니다.\n\n이 정책은 주거마련에 대한 부담을 완화하여 혼인수 감소와 출산기피 현상을 해결하고, 더 나은 주거환경을 제공하기 위해 서울시에서 운영하는 정책입니다. 대상 가구는 총 8,000가구로 제한되며, 지원 기간은 2023년 1월 1일부터 2023년 12월 31일까지입니다.')]} |
출처가 23.txt로 동일하지만 두 개의 텍스트는 서로 다릅니다. 원본 파일 23.txt가 두 개의 텍스트로 분할되었기 때문입니다. 또한 두 개의 텍스트에서 '이 정책은 주거마련에 대한 부담을 완화하여 혼인수 감소와 출산기피 현상을 해결하고, 더 나은 주거환경을 제공하기 위해 서울시에서 운영하는 정책입니다. 대상 가구는 총 8,000가구로 제한되며, 지원 기간은 2023년 1월 1일부터 2023년 12월 31일까지입니다.' 라는 텍스트가 공통적으로 들어가있음을 확인할 수 있습니다. 이는 RecursiveCharacterTextSplitter() 선언 시에 chunk_overlap을 사용하였기 때문에 텍스트를 분할할 때 겹치지 않도록 분할하는 것이 아니라 일부 겹칠 수 있도록 허용하였기 때문입니다.
이번에는 실제 챗봇과의 답변을 가정하고 사용자의 질문으로부터 챗봇의 답변이 오면 해당 챗봇의 답변으로부터 이어서 사용자가 질문하는 시나리오를 진행해보겠습니다. "전세 자금이 부족한 사람을 위한 정책 이름이 뭐야?"라는 임의의 질문을 입력합니다.
input_text = "전세자금이 부족한 사람을 위한 정책 이름이 뭐야?"
llm_response = qa_chain(input_text)
get_chatbot_response(llm_response)
|
죄송하지만, 전세자금이 부족한 사람을 위한 특정 정책 이름에 대한 정보는 제공되지 않았습니다. 다른 정책이나 지원 프로그램에 대한 정보가 필요하시면 추가로 문의해 주세요.
문서 출처:
40.txt
40.txt
'희망두배 청년통장'이라는 정책이 있음을 알았습니다. 이어서 '희망두배 청년통장'의 구체적인 지원 내용을 문의합니다.
query = "희망두배 청년통장은 어떤걸 지원하니?"
llm_response = qa_chain(query)
get_chatbot_response(llm_response)
|
희망두배 청년통장은 저소득 근로 청년들의 자립을 지원하기 위해 서울시청 안심돌봄복지과에서 운영하는 정책입니다. 이 정책은 교육비, 주거비, 결혼자금, 창업운영자금 등을 위한 저축을 지원합니다. 지원 내용은 다음과 같습니다: - 저축 목적에 따라 월 10만원 또는 15만원의 저축액을 선택할 수 있으며, 저축기간은 2년 또는 3년입니다. - 본인이 적립한 금액의 100%를 지원받을 수 있습니다. 예를 들어, 10만원 저축 시 2년형은 480만원 이상(이자 포함), 3년형은 720만원 이상(이자 포함), 15만원 저축 시 2년형은 720만원 이상(이자 포함), 3년형은 1,080만원 이상(이자 포함)의 지원이 이루어집니다. 신청 자격은 18세에서 34세까지의 서울시 거주자로, 공고일 현재 근로 중인 자격 요건을 모두 충족하는 경우에 신청할 수 있습니다.
문서 출처:
40.txt
36.txt
이번에는 지원 조건을 문의해봅시다.
query = "희망두배 청년통장의 지원 조건은?"
llm_response = qa_chain(query)
get_chatbot_response(llm_response)
|
희망두배 청년통장의 지원 조건은 다음과 같습니다: 1. 연령: 18세에서 34세까지 2. 거주지: 서울시 거주자 3. 근로 상태: 공고일 현재 근로 중인 자 이 조건을 모두 충족하는 경우에 신청할 수 있습니다.
문서 출처:
40.txt
36.txt
희망두배 청년통장의 마감 기한을 문의해봅시다.
query = "희망두배 청년통장의 마감 기한은?"
llm_response = qa_chain(query)
get_chatbot_response(llm_response)
|
죄송하지만, 제공된 정보에는 희망두배 청년통장의 마감 기한에 대한 구체적인 내용이 포함되어 있지 않습니다. 자세한 사항은 서울시복지재단의 홈페이지나 서울시 안심돌봄복지과의 홈페이지를 통해 확인하시기 바랍니다.
문서 출처:
40.txt
37.txt
원본 문서에서 마감 기한이 구체적으로 나와있지 않아 마감 기한을 알 수 없다고 답변합니다. 해당 챗봇은 주어진 57개의 문서를 기반으로 답변하기 때문입니다. 이렇게 다수의 문서로부터 질의 응답을 할 수 있는 챗봇을 구현해보았습니다. 이렇게 구현한 챗봇을 앞서 실습과 같이 streamlit으로 UI를 구현하거나, 카카오톡이나 텔레그램 등을 연동하여 나만의 커스텀 챗봇을 구현할 수 있습니다.
!pip install gradio
|
To create a public link, set share=True in launch().
Running on https://localhost:7860/
라는 식의 문구가 나오면 위의 localhost로 시작하는 주소를 클릭하세요.
import gradio as gr
# 인터페이스를 생성.
with gr.Blocks() as demo:
chatbot = gr.Chatbot(label="청년정책챗봇") # 청년정책챗봇 레이블을 좌측 상단에 구성
msg = gr.Textbox(label="질문해주세요!") # 하단의 채팅창의 레이블
clear = gr.Button("대화 초기화") # 대화 초기화 버튼
# 챗봇의 답변을 처리하는 함수
def respond(message, chat_history):
result = qa_chain(message)
bot_message = result['result']
bot_message += ' # sources :'
# 답변의 출처를 표기
for i, doc in enumerate(result['source_documents']):
bot_message += '[' + str(i+1) + '] ' + doc.metadata['source'] + ' '
# 채팅 기록에 사용자의 메시지와 봇의 응답을 추가.
chat_history.append((message, bot_message))
return "", chat_history
# 사용자의 입력을 제출(submit)하면 respond 함수가 호출.
msg.submit(respond, [msg, chatbot], [msg, chatbot])
# '초기화' 버튼을 클릭하면 채팅 기록을 초기화.
clear.click(lambda: None, None, chatbot, queue=False)
# 인터페이스 실행.
demo.launch(debug=True)
|
/usr/local/lib/python3.11/dist-packages/gradio/components/chatbot.py:285: UserWarning: You have not specified a value for the `type` parameter. Defaulting to the 'tuples' format for chatbot messages, but this is deprecated and will be removed in a future version of Gradio. Please set type='messages' instead, which uses openai-style dictionaries with 'role' and 'content' keys.
warnings.warn(
Running Gradio in a Colab notebook requires sharing enabled. Automatically setting `share=True` (you can turn this off by setting `share=False` in `launch()` explicitly).
Colab notebook detected. This cell will run indefinitely so that you can see errors and logs. To turn off, set debug=False in launch().
* Running on public URL: https://330d10ff3b6af7560c.gradio.live
This share link expires in 72 hours. For free permanent hosting and GPU upgrades, run `gradio deploy` from the termi
'AI' 카테고리의 다른 글
MultipleNegativesRankingLoss를 활용한 임베딩 파인 튜닝 (0) | 2025.04.04 |
---|---|
RAG 실습 이후 + LLM 추천 (0) | 2025.04.04 |
벡터 스토어와 RAG 실습 (0) | 2025.04.03 |
랭체인을 이용한 RAG (0) | 2025.04.01 |
Deep Learning GPU and CPU (0) | 2025.03.28 |