Full SFT Customization
Full SFT Customization
Learn how to fine-tune all model weights using supervised fine-tuning (SFT) to customize LLM behavior for your specific tasks.
About
Supervised Fine-Tuning (SFT) customizes model behavior, injects new knowledge, and optimizes performance for specific domains and tasks. Full SFT modifies all model weights during training, providing maximum customization flexibility.
What you can achieve with SFT:
- 🎯 Specialize for domains: Fine-tune models on legal texts, medical records, or financial data
- 💡 Inject knowledge: Add new information not present in the base model
- 📈 Improve accuracy: Optimize for specific tasks like sentiment analysis, summarization, or code generation
SFT vs LoRA: Understanding the Trade-offs
Full SFT trains all model parameters (for example, all 70 billion weights in Llama 70B):
- ✅ Maximum model adaptation and knowledge injection
- ✅ Can fundamentally change model behavior
- ✅ Best for significant domain shifts or specialized tasks
- ❌ Requires substantial GPU resources (4-8x more than LoRA)
- ❌ Produces full model weights (~140GB for Llama 70B)
- ❌ Longer training time
LoRA trains only ~1% of weights by adding thin matrices to existing weights:
- ✅ 75-95% less memory required
- ✅ Faster training (2-4x speedup)
- ✅ Produces small adapter files (~100-500MB)
- ✅ Multiple adapters can share one base model
- ❌ Limited adaptation capability compared to full fine-tuning
When to choose Full SFT:
- Training small models (1B-8B) where resource cost is manageable
- Need fundamental behavior changes (for example, medical diagnosis, legal reasoning)
- Injecting substantial new knowledge not in the base model
When to choose LoRA: Refer to the LoRA tutorial for most use cases, especially with large models (70B+) or limited GPU resources.
Prerequisites
Before starting this tutorial, ensure you have:
- Completed the Quickstart to install and deploy NeMo Platform locally
- Installed the Python SDK (PyPI wrapper:
pip install "nemo-platform[all]"; source checkout: runmake bootstrapfrom the repository root)
Quick Start
1. Initialize SDK
The SDK needs to know your NeMo Platform server URL. By default, http://localhost:8080 is used in accordance with the Quickstart guide. If NeMo Platform is running at a custom location, you can override the URL by setting the NMP_BASE_URL environment variable:
2. Prepare Dataset
Create your data in JSONL format—one JSON object per line. The platform auto-detects your data format. Supported dataset formats are listed below.
Flexible Data Setup:
- No validation file? The platform automatically creates a 10% validation split
- Multiple files? Upload to
training/orvalidation/subdirectories—they will be automatically merged - Format detection: Your data format is auto-detected at training time
In this tutorial the following dataset directory structure will be used:
Simple Prompt/Completion Format
The simplest format with input prompt and expected completion:
prompt: The input prompt for the modelcompletion: The expected output response
Chat Format (for conversational models)
For multi-turn conversations, use the messages format:
messages: List of message objects withroleandcontentfields- Roles:
system,user,assistant
Custom Format (specify columns in job)
You can use custom field names and map them during job creation:
- Define your own field names
- Map them to prompt/completion in the job configuration
3. Create Dataset FileSet and Upload Training Data
Install huggingface datasets package to download public rajpurkar/squad dataset if it is not installed in your Python environment:
Download rajpurkar/squad Dataset
SQuAD (Stanford Question Answering Dataset) is a reading comprehension dataset consisting of questions posed on Wikipedia articles, where the answer is a segment of text from the corresponding passage.
4. Secrets Setup
If you plan to use NGC or HuggingFace models, you will need to configure authentication:
- NGC models (
ngc://URIs): Requires NGC API key - HuggingFace models (
hf://URIs): Requires HF token for gated/private models
Configure these as secrets in your platform. Refer to Managing Secrets for detailed instructions.
Get your credentials to access base models:
- NGC API Key (Setup → Generate API Key)
- HuggingFace Token (Create token with Read access)
Quick Setup Example
In this tutorial we are going to work with meta-llama/Llama-3.2-1B-Instruct model from HuggingFace. Ensure that you have sufficient permissions to download the model. If you cannot access the files on the meta-llama/Llama-3.2-1B-Instruct Hugging Face page, request access.
HuggingFace Authentication:
- For gated models (Llama, Gemma), you must provide a HuggingFace token via the
token_secretparameter - Get your token from HuggingFace Settings (requires Read access)
- Accept the model’s terms on the HuggingFace model page before using it. Example: meta-llama/Llama-3.2-1B-Instruct
- For public models, you can omit the
token_secretparameter when creating a fileset for model in the next step
5. Create Base Model FileSet and Model Entity
Create a fileset pointing to meta-llama/Llama-3.2-1B-Instruct model in HuggingFace that we will train with SFT. Then create a Model Entity that references this fileset. Model downloading will take place at training time.
Note: for public models, you can omit the token_secret parameter when creating a model fileset.
6. Create SFT Finetuning Job
Create a customization job to fine-tune all model weights using the Automodel backend and AutomodelJobInput.
GPU Requirements:
- 1B models: 1 GPU (24GB+ VRAM)
- 3B models: 1-2 GPUs
- 8B models: 2-4 GPUs
- 70B models: 8+ GPUs
Adjust num_gpus_per_node based on your model size.
7. Track Training Progress
Interpreting SFT Training Metrics:
Monitor the relationship between training and validation loss curves:
Note: Training metrics measure optimization progress, not final model quality. Always evaluate the deployed model on your specific use case.
(ft-deploy-full-weight-model)=
8. Deploy Fine-Tuned Model
After training completes, deploy using the Deployment Management Service:
The deployment service automatically:
- Downloads model weights from the Files service
- Provisions storage (PVC) for the weights
- Configures and starts the vLLM container
Multi-GPU Deployment:
For larger models requiring multiple GPUs, increase gpu in executor_config. vLLM computes tensor parallelism from the GPU count and model architecture:
Single-Node Constraint: Model deployments are limited to a single node. The maximum gpu value depends on the total GPUs available on a single node in your cluster. Multi-node deployments are not supported.
Track Deployment Status
9. Evaluate Your Model
After training, evaluate whether your model meets your requirements:
Quick Manual Evaluation
Evaluation Best Practices
Manual Evaluation (Recommended)
- Test with real-world examples from your use case
- Compare responses to base model and expected outputs
- Verify the model exhibits desired behavior changes
- Check edge cases and error handling
What to look for:
- ✅ Model follows your desired output format
- ✅ Applies domain knowledge correctly
- ✅ Maintains general language capabilities
- ✅ Avoids unwanted behaviors or biases
- ❌ Doesn’t hallucinate facts not in training data
- ❌ Doesn’t produce repetitive or nonsensical outputs
Hyperparameters
For detailed information on all available hyperparameters, recommended values, and tuning guidance, refer to the Hyperparameter Reference.
Troubleshooting
Job fails during model download:
- Verify authentication secrets are configured (refer to Managing Secrets)
- For gated HuggingFace models (Llama, Gemma), accept the license on the model page (for example, meta-llama/Llama-3.2-1B-Instruct)
- Confirm the model fileset uses
token_secret=hf_secret.namefor gated models - Check
AutomodelJobInputreferences use theworkspace/nameformat:model=f"default/{MODEL_NAME}"anddataset={"training": f"default/{DATASET_NAME}"}(for example,default/llama-3-2-1b-base,default/sft-dataset) - Verify the model entity points at the fileset:
fileset=f"default/{MODEL_NAME}" - Check job status:
client.jobs.get_status(name=job.job.name, workspace="default")
Job fails with OOM (Out of Memory) error:
- First try: Reduce
global_batch_sizefrom 64 to 32 or 16 inbatch={...} - Still OOM: Keep
micro_batch_sizeat 1 (already the minimum in this tutorial) - Still OOM: Reduce
max_seq_lengthfrom 2048 to 1024 or 512 intraining={...} - Last resort: Increase
num_gpus_per_nodeandtensor_parallel_sizeinparallelism={...}
Loss curves not decreasing (underfitting):
- Increase training duration: raise
epochsfrom 2 to 3-5 inschedule={...} - Adjust learning rate: try
1e-4or1e-5instead of the default5e-5inoptimizer={...} - Check data quality: Verify formatting, remove duplicates, ensure diversity
Training loss decreases but validation loss increases (overfitting):
- Reduce
epochsfrom 2 to 1 inschedule={...} - Lower
learning_ratefrom5e-5to2e-5or1e-5inoptimizer={...} - Increase dataset size and diversity
- Verify train/validation split has no data leakage
Model output quality is poor despite good training metrics:
- Training metrics optimize for loss, not your actual task—evaluate on real use cases
- Review data quality, format, and diversity—metrics can be misleading with poor data
- Try a different base model size or architecture
- Adjust
learning_rateandglobal_batch_size - Compare to baseline: Test base model to ensure fine-tuning improved performance
Deployment fails:
- Verify output model exists:
client.models.retrieve(name=OUTPUT_NAME, workspace="default") - Check deployment logs:
client.inference.deployments.get_logs(name=deployment.name, workspace="default") - Ensure sufficient GPU resources for
executor_config={"gpu": 1, ...} - Verify the deployment config matches this tutorial:
engine="vllm"withvllm/vllm-openai:v0.22.1
Next Steps
- Monitor training metrics in detail
- Evaluate your fine-tuned model using the Evaluator service
- Learn about LoRA customization for resource-efficient fine-tuning