跳到主要内容
版本:Dev

决策模型

决策模型不生成文本,而是针对输入回答结构化的问题。每个问题属于以下三类之一:用概率回答的是/否判断、在若干命名选项中做出选择,或在有序刻度上打分。答案以概率和置信度的形式返回,应用可以据此设定阈值、做路由或记录日志。

AISIX 在两个端点上提供决策模型,分别对应目前使用的两种请求格式:

端点请求格式问题类型
POST /v1/systemoneTypeSafe 的 System One 格式:model、state,以及按问题名称为键的 questions 对象。答案以相同的名称为键,usage 上报 input_tokens 和 output_tokens。noul(是/否)、choice、score
POST /v1/decisionsOpenAI 的 Decisions 格式:model、input,以及 questions 数组。answers 是按问题顺序排列的数组,其中可能包含 refusal;usage 上报 input_tokens、output_tokens、total_tokens 及其明细。predicate(是/否)、choice、score

任一端点都可以使用任一受支持的上游。当调用方的格式与上游不同时,AISIX 会转换请求和答案,详见格式转换。

两个端点都不支持流式。它们与其他代理端点使用相同的调用方 API Key、模型别名、访问控制、限流和预算,唯一的例外是安全护栏不会在这两个端点上运行。

支持的上游​

模型所用服务提供方密钥的 provider 字段决定由哪个上游处理请求,以及上游使用哪种格式:

服务提供方密钥的 provider上游格式上游 URL
typesafeTypeSafeSystem One{api_base}/v1/systemone,api_base 默认为 https://api.typesafe.ai
azureMicrosoft FoundrySystem One{资源根地址}/providers/microsoft/v1/systemone
openrouterOpenRouterSystem One{api_base}/systemone
openaiOpenAIDecisions{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 示例
TypeSafejev-latest
Microsoft Foundry你的 Foundry 资源中承载 Microsoft-Decision-1 的部署名称
OpenAIgpt-6-luna
OpenRoutertypesafe/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 网关​

在资源文件中添加服务提供方密钥和模型:

resources.yaml(决策模型)
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 One choice 或 score 问题发送给 OpenAI 时会带上默认说明,例如 Which choice best fits the input?,因为 Decisions 格式要求必须有说明。
  • 缺失的答案,或类型与问题不匹配的答案,在 /v1/decisions 上会变成 refusal;/v1/systemone 没有 refusal 类型,因此会在 answers 中省略该答案。
  • 一种格式中没有对应位置的字段会被丢弃。

以下请求无法转换,AISIX 在联系上游之前就会以 400 拒绝:

请求上游错误信息
带 input_image 内容片段的 /v1/decisionsTypeSafe、Foundry 或 OpenRouterinput_image content parts are not supported because this model's upstream accepts text input only
带 safety_identifier 的 /v1/decisionsTypeSafe、Foundry 或 OpenRouter`safety_identifier` is supported only when the model is served by OpenAI
choice 或 score 问题的选项或等级少于 2 个的 /v1/systemoneOpenAIOpenAI needs at least 2 choices or levels on every choice or score question
带 audio 或 videos 的 /v1/systemoneOpenAIaudio 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 密钥的模型。
  • 流式。 两个端点都不支持流式。

后续步骤​