从“写提示”到“造系统”:对话式 Prompt 工程的结构化方法与实战架构

18 阅读6分钟

从“写提示”到“造系统”:对话式 Prompt 工程的结构化方法与实战架构

在上一阶段,我们理解了 Prompt 的核心理念。这一篇,我们进一步进入工程层面:

  • 如何构造一个结构化 Prompt?
  • 为什么“定义角色”特别有效?
  • 如何用 Prompt 实现 NLU / DST / NLG?
  • 纯 API 方案 vs 模块化架构,哪个更好?
  • 大模型应用架构师到底在思考什么?

本文将通过一个完整的“流量套餐智能客服”案例,带你走完一条可落地的 Prompt 工程路径。


一、结构化 Prompt 的六要素

一个工程级 Prompt,通常包含六个部分:

  1. 角色(Role)
  2. 指示(Instruction)
  3. 上下文(Context)
  4. 例子(Examples)
  5. 输入(Input)
  6. 输出格式(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/月)价格(元/月)适用人群
经济套餐1050无限制
畅游套餐100180无限制
无限套餐1000300无限制
校园套餐200150在校生

对话系统的经典五模块

模块作用
ASR语音转文本
NLU语义理解
DST状态追踪
Policy策略决策
NLG自然语言生成

核心思想:

  1. 把自然语言 → 结构化语义
  2. 用结构化语义 → 决策策略
  3. 用策略 → 生成自然语言回复

三、用 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 用程序维护

优点:

  • 可控性强
  • 易于调试
  • 成本低

缺点:

  • 需要设计冲突合并逻辑

工程上更推荐第二种。


五、实现完整客服机器人

我们把模块串起来:

用户输入
  ↓
NLUPrompt 解析 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 模板化
  • 模块解耦
  • 版本可管理
  • 状态与生成分离

十、大模型应用架构师在想什么?

真正的关注点是:

  1. 控制生成的概率空间
  2. 控制系统成本
  3. 控制风险
  4. 控制复杂度

本质是:

用大模型做“智能”,
用传统程序做“确定性”。


十一、终极理解:Prompt 工程不是写话术

它是:

  • 输入建模能力
  • 结构化表达能力
  • 概率分布控制能力
  • 系统架构设计能力

真正的高手不是“会写 Prompt”,而是:

知道什么时候该用 Prompt,
什么时候不该用。