决策模型
决策模型不生成文本,而是针对输入回答结构化的问题。每个问题属于以下三类之一:用概率回答的是/否判断、在若干命名选项中做出选择,或在有序刻度上打分。答案以概率和置信度的形式返回,应用可以据此设定阈值、做路由或记录日志。
AISIX 在两个 端点上提供决策模型,分别对应目前使用的两种请求格式:
| 端点 | 请求格式 | 问题类型 |
|---|---|---|
POST /v1/systemone | TypeSafe 的 System One 格式:model、state,以及按问题名称为键的 questions 对象。答案以相同的名称为键,usage 上报 input_tokens 和 output_tokens。 | noul(是/否)、choice、score |
POST /v1/decisions | OpenAI 的 Decisions 格式:model、input,以及 questions 数组。answers 是按问题顺序排列的数组,其中可能包含 refusal;usage 上报 input_tokens、output_tokens、total_tokens 及其明细。 | predicate(是/否)、choice、score |
任一端点都可以使用任一受支持的上游。当调用方的格式与上游不同时,AISIX 会转换请求和答案,详见格式转换。
两个端点都不支持流式。它们与其他代理端点使用相同的调用方 API Key、模型别名、访问控制、限流和预算,唯一的例外是安全护栏不会在这两个端点上运行。
支持的上游
模型所用服务提供方密钥的 provider 字段决定由哪个上游处理请求,以及上游使用哪种格式:
服务提供方密钥的 provider | 上游 | 格式 | 上游 URL |
|---|---|---|---|
typesafe | TypeSafe | System One | {api_base}/v1/systemone,api_base 默认为 https://api.typesafe.ai |
azure | Microsoft Foundry | System One | {资源根地址}/providers/microsoft/v1/systemone |
openrouter | OpenRouter | System One | {api_base}/systemone |
openai | OpenAI | Decisions | {api_base}/decisions,api_base 默认为 https://api.openai.com/v1 |
如果目标的服务提供方密钥使用其他 provider 值,请求会被拒绝并返回 400,错误信息会写出模型及其 provider 值,例如 model `my-model` uses provider `anthropic`; /v1/decisions requires a typesafe, azure, openai, or openrouter provider。
模型的 model_name 是 AISIX 作为 model 发送给上游的模型 ID:
| 上游 | model_name 示例 |
|---|---|
| TypeSafe | jev-latest |
| Microsoft Foundry | 你的 Foundry 资源中承载 Microsoft-Decision-1 的部署名称 |
| OpenAI | gpt-6-luna |
| OpenRouter | typesafe/jev-1.13 |
TypeSafe
创建一个 provider 为 typesafe 的服务提供方密钥,密钥值为你的 TypeSafe API Key。AISIX 会将其作为 Bearer Token 发送。api_base 为可选字段:留空时使用 https://api.typesafe.ai,也可以设置为其他 TypeSafe 端点的主机地址。AISIX 会在主机地址后追加 /v1/systemone,已经以 /v1 或 /v1/systemone 结尾的值也可以接受。
typesafe 服务提供方密钥既可以用于决策模型,也可以用作 TypeSafe jev 语义路由器的分类器凭据。AISIX Enterprise 和 AISIX Cloud 均不允许向量嵌入模型使用它。
Microsoft Foundry
使用 provider 为 azure 的服务提供方密钥,并将其 api_base 设置为承载 Microsoft-Decision-1 部署的 Foundry 资源端点,例如 https://acme-foundry.services.ai.azure.com。也可以粘贴项目端点(…/api/projects/<project>),或以 /openai/v1、/openai、/models、/v1 结尾的端点;AISIX 会先把它们还原为资源根地址,再追加 /providers/microsoft/v1/systemone。没有设置 api_base 的 Foundry 密钥会被拒绝并返回 400。
将模型的 model_name 设置为部署名称。认证方式与 Azure OpenAI 相同:资源 API Key 通过 api-key 请求头发送;Entra ID 客户端凭据会先换取 Token,再以 Authorization: Bearer <token> 发送。
OpenAI
使用 provider 为 openai 的服务提供方密钥。api_base 默认为 https://api.openai.com/v1,AISIX 调用 {api_base}/decisions。将 model_name 设置为支持 Decisions API 的模型,例如 gpt-6-luna。
OpenRouter
使用 provider 为 openrouter、api_base 为 https://openrouter.ai/api/v1 的服务提供方密钥,配置方式见 OpenRouter 指南。AISIX 调用 {api_base}/systemone。将 model_name 设置为 OpenRouter 的 System One 端点支持的模型,例如 typesafe/jev-1.13。
配置决策模型
决策模型就是一个普通的直接模型,只是它的服务提供方密钥使用上述四种 provider 值之一。下面的示例创建一个使用 TypeSafe 的模型。
AISIX Enterprise 或 AISIX Cloud
导出控制面连接信息和你的 TypeSafe API Key:
# AISIX_CP 是 Admin API 基础 URL;包含 /api,并省略末尾斜杠。
# 本地 AISIX Enterprise 快速入门使用 http://localhost:8080/api。
export AISIX_CP="YOUR_AISIX_CONTROL_PLANE_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
export TYPESAFE_API_KEY="YOUR_TYPESAFE_API_KEY"
创建服务提供方密钥,并允许它在该环境中使用:
TYPESAFE_KEY_ID=$(curl -sS -X POST "$AISIX_CP/provider_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "typesafe",
"provider": "typesafe",
"api_key": "'"$TYPESAFE_API_KEY"'",
"allowed_environments": ["'"$ENV_ID"'"]
}' | jq -r '.provider_key.id')
在该密钥上创建一个直接模型:
curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/models" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "jev",
"model_name": "jev-latest",
"provider_key_id": "'"$TYPESAFE_KEY_ID"'"
}'
在控制台中,先在 Provider Keys 页面创建 provider 为 typesafe 的密钥,再在 Models 页面创建直接模型并选择该密钥。表单会建议使用 jev-latest 作为上游模型 ID。
将该模型加入调用方 API Key 的允许模型列表,然后为它定价。
开源 AISIX 网关
在资源文件中添加服务提供方密钥和模型:
provider_keys:
- display_name: typesafe
provider: typesafe
api_key: ${TYPESAFE_API_KEY}
models:
- display_name: jev
provider: typesafe
model_name: jev-latest
provider_key: typesafe
将 jev 加入调用方 API Key 的 allowed_models,然后校验并重新加载完整的资源文件。
模型类型
决策端点支持以下模型类型:
- 直接模型,其服务提供方密钥的
provider为typesafe、azure、openai或openrouter。 - 路由模型,会像其他单次请求端点一样在目标之间故障转移,详见路由与故障转移。每个目标都必须是使用上述四种
provider值之一的决策模型;使用其他provider值的目标会直接以400结束请求,而不会转移到下一个目标。 - 通配符别名,与其他请求一样解析为直接模型。
合议模型、语义路由器和向量嵌入模型会被拒绝并返回 400,例如 model `my-ensemble` is a `ensemble` model; /v1/systemone serves direct and routing models only。
发送请求
导出网关连接信息和模型别名:
# AISIX_PROXY 不要包含末尾斜杠或 /v1 等端点路径。
# 本地快速入门使用 http://127.0.0.1:3000。
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export AISIX_MODEL="jev"
System One 格式
向 /v1/systemone 发送一个带命名 choice 问题的请求:
curl -sS -X POST "${AISIX_PROXY}/v1/systemone" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "'"${AISIX_MODEL}"'",
"state": "The API returns 500 on every call; engineering should look.",
"questions": {
"team": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "Charges and invoices",
"engineering": "Bugs and outages"
}
}
}
}'
答案以问题名称为键,model 为调用方发送的别名:
{
"model": "jev",
"answers": {
"team": {
"type": "choice",
"choice": "engineering",
"confidence": 0.97,
"probabilities": {
"billing": 0.03,
"engineering": 0.97
}
}
},
"usage": {
"input_tokens": 381,
"output_tokens": 62
}
}
noul 问题的答案是其 noul 字段中的概率。score 问题的答案包括 score、confidence、把每个等级序号映射到其标签的 legend,以及以等级序号为键的 probabilities。
Decisions 格式
把同一个问题作为数组元素发送到 /v1/decisions:
curl -sS -X POST "${AISIX_PROXY}/v1/decisions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "'"${AISIX_MODEL}"'",
"input": "The API returns 500 on every call; engineering should look.",
"questions": [
{
"type": "choice",
"name": "team",
"instructions": "Which team should handle this?",
"choices": [
{"value": "billing", "description": "Charges and invoices"},
{"value": "engineering", "description": "Bugs and outages"}
]
}
]
}'
答案按问题顺序返回:
{
"model": "jev",
"answers": [
{
"type": "choice",
"name": "team",
"choice": "engineering",
"probabilities": [
{"value": "billing", "probability": 0.03},
{"value": "engineering", "probability": 0.97}
],
"confidence": 0.97
}
],
"usage": {
"input_tokens": 381,
"input_tokens_details": {"cached_tokens": 0, "cache_write_tokens": 0},
"output_tokens": 62,
"output_tokens_details": {"reasoning_tokens": 0},
"total_tokens": 443
}
}
predicate 问题的答案是 probability。score 问题的答案包括 score、confidence,以及 probabilities 条目,每个条目以 value 给出等级序号,并带有该等级的 label 和 probability。类型为 refusal 的答案表示模型拒绝回答该问题。
使用 SDK
两家厂商的 SDK 都只需修改基础 URL 即可通过网关访问。
TypeSafe Python SDK 会在基础 URL 后追加 /v1/systemone,因此传入不带 /v1 的网关地址:
import os
from typesafe_sdk import Choice, TypeSafeClient
with TypeSafeClient(
api_key=os.environ["AISIX_API_KEY"],
base_url=os.environ["AISIX_PROXY"],
model="jev",
) as client:
response = client.system_one(
state="The API returns 500 on every call; engineering should look.",
questions={
"team": Choice(
instructions="Which team should handle this?",
criteria={"billing": "Charges and invoices", "engineering": "Bugs and outages"},
),
},
)
print(response.choices["team"].choice)
OpenAI Python SDK 会在基础 URL 后追加 /decisions,因此传入带 /v1 的网关地址:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["AISIX_API_KEY"],
base_url=os.environ["AISIX_PROXY"] + "/v1",
)
response = client.decisions.create(
model="jev",
input="The API returns 500 on every call; engineering should look.",
questions=[
{
"type": "choice",
"name": "team",
"instructions": "Which team should handle this?",
"choices": [
{"value": "billing", "description": "Charges and invoices"},
{"value": "engineering", "description": "Bugs and outages"},
],
}
],
)
print(response.answers[0])
格式转换
相同格式
当调用方的格式与上游一致时,AISIX 原样转发请求体,只把 model 改写为上游模型 ID。响应也原样返回,只把 model 改回调用方的别名。AISIX 不认识的字段在两个方向上都会透传,是否接受由上游决定。服务提供方密钥上配置的请求体覆盖仍然生效。
转换后的请求
当两种格式不同时,AISIX 会转换请求和答案。转换在以下几处会丢失或改写信息:
/v1/decisions的消息形式input会变成 System One 的state字符串:每条消息的文本片段以空行连接,消息之间同样以空行连接。- 当每个 Decisions 问题都有互不相同的
name时,System One 的键就是问题名称。只要有名称缺失或重复,所有问题都会改用位置作为键,即"0"到"n-1",答案也按 位置映射回来。 noul问题的true和false判定条件会以Answer true when: …和Answer false when: …的形式并入predicate的instructions。predicate会变成只有instructions的noul问题。- 布尔类型的选项值以
"true"和"false"作为键发送给 System One 上游,答案中会还原为布尔值。 - 带描述的评分等级以
"label: description"的形式作为判定条件发送给 System One 上游。答案中的标签取自请求;上游没有给出概率的等级,其概率报告为0。 - 没有
instructions的 System Onechoice或score问题发送给 OpenAI 时会带上默认说明,例如Which choice best fits the input?,因为 Decisions 格式要求必须有说明。 - 缺失的答案,或类型与问题不匹配的答案,在
/v1/decisions上会变成refusal;/v1/systemone没有 refusal 类型,因此会在answers中省略该答案。 - 一种格式中没有对应位置的字段会被丢弃。
以下请求无法转换,AISIX 在联系上游之前就会以 400 拒绝:
| 请求 | 上游 | 错误信息 |
|---|---|---|
带 input_image 内容片段的 /v1/decisions | TypeSafe、Foundry 或 OpenRouter | input_image content parts are not supported because this model's upstream accepts text input only |
带 safety_identifier 的 /v1/decisions | TypeSafe、Foundry 或 OpenRouter | `safety_identifier` is supported only when the model is served by OpenAI |
choice 或 score 问题的选项或等级少于 2 个的 /v1/systemone | OpenAI | OpenAI needs at least 2 choices or levels on every choice or score question |
带 audio 或 videos 的 /v1/systemone | OpenAI | audio and video input are not supported when the model is served by OpenAI |
不符合端点格式的请求体,例如缺少 state 的 /v1/systemone 请求,或包含未知类型问题的请求,在需要转换时同样会以 400 拒绝。
上游错误与格式错误的答案
上游返回 4xx 时,AISIX 会保留上游的状态码和错误信息。上游返回 5xx 时,AISIX 返回 502。可重试的失败会转移到路由模型的下一个目标。
对于转换后的请求,AISIX 会在回复前读取上游答案。如果响应不是 JSON、缺少 answers 集合,或者某个答案缺少其类型要求的字段,整个请求会以 502 失败,错误信息会写出该字段,例如 the decision upstream returned an unexpected decision response: `answers.team.confidence` is missing or not a number。这类失败与其他上游故障一样计入该目标。
治理与遥测
决策端点应用与其他模型端点相同的请 求侧控制:
- 调用方认证、模型访问权限,以及模型的
allowed_cidrs。 - 针对请求数和 Token 数的 API Key 与模型限流。Token 数为上游上报的输入与输出 Token 之和。
- AISIX Enterprise 或 AISIX Cloud 中的预算。
- 模型冷却、重试和故障转移。
挂载在模型或 API Key 上的安全护栏不会在 /v1/systemone 或 /v1/decisions 上运行,也不会做任何脱敏。不要依赖安全护栏来筛查决策流量。
每个请求都会产生用量事件,无论由哪个上游处理,/v1/systemone 的 operation 都是 systemone,/v1/decisions 的都是 decisions。事件中记录上游的输入和输出 Token,以及 OpenAI 上游上报的缓存命中、缓存写入和推理 Token 数。访问日志和请求指标与其他端点一样记录。
定价
使用与模型的 provider 和模型名称相匹配的组织级价格覆盖项为决策模型定价。models.dev 目录中没有 TypeSafe jev 模型、OpenRouter 的 typesafe/jev-1.13 或 Foundry 部署名称的价格,因此没有覆盖项时,它们的用量会记录为 $0.00 支出。
覆盖项还可以带一组可选的决策端点单价。在 Add pricing 对话框中展开 Decisions pricing (optional),或在 Admin API 请求中发送 decisions 对象。这些单价只适用于 /v1/systemone 和 /v1/decisions 上的请求,与调用方使用哪种格式无关:
- 设置了的单价会替换这些请求对应的基础单价。
- 留空的单价沿用对应的基础单价。
- 之后对生效的单价照常执行回退:缓存读取和缓存写入没有单独单价时按提示词单价计费,推理按补全单价计费。
当同一个模型在决策端点上的计费方式与其他端点不同时使用它。例如,gpt-6-luna 在目录中有通用价格;如果要让它的决策调用按不同单价计费,请为 openai / gpt-6-luna 添加一个同时包含基础单价和决策端点单价的覆盖项。
决策端点单价只影响记录的成本和预算。least_cost 路由仍按基础单价对目标排序。保存覆盖项会替换整条价格,因此通过 Admin API 保存价格时如果省略 decisions,会清除决策端点单价。
限制
- 后台健康探测。 后台探测使用 Chat Completions 请求探测模型。AISIX Enterprise 和 AISIX Cloud 均不允许在服务提供方密钥为
typesafe的模型上开启探测,也不允许把已开启探测的模型换到这类密钥上。对于使用azure、openai或openrouter密钥、只提供决策能力的模型,也不要开启探测:探测会失败并把模型标记为不健康。 - 合议模型和语义路由器。 服务提供方不提供 Chat Completions 的模型,例如使用
jina、runwayml或typesafe密钥的模型,不能作为合议模型的成员或评审模型,也不能作为语义路由器的目标。因为这些位置会发送 Chat Completions 请求,AISIX Enterprise 和 AISIX Cloud 均会拒绝这类引用。 - Playground。 Playground 发送的是 Chat Completions 请求,不支持决策模型,也不会列出使用
typesafe密钥的模型。 - 流式。 两个端点都不支持流式。
后续步骤
- 使用 TypeSafe Jev 的语义路由使用同一个决策模型为语义路由器选择路由。
- 模型定价说明覆盖项和目录价格如何解析。
- 指标与用量事件列出了所有
operation取值。