知识保鲜与权限
过期知识、增量更新、多租户隔离,以及“这个用户能不能看”。
一句话理解:知识库上线那天是最准的一天;要让它持续可用,必须解决两件事——知识变了索引能跟着变(保鲜),以及每次检索只返回这个用户有权看的内容(权限)。
知识库 Agent 上线三个月后,最常见的两类严重事故几乎都与模型能力无关:
- 过期事故:退款政策 8 月 1 日已经从 v2 升级到 v3,但索引里 v2 还在,而且因为 v2 的片段更多、被引用更久,它排在了前面。Agent 按旧规则给出了处置建议。
- 越权事故:销售专员问“某大客户的合同折扣价是多少”,Agent 从合同附件的片段里如实回答了。问题是,这位销售不负责这个客户,按规定无权查看。
前者会让用户不再信任 Agent,后者可能直接构成合规事件。这一课把两件事分开讲清楚。
知识为什么会“过期”
知识过期有几种不同的形态,处理方式也不同:
| 形态 | 例子 | 风险 |
|---|---|---|
| 文档被更新 | 退款政策从 v2 更新为 v3 | 新旧版本同时被召回,模型混用 |
| 文档被废止或删除 | 某临时补偿政策已于 6 月底废止 | 源头删了,索引里还在 |
| 部分内容失效 | 手册中的某个系统截图、某个联系人已变更 | 整份文档仍“生效”,局部错误难以发现 |
| 事实本身快速变化 | 某笔订单当前能否退款、某客户当前欠款 | 这类信息根本不该进知识库 |
| 尚未生效 | 10 月 1 日起执行的新价格 | 提前被当作现行规则使用 |
最后两类提示了一条重要的边界:变化频率高的事实,不应该放进知识库,而应该通过工具实时查询。 知识库适合“规则、流程、说明”这类以周、月为单位变化的内容。“这笔订单现在能不能退款”应该调用订单系统接口,“客户当前欠款”应该调用财务系统接口。
保鲜的四个机制
保鲜要在整条链路上设四道关:
① 变更检测。 优先使用源系统的变更事件或修改时间;做不到时,定期比对文档内容的哈希值。关键是 删除也要被检测到。很多同步脚本只处理“新增和修改”,被删除的文档在索引里永远存活。
② 增量更新。 文档被修改时,要先删除该文档的全部旧片段,再写入新片段。如果只是“追加”,新旧片段会同时存在。切块策略或 Embedding 模型变化时,则需要全量重建(参见 Embedding 与语义搜索)。
③ 检索时过滤。 依靠 切块与元数据 中设计的 status、effective_from 等字段,在检索条件里直接排除失效和未生效的内容。需要查看历史版本的场景(例如“事发当时适用的是哪版规则”)可以显式放开,但应该是特殊路径,而不是默认行为。
④ 可见的时效。 在引用中显示版本和更新日期,让用户自己也能判断。对超过一定时间未更新的文档,可以在回答中提示“该文档最后更新于一年前,请注意核实”。
还需要明确 同步延迟的承诺:文档修改后多久能在 Agent 中生效?是分钟级、小时级还是每日?这是一个需要写进需求、告知用户的产品指标。
权限:在检索时过滤,而不是在回答时隐瞒
处理权限最常见的错误做法,是检索时不区分用户,把所有相关片段交给模型,再在指令里写“不要向用户透露其无权查看的信息”。这种做法不可靠:
- 模型可能在总结、推理中间接泄露信息(“根据合同价推算,该客户的折扣约为……”)。
- 精心构造的提问可以绕过指令约束,参见 Prompt 注入。
- 引用列表、文档标题本身也可能泄露信息(“参考:《某客户 2026 年保密合作协议》”)。
正确的原则是:用户无权查看的内容,根本不应该进入这次调用的上下文。
权限模型的三种实现
| 方式 | 做法 | 适用 | 注意 |
|---|---|---|---|
| 元数据过滤 | 每个片段带 access_groups,检索时与用户所属组求交集 |
同一组织内部的部门、角色、区域权限 | 权限变化要同步到片段元数据 |
| 分库 / 分命名空间 | 每个租户或敏感域一个独立索引 | 多租户 SaaS、强隔离要求 | 运维成本高,但隔离最彻底 |
| 检索后实时鉴权 | 检索结果返回前,逐个调用源系统的权限接口确认 | 权限规则复杂、变化频繁 | 延迟较高,可与缓存结合 |
实际系统常常组合使用:租户之间分库隔离,租户内部用元数据过滤,高敏感文档再做实时鉴权。
组合起来是一个一层套一层的结构:
权限设计中容易漏掉的地方
- 权限同步延迟:员工调岗后,旧权限在索引元数据里还保留多久?离职人员呢?
- 片段继承权限:文档的权限要完整传递到它的每一个片段,包括附件、嵌入的表格。
- Agent 代表谁的身份:Agent 查询知识库和业务系统时,应该使用 当前用户的身份和权限,而不是一个拥有全部权限的服务账号。参见 最小权限与凭据管理。
- 缓存与记忆的串用:为了省钱,把“问题 → 答案”缓存起来复用时,必须按权限范围隔离,否则 A 用户的答案会被返回给 B 用户。长期记忆同理,参见 记忆的隐私与可控。
- 日志与评测数据:检索日志、Trace 中包含片段原文,查看这些日志的人也需要相应权限。
一个完整示例
华东区售后客服提问“订单已经开了发票,还能退款吗”,系统的实际检索条件是:
query: 已开具发票 订单 退款 处理
filters:
status: effective # 保鲜:只取生效中
effective_from: "<= 2026-09-17" # 保鲜:排除未生效
business_line: [after_sales]
region: [national, east] # 业务范围:全国通用 + 华东
access_groups: {intersects: [support_east, finance_common]} # 权限
tenant: acme-cn # 租户隔离:独立索引
ranking:
tie_breaker: updated_at desc # 同等相关时新版优先
而同一个问题由华南区的客服提问时,region 与 access_groups 不同,可能检索到不同的片段、得到不同的回答。同一个问题对不同用户给出不同答案,在企业知识 Agent 中是正常且必要的。 这一点要提前和业务方、测试同学对齐,否则会被当成 Bug。
常见误区
- “在指令里告诉模型不要泄露就行。” 无权查看的内容一旦进入上下文,就有泄露的可能。权限必须在检索层过滤。
- “文档更新了,重新导入一遍就好。” 只追加不删除,新旧版本会同时存在;删除的文档如果没有同步,会永远被检索到。
- “知识库什么都可以放。” 高频变化的事实放进知识库,一定会过期。它们应该通过工具实时查询。
产品经理检查清单
- 知识源的更新频率如何?文档修改后多久在 Agent 中生效?
- 删除、废止、未生效的文档如何处理?是否有测试用例覆盖?
- 哪些信息变化太快、不应进入知识库,而应通过工具查询?
- 权限在哪一层过滤?是否存在“先检索全部、再让模型保密”的做法?
- Agent 访问知识库和业务系统时,使用的是用户身份还是服务账号?
- 调岗、离职后的权限多久同步到索引?
- 答案缓存、记忆、日志是否按权限隔离?
练习
为公司知识库 Agent 设计保鲜与权限方案:
- 列出知识库中的 5 类文档,为每类填写:更新频率、负责人、变更检测方式、同步延迟目标。
- 设计 3 个“过期陷阱”测试用例,例如:同一问题在 v2 与 v3 规则中答案不同,期望 Agent 只引用 v3。
- 设计 3 个“越权陷阱”测试用例,例如:华南区客服询问华东区客户合同价,写出期望的回复。
- 画一张简图,说明用户身份如何从登录一路传递到检索过滤条件。
下一步
到目前为止,检索都是“问一次、查一次”。下一课「Agentic RAG 与联网搜索」讲如何让 Agent 自己决定搜什么、搜几次、什么时候停。