Java for You AI Python实现声明级RAG证据覆盖率门禁

Python实现声明级RAG证据覆盖率门禁

数据中心机房

检索增强生成(RAG)常被误解成“把资料塞给模型就不会胡说”。实际风险在最后一公里:模型可能拿一段旧条款支持新结论,或把两个来源拼成一个看似合理的回答。解决办法不是再写一条“请诚实”的提示词,而是让模型输出候选声明与来源 ID,再用确定性代码逐条检查。这样,界面能清楚显示“已证实”“资料过期”还是“缺证据”。

OpenAI Structured Outputs 文档提供让输出贴合 JSON Schema 的路径;本文先展示不依赖密钥的本地门禁。线上接入时,把模型的结构化结果喂给 verify,而不是直接展示模型文本。

mermaid diagram

环境与完整代码

Python 3.10+ 无第三方依赖,保存为 citation_gate.py,运行 python citation_gate.py。本次在本机 Python 3.9.6 运行,两个断言通过;真实模型未被调用。

from datetime import date, timedelta

SOURCES = {
    "policy-2026": {"text": "报销上限为2000元", "updated": date(2026, 10, 1)},
    "legacy-2024": {"text": "旧流程需纸质单", "updated": date(2024, 1, 1)},
}

def verify(claims: list[dict], today=date(2026, 10, 8)) -> list[dict]:
    result = []
    for claim in claims:
        ids = claim.get("source_ids", [])
        if not ids:
            result.append({"claim": claim.get("text"), "status": "BLOCK", "reason": "没有来源"}); continue
        found = [SOURCES.get(i) for i in ids]
        if None in found:
            result.append({"claim": claim["text"], "status": "BLOCK", "reason": "来源ID不存在"}); continue
        if any(today - s["updated"] > timedelta(days=365) for s in found):
            result.append({"claim": claim["text"], "status": "REVIEW", "reason": "来源超过一年"}); continue
        if not any(claim["text"] in s["text"] for s in found):
            result.append({"claim": claim["text"], "status": "BLOCK", "reason": "来源未覆盖该声明"}); continue
        result.append({"claim": claim["text"], "status": "ALLOW", "reason": "证据覆盖且新鲜"})
    return result

good = [{"text": "报销上限为2000元", "source_ids": ["policy-2026"]}]
bad = [{"text": "可免审付款", "source_ids": ["legacy-2024"]}]
assert verify(good)[0]["status"] == "ALLOW"
assert verify(bad)[0]["status"] == "REVIEW"
print(verify(good) + verify(bad))

预期结果是一条 ALLOW 和一条 REVIEW。关键规则是“声明级覆盖”而非“回答末尾挂一个链接”;生产环境还要做语义蕴含检查、版本化索引和来源权限过滤。

常见错误:只引用最相似文档却不检查是否支持结论;混用不同生效日期的政策;把内部文档 ID 直接暴露给无权限用户;相信模型自己判断新鲜度。该方式适合制度问答、知识库助手和客服草稿,不适合在缺少权威材料时假装能给出事实答案。工程化时把 ALLOW/REVIEW/BLOCK 映射为 UI 徽标与人工队列。5分钟练习:新增“来源必须属于当前部门”的字段检查。

不要把引用做成装饰

有效引用至少有三个粒度:文档级证明“来自哪里”,段落级证明“依据在哪一段”,声明级证明“这句话由哪条材料支撑”。知识库更新时,索引和来源版本应一起更新;否则旧向量仍能召回,却不再代表现行规则。对于金额、期限、资格这类高风险声明,可以让系统在缺证据时只展示相关原文,不生成结论。还应监控被拦截的原因:如果大量回答因“来源过期”进入 REVIEW,问题通常在内容治理而非提示词。上线前选二十个真实问题,让业务负责人逐句判断引用是否足够;把错例加入回归集,才能知道一次模型升级是否悄悄降低了证据质量。

官方文档:Structured model outputs。你会把“无法给出处”显示为拒答,还是降级为待核实草稿?

关注「蜗牛聊AI」,一起看懂技术变化背后的真正机会。


本文首发于 java4u.cn,转载请注明出处。

本文由 java4u.cn 发布,可自由转载、引用,但需署名作者且注明文章出处(作者:白色蜗牛,出处:java4u.cn)。如转载至微信公众号,请在文末添加作者公众号二维码。 https://java4u.cn/ai/3085.html

作者: 蜗牛

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

联系我们

公众号:蜗牛互联网

在线咨询: QQ交谈

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部