客服 Agent 完整架构设计

从意图识别到人工交接:构建三级客服智能体的工程实践

一、架构总览

客服 Agent 的核心挑战不是"能不能回答问题",而是"知道什么时候该升级、该交接、该闭嘴"。本文设计一个三级分流架构:L1 全自动解决高频问题,L2 Agent 辅助人工处理复杂场景,L3 无缝交接至人工坐席。

                     客服 Agent 三级架构
 ================================================================

 用户消息
   |
   v
 +---------------------------+
 |     意图分类器 (Router)    |    ← 基于 embedding + 规则双通道
 +---------------------------+
   |          |           |
   v          v           v
 +------+  +------+  +----------+
 |  L1  |  |  L2  |  |    L3    |
 | 自动  |  | 辅助  |  | 人工交接 |
 | 解决  |  | 处理  |  |         |
 +------+  +------+  +----------+
   |          |           |
   |     +----+----+      |
   |     | 知识库   |      |
   |     | (RAG)   |      |
   |     +---------+      |
   v          v           v
 +---------------------------+
 |    会话状态管理 (FSM)      |
 +---------------------------+
   |
   v
 +---------------------------+
 |    评估与反馈闭环          |
 +---------------------------+

二、意图分类器设计

意图分类是整个系统的"分诊台"。我们采用双通道策略:规则匹配处理确定性场景,向量检索处理模糊意图。

from dataclasses import dataclass
from enum import Enum
from typing import Optional
import numpy as np


class IntentLevel(Enum):
    L1_AUTO = "l1_auto"
    L2_ASSISTED = "l2_assisted"
    L3_HUMAN = "l3_human"


class IntentType(Enum):
    ORDER_QUERY = "order_query"
    REFUND_REQUEST = "refund_request"
    FAQ = "faq"
    COMPLAINT = "complaint"
    TECHNICAL_ISSUE = "technical_issue"
    ACCOUNT_SECURITY = "account_security"
    UNKNOWN = "unknown"


# 意图 -> 级别的路由映射
INTENT_ROUTING: dict[IntentType, IntentLevel] = {
    IntentType.ORDER_QUERY: IntentLevel.L1_AUTO,
    IntentType.FAQ: IntentLevel.L1_AUTO,
    IntentType.REFUND_REQUEST: IntentLevel.L2_ASSISTED,
    IntentType.TECHNICAL_ISSUE: IntentLevel.L2_ASSISTED,
    IntentType.COMPLAINT: IntentLevel.L3_HUMAN,
    IntentType.ACCOUNT_SECURITY: IntentLevel.L3_HUMAN,
    IntentType.UNKNOWN: IntentLevel.L2_ASSISTED,
}


@dataclass
class ClassificationResult:
    intent: IntentType
    level: IntentLevel
    confidence: float
    reasoning: str


def classify_intent(
    message: str,
    rule_patterns: dict[str, IntentType],
    embedding_model,
    intent_embeddings: dict[str, np.ndarray],
    confidence_threshold: float = 0.78,
) -> ClassificationResult:
    """双通道意图分类:规则优先,向量兜底。"""

    # 通道 1:规则匹配(确定性高、延迟低)
    normalized = message.lower().strip()
    for pattern, intent in rule_patterns.items():
        if pattern in normalized:
            return ClassificationResult(
                intent=intent,
                level=INTENT_ROUTING[intent],
                confidence=0.95,
                reasoning=f"rule_match: pattern='{pattern}'",
            )

    # 通道 2:向量检索(处理模糊表达)
    msg_embedding = embedding_model.encode(message)
    best_intent = IntentType.UNKNOWN
    best_score = 0.0

    for intent_name, intent_emb in intent_embeddings.items():
        score = float(np.dot(msg_embedding, intent_emb) / (
            np.linalg.norm(msg_embedding) * np.linalg.norm(intent_emb)
        ))
        if score > best_score:
            best_score = score
            best_intent = IntentType(intent_name)

    if best_score < confidence_threshold:
        best_intent = IntentType.UNKNOWN

    return ClassificationResult(
        intent=best_intent,
        level=INTENT_ROUTING[best_intent],
        confidence=best_score,
        reasoning=f"embedding_match: score={best_score:.3f}",
    )

三、会话状态机

客服对话不是无状态的问答,而是有明确生命周期的流程。用有限状态机管理会话,确保每个状态都有出路。

 会话状态流转图
 =============================================

 [idle] --用户发起--> [classifying]
                         |
            +------------+------------+
            |            |            |
            v            v            v
      [l1_resolving] [l2_assisting] [l3_queuing]
            |            |            |
            v            v            v
      [l1_resolved]  [l2_resolved] [l3_connected]
            |            |            |
            +------------+-----+------+
                               |
                               v
                        [feedback_pending]
                               |
                               v
                           [closed]

四、工具定义(Tool Schema)

Agent 的能力边界由工具决定。以下是三个核心工具的 JSON Schema 定义。

TOOLS = [
    {
        "name": "order_lookup",
        "description": "根据订单号或用户ID查询订单状态、物流信息、支付详情",
        "input_schema": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "订单编号,格式:ORD-YYYYMMDD-XXXXX",
                },
                "user_id": {
                    "type": "string",
                    "description": "用户ID,当无订单号时用于模糊查询",
                },
                "fields": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "需要返回的字段:status/logistics/payment/items",
                },
            },
            "required": ["fields"],
        },
    },
    {
        "name": "process_refund",
        "description": "发起退款申请。金额超过500元或订单超过30天需人工审批",
        "input_schema": {
            "type": "object",
            "properties": {
                "order_id": {"type": "string"},
                "reason": {
                    "type": "string",
                    "enum": [
                        "quality_issue",
                        "wrong_item",
                        "not_received",
                        "changed_mind",
                        "other",
                    ],
                },
                "amount": {
                    "type": "number",
                    "description": "退款金额(元),不得超过订单实付金额",
                },
                "evidence_urls": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "凭证图片URL列表",
                },
            },
            "required": ["order_id", "reason", "amount"],
        },
    },
    {
        "name": "faq_search",
        "description": "在知识库中检索FAQ,返回最相关的答案片段",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {"type": "string", "description": "用户问题"},
                "category": {
                    "type": "string",
                    "description": "限定搜索类目:shipping/payment/account/product",
                },
                "top_k": {
                    "type": "integer",
                    "default": 3,
                    "description": "返回结果数量",
                },
            },
            "required": ["query"],
        },
    },
]

五、System Prompt 模板

# 角色
你是「灵阙商城」的智能客服助手。你的职责是高效、准确、有温度地帮助用户解决问题。

# 核心原则
1. 先理解,再回答。确认用户意图后再调用工具,不要猜测。
2. 能解决就解决,不能解决就升级。禁止给用户"踢皮球"的感受。
3. 涉及资金操作(退款/赔偿)必须二次确认。
4. 不编造信息。知识库没有的答案,如实告知并升级。
5. 保持简洁。每次回复不超过3段,优先用列表呈现关键信息。

# 工具使用规则
- order_lookup: 用户提到订单/物流/发货时调用
- process_refund: 仅在用户明确表达退款意愿且确认后调用
- faq_search: 通用问题优先检索知识库

# 升级规则(触发任一条件立即升级至人工)
- 用户连续表达不满超过2轮
- 涉及账户安全(盗号/异常登录/资金异常)
- 退款金额 > 500元
- Agent 连续2次未能解决用户问题(用户重复提问)
- 用户主动要求人工服务

# 会话上下文
当前用户ID: {{user_id}}
会话ID: {{session_id}}
历史摘要: {{conversation_summary}}

六、RAG 知识库集成

 知识库检索流程
 =============================================

 用户问题
   |
   v
 +------------------+
 | Query Rewriting  |    ← 消歧义 + 关键词提取
 +------------------+
   |
   v
 +------------------+
 | Hybrid Search    |    ← BM25 + 向量检索
 | (Elasticsearch   |
 |  + pgvector)     |
 +------------------+
   |
   v
 +------------------+
 | Reranker         |    ← Cross-encoder 精排
 +------------------+
   |
   v
 +------------------+
 | Context Assembly |    ← Top-3 片段 + 元数据
 +------------------+
   |
   v
 +------------------+
 | LLM Generation   |    ← 基于检索结果生成回答
 +------------------+

知识库数据来源:产品手册、退换货政策、物流规则、历史工单(脱敏)、FAQ 文档。每周增量更新,每月全量重建索引。

七、评估指标体系

指标 定义 L1 目标 L2 目标 L3 基线
自动解决率 L1 独立解决 / 总会话 >= 65% - -
首次解决率 (FCR) 单次会话解决 / 总会话 >= 80% >= 70% >= 85%
平均处理时长 (AHT) 从开始到关闭的平均时间 < 90s < 300s < 600s
用户满意度 (CSAT) 结束后评分 4-5 星占比 >= 85% >= 80% >= 90%
升级准确率 应升级且升级 / 应升级总数 >= 95% - -
幻觉率 回答与知识库矛盾的比例 < 2% < 1% -

八、关键设计决策

  1. 为什么不用纯 LLM 做意图分类? 规则通道处理确定性场景(订单号正则匹配)延迟 < 5ms,向量通道处理模糊表达延迟 ~50ms。混合策略比纯 LLM 分类(~500ms)快一个数量级,且规则部分 100% 可控。

  2. 为什么 L2 不是全自动? 退款等资金操作的错误成本极高。L2 让 Agent 准备好方案、拉取数据、草拟回复,但最终操作由人工确认。这是成本与风险的最优平衡点。

  3. 为什么用状态机而不是自由对话? 自由对话在客服场景容易失控(Agent 被用户带偏、忘记收集关键信息)。状态机确保每个阶段有明确目标和退出条件,同时保留 LLM 在每个状态内的灵活表达能力。

  4. 升级判定为什么用规则而不是情感分析? 情感分析模型在短文本上准确率不稳定(约 75-80%)。而"连续不满2轮"的规则判定虽然粗糙,但误判成本低(最多多升级几次),远好过漏判导致用户流失。


Maurice | maurice_wen@proton.me