OpenAI Decisions 决策API
Decisions API现已正式开放使用(GA)。本页说明从公开Beta到正式版本新增的能力。
Decisions API评估文本、图像和JSON,并返回具有明确类型的答案。官方指南称其速度约为Responses API的10倍;这是来源的产品描述,不是本地实测或对每次请求的延迟保证。它可返回某个条件为真的概率、固定选项中的一个选择,或按评分量表计算的分数,用于内容分类、请求路由和工作优先级排序。
可先在Playground试验问题及输入,再编写代码。
请求发送至POST /v1/decisions,使用gpt-6-luna;这是本次来源快照列出的唯一支持模型。
新增能力
自公开Beta发布以来,Decisions增加了以下能力:
- 提示缓存:跨请求复用共享输入,并获得缓存读取折扣。
- 问题指令中的图像:为每个问题提供各自的图像,与共享证据进行比较。
- JSON输入:通过
input_json内容部分直接传递结构化数据。 - 更多问题:单次最多400个问题,公开Beta期间为200个。
- 托管图像输入:除内联Base64数据URL外,也可使用公开可访问的HTTP或HTTPS图像URL。
- 会话历史:将消息、函数/自定义工具调用及其输出一起评估。
- 组织用量报告:跟踪词元用量与请求数。
- 原生GPT-Live集成:让Live直接调用Decisions,或在输入/输出转录到达时触发决策。
- Private Link:通过私有连接发送请求。
Decisions的工作方式
一个请求有三个主要部分:
| 字段 | 用途 |
|---|---|
model |
负责评估的模型,当前来源仅列出gpt-6-luna。 |
input |
所有问题共享的证据,可以是文本字符串,也可以是按顺序排列的消息、工具调用及工具输出数组。 |
questions |
需要评估的内容,包括每个问题的类型、指令及允许的选项或评分等级。 |
响应包含answers数组。为每个问题指定唯一name,API会在答案中原样返回该名称,方便对应问题与结果。
选择问题类型
| 类型 | 适合的任务 | 主要结果 |
|---|---|---|
predicate(条件判断) |
检查是否存在可见损坏、段落是否相关等条件。 | probability:条件为真的估计概率,范围0到1。 |
choice(选项选择) |
从部门、内容类别等固定选项中选一个。 | choice:调用方提供的值之一。 |
score(量表评分) |
根据问题严重程度等有序等级进行评分。 | score:等级索引的概率加权平均值。 |
choice和score都会返回离散选项的概率。无序类别,例如部门,使用choice;有序等级,例如严重程度,使用score。评分使用各等级数字索引的概率加权平均,因此可能落在两个等级之间。
应用需要上述类型答案时使用Decisions;如果要生成符合自定义JSON结构的对象,例如提取字段或书面解释,应使用Responses的结构化输出。需要模型请求调用工具并提供参数时,使用函数调用。
评估会话
将会话历史放入input,可以结合上下文评估请求。按顺序传入消息、函数或自定义工具调用及其输出,用call_id将每个工具输出与调用对应。
| 输入项 | 支持的内容 |
|---|---|
| 用户消息 | 文本、图像与JSON。 |
| 开发者或系统消息 | 仅输入文本;系统消息按开发者消息处理。 |
| 助手消息 | 输出文本或拒绝内容。 |
| 函数或自定义工具输出 | 文本和图像,并与匹配的工具调用关联。 |
工具调用和输出只是问题的评估证据。Decisions返回类型化答案,由应用执行答案所选的动作;它不会代替应用执行这些动作。不支持文件、音频或条目引用(item references)。接受的输入字段见创建决策参考。
评估JSON数据
用input_json内容部分直接传递结构化证据,无需先转成字符串。将JSON对象或数组放入data,可以与同一用户消息中的文本、图像部分并列。消息内容中的input_json仅支持user角色。
以下JSON请求体发送到POST /v1/decisions,对照订单记录判断客服工单是否反映重复扣款:
来源示例 1(json):
结构化订单证据中的重复扣款判断:ticket为工单,charges为扣款记录;输入JSON中的键仅为数据。
{
"model": "gpt-6-luna",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Evaluate the ticket using the order evidence."
},
{
"type": "input_json",
"data": {
"ticket": { "body": "Please refund the duplicate charge." },
"order": { "charges": [49, 49] }
}
}
]
}
],
"questions": [
{
"type": "predicate",
"name": "duplicate_charge",
"instructions": "Does the ticket describe a duplicate charge supported by the order?"
}
]
}
data中的role、image_url等键只是普通数据,不会创建消息或触发图像获取。答案仍采用所选问题类型;JSON输入不会改变响应格式。
检查图像中的可见损坏
用predicate问题检查产品照片是否有可见损坏。示例将图像与查找裂纹、撕裂或凹痕的指令一起发送;判断时应忽略阴影和包装损坏:
来源示例 2(bash):
## [中文] 用predicate检查产品图像是否有裂纹、撕裂或凹痕;判断时忽略阴影和包装损坏;按来源使用本地图片编码或图像URL,先准备对应素材。读取答案时区分refusal;probability是条件为真的估计概率,本次未验证素材或调用API。
IMAGE_BASE64="$(base64 < product.png | tr -d '\r\n')"
curl https://api.openai.com/v1/decisions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<JSON
{
"model": "gpt-6-luna",
"input": [{
"role": "user",
"content": [
{"type": "input_text", "text": "Inspect the product in this photo."},
{"type": "input_image", "image_url": "data:image/png;base64,$IMAGE_BASE64"}
]
}],
"questions": [{
"type": "predicate",
"name": "visible_damage",
"instructions": "Does the product have visible damage, such as a crack, tear, or dent? Ignore shadows and damage to the packaging."
}]
}
JSON
来源示例 3(javascript):
// [中文] 用predicate检查产品图像是否有裂纹、撕裂或凹痕;判断时忽略阴影和包装损坏;按来源使用本地图片编码或图像URL,先准备对应素材。读取答案时区分refusal;probability是条件为真的估计概率,本次未验证素材或调用API。
import { readFile } from "node:fs/promises";
import OpenAI from "openai";
const client = new OpenAI();
const imageBase64 = (await readFile("product.png")).toString("base64");
const decision = await client.decisions.create({
model: "gpt-6-luna",
input: [
{
role: "user",
content: [
{ type: "input_text", text: "Inspect the product in this photo." },
{
type: "input_image",
image_url: `data:image/png;base64,${imageBase64}`,
},
],
},
],
questions: [
{
type: "predicate",
name: "visible_damage",
instructions:
"Does the product have visible damage, such as a crack, tear, or dent? Ignore shadows and damage to the packaging.",
},
],
});
const answer = decision.answers[0];
if (answer.type === "refusal") {
console.log(`Refused: ${answer.name}`);
} else if (answer.type === "predicate") {
console.log(`Visible damage probability: ${answer.probability}`);
}
来源示例 4(python):
## [中文] 用predicate检查产品图像是否有裂纹、撕裂或凹痕;判断时忽略阴影和包装损坏;按来源使用本地图片编码或图像URL,先准备对应素材。读取答案时区分refusal;probability是条件为真的估计概率,本次未验证素材或调用API。
import base64
from pathlib import Path
from openai import OpenAI
client = OpenAI()
image_base64 = base64.b64encode(Path("product.png").read_bytes()).decode("ascii")
decision = client.decisions.create(
model="gpt-6-luna",
input=[
{
"role": "user",
"content": [
{"type": "input_text", "text": "Inspect the product in this photo."},
{
"type": "input_image",
"image_url": f"data:image/png;base64,{image_base64}",
},
],
}
],
questions=[
{
"type": "predicate",
"name": "visible_damage",
"instructions": (
"Does the product have visible damage, such as a crack, tear, or dent? "
"Ignore shadows and damage to the packaging."
),
}
],
)
answer = decision.answers[0]
if answer.type == "refusal":
print(f"Refused: {answer.name}")
elif answer.type == "predicate":
print(f"Visible damage probability: {answer.probability}")
来源示例 5(go):
// [中文] 用predicate检查产品图像是否有裂纹、撕裂或凹痕;判断时忽略阴影和包装损坏;按来源使用本地图片编码或图像URL,先准备对应素材。读取答案时区分refusal;probability是条件为真的估计概率,本次未验证素材或调用API。
package main
import (
"context"
"encoding/base64"
"fmt"
"os"
"github.com/openai/openai-go/v3"
)
func main() {
image, err := os.ReadFile("product.png")
if err != nil {
panic(err)
}
client := openai.NewClient()
decision, err := client.Decisions.New(context.Background(), openai.DecisionNewParams{
Model: "gpt-6-luna",
Input: openai.DecisionNewParamsInputUnion{
OfDecisionInputMessageArray: []openai.DecisionInputMessageParam{{
Content: openai.DecisionInputMessageContentUnionParam{
OfParts: []openai.DecisionInputPartUnionParam{
{OfInputText: &openai.DecisionInputTextParam{Text: "Inspect the product in this photo."}},
{OfInputImage: &openai.DecisionInputImageParam{
ImageURL: "data:image/png;base64," + base64.StdEncoding.EncodeToString(image),
}},
},
},
}},
},
Questions: []openai.DecisionNewParamsQuestionUnion{{
OfPredicate: &openai.DecisionNewParamsQuestionPredicate{
Name: openai.String("visible_damage"),
Instructions: openai.DecisionNewParamsQuestionPredicateInstructionsUnion{
OfString: openai.String("Does the product have visible damage, such as a crack, tear, or dent? Ignore shadows and damage to the packaging."),
},
},
}},
})
if err != nil {
panic(err)
}
switch answer := decision.Answers[0].AsAny().(type) {
case openai.DecisionAnswerPredicate:
fmt.Println(answer.Probability)
case openai.DecisionAnswerRefusal:
fmt.Printf("Decision refused for %s\n", answer.Name)
default:
panic("unexpected answer type")
}
}
来源示例 6(java):
// [中文] 用predicate检查产品图像是否有裂纹、撕裂或凹痕;判断时忽略阴影和包装损坏;按来源使用本地图片编码或图像URL,先准备对应素材。读取答案时区分refusal;probability是条件为真的估计概率,本次未验证素材或调用API。
import com.openai.models.decisions.DecisionCreateParams;
import com.openai.models.decisions.DecisionInputImage;
import com.openai.models.decisions.DecisionInputItem;
import com.openai.models.decisions.DecisionInputMessage;
import com.openai.models.decisions.DecisionInputPart;
import com.openai.models.decisions.DecisionInputText;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.List;
String imageBase64 =
Base64.getEncoder().encodeToString(Files.readAllBytes(Path.of("product.png")));
var message =
DecisionInputMessage.User.builder()
.contentOfParts(
List.of(
DecisionInputPart.ofInputText(
DecisionInputText.builder()
.text("Inspect the product in this photo.")
.build()),
DecisionInputPart.ofInputImage(
DecisionInputImage.builder()
.imageUrl("data:image/png;base64," + imageBase64)
.build())))
.build();
var decision =
client
.decisions()
.create(
DecisionCreateParams.builder()
.model("gpt-6-luna")
.inputOfDecisionInputItems(
List.of(
DecisionInputItem.ofDecisionInputMessage(
DecisionInputMessage.ofUser(message))))
.addQuestion(
DecisionCreateParams.Question.Predicate.builder()
.name("visible_damage")
.instructions(
"Does the product have visible damage, such as a crack, tear, or"
+ " dent? Ignore shadows and damage to the packaging.")
.build())
.build());
var answer = decision.answers().get(0);
if (answer.isRefusal()) {
System.out.println("Refused: " + answer.asRefusal().name().orElse("visible_damage"));
} else {
System.out.println(answer.asPredicate().probability());
}
来源示例 7(ruby):
## [中文] 用predicate检查产品图像是否有裂纹、撕裂或凹痕;判断时忽略阴影和包装损坏;按来源使用本地图片编码或图像URL,先准备对应素材。读取答案时区分refusal;probability是条件为真的估计概率,本次未验证素材或调用API。
require "base64"
require "openai"
image_base64 = Base64.strict_encode64(File.binread("product.png"))
client = OpenAI::Client.new
decision = client.decisions.create(
model: "gpt-6-luna",
input: [
{
role: :user,
content: [
{
type: :input_text,
text: "Inspect the product in this photo."
},
{
type: :input_image,
image_url: "data:image/png;base64,#{image_base64}"
}
]
}
],
questions: [
{
type: :predicate,
name: "visible_damage",
instructions: "Does the product have visible damage, such as a crack, tear, or dent? Ignore shadows and damage to the packaging."
}
]
)
answer = decision.answers.fetch(0)
case answer
when OpenAI::Models::Decision::Answer::Predicate
puts(answer.probability)
when OpenAI::Models::Decision::Answer::Refusal
warn("Decision refused for #{answer.name}")
else
raise("Unexpected answer type: #{answer.type}")
end
示意响应节选:
来源示例 8(json):
条件成立概率的示意响应,数值用于展示格式,不是本地测量结果。
{
"answers": [
{
"type": "predicate",
"name": "visible_damage",
"probability": 0.92
}
]
}
probability是模型对条件成立的估计概率。可根据自行选定的阈值,将照片标记为需要复核。
图像可以使用内联Base64数据URL,或公开可访问的HTTP/HTTPS URL。此端点不支持file_id。将用户消息中的input_text和input_image组合,可让模型结合指令及其他上下文评估图像。
在问题指令中包含图像
把所有问题共享的证据放在input。如果每个问题要使用不同图像,将该问题的instructions设为包含input_text和input_image的非空数组。这适用于predicate、choice和score;纯文本指令仍可使用字符串。
以下JSON请求体判断候选图B是否为共享参考图A的派生图或变体,包括重新压缩、缩放后的图像。将两个示例URL替换成公开可访问的图像地址,或使用Base64图像数据URL:
来源示例 9(json):
共享参考图A与问题候选图B分别放在input和instructions;判断候选图B是否为参考图A的派生图或变体,包括重新压缩、缩放的情况。示例地址需替换。
{
"model": "gpt-6-luna",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "The shared image is reference image A."
},
{
"type": "input_image",
"image_url": "https://example.com/reference.jpg"
}
]
}
],
"questions": [
{
"type": "predicate",
"name": "candidate_matches_reference",
"instructions": [
{
"type": "input_text",
"text": "Is candidate image B a derivative or variant of reference image A, including recompression or resizing?"
},
{
"type": "input_image",
"image_url": "https://example.com/candidate.jpg"
}
]
}
]
}
添加问题图像时:
- 每张候选图像对应新增一个问题;各问题分别将自己的候选图与同一共享参考图比较。
- 直接把内容部分放入
instructions,不加消息包装或role。 - 问题指令中的图像与
input中的图像共同占用请求的图像限制。
从固定选项中选择
choice从调用方给出的选项中选择一个值。各值应明确区分,并通过描述说明其适用条件。以下示例把客户投诉路由到相应部门:
来源示例 10(bash):
## [中文] 用choice判断重复扣款投诉应交给哪个部门:billing账务、technical技术、shipping配送、other其他。区分refusal和choice,并查看概率分布与confidence;由应用执行后续路由。
curl https://api.openai.com/v1/decisions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-luna",
"input": "I was charged twice for my order.",
"questions": [{
"type": "choice",
"name": "department",
"instructions": "Which department should handle this complaint?",
"choices": [
{"value": "billing", "description": "Payments, invoices, and refunds."},
{"value": "technical", "description": "Problems using the product."},
{"value": "shipping", "description": "Delivery and tracking."},
{"value": "other", "description": "Requests outside these categories."}
]
}]
}'
来源示例 11(javascript):
// [中文] 用choice判断重复扣款投诉应交给哪个部门:billing账务、technical技术、shipping配送、other其他。区分refusal和choice,并查看概率分布与confidence;由应用执行后续路由。
import OpenAI from "openai";
const client = new OpenAI();
const decision = await client.decisions.create({
model: "gpt-6-luna",
input: "I was charged twice for my order.",
questions: [
{
type: "choice",
name: "department",
instructions: "Which department should handle this complaint?",
choices: [
{ value: "billing", description: "Payments, invoices, and refunds." },
{ value: "technical", description: "Problems using the product." },
{ value: "shipping", description: "Delivery and tracking." },
{ value: "other", description: "Requests outside these categories." },
],
},
],
});
const answer = decision.answers[0];
if (answer.type === "refusal") {
console.log(`Refused: ${answer.name}`);
} else if (answer.type === "choice") {
console.log(
`Department: ${answer.choice} (confidence: ${answer.confidence})`
);
}
来源示例 12(python):
## [中文] 用choice判断重复扣款投诉应交给哪个部门:billing账务、technical技术、shipping配送、other其他。区分refusal和choice,并查看概率分布与confidence;由应用执行后续路由。
from openai import OpenAI
client = OpenAI()
decision = client.decisions.create(
model="gpt-6-luna",
input="I was charged twice for my order.",
questions=[
{
"type": "choice",
"name": "department",
"instructions": "Which department should handle this complaint?",
"choices": [
{"value": "billing", "description": "Payments, invoices, and refunds."},
{"value": "technical", "description": "Problems using the product."},
{"value": "shipping", "description": "Delivery and tracking."},
{"value": "other", "description": "Requests outside these categories."},
],
}
],
)
answer = decision.answers[0]
if answer.type == "refusal":
print(f"Refused: {answer.name}")
elif answer.type == "choice":
print(f"Department: {answer.choice} (confidence: {answer.confidence})")
来源示例 13(go):
// [中文] 用choice判断重复扣款投诉应交给哪个部门:billing账务、technical技术、shipping配送、other其他。区分refusal和choice,并查看概率分布与confidence;由应用执行后续路由。
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
)
func main() {
client := openai.NewClient()
decision, err := client.Decisions.New(context.Background(), openai.DecisionNewParams{
Model: "gpt-6-luna",
Input: openai.DecisionNewParamsInputUnion{OfString: openai.String("I was charged twice for my order.")},
Questions: []openai.DecisionNewParamsQuestionUnion{{
OfChoice: &openai.DecisionNewParamsQuestionChoice{
Name: openai.String("department"),
Instructions: openai.DecisionNewParamsQuestionChoiceInstructionsUnion{
OfString: openai.String("Which department should handle this complaint?"),
},
Choices: []openai.DecisionNewParamsQuestionChoiceChoice{
{
Value: openai.DecisionNewParamsQuestionChoiceChoiceValueUnion{OfString: openai.String("billing")},
Description: openai.String("Payments, invoices, and refunds."),
},
{
Value: openai.DecisionNewParamsQuestionChoiceChoiceValueUnion{OfString: openai.String("technical")},
Description: openai.String("Problems using the product."),
},
{
Value: openai.DecisionNewParamsQuestionChoiceChoiceValueUnion{OfString: openai.String("shipping")},
Description: openai.String("Delivery and tracking."),
},
{
Value: openai.DecisionNewParamsQuestionChoiceChoiceValueUnion{OfString: openai.String("other")},
Description: openai.String("Requests outside these categories."),
},
},
},
}},
})
if err != nil {
panic(err)
}
switch answer := decision.Answers[0].AsAny().(type) {
case openai.DecisionAnswerChoice:
fmt.Println(answer.Choice.AsString(), answer.Confidence, answer.Probabilities)
case openai.DecisionAnswerRefusal:
fmt.Printf("Decision refused for %s\n", answer.Name)
default:
panic("unexpected answer type")
}
}
来源示例 14(java):
// [中文] 用choice判断重复扣款投诉应交给哪个部门:billing账务、technical技术、shipping配送、other其他。区分refusal和choice,并查看概率分布与confidence;由应用执行后续路由。
import com.openai.models.decisions.DecisionChoiceOption;
import com.openai.models.decisions.DecisionCreateParams;
import com.openai.models.decisions.DecisionCreateParams.Question.Choice;
var decision =
client
.decisions()
.create(
DecisionCreateParams.builder()
.model("gpt-6-luna")
.input("I was charged twice for my order.")
.addQuestion(
Choice.builder()
.name("department")
.instructions("Which department should handle this complaint?")
.addChoice(
DecisionChoiceOption.builder()
.value("billing")
.description("Payments, invoices, and refunds.")
.build())
.addChoice(
DecisionChoiceOption.builder()
.value("technical")
.description("Problems using the product.")
.build())
.addChoice(
DecisionChoiceOption.builder()
.value("shipping")
.description("Delivery and tracking.")
.build())
.addChoice(
DecisionChoiceOption.builder()
.value("other")
.description("Requests outside these categories.")
.build())
.build())
.build());
var answer = decision.answers().get(0);
if (answer.isRefusal()) {
System.out.println("Refused: " + answer.asRefusal().name().orElse("department"));
} else {
var choice = answer.asChoice();
System.out.println(choice.choice().asString());
System.out.println(choice.probabilities());
System.out.println(choice.confidence());
}
来源示例 15(ruby):
## [中文] 用choice判断重复扣款投诉应交给哪个部门:billing账务、technical技术、shipping配送、other其他。区分refusal和choice,并查看概率分布与confidence;由应用执行后续路由。
require "openai"
client = OpenAI::Client.new
decision = client.decisions.create(
model: "gpt-6-luna",
input: "I was charged twice for my order.",
questions: [
{
type: :choice,
name: "department",
instructions: "Which department should handle this complaint?",
choices: [
{
value: "billing",
description: "Payments, invoices, and refunds."
},
{
value: "technical",
description: "Problems using the product."
},
{
value: "shipping",
description: "Delivery and tracking."
},
{
value: "other",
description: "Requests outside these categories."
}
]
}
]
)
answer = decision.answers.fetch(0)
case answer
when OpenAI::Models::Decision::Answer::Choice
puts(answer.choice, answer.confidence, answer.probabilities)
when OpenAI::Models::Decision::Answer::Refusal
warn("Decision refused for #{answer.name}")
else
raise("Unexpected answer type: #{answer.type}")
end
示意响应节选:
来源示例 16(json):
选项示意响应:billing为账务,technical为技术,shipping为配送,other为其他;保留概率和置信度字段。
{
"answers": [
{
"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
}
]
}
答案中的choice包含预先提供的一个值,本例为"billing";还会返回各选项的probabilities和单独的confidence字段。阈值设置见理解答案。
如果分类不能覆盖所有输入,应加入"other"等兜底选项。应用可将该结果送入通用复核队列。
按量表评分
score根据2到10个有序levels评估输入。为每个等级定义标准,并按从低到高排列。以下按严重程度评估问题:
来源示例 17(bash):
## [中文] 用score评估Safari导出失败、Chrome可用的问题;按外观问题、存在替代方案、完全阻塞三个有序等级计算。先判断refusal,再读取score、confidence及支持的分布字段;不把加权分数当作单选类别。
curl https://api.openai.com/v1/decisions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-luna",
"input": "Export fails in Safari but works in Chrome.",
"questions": [{
"type": "score",
"name": "severity",
"instructions": "How severe is this issue?",
"levels": [
{"label": "Cosmetic", "description": "Appearance only; no lost functionality."},
{"label": "Workaround available", "description": "A task fails, but another way works."},
{"label": "Fully blocked", "description": "A task fails with no workaround."}
]
}]
}'
来源示例 18(javascript):
// [中文] 用score评估Safari导出失败、Chrome可用的问题;按外观问题、存在替代方案、完全阻塞三个有序等级计算。先判断refusal,再读取score、confidence及支持的分布字段;不把加权分数当作单选类别。
import OpenAI from "openai";
const client = new OpenAI();
const decision = await client.decisions.create({
model: "gpt-6-luna",
input: "Export fails in Safari but works in Chrome.",
questions: [
{
type: "score",
name: "severity",
instructions: "How severe is this issue?",
levels: [
{
label: "Cosmetic",
description: "Appearance only; no lost functionality.",
},
{
label: "Workaround available",
description: "A task fails, but another way works.",
},
{
label: "Fully blocked",
description: "A task fails with no workaround.",
},
],
},
],
});
const answer = decision.answers[0];
if (answer.type === "refusal") {
console.log(`Refused: ${answer.name}`);
} else if (answer.type === "score") {
console.log(`Severity: ${answer.score} (confidence: ${answer.confidence})`);
}
来源示例 19(python):
## [中文] 用score评估Safari导出失败、Chrome可用的问题;按外观问题、存在替代方案、完全阻塞三个有序等级计算。先判断refusal,再读取score、confidence及支持的分布字段;不把加权分数当作单选类别。
from openai import OpenAI
client = OpenAI()
decision = client.decisions.create(
model="gpt-6-luna",
input="Export fails in Safari but works in Chrome.",
questions=[
{
"type": "score",
"name": "severity",
"instructions": "How severe is this issue?",
"levels": [
{
"label": "Cosmetic",
"description": "Appearance only; no lost functionality.",
},
{
"label": "Workaround available",
"description": "A task fails, but another way works.",
},
{
"label": "Fully blocked",
"description": "A task fails with no workaround.",
},
],
}
],
)
answer = decision.answers[0]
if answer.type == "refusal":
print(f"Refused: {answer.name}")
elif answer.type == "score":
print(f"Severity: {answer.score} (confidence: {answer.confidence})")
来源示例 20(go):
// [中文] 用score评估Safari导出失败、Chrome可用的问题;按外观问题、存在替代方案、完全阻塞三个有序等级计算。先判断refusal,再读取score、confidence及支持的分布字段;不把加权分数当作单选类别。
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
)
func main() {
client := openai.NewClient()
decision, err := client.Decisions.New(context.Background(), openai.DecisionNewParams{
Model: "gpt-6-luna",
Input: openai.DecisionNewParamsInputUnion{OfString: openai.String("Export fails in Safari but works in Chrome.")},
Questions: []openai.DecisionNewParamsQuestionUnion{{
OfScore: &openai.DecisionNewParamsQuestionScore{
Name: openai.String("severity"),
Instructions: openai.DecisionNewParamsQuestionScoreInstructionsUnion{
OfString: openai.String("How severe is this issue?"),
},
Levels: []openai.DecisionNewParamsQuestionScoreLevel{
{Label: "Cosmetic", Description: openai.String("Appearance only; no lost functionality.")},
{Label: "Workaround available", Description: openai.String("A task fails, but another way works.")},
{Label: "Fully blocked", Description: openai.String("A task fails with no workaround.")},
},
},
}},
})
if err != nil {
panic(err)
}
switch answer := decision.Answers[0].AsAny().(type) {
case openai.DecisionAnswerScore:
fmt.Println(answer.Score, answer.Confidence, answer.Probabilities)
case openai.DecisionAnswerRefusal:
fmt.Printf("Decision refused for %s\n", answer.Name)
default:
panic("unexpected answer type")
}
}
来源示例 21(java):
// [中文] 用score评估Safari导出失败、Chrome可用的问题;按外观问题、存在替代方案、完全阻塞三个有序等级计算。先判断refusal,再读取score、confidence及支持的分布字段;不把加权分数当作单选类别。
import com.openai.models.decisions.DecisionCreateParams;
import com.openai.models.decisions.DecisionCreateParams.Question.Score;
var decision =
client
.decisions()
.create(
DecisionCreateParams.builder()
.model("gpt-6-luna")
.input("Export fails in Safari but works in Chrome.")
.addQuestion(
Score.builder()
.name("severity")
.instructions("How severe is this issue?")
.addLevel(
Score.Level.builder()
.label("Cosmetic")
.description("Appearance only; no lost functionality.")
.build())
.addLevel(
Score.Level.builder()
.label("Workaround available")
.description("A task fails, but another way works.")
.build())
.addLevel(
Score.Level.builder()
.label("Fully blocked")
.description("A task fails with no workaround.")
.build())
.build())
.build());
var answer = decision.answers().get(0);
if (answer.isRefusal()) {
System.out.println("Refused: " + answer.asRefusal().name().orElse("severity"));
} else {
var score = answer.asScore();
System.out.println(score.score());
System.out.println(score.probabilities());
System.out.println(score.confidence());
}
来源示例 22(ruby):
## [中文] 用score评估Safari导出失败、Chrome可用的问题;按外观问题、存在替代方案、完全阻塞三个有序等级计算。先判断refusal,再读取score、confidence及支持的分布字段;不把加权分数当作单选类别。
require "openai"
client = OpenAI::Client.new
decision = client.decisions.create(
model: "gpt-6-luna",
input: "Export fails in Safari but works in Chrome.",
questions: [
{
type: :score,
name: "severity",
instructions: "How severe is this issue?",
levels: [
{
label: "Cosmetic",
description: "Appearance only; no lost functionality."
},
{
label: "Workaround available",
description: "A task fails, but another way works."
},
{
label: "Fully blocked",
description: "A task fails with no workaround."
}
]
}
]
)
answer = decision.answers.fetch(0)
case answer
when OpenAI::Models::Decision::Answer::Score
puts(answer.score, answer.confidence, answer.probabilities)
when OpenAI::Models::Decision::Answer::Refusal
warn("Decision refused for #{answer.name}")
else
raise("Unexpected answer type: #{answer.type}")
end
示意响应节选:
来源示例 23(json):
评分示意响应:等级0外观问题、1有替代方案、2完全阻塞;加权平均为1.1,置信度0.55。
{
"answers": [
{
"type": "score",
"name": "severity",
"score": 1.1,
"probabilities": [
{ "value": 0, "label": "Cosmetic", "probability": 0.1 },
{ "value": 1, "label": "Workaround available", "probability": 0.7 },
{ "value": 2, "label": "Fully blocked", "probability": 0.2 }
],
"confidence": 0.55
}
]
}
等级索引从0开始:本例0表示外观问题,1表示存在替代方案,2表示完全阻塞。score是概率加权平均,可以位于等级之间。本例概率为0.1、0.7、0.2,得到0×0.1 + 1×0.7 + 2×0.2 = 1.1。
答案还包含confidence及各等级的probabilities。分数概括整个等级分布;若要选择一个类别,应使用choice。
一次提出多个问题
单次请求可包含1到400个问题。把彼此独立的问题放入同一questions数组,共享输入证据。例如,一次请求可同时检查产品照片是否损坏并判断产品类别,各问题可以使用不同类型。
如果后一个决策依赖前一个答案,应拆成不同请求。例如先检查损坏,再据此决定是否请求维修类别。
问题应围绕可观察标准编写。不同关注点拆成不同问题,选项含义应明确,评分等级之间应有可区分的相邻标准。
理解答案
条件判断返回条件为真的估计概率;选择和评分返回概率分布,并附带单独的confidence字段。
用应用自身的标注样本设定路由、过滤或人工复核阈值,并考虑误报与漏报各自的成本。
用提示缓存复用共享输入
提示缓存让重复请求复用共享input中匹配的前缀,并按缓存读取价格计费。例如,将参考文档或图像保留在input,每次只修改问题。questions中的内容,包括问题专属图像,不属于可复用前缀。
Decisions默认在共享input末尾设置隐式缓存断点,无需修改现有请求体也可能受益。可复用前缀至少包含1,024个词元,问题内容不计入此阈值。跨请求保持前缀完全一致才能允许复用。
用prompt_cache_key按调用方提供的键划分缓存复用。需要控制边界时,在共享input中的文本或图像内容部分添加prompt_cache_breakpoint: {"mode": "explicit"}。将prompt_cache_options.mode设为"explicit",则只使用显式标记的边界;该模式下没有任何标记的请求不使用提示缓存。问题指令不支持缓存断点。
通过usage.input_tokens_details.cached_tokens查看缓存读取,usage.input_tokens_details.cache_write_tokens查看缓存写入。两者已计入usage.input_tokens,不要再次相加。缓存概念见提示缓存指南,请求控制项见Decisions参考。
监控用量
使用GET /v1/organization/usage/decisions获取组织的Decisions词元用量与请求数。认证需要管理员API密钥及api.usage.read权限。
选择时间范围与统计桶宽度,再按项目、API密钥或模型过滤、分组。num_model_requests统计请求数,不是问题数;一个请求有多个问题也只计一次。过滤与分页见Decisions用量参考。
价格与可用性
本次官方快照中,gpt-6-luna在Decisions端点的未缓存输入价格为每100万词元0.10美元。缓存命中采用有折扣的输入价格,缓存写入收费;读写单价与标准gpt-6-luna提示缓存价格一致。输出词元不收费。
区域处理附加费和长上下文输入价格倍率仍适用。上述规则用于/v1/decisions;使用gpt-6-luna的其他请求按相应模型与处理层级价格计费。
Decisions为符合条件的客户支持零数据保留(ZDR)和HIPAA用途。数据驻留覆盖所有受支持的API区域;区域处理支持美国及欧洲(欧洲经济区和瑞士)。资格要求、必要协议及限制见数据控制。
添加语音控制
将语音连接到Decisions,可以根据口头请求选择动作,或在用户、GPT-Live说话时作出反应。

TRAE-AI编程


更多建议: