本文范围:请求格式与应用代码依据 2026-09-25 核对的 TypeSafe 官方文档。文中的工单、标注和阈值都是演示业务规则的合成示例。本页不提供模型输出、准确率、速度或费用对比;上线前请用你自己的标注数据测量。
1. 先划定分流器能做什么
这里的分流器只做两件事:选择处理队列、标记缺失信息。它不写回复、不退款、也不修改账户,这些操作应继续放在正常权限控制之后。Jev 返回类型化答案:Choice 返回选中的选项、每个选项的概率和 confidence;Noul 返回答案为“是”的概率,取值 0 到 1。有了这种结构,下面的判断就能交给代码可靠地执行。
2. 写清四个队列的边界
下表是用于说明的示例业务规则,请按你们的实际分工修改。
| 队列 | 负责 | 转交条件 |
|---|---|---|
billing | 已发生的扣款、发票、退款、付款方式、续费失败 | 客户在购买前询问价格(转 sales) |
technical | 故障、服务中断、错误提示、登录问题、集成报错 | 问题本质是一笔已经发生的扣款(转 billing) |
sales | 价格咨询、套餐比较、新购买、报价 | 客户已在付费,询问的是某笔扣款(转 billing) |
other | 合作、媒体采访、求职、一般意见 | 不自动关闭,必须有人阅读 |
把这些边界写进选项描述里。TypeSafe 的 Jev 1.13 已知局限页面指出,Jev 会按字面理解指令。看到错误答案时,如果你想解释“其实我的意思是……”,那句解释就是 criteria 里缺少的内容。一定要保留 other 这个真实选项,这样哪一类都不符合的工单不会被硬塞进最接近的队列。
3. 从请求实验室的示例开始
打开实验室里的 support-routing 示例,会载入下面这个请求。你可以修改内容,复制 JSON 或 cURL;只有真正发送时才需要自己的 API 密钥。实验室示例使用英文内容,与本站英文版一致;换成中文工单前,请先读第 6 节关于语言测试的说明。
{
"model": "jev-1.13.0",
"state": {
"message": "I was charged twice for the same subscription this month."
},
"questions": {
"decision": {
"type": "choice",
"instructions": "Which team should handle this request? Choose other if none of the specific teams fits.",
"criteria": {
"billing": "Payments, charges, invoices or refunds",
"technical": "Bugs, outages or integration errors",
"sales": "Pricing or a new purchase",
"other": "A request outside these teams"
}
}
}
}
cURL 从环境变量读取密钥,请求体通过带引号的 heredoc 传入:
curl --fail-with-body --max-time 20 https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JEV_ATLAS_REQUEST'
{
"model": "jev-1.13.0",
"state": {
"message": "I was charged twice for the same subscription this month."
},
"questions": {
"decision": {
"type": "choice",
"instructions": "Which team should handle this request? Choose other if none of the specific teams fits.",
"criteria": {
"billing": "Payments, charges, invoices or refunds",
"technical": "Bugs, outages or integration errors",
"sales": "Pricing or a new purchase",
"other": "A request outside these teams"
}
}
}
}
JEV_ATLAS_REQUEST
在生产环境中,把队列判断和缺失信息判断放在同一次请求里。两个问题会针对同一个 state 各自独立评估,一个答案不会成为另一个问题的上下文,组合逻辑由代码负责。team 和 needs_details 是你自己定义的 ID,答案会用同样的 ID 返回。
{
"model": "jev-1.13.0",
"state": {
"subject": "Charged twice this month",
"message": "I was charged twice for the same subscription this month. The invoice numbers end in 4471 and 4472.",
"channel": "email"
},
"questions": {
"team": {
"type": "choice",
"instructions": "Which team should handle this support request? Judge the customer's main request. Choose other if none of the specific teams fits.",
"criteria": {
"billing": "Existing charges, invoices, refunds, payment methods or failed payments on an existing account",
"technical": "Bugs, outages, error messages, login problems or integration failures",
"sales": "Pricing questions before purchase, plan comparisons, new purchases or quotes",
"other": "Anything outside these three teams, such as partnerships, press or general feedback"
}
},
"needs_details": {
"type": "noul",
"instructions": "Does this request lack a detail that a support agent needs before starting work, such as which account, order, product or error it is about?",
"criteria": {
"true": "At least one detail needed to start work is missing",
"false": "The request identifies what it is about well enough to start work"
}
}
}
}
4. 明确处理缺失信息
needs-clarification 示例 用一个 Noul 问:这条请求是否缺少必要信息?
{
"model": "jev-1.13.0",
"state": {
"request": "Please send it to the other address.",
"known_context": "No document or recipient address has been specified."
},
"questions": {
"decision": {
"type": "noul",
"instructions": "Does this request need additional context to identify both what should be sent and its destination?",
"criteria": {
"true": "At least one required detail is missing",
"false": "Both the item and destination are explicitly identified"
}
}
}
}
Noul 返回的是“答案为是”的概率估计,取值 0 到 1,没有 confidence。数值偏高时,不要让模型猜队列,而是针对缺少的内容向客户追问。能确定判断的事情交给代码:比如表单要求填写订单号或账户邮箱,就在调用模型之前用代码检查这个字段。
5. 阈值与人工复核由代码决定
// Node 18+ or any runtime with fetch. Example thresholds: calibrate them on your
// own labeled tickets; they are starting points, not measured values.
const ENDPOINT = 'https://api.typesafe.ai/v1/systemone';
const ROUTE_AT_CONFIDENCE = 0.8;
const ASK_AT_MISSING = 0.7;
const TEAMS = new Set(['billing', 'technical', 'sales']);
export async function classifyTicket(request, apiKey) {
const response = await fetch(ENDPOINT, {
method: 'POST',
headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
body: JSON.stringify(request),
signal: AbortSignal.timeout(20_000),
});
if (response.status === 429 || response.status === 529) {
// Back off; honor retry-after when present. Do not retry in a tight loop.
const error = new Error('typesafe_retry_later');
error.retryAfter = response.headers.get('retry-after');
throw error;
}
if (!response.ok) throw new Error(`typesafe_http_${response.status}`);
return response.json();
}
export function decideRoute(result) {
const team = result.answers.team;
const missing = result.answers.needs_details.noul;
if (missing >= ASK_AT_MISSING) return { action: 'ask_customer', reason: 'missing_details' };
if (!TEAMS.has(team.choice)) return { action: 'human_triage', reason: 'no_specific_team' };
if (team.confidence < ROUTE_AT_CONFIDENCE) {
return { action: 'human_triage', reason: 'low_confidence', suggestion: team.choice };
}
// Log the versioned model that answered, so threshold changes stay traceable.
return { action: 'route', queue: team.choice, confidence: team.confidence, model: result.model };
}
这三个阈值只是起点示例,不是推荐值。TypeSafe 建议把 confidence 划为高、中、低三段,并按风险设置不同阈值。分错队列的代价有限,自动退款这类影响更大的动作就需要更严格的门槛。用标注数据调整阈值,每次判断都记录 result.model;阈值调好后,固定使用 jev-1.13.0 这样的具体版本,因为 jev-latest 可能切换到新模型。
- 401:检查 API 密钥和 Authorization 请求头。
- 422:请求未通过校验,响应体会指出出错字段。
- 429 / 529:不要立即重发,按指数退避重试;如果响应带有 retry-after,就按它等待。
6. 先固定一小份标注集,再决定是否信任
先写下期望结果,再运行请求做对比。下表是合成工单,以及按示例规则应得的结果,并不是模型输出。
| 合成工单 | 期望队列(示例规则) | 缺信息? |
|---|---|---|
| 请退还发票 INV-2291 的费用,我在续费日前已经取消。 | billing | 否 |
| 今天早上更新后,导出按钮一直返回 500 错误。 | technical | 否 |
| 年付方案买 40 个席位有折扣吗? | sales | 否 |
| 付款页面超时了,但我的卡还是被扣款了。 | billing(规则:已发生扣款归 billing) | 是:哪一笔扣款 |
| 我能把现有套餐改成年付吗?今天会扣款吗? | billing(规则:现有客户归 billing) | 否 |
| 我想为杂志文章采访你们团队。 | other | 否 |
| 用不了。 | 暂不判断:先追问 | 是 |
| 请把它发到另一个地址。 | 暂不判断:先追问 | 是(needs-clarification 示例) |
对每条工单记录:选中的队列、confidence、Noul 数值,以及代码最终是直接分流、追问客户还是转人工。按队列统计不一致的情况并逐条阅读,通常会发现边界描述不清,或者某条规则本该由代码处理。标注集要包含你实际收到的语言:TypeSafe 模型页面(2026-09-25 核对)说明英语是主要训练语言,其他语言需要用自己的内容测试。
采用类似做法的项目
- Jev Ticket Router: 结合 Jev 与明确业务规则分配波斯语或英语客服工单。
- Triage Guard: 探索 Jev 在工单、运维告警和部署风险中的工作流。
以上条目于 2026-09-18 依据各自 README 核对来源。Jev Atlas 没有运行、测评或做安全审计。
资料来源
- TypeSafe: API reference
- TypeSafe: Choice
- TypeSafe: Noul
- TypeSafe: Confidence
- TypeSafe: Confidence-gated routing
- TypeSafe: Intent routing
- TypeSafe: Jev 1.13 jaggedness
- TypeSafe: Models
TypeSafe 文档核对日期:2026-09-25。模型、限额和价格可能变化,接入前请以官方为准。
动手试试
在实验室打开 support-routing · 打开 needs-clarification · 如何写出好判断的问题