当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > AI 应用如何隔离租户知识库:检索权限、缓存键与引用验收

AI 应用如何隔离租户知识库:检索权限、缓存键与引用验收

来源:17golang原创 2026-08-25 23:51:04 0浏览 收藏

多租户 AI 知识库上线后,最难排查的往往不是“检索不到”,而是偶尔检索到了不该看到的内容:同一个问题在 A 租户命中,B 租户却看见了相似片段,或者答案引用了另一家公司的文档。这个问题不能靠提示词里加一句“不要串租户”解决,权限过滤、缓存键和引用回显必须在服务端形成闭环。

实践要点:
  • 从认证上下文得到不可伪造的 tenant_id,把租户条件下推到检索层。
  • 缓存键包含租户、权限版本和知识库版本,避免跨租户复用。
  • 引用只能来自本次检索结果,并留下可回放的审计记录。

先把真正需要保护的资产列出来

知识库隔离保护的不是一个抽象的“上下文”,而是文档片段、原文链接、文件名、检索分数和缓存结果。只要其中一项跨过租户边界,后面的模型回答再流畅也没有意义。

线上排查时,可以先固定四个字段:tenant_idprincipal_iddocument_idtrace_id。其中 tenant_id 来自登录态或网关签发的令牌,不能接受前端 JSON 里的同名字段覆盖;document_id 用来追溯来源;trace_id 让一次问答可以从检索日志追到引用回显。

多租户知识库中身份、权限过滤和片段返回的隔离链路示意图

检索权限要在召回之前生效

常见错误是先用向量相似度召回一批片段,再在应用层过滤租户。这样做既浪费检索预算,也容易在调试日志、重排服务或缓存层留下越权数据。更稳妥的顺序是:认证上下文确定租户,权限服务生成允许的范围,检索请求带着这个范围进入索引。

type SearchScope struct {
    TenantID        string
    PrincipalID      string
    PermissionEpoch  uint64
}

func buildFilter(scope SearchScope) Filter {
    return Filter{
        "tenant_id":  scope.TenantID,
        "principal":  scope.PrincipalID,
        "status":     "published",
    }
}

这里的 principal_id 不一定要直接写入每个向量记录,也可以由权限服务转换成可检索的文档集合或访问标签。关键是过滤条件由后端生成,并且在召回、重排、引用回显三个环节保持一致。

权限拒绝应该留下可判断的证据

检索不到结果时,不要简单记成“模型回答为空”。日志至少应区分 scope_emptyfilter_rejectedindex_timeout。前两种说明权限链在工作,后一种才是基础设施故障。日志中可以保留数量和哈希,但不要把被拒绝文档的正文写进普通业务日志。

缓存键不能只拼问题文本

缓存是租户串线最容易被忽略的一层。把用户问题标准化后直接作为键,例如 rag:answer:合同续期,在单租户演示环境里看不出问题,到了共享缓存就会把答案和引用一起复用。

缓存键至少应绑定租户、主体权限版本、知识库版本、检索配置和问题摘要:

key := fmt.Sprintf(
    "rag:v3:%s:%d:%s:%s",
    scope.TenantID,
    scope.PermissionEpoch,
    knowledgeBaseVersion,
    sha256(normalizedQuestion+searchMode),
)

权限发生变化时递增 PermissionEpoch,比依赖一个很短的过期时间更可靠。知识库重新切片或删除文档时也要改变版本号,否则旧答案可能继续带出已经撤回的引用。

引用回显必须回到本次检索结果

回答正文可以由模型生成,但引用列表不应由模型自由编造。服务端应保存本次检索返回的 document_id、片段范围和访问判断,再把模型输出中的引用标记映射回这份白名单。找不到对应片段的引用直接丢弃,并把异常记入审计记录。

验收时重点看三件事:引用文档是否属于当前 tenant_id,引用是否出现在本次召回集合,引用链接是否经过同一权限检查。只检查回答文字里的公司名是不够的,因为文件名、URL 参数和隐藏元数据同样可能泄露边界信息。

租户知识库缓存键、引用校验与审计记录的闭环验收图

用一组对照请求验证隔离是否真的生效

不要只拿一个租户做冒烟测试。至少准备 A、B 两个租户,各放入一段只有本租户能识别的哨兵文本,例如不同的项目代号。然后对同一问题交替发起请求,并清空与不清空缓存各测一遍。

for tenant in tenantA tenantB; do
  curl -sS -H "X-Test-Tenant: $tenant" \
    -H "X-Trace-Id: isolation-$tenant-01" \
    https://example.invalid/api/ask \
    -d '{"question":"项目代号是什么?"}'
done

测试结果应同时核对 HTTP 响应、引用数组、缓存命中日志和审计记录。A 的答案不能出现 B 的哨兵词;更严格的检查是,B 即使复用同一个问题文本,也必须得到自己的缓存键和自己的引用集合。

几个看似合理、实际危险的做法

  • 把租户 ID 放在前端请求体里,后端直接信任。
  • 只在最终答案阶段做敏感词过滤,却让重排服务先看到跨租户片段。
  • 缓存只按问题和模型名分组,忽略权限版本与知识库版本。
  • 让模型自行生成引用 URL,服务端只检查 URL 是否可访问。

这些做法的问题不在于“模型不够聪明”,而在于边界放错了位置。模型可以参与摘要和排序,但身份、权限、缓存分区和引用白名单都应由确定性的服务端逻辑负责。

上线前留下可回放的审计记录

一条合格的审计记录应能回答:谁在什么租户下发起了什么问题,本次用了哪个权限版本和知识库版本,召回了哪些文档,最终展示了哪些引用,缓存是否命中。正文可以脱敏,字段关系不能缺失。

建议把 trace_id 作为主关联键,把原始问题保存为受控哈希或按保留策略加密存储;对外排障时只暴露租户自己的记录。发生疑似串租户时,先冻结相关缓存命中记录,再按 trace_id 回放权限过滤和引用映射,不要直接删除日志。

相关问题

只在向量库里增加 tenant_id 够不够?

不够。还要确保重排、缓存、引用回显和下载入口使用同一套授权判断,否则向量检索虽然隔离,后续链路仍可能泄露。

权限变化后必须清空全部缓存吗?

不一定。把权限版本纳入缓存键,并让旧版本自然失效或进入受控清理队列,可以减少全量清空;高风险权限变更仍应主动撤销相关键。

如何判断一次串租户是缓存问题还是检索问题?

对同一问题做冷缓存和热缓存对照,并比较召回文档集合。如果冷缓存已经越权,先查检索过滤;冷缓存正常、热缓存异常,再查缓存键和权限版本。

结语:把隔离做成四道能验收的门

多租户知识库的安全边界可以收敛为四道门:身份决定租户,检索决定可见范围,缓存决定复用边界,引用决定最终展示内容。每道门都要有字段、有日志、有对照测试,出了问题才能定位到具体环节,而不是把责任推给模型“偶尔答错”。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go context.WithoutCancel 为什么会丢失 Done:保留 Value 与切断取消的边界Go context.WithoutCancel 为什么会丢失 Done:保留 Value 与切断取消的边界
上一篇
Go context.WithoutCancel 为什么会丢失 Done:保留 Value 与切断取消的边界
Go embed.FS 如何支持可回滚模板:版本目录、启动校验与热切换边界
下一篇
Go embed.FS 如何支持可回滚模板:版本目录、启动校验与热切换边界
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ljg-skills -
    ljg-skills
    ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
    5273次使用
  • MELO音乐 - AI 音乐生成平台,支持多模态创作能力
    MELO音乐
    MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
    4788次使用
  • UniScribe - AI 免费在线音视频转文字平台
    UniScribe
    UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
    4734次使用
  • 剧云 - 免费 AI 智能中文剧本创作平台
    剧云
    剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
    4991次使用
  • 万象有声 - AI 一站式有声内容创作平台
    万象有声
    万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
    4942次使用