EdgeJev

September 20, 2026 · View on GitHub

EdgeJev

在本地跑类型化决策模型

把开源 Jev 复现转成 ONNX,量化,部署到 CPU

PyPI License Python 3.9+


EdgeJev 把 layakevPlayJev 这些开源 Jev 复现统一成一条「转换 → 量化 → 部署」的路径。跑在普通 CPU 上,一台 4 vCPU 的机器单题 15.6 ms;运行时只要 onnxruntime、tokenizers、numpy 三个包,不装 torch。

Quick start

uv tool install "edgejev[build]"
edgejev build --backend laya --out ./jev-int8
from edgejev import Agent

ag = Agent("./jev-int8")
r = ag.system_one("我的信用卡被扣了两次款,麻烦退一笔。", {
    "dept":   {"type": "choice", "instructions": "该转给哪个组?",
               "criteria": {"billing": "支付、扣款、发票、退款",
                            "technical": "程序缺陷、报错",
                            "sales": "售前咨询、定价"}},
    "urgent": {"type": "noul",  "instructions": "这条消息表达了紧急或时间压力"},
    "anger":  {"type": "score", "instructions": "客户的不满程度",
               "criteria": ["平静陈述", "有情绪但讲道理", "非常愤怒"]},
})

r["answers"]["dept"]["choice"]          # 'billing'
r["answers"]["dept"]["probabilities"]   # {'billing': 0.92, 'technical': 0.08, 'sales': 0.00}
r["answers"]["anger"]["confidence"]     # 0.41

转换那一步需要 torch,转完就可以卸掉。之后只装 edgejev 即可运行。

Model zoo

4 vCPU Intel Xeon Cascade Lake(AVX512-VNNI)。准确率由 edgejev eval --task all --n 400 跑出, AG News 4 分类、dair-ai emotion 6 分类,各 400 条,batch=1。

后端模型精度体积单题三题AG Newsemotion构建命令
layammBERT-base 322Mfp321290 MB32.1 ms84.1 ms92.8%54.0%--precision fp32
layammBERT-base 322Mint8324 MB15.6 ms44.8 ms91.2%48.2%默认
playjevQwen3.5-0.8B VLMfp322214 MB1.2 s--backend playjev
kevQwen + LoRA 0.5B–8B导出器开发中

同一份权重的横向参照:laya 自己公布的是 T4 GPU 上 32.8 ms、CPU 上 200–500 ms; 官方 Jev 1.13 托管 API 实测中位 314 ms(含网络往返)。

官方 API 在同样 400 条上的成绩:AG News 85.5%、emotion 61.5%(Vercel AI Gateway,原生 criteria); 88.0% / 62.7%(classifier.dev,光标签)。laya 在 AG News 上高 5–7 点,emotion 上低 8–11 点。 laya 的 README 声称 DAIR Emotion 0.595 对 Jev 0.480,这个方向在上表里没有复现出来。

与上游的一致性

--precision fp32 与上游 laya(PyTorch)逐位一致。对拍覆盖 choice / score / noul 三种原语、 中英文、字符串与 dict 状态、带描述与不带描述的 criteria:

偏差
概率0.00000
置信度0.000000
input_tokens完全相同

playjev 后端没有上游数值可对,改用分布核对:五个游戏画面给出不同的 argmax 与分布形状, max(p) 落在上游公开回放的区间内(167 步真实对局,最小 0.604 / 中位 0.827 / 最大 1.000)。

怎么选精度

下表由 quant_dataset.py 跑出,两个任务都用带描述的标签、batch=16,所以数值与上面的 zoo 表 不能直接比较,但档位之间可以横向比:

精度体积单题AG Newsemotion说明
fp321290 MB32.1 ms92.8%47.0%与上游逐位一致
int8 per-tensor324 MB15.6 ms90.5%52.2%默认
int8 per-channel325 MB16.7 ms90.2%53.0%--precision int8-pc
int8 pc + reduce_range325 MB16.5 ms91.0%54.2%两项都接近最好
int8 混合(决策路径 fp32)366 MB19.2 ms90.2%52.8%--precision mixed
uint8 per-channel325 MB27.9 ms91.0%48.5%见下
int8 但嵌入表保持 fp32915 MB23.9 ms91.0%51.5%见下
int8-static326 MB195 ms25.8%29.8%不可用,见下

几条实测结论:

动态量化的结果依赖 batch。 激活的量化 scale 在运行时按实际张量计算,padding 一变 scale 就变。 同一条输入单独跑和跟别人一批跑,logits 最大差 2.43;fp32 ONNX 同样对比是 0.000。 Agent.system_one 是单请求路径,zoo 表的数字不受影响;自己写批量推理的固定 batch=1 或用 fp32。 edgejev build 会检查这一项并在不满足时警告。

int8-static 目前不能用。 它做到了批次无关(漂移 0.0e+00),但 MinMax 标定下精度掉到随机水平, 而且比动态量化慢约 4 倍。入口保留着,等换 Percentile 或 Entropy 标定。

QUInt8 没有理由选。 同样 8 bit、同样体积,x86 的 AVX512-VNNI 只对有符号 int8 有快路径。 ARM 走 SDOT,这一条不适用。

把嵌入表排除在量化之外没有收益。 322M 参数里 196.6M 是 256k 词表的嵌入表,看上去像精度损失的大头, 但保留它精度并不回升,体积从 324 MB 涨到 915 MB。

fp16 在 x86 CPU 上没有意义。 没有 avx512_fp16,ONNX Runtime 的 CPU EP 会转回 fp32 计算; 另外 onnxconverter_common 的 fp16 pass 处理不了 dynamo 导出图里的 _to_copy 节点,转出来加载失败。

起一个官方协议的服务

edgejev serve --model ./jev-int8 --port 8009
export TYPESAFE_BASE_URL=http://127.0.0.1:8009
export TYPESAFE_API_KEY=local

官方 SDK 改一个 base_url 就切过来,可以先用官方 API 把代码写完再换本地。

CLI

命令作用
edgejev buildcheckpoint → ONNX → 量化 → 多形状自检
edgejev servePOST /v1/systemone
edgejev evalAG News / emotion 上跑指标
edgejev bench测延迟
edgejev infoprovider 与已注册后端

后端

开源 Jev 复现的序列构造、注意力、读出方式各不相同。EdgeJev 把共性放进 edgejev/core/, 一个后端只声明四个维度:

SPEC = BackendSpec(
    name="kev",
    layout="packed_branches",
    attention="block_causal",
    readout="model_logits",
    runtime="onnx",
)
后端布局注意力读出运行时
laya每题一行,[MASK] 标记位bidirectional打分头随模型进图ONNX
kev多题打包一条序列block-causal + 选项隔离PointerHeadONNX
playjev画面 + 字母清单causal词表字母槽torch

渲染、掩码、温度标定、置信度、答案组装都在 core 共用。laya.py 17 行、kev.py 20 行、playjev.py 32 行。

playjev 走 torch 而不是 ONNX:Qwen3.5 的文本塔是混合线性注意力,linear_attention 层依赖 causal_conv1d 和 flash-linear-attention 的递归状态核,没有对应的 ONNX 算子。

安装

uv tool install edgejev              # 全局命令
uv add edgejev                       # 或加进项目,跑的时候 uv run edgejev
uvx --from edgejev edgejev info      # 或临时跑一次
extra什么时候需要
edgejev[build]edgejev build,需要 torch / transformers / laya
edgejev[vlm]playjev 后端,需要 torch / torchvision / pillow
edgejev[train]edgejev.train 训练模块

平台

平台Execution Provider
Linux / Windows x86CPU(AVX512-VNNI / AVX2)
macOS Apple SiliconCoreML,不支持的算子回退 CPU
Linux ARMCPU(int8 走 SDOT)

edgejev info 看实际选用的,--provider cpuEDGEJEV_PROVIDER=cpu 强制。

训练

edgejev.train 与推理共用同一个渲染器,训练序列和线上请求逐 token 相同。

  • losses.py — 严格恰当评分规则(log score + spherical,score 型加 ranked probability score), 优化概率校准而不是 argmax 正确。另含 ECE 与可靠性分桶。
  • data.py — 硬标签与软标签统一成目标分布。
  • model.py — 任意 HF 编码器 + 两层 transformer head + 标记位打分头,训完可被 edgejev build --backend laya 导出。

Acknowledgements

License

Apache-2.0。权重与 tokenizer 的许可归各自上游所有。本项目与 TypeSafe AI 无隶属关系。