【LangChain】P13 LangChain 提示词模板深度解析(四):MessagePlaceholder 与少量样本示例详解
在实际应用中,我们经常会遇到这样的场景:提示词模板中的消息类型和数量不确定,或者需要在运行时动态插入一系列历史对话。MessagePlaceholder 就是为解决这类问题而设计的,它可以在提示词模板的特定位置插入消息列表。解决了动态消息插入的问题系列让少量样本学习变得简单实现了智能示例选择,优化性能和效果掌握这些工具,可以帮助我们构建更加智能、高效的大语言模型应用。在实际项目中,建议根据具体场景
目录

接续我们 LangChain 系列博文内容,本节博文将继续围绕提示词模板的深度使用展开。本博文将深入探讨 MessagePlaceholder 和少量样本示例(Few-Shot Learning)的使用方法。
MessagePlaceholder:动态消息占位符
什么是 MessagePlaceholder?
在实际应用中,我们经常会遇到这样的场景:提示词模板中的消息类型和数量不确定,或者需要在运行时动态插入一系列历史对话。MessagePlaceholder 就是为解决这类问题而设计的,它可以在提示词模板的特定位置插入消息列表。
基础用法
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts.chat import MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage
# 创建包含 MessagePlaceholder 的提示模板
chat_prompt_template = ChatPromptTemplate.from_messages([
("system", "你是一个AI助手,你的名字叫{name}"),
MessagesPlaceholder(variable_name="msgs")
])
# 调用时传入消息列表
prompt_value = chat_prompt_template.invoke(input={
"name": "小智",
"msgs": [
HumanMessage(content="我的问题是1+2*3=?"),
AIMessage(content="1+2*3=7")
]
})
对话历史管理场景
MessagePlaceholder 在处理多轮对话时特别有用:
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "you are a helpful assistant"),
MessagesPlaceholder(variable_name="history"),
("human", "{question}")
])
# 传入对话历史
prompt_value = prompt.invoke(input={
"history": [
("human", "what is 5+2?"),
("ai", "5 + 2 is 7")
],
"question": "我刚才问的问题是什么?"
})
这种方式让我们能够轻松管理对话上下文,无需手动拼接消息。
少量样本示例:提升模型表现的关键技术
为什么需要 Few-Shot Learning?
少量样本示例(Few-Shot)是一种简单但强大的技术,通过在提示词中提供少量示例,可以显著提升大模型的性能和输出质量。
相比于零样本(Zero-Shot),Few-Shot 能够:
- 明确输出格式: 让模型理解期望的输出结构
- 统一风格: 确保输出符合特定的语言风格
- 提高准确性: 通过示例引导模型更好地理解任务
在 LangChain 中,常用的三项相关 Few-Shot 方法,与 PromptTemplate 以及 ChatPromptTemplate 结合。本博文剩余内容,将围绕这三种方法展开,提供完整示例与解析。
- FewShotPromptTemplate
- FewShotChatMessagePromptTemplate
- Example Selector(示例选择器)
FewShotPromptTemplate:基础文本场景
FewShotPromptTemplate 适合处理基础的文本生成任务,需要与 PromptTemplate 配合使用。
完整示例
import os
import dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
# 环境配置
dotenv.load_dotenv()
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")
os.environ["OPENAI_BASE_URL"] = os.getenv("OPENAI_BASE_URL")
chat_model = ChatOpenAI(model="deepseek-chat")
# 1. 创建示例模板
example_prompt = PromptTemplate.from_template(
template="input:{input}\n output:{output}",
)
# 2. 提供示例数据
examples = [
{"input": "北京天气怎么样", "output": "北京市"},
{"input": "南京下雨吗", "output": "南京市"},
{"input": "武汉热吗", "output": "武汉市"}
]
# 3. 创建 FewShotPromptTemplate
few_shot_template = FewShotPromptTemplate(
example_prompt=example_prompt,
examples=examples,
suffix="input:{input}\n output:",
input_variables=["input"]
)
# 4. 使用模板
prompt = few_shot_template.invoke(input={"input": "天津会下雨吗"})
result = chat_model.invoke(prompt)
复杂示例:多变量场景
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
# 创建包含多个变量的提示模板
prompt_template = PromptTemplate.from_template(
template="你是一个数学专家,算式:{input} 值:{output} 使用:{description}",
)
examples = [
{"input": "2+2", "output": "4", "description": "加法运算"},
{"input": "5-2", "output": "3", "description": "减法运算"}
]
few_shot_prompt_template = FewShotPromptTemplate(
example_prompt=prompt_template,
examples=examples,
suffix="你是一个数学专家,算式:{input} 值:{output}",
input_variables=["input", "output"]
)
prompt = few_shot_prompt_template.invoke(
input={"input": "2*5", "output": "10"}
)
result = chat_model.invoke(prompt)
FewShotChatMessagePromptTemplate:对话场景优化
对于聊天对话场景,FewShotChatMessagePromptTemplate 是更好的选择,它专门针对聊天消息格式进行了优化。
完整示例
from langchain_core.prompts import (
ChatPromptTemplate,
FewShotChatMessagePromptTemplate
)
# 1. 创建对话格式的提示模板
prompt_template = ChatPromptTemplate.from_messages([
("human", "{input}是多少"),
("ai", "{output}")
])
# 2. 提供对话示例
examples = [
{"input": "2+2", "output": "4"},
{"input": "2*3", "output": "6"}
]
# 3. 创建 FewShotChatMessagePromptTemplate
few_shot_prompt_template = FewShotChatMessagePromptTemplate(
example_prompt=prompt_template,
examples=examples
)
# 4. 组合成完整的提示词
final_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个数学奇才"),
few_shot_prompt_template,
("human", "{input}")
])
prompt = final_prompt.invoke(input={"input": "2+4"})
result = chat_model.invoke(prompt)
如何选择?
FewShotPromptTemplate:用于简单的文本输入输出场景FewShotChatMessagePromptTemplate:用于需要保留对话结构的场景
Example Selectors:智能示例选择器
为什么需要示例选择器?
在前面的方法中,无论输入什么问题,都会包含全部示例。但在实际开发中,这可能导致:
- Token 消耗过大: 所有示例都传递给模型
- 相关性不足: 某些示例与当前问题无关
- 效果不佳: 无关示例可能干扰模型判断
Example Selectors 可以根据当前输入,从大量候选示例中智能选择最相关的子集。
三种选择策略
1. 语义相似选择(Semantic Similarity)
通过余弦相似度等方式,选择与输入语义最接近的 k 个示例。
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from langchain_core.example_selectors import SemanticSimilarityExampleSelector
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
# 准备示例数据
examples = [
{"input": "北京天气怎么样", "output": "北京市"},
{"input": "上海会下雨吗", "output": "上海市"},
{"input": "广州今天热吗", "output": "广州市"},
{"input": "深圳的温度是多少", "output": "深圳市"},
]
# 创建语义相似度选择器
example_selector = SemanticSimilarityExampleSelector.from_examples(
examples, # 候选示例列表
OpenAIEmbeddings(), # 用于生成向量的嵌入模型
Chroma, # 向量数据库类
k=2 # 选择最相似的2个示例
)
# 创建提示模板
example_prompt = PromptTemplate.from_template("input:{input}\n output:{output}")
# 组合成 FewShotPromptTemplate
few_shot_prompt = FewShotPromptTemplate(
example_selector=example_selector, # 使用选择器而非固定示例
example_prompt=example_prompt,
suffix="input:{input}\n output:",
input_variables=["input"]
)
# 使用时会自动选择最相关的示例
prompt = few_shot_prompt.invoke(input={"input": "杭州的气候如何"})
result = chat_model.invoke(prompt)
SemanticSimilarityExampleSelector 参数解析:
examples:候选示例列表,每个示例是一个字典embeddings:嵌入模型,用于将文本转换为向量(如 OpenAIEmbeddings 中应用 OpenAI Embedding 模型:text-embedding-ada-002)vectorstore_cls:向量数据库类,如 Chroma、FAISSk:选择返回的示例数量input_keys:(可选)指定用于计算相似度的输入键
2. 长度选择(Length-Based Selection)
根据输入文本长度选择匹配的示例,适合对响应速度要求高的场景。
from langchain_core.example_selectors import LengthBasedExampleSelector
examples = [
{"input": "天气", "output": "短问题"},
{"input": "今天北京的天气怎么样啊", "output": "中等问题"},
{"input": "能否详细描述一下今天北京的天气情况,包括温度、湿度等", "output": "长问题"}
]
example_selector = LengthBasedExampleSelector(
examples=examples,
example_prompt=example_prompt,
max_length=50 # 根据长度限制选择示例
)
3. 最大边际相关选择(MMR)
在保证语义相似的同时,避免选择同质化内容,增加示例多样性。
from langchain_core.example_selectors import MaxMarginalRelevanceExampleSelector
example_selector = MaxMarginalRelevanceExampleSelector.from_examples(
examples,
OpenAIEmbeddings(),
Chroma,
k=2,
fetch_k=10 # 先获取10个候选,再通过MMR选择2个
)
使用 FAISS 的完整示例
FAISS 是 Facebook 开发的高效向量检索库,特别适合大规模示例场景。
# 安装依赖
# pip install faiss-cpu
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from langchain_core.example_selectors import SemanticSimilarityExampleSelector
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
# 准备示例
examples = [
{"question": "苹果是什么颜色", "answer": "红色或绿色"},
{"question": "天空是什么颜色", "answer": "蓝色"},
{"question": "草地是什么颜色", "answer": "绿色"},
{"question": "香蕉是什么颜色", "answer": "黄色"},
{"question": "橙子是什么颜色", "answer": "橙色"},
]
# 创建示例选择器(使用 FAISS)
example_selector = SemanticSimilarityExampleSelector.from_examples(
examples,
OpenAIEmbeddings(),
FAISS,
k=2
)
# 创建提示模板
example_prompt = PromptTemplate(
input_variables=["question", "answer"],
template="问题:{question}\n答案:{answer}"
)
# 组合成 FewShotPromptTemplate
few_shot_prompt = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=example_prompt,
prefix="请回答以下问题:",
suffix="问题:{input}\n答案:",
input_variables=["input"]
)
# 使用
prompt = few_shot_prompt.invoke(input={"input": "西红柿是什么颜色"})
# 系统会自动选择与"西红柿"最相关的示例(如苹果、橙子)
result = chat_model.invoke(prompt)
最佳实践建议
1. 选择合适的工具
- 简单任务: 直接使用
FewShotPromptTemplate - 对话应用: 使用
FewShotChatMessagePromptTemplate - 大量示例: 使用
Example Selectors动态选择 - 历史管理: 使用
MessagePlaceholder
2. 优化示例质量
- 示例要具有代表性和多样性
- 避免示例之间过于相似
- 确保示例格式一致
- 定期更新和维护示例库
3. 控制 Token 消耗
- 使用
Example Selectors减少无关示例 - 根据任务复杂度调整 k 值
- 考虑使用长度选择器控制总长度
4. 性能与效果平衡
- 语义相似度选择最准确但计算开销大
- 长度选择速度快但可能不够精确
- MMR 在准确性和多样性间取得平衡
总结
LangChain 的提示词工程工具为我们提供了强大而灵活的能力:
- MessagePlaceholder 解决了动态消息插入的问题
- FewShotPromptTemplate 系列让少量样本学习变得简单
- Example Selectors 实现了智能示例选择,优化性能和效果
掌握这些工具,可以帮助我们构建更加智能、高效的大语言模型应用。在实际项目中,建议根据具体场景选择合适的方法,并通过实验不断优化提示词策略。
2025.10.05 G930 北京朝阳
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)