LangChain 示例选择器(Example selectors)完整基础概念解读

发布时间:2026/8/21 11:23:04
LangChain 示例选择器(Example selectors)完整基础概念解读 我挖掘了一个巨牛的 人工智能 学习网站通俗易懂风趣幽默忍不住分享一下给大家。点击跳转到网站。前言核心背景为什么需要示例选择器少样本提示的矛盾点给模型提供越多示例任务规则、输出格式越清晰模型效果越好 但示例全部塞进提示词会带来三大问题Token 变多调用成本上升、响应延迟更高超出模型上下文窗口直接报错截断过量无关示例会干扰模型判断反而降低准确率。业务场景痛点当你的示例库规模很大几十、上百条不可能一次性全部放入提示词。 此时不能固定写死少量examples[...]需要一套动态筛选机制针对用户当下输入自动挑最合适的一小批示例送入提示词。示例选择器的定位专门负责接收完整示例库 用户当前输入按照指定算法策略输出一小段最优示例子集供给少样本模板FewShotPromptTemplate/FewShotChatMessagePromptTemplate拼接提示词。所以说示例选择器本质只是一个组件需要搭配着模板使用示例选择器本质是筛选示例筛选完还是需要套入模板传给大模型调用。调用完整流程示例选择器 (筛选) → 选中的示例 → 套入模板 → 最终提示词 → 传给大模型1、按长度选择LengthBasedExampleSelector 完整讲解1.1、核心作用当你批量放入很多少样本示例时如果全部塞进提示词很容易超出模型上下文窗口限制、token 超限报错。LengthBasedExampleSelector会自动从示例列表里挑选若干样本控制拼接后的总文本长度不超过你设定的max_length动态删减样本避免上下文溢出。它只会配合老式文本模板FewShotPromptTemplate使用不支持对话模板 FewShotChatMessagePromptTemplate。1.2、构造参数逐行拆解example_selector LengthBasedExampleSelector( examplesexamples, example_promptexample_prompt, max_length25, # get_text_length: 自定义长度计算函数 )参数讲解1.examplesexamples原始样本列表就是你存放所有输入输出样例的数组会被选择器读取。 示例examples [ {input: happy, output: sad}, {input: tall, output: short}, {input: energetic, output: lethargic}, ]2.example_promptexample_prompt单条示例的格式化模板选择器必须知道一条样本格式化后长什么样才能计算单条占用长度。 我定义的模板example_prompt PromptTemplate.from_template(Input: {input}\nOutput: {output})每条样本会先套用模板拼接成完整文本再计算长度。3.max_length25关键阈值允许所有选中示例拼接后的总最大长度按单词 / 字符统计取决于get_text_length。 选择器逻辑从列表从头依次加入样本每加入一条累加当前总长度如果再加下一条会超过max_length就停止不再纳入后续样本最终只保留前面累加后不超限的样本。举个直观例子max_length25第一条格式化Input: happy\nOutput: sad→ 统计长度 8累加 8小于 25保留第二条Input: tall\nOutput: short→ 长度 7累加 15保留第三条Input: energetic\nOutput: lethargic→ 长度 12累加 151227 25舍弃第三条最终提示词只会包含前两条示例。注意是所有示例加起来总长度不是单条示例上限。4.get_text_length长度统计函数可选有默认默认内置函数lambda x: len(re.split(\n| , x))逻辑把格式化后的示例文本按换行\n、空格 切分成单词列表返回列表元素个数以单词数量作为长度单位。1.3两种自定义场景想按字符数统计长度替代单词import re # 按字符串字符长度计算 def count_char(text: str) - int: return len(text) example_selector LengthBasedExampleSelector( examplesexamples, example_promptexample_prompt, max_length100, get_text_lengthcount_char )2.想要按 token 数量精准控制最贴合 LLM 配合 tiktoken open AI官方统计真实 token精准防止超限import tiktoken from langchain_core.example_selectors import LengthBasedExampleSelector # 初始化编码器根据您的模型选择 encoding tiktoken.encoding_for_model(gpt-3.5-turbo) # 或 gpt-4 def token_length(text: str) - int: 计算文本的 token 数量 return len(encoding.encode(text)) example_selector LengthBasedExampleSelector( examplesexamples, example_promptexample_prompt, max_length25, # 最大 token 数 get_text_lengthtoken_length # 自定义函数 )1.4、完整运行流程FewShotPromptTemplate格式化提示词时会调用example_selector.select_examples({adjective: angry})选择器循环遍历examples用example_prompt渲染单条文本调用get_text_length计算单条长度持续累加一旦累加值触碰max_length停止读取剩余样本返回筛选后的小样例列表交给FewShotPromptTemplate拼接进提示词。1.5、使用限制与注意事项只能搭配 FewShotPromptTemplate文本模板对话式FewShotChatMessagePromptTemplate不支持任何 example_selector二者互斥。样本遍历顺序固定从头往后累加只会保留前面的样本后面长样本会被丢弃如果想优先匹配语义相似样本改用SemanticSimilarityExampleSelector相似度选择器。和examples参数互斥FewShotPromptTemplate里传了example_selector就不能再写examples[]二选一。如下面的代码# 正确 few_shot_prompt FewShotPromptTemplate( example_selectorexample_selector, example_promptexample_prompt, prefix给出每个输入的反义词, suffixInput: {adjective}\nOutput: , input_variables[adjective], ) # 错误不能同时写 # few_shot_prompt FewShotPromptTemplate( # examplesexamples, # example_selectorexample_selector, # )1.6、适用场景 对比其他选择器适用 LengthBasedExampleSelector示例无区分优先级随便保留前几条即可主要需求防止提示词文本过长、简单控制上下文长度不需要语义匹配所有样本任务逻辑一致。对比语义相似度选择器 SemanticSimilarityExampleSelectorLengthBasedExampleSelector按长度截断顺序优先无语义速度快不需要向量库SemanticSimilarityExampleSelector根据当前用户输入语义挑选最相似样本效果更好但依赖向量数据库、额外向量计算开销更大。1.7、优缺点总结优点开箱即用无需向量库零额外依赖自动控制提示词长度解决上下文超限报错支持自定义长度统计规则字符 / 单词 /token。缺点只按顺序截取不关心样本和当前提问的相关性后面高价值长样本会直接被舍弃仅支持老式文本少样本模板对话模板无法使用。完整代码调用from langchain.prompts import FewShotPromptTemplate, PromptTemplate from langchain.prompts.example_selector import LengthBasedExampleSelector from langchain_openai import ChatOpenAI import tiktoken # 1. 准备数据 all_examples [ {word: happy, antonym: sad}, {word: big, antonym: small}, {word: hot, antonym: cold}, {word: fast, antonym: slow}, {word: bright, antonym: dark}, ] # 2. 定义单个示例的模板最终套用的模板 example_prompt PromptTemplate( input_variables[word, antonym], templateInput: {word}\nOutput: {antonym}\n ) # 3. 创建示例选择器只负责筛选 def token_count(text): return len(tiktoken.encoding_for_model(gpt-3.5-turbo).encode(text)) example_selector LengthBasedExampleSelector( examplesall_examples, example_promptexample_prompt, # 选择器用这个模板来计算长度 max_length30, # 筛选条件总长度不超过30 tokens get_text_lengthtoken_count ) # 4. 创建完整模板选择器 模板的组合 few_shot_prompt FewShotPromptTemplate( example_selectorexample_selector, # 注入选择器 example_promptexample_prompt, # 注入单示例模板 prefix请给出反义词, # 前缀 suffixInput: {adjective}\nOutput: , # 后缀含变量 input_variables[adjective], ) # 5. 格式化选择器筛选 套入模板 final_prompt few_shot_prompt.format(adjectiveangry) # 6. 传给大模型 llm ChatOpenAI(modelgpt-3.5-turbo) response llm.invoke(final_prompt)max_length25 完整含义1. 定义max_length是所有被选中示例格式化拼接后的总长度上限单位由get_text_length函数决定默认是「单词数」。 25 允许纳入提示词的所有示例加起来最多 25 个单词。2.默认长度计算规则get_text_length 底层逻辑# 默认函数 lambda x: len(re.split(\n| , x))把格式化后的示例文本默认按换行、空格切割统计切出来片段的总数当作 “单词数量”。示例单条模板Input: happy Output: sad切割拆分结果[Input:, happy, Output:, sad]→ 长度 43. 选择器筛选流程演示结合反义词样例examples [ {input: happy, output: sad}, # 格式化后单词数4 {input: tall, output: short}, # 4 {input: energetic, output: lethargic}, #4 {input: sunny, output: gloomy}, #4 {input: windy, output: calm}, #4 ] max_length25第一条累计 4 ≤25保留第二条累计 8 ≤25保留第三条累计 12第四条累计 16第五条累计 20 五条全部加起来总单词数 20小于 25全部保留。如果每条单词数更大累加超过 25 就停止读取后面样本 比如每条占 7 个单词4 条累加 28 25则只保留前 3 条。4. 关键两点容易误解❌ 不是单条示例最多 25 个单词 ✅ 是全部选中示例总和不超过 25❌ 不是字符个数 ✅ 默认是按空格 / 换行分割后的单词计数 如果你想改成按字符、token 统计可以自定义get_text_length。5. 举例切换成按字符统计def count_char(text: str) - int: return len(text) example_selector LengthBasedExampleSelector( examplesexamples, example_promptexample_prompt, max_length100, # 此时代表总字符上限100 get_text_lengthcount_char )6. 设计目的限制示例总长度防止示例太多导致提示词整体过长超出模型上下文窗口、触发报错。语义相似性选择示例3.4.3 按语义相似性选择示例SemanticSimilarityExampleSelector知识点整理3.4.3.1 核心概念1. 语义相似定义衡量两段文本内在含义的贴近程度而非字面文字重合度可解决一词多义、字面相近但含义无关的问题。示例 1text1 我喜欢猫text2 我讨厌狗 字面文字差异大但语义都在表达对小动物的喜好态度语义相似度高。示例 2text1 苹果很甜水果text2 苹果市值创新高科技公司 字面都含 “苹果”但指代完全不同语义相似度极低。2. 底层实现原理通过嵌入模型Embedding将文本转为高维数字向量计算用户输入向量与所有示例向量的余弦相似度筛选出余弦相似度最高的 k 条示例放入提示词。3. 适用场景示例库量大需要动态匹配和用户提问含义最贴合的样例替代固定示例、按长度截断的简单筛选大幅提升少样本效果。3.4.3.2 核心类与内置方法类路径langchain_core.example_selectors.semantic_similarity.SemanticSimilarityExampleSelector1. 静态构造方法 from_examples ()最常用作用一次性加载示例集自动完成向量化、存入向量库生成选择器实例 入参examples示例字典列表每条示例是{变量名:文本}结构embeddings嵌入模型实例用于文本向量化OpenAIEmbeddings / BGE 本地向量vectorstore_cls向量数据库类用于存储向量、相似度检索Chroma/FAISSk每次检索返回语义最接近的示例数量默认值 4 返回值语义相似度示例选择器对象2. add_example(example: dict[str, str])作用运行时动态新增单条示例自动向量化存入向量库 入参单条示例字典格式和初始化 examples 保持一致3. select_examples(input_variables: dict[str, str]) → list[dict]作用接收用户输入执行向量检索返回筛选后的示例子集 入参用户输入变量字典和模板占位符匹配 返回值匹配到的相似示例列表3.4.3.3 完整标准代码官方原版OpenAI 向量前置安装命令# 新版langchain分离包必须安装 pip install -U langchain-chroma chromadb langchain-openaifrom langchain_chroma import Chroma from langchain_core.example_selectors import SemanticSimilarityExampleSelector from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate from langchain_openai import OpenAIEmbeddings # 1. 反义词示例数据集 examples [ {input: happy, output: sad}, {input: tall, output: short}, {input: energetic, output: lethargic}, {input: sunny, output: gloomy}, {input: windy, output: calm}, ] # 2. 单条示例格式化模板 example_prompt PromptTemplate( input_variables[input, output], templateInput: {input}\nOutput: {output}, ) # 3. 构建语义相似选择器 example_selector SemanticSimilarityExampleSelector.from_examples( examples, OpenAIEmbeddings(), # 云端OpenAI向量模型 Chroma, # 向量存储数据库 k1, # 每次只选1条最相似示例 ) # 4. 组装完整少样本文本模板 similar_prompt FewShotPromptTemplate( example_selectorexample_selector, # 使用选择器替代固定examples列表 example_promptexample_prompt, prefix给出每个输入的反义词, suffixInput: {adjective}\nOutput:, input_variables[adjective], ) # 5. 执行格式化打印完整提示词文本 res_text similar_prompt.invoke({adjective: worried}).to_messages()[0].content print(res_text)运行输出给出每个输入的反义词 Input: happy Output: sad Input: worried Output:结果说明用户输入worried焦虑的属于情绪类词汇向量计算后和happy开心语义最贴近因此自动筛选出这条情绪相关示例。3.4.4 按最大边际相关性选择示例MMR知识点整理3.4.4.1 核心概念1. MMR 定义最大边际相关性Max Marginal Relevance是一种重排序算法以语义相似度为基础从候选示例集中选出一组示例同时满足两点单个示例和用户查询语义高度相关选中的示例彼此差异大、无冗余兼顾多样性。2. MMR 与普通语义相似度的通俗对比纯语义相似度只单独打分只看单个示例和用户输入匹配度。如同面试官单独评估每位求职者只看个人匹配分数容易选出一堆技能完全一样的候选人。MMR 最大边际相关性兼顾匹配度 样本多样性类似组建团队。第一轮先选和输入最匹配的示例后续每一轮挑选时会惩罚和已选中示例高度雷同的候选最终选出 k 个相关但覆盖不同维度、信息不重复的示例。3. 适用场景语义相似度选择器适用场景基础搜索、单一精准匹配、只追求最高相关、不在乎示例重复。MMR 专属适用场景推荐系统避免信息茧房推荐同类但不同维度内容文本摘要挑选多维度关键句子摘要不重复RAG 检索增强生成检索后去重多维度素材减少模型幻觉少样本提示工程示例库大量同类样例需要多样参考案例。4. 底层算法逻辑全部示例通过 Embedding 转为向量计算与用户输入的余弦相似度贪心迭代选取首次选取相似度最高的示例加入结果集后续对每个候选计算综合得分 相关性 − 与已选样本最大相似度雷同样本扣分循环选出 k 个示例保证整体相关且多元可调参数lambda_mult平衡相关性和多样性越接近 1 越看重相似度越接近 0 越看重多样性。3.4.4.2 类与内置核心方法类完整路径langchain_core.example_selectors.MaxMarginalRelevanceExampleSelector1. 静态构造方法 from_examples ()实例化选择器入参examples示例字典列表embeddings嵌入模型实例OpenAIEmbeddings/BGE 本地向量vectorstore_cls向量数据库类Chroma/FAISSk最终需要选出的示例数量默认 4fetch_k先检索多少条候选再做 MMR 重排必须大于 klambda_mult相关性与多样性平衡系数0~1 之间。 返回MMR 示例选择器实例。2. add_example(example: dict[str, str])运行时动态新增单条示例自动向量化存入向量库。3. select_examples(input_variables: dict[str, str]) → list[dict]接收用户输入变量执行 MMR 检索重排返回筛选完毕、多样不重复的示例子集。3.4.4.3 完整标准代码OpenAI 向量前置安装pip install -U langchain-chroma chromadb langchain-openaifrom langchain_chroma import Chroma from langchain_core.example_selectors import MaxMarginalRelevanceExampleSelector from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate from langchain_openai import OpenAIEmbeddings # 反义词示例集合 examples [ {input: happy, output: sad}, {input: tall, output: short}, {input: energetic, output: lethargic}, {input: sunny, output: gloomy}, {input: windy, output: calm}, ] # 单条示例格式化模板 example_prompt PromptTemplate( input_variables[input, output], templateInput: {input}\nOutput: {output}, ) # MMR语义选择器k2选出2条相关且多样示例 example_selector MaxMarginalRelevanceExampleSelector.from_examples( examples, OpenAIEmbeddings(), Chroma, k2, ) # 组装完整少样本文本模板 similar_prompt FewShotPromptTemplate( example_selectorexample_selector, example_promptexample_prompt, prefix给出每个输入的反义词, suffixInput: {adjective}\nOutput:, input_variables[adjective], ) # 打印完整提示词文本 res similar_prompt.invoke({adjective: worried}).to_messages()[0].content print(res)运行输出plaintext给出每个输入的反义词 Input: happy Output: sad Input: windy Output: calm Input: worried Output:结果说明输入worried焦虑属于情绪类词汇第一条匹配最高相关示例happy-sad情绪维度MMR 会规避第二个情绪类示例energetic-lethargic转而挑选天气维度不重复的windy-calm最终两条示例覆盖不同语义维度避免全部是情绪类冗余案例。基于 N-Gram 重叠选择示例NGramOverlapExampleSelector知识点整理3.4.5.1 核心概念1. N-Gram 定义N-Gram 指一段文本里连续 n 个单词 / 字符组成的片段用于衡量文本字面重合度。2. 传统 N-Gram 重叠字面匹配通过统计两段文本完全相同的连续字词片段数量计算相似度仅比对文字本身无法识别同义词、近义词。示例 1重叠度高text1 苹果手机很好用 text2 这款手机很好用 分词后共享连续片段「手机、很好用」N-Gram 重叠分数高。示例 2语义相近、重叠度 0text1 苹果手机很好用 text2 iPhone 非常不错 文字无任何相同片段传统 N-Gram 重叠为 0但实际表达同一含义。3. 语义 N-Gram 重叠拓展概念不再比对原始文字而是将单词转为 Embedding 向量通过向量相似度判断片段是否 “语义重叠”可以识别同义词改写文本多用于查重、抄袭检测。4. 传统 N-Gram 选择器优缺点✅ 优势无需 Embedding、无需向量数据库、依赖轻量、计算速度快只需要 nltk 分词库 ❌ 劣势仅字面匹配不能理解深层语义同义词、同义句无法匹配。5. 适用场景短关键词、指令、固定句式匹配低成本轻量检索不想部署向量模型 / 向量库过滤完全无相同字词、字面完全无关的示例简单文本查重、固定模板匹配。3.4.5.2 类、参数与内置方法类路径langchain_community.example_selectors.ngram_overlap.NGramOverlapExampleSelector构造入参说明examples示例字典列表{input:文本,output:结果}格式example_prompt格式化单条示例的 PromptTemplatethreshold重叠分数字段过滤阈值分数区间 0~1默认-1.0threshold 0不剔除任何示例仅按重叠分数降序排序threshold 0.0排序后剔除无任何字面重叠的示例threshold ≥ 1.0所有示例分数≤1直接全部剔除返回空列表。内置核心方法add_example(example: dict[str, str])动态新增单条示例自动参与后续 N-Gram 分数计算。select_examples(input_variables: dict[str, str]) - list[dict]接收用户输入计算全部示例 N-Gram 重叠分数按规则过滤、降序排序返回筛选后的示例列表。运行前置依赖# 分词依赖 pip install nltk # 社区组件依赖 pip install langchain-community3.4.5.3 完整标准可运行代码from langchain_community.example_selectors import NGramOverlapExampleSelector from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate # 翻译任务示例集 examples [ {input: See Spot run., output: 看见Spot跑。}, {input: My dog barks., output: 我的狗叫。}, {input: Spot can run., output: Spot可以跑。}, ] # 单条示例格式化模板 example_prompt PromptTemplate( input_variables[input, output], templateInput: {input}\nOutput: {output}, ) # 1. threshold-1.0全部保留仅按重叠分数排序 example_selector NGramOverlapExampleSelector( examplesexamples, example_promptexample_prompt, threshold-1.0, ) # 组装完整少样本文本模板 dynamic_prompt FewShotPromptTemplate( example_selectorexample_selector, example_promptexample_prompt, prefix给出每个输入的中文翻译, suffixInput: {sentence}\nOutput:, input_variables[sentence], ) # 用户输入 res dynamic_prompt.invoke({sentence: Spot can run fast.}).to_messages()[0].content print(res)输出结果threshold-1.0plaintext给出每个输入的中文翻译 Input: Spot can run. Output: Spot可以跑。 Input: See Spot run. Output: 看见Spot跑。 Input: My dog barks. Output: 我的狗叫。 Input: Spot can run fast. Output:排序逻辑Spot can run.字面重叠最多排第一See Spot run.次之完全无关的My dog barks.排在最后。不同 threshold 效果对比threshold0.0剔除无任何相同字词的My dog barks.仅保留前两条重叠示例给出每个输入的中文翻译 Input: Spot can run. Output: Spot可以跑。 Input: See Spot run. Output: 看见Spot跑。 Input: Spot can run fast. Output:threshold1.0所有示例分数小于 1全部过滤无参考示例给出每个输入的中文翻译 Input: Spot can run fast. Output:3.4.6 四种示例选择器完整对比总结选择器核心匹配逻辑依赖组件优势短板适用场景LengthBasedExampleSelector文本总长度截断无额外依赖零开销、轻量不看语义、易保留无关示例示例语义统一仅控制提示词长度SemanticSimilarityExampleSelector向量余弦相似度Embedding 向量库理解深层语义匹配同义句需要向量模型、数据库开销大需要精准语义匹配、多语义示例库MaxMarginalRelevanceExampleSelector(MMR)相似度 样本多样性Embedding 向量库匹配相关且示例不重复计算开销最高RAG 检索、多维度参考、避免信息冗余NGramOverlapExampleSelector字面 N-Gram 片段重叠nltk 分词库无需向量、速度极快仅匹配字面不识别同义词短指令、关键词、固定句式轻量匹配四类选择器对话能力总区分SemanticSimilarity / MMR完整支持对话特性自动拆分 human/ai仅提取用户提问做向量检索匹配同类用户问题贴合问答逻辑。LengthBased / NGramOverlap仅语法兼容不支持对话专属特性Length全部对话文本拼接统计长度无角色区分、无语义匹配NGram全部对话文本拼接计算字面重叠无角色区分 二者都只是单纯对完整对话字符串做处理完全无视一问一答的对话结构。