向量检索返回五段内容,四段都来自同一份文档的相邻位置。它们与问题很像,放进模型上下文以后却重复占地方。最大边际相关性专门处理这种取舍。它一边看候选与问题有多相关,一边看候选与已经选中的内容有多相似。
这个方法简称 MMR。1998 年的论文把它用于文档重排和摘要选择,目标是减少冗余,同时保住查询相关性。我又对照了 LangChain 当前的向量库接口和内存实现,今天常见的 RAG 工具仍在使用同一类逐项选择思路。
每选一条,后面的标准都会变化
普通相似度排序可以一次算完,最像查询的排在前面。MMR 先选最相关的候选,随后每增加一条,都重新考虑剩余候选与已选结果的重复程度。某段内容分数很高,但与第一段几乎相同,它可能让位给稍低一点、却补充了新信息的段落。
这也解释了名称里的“边际”。要判断下一条新加入的内容能带来多少增量。原论文在信息检索和多文档摘要环境中讨论这个问题,它没有承诺任何一组向量都能自动得到全面答案。相关性与新颖性的计算仍依赖表示方法和候选质量。
LangChain 的接口里有三个容易混淆的数量。fetch_k 决定先从向量库取多少候选,k 决定最后返回多少条,lambda_mult 在相关性与多样性之间调节。当前文档说明,值接近 1 时更看重查询相似,接近 0 时更强调结果之间的差异。
多样性过头会把边缘材料带进来
用户问一种具体设备的故障,最相关的几个段落可能本来就会重复同一操作。为了多样而压低这些段落,反倒可能选进只沾一点边的说明。MMR 没有一个脱离任务的最佳参数。知识问答、商品推荐和摘要,各自能接受的重复程度不同。
候选范围也很关键。实现通常先取 fetch_k 条,再从中做 MMR。正确资料没有进入这批候选,后面的重选无法补回。fetch_k 过小,多样选择没有空间。取得太大,计算和读取量都会增加,还可能带入许多弱相关内容。
实际试验可以保存两份结果。一份按纯相似度取前 k 条,一份用 MMR 从相同候选池里选。人工检查每条是否回答问题、是否只是相邻重复,并观察最终答案有没有漏掉必要步骤。只看五条文字长得更不一样,很难证明回答变好了。
MMR 适合处理候选已经相关、重复又明显的情况。先取回相关资料。资料压根没找到时,应先查切块、查询与索引。两类问题分开,调参数才不会变成碰运气。