【LangChain】P13 LangChain 提示词模板深度解析(四):MessagePlaceholder 与少量样本示例详解
目录
- MessagePlaceholder:动态消息占位符
- 什么是 MessagePlaceholder?
- 基础用法
- 对话历史管理场景
- 少量样本示例:提升模型表现的关键技术
- 为什么需要 Few-Shot Learning?
- FewShotPromptTemplate:基础文本场景
- 完整示例
- 复杂示例:多变量场景
- FewShotChatMessagePromptTemplate:对话场景优化
- 完整示例
- 如何选择?
- Example Selectors:智能示例选择器
- 为什么需要示例选择器?
- 三种选择策略
- 1. 语义相似选择(Semantic Similarity)
- 2. 长度选择(Length-Based Selection)
- 3. 最大边际相关选择(MMR)
- 使用 FAISS 的完整示例
- 最佳实践建议
- 1. 选择合适的工具
- 2. 优化示例质量
- 3. 控制 Token 消耗
- 4. 性能与效果平衡
- 总结
接续我们 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, MessagesPlaceholderprompt = 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 LengthBasedExampleSelectorexamples = [{"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 MaxMarginalRelevanceExampleSelectorexample_selector = MaxMarginalRelevanceExampleSelector.from_examples(examples,OpenAIEmbeddings(),Chroma,k=2,fetch_k=10 # 先获取10个候选,再通过MMR选择2个
)
使用 FAISS 的完整示例
FAISS 是 Facebook 开发的高效向量检索库,特别适合大规模示例场景。
# 安装依赖
# pip install faiss-cpufrom 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 北京朝阳