Fine-tuning LLMs with Training Hub
training_hub is a Python library that wraps several LLM post-training algorithms — Supervised Fine-Tuning (SFT), Orthogonal Subspace Fine-Tuning (OSFT), LoRA / QLoRA, and continued pre-training (CPT) — behind single function calls (sft(...), osft(...), lora_sft(...)) that handle single-GPU, multi-GPU, and multi-node training uniformly.
- Automatic memory management —
max_tokens_per_gpucaps GPU memory and auto-computes micro-batch size and gradient accumulation to hit your targeteffective_batch_size. - OSFT implements Nayak et al., 2025 (arXiv:2504 .07097) — restricting weight updates to orthogonal subspaces prevents catastrophic forgetting without replay data.
- QLoRA loads the frozen base model in 4-bit and trains only LoRA adapters, fitting large models on a single small GPU slice (Dettmers et al., 2023, arXiv:2305 .14314).
- Continued pre-training (CPT) runs next-token prediction over a raw-text corpus to inject domain knowledge before instruction tuning.
- Built-in checkpointing, experiment tracking, and Liger kernel support.
training_hub is the upstream library RHOAI / Open Data Hub uses to expose post-training
algorithms behind a single API, and Alauda AI runs the same code on Kubeflow Trainer v2
(TrainJob / ClusterTrainingRuntime). The split between the algorithm (this library)
and the distributed runtime (Kubeflow Trainer) follows the Open Data Hub
architecture decision records
(see the distributed-workload and workbenches component docs) — so the recipes here
map cleanly onto the same sft / osft / lora_sft entrypoints whether you run them in a
workbench notebook or as a cluster TrainJob.
TOC
RequirementsData formatRun the example notebooksKey parametersQLoRA (4-bit LoRA)Continued pre-training (CPT)Multi-nodeRequirements
- Alauda AI Workbench installed in your cluster.
- A workbench with internet (or internal PyPI mirror), at least one NVIDIA GPU, and persistent storage for checkpoints.
- HuggingFace model name or local path.
- Training data in JSONL format (see below).
Data format
Each line is a conversation:
Roles: system, user, assistant, pretraining. Masking:
- SFT (default) — only
assistantcontent contributes to loss. Add"unmask": trueto a sample to include all non-system content. - OSFT — controlled by
unmask_messages(defaultFalse).
Pre-tokenized datasets with input_ids / labels are supported via use_processed_dataset=True.
Run the example notebooks
Download into your workbench and execute cell-by-cell:
Install and configure:
On the prebuilt traininghub0.1-cu126-amd64:v0.1.0 runtime image, install training-hub
inside a fresh venv — pip install --user training-hub upgrades transformers
to a version incompatible with the bundled peft:
Edit the parameter cells:
Bundled model presets cover Qwen 2.5 7B, Llama 3.1 8B, Phi 4 Mini, and generic 7B / small models.
Run all cells. The final training cell calls:
Checkpoints land in ckpt_output_dir at each epoch (controlled by checkpoint_at_epoch).
Key parameters
Common (SFT and OSFT):
OSFT-only:
QLoRA (4-bit LoRA)
QLoRA freezes the base model in 4-bit NormalFloat (NF4) precision and trains only small LoRA adapter matrices on top. A 7B model that needs ~60 GiB for full SFT then fits on a single 16–24 GiB GPU (or HAMI vGPU slice). Use it whenever you are GPU-memory bound; the cost is a small quantization quality gap and slightly slower steps.
training_hub exposes QLoRA through lora_sft(...) — LoRA plus the bitsandbytes 4-bit knobs:
QLoRA-specific parameters:
The output is a LoRA adapter, not a full checkpoint. To serve, load base + adapter with
peft, or merge once with merge_and_unload() and export a standalone model.
4-bit QLoRA via bitsandbytes needs an NVIDIA GPU of compute capability sm_75 or newer
(Turing / Ampere / Hopper). The traininghub0.1-cu126-amd64 runtime already bundles
trl, peft, and bitsandbytes. The default lora_sft backend is unsloth; for full
control you can also drive peft + bitsandbytes directly on the same runtime image.
NPU: training_hub and mainline bitsandbytes do not target Huawei Ascend. Two paths on
NPU:
- True 4-bit NF4 QLoRA via the community
bitsandbytes-npu-betafork (SlightwindSec/bitsandbytes, tracked upstream in PR #1695) — seeqlora-npu-tutorial.ipynb. Uses standardtransformers+peft+torch_npu; the API is drop-in, but the wheel is only tested againsttorch_npu 2.1–2.4/ CANN 8.0–8.1 and compatibility with newer CANN builds is best-effort. - Plain LoRA (no 4-bit) on the
llamafactory0.9-cann8.5-arm64runtime (finetuning_type: lora) — see Fine-tune and Pretrain on Ascend NPU. Slightly higher memory footprint than QLoRA, but no non-mainline dependencies.
Continued pre-training (CPT)
Continued pre-training (CPT) keeps the original next-token prediction objective but runs it over a raw-text corpus from your domain (medical, legal, code, a new language). It injects knowledge and vocabulary — unlike SFT/OSFT, which teach behavior from chat data. A common pipeline is CPT → SFT → alignment.
training_hub runs CPT through the same sft(...) entrypoint with is_pretraining=True:
the loss covers all tokens (no assistant-only masking) and documents are packed into
fixed-size block_size windows.
CPT data is raw text, not chat turns — one document per line under document_column_name:
CPT-specific parameters:
CPT updates all weights and writes a full checkpoint. It can cause catastrophic
forgetting of general ability — mitigate with a low learning rate, by mixing in some
general-domain text, and by following up with an SFT/OSFT pass (point model_path at the CPT
checkpoint). If forgetting is the primary concern, prefer OSFT.
NPU: Two paths for CPT on Ascend:
- Light-weight, single-node CPT with
transformers.Trainerontorch_npu— seecpt-npu-tutorial.ipynb. Uses only mainlinetransformers+torch_npu(noMindSpeed-LLM, no HF↔MCore conversion). Best when the model fits in bf16 on the NPUs you have and you don't need TP/PP. - Distributed, TP/PP-aware CPT via the
MindSpeed-LLMruntime (pretrain_gpt.py) — see Fine-tune and Pretrain on Ascend NPU and theqwen25_pretrain_verify.ipynbrecipe.
Multi-node
Run the notebook (or script) on every node with the same rdzv_id / rdzv_endpoint and varying node_rank:
All nodes need network reachability to rdzv_endpoint before training starts.