RAG 权限应在检索时执行
文章指出,将机密文档放入上下文后再要求模型保密,无法形成可靠的访问控制。多人共享知识索引时,应在检索阶段按用户权限限制可返回内容,避免越权片段进入模型。
AI 深度解读
RAG 演示通常默认所有文档都能读,接入公司资料后,这个默认就失效了。HR 文件、客户合同、团队内部文档共享一个索引,检索结果就必须随用户权限变化。作者的核心判断是:保密指令不能代替访问控制,权限应该在检索时执行。
这篇值得读的地方,是它把问题从「模型会不会泄密」前移到了「数据为什么能进模型」。对正在做企业知识库或内部 AI 助手的程序员,这个边界直接影响检索实现、权限同步和测试方式。
权限判断为什么要放进检索请求
教程里的流程很简单:文档向量化,按相似度取前 5 个片段,塞进提示词。生产环境多了一道必要条件:这些片段是否允许当前用户读取。
作者反对用提示词要求模型「只使用用户有权查看的文档」「不要透露机密」。原因并不复杂:模型读到指令时,机密内容已经进入上下文。后续追问、摘要请求,或者其他文档里的提示注入,都可能让内容被输出。
受限片段进入模型上下文,就已经越过了权限边界。
先检索、再过滤,看起来也能解决问题:
chunks = vector_store.similarity_search(query, k=20)
allowed = [c for c in chunks if user_can_read(user, c.metadata["doc_id"])]
context = allowed[:5]
要看的是第一行:k=20 的候选来自整个索引。如果受限文档占满相似度最高的位置,用户实际有权读取的内容可能根本没进入候选,过滤后只剩空结果。作者还指出,过滤逻辑漏分支时,可能留下未授权内容。
作者建议把权限条件放进检索请求,让存储层只返回允许访问的片段:
chunks = vector_store.similarity_search(
query,
k=5,
filter={"acl_groups": {"$in": user.group_ids}},
)
这里关键是 filter:用文档的 acl_groups 匹配当前用户的 user.group_ids,没有匹配组就不返回内容。不过,这只是示意代码,原文没有指定向量数据库,不能直接当成所有产品通用的查询语法。
文档没变,权限也可能已经过期
访问控制列表(ACL)不能只在建索引时复制一次。
作者举了一个假设场景:工程师周一从 payments 团队转到 mobile 团队,源系统当天撤销旧权限。但向量索引上周四才构建,每周同步一次,于是 RAG 仍可能保留 4 天的过期授权。
内容同步和权限同步,不能默认采用同一个周期。
原文给了三个方向:权限变更比正文变更更快同步;查询时解析用户所属组,避免把用户 ID 固化到片段;敏感资料返回前,再向源系统检查权限。这些是可选做法,作者没有给出延迟、成本或一致性的对照数据。
还有一个更容易漏掉的入口:派生内容。
一份文档拆成 40 个片段,附件被单独提取,夜间任务又为长讨论生成摘要,这些产物都必须继承来源的权限限制。三份文档合成一份摘要,只要其中一份受限,摘要也需要受限。否则,摄取流水线就把受限内容加工成了看似公开的新资料。
实际实现时,还要弄清「最严格权限」怎么计算。涉及不同团队的复杂 ACL 时,原文没有展开合并算法,不能只靠挑一个权限标签完成继承。
引用来源不能证明用户有权阅读
引用解决的是「答案从哪里来」,授权解决的是「这个人能不能收到」。
如果答案已经透露了受限内容,即使附上一个用户打不开的引用链接,泄露也已经发生。链接报错不会收回答案。
因此,只测 user_can_read() 不够,只看最终回答也不够。作者建议选择涉及受限资料的问题,分别用管理员、团队成员、外包人员,以及昨天刚被撤权的用户身份运行。
真正需要比较的是进入模型上下文的片段 ID。
不同角色可能得到一样的回答,但模型接收到的资料并不一样。模型碰巧没有提及某段机密,不能算权限测试通过。按照作者的标准,只要未授权片段进入上下文,就应该判定失败。
我的判断
我认同把授权放在数据进入提示词之前。这让权限边界落在可以检查、可以测试的系统逻辑上,也避免把安全性押在模型每次都遵守指令上。
但「把过滤条件传给向量数据库」还不是完整方案。原文没有说明具体数据库如何执行过滤,也没有给出组权限之外的授权模型。落地时,需要确认所用检索接口是否按预期限制候选,以及撤权后多久能生效。
与先检索再过滤相比,作者的方案解释清楚了候选被受限文档挤占的问题;至于实际能改善多少召回、增加多少查询成本,没有实验数据,这是架构建议和经验判断。
提示词仍然可以约束回答行为,只是承担不了文档授权职责。引用也有核验价值,只是不能作为权限通过的证据。
能拿来做什么
- 给内部 RAG 的检索入口补上权限过滤,并明确空用户组、缺失 ACL 等情况下应返回什么,避免默认开放。
- 在 Node 服务里梳理用户组的获取与缓存流程,明确撤权多久能影响查询,不要只检查文档同步任务是否成功。
- 检查切片、附件提取和摘要任务,确认每种派生内容都保留来源与权限,尤其留意多文档合成的摘要。
- 为同一个问题准备多种角色测试,断言进入模型上下文的片段 ID 是否全部获授权,前端显示的答案和引用只能作为辅助检查。