【LangChain Prompt 完整指南】提示词篇

LangChain Prompt 完整指南

目录


消息类型

在 LangChain 中,Message 是大模型对话的基本单元,就像聊天记录里的每一条消息。

四种核心消息类型

类型 谁说的 作用 代码示例
SystemMessage 系统/开发者 给AI定角色、定规则 SystemMessage(content="你是一个法律助手")
HumanMessage 用户 用户的提问 HumanMessage(content="酒驾了怎么办")
AIMessage AI AI的回复 AIMessage(content="非法律问题无可奉告")
ToolMessage 工具 工具执行结果 ToolMessage(tool_call_id="abc", content="...")

为什么要区分消息类型?

多轮对话需要记忆

复制代码
# 错误做法:每次只问当前问题
HumanMessage(content="北京人口有多少?")
​
# 正确做法:带上对话历史
messages = [
    SystemMessage(content="你是一个旅游助手"),
    HumanMessage(content="北京有什么景点?"),      # 第1轮
    AIMessage(content="推荐故宫、长城、颐和园"),   # AI回答
    HumanMessage(content="故宫要门票吗?"),        # 第2轮(带上了上文)
]

SystemMessage - 系统消息

是什么:定义 AI 的身份、角色和行为规则

复制代码
SystemMessage(content="你是一个法律助手,只回答法律问题,超出范围的统一回答,非法律问题无可奉告")

就像:给 AI 定了一个"岗位说明书"

HumanMessage - 用户消息

是什么:模拟用户的输入/提问

复制代码
HumanMessage(content="11")  # 用户随便输入的内容

就像:用户发给 AI 的每一条消息

AIMessage - AI消息

是什么:模拟 AI 的回复

复制代码
AIMessage(content="非法律问题无可奉告")

就像:AI 回复的每一条消息

ToolMessage - 工具消息

是什么 :用于 Agent 调用工具后的结果返回

复制代码
ToolMessage(
    tool_call_id="call_abc123",  # 关联的工具调用ID
    content='{"population": 21540000, "area": "16410平方公里"}',  # 工具执行结果
)

使用场景:当 AI 调用搜索、计算等工具时,工具返回的结果通过 ToolMessage 传回给 AI

完整示例

复制代码
from langchain.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
​
messages = [
    SystemMessage(content="你是一个乐于助人的智能小助手"),
    HumanMessage(content="你好,请你介绍一下你自己"),
    AIMessage(content="我是一名人工智能助手,请问您有什么想问的嘛?"),
    # ToolMessage - 用于工具调用场景
    ToolMessage(
        tool_call_id="call_abc123",
        content='{"population": 21540000, "area": "16410平方公里"}',
    )
]

Prompt 模板

什么是 PromptTemplate?

PromptTemplate 用于生成格式化的提示词文本,是纯字符串模板。

核心特点

  • 输入:模板 + 变量值

  • 输出:格式化后的字符串

  • 适用场景:简单问答、文本生成

1. 构造方法创建

复制代码
from langchain_core.prompts import PromptTemplate
​
template = PromptTemplate(
    template="你是一个专业的{role}工程师,请回答我的问题:{question}",
    input_variables=['role', 'question']
)
​
prompt = template.format(role="python开发", question="冒泡排序怎么写?")
print(prompt)
# 你是一个专业的python开发工程师,请回答我的问题:冒泡排序怎么写?

2. from_template 方法创建

复制代码
from langchain_core.prompts import PromptTemplate
​
# 方式1:直接创建
template = PromptTemplate.from_template(
    "你是一个专业的{role}工程师,请回答我的问题:{question}"
)
​
# 方式2:模板拼接(使用 + 号连接)
template1 = PromptTemplate.from_template("请用一句话介绍{topic},要求通俗易懂\n")
template2 = PromptTemplate.from_template("内容不超过{length}个字")
combined_template = template1 + template2
​
prompt = combined_template.format(topic="LangChain", length=100)

3. format vs invoke 方法

复制代码
# format() - 返回字符串
prompt_str = template.format(role="python", question="什么是闭包?")
print(prompt_str)  # 字符串类型

# invoke() - 返回 PromptValue 对象,可转换为字符串或消息列表
from langchain_core.prompts import PromptTemplate

template = PromptTemplate.from_template(
    "你是一个专业的{role}工程师,你的问题是:{question}"
)

prompt_value = template.invoke({"role": "python开发", "question": "冒泡排序怎么写?"})

print(prompt_value)              # PromptValue 对象
print(prompt_value.to_string())  # 转为字符串: "你是一个专业的python开发工程师..."
print(prompt_value.to_messages()) # 转为消息列表 [HumanMessage(content='你是一个专业的...')]

4. partial 预绑定变量

有时候希望先固定部分变量,后续再填充剩余变量:

复制代码
from langchain_core.prompts import PromptTemplate
from datetime import datetime

# 方式1:实例化时使用 partial_variables
template1 = PromptTemplate.from_template(
    "现在时间是:{time}, 请回答我的问题:{question}",
    partial_variables={"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
)
prompt1 = template1.format(question="今天是几号?")

# 方式2:使用 partial() 方法(推荐,更灵活)
template2 = PromptTemplate.from_template("现在时间是:{time}, 请回答我的问题:{question}")
partial_template = template2.partial(time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
prompt2 = partial_template.format(question="今天是几号?")

# 方式3:构造时使用 partial_variables 预绑定
template3 = PromptTemplate(
    template="{foo} {bar}",
    input_variables=["foo", "bar"],
    partial_variables={"foo": "hello"}  # foo 预先绑定为 hello
)
prompt3 = template3.format(bar="world")  # 只需传入 bar
# 结果: hello world

5. PromptTemplate 完整方法对比

方法 作用 返回类型 示例
format() 填充变量生成字符串 str template.format(var1="a", var2="b")
invoke() 填充变量生成 PromptValue PromptValue template.invoke({"var1": "a", "var2": "b"})
partial() 预绑定部分变量 PromptTemplate template.partial(var1="a")
to_string() PromptValue 转为字符串 str prompt_value.to_string()
to_messages() PromptValue 转为消息列表 List[BaseMessage] prompt_value.to_messages()

ChatPromptTemplate 对话模板

什么是 ChatPromptTemplate?

ChatPromptTemplate 用于构建多角色对话场景,生成消息列表而非纯文本。

PromptTemplate vs ChatPromptTemplate 对比

特性 PromptTemplate ChatPromptTemplate
输出类型 字符串 str 消息列表 List[BaseMessage]
用途 简单文本生成 多角色对话
支持角色 System/Human/AI/Tool
对话历史 不支持 支持(通过占位符)

1. 构造方法 - 三种参数格式

复制代码
from langchain_core.prompts import ChatPromptTemplate

# 格式1:tuple 元组 ("role", content) - 最常用
chat_prompt1 = ChatPromptTemplate.from_messages([
    ("system", "你是一个{name},你的职责是{role}。"),
    ("human", "{user_input}")
])

# 格式2:dict 字典 {"role": ..., "content": ...}
chat_prompt2 = ChatPromptTemplate.from_messages([
    {"role": "system", "content": "你是AI助手,名字叫{name}。"},
    {"role": "user", "content": "请问:{question}"}
])

# 格式3:Message 类(显式指定消息类型)
from langchain_core.messages import SystemMessage, HumanMessage
chat_prompt3 = ChatPromptTemplate.from_messages([
    SystemMessage(content="你是AI助手,名字叫{name}。"),
    HumanMessage(content="请问:{question}")
])

2. format_messages 方法

ChatPromptTemplate 使用 format_messages() 生成消息列表:

复制代码
# 构建模板
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个AI开发工程师,你的名字是{name}。"),
    ("human", "你能帮我做什么?"),
    ("ai", "我能开发很多{thing}。"),
    ("human", "{user_input}")
])

# 填充变量,生成消息列表
messages = chat_prompt.format_messages(
    name="小谷AI",
    thing="AI应用",
    user_input="7 + 5等于多少"
)

print(messages)
# 输出:
# [
#     SystemMessage(content='你是一个AI开发工程师,你的名字是小谷AI。'),
#     HumanMessage(content='你能帮我做什么?'),
#     AIMessage(content='我能开发很多AI应用。'),
#     HumanMessage(content='7 + 5等于多少')
# ]

3. from_messages vs format_messages

  • ChatPromptTemplate.from_messages() - 从模板定义创建模板对象

  • chat_template.format_messages() - 填充变量,生成实际的消息列表

复制代码
# from_messages - 创建模板
chat_prompt = ChatPromptTemplate.from_messages([
    SystemMessage(content="你是AI助手,你的名字叫{name}。"),
    HumanMessage(content="请问:{question}")
])

# format_messages - 填充变量,生成消息
formatted_messages = chat_prompt.format_messages(name="亮仔", question="什么是LangChain")

4. MessagesPlaceholder 占位符

用于动态插入对话历史,实现多轮对话记忆:

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

# 显式使用 MessagesPlaceholder
prompt1 = ChatPromptTemplate.from_messages([
    ("system", "你是一个资深的Python开发工程师"),
    MessagesPlaceholder("memory"),  # 动态插入对话历史
    ("human", "{question}")
])

# 隐式使用占位符(简写形式,效果相同)
prompt2 = ChatPromptTemplate.from_messages([
    ("placeholder", "{memory}"),  # 等价于 MessagesPlaceholder("memory")
    ("system", "你是一个资深的Python开发工程师"),
    ("human", "{question}")
])

# 调用时传入历史消息
prompt_value = prompt1.invoke({
    "memory": [
        HumanMessage(content="我的名字叫亮仔,是一名程序员"),
        AIMessage(content="好的,亮仔你好"),
    ],
    "question": "Python的装饰器是什么?"
})


进阶用法

外部加载 Prompt

可以将 Prompt 模板保存为 JSON 或 YAML 文件,然后加载使用,实现 Prompt 和代码分离。

从 JSON 加载
复制代码
# prompt.json 文件内容
# {
#     "input_variables": ["name", "what"],
#     "template": "请{name}讲一个{what}的故事"
# }

from langchain_core.prompts import load_prompt

template = load_prompt("prompt.json", encoding="utf-8")
print(template.format(name="张三", what="搞笑的"))
# 请张三讲一个搞笑的的故事
从 YAML 加载
复制代码
# prompt.yaml 文件内容
# input_variables:
#   - name
#   - what
# template: "请{name}讲一个{what}的故事"

from langchain_core.prompts import load_prompt

template = load_prompt("prompt.yaml", encoding="utf-8")
print(template.format(name="年轻人", what="滑稽"))
# 请年轻人讲一个滑稽的故事

多轮对话完整示例

复制代码
from langchain.chat_models import init_chat_model
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
import os
from dotenv import load_dotenv

load_dotenv(encoding='utf-8')

# 初始化模型
model = init_chat_model(
    model="qwen-plus",
    model_provider="openai",
    api_key=os.getenv("aliQwen-api"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

# 构建带记忆的对话模板
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个旅游助手,为用户提供旅行建议"),
    MessagesPlaceholder("history"),  # 对话历史占位符
    ("human", "{question}")
])

# 模拟多轮对话
def chat(prompt, history, question):
    messages = prompt.format_messages(history=history, question=question)
    response = model.invoke(messages)

    # 更新历史
    history.append(HumanMessage(content=question))
    history.append(AIMessage(content=response.content))

    return response.content, history

# 开始对话
history = []
response1, history = chat(prompt, history, "推荐几个国内旅游城市")
print(f"AI: {response1}")

response2, history = chat(prompt, history, "北京有什么好吃的?")
print(f"AI: {response2}")

response3, history = chat(prompt, history, "那上海呢?")
print(f"AI: {response3}")

组合提示词模板

通过将多个子提示(Prompt)按一定逻辑顺序或层级组合起来,形成一个复杂任务的整体 Prompt:

复制代码
from langchain_core.prompts import PromptTemplate

# 方式1:直接拼接
template = PromptTemplate.from_template("请用一句话介绍{topic},要求通俗易懂\n") + "内容不超过{length}个字"
prompt = template.format(topic="LangChain", length=100)

# 方式2:变量拼接
prompt_a = PromptTemplate.from_template("请用一句话介绍{topic},要求通俗易懂\n")
prompt_b = PromptTemplate.from_template("内容不超过{length}个字")
prompt_all = prompt_a + prompt_b
prompt = prompt_all.format(topic="LangChain", length=200)

模板变量类型

类型 说明 示例
普通变量 需要手动传入 {question}, {name}
部分变量 预绑定值,可不传 partial_variables={"time": now}
占位符 动态插入消息列表 MessagesPlaceholder("memory")

注意事项

1. load_dotenv() 必须放在最前面

复制代码
# 正确:放在最前面
import os
from dotenv import load_dotenv
load_dotenv(encoding='utf-8')

# 错误:被注释或放在后面
# load_dotenv()  # 这行被注释了,导致 API Key 读取不到

2. temperature 范围

阿里云 DashScope 要求 temperature 在 0.0 到 2.0 之间(不包含2.0)

复制代码
temperature=0.0   # 最稳定
temperature=0.7   # 适中(推荐日常使用)
temperature=1.9   # 很随机(创意场景)
temperature=2.0   # ❌ 错误:超出范围会报错

3. 响应对象没有 content_blocks 属性

复制代码
# 错误:content_blocks 不存在
print(response.content_blocks)

# 正确:使用 content 获取回复内容
print(response.content)

4. 异步调用必须用 asyncio.run()

复制代码
# 正确
asyncio.run(async_function())

# 错误:直接调用不会执行
async_function()

5. astream 必须用 async for

复制代码
# 正确
async for chunk in response:
    print(chunk.content)

# 错误:不能用普通 for
for chunk in response:  # 不会迭代
    print(chunk.content)

6. 区分 PromptTemplate 和 ChatPromptTemplate

复制代码
# PromptTemplate - 输出字符串
from langchain_core.prompts import PromptTemplate
template = PromptTemplate.from_template("你是{role}专家")
print(template.format(role="Python"))  # 字符串
​
# ChatPromptTemplate - 输出消息列表
from langchain_core.prompts import ChatPromptTemplate
chat = ChatPromptTemplate.from_messages([("human", "你是{role}专家")])
print(chat.format_messages(role="Python"))  # 消息列表
相关推荐
weixin_397578022 小时前
DeerFlow 2.0 深度解析
人工智能
量子-Alex2 小时前
【大模型】EvoLM EvoLM: 探寻遗失的语言模型训练动态
人工智能·语言模型·自然语言处理
你可以叫我仔哥呀2 小时前
Agent架构之ReAct
人工智能·ai·大模型
啊哈一半醒2 小时前
React 核心知识点系统总结:从基础语法到高级 API,一篇文章梳理完整学习路线
javascript·学习·react.js
大象AI共学2 小时前
我让AI写了个网页,它自动变成了视频
人工智能·音视频
ting94520002 小时前
腾讯 Hy3 Preview (Free) 深度解析:免费体验 295B 参数顶级 MoE 大模型
人工智能
逸Y 仙X2 小时前
文章二十:Elasticsearch高亮搜索完全指南
java·大数据·运维·elasticsearch·搜索引擎·全文检索
2601_956139422 小时前
集团品牌全案公司哪家专业
大数据·人工智能·python
梦想画家2 小时前
拒绝硬编码:将 LangFlow 编排的 AI 工作流无缝接入 OpenClaw
人工智能·智能体·mcp服务