客户在微信客服里问这个多少钱机器人回了一段功能介绍末尾还补了句可以试用。截图发过来客服同事问是不是 AI 坏了。模型没坏坏在它前面的知识库检索层——AI 拿到的上下文里根本没有价格信息只能拿功能描述硬答再凭训练语料的直觉补一句试用看起来通顺完全不对题。这类问题在工单里的原始描述都是机器人答非所问但拆开看答案的质量上限在检索层就定了。这篇复盘我们企业微信 AI 自动回复链路上检索层踩过的三次翻车和一次架构选型给同行参考。## 一问价格答功能裸产品名的平局挤出我们的知识库是检索式的每条知识带一组关键词客户消息进来先分词再按命中关键词的个数和权重打分取前三名拼进 AI 的上下文。事故那条知识的关键词只配了产品名裸词。后果是客户问价格时所有含该产品名的条目全都命中同一个词、得分相同价格条目没有任何独特词给它加分同分排序又按更新时间垫底挤不进前三。AI 看到的上下文里压根没有价格回答自然答非所问。修法是把关键词从分类标签的思路改成检索索引产品名加意图词复合配置比如产品名 价格 多少钱 报价并给意图词更高权重让问价格这个意图本身参与排序。上线后价格类问法的命中稳定了下来。教训落在配置侧检索式知识库里关键词不是给系统看的分类是给客户消息准备的钩子。配置界面引导配置的人用客户会怎么问的原话做关键词再配一个试算入口当场验证命中比培训他们理解打分算法有用得多。举一个修复前后的对比客户问你们那个扫码进来的客服机器人多少钱。修复前这句话分词后命中的是几个产品名裸词一堆功能介绍条目同分价格条目排在第四名开外AI 只能拿功能描述搪塞修复后价格条目带着多少钱“报价两个意图词的权重直接登顶AI 拿到价格信息回复既准确又克制。同一条客户消息同一个模型检索层一改答案判若两物——这就是上下文决定下限的意思。## 版本号变成负数一次乘法溢出第二个问题更隐蔽有客户改了知识库客服端永远拿旧答案怎么改都不生效。翻日志快照版本号是个负数。根因是快照版本号用秒级时间戳乘以十亿生成落库字段却是三十二位整数。算一笔账秒级时间戳本身约十七亿七千万乘以十亿是一点七七乘十的十八次方而三十二位有符号整数的上限约二十一亿四千万乘完直接溢出截断成负数。版本比较逻辑是版本变大才重装快照”负数比库里的历史版本都小快照永远不更新——配置改得再勤客服端读到的都是上线那天的旧数据。修法除了换成六十四位整数更重要的是补了一条边界测试新生成的版本号必须大于库里已有的版本号。溢出这类 bug 在单测里很好拦难的是先想到这个数会溢出——两个来源不同、量纲不同的字段相乘之前先把理论上限算一遍这条该进代码评审的清单。## 改完要等五分钟快照时效的两档设计第三个问题是体验知识库改完马上测还是旧答案要等五分钟才生效。桥接服务每五分钟无条件重装一次知识库快照这个兜底保住了最终一致但用户视角就是改了没反应客服收到的工单原话是系统坏了。修法分两档知识库的发布动作变成主动发缓存失效通知、版本号加一桥接服务收到通知立刻重装秒级生效不点发布最多五分钟由兜底机制自然生效。显式失效管我要马上对兜底过期管我忘了发布也不能永远旧两档叠加任何一条路径都不会留下永久旧数据。配置页上我们把这件事写成了明话“不发布也会在五分钟内自动生效”。上线后改了没反应的工单就绝迹了——用户不是不能等是不能不知道要等多久。## 为什么先不上向量答案列恒空的教训排查期间内部有个声音上向量检索做语义匹配不就没有关键词配置这些事了我们翻了自己一版半接线的向量管道向量化的写入管道没接完答案列恒空等于线上跑着一个空转的模块全靠关键词层和兜底在撑这件事还是季度审计逐列对账时抓出来的。这次选型的结论是向量检索留在路线图上但关键词层必须先做扎实理由是可解释、可复算。关键词引擎的每条回复都能从日志回答命中了哪条知识、为什么命中、得分多少客服反馈答错了能定位到具体条目去修语义检索召回是好可一旦答错说不清为什么对接客服排障是灾难。两者并不冲突关键词层做可解释的基线向量做补充召回、混合排序但基线层的每一次命中都要能对账这条不妥协。## 小结三次翻车一个共同病根检索层被当成了内部实现没被当成要验收的产品行为。配置的人按分类的直觉填关键词生成版本号的人没算过溢出做缓存的人只保证了最终一致——每一层在自己的视角里都对拼起来就是机器人答非所问。后来我们把四十多种真实问法固定成回归用例每次动关键词、动排序、动版本逻辑都跑一遍命中不对就拦在发布之前检索日志里也加了命中率统计命中不了前三的消息单独归档每周回头补关键词。企业微信 AI 自动回复的体验下限不取决于模型多聪明取决于喂给它的上下文对不对。## 参考文章- 微信客服自动回复怎么设置入口与规则详解- 企业微信自动回复设置从接入到转人工的完整方案