Some checks failed
CI / build-and-test (push) Has been cancelled
- E4B-MarkBase model (42 layers, 4.4GB) loaded successfully - All Phase 1-6 tests passed (model loading, forward pass, vision/audio towers, token generation, performance) - All stress tests passed (5/5 in 127.6s) - Concurrent inference - Memory stress (67.5 tok/s, 0 NaN) - Continuous generation - Batch processing - Long-running stability - Swift Metal inference engine with multimodal support
8.3 KiB
8.3 KiB
Gemma-4 26B 测试结果报告
测试状态: 需要格式适配 ⚠️
测试时间: June 19, 2026
模型位置: /Users/accusys/.cache/huggingface/hub/models--mlx-community--gemma-4-26b-a4b-mxfp4/
模型大小: 14.8 GB (3 shards)
测试结果
文件检查 ✓
✓ Config.json: 存在
✓ Tokenizer.json: 30 MB
✓ Weights shard 1: 5063 MB
✓ Weights shard 2: 5075 MB
✓ Weights shard 3: 4011 MB
✓ Total: 1283 tensors
加载尝试 ⚠️
✓ Engine created
✓ Found 3 safetensors shards
✗ Error: unsupportedDtype("Embed tokens not quantized")
问题分析
主要问题
错误: Embed tokens not quantized
原因: MLX 格式与我们的格式不兼容
具体差异
1. 权重命名差异
MLX 格式:
language_model.model.embed_tokens.weight
language_model.model.layers.0.experts.switch_glu.down_proj.weight
language_model.model.layers.0.input_layernorm.weight
我们的格式:
embed_tokens.weight
layers.0.down_proj.weight
layers.0.input_layernorm.weight
2. Embed tokens 格式
MLX 26B:
embed_tokens.weight: uint32 [262144, 352]
embed_tokens.scales: uint8 [262144, 88]
我们期望:
embed_tokens.weight: uint32 (quantized)
embed_tokens.scales: uint32 (BF16 scales)
embed_tokens.biases: uint32 (BF16 biases)
3. MoE 结构
MLX 26B 有 MoE (Mixture of Experts):
layers.0.experts.switch_glu.down_proj
layers.0.experts.switch_glu.gate_proj
layers.0.experts.switch_glu.up_proj
我们的代码不支持 MoE 专家路由
4. Config 结构
MLX config:
{
"text_config": {
"hidden_size": 2816,
"num_hidden_layers": ?,
"enable_moe_block": true,
...
}
}
我们期望:
{
"hidden_size": 2816,
"num_hidden_layers": ?,
...
}
详细对比
模型架构
Gemma-4 26B MLX:
Model type: gemma4
Architecture: Gemma4ForConditionalGeneration
Hidden size: 2816 (比 12B 的 2560 大)
Intermediate size: 2112
MoE blocks: enabled
Experts: 128 experts per layer (推测)
我们的 E4B-MarkBase:
Model type: gemma4
Architecture: Gemma4ForConditionalGeneration
Hidden size: 2560
Intermediate size: 10240
MoE: disabled (dense layers)
权重对比
| Component | MLX 26B | 我们的 E4B |
|---|---|---|
| Embed tokens | uint32 + uint8 scales | uint32 + BF16 scales/biases |
| Layers | language_model.model.layers.X | layers.X |
| MoE | experts.switch_glu | dense MLP |
| Vision | embed_vision.embedding_projection | vision_tower.X |
格式差异
量化格式:
MLX mxfp4:
- weight: uint32 (packed 4-bit)
- scales: uint8 (8-bit)
- 无 biases
我们的标准 4-bit:
- weight: uint32 (packed, group_size=64)
- scales: uint32 (BF16)
- biases: uint32 (BF16)
解决方案
方案 1: 转换模型格式 (推荐)
步骤:
1. 下载并转换
from safetensors.torch import load_file, save_file
import torch
# Load MLX model
mlx_dir = "/Users/accusys/.cache/huggingface/hub/models--mlx-community--gemma-4-26b-a4b-mxfp4"
weights = {}
for shard in ["model-00001-of-00003.safetensors", ...]:
w = load_file(f"{mlx_dir}/{shard}")
weights.update(w)
# Rename weights
renamed = {}
for key, tensor in weights.items():
# Remove language_model.model prefix
new_key = key.replace("language_model.model.", "")
renamed[new_key] = tensor
# Convert MoE to dense (可选)
# 或保留 MoE 并实现路由
# Convert scales format
# uint8 → BF16 uint32
# Save as single file
save_file(renamed, "gemma-4-26b-converted.safetensors")
2. 创建适配的 config.json
{
"model_type": "gemma4",
"architectures": ["Gemma4ForConditionalGeneration"],
"hidden_size": 2816,
"num_hidden_layers": 42,
"vocab_size": 262144,
"quantization_config": {
"bits": 4,
"group_size": 64
}
}
3. 测试加载
swift run G12BServer /path/to/converted-26b 8080 gemma-26b
优点:
- ✓ 可以加载
- ✓ 性能优化
- ✓ 与现有代码兼容
缺点:
- 需要转换时间
- MoE 仍需额外实现
- 需要足够 memory
方案 2: 适配代码支持 MLX
需要修改:
1. 权重加载
// Sources/G12B/Model.swift
// 支持两种命名格式
let weightName = {
if tensorName.hasPrefix("language_model.model.") {
return tensorName.replacing("language_model.model.", with: "")
}
return tensorName
}()
2. Scales 格式
// 支持 uint8 scales
if scalesTensor.dtype == .uint8 {
// 转换为 BF16
scales = convertUint8ToBfloat16(scalesTensor)
}
3. MoE 支持
// 新增 MoE 路由实现
struct MoERouter {
func route(input: MTLBuffer, experts: [Expert]) -> MTLBuffer {
// 专家路由逻辑
}
}
struct Expert {
let down_proj: QuantizedWeights
let gate_proj: QuantizedWeights
let up_proj: QuantizedWeights
}
优点:
- ✓ 直接支持 MLX
- ✓ 无需转换
- ✓ 支持更多模型
缺点:
- 需要较多代码修改
- MoE 实现复杂
- 测试工作量
方案 3: 下载标准版本
等待官方或社区提供:
- 标准 4-bit quantized 格式
- 无 MoE 或 MoE 已转换
- 命名符合标准
来源:
- HuggingFace 标准量化版本
- 自行量化官方模型
- 社区转换版本
优点:
- ✓ 无需修改代码
- ✓ 直接可用
- ✓ 官方支持
缺点:
- 可能不存在
- 需要等待
- 需要自己量化
Memory 需求估算
26B Memory 分析
权重大小:
26B parameters × 0.5 bytes (4-bit) = 13 GB
Embed tokens (可能未量化): +1 GB
Vision tower: +0.5 GB
Total weights: ~14.5 GB
运行时 Memory:
Weights: 14.5 GB
KV Cache (128 context): 0.5 GB
Activations: 1-2 GB
Total: ~17 GB
Mac 要求:
M3 Pro (36GB): ✓ 充足
M3 Max (48GB): ✓ 充足
M4/M5 (64GB+): ✓ 完全充足
M1/M2 Max (24-32GB): ⚠ 勉强
推荐路径
立即可行
短期 (1-2天):
- 转换现有 MLX 26B 为标准格式
- 转换 scales uint8 → BF16
- 重命名权重
- 测试加载
长期支持
中期 (1-2周):
- 实现 MLX 格式直接支持
- 实现 uint8 scales 支持
- 权重命名自动适配
长期 (1-2月):
- 实现完整 MoE 支持
- 专家路由优化
- 分布式 MoE 推理
下一步行动
Option A: 快速转换 (推荐)
1. 编写转换脚本 (Python):
python convert_mlx_26b.py \
--input ~/.cache/huggingface/hub/models--mlx-community--gemma-4-26b-a4b-mxfp4 \
--output ~/models/gemma-4-26b-standard \
--rename \
--convert-scales
2. 测试加载:
swift test --filter test26BModelLoading
3. 性能测试:
swift run G12BServer ~/models/gemma-4-26b-standard 8080 gemma-26b
Option B: 代码适配
1. 支持双重命名:
// 修改 Model.swift 支持两种格式
2. uint8 scales 转换:
// 在加载时转换格式
3. 测试验证:
swift test
结论
当前状态: 26B 模型存在但格式不兼容
问题: MLX 格式 vs 我们的标准格式
解决方案:
- ✓ 方案1: 转换格式 (最快)
- ⚠️ 方案2: 适配代码 (需要工作量)
- ⏳ 方案3: 等待标准版本 (可能不存在)
推荐: 方案 1 - 转换格式
预计时间: 1-2天完成转换和测试
Memory 要求: M3 Pro/Max 或更高 (36GB+)
附录
MLX 权重列表 (部分)
language_model.model.embed_tokens.weight [262144, 352] uint32
language_model.model.embed_tokens.scales [262144, 88] uint8
language_model.model.layers.0.experts.switch_glu.down_proj.weight [128, 2816, 88] uint32
language_model.model.layers.0.experts.switch_glu.down_proj.scales [128, 2816, 22] uint8
language_model.model.layers.0.input_layernorm.weight [2816] bfloat16
language_model.model.layers.0.layer_scalar [1] bfloat16
...
embed_vision.embedding_projection.weight [...] uint32
embed_vision.embedding_projection.scales [...] uint8
需要的转换脚本功能
Python script:
- Load MLX safetensors shards
- Rename weights (remove language_model.model prefix)
- Convert uint8 scales to BF16
- Flatten MoE structure (可选)
- Merge into single safetensors
- Generate standard config.json
- Copy tokenizer files
报告生成: June 19, 2026 测试结果: 格式不兼容,需要转换 建议: 转换 MLX 格式为标准格式