Merge & Retrain API
Merge and retrain-on-top are first-class platform operations: any account can (a) merge one or more trained models/adapters into a base, and (b) retrain on top of any trained or merged model — through the normal product APIs, with nothing hardcoded.
Both operations resolve their inputs generically, by catalog reference (an ArtifactRef),
never by hand-written storage paths. The result of either operation is an ordinary model_version:
servable through the normal inference path and reusable as a base — with full lineage recorded.
Base URL: https://api.colabhive.com/api/builder/v1
All endpoints require an API key; the account is derived from that key. X-Account-ID is optional
and, if supplied, must match the key's account. Merge and retrain runs count against your account's
training quota (a merge is a job, like any other).
ArtifactRef
A base, adapter, or source is always referenced as an ArtifactRef — a discriminated union on
type. The gateway resolves the reference to a storage location and metadata (framework, precision,
detected base) from the catalog, validates ownership, and builds the internal staging. You never
manipulate object-store paths directly.
type | Shape | Meaning |
|---|---|---|
hf | { "type": "hf", "repo_id": "Qwen/Qwen2.5-7B-Instruct", "revision": "main" } | A HuggingFace repo. revision defaults to main. Travels as the base repo; not staged. |
model_version | { "type": "model_version", "version_id": "<uuid>" } | Any trained or merged model_version you own or that is public. |
job | { "type": "job", "job_id": "<uuid>" } | Shortcut: uses the output version of a training job. |
storage | { "type": "storage", "storage_url": "s3://..." } | Advanced escape-hatch: a direct s3:// URL. Not the normal path. |
Ownership & visibility
Resolution reuses ColabHive's existing visibility mechanism — no new permission model is invented:
- Public model version → any account may use it as a base/adapter/source.
- Private → only the owner. To let others build on your model, publish it (make it public).
- The lineage always records the origin, so provenance survives even across accounts.
A storage-type reference has no catalog entry to check visibility against — it is trusted to the
authenticated caller and intended for advanced use only.
Merge models
POST /training/merges
Merges N trained models/adapters into a base and produces a new full model_version. Merging is
weight arithmetic and runs on CPU — it does not consume GPU. The output is framework=transformers,
precision=bf16 (chains are never re-quantized), servable and reusable as a base.
For retry-safe creation, send Idempotency-Key with a UUID value. The key is scoped to the account
and operation for 24 hours. Repeating the same request returns the original response with
Idempotency-Replayed: true; reusing the key with a different body returns HTTP 409.
Request:
{
"name": "qwen-domain-base",
"base": { "type": "hf", "repo_id": "Qwen/Qwen2.5-7B-Instruct" },
"method": "adapter_merge",
"adapters": [ { "type": "model_version", "version_id": "ADAPTER_VERSION_UUID" } ],
"sources": [],
"weights": null,
"precision": "bf16",
"hardware_preference": "cpu_only"
}
| Field | Type | Default | Notes |
|---|---|---|---|
name | string | — (required) | Name of the resulting model_version. |
base | ArtifactRef | auto-detected | Optional. If omitted, the base is auto-detected from the first adapter/source. |
method | string | adapter_merge | adapter_merge | slerp | ties | dare. Extensible. |
adapters | ArtifactRef[] | [] | 1..N adapters. Required for adapter_merge. |
sources | ArtifactRef[] | [] | 1..N full models. Required for slerp / ties / dare. |
weights | array | null | Optional per-method weights/parameters (e.g. TIES/DARE ratios). |
precision | string | bf16 | Default bf16; never re-quantize in a chain. |
hardware_preference | string | cpu_only | Merge is weight arithmetic → CPU. |
Method rules (validated):
methodmust be one of the allowed values, or400.- At least one of
adaptersorsourcesis required, or400. adapter_mergerequires ≥ 1 adapter;slerp/ties/darerequire ≥ 1 source.
Response 201:
{
"job_id": "MERGE_JOB_UUID",
"produces_version_id": null,
"status": "queued",
"lineage": { "base_model_version_id": "PRIMARY_INPUT_VERSION_UUID" }
}
produces_version_id is null at creation and is populated once the job completes and the registrar
creates the model_version. Poll the job with GET /training/runs/{job_id}.
cURL:
curl -X POST "https://api.colabhive.com/api/builder/v1/training/merges" \
-H "Content-Type: application/json" \
-H "X-Account-ID: YOUR_ACCOUNT_ID" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"name": "qwen-domain-base",
"adapters": [{"type": "model_version", "version_id": "ADAPTER_VERSION_UUID"}]
}'
Multi-source example (TIES):
{
"name": "ensemble-base",
"method": "ties",
"sources": [
{ "type": "model_version", "version_id": "MODEL_A_VERSION_UUID" },
{ "type": "model_version", "version_id": "MODEL_B_VERSION_UUID" }
],
"weights": [0.5, 0.5]
}
Retrain on top
Retrain-on-top is an extension of POST /training/runs: the
base of the run can be an existing trained or merged model_version (or a job/storage/HF repo)
instead of the base defined by the model_config.
Two first-class optional fields are added to the training-run create request:
| Field | Type | Notes |
|---|---|---|
base | ArtifactRef | Optional. model_version / job / storage → retrain-on-top (staged as the base). hf or omitted → current behavior (base from the model_config). |
parent_job_id | string | null | Optional lineage parent. Derived automatically from base if not provided. |
Request:
{
"job_name": "domain-expert-v2",
"model_config_id": "MODEL_CONFIG_UUID",
"dataset_id": "DATASET_UUID",
"base": { "type": "model_version", "version_id": "MERGED_OR_TRAINED_VERSION_UUID" },
"parent_job_id": null,
"hyperparameters": { "learning_rate": 0.0002, "num_epochs": 3, "adapter": "qlora" }
}
hyperparametersnow carries only hyperparameters (learning rate, epochs, adapter, sequence length, …). The base and staging are derived from thebasefield — you no longer smuggle them throughhyperparameters.- Back-compat: if
stage_artifacts/base_model_version_id/base_modelstill arrive insidehyperparameterswhilebaseis also set, the first-classbasetakes precedence and a deprecation warning is logged.
The response is the created run (see Create Training Run). The
resulting model_version records base_model_version_id and parent_job_id for lineage.
Model lineage
GET /models/{model_id}/lineage
Returns the base→derivatives graph for a model, walking base_model_version_id up (ancestors/bases)
and down (derivatives). This powers the "use as base" UI and full history traceability — provenance
holds even after models are renamed, because identity is the version_id, not the name.
Response:
{
"model_id": "MODEL_UUID",
"model_name": "qwen-domain-base",
"root_version_ids": ["VERSION_UUID_1"],
"nodes": [
{
"version_id": "VERSION_UUID_1",
"base_model_version_id": "PARENT_VERSION_UUID",
"restricted": false,
"model_id": "MODEL_UUID",
"model_name": "qwen-domain-base",
"version_name": "v1",
"framework": "transformers",
"precision": "bf16",
"training_job_id": "JOB_UUID",
"created_at": "2026-07-23T00:00:00Z"
},
{
"version_id": "PARENT_VERSION_UUID",
"base_model_version_id": null,
"restricted": true
}
],
"edges": [
{ "from": "PARENT_VERSION_UUID", "to": "VERSION_UUID_1" }
]
}
- Each node always exposes its
version_idand edges (complete traceability). Rich metadata appears only for nodes the caller may see; nodes you cannot see are returned with"restricted": trueand no metadata. 403if the target model is private and not owned by the caller;404if not found.
Rename a model version
PATCH /models/{model_id}/versions/{version_id}
A model version's name is a mutable label. Renaming does not change its identity (version_id)
or break lineage. Only the owner can rename.
Request:
{ "name": "qwen-domain-base-approved" }
Response:
{
"version_id": "VERSION_UUID",
"model_id": "MODEL_UUID",
"version_name": "qwen-domain-base-approved",
"framework": "transformers",
"precision": "bf16",
"base_model_version_id": "PARENT_VERSION_UUID",
"training_job_id": "JOB_UUID"
}
403 if the caller is not the owner; 404 if the version does not exist under that model.
See Also
- The Model Flywheel — the concept behind merge + retrain-on-top
- End-to-end tutorial — build a flywheel step by step
- Training API — the base training-run surface
- Models API — catalog, versions, download
- Merged & Retrained Models — how results appear in the catalog
- MCP Tools Reference —
training.merge/training.retrain_onfor agents
Authors: José Luis Minich, Maximiliano Lucius.