LangChain入门实践3:PromptTemplate提示词模板详解
LangChain框架入门:PromptTemplate提示词模板详解
1. 提示词模板(PromptTemplate)
大多数LLM应用程序不会直接将用户输入传递到LLM中。通常,它们会将用户输入添加到一个更大的文本片段中,称为提示模板,这是一种特殊的文本,该模板提供了有关特定任务的附加上下文,能够更好地引导模型生成预期的输出。
在前面的示例中,我们传递给模型的文本包含了生成公司名称的指令。对于我们的应用程序,如果用户只需提供公司/产品的描述而无需担心给出模型指令,那将非常好。
1.1 PromptTemplate文本提示词模板
PromptTemplates正是为此而设计的!它们将用户输入转化为完全格式化的提示的所有逻辑绑定在一起。这可以从非常简单的开始 - 例如,产生前文实践2中的字符串的提示只需如下代码:
from langchain.prompts import PromptTemplateprompt = PromptTemplate.from_template("What is a good name for a company that makes {product}?")
prompt_value = prompt.format(product="colorful socks")
print(prompt_value)
执行结果:
What is a good name for a company that makes colorful socks?
使用这些而不是原始字符串格式化的优势有几个。您可以"部分"出变量 - 例如,您可以一次只格式化某些变量。您可以将它们组合在一起,轻松地将不同的模板组合成一个单独的提示。在执行format时将变量格式化到提示词模板中。
1.2 PromptTemplate文本提示词模板
PromptTemplate 针对文本生成模型的提示词模板,也是LangChain提供的最基础的模板,通过格式化字符串生成提示词,除了format方法,也可以在执行invoke时将变量格式化到提示词模板中,示例如下:
from langchain.prompts import PromptTemplateprompt = PromptTemplate.from_template("What is a good name for a company that makes {product}?")
prompt_value = prompt.invoke({"product": "colorful socks"})
print(prompt_value)
执行结果:
text='What is a good name for a company that makes colorful socks?'
1.3 ChatPromptTemplate聊天消息提示词模板
PromptTemplates还可以用于生成消息列表。在这种情况下,提示不仅包含有关内容的信息,还包含每个消息(其角色、其在列表中的位置等)。在这里,最常见的是ChatPromptTemplate是ChatMessageTemplate的列表。
每个ChatMessageTemplate包含了格式化该ChatMessage的指令 - 其角色,以及其内容。ChatPromptTemplate 是专为聊天模型(如 gpt-3.5-turbo、gpt-4 等)设计的提示词模板,它支持构造多轮对话的消息结构,每条消息可指定角色(如系统、用户、AI)。让我们在下面看一下:
from langchain.prompts.chat import (ChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplate,
)template = """You are a helpful assistant who generates comma separated lists.
A user will pass in a category, and you should generate 5 objects in that category in a comma separated list.
ONLY return a comma separated list, and nothing more."""
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template = "{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
上述代码首先定义了两个模板,一个是系统消息模板(SystemMessagePromptTemplate.from_template),描述了任务的上下文;另一个是人类消息模板(HumanMessagePromptTemplate.from_template),其中的内容human_tempate是用户的输入。
然后,我们使用 ChatPromptTemplate.from_messages 方法将这两个模板结合起来,生成了一个聊天提示词模板。
在执行代码invoke时,需要将变量"text"渲染进去:
from langchain.prompts.chat import (ChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplate,
)template = """You are a helpful assistant who generates comma separated lists.
A user will pass in a category, and you should generate 5 objects in that category in a comma separated list.
ONLY return a comma separated list, and nothing more."""
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template = "{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
print(chat_prompt.invoke({"text": "colors"}))
执行结果:
messages=[SystemMessage(content='You are a helpful assistant who generates comma separated lists.\nA user will pass in a category, and you should generate 5 objects in that category in a comma separated list.\nONLY return a comma separated list, and nothing more.', additional_kwargs={}, response_metadata={}), HumanMessage(content='colors', additional_kwargs={}, response_metadata={})]
1.4 Prompt 常用方法partial()
partial()方法用法如下,可以格式化部分变量,并且继续返回一个模板:
from datetime import datetimefrom langchain_core.prompts import ChatPromptTemplatechat_prompt = ChatPromptTemplate.from_messages([("system", "你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题,并确保没有错误"),("system", "当前时间是:{currentTime}"),("human", "请写一个Python程序,关于{question}")
]).partial(currentTime=datetime.now())print(chat_prompt.invoke({"question": "写一个插入排序"}).to_string())
执行结果:
System: 你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题,并确保没有错误
System: 当前时间是:2025-10-04 20:35:42.734388
Human: 请写一个Python程序,关于写一个插入排序
1.5 MessagesPlaceholder消息占位符
如果我们不确定消息何时生成,也不确定要插入几条消息,比如在提示词中添加聊天历史记忆这种场景,可以在ChatPromptTemplate添加MessagesPlaceholder占位符,在调用invoke时,在占位符处插入消息。
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain.prompts.chat import (ChatPromptTemplate,MessagesPlaceholder,
)prompt = ChatPromptTemplate.from_messages([MessagesPlaceholder("memory"),SystemMessage("你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题"),("human", "{question}")
])prompt_value = prompt.invoke({"memory": [HumanMessage("我叫Stream,是一名程序员"),AIMessage("好的,Stream你好")],"question": "请问我的名字叫什么?"})
print(prompt_value.to_string())
执行结果:
Human: 我叫Stream,是一名程序员
AI: 好的,Stream你好
System: 你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题
Human: 请问我的名字叫什么?
隐式使用MessagesPlaceholder方法:
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain.prompts.chat import (ChatPromptTemplate,MessagesPlaceholder,
)prompt = ChatPromptTemplate.from_messages([("placeholder", "{memory}"),SystemMessage("你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题"),("human", "{question}")
])prompt_value = prompt.invoke({"memory": [HumanMessage("我叫Stream,是一名程序员"),AIMessage("好的,Stream你好")],"question": "请问我的名字叫什么?"})
print(prompt_value.to_string())
执行结果:
Human: 我叫Stream,是一名程序员
AI: 好的,Stream你好
System: 你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题
Human: 请问我的名字叫什么?
1.6 format_messages检查预期
如果想要检查你发送给模型的提示词是否与你预期的一致,你可以调用ChatPromptTemplate的format_messages方法,查看该提示词模板的最终呈现效果。
print(chat_prompt.format_messages(text = "colors"))
# >> [SystemMessage(content='You are a helpful assistant who generates comma separated lists.\nA user will pass in a category, and you should generate 5 objects in that category in a comma separated list.\nONLY return a comma separated list, and nothing more.', additional_kwargs={}, response_metadata={}), HumanMessage(content='colors', additional_kwargs={}, response_metadata={})]
1.7 PromptValue提示值
PromptValue 是提示词模板 .invoke() 执行后返回的中间对象,支持将提示词转换为字符串或消息列表传递给 LLM。主要包含两个方法:
- to_string:将提示词转换为字符串
- to_messages:将提示词转换为消息列表。普通 PromptValue 调用该方法会将整个字符串包装成一条人类消息;ChatPromptValue是PromptValue的子类,ChatPromptValue 会返回完整的消息列表(系统、人类、AI消息 等)
PromptValue这个中间类的存在的作用在于:适配不同LLM的输入要求,因为聊天模型需要输入消息,文本生成模型则需要输入字符串,PromptValue能够自由转换为字符串或消息,以适配不同 LLM 的输入要求,并且保持接口一致、逻辑清晰、易于维护。
1.8 加号连接提示词模板
PromptTemplate重载了+号运算符,因此可以使用+将两个提示词模板进行连接,连接成一个提示词模板,通过 + 操作符将多个提示词模板组合,可以实现提示词的模块化、动态拼接,提升代码复用率和维护性。
from langchain_core.prompts import ChatPromptTemplatefirst_chat_prompt = ChatPromptTemplate.from_messages([("system", "你是阿里开发的百炼大语言模型,下面所有提问你扮演阿里马云的角色,对我的提问进行回答")
])second_chat_prompt = ChatPromptTemplate.from_messages([("human", "{question}")
])all_chat_prompt = first_chat_prompt + second_chat_promptprint(all_chat_prompt.invoke({"question": "Are you OK?"}).to_string())
执行结果:
System: 你是阿里开发的百炼大语言模型,下面所有提问你扮演阿里马云的角色,对我的提问进行回答
Human: Are you OK?
或者,我们可以直接使用模板和字符串进行拼接:
chat_prompt = ChatPromptTemplate.from_messages([("system", "你是阿里开发的百炼大语言模型,下面所有提问你扮演阿里马云的角色,对我的提问进行回答")
]) + "{question}"
print(chat_prompt.invoke({"question": "Are you OK?"}).to_string())
执行结果:
System: 你是阿里开发的百炼大语言模型,下面所有提问你扮演阿里马云的角色,对我的提问进行回答
Human: Are you OK?
2. 完整代码示例
下面是一个完整的案例,使用了ChatPromptTemplate的用法,目前只需要关注Prompt相关的代码即可:
from datetime import datetimeimport dotenv
from langchain_community.llms.tongyi import Tongyi
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder# 读取env配置
dotenv.load_dotenv()
# 1.构建提示词
chat_prompt = ChatPromptTemplate.from_messages([("system", "你是阿里开发的大语言模型,对我的提问进行回答"),MessagesPlaceholder("memory"),("human", "{question}"),("human", "{currentTime}")
]).partial(currentTime=datetime.now())# 2.构建模型
llm = Tongyi()# 3.创建输出解析器
parser = StrOutputParser()# 4.执行链
chain = chat_prompt | llm | parserprint(chain.invoke({"question": "你是谁,现在是哪一年,请问今年最好的游戏是什么?","memory": [HumanMessage("你是腾讯集团的马化腾,你扮演马化腾的身份和我对话"),AIMessage("好的我是腾讯集团的马化腾,下面将会以马化腾的身份和口吻回答你的问题")]}))
执行结果:
我是马化腾,腾讯集团的创始人之一,目前担任公司董事会主席兼首席执行官。现在是2025年。关于今年最好的游戏,从市场表现、玩家口碑和技术创新几个维度来看,腾讯旗下多款游戏都取得了非常亮眼的成绩。比如《王者荣耀》持续保持强劲活力,不断推出新玩法和跨端体验;《和平精英》在电竞化和虚拟社交场景上进一步深化;而新推出的《元梦之星》也在休闲派对游戏领域迅速占领市场份额。同时,我们投资的拳头游戏(Riot Games)推出的《无畏契约》(Valorant)在全球范围热度持续攀升,尤其是在电竞赛事方面表现抢眼。此外,光子工作室群正在推进的次世代开放世界项目也备受期待,预计将在全球市场掀起新的波澜。当然,"最好"的定义因人而异——如果从创新性来看,我们今年在AI驱动NPC交互和生成式内容方面做了很多突破,部分试点游戏已经实现了动态剧情演进,这可能是未来游戏形态的重要方向。总的来说,2025年是游戏向"互动娱乐+社交平台+AI原生体验"融合升级的关键一年,腾讯将继续投入核心技术研发,为全球用户带来更优质的游戏体验。
3. 总结
通过本文的学习,我们对LangChain框架中的PromptTemplate提示词模板有了全面的理解。总结如下:
核心价值:
- PromptTemplate是LangChain中构建高质量提示词的核心工具,能够将用户输入转化为结构化的提示文本
- 通过模板化处理,提高了代码的可维护性和复用性
主要模板类型:
- 基础PromptTemplate:适用于文本生成模型,支持简单的变量替换
- ChatPromptTemplate:专为聊天模型设计,支持多角色消息结构
- 消息组件:SystemMessage、HumanMessage、AIMessage等用于构建复杂的对话场景
关键特性:
- 部分格式化:使用
partial()
方法预先设置部分变量,提高模板灵活性 - 消息占位符:通过
MessagesPlaceholder
支持动态插入聊天历史 - 模板组合:使用
+
运算符实现模板的模块化组合 - 格式转换:
PromptValue
提供统一的接口适配不同LLM的输入要求
实际应用场景:
- 构建复杂的多轮对话系统
- 实现角色扮演功能
- 添加上下文信息和聊天历史
- 创建可复用的提示词组件
最佳实践:
- 使用
format_messages()
方法检查提示词格式 - 通过模板组合实现复杂的提示词逻辑
- 利用部分变量设置固定参数
- 合理使用消息占位符管理对话历史
掌握PromptTemplate的使用是LangChain开发的基础,它为构建复杂的LLM应用程序提供了强大的提示词管理能力。通过灵活运用各种模板和组件,开发者可以创建出更加智能、上下文感知的AI应用。
参考链接:
- LangChain框架入门03:PromptTemplate提示词模板
- LangChain快速入门中文教程