colibri 模型准备与离线工具链实战:FP8 重打包、格式转换与量化一致性验证
发布时间:2026/9/12 4:55:08 作者:尧图编辑部 阅读量:1,286

colibri 模型准备与离线工具链实战FP8 重打包、格式转换与量化一致性验证【免费下载链接】colibriRun frontier MoE models on hardware you already own — pure C, zero deps, experts streamed from disk. Tiny engine, immense model. 项目地址: https://gitcode.com/GitHub_Trending/colibri3/colibri导读本文以 colibri 仓库中 c/tools/README.md 为骨架完整梳理 colibri 的模型准备model preparation与离线工程工具链从 Z.ai GLM-5.2-FP8 原始 checkpoint 出发经过 FP8 逐字节保真重打包fmt8、FP8→int4 有损转换、fmt4分组 int4→fmt2逐行 int4的 Metal 兼容再量化再到确定性小模型 oracle / bench fixture 的生成、tokenizer 表生成与离线评测。读完本文你将掌握这些脚本的适用场景、命令行用法、格式判别规则与源码级实现原理并理解这些工具如何与 C 引擎的qt_resolve_fmt、qt_from_disk等读取侧逻辑形成“写侧拒绝、读侧验证”的一致性闭环。# 在 c/ 目录下运行全部工具 cd c/ python3 tools/convert_fp8_to_int4.py --selftest python3 tools/make_glm_bench_model.py --output /tmp/colibri-bench这些脚本均不是 C 引擎的运行时依赖只服务于离线准备、格式研究与质量验证不会影响./colibri的正常启动与推理。工具总览与分类c/tools/README.md将工具按职责划分为四类对应不同生命周期阶段类别工具用途模型准备convert_fp8_to_int4.py、download_glm52.py下载 GLM-5.2-FP8 shard 并转换到引擎原生 int4 容器格式迁移convert_fmt4_to_fmt2.py、repack_fp8_passthrough.pyfmt4→fmt2 再量化、fmt8 逐字节保真重打包确定性 fixturemake_glm_oracle.py、make_glm_bench_model.py生成 token 级一致的 oracle 与可重复的 bench 模型基准与评测benchmark_cuda_fixture.py、eval_glm.py、fetch_benchmarks.pyCPU/CUDA A/B 基准、离线 log-likelihood 质量评测Tokenizer 支持gen_unicode.py由 Pythonunicodedata生成 C 头文件tok_unicode.h模型准备从原始 FP8 checkpoint 到引擎原生容器下载 GLM-5.2-FP8 权重download_glm52.py 面向zai-org/GLM-5.2-FP8FP8 e4m3、141 个 shard、约 756 GB。脚本强制通过环境变量GLM_DIR指定落盘位置避免权重落到继承的工作目录用GLM_REVISION环境变量钉住上游 commit SHA防止上游被篡改后静默换掉已下载的权重GLM_DIR/data/glm52 python3 tools/download_glm52.py # 下载全部 shard可断点续传 python3 tools/download_glm52.py --check # 只做空间估算与文件计数--check模式通过HfApi().repo_info汇总仓库总大小并与目标盘剩余空间比对需要 1.05 倍余量。下载完成后权重以F8_E4M3*.weight_scale_inv128×128 块尺度的布局落地这正是引擎st.h加载器与转换器期望的输入格式。FP8 → int4磁盘安全的分阶段转换convert_fp8_to_int4.py 是“STADIO B”转换器采用磁盘安全策略下载一个 shard约 5 GB→ 立即转换为 int4 → 删除源 shard → 处理下一个全程磁盘峰值只有 1 个 shard 加逐渐增长的 int4 输出约 372 GB并带空间不足即停的检查。每个张量的处理规则见模块内dequant/classifyFP8e4m3权重 weight_scale_inv→ 按 128×128 块反量化到 f32BF16 权重norm/embed/lm_head 等→ 转 f32注意力/MLP/shared/expert/embed/lm_head → 量化为 int4或 int8量化数学与 C 引擎完全一致np.rint对应lrintf同阈值、同 nibble 打包保证 token 级一致norm / routermlp.gate.weight/ bias /e_score_correction_bias→ 保持 F32DSA indexer / MTP 层第 78 层/shared_head/eh_proj等 → 跳过。量化原语convert_fp8_to_int4.py包含quant_int8、quant_int4逐行尺度、quant_int4_grouped沿输入维每gs个元素一个尺度对齐 FP8 源的 128×128 块粒度、quant_int3_g64fmt53.5 bits/weight、quant_e8fmt6 E8/IQ3 点阵256 权重/98 字节3.0625 bpw先旋转行再做 IQ3 打包与quant_int2。它们统一被 quant_ablation.py 等消融脚本复用是引擎各量化格式的“参考实现”。典型用法# 本地 tiny oracle 转换无下载 python3 tools/convert_fp8_to_int4.py --indir glm_tiny --outdir glm_tiny_i4 --ebits 4 --io-bits 4 # FP8 反量化自测需 torch python3 tools/convert_fp8_to_int4.py --selftest # 真实场景下载转换删除shard 逐个进行 python3 tools/convert_fp8_to_int4.py --repo zai-org/GLM-5.2-FP8 --outdir /path/to/glm52_i4输出目录中的每个量化权重形如nameU8打包 nibblename.qsF32逐行尺度引擎可直接读取。fmt8FP8 逐字节保真重打包repack_fp8_passthrough.py 是工具链中最复杂的脚本与convert_fp8_to_int4.py的“反量化→再量化”路线相反它将 FP8 权重字节原样拷贝.view(torch.uint8)是纯位重解释仅把weight_scale_inv侧车重命名为引擎的.qs约定从而做到零额外量化损失、与源相同的 8 bits/weight 流式成本。适用场景与取舍它服务于把 GLM-5.2-FP8 原始 checkpoint 铸成独立可加载的模型目录routed experts占 checkpoint FP8 字节的大头与全部 resident 家族注意力投影含kv_b_proj、shared expert、dense-MLP 权重都以 fmt8 输出norm/router/embed/lm_head非 FP8以原始 BF16/F32逐字节拷贝纯 pass-through无.qs、无 stamp并复制加载器运行时必需的非张量文件config.json、tokenizer.json为必需项缺失则硬退出generation_config.json为 best-effort--mtp作为独立 pass把多 token 预测头model.layers.n_layers.*重打包进同一--outdir引擎靠张量名探测 MTPout-mtp-前缀只是人和工具间的约定。# 只扫描头部、打印选择清单不写任何字节 python3 tools/repack_fp8_passthrough.py --indir fp8_dir --outdir out --dry-run # 主 pass78 层 python3 tools/repack_fp8_passthrough.py --indir fp8_dir --outdir out --n-layers 78 # 主 pass MTP pass python3 tools/repack_fp8_passthrough.py --indir fp8_dir --outdir out --n-layers 78 --mtp重要限制目前该工具仅用合成 fixture 单元测试tests/test_fp8_repack.py 所述体系之外、由tools/glm_fp8_emit.py复刻真实 checkpoint 布局尚未对真实 Z.ai shard 做过整包重打包且铸出的kv_b_proj今天能加载但在引擎的 fmt8 absorbMLA 吸收支持落地前分支f8/absorb-fmt8任何走到批处理路径的解码都会响亮崩溃而非静默损坏——详见模块 docstring 与 docs/FORMATS.md。两个“设计雷区”与写侧拒绝引擎在读取时仅凭尺度数组几何区分 fmt8每 128×128 块尺度与 fmt1纯 int8 逐行尺度qt_resolve_fmt见 colibri.c。这带来两个碰撞形状THE DESIGN LANDMINE当O ceil(O/128)*ceil(I/128)即块尺度字节数nblkO*nblkI*4恰好等于逐行 int8 尺度字节数O*4时无 stamp 的 fmt8 张量会被静默读成 int8。GLM-5.2 的self_attn.o_proj.weight[6144,16384]正是真实实例全 checkpoint 普查中唯一一个 2-D 模糊形状SECOND DESIGN LANDMINEI98的单块 fp8 张量其权重字节数恰好与 fmt6E8/IQ3一致无 stamp 时读侧无条件拒绝。因此 repack_fp8_passthrough.py 在写侧实现了一整套结构性防线_check_geometry、_emission_stamp_gate、_check_stamp_budget与_canonicalize_metadata_order原则是**“拒绝而不是猜测”**对于不可 stamp 的张量routed experts读侧三个加载点都以stamped_nameNULL调用qt_resolve_fmt见 colibri.c碰撞形状直接拒绝可 stamp 的 resident 则打上元数据 stamp 后放行。stamp 与容器级格式声明colibri.fmt、colibri.container.formats写入 safetensors__metadata__读侧走 TRUST-VERIFY-REFUSE 路径。stamp 预算以容器级上限ST_FMT_STAMP_MAX 4096镜像 st.h跨 shard、跨 main/--mtp 两次 pass 合计校验。输出采用内容校验的断点续传清单.fp8pass-progress.json输入以 sizemtime_ns 指纹、输出以 sizesha256 校验输入中途变更会以InputChangedError中止防止两个来源混进同一个容器。fmt4 → fmt2为 Metal 后端迁移分组 int4convert_fmt4_to_fmt2.py 解决一个具体痛点Metal 后端在注意力/dispatch 入口拒绝 fmt4issue #585/#587而 fmt2逐行 int4是后端全支持的格式。转换后的容器在 docs/METAL-M1ULTRA-FMT2-REPORT.md 中有基准记录。两种格式的容器布局一致量化张量是扁平 1-D U8 数组name打包 nibble偏移二进制值 nibble − 8低 nibble 偶数元素外加扁平 1-D F32 伴随数组name.qs。引擎仅凭字节计数判别格式qt_resolve_fmtcolibri.cint4 权重字节数 O*I/2.qs为 O 个 float → fmt2O*ceil(I/64)个 float → fmt4。因此转换 把每个 fmt4 张量重写为恰好 O 个逐行尺度。逐张量分类依据权重字节/尺度 float 的元素数之比nb/nsnb 32 * ns→ fmt4 g64转换形状无关判别器nb O*I且ns O→ int8 逐行原样拷贝embed_tokens、lm_headnb O*I/2且ns O→ int4 逐行已合规原样拷贝其他任何情况 → 响亮中止。转换数学所有维度为 64 的倍数先反量化w[o,i] (nib[o,i] − 8) * qs[o*ng i//64]到 f32再用 convert_fp8_to_int4.py 中quant_int4的精确数学逐行再量化np.rint、absmax/7 且下限 1e-8、clip −8..7、8、低 nibble 偶数元素最后写扁平 U8[O*I/2] 恰好 O 个 float 的.qs引擎自动识别为 fmt2。O/I来自由 tensor 名 config.json推导的形状表覆盖 embed/lm_head、MLA 的 q_a/q_b/kv_a/kv_b/o_proj、前 3 层 dense MLP 与 MoE routed/shared experts每个张量在转换前都对照形状表断言字节/尺度计数。MTP shardout-mtp-*.safetensors逐行 int8整片字节拷贝。python3 -m pip install numpy safetensors python3 c/tools/convert_fmt4_to_fmt2.py --selftest python3 c/tools/convert_fmt4_to_fmt2.py --indir SRC --outdir DST --dry-run python3 c/tools/convert_fmt4_to_fmt2.py --indir SRC --outdir DST [--workers 8]工程细节expected_size()精确预测每个输出 shard 的字节数safetensors 序列化是确定性的中断后重跑会跳过尺寸已符合预期的输出 shard所有写入走.tmpos.replace中断不会留下半截 shard主进程按序写盘保证任意 worker 数输出字节一致。--selftest验证反量化往返误差、nibble 顺序与大小预测器对 10/10 种头部填充情况的命中。确定性 fixtureoracle 与 bench 模型make_glm_oracle.pytoken 级一致的量化奇偶门make_glm_oracle.py 生成一个真实架构MLA DSA indexer sigmoid/noaux_tc router shared expert、极小尺寸的随机权重 GLM-5.2 oracle序列短于index_topk使 DSA 选中全部 key从而让 C 引擎无需实现稀疏 indexer 也能验证 MLA 密集注意力。默认 bf16--fp8则以真实 GLM-5.2-FP8 布局e4m3 128×128scale_inv写权重并在计算参考前对模型做 FP8 往返使ref_glm.json精确反映转换器读到的 FP8 模型。--fmt6/--fmt4只量化 routed experts分别到 E8/IQ3 或分组 int4shared/dense/attn 保持 f32参考从反量化后的权重计算让引擎能逐 token 复现。脚本还硬性要求transformers 5.11更老版本对 GLM-5.2 的 MLA 施加了 split-halfLlama 风格RoPE而 C 引擎实现的是 interleavedDeepSeek 风格RoPE旧版本生成的 oracle 会让引擎只拿到 25/32 而非文档中的 32/32issue #281因此直接硬失败而非告警。E8 超块为 256 权重98 字节迫使 quantized fixture 使用 hidden256/moe_inter256f32 默认保持 128/32。python3 tools/make_glm_oracle.py --fmt6 # - glm_tiny_fmt6/ python3 tools/make_glm_oracle.py --fmt4 # - glm_tiny_fmt4/ # 验证引擎直接加载两种格式期望 32/32 SNAP./glm_tiny_fmt6 REF./glm_tiny_fmt6/ref_glm.json TF1 COLI_TEMP0 ./colibri 64 16 16 SNAP./glm_tiny_fmt4 REF./glm_tiny_fmt4/ref_glm.json TF1 COLI_TEMP0 ./colibri 64 16 16make_glm_bench_model.py可重复的 CPU/CUDA 基准 fixturemake_glm_bench_model.py 构建中等尺寸hidden1024、8 层、32 routed experts的确定性 GLM-MoE 模型保留真实数据流但足够小可在本地反复跑 CPU/CUDA A/B 而不必下载 379 GB checkpoint。它同时记录 prompt、生成结果与 logits 到ref_glm.json供 benchmark_cuda_fixture.py 等基准脚本比对。--fp8模式用与真实 GLM-5.2-FP8 相同的布局写权重从而让convert_fp8_to_int4.py在本地 fixture 上演练 FP8→int4 反量化路径python tools/make_glm_bench_model.py --fp8 --output glm_bench_fp8 python tools/convert_fp8_to_int4.py --indir glm_bench_fp8 --outdir glm_bench_i4 --ebits 4 --group-size 128基准与离线评测benchmark_cuda_fixture.pybenchmark_cuda_fixture.py 对make_glm_bench_model.py的输出做可复现的 CPU/CUDA A/B 基准用正则解析引擎输出的REPLAY decode ... tok/s吞吐、PROFILE:的 expert-disk/expert-matmul/attention/lm_head/other 时间分解以及PROF1的 P0-EXEC 执行层分解routed CPU/GPU 临界时间、router、P2P 跳数与编排。fetch_benchmarks.py 与 eval_glm.py离线 log-likelihood 评测fetch_benchmarks.py 一次性把 HellaSwag、ARC、MMLU、WinoGrande、PIQA、OpenBookQA 等标准任务转成统一 JSONL 格式每行{ctx,choices,gold}使评测完全离线、确定python3 tools/fetch_benchmarks.py --out ./bench --tasks hellaswag,arc_challenge,mmlu --limit 200eval_glm.py 使用多项选择的 log-likelihood每个选项一次 forward无生成因此低吞吐也能跑它自动为 GLM snapshot 在每条上下文前加[gMASK]sop前缀issue #108 指出裸文本打分是分布外、会压低分数可用EVAL_PREFIX覆盖# 机制 smoke 测试无引擎 python3 tools/eval_glm.py --snap /path/to/glm52_i4 --data ./bench --tasks smoke --dry # 真实验证 python3 tools/eval_glm.py --snap /path/to/glm52_i4 --data ./bench \ --tasks hellaswag,arc_challenge,mmlu --limit 40 --ram 15 # 把采样参数传给引擎 TOPP0.9 python3 tools/eval_glm.py --snap /path/to/glm52_i4 --data ./bench --tasks mmlu --ram 15Tokenizer 表生成gen_unicode.pygen_unicode.py 生成 tok_unicode.h把 GLM-5.2 pre-tokenizercl100k 正则所需的 Unicode 类别\p{L}、\p{N}与空白属性\sWhite_Space扫描成有序闭区间数组C 侧用二分查找判定。生成的头文件带“由 tools/gen_unicode.py 生成勿手工编辑”标记并提供is_L/is_N/is_S内联辅助函数python3 tools/gen_unicode.py tok_unicode.h从“写侧拒绝”到“读侧验证”的一致性设计贯穿全部离线工具的一条主线是格式判别的一致性引擎在读取时几乎从不读显式的格式字段而是靠张量字节计数/尺度几何推断int4 权重字节数、.qs元素数、I98等特征因此任何写侧工具都必须精确复刻读侧规则否则会铸出“引擎静默误读”的容器。为此工具链在每个可能出错的方向上都做了写侧防线形状/计数与形状表不符 → 响亮中止convert_fmt4_to_fmt2.py的die、repack_fp8_passthrough.py的MalformedRepackTensorError碰撞形状且不可 stamp → 拒绝写入而非冒险发射_check_geometry与_emission_stamp_gate双重把关后者从输出张量自身推导结构性而非程序性保证输出尺寸与预测不符 → 删除并中止避免以错误尺寸续传convert_fmt4_to_fmt2.py断点续传输入变更 →InputChangedError中止杜绝两个来源混装repack_fp8_passthrough.py空选择运行 → 拒绝以 exit 0 产出空容器repack_fp8_passthrough.py的 FIX ROUND 2。这些细节保证一个能通过写侧检查的容器读侧要么正确加载要么响亮拒绝绝不静默损坏。同一套“拒绝而非猜测”的纪律也延伸到了引擎读取侧qt_resolve_fmt的 THE DESIGN LANDMINE 拒绝逻辑与测试体系如 tests/test_fp8_repack.py 钉住 stamp 预算上限与元数据顺序确定性形成了工具与运行时之间可交叉验证的闭环。参考文档与进一步阅读c/tools/README.md工具链官方总览本文骨架docs/FORMATS.md引擎各量化格式fmt1/2/4/5/6/8的注册表式规范与 stamp 约定docs/METAL-M1ULTRA-FMT2-REPORT.mdfmt2 转换后的 Metal 基准报告docs/quickstart.md 与 docs/deepseek-v4.md引擎运行与模型目录准备c/quant.h 与 c/colibri.cqt_resolve_fmt读侧格式推断与qt_from_disk/stamp 验证【免费下载链接】colibriRun frontier MoE models on hardware you already own — pure C, zero deps, experts streamed from disk. Tiny engine, immense model. 项目地址: https://gitcode.com/GitHub_Trending/colibri3/colibri创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考