让AI评测AI:构建智能客服的自动化运营Agent体系
AI正在重塑客服行业,从规则驱动迈向智能对话时代,探索如何构建自动化运营Agent体系提升服务体验。
大模型和算力的快速发展,正在推动不少行业发生实质性变革。虽然当前AI整体还处于“辅助人”的初级阶段,但它的演进路径和潜力已经相当清晰。客服领域作为最早拥抱“智能能力”的赛道之一,随着LLM的发展,也焕发出了新的生命力。
先来回顾一下智能客服的演进历程。
一、基于NLP的传统机器人客服
上一代“机器人客服”以NLP、规则引擎和知识库为核心,相较于传统人工客服确实是一次飞跃。但其短板也相当突出:意图理解能力偏弱(多意图处理几乎只能靠定向训练)、维护成本居高不下(冷启动和知识维护都很费劲)、对话能力几乎为零(泛化能力差、回答生硬、指代消解基本不存在)。这一阶段的客服运营(这里特指机器人客服运营,不包括排班、培训、质检、考核等人工客服运营),工作重点主要集中在以下几个方面:
- :将常见客户问题整理成“问题-答案”对;
知识库建设(FAQ喂养)
- :为每个问题配置大量关键词和同义句。比如“如何退款”要配上“想退货”、“钱怎么退”、“不要了”等等;
同义词和规则配置
- :设计复杂的树状对话流程(SOP、决策树等),比如“用户选择A → 跳转到流程A1 → 询问信息A2...”这样的链路;
对话流程设计
- :监控关键词触发和未被识别的问题,然后不断打补丁、加规则。
监控与维护
现实很残酷:语言是无限的,规则却是有限的。客服运营团队永远在追赶用户层出不穷的新问法,陷入一种“猫鼠游戏”,疲于奔命。更要命的是,无论怎么优化,机器人智能水平的上限在设计之初就被规则库的规模锁死了,规则之外的问题根本处理不了。
二、基于RAG的智能客服
大模型的快速发展,重新定义了“机器人客服”,让它向“智能客服”迈进了一大步。LLM在客服领域的应用,最初是从RAG(这个名词现在确实被说烂了,但还得提)切入的,目标是提升文档问答的准确率、降低知识运营成本。
RAG为什么有效?它不是单纯的
也不是单纯的
而是从“知识库”中找出最相关的内容,把“检索到的信息”和“用户问题”打包成一个超级提示词,让LLM扮演“专家助理”而非“专家本人”。这样既有准确的知识作为供给,又能通过LLM的润色让表达更自然。
- :作为RAG质量的生命线,向量化检索的引入弥补了传统关键词和搜索引擎检索(ES方式)的不足,能有效提升召回率。
检索(Retrieval)方面
- ES方式:
- 向量化方式:
- RAG中经常把两者融合处理:
- :把检索到的信息片段和用户问题精心组装成一个LLM能理解的提示词,为生成环节打好基础。这包含两方面:
增强(Augmentation)方面
- :在工程侧,把检索到的候选知识分片按相关性排序,结合历史对话内容拼接成完整的“上下文背景信息”;
信息组装
- :这是“增强”环节的灵魂,通常包含以下部分:
提示词工程
- :定义LLM的身份。比如“你是一个专业的客服助手,严格根据提供的背景信息回答问题”;
系统角色
- :明确告知LLM答案来源和规则。比如“请严格根据以下用```标记的背景信息回答最终问题。如果背景信息中没有答案,请直接说‘根据现有信息,我无法回答这个问题’,不要编造信息”;
背景信息/指令
- :前面提到的上下文;
背景信息内容
- :原始的用户问题;
用户问题
- :要求LLM以特定格式(如Markdown、带项目符号的列表)输出,或要求引用来源。
输出格式要求(可选)
- :将组装好的提示词发给大语言模型。LLM会基于强大的语言理解和生成能力,执行以下核心操作:
生成(Generation)方面
- :识别自己的角色和回答规则;
理解指令
- :在提供的背景信息中定位与问题直接相关的部分;
关联信息
- :对找到的信息进行归纳、总结和重新组织,用更自然流畅的语言表达出来,而不是简单复制粘贴。
总结和生成
- 首先,明确评测能力的目标:识别AI原生客服机器人回答的准确性,对BadCase进行根因归类,自动生成优化建议,并具备优化建议自动执行的能力。
- 为了实现这个目标,需要对完整对话链路进行拆解,按功能模块粒度落数关键信息(DB或日志)。这样就能根据服务记录ID,把从接收到Query到产出Answer的关键链路串联起来。
- 其次,定义效果评测的主框架脉络:
- :为了适配不同评测场景,我们既提供了根据知识内容自动生成评测集的能力,也提供了文件方式上传原声评测集的能力。对于已经使用AI原生机器人客服的场景,还支持动态根据多种组合条件,从生产环境直接筛选服务记录作为评测集。
评测集的构建
- 核心思路是:先根据评判规则判断机器人回答内容是否符合期望(即命中规则),不符合期望的标记为BadCase。有了BadCase就缩小了目标范围,为后续根因归类和优化建议生成提供了可能。规则的定义至关重要,直接影响BadCase的产出。我们从语义相关性、表达质量、内容合规性、信息完整性等多个维度评估,每个大维度下又包含更细致的子维度。
端到端
- 会直指BadCase的核心。根据拆解的对话链路关键环节,从知识角度、对话中控决策角度、大模型推理生成角度,定义了十几种
根因归类
,包括粗召检测问题、精排问题、生成错误问题、生成幻觉问题等。根因类别定义得越细致,越能精准找到问题和解决问题。根因类别
- BadCase的根因被识别出来后,部分类别可以并自动执行。比如缺少知识的根因类别,可以结合对话上下文自动触发从互联网检索关联知识;粗召遗漏或精排遗漏的场景,可以对识别出的关联分片信息增加相似问,增加被召回的概率。实际使用下来,自动生成相似问的场景更容易落地。
自动生成优化建议
- 基于AI原生的对话链路,为了保证性能和体验,使用的LLM参数尺寸都不是特别大。而我们建设的评测能力也是基于AI原生,并且能对同样基于AI原生的对话链路起到“裁判”评测的效果(准确率85%+)。这得益于两个关键点:很多环节使用了的LLM,并针对性开启了思考模式,让LLM的推理和判断能力有更大发挥空间;同时,作为输入给到LLM的关联内容(对话上下文、参考知识、业务规则等)也
更大尺寸
,让LLM的思考基础更充分。更加全面
- 最后,搭建平台的思路和理论并不困难,尤其是基于AI原生的场景。但如果要达成目标,还是不断发现问题、思考问题、解决问题,才能提升评测的最终效果。
得在实践中
引入RAG之后,机器人客服的主链路如下:
RAG的能力让机器人客服的知识来源从之前单一的FAQ维度跃迁到了整篇文档维度(doc、pdf、ppt、表格等),对机器人知识问答场景的影响非常大。
虽然当时的LLM还没有现在这么强悍,支持的上下文Token量级也很有限,不少工作(意图理解、多轮支持、RAG结果精排等)还得靠工程侧和小模型协作。但即便如此,客服运营的工作内容已经发生了很大变化:冷启动和知识维护的成本降低了不少——毕竟上传知识文档比配置一串FAQ要方便得多。客服运营可以把精力放到业务SOP流程的构建和知识文档的保鲜上。
三、基于AI原生的智能客服
LLM经历了2022年底的闪耀登场、2023年的百模大战、2024年的AI应用涌现,终于迎来了2025年智能体的蓬勃发展。随着基模能力越来越强,我们可以把更复杂的逻辑交给LLM理解,甚至可以借助MCP让LLM直接调用外部工具,通过Function-Call能力动态利用本地服务数据。这让“传统研发”的工程同学可以直接通过对基模的调用(比如基于百炼)手搓完整的机器人客服链路,基于AI原生的智能客服得以落地。
基于AI原生的智能客服主链路:
链路中用到模型的地方都切换成了LLM,根据不同场景选用不同尺寸的LLM。比如改写会用参数量小一点的模型(7b),而规划和决策会使用参数量大一些的模型(max、32b)。因为是对话场景,对耗时比较敏感,需要权衡LLM的选型和响应时间——通常模型参数越大效果越好,但响应时间也会变长。
基模的强悍之处在于,我们可以把更多内容交给LLM去推理判断。比如把复杂的业务逻辑通过自然语言描述成“如果xxx,那么xxx”这种格式,结合上下文信息让LLM决策走什么样的逻辑分支,这就是所谓的“智能SOP”。智能SOP(当然还有很大的优化空间)中如果需要动态调用LLM以外的内容,可以通过Function-Call实现。
对于知识类问答,RAG仍然必不可少,而且也在不断进化:
四、对话效果如何评测
基于AI原生搭建的对话链路,做个Demo没问题,但要商业化交付,就得关注实际效果。这正是本文要讨论的重点:如何观测效果?
虽然整个链路很多环节都用到了LLM,但我们关注的是端到端的机器人回答效果,单纯评测LLM本身不是目标。
传统做法是运营人员通过指定评测集,或者从生产环境抽取服务记录,线下人工标注看效果。发现问题后单独记录,找技术定位是问答链路中哪个环节出了问题导致BadCase,修复方案可能是运营介入,也可能是技术介入。修复后再重新评测,整个过程相当费时费力。
既然机器人对话都能基于AI原生实现了,那么对话链路的效果评估,是不是也可以利用AI原生的能力,节省人工参与成本?
答案是肯定的。经过不断摸索和实践,我们建设了“评估-诊断-优化”三位一体的
运营Agent平台(一个垂类Agent)
在KA客户的实际应用中,服务记录
BadCase发现的准确率达到85%+,根因归类和优化建议生成的准确率80%+
85%+
五、评测怎么落地
其中:
六、遇到了哪些难题
建设运营Agent进行对话效果评测的过程并不轻松:规则如何准确生效、上下文怎么设计、怎么降低LLM的抽风概率……下面分享一些在实践中踩坑积累的经验,算是抛砖引玉。
6.1 正向评判还是负向评判
要评判机器人回答是否符合预期,首先得定义“规则”。最开始的想法是搞几个通用规则,每个规则都有分数,让LLM根据输入的Query和机器人回答的Answer,判断是否命中规则。每个规则项根据权重设定不同分数,比如“语义相关性”维度分值最大(50分),“表达质量”维度分值较低(20分),所有维度总分100分。
这里的分数判断,不是让LLM只做“正向判断”或只做“负向判断”,而是一种混合做法。“纯负向”判断会让LLM过度关注缺陷,忽略整体价值;“纯正向”评判又比较宽松,可能遗漏问题。
我们采用“混合策略”进行分层评估:既有明确的红线扣分点,也给LLM一定的发挥空间,在一定分值波动阈值内综合判断。LLM的思考过程会变成“找优点→找缺点→综合权衡”,更接近人类的全面评估。
6.2 业务场景的强依赖
有了上面的评判规则后,在实操中发现,有些服务记录的评判总达不到预期效果。例如用户咨询“课程取消规则”时,机器人需要进一步澄清是哪种类型的课程才能给出对应内容——不同类型课程在规则上有差异(比如A类型课程可以上课前2小时取消,B类型需要提前3小时取消)。如果运营Agent不知道不同种类的明细规则,不清楚客户的真实诉求,就会导致误判。
因此,在运营Agent判断服务记录是否为BadCase之前,需要做两件事:1、识别出客户诉求;2、根据客户诉求获取强关联的业务内容作为参考知识提供给LLM。
6.2.1 客户诉求
如何准确识别客户诉求?单纯依靠LLM对当前Query内容进行提取,准确性存在问题。如果涉及多轮对话,更需要结合历史对话内容才能提取出完整诉求——因为诉求可能会变,也可能需要综合多句内容才能识别完整(比如上面的例子)。
更关键的是,一些商家的业务场景相当复杂。比如某健身企业,包含多种健身品牌,每种品牌下又有名称相似的课程(比如私教课、团课),每种课程下又有类似的子场景(比如预约课程、取消课程等)。这些细分场景的描述有时很接近,会影响客户诉求的识别。
客户的问法千奇百怪,但企业客户服务的业务范围是明确且可枚举的。我们设计了两个层级的关联:业务品类和业务场景。
业务品类
业务场景
通过分析服务记录数据、与业务同学沟通,我们梳理出上述KA健身企业7个业务品类、40多个业务场景信息。将这些信息放入Prompt中,结合历史对话内容,让LLM把Query信息与品类/场景信息做映射判断,同时兼顾
历史诉求的延续、新诉求的产生
最新诉求
以下是一个案例:
{
"customerQuery": "转让",
"robotAnswer": "请问您是想咨询哪种类型的课程转让呢?例如私教课或其他类型?"
},
{
"customerQuery": "会员卡",
"robotAnswer": "请问您是想咨询关于会员卡转让的具体问题吗?"
}
如果用户只提问“会员卡”三个字,历史情况下很容易被识别为会员卡咨询等意图,导致误判。经过上述逻辑处理后,能有效识别用户意图,为后续的根因归类、优化建议产出提供保障。
{
"customerDemand": "会员卡转让咨询",
"brand": "**健身会员卡",
"scene": "会员卡转让场景",
"thought": "客户当前问题为'会员卡',结合历史对话中客户连续提及'转让'和'会员卡',且客服明确询问'是否咨询会员卡转让问题',可判定客户诉求聚焦于会员卡转让。根据品类信息列表匹配规则,'会员卡'属于xx健身的业务种类且未提及其他品牌,品牌xxx,结合业务种类记录为'xxxx'。场景匹配【场景信息】列表第28项'会员卡转让场景'的核心词'转让卡'、'会员卡转让'。"
}
业务品类和业务场景信息(也可以称为“意图分层体系”)可以通过自动化方式抽取,但也需要人工介入进行保鲜。
6.2.2 参考知识
评测需要用“怀疑”的视角看待对话链路中的每一个环节。比如RAG检索到的知识是否ok?有没有可能漏掉一些分片信息?
这就和上文中对话链路的梳理关联起来了。我们与知识Agent、对话Agent约定,将每个中间环节的输出结果进行持久化保存。比如知识Agent做检索时,需要保存粗召的结果分片信息和精排的结果。运营Agent会对每个阶段的结果数据进行判断:如果发现候选分片在粗召结果中未出现,根因归类为“粗召遗漏”;如果目标分片在粗召结果中存在但在精排结果中消失了,根因归类为“精排遗漏”。现在问题的关键是:如何知道和Query关联的所有目标知识分片?
Query或服务记录与某个客服机器人强绑定,且只属于一个机器人。一开始的想法是把当前机器人绑定的所有知识文档作为候选知识,用Query、历史对话、提取出的业务品类/业务场景/客户诉求综合作为输入信息,让LLM校验哪些分片是与Query强关联的目标知识分片。
这种方式在机器人绑定资料较少时适用,会对每个分片都做检查。但当机器人绑定资料较多时就不合适了——太慢了!
正常的RAG问答链路中,会按设定阈值从知识库召回TopN的知识内容。我们在此基础上适当降低阈值,扩大TopN数量,尽可能把所有与Query相关的内容都获取到。这样召回数量不再是全部文档分片,性能上也会得到提升。
6.2.3 豁免
由于某些业务场景的特殊性,客户的Query可能被规则命中后走特殊逻辑,比如触发转人工或机器人吐出固定话术。即使这些回答并未解决客户诉求,但在特殊场景下符合业务预期,不应被判为BadCase,应予以豁免。
最初,豁免判断和BadCase发现的逻辑放在同一个Prompt中交给LLM处理。但实操下来发现识别有偏差。为了避免“误杀”,我们把豁免判断抽成独立逻辑,先做豁免检测,再进行BadCase识别。
6.3 LLM的对抗
大模型本质上是概率性模型——即使给定“确定”的Prompt,输出结果也有“随机性”。在让LLM进行BadCase识别时,我们遇到了这种“随机性”带来的两个问题:
(1)使用同一个LLM(业界头部的LLM)和相同的Prompt,多次调用,输出结果不完全一样;
(2)相同的Prompt,使用不同的LLM(同样是业界头部的LLM),输出结果也不完全一样,甚至可能相反。
6.3.1 第一个问题
第一个问题的核心在于LLM的“随机采样”。随机性本身不是问题,它恰恰是LLM推理性和多样性的来源。大模型生成结果(文本内容为例)是一个自回归过程,逐Token进行。输入Prompt后,模型执行以下步骤:
- step1:处理输入内容;
- step2:计算出所有可能的下一个Token的概率分布;
- step3:从这个分布中选出一个Token作为输出;
- step4:把新生成的Token追加到原有上下文中,重复上述过程生成下一个Token,如此循环。
关键在于第2步和第3步。
第2步中,LLM为每个可能的词(姑且把Token这样理解)计算分数(
logit
Softmax
logits
如果没有随机性,模型每次总是选“公园”,输出会非常死板。为了增加随机性,LLM使用了两个重要参数:
Temperature
Top-P
Temperature(温度)
温度是一个在Softmax计算之前应用的参数,直接重塑概率分布:
概率 = Softmax(原始分数 / Temperature)- 低温度(如0.1):除以很小的数,会放大高分和低分之间的差距。
- 效果:高概率词(如“公园”)概率更高,低概率词(如“飞翔”)概率更低,输出更确定、保守。
- 上例中,“公园”概率可能从65%上升到95%,其他词被严重压制。
- 高温度(如1.5):除以大于1的数,缩小分数差距。
- 效果:概率分布更平缓,低概率词(如“吃饭”、“飞翔”)机会变大。
- 上例中,“公园”概率从65%降到40%,“散步”升到30%,“吃饭”升到20%,“飙车”升到10%。输出更多样、更有创意,也更不稳定。
Top-P
Top-P是在Softmax计算之后应用的筛选机制。它将候选词按概率从高到低排序,保留一个最小集合,使集合中所有词的概率之和刚好超过Top-P中的P(例如p=0.9)。整个过程如下:
- 排序:公园(65%),散步(24%),吃饭(9%),飙车(2%)……
- 计算累积概率:公园(65%),公园+散步=89%,公园+散步+吃饭=98%(超过90%);
- 筛选:只保留{公园,散步,吃饭},概率极低的“飙车”被剔除;
- 重新归一化:这三个词的概率重新缩放到和为100%(例如:公园~66%,散步~25%,吃饭~9%);
- 最后从新的、筛选后的集合中随机采样。
由此可见,只要
Temperature
Top-P
随机
P(全文)=P(x1)⋅P(x2|x1)⋅P(x3|x1,x2)...P(xn|x1,...,xn-1)
每一步的微小随机差异通过这个链式法则被指数级放大,导致最终结果的显著不同。
6.3.2 第二个问题
为什么相同的Prompt,不同LLM输出结果不同(即使都是国内顶流模型)?这主要源于分词和训练参数的差异。
分词差异
LLM不是直接理解输入的文字,它会先拆成“Token”。不同模型的分词器(Tokenizer)不同,比如“unstable”这个词,分词器A可能拆成"un"和"stable",分词器B可能直接视为整体"unstable"。这导致LLM接收到的初始输入序列不同,后续推理计算自然也不同。
训练参数差异
LLM的核心是千亿甚至万亿个参数,这些参数从大量数据中通过训练学习得到。不同模型的训练过程和训练数据不尽相同,这些参数决定了LLM如何处理通过分词得到的输入Token,并计算出前面提到的原始分数(
logits
- 此外,指令微调和RLHF也千差万别,这也是不同LLM输出结果差异性的原因。
6.3.3 怎么解决
对于第一个问题,调用LLM时可以通过调整Temperature和Top-P的值来缓解(阿里云百炼的SDK支持动态设置),虽然不能完全避免随机性,但可以降低发散概率。对于第二个问题,我们采用多个LLM对抗的方式:识别BadCase时,通过两到三个LLM执行相同Prompt,用统计学方式得到最终结果(前提是对LLM执行耗时不是特别敏感)。
LLM判断为BadCase的结果示例:
{
"qwen3-235b-a22b" : "{"score":30,"thought":"1. 内容合规性:客服回答未直接处理客户因店面装修申请停卡的诉求,且未正确引用参考知识中关于特殊情况(如装修)需联系人工或店长的规则,违反了特殊场景需转人工的合规要求,扣20分。\\n2. 语义相关性:客户明确诉求为停卡一周,但客服未提供有效解决方案(如指引停卡路径或确认资格),仅重复引导选择订单或转人工,未解决实际问题,扣30分。\\n3. 表达质量:语言结构合理,但未明确说明停卡规则,导致信息模糊,扣5分。\\n4. 信息完整性:未提及停卡条件(如需备注原因、审核时间等)或操作路径(如链接申请),核心信息缺失,扣15分。\\n综合评分:100-20-30-5-15=30"}",
"DeepSeek-r1" : "{"score":60,"thought":"客户诉求识别:客户问题'店面还在装修,申请停卡一周'为肯定句式,但含业务动词'申请停卡',根据规则视为明确诉求(停卡申请)。参考知识分析:分片'我可以停卡一周吗?'直接匹配客户问题,chunkContent明确'不支持自定义停卡时长或指定到某一时间',仅支持无理由停卡30天或特殊情况需证明。客服回答让客户'返回订单列表选择订单'或'转人工',未引用该核心知识,且与参考知识中自助停卡路径(如分片1的链接)矛盾,内容合规性扣20分。语义相关性:参考知识有完全匹配分片,但客服回答缺失核心信息(不支持自定义时长),扣10分;历史对话显示客户重复诉求(多次'转人工'),但回答包含转人工语义,不额外扣分,得40分。表达质量:语言流畅,无语法错误或质疑语句,得10分。信息完整性:未提供停卡规则(如时长限制)或自助路径,核心信息缺失,扣10分,得10分。总分:0(合规性)+40(相关性)+10(表达)+10(完整性)=60。"}"
}
两个LLM给出的判断分值不同,但都远小于设定的BadCase阈值,最终均值为45分,准确识别为BadCase,符合预期。
6.4 深度思考模式
让LLM进行的推理分析场景包括BadCase识别、根因归类和优化建议产出,逻辑都比较复杂。即使我们在Prompt中特意强调了“让我们一步一步分析”等COT方式,LLM也不是每次推理都能输出准确结果。
这就涉及到LLM的思考模式问题。开启深度思考模式后(比如百炼可通过SDK的enableThinking参数控制),与普通“链式思考”相比,“深度思考”相当于启动了一个高级的、内置的“系统Prompt”,专门指示模型做以下事情:
- 问题解析与规划:不要急于回答,先彻底理解问题的核心和边界条件;
- 多路径推理:构思多种解决方案并比较优劣;
- 逐步执行与验证:严格按步骤执行,每一步都进行自我检查,确保逻辑和事实正确性;
- 自我批判与修正:主动寻找推理中的漏洞、假设或错误,并尝试修正;
- 最终整合:确认推理过程无误后,给出精炼准确的最终答案。
实际使用中,我们既在Prompt中详细描述了让LLM执行的步骤,也根据场景复杂度开启了“深度思考模式”。因为深度思考不仅仅是执行我们给出的步骤,还包含了更高层次的推理:
- :即使列出了步骤,模型也可能不理解每一步的意图,开启深度思考会迫使它理解背后逻辑,执行时更不容易出错(当然也无法完全避免);
理解“为什么”要这么做
- :给出的步骤本身可能有漏洞,或模型在执行某一步时可能出错,深度思考模式下的自我批判机制能主动发现并纠正这些错误;
自我验证
- :如果步骤描述不够精确,或问题中间出现意外情况(如数据单位不统一),开启深度思考更有可能发现并处理歧义,而关闭模式则直接可能导致错误(这一点非常重要)。
处理模糊和意外情况
需要注意的是,开启“深度思考模式”后,虽然对LLM推理结果的准确性和全面性有正向作用,但
响应时间也会显著变长
“深度思考模式”也不是一开启就能立竿见影。对于事实查询、摘要、简单分类、格式转换这类任务,可以关闭深度思考,这样响应更快、成本更低,结果通常也足够好。
当需要LLM进行复杂推理分析、追求高可靠性输出时,“深度思考模式”通常能带来不错的效果。
6.5 上下文工程
通过以上一系列处理,我们有了让LLM执行的规则、操作步骤、参考数据,还有了运行态的动态参数调整(Temperature等)。理论上LLM可以按期望进行推理输出了。但实际并非如此,还有大量工作要做——这就是上下文工程(
Context Engineering
之前有个概念叫“
Prompt Engineering
Context Engineering
给LLM的上下文内容,太长或太短都会出问题
实际使用中发现,很多LLM号称支持几十万、上百万Token的窗口,但实际情况是“支持”归“支持”,“效果”却不一定有保障。
在我们的场景中,需要提供很多参考知识(与Query相关的文档分片内容、智能SOP内容、FAQ内容等)让LLM推理判断。分片内容本身包含大量文字,加上其他内容(规则、步骤、历史对话、Few-Shot等),每次累加起来需要
大几万
{
"chunkContent": "xxxxxxxxxxxxxxxxxxxxxxxxxxx,上百个字符)",
"chunkId": "123456789034576961536",
"chunkRelatedQuestion": [ "aaaaaaaaaaaaa,几十个字符" ],
"chunkTitle": "aaaaaa"
}…………{
"chunkContent": "yyyyyyyyyyyyyyyyyy,上百个字符)",
"chunkId": "123456789034576961578",
"chunkRelatedQuestion": [ "bbbbbbbbbbbb,几十个字符" ],
"chunkTitle": "ccccccc"
}
LLM会把chunkId为“123456789034576961536”的数据误认为是“1920679034576961578”,出现张冠李戴的问题(当给LLM的Prompt内容Token量较少时,基本不会出现这种问题)。
6.5.1 为什么会这样
LLM的“记忆力”完全依赖于工作记忆(Working Memory),也就是通常说的“上下文窗口”。可以把大模型想象成一个拥有海量长期记忆(从训练数据中学到的知识)但只有极短工作记忆(上下文窗口)的机器人——它的思考完全依赖当前上下文窗口中的信息,一旦超出窗口就“看不见”了。而即使是窗口内的信息,处理机制也因为底层架构的注意力机制存在局限性。
LLM底层的(Transformer)注意力机制,通过计算所有输入Token之间的注意力权重,决定生成下一个Token时应该“关注”上下文中的哪些部分。当上下文内容过长时,这个机制存在三个局限性:
注意力权重稀释
LLM计算注意力时,会为上下文中的每个Token分配权重,权重之和为1。随着上下文变长,模型需要处理的Token数量同步增加。当大量不相关或低相关性信息涌入上下文时,这些信息会瓜分本应属于关键信息的注意力权重,导致重要信息权重被稀释。
缓存局限
为了高效生成,LLM使用缓存存储之前所有Token的中间计算结果,避免重复计算。这个缓存就是模型的“短期记忆”,大小固定,等于上下文窗口长度。新Token进入时,最老的Token会被挤出缓存、被遗忘——这就是最直接的“上下文丢失”。
模型无法像人类一样有选择地将重要信息从“短期记忆”转存到“长期记忆”
位置编码局限
LLM需要知道每个Token在上下文序列中的绝对位置和相对位置(比如旋转位置编码RoPE)。在超长上下文中,位置编码可能失去区分度。例如,第20000个Token和第20100个Token的位置编码可能非常相似,导致模型难以精确区分位置关系,引发上下文混淆。
以上三点会带来一些问题,可以概括为上下文失效的四种场景(参考《How Long Contexts Fail》一文):
(1)上下文冲突场景
上下文中包含相互矛盾的信息或指令,LLM输出混乱或偏向某一方。
- :
近因效应与首因效应
- 注意力机制在实践中常表现出“近因效应”,即更关注上下文尾部信息。这是因为在训练和生成过程中,序列末尾通常与当前要预测的Token关系最直接。
- 同时,也存在一定的首因效应,即开头的指令(如系统提示)也占有重要权重。
- 近因效应和首因效应并非逻辑矛盾,而是注意力机制在不同力量影响下表现出的两种竞争性偏好:首因效应是“规则和背景”的守护者,近因效应是“当前和具体”的响应者。
在实际的BadCase识别场景中,把最重要的规则写在Prompt前面,确实会让LLM更加重视。
- :当两条冲突(或不同维度)的指令A和B分别位于上下文不同位置时,模型会陷入“注意力内战”。最终输出取决于哪条指令的综合“注意力得分”更高,这个得分受多种因素影响:
注意力竞争
- 位置:末尾指令(近因效应)通常占优。
- 显著性:被强调(如加粗、重复)的指令更容易获得高权重。
- 与查询的相关性:与当前生成任务在语义上更匹配的指令会获得更高权重。
- LLM没有内部的“逻辑仲裁器”,它只是在做基于统计的加权平均。当两种力量势均力敌时,输出就会显得矛盾和不确定,“冲突”就出现了。
(2)上下文混淆场景
LLM混淆了不同实体、概念或话题的来源。例如,把用户A说过的话安到用户B身上。前面提到的
chunkId内容混淆
- :
注意力泛化
- 注意力机制本质是基于相似度的。当上下文中间出现多个相似实体(如多个人物、多个名称、多个相似格式的ID)时,模型在计算注意力时可能发生“张冠李戴”。例如,生成关于“张三说了什么”的回应时,由于“李四”的发言在语义和主题上与当前查询高度相似,模型错误地给“李四”的KV对分配了过高权重。
- :
位置编码模糊
- 如前所述,长文本中精确的位置信息可能变得模糊。如果张三和李四的发言位置接近,模型更难依靠微弱的位置差异来正确区分。
- :
缺乏实体追踪
- 模型没有内置的、符号化的“实体状态追踪表”,完全依靠前文Token分布隐式建模关系。当关系复杂时,这种隐式建模就容易出错。
(3)上下文干扰场景
无关紧要的背景信息或之前的失败案例影响了LLM当前的表现。
- :见前文局限性描述。
注意力稀释
- :在Transformer前向传播中,每一层的输出都是下一层的输入。无关信息通过注意力机制和FFN层,将其“激活模式”传播到后续计算中。即使模型试图忽略,这些噪音的“回声”依然存在于整个计算图,污染了纯净信息的处理过程。
激活值传播
- :如果污染源是一个矛盾指令(如“请用悲观的语气回答,但请忽略这句话”),模型在解码时,这个指令的缓存信息会持续参与所有后续Token的生成计算,导致模型很难真正“忽略”。
指令遵循的脆弱性
(4)上下文丢失
LLM忘记了上下文窗口开头部分的内容。
- :这是最直接的原因。当输入长度达到上下文窗口上限,生成下一个Token时,最老Token的缓存会被丢弃。
缓存的先进先出
- :即使在窗口内,随着输入变长,开头部分Token获得的注意力权重也会系统性降低。大模型更倾向关注局部、临近的信息,因此即使开头Token理论上还存在,功能上已经被“边缘化”了。
注意力权重衰减
6.5.2 怎么解决
文章《How to Fix Your Context》针对以上四种问题,提出了上下文管理策略:
- RAG
- 工具装载
- 上下文隔离
- 上下文修剪
- 上下文总结
- 上下文卸载
有兴趣可以看看原文。我们在实践中感触最深的是“
上下文修剪
(1)逻辑分拆
设计之初,我们高估了LLM的能力,把大量复杂逻辑写在一个Prompt里让LLM分析。比如做BadCase根因归类时,把所有根因类别及其规则描述都放在一个Prompt中:
……
……
## 【问题种类】:根据【用户提问】、【回答内容】、【知识粗召结果】、【知识精排结果】进行综合分析,判断当前【回答内容】视为badcase的归因类型,归因类型如下:
### 精排问题
(1)「类型code」:SORT_INACCURATE
(2)「规则描述」:xxxxxxx
### 生成时幻觉问题
(1)「类型code」:GENERATE_ILLUSION
(2)「规则描述」:xxxxxxx
### 生成内容错误
(1)「类型code」:GENERATE_WRONG
(2)「规则描述」:xxxxxxx
### 操作行为超出范围
(1)「类型code」:NO_TOOL_MATCH
(2)「规则描述」:xxxxxxx
### 缺少知识
(1)「类型code」:NO_KNOWLEDGE
(2)「规则描述」:xxxxxxx
### 用户提问没有全部得到回答
(1)「类型code」:INCOMPLETE_ANSWER
(2)「规则描述」:xxxxxxx
……
……
结合历史对话等上下文,让LLM判断BadCase属于哪种根因——这个模式类似于Function-Call。
实际运行发现根因判断有误判。我们根据前文分析做了逻辑拆分,把每种根因归类单独拆出来,由一次大模型调用改为多次调用,
降低每次给LLM的任务复杂度
(2)内容精简
- 明确告诉LLM“请一步一步进行分析”这类语句,十分必要;
- 根据前文对LLM注意力机制的分析,(目前控制在5万以内,这个值不固定,LLM也在不断发展);
降低Prompt长度
- 把描述放在Prompt头部。比如把“内容合规性”判断放到BadCase识别规则中靠前的位置,降低该规则放在后面被LLM漏掉的概率——毕竟“合规”是底线;
重点规则
- Prompt中,尤其给LLM的参考知识内容较多时,减少冗余信息就是减少对LLM的干扰。比如文档分片包含很多属性(分片名称、相似问、分片ID、标签、创建时间、修改时间、创建人、修改人、状态、来源等),我们只把最需要的ID、名称、内容、相似问信息给到LLM,其他冗余信息全部丢弃。
只包含必要信息
- :一些ID、变量名等信息需要传给LLM,但其原始格式因上游系统设计原因可能很长(例如123456789066515357696)。这些长ID占用Token较多。我们在组装Prompt之前,先对这些数据做映射,比如把“1123456789515357696”映射为“1”,“123456789515357697”映射为“2”,映射时保证唯一性,这样也能大大减少Prompt长度。
压缩数据
(3)强制性约束
期望LLM输出固定格式时,需要明确约束:
# 输出规范(请严格按照标准的json格式输出!) 请严格遵循:
## 直接输出纯净JSON对象,禁止包含```json等代码块标识符
## 使用标准JSON格式:
### 取消所有换行符,保持单行结构
### 必须使用双引号
### 结尾不要带多余符号
## 错误示例: x ```jsonn{n...}n``` (含代码块标识) x {'tasks': [...]} (单引号非法)
## 输出必须为正确可解析的json格式(严禁多余、缺少和错误的{}和`符号和多余的json字母)
# 禁止行为
× 使用非工具库中的工具
× 情感化表达或主观猜测
× 非标准JSON格式的输出
(4)Few-Shot
在Prompt中添加适当的Few-Shot示例,可以有效引导大模型参考给出的示例和思考步骤进行推理,对提升整体推理准确性有很大帮助。
大模型在预训练阶段已经“阅读”了海量互联网文本,其中包括无数数学题解、逻辑论证、计划步骤等,模型内部已经存储了如何进行推理的“知识”或“模式”。但如果没有引导,它可能不知道在当下需要调用这种模式。Few-Shot示例可以充当“触发器”,引导大模型正确使用它已经掌握的知识。
6.6 并发和限流
我们主要通过百炼进行LLM调用,而且多是集中式调用——创建对话效果评测任务后,就开始
大量并发
com.alibaba.dashscope.exception.ApiException: {"statusCode":429,"message":"Requests rate limit exceeded, please try again later.","code":"Throttling.RateQuota","isJson":true,"requestId":"********"}
com.alibaba.dashscope.exception.ApiException: {"statusCode":429,"message":"Allocated quota exceeded, please increase your quota limit.","code":"Throttling.AllocationQuota","isJson":true,"requestId":"********"}
对于QPM限流,我们只能
控制线程调用的并发数
也会影响并发调用LLM的响应速度
对于TPM限流,不仅输入Token有影响,如果开启思考模式,输出时思考过程数据也会占用TPM阈值。
输出Token量
6.7 中断及恢复
运营Agent执行效果评测任务需要长时间运行。每个任务包含很多服务记录的检测,每条服务记录又包含多个阶段的逻辑处理。
如果遇到服务重启或其他原因,运行中的任务会被中断。这种异常中断会影响使用体验——因为是长时间运行的任务,当用户察觉到异常时已经滞后了,重新开始又要耗费大量时间,更不用说LLM的重复调用(Token的浪费)。
我们设计了一套任务的checkpoint机制:在避免频繁扫表(DB)的情况下,能主动发现异常中断的任务,并自动根据当前中断的阶段重新运行,而不是盲目地从“初始化阶段”全部重来。
核心思路是:每个阶段运行时,该阶段中每条服务记录在逻辑处理时都会上报心跳,更新对应任务的最新状态。定时任务会轮询当前超时的任务,将未开始或失败的服务记录重新执行该阶段的逻辑。
七、效果
一些指标性结果在前面第4小节已做了概要描述(BadCase发现准确率85%+、根因归类和优化建议生成准确率80%+等)。
找出BadCase的根因只是第一步,更进一步的是如何解决:
- 有些根因需要才能解决,比如转人工策略的优化等。
运营协作
- 举例:客户多次询问类似问题并有情绪化表达,但没有触发转人工。运营Agent可以提取此类场景,给出优化建议(如下样例)供运营同学参考:
通过对内容的分析,客户在历史对话中已多次表达转人工诉求(共4次提及),且当前问题仍聚焦于会员卡退卡处理。机器人客服在对话中未有效解决客户诉求,针对退卡问题未提供实质性解决方案,反而在回答中持续引导购买季卡等无关信息,导致客户情绪升级并反复强调转人工需求,符合反复追问强调、客服未有效回答及强烈转人工诉求三个场景。需优化服务策略以提升响应有效性。
- 有些根因需要才能解决,比如生成内容的Prompt优化等。
技术协作
- 举例1:客户咨询了多个问题,机器人只回答了其中一个,会被识别为“”。该根因需要技术协助,运营Agent给出优化建议(如下样例)供技术同学参考:
回答内容不完整根因
通过对内容的分析,客户问题包含「退款申请」和「扣款原因咨询」两个诉求,场景为「退款咨询场景」。客服回答内容包含「自动续费订单退费登记」和「会员卡退款申请流程」,对应「退款操作指引场景」和「自动续费场景」。虽然客服回答覆盖了退款操作路径,但未对客户提出的「扣款原因咨询」诉求作出任何解释,也未明确说明扣款依据或提供查询渠道。因此客服回答未解决客户全部诉求,标记为回答不完整。
- 举例2:一次运营Agent任务结果中,BadCase的会话量突然暴增,如下图:
其中大部分BadCase的根因属于“
回答内容不完整
“上下文工程”中描述的“近因效应”
- 还有一些场景,运营Agent可以:
直接给出优化建议
- 比如“”、“
粗召遗漏问题根因
”等。这些根因意味着与Query相关的内容确实存在于知识库中,但召回时因相似度等原因在最后环节没有被用上。优化建议一般是给强关联的候选分片精排遗漏问题根因
,可以自动入库生效,或运营审核后入库生效。增加“相似问”
- 举例:给符合意图的知识分片增加相似问内容,如下:
{
"客户": "麻烦看一下我的连续包月后续每个月多少钱",
"机器人": "请问您是想咨询关于连续包月的什么问题呢?"
}
根因归类:粗召遗漏问题
根因归类描述:分片标题为【一、卡种介绍, 1.1通用卡, 1.1.2自动续费】的分片,在问答链路的粗召环节没有被召回,其内容和用户意图强相关
优化建议:增加相似问
优化建议内容:如何查看自动续费的下次扣费金额
- 又比如“缺少知识”等根因,运营Agent会根据当前服务记录的上下文和客户意图,相关知识,并对检索到的内容进行二次校验,将高度匹配的内容抽取成知识自动入库,或运营审核后入库(但客服场景下,从互联网抓取到高匹配内容的概率较小,绝大部分情况是运营Agent把意图和业务场景提供给运营同学
自动从互联网检索
相关知识)。手动补充
- 运营Agent也间接推动了知识Agent的逻辑优化。最初执行“增加相似问”优化建议时,发现即使给对应知识分片添加了符合预期的相似问内容,二次Check优化建议是否生效时,仍然无法召回对应的分片。与知识Agent同学一起分析后,发现之前RAG做融合召回时,相似问只用在兜底逻辑——只有当(标题、正文的向量化)召回数量达不到阈值时,才会用搜索引擎召回作为补充,存在漏召场景。随后
向量化
,将相似问也纳入向量化(标题、正文、相似问)和搜索引擎(标题、正文、相似问)的优化RAG逻辑
中,才解决了这个问题。多路召回逻辑
八、还能做什么
如果把关注点从BadCase的粒度放大到整个服务链路,AI还能做什么?
从服务爬坡阶段(非初始化冷启动)的提效(满意度、服务成本等)角度来看,一般期望机器人承担更多客户服务、减少人工服务,只有机器人服务不了的才通过转人工兜底。量化这个期望通常有两个指标:机器人回答准确率和机器人解决率。
机器人回答准确率
- 准确,通常指机器人回答内容是否符合预期。
机器人回答解决率
- 解决,通常指机器人回答的内容是否解决了客户的咨询问题。
但
准确率并不等于解决率
一通转人工的服务(
转人工即视为机器人服务未解决客户问题
服务分析
(1)服务策略配置导致触发转人工
运营人员可以配置拦截策略,命中策略的客户咨询会中断机器人服务、触发转人工。如果一段时间内出现大量转人工请求,可能是某个策略异常变动导致。运营Agent也可以发挥能力,做到自动分析识别。
同时结合复访数据和6.2.1小节中描述的“业务品类”、“业务场景”等信息,以及人工服务阶段的对话内容,利用LLM分析出复访客户的归属场景。如果某个场景有异动,就可以进一步定位具体原因。
(2)客户心智问题
用户心智导致的转人工,比如客户不说话或只表达“转人工”等内容。这种场景下机器人服务阶段很难改善,它间接决定了“解决率”的上限。
不过,仍然可以根据“是否复访”拆解出有多少是之前没服务好、导致本次服务客户一接通就想转人工。
另外,结合用户最近的订单记录、咨询记录以及当前的整体Top问题,把“猜问”进一步个性化,理论上也能起到正向效果。
(3)机器人回答内容不能解决客户问题
机器人按要求回答了内容,但客户仍然触发转人工。运营Agent需要深度分析这种场景。
可能是机器人问答链路的问题,可以参考前文大篇幅描述的对话效果评测内容;也可能是机器人覆盖范围受限,需要利用LLM,结合机器人服务对话内容和人工服务对话内容,分析机器人给的方案与人工服务阶段方案的差异性,根据下钻分析的结果调整机器人所能服务的业务范围和知识内容。
也可能是业务本身的异动,比如大促活动等。
九、总结
在客服运营领域,AI能力的加持可以细粒度地进行机器人服务对话效果的全链路评测分析,为机器人对话能力和知识能力带来正向反馈;也可以站在更宏观的视角,综合业务数据、人工服务对话数据等,为提升机器人服务解决率提供参考方向。