Skip to content

Finetune

Start a new fine-tuning job with your configuration.

from qualia import Qualia
client = Qualia()
job = client.finetune.create(
project_id="...",
model_id="lerobot/smolvla_base", # HuggingFace model ID
vla_type="smolvla", # smolvla, pi0, pi05, act, gr00t_n1_5, sarm (soon)
dataset_id="lerobot/pusht", # HuggingFace dataset ID
hours=2.0, # Training duration (max 168)
camera_mappings={ # Map model slots to dataset keys
"cam_1": "observation.images.top",
},
# Optional parameters:
instance_type="gpu_1x_a100", # From client.instances.list()
region="us-east-1",
batch_size=32,
name="My training run",
)

Response

FinetuneJob
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"project_id": "123e4567-e89b-12d3-a456-426614174000",
"status": "queuing"
}
ParameterTypeRequiredDescription
project_idstrYesProject to create the job in
model_idstrConditionalHuggingFace model ID (required for smolvla, pi0, pi05; omit for act, gr00t_n1_5, sarm (soon))
vla_typestrYesModel type: smolvla, pi0, pi05, act, gr00t_n1_5, or sarm (soon)
dataset_idstrYesHuggingFace dataset ID
hoursfloatYesTraining duration in hours (max 168)
camera_mappingsdictYesMap model camera slots to dataset image keys
instance_typestrNoGPU instance type (default: auto-selected)
regionstrNoCloud region (default: auto-selected)
batch_sizeintNoTraining batch size (default: 32)
namestrNoJob description
use_rabcboolNoEnable SARM Reward-Aware Behavior Cloning (soon)
sarm_reward_model_pathstrNoHuggingFace path to trained SARM reward model (soon)
sarm_image_observation_keystrNoImage key from dataset for reward annotations (soon)
vla_hyper_specdictNoCustom hyperparameters (see Advanced VLA Hyperparameters)

Reward-Aware Behavior Cloning (RA-BC) (soon)

Section titled “Reward-Aware Behavior Cloning (RA-BC) (soon)”

Use SARM reward models to weight training samples via Reward-Aware Behavior Cloning. This requires a pre-trained SARM reward model on HuggingFace.

job = client.finetune.create(
project_id="...",
vla_type="smolvla",
model_id="lerobot/smolvla_base",
dataset_id="lerobot/pusht",
hours=4.0,
camera_mappings={
"cam_1": "observation.images.top",
},
use_rabc=True,
sarm_reward_model_path="your-org/sarm-reward-model",
rabc_head_mode="sparse",
sarm_image_observation_key="observation.images.top",
)

You can customize model hyperparameters for fine-grained control over training. The SDK validates hyperparameters before submitting the job, so invalid configurations are caught early.

Retrieve the default hyperparameters for a VLA model type. Use these as a starting point for customization.

params = client.finetune.get_hyperparams_defaults(
vla_type="smolvla",
model_id="lerobot/smolvla_base",
)

Check whether your hyperparameters are valid before creating a job.

validation = client.finetune.validate_hyperparams(
vla_type="smolvla",
hyperparams=params,
)
if not validation.valid:
for issue in validation.issues:
print(f" {issue.field}: {issue.message}")

Response

HyperparamsValidation (valid)
{
"valid": true,
"issues": null
}
HyperparamsValidation (invalid)
{
"valid": false,
"issues": [
{ "field": "chunk_size", "message": "Input should be a valid integer" }
]
}

Create a Job with Advanced VLA Hyperparameters

Section titled “Create a Job with Advanced VLA Hyperparameters”

Pass your customized hyperparameters via vla_hyper_spec when creating a job. The create() method internally calls validate_hyperparams() — if validation fails, a ValueError is raised and no job is created.

# 1. Get defaults and customize
params = client.finetune.get_hyperparams_defaults(
vla_type="smolvla",
model_id="lerobot/smolvla_base",
)
params["training"]["learning_rate"] = 1e-5
params["training"]["num_epochs"] = 50
# 2. Create the job with custom hyperparameters
job = client.finetune.create(
project_id=project.project_id,
model_id="lerobot/smolvla_base",
vla_type="smolvla",
dataset_id="qualiaadmin/oneepisode",
hours=2.0,
camera_mappings={"cam_1": "observation.images.side"},
vla_hyper_spec=params,
)

Check the status of a fine-tuning job.

status = client.finetune.get(job.job_id)

Response

FinetuneStatus
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"current_phase": "training_running",
"status": "running",
"phases": [
{
"name": "queuing",
"status": "completed",
"started_at": "2024-01-15T10:00:00Z",
"completed_at": "2024-01-15T10:01:00Z",
"events": [],
"error": null
},
{
"name": "training_running",
"status": "started",
"started_at": "2024-01-15T10:05:00Z",
"completed_at": null,
"events": [
{
"status": "started",
"message": "Training started",
"error": null,
"timestamp": "2024-01-15T10:05:00Z",
"retry_attempt": 0
}
],
"error": null
}
]
}

Jobs progress through these phases in order:

PhaseDescription
queuingJob is queued and waiting to start
credit_validationValidating credit balance
instance_bootingGPU instance is booting
instance_activationInstance is being activated
instance_setupSetting up the training environment
dataset_preprocessingPreprocessing the dataset
training_runningTraining is in progress
model_uploadingUploading the fine-tuned model to HuggingFace
completedJob completed successfully
failedJob failed (check phase errors for details)
cancelledJob was cancelled

Each phase has a status of started, completed, or failed.

Cancel a running fine-tuning job.

result = client.finetune.cancel(job.job_id)

Response

FinetuneCancelResult
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"cancelled": true,
"previous_status": "training_running",
"instance_terminated": true
}