第 1 章

第 1 章:认识 Jev:模型、上手与场景

第 1 章:认识 Jev:模型、上手与场景

本文整理自 Datawhale 开源项目 datawhalechina/jev-cookbook(CC BY-NC-SA 4.0),源文件:main/01_认识Jev。

本章回答一个问题:当答案本来就在有限选项里时,是否有必要让模型先生成一段文字,再把文字解析回标签?

为什么学判断模型

以「这条工单是否需要人工处理」为例。生成式 LLM 通常逐 token 生成文本;现代实现可以用 KV cache 重用先前计算,但仍要按自回归步骤生成后续 token。KV cache 文档解释了缓存复用如何减少重复计算,也指出每个新 token 仍依赖前序 token。要求模型只输出 JSON 可以减少解析问题,却不会把任务变成直接返回概率分布。

Jev 的公开接口把分析内容作为 state,把答案范围写成类型化问题,并返回选项与概率。应用代码据此执行阈值、权限、路由和动作规则。这里讲的是接口提供的能力,不对未公开的服务端计算方式作假设。

流程可以概括为:允许使用的证据 → 明确问题与选项 → 类型化答案及概率 → 确定性策略 → 业务动作。

flowchart LR
  subgraph gen[生成式任务]
    A[State 与 Prompt] --> B[生成式 LLM] --> C[逐 token 生成] --> D[解析文本] --> E[业务动作]
  end
  subgraph decision[有限选项判断]
    F[State 与类型化问题] --> G[Jev 接口] --> H[答案及概率分布] --> I[代码策略] --> J[业务动作]
  end

一条工单经过两种路径

工单:「充电器冒烟,刚买两天」

生成式路径
  工单 + prompt → “这可能涉及安全问题,请转人工……”
  → 解析文本 / 校验 JSON → 代码决定后续动作

有限选项路径
  工单 + Choice{安全问题, 退款, 普通咨询}
  → 概率分布{安全问题: 0.93, 退款: 0.05, 普通咨询: 0.02}
  → 代码检查策略 → 转人工处理

这组概率只是结构示意,不是 API 实测。例子要表达的是:模型回答“属于哪类”和应用决定“接下来做什么”是两个步骤;涉及安全的动作仍要走既定人工流程。

读图时要留意两条路径真正的分界:右侧把“答案表示”和“业务策略”拆成两个环节。类型化输出能让程序更容易检查答案范围,但是否准确、概率是否可信,仍要通过目标数据评测;代码策略也不能因为收到高概率就省略授权与安全校验。

Jev 适合有限答案空间中的判断、路由、打分和筛选;长篇生成、开放式问答、创作仍应交给生成模型。它与普通分类器、NLI 和 reranker 的区别也不是简单的「谁更聪明」:

方法 常见输出 更适合的任务 需要注意
生成式 LLM 自由文本,也可受格式约束 解释、写作、开放式推理 生成结果仍需校验;JSON 约束不等于概率校准
固定标签分类器 训练标签上的类别或分数 标签集合长期固定、可积累标注数据 新标签通常需要重训或额外设计
NLI / reranker 蕴含关系或相关性分数 文本蕴含、候选排序 分数语义由模型与训练任务决定
Jev 类类型化决策接口 请求中定义的类型化答案与分布 同一任务需要明确问题、选项和可读概率 分布质量和延迟仍须在目标数据上测量

本章实验地图

实验 要回答的问题 看什么 结果能说明什么
同一工单的 Noul、Choice、Score 同一份 state 能否承载不同类型的问题? 返回结构、选项概率、代码如何读值 展示接口组合方式;不证明多问没有额外成本
20 条校准示例 概率和单条预测正确性是否相同? 预测概率组与实际频率 人工小样本只帮助理解概念,不足以评估模型校准
赛事指挥台 如何把类型化判断接到业务动作? 医疗升级、补给路由、FAQ 分支 展示策略代码;不表示 API 能保证安全处置

扩展练习:测量问题数的影响。 在同一数据、问题集合和 API 版本下比较 1、3、5、10 个问题;每种设置多次重复,记录 p50/p95 延迟、输入 token、费用、错误率和问题间结果变化。不要预设「多问不增加延迟」,要从测量中得出结论。

阅读与运行

第一次阅读建议依次看 Notebook 的「Jev 是什么」「三分钟上手」「场景地图」「概率为什么可信」和「赛事指挥台」。有真实 API key 时按 Notebook 的实时模式运行;离线示例只演示数据结构,不是服务返回。

官方 Introduction、Quickstart 和 Use Case Map 的中文对应内容见翻译站。本地实验来源与限制见第十一章知识库。

学完后

你应能判断一个任务是否有清晰的有限答案空间,写出一份不泄漏答案的 state,并把模型输出交给代码策略处理。下一章会拆解 state、原语、概率和置信度;入门 Notebook是本章实践入口。


针对官方文档对应章节的可运行实验笔记,全部实验使用中文场景与中文提示词。 面向会基础 Python、刚接触 AI Agent 的读者。

学习目标: 一册读完 Jev 是什么、怎么调、用在哪、概率为什么可信,并附社区实测补充与一个综合实验。

官方原文 · 中文参考。本章以中文重述理论、复刻对应场景;扩展实验会单独说明。 所有客户、订单及消息均为教学合成数据。

笔记本结构

章节 内容
0. 准备 安装库、配置客户端、连通性测试与离线示例
1 Jev 是什么:与 LLM 的区别、三种原语
2 三分钟上手:亲手发出第一次请求
3 场景地图:什么活儿适合交给 Jev
4 概率为什么可信:训练目标与校准
5 社区实测补充(jev-cookbook)
6 综合实验:赛事指挥台
练习与小结 练习、自查、总结与本次执行记录

实验按原理 → 理论根基 → 定义数据 → 定义问题 → 调用 → 解读结果展开,每个代码单元格只做一件事。

运行要求

  • Python ≥ 3.10;本章使用 typesafe-sdk==0.7.0。
  • 真实实验需要启动进程的 TYPESAFE_API_KEY 环境变量,密钥不要写进 Notebook。

在本仓库 notebooks/ 目录创建环境并打开本文件:

./setup_env.sh
.venv/bin/python -m pip install -r requirements.txt -c generators/constraints-foundations.txt
.venv/bin/jupyter lab 01_认识Jev.ipynb

产品名、字段名和选项 key 保持英文,state、提示词与解说使用中文。 默认 JEV_RUN_MODE=auto(在线优先):检测到 TYPESAFE_API_KEY 即调用真实模型;未检测到才回退离线替身,每格输出都标注来源。 正式验收设置 JEV_RUN_MODE=live(无密钥直接报错、不回退);强制纯离线学习设置 JEV_RUN_MODE=offline。

验证状态:2026-09-25 已用真实 API 在线执行本章全部调用,下方输出即实测结果。 批量执行、离线预览和验收记录见本目录 MAINTENANCE.md。

0. 准备

本节可折叠阅读,但独立运行时不能跳过。客户端、辅助对象和示例数据都在本文件中定义。

0.1 安装依赖

推荐先运行 setup_env.sh。只有当前内核缺少 SDK 时,本格才安装依赖。

import importlib.util
if importlib.util.find_spec("typesafe_sdk") is None:
    %pip install -q typesafe-sdk==0.7.0

观察与理解: 安装包的名字是 typesafe-sdk,Python 导入名是 typesafe_sdk。安装成功不代表 API 已连通。

0.2 导入与配置

默认模型固定版本,便于记录实验条件;可通过环境变量更换。不要从 Notebook 输入密钥。

import os
import json
import time
import math
from datetime import datetime, timezone
from importlib.metadata import version
from typesafe_sdk import (
    Choice, Score, Noul, NoulCriteria, TypeSafeClient,
    TypeSafeAuthenticationError, RetryPolicy,
)

MODEL = os.environ.get("TYPESAFE_DEFAULT_MODEL", "jev-1.13.0")
RUN_MODE = os.environ.get("JEV_RUN_MODE", "auto")
API_KEY = os.environ.get("TYPESAFE_API_KEY", "")
if RUN_MODE not in {"live", "offline", "auto"}:
    raise ValueError("JEV_RUN_MODE 只能是 live、offline 或 auto")
if RUN_MODE == "live" and not API_KEY:
    raise RuntimeError("JEV_RUN_MODE=live 需要真实密钥:请配置 TYPESAFE_API_KEY;仅学习可改用默认 auto(无密钥自动离线)")
client = None if (RUN_MODE == "offline" or not API_KEY) else TypeSafeClient(
    api_key=API_KEY, model=MODEL, timeout=30, retry=RetryPolicy(max_retries=0))
mode_note = ("在线优先:本次会话调用真实模型" if client is not None else
             ("强制离线(JEV_RUN_MODE=offline)" if RUN_MODE == "offline" else
              "未检测到 TYPESAFE_API_KEY → 离线替身;配置密钥后重跑本格即切在线实测"))
print("模式:", RUN_MODE, "|", mode_note, "|SDK:", version("typesafe-sdk"), "|模型配置:", MODEL)
模式: auto | 在线优先:本次会话调用真实模型 |SDK: 0.7.1 |模型配置: jev-1.13.0

默认在线优先:有密钥即走真实模型,每次调用的来源(live/offline)都记录在 CALL_LOG 与输出中;auto 仅在未配置密钥或 401 时回退离线替身。正式验收设 JEV_RUN_MODE=live(禁用回退、不自动重试,请求数量有界)。

0.3 连通性测试

用一条 Noul 检查真实响应能否返回。网络、限流与输入错误直接抛出,不伪装成不确定判断。

PING = {"source": "offline", "reason": "未发起连通性请求(无 client:未配置密钥或强制离线)"}
if client is not None:
    try:
        ping = client.system_one("你好", {"greeting": Noul(
            instructions="这段文字是否在打招呼?")})
        PING = {"source": "live", "model": ping.model,
                "input_tokens": ping.usage.input_tokens,
                "output_tokens": ping.usage.output_tokens}
    except TypeSafeAuthenticationError:
        if RUN_MODE == "live":
            raise
        client.close()
        client = None
        PING["reason"] = "401 鉴权失败,仅教学模式允许回退"
print(json.dumps(PING, ensure_ascii=False))
{"source": "live", "model": "jev-1.13.0", "input_tokens": 278, "output_tokens": 22}

观察与理解: source=live 表示这一次连通性请求成功;仍要查看后续实验记录,不能用它代替整章验收。

0.4 离线替身

沿用参考模板的 _FakeAnswer 与 _FakeResponse 访问方式。人工数字仅用来检验读取字段和代码分支。

class _FakeAnswer:
    def __init__(self, type_, **values):
        self.type = type_
        for name, value in values.items():
            setattr(self, name, value)


class _FakeResponse:
    def __init__(self, answers):
        self.answers = answers
        self.choices = {k: v for k, v in answers.items() if v.type == "choice"}
        self.scores = {k: v for k, v in answers.items() if v.type == "score"}
        self.nouls = {k: v for k, v in answers.items() if v.type == "noul"}
        self.model = "人工示例,非模型预测"
        self.usage = _FakeAnswer("usage", input_tokens=0, output_tokens=0)

人工 Score 由概率计算期望,避免模板中的分数与分布不一致。人工 confidence 只是指定的演示字段,不是在复现服务端的计算公式。

定义两种示例答案构造器;Noul 可直接用 _FakeAnswer。所有具体答案集中在下一节。

def fake_choice(probabilities, confidence):
    return _FakeAnswer("choice", choice=max(probabilities, key=probabilities.get),
                       probabilities=probabilities, confidence=confidence)


def fake_score(probabilities, legend, confidence):
    return _FakeAnswer("score", score=sum(k * p for k, p in probabilities.items()),
                       probabilities=probabilities, legend=dict(enumerate(legend)),
                       confidence=confidence)

观察与理解: 例如概率 {0:0.05, 1:0.26, 2:0.69} 对应 1.64。不能把另一个数与该分布配在一起。

0.5 统一调用入口

每次调用记录来源、模型与 token 用量。离线耗时记为 None,不把本地字典访问当成模型速度。

CALL_LOG = []


class TS:
    def call(self, state, questions, offline_answers, label):
        start = time.perf_counter()
        source = "live"
        if client is None:
            response, source = _FakeResponse(offline_answers), "offline"
        else:
            try:
                response = client.system_one(state, questions)
            except TypeSafeAuthenticationError:
                if RUN_MODE != "auto":
                    raise
                response, source = _FakeResponse(offline_answers), "offline"
        validate_response(response, questions)
        CALL_LOG.append({"case": label, "source": source, "model": response.model,
                         "seconds": time.perf_counter() - start if source == "live" else None,
                         "input_tokens": response.usage.input_tokens,
                         "output_tokens": response.usage.output_tokens})
        if source == "offline":
            print("离线替身(未调用真实模型):", label, ";人工答案,仅演示代码路径")
        return response


ts = TS()

与参考模板相比,这里增加了严格 live 模式和逐次记录。保留 401 教学回退,但超时、429 等错误继续失败,防止验收被回退掩盖。

校验结构与数值契约;只断言接口应满足的性质,不断言真实模型必须预测某个标签。

def validate_response(response, questions):
    if set(response.answers) != set(questions):
        raise ValueError("答案 ID 与问题 ID 不一致")
    for key, question in questions.items():
        answer = response.answers[key]
        if isinstance(question, Noul):
            if not 0 <= answer.noul <= 1:
                raise ValueError("Noul 超出概率范围")
            continue
        probabilities = answer.probabilities
        if not all(math.isfinite(p) and 0 <= p <= 1 for p in probabilities.values()):
            raise ValueError("概率值无效")
        if not math.isclose(sum(probabilities.values()), 1, abs_tol=0.02):
            raise ValueError("概率之和偏离 1")
        if not 0 <= answer.confidence <= 1:
            raise ValueError("confidence 超出范围")
        if isinstance(question, Choice):
            if set(probabilities) != set(question.criteria):
                raise ValueError("Choice 选项集合不一致")
            if answer.choice not in probabilities:
                raise ValueError("Choice 标签不在选项中")
        else:
            expected = sum(int(k) * p for k, p in probabilities.items())
            if not math.isclose(answer.score, expected, abs_tol=0.03):
                raise ValueError("Score 与概率加权期望不一致")

观察与理解: 容差用于服务端数值舍入。结构检查通过只说明响应可读取,不证明语义判断正确。

显示结果时统一列出类型、概率和置信度;Noul 不额外制造 confidence 字段。

def show(response):
    rows = {}
    for key, answer in response.answers.items():
        rows[key] = {name: getattr(answer, name) for name in
                     ("type", "choice", "score", "noul", "confidence", "probabilities", "legend")
                     if hasattr(answer, name)}
    print(json.dumps(rows, ensure_ascii=False, indent=2))

0.6 本章离线示例数据

以下数值全部人工构造,专门测试分支;不来自 Jev,也不能用于估计中文准确率或校准情况。正式 live 运行不会使用这些答案。

1. Jev 是什么

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

传统 LLM 为人类阅读写文本;当代码需要做判断时,就得把生成的文字再解析回程序可依赖的形式——这一步既慢又脆。Jev 直接跳过这两步:像 LLM 一样读懂自然语言,但只返回你问的那几个数。

与 LLM 的区别(官方对比)

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

两个边界:目前只接受文本输入(字符串、JSON、文本数组;图像/音频/视频暂不支持);名字借自《思考,快与慢》的「系统 1」——快速直觉判断,不是对人类思考的科学复现。

三种原语 = 全部词汇

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

三种问题可以在一次调用里混用,每个问题并行、相互独立地对照同一 state 求值——加问题几乎不增加延迟,也没有长上下文「越读越糊」的问题。

提问纪律:每个问题只问一件专家几秒内能下结论的事(原子判断)。 复杂判断拆成多个独立问题,在代码里用自有逻辑加权组合——优先级变了只改代码系数,不用改提示词。

速度与价格量级

输入 $0.042 / 百万 token,输出免费(官方 Models 页);实测中位延迟约 0.65–0.72 秒(JevBench v1.2)。便宜到可以「投机式地多问」——把不确定用不用得上的问题都塞进同一次调用。

阅读:官方 Introduction · 官方原文 · 中文参考

2. 三分钟上手

最快的方式:打开官方 Playground,粘贴任意文本,加一个问题就能看到答案。不想登录也可以直接发 HTTP:

curl -X POST 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": "这条消息是否表达了紧迫性?"}}}'

下面用 SDK 做同样的事,并在一次调用里同时问三种原语——这是 System One 的核心体验:一发请求,三份带概率的答案。离线运行时返回人工构造答案(会打印提示),不代表 Jev 实测。

实验 A:一次调用,三种原语

EXP_STATE = ("用户:我连续三天没能把 Stripe 账户连上,集成一直失败,"
             "每耽误一天都在丢订单,请尽快处理!")

EXP_QUESTIONS = {
    "urgency": Noul(instructions="这条消息是否表达了紧迫性?"),
    "intent": Choice(instructions="用户的主要诉求是什么?", criteria={
        "troubleshoot": "希望排查或修复连接问题",
        "refund": "要求退款或赔偿",
        "inquiry": "只是咨询,不要求立即处理"}),
    "frustration": Score(instructions="用户的受挫程度如何?", criteria=[
        "平静,仅陈述事实", "有些不满", "强烈不满,有流失风险"]),
}
EXP_OFFLINE = {
    "urgency": _FakeAnswer("noul", noul=0.94),
    "intent": fake_choice({"troubleshoot": 0.82, "refund": 0.03, "inquiry": 0.15}, 0.8),
    "frustration": fake_score({0: 0.05, 1: 0.35, 2: 0.6},
                              ["平静", "有些不满", "强烈不满"], 0.87),
}

resp_a = ts.call(EXP_STATE, EXP_QUESTIONS, EXP_OFFLINE, "实验A·三原语一次调用")
show(resp_a)
{
  "urgency": {
    "type": "noul",
    "noul": 0.98
  },
  "intent": {
    "type": "choice",
    "choice": "troubleshoot",
    "confidence": 1.0,
    "probabilities": {
      "refund": 0.0,
      "inquiry": 0.0,
      "troubleshoot": 1.0
    }
  },
  "frustration": {
    "type": "score",
    "score": 1.99,
    "confidence": 0.98,
    "probabilities": {
      "0": 0.0,
      "1": 0.01,
      "2": 0.99
    },
    "legend": {
      "0": "平静,仅陈述事实",
      "1": "有些不满",
      "2": "强烈不满,有流失风险"
    }
  }
}

观察与理解: live 模式下三份答案来自同一次网络往返;Choice/Score 带 confidence,Noul 的不确定性直接体现在概率靠近 0.5。三个问题相互独立——如果改 intent 的措辞会牵动 urgency 的数值,说明问题写得不够原子。

3. 场景地图:什么活儿适合交给 Jev

官方 Use Case Map 整页回答这一个问题。五大类用法:

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

官方归纳的判断形态,每一种都落到三种原语上:

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

两个边界(从官方用例读出,非官方明文):各场景几乎都配「不确定就转人工」——法务、理赔、招聘淘汰这类高风险终审不能全交给它;需要长篇写作或开放推理时转交大模型,Jev 在前面把「该走哪条路」快速定下来。

阅读:官方 Use Case Map · 官方原文 · 中文参考

4. 概率为什么可信:训练目标与校准

预训练模型之后有三条改造路线(官方 AI Primer):RLHF 把模型变成聊天机器人;RLVR 造出会推理但更慢更贵的模型;RLCD(面向校准决策的强化学习)是 Jev 走的第三条路——训练模型返回决策和校准概率,而不是文本。

校准的含义:按一组预测衡量。给 0.8 概率的事件,长期发生频率应接近 80%;它不保证任何单次预测正确。

用 20 条人工数据直观感受「校准」——预测 0.2 的组实际发生 10%,预测 0.8 的组发生 80%,两组都「准」,但组内单次仍会错:

groups = {0.2: [1] * 2 + [0] * 8, 0.8: [1] * 8 + [0] * 2}
for p, labels in groups.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 次没发生

观察与理解: 校准好 ≠ 单次必对。工程上正确的用法:用概率做群体决策(路由、排序、抽检),单点高风险动作交给阈值和人工复核。

5. 知识补充:社区实测认知(jev-cookbook)

以下数字全部来自 datawhalechina/jev-cookbook 知识库收录的实验报告:

JevBench v1.2(cookbook 15-jevbench,242 个类型化决策的公开基准):

  • Jev 1.13.0 综合智能分榜首(75.4),答案可解析率 100%,路由任务 74.1%,中位延迟 0.65–0.72s,每千次决策成本约 $0.04;
  • 稳定性:同一套题隔 16 分钟跑两遍,仅 1.2% 的答案变化——端点不是确定性的,读表时约 1 个百分点的差距应视为噪声。

Jev 能替代 Rerank 吗(cookbook 18-wechat-rerank-experiment,80 条 SciFact 查询的精排对照):

  • 相对不做精排,Jev 的 nDCG@10 提升 +0.0778,比传统精排还高 +0.0332,精排耗时与 token 用量显著更低。固定候选集上的语义重排是 Jev 的甜点区。

fast-jev-compaction(cookbook 04,Claude Code 压缩插件的生产用法):

  • 每次工具调用和结果在一次快请求里逐条打分,过期内容丢弃、保留的保持原文——用 Jev 的判断替代有损摘要。

智能家居(官方 demos/smart-home + 我们的可运行复刻):

  • 模式:一次调用捆绑 10 个问题(意图、是否复合、范围、房间、设备类别 + 五类设备动作预判),代码端剪枝无关分支;复合指令再用 noul 判「谁必须先于谁」做串并行编排——「投机式多问 + 原子组合」的完整实战。

6. 综合实验:赛事指挥台

一次夜跑赛事收到三条现场消息。我们让 Jev 在一次请求中对每条消息回答三个独立问题(哪类事件 Choice、多快处理 Score、是否需要人工 Noul),再由 Python 按阈值分流——模型管语义,代码管规则。

6.1 定义状态与问题

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="是否需要人工到场介入?"),
}

6.2 逐条调用并由代码分流

ROUTES = {"medical_help": "现场负责人 / 医疗人员",
           "supplies": "补给组(优先处理)",
           "event_info": "自动回复赛事 FAQ(模拟)"}
LEVELS = ["可赛后", "30分钟", "10分钟", "立即"]
OFFLINE = [
    {"incident_type": fake_choice({"medical_help": 0.9, "supplies": 0.06, "event_info": 0.04}, 0.9),
     "priority": fake_score({0: 0, 1: 0, 2: 0.15, 3: 0.85}, LEVELS, 0.9),
     "requires_human": _FakeAnswer("noul", noul=0.93)},
    {"incident_type": fake_choice({"supplies": 0.88, "medical_help": 0.06, "event_info": 0.06}, 0.85),
     "priority": fake_score({0: 0.1, 1: 0.7, 2: 0.2, 3: 0}, LEVELS, 0.8),
     "requires_human": _FakeAnswer("noul", noul=0.22)},
    {"incident_type": fake_choice({"event_info": 0.9, "supplies": 0.05, "medical_help": 0.05}, 0.9),
     "priority": fake_score({0: 0.8, 1: 0.2, 2: 0, 3: 0}, LEVELS, 0.85),
     "requires_human": _FakeAnswer("noul", noul=0.04)},
]

for inc, off in zip(INCIDENTS, OFFLINE):
    r = ts.call(inc["state"], INCIDENT_QUESTIONS, off, f"指挥台·{inc['id']}")
    t = r.choices["incident_type"].choice
    human = r.nouls["requires_human"].noul >= 0.7   # 阈值是应用政策
    print(f"{inc['id']:14s} → {ROUTES[t]}{'(转人工)' if human else ''}")
runner_injury  → 现场负责人 / 医疗人员(转人工)
water_station  → 补给组(优先处理)(转人工)
shirt_pickup   → 自动回复赛事 FAQ(模拟)

观察与理解: 模型只回答了三个数;「≥0.7 转人工」这条规则完全在代码里——改阈值不重跑模型、不碰提示词。把不可妥协的规则(如医疗类永远转人工)写进确定性代码,正是官方推荐的分工。

练习与自查

把「该不该给这条工单升级到人工?」设计成一个合格的问题。它该用哪种原语?什么样的写法违反了原子性?

参考思路:先完成练习再展开

「升级到人工」混了两个判断:问题严重不严重(Score 或 Noul)+ 当前自动流程能不能处理(Noul/Choice)。合格写法是拆成两个独立问题,由代码组合;一个 noul 同时问两件事,任一因素翻转都会污染概率。下一章:System One 深入单次调用机制;想先练原语可看原语。

小结

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

离线运行只说明教材代码能执行。正式交付必须实际运行 live,并阅读每条输出;缺失的分支应记为未观察到。

本次执行记录

先关闭连接,再生成记录。下面的 JSON 由实际运行计算,批量执行器会据此检查来源。

if client is not None:
    client.close()

本章拿几句话试了试真实模型,看它给的概率怎么反应——这只说明模型对这类输入的反应方式,不构成准确率评测。特别提醒:如果哪句答得合心意就专门挑出来当考题,再拿这些挑过的句子去算准确率,数字必然虚高。输出里的耗时也只是当时网络的快照,每次都会不一样。

AUDIT = {
    "kind": "jev_execution_audit",
    "executed_at_utc": datetime.now(timezone.utc).isoformat(),
    "sdk": version("typesafe-sdk"), "requested_model": MODEL,
    "mode": RUN_MODE, "ping": PING,
    "real_calls": sum(x["source"] == "live" for x in CALL_LOG),
    "offline_calls": sum(x["source"] == "offline" for x in CALL_LOG),
    "cases": CALL_LOG,
    "coverage": globals().get("COVERAGE", {}),
    "validation_status": "live_executed_requires_review" if (
        PING["source"] == "live" and CALL_LOG
        and all(x["source"] == "live" for x in CALL_LOG)
    ) else "offline_only_not_model_evidence",
}
print(json.dumps(AUDIT, ensure_ascii=False, indent=2))
{
  "kind": "jev_execution_audit",
  "executed_at_utc": "2026-09-25T09:21:31.117446+00:00",
  "sdk": "0.7.1",
  "requested_model": "jev-1.13.0",
  "mode": "auto",
  "ping": {
    "source": "live",
    "model": "jev-1.13.0",
    "input_tokens": 278,
    "output_tokens": 22
  },
  "real_calls": 4,
  "offline_calls": 0,
  "cases": [
    {
      "case": "实验A·三原语一次调用",
      "source": "live",
      "model": "jev-1.13.0",
      "seconds": 0.2818761672824621,
      "input_tokens": 478,
      "output_tokens": 78
    },
    {
      "case": "指挥台·runner_injury",
      "source": "live",
      "model": "jev-1.13.0",
      "seconds": 0.2828013342805207,
      "input_tokens": 499,
      "output_tokens": 76
    },
    {
      "case": "指挥台·water_station",
      "source": "live",
      "model": "jev-1.13.0",
      "seconds": 0.25633825035765767,
      "input_tokens": 495,
      "output_tokens": 77
    },
    {
      "case": "指挥台·shirt_pickup",
      "source": "live",
      "model": "jev-1.13.0",
      "seconds": 0.3410124173387885,
      "input_tokens": 492,
      "output_tokens": 76
    }
  ],
  "coverage": {},
  "validation_status": "live_executed_requires_review"
}

读完输出后,在本仓库 notebooks/MAINTENANCE.md 的验收表中记录日期、真实模型、观察到的分支和偏离预期之处。不要把人工演示数值抄进实测记录。

📑 Jev Cookbook:System One 判断模型实战教程

1 第 1 章:认识 Jev:模型、上手与场景 2 第 2 章:核心概念总览 3 第 3 章:System One:判断的核心心智模型 4 第 4 章:状态:让判断连续可追溯 5 第 5 章:原语:Choice、Score 与 Noul 6 第 6 章:置信度:让概率可信 7 第 7 章:应用构建:从原语到完整系统 8 第 8 章:架构模式 9 第 9 章:实战指南总览 10 第 10 章:自一致性 · Noul 11 第 11 章:自一致性 · Choice 12 第 12 章:并行提问 13 第 13 章:重排序 14 第 14 章:逐行语义搜索 15 第 15 章:结构恢复 16 第 16 章:函数调用 17 第 17 章:技能推荐 18 第 18 章:实体对齐 19 第 19 章:RAG 段落分类 20 第 20 章:引用核查 21 第 21 章:LLM 防护栏 22 第 22 章:SDE 级联 23 第 23 章:日期抽取 24 第 24 章:预解析值抽取 25 第 25 章:层级分类 26 第 26 章:自动研究特征发现 27 第 27 章:基于置信度的分类 28 第 28 章:智能家居实验 29 第 29 章:模型评测总览 30 第 30 章:模型评测实验 31 第 31 章:Laya vs Jev 对比基准 32 第 32 章:JevBench:LLM 评测体系 33 第 33 章:智能家居应用实战 34 第 34 章:Jev-Mem 研究总览 35 第 35 章:Jev-Mem 缩放实验 36 第 36 章:Jev-Mem 完整走查 37 第 37 章:Agent 集成总览 38 第 38 章:Pi 集成实验 39 第 39 章:DSH 决策协作 40 第 40 章:本地模型总览 41 第 41 章:本地模型介绍与对比 42 第 42 章:中文数据集构建方案 43 第 43 章:微调指南 44 第 44 章:RLCD 原理与实验优化 45 第 45 章:中文数据集构建实验 46 第 46 章:中文 Head 微调实验 47 第 47 章:全量 v2 微调实验 48 第 48 章:知识库
← 返回本书大纲