MMR最大边际相关性

MMR(最大边际相关性,Maximal Marginal Relevance)的核心公式如下:

MMR = λ ⋅ Sim₁(Di, Q) - (1 - λ) ⋅ max Sim₂(Di, Dj)

这个公式的含义是:在构建 Few-Shot 提示词时,系统会从你的示例库(examples)中,贪心地挑选出下一个最能平衡"相关性"和"多样性"的示例加入最终列表。

公式中各项参数的具体含义如下:

Di:当前正在被评估的候选示例(比如你示例库里的 {"question": "高", "answer": "低"})。

Q:用户的实际输入(比如你代码中的 input="个子")。

Dj:已经被选中放入最终提示词里的示例集合。

Sim₁(Di, Q):相关性得分。衡量候选示例 Di 和用户输入 Q 的语义相似度。在你的代码中,Embedding 模型会计算"高"和"个子"的向量距离,距离越近得分越高。

max Sim₂(Di, Dj):多样性惩罚项。衡量候选示例 Di 与已选示例 Dj 的最大相似度。如果 Di 和已经选中的示例长得很像,这一项的值就会很大,导致 MMR 总分被扣减,从而避免选出重复或过于相似的示例。

λ (Lambda):平衡因子(取值范围 0 到 1)。它决定了算法更偏向哪一边:

λ 接近 1:极度看重相关性,选出的示例会和用户输入最贴近(退化为纯相关性排序)。

λ 接近 0:极度看重多样性,选出的示例会尽量互不相同,哪怕和用户输入关系不大。

简单来说,MMR 的打分逻辑就是:

最终得分 = 相关性奖励 - 重复性惩罚

算法筛选大致过程:

假设你的示例库 examples 里有4个例子:[开心, 高, 精力充沛, 粗]。

现在用户输入了 "走",算法开始工作:

如果我们设置需要两个示例即k=1,则进行1轮筛选,k=2则是2轮筛选。

csharp 复制代码
example_selector = MaxMarginalRelevanceExampleSelector.from_examples(
    examples,
    embeddings,
    FAISS,
    k=1  #这里的 k 决定了挑选的轮数
)

我们假设 λ = 0.5(即相关性和多样性各占一半权重)。

第一轮挑选:只看相关性

此时最终的结果集 S 还是空的,没有任何元素被选中,所以公式里的 Dj ∈ S(已选集合)为空。 因为没有

Dj,公式后半部分的"多样性惩罚项" (1 - λ) ⋅ max Sim₂(Di, Dj) 也就无从计算,直接视为 0。

所以,第一次计算时,MMR 公式实际上退化成了: MMR = λ ⋅ Sim₁(Di, Q)

这意味着,算法会直接从候选池里,挑出那个和用户输入 Q 最相关、得分最高的 Di,作为第一个被选中的元素。

此时已选集合 S 是空的,没有 Dj,所以不需要计算多样性惩罚。公式退化为:MMR = 0.5 × 相关性。

算法会把"走"和四个备选示例的 question 进行语义相似度对比:

开心 vs 走:语义不相关,假设相似度 0.1 → 得分 0.05

高 vs 走:语义不相关,假设相似度 0.05 → 得分 0.025

精力充沛 vs 走:语义不相关,假设相似度 0.1 → 得分 0.05

粗 vs 走:语义不相关,假设相似度 0.05 → 得分 0.025

结果:虽然都很不相关,但"开心"和"精力充沛"勉强排在前两名。假设"开心"以微弱优势胜出。

动作:{开心, 伤心} 被选中,放入已选集合 S。

此时 S = {开心}。

第二轮挑选:相关性与多样性并重

现在 S 里已经有了 {开心},它变成了 Dj。算法在评估剩下的三个备胎(高、精力充沛、粗)时,不仅要算它们和"走"的相关性,还要算它们和已入选的"开心"的相似度(作为惩罚项)。

公式:MMR = 0.5 × 相关性 - 0.5 × max(与"开心"的相似度)

候选者:高

与"走"的相关性:极低 (0.05)

与 Dj"开心"的相似度:极低 (0.1)

最终得分:0.5×0.05 - 0.5×0.1 = -0.025

候选者:精力充沛

与"走"的相关性:极低 (0.1)

与 Dj"开心"的相似度:极高 (0.9) (因为"精力充沛"和"开心"都是形容积极情绪的词)

最终得分:0.5×0.1 - 0.5×0.9 = -0.4 (被严重扣分!)

候选者:粗

与"走"的相关性:极低 (0.05)

与 Dj"开心"的相似度:极低 (0.1)

最终得分:0.5×0.05 - 0.5×0.1 = -0.025

结果:虽然大家的得分都是负的(因为跟"走"都不相关),但"高"和"粗"因为没有被惩罚,分数远高于"精力充沛"。假设"高"胜出。

动作:{高, 低} 被选中,放入已选集合 S。

此时 S = {开心, 高}。

问题:

为什么跟Dj相似就要惩罚?

跟 Dj 相似就要惩罚,核心原因是为了消除信息冗余,提升结果的多样性。

保证Di和Q的相似性,降低 S集合中Dj的相似性,保证 Dj的多样性。

相关推荐
handler011 小时前
速通蓝桥杯省一:二分算法
c语言·开发语言·c++·笔记·算法·职场和发展·蓝桥杯
炽烈小老头1 小时前
【 每天学习一点算法 2026/05/08】最小覆盖子串
学习·算法
汉克老师2 小时前
GESP5级C++考试语法知识(十六、分治算法(三))
c++·算法·分治算法·汉诺塔·逆序对·gesp5级·gesp五级
V搜xhliang02462 小时前
OpenClaw进阶完全教程
运维·人工智能·算法·microsoft·自动化
叼烟扛炮2 小时前
C++ 知识点12 构造函数
开发语言·c++·算法·构造函数
满天星83035772 小时前
定长内存池ObjectPool
数据结构·c++·算法·链表
叼烟扛炮2 小时前
C++第八讲:string 类
开发语言·c++·算法·string
Chase_______2 小时前
LeetCode 1493 & 3634 题解:滑动窗口双指针,从“删一个元素的全1子数组“到“最少移除使数组平衡“
算法·leetcode
悲伤小伞2 小时前
LeetCode 热题 100_4-283. 移动零
算法·leetcode·职场和发展