Skip to main content

Fine-Tuning

Fine-Tuning

toothfairyai@latest…

Manager for fine-tuning operations.

This manager provides methods to list trainable models, generate datasets, start training, monitor job status, and cancel training jobs.

Example:

>>> client = ToothFairyClient(api_key="...", workspace_id="...")
>>> models = client.finetuning.list_models()
>>> job = client.finetuning.generate_dataset(
... name="my-sft-job",
... training_type="conversationalTraining",
... base_model="toothfairyai/Llama-3.2-1B-Instruct"
... )
>>> status = client.finetuning.get_status(job["training_log_id"])

Accessed via client.finetuning.

Methods

MethodHTTPEndpoint
list_modelsGETGET /models
list_jobsGETGET /jobs
generate_datasetPOSTPOST /dataset
get_statusGETGET /status/{training_log_id}
start_trainingPOSTPOST /start/{training_log_id}
cancel_trainingPOSTPOST /cancel/{training_log_id}
download_datasetGETGET /dataset/{training_log_id}
list_adaptersGETGET /adapters
create_adapter_versionPOSTPOST /adapters/{training_log_id}/version
rollback_adapterPOSTPOST /adapters/{training_log_id}/rollback
get_servingGETGET /serving/{training_log_id}
set_servingPOSTPOST /serving/{training_log_id}
serving_powerPOSTPOST /serving/{training_log_id}/power
generate_training_dataPOSTPOST /magicwand

list_models

List all trainable models with their configurations.

def list_models() -> List[TrainableModel]

Endpoint: GET /models · Fine-Tuning service

Example

client.finetuning.list_models()

list_jobs

List all fine-tuning jobs for the authenticated workspace.

def list_jobs() -> List[TrainingJob]

Endpoint: GET /jobs · Fine-Tuning service

Example

client.finetuning.list_jobs()

generate_dataset

Generate a training dataset from workspace documents.

def generate_dataset(
name: str,
base_model: str,
training_type: str = 'conversationalTraining',
topics: Optional[List[str]] = None,
test_size: Optional[float] = None,
test_size_threshold: Optional[int] = None,
description: Optional[str] = None
) -> Dict[str, Any]

Endpoint: POST /dataset · Fine-Tuning service

Request fields

Python kwargWire fieldTypeRequiredDescription
namenamestringyesHuman-readable name for the training job
training_typetraining_typestringnoTraining method to use. Each method maps to a document type:
  • conversationalTraining (SFT) — uses Conversation documents
  • generativeTraining (DPO) — uses Preference documents
  • grpoTraining (GRPO) — uses Conversation documents (model self-generates)
  • ktoTraining (KTO) — uses Preference documents (unpaired)
  • continuedPretraining (CPT) — uses Conversation documents (plain text)

Defaults to conversationalTraining. Note: the REST endpoint does not enforce the enum at request time (validation occurs in the async worker); send one of the listed values.

Allowed: conversationalTraining, generativeTraining, grpoTraining, ktoTraining, continuedPretraining | | base_model | base_model | string | yes | Base model to fine-tune (canonical id from the /models endpoint) | | topics | topics | array<string> | no | Optional list of topic IDs to filter documents by | | test_size | test_size | number | no | Fraction of the dataset to reserve as the test split (0.0–1.0) | | test_size_threshold | test_size_threshold | integer | no | Minimum number of examples required in the test split | | description | description | string | no | Optional human-readable description of the training job |

Always pass snake_case keyword arguments — the Python kwarg column shows the exact name to use for each wire field (as a named parameter where it appears in the method signature, otherwise via **kwargs). The SDK converts it deterministically to the camelCase wire key the API expects. Passing camelCase directly is deprecated: it emits a warning and converts to the same wire key.

Example

client.finetuning.generate_dataset(name="…", base_model="…")

get_status

Get detailed status of a fine-tuning job.

def get_status(training_log_id: str) -> TrainingStatusResponse

Endpoint: GET /status/{training_log_id} · Fine-Tuning service

Response fields

FieldTypeDescription
training_log_idstringTraining log ID
statusstringCurrent job status. Lifecycle: dispatchedinProgressdatasetReadyfineTuningRequestedtrainingcompleted (or inError).

Allowed: dispatched, inProgress, datasetReady, fineTuningRequested, training, completed, inError, cancellationRequested | | name | string | Job name | | training_type | string | Training method | | created_at | string | Job creation timestamp (ISO 8601) | | duration | integer | Training duration in seconds (present once training has progressed) | | dataset | object | Dataset paths (present after dataset generation reaches the relevant stage) | | compute_uoi | number | UoI consumed by the training job (present when status is completed) | | model_id | string | S3 path to the fine-tuned LoRA adapter (present when status is completed) | | base_model | string | Base model used for training (present when status is completed) | | metrics_summary | object | Final training metrics (present when status is completed) | | downloads | object | Presigned download URLs (present when status is completed) | | error | object | Error detail (present when status is inError) |

Example

client.finetuning.get_status(training_log_id="agent-id")

start_training

Start a fine-tuning training job.

def start_training(
training_log_id: str,
config: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]

Endpoint: POST /start/{training_log_id} · Fine-Tuning service

Request fields

Python kwargWire fieldTypeRequiredDescription
configconfigobjectnoTraining configuration overrides merged over the existing training configuration. Keys not present retain their prior values. Only the keys listed in x-recognized-config-keys are consumed by the managed Unsloth/QLoRA+SageMaker training engine; any other key is silently persisted but ignored. Evaluation and checkpoint frequency are controllable via evalStrategy*/evalSteps*, saveStrategy*/saveSteps*, and checkpointsNumber* (save_total_limit).

Always pass snake_case keyword arguments — the Python kwarg column shows the exact name to use for each wire field (as a named parameter where it appears in the method signature, otherwise via **kwargs). The SDK converts it deterministically to the camelCase wire key the API expects. Passing camelCase directly is deprecated: it emits a warning and converts to the same wire key.

Example

client.finetuning.start_training(training_log_id="agent-id")

cancel_training

Cancel a running fine-tuning job.

def cancel_training(training_log_id: str) -> Dict[str, Any]

Endpoint: POST /cancel/{training_log_id} · Fine-Tuning service

Example

client.finetuning.cancel_training(training_log_id="agent-id")

download_dataset

Get a presigned download URL for a job's generated dataset.

def download_dataset(
training_log_id: str,
which: str = 'dataset'
) -> DatasetDownloadResponse

Endpoint: GET /dataset/{training_log_id} · Fine-Tuning service

Example

client.finetuning.download_dataset(training_log_id="agent-id")

list_adapters

List completed LoRA adapters for the workspace (adapter registry).

def list_adapters(
base_model: Optional[str] = None,
limit: Optional[int] = None,
next_token: Optional[str] = None
) -> AdapterListResponse

Endpoint: GET /adapters · Fine-Tuning service

Example

client.finetuning.list_adapters()

create_adapter_version

Snapshot a completed adapter as an immutable version (vN).

def create_adapter_version(
training_log_id: str,
label: Optional[str] = None
) -> AdapterVersionResponse

Endpoint: POST /adapters/{training_log_id}/version · Fine-Tuning service

Request fields

Python kwargWire fieldTypeRequiredDescription
labellabelstringnoOptional human-readable label for this version (e.g. "best-held-out", "promoted-2026-07").

Always pass snake_case keyword arguments — the Python kwarg column shows the exact name to use for each wire field (as a named parameter where it appears in the method signature, otherwise via **kwargs). The SDK converts it deterministically to the camelCase wire key the API expects. Passing camelCase directly is deprecated: it emits a warning and converts to the same wire key.

Response fields

FieldTypeDescription
adapter_idstringTraining log ID of the snapshotted adapter
versionintegerThe version number assigned (1, 2, 3, …)
snapshotobjectThe immutable version record written to the manifest
manifest_keystringS3 key of the manifest storing this adapter's versions

Example

client.finetuning.create_adapter_version(training_log_id="agent-id")

rollback_adapter

Get presigned artefacts to roll back to a pinned adapter version.

def rollback_adapter(
training_log_id: str,
version: Optional[int] = None
) -> AdapterRollbackResponse

Endpoint: POST /adapters/{training_log_id}/rollback · Fine-Tuning service

Request fields

Python kwargWire fieldTypeRequiredDescription
versionversionintegernoVersion number to roll back to (from a prior /version call). Omit to use the latest snapshot.

Always pass snake_case keyword arguments — the Python kwarg column shows the exact name to use for each wire field (as a named parameter where it appears in the method signature, otherwise via **kwargs). The SDK converts it deterministically to the camelCase wire key the API expects. Passing camelCase directly is deprecated: it emits a warning and converts to the same wire key.

Response fields

FieldTypeDescription
adapter_idstringTraining log ID the rollback was requested on
rolled_back_tointegerThe version that was resolved (explicit version or latest); null when the latest snapshot was used implicitly
target_adapter_idstringThe training log ID whose S3 prefix holds the target weights. May differ from adapter_id when rolling back along a parent-adapter lineage (a snapshot taken from a different completed job).
weights_urlstringPresigned URL (valid 1h) to the pinned adapter_model.safetensors
config_urlstringPresigned URL (valid 1h) to the pinned adapter_config.json, or null if the config file is absent in S3
base_modelstringBase model of the resolved snapshot (from the manifest, falling back to the training meta)
inference_templatestringInference chat-template key to use for serving this base model
notestringExplains that the inference switch is performed by the Chat routing layer; this endpoint only returns the pinned adapter artefacts.
available_versionsarray<integer>Present only in the 404 response body (not on 200) when the requested version was not found — lists all known version numbers to aid retry. Returned here for reference.

Example

client.finetuning.rollback_adapter(training_log_id="agent-id")

get_serving

Get the serving config and live lane state for a fine-tuned model.

def get_serving(training_log_id: str) -> ServingConfig

Endpoint: GET /serving/{training_log_id} · Fine-Tuning service

Response fields

FieldTypeDescription
modelIdstringThe fine-tuned model's API name (usable as model on chat-completions)
trainingLogIdstringTraining log ID that produced this fine-tuned model
base_modelstringTrainable base the model was fine-tuned from
inference_basestringCanonical checkpoint the lane serves
modestringCurrent serving mode

Allowed: on-demand, scheduled, always | | schedule | object | A recurring warm window in the given IANA timezone. end must be later than start (overnight windows are not supported). | | lane | object | Live lane state for the fine-tuned model's inference lane. | | warm_seconds_accrued | integer | Warm seconds accrued in the current billing day | | warm_seconds_note | string | Billing note: warm hours bill daily in 1-hour units (minimum 1) at the size-tier hourly rate |

Example

client.finetuning.get_serving(training_log_id="agent-id")

set_serving

Set the serving mode for a fine-tuned model.

def set_serving(
training_log_id: str,
mode: str = 'on-demand',
schedule: Optional[Dict[str, Any]] = None
) -> ServingSetResponse

Endpoint: POST /serving/{training_log_id} · Fine-Tuning service

Request fields

Python kwargWire fieldTypeRequiredDescription
modemodestringnoon-demand (default when omitted — wakes on first request, sleeps after ~15 min idle, $0 while idle), scheduled (warm inside recurring time windows), or always (kept warm continuously).

Allowed: on-demand, scheduled, always | | schedule | schedule | object | no | A recurring warm window in the given IANA timezone. end must be later than start (overnight windows are not supported). |

Always pass snake_case keyword arguments — the Python kwarg column shows the exact name to use for each wire field (as a named parameter where it appears in the method signature, otherwise via **kwargs). The SDK converts it deterministically to the camelCase wire key the API expects. Passing camelCase directly is deprecated: it emits a warning and converts to the same wire key.

Response fields

FieldTypeDescription
modelIdstringThe fine-tuned model's API name (usable as model on chat-completions)
trainingLogIdstringTraining log ID that produced this fine-tuned model
modestringThe stored serving mode

Allowed: on-demand, scheduled, always | | schedule | object | A recurring warm window in the given IANA timezone. end must be later than start (overnight windows are not supported). | | mirrored_to_training_log | boolean | Whether the config was also mirrored onto the TrainingLog entity (inside trainingMeta) | | note | string | scheduled/always modes take effect within ~2 minutes (the serving monitor picks up the change) |

Example

client.finetuning.set_serving(training_log_id="agent-id")

serving_power

Turn a fine-tuned model on or off right now.

def serving_power(
training_log_id: str,
state: str,
hours: Optional[int] = None
) -> ServingPowerResponse

Endpoint: POST /serving/{training_log_id}/power · Fine-Tuning service

Request fields

Python kwargWire fieldTypeRequiredDescription
statestatestringyeson = wake and hold warm for hours; off = release the hold now

Allowed: on, off | | hours | hours | integer | no | Hours to hold the lane warm (minimum 1, 1-hour billing units) |

Always pass snake_case keyword arguments — the Python kwarg column shows the exact name to use for each wire field (as a named parameter where it appears in the method signature, otherwise via **kwargs). The SDK converts it deterministically to the camelCase wire key the API expects. Passing camelCase directly is deprecated: it emits a warning and converts to the same wire key.

Response fields

FieldTypeDescription
modelIdstringThe fine-tuned model's API name
trainingLogIdstringTraining log ID that produced this fine-tuned model
statestringThe power state applied

Allowed: on, off | | hours | integer | Hours booked (0 for off) | | lane | object | Lane result returned by the serving power endpoint. With state: on, the orchestrator returns the lane's status plus pinned_until (epoch seconds the lane is held warm until). With state: off, it returns status: unpinned and the lane idles out per normal rules (up to 15 min grace). | | billing_note | string | Warm hours accrue while held and bill daily in 1-hour units (minimum 1) |

Example

client.finetuning.serving_power(training_log_id="agent-id", state="…")

generate_training_data

Transform a chat conversation or uploaded file into training data.

def generate_training_data(
chat_id: Optional[str] = None,
file_key: Optional[str] = None,
training_type: str = 'conversationalTraining',
user_id: Optional[str] = None,
create_document: bool = True,
system_message: Optional[str] = None,
instructions: Optional[str] = None,
title: Optional[str] = None,
topics: Optional[List[str]] = None,
status: str = 'draft',
scope: str = 'training',
non_preferred_responses: Optional[List[Dict[str, Any]]] = None,
tools: Optional[List[Dict[str, Any]]] = None,
generate_non_preferred: bool = False,
chunk_size: Optional[int] = None,
overlap_percent: Optional[float] = None,
num_turns: Optional[int] = None,
samples_per_chunk: Optional[int] = None
) -> Dict[str, Any]

Endpoint: POST /magicwand · AI service

Request fields

Python kwargWire fieldTypeRequiredDescription
chatidchatidstringnoChat mode: Unique chat session identifier to extract messages from. Mutually exclusive with file_key.
file_keyfile_keystringnoFile mode: S3 key of uploaded file to generate training data from. Obtain via /documents/requestPreSignedURL endpoint. Mutually exclusive with chatid.

Supported formats: PDF, DOCX, XLSX, PPTX, TXT, MD, CSV, JSON, HTML, XML | | workspace_id | workspaceid | string | yes | Unique workspace identifier | | userid | userid | string | no | User identifier performing the operation | | chunk_size | chunk_size | integer | no | File mode only: Target size of each text chunk in characters. Larger chunks provide more context but generate fewer training samples. | | overlap_percent | overlap_percent | number | no | File mode only: Percentage of overlap between adjacent chunks to preserve context continuity. | | num_turns | num_turns | integer | no | File mode only: Number of conversation turns (user-assistant pairs) to generate per chunk. Each turn adds a question and answer. | | samples_per_chunk | samples_per_chunk | integer | no | File mode only: Number of independent training samples to generate per chunk. Useful for data augmentation. | | create_document | create_document | boolean | no | Whether to create a training document in the knowledge hub. If false, only returns the transformed data without persisting. | | system_message | system_message | string | no | Custom system message to prepend to the training data. If not provided, a default message will be used. | | instructions | instructions | string | no | Optional instructions to refine the training data output.

Chat mode: Refine conversation messages. File mode: Guide conversation synthesis from document content.

Examples:

  • "Focus on technical accuracy"
  • "Remove any personal information"
  • "Make the tone more professional"
  • "Include code examples where relevant" | | title | title | string | no | Title for the training document (only used when create_document is true) | | topics | topics | array<string> | no | Topic IDs to tag the training document with (only used when create_document is true) | | training_type | training_type | string | no | Training method to use

Allowed: conversationalTraining, generativeTraining, grpoTraining, ktoTraining, continuedPretraining | | non_preferred_responses | non_preferred_responses | array<string> | no | For DPO training: List of non-preferred responses. Only used when training_type is 'generativeTraining' (chat mode only). | | generate_non_preferred | generate_non_preferred | boolean | no | For DPO training: Auto-generate non-preferred responses using AI. Only used when training_type is 'generativeTraining' (chat mode only). | | tools | tools | array<object> | no | Optional tools/functions for function calling training (chat mode only). | | scope | scope | string | no | The scope of the training document:

  • training (default): Document will be used for model training
  • validation: Document will be used for model validation/evaluation

Allowed: training, validation | | status | status | string | no | Status for the created training document

Allowed: draft, published |

Always pass snake_case keyword arguments — the Python kwarg column shows the exact name to use for each wire field (as a named parameter where it appears in the method signature, otherwise via **kwargs). The SDK converts it deterministically to the camelCase wire key the API expects. Passing camelCase directly is deprecated: it emits a warning and converts to the same wire key.

Response fields

FieldTypeDescription
successbooleanWhether the operation completed successfully
rawTrainingDataobjectThe transformed conversation in training data format
messageCountintegerTotal number of messages in the generated training data
chatIdstringSource chat identifier (chat mode only, null for file mode)
fileKeystringSource file S3 key (file mode only, null for chat mode)
sourceTypestringIndicates whether training data was generated from chat or file

Allowed: chat, file | | documentCreated | boolean | Whether a training document was created in the knowledge hub | | instructionsApplied | boolean | Whether custom instructions were applied to transform the data | | trainingType | string | The type of training data generated

Allowed: conversationalTraining, generativeTraining | | scope | string | The scope of the training document

Allowed: training, validation | | chunksProcessed | integer | Number of chunks processed (file mode only) | | samplesGenerated | integer | Number of training samples generated (file mode only) | | chunksConfig | object | Configuration used for chunking (file mode only) | | document | object | Created document details (only present when create_document is true) |

Example

client.finetuning.generate_training_data()