别再手写Prompt了!LangChain模板实战指南,3个案例带你从入门到业务落地

1. 本章目标

学完本章后,你应该能够:

  • 理解 Prompt 在大模型应用中的作用
  • 使用普通字符串编写 Prompt
  • 使用PromptTemplate管理单段提示词
  • 使用ChatPromptTemplate管理聊天消息
  • 给 Prompt 注入变量
  • 编写适合业务场景的提示词
  • 完成商品文案、学习计划、客服回复三个案例

2. 什么是 Prompt

Prompt 就是给模型的指令。

例如:

请用一句话介绍 LangChain。

这是一条很简单的 Prompt。

在实际项目中,Prompt 往往会更复杂:

你是一名电商运营专家。 请根据商品名称、商品卖点、目标用户,生成一段适合详情页展示的商品文案。 要求: 1. 语气自然 2. 不超过 150 字 3. 突出用户利益

Prompt 的质量会直接影响模型输出质量。

3. 为什么需要 Prompt 模板

如果每次都手写完整 Prompt,会有几个问题:

  • 代码里字符串太长
  • 多个地方重复写类似提示词
  • 变量拼接容易出错
  • 后期不方便维护和修改

例如:

prompt = f"请为商品 {product_name} 写一段文案,卖点是 {selling_points}"

这种写法可以用,但当提示词变长后就不好维护。

LangChain 提供了 Prompt 模板,可以把固定内容和变量分开

4. PromptTemplate 基本使用

PromptTemplate适合普通文本提示词

示例:

from langchain_core.prompts import PromptTemplate prompt_template = PromptTemplate.from_template( "请为商品 {product_name} 写一句广告语,突出卖点:{selling_points}" ) prompt = prompt_template.invoke( { "product_name": "无线鼠标", "selling_points": "静音、续航长、轻便", } ) print(prompt.text)

模板中的变量:

{product_name} {selling_points}

会被实际数据替换。

5. ChatPromptTemplate 基本使用

如果要使用 system / human 消息结构,推荐使用ChatPromptTemplate

示例:

from langchain_core.prompts import ChatPromptTemplate prompt_template = ChatPromptTemplate.from_messages( [ ("system", "你是一名电商运营专家,回答要简洁、有吸引力。"), ("human", "请为商品 {product_name} 写一段文案,卖点是:{selling_points}"), ] )

调用:

prompt = prompt_template.invoke( { "product_name": "无线鼠标", "selling_points": "静音、续航长、轻便", } )

ChatPromptTemplate会生成消息列表,适合聊天模型。

本课程后面会经常使用它。

随堂代码:

from langchain_core.prompts import PromptTemplate prompt_template=PromptTemplate.from_template("请为商品 {product_name} 写一句广告语,突出卖点:{selling_points}") prompt=prompt_template.invoke( { "product_name":"logi鼠标", "selling_points":"特别安静,灵敏,速度快,无延迟" } ) print(prompt.text)
from langchain_core.prompts import ChatPromptTemplate chat_template=ChatPromptTemplate.from_messages( [ ("system","你是一名电商运营专家,回答要简洁、有吸引力。"), ("human","请为商品 {product_name} 写一段文案,卖点是:{selling_points}") ] ) prompt=chat_template.invoke( { "product_name":"logi鼠标", "selling_points":"特别安静,灵敏,速度快,无延迟" } ) print(prompt) # 在真正使用时,需要将整个对象都传递给大模型,而不是一个字符串 print(prompt.messages[1].content)

核心本质差异

PromptTemplate

纯文本提示词模板,只生成一段完整字符串

无角色概念,只能把系统指令、用户提问揉在一段文字里,靠文字描述区分角色,模型容易混淆。

ChatPromptTemplate 【建议使用】

对话消息模板,生成结构化消息列表[SystemMessage, HumanMessage, AIMessage]

适用:现代对话大模型(GPT-3.5/4、Claude、通义千问、文心一言等),所有 Agent、ReAct、聊天智能体都用它。

ChatPromptTemplate:原生支持三种角色消息:

  • SystemMessage:系统提示词(智能体规则、ReAct 流程、约束)
  • HumanMessage:用户输入
  • AIMessage:模型历史回复(用于多轮记忆)

6. Prompt 编写建议

第一阶段先掌握几个最实用的原则。

6.1 明确角色

例如:

你是一名电商运营专家。

角色可以帮助模型确定回答风格。

6.2 明确任务

例如:

请根据商品名称和卖点生成一段详情页文案。

任务越明确,模型越容易输出想要的结果。

6.3 明确约束

例如:

要求: 1. 不超过 150 字 2. 不要使用夸张宣传 3. 适合年轻上班族

约束可以减少输出跑偏。

6.4 给出输入字段

例如:

商品名称:{product_name} 商品卖点:{selling_points} 目标用户:{target_user}

让模型清楚知道每个变量的含义。

7. 案例一:商品文案生成器

本案例根据商品信息生成一段电商文案。

创建01_product_copywriter.py

import os from dotenv import load_dotenv from langchain.chat_models import init_chat_model from langchain_core.prompts import ChatPromptTemplate load_dotenv() model=init_chat_model( model="deepseek-v4-flash", model_provider="openai", base_url=os.getenv("DEEPSEEK_BASE_URL"), api_key=os.getenv("DEEPSEEK_API_KEY"), temperature=0.5 ) prompt_str=""" 请根据下面信息生成一段商品详情页文案。 商品名称:{product_name} 商品卖点:{selling_points} 目标用户:{target_user} 要求: 1. 不超过 150 字 2. 突出用户能获得的好处 3. 不要使用虚假夸张表达 """ chat_promt_template=ChatPromptTemplate.from_messages([ ("system","你是一名电商运营专家,擅长写自然、有吸引力但不过度夸张的商品文案"), ("human",prompt_str) ]) prompt=chat_promt_template.invoke({ "product_name":"无线静音鼠标", "selling_points":"静音按键、蓝牙连接、续航 30 天、轻便便携", "target_user":"经常在办公室和图书馆使用电脑的人", }) response=model.invoke(prompt) print(response.content)

运行:

python 01_product_copywriter.py

这个案例体现了 Prompt 的基本结构:

  • 角色
  • 输入
  • 要求
  • 输出任务

8. 减少重复代码:封装模型初始化

前面几个案例都重复写了模型初始化代码。

将其放入到一个 utils 工具包下

可以创建model_factory.py

import os from dotenv import load_dotenv from langchain.chat_models import init_chat_model def get_deepSeek_model(temperature:float=0.7): load_dotenv() model = init_chat_model( model="deepseek-v4-flash", model_provider="openai", base_url=os.getenv("DEEPSEEK_BASE_URL"), api_key=os.getenv("DEEPSEEK_API_KEY"), temperature=temperature ) return model

然后案例中可以改成:

from model_factory import get_deepseek_model model = get_deepseek_model(temperature=0.5)

这不是复杂封装,只是减少重复代码。

9. 案例二:学习计划生成器

本案例根据学习目标生成学习计划。

创建02_study_plan.py

from langchain_core.prompts import ChatPromptTemplate from utils.model_factory import get_deepSeek_model model=get_deepSeek_model(0.5) prompt_str=""" 请为我制定一个学习计划。 学习主题:{topic} 学习时长:{days} 天 每天可学习时间:{hours_per_day} 小时 当前基础:{level} 要求: 1. 按天列出学习内容 2. 每天给出练习任务 3. 内容要适合当前基础 """ chat_promt_template=ChatPromptTemplate.from_messages([ ("system","你是一名编程课程规划老师,擅长为初学者制定可执行的学习计划。"), ("human",prompt_str) ]) prompt=chat_promt_template.invoke({ "topic":"langchain", "days":"3", "hours_per_day":"1", "level":"会python基础" }) response=model.invoke(prompt) print(response.content)

运行:

python 02_study_plan.py

这个案例可以看到:

  • Prompt 可以接收多个变量
  • 变量可以是字符串,也可以是数字
  • 模型输出可以被规则引导

10. 案例三:客服回复生成器

本案例根据用户问题和订单状态,生成客服回复。

创建03_customer_reply.py

from langchain_core.prompts import ChatPromptTemplate from utils.model_factory import get_deepSeek_model model = get_deepSeek_model(0.7) prompt_str = """ 请根据用户问题和订单状态,生成一段客服回复。 用户问题:{user_question} 订单状态:{order_status} 物流信息:{shipping_info} 要求: 1. 先安抚用户 2. 再说明当前情况 3. 最后给出下一步建议 4. 不超过 120 字 """ chat_promt_template = ChatPromptTemplate.from_messages([ ("system", "你是一名电商客服,回复要礼貌、明确,不推卸责任。"), ("human", prompt_str) ]) prompt = chat_promt_template.invoke({ "user_question": "我的快递三天没更新了,是不是丢了?", "order_status": "已发货", "shipping_info": "物流显示包裹已到达上海转运中心,暂未更新下一站信息" }) response = model.invoke(prompt) print(response.content)

运行:

python 03_customer_reply.py

这个案例接近真实业务:

  • 用户问题来自前端
  • 订单状态来自数据库
  • 物流信息来自第三方接口
  • Prompt 负责组织这些信息并生成回复

11.MessagesPlaceholder

作用:

MessagesPlaceholder用来在ChatPromptTemplate中插入一组消息列表。

它通常用于:

  • 插入聊天历史
  • 插入 Agent 中间步骤
  • 插入已经构造好的多条 message

普通变量{question}只能填充一段文本,而MessagesPlaceholder("history")可以一次插入多条(历史)消息。

基本导入

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

基本语法

MessagesPlaceholder(variable_name)

常用写法:

MessagesPlaceholder("history")

完整参数:

MessagesPlaceholder( variable_name="history", optional=True, n_messages=6, )

参数说明

参数

类型

说明

variable_name

str

占位符对应的输入变量名

optional

bool

是否允许不传该变量

n_messages

int \| None

最多保留最近多少条消息

在 ChatPromptTemplate 中使用

prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant. "), MessagesPlaceholder("history"), ("human", "{question}"), ])

这里面有一个照应关系:当MessagesPlaceholder("history")时,默认optional=False

也就是说 prompt.invoke 时,必须传入history 这个标签,当然这个标签的名字两个地方保持一致即可

那如果optional=True, 那么prompt.invoke 时,可以不传递 history

另外这个history,必须是一个列表才行

调用时传入:

prompt_value = prompt.invoke({ "history": [ ("human", "My name is Alice."), ("ai", "Nice to meet you, Alice."), ], "question": "What is my name?", })

最终消息顺序相当于:

[ SystemMessage(content="You are a helpful assistant."), HumanMessage(content="My name is Alice."), AIMessage(content="Nice to meet you, Alice."), HumanMessage(content="What is my name?"), ]

输入格式

MessagesPlaceholder对应的变量必须是消息列表

可以使用 tuple 格式:

history = [ ("human", "你好"), ("ai", "你好,有什么可以帮你?"), ]

也可以使用 LangChain 消息对象:

from langchain_core.messages import HumanMessage, AIMessage history = [ HumanMessage(content="你好"), AIMessage(content="你好,有什么可以帮你?"), ]

错误写法:

prompt.invoke({ "history": "你好", "question": "刚才我说了什么?", })

history不能是普通字符串,必须是 list。

optional=True

默认情况下,如果没有传入history,会报错。

prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant."), MessagesPlaceholder("history"), ("human", "{question}"), ]) prompt.invoke({ "question": "Hello!", })

如果聊天历史可能为空,建议设置:

prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant."), MessagesPlaceholder("history", optional=True), ("human", "{question}"), ])

这样就可以不传history

prompt_value = prompt.invoke({ "question": "Hello!", })

n_messages

n_messages用来限制插入最近多少条消息。

prompt = ChatPromptTemplate.from_messages([ ("system", "You are a concise assistant."), MessagesPlaceholder("history", optional=True, n_messages=4), ("human", "{question}"), ])

示例输入:

prompt_value = prompt.invoke({ "history": [ ("human", "My name is Alice."), ("ai", "Nice to meet you, Alice."), ("human", "I like Python."), ("ai", "Great choice."), ("human", "I also use LangChain."), ("ai", "LangChain is useful for LLM apps."), ], "question": "What do you know about me?", })

这里history只会插入最近 4 条消息:

[ HumanMessage(content="I like Python."), AIMessage(content="Great choice."), HumanMessage(content="I also use LangChain."), AIMessage(content="LangChain is useful for LLM apps."), ]

然后再追加当前问题:

HumanMessage(content="What do you know about me?")

placeholder 简写

MessagesPlaceholder也可以使用 tuple 简写:

prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant."), ("placeholder", "{history}"), ("human", "{question}"), ])

通常等价于:

prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant."), MessagesPlaceholder("history", optional=True), ("human", "{question}"), ])

如果需要设置n_messages,建议使用显式写法:

MessagesPlaceholder("history", optional=True, n_messages=4)
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from utils.model_factory import get_deepSeek_model model=get_deepSeek_model(temperature=0.7) chat_prompt=ChatPromptTemplate.from_messages( [ ("system","你是一个很棒的问答助手"), MessagesPlaceholder(variable_name="history",optional=True,n_messages=4), ("human","{question}") ] ) prompt=chat_prompt.invoke({ "history":[ ("human", "My name is Alice."), ("ai", "Nice to meet you, Alice."), ("human", "I like Python."), ("ai", "Great choice."), ("human", "I also use LangChain."), ("ai", "LangChain is useful for LLM apps."), ], "question":"我叫什么名字?" }) resp=model.invoke(prompt) print(resp.content)

12. 本章重点

本章最重要的是掌握:

  • Prompt 是给模型的任务说明
  • Prompt 应该包含角色、任务、输入、约束
  • PromptTemplate适合普通文本提示词
  • ChatPromptTemplate适合聊天模型
  • Prompt 模板可以通过变量复用
  • 业务场景中要把输入信息清晰地交给模型

13. 常见问题

12.1 Prompt 越长越好吗

不是。

Prompt 应该清晰,但不应该堆太多无关要求。

要求越多,模型越可能顾此失彼。

12.2 为什么模型没有完全按要求输出

大模型不是传统程序,不能保证百分百服从每一条指令。

如果输出格式很重要,后续要结合结构化输出和程序校验。

这部分会在第 4 章讲。

12.3 PromptTemplate 和 ChatPromptTemplate 怎么选

简单建议:

  • 普通文本任务:可以用PromptTemplate
  • 聊天模型任务:优先用ChatPromptTemplate

本课程后面会更多使用ChatPromptTemplate