日期:2026-09-19
某集团知识库文档几百万份,业务方改一份制度,想立刻能在问答里被查到,但原来的架构每次全量重建索引要半天,结果经常 RAG 答的还是旧版,员工问最新报销标准答出来的是去年作废的。信任一旦掉了,后面推什么都没人用,知识库从高频工具变成没人点的大门面。这个项目让我明白,知识库的新鲜度比召回率更影响人愿不愿意用,答错一次旧版,用户就回关键词检索了,前面所有工程都白做。我们进场时,知识库的日活已经掉得厉害,员工宁愿翻共享盘也不问问答,运营每周收到好几起"答的都是旧版"的投诉,知识库项目面临被砍。
我们进场时知识库日活已经掉得厉害,员工宁愿翻共享盘也不问问答,运营每周收到好几起答旧版的投诉,项目面临被砍,所以新鲜度是救命不是优化。
我们进场时知识库日活掉得厉害,员工宁愿翻共享盘也不问问答,运营每周收到好几起答旧版的投诉,项目面临被砍,所以新鲜度这次是救命不是优化,答不对版一切白搭。
我们改成增量管线:文档一更新,只解析变动的那份,向量增量写进库,不用全量重来;同时在网关层加了热点查询缓存,高频问题(比如年假怎么算)命中缓存秒回,冷查询才走检索。多版本文档用版本号标记,旧版过期自动失效,避免答非所问。业务方改完制度,分钟级就能在问答里被问到,不用等半夜重建。运营侧能看到每份文档的索引更新时间和命中情况,哪份文档老没人查、哪份老被问,一目了然,知识运营从盲改变有据。检索侧对高频 query 直接走缓存,后端压力也小了。
运营侧能看到每份文档的索引更新时间和命中情况之后,知识运营从盲改变有据,哪份老没人查、哪份老被问一目了然,运营终于敢主动推而不是被动救火。
索引更新从半天压到分钟级之后,业务方改制度不用再等半夜排重建,运营节奏第一次跟得上业务,而不是被工程排期拖着走。
增量索引一致性是第一个坑,并发更新可能让索引和原文短暂对不上,我们给每份文档加了版本锁,更新期间读旧版、更新完原子切换,用户无感,不会出现半新半旧。热点缓存失效是第二个,缓存过期策略不清会把旧答案喂给用户,我们按文档版本号做缓存键,文档一变缓存整桶失效,不是按时间糊涂过期,这样保证答的永远是最新版。第三个是大库重建成本,几百万份全量重建太贵,我们保留了周级全量重建做兜底,平时只跑增量,兜底不删,极端情况(向量库升级、索引损坏)有路可走。第四个是版本管理,同一份制度多个版本并存,检索时只认最新版,旧版不进召回,避免答到历史版。
版本管理那块,检索时只认最新版、旧版不进召回,这个看似简单,但能彻底杜绝答到历史版,我们早期漏了这层,偶尔还是会把作废制度答出来。
索引更新时效从半天压到分钟级,业务方改完制度马上能在问答里查到,运营不用再半夜排重建;命中新鲜度(答到最新版的比例)从约 70% 提到 98% 以上,旧版答非所问基本消失,相关投诉归零;高频查询检索延迟从几百毫秒降到缓存命中的十几毫秒,体感明显,员工愿意回来用;全量重建的资源开销因为平时不跑,下降约八成,省下不少算力。知识库日活跟着新鲜度一起回来了,运营说终于敢推了。版本号失效策略上线后,再没出现过答旧版的工单。
全量重建开销降八成之后,省下的算力可以挪去别的计算任务,知识库从一个吃算力的黑洞变成可控成本,科技部那边对这套架构的接受度也高了。
知识库这事,业务方不在乎你召回多花哨,在乎问的能不能是当下最新的。我们先把全量重建当默认,结果新鲜度一直救不回来,换成增量加热点缓存才真正解决问题。但缓存失效一定想清楚键怎么设计,我们有一版按时间过期,文档没动也过期重算,白白浪费还偶尔答旧,改成按版本号才稳。兜底的全量重建别删,增量再稳也有极端情况要重修,比如向量库升级。版本号这个东西,从一开始就打,别等出了问题再补,补的成本比一开始高十倍,几百万份文档回溯打版本号能让人数秃。热点缓存只给高频 query 用,冷 query 硬缓存反而占内存还没命中。
热点缓存只给高频 query 用,冷 query 硬缓存反而占内存还没命中,我们按命中率动态收缓存,真正热的才留,内存和命中率一起顾住,不贪多。
案例片段(已脱敏): 增量索引与热点缓存配置片段:
yaml index: mode: incremental version_lock: true full_rebuild: weekly hot_cache: key: "q:{query}:v{doc_version}" ttl: 3600 invalidate_on: doc_version_change新鲜度修复日志:[IDX] doc policy-2026 v3 updated, incremental 12s [CACHE] invalidate bucket v2->v3, 3 hot keys dropped [FRESH] latest-hit 0.70 -> 0.98