AI 工程基础体系 · 第 20/100 篇。内容覆盖机器学习、深度学习与生成式 AI;模型、数据、评测、权限和成本会作为同一生产系统处理。
RAG 权限与评测:ACL、版本、缓存、忠实度、无答案和删除
RAG(Retrieval-Augmented Generation,检索增强生成)不是“向量数据库加一个大模型”。它是一条把数据摄取、解析、切块、索引、检索、重排、上下文组装、生成和引用连接起来的生产流水线。原始 RAG 论文将外部非参数记忆与生成模型结合起来;在工程实现中,检索结果还必须同时满足权限、版本、生命周期和可审计性要求。
如果这些条件没有被纳入同一个系统,常见故障并不是模型“回答得不够好”,而是:
- 用户看到了自己无权访问的文档;
- 文档已更新,但回答仍来自旧版本;
- 文档已删除,向量库或缓存仍然召回它;
- 模型给出了一段语气肯定、但上下文没有支持的内容;
- 正确答案不在知识库中时,模型编造了答案;
- 评测集和线上权限分布不一致,离线指标很好,线上事故频发。
下面把这些问题放在同一条数据流中分析。
1. 先定义 RAG 的对象和信任边界
设文档集合为 ,每个文档 至少包含:
其中:
id:稳定的逻辑文档标识;tenant:租户或数据域;content:原始内容或规范化内容;acl:访问控制列表;version:内容版本;status:有效、撤销、删除、隔离等状态;embedding:由内容版本计算出的向量。
一个查询请求还包含用户身份和当前权限:
因此,合法的候选集合不是全部文档,而是:
这里的 Allow 是授权函数,而不是模型判断。例如:
实际系统通常还要处理显式拒绝、继承权限、部门边界、时间条件和文档密级。授权规则必须由确定性代码执行,不能把“请只使用有权限的内容”作为唯一安全措施。
1.1 RAG 的正确数据流
一个较完整的请求路径如下:
flowchart LR
U[用户请求] --> I[身份认证]
I --> A[构造授权上下文]
A --> Q[查询改写/嵌入]
Q --> R[带 ACL 和版本约束的检索]
R --> F[重排与过滤]
F --> C[上下文、版本和引用组装]
C --> G[生成模型]
G --> V[忠实度/引用/安全校验]
V --> O[答案或无答案]
D[原始文档] --> P[解析与切块]
P --> E[嵌入]
E --> X[索引]
D --> M[元数据、ACL、版本、删除状态]
M --> X
关键路径是:授权上下文必须在检索前形成,并进入检索条件;生成后的检查只能降低风险,不能修复已经发生的越权检索。
例如,先从全库召回 20 个结果,再在应用层过滤掉无权文档,仍可能产生以下问题:
- 检索器、重排器或日志已经处理过受限内容;
- 无权文档影响了查询改写或上下文截断;
- 缓存把另一个用户的结果返回给当前用户;
- 过滤后上下文为空,但模型仍根据提示或参数记忆作答。
因此,ACL 过滤至少需要出现在检索候选生成之前或检索器内部。应用层还应再次校验,形成纵深防御。
2. ACL:权限不是一个字段,而是检索条件
ACL(Access Control List)是“哪些主体可以对对象执行哪些操作”的授权表示。在 RAG 中最重要的操作通常是 retrieve 或 read,而不是只控制最终页面是否展示。
2.1 文档级 ACL 与切块级 ACL
文档切成多个 chunk 后,权限通常应从父文档继承:
document_id = handbook-42
document_version = 7
acl = {group: engineering, action: read}
chunk-001 -> 继承 handbook-42 的 acl
chunk-002 -> 继承 handbook-42 的 acl
不要只把 ACL 存在父文档表中,却让向量索引中的 chunk 没有可过滤的权限信息。否则检索时无法高效且确定地排除无权 chunk。
如果一份文档内存在不同权限段落,则不能简单继承同一个 ACL,必须在切块前识别安全边界,或者为每个安全区间生成独立的对象。一个 chunk 不能混合“所有员工可见”和“仅财务可见”的文字,否则即使最终引用看起来合法,也可能通过相邻上下文泄漏秘密。
2.2 预过滤、后过滤和混合方案
设相似度函数为 ,需要返回 个结果。
正确的授权检索目标是:
而不安全的后过滤是:
两者不等价。考虑 :
| 文档 | 相似度 | 权限 |
|---|---|---|
| A | 0.99 | 无权 |
| B | 0.98 | 有权 |
| C | 0.97 | 有权 |
后过滤得到 {B},而正确结果应是 {B, C}。如果系统只取前 2 个再过滤,可能错误地认为“知识库没有足够证据”。
常见实现有三种:
- 索引过滤:向量数据库在 ANN 搜索时使用 tenant、ACL、状态和版本过滤器。效率通常较好,但要求索引支持这些谓词。
- 候选分区:按租户、数据域或安全级别建立独立索引。隔离强,但索引数量、更新和成本增加。
- 混合检索:先用结构化条件缩小候选,再做向量和关键词检索。适合 ACL 复杂、全文检索和向量检索并存的场景。
分区不能代替授权判断。用户权限可能随时间变化,用户组也可能变化;分区只是在数据层提供隔离,最终仍需根据请求时的身份状态授权。
2.3 ACL 的典型错误
错误一:把用户 ID 放进提示词。
用户是 alice。请不要回答她无权查看的内容。
模型并不具备可靠的授权执行能力。它可能引用上下文中已经存在的受限文字,也可能根据自身知识猜出敏感信息。
错误二:缓存只使用查询文本作为键。
cache["公司裁员计划"] = answer
这会把 Alice 的答案直接返回给 Bob。权限相关缓存键至少要区分租户、权限版本、检索版本和查询规范化结果。
错误三:把“可引用”误当成“可检索”。
有些系统允许模型读取文档,但禁止向用户展示原文;这仍需定义可执行的脱敏、摘要和字段级策略。只在输出阶段删除引用,不能保证模型没有从受限内容中生成事实。
3. 版本:回答必须知道自己基于哪一份知识
版本控制解决的不是 Git 式代码协作,而是回答与知识状态的一致性问题。至少要区分四种版本:
- 内容版本:文档正文从版本 6 变为版本 7;
- 解析版本:PDF 解析器或 OCR 结果发生变化;
- 索引版本:embedding 模型、chunk 策略或向量索引构建发生变化;
- 生成版本:提示模板、模型、重排器或安全策略发生变化。
一个 chunk 的可验证身份可以表示为:
其 embedding 也应记录:
如果只使用 doc_id,文档更新后可能出现旧 chunk 和新 chunk 共存,检索结果便无法解释。
3.1 版本更新的原子性
文档更新不能简单地按以下顺序异步执行:
1. 更新文档表
2. 删除旧向量
3. 写入新向量
在步骤 1 和 2 之间,系统可能检索到旧向量;在步骤 2 和 3 之间,系统可能完全检索不到文档;如果新向量写入失败,文档表和索引状态还会永久不一致。
更可靠的做法是使用索引代次(generation):
active_generation = 41
构建新版本时:
generation 42:
写入文档版本 7
写入全部新 chunk
校验数量、哈希、ACL 和索引可查询性
将 generation 42 标记为 ready
原子切换:
active_generation = 42
查询只读取当前活动代次。旧代次可以保留一段时间用于回滚,但不能继续被默认检索。
这是一种“发布后切换”模型。它的代价是需要额外存储和构建时间,但避免了半成品索引暴露给线上请求。
3.2 请求级一致性
在多副本系统中,用户刚修改权限或文档刚删除时,不同副本可能看到不同状态。可以给每次写入分配单调递增的水位线:
请求携带 required_watermark = w,检索副本只有在已应用到至少 时才服务该请求;否则等待、转发到主副本,或明确返回暂不可用。
如果业务不能接受等待,也必须定义可接受的陈旧窗口,例如“权限撤销最多 30 秒生效”。这不是模型指标,而是安全和一致性协议,应该写入系统契约。
4. 缓存:缓存的是带权限和版本的计算结果
RAG 常见缓存包括:
- 查询嵌入缓存;
- 检索候选缓存;
- 重排结果缓存;
- 上下文组装缓存;
- 最终答案缓存。
不同缓存的安全边界不同。
4.1 哪些结果可以跨用户复用
查询嵌入通常只依赖规范化文本和 embedding 模型版本,因此可以使用:
但检索结果依赖权限和数据状态,缓存键至少应包含:
其中 authz_snapshot 可以是权限集合的稳定摘要,而不是直接把完整 ACL 放进键中。
最终答案还依赖提示模板、模型、上下文、工具结果和语言设置:
如果答案中包含用户个性化信息,通常不应做跨用户共享缓存。
4.2 缓存失效不是“过期时间”一个问题
TTL 只能处理时间,不知道“某个文档刚被撤销”。因此需要事件驱动失效:
document handbook-42 version 6 -> version 7
|
+--> 删除/隔离相关检索缓存
+--> 删除旧上下文缓存
+--> 标记旧答案缓存不可用
+--> 推进权限或索引水位线
缓存命中后仍应做轻量状态校验。否则一个长 TTL 缓存可能绕过最新 ACL。
缓存污染也可能来自提示注入:如果把恶意文档内容生成的答案缓存为“可信答案”,后续请求即使上下文不同,也可能复用错误结果。缓存对象应记录来源文档 ID、版本、引用集合和安全检查结果,不能只保存一段字符串。
5. 忠实度:答案是否由上下文支持
忠实度(faithfulness)表示生成答案是否被提供给模型的上下文支持。它与“答案正确”不是同一个指标。
设上下文为 ,答案被拆成声明集合:
若某个声明 能由 蕴含,则记:
一个简单的声明级忠实度为:
其中 可以按声明重要性加权。实际评测可使用人工标注、规则匹配、自然语言推理模型或 LLM judge,但自动评判本身也会误判,关键样本仍需要人工复核。
5.1 忠实度、正确性和检索质量的区别
有四种典型情况:
| 检索上下文 | 模型答案 | 忠实度 | 外部事实正确性 |
|---|---|---|---|
| 含正确证据 | 正确回答 | 高 | 高 |
| 含正确证据 | 编造额外细节 | 低 | 部分或低 |
| 未含证据 | 模型凭参数记忆答对 | 低或不可判定 | 可能高 |
| 含错误文档 | 忠实复述错误文档 | 高 | 低 |
因此,RAG 评测至少要分解为:
- 检索召回:支持答案的文档是否进入候选;
- 检索精确性:召回结果中有多少是相关的;
- 忠实度:答案中的声明是否由上下文支持;
- 答案正确性:答案是否符合参考答案或事实;
- 引用正确性:引用是否真的支持对应声明;
- 拒答质量:无证据时是否拒答,有证据时是否避免误拒答。
5.2 完整算例
问题是:
工程师申请生产数据库只读权限需要什么审批?
知识库中有:
d1,版本 3:
生产数据库只读权限需要直属主管和数据 владельца 审批。
d2,版本 5:
生产数据库写权限需要安全团队审批。
正确检索上下文为 。模型回答:
只读权限需要直属主管和数据 владельца 审批,并且还需要安全团队审批。
将答案拆成两个声明:
- :需要直属主管和数据所有者审批;
- :还需要安全团队审批。
其中 被 d1 支持, 只在 d2 中出现,且 d2 讨论的是写权限。因此:
即使用户组织流程恰好也要求安全团队审批,这个回答在“基于给定上下文作答”的意义下仍不忠实,因为答案没有说明该结论来自哪条证据,且把写权限规则迁移到了只读权限。
5.3 引用不能只放在答案末尾
更可验证的输出是把声明与引用绑定:
{
"answer": "只读权限需要直属主管和数据所有者审批。",
"claims": [
{
"text": "只读权限需要直属主管和数据所有者审批",
"citations": [
{"document_id": "d1", "version": 3, "chunk_id": "d1-004"}
]
}
]
}
这样可以逐条检查引用是否支持声明,也能在文档版本删除或撤销后定位哪些答案缓存需要失效。仅在整段答案后附一个来源列表,无法判断每个句子是否被来源支持。
6. 无答案:没有证据时应当拒答
“无答案”有两种不同含义:
- 知识库无答案:所有有权限且有效的文档都没有支持该问题的内容;
- 用户无权获得答案:系统可能有相关文档,但当前用户不能确认其存在或内容。
第二种情况不能直接返回“文档存在但你无权访问”,因为这可能泄漏文档标题、数量或主题。对外可以统一返回:
当前可访问的知识中没有足够信息回答该问题。
但内部审计日志仍应区分“无证据”和“权限拒绝”。
6.1 拒答判定不是单一相似度阈值
设最高检索分数为 ,第二名为 ,支持声明的证据覆盖率为 ,权限过滤后的候选数量为 。可以定义一个拒答策略:
但这只是工程决策,不是普遍有效的数学定理。向量相似度通常未校准,不同问题长度、领域和 embedding 模型下分数不可直接比较。实际需要在带标签验证集上选择阈值,并测量:
- 覆盖率:多少问题系统愿意回答;
- 选择性风险:系统选择回答的问题中有多少是错误的;
- 误拒答率:其实有证据却拒答的比例;
- 误答率:无证据却给出实质答案的比例;
- 校准:模型或检索器给出的置信度是否与真实正确率匹配。
一个简单的二分类混淆矩阵如下:
| 实际情况 | 系统回答 | 系统拒答 |
|---|---|---|
| 有足够证据 | 真阳性 | 假阴性 |
| 无足够证据 | 假阳性 | 真阴性 |
在企业知识库中,假阳性通常比假阴性更危险:错误的肯定答案可能导致生产操作、合规判断或权限配置错误。
6.2 无答案示例和反例
问题:
2025 年第三季度新加坡办公室的差旅上限是多少?
检索结果只有:
d1:2024 年全球差旅政策
d2:2025 年美国办公室差旅政策
这两个结果可能语义相似,但都不能支持目标声明。正确输出应是无答案,而不是把美国政策或旧年份政策迁移到新加坡。
反例是:
2025 年第三季度差旅上限是多少?
如果系统把“2024 年政策”的相似度设为高于阈值,就可能输出一个过时数字。解决方法不是单纯提高阈值,还要把年份、地区等结构化约束纳入检索和证据判定。
7. 删除:从搜索结果消失不等于真正删除
删除操作至少有三个层次:
- 逻辑删除:线上查询不再返回对象;
- 索引删除:向量、倒排索引、缓存和派生 chunk 不再可查询;
- 物理删除:原文、备份、日志、临时文件和第三方处理副本按策略销毁。
不同法规和业务场景对物理删除的要求不同,不能笼统地声称“删除接口调用成功就完成了删除”。
7.1 删除状态机
可以把文档生命周期表示为:
stateDiagram-v2
[*] --> Active
Active --> Revoked: 权限撤销
Active --> Deleting: 删除请求
Revoked --> Deleting: 删除请求
Deleting --> Tombstoned: 写入墓碑并停止新摄取
Tombstoned --> Purged: 索引/缓存/副本清理完成
Deleting --> DeleteFailed: 某个派生系统失败
DeleteFailed --> Deleting: 重试或人工处理
**墓碑(tombstone)**是一个不可忽略的删除标记,通常包含:
document_id
deleted_at
delete_sequence
reason
retention_until
摄取任务和索引重建任务必须读取墓碑。否则会出现这种故障:
1. 文档 d 被删除
2. 当前向量被删除
3. 旧的离线备份恢复
4. 重建任务把 d 重新写入索引
墓碑可以阻止第 4 步,直到删除策略允许清除它。
7.2 删除必须覆盖派生数据
原文删除后,以下数据仍可能包含可识别内容:
- 解析后的纯文本;
- chunk 表;
- embedding;
- BM25 或倒排索引;
- 重排特征缓存;
- 查询结果缓存;
- 上下文缓存和答案缓存;
- 评测样本、调试日志和 tracing;
- 备份、复制副本和第三方 API 日志。
尤其要注意 embedding 不是“无法还原的安全摘要”。向量通常不能直接等价还原原文,但可能泄漏语义,且仍然是由受保护内容派生的数据。是否需要删除应由数据分类和合规要求决定,而不能依赖“向量看不懂”。
删除流程应具备幂等性:重复收到同一个删除事件不能报错或恢复数据。可用 delete_sequence 或事件 ID 去重,并为每个派生系统记录:
document_id = d42
delete_sequence = 1088
vector_index = applied
keyword_index = applied
cache = applied
backup = pending
只有所有必要系统达到规定状态,才能把删除请求标记为完成。
7.3 删除验证
验证不应只查询一次向量库。至少需要:
- 用原始标题、正文片段和同义改写查询;
- 检查向量索引和关键词索引;
- 检查热缓存和持久缓存;
- 检查当前活动索引代次;
- 检查新建索引不会重新摄取墓碑对象;
- 检查审计日志中没有不必要的原文残留。
如果系统采用最终一致性,需要记录删除延迟和最坏情况,而不是声称删除瞬时生效。
8. 把 ACL、版本、缓存、无答案和删除放进评测
单一的“回答准确率”无法覆盖这些风险。评测集中的每个样本至少应包含:
{
"query": "工程师申请生产数据库只读权限需要什么审批?",
"user": {
"tenant": "acme",
"id": "u-17",
"groups": ["engineering"]
},
"expected": {
"answerable": true,
"required_claims": [
"需要直属主管和数据所有者审批"
],
"forbidden_documents": ["hr-秘密-9"],
"required_citations": [
{"document_id": "d1", "version": 3}
]
}
}
测试集必须覆盖以下边界:
- 同一个问题由不同权限用户提出;
- 用户刚被撤销权限;
- 文档从旧版本更新到新版本;
- 文档被删除后重复查询;
- 有相似但年份、地区或权限不匹配的文档;
- 知识库完全没有答案;
- 检索到恶意提示注入文档;
- 多租户中出现相同标题和相同问题;
- 缓存命中与未命中两条路径;
- 索引切换发生在请求处理中。
8.1 检索指标
如果标注了支持答案的文档集合 ,检索结果为 ,则:
对 RAG 而言,还应测量:
AuthorizedRecall@k:只在当前用户有权文档中计算召回;UnauthorizedHitRate:结果中出现无权文档的比例,生产目标应为零;FreshnessViolationRate:召回文档版本低于请求要求的比例;DeletedHitRate:删除后仍被召回的比例,生产目标应为零;CitationCoverage:答案声明中有有效引用的比例。
权限泄漏即使只发生一次,也不能被整体平均指标掩盖,所以应同时报告最大风险、按租户分组的指标和每条越权样本。
8.2 端到端答案指标
对可回答问题,测量正确性、忠实度和引用准确性;对不可回答问题,测量拒答质量。一个简单的加权评估可以是:
这里的 不是固定标准,而是业务风险权重。例如医疗、财务和生产运维场景通常会给越权和幻觉更高权重。
不要把“LLM judge 给了 4 分”当成安全证明。评判模型可能看不出版本错误、权限错误或引用与声明之间的细微不匹配。权限、版本和删除应尽可能使用确定性断言:
assert result.document.tenant == request.tenant
assert allow(request.user, result.document.acl)
assert result.document.status == "active"
assert result.document.version >= request.required_version
语义质量则可以结合人工标注和模型辅助评估。
9. 一个最小的授权过滤示例
下面的 Python 代码不实现向量检索,而是展示检索结果进入上下文前必须经过的确定性检查。它可以直接运行,输入是候选 chunk,输出是当前用户可用的 chunk。
from dataclasses import dataclass
from typing import FrozenSet, List
@dataclass(frozen=True)
class User:
tenant: str
user_id: str
groups: FrozenSet[str]
@dataclass(frozen=True)
class Chunk:
document_id: str
version: int
tenant: str
groups_allowed: FrozenSet[str]
status: str
score: float
text: str
def authorized(user: User, chunk: Chunk, required_version: int) -> bool:
if chunk.tenant != user.tenant:
return False
if chunk.status != "active":
return False
if chunk.version < required_version:
return False
return bool(user.groups & chunk.groups_allowed)
def filter_candidates(
user: User,
candidates: List[Chunk],
required_version: int,
) -> List[Chunk]:
visible = [
c for c in candidates
if authorized(user, c, required_version)
]
return sorted(visible, key=lambda c: c.score, reverse=True)
if __name__ == "__main__":
alice = User("acme", "u-1", frozenset({"engineering"}))
candidates = [
Chunk("d-secret", 8, "acme", frozenset({"hr"}), "active",
0.99, "未公开的裁员计划"),
Chunk("d-public", 3, "acme", frozenset({"engineering"}), "active",
0.95, "生产数据库只读权限需要审批"),
Chunk("d-old", 2, "acme", frozenset({"engineering"}), "active",
0.94, "旧版审批规则"),
Chunk("d-other-tenant", 9, "other", frozenset({"engineering"}), "active",
0.93, "其他租户的内容"),
]
result = filter_candidates(alice, candidates, required_version=3)
print([(c.document_id, c.version) for c in result])
预期输出是:
[('d-public', 3)]
d-secret 因群组不匹配被拒绝,d-old 因版本过低被拒绝,d-other-tenant 因租户不同被拒绝。生产实现还需要处理显式拒绝、用户权限快照、字段级脱敏和索引层预过滤;这个示例不能替代数据库或向量引擎中的授权约束。
一个重要风险是:即使最终 result 经过了过滤,前面的候选生成器也可能把 d-secret 写入日志、重排服务或外部模型。安全边界应尽量前移到检索器内部,并对每个下游组件定义它是否允许接触原文。
10. 常见失败表现与诊断路径
10.1 用户刚失去权限,仍能看到旧答案
可能路径是:
权限服务已更新
↓
检索缓存未失效
↓
答案缓存命中
↓
请求没有重新执行 ACL
诊断时应同时检查:
- 请求使用的权限快照 ID;
- 检索缓存键是否包含权限版本;
- 答案缓存是否记录来源文档;
- 权限变更事件是否到达所有缓存;
- 是否存在绕过检索层的答案缓存。
修复方式不是简单缩短 TTL,而是让权限变更事件主动使相关缓存失效,并在缓存命中时验证权限水位线。
10.2 文档已经更新,回答仍引用旧版本
通常是旧 chunk 没有被删除,或者答案缓存没有关联版本。检查:
answer_id
-> context_hash
-> document_id + document_version + chunk_id
-> index_generation
如果链路中缺少任何一个版本字段,系统很难证明答案基于当前知识。对于高风险问题,宁可在版本水位线不足时暂时无答案,也不要静默使用旧知识。
10.3 无答案问题得到一个“听起来合理”的回答
检查三个分数:
- 授权后候选数是否为零;
- 最高相似度是否只是相对较高,而非经过校准;
- 答案声明是否能映射到引用 chunk。
如果候选为空却仍生成答案,说明生成路径没有强制经过 answerable 判断。生成模型应收到明确的结构化状态,例如:
{
"evidence_status": "insufficient",
"contexts": []
}
然后由程序或受约束的输出协议决定返回拒答,而不是只依赖自然语言提示。
10.4 删除后仍能被相似查询召回
这通常说明只删除了一个精确键,没有清理:
- 文档的所有 chunk;
- 旧版本;
- 其他索引;
- 查询结果缓存;
- 备用索引代次;
- 重建任务输入;
- 备份恢复源。
应通过文档 ID、内容哈希和版本集合执行删除,而不是只删除当前看到的一个向量 ID。
11. 生产取舍:安全保证与成本的边界
有些保证可以做成系统不变量:
- 不同租户的文档不能互相召回;
status != active的对象不能进入上下文;- 版本低于请求水位线的对象不能被使用;
- 删除墓碑之后不能被新索引重新摄取;
- 缓存命中不能绕过当前授权检查。
这些属于规范保证,应通过代码、索引约束、事件处理和自动化测试实现。
另一些是经验性策略:
- 取多少个 chunk;
- 相似度阈值设为多少;
- 是否使用 LLM judge;
- 多久刷新索引;
- 是否缓存最终答案;
- 忠实度低于多少就重新生成。
这些参数没有跨系统通用的正确值,必须在目标领域验证集上测量,并按模型、embedding、数据分布和业务风险重新校准。
成本也必须纳入设计。更严格的租户分区、实时权限过滤、双索引发布、删除确认和多轮忠实度检查都会增加存储、延迟和计算开销。但把权限检查、版本校验和删除清理放在事后补救,通常会把一次局部优化变成全链路事故。
12. 最小生产契约
一个可审计的 RAG 请求,至少应能回答以下问题:
这次请求是谁发起的?
属于哪个租户和权限快照?
使用了哪个索引代次?
召回了哪些文档、哪些版本?
每个文档当时是否有效且有权?
答案中的每个声明由什么引用支持?
是否因为证据不足而拒答?
请求完成后,相关缓存和删除状态是什么?
如果系统无法回答这些问题,就很难区分“模型质量问题”和“数据、权限、版本、缓存问题”。
RAG 的核心不是让模型在更多文本上生成更流畅的句子,而是让每个答案都满足一个可验证条件:
ACL 保证证据属于当前用户可见范围;版本保证证据不是过时状态;缓存保证复用不会绕过这些条件;忠实度保证答案没有超出证据;无答案机制保证证据不足时停止生成;删除机制保证已经撤销的数据不会从派生系统中重新出现。只有这几个条件同时成立,RAG 才能作为一个可控的生产知识系统运行。
系列导航与关联阅读
- 系列入口:AI 工程完整学习路线:从机器学习与 Transformer 到 RAG、Agent 和生产治理
- 上一篇:RAG 完整流水线:摄取、解析、切块、检索、重排、上下文和引用
- 下一篇:AI Agent 基础:状态机、计划、工具、循环、终止和人工确认
- 延伸:AI 安全工程:提示注入、数据泄漏、越权工具、模型供应链和红队
官方资料
本文依据研究论文、标准组织与主流框架官方文档重新梳理;正文、示例与工程清单由 WR BLOG 编写。

评论
0 条讨论