智能体的知识库不维护就一定会变蠢:文档改了索引没更新、源文档删了向量还在、内容更新后新旧版本同时被检索到。解决方案不是「定期全量重建」这一招,而是把维护做成流水线:增量更新、失效判定、重建节奏三件事各自有明确的触发条件和做法。
知识库腐化的三种典型症状
先对号入座,看你的系统中了哪一种:
- 答案陈旧:业务规则改了三个月,智能体还在按旧规则回答。根因是源文档更新后没有触发重新索引。
- 新旧打架:同一问题检索出两段矛盾的内容,回答时而对时而错。根因是增量更新只做插入、不做旧版本清理。
- 幽灵内容:源文档已删除,但检索仍会命中它。根因是删除动作没有传导到向量库。
增量更新的核心:记录管理器
全量重建在小知识库上可行,文档一过万就会遇到两个问题:嵌入计算的费用随文档量线性增长,重建窗口内检索质量下降。增量更新的关键设施是记录管理器:每次写入向量库时,为每个文档(及其切块)记录内容哈希、写入时间和来源标识。再次索引时逐条比对:
- 哈希没变 → 跳过,不重算嵌入;
- 哈希变了 → 清理旧切块,写入新切块;
- 来源在本次索引中消失 → 该来源的所有切块进入待删除集合。
这个模式 LangChain 的 Indexing API 已经做了标准化实现,其清理模式分三档:incremental 持续清理已变更内容、full 在整轮索引结束后统一清理(要求本轮加载全量数据)、scoped_full 只清理本轮见到的来源。选型原则:数据源能全量枚举就用 full,只能增量拉取就用 incremental,二者都难以满足时用 scoped_full 折中。
失效判定:怎么知道一条知识过期了
哈希比对只能发现「文档变了」,发现不了「文档没变但事实变了」。需要按内容类型分别设计失效信号:
| 内容类型 | 失效信号 | 处理方式 |
|---|---|---|
| 带更新时间的文档 | 源的 modified_at 晚于索引写入时间 | 标记为待重索引 |
| 接口 / 配置类数据 | 版本号或 ETag 变化 | 对应条目失效重建 |
| 无时间戳的纯文本 | 定期抽样让模型比对新旧版本语义差异 | 差异超过阈值则重索引 |
| 业务规则类 | 上游系统发布变更事件 | 事件驱动,立即失效 |
特别提醒:切块(chunk)层面的失效比文档层面更隐蔽。一个文档只改了一段,整篇重嵌入当然正确但浪费;更精细的做法是只对内容变化的块重算嵌入——前提是你的切块策略稳定,否则块边界一变,全部块都要重来。
重建节奏与窗口期问题
即使有增量机制,仍建议保留低频全量重建,用于纠正两类漂移:嵌入模型升级导致新旧向量空间不一致;切块策略调整导致检索粒度变化。这两类变更会让增量比对彻底失效,只能全量重来。
- 日常:事件驱动增量索引。源系统发布变更事件(webhook 或轮询变更时间戳)后 5 分钟内完成受影响文档的重索引,全程自动,无需人工。
- 每日:失效对账。跑一次「源清单 vs 记录管理器」比对,找出源里已删除但索引还在的幽灵条目,输出删除清单并执行清理。
- 每周:检索质量抽查。抽 20 个高频真实问题跑检索,人工确认命中内容是否为最新版本,异常集中出现说明有系统性失效信号没接上。
- 季度或版本变更时:全量重建。嵌入模型或切块策略变更后,用新配置重建整个索引,重建期间旧索引保持只读服务,新索引验证通过后一次性切换。
窗口期:新旧版本同存的代价
增量更新有个绕不开的间隙:新切块写入之后、旧切块删除之前,两份内容会同时存在于索引中,用户可能检索到过期版本。两种缓解思路:
- 先删后写:同一来源的新内容入库前先删旧内容。窗口最短,但删写之间检索会短暂漏掉该文档,适合能容忍瞬时缺失的场景。
- 写入时打版本标记,查询时过滤:给每个切块挂上来源的当前版本号,检索层只取每个来源的最新版本。无窗口期,但要求元数据设计与查询层配合。
清理策略速查(点击展开)
- incremental:持续清理变更内容,不清理「源已删除」的条目,适合持续拉取的数据源;
- full:整轮索引后统一清理,能正确处理源删除,但要求本轮必须加载全量数据,否则会误删;
- scoped_full:只清理本轮见到的来源,适合数据源太大无法一次全量、又想按批清理的场景。
相关阅读:RAG 文档切块怎么做:策略与参数选择、AI 长文档问答为什么答不准:分块、表格解析与引用溯源、智能体成本怎么算:token 、工具调用与重试的账本模型。










评论 (0)