第 2 章

第 2 章:三种类型化输出——Choice、Score、Noul 与调用契约

第 2 章:三种类型化输出——Choice、Score、Noul 与调用契约

上一章说 Jev 输出"类型化决策",但类型化到什么程度?答案是:只有三种——多选、有序评分、布尔。听起来少得可疑,但正是这种克制让判别变得可组合、可测试。本章拆开调用契约,把三种输出的语义、概率和边界用法讲透。

一次调用长什么样

Jev 的核心接口是 POST /v1/systemone,模型名通常是 jev-latest(也可以锁定到具体版本如 jev-1.13)。一次调用由三部分组成:

  • state:非结构化的上下文。可以是用户输入、文档片段、代码、检索结果、工具返回值——任何"需要被判断的东西"。
  • questions:一组类型化的提问。这是关键:每个问题都要声明它的类型(choice / score / noul),可选地给出选项或打分范围。
  • instructions:系统层面的指令,描述角色、判断标准、边界。相当于 system prompt,但服务的对象是决策而不是生成。

返回值就是与 questions 一一对应的类型化决策,每个决策都带概率。用官方 Python SDK 写出来大致是这样:

from typesafe import TypesafeClient

client = TypesafeClient()  # 读取 TYPESAFE_API_KEY

decision = client.systemone(
    state="订单号 88371,用户申请退款,理由:收到时包装破损,商品本身完好。",
    questions={
        "intent": {
            "type": "choice",
            "question": "这条工单的核心诉求是什么?",
            "choices": ["退款", "换货", "咨询", "投诉"]
        },
        "urgency": {
            "type": "score",
            "question": "这条工单的紧急程度如何?",
            "labels": ["低", "中", "高"]
        },
        "needs_human": {
            "type": "noul",
            "question": "是否必须人工介入才能处理?"
        }
    },
    instructions="你是电商客服分诊助手,按工单的实际诉求判断,不要被情绪词带偏。"
)

返回值里,intent 给的是带概率的选项,urgency 给的是有序评分,needs_human 给的是布尔概率。三种类型,覆盖了绝大多数判别任务。下面逐个说清。

Noul:布尔判断

Noul 回答的是"是/否",返回一个 P(true)。官方之所以不叫它 Boolean,是想强调它返回的不是一个干巴巴的 true/false,而是带概率的布尔。

needs_human = decision["needs_human"]
print(needs_human.value)        # True / False
print(needs_human.probability)  # 例如 0.87

用法上,Noul 是十种决策形态里 Detection 和 Verification 的底层形态:这条评论是不是垃圾、这段代码有没有 SQL 注入、这个回复有没有捏造事实——凡是能归约成"是/否"的,都用 Noul。

实际工程里,Noul 最重要的不是那个布尔值,而是概率。你可以据此设阈值:

p = decision["needs_human"].probability
if p >= 0.9:
    escalate_now(ticket)        # 高置信,直接人工
elif p >= 0.5:
    queue_for_review(ticket)    # 中等,进入待复核队列
else:
    auto_reply(ticket)          # 低置信,自动处理

阈值不是拍脑袋定的,而是对着你的业务代价调出来的——漏判的成本高就压低阈值,误判的成本高就抬高阈值。第 5 章会专门讲校准。

Choice:多选

Choice 回答的是"从 N 个选项里选一个"。返回每个选项的概率,所有概率之和为 1。选项数量支持 2 到 255 个。

intent = decision["intent"]
print(intent.choice)         # "换货"
print(intent.probabilities)  # {"退款": 0.12, "换货": 0.79, "咨询": 0.05, "投诉": 0.04}

三个工程要点:

第一,选项是封闭的。 模型只能在给定的选项里选,不可能给你一个"其他"。这消灭了"解析自由文本"的全部麻烦。代价是你要提前穷举可能的类别——这也是分类任务真正的设计工作量所在。

第二,概率分布是连续的可用信息。 0.79 对 0.12 说明这次判断很笃定;但如果分布是 0.34 / 0.31 / 0.20 / 0.15,你就知道这条工单本身就模糊,适合转人工或者追问。不要只看 choice 字段,要看整个分布。

第三,多选不等于多标签。 这里"多选"指的是从多个候选中选一个。如果你要打多个标签,用多个 Noul 问题(每个标签一个"是不是"),而不是一个 Choice。这个区别在 Classification 形态里很重要。

Choice 是十种形态里 Classification 和 Routing 的底层形态。

Score:有序评分

Score 回答的是"在某个有序尺度上打几分"。它的精妙之处在于评分不是一个数字,而是一个概率分布。

urgency = decision["urgency"]
print(urgency.probabilities)  # {"低": 0.10, "中": 0.25, "高": 0.65}
print(urgency.score)          # 计算得到:1*0.10 + 2*0.25 + 3*0.65 = 2.55

score 的计算方式是按序号加权求和:设尺度的第 i 档对应数值 i,则 score = Σ i · p_i。上面例子里 低/中/高 对应 1/2/3,得到 2.55——一个落在 1 到 3 之间的连续值,比单纯取"最高概率的那一档"信息量更大。

为什么要用分布而不是直接要一个数?因为直接让模型给数字("打 1-10 分")是最不可靠的——它对"7 分"和"8 分"的边界没有共识,不同调用之间抖动很大。而让它在少数几个有序档位上给分布,每个档位都有明确语义,稳定性高得多,还能顺带拿到不确定性。

sev = decision["severity"].score
if sev >= 2.5:
    pager.oncall()

Score 是 Scoring 和 Ranking(用 score 排序)的底层形态。

三种类型与十种形态的对应

十种决策形态不是十种新 API,而是三种类型化输出在具体任务上的组合玩法。先建立这张对应关系,后面的章节会顺次展开:

flowchart LR
    subgraph 三种类型化输出
        C["Choice
多选,Σp=1"] S["Score
有序评分,Σi·p_i"] N["Noul
布尔,P(true)"] end subgraph 十种决策形态 CL["Classification"] --> C RT["Routing"] --> C DT["Detection"] --> N SC["Scoring"] --> S RK["Ranking"] --> S VF["Verification"] --> N SE["Search"] --> N RE["Retrieval"] --> N FE["ML Feature Extraction"] --> S SD["Structured Data Extraction"] --> C end

一句话记住:Choice 管"选哪个",Score 管"多少分",Noul 管"是不是"。 十种形态无非是在这三种之上叠加了任务语境和后处理。

调用契约里的几个细节

关于成本。 决策调用的成本远低于生成调用,因为它不生成 token 序列,只在一个封闭的选择空间上出分布。社区里大量项目的实测都指向同一个量级:单次判定成本常常低到"每千次几美分",某些场景下比用生成模型省两个数量级。第 22 章会用具体数字展开。

关于延迟。 决策调用的延迟也显著低于生成,官方把 150 毫秒作为实时应用的预算线。第 20 章会讲怎么在 150 毫秒内完成一次决策乃至一串决策。

关于批量。 大规模判定不要一次一个地调用,而是把多条 state 打成一批(batch)送进去。第 22 章的 AI Map Reduce 就是围绕批处理展开的。

关于版本。 生产环境建议锁定具体版本(如 jev-1.13)而不是 jev-latest,这样行为可复现。升级时单独刷一遍回归测试——第 23 章会讲怎么做决策层的回归验证。

关于确定性。 决策层给出的是概率分布,不是"永远同一个答案"。同一个 state 调两次,choice 可能一致但概率有细微浮动。如果你的下游逻辑对确定性敏感,要么设阈值把区间切断,要么在测试里断言"概率落在某个范围"而不是"等于某个值"。

一个最小可运行的例子

把三种类型凑在一次调用里,做一个"邮件分诊":

def triage(email_text: str) -> dict:
    d = client.systemone(
        state=email_text,
        questions={
            "label": {
                "type": "choice",
                "question": "这封邮件的类型?",
                "choices": ["工作", "账单", "推广", "社交", "其他"]
            },
            "importance": {
                "type": "score",
                "question": "重要程度?",
                "labels": ["可忽略", "一般", "重要", "紧急"]
            },
            "has_deadline": {
                "type": "noul",
                "question": "邮件的正文里是否包含一个明确的截止时间?"
            }
        },
        instructions="你是邮箱助理。判断依据只看邮件正文,不要脑补。"
    )

    return {
        "label": d["label"].choice,
        "label_conf": max(d["label"].probabilities.values()),
        "importance": d["importance"].score,
        "deadline": d["has_deadline"].value,
        "deadline_p": d["has_deadline"].probability,
    }

一次调用同时拿到了分类、评分、检测三种判断,各有各的概率。你的代码拿着这三个结果去做任何它想做的控制流——这就是"代码拥有控制流,模型只做判定"落到手边的样子。

小结

  • 一次调用由 state + questions + instructions 组成,返回与 questions 对应的类型化决策。
  • 三种输出:Noul(布尔 + P(true))、Choice(多选,Σp=1,2–255 个选项)、Score(有序评分,score = Σ i·p_i)。
  • 看决策要看整个概率分布,不只看选中的那一项;概率是设阈值、判不确定性、做升级策略的依据。
  • 十种决策形态都是这三种输出在具体任务上的组合:Choice 管"选哪个",Score 管"多少分",Noul 管"是不是"。
  • 生产建议:批处理、锁版本、对概率做区间断言而非等值断言。

下一章把镜头拉远,站在选型的高度看十种形态各自的适用边界,回答"什么判断该交给 Jev"。

📑 Jev 实战:用类型化决策重构软件

1 第 1 章:为什么需要决策层——从"生成一切"到"只做判定" 2 第 2 章:三种类型化输出——Choice、Score、Noul 与调用契约 3 第 3 章:十个决策形态——什么时候该把判断交给 Jev 4 第 4 章:Classification 与 Routing——把分诊做成一等公民 5 第 5 章:Detection 与 Scoring——二元判断与有序评分 6 第 6 章:Search 与 Retrieval——在候选集里找相关 7 第 7 章:Ranking 与 Verification——排序与校验 8 第 8 章:ML Feature Extraction 与 Structured Data Extraction——把文本变特征与结构化数据 9 第 9 章:检索与知识图谱——Search and retrieval / Graphs and knowledge graphs 10 第 10 章:模型路由与 LLM 护栏——Model routing / LLM guardrails 11 第 11 章:语义代码检查——Semantic code linting 12 第 12 章:特征提取与需求预测——Feature extraction / Demand forecasting 13 第 13 章:招聘与线索生成——Recruiting / Lead generation 14 第 14 章:客户支持——Customer support 15 第 15 章:理赔、金融犯罪与风险评估——Insurance claims / Financial crime / Risk assessment 16 第 16 章:法律与合规——Legal and compliance 17 第 17 章:电商市场与广告——E-commerce marketplaces / Advertising 18 第 18 章:内容审核与信任安全——Moderation and trust and safety 19 第 19 章:游戏——Gaming 20 第 20 章:实时应用——150 毫秒预算 21 第 21 章:科学发现——Scientific discovery 22 第 22 章:大数据上的 AI Map Reduce——为什么便宜 100 倍 23 第 23 章:通用验证——Universal Verification 24 第 24 章:Harness Engineering——把决策织进智能体骨架
← 返回本书大纲