AI * ML

LangChain 시작하기 - 대화내용을 Context로 가지는 Retriever 설정

armyost 2024. 6. 23. 22:43
728x90

이전 포스팅에서 단순 INPUT을 받아 답변을 받는 실습을 하였습니다.

https://armyost.tistory.com/488

 

LangChain 시작하기 - Retrieval 를 통한 컨텍스트 정의하기

Retrieval Chain어떤 특정한 질문에 올바르게 대답하려면 LLM에 추가 컨텍스트를 제공해야 합니다. 추가적인 탐색을 통해 이를 수행할 수 있습니다. 이때 Retrieval을 쓰며 이는 LLM에 직접 전달하기에

armyost.tistory.com

 

기존 샘플의 Prompt에 아래의 방법을 덮어써봅시다. 이번에는 대화내용을 Context로 가질 수 있도록 하는 Retriever설정에 대한 내용입니다.

 

 

Prompt 설정

retriever을 업데이트하기 위해 새 chain을 생성합니다. 이 chain은 가장 최근 입력(input)과 대화 기록(chat_history)을 받아서 LLM을 사용하여 검색 쿼리를 생성합니다.

from langchain.chains import create_history_aware_retriever
from langchain_core.prompts import MessagesPlaceholder

# First we need a prompt that we can pass into an LLM to generate this search query

prompt = ChatPromptTemplate.from_messages([
    MessagesPlaceholder(variable_name="chat_history"),
    ("user", "{input}"),
    ("user", "Given the above conversation, generate a search query to look up to get information relevant to the conversation")
])
retriever_chain = create_history_aware_retriever(llm, retriever, prompt)

 

- Create_history_aware_retiever API 문서 : langchain.chains.history_aware_retriever.create_history_aware_retriever — 🦜🔗 LangChain 0.2.5\

- Message Place holder API 문서 : langchain_core.prompts.chat.MessagesPlaceholder — 🦜🔗 LangChain 0.2.5

 


사용자가 후속 질문을 하는 인스턴스를 전달하여 이를 테스트할 수 있습니다.

from langchain_core.messages import HumanMessage, AIMessage

chat_history = [HumanMessage(content="Can LangSmith help test my LLM applications?"), AIMessage(content="Yes!")]
retriever_chain.invoke({
    "chat_history": chat_history,
    "input": "Tell me how"
})

여기서 보면 chat_history는 List 형식으로 HumanMessage, AIMessage를 가지는 것을 알 수 있습니다. 이런식으로 chat_history에 List 형식으로 누적시켜 history를 사용하면됩니다.

 

- HumanMessage :  langchain_core.messages.human.HumanMessage — 🦜🔗 LangChain 0.2.5

- AIMessage : langchain_core.messages.ai.AIMessage — 🦜🔗 LangChain 0.2.5

 

 

그러면 LangSmith의 테스트에 관한 문서가 반환되는 것을 볼 수 있습니다. 이는 LLM이 채팅 기록과 후속 질문을 결합하여 새로운 쿼리를 생성했기 때문입니다.

 

Context 정의 방식과 비교해보기
이제 이 새로운 retriever로 검증해볼 것입니다. 방금전에 retrieved된 문서를 염두에 두고 대화를 계속하기 위해 새 chain을 만들 수 있습니다.

prompt = ChatPromptTemplate.from_messages([
    ("system", "Answer the user's questions based on the below context:\n\n{context}"),
    MessagesPlaceholder(variable_name="chat_history"),
    ("user", "{input}"),
])
document_chain = create_stuff_documents_chain(llm, prompt)

retrieval_chain = create_retrieval_chain(retriever_chain, document_chain)


이제 이것을 엔드 투 엔드로 테스트할 수 있습니다.

chat_history = [HumanMessage(content="Can LangSmith help test my LLM applications?"), AIMessage(content="Yes!")]
retrieval_chain.invoke({
    "chat_history": chat_history,
    "input": "Tell me how"
})


이것이 일관된 답변을 제공한다는 것을 알 수 있습니다. retrieval chain을 챗봇으로 성공적으로 전환했습니다!