LangChain 提示词模板(Prompt Templates)
一、简介
提示词模板(Prompt Templates) 是 LangChain 最核心、最基础的模块之一,专门解决动态生成提示词的问题。它能让你把固定的提示词逻辑封装起来,通过传入变量自动生成高质量、标准化的提示词,告别手动拼接字符串的混乱与错误。
1.1 为什么需要提示词模板?
先看反面案例(手动拼接字符串):
user_name = "小明"
user_question = "Python 是什么?"
# 手动拼接,容易出错、难以维护
prompt = f"你是一个专业编程助手,请回答{user_name}的问题:{user_question}"
这种做法在简单场景下可行,但随着应用复杂度增加,会暴露出以下问题:
- 重复代码:相同的提示结构在多处重复出现。
- 难以维护:提示结构变更时需要修改多处代码。
- 缺少组合能力:无法方便地复用片段或动态组合。
- 难以与对话历史、工具调用等结合:纯字符串无法表达消息的角色、工具调用等元数据。
LangChain 的提示词模板通过将提示抽象为模板对象,解决了上述问题,并提供了丰富的扩展能力。让开发者能够实现以下:
- 统一抽象:通过 PromptTemplate 和 ChatPromptTemplate 将提示构建与模型调用解耦。
- 强大组合:支持变量、部分填充、消息占位符、Few-shot 等。
- 可复用与序列化:模板可以保存、加载,实现提示工程的最佳实践。
- 与 LCEL 无缝集成:模板作为链的一部分,可以灵活组合。
1.2 核心类型
LangChain 主要提供了两种主要的提示词模板类型:
| 模板类型 | 适用场景 | 输入格式 | 输出格式 |
|---|---|---|---|
| PromptTemplate | 简单的文本生成、旧版 LLM | 字符串变量 | 字符串 |
| ChatPromptTemplate | 对话模型(推荐) | 消息列表(角色+内容) | 消息列表 |
二、PromptTemplate(基础文本模板)
最简单的模板,用于生成纯文本提示词。使用 Python 的 str.format 语法({variable_name})。
2.1 基本用法
from langchain_core.prompts import PromptTemplate
# 1. 定义模板({变量名} 为占位符)
template = PromptTemplate(
input_variables=["name", "question"], # 声明变量
template="你是专业助手,请回答 {name} 的问题:{question}"
)
# 2. 传入变量,生成最终提示词
prompt = template.format(name="小明", question="Python 是什么?")
print(prompt)
简化写法(推荐):
template = PromptTemplate.from_template(
"你是专业助手,请回答 {name} 的问题:{question}"
)
# 自动识别变量,无需手动写 input_variables
输出:
你是专业助手,请回答 小明 的问题:Python 是什么?
2.2 从文件加载
把 Prompt 从代码里抽离出来,放在 .txt / .yaml / .json 文件中统一管理,方便修改、版本控制、多语言切换。
步骤 1:创建 Prompt 文件
新建文件:prompts/system_prompt.txt
你是一位专业的AI助手,请根据以下上下文回答用户问题。
保持回答简洁、准确、有礼貌。
上下文:{context}
用户问题:{question}
步骤 2:用 LangChain 加载并生成 PromptTemplate
from langchain.prompts import PromptTemplate
# 1. 从文本文件读取内容
with open("prompts/system_prompt.txt", "r", encoding="utf-8") as f:
prompt_template = f.read()
# 2. 加载为 PromptTemplate
prompt = PromptTemplate(
template=prompt_template,
input_variables=["context", "question"] # 必须和文件里的 {变量} 对应
)
# 测试
print(prompt.format(context="RAG是检索增强生成", question="RAG是什么?"))
三、ChatPromptTemplate(对话模板)
这是现代 LangChain 应用中最常用的模板类型。它将提示词组织为消息列表,每条消息都有明确的角色(system、human、ai)。
3.1 基本用法
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage
# 定义聊天模板(列表形式,按角色分段)
chat_prompt = ChatPromptTemplate.from_messages([
# 系统提示(固定角色)
("system", "你是 {role},回答语言必须使用 {language}"),
# 用户消息(动态问题)
("user", "{question}")
])
# 生成完整消息列表
messages = chat_prompt.format_messages(
role="资深Python工程师",
language="中文",
question="什么是装饰器?"
)
print(messages)
输出:
[
SystemMessage(content="你是 资深Python工程师,回答语言必须使用 中文"),
HumanMessage(content="什么是装饰器?")
]
3.2 支持的消息类型
ChatPromptTemplate.from_messages([
("system", "系统指令"), # SystemMessage
("human", "用户消息"), # HumanMessage
("ai", "AI消息"), # AIMessage
("function", "函数调用结果"), # FunctionMessage(旧版)
("tool", "工具结果"), # ToolMessage(新版)
])
3.3 角色写法支持 3 种格式
# 1. 元组(最简洁,推荐)
("system", "你是一个助手")
# 2. 消息类(灵活)
SystemMessage(content="你是一个助手")
# 3. 字典(兼容序列化)
{"role": "system", "content": "你是一个助手"}
3.4 链式调用与格式化
prompt = ChatPromptTemplate.from_template("解释:{topic}") # 快速创建单消息模板
# 等同于:
prompt = ChatPromptTemplate.from_messages([("human", "解释:{topic}")])
# 格式化获取消息列表
messages = prompt.format_messages(topic="量子计算")
# 格式化获取字符串(仅当只有一条消息时可用)
text = prompt.format(topic="量子计算")
四、MessagesPlaceholder(消息占位符)
这是 LangChain 中最强大的特性之一,用于在模板中动态插入任意数量的历史消息或工具结果。
4.1 基本用法
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个乐于助人的助手。"),
MessagesPlaceholder(variable_name="chat_history"), # 历史对话占位符
("human", "{input}")
])
# 动态插入历史消息
from langchain.memory import ChatMessageHistory
history = ChatMessageHistory()
history.add_user_message("我叫小明")
history.add_ai_message("你好小明!")
# 填充模板
messages = prompt.format_messages(
chat_history=history.messages, # 插入整个历史列表
input="我叫什么名字?"
)
4.2 控制占位符的显示方式
MessagesPlaceholder(
variable_name="conversation",
optional=True, # 是否可选(不提供时忽略)
separator="\n", # 消息之间的分隔符(仅字符串输出时)
)
五、模板变量与部分填充
5.1 变量
模板中可以定义任意数量的变量。格式化时必须提供所有变量的值(除非使用部分填充)。
template = "Hello {name}, your score is {score}."
prompt = PromptTemplate.from_template(template)
prompt.format(name="Alice", score=95) # 必须提供所有变量
5.2 批量生成提示词(Batch)
一次性生成多条提示:
prompts = template.batch([
{"name": "A", "question": "Q1"},
{"name": "B", "question": "Q2"}
])
5.3 校验变量
自动检查是否缺少变量:
template = PromptTemplate(
template="{a} + {b} = {c}",
input_variables=["a", "b"],
validate_template=True # 开启校验,发现缺少 c 会报错
)
5.4 部分填充(Partial)
部分填充允许我们预先固定某些变量的值,生成一个部分模板,稍后再填充剩余变量。
# 使用 partial 方法
partial_prompt = prompt.partial(score=100)
formatted = partial_prompt.format(name="Bob")
print(formatted) # Hello Bob, your score is 100.
部分填充也可以使用函数,在运行时动态计算:
from datetime import datetime
def _get_datetime():
return datetime.now().strftime("%Y-%m-%d")
prompt = PromptTemplate(
template="Today is {date}. Tell me a fact about {topic}.",
partial_variables={"date": _get_datetime}
)
print(prompt.format(topic="moon"))
# Today is 2025-03-28. Tell me a fact about moon.
5.5 序列化与保存(保存到文件 / 云端)
# 保存为 JSON
chat_prompt.save("prompt.json")
# 从文件加载
from langchain_core.prompts import load_prompt
loaded_prompt = load_prompt("prompt.json")
六、组合与管道
提示词模板可以与模型、输出解析器组合成可运行的链条(Runnable)。
6.1 基础组合
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
model = ChatOpenAI()
prompt = ChatPromptTemplate.from_template("用{language}写一首关于{theme}的诗。")
# 组合成 LCEL 链
chain = prompt | model | StrOutputParser()
# 执行
result = chain.invoke({"language": "中文", "theme": "春天"})
6.2 多输入与字典传递
# 模板可以包含多个变量
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个{role}。"),
("human", "请回答:{question}。参考上下文:{context}")
])
# invoke 时传递字典
chain = prompt | model
response = chain.invoke({
"role": "历史学家",
"question": "秦始皇统一六国的时间?",
"context": "公元前221年"
})
6.3 模板组合
可以将多个模板组合成一个更大的模板。LangChain 提供了 PipelinePromptTemplate,但更常见的是直接使用字符串拼接或利用 ChatPromptTemplate.from_messages 合并消息列表。
base_system = ChatPromptTemplate.from_messages([
("system", "You are an AI assistant. Follow the rules: {rules}.")
])
task_specific = ChatPromptTemplate.from_messages([
("human", "Solve this math problem: {problem}")
])
combined = ChatPromptTemplate.from_messages(
base_system.messages + task_specific.messages
)
七、Few-shot 提示模板
Few-shot 学习(少样本学习)需要在提示中提供几个示例,引导模型按示例格式输出。LangChain 提供了 FewShotPromptTemplate 和 FewShotChatMessagePromptTemplate 来简化这一过程。
7.1 基础 Few-shot 模板(文本模型)
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
# 定义示例格式
example_prompt = PromptTemplate(
input_variables=["input", "output"],
template="Input: {input}\nOutput: {output}"
)
# 示例列表
examples = [
{"input": "happy", "output": "joyful"},
{"input": "sad", "output": "unhappy"},
]
# 创建 FewShotPromptTemplate
few_shot = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
prefix="Give the antonym for the following words:",
suffix="Input: {word}\nOutput:",
input_variables=["word"],
example_separator="\n\n"
)
print(few_shot.format(word="big"))
# Give the antonym for the following words:
#
# Input: happy
# Output: joyful
#
# Input: sad
# Output: unhappy
#
# Input: big
# Output:
7.2 Few-shot 聊天模板
对于聊天模型,我们可以使用 FewShotChatMessagePromptTemplate,它接受一组聊天消息作为示例。
from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate
# 定义示例:每个示例是一组消息
examples = [
[
HumanMessage(content="What is 2+2?"),
AIMessage(content="4"),
],
[
HumanMessage(content="What is 3+3?"),
AIMessage(content="6"),
]
]
# 创建 Few-shot 模板
few_shot_template = FewShotChatMessagePromptTemplate(
examples=examples,
# 可选:指定每个示例的格式化方式,这里直接使用示例本身
example_prompt=ChatPromptTemplate.from_messages([("human", "{input}"), ("ai", "{output}")]),
# 但示例已经是消息,所以 example_prompt 实际上不会应用,而是直接使用 examples
)
# 合并到主模板
final_prompt = ChatPromptTemplate.from_messages([
("system", "You are a math assistant."),
few_shot_template,
("human", "{input}"),
])
# 格式化
messages = final_prompt.format_messages(input="What is 5+5?")
八、高级特性
8.1 自定义模板格式
当系统自带的 PromptTemplate / ChatPromptTemplate 不够用时,可以自己写一个完全可控的模板。其主要实现步骤有以下几点:
- 继承 StringPromptTemplate 或 BaseChatPromptTemplate
- 定义 input_variables
- 在 format() 或 format_messages() 里拼提示词
8.1.1 最简单的自定义模板
from langchain.prompts import StringPromptTemplate
from pydantic import BaseModel, Field
from typing import List
# 自定义模板
class MyCustomPrompt(StringPromptTemplate, BaseModel):
# 定义你需要的变量
context: str
question: str
def format(self, **kwargs) -> str:
# 在这里自由拼接提示词
return f"""
你是专业AI助手。
上下文:
{self.context}
用户问题:
{self.question}
请根据上下文回答问题。
"""
# 使用
prompt = MyCustomPrompt(
context="RAG是检索增强生成",
question="RAG是什么?"
)
print(prompt.format())
8.1.2 带动态变量的自定义模板
class RAGPrompt(StringPromptTemplate, BaseModel):
# 允许外部传入
input_variables: List[str] = ["context", "question"]
def format(self,** kwargs):
context = kwargs["context"]
question = kwargs["question"]
return f"""
请根据下面的文档回答问题,不要编造。
文档:
{context}
问题:{question}
"""
# 使用
prompt = RAGPrompt()
print(prompt.format(context="xxx", question="yyy"))
8.1.3 聊天模型专用自定义模板
适合 Qwen、Llama、ChatGLM、GPT 等。
from langchain.schema import SystemMessage, HumanMessage, AIMessage
from langchain.prompts import BaseChatPromptTemplate
from typing import List, Sequence
class ChatCustomPrompt(BaseChatPromptTemplate, BaseModel):
def format_messages(self,** kwargs) -> Sequence:
context = kwargs["context"]
question = kwargs["question"]
return [
SystemMessage(content="你是专业RAG助手,根据上下文回答。"),
HumanMessage(content=f"上下文:{context}\n问题:{question}")
]
# 使用
prompt = ChatCustomPrompt(input_variables=["context", "question"])
msgs = prompt.format_messages(context="检索内容", question="什么是RAG?")
8.1.4 带逻辑的高级自定义模板
例如:自动截断上下文、过滤空内容、拼接历史对话
class AdvancedRAGPrompt(StringPromptTemplate, BaseModel):
input_variables: List[str] = ["context", "question", "history"]
def format(self, **kwargs):
context = kwargs["context"]
question = kwargs["question"]
history = kwargs.get("history", "")
# 自定义逻辑1:截断太长的上下文
if len(context) > 2000:
context = context[:2000] + "..."
# 自定义逻辑2:拼接历史
history_prompt = f"历史对话:{history}" if history else ""
return f"""
{history_prompt}
上下文:
{context}
问题:{question}
请简洁回答。
"""
8.2 多模态模板(图像+文本)
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import HumanMessage
# 手动构建多模态消息
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个图像识别助手。"),
("human", [
{"type": "text", "text": "描述这张图片:{description_request}"},
{"type": "image_url", "image_url": {"url": "{image_url}"}}
])
])
8.3 与模型链(Chain)结合
提示词模板通常与 LLMChain 或 ChatOpenAI 结合使用,构建完整的链。
from langchain.chains import LLMChain
from langchain_openai import OpenAI
llm = OpenAI()
prompt = PromptTemplate.from_template("Tell me a {adjective} joke about {topic}.")
chain = LLMChain(llm=llm, prompt=prompt)
result = chain.run(adjective="funny", topic="dogs")
print(result)
对于聊天模型,可以使用 ChatOpenAI 和 ChatPromptTemplate:
from langchain_openai import ChatOpenAI
chat_model = ChatOpenAI()
chat_prompt = ChatPromptTemplate.from_messages([
("system", "You are a {persona} assistant."),
("human", "{input}")
])
chain = chat_prompt | chat_model # 使用 LCEL(LangChain Expression Language)
response = chain.invoke({"persona": "pirate", "input": "Tell me a joke."})
8.4 动态选择模板
from langchain_core.prompts import PromptTemplate
# 根据条件选择不同模板
def select_template(topic):
if topic == "代码":
return PromptTemplate.from_template("用{python}代码实现:{task}")
else:
return PromptTemplate.from_template("解释:{task}")
template = select_template("代码")
九、最佳实践与技巧
- 使用 ChatPromptTemplate 处理聊天模型:即使是简单场景,也推荐使用聊天模板,因为它天然支持系统消息、历史等扩展。
- 利用 MessagesPlaceholder 注入动态内容:如对话历史、工具调用结果,避免硬编码。
- 部分填充实现默认值:将不常变的变量(如当前日期、固定指令)通过 partial 固化,减少调用时的参数。
- 示例管理:对于 Few-shot,考虑将示例存储在外部文件或数据库中,动态加载。
- 模板版本控制:将提示模板保存为独立文件,方便团队协作和 A/B 测试。
- 避免在模板中写入敏感信息:使用环境变量或部分填充函数从安全处获取。
- 调试:在开发阶段,可以先用 format_messages 查看最终生成的消息,再送入模型。
更多推荐


所有评论(0)