9.3 客户支持聊天机器人-项目关键技术
邓立国《LangGraph开发AI Agent实践》1~8章试读_langgraph开发ai agent实践在线阅读-CSDN博客
9.3.1 初始化模型
该程序使用的是DashScope提供的云端API服务(通义千问Qwen-Turbo),属于无状态的远程模型调用。
1. 首先安装必要的依赖
# 安装基础依赖
pip install langgraph==1.0.5 langchain langchain-community gradio dashscope python-dotenv
# 安装LangSmith用于追踪
pip install langsmith
2. 模型初始化相关代码
从功能角度看,模型调用所需的配置与封装可以视为“模型初始化”的逻辑部分。以下是程序中与模型初始化和调用准备相关的核心代码片段。
1)环境配置
# ====================== 1. 环境配置 ======================
import os
from dotenv import load_dotenv
import dashscope
# 加载环境变量
load_dotenv()
# 配置通义千问 API 密钥(这是使用 DashScope 模型的前提)
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY") or ""
2)模型调用函数(封装模型接口)
# ====================== 2. 模型调用函数(封装模型接口) ======================
from dashscope import Generation
def call_qwen_model(prompt: str, temperature: float = 0.3) -> str:
"""调用通义千问模型(带LangSmith追踪)"""
try:
response = Generation.call(
model="qwen-turbo", # 指定模型
messages=[{"role": "user", "content": prompt}],
temperature=temperature,
result_format='text'
)
return response.output.text.strip()
except Exception as e:
return f"模型调用出错:{str(e)}"
- dashscope.api_key=...是使用DashScope API的必要初始化步骤,相当于“认证初始化”。
- call_qwen_model函数是对模型调用的统一封装,指定了:
- 模型名称:qwen-turbo。
- 输入格式:messages(符合聊天格式)。
- 输出格式:text。
- 控制参数:temperature。
9.3.2 构建图结构与定义节点的逻辑
构建图结构-定义节点的逻辑包含两个部分:
(1)节点函数的实现(即每个节点的具体逻辑)。
(2)在图中注册这些节点(通过graph.add_node())。
定义节点的逻辑,我们聚焦于节点函数本身的实现逻辑,即每个节点做了什么。节点定义逻辑代码(不含图注册、路由或边连接代码):
def identify_intent_node(state: SupportState) -> SupportState:
"""节点1:识别用户意图"""
prompt = """
你是一个客户支持意图识别助手,请分析用户的问题并归类到以下类别之一:
- faq: 常见问题(账户、产品使用、价格等)
- technical: 技术问题(故障、报错、功能异常等)
- complaint: 投诉(服务不满、产品质量、退款等)
- other: 无法分类的其他问题
只需要返回类别名称,不要返回其他内容。
用户问题:{user_input}
""".format(user_input=state["user_input"])
intent = call_qwen_model(prompt).lower()
valid_intents = ["faq", "technical", "complaint", "other"]
state["intent"] = intent if intent in valid_intents else "other"
return state
def answer_faq_node(state: SupportState) -> SupportState:
"""节点2:回答常见问题"""
prompt = """
你是一个专业的客户支持助手,请友好、简洁地回答用户的常见问题。
回答要准确、易懂,避免使用专业术语。
聊天历史:{chat_history}
用户问题:{user_input}
请给出你的回答:
""".format(
chat_history=state["chat_history"],
user_input=state["user_input"]
)
state["response"] = call_qwen_model(prompt)
return state
def handle_technical_node(state: SupportState) -> SupportState:
"""节点3:处理技术问题"""
prompt = """
你是一位技术支持专家,请详细解答用户的技术问题。
步骤要清晰,先给出解决方案概述,再分步骤说明。
聊天历史:{chat_history}
用户问题:{user_input}
请给出你的回答:
""".format(
chat_history=state["chat_history"],
user_input=state["user_input"]
)
state["response"] = call_qwen_model(prompt)
return state
def handle_complaint_node(state: SupportState) -> SupportState:
"""节点4:处理投诉问题"""
prompt = """
你是一名客户投诉处理专员,请先表达歉意,然后记录投诉内容,
并给出具体的解决措施和时间承诺。保持语气诚恳、专业。
聊天历史:{chat_history}
用户问题:{user_input}
请给出你的回复:
""".format(
chat_history=state["chat_history"],
user_input=state["user_input"]
)
state["response"] = call_qwen_model(prompt)
return state
def transfer_to_human_node(state: SupportState) -> SupportState:
"""节点5:转接人工客服"""
state["response"] = """
非常抱歉,我暂时无法解答你的问题。
正在为你转接人工客服,请稍候...
人工客服工作时间:9:00~18:00
你也可以通过以下方式联系我们:
- 客服热线:400-123-4567
- 邮箱:support@example.com
"""
return state
说明:
- 每个节点函数接收SupportState类型的状态对象,处理后原地更新并返回。
- 所有节点均为纯函数式设计:无副作用,仅依赖输入状态,输出更新后的状态。
- 除transfer_to_human_node外,其余节点均通过call_qwen_model调用大模型生成响应。
- 节点职责明确:
- 意图识别→分类。
- FAQ/技术/投诉→领域化生成。
- 转人工→静态兜底回复。
注意:call_qwen_model和 SupportState类型定义虽未在此段落内,但属于节点逻辑的必要依赖,在实际使用中需一并保留。
9.3.3 连接节点与转向边缘
“连接节点-转向边缘”(即定义节点之间如何连接,特别是基于条件的动态路由)主要体现在以下两个部分:
(1)使用条件路由函数(route_by_intent)决定从意图识别节点转向哪个处理节点。
(2)使用add_conditional_edges添加条件边。
(3)使用add_edge添加静态终止边(所有处理节点→END)。
以下是完整抽取的“连接节点-转向边缘”逻辑代码:
# 定义条件路由函数:根据意图状态动态选择下一个节点
def route_by_intent(state: SupportState) -> str:
"""根据意图转向不同节点"""
intent = state["intent"]
routing_map = {
"faq": "answer_faq",
"technical": "handle_technical",
"complaint": "handle_complaint",
"other": "transfer_to_human"
}
return routing_map.get(intent, "transfer_to_human")
# 添加从意图识别节点出发的条件边(动态路由)
graph.add_conditional_edges(
source="identify_intent",
path=route_by_intent,
path_map={
"answer_faq": "answer_faq",
"handle_technical": "handle_technical",
"handle_complaint": "handle_complaint",
"transfer_to_human": "transfer_to_human"
}
)
# 所有处理节点执行完毕后直接结束(静态边,无循环)
graph.add_edge("answer_faq", END)
graph.add_edge("handle_technical", END)
graph.add_edge("handle_complaint", END)
graph.add_edge("transfer_to_human", END)
说明:
- add_conditional_edges:实现动态分支,根据state["intent"]的值在运行时决定流向哪个节点。
- path_map:显式声明所有可能的返回值与目标节点的映射关系(LangGraph 1.x 推荐写法,增强可读性和校验)。
- add_edge(..., END):确保每个处理路径单向终止,符合“无递归、单次执行”的设计目标。
- 该逻辑位于build_support_graph()函数内部,依赖已添加的节点(如"identify_intent""answer
_faq" 等)。
9.3.4 LangSmith追踪
LangSmith 是一个用于调试、测试、评估和监控大型语言模型应用的开发平台,特别适合与 LangChain 等框架配合使用。本节将讲解LangSmith API密钥的申请和使用方法。
1. LangSmith API密钥的申请
首先到LangSmith网站https://smith.langchain.com申请LangSmith API密钥,步骤说明如下:
(1)访问LangSmith官网:打开浏览器,访问网址https://smith.langchain.com。
(2)登录或注册账号:如果你已经有LangChain账号(例如通过GitHub或邮箱注册过),直接登录。如果没有,请点击Sign Up注册一个新账号(支持GitHub、Google或邮箱注册)。
(3)进入API密钥管理页面:点击右上角你的头像或用户名,在下拉菜单中选择“API Keys”(或访问:https://smith.langchain.com/settings/api_keys)。
(4)创建新API密钥:点击“Create API Key”按钮,为密钥添加一个描述(如My LangGraph Project),再点击Create按钮,系统会生成一个形如lsk_abc123def456...的密钥。
(5)使用API密钥,在你的代码或环境变量中设置:
- export LANGCHAIN_API_KEY=lsk_abc123def456...
- export LANGCHAIN_TRACING_V2=true
- export LANGCHAIN_PROJECT=YourProjectName # 可选,指定项目名
启用LANGCHAIN_TRACING_V2=true后,LangChain会自动将trace数据发送到LangSmith网站,方便读者调试和分析。简单说,使用LangSmith可以:
- 查看每个节点的执行过程。
- 监控模型调用的耗时和成本。
- 调试对话流程中的问题。
- 记录用户对话历史。
- 分析意图识别的准确性。
LangSmith追踪(LangSmith Tracing)的配置与使用主要体现在两个部分:
- 在系统环境变量LANGSMITH_API_KEY中配置(启用追踪并设置项目信息)。
- 在Gradio接口中使用tracing_v2_enabled上下文管理器包裹图的执行。
2. LangSmith追踪相关代码
以下是完整抽取的LangSmith追踪相关代码。
(1)环境配置(启用LangSmith追踪):
# ====================== 1. 环境配置(启用 LangSmith 追踪) ======================
import os
from dotenv import load_dotenv
from langchain_core.tracers.context import tracing_v2_enabled
load_dotenv()
# 启用 LangSmith 追踪
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = os.getenv("LANGCHAIN_API_KEY") or ""
os.environ["LANGCHAIN_PROJECT"] = "客户支持聊天机器人-无递归版"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
(2)在图执行时启用追踪上下文:
# ====================== 2. 在图执行时启用追踪上下文 ======================
def chat_interface(message, history):
# ...(构建 initial_state)
# 使用 tracing_v2_enabled 上下文管理器包裹图的invoke调用
with tracing_v2_enabled(project_name="客户支持聊天机器人"):
result = support_graph.invoke(initial_state)
return result["response"]
说明:
- LANGCHAIN_TRACING_V2="true":全局开启LangChain v2追踪功能。
- LANGCHAIN_API_KEY:用于认证LangSmith服务(需在LangSmith获取)。
- LANGCHAIN_PROJECT:指定追踪数据归属的项目名称(用于LangSmith控制台分组)。
- LANGCHAIN_ENDPOINT:LangSmith API地址(默认官方地址)。
- tracing_v2_enabled(project_name=...):上下文级追踪控制,确保本次invoke的完整执行链(包括所有节点)被记录到指定项目。
该代码通过“环境变量全局启用+上下文管理器精细控制”的方式,实现了对LangGraph工作流执行过程的端到端可观测性,所有节点输入/输出、模型调用、状态变更均可在LangSmith控制台中查看、调试和评估。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)