LangChain框架入门03:PromptTemplate 提示词模板
在上一期文章中,我们已经完成了 LangChain 的基本环境搭建并成功运行了一个基础示例程序。本篇将继续深入介绍LangChain 的核心模块之一 :PromptTemplate(提示词模板)。
在与大语言模型交互时,通常不会直接将用户的原始输入直接传递给大模型,而是会先进行一系列包装、组织和格式化操作。这样做的目的是:更清晰地表达用户意图,更好地利用模型能力。
这套结构化的提示词构建方式,就是 LangChain 中的 提示词模板(PromptTemplate)。对于 LLM 应用来说,好的提示词就是成功的一半。本文将深入讲解提示词模板的使用方法与技巧。
一、提示词模板分类
LangChain 提供了多种不同的提示词模板,下面介绍几种常用的提示词模板:
PromptTemplate:文本生成模型提示词模板,用字符串拼接变量生成提示词
ChatPromptTemplate:聊天模型提示词模板,适用于如 gpt-3.5-turbo、gpt-4 等聊天模型
HumanMessagePromptTemplate:人类消息提示词模板
SystemMessagePromptTemplate:系统消息提示词模板
FewShotPromptTemplate:少量示例提示词模板,自动拼接多个示例到提示词中,例:1+1=2,2+2=4,让大模型去计算5+5等于多少。
二、提示词模板用法
2.1 PromptTemplate文本提示词模板
PromptTemplate 针对文本生成模型的提示词模板,也是LangChain提供的最基础的模板,通过格式化字符串生成提示词,在执行invoke时将变量格式化到提示词模板中,示例如下:
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate.from_template("你是一个专业的律师,请你回答我提出的法律问题,并给出法律条文依据,我的问题是:{question}")
prompt_value = prompt.invoke({"question": "婚姻法是在哪一年颁布的?"})
print(prompt_value)
执行结果:
text='你是一个专业的律师,请你回答我提出的法律问题,并给出法律条文依据,我的问题是:婚姻法是在哪一年颁布的?'
2.2 ChatPromptTemplate聊天消息提示词模板
ChatPromptTemplate 是专为聊天模型(如 gpt-3.5-turbo、gpt-4 等)设计的提示词模板,它支持构造多轮对话的消息结构,每条消息可指定角色(如系统、用户、AI)。
代码示例如下,提示词模板中包含两条消息,第一条是系统消息,无需做提示词渲染,第二条是人类消息,在执行invoke时,需要把变量question渲染进去。
from langchain_core.prompts import ChatPromptTemplate
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题,并确保没有错误"),
("human", "请写一个Python程序,关于{question}")
])
print(chat_prompt.invoke({"question": "冒泡排序"}))
执行结果:
messages=[SystemMessage(content='你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题'), HumanMessage(content='请写一个Python程序,关于冒泡排序')]
2.3 Prompt三个常用方法区别
上述的代码示例中,我们使用了invoke方法,除了invoke方法能够格式化提示词模板,format()和partial()方法也可以做到,以下是它们的作用:
format:格式化提示词模板为字符串
partial:格式化提示词模板为一个新的提示词模板,可以继续进行格式化
invoke:格式化提示词模板为PromptValue
format() 方法用法如下,将 question 参数格式化到提示词模板中,返回一个字符串:
from langchain_core.prompts import ChatPromptTemplate
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题,并确保没有错误"),
("human", "请写一个Python程序,关于{question}")
])
print(chat_prompt.format(question="冒泡排序"))
执行结果:
System: 你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题,并确保没有错误
Human: 请写一个Python程序,关于冒泡排序
partial()方法用法如下,可以格式化部分变量,并且继续返回一个模板
from datetime import datetime
from langchain_core.prompts import ChatPromptTemplate
chat_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-07-19 09:37:38.084382
Human: 请写一个Python程序,关于写一个插入排序
2.4 MessagesPlaceholder消息占位符
如果我们不确定消息何时生成,也不确定要插入几条消息,比如在提示词中添加聊天历史记忆这种场景,可以在ChatPromptTemplate添加MessagesPlaceholder占位符,在调用invoke时,在占位符处插入消息。
prompt = ChatPromptTemplate.from_messages([
MessagesPlaceholder("memory"),
SystemMessage("你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题"),
("human", "{question}")
])
prompt_value = prompt.invoke({"memory": [HumanMessage("我的名字叫大志,是一名程序员"),
AIMessage("好的,大志你好")],
"question": "请问我的名字叫什么?"})
print(prompt_value.to_string())
执行结果:
Human: 我的名字叫大志,是一名程序员
AI: 好的,大志你好
System: 你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题
Human: 请问我的名字叫什么?
隐式使用MessagesPlaceholder方法
prompt = ChatPromptTemplate.from_messages([
("placeholder", "{memory}"),
SystemMessage("你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题"),
("human", "{question}")
])
prompt_value = prompt.invoke({"memory": [HumanMessage("我的名字叫大志,是一名程序员"),
AIMessage("好的,大志你好")],
"question": "请问我的名字叫什么?"})
print(prompt_value.to_string())
执行结果:
Human: 我的名字叫大志,是一名程序员
AI: 好的,大志你好
System: 你是一个资深的Python应用开发工程师,请认真回答我提出的Python相关的问题
Human: 请问我的名字叫什么?
2.5 PromptValue提示值
PromptValue 是提示词模板 .invoke() 执行后返回的中间对象,支持将提示词转换为字符串或消息列表传递给 LLM。主要包含两个方法:
to_string:将提示词转换为字符串
to_messages:将提示词转换为消息列表。普通 PromptValue 调用该方法会将整个字符串包装成一条人类消息;ChatPromptValue是PromptValue的子类,ChatPromptValue 会返回完整的消息列表(系统、人类、AI消息 等)
PromptValue这个中间类的存在的作用在于:适配不同LLM的输入要求,因为聊天模型需要输入消息,文本生成模型则需要输入字符串,PromptValue能够自由转换为字符串或消息,以适配不同 LLM 的输入要求,并且保持接口一致、逻辑清晰、易于维护。
2.6 加号连接提示词模板
PromptTemplate重载了+号运算符,因此可以使用+将两个提示词模板进行连接,连接成一个提示词模板,通过 + 操作符将多个提示词模板组合,可以实现提示词的模块化、动态拼接,提升代码复用率和维护性。
from langchain_core.prompts import ChatPromptTemplate
first_chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是OpenAI开发的大语言模型,下面所有提问你扮演小米雷军的角色,对我的提问进行回答")
])
second_chat_prompt = ChatPromptTemplate.from_messages([
("human", "{question}")
])
all_chat_prompt = first_chat_prompt + second_chat_prompt
print(all_chat_prompt.invoke({"question": "Are you OK?"}).to_string())
执行结果:
System: 你是OpenAI开发的大语言模型,下面所有提问你扮演小米雷军的角色,对我的提问进行回答
Human: Are you OK?
或者直接使用模板和字符串进行连接
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是OpenAI开发的大语言模型,下面所有提问你扮演小米雷军的角色,对我的提问进行回答")
]) + "{question}"
print(chat_prompt.invoke({"question": "Are you OK?"}).to_string())
执行结果:
System: 你是OpenAI开发的大语言模型,下面所有提问你扮演小米雷军的角色,对我的提问进行回答
Human: Are you OK?
三、完整示例
下面是一个完整的案例,使用了ChatPromptTemplate的用法,目前只需要关注Prompt相关的代码即可,其他相关代码后续文章会展开讲解。
from datetime import datetime
import dotenv
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
# 读取env配置
dotenv.load_dotenv()
# 1.构建提示词
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是OpenAI开发的大语言模型,对我的提问进行回答"),
MessagesPlaceholder("memory"),
("human", "{question}"),
("human", "{currentTime}")
]).partial(currentTime=datetime.now())
# 2.构建GPT-3.5模型
llm = ChatOpenAI(model="gpt-3.5-turbo")
# 3.创建输出解析器
parser = StrOutputParser()
# 4.执行链
chain = chat_prompt | llm | parser
print(chain.invoke({"question": "你是谁,现在是哪一年,请问今年最好的手机品牌是什么?",
"memory": [HumanMessage("你是小米公司的雷军,你扮演雷军的身份和我对话"),
AIMessage("好的我是小米公司的雷军,下面将会以雷军的身份和口吻回答你的问题")]}))
执行结果如下,是不是很有雷军内味?
你好,我是雷军。现在是2025年7月19日,感谢你对小米的关注!
至于今年最好的手机品牌,其实这个问题没有固定答案。每个品牌都有自己的优势和特点。在我看来,作为小米的创始人,我们的小米系列无论是在技术创新、性价比还是用户体验方面都走在行业的前沿。当然,苹果、三星等品牌也在不断推陈出新,各有各的魅力。
从整体来看,2025年5G、AI、影像技术、屏幕表现等方面仍然是手机的核心竞争力。小米在这些领域持续投入,尤其是在AI相机和超快充电技术上,我们的创新和突破都得到了不少用户的认可。
你觉得现在最注重手机的哪个方面?
四、总结
本文介绍了用来构建文本生成模型的提示词模板 PromptTemplate 、 构建对话模型的提示词模板 ChatPromptTemplate,在ChatPromptTemplate中还可以使用MessagesPlaceholder 占位符灵活的插入动态信息。
还介绍了PromptTemplate类中三种方法的作用 invoke、format、partial ,最后介绍了用+号连接多个PromptTemplate。
提示词模板是LangChain 中非常核心的模块,它可以让AI能够更加清晰理解我们的意图,通过提示词模板的复用、拼接,能大大简化使用LLM的工作量,通过本文,相信你应该已经掌握了如何使用提示词模板,后续将继续深入介绍LangChain的核心模块和高级用法,敬请期待。
LangChain框架入门03:PromptTemplate 提示词模板的更多相关文章
- Semantic Kernel 入门系列:🥑突破提示词的限制
无尽的上下文 LLM的语言理解和掌握能力在知识内容的解读和总结方面提供了强大的能力. 但是由于训练数据本身来自于公共领域,也就注定了无法在一些小众或者私有的领域能够足够的好的应答. 因此如何给LLM ...
- 教程:Visual Studio 中的 Django Web 框架入门
教程:Visual Studio 中的 Django Web 框架入门 Django 是高级 Python 框架,用于快速.安全及可扩展的 Web 开发. 本教程将在 Visual Studio 提供 ...
- JavaWeb框架_Struts2_(一)----->Struts2 框架入门
1. 框架入门 2.1 Struts2简介 (1). Struts2是一种基于MVC模式的的轻量级Web开发框架. MVC模式:MVC全名是Model View Controller,是模型(mo ...
- Newbe.Claptrap 框架入门,第一步 —— 开发环境准备
Newbe.Claptrap 框架依托于一些关键性的基础组件和一些可选的辅助组件.本篇我们来介绍一下如何准备一个开发环境. Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架.如 ...
- Newbe.Claptrap 框架入门,第二步 —— 创建项目
接上一篇 Newbe.Claptrap 框架入门,第一步 -- 开发环境准备 ,我们继续了解如何创建一个 Newbe.Claptrap 项目. Newbe.Claptrap 是一个用于轻松应对并发问题 ...
- CPF 入门教程 - 设计器和模板库的使用(五)
CPF netcore跨平台UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) CPF 入门教程 - 绘图(四) CPF ...
- 【原创】NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战
概述 本文演示的是一个Android客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo. 当前由于NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能. ...
- CodeIgniter框架入门教程——第一课 Hello World!
本文转载自:http://www.softeng.cn/?p=45 今天开始,我将在这里连载由我自己编写的<CodeIgniter框架入门教程>,首先,这篇教程的读着应该是有PHP基础的编 ...
- Spring框架入门
技术分析之什么是Spring框架 1. Spring框架的概述 * Spring是一个开源框架 * Spring是于2003 年兴起的一个轻量级的Java开发 ...
- ThinkJS框架入门详细教程(二)新手入门项目
一.准备工作 参考前一篇:ThinkJS框架入门详细教程(一)开发环境 安装thinkJS命令 npm install -g think-cli 监测是否安装成功 thinkjs -v 二.创建项目 ...
随机推荐
- 哨兵线性搜索算法浅析与Python,C#实践Demo
如题: 在数组A[]中搜索给定值foundNum,其中length是A[]的长度 常规线性搜索 1.令索引i初始值为0,按次序依次赋值到n-1; (a)如果A[i]==foundNum,返回当前i; ...
- 经典webshell流量特征
开门见山,不说废话 判断条件 是否符合通信的特征 请求加密的数据和响应包加密的类型一致 是否一直向同一个url路径发送大量符合特征的请求,并且具有同样加密的响应包 一 .蚁剑 特征为带有以下的特殊字段 ...
- Python中的cls变量
技术背景 在Python的类型设计中,有时候会遇到一个cls参数.其实cls参数就是一个约定俗成的名称,用其他的名字也能正常运行但不建议这么用.它的作用类似于实例方法中的self参数,代表的是类本身, ...
- python C3算法
Python MRO C3算法是python当中计算类继承顺序的一个算法,从python2.3以后就一直使用此算法了. c3 linearization算法称为c3线性化算法 C3算法原理 首先定义几 ...
- Python字符串进化史:从青涩到成熟的蜕变
Python字符串进化史:从青涩到成熟的蜕变 Python 2.x 的字符串世界 在 Python 2.x 的时代,字符串处理已经是编程中的基础操作,但与现在相比,有着不少差异.在 Python 2. ...
- ceph部署mimic版本集群
一.简单说明 ceph mimic版本在对MDS的稳定性等方面做了大量的改进和优化,这里我们k8s集群使用ceph时需要使用cephfs,因此对MDS的稳定性方面有很高的要求,因此,我们选择ceph ...
- Coze工作流实战:一键生成像素风格视频
前言 最近像素画风的视频非常火,一个视频浏览量超过10w+的也有很多. 那么这个是怎么实现的? 其实,通过AI工作流可以比较简单地实现这样的短视频. 今天给大家分享一下,我是如何搭建工作流实现的. 欢 ...
- TreeMap实现类和SortMap接口
注意:Map与Set集合的关系非常密切.java源码就是先实现了HashMap,TreeMap,再包装了一个value都为null的Map集合实现Set集合类. 因此:TreeSet可以和TreeMa ...
- teamcity自动化部署
简介 用的自动化部署的工具,IntelliJ 家的产品teamcity对内存要求及高,我的1gb的内存就出现了"TeamCity服务器正在遇到内存不足的问题.内存清理花费了超过50%的时间. ...
- vim 的复制与黏贴
http://www.cnblogs.com/MMLoveMeMM/articles/3707287.html 转载自 用vim写代码时,经常遇到这样的场景,复制多行,然后粘贴. 这样做:1. 将光标 ...