# Decisions API — 类型化判断(Jev 等决策模型) Source: https://ofox.ai/zh/docs/api/decisions Decisions API 用来让模型对一段内容做**类型化判断**,而不是生成文本。你提供要判断的内容和一组问题,模型对每个问题返回一个结构化答案:是/否的概率、从选项中选一个、或在分级量表上打分,并附带每个选项的概率和置信度。 适合分类、路由、审核、打分、过滤等需要「程序直接拿结果做分支」的场景。模型只能在你给定的选项和分级里作答,不会返回选项以外的内容,也不需要解析自由文本。 首次使用判断模型时,建议先阅读 [Jev 使用指南](https://ofox.ai/zh/docs/develop/models/jev),其中包含快速开始、问题设计、返回结果说明与场景示例。本页为字段级参考。 ## 端点 三条路径背后是同一批模型、同一套计费,区别只在请求和响应的格式。按你使用的客户端选一条: | 路径 | 格式 | 适合 | |---|---|---| | `POST https://api.ofox.ai/v1/decisions` | OfoxAI 统一格式(问题为数组) | cURL、任意 HTTP 客户端、[OpenAI SDK](#openai-sdk) | | `POST https://api.ofox.ai/openai/v1/decisions` | 同上 | 已把 OpenAI SDK 的 `base_url` 设为 `https://api.ofox.ai/openai/v1` 的项目 | | `POST https://api.ofox.ai/typesafe/v1/systemone` | TypeSafe 官方 System One 格式(问题为对象) | [TypeSafe 官方 SDK](#typesafe-sdk),或照着 TypeSafe 官方文档写的代码 | 认证方式与其他接口相同:`Authorization: Bearer <你的 OFOXAI_API_KEY>`。只支持非流式,一次请求同步返回全部答案。 ## 可用模型 | 模型 ID | 说明 | |---|---| | `typesafe/jev-latest` | TypeSafe Jev,专用判断模型。仅文本或 JSON 输入,64K 上下文。可简写为 `jev-latest` | | `openai/gpt-6-luna` | 三条路径都可调用;可读图片(在[消息数组](#input)里传 `input_image`) | 支持该接口的完整模型列表见[模型页](https://ofox.ai/zh/models?output=decisions)。对普通对话模型(如 `openai/gpt-4o`)调用会返回 `endpoint_not_supported`。 ## 统一格式:`/v1/decisions` ### 请求参数 | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | `model` | string | ✅ | 模型 ID,如 `typesafe/jev-latest` | | `input` | string \| object \| array | ✅ | 要判断的内容,见[输入格式](#input) | | `questions` | array | ✅ | 问题列表,每个元素是一个[问题对象](#questions)。答案按同样顺序返回 | | `safety_identifier` | string | — | 稳定的终端用户 ID,仅对 OpenAI 模型生效 | ### 输入格式 `input` 支持三种写法: - **文本**:一个字符串。 ```json "input": "客户留言:我被重复扣款了,两封邮件都没人回,今天必须退款。" ``` - **结构化数据**:一个 JSON 对象,原样交给模型。问题里可以用反引号引用字段名,如 `` `message` ``。 ```json "input": { "ticket_id": 4812, "message": "我被重复扣款了。", "plan": "pro" } ``` - **消息数组**:`[{ "role", "content" }]`,`content` 为字符串或内容块列表,内容块只支持 `input_text` 与 `input_image`。图片仅对可读图片的模型有效,**Jev 不读图片**,传图片会返回 400。 ### 问题对象 | 字段 | 适用类型 | 说明 | |---|---|---| | `type` | 全部 | `predicate`(是/否)、`choice`(单选)、`score`(分级打分) | | `name` | 全部 | 可选,但建议填写。原样带回答案里,便于对应。同一请求内不能重复 | | `instructions` | 全部 | 问题本身。字符串,或包含问题和参考数据的 JSON 对象 | | `criteria` | `predicate` | 可选,`{ "true": "...", "false": "..." }`,说明「是」和「否」各指什么 | | `choices` | `choice` | 必填。选项数组,每项为 `{ "value": "billing", "description": "扣款、退款" }`,`description` 可省略。最多 255 项 | | `levels` | `score` | 必填。按从低到高排列的级别数组,每项为 `{ "label": "low", "description": "..." }`。2–10 级 | ### 请求示例 **cURL** ```bash filename="Terminal" curl https://api.ofox.ai/v1/decisions \ -H "Authorization: Bearer $OFOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "typesafe/jev-latest", "input": "客户留言:我被重复扣款了,两封邮件都没人回,今天必须退款。", "questions": [ { "type": "predicate", "name": "is_frustrated", "instructions": "客户是否不满?" }, { "type": "choice", "name": "category", "instructions": "这张工单属于哪一类?", "choices": [ { "value": "billing", "description": "扣款与退款" }, { "value": "bug", "description": "产品故障" }, { "value": "other", "description": "其他" } ] }, { "type": "score", "name": "urgency", "instructions": "需要多快由人工回复?", "levels": [ { "label": "low", "description": "一周内即可" }, { "label": "medium", "description": "应尽快回复" }, { "label": "high", "description": "今天必须回复" } ] } ] }' ``` **Python** ```python filename="decisions.py" showLineNumbers import os from openai import OpenAI client = OpenAI(base_url="https://api.ofox.ai/v1", api_key=os.environ["OFOX_API_KEY"]) result = client.decisions.create( model="typesafe/jev-latest", input="客户留言:我被重复扣款了,两封邮件都没人回,今天必须退款。", questions=[ {"type": "predicate", "name": "is_frustrated", "instructions": "客户是否不满?"}, { "type": "choice", "name": "category", "instructions": "这张工单属于哪一类?", "choices": [ {"value": "billing", "description": "扣款与退款"}, {"value": "bug", "description": "产品故障"}, {"value": "other", "description": "其他"}, ], }, ], ) is_frustrated, category = result.answers print(is_frustrated.probability) # 0.97 print(category.choice) # billing ``` **TypeScript** ```typescript filename="decisions.ts" showLineNumbers const res = await fetch('https://api.ofox.ai/v1/decisions', { method: 'POST', headers: { Authorization: `Bearer ${process.env.OFOX_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'typesafe/jev-latest', input: '客户留言:我被重复扣款了,两封邮件都没人回,今天必须退款。', questions: [ { type: 'predicate', name: 'is_frustrated', instructions: '客户是否不满?' } ] }) }) const { answers } = await res.json() console.log(answers[0].probability) ``` ### 响应格式 ```json { "model": "typesafe/jev-latest", "answers": [ { "type": "predicate", "name": "is_frustrated", "probability": 0.97 }, { "type": "choice", "name": "category", "choice": "billing", "confidence": 1, "probabilities": [ { "value": "billing", "probability": 1 }, { "value": "bug", "probability": 0 }, { "value": "other", "probability": 0 } ] }, { "type": "score", "name": "urgency", "score": 2, "confidence": 1, "legend": { "0": "low: 一周内即可", "1": "medium: 应尽快回复", "2": "high: 今天必须回复" }, "probabilities": [ { "value": 0, "label": "low", "probability": 0 }, { "value": 1, "label": "medium", "probability": 0 }, { "value": 2, "label": "high", "probability": 1 } ] } ], "usage": { "prompt_tokens": 407, "completion_tokens": 72, "total_tokens": 479 } } ``` `answers` 与 `questions` 一一对应、顺序相同。各类型答案的字段: | 类型 | 字段 | 说明 | |---|---|---| | `predicate` | `probability` | 答案为「是」的概率,0–1 | | `choice` | `choice` | 概率最高的选项 | | | `probabilities` | 每个选项的概率,合计为 1 | | | `confidence` | 模型对这次判断有多确定,0–1,见[概率与置信度](#confidence) | | `score` | `score` | 按概率加权的级别值,从 0 开始,**可以落在两级之间**(如 1.43) | | | `legend` | 级别编号到描述的对照 | | | `probabilities` | 每一级的概率 | | | `confidence` | 同上 | ## TypeSafe 原生格式:`/typesafe/v1/systemone` 与 [TypeSafe 官方 API](https://docs.typesafe.ai/api) 的请求和响应格式一致,适合直接使用 TypeSafe SDK 或迁移已有代码。和统一格式相比有三处不同: | | 统一格式 `/v1/decisions` | TypeSafe 原生格式 | |---|---|---| | 要判断的内容 | `input` | `state` | | 问题 | 数组,用 `name` 标识 | 对象,键名即问题 ID | | 是/否问题 | `type: "predicate"`,答案字段 `probability` | `type: "noul"`,答案字段 `noul` | | 选项与级别 | `choices` / `levels` 数组 | 都写在 `criteria` 里:choice 用 `{选项: 描述}` 对象,score 用描述字符串数组 | | 用量字段 | `prompt_tokens` / `completion_tokens` | `input_tokens` / `output_tokens` | ```bash filename="Terminal" curl https://api.ofox.ai/typesafe/v1/systemone \ -H "Authorization: Bearer $OFOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "jev-latest", "state": "Help! My payouts have been failing for 3 days.", "questions": { "is_urgent": { "type": "noul", "instructions": "Does this convey urgency?" }, "department": { "type": "choice", "instructions": "Which team should handle this?", "criteria": { "billing": "Payments, invoicing, refunds", "technical": "Bugs, outages, integrations", "sales": "Pricing, upgrades" } }, "frustration": { "type": "score", "instructions": "How frustrated is the customer?", "criteria": ["Calm", "Frustrated", "Very angry"] } } }' ``` ```json { "model": "typesafe/jev-latest", "answers": { "is_urgent": { "type": "noul", "noul": 0.95 }, "department": { "type": "choice", "choice": "billing", "confidence": 0.85, "probabilities": { "billing": 0.9, "technical": 0.1, "sales": 0 } }, "frustration": { "type": "score", "score": 1.03, "confidence": 0.95, "legend": { "0": "Calm", "1": "Frustrated", "2": "Very angry" }, "probabilities": { "0": 0, "1": 0.97, "2": 0.03 } } }, "usage": { "input_tokens": 399, "output_tokens": 73 } } ``` ## SDK 接入 ### OpenAI SDK OpenAI 官方 SDK 提供 `client.decisions.create()`,`base_url` 指向 `https://api.ofox.ai/v1` 即可,请求体使用[统一格式](#unified)。示例见上方 [Python 标签页](#example)。需使用包含 Decisions API 的 SDK 版本(实测 `openai` Python 3.31.0 可用)。 ### TypeSafe SDK TypeSafe 官方 SDK 把 `base_url` 指向 `https://api.ofox.ai/typesafe`,`api_key` 换成 OfoxAI API Key,其余代码不变: **Python** ```python filename="typesafe_sdk.py" showLineNumbers # pip install typesafe-sdk import os from typesafe_sdk import TypeSafeClient, Noul, Choice, Score with TypeSafeClient(base_url="https://api.ofox.ai/typesafe", api_key=os.environ["OFOX_API_KEY"]) as client: r = client.system_one( model="jev-latest", state={"message": "我被重复扣款了,两封邮件都没人回,今天必须退款。"}, questions={ "urgent": Noul(instructions="客户是否要求今天处理?"), "dept": Choice( instructions="应该由哪个团队处理?", criteria={"billing": "扣款、发票、退款", "technical": "故障、接入", "sales": "价格、升级"}, ), "anger": Score(instructions="客户有多不满?", criteria=["平静", "不满但礼貌", "非常愤怒"]), }, ) print(r.nouls["urgent"].noul) # 0.98 print(r.choices["dept"].choice) # billing print(r.scores["anger"].score) # 1.92 ``` **TypeScript** ```typescript filename="typesafe_sdk.ts" showLineNumbers // npm install @typesafe-ai/sdk import { TypeSafeClient, choice } from '@typesafe-ai/sdk' const client = new TypeSafeClient({ baseURL: 'https://api.ofox.ai/typesafe', apiKey: process.env.OFOX_API_KEY }) const response = await client.systemOne({ model: 'jev-latest', state: { message: '我被重复扣款了,今天必须退款。' }, questions: { category: choice('这张工单属于哪一类?', { billing: null, technical: null, other: null }) } }) ``` **环境变量** ```bash filename="Terminal" # 两个 SDK 都会读取这两个环境变量,代码无需改动 export TYPESAFE_BASE_URL="https://api.ofox.ai/typesafe" export TYPESAFE_API_KEY="$OFOX_API_KEY" ``` ## 概率与置信度 - **概率**回答「答案是什么」:`probability`、`probabilities` 是模型对各个答案的校准概率。 - **置信度**回答「该不该信这次判断」:`confidence` 由概率分布推出,分布越集中越高。两个选项各 0.5 时,`choice` 仍会给出一个,但 `confidence` 很低。 常见做法是在代码里设阈值:置信度高时自动执行,低时转人工或交给更强的模型复核。 ## 计费 按 token 计费,单价见[模型页](https://ofox.ai/zh/models/typesafe/jev-latest)。`typesafe/jev-latest` **只按输入 token 计费**,输出不计费(`completion_tokens` / `output_tokens` 照常返回)。 一次请求里的所有问题共享同一份输入,**把多个问题放进同一请求**比拆成多次调用便宜得多,也更快。 ## 限制 | 项目 | 限制 | |---|---| | 请求体 | 最大 32 MiB | | 上下文 | Jev 为 64K token,超出返回 400 | | choice 选项 | 最多 255 个 | | score 级别 | 2–10 级 | | JSON 嵌套 | `input`/`state`、`instructions`、`criteria` 各自最多 64 层 | | 流式 | 不支持 | ## 常见报错 | HTTP · type | 报错原文 | 原因 | 处理方法 | |---|---|---|---| | 400 `invalid_request_error` | `question "a" has kind choice and requires criteria options` | choice 问题没有 `choices` | 补上选项数组 | | 400 `invalid_request_error` | `question name "a" is used more than once` | 两个问题的 `name` 相同 | 改成不重复的名字 | | 400 `invalid_request_error` | `Too many score levels. Must have at most 10 levels.` | score 级别超过 10 个 | 合并级别,或拆成多个问题 | | 400 `invalid_request_error` | `decision input carries an "input_image" part, which Typesafe cannot read` | 给 Jev 传了图片 | 去掉图片,或改用可读图片的模型 | | 400 `invalid_request_error` | `Invalid request payload` | 在 `/v1/decisions` 上使用了 TypeSafe 原生格式(`state` + 对象形式的 `questions`) | 改用统一格式,或改调 `/typesafe/v1/systemone` | | 400 `endpoint_not_supported` | `Model 'openai/gpt-4o' does not support the /v1/decisions endpoint on this platform.` | 该模型不是判断模型 | 换用[可用模型](#models) | | 404 `model_not_found` | `Model 'typesafe/jev-9' not found` | 模型 ID 写错 | 使用 `typesafe/jev-latest` | | 404 `invalid_request_error` | `Unsupported API endpoint.` | 路径写成了 `/v1/systemone` | TypeSafe 原生格式的路径是 `/typesafe/v1/systemone` | 其他通用错误见[错误处理](https://ofox.ai/zh/docs/develop/guides/error-handling)。