AI Agent白手起家32: MMR与最大余弦相似度选择示例
内容纲要
- 回顾余弦相似度选择器的优势与局限
- 最大边际相关性(MMR)算法
- 目标:在相关性与多样性之间取得平衡
- 核心机制:惩罚与已选示例过于相似的样本
- LangChain 中的 MMR 示例选择器
MaxMarginalRelevanceExampleSelector- 与余弦相似度选择器的对比
- 完整可运行代码:使用 FAISS 向量库与
FakeEmbeddings模拟嵌入 - 适用场景与选型建议
引言
在上一篇文章中,我们介绍了基于余弦相似度的 SemanticSimilarityExampleSelector,它能够从示例池中精准地找出与输入语义最相似的 Top-K 个示例。然而,当示例池中存在大量高度相似的样本时(比如几乎相同的双语版本),余弦相似度选择器往往会返回多个“同质化”的示例,这些示例虽然都与输入相关,但彼此之间却没有提供额外的多样性信息。
为了解决这个问题,LangChain 提供了基于最大边际相关性(Maximal Marginal Relevance,简称 MMR)的示例选择器。MMR 在保证示例与输入相关的同时,刻意避免选出过于雷同的样本,从而让 Few Shot 提示中的示例更具代表性,覆盖更多视角。
MMR 算法原理
MMR 最初应用于信息检索和文本摘要领域,其核心思想是:在每一步选择新的结果时,既考虑该结果与查询的相关性,又考虑其与已选择结果的差异性。在示例选择场景中,MMR 会先找到与输入最相似(余弦相似度最大)的示例,然后在对后续示例进行评分时,对那些与已选示例相似度过高的样本施加“惩罚”,使其得分降低。
这样,最终选出的 Top-K 个示例既能保持与任务的高度相关,又能尽量分散在语义空间的不同方向上,从而向模型提供更丰富的参考信息。
MMR 与余弦相似度选择器的对比
下表直观展示了两种选择器在相同输入下的行为差异(以文中“难过”为例,示例池包含中英文情绪词、天气词以及体型词):
| 选择器类型 | 输入 | K 值 | 返回示例 | 特点 |
|---|---|---|---|---|
| 余弦相似度 | 难过 | 2 | 高兴/悲伤, happy/sad |
两个示例高度同质(中英对照),仅体现情绪维度 |
| MMR | 难过 | 2 | 高兴/悲伤, tall/short 或 big/small |
第一个示例最相关,第二个示例来自不同语义方向,增加多样性 |
可见,MMR 避免了“把鸡蛋放在一个篮子里”的问题,尤其适用于示例池规模较大且存在多条近似示例的场景。
完整可运行代码
以下代码使用 FAISS 向量库和 FakeEmbeddings 模拟嵌入过程,演示 MaxMarginalRelevanceExampleSelector 的用法。无需任何外部 API Key 即可运行。
安装依赖:
pip install langchain langchain-core langchain-community faiss-cpu
核心代码:
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
from langchain_core.example_selectors import MaxMarginalRelevanceExampleSelector
from langchain_community.embeddings.fake import FakeEmbeddings
from langchain_community.vectorstores import FAISS
# 1. 构建示例池(包含中英文、情绪与体型等多类反义词)
examples = [
{"input": "happy", "output": "sad"},
{"input": "高兴", "output": "悲伤"},
{"input": "sunny", "output": "gloomy"},
{"input": "晴朗", "output": "阴沉"},
{"input": "tall", "output": "short"},
{"input": "高", "output": "矮"},
]
# 2. 示例格式化模板
example_prompt = PromptTemplate(
input_variables=["input", "output"],
template="原词: {input}\n反义词: {output}"
)
# 3. 创建 MMR 示例选择器
# 使用 FakeEmbeddings(size=128) 模拟嵌入
embedding_model = FakeEmbeddings(size=128)
mmr_selector = MaxMarginalRelevanceExampleSelector.from_examples(
examples=examples,
embeddings=embedding_model,
vectorstore_cls=FAISS,
k=2, # 返回 2 个示例
fetch_k=5, # 先获取 5 个候选再从中做 MMR 筛选
)
# 4. 构建 Few Shot 提示词模板
mmr_prompt = FewShotPromptTemplate(
example_selector=mmr_selector,
example_prompt=example_prompt,
prefix="给出每个输入词的反义词:",
suffix="原词: {input}\n反义词:",
input_variables=["input"],
)
# 5. 测试:输入中文情绪词“难过”
print("=== 输入: 难过 ===")
print(mmr_prompt.format(input="难过"))
运行后,难过 会优先匹配到 高兴/悲伤 这一最相关的示例,而第二个示例可能是 tall/short 或 big/small 等与情绪无关但能提供其他维度信息的条目,从而实现了多样化的 Few Shot 示例组合。
适用场景与选型建议
- 优先选用余弦相似度选择器的情况:示例池规模较小,且每条示例都具有不可替代的独特信息;任务对多样性的要求不高,最相关的一两条示例即可满足需求。
- 推荐使用 MMR 选择器的情况:示例池中包含大量语义重复或中英对照的“冗余”样本;希望用较少的 K 覆盖更多的语义方向,提高提示的泛化能力。
- 参数调优:
fetch_k参数决定了从向量库中初筛出多少个候选,然后再执行 MMR 算法从中选出k个。适当增大fetch_k可以给 MMR 提供更大的选择空间,但也会增加计算开销。
总结
MMR 示例选择器是余弦相似度选择器的有力补充,它通过引入多样性惩罚机制,有效避免了示例同质化问题。
在示例池庞大且存在大量相似样本的情况下,MMR 能够以更少的示例数量提供更全面的参考信息,从而进一步提升大模型 Few Shot 学习的效率与效果。
更多推荐
所有评论(0)