RAG 数据生命周期:解析、更新、删除与权限
让知识库不只「找得到」,还要「读得对、跟得上、删得净、看得合规」。前置:RAG 进阶已经解释召回与重排;本文管理被检索数据的一生,工程验收接到RAG 旗舰项目。
先从一份改过的报销制度说起
公司把报销期限从三十天改为十五天,文档管理员上传了新版。员工询问时,助手仍能给出条款、页码和链接,看起来证据齐全。
但引用来自旧块。另一名已经调离部门的同事仍能从缓存看到内部说明,管理员删除原文件也没用,因为向量索引和答案缓存还留着副本。
为什么检索排序都正常,系统却同时答错事实、越过权限?
因为索引不是原文件本身,而是带版本、来源和权限的派生副本。数据发生变化时,必须管理所有派生物的可见性;回答正确不能替代访问合法。
全景图:原件与派生物要有共同账本
图:先看③到④的通道,物理清理尚未结束,也必须阻止过期或越权副本进入上下文。
渐进拆解:图书馆换书,不只是重新排书架
把知识库想成图书馆:原件是馆藏,切块像摘录卡,索引像目录。原书撤架了,目录和摘录卡不能继续提供借阅;内部阅览资格取消了,也不能因为读者昨天借过就放行。这个类比只帮助建立「原件与副本」的关系,真正实施还需要可追踪标识和查询时检查。
① 解析质量先于向量质量
解析不是把文件后缀改成文本。双栏扫描件可能被读成左右交错的一句话,表格可能只留下数字却丢了列名,「十五」也可能被识别成「五十」。这些错误即使被检索准确命中,生成模型仍会认真总结错误资料,换更好的重排器无济于事。
验收按「分流 → 建验收集 → 失败隔离」三步走:
- 按原生文本、扫描件、表格密集文件分流,保存解析器及配置版本。
- 建立小型解析验收集,按下述四类内容核对。
- 关键单元格失败就隔离该文件、保留错误原因和原件定位,让管理员复核,不把坏解析静默入库。
四类核对的对象与重点:
- 普通段落:核对阅读顺序。
- 金额表:核对行列对应与单位。
- 跨页表:核对重复表头和续表关系。
- 页码引用:核对原件位置。
字符数不为零仅证明有输出,不证明语义完整。例如原件写「地区|住宿上限」,下一行是「甲地|三百元」。解析结果必须保留甲地与三百元的对应关系,不能把另一列交通补贴拼进来。
当前 Unstructured 文档区分 fast、hi_res、ocr_only 等策略,表格抽取与版面识别也有专门条件。它提醒我们,策略选择和格式有关,而不是越贵越万能;本文没有运行真实 OCR,不给这些策略编造准确率。向量化与切块的具体选择回看向量化基础与前置篇。
② 增量更新是发布协议,不是覆盖一个字段
给文档稳定的业务标识,内容版本与权限版本分开记;解析器、切块器和嵌入模型的版本也要能从批次清单追溯。每个块至少携带以下字段:
| 字段 | 作用 |
|---|---|
| 租户 | 划定数据边界,查询先按租户隔离 |
| 文档标识 | 稳定的业务标识,文档改名也不变 |
| 内容版本 | 与权限版本分开记,判定内容新旧 |
| 块标识 | 定位单个块;不能只用文件名加行号,插入一段后行号会整体漂移 |
| 原文位置 | 回指原件,供引用与复核 |
| 有效权限引用 | 查询时判定该块对此人是否可见 |
内容哈希适合判断输入是否改变,但相同文本的权限可能不同,不能据此跳过权限更新。一个可用的派生键包含文档标识、内容版本、变换版本及块序号,哈希作为完整性校验。文档改名而业务标识没变,应按同一文档更新,不凭路径变化复制一份长期存活的旧制度。
发布一个新版本走「暂存 → 验收 → 原子切换 → 回收」四步:
- 暂存:把新版所有块写进暂存集合。
- 验收:检查数量、解析质量、来源引用与权限字段。
- 原子切换:切换该文档的活动版本,查询只读活动版本。
- 回收:旧版随后回收。
跨向量库、关键词库与缓存没有天然共同事务,必须用发布清单或版本门控制可见性,不能先删旧版、再赌新版一定写成功。
消费内容更新事件时检查该文档的单调内容版本号,它不是删除、撤权等所有事件的全局顺序。同一版本重放应幂等,较旧内容晚到不能把新版覆盖回去;处理成功的游标在持久提交之后推进。嵌入模型变化通常需要重建相关向量,只有内容变化且变换版本不变时,才有安全复用未变块的空间。
③ 删除与撤权都要传播,但不是同一种操作
逻辑封读是立即停止使用,物理删除是随后清理副本。收到删除请求,先封读、再清理,两个完成点不能互相冒充:
| 对比项 | 逻辑封读 | 物理删除 |
|---|---|---|
| 立即效果 | 权威状态写墓碑、撤销可见性并增加失效版本,任何查询立即读不到 | 依次清理向量索引、关键词索引、块存储、检索缓存和答案缓存 |
| 存储 | 墓碑与删除状态写入权威存储,派生副本留待清理 | 移除索引、正文和权限,但不抹掉标识、版本与删除状态 |
| 恢复 | 本模拟不支持恢复或复用已删标识 | 真实系统若支持恢复,须另设独立授权入口与事件顺序协议,不能把版本加一冒充恢复授权 |
墓碑要保留到旧事件不可能重放,防止离线重建把被删文档复活;本模拟中它在 Store 存活期间永久保留。
普通发布不能覆盖墓碑,即便内容版本更高也不行:新版可能在删除前已排队,只是迟到。
缓存不能只以问题文本为键。租户、用户或权限集合版本、活动知识版本都会影响答案;缓存值还应保存所依赖的文档版本,便于定向失效。小系统可以用全局失效代数(用于标识缓存批次的计数器)加一并清缓存,简单但命中率下降;大系统可用文档到缓存项的反向依赖表,复杂度更高但影响范围更小。
删除索引不等于删除所有数据。对象存储、备份、审计日志、历史会话和下载副本有不同保留策略,须明确责任人与完成时限。已经发给用户的信息无法靠后台撤权收回,但新的回答、历史会话重新组装的上下文和共享链接必须重新检查,不再主动传播。
撤权可以不删正文、不重算向量,但必须更新权限状态并失效相关缓存。若索引权限同步要几分钟,而业务要求立即撤权,就需要同步拒绝清单或权威权限服务作为读路径防线;服务不可用时对受限资料拒绝读取,不能降级成无过滤查询。
④ ACL 继承到块,查询时仍要复核
ACL 是访问控制列表。目录允许财务组、文件另有明确限制时,应按源系统真实规则算有效权限,再投影到每个块,不能自创「父目录允许就全允许」的简化规则。跨租户分区必须先约束,缺少权限信息的块默认拒绝,不能被当成公共资料。
用户身份来自经过验证的会话,不从提示词里读取「我是管理员」。不能先把全库敏感文本传给外部重排服务,再在最终答案处删掉。
前过滤与后校验不是二选一,各拦一类问题:
| 对比项 | 前过滤 | 后校验 |
|---|---|---|
| 时机 | 检索前,在向量与关键词两路都加入授权过滤 | 候选进入重排、模型和日志之前 |
| 核对内容 | 授权范围 | 活动版本、墓碑及最新权限 |
| 作用与要求 | 解决候选范围 | 拦住同步滞后的陈旧索引;批量查询当前权威状态,避免每个块循环查库 |
校验与发送之间还有竞态:高敏系统可绑定授权快照或短租约,并在输出前复核;需要流式输出时,必须定义撤权后终止流的响应边界。
Azure AI Search 当前文档明确区分普通安全过滤和原生权限机制,并说明查询时使用已经同步到索引的权限元数据。部分能力处于预览,源权限改变到索引识别之间存在延迟。它是现实产品对这道边界的公开说明,不代表使用云服务就自动获得即时撤权保证。
动手:故意留下陈旧索引,看看还能不能读
小程序读者请在电脑浏览器打开下方链接下载,随后在电脑终端运行。下载完整生命周期实验,保存为 rag-lifecycle.py。Python 3 标准库即可运行,无需模型、数据库或密钥。它是内存模拟,不实现 OCR、真实向量检索和分布式事务,也省略租户、块标识与原文位置字段,目的是验证可见性条件。
python3 rag-lifecycle.py
脚本按五步验证:
- 先发布三十天制度,读一次填充缓存,再发布十五天制度。
- 故意换回旧索引,断言查询不能把旧内容交给用户。
- 恢复新索引后撤销一名用户权限,断言此人读不到、另一名仍读得到。
- 写删除墓碑,在物理索引仍存在时断言任何用户都读不到。
- 清理前后分别尝试发布旧版本、同版本及更高版本,全部拒绝且状态不变;清理后再注入旧索引也必须读不到。
预期输出以 PASS update, stale-version, revoke, delete, physical-cleanup 开头。每条断言都核对返回内容或空集合,不靠模型说「已删除」。把删除后的墓碑判断去掉,最后的读路径测试会失败,这是你应独立复现的变体;不要同时移除测试来让终端变绿。
核心可见性条件可以单独读懂,编号与全景图一致。
# ④可见性条件的独立示意改写,非下载脚本原文。
def visible(user, candidate, current):
return (not current["deleted"]
and candidate["version"] == current["version"]
and user in current["allowed"])
实验用全局失效代数与清空缓存保证简单可复现;这个计数器只管理本实例缓存批次,不是分布式事件时钟。脚本对同版本发布直接拒绝,生产事件消费者可以将已确认的同版本同载荷重放处理为幂等无操作。生产可换为按文档失效。它故意把旧索引留着以测试纵深校验,但不能据此宣布「生产删除完成」:物理清理、备份到期、并发撤权与跨服务失败恢复都需要各自的集成测试证据。
图:中间节点是读路径安全承诺,右边节点是清理承诺,应分别记录耗时与失败。
边界与取舍
全量重建适合小型低频知识库,增量发布适合高频变更和大量文档。前者可以少写事件协议,但仍需要活动版本切换与删除清单;后者节省计算,却增加乱序、重放和半成功的处理成本。不要为了几百份稳定文档先造复杂事件平台。
知识库里的「最新」也需业务解释。制度可以预先上传、下月生效,上传时间不能直接替代生效时间;查询旧报销单可能应使用当时有效版本。本文实验只实现当前版本可见,历史时点查询要增加有效时间区间与对应授权规则,不能悄悄放开全部历史块。
生命周期质量与检索质量应分账。命中率高而引用旧版本,修发布与失效;权限正确而相关证据搜不到,修召回。实际叫法对齐如下。
| 本文叫法 | 常见叫法 | 示例 |
|---|---|---|
| 活动版本 | 发布指针、索引别名 | 仅十五天制度可读 |
| 逻辑封读 | 墓碑、软删除 | 索引未清完也返回空 |
| 权限过滤 | 安全裁剪、访问控制 | 财务资料不进普通员工上下文 |
| 失效传播 | 缓存失效、依赖清理 | 制度改版后旧答案失效 |
自测
解析出了文字为什么仍可能不能入库,怎样验收表格和引用?
文字可能丢失阅读顺序、表头、单位或行列关系。按格式分层建原件对照样本,核对关键单元格及原文定位;失败文件隔离并记录原因。字符数不为空和向量生成成功都不是解析质量证明。
文档增量更新怎样避免新旧块混用和旧事件覆盖新版?
稳定文档标识与内容版本分离,新块在暂存区完整构建并验收后切换活动版本。查询核对活动版本,事件按单调版本处理,旧事件拒绝或安全忽略并留记录;同版本重放幂等,提交后再推进游标。
删掉原文件后,还要怎样处理索引、缓存与删除验收?
先写墓碑封读并传播缓存失效,再清向量、关键词、块存储和答案等派生物。分别验证停止可见与物理清理回执,并明确备份和历史会话保留规则;普通发布的同版本和高版本迟到都不能覆盖墓碑,物理清理保留防复活信息;本模拟不支持恢复。内容版本不是全局事件顺序,已发送给用户的副本无法靠后台撤回。
ACL 怎样继承到块,撤权后为何还要在检索时校验?
按源系统父子权限规则计算有效 ACL 并投影到每个块,身份来自可信会话。两路检索先过滤,候选进入重排与模型前批量复核当前权限、版本和墓碑;索引元数据可能滞后,所以即时撤权还需要权威读路径防线,不能只等后台同步。
参考与延伸
- Unstructured 解析策略,持续更新文档,发布日期未知,核验日期 2026-09-08:格式分流与表格抽取条件。
- Azure AI Search 文档级访问控制,页面日期 2026-08-08,核验日期 2026-09-08:权限投影、查询校验与同步滞后,部分能力为预览。
- 文档管理与更新,持续更新文档,发布日期未知,核验日期 2026-09-08:文档标识及更新、删除接口参照。
- 接续RAG 旗舰项目的变更验收;通用威胁模型见Agent 安全边界。