Skip to main content

:::note Generated reference Generated from honeyframeapi 0.1.8 — do not edit by hand. :::

honeyframeapi.experiments

Experiment Tracking — log training runs from your own code.

The MLflow-shaped side of Honeyframe's ML surface: an experiment groups runs, and a run carries params, metrics, tags and artifacts. The Analysis Lab fills this ledger by itself; this module is how a script, a notebook or a scheduled job puts its OWN training runs in the same place.

proj = client.get_project(1)
exp = proj.create_experiment("churn", description="Q3 sweep")

run = exp.log_run("xgboost depth=6", params={"depth": 6, "lr": 0.1})
... # train however you like
run.log_metrics({"f1": 0.83, "auc": 0.91})
run.log_artifact("roc.png")
run.finish() # or .finish("failed")

run.download_artifact("roc.png", dest="/tmp/roc.png") # and back out

exp.compare([r.run_id for r in exp.list_runs()])["metrics"]["f1"]

A context manager closes the run for you, including on an exception — which is the point, since a crashed training script otherwise leaves a run 'running' forever:

with exp.start_run("nightly", params={"depth": 6}) as run:
run.log_metrics({"f1": 0.83}) # → finished
# raise → the run is closed as 'failed', and the exception propagates

Promotion is deliberately narrow: ExperimentRun.promote only works on a run the Analysis Lab produced, because that is the only kind the platform can rebuild a reproducible training recipe from. An SDK-logged run raises HoneyframeValidationError saying so rather than registering a model with nothing behind it.

Backed by /api/experiments. Docs: https://docs.honeyframe.io/

class Experiment​

A handle to one project experiment.

Experiment.get_info()​

get_info() -> dict

Refresh the experiment row (run counts, last run time).

Experiment.list_runs()​

list_runs(*, status: Optional[str] = None, limit: int = 200) -> list[ExperimentRun]

Runs of this experiment, newest first.

Experiment.get_run()​

get_run(run_id: int) -> ExperimentRun

Experiment.compare()​

compare(run_ids: list[int]) -> dict

Metrics/params matrix across runs.

Ids that are not in this experiment come back under missing_run_ids — check it rather than assuming every id you asked for is in the matrix.

Experiment.log_run()​

log_run(run_name: str, *, params: Optional[dict] = None, metrics: Optional[dict] = None, tags: Optional[dict] = None, status: RunStatus = 'running') -> ExperimentRun

Open a run (default status='running').

Pass status='finished' with the metrics to record a run that has already completed elsewhere in one call.

Experiment.start_run()​

start_run(run_name: str, *, params: Optional[dict] = None, tags: Optional[dict] = None) -> _RunContext

log_run as a context manager: the run is finished on exit, and closed as failed if the block raises (the exception still propagates). Use it so a crashed script cannot leave a run 'running' forever.

Experiment.delete()​

delete() -> None

Delete the experiment and its runs. A run that was promoted keeps its saved model — the FK lives on the run, not the model.

class ExperimentRun​

A handle to one run. log_* calls MERGE — logging one metric leaves the others alone.

ExperimentRun.get_info()​

get_info() -> dict

ExperimentRun.run_name​

property

run_name: str

ExperimentRun.status​

property

status: str

ExperimentRun.metrics​

property

metrics: dict

ExperimentRun.params​

property

params: dict

ExperimentRun.tags​

property

tags: dict

ExperimentRun.artifacts​

property

artifacts: list

ExperimentRun.saved_model_id​

property

saved_model_id: Optional[int]

ExperimentRun.log_metrics()​

log_metrics(metrics: dict) -> ExperimentRun

Merge metrics into the run (re-logging a key overwrites that key).

ExperimentRun.log_params()​

log_params(params: dict) -> ExperimentRun

ExperimentRun.log_tags()​

log_tags(tags: dict) -> ExperimentRun

ExperimentRun.log_artifact()​

log_artifact(path: str, *, name: Optional[str] = None) -> dict

Upload a local file as an artifact of this run.

The server writes it under the run's own directory in the platform data dir and records its real path — only the basename comes from here.

ExperimentRun.download_artifact()​

download_artifact(name: str, *, dest=None) -> bytes

Read one recorded artifact back, by the name it was logged under.

Returns the file's bytes; pass dest to write them to a local path as well (the bytes still come back, so a checksum needs no re-read). The names are in artifacts — use those, not a local filename you happen to remember, since log_artifact records the basename the server stored.

A run whose DB row names a file the disk no longer has raises HoneyframeAPIError with the platform's 410 — deliberately distinct from a 404 "no such artifact", because the two mean different things when you are diagnosing a restored database against a pruned data dir.

Like log_artifact, the body is held in memory for the length of the call — artifacts are run metadata (plots, reports, a small model dump), not a bulk data path. Use a managed Folder for anything large.

ExperimentRun.finish()​

finish(status: RunStatus = 'finished', *, metrics: Optional[dict] = None) -> ExperimentRun

Close the run. The FIRST terminal write wins — a second finish leaves the recorded outcome and end time alone.

ExperimentRun.promote()​

promote(model_name: str) -> dict

Register this run's model in the saved-model registry.

Only a finished Analysis Lab run can be promoted; anything else raises a validation error naming the reason. Returns the registry row (model_id, name, version).

ExperimentRun.delete()​

delete() -> None

Functions​

list_experiments()​

list_experiments(project) -> list[Experiment]

create_experiment()​

create_experiment(project, name: str, *, description: str = '') -> Experiment

get_experiment()​

get_experiment(project, experiment_id: int) -> Experiment

iter_runs()​

iter_runs(experiment: Experiment, *, limit: int = 200) -> Iterator[ExperimentRun]

The newest limit runs of an experiment, oldest first.

One request: the default returns at most the 200 newest runs (not every run). limit goes up to 1,000, the server's cap; above it raises ValueError.


Verified against honeyframeapi 0.1.8.