2026 年 9 月 15 日,TypeSafe AI 发布了 Jev——第一个 System One 模型。它不聊天、不写代码、不生成任何一个字,只输出带校准概率的结构化判断。

这不是又一个"更快更便宜的小模型"。它把 AI 的能力边界重新切了一刀:把「判断」从「生成」里拆出来,做成一次函数调用。

这篇文章从零讲清:怎么调、每个参数什么意思、什么时候该用它、以及最容易踩的坑。

一、Jev 到底是个什么东西

名字来自卡尼曼的《思考,快与慢》。LLM 是 System 2——慢、深、逐 token 推理;Jev 想做 System 1——快、直觉、一次给出判断。

传统的自回归 LLM:输入 token 序列,一个一个吐出 token,直到生成结束。Jev 砍掉了整个逐 token 解码过程,改用并行采样,在一次前向计算里同时产出所有判断结果

它的能力面被压缩到极窄的三件事:

原语回答什么返回什么
Choice这几个选项里是哪个?choiceprobabilitiesconfidence
Score处在哪个等级?scorelegendprobabilitiesconfidence
Noul这件事是真的吗?noul(0 到 1 的概率)

除此之外,它什么都不会。

代价换来的是:70–500 毫秒的端到端延迟、输入 $0.042/百万 token、输出完全免费、类型错误率数学上为 0。相比前沿 LLM,快了 40–200 倍,便宜了最多 444 倍。

值得强调的一点:输出永远锁定在你预设的选项集合内。代码不需要从自由文本里捞值,也不需要 JSON 解析兜底——这是它敢宣称"零类型错误"的机制来源。

它的定位不是替代 LLM,而是做 Agent 系统的前置反射弧:让前沿模型专注复杂推理,把所有高频小判断——路由、分类、风控初筛、内容过滤、是否终止——交给 Jev。

二、准备工作

2.1 拿 API Key

typesafe.ai 加入 waitlist,通过后在 console.typesafe.ai 获取 API Key。

Console 里的 Playground 很有用:可以可视化地配置问题、定义 Schema,直接看到带概率的决策结果。建议先在 Playground 里把 Schema 调好,再写代码。

2.2 装 SDK

# Python
pip install typesafe-sdk

# JavaScript / TypeScript
npm install @typesafe-ai/sdk

SDK 会自动处理请求构造、类型校验,以及 429/529 的指数退避重试。

2.3 设环境变量

export TYPESAFE_API_KEY="你的 key"

SDK 默认读取这个变量。

三、第一个请求

先看最小可用的 HTTP 调用:

POST https://api.typesafe.ai/v1/systemone
Authorization: Bearer <API_KEY>
Content-Type: application/json
{
  "state": "Help! My payouts have been failing for 3 days.",
  "model": "jev-latest",
  "questions": {
    "is_urgent": {
      "type": "noul",
      "instructions": "Does this convey urgency?"
    }
  }
}

返回:

{
  "model": "jev-latest",
  "answers": {
    "is_urgent": {
      "type": "noul",
      "noul": 0.92
    }
  },
  "usage": { "input_tokens": 312, "output_tokens": 48 }
}

0.92 —— 92% 的概率"这条消息传达了紧急感"。

用 Python SDK 是同样的形状:

from typesafe_sdk import TypeSafeClient

with TypeSafeClient() as client:
    response = client.system_one(
        state="Help! My payouts have been failing for 3 days.",
        questions={
            "is_urgent": {
                "type": "noul",
                "instructions": "Does this convey urgency?",
            },
        },
    )

print(response.answers["is_urgent"].noul)

已经是全部的核心流程了。 剩下的都是细节。

四、请求参数完全手册

顶层请求体只有三个字段:

字段类型必填说明
statestring | object | array被评估的内容。是材料,不是问题
modelstring目前填 jev-latest
questionsmap<string, Question>题目映射。key 由你定,答案用同一个 key 返回

4.1 state:你要判断的材料

三种形态:

形态适合场景例子
字符串单条消息、文章、段落"My card was charged twice."
对象(推荐)命名字段、关联记录、应用状态{"message": "...", "order_id": "A-104"}
数组消息序列、记录列表["Hi", "My number is TS1337.", "我卡被扣了两次。"]

默认用对象。 每个部分有名字,字段之间的关系才清晰。文档给的心智模型很好:把 state 想象成"递给专家小组做判断之前,要先摆到桌面上的全部材料"。

{
  "ticket": {
    "subject": "Duplicate charge",
    "messages": [
      {"from": "customer", "text": "I was charged twice for order A-104. Please refund the duplicate."},
      {"from": "support", "text": "We are checking the charges."}
    ]
  },
  "order": {
    "id": "A-104",
    "charges": [
      {"amount_usd": 49, "status": "captured"},
      {"amount_usd": 49, "status": "captured"}
    ]
  },
  "refund_policy": "Duplicate charges are eligible for a refund."
}

这一整块算一个 state,即使里面既有对话、又有订单、又有政策。判断需要对比哪几个部分,就把它们放在一起。

硬限制:Jev 只吃文本。 图片、音频、视频一律不支持(至少目前)。非文本输入必须先转成文本或结构化字段。另一个关键限制:主要训练语言是英文,中文等 CJK 文字可以使用,但准确率明显更低。 中文生产环境务必自己测数据,并且紧盯 confidence。

4.2 questions:每道题的四个字段

字段说明
key(题目 ID)你起的名字。不会发给模型,也不参与推理——纯粹给你的代码做映射用
type"noul" / "choice" / "score"
instructions核心字段。要评估的具体判断,支持字符串、对象、数组
criteria答案空间。形态随 type 而变

最容易犯的错:以为题目 ID 会告诉模型什么。 你写 "refund_requested",模型完全看不到这个 key。instructions 里必须把问题写完整,别指望 ID 自带语义。

4.3 三种 Question 的 criteria 形态

Noul(可选):

"is_urgent": {
  "type": "noul",
  "instructions": "Does this convey urgency?",
  "criteria": {
    "true": "Explicitly time-sensitive",
    "false": "No urgency expressed"
  }
}

Choice(必填,map<string, string|null>):

"department": {
  "type": "choice",
  "instructions": "Which team should handle this?",
  "criteria": {
    "billing": "Payments, invoicing, refunds",
    "technical": "Bugs, outages, integrations",
    "sales": "Pricing, upgrades, new accounts"
  }
}

选项之间无序。如果选项集合可能覆盖不全,加一个 othernone of the above

Score(必填,有序数组,至少 2 个等级):

"frustration": {
  "type": "score",
  "instructions": "How frustrated is the customer?",
  "criteria": ["Calm", "Frustrated", "Very angry"]
}

4.4 响应体

{
  "model": "jev-latest",
  "answers": { "<你给的 key>": { "...": "..." } },
  "usage": { "input_tokens": 312, "output_tokens": 48 }
}

model 返回的是具体版本 ID(如 jev-1.13.0),不是别名。这一点很重要——见第十节的坑。

三种答案的具体结构:

// Noul:注意没有 confidence
{ "type": "noul", "noul": 0.92 }

// Choice
{
  "type": "choice",
  "choice": "technical",
  "probabilities": { "billing": 0.08, "technical": 0.85, "sales": 0.07 },
  "confidence": 0.82
}

// Score
{
  "type": "score",
  "score": 1.6,
  "legend": { "0": "Calm", "1": "Frustrated", "2": "Very angry" },
  "probabilities": { "0": 0.05, "1": 0.3, "2": 0.65 },
  "confidence": 0.78
}

Score 的 score概率加权后的连续值,会落在两个等级之间(1.6 就是"介于 Frustrated 和 Very angry 之间")。legend 把数字索引映射回你的等级描述。

五、三种原语怎么选

判断标准只有一条:哪种答案形态能让你的代码直接行动。

  • Choice —— 答案落在无序的已知集合里。工单派给哪个部门、文档是什么类型、代码是什么语言。选项映射到代码分支最直接。
  • Score —— 答案落在一条能描述清楚的光谱上。Bug 严重度、客户愤怒度、技能水平。等级由你定义。
  • Noul —— 干净的是非题,且概率本身就有信息量。这条消息是否在报 Bug?是否在要求退款?

别混淆 Noul 和 Score

这是新手最常翻车的地方:

"这个候选人 Python 强不强?" —— 坏问题。

Noul 返回 0.5 的意思是"是和否概率相等",不是"中等水平"。条件定义不清,这个概率根本没法解读。

正确做法二选一:

  • 想测水平 → 用 Score,明确定义等级:["无经验", "会一点", "日常使用", "深度专家"]
  • 想要是非 → 把条件写死:"简历是否写明候选人在工作中使用过 Python?"

好问题 vs 坏问题

System One 模型是为**"一个懂行的人在有一秒时间、且手握足够上下文时能做出的判断"**设计的。

  • ✅ 好问题:"这条消息是否传达了紧急感?"
  • ❌ 坏问题:"分析这条消息并决定最佳行动方案。"

后者需要慢推理。看到这类问题就是信号:拆成几个小问题,答案在代码里组合。

比如"给这个创业项目打分"应该拆成:市场规模、技术可行性、差异化——三个独立的 Score 问题,然后在代码里按重要性加权。优先级变了就改权重数字,不用重写 prompt。

六、把 state 设计对:字段路径引用

state 是结构化对象时,instructions 里要用反引号包裹的点加索引路径,明确点名要判断的是哪一部分:

questions = {
    "refund_requested": {
        "type": "noul",
        "instructions": "Does `ticket.messages[0].text` request a refund?",
    },
    "policy_supports_refund": {
        "type": "noul",
        "instructions": (
            "Does `refund_policy` support the refund requested "
            "in `ticket.messages[0].text`, given `order.charges`?"
        ),
    },
}

不加反引号,模型就不知道该看哪块。 这是把结构化 state 用好的关键细节。

高级技巧:instructionscriteria 都能传 JSON

instructions(三种类型通用)、Score 的每个等级描述、Noul 的 criteria.true/false,类型都是 EntryType——即 string | object | array | null

什么时候该结构化:

  • 问题有多个部分时:JSON 的 key 起了标注作用,比堆成一句话清晰得多
  • 已有 schema / taxonomy / 数据库行时:本来就是 JSON,直接塞进去,别自己拼字符串模板
"instructions": {
  "question": "Does the claimed sender identity conflict with the sending domain?",
  "compare": ["ticket.sender.display_name", "ticket.sender.email"],
  "focus": "Compare the named organization with the email domain."
}

七、一次问多个:它和 LLM 最大的区别

一个请求里的所有问题都是并行评估的,彼此独立,各自用你给的 key 返回。

这意味着:

  • 加问题几乎不增加延迟
  • 只多付那点输入 token

由此衍生出官方推荐的 Speculative fan-out(投机性扇出) 模式:把所有可能需要的判断一次性全问上,代码自己决定用哪条答案。一个工单如果最后发现不是 Bug 报告,忽略那条严重度评分就行了。

官方给的数据很有说服力:把 13 个问题打包成一次调用,相比 13 次独立调用,便宜 11.5 倍、快 9.6 倍,且答案完全一致

文档里有句话很直白:"问一个可能用不上的问题几乎是免费的。" 它还专门点名说,写代码的 agent 最容易犯"一次调用只问一个问题"的毛病。

需要多次请求的情况

同一请求内的问题互相独立,一个答案不会成为另一个问题的上下文。

只有当你的代码必须先拿到第一个答案才能构造第二个请求时,才发第二次请求——比如需要拿答案去取更多数据、或者需要根据答案决定下一题的选项。

"两次请求是例外,不是常态。" 如果第二题其实能对着原始 state 问,那就放进第一次请求,让代码忽略不需要的答案。

上下文预算

  • 64k token / 请求state + 全部问题合计
  • 32k token:适用于 state + 单个最长的问题

大约相当于 15 万英文字符的英文文本。问题数量本身没有上限,只受 token 预算约束。

八、置信度:真正让它可落地的那个特性

这是 Jev 最有工程价值的部分,也是最容易被当成"附赠品"忽略的部分。

probabilitiesconfidence 的分工

  • probabilities原始分布:Choice 是各选项上的分布,Score 是各等级上的分布。
  • confidence从这个分布算出来的一个统计量,折叠成 0–1 的单一数字,方便你直接卡阈值。

判断置信度的本质是看分布的形状越尖越自信,越平越不确定。

  • Choice 低置信 → 没有哪个选项明显胜过其他
  • Score 低置信 → 等级定义模糊、维度混杂,或者 state 信息不足

文档明确说了:confidence 只是推荐的默认算法,你完全没有被锁死。完整的 probabilities 都给到你了,想要别的度量(比如熵、margin)自己算就行。

RLCD:为什么它敢让你信这个概率

Jev 用 RLCD(Reinforcement Learning for Calibrated Decisions) 训练。

  • RLHF 优化人类偏好
  • RLVR 优化可验证答案
  • RLCD 优化的是"判断对不对"加上"模型自称的把握是否诚实"

具体含义:当模型对一批任务都报 90% 把握时,其中应该有约 90% 真的正确。

这是自动化分流的数学前提。没有校准的概率只是装饰品。

一个必须记住的限定:校准是群体层面的性质,它不保证单个答案正确。

三档阈值:让代码显式处理不确定性

response = client.system_one(
    state=user_message,
    questions={
        "action": Choice(
            instructions="What is the user trying to do?",
            criteria={
                "check_balance": "View account balance",
                "approve_transfer": "Approve the pending withdrawal request",
                "support": "Get help with an issue",
            },
        ),
    },
)

action = response.answers["action"]
confidence = action.confidence

if confidence < 0.5:
    # 模型真的不确定。别猜。
    route_to_human(user_message)

elif action.choice == "check_balance":
    # 低风险。跳错页面可以补救。
    show_balance(account_id)

elif action.choice == "approve_transfer":
    if confidence > 0.9:
        # 高风险 + 高置信:确认后执行
        confirm_then_execute(account_id)
    else:
        # 高风险 + 中等置信:先验证
        ask_user_to_confirm(account_id)

三个关键点:

  1. 阈值不是一个数字。 同一个系统里,不同操作的阈值应该不同——取决于出错的后果。
  2. 只读操作和销毁性操作不能用同一把尺子。 上面例子里,check_balance 无论如何都执行,approve_transfer 却要 0.9 以上。
  3. 区间划分要按你的风险承受度定。 官方建议:先保守,用自己的数据测,再根据观察结果调整。

文档里有一句话值得抄在墙上:

如果一个智能系统——无论人还是机器——无法表达诚实的不确定性,那这个系统就不可信。

九、计费、限流与错误处理

计费

只按输入 token 计费,输出免费。 $0.042 / 百万 token。

这意味着一个反常的结论:问题问得多不心疼,state 塞得大才心疼。 这正好和第七节的并行策略互相强化。

限流

  • 250,000 token / 秒
  • 1,200 请求 / 分钟

官方警告:这些限值正在动态调整中,可能无预警变化。企业级自定义额度需联系 sales。

错误码

状态码含义怎么办
401 UnauthorizedAPI Key 缺失或无效检查 Authorization
422 Unprocessable Entity请求体校验失败(缺字段 / 题目格式错)body 会指出问题字段
429 Too Many Requests超限指数退避重试,别立刻重试
529 OverloadedTypeSafe 暂时过载退避后重试

429/529 一定用指数退避。用官方 SDK 的话默认就带退避策略,还会遵守响应里的 retry-after 头。

列出可用模型

curl https://api.typesafe.ai/v1/models \
  -H "Authorization: Bearer $TYPESAFE_API_KEY"

GET /v1/models 返回你账号可用的模型名和别名。

十、踩坑清单

  1. 以为题目 ID 会传给模型。 不会。instructions 必须自包含地把问题写完整。
  2. 中文直接上生产。 英文才是主训练语言,CJK 只是"能处理"。中文场景必须先测,并且严密监控 confidence。
  3. jev-latest 别名跑已调优的阈值。 别名会随新版本漂移,model 返回的版本 ID 才是真相。如果你按某个版本校准过阈值,就把版本号 pin 死(如 jev-1.13.0),升级自己挑时间。
  4. 把 Noul 的 0.5 当成"中等"。 它是"是非概率各半",不是程度上的中等。要测程度就用 Score。
  5. 一次调用只问一个问题。 并行是免费的,这是最大的浪费。
  6. 让同请求内的问题互相依赖。 它们彼此独立,前一个答案不会成为后一个的上下文。
  7. 拿它做开放推理。 让它解释理由、写文本、生成方案——纯属用错工具。
  8. 忘记给 state 里的字段加反引号路径。 结构化 state 不指路,模型就瞎猜。
  9. 忽略置信度。confidence 当附赠品直接扔掉,等于放弃了这个模型一半的价值。

结语

Jev 的价值不在于"又一个更便宜更快的模型",而在于它把不确定性变成了可编程的接口

choice 告诉你是什么confidence 告诉你该不该采取行动。这两条轴一分开,"AI 自动决策"这件事第一次有了可工程化的边界:高置信自动执行、中置信加确认、低置信转人工。

从架构上,这意味着一个很清晰的切分——LLM 做开放式推理和生成,Jev 做路上所有高频的小判断。

对已经写了大量 if prompt says ... 这种脆弱逻辑的人来说,这大概是今年最值得动手试的一次接口升级。

参考:官方文档 https://docs.typesafe.ai/(该站提供 llms.txt 完整索引,可以直接喂给你的 coding agent)。

下一篇
Rust构建的AI智能体编排框架 - thClaws
余白

评论与来信

已通过审核的评论共 0 条。
还没有公开评论

如果正文触发了新的想法,可以把第一封留言写在右侧;提交后会先进入审核。

留言

写下你的想法

提交后进入审核队列,通过后显示于左侧。