客服 Agent 第一轮调订单查询工具,把 4KB 的 JSON 原样留在历史里,第二轮问那能退吗时,模型复述了内部字段名,还编出一个 refund_status。
一开始怀疑是「第二轮问题缺指代对象,模型只能从 JSON 里找线索」,查了一圈,方向不对。
这类报错背后常见的原因有几处,逐个排除就行。工具结果按原文进历史,模型会把内部结构当成事实。少数情况下是历史里没有对工具结果做摘要或裁剪。
另外,提示词没有禁止引用工具原始字段。
上来先统计历史里工具消息的字符占比
python -c "import json;m=json.load(open('hist.json'));print(sum(len(x.get('content') or '') for x in m if x.get('role')=='tool'))"
再往下把工具结果压成三行摘要再入历史
python -c "print('订单 A123 已签收 可退 7 天')"
接着在 system 里禁止引用字段名
python -c "print('不要输出接口字段名,只给用户能懂的结论')"
给下一轮问题补上指代对象
python -c "print('上一轮的订单 A123 能退吗')"
恢复的判定其实很直接。第二轮回答里不再出现 refund_status 这类字段名,工具消息字符数降到 200 以内,指代问题能正确落到订单号上。
这里还有个坑。工具结果既是事实来源也是污染源,进历史前压缩一次,比事后在提示词里加禁令有效。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
