A recipe is a Dockerfile-like YAML blueprint for an adapted model. Compile it
with biolm model build (or biolm.models.build_model()); build writes a
locked package under ~/.biolm/models/ with a shouty
BioLM manifest (YAML, no .yaml suffix). The recipe file is not modified.
v0 supports exactly one embedding_head layer, which maps to
xgboost().
See Model finetuning for the workflow and Models for CLI flags.
Recipe (input)
Minimal example
schema_version: 1
name: antibody-binder-clf
from: esm2-8m
layers:
- type: embedding_head
task: classification
data: ./data/binders.csv
Recommended example
schema_version: 1
name: antibody-binder-clf
description: Classify binder vs non-binder from ESM2 embeddings
from: esm2-8m
layers:
- type: embedding_head
task: classification
data: ./data/binders.csv
embedding_models:
- esm2-8m
target_column: label
text_column: sequence
actions:
encode:
input: sequence
predict:
input: sequence
task: classification
Top-level fields
Required
name— package name (slug); may be overridden with--name/name=.from— base model slug used for embeddings (e.g.esm2-8m).layers— list with exactly one layer in v0.
Optional
schema_version— integer; default1.description— human-readable context; copied into the package when set.actions— optional overrides merged into default serving actions. When present, must include bothencodeandpredictkeys.
Layer (embedding_head)
Required
type— must beembedding_head.data— local filesystem path to a training CSV. Relative paths resolve against the recipe file’s directory.
Optional
task—classification(default) orregression.embedding_models— list of model slugs; default is[from].target_column— label column name; defaultlabel.text_column— sequence column name; defaultsequence.
Training CSV
Must exist at build time. Column names must match text_column /
target_column. Content is passed to
xgboost() as train_data.
Package (BioLM manifest)
Build layout:
~/.biolm/models///
├── BioLM
└── artifacts/ # only with --bundle
└──
Example locked manifest (shape; values vary by run):
schema_version: 1
name: antibody-binder-clf
tag: latest
description: Classify binder vs non-binder from ESM2 embeddings
from:
slug: esm2-8m
load: lazy
layers:
- type: embedding_head
task: classification
data:
path: /abs/path/to/binders.csv
embedding_models:
- esm2-8m
target_column: label
text_column: sequence
run_id: ""
artifact:
load: preload
uri: https://example.com/model.joblib
# path: only when bundled
# metrics: ... # when present on the finetune result
actions:
encode:
input: sequence
schema: biolm.encode.v1
predict:
input: sequence
task: classification
schema: biolm.predict.v1
built:
at: "2026-07-21T18:00:00Z"
status: locked
recipe_path: /abs/path/to/antibody-binder-clf.yaml
Package fields
from— object withslug(base model) andload(lazy: resolve the base model at serve time).layers[0].data— object with absolutepathto the training CSV used at build.layers[0].run_id— finetune run that produced the head.layers[0].artifact— head weights policy:load—preload(default for the head).uri— remote or local URI when known (from the finetune result or--artifact).path— absolute path underartifacts/when built with--bundle.
actions— serving contract for MLflow / Modal consumers (viamlflow-biolm). Defaults always includeencodeandpredictwith schema refsbiolm.encode.v1/biolm.predict.v1. Recipeactionsmerge on top of those defaults.built— provenance: UTC timestamp,status: locked, absoluterecipe_path.
Bundle and export
biolm model build … --bundledownloads the head intoartifacts/and setsartifact.path. Requires a URI from the finetune result or an explicit--artifactpath/URL.biolm model export-mlflow name:tag -o ./mlflow-model(requiresmlflow-biolm) turns a package into an MLflow model directory.
Python
from biolm.models import build_model, load_recipe, resolve_package
recipe = load_recipe("models/antibody-binder-clf.yaml")
pkg = build_model("models/antibody-binder-clf.yaml", tag="v1", bundle=True,
artifact="./head.joblib")
print(pkg.path, pkg.manifest["actions"])
print(resolve_package("antibody-binder-clf:v1"))
What is not in v0
Multiple layers, non-
embedding_headtypes, or LoRA / full fine-tune recipes.Dataset IDs or Hub URIs as
data(local CSV path only).Editing the recipe in place; rebuild to refresh the package for a given tag.