LangChain之Prompt核心组件.2026年新版讲解,超详细

深入学习 Prompt(提示词) 组件是掌握 LangChain 的基石。在 LangChain 中,Prompt 不仅仅是一个字符串,它是一个管理输入逻辑的工厂

LangChain 的 Prompt 组件主要解决两个问题:

  1. 动态替换:把用户输入(如"苹果")填入固定的模板(如"请介绍一下{fruit}")。
  2. 角色管理:在对话模型中,区分"系统指令"、"用户提问"和"历史记录"。

下面我将分层次、全方位地讲解,并附带代码示例。不是没讲invoke()是在后面部分讲解的一定要看到最后.


第一部分:核心概念 ------ 两种主要的 Prompt 模板

LangChain 主要提供两种模板,分别对应文本补全模型(老式)聊天模型(现代,如 GPT-3.5/4, DeepSeek)

1. PromptTemplate (字符串模板)

这是最基础的,用于生成一个单纯的字符串。它不区分角色,就是把变量填进去。

  • 适用场景:简单的文本生成,或非对话模型。
  • 语法 :使用 Python 的 f-string 风格 {variable}

代码实战:

python 复制代码
from langchain_core.prompts import PromptTemplate

# 1. 定义模板
template = PromptTemplate.from_template(
    "你是一个{profession},请用{style}的语气介绍一下你自己。"
)

# 2. 填充变量 (看看它变成了什么)
formatted_prompt = template.format(profession="相声演员", style="幽默")

print("=== 生成的 Prompt 字符串 ===")
print(formatted_prompt)
# 输出: 你是一个相声演员,请用幽默的语气介绍一下你自己。
2. ChatPromptTemplate (聊天提示词模板) ------ 重点掌握

这是目前最常用的。它生成的不是一个字符串,而是一个 Message 列表 。它完美对应了 OpenAI/DeepSeek 接口中的 messages 参数。

它包含三种核心角色(Message Types):

  • System (系统):设定的"人设"或"规则"(例如:你是一个翻译官)。
  • Human (人类):用户的输入。
  • AI (模型):模型回复的内容(通常用于由你伪造历史记录,或是 Few-shot 示例)。

代码实战:

python 复制代码
from langchain_core.prompts import ChatPromptTemplate

# 方式一:使用元组 (推荐,最简洁)
chat_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的{language}翻译官。"),
    ("human", "请翻译这句话:{text}"),
])

# 方式二:使用对象类 (更严谨,适合复杂逻辑)
# from langchain_core.messages import SystemMessage, HumanMessage
# chat_template = ChatPromptTemplate.from_messages([
#     SystemMessage(content="你是一个专业的{language}翻译官。"),
#     HumanMessage(content="请翻译这句话:{text}"),
# ])

# 填充变量
messages = chat_template.format_messages(language="文言文", text="编程真好玩")

print("=== 生成的 Message 列表 ===")
for msg in messages:
    print(f"[{msg.type}]: {msg.content}")

第二部分:进阶用法 ------ 让 Prompt 更强大

掌握了基础后,实际开发中你很快会遇到以下需求:

1. MessagesPlaceholder (用于管理历史对话)

做聊天机器人时,你无法预知用户会聊多少句。你需要一个"占位符",把之前的聊天记录(History)一股脑塞进去。

场景:带记忆的聊天机器人。

代码实战:

python 复制代码
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage

chat_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个暴躁的客服。"),
    # 这是一个占位符,专门用来放历史记录列表
    MessagesPlaceholder(variable_name="history"), 
    ("human", "{user_input}")
])

# 模拟之前的对话历史
fake_history = [
    HumanMessage(content="我想退款"),
    AIMessage(content="退款?门都没有!"),
    HumanMessage(content="我要投诉你")
]

# 填充
messages = chat_template.format_messages(
    history=fake_history, # 把列表塞进去,注意这个history必须是你在MessagePlaceholder中声明的变量.
    user_input="你这什么态度?"
)

print("=== 包含历史记录的 Prompt ===")
print(messages)
2. Few-Shot Prompting (少样本提示) ------ 提分秘籍

大模型有时候听不懂指令,但看懂例子。"与其告诉它怎么做,不如演示给它看"

LangChain 提供了 FewShotChatMessagePromptTemplate 来标准化这个过程。

场景:让模型按特定格式输出,或学习特定的风格(如:反义词生成器)。

用**"教徒弟"**的比喻,把这个概念拆碎了讲.


  1. 什么是 Few-Shot?(核心逻辑)

假设你要教一个新来的徒弟(大模型)做"把现代汉语翻译成古文"。

  • Zero-Shot(零样本)

    你直接命令他:"把'你好'翻译成古文。"

    • 徒弟可能会懵:是翻译成《诗经》风?还是《水浒》风?
  • Few-Shot(少样本/举例子)

    你先给他看几个已经做好的标准答案,然后再让他做题。

    • 你:"看着啊,'早上好'翻译成'早安';'吃了吗'翻译成'用膳否'。懂了吗?好,现在把'再见'翻译一下。"
    • 徒弟瞬间秒懂:哦!原来你要这种风格的!那'再见'就是'后会有期'。

总结: Few-Shot 就是在提问之前,先伪造几段"完美的对话历史",让大模型照猫画虎,模仿你的格式和风格。


  1. 在 LangChain 中怎么实现?(三步走)

在 LangChain 中,实现 Few-Shot 就像**"做汉堡"**,我们需要分层组装。

第一步:准备"馅料" (定义例子列表)

首先,你要准备好几个标准的"输入-输出"对。这就是你要喂给模型的样本

python 复制代码
# 1. 准备样本数据 (List of Dictionaries)
examples = [
    {
        "input": "天气真好", 
        "output": "天朗气清,惠风和畅"
    },
    {
        "input": "我好饿啊", 
        "output": "饥肠辘辘,腹空如洗"
    },
    {
        "input": "这东西太贵了", 
        "output": "物贵虽奇,囊中羞涩"
    }
]

第二步:准备"模具" (定义单个例子的格式)

你要告诉 LangChain,每一个例子在对话中长什么样。

通常,一个例子就是:用户说一句 (HumanMessage) -> AI 回一句 (AIMessage)

python 复制代码
from langchain_core.prompts import ChatPromptTemplate

# 2. 定义单个例子的模版
# 这意味着:对于上面列表里的每一对数据,我都把它变成一轮对话
example_prompt = ChatPromptTemplate.from_messages([
    ("human", "{input}"),
    ("ai", "{output}")
])

第三步:组装"汉堡" (生成 FewShot 模板)

现在使用 LangChain 专门的组件 FewShotChatMessagePromptTemplate 把上面两步结合起来。

python 复制代码
from langchain_core.prompts import FewShotChatMessagePromptTemplate

# 3. 创建 Few-Shot 模版
few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt, # 使用刚才定义的模具
    examples=examples,             # 填入刚才准备的馅料
)

  1. 完整代码实战与效果演示

我们把上面三步串联起来,看看最终发给大模型的到底是什么。

python 复制代码
from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate

# --- 1. 准备数据 ---
examples = [
    {"input": "天气真好", "output": "天朗气清,惠风和畅"},
    {"input": "我好饿啊", "output": "饥肠辘辘,腹空如洗"},
]

# --- 2. 定义格式 ---
example_prompt = ChatPromptTemplate.from_messages([
    ("human", "{input}"),
    ("ai", "{output}"),
])

# --- 3. 组装 FewShot 组件 ---
few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=examples,
)

# --- 4. 组装最终的大 Prompt ---
# 结构通常是:[系统指令] -> [那是几个示例] -> [用户真正的问题]
final_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个文采飞扬的古人,请把现代白话文转化为文言文。"),
    few_shot_prompt,  # <--- 这里把示例插进去了!
    ("human", "{user_input}")
])

# --- 5. 见证奇迹 (Invoke) ---
# 假设用户输入了 "我很开心"
messages = final_prompt.invoke({"user_input": "我很开心"})

# 打印出来看看,LangChain 到底背着我们生成了什么?
print("=== 发给模型的实际消息列表 ===")
for msg in messages.to_messages():
    print(f"[{msg.type}]: {msg.content}")

运行结果(非常重要,请仔细看):

你会发现,虽然你只输入了一句话,但 LangChain 帮你生成了 5 条消息发给模型:

text 复制代码
=== 发给模型的实际消息列表 ===
[system]: 你是一个文采飞扬的古人,请把现代白话文转化为文言文。
[human]: 天气真好             <-- 示例 1 开始
[ai]: 天朗气清,惠风和畅      <-- 示例 1 结束
[human]: 我好饿啊             <-- 示例 2 开始
[ai]: 饥肠辘辘,腹空如洗      <-- 示例 2 结束
[human]: 我很开心             <-- 这才是用户刚才真正输入的!

原理解析:

大模型看到这个列表时,它会以为前面两轮对话是真的发生过的。它会想:"哦,原来这个用户的习惯是这样说话的,那我也要保持队形。"

于是,针对最后一句"我很开心",它更有可能回答:"心旷神怡,喜不自胜",而不是简单的"我很愉快"。


  1. 为什么要这么麻烦?直接写在 System 里不行吗?

你可能会问:我直接在 System 里写"举个例子:天气好->天朗气清",不行吗?

可以,但是 Few-Shot 组件有两个巨大的优势:

  1. 防止 Token 溢出(动态选择)

    假设你有 100 个例子(总共有 5万字),你不能全塞进 Prompt 里,因为会把额度用光。

    LangChain 的 FewShot 组件支持**"示例选择器 (ExampleSelector)"**。它可以根据用户输入的问题,只挑选最相关的 3 个例子塞进去!

    • 用户问数学题 -> 挑数学例子
    • 用户问历史题 -> 挑历史例子
    • (这是进阶功能,目前先了解即可)
  2. 格式更标准

    相比于把例子像写作文一样堆在 System 里,使用 Human/AI 的消息对格式,能让模型更清晰地理解**"哪句是输入,哪句是输出"**。

  • Few-Shot 就是**"照猫画虎"**。
  • 它通过伪造历史对话记录来教模型做事。
  • 在 LangChain 中,你只需要准备好列表 (List)格式 (Prompt) ,剩下的组装工作由 FewShotChatMessagePromptTemplate 自动完成。

第四部分:综合实战 ------ 结合 API 调用,后面会详细介绍最核心的'链(Chain)'

光生成 Prompt 没用,最后我们要把它传给 API(LLM)。我们用 LCEL (LangChain Expression Language) 也就是 | 来串联。

假设你已经配置好了 llm

完整流程代码:

python 复制代码
import os
# 假设你已经定义了 llm
from langchain_openai import ChatOpenAI
# 替换为你的 key 和 base_url
llm = ChatOpenAI(
    model="deepseek-ai/DeepSeek-V3", 
    openai_api_key="sk-xxxx", 
    openai_api_base="https://api.siliconflow.cn/v1"
)

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser # 输出解析器后面讲解

# 1. 定义 Prompt (带人设)
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个资深的Python代码评审专家。请指出代码中的错误并优化它。"),
    ("human", "{code_snippet}")
])

# 2. 定义解析器 (直接拿字符串,不要 Message 对象)
parser = StrOutputParser()

# 3. 组成链:Prompt -> LLM -> Parser
chain = prompt | llm | parser

# 4. 准备一段烂代码
bad_code = """
def add(a, b):
    print(a+b)
"""

# 5. 运行
print("Waiting for response...")
response = chain.invoke({"code_snippet": bad_code}) # invoke一定要看到后面!!!

print("\n=== AI 回复 ===")
print(response)

前面的讲解中,为了看清楚 Prompt 到底生成了什么"原始数据"(即 List of Messages),特意使用了 format_messages。但在实际的 LangChain LCEL (LangChain Expression Language) 开发中,99% 的情况我们都会使用 invoke

下面详细讲解 invoke 在 Prompt 组件中的用法,并做一个深度的对比。


1. 为什么现在都用 invoke

LangChain 引入了一套新标准,叫 Runnable Protocol(可运行协议)

在这个协议下,所有的组件 (Prompt、LLM、OutputParser、Chain)都实现了同一个方法:invokeinvoke的汉语意思是调用,非常见名之意🥳🥳🥳

这样做的好处是:接口统一

  • 你不需要记 prompt.format()
  • 也不需要记 llm.predict()
  • 更不需要记 parser.parse()
  • 统统都用 invoke()

2. Prompt 组件使用 invoke 的实战

让我们把之前的例子改写成 invoke 版本。

代码示例:
python 复制代码
from langchain_core.prompts import ChatPromptTemplate

# 1. 定义模版
template = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的{role}。"),
    ("human", "请解释一下:{concept}")
])

# ==========================================
# 方式 A: 旧方法 (便于调试,看原始数据)
# ==========================================
messages = template.format_messages(role="数学老师", concept="微积分")
print("=== A. format_messages 的结果 (List) ===")
print(type(messages)) 
# 输出: <class 'list'>
print(messages) 
# 输出: [SystemMessage(...), HumanMessage(...)]


# ==========================================
# 方式 B: 新方法 (标准用法,用于 LCEL)
# ==========================================
prompt_value = template.invoke({"role": "数学老师", "concept": "微积分"})

print("\n=== B. invoke 的结果 (PromptValue) ===")
print(type(prompt_value)) 
# 输出: <class 'langchain_core.prompt_values.ChatPromptValue'> (注意这里!)

print(prompt_value)
# 输出: messages=[SystemMessage(...), HumanMessage(...)]
关键区别点(敲黑板):
  • format_messages 返回的是一个 Python List(列表)。
  • invoke 返回的是一个 ChatPromptValue 对象。

ChatPromptValue 是一个包装器,它既包含消息列表,也包含生成后的字符串。它是连接 Prompt 和 LLM 的通用桥梁。


3. 深度对比:format vs invoke

特性 format / format_messages invoke (推荐)
所属体系 旧版 / 字符串处理逻辑 LCEL (LangChain 表达式语言)
输入参数 关键字参数 (a=1, b=2) 字典 {"a": 1, "b": 2}
返回值 StringList[Message] PromptValue 对象 (更高级的包装)
主要用途 调试 (Print出来看看对不对) 生产 (在链中传递数据)
兼容性 无法直接被 ` ` 管道符连接

4. 为什么 invoke 在链(Chain)中如此重要?

如果你不使用 invoke,你就无法使用 LangChain 最强大的 管道操作符 (|)

请看下面这个对比:

如果没有 invoke (传统的、痛苦的写法):
python 复制代码
# 你需要手动一步步传数据
formatted_input = prompt.format_messages(role="老师", concept="数学")
response = llm.predict_messages(formatted_input)
result = parser.parse(response.content)
使用 invoke (LCEL 的优雅写法):

LangChain 会自动在内部调用 invoke

python 复制代码
# 1. 定义链
chain = prompt | llm | parser

# 2. 一键运行
# 这里你调用的 chain.invoke,其实内部自动调用了 prompt.invoke
result = chain.invoke({"role": "老师", "concept": "数学"})

先简单讲解一下链:

当你执行 chain.invoke({...}) 时,数据流是这样的:

  1. 字典 {"role":...} 传给 Prompt。
  2. Prompt 自动调用 invoke ,生成 ChatPromptValue
  3. ChatPromptValue 传给 LLM。
  4. LLM 自动调用 invoke ,生成 AIMessage
  5. AIMessage 传给 Parser。
  6. Parser 自动调用 invoke,生成最终字符串。

总结

  1. 真正写代码/构建应用时请一律使用 invoke
  2. 记忆口诀
    • Prompt 是一个 Runnable(可运行对象)。
    • 所有 Runnable 都要用 invoke 启动。
    • invoke 接收字典,返回对象。

现在你已经掌握了最核心的机制,接下来在学习 Chain(链)的时候,你会发现 invoke 无处不在!

总结 ------ 你需要记住什么?

  1. 如果你用 GPT/DeepSeek/通义千问 :请死磕 ChatPromptTemplate
  2. 结构公式System (人设) -> MessagesPlaceholder (历史) -> Human (新问题)。
  3. 调试技巧 :如果 AI 回答不符合预期,先打印 prompt.invoke(dict1).to_string() 看看你到底发给 AI 了什么内容,通常是 Prompt 拼写有问题。

这就是 LangChain Prompt 组件最核心、最实用的部分!你可以试着把上面的 Few-Shot 例子跑一下,看看效果是不是比直接问更好。

相关推荐
大好人ooo2 小时前
LLM Prompts的企业安全问题
prompt
城东米粉儿2 小时前
Kotlin suspendCancellCoroutine 笔记
android
不会敲代码12 小时前
用 LangChain 把大模型串起来:一个前端开发者的 AI 入门笔记
langchain·llm·aigc
Jomurphys2 小时前
Android 优化 - R8 混淆
android
无聊的小坏坏2 小时前
精准控制:提示词工程与结构化输出
langchain·提示词·大模型应用
summerkissyou19873 小时前
Android-Audio-MediaPlayer和AudioTrack播放区别
android·audio
独自破碎E3 小时前
BISHI69 [HNOI2008]越狱
android·java·开发语言
Rhystt3 小时前
furryCTF题解|Web方向|ezmd5、猫猫最后的复仇
android·前端·web安全·web