首页 / 资讯中心 / 文章详情

客服Agent实战:多轮对话、工具调用与情绪控制的三线架构

客服Agent实战:多轮对话、工具调用与情绪控制的三线架构 ★ FEATURED ARTICLE
这两年做客服 Agent 项目的人越来越多但我发现很多团队把精力全砸在“多轮对话”这一个点上结果模型确实能聊却始终没法真正解决用户的问题。直到我在做一个某电商平台的客服 Agent 时把架构拆成三条主线——多轮对话、工具查询、情绪控制才第一次感觉到系统从“能聊”升级到了“能办事”。这三个能力拆开看都不算新鲜但把它们组合成一个完整链路并且真的扛住线上流量里面全是细节。这篇文章我会从需求拆解讲到模块落地再聊到评测和排障把我实际踩过的坑和验证过有效的方案都摊开讲。适合正准备做客服 Agent 的开发者、产品经理以及想把自己的大模型应用从 Demo 推到生产环境的人。1. 需求拆解客服 Agent 到底在解决什么问题很多团队做客服 Agent 的第一步就错了上来就微调模型、堆提示词却没有想清楚这个 Agent 的核心职责边界。我习惯先把用户诉求拆成三类问知识、办业务、求安抚。这三类分别对应工具查询、多轮对话和情绪控制但在真实会话里往往混合出现这就让问题变得复杂了。1.1 三类用户诉求的真实形态看几个我在实际项目中遇到的例子。第一类是知识查询型。“你们家退货政策是什么”“运费谁出”这种问题信息密度低答案相对固定本质是查文档。用检索加固化的方案就能解决难点在于文档版本更新后Agent 能不能及时跟上。第二类是业务办理型。“我想把上个月买的那双鞋退掉订单号是 123456。”“帮我查下快递到哪了。”这种问题必须调用订单系统、物流系统而且往往需要多轮交互才能拿到完整的查询参数。用户一开始可能只说“我要退货”你得先通过对话问出订单号、商品编号、退货原因才能发起后续流程。第三类是情绪宣泄型。“你们什么破服务等了半天没人理”这类消息不解决任何业务问题但如果处理不好前面的业务全白做。用户带着情绪的时候你跟他讲政策只会火上浇油必须先处理情绪再处理事情。难点在于这三种诉求不是独立的。用户可能一边生气一边问退货也可能在办理过程中情绪升级。所以客服 Agent 的架构必须是三个能力协同工作而不是三个独立模块各干各的。1.2 为什么是组合拳而不是单点能力只做多轮对话的系统容易变成“口才很好但什么也办不了”的客服。用户问一句“物流怎么还没到”它能聊十分钟物流知识却查不了用户的真实订单。只做工具查询的系统容易变成“效率很高但很冰冷”的机器。用户带着情绪来它直接甩一个退货链接流程没错但用户更生气了。只做情绪控制的系统那就更偏了。共情话术再好用户的问题没解决最后该投诉还是投诉。我设计整套系统时定了一个原则情绪控制是前提多轮对话是骨架工具查询是终点。所有对话的最终目的是把用户引导到问题被解决的状态而工具查询就是那个“解决”的动作。情绪控制负责不让链路中断多轮对话负责把信息补齐工具查询负责落地的执行。三个能力有一条明确的数据流向情绪识别结果会影响对话策略对话策略决定是否触发工具调用工具调用结果又反过来影响后续话术。1.3 明确边界哪些事 Agent 做不了这其实是很多人忽略却又最关键的一步。我在项目启动时就和业务方对清楚了边界——哪些必须转人工哪些绝对不能让 Agent 碰。涉及退款金额变更、账号安全风控、投诉升级这类高敏感操作Agent 只能收集信息最终确认必须人工完成。这不是技术做不到而是责任归属问题。技术上完全可以做到自动退款但这个授权谁都不敢给模型。另外Agent 对实时性极强或数据权限敏感的场景要主动让位。比如用户要求“立刻撤销刚才的投诉工单”这种操作不可逆、影响面大Agent 要做的是安抚并转人工而不是尝试自己去调工单系统的撤销接口。边界定清楚之后整个系统的设计压力小很多。因为你知道哪里是墙哪里是门。2. 多轮对话从“聊得起来”到“聊得明白”多轮对话是客服 Agent 的门面也是用户感知最强的部分。很多团队做到“能聊”就停了但生产环境要求的是“聊得明白”。这中间的差距集中在状态管理、上下文管理和指代消解三个点上。2.1 对话状态管理把用户意图拆成可执行的槽位客服场景里的多轮对话本质上是一个填表过程。用户说要退货这是一等意图要完成退货你需要知道订单号、商品、退货原因、退款方式。这些信息项在任务型对话里叫槽位把槽位填齐了工具才能执行。我的做法是给每个场景建一个槽位清单。以退货为例槽位是否必填默认值获取方式订单号是无用户提供或订单列表查询商品ID否无订单查询回填退货原因是无用户选择或自由输入退款方式否原路退回由账户信息决定状态管理的核心是State Machine状态机 Slot Filling槽位填充的组合。模型每一轮输出不只是生成一句话还要同时输出当前对话状态。我常用一个结构化的中间表示让模型在回复用户的同时把当前已填槽位、缺失槽位、下一步动作都暴露出来。{ intent: return_order, slots: { order_id: E20240115001, item_id: null, reason: null, refund_method: original }, missing_slots: [item_id, reason], next_action: ask_slot, ask_target: reason }这样做的最大好处是流程可控。模型偶尔会发挥不稳定但你可以用外部的状态机规则兜底。比如模型连续两轮输出不一致就强制回到缺失槽位的问题上。2.2 上下文管理别让模型“失忆”所有做过多轮对话的人都会遇到同一个问题聊到第五轮模型忘了用户第一轮说的订单号。这不是模型变笨了而是上下文窗口不够用或者早期信息被挤出了注意力范围。我的经验是三层上下文管理方案第一层保留关键槽位信息。把已确认的订单号、用户名、用户 ID 这类硬信息抽取出来放在一个固定的系统消息里每一轮都注入。这样就算历史对话被截断关键业务参数也不会丢。第二层历史消息摘要。超过一定长度的历史对话用模型压缩成一段摘要比如“用户确认了订单 E20240115001正在询问退货流程已经告知需要填写原因”。摘要保留意图线索但不会占用太多窗口。第三层原始消息裁剪。最近的 3-5 轮保留完整原文再往前的用摘要替代。这样兼顾了即时上下文和长期记忆。这套方案上线后对话到 10 轮以上的槽位准确率从 76% 提升到 92%效果非常显著。关键是你要理解模型处理的是 token不是记忆。它没有“记住”的能力你要主动帮它维护一个简化的记忆结构。2.3 指代消解用户说话天生省略“那个订单帮我取消了”“这个还能退货吗”——用户默认你知道他说的“那个”“这个”指什么。指代消解如果做不好多轮对话就是灾难现场。我在实践中发现客服域的指代消解跟通用对话不一样。通用场景要理解“它”指代猫还是狗客服场景里的“它”“这个”“那单”大概率指代最近一次提到的订单或商品。所以策略上不需要多复杂用一个两层方案就够第一层实体优先级映射。在对话状态里维护一个“最近提到的实体列表”按时间排序包含订单、商品、地址、优惠券等类型。模型处理完用户输入后先做一次实体链接把提到的代词映射到最近的候选实体上。第二层确认机制兜底。如果指代模糊且处理的是高影响操作如取消订单、修改地址就让 Agent 多问一句“您指的是订单 123456 还是订单 654321”。宁可多一轮对话也不要做错一步操作。这个设计源于一个惨痛教训某次演示时用户之前查过两个订单说“把这个退了吧”Agent 默认操作了最近的一个结果那是三天前已经发货的订单。从那以后所有高影响操作一律走确认。3. 工具查询让 Agent 真正“接到业务”多轮对话聊得再好最后还是要落到“帮用户把事办了”。工具查询模块就是 Agent 的手和脚价值直接体现在能不能把用户的意图转换成系统调用。3.1 函数调用让模型学会“伸手要数据”大语言模型本身不联网、不查库它能做的只是生成文本。工具查询的关键机制是Function Calling让模型在对话中识别出需要调用外部工具的意图并生成结构化的参数。我以电商系统的物流查询为例设计了一个工具声明{ type: function, function: { name: track_logistics, description: 根据订单号查询物流轨迹, parameters: { type: object, properties: { order_id: { type: string, description: 订单号 } }, required: [order_id] } } }当用户说“帮我看看我的货到哪了”模型会在回复中判断需要调用 track_logistics 工具并尝试从对话上下文提取 order_id。如果用户没提过订单号模型会把参数置空然后生成一句“请提供您的订单号”。这里面有两个细节容易被忽略第一个是工具描述要写清楚。description 里“根据订单号查询物流轨迹”这段文字直接影响模型判断何时调用这个工具。写得模糊模型可能该调时不调不该调时乱调。第二个是参数名称要跟业务侧对齐。我之前吃过亏工具参数叫orderNo对话状态里叫order_id模型一会儿输出这个一会儿输出那个导致解析层崩溃。后来统一用 snake_case并在描述里注明别名问题才解决。3.2 参数校验与缺失槽位追问Function Calling 输出的是结构化的 JSON但这不代表可以直接用。模型输出的参数经常有两个问题值不规范、字段缺失。值不规范常见于日期和金额。“上周五”这种相对时间模型可能输出“2025-01-17”但也可以输出“上周五”本身。金额可能带“元”“块”这类口语单位。我的做法是加一个参数清洗层用规则把口语单位规范化再交给下游系统。字段缺失的情况更常见。用户说“我要退单”但没有提供订单号。此时不能让工具硬调而是返回一个“缺参”信号由对话管理模块继续追问。整套流程应该是模型识别意图生成工具调用请求。参数校验层检查必填字段。缺参则进入追问子流程补全后重新调用。参数完整则真实调用业务接口。这一步很多人图省事跳过了直接把模型输出拼进接口请求。结果就是 API 一路报错用户反复收到“系统开小差了”的提示。其实补一个校验层大部分的健壮性问题都能在源头拦住。3.3 从工具查询到知识库检索的协同除了查订单、查物流这种结构化数据客服还有大量非结构化知识查询。比如“退货政策是什么”“怎么开发票”。这类需求适合走检索增强生成先把问题转成向量去知识库捞相关文档片段再让模型基于片段组织答案。我的做法是让工具查询模块同时暴露两类工具一类是查业务系统的接口另一类是查知识库的检索函数。模型根据用户的意图判断走哪条路。知识库这一侧有几个直接影响效果的参数参数推荐值说明分块大小300-500 字太小语义不完整太大检索噪音多检索条数3-5 条太多会引入无关内容干扰回答相似度阈值0.65-0.75低于阈值的宁可不返回避免幻觉top-p0.3-0.5生成时做一定的保守采样3.4 工具调用的失败处理线上环境里没有任何一个接口能保证 100% 可用。工具调用失败是常态关键是怎么处理。我定了三条规则一是工具调用超时默认走兜底话术。比如“抱歉物流信息暂时获取失败请您稍后再试或者联系人工客服”同时把这次失败的会话标记为待人工介入。二是连续失败两次以上强制转人工。不要让用户在一个死循环里转。这里“连续失败”的判断逻辑要放在 Agent 外部用规则做不要依赖模型自己判断。三是每个工具调用都要记录 trace_id。出问题溯源时会轻松很多。搜索词里的“客服 Agent”“多轮对话”“情绪控制”这几个词在后端日志里都要能做关联追踪否则整个链路调试就是黑盒。4. 情绪控制客服 Agent 的“软实力”情绪控制在很多技术团队眼里是“不务正业”但它恰恰是客服场景里决定生死的一环。用户情绪稳定时业务办理成功率能高出 30% 以上这是我在多轮实验里验证过的数字。情绪控制做得不好前面两个模块再优秀用户照样不满意。4.1 情绪识别不让用户的愤怒被忽略情绪识别不能靠模型“零样本”去猜要有一个明确的识别机制。我给 Agent 设置了情绪标签体系分为三级等级标签典型表达处理策略L1平静/中性正常提问正常对话L2不满/失望语气有火药味共情降低承诺L3愤怒/强烈不满投诉、威胁性言论安抚转人工准备情绪识别模块的输出不只用一个标签还要输出一个置信度分数。当置信度低但表达里出现了“投诉”“再也不买了”“曝光”这类高烈度词时模型可以强行提升情绪等级。这是规则和模型的风控协同能有效防止模型误判。4.2 共情话术模板与生成相结合情绪识别完成后最关键的动作是调整回复策略。我的经验是共情话术不能全靠模型现编要有模板兜底。L2 情绪下的共情模板我常用的是“理解 确认 替代方案”三段式。比如用户说“你们怎么回事我等了三天都没收到货”Agent 可以回“非常理解您的心情订单在运输途中出现了延误我这边帮您看到最新状态是正在派送中预计今天能送到。如果超时未到我们支持优先退款处理。”L3 情绪下的策略要更保守先道歉再重复用户的核心诉求然后给出人工客服通道。这里有个原则是绝不争辩。哪怕用户说的内容不符合事实Agent 也不能直接指出“您记错了”。正确的做法是“我理解您对这个情况很在意让我核实一下记录然后给您一个明确的答复。”4.3 情绪与任务的双轨控制情绪控制不能孤立运行它要影响任务链路。我设计了一条简单的规则链L1 情绪正常执行任务流程按槽位填充逻辑走。 L2 情绪任务照常执行但回复时先做共情铺垫延迟工具调用的触发避免“机器人冷冰冰地处理”。 L3 情绪暂停任务推进优先安抚并且触发转人工的候选方案。在转人工前Agent 会先说“我已经把您的情况同步给了人工专员您也可以选择在这里继续操作”。这条链路的实现本质上是在传统的“意图-槽位-动作”框架里加了一层情绪轨道。情绪轨道不替代任务轨道但在每个决策点都有优先级。这个设计在用户满意度评测中提升明显特别是“是否愿意再次使用自助服务”这项指标提升了约 20 个百分点。4.4 转人工最难的决策不是技术而是时机转人工的触发条件我总结成三个场景一是业务权限不足。用户要做高敏感操作Agent 没有授权。 二是情绪等级持续为 L3。连续三轮对话情绪标签都是 L3自动转人工。 三是会话超长。超过 15 轮还没解决问题大概率是信息反复拉锯转人工效率更高。转人工的时候要做一个动作把对话摘要、已填槽位、情绪等级一并提交给人工系统。人工接手的瞬间能看到“用户之前查过订单 123456情绪等级 L3原因是对物流延误不满”这样人工就不用从头问一遍体验会好很多。5. 落地实操从原型到可上线的系统前面讲的是模块设计这一节说落地时要做的具体决策和配置。包括技术栈选型、提示词工程和评测方法论。这些是在真实项目里反复迭代后沉淀下来的方案。5.1 技术栈选型与关键配置我当前项目使用的技术栈是全 Python 体系FastAPI 作为网关层内部用一个大语言模型处理对话和工具调度检索用向量数据库业务系统通过 REST API 对接。选型时核心考量是可控性。考虑到客服场景对回复格式和流程切换的稳定性要求极高优先使用支持结构化输出的模型方便解析函数调用结果。如果模型版本不支持函数调用退而求其次的做法是让模型输出固定的 JSON 文本再用正则或解析器提取但稳定性会差一些。几个关键参数的经验值供参考参数推荐值说明temperature0.3-0.5太低了回复呆板太高了容易跑偏top_p0.85-0.95配合 temperature 控制采样范围max_tokens500-800客服回复不需要太长够用就好上下文轮数5-8 轮超过这个基本靠摘要和信息抽取兜底这些参数别照着别人的配置抄要基于自己的测试集调。客服场景中temperature 高于 0.5 后我发现模型在工具选择上会变得不够果断有时候会答非所问。5.2 Prompt 设计最容易被低估的工程很多人觉得 Prompt 就是写几句话实际上客服 Agent 的 Prompt 设计直接影响工具调用是否准确、情绪处理是否得体、后续流程是否顺畅。我的系统里用了一套分层的 Prompt 结构第一层是系统级指令。定义 Agent 的角色、会话守则、权限边界。比如“你是某电商平台客服助手只负责处理订单、物流、售后相关问题不回答无关内容”“当用户情绪为 L3 时不得反驳用户必须优先安抚”。第二层是场景级指令。按目标场景分发退货流程、物流查询各自有独立的指令片段。这层指令在对话中途动态注入只在当前意图命中时激活。第三层是工具说明。Function Calling 的工具描述就是这层要写得让模型一看就懂何时调用。第四层是安全兜底。任何情况下如果无法判断用户意图回复“我帮您转接人工专员处理”。5.3 评测方法论别让模型自己给自己打分客服 Agent 的评测不能只看模型端到端的文本生成质量要从三个维度分开评任务成功率用户意图是否被正确识别工具参数是否齐全业务结果是否正确。这个可以量化比如订单查询的准确率、退货流程的完结率。对话自然度回复是否流畅、有没有答非所问、有没有重复问同一个槽位。这里要人工抽测每周抽 100 条会话记录评分。情绪安抚效果方向性指标可以统计“出现愤怒情绪的会话中最终转为 L1 的比例”或者转人工后的用户满意度回访数据。单测集要区分普通问题和边缘问题。边缘问题包括上下文指代模糊、用户情绪激烈且业务复杂、工具调用失败后的追问、用户中途换话题。这几类测试集分开打分才能看到系统的真实短板。6. 常见问题与排查心得做客服 Agent 的线上一段时间后遇到的典型问题其实很集中。我把这些问题和排查思路列成一个速查表希望对后来的人有用。6.1 多轮对话“偏题漂移”症状聊到 10 轮以上模型开始重复问已经确认过的信息或者回复内容跟当前话题偏离。排查步骤先看上下文管理是否生效。确认关键槽位信息有没有被写入到系统级上下文里。再看历史消息摘要是否更新及时。摘要生成失败或者截断会导致早期信息丢失。最后检查模型的 max_tokens 设置。如果输出长度被压缩可能让模型跳过必要的确认。我遇到过最隐蔽的一个问题摘要生成用的模型 temperature 太高导致摘要内容张冠李戴把 A 订单的号写到了 B 订单的摘要里。之后所有涉及订单的操作全部错乱。后来我单独把摘要模型的 temperature 调成 0并加了字段校验才根治。6.2 工具调用误触发症状用户只是问了一句“你们能开发票吗”Agent 直接调用了开票接口。排查方向工具 description 写得过于宽泛。比如“根据用户需求处理发票相关操作”模型就会把咨询也当成执行。缺少二次确认机制。高影响操作必须加确认上面说过的“退款/取消订单”是要特别注意的。上下文里出现了相近实体。用户之前提过订单当前问题又是咨询性质模型容易误以为要继续处理那个订单。这类问题靠调整 Prompt 见效最直接工具描述改得越具体误触发概率越低。没必要重新训练模型。6.3 情绪识别误判症状用户正常吐槽一句“这功能做得太差了”Agent 直接进入 L3 流程开始道歉并转人工。排查方向情绪识别规则中“投诉”“太差”这类词触发的权重是否过高需要结合上下文判断。识别模块输入的是否是原始用户消息还是带上了模型的回复。如果带上模型回复模型语气可能会干扰判定。置信度阈值设置过低时中性表达容易被标记为情绪表达阈值上调就能解决。在客服场景里情绪误判的代价不完全一样。把 L1 误判成 L3用户会觉得机器人小题大做把 L3 误判成 L1用户会觉得被无视。如果取舍我倾向于“宁高勿低”尤其在前三轮对话中多些安抚动作通常没有坏处。6.4 工具查询结果与用户预期不匹配症状用户问“我买了两件衣服为什么只退了一件”Agent 查到的数据只涵盖了一个订单原因是用户两个商品在两个订单下。排查方向确认工具设计是否覆盖了“订单 商品”的多层关系。查询粒度要能支撑“一笔订单对应多个商品”的数据模型。用户描述与实际订单不匹配时应由 Agent 反问确认而不是硬套查询结果。日志中要记录原始查询参数和系统返回结果的映射方便快速定位是参数错误还是数据错误。这类问题暴露的往往是需求分析阶段没摸清业务数据模型补一个更完整的工具接口就能覆盖。6.5 定时任务与消息推送的边界问题客服 Agent 不只是“用户问一句、Agent 回一句”有的场景需要主动推进。比如物流异常时主动通知用户、退货流程中断时提醒补全信息。这块我踩过坑做得太主动会打扰用户做得太被动用户又觉得服务没温度。我的经验是用“用户可见的进度状态”来驱动推送。比如退货流程创建成功后显示“等待商家审核”状态变化时再触发一次通知。推送内容里标明操作入口用户点进去直接进到对应会话保留上下文这样无头会话比“从零开始问”的效果好很多。写在最后的一些体会做客服 Agent 的最大收获是意识到技术难度不在某个单点的模型能力而在于把多轮对话、工具查询、情绪控制这三条线编成一张网让它们互相配合而不是互相打架。我在项目中后期每次改动都要先过一遍三个模块的联动测试避免出现“情绪控制更好了但工具查询变慢了”这种按下葫芦浮起瓢的情况。如果你正准备做自己的客服 Agent我有几条建议先花两周时间把业务边界和槽位模型理清楚这是后面所有工作的地基工具查询一开始就按“带参数校验 失败兜底 日志追踪”的标准来写别等上线了再补情绪控制模块哪怕先用最简单的手写规则做着也比完全没有强它能帮你在早期发现大量体验问题。这套东西我已经在线上跑了大半年验证过稳定性和效果。你照着做至少能少走几个月的弯路。
阅读完成 · 觉得有帮助?
咨询建站