Jev 决策
curl --request POST \
--url https://api.mixroute.ai/typesafe/v1/systemoneimport requests
url = "https://api.mixroute.ai/typesafe/v1/systemone"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/typesafe/v1/systemone', 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/typesafe/v1/systemone",
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/typesafe/v1/systemone"
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/typesafe/v1/systemone")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/typesafe/v1/systemone")
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决策模型
Jev 决策
TypeSafe Jev 的 Choice、Score、Noul 原生参数、结构化输入、响应与计费说明。
Jev 决策
curl --request POST \
--url https://api.mixroute.ai/typesafe/v1/systemoneimport requests
url = "https://api.mixroute.ai/typesafe/v1/systemone"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/typesafe/v1/systemone', 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/typesafe/v1/systemone",
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/typesafe/v1/systemone"
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/typesafe/v1/systemone")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/typesafe/v1/systemone")
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_bodyJev 是 TypeSafe 的结构化决策模型。输入业务状态
问题 ID 只用于请求与答案的对应,不参与模型推理;不要把真正的问题只写在 ID 中。多个问题针对相同 state 独立评估,可以混合三种类型,但不能依赖同一次请求中其他问题的答案。需要前后依赖时,在应用层分两次调用。
返回
等级索引从 0 开始:三个等级对应 0、1、2。
返回的
文字内容、instructions 和 criteria 都占用上下文预算。多问题请求中的 state 共用,但各个问题仍增加总输入量。不要把厂商的公开速率上限当作 MixRoute 账户的可用配额,实际限额以账户配置为准。
示例概率和 token 用量仅用于展示响应格式;不同输入或调用可能返回不同值。
在应用层设置概率/置信度阈值,并为不确定的输入保留人工处理或补充信息的路径。高 confidence 不保证结论正确;尤其要用自身业务数据验证非英语任务。
以上为美元基础单价,实际价格以 模型广场、账户分组倍率及账单为准。输入用量包括 state 和问题定义,更多问题与选项也会增加输入 token。响应的
网络超时不等于请求没有执行。重复提交会创建新的评估并可能再次计费,重试策略应由应用明确控制。
state 和具名问题 questions,同步获得分类、评分或真假概率,而不是生成聊天文本。
POST https://api.mixroute.ai/typesafe/v1/systemone
使用 MixRoute API Key,以 Authorization: Bearer $MIXROUTE_API_KEY 认证,Content-Type: application/json。请求体保留 TypeSafe 原生的 model、state、questions 层级,不使用 metadata、聊天 messages 或异步任务轮询。
支持模型
| 模型 | 调用 ID |
|---|---|
| Jev 1.13 | jev-1.13.0 / jev-latest |
jev-1.13.0 是固定版本 ID,jev-latest 是最新稳定版别名,当前都调用 Jev 1.13,属于同一个模型,不是两个独立型号。以后 latest 可能随新版本发布更新;需要固定行为时使用版本 ID,并读取响应的 model 确认实际版本。
仅使用账户 模型列表 中返回的完整型号。
选择问题类型
| 类型 | 适用情况 | 主要返回字段 |
|---|---|---|
choice | 从给定候选项中选择一项,如工单分类。 | choice, probabilities, confidence |
score | 沿有序、可描述的等级评分,如问题严重程度。 | score, legend, probabilities, confidence |
noul | 判断单个命题为真的概率,如是否请求退款。 | noul |
顶层参数
| 字段 | 类型 | 要求 | 说明 |
|---|---|---|---|
model | string | 必填 | jev-1.13.0 或 jev-latest。使用固定版本可避免别名更新影响集成。 |
state | string / object / array | 必填 | 所有问题共同评估的内容。可直接传文本、业务记录或对话数组;顶层不能是 null、数字或布尔值。JSON 内部可保留数字和布尔业务属性。 |
questions | object | 必填 | 非空问题映射,不是数组。每个键是自定义 question_id,每个值是一个问题对象。 |
问题参数
以下字段位于questions[question_id] 内。建议为每个问题显式填写 instructions,一次只描述一个明确的判断目标。
Choice 分类
| 字段 | 类型 | 要求 | 说明 |
|---|---|---|---|
type | string | 必填 | 固定为 choice。 |
instructions | string / object / array | 建议提供 | 说明模型应如何选择,复杂业务规则可使用对象或数组组织。 |
criteria | object | 必填 | 选项名到描述的映射,1-255 个选项,不使用 options 数组。选项名与描述都会参与判断。 |
criteria[option] | string / object / array / null | 按选项 | 该选项的描述;名称本身已足够清楚时可用 null。 |
choice 为概率最高的选项;probabilities 包含所有选项,概率和约为 1。可增加 other 或 insufficient_information 选项处理信息不足的输入。
Score 评分
| 字段 | 类型 | 要求 | 说明 |
|---|---|---|---|
type | string | 必填 | 固定为 score。 |
instructions | string / object / array | 建议提供 | 描述待评价的一个维度,例如严重程度。 |
criteria | array | 必填 | 有序等级描述,不能空,最多 10 个;建议至少两个。每项可以是字符串、对象或数组,不使用只有数字的评分标签。 |
score 是等级索引的概率加权位置,范围为 0 到等级数减 1,可以是小数,并非固定的 0-1 分数。legend 把字符串形式的索引映射回原始描述,probabilities 使用相同索引。使用返回的 score,不要直接截断为整数;需要离散等级时由应用选择映射规则。
Noul 真假判断
| 字段 | 类型 | 要求 | 说明 |
|---|---|---|---|
type | string | 必填 | 固定为 noul。 |
instructions | string / object / array | 建议提供 | 一个是非问题或待判断的陈述,高值始终表示更倾向于“是/真”。 |
criteria | object / null | 可选 | 补充真假标准,省略时按 instructions 判断。 |
criteria.true | string / object / array / null | 可选 | 什么情况算是“是/真”。 |
criteria.false | string / object / array / null | 可选 | 什么情况算是“否/假”。 |
noul 是 0-1 的概率,不是布尔值:接近 1 倾向于真,接近 0 倾向于假,接近 0.5 表示不确定。Noul 没有单独的 confidence 字段,也不是用于衡量程度的评分;程度问题使用 Score。
输入与上下文限制
| 项目 | 限制 |
|---|---|
| 输入模态 | 仅文本。支持文本字符串或包含文本及业务字段的 JSON 对象/数组;图像、音频、视频须先转换为文本。 |
| 请求总上下文 | state 与全部问题合计最多 64k tokens。 |
| 单问题上下文 | state 与最长的一个问题合计最多 32k tokens;必须同时满足总上下文限制。 |
| Choice | 每个问题最多 255 个选项;criteria 不能为空对象。 |
| Score | 每个问题最多 10 个等级;criteria 不能为空数组,建议至少两个有明确区分的等级。 |
请求示例
设置服务端环境变量MIXROUTE_API_KEY。下面在一次请求中混合三种问题。
curl --request POST "https://api.mixroute.ai/typesafe/v1/systemone" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "jev-latest",
"state": "I was charged twice for order 123. Please refund the duplicate charge today.",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this request?",
"criteria": {
"billing": "Duplicate charges, payments and refunds",
"technical": "Broken software and integration issues",
"shipping": "Shipment delivery and tracking"
}
},
"urgency": {
"type": "score",
"instructions": "How time-sensitive is the request?",
"criteria": [
"No deadline; routine request",
"Needs attention within a week",
"Explicitly requires action today"
]
},
"duplicate_charge": {
"type": "noul",
"instructions": "The customer was charged twice for the same order.",
"criteria": {
"true": "Explicit duplicate payment for the same order",
"false": "No duplicate payment is mentioned"
}
}
}
}'
响应示例
{
"model": "jev-1.13.0",
"answers": {
"department": {
"type": "choice",
"choice": "billing",
"confidence": 1,
"probabilities": {
"technical": 0,
"billing": 1,
"shipping": 0
}
},
"urgency": {
"type": "score",
"score": 2,
"confidence": 1,
"legend": {
"0": "No deadline; routine request",
"1": "Needs attention within a week",
"2": "Explicitly requires action today"
},
"probabilities": {
"0": 0,
"1": 0,
"2": 1
}
},
"duplicate_charge": {
"type": "noul",
"noul": 0.9
}
},
"usage": {
"input_tokens": 447,
"output_tokens": 70
}
}
| 字段 | 类型 | 要求 | 说明 |
|---|---|---|---|
model | string | 返回 | 实际处理请求的版本号,可能不同于请求中的别名。 |
answers | object | 返回 | 以原始 question_id 为键的答案映射;每项 type 与对应问题一致。 |
answers[id].type | string | 返回 | choice、score 或 noul,与请求中的对应问题类型相同。 |
answers[id].choice | string | Choice | 选中的选项名称,来自请求的 criteria 键。 |
answers[id].probabilities | object | Choice / Score | 选项名或等级索引到概率的映射;各值在 0-1 之间,合计约为 1。 |
answers[id].score | number | Score | 等级索引的概率加权位置,可为小数,范围由 criteria 的等级数决定。 |
answers[id].legend | object | Score | 字符串形式的等级索引到原始 criteria 描述的映射;描述保留字符串、对象或数组结构。 |
answers[id].noul | number | Noul | 命题为真的概率,范围 0-1,不是布尔值。 |
answers[id].confidence | number | Choice / Score | 0-1,从概率分布概括确定程度。不是结果必然正确的保证,也不应等同于最高选项概率。 |
usage.input_tokens | integer | 返回 | 用于本次评估的计费输入 token 数。 |
usage.output_tokens | integer | 返回 | 答案的输出 token 数;当前输出免费。 |
结构化输入
state、instructions 和描述性 criteria 可以使用原生 JSON 结构。以下示例同时展示对象指令、数组指令及结构化等级描述。{
"model": "jev-1.13.0",
"state": {
"incident": {
"feature": "export",
"symptom": "CSV export always fails",
"workaround": "Download JSON instead"
},
"customer_request": "Please fix this when convenient; no immediate deadline."
},
"questions": {
"route": {
"type": "choice",
"instructions": {
"question": "Which team owns the incident?",
"field": "incident"
},
"criteria": {
"engineering": {
"covers": [
"software errors",
"broken export"
],
"excludes": "billing"
},
"billing": [
"payments",
"refunds"
]
}
},
"impact": {
"type": "score",
"instructions": [
"Assess the functionality impact of incident only.",
"Use the documented workaround when judging."
],
"criteria": [
{
"description": "Cosmetic only",
"examples": [
"misaligned label"
]
},
[
"A feature fails but a workaround is available"
],
{
"description": "Completely blocked and no workaround"
}
]
},
"has_workaround": {
"type": "noul",
"instructions": {
"question": "Does incident describe a usable workaround?"
},
"criteria": {
"true": {
"description": "A concrete alternative is provided"
},
"false": [
"No alternative",
"Explicitly no workaround"
]
}
}
}
}
对话数组
对话记录直接作为 state 数组传入;这里的 role/text 是业务字段,不是 Chat Completions 的消息协议。{
"model": "jev-1.13.0",
"state": [
{
"role": "customer",
"text": "Please check order 123. It was charged twice."
},
{
"role": "agent",
"text": "The duplicate charge has now been refunded."
}
],
"questions": {
"refund_done": {
"type": "noul",
"instructions": "The agent says the duplicate charge has been refunded."
},
"shipment_lost": {
"type": "noul",
"instructions": "The conversation says a shipment was lost."
}
}
}
Python
需要 Python 3 和 requests。示例直接读取同步答案,不进行任务轮询或自动重复提交。import json
import os
import requests
def evaluate_jev(payload):
response = requests.post(
"https://api.mixroute.ai/typesafe/v1/systemone",
headers={"Authorization": "Bearer " + os.environ["MIXROUTE_API_KEY"]},
json=payload,
timeout=60,
allow_redirects=False,
)
request_id = response.headers.get("x-oneapi-request-id", "")
try:
result = response.json()
except ValueError as exc:
raise RuntimeError(
f"HTTP {response.status_code}; request_id={request_id}; invalid JSON"
) from exc
if not 200 <= response.status_code < 300:
detail = result.get("detail", result) if isinstance(result, dict) else result
raise RuntimeError(
f"HTTP {response.status_code}; request_id={request_id}; detail={detail}"
)
if not isinstance(result, dict) or not isinstance(result.get("answers"), dict):
raise RuntimeError("Invalid Jev response; request_id=" + request_id)
if set(result["answers"]) != set(payload["questions"]):
raise RuntimeError("Response question IDs do not match the request")
return result
if __name__ == "__main__":
payload = json.loads(r'''
{
"model": "jev-latest",
"state": "I was charged twice for order 123. Please refund the duplicate charge today.",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this request?",
"criteria": {
"billing": "Duplicate charges, payments and refunds",
"technical": "Broken software and integration issues",
"shipping": "Shipment delivery and tracking"
}
},
"urgency": {
"type": "score",
"instructions": "How time-sensitive is the request?",
"criteria": [
"No deadline; routine request",
"Needs attention within a week",
"Explicitly requires action today"
]
},
"duplicate_charge": {
"type": "noul",
"instructions": "The customer was charged twice for the same order.",
"criteria": {
"true": "Explicit duplicate payment for the same order",
"false": "No duplicate payment is mentioned"
}
}
}
}
''')
result = evaluate_jev(payload)
print(result["model"])
print(result["answers"]["department"]["choice"])
print(result["answers"]["urgency"]["score"])
print(result["answers"]["duplicate_charge"]["noul"])
print(result["usage"])
JavaScript
Node.js 18+,使用 ES module(.mjs)。API Key 仅保存在服务端,不放入浏览器代码。async function evaluateJev(payload) {
const apiKey = process.env.MIXROUTE_API_KEY;
if (!apiKey) throw new Error("Set MIXROUTE_API_KEY");
const response = await fetch("https://api.mixroute.ai/typesafe/v1/systemone", {
method: "POST",
headers: {
Authorization: "Bearer " + apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
redirect: "error",
signal: AbortSignal.timeout(60000),
});
const requestId = response.headers.get("x-oneapi-request-id") ?? "";
let result;
try {
result = await response.json();
} catch {
throw new Error("HTTP " + response.status + "; request_id=" + requestId + "; invalid JSON");
}
if (!response.ok) {
throw new Error("HTTP " + response.status + "; request_id=" + requestId +
"; detail=" + JSON.stringify(result?.detail ?? result));
}
if (!result?.answers || typeof result.answers !== "object" || Array.isArray(result.answers)) {
throw new Error("Invalid Jev response; request_id=" + requestId);
}
const requested = Object.keys(payload.questions).sort();
const returned = Object.keys(result.answers).sort();
if (JSON.stringify(requested) !== JSON.stringify(returned)) {
throw new Error("Response question IDs do not match the request");
}
return result;
}
const payload = {
"model": "jev-latest",
"state": "I was charged twice for order 123. Please refund the duplicate charge today.",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this request?",
"criteria": {
"billing": "Duplicate charges, payments and refunds",
"technical": "Broken software and integration issues",
"shipping": "Shipment delivery and tracking"
}
},
"urgency": {
"type": "score",
"instructions": "How time-sensitive is the request?",
"criteria": [
"No deadline; routine request",
"Needs attention within a week",
"Explicitly requires action today"
]
},
"duplicate_charge": {
"type": "noul",
"instructions": "The customer was charged twice for the same order.",
"criteria": {
"true": "Explicit duplicate payment for the same order",
"false": "No duplicate payment is mentioned"
}
}
}
};
const result = await evaluateJev(payload);
console.log(result.model);
console.log(result.answers.department.choice);
console.log(result.answers.urgency.score);
console.log(result.answers.duplicate_charge.noul);
console.log(result.usage);
价格与用量
| 模型 | 输入 / 百万 token | 输出 / 百万 token |
|---|---|---|
Jev 1.13 (jev-1.13.0 / jev-latest) | $0.042 | $0 |
usage.output_tokens 可以大于 0,但输出 token 不收费。
使用 usage.input_tokens 估算费用:输入 token 数 × 输入单价 ÷ 1,000,000,再应用账户倍率。平台按内部额度逐笔结算,取整后的账单可能与直接按美元计算的微小金额略有差异。
额度换算说明见 认证与额度。
响应处理
先检查 HTTP 状态,再读取 JSON。成功响应直接包含 answers;错误响应通常使用 detail,可能是字符串、对象或字段错误数组。保留响应头 x-oneapi-request-id 便于定位请求,不要记录完整 API Key。| 状态 | 处理方式 |
|---|---|
200 | 读取 model、answers 和 usage,按 question_id 对应结果。 |
400 / 422 | 检查 model、字段类型、非空约束、选项/等级数和上下文长度;修改请求后再发送。 |
401 / 403 | 检查 MixRoute Key、模型权限及认证请求头。 |
429 / 529 | 限流或上游繁忙;如有 Retry-After 则遵守,并采用有上限的退避重试。 |
5xx | 检查错误内容并保留请求 ID,避免无上限地重复提交。 |