LoRA Model Customization
Learn how to use NeMo Helix to create a LoRA (Low-Rank Adaptation) customization job using a custom dataset. In this tutorial we use LoRA to fine-tune NVIDIA Nemotron 3.5 Lightning 30B-A3B into a question-answering model with the SQuAD dataset.
LoRA is a parameter-efficient fine-tuning method that requires fewer computational resources than full fine-tuning. If you need full model fine-tuning instead, see the Full SFT Customization Job tutorial.
Time to complete: approximately 45 minutes. Job duration increases with model size and dataset size.
Prerequisites
Before starting this tutorial, ensure you have:
- Completed the Quickstart to install and deploy NeMo Helix locally
- Installed the Python SDK (PyPI wrapper:
pip install "nemo-helix[all]"; source checkout: runmake bootstrapfrom the repository root) - Installed the
datasetspackage for loading SQuAD:pip install datasets - Four NVIDIA Hopper or Blackwell era GPUs with 80 GB+ each and CUDA 13+ (for example, H100 or B200) for training. Nemotron customization is supported on Hopper or Blackwell era GPUs only. The deployment step later reuses two of them.
Quick Start
1. Initialize SDK
The SDK connects to the deployment in your current CLI context, using its base URL, default workspace, and credentials. To connect to another deployment, refer to Connect with CLI Contexts. These examples use the default workspace. If your current CLI context uses a different workspace, run nemo config set --workspace default first.
In environments without a CLI configuration file, such as Google Colab, set NHX_BASE_URL (and NHX_ACCESS_TOKEN for an authenticated deployment) before you create the client. NemoClient.from_config() reads both:
2. Prepare Dataset
Create your data in JSONL format (one JSON object per line). For a chat model, use the chat format so training and inference share the model’s chat template.
Dataset structure:
- Training files under
training/(or root withtraining.jsonl) - Validation files under
validation/(orvalidation.jsonl)
Chat format: Each line is a JSON object with:
messages: A list ofuserandassistantturns. The finalassistantturn is the desired model output.
Example record (single line in .jsonl):
Download SQuAD and Convert to Chat Format
We use the SQuAD dataset. We convert each example to the chat messages format. The user turn is the same prompt the evaluation step sends, so the model is trained and queried through the same chat template, including the end-of-turn token that stops generation.
3. Create FileSet and Upload Training Data
Upload the training and validation JSONL files to a FileSet so the customization job can use them.
4. Secrets Setup
For Hugging Face models that require authentication, create a secret with your HF token. Get a token from Hugging Face Settings and accept the model terms.
The Nemotron model in this tutorial is public, so the token is optional.
5. Create Base Model FileSet and Model Entity
Create a fileset pointing to nvidia/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-BF16 and a Model Entity that references it. Model download happens when the customization job runs.
Train on the BF16 checkpoint. The NVFP4 variant is quantized for inference and cannot be used as a training base.
6. Create LoRA Customization Job
Submit to the Automodel backend using AutomodelJobInput with finetuning_type: lora. After training completes, deploy the base model with LoRA support manually (step 8).
The hyperparameters follow the Automodel reference recipes for this architecture, customizer_nemotron_nano_peft.yaml and nemotron_nano_v3_hellaswag_peft.yaml:
- Expert parallelism: the 128 experts are sharded across 4 GPUs (
expert_parallel_size=4,tensor_parallel_size=1). - LoRA targets:
*.out_projis excluded because the Mamba output projection runs through a fused kernel that LoRA cannot wrap.
7. Track Training Progress
Poll until the job finishes. Each update shows the current step, how much of that step is done, and the latest loss. Once the backend reports a loss history, the cell charts loss by step.
8. Validate Output Model and Deployment
With the base model entity and LoRA adapter from training, create a NIM deployment with lora_enabled=True so the adapter is served alongside the base weights. Check the model entity and deployment status.
9. Monitor Deployment Until Ready
Wait for the deployment to reach RUNNING/READY before sending inference requests. Image pull and weight load often take 10–20 minutes, and the status stays PENDING until the server is ready.
10. Check Model Output
Send a chat completion request to the deployed LoRA model and compare the output to the expected answer.
Conclusion
You have started a LoRA customization job, monitored it to completion, and evaluated the fine-tuned model. Use the output.name to access the model for further inference or evaluation.
Next Steps
- Monitor training metrics in detail
- Evaluate your fine-tuned model using the Evals service
- Try Full SFT for other customization options