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 调用:
- 打开 Playground,粘贴一小段文本,先加一个 Noul 问题,确认返回
noul值在 0~1 之间。 - 到控制台拿 key,
export TYPESAFE_API_KEY=...。 - 用上面 cURL 命令发一次真实 HTTP 请求,确认响应里能找到对应问题 ID。
pip install typesafe-sdk,确认 Python ≥3.10。- 用 SDK 一次问一个 Choice、一个 Score、一个 Noul,按类型读对应字段。
- 检查 Score 的
criteria是否是有序数组;检查 Noul 是否只读了noul。 - 如果结果不符合预期,先检查问题是否问得太宽,再检查 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 示例值,不是保证值,也不是所有请求的平均值。
参考来源
评论区
登录后可评论。