Skip to main content

Fine-Tuning

Create fine-tuning jobs, monitor training progress, and deploy fine-tuned models.

Overview

The Fine-Tuning resource provides:

  • Job creation from a base model and training dataset
  • Real-time training progress and metrics monitoring
  • Cost estimation before starting a job
  • Hardware and base model discovery
  • Deployment of completed fine-tuned models

All fine-tuning methods are accessed through client.fine_tuning.


Creating a Job

Basic Job

from strongly import Strongly

client = Strongly()

job = client.fine_tuning.create_job({
"name": "customer-support-v1",
"base_model": "gpt-4o-mini-2024-07-18",
"training_dataset": "dataset-abc123",
"description": "Fine-tuned on customer support conversations",
})

print(f"Job created: {job.name} (ID: {job.id})")
print(f"Status: {job.status}")
print(f"Base model: {job.base_model}")

With Hyperparameters and Validation

from strongly import Strongly

client = Strongly()

job = client.fine_tuning.create_job({
"name": "code-assistant-v2",
"base_model": "gpt-4o-mini-2024-07-18",
"training_dataset": "dataset-train-456",
"validation_file": "dataset-val-789",
"description": "Code completion model trained on internal repos",
"suffix": "code-assist",
"hyperparameters": {
"n_epochs": 3,
"batch_size": 4,
"learning_rate_multiplier": 0.1,
},
})

print(f"Job ID: {job.id}")
print(f"Status: {job.status}")

Cost Estimation

Estimate the cost and time before starting a job:

from strongly import Strongly

client = Strongly()

estimate = client.fine_tuning.estimate_cost(
base_model="gpt-4o-mini-2024-07-18",
dataset_size=10000,
)

print(f"Base model: {estimate.base_model}")
print(f"Dataset size: {estimate.dataset_size} examples")
print(f"Estimated cost: {estimate.currency} {estimate.estimated_cost:.2f}")
print(f"Estimated time: {estimate.estimated_time_minutes:.0f} minutes")

Discovering Base Models and Hardware

Available Base Models

from strongly import Strongly

client = Strongly()

base_models = client.fine_tuning.base_models()
for model in base_models:
print(f" {model}")

Available Hardware

from strongly import Strongly

client = Strongly()

hardware = client.fine_tuning.hardware()
for hw in hardware:
print(f" {hw}")

Monitoring Progress

Job Stats

Get a summary of all fine-tuning jobs by status:

from strongly import Strongly

client = Strongly()

stats = client.fine_tuning.stats()
print(f"Total jobs: {stats.total}")
print(f"Running: {stats.running}")
print(f"Completed: {stats.completed}")
print(f"Failed: {stats.failed}")
print(f"Queued: {stats.queued}")

Listing Jobs

from strongly import Strongly

client = Strongly()

# List all jobs
for job in client.fine_tuning.list_jobs():
print(f"{job.name}{job.status}")

# Filter by status
for job in client.fine_tuning.list_jobs(status="running"):
print(f"{job.name}: started at {job.started_at}")

# Filter by base model
for job in client.fine_tuning.list_jobs(base_model="gpt-4o-mini-2024-07-18"):
print(f"{job.name}{job.status}")

# Search by name
for job in client.fine_tuning.list_jobs(search="customer"):
print(f"{job.name} (ID: {job.id})")

Tracking a Job

Poll a running job until it completes:

from strongly import Strongly
import time

client = Strongly()

job = client.fine_tuning.create_job({
"name": "sentiment-classifier",
"base_model": "gpt-4o-mini-2024-07-18",
"training_dataset": "dataset-sentiment-001",
})
job_id = job.id

while True:
job = client.fine_tuning.retrieve_job(job_id)
print(f"Status: {job.status}")

if job.metrics:
print(f" Metrics: {job.metrics}")

if job.status in ("completed", "failed"):
break

time.sleep(30)

if job.status == "completed":
print(f"Training complete. Result model: {job.result_model}")
print(f"Trained tokens: {job.trained_tokens}")
else:
print(f"Training failed: {job.error}")

Job Logs and Metrics

from strongly import Strongly

client = Strongly()

# Get training logs
logs = client.fine_tuning.job_logs("job-abc123", lines=50)
print(logs)

# Get training metrics (loss curves, accuracy, etc.)
metrics = client.fine_tuning.job_metrics("job-abc123")
print(metrics)

Job Lifecycle

Stopping a Job

Cancel a running job:

from strongly import Strongly

client = Strongly()

client.fine_tuning.stop_job("job-abc123")
print("Job stopped")

Restarting a Job

Restart a stopped or failed job:

from strongly import Strongly

client = Strongly()

client.fine_tuning.restart_job("job-abc123")
print("Job restarted")

Deleting a Job

from strongly import Strongly

client = Strongly()

client.fine_tuning.delete_job("job-abc123")
print("Job deleted")

Deploying a Fine-Tuned Model

After a job completes, deploy the resulting model so it can be used for inference:

from strongly import Strongly
import time

client = Strongly()

# Check the job is complete
job = client.fine_tuning.retrieve_job("job-abc123")

if job.status != "completed":
print(f"Job is not complete (status: {job.status})")
else:
print(f"Result model: {job.result_model}")

# Deploy the fine-tuned model
client.fine_tuning.deploy_model("job-abc123")
print("Deployment started")

# Use the deployed model for inference
response = client.ai.inference.chat_completion(
model=job.result_model,
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.content)

Method Reference

MethodDescriptionReturns
list_jobs(*, status=None, base_model=None, search=None, limit=50)List fine-tuning jobsSyncPaginator[FineTuningJob]
stats()Get job count summaryFineTuningStats
base_models()List available base modelsList[dict]
hardware()List available hardware optionsList[dict]
estimate_cost(*, base_model, dataset_size, **kwargs)Estimate job cost and timeFineTuningCostEstimate
create_job(body)Create a new fine-tuning jobFineTuningJob
retrieve_job(job_id)Get a job by IDFineTuningJob
delete_job(job_id)Delete a jobdict
stop_job(job_id)Stop a running jobdict
restart_job(job_id)Restart a stopped/failed jobdict
deploy_model(job_id, **kwargs)Deploy the fine-tuned modeldict
job_logs(job_id, *, lines=None, since=None)Get training logsdict
job_metrics(job_id)Get training metricsdict

Response Models

FineTuningJob Fields

FieldTypeDescription
idstrUnique job identifier
namestrJob display name
base_modelstrBase model used for fine-tuning
statusstrCurrent status (queued, running, completed, failed, stopped)
descriptionstrHuman-readable description
ownerstrOwner user ID
organization_idstrOwning organization
training_datasetstrTraining dataset identifier
training_filestrTraining file reference
validation_filestrValidation file reference
hyperparametersdictTraining hyperparameters (n_epochs, batch_size, learning_rate_multiplier)
result_modelstrIdentifier of the fine-tuned model (set on completion)
trained_tokensintTotal tokens processed during training
errorstrError message (if job failed)
metricsdictTraining metrics (loss, accuracy, etc.)
started_atstrTraining start timestamp
finished_atstrTraining end timestamp
created_atstrJob creation timestamp
updated_atstrLast update timestamp

FineTuningStats Fields

FieldTypeDescription
totalintTotal fine-tuning jobs
runningintCurrently running jobs
completedintSuccessfully completed jobs
failedintFailed jobs
queuedintJobs waiting to start

FineTuningCostEstimate Fields

FieldTypeDescription
base_modelstrBase model for the estimate
dataset_sizeintNumber of training examples
estimated_costfloatEstimated cost
estimated_time_minutesfloatEstimated training time in minutes
currencystrCurrency code (default: "USD")

create_job Body Fields

FieldTypeRequiredDescription
namestrYesJob display name
base_modelstrYesBase model to fine-tune
training_datasetstrYesTraining dataset identifier
descriptionstrNoJob description
validation_filestrNoValidation dataset for evaluation
hyperparametersdictNoTraining hyperparameters
suffixstrNoSuffix appended to the fine-tuned model name

Complete Example

from strongly import Strongly
import time

def main():
client = Strongly()

# --- Check current stats ---
print("=== Fine-Tuning Stats ===")
stats = client.fine_tuning.stats()
print(f"Total: {stats.total}, Running: {stats.running}, Completed: {stats.completed}")

# --- Discover available base models ---
print("\n=== Available Base Models ===")
base_models = client.fine_tuning.base_models()
for model in base_models:
print(f" {model}")

# --- Discover available hardware ---
print("\n=== Available Hardware ===")
hardware = client.fine_tuning.hardware()
for hw in hardware:
print(f" {hw}")

# --- Estimate cost ---
print("\n=== Cost Estimate ===")
estimate = client.fine_tuning.estimate_cost(
base_model="gpt-4o-mini-2024-07-18",
dataset_size=5000,
)
print(f"Cost: {estimate.currency} {estimate.estimated_cost:.2f}")
print(f"Time: {estimate.estimated_time_minutes:.0f} minutes")

# --- Create a fine-tuning job ---
print("\n=== Creating Job ===")
job = client.fine_tuning.create_job({
"name": "support-agent-v1",
"base_model": "gpt-4o-mini-2024-07-18",
"training_dataset": "dataset-support-001",
"description": "Fine-tuned on customer support conversations",
"suffix": "support",
"hyperparameters": {
"n_epochs": 3,
"batch_size": 4,
"learning_rate_multiplier": 0.1,
},
})
job_id = job.id
print(f"Job ID: {job_id}")
print(f"Status: {job.status}")

# --- Monitor progress ---
print("\n=== Monitoring Progress ===")
while True:
job = client.fine_tuning.retrieve_job(job_id)
print(f" Status: {job.status}")

if job.metrics:
print(f" Metrics: {job.metrics}")

if job.status in ("completed", "failed", "stopped"):
break

time.sleep(30)

if job.status == "failed":
print(f"\nTraining failed: {job.error}")

# View logs for debugging
logs = client.fine_tuning.job_logs(job_id, lines=50)
print(f"Logs: {logs}")
return

print(f"\nTraining complete!")
print(f"Result model: {job.result_model}")
print(f"Trained tokens: {job.trained_tokens}")
print(f"Duration: {job.started_at} to {job.finished_at}")

# --- View training metrics ---
print("\n=== Training Metrics ===")
metrics = client.fine_tuning.job_metrics(job_id)
print(metrics)

# --- Deploy the fine-tuned model ---
print("\n=== Deploying Model ===")
client.fine_tuning.deploy_model(job_id)
print("Deployment started")

# --- Use the fine-tuned model ---
print("\n=== Using Fine-Tuned Model ===")
response = client.ai.inference.chat_completion(
model=job.result_model,
messages=[
{"role": "user", "content": "How do I reset my password?"},
],
)
print(f"Response: {response.content}")

# --- List all completed jobs ---
print("\n=== Completed Jobs ===")
for j in client.fine_tuning.list_jobs(status="completed"):
print(f" {j.name}{j.result_model} ({j.finished_at})")

if __name__ == "__main__":
main()