JEV使用教程

先说结论

  • JEV 当前在 TypeSafe 平台以 model: "jev-latest" 调用,统一 POST 到 https://api.typesafe.ai/v1/systemone。
  • 三种问题类型覆盖大多数业务判断:Choice 做多选一,Score 做有序等级评分,Noul 做是非判断。
  • 最小上手路径是:Playground 手动验证 → 控制台拿 key → cURL 调用 HTTP API → Python SDK 集成。
  • 响应形状必须按类型区分:Choice 有 choice/probabilities/confidence,Score 有 score/legend/probabilities/confidence,Noul 只有 noul。
  • 三个新手坑要避开:不要把整篇文档塞进 state、不要一个问题问多件事、不要把 confidence 当真实准确率。

第一步:Playground 里先跑一个 Noul

官方 Quick start 给的第一步是打开 Playground,粘贴一段文本作为 state。官方 sample state 是:

Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP.

然后添加一个 Noul 问题。官方示例的 JSON 片段是:

"urgency": {
  "type": "noul",
  "instructions": "Does this message express urgency?"
}

这里的关键是:Noul 回答的是“是/否”问题,返回一个 0 到 1 的概率值,越接近 1 表示越像“yes”。官方 Primitives 页的表格直接写明 Noul 的 Returns 是 noul (0 to 1)。不要指望它返回 confidence 或 probabilities,这两个字段在 Noul 答案里不存在。

我的判断:如果你第一次接触 JEV,先在 Playground 里跑通 Noul,能最快建立对“state + questions”输入模式的感觉。Playground 不需要写代码,适合验证问题描述是否清楚。

第二步:拿 API key,放进环境变量

官方 Quick start 的 API 部分说从 dashboard 拿 key。官方示例在 cURL 和 Python SDK 中都用了环境变量 TYPESAFE_API_KEY,而不是把 key 写死在命令或代码里。

官方 Quick start 对 Python SDK 有一句很关键的原话:“The client reads TYPESAFE_API_KEY from the environment and calls jev-latest by default.” 也就是说,SDK 客户端默认从环境变量读取 key,并默认使用 jev-latest 模型。

所以工程上的做法是:把 key 放进 shell 配置文件或当前 shell 会话:

export TYPESAFE_API_KEY="你的 key"

这是官方示例采用的模式,不是额外安全建议。

第三步:cURL 调用 HTTP API

官方 API reference 写明评估端点是 POST https://api.typesafe.ai/v1/systemone,认证头是 Authorization: Bearer <API_KEY>,并且 request body 顶层必须包含 state、model、questions。

官方 Quick start 中的 Sample cURL command 在本次来源抓取时显示不完整,所以下面这条命令是我按照 API reference 的 request body 字段拼出的可复制版本:

curl -X POST https://api.typesafe.ai/v1/systemone 
  -H "Authorization: Bearer $TYPESAFE_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{
    "model": "jev-latest",
    "state": "Help! My payouts have been failing for 3 days.",
    "questions": {
      "is_urgent": {
        "type": "noul",
        "instructions": "Does this convey urgency?"
      }
    }
  }'

这里的字段名和示例值都可以在官方 API reference 的 Example request 中找到。官方示例请求中的 model 就是 "jev-latest",questions 是一个 map,每个 key 是你自己起的 ID,例如 is_urgent。

注意:questions 里的 key 不会发送给底层模型,它只用来在响应中匹配答案。官方 API reference 原话是:“The key is not sent to the underlying model and is not used in inference.” 所以不要试图用问题 ID 去影响模型判断,完整问题必须写在 instructions 里。

第四步:用 Python SDK 调用

官方 Client SDKs 页面列出了 Python 和 JavaScript/TypeScript 两种客户端。Python SDK 需要 Python ≥3.10,安装命令是 pip install typesafe-sdk。

官方 Quick start 给出的 Python 用法是:

from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

client = TypeSafeClient()   # 读取环境变量 TYPESAFE_API_KEY

ticket = "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP."

response = client.system_one(
    state=ticket,
    questions={
        "department": Choice(
            instructions="Which team should handle this",
            criteria={
                "billing": "Payment or subscription issues",
                "technical": "Bugs or integration problems",
                "sales": "Pricing or account questions",
            },
        ),
        "frustration": Score(
            instructions="How frustrated the customer appears",
            criteria=[
                "Calm, just stating facts",
                "Frustrated but civil",
                "Very angry, strong language",
            ],
        ),
        "is_urgent": Noul(
            instructions="The message conveys urgency or time-sensitivity",
        ),
    },
)

print(response.answers["department"].choice)   # 官方示例输出 "technical"
print(response.answers["frustration"].score)   # 官方示例输出 1.0
print(response.answers["is_urgent"].noul)      # 官方示例输出 1.0

这段代码是我根据官方 Quick start 示例整理的,只做了缩进和注释上的微调,参数名和调用方式与官方一致。可以看到三种问题类型在一次 system_one 调用里并行返回。

需要特别注意 Score 的 criteria 是有序数组:["Calm, just stating facts", "Frustrated but civil", "Very angry, strong language"]。官方 API reference 明确要求 Score 的 criteria 是 ordered array,至少两级,最多 10 级。工程上我把它理解为从低到高排列,因为 score 返回的数值索引需要映射到有序等级,这样代码里才能用索引取 legend 和 probabilities。

响应怎么读:字段形状一次说清

官方 Primitives 页给了一张很清晰的表,我把它转成更方便速查的形式:

类型 返回字段
Choice choice, probabilities, confidence
Score score, legend, probabilities, confidence
Noul noul (0 to 1)

注意:这张表的字段名来自官方 Primitives 页,不是我自己编的。你需要按字段名去读响应,不要张冠李戴。

具体到 Python SDK,可以这样读取:

# Choice
dept = response.answers["department"]
print(dept.choice)           # 选中的选项 key
print(dept.probabilities)    # 各选项概率
print(dept.confidence)       # 置信度

# Score
frust = response.answers["frustration"]
print(frust.score)           # 概率加权的连续位置(可落在两级之间,不是等级序号)
print(frust.legend)          # 等级编号 → 等级描述(对应你传入的有序 criteria)
print(frust.probabilities)   # 各等级概率
print(frust.confidence)      # 置信度

# Noul
urgent = response.answers["is_urgent"]
print(urgent.noul)           # 仅此一个字段,0~1

这里要特别提醒一个极易写错的地方:score 不是等级序号,而是按概率加权后的连续位置,可以落在两个等级之间(官方字段表对 Score 的说明就是”a position along your levels, and can fall between two of them”)。你要拿到”落在哪一档”,看的是 legend 与 probabilities:它们按等级编号索引(官方 Quick start 的响应示例里这两个字段都是形如 {"0": ..., "1": ...} 的对象,不是数组),例如某个等级编号为 1 时,对应标签取 legend["1"]、该等级的概率取 probabilities["1"]。所以正确做法是:用 score 做排序或设连续阈值,用 legend/probabilities 做分档展示与不确定度判断。

另外,官方 Quick start 示例还提到了顶层 usage 字段。官方示例给出的 input_tokens 和 output_tokens 分别是 392 和 65。这个数字来自官方 Quick start 的某一具体示例,属于官方示例值,不同请求会变化,不要当成固定开销。

三条新手坑

第一,不要把整篇文档塞进 state。官方 Primitives 页强调 System One 模型是为 fast, focused judgments 设计的,原话是:“System One models are built for fast, focused judgments.” 并且指出像“Analyze this message and determine the best course of action”这种宽泛问题不适合,它需要慢思考,应当拆成小问题再用代码组合。按这个定位,state 应该只放当前判断真正需要的文本,而不是把整个知识库或长文档全部丢进去。这是我在官方定位基础上的工程判断。

第二,不要一个问题问多件事。官方 Primitives 页专门有一节标题就叫 “Ask for one snap judgment per question”,并且建议如果一个判断依赖多个独立因素,应该分别提问再在代码里组合权重。所以不要写“请分析这条消息的情感、紧急程度和购买意向”这种复合问题,而是拆成三个问题。

第三,不要把 confidence 当准确率。官方确实在 Choice 和 Score 的答案里返回 confidence,并且有单独的 Confidence 文档页专门解释它:它是把答案的概率分布”尖锐程度”折叠成 0~1 的一个数,方便你直接设阈值;该页同时明确写着 Noul 的答案不带 confidence(原文:”Noul answers don’t carry one.”)。所以它适合用来做”自动处理还是升级给人”的分流信号,但它不是”这个答案在现实世界里正确的概率”这样的准确率承诺——要做准确率评估,得自己构造标注集并统计。

上手清单:我自己的判断

按顺序执行,基本能跑通第一个 JEV 调用:

  1. 打开 Playground,粘贴一小段文本,先加一个 Noul 问题,确认返回 noul 值在 0~1 之间。
  2. 到控制台拿 key,export TYPESAFE_API_KEY=...。
  3. 用上面 cURL 命令发一次真实 HTTP 请求,确认响应里能找到对应问题 ID。
  4. pip install typesafe-sdk,确认 Python ≥3.10。
  5. 用 SDK 一次问一个 Choice、一个 Score、一个 Noul,按类型读对应字段。
  6. 检查 Score 的 criteria 是否是有序数组;检查 Noul 是否只读了 noul。
  7. 如果结果不符合预期,先检查问题是否问得太宽,再检查 state 是否塞了太多无关内容。

这次没核实的

  • 官方 State 页的 best practices 正文没有抓取到,因此“不要把整篇文档塞进 state”主要是基于 System One 快判断定位的推断,不是官方 State 页原话。
  • 官方 Quick start 里的 Sample cURL command 在来源抓取时显示不完整,本文的 cURL 命令是按照 API reference 的字段重写的,但字段名和请求结构均来自 API reference。
  • 官方 Confidence 页面只拿到链接,没有拿到正文。所以“confidence 不是真实准确率”这条属于工程惯例,不是官方定义。
  • usage 字段的 392/65 是官方 Quick start 示例值,不是保证值,也不是所有请求的平均值。

参考来源

评论区

0 条评论

登录后可评论。

我家大橘 13 阅读