智能客服技术设计

目录

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,       # 产品对比
]

处理流程:

  1. 根据 intent 选择工具
  2. 调用工具获取数据
  3. 格式化响应返回用户

3. RAGAgent(知识问答Agent)

职责: 处理知识类问题(使用教程、故障排查、政策咨询、FAQ)

支持意图:

  • USAGE_TUTORIAL - 使用教程
  • FAULT_DIAGNOSIS - 故障排查
  • POLICY_INQUIRY - 政策咨询
  • FAQ - 常见问题

工具集:

tools = [
    knowledge_retriever,   # 向量检索
    rerank_documents,      # 重排序(可选)
]

处理流程:

  1. 使用向量检索召回 Top-K 文档(K=10)
  2. 可选:使用 Reranker 重排序
  3. 将文档作为 context 传给 LLM
  4. LLM 生成答案

4. Orchestrator(多意图编排Agent)

职责: 处理多意图查询,并行调用多个子 Agent

场景示例:

  • 输入: "对比 Find X8 和 X9 的区别,并告诉我 X9 国补后多少钱"
  • 意图拆解:
    • 意图1: PRODUCT_COMPARE (Find X8 vs X9)
    • 意图2: PRICE_QUERY (X9 国补价格)

处理流程:

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(下一步)

  1. /speckit.task - 生成开发任务
  2. 实现 Coordinator 节点(TDD)
  3. 实现 ReactAgent 节点(TDD)
  4. 实现 Mock 工具
  5. 集成测试

Approval(批准)

角色 状态
Tech Lead ⏳ Pending
QA Lead ⏳ Pending

References(参考)

posted @ 2025-12-07 14:54  向着朝阳  阅读(14)  评论(0)    收藏  举报