LoggedModels and model-centric tracking

MLflow · Expert · 12 min

In MLflow 3 the model, not the run, is the central object, which matters for GenAI apps and checkpoint selection.

Before MLflow 3, a model was just an artifact inside a run. MLflow 3 introduces the LoggedModel as a first-class entity with its own ID (m-...), parameters, metrics, tags and status, which can be linked to several runs.

What this enables:

  • Checkpoints as models: during deep learning training you can log a model per epoch (log_model(..., step=epoch)) and log metrics with model_id=...; then mlflow.search_logged_models(filter_string="metrics.val_acc > 0.9", order_by=[...]) picks the best checkpoint directly.
  • Evaluation across runs: evaluating an existing model in a new run links the resulting metrics back to that model's ID, so each model page shows all its evaluations.
  • GenAI versions without weights: mlflow.set_active_model(name="support-agent-v3") creates or selects a LoggedModel that represents an application version (code, prompts, config). Traces produced while it is active are linked to it, so you can compare quality and latency between app versions.

mlflow.last_logged_model() returns the most recent one, and mlflow.get_logged_model(model_id) loads metadata. Registry versions point at LoggedModels, so lineage runs from deployed alias to model to training run and dataset.

Code written for MLflow 2 (artifact_path=, runs:/ URIs) mostly still works, but artifact_path is deprecated in favour of name, and new features assume model IDs.

Example

import mlflow
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression

X, y = load_iris(return_X_y=True, as_frame=True)
mlflow.set_experiment("checkpoints")

with mlflow.start_run():
    for i, C in enumerate([0.01, 0.1, 1.0]):
        m = LogisticRegression(C=C, max_iter=1000).fit(X, y)
        info = mlflow.sklearn.log_model(m, name=f"lr-{i}", params={"C": C},
                                        input_example=X.head(2))
        mlflow.log_metric("train_acc", m.score(X, y), model_id=info.model_id)

best = mlflow.search_logged_models(
    order_by=[{"field_name": "metrics.train_acc", "ascending": False}],
    output_format="list", max_results=1)[0]
print(best.name, best.params)   # lr-2 {'C': '1.0'}

mlflow.set_active_model(name="support-agent-v3")   # GenAI app version; traces link to it

Remember

  • LoggedModel is a first-class entity with an ID, metrics and params
  • Log metrics with model_id and pick checkpoints with search_logged_models
  • set_active_model versions GenAI apps and links their traces

Watch out for

  • Continuing to use artifact_path= and parsing run artifact paths, instead of using model IDs that MLflow 3 features rely on.

Check yourself

  1. What is the main change in how MLflow 3 models relate to runs?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: mlflow.org/docs/latest/ml/mlflow-3/