场景方案·智能体电商客服
本文档主要以电商客服场景为例,支持客户基于文心大模型快速构建业务实践,同样方法也适用于其他客服场景。
一、传统人工客服的局限
在电商行业,客服至关重要,他们解答疑问、处理订单问题,是促进销售转化的关键力量。然而,随着业务增长,面对海量客服请求,人工客服模式逐渐显露出其局限性,比如高昂的人力成本、响应速度的限制、以及难以避免的人为错误等。
二、智能体客服的优势
此时,您可以考虑使用智能体客服,这种方案能用更低的成本实现更高的销售转化,具有诸多优势,如:自动化处理高频问题,降低运营成本,提高响应速度;不受时间地域限制,能全天候、不间断地提供服务等。
三、本文场景总述
本文选取了电商客服两个常见的小场景,为您介绍如何用代码搭建智能体,从而实现对应客服任务。每个场景都提供了逐步教程,并在最后提供完整样例代码,可供您迁移至您的业务场景改编使用。以下是两个场景的简介:
1. 简单场景:为顾客更新收货地址 这是一个简单的单一任务场景,智能体客服只需根据顾客的问题进行判断,当识别到顾客有更改顾客地址需求时,让顾客提供新信息,然后更新收货地址。
2. 进阶场景:为顾客处理运费险事项 这是一个相对复杂,其下涉及多个子任务的场景。智能体客服需要根据顾客的不同情况,进行多轮交互与子任务来完成。比如:顾客的询问可能分为:欲购买商品是否支持运费险、已购买订单是否支持运费险、直接申请运费险等。对以上不同情况,智能体客服需向顾客获取不同信息,再完成不同子任务。例如,顾客直接申请运费险时,智能体客服需首先询问订单信息,获取后,需查询订单是否支持运费险、是否超出售后期限等,查询结果的不同又决定后续子任务的不同。
三、简单场景:为顾客更新收货地址
本场景将构建两个智能体来合作完成该任务:“客服智能体”和“更新地址助手”。它们的详细功能如下:
- 客服智能体:作为整体流程的主入口,根据用户输入,判断是否使用“更新地址助手”还是“申请补偿助手”(该助手本场景未使用,为简化演示,本文代码中不做实现)。
-
更新地址助手:完成更新地址的流程,具体流程包括:
- 要求用户提供订单号
- 要求用户提供新的地址
- 调用更新地址的API
3.1 搭建过程
本节将正式讲解如何用代码实现该场景下的智能体客服,所有场景都用Python实现,您可以在Jupyter Notebook运行提供的示例代码。
代码将主要用Python和LangGraph库实现整个应用。LangGraph是一个用图的方式构建智能体的库,其构建多智能体应用的流程通常如下:
1 1. 创建智能体
2 2. 定义智能体使用的工具
3 3. 创建图
4 3.1 定义状态
5 3.2 定义智能体节点
6 3.3 定义工具节点
7 3.4 定义边逻辑
8 3.5 定义代理节点
9 3.6 定义图
10 4. 调用
本文代码搭建思路也遵循这一流程,我们将:
- 先进行一定初始化工作,您需要在这一步进行一定设置,如填写您的AK和SK,设置使用的智能体大模型
- 分别搭建客服智能体和更新地址助手智能体,搭建过程中完成智能体使用工具的定义
- 创建智能体图结构,将所有智能体整合,编译成一个可运行调用的应用
对于后两步的代码,作为初次体验,您可以直接复制运行。熟悉后,您可以基于它们针对您的特定业务场景进行改编使用。
3.1.1 初始化工作
首先,请安装本文将使用的各类Python库,您可以逐条运行以下命令以安装需要的库。
1!pip3 install -U langgraph
2!pip3 install -U langchain
3!pip3 install grandalf
4!pip3 install qianfan
安装完毕后,我们用以下代码进行模型初始化。您需要在其中进行一定修改。
1# 导入将使用模块、类和函数
2from typing import TypedDict, Annotated, Union, Optional, Type, List, Annotated, Sequence
3
4import requests
5from langchain.pydantic_v1 import BaseModel, Field
6from langchain.tools import BaseTool, tool
7from langchain_core.agents import AgentAction
8from langchain_core.agents import AgentFinish
9from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage, AIMessage
10from langgraph.graph import END, StateGraph
11from langgraph.prebuilt.tool_executor import ToolExecutor
12from langchain.chat_models import QianfanChatEndpoint
13import qianfan
14from langgraph.graph.message import add_messages
15from functools import partial
16from qianfan.extensions.langchain.agents import QianfanSingleActionAgent
17from langchain.agents import AgentExecutor
18
19import os
20
21# 请填入您的千帆AK和SK
22os.environ['QIANFAN_AK'] = 'Your_AK'
23os.environ['QIANFAN_SK'] = 'Your_SK'
24
25# 填写使用的模型
26qianfan_chat_model = QianfanChatEndpoint(model='ERNIE-3.5-8K')
请在以上代码中:
- 填写AK和SK:将
Your_AK
和Your_SK
替换为您的API Key和Secret Key,具体获取方式为:【登录到本平台】-【点击左侧导航栏“应用接入”】-【点击“创建应用”创建一个“智能体客服”应用】-【回到“应用接入”页面,在已创建应用列表找到AK和SK】。
- 填写使用的模型(可选):将
ERNIE-3.5-8K
替换为您想为智能体使用的模型,目前已预填的ERNIE-3.5-8K
是百度自研的旗舰级大规模⼤语⾔模型,具有强大的通用能力,您也可以选择使用这个模型(需先为该模型开通付费)。
3.1.2 构建客服智能体
接下来,我们用代码正式实现两个智能体,以下是搭建客服智能体的代码。
1# 客服智能体的Tool和System Prompt定义
2system_customer_support_agent = '''你是小店平台的客服路由工具。尽量不直接回话,而是通过工具完成客户咨询。你的主要职责是根据客户咨询的问题,提供对应的服务。如果客户咨询修改地址,申请运费补偿等问题,请调用对应的工具将任务委托给合适的专业助手。你自己无法做出这些类型的改变只有专业助手被授权为用户执行这些操作。用户不知道不同的专业助理,因此不要提及他们,直接通过函数委派任务即可'''
3@tool("ToOrderAddressUpdateAssistant")
4def ToOrderAddressUpdateAssistant(content: str) -> str:
5 """将工作转交给专门的助手处理更新订单收货地址的事件"""
6 # do nothing
7 print('调用了ToOrderAddressUpdateAssistant函数')
8 return '触发后面的更新订单收货地址的助手'
9
10@tool("ToOrderApplyShippingFeeAgent")
11def ToOrderApplyShippingFeeAgent(content: str) -> str:
12 """将工作转交给专门的助手处理申请运费补偿的事件"""
13 # do nothing
14 print('调用了ToOrderApplyShippingFeeAgent函数')
15 return '触发后面的申请运费补偿的助手'
16
17# 客服智能体的Agent和Executor定义
18tools_customer_support_agent = [ToOrderAddressUpdateAssistant, ToOrderApplyShippingFeeAgent]
19qianfan_customer_support_agent = QianfanSingleActionAgent.from_system_prompt(tools_customer_support_agent, qianfan_chat_model, system_prompt=SystemMessage(system_customer_support_agent))
20excutor_customer_support_agent = AgentExecutor(agent=qianfan_customer_support_agent, tools=tools_customer_support_agent, verbose=True)
以上代码中:
- 首先,我们用
system_customer_support_agent
定义了客服智能体的核心职责与行为准则。 -
然后,在
@tool
部分,我们定义了客服智能体所使用的两个工具:ToOrderAddressUpdateAssistant
:用于实现更新地址助手ToOrderApplyShippingFeeAgent
:用于实现申请补偿助手
为简化演示,在此示例中,这些函数的具体实现部分没有写出,仅用打印调试信息代替,在实际部署时,它们将调用后端服务或专业助手来执行实际的操作。
-
最后,我们通过
QianfanSingleActionAgent.from_system_prompt()
方法来创建客服智能体,并用AgentExecutor()
启动运行该智能体。其中,QianfanSingleActionAgent.from_system_prompt()
方法需要三个参数:- 预定义的工具列表(
tools_customer_support_agent
):智能体可以调用的工具或服务,其内正是上一步我们通过@tool定义的工具。 - 聊天模型(
qianfan_chat_model
):智能体使用的模型,在初始化步骤已经设定。 - 智能体的prompt(
system_prompt
):该信息我们已经在system_customer_support_agent
里设定。
- 预定义的工具列表(
3.1.3 构建更新地址助手智能体
搭建更新地址助手智能体的核心思路与客服智能体类似,以下是具体代码:
1# 地址更新智能体的Tool和System Prompt定义
2system_addr_update_agent = '''你是一个引导客户进行修改地址的助手,当客户需要修改地址信息的时候,主助手会将委托你进行工作。根据客户提供到的信息,按照以下步骤引导客户完成修改地址的操作。
31.如果客户没有提供订单信息,请先调用ask_for_order引导客户提供订单信息
42.如果客户提供的订单信息,请调用ask_for_address引导客户提供新的地址信息
53.如果客户提供了新的地址信息,请调用update_address更新地址
6
7请记住,如果客户终止了意图,请调用intent_interrupt工具退出
8以下是一些您应该intent_interrupt的示例:
9- 算了,我不想改了
10- 等等,我在想一下
11- 转人工
12- 再见
13- 我不想修改地址了
14请记住,如果客户改变了意图,请调用CompleteOrEscalate交给主助手,不要创建无效的工具或函数。
15以下是一些您应该CompleteOrEscalate的示例:
16- 帮我申请运费
17- 帮我取消订单
18'''
19@tool("ask_for_order")
20def ask_for_order(content: str) -> str:
21 """向用户索要订单信息。"""
22 print('调用ask_for_order')
23 return '请提供订单信息'
24
25@tool("ask_for_address")
26def ask_for_address(content: str) -> str:
27 """向用户索要新的地址信息。"""
28 print('调用ask_for_address')
29 return '请提供新的地址信息'
30
31@tool("update_address")
32def update_address(content: str) -> str:
33 """更新新地址"""
34 print('调用update_address')
35 # 调用API更新地址
36 return '已完成地址更新,感谢使用'
37
38@tool("intent_interrupt")
39def intent_interrupt(content: str) -> str:
40 """用户取消,退出"""
41 print('调用intent_interrupt')
42 return '用户取消,退出'
43
44@tool("CompleteOrEscalate")
45def CompleteOrEscalate(content: str) -> str:
46 """A tool to mark the current task as completed and/or to escalate control of the dialog to the main assistant,
47 who can re-route the dialog based on the user's needs."""
48 # do nothing
49 print('调用CompleteOrEscalate')
50 return '任务完成交给上游智能体'
51
52
53tools_addr_update_agent = [ask_for_order, ask_for_address, update_address, intent_interrupt, CompleteOrEscalate]
54qianfan_addr_update_agent = QianfanSingleActionAgent.from_system_prompt(tools_addr_update_agent, qianfan_chat_model, system_prompt=SystemMessage(system_addr_update_agent))
55excutor_addr_update_agent = AgentExecutor(agent=qianfan_addr_update_agent, tools=tools_addr_update_agent, verbose=True)
以上代码中:
- 首先,我们用
system_addr_update_agent
定义了更新地址助手智能体的核心职责与行为准则。 -
然后,在
@tool
部分,我们实现了更新地址助手智能体使用的五个关键工具函数,分别用于实现:- 索要订单信息(
ask_for_order
) - 索要新地址信息(
ask_for_order
) - 更新地址(
update_address
) - 在顾客不想更改地址时退出(
intent_interrupt
) - 在完成任务或顾客中途变更、要处理其他事务时,将任务交给上游智能体(
CompleteOrEscalate
)
同样,为简化演示,在此示例中,这些函数的具体实现部分没有写出,仅用打印调试信息代替,在实际部署时,它们将调用后端服务或专业助手来执行实际的操作。
- 索要订单信息(
-
最后,我们通过
QianfanSingleActionAgent.from_system_prompt()
方法来创建更新地址助手智能体,并用AgentExecutor()
启动运行该智能体。其中,QianfanSingleActionAgent.from_system_prompt()
方法需要三个参数,分别填写为:- 预定义的工具列表:
tools_addr_update_agent
- 聊天模型:
qianfan_chat_model
- 智能体的prompt:
system_prompt
- 预定义的工具列表:
3.1.4 将所有智能体编译成一个应用
构建完单个智能体后,我们要创建智能体图结构,也就是将多个智能体整合起来,告诉它们互相之间按何种顺序逻辑协作工作,从而编译成一个真正可运行调用的APP,以下是具体实现代码:
1 # 定义图状态
2class State(TypedDict):
3 # messages have the type "list".
4 # The add_messages function appends messages to the list, rather than overwriting them
5 messages: Annotated[list, add_messages]
6
7# 定义图对象
8graph_builder = StateGraph(State)
9
10# 定义客服智能体节点
11def customer_support_agent_rec_act(state):
12 # print(state['messages'])
13 result_customer_support_agent = excutor_customer_support_agent.invoke(state['messages'])
14 # return {'messages': [AIMessage(content=result_customer_support_agent['output'])]}
15 return {'messages': []}
16
17# 定义地址更新智能体节点
18def addr_update_agent_rec_act(state):
19 print(state['messages'])
20 result_addr_update_agent = excutor_addr_update_agent.invoke(state['messages'])
21 return {'messages': [AIMessage(content=result_addr_update_agent['output'])]}
22
23# 添加节点
24graph_builder.add_node("客服智能体", customer_support_agent_rec_act)
25graph_builder.add_node("更新地址的助手", addr_update_agent_rec_act)
26
27# 添加边
28graph_builder.add_edge("客服智能体", "更新地址的助手")
29
30# 定义主入口
31graph_builder.set_entry_point("客服智能体")
32
33# 编译图
34app = graph_builder.compile()
35
36## 打印图结构
37app.get_graph().print_ascii()
以上代码中,我们将客服智能体定义为这个应用的主入口,其下是更新地址助手智能体,然后编译成一个应用等待后续调用,并将这个图结构打印。当您将以上1到4步的代码输入Jupyter Notebook中运行时,可以看到打印结果如下:
如果您想了解这段代码的更多细节,可参考LangGraph多智能体协作文档中的详细介绍。
3.2 测试验证
搭建完成后,我们对该应用进行测试,方式为与其对话。请在Jupyter Notebook中输入以下代码。
1## 第一轮对话:用户输入信息,想要修改地址
2input_1st = "我想修改地址"
3
4## 调用上一步创建好的应用,将用户信息传入,并获取智能体回复
5result = app.invoke({
6 "messages": [{"role": "user", "content": input_1st}]
7})
8
9## 将智能体的最后回复内容放入变量,以便后续打印
10output_1st = result['messages'][-1].content
11
12## 打印对话
13print("########### 第一轮对话 ##########")
14print("输入:" + input_1st)
15print("输出:" + output_1st)
您将看到类似如下输出结果:
1########### 第一轮对话 ##########
2输入:我想修改地址
3输出:好的,为了修改地址,我需要先了解一下您的订单信息。请问您能提供一下订单号吗?
接下来,我们可以再进行几轮对话,您将看到类似如下的输出结果:
对话:
1## 第二轮对话:用户输入,订单号123456789
2input_2nd = "我的订单是123456789"
3result = app.invoke({
4 "messages": [
5 {"role": "user", "content": input_1st},
6 {"role": "assistant", "content": output_1st},
7 {"role": "user", "content": input_2nd}
8 ]
9})
10## 拿到输出
11output_2nd = result['messages'][-1].content
12
13print("########### 第二轮对话 ##########")
14print("输入:" + input_2nd)
15print("输出:" + output_2nd)
输出:
1########### 第二轮对话 ##########
2输入:我的订单是123456789
3输出:好的,为了修改您的地址,我需要您提供新的地址信息。请告诉我您的新地址是什么呢?
对话:
1## 第三轮对话:用户输入,地址是上海市杨浦区
2input_3rd = "地址是上海市杨浦区"
3result = app.invoke({
4 "messages": [
5 {"role": "user", "content": input_1st},
6 {"role": "assistant", "content": output_1st},
7 {"role": "user", "content": input_2nd},
8 {"role": "assistant", "content": output_2nd},
9 {"role": "user", "content": input_3rd},
10 ]
11})
12## 拿到输出
13output_3rd = result['messages'][-1].content
14
15print("########### 第三轮对话 ##########")
16print("输入:" + input_3rd)
17print("输出:" + output_3rd)
输出:
1########### 第三轮对话 ##########
2输入:地址是上海市杨浦区
3输出:好的,您的地址已经更新为上海市杨浦区。如果您还有其他问题或需要进一步帮助,请随时告诉我。
3.3 样例代码
以下是本场景的完整示例代码,您可以在Jupyter Notebook中运行:
四、进阶场景:为顾客处理运费险事项
在第一个场景里,我们专门截取了一个不存在太多情况、实现简单的单一任务。然而,实际的客服场景往往是复杂的,即使是同一任务,也需要分成多个步骤完成,并且根据顾客情况的不同,每一步骤采取的应对办法也不同。
因此,在进阶场景中,我们将完成一个相对更完整的流程任务,处理与运费险相关的事项。 以下是处理运费险可能遇到的多种情况与相应处理示意图:
我们将搭建一个主控智能体和多个辅助智能体,由辅助智能体根据主控智能体的要求,在依次执行若干个tool完成对应子任务后,最终实现处理运费险的最终任务。它们分别是:
- 主控智能体:运费险助手,下文称主控节点
-
辅助智能体:包括以下四个智能体,下文称上下游节点
- 索要商品信息智能体
- 索要订单信息智能体
- 查询商品是否支持运费险智能体
- 查询订单对应的售后单列表智能体
4.1 搭建过程
本节将正式讲解如何用代码实现处理运费险场景下的智能体客服,用Python实现,您可以在Jupyter Notebook运行提供的示例代码。
与第一个场景相同,代码将主要用Python和LangGraph库实现整个应用。LangGraph是一个用图的方式构建智能体的库,其构建多智能体应用的流程通常如下,本场景搭建依旧遵循:
1 1. 创建智能体
2 2. 定义智能体使用的工具
3 3. 创建图
4 3.1 定义状态
5 3.2 定义智能体节点
6 3.3 定义工具节点
7 3.4 定义边逻辑
8 3.5 定义代理节点
9 3.6 定义图
10 4. 调用
我们将:
- 先进行一定初始化工作,补充安装一些Python库
- 然后搭建主控节点的智能体,再搭建其他多个上下游节点的智能体或工具
- 创建智能体图结构,将所有智能体整合,编译成一个可运行调用的应用
对于以上所有步骤的代码,作为初次体验,您可以直接复制运行。熟悉后,您可以基于它们针对您的特定业务场景进行改编使用。
4.1.1 初始化工作
在进阶场景的初始化中,我们还需补充导入以下模块和函数。
1from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
2from langchain_core.utils.function_calling import convert_to_openai_function
3from langgraph.graph import END
4.2.2 搭建主控节点智能体
初始化结束后,我们先搭建主控节点智能体“运费险助手”:
1# 流程主控节点system指令,根据流程逐步执行
2system = '''你是一个专门处理'运费险(也叫退换货包邮、退换运费无忧)/运费补偿'事项的助手,当用户咨询或者申请'运费险/运费补偿'的时候,主助手会将任务委托给你。
3你要做的事情是返回一个工具调用,如果没有合适的工具,请将任务交还给主助手。
4按以下步骤引导用户:
51. 如果用户咨询商品运费险,引导用户提供商品信息; 如果用户咨询订单运费险,引导用户提供订单信息; 如果用户申请运费险,引导用户提供订单信息; 如果用户咨询运费险(未指定是商品运费险还是订单运费险),引导用户提供商品或者订单信息。
62. 如果用户选择商品,查询商品是否支持运费险
73. 如果用户选择订单,查询订单对应的售后单列表
84. 如果没有售后单,查询订单是否超售后期: 如果超售后期,告知用户订单超售后期; 如果没有超售后期,查询订单是否支持运费险
95. 如果有多个售后单,调用工具引导用户选择售后单; 如果只有一个售后单,调用工具选择这个售后单
106. 如果用户选择的售后单不是退换货类型,调用工具告知用户售后单非退换货类型
117. 如果用户选择的售后单是退换货类型,显示运费险状态
12'''
13
14@tool("ask_for_good")
15def ask_for_good() -> str:
16 """向用户索要商品信息。"""
17 print('调用ask_for_good')
18 return '商品信息为食品'
19
20@tool("ask_for_order")
21def ask_for_order() -> str:
22 """向用户索要订单信息"""
23 print('调用ask_for_order')
24 return '订单号为123456789'
25
26@tool("query_good_support")
27def query_good_support() -> str:
28 """查询商品是否支持运费险"""
29 print('调用query_good_support')
30 return '支持运费险'
31
32@tool("query_aftersales_by_order")
33def query_aftersales_by_order() -> str:
34 """查询订单对应的售后单列表"""
35 print('调用query_aftersales_by_order')
36 return '售后单为aaaa和bbbb'
37
38# 定义运费险助手节点
39def apply_shipping_fee_agent(state):
40 print('主节点正在思考,准备调用工具')
41 # print(state['messages'])
42 tools = [ask_for_order, ask_for_good, query_good_support, query_aftersales_by_order]
43 llm_with_tools = qianfan_chat_model.bind_tools(tools)
44 resp = llm_with_tools.invoke([SystemMessage(system)] + state['messages'])
45 if len(resp.tool_calls) > 0:
46 function_name = resp.tool_calls[0]['name']
47 print('主节点思考完成,准备调用:' + function_name)
48 return {'messages': state['messages'] + [AIMessage('调用' + function_name)], 'tool': function_name}
49 else:
50 return {'messages': state['messages'], 'tool': ''}
以上代码中:
- 我们通过
system
定义了运费险助手智能体的行为规范和流程步骤,包括如何根据用户咨询或申请的类型(商品运费险、订单运费险、运费险申请等)来引导用户提供相应的信息(商品或订单信息)。 -
接着,通过@tool,我们定义了四个工具函数,也就是四个辅助智能体:
ask_for_good
:用于向用户索要商品信息。ask_for_order
:用于向用户索要订单信息。query_good_support
:用于查询商品是否支持运费险。query_aftersales_by_order
:用于查询订单对应的售后单列表。
同样,为简化演示,在此示例中,这些函数的具体实现部分没有写出,仅用打印调试信息代替,并预填了一个返回值,以使后续测试步骤顺利运行。在实际部署时,它们将调用后端服务或专业助手来执行实际的操作。
- 最后,在
apply_shipping_fee_agent
函数中,我们将运费险助手智能体定义为图结构的一个节点。这个函数会基于输入的信息来决定下一步应调用的工具函数,并打印出调用的工具。
4.1.3 搭建上下游节点的智能体
接下来,我们将其他几个辅助智能体也定义为节点,同样,为简化演示,我们在具体实现部分只打印调试信息,并预填一个返回值供后续调试。
1# 用户交互商品信息的节点
2def ask_for_good_node(state):
3 result = '商品信息为食品'
4 print('调用ask_for_good_node函数,拿到结果:' + result)
5 return {'messages': state['messages'] + [result], 'tool': ''}
6
7# 用户交互订单信息的节点
8def ask_for_order_node(state):
9 result = '订单号为123456789'
10 print('调用ask_for_order_node函数,拿到结果:' + result)
11 return {'messages': state['messages'] + [result], 'tool': ''}
12
13# 查询商品是否支持运费险的节点
14def query_good_support_node(state):
15 result = '支持运费险'
16 print('调用query_good_support_node函数,拿到结果:' + result)
17 return {'messages': state['messages'] + [result], 'tool': ''}
18
19# 查询售后单的节点
20def query_aftersales_by_order_node(state) :
21 result = '售后单为aaaa和bbbb'
22 print('调用query_aftersales_by_order_node函数,拿到结果:' + result)
23 return {'messages': state['messages'] + [result], 'tool': ''}
4.1.4 将所有智能体编译成一个应用
搭建好智能体后,我们将其编译成一个可运行的应用:
1# 定义图状态
2class State(TypedDict):
3 # messages have the type "list".
4 # The add_messages function appends messages to the list, rather than overwriting them
5 tool: str
6 messages: Annotated[list, add_messages]
7
8# 定义图对象
9graph_builder = StateGraph(State)
10
11# 添加节点
12graph_builder.add_node("运费险助手节点", apply_shipping_fee_agent)
13graph_builder.add_node("索要商品信息", ask_for_good_node)
14graph_builder.add_node("索要订单信息", ask_for_order_node)
15graph_builder.add_node("查询商品是否支持运费险", query_good_support_node)
16graph_builder.add_node("查询订单对应的售后单列表", query_aftersales_by_order_node)
17
18def decide_next_node(state):
19 tool = state['tool']
20 print('根据工具进行选择下一个节点,当前工具tool为:' + tool)
21 if tool == 'ask_for_good':
22 return '索要商品信息'
23 elif tool == 'ask_for_order':
24 return '索要订单信息'
25 elif tool == 'query_good_support':
26 return '查询商品是否支持运费险'
27 elif tool == 'query_aftersales_by_order':
28 return '查询订单对应的售后单列表'
29 else:
30 return 'end'
31
32# 添加边
33graph_builder.add_conditional_edges(
34 "运费险助手节点",
35 decide_next_node,
36 {
37 '索要商品信息': '索要商品信息',
38 '索要订单信息': '索要订单信息',
39 '查询商品是否支持运费险': '查询商品是否支持运费险',
40 '查询订单对应的售后单列表': '查询订单对应的售后单列表',
41 'end': END
42 }
43)
44graph_builder.add_edge('索要商品信息', '运费险助手节点')
45graph_builder.add_edge('索要订单信息', '运费险助手节点')
46graph_builder.add_edge('查询商品是否支持运费险', '运费险助手节点')
47graph_builder.add_edge('查询订单对应的售后单列表', '运费险助手节点')
48
49
50# 定义主入口
51graph_builder.set_entry_point("运费险助手节点")
52
53# 编译图
54app = graph_builder.compile()
55
56## 打印图结构
57app.get_graph().print_ascii()
以上代码中,我们将运费险助手定义为这个应用的主入口,其下是查询商品是否支持运费险、查询订单对应的售后单列表、索要商品信息、索要订单信息等4个辅助智能体,然后编译成一个应用等待后续调用,并将这个图结构打印。当您将以上几步代码输入Jupyter Notebook中运行时,可以看到打印结果如下:
如果您想了解这段代码的更多细节,可参考LangGraph多智能体协作文档中的详细介绍。
4.2 测试验证
接下来,您可以用以下代码进行测试,将其输入Jupyter Notebook。
1# 用户输入,想要修改地址
2input_1st = "咨询商品运费险"
3result = app.invoke({
4 "messages": [{"role": "user", "content": input_1st}]
5})
6## 拿到输出
7print(result)
以上代码中,我们进行了一轮对话测试。假设用户提问为”咨询商品运费险”,将其放入input_1st
,然后作为参数传给创建好的应用,并打印返回结果。您将看到类似如下输出结果:
1主节点正在思考,准备调用工具
2主节点思考完成,准备调用:ask_for_good
3根据工具进行选择下一个节点,当前工具tool为:ask_for_good
4调用ask_for_good_node函数,拿到结果:商品信息为食品
5主节点正在思考,准备调用工具
6主节点思考完成,准备调用:query_good_support
7根据工具进行选择下一个节点,当前工具tool为:query_good_support
8调用query_good_support_node函数,拿到结果:支持运费险
9主节点正在思考,准备调用工具
10根据工具进行选择下一个节点,当前工具tool为:
11{'tool': '', 'messages': [HumanMessage(content='咨询商品运费险', id='7e049d23-00b2-439c-8d27-11d90efcb1e0'), AIMessage(content='调用ask_for_good', id='769a70d4-4fb0-45b5-9139-167ce12e1185'), HumanMessage(content='商品信息为食品', id='e3bac940-2326-4d29-a6e2-dbe1fa1647d5'), AIMessage(content='调用query_good_support', id='da77579a-24b4-4527-bec4-3556d2a8abb5'), HumanMessage(content='支持运费险', id='719ff2f0-a941-4fb7-b2d4-efb72cc008b9')]}
4.3 样例代码
以下是本文两个场景的完整示例代码,您可以在Jupyter Notebook中运行: