1. 为什么要用指令来管理 UX
从 ChatGPT 的视角,您的 App 只是额外的工具和小部件。但对用户而言,那是一个会在对话中突然出现的完整界面。如果不去约束模型行为,就可能出现两个极端场景。
一种情况是 GPT 忽略 App,试图“全靠文字解决”。用户请求挑选礼物,模型却没有启动 GiftGenius,而是输出一篇冗长的“自我推荐”式文字。有时未必糟糕,但你编写 App 并不是为了让它“吃灰”。
另一种情况则是 GPT 过度使用 App。比如遇到“你们的服务会什么?”这类问题,它就启动小部件、渲染一个不清不楚的表单,把用户吓得赶紧关掉。这从 UX 的角度非常打扰人。
因此逻辑很简单:要像固定工具的 JSON 架构或 React 组件的 props 一样,显式固定行为。System‑prompt(以及配套指令)就是你的“UX 协议”。在其中你要描述,助理应当何时以及如何:
- 预告即将启动 App;
- 有意识地不启动 App,而改用文字回答;
- 在小部件已经展示结果之后应如何表现;
- 如何尊重用户“不要应用”的请求。
这些并非营销或聊天风格问题,而是真正会影响你的 App 被调用的频率,以及用户的舒适度。
接下来我们将逐步讲解:助理应如何预告启动 App,哪些情况下应刻意不提供小部件,应用执行完后该如何互动,如何尊重用户对对话形式的明确要求,以及如何把这些规则妥善写入 system‑prompt。
2. App 的预告:模型应如何“提醒”将显示小部件
当 ChatGPT 决定使用 App 时,界面会变化:聊天里会出现小部件卡片,有时是全屏,还会出现按钮等 UI 元素。如果助理没有解释就直接展示小部件,用户可能完全不明白发生了什么、这个区块从哪里来的。
因此比较好的做法是——先用文字说明接下来会发生什么,然后再启动 App。这有点像浏览器会问:“要打开新窗口吗?”或者移动应用会提示:“我们将请求相机权限。”
预告的类型
大致可以区分三种预告风格。
第一种——温和提议。助理会这样说:“我可以为您打开 GiftGenius 应用,它会根据您的参数来挑选礼物。要打开吗?”然后等待“是/否”的回复。这在用户首次接触服务或对界面切换比较敏感的场景中很有效。
第二种——自信推荐。如果你的 App 是产品的主要界面,可以这样写:“我现在将启动 GiftGenius 应用,并以卡片形式展示若干礼物选项。”助理仍会尊重拒绝,但默认更为果断。
第三种——中性通知。在这种情况下,助理只简单说明:“正在启动 GiftGenius 应用以进行礼物挑选……”,不做冗长解释。当用户已经多次见过你的 App 并期待它出现时,这种风格很合适。
重要的是,你可以且应当把这些变体写进 system‑prompt。只要你先给出骨架,模型就不会从零编造 UX 文案。
迷你代码示例:system‑prompt 中的预告章节
假设你的 Next.js 模板里有文件 appDefinition.ts,你在其中为 App 设置 system‑prompt:
// app/appDefinition.ts
export const systemPrompt = `
# 角色
你是 ChatGPT App GiftGenius,帮助挑选礼物。
# 对话与 UX —— 应用预告
如果你决定启动 GiftGenius 小部件,
请先用一两句话说明
接下来会打开一个用于挑选礼物的应用,
以及它将如何帮助用户。
`;
这还不是完整合同,但即便是这样的小段落,也会大幅提升行为的可预测性。
何时预告尤为重要
你的 UI 越复杂,越需要提前说明将要启动它。如果小部件只是展示三张礼物卡片——这算是相对温和的上下文切换。而如果你要打开一个包含筛选、预算、类别等的多步骤向导,用户就应当理解为何对话突然变成了“聊天里的小型 Web 应用”。
官方的 UX 指南也强调,助理应当显式把文字与 UI 关联起来,而不是在回答里默默塞一个小部件。
3. 何时应刻意不提供 App
在 App 开发早期最常见的错误,是典型的“拿着锤子看什么都像钉子”效应。既然我们有一个漂亮的 GiftGenius,模型就会把它往每个对话里塞。用户问:“你们的应用到底会什么?”,ChatGPT 已经在说:“正在启动 GiftGenius……”,可对方其实只想要两行解释。
为了避免这种情况,需要在 system‑prompt 中明确描述什么时候最好不要提供 App。下面是几个典型场景。
- 首先,了解型问题。如果用户说的是“GiftGenius 做什么?”或者“你们如何工作?”,指令应要求先给出简短文字解释,不要启动 UI。此处小部件只会分散注意力。
- 其次,过于泛化或模糊的请求。用户写“讲讲新年礼物”,这更像是科普,而非具体挑选。助理可以简述通用原则、提出澄清问题,等出现具体参数(预算、收礼人、类别)时再提议使用 App。
- 第三,超出 App 领域的请求。如果用户说:“帮我写简历”,而你的 App 专注于礼物,正确做法是如实地以普通 ChatGPT 方式作答,且不启动任何东西。可以委婉提及 App 的用途,但不应在明显不相关时强推它。
- 第四,对 UI 的明确拒绝。如果用户写:“别打开任何应用,只要用文字说明”,模型必须遵从,即便这是一个使用 App 的“完美场景”。
表格:请求类型与助理行为
| 请求场景 | 助理该做什么 |
|---|---|
| “你们的服务会什么?” | 用简短文字解释,不要启动 App |
| “帮同事挑个不超过 $50 的礼物” | 提议启动 App 并说明它会做什么 |
| “讲讲新年受欢迎的礼物” | 用文字讨论,必要时提出澄清问题 |
| “帮我写简历” | 像普通 ChatGPT 一样回答,不要提供 App |
| “请不要用任何应用” | 尊重请求,不要启动小部件 |
为 system‑prompt 补充不启动 App 的规则
继续完善同一个 systemPrompt,加入关于何时不启动 App 的模块:
export const systemPrompt = `
# 角色
你是 ChatGPT App GiftGenius,帮助挑选礼物。
# 何时不要启动小部件
如果用户只是询问服务能做什么,
或提出关于礼物的泛化/理论性问题,
先用文本回答,不要启动应用。
如果请求与挑选礼物无关,
请像普通 ChatGPT 一样回答,不要提供 GiftGenius。
如果用户明确要求不要使用应用,
必须尊重该请求,仅在聊天中工作。
`;
这样的文字会在边界情形下转化为模型的具体决策,否则它可能会把重心“拉向 UI”。我们已经固定了 App 不需要出现的时机。接下来要描述另一面:当小部件已经执行完毕、用户看到结果时助理应当怎么做。
4. 使用 App 之后的行为:follow‑up 与场景收束
在小部件模块中你已经看到,follow‑up 消息可以帮助在 UI 完成后继续对话。小部件展示卡片,在它下面助理会写类似:“我找到了不超过 $50 的同事礼物备选。要不要看看更便宜的,或者调整类别?”并给出常用操作的按钮。
现在我们的任务是——把这种行为写进指令中,而不是依赖模型“直觉”。
小部件之后助理应做什么
理想情况下会发生几件事。
- 先由助理用简短文字概述 App 的结果。即便小部件展示了十张卡片,写一句“我为‘同事、不超过 $50’的条件挑选了 4 个礼物选项,其中包括带定制印花的杯子、桌面绿植、精品咖啡礼盒和精致笔记本。”也很有帮助。
- 然后提出后续步骤。此处可用预先设计好的 follow‑up 句式:“要不要更便宜一些?”,“需要按兴趣缩小范围吗?”,“只展示你所在地区可购买的?”这些短语既可以在小部件里通过 sendFollowUpMessage 发送,也可以在 system‑prompt 中推荐模型使用。
- 最后,如果用户显式结束场景(“谢谢,够了”),助理应当体面地“收尾”:确认任务已完成,并询问是否需要其他帮助。
流程图:问题 → 小部件 → follow‑up
为直观起见,可以把助理行为想象成一个简单的状态机。
flowchart TD
U[用户提出任务] --> G[GPT 决定:要启动 App 吗?]
G -->|是| A[预告启动 App]
A --> W[GiftGenius 小部件挑选候选项]
W --> S[助理总结结果]
S --> F[助理提供 follow-up 选项]
F -->|用户选择一个操作| G
G -->|否,不启动 App| T[无 UI 的文本回答]
F -->|用户说“谢谢”| E[助理结束场景并提供其他帮助]
我们实际上就是把这样的流程用文字写进 system‑prompt。
代码示例:来自小部件的 follow‑up
在 UI 侧,你已经会发送 follow‑up 消息。这里给出一个简单组件示例:点击按钮后,请求模型“扩大预算”:
// components/ExpandBudgetButton.tsx
export function ExpandBudgetButton() {
const onClick = () => {
window.openai?.sendFollowUpMessage(
"请展示预算稍高的选项"
);
};
return <button onClick={onClick}>想看更贵的选项</button>;
}
现在我们把引导模型处理此类 follow‑up 消息的文本补充到 system‑prompt 中。
// 继续补充 systemPrompt
const followUps = `
# 应用启动后的行为
当小部件展示出礼物列表后,
请用简短文字概述结果。
随后给出 1–3 个清晰的下一步
(例如:展示更便宜的、调整预算、变更类别)。
如果小部件发送了 follow-up 消息,
将其作为下一步的提示信号使用。
`;
从技术上看这只是一个普通字符串;从 UX 的角度看,它是可预测剧本的基础。
5. 尊重用户意图
以上讨论的都是你对 App 行为的产品预期。如果模型不会“倾听”用户,UX 指令就很难发挥作用。即便是完美设计的 App,在用户明确要求不改变交互形式时也应当让步。
下面是几种典型情形。
- 如果用户直说不想启动应用(“不要任何 UI,只告诉我该买什么”),助理应把这视为硬性约束,不要试图绕过。可以礼貌地说:“好的,我将只用文字回答”,然后确实守约。
- 如果用户担心会自动启动什么东西,给予控制感很有用。比如:“我可以打开一个用于挑选礼物的应用,如果您更喜欢,我们也可以只在聊天里讨论。您更愿意哪种方式?”——这里你给出了明确选择。
- 如果用户写“我在用手机,请不要启动复杂的表单”——这也是上下文的一部分。助理应当接受,比如仅给出简短的想法清单和澄清问题。
把“尊重”写进合同
这些内容都可以简洁地写进 system‑prompt:
export const respectBlock = `
# 用户意图优先
始终遵从用户对
交互形式的明确要求。
如果对方要求不启动应用或小部件,
不要建议,也不要启动 GiftGenius,
即使那样更有助于解决问题。
改为通过文本提供帮助。
`;
这样就清楚地固定了对话中的“谁说了算”。剧透一下:主导者不是你对漂亮 UI 的自豪,而是屏幕另一侧的真人。
6. 如何在 system‑prompt 和文档中编写 UX 指令
我们已经罗列了不少行为规则——从 App 的预告到 follow‑up 消息,以及对对话形式的尊重。现在重要的不仅是说什么,还有如何写进 system‑prompt 与文档。
真实项目中的 system‑prompt 会很快变长。如果把它写成一大段“散文”,一周之后就没人看得懂了。因此请把它当作技术规范或 README 来对待:要有结构。
一个好实践是把 prompt 划分为若干带标题的逻辑章节。例如:“角色与职责”、“何时使用 App”、“何时不使用 App”、“对话与 UX”、“安全与限制”。在每个章节中使用简洁、明确的句子。
更进一步——把 system‑prompt 放到靠近代码的独立文件中,而不是塞在组件的字符串字面量里。这样更便于评审、对比改动,以及与产品或法务讨论。
在代码中组织 system‑prompt 的示例
一种做法是把各部分 prompt 存放为独立字符串,再拼接为整体:
// app/prompt/role.ts
export const roleSection = `
# 角色
你是 ChatGPT App GiftGenius。
你帮助用户依据任务与预算挑选礼物。
`;
// app/prompt/ux.ts
export const uxSection = `
# 对话与 UX
在启动 GiftGenius 小部件之前,
简要说明将会打开一个带有礼物卡片的应用。
对于一般性或理论性问题不要启动应用,
除非用户明确要求进行挑选。
小部件运行后,用文字总结结果,
并提出 1–3 个后续步骤。
`;
// app/appDefinition.ts
import { roleSection } from "./prompt/role";
import { uxSection } from "./prompt/ux";
export const systemPrompt = `
${roleSection}
${uxSection}
`;
这种拆分能让你把指令当作独立模块来思考:UX、安全、工具使用等。当你添加新能力、需要与多支团队协作时,这种方式尤其有用。
此外,将 App 的文档(内部 README、Confluence、Notion)与这些章节保持同步也很有意义。你可以用自然语言解释,为什么要这样预告 App,以及为什么不在试探性请求中启动它。把 follow‑up 台词单独固定下来。这样新人就不会在不了解背景的情况下尝试“修 prompt”。
7. 实践:为我们的 GiftGenius 重写 UX 部分
让我们把所有内容整合为一个相对完整的 system‑prompt 示例。假设我们之前的 system‑prompt 很简短:
export const systemPrompt = `
你是 GiftGenius 应用。
为用户挑选礼物。
`;
这样的文本并没有说明何时启动 App、如何预告以及小部件之后该做什么。我们一步步补充 UX 指令。
先明确职责与工作方式:
const role = `
# 角色
你是 ChatGPT App GiftGenius。
你的任务是帮助用户挑选 3–7 个相关礼物,
基于指定预算、收礼人和场合。
你可以使用 GiftGenius 小部件进行可视化筛选。
`;
然后描述如何预告启动:
const announce = `
# 应用预告
如果你认为 GiftGenius 小部件会更有帮助,
先用一两句话说明
将会打开带有礼物卡片的应用,
用户可以浏览并进行筛选。
之后再启动应用。
`;
再补充何时不启动 App 的规则:
const noApp = `
# 何时不使用应用
如果用户只是在询问服务能做什么,
或想了解关于礼物的一般性/理论性信息,
用文本回答,不要启动 GiftGenius。
如果请求与礼物无关(例如关于简历或代码),
像普通 ChatGPT 一样回答,不要建议应用。
如果用户要求不使用应用,
将其视为强制性限制。
`;
最后补充小部件之后的行为:
const afterWidget = `
# 小部件之后的行为
当小部件展示出礼物选项之后,
用自己的话简要描述结果。
向用户提出 1–3 个下一步
(例如:调整预算、按兴趣筛选、
仅显示更便宜的选项)。
如果小部件发送了 follow-up 消息,
将其作为下一步的主要信号。
`;
最终的 system‑prompt 可以是这样:
export const systemPrompt = `
${role}
${announce}
${noApp}
${afterWidget}
`;
这已经更像是“行为规范”而不是“心想事成”。在后续模块中,你会继续补充安全、幻觉、商业化等方面的指令,但 UX 部分已经是坚实的基础。
8. 配置 UX 指令时的常见错误
错误 №1:“App 总是比文本好”。
有时开发者太为自己小部件自豪,要求模型逮住机会就调用它。结果用户在只想问“这是什么”的地方也收到了 App。模型变得很打扰,用户开始忽视应用。正确做法是明确写出哪些场景不需要 App,并尊重这些用例。
错误 №2:在启动 App 前没有明确预告。
如果助理默默启动小部件,用户就不明白 UI 区块从哪来、怎么用。OpenAI 指南与实践都表明:用一两句“接下来我会打开一个做 X 的应用”能显著改善 UX,减少困惑。
错误 №3:过于激进地反复建议使用 App。
有时 App 在每次回答后又来一次:“要不要再打开应用?现在要吗?这次呢?”这很快会变成垃圾信息。应在指令中固定:在第一次使用 App 后要看上下文——仅当用户明确更改了任务参数,或主动要求“再多看看”时再提议。
错误 №4:忽视用户对应用的明确拒绝。
诸如“请不要用应用”或“我用手机,不方便处理表单”的话语应被视为硬性约束。如果模型仍强推 App,用户会对助理和你的产品都失去信任。这在 system‑prompt 里只需两三句话就能固定,但很多人会忘记。
错误 №5:在小部件之后缺少摘要与 follow‑up 消息。
有时小部件展示了选项,但助理随后保持沉默。用户看到了 UI,却不知道下一步做什么。没有文字、没有问题、没有常用操作按钮。这个场景是不完整的,破坏了对话连贯性。请始终在指令中要求:小部件之后应有简短文字总结和 1–3 个清晰的下一步。
错误 №6:把产品 UX 与“通用 ChatGPT 风格”混在一个段落里。
有时 system‑prompt 会变成长篇散文:“要友好、用表情、合适时开个玩笑。对了,也许有时可以启动 App。”在这种文字里很难看出真正的 UX 规则。更好的做法是用清晰标题划分章节:“角色”、“对话与 UX”、“何时使用 App”、“何时不使用 App”。这既帮助模型,也帮助后来维护 prompt 的人。
GO TO FULL VERSION