AI Agent开发学习系列 - langchain之示例选择器2:相关性与多样性兼得-MaxMarginalRelevanceExampleSelector在LangChain中的用法

MaxMarginalRelevanceExampleSelector

MaxMarginalRelevanceExampleSelector 是 LangChain 中用于 Few-Shot Prompt 的一种智能示例选择器。
它的作用是:
在众多示例中,自动选择与当前输入最相关、同时彼此多样性最大的示例,插入到 prompt 里。

主要特点

  • 相关性优先:优先选择与用户输入最相似的示例。
  • 多样性保证:避免选到内容高度重复的示例,提升覆盖面。
  • 适合多样化、复杂任务:如输入分布广、示例数量多时,能自动挑选最有代表性的 few-shot 示例。

典型用法

from langchain.prompts.example_selector import MaxMarginalRelevanceExampleSelector
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS

examples = [
    {"input": "happy", "output": "sad"},
    {"input": "tall", "output": "short"},
    # ...更多示例
]

example_selector = MaxMarginalRelevanceExampleSelector.from_examples(
    examples,
    OpenAIEmbeddings(model="text-embedding-ada-002", openai_api_key="你的API_KEY"),
    FAISS,
    k=2,  # 选出2个最相关且多样的示例
    input_keys=["input"],
)

每次你有新输入时,example_selector 会自动为你挑选最合适的 few-shot 示例,帮助大模型更好地理解任务。

  • MaxMarginalRelevanceExampleSelector 能自动为每次输入挑选最相关且多样化的 few-shot 示例,提升大模型的泛化能力和输出质量。
  • 适合示例数量多、输入分布广的 few-shot 场景。

关于Embeddings

在这段代码中,Embeddings(如 HunyuanEmbeddings 或 OpenAIEmbeddings)的作用是:
把每个示例的输入(如 “happy”、“tall” 等)转换成向量(embedding),用于计算相似度。

  • MaxMarginalRelevanceExampleSelector 需要判断哪些示例和当前输入最相关、最有代表性。
  • 这种“相关性”不是直接比字符串,而是通过“向量空间”来衡量的。
  • Embeddings 类负责把文本(如 “happy”)转成高维向量(如 [0.12, -0.34, …])。
  • 选择器会用这些向量计算“距离”或“相似度”,自动选出最相关、最有多样性的 few-shot 示例。

总结
Embeddings 的作用就是把文本变成“可比”的向量,供示例选择器用来智能筛选最合适的 few-shot 示例。

用腾讯混元 Embeddings + MaxMarginalRelevanceExampleSelector 智能选例 + Few-Shot Prompt + 混元大模型自动补全反义词的完整流程

# 导入必要的库
from langchain.prompts import PromptTemplate
from langchain.prompts.example_selector import MaxMarginalRelevanceExampleSelector
# 不使用OpenAI的embedding模型,改用腾讯混元的Embeddings
from langchain.embeddings.base import Embeddings
from langchain.vectorstores import FAISS
import os
import requests

# 设置API配置
api_base = "https://api.hunyuan.cloud.tencent.com/v1"  # 腾讯混元OpenAI兼容endpoint
api_key = os.environ.get("HUNYUAN_API_KEY")
model = "hunyuan-embedding"

# 定义腾讯混元Embeddings类
# 通过 HTTP 请求腾讯混元 embedding API,把文本转成向量,供后续相似度计算。
class HunyuanEmbeddings(Embeddings):
    def __init__(self, api_key, api_base, model="hunyuan-embedding"):
        self.api_key = api_key
        self.api_base = api_base
        self.model = model

    # 批量文本向量化方法
    def embed_documents(self, texts):
        url = f"{self.api_base}/embeddings"
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        data = {
            "model": self.model,
            "input": texts
        }
        response = requests.post(url, headers=headers, json=data)
        result = response.json()
        return [item["embedding"] for item in result["data"]]

    # 单条文本向量化方法
    def embed_query(self, text):
        return self.embed_documents([text])[0]

# 定义示例数据集
# 这些是 few-shot 的候选示例,后续会自动筛选最相关的插入 prompt。
examples = [
    {"input": "happy", "output": "sad"},
    {"input": "tall", "output": "short"},
    {"input": "hard", "output": "soft"},
    {"input": "big", "output": "small"},
    {"input": "快", "output": "慢"},
    {"input": "高", "output": "低"},
    {"input": "硬", "output": "软"},
]

# 初始化示例选择器
# 用自定义的腾讯混元 Embeddings,把所有示例和输入词都转成向量。
# 用 FAISS 做向量检索,自动选出2个与输入最相关且多样的 few-shot 示例。
example_selector = MaxMarginalRelevanceExampleSelector.from_examples(
    examples,  # 字典列表
    HunyuanEmbeddings(
        api_key=os.environ.get("HUNYUAN_API_KEY"),
        api_base="https://api.hunyuan.cloud.tencent.com/v1"
    ),
    FAISS,
    k=2, # 选出2个最相关且多样的示例
    input_keys=["input"],
)

# 根据输入获取示例的辅助函数
def get_examples_by_inputs(selected_inputs, all_examples):
    return [ex for ex in all_examples if ex["input"] in selected_inputs]

# 根据输入词“多”,自动选出最合适的 few-shot 示例,拼接成完整的 prompt。
# 设置待处理的形容词
adjective = "多"
# 选择相关示例
selected_examples = example_selector.select_examples({"input": adjective}) 
print(selected_examples)

# 定义示例模板
example_prompt = PromptTemplate(
    input_variables=["input", "output"],
    template="原词:{input}\n反义词:{output}",
)

# 构建完整的提示词
prefix = "请给出下列形容词的反义词:"
suffix = f"\n原词:{adjective}\n反义词:"

# 将选中的示例格式化
shots = "\n".join([example_prompt.format(**ex) for ex in selected_examples])
final_prompt = f"{prefix}\n{shots}\n{suffix}"

print(final_prompt)

# 初始化LLM模型
llm = ChatOpenAI(
    api_key=SecretStr(os.environ.get("HUNYUAN_API_KEY", "")),
    base_url="https://api.hunyuan.cloud.tencent.com/v1",
    model="hunyuan-lite",
    temperature=0,  # 设置为0以获得确定性输出
)

# 调用LLM获取结果
result = llm.invoke(final_prompt)
print(result.content)

结果:

[{'input': '高', 'output': '低'}, {'input': '快', 'output': '慢'}]
请给出下列形容词的反义词:
原词:高
反义词:低
原词:快
反义词:慢

原词:多
反义词:
少
  • 这段代码实现了自动选例+few-shot+大模型补全的完整链路。
  • 通过自定义 Embeddings 适配腾讯混元,保证示例选择和大模型调用都用混元生态。
  • 适合需要高质量 few-shot 提示词和中文生态 embedding 的场景。
  • 如果你不插入任何 few-shot 示例,只给大模型一个“原词:多\n反义词:”的 prompt,大模型依然能给出正确答案(比如“少”),因为它本身就有很强的知识和泛化能力。但 few-shot 示例可以让模型更好地模仿你想要的格式、风格,或者在任务更复杂时提升准确率。

你可能感兴趣的:(AI,Agent,学习,人工智能,langchain,prompt,语言模型,python)