Jev将语义判断封装成带概率的类型化结果,让代码据此选择分支。
冷月清谈:
怜星夜思:
2、带概率和置信度的输出,真的能让自动化决策更安全吗?阈值应该怎么定?
3、“一次把独立问题全问完”适合哪些业务?会不会因为无关问题太多反而增加噪声和成本?
4、如果把 Jev 用在退款、风控或破坏性命令判断中,出了错应该由谁负责?
原文标题:最近爆火的 Jev 到底是什么?凭什么能刷屏硅谷!
原文作者:图灵编辑部
原文内容
Jev 不是 ChatGPT 那样的聊天机器人,也不是编程模型。它不回复、不解释,也不写代码。这个 "哑巴"AI,到底是怎么在硅谷火起来的?
Jev 到底是什么
一句话定义:Jev 是一个聪明的 if 语句。
普通代码根据能算出来的值做分支,比如 if (order.total > 100)。可条件一旦变成“判断”,这种写法就不管用了:这条客服消息是不是在发火?这封邮件和账单有没有关系?这 12 个按钮里,哪个能继续结账?Jev 就是为这类判断准备的。你给它一份数据和一组定义好类型的问题,它对每个问题给出一个答案:可能是一个是或否的概率,可能是你列出的选项中的一个,也可能是你定义的刻度上的一个位置,每个答案都附带概率。
TypeSafe 称大多数调用约 100 毫秒就能完成,输入每百万 token 只收 0.042 美元,输出免费。它和 ChatGPT 这类工具的区别在于 AI 所处的位置。用 ChatGPT 或编程 Agent 时,AI 本身就是界面,或者就是干活的那个;而 Jev 只是普通应用里的一个小组件,放在代码需要做一次判断的地方。
Jev 出自旧金山的 TypeSafe AI。这家实验室在 2026 年 9 月 15 日结束隐身,拿到 4000 万美元种子轮,Jev 是它公开发布的第一个模型。TypeSafe 把它称为 System One 模型:它的用途是在软件内部快速做决策,不是陪人聊天。
整个思路就是模型负责判断,代码决定下一步怎么走。
与 ChatGPT、Cursor、Codex、Claude Code 有什么不同
大多数 AI 工具以生成式模型为核心。你提一个宽泛的需求,它给你产出新东西。ChatGPT 通过对话返回生成的内容;Cursor、Codex、Claude Code 这类编程 Agent 接收目标后,会自己读项目、改文件、跑命令,反复迭代。
这些 Jev 一样都不做。它不接收开放式目标,不调用工具,不改文件,也不跑循环。你的代码给它一份 state 和一组问题,它返回带类型的答案和概率,然后就结束了。
|
工具
|
你给它什么
|
它返回什么
|
它的角色
|
|---|---|---|---|
|
ChatGPT
|
一段提示词或一场对话
|
生成的回复
|
通用助手
|
|
Cursor
|
编程任务、代码仓库和工具
|
文件修改、命令、测试结果
|
编辑器兼编程 Agent
|
|
OpenAI Codex
|
编程目标、项目和工具
|
代码改动和完成的任务
|
编程 Agent
|
|
Claude Code 等 CLI Agent
|
一条指令和本地工具
|
工具调用、修改和终端输出
|
终端编程 Agent
|
|
Jev
|
state 加上定义好答案形式的问题
|
选项、分数和概率
|
软件内部的决策原语
|
Jev 不是要取代这些工具,而是可以嵌进它们里面。编程 Agent 在执行一条 shell 命令之前,可以先问 Jev:这条命令是只读的、可撤销的,还是破坏性的?路由器可以用它决定把任务交给哪个模型。代码照样由编程 Agent 来写,回答照样由 ChatGPT 来写,Jev 只负责走哪条路这个小决定。
这改变了往产品里加 AI 的方式,产品不必变成聊天机器人或 Agent。现有应用照旧,只在普通 if 看不懂输入的地方加一次模型调用。
和分类器、LLM 结构化输出有什么不同
在 Jev 之前,软件里做这类决策常见的办法有三种:
-
写 if、正则表达式或决策树:快、便宜、可预测,但一旦涉及语义就很脆。
-
训练分类器:也快,但需要标注样本和训练,每个任务要单独一个模型。
-
让通用 LLM 返回结构化输出:不用训练就能理解非结构化文本,但它终究是生成式模型。
Jev 瞄准的是中间地带。它像 LLM 一样,能接收非结构化文本和运行时定义的问题;又像分类器一样,返回的是一个受约束的概率分布,而不是开放式回答。
区别在于答案是怎么产生的:
-
生成方式不同:LLM 是一个 token 一个 token 地生成答案,生成过程可能失败或提前停止,它给出的概率也不保证校准过。Jev 不生成字符串,而是并行地对所有答案采样,输出你定义的选项上的概率分布。
-
速度和成本不同:TypeSafe 给出的端到端耗时是 70 到 500 毫秒,前沿 LLM 处理同类问题需要 3 到 329 秒。输入价格比 LLM 低 5 到 240 倍,输出免费。“快 193.6 倍、便宜 444.6 倍”这个数字来自 TypeSafe 自己的评测,处在真实场景的高位,把它当作上限来看。
-
训练目标不同:聊天模型用 RLHF 奖励人类更喜欢的回答;Jev 用“校准决策强化学习”(RLCD)训练,目标是让概率和实际结果吻合:给出 90% 概率的答案,应该有大约 90% 是对的。
Jev 也刻意放弃了一些能力:不能写回复、不能生成代码、不能总结文档、不能解释推理。真正有意思的架构是两者搭配:Jev 负责判断,LLM 负责写。
核心原理解析
内部机制
-
并行独立:同一个请求里的所有问题共用一份 state,独立、并行地评估,一个问题的答案不会成为另一个问题的上下文。
-
0% 类型错误:输出是你所给选项上的概率分布,成功返回的答案不可能出现格式错误。这是由结构保证的,但它只保证答案的形式,不保证答案正确。
-
大小限制:state 和所有问题加起来约 64,000 token,state 加上最长的问题须在约 32,000 token 以内。一个 Choice 最多 255 个选项,一个 Score 有 2 到 10 个等级。
-
只读文本:字符串、JSON 对象或文本组成的 JSON 数组,暂不支持图片、音频和视频。
-
版本:当前模型是 jev-1.13.0。响应里会带上实际作答的版本号,阈值调好之后,把版本号固定下来。
三种问题类型
|
类型
|
问的是什么
|
返回什么
|
|---|---|---|
|
Noul
|
这是真的吗?
|
noul
,0 到 1 之间的概率
|
|
Choice
|
是这几个选项里的哪一个?
|
choice
、 probabilities、confidence
|
|
Score
|
在这个刻度上处于什么位置?
|
score
、 legend、probabilities、confidence
|
每个问题都要有 ID、类型和说明(instructions)。ID 只给代码用,不会发给模型,所以完整的问题要写在 instructions 里。
Noul:是非题
{
"refund_requested": {
"type": "noul",
"instructions": "Does the customer ask for money back?"
}
}
返回 { "noul": 0.93 },即答案为“是”的概率。
“⚠️ 踩坑提示:Noul 等于 0.5 不代表中等,只说明模型分辨不出来。要衡量程度,用 Score。
Choice:多选一
{
"department": {
"type": "choice",
"instructions": "Which team should handle this message?",
"criteria": {
"billing": "Charges, invoices, refunds, subscriptions",
"technical": "Bugs, outages, integration problems",
"sales": "Pricing questions, upgrades, new accounts",
"other": "None of the above"
}
}
}
返回概率最高的 choice、完整分布 probabilities,以及 confidence:某个选项一枝独秀时高,概率分散时低。
“⚠️ 踩坑提示:选项可能覆盖不全时,一定要加
other,因为模型总得选一个。
Score:在刻度上定位
{
"bug_severity": {
"type": "score",
"instructions": "How severe is the reported issue?",
"criteria": [
"Cosmetic; no impact on functionality",
"Broken or degraded feature, but a workaround exists",
"Blocking issue; no workaround exists"
]
}
}
criteria 从低到高排列,下标就是等级编号。score 是按概率加权的平均值,比如概率分布为 {0: 0.0, 1: 0.7, 2: 0.3} 时,score = 0 × 0.0 + 1 × 0.7 + 2 × 0.3 = 1.3。
“⚠️ 踩坑提示:描述情形,不要描述程度。功能故障,但有变通办法给了模型可以对照的东西,中等严重没有。一个 Score 只衡量一个维度。
置信度:什么时候直接动手,什么时候先问一声
每个 Choice 和 Score 答案都带一个 0 到 1 的 confidence。文档推荐把它分成三段:
-
高:自动执行。
-
中:请用户确认、标记待审,或者先收集更多数据。
-
低:转给人工、请对方澄清,或者退回到更慢的系统。
分界线取决于答错的代价。文档举例时,用 0.5 作为人工审核的下限,破坏性操作前要求 0.9,这些只是例子,不是默认值。风险容忍度写在你的代码里,是看得见、改得了的数字。先保守一点,在自己的数据上跑一跑,把置信度和准确率画成图,再据此调整阈值。
快速上手(Python)
获取权限
Jev 目前处于早期访问阶段。在 typesafe.ai 加入等候名单,获批后会收到邮件,一般一两天就能通过。不想排队的话,Jev 也上架了 Vercel 的 AI Gateway,模型名是 typesafe-ai/jev,价格相同。
建议头一个小时花在控制台的 Playground 上,用你自己的数据:一条真实的客服消息、一行真实的日志、一份真实的表单提交。
第一个 Python 请求
Python SDK 要求 Python 3.10 及以上:
pip install typesafe-sdk
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
client = TypeSafeClient()
response = client.system_one(
state="I was charged twice for order A-104. Please refund the duplicate.",
questions={
"department": Choice(
instructions="Which team should handle this?",
criteria={
"billing": "Charges, invoices, refunds",
"technical": "Bugs and integration problems",
"other": None,
},
),
"refund_requested": Noul(
instructions="Does the customer ask for money back?",
),
},
)
print(response.answers["department"].choice)
print(response.answers["refund_requested"].noul)
客户端从环境变量 TYPESAFE_API_KEY 读取密钥。另外还有 AsyncTypeSafeClient,重试策略也可以配置。
底层接口与错误处理
SDK 背后只有一个接口:
POST https://api.typesafe.ai/v1/systemone
Authorization: Bearer <API_KEY>
Content-Type: application/json
返回内容包括 answers 对象、实际作答的模型版本,以及记录输入、输出 token数的 usage。
常见错误码:
|
状态码
|
含义
|
处理方式
|
|---|---|---|
|
401
|
密钥缺失或错误
|
检查密钥
|
|
422
|
请求体校验失败
|
响应会指出是哪个字段
|
|
429
|
触发限流
|
指数退避重试(SDK 自动处理)
|
|
529
|
服务过载
|
指数退避重试(SDK 自动处理)
|
截至原文写作时,限流标准是每秒 25 万 token、每分钟 1,200 次请求,早期访问阶段会动态调整。
关键习惯:一次把问题问完
这个习惯会改变你用 Jev 做设计的方式,也是编程 Agent 最常犯错的地方。
LLM 调用又慢又贵,所以工作流通常问一个问题,再决定下一个问什么。而 Jev 的所有问题是基于同一份 state 并行运行的,多一个问题只多花它自己那部分 token。所以,把可能用得上的独立问题一次全问了,哪怕有些只对部分输入有意义,再让代码决定用哪些答案。
TypeSafe 把这叫作“推测式扇出”(speculative fan-out)。在一个 cookbook 里,13 个问题一次调用问完,比分 13 次依次调用便宜 12.2 倍、快 10 倍。
下面是原文中一次请求完成的客服分诊示例(JavaScript SDK)。bug 严重程度只对 bug 有意义,退款问题只对账单类工单有意义,但照样全问:
import { choice, noul, score, TypeSafeClient } from'@typesafe-ai/sdk'
const client = new TypeSafeClient()
const TRIAGE = {
category: choice('What kind of ticket is `ticket`?', {
bug_report: 'Something is broken or behaving wrong',
billing: 'Charges, invoices, refunds, subscriptions',
feature_request: 'Asks for something that does not exist yet',
other: null,
}),
bug_severity: score('If `ticket` reports a bug, how severe is it?', [
'Cosmetic; no impact on functionality',
'Broken or degraded feature, but a workaround exists',
'Blocking issue; no workaround exists',
]),
has_repro_steps: noul('Does `ticket` include steps to reproduce a problem?'),
refund_requested: noul('Does `ticket` ask for money back?'),
frustration: score('How frustrated is the author of `ticket`?', [
'Calm, just stating facts',
'Frustrated but civil',
'Very angry, strong language, or threatening to leave',
]),
}
exportasyncfunctiontriage(ticket) {
const { answers } = await client.systemOne({
state: { ticket },
questions: TRIAGE,
})
const { category, bug_severity, has_repro_steps, refund_requested, frustration } = answers
if (category.confidence < 0.6) {
return { route: 'human', reason: 'unclear category' }
}
if (category.choice === 'bug_report') {
if (bug_severity.score > 1.5 && has_repro_steps.noul > 0.6) {
return { route: 'engineering', priority: 'high' }
}
return { route: 'bug_backlog' }
}
if (category.choice === 'billing') {
return { route: 'billing', refundLikely: refund_requested.noul > 0.7 }
}
if (category.choice === 'feature_request') {
return { route: 'product' }
}
return { route: 'human', flag: frustration.score > 1.5 }
}
一次调用就撑起了整棵决策树。注意,所有问题都放在一个常量里,阈值也在同一个文件中,审代码的人需要看的就是这部分。
写问题的几条要点
-
一个问题只做一个判断。 “这条消息是否传达了紧迫感?”是好问题;“分析这条消息并决定最佳处理方式”则把好几个判断藏在了一个答案背后。
-
把条件写准确。 Jev 回答的是你写下的问题,不是你心里想的问题。限定词、否定词和隐含条件,它都按字面理解。
-
给模型留个出口。 选项可能覆盖不全时加
other;抽取可能不存在的信息时,加一个“未提及”。 -
只发问题需要的内容。 state 里无关内容越多,准确率越低,先在代码里过滤。
-
数字、日期和计数留在代码里。 Jev 不是计算器,计数也不可靠。
一个聪明的 if 语句,和其他 if 语句一样,要一个分支一个分支地用起来。
原文链接:https://flaviocopes.com/jev/
获取最前沿的 AI 内容,加入图灵 AI365,每天花费不到一元钱,每月 3 本免费电子书畅读,24 小时动态知识库,跟志同道合的小伙伴一起成长!即买即学,火速加购吧!👇
