在这里插入图片描述

在使用 LangChain 构建 AI 应用时,提示词模板是连接用户输入和大语言模型的关键桥梁。今天我们来深入了解 ChatPromptTemplate —— 一个专为对话场景设计的强大工具。

ChatPromptTemplate 是什么

ChatPromptTemplate 是 LangChain 中专为多角色对话场景设计的提示词模板类。它通过结构化的方式组织 System、Human、AI 等不同角色的消息,让复杂对话的构建变得清晰可控。

与 PromptTemplate 的本质区别:

  • PromptTemplate:单一文本模板,适合简单的单次问答
  • ChatPromptTemplate:消息列表模板,为多轮对话和角色管理而生

核心设计:元组参数格式

ChatPromptTemplate 使用元组来定义每条消息:

(role, content)
  • role:字符串类型,如 "system""human""ai"
  • content:字符串类型,支持 {变量名} 占位符

这种设计带来三个优势:

  1. 代码可读性强,角色一目了然
  2. 类型安全,减少运行时错误
  3. 易于扩展和维护

两种实例化方式对比

方式一:构造方法

from langchain_core.prompts import ChatPromptTemplate

chat_prompt = ChatPromptTemplate(
    messages=[
        ("system", "你是一个AI助手,你的名字叫{name}"),
        ("human", "我的问题是{question}")
    ],
    input_variables=["name", "question"]
)

特点: 显式声明 input_variables,适合需要严格参数校验的场景。

方式二:from_messages() 【推荐】

chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个AI助手,你的名字叫{name}"),
    ("human", "我的问题是{question}")
])

特点: 自动识别变量,代码更简洁。95% 的场景推荐使用。


四种调用方法的本质差异

理解这四种方法的关键是 输入方式输出类型

核心对比表

方法 输入 输出 核心用途
invoke() 字典 ChatPromptValue 链式调用标准接口
format() 关键字参数 str 调试查看
format_messages() 关键字参数 list[BaseMessage] 消息对象操作
format_prompt() 关键字参数 ChatPromptValue 非链式场景的标准输出

1. invoke() - 链式调用标准

result = chat_prompt.invoke({"name": "小智", "question": "1+2*3=?"})
# 输出: ChatPromptValue(messages=[SystemMessage(...), HumanMessage(...)])

关键点: 传入字典,返回 ChatPromptValue 对象,这是 LangChain 链式调用的标准输入格式。

2. format() - 快速调试

result = chat_prompt.format(name="小智", question="1+2*3=?")
# 输出: "System: 你是一个AI助手,你的名字叫小智\nHuman: 我的问题是1+2*3=?"

关键点: 返回字符串,直接看到最终发送给模型的文本,调试利器。

3. format_messages() - 消息级操作

messages = chat_prompt.format_messages(name="小智", question="1+2*3=?")
# 输出: [SystemMessage(content='...'), HumanMessage(content='...')]

# 典型应用:插入历史消息
messages.insert(1, AIMessage(content="我记得你上次问过类似问题"))

关键点: 返回消息对象列表,可直接操作每条消息,适合需要动态调整对话结构的场景。

4. format_prompt() - 非字典输入的标准输出

result = chat_prompt.format_prompt(name="小智", question="1+2*3=?")
# 输出: ChatPromptValue(messages=[...])

关键点: 功能等同 invoke(),但使用关键字参数而非字典。


实战选择指南

场景一:构建标准 LCEL 链

from langchain_openai import ChatOpenAI

chain = chat_prompt | ChatOpenAI(model="gpt-4")
result = chain.invoke({"name": "小智", "question": "1+2*3=?"})

选择: invoke() - 字典格式是链式调用的标准

场景二:调试模板输出

print(chat_prompt.format(name="小智", question="测试"))

选择: format() - 直观查看文本

场景三:动态插入历史对话

messages = chat_prompt.format_messages(name="小智", question="今天天气")
messages.insert(1, HumanMessage(content="昨天:你好"))
messages.insert(2, AIMessage(content="昨天:你好,我是小智"))

选择: format_messages() - 可操作消息列表

场景四:简单脚本(非链式)

prompt_value = chat_prompt.format_prompt(name="小智", question="测试")
response = llm.generate_prompt([prompt_value])

选择: format_prompt() - 关键字参数更直观


进阶技巧(选)

技巧 1:MessagesPlaceholder 处理历史对话

from langchain_core.prompts import MessagesPlaceholder

chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是助手{name}"),
    MessagesPlaceholder(variable_name="history"),
    ("human", "{question}")
])

# 使用时传入历史消息
chat_prompt.invoke({
    "name": "小智",
    "history": [
        HumanMessage(content="1+1=?"),
        AIMessage(content="1+1=2")
    ],
    "question": "那2+2呢?"
})

技巧 2:partial() 预填充变量

# 固定 system 角色名称
partial_prompt = chat_prompt.partial(name="小智")

# 之后只需传入 question
result = partial_prompt.invoke({"question": "你好"})

常见错误与避坑

错误 1:混淆输入格式

# ❌ 错误:invoke() 不接受关键字参数
chat_prompt.invoke(name="小智", question="测试")

# ✅ 正确
chat_prompt.invoke({"name": "小智", "question": "测试"})

错误 2:变量名不匹配

# 模板中是 {question},但传入了 {query}
chat_prompt.invoke({"name": "小智", "query": "测试"})  # ❌ KeyError

总结

ChatPromptTemplate 的核心价值在于结构化组织多角色对话。掌握它的关键是:

  1. 实例化: 优先使用 from_messages()
  2. 调用方法: 根据场景选择合适的输出格式
  3. 进阶应用: 利用 MessagesPlaceholder 和 partial 处理复杂场景

2025.10.04 吉林·松原

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐