JEV如何使用?

先说结论

  • JEV 的关键不是让它“思考”,而是把业务拆成 Choice、Score、Noul 三类小问题,再用代码组合。
  • 一个请求可以对同一个 state 并行问多个问题;例如“这条工单要不要升级”能拆成部门路由、是否退款、紧急度三个判断。
  • confidence 是概率分布压缩出的单一数字,用来做高置信自动、低置信转人工的门控;阈值应按动作风险分别设置。
  • 上线前需要按官方定价和限流做成本估算,并记录实际响应的模型版本;非英文场景要先用自己的数据回测。

从模糊需求到类型化问题

JEV 是 TypeSafe 的 System One 模型,定位是快速、有类型返回的判断。官方 Primitives 页面给出的三种原语是:

  • Choice:回答“哪个选项”,返回 choiceprobabilitiesconfidence
  • Score:回答“处于哪个等级”,返回 scorelegendprobabilitiesconfidence;它的 criteria 是一个有序数组,从低到高。
  • Noul:回答“这件事是不是真的”,只返回一个 noul 值,取值范围 0 到 1;它没有 confidence,也没有 probabilities

官方 Primitives 页面强调“一个问题只做一次快速判断”:

Ask for a judgment a knowledgeable person makes in a second given the right context. “Does this message convey urgency?” is a good question. “Analyze this message and determine the best course of action” is not.

这句话对工程落地很重要:如果需求是“分析这条消息并决定最佳行动”,那不是 JEV 的原语擅长的事情。官方继续建议,如果一个判断依赖多个独立因素,就逐个因素分开问,再用自己的逻辑组合:

If the judgment you want depends on several independent factors, ask about each factor separately and combine the answers with your own logic.

所以使用 JEV 时,我会先做一步拆解:把“模糊需求”改成多个边界清楚的小问题,每个问题只判一件事,最后在代码里组合。

工单拆解:把三个问题放进同一次请求

举个业务例子:客服系统里要判断“这条工单要不要升级”。这其实不是单一问题,它至少包含三件事:应该由哪个部门处理、客户是否在要求退款、问题有多紧急。下面是一个本文示例,用来演示拆解方式;代码不是官方示例,但字段形状来自官方 Primitives 页面。

from typesafe_sdk import TypeSafeClient, Choice, Score, Noul

client = TypeSafeClient()

state = {
    "ticket": {
        "subject": "被重复扣款",
        "messages": [
            {"from": "customer", "text": "我被重复扣款了,请退款"},
            {"from": "support", "text": "正在核查扣款记录"},
        ],
        "policy": "重复扣款符合退款条件",
    }
}

questions = {
    "route_to": Choice(
        instructions="Which department should handle this ticket?",
        criteria={
            "billing": "Charges, refunds, invoices",
            "technical": "Login, performance, bugs",
            "account": "Account access and verification",
            "other": "None of the above",
        },
    ),
    "refund_requested": Noul(
        instructions="Does the customer request a refund?",
    ),
    "urgency": Score(
        instructions="How urgent is this ticket?",
        criteria=["low", "medium", "high", "critical"],
    ),
}

response = client.system_one(state=state, questions=questions)

dept = response.answers["route_to"].choice
refund_signal = response.answers["refund_requested"].noul
urgent_level = response.answers["urgency"].score

这里我把“要不要升级”拆成三个可组合的信号:route_to 是 Choice,refund_requested 是 Noul,urgency 是 Score。官方 Models 页面写明:

Jev ingests the state once and evaluates every question against it in parallel.

也就是说,这三个问题会看到同一份 state,并在一次请求里被并行评估。这不是我自己的架构设计,而是官方对请求处理方式的说明。代码里的组合逻辑可以由业务决定,例如我认为“路由到 billing 且退款信号很高,或者紧急度达到 high/critical,就升级”。这是我在本文示例中的做法,不是官方要求。

state 怎么给:官方约束与工程建议

官方 State 文档对 state 的定义是:

State can be a simple string or a structured JSON value

具体来说,state 可以是字符串、JSON 对象,或者文本值数组。文档还写明 JEV 是文本输入:

State must be a string, JSON object, or array of text values. Images, audio, and video are not supported (yet).

如果只是简单判断,一个字符串就够;但多数业务判断会涉及多个相关字段。官方建议大多数请求使用对象,这样每个部分都有描述性名称,关系更清楚:

Use an object for most requests so each part of the state has a descriptive name and its relationships remain clear.

我的工程建议是:state 只放与当前判断相关的片段,不要把全量日志、无关用户轨迹、整张订单表都倒进去。倒全量日志会带来三个问题:输入 token 成本上升、模型注意力被噪声稀释、问题与证据的边界不清。官方并没有禁止你放更多内容,但按官方“把 state 当作你给专家看的材料”这一类比,给专家的也应该是精选材料,而不是原始流水。这条建议是我的工程判断,不是官方要求。

confidence 怎么用:官方定义与门控模式

JEV 的 Choice 和 Score 答案会返回概率分布,并在此基础上给一个 confidence。官方 Confidence 文档直接说明它来自概率分布:

All Score and Choice answers from TypeSafe include a probabilities property representing the probability distribution across the options (for Choice) or levels (for Score). The shape of that distribution is what tells you how certain the model is: concentrated on one outcome means a confident answer, spread out means an uncertain one.

并且:

Confidence is derived from the probabilities

也就是说,confidence 不是独立生成的第二个判断,而是把概率分布“压平”成一个 0 到 1 的数,方便代码做阈值判断。Noul 不返回 confidence,所以如果你需要对“是否退款”这种 Noul 问题做门控,应该自己定如何处理 noul 值,不能期待它自带置信字段。

官方 Confidence-gated routing 这个模式页把 confidence 当成第二轴:

Use confidence as a second axis. The answer tells you what; confidence tells you whether to act.

工程上常用的门控分三档:高置信可以自动执行;中等置信要谨慎处理,比如请用户确认或标记复核;低置信不要行动,转人工、要求澄清或回退到其他系统。官方 Confidence 页面也强调阈值不是单个数字:

A confidence threshold is not one number. Different actions within the same system should be gated at different levels depending on the consequences of getting it wrong.

例如官方 pattern 示例里,查询余额可以用较低置信度就放行,但批准转账需要高置信度。按该示例的思路简化后,代码大致如下:

action = response.answers["intent"]

if action.confidence < 0.6:
    route_to_human()
elif action.choice == "check_balance":
    show_balance()
elif action.choice == "approve_transfer":
    if action.confidence > 0.85:
        approve_transfer()
    else:
        ask_user_to_confirm()

这里的 0.6 和 0.85 来自官方 confidence-routing 示例,不是适合所有业务的标准答案。官方 Confidence 页面也建议从保守阈值开始,用自己的数据测试并调整:

Start with conservative thresholds, test with your own data, and adjust as you observe results.

成本与限流提醒

上线前必须把成本和限流算进方案。官方 Models 页面给出当前 JEV 1.13.0 的官方数据:

  • 价格:每十亿 input tokens 42 美元,也就是每百万 input tokens 0.042 美元;输出 token 免费。
  • 限流:250,000 tokens/秒,以及 1,200 请求/分钟;超出会返回 429 Too Many Requests。

这些数字是官方数据,但有很强的时间性。Models 页面自己写明:

Rate limits are adjusting dynamically.

所以不要把这些当成永久 SLA。真实接入前要重新查一遍 Models 页面。以输入 token 免费输出的价格结构看,控制 state 长度和问题数量会对成本更敏感;这也回到前面“不要倒全量日志”的工程建议上。

落地检查清单

如果我要把 JEV 接进一个真实业务,会按下面清单做:

  1. 记录模型版本:官方 Models 页面说明 jev-latest 这类别名会移动,但响应的 model 字段会返回实际版本 ID。阈值是按某个版本调出来的时候,日志必须记录实际响应的模型版本。
  2. 记录用量:至少统计每次请求的输入 token 消耗,否则成本会失控。具体的 usage 字段形状以实际 API 返回为准,本稿未展开核实,但费用是按输入 token 算的。
  3. 阈值必须有回测集:不要凭感觉定 confidence 阈值;把历史数据标注后回测每个动作的错误率,再决定自动、确认、转人工三档边界。
  4. 低置信必须有人工兜底:官方 Confidence 页面把“低置信不行动”作为有用起点,我建议直接作为底线:没有兜底就不要自动执行高风险动作。
  5. 非英文内容要单独测试:官方 Models 页面说英文是主要训练语言,CJK 等语言可用但精度较低,真实接中文业务前必须用自己的中文数据回测。

这次没核实的

  • Primitives 页面详情里 Choice、Score、Noul 各自页面的更细结构,本次只读了总览,未逐页展开;特别是 Noul 的 criteria 可选结构需要后续再确认。
  • 官方 API Reference 不在本次来源正文里,所以 usage 字段的具体形状和 SDK 响应包装没有核实,不能在本稿写成确定字段。
  • 官方 Models 页提到的 64k/32k 上下文长度细节没有足够空间展开,但这两个也是官方数据,只是在本文中不展开。
  • 文中 0.6 与 0.85 是官方 pattern 示例值,不是官方推荐万能值;是否适合你的业务,需要回测。

参考来源

评论区

0 条评论

登录后可评论。

三分钟热度 28 阅读