内部测试全员点赞,演示效果惊艳全场——这样的功能上线2周后,你的用户突然问:"这些总结是不是在编东西?"
这就是几个月前我遇到的真事。一个用 LLM 做工单摘要和回复建议的功能,50次里大概出错1次。但错的那次,语气、结构、细节看起来和正确的毫无区别。付款失败被总结成"用户想取消订阅",加载慢的投诉被改写成"用户报告欧盟地区服务中断"。
模型没坏,基准测试分数漂亮,但长尾里全是这种"自信的错误答案",发现它们的是你的真实用户。
以下是 debug 过程中的关键教训,以及最终把幻觉率压到可接受范围的分层方案。
为什么难抓:流畅≠正确
首先要理解一件事:语言模型不管底层推理是否成立,都能产出流畅文本。表面输出里读不到"我不太确定"的信号。自信编造细节的模型,和自信陈述事实的模型,从你的应用视角看一模一样。
更糟的是,评估套件通常偏向典型输入。你的测试打中的是中位数场景,生产流量却撞向长尾——奇怪格式、罕见实体、矛盾上下文、模糊代词、多语言混杂。幻觉就住在长尾里。
我们的具体案例:客户提到多个无关话题时,摘要器会锚定第一个出现或情绪最强的话题,自信地把它当成整单主题。
第一层:约束输出结构
自由散文给模型留下了顺畅编造的空间。约束输出则迫使它对具体主张做出承诺,而这些主张你可以逐一验证。
不要要摘要,要结构化对象:
// 差的写法:自由散文,难验证
prompt = f"Summarize this ticket: {ticket}"
// 好的写法:结构化主张,可逐项检查
schema = {"primary_issue": "str", "customer_intent": "enum[refund, cancel, technical_help, billing, other]", "mentioned_order_ids": "list[str]", "sentiment": "enum[neutral, frustrated, angry]", "requires_human": "bool"}
JSON Schema 或各家提供的函数调用特性更好,因为它们在解码层就施加约束。核心思路是:你要离散的主张,不是段落。主张可以检查,散文不能。
第二层:加验证轮次
这是真正起作用的改动。把输出再过一遍模型,这次唯一的任务是检查每个主张是否有原文支持。
热门跟贴