企业级RAG权限检索实战:用Milvus实现千人千权的完整方案
在企业知识助手的应用场景中,一次看似简单的文档检索背后隐藏着复杂的安全博弈。当用户提问「我们去年与A公司签订的框架协议赔偿上限是多少」时,在Demo环境里这只是向量相似度匹配;但在真实企业中,它首先是一次严格的权限判断。同一知识空间内可能同时存在公开制度、部门文档、项目材料、客户合同和管理层报告等多种密级内容,用户能进入空间不代表能查看所有文件,能访问某个文件夹也不代表能穿透被隐藏的子目录。这种权限颗粒度的复杂性,正是区分企业级RAG与普通文档问答的核心分水岭。
企业级RAG不能采用「先把答案找出来再问用户有没有权限」的逆向逻辑。常见的错误做法是在Prompt中告诉模型「请不要回答用户无权访问的内容」,但当这句话出现时,泄露就已经发生了——无权chunk已经被向量库返回到应用内存,甚至进入LLM的上下文窗口。另一种全量召回后过滤的方案虽然更可靠,但会严重伤害召回率:假设Top10中前9条都来自无权文件,过滤后只剩1条有效结果,系统可能给出「未找到」的错误答案而非正确响应。因此需要设计前置过滤、召回复核、展示兜底的三层安全防链,让权限真正成为检索本身的组成部分而非外围校验。
权限必须成为检索本身的一部分
权限系统擅长回答「用户1001能读哪些knowledge_file」,而Milvus擅长回答「在给定候选集内哪些向量与问题最相似」。这两类系统之间需要一个权限编译层来建立连接。在入库链路中,每个chunk携带document_id等结构化元数据,将向量世界与业务世界关联。检索时,系统先通过PermissionService获取用户可访问的文件ID集合,再与空间、文件夹、标签等业务范围求交集,生成Milvus可执行的布尔表达式如「document_id in [101,205,309]」。这种filtered search模型先用标量条件缩小候选集,再在匹配实体上执行ANN检索,让无权数据尽量不进入向量相似度竞争。
企业级RAG的成败,不在Prompt的约束里、不在召回后的过滤里,而在检索的每一个环节里。
“行业观察”积墨 AI 智能体开发平台
快速搭建具备商业价值的 AI 智能体,支持复杂工作流编排、50+ 主流模型接入与私有化部署。
权限编译层的桥梁作用
当用户可访问文件数量达到数万级别时,简单使用IN表达式会带来性能问题。KnowledgeFileVisibilityService会根据可见文件数K与空间文件总数N的比例,自适应选择白名单、黑名单或后过滤策略。文件夹和标签作为业务边界不能随意丢弃,即使列表很大也需保留;主版本过滤与权限过滤叠加生效,确保用户有权访问某个文件不代表该文件的所有历史版本都可被查看。双层过滤机制中,索引层粗过滤用can_read生成Milvus表达式缩小搜索空间,结果层精过滤则对召回结果解析view_file精细权限,与前端文件列表使用同一套有效权限语义——第一层决定去哪里找,第二层决定什么最终可以被看见。
自适应策略与双层过滤机制
为解决权限稀疏场景下TopK不足的问题,系统采用有界扩张策略:首轮按基准候选数的3倍召回,精过滤后若无可用结果最多再扩张到6倍,总召回次数不超过2次。同时需注意两个重要边界:历史会话中的引用可能成为越权通道,citation resolve链路必须在回显时按当前权限重新校验,失去权限的引用整条剔除不返回任何占位符。另外,权限变更使用租户隔离的Redis缓存,默认TTL为10秒,授权变更走统一失效逻辑确保下一轮检索即可收敛。当权限系统暂时不可达时,检索链路会回退到可确定的scope而非放行全量数据,让该次问答少答而不是越权。
企业级RAG的权限管理,本质是将业务世界的访问控制规则,编译为数据面的检索执行条件。这一过程需要在正确性、性能和用户体验之间取得平衡,既要防止越权访问导致的信息泄露,也要避免过度过滤导致的有效信息缺失。通过三层安全防链、权限编译层和自适应策略的组合设计,才能构建真正满足企业安全要求的知识检索系统。
