Chapter 12

Checkpoint 转换:NeMo ↔ HF

📌 commit 2ea3e0f训完模型怎么进 HF / vLLM / TRT-LLM 生态

NeMo 训完的模型是 .nemo 格式(zip 包含 weight + config + tokenizer),跟 HF 生态不直接互通。本章给两个方向的转换脚本。

12.1.nemo 是什么

.nemo 是 NeMo 自定义的打包格式,本质是 tar/zip,内部结构:

my_model.nemo
├── model_config.yaml         # Hydra 风格的完整配置
├── model_weights.ckpt        # PyTorch state_dict(torch.save)
├── tokenizer.model           # SentencePiece / HF tokenizer
└── (可选) extra files

大文件可以分 shard,每个 shard 一个文件夹。

12.2NeMo → HF:常见模型转换脚本

模型脚本
Llama 系scripts/checkpoint_converters/convert_llama_nemo_to_hf.py
Mistral / Mixtralconvert_mistral_*_to_hf.py
Gemmaconvert_gemma_*_to_hf.py
Falconconvert_falcon_*_to_hf.py
Qwen / Qwen2convert_qwen_*_to_hf.py
Starcoder2convert_starcoder2_*_to_hf.py
Baichuan2convert_baichuan2_*_to_hf.py

典型命令

python scripts/checkpoint_converters/convert_llama_nemo_to_hf.py \
    --input_name_or_path ./out/llama3_8b_sft.nemo \
    --output_path ./hf_out/llama3_8b_sft \
    --hf_input_path meta-llama/Meta-Llama-3-8B \
    --precision bf16

--hf_input_path 是关键:从原 HF 模型抄走 tokenizer / config,再覆盖 weight。

12.3HF → NeMo

模型脚本
Llamaconvert_llama_hf_to_nemo.py
Mistralconvert_mistral_hf_to_nemo.py
Gemmaconvert_gemma_hf_to_nemo.py
python scripts/checkpoint_converters/convert_llama_hf_to_nemo.py \
    --input_name_or_path meta-llama/Meta-Llama-3-8B \
    --output_path ./nemo_out/llama3_8b.nemo \
    --precision bf16

12.4转换原理

核心是权重名映射。NeMo / Megatron 风格 vs HF 风格:

NeMo 权重名HF 权重名变换
model.embedding.word_embeddings.weightmodel.embed_tokens.weight直接对应
model.decoder.layers.N.self_attention.linear_qkv.weight分成 q_proj / k_proj / v_proj★ 需要 split + 重排
model.decoder.layers.N.self_attention.linear_proj.weighto_proj.weight直接
model.decoder.layers.N.mlp.linear_fc1.weight分成 gate_proj / up_projsplit
model.decoder.layers.N.mlp.linear_fc2.weightdown_proj.weight直接
model.decoder.final_layernorm.weightmodel.norm.weight直接
model.output_layer.weightlm_head.weight直接

关键难点:QKV 的合并和拆分。NeMo 把 q/k/v 合并成一个 fused tensor (3d, d) 排列,而且 GQA 时按 group 排,转的时候要按 head_dim、num_query_heads、num_key_value_heads 切对。

12.5转 GGUF(llama.cpp 用)

NeMo → HF 之后用 llama.cpp 工具继续转:

# 先 NeMo → HF
python convert_llama_nemo_to_hf.py ...

# 然后 HF → GGUF
python llama.cpp/convert_hf_to_gguf.py ./hf_out --outtype bf16 -o ./model.gguf

# 量化
./llama.cpp/llama-quantize ./model.gguf ./model-q4_k_m.gguf q4_k_m

12.6NeMo 内部 ckpt 形式

除了 .nemo 打包格式,NeMo 训练中产生:

distributed ckpt 加载快、save 快,但不能直接转 HF,要先合并:

python scripts/checkpoint_converters/convert_zarr_to_torch_dist.py \
    --input ./out/checkpoints/last.zarr \
    --output ./out/last.nemo

12.7LoRA adapter 单独转

# NeMo 的 LoRA adapter 在 .nemo 包里
python scripts/checkpoint_converters/convert_lora_nemo_to_hf.py \
    --input ./sft_lora_out/.nemo \
    --output ./hf_lora

转完用 HF PEFT 直接加载:

from peft import PeftModel
model = PeftModel.from_pretrained(base_hf_model, "./hf_lora")

12.8常见错误

现象处理
转完 HF 推理乱码QKV 拆分错;num_key_value_heads 没对
shape mismatchTP > 1 时要先合并到 TP=1;用 --tensor_model_parallel_size 1
tokenizer 不一致转时记得 --hf_input_path 指对原 HF 模型
转完后精度大降用 bf16 转;或保 fp32

12.9这章你需要带走的