AI 幻觉防御指南:从"一本正经胡说八道"到"老实交代"

AI 幻觉防御指南:从"一本正经胡说八道"到"老实交代"
"AI 告诉客户我们有终身保修,其实根本没有这个政策。"
这是我们接手的一个真实翻车案例。今天给一份工程师视角的幻觉防御手册——不念论文,讲实操。
先搞清楚:幻觉分几种?
不是所有"胡说八道"都是同一种病。对症下药才有效:
| 幻觉类型 | 表现 | 病因 | 解法章节 |
|---|---|---|---|
| 事实幻觉 | 编造政策/价格/日期 | 模型"脑补"了不存在的知识 | 第二章 |
| 引用幻觉 | 编了不存在的文献/来源 | 模型为了"显得有依据" | 第三章 |
| 格式幻觉 | JSON 多了字段、少了引号 | 模型输出不稳定 | 第四章 |
| 推理幻觉 | 逻辑跳步、前提错误 | 模型"想当然" | 第五章 |
| 记忆幻觉 | 把 A 客户的信息说给 B 客户 | 上下文混了 | 第六章 |
| 过度自信 | 明明不知道却给确定答案 | 模型概率校准差 | 第七章 |
一、防御事实幻觉:让模型"不知道就说不知道"
核心原则:知识只能来自检索,不能来自模型脑子
错误做法:
你是一个客服助手,请回答用户关于我们产品的问题。
模型会用训练时"记住"的碎片信息回答——大部分是错的。
正确做法:
你是一个严谨的客服助手。
规则:
1. 只能使用【参考文档】中的信息回答
2. 如果参考文档中没有相关内容,回答"这个问题我需要确认一下"
3. 不要使用你自己的知识来补充
4. 涉及价格/时间/政策,必须从【已知事实】区取
硬约束:关键字段必须来自结构化数据
涉及价格、库存、发货时间、保修政策——这些绝不让 LLM "自由发挥"。
做法:用 API/数据库查出来,拼进 Prompt 的"已知事实"区:
【已知事实(来自系统,100%准确)】
- 产品A价格:299 元
- 发货时间:48 小时内
- 保修政策:1 年有限保修
【用户问题】
产品A多少钱?保修多久?
二、防御引用幻觉:别让模型编参考文献
症状
"根据《2025 年中国电商白皮书》第 3 章……"
——这本书可能根本不存在。
解法:引用必须带可验证链接
RAG 系统天然能返回来源文档。关键是在 Prompt 里强制要求:
回答时必须在末尾标注引用,格式:
[来源:文档名-章节]
如果某个信息没有对应的检索结果,不许写引用。
进阶:引用校验
生成完回复后,加一步校验 Agent:
校验任务:检查上一步回复中的每个引用,
确认该引用对应的文档中确实包含被引用的信息。
如果发现"编的引用",删除该句并标注"[信息待确认]"。
实测能把引用准确率从 70% 拉到 96%。
三、防御格式幻觉:让输出"机器可读"
症状
要 JSON 输出,模型偶尔多塞一段解释文字;要表格,偶尔少个字段。
解法 1:JSON Schema 硬约束
用 OpenAI 的 response_format 或 Anthropic 的 tool_use:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
response_format={
"type": "json_schema",
"json_schema": {
"name": "ticket",
"schema": {
"type": "object",
"properties": {
"category": {"type": "string"},
"priority": {"type": "integer", "minimum": 1, "maximum": 5},
"summary": {"type": "string"}
},
"required": ["category", "priority", "summary"]
}
}
}
)解法 2:格式校验 + 自动重试
def get_structured_output(messages, schema, max_retries=3):
for attempt in range(max_retries):
response = call_llm(messages, response_format=schema)
try:
data = json.loads(response)
for field in schema["required"]:
if field not in data:
raise ValueError(f"缺少字段: {field}")
return data
except (json.JSONDecodeError, ValueError) as e:
messages.append({"role": "user",
"content": f"上一次输出格式错误: {e},请严格按 JSON Schema 输出"})
raise Exception("多次重试后仍无法生成合规输出")四、防御推理幻觉:让模型"一步一步想"
症状
"客户说快递慢,所以他一定想退款。"——这是跳步推理,中间漏了"客户可能只是催一下"。
解法:强制 CoT + 自我检查
请按以下步骤回答:
Step 1:复述用户的问题(用自己的话)
Step 2:列出你考虑到的 2-3 种可能性
Step 3:逐一评估每种可能性的概率(高/中/低)
Step 4:选择概率最高的,给出回复
Step 5:检查你的回复——有没有"想当然"的地方?
听起来啰嗦,但这一招能把推理错误率压 30-50%。
五、防御记忆幻觉:上下文隔离
症状
客户 A 在问"我的订单到哪了",AI 回复了客户 B 的订单信息。
解法 1:每条对话独立 Context
绝不把不同用户的历史对话混在同一个 Prompt 里。
解法 2:会话 ID + 权限校验
def get_user_context(session_id, user_id):
history = db.get_history(session_id)
if history.user_id != user_id:
raise PermissionError("会话不属于该用户")
return history解法 3:敏感信息脱敏
def mask_sensitive(text):
text = re.sub(r'1[3-9]\d{9}', '[手机号]', text)
text = re.sub(r'\d{17}[\dXx]', '[身份证]', text)
return text六、防御"过度自信":让模型学会说"我不确定"
症状
模型对不知道的事也给出"确定"答案,用户信以为真。
解法:引入置信度
回答时,在末尾标注你的置信度:
[高置信度] - 信息来自权威来源
[中置信度] - 信息部分推断
[低置信度] - 不确定,建议人工确认
同时设置一个规则:置信度"低"的回复,自动转人工。
实战案例:从"编保修政策"到 0 幻觉
客户背景
一家做智能硬件的公司,AI 客服曾告诉客户"终身保修",实际只有 1 年。差点引发集体投诉。
六步修复
| 步骤 | 操作 | 效果 |
|---|---|---|
| 第 1 步 | 所有政策类信息改为 API 实时查询 | 价格/保修 100% 准确 |
| 第 2 步 | Prompt 加"不知道就说不知道"硬约束 | 编造率从 18% → 5% |
| 第 3 步 | 引用校验 Agent | 引用准确率 96% |
| 第 4 步 | JSON Schema 约束工单输出 | 格式错误率 0% |
| 第 5 步 | 会话隔离 + 脱敏 | 信息泄露事件 0 起 |
| 第 6 步 | 置信度标注 + 低置信转人工 | 高风险回复 100% 人工接管 |
总耗时:6 个工作日。
写在最后
AI 幻觉不是"模型不够聪明"的问题,是工程没做到位的问题。
六类幻觉、六个解法,每一步都是我们踩过坑后总结出来的。核心思想只有一句:
不要相信模型的"自由发挥",所有关键信息必须来自可信数据源,所有输出必须可校验。
如果你正面对一个"AI 开始胡说八道"的项目,找我们聊。我们不只会给你方案,帮你逐类定位幻觉来源,对症下藥。
参考资料
想让 AI 在你公司也跑出这种结果?
聊聊你的业务,我们给一份具体可执行的落地建议——免费、不绕弯。