☰
告别“生成+解析“:一文认识 Jev——第一个 System One 模型
2026/10/15 4:09:12 网站建设 项目流程

本文基于 Datawhale 开源项目 jev-cookbook 第一章《认识 Jev》整理与扩写,结合官方文档做了中文场景的复述与实战补充。所有示例数据均为教学合成数据。


摘要

你有没有写过这样的代码:让大模型判断一条工单是否紧急,于是你在 prompt 里写「请只返回 JSON,格式如下……」,然后拿到一堆带 ```json 标记、夹着「好的,我认为……」的文字,再用正则去抠、用try/except兜底、失败就重试一遍。

Jev 想干掉的就是这一步。

它是 TypeSafe 的旗舰模型,也是第一个所谓System One模型:输入是「状态(state)+ 一组类型化的问题(questions)」,输出是「类型化的答案 + 概率分布」。不生成文本,也不需要解析。

本文带你搞清楚:Jev 是什么、和 ChatGPT 这类大模型差在哪、三种原语怎么用、什么场景该交给它、它给出的概率凭什么可信,最后用一个完整的中文实战案例收尾。

关键词:Jev、TypeSafe、System One、RLCD、概率校准、AI Agent、LLM 工程化


一、先说痛点:我们到底在为什么买单

传统 LLM 是为「人类阅读」而生的——它写出来的东西,是给人看的。

可一旦代码需要做判断,流程就变成了这样:

自然语言输入 → 大模型生成一段文本 → 正则/JSON 解析 → 程序可用的结构化值

中间这一步「把生成的文字再解析回程序能依赖的形式」,既慢又脆。慢在要多生成一堆废话 token,脆在格式随时可能崩:多一个逗号、多一句寒暄、少一个引号,你的json.loads就炸了。

于是工程上涌现出各种补丁:JSON Mode、function calling、结构化输出约束、重试兜底、双模型校验……本质上都是在给「生成」这一步打补丁。

Jev 的思路更直接:把生成这一步整个砍掉。

它像 LLM 一样能读懂自然语言,但只返回你问的那几个数,而且每个数都带着概率。


二、Jev 是什么:一句话定义

Jev 是 TypeSafe 的旗舰模型,也是第一个 System One 模型——输入是 state 加一组类型化的问题,输出是类型化的答案加概率分布。没有文本生成,也没有解析。

用公式表示就是:

System One: (state, questions) → typed answers + probability distributions

这里的state就是你要判断的那段文本(可以是一句话、一段对话、一个 JSON、一个文本数组),questions是你预先定义好的一组带类型的问题。

两个必须知道的边界

  1. 目前只接受文本输入——字符串、JSON、文本数组都行,图像/音频/视频暂不支持。
  2. 名字借自《思考,快与慢》的「系统 1」——取「快速直觉判断」这个意象,不是说它在科学上复现了人类思考。别过度解读这个名字。

三、和聊天大模型到底差在哪

这是最容易被问到的问题,官方给了个非常清晰的对比表:

维度聊天大模型(LLM)Jev(System One)
训练目标生成讨人喜欢的回复(RLHF)校准决策(RLCD):概率对齐真实结果
输出一段自由文本类型化取值 + 概率分布(由你的问题定义)
会做什么写作、代码、解释推理只做判断;不写回复、不解释推理
适合谁消费人程序:分支、排序、路由

关键差异在第二行——训练目标。

  • RLHF(人类反馈强化学习):目标是让回复更讨人喜欢,产出是文本。
  • RLVR(可验证奖励强化学习):目标是让推理更准,产出是会思考但更慢更贵的模型。
  • RLCD(面向校准决策的强化学习):Jev 走的第三条路——训练模型返回决策和校准概率,而不是文本。

一句话总结:LLM 是给写给人看的内容的,Jev 是给程序做分支用的。

它不会给你写周报,也不会给你解释推理过程。它就是个高速、带概率的判断器。


四、三种原语,就是它的全部词汇

Jev 的全部表达能力,就三个原语(primitive)。记住这三个,你就掌握了它的 90%。

原语问题类型示例输出
Choice从选项中选一个choice: "billing"+ 各选项概率
Score按有序标准打分score: 1.4(0=平静,1=沮丧,2=非常沮丧)
Noul某陈述是否为真noul: 0.95

4.1 Choice —— 是哪一类?

从一组互斥的选项里挑一个,返回选中的标签 + 每个选项的概率。

Choice(instructions="用户的主要诉求是什么?",criteria={"troubleshoot":"希望排查或修复连接问题","refund":"要求退款或赔偿","inquiry":"只是咨询,不要求立即处理",})

criteria是「选项 key → 选项描述」的字典。选项 key 建议用英文,描述用中文,这样代码里判断分支时不会被中文 key 坑到编码问题。

4.2 Score —— 打几分?

按一组有序的标准打分,返回的是概率加权后的期望值(所以会出现 1.4 这种小数,而不是硬选一档)。

Score(instructions="用户的受挫程度如何?",criteria=["平静,仅陈述事实","有些不满","强烈不满,有流失风险"])

注意criteria这里传的是列表(有序),不是字典。下标 0/1/2 对应三档,最终score = Σ(下标 × 概率)。

比如概率分布是{0: 0.05, 1: 0.26, 2: 0.69},那么:

score = 0×0.05 + 1×0.26 + 2×0.69 = 1.64

这个设计很妙——它把「模棱两可」诚实地表达成了 1.64,而不是强行归到某一档。

4.3 Noul —— 是不是?

判断某个陈述是否为真,返回一个 0~1 的概率值。

Noul(instructions="这条消息是否表达了紧迫性?")

noul这个名字挺怪,官方的解释是它代表一个「是/否 + 不确定度」的量。不确定性直接体现在数值靠近 0.5——0.95 是很确定,0.55 是基本没谱。

4.4 一次调用,三种混用(核心体验)

这是 System One 最值得体验的一点:

三种问题可以在一次调用里混用,每个问题并行、相互独立地对照同一个 state 求值。

带来两个直接好处:

  • 加问题几乎不增加延迟——不是串行地问三个问题,是一次往返问完。
  • 没有长上下文「越读越糊」的问题——每个问题独立看同一份 state,不存在多轮对话那种注意力稀释。

五、三分钟上手

5.1 环境准备

要求 Python ≥ 3.10:

pipinstalltypesafe-sdk==0.7.0

注意一个坑:安装包名是typesafe-sdk,Python 导入名是typesafe_sdk(横杠 vs 下划线)。

然后配置 API Key(不要写进代码或 Notebook):

exportTYPESAFE_API_KEY="your-api-key"

5.2 最快的方式:一行 curl

不想装 SDK,直接发 HTTP 也行:

curl-XPOST https://api.typesafe.ai/v1/systemone\-H"Authorization: Bearer$TYPESAFE_API_KEY"\-H"Content-Type: application/json"\-d'{ "state": "连续三天连不上 Stripe,每天在丢订单,尽快处理!", "model": "jev-latest", "questions": { "urgency": { "type": "noul", "instructions": "这条消息是否表达了紧迫性?" } } }'

也可以直接去官方 Playground 粘贴文本试,连登录都省了。

5.3 Python SDK:一次调用问三个问题

importosfromtypesafe_sdkimportChoice,Score,Noul,TypeSafeClient client=TypeSafeClient(api_key=os.environ["TYPESAFE_API_KEY"],model="jev-1.13.0",# 固定版本,便于复现实验timeout=30,)state=("用户:我连续三天没能把 Stripe 账户连上,集成一直失败,""每耽误一天都在丢订单,请尽快处理!")questions={"urgency":Noul(instructions="这条消息是否表达了紧迫性?"),"intent":Choice(instructions="用户的主要诉求是什么?",criteria={"troubleshoot":"希望排查或修复连接问题","refund":"要求退款或赔偿","inquiry":"只是咨询,不要求立即处理",},),"frustration":Score(instructions="用户的受挫程度如何?",criteria=["平静,仅陈述事实","有些不满","强烈不满,有流失风险"],),}resp=client.system_one(state,questions)

5.4 读结果

# Noul → 概率print(resp.nouls["urgency"].noul)# 0.94# Choice → 选中的标签 + 全部概率 + 置信度print(resp.choices["intent"].choice)# 'troubleshoot'print(resp.choices["intent"].probabilities)# {'troubleshoot': 0.82, 'refund': 0.03, 'inquiry': 0.15}print(resp.choices["intent"].confidence)# 0.8# Score → 期望分 + 分布 + 图例print(resp.scores["frustration"].score)# 1.64print(resp.scores["frustration"].probabilities)# {0: 0.05, 1: 0.26, 2: 0.69}print(resp.scores["frustration"].legend)# {0: '平静', 1: '有些不满', 2: '强烈不满'}

一发请求,三份带概率的答案。这就是 System One 的核心体验。

拿到手之后,你的代码可以直接这么写:

ifresp.nouls["urgency"].noul>0.8andresp.choices["intent"].choice=="troubleshoot":route_to("oncall_engineer")

干净、可测、不需要任何正则。


六、提问纪律:原子性(最重要的工程经验)

这是整份教程里我认为最有价值的一条:

每个问题只问一件专家几秒内能下结论的事(原子判断)。

复杂判断拆成多个独立问题,在代码里用你自己的逻辑加权组合。

这样做的好处是:优先级变了,只改代码里的系数,不用改提示词、不用重跑评测。

反例:一个问题问两件事

比如你想问「该不该给这条工单升级到人工?」

这是个不合格的问题。它其实混了两个独立判断:

  1. 这个问题严重不严重?→Score或Noul
  2. 当前的自动流程能不能处理?→Noul或Choice

如果塞进一个noul里问,任一因素翻转都会污染概率——你拿到 0.6 的时候,根本不知道是「不严重但要升级」还是「严重但能自动处理」。

正例:拆开问,代码里组合

questions={"severity":Score(instructions="这个问题的严重程度如何?",criteria=["轻微","中等","严重","致命"],),"auto_solvable":Noul(instructions="现有的自助文档或机器人流程能否解决这个问题?"),}resp=client.system_one(ticket_text,questions)severity=resp.scores["severity"].score auto_solvable=resp.nouls["auto_solvable"].noul# 规则完全在代码里,随时可调should_escalate=(severity>=2.5)or(severity>=1.5andauto_solvable<0.4)

模型管语义,代码管规则。这句话是 Jev 用法的心法。


七、场景地图:什么活儿适合交给 Jev

官方 Use Case Map 归纳了五大类用法:

用法人话解释
自动化软件里的语义判断代码管流程,Jev 出判断;可后台跑上百万次不用人盯
实时应用~150ms 出答案,快到能进游戏和用户界面
大数据上的批量判断同一个判断跑一百万次,成本约为大模型调用的百分之一
万能校验器查幻觉、查引用是否支撑结论、查越狱与违规话术
给大模型当管家决定哪条请求发给哪个模型;拦住注入与泄露

映射到三种原语上,常见的判断形态有这七种:

  • 是哪一类?意图 / 主题 / 风险类型 →Choice
  • 有没有?垃圾 / 欺诈 / 紧迫 / 敏感信息 →Noul
  • 打几分?严重度 / 相关性 / 质量 →Score
  • 该走哪条路?工具选择 / 人工升级 / 队列分派 →Choice+ 代码分支
  • 找最相关的?语义搜索 / RAG 上下文 / 排序 → 检索与排序组合
  • 核对有没有错?引用支持 / 策略违规 →Noul逐条校验
  • 抽特征或字段?购买意图喂预测模型 / 从文本回填表单 →Score/Choice

两个边界(别越界)

  1. 几乎所有场景都该配「不确定就转人工」。法务、理赔、招聘淘汰这类高风险终审,不能全交给它。
  2. 需要长篇写作或开放推理时,转交大模型。更合理的架构是:Jev 在前面快速定「该走哪条路」,大模型在后面做重活。

八、概率凭什么可信:RLCD 与校准

这是 Jev 最核心的卖点,也是最容易被误用的地方。

校准是什么意思?

校准是按一组预测来衡量的,不是按单次。

给 0.8 概率的事件,长期发生频率应该接近 80%。它不保证任何单次预测正确。

用 20 条数据直观感受一下:

groups={0.2:[1]*2+[0]*8,0.8:[1]*8+[0]*2}forp,labelsingroups.items():print(f"预测概率{p}:{len(labels)}条,实际发生{sum(labels)/len(labels):.0%},"f"组内仍有{labels.count(0)}次没发生")

输出:

预测概率 0.2:10 条,实际发生 20%,组内仍有 8 次没发生 预测概率 0.8:10 条,实际发生 80%,组内仍有 2 次没发生

两个组都「准」,但组内单次照样会错。

工程上的正确用法

  • ✅ 用概率做群体决策:路由、排序、抽检、批量分流
  • ❌ 用概率做单点高风险动作的唯依据——该交给阈值 + 人工复核

一句话:校准好 ≠ 单次必对。


九、社区实测数据(来自 jev-cookbook)

以下数字来自 datawhalechina/jev-cookbook 收录的实验报告,供选型参考:

JevBench v1.2(242 个类型化决策的公开基准)

  • Jev 1.13.0 综合智能分榜首:75.4
  • 答案可解析率 100%(这一点对工程化太重要了)
  • 路由任务:74.1%
  • 中位延迟:0.65 ~ 0.72 秒
  • 每千次决策成本:约$0.04

稳定性:同一套题隔 16 分钟跑两遍,仅1.2%的答案变化。这说明端点不是完全确定性的——读 benchmark 表格时,约 1 个百分点的差距应视为噪声。

能替代 Rerank 吗(80 条 SciFact 查询精排对照)

  • 相对不做精排,Jev 的 nDCG@10 提升+0.0778
  • 比传统精排还高+0.0332
  • 精排耗时与 token 用量显著更低

结论:固定候选集上的语义重排,是 Jev 的甜点区。

速度与价格量级

  • 输入:$0.042 / 百万 token
  • 输出免费(因为输出就那么几个数)

便宜到什么程度?——可以「投机式地多问」:把不确定用不用得上的问题都塞进同一次调用,反正几乎不增加延迟和成本,代码端再决定用不用。

一个典型生产案例是智能家居场景:一次调用捆绑 10 个问题(意图、是否复合、范围、房间、设备类别 + 五类设备动作预判),代码端剪枝无关分支。这就是「投机式多问 + 原子组合」的完整实战。


十、实战:赛事指挥台(模型管语义,代码管规则)

来个完整的中文场景。假设一次夜跑赛事收到三条现场消息,我们要做自动分流。

10.1 定义状态与问题

fromtypesafe_sdkimportChoice,Score,Noul,TypeSafeClient client=TypeSafeClient(api_key=os.environ["TYPESAFE_API_KEY"],model="jev-1.13.0")INCIDENTS=[{"id":"runner_injury","state":{"event":"海湾夜跑 10 公里","time":"19:12","message":"2.4 公里蓝旗处有跑者脚踝扭伤,无法继续前进,请派人协助。"}},{"id":"water_station","state":{"event":"海湾夜跑 10 公里","time":"19:13","message":"7 号补水站的纸杯用完了,但仓库还有整箱,麻烦补送两箱。"}},{"id":"shirt_pickup","state":{"event":"海湾夜跑 10 公里","time":"19:15","message":"完赛T恤的领取处是先到先得吗?明天早上还能领吗?"}},]# 三个原子问题,一次调用问完INCIDENT_QUESTIONS={"incident_type":Choice(instructions="这条赛事消息主要属于哪类事件?",criteria={"medical_help":"跑者受伤或需要现场医疗","supplies":"物资补给问题","event_info":"赛事信息咨询",},),"priority":Score(instructions="需要多快处理?",criteria=["可赛后处理","30 分钟内","10 分钟内","必须立即"],),"requires_human":Noul(instructions="是否需要人工到场介入?"),}

10.2 逐条调用,代码分流

ROUTES={"medical_help":"现场负责人 / 医疗人员","supplies":"补给组(优先处理)","event_info":"自动回复赛事 FAQ",}forincinINCIDENTS:r=client.system_one(inc["state"],INCIDENT_QUESTIONS)# 1) 模型出判断t=r.choices["incident_type"].choice urgency=r.scores["priority"].score p_human=r.nouls["requires_human"].noul# 2) 代码管规则(阈值 = 应用政策,不是模型的事)human=p_human>=0.7# 不可妥协的硬规则直接写死ift=="medical_help":human=Trueprint(f"{inc['id']:14s}紧急度={urgency:.2f}→{ROUTES[t]}"f"{'(转人工)'ifhumanelse''}")

预期输出类似:

runner_injury 紧急度=2.85 → 现场负责人 / 医疗人员(转人工) water_station 紧急度=1.10 → 补给组(优先处理) shirt_pickup 紧急度=0.20 → 自动回复赛事 FAQ

10.3 这段代码里值得注意的三件事

  1. 模型只回答了三个数,所有业务规则都在 Python 里。改阈值不需要重跑模型、不需要碰提示词。
  2. ≥0.7 转人工是应用政策,不是模型判断。阈值该由业务方定,不该塞进 prompt 里。
  3. 不可妥协的规则(医疗类永远转人工)写进确定性代码——这正是官方推荐的分工方式。概率再准,也不该拿它去赌安全红线。

十一、避坑清单

整理几个新手容易踩的坑:

坑说明
把密钥写进 Notebook用环境变量TYPESAFE_API_KEY,别硬编码
一个问题问两件事违反原子性,概率会被污染,见第六节
拿概率当单次的确定性结论校准是群体概念,高风险单点必须有阈值 + 人工
用离线/人工数据估计算准确率教学用的构造数字只能验证代码路径,不能证明模型能力
看到 benchmark 差 1 个点就换模型端点非确定性,1 个百分点应视为噪声
让 Jev 写长文本它不是干这个的,写作交给大模型
高风险终审全交给它法务、理赔、招聘淘汰必须配人工兜底

另外,如果你在做评测,有个很隐蔽的陷阱:如果哪句答得合心意就专门挑出来当考题,再拿这些挑过的句子去算准确率,数字必然虚高。测试集要预先固定。


十二、小结

概念一句话
System One状态 + 类型化问题 → 带概率的类型化答案
三原语Choice 选、Score 评、Noul 判
原子问题一题只问一件事,组合交给代码
校准群体频率对齐,不保证单次正确
分工模型管语义,代码管规则

Jev 不是又一个聊天模型,它是把「判断」这件事从「生成」里剥离出来的一次尝试。如果你的系统里有一堆需要语义理解的 if-else,它值得你花半小时试一下。


参考资料

  • 官方文档:Introduction
  • 官方场景地图:Use Case Map
  • 官方 Demo:Smart Home
  • 开源教程(本文来源):datawhalechina/jev-cookbook
  • 中文参考站:jev-cookbook

本文基于 jev-cookbook 第一章整理,实验数据引自该项目收录的社区实测报告。若你准备在生产环境落地,请务必用自己的数据跑一遍真实评测——本文的数字不构成对你场景的准确率承诺。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询