1. Jev 是什么
Jev 是 TypeSafe 的第一个 System One 模型。它不是用来生成长文本、代码或解释的聊天模型,而是把自然语言和业务状态转换成程序可以直接消费的结构化判断。
业务状态 + 明确的问题定义 → Jev → typed answer + 概率 → JavaScript 组合规则并执行动作当前 Jev 接收文本、JSON 对象和文本数组;图片、音频、视频不在当前输入范围内。
2. 三种基础问题类型
这是三种 primitive / 判断输出类型,不是三个独立模型。
| 类型 | 要问的问题 | 主要输出 |
|---|---|---|
Choice | “它属于哪一个?” | 一个选项、完整概率分布、confidence |
Noul | “这个条件成立吗?” | “是”的概率 |
Score | “程度有多高?” | 期望分数、等级概率、confidence |
Choice:从封闭选项中选择一个
import { choice } from "@typesafe-ai/sdk";
const topic = choice("这条客户消息主要属于哪个主题?", {
quotation: "询价、报价或采购需求",
delivery: "交期、物流或出货安排",
technical: "图纸、材料、工艺或技术规格",
complaint: "质量、服务或交付投诉",
other: "以上都不符合,或信息不足"
});返回形态:
{
"type": "choice",
"choice": "delivery",
"probabilities": { "quotation": 0.03, "delivery": 0.91, "technical": 0.04, "complaint": 0.01, "other": 0.01 },
"confidence": 0.89
}Choice 的关键是先由业务方定义选项和边界。选项应尽量互斥,并保留 other 或 no-match,避免强行分类。
Noul:判断一个条件是否成立
import { noul } from "@typesafe-ai/sdk";
const isUrgent = noul(
"这条消息是否明确表达了需要尽快处理的紧迫性?",
{
true: "提到截止时间、延误后果、取消订单或要求立即处理",
false: "没有明确的时间压力或严重后果"
}
);返回:
{ "type": "noul", "noul": 0.97 }noul 是“是”的概率。Noul 没有单独的 confidence;是否自动执行由代码根据风险设阈值。
Score:沿着有序等级打分
import { score } from "@typesafe-ai/sdk";
const frustration = score("客户的不满程度如何?", [
"平静地陈述事实,没有明显不满",
"有轻微不满或抱怨,但仍然合作",
"明显不满,质疑服务或要求升级处理",
"强烈不满,威胁取消订单、投诉或终止合作"
]);Score 的 criteria 必须是从 0 开始的有序数组。返回的 score 可以是小数:
{
"type": "score",
"score": 2.76,
"confidence": 0.91,
"probabilities": { "0": 0.01, "1": 0.04, "2": 0.12, "3": 0.83 }
}3. 一次请求可以问多个问题
同一个 state 上彼此独立的问题可以批量请求:
import { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient();
const response = await client.systemOne({
model: "jev-latest",
state: {
message: "客户说模具已经延误两周,如果本周还不能出货就要取消订单。",
customer: { country: "Germany", previous_orders: 2 }
},
questions: {
topic: choice("这条消息主要属于哪个主题?", {
quotation: "询价或采购需求",
delivery: "交期、物流或出货",
technical: "技术规格或图纸",
other: "其他或信息不足"
}),
isUrgent: noul("这条消息是否表达了紧迫性?", {
true: "有明确期限、延误后果或要求立即处理",
false: "没有明确时间压力"
}),
frustration: score("客户的不满程度如何?", [
"平静", "轻微不满", "明显不满,需要优先跟进", "强烈不满或威胁取消订单"
])
}
});一次请求里的问题不能看到彼此的答案。如果后一个问题依赖前一个问题的结果,就分成两次调用:第一次判断意图,代码检索资料,第二次把新增资料放入 state 再判断。
4. Jev 和普通代码的边界
Jev 负责理解自然语言、在定义好的选项中选择、判断条件概率、沿等级评分,并返回概率和 confidence。代码负责阈值、业务政策、组合判断、数据库/队列/通知和人工升级。
function route({ topic, isUrgent, quoteReady, frustration, churnRisk }) {
if (churnRisk.noul >= 0.8 || frustration.score >= 2.5) return "urgent_sales";
if (quoteReady.noul < 0.6) return "need_more_info";
if (topic.choice === "technical") return "technical_review";
return isUrgent.noul >= 0.8 ? "priority_sales" : "normal_sales";
}不要让 Jev 直接决定不可逆动作。Jev 输出语义信号,最终动作应由可测试、可审计的程序规则决定。
5. 真实例子:外贸询盘分诊
输入客户邮件、客户资料和产品报价所需字段:
{
"message": "We need 500 aluminum die casting parts. Please quote FOB Ningbo. The tooling has already been delayed for two weeks, and we may cancel if it cannot ship this week.",
"customer": { "country": "Germany", "previous_orders": 2 },
"required_fields": ["quantity", "material", "drawing", "surface_finish", "delivery_date", "incoterm"]
}同时问:
Choice:主要意图是报价、样品、技术确认、交期还是投诉?
Noul:是否已经有足够信息开始报价?
Noul:是否存在取消订单或流失风险?
Score:客户不满程度是 0~3 的哪一级?程序再做路由:高风险进入紧急销售队列;资料不足进入补充信息队列;技术意图进入技术评审;其余进入普通销售队列。
这个例子体现的不是“Jev 会读邮件”,而是:一封自然语言输入可以被拆成多个独立、可复用、带概率的语义信号,然后接入普通软件流程。
6. 问题设计是核心工作
业务方需要定义:
- 真正要判断什么
- 答案集合是什么
- 每个答案的边界是什么
- 不确定或不匹配时怎么办
- 每个结果怎样影响程序动作
好的问题应当窄、独立、可复用。不要把主题、紧急性、客户情绪揉成一个模糊问题;拆开后,代码才能单独调整阈值和组合方式。
不需要一开始设计完美,先用真实询盘跑通闭环:
真实询盘 → Jev 判断 → 程序路由 → 人工确认 → 对比结果 → 修改问题或阈值建议保留原始记录:
{
"message": "原始询盘",
"questions": "当时使用的问题定义",
"answers": "Jev 原始答案",
"final_route": "程序最终路由",
"human_result": "人工确认结果"
}7. 当前最小实验台
本次创建的本地实验台使用 Node.js 20.6+ 和 JavaScript SDK:
npm install
npm start根目录 .env:
TYPESAFE_API_KEY=<TYPESAFE_API_KEY>页面会展示实际问题、候选定义、答案、概率分布、confidence 和 token 用量。API key 只在 Node 服务端读取,不进入浏览器。
8. 一句话总结
我定义清晰的判断空间,Jev 把自然语言映射到这个空间,代码再把多个判断组合成可执行的业务流程。