Skip to content
elevatedevco

Data & MLOps

MLflow & Experiment Tracking

Learn MLflow & Experiment Tracking: 50 practice questions and answers with an interactive quiz — from the offline AI Learning app.

Professional50 questions17 quiz questions

Questions & Answers

Tap a question to reveal its answer. Written for self-study and interview preparation.

What are the four core components of MLflow?

MLflow has four core components: Tracking logs parameters, metrics, and artifacts for every experiment run; Projects packages ML code reproducibly using an MLproject YAML file with dependency specifications; Models provides a standard format for saving and loading models with multiple deployment flavors such as sklearn, pyfunc, and pytorch; Model Registry manages model versioning with lifecycle stages and named aliases. Together these components cover the full ML lifecycle from experimentation through production deployment.

How does mlflow.log_param differ from mlflow.log_metric?

mlflow.log_param records a static key-value hyperparameter (string or numeric) once per key per run, representing settings like learning rate or batch size. mlflow.log_metric records a numeric value with an optional step index, enabling time-series tracking across training epochs. Parameters appear as static metadata; metrics support history and can be plotted over steps. For batch operations use log_params(dict) and log_metrics(dict). Metrics are strictly floating-point, while parameters accept strings. Both are queryable via the search_runs API with SQL-like filter expressions.

mlflow.log_param("lr", 0.001)
mlflow.log_metric("val_loss", 0.23, step=5)
What is an MLflow experiment and how do you create one?

An MLflow experiment is a named container that groups related runs. Each experiment has a unique integer ID and a unique name. Runs always belong to exactly one experiment. Experiments organize work by project, model type, or team. Create them with mlflow.create_experiment() or switch the active experiment with mlflow.set_experiment(). The default experiment has ID 0. Deleting an experiment moves it to a Deleted lifecycle state; data is retained for a configurable retention period before permanent removal. Experiments are stored in the configured backend store.

mlflow.set_experiment("fraud_detection_v2")
How do you enable autologging for scikit-learn in MLflow?

Call mlflow.sklearn.autolog() before fitting any estimator. MLflow automatically captures hyperparameters from the estimator constructor, training and validation scores, model artifacts, and feature importance plots for tree-based models. The universal mlflow.autolog() enables autologging for all supported frameworks simultaneously. If no active run exists when fit() is called, MLflow creates one automatically. Fine-tune behavior with keyword arguments: log_models=False skips model serialization, log_input_examples=True logs sample inputs, silent=True suppresses autolog warnings. Autolog also captures post-training metrics from evaluate calls.

import mlflow
mlflow.sklearn.autolog(log_input_examples=True)
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators=100)
rf.fit(X_train, y_train)
What lifecycle stages does the MLflow Model Registry support?

MLflow Model Registry supports four stages: None (the default when a version is first registered), Staging (for testing and validation before production), Production (serving live traffic), and Archived (deprecated versions no longer in active use). Stage transitions are recorded with timestamps and optional comments. In MLflow 2.x, model aliases are the recommended approach — string labels like champion or challenger point to specific versions, decoupling deployment semantics from rigid stage names. Aliases are set with client.set_registered_model_alias() and resolved with client.get_model_version_by_alias().

client.set_registered_model_alias("fraud_model", "champion", version=3)
What data does an MLflow run capture and what is its structure?

An MLflow run is the atomic unit of tracking. It captures: parameters (hyperparameters), metrics (numeric time-series values), tags (arbitrary key-value metadata), and artifacts (files such as models, plots, and datasets). Each run holds a unique run_id, parent experiment_id, run_name, start/end timestamps, duration, and a status (RUNNING, FINISHED, FAILED, KILLED). Runs can be nested using the parent_run_id parameter to represent sub-tasks or child runs of a hyperparameter sweep. Run data is stored in the backend store; artifacts go to the artifact store.

with mlflow.start_run(run_name="baseline") as run:
    mlflow.log_param("epochs", 10)
    mlflow.log_metric("accuracy", 0.92)
    print(run.info.run_id)
How do you log files and directories as artifacts in MLflow?

Use mlflow.log_artifact(local_path, artifact_path=None) to upload a single file to the run's artifact store. The optional artifact_path specifies a subdirectory within the artifact directory. Use mlflow.log_artifacts(local_dir, artifact_path=None) to upload all files in a directory. Artifacts are stored in the configured artifact store (local filesystem, S3, Azure Blob Storage, GCS, or HDFS). Retrieve them later with mlflow.artifacts.download_artifacts(run_id=..., artifact_path=...). Common artifacts include serialized models, confusion matrices, tokenizer files, and SHAP summary plots.

mlflow.log_artifact("model.pkl", artifact_path="models")
mlflow.log_artifacts("./plots/", artifact_path="charts")
What is a model flavor in MLflow and why does it matter?

A model flavor is a convention that defines how a model is serialized, deserialized, and served using a specific ML framework. Built-in flavors include sklearn, pytorch, tensorflow, xgboost, lightgbm, huggingface, and pyfunc. Each flavor knows the correct API for loading its model type. The pyfunc flavor is the universal Python flavor — any model wrapped as mlflow.pyfunc.PythonModel can be loaded generically without framework-specific knowledge. A saved MLflow model can expose multiple flavors simultaneously, giving consumers flexibility. Flavors also determine how the model is served via mlflow models serve.

What backend stores does MLflow Tracking support and which is recommended for production?

MLflow Tracking supports two categories of backend stores. File stores write run metadata to the local filesystem as YAML/JSON (default: ./mlruns directory). Database stores use SQLAlchemy-compatible databases including SQLite, PostgreSQL, MySQL, and Microsoft SQL Server. The backend URI is set via mlflow.set_tracking_uri() or the MLFLOW_TRACKING_URI environment variable. For production, PostgreSQL is strongly recommended: it supports concurrent writes, efficient querying of run history, and reliable distributed access. SQLite is suitable only for single-user local development due to write locking limitations.

mlflow.set_tracking_uri("postgresql://user:pass@db-host:5432/mlflow")
What is an MLflow model signature and how do you create one?

A model signature defines the expected schema for a model's inputs and outputs, specifying column names, types (long, double, string, binary), and tensor shapes. It enables input validation at inference time and serves as documentation. Infer signatures automatically with mlflow.models.infer_signature(input_data, predictions). Signatures can be ColSpec-based for tabular data or TensorSpec-based for tensors. In MLflow 2.x, pyfunc enforces signatures during prediction by default, raising exceptions on type mismatches. Attach signatures when logging: mlflow.sklearn.log_model(model, name, signature=sig). They also power the OpenAPI spec generated by mlflow models serve.

from mlflow.models import infer_signature
sig = infer_signature(X_train, model.predict(X_train))
mlflow.sklearn.log_model(model, "model", signature=sig)
What is MLflow Recipes and what problem does it address?

MLflow Recipes (formerly MLflow Pipelines) is a framework for building standardized, opinionated ML pipelines using predefined step templates. It solves the inconsistency problem across teams where every project has a bespoke pipeline structure. Recipes are configured via YAML files and consist of ordered steps: ingest, split, transform, train, evaluate, and register. Each step is implemented as a Python function with defined inputs and outputs. Step outputs are cached, avoiding redundant computation on reruns. Recipes integrate automatically with MLflow Tracking and enforce best practices including reproducibility and test-set holdout discipline. Templates exist for regression and classification tasks.

# recipe.yaml snippet
recipe: "regression/v1"
target_col: "price"
primary_metric: "root_mean_squared_error"
What does mlflow.set_tracking_uri() do and what values does it accept?

mlflow.set_tracking_uri() sets the location where MLflow stores and retrieves run metadata. It accepts a local file path (file:///tmp/mlruns), an HTTP URL to a remote MLflow Tracking Server (http://mlflow-server:5000), or a database connection URI (postgresql://user:pass@host/db). Once set, all subsequent mlflow.log_* and mlflow.start_run() calls in the process use that backend. The MLFLOW_TRACKING_URI environment variable serves the same purpose and takes precedence over programmatic settings. Databricks workspaces use the special value databricks to route tracking through the Databricks hosted MLflow service.

mlflow.set_tracking_uri("http://mlflow.company.com:5000")
How do you compare multiple MLflow runs programmatically?

Use mlflow.search_runs(experiment_ids=[...]) which returns a Pandas DataFrame. Each row is a run; columns are prefixed with params. for parameters and metrics. for metrics. Filter with the filter_string argument (SQL-like syntax: "metrics.accuracy > 0.9 AND params.model_type = 'xgb'") and sort via order_by. MlflowClient().search_runs() provides finer control including pagination via page_token. The DataFrame enables downstream analysis: finding the best run, computing metric distributions, or exporting results. The MLflow UI's Runs Comparison view provides visual side-by-side charts without code.

df = mlflow.search_runs(
    experiment_ids=["1"],
    filter_string="metrics.accuracy > 0.9",
    order_by=["metrics.accuracy DESC"]
)
best = df.iloc[0]
What are MLflow system metrics and how do you enable them?

MLflow system metrics (introduced in MLflow 2.8) automatically log hardware resource utilization during training runs using a background thread. Captured metrics include CPU utilization, RAM usage, GPU memory, GPU utilization percentage, and disk I/O — prefixed with system/ in the tracking UI. Enable by calling mlflow.enable_system_metrics_logging() before starting a run, or set the MLFLOW_ENABLE_SYSTEM_METRICS_LOGGING=true environment variable. The sampling interval defaults to 10 seconds and is configurable via mlflow.set_system_metrics_sampling_interval(). System metrics help diagnose bottlenecks such as CPU-bound data loading or underutilized GPU memory.

mlflow.enable_system_metrics_logging()
with mlflow.start_run():
    train_model()  # system/cpu_utilization_percentage auto-logged
How do you deploy an MLflow model as a local REST endpoint?

Use the mlflow models serve CLI command, pointing to the model URI (run, registry, or local path). The server exposes a POST /invocations endpoint that accepts JSON or CSV input and returns predictions. The Content-Type header controls input format: application/json for split/records-oriented JSON and text/csv for CSV. For scored JSON with column names use the split format. The server validates inputs against the model signature. For production, wrap the MLflow model in a custom FastAPI/Flask service for additional middleware, authentication, or input preprocessing logic.

# Terminal
mlflow models serve -m "models:/fraud_model/Production" -p 8080

# Call it
curl -X POST http://localhost:8080/invocations \
  -H 'Content-Type: application/json' \
  -d '{"dataframe_split": {"columns": ["f1"], "data": [[1.2]]}}'
What is the default artifact store location when running MLflow locally?

When running MLflow locally without any configuration, artifacts are stored in the ./mlruns directory relative to where the Python script is executed. Within that directory, each experiment has a numeric subdirectory (e.g., ./mlruns/0/) and each run has a further subdirectory keyed by run_id, containing an artifacts/ folder. This file-based artifact store is only suitable for local development. In production, configure a remote artifact store such as S3, Azure Blob Storage, GCS, SFTP, or HDFS by setting the artifact_location when creating an experiment or configuring the server.

How do you register a trained model into the MLflow Model Registry?

Register a model in three ways. First, pass registered_model_name to log_model: mlflow.sklearn.log_model(model, 'model', registered_model_name='FraudDetector'). Second, call mlflow.register_model(model_uri, name) after the run completes. Third, use MlflowClient().create_registered_model() and create_model_version() for programmatic control. Each registration creates a new model version. The model URI format for runs is runs:/<run_id>/model_path. After registration, transition versions through stages or assign aliases using MlflowClient().set_registered_model_alias(). Registration requires a connected Model Registry (database or Databricks backend).

mlflow.sklearn.log_model(
    model, "model",
    registered_model_name="FraudDetector"
)
# or after run:
mlflow.register_model(f"runs:/{run_id}/model", "FraudDetector")
What is the difference between mlflow.start_run() and mlflow.active_run()?

mlflow.start_run() creates a new run (or resumes one if a run_id is provided) and returns a Run object. It can be used as a context manager to auto-end the run on exit or called manually with mlflow.end_run(). mlflow.active_run() returns the currently active Run object without creating a new one — returning None if no run is active. Use active_run() inside helper functions to access the current run's metadata (ID, experiment ID) without needing to pass run objects explicitly through function arguments. Nested calls to start_run() with nested=True create child runs under the active parent run.

with mlflow.start_run():
    run = mlflow.active_run()
    print(f"Run ID: {run.info.run_id}")
How do nested runs work in MLflow and when should you use them?

Nested runs model hierarchical ML workflows where a parent run represents the overall job (e.g., a hyperparameter search) and child runs represent individual trials. Create a child run by passing nested=True to mlflow.start_run() while a parent run is active. Children inherit the parent's experiment and are linked via parent_run_id in RunInfo. The MLflow UI displays nested runs in a collapsible tree. Use nested runs for hyperparameter sweeps, cross-validation folds, multi-step pipelines, or ensemble training where each component trial should be independently queryable but logically grouped under a parent.

with mlflow.start_run(run_name="sweep"):
    for lr in [0.01, 0.001]:
        with mlflow.start_run(run_name=f"lr={lr}", nested=True):
            mlflow.log_param("lr", lr)
What is mlflow.evaluate() and what does it produce?

mlflow.evaluate() provides a standardized way to compute and log model evaluation metrics against a dataset. Pass the model URI (or a callable), an evaluation dataset, and a model_type ('classifier', 'regressor', 'text'). MLflow computes standard metrics automatically (accuracy, F1, AUC for classifiers; RMSE, MAE, R2 for regressors) and logs them to the active run along with artifacts like confusion matrices, ROC curves, and residual plots. Custom metrics are added via extra_metrics=[make_metric(...)]. In MLflow 2.x, evaluate() also supports LLM judge metrics using language models as evaluators, enabling automated quality scoring for generative outputs.

result = mlflow.evaluate(
    model=f"runs:/{run_id}/model",
    data=eval_df,
    targets="label",
    model_type="classifier"
)
print(result.metrics)
What is the MLproject file format in MLflow Projects?

An MLproject file is a YAML configuration file placed at the root of an MLflow Project directory. It defines the project name, environment specification (conda, virtualenv, docker, or system), and entry points. Each entry point specifies the command to run, expected parameters with types and defaults, and optionally the command template. The environment section references a conda.yaml or requirements.txt for dependency pinning. Projects can be run locally, remotely on Kubernetes, or via mlflow run <uri>. The URI can be a local path, GitHub URL, or GitHub URL with a specific commit, enabling reproducible re-execution of any historical training run.

# MLproject
name: FraudModel
conda_env: conda.yaml
entry_points:
  main:
    parameters:
      lr: {type: float, default: 0.01}
    command: "python train.py --lr {lr}"
Which MLflow autolog function covers XGBoost training?

mlflow.xgboost.autolog() automatically logs XGBoost training metadata when called before xgb.train() or XGBClassifier.fit(). It captures hyperparameters from booster parameters, evaluation metrics at each boosting round (logged as time-series with step values), feature importance scores as artifacts, and the trained booster model. The universal mlflow.autolog() also enables XGBoost autologging. In MLflow 2.x, autologging for XGBoost also captures input examples and model signatures by default. Set log_models=False to skip model artifact logging for faster iteration during hyperparameter sweeps where only metrics matter.

import mlflow.xgboost
mlflow.xgboost.autolog()
model = xgb.XGBClassifier(n_estimators=200, learning_rate=0.05)
model.fit(X_train, y_train, eval_set=[(X_val, y_val)])
How do you configure a remote MLflow Tracking Server for a team?

Run mlflow server with explicit backend and artifact store configurations. Use --backend-store-uri to point to a PostgreSQL database and --default-artifact-root to specify a shared artifact location such as an S3 bucket. Secure the server with --host 0.0.0.0 and a reverse proxy (Nginx/Traefik) with TLS termination and authentication middleware. Set MLFLOW_TRACKING_URI on all client machines to the server URL. For artifact access, configure client AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) or IAM roles so clients can directly upload artifacts to S3, bypassing the tracking server for large binary transfers.

mlflow server \
  --backend-store-uri postgresql://user:pass@host/mlflow \
  --default-artifact-root s3://company-mlflow-artifacts \
  --host 0.0.0.0 --port 5000
How do you use MLflow with PyTorch for experiment tracking?

Use mlflow.pytorch.autolog() to automatically capture PyTorch Lightning training metrics, or manually log with mlflow.pytorch.log_model() for vanilla PyTorch. For manual tracking, wrap training in mlflow.start_run(), log hyperparameters and metrics per epoch, then save the model with mlflow.pytorch.log_model(model, 'model'). To load: mlflow.pytorch.load_model(model_uri). For PyTorch Lightning, autolog hooks into the Trainer callbacks and captures loss curves, learning rate schedules, and epoch-level metrics. The saved model is stored with the torch flavor and can be loaded back via the pyfunc interface for framework-agnostic inference.

import mlflow.pytorch
mlflow.pytorch.autolog()
trainer = pl.Trainer(max_epochs=20)
trainer.fit(model, train_loader)
What is the MLflow AI Gateway (Deployments Server) and what does it solve?

The MLflow AI Gateway (previously called MLflow Deployments Server) is a unified reverse proxy for LLM API providers including OpenAI, Anthropic, Cohere, Azure OpenAI, and HuggingFace Inference Endpoints. It solves provider lock-in and credential management by exposing a single standardized MLflow API regardless of the underlying provider. Teams configure routes (endpoint definitions) in a YAML config; clients call one API. The gateway handles API key injection server-side, rate limiting, and provider failover. This enables vendor swapping without application code changes and centralizes LLM access control in one place.

# config.yaml
routes:
  - name: completions
    route_type: llm/v1/completions
    model:
      provider: openai
      name: gpt-4o
      config:
        openai_api_key: $OPENAI_API_KEY
How do you set tags on an MLflow run and what are they used for?

Tags are free-form key-value string metadata attached to a run. Set them with mlflow.set_tag(key, value) for individual tags or mlflow.set_tags(dict) for batch setting. Unlike parameters, tags can be updated after the run finishes using MlflowClient().set_tag(run_id, key, value). MLflow uses reserved tag prefixes: mlflow.source.name (script path), mlflow.user (OS user), mlflow.source.git.commit (current Git SHA). Common uses include marking run type (tuning vs. final), CI/CD pipeline ID, dataset version, or infrastructure tags. Tags are searchable via filter_string in search_runs().

mlflow.set_tags({
    "team": "risk",
    "dataset_version": "v3.1",
    "mlflow.source.git.commit": git_sha
})
What is model lineage in MLflow Model Registry?

Model lineage in MLflow Model Registry is the traceable link between a registered model version and the run that produced it. When a model is registered from a run, the run_id is stored with the model version. From any version, you can navigate back to the originating run to inspect its parameters, metrics, dataset artifacts, and code version. This lineage is preserved even after the run is deleted (though artifact access would be lost). Lineage supports auditability for regulatory requirements, reproducibility for debugging production issues, and root-cause analysis when a model version underperforms.

client = mlflow.tracking.MlflowClient()
version = client.get_model_version("FraudDetector", "3")
run = client.get_run(version.run_id)
print(run.data.params)
What artifact stores does MLflow support for remote storage?

MLflow's artifact store supports multiple remote backends beyond the local filesystem. Amazon S3 and S3-compatible stores (MinIO, Ceph) use the s3:// URI scheme. Azure Blob Storage uses wasbs:// and requires the azure-storage-blob package. Google Cloud Storage uses gs:// and requires google-cloud-storage. SFTP servers use sftp://. HDFS uses hdfs://. FTP uses ftp://. NFS-mounted paths are supported via the file:// scheme. The artifact store URI is set when creating an experiment or configured server-side. Clients must have proper credentials configured (AWS IAM, GCP service account, Azure SAS token) to read and write artifacts directly.

What are input examples in MLflow model logging and why include them?

Input examples are sample data records stored alongside a logged model as an artifact, representing valid model inputs. They serve three purposes: auto-inferring a model signature when one is not provided explicitly, powering the inference UI in the MLflow UI for live testing, and documenting the expected input format for model consumers. Log them via the input_example parameter in log_model: mlflow.sklearn.log_model(model, 'model', input_example=X_train[:5]). Input examples can be Pandas DataFrames, NumPy arrays, Python dicts, or lists. In MLflow 2.x, autologging captures input examples by default to streamline signature inference.

mlflow.sklearn.log_model(
    model, "model",
    input_example=X_train[:5]
)
How do model aliases work in MLflow 2.x and how do they improve on stages?

Model aliases are named, mutable pointers to specific model versions in the MLflow Model Registry. Unlike the four fixed stages (None, Staging, Production, Archived), aliases are fully user-defined strings (e.g., champion, challenger, shadow, canary). A single version can have multiple aliases; an alias always points to exactly one version. Set aliases with MlflowClient().set_registered_model_alias(name, alias, version) and load them with mlflow.pyfunc.load_model('models:/ModelName@champion'). Aliases decouple deployment semantics from rigid stage names, enabling richer deployment patterns such as progressive rollouts and shadow mode without workarounds.

client.set_registered_model_alias("FraudDetector", "champion", 5)
model = mlflow.pyfunc.load_model("models:/FraudDetector@champion")
What are MLflow Projects entry points and how are they invoked?

Entry points are named commands defined in an MLproject file that expose the project's runnable scripts. Each entry point specifies the command template (e.g., python train.py) and parameters with types and defaults. Invoke them with mlflow run <project_uri> -e <entry_point> -P param=value. The default entry point is named main. Multiple entry points allow a project to expose distinct workflows: train, evaluate, preprocess. The --no-conda flag skips environment creation. Entry points run inside the project's declared environment (conda, virtualenv, or docker) ensuring reproducibility across machines and time.

mlflow run . -e train -P learning_rate=0.001 -P n_estimators=200
How do you delete MLflow runs and what happens to the data?

Runs are soft-deleted by default. Calling MlflowClient().delete_run(run_id) sets the run's lifecycle_stage to deleted without immediately removing data. Soft-deleted runs are hidden in the UI but retrievable programmatically via search_runs(experiment_ids=...) with the run stage filter. Permanent deletion requires calling mlflow gc (garbage collection) CLI command, which removes all metadata and artifacts for deleted runs permanently. Note: artifact deletion depends on artifact store permissions — MLflow deletes metadata but may not remove files from S3/GCS if lifecycle policies are configured separately. Experiments can similarly be soft-deleted with client.delete_experiment().

from mlflow.tracking import MlflowClient
client = MlflowClient()
client.delete_run(run_id)  # soft delete
# Permanent cleanup:
# mlflow gc --backend-store-uri postgresql://...
How does MLflow search_runs support filtering and sorting?

search_runs() accepts a filter_string using a SQL-like DSL. Filter on metrics with metrics.<name> (operators: =, !=, <, <=, >, >=), parameters with params.<name> (string comparisons), tags with tags.<key>, and run attributes (run_name, status, user_id, start_time). Combine conditions with AND (OR is not supported). Sort via order_by=['metrics.accuracy DESC', 'start_time ASC']. MlflowClient().search_runs() additionally supports max_results and page_token for cursor-based pagination through large result sets. The API returns RunInfo and RunData together, giving access to all run properties without additional round-trips.

runs = mlflow.search_runs(
    experiment_ids=["42"],
    filter_string="metrics.f1 > 0.85 AND params.model = 'xgb'",
    order_by=["metrics.f1 DESC"],
    max_results=10
)
How do you add custom evaluation metrics to mlflow.evaluate()?

Define custom metrics using mlflow.metrics.make_metric(eval_fn, greater_is_better, name). The eval_fn receives EvaluationResults objects with predictions and targets and must return a MetricValue. Pass a list of custom metric objects to mlflow.evaluate() via the extra_metrics parameter. MLflow logs them alongside built-in metrics under the active run. For LLM use cases, mlflow.metrics.genai provides pre-built judge metrics like mlflow.metrics.genai.relevance() and mlflow.metrics.genai.toxicity() that use an LLM to score outputs. Custom aggregation functions are supported via per_row_scores=True for row-level granularity.

from mlflow.metrics import make_metric, MetricValue
def my_metric(eval_df, _):
    scores = (eval_df['prediction'] == eval_df['target']).astype(float)
    return MetricValue(scores.mean())
custom = make_metric(my_metric, greater_is_better=True, name="exact_match")
mlflow.evaluate(..., extra_metrics=[custom])
What is the pyfunc flavor and when should you use a custom PythonModel?

The pyfunc (Python function) flavor is MLflow's universal model interface. Any model implementing predict(context, model_input) via mlflow.pyfunc.PythonModel can be logged and loaded without framework-specific code. Use custom PythonModel when your inference logic goes beyond a single model call: combining multiple models, pre/post-processing pipelines, rule-based overrides, or returning structured outputs beyond raw predictions. The context object provides access to logged artifacts. Load any pyfunc model generically with mlflow.pyfunc.load_model(uri), making deployment code framework-agnostic. This is the recommended pattern for complex inference graphs in production.

class MyModel(mlflow.pyfunc.PythonModel):
    def predict(self, ctx, model_input):
        return model_input * 2
with mlflow.start_run():
    mlflow.pyfunc.log_model("model", python_model=MyModel())
How do you log matplotlib figures as artifacts in MLflow?

Use mlflow.log_figure(figure, artifact_file) to log a matplotlib Figure object directly without saving it to disk first. The artifact_file parameter specifies the filename including extension (e.g., 'plots/confusion_matrix.png'). Under the hood, MLflow serializes the figure and uploads it. Alternatively, save the figure to a temp file and use mlflow.log_artifact(). For Plotly figures, the same mlflow.log_figure() works with plotly.graph_objs.Figure objects, saving them as HTML for interactive viewing in the MLflow UI. Log figures during training to capture learning curves, confusion matrices, feature distributions, and residual plots.

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(history['loss'])
mlflow.log_figure(fig, 'plots/training_loss.png')
What CI/CD best practices should you follow when using MLflow run tags?

Tag runs with pipeline metadata to enable traceability from model versions back to CI/CD events. Recommended tags include: mlflow.source.git.commit (exact commit SHA for reproducibility), ci.pipeline_id (build job identifier), ci.branch (source branch name), dataset.version (dataset hash or version string), and environment (dev, staging, prod). These tags enable filtering runs by pipeline, auditing which commit produced a given model, and correlating model performance with code or data changes. Set reserved mlflow.* tags carefully — some are auto-populated by MLflow and overwriting them may cause unexpected UI behavior.

mlflow.set_tags({
    "mlflow.source.git.commit": os.getenv("GIT_SHA"),
    "ci.pipeline_id": os.getenv("CI_JOB_ID"),
    "dataset.version": "2025-Q4-v2"
})
How does mlflow models serve handle input format and what Content-Types are supported?

mlflow models serve exposes a POST /invocations endpoint supporting multiple input serialization formats via the Content-Type header. application/json accepts three JSON orientations: split ({columns, data}), records ([{col: val}]), and values ([[v1, v2]]). The dataframe_split and dataframe_records keys explicitly indicate Pandas DataFrame input. For NumPy array inputs, use instances or inputs keys (TensorFlow Serving compatible format). text/csv accepts comma-separated tabular data. The server validates input against the model signature if present and returns predictions as JSON. Use the MLFLOW_FLASK_SERVER_SECRET_KEY environment variable to enable request signing in secured deployments.

curl -X POST http://localhost:5001/invocations \
  -H 'Content-Type: application/json' \
  -d '{"dataframe_split": {"columns": ["age", "score"], "data": [[30, 0.8]]}}'
How do you launch the MLflow tracking UI locally and what does it show?

Run mlflow ui in the directory containing your mlruns folder, or specify --backend-store-uri to point to a database or remote tracking server. By default it starts on http://localhost:5000. The UI displays all experiments and their runs in a table with sortable columns for parameters, metrics, and tags. The Runs Comparison view charts multiple runs side-by-side. Clicking a run shows full parameter/metric history, artifact browser, and metadata. The Models tab shows the Model Registry. The --port flag changes the port and --host 0.0.0.0 makes it accessible on a network. For production team access, run mlflow server instead.

mlflow ui --backend-store-uri sqlite:///mlflow.db --port 5000
What does the mlflow.set_experiment() function do if the experiment does not exist?

mlflow.set_experiment(experiment_name) sets the active experiment for subsequent runs in the current process. If an experiment with the given name does not exist, MLflow automatically creates it using default settings (local artifact store, default backend). If the experiment was previously deleted (soft delete), set_experiment() reactivates it. The function returns an Experiment object with the ID and metadata. This behavior means you can safely call set_experiment() at script startup without checking for prior existence. For controlled creation with custom artifact locations, use mlflow.create_experiment(name, artifact_location=...) explicitly before calling set_experiment().

exp = mlflow.set_experiment("churn_prediction")
print(exp.experiment_id)
How do you handle run filtering by date range in MLflow search_runs?

Filter by time using the start_time and end_time run attributes in the filter_string, expressed as millisecond Unix timestamps. MLflow's search DSL supports attribute.start_time >= <ms_timestamp> and attribute.end_time <= <ms_timestamp> comparisons. Convert Python datetimes to milliseconds with int(datetime.timestamp() * 1000). The filter can be combined with metric and parameter filters using AND. For convenience, wrap the timestamp computation in a helper. Note that end_time is null for RUNNING runs, so end_time filters will exclude active runs. Use status = 'FINISHED' to restrict to completed runs only.

from datetime import datetime
start_ms = int(datetime(2025, 1, 1).timestamp() * 1000)
runs = mlflow.search_runs(
    filter_string=f"attribute.start_time >= {start_ms} AND status = 'FINISHED'"
)
What is the purpose of the MLflow model conda environment file?

When MLflow logs a model, it also captures the Python environment needed to run it as a conda.yaml (or requirements.txt for virtualenv-based flavors). This environment snapshot includes the Python version, framework package versions (e.g., scikit-learn==1.4.2), and all transitive dependencies. When serving or loading the model later, MLflow can recreate the exact environment using this file, preventing version skew between training and inference. The conda.yaml is stored as an artifact alongside the model. For Docker-based serving, mlflow models build-docker uses this file to build a reproducible image. Inspect it with mlflow.pyfunc.get_model_dependencies(model_uri).

# Auto-generated conda.yaml example:
channels: [defaults]
dependencies:
  - python=3.11
  - pip:
    - scikit-learn==1.4.2
    - mlflow==2.12.0
How does MLflow integrate with Databricks and what does managed MLflow offer?

Databricks provides a managed MLflow service embedded in its Lakehouse Platform. Set MLFLOW_TRACKING_URI=databricks to automatically route tracking to the Databricks workspace. Authentication uses the DATABRICKS_HOST and DATABRICKS_TOKEN environment variables or Databricks CLI profiles. Databricks MLflow adds Unity Catalog integration for the Model Registry, providing governance with fine-grained ACLs, lineage across tables and models, and cross-workspace model sharing. Databricks also manages the MLflow server infrastructure, auto-scaling, and backups. Feature Serving and Model Serving on Databricks integrate directly with MLflow Registry for one-click deployment of registered model versions.

import os
os.environ['MLFLOW_TRACKING_URI'] = 'databricks'
os.environ['DATABRICKS_HOST'] = 'https://adb-xxx.azuredatabricks.net'
os.environ['DATABRICKS_TOKEN'] = 'dapi...'
What are MLflow plugins and how do you extend MLflow with custom tracking or deployment backends?

MLflow plugins are Python packages that extend MLflow's behavior by registering against defined entry_points in setup.py or pyproject.toml. The primary extension points are: mlflow.tracking_store (custom backend store implementations), mlflow.artifact_repository (custom artifact stores), mlflow.deployments (custom deployment targets), and mlflow.project_backend (custom project execution environments). A plugin registers a class that implements the corresponding abstract interface. Install the plugin package and MLflow discovers it automatically via Python entry points. Example use cases include proprietary data stores, enterprise artifact repositories, or on-premise model deployment orchestrators not natively supported by MLflow.

# setup.py entry_points
entry_points={
    'mlflow.tracking_store': [
        'custom=my_plugin.store:CustomTrackingStore'
    ]
}
How does mlflow.autolog() interact with a manually created run context?

When mlflow.autolog() is active and you manually create a run with mlflow.start_run(), autolog attaches its callbacks to the active run rather than creating a new one. This means autologged parameters and metrics are logged into your manually controlled run, giving you full control over run naming, tagging, and additional manual logging while still benefiting from autologged framework data. If you call fit() outside any run context with autolog active, MLflow creates a run automatically. To disable autolog for a specific code block, call mlflow.autolog(disable=True) as a context or use the framework-specific autolog with disable=True.

mlflow.autolog()
with mlflow.start_run(run_name="production_train"):
    mlflow.set_tag("priority", "high")
    model.fit(X_train, y_train)  # autolog fires into this run
How do you log a Python dictionary of parameters without individual log_param calls?

Use mlflow.log_params(params_dict) to log all entries in a dictionary as parameters in a single API call. The dictionary keys become parameter names and values are converted to strings. This is more efficient than calling log_param() in a loop and reduces HTTP round-trips when using a remote tracking server. Note that MLflow has a maximum of 500 parameters per run by default (configurable server-side). Values exceeding 6000 characters are truncated. For logging large configuration objects, prefer logging them as JSON artifacts with mlflow.log_dict() rather than parameters to avoid truncation and length limits.

params = {"lr": 0.001, "epochs": 50, "batch_size": 128, "optimizer": "adamw"}
mlflow.log_params(params)
# Also log as artifact for full fidelity:
mlflow.log_dict(params, "config.json")
What is the difference between mlflow.log_artifact and mlflow.log_artifacts?

mlflow.log_artifact(local_path, artifact_path=None) uploads a single file to the run's artifact store. The artifact_path parameter specifies a subdirectory within the artifact root for organizational purposes. mlflow.log_artifacts(local_dir, artifact_path=None) uploads every file in a local directory recursively, preserving subdirectory structure under the specified artifact_path. Use log_artifact for individual files (model pickles, config JSONs) and log_artifacts for directories with multiple related outputs (a model directory with weights, tokenizer, and config files). Both support the same artifact stores and both are non-destructive — uploading does not delete existing artifacts from the same run.

mlflow.log_artifact("report.html")
mlflow.log_artifacts("./model_dir/", artifact_path="model")
How do you implement a promotion workflow for MLflow Model Registry versions?

A robust promotion workflow uses MlflowClient API calls chained with evaluation gates. After training, register the model and assign a challenger alias. Run automated evaluation (mlflow.evaluate() or custom tests) against a holdout set. If metrics exceed thresholds, reassign the champion alias from the current version to the new version atomically using set_registered_model_alias(). Simultaneously, archive the old champion version. Automate this in CI/CD pipelines triggered on new model versions. For rollback, simply reassign the champion alias back to a known-good version — no redeployment needed if serving code loads by alias. Audit all transitions via Registry event logs.

client.set_registered_model_alias("FraudModel", "challenger", new_v)
if evaluate_model(new_v) > evaluate_model(current_champion):
    client.set_registered_model_alias("FraudModel", "champion", new_v)
What MLflow autolog parameters allow you to control which frameworks are enabled?

mlflow.autolog() accepts per-framework enable flags: sklearn=True/False, tensorflow=True/False, keras=True/False, pytorch=True/False, xgboost=True/False, lightgbm=True/False, statsmodels=True/False, gluon=True/False, spark=True/False, fastai=True/False. Disable a specific framework while keeping others active to avoid conflicts (e.g., disable keras if using tensorflow directly). The disable=True argument turns off all autologging. silent=True suppresses warnings. log_models=False skips model artifact logging globally. exclusive=True prevents autolog from running if a run is already active — useful when you want autolog only for runs it creates, not for manually managed runs.

mlflow.autolog(
    sklearn=True,
    xgboost=True,
    keras=False,
    log_models=False,
    silent=True
)
How does MLflow handle model versioning when the same model name is registered multiple times?

Each call to mlflow.register_model() or log_model with registered_model_name creates a new model version under the same registered model name. Version numbers increment sequentially starting from 1. All versions share the same registered model entry but have independent run_id links, source URIs, creation timestamps, and stage or alias assignments. Versions are never overwritten — registration is always additive. Delete a specific version with MlflowClient().delete_model_version(name, version), which is a hard delete removing metadata but not necessarily artifacts. The registered model itself persists until explicitly deleted with delete_registered_model().

# Each call creates a new incremented version
for run_id in top_run_ids:
    mlflow.register_model(f"runs:/{run_id}/model", "MyModel")

Put it into practice with AI Learning

This topic — and hundreds more — comes from our free, offline AI Learning app. Practice Q&A, quizzes and cheat sheets anywhere, no account needed.

  • Free
  • No account
  • Works offline
Coming soon toGoogle Play