5.提示词模板

提示词模板

一、基础概念前置

1 两类核心模板区分

  1. PromptTemplate:纯字符串文本模板,适合单轮简单提问,输出普通文本字符串
  2. ChatPromptTemplate:结构化对话模板,区分system/human/ai角色,适配聊天大模型,生产消息列表(工业95%场景首选)

2 四大消息角色

  • SystemMessage:系统角色,定义AI身份、输出规则、回答边界
  • HumanMessage:用户人类提问
  • AIMessage:AI历史回复(用于多轮上下文)
  • ToolMessage:工具返回数据(工具调用场景专用)

3 占位符核心作用

把可变内容抽离成{变量名},一套模板复用不同输入,避免硬编码重复文本;
特殊:MessagesPlaceholder支持一对多填充多条历史对话消息。

二、PromptTemplate 纯文本提示模板

2.1 两种实例化创建模板

方式1:构造函数直接创建 PromptTemplate

from langchain_core.prompts import PromptTemplate
# template:模板文本;input_variables:模板内所有占位变量列表
template = PromptTemplate(
    template="你是专业{role}工程师,解答问题:{question}",
    input_variables=["role", "question"]
)
# format填充变量,输出纯字符串
prompt_str = template.format(role="Python", question="冒泡排序代码")
print(prompt_str)

讲解:手动声明输入变量,适合模板逻辑复杂、需要显式管控变量的场景。

方式2:静态方法 from_template(推荐最简写法)

template = PromptTemplate.from_template("你是专业{role}工程师,解答问题:{question}")
prompt_str = template.format(role="Java", question="快速排序思路")

讲解:自动识别{xxx}占位,不用手动写input_variables,日常开发首选。

2.2 三大格式化核心方法

  1. format() → 返回纯字符串(最简单,只输出文本)
res = template.format(role="前端", question="Vue双向绑定原理")
print(type(res)) # str
  1. invoke() → 返回PromptValue对象(高阶,可转字符串/消息列表)
prompt_val = template.invoke({"role":"Go", "question":"goroutine原理"})
print(prompt_val.to_string()) # 转文本
print(prompt_val.to_messages()) # 转消息列表,对接Chat模型
  1. partial() → 局部预填充变量,返回新模板(半成品模板)

2.3 partial 局部预填充(动静分离)

适用:部分变量固定不变,仅少量变量动态传入(如固定时间、固定角色)

from datetime import datetime
# 写法1:实例时传入partial_variables
t1 = PromptTemplate.from_template(
    "当前时间{now},问题:{q}",
    partial_variables={"now": datetime.now().strftime("%Y-%m-%d")}
)
print(t1.format(q="今天几号"))

# 写法2:模板.partial() 动态绑定固定变量
t2 = PromptTemplate.from_template("当前时间{now},问题:{q}")
t2_fixed = t2.partial(now=datetime.now().strftime("%Y-%m-%d"))
print(t2_fixed.format(q="现在几点"))

逻辑:提前锁定不变参数,后续只传动态参数,减少重复传参。

2.4 多模板拼接组合

多个短模板相加,拼接成完整提示词

t1 = PromptTemplate.from_template("用通俗语言介绍{topic}\n")
t2 = PromptTemplate.from_template("回答字数不超过{num}")
t_all = t1 + t2 # 模板拼接
print(t_all.format(topic="Redis", num=100))

2.5 外部加载模板(解耦代码与提示词)

提示词写在json/yaml文件,不硬编码在Python里,便于运营修改文案

1)prompt.json 配置文件

{
    "_type": "prompt",
    "input_variables": ["name", "content"],
    "template": "请{name}讲解{content}"
}

2)加载代码

from langchain_core.prompts import load_prompt
template = load_prompt("prompt.json", encoding="utf-8")
print(template.format(name="程序员", content="生成器"))

yaml文件用法一致,仅文件格式不同。

三、ChatPromptTemplate 对话模板

3.1 三种消息入参格式(创建模板时可用)

格式1:元组列表(最简,项目最常用)

from langchain_core.prompts import ChatPromptTemplate
chat_tpl = ChatPromptTemplate([
    ("system", "你是资深{lang}开发工程师"),
    ("human", "讲解{func}底层原理")
])

格式2:字典列表

chat_tpl = ChatPromptTemplate([
    {"role":"system", "content":"你是资深{lang}开发工程师"},
    {"role":"human", "content":"讲解{func}底层原理"}
])

格式3:Message 对象列表(多轮历史硬编码场景)

from langchain_core.messages import SystemMessage, HumanMessage
chat_tpl = ChatPromptTemplate([
    SystemMessage(content="你是资深{lang}开发工程师"),
    HumanMessage(content="讲解{func}底层原理")
])

3.2 标准创建方式 from_messages

chat_tpl = ChatPromptTemplate.from_messages([
    ("system", "你是资深Python工程师"),
    ("human", "{user_question}")
])
# format_messages:输出 List[BaseMessage] 消息列表,直接传给LLM
msg_list = chat_tpl.format_messages(user_question="装饰器作用")
print(msg_list)

3.3 ChatPromptTemplate 三种格式化方法

  1. format_messages():返回消息列表,模型原生接收格式(推荐)
  2. invoke(dict):返回PromptValue,支持to_string()/to_messages()
  3. format():直接拼接成纯文本字符串,调试用

3.4 MessagesPlaceholder 历史对话占位(多轮对话核心)

作用:占位位置批量插入多条历史Human/AI消息,实现上下文记忆,分显式隐式简写两种写法

写法1:显式导入 MessagesPlaceholder

from langchain_core.prompts import MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是Python开发工程师"),
    MessagesPlaceholder("memory"), # 历史消息占位符
    ("human", "{question}")
])
# 传入历史对话 + 当前问题
res = prompt.invoke({
    "memory": [
        HumanMessage("我叫亮仔,程序员"),
        AIMessage("亮仔你好")
    ],
    "question": 我叫什么名字?
})
print(res.to_string())

写法2:隐式简写 ("placeholder", "变量名")

等价于上面MessagesPlaceholder("memory"),代码更整洁

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是Python开发工程师"),
    ("placeholder", "{memory}"), # 隐式消息占位
    ("human", "{question}")
])

四、LLM 六大模型调用方式(同步+异步)

前置模型初始化(通义千问兼容OpenAI接口示例)

import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
load_dotenv()
# 初始化通义千问大模型
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"
)

同步调用(主线程阻塞,简单业务优先)

  1. invoke() 单次完整请求,一次性返回全部结果
messages = [SystemMessage("简洁回答,100字内"), HumanMessage("什么是Redis")]
resp = model.invoke(messages)
print(resp.content)
  1. stream() 流式逐块返回(打字机效果,前端对话)
for chunk in model.stream(messages):
    print(chunk.content, end="", flush=True)
  1. batch() 批量一次性执行多个问题
qs = ["Redis是什么", "Python生成器作用", "Docker和K8s关系"]
res_list = model.batch(qs)
for q, r in zip(qs, res_list):
    print(f"问题:{q}\n答案:{r.content}")

异步调用(web服务、高并发不阻塞主线程)

方法名带前缀a,搭配async/await + asyncio.run()

  1. ainvoke 异步单次请求
import asyncio
async def run():
    resp = await model.ainvoke("LangChain介绍,100字")
    print(resp.content)
asyncio.run(run())
  1. astream 异步流式输出
async def run_stream():
    async for chunk in model.astream(messages):
        print(chunk.content, end="")
asyncio.run(run_stream())
  1. abatch 异步批量并发提问(性能最优)
async def run_batch():
    qs = ["Redis是什么", "Python生成器作用"]
    res = await model.abatch(qs)
    for q, r in zip(qs, res):
        print(q, r.content)
asyncio.run(run_batch())

六大调用场景选择口诀

  1. 简单单轮问答 → invoke
  2. 前端实时打字效果 → stream / astream
  3. 一次性批量多个问题 → batch / abatch
  4. FastAPI、高并发web服务 → 全部用异步a开头方法
  5. 接口阻塞、并发量大 → 放弃同步,改用异步

五、综合完整案例(带历史记忆对话)

import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import HumanMessage, AIMessage

# 1 加载模型
load_dotenv()
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"
)

# 2 构建带历史占位的对话模板
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是资深Python后端工程师,回答简洁"),
    ("placeholder", "{history}"), # 历史对话占位
    ("human", "{input}")
])

# 3 填充模板,拼接历史对话
prompt_val = chat_prompt.invoke({
    "history": [
        HumanMessage("我叫亮仔,后端程序员"),
        AIMessage("亮仔你好,有什么Python问题?")
    ],
    "input": "我的名字是什么?"
})

# 4 调用大模型
resp = model.invoke(prompt_val.to_messages())
print("AI回答:", resp.content)

运行效果:模型读取历史对话,正确输出名字「亮仔」,实现上下文记忆。

六、学习总结

  1. 日常对话业务优先用 ChatPromptTemplate,区分角色,支持多轮记忆;简单单文本提问用PromptTemplate
  2. 占位符分普通变量{xxx}、消息占位MessagesPlaceholder(一对多填充历史)。
  3. 模板创建:from_template / from_messages 最简,优先使用;partial实现固定参数预填充。
  4. 模型调用分同步/异步,流式用于前端实时展示,批量处理多问题,web服务全部异步。
  5. 复杂提示词建议外部json/yaml加载,代码和文案解耦,方便迭代维护。
posted @ 2026-08-17 20:15  _丑小鸭  阅读(0)  评论(0)    收藏  举报