内容纲要
- 核心概念
Zero Shot:零样本推理,不给示例直接提问Few Shot:少样本推理,通过少量示例引导模型输出FewShotChatMessagePromptTemplate:LangChain 中实现 Few Shot 的专用模板
- 关键流程:准备示例 → 定义示例模板 → 组合最终提示词 → 提交给 LLM
- 涉及组件:
langchain_core.prompts、langchain_core.messages,示例使用ChatPromptTemplate - 代码演示:完整可运行的 Python 脚本,包含构建示例、组合模板、调用模型(使用模拟模型)全过程
引言
在提示词工程中,如果直接让大模型完成一个从未见过的任务,往往会出现答非所问或质量低下的情况。Few Shot(少样本)提示就是通过提供少量"输入-输出"示例,让模型快速理解任务模式,从而在新问题上给出更符合预期的答案。本文将介绍 Few Shot 的核心思想,并结合 LangChain 展示如何用 FewShotChatMessagePromptTemplate 高效地构建示例驱动的提示。
Zero Shot 与 Few Shot 对比
- Zero Shot:不提供任何示例,直接提问。对于推理能力较强的模型(如具备思维链的模型),也能获得不错的效果;但对于常规对话模型,直接回答生僻或自定义的任务往往表现不佳。
- Few Shot:提供若干精心设计的示例,让模型模仿示例格式和逻辑进行回答。示例的质量和与任务的相关性远比数量更重要。
例如,直接问模型 "what is 2 小鸟 9?",Zero Shot 方式可能得到不知所云的回复;而如果先给出两个示例 "2 小鸟 2 = 4"、"2 小鸟 3 = 5",模型便能推断出"小鸟"代表加法,并正确回答 "2 小鸟 9 = 11"。
下表对比了两种方式的特点:
| 方式 | 示例数量 | 适用场景 | 对模型推理要求 |
|---|---|---|---|
| Zero Shot | 0 | 常识问答、简单任务 | 高 |
| Few Shot | ≥1 | 自定义规则、格式转换、新任务 | 较低 |
LangChain 中的 Few Shot 实现
LangChain 提供了 FewShotChatMessagePromptTemplate,它可以轻松地将一组示例和基础提示词组合成最终的消息列表。整个流程如下:
#mermaid-svg-yg2tbjEeKNW6PnVl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yg2tbjEeKNW6PnVl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yg2tbjEeKNW6PnVl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yg2tbjEeKNW6PnVl .error-icon{fill:#552222;}#mermaid-svg-yg2tbjEeKNW6PnVl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yg2tbjEeKNW6PnVl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yg2tbjEeKNW6PnVl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yg2tbjEeKNW6PnVl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yg2tbjEeKNW6PnVl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yg2tbjEeKNW6PnVl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yg2tbjEeKNW6PnVl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yg2tbjEeKNW6PnVl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yg2tbjEeKNW6PnVl .marker.cross{stroke:#333333;}#mermaid-svg-yg2tbjEeKNW6PnVl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yg2tbjEeKNW6PnVl p{margin:0;}#mermaid-svg-yg2tbjEeKNW6PnVl .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yg2tbjEeKNW6PnVl .cluster-label text{fill:#333;}#mermaid-svg-yg2tbjEeKNW6PnVl .cluster-label span{color:#333;}#mermaid-svg-yg2tbjEeKNW6PnVl .cluster-label span p{background-color:transparent;}#mermaid-svg-yg2tbjEeKNW6PnVl .label text,#mermaid-svg-yg2tbjEeKNW6PnVl span{fill:#333;color:#333;}#mermaid-svg-yg2tbjEeKNW6PnVl .node rect,#mermaid-svg-yg2tbjEeKNW6PnVl .node circle,#mermaid-svg-yg2tbjEeKNW6PnVl .node ellipse,#mermaid-svg-yg2tbjEeKNW6PnVl .node polygon,#mermaid-svg-yg2tbjEeKNW6PnVl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yg2tbjEeKNW6PnVl .rough-node .label text,#mermaid-svg-yg2tbjEeKNW6PnVl .node .label text,#mermaid-svg-yg2tbjEeKNW6PnVl .image-shape .label,#mermaid-svg-yg2tbjEeKNW6PnVl .icon-shape .label{text-anchor:middle;}#mermaid-svg-yg2tbjEeKNW6PnVl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yg2tbjEeKNW6PnVl .rough-node .label,#mermaid-svg-yg2tbjEeKNW6PnVl .node .label,#mermaid-svg-yg2tbjEeKNW6PnVl .image-shape .label,#mermaid-svg-yg2tbjEeKNW6PnVl .icon-shape .label{text-align:center;}#mermaid-svg-yg2tbjEeKNW6PnVl .node.clickable{cursor:pointer;}#mermaid-svg-yg2tbjEeKNW6PnVl .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yg2tbjEeKNW6PnVl .arrowheadPath{fill:#333333;}#mermaid-svg-yg2tbjEeKNW6PnVl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yg2tbjEeKNW6PnVl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yg2tbjEeKNW6PnVl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yg2tbjEeKNW6PnVl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yg2tbjEeKNW6PnVl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yg2tbjEeKNW6PnVl .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yg2tbjEeKNW6PnVl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yg2tbjEeKNW6PnVl .cluster text{fill:#333;}#mermaid-svg-yg2tbjEeKNW6PnVl .cluster span{color:#333;}#mermaid-svg-yg2tbjEeKNW6PnVl div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yg2tbjEeKNW6PnVl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yg2tbjEeKNW6PnVl rect.text{fill:none;stroke-width:0;}#mermaid-svg-yg2tbjEeKNW6PnVl .icon-shape,#mermaid-svg-yg2tbjEeKNW6PnVl .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yg2tbjEeKNW6PnVl .icon-shape p,#mermaid-svg-yg2tbjEeKNW6PnVl .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yg2tbjEeKNW6PnVl .icon-shape .label rect,#mermaid-svg-yg2tbjEeKNW6PnVl .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yg2tbjEeKNW6PnVl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yg2tbjEeKNW6PnVl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yg2tbjEeKNW6PnVl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 准备示例列表
创建示例模板
用FewShotChatMessagePromptTemplate组合示例与基础提示
追加最终用户问题
提交给大模型
构建示例
示例通常是一个字典列表,每个字典包含 input 和 output 字段,分别代表人类问题和期望的 AI 回答。
创建示例模板
使用 ChatPromptTemplate 定义如何将示例格式化为消息:一般将 input 放入 HumanMessage,output 放入 AIMessage。
组合最终提示
将示例模板与包含系统消息和最终人类问题的完整提示词模板进行组合,由 FewShotChatMessagePromptTemplate 统一编排。
完整可运行代码
以下代码演示了用 Few Shot 让模型理解自定义运算符"小鸟"为加法的过程。为便于运行,使用 FakeListChatModel 模拟大模型响应,无需 API Key。
安装依赖:
bash
pip install langchain langchain-core langchain-community
核心代码:
python
from langchain_core.prompts import (
ChatPromptTemplate,
FewShotChatMessagePromptTemplate,
)
from langchain_community.chat_models.fake import FakeListChatModel
# 1. 定义示例列表
examples = [
{"input": "2 小鸟 2", "output": "4"},
{"input": "2 小鸟 3", "output": "5"},
]
# 2. 构建示例模板:将每个示例格式化为 HumanMessage 和 AIMessage
example_prompt = ChatPromptTemplate.from_messages([
("human", "{input}"),
("ai", "{output}"),
])
# 3. 用 FewShotChatMessagePromptTemplate 组合示例和模板
few_shot_prompt = FewShotChatMessagePromptTemplate(
example_prompt=example_prompt,
examples=examples,
)
# 4. 构建最终提示词模板(系统消息 + few shot 示例 + 最终人类问题)
final_prompt = ChatPromptTemplate.from_messages([
("system", "你是一位神奇的数学奇才。"),
few_shot_prompt,
("human", "{input}"),
])
# 5. 格式化并查看组合后的消息
formatted_messages = final_prompt.format_messages(input="2 小鸟 9")
print("组合后的消息列表:")
for msg in formatted_messages:
print(f" {msg.type}: {msg.content}")
# 6. 使用模拟模型进行回答(预设输出为 "11")
model = FakeListChatModel(responses=["11"])
chain = final_prompt | model
response = chain.invoke({"input": "2 小鸟 9"})
print(f"\n模型回答:{response.content}")
运行上述代码,可以看到消息列表中包含了示例的 Human 和 AI 消息,以及最后的用户问题 "2 小鸟 9"。模拟模型返回 "11",证明 Few Shot 成功让模型掌握了"小鸟"的含义。
示例设计的注意事项
- 示例与任务高度相关:如果任务是写唐诗,示例应该是唐诗,而不是宋词或现代诗。
- 质量优于数量:一两个精准的示例往往比一堆模糊的示例更有效。
- 格式一致:保证示例的输入输出格式与最终期望的格式完全一致,让模型容易模仿。
总结
Few Shot 是提升大模型在特定任务上表现的重要技巧,LangChain 通过 FewShotChatMessagePromptTemplate 将其变成了一个可复用、可组合的组件。
无论是自定义符号运算、特定领域的文本生成还是格式转换,都可以通过提供少量示例,大幅提高模型的输出质量和稳定性。