LangChain 构建智能 AI 客服系统实战
本文介绍基于 LangChain 框架开发 AI 客服系统的优化方案。通过对比 RetrievalQA 与 ConversationalRetrievalChain 提升检索效果,利用自定义 System Prompt 增强可控性,结合 OpenAIFunctionsAgent 实现工具调用,并使用 Redis 管理用户会话上下文。旨在降低企业成本,提升响应效率与用户体验。

本文介绍基于 LangChain 框架开发 AI 客服系统的优化方案。通过对比 RetrievalQA 与 ConversationalRetrievalChain 提升检索效果,利用自定义 System Prompt 增强可控性,结合 OpenAIFunctionsAgent 实现工具调用,并使用 Redis 管理用户会话上下文。旨在降低企业成本,提升响应效率与用户体验。

LangChain 是一个用于开发由语言模型驱动的应用程序的框架。它提供灵活的抽象和广泛的工具包,使开发人员能够利用大语言模型(LLM)的强大能力。由于该框架版本迭代较快,开发者需要持续关注其更新以适配最新功能。
AI 客服旨在提供实用的辅助和支持,通过与用户的互动,自动分析用户输入的问题,并根据需求响应适当的回答或建议。
AI 客服可以为企业提高效率、降低成本。通过快速响应提升用户满意度,并减少人工客服的工作负担。例如,原本可能需要 10 人的客服团队,在 AI 的辅助下可能只需要 2 人就能胜任大部分工作。
目前 AI 客服尚无法完全自主解决所有问题,但提升其解决问题能力的探索空间依然很大。例如基于 LangChain 实现日常客服(如售前、售后)流程阶段自动化,通过 LangChain 的代理及工具可以和其他业务系统紧密结合,利用 LangChain 的链可以对会话或阶段进行分析和评估等。
本文基于前文实现的简易 AI 客服进行了深度优化。
在之前的实现中使用了 RetrievalQA。这是 LangChain 中的一个模块,用于构建基于检索的问答系统。
RetrievalQA 的主要思想是先从文档库中检索出与问题相关的文档,基于相关性对候选答案进行排序和筛选,然后将这些文档和原始问题一起提供给语言模型,让模型根据上下文生成答案。
本次优化使用 ConversationalRetrievalChain 去实现。该组件用于构建会话式的检索问答代理。它会考虑会话的上下文信息,根据之前的问题和回答来改进当前问题的检索结果。相比单轮的 RetrievalQA,可以在会话过程中不断改进检索性能。
ConversationalRetrievalChain 的主要思想是先构建一个检索工具,对用户的问题进行检索获取相关文档。然后构建一个会话式的代理,内部集成了检索工具。当用户提出问题时,代理首先用检索工具获取相关文档,然后将问题、相关文档以及之前的对话历史作为 prompt 提供给语言模型生成回答。这样可以利用检索结果增强语言模型的理解能力,生成更好的回答。
ConversationBufferMemory 是 LangChain 中的一个组件,用于在会话问答系统中存储对话历史。它可以跟踪对话的上下文,在生成回复时提供给语言模型使用。
qa = RetrievalQA.from_chain_type(
llm=ChatOpenAI(model_name='gpt-3.5-turbo-0613'),
chain_type="stuff",
retriever=vector_store.as_retriever()
)
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
verbose=True
)
qa = ConversationalRetrievalChain.from_llm(
llm=ChatOpenAI(model_name='gpt-3.5-turbo-0613'),
chain_type="stuff",
memory=memory,
retriever=vector_store.as_retriever(),
condense_question_prompt=common_prompt,
verbose=True
)
系统提示预设可以让模型回答更可控。通过自定义系统模板,可以让 AI 的回复更加符合交互场景的需要,提高用户体验。它为构建会话式问答系统提供了更多可定制性,比如让系统回复更加人性化,丰富系统和用户之间的交互形式,又如控制 AI 哪些可以回答,哪些不能回答。
将 system_prompt.txt 保存在静态文件中,在 Docker 部署时,方便快速调试以及优化 Prompt。
# 构建 system_template.txt 文件的路径
system_template_path = os.path.join(base_dir, 'static', 'system_template.txt')
with open(system_template_path, 'r') as file:
system_template = file.read()
common_prompt = PromptTemplate(
template=system_template,
input_variables=[]
)
OpenAI 有 Function calling 的功能,LangChain 的代理也是类似,这里我们使用了 OpenAIFunctionsAgent。
LangChain 的代理可以根据用户的提问,结合工具的描述(描述是非常有用的)和自定义参数自动判断是否需要调用工具以及选择什么工具。
基于代理和工具我们还可以把业务和 GPT 模型能力完美结合起来。
这里把之前写的实时查询天气的工具集成了进来,方便测试。可以阅读相关文章学习如何实现自定义工具(工具即是函数或者接口能力)。
qa = ConversationalRetrievalChain.from_llm(
llm=llm,
chain_type="stuff",
memory=memory,
retriever=vector_store.as_retriever(),
condense_question_prompt=common_prompt,
verbose=True
)
realWeatherTool = RealWeatherTool()
tools = [
Tool(
name="xmhc",
func=qa.run,
description="当您需要回答小猫惠充客服相关问题时,包括话费充值、充值类型 (快充/慢充)、到账时间、充值须知、充值规则、充值协议、活动规则、客服联系方式、联系客服等,这非常有用。输入应该是一个完整的问题。",
verbose=True,
),
Tool(
name="RealWeatherTool",
func=realWeatherTool.run,
description=realWeatherTool.description,
verbose=True,
)
]
chat_prompt = OpenAIFunctionsAgent.create_prompt(
system_message=SystemMessage(content=system_template)
)
agent = OpenAIFunctionsAgent(
llm=llm,
tools=tools,
prompt=chat_prompt,
verbose=True
)
agent_executor = AgentExecutor(agent=agent, tools=tools, memory=memory, verbose=True)
我们知道微信公众消息都是基于公众号用户的,所以我们可以采用 openid 作为用户唯一标识,以此来用于会话隔离。
同时需要记录用户会话的上下文,这里采用 Redis 来缓存用户会话记录,后续还可以基于会话记录来做一个会话分析功能。
对会话上下文进行限制,以防超出模型最大 token 限制。
@app.route("/xmhc/kf", methods=['POST'])
def chat():
# 接口请求参数
json_data = request.get_json()
userid = json_data['userid']
question = json_data['question']
# 获取当前用户历史会话内容
history_message = []
if redis_store.exists(userid):
history_message_str = redis_store.get(userid)
history_message = json.loads(history_message_str)
try:
answer = agent_executor.run({"input": question, "chat_history": history_message})
current_message = (question, answer)
# 缓存当前用户历史对话内容
history_message.append(current_message)
# 对会话数进行限制,防止超出 Token 上限
if len(history_message) > 10:
# 删除最旧的数据
history_message.pop(0)
# 将元组列表转换为 JSON 字符串
history_message_str = json.dumps(history_message)
redis_store.set(userid, history_message_str)
print(answer)
except InvalidRequestError:
# 调用模型请求失败,可能是额度不足或者请求频繁
return {
"err_code": -1,
"data_list": []
}
return {
"err_code": 0,
"data_list": [
{"content": answer}
]
}
通过上述优化,AI 客服系统在检索准确性、上下文理解、工具调用灵活性以及会话管理稳定性方面均得到了显著提升。在实际生产环境中,建议进一步监控 Token 使用情况,定期更新知识库向量数据,并根据用户反馈调整 System Prompt 策略,以实现持续的服务质量优化。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online