我让大模型「写作文」写了 47 版正则,直到老陈说:你在让语文老师做判断题

简介: 周五晚上十一点,第 47 版正则还是错的。这不是提示词问题——我一直在让一个「写作文的模型」去做判断题。记录我换成 TypeSafe Jev(System One 模型)重写工单分诊的完整过程:三类问题原语怎么选、问题为什么要拆到原子级、一次调用问 13 个问题便宜 12 倍的实测数据,以及 confidence 门控与中文准确率等四个踩坑心得。

周五晚上十一点,阿杰盯着屏幕上第 47 版正则表达式发呆。

# v47,还是错的
pattern = r'"category"\s*:\s*"(billing|technical|sales|account)"'

他要做的事其实特别简单:把客户工单分给对的那个团队。他让大模型判断这封工单该给哪个部门,模型回了一段话:

根据您的描述,这封工单涉及支付问题,同时也提到了无法登录。
考虑到主要诉求是重复扣款,我建议归类为 billing(账单)。当然,
如果您认为账号问题更紧急,也可以考虑 account...

阿杰要的是 billing 三个字母。他拿到的是一篇小作文。

小迪从旁边探过头来,嘴里还叼着奶茶:「杰哥,它为什么就是不听话呀?你都说清楚了吧?」

「说清楚了。」阿杰把椅子往后一推,「但它天生就是干这个的——它是来跟人聊天的,不是来给你填表的。」

老陈路过

老陈端着咖啡从背后经过,瞥了一眼屏幕,停下了。

「第几版了?」

「四十七。」

「那你不是在做工程,你是在做心理疏导。」老陈拉了把椅子坐下,「问题的根不在正则。你在让一个写作文的去干判断题。」

阿杰没说话。

「你想想看,」老陈拿手指敲了敲屏幕,「它被训练出来是为了让人类读着舒服。你觉得舒服,跟它给的答案靠不靠谱,是两个完全不同的优化目标。」

小迪举手:「等等,这两个不一样吗?读着舒服不就说明它很懂吗?」

「你想想看,」老陈对她说话的语气明显软了半档,「一个人把话说得很漂亮,你就敢把转账按钮交给他按吗?」

小迪愣了两秒:「哦——所以它是会说,但不一定是说对?」

「对。而且还有个更麻烦的:它永远不肯说『我不知道』。你让它强行选一个,它就选一个给你,括号里还给你补个理由。」

老陈甩过来一个链接:docs.typesafe.ai

「TypeSafe 的 Jev。它不是语言模型,是 System One 模型——专门做判断的。」

小迪的翻译时间

小迪把链接点开,看了三行就转头:「杰哥,什么叫 System One 模型?」

「你先别管这个名字。你就记一句话:它不生成文字,它只给你答案和概率。

「可是不给文字我怎么知道它对不对?」

「你不用知道它对不对,」阿杰说,「你的代码知道。它返回的是 choice 这个字段,值就是 billing 三个字母。不是一句话,是一个值。」

「哦——所以它就是……把『判断』这个东西做成了一个函数?」

阿杰和老陈同时看了她一眼。

「……这句话比我准备讲的都准。」老陈说。

它到底怎么用

Jev 的核心是三种「问题原语」。你定义问题,它返回答案。

原语 回答什么 返回什么
Choice 从一组选项里选一个 choice + probabilities + confidence
Score 在一条有序量表上的位置 score + legend + probabilities + confidence
Noul 是 / 否 noul(0 到 1 之间,没有单独的 confidence)

一个请求长这样:

{
   
  "state": "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP.",
  "model": "jev-latest",
  "questions": {
   
    "department": {
   
      "type": "choice",
      "instructions": "Which team should handle this",
      "criteria": {
   
        "billing": "Payment or subscription issues",
        "technical": "Bugs or integration problems",
        "sales": "Pricing or account questions"
      }
    },
    "is_urgent": {
   
      "type": "noul",
      "instructions": "The message conveys urgency or time-sensitivity"
    }
  }
}

返回:

{
   
  "model": "jev-1.13.0",
  "answers": {
   
    "department": {
   
      "type": "choice",
      "choice": "technical",
      "confidence": 0.78,
      "probabilities": {
    "technical": 0.85, "sales": 0.0, "billing": 0.15 }
    },
    "is_urgent": {
    "type": "noul", "noul": 1.0 }
  },
  "usage": {
    "input_tokens": 392, "output_tokens": 65 }
}

阿杰盯着那个 "choice": "technical" 看了半天。

「没有一句话。」他说。

「你可以直接 if 它。」老陈说。

Python SDK 也就三行:

from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

with TypeSafeClient() as client:
    response = client.system_one(
        state=ticket,
        questions={
   
            "department": Choice(
                instructions="Which team should handle this",
                criteria={
   
                    "billing": "Payment or subscription issues",
                    "technical": "Bugs or integration problems",
                    "sales": "Pricing or account questions",
                },
            ),
        },
    )

print(response.answers["department"].choice)   # 直接就是 "technical"

心得一:问得越"小",结果越准

阿杰上手第一件事,就是把原来那句大问题原样搬了过去:

这封工单是不是垃圾邮件?

结果不太好。老陈看了一眼说:「你这不叫提问,你这叫让它在脑子里开一场会。」

官方文档里有一句话阿杰抄在了便签上:System One 模型最擅长的是「一个懂行的人几秒钟能做出的判断」。如果一个问题需要长时间推理,或者要权衡好几个独立因素——那不是问题,那是任务。

正确的做法是拆开。不要问「这封邮件是不是垃圾邮件」,而是问:

  • 是否要求收件人提供密码或其他登录凭据?
  • 是否宣称收件人获得了意外奖励或奖金?
  • 是否在制造时间压力、催促立刻行动?
  • 发件人显示的组织名与它的邮箱域名是否冲突?
  • 链接文案是否隐瞒或误导了真实跳转地址?

然后在你自己的代码里组合:

answers = response.answers
spam_risk = (
    0.45 * answers["requests_credentials"].noul
    + 0.30 * answers["sender_identity_mismatch"].noul
    + 0.25 * answers["unexpected_reward"].noul
)

if 0.4 < spam_risk < 0.6:
    route_to_human_review(ticket)   # 不确定交给人工
elif spam_risk >= 0.6:
    quarantine_as_spam(ticket)

权重在你的代码里,所以你能一眼看出这个分数是怎么算出来的。哪天业务优先级变了,你改一个系数,而不是重写一段 prompt 再祈祷它别崩。

小迪看着这段代码:「杰哥,这几个 0.45、0.30 是什么意思呀?」

「我觉得哪个信号更重要,就给哪个更大。」

「那……你怎么知道该给多少?」

「先拍一个,然后拿真实数据看结果对不对,再调。」阿杰说,「重点是——这个数字你看得见,也改得动。 以前那个版本,权重全在模型的脑子里,你够不着。」

心得二:一次把所有问题问完

这是阿杰最没想到的一点。

他以前的做法很"自然":先问分类,拿到结果,再根据分类决定要不要问严重程度。两次调用,串行。

Jev 的做法是:全都一次问完,包括你这次可能用不上的。

questions = {
   
    "category":          Choice(...),   # 这封工单属于哪一类
    "bug_severity":      Score(...),    # 如果是 bug,多严重
    "has_repro_steps":   Noul(...),     # 如果是 bug,有没有复现步骤
    "refund_requested":  Noul(...),     # 如果是账单,是不是要退款
    "frustration":       Score(...),    # 不管哪一类,客户情绪如何
}

如果结果是「产品建议」,那 bug_severity 的答案直接忽略掉就好。多问的这几个问题,成本几乎为零。

官方有一个跑在 GDPR 维基百科条目(约 5.4 万字符)上的基准测试,13 个问题:

策略 调用次数 成本 总耗时
一次调用问全部 13 个 1 $0.000497 0.27s
13 次调用各问 1 个 13 $0.006090 2.71s

便宜 12.2 倍,快 10.0 倍,答案完全一致。

阿杰盯着这张表看了很久。

「因为文档要重复发 13 遍对吧。」

「对。」老陈说,「而且你有没有注意到,13 次是串行的。你以前那个『先分类再判断』的流程,每次都要等一次网络往返。」

「那问题多了会不会互相干扰?」

「这是个好问题。」老陈说,「不会。同一次请求里的每个问题都是独立评估的,一个问题的答案不会变成另一个问题的上下文。所以答案是可加的——你删掉任何一个问题,其他答案都不变。」

心得三:confidence 是第二个决策轴

阿杰一开始觉得 confidence 就是个花哨的装饰。直到他发现自己以前那个系统最大的问题:

它从来不承认自己不确定。

「你以前怎么处理的?」老陈问。

「我就……硬信它。反正它每次都给我一个答案。」

「所以你的系统在客户消息模糊的时候,会特别自信地走错路。」

Jev 的 confidence 是 0 到 1 的一个数,由概率分布的形状算出来:全压在某一项 → 接近 1;分散在好几项 → 低。你可以直接用它做分层:

action = response.answers["action"]
confidence = action.confidence

if confidence < 0.5:
    route_to_human(user_message)          # 真不确定,别猜

elif action.choice == "check_balance":
    show_balance(account_id)              # 低风险,错了也只是看错一屏

elif action.choice == "approve_transfer":
    if confidence > 0.9:
        confirm_then_execute(account_id)  # 高风险 + 高置信
    else:
        ask_user_to_confirm(account_id)   # 高风险 + 中等置信 → 先确认

关键体会:阈值不该是一个数。

查余额和批转账,误判的代价完全不一样。低风险的动作用 0.6 就够了,高风险的得压到 0.85 以上。这个"风险容忍度"必须由你的代码来编码——那是业务判断,不是模型该替你做的。

小迪又举手了:「杰哥,那如果它给 0.95,是不是就一定对了呀?」

「不是。」阿杰说得很干脆,「它 0.95 的意思是『我很有把握』,不是『我肯定对』。这两个是两回事。」

「那怎么知道它靠不靠谱?」

「拿你自己的数据跑,画一张置信度 vs 准确率的图,看它在哪个区间是真的可信。」

心得四:上下文放进 state,别赌模型的记忆

Jev 不会用你的数据做微调,所有账号共享同一套权重。定制靠的是你每次请求里给它的东西

{
   
  "ticket": {
   
    "message": "My flight was cancelled. Can I get a refund?",
    "sender": {
    "display_name": "Acme Payroll", "email": "rewards@claim-bonus.example" }
  },
  "refund_policy": "Cancelled flights are eligible for a full refund.",
  "customer": {
    "plan": "business", "open_orders": [...] }
}

重点是只放和当前问题有关的那部分。塞太多不相关的上下文,反而会分散它的注意力。

还有一个技巧阿杰觉得很妙:可以用反引号路径把问题精确指向 state 里的某个值。

{
   
  "type": "noul",
  "instructions": "Do `support.tickets[0].message` and `commerce.orders[0].charges` indicate a duplicate charge?"
}

「这就相当于告诉它:别扫全文,就看这两个字段。」

踩过的坑

一、中文的准确率确实低一档。

Jev 的主要训练语言是英文。中文、日文、韩文能处理,但官方明确说了准确率会降。阿杰拿自己的一批工单测过,同样的问法,英文样本上 confidence 普遍在 0.9 以上,中文样本明显更分散。

所以中文场景下:调低你的自动通过阈值,把更多案例留给人工。这不是模型不行,是你得知道它的边界在哪。

二、别把 probabilitiesconfidence 混着用。

只想选最优选项?直接取概率最高的那个,不要设阈值。

要上统计或排序算法?用完整的 probabilities,别用被压缩成一个数的 confidence

三、Score 的分数相同,不代表分布相同。

score = 1.0 有可能是「全部概率压在等级 1」,也有可能是「一半在等级 0,一半在等级 2」。这两种情况在业务上完全不是一回事,必须结合 probabilities 一起读。

四、写 Score 的等级时,描述"情境",别描述"程度"。

有效:"Broken or degraded feature, but workaround exists"

无效:"Moderately severe"

官方实测过一个极端例子:同样的输入,用三个情境化描述能得到 score=0.0、confidence 1.0;换成纯数字等级 ["0","1","2"],分数飘到 0.55、confidence 掉到 0.33。因为模型没有可匹配的东西。

最后

阿杰把那 47 版正则全删了。整个分诊逻辑缩到了大概 80 行——其中一半是问题定义,一半是阈值和权重。

「所以你现在明白了吗,」老陈收拾咖啡杯,「最大的变化不是你换了个模型,是你把『判断』和『控制流』分开了。

「模型只负责『看一眼,给个概率』。谁来决定走哪条路、什么情况下该停下来找人——那永远是你的代码。」

小迪在旁边用 Jev 写了自己第一个小脚本,抬头说:「杰哥,我这个跑通了!它就是……我把问题问清楚,它就老老实实给我答案,一句废话都没有。」

「对,」阿杰笑了一下,「能少说的,才是真的会说。


参考链接

Python 装起来就一行:pip install typesafe-sdk(需要 Python 3.10+),然后在 https://console.typesafe.ai/keys 拿个 key 就能开跑。

目录
相关文章
|
12天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
|
12天前
|
人工智能
千问办公官网入口:阿里AI办公QwenWork产品页和免费网页端链接
千问办公官网含两大入口:一是网页端(qwenwork.cn),即开即用,支持浏览器直接访问;二是阿里云产品页 https://t.aliyun.com/U/JNKJuO 提供免费/付费版详情、功能介绍及使用指南。
|
18天前
|
网络协议 Linux iOS开发
【2026实测】Wireshark下载+安装+汉化+使用教程(图文版,巨详细)
Wireshark 是一款免费开源的网络协议分析工具,可实时捕获、解析并可视化数据包,助你诊断网络故障、分析通信协议(如HTTP、DNS、TCP等)。支持Windows/macOS/Linux,含中文界面,新手入门便捷。(239字)
|
11天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1371 8
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
|
13天前
|
缓存 人工智能 自然语言处理
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
本文是阿里云百炼平台Qwen3.8-Flash大模型的选型接入指南,作为兼顾性能与响应速度的高性价比多模态模型,它支持百万级上下文窗口、全场景多模态输入与完整智能体能力矩阵,适配编程辅助、智能体协作等核心场景。文中同步梳理了最新下调的阶梯定价、夜间4折等优惠活动,搭配OpenAI兼容流式调用示例,帮助开发者低成本快速落地高并发AI应用。
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
|
13天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
1983 15
|
17天前
|
人工智能 运维 BI
阿里云千问办公QwenWork深度解析:基于Qwen3.8,六大核心能力重构企业全自动化工作流与计费选型指南
传统AI办公工具大多停留在对话问答、文档摘要、简单文案生成层面,只能完成单点碎片化任务,无法自主拆解复杂业务流程,很难串联多工具、多文档、外部业务系统完成端到端完整工作交付。很多企业在落地AI办公的时候,需要组合多款不同工具,来回切换界面,手动复制粘贴中间结果,智能化改造落地门槛居高不下。千问办公QwenWork是整合多款智能体产品能力打造的一体化企业办公智能体平台,底层基座依托Qwen3.8大模型,打通桌面端Agent、云端Agent、企业协同Agent三种运行形态,不再局限简单问答,接收业务目标之后自主拆解任务步骤,调用各类工具,处理文档、表格、浏览器自动化、数据查询,直接输出可交付的办公
1686 4
|
19天前
|
缓存 数据可视化 开发工具
DeepSeek Harness 怎么更新?dsh 更新完整指南:更新本体(npx、npm、源码)与更新插件两种方式
DeepSeek Harness 的更新分两层:本体更新(npx 自动最新、npm update -g、源码 git pull)与插件更新(插件市场点更新、命令行覆盖安装)。本文按「准备 → 更新本体 → 更新插件 → 更新后检查」四步走,覆盖新手常见疑问。
2051 1
DeepSeek Harness 怎么更新?dsh 更新完整指南:更新本体(npx、npm、源码)与更新插件两种方式
|
13天前
|
缓存 JSON API
阿里云千问Qwen3.8‑Max深度解析:核心能力、订阅计费规则、API接入配置与生产落地完整教程
Qwen3.8‑Max作为千问系列新一代MoE架构旗舰基座,总参数量达到2.4万亿,激活参数950亿,是面向复杂专业任务、长周期智能体、工程级代码开发、多模态深度解析的高阶大模型,原生支持文本、图像、视频多模态输入,最大上下文窗口达到百万Token,最大输出Token支持131072,内置深度思考推理链路,在编程、科研、法律金融专业分析、长视频文档解析、自主Agent任务等场景能力表现突出。很多开发者在项目前期直接接入该旗舰模型,却对模型能力边界、多种计费模式、订阅套餐权益、API参数配置、上下文缓存优化缺乏完整认知,出现成本失控、接口报错、长文本信息丢失、深度思考模式额外消耗大量Token等
908 3
|
7天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)