智能体开发(1)LangGraph的轮次对话
·
一、目的
从最简单的调用api开始,不断加入中断执行、审批流程、输入验证、交互对话、反馈循环,实现良好人际交互
二、对话
2.1 调用API
客户端对话补全创造
注:1.是创造本次对话的完整回复,即只有一个回复,choices[0];2.下面的n用不了
| 对象 | 常用参数 | 说明 |
|----------------|-------------------|--------------------------|
| create() | model, messages | 模型,消息列表 |
| | n | 生成几个回复选项 |
| | temperature | 随机性 (0-2) |
| | max_tokens | 最大输出长度 |
| | stream | 是否流式输出 |
| response | id, model | 请求ID,模型名 |
| | choices | 回复选项列表 |
| | usage | token使用统计 |
| choices[] | message | 消息对象 |
| | finish_reason | 结束原因 |
| message | role, content | 角色,内容 |
| usage | prompt_tokens | 输入token数 |
| | completion_tokens | 输出token数 |
#得充钱才行
os.environ["DEEPSEEK_API_KEY"] = "your api_key"
# Please install OpenAI SDK first: `pip3 install openai`
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get('DEEPSEEK_API_KEY'),
base_url="https://api.deepseek.com")
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Hello"},
],
stream=False
)
print(response.choices[0].message.content)
2.2 LangGraph+api
LangGraph
状态:信息列表; 节点:调用api,将角色和信息返回状态; 图:api---end
api:客户端对话补全创造
import os
from typing import TypedDict
from openai import OpenAI
from langgraph.graph import StateGraph, END
# 初始化 DeepSeek 客户端
client = OpenAI(
api_key=os.environ.get('DEEPSEEK_API_KEY'),
base_url="https://api.deepseek.com"
)
# 定义状态
class GraphState(TypedDict):
messages: list
# 节点函数 - 调用 DeepSeek API
def call_api_node(state: GraphState):
"""调用 DeepSeek API 的节点"""
response = client.chat.completions.create(
model="deepseek-chat",
messages=state["messages"],
stream=False,
)
# 将回复添加到消息列表
state["messages"].append({
"role": "assistant",
"content": response.choices[0].message.content
})
return state
# 创建图
def create_simple_graph():
graph = StateGraph(GraphState)
# 添加节点
graph.add_node("call_api", call_api_node)
# 设置入口点
graph.set_entry_point("call_api")
# 设置结束边
graph.add_edge("call_api", END)
return graph.compile()
# 使用图
if __name__ == "__main__":
# 创建图
app = create_simple_graph()
# 初始状态
initial_state = {
"messages": [
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Hello"},
]
}
# 执行图
result = app.invoke(initial_state)
# 打印结果
print(result["messages"][-1]["content"])
2.3 多轮对话
中断和人工干预
状态:退出
节点
输入:查看是否有退出
回复:如果是退出,就返回
是否继续:看退出状态
做图:输入-回复-是否继续-end
import os
from typing import TypedDict
from openai import OpenAI
from langgraph.graph import StateGraph, END
client = OpenAI(
api_key=os.environ.get('DEEPSEEK_API_KEY'),
base_url="https://api.deepseek.com"
)
class ChatState(TypedDict):
messages: list
should_exit: bool # 新增退出标志
def get_input_node(state: ChatState) -> ChatState:
"""获取用户输入"""
user_input = input("👤 您: ")
# 检查是否退出
if user_input.lower() in ['退出', 'quit', 'exit', '结束']:
return {
"messages": state["messages"],
"should_exit": True # 设置退出标志
}
# 添加用户消息到历史
new_messages = state["messages"] + [
{"role": "user", "content": user_input}
]
return {
"messages": new_messages,
"should_exit": False
}
def ai_respond_node(state: ChatState) -> ChatState:
"""AI回复"""
# 如果应该退出,直接返回
if state.get("should_exit", False):
return state
response = client.chat.completions.create(
model="deepseek-chat",
messages=state["messages"],
stream=False,
)
ai_reply = response.choices[0].message.content
# 添加AI回复到历史
new_messages = state["messages"] + [
{"role": "assistant", "content": ai_reply}
]
print(f"🤖 AI: {ai_reply}")
return {
"messages": new_messages,
"should_exit": state.get("should_exit", False)
}
def should_continue(state: ChatState) -> str:
"""决定是否继续对话"""
# 检查退出标志
if state.get("should_exit", False):
return "end"
else:
return "continue"
# 创建多轮对话图
graph = StateGraph(ChatState)
graph.add_node("get_input", get_input_node)
graph.add_node("ai_respond", ai_respond_node)
graph.set_entry_point("get_input")
graph.add_edge("get_input", "ai_respond")
graph.add_conditional_edges(
"ai_respond",
should_continue,
{
"continue": "get_input",
"end": END
}
)
app = graph.compile()
# 使用
initial_state = {
"messages": [
{"role": "system", "content": "You are a helpful assistant"}
],
"should_exit": False
}
print("=== 多轮对话开始 ===")
print("输入 '退出' 结束对话")
result = app.invoke(initial_state)
print("对话已结束!")
2.4 智能客服工单系统
# 工单系统状态
class TicketState(TypedDict):
ticket_id: str
customer_issue: str
issue_category: str
severity_level: str
ai_solution: str
requires_human_review: bool
human_agent_assigned: Optional[str]
resolution_status: str
customer_feedback: Optional[str]
processing_log: List[str]
def analyze_customer_issue(state: TicketState) -> TicketState:
"""分析客户问题"""
issue = state.get("customer_issue", "")
ticket_id = f"TK-{int(time.time())}"[-8:]
# AI分析问题类别和严重程度
if "无法登录" in issue or "密码" in issue:
category = "账户问题"
severity = "中等"
elif "付款" in issue or "账单" in issue:
category = "财务问题"
severity = "高"
elif "功能" in issue or "使用" in issue:
category = "功能咨询"
severity = "低"
elif "故障" in issue or "错误" in issue:
category = "技术故障"
severity = "高"
else:
category = "一般咨询"
severity = "低"
print(f"📋 工单 {ticket_id}: 分析客户问题")
print(f" 类别: {category}, 严重程度: {severity}")
return {
"ticket_id": ticket_id,
"issue_category": category,
"severity_level": severity,
"resolution_status": "analyzing",
"processing_log": ["问题分析完成"]
}
def generate_ai_solution(state: TicketState) -> TicketState:
"""生成AI解决方案"""
category = state.get("issue_category", "")
severity = state.get("severity_level", "")
# 根据类别生成解决方案
solutions = {
"账户问题": "请尝试以下步骤:1) 点击'忘记密码'重置密码 2) 清除浏览器缓存 3) 使用其他设备尝试登录",
"财务问题": "建议:1) 检查账户余额和付款方式 2) 联系银行确认交易状态 3) 如需进一步帮助,将转接财务专员",
"功能咨询": "使用指南:1) 查看帮助文档 2) 观看教学视频 3) 如需个性化指导,可安排专人协助",
"技术故障": "故障处理:1) 重启应用程序 2) 检查网络连接 3) 更新到最新版本 4) 如问题持续,技术团队将介入",
"一般咨询": "感谢您的咨询!我们的客服团队会尽快为您提供详细解答。"
}
ai_solution = solutions.get(category, "我们正在分析您的问题,请稍候...")
# 判断是否需要人工审核
requires_human = severity == "高" or category in ["财务问题", "技术故障"]
print(f"🤖 AI方案: {ai_solution[:50]}...")
print(f"🔍 需要人工审核: {'是' if requires_human else '否'}")
return {
"ai_solution": ai_solution,
"requires_human_review": requires_human,
"resolution_status": "solution_generated",
"processing_log": state.get("processing_log", []) + ["AI方案生成完成"]
}
def human_agent_review(state: TicketState) -> TicketState:
"""人工客服审核"""
ticket_id = state.get("ticket_id", "")
ai_solution = state.get("ai_solution", "")
category = state.get("issue_category", "")
# 模拟分配人工客服
agents = ["Alice", "Bob", "Carol", "David"]
assigned_agent = random.choice(agents)
print(f"👨💼 人工客服 {assigned_agent} 审核工单 {ticket_id}")
print(f" 审核AI方案: {ai_solution[:80]}...")
# 模拟人工审核决定
review_decisions = ["approve", "modify", "escalate"]
decision = random.choice(review_decisions)
if decision == "approve":
print(f"✅ {assigned_agent}: AI方案已批准")
status = "approved_by_human"
log_msg = f"人工客服{assigned_agent}批准AI方案"
elif decision == "modify":
modified_solution = f"{ai_solution} [人工修改:建议优先联系技术支持团队]"
print(f"✏️ {assigned_agent}: AI方案已修改")
status = "modified_by_human"
log_msg = f"人工客服{assigned_agent}修改了AI方案"
else: # escalate
print(f"⬆️ {assigned_agent}: 问题升级至专业团队")
status = "escalated"
log_msg = f"人工客服{assigned_agent}将问题升级"
return {
"human_agent_assigned": assigned_agent,
"resolution_status": status,
"ai_solution": modified_solution if decision == "modify" else state.get("ai_solution", ""),
"processing_log": state.get("processing_log", []) + [log_msg]
}
def send_solution_to_customer(state: TicketState) -> TicketState:
"""向客户发送解决方案"""
ticket_id = state.get("ticket_id", "")
solution = state.get("ai_solution", "")
print(f"📧 向客户发送工单 {ticket_id} 的解决方案")
print(f" 方案内容: {solution[:100]}...")
# 模拟客户反馈
feedback_options = ["满意", "部分解决", "未解决"]
customer_feedback = random.choice(feedback_options)
print(f"📝 客户反馈: {customer_feedback}")
if customer_feedback == "满意":
status = "resolved"
elif customer_feedback == "部分解决":
status = "partially_resolved"
else:
status = "unresolved"
return {
"customer_feedback": customer_feedback,
"resolution_status": status,
"processing_log": state.get("processing_log", []) + [f"解决方案已发送,客户反馈:{customer_feedback}"]
}
def escalate_to_specialist(state: TicketState) -> TicketState:
"""升级给专家处理"""
ticket_id = state.get("ticket_id", "")
category = state.get("issue_category", "")
specialists = {
"技术故障": "技术支持团队",
"财务问题": "财务专员",
"账户问题": "账户安全专家",
}
specialist = specialists.get(category, "高级客服专员")
print(f"🎯 工单 {ticket_id} 已升级至 {specialist}")
print(f" 预计24小时内获得专业解答")
return {
"resolution_status": "escalated_to_specialist",
"human_agent_assigned": specialist,
"processing_log": state.get("processing_log", []) + [f"升级至{specialist}"]
}
# 决策函数
def decide_ticket_flow(state: TicketState) -> str:
"""决定工单处理流程"""
status = state.get("resolution_status", "")
requires_human = state.get("requires_human_review", False)
if status == "analyzing":
return "generate_solution"
elif status == "solution_generated" and requires_human:
return "human_review"
elif status == "solution_generated" and not requires_human:
return "send_solution"
elif status in ["approved_by_human", "modified_by_human"]:
return "send_solution"
elif status == "escalated":
return "escalate_specialist"
else:
return "end"
# 创建工单处理系统
def create_ticket_system():
checkpointer = MemorySaver()
graph = StateGraph(TicketState)
graph.add_node("analyze", analyze_customer_issue)
graph.add_node("generate_solution", generate_ai_solution)
graph.add_node("human_review", human_agent_review)
graph.add_node("send_solution", send_solution_to_customer)
graph.add_node("escalate_specialist", escalate_to_specialist)
graph.set_entry_point("analyze")
# 添加条件边
for node in ["analyze", "generate_solution", "human_review"]:
graph.add_conditional_edges(
node,
decide_ticket_flow,
{
"generate_solution": "generate_solution",
"human_review": "human_review",
"send_solution": "send_solution",
"escalate_specialist": "escalate_specialist",
"end": END
}
)
graph.add_edge("send_solution", END)
graph.add_edge("escalate_specialist", END)
return graph.compile(checkpointer=checkpointer)
# 测试工单系统
ticket_app = create_ticket_system()
print("\n=== 智能客服工单系统演示 ===")
# 测试不同类型的客户问题
test_issues = [
"我无法登录账户,一直提示密码错误",
"付款时遇到错误,订单状态异常",
"如何使用新功能进行数据导出?",
"系统出现严重故障,无法正常工作",
"想了解你们的服务包含哪些内容"
]
for i, issue in enumerate(test_issues):
print(f"\n{'='*20} 工单 {i+1} {'='*20}")
print(f"客户问题: {issue}")
ticket_thread_id = str(uuid.uuid4())
ticket_config = {"configurable": {"thread_id": ticket_thread_id}}
result = ticket_app.invoke({
"customer_issue": issue
}, config=ticket_config)
print(f"\n📊 处理结果:")
print(f" 工单ID: {result.get('ticket_id', 'N/A')}")
print(f" 问题分类: {result.get('issue_category', 'N/A')}")
print(f" 严重程度: {result.get('severity_level', 'N/A')}")
print(f" 最终状态: {result.get('resolution_status', 'N/A')}")
print(f" 分配客服: {result.get('human_agent_assigned', '无')}")
print(f" 客户反馈: {result.get('customer_feedback', '未收到')}")
print(f" 处理步骤: {' -> '.join(result.get('processing_log', []))}")更多推荐


所有评论(0)