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的多样性。