这道题其实是在问,怎么让大模型在回答时既能拿到外部知识,又能保证拿到的知识是最新的。[[RAG]] 的核心就是给 LLM 配一个可检索的外部知识库,而不是靠它自己的参数硬记。
我先说完整流程,分三个阶段。索引阶段,离线把文档切成块,chunk 大小我一般控制在 256 到 512 tokens,太短缺上下文,太长噪声多。然后拿 [[Embedding]] 模型转成向量,同时把时间戳、来源、类别这些元数据也存下来。最后写入 [[Vector Database]],比如 Milvus 或者 ES,建 [[HNSW]] 索引。这一步有个坑:[[分块]]策略要跟下游任务对齐。如果是客服退款场景,按段落切比固定长度好,因为一个退款流程的上下文往往跨好几个句子。
检索阶段,用户 query 进来,我先做改写,比如补全指代、扩展同义词。然后不是只做向量检索,我一般会加上关键词检索,也就是 [[Hybrid Search]],因为向量擅长语义但可能漏掉精确匹配,比如订单号。召回 top-K 之后再做一轮 [[Rerank]],用 [[Cross-Encoder]] 精排,把相关性低的过滤掉。这么做的前提是重排模型不能太慢,否则延迟扛不住。
生成阶段,把检索结果按相关性排序组装成上下文,控制 token 数,别超模型窗口。然后让 LLM 生成回答。这里有个常见失败场景:检索出的文档互相矛盾时,LLM 可能胡编,所以上线我会特别关注 [[Faithfulness]],比如加一层自检,让模型引用原文。
接下来重点说时效性。知识库里的内容有新旧,如果只按语义相似度取,旧的高质量文章可能永远压过新的,导致回答过时。比如商家满减政策变了,模型还按旧政策回答就会出错。
我的做法是时间衰减加权:最终得分 = 语义相似度 × exp(-λ × 时间差)。λ 控制衰减快慢,新闻类 λ 设大一点,让新内容快速出头;百科类 λ 设小,因为知识半衰期长。但有个风险:λ 调太大,新但质量差的内容会冲上来,压制旧但精准的结果。所以上线前我会用历史 query 回放,调 λ 让 Recall@K 最优。
另一个方案是动态时间窗口:先只搜最近 N 天的数据,如果召回不够再放宽。比如金融公告场景,财报发布后一周内只搜当季数据,没有结果再扩到全库。这样既保证时效,又不会完全丢掉长尾知识。
实际落地,我更倾向把时间衰减和混合检索结合起来。检索时先用时间范围过滤,比如只取最近一年,再在结果里做衰减加权。这样既快又稳。
还有一个细节是,时间戳本身的质量很重要。如果元数据里时间戳不准,比如爬虫抓的新闻发布时间是错的,那所有时效优化都白搭。所以我一般会加一层时间清洗,比如用页面里的发布时间而不是抓取时间。这个清洗策略其实可以单独聊。
最后总结一下:RAG 不是简单的检索加生成,难点在索引和检索阶段的工程细节,尤其是时效性和语义的平衡。我会把时间衰减看成一种先验偏置,而不是绝对规则,具体参数靠业务调优。这样既能保证回答新鲜,又不牺牲精准度。