多租户 RAG 知识库权限怎么隔离
先给结论:多租户场景下做 RAG,最致命的不是检索准不准,是 A 公司的人能不能搜到 B 公司的文档。这道权限隔离做漏了,就是数据泄露事故。我踩过一次差点出事的边,把几种隔离方案和选型摆在这。
场景
我做的是一个给多家客户用的合同问答 Agent。每家客户上传自己的合同到知识库,问答时只能检索到自家的文档。早期我图快,所有客户的文档丢一个向量库里,检索时全局召回——直到测试时 A 客户搜出了 B 客户的合同片段,后背一凉。
三种隔离方案对比
我把试过的三种摆一起:
方案 | 隔离强度 | 成本 | 适合规模 | 主要风险 |
元数据过滤 | 中 | 低 | 中小,几十个租户 | 过滤条件漏写就穿透 |
独立 collection | 高 | 中 | 几十到几百租户 | collection 多了管理累 |
独立向量库实例 | 最高 | 高 | 大客户/强合规 | 资源浪费、运维重 |
元数据过滤:所有文档进同一个库,但每条切片打上tenant_id标签,检索时强制带where tenant_id = 当前租户这个过滤条件。成本最低,但有个致命点——只要哪次检索忘了带这个过滤条件,立刻全局穿透。我那次事故就是某条检索分支漏了过滤。
独立 collection:每个租户一个独立的向量集合,检索时按租户路由到对应 collection。物理上分开,不存在"忘了过滤"的穿透问题,隔离强度高一档。代价是租户多了之后,几百个 collection 管起来有点烦。
独立向量库实例:每个大客户单独起一套库。隔离最彻底,合规审计最好交代,但资源和运维成本最高,只对强合规的大客户才值得。
我最后的选型
中小租户用元数据过滤兜底,但加了两道保险:一是把tenant_id过滤写进检索的公共封装里,任何检索调用都自动带上,不给"忘记"的机会;二是上线前专门写了一条越权检索的测试用例,A 租户的请求去搜 B 的关键词,断言必须召回 0 条。
少数强合规的大客户单独切独立 collection。这套混合策略落地下来,既没为小客户上重型方案,又给大客户留了硬隔离。
实现上我是在一个带场景化 RAG 能力的搭智能体平台上做的,它支持按知识库维度建多个独立库,我直接一个租户挂一个知识库,检索时绑定当前租户的库,从源头上就不会跨租户召回——比自己在一个大库里靠过滤条件兜底,心理踏实多了。
一个容易忽略的细节
权限不只是检索那一刻的事。文档删除也要隔离——客户解约后,他那批向量得能干净删掉。我早期是按文档 ID 一条条删,后来发现切片散在库里删不干净,残留的向量还能被搜到。改成按tenant_id批量清,才算彻底。
收尾
多租户 RAG,我的经验是:隔离强度按客户分级别给,别一刀切;同时把越权检索写成自动化测试,每次发版都跑,这比任何人工 review 都靠谱。
模型和向量化那层我用的讯飞星辰现成的服务,大模型 API 直接调,不用自己搭嵌入和推理服务,省下的工夫全花在把权限这道闸做严上了。
