CodeGym /课程 /ChatGPT Apps /从指令到工具与元数据的设计:发现与路由

从指令到工具与元数据的设计:发现与路由

ChatGPT Apps
第 5 级 , 课程 4
可用

1. 为什么没有好的 tools 和元数据,仅靠指令是不够的

需要先承认一个不太令人愉快的事实:模型看不到你的代码。它不知道你的 Next.js 里有哪些控制器、TypeScript 里有哪些函数,也不知道你在推荐服务里堆叠了哪些神奇的启发式。

它通过以下几个接口“看见”你的 App:

  1. System‑prompt(角色契约)。
  2. 工具描述:名称、descriptioninputSchemaoutputSchema、注解等。
  3. 应用本身的元数据:名称、图标、短/长描述、类别、conversation starters 等等。

在处理请求时,模型会查看对话上下文和这些元数据,以决定:

  • 是否应该推荐某个 App;
  • 如果应该——在可用的 App 中该选哪一个;
  • 如果已选定 App——该 App 的哪个工具最适合当前请求。

在模块 5 的前一部分里,我们处理的是可以“用语言告诉”模型的内容——system‑prompt 与 UX 指令。现在转向它除了文本之外还能看到的东西:tools 与元数据。

所以模块 5 的任务其实是双重的。你先在 system‑prompt 中表述“这个 App 应该做什么、如何表现”,然后通过 tools 与元数据的设计,把这些要求包装成模型能够真正使用的形式——包括用于 discovery 与路由。

可以这样给自己一个比喻:system‑prompt 是宪法,而 tools 与元数据就是法律与周边的行政体系:表单、数据库模式等等。只停留在宪法层面,是走不远的。

2. 分解:“一项任务—一个 tool”,但要理性

先谈最让人头疼的问题:到底要做多少个工具,如何划分。

直觉上的原则:一个工具——一个清晰的任务。这会大幅降低模型的选择难度:它面对的不是一个巨无霸函数 do_everything,而是若干个命名良好的小动作。

针对 GiftGenius,我们可以有如下基础工具:

  • profile_to_segments——把收礼人的自由描述(年龄、兴趣、关系、上下文)转成规范化的分段,比如 "tech""fitness""gamer"
  • recommend_gifts——基于分段、预算、地区/语言/本地化和场合推荐礼物 id 列表。
  • get_gift——根据 id 获取选定礼物的完整卡片(描述、媒体、SKU/变体)。
  • (可选)similar_gifts——基于某个已选礼物,再给出 3–5 个相似选项。

理论上可以合成一个 gift_tool,用 mode: "profile_to_segments" | "recommend" | "details" | "similar" 来切换,但这会给你和模型都徒增复杂度:描述会拉成长篇大论,inputSchema 膨胀,而在选择工具时模型缺少清晰锚点。

反模式:God Tool

想象这样的方案:

server.registerTool(
  "gift_tool",
  {
    description: "与礼物相关的多种操作。",
    inputSchema: { /* 50 个字段和标志 */ },
  },
  async ({ input }) => { /* 根据 mode 的超大 switch */ }
);

在模型“脑海里”,这就像是“有个抽象的礼物工具,至于怎么用再说”。这会降低选择的准确度,妨碍 discovery,也让你的维护更困难。

但走向另一个极端——为每个小动作都做一个微型工具,堆到 50 个——也不好。每增加一个工具,它就会进入上下文,占用模型注意力,提高路由出错的风险。文档明确提醒:太多细碎工具会降低质量,尤其在描述互相重叠时。

一个实用的规则:

  • 凡是用户在流程里感知为一个“步骤”的(例如基于画像的首次礼物推荐),都适合做成单独的 tool;
  • 凡是严格在这个步骤内部完成、没有独立意义的(例如计算评分或记录卡片浏览日志),最好留在工具实现内部。

假设你遵循该原则,把场景切分到了 2–4 个工具。接下来一个关键问题是——如何描述这些 tools 的输入,让模型无需猜测就能使用。我们从这里开始。

3. 将 use‑cases 投影到 Input Schema

现在拿一个具体的 use case,老老实实看看这个工具实际上需要哪些数据。

场景:送礼人赶在最后期限内,需要为 25 岁、喜欢足球和桌游的朋友挑 5–7 个主意,预算不超过 $50。

从 jobs‑to‑be‑done 的角度,GiftGenius 的推荐内核任务是把选择范围缩小到一个短列表,并降低“选错礼物”的焦虑。在聊天层面,助手需要:

  • 收礼人的基本信息(年龄、性别、与送礼人的关系);
  • 兴趣/爱好;
  • 预算与货币;
  • 场合(生日、周年、新年等);
  • 可选——国家/城市,用于配送筛选。

在 GiftGenius 的架构中,这被拆成两个步骤:

  1. profile_to_segments(input) 接受“原始”数据(年龄、兴趣、文本描述),并把它们转换为规范化的分段,便于后续处理。
  2. recommend_gifts(segments, budget, locale, occasion) 根据分段与预算,从目录中挑选具体的礼物 id。

从 ChatGPT ↔ MCP 的契约角度,我们需要重点描述第二步——也就是 recommend_gifts 的 schema,因为这个工具会在大多数选礼场景中被调用。

同时不必一开始就向用户索要全部信息:模型可以通过追问补齐(“大概预算是多少?”)。因此画像中的部分字段可以是可选的;但等到要调用 recommend_gifts 时,就应该有规范化的参数集了。

示例:TypeScript + JSON Schema(针对 recommend_gifts

在 TypeScript 的 MCP 服务器中,可以这样写:

// apps/mcp/server.ts
import { McpServer } from "@openai/mcp-server";

const server = new McpServer();

server.registerTool(
  "recommend_gifts",
  {
    title: "礼物推荐",
    description:
      "当需要基于收礼人分段、预算、地区/语言/本地化和场合来推荐礼物时,使用此工具。",
    inputSchema: {
      type: "object",
      properties: {
        segments: {
          type: "array",
          description:
            "收礼人的分段列表,例如 ['tech', 'football_fan']。通常来自 profile_to_segments。",
          items: { type: "string" },
          minItems: 1
        },
        budget: {
          type: "object",
          description:
            "用户货币下的礼物预算区间(最小/最大)。",
          properties: {
            min: {
              type: "number",
              minimum: 0,
              description: "用户愿意支付的最低金额。"
            },
            max: {
              type: "number",
              minimum: 0,
              description: "用户愿意支付的最高金额。"
            },
            currency: {
              type: "string",
              minLength: 3,
              maxLength: 3,
              description: "三字母货币代码(例如,USD、EUR、RUB)。"
            }
          },
          required: ["min", "max", "currency"]
        },
        locale: {
          type: "string",
          description:
            "BCP‑47 格式的用户本地化(例如 'ru-RU' 或 'en-US')。"
        },
        occasion: {
          type: "string",
          description:
            "送礼场合,例如 'birthday'、'new_year'、'anniversary'。"
        }
      },
      required: ["segments", "budget", "locale", "occasion"]
    }
  },
  async ({ input }) => {
    // 这里先不做复杂逻辑,返回一个占位结果
    return {
      content: [
        {
          type: "text",
          text: `正在根据分段 ${input.segments?.join(
            ", "
          )} 在预算 ${input.budget?.min}–${input.budget?.max} ${input.budget?.currency} 内挑选礼物...`
        }
      ],
      structuredContent: {}
    };
  }
);

注意以下几点。

第一,我们积极使用类似 enum 的约束与清晰的描述。即使形式上只是字符串,description 也会向模型暗示期望的取值,这显著提升它正确填写参数的概率。与其放一个模糊的 "场合": "类似生日的东西",不如给出干净的 occasion: "birthday"

第二,字段描述不是写给“团队的人”看的,而应当直给模型:这个字段是什么、典型取值是什么、能否给个示例。Apps SDK 文档的作者明确建议为每个参数提供清晰的人类可读描述与示例。

输入 schema 中不该出现的内容

常见的“寄生字段”,很多人会忍不住塞进去:

  • 内部标识(tenantIdinternalSegment),这些完全可以在服务器端自行填充;
  • 模型不可能知道的东西(例如 deploymentRegion)——这是你的职责范围;
  • 重复对话历史的字段(例如 userPrompt):模型已经能看到原始消息,不要强迫它复制粘贴。

Input Schema 只应包含模型需要决定并填写的内容,而不是一个“装一切”的大口袋。

4. Output Schema:不仅是数据,也是语义

在 Apps SDK 中,工具的结果会以 role: tool 的消息形式回到对话里。之后如何处理交给模型:如何组织答案、要不要追问、是否打开小部件等。因此,输出 schema 的设计和输入一样重要。

有两种做法。

“原始数据”变体如下:

{
  "items": [
    { "id": "GIFT_1" },
    { "id": "GIFT_2" }
  ]
}

模型只能看到一串 id,不知道这些选项为何出现、总共多少候选、哪些是更好的。它可能会“编造”点什么,但怪异的概率更高。

“语义丰富”的变体:

{
  "items": [
    {
      "id": "GIFT_1",
      "score": 0.92,
      "reason": "与 'football_fan' 分段高度匹配,且在预算内。"
    },
    {
      "id": "GIFT_2",
      "score": 0.81,
      "reason": "适合桌游爱好者,价格略接近预算上限。"
    }
  ],
  "meta": {
    "totalCandidates": 27,
    "returned": 5,
    "segmentsUsed": ["football_fan", "board_games"],
    "budget": { "min": 20, "max": 50, "currency": "USD" },
    "advice": "建议先从 score 较高且理由清晰的选项开始。"
  }
}

这样模型就能如实解释为什么是这些礼物,并据此组织追问:“我找到了 27 个候选,展示其中 5 个最佳。这是它们入选的原因。”

示例:为 recommend_gifts 描述 Output Schema

把结果 schema 加进工具描述中(即使技术上不是必填项,也最好写上——它是和模型的契约的一部分):

const recommendGiftsOutputSchema = {
  type: "object",
  properties: {
    items: {
      type: "array",
      items: {
        type: "object",
        properties: {
          id: { type: "string", description: "目录中的礼物 ID。" },
          score: {
            type: "number",
            description: "与画像的匹配度评分(0..1)。"
          },
          reason: {
            type: "string",
            description:
              "简短解释为什么该礼物合适(可由后端生成)。"
          }
        },
        required: ["id", "score"]
      },
      description: "带有匹配度评分的推荐礼物列表。"
    },
    meta: {
      type: "object",
      properties: {
        totalCandidates: {
          type: "integer",
          description: "目录中找到的候选总数。"
        },
        returned: {
          type: "integer",
          description: "本次调用返回了多少个礼物。"
        },
        advice: {
          type: "string",
          description:
            "总体建议:例如建议从哪类礼物开始。"
        }
      }
    }
  },
  required: ["items"]
};

并在实现中使用该 schema:

server.registerTool(
  "recommend_gifts",
  {
    title: "礼物推荐",
    description:
      "当需要基于分段与预算挑选 3–7 个礼物时使用。返回礼物 id 和匹配度评分;若需查看详情请调用 get_gift。",
    inputSchema: /* 如上 */,
    // 并非总是要求显式声明 outputSchema,但作为文档非常有用:
    // outputSchema: recommendGiftsOutputSchema
  },
  async ({ input }) => {
    const recommendations = await recommendFromCatalog(input); // 我们的业务逻辑

    return {
      content: [
        {
          type: "text",
          text: `我找到了 ${recommendations.items.length} 个合适的主意。现在展示最佳选项。`
        }
      ],
      structuredContent: {
        items: recommendations.items,
        meta: {
          totalCandidates: recommendations.meta.totalCandidates,
          returned: recommendations.items.length,
          advice: recommendations.meta.advice
        }
      }
    };
  }
);

我们做了两件事:给模型提供最小化的用户可见文本,同时附上语义化的 JSON,便于模型继续推进对话与追问。

与此同时,get_gift 会基于 id 拉取完整卡片(名称、媒体、SKU 等),GiftGenius 的小部件将其渲染成礼物卡片。

5. 工具的命名与描述:discovery 的基础

接下来是最“香”的部分:工具的名称与描述如何影响模型是否会调用它们。

元数据的文档与最佳实践建议:

  • 使用以行动为导向的命名:profile_to_segmentsrecommend_giftsget_giftsimilar_gifts,而不是 tool1searchdo_stuff
  • 以 “Use this when…”/“当……时使用该工具” 的句式开头,描述触发场景与限制(“不要用于……”)。

这和你的 golden prompt set 直接相关。描述中的措辞应与真实的用户请求有交集。如果在描述中写着“当用户按预算与收礼人兴趣请求推荐礼物时使用”,而在 golden prompt 里有“给爱打游戏的朋友推荐不超过 $50 的礼物”,模型就更容易把请求和该工具匹配起来。

一个好的工具描述示例

再看一个 GiftGenius 的附加工具——similar_gifts。它在用户选定某个礼物后,基于该礼物扩展出相似的主意:

server.registerTool(
  "similar_gifts",
  {
    title: "相似礼物",
    description:
      "当用户已选定某个礼物并希望再看一些相似选项时使用此工具。不要用于从零开始的首次挑选——那请使用 recommend_gifts。",
    inputSchema: {
      type: "object",
      properties: {
        giftId: {
          type: "string",
          description:
            "来自上一次候选集的礼物标识,需要基于它查找相似选项。"
        },
        limit: {
          type: "integer",
          description:
            "返回多少个相似礼物(默认 3–5)。",
          minimum: 1,
          default: 5
        }
      },
      required: ["giftId"]
    }
  },
  async () => {
    /* ... */
  }
);

要点:

  • 明确指出何时应使用该工具、何时不应使用。
  • 描述中包含“相似选项”“已选定礼物”等词,这些词会高频出现在真实用户请求中。
  • 避免与 recommend_gifts 的适用范围重叠——这能降低工具之间在选择时的竞争。

一个不好的描述

description: "处理礼物。"

模型几乎无法从这样的描述中获取任何信息。它只有在“走投无路”时才可能“盲抽”这个工具。

6. 注解与 hints:如何提示模型动作的严肃性

工具不仅有名称与 schema,还有注解,用于提示 ChatGPT 该动作的危险性/重要性,以及是否需要征得用户确认。在 Apps SDK 规范中有多种 hint,比如 readOnlyHintdestructiveHintopenWorldHint 等。

  • readOnlyHint: true 表示工具只读不改状态。助手可略过多余确认,更自由地调用它。
  • destructiveHint: true 表示工具可能删除或不可逆修改内容,需要向用户显示明确的“你确定吗?”。
  • openWorldHint: true 表示动作会影响外部世界(发帖到社交媒体、在账号外创建记录等),同样需要提醒。

最低级别——无需确认

如果你有 public readonly tools,就很有必要标注 readOnlyHint: true。例如:

"annotations": {
  "readOnlyHint": true,
  "destructiveHint": false,
  "openWorldHint": false
}

这样的工具可以在 GPT 侧无需额外对话式确认即可调用。

一次确认

若你的工具会在服务器上产生变更,建议标注为 readOnlyHint: false

"annotations": {
  "readOnlyHint": false,
  "destructiveHint": false,
  "openWorldHint": false
}

模型看到这样的工具,通常会向用户请求一次确认(一般是 ChatGPT UI 中的模态对话框)。

危险操作

如果你的工具会在服务器上执行删除等操作,请标注为 destructiveHint: true

"annotations": {
  "readOnlyHint": false,
  "destructiveHint": true,
  "openWorldHint": false
}

模型会非常谨慎地调用该工具,并进行两次确认:

  • 先在文本中向用户索取确认,
  • 然后平台再弹出标准确认对话框。

在本模块中,我们暂不实现电商相关工具,但可以草拟将来的 create_gift_order

server.registerTool(
  "create_gift_order",
  {
    title: "创建礼物订单",
    description:
      "只有在用户明确同意购买所选礼物后才使用。该工具会在系统中创建订单并返回状态。",
    inputSchema: {
      type: "object",
      properties: {
        giftId: {
          type: "string",
          description: "用户已选礼物的 ID。"
        },
        deliveryEmail: {
          type: "string",
          description: "接收数字礼物的邮箱。"
        }
      },
      required: ["giftId", "deliveryEmail"]
    },
    annotations: {
      destructiveHint: true,
      openWorldHint: true
    }
  },
  async () => {
    /* ... */
  }
);

注解并不能替代你在服务器端的权限校验;它们只是帮助 ChatGPT 设计合适的 UX:询问确认、显示警告,避免“悄悄”执行这类工具。

7. App 元数据与两个层级的 discovery

工具只是故事的一半。另一半是用户如何发现并启动你的 App。

在 ChatGPT 生态里,有两个关键的 discovery 层级。

其一是对话内的 in‑conversation discovery。当用户在聊天里输入内容(即使没有显式提到 App),模型会查看:

  • 消息文本与对话历史;
  • 可用应用及其工具的描述;
  • 品牌提及、主题与关键短语。

据此模型决定是否要推荐某个 App,如果要,推荐哪一个、并以哪个场景切入。在这里,工具与 App 的描述尤为重要。如果其中包含“礼物推荐”“礼物创意”“礼物预算”等“触发词”,模型选择你的 App 的机会会显著提升。

其二是全局 discovery:目录与 launcher。在这一层,起作用的是人:他会根据名称、图标、短描述与标签来选择 App。此时,你需要清晰诚实地说明应用做什么、面向谁、核心价值是什么。

可以总结成一张小表:

模型/用户看到什么 元数据中重要的是什么
In‑conversation 对话文本、tools 与 App 的描述 触发性表述、以行动为导向的命名、限制条件
目录/launcher 名称、图标、short/long description、标签 清晰定位、明确的价值主张

以 GiftGenius 为例,可以这样表述:

  • 名称:GiftGenius — 60 秒内完成礼物推荐
  • 短描述:收集收礼人画像,并给出 5–7 个礼物主意,可在 ChatGPT 内一键购买。
  • 对话内描述:当用户请求帮忙选礼物、不知道送什么、提到预算、收礼人兴趣或场合时,请使用此应用。

这些表述最好与 system‑promptrecommend_gifts 的描述保持一致。这样模型看到的就是一幅完整一致的图景,而不是互相矛盾的文本碎片。

8. 路由在 ChatGPT“脑中”是如何工作的

把一切串起来,看看一个典型请求的路径——不深入 MCP 协议,相关内容在后续模块展开。

假设用户写道:

“帮我给弟弟想个礼物,他超爱足球和桌游,预算不超过 50 美元。”

高度简化的流程:

  1. 模型分析消息与历史,识别出“礼物”“弟弟”“足球”“桌游”“预算 50”等信号。
  2. 把这些与可用 App 及其工具的描述进行对比。对于 GiftGenius,描述中明确包含“按兴趣与预算推荐礼物”,因此相关性较高。
  3. 如果该 App 尚未在会话中激活,模型会给出一条“预告”回复:“我可以打开 GiftGenius 应用,按你的参数帮你选礼物。要打开吗?”——这在我们的 UX 指令中已预先编写。
  4. 在用户同意后,模型会在 App 内选择 recommend_gifts,因为它的名称、descriptioninputSchema 与当前意图最吻合。
  5. 模型基于请求填写工具参数:必要时先调用 profile_to_segments,把“弟弟、爱足球和桌游”的文本转为分段 ["football_fan", "board_games"];随后用 recommend_gifts 并提供 segmentsbudget: {min: 0, max: 50, currency: "USD"}localeoccasion: "birthday"
  6. MCP 服务器执行该工具,生成包含 itemsmeta 的结构化输出并返回。
  7. 模型读取你在 outputSchema 中定义的 JSON,组织回复:说明找到了什么、为什么是这些礼物,并提出追问(“要按类别缩小范围吗?”“要看这个礼物的相似选项吗?”或者“要直接购买这个礼物吗?”)。

下图是该流程的简易流程图:

flowchart TD
  A[User: 礼物相关的请求] --> B[ChatGPT 分析上下文]
  B --> C[与 App 与 tools 的元数据进行匹配]
  C -->|相关| D[GiftGenius 预告]
  D -->|用户同意| E["调用 recommend_gifts(+ profile_to_segments)"]
  E --> F[GiftGenius 的 MCP 服务器]
  F --> G[包含 items/meta 的 JSON 结果]
  G --> H[模型组织回复并提出 follow-up]

你对工具与 use case 的描述越好,这里的“随机性”就越少,路由就越稳定。

洞见:Tool Call SEO

在 Apps 生态中,你很快将面临的不仅是目录里对用户注意力的竞争,更是对模型注意力的竞争。面对同一条用户请求,ChatGPT 可能会考虑调用十来个应用;选择不会发生在谁的展示页更漂亮,而是在模型“脑中”的“搜索结果”里。这个看不见的层越来越像 SEO,只不过页面换成了 tools 和 MCP 服务器。

本质上,模型会对候选进行排序:先是 App 层,再是单个工具层。它会查看名称、descriptions、schema、注解,并把它们与用户请求的表述进行匹配。如果 recommend_gifts 的描述里有“按预算与收礼人兴趣推荐礼物”,而用户请求写着“给爱玩游戏的朋友推荐不超过 $50 的礼物”,这个工具就更有机会“排进前列”,而不是一个描述为“处理礼物”的抽象 search

由此产生了一个实践概念:Tool Call SEO——把名称、description、enum 值与元数据当作关键词与摘要来设计。你不是只给开发者写契约,而是在为来自 golden prompt set 的真实请求流做优化。过于笼统的表述、多个工具的适用范围重叠、没有明确“领域”的 God 工具——都会降低你的 App 在模型“脑中”的“点击率”。

9. 一个小练习

不妨在脑中(或你的仓库里)做如下练习。

先选一个 GiftGenius 的关键场景——例如“在预算受限的前提下,为同事挑选礼物”。

为它进行如下设计:

  1. 针对这个场景需要哪个单独的工具:是纯粹的 recommend_gifts,还是需要一个更偏 B2B 的专用工具,或者说在 recommend_gifts 之后用 similar_gifts 做扩展就足够?
  2. recommend_gifts 的输入 schema 里,哪些字段是确实必要的。哪些可以通过追问(follow‑up)向用户补齐,而不是强迫模型“猜”。
  3. outputSchema 应该长什么样,才能让模型既能如实解释选择依据,又能提出下一步建议(例如切到 B2B 模式、只显示数字礼物、按价格区间再收窄)。

然后回看上一讲中你的 golden prompt set,检查:

  • 每条基准请求是否都对应一个显而易见的工具(recommend_giftsget_giftsimilar_gifts 等);
  • 是否出现两个工具“同样适合”某一请求的情况(overlapping tools);
  • 是否需要加强描述或重命名某个 tool,以减少模型的混淆。

这正是你在每次对 prompt、schema 或逻辑做重大调整前要重复的流程——本质上是一次针对 discovery/路由质量的迷你评测(mini‑eval)。

把上述要点化成一个清单,此阶段你需要:

  • 把场景诚实地切成 2–4 个有意义的工具;
  • 细致描述 inputSchema/outputSchema,辅以示例与 enum
  • 整理命名、description 与注解;
  • system‑prompt 与 App 元数据保持同步。

在接下来的模块中,我们会看看这些东西如何通过 MCP 运转,以及如何诊断 discovery/路由的异常行为。

10. 设计 tools 与元数据时的常见错误

错误 #1:“我们都写在 system‑prompt 里了,工具自己会搞定”。
即使你把 App 的角色、职责边界与 UX 行为写得很好,但如果工具仍叫 tool1searchdo_stuff,schema 也没有描述,模型就无法把漂亮的文字与真实调用对应起来。对 ChatGPT 而言,工具才是主接口;没有良好的元数据,再强的 system‑prompt 也救不了场。

错误 #2:什么都做的 God Tool。
“优化”为一个带 mode 的函数可以理解,但它会导致臃肿的 JSON schema、混乱的描述、糟糕的路由。模型要猜用哪个模式,而你要维护服务器端一个巨大的 switch。不如用几个面向具体步骤的清晰工具,胜过一个“包打天下”的工具。

错误 #3:输入 schema 填满“以防万一”的字段。
很多开发者试图把可能用得上的所有参数都一次性塞进 inputSchema,再加上几个内部字段。结果模型被迫去猜不可能知道的东西(例如 tenantId),然后你对奇怪的取值一脸疑惑。Input Schema 只应包含模型能从对话里得出或通过提问补齐的内容。内部细节请在服务器端添加。

错误 #4:没有元信息的“哑输出”。
只返回一个对象数组很诱人。但这会剥夺模型理解结果为什么出现的能力。缺少 scorereasonsearchCriteriatotalCandidates 等字段,模型更难组织诚实的解释与追问。添加一个小型的 meta 包装,包含检索条件与建议,往往能显著提升回答质量。

错误 #5:描述像墙板一样千篇一律:“处理礼物”“搜索课程”“数据处理”。
这类描述的问题在于既不给模型触发器,也不给边界。它不知道“何时”调用、适用“哪个领域”。一个好的描述从“当……时使用该工具”开始,包含具体场景与“不要用于……”的限制。理想情况下,这些表述应和你的 golden prompt set 中的“金句”相互呼应。

错误 #6:忽视注解,混合只读与变更动作。
如果你不区分仅读取数据的工具(readOnlyHint)和会执行动作的工具(destructiveHintopenWorldHint),模型就无法设计正确的确认 UX。结果可能是每一步都弹“你确定吗?”,或者相反,默默地完成购买/修改。注解是廉价且高效的方式,向模型传达操作的重要性。

错误 #7:目录用的 App 元数据与对话内的元数据“各说各话”。
有时目录里的短描述由市场同学撰写(“颠覆人生的革命性 AI 助手”),而工具的 description 与 system‑prompt 则由开发者撰写(“按预算推荐礼物”)。结果在目录中看不出 App 究竟做什么,而模型在对话里也难以把“这是什么服务?”的提问与 App 的真实能力对应起来。把元数据当成一份统一的规范来写,而不是两篇互不相关的营销文案。

1
调查/小测验
ChatGPT App 的行为第 5 级,课程 4
不可用
ChatGPT App 的行为
面向模型的指令与 ChatGPT App 的行为
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION