Jev 是 TypeSafe AI 推出的模型,用来做分类、打分和判断。比如,读一条客服消息,判断用户是不是要求退款,再把结果交给程序处理。它不负责写客服回复,返回的是选项、分数或概率。
TypeSafe 把这类模型称为 System One Model。这里先用退款消息试着理解它:程序已经有退款咨询、故障排查等流程,需要根据用户说的话,决定接下来走哪个流程。官方介绍
用语义判断代替关键词匹配
假设一个客服系统收到消息:
这个东西用不了,我也不想再折腾了,把钱退给我吧。
程序需要知道“用户是否正在要求退款”,才能决定是否进入退款咨询流程。最直接的办法是匹配关键词:
message = "这个东西用不了,我也不想再折腾了,把钱退给我吧。"
wants_refund = "退款" in message
print(wants_refund) # False用户说的是“把钱退给我”,没有出现“退款”两个字,所以这段代码漏判了。反过来,“我暂时不退款,先帮我修一下”包含关键词,却不应该进入退款流程。不断补充关键词和排除规则,很容易变成对各种表达的追赶。
Jev 可以根据语义回答“用户是否明确要求退款”,把判断结果交回代码。程序再根据结果分支:确定是在申请退款,就进入退款咨询;确定没有这个意图,就继续处理原问题;意思不清楚,就请用户补充说明。这就是官方所说的“智能 if 判断”的一种用法。官方应用场景
这里的分工很具体:模型理解用户表达,业务代码决定接下来执行什么。订单是否存在、是否已支付、是否超过退款期限,通常可以查询数据后按规则处理。识别出退款意图,也不代表用户已经满足退款条件。
普通聊天模型同样能识别意图,也能通过结构化输出返回分类结果。Jev 的特点是专门围绕这类判断设计接口,直接提供有限选项、评分和概率。它当前不生成自由文本,因此需要解释退款政策、撰写回复时,可以继续交给聊天模型。
| 当前要完成的工作 | 可以怎样处理 |
|---|---|
| 查询订单是否存在、计算距下单已经过了几天 | 数据库查询和普通代码 |
| 理解“把钱退给我”是否表达了退款意图 | Jev,或能完成分类的聊天模型 |
| 根据退款政策组织一段自然、清楚的回复 | 能生成文本的聊天模型 |
Jev 的设计目标包括降低这类判断的延迟和成本。是否值得引入,要看实际任务:如果已有模型一次调用就能完成分类和回复,再增加一道 Jev 调用也可能增加耗时;如果大量请求只需要分类后进入固定流程,专门的判断模型就更值得比较。官方性能数据有其测试条件,不能直接推算成整个应用的提速比例。官方产品说明与评测条件
请求里传什么
调用 Jev 时,state 放待判断的内容,questions 放需要它回答的问题,model 指定模型。下面是一份识别退款意图的请求体:
{
"model": "jev-latest",
"state": "这个东西用不了,我也不想再折腾了,把钱退给我吧。",
"questions": {
"wants_refund": {
"type": "noul",
"instructions": "用户是否明确要求退款?仅询问退款政策不算申请退款。"
}
}
}state 提供本次判断的依据。这里一条消息已经够用;如果用户只说“那就按刚才说的办”,单看这句话就无法知道其意图,需要提供相关的前文。
questions 里每个问题都有一个名字,这里叫 wants_refund,用于在返回结果中找到对应答案。问题真正的含义写在 instructions 中;不能只起一个 wants_refund 的名字,就期待模型知道判断标准。type: "noul" 则告诉接口,这是一道“是不是”的题。请求结构
三种问题类型
这里用到三种文本判断类型:Noul、Choice 和 Score,分别适合判断是非、选择分类和按等级评分。它们已经够用来处理这份客服消息。
| 类型 | 用来问什么 | 客服场景中的例子 |
|---|---|---|
| Choice | 从预先定义的选项中选一个 | 这条消息属于支付问题、物流问题,还是产品使用问题? |
| Score | 按预先描述的等级评分 | 用户的情绪有多强烈?从平静、不满到非常愤怒。 |
| Noul | 判断一个问题的答案是否为“是” | 用户是否明确要求退款? |
Noul:判断是不是
前面的退款问题使用 Noul。返回结果中与问题有关的部分如下,数值是示意:
{
"answers": {
"wants_refund": {
"type": "noul",
"noul": 0.97
}
}
}0.97 表示模型估计“用户明确要求退款”为真的概率是 97%。接近 1 时倾向“是”,接近 0 时倾向“否”,接近 0.5 时两种答案相近。Noul 没有另一个独立的 confidence 字段。
不要把这个值理解成“退款意愿强度”:0.5 不表示用户只想退一半的钱,也不直接表示他有一半程度的不满。它描述的是模型对这一命题的判断。像“这东西让我挺失望的”这样的表达,可能需要追问用户想要维修、换货还是退款。Noul 的含义
Choice:从选项里选一个
如果想知道消息应交给哪个团队,可以用 Choice。把下面的问题对象放进请求的 questions:
{
"department": {
"type": "choice",
"instructions": "这条消息应优先交给哪个团队处理?",
"criteria": {
"after_sales": "退货、退款申请、换货等售后诉求",
"technical": "希望获得产品使用或故障排查帮助",
"shipping": "查询物流进度、配送延迟或包裹丢失",
"other": "其他情况,或信息不足以判断"
}
}
}criteria 定义允许选择的选项,每个选项都有业务含义。返回的 choice 是选中的选项,probabilities 给出各选项的概率。例如,下面是假设的一组概率:
{
"after_sales": 0.88,
"technical": 0.08,
"shipping": 0.01,
"other": 0.03
}此时 choice 会是 after_sales。模型依然认为技术支持有一定可能性,因为用户也提到“东西用不了”。如果公司规定“只要明确要求退款,就优先交给售后”,应该把这个规则补进问题或选项说明,让模型知道业务边界。
Choice 是从选项中选一个。需要同时判断“是否有故障”和“是否要求退款”时,可以问两道 Noul,保留两个结果。也可以给 Choice 增加 other,避免把所有消息都硬塞进并不合适的部门。Choice 文档
Score:按定义的等级评分
如果关心用户的不满程度,可以用 Score。先把每个等级对应的表现写出来:
{
"frustration": {
"type": "score",
"instructions": "仅根据消息措辞,评价用户表达出的不满程度。",
"criteria": [
"语气平静,主要在陈述问题,没有明显抱怨",
"明确表达失望、不耐烦或抱怨,但语气仍然克制",
"表达强烈愤怒,出现辱骂或强烈指责"
]
}
}这里的等级按数组顺序从 0 开始编号,所以分数范围是 0 到 2。如果返回 1.2,可以理解为落在“不满但克制”和“强烈愤怒”之间,更靠近前者。这个数值可以有小数,不能按“满分 100 分”去解读。
Score 还会返回每个等级的概率和等级说明。分数是等级编号按概率加权后的结果。例如,等级 0、1、2 的概率分别为 0.1、0.6、0.3,分数就是 0 × 0.1 + 1 × 0.6 + 2 × 0.3 = 1.2。分数的意义来自你定义的等级;只写“低、中、高”,往往不如描述具体表现清楚。Score 文档
confidence 和答案概率的区别
Choice 和 Score 都有 confidence。它概括的是概率集中程度:一个选项明显领先时高,几个选项差不多时低。它不是所选答案的概率,confidence = 0.9 也不表示这次判断有 90% 的正确率。置信度说明
这一区别影响程序怎么处理结果:Choice 可能已经选出了一个部门,但如果几个部门的概率很接近,程序仍可以转人工分流;Score 得到一个中间分数,也可能是模型在不同等级之间犹豫。输出格式可靠,不保证语义判断正确。 即使返回的选项一定在允许范围内,也仍可能选错。
在 Playground 里试几条消息
不接代码时,可以先用官方 Playground:
- 打开 TypeSafe Playground,登录并按页面提示获取访问权限。
- 把上面的客服消息填入
state,添加一个 Noul 问题:“用户是否明确要求退款?” - 在问题说明中补上“仅询问退款政策不算申请退款”,运行后查看返回的
noul值。 - 保持问题不变,换几条消息再运行,观察结果是否符合预期。
可以从下面这组消息开始。表中是按照本例定义应识别出的含义,不是模型实测结果:
| 消息 | 应区分出的含义 |
|---|---|
| 这个东西用不了,把钱退给我吧。 | 明确要求退款 |
| 我暂时不退款,先帮我修一下。 | 明确否定退款意图 |
| 如果不好用,可以退款吗? | 询问政策,没有提出当前退款申请 |
| 上周申请的退款,怎么还没到账? | 查询已有退款的进度,需要与新的申请区分 |
| 太失望了,真的不想再折腾。 | 表达不满,具体诉求仍不明确 |
第四条尤其适合用来检查问题定义:你的系统是否把“查询退款进度”也算退款意图?如果只是决定进入售后流程,可以合并;如果要创建新的退款申请,就必须区分。模型的回答能否满足需求,取决于这道题有没有问到真正需要判断的事情。
用 Python 接入退款意图判断
这里使用官方 SDK,需要 Python 3.10 或以上,以及具有调用权限的 API Key。在示例目录创建环境并安装:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install "typesafe-sdk==0.7.5"将下面代码保存为 jev_refund_demo.py。运行时通过隐藏输入读取 API Key,再放入当前进程的环境变量,SDK 会自动读取 TYPESAFE_API_KEY。官方 Quick Start
import os
from getpass import getpass
from typesafe_sdk import Noul, TypeSafeClient
def choose_next_step(probability: float) -> str:
# 演示阈值,实际项目需要用自己的样例调整。
if probability >= 0.9:
return "进入退款咨询流程,继续核对订单和退款条件"
if probability <= 0.1:
return "继续处理原问题,不创建退款申请"
return "请用户澄清:您希望申请退款,还是继续排查问题?"
if __name__ == "__main__":
if not os.environ.get("TYPESAFE_API_KEY"):
os.environ["TYPESAFE_API_KEY"] = getpass("TypeSafe API Key: ")
message = input("请输入客服消息:").strip()
if not message:
raise SystemExit("消息不能为空")
with TypeSafeClient() as client:
response = client.system_one(
model="jev-latest",
state=message,
questions={
"wants_refund": Noul(
instructions=(
"用户是否明确提出当前的退款申请?"
"仅询问退款政策、查询已有退款进度,"
"或明确表示暂不退款,都不算。"
)
)
},
)
probability = response.answers["wants_refund"].noul
print(f"退款申请概率:{probability:.3f}")
print(f"下一步:{choose_next_step(probability)}")在同一终端执行:
python jev_refund_demo.py输入 API Key 和客服消息后,程序会调用 Jev,再打印概率和下一步建议。如果实际返回 0.97,代码就会输出:
退款申请概率:0.970
下一步:进入退款咨询流程,继续核对订单和退款条件这段程序里,client.system_one() 发出请求;response.answers["wants_refund"].noul 取出这道题的结果;choose_next_step() 决定如何处理。示例只打印下一步建议,没有执行退款操作。jev-latest 是模型别名;后续要做可重复的效果对比时,应记录实际返回的模型版本。
这里刻意保留了三个分支:概率接近 1,按“是”处理;接近 0,按“否”处理;中间留给澄清。对 Noul 来说,很低的值可以表示模型很确定答案为“否”,不能把所有低值都当成“不确定”。0.9 和 0.1 只是演示阈值,需要根据误判代价和实际样例调整。
调用失败时也没有概率可以使用。如果报错,应根据错误信息检查凭据、访问权限、请求参数或网络。接入真实业务后,需要给 API 失败单独安排重试、提示或人工处理路径,不能把失败默认转换成“没有退款意图”。
当客服流程需要更多信息时,可以把 wants_refund、department 和 frustration 放进同一次请求的 questions。它们共享同一个 state,分别回答自己的问题。按官方说明,这些问题独立、并行评估;同一请求中的一道题不会先读到另一道题的答案。因此,“先根据部门决定后面问什么”这样的依赖关系,应由代码在拿到结果后安排。多个问题的评估方式
用在 Agent 和知识库问答里
工单分类、意图识别和流程分流,都有比较明确的选项。可以先让 Jev 给出建议,与人工结果对照,再决定哪些情况交给程序自动处理。
在 Agent 中,一个常见用法是入口路由。假设应用有普通问答、知识库查询、联网搜索三个处理流程,Jev 可以用 Choice 判断请求属于哪类,再由代码调用对应流程:
flowchart LR A[用户请求] --> B[Jev 判断处理类型] B --> C[普通问答] B --> D[知识库查询] B --> E[联网搜索] B --> F[不确定时澄清或转人工] C --> G[组织回复] D --> G E --> G
这里的“路由”就是选择交给谁处理。例如,“根据产品手册解释退款规则”可以进入知识库查询,“查一下今天发布的新政策”可能需要联网搜索。类似地,也可以把请求分给不同模型或专门的 Agent。官方意图路由示例
不过,选中 web_search 并不意味着已经得到搜索关键词,更不意味着已经完成搜索。选择处理流程、准备工具参数、执行工具、组织回复,是不同的工作。 Jev 可以负责其中范围明确的选择,参数准备则由代码或具备相应能力的模型完成。多意图请求也要单独考虑:一句话同时要求查询政策和修改订单时,只选一个流程可能丢掉一部分诉求。
在 RAG,也就是先检索资料再生成答案的系统里,Jev 可以放在检索与生成之间,检查候选文档能否支持回答。比如用户问“退款多久到账”,检索结果可能同时包含“申请退款的条件”和“退款到账时间”。两段内容都与退款有关,但只有后者直接回答到账时间。可以把问题和每段候选资料一起交给 Jev,判断“这段内容是否提供回答该问题所需的信息”。官方 RAG 筛选示例
这样,检索负责从大量资料中找出候选,Jev 帮助筛选候选,生成模型利用保留下来的资料回答。是否增加这一步,要比较回答质量、漏掉有用资料的情况,以及新增耗时和费用。如果筛完没有足够证据,流程也应允许继续检索或说明资料不足。相关性判断本身不会补出缺失的知识。
还有一类用法是检查输出。例如,把客服回复和相关政策一起提供给 Jev,问“回复是否包含政策没有支持的退款承诺”。这种问题比笼统地问“回答好不好”更容易定义,也更容易人工核对。它仍是一次模型判断;如果要检查金额是否相等、JSON 是否符合结构、必填字段是否齐全,优先使用直接的程序校验。
实际接入前,可以用退款申请、否定申请、政策咨询和含糊表达各准备一些样例,先写下期望结果,再比较模型输出。除了误判,还要看有多少请求被送去澄清,以及新增的耗时和费用。高置信度结果也需要抽查,模型可能很确定,却理解错了业务标准。