Merge and Retrain
ColabHive treats merge and retrain-on-top as first-class, generic operations. Together they form a flywheel: combine capabilities that already exist, train new capability on top of the result, and feed that result back in as the base for the next round — indefinitely, with nothing hardcoded.
adapter ─► merge ─► serve ─► retrain ─► (new base) ─► merge ─► ...
Every step produces an ordinary model_version. A merged model is not a special artifact: it is
served through the normal inference path and reused as a base exactly like any trained model.
This guide walks the full loop with real product APIs: train an adapter → merge it into a base → serve the merged model → retrain on top → inspect lineage → repeat. All identifiers below are placeholders — nothing here is specific to any one model or domain.
Prerequisites: an API key and account ID (see Authentication), and the
Python SDK (pip install colabhive).
from colabhive import ColabHive
import os
client = ColabHive(
api_key=os.getenv("COLABHIVE_API_KEY"),
account_id=os.getenv("COLABHIVE_ACCOUNT_ID"),
)
Step 1 — Train an adapter
Fine-tune an adapter on your dataset with an LLM QLoRA template. (If you already have a trained
adapter or model, skip to Step 2 and reference it by version_id.)
adapter_job = client.training.create(
model="MODEL_CONFIG_UUID", # a QLoRA template from client.training.model_configs()
dataset_id="DATASET_A_UUID",
job_name="domain-adapter-v1",
hyperparameters={"adapter": "qlora", "epochs": 3, "learning_rate": 0.0002},
)
adapter_job.wait()
print(adapter_job.status) # -> "completed"
Grab the version_id this run produced — a completed job reports it as produces_version_id. (A
job's .model_id is the training template it ran from, not the model it produced, so don't
resolve versions off .model_id.)
adapter_version = adapter_job.produces_version_id
Step 2 — Merge the adapter into a base
Fold the adapter into a base model to produce a standalone full model (bf16). Merging is weight
arithmetic on CPU — no GPU, no training data.
merge = client.training.merge(
name="qwen-domain-base",
base={"type": "hf", "repo_id": "Qwen/Qwen2.5-7B-Instruct"}, # optional; auto-detected if omitted
adapters=[{"type": "model_version", "version_id": adapter_version}],
)
print(merge.job_id, merge.status) # -> "queued"
merge.wait() # blocks until the merged model_version is registered
merged_version = merge.produces_version_id
cURL equivalent:
curl -X POST "https://api.colabhive.com/api/builder/v1/training/merges" \
-H "Content-Type: application/json" \
-H "X-API-Key: $COLABHIVE_API_KEY" \
-d '{
"name": "qwen-domain-base",
"adapters": [{"type": "model_version", "version_id": "ADAPTER_VERSION_UUID"}]
}'
Merge methods — adapter_merge (default; fold LoRA adapters into a base) or, to combine several
full models, slerp, ties, or dare with sources:
client.training.merge(
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],
)
A merge is a job — it counts against your account's training quota. Chains are never re-quantized, so
precision stays bf16 and quality does not decay round to round.
Step 3 — Serve the merged model
A merged model is a normal model_version. Promote it to an endpoint the same way as any trained
run, then run inference. Register with visibility="public" if you want other accounts to be able to
use it as a base too.
endpoint = client.training.register_for_inference(
run_id=merge.job_id,
name="qwen-domain-base",
description="Base model with domain adapter merged in.",
visibility="account",
)
result = client.endpoints.infer(
endpoint.endpoint_id,
{"messages": [{"role": "user", "content": "Summarize this quarter's report."}]},
)
print(result["result"])
A newly produced model enters as
candidateand becomesreadyafter an inference test — verify it works before relying on it. See Inference Lifecycle.
Step 4 — Retrain on top of the merged model
Start a new training run whose base is the merged model: pass a base reference pointing at the
merged version_id. Mix in fresh data and, optionally, enable replay to guard against forgetting.
v2 = client.training.create(
model="MODEL_CONFIG_UUID",
dataset_id="DATASET_B_UUID",
job_name="domain-expert-v2",
base={"type": "model_version", "version_id": merged_version},
hyperparameters={
"adapter": "qlora",
"epochs": 2,
"learning_rate": 0.0001,
"replay_fraction": 0.25, # optional anti-forgetting knob
},
)
v2.wait()
The new version records base_model_version_id = the merged model and parent_job_id = its job,
automatically.
Step 5 — Inspect lineage and rename
Query the base→derivatives graph, then rename a version. Names are mutable labels — renaming never
breaks the chain, because identity is the version_id, not the name.
graph = client.models.lineage(v2.model_id)
for edge in graph["edges"]:
print(edge["from"], "->", edge["to"])
# Rename is nested under the OWNING model: PATCH /models/{model_id}/versions/{version_id}.
# Pair merged_version with the model_id that actually owns it — read that from the version's
# own lineage node. Pairing it with the retrain job's model_id (a different model) would 404.
merge_model_id = next(
n["model_id"] for n in graph["nodes"]
if n["version_id"] == merged_version and not n.get("restricted")
)
client.models.rename(merge_model_id, merged_version, name="qwen-domain-base-approved")
cURL:
curl "https://api.colabhive.com/api/builder/v1/models/MODEL_UUID/lineage" \
-H "X-API-Key: $COLABHIVE_API_KEY"
Step 6 — Spin the flywheel
The v2 model is itself a normal model_version — feed it back into Step 2 (merge in another
adapter) or Step 4 (retrain again). Each turn compounds capability while lineage keeps the whole
history navigable.
Reference: ArtifactRef
You point at inputs by reference, and the platform resolves them to storage + metadata, validates ownership, and stages them — you never write a storage path.
type | Use it for |
|---|---|
hf | A HuggingFace repo (repo_id, optional revision) |
model_version | Any trained or merged version you own or that is public (version_id) |
job | A training job's output version (job_id) |
storage | Advanced escape-hatch: a direct s3:// URL |
Public versions are usable by anyone; private versions only by their owner. To let another account build on your model, publish it. Full type reference: ArtifactRef.
See also
- Merge & Retrain API — full request/response contract.
- SDK Reference —
client.training.merge(...)andclient.training.create(base=...). - Merged & Retrained Models — how results appear in the catalog.
- LLM Fine-Tuning — training LLMs on ColabHive.
Authors: José Luis Minich, Maximiliano Lucius.