Skip to content

LangChain教程 - 8 LangChain提示词模板

下面介绍一下 LangChain 中的提示词模板。

8.1 消息的简写形式

首先先看一下消息的简写形式。

在上一个章节介绍 LangChain 使用 SystemMessageHumanMessageAIMessage 来创建消息。

消息还可以使用下面的方式进行简写:

python
from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage

# 初始化聊天模型
model = ChatOllama(model="qwen3:1.7b")

# 构造消息
messages = [
    ("system", "请用一句话回答"),
    ("human", "3加5等于多少?"),
    ("ai", "等于8"),
    ("human", "再加5等于多少?"),
    ("ai", "等于13"),
    ("human", "再加2等于多少?")
]

# 调用模型,通过 stream 方法提问,流式返回
response = model.stream(input = messages)
for chunk in response:
    print(chunk.content, end="", flush=True)  # end="" 避免换行,flush=True 及时刷新输出
  • 在消息列表中,使用的是二元元组,使用 systemhumanai 作为元组第一个元素,与 SystemMessageHumanMessageAIMessage 对应,后面写的是消息的内容。

8.2 提示词模板

什么是提示词模板,简单来说,提示词模板就是预先定义好的提示词结构,里面可以包含一些占位符,后续根据需要动态填充内容。

举个栗子:

python
# 创建提示词模板
prompt_template = PromptTemplate.from_template("请把:{content},翻译成{language}")

# 传递参数,生成提示词
prompt = prompt_template.format(content="今天天气怎么样?", language="英语")

# 打印提示词
print(prompt)  # 请把:今天天气怎么样?,翻译成英语
  • 首先创建模板,然后给模板传递数据,生成最终的提示词。

为什么要使用提示词模板,我直接用 f-string 拼接不也一样吗?就像这样:

python
prompt = f"请翻译成{language}{text}"

话是这么说,但在真实项目中,情况会复杂很多。使用提示词模板的好处却很多:

  • 结构化管理:当你的提示词变得越来越复杂时,直接拼接字符串会让代码变得一团糟。而使用提示词模板,可以将提示词结构和具体内容分离,更清晰地组织提示词逻辑,方便团队协作和维护;

  • 动态内容处理:提示词模板可以轻松处理动态内容,支持多个变量占位,可以设置默认值,还支持变量类型检查;

  • 复用性强:定义好的模板可以在多个地方重复使用,避免了代码冗余;

  • 易于扩展:当你需要修改提示词时,只需要修改模板本身,而不需要修改所有使用的地方。

最主要的原因是可以加入 LangChain 的执行链,Chain 链后面再讲。

8.3 PromptTemplate

PromptTemplate 是 LangChain 中最基础的提示词模板类,它允许你创建包含占位符的模板,然后动态填充内容。

PromptTemplate 主要用于“单段文本 Prompt” 的场景,不维护历史对话记录,也就是没有 system / human / ai 的角色区分。

换句话说,如果你只是给模型发送 一整段文本提示词,那 PromptTemplate 就非常适合。


下面来看看 LangChain 中 PromptTemplate 如何使用。

首先需要导入 PromptTemplate,然后就是创建模板,然后将参数传递给模板,生成最终的字符串而已:

python
from langchain_ollama import ChatOllama
from langchain.prompts import PromptTemplate

# ----提示词部分
# 创建一个简单的提示词模板
prompt_template = PromptTemplate.from_template("请把:{content},翻译成{language}")
# 使用模板生成提示词
prompt = prompt_template.format(content="今天天气如何?", language="英文")
# 得到完整提示词:提示词: 请把:今天天气如何?,翻译成英文
print("提示词:", prompt)

# ----模型部分
# 1.创建聊天模型
model = ChatOllama(model="qwen3:1.7b")

# 2.调用模型,通过 stream 方法提问,流式返回
response = model.stream(prompt)
for chunk in response:
    print(chunk.content, end="", flush=True)  # end="" 避免换行,flush=True 及时刷新输出
  • 上面的代码是在之前调用大语言模型的基础上,添加了提示词模板而已。
  • PromptTemplate 可以用于调用大语言模型或聊天模型,都可以。

但是感觉有点脱裤子放屁,直接使用字符串可能更简单,但是使用提示词模板可以加入 LangChain 的执行力链,在 LangChain 里,模板可以和模型“管道式连接”:

python
from langchain_ollama import ChatOllama
from langchain.prompts import PromptTemplate

# ----提示词部分
# 1.创建一个简单的提示词模板
prompt_template = PromptTemplate.from_template("请把:{content},翻译成{language}")

# 2.创建聊天模型
model = ChatOllama(model="qwen3:1.7b")

# 3.使用 | 组成执行链
chain = prompt_template | model

# 4.通知链条执行,直接传入参数执行
response = chain.stream({"content": "你在做什么?", "language": "英文"})
for chunk in response:
    print(chunk.content, end="", flush=True)  # end="" 避免换行,flush=True 及时刷新输出
  • 提示词模板可以加入到执行链条,字符串是不行的,后面我们会学习链条。

8.4 ChatPromptTemplate

ChatPromptTemplate 是 LangChain 中专门用于构建聊天消息的模板类,它支持多轮对话,可以包含不同角色的消息。

ChatPromptTemplate 适用于以下场景:

  • 多轮对话,需要维护对话历史
  • 聊天机器人、客服助手等交互场景
  • 当你需要明确区分系统消息、用户消息和助手消息时

1 简单示例

首先,咱们来看一个简单的 ChatPromptTemplate 示例:

python
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import ChatOllama

# 1. 创建聊天提示词模板
chat_prompt_template = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一个幽默的助手,用简洁的语言回答问题。"),
        ("human", "{question}")
    ]
)

# 2. 生成提示词
prompt = chat_prompt_template.format(question="你是谁?")
print("生成的提示词:", prompt)

# 3. 创建聊天模型
model = ChatOllama(model="qwen3:1.7b")

# 4. 调用模型
response = model.stream(prompt)
for chunk in response:
    print(chunk.content, end="", flush=True)

2 使用 MessagesPlaceholder

对于需要维护对话历史的场景,可以使用 MessagesPlaceholder 来动态注入历史对话:

python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_ollama import ChatOllama

# 1. 创建聊天提示词模板,在模板中使用MessagesPlaceholder占位符
chat_prompt_template = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一位专业的健身教练,回答要简单实用。"),
        MessagesPlaceholder("history"),
        ("human", "{question}")
    ]
)

# 2. 准备历史对话数据
history_data = [
    ("human", "我想减肥,有什么建议?"),
    ("ai", "建议控制饮食,并配合每周3次有氧运动。"),
    ("human", "我平时中午吃米饭可以吗?"),
    ("ai", "可以,但建议减少分量,多搭配蔬菜和蛋白质。")
]

# 3. 将历史数据注入模板,生成最终提示词
prompt = chat_prompt_template.invoke(
    {"history": history_data, "question": "那我晚饭应该怎么吃?"}
)

print("生成的提示词:", prompt.to_string())

# 4. 创建聊天模型
model = ChatOllama(model="qwen3:1.7b")

# 5. 调用模型
response = model.stream(prompt)
for chunk in response:
    print(chunk.content, end="", flush=True)
  • 使用 MessagesPlaceholder 可以方便地将历史对话注入到模板中,实现多轮对话的上下文管理。

8.5 format和invoke方法

上面在使用提示词模板时,使用了两种方法来生成提示词:formatinvoke

什么区别呢?

PromptTemplateChatPromptTemplate 等模板类都直接或间接继承自 BasePromptTemplateBasePromptTemplate 定义了 format() 方法, BasePromptTemplate 间接继承了 RunnableRunnable 定义了 invoke() 方法,所以来源的类是不同的。

1 format方法

format 方法是直接返回一个字符串:

python
from langchain.prompts import PromptTemplate

# 创建模板
prompt_template = PromptTemplate.from_template("请把{text}翻译成{language}")

# 使用format方法
prompt = prompt_template.format(text="你好", language="英语")
print(prompt)  # 输出:请把你好翻译成英语
  • 当你只需要一个字符串形式的提示词时,不需要将模板加入执行链时,可以使用 format() 方法,例如快速生成提示词进行测试时。

2 invoke方法

invoke 方法返回的是一个 PromptValue 对象,需要调用 to_string() 方法才能得到字符串:

python
from langchain.prompts import PromptTemplate

# 创建模板
prompt_template = PromptTemplate.from_template("请把{text}翻译成{language}")

# 使用invoke方法
prompt_value = prompt_template.invoke({"text": "你好", "language": "英语"})
prompt = prompt_value.to_string()
print(prompt)  # 输出:请把你好翻译成英语
  • 当需要将模板加入 LangChain 执行链时(只有 invoke 方法支持链式调用),需要获取 PromptValue 对象进行进一步处理,可以使用 invoke 方法。

整理一下区别:

区别formatinvoke
定义BasePromptTemplate 中定义的Runnable 中定义的
返回值字符串PromptValue 对象
参数.format(text="你好", language="英语"),参数名方式.invoke({"text": "你好", "language": "英语"}),字典形式
解析支持 {} 占位符支持 {} 占位符和 MessagesPlaceholder 结构化占位符

3 执行链中的使用

invoke 方法的一个重要优势是可以将模板加入到 LangChain 的执行链中:

python
from langchain_ollama import ChatOllama
from langchain.prompts import PromptTemplate

# 1.创建提示词模板
prompt_template = PromptTemplate.from_template("请把:{content},翻译成{language}")

# 2.创建聊天模型
model = ChatOllama(model="qwen3:1.7b")

# 3.使用 | 组成执行链(这里必须使用invoke方法)
chain = prompt_template | model

# 4.通知链条执行,直接传入参数执行
response = chain.stream({"content": "你在做什么?", "language": "英文"})
for chunk in response:
    print(chunk.content, end="", flush=True)
  • 在执行链中,LangChain 会自动调用模板的 invoke 方法来生成提示词,然后将结果传递给模型。
  • 下一章介绍执行链。

8.6 Zero-shot与Few-shot

1 什么是Zero-shot

Zero-shot 学习是指不给模型提供任何示例,直接让它完成任务。这种方法依赖于模型在预训练过程中学习到的知识和能力,适用于一些通用的、常见的任务。

例如,如果你想让模型将一段中文翻译成英文,你可以直接告诉它:"请将下面的中文翻译成英文:你好,很高兴认识你",而不需要给它任何翻译示例。

2 什么是Few-shot

Few-shot 学习是指给大模型提供少量示例(通常是几个),让它基于这些示例来理解任务要求并生成相应的输出。这种方法可以帮助模型更好地理解具体的任务格式和期望输出,尤其适用于一些复杂或特定领域的任务。

举个例子,如果你想让模型根据描述生成产品评价,你可以先给它几个示例:

  • 描述:"这个手机续航时间很长,屏幕清晰,但是价格有点贵。" 评价:"4星,续航和屏幕表现出色,但价格偏高。"
  • 描述:"这家餐厅的菜味道不错,服务也很好,环境干净整洁。" 评价:"5星,菜品美味,服务周到,环境舒适。"
  • 描述:"这个软件功能很多,但界面有点复杂,需要时间学习。"
  • 评价:"3星,功能丰富但界面不够友好,学习成本较高。"

然后模型就能根据这些示例,为新的描述生成类似格式的评价。

例如我给出描述"这款耳机音质很棒,佩戴舒适,续航也不错,就是价格稍微有点高。",让模型按照示例的形式,给出评价。

3 FewShotPromptTemplate的使用

LangChain 提供了 FewShotPromptTemplate 来实现 Few-shot 学习。

下面介绍一下如何使用它来让大模型基于示例完成回答,基于上面根据产品描述生成评价:

python
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
from langchain_ollama import ChatOllama

# 1.定义示例的格式模板
example_template = PromptTemplate.from_template(
    "描述: {description}\n评价: {review}"
)

# 2.给出示例数据(示例会自动注入到 example_template)
examples_data = [
    {
        "description": "这个手机续航时间很长,屏幕清晰,但是价格有点贵。",
        "review": "4星,续航和屏幕表现出色,但价格偏高。"
    },
    {
        "description": "这家餐厅的菜味道不错,服务也很好,环境干净整洁。",
        "review": "5星,菜品美味,服务周到,环境舒适。"
    },
    {
        "description": "这个软件功能很多,但界面有点复杂,需要时间学习。",
        "review": "3星,功能丰富但界面不够友好,学习成本较高。"
    }
]

# 3.创建 FewShotPromptTemplate,参数是重点,待会介绍一下
few_shot_template = FewShotPromptTemplate(
    example_prompt=example_template,
    examples=examples_data,
    prefix="请根据下面的示例,为产品描述生成评价:",
    suffix="描述: {product_description}",
    input_variables=["product_description"]
)

# 4.生成最终的提示词
prompt = few_shot_template.invoke(
    input={"product_description": "这款耳机音质很棒,佩戴舒适,续航也不错,就是价格稍微有点高。"}
)
print("生成的提示词:", prompt.to_string())

# 5.创建模型
model = ChatOllama(model="qwen3:1.7b")

# 6.调用模型
response = model.stream(prompt)
print("\n模型回答:")
for chunk in response:
    print(chunk.content, end="", flush=True)

首先介绍一下 FewShotPromptTemplate 的5个参数的意思:

  • example_prompt:示例数据的提示词模板,定义了每个示例的格式
  • examples:示例数据,list格式,内套字典,每个字典包含示例的键值对
  • prefix:在示例数据前输出的内容,用于说明任务要求
  • suffix:在示例数据后输出的内容,用于放置用户输入
  • input_variables:提示词中的参数列表,需要从外部注入的变量列表

执行结果:

生成的提示词: 请根据下面的示例,为产品描述生成评价:    # prefix的内容

描述: 这个手机续航时间很长,屏幕清晰,但是价格有点贵。  # 示例数据
评价: 4星,续航和屏幕表现出色,但价格偏高。

描述: 这家餐厅的菜味道不错,服务也很好,环境干净整洁。
评价: 5星,菜品美味,服务周到,环境舒适。

描述: 这个软件功能很多,但界面有点复杂,需要时间学习。
评价: 3星,功能丰富但界面不够友好,学习成本较高。

描述: 这款耳机音质很棒,佩戴舒适,续航也不错,就是价格稍微有点高。  # suffix的内容

模型回答:
评价: 4星,音质清晰,佩戴舒适,续航优秀,但价格偏高。