🎯 课程主题
讲解 ChatPromptTemplate 的核心概念、两种实例化方式(from_messages 类方法与直接构造)以及三种调用方式(invoke、format、format_messages),并与模型调用串联展示完整链路。
📝 核心知识点
1. 提示词(Prompt)与提示词模板(PromptTemplate)
- 概念说明:
- 提示词:调用
model.invoke()时传入的参数,可以是字符串、消息列表或字典列表。 - 提示词模板:一种填充提示词中变量的方案,类比作文模板——预先定义结构,使用时填充变量。
- 提示词:调用
- 关键细节:传统字符串拼接方式的缺点:可读性差、不易维护、无变量校验机制、难以支持多角色复杂场景。正式开发推荐使用 PromptTemplate。
2. 两种 PromptTemplate API
- 概念说明:
PromptTemplate:对应补全模型(Completion Model),处理单一字符串,已非主流,本节不讲。ChatPromptTemplate:对应对话模型(Chat Model),处理结构化的消息列表,本节主角。
- 关键细节:LangChain 官网明确指出,结构化的消息列表已取代单一字符串成为模型交互的标准数据格式。
PromptTemplate无法模拟多轮对话中的不同角色。
3. ChatPromptTemplate 的两种实例化方式
- 方式一:
from_messages()类方法(推荐)- 传入由元组构成的列表:
[("system", "..."), ("user", "..."), ("ai", "..."), ("human", "{变量}")] - 内部最终仍调用
__init__构造函数,但写法更清晰、符合直觉。
- 传入由元组构成的列表:
- 方式二:直接构造
ChatPromptTemplate(messages=[...])- 本质与方式一相同,源码中
from_messages最终转到__init__。
- 本质与方式一相同,源码中
- 关键细节:
- 有效角色类型(大小写敏感,必须小写):
system、user/human、ai/assistant。 - 变量使用花括号包裹:
{"name"}、"{user_input}"。
- 有效角色类型(大小写敏感,必须小写):
4. ChatPromptTemplate 的三种调用方式
| 方法 | 参数形式 | 返回值类型 | 用途 |
|---|---|---|---|
invoke({"var": "val"}) | 字典 | ChatPromptValue | 返回 PromptValue,可直接传入 model.invoke() |
format(var="val") | 关键字参数 | str | 返回格式化后的字符串 |
format_messages(var="val") | 关键字参数 | List[Message] | 返回消息列表 |
- 关键细节:三种方法的返回值均可直接传入
model.invoke(),因为模型同时接受str、List[Message]、PromptValue类型。
🏗️ 架构与工作流
ChatPromptTemplate.from_messages([
("system", "你是{name}..."),
("human", "{user_input}")
])
│
├── .invoke({"name": "小智", "user_input": "2+2=?"})
│ └──→ ChatPromptValue → model.invoke() → AIMessage
│
├── .format(name="小智", user_input="2+2=?")
│ └──→ str → model.invoke() → AIMessage
│
└── .format_messages(name="小智", user_input="2+2=?")
└──→ List[Message] → model.invoke() → AIMessage
💻 代码实战
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="gpt-4o",
base_url="https://api.claude.ai/v1",
api_key="your-api-key"
)
# ========== 实例化方式一:from_messages() — 推荐 ==========
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个友好的AI助手,你的名字叫{name}。"),
("user", "你好,最近怎么样?"),
("ai", "我很好,谢谢!"),
("human", "{user_input}"),
])
# ========== 实例化方式二:直接构造 ==========
chat_prompt = ChatPromptTemplate(messages=[
("system", "你是一个友好的AI助手,你的名字叫{name}。"),
("user", "你好,最近怎么样?"),
("ai", "我很好,谢谢!"),
("human", "{user_input}"),
])
# ========== 调用方式一:invoke() — 返回 ChatPromptValue ==========
result = chat_prompt.invoke({"name": "小智", "user_input": "2+2等于多少?"})
print(result) # ChatPromptValue 对象
print(type(result)) # <class 'langchain_core.prompt_values.ChatPromptValue'>
# ========== 调用方式二:format() — 返回字符串 ==========
result = chat_prompt.format(name="小智", user_input="2+2等于多少?")
print(result)
print(type(result)) # <class 'str'>
# ========== 调用方式三:format_messages() — 返回消息列表 ==========
result = chat_prompt.format_messages(name="小智", user_input="2+2等于多少?")
print(result)
print(type(result)) # <class 'list'>
# ========== 结合模型调用 ==========
prompt_value = chat_prompt.invoke({"name": "小智", "user_input": "2+2等于多少?"})
response = model.invoke(prompt_value)
print(response.content)
# format_messages() 的结果也可直接传入
messages = chat_prompt.format_messages(name="小智", user_input="2+2等于多少?")
response = model.invoke(messages)
print(response.content)
⚠️ 常见问题与避坑指南
- 角色名称大小写敏感:
AI(大写)会报错,必须使用ai/assistant、user/human、system(全小写)。错误示例:("AI", "...")→ 报错message type "AI" is not recognized。 from_messages传入的是元组列表:格式为[("角色", "内容"), ...],不要误写成字典。- 变量使用花括号:模板字符串中的变量用
{变量名}包裹,调用时需通过字典或关键字参数传入对应的值,否则会报错。 - 三种调用方式的参数形式不同:
invoke()接受字典{"key": "value"},而format()和format_messages()接受关键字参数key="value",混用会导致报错。 - 开发建议:小 Demo 可用字符串拼接,正式 AI 应用开发推荐使用
ChatPromptTemplate——结构清晰、可复用、有变量校验。
💡 个人总结与延伸
本节完整覆盖了 ChatPromptTemplate 的实例化与调用方式,是 LangChain 提示词工程的基础。from_messages() 是推荐的实例化方式,代码可读性更好。三种调用方式可根据实际场景选择:需要 PromptValue 传模型时用 invoke(),只需字符串展示时用 format(),需要逐条消息操作时用 format_messages()。后续学习 LCEL(LangChain Expression Language)链式调用时,模板 + 模型 + 解析器的管道模式(prompt | model | parser)正是基于本节的内容构建。