This document describes the three training modes supported by this repo:
- SFT the base HunyuanOCR model (full end-to-end fine-tuning)
- DFlash draft — train from scratch (large data, e.g. ~1M packs)
- DFlash draft — continue-finetune (small domain data, e.g. ~10k packs)
Full end-to-end supervised fine-tuning of HunyuanOCR: vision encoder + MLP + LLM.
train/train_hunyuan.py — invoked by scripts/sft_base.sh.
# Single-node 8-GPU
MODEL_PATH=/path/to/HunyuanOCR \
TRAIN_DATA=./data/parsing_packed_20480.jsonl \
bash scripts/sft_base.sh| Env var | Default | Meaning |
|---|---|---|
LR |
2e-5 |
Learning rate |
EPOCHS |
5 |
Number of training epochs |
BATCH_SIZE |
1 |
Per-device train batch size |
GRAD_ACCUM |
1 |
Gradient accumulation steps |
SAVE_STEPS |
200 |
Checkpoint every N steps |
NPROC_PER_NODE |
8 |
GPUs per node |
Set standard PyTorch distributed env vars:
# Node 0 (master)
NNODES=4 NODE_RANK=0 NPROC_PER_NODE=8 \
MASTER_ADDR=10.0.0.1 MASTER_PORT=29500 \
bash scripts/sft_base.sh
# Node 1
NNODES=4 NODE_RANK=1 NPROC_PER_NODE=8 \
MASTER_ADDR=10.0.0.1 MASTER_PORT=29500 \
bash scripts/sft_base.sh
# ... etc for node 2, 3Adjust NCCL_SOCKET_IFNAME / NCCL_IB_HCA in scripts/env_common.sh to match your cluster's NIC layout.
Train a small MTP-style draft model from randomly initialized weights. Recommended when you have plenty of data (~1M packs).
train/train_draft.py — invoked by scripts/sft_dflash.sh.
MODEL_PATH=/path/to/HunyuanOCR \
TRAIN_DATA=./data/parsing_packed_20480.jsonl \
bash scripts/sft_dflash.sh| Env var | Default | Meaning |
|---|---|---|
LR |
1e-4 |
Larger LR for from-scratch |
EPOCHS |
2 |
Fewer epochs (large data) |
NUM_MASK_TOKENS |
16 |
K speculative tokens per position |
SAMPLE_BLOCK_NUM |
8 |
Number of blocks sampled per pack |
LOOP_NUM |
1 |
MTP-style iteration count |
SAVE_STEPS |
2000 |
Checkpoint every N steps |
The draft-model architecture (layers, hidden size, block size, ...) is loaded
from a small template directory containing config.json + dflash.py. Default:
train/configs/ (bundled with the repo). Override with the
env var HYOCR_DFLASH_CONFIG_DIR to point at any directory that ships the same
two files, for example the dflash/ subfolder that comes with the HuggingFace
HunyuanOCR release:
HYOCR_DFLASH_CONFIG_DIR=/path/to/HunyuanOCR/dflash \
bash scripts/sft_dflash.shTraining produces:
output/{run_name}/model.safetensors— DFlash draft weights (~350 MB)output/{run_name}/config.json— DFlash draft configoutput/{run_name}/checkpoint-XXXX/— intermediate checkpoints
Only model.safetensors + config.json + your dflash.py are needed for inference; see docs/inference/inference.md.
Start from a pre-trained DFlash checkpoint (e.g. our released v1) and adapt to a smaller/domain-specific dataset.
Recommended when data is small (~10k packs) and a decent DFlash draft already exists.
train/train_draft_from_dflash.py — invoked by scripts/sft_dflash_finetune.sh.
MODEL_PATH=/path/to/HunyuanOCR \
DFLASH_INIT=/path/to/existing/dflash/checkpoint \
TRAIN_DATA=./data/domain_packed_20480.jsonl \
bash scripts/sft_dflash_finetune.sh| Env var | Default | Meaning |
|---|---|---|
LR |
2e-5 |
5× smaller than from-scratch |
EPOCHS |
10 |
More passes for small data |
WARMUP |
0.05 |
Slightly longer warmup |
SAVE_STEPS |
500 |
~10 ckpts over full run |
DFLASH_INIT |
(required) | Path to existing draft checkpoint dir |
The draft config is loaded from DFLASH_INIT when it points at a valid
directory; otherwise the loader falls back to HYOCR_DFLASH_CONFIG_DIR
(default: train/configs/).
| v1 (1M packs, from-scratch) | v3 (14.7k packs, finetune) | |
|---|---|---|
| Data volume | 1.02 M packs | 14.7 k packs (70× smaller) |
| End-to-end speedup vs base AR | 1.92× | 2.14× (+11.6%) |
| Mean acceptance length (/15) | 6.06 | 7.36 (+21.4%) |
| Avg draft accept rate | 33.8% | 42.4% (+8.7 pp) |
Takeaway: for domain adaptation, finetuning from a pretrained draft with a smaller LR + more epochs consistently beats training from scratch with the same/less data.
All three modes consume the same packed JSONL format produced by tools/pipeline_count_and_pack.py. See data_format.md for details.
To use DeepSpeed ZeRO-2 (recommended for models > 3B params on ≤ 24GB GPUs), add:
--deepspeed scripts/zero2.json \to the args block inside your training script. Not enabled by default — H20 80GB with gradient_checkpointing=True fits full training without ZeRO for most cases.
- Enable NCCL debug logging:
export NCCL_DEBUG=INFO(already inenv_common.sh) - Enable CUDA sync for stack traces:
export CUDA_LAUNCH_BLOCKING=1 - Enable full torch dist debug:
export TORCH_DISTRIBUTED_DEBUG=DETAIL
Common issues:
| Symptom | Fix |
|---|---|
| NCCL timeout after N min | Check IB fabric; increase NCCL_TIMEOUT |
| OOM on 80GB GPU | Reduce packed_max_length from 20480 to 16384 |
| Loss doesn't decrease | For DFlash: check draft init dir has correct config.json |