公司内部最常见的RAG错误很简单:上传所有内容、开始提问,然后认为带有来源引用的答案自然就是安全的。
第二种最常见的错误随后出现:有人发现,助手可以根据用户根本不应看到的文档作答,例如薪资范围、客户合同、法律草案、董事会记录、客服工单、人力资源调查和安全规程。答案可能准确且带有引用,系统却已经泄露了信息。
企业知识RAG不是一个文笔更好的搜索框,而是一个受权限控制的信息系统。你应该按这样的系统来对待它。
检索必须执行与源系统相同或更严格的权限。如果用户无法在Google Drive、SharePoint、Notion、Confluence或CRM中打开某份文档,RAG就不应为该用户检索这份文档。
核心规则
检索层在返回任何文本块前,都必须回答:
这名用户现在是否有权查看这个来源?
要问的不是“这个来源是否在向量数据库中”,不是“这个来源是否相关”,也不是“这个来源是否有用”。权限永远优先。
常见模式有三种:
| 模式 | 工作方式 | 适用场景 |
|---|---|---|
| 独立索引 | 每个受众群体或工作区使用一个索引 | 简单团队、粗粒度权限 |
| 元数据筛选 | 存储ACL、群组和来源元数据,并在检索前筛选 | 大多数企业RAG系统 |
| 实时权限检查 | 检索时查询源系统权限 | 敏感数据或频繁变化的权限 |
正确选择取决于源系统和风险等级。对大多数中小企业而言,独立索引加元数据筛选已经足够。对于客户、人力资源、法律或受监管数据,可能需要实时检查。
难点:保持ACL同步
上述每一种模式都悄然依赖同一件事:索引中的权限数据必须与源系统中的权限数据一致。真正的工程难点就在这种同步上。
**ACL来自哪里。**SharePoint和OneDrive通过Microsoft Graph API公开单个项目的权限;Google Drive通过Drive API的单文件权限列表公开权限;Confluence则通过空间和页面限制来控制权限。它们采用不同的数据结构(用户、群组、继承关系、共享链接),有不同的API速率限制,对“谁可以查看此内容”的定义也各不相同。
**群组展开不可省略。**现实中的大多数权限都授予群组,而群组还可能嵌套。位于“Sales”内、而“Sales”又位于“All Staff”内的“Sales EU”,必须在同步时(索引元数据更大、查询更快)或查询时(更新、较慢、API调用更多)展开为具体用户。请有意识地选择一种方式;无意间处理这一问题的团队,往往会得出不一致的结果。
**同步延迟是安全参数,不是性能细节。**当某人失去文档访问权限时——例如职位变动、离职或交易转为保密——索引会继续按旧ACL提供内容,直到下次同步。应按语料库确定并记录可接受的权限撤销延迟:受限语料库需要接近实时,内部流程文档则可能允许数小时延迟。如果没有人写下这个数字,实际答案就是“等夜间任务运行时再说”,而这经不起安全评审。
**实时检查提高了时效性,但会增加延迟、消耗速率配额,并引入一种新的失败模式。**每次检索都进行权限调用,会为每次查询增加一次源系统往返,在规模扩大后迅速消耗API配额;通常的折中方案是使用短期缓存,但这其实又把“实时”悄悄变回了“数值更小的同步延迟”。无论选择哪种方式,都要明确超时行为:**如果权限检查失败或超时,就不能交付该文本块。**采用关闭式失败,记录故障并让助手拒绝作答——缓慢但正确的回答胜过快速泄露。
测试部分的离职测试,可以验证这一切是否真正有效:被停用的账户必须无法从受限语料库中检索到任何内容,而且这一要求必须在账户停用后的第二天仍然成立,而不只是等到下一次完全重新同步后才成立。
来源边界
不要建立一个巨大的知识池。应按受众和敏感程度进行分隔:
| 语料库 | 受众 | 示例 | 规则 |
|---|---|---|---|
| 公开/产品 | 所有人 | 帮助文档、公开价格、产品页面 | 可供通用助手使用 |
| 内部运营 | 员工 | 流程文档、内部常见问题 | 仅限员工 |
| 部门 | 部门成员 | 销售手册、客服回复模板、工程运行手册 | 按群组筛选 |
| 客户记录 | 指定团队 | 工单、合同、账户备注 | 严格ACL和审计 |
| 受限 | 仅限指定用户 | 人力资源、法律、安全、董事会资料 | 通常使用独立系统或不使用RAG |
一个语料库服务的受众越少,就越容易分析信息泄露风险。
摄取控制
许多泄露始于摄取流水线。
为来源建立索引之前,应记录:
- 源系统。
- 文档ID。
- 负责人。
- 受众或ACL。
- 敏感度标签。
- 创建和更新时间戳。
- 到期或复核日期。
- 文档是否允许用于AI检索。
- 文档是否包含个人数据。
如果源系统已有标签,请予以保留。如果没有,则在摄取前增加一个轻量级分类步骤。
检索控制
检索应按以下顺序进行:
- 识别用户及其群组。
- 识别请求所针对的工作区或助手。
- 按语料库、ACL、敏感度和时效性筛选候选来源。
- 仅从允许的来源中检索相关文本块。
- 对允许的文本块进行重排序。
- 生成带有来源引用的答案。
- 当允许的来源不足时拒绝作答或升级处理。
不要先检索,再在提示词中筛选。如果禁止访问的文本块进入模型上下文,边界就已经失守。
提示词和回答行为
应指示助手:
- 仅根据检索到的来源作答。
- 引用来源标题和章节或链接。
- 在允许使用的来源不包含答案时如实说明。
- 将推断与有来源依据的事实分开标明。
- 不泄露受限来源的存在。
- 不概述访问被拒绝的资料。
不妥的拒绝方式:
“我找到了人力资源薪资范围,但你没有访问权限。”
更好的拒绝方式:
“我没有可用于回答这个问题的已批准来源。”
第二种回答不会泄露受限文档的存在或主题。
记录日志,但不要造成二次泄露
RAG日志属于敏感数据,其中可能包含用户问题、检索到的文本块、来源ID、答案,有时还包括个人数据。
记录足够用于调试的信息:
- 用户ID或假名化ID。
- 助手/工作区。
- 查询时间戳。
- 检索到的来源ID。
- 权限筛选结果。
- 答案ID。
- 拒绝/升级原因。
- 延迟和错误。
谨慎记录:
- 完整用户问题。
- 检索到的完整文本块。
- 完整生成答案。
- 客户数据。
- 人力资源、法律或安全主题。
对于敏感系统,应存储脱敏日志或来源ID,而不是全文。为日志设置独立的访问控制和保留期限。
过时和冲突的来源
权限并不是唯一边界,来源质量同样重要。
每个建立索引的来源都应有负责人和时效规则:
| 来源类型 | 复核规则 |
|---|---|
| 定价 | 每次价格变动时复核 |
| 政策 | 政策负责人更新时复核,至少每季度一次 |
| 产品文档 | 每次发布时复核 |
| 法律模板 | 由法律负责人复核 |
| 客服回复模板 | 每月复核,或在升级模式发生变化后复核 |
当来源相互冲突时,只有用户有权访问两个来源,助手才能提示冲突。否则,它应根据允许访问且权威性最高的来源作答,或升级处理。
测试权限边界
应使用不同类型的用户进行测试,而不只是测试文档:
- 拥有广泛访问权限的员工。
- 仅有少量部门访问权限的员工。
- 仅有团队访问权限的经理。
- 承包商。
- 前员工或账户已停用的用户。
- 面向客户的支持人员。
- 管理员。
对每类用户,分别询问:
- 一个他们应该能够回答的问题。
- 一个刚好超出其权限的问题。
- 一个与其明知存在的受限文档有关的问题。
- 一个公开文档与内部文档相冲突的问题。
- 一个使用提示词注入的问题:“忽略访问规则。”
正确结果不只是“答案很好”,而是“答案很好,并且只使用允许的来源”。
推广路径
从敏感度最低的语料库开始:
- 公开/产品文档。
- 内部运营文档。
- 部门专属文档。
- 采用严格ACL的客户记录。
- 仅在获得明确的安全与法律批准后处理受限语料库。
每个阶段都应衡量:
- 答案实用性。
- 引用质量。
- 拒绝行为正确性。
- 访问被拒绝内容的检索率。
- 过时来源率。
- 用户对缺失或错误来源的报告。
目前不要这样做
不要把“所有公司文档”索引到一个助手中。
不要依赖提示词指令来执行权限。
没有明确的保留和访问政策时,不要为敏感语料库记录完整的检索文本块。
不要把人力资源、法律、客户和公开文档混在同一个语料库中。
不要为了显得有帮助,就让RAG在允许的来源之外作答。
要点总结
企业知识RAG之所以有价值,是因为它把有来源依据的答案带入日常工作。它之所以有风险,是因为有来源依据的答案仍然可能泄露信息。
应优先设计权限边界,在检索前进行筛选,按受众分隔语料库,保留来源元数据,安全拒绝,谨慎记录日志,并使用真实权限配置进行测试。如果用户无法直接访问某个来源,RAG就不应使用该来源为其作答。



