AI Agent白手起家31: 根据语义相似度动态选择 Few Shot 示例
纲要
- 动态示例选择进阶:从长度到语义
- 核心概念
SemanticSimilarityExampleSelector:基于语义相似度从示例池中选择与输入最相关的示例- 向量嵌入(Embedding)与向量数据库(如
Chroma) - 余弦相似度:衡量向量空间距离的常用算法
- 关键流程:准备示例 → 定义嵌入模型和向量数据库 → 创建选择器 → 组合 Few Shot 提示词模板 → 调用 LLM
- 涉及组件:
langchain_core.example_selectors、langchain_community.embeddings、langchain_community.vectorstores - 代码演示:完整可运行的 Python 脚本,使用
FakeEmbeddings模拟嵌入过程,无需外部 API Key
引言
在上一篇文章中,我们介绍了根据长度动态截取示例的 LengthBasedExampleSelector,它虽然能够控制上下文窗口的大小,但选择逻辑过于机械:只是从列表头部开始依次添加示例,完全不考虑示例与当前输入的相关性。如果示例池里混杂了中文和英文、天气和情绪等多种场景,长度选择器很可能给出与当前任务毫不相干的例子。
LangChain 提供了另一种更智能的选择器——SemanticSimilarityExampleSelector,它利用文本嵌入技术,将输入和示例都映射到向量空间,然后通过计算余弦相似度,从示例池中选出语义最接近的 Top-K 个示例。这种方式可以轻松实现跨语言、跨领域的精准匹配,让 Few Shot 提示真正“看懂”输入的内容。
工作原理
其本质是检索增强生成(RAG)在提示词构建阶段的应用,整体流程如下:
- 向量化:使用嵌入模型(Embedding Model)将文本转换为高维向量。
- 存储:将示例向量存入向量数据库(本文使用轻量级的 Chroma)。
- 查询:将用户输入也向量化,通过余弦相似度计算与各示例向量的距离,返回距离最近(即语义最相似)的 K 个示例。
完整可运行代码
为了让你无需任何外部 API Key 即可运行,本示例使用 FakeEmbeddings 模拟向量嵌入。实际项目中只需替换为真实的嵌入模型(如 OpenAI 或 HuggingFace 模型),代码结构完全一致。
首先安装依赖:
pip install langchain langchain-core langchain-community chromadb
核心代码:
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
from langchain_core.example_selectors import SemanticSimilarityExampleSelector
from langchain_community.embeddings.fake import FakeEmbeddings
from langchain_community.vectorstores import Chroma
# 1. 准备示例池(反义词任务)
examples = [
{"input": "happy", "output": "sad"},
{"input": "高兴", "output": "悲伤"},
{"input": "sunny", "output": "gloomy"},
{"input": "晴朗", "output": "阴沉"},
{"input": "big", "output": "small"},
]
# 2. 定义示例格式化模板
example_prompt = PromptTemplate(
input_variables=["input", "output"],
template="原词: {input}\n反义词: {output}"
)
# 3. 创建语义相似度示例选择器
# 使用 FakeEmbeddings 模拟嵌入,size 参数指定向量维度
embedding_model = FakeEmbeddings(size=128)
example_selector = SemanticSimilarityExampleSelector.from_examples(
examples=examples,
embeddings=embedding_model,
vectorstore_cls=Chroma, # 使用 Chroma 作为向量数据库
k=1, # 每次选择最相似的 1 个示例
)
# 4. 构建动态 Few Shot 提示词模板
dynamic_prompt = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=example_prompt,
prefix="给出每个输入词的反义词:",
suffix="原词: {input}\n反义词:",
input_variables=["input"],
)
# 5. 测试:输入英文情绪词,期望选中情绪相关示例
print("=== 输入: worried ===")
print(dynamic_prompt.format(input="worried"))
print()
# 6. 测试:输入中文天气词,期望选中天气相关示例
print("=== 输入: 晴朗 ===")
print(dynamic_prompt.format(input="晴朗"))
运行后可以看到,worried 会匹配到情绪相关的示例(如 happy/sad),晴朗 则匹配到天气相关的示例(如 sunny/gloomy 或 晴朗/阴沉)。注意 FakeEmbeddings 使用随机向量,因此结果可能略有随机性;若换成真实嵌入模型,匹配会非常精准。
与长度选择器的对比
| 特性 | 长度选择器 (LengthBasedExampleSelector) |
语义选择器 (SemanticSimilarityExampleSelector) |
|---|---|---|
| 选择依据 | 示例字符数 + 顺序 | 输入与示例的语义相似度 |
| 能否跨语言 | 不支持 | 支持(嵌入模型通常跨语言) |
| 计算开销 | 极低 | 较高(需向量化和相似度搜索) |
| 适用场景 | 示例少且顺序重要 | 示例多、任务多变、要求高相关性 |
使用建议
- 嵌入模型选型:对中文任务推荐使用
text-embedding-ada-002(OpenAI)或开源的BAAI/bge-large-zh,它们对中英文混合场景支持良好。 - Top-K 设置:
k值一般设为 1~3,过多示例可能引入噪声。可根据实际效果调整。 - 向量数据库:Chroma 适合原型开发和小规模数据;生产环境可考虑 FAISS、Pinecone、Milvus 等。
- 示例池维护:定期更新示例池并重新生成向量,以保持与最新任务的语义一致性。
总结
SemanticSimilarityExampleSelector 将检索增强生成(RAG)的向量检索思路应用于提示词工程,让 Few Shot 示例的选择从“机械截断”进化为“智能检索”。
它充分利用了嵌入模型捕捉语义的能力,无论输入是中文还是英文,都能从庞大的示例池中精准捞出最有参考价值的样例,大幅提升 Few Shot 的命中率和回答质量。
更多推荐

所有评论(0)