5.提示词模板
提示词模板
一、基础概念前置
1 两类核心模板区分
- PromptTemplate:纯字符串文本模板,适合单轮简单提问,输出普通文本字符串
- ChatPromptTemplate:结构化对话模板,区分system/human/ai角色,适配聊天大模型,生产消息列表(工业95%场景首选)
2 四大消息角色
- SystemMessage:系统角色,定义AI身份、输出规则、回答边界
- HumanMessage:用户人类提问
- AIMessage:AI历史回复(用于多轮上下文)
- ToolMessage:工具返回数据(工具调用场景专用)
3 占位符核心作用
把可变内容抽离成{变量名},一套模板复用不同输入,避免硬编码重复文本;
特殊:MessagesPlaceholder支持一对多填充多条历史对话消息。
二、PromptTemplate 纯文本提示模板
2.1 两种实例化创建模板
方式1:构造函数直接创建 PromptTemplate
from langchain_core.prompts import PromptTemplate
# template:模板文本;input_variables:模板内所有占位变量列表
template = PromptTemplate(
template="你是专业{role}工程师,解答问题:{question}",
input_variables=["role", "question"]
)
# format填充变量,输出纯字符串
prompt_str = template.format(role="Python", question="冒泡排序代码")
print(prompt_str)
讲解:手动声明输入变量,适合模板逻辑复杂、需要显式管控变量的场景。
方式2:静态方法 from_template(推荐最简写法)
template = PromptTemplate.from_template("你是专业{role}工程师,解答问题:{question}")
prompt_str = template.format(role="Java", question="快速排序思路")
讲解:自动识别{xxx}占位,不用手动写input_variables,日常开发首选。
2.2 三大格式化核心方法
- format() → 返回纯字符串(最简单,只输出文本)
res = template.format(role="前端", question="Vue双向绑定原理")
print(type(res)) # str
- invoke() → 返回PromptValue对象(高阶,可转字符串/消息列表)
prompt_val = template.invoke({"role":"Go", "question":"goroutine原理"})
print(prompt_val.to_string()) # 转文本
print(prompt_val.to_messages()) # 转消息列表,对接Chat模型
- partial() → 局部预填充变量,返回新模板(半成品模板)
2.3 partial 局部预填充(动静分离)
适用:部分变量固定不变,仅少量变量动态传入(如固定时间、固定角色)
from datetime import datetime
# 写法1:实例时传入partial_variables
t1 = PromptTemplate.from_template(
"当前时间{now},问题:{q}",
partial_variables={"now": datetime.now().strftime("%Y-%m-%d")}
)
print(t1.format(q="今天几号"))
# 写法2:模板.partial() 动态绑定固定变量
t2 = PromptTemplate.from_template("当前时间{now},问题:{q}")
t2_fixed = t2.partial(now=datetime.now().strftime("%Y-%m-%d"))
print(t2_fixed.format(q="现在几点"))
逻辑:提前锁定不变参数,后续只传动态参数,减少重复传参。
2.4 多模板拼接组合
多个短模板相加,拼接成完整提示词
t1 = PromptTemplate.from_template("用通俗语言介绍{topic}\n")
t2 = PromptTemplate.from_template("回答字数不超过{num}")
t_all = t1 + t2 # 模板拼接
print(t_all.format(topic="Redis", num=100))
2.5 外部加载模板(解耦代码与提示词)
提示词写在json/yaml文件,不硬编码在Python里,便于运营修改文案
1)prompt.json 配置文件
{
"_type": "prompt",
"input_variables": ["name", "content"],
"template": "请{name}讲解{content}"
}
2)加载代码
from langchain_core.prompts import load_prompt
template = load_prompt("prompt.json", encoding="utf-8")
print(template.format(name="程序员", content="生成器"))
yaml文件用法一致,仅文件格式不同。
三、ChatPromptTemplate 对话模板
3.1 三种消息入参格式(创建模板时可用)
格式1:元组列表(最简,项目最常用)
from langchain_core.prompts import ChatPromptTemplate
chat_tpl = ChatPromptTemplate([
("system", "你是资深{lang}开发工程师"),
("human", "讲解{func}底层原理")
])
格式2:字典列表
chat_tpl = ChatPromptTemplate([
{"role":"system", "content":"你是资深{lang}开发工程师"},
{"role":"human", "content":"讲解{func}底层原理"}
])
格式3:Message 对象列表(多轮历史硬编码场景)
from langchain_core.messages import SystemMessage, HumanMessage
chat_tpl = ChatPromptTemplate([
SystemMessage(content="你是资深{lang}开发工程师"),
HumanMessage(content="讲解{func}底层原理")
])
3.2 标准创建方式 from_messages
chat_tpl = ChatPromptTemplate.from_messages([
("system", "你是资深Python工程师"),
("human", "{user_question}")
])
# format_messages:输出 List[BaseMessage] 消息列表,直接传给LLM
msg_list = chat_tpl.format_messages(user_question="装饰器作用")
print(msg_list)
3.3 ChatPromptTemplate 三种格式化方法
format_messages():返回消息列表,模型原生接收格式(推荐)invoke(dict):返回PromptValue,支持to_string()/to_messages()format():直接拼接成纯文本字符串,调试用
3.4 MessagesPlaceholder 历史对话占位(多轮对话核心)
作用:占位位置批量插入多条历史Human/AI消息,实现上下文记忆,分显式、隐式简写两种写法
写法1:显式导入 MessagesPlaceholder
from langchain_core.prompts import MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage
prompt = ChatPromptTemplate.from_messages([
("system", "你是Python开发工程师"),
MessagesPlaceholder("memory"), # 历史消息占位符
("human", "{question}")
])
# 传入历史对话 + 当前问题
res = prompt.invoke({
"memory": [
HumanMessage("我叫亮仔,程序员"),
AIMessage("亮仔你好")
],
"question": 我叫什么名字?
})
print(res.to_string())
写法2:隐式简写 ("placeholder", "变量名")
等价于上面MessagesPlaceholder("memory"),代码更整洁
prompt = ChatPromptTemplate.from_messages([
("system", "你是Python开发工程师"),
("placeholder", "{memory}"), # 隐式消息占位
("human", "{question}")
])
四、LLM 六大模型调用方式(同步+异步)
前置模型初始化(通义千问兼容OpenAI接口示例)
import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
load_dotenv()
# 初始化通义千问大模型
model = init_chat_model(
model="qwen-plus",
model_provider="openai",
api_key=os.getenv("aliQwen-api"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
同步调用(主线程阻塞,简单业务优先)
- invoke() 单次完整请求,一次性返回全部结果
messages = [SystemMessage("简洁回答,100字内"), HumanMessage("什么是Redis")]
resp = model.invoke(messages)
print(resp.content)
- stream() 流式逐块返回(打字机效果,前端对话)
for chunk in model.stream(messages):
print(chunk.content, end="", flush=True)
- batch() 批量一次性执行多个问题
qs = ["Redis是什么", "Python生成器作用", "Docker和K8s关系"]
res_list = model.batch(qs)
for q, r in zip(qs, res_list):
print(f"问题:{q}\n答案:{r.content}")
异步调用(web服务、高并发不阻塞主线程)
方法名带前缀a,搭配async/await + asyncio.run()
- ainvoke 异步单次请求
import asyncio
async def run():
resp = await model.ainvoke("LangChain介绍,100字")
print(resp.content)
asyncio.run(run())
- astream 异步流式输出
async def run_stream():
async for chunk in model.astream(messages):
print(chunk.content, end="")
asyncio.run(run_stream())
- abatch 异步批量并发提问(性能最优)
async def run_batch():
qs = ["Redis是什么", "Python生成器作用"]
res = await model.abatch(qs)
for q, r in zip(qs, res):
print(q, r.content)
asyncio.run(run_batch())
六大调用场景选择口诀
- 简单单轮问答 → invoke
- 前端实时打字效果 → stream / astream
- 一次性批量多个问题 → batch / abatch
- FastAPI、高并发web服务 → 全部用异步a开头方法
- 接口阻塞、并发量大 → 放弃同步,改用异步
五、综合完整案例(带历史记忆对话)
import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import HumanMessage, AIMessage
# 1 加载模型
load_dotenv()
model = init_chat_model(
model="qwen-plus",
model_provider="openai",
api_key=os.getenv("aliQwen-api"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
# 2 构建带历史占位的对话模板
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是资深Python后端工程师,回答简洁"),
("placeholder", "{history}"), # 历史对话占位
("human", "{input}")
])
# 3 填充模板,拼接历史对话
prompt_val = chat_prompt.invoke({
"history": [
HumanMessage("我叫亮仔,后端程序员"),
AIMessage("亮仔你好,有什么Python问题?")
],
"input": "我的名字是什么?"
})
# 4 调用大模型
resp = model.invoke(prompt_val.to_messages())
print("AI回答:", resp.content)
运行效果:模型读取历史对话,正确输出名字「亮仔」,实现上下文记忆。
六、学习总结
- 日常对话业务优先用
ChatPromptTemplate,区分角色,支持多轮记忆;简单单文本提问用PromptTemplate。 - 占位符分普通变量
{xxx}、消息占位MessagesPlaceholder(一对多填充历史)。 - 模板创建:from_template / from_messages 最简,优先使用;partial实现固定参数预填充。
- 模型调用分同步/异步,流式用于前端实时展示,批量处理多问题,web服务全部异步。
- 复杂提示词建议外部json/yaml加载,代码和文案解耦,方便迭代维护。

浙公网安备 33010602011771号