在大语言模型(LLM)应用开发中,提示词(Prompt)是引导模型行为的“指令集”。然而,硬编码静态提示词不仅难以维护,更无法适应动态输入。LangChain 的 Prompt 模板(Prompt Template)正是为解决这一问题而生,它提供了一套强大且灵活的机制,用于将用户输入、上下文信息和其他变量安全、高效地注入到预定义的提示词结构中,从而生成符合特定格式和意图的最终提示。

Prompt 模板的核心价值与设计哲学
Prompt 模板的核心作用在于解耦提示逻辑与动态数据。一个精心设计的提示模板就像一个填空题的骨架,其中包含固定的指令、示例(Few-shot)和占位符。当应用运行时,LangChain 负责将实时数据填充到这些占位符中,形成完整的、可执行的提示。
这种模式带来了多重优势。首先,它极大地提升了代码的可读性和可维护性。开发者可以专注于设计最优的提示策略,而不必在业务逻辑中拼接复杂的字符串。其次,它增强了安全性。通过使用 Pydantic 驱动的 ChatPromptTemplate,可以对输入变量进行类型校验和格式化,有效防止因恶意或畸形输入导致的提示注入(Prompt Injection)攻击。最后,它支持复杂的多消息对话历史管理,这是构建连贯的多轮对话机器人的基础。
LangChain 区分了两种主要的模板类型:PromptTemplate 用于传统的单字符串提示,而 ChatPromptTemplate 则专为现代聊天模型(如 GPT 系列、Claude)设计,能构造包含系统消息、人类消息和 AI 消息的多轮对话序列。
基础用法:PromptTemplate 与变量注入
PromptTemplate 是最简单的形式,适用于不需要复杂对话历史的场景。
from langchain_core.prompts import PromptTemplate
# 定义模板,{topic} 是占位符
template = "请写一篇关于{topic}的简短博客文章,字数约200字。"
prompt = PromptTemplate.from_template(template)
# 注入变量并生成最终提示
final_prompt = prompt.format(topic="可再生能源的未来")
print(final_prompt)
此例中,format 方法将 topic 变量的值替换到模板中的 {topic} 位置。模板可以包含多个占位符,并通过关键字参数传入。此外,PromptTemplate 还支持从文件加载模板内容,便于团队协作和版本控制。
高级用法:ChatPromptTemplate 构建多角色对话
对于基于聊天模型的应用,ChatPromptTemplate 是首选。它允许开发者精确控制每条消息的角色(系统、人类、AI)和内容。
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# 构建一个包含系统指令、对话历史和当前问题的模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个乐于助人的AI助手,名为{assistant_name}。"),
MessagesPlaceholder(variable_name="chat_history"), # 动态插入历史消息
("human", "{input}") # 当前用户输入
])
# 准备输入数据
input_data = {
"assistant_name": "小智",
"chat_history": [
("human", "你好!"),
("ai", "你好!有什么我可以帮你的吗?")
],
"input": "今天天气怎么样?"
}
# 生成消息列表
messages = prompt.invoke(input_data)
MessagesPlaceholder 是一个关键组件,它能自动将传入的 chat_history(一个由 (role, content) 元组组成的列表)转换为 LangChain 内部的消息对象(如 HumanMessage, AIMessage)。这使得在链(Chain)或智能体(Agent)中无缝集成对话历史变得异常简单。
结合输出解析器与链式调用
Prompt 模板很少单独使用,通常作为 LCEL(LangChain Expression Language)链的第一步。它可以与 LLM 和输出解析器(Output Parser)串联,形成端到端的数据处理管道。
例如,要求模型以 JSON 格式返回答案:
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.pydantic_v1 import BaseModel, Field
class Answer(BaseModel):
summary: str = Field(description="问题的摘要回答")
confidence: float = Field(description="回答的置信度,0-1之间")
parser = JsonOutputParser(pydantic_object=Answer)
# 在模板中加入格式化指令
prompt = ChatPromptTemplate.from_messages([
("system", "请根据以下上下文回答问题。{format_instructions}"),
("human", "上下文: {context}nn问题: {question}")
]).partial(format_instructions=parser.get_format_instructions())
chain = prompt | llm | parser
result = chain.invoke({"context": "...", "question": "..."})
# result 现在是一个 Answer 类型的 Pydantic 对象
这里使用了 .partial() 方法,它允许预先填充模板中的某些变量(如 format_instructions),使其在后续调用中保持不变。这种方式确保了输出格式的严格一致性,便于程序后续处理。
最佳实践与常见陷阱
使用 Prompt 模板时,有几个关键点需要注意。避免过度复杂的模板:虽然模板功能强大,但过于嵌套或包含大量逻辑的模板会变得难以调试。应尽量保持模板简洁,将复杂逻辑移至链的其他部分。重视变量命名:清晰、一致的变量名是保证模板可读性的关键。利用社区模板:LangChain Hub 提供了大量经过优化的模板,如 "rlm/rag-prompt",可以直接拉取使用,加速开发。