문서를 기반으로 하는 챗봇 📚&🤖 (feat.langchain ,ChromaDB)

박하영·2023년 7월 12일
1

LLM

목록 보기
2/4

안녕하세요. 오늘은 문서를 기반으로 응답할 수 있는 챗봇을 만들어 보도록 하겠습니다.

CromaDB,langchain,ChatGPT (gpt-3.5-turbo)을 사용하여 QA ChatBot을 만들어보도록 하겠습니다.
domain specific한 챗봇을 만들기 원하시는 분들이 참고하면 좋을 것 같습니다.

💡 setting , data load, processing

우선 필요한 패키지들을 설치해줍니다.

!pip install langchain==0.0.142
!pip install openai==0.27.4
!pip install chromadb==0.3.21
!pip install tiktoken==0.3.3

그리고 여러 문서들을 이용할 수 있는데, 이 실습에서는 TechCrunch article 21개를 사용합니다.

!wget -q https://github.com/kairess/toy-datasets/raw/master/techcrunch-articles.zip
!unzip -q techcrunch-articles.zip -d articles

개인 api_key를 입력해주고, 필요한 라이브러리들을 import해주세요.

import os

os.environ["OPENAI_API_KEY"] = " 개인 api key 입력 "
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.llms import OpenAI
from langchain.chains import RetrievalQA
from langchain.document_loaders import TextLoader
from langchain.document_loaders import DirectoryLoader

데이터를 로드해주고 1000 chunk씩 나누어 줍니다. 이때 chunk_overlap은 누락되는 부분을 방지해서 200개씩은 겹쳐주는 방식이라고 하네요.

loader = DirectoryLoader('./articles', glob="*.txt", loader_cls=TextLoader)
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
texts = text_splitter.split_documents(documents)

여기까지 만들어주면 len(texts)는 233이라는 결과가 나와야합니다.

💡 text를 embbeding값으로 바꾸어주고, DB에 저장

persist_directory = 'db'

embedding = OpenAIEmbeddings()

vectordb = Chroma.from_documents(
    documents=texts,
    embedding=embedding,
    persist_directory=persist_directory)
vectordb.persist()
vectordb = None
vectordb = Chroma(
    persist_directory=persist_directory,
    embedding_function=embedding)

WARNING:chromadb:Using embedded DuckDB with persistence: data will be stored in: db 이라는 경고문이 뜨긴하는데 뒤에서 잘돌아가서 일단은 냅두기로 합니다.

💡 DB에서 query에 맞는 문서 retreiver하기

retriever = vectordb.as_retriever(search_kwargs={"k": 3})
docs = retriever.get_relevant_documents("What is Generative AI?")

for doc in docs:
    print(doc.metadata["source"])

이때 k는 상위 k개의 결과를 반환할 수 있도록 하는 변수를 의미합니다.
결과값을 보시면 이렇게 세가지의 문서가 뽑히게 되는 것을 확인 할 수 있습니다.

# 결과값
articles/05-04-slack-updates-aim-to-put-ai-at-the-center-of-the-user-experience.txt
articles/05-04-microsoft-doubles-down-on-ai-with-new-bing-features.txt
articles/05-03-spawning-lays-out-its-plans-for-letting-creators-opt-out-of-generative-ai-training.txt

💡 Make a chain

이제 langchain을 통해 연결하면 마무리되게 됩니다.

qa_chain = RetrievalQA.from_chain_type(
    llm=OpenAI(),
    chain_type="stuff",
    retriever=retriever,
    return_source_documents=True)
def process_llm_response(llm_response):
    print(llm_response['result'])
    print('\n\nSources:')
    for source in llm_response["source_documents"]:
        print(source.metadata['source'])

💡 Query

이제 chain이 완성되었고, 문서에서 궁금한 query를 하게되면 출처 문서와 함께 응답을 하게됩니다.

query = "How much money did Pando raise?"
llm_response = qa_chain(query)
process_llm_response(llm_response)
# 결과값
 Pando raised $30 million in a Series B round, bringing its total raised to $45 million.


Sources:
articles/05-03-ai-powered-supply-chain-startup-pando-lands-30m-investment.txt
articles/05-03-ai-powered-supply-chain-startup-pando-lands-30m-investment.txt
articles/05-03-ai-powered-supply-chain-startup-pando-lands-30m-investment.txt

간단하고 재밌는 실습이었습니다.😃
앞으로 text 말고도 다른 형태의 문서도 활용해 볼 예정입니다.

reference

빵형의 개발도상국 : https://www.youtube.com/watch?v=ftXLn9DE7YY
외국 유튜브 : https://www.youtube.com/watch?v=3yPBVii7Ct0

profile
NLP 파이팅해야지!

1개의 댓글

comment-user-thumbnail
2023년 7월 18일

도움이 됐습니다. 유익합니다. 감사합니다.

답글 달기