Skip to content

Instantly share code, notes, and snippets.

@tae0y
Last active May 17, 2023 17:29
Show Gist options
  • Save tae0y/4ce973599016efa00953c3f911a22e4a to your computer and use it in GitHub Desktop.
Save tae0y/4ce973599016efa00953c3f911a22e4a to your computer and use it in GitHub Desktop.
langchain, opeanai, faiss를 활용한 챗봇 개념증명

langchain_openai_faiss_chatbot_test

  • langchain, opeanai, faiss를 활용한 챗봇 개념증명으로, 제 json 데이터를 llm 활용해 시멘틱 검색할 수 있습니다.
  • 아래 코드는 openai api를 사용하는데, 언어모델을 바꿔서 완전히 로컬에서 동작할 수도 있습니다 (임베딩할때 사용량이 많았는지 4.7달러 과금, 지금은 질문응답하면 2건당 0.01정도 과금)
  • 응답 예시 image

소스설명, 약간 변경한 부분

  • 질의문/프롬프트
    • 책은 컨텍스트로 제공된 것 중에서만 골라줘
    • 응답은 200자 이내로 간략히 요약해서 작성해줘
  • books.txt : 검색대상, json 형태로 추출한 책 데이터입니다.
  • embed.py : 텍스트파일을 로컬 faiss 벡터 데이터베이스로 임베딩합니다.
    • 임베딩: 자연어를 ai가 이해할 수 있는 행렬 형태로 표현하는 것
    • 벡터 데이터베이스 : 그런 임베딩 결과를 저장하기 위해 고안된 데이터베이스 종류
    • 청크 크기를 1000(최대 토큰수 제한) > 200(문맥을 잃어버림) > 500 > 700으로 조정함
from langchain.embeddings import OpenAIEmbeddings
from langchain.embeddings import ChatOpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.document_loaders import TextLoader

embeddings = OpenAIEmbeddings(openai_api_key="")

from langchain.document_loaders import TextLoader
loader = TextLoader('./books.txt')
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size = 700, 
    chunk_overlap = 50,
    length_function = len)
docs = text_splitter.split_documents(documents)

db = FAISS.from_documents(docs, embeddings)
db.save_local("faiss_index")

query = "Who is Whitfield Diffie?"
docs = db.similarity_search(query)
for doc in docs:
    print(doc.page_content)
  • search.py : 사용자 질의문을 임베딩하고, 벡터 데이터베이스에서 관련 데이터를 찾습니다. 찾은 데이터를 질의문 컨텍스트로 포함시켜 llm에 전달합니다.
    • 질의문 임베딩, 벡터 데이터베이스 쿼리, 컨텍스트 제공 등은 langchain을 사용해서 체이닝합니다.
    • 오픈소스 llm대신 한국어를 잘 이해하고, 질문/응답에 최적화된 chatopenai를 사용, openai는 응답이 자연스럽지 않고 최대 토큰수가 작음
from langchain.vectorstores import FAISS
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
from langchain.embeddings import OpenAIEmbeddings
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain.chains import RetrievalQA

embeddings = OpenAIEmbeddings(openai_api_key="")
new_db = FAISS.load_local("faiss_index", embeddings)

callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
llm = ChatOpenAI(
    openai_api_key="",
    temperature=0.7,
    callback_manager=callback_manager, 
    verbose=True
)

retriever = new_db.as_retriever()

qa = RetrievalQA.from_chain_type(
    llm=llm
    ,chain_type="stuff" 
    ,retriever=retriever
)

while True:
    query = input("You: ")
    if query.lower() == "exit":
        break

    response = qa.run(query)
    print(f"AI: {response}")
    print("==============================================")

남은과제

  • 데이터 도메인에 적절한, 문맥을 잃지 않으면서 llm 최대토큰 이내로 들어올 수 있는 임베딩 청크크기 찾기
  • 데이터 도메인에 적절한, 한국어를 잘 이해하는 언어모델 적용해보기(hugging face에서?)

레퍼런스 (아래 글들을 보고 따라한 수준입니다)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment