从 Jev 回看我们的外呼系统:把"判断"从"说话"里拆出来

9 月中旬,TypeSafe AI 发布了一个叫 Jev 的模型,很快在开发者圈子里火了起来。它不聊天、不写代码、不解释自己的思路,只做一件事:你给它一段"状态"和几道预先定义好的题,它直接告诉你每个选项的概率。
读完它的发布文章和几份第三方评测,我们的第一反应是:这个思路我们并不陌生。过去一年做 AI 外呼,我们在很多地方做的其实是同一件事,只是从来没有把它抽象成一个统一的概念,也没起过名字。这篇文章想讲清楚三件事:
- 我们怎么理解 Jev,它真正新的地方在哪;
- 我们之前做过哪些"同路"的工作,各自做到了什么程度、踩了哪些坑;
- 接下来打算怎么做。
文中凡是 Jev 的性能数字,都来自 TypeSafe 官方或公开的第三方评测,我们自己没有测过 Jev;我们自己的数字都来自线上真实通话的离线对照,样本量会写清楚。
一、Jev 到底是什么
先用一句话概括:Jev 把"让 AI 做判断"从"让 AI 说一段话,程序再去解析",变成了"程序问一道有固定选项的题,AI 直接返回概率"。
传统的大模型用法是这样的:想知道客户是不是在要求退款,就写一段提示词,让模型输出"是"或"否"(或者一段 JSON),程序再去解析这段文字。模型要先"说出来",程序才能用。
Jev 的接口反过来:
- 开发者先给出一个 state,也就是待判断的文本、JSON 或文本列表;
- 再给出一道或多道类型化的问题,比如单选(这张工单属于账单、技术还是账号问题)、有序评分(客户情绪是平静、沮丧还是非常沮丧)、是非题(这条消息是否在要求退款);
- 模型返回的不是一段话,而是选中的答案、每个选项的概率、以及置信度。多道题可以在一次请求里并行回答。
TypeSafe 给它起的类别名叫 "System One Model",借用卡尼曼《思考,快与慢》里的说法:System 1 是快速、直觉式的判断,System 2 是缓慢、需要推理的思考。Jev 只想做前者——大量、快速、边界清楚的小判断。名字则来自经济学家杰文斯:一种资源越便宜,用得反而越多。TypeSafe 的设想是,一次智能判断便宜到一定程度,它就会从"整个流程调一两次大模型",扩散到软件里每一个路由、审核、评分和监控节点。
官方公布的几个数字:端到端响应 70~500 毫秒;输入每百万 token 0.042 美元,输出不收费;训练方法叫 RLCD(面向校准决策的强化学习),目标是让模型报出的概率接近真实发生的频率——长期看,它说 80% 的事,大概真有 80% 会发生。
我们认为它真正新的地方
把一个大模型拿来做分类,这件事本身不新。我们觉得 Jev 值得认真看的地方有三点:
第一,判断和生成彻底分开。 判断不再是"让模型写一段话"的副产品,而是一个独立的、有固定接口的调用。输出空间提前限定好,模型不可能答出选项以外的东西,程序拿到结果可以直接进 if/else。
第二,返回的是概率,而不只是一个标签。 这一点最重要。只有一个标签,程序只能"信"或者"不信";有了概率,程序才能分层处理:把握大且风险低的自动执行,中间那段交给更强的模型,把握小或者后果严重的交给人。概率是把 AI 判断接进自动化流程的前提。
第三,这个概率是训练出来要"对得上"的。 一般大模型吐出的概率并不代表真实频率,经常是简单样本全是 1.0,判错了也是 1.0。Jev 把"校准"直接当作训练目标,这是它和"拿个大模型改造成分类器"最本质的区别。
它不是什么
评测和安全研究里有几点同样值得记住,我们在自己的工作里也都碰到过:
- 类型安全不等于判断正确。 只允许三个选项,模型不会答出第四个,但完全可能在三个里选错。
- 校准不是全局属性。 波恩大学和 Fraunhofer IAIS 的独立评测(37 个数据集、34 万多次请求)显示,Jev 单选题的概率整体校准不错,但是非题直接用 0.5 当阈值并不合适,多标签场景会明显高估少见标签,在低资源语言、细粒度标签和主观评分任务上也会变差。换到具体业务,概率要用业务数据重新标定。
- 结构化输出挡不住提示注入。 Check Point 的测试里,攻击者只要控制文档中的一段内容,就能让模型稳定地返回一个"格式完全合法"的错误判断。
- System 1 有能力上限。 一个问题最后只有三个选项,并不代表得出答案的过程不需要推理。
二、我们之前做了什么
回头看,我们的外呼系统里早就有一层"快速判断",只是它分散在各个模块里,实现方式五花八门,也没有统一的名字。按时间和成熟度,大概可以分成三类。
1. 通话中:一直存在、但没有概率的"快判断层"
AI 打电话时,每一轮客户说完话,系统都要在极短时间内回答一串问题:
| 每轮要回答的问题 | 现在由谁回答 | 怎么判断 |
|---|---|---|
| 当前这一步任务完成了没有?客户是不是提了某条异议?是不是在向 AI 求证? | 对话导演 Director | 关键词子串匹配 + 否定词护栏 |
| 客户是不是生气了、耐心还剩多少? | 认知状态追踪 | 关键词 + 规则打分(约 15 个维度,不调模型,10 毫秒以内) |
| 接电话的是真人,还是手机 AI 秘书、语音信箱? | 接听筛查 | 正则 |
| 这句话该垫一句什么场? | FlashFiller 垫场 | 语义向量匹配,阈值 0.88 |
这些问题全都是 Jev 定义里的 "System One" 问题:有固定选项、要快、不需要长链推理。我们当初的设计思路和 Jev 也很像——这些判断不交给负责说话的主 LLM,而是由独立的模块先判断好,再把结论作为约束交给主 LLM,让它只管把话说好。
差别在于实现:我们用的是关键词、正则和语义阈值。好处是零成本、零延迟、可解释;坏处同样明显:
- 只有"命中/没命中",没有"有几分把握"。 一个"行吧"既可能是同意,也可能是不耐烦,规则只能二选一。
- 词表会越堆越长。 每复盘出一个漏判,就补一个词;每出一个误判,就加一条否定护栏。
- 最关键的动作反而最没底。 接听筛查一旦判定是语音信箱,就会留一句话然后挂断。这种直接改变通话走向的动作,最需要的恰恰是"有把握才执行",而正则给不了把握。
2. 通话后:意向判定,从"一段话里顺带写一句"拆成独立的判断题
通话结束后,系统要给每通电话出一份分析:摘要、业务字段提取,以及最关键的"客户有没有意向"。意向直接决定这通电话要不要推送给客户的销售、计不计费。
原来的做法是一份提示词让 LLM 一次输出意向、摘要和所有字段。10 月初我们做了一次离线对照(75 通真实通话,覆盖 16 个机器人,同一个模型,每种写法跑两次),结论很直接:
- 原写法自己都不稳定:同一通电话跑两次,意向一致的只有 85%;把意向拆成一组独立判断题之后,两次一致率是 95%~96%。
- 拆开之后更准:对两种写法有分歧的通话逐条人工标注,在普通意向型机器人上,原写法 18 次里对了 7 次,拆分后对了 17 次。
- 还更快:判断这一步的耗时中位数从 18 秒降到 5~7 秒,因为模型不用再先写完一大段摘要。
于是我们上线了"核心判断 + A/B/C/D 四档":意向判断和摘要生成并行跑,意向以判断结果为准,判断失败或超时就沿用原来的结果。A/B 算有意向(计入意向、计费、推送),C 是"有明确犹豫表态"(推送给企业但不算意向、不收费),D 是否。每个机器人还可以自定义判断题的标题和每一档的定义,比如把题目改成"客户是否确认参加会议"。
回头看,这就是 Jev 的类型化问题:题目、选项、每个选项的定义都提前写死,模型只负责在这几个选项里选。
这一步也踩了两个坑,和 Jev 评测里提到的局限对得上:
- 题目必须写清主语。 第一版判断题没写清"对方"指的是谁,75 通里有 31 通被判成了"机器接听"。题目一拆开,原来靠上下文自然理解的东西就必须一个字一个字写清楚。
- 同一个词在不同业务里语义不同。 有些质检类机器人把"意向"重新定义成了"是否检测到异常"——对它们来说,接到语音信箱恰恰是"是"。系统固定的判断题处理不了这种语义翻转,我们只能让这类机器人继续走老路径。这正是"校准和语义都要落到具体业务"的一个小例子。
但这一版仍然只解决了一半:模型输出的还是一个档位字母,没有概率。没有概率就没法排序,也就没法回答"哪些电话最该交给人工复核"。
3. 最近:用大模型的 logprobs 做一个"穷人版 Jev"
Jev 发布之后,我们在 agent 里写了一个实验模块 LogprobClassifier,想看看不训练新模型,能把 Jev 的接口复刻到什么程度。做法是:
- 每道题只让模型输出一个选项字母(
max_tokens=1),从返回的top_logprobs里读出各个字母的概率,只在合法选项里做归一化,全角、带标点的同一个字母合并计算; - 额外算一个覆盖率:合法选项的概率加起来占多少。覆盖率低,说明模型其实想答选项以外的东西,这题本身可能出得有问题;
- 同一个状态下的多道题并发请求,状态放在题目前面,共享前缀命中缓存;
- 按(模型、题目、状态)精确缓存,在途请求共享结果;任何失败都返回带错误标记的答案,不抛异常、不影响主流程。
和 Jev 一项项对比:
| Jev 的特性 | 我们的近似实现 | 差距 |
|---|---|---|
| 只输出选项以内的答案 | 只取选项字母的概率 + 覆盖率指标 | 基本等效 |
| 一次请求并行回答多道题 | 每道题一个请求,多题并发、共享前缀 | 近似,请求数更多 |
| 概率经过校准 | 通用大模型的原始概率,没有校准 | 最本质的差距 |
| 70~500 毫秒 | 实测中位数约 1.1 秒,p90 约 1.9 秒(共享接入点) | 放不进每轮的关键路径 |
校准这一点值得多说一句:我们实测下来,通用模型在简单样本上几乎全是 1.0 或 0.0,判错的时候也可能是 1.0。所以模型报"0.95"不能直接当成"95% 正确",阈值必须在业务数据上重新标定。
在真实通话上的第一次对照
我们拿一个运营商催缴项目的 155 通真实通话(1176 个客户轮次),让关键词规则和分类器在同一个上下文里回答同样四道题:
| 判断 | 规则判"是"的比例 | 分类器判"是"的比例 | 两者一致率 | 分歧轮数 |
|---|---|---|---|---|
| 当前步骤是否完成 | 16.7% | 2.4% | 84.2% | 186 |
| 客户提了哪条异议 | 2.3% | 13.6% | 86.7% | 156 |
| 客户是否在向 AI 求证 | 3.1% | 9.2% | 92.5% | 88 |
| 客户是否在生气 | 0.8% | 4.0% | 96.6% | 40 |
这张表还不能说明谁更准:我们没有人工标准答案,只能先把 656 行分歧挑出来等人工标注。但它已经说明了一件事:规则和模型的偏差方向是系统性的。规则在"步骤完成"上判得过宽(子串一碰上就算完成),在"异议"和"生气"上又判得过窄。之前人工复盘这个项目时我们就发现,客户骂人的话大半没被情绪关键词抓到,这张表和那次复盘的结论对得上。
另一份是某医院出院随访项目的小样本(4 通真人录音、40 个患者或家属轮次),让分类器识别"这一轮属于哪种情况"(正常回答、恢复不好、用药有问题、没听清、想结束……)。和弱标签对比,一致率 72%。样本很小,但有一个现象很有意思:分类器最高概率在 0.8 以上的 36 轮里,选对了 86%;低于 0.8 的 4 轮全错。 即使没有校准,概率也已经是一个有用的信号,能帮我们分出"可以放心"和"需要升级"的样本。
同一份报告也让我们看清了现有做法的问题。这个随访机器人用的是一份大提示词,让 LLM 一边判断患者是什么情况,一边记住问到了第几项,一边组织语言。整体处理正确率 92%,看起来不错,可出错的恰恰是最要紧的几类:家属说自己停了一种药,AI 没有提醒不能自行停药;对方说"谁?"表示没听清,AI 没有澄清就直接往下问。判断、记进度、说话全塞在一次生成里,最需要被单独、可靠地判断的那个问题,反而被淹没了。 Jev 推荐的工作流正好相反:拆成很多个独立的小问题,最后由代码做分支。
三、我们和 Jev 的思路哪里一样,哪里不一样
把上面这些放在一起看,我们和 Jev 的共同点其实是同一个判断:
软件不需要每一步都让 AI 写一段话。很多地方只需要一个可靠、快速、带不确定性的判断,剩下的交给系统。
我们分别从两头走到了这里:通话中,出于延迟考虑,一开始就不能把判断交给主 LLM,但我们使用的是规则,没有概率;通话后,我们为了准确和稳定,把判断从生成里拆了出来,但输出的还只是档位,同样没有概率。
不一样的地方:
- Jev 是一个模型,我们是一堆模块。 它的输入输出接口是统一的;我们的判断散落在 Director、认知状态、接听筛查、通话分析里,每处一套实现,没有共用的定义、阈值管理和评测方法。
- Jev 的护城河是校准。 这一点我们短期内不会自己训练,能做的是在自己的业务数据上做事后标定。
- 我们的场景对延迟要求更苛刻。 电话里留给一轮判断的时间是几百毫秒,而我们在国内调用通用模型实测给出概率结果需要要一秒左右。
四、接下来需要做什么
我们计划按"先离线、再旁路、后接管"的顺序,大致分为五步落地。
1. 先搞清楚"谁更准确"
整理分析以后项目真实拨打数据局进行分歧标注,算出规则和分类器各自的准确率、校准曲线,在业务数据上做温度缩放之类的事后标定,确定每次问答的阈值。没有这一步,后面所有"用概率做决策"都无从谈起。
改进评测方法。Jev 的评测思路是不依赖人工标准答案,而用最强模型的输出当参考概率。同样,我们计划使用国内最好的模型,开启推理生成参考标签,人工只标分歧样本。
2. 通话后的环节切换概率判定
意向判定、质检、坏通话筛选等不依赖模型,网络延时,适合先落地验证。有了概率,就可以把握大小排序:准确性高的结果的自动给出结果;然后交给推理强模型复核;没把握的、或者涉及计费和推送的,进人工复核队列。
3. 通话中"旁路试运行"
步骤完成、异议识别、求证识别、情绪判断,这几处规则已经证实误判多,但它们每一轮都需要判定,一秒的延迟暂时不能进入关键路径。所以第一步只进行旁路分析:分类器在后台运行,只记录日志、积累足够多"规则怎么判定、模型如何判定、最后实际怎么样"的样本。
延迟的解决思路:一是在客户尚未说完时,实时中间转写提前问,将判断时间藏到客户说话的时间里;二是评估专用接入点或者更小的专用模型。
4. 大段提示词拆分
像随访数字员工这样"一份提示词同时做判断、记进度、组织语言"的写法,会逐步改进为:先使用一组独立判断题识别这一轮的情况,再由代码决定该走哪个分支、要不要提醒什么,最后主 LLM 只负责生成自然对话结果。这样关键的判断可以独立评测、调整阈值,出问题也知道是哪环节出错。
5. 抽象出统一的"决策层"
上面这些做完之后,我们计划将散落在各处的判断收拢为一层:
- 对话由业务平台统一定义和下发,包括题目、选项、每个选项的定义、阈值,以及"中间区间交给谁",而不是写死在 agent 逻辑中;
- 每次判断都留下记录:使用哪个模型版本、问答版本、概率是多少、最后执行了什么动作,便于回溯审计;
- 持续监控漂移:客户的说法会变,业务政策会变,同一个阈值不会永远有效。
关键一点:判断的输入是客户说的话,它本身就是不可信的。 结构化输出只约束了答案的形状,并不能保证依据是真实的。所以凡是会影响计费、推送和挂断的判断,规则兜底和人工复核都会保留。
写在最后
Jev 给我们的启发,不是某个具体的数字,而是它给了一个清楚的方法:在"写死的规则"和"什么都让大模型生成"之间,应该有一层专门做快速判断的逻辑层,而且它必须告诉系统自己有多确定。