RAG Faithfulness 校验:防止幻觉进入治疗方案
RAG 系统的安全护栏:校验 LLM 生成的治疗方案中的每个动作是否能在知识库中找到依据,防止模型编造不存在的训练动作。
#type / concept
#status / growing
#tech / ai
[!info] related notes
- 并列安全系统: Red Flag 检测器
- 前置: RAG 知识库设计
- 应用: 咨询 Agent 工作流
RAG Faithfulness 校验:防止幻觉进入治疗方案
核心问题
RAG 的承诺是”基于知识库回答”,但 LLM 仍然可能在生成阶段编造知识库中不存在的内容。在医疗健康场景,一个不存在的训练动作可能造成伤害。
典型幻觉:
- 知识库里有”颈部后缩”,LLM 生成了”颈部旋转拉伸”(不存在)
- 知识库里有”猫牛式”,LLM 生成了”猫式伸展”(名字变了)
设计思路
在 LLM 生成治疗方案后,逐个检查方案中的动作名称是否能匹配到 RAG 检索结果:
治疗方案 → 提取所有动作名称 → 逐个在 RAG 结果中查找 → 标记 grounded/ungrounded
匹配策略
按优先级从高到低:
| 匹配方式 | 置信度 | 示例 |
|---|---|---|
| 标题精确匹配 | high | ”颈部后缩” 出现在知识单元标题中 |
| 内容包含匹配 | medium | ”颈部后缩” 出现在知识单元正文中 |
| 别名匹配 | medium | ”收下巴” → 别名表 → “颈部后缩” → 匹配 |
EXERCISE_ALIASES = {
"颈部后缩": ["收下巴", "颈后缩", "下巴后缩"],
"肩胛骨回缩": ["夹肩胛骨", "扩胸", "挺胸"],
"猫牛式": ["猫牛伸展", "脊柱屈伸"],
"臀桥": ["臀桥训练", "glute bridge"],
"平板支撑": ["plank", "平板"],
}
别名表解决”知识库里叫 A,LLM 生成的叫 B”的问题。
结果输出
@dataclass
class FaithfulnessResult:
faithful: bool # 是否全部 grounded
exercises: list[ExerciseFaithfulness] # 每个动作的状态
ungrounded_exercises: list[str] # 未找到依据的动作名
与前端的配合
faithful=False时,前端标注”此动作未经知识库验证”- 可以要求 LLM 重新生成(只用知识库中的动作名称)
- 或者直接过滤掉 ungrounded 的动作
设计要点
- 别名表要维护 — 新知识入库时同步更新别名
- 匹配粒度要适当 — 太严格会误杀(“拉伸胸肌” vs “胸小肌拉伸”),太宽松会漏检
- 不只检查名称 — 理想情况下还要检查组数、频率等参数是否合理
- 这是最后一道防线 — 不要依赖 faithfulness checker 兜底所有幻觉,prompt 设计和 RAG 质量才是根本
局限性
- 依赖 RAG 检索质量——如果相关知识没被检索到,合理动作也会被标记为 ungrounded
- 别名表不完整——新动作需要手动添加
- 纯字符串匹配——“拉伸胸肌” 和 “胸小肌拉伸” 是同一个动作但可能匹配失败
- 只检查名称——不检查动作描述是否正确
优化方向
- 用 embedding 做模糊匹配(而不是字符串匹配)
- 从知识库自动提取同义词扩展别名表
- 不只检查名称,还检查参数(组数、频率、持续时间)