OpenAI 开发者的 Skill 经验:如何使用评估系统来优化 Skill

AI教程20小时前更新 小小编
2 1
OpenAI 开发者的 Skill 经验:如何使用评估系统来优化 Skill

当你给 Codex 这类 AI 智能体迭代技能时,你往往摸不透效果:

到底是真的优化了技能,还是只是改变了它的行为模式?比如这个版本感觉更快,那个版本似乎更可靠,但突然就出问题了:技能不触发、跳过必要步骤,或者留下一堆多余文件。

本质上,针对大语言模型的技能,其实就是一组有条理的提示词和指令集合。要让技能持续改进,最靠谱的方法就是像评估其他大语言模型应用的提示词那样来评估它。

模型评估(evaluations,简称 Evals)用于验证模型的输出结果及其生成过程是否符合预期。它不再让你问模糊的问题或仅凭直觉判断,而是支持你提出具体的问题,比如:

  • 智能体是否成功调用了目标技能?

  • 是否执行了预期的命令序列?

  • 输出结果是否符合预设的规范要求?

具体来说,评测的完整流程是这样的:输入提示词 → 记录运行全程(含过程与产物)→ 执行几项关键检查 → 生成一个可长期追踪对比的评分。

OpenAI 开发者的 Skill 经验:如何使用评估系统来优化 Skill

在实际操作中,智能体技能评估的方式其实很像简化版的端到端测试:你先跑一遍智能体,记录下它的行为过程,最后对照几条简单规则给结果打分。

原文:https://developers.openai.com/blog/eval-skills#6-conduct-qualitative-checks-with-codex-and-rubric-based-grading

这篇文章讲解了如何用 Codex 完成这项任务,步骤非常清晰:首先定义成功标准,然后加入确定性检查和基于评分规则的评估,这样改进(或倒退)的效果就能一眼看出来了。

OpenAI 开发者的 Skill 经验:如何使用评估系统来优化 Skill

1、先明确成功标准,再设计技能

在动手设计技能之前,先把成功的定义用可量化的方式写下来。

一个实用的思路是把评估项分成几大类:

  • 结果目标:任务完成了吗?应用能正常运行吗?

  • 过程目标:Codex 是否调用了指定技能,并遵循了你预期的工具和步骤?

  • 风格目标:输出是否符合你要求的规范?

  • 效率目标:是否避免了冗余操作(比如不必要的命令或过度消耗 token)?

记住,清单要精简,聚焦于必须通过的检查项。目标不是预先设定所有偏好,而是抓住你最在意的行为。

比如在这篇文章里,指南评估了一项搭建演示应用的技能。有些检查项很实在,比如有没有执行 npm install?有没有创建 package.json 文件?

此外,指南还搭配了结构化的风格评估准则,用来判断代码规范和排版是否符合行业惯例。这种组合是有意设计的。你要的不是一个简单的通过/失败判定,而是找到快速、精准的信号,而它们往往能早早揪出特定的回归问题。

2、创建技能

Codex 技能本质上是一个目录,其中必须包含 SKILL.md 文件,该文件由几部分组成:

首先是 YAML 前置元数据(包含名称、描述字段),然后是 Markdown 格式的指令(用于定义技能的行为逻辑),还可附带可选的资源文件和脚本。

OpenAI 开发者的 Skill 经验:如何使用评估系统来优化 Skill

技能的名称和描述远比表面看起来重要。 它们是 Codex 判断是否调用该技能、以及何时将 SKILL.md 其余内容注入智能体上下文的核心依据。如果这两个字段模糊不清或功能过载,技能就无法稳定触发。

最快上手的方式,是直接用 Codex 的内置技能创建器:有意思的是,这个创建器本身也是一个技能。它会一步步引导你完成对应步骤:$skill-creator。

创建技能时,你需要回答三个核心问题:这个技能具体能做什么?它会在什么时机触发?是选择仅指令型还是脚本驱动型?想要了解更多创建技能的细节,可以查看官方文档。

一个示例技能

本文特意选用了一个极简案例:这个技能能以可预测且可重复的方式,快速搭建一个小型 React 演示应用。

这项技能将:

  • 用 Vite 的 React + TypeScript 模板初始化项目

  • 通过官方 Vite 插件的方式配置 Tailwind CSS

  • 确保采用简洁且一致的文件结构

  • 明确完成标准,以便能简单直接地评估项目是否成功

以下是一个简洁的例子,可以将其粘贴到以下目录:

.codex/skills/setup-demo-app/SKILL.md (repo-scoped) 或 ~/.codex/skills/setup-demo-app/SKILL.md (user-scoped)

---
名称:setup-demo-app
描述:用一个小型、一致的项目结构搭建了一个 Vite + React + Tailwind 演示应用的支架。
---

## 什么时候用这个
当你需要一个全新的演示应用来快速做界面实验或复刻时使用。

## 建造什么
创建一个 Vite React TypeScript 应用并配置 Tailwind。保持简约。

设置后的项目结构:
- src/
- main.tsx(入口文件)
- App.tsx(根 UI 组件)
- components/
- Header.tsx
- Card.tsx
- index.css(Tailwind 进口)
- index.html
- package.json

风格要求:
- TypeScript 组件
- 仅函数式组件
- 使用 Tailwind 工具类进行样式设置(无 CSS 模块)
- 无额外的 UI 库

## 脚本
1. 使用 React TS 模板的 Vite 支架:
npm create vite@latest demo-app -- --template react-ts

2. 安装依赖:
cd demo-app
npm install

3. 使用 Vite 插件安装并配置 Tailwind。
- npm TailwindCSS @tailwindcss/vite
- npm install tailwindcss @tailwindcss/vite
- 在 src/index.css 中,将内容替换为:
@import“tailwindcss”;

4. 实现最简 UI:
- Header:应用标题和简短副标题
- Card:可复用的卡片容器
- App:渲染 Header + 2 张带有占位文字的 Card

## 完成的定义
- npm run dev 成功启动
- package.json 存在
- src/components/Header.tsx 和 src/components/Card.tsx 存在

这个示例技能特意带有明确的标准:没有清晰的约束条件,就无从进行具体评估。

3、手动触发技能以揭示隐藏假设

由于技能调用的效果很大程度上取决于 SKILL.md 文件中的名称和描述,因此首先需要确认的是:

setup-demo-app 技能是否会在你预期的时机触发。

刚开始测试时,你得明确激活这个技能,无论是用 /skills 斜杠命令,还是在真实代码仓库或临时目录里用 $ 前缀引用它。然后盯着看它哪里出问题:是完全没触发?触发太频繁?还是运行起来后偏离了预期步骤?这些都是你要找的漏洞点。

现阶段,不用急着追求速度或打磨细节。你要做的是找出这个技能隐含的那些假设,比如:

  • 触发假设:一类是「该触发却没触发」,比如输入快速搭建 React 演示,系统本应调用 setup-demo-app 工具,结果毫无反应;另一类是「不该触发却触发」,比如输入添加 Tailwind 样式这种通用指令,反而意外启动了 setup-demo-app。

  • 环境假设:该功能模块默认运行在空目录下,或需确保 npm 可用且优先于其他包管理器。

  • 执行假设:智能体可能跳过 npm install 步骤(安装项目依赖的命令),误以为依赖已经安装完毕;或者在 Vite 项目创建之前就开始配置 Tailwind CSS(一种流行的 CSS 框架)。

当你需要让这些运行过程可重复时,就切换到 codex exec 工具吧。它专为自动化和持续集成场景设计:进度信息会实时输出到标准错误流,而最终结果只写入标准输出流,这样一来,整个流程更容易通过脚本控制、捕获结果,也方便后续排查问题。

默认情况下,Codex exec 会在受限沙箱环境中运行。如果你的任务需要写入文件,请加上 --full auto 参数执行该命令。一般原则是,尤其是在自动化操作时,应遵循最小权限原则(只用完成任务必需的权限就足够了)。

一个基础的手动运行流程大概是这样的:

codex exec --full-auto
   'Use the $setup-demo-app skill to create the project in this directory.'

首次测试的重点不是验证正确性,而是发现边缘情况。你在这里做的每一处手动修复,比如补充缺失的 npm install、修正 Tailwind 配置,或是细化触发器描述,都可以作为未来评估的候选内容。这样一来,你就能在大规模评估前锁定系统的预期行为。

4、用小而精准的提示词集尽早发现性能退化

评估不必依赖庞大的基准测试集也能发挥价值,针对单一能力,10-20 个提示词就足够:

既能早期捕捉到性能退化的迹象,也能快速验证改进效果。

先从一个小型 CSV 文件开始,随着开发或使用中遇到实际问题,逐步扩充它的内容。CSV 的每一行对应一个场景,你需要明确 setup-demo-app 技能是否触发,以及触发成功的具体表现是什么。

比如,初始的 evals/setup-demo-app.prompts.csv 文件可能长这样:

id, 是否预期触发, 提示词
test-01, true, "创建devday-demo的应用,用$setup-demo-app技能"
test-02, true, "搭建极简React演示应用,方便快速UI实验"
test-03, true, "创建小型演示应用,展示Responses API的功能"
test-04, false, "为现有React应用添加Tailwind样式"

这些案例的测试重点各有不同:

  • 显式调用:test-01 测试用例,该提示词会直接指定技能名称。这样做能确保 Codex 在接收到请求时,可以正确调用 setup-demo-app 技能;同时,即便后续修改该技能的名称、描述或使用说明,也不会影响直接调用的有效性。

  • 隐式调用测试:test-02 测试用例,该提示词准确描述了目标技能适用的场景:搭建一个极简的 React + Tailwind 示例,但全程未提及技能本身的名称。这个测试的目的是验证 SKILL.md 中的技能名称和描述是否足够清晰,让 Codex 模型能够自主选择对应的技能。

  • 上下文调用:test-03 测试用例,该提示词新增了领域上下文,但仍沿用相同的底层配置。它主要验证两个核心点:一是技能能否在真实且略带干扰的提示词环境中正常触发;二是生成的应用是否符合预期的结构和规范。

  • 负向控制测试:test-04 测试用例,这个提示指令不应触发 setup-demo-app 功能。这类请求很常见:用户想给现有应用添加 Tailwind,但可能无意中匹配到技能描述里的「React+Tailwind 演示」。加入至少一个是否预期触发 =false 的测试用例,能帮助识别这种问题:Codex 过于急切地选择该技能,在用户只想对现有项目做增量修改时,却生成了全新项目。

OpenAI 开发者的 Skill 经验:如何使用评估系统来优化 Skill

这种设计是刻意安排的。有些评估要验证功能在被显式调用时是否正常工作;另一些则要检查它在用户完全没提到该功能的实际场景中会不会自动激活。

当你遇到遗漏的情况、触发不了技能的提示词,或是输出和预期不一致的案例时,把它们都加到 CSV 文件里,作为新行。

随着时间推移,这个小小的数据集会慢慢变成一份活的记录,它会记下该技能需要一直做好的那些关键点。

5、开始使用轻量级确定性评分工具

这是评估环节的核心:使用 codex exec --json 命令,让你的评估框架能够对实际发生的过程进行打分,而非仅评判最终输出是否「看起来正确」。

启用 --json 参数后,标准输出会输出结构化事件的 JSONL(即每行一个 JSON 对象的格式)。这让你能轻松编写确定性检查,直接针对你关注的行为逻辑。比如:

有没有执行 npm 安装?有没有生成 package.json 文件?有没有按照预期顺序调用指定命令?

这些检查是有意设计得轻量的,因为在引入基于模型的评分之前,它们能快速给出清晰易懂的反馈信号。

极简 Node.js 运行器

一个「够用就好」的实现方案大致如下:

针对每个提示词,执行以下操作:先运行 codex exec --json --full-auto ""命令,再将 JSONL 跟踪日志保存到磁盘,最后解析该日志并对其中的事件执行确定性检查。

// evals/run-setup-demo-app-evals.mjs
import { spawnSync } from "node:child_process";
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
import path from "node:path";

function runCodex(prompt, outJsonlPath) {
  const res = spawnSync(
    "codex",
    [
      "exec",
      "--json", // REQUIRED: emit structured events
      "--full-auto", // Allow file system changes
      prompt,
    ],
    { encoding: "utf8" }
  );

  mkdirSync(path.dirname(outJsonlPath), { recursive: true });

  // stdout is JSONL when --json is enabled
  writeFileSync(outJsonlPath, res.stdout, "utf8");

  return { exitCode: res.status ?? 1, stderr: res.stderr };
}

function parseJsonl(jsonlText) {
  return jsonlText
    .split("n")
    .filter(Boolean)
    .map((line) => JSON.parse(line));
}

// deterministic check: did the agent run `npm install`?
function checkRanNpmInstall(events) {
  return events.some(
    (e) =>
      (e.type === "item.started" || e.type === "item.completed") &&
      e.item?.type === "command_execution" &&
      typeof e.item?.command === "string" &&
      e.item.command.includes("npm install")
  );
}

// deterministic check: did `package.json` get created?
function checkPackageJsonExists(projectDir) {
  return existsSync(path.join(projectDir, "package.json"));
}

// Example single-case run
const projectDir = process.cwd();
const tracePath = path.join(projectDir, "evals", "artifacts", "test-01.jsonl");

const prompt =
  "Create a demo app named demo-app using the $setup-demo-app skill";

runCodex(prompt, tracePath);

const events = parseJsonl(readFileSync(tracePath, "utf8"));

console.log({
  ranNpmInstall: checkRanNpmInstall(events),
  hasPackageJson: checkPackageJsonExists(path.join(projectDir, "demo-app")),
});

它的价值点很明确:所有流程都是确定的,而且支持调试。

要是检查没通过,打开 JSONL 文件就能一目了然地看到问题细节。所有命令执行都会按顺序记录成 item.* 事件,这让回归问题的排查和修复变得简单直接,这正是你当前阶段最需要的效果。

6、用 Codex 和基于评分标准的方法开展定性检查

确定性检查只能回答「它有没有完成基础要求?」,却回答不了「它是不是按你想要的方式完成的?」

以演示应用搭建这类技能为例,其要求多为定性指标,比如组件结构是否合理、样式规范是否统一,或是 Tailwind 是否符合预期配置。这些指标很难仅靠检查文件是否存在或统计命令数量来衡量。

一个务实的做法是,在评估流程中增加一个模型辅助的第二步:

1、执行设置技能(此操作会把代码写入磁盘)

2、对生成的代码仓库做一次只读的风格检查

3、需要结构化的响应,让你的评估工具能一致打分

Codex 通过 --output-schema 直接支持这一点:它会把最终响应限制在你定义的 JSON Schema 范围内。

简易评估规则模板

首先,定义一套简易的规则模板,把你关注的所有检查项都涵盖进去。

比如,可以创建一个文件,命名为 evals/style-rubric.schema.json:

{
  "type": "object",
  "properties": {
    "overall_pass": { "type": "boolean" },
    "score": { "type": "integer", "minimum": 0, "maximum": 100 },
    "checks": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "pass": { "type": "boolean" },
          "notes": { "type": "string" }
        },
        "required": ["id", "pass", "notes"],
        "additionalProperties": false
      }
    }
  },
  "required": ["overall_pass", "score", "checks"],
  "additionalProperties": false
}

这套架构包含几个稳定字段:整体通过状态、得分和单项检查结果。

你可以对这些字段进行合并分析、差异对比,还能长期追踪其变化趋势。

风格检查提示词

接下来,请运行第二个 Codex 执行程序,该程序仅检查代码仓库并生成符合评分标准的 JSON 响应:

codex exec
  "Evaluate the demo-app repository against these requirements:
   - Vite + React + TypeScript project exists
   - Tailwind is configured via @tailwindcss/vite and CSS imports tailwindcss
   - src/components contains Header.tsx and Card.tsx
   - Components are functional and styled with Tailwind utility classes (no CSS modules)
   Return a rubric result as JSON with check ids: vite, tailwind, structure, style."
  --output-schema ./evals/style-rubric.schema.json
  -o ./evals/artifacts/test-01.style.json

这时候,输出模式参数 --output-schema 就派上用场了。不用再处理那些难以解析、无法直接对比的自由文本,而是能得到结构固定的 JSON 对象,你的评估工具可以基于它在多次运行中自动打分。

如果之后你把这个评估套件迁移到持续集成环境中,Codex GitHub Action 明确支持通过 codex-args 传递 --output-schema 参数,这样就能在自动化工作流里强制要求统一的结构化输出格式了。

7、技能成熟后,扩展评估体系

一旦核心流程搭建完成,你就可以朝着对技能最关键的方向扩展评估。

先从小处着手,只在能真正增强信心的环节,逐步加入更深入的检查机制。

下面是一些例子:

  • 命令计数与无效循环监控:通过统计 JSONL 跟踪日志中的命令执行记录,及时发现智能体开始无效循环或重复执行命令的异常回归问题。此外,`turn.completed` 事件中还会记录 Token 消耗情况。

  • Token 预算:跟踪 usage.input_tokens 和 usage.output_tokens,以识别意外的提示词冗余,并跨版本比较效率。

  • 构建检查:技能执行完成后运行 npm run build 命令。这能提供更可靠的端到端验证,及时发现导入错误或工具链配置问题。

  • 运行时冒烟测试:可以执行 npm run dev 命令启动开发服务器,再用 curl 工具发起请求验证;如果已有轻量级的 Playwright 检查脚本,也可直接运行。不过这种检查要按需使用,它能提升验证信心,但会消耗额外时间。

  • 代码仓库整洁性:确保运行过程中不生成多余文件,且 git status --porcelain 命令输出为空(或符合明确指定的允许列表)。

  • 沙箱测试与权限回归检查:确保技能在未获取超出预期的额外权限时仍可正常运行。一旦进入自动化阶段,默认遵循最小权限原则将变得尤为关键。

这个模式始终如一:先做快速检查摸清行为情况,然后只有在能降低风险时,才加上那些更慢但更重量级的检查。

8、核心要点

这个小巧的 setup-demo-app 示例,展示了从「主观感受良好」到「客观数据可证」的转变:只需运行智能体、记录过程,再通过几项关键检查点评定其表现即可。

一旦形成这样的闭环,每一次调整的效果都能轻松验证,任何性能倒退的问题也会清晰显现。

以下是本次的核心要点:

  • 要衡量关键指标。高质量的评估能让性能衰退一目了然,也能让错误原因有据可查。

  • 首先得明确可验证的验收标准。先用 $skill-creator 工具快速搭建基础框架,再逐步细化指令,直到成功标准清晰明确、没有歧义。

  • 评估要落地到实际行为上。通过 codex exec --json 命令导出 JSONL 数据,然后针对 `command_execution` 事件编写确定性验证逻辑。

  • 当规则无法覆盖所有场景时,就借助 Codex 通过 --output-schema 参数添加结构化的、基于评分标准的验证环节,这样就能可靠地评估风格和规范是否达标。

  • 让真实的失败案例驱动测试覆盖。每一次手动修复都是一个信号,把它转化为自动化测试,这样技能就能持续输出正确结果。

 

© 版权声明

相关文章

1 条评论

评论已关闭...
  • 月之呢喃
    月之呢喃 读者

    这个评估思路挺靠谱的。