AI 工程基础体系 · 第 93/100 篇。内容覆盖机器学习、深度学习与生成式 AI;模型、数据、评测、权限和成本会作为同一生产系统处理。
RAG 引用与溯源:证据定位、忠实度、冲突和可验证回答
检索增强生成(Retrieval-Augmented Generation,RAG)把生成模型的参数记忆与外部、可检索的知识结合起来。原始 RAG 论文将知识表示为两部分:参数化记忆 ,即模型自身的参数;非参数化记忆,即可由检索器访问的文档集合。给定问题 ,系统先检索文档,再根据问题和文档生成答案 。
但“检索到了文档”不等于“答案有依据”,“给出了链接”也不等于“引用可验证”。一个生产级 RAG 系统至少要回答四个不同问题:
- 证据定位:答案中的具体断言由文档的哪一段支持?
- 忠实度:答案是否只表达了证据能够支持的内容?
- 冲突处理:多个来源不一致时,系统如何识别、解释和决策?
- 可验证回答:用户能否沿着稳定的引用回到原始证据,并重新检查推理?
这四个问题分别对应事实连接、生成约束、知识治理和用户验证。它们不能通过“在答案末尾附几个文档链接”统一解决。
一、先区分四个容易混淆的概念
1. 检索结果不是证据
检索结果是检索器返回的候选文档或文本块。它说明“系统认为这些内容可能相关”,不说明这些内容已经支持了答案。
例如,问题是:
公司的远程办公政策是否允许每周三天在家办公?
检索器返回了一篇包含“远程办公”“每周”“办公地点”等词的文档,但其中实际内容可能是:
远程办公申请需要直属经理审批。具体天数由各部门另行规定。
这篇文档与问题相关,却不能支持“允许每周三天”这一断言。相关性是检索属性,支持关系是证据属性。
2. 引用是答案中的可见指向
**引用(citation)**是答案中指向来源的标记,例如 [S1]、文档 URL、页码或段落编号。它是面向读者的输出结构,通常回答“这句话来自哪里”。
引用的最小要求是:
- 能唯一定位来源;
- 来源对用户可访问,或系统明确说明访问限制;
- 引用范围足够精确,不能用一整篇文档掩盖具体支持位置;
- 引用和断言之间存在明确的支持关系。
因此,引用不是装饰,也不是检索结果的自动转发。引用必须绑定到答案中的一个或多个可判定断言。
3. 溯源是从输出回到数据生命周期
**溯源(provenance)**描述一条信息从原始来源进入系统、被处理、被检索、被生成并最终出现在回答中的完整链路。
一条完整溯源记录通常包括:
原始文件
-> 文件版本和哈希
-> 解析结果
-> 清洗或 OCR 结果
-> 分块结果
-> 向量或倒排索引
-> 检索请求和排序结果
-> 被选中的证据片段
-> 答案断言
-> 展示给用户的引用
引用是溯源链的一个用户可见投影;溯源本身还要记录处理过程、版本、权限、时间和转换关系。
4. 忠实度不是语言流畅度
**忠实度(faithfulness)**指生成答案中的断言是否能够由给定证据推出。它不同于:
- 相关性:答案是否回答了问题;
- 正确性:答案是否符合现实世界;
- 流畅度:答案是否自然易读;
- 引用完整性:重要断言是否都有引用。
一个答案可能语言流畅、引用齐全,却把证据没有说过的条件补了进去,因此忠实度仍然很低。
二、RAG 的核心数据流:检索、生成和引用是三条不同的路径
一个可验证的 RAG 系统可以抽象为以下流程:
flowchart LR
A[用户问题] --> B[问题规范化]
B --> C[检索器]
C --> D[候选证据片段]
D --> E[重排与权限过滤]
E --> F[证据包]
F --> G[生成模型]
G --> H[答案断言]
H --> I[断言-证据对齐]
I --> J{验证通过?}
J -- 是 --> K[答案与精确引用]
J -- 否 --> L[降级: 改写、补检索或拒答]
R[原始文档] --> S[解析/OCR]
S --> T[分块]
T --> U[索引]
U --> C
R --> V[版本、权限、哈希、时间]
V --> E
这里有三个容易被错误合并的阶段:
- 检索阶段产生候选证据;
- 生成阶段根据候选证据产生自然语言;
- 验证阶段检查每个断言是否确实由证据支持。
仅执行前两个阶段,就得到普通 RAG;执行第三个阶段,才有机会得到可验证回答。
检索器可以使用稀疏检索、稠密向量检索或混合检索。稀疏检索依赖词项匹配,适合专有名词、错误码和精确术语;稠密检索使用模型将问题和文本映射到向量空间,适合语义改写;混合检索将二者的候选合并。无论采用哪种检索方式,检索分数都只是排序信号,不是事实证明。
在原始 RAG 形式中,检索器从文档集合 中选择若干文档,生成模型再建模:
其中:
- 是用户问题;
- 是候选文档或文本块;
- 是检索器对文档相关性的估计;
- 是生成模型基于问题和证据生成答案的概率;
- 是检索器返回的前 个候选。
这个公式表达的是“检索文档有助于生成”,并没有自动表达“生成答案中的第 2 句必须由第 3 个文档的第 5 行支持”。因此,原始 RAG 机制本身不提供引用保证。引用、证据定位和忠实度验证需要额外的系统设计。
三、证据定位:从文档级链接细化到可复现的文本范围
1. 为什么“引用整篇文档”不够
假设系统回答:
退款申请必须在购买后 30 天内提交。[S1]
而 [S1] 只是一个 20 页 PDF 的链接。用户无法快速知道:
- “30 天”出现在哪一页;
- 这个期限针对所有商品还是某一类商品;
- 是否存在会员、地区或支付方式例外;
- 系统引用的是当前版本还是旧版本。
文档级引用可以作为导航,但不能单独作为强证据。对于关键事实,应尽量提供段落、页码、表格行、章节标题或字符范围。
2. 证据定位的最小数据模型
可以为每个可引用片段建立稳定标识:
{
"source_id": "policy-refund",
"document_version": "sha256:abc123...",
"uri": "https://example.com/policies/refund.pdf",
"title": "退款政策",
"published_at": "2025-01-10",
"effective_from": "2025-02-01",
"locator": {
"page": 3,
"section": "2.1 申请期限",
"char_start": 1840,
"char_end": 1976
},
"text": "退款申请应在购买日起 30 个自然日内提交……",
"access_policy": "tenant:acme"
}
其中最重要的不是字段数量,而是定位稳定性:
source_id标识逻辑来源;document_version防止同一 URL 内容更新后引用漂移;locator说明页面、章节或字符范围;text保存当时实际用于生成的证据快照;access_policy保证用户只能看到自己有权访问的内容。
只保存 URL 是不够的。URL 可能指向动态页面,页面内容也可能在回答生成后发生变化。
3. 分块会改变证据边界
分块(chunking)是把长文档切成检索单元。分块过大,会增加无关内容和上下文成本;分块过小,会拆开条件、例外和定义。
下面的文本如果按句子简单切分,就可能丢失条件关系:
普通用户可以申请退款。若商品已下载,则不适用本条。
第一块会错误地看起来像“所有普通用户都可以退款”,而真正的规则需要同时读取第二句。
因此,一个证据片段不应只包含关键词,还应尽量包含:
- 适用主体;
- 操作或事实;
- 时间条件;
- 例外;
- 否定词;
- 定义和指代对象。
分块系统最好同时保留父文档、章节路径和相邻块关系。检索时可以用小块提高定位精度,再把同一章节的上下文补回生成上下文,但最终引用应指向实际支持断言的最小范围,而不是盲目引用补回的整个章节。
4. 表格、图片和 OCR 是定位难点
PDF 中的视觉顺序不一定等于文本抽取顺序。一个表格可能被抽取为:
套餐 A 套餐 B 价格 100 200
如果系统没有保留行列关系,模型可能把套餐 A 的价格配给套餐 B。图片中的流程图、扫描件中的否定词和脚注也可能在普通文本抽取中丢失。
因此,表格和图片证据应保留结构化定位信息,例如:
{
"type": "table_cell",
"page": 5,
"table": 1,
"row": "套餐 B",
"column": "月费",
"value": "200 元"
}
OCR 结果还应记录置信度和原始图像位置。低置信度 OCR 不应被当作与原生文本同等级别的证据,尤其是数字、日期、单位和“不”等决定性词语。
四、从证据到断言:忠实度的形式化判断
1. 把答案拆成可验证断言
自然语言句子经常包含多个事实。例如:
该接口从 2025 年 2 月开始收费,免费额度是每月 10,000 次,并且超出后会自动扣费。[S1]
这句话至少包含三个断言:
- :收费开始时间是 2025 年 2 月;
- :免费额度是每月 10,000 次;
- :超出额度后会自动扣费。
如果 [S1] 只支持 和 ,那么整个句子虽然只有一个引用,仍然是不完整甚至误导的。工程上应先做断言分解,再做断言到证据的映射:
定义支持关系:
只有在每个重要断言 至少有一个足够强的证据 时,答案才满足基本忠实度要求。
2. “证据蕴含断言”而不是“证据和断言很像”
忠实度要求的是:
即证据 能够蕴含断言 。它不是简单的向量相似,也不是关键词重叠。
例如:
证据:退款申请应在购买日起 30 个自然日内提交。
断言:用户可以在购买后 30 天内申请退款。
在没有其他例外条件的前提下,二者大体等价。
但下面的改写就超出了证据:
证据:退款申请应在购买日起 30 个自然日内提交。
断言:所有用户都可以无条件在购买后 30 天内获得退款。
新增的“所有用户”“无条件”“获得退款”都没有被证据支持。证据只规定申请期限,不保证审核结果。
3. 量词、模态和时间是最常见的忠实度破坏点
生成模型容易改变原文的逻辑强度:
| 证据中的表达 | 不能随意改成 |
|---|---|
| 可以申请 | 一定批准 |
| 通常需要 | 必须 |
| 可能导致 | 会导致 |
| 截至 2024 年 | 当前仍然 |
| 部分用户 | 所有用户 |
| 建议 | 要求 |
| 不支持 | 禁止所有替代方案 |
这些词改变了断言的模态、范围或时间。验证器至少应检查:
- 主体是否一致;
- 时间范围是否一致;
- 数值和单位是否一致;
- 否定是否一致;
- “可能、通常、必须、禁止”等模态是否被增强;
- 例外条件是否被删除。
4. 完整算例:一个有引用但不忠实的回答
证据集合如下:
E1:企业版用户每月包含 10,000 次 API 调用。
E2:超过包含额度的调用将按照价目表计费。
E3:教育机构客户可以申请折扣,具体折扣率由销售团队确认。
问题:
企业版超过免费额度后如何收费?教育机构有什么特殊政策?
模型回答:
企业版每月免费 10,000 次调用,超出后自动按标准价格扣费;教育机构可享受 20% 折扣。[E1][E2][E3]
逐条检查:
- “每月免费 10,000 次调用”是对 E1 的近似改写,但“免费”是否等价于“包含”要看计费语义,通常应写成“每月包含 10,000 次”更安全。
- “超出后按标准价格计费”由 E2 支持。
- “自动扣费”并未由 E2 明确支持。E2 只说“按照价目表计费”,可能还需要账单确认或支付流程。
- “教育机构可享受 20% 折扣”没有证据支持。E3 只说可以申请折扣,折扣率待确认。
更忠实的回答应是:
企业版每月包含 10,000 次 API 调用;超过该额度的调用将按照价目表计费。[E1][E2]
教育机构可以申请折扣,但具体折扣率需要由销售团队确认。[E3]
这个例子说明,引用存在并不能证明引用覆盖了句子中的所有语义成分。
五、引用覆盖率、忠实度和正确性必须分开评测
设答案包含断言集合 ,每个断言有重要性权重 。可以定义引用覆盖率:
它衡量“有多少重要断言被引用”,不衡量引用是否真的支持断言。
再定义忠实度:
其中 是系统提供给生成器的证据集合。这个指标关注答案是否超出了上下文证据。
还需要单独评估世界正确性:
因为证据本身可能过期、错误或恶意。一个答案可以“忠实地复述”一份错误政策,因此高忠实度不等于高事实正确性。
生产评测通常至少建立三类标注:
- 问题—证据相关性:返回的片段是否包含回答问题所需信息;
- 断言—证据支持性:每个断言是否被指定证据蕴含;
- 答案—真实标签正确性:答案是否符合经过治理的事实或人工参考答案。
如果把这三类指标合并成一个分数,故障来源会被掩盖。例如,检索失败和生成幻觉都可能表现为最终答案错误,但修复方法完全不同。
六、冲突不是检索噪声,而是知识系统中的一等状态
1. 冲突的几种来源
多个证据不一致,可能有不同原因:
- 时间冲突:旧政策与新政策并存;
- 范围冲突:一个来源针对企业客户,另一个针对个人客户;
- 地域冲突:不同国家或地区规则不同;
- 版本冲突:同一文档的草稿和正式版同时被索引;
- 权限冲突:用户能看到的内部文档与公开文档内容不同;
- 事实冲突:来源确实对同一条件给出不同结论;
- 抽取冲突:OCR、表格解析或分块过程改变了原意。
不能把冲突简单交给模型,让模型根据语言流畅度选择一个答案。模型可能偏向文本更长、位置更近或措辞更确定的来源,而不是权威来源。
2. 先判断是否真的在说同一个命题
两个证据只有在主体、条件、时间和谓词相同或可比时,才构成直接冲突。
例如:
E1:普通用户每月最多导出 10 个报表。
E2:企业版用户每月最多导出 100 个报表。
这不是冲突,而是不同主体条件下的两条规则。
相反:
E1:所有用户每月最多导出 10 个报表。
E2:企业版用户每月最多导出 100 个报表。
如果 E1 的“所有用户”确实包含企业版,二者就存在范围冲突。系统需要检查版本、层级和例外关系,而不是只比较数字。
3. 用来源治理信息处理冲突
可以为来源建立一个优先级函数:
其中:
authority表示来源权威性,例如正式政策高于讨论帖;effective_time表示规则生效时间;scope_match表示来源是否适用于当前用户、地区和产品;version表示版本状态,例如正式版高于草稿。
这个函数不一定要输出一个绝对分数,也可以使用分层规则:
- 先过滤用户无权访问的证据;
- 再过滤不适用的主体、地区和产品范围;
- 在有效时间内选择正式版本;
- 若仍有冲突,展示冲突并说明采用的来源;
- 无法安全判定时拒答或转人工确认。
4. 冲突回答应保留差异
错误做法:
根据相关文档,限额是 10 到 100 次,具体取决于情况。
这句话把冲突压扁成模糊范围,没有告诉用户“情况”是什么。
更好的回答是:
普通用户的月度导出上限为 10 个,企业版用户的上限为 100 个。公开文档没有说明企业版是否属于“所有用户”规则的例外,因此应以企业版合同或当前生效的产品政策为准。[E1][E2]
如果两个正式来源对同一主体、同一时间仍然给出不同规则,应明确说:
当前检索到的两份正式文档对企业版上限存在冲突:文档 A 规定为 10 个,文档 B 规定为 100 个。文档 B 的生效日期较新,因此本回答暂采用 100 个;在文档治理完成前,不应将该结论视为无条件确定。
这种回答的信息量更大,因为它暴露了决策依据和剩余不确定性。
七、可验证回答的结构:让用户能重新检查每个关键结论
一个可验证回答至少应将以下对象显式关联:
问题
-> 子问题
-> 断言
-> 证据片段
-> 来源版本和定位
-> 决策或推理步骤
-> 最终文字
对于简单事实,答案可以采用句末引用:
退款申请应在购买日起 30 个自然日内提交(《退款政策》v2025-02,第 3 页,第 2.1 节)。
对于包含多个条件的回答,更适合使用断言分组:
- 申请期限:购买日起 30 个自然日内([E1])。
- 适用范围:仅适用于未下载商品;已下载商品不适用([E1])。
- 审核结果:来源只规定申请期限,没有保证申请一定获批。
最后一句很重要。它不是额外事实,而是对证据边界的声明,可以防止用户把“允许申请”理解成“必然批准”。
引用定位的优先级
在不同数据类型中,定位方式不同:
- 网页:稳定 URL、页面标题、章节、段落文本;
- PDF:文件版本、页码、章节、文本片段;
- 表格:文件版本、表名、行键、列名、单元格;
- 数据库:查询版本、表、过滤条件、快照时间;
- API:接口版本、请求参数摘要、响应时间和响应哈希;
- 图片或扫描件:页码、图像区域、OCR 文本和 OCR 版本。
引用必须绑定到回答时使用的快照。如果系统只保存了实时 URL,用户稍后打开页面看到的内容可能已经不同,验证就失去了可重复性。
“引用”不能泄露权限外信息
引用生成必须在权限过滤之后进行。一个常见错误是:
- 检索器找到包含机密信息的文档;
- 生成器使用了该文档;
- 最终答案隐藏正文,只展示内部文档标题或 URL。
即使没有直接泄露机密文本,文档标题、路径、段落摘要也可能泄露敏感信息。权限控制应作用于检索候选、上下文拼接、引用展示和日志,而不是只作用于最终答案。
八、一个可运行的最小引用验证示例
下面的 Python 示例不调用外部模型,而是演示一个最小的“证据片段—断言—引用”检查流程。它能验证引用是否存在、定位是否有效、引用文本是否与来源快照一致;它不能替代语义蕴含判断。
from dataclasses import dataclass
from typing import List, Dict
@dataclass
class Evidence:
evidence_id: str
source_id: str
version: str
page: int
section: str
text: str
@dataclass
class Claim:
claim_id: str
text: str
evidence_ids: List[str]
evidences = [
Evidence(
evidence_id="E1",
source_id="refund-policy",
version="2025-02-01",
page=3,
section="2.1 申请期限",
text="退款申请应在购买日起 30 个自然日内提交。"
),
Evidence(
evidence_id="E2",
source_id="refund-policy",
version="2025-02-01",
page=3,
section="2.2 下载商品",
text="已下载的数字商品不适用本退款条款。"
),
]
claims = [
Claim(
claim_id="C1",
text="退款申请应在购买日起 30 个自然日内提交。",
evidence_ids=["E1"]
),
Claim(
claim_id="C2",
text="已下载的数字商品不适用本退款条款。",
evidence_ids=["E2"]
),
Claim(
claim_id="C3",
text="符合期限的退款申请一定会获批。",
evidence_ids=["E1"]
),
]
def validate_claims(claims: List[Claim], evidences: List[Evidence]) -> None:
evidence_map: Dict[str, Evidence] = {
evidence.evidence_id: evidence for evidence in evidences
}
for claim in claims:
if not claim.evidence_ids:
print(f"{claim.claim_id}: FAIL - 没有引用")
continue
for evidence_id in claim.evidence_ids:
evidence = evidence_map.get(evidence_id)
if evidence is None:
print(
f"{claim.claim_id}: FAIL - 引用 {evidence_id} 不存在"
)
continue
if not evidence.text.strip():
print(
f"{claim.claim_id}: FAIL - 引用 {evidence_id} 没有证据文本"
)
continue
print(
f"{claim.claim_id}: PASS - "
f"{evidence.source_id} v{evidence.version}, "
f"第 {evidence.page} 页 / {evidence.section}"
)
validate_claims(claims, evidences)
预期输出类似:
C1: PASS - refund-policy v2025-02-01, 第 3 页 / 2.1 申请期限
C2: PASS - refund-policy v2025-02-01, 第 3 页 / 2.2 下载商品
C3: PASS - refund-policy v2025-02-01, 第 3 页 / 2.1 申请期限
这里 C3 被标记为 PASS,恰好说明了结构校验的边界:它有一个存在的引用,定位也有效,但 E1 没有蕴含“一定会获批”。因此,生产系统还需要语义验证器或人工评测来判断:
这个语义验证器可以使用自然语言推理模型、规则系统、结构化政策引擎或人工标注。模型判定结果也应保留置信度和“无法判断”状态,不能把低置信度强行变成通过。
实际生成时,可以让模型先输出结构化结果,再渲染为用户文本:
{
"claims": [
{
"claim_id": "C1",
"text": "退款申请应在购买日起 30 个自然日内提交。",
"evidence_ids": ["E1"],
"support": "entailed"
},
{
"claim_id": "C2",
"text": "已下载的数字商品不适用本退款条款。",
"evidence_ids": ["E2"],
"support": "entailed"
}
],
"uncertainties": []
}
结构化中间结果的价值在于:引用完整性、权限校验、冲突检查和答案渲染可以分开实现。若直接让模型生成最终 Markdown,系统很难可靠判断一句话中有几个断言、每个断言对应哪些证据。
九、失败路径:引用正确但答案仍然不可验证
1. 检索失败
问题中的关键实体没有进入候选证据,模型可能凭参数记忆回答。表现通常是:
- 引用与问题只有主题相关性;
- 关键数字、日期和限定词没有来源;
- 答案使用“通常”“一般来说”掩盖证据缺失。
诊断方法是检查检索结果中是否存在包含答案核心实体的片段,并查看问题改写是否丢失了条件。修复可以包括混合检索、查询扩展、实体识别、按字段过滤或提高召回深度,但提高 top_k 只能增加候选,不会自动提高忠实度。
2. 上下文中有证据,但模型忽略证据
这是典型的生成忠实度问题。模型可能选择训练记忆中更熟悉的规则,或者在长上下文中忽略后部证据。
诊断时应比较:
- 最终断言与证据文本;
- 证据在上下文中的位置;
- 多份来源是否冲突;
- 生成提示是否明确要求“无法从证据得到时拒答”。
可以使用证据包而不是原始检索列表:为每段证据附加来源、时间、适用范围和唯一 ID,并要求模型只引用证据包中的 ID。这个做法能降低引用伪造,但不能证明语义支持关系。
3. 引用被错误绑定
模型可能生成正确事实,却把引用标到了相邻段落;也可能把一条引用放在包含多个不同事实的长句末尾。
诊断应逐断言检查引用,而不是逐句检查。修复方法包括:
- 限制一个句子只表达一个主要事实;
- 要求每个断言拥有独立证据 ID;
- 引用渲染器根据结构化断言自动生成,而不是让模型自由编写链接;
- 对引用位置和证据文本做回归测试。
4. 证据已经过期
答案可能忠实复述旧版本,但用户需要的是当前规则。这个问题不是生成幻觉,而是知识库时间治理失败。
每次检索都应考虑:
其中 是回答时间或问题指定的历史时间。若问题问“现在的政策”,应优先选择当前生效版本;若问题问“2023 年当时的规则”,则不能简单使用最新文档。
5. 引用本身不可访问
如果答案引用了内部 URL、过期临时链接或权限外资源,用户无法验证。系统应在返回前检查:
- 引用是否可以被当前用户访问;
- URL 是否过期;
- 版本是否仍可读取;
- 是否需要脱敏后的公开快照;
- 是否必须显示“该来源仅对有权限用户可见”。
不可访问的来源可以保留在审计日志中,但不能假设用户能够据此完成验证。
十、冲突、拒答和不确定性应成为正常输出
可验证回答不要求系统对所有问题都给出确定结论。至少应有三种结果:
- 支持:证据足以推出断言;
- 不支持:检索到的证据不足以推出断言;
- 冲突或不确定:存在多个无法安全统一的结论。
推荐的拒答不是简单的“我不知道”,而是说明缺口:
当前文档只说明超过额度后按价目表计费,没有给出具体单价,因此无法从现有证据计算本月费用。需要提供调用次数、计费周期和当前价目表版本。
这种回答仍然是可验证的,因为它明确了已知事实、未知变量和继续验证所需的信息。
当用户要求系统进行计算时,也要区分“证据中的事实”和“系统推导的结果”。例如:
证据:
- 每月包含 10,000 次调用;
- 超出部分每次 0.01 元。
用户调用量:12,500 次。
推导:
超出量 = 12,500 - 10,000 = 2,500
费用 = 2,500 × 0.01 = 25 元
最终回答应标记:
按当前价目表计算,超出部分为 2,500 次,预计费用为 25 元。[E1][E2]
这是根据调用量和单价推导的结果,不是文档中的原文金额。
这样用户可以分别核查输入证据和算术步骤。
十一、在生产系统中同时管理模型、数据、权限和成本
引用与溯源会增加数据结构、存储、验证和推理成本,因此不能只在提示词层面实现。
数据生命周期
原始文档应有不可变版本或内容哈希。重新解析、OCR、分块和索引时,应记录处理器版本。否则,同一个 source_id 可能对应不同文本,导致历史答案无法重现。
权限生命周期
权限过滤应尽量在检索前或检索排序过程中完成,而不是检索后才隐藏结果。若模型已经读到无权内容,再删除引用并不能撤销信息泄露。
模型生命周期
不同模型可能产生不同的断言拆分、引用绑定和冲突选择。答案日志应保存模型版本、提示模板版本、检索器版本、证据 ID 和生成时间。这样才能区分“文档变了”“检索变了”和“模型行为变了”。
成本控制
增加 top_k、保留更长上下文、运行语义验证器和生成多次候选都会增加成本。可以采用分层策略:
- 先用低成本规则检查引用存在、版本和权限;
- 对包含数字、时间、否定和高风险操作的断言进行重点验证;
- 对低置信度或冲突回答进入更强模型或人工审核;
- 对高频稳定问题缓存“问题—证据版本—答案”组合。
缓存不能只按问题文本命中,还应把知识版本、权限范围和有效时间纳入缓存键。否则政策更新后,系统可能继续返回带有旧引用的答案。
十二、如何设计针对引用与忠实度的测试集
普通问答测试集通常只看最终答案是否正确,不足以定位 RAG 问题。应为每个问题保存:
问题
期望断言
必要证据片段
不应使用的相似片段
适用主体、地区和时间
冲突来源
允许的拒答条件
测试样例至少应覆盖以下情况:
- 证据直接给出答案;
- 证据需要跨两个片段合并;
- 相关文档存在但没有答案;
- 证据包含例外条件;
- 两个版本的政策冲突;
- 表格中相邻列容易错配;
- 证据中包含否定词;
- 用户无权访问最相关文档;
- 问题要求历史时点;
- 答案需要进行简单计算。
评测结果最好输出断言级记录:
C1:支持,引用 E1,定位有效
C2:未覆盖,无引用
C3:引用 E2,但证据不蕴含
C4:与 E3 冲突,采用 E4,理由是版本更新
这种结果比一个总分更适合工程诊断,因为它能直接指向检索、分块、生成、权限或版本治理中的具体故障。
十三、与官方 RAG 实现的关系
原始 Retrieval-Augmented Generation 论文说明了如何将外部检索记忆接入生成模型,但论文中的检索—生成概率模型不等价于引用系统。若需要向量存储、文档导入、检索和上下文拼接等产品化能力,应结合具体平台的官方文档,例如 OpenAI Retrieval Guide。
使用任何具体 API 时,都应把以下能力分开确认:
- API 是否返回原文片段,还是只返回文档标识;
- 是否返回稳定的文件、块或段落定位;
- 检索结果是否包含分数、排序和过滤信息;
- 权限过滤发生在检索前还是应用层;
- 文件更新后旧版本是否保留;
- 返回的 URL 是否稳定、是否需要重新签名;
- 当前 SDK 和接口版本是否支持所需字段。
平台提供的检索能力可以减少索引和召回工作,但通常不会自动保证“每个生成断言都被证据支持”。引用渲染、冲突处理、版本治理、权限验证和断言级评测仍然属于应用系统责任,除非具体产品文档明确给出相应保证。
结语:把回答从“像是正确”变成“可以检查”
RAG 的核心价值不是让模型在回答末尾附加链接,而是让生成过程建立在可访问、可定位、可追踪的外部证据上。
一个可靠的引用系统应当:
- 把文档版本、处理过程和证据范围保存为溯源链;
- 把答案拆成断言,而不是把整段自然语言视为不可分割整体;
- 判断证据是否蕴含断言,而不是只比较文本相似度;
- 区分相关性、忠实度、正确性和引用覆盖率;
- 对时间、范围、权限和版本冲突显式建模;
- 在证据不足时说明缺口、降低确定性或拒答;
- 让用户能够从每个关键结论回到稳定的原始证据。
当检索、生成和验证被分别建模后,RAG 才不只是“搜索后让模型总结”,而是一个具有证据边界、版本状态、冲突策略和审计能力的知识系统。
系列导航与关联阅读
- 系列入口:AI 工程完整学习路线:从机器学习与 Transformer 到 RAG、Agent 和生产治理
- 上一篇:RAG 上下文压缩:去重、摘要、证据选择与信息损失
- 下一篇:RAG 增量索引:变更捕获、版本、删除、重嵌入和一致性
官方资料
本文依据研究论文、标准组织与主流框架官方文档重新梳理;正文、示例与工程清单由 WR BLOG 编写。

评论
0 条讨论