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, or pi0.5
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"
}

| Parameter | Type | Required | Description | | ---------------------------- | ----- | ----------- | --------------------------------------------------------------------------------------------------------- | | project_id | str | Yes | Project to create the job in | | model_id | str | Conditional | HuggingFace model ID (required for smolvla, pi0, pi05; omit for act, gr00t_n1_5, sarm (soon)) | | vla_type | str | Yes | Model type: smolvla, pi0, pi05, act, gr00t_n1_5, or sarm (soon) | | dataset_id | str | Yes | HuggingFace dataset ID | | hours | float | Yes | Training duration in hours (max 168) | | camera_mappings | dict | Yes | Map model camera slots to dataset image keys | | instance_type | str | No | GPU instance type (default: auto-selected) | | region | str | No | Cloud region (default: auto-selected) | | batch_size | int | No | Training batch size (default: 32) | | name | str | No | Job description | | use_rabc | bool | No | Enable SARM Reward-Aware Behavior Cloning (soon) | | sarm_reward_model_path | str | No | HuggingFace path to trained SARM reward model (soon) | | sarm_image_observation_key | str | No | Image key from dataset for reward annotations (soon) | | vla_hyper_spec | dict | No | Custom 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:

| Phase | Description | | ----------------------- | --------------------------------------------- | | queuing | Job is queued and waiting to start | | credit_validation | Validating credit balance | | instance_booting | GPU instance is booting | | instance_activation | Instance is being activated | | instance_setup | Setting up the training environment | | dataset_preprocessing | Preprocessing the dataset | | training_running | Training is in progress | | model_uploading | Uploading the fine-tuned model to HuggingFace | | completed | Job completed successfully | | failed | Job failed (check phase errors for details) | | cancelled | Job 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
}