【免费下载链接】d1a-e2b-it-qat-4bit
想真正读懂 Gemma 4 E2B 的架构设计吗?d1a-e2b-it-qat-4bit 是一个绝佳的"解剖标本":它是面向 Apple Silicon 的 MLX 4-bit 量化模型,完整保留了 Gemma 4 E2B 的滑动注意力、131K 长上下文和双量化策略(QAT 权重 4-bit + 分组嵌入量化),仅 2.7 GB 即可在 M 系列芯片上跑起一个多模态决策模型。这篇文章带你从配置文件出发,逐层拆开它的设计。
先认识项目:一个"只做判断"的决策模型
d1a-e2b-it-qat-4bit 并不是普通的聊天模型。它的核心玩法是:
- 给它一份文档 + 若干问题(是非题、选择题或打分题);
- 模型一次前向推理就为每个选项返回校准过的概率;
- 不生成任何文本,因此每个答案必然是一个合法选项,天然适合自动化流水线(比如 PR 标签、工单路由)。
同一套权重还"兼职"两个身份(见 README.md):
| 角色 | 说明 | 大小 |
|---|---|---|
| 决策模型 D1A | 挂载 LoRA 适配器 + 指针头,输出选项概率 | 97 MB 适配器 |
| 聊天模型 | 关掉适配器,就是原版 Gemma 4 E2B-it QAT | 2.7 GB |
| 多模态输入 | 照片、语音、视频走 media/ 编码器 | 1.0 GB |
📌 换句话说:一个模型,三种用法,全部本地推理。
滑动注意力:35 层里藏着的"28+7"节奏
打开 config.json,text_config 段落信息量很大。先看层结构(config.json#L107-L143):
- 总共 35 层(
num_hidden_layers: 35); layer_types是 28 层sliding_attention+ 7 层full_attention;- 全注意力层固定在第 5、10、15、20、25、30、35 层(0 起始索引 4/9/14/19/24/29/34),大约每隔 5 层出现一次。
这是什么思路?打个比方:
滑动注意力层像"速读者"——只回头看最近 512 个 token(
sliding_window: 512),处理局部语义又快又省;全注意力层像"总编辑"——通读全文,负责跨段落的长程关联。
这样交替排布带来两个直接好处:
- KV 缓存大幅缩水:大部分层只需缓存窗口内的 512 个 token,显存占用和推理延迟都下降(README 实测比 8-bit 版快 11%);
- 局部计算量恒定:无论上下文多长,28 个滑动层的计算成本基本不变,长文本的开销主要由 7 个全注意力层承担。
还有一个容易忽略的细节——rope_parameters 里配了两套旋转位置编码:
- 全注意力层:
rope_theta: 1000000.0、rope_type: proportional、partial_rotary_factor: 0.25,为超长距离设计; - 滑动层:
rope_theta: 10000.0、默认类型,服务于短窗口。
局部和全局各用一套"坐标系统",这正是混合注意力架构的典型配套设计。
131K 上下文:131072 个 token 是怎么做到的
max_position_embeddings: 131072——这就是标题里的 131K 上下文(约 128K token,相当于一本长篇小说)。小模型能撑住这么长的窗口,靠的是几个"省 KV"设计:
| 参数 | 值 | 作用 |
|---|---|---|
num_key_value_heads | 1 | 极致 GQA:8 个注意力头共享 1 个 KV 头,KV 缓存压到最小 |
num_kv_shared_layers | 20 | 层间共享 KV,35 层中 20 层复用缓存 |
hidden_size / intermediate_size | 1536 / 6144 | 小隐藏层,单 token 状态开销低 |
use_double_wide_mlp | true | 用更宽的 MLP 补偿小隐藏层的表达力 |
配合前面的滑动窗口,长上下文的实际成本被压得很低。另外 head_dim: 256、num_attention_heads: 8、词表大小 vocab_size: 262144,总参数量约 4.6B(见 model.safetensors.index.json 的 metadata),是典型的"端侧友好"体量。
⚠️ 小提示:模型训练时每条记录开头都带 <bos>(id 2),自己编码请求的应用需要手动加上,d1a_config.json 中的 leading_ids: [2] 就是干这件事的。
双量化策略:QAT 的 4-bit 权重与两套分组
"Gemmma 4 E2B 的量化"是这个仓库最硬核的部分,quantization 配置(config.json#L60-L89)揭示了"双"的由来:
第一重:权重 4-bit、激活 16-bit(w4a16)
- 底模是 Google 官方 量化感知训练(QAT) 的 int4 检查点,276 个线性层全部以 int4 存储,
mode: affine(对称 + 缩放/偏置); - 仓库按位原样搬进 MLX 4-bit,没有从 bf16 重新量化,反量化误差为 0;
d1a_config.json中的"grid": "ct-int4"表示使用 QAT 自定义量化网格,而非普通对称网格。
第二重:两种分组大小(group_size)
| 组件 | 位宽 | 分组 | 说明 |
|---|---|---|---|
| 276 个线性层 | 4-bit | group 32 | QAT 直接训练出来的粒度 |
embed_tokens | 4-bit | group 64 | 词表嵌入 |
embed_tokens_per_layer | 4-bit | group 64 | Gemma 4 特有的逐层嵌入(配合 hidden_size_per_layer_input: 256 的逐层输入投影) |
为什么嵌入要用更大的组?因为 QAT 只优化了线性层的 32 分组,嵌入层若沿用 32 分组会损失更多信息;放大到 64 分组后体积还能再小 0.17 GB,精度几乎无损。
💡 更关键的一步:D1A 适配器在 QAT 主干上重新训练了。因为 QAT 权重与 bf16 权重并不相同(余弦相似度 0.992),旧适配器直接搬过来会导致 9.6% 的明确答案发生变化、三个基准平均掉 1~3 个点。重训用的是 LoRA(rank 16,见 adapter/adapter_config.json),适配器保持未合并状态放在 adapter/ 目录——关掉它,模型就变回原生 Gemma 4 E2B 聊天模型,一套权重两用。
多模态:1.0 GB 的视觉与音频编码器
media/ 目录装的是 Gemma 4 的视觉和音频编码器(bf16,约 1.0 GB),配置见 media/config.json:
- 视觉编码器:16 层 Transformer,
hidden_size: 768,patch_size: 16,每张图片编码为 280 个软 token(vision_soft_tokens_per_image: 280)注入文本序列; - 音频编码器:12 层,
hidden_size: 1024,带卷积下采样(conv_kernel_size: 5)和 logit cap 50,专为短语音片段优化; - 这两个编码器与 E2B-it 版本基本相同,唯一例外是视觉投影层——因为文本主干换成了 int4,投影层被 QAT 重新训练过以对齐。
实测表现:playground 的 14 条图片/语音/视频请求全部有响应,中位延迟 1.6 秒/条,其中 25/28 的答案与 8-bit 版完全一致。
校准与成绩单:概率"说到做到"
决策模型的核心竞争力是校准(calibration)——概率 0.67 就该有约 67% 的把握。d1a_config.json 记录了校准温度 1.55 的完整拟合过程(5 折交叉验证,3178 条样本),效果:
期望校准误差 ECE:0.064 → 0.018,置信错误率从 4.3% 降到 2.1%。
对照上一版(v0.6 bf16 主干)的成绩单(详见 README 的 Scorecard 章节):
| 指标 | 结果 |
|---|---|
| 22 个套件、17,418 题综合 | +0.40 分 |
| PR 严重度(新 PR) | +3.5 分 |
| PR 标签 | +1.7 分 |
| transfer-v4(训练外的任务类型) | −5.2 分 ⚠️ |
| 单决策延迟 | 快 11% |
注意那条显著负项:模型对没见过的任务类型会明显变弱,这也是发布时官方给的明确警告——任务偏离 D1A 训练分布时,应固定使用 v0.6。
快速上手:Apple Silicon 三步跑起来
依赖 d1a 框架,两条命令即可起服务:
pip install "d1a[serve,mlx,media]"
python -m d1a.serving.serve --run mlx-community/d1a-e2b-it-qat-4bit --port 8009
三个端点各司其职:
- 决策:
POST /v1/systemone,传入状态描述 + 问题,返回每个选项的校准概率; - 多模态:
POST /v1/systemone/media,多一个media字段(图片 / ≤30 秒音频 / ≤32 MB 视频); - 聊天:
POST /v1/chat/completions(OpenAI 兼容、支持流式),自动关闭适配器,采样默认值见 generation_config.json:temperature 1.0、top_k 64、top_p 0.95。
关键文件导航:跟着配置读懂架构
| 文件 | 看什么 |
|---|---|
| config.json | 主干架构:层类型、滑动窗口、RoPE、QAT 量化参数 |
| d1a_config.json | D1A 适配器、校准温度 1.55 及其交叉验证记录 |
| adapter/adapter_config.json | LoRA 细节:rank 16、alpha 32、7 个目标投影层 |
| media/config.json | 视觉/音频编码器结构 |
| model.safetensors.index.json | 权重清单:2.7 GB、4.6B 参数、1096 个张量 |
| tokenizer_config.json | 多模态特殊 token(<|image|>、<|audio|>、<|video|>)与工具调用模板 |
| chat_template.jinja | 对话与 thinking/tool 消息的渲染模板 |
小结:这套架构值得学的三点
- 混合注意力排布:28 滑动 + 7 全注意力、512 窗口,用不到四分之一层的成本换来 131K 上下文的低成本推理;
- QAT 端到端一致:从 Google 的 int4 训练检查点逐位搬运、适配器在同一量化主干上重训,"你训练的就是你跑的",避免了事后量化带来的隐性掉点;
- 双分组量化:线性层 32 组、嵌入 64 组,按组件敏感度分配精度,2.7 GB 装下 4.6B 参数。
对想深入的同学,建议按 config.json → d1a_config.json → media/config.json 的顺序通读一遍——所有架构细节都在这里明码标价,这正是 d1a-e2b-it-qat-4bit 作为"教学样本"的最大价值。
【免费下载链接】d1a-e2b-it-qat-4bit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



