JEV / code /DESIGN.md
cloudyu's picture
Upload JEV v0.7.0 (Qwen3.5-9B distilled from Jev 1.13)
b2f3bf4 verified
|
Raw
History Blame Contribute Delete
16.5 kB

基于 qwen3_5 代码路径微调 Jev-API 兼容判断模型 — 设计文档

项 值
状态 v0.7(B200 落地;Qwen3.5-9B 全流程完成并验收;27B 转为条件项)
日期 2026-09-23
数据 SargeDev/jev-distill-corpus-v3(Apache-2.0,740,957 行;data/*.parquet,审计见 reports/data_audit.md)
主干 Qwen3.5-9B(/root/models/Qwen3.5-9B,bf16,Apache-2.0,文本路径 8.0B);Qwen3.8-27B 已就位(/root/models/Qwen3.8-27B)但不再必需
硬件 1× NVIDIA B200 183GB(sm_100)· torch 2.13.0+cu130 · transformers 5.16.1 · peft 0.21 · flash-linear-attention 0.5.2
产出 exports/jev-judge-qwen35-9b(15.9GB 纯文本权重 + 24 槽头 + calibration.json + tokenizer)+ 兼容 HTTP API
工程根目录 /root/jev-judge/

v0.6 → v0.7 变更摘要:开发/冒烟从 GB10 迁到 B200 单卡;主干从 27B 改为同代码路径的 9B 快速迭代,9B 已满足"镜像 Jev"目标,27B 仅作条件兜底;训练侧加入 token 预算 micro-batch、bf16 autocast + fp32 LoRA master 权重、梯度重计算、LR 退火(cooldown);评估侧加入 D1 占位排除口径与教师间距分层分析;服务侧加入动态批处理。


0. TL;DR

(state, question, kind, options) → 裸文本模板 → 单次前向 → [decision]: 末位 hidden → 24 槽 fp32 线性头(初始化 = lm_head 口头词行,第 0 步 ≡ 零样本受限解码,实测 8.6e-07 / 1.49e-06 < 1e-5)→ 按 kind 掩码 softmax → 与 options 对齐的校准分布。训练 = KL 蒸馏教师全分布 + score 有序 RPS,主干冻结 + LoRA(r16, α32)。

最终结果(Qwen3.5-9B,S2 2000 步 + 500 步退火,≈ 32 万样本 ≈ 0.49 epoch,B200 单卡约 1.7 小时),test_set_30k 温度校准后:

指标 §8.3 目标 B0 零样本 最终 判定
平均 KL ≤ 0.15 0.510 0.0276 ✅
noul AUROC ≥ 0.95 0.824 0.9938 ✅
noul Brier(soft) ≤ 0.10 0.096 0.0022 ✅
score 期望分 MAE ≤ 0.35 1.130 0.119 ✅
ECE(15 bin) ≤ 0.03 0.094 0.0014 ✅
choice top-1 ≥ 0.90 0.532 0.884(总体 top-1 0.904) ❌ 见 §8.4
ood KL 退化比 ≤ 2.0 1.68 7.5(ood 绝对 KL 0.857→0.208,top-1 0.52→0.916) ❌ 指标失效,见 §8.4
choice 置换一致性 — max|Δp| 0.173 / 翻转 38% 0.031 / 4.7% ✅

温度:noul 1.004 / choice 0.999 / score 1.004 —— 退火后模型天然校准。服务:单请求 p50 ≈ 90–110 ms,批量 2.5 ms/决策,8 并发 32 req/s(动态批处理)。

1. 已验证结论速览(B200 / 9B 实测)

# 结论 实测值 影响
V1 头初始化 ≡ 受限解码(fp32 重算) 9B 8.64e-07(4 条构造样本)/ 1.49e-06(96 条真实 validation 行);27B 4.47e-07 预训练信息零损耗注入;B0 白给
V1b 右填充不变性 末位 hidden 相对差 9e-03(9B)/ 4.5e-03(27B),bf16 噪声级 可安全按长度桶右填充
V3 模块对表(transformers 5.16.1) GDN 层 Linear 叶子:in_proj_qkv, in_proj_z, in_proj_a, in_proj_b, out_proj;attn:q/k/v/o_proj;MLP:gate/up/down_proj LoRA 挂 10 类叶子(**去掉 in_proj_a/b**:4096→48 的门控标量投影,挂 LoRA 只增加 launch 开销)
V4 口头词裸形式单 token false/true/0–5/A–P 全部单 token,且行首形式 token 与裸形式一致 同 v0.6
V6 数据长度(9B tokenizer) train mean 129.0 / p50 87 / p95 369 / p99 531 / max 856;零截断;84.6M tok/epoch 与 v0.6 一致
V7 D1 均匀占位 yuri_v1 noul **137,203/137,203 = 100%**(train),各 split 同为 100%;test_set_30k 含 2,260 行 训练降权 0.05;校准拟合排除;评估双口径报告
V9 B0 零样本基线(9B) test_set_30k KL 0.510 / top-1 0.441 / noul AUROC 0.824 / ECE 0.094;ood KL 0.857 27B GB10 是 0.479 / 0.538,9B 略弱
V10 B200 吞吐 fwd-only 30–43k tok/s(fla 内核,mb 32–128);S2 fwd+bwd 无 ckpt 7–10k tok/s,有 ckpt + 24k tok micro-batch ~9k tok/s(峰值 34GB) 9B 1 epoch ≈ 2.6–3.5 h;见 §7
V11 激活显存 无 ckpt ≈ 10 MB / padded token(GDN 48×128 扩展维度) v0.6 §7.3 "无需 ckpt" 估算偏乐观 2×;S2 默认开 ckpt
V12 CPU 固定开销 每步 ≈ 300 ms(≈5k 次小 kernel launch:248 个 LoRA 模块 + GDN 胶水);宿主机 load 15–27 时更明显 micro-batch 必须做大;两进程并发训练总吞吐反而下降(3k+3k < 9k)
V13 学习曲线 val KL:B0 0.485 → step500 0.094 → 1500 0.038 → 2000 0.0325;退火 500 步 → 0.0260(全量 validation) 0.49 epoch 即收敛到目标以下 4×;2 epoch 计划不必要
V14 退火收益 同一起点(step 2000):直接评估 val KL 0.0347 vs 退火后 0.0260(−25%);choice top-1 0.863 → 0.884 高 LR 处取的 checkpoint 应做 cooldown
V15 教师 choice 软标签天花板 test_set_30k choice 行 top-1 概率中位数 0.70;top-2 间距 <0.05 占 7.5%(该层一致率 0.46≈抛硬币);间距 ≥0.1 的 86% 行一致率 0.918,≥0.3 行 0.965;我们 argmax 拿到的教师质量 0.682 vs 完美镜像 0.709(**96%**) choice top-1 ≥0.90(全体行)对该教师而言接近上限,见 §8.4

2. 背景与选型(v0.7)

Jev(TypeSafe System One)的 typed decision 由远端 Jev 1.13 产出;jev-distill-corpus-v3 提供 74 万行教师全分布软标签。目标是本地镜像。

选型变化:Qwen3.5-9B(model_type: qwen3_5,与 Qwen3.8-27B 同一套 Qwen3_5* 类与 tokenizer 家族、tie=false、无 softcap)作为主线:

  • 同代码路径 → 27B 只需改 model_path(已在 27B 上跑通门禁);
  • Apache-2.0;无 softcap,头初始化精确等价;
  • 3× 于 27B 的迭代速度,B200 单卡 0.5 epoch ≈ 1.5 h。

曾评估 Gemma 4 12B:final_logit_softcapping=30(需 tanh 修正)、tied embedding、Gemma ToU;作为第二数据点未采用。

3. 数据(M1 完成,reports/data_audit.md)

Schema、划分纪律与 v0.6 一致。B200/9B tokenizer 复核:schema 违规 0;zero truncation @1024;train kind 占比 noul 52.1% / choice 25.0% / score 22.9%;source 占比 yuri_v3 67.7% / yuri_v1 20.9% / openjev_v2 11.4%;choice 选项数以 4 为主(142k),另有 3/5/7/9/16。

D1 处置(三处一致):训练 d1_policy: downweight 0.05, scope yuri_v1;温度拟合默认排除 yuri_v1 均匀占位行(否则 family 级温度会学出 T=17 把一切压平);评估报告"全部行"与"排除 D1"两个口径(差异仅在 KL/ECE 小数点后第三位)。

4. 兼容 API 规格(实现:src/jev_judge/server.py,契约测试 tests/test_server_contract.py 7/7)

POST /v1/decisions · POST /v1/decisions:batch(保序,≤256)· GET /healthz

请求 {"kind","state","question","options","truncate":false,"family":null};响应含 id / kind / options(回显对齐) / distribution(和为 1±1e-4,末位修正) / decision{noul,choice,score,expected_score} / confidence / model{name,version,calibrated} / latency_ms / batch_size。 422:kind/options 非法(noul 必须 ["false","true"],score 必须 ["0".."5"],choice 2–16 项);413:超长且 truncate=false,或 batch > 256;头 X-Jev-Judge-Version;缺 calibration.json 拒绝启动。 动态批处理:单 GPU 工作线程,≤4 ms 窗口合批(≤128 项);校验/分词在提交前同步完成,坏请求不会污染批。实测 8 并发 3 → 32 req/s,p50 2.3 s → 251 ms。 ⚠️ A1(仍待办):与真实 Jev 契约逐字段 diff。

5. 输入模板(冻结,template.py,TEMPLATE_VERSION = bare-v1)

同 v0.6 裸文本模板。分词方式:整串自然 BPE(不分段拼接,避免缝处出现 " "+word 的不自然切分);仅超长时按 token 截 state(头 60% / 尾 40%)后 decode 重渲染。语料零截断,该路径只服务线上边缘输入。

6. 模型架构

同 v0.6 §6.1–6.3(24 槽不相交布局、W[slot]=lm_head[verbalizer]、KL + 0.5·RPS、choice 30% 置换增强、KindBatchSampler floor 1/6)。实现细节(B200):

  • 加载:不实例化视觉塔——按 shard 流式读取 safetensors,model.language_model.*→model.* 重映射进 Qwen3_5ForCausalLM,跳过 model.visual.* / mtp.*;初始化头后释放 lm_head(省 2–2.5GB)。同一加载器读取导出的纯文本 bundle。
  • 精度:主干 bf16 + autocast(bf16);LoRA adapter fp32 master 权重(peft 默认 bf16 会让 1e-4 量级更新被舍入;直接 fp32 计算则走 SIMT sgemm,慢且多 cast);头恒 fp32 且在 autocast 之外;AdamW fused,β=(0.9,0.98),clip 1.0。
  • 训练阶段:S0(B0)✅ · S1 头探针(实现,未单独跑:S2 在 30 步冒烟即达 val KL 0.26,探针价值低)· S2 主交付 ✅ · S3 未触发。

7. 训练方案与硬件(B200 实测替代 v0.6 §7 外推)

7.1 Micro-batch 策略

优化步 = batch_size 个样本(默认 128),内部按长度排序后贪心切成 B·T ≤ max_padded_tokens 的 micro-batch,loss 按样本权重比例缩放使一步等于整 batch 的加权均值。

  • 9B 无 ckpt:max_padded_tokens 10k → 峰值 ~100GB,7–10k tok/s,但 128 样本会切成 3–5 个小 micro,CPU 固定开销放大(实测仅 3.8k tok/s);
  • 9B 有 ckpt(采用):max_padded_tokens 24k → 每步 1–2 个 micro,峰值 34GB,稳态 ~9k tok/s;
  • 27B(配置已备 configs/train_27b.yaml):ckpt + 16k。

7.2 实测时长(9B,单卡独占)

阶段 步数 墙钟
S2 主跑 0 → 2500 步(0.49 epoch,含 5 次 val_sub 评估) 2500 ≈ 1.4 h(前 20 分钟与扫描并发,稍慢)
阶段检查 ×3(暂停训练:校准 + test_set_30k + ood + 500 行置换) — ≈ 3.5 min / 次
LR 退火 500 步(warmup 25,0.9×峰值 → 0.02×) 500 ≈ 20 min
最终校准 + 全量评估(4 split + 1000 行置换) — ≈ 6 min
导出 15.9GB bundle — ≈ 1 min

对照 v0.6 §7.4 的 8×H200/B200 集群测算:单卡 B200 上 9B 达标只需 ≈1.7 h GPU,无需多卡。

7.3 环境要点(B200)

  1. fla 0.5.2 的 chunk_gated_delta_rule Triton 内核在 sm_100 可用(transformers 经 kernels hub 回退机制自动接入);
  2. causal_conv1d 无法编译:系统 nvcc 12.8 vs torch cu130 版本不匹配 → transformers 回退 F.conv1d(前向 ~9% 时间),可接受;
  3. Triton JIT 正常(有 python3.11-dev),无需 GB10 的 _triton_guard;
  4. PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True;后台任务用 scripts/bg.sh(setsid+nohup);不要用 pkill -f 匹配含自身命令行的字符串;
  5. 宿主机共享 CPU(配额 20 核,load 15–27)会放大 launch 开销并造成偶发 10–30 s 停顿;以中位数吞吐评估。

7.4 超参(实际使用)

configs/train.yaml + 覆盖 gradient_checkpointing=true max_padded_tokens=24000:batch 128,lr 头 2e-4 / LoRA 1e-4,cosine warmup 3% min 10%(原计划 2 epoch 的日程,实际在 step 2500 按检查结论停止),λ_RPS 0.5,D1 downweight 0.05,choice 置换 30%,eval_every 500 × 4000 行,patience 3。 退火:--init-from checkpoints/s2_9b_seed42/best,500 步,warmup 5%,lr 头 1.8e-4 / LoRA 9e-5 → ×0.02,seed 43。

7.5 10% 扫描(M3,后台进行中)

scripts/run_scan.sh:base / λ_RPS=0 / D1 drop / lr×2,各 10% 子集 2 epoch。结果落 checkpoints/scan_*/log.jsonl,供下一版并入;不影响本次交付。

8. 校准与评估

8.1 温度校准

per-kind 标量 T,L-BFGS 最小化 KL,仅 calibration 划分且排除 D1 占位行(10,954/13,766);family 级细化阈值 ECE>0.02 & n≥500(最终模型未触发)。最终 T = noul 1.004 / choice 0.999 / score 1.004。

8.2 阶段检查流程(v0.7 新增,scripts/review_checkpoint.sh)

训练中每 500 步存 best/last;在 step 500 / 1500 / 2500 SIGSTOP 暂停训练 → 快照 checkpoint → 校准 → test_set_30k + ood 全量评估 + 置换一致性 → 对照预期 → SIGCONT 恢复。三次检查全部单调改善后,依据 V13/V15 在 step 2500 停止长跑改做退火。

step val KL t30k KL choice top-1 score MAE noul AUROC ECE ood KL 翻转率
B0 0.485 0.510 0.532 1.130 0.824 0.094 0.857 38%
500 0.094 0.081 0.817 0.224 0.977 0.022 0.296 11.2%
1500 0.038 0.040 0.861 0.151 0.991 0.0025 0.235 6.8%
2000 0.0325 0.037 0.865 0.143 0.992 0.004 0.253 5.3%
2000+退火 500 0.026 0.0276 0.884 0.119 0.994 0.0014 0.208 4.7%

8.3 验收(test_set_30k,温度后)—— 见 §0 表;完整切片见 reports/eval_s2_9b.md

按 source×kind:yuri_v3 choice KL 0.05 / openjev choice KL 0.25(snake 等程序化任务最难,top-1 0.84);yuri_v1 占位切片 KL ≈ 0.01(模型输出接近 0.5/0.5)。

8.4 两项未达标的判定

  1. choice top-1 0.884 < 0.90:教师软标签天花板(V15)。在教师有明确倾向的 86% 行上一致率 0.918,与"完美镜像"的差距仅 4%(0.682 vs 0.709 教师质量)。判定:模型已足够忠实;若要冲 0.90 需继续训练 ~5 h 且边际收益 ≤2 点。建议下一版把该指标改为"教师 top-2 间距 ≥0.1 行上的 top-1 ≥ 0.90"(当前 0.918 ✅)。
  2. ood KL 退化比 7.5 > 2.0:域内 KL 压到 0.028 后比值必然膨胀(B0 时 1.68 只是因为域内也差)。ood 绝对 KL 从 0.857 降到 0.208、top-1 0.52 → 0.916、noul AUROC 0.69 → 0.985。建议改为绝对指标(ood KL ≤ 0.30 且 top-1 ≥ 0.85)。

9. 推理服务(bf16,exports/jev-judge-qwen35-9b)

项 值
形态 纯文本权重 4 shards 15.9GB(LoRA 已合并,不含 vision/mtp/lm_head)+ head.safetensors + judge_config.json + calibration.json + tokenizer
显存 ≈ 17GB
延迟(B200 独占) 单请求 p50 87 ms(无合批)/ 111 ms(合批窗口 4 ms);batch 128 → 2.5 ms/决策;8 并发 32 req/s p50 251 ms
强约束 分布和 1±1e-4;options 回显对齐;缺温度表 fail-fast;低置信度(归一化熵 >0.9)打日志不改响应

10. 工程结构与命令 —— 见 README.md

11. 风险与状态

风险 缓解 状态
yuri_v1 均匀占位(D1) 训练降权 0.05;校准排除;评估双口径 ✅
bf16 舍入破坏等价性 fp32 重算门禁 + 头恒 fp32 ✅ 9B/27B PASS
fla/causal_conv1d 快核 fla OK;conv 回退 torch ✅ 可接受
激活显存超预期(10MB/tok) ckpt + token 预算 micro-batch ✅
高 LR 处停训 500 步退火 ✅ −25% KL
教师 choice 软标签天花板 间距分层报告;建议改指标 📝 已记录
A1 契约字段差异 上线前与真实 Jev diff ⏳ 待办
27B 仅当 9B 不满足业务需求时启用(configs/train_27b.yaml,门禁已过) 🟢 条件项

12. 里程碑(v0.7)

# 内容 状态
M0 剥塔加载 / 对表 / 口头词 / 等价性门禁(9B、27B)/ B200 吞吐 / B0 ✅ reports/m0_qwen35_9b.md, reports/b0_qwen35_9b.md
M1 数据审计 + D1 + 长度 + parquet ✅ reports/data_audit.md
M2 模板定案 ✅ 沿用 v0.6 裸文本;分词改整串
M3 S2 主跑 + 阶段检查 ×3 + 退火 ✅ reports/review/step{0500,1500,2500}.md
M4 温度校准 + 全量评估 ✅ reports/eval_s2_9b.md(5/7 达标,2 项判定为指标问题)
M5 导出 + 服务 + 契约测试 + 压测 ✅ exports/jev-judge-qwen35-9b,7/7
M3b 10% 超参扫描 🟡 后台进行中
— 27B ⏸ 条件项

附录 A:头初始化等价性 —— 同 v0.6(qwen3_5 无 softcap,精确成立;9B 实测 8.6e-07,27B 4.5e-07)

附录 B:槽位/口头词总表 —— 同 v0.6;9B/27B tokenizer 均通过单 token 与行首一致性校验(reports/m0_qwen35_9b.md)