OpenAI Decisions API
curl --request POST \
--url https://api.mixroute.ai/v1/decisionsimport requests
url = "https://api.mixroute.ai/v1/decisions"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/v1/decisions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.mixroute.ai/v1/decisions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixroute.ai/v1/decisions"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mixroute.ai/v1/decisions")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/v1/decisions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body决策模型
OpenAI Decisions API
通过 gpt-6-luna 调用 OpenAI 兼容 Decisions 接口:判断、分类、评分的参数、结构化结果与错误处理。
OpenAI Decisions API
curl --request POST \
--url https://api.mixroute.ai/v1/decisionsimport requests
url = "https://api.mixroute.ai/v1/decisions"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/v1/decisions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.mixroute.ai/v1/decisions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixroute.ai/v1/decisions"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mixroute.ai/v1/decisions")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/v1/decisions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body通过 MixRoute 的 OpenAI 兼容 Decisions 接口,对同一份输入提出具名问题并获得结构化答案。模型使用
任何问题都可能返回 type=refusal,其他问题仍可正常返回。按 name 或问题顺序匹配,先判断 type,再读取对应字段,并显式处理拒答。置信度和概率不保证判断正确。
图片使用公开 HTTP(S) URL 或 Base64 data URL,不使用 file_id。detail 可选 auto、low、high、original。developer/system 消息使用文本;assistant 消息使用输出文本或拒答项。工具结果通过 call_id 与调用匹配。此协议不接受文件、音频或条目引用。以上为协议格式,高级输入的实际可用性取决于 MixRoute 路由。
将示例图片地址替换为可公开访问的商品图片或 Base64 data URL。
结合 usage 与当前模型广场确认计费。不要假定 Responses 或 Chat Completions 的费率适用于 Decisions;实际费用取决于账户倍率和路由定价。
gpt-6-luna;此协议与 Jev System One 不同。
接入方式
POST https://api.mixroute.ai/v1/decisions
请求头使用 Authorization: Bearer $MIXROUTE_API_KEY 和 Content-Type: application/json。API Key 仅保存在服务端。模型和渠道权限取决于账户;模型出现在列表中不代表所有接口均可用。
使用
input,不是 state;questions 是可带 name 的数组,不是以问题 ID 为键的对象。真假判断用 predicate,不是 noul;分类用 choices,评分用 levels,不是 Jev 的 criteria。响应中的 answers 也是数组。Jev 协议见 System One。请求参数
| 字段 | 类型 | 要求 | 说明 |
|---|---|---|---|
model | string | 必填 | 使用 gpt-6-luna;不能直接替换成其他聊天模型或 Jev ID。 |
input | string / array | 必填 | 所有问题共同评估的输入:文本,或按顺序排列的消息、函数调用及结果、自定义工具调用及结果数组。 |
questions | object[] | 必填 | 包含 1-400 个 predicate、choice 或 score 问题的数组。各问题独立评估;若依赖上一个答案,应分开请求。 |
prompt_cache_key | string / null | 可选 | 调用方提供的缓存分区标识,最多 64 个字符。 |
prompt_cache_options | object / null | 可选 | 可选缓存设置。mode 为 implicit(默认)或 explicit;ttl 当前支持 30m。实际缓存可用性和计费取决于路由。 |
safety_identifier | string / null | 可选 | 不透明的终端用户标识,最多 128 个字符;建议使用稳定且不含个人信息的标识。 |
问题字段
| 字段 | 类型 | 要求 | 说明 |
|---|---|---|---|
type | string | 必填 | predicate、choice 或 score。 |
instructions | string / array | 必填 | 要作出的判断。使用文本字符串或非空的受支持内容项数组。文本和图片项直接放入 instructions,不加消息外层。 |
name | string | 可选 | 响应中原样返回的名称,建议每个问题使用不同名称;未命名的问题可返回 name=null。 |
choices | object[] | 按类型 | choice 必填,包含 2-255 个互不相同的选项。每项必填 value(字符串或布尔值),可选 description(字符串)。字符串 “true” 与布尔值 true 是不同值。 |
levels | object[] | 按类型 | score 必填,包含 2-10 个从低到高排列的等级。每项必填 label(字符串),可选 description(字符串);等级索引从 0 开始。 |
答案类型
| 类型 | 说明 |
|---|---|
predicate | probability 是条件成立的估计概率,范围 0-1,不是布尔值。 |
choice | choice 是给定的字符串或布尔选项。probabilities 是 value/probability 对象数组,另有 confidence 字段。 |
score | score 是等级索引的概率加权平均值,范围为 0 到 levels.length-1,可为小数。probabilities 包含 value(索引)、label 和 probability。 |
请求示例
调用前设置MIXROUTE_API_KEY。示例只提交一次,不自动重试;客户端超时不代表服务端没有执行推理。
- cURL
- Python
- JavaScript
curl --request POST "https://api.mixroute.ai/v1/decisions" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "gpt-6-luna",
"input": "CSV export fails on every attempt. The customer needs the file today and asks for a human agent.",
"questions": [
{
"type": "choice",
"name": "team",
"instructions": "Which team should handle this ticket?",
"choices": [
{
"value": "engineering",
"description": "Software defects"
},
{
"value": "billing",
"description": "Payments and refunds"
}
]
},
{
"type": "score",
"name": "urgency",
"instructions": "How soon does the customer need help?",
"levels": [
{
"label": "No deadline",
"description": "No deadline is specified."
},
{
"label": "This week",
"description": "Help is needed within a week."
},
{
"label": "Today",
"description": "Help is explicitly required today."
}
]
},
{
"type": "predicate",
"name": "needs_human",
"instructions": "Does the customer request a human agent?"
}
]
}'
import json
import os
import requests
payload = json.loads(r'''{
"model": "gpt-6-luna",
"input": "CSV export fails on every attempt. The customer needs the file today and asks for a human agent.",
"questions": [
{
"type": "choice",
"name": "team",
"instructions": "Which team should handle this ticket?",
"choices": [
{
"value": "engineering",
"description": "Software defects"
},
{
"value": "billing",
"description": "Payments and refunds"
}
]
},
{
"type": "score",
"name": "urgency",
"instructions": "How soon does the customer need help?",
"levels": [
{
"label": "No deadline",
"description": "No deadline is specified."
},
{
"label": "This week",
"description": "Help is needed within a week."
},
{
"label": "Today",
"description": "Help is explicitly required today."
}
]
},
{
"type": "predicate",
"name": "needs_human",
"instructions": "Does the customer request a human agent?"
}
]
}''')
response = requests.post(
"https://api.mixroute.ai/v1/decisions",
headers={"Authorization": "Bearer " + os.environ["MIXROUTE_API_KEY"]},
json=payload,
timeout=60,
allow_redirects=False,
)
response.raise_for_status()
result = response.json()
if not isinstance(result.get("answers"), list):
raise ValueError("Expected an answers array")
for answer in result["answers"]:
kind = answer["type"]
if kind == "refusal":
print(answer.get("name"), "refused")
continue
field = {"predicate": "probability", "choice": "choice", "score": "score"}.get(kind)
if field is None:
raise ValueError("Unexpected answer type: " + kind)
print(answer.get("name"), answer[field])
const apiKey = process.env.MIXROUTE_API_KEY;
if (!apiKey) throw new Error("Set MIXROUTE_API_KEY");
const payload = {
"model": "gpt-6-luna",
"input": "CSV export fails on every attempt. The customer needs the file today and asks for a human agent.",
"questions": [
{
"type": "choice",
"name": "team",
"instructions": "Which team should handle this ticket?",
"choices": [
{
"value": "engineering",
"description": "Software defects"
},
{
"value": "billing",
"description": "Payments and refunds"
}
]
},
{
"type": "score",
"name": "urgency",
"instructions": "How soon does the customer need help?",
"levels": [
{
"label": "No deadline",
"description": "No deadline is specified."
},
{
"label": "This week",
"description": "Help is needed within a week."
},
{
"label": "Today",
"description": "Help is explicitly required today."
}
]
},
{
"type": "predicate",
"name": "needs_human",
"instructions": "Does the customer request a human agent?"
}
]
};
const response = await fetch("https://api.mixroute.ai/v1/decisions", {
method: "POST",
headers: {
Authorization: "Bearer " + apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
signal: AbortSignal.timeout(60000),
redirect: "error",
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.error?.message ?? "HTTP " + response.status);
}
if (!Array.isArray(result.answers)) throw new Error("Expected an answers array");
for (const answer of result.answers) {
if (answer.type === "refusal") {
console.log(answer.name, "refused");
continue;
}
const field = { predicate: "probability", choice: "choice", score: "score" }[answer.type];
if (!field) throw new Error("Unexpected answer type: " + answer.type);
console.log(answer.name, answer[field]);
}
响应示例
同步返回 JSON 对象,不是 Chat Completions 的 choices 数组,也不是需要轮询的任务。概率和 token 用量会随请求变化。{
"model": "gpt-6-luna",
"answers": [
{
"type": "choice",
"name": "team",
"choice": "engineering",
"probabilities": [
{
"value": "engineering",
"probability": 1
},
{
"value": "billing",
"probability": 0
}
],
"confidence": 1
},
{
"type": "score",
"name": "urgency",
"score": 2,
"probabilities": [
{
"value": 0,
"label": "No deadline",
"probability": 0
},
{
"value": 1,
"label": "This week",
"probability": 0
},
{
"value": 2,
"label": "Today",
"probability": 1
}
],
"confidence": 1
},
{
"type": "predicate",
"name": "needs_human",
"probability": 1
}
],
"usage": {
"input_tokens": 416,
"input_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0
},
"output_tokens": 0,
"output_tokens_details": {
"reasoning_tokens": 0
},
"total_tokens": 416
}
}
| 字段 | 说明 |
|---|---|
model | 实际执行判断的模型。 |
answers | 与问题顺序一致的数组;先检查每项的 type 和 name。 |
usage.input_tokens | 本次请求的输入 token 用量。 |
usage.input_tokens_details | cached_tokens、cache_write_tokens 已包含在 input_tokens 中,不要重复相加。 |
usage.output_tokens / usage.output_tokens_details | 输出用量及 reasoning_tokens,不代表返回了聊天文本。 |
usage.total_tokens | 接口报告的总 token 用量。 |
结构化与图片输入
user 消息的 content 可包含 input_text(text)、input_image(image_url)、input_json(data)。JSON data 必须是对象或对象数组;其中的键仅为待判断的数据,不会触发图片抓取或创建消息。JSON 输入最多 32 层容器、10,000 个值、256 KiB 的紧凑 UTF-8 JSON。{
"model": "gpt-6-luna",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Evaluate the ticket record."
},
{
"type": "input_json",
"data": {
"ticket": {
"feature": "CSV export",
"fails": true,
"deadline": "today"
}
}
}
]
}
],
"questions": [
{
"type": "predicate",
"name": "deadline_today",
"instructions": "Does the ticket require action today?"
}
]
}
{
"model": "gpt-6-luna",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Inspect this product photo."
},
{
"type": "input_image",
"image_url": "https://example.com/product.png",
"detail": "auto"
}
]
}
],
"questions": [
{
"type": "predicate",
"name": "visible_damage",
"instructions": "Does the product show a crack, tear, or dent?"
}
]
}
可选提示词缓存
共享 input 至少达到 1,024 tokens 才具备缓存条件;questions 不属于可复用输入前缀。默认使用隐式断点;显式断点在共享 input 的文本或图片项中设置prompt_cache_breakpoint: {"mode": "explicit"}。prompt_cache_options.mode=explicit 且没有显式断点时不使用缓存。问题 instructions 不支持缓存断点。不要将上游缓存折扣或价格直接视为 MixRoute 费率。
错误与计费
先检查 HTTP 状态。网关错误可能包含 error.message、error.type、error.code、error.param,其中 param 可能为空。排查时保留 x-oneapi-request-id,不记录完整 API Key。| HTTP | 说明 |
|---|---|
| 400 invalid_request | 检查 input 和 questions 数组;问题对象映射属于 Jev 格式,不适用于本接口。 |
| 401 / 403 | 检查认证及接口、模型权限。 |
| 503 model_not_found | 当前 Key/分组没有该模型的可用渠道,不是模型返回的判断结果。 |
| 429 / 其他 5xx | 存在 Retry-After 时遵循该值,仅在适当情况下有限重试;结果不确定的超时不要自动重复提交。 |
{
"error": {
"message": "questions must be a non-empty array",
"type": "mixroute_error",
"param": "",
"code": "invalid_request"
}
}