Appearance
提示词模板(Prompts)
LangChain V1.x
1、什么是提示词模板
在大模型应用开发中,我们通常需要根据不同的用户输入来构造不同的Prompt。如果每次都手动拼接字符串,不仅代码冗余,还容易出错。提示词模板(Prompt Template)的核心思想是将Prompt中的固定部分与可变部分分离,通过定义模板 + 传入变量的方式,动态生成最终的Prompt。
核心价值:
| 优势 | 说明 |
|---|---|
| 复用性 | 一次定义模板,多次使用不同参数 |
| 参数化 | 支持变量插值和动态内容生成 |
| 标准化 | 统一管理所有提示词,便于维护和版本控制 |
| 优化友好 | 独立的模板便于A/B测试和提示词工程 |
2、提示词模板类型概览
LangChain围绕不同的使用场景,提供了多种提示模板类型。在学习具体类型之前,先从全局视角了解它们的定位:

下面我们按照从简单到复杂的顺序,逐一讲解每种模板。
3、提示词模板工作原理
在深入各类模板之前,先理解它们的统一工作原理。所有提示词模板都遵循相同的处理流程:
变量值 → PromptTemplate → PromptValue → 聊天模型 / LLM工作流程:
- 输入:传入变量值(通常以字典形式,如
{"topic": "AI"};若变量已通过partial预先填充,可不传) - 格式化:模板将变量值插入到预定义的占位符位置
- 输出:生成
PromptValue对象(一种中间格式) - 调用:
PromptValue可以自动适配聊天模型(转为消息列表)或LLM(转为字符串)
这种统一的输入输出机制,使得所有模板都可以在LCEL链中无缝使用(LCEL将在后续课件中详细介绍)。
4、PromptTemplate
这是最基础的提示词模板类型,适用于简单的文本生成场景——即字符串提示模板。它接收一个包含占位符的字符串模板,通过传入变量值来生成最终的Prompt。
4.1 基本用法
python
from langchain_core.prompts import PromptTemplate
# 方式一:使用from_template
prompt = PromptTemplate.from_template(
"讲一个关于{topic}的{adjective}故事"
)
# 方式二:使用构造方法
prompt = PromptTemplate(
template="讲一个关于{topic}的{adjective}故事",
input_variables=["topic", "adjective"]
)
# 调用模板
formatted_prompt = prompt.invoke({"topic": "人工智能", "adjective": "有趣的"})
print(formatted_prompt) # 得到一个PromptValue对象
# 输出: text='讲一个关于人工智能的有趣的故事'4.2 部分变量
当模板中有些变量的值是固定的或可以提前确定时,可以使用 partial 机制预先填充部分变量,减少后续调用时需要传入的参数数量。
python
# 方式一:调用partial方法固定部分变量
prompt = PromptTemplate.from_template(
"讲一个关于{topic}的{adjective}故事"
)
fixed_prompt = prompt.partial(adjective="有趣的")
print(fixed_prompt.invoke({"topic": "编程"}))
# 输出: text='讲一个关于编程的有趣的故事'
# 方式二:创建时直接指定partial_variables
prompt = PromptTemplate(
template="请解释{concept},使用{style}风格",
input_variables=["concept"],
partial_variables={"style": "简单易懂"}
)
print(prompt.invoke({"concept": "递归"}))
# 输出: text='请解释递归,使用简单易懂风格'
# 再次 partial,覆盖 style
advanced = prompt.partial(style="学术严谨")
print(advanced.invoke({"concept": "递归"}))
# 输出: 用学术严谨解释递归如何选择?
- 优先用
partial():当"固定值"是在运行时才确定,或需要分阶段逐步补全时- 例:来自配置文件/环境变量/用户选择后再固定;或先固定
style,后续再固定adjective。 - 优点:更灵活,适合链式构建与复用同一个基础模板。
- 例:来自配置文件/环境变量/用户选择后再固定;或先固定
- 优先用
partial_variables:当"固定值"在定义模板时就确定,且希望模板对象一创建就自带默认常量时- 例:文档里明确规定"统一用简单易懂风格";团队约定的固定前缀/固定语气。
- 优点:模板更"自描述",一眼能看出哪些变量是固定的,适合沉淀为通用模板。
- 简单决策表
- 固定值 是否依赖运行时上下文:是 →
partial();否 →partial_variables - 是否需要 多次派生不同版本(同一模板固定不同值):是 →
partial()更方便 - 是否想把"默认值/常量"写死在模板定义处:是 →
partial_variables
- 固定值 是否依赖运行时上下文:是 →
5、ChatPromptTemplate
PromptTemplate 生成的是一个纯字符串Prompt,而在多轮对话场景中,大模型需要接收的是消息列表(包含角色信息的多条消息)。ChatPromptTemplate——即聊天提示模板——正是为此设计的,它可以构建包含 system、human、ai 等不同角色的消息序列。
5.1 基本用法
python
from langchain_core.prompts import ChatPromptTemplate
# 使用from_messages构造(推荐)
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个专业的{role}。"),
("human", "请回答关于{topic}的问题。"),
("ai", "好的,我会尽力回答。"),
("human", "{question}")
])
# 调用模板,生成消息列表
messages = chat_prompt.invoke({
"role": "Python编程助手",
"topic": "Python装饰器",
"question": "什么是装饰器?"
})
print(messages)其中,元组的第一个元素是角色标识,第二个元素是消息内容模板。LangChain支持的角色标识包括:
| 角色标识 | 对应消息类型 | 用途 |
|---|---|---|
"system" | SystemMessage | 设定AI的行为规范和角色 |
"human" | HumanMessage | 用户输入的消息 |
"ai" | AIMessage | AI的回复消息 |
5.2 使用Message对象
除了元组形式,也可以直接使用Message对象来构造模板。两种方式可以混合使用:
python
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
chat_prompt = ChatPromptTemplate.from_messages([
SystemMessage(content="你是一个有帮助的AI助手"), # 固定内容用Message对象
HumanMessage(content="你好!"), # 固定内容
AIMessage(content="你好!有什么可以帮助你的?"), # 固定内容
("human", "请介绍{topic}") # 含变量的用元组形式
])
messages = chat_prompt.invoke({"topic": "LangChain"})
print(messages)选择建议:如果消息内容是固定的(不包含变量),用Message对象更直观;如果内容包含需要填充的变量,用元组形式更简洁。
6、MessagesPlaceholder
在实际的对话应用中,我们往往需要将历史对话记录动态插入到Prompt中。MessagesPlaceholder 允许你在模板中预留一个"插槽",运行时将一个消息列表整体插入到该位置。
这在构建带记忆的对话系统时尤为常用。
MessagesPlaceholder---->BaseMessagePromptTemplate
PromptTemplate-----> StringPromptTemplate---->BasePromptTemplate
ChatPromptTemplate---->BaseChatPromptTemplate---->BasePromptTemplate
python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import AIMessage, HumanMessage
prompt = ChatPromptTemplate.from_messages([
("system", "你是AI助手"),
MessagesPlaceholder(variable_name="history"), # 对话历史插槽
("human", "{input}")
])
# 调用时传入历史消息列表
messages = prompt.invoke({
"history": [
HumanMessage(content="什么是Python?"),
AIMessage(content="Python是一种通用编程语言。"),
],
"input": "它有什么特点?"
})
print(messages)注意:history 变量在格式化的时候一定是一个列表类型
也可以使用更简洁的元组语法实现同样的效果:
python
# 等价写法,使用("placeholder", ...)语法
prompt = ChatPromptTemplate.from_messages([
("system", "你是AI助手"),
("placeholder", "{history}"), # 等同于MessagesPlaceholder
("human", "{input}")
])7、FewShotPromptTemplate
前面介绍的模板解决了"如何动态构建Prompt"的问题。但在实际应用中,我们经常需要通过提供示例来引导模型理解任务模式——这就是少样本提示模板。FewShotPromptTemplate 将示例数据和格式化模板组合在一起,自动生成包含示例的完整Prompt。
7.1 基本用法
python
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
# 第一步:准备示例数据
examples = [
{"input": "高兴", "output": "开心"},
{"input": "难过", "output": "悲伤"},
{"input": "生气", "output": "愤怒"}
]
# 第二步:定义单条示例的格式化模板
example_formatter = PromptTemplate(
template="输入: {input}\n输出: {output}",
input_variables=["input", "output"]
)
# 第三步:创建少样本提示模板
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_formatter,
prefix="以下是一些同义词转换的例子:", # 示例前的说明文字
suffix="\n输入: {input}\n输出:", # 示例后的实际问题
input_variables=["input"]
)
# 调用
print(few_shot_prompt.invoke({"input": "兴奋"}))生成的Prompt结构为:prefix + 示例1 + 示例2 + ... + suffix。
7.2 对接LLM
python
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
load_dotenv()
# 第一步:准备示例数据
examples = [
{"input": "高兴", "output": "开心"},
{"input": "难过", "output": "悲伤"},
{"input": "生气", "output": "愤怒"}
]
# 第二步:定义单条示例的格式化模板
example_formatter = PromptTemplate(
template="输入: {input}\n输出: {output}",
input_variables=["input", "output"]
)
# 第三步:创建少样本提示模板
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_formatter,
prefix="以下是一些同义词转换的例子:", # 示例前的说明文字
suffix="\n输入: {input}\n输出:", # 示例后的实际问题
input_variables=["input"]
)
# 第四步:格式化
prompt_value = few_shot_prompt.invoke({"input": "兴奋"})
# 第五步:定义LLM
llm = ChatOpenAI(model="gpt-4o-mini")
# 第六步:调用
res = llm.invoke(prompt_value)
print(res.content)
# 输出:激动8、提示词模板最佳实践
| 实践 | 说明 | 示例 |
|---|---|---|
| 清晰的指令 | 明确告诉模型要做什么 | "请翻译..." → "将以下文本从中文翻译成英文..." |
| 提供示例 | 使用少样本学习引导模型 | 使用 FewShotPromptTemplate |
| 角色设定 | 使用系统消息设定角色 | "你是一个有10年经验的Python工程师" |
| 约束条件 | 明确限制和约束 | "不超过100字"、"只回答与Python相关的问题" |
小结:介绍了LangChain提供的各类提示词模板。从简单的
PromptTemplate(字符串模板)到ChatPromptTemplate(聊天模板),再到FewShotPromptTemplate(少样本模板),它们解决的核心问题是如何灵活、可维护地构建Prompt。有了结构化的Prompt之后,下一个问题自然是:模型返回的结果如何解析为我们需要的结构化数据?这就是输出解析器要讨论的内容。