从“写提示”到“造系统”:对话式 Prompt 工程的结构化方法与实战架构
在上一阶段,我们理解了 Prompt 的核心理念。这一篇,我们进一步进入工程层面:
- 如何构造一个结构化 Prompt?
- 为什么“定义角色”特别有效?
- 如何用 Prompt 实现 NLU / DST / NLG?
- 纯 API 方案 vs 模块化架构,哪个更好?
- 大模型应用架构师到底在思考什么?
本文将通过一个完整的“流量套餐智能客服”案例,带你走完一条可落地的 Prompt 工程路径。
一、结构化 Prompt 的六要素
一个工程级 Prompt,通常包含六个部分:
- 角色(Role)
- 指示(Instruction)
- 上下文(Context)
- 例子(Examples)
- 输入(Input)
- 输出格式(Output Format)
可以理解为:
Role
Instruction
Output Format
Examples
User Input
这是典型的“工程四段式”或“六要素模型”。
1. 角色(Role)
例如:
- “你是一位软件工程师”
- “你是一位小学老师”
- “你是一位手机流量套餐客服”
为什么定义角色有效?
这并不是模型训练者刻意设计的功能,而是“把 AI 当人用”产生的 emergent behavior。
更深层原因在于:
大模型对输入的开头和结尾更敏感。
这一现象在斯坦福的论文
Lost in the Middle: How Language Models Use Long Contexts 中得到验证。
结论:
- 重要信息放在开头或结尾
- 角色定义在开头,相当于“收窄问题域”
- 减少歧义,提高输出稳定性
现在大模型训练语料中已经充满“你是一个 xxx”句式,因此更有效。
2. 指示(Instruction)
明确告诉模型:
- 任务是什么
- 目标是什么
- 要输出什么
例如:
你的任务是识别用户对手机流量套餐产品的选择条件。
3. 输出格式(Output Format)
这是工程级 Prompt 的关键。
不要让模型“随便回答”,要:
- 强约束 JSON 结构
- 明确字段类型
- 指明允许的取值范围
- 禁止输出 null
例如:
只输出用户提及字段
不要输出值为 null 的字段
确保可以被 json.loads 解析
这一步直接决定了系统可控性。
4. 例子(Few-shot Learning)
例子极其重要。
学术叫:
- one-shot learning
- few-shot learning
- in-context learning
工程结论:
给例子,输出稳定性显著提升。
例如:
便宜的套餐:
{"sort":{"ordering":"ascend","value":"price"}}
100G以上流量最便宜的套餐:
{"sort":{"ordering":"ascend","value":"price"},"data":{"operator":">=","value":100}}
例子越贴近真实业务,效果越稳定。
二、智能客服案例:对话系统基本架构
我们用一个套餐推荐系统作为实战案例。
套餐产品
| 名称 | 流量(G/月) | 价格(元/月) | 适用人群 |
|---|---|---|---|
| 经济套餐 | 10 | 50 | 无限制 |
| 畅游套餐 | 100 | 180 | 无限制 |
| 无限套餐 | 1000 | 300 | 无限制 |
| 校园套餐 | 200 | 150 | 在校生 |
对话系统的经典五模块
| 模块 | 作用 |
|---|---|
| ASR | 语音转文本 |
| NLU | 语义理解 |
| DST | 状态追踪 |
| Policy | 策略决策 |
| NLG | 自然语言生成 |
核心思想:
- 把自然语言 → 结构化语义
- 用结构化语义 → 决策策略
- 用策略 → 生成自然语言回复
三、用 Prompt 实现 NLU
我们定义任务:
识别用户在 name / price / data / sort 上的意图。
关键设计:
- 强约束 JSON
- 明确 operator 取值
- 明确字段范围
- 禁止 null 字段
为什么这一步很重要?
因为自然语言输出:
“用户可能想要一个比较便宜且流量多的套餐。”
这种话无法做程序判断。
而结构化输出:
{
"price":{"operator":"<=","value":200},
"sort":{"ordering":"descend","value":"data"}
}
才可以直接驱动业务逻辑。
四、用 Prompt 实现 DST(多轮状态管理)
DST 的核心问题:
用户第二句话可能依赖第一句话。
例如:
第一轮:
100G以上有什么?
第二轮:
200元以内的呢?
这时状态应是:
data >= 100
price <= 200
实现方式有两种:
方案一:用 Prompt 实现 DST
优点:
- 开发量小
- 快速上线
缺点:
- 调优复杂
- 长上下文成本高
- 迁移成本大
方案二:NLU 用 Prompt,DST 用程序维护
优点:
- 可控性强
- 易于调试
- 成本低
缺点:
- 需要设计冲突合并逻辑
工程上更推荐第二种。
五、实现完整客服机器人
我们把模块串起来:
用户输入
↓
NLU(Prompt 解析 JSON)
↓
DST(更新状态)
↓
DB(检索)
↓
Policy(决定推荐)
↓
NLG(生成自然语言)
这是典型的:
大模型 + 传统系统的混合架构
而不是“全交给模型”。
六、纯 OpenAI API 方案 vs 模块化方案
纯 OpenAI 方案:
system: 放套餐信息
user: 直接问
assistant: 直接回答
优点:
- 简单
- 开发快
缺点:
- 可控性差
- 不易调试
- 成本高
- 复杂逻辑难维护
模块化方案:
- NLU 用 Prompt
- DST 程序维护
- DB 精确查询
- NLG 用 Prompt
优点:
- 可控
- 易扩展
- 可调优
- 成本更低
七、Prompt 工程的一个重要原则
一切问题,优先尝试用 Prompt 解决。
很多原本要写 200 行正则的逻辑,用 Prompt + JSON 输出可能只需要 5 行代码。
这就是:
四两拨千斤
八、加入语气约束与统一口径
例如:
遇到类似问题,请参照以下回答:
问:流量包太贵了
答:亲,我们都是全省统一价哦。
这就是:
用例子控制语气
而且可以动态加入例子(未来可结合 Embedding / RAG)。
九、纯 API 是否更好?
关键不在“简单”,而在三个问题:
1️⃣ 怎样更准确?
答:
- 让更多环节可控
- 用结构化输出
- 用程序做逻辑判断
2️⃣ 怎样更省钱?
答:
- 减少 Prompt 长度
- 避免重复上下文
- 用短 JSON 代替长自然语言
3️⃣ 怎样更好维护?
答:
- Prompt 模板化
- 模块解耦
- 版本可管理
- 状态与生成分离
十、大模型应用架构师在想什么?
真正的关注点是:
- 控制生成的概率空间
- 控制系统成本
- 控制风险
- 控制复杂度
本质是:
用大模型做“智能”,
用传统程序做“确定性”。
十一、终极理解:Prompt 工程不是写话术
它是:
- 输入建模能力
- 结构化表达能力
- 概率分布控制能力
- 系统架构设计能力
真正的高手不是“会写 Prompt”,而是:
知道什么时候该用 Prompt,
什么时候不该用。