Skip to main content

EdgeJev

在本地跑类型化决策模型

一台 4 核 CPU,单题 15.6 ms

PyPI Latency License Python 3.9+


EdgeJev 把 laya、kev、PlayJev 这些开源 Jev 复现统一成一条「转换 → 量化 → 部署」的路径,跑在普通 CPU 上。运行时只要 onnxruntime、tokenizers、numpy 三个包,不装 torch。

一次类型化决策要多久(每格 8 ms):

官方 Jev 托管 API   ████████████████████████████████████████  314 ms
laya 原项目 · CPU   █████████████████████████·····            200–500 ms
laya 原项目 · T4    ████                                       32.8 ms
EdgeJev · 4 核 CPU  ██                                         15.6 ms

跑的是 laya 同一份权重,没有换更小的模型。省下来的是网络往返,加上 ONNX Runtime 图优化(1.7x) 和 INT8 走 AVX512-VNNI 整数乘加(1.2x)。模型同时从 1290 MB 缩到 324 MB。

15.6 ms 的意义在于它够小。语音对话留给决策层的预算是 50–150 ms,一轮还往往要问好几个问题; 三题打成一次请求是 44.8 ms,仍在预算内。

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 News emotion 构建命令
laya mmBERT-base 322M fp32 1290 MB 32.1 ms 84.1 ms 92.8% 54.0% --precision fp32
laya mmBERT-base 322M int8 324 MB 15.6 ms 44.8 ms 91.2% 48.2% 默认
kev Qwen2.5-0.5B + LoRA fp32 1978 MB 44 ms 131 ms 90.0%¹ 44.0%¹ 默认
kev Qwen2.5-0.5B + LoRA int8 497 MB 26 ms 78 ms 84.0%¹ 21.0%¹ --precision int8
playjev Qwen3.5-0.8B VLM fp32 2214 MB 1.2 s — — — 默认

¹ kev 用 n=100 子集评测,与上面 n=400 的行不可直接比较。同一子集上 laya 的成绩是 fp32 94.0% / 57.0%、int8 91.0% / 53.0%。

同一份权重的横向参照: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 完全相同

kev 同样对拍过,参照是上游 kev/model.py 原文(encode / branch_mask_batch / PointerHead), 两条路径从分词到读出全程独立,只共享权重。六个用例覆盖中英文、2/3/6 选项、长短 state、 含 opt_mask padding 的情形:logits 最大偏差 7.15e-06、概率最大偏差 1.19e-06、argmax 零翻转。

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

怎么选精度

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

精度 体积 单题 AG News emotion 说明
fp32 1290 MB 32.1 ms 92.8% 47.0% 与上游逐位一致
int8 per-tensor 324 MB 15.6 ms 90.5% 52.2% 默认
int8 per-channel 325 MB 16.7 ms 90.2% 53.0% --precision int8-pc
int8 pc + reduce_range 325 MB 16.5 ms 91.0% 54.2% 两项都接近最好
int8 混合(决策路径 fp32) 366 MB 19.2 ms 90.2% 52.8% --precision mixed
uint8 per-channel 325 MB 27.9 ms 91.0% 48.5% 见下
int8 但嵌入表保持 fp32 915 MB 23.9 ms 91.0% 51.5% 见下
int8-static 326 MB 195 ms 25.8% 29.8% 不可用,见下

几条实测结论: 不同后端的默认精度不一样。 edgejev build 不指定 --precision 时按后端取:laya 用 int8, kev 和 playjev 用 fp32。原因是读出头的结构不同——laya 的打分头是 LayerNorm → Linear → GELU → Linear, 量化噪声被非线性吸收;kev 的 PointerHead 只有两个 Linear 做点积,噪声直接作用在选项排序上。 实测 kev 量化后 AG News 掉 6 点、emotion 从 44.0% 掉到 21.0%(六分类随机基线 16.7%), 选项越多塌得越狠。laya 同样量化只掉 3–4 点。

动态量化的结果依赖 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 build checkpoint → ONNX → 量化 → 多形状自检
edgejev serve POST /v1/systemone
edgejev eval AG News / emotion 上跑指标
edgejev bench 测延迟
edgejev info provider 与已注册后端

后端

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

SPEC = BackendSpec(
    name="kev",
    layout="packed_branches",
    attention="block_causal",
    readout="model_logits",
    runtime="onnx",
)
后端 布局 注意力 读出 运行时 默认精度
laya 每题一行,[MASK] 标记位 bidirectional 打分头随模型进图 ONNX int8
kev 多题打包一条序列 block-causal + 选项隔离 PointerHead ONNX fp32
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 x86 CPU(AVX512-VNNI / AVX2)
macOS Apple Silicon CoreML,不支持的算子回退 CPU
Linux ARM CPU(int8 走 SDOT)

edgejev info 看实际选用的,--provider cpu 或 EDGEJEV_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 无隶属关系。

Metadata

Release files for edgejev 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for edgejev 0.3.1
File Size Uploaded
edgejev-0.3.1.tar.gz 44.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for edgejev 0.3.1
File Interpreter ABI Platform
edgejev-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 91.8 kB

Release files / edgejev-0.3.1.tar.gz

Download URL edgejev-0.3.1.tar.gz
Size 44.0 kB
Tags Source
SHA-256 checksum
How to use checksums
9e471156a3a81bcd601ccda6f4b0a85c6dd4c27bc86a7cf489681060a6457a40
BLAKE2b-256 checksum
How to use checksums
5d58ef3e9b5546de26d31ca829b9e71b8418e0aec46a99e4e0af1c019f1b365f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / edgejev-0.3.1-py3-none-any.whl

Download URL edgejev-0.3.1-py3-none-any.whl
Size 47.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2e6ec3d792d9a4b6109cd8b4778eacf9e7008c0770858461ee2f708d6aba9ca5
BLAKE2b-256 checksum
How to use checksums
523dfdea726370fc11bd4234e429079bdbbf062c47a4cc68cad1c3a9e4c56d59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

0.3.2

2 release files

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page