从零复现EVIE-4.5B:8B教师模型双臂训练与Soup权重合并实战教程

从零复现EVIE-4.5B:8B教师模型双臂训练与Soup权重合并实战教程

本文带你从零复现 EVIE-4.5B——腾讯开源的轻量级视觉文档检索(Visual Document Retrieval)模型。你将亲手完成 8B 教师模型的双臂(two-arms)训练、Soup 权重合并,以及 Prefix-MRL + ARD 学生模型蒸馏全流程。整篇文章跟着官方脚本一步步执行,新手也能跑通。

EVIE(Evidence-Vector-Informed Embedding)采用 Late-Interaction 多向量范式:文档页面和查询文本都被编码为 token 级向量,通过 MaxSim 逐 token 匹配打分,因此能保留表格、图表、小字排版等细粒度视觉信息,在 ViDoRe V3 榜单上以 66.02 分登顶开源梯队。

仓库结构与复现路线一览

仓库本身就是"模型权重 + 完整训练管线"二合一,复现所需的每一环节都有对应目录:

模块路径作用
教师模型训练code/teacher/EVIE-8B 双臂训练 + Soup 合并入口
学生模型训练code/student/EVIE-4.5B Prefix-MRL + ARD 蒸馏
共享工具code/shared/数据加载、权重合并、138 任务评测
压缩管线code/compress/免训练 HAC token 压缩
检索引擎colpali/ColQwen3.5 模型实现与 ARD 损失

复现主线只需三条命令(来自 README.md):

bash code/teacher/run.sh # 第1步:训练8B教师双臂并合并Soup bash code/student/run.sh # 第2步:蒸馏4.5B学生模型 bash code/shared/eval_run.sh # 第3步:138任务全面评测

环境准备:一键配置环境变量

克隆仓库并安装依赖:

git clone https://gitcode.com/tencent_hunyuan/EVIE-4.5B cd EVIE-4.5B pip install -r requirements.txt

关键一步是初始化环境变量。仓库提供了模板 env.sh.example,它定义了四个核心路径变量:

  • DATA_ROOT/HARDNEG_ROOT:训练数据与难负例根目录(默认指向examples/toy玩具数据,真实训练需替换)
  • RUNS_DIR:所有模型产出目录(checkpoint、Soup 模型)
  • EVAL_ROOT:评测任务数据根目录
  • EVIE_8B_DIR/TEACHER_DIR:教师模型权重位置
cp env.sh.example env.sh source env.sh

这些路径由 code/shared/lib.sh 中的evie_workdirs统一解析,并禁止把 checkpoint 写进 venv 目录,避免常见坑。

第1步:8B教师模型双臂训练实战

什么是"双臂训练"?

EVIE-8B 并不是只训练一次,而是用同一套超参配方、不同难负例(hard-negative)数据分片并行训练两个模型,称为 Arm A 和 Arm B:

臂运行名(默认)难负例分片
Arm Aevie-8b-d4096_mvt1024_s42-judgedjudged(人工/模型判定的精选难负例)
Arm Bevie-8b-d4096_mvt1024_s42-allposallpos(全部正例参与构造)

编排逻辑全部写在 code/teacher/run.sh:脚本以for RUN_NAME in "$ARM_A" "$ARM_B"循环依次调用 code/teacher/scripts/launch.sh,任一臂失败则跳过合并直接退出,保证产物可追溯。

核心训练超参速查

两臂共用以下关键配置(默认值来自 launch.sh):

  • COL_DIM=4096:教师模型单头投影维度
  • MVT=1024:最大视觉 token 数
  • EPOCHS=1、EFF_BATCH=512(有效批大小,梯度累积自动计算)
  • LR=4.57e-5、LORA_R=32、LORA_ALPHA=128(LoRA 微调)
  • NUM_HARD_NEGS=2、HARDNEG_IN_BATCH_WEIGHT=0.5:难负例数量与 batch 内负例权重
  • BIDIR=on:双向注意力(编码器化改造,Late-Interaction 的精髓)

底层训练脚本为 code/teacher/scripts/train.py,它基于ColbertNegativeCELoss对比损失,并用torch.distributed.run拉起多卡进程。

第2步:Soup权重合并——为什么默认α=0.4

两臂训练完成后,run.sh会自动调用 code/shared/merge_seeds.py 做Soup 合并:

  1. 将两个 LoRA adapter 分别merge_and_unload到基座 Qwen3.5 上;
  2. 对完整state_dict按权重加权平均,教师默认ALPHA=0.4(Arm A 占 0.4,Arm B 占 0.6);
  3. 以 float32 累加保证精度,最终存为 bfloat16,并写入run_config.json记录soup_arms、merge_weights等元信息。

合并前脚本会做配方契约校验(CONTRACT字段列表):两臂的学习率、LoRA 配置、损失温度等任何一项不一致都会直接报错,从机制上杜绝"错误合并"。

💡 想扫更多权重组合?使用 code/teacher/merge_alpha.sh,设置ALPHAS="0.3 0.4 0.5"即可批量生成多个 Soup 并逐个评测,找到最优 α。

合并产物输出到$RUNS_DIR/evie-8b-d4096_mvt1024_s42/,训练+合并+评测一条龙完成后可直接作为学生蒸馏的教师权重。

第3步:学生模型蒸馏(Prefix-MRL + ARD)

ARD损失:锚点保持的容量感知关系蒸馏

4.5B 学生从冻结的 8B 教师学习,核心是 colpali/colpali_engine/loss/ard.py 中的 ARD 损失,由三部分组成:

  • Relation Distillation(RELATION_WEIGHT=1.0):对齐师生 MaxSim 矩阵的行/列关系拓扑(KD_DIRECTIONS=both)
  • Margin Distillation(MARGIN_WEIGHT=0.25):回归教师给出的难负例分数间隔
  • Anchor Alignment(ANCHOR_WEIGHT=0.25):用 EVIE-Preview 权重锚定 128D 前缀,防止低维退化

Prefix-MRL弹性多头

学生只训练一个 2048D 线性投影,运行时可自由截断为 64/128/256/512/1024/2048 维,无需维护多套模型。相关配置集中在 code/student/run.sh:

export TEACHER_DIR=../Evie-8B # 指向第2步合并出的教师模型 bash code/student/run.sh

学生同样是双臂结构(allpos+judged),但合并策略是等权平均(不带--weights,即full_state_dict_mean),基座为tencent/EVIE-Preview-4.5B热启动,学习率降为1.5e-5(见 code/student/scripts/launch.sh)。

验证成果:评测与HAC压缩

一键评测

评测统一走 code/shared/eval_run.sh,它会自动读取run_config.json中的head_dims,对每个前缀维度分别跑评测并输出到eval/d{dim}/summary.json,最后用aggregate_heads.py汇总。完整 138 任务矩阵(ViDoRe V1/V2/V3 + JinaVDR)参考输出:EVIE-4.5B 在 nDCG@10 上取得 V1 92.53 / V2 74.91 / V3 66.02。

先玩demo再上生产

没有大评测集?仓库内置了 8 页文档的演示,跑一下就能直观看到检索效果:

bash examples/demo/run.sh

它会对 examples/demo/pages/ 下的 8 张文档页(财报、发票、架构图、报错日志等)做嵌入与 MaxSim 打分。

可选:HAC token压缩

原始表示每页约 750 个向量,code/compress/run.sh 提供免训练 HAC(层次凝聚聚类)压缩,默认配方d64 × K32把每页压到 32 个向量,百万页索引仅 3.81 GiB,同时保留 73.47 的 Avg4 分数——生产部署强烈推荐。

常见问题排查

现象原因与解法
[fatal] set DATA_ROOT未source env.sh,或DATA_ROOT仍指向 toy 数据(正式训练需换成真实 dump)
recipe mismatch合并报错两臂超参不一致,检查COL_DIM、SEED、难负例分片是否按默认配对
输出目录非空被拒脚本默认拒绝覆盖半成品,OVERWRITE=1强制重跑,旧目录会自动归档
显存不足调小BSZ、开GRAD_CHECKPOINTING=on;多节点时通过NNODES/MASTER_ADDR扩展
想只训一臂省资源ARMS="a" DO_MERGE=0(学生脚本)即可跳过 B 臂与合并

总结

至此你已经完整走通了 EVIE-4.5B 的复现链路:双臂差异化训练 → Soup 加权合并 → ARD 蒸馏 → 多头评测 → HAC 压缩。这条管线设计得非常工程化:契约校验防错、断点续跑、rank 0 统一合并、评测自动聚合,非常适合学习大模型检索系统的训练最佳实践。动手前先把env.sh配好,从 teacher 开始,一条命令一个阶段,稳定且可复现。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考