Appearance
项目三速成:企业智能客服 Multi-Agent 平台
深挖版见 03-项目-智能客服MultiAgent。本文目标:60 分钟读懂 + 20 分钟画熟 + 20 分钟背数字。 这个项目必被追问的一个数字:转人工率 35%→18%——单讲下降会被质疑「该转的没转」,必须配反向指标(见数字卡,必背)。
记忆锚点:闸门。 模型只能 propose(产出申请单),execute 永远在人确认后的确定性代码里;所有失败有分类去向,所有动作可倒查。
一、项目名片(30 秒能背)
- 业务:售前咨询、订单查询、售后、投诉、退款散在不同系统和坐席手里;写操作(退款/工单)让模型直接调风险不可控;复杂任务缺人工兜底 → 统一 Multi-Agent 入口,可审计。
- 我的位置:Agent 编排层(主图+五个领域子图)、Tool 安全层、HITL、审计分析归我;订单/CRM/工单是业务系统团队的 OpenAPI,我只消费;知识库 RAG 检索服务是复用(我做引用约束和拒答)。措辞统一成「我负责编排层与工具安全层」,别说主导整个客服系统。
- 栈:Python / FastAPI / LangGraph / LangChain / PostgreSQL / Redis / SSE。
- 一句话价值:把「会说话的机器人」做成敢让它动钱的系统——风险分级、人工兜底、全链路可审计。
二、架构与一次退款会话的旅程(必须画得出)
一次退款会话(背):主 Agent 意图识别(规则前置强信号 + LLM 受限枚举 + 低置信澄清)→ 路由到售后子图 → 子图内 ReAct + Tool Calling → 识别为敏感操作 → 模型最多产出一张「申请单」(参数过 Pydantic + 来源白名单 + 业务不变量)→ interrupt 挂起,Checkpoint 和审批单落 PostgreSQL → 坐席确认后凭 thread_id 恢复,确定性代码执行(带幂等键)→ 超时未确认默认拒绝 → 全程审计可倒查。
三、技术方案四大块
3.1 主 Agent + 领域子 Agent
- 为什么拆(不是赶时髦):单 Agent 挂五条线全部工具时,工具集和 Prompt 互相污染——物流问题调退款工具、选错率随工具数上升;改一条线要回归全部。
- 拆分标准(背):「工具集 + 数据权限 + 话术规则」三条线是否一致;一致的合并,不一致的独立成子图;每个子图工具数控制在小集合。
- 主 Agent 只做三件事:意图识别、任务拆解、条件路由;不持有任何业务工具——路由决策点唯一、可审计,主图上下文不被业务细节撑大。
- State 分层:主图只留意图、用户身份、当前子任务、最终结果;领域中间态(候选订单、检索证据、待确认参数)留子图。跨域请求由主图拆成子任务顺序执行,子图间不直接通信。
- 意图识别怎么保证(没算法背景的答法):规则前置(订单号、「退款」等强信号直连)+ LLM 输出受限枚举(可校验)+ 置信度低走澄清 + 错分样本回灌 few-shot 和回归用例。「我用可回归的工程方法控制质量。」
- 为什么不去中心化 handoff:客服要能倒查「这次为什么走到退款」,中心化 supervisor 决策点唯一;去中心化易绕圈难定责。
- 加新业务线改哪:加子图 + 注册意图枚举 + 补回归用例,主图不动——这正是拆分的收益,也是「该不该拆」的标准。
3.2 Tool 层:封装、校验与失败矩阵
- Tool Calling 本质:模型只输出「想调什么、参数是什么」,执行永远在我的代码里——安全边界做在执行侧,不写在 Prompt 里。
- 面向任务封装:内部接口不是一对一映射成 Tool;按「客服会问什么」收敛(查订单状态、查物流轨迹、创建售后工单),一个 Tool 内部可串多个下游调用。描述和 JSON Schema 是给模型看的说明书;返回体做字段白名单投影,不把原始大 JSON 灌回上下文。
- ReAct 只用在需要中间结果决策的链路;一步定死的只读查询走确定性节点。防打转:最大步数 + 同工具同参重复调用检测 + 无进展检测,触顶走兜底或转人工。
- 错误分类矩阵(背四类):可重试(超时/限流/5xx,指数退避)、可修正(Schema/参数问题,回模型有限次)、业务终态(订单不存在/已退款——不重试,转成结论答复)、不可恢复(鉴权/熔断,降级或转人工)。写操作超时=「结果未知」,必须先查询确认再决定,绝不盲目重试。
- 参数来源白名单(故障沉淀):模型曾编造格式合法的订单号查到别人的单。之后关键实体只能取自 State 已确认字段或前序工具返回,Tool 内部再做归属校验(这单是否属于当前用户)。格式合法 ≠ 来源可信。
- 只读工具也不许泄露:每次调用强制携带调用者身份,数据权限在 Tool 内按用户过滤,不依赖模型传对参数。
- 为什么不用 MCP:当时工具都在同一服务内、调用方只有这个 Agent,收益不足;要跨团队复用就包成 MCP Server。
3.3 风险分级与幂等(最硬的一段)
- 分级:只读类直接执行;敏感写类(退款、创建工单、改地址、发券)→ 必须过 HITL + 必须带幂等键 + 审计记到最细。哪些工具是敏感级是配置死的,模型没有话语权。
- 入参校验链(四层拦截,背):Pydantic Schema 校验 → 参数来源白名单 → 业务不变量与状态机校验(退款金额≤可退金额、订单状态机允许的动作)→ HITL 人工确认。任何一层不过都不执行;校验失败把逐字段错误结构化回传模型修,限次后转人工。
- 幂等键构造(必背):稳定业务要素拼接后哈希——租户+用户 ID+业务类型+业务主键(订单号)+关键参数(金额)+审批单 ID;不含时间戳和随机数。落幂等记录表加唯一索引,冲突返回首次结果。带审批单 ID 是为了区分「重复表达同一诉求」和「真的要发起第二笔」。
- 写操作三件套:幂等键 + 超时(结果未知先查询确认)+ 结构化错误返回。写操作三种结果:成功、失败、未知——未知单独处理是本项目最深的一条认知。
- 两段式是最关键的一刀:模型最多产出申请单(propose),execute 由审批通过后的确定性代码执行,模型不在执行路径上。金额上限这类规则放服务端代码,绝不能只靠 Prompt。
- 事务边界:不跨 LLM 调用持有事务;写操作短事务落本地状态,与下游之间用「本地状态机+补偿」,不用分布式事务。两个坐席同时审批同一单:状态流转用条件更新(pending→approved 只成功一次)+ 执行侧幂等兜底。
3.4 HITL、记忆与审计
- HITL 节点选择标准(三条同时成立):动作不可逆、影响资金或客户信誉、需要人类判断。只读不挂起,否则坐席被淹没。
- 实现:LangGraph interrupt + Checkpointer——到审批节点前把状态持久化并中断,SSE 推「待审批」;坐席确认后凭同一 thread_id 恢复。挂起态不能只存内存:Checkpoint 落 PostgreSQL + 独立审批单表(业务可查、可做看板、可被超时任务扫描),两者用 thread_id 关联。多实例部署时服务无状态,任意实例都能续跑。
- 超时默认拒绝(绝不默认通过):后台扫描过期单 → 置 timeout → 走拒绝分支通知用户并留痕。
- 审计闭环:谁、什么时间、看到什么参数、批还是拒、执行结果——任何一笔退款能倒查完整决策链。防绕过:执行函数只接受带有效审批单 ID 的调用;用审计日志对账,每笔写操作必须匹配一条已通过的审批单。
- 会话记忆三层:Redis 短期状态与最近若干轮;关键业务事实(身份、订单号、已确认参数)以结构化字段进 State(不靠模型从历史回忆);超长对话滑窗+摘要(摘要只压闲聊,关键事实不靠它)。Redis 丢的是可丢的(缓存/摘要),不可丢的(审批单/审计/Checkpoint)在 PG。
- 拒答三类:证据不足、路由不确定(澄清一次仍不明确)、多次调用失败。拒答必须给出口(转人工/自助入口),原因枚举落库——是补知识库补工具的输入,不是一句「答不了」。
- 指标三层(背):工具层(成功率、错误类型分布、P95 耗时)/ 编排层(路由准确率、平均步数、HITL 触发与通过率)/ 业务层(任务完成率、转人工率、人工改写率)。固定用例集回归:改 Prompt、加工具、换模型前后各跑一遍,退步不发布。
四、简历 bullet 对照表
| 简历 bullet | 两个技术锚点 | 20 秒展开方向 |
|---|---|---|
| 主+子 Agent 架构与路由 | 拆分三标准 / 主图不持工具 | 工具集权限话术一致才合并;路由决策点唯一可审计;加线只加子图 |
| ReAct + Tool Calling + 失败分类 | 执行侧安全边界 / 错误四分类 | 面向任务封装 Tool;失败按类型走重试/修正/终态答复/转人工;写操作超时先确认 |
| 风险分级 + Pydantic + 幂等 | 四层校验链 / 幂等键构造 | 只读/敏感分级;敏感操作模型只 propose;幂等键=业务要素+审批单 ID |
| HITL + 审计 | interrupt+Checkpoint 落库 / 超时默认拒绝 | 挂起态是可持久化可恢复可超时的业务数据;多实例无状态恢复;审批对账 |
| RAG + 记忆 + SSE + 拒答 | 关键事实结构化不靠回忆 / 拒答三类给出口 | 阶段事件推意图/路由/工具/待审批;证据不足转人工 |
| 埋点回归 + 94%/86% | 指标三层 / 固定用例集回归 | 只看端到端等于没测;失败样本回灌评测集 |
五、数字解释卡(4 个)
| 简历上的数 | 口径 | 被问「怎么来的」第一句话 |
|---|---|---|
| 工具调用成功率 94% | 分母 = 发起调用次数(重试合并计数);分子 = 最终返回业务成功的次数;只读与写分开报;业务终态拒绝(订单不存在)不算失败算正常答复 | 「94% 按最终结果算,含重试后成功,只读和写分开统计;失败的部分全部有去向——重试、转人工或明确告知用户,没有静默失败」 |
| 任务完成率 86% | 分母 = 有明确任务意图的会话(剔除闲聊);分子 = 会话内达成目标、无转人工、无人工改写;规则判定 + 抽样人工复核 | 「『完成』是规则判的:会话内达成目标且没转人工没被人工改写,另抽样人工复核;用户中途放弃单独统计不混在里面」 |
| 日均约 1,500 次会话 | 统计窗口内会话数/天数;会话切分口径要定死(如 30 分钟无消息算新会话);排除内部测试账号 | 「上线后稳定期的日均,会话按 30 分钟无消息切分,测试流量剔除」 |
| 转人工率 35% → 18% | ⚠️ 全篇最危险的数字,必须主动拆:①分子分母=转人工会话/总会话;②拆主动转(拒答/低置信/失败兜底)vs 被动转(用户要求);③35% 的基线=老客服系统日志,口径对齐过;④必配反向指标——漏转率或人工事后纠正率、二次来访率,证明下降不是靠「少转」换的;⑤HITL 覆盖率是硬约束不参与优化 | 「18% 里大头是被动转和兜底转,简单问答基本被接住了;同时我们盯人工纠正率——没有因为少转而多出投诉。高风险操作的人工确认覆盖率没有随这个指标降」 |
如果被问漏转率没统计过:直说「严格的漏转率统计是当时的欠账,我们主要靠投诉和二次来访做侧面验证」——承认欠账比编指标安全。
说不准时的兜底句:「拿不出口径的数字我不敢往上报;先讲我们怎么定义指标、怎么发现退步,具体数值我核对完再给你。」
六、高频追问 6 题(每题 3-4 句接住)
- 幂等键怎么构造? —— 业务要素哈希(租户+用户+类型+主键+金额+审批单 ID),不含时间戳随机数;唯一索引兜底;带审批单 ID 区分重复诉求和二次发起;下游支持就透传同一键,双层保护。
- 挂起态存哪?服务重启怎么办? —— PG Checkpoint + 独立审批单表,thread_id 关联;服务无状态,任意实例可恢复;曾有挂起态只存内存导致重启失联的教训(⚠️ 换成真实经历),之后「任何实例挂掉流程必须能换实例续跑」成了评审必检项。
- 转人工率下降是好事吗? —— 主动拆主动转/被动转 + 配反向指标 + HITL 不参与优化(答案见数字卡,这段要背熟)。
- Multi-Agent 是不是过度设计? —— 给判断依据不给立场:工具数与误选率、业务线间 Prompt 规则冲突、按域收敛数据权限、独立回归收益;同时承认代价(多一跳路由延迟);少于两三条业务线我不会这么拆。
- 模型幻觉参数怎么拦? —— 四层:Schema 校验 / 参数来源白名单 / 业务不变量状态机 / HITL。曾出过编造订单号的事故,之后实体只许来自 State 或工具返回(⚠️ 用真实版本讲)。
- 为什么不用 Dify/Coze 或客服 SaaS? —— 卡点在「写操作+审批+审计」要深度接内部系统和组织权限:幂等、事务边界、审批状态机、审计留痕这些地方低代码平台改不动;知识问答部分用平台没问题,可执行业务闭环必须自己控代码。不贬低工具,讲边界。
故障故事一句话版(换成你真实的):⚠️ 推荐背「超时重试产生两笔操作」:下游超时自动重试,实际第一次已成功 → 幂等键当时是随机值 → 改业务语义键 + 写操作超时改先查询确认 + 本地幂等表唯一索引 → 沉淀「写操作有成功、失败、未知三种结果,未知必须单独处理」。
七、速记卡(面试前 10 分钟)
- 锚点:闸门。模型 propose,代码 execute;失败有分类去向;动作可倒查。
- 主 Agent 三件事:意图识别、任务拆解、条件路由;不持业务工具。
- 拆分三标准:工具集、数据权限、话术规则一致才合并。
- 错误四分类:可重试 / 可修正 / 业务终态 / 不可恢复;写操作超时=未知,先确认再动。
- 四层拦截:Schema / 来源白名单 / 业务不变量 / HITL。
- 幂等键:业务要素+审批单 ID,哈希,唯一索引,不含时间戳。
- HITL:interrupt+Checkpoint(PG)+审批单表;超时默认拒绝;对账防绕过。
- 记忆三层:Redis 短期 / 关键事实进 State / 摘要压闲聊。
- 指标三层:工具 / 编排 / 业务;固定用例集回归。
- 数字:94%(最终结果口径,读写分开)/ 86%(规则判定+抽检)/ 1,500 次/天 / 35%→18%(必配反向指标)。