本頁內容

難度
中階
所需時間
約 30–60 分鐘(含練習與自行驗證)
你需要準備
TypeSafe 官方文件 · Node.js 20+ · 可用的 TypeSafe API 帳戶(執行呼叫時需要)
開始之前
- 能閱讀 JSON 與基本流程規則
- 先用教學或去識別資料,保留人手回退
Jev 的直接 HTTP 入口是 POST https://api.typesafe.ai/v1/systemone。請求的三個核心欄位是 model、state、questions;回應則按你的問題 ID 放在 answers。本篇用 JavaScript 原生 fetch 示範,避免把 Jev 當作 chat completion API。
資料核對:2026 年 9 月 21 日。本文依官方文件研究;原創情境、門檻及計算例子均有標明。本站未以 Jev API 執行性能或廣東話準確率測試。模型、價格與 early access 狀態可能更新。
準備環境與 API key
你需要可使用 TypeSafe API 的帳戶,以及 Node.js 20 或以上。本篇示例只在本機或伺服器執行。用終端機的環境變數或部署平台的 secret manager 提供 TYPESAFE_API_KEY;不要加上 NEXT_PUBLIC_ 前綴,不要寫入前端程式或提交到 Git。尚未取得 early access 時,可先完成 request 結構及本地測試,但不能聲稱已成功呼叫模型。
先建立 jev-client.mjs 放下方 evaluate 函式,再建立 run-jev.mjs 放請求與呼叫程式。若偏好官方 SDK,可使用 @typesafe-ai/sdk;截至核對日文件的方法名為 client.systemOne(...)。本文採用直接 HTTP,方便看清楚實際傳送內容。
核對來源:JavaScript SDK、TypeSafe quickstart。

第一個 request:用 Choice 分類,用 Noul 判斷明確退款要求
export const request = {
"model": "jev-1.13.0",
"state": {
"ticket": "我唔係要退款,想查下點解同一張單扣咗兩次錢。"
},
"questions": {
"category": {
"type": "choice",
"instructions": "Classify the main support need in state.ticket. Classify the issue, not an action to execute.",
"criteria": {
"billing": "Charges, invoices, duplicate payments or refund enquiries.",
"technical": "Login or software faults.",
"delivery": "Shipping, delivery or missing goods.",
"other": "Unclear or outside these categories."
}
},
"refund_requested": {
"type": "noul",
"instructions": "Does the customer explicitly request a refund now? A denial of wanting a refund is no. A duplicate-charge enquiry alone is not a refund request."
}
}
};
這個例子刻意使用「唔係要退款」的否定句,並在 instructions 寫清楚,查重複扣款不必然代表要求退款。英文 instructions 只是本篇設計選擇,並沒有證據證明這樣一定比中文好;真正上線前應固定測試集比較。問題 ID category 只用於映射答案,不能代替 instructions 裏的完整語意。
核對來源:TypeSafe HTTP API reference、Jev 1.13 jaggedness — 已知能力弱點。
發送請求:處理錯誤和有限次重試
// Node.js 20+;在伺服器或本機執行,API key 由環境提供。
import { setTimeout as sleep } from 'node:timers/promises';
export async function evaluate(request, apiKey, fetcher = fetch) {
if (!apiKey) throw new Error('Missing TYPESAFE_API_KEY');
for (let attempt = 0; attempt < 3; attempt++) {
const res = await fetcher('https://api.typesafe.ai/v1/systemone', {
method: 'POST',
headers: { Authorization: 'Bearer ' + apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify(request),
signal: AbortSignal.timeout(15000),
});
if (res.ok) {
const data = await res.json();
if (!data.model || !data.answers || !data.usage) throw new Error('Unexpected response');
return data;
}
if (![429, 529].includes(res.status) || attempt === 2) {
throw new Error('TypeSafe HTTP ' + res.status);
}
const retryAfter = res.headers.get('retry-after');
let waitMs = 500 * 2 ** attempt + Math.random() * 250;
if (retryAfter) {
const seconds = Number(retryAfter);
const parsed = Number.isFinite(seconds)
? seconds * 1000 : Date.parse(retryAfter) - Date.now();
if (Number.isFinite(parsed)) waitMs = Math.max(waitMs, parsed, 0);
}
// 長等待交回工作佇列,避免一直佔住請求。
if (waitMs > 30000) throw new Error('Retry later through the job queue');
await sleep(waitMs);
}
}
程式只對文件列出的 429、529 作最多三次請求,並尊重可解析的 Retry-After。15 秒 timeout 與 30 秒等待上限是本篇的示例設定,不是 TypeSafe SLA;應配合你的工作佇列調整。網絡中斷、timeout、無法解析 JSON 或缺欄位會拋出例外,讓呼叫端保留人工處理,不能默默視為否定答案。
import { evaluate } from './jev-client.mjs';
// request 使用上方完整物件。
try {
const result = await evaluate(request, process.env.TYPESAFE_API_KEY);
const answer = result.answers.category;
const allowed = Object.keys(request.questions.category.criteria);
if (answer?.type !== 'choice' || !allowed.includes(answer.choice)) {
throw new Error('Invalid category answer');
}
console.log({ model: result.model, category: answer.choice, usage: result.usage });
} catch (error) {
console.error(error.message);
process.exitCode = 1; // 真正系統在此留下待覆核工單。
}
以上是分開展示的程式片段:把 request 宣告與呼叫段放進同一個 run-jev.mjs,然後執行 node run-jev.mjs。不要把終端輸出中的類別當作已授權操作。正式版還應按完整 schema 驗證每題、機率範圍及分佈,再把資料送入業務規則。
如何讀回應,避免自己加出不存在的欄位
| 位置 | 用途 | 常見錯誤 |
|---|---|---|
| model | 記錄實際回答的版本 | 只保存 jev-latest,之後無法重現。 |
| answers.category.choice | 這題選中的類別 | 把其他欄位或自由文字當成 choice。 |
| answers.category.probabilities | 每個候選選項的機率 | 只讀最大值,忽略第二選項接近。 |
| answers.category.confidence | 由分佈導出的信心統計 | 當作相同數值的真實準確率。 |
| answers.refund_requested.noul | 「有明確退款要求」的機率值 | 讀取不存在的 noul.confidence。 |
| usage | 記錄 token 用量 | 看到 output_tokens 就以為必然按輸出收費。 |
本篇不提供偽造的「實際成功回應」數字。你應以自己的 API 回應查看欄位,再在測試資料中核對意圖是否正確。輸出 token 仍可能出現在 usage 裏,而現行模型卡的輸出價格是免費;用量紀錄與計費規則是兩件事。
核對來源:TypeSafe HTTP API reference、Models — Jev 1.13、定價與限制。

401、422、429、529 應分開處理
| 狀態 | 先檢查 | 不應怎樣做 |
|---|---|---|
| 401 | key 是否存在、有效及放在 Bearer header | 無限重試同一把無效 key。 |
| 422 | state、model、questions,以及每種題目的 criteria | 把格式錯誤當作模型認為「其他」。 |
| 429 | 速率與並行工作量、Retry-After | 同時啟動更多工作搶重試。 |
| 529 | 供應端暫時過載、延後工作與回退 | 阻塞整條客服流程直到成功。 |
核對來源:TypeSafe HTTP API reference。
批次大小與版本:不要只看「64k context」
現行文件有兩個同時適用的預算:state 加所有 questions 合計最多 64k tokens;state 加最長單題最多 32k tokens。Choice 最多 255 個選項,Score 應有至少兩級、API 接受最多十級。超過限制應重新切分工作,不是把錯誤吞掉。
上線前固定模型 ID、instructions 及 criteria;更改任何一項都應視作新版本。你不需要把大量歷史訊息全部塞入 state;較短而相關的上下文通常更容易檢查,實際準確性仍以自己的測試為準。
核對來源:Models — Jev 1.13、定價與限制、TypeSafe HTTP API reference。
下一步閱讀
資料來源與引用
我們附上第一手及官方來源,方便你逐一核實。
常見問題
Jev API endpoint 是甚麼?
POST https://api.typesafe.ai/v1/systemone,使用 Authorization: Bearer API_KEY,body 包含 model、state 及 questions。
Noul 為甚麼沒有 confidence?
API 的 Noul answer 只有 type 和 noul;不要假設它與 Choice/Score 的欄位完全相同。
示例已在 Jev 上跑過嗎?
沒有。本篇按官方 API 編寫並做本地程式檢查;沒有把模擬回應或算術例子稱作 Jev 實測。
本文遵循我們的 編輯準則.

關於作者
HK Learn AI 編輯部
HK Learn AI 編輯部負責研究、查證同編寫每一篇內容,並引用官方及第一手來源。
此主題相關文章

Jev Choice、Score、Noul 教學:選項、評級與是非機率點樣設計
以客服和故障評級例子拆解 Choice、Score、Noul:選項覆蓋、rubric、加權分數、否定句與批次獨立性,避免輸出可解析卻語意錯誤。

Claude Code GitHub Actions 教學:@claude 修 issue、PR 自動審查,訂閱 token 定 API key 點揀
按 Anthropic 現行官方文件(2026 年 9 月 15 日核對)設定 Claude Code GitHub Actions:用 /install-github-app 快速設定,或手動安裝 Claude GitHub App、加 Secret、放 workflow,再留言 @claude 改 code 及開 PR 自動審查。另有訂閱 token 與 API key 之選、成本、安全設定同排錯。文首附支援地區狀態。

Claude Code MCP 教學:連接 GitHub、資料庫同 Notion,scope、權限同安全設定
按 Anthropic 現行官方文件(2026 年 9 月 15 日核對)一步步設定 Claude Code MCP:加第一個免登入 server、分清 HTTP/stdio 同 -- 分隔符、揀 local/project/user scope,再連接 GitHub(唯讀網址)、DBHub 資料庫(唯讀帳戶)同 Notion,最後講 mcp__ 權限規則、安全清單、context 用量同常見錯誤。文首附支援地區狀態。