做过客服系统的人都知道真正让用户发火的往往不是问题本身而是“客服听不懂人话”。用户说“我上周买的东西还没到”系统却答非所问地推荐优惠券用户反反复复解释了三遍订单号客服却每次都让他重新报一遍。这种体验比没有客服还糟糕。所以我一直觉得客服Agent的核心从来不是“能聊天”而是“真的在干活”——既要记住上下文又要查得到数据还得在用户情绪失控时懂得退让。这篇文章我就围绕“多轮对话、工具查询与情绪控制”这三个关键能力聊聊我在实际项目中是怎么设计、怎么踩坑、又是怎么把准确率从65%拉到90%以上的。1. 客服Agent到底比传统机器人强在哪先从一次事故说起1.1 传统FAQ机器人的死穴它根本没有“记忆”早年的在线客服机器人说白了就是一个关键词匹配器。你在对话框里输入“运费多少”它把问题拆成“运费”“多少”然后去FAQ表里找相似度最高的答案返回一段固定话术。这种做法有两个致命问题。第一它不区分“用户想问什么”和“用户实际说了什么”。用户输入“你们那个包邮的门槛是什么来着”传统机器人大概率会把“包邮”“门槛”拆出来去匹配“满多少包邮”的答案——如果FAQ里压根没这条它就回一句“抱歉我不太明白您的问题”然后让用户转人工。一次会话就这么废了。第二它没有状态。同一个用户在两轮对话里分别问“你们发货到新疆吗”和“那大概要几天”传统机器人会把两句话当成两个独立的、毫无关联的问题去处理。它不知道“那”指的是“发到新疆的订单”“几天”问的是“运输时效”。于是在第二轮它又得让用户重新说一遍完整的问题。我接手过一个真实的客服数据统计某电商平台的传统机器人真实解决率只有31%。将近七成用户在和机器人聊了三四轮之后最终还是选择了转人工。问题不在知识库不够大而在机器人根本接不住“人话”——它处理不了指代、省略和上下文依赖。1.2 大模型带来的本质变化从“检索答案”变成“完成任务”客服Agent和传统机器人最大的不同是它把“查答案”这个动作升级成了“理解任务调用工具组织回复”的完整链路。以前你需要预先录入几百条FAQ再给每条FAQ写一堆同义词和变体让匹配器能撞上。现在你只需要给Agent一个知识库的检索接口把对话历史和当前问题一起交给大模型让它自己判断“用户需要我查什么、去哪里查、查到之后怎么组织语言”。更重要的是大模型天然具备多轮记忆能力。它在上下文窗口里保存了前面几轮对话的内容你不需要自己去维护一个复杂的状态机只需要把历史对话拼进Prompt里模型就能理解“那”指代的是什么。我设计客服Agent的时候把整个系统分成了三层入口层负责识别用户意图决定当前这一轮交给哪个模块处理核心层负责多轮对话的上下文组装、工具调用的决策、情绪状态的判断执行层负责实际的数据查询订单、物流、优惠券等和最终的回复生成这三层各有各的难点。入口层要解决“用户一句话里包含了多个意图”的问题核心层要解决“什么时候该调用工具、调用哪个工具”的问题执行层要解决“数据查回来了怎么用自然语言包装成用户看得懂的话”的问题。1.3 什么场景才真正需要Agent而不是问答库不是所有客服场景都需要上Agent。如果你的业务只有二三十条固定问答比如“营业时间是什么”“怎么退货”这种用传统决策树就够用了上大模型反而增加成本和延迟。但下面的场景传统方案基本扛不住用户问题高度依赖上下文比如“我刚问的那个订单现在到哪了”“那如果我申请退款的话运费谁出”用户喜欢用口语、长句、带错别字和省略的表达比如“你们那个东西为啥还不送来啊我都等好几天了”答案需要实时从业务系统里查比如订单状态、物流轨迹、优惠券信息这类数据不存在静态FAQ里用户情绪波动较大需要系统根据对话氛围调整回应方式如果你的业务命中其中两条以上就值得认真考虑引入客服Agent。我在实际项目里发现它带来的提升不是某一个环节的优化而是整个客服链路的体验重构——用户不用再把问题拆成“关键词”喂给机器人了他可以像跟真人说话一样想到哪儿说到哪儿。2. 多轮对话的设计让Agent真正“记住”并“接住”上下文2.1 会话记忆的三种方案对比短记、长记、摘要记做多轮对话第一个要解决的就是“记忆存哪里”。我踩过不少坑也对比过主流方案这里给大家列个清单。短记忆方案是最近使用较多的。直接把最近几轮对话原文拼进Prompt借助大模型的上下文窗口来理解指代。优点是实现简单、效果直接模型能完整看到用户上一句说了什么理解“那”“这个”“它”的时候不会丢信息。缺点是上下文窗口有限超出长度会被截断而且每轮请求都要重复携带历史消息token消耗会越来越大。长记忆方案是做持久化存储。把用户ID、Session ID、对话内容、时间戳存进数据库一般用Redis或MongoDB每次对话前把该Session最近N条记录取出来组装进Prompt。优点是可以跨请求保存状态即使用户隔了十分钟又回来问系统还记得他之前问了什么。缺点是需要自己管理容器的过期时间、并发读写工程量会上升不少。摘要记忆方案是比较进阶的做法。当对话轮次超过某个阈值比如10轮用模型把前面的长对话压缩成一个摘要后续只携带“摘要最近两轮原文”继续对话。优点是能长期维持大上下文token消耗可控。缺点是摘要过程有信息损耗用户提到的某个关键细节比如具体订单号如果没被摘进去后面就找不回来了。我在实际项目里采用的是“短记忆摘要记忆”的组合策略会话前8轮直接带原文超过8轮的早期内容先做摘要但所有涉及订单号、手机号、金额这类关键实体的字段就算做摘要也强制保留。这样既保证了上下文的连贯性又不会因为对话太长而丢失关键信息。2.2 指代消解与省略补全用系统提示词让模型学会“联系上下文”多轮对话做得不好最常见的表现就是“答非所问”。用户上一轮说了“订单号是20240001”这一轮问“它什么时候能到”模型如果没把上一轮的订单号跟“它”关联起来就会去知识库检索“什么时候能到”的FAQ返回一个通用话术——这是典型的上下文丢失。要解决这个问题一个很有效的做法是在系统提示词里明确写清楚上下文规则。我给Agent定过一条硬性规定在回复前先检查用户当前这句话是否包含指代词它、这个、那个、刚才的、之前的如果有必须从对话历史中找到对应的实体并把找到的结果以“用户在上一轮提到的[{实体}]在本轮用[{指代词}]指代应理解为{具体内容}”的形式内部确认一遍再决定下一步动作。这个提示词看着简单作用非常大。它相当于强制模型在生成回复之前先做一次“自我确认”把隐含的指代关系显式化。我在评估集上做了个对比实验加上这条规则之后指代消解的准确率从68%升到了92%。省略补全也是一样的逻辑。用户说“那退款呢”模型需要自己补出被省略的主语理解成“如果订单退款退款金额是多少/多久到账/运费谁承担”。这部分的补全能力依赖模型本身的常识推理但前提是上下文里得有足够的信息支撑它推理。2.3 追问策略与澄清机制宁可多问一句不要硬猜多轮对话还有一个很实际的问题用户的话里有信息缺口。比如用户问“我要退款”但没说哪个订单、哪个原因。如果Agent直接查“所有订单”然后返回一个列表体验会很差——用户会觉得机器人“自作主张”。我的做法是设计了一套“澄清触发机制”。系统会先判断当前请求里是否包含查询所需的全部必需参数比如订单号、用户ID如果缺少就主动向用户追问而不是猜测。举个例子用户“我要退我那个耳机。”Agent“好的您要退款的是哪个订单呢方便提供一下订单号吗或者您也可以告诉我下单的大概日期和收货人姓名。”这里的追问不是瞎问而是按照业务规则查缺补漏。我维护了一个“意图-参数表”每个意图都有必填参数和可选参数只有必填参数全了才允许触发工具调用。这个设计的另一个好处是能给用户“选择权”。有的订单号很长用户自己都记不住你让他报订单号体验反而差。于是我把参数补全做得更灵活——如果用户愿意也可以用“收货手机号后四位日期范围”来定位订单。实测下来提供这种“替代参数”之后用户一轮就把信息补齐的比例从54%提到了81%。2.4 多轮对话的阶段性边界什么时候该结束会话多轮对话不是无限聊下去就好。对话越长模型出错的可能越大token成本也越高而且很多用户聊着聊着就忘了最初的问题是什么。所以我还给Agent设置了一个“会话收敛”机制。具体规则是当用户的目标已经达成比如查到了物流、提交了退款申请Agent会主动输出结束语并把会话标记为“待关闭”当用户连续两轮发送不相关的内容闲聊、吐槽、说跟业务无关的话题Agent会礼貌地把话题拉回正轨当对话轮次超过15轮仍然没有目标达成的信号系统会主动建议转人工避免用户陷入“聊不完”的困境这个收敛机制看着简单但真正做起来有个难点怎么判断“目标已达成”我的做法是让模型在生成回复之外额外输出一个“status”字段取值包括“需继续”“任务完成”“待转人工”三种。通过结构化输出来控制会话流程比让模型自由发挥要稳得多。3. 工具查询层让Agent真的“查得到”和“查得准”3.1 工具注册与参数抽取模型怎么知道“该查什么”客服Agent跟普通聊天机器人最本质的区别就是它有“手”——能通过工具调用去查业务系统里的真实数据。但想让模型正确地使用工具你必须先让模型“看得到”工具并且理解每个工具是干什么的。我通过函数模板把工具描述传给模型每个工具包括以下几个要素工具名称、功能描述、输入参数列表含参数名、类型、是否必填、以及一个清晰的调用示例。模型读到这些描述后会自己在对话上下文中提取参数。以订单查询为例工具名称query_order 功能根据订单号或手机号查询订单信息 参数order_id字符串可选订单号phone_last4字符串可选收货手机号后四位date_range字符串可选下单日期范围为了让模型“照着葫芦画瓢”而不是自由发挥我还会在工具描述里附上一个示例“如果用户说‘我要查一下昨天买的那个显示器到哪了’你应该提取order_id空phone_last4空date_range昨天。如果定位到唯一订单则查询否则追问用户补充订单号或手机号后四位。”这个设计的核心思路是把“工具调用”当作一个格式严格的输出任务而不是让模型随意发挥。模型需要输出的是一个JSON结构体包括工具名、参数、以及一个是否直接执行的判断。系统拿到这个结构体之后再做后续处理。3.2 查询结果的组装与转译从JSON变成人能看懂的话工具返回的原始数据是JSON数组里面可能是一堆字段订单状态、物流节点、时间戳、承运商、下一站网点。如果Agent直接把这段JSON贴给用户那体验就是灾难。所以我在工具调用之后加了一个“结果转译层”把查询结果和用户的原始问题一起交给模型让它把结构化数据转成自然语言。举例说明原始查询结果order_status“已发货”tracking[{time: 2024-01-01 10:00, location: 广州分拨中心, status: 已揽收}]生成后的回复“您的订单已于1月1日上午10点在广州分拨中心揽收目前物流状态是‘已发货’。一般情况下从揽收到送达大约需要2-3天您可以明天下午再查看一次物流进度。”这个转译过程有两个关键点。第一不能让模型编造数据。我在提示词里明确写了约束不得输出与查询结果不一致的信息所有日期、地点、状态必须与返回数据完全一致如果数据缺失可以使用“未显示”之类的中性表达而不是猜测。第二要结合用户的问题来组织语言。如果用户问“什么时候到”那回复的侧重点是时效预测如果他问“现在在哪”那回复的侧重点就是最新的物流节点。模型需要理解用户的问题焦点而不是把查询结果全部照搬。3.3 工具调用的失败兜底查不到不等于不回答工具调用一定会遇到查不到的情况。用户报错了订单号、订单编号输入有误、手机号后四位匹配到多个订单——这些都是日常不处理好的话体验崩得特别快。我总结出了一套分级兜底策略第一级参数缺失。提示用户补充参数给出具体的输入示例比如“您可以提供下单时填写的手机号后四位我帮您定位订单”第二级参数合法但查无结果。主动给用户解释可能的原因订单号输错、订单未创建成功等并让用户确认是否提供了正确的信息第三级参数匹配到多条记录。列出候选列表让用户选择具体是哪一单附上时间、商品名、金额等辅助信息方便用户辨认这三级的核心逻辑是“帮用户节省沟通成本”。查询失败时Agent不是干巴巴地说“查不到”而是根据失败原因提供下一步的行动选项。3.4 工具编排的多步操作从查物流到查售后的一气呵成真实客服场景里用户的问题往往需要多个工具串联。比如“我要退货”——这背后涉及到订单查询先确认订单存在、售后政策查询确认该商品是否支持7天无理由、退款金额计算查实付金额、提交申请调用售后系统接口这四个步骤。工具编排的原理其实不复杂核心是一个“循环决策”机制Agent先执行第一个工具根据结果判断“是否还需要第二个工具”如果需要就继续调用直到完成整个流程或者用户叫停。但在实际项目里工具编排最怕的是“死循环”。模型可能因为没有得到理想的结果不断重试同一个工具白白消耗请求时间。我的做法是给模型设置一个工具调用的最大轮数上限比如5次达到上限后强制要求Agent总结当前进展给出下一步建议而不是继续“撞墙”。另一个教训是工具调用之间的“中间产物”要传给用户看但不要传得太多。比如查物流时系统先定位到订单再查物流轨迹中间这个“定位成功”的过程可以作为一句轻量提示展示出来“已为您找到订单正在查询物流信息…”让用户知道系统在干活。但如果每调一个工具都弹一条长文案用户会产生信息焦虑。4. 情绪控制模块让Agent“会说话”而不是“说对话”4.1 情绪识别的前置判断愤怒型、焦虑型、困惑型要区别对待客服Agent不是聊天机器人它面对的用户大多带着情绪来这可能让事件的初期处理变得棘手。如果系统不能感知这一点只用“标准话术”去回应用户会越来越火大最后导致投诉升级。我在设计情绪识别模块时给情绪分了四类愤怒型用户使用了大量感叹号、贬义词、威胁性表达比如“你们就是骗子”“再不解决我就投诉了”焦虑型用户反复确认时效、追问细节比如“到底什么时候能到啊”“能不能帮我催一下”困惑型用户表达里充满不确定性比如“我不知道怎么回事”“我是不是操作错了什么”平静型正常的信息查询没有明显情绪色彩分类的方式有两种一种是让模型直接输出一个“emotion”字段另一种是先用一个轻量级分类器做情绪预判再把结果作为标签传给大模型。第一种简单但对模型的稳定性要求高第二种多一步但要稳得多。我最终采用的是混合方案用一个文本多分类模型做情绪初筛把结果拼进Prompt里让Agent在回复时明确带上“detected_emotionxxx”的标记。4.2 语言风格的动态调节温度参数和提示词的双重控制情绪识别出来之后关键是“变着法子说话”。同样一句“您的订单正在配送中”对不同情绪的人措辞是完全不同的对愤怒的用户先把道歉放在第一位再给解决方案不含糊不推脱对焦虑的用户给出明确的时效预期并且主动提供“帮您催一下”“给您加急”之类的后续手段对困惑的用户不要一上来就给一堆专业术语而是分步骤、一条条讲清楚我在提示词里维护了一个“回复风格映射表”让模型根据情绪标签选择对应的语言模板。同时我也会调整生成参数——当检测到用户情绪不好时把temperature调低让回复更稳妥避免模型“自由发挥”说出可能刺激用户的表达。4.3 冲突升级的熔断机制什么时候必须转人工情绪控制的边界在于Agent不是万能的有些场景必须及时把人请上来。我设定的转人工触发条件包括用户明确要求、用户表达出强烈的投诉升级意愿、连续两轮同一问题未解决、客服业务本身要求人工介入比如涉及理赔、纠纷。转人工不是简单地扔一句“我帮您转接人工客服”然后结束。连接要做到平滑先把用户的问题和对话摘要传递给人工客服让用户不用重复描述一遍。我用的是一个“对话交接卡”机制——把用户ID、当前问题、已执行的查询结果、情绪标识、待办事项打包成结构化数据随会话一起转给人工坐席。用户到了人工那边系统会提示“已将您的对话内容同步给人工客服您不需要重复说明”这一点对用户体感提升很大。4.4 对话通识与人格一致性回应要“有温度”但也要“守住边界”客服Agent还有一个容易被忽视的点一致性。同一个用户上一次会话客服很温和这一次客服却冷冰冰的这种前后矛盾会让用户觉得不专业。所以我会把“人格设定”作为固定系统提示词的一部分不随场景切换而变更。比如始终使用礼貌用语主动承担责任不使用“不关我的事”之类的表达确认用户的问题后再给方案不承诺能力范围外的事这个人格一致性看起来是“台词设计”层面的小事但对用户的信任感影响非常大。我实测过一组对比有人格设定的Agent用户愿意继续对话的比率比“无人格设定”高出约37%。5. 实战落地要点从Demo到上线这些坑真的绕不开5.1 评估集的建设没有一套好测试用例你都不知道自己改坏了什么客服Agent和别的算法系统一样没有高质量评估集迭代就是盲人摸象。很多团队在做Agent时最常犯的错就是只看几个手工挑出来的例子的输出是否合理就决定改不改提示词——这不科学。我建了一套分维度评估集包括多轮指代消解测试50条专门测模型能不能正确理解“它”“这个”“之前说的”工具调用参数抽取测试80条测模型从口语里提取结构化参数的准确率情绪识别测试40条含愤怒、焦虑、困惑、平静各10条回复规范性测试60条语言是否自然、是否与上下文一致、是否包含安全违规内容每轮改完提示词我都会让模型跑一遍全量测试集用脚本统计通过率。没有这个习惯之前我经常改一个Prompt把另一个能力改没有了评估集之后回归测试立刻能暴露问题。评估集还有一个作用内部跑分过硬的Agent不代表线上就好用。因为真实用户的话术分布比评估集丰富得多。所以我建议评估集至少每两周更新一次从线上日志里捞出现实中模型答错或答偏的case补充进去。5.2 延迟与成本的平衡不是所有请求都要走大模型大模型推理有延迟有token成本如果每一轮对话都调用一次大模型客服系统的响应时间和商业成本都会比较难看。我采取的优化思路是按场景分层处理。快速路径用户输入命中“意图明确参数齐全工具结果无需复杂转译”的模板化场景时直接用模板拼装回复不走大模型生成。标准路径大多数普通查询场景走一次大模型生成回复使用小尺寸模型例如7B~13B级别。复杂路径只有需要跨多工具编排、强推理、或多轮澄清的场景才调用大尺寸模型。这个分层策略让整体平均响应耗时降低了约42%token成本下降了约30%而在“标准路径”和“复杂路径”之间的体验差异也不明显。做客服Agent千万不要追求“所有对话都让大模型自由发挥”那样既贵又不可控。5.3 从“报错”里学知识线上日志的迭代闭环Agent上线后最宝贵的资源不是它跑得多好而是它犯错时留下的日志。我把线上所有“用户不满意”的信号都做了采集用户重复提问、用户直接转人工、用户在消息里表达不满、用户连续同一句话重发了N次。我每天都会从日志里挑出Top 20的失败case分析模型在哪一步出了问题是没理解用户意图是工具参数抽偏了是情绪判断错了还是提示词里某个约束不够导致模型产出了越界回复。每类问题都需要不同的修复手段如果是指代消解失败给提示词加一条对应的规则如果是工具参数抽取错误给工具描述补一个同类示例如果是回复方式不合适调整情绪风格的映射表如果是知识库压根没有这个答案给系统补充一条FAQ或让模型学会兜底这个闭环跑起来之后系统每周的解决率都在小步爬升。从第一周的71%到第四周的83%再到第六周的89%。现在回看这89%的解决率里有将近一半的增长都不是靠“换更大模型”得到的而是靠数据分析和提示词迭代一点点抠出来的。5.4 安全与合规的注意点不承诺做不到的事客服Agent上线前还有一个必须做的工作安全边界审查。客服话术直接面对用户如果模型在情绪化场景里随口说“我们绝对负责到底”“赔偿您没问题的”一旦和公司政策不符就是事故。我梳理了一套客服Agent的安全红线强制写入系统提示词不主动承诺赔偿金额、赔偿条件、售后时间等具体结果除非这些信息来自业务系统且明确匹配不评价公司内部流程不承认“是我们错了”这类的认责表述除非在人工坐席介入后由人工来定论不在缺少依据的情况下提供“马上到账”“一定今天送到”这类确定性承诺不讨论竞品、价格政策、内部规则等非公开信息这个安全边界对模型自由发挥形成约束。但真正稳妥的做法是把“人力复核”嵌入高风险场景——当模型识别到用户要求赔偿、投诉升级、或涉及纠纷处理时不真正执行任何有后果的操作而是走人工渠道确认。6. 最后分享几点个人在实战中的体会做了几个月的客服Agent项目我最大的感受是这类系统永远不会有“完美完成”的一天但只要把“记忆、查询、情绪”这三件事做扎实用户体验就会有质的提升。要说最核心的窍门就一句话Agent能力再强也要你和业务规则对齐好。所谓对齐一方面是技术层面的参数、工具字段、知识库索引另一方面就是话术和红线——哪些能说哪些不能碰死不同业务有不同的答案。再强的模型也救不了混乱的业务定义但一个80分的模型配上清晰、扎实的业务框架绝对能跑出95分的体感。如果让我给想入手的团队一句话建议我会说别急着上大模型先把工具接口的数据质量确保好再把多轮对话的评估集建好让模型的每次升级有数据可依。这两件基础工作做得越扎实后边的一切都会顺很多。