构建可投入生产的LLM提示:七层框架
学习一种基于API结构的七层提示框架——包括指令、上下文、约束条件等——用以构建可靠且可用于实际应用的LLM系统。
21天高级提示工程课程
这是一套循序渐进的实践课程,带领您从提示语的基础知识逐步掌握完整AI系统的设计方法。
大多数人认为提示语只不过是交给大语言模型的一个问题而已。
例如:
Classify this customer support ticket.
这样就能得到想要的结果。
但情况并非总是如此。
起初的几条输入或许能准确满足需求,但一旦遇到稍有不同的请求,模型就会:
- 选择错误的类别,
- 编造输入中不存在的细节,
- 以非预期的格式返回结果,
- 给出一段解释而非结构化数据,
- 或仅仅因为表述方式稍有变化就出现行为不一致的情况。
这正是随意测试的提示词与为实际应用设计的提示词之间差异开始显现的地方。
在生产系统中,提示词并非仅仅是一个问题。
它实际上是你的应用程序与模型之间的协议组成部分。
开发者们早已知道如何设计具有明确边界的 API:
Request → Validation → Business Logic → Response
基于提示词构建的系统也需要同样的规范:
Instructions
↓
Context
↓
Constraints
↓
Task
↓
Examples
↓
Output Contract
↓
Validation
接下来的内容将逐一探讨这些层面,然后把它们整合成一个可运行的示例。
1. “直接询问模型”的问题
想象一个由人工智能驱动的客户支持平台功能。每条收到的工单都必须被分类到四个类别之一:
billing
technical
account
general
一个最简单的提示词可能长这样:
Classify this customer support ticket:
"I was charged twice for my subscription."
模型可以这样回复:
Billing
表面上看似乎没问题。
但后端通常需要的不仅仅是单个标签,它很可能期望某种结构化的信息,比如:
{
"category": "billing",
"priority": "high"
}
这时问题就变得复杂了。
优先级究竟是如何确定的?
考虑这样一个工单,上面只写着:
“我无法登录。”
这应该归类到account下,还是实际上属于technical问题?
如果客户在同一条消息中同时提到计费问题和登录问题,会怎样?
如果类别确实存在歧义,又该如何处理?
在这种情况下,预期的默认处理方式是什么?
由于提示语从未明确指定规则,模型根本无法可靠地回答这些问题。
这正是为什么在为实际应用构建提示语时,首先要明确规范,而非打磨措辞的原因。
2. 生产级提示语的构成结构
一个完善的实用提示语可以拆解为七个独立的组成部分。
这些部分并不一定非得以带标签的标题形式直接出现在提示语文本中。
重要的是你要明白每一层的作用。
我们逐一来看吧。
3. 系统指令——定义角色与行为
第一层决定了模型需要承担的任务范围。
以工单分类器为例:
You are a customer support classification assistant.
Your job is to classify incoming support tickets
according to the provided category definitions.Return only information supported by the ticket.
Do not invent customer information.
这比类似以下的通用表述要有用得多:
You are an intelligent AI assistant.
为什么这种差异很重要?
因为将模型称为“智能AI助手”并无法明确其具体行为。
更具体的表述会详细说明:
- 模型正在执行的任务
- 它运行的领域
- 它被允许获取的信息
- 哪些行为是禁止的
你可以把系统指令视为交互过程中的行为契约。
4. 上下文——为模型提供所需信息
下一层会提供完成任务所需的全部信息。
例如:
Available categories:
billing:
Questions about charges, invoices, refunds, or payments.technical:
Problems with product functionality, errors, or system behavior.account:
Login, password, profile, access, or account-management issues.general:
Questions that don't clearly belong to the above categories.
随后是实际的工单内容:
Customer ticket:
"I was charged twice for my subscription this month."
这里需要明确区分这两者:
Instructions = What to do
Context = Information needed to do it
如果在不修改指令的情况下更换上下文,模型仍应能够正确处理新的输入。
将它们分开也能让提示模板更易于长期维护。
5. 约束——告诉模型何时停止
约束是消除歧义的关键环节。
继续之前的例子:
Rules:
1. Select exactly one category.
2. Use only the four categories provided.
3. Do not create new categories.
4. Do not infer facts that are not present.
5. If the issue is unclear, use "general".
6. Priority must be one of: low, medium, high.
7. Return only the requested JSON.
这些规则大幅缩小了可能出现的响应范围。
如果没有这些约束,像这样的提示:
Classify the ticket.
可能会产生类似这样的结果:
This appears to be a billing-related issue because
the customer mentions being charged twice.
对人类读者来说,这是个完全合理的答案。
但你的 API 很可能期望的是格式规范的 JSON,而非散文式文本。
请明确添加约束:
Return only the requested JSON.
这样预期的行为就不再存在歧义了。
6. 任务——明确具体操作
在确定了指令和约束条件后,你需要详细说明期望执行的实际操作。
Task:
1. Identify the most appropriate category.
2. Determine the priority based on the rules.
3. Provide a short reason.
4. Return the result using the specified JSON structure.
这与给出模糊的指示相比:
Understand this customer issue.
当任务被如此精确地描述时,就能在事后检查模型是否真的完成了要求的任务。
想象一个如下形状的流程:
Input
↓
Classify
↓
Determine priority
↓
Generate reason
↓
Return JSON
这样一来,任务就不再是凭猜测进行,而变成了可衡量、可测试的内容。
7. 示例——展示期望的行为
指令用文字告诉模型该做什么。
示例则直接演示这一点。
以这个为例:
Example 1
Example 1Input:
"I was charged twice for the same subscription."Output:
{
"category": "billing",
"priority": "medium",
"reason": "The customer reports a duplicate subscription charge."
}
另一个示例可以展示完全不同的场景,比如技术故障报告:
Example 2Input:
"The application crashes every time I upload an image."Output:
{
"category": "technical",
"priority": "high",
"reason": "The customer reports a repeatable application failure."
}
当仅靠规则难以确定所需行为时,示例的作用最为显著,因为它们能让模型锁定具体的模式。
不过仍有一个需要牢记的注意事项。
示例越多并不等于提示词就一定更好
一味堆砌更多示例会带来实际代价,包括:
- 提示词长度
- 令牌消耗量
- 响应延迟
- 潜在的矛盾之处
更明智的做法是精心挑选少量示例。
应优先选择能体现显著不同情境的示例,尤其是那些模糊或边缘情况的示例。
比如这样的三组示例:
Clear billing issue
Clear technical issue
Ambiguous issue
通常比堆砌十个几乎相同的计费示例效果更好。
8. 输出格式——将其视为 API 订阅协议
在生产级提示中,没有比这一层更重要的了。
如果要有其他系统来解析模型返回的内容,就不能让响应形式以松散的散文形式存在,而应加以规范。
应当明确指定数据结构。
例如:
{
"category": "billing | technical | account | general",
"priority": "low | medium | high",
"reason": "string"
}
一旦这样设计完成,模型就有了明确的目标可追求,后续代码也可以依赖如下流程:
LLM
↓
JSON
↓
Parser
↓
Schema validation
↓
Business logic
而不是像下面这样混乱不堪的结构:
LLM
↓
Some paragraph
↓
Regex
↓
Hope it works
第二种架构很难长期保持可维护性。
经过良好定义的结构化输出能够在大语言模型生成的成果与应用程序实际需求之间划出清晰的界限。
9. 验证——模型并非验证工具
以下是在人工智能驱动系统中经常出现的错误。
假设模型返回的内容为:
{
"category": "billing",
"priority": "urgent",
"reason": "The customer has a billing issue."
}
从语法上看,这个 JSON 没有问题。
问题就出在这里:
"urgent"
“urgent”从来都不是你允许的取值之一。
检测这种不匹配是应用程序的任务,而非模型的任务。
以下是使用 Pydantic 的实现方式:
from pydantic import BaseModel
from typing import Literal
class TicketClassification(BaseModel):
category: Literal[
"billing",
"technical",
"account",
"general"
]
priority: Literal[
"low",
"medium",
"high"
]
reason: str
然后你会调用:
result = TicketClassification.model_validate(llm_response)
如果模型返回类似这样的结果:
{
"category": "billing",
"priority": "urgent",
"reason": "Duplicate charge."
}
验证步骤应当直接拒绝它。
这种拒绝正是其目的所在。
绝不能让模型输出未经检查就通过。
这就引出了在设计基于 LLM 的系统时应当遵循的一条规则:
LLM 负责生成,应用程序负责验证。
该模型可以辅助做出判断,但任何真正不可妥协的要求都应体现在能够直接强制执行它的确定性应用代码中。
10. 完整的面向生产环境的提示语
将所有部分整合在一起后,就会得到类似这样的结构:
SYSTEM
You are a customer support classification assistant.
Your job is to classify incoming support tickets
according to the provided category definitions.
Return only information supported by the ticket.
Do not invent customer information.
CONTEXT
Available categories:
billing:
Charges, invoices, refunds, or payment-related issues.
technical:
Product functionality, errors, crashes, or system behavior.
account:
Login, password, profile, access, or account-management issues.
general:
Issues that do not clearly belong to another category.
Customer ticket:
{{ticket_text}}
CONSTRAINTS
1. Select exactly one category.
2. Use only the categories provided above.
3. Do not create new categories.
4. Do not infer unsupported facts.
5. If the issue is unclear, use "general".
6. Priority must be "low", "medium", or "high".
7. Return only the requested JSON.
TASK
1. Classify the ticket.
2. Determine the priority.
3. Provide a short reason.
4. Return the result in the required JSON format.
EXAMPLE
Input:
"I was charged twice for the same subscription."
Output:
{
"category": "billing",
"priority": "medium",
"reason": "The customer reports a duplicate subscription charge."
}
OUTPUT FORMAT
{
"category": "billing | technical | account | general",
"priority": "low | medium | high",
"reason": "string"
}
现在将其放在整个流程的起始位置旁边:
Classify this customer support ticket.
这两个提示语之间的差异并非在于字数多少。
变化在于所有内容都变得更加明确了。
较长版本中的每个部分都有特定的功能:
- 系统部分规定了模型应如何行事
- 上下文部分提供了模型需要处理的信息
- 约束部分明确了模型不可违反的规则
- 任务部分则精确规定了模型需要完成的目标
11. 提示词设计与API设计类似
对于软件工程师而言,这种类比让他们能很快理解生产环境中的提示词使用方式。
想象一个典型的REST接口端点。
你会这样定义它:
POST /tickets/classify
请求体:
{
"ticket": "I was charged twice."
}
以及响应体:
{
"category": "billing",
"priority": "medium",
"reason": "Duplicate charge reported."
}
现在将同样的思路应用到大型语言模型提示词上。
提示词实际上就是该接口端点背后的实现逻辑。
API
↓
Input
↓
Prompt Template
↓
LLM
↓
Structured Output
↓
Validation
↓
API Response
这就是为什么提示词工程越来越偏向于软件工程领域,而非单纯的文字创作练习。
你不必追求完美的表述。
你需要在具有概率性行为的系统之上构建一个可靠的接口。
12. 生产环境提示中的常见错误
1. 表述模糊
Analyze the ticket carefully.
这里的“谨慎”具体指什么?
明确说明你期望的实际行为,而非让对方自行解读。
2. 要求不需要的内容
说明你的应用仅需要:
{
"category": "billing"
}
那么就不要请求:
category
reason
summary
sentiment
customer mood
recommended response
next action
除非你的应用确实在后续流程中使用了这些字段。
每多请求一个字段,输出就有可能出现偏差或不一致。
3. 将业务逻辑完全放在提示中
这种错误的示例:
If the customer has been waiting more than 48 hours,
has contacted support three times, and is a premium customer,
set priority to high...
这类规则通常应放在应用程序的确定性代码中,而非提示语里。
更合理的划分方式如下:
LLM → classify issue
Application → calculate priority
以这种方式分离各部分通常能让整个系统更易于测试。
4. 未经评估即修改提示语
假设版本1在生产环境中的表现良好。
然后有人对其进行了修改:
Classify the ticket.
变为:
Analyze and intelligently classify the ticket.
这看起来只是简单的措辞调整。
然而生产环境中的行为却可能发生显著变化。
这正是为什么提示语也需要版本控制与评估,就像对待应用程序代码一样。
5. 以为模型总会遵循指令
请记住,大语言模型本质上是概率性的。
即使精心设计的提示语,也仍可能返回并非你所要求的内容。
正因如此,一个真正的生产系统需要的不仅仅是优质的提示语——它还需要:
Prompt
+
Structured output
+
Validation
+
Monitoring
+
Fallback handling
仅依赖提示语的表述并非稳妥策略。
13. 生产环境中的提示语设计需要评估
随意试用大型语言模型与正式推出人工智能功能之间的关键差异就在于评估。
想象你有1,000份历史支持工单。
你可以从中构建一个测试集,结构如下:
200 billing
200 technical
200 account
200 general
100 ambiguous
100 edge cases
然后用不同的提示语版本在同一个测试集上运行并比较结果。
例如:
Prompt V1 Prompt V2
----------------------------------------
Category accuracy 88% 93%
Schema failures 4% 1%
Invalid values 3% 0.5%
Average latency 1.8s 2.1s
Token usage 650 820
这样一来,提示语的设计就不再具有主观性。
你不会再问:
"这个提示语是否更好?"
而是会问:
“在对我们应用真正重要的场景中,这个版本的表现是否更好?”
这是一个更具实际指导意义的疑问。
14. 权衡:更多指令与更高复杂性
并没有固定的规则表明:
“越长的提示语表现就越好。”
提示语确实有可能设计得过于复杂。
比如:
30 rules
+
20 examples
+
multiple exceptions
+
long explanations
+
repeated instructions
可能会变成维护负担而非助力。
一个有用的习惯是不断问自己:
这条指令是否真的针对我观察到的实际问题?
如果答案是否定的,那这条指令很可能就不该存在。
最佳的实际应用提示语并非内容最丰富的那个。
它能够提供恰当的上下文、合理的约束条件以及预期的行为表现,同时尽可能减少不必要的冗余内容。
15. 一个实用的心智模型
在编写提示语时,通过思考七个指导性问题会有所帮助。
1. 在这个工作流程中,模型扮演什么角色?
系统指令
2. 模型需要了解哪些信息?
上下文
3. 模型绝对不能做什么?
约束条件
4. 模型必须完成什么具体任务?
任务内容
5>我能展示预期的行为表现吗?
示例
6>响应内容应该是什么样的?
输出格式
7>我的应用程序如何判断响应是否合格?
验证方式
这七个问题结合起来便构成一个完整的框架。
这种思维模式的价值远超过记住任何单一的提示词模板。
16. 提示词工程正朝着系统设计方向发展
这或许是整个讨论中最重要的一点。
早期,使用大语言模型时通常只需回答类似这样的问题:
How can I phrase this question better?
当系统变得更为复杂时,这类问题就会转变为完全不同的问题:
What does the model need to know?
What should it be allowed to do?
What should it return?
How do I validate it?
What happens when it fails?
How do I evaluate changes?
这些已不再是措辞上的问题,而是软件工程方面的问题。
正因如此,生产级的提示词工程与其说是在寻找某种神奇的句子,不如说是在设计应用程序与具有概率行为特性的模型之间的可靠交互方式。
核心要点
从这一切中可以提炼出几条核心理念:
1. 可用于实际应用的提示语绝非仅仅一个问题。
它需要明确行为规范、提供背景信息、设定边界、阐述任务要求、给出示例,并定义输出内容应有的格式。
2. 将指令与数据分开。
模型应能一目了然地区分自己被要求执行的任务与需要处理的信息。
3. 明确的约束条件能减少猜测。
不要让模型自行决定在数据缺失、含义模糊或格式错误时该如何处理。
4>示例的存在是为了展示行为表现。
应刻意使用这些示例,尤其是在处理复杂边缘情况时更需依赖它们。
5. 结构化的输出应像 API 订阅协议那样被规范处理。
每当下游服务读取模型的响应时,都必须明确说明该响应应有的具体格式。
6. 不要仅依赖提示词作为唯一的安全检查手段。
真正的验证应通过应用程序中的模式校验及确定的业务规则来完成。
7. 将提示词视为需要评估的代码。
为它们编号,用典型测试案例进行测试,并跟踪其表现。
8. 更长的提示词并不一定就更好。
每添加的一行都应有其存在的必要。
结论
构建生产级提示词的目的并非让大型语言模型听起来更聪明。
其核心在于使信息交互更具可预测性、更透明,并且更容易集成到实际系统中。
这种转变通常表现为如下情况:
Simple question
↓
Structured instructions
↓
Clear context
↓
Explicit constraints
↓
Defined task
↓
Useful examples
↓
Structured output
↓
Application validation
↓
Evaluation + monitoring
一旦理解了这种思维方式,提示工程就不再像是反复试错的文字游戏,而更像是在为具有概率行为的组件设计 API 订阅协议。一旦你不再局限于演示,开始构建用于实际生产的系统,这种转变就显得尤为重要。
相关阅读
- 从零构建 AI 智能体:模式、ReAct 与 LangGraph — 了解 AI 智能体的核心概念——规划、工具使用、反思以及 ReAct 模式——并了解 LangChain 和 LangGraph 如何帮助手动构建此类智能体。