langchain中的提示词模板PromptTemplate、ChatPromptTemplate、格式化适配器、PromptValue

文章目录

有人问了,为什么一个简单的提示词还需要弄个模板呢?
其实不然,通过不通的模板,不但方便定义,而且有利于大模型准确的理解。

注:这篇笔记说的都是提示词相关的内容,所以有时prompt会省略掉,例如说template就表示promptTemplate。

运行机制:

1、定义模板

2、传入数据并格式化

3、输出标准化(重)

在 LangChain 等框架中,生成的不仅仅是字符串,而是一个PromptValue对象。

作用:这个对象是一个"变形金刚"。

如果传给普通模型(LLM),它调用 .to_string() 变成纯文本。

如果传给聊天模型(ChatModel),它调用 .to_messages() 变成 [HumanMessage(...)] 列表。

常见的提示词模板有哪些?

1、PromptTemplate

2、ChatPromptTemplate

3、FewShotPromptTemplate

如下表:

模板类型 核心作用 适用场景
PromptTemplate 通用字符串格式化 单次任务、简单文本生成
ChatPromptTemplate 结构化对话消息 聊天机器人、多轮对话、Agent
FewShotPromptTemplate 注入示例数据 需要给模型看例子才能做对的复杂任务

PromptTemplate

PromptTemplate示例
python 复制代码
from langchain.prompts import PromptTemplate

# 注意看模板的结尾:冒号和换行符是关键
# 我们人为制造了一个"填空题"的语境
template_str = """
你是一个专业的翻译助手。
请将以下中文翻译成英文。

中文:{input_text}
英文:"""  # <--- 关键点:在这里戛然而止,强迫 LLM 续写英文

prompt = PromptTemplate.from_template(template_str)
# 生成结果:"...英文:" -> LLM 看到后会自然地接下去写 "Hello World"

ChatPromptTemplate

ChatPromptTemplate示例

python 复制代码
from langchain.prompts import ChatPromptTemplate

# 我们不再拼接长字符串,而是定义"消息块"
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的翻译助手,负责将中文翻译成英文。"), # 设定人设/指令
    ("human", "{input_text}") # 用户输入
    # 不需要写 ("ai", ""),模型会自动在这里开始生成
])

# 生成结果:[SystemMessage(...), HumanMessage("你好")] 
# -> ChatModel 收到后知道该输出 AIMessage 了

FewShotPromptTemplate

FewShotPromptTemplate示例

python 复制代码
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain_core.prompts import PromptTemplate

# 1. 定义示例数据 (Examples)
# 这就是"少样本"的核心:我们预先准备好几组标准的"输入-输出"对
examples = [
    {
        "document": "这部电影的特效简直炸裂,视觉盛宴!但是剧情有点拖沓,结尾让人摸不着头脑。",
        "summary_json": "{\n  \"主题\": \"电影评论\",\n  \"核心观点\": \"特效好但剧情差\",\n  \"情感\": \"混合\",\n  \"评分\": 6\n}"
    },
    {
        "document": "这款手机的电池续航能力太差了,充满电只能用半天。而且充电速度也很慢,完全不推荐购买。",
        "summary_json": "{\n  \"主题\": \"电子产品评论\",\n  \"核心观点\": \"续航差,充电慢\",\n  \"情感\": \"负面\",\n  \"评分\": 2\n}"
    },
    {
        "document": "昨天的会议主要讨论了下一季度的市场预算分配问题,大家一致同意增加在数字营销方面的投入。",
        "summary_json": "{\n  \"主题\": \"会议纪要\",\n  \"核心观点\": \"增加数字营销预算\",\n  \"情感\": \"中立\",\n  \"评分\": null\n}"
    }
]

# 2. 定义示例模板 (Example Prompt)
# 告诉 LangChain 如何把上面字典里的数据拼成一个字符串
example_prompt = PromptTemplate(
    input_variables=["document", "summary_json"],
    template="文档内容:{document}\n标准摘要:{summary_json}"
)

# 3. 构建 FewShotPromptTemplate
# 这是核心类,它会自动把 examples 和 example_prompt 组合起来
prefix = """你是一个专业的数据分析师。请阅读下方的"待处理文档",并严格按照示例中的格式输出 JSON 摘要。
注意:不要输出任何多余的解释文字,只输出 JSON。

以下是几个示例:"""

suffix = """待处理文档:{input_document}
标准摘要:"""

prompt = FewShotPromptTemplate(
    examples=examples,              # 传入示例列表
    example_prompt=example_prompt,  # 传入示例的格式化模板
    prefix=prefix,                  # 头部指令
    suffix=suffix,                  # 尾部输入(包含变量 {input_document})
    input_variables=["input_document"] # 声明用户需要传入的变量
)

# ==========================================
# 4. 模拟用户输入(批量/多文档场景)
# ==========================================
user_input = """
文档 A:苹果发布了新款 Vision Pro,售价 3500 美元,虽然技术很先进,但价格让很多人望而却步。
文档 B:特斯拉的股价今天上涨了 5%,因为马斯克宣布了新的全自动驾驶测试计划。
"""

# 5. 生成最终提示词
final_prompt_value = prompt.format(input_document=user_input)

# 打印出来看看效果(模拟发送给模型前的样子)
print("------- 发送给模型的最终内容 -------")
print(final_prompt_value)

解读:

当你运行这段代码时,FewShotPromptTemplate 会自动执行以下拼接逻辑:

**1、Prefix(前缀):**先输出通用的指令("你是一个分析师...")。

**2、Examples(示例循环):**它会自动遍历 examples 列表,利用 example_prompt 把每一组示例格式化成文本,拼在指令后面。

文档内容:电影...

标准摘要:{JSON}...

文档内容:手机...

标准摘要:{JSON}...

**3、Suffix(后缀):**最后放上你的 user_input(待处理文档),并以 标准摘要: 结尾。

🚀 为什么这对"批量/多文档"很有用?

格式锁定:通过示例,模型会模仿示例中的 JSON 结构,即使你的 user_input 包含多个文档(文档 A 和 文档 B),模型也会倾向于按照示例的风格,把它们整合成一个结构化的输出。

逻辑示范:示例中展示了如何处理"混合情感"(电影评论),这教会了模型在面对复杂情况时该怎么做,而不仅仅是简单的正面/负面。

动态性:你可以随时更换 examples 列表。比如针对"医疗文档",你可以换成一组医疗相关的示例,而不需要修改核心代码逻辑。

这就是 Few-Shot 的威力:用示例代替复杂的规则说明。

ChatPromptTemplate和ChatPromptTemplate的区别
维度 LLM (续写型) 的 PromptTemplate ChatModel (交互型) 的 ChatPromptTemplate
思维模式 剧本编剧模式:我要怎么写开头,演员才会顺着我的剧本演下去? 对话管理模式:我要给系统什么规则?用户说了什么?
模板结构 单一大字符串:包含所有指令和输入。 消息列表:由 System, Human, AI 等模块组成。
关键技巧 结尾诱导:模板通常以 Answer:\n 结尾,利用模型的续写本能。 角色隔离:利用 system 角色来强行注入指令,模型会无条件服从。
如果写错 如果结尾没写好(例如以句号结尾),模型可能会自己接一句废话,或者直接停止。 如果把指令写在 human 里,模型可能会觉得这是用户在自言自语,而不是在下达命令。
baseMessage属于promptTemplate吗?

不属于。

baseMessage是数据单元

promptTemplate是模板工具

他们相互协作将消息定义的更加清楚,更加结构化。

PromptValue

提示值。实际就是发给大模型前的最后一站了。

template、model、value之间是什么关系?

如下这个例子讲的太好了:
1、PromptTemplate 是工厂,负责生产内容。
2、Model 是客户,有的客户只收现金(String),有的客户只收刷卡(List[Message])。
3、PromptValue 就是"万能支付卡"。

你拿着这张卡(PromptValue)去付款。

如果客户要现金,它就提现(to_string)。

如果客户要刷卡,它就刷卡(to_messages)。

自定义格式化转换器

场景:

主流的大模型都支持提示词转换,但是假如某个大模型不支持提示词转换怎么办,那么我们完全可以自己做一个提示词转换工具。

例如,就复用PromptValue这个类。

实现两个方法即可:
to_string()
to_messages()

1、自定义提示词模板:

python 复制代码
from typing import List, Any
from langchain_core.prompt_values import BasePromptValue
from langchain_core.messages import BaseMessage, HumanMessage, SystemMessage

# 1. 定义自定义的 PromptValue
class MyCustomPromptValue(BasePromptValue):
    # 这里定义你的数据源,比如一段文本和一个特殊的指令头
    text: str
    special_header: str = "[SPECIAL_MODE]"

    # 核心方法 A:适配"普通文本模型"
    # 当这个 PromptValue 传给一个只认字符串的模型时,会调用这个方法
    def to_string(self) -> str:
        return f"{self.special_header}\n\n{self.text}"

    # 核心方法 B:适配"聊天模型"
    # 当这个 PromptValue 传给 ChatModel 时,会调用这个方法
    def to_messages(self) -> List[BaseMessage]:
        # 这里你可以随意定义消息的结构
        # 比如:把特殊头放在 SystemMessage 里,正文放在 HumanMessage 里
        return [
            SystemMessage(content="系统已激活特殊模式。"),
            HumanMessage(content=f"{self.special_header} {self.text}")
        ]

    # (可选) 如果你需要序列化(比如保存链条),可能需要实现这个
    def __str__(self):
        return self.to_string()

2、调用并测试

python 复制代码
# 实例化你的自定义 PromptValue
my_value = MyCustomPromptValue(text="你好,世界", special_header="[DEBUG]")

# 测试变身成字符串 (给普通模型看)
print("--- 字符串格式 ---")
print(my_value.to_string())
# 输出: [DEBUG]
#       你好,世界

# 测试变身成消息 (给聊天模型看)
print("\n--- 消息格式 ---")
for msg in my_value.to_messages():
    print(f"{msg.type}: {msg.content}")
# 输出: 
# system: 系统已激活特殊模式。
# human: [DEBUG] 你好,世界
自动调用和手动调用的区别?

自动调用,不需要显示的格式化:

(1)定义模板

(2)定义调用链

python 复制代码
chain = prompt | model
model.invoke("你好")

手动调用,需要手动格式化,不需要定义调用链了,直接invoke:

(1)手动格式化

(2)不需要定义调用链

python 复制代码
prompt_value="手动格式化的内容"
model.invoke("你好")
相关推荐
qq_5470261793 小时前
LangChain 工具调用(Tool Calling)
java·大数据·langchain
AI大模型..4 小时前
数据洞察加速器:LLM Copilot 如何让 SQL 查询效率提升 50% 以上?
人工智能·langchain·llm·agent·llama
汀沿河7 小时前
6 LangGraph的stream流式输出
langchain
PiaoShiSun9 小时前
小米手机浏览器缓存视频如何导出
缓存·智能手机·音视频
盐焗西兰花9 小时前
鸿蒙学习实战之路-Share Kit系列(14/17)-手机间碰一碰分享实战
学习·智能手机·harmonyos
wanhengidc10 小时前
云手机 性能不受限 数据安全
服务器·网络·安全·游戏·智能手机
new Object ~1 天前
LangChain的短期记忆存储实现
python·langchain
liu****1 天前
LangChain-AI应用开发框架(六)
人工智能·python·langchain·大模型应用·本地部署大模型
java资料站1 天前
第07章:LangChain使用之Agents
langchain
jixingkj1 天前
拒绝注意力被切割,批量管理应用通知的实用指南
智能手机