公司动态
【LangChain】示例选择器(Example Selectors)实战指南
草莓熊Lotso个人主页❄️个人专栏:《C知识分享》 《Linux 入门到实践零基础也能懂》✨生活是默默的坚持毅力是永久的享受 博主简介文章目录前言一. 什么是示例选择器二. 四大核心示例选择器原理解析2.1 按长度选择LengthBasedExampleSelector2.2 按语义相似性选择SemanticSimilarityExampleSelector2.3 按最大边际相关性选择MaxMarginalRelevanceExampleSelector2.4 按 Ngram 重叠选择NGramOverlapExampleSelector三. 实战落地从零实现四大示例选择器3.1 环境准备3.2 按长度选择示例实战3.3 按语义相似性选择示例实战3.4 按最大边际相关性选择示例实战3.5 按 Ngram 重叠选择示例实战四. 核心考点与选型指南4.1 四大选择器对比表4.2 选型建议前言少样本提示Few-shot Prompting是提升大语言模型性能最有效的手段之一。通过给模型提供几个 “输入 - 输出” 示例我们可以清晰地告诉模型应该做什么、怎么做、以什么格式输出从而大幅减少模型 “胡说八道” 的概率获得更稳定、更符合预期的结果。然而当我们的示例库越来越大时一个棘手的问题出现了如果把所有示例都塞进提示词会迅速耗尽模型的上下文窗口导致 API 调用失败过多的冗余示例会增加 token 成本还可能混淆模型反而降低输出质量不同的查询需要不同的示例一刀切的示例选择方式效率极低。这正是示例选择器Example Selectors要解决的问题。它能根据给定的输入从大量示例集中动态、智能地选择最相关的示例子集在保证提示效果的同时严格控制上下文长度和调用成本。本文将系统讲解 LangChain 中四大核心示例选择器的原理、适用场景并提供完整的实战代码和源码解读。一. 什么是示例选择器示例选择器是 LangChain 中专门用于优化少样本提示的核心组件。它的工作流程非常清晰接收用户的查询输入根据预设的策略从预定义的示例集中筛选出最相关的 N 个示例将筛选后的示例格式化为模型可理解的消息格式与用户查询一起构建最终的提示词它为我们带来了四个核心价值控制上下文长度避免因示例过多导致的上下文窗口溢出提升提示质量只保留与查询最相关的示例减少冗余信息干扰降低 API 成本更少的 token 意味着更低的调用费用提高响应准确性精准的示例能更好地引导模型输出正确结果在这里插入图片描述二. 四大核心示例选择器原理解析LangChain 内置了四种常用的示例选择器分别适用于不同的业务场景。下面我们逐一拆解它们的核心原理和适用边界。2.1 按长度选择LengthBasedExampleSelector核心原理根据用户输入文本的长度动态调整示例数量。输入越短选择的示例越多输入越长选择的示例越少。设计逻辑当用户输入本身已经很长时留给示例的 token 空间就很小了此时应该减少示例数量以避免上下文溢出反之短输入可以搭配更多示例来提升效果。适用场景对上下文长度有严格限制、token 成本敏感的简单任务。核心参数max_length提示词的最大长度默认按单词数统计get_text_length自定义文本长度计算函数2.2 按语义相似性选择SemanticSimilarityExampleSelector核心原理将所有示例和用户查询都通过嵌入模型转换为高维向量然后计算查询向量与所有示例向量之间的余弦相似度选择相似度最高的 k 个示例。关键依赖嵌入模型Embeddings将文本转换为语义向量向量数据库VectorStore高效存储和检索向量适用场景大多数少样本提示任务尤其是需要语义理解而非简单关键词匹配的场景。核心参数k最终返回的示例数量embeddings嵌入模型实例vectorstore_cls向量数据库类2.3 按最大边际相关性选择MaxMarginalRelevanceExampleSelector解决的问题纯语义相似性选择有一个致命缺陷 —— 返回的结果往往高度同质化信息冗余严重。例如查询 “苹果的价格” 时可能返回的都是关于红富士苹果价格的示例而缺少其他品种的信息。核心原理MMRMaximum Marginal Relevance算法是一种重新排序技术它在选择示例时同时兼顾相关性和多样性首先从向量库中获取fetch_k个最相似的示例广撒网然后从这fetch_k个示例中迭代选出既与查询相关、又与已选示例差异最大的k个示例适用场景RAG检索增强生成、推荐系统、文档摘要等需要结果多样性的场景。核心参数k最终返回的示例数量fetch_k初步筛选的候选示例数量通常fetch_k klambda_mult控制相关性和多样性的权重0~1默认 0.5值越大越偏向相关性2.4 按 Ngram 重叠选择NGramOverlapExampleSelector核心原理计算用户查询和每个示例之间的ngram 重叠度连续 n 个词的匹配数量然后按重叠度从高到低排序示例。特点基于表面形式匹配不理解语义速度极快无需嵌入模型和向量数据库对同义词、一词多义等情况处理能力差适用场景关键词匹配、代码搜索、精确查询等不需要深度语义理解的场景。核心参数threshold重叠度阈值控制是否排除示例-1.0按重叠度排序不排除任何示例0.0排除与查询没有任何 ngram 重叠的示例1.0排除所有示例nngram 的长度默认 2三. 实战落地从零实现四大示例选择器3.1 环境准备首先安装所需的依赖包pipinstalllangchain langchain-openai langchain-chroma nltk langchain-community python-dotenv然后配置 OpenAI API Key推荐使用.env文件管理fromdotenvimportload_dotenv load_dotenv()# 加载.env文件中的环境变量3.2 按长度选择示例实战我们以 “反义词生成” 任务为例演示 LengthBasedExampleSelector 的使用fromlangchain_core.example_selectorsimportLengthBasedExampleSelectorfromlangchain_core.promptsimportFewShotPromptTemplate,PromptTemplate# 1. 定义反义词示例集examples[{input:happy,output:sad},{input:tall,output:short},{input:energetic,output:lethargic},{input:sunny,output:gloomy},{input:windy,output:calm},]# 2. 定义单个示例的格式化模板example_promptPromptTemplate(input_variables[input,output],templateInput: {input}\nOutput: {output},)# 3. 初始化长度示例选择器example_selectorLengthBasedExampleSelector(examplesexamples,example_promptexample_prompt,max_length25,# 提示词的最大长度单词数)# 4. 构建动态少样本提示模板dynamic_promptFewShotPromptTemplate(example_selectorexample_selector,# 使用选择器而非固定examplesexample_promptexample_prompt,prefix给出每个输入的反义词,suffixInput: {adjective}\nOutput:,input_variables[adjective],)# 测试1短输入print( 短输入测试 )print(dynamic_prompt.invoke({adjective:big}).to_string())# 测试2长输入print(\n 长输入测试 )long_input非常 非常 非常 非常 非常 非常 非常 非常 非常 非常 非常 非常 非常 非常 非常 非常大print(dynamic_prompt.invoke({adjective:long_input}).to_string())源码解读max_length25表示整个提示词前缀 所有示例 后缀的单词数不能超过 25默认的长度计算函数是按空格和换行符分割文本统计单词数量当输入过长时选择器会自动从后往前截断示例直到满足长度限制3.3 按语义相似性选择示例实战fromlangchain_chromaimportChromafromlangchain_core.example_selectorsimportSemanticSimilarityExampleSelectorfromlangchain_core.promptsimportFewShotPromptTemplate,PromptTemplatefromlangchain_openaiimportOpenAIEmbeddings# 1. 复用之前的反义词示例集examples[{input:happy,output:sad},{input:tall,output:short},{input:energetic,output:lethargic},{input:sunny,output:gloomy},{input:windy,output:calm},]example_promptPromptTemplate(input_variables[input,output],templateInput: {input}\nOutput: {output},)# 2. 初始化语义相似示例选择器example_selectorSemanticSimilarityExampleSelector.from_examples(examplesexamples,embeddingsOpenAIEmbeddings(modeltext-embedding-3-small),# 嵌入模型vectorstore_clsChroma,# 使用Chroma内存向量数据库k1,# 只返回最相似的1个示例)# 3. 构建少样本提示模板similar_promptFewShotPromptTemplate(example_selectorexample_selector,example_promptexample_prompt,prefix给出每个输入的反义词,suffixInput: {adjective}\nOutput:,input_variables[adjective],)# 测试查询worried担心的print( 语义相似性测试 )print(similar_prompt.invoke({adjective:worried}).to_string())源码解读from_examples方法会自动将所有示例转换为向量并存储在 Chroma 向量数据库中当调用invoke时选择器会先将查询转换为向量然后在向量库中搜索最相似的 k 个示例输出结果会显示最相似的示例是 “happy → sad”因为它们都表示情绪状态语义最接近3.4 按最大边际相关性选择示例实战fromlangchain_chromaimportChromafromlangchain_core.example_selectorsimportMaxMarginalRelevanceExampleSelectorfromlangchain_core.promptsimportFewShotPromptTemplate,PromptTemplatefromlangchain_openaiimportOpenAIEmbeddings examples[{input:happy,output:sad},{input:joyful,output:miserable},{input:tall,output:short},{input:energetic,output:lethargic},{input:sunny,output:gloomy},]example_promptPromptTemplate(input_variables[input,output],templateInput: {input}\nOutput: {output},)# 初始化MMR示例选择器example_selectorMaxMarginalRelevanceExampleSelector.from_examples(examplesexamples,embeddingsOpenAIEmbeddings(modeltext-embedding-3-small),vectorstore_clsChroma,k2,# 最终返回2个示例fetch_k4,# 先获取4个最相似的候选)mmr_promptFewShotPromptTemplate(example_selectorexample_selector,example_promptexample_prompt,prefix给出每个输入的反义词,suffixInput: {adjective}\nOutput:,input_variables[adjective],)# 测试查询cheerful快乐的print( MMR测试 )print(mmr_prompt.invoke({adjective:cheerful}).to_string())源码解读fetch_k4表示先从向量库中获取 4 个最相似的示例然后 MMR 算法会从这 4 个示例中选出 2 个既相关又多样的示例输出结果会包含 “happy → sad” 和 “joyful → miserable” 吗不MMR 会避免选择过于相似的示例可能会返回 “happy → sad” 和 “energetic → lethargic”这样既相关又有多样性3.5 按 Ngram 重叠选择示例实战fromlangchain_community.example_selectorsimportNGramOverlapExampleSelectorfromlangchain_core.promptsimportFewShotPromptTemplate,PromptTemplate# 1. 定义翻译示例集examples[{input:See Spot run.,output:看见Spot跑。},{input:My dog barks.,output:我的狗叫。},{input:Spot can run.,output:Spot可以跑。},]example_promptPromptTemplate(input_variables[input,output],templateInput: {input}\nOutput: {output},)# 2. 初始化NGram示例选择器threshold-1不排除任何示例example_selectorNGramOverlapExampleSelector(examplesexamples,example_promptexample_prompt,threshold-1.0,)# 3. 构建少样本提示模板dynamic_promptFewShotPromptTemplate(example_selectorexample_selector,example_promptexample_prompt,prefix给出每个输入的中文翻译,suffixInput: {sentence}\nOutput:,input_variables[sentence],)# 测试查询Spot can run fast.print( NGram重叠测试threshold-1 )print(dynamic_prompt.invoke({sentence:Spot can run fast.}).to_string())# 测试threshold0.0排除无重叠的示例example_selector.threshold0.0print(\n NGram重叠测试threshold0 )print(dynamic_prompt.invoke({sentence:Spot can run fast.}).to_string())源码解读对于查询 “Spot can run fast.”与示例 “Spot can run.” 的 2gram 重叠度最高“Spot can” 和 “can run”当threshold0.0时与查询没有任何 ngram 重叠的示例会被排除输出结果会按重叠度从高到低排序示例四. 核心考点与选型指南4.1 四大选择器对比表选择器类型核心原理依赖优点缺点适用场景Length输入文本长度无简单快速无额外成本不考虑语义效果一般严格控制 token简单任务Similarity余弦相似度嵌入模型 向量库语义匹配效果好结果同质化有嵌入成本大多数少样本任务MMR相关性 多样性嵌入模型 向量库兼顾相关和多样减少冗余计算稍复杂RAG、推荐系统、文档摘要NGram连续词重叠nltk速度极快无嵌入成本表面匹配不理解语义关键词匹配、代码搜索4.2 选型建议优先选择 SemanticSimilarity对于大多数需要语义理解的少样本任务它的效果最好需要多样性选 MMR在 RAG、推荐等场景中MMR 能有效避免结果同质化提升答案的全面性成本敏感选 Length/NGram如果对 token 成本和响应速度要求极高且任务不需要深度语义理解可以选择这两种精确匹配选 NGram对于代码搜索、关键词查询等场景NGram 的表面匹配效果反而更好 我是草莓熊 Lotso若这篇技术干货帮你打通了学习中的卡点 【关注】跟我一起深耕技术领域从基础到进阶见证每一次成长 ❤️ 【点赞】让优质内容被更多人看见让知识传递更有力量 ⭐ 【收藏】把核心知识点、实战技巧存好需要时直接查、随时用 【评论】分享你的经验或疑问比如曾踩过的技术坑一起交流避坑 ️ 【投票】用你的选择助力社区内容方向告诉大家哪个技术点最该重点拆解 技术之路难免有困惑但同行的人会让前进更有方向愿我们都能在自己专注的领域里一步步靠近心中的技术目标结语示例选择器是 LangChain 中优化少样本提示的关键组件它解决了 “示例太多上下文溢出、示例太少效果不好” 的核心矛盾。在实际开发中建议先从 SemanticSimilarity 开始尝试然后根据业务需求逐步优化。如果发现返回的示例过于同质化可以切换到 MMR如果对成本和速度有严格要求可以考虑 Length 或 NGram。未来随着大模型上下文窗口的不断扩大示例选择器的作用不会减弱反而会更加重要。它将在复杂 Agent、多轮对话、长上下文 RAG 等场景中发挥越来越关键的作用帮助我们构建更高效、更智能的 AI 应用。✨把这些内容吃透超牛的放松下吧✨ʕ˘ᴥ˘ʔづきらど