
个人主页 for_ever_love__ 欢迎各位大佬莅临其他栏目: 大模型开发从0到1 其他栏目: iOS项目总结大全 其他栏目: 我想学python了 其他栏目: iOS UI 文章目录LangChain Few-shot 实战不微调也能让输出稳定下来的技巧一、为什么例子比指令管用二、写法一FewShotPromptTemplate三、写法二FewShotChatMessagePromptTemplate推荐四、动态选示例ExampleSelector4.1 按语义相似度挑4.2 按长度挑长输入多给例子4.3 自定义选择器五、写例子的四条经验5.1 例子要覆盖边界情况5.2 例子的格式要和期望输出严格一致5.3 3~5 个够了5.4 顺序有影响六、什么时候不该用 Few-shot七、完整示例客服意图分类八、小结LangChain Few-shot 实战不微调也能让输出稳定下来的技巧模型听不懂你要什么格式时最有效的办法往往不是把指令写得更长而是给它几个例子。这篇讲 Few-shot 的三种写法、示例怎么动态挑选以及什么时候不该用 Few-shot。一、为什么例子比指令管用对比一下。指令式把用户输入的商品描述解析成 JSON包含 name、price、category 三个字段。模型可能输出{商品名:...,价格:...,分类:...}← 键名被翻译了加上两个例子把商品描述解析成 JSON。 示例1 输入苹果 iPhone 15售价 5999 元 输出{name: iPhone 15, price: 5999, category: 手机} 示例2 输入联想 ThinkPad X112999 元 输出{name: ThinkPad X1, price: 12999, category: 笔记本} 输入华为 Mate606999 元 输出模型几乎不会搞错键名了。例子比描述更具体、更没有歧义而且能顺便把边界情况数字不带单位、分类用什么词一起教会。二、写法一FewShotPromptTemplatefromlangchain_core.promptsimportFewShotPromptTemplate,PromptTemplate examples[{input:苹果 iPhone 15售价 5999 元,output:{name: iPhone 15, price: 5999, category: 手机}},{input:联想 ThinkPad X112999 元,output:{name: ThinkPad X1, price: 12999, category: 笔记本}},]example_templatePromptTemplate.from_template(输入{input}\n输出{output})promptFewShotPromptTemplate(examplesexamples,example_promptexample_template,prefix把商品描述解析成 JSON字段为 name / price / category。价格只填数字。,suffix输入{user_input}\n输出,input_variables[user_input],)print(prompt.format(user_input华为 Mate606999 元))生成的完整 prompt把商品描述解析成 JSON字段为 name / price / category。价格只填数字。 输入苹果 iPhone 15售价 5999 元 输出{name: iPhone 15, price: 5999, category: 手机} 输入联想 ThinkPad X112999 元 输出{name: ThinkPad X1, price: 12999, category: 笔记本} 输入华为 Mate606999 元 输出四个参数参数作用examples示例列表example_prompt单个示例怎么渲染prefix示例前面的说明suffix示例后面、放真实输入的地方三、写法二FewShotChatMessagePromptTemplate推荐对话模型用这个更自然——示例变成一轮轮对话而不是一大段文本fromlangchain_core.promptsimport(FewShotChatMessagePromptTemplate,ChatPromptTemplate,)examples[{input:这个bug怎么修,output:error},{input:帮我写个快排,output:code},{input:今天天气怎么样,output:chat},]example_promptChatPromptTemplate.from_messages([(human,{input}),(ai,{output}),])few_shotFewShotChatMessagePromptTemplate(example_promptexample_prompt,examplesexamples,)finalChatPromptTemplate.from_messages([(system,你是一个意图分类器只输出 error / code / chat 之一。),few_shot,(human,{input}),])print(final.format_messages(input我的程序崩溃了))渲染出来是一串消息[System] 你是一个意图分类器… [Human] 这个bug怎么修 [AI] error [Human] 帮我写个快排 [AI] code [Human] 今天天气怎么样 [AI] chat [Human] 我的程序崩溃了为什么这样更好因为模型在预训练时见过海量多轮对话这个格式它最熟悉理解和模仿得更好。四、动态选示例ExampleSelector示例不是越多越好——全塞进去会撑爆上下文。ExampleSelector帮你按相似度挑几个最相关的。4.1 按语义相似度挑pipinstallfaiss-cpu# 或 chromadbfromlangchain_core.example_selectorsimportSemanticSimilarityExampleSelectorfromlangchain_openaiimportOpenAIEmbeddingsfromlangchain_community.vectorstoresimportFAISS examples[{input:退款多久到账,output:退款审核通过后 3 个工作日内到账},{input:怎么改收货地址,output:在订单详情页点击「修改地址」},{input:发票怎么开,output:订单完成后在「我的-发票」申请},# ... 假设有 50 条]selectorSemanticSimilarityExampleSelector.from_examples(examples,OpenAIEmbeddings(),FAISS,k2,# 每次只挑 2 条最像的)selector.select_examples({input:钱什么时候退回来})# → 挑出「退款多久到账」那条50 条示例只送 2 条既省 token 又提高相关性。4.2 按长度挑长输入多给例子fromlangchain_core.example_selectorsimportLengthBasedExampleSelector selectorLengthBasedExampleSelector(examplesexamples,example_promptexample_prompt,max_length200,# 总长度上限)输入长的时候自动少放几个例子避免超上下文。4.3 自定义选择器fromlangchain_core.example_selectors.baseimportBaseExampleSelectorclassKeywordSelector(BaseExampleSelector):def__init__(self,examples):self.examplesexamplesdefadd_example(self,example):self.examples.append(example)defselect_examples(self,input_variables):qinput_variables[input]hits[eforeinself.examplesifany(kwinqforkwine.get(keywords,[]))]returnhits[:3]orself.examples[:1]比如按业务线挑示例物流类问题只给物流示例比纯语义更可控。五、写例子的四条经验5.1 例子要覆盖边界情况examples[{input:iPhone 15 5999元,output:{name:iPhone 15,price:5999,category:手机}},# 边界1没有价格的{input:二手 iPad,output:{name:iPad,price:null,category:平板}},# 边界2价格带单位的{input:MacBook 12999 元起,output:{name:MacBook,price:12999,category:笔记本}},# 边界3完全不是商品的{input:你好,output:{name:null,price:null,category:null}},]边界例子比正常例子更有价值。“没有价格时填 null” 这种规则写十条说明不如给一个例子。5.2 例子的格式要和期望输出严格一致# ❌ 示例里 price 写了 5999元模型就会跟着带单位{output:{name:iPhone 15,price:5999元,category:手机}}# ✅{output:{name:iPhone 15,price:5999,category:手机}}5.3 3~5 个够了超过 5 个例子边际收益急剧下降还浪费 token。先用 2 个效果不够再加到 4~5 个。5.4 顺序有影响模型对最后出现的例子更敏感近因效应。把最想让它模仿的那个放最后。六、什么时候不该用 Few-shot情况原因模型已经很懂这个任务白白浪费 token输出格式已经用with_structured_output保证了schema 比例子更可靠示例本身很难写且容易出错错例子比没例子更糟任务需要大量知识而非格式该用 RAG 而不是 Few-shot一句话Few-shot 解决的是格式和风格问题不是知识问题。模型不知道你们公司的退款政策给再多例子也没用——那得靠 RAG。七、完整示例客服意图分类fromlangchain_core.promptsimportFewShotChatMessagePromptTemplate,ChatPromptTemplatefromlangchain_core.example_selectorsimportSemanticSimilarityExampleSelectorfromlangchain_openaiimportChatOpenAI,OpenAIEmbeddingsfromlangchain_community.vectorstoresimportFAISSfromlangchain_core.output_parsersimportStrOutputParser examples[{input:我的快递到哪了,output:logistics},{input:我要退货,output:return},{input:发票怎么申请,output:invoice},{input:你们客服电话多少,output:contact},{input:这个商品还有货吗,output:stock},{input:密码忘了怎么办,output:account},]selectorSemanticSimilarityExampleSelector.from_examples(examples,OpenAIEmbeddings(),FAISS,k3,)few_shotFewShotChatMessagePromptTemplate(example_promptChatPromptTemplate.from_messages([(human,{input}),(ai,{output})]),examplesexamples,example_selectorselector,)promptChatPromptTemplate.from_messages([(system,你是客服意图分类器。只从 logistics/return/invoice/contact/stock/account 中输出一个词不要解释。),few_shot,(human,{input}),])chainprompt|ChatOpenAI(modelgpt-4o-mini,temperature0,max_tokens20)|StrOutputParser()print(chain.invoke({input:东西什么时候能送到}))注意最后加了max_tokens20——分类任务输出很短限制上限能防模型啰嗦也省成本。八、小结例子比指令更具体模型靠例子学格式、学边界、学风格两种写法FewShotPromptTemplate文本和FewShotChatMessagePromptTemplate对话推荐示例多了用ExampleSelector动态挑语义相似度最常用、按长度、自定义规则写例子的四条经验覆盖边界情况、格式严格一致、3~5 个就够、最想模仿的放最后Few-shot 解决格式问题不解决知识问题缺知识要用 RAG短输出任务记得设max_tokens省成本。下一篇讲输出失败怎么办——解析失败、JSON 截断的自动修复方案。