智能客服技术设计
目录
- Technical Plan: 电商客服智能体
- Overview(概述)
- Architecture(架构)
- State Schema(状态Schema)
- LangGraph Structure(Graph 结构)
- Tools(工具定义)
- Data Flow(数据流)
- Caching Strategy(缓存策略)
- Error Handling(错误处理)
- Security(安全)
- Performance Optimization(性能优化)
- Testing Strategy(测试策略)
- Deployment(部署)
- Dependencies(依赖)
- Risks & Mitigations(风险与缓解)
- Open Questions(待解决问题)
- Next Steps(下一步)
Technical Plan: 电商客服智能体
Feature: R-001 电商客服智能体
Branch: 001-customer-service-agent
Created: 2025-12-08
Version: 1.0.0
Status: Draft
Overview(概述)
本文档定义 R-001 电商客服智能体的技术实现方案,包括 Multi-Agent 架构、State Schema、LangGraph 结构、工具定义、数据流设计等。
Architecture(架构)
Multi-Agent Architecture(多 Agent 架构)
系统采用分层、分工的 Multi-Agent 架构:
用户输入
↓
Coordinator (协调者)
├──→ ReactAgent (实时查询)
├──→ RAGAgent (知识问答)
├──→ Orchestrator (多意图编排)
│ ├──→ ReactAgent (并行)
│ ├──→ ReactAgent (并行)
│ └──→ RAGAgent (并行)
├──→ WorkflowAgent (流程处理)
└──→ Handoff (转人工)
Agent Responsibilities(Agent 职责)
1. Coordinator(协调者)
职责: 意图识别、实体提取、路由决策
输入:
- 用户输入文本
- 对话历史
输出:
- 意图分类结果(单一或多个)
- 提取的实体
- 路由目标(route_to)
路由逻辑:
if 意图数量 == 1:
if 意图 in [查询类]:
route_to = "react_agent"
elif 意图 in [知识类]:
route_to = "rag_agent"
elif 意图 in [流程类]:
route_to = "workflow_agent"
elif 意图 == 转人工:
route_to = "handoff"
elif 意图数量 >= 2:
route_to = "orchestrator"
else:
route_to = "handoff" # 兜底
工具:
classify_intent: 意图识别(可能使用缓存)extract_entities: 实体提取
2. ReactAgent(实时查询Agent)
职责: 处理查询类、推荐类、对比类意图
支持意图:
INVENTORY_CHECK- 库存查询PRICE_QUERY- 价格查询ORDER_QUERY- 订单查询LOGISTICS_QUERY- 物流查询PARAMS_QUERY- 参数查询PRODUCT_RECOMMEND- 产品推荐PRODUCT_COMPARE- 产品对比
工具集:
tools = [
product_search, # 产品搜索
get_inventory_info, # 库存查询
get_price_info, # 价格查询(含国补)
get_order_info, # 订单查询
get_logistics_info, # 物流查询
product_compare, # 产品对比
]
处理流程:
- 根据 intent 选择工具
- 调用工具获取数据
- 格式化响应返回用户
3. RAGAgent(知识问答Agent)
职责: 处理知识类问题(使用教程、故障排查、政策咨询、FAQ)
支持意图:
USAGE_TUTORIAL- 使用教程FAULT_DIAGNOSIS- 故障排查POLICY_INQUIRY- 政策咨询FAQ- 常见问题
工具集:
tools = [
knowledge_retriever, # 向量检索
rerank_documents, # 重排序(可选)
]
处理流程:
- 使用向量检索召回 Top-K 文档(K=10)
- 可选:使用 Reranker 重排序
- 将文档作为 context 传给 LLM
- LLM 生成答案
4. Orchestrator(多意图编排Agent)
职责: 处理多意图查询,并行调用多个子 Agent
场景示例:
- 输入: "对比 Find X8 和 X9 的区别,并告诉我 X9 国补后多少钱"
- 意图拆解:
- 意图1:
PRODUCT_COMPARE(Find X8 vs X9) - 意图2:
PRICE_QUERY(X9 国补价格)
- 意图1:
处理流程:
1. 接收多个意图
2. 并行调用:
- ReactAgent 处理 PRODUCT_COMPARE
- ReactAgent 处理 PRICE_QUERY
3. 收集所有子结果
4. 合并格式化返回用户
伪代码:
async def orchestrator_node(state):
intents = state["intents"] # 多个意图
tasks = []
for intent in intents:
if intent.type in [查询类, 推荐类, 对比类]:
tasks.append(invoke_react_agent(intent))
elif intent.type in [知识类]:
tasks.append(invoke_rag_agent(intent))
results = await asyncio.gather(*tasks)
merged_response = merge_results(results)
return {"response": merged_response}
5. WorkflowAgent(流程处理Agent)
职责: 处理多步流程(退货、换货、维修、开发票)
支持意图:
RETURN_PROCESS- 退货流程EXCHANGE_PROCESS- 换货流程REPAIR_PROCESS- 维修流程INVOICE_PROCESS- 开发票流程
工具集:
tools = [
get_order_info, # 订单查询(验证资格)
create_return_order, # 创建退货单
create_repair_order, # 创建维修工单
generate_invoice, # 生成发票
]
处理流程(以退货为例):
async def return_workflow(state):
step = state.get("workflow_step", 1)
if step == 1:
# 收集订单号
return {"prompt": "请提供您的订单号", "workflow_step": 2}
elif step == 2:
# 验证订单资格
order = await get_order_info(state["order_id"])
if not order or order.status != "已签收":
return {"response": "订单状态不符,无法退货"}
days_since_delivery = (now - order.delivery_date).days
if days_since_delivery > 7:
return {"response": "已超过退货期限(7天无理由退货)"}
return {"prompt": "请告知退货原因", "workflow_step": 3}
elif step == 3:
# 收集退货原因
reason = state["user_input"]
return {"prompt": "是否需要上传商品照片?(可选)", "workflow_step": 4}
elif step == 4:
# 生成退货单
return_order = await create_return_order({
"order_id": state["order_id"],
"reason": state["return_reason"],
"photos": state.get("photos", [])
})
return {
"response": f"退货单已生成({return_order.id}),退货地址:XXX",
"workflow_complete": True
}
6. Handoff(转人工)
职责: 转接人工客服,记录转接原因
转接触发条件:
- 意图识别置信度 < 0.5
- 用户明确要求转人工
- 连续3次无法回答
处理流程:
def handoff_node(state):
reason = state.get("handoff_reason", "未知原因")
# 记录日志
logger.info(f"转人工: {reason}")
return {
"response": "正在为您转接人工客服,请稍候...",
"handoff": True
}
State Schema(状态Schema)
系统使用 TypedDict 定义状态,所有节点共享同一状态。
from typing import TypedDict, List, Optional, Literal, Any
from enum import Enum
class IntentType(str, Enum):
# 查询类
INVENTORY_CHECK = "库存查询"
PRICE_QUERY = "价格查询"
ORDER_QUERY = "订单查询"
LOGISTICS_QUERY = "物流查询"
PARAMS_QUERY = "参数查询"
# 对比类
PRODUCT_COMPARE = "产品对比"
# 推荐类
PRODUCT_RECOMMEND = "产品推荐"
# 流程类
RETURN_PROCESS = "退货流程"
EXCHANGE_PROCESS = "换货流程"
REPAIR_PROCESS = "维修流程"
INVOICE_PROCESS = "开发票流程"
# 知识类
USAGE_TUTORIAL = "使用教程"
FAULT_DIAGNOSIS = "故障排查"
POLICY_INQUIRY = "政策咨询"
FAQ = "常见问题"
# 转人工
HANDOFF = "转人工"
class Intent(TypedDict):
type: IntentType
confidence: float
entities: dict # 提取的实体 {product_model, price_range, ...}
class CustomerServiceState(TypedDict):
# 输入
messages: List[dict] # 对话历史
user_input: str # 当前用户输入
thread_id: str # 会话 ID
# 意图识别
intents: List[Intent] # 识别的意图列表(可能多个)
route_to: Optional[str] # 路由目标
# Agent 执行
tool_calls: List[dict] # 工具调用记录
tool_results: List[Any] # 工具返回结果
# 流程控制
workflow_step: Optional[int] # 流程类当前步骤
workflow_data: Optional[dict] # 流程类收集的数据
workflow_complete: bool # 流程是否完成
# 输出
response: Optional[str] # 最终返回给用户的回复
agent_name: Optional[str] # 当前执行的 Agent 名称
# 异常处理
error: Optional[str] # 错误信息
handoff: bool # 是否转人工
handoff_reason: Optional[str] # 转人工原因
LangGraph Structure(Graph 结构)
Graph Definition(Graph 定义)
from langgraph.graph import StateGraph, END
def build_customer_service_graph():
workflow = StateGraph(CustomerServiceState)
# 添加节点
workflow.add_node("coordinator", coordinator_node)
workflow.add_node("react_agent", react_agent_node)
workflow.add_node("rag_agent", rag_agent_node)
workflow.add_node("orchestrator", orchestrator_node)
workflow.add_node("workflow_agent", workflow_agent_node)
workflow.add_node("handoff", handoff_node)
# 设置入口点
workflow.set_entry_point("coordinator")
# 定义条件边(从 Coordinator 路由)
workflow.add_conditional_edges(
"coordinator",
route_from_coordinator,
{
"react_agent": "react_agent",
"rag_agent": "rag_agent",
"orchestrator": "orchestrator",
"workflow_agent": "workflow_agent",
"handoff": "handoff"
}
)
# 定义结束边
workflow.add_edge("react_agent", END)
workflow.add_edge("rag_agent", END)
workflow.add_edge("orchestrator", END)
workflow.add_edge("handoff", END)
# WorkflowAgent 可能循环
workflow.add_conditional_edges(
"workflow_agent",
route_from_workflow,
{
"continue": "workflow_agent",
"end": END
}
)
return workflow.compile(checkpointer=checkpointer)
Routing Functions(路由函数)
def route_from_coordinator(state: CustomerServiceState) -> str:
"""从 Coordinator 路由到下一个节点"""
route_to = state.get("route_to")
if route_to:
return route_to
# 默认兜底
return "handoff"
def route_from_workflow(state: CustomerServiceState) -> str:
"""WorkflowAgent 循环控制"""
if state.get("workflow_complete"):
return "end"
return "continue"
Tools(工具定义)
查询类工具
1. product_search(产品搜索)
@tool
def product_search(
price_min: Optional[int] = None,
price_max: Optional[int] = None,
ram: Optional[int] = None,
category: Optional[str] = None,
tags: Optional[List[str]] = None
) -> List[dict]:
"""
搜索符合条件的产品
Args:
price_min: 最低价格
price_max: 最高价格
ram: 内存 (GB)
category: 分类 (手机/平板/耳机)
tags: 标签 (女性/轻薄/游戏/拍照)
Returns:
产品列表 [{"model": "Find X8", "price": 2999, ...}]
"""
pass
2. get_inventory_info(库存查询)
@tool
def get_inventory_info(
product_model: str,
color: Optional[str] = None
) -> dict:
"""
查询产品库存
Args:
product_model: 产品型号
color: 颜色(可选)
Returns:
{"in_stock": True, "quantity": 156, "colors": ["白色", "黑色"]}
"""
pass
3. get_price_info(价格查询,含国补)
@tool
def get_price_info(
product_model: str,
apply_subsidy: bool = False
) -> dict:
"""
查询产品价格
Args:
product_model: 产品型号
apply_subsidy: 是否计算国补后价格
Returns:
{
"model": "Find X9",
"original_price": 3999,
"subsidy": 500,
"final_price": 3499
}
"""
pass
4. get_order_info(订单查询)
@tool
def get_order_info(order_id: str) -> dict:
"""
查询订单信息
Args:
order_id: 订单号
Returns:
{
"order_id": "12345",
"status": "已签收",
"tracking_number": "SF123456",
"delivery_date": "2025-12-01",
"items": [...]
}
"""
pass
5. get_logistics_info(物流查询)
@tool
def get_logistics_info(tracking_number: str) -> dict:
"""
查询物流信息
Args:
tracking_number: 快递单号
Returns:
{
"status": "运输中",
"current_location": "深圳南山区",
"estimated_arrival": "2025-12-10",
"history": [...]
}
"""
pass
6. product_compare(产品对比)
@tool
def product_compare(product_models: List[str]) -> dict:
"""
对比多个产品
Args:
product_models: 产品型号列表 (2-5个)
Returns:
{
"comparison_table": {
"Find X8": {"price": 2999, "processor": "天玑9300", ...},
"Find X9": {"price": 3999, "processor": "骁龙8 Gen3", ...}
}
}
"""
pass
流程类工具
7. create_return_order(创建退货单)
@tool
def create_return_order(
order_id: str,
reason: str,
photos: Optional[List[str]] = None
) -> dict:
"""
创建退货单
Args:
order_id: 原订单号
reason: 退货原因
photos: 商品照片(可选)
Returns:
{
"return_order_id": "R12345",
"return_address": "XXX",
"instructions": "请在3天内寄回"
}
"""
pass
8. create_repair_order(创建维修工单)
@tool
def create_repair_order(
device_imei: str,
issue_description: str,
warranty_status: str,
repair_type: Literal["到店", "寄修"]
) -> dict:
"""
创建维修工单
Args:
device_imei: 设备 IMEI
issue_description: 故障描述
warranty_status: 保修状态 (保内/保外)
repair_type: 维修方式
Returns:
{
"repair_order_id": "RP12345",
"estimated_cost": 800,
"appointment_info": "..."
}
"""
pass
9. generate_invoice(生成发票)
@tool
def generate_invoice(
order_id: str,
invoice_type: Literal["个人普票", "企业普票", "企业专票"],
invoice_title: str,
tax_id: Optional[str] = None
) -> dict:
"""
生成发票
Args:
order_id: 订单号
invoice_type: 发票类型
invoice_title: 发票抬头
tax_id: 税号(企业专票必填)
Returns:
{
"invoice_id": "INV12345",
"download_url": "https://...",
"delivery_method": "电子发票/邮寄"
}
"""
pass
知识类工具
10. knowledge_retriever(知识检索)
@tool
def knowledge_retriever(
query: str,
top_k: int = 10
) -> List[dict]:
"""
从知识库检索相关文档
Args:
query: 查询文本
top_k: 返回文档数量
Returns:
[
{"content": "...", "score": 0.95, "source": "使用手册"},
...
]
"""
pass
Data Flow(数据流)
场景1:简单查询(单一意图)
用户: "Find X8 多少钱?"
↓
Coordinator:
- intent = PRICE_QUERY
- entities = {product_model: "Find X8"}
- route_to = "react_agent"
↓
ReactAgent:
- 调用 get_price_info("Find X8")
- 返回: "Find X8 当前售价 2999 元"
↓
END
场景2:复杂多意图查询
用户: "对比 X8 和 X9,告诉我 X9 国补后多少钱"
↓
Coordinator:
- intents = [
{type: PRODUCT_COMPARE, entities: {products: ["X8", "X9"]}},
{type: PRICE_QUERY, entities: {product: "X9", subsidy: True}}
]
- route_to = "orchestrator"
↓
Orchestrator:
- 并行调用:
├─→ ReactAgent (PRODUCT_COMPARE)
│ └─→ product_compare(["X8", "X9"])
└─→ ReactAgent (PRICE_QUERY)
└─→ get_price_info("X9", apply_subsidy=True)
- 合并结果:
"X8 vs X9 对比表: ..."
"X9 国补后价格: 3499 元"
↓
END
场景3:流程类(退货)
用户: "我要退货"
↓
Coordinator:
- intent = RETURN_PROCESS
- route_to = "workflow_agent"
↓
WorkflowAgent (Step 1):
- prompt = "请提供订单号"
- workflow_step = 2
- route_to = "continue"
↓
用户: "订单号 12345"
↓
WorkflowAgent (Step 2):
- 调用 get_order_info("12345")
- 验证资格通过
- prompt = "请告知退货原因"
- workflow_step = 3
↓
用户: "不喜欢"
↓
WorkflowAgent (Step 3):
- 调用 create_return_order(...)
- response = "退货单已生成..."
- workflow_complete = True
↓
END
Caching Strategy(缓存策略)
意图识别缓存(Intent Cache)
- 目的: 减少重复意图识别的 LLM 调用
- Key:
md5(user_input)或语义哈希 - TTL: 24 小时
- 预期命中率: > 60%
向量检索缓存(Vector Search Cache)
- 目的: 加速知识库检索
- Key:
md5(query) - TTL: 1 小时
- 预期命中率: > 50%
API 响应缓存(Response Cache)
- 目的: 缓存工具调用结果(库存、价格)
- Key:
tool_name:params_hash - TTL: 5 分钟
- 预期命中率: > 70%
Error Handling(错误处理)
重试机制(Retry)
@retry(max_attempts=3, backoff=exponential, exceptions=[APIError])
async def call_tool(tool_name, params):
...
降级策略(Fallback)
- LLM 超时 → 返回预设回复
- 工具调用失败 → 返回缓存数据
- 知识库检索失败 → 转人工
熔断器(Circuit Breaker)
- 错误率 > 50% → 暂停调用,直接转人工
- 5分钟后自动恢复
Security(安全)
Prompt 注入防御
def validate_input(user_input: str) -> bool:
# 检测可疑指令
suspicious_patterns = [
r"ignore.*instructions",
r"system.*prompt",
r"你现在是.*"
]
for pattern in suspicious_patterns:
if re.search(pattern, user_input, re.IGNORECASE):
return False
return True
工具权限隔离
# 只读工具(无需特殊权限)
READONLY_TOOLS = [
"product_search",
"get_inventory_info",
"get_price_info",
"get_order_info",
"knowledge_retriever"
]
# 写入工具(需要用户认证)
WRITE_TOOLS = [
"create_return_order",
"create_repair_order",
"generate_invoice"
]
敏感数据脱敏
def mask_sensitive_data(text: str) -> str:
# 手机号脱敏
text = re.sub(r"(\d{3})\d{4}(\d{4})", r"\1****\2", text)
# 身份证脱敏
text = re.sub(r"(\d{6})\d{8}(\d{4})", r"\1********\2", text)
return text
频率限制
# 每用户 100 req/min
@rate_limit(limit=100, window=60)
async def handle_request(user_id, request):
...
Performance Optimization(性能优化)
异步处理
# 并行调用工具
results = await asyncio.gather(
get_price_info("X8"),
get_inventory_info("X8"),
get_order_info("12345")
)
连接池
# HTTP 连接池
session = aiohttp.ClientSession(
connector=aiohttp.TCPConnector(limit=100)
)
批量处理
# 批量向量检索
embeddings = await embed_batch(queries)
Testing Strategy(测试策略)
Unit Tests(单元测试)
- 每个 Agent 节点
- 每个工具函数
- 路由逻辑
示例:
def test_coordinator_single_intent():
state = {
"user_input": "Find X8 多少钱?",
"intents": [{"type": IntentType.PRICE_QUERY, ...}]
}
result = coordinator_node(state)
assert result["route_to"] == "react_agent"
Integration Tests(集成测试)
- 完整 Graph 执行
- 多意图场景
- 流程类完整流程
示例:
async def test_multi_intent_flow():
result = await graph.ainvoke({
"user_input": "对比 X8 和 X9,告诉我 X9 国补后多少钱"
})
assert "对比" in result["response"]
assert "3499" in result["response"]
E2E Tests(端到端测试)
- 通过 API 调用
- 验证 SSE 流式响应
Deployment(部署)
Environment(环境)
- Python 3.12+
- LangGraph
- FastAPI
- Uvicorn
Configuration(配置)
llm:
provider: dashscope
model: qwen-turbo
temperature: 0.7
cache:
type: redis
host: localhost
port: 6379
vector_db:
type: milvus
host: localhost
port: 19530
tools:
api_base_url: https://api.example.com
timeout: 5
Monitoring(监控)
- Metrics: 响应时间、QPS、错误率、缓存命中率
- Logging: 所有请求、工具调用、错误日志
- Tracing: 分布式追踪(LangSmith / OpenTelemetry)
Dependencies(依赖)
[tool.poetry.dependencies]
python = "^3.12"
langgraph = "^0.2.0"
langchain = "^0.3.0"
langchain-community = "^0.3.0"
fastapi = "^0.115.0"
uvicorn = "^0.32.0"
pydantic = "^2.0"
redis = "^5.0"
pymilvus = "^2.4"
httpx = "^0.27"
Risks & Mitigations(风险与缓解)
| 风险 | 缓解措施 |
|---|---|
| LLM 意图识别错误 | 置信度阈值、多轮确认、人工兜底 |
| 工具调用失败 | 重试机制、降级策略、熔断器 |
| 响应时间超标 | 缓存、并行调用、流式响应 |
| 安全攻击 | 输入验证、权限隔离、频率限制 |
Open Questions(待解决问题)
Next Steps(下一步)
/speckit.task- 生成开发任务- 实现 Coordinator 节点(TDD)
- 实现 ReactAgent 节点(TDD)
- 实现 Mock 工具
- 集成测试
Approval(批准)
| 角色 | 状态 |
|---|---|
| Tech Lead | ⏳ Pending |
| QA Lead | ⏳ Pending |
References(参考)

浙公网安备 33010602011771号