3.2 predict_batch 与 decide


3.2 predict_batch 与 decide

本节摘要:单次 predict 之后是两个进阶入口。predict_batch 处理批量:把一批 context 与 questions 组织成一次调用,并行红利来自第 1.1 节说过的「无循环依赖」——样本之间不互相等待,吞吐随批量大势抬升(具体倍数取决于硬件,本书只给示意值与实测方法)。decide 是高层封装:不要求你消费分布,直接返回「决策加置信」,低置信时给出弃权信号——这正是第 7 章 min_confidence 门控的接口雏形。本节还给出单次循环与批量的量级对照表(示意值)、批量的组织要领(批大小、内存、顺序保证),以及「什么时候不要批量」的反例。接口写法为示意,以官方仓库 README 为准。

学习目标

  • 用 predict_batch 组织一批 context × questions 并正确解读批量返回。
  • 用 decide 拿到「决策加置信」形态,并说出它与第 7 章门控的衔接点。
  • 用对照表与自测方法评估批量的吞吐收益(示意值口径)。
  • 说出三种不适合批量的场景,避免为批而批。

一、为什么需要批量

单个 predict 循环一万次,每次都有固定开销:请求组织、前向调度、结果拆包。批量的意义是把这部分开销摊薄到整批样本上,同时让并行硬件(多核 CPU 的批量矩阵运算)吃满。laya 的架构对批量天然友好——第 1.1 节红利三:单次前向、无循环依赖,一批样本就是一个大矩阵,不存在「上一条的答案影响下一条」的串行链。

什么时候批量收益最大:离线打标(昨晚的十万条日志今天分类)、非实时管道(每天一次的存量清洗)、预热缓存(把高频问题的答案提前算好)。什么时候收益有限:纯在线单条请求——它们本来就该走服务化(第 4 章)而不是攒批。

二、predict_batch:组织一批 context × questions

# batch_tag.py —— 批量打标一批工单(写法示意,接口以官方仓库 README 为准) from laya import Router tickets = [ "发票抬头开错了,需要重开并寄送到新地址。", "App 在 Android 12 上闪退,重启无效。", "请问你们的企业版支持私有化部署吗?", "配送显示已签收但我没收到货。", ] question = [{ "id": "category", "type": "choice", "question": "这条工单属于哪个类别?", "options": ["账务", "软件缺陷", "售前咨询", "物流"], }] router = Router() results = router.predict_batch( contexts=tickets, # 一批状态文本 questions=question, # 共享同一组问题(也可按条不同,以文档为准) ) for text, res in zip(tickets, results["results"]): print(text[:18], "->", res["answer"], "| conf", res["confidence"]) ​

组织要领三条。批大小:从几十条起步往上试,收益会在某个规模后趋平(内存与调度开销开始显形),用你自己的流量实测拐点(示意建议:常见拐点在百条量级,仅供参考)。内存:批量把整批样本的中间张量同时放在内存里,CPU 内存紧张的环境宁可小批多次。顺序:批量结果与输入顺序一一对应(以上面 zip 用法为前提),依赖顺序的逻辑(比如按置信度取 top 再回查原文)要在拆包后再做。

批量返回的拆包要点:返回是一个与 contexts 等长的结果列表,每项的形态与单次 predict 完全一致(第 3.1 节的四字段)——「单次读懂、批量会拆」是同一套知识。两个易错位:混装多种问题时,先按 id 取对再取 answer,别按位置硬猜;批量失败常见于个别样本超长或为空,先做长度与空值过滤再进批(脏样本逐条降级处理,别让它拖垮整批)。

三、decide:直接返回决策加置信

predict 返回分布,你还要自己 argmax、自己判断置信够不够。decide 把这两步封装掉:

# decide_route.py —— decide 高层封装(写法示意,接口以官方仓库 README 为准) from laya import Router router = Router() decision = router.decide( context="用户输入:我要退掉昨天的订单,商品还没发货。", questions=[{ "id": "intent", "type": "choice", "question": "用户意图是什么?", "options": ["退款", "换货", "咨询", "投诉"], }], ) # decide 的返回聚焦「动作」:答了什么、多可信、要不要采信 print(decision["results"][0]["answer"]) # 退款 print(decision["results"][0]["confidence"]) # 0.83(示意值) ​

decide 与 predict 的关系是「消费层级」而不是「能力差异」:底层是同一套检查点与路由,decide 只是把最常用的消费路径(取 argmax、带出置信)固化成一步。它的价值在接门控——第 7 章会给置信设最低线(min_confidence),低于线的样本弃权转人工,而 decide 的返回形态正好是「决策加置信」,门控逻辑写在它上面最顺。本章先把接口用熟,门控细节留给第 7 章。

在门控正式落地前,可以先在本地预演同样的逻辑,体会「置信驱动的三岔路」:

# gate_preview.py —— 本地门控预演(纯本地逻辑示意,正式门控见第 7 章) MIN_CONF = 0.60 # 示意值:门限的定法在第 7 章用代价函数讲 def act(item): if item["confidence"] >= MIN_CONF: return ("自动执行", item["answer"]) return ("转人工", item["probabilities"]) # 分布一并带上,供人参考 # for item in decide_results: # print(act(item)) ​

预演的价值是提前发现「弃权率是不是高得离谱」——门限 0.60 意味着低置信样本全部转人工,如果八成都转了人工,说明该微调了(第 5 章)或门限定错了(第 7 章),这两种病因要用不同的药。

四、单次与批量:量级对照

方式 组织形式 吞吐量级 适用
predict 循环 逐条调用,每条完整开销 基准 1 倍 调试、单条在线请求
predict_batch 整批一次调用 数倍于循环(示意值,实测为准) 离线打标、存量清洗、缓存预热
decide 单条或批量的封装层 与所封装的调用同级 需要直接消费决策的业务代码

表中「数倍」是示意口径:真实倍数由你的 CPU 核数、批大小、文本长度共同决定。给自己做一次基准测试的方法很朴素——同一批一千条样本,分别用循环与批量跑,各计时三次取中位数,你就有自己环境的数字了(这个数字也顺便是第 9 章选型时说服同事的证据)。

# bench_batch.py —— 批量收益基准(方法示意,数字以自测为准) import time def bench(fn, args, repeat=3): times = [] for _ in range(repeat): t0 = time.perf_counter() fn(*args) times.append(time.perf_counter() - t0) return sorted(times)[repeat // 2] # 取中位数,抗抖动 # loop_secs = bench(lambda: [router.predict(c, q) for c in contexts], ()) # batch_secs = bench(router.predict_batch, (contexts, q)) # print("批量收益倍数(示意):", round(loop_secs / batch_secs, 1)) ​

基准的三条纪律:同机同时段(别拿午夜的循环比下午的批量);同批样本(两组跑的必须是同一份数据);报中位数不报最好值(最好值是运气,中位数是能力)。

五、什么时候不要批量

  • 强在线的单条请求:为了攒批引入等待窗口,等于拿延迟换吞吐,方向反了——在线流量走第 4 章的服务化加并发。
  • 依赖前序结果的链路:下一步的问题取决于上一步的答案(先判类别、再按类别问不同问题),串行链攒不成批;要么拆成多轮,要么改问题设计。
  • 内存紧张的环境:小容器里硬上大批次,OOM 的损失远大于吞吐收益;小批多次更稳。

本节要点回顾

  • predict_batch 把固定开销摊到整批,并行红利来自无循环依赖;组织要领是批大小、内存、顺序。
  • decide 是消费层封装:直接返回决策加置信,是第 7 章 min_confidence 门控的天然接口。
  • 批量收益自己测:同批样本两种跑法各计时三次,拿自己环境的数字。
  • 三种不要批量的场景:强在线单条、依赖前序结果的链路、内存紧张。

SDK 的三个入口都用熟了。下一节换个视角——不写 Python 的时候,CLI 怎么完成预测、脚本检测与模型信息查看,以及怎么把 laya 接进 shell 管道做轻量胶水。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U