跳到主要内容

RAG 中的新鲜度与相关度权衡:为什么你无法在查询时同时优化两者

· 阅读需 13 分钟
Tian Pan
Software Engineer

一名用户询问你的助手公司的育儿假政策。机器人返回了 12 周,并附带了引用。被引用的文档是 2023 年的正确答案;而人力资源部门在上个季度发布了更新,将其延长到了 16 周。这两个版本都在你的知识库中。由于旧版页面的表述更简洁且模棱两可的内容较少,余弦相似度给 2023 年版本的评分是 0.87,而 2024 年版本的评分是 0.84。较新的文档以 3 个百分点的差距落败,用户得到了一个看似经过审计的错误答案。

这就是时效性与相关性的权衡(freshness-relevance tradeoff),令人不安的是,这在查询时并没有完美的解决方案。如果你增加时效性的权重,检索结果就会偏向于昨天刚编辑过的任何内容——在大多数知识库中,这些通常是高频变动的嘈杂区域,不应作为事实来源。如果你不增加时效性的权重,你给出的答案将基于几个月前就被取代的文档。没有一个全局按钮能同时搞定这两点,大多数团队只有在一些令人尴尬的答案绕过评估套件泄露出去后,才会发现这个问题。

默认架构让这个问题变得隐形。检索系统根据语义相似度对文档进行评分,返回前 k 个结果,并让模型围绕出现的内容编写流畅的文本。对于一个原生的 Embedding 模型来说,“我们的育儿假政策是什么”和“2023 年我们的育儿假政策是什么”这两个查询看起来是一样的;它们在任何使用了这些词汇的文档面前都会得到高分。模型看到了有依据的上下文,追踪记录看起来也很健康,但最终输出的是一个错误的答案,并引用了一个过时的 URL。

为什么纯语义检索在时间维度上会失效

Embedding 的训练目标是捕获含义,而非时间顺序。同一政策页面的两个版本在向量空间中会互为近邻,正是因为它们涵盖了相同的主题。无论哪种表述在余弦相似度上高出那么一点点,它都会胜出,而且这种排名在不同查询中是稳定的——这意味着一个表述干练的坏文档一旦进入索引,就可以无限期地主导检索结果。

最近的学术研究使这一点变得具体。ChronoQA 基准测试由 2019 年至 2024 年间发布的 30 多万篇新闻文章构建而成,旨在评估检索器在具有明确时间约束的问题上的表现。标准的语义检索器得分很低,因为当两个文档讨论同一个职位时,它们的 Embedding 无法区分“现任 CEO”和“三届任期前的 CEO”。相关性信号是正确的,但时间信号完全缺失了。

推论是,单纯增加时效性先验(recency prior)也无法解决问题。加权时效性的检索会欣然将昨天实习生修改错别字的文档排在已经 8 个月没动过、且无需任何改动的权威参考文档之上。编辑的时效性并不能很好地代表内容的时效性,将“最近修改”视为“更相关”奖励的是活跃度而非正确性。

时效性先验——何时奏效

最简单的缓解方法是将语义相似度与时间衰减因子结合起来的融合评分。一个常见的公式如下:

score(q, d, t) = α · cos(q, d) + (1 − α) · 0.5^(age_days(t) / h)

其中 α 权衡相关性与时效性(默认约为 0.7),h 是以天为单位的半衰期(通常的起始点是 14)。文档的时效性贡献每隔 h 天就会减半,并且设定一个绝对底限,以免古老的文档得分降为零。

这在时效性就是答案的查询中效果很好,有时甚至效果惊人。一篇 2025 年评估该方法的论文报告称,在“最新文档检索”任务中,该方法的准确率近乎完美,而纯语义检索得分为零。如果用户问“最近的财报数字是多少”,时效性先验会使正确的文档排名高于那些旧的但语义更契合的匹配项。

陷阱在于,这只有在你将其应用于正确的查询时才有效。如果将同样的先验应用于“公司的创始使命是什么”,你会偏向于任何碰巧提到使命的近期文档,而不是那份已经五年没动过的真实原始文档。时效性先验对于时间敏感的查询是正确的,而对于时间稳定的查询则是积极有害的。为一个平均查询选择的单一全局 α 在面对那些真正关键的查询时,会有一半的时间是错误的。

时间敏感性分类器

下一层是在查询时识别时间敏感性并有选择地应用时效性先验。可以将其视为一种路由:对于像“我们的退款期限是多久”这样的查询,你希望将时效性推到最高,因为答案确实是随时间变化的。对于像“解释我们定价模型的架构”这样的查询,你希望时效性几乎不产生影响,因为规范的解释在设计上就是长期的。

分类器不需要太复杂。一个小模型——甚至是几次(few-shot)LLM 调用——就能可靠地为查询标记时间敏感度评分。信号是很明确的:显式的时间标记(“现在”、“当前”、“本季度”)、本质上易变的实体类型(价格、人数、领导层),以及事实真相会发生偏移的内容领域(政策、定价、库存、新闻)与那些不会发生偏移的领域(架构、历史、哲学、品牌)。生产系统通常将 LLM 分类器与针对高置信度案例的规则层结合使用,对于模糊的案例则回退到模型。

这为你带来了针对每个查询的 α 调整。一个易变的查询得到 α=0.4 和 7 天的半衰期。一个参考性查询得到 α=0.95 和 365 天的半衰期。静态旋钮问题消解了,因为不存在静态旋钮;评分函数是由查询参数化的,而不是由系统参数化的。

这个路由层也是你可以优雅地拒绝某些组合的地方。如果分类器判定查询高度时间敏感,但语料库中没有任何文档在 200 多天内更新过,这就是一个信号,可以提示“此信息可能已过时”,而不是默默地提供过时的内容作为权威答案。

来源波动率评分

与查询侧的时间敏感性互补的是语料库侧的波动率(volatility)。并非知识库中的每篇文档都以相同的速度老化。描述公司使命的页面衰减较慢,而列出当前价格档位的页面则衰减很快。用同样的近时性曲线(recency curve)处理两者是错误的衰减模型。

波动率评分可以针对小规模语料库手动设置,也可以针对大规模语料库从编辑历史中学习。信号存在于版本控制中:每六周编辑一次的文档是高波动的;五年内只有三次提交的文档是低波动的。每篇文档的“知识熵”评分在索引时作为元数据附加,让检索层能够对不同类型的内容应用不同的衰减曲线。

实际效果是检索评分变为:

score(q, d, t) = α(q) · cos(q, d) + (1 − α(q)) · 0.5^(age_days(t) / h(d))

其中 α(q) 是来自时间敏感性分类器的每条查询权重,h(d) 是来自波动率评分的每篇文档半衰期。语义相似度保持不变;评分的时间部分现在既是查询感知的,也是文档感知的。价格页面获得 7 天的半衰期,架构概览获得 365 天的半衰期,而用户查询决定了哪一侧更重要。

显式波动率评分的二阶收益是它让过时审计(staleness audit)浮出水面。一旦每篇文档都有了波动率标签和时长,你就可以计算语料库中存在多少“高波动、高时长”的文档——这个数字是失败的前导指标。如果一个知识库中有 12% 的高波动文档超过了预期的更新窗口,那么这个知识库的回答质量正在衰减。大多数团队只有在收到投诉后才会发现这一点;而审计让你能从索引中发现它。

权衡演变为架构问题之处

一旦你接受没有静态公式适用于所有查询,架构就必须改变以支持基于查询的参数化。检索层不再是“对查询进行嵌入,返回 top-k”。而是“分类查询,查找分类器导出的参数,使用文档侧元数据计算融合评分,返回 top-k,然后在分类器和语料库不一致时选择性地在响应中进行对冲(hedge)”。

这比教科书上的 RAG 图解需要更多代码,大多数团队都低估了这一点。波动率元数据必须得到维护——要么在摄取(ingestion)过程中从编辑历史推断,要么作为文档 frontmatter 的一部分进行策展(curated)。分类器必须经过训练或提示(prompted),其输出必须反馈给评分函数,而不是留在单独的分析仪表盘中。评估套件必须同时包含时间敏感和时间稳定的查询,因为针对其中一个进行优化会悄无声息地导致另一个退化。

更深层次的认识是,新鲜度与相关性之间的权衡不是一个调优问题,而是一个建模问题。错误在于将“相关性”视为将文档与查询进行排名的单一标量。真正的相关性至少是二维的:这篇文档回答查询的效果如何,以及它给出的答案在多大程度上仍然正确。纯语义检索优化了前者而忽略了后者。近时性加权检索优化了后者的代理指标,却污染了前者。你无法将它们折叠成一个在任何地方都通用的数字;你必须分别对它们评分,并根据查询和文档的权重进行组合。

这对你的评估套件意味着什么

如果你的检索评估只针对一组静态的“问题-文档”对评分 top-k 准确率,那么你的系统可能通过所有测试,但在时间上仍然是错误的。这里有两个评估鸿沟往往会让团队吃亏。

首先是静态评估集会因过时而失效。当政策变为 14 天后,一个在政策为 60 天时编写的测试用例仍会标记错误答案为正确,因为没人更新评估。评估套件必须包含新鲜度检查:当源文档发生变化时,重新生成受影响的预期答案,或者至少标记它们以供审查。

其次是平均准确率指标掩盖了时间敏感型的失败模式。一个检索器在整体上可能达到 88% 的准确率,但在依赖最近更新的查询子集上只有 30% 的准确率——由于时间敏感的子集只占总流量的一小部分,仪表盘会显示“一切正常”。按时间敏感性类别切分准确率可以让差距显现出来。将“陈旧检索率”作为一级指标也是如此:即 top 结果已被检索器未找出的更近文档所取代的检索比例。

这些指标的前提是首先拥有时间敏感性分类器和每篇文档的波动率评分。驱动每条查询 α 的相同机制也驱动了评估切分。构建一次,配置一次,系统的新鲜度行为就会变得清晰可见,而不是由用户投诉引发的基于“感觉(vibes)”的争论。

坦诚的结论

新鲜度与相关性之间的权衡是检索工程中极少数的情况之一,在这种情况下,教科书式的架构在结构上存在缺陷,而不仅仅是缺乏微调。对于不同时效的文档和不同时间敏感度的查询,使用单一的相似度得分会导致相当一部分流量出现错误,且下游任何程度的提示词工程都无法修复检索到错误文档的问题。

解决方案是放弃单一的全局开关,转而对双端进行评分参数化——通过时间敏感度分类器处理查询端,并通过易变性得分处理文档端。其代价是检索层变得更加复杂,并需要显式的元数据流水线。而回报则是,系统能基于同一个索引、使用同一个模型,同时正确回答“我们的创立使命是什么”和“今天的退款窗口期是多久”,且无需操作员为每种新的查询类型手动调整 α 参数。

如果你的 RAG 系统的错误集中在那些关于近期变化的问题上,答案并不是重新训练嵌入器,而是要承认检索是一个双轴问题,并开始以这种方式进行评分。

References:Let's stay in touch and Follow me for more thoughts and updates