一、为什么需要提示词模板?
过去一段时间,大家和大模型交互时,往往习惯直接手写 Prompt:
"帮我写一封请假条。"
"用 Python 写一个快速排序。"
这种方式在小实验中没问题,但一旦进入工程化开发,立刻会遇到几个问题:
-
不可复用:每次都要重新写 Prompt,重复劳动。
-
容易出错:变量拼接混乱,格式不一致。
-
难以维护:Prompt 散落在代码各处,改一处要全局搜索。
-
缺乏结构:系统指令、用户输入、示例混杂在一起。
于是,**提示词模板(Prompt Template)** 应运而生。
一句话概括:
提示词模板 = 把"写死的 Prompt"变成"可配置、可复用、可组合的结构化指令系统"。
它不是简单地往字符串里填变量,而是 LangChain 工程化体系里的第一块积木。
二、什么是提示词模板?
1️⃣ 通俗理解
你可以把提示词模板想象成**"填空题"** 或**"邮件模板"**:
-
固定内容:系统角色、任务要求、输出格式。
-
可变内容:用户输入、日期、上下文、示例。
运行时,LangChain 会把变量注入模板,生成最终交给大模型的 Prompt。
2️⃣ 一个直观对比
传统写法(硬编码):
prompt = "你是一个Python工程师,请解释什么是装饰器。"
问题:换个角色就要重写,换个问题也要重写。
模板化写法:
template = "你是一个{role},请解释{concept}。"
优点:同一个模板,可以生成无数个不同场景的 Prompt。
三、提示词模板的核心组成
一个成熟的提示词模板,通常包含以下几个维度:
| 组成部分 | 作用 | 示例 |
|---|---|---|
| 静态文本 | 固定不变的指令 | "你是一个资深工程师" |
| 变量占位符 | 动态注入用户输入 | {topic}, {question} |
| 系统指令 | 定义角色和行为边界 | System Message |
| **示例(Few-Shot)** | 教模型"照葫芦画瓢" | 输入/输出对 |
| 历史上下文 | 支持多轮对话 | chat_history |
LangChain 把这些要素抽象成了不同类型的模板类,让你可以像搭积木一样组合它们。
四、LangChain 常见提示词模板类型
✅ 1. PromptTemplate(基础文本模板)
最基础的模板,用于生成纯字符串 Prompt。
适用场景:
-
简单的文本生成
-
单轮问答
-
不需要角色区分的任务
from langchain_core.prompts import PromptTemplate
template = PromptTemplate.from_template(
"你是一个{role},请用{style}风格回答:{question}"
)prompt_value = template.invoke({
"role": "算法工程师",
"style": "专业严谨",
"question": "什么是梯度下降?"
})print(prompt_value.to_string())
👉 适合入门和简单任务,写法最接近原生字符串格式化。
✅ 2. ChatPromptTemplate(聊天消息模板)
这是生产环境最常用的模板,专为聊天模型设计。
它生成的不是字符串,而是一个消息列表(List of Messages),包含 system、human、ai 等角色。
from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate.from_messages([
("system", "你是一个{role},回答要控制在{word_count}字以内。"),
("human", "{user_input}")
])
prompt_value = chat_template.invoke({
"role": "产品经理",
"word_count": 100,
"user_input": "帮我写一段AI Agent的需求文档摘要。"
})
print(prompt_value.to_messages())
👉 适合构建聊天机器人、客服助手、多轮对话系统。
✅ 3. FewShotPromptTemplate(少样本模板)
当你需要模型严格按照某种格式或风格输出时,仅靠文字描述往往不够稳定。这时就需要给模型看"示例"。
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
examples = [
{"input": "开心", "output": "难过"},
{"input": "高", "output": "矮"},
]
example_template = PromptTemplate.from_template(
"输入:{input}\n输出:{output}"
)
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_template,
prefix="请根据示例写出反义词:",
suffix="输入:{word}\n输出:",
input_variables=["word"]
)
print(few_shot_prompt.invoke({"word": "快"}).to_string())
👉 适合分类任务、格式转换、风格模仿。
✅ 4. MessagesPlaceholder(动态消息占位符)
在多轮对话中,你无法预知用户会说几句。这时就需要 MessagesPlaceholder来动态插入历史记录。
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage
chat_template = ChatPromptTemplate.from_messages([
("system", "你是一个乐于助人的助手。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
history = [
HumanMessage(content="我叫小明。"),
AIMessage(content="你好小明,很高兴认识你!")
]
prompt_value = chat_template.invoke({
"history": history,
"input": "你还记得我的名字吗?"
})
print(prompt_value.to_messages())
👉 这是构建有记忆的 AI Agent 的关键组件。
五、进阶技巧:组合与工程化
1. 模板组合(+ 运算符)
LangChain 支持把多个模板拼在一起,实现模块化复用:
from langchain_core.prompts import PromptTemplate
base_template = PromptTemplate.from_template("你是一个{expertise}领域的专家。\n")
task_template = PromptTemplate.from_template("请完成以下任务:{task}")
combined_template = base_template + task_template
print(combined_template.invoke({
"expertise": "金融",
"task": "解释什么是复利效应。"
}).to_string())
2. Partial(部分变量预填充)
有些变量是全局固定的(如当前时间、系统版本),可以用 partial提前锁定:
from datetime import datetime
from langchain_core.prompts import PromptTemplate
template = PromptTemplate.from_template(
"当前时间:{current_time}\n问题:{question}"
).partial(current_time=datetime.now().strftime("%Y-%m-%d %H:%M"))
print(template.invoke({"question": "今天星期几?"}).to_string())
3. LCEL 链式调用(Prompt → LLM → Output)
提示词模板通常不是孤立使用的,它会和模型、输出解析器连成一条链:
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI # 或其他兼容模型
prompt = ChatPromptTemplate.from_template("{question}")
model = ChatOpenAI()
parser = StrOutputParser()
chain = prompt | model | parser
result = chain.invoke({"question": "用一句话解释LangChain。"})
print(result)
👉 这就是 LangChain 表达式语言(LCEL)的魅力:把"生成 Prompt → 调用模型 → 解析输出"变成一条流水线。
六、提示词模板 vs 裸写 Prompt
| 对比项 | 裸写 Prompt | 提示词模板 |
|---|---|---|
| 是否可复用 | ❌ | ✅ |
| 是否支持变量 | ❌ | ✅ |
| 是否支持多轮对话 | ❌ | ✅ |
| 是否支持示例注入 | ❌ | ✅ |
| 是否易于维护 | ❌ | ✅ |
| 是否适合生产环境 | ❌ | ✅ |
👉 模板不是为了炫技,而是为了把 Prompt 从"字符串"升级为"工程资产"。
七、常见坑点与最佳实践
⚠️ 常见坑
-
变量名不一致 :模板里写
{input},调用时传{"user_input": "xxx"},直接报错。 -
忘记转义:模板里有 JSON 结构,花括号冲突导致格式化失败。
-
过度堆砌示例:Few-Shot 示例太多会撑爆 Token 窗口,增加成本和延迟。
-
忽视角色分离:把所有指令都塞进 user 消息,导致模型行为不稳定。
✅ 最佳实践
-
命名清晰 :用
user_input、task_description,别用a、b、x。 -
三段式结构:任务描述 + 上下文 + 输出约束。
-
优先使用
invoke:它是 LangChain Runnable 标准接口,兼容链式调用。 -
复杂对话用 ChatPromptTemplate:永远不要用字符串模板硬拼多轮对话。
八、总结一句话
提示词模板不是"更复杂的 Prompt",而是让 AI 从"临时对话"走向"工程化交付"的基础设施。
如果说大模型是发动机,那么提示词模板就是方向盘、仪表盘和控制系统。没有它,你只能"开一下";有了它,你才能造出一辆真正能跑的车。