如何使用 OpenAI Decisions API:从第一个请求到阈值与测试

手把手上手 OpenAI Decisions API:获取密钥后用 curl、Python、JavaScript 发出第一个 POST /v1/decisions 请求,读懂 predicate、choice、score、refusal 四种答案,掌握图片输入、一条工单多问题、阈值设定与错误处理,并在 Apifox 中搭建断言与 CI 测试。

用 Apifox,节省研发团队的每一分钟

如何使用 OpenAI Decisions API:从第一个请求到阈值与测试

免费使用 Apifox

相关推荐

最新文章

API

一体化协作平台

API 设计

API 文档

API 调试

自动化测试

API Mock

API Hub

立即体验 Apifox
目录

使用 OpenAI Decisions API 的方式是:向 https://api.openai.com/v1/decisions 发送 POST 请求,带 "model": "gpt-6-luna"、一个 input(文本、图片或两者)和一个 questions 数组,每个问题可以是 predicate、choice 或 score。你拿回的是带概率的类型化答案,而不是需要解析的文本;费用为每 100 万输入 token 0.10 美元,无输出、缓存读或缓存写费用。该接口自 2026 年 10 月 6 日起处于公测阶段。

本指南覆盖获取密钥、用 curl/Python/JavaScript 完成第一次调用、读懂每种答案类型、在一条工单上提三个问题、图片输入、阈值设定,以及在 Apifox 中搭建测试环境。要判断什么时候该选这个接口,从「什么是 OpenAI Decisions API」开始。

AI Coding 交流群

如果你也在用 AI 写代码,或者正在研究 Cursor、Claude Code 这些工具,欢迎加入以下交流群。群里平时会聊一些 AI 编程的实际用法、开发工作流,还有各种新工具和新玩法。

Decisions API 请求速览

字段 取值
model gpt-6-luna(公测阶段唯一可用模型)
input 字符串,或 user 消息数组,其 content 为字符串或 input_text、input_image 类型的部分
questions[].type predicate、choice 或 score
questions[].instructions 必填;用平实语言描述问题
questions[].name 可选;在答案中回显(省略时为 null)
questions[].choices 仅 choice;2 到 255 个不重复的 {value, description} 对象,value 为字符串或布尔值
questions[].levels 仅 score;有序 {label, description} 对象,从低到高,索引从 0 开始
safety_identifier 可选的不透明终端用户 id,最长 128 字符

来源:Decisions API 参考。这个接口上没有 temperature、stream、tools 或 text.format。

获取密钥并完成第一次调用

在 OpenAI 控制台创建密钥(「OpenAI API key 指南」有完整步骤),导出为 OPENAI_API_KEY,永远不要把它粘贴进代码。然后问一个是/否问题:

curl https://api.openai.com/v1/decisions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6-luna",
    "input": "The box arrived crushed and the screen is cracked.",
    "questions": [
      {"type": "predicate", "name": "damaged",
       "instructions": "Does the customer report a damaged item?"}
    ]
  }'

响应有三个顶层字段:model、answers 和 usage。这是 OpenAI 参考中的形状,output_tokens 为 0,因为这个接口不收输出费用:

{
  "model": "gpt-6-luna",
  "answers": [
    {"type": "predicate", "name": "damaged", "probability": 0.95}
  ],
  "usage": {
    "input_tokens": 42,
    "input_tokens_details": {"cached_tokens": 0, "cache_write_tokens": 0},
    "output_tokens": 0,
    "output_tokens_details": {"reasoning_tokens": 0},
    "total_tokens": 42
  }
}

同样的调用用 Python(SDK 3.26.0 或更高):

from openai import OpenAI

client = OpenAI()  # reads OPENAI_API_KEY from the environment

decision = client.decisions.create(
    model="gpt-6-luna",
    input="The box arrived crushed and the screen is cracked.",
    questions=[
        {"type": "predicate", "name": "damaged",
         "instructions": "Does the customer report a damaged item?"}
    ],
)
print(decision.answers[0].probability)

以及 JavaScript(SDK 7.30.0 或更高):

import OpenAI from "openai";

const client = new OpenAI();

const decision = await client.decisions.create({
  model: "gpt-6-luna",
  input: "The box arrived crushed and the screen is cracked.",
  questions: [
    { type: "predicate", name: "damaged",
      instructions: "Does the customer report a damaged item?" },
  ],
});
console.log(decision.answers[0].probability);

按类型读取答案

答案按提问顺序返回,各带一个 type。按类型分支处理,因为任何问题都可能以 refusal 返回。

  • predicate 返回 probability,即条件为真的 0 到 1 估计值。
  • choice 返回 choice(胜出的 value)、作为 {value, probability} 对象数组的 probabilities,以及 confidence。
  • score 返回 score、作为 {value, label, probability} 对象数组的 probabilities(其中 value 是 0 起始的等级索引),以及 confidence。score 是等级索引按概率加权后的平均,因此可能落在两级之间:1.1 表示“介于等级 1 和等级 2 之间,更靠近 1”。
  • refusal 只返回 type 和 name。模型拒绝回答该问题;同一请求中的其他问题仍可收到答案。
for a in decision.answers:
    if a.type == "refusal":
        send_to_review(a.name)
    elif a.type == "predicate":
        flag = a.probability > 0.9
    elif a.type == "choice":
        route = a.choice if a.confidence > 0.8 else "review"
    elif a.type == "score":
        priority = round(a.score)

OpenAI 指南如此划线:无序类别(如部门)用 choice;有序等级(如严重程度)用 score。

一条工单上三个问题

相互独立的问题共享一次请求和同一个 input,每个问题可以用不同类型。下面在一条工单上同时提一个 predicate、一个 choice 和一个 score:

{
  "model": "gpt-6-luna",
  "input": "I was charged twice for my order.",
  "questions": [
    {"type": "predicate", "name": "refund_requested",
     "instructions": "Is the customer asking for money back?"},
    {"type": "choice", "name": "department",
     "instructions": "Which team should handle this ticket?",
     "choices": [
       {"value": "billing", "description": "Charges, refunds, invoices"},
       {"value": "technical", "description": "Bugs and errors in the product"},
       {"value": "shipping", "description": "Delivery and tracking"},
       {"value": "other", "description": "Anything else"}
     ]},
    {"type": "score", "name": "urgency",
     "instructions": "How urgent is this ticket?",
     "levels": [
       {"label": "low", "description": "No time pressure"},
       {"label": "medium", "description": "Needs a reply this week"},
       {"label": "high", "description": "Customer is blocked or losing money"}
     ]}
  ]
}

answers 数组按相同顺序返回。下面的 choice 取值是 OpenAI 指南对这个输入给出的数值;predicate 和 score 的数值为示意:

"answers": [
  {"type": "predicate", "name": "refund_requested", "probability": 0.88},
  {"type": "choice", "name": "department", "choice": "billing",
   "probabilities": [
     {"value": "billing", "probability": 0.95},
     {"value": "technical", "probability": 0.02},
     {"value": "shipping", "probability": 0.01},
     {"value": "other", "probability": 0.02}
   ],
   "confidence": 0.93},
  {"type": "score", "name": "urgency", "score": 1.6,
   "probabilities": [
     {"value": 0, "label": "low", "probability": 0.05},
     {"value": 1, "label": "medium", "probability": 0.30},
     {"value": 2, "label": "high", "probability": 0.65}
   ],
   "confidence": 0.65}
]

指南的两条规则:当你的分类覆盖不了所有输入时,加上 other 之类的兜底项;围绕可观察的标准来写问题,让相邻的 score 等级有不同含义。如果第二个决策依赖第一个答案,请单独发一个请求。

图片输入

把图片作为 user 消息里的一个 content 部分传入。指南文档化了内联 base64 data URL:

{
  "model": "gpt-6-luna",
  "input": [{
    "role": "user",
    "content": [
      {"type": "input_text", "text": "Photo attached to a return request."},
      {"type": "input_image", "image_url": "data:image/jpeg;base64,/9j/4AAQ..."}
    ]
  }],
  "questions": [
    {"type": "predicate", "name": "visible_damage",
     "instructions": "Is the product visibly damaged?"}
  ]
}

API 参考另列出可公开访问的 HTTP(S) URL、单请求所有消息合计最多 128 张图,以及可选的 detail 字段(low、high、auto、original),所以在依赖托管 URL 之前,先用你自己的账号测一遍。两个页面都未支持 file_id 输入。

用标注样本定阈值

OpenAI 没有公布这个接口的准确率或校准数据。官方建议使用你自己应用中的标注样本来设定分派、过滤或复审的阈值,依据是误报与漏报的成本对比。实践中就是:拿一个小 CSV,装着真实工单和人工选出的部门,跑同一个请求,观察 confidence 在哪里把“能自动分派”和“需要人工”的样本分开。下一节就搭这个闭环。

在 Apifox 中测试 Decisions API

保存好的请求让阈值调优和回归检查可以重复。下面是在 Apifox 里的搭建步骤:

  1. 把密钥存为环境变量。创建一个环境,把 OPENAI_API_KEY 添加为私密变量(「Apifox 环境与私密变量」有配置说明),并把 Authorization 请求头设为 Bearer {{OPENAI_API_KEY}}。密钥原文永远不会落进共享请求体。
  2. 每种问题类型保存一条请求。创建一条指向 https://api.openai.com/v1/decisions 的 POST 请求,Content-Type: application/json,把上面工单示例里的 choice 问题单独粘进去并保存。再复制出 predicate 和 score 两个版本。
  3. 添加 JSONPath 断言。在 choice 请求上:状态为 200、$.answers[0].type 等于 choice、$.answers[0].choice 等于 billing、$.answers[0].confidence 大于 0.8、$.usage.output_tokens 等于 0。对破损判断的 predicate,断言 $.answers[?(@.name=='damaged')].probability 大于 0.9。这样措辞变更或模型行为变化都会让测试失败,而不是错分工单。
  4. 在标注工单上跑。用保存的请求建一个测试场景,附上一个两列的小 CSV:ticket_text 和 expected_department。把 {{ticket_text}} 映射进 input,断言 $.answers[0].choice 等于 {{expected_department}}。运行报告显示每一行的 confidence,这正是 OpenAI 让你用来定阈值的数据。所有错分样本所在的分界线,就变成你代码里“自动分派”的阈值。
  5. 为前端 mock answers 数组。把分派逻辑或 UI 指向同一接口的 mock,让它返回 confidence 高于和低于阈值的 choice 答案,外加一个 refusal,这样复审队列路径在你花掉一个输入 token 之前就能开发好。「Apifox 条件 mock 响应」讲了按请求内容切换 mock。
  6. 在 CI 里跑场景。导出一个访问令牌,然后在流水线里加一步:
apidog run --access-token "$APIDOG_ACCESS_TOKEN" \
  -t "$SCENARIO_ID" -e "$ENV_ID" -r cli,junit

断言失败会让构建失败,confidence 的悄然下滑会在部署前被抓住,而不是出现在支持队列里。更多模式见「测试 LLM 应用」。

错误与边界情况处理

  • 429 限流。官方没有公布 Decisions 专属限制;请到 Settings > Organization > Limits 查看你的数值。指数退避,出现 Retry-After 响应头时遵循它。「速率限制超限指南」里有一个重试包装器。
  • 拒答。把 type: "refusal" 当作一种分派结果,而不是异常。把这条工单转给人工,同一请求的其他答案照常使用。
  • 依赖决策。每个问题都是针对共享输入独立评估的。任何依赖前一个答案的问题都需要单独请求。

常见问题

Decisions API 多少钱?gpt-6-luna 上每 100 万输入 token 0.10 美元,无输出、缓存读或缓存写费用。一条 500 token、三个问题的工单花费 500 / 1,000,000 x $0.10 = $0.00005,一百万条这样的工单花费 50 美元。超过 272K token 的长上下文输入按 2 倍计费,区域处理加收 10%。

Decisions API 免费吗?不免费,没有免费档。想不花钱试用 GPT-6 Luna,「GPT-6 Luna 免费使用渠道」一文列出了现有途径。

它有多快?OpenAI 称比 Responses API 快约 10 倍,没有公布绝对延迟数字。OpenAI 论坛有开发者反馈图片决策约 0.8 秒返回。

哪些模型能配 Decisions API?目前只有 gpt-6-luna。它是 Luna 上的一个接口,不是独立模型。模型本身见「什么是 GPT-6 Luna」。

什么时候该改用 Structured Outputs?需要按你自己的 JSON schema 返回对象(如抽取字段或书面说明)时;需要模型发起带参数的工具调用时用 function calling。「Decisions API 与 Responses API」一文展示了同一个工单的两种做法。

和 Jev 相比如何?两者都返回带概率的类型化答案、都只按输入计费;Jev 仅支持文本,每 100 万 0.042 美元。「Decisions API 与 Jev 对比」有完整表格。

下一步

把本指南的三问题工单请求发出去,然后在 20 条你自己的标注工单上跑一遍,观察 confidence 在哪里把分对和分错的样本分开。接着下载 Apifox,把请求、CSV 场景和断言放在一起保存,今天定下的阈值在每次部署时都会被重新校验。

开发必备:API 全流程管理神器 Apifox

介绍完上文的内容,我想额外介绍一个对开发者同样重要的效率工具 —— Apifox。作为一个集 API 文档、调试、设计、测试、Mock、自动化测试于一体的工具,Apifox 是目前提升研发效率的首选。

如果你正在开发项目,不妨试试其极其友好的界面设计,它完全兼容 Postman 和 Swagger 数据格式,导入数据非常方便,,即使是新手也能很快上手,点击这里即可注册使用。

Apifox

值得一提的是,除了个人和常规团队使用,针对有高安全合规要求、或需要在内网环境协作的企业,Apifox 还提供了深度定制的私有化部署方案。

获取专属报价与部署方案

icon 详细的私有化部署系统架构与安全白皮书
icon 针对您公司规模的专属报价单
icon 免费的 1v1 专属产品演示 (Demo) 机会
获取部署方案
* 提交后,我们的客户经理将在 1 个工作日内与您联系
林俊锋 企业微信
@Apifox 专属顾问
扫码备注: 私有化 + 公司名