Deep Read

LangChain - 提示模板

 

为什么需要提示模板

直接给模型写死一段提示词有两个问题:① 提示词固定,无法根据不同输入灵活变化;② 复制粘贴拼字符串,难以复用和维护。

提示模板(Prompt Template) 就是带 {变量} 占位符的提示字符串。它接收原始用户输入,把变量填进去,生成一段「准备好发给模型」的提示词。好处是:清晰可读、可复用、易维护、参数化生成。

四种常见模板

模板适用场景
PromptTemplate单条字符串提示,最基础
ChatPromptTemplate多角色对话提示(system / human / ai),聊天模型首选
FewShotPromptTemplate给几个示例「教」模型怎么答
部分填充 partial先固定一部分变量,其余后续再填(不是独立模板,是通用能力)

一、PromptTemplate

最基础的字符串模板:一段含 {变量} 的文本,填充后得到完整提示词。

1. 两种用法对比

模板本身只负责「把变量填进字符串」。填好之后既可以手动调用模型,也可以用 LCEL 管道串起来。

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from models import DEEPSEEK_URL, DEEPSEEK_V4_PRO

load_dotenv()
llm = ChatOpenAI(
    api_key=os.getenv("MY_DEEPSEEK_API_KEY"),
    base_url=DEEPSEEK_URL,
    model=DEEPSEEK_V4_PRO,
)

# 创建模板:{text} 是占位符
template = PromptTemplate.from_template("你是一名专业的程序员,请描述这个概念:{text}")

# 用法 A:LCEL 管道(推荐)—— 模板 | 模型 | 输出解析器
chain = template | llm | StrOutputParser()
print(chain.invoke({"text": "递归算法"}))

# 用法 B:手动 format —— 先把模板渲染成普通字符串,再自己喂给模型
text_prompt = template.format(text="递归算法")   # 得到一段填好变量的字符串
print(llm.invoke(text_prompt).content)

format() 的作用就是把模板里的 {变量} 替换成真实值,返回一个普通字符串——常用来打印检查最终发给模型的内容。

2. 多变量

模板里可以有多个占位符,format 时按关键字一一传入即可。

prompt = PromptTemplate.from_template("请把下面的内容翻译成 {language}:\n\n{text}")
print(prompt.format(language="英文", text="你好世界"))

3. 部分填充 partial

先固定一部分变量(比如角色设定),之后只需传剩下的,适合复用同一套设定。

prompt = PromptTemplate.from_template("{role},请回答:{question}")

# 先预填 role,得到一个新的模板
assistant = prompt.partial(role="你是一位专业的直播运营助手")

# 之后只需传 question
print(assistant.format(question="如何提高观众停留时长?"))

4. 关键点速记

概念说明
template{变量} 占位符的字符串
input_variables变量名列表(用 from_template 创建时可自动推断,无需手写)
.format(**kwargs)填充变量,返回普通字符串
.partial(**kwargs)预填部分变量,返回新模板
prompt | llm | parserLCEL 管道:模板 → 模型 → 输出解析器

PromptTemplate 处理的是单条字符串提示;如果是多角色的对话模型,用 ChatPromptTemplate 更合适。


二、ChatPromptTemplate

聊天模型的输入不是一段字符串,而是一个带角色的消息列表(system / human / ai)。ChatPromptTemplate 就是用来生成这种消息列表的模板。

1. 三种创建方式

import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from models import DEEPSEEK_URL, DEEPSEEK_V4_PRO

llm = ChatOpenAI(
    api_key=os.getenv("MY_DEEPSEEK_API_KEY"),
    base_url=DEEPSEEK_URL,
    model=DEEPSEEK_V4_PRO,
)

# 方式 1:多条消息,带 system 角色(最常用)
template = ChatPromptTemplate.from_messages([
    ("system", "你是一名专业的翻译助手"),
    ("human", "请将以下内容翻译成英文:{text}"),
])

# 方式 2:单条 human 消息
# template = ChatPromptTemplate.from_messages([("human", "请将以下内容翻译成英文:{text}")])

# 方式 3:from_template,等价于只有一条 human 消息
# template = ChatPromptTemplate.from_template("请将以下内容翻译成英文:{text}")

message = template.invoke({"text": "我是程序员"})   # 渲染成消息列表
aimessage = llm.invoke(message)                      # 调用模型,返回 AI 回复
print(aimessage.content)

2. 消息列表的写法

from_messages 接收一个列表,列表里每个元素是一个 (角色, 内容) 元组,每个元组就是一条消息:

[("system", "你是一名专业的程序员"), ("human", "{input}")]
  • 第一个元素:角色,固定字符串 "system" / "human" / "ai""user""assistant" 也兼容)。
  • 第二个元素:消息内容,可以包含 {变量名} 占位符。

也可以用 SystemMessagePromptTemplate / HumanMessagePromptTemplate / AIMessagePromptTemplate 这类对象来写每条消息,效果和上面的元组写法一样,元组写法更简洁。


三、FewShotPromptTemplate

少样本提示:先给模型几个示例(examples),让它学会输出的格式和风格,再回答真正的问题。适合「靠规则说不清、给几个例子一看就懂」的任务。

1. 组成

参数作用
examples示例列表,每个示例是一个 dict
example_prompt单个示例怎么渲染(一个 PromptTemplate
prefix示例前的引导语(角色、任务说明)
suffix示例后的正式提问,含待填变量
input_variablessuffix 中的变量名列表

最终提示词 = prefix + 所有示例渲染结果 + suffix,拼成一整段发给模型。

2. 基本用法

import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from models import DEEPSEEK_URL, DEEPSEEK_V4_PRO

llm = ChatOpenAI(
    api_key=os.getenv("MY_DEEPSEEK_API_KEY"),
    base_url=DEEPSEEK_URL,
    model=DEEPSEEK_V4_PRO,
)

# 示例:每个都是一个 dict
examples = [
    {"input": "2+2", "output": "4", "description": "加法运算"},
    {"input": "5-2", "output": "3", "description": "减法运算"},
]

# 单个示例如何渲染(占位符要和 examples 的键对应)
example_prompt = PromptTemplate.from_template(
    "算式:{input} 值:{output} 类型:{description}"
)

prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="你是一个数学专家,能准确说出算式的类型。",
    suffix="现在给你算式:{input},值:{output},告诉我类型:",
    input_variables=["input", "output"],
)

# 先打印出来检查最终提示词长什么样
print(prompt.format(input="2*5", output="10"))

# 再发给模型
print(llm.invoke(prompt.format(input="2*5", output="10")).content)  # 乘法运算

3. 要点

  • prompt.format(...) 可以把拼好的完整提示词打印出来,方便检查。
  • 示例 dict 的键,必须和 example_prompt 模板里的占位符一致。
  • 多角色对话场景用 FewShotChatMessagePromptTemplate:把示例渲染成消息列表,配合 ChatPromptTemplate 使用。