Fine-tuning
New
Fine-tuning supports mo (mo-1.3.1) with head_only or lora training.
Mo Fast is inference-only.
Upload a dataset
from modaic import Modaic
client = Modaic()
upload = client.knowledge_base.uploads.upload_file(
"train.jsonl", kind="dataset", name="support-labels", workspace="acme",
)
if upload.status != "completed" or upload.result is None:
raise RuntimeError(upload.error)
training_file = upload.result.name
File helpers handle chunking and wait for validation by default. TypeScript's
file helper requires Node.js. Dataset and artifact uploads support files up to
8 GiB. Names use lowercase
letters, digits, _, and -, start with a letter or digit, and are at most
128 characters. They are unique across datasets and artifacts. If you omit a
name, the server generates one.
Dataset format
Use UTF-8 JSONL, one example per line. Each row contains state and an
answers object with exactly one question ID. Use the same ID on every row;
it must match the job's task_id (Python) or taskId (TypeScript).
{"state":"Checkout is unavailable","answers":{"urgent":true},"split":"train"}
{"state":"Can I change my invoice address?","answers":{"urgent":false},"split":"validation"}
{"state":"All payment attempts fail","answers":{"urgent":true},"split":"test"}
Labels are booleans for Noul, option keys for Choice, or zero-based integer levels for Score. This three-row example shows the format; use representative data for training.
Provide split on every row or omit it everywhere for automatic assignment.
Training datasets need nonempty train, validation, and test partitions.
Optional groupId keeps related rows in one partition; identical visible inputs
must also stay in one partition. IDs, when supplied, must be unique.
Limits: 1,000,000 rows, 1 MiB per line, no blank lines.
Optional questions overrides instructions for that row's task only:
{"questions":{"urgent":{"instructions":"Does this block checkout?"}}}.
Start fine-tuning
For an existing model, its saved question schema is reused:
job = client.fine_tunes.create(
model="acme/support-priority",
training_file=training_file,
task_id="urgent",
training_type="head_only",
idempotency_key="support-tune-v1",
)
job = client.fine_tunes.wait(job.id)
print(job.status, job.error)
To create a new model, pass model="mo", a destination such as
acme/support-priority, and questions containing the task schema.
training_type="lora" / trainingType: "lora" selects LoRA training.
Successful training publishes a new checkpoint to the selected model branch;
the branch defaults to main. The REST request can set branch to publish an
experiment without moving main, and can set tag to create an immutable name
for the completed checkpoint. The branch must already exist. This lets an
orchestrator such as Protégé train and evaluate on a working branch, then use
the repository merge API to fast-forward main after it decides to promote
the result.
After artifact validation, training selects the new weights in model.json
with readiness unknown, then evaluates the exact immutable artifact commit.
Held-out model quality becomes passed, warning, or unknown readiness
metadata. Evaluation infrastructure failure leaves the checkpoint published
with unknown readiness. Runtime compatibility and serving isolation are
verified before deployment rather than reported as per-model readiness.
Malformed or unloadable artifacts and identity mismatches still fail the job.
Optional controls include epochs, learning rate, batch size, and evaluation
frequency. Python accepts controls={"n_epochs": 2}; TypeScript accepts
nEpochs: 2 directly. Evaluations require validation_file / validationFile;
early stopping also requires enough evaluations for warmup and patience.
See create fine-tune for all fields.
Monitor or cancel
job = client.fine_tunes.get(job.id)
logs = client.fine_tunes.logs(job.id)
recent = client.fine_tunes.list(workspace="acme")
client.fine_tunes.cancel(job.id)
wait returns done, failed, or cancelled jobs. Check status and error;
a timeout stops waiting without cancelling the job. The completed job's
result.publication identifies the commit, branch, and optional tag.
Artifacts and downloads
Upload other files with kind="artifact". Artifacts are stored resources;
they are not training datasets.
artifact = client.knowledge_base.uploads.upload_file(
"report.pdf", kind="artifact", name="support-report", workspace="acme",
)
resources = client.knowledge_base.resources.list(workspace="acme", kind="artifact")
metadata = client.knowledge_base.resources.get("support-report", workspace="acme")
content = client.knowledge_base.resources.download("support-report", workspace="acme")
For another resource page, pass both the returned cursor and commit:
cursor=resources.next_cursor, commit_sha=resources.commit_sha in Python,
or cursor: resources.nextCursor, commitSha: resources.commitSha in TypeScript.