侧边栏壁纸
博主头像
码森林博主等级

一起走进码森林,享受编程的乐趣,发现科技的魅力,创造智能的未来!

  • 累计撰写 145 篇文章
  • 累计创建 73 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

畅享无缝支持:LangChain与ChatGPT重塑AI客服服务

码森林
2023-08-15 / 0 评论 / 0 点赞 / 271 阅读 / 2,174 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2023-08-15,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

大家好,我是 AI 研习者轻寒。在之前的文章《解密AI客服:LangChain+ChatGPT打造智能客服新时代》中,我基于 LangChain + ChatGPT 实现了简易公众号的 AI 客服,主要是基于文本回答用户提出的问题,但缺陷在于无法回答文本之外的内容,且回答较为生硬,同时没有根据用户隔离会话。本文通过优化,使客服能够在回答业务问题之外,还能与用户闲聊,同时隔离用户会话的同时保留上下文缓存。

打造 AI 客服

LangChain

LangChain 是一个用于开发由语言模型驱动的应用程序的框架,LangChain 灵活的抽象和广泛的工具包使开发人员能够利用 LLM 的力量。由于其版本迭代的太快,作者也是在不断的探索。

AI 客服

AI 客服旨在提供实用的辅助和支持,通过与用户的互动,自动分析用户的输入的问题,并根据用户的需求响应适当的回答或建议。

AI 客服可以为企业提高高效、降低成本,通过快速响应以提升用户满意度,并减少人工客服的工作负担,如原本可能需要 10 人的客服团队,现在在 AI 的辅助下可能只需要 2 人就能胜任工作。

目前 AI 客服还没法完全自主解决所有问题,但如何提升 AI 客服解决问题的能力还有很多探索的空间,比如基于 LangChain 实现日常客服(如售前、售后)流程阶段自动化,通过 LangChain 的代理及工具可以和其他业务系统紧密结合,利用 LangChain 的链可以对会话或阶段进行分析和评估等等。

基于文本问答的客服实现

这是之前实现简易 AI 客服,有兴趣的可以去看看:《解密AI客服:LangChain+ChatGPT打造智能客服新时代》

功能优化

本文是基于前文的实现进行了优化。

检索问答优化

优化概述

在之前的实现中使用了 RetrievalQA,RetrievalQA 是 LangChain 中的一个模块,用于构建基于检索的问答系统。

RetrievalQA 的主要思想是先从文档库中检索出与问题相关的文档,基于相关性对候选答案进行排序和筛选,然后将这些文档和原始问题一起提供给语言模型,让语言模型根据这些上下文来生成答案。

本次优化使用 ConversationalRetrievalChain 去实现,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)

系统prompt预设

优化概述

系统提示预设可以让模型回答的更可控,通过自定义系统模板,可以让 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 模型能力完美的结合起来。

代码实现

这里把之前写的实时查询天气的工具集成了进来,方便测试。可以阅读之前的文章《基于LangChain实现ChatGPT实时查询天气》来学习如何实现自定义工具(工具即是函数或者接口能力)。

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():  # put application's code here
    # 接口请求参数
    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)
        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}
        ]
    }

成果演示

image-20230815172853284

image-20230815172936755

image-20230815172959343

结尾

LangChain 给了我很多的惊喜,它让开发 AI 应用变得简单。但它的生态还在不断扩展,版本不断迭代,所以我们只能不断的探索。

理解新范式,拥抱新时代,把握新机会。

扫码_搜索联合传播样式-标准色版

以下二维码即是接入了 AI 客服的小猫惠充公众号了,可以体验一下~

👇🏻👇🏻👇🏻👇🏻👇🏻👇🏻👇🏻

00000

0

评论区