> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kapon.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# System One 调用

> 通过原生 HTTP 提交 Jev 分类、评分、真假判断与图片定位，并使用官方客户端调用文本决策。

> [!NOTE]
>
> 预览功能，需在目标环境开通 Jev。基础地址、令牌、可用模型和收费规则见 [TypeSafe / Jev](https://docs.kapon.cloud/typesafe/overview.md)。

## 请求字段

| 字段 | 说明 |
| - | - |
| `model` | 必填，使用当前令牌模型列表中的名称。 |
| `state` | 必填，待判断的材料，可以是字符串、JSON 对象或数组。 |
| `questions` | 必填，非空对象；键是你为问题取的名称，结果使用相同名称关联。 |
| `assets` | 图片请求使用的资源对象；本页示例通过唯一标识引用 PNG/JPEG 的 Base64 数据。 |

每个问题用 `type` 指定类型，`instructions` 描述判断要求，`criteria` 定义选项或等级。

| 类型 | `criteria` 要求 |
| - | - |
| `choice` | 对象，包含 1–255 个选项；键为选项名，值为说明，允许空字符串或 null 说明。 |
| `score` | 数组，包含 2–10 个等级说明，顺序表示等级顺序。 |
| `noul` | 可用 `instructions` 描述条件；也可用对象中的 `true`、`false` 描述判断标准，至少提供一种有效描述。 |
| `box` | 不要求 `criteria`；必须用 `instructions` 描述要定位的目标，需要具备 Box 能力的 Jev 1.14 供给。 |

材料、说明和选项的嵌套 JSON 会按原生协议转发。超出上游支持的长度或格式时会返回错误，不会通过截断材料来伪装成功。

## cURL

先按[接入说明](https://docs.kapon.cloud/typesafe/overview.md)设置 `ONEHUB_BASE_URL` 和 `ONEHUB_API_KEY`：

```bash theme={null}
curl "$ONEHUB_BASE_URL/typesafe/v1/systemone" \
  -H "Authorization: Bearer $ONEHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "jev-latest",
    "state": "The same order was charged twice. Please refund the duplicate charge.",
    "questions": {
      "refund_requested": {
        "type": "noul",
        "instructions": "Does the customer request a refund?"
      }
    }
  }'
```

成功响应包含 `model`、`answers` 和 `usage`。下面仅展示结构，判断值与用量不是固定结果：

```json theme={null}
{
  "model": "jev-1.13.0",
  "answers": {
    "refund_requested": {"type": "noul", "noul": 0.99}
  },
  "usage": {"input_tokens": 100, "output_tokens": 10}
}
```

## JSON 图片与 Box 定位

图片与 Box 属于 Jev 1.14 的实验能力，需确认当前令牌选择的模型及上游渠道支持。支持 JSON `assets` 中的 PNG/JPEG Base64；multipart、图片 URL 下载和新版 SDK 文件上传方式不在本页支持范围内。上面的文本示例和下方两个已验证版本的 SDK 文本示例继续适用。

请求添加 `TypeSafe-Danger-Zone-Images: true`，并在 `state` 中引用 `assets` 的同一个唯一标识。渠道若已显式配置该图片开关，其配置优先于客户请求头；平台不会因出现 Box 自动开启其他实验功能。

以下示例只使用 Python 标准库，生成一张 512×512 白底图，中央红块覆盖 x/y 的 128 至 383 像素，再生成 JSON 请求文件，不在命令中展开长 Base64。`ONEHUB_MODEL` 可指定当前令牌已获授权且有 1.14 供给的模型；默认使用 `jev-latest`。

```bash theme={null}
python3 - <<'PY'
import base64
import json
import os
import struct
import uuid
import zlib
from pathlib import Path

def chunk(kind, data):
    return struct.pack(">I", len(data)) + kind + data + struct.pack(">I", zlib.crc32(kind + data))

pixels = b"".join(
    b"\x00" + b"".join(
        b"\xff\x00\x00" if 128 <= x < 384 and 128 <= y < 384 else b"\xff\xff\xff"
        for x in range(512)
    ) for y in range(512)
)
png = b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", 512, 512, 8, 2, 0, 0, 0))
png += chunk(b"IDAT", zlib.compress(pixels)) + chunk(b"IEND", b"")
Path("red-square.png").write_bytes(png)
asset_id = str(uuid.uuid4())
request = {
    "model": os.environ.get("ONEHUB_MODEL", "jev-latest"),
    "state": "请观察这张测试图片：" + asset_id,
    "assets": {asset_id: {"type": "image", "format": "png", "data_base64": base64.b64encode(png).decode()}},
    "questions": {
        "has_rectangle": {"type": "noul", "instructions": "图中是否存在一个红色矩形？"},
        "rectangle": {"type": "box", "instructions": "图片中央的红色矩形"},
    },
}
Path("box-request.json").write_text(json.dumps(request, ensure_ascii=False), encoding="utf-8")
PY

curl "$ONEHUB_BASE_URL/typesafe/v1/systemone" \
  -H "Authorization: Bearer $ONEHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "TypeSafe-Danger-Zone-Images: true" \
  --data-binary @box-request.json
```

Box 回答结构如下，数值仅作说明，实际结果及用量以响应为准：

```json theme={null}
{
  "type": "box",
  "box": {"top": 0.25, "bottom": 0.75, "left": 0.25, "right": 0.75},
  "confidence": 0.9
}
```

四边坐标均为 0–1 的相对位置；横向乘图片宽度、纵向乘图片高度即可画回原图，且应满足 `left < right`、`top < bottom`。`confidence` 也是 0–1 的数字，Box 不要求 Choice/Score 所需的 `probabilities` 或 `legend`。它始终给出一个矩形，目标不存在时也不能只凭框判断存在性；需要时像示例一样搭配 Noul。Box、Noul、Choice、Score 可以放在同一请求，仍按该请求的最终用量结算。

## Python 官方客户端

以下示例基于已验证的 `typesafe-sdk==0.7.4`：

```bash theme={null}
pip install typesafe-sdk==0.7.4
```

```python theme={null}
import os
from typesafe_sdk import TypeSafeClient, RetryPolicy, Choice, Score, Noul

with TypeSafeClient(
    api_key=os.environ["ONEHUB_API_KEY"],
    base_url=os.environ["ONEHUB_BASE_URL"].rstrip("/") + "/typesafe",
    retry=RetryPolicy(max_retries=0),
    timeout=35,
) as client:
    print([model.name for model in client.models.list().models])
    result = client.system_one(
        model="jev-latest",
        state={"ticket": "The same order was charged twice. Please refund the duplicate charge."},
        questions={
            "team": Choice(
                instructions="Which team handles this ticket?",
                criteria={"billing": "Payments and refunds", "technical": "Software problems", "other": "Other topics"},
            ),
            "refund_requested": Noul(instructions="Does the customer request a refund?"),
            "urgency": Score(
                instructions="How urgent is the ticket?",
                criteria=["Routine", "Time sensitive", "Immediate emergency"],
            ),
        },
    )
    print(result.choices["team"].choice)
    print(result.nouls["refund_requested"].noul)
    print(result.scores["urgency"].score)
    print(result.model, result.usage.input_tokens, result.usage.output_tokens)
```

## JavaScript 官方客户端

以下示例基于已验证的 `@typesafe-ai/sdk@0.6.0`，使用 Node.js 的 `.mjs` 文件运行：

```bash theme={null}
npm install @typesafe-ai/sdk@0.6.0
```

```javascript theme={null}
import { TypeSafeClient } from "@typesafe-ai/sdk";

const client = new TypeSafeClient({
  apiKey: process.env.ONEHUB_API_KEY,
  baseURL: process.env.ONEHUB_BASE_URL.replace(/\/$/, "") + "/typesafe",
  retry: { maxRetries: 0 },
  timeout: 35000,
});

const models = await client.models.list();
console.log(models.map((model) => model.name));
const result = await client.systemOne({
  model: "jev-preview",
  state: ["The same order was charged twice.", "Please refund the duplicate charge."],
  questions: {
    team: {
      type: "choice",
      instructions: "Which team handles this ticket?",
      criteria: { billing: "Payments and refunds", technical: "Software problems", other: "Other topics" },
    },
    refund_requested: { type: "noul", instructions: "Does the customer request a refund?" },
    urgency: {
      type: "score",
      instructions: "How urgent is the ticket?",
      criteria: ["Routine", "Time sensitive", "Immediate emergency"],
    },
  },
});
console.log(result.answers);
console.log(result.model, result.usage);
```

这两个版本的模型列表返回值不同：Python 使用 `client.models.list().models`，JavaScript 的 `client.models.list()` 直接返回数组。调用时使用自己的平台令牌；不要把管理员配置的上游密钥放进客户应用。

## 读取答案与失败处理

`answers` 按问题名称返回答案。Choice 的 `choice` 对应提交的选项，Score 的 `legend` 解释等级；概率和置信度应按业务需要使用，不应直接视为判断必然正确的保证。

默认只按有效的最终输入用量收费，输出字段仍保留用于对账。错误、断开、重试和扣费的关系见[失败时是否收费](https://docs.kapon.cloud/typesafe/overview.md#失败时是否收费)；查询消费记录时同时保留本次请求的模型名称和 `X-Oneapi-Request-Id` 响应头。


## OpenAPI

````yaml POST /typesafe/v1/systemone
openapi: 3.0.3
info:
  title: TypeSafe / Jev API
  version: 1.0.0-preview
  description: 预览功能，仅用于已开通 Jev 的 OneHub 环境。使用平台模型调用令牌。
servers:
  - url: https://your-onehub.example
    description: 替换为已开通 Jev 的环境域名
security:
  - BearerAuth: []
paths:
  /typesafe/v1/systemone:
    post:
      tags:
        - TypeSafe
      summary: 提交原生分类、评分和真假判断
      operationId: createSystemOne
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - model
                - state
                - questions
              additionalProperties: true
              properties:
                model:
                  type: string
                  minLength: 1
                  description: 当前令牌模型列表中的名称。
                  example: jev-latest
                state:
                  $ref: '#/components/schemas/Content'
                questions:
                  type: object
                  minProperties: 1
                  description: 键为问题名称，答案按相同名称返回。
                  additionalProperties:
                    type: object
                    required:
                      - type
                    additionalProperties: true
                    properties:
                      type:
                        type: string
                        enum:
                          - choice
                          - score
                          - noul
                      instructions:
                        description: >-
                          问题说明，可为字符串、对象、数组或 null。Noul 至少需要 instructions 或
                          criteria。
                        nullable: true
                      criteria:
                        description: >-
                          Choice 使用含 1–255 个选项的对象；Score 使用含 2–10 个等级的数组；Noul 可使用
                          true、false 标准对象。
            example:
              model: jev-latest
              state: The customer requests a refund.
              questions:
                refund_requested:
                  type: noul
                  instructions: Does the customer request a refund?
      responses:
        '200':
          description: 原生答案与有效最终用量。默认仅输入计费；响应版本不自动成为可调用模型。
          headers:
            X-Oneapi-Request-Id:
              description: 平台请求关联号，用于查询消费记录和排查失败。
              schema:
                type: string
          content:
            application/json:
              schema:
                type: object
                required:
                  - model
                  - answers
                  - usage
                additionalProperties: true
                properties:
                  model:
                    type: string
                    example: jev-1.13.0
                  answers:
                    type: object
                    additionalProperties:
                      type: object
                      description: 按问题类型返回 choice、score 或 noul，以及对应概率、置信度或等级说明。
                      additionalProperties: true
                  usage:
                    type: object
                    required:
                      - input_tokens
                    additionalProperties: true
                    properties:
                      input_tokens:
                        type: integer
                        minimum: 0
                      output_tokens:
                        type: integer
                        nullable: true
                        minimum: 0
              example:
                model: jev-1.13.0
                answers:
                  refund_requested:
                    type: noul
                    noul: 0.99
                usage:
                  input_tokens: 100
                  output_tokens: 10
        default:
          $ref: '#/components/responses/Error'
components:
  schemas:
    Content:
      description: 文本材料或其结构化 JSON 表达，不表示图像、音视频输入能力。
      oneOf:
        - type: string
        - type: object
          additionalProperties: true
        - type: array
          items: {}
  responses:
    Error:
      description: 返回实际 HTTP 状态与可读错误。可能为 TypeSafe 原生错误或兼容错误包装；有最终用量的失败仍可能计费。
      headers:
        Retry-After:
          description: 上游提供的重试等待秒数或 HTTP 日期，主要用于 429、529。
          schema:
            type: string
      content:
        application/json:
          schema:
            type: object
            additionalProperties: true
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: 使用平台签发的模型调用令牌，不填写上游密钥。

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.