20分钟跑通 Jev:从 Playground 到首个 /v1/systemone 调用
先说结论
- Jev 是 TypeSafe 的旗舰模型,定位不是“生成文本”,而是“对 state 做结构化判断”,它接收 state 和一组问题,直接返回 typed answers。
- 最小可跑路径一共四步:打开 Playground 看一次判断 → 在控制台拿 API key → 用 cURL 调一次 HTTP API → 用 Python SDK 调一次。
- API 端点是
POST https://api.typesafe.ai/v1/systemone,请求体核心字段是state、model、questions,其中model当前写"jev-latest"。 questions只有三种 primitive:Noul、Choice、Score,可以在一次调用里混用,每个问题独立评估,返回值形状不同。- 响应里
answers是每个问题 ID 对应的结果,choice返回选项 +confidence+probabilities,score返回分数 +legend+confidence+probabilities,noul只返回一个 0~1 的noul值(没有 confidence);顶层还有usage.input_tokens和usage.output_tokens。
证据与过程
1. 先在 Playground 免费试一次,不需要写代码
最直接的入口是官方控制台的 Playground:https://console.typesafe.ai/playground。按照官方 Quick start 的建议,第一步就是打开它并登录。
你可以把任意一段文本当作 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 问题,例如:"Does this message express urgency?"。Noul 是 yes/no 判断,返回一个 0 到 1 的数值,数值接近 1 表示“是”的概率更高。在 Playground 里,你可以马上看到结果。这是理解 Jev 工作方式的最快路径:你不是让模型写一段分析,而是让它对一个明确问题给出可被代码消费的判断。
这一步的官方来源是 TypeSafe 的 Quick start 页面。它强调可以先从 Playground 试 Noul,再混合 Choice 和 Score 一起看结果。这个混合能力是 Jev 的重要特点:一次调用可以同时获得多个不同类型的判断。
2. 拿 API key:去官方控制台,别把 key 写死
要从本地调 API,需要 key。官方控制台的 key 管理页是 https://console.typesafe.ai/keys,这是 TypeSafe 自己提供的控制台页面。
登录后生成 API key。强烈建议把它放进环境变量里,比如 TYPESAFE_API_KEY。这样你在 cURL 和 Python SDK 里都可以直接引用环境变量,避免把 key 明文写进脚本或仓库。Quick start 的示例 cURL 命令里写的是 $TYPESAFE_API_KEY,那是一个环境变量引用,不是让你把字面量 $TYPESAFE_API_KEY 填进去。新手容易在这里犯迷糊,所以我们明确说明:先在终端执行 export TYPESAFE_API_KEY=你的真实key,再运行后续命令。
3. 用 cURL 调一次 HTTP API
官方 API Reference 给出的评估端点是:
POST https://api.typesafe.ai/v1/systemone
Authorization: Bearer <API_KEY>
Content-Type: application/json
请求体是一个 JSON 对象,三个核心字段:state 是待评估内容;model 必须写 "jev-latest";questions 是一个映射,键是你自己起的 ID,值是一个 typed question 对象。
下面是一个可直接复制的 cURL 示例。注意,$TYPESAFE_API_KEY 是环境变量,不要直接替换成字面量:
curl -X POST https://api.typesafe.ai/v1/systemone
-H "Authorization: Bearer $TYPESAFE_API_KEY"
-H "Content-Type: application/json"
-d '{
"state": "Help! My payouts have been failing for 3 days.",
"model": "jev-latest",
"questions": {
"is_urgent": {
"type": "noul",
"instructions": "Does this convey urgency?"
},
"department": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "Payments, invoicing, refunds",
"technical": "Bugs, outages, integrations",
"sales": "Pricing, upgrades, new accounts"
}
},
"frustration": {
"type": "score",
"instructions": "How frustrated does the customer appear?",
"criteria": [
"Calm, just stating facts",
"Frustrated but civil",
"Very angry, strong language"
]
}
}
}'
这个示例同时展示了三种 primitive 的混用:noul、choice、score。根据官方 Primitives 文档,每种类型对应不同的返回结构。choice 需要 criteria 是映射,键是选项,值是该选项的描述;score 的 criteria 是一个有序数组,代表从低到高的等级;noul 的 criteria 是可选的,用来补充说明 yes/no 的边界。
4. 用 Python SDK 调一次
官方提供了 Python SDK。安装条件是 Python 版本大于等于 3.10。可以用 pip 安装:
pip install typesafe-sdk
也可以使用 uv:
uv add typesafe-sdk
SDK 的使用方式比直接拼 HTTP 请求更顺手。官方 Quick start 里的最小代码如下:
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
client = TypeSafeClient()
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
几个关键点:TypeSafeClient() 默认从环境变量 TYPESAFE_API_KEY 读取 API key,不需要显式传入;默认调用的模型就是 jev-latest;client.system_one 接收 state 和 questions,返回一个结构化响应对象。三个问题 ID 是自定义的,回答也会按同样的 ID 返回。官方 Quick start 里的注释输出值是文档示例,不代表你运行时会得到完全相同的结果,但结构是固定的。
5. 一次真实响应的结构:别只关心那个值
调用结束后,很多人只打印一个 response.answers["xxx"].choice 就结束了。但理解完整响应结构能帮你写出更可靠的业务逻辑。根据官方 API Reference,响应顶层的 answers 是一个映射,每个问题 ID 对应一个 answer 对象。answer 对象里有 type,以及根据类型不同而不同的字段:
- Noul 返回
noul,是一个 0 到 1 的数值,表示 yes 的概率; - Choice 返回
choice,是选中的选项字符串,同时还有probabilities,给出所有选项的概率分布; - Score 返回
score,是概率加权后的评分,同时还有legend,对应你定义的有序等级,以及probabilities,表示各个等级的概率分布。
除了具体的值,Choice 和 Score 还会返回 confidence。这个 confidence 是模型对自己判断的置信度,用于判断是否要相信这个答案,但它不是“准确率”。官方在 Introduction 里也强调,Choice 和 Score 除了返回对应值,还返回 confidence,你的代码可以用它来决定是否继续往下走、是否转人工、是否忽略结果。
顶层还有 usage 字段。官方 Quick start 文档给出的响应示例中,usage.input_tokens 为 392,usage.output_tokens 为 65(API Reference 只定义了这两个字段的类型,没有具体数值)。这是官方文档示例值(官方数据),不是你的账号额度,也不是任何计费承诺。实际调用的 token 数量取决于你的 state 长度和 questions 复杂度。
下面是官方 Quick start 文档里原样给出的响应示例(不是我自己编的形状,逐字段照抄,其中 legend 与 probabilities 在 score 里都是按等级索引的对象,不是数组;noul 类型只返回 noul 值,没有 confidence 字段):
{
"model": "jev-1.13.0",
"answers": {
"department": {
"type": "choice",
"choice": "technical",
"confidence": 0.78,
"probabilities": {
"technical": 0.85,
"sales": 0.0,
"billing": 0.15
}
},
"frustration": {
"type": "score",
"score": 1.0,
"confidence": 1.0,
"legend": {
"0": "Calm, just stating facts",
"1": "Frustrated but civil",
"2": "Very angry, strong language"
},
"probabilities": {
"0": 0.0,
"1": 1.0,
"2": 0.0
}
},
"is_urgent": {
"type": "noul",
"noul": 1.0
}
},
"usage": {
"input_tokens": 392,
"output_tokens": 65
}
}
上面这段就是官方文档示例的原文结构(usage 里的 392 / 65 也是官方示例值,属于官方数据);你自己跑出来的概率分布和 token 数都会不同。要注意的是:noul 只回 noul 一个值,confidence 只出现在 choice 和 score 上——如果你在代码里对 noul 读 confidence,会拿到 undefined。
自己的判断与新手清单
我跑完官方 Quick start 后,最明显的感受是:Jev 的价值不在于“输出一段聪明的话”,而在于把模糊的自然语言判断变成可编程、可路由、可组合的决策原语。对于中文圈的开发者,最容易犯的不是 API 调用错误,而是思维还停留在“写个好 prompt 让大模型分析”。下面是三个我自己观察到、或者从文档推断出的新手坑,带有自己的判断色彩。
坑 1:把大段上下文直接塞进 state。
state 可以是字符串、对象或数组,但不代表你应该把整个工单系统日志、五个会话记录和客户资料全倒进去。官方文档提到的是“当前状态”或“结构化数据”,并且强调每个问题都是一次快判断。我的判断是:先做粗筛或抽取,再把与问题相关的最小上下文放进去。如果 state 太长,token 消耗会上升,判断质量也可能因为噪声而下降。这个观点来自我对文档原则的推断,不是官方给出的严格阈值。
坑 2:一个问题里塞多个判断。
比如 "Analyze this message and determine the best course of action",这不是 Jev 适合的问题。官方 Primitives 页面明确说:如果一个判断依赖多个独立因素,就分解成多个问题,分别评估,再用自己的代码组合。官方 Introduction 给出的示例是:不要问“rate this startup pitch”,而是分别问市场规模、技术可行性、差异化,然后在代码里加权。我自己的清单是:每个问题只问一个可回答是/否、选一个、打一个分的判断;一旦你发现 instructions 里出现“并且”“同时”“然后”,就该拆开。
坑 3:拿 confidence 当准确率。
这是最容易导致业务事故的误解。confidence 表示模型对当前判断的置信度,不代表该判断在实际业务中的准确率。官方文档把它定位为“你的代码用来决定是否行动或转人工”的架构信号,而不是“准确率 90% 就一定能自动处理”。我的清单:把 confidence 作为一个阈值开关,低于某值就人工复核;不要把它当成模型能力的评估指标,更不能拿它直接向业务方承诺准确率。
这次没核实的
- 未能核实 TypeSafe 的计费方式、免费额度以及速率限制。官方 Quick start 和 API Reference 未提供完整计费细节。
- 未能核实 Playground 登录后是否需要额外配置或邀请码。官方文档仅说“log in”,没有描述账号体系细节。
- 未能核实
usage示例值 392/65 是否对应最新 jev-latest 模型在某个具体输入下的实际统计。该数字来自官方 Quick start 的响应示例,标注为官方数据,但未验证其上下文。 - 未能核实 Python SDK 的全部异常行为和错误码处理方式。官方文档只覆盖了正常调用路径。
参考来源
评论区
登录后可评论。