| name | mlflow |
| description | ML lifecycle management with MLflow. Track experiments, package models, manage registries, and deploy models. Use for ML operations, experiment tracking, and model deployment. |
MLflow Skill
Complete guide for MLflow - ML lifecycle platform.
Quick Reference
Components
| Component | Description |
|---|
| Tracking | Log experiments |
| Projects | Package ML code |
| Models | Model packaging |
| Registry | Model versioning |
| Serving | Model deployment |
CLI Commands
mlflow run .
mlflow ui
mlflow models serve -m model
mlflow server
1. Installation
pip install mlflow
pip install mlflow[extras]
pip install mlflow[gateway]
pip install mlflow[genai]
2. Experiment Tracking
Basic Logging
import mlflow
mlflow.set_experiment("my-experiment")
with mlflow.start_run():
mlflow.log_param("learning_rate", 0.01)
mlflow.log_param("epochs", 100)
mlflow.log_metric("accuracy", 0.95)
mlflow.log_metric("loss", 0.05)
for epoch in range(10):
mlflow.log_metric("train_loss", 0.1 - epoch * 0.01, step=epoch)
mlflow.log_artifact("model.pkl")
mlflow.log_artifacts("./outputs")
mlflow.set_tag("model_type", "neural_network")
Auto-Logging
import mlflow
mlflow.sklearn.autolog()
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(X_train, y_train)
mlflow.pytorch.autolog()
mlflow.tensorflow.autolog()
mlflow.xgboost.autolog()
mlflow.lightgbm.autolog()
Manual Run Management
run = mlflow.start_run(run_name="my-run")
try:
mlflow.log_param("param1", "value1")
mlflow.log_metric("metric1", 0.9)
finally:
mlflow.end_run()
run_id = run.info.run_id
print(f"Run ID: {run_id}")
with mlflow.start_run(run_id=run_id):
mlflow.log_metric("additional_metric", 0.95)
Nested Runs
with mlflow.start_run(run_name="parent"):
mlflow.log_param("parent_param", "value")
for i in range(3):
with mlflow.start_run(run_name=f"child_{i}", nested=True):
mlflow.log_param("child_param", i)
mlflow.log_metric("child_metric", i * 0.1)
3. Tracking Server
Start Server
mlflow server --host 0.0.0.0 --port 5000
mlflow server \
--backend-store-uri postgresql://user:pass@localhost/mlflow \
--default-artifact-root s3://mlflow-artifacts/ \
--host 0.0.0.0 \
--port 5000
mlflow server \
--backend-store-uri sqlite:///mlflow.db \
--default-artifact-root ./mlruns \
--host 0.0.0.0
Connect to Server
import mlflow
mlflow.set_tracking_uri("http://localhost:5000")
Docker Compose
services:
mlflow:
image: ghcr.io/mlflow/mlflow:latest
ports:
- "5000:5000"
environment:
- MLFLOW_BACKEND_STORE_URI=postgresql://mlflow:mlflow@postgres/mlflow
- MLFLOW_DEFAULT_ARTIFACT_ROOT=s3://mlflow-artifacts/
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
command: >
mlflow server
--host 0.0.0.0
--port 5000
depends_on:
- postgres
postgres:
image: postgres:15
environment:
- POSTGRES_USER=mlflow
- POSTGRES_PASSWORD=mlflow
- POSTGRES_DB=mlflow
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
4. Model Logging
Log Scikit-learn Model
from sklearn.ensemble import RandomForestClassifier
import mlflow.sklearn
model = RandomForestClassifier()
model.fit(X_train, y_train)
with mlflow.start_run():
mlflow.sklearn.log_model(
model,
artifact_path="model",
registered_model_name="my-rf-model"
)
from mlflow.models import infer_signature
signature = infer_signature(X_train, model.predict(X_train))
mlflow.sklearn.log_model(model, "model", signature=signature)
Log PyTorch Model
import mlflow.pytorch
with mlflow.start_run():
mlflow.pytorch.log_model(
pytorch_model=model,
artifact_path="model",
conda_env="conda.yaml",
code_paths=["./src"]
)
Log Custom Model (PyFunc)
import mlflow.pyfunc
class MyModel(mlflow.pyfunc.PythonModel):
def load_context(self, context):
import pickle
with open(context.artifacts["model_path"], "rb") as f:
self.model = pickle.load(f)
def predict(self, context, model_input):
return self.model.predict(model_input)
with mlflow.start_run():
mlflow.pyfunc.log_model(
artifact_path="model",
python_model=MyModel(),
artifacts={"model_path": "model.pkl"},
conda_env={
"dependencies": ["scikit-learn==1.0.0", "pandas"]
}
)
Load Model
model = mlflow.sklearn.load_model(f"runs:/{run_id}/model")
model = mlflow.sklearn.load_model("models:/my-model/1")
model = mlflow.sklearn.load_model("models:/my-model/Production")
model = mlflow.pyfunc.load_model(f"runs:/{run_id}/model")
predictions = model.predict(X_test)
5. Model Registry
Register Model
mlflow.sklearn.log_model(
model,
"model",
registered_model_name="my-model"
)
result = mlflow.register_model(
model_uri=f"runs:/{run_id}/model",
name="my-model"
)
Manage Versions
from mlflow import MlflowClient
client = MlflowClient()
versions = client.search_model_versions("name='my-model'")
client.transition_model_version_stage(
name="my-model",
version=1,
stage="Production"
)
client.update_model_version(
name="my-model",
version=1,
description="Production model v1"
)
client.set_model_version_tag(
name="my-model",
version=1,
key="validation_status",
value="approved"
)
Model Aliases
client.set_registered_model_alias(
name="my-model",
alias="champion",
version=1
)
model = mlflow.pyfunc.load_model("models:/my-model@champion")
client.delete_registered_model_alias(
name="my-model",
alias="champion"
)
6. Model Serving
Local Serving
mlflow models serve -m runs:/<run_id>/model -p 5001
mlflow models serve -m models:/my-model/Production -p 5001
mlflow models serve -m models:/my-model/1 -p 5001 --env-manager=conda
Make Predictions
curl -X POST http://localhost:5001/invocations \
-H "Content-Type: application/json" \
-d '{"dataframe_split": {"columns": ["a", "b"], "data": [[1, 2]]}}'
Docker Deployment
mlflow models build-docker -m models:/my-model/1 -n my-model-image
docker run -p 5001:8080 my-model-image
Kubernetes Deployment
apikind: Deployment
metadata:
name: mlflow-model
spec:
replicas: 2
selector:
matchLabels:
app: mlflow-model
template:
metadata:
labels:
app: mlflow-model
spec:
containers:
- name: model
image: my-model-image:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi"
cpu: "500m"
---
apikind: Service
metadata:
name: mlflow-model-service
spec:
selector:
app: mlflow-model
ports:
- port: 80
targetPort: 8080
7. MLflow Projects
MLproject File
name: my-project
conda_env: conda.yaml
entry_points:
main:
parameters:
learning_rate: {type: float, default: 0.01}
epochs: {type: int, default: 100}
command: "python train.py --lr {learning_rate} --epochs {epochs}"
validate:
parameters:
model_path: {type: string}
command: "python validate.py --model {model_path}"
conda.yaml
name: my-project-env
channels:
- conda-forge
dependencies:
- python=3.10
- pip
- pip:
- mlflow
- scikit-learn
- pandas
Run Project
mlflow run . -P learning_rate=0.001 -P epochs=50
mlflow run https://github.com/user/repo -P param=value
mlflow run . -e validate -P model_path=./model
mlflow run . --env-manager=conda
8. GenAI Tracking
Track LLM Calls
import mlflow
mlflow.set_experiment("llm-experiment")
with mlflow.start_run():
mlflow.log_params({
"model": "gpt-4",
"temperature": 0.7,
"max_tokens": 1000
})
response = openai_client.chat.completions.create(...)
mlflow.log_text(prompt, "input.txt")
mlflow.log_text(response.choices[0].message.content, "output.txt")
mlflow.log_metrics({
"prompt_tokens": response.usage.prompt_tokens,
"completion_tokens": response.usage.completion_tokens
})
Auto-log LangChain
import mlflow
mlflow.langchain.autolog()
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
llm = ChatOpenAI(model="gpt-4o")
prompt = ChatPromptTemplate.from_template("Tell me about {topic}")
chain = prompt | llm
result = chain.invoke({"topic": "MLflow"})
Evaluate LLM
import mlflow
eval_data = pd.DataFrame({
"inputs": ["Question 1", "Question 2"],
"ground_truth": ["Answer 1", "Answer 2"]
})
with mlflow.start_run():
results = mlflow.evaluate(
model="runs:/{run_id}/model",
data=eval_data,
targets="ground_truth",
model_type="question-answering",
evaluators="default"
)
print(results.metrics)
9. Querying Runs
Search Runs
from mlflow import MlflowClient
client = MlflowClient()
runs = client.search_runs(
experiment_ids=["1"],
filter_string="metrics.accuracy > 0.9 AND params.model_type = 'rf'",
order_by=["metrics.accuracy DESC"],
max_results=10
)
for run in runs:
print(f"Run: {run.info.run_id}")
print(f" Accuracy: {run.data.metrics.get('accuracy')}")
print(f" Params: {run.data.params}")
best_run = runs[0]
Compare Runs
import mlflow
runs = mlflow.search_runs(
experiment_names=["my-experiment"],
filter_string="status = 'FINISHED'"
)
print(runs[["run_id", "params.learning_rate", "metrics.accuracy"]])
client = MlflowClient()
artifacts = client.list_artifacts(run_id)
10. Best Practices
Project Structure
ml-project/
├── MLproject
├── conda.yaml
├── src/
│ ├── train.py
│ ├── evaluate.py
│ └── utils.py
├── data/
├── notebooks/
└── tests/
Training Script
import argparse
import mlflow
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--lr", type=float, default=0.01)
parser.add_argument("--epochs", type=int, default=100)
args = parser.parse_args()
mlflow.set_experiment("my-experiment")
with mlflow.start_run():
mlflow.log_params(vars(args))
model = train(args.lr, args.epochs)
metrics = evaluate(model)
mlflow.log_metrics(metrics)
mlflow.sklearn.log_model(
model,
"model",
signature=infer_signature(X, y),
registered_model_name="my-model"
)
if __name__ == "__main__":
main()
Best Practices
- Always set experiment - Organize runs
- Log signatures - Model input/output schemas
- Use auto-logging - Reduce boilerplate
- Version models - Track production models
- Use artifacts - Store plots, configs
- Tag runs - Searchable metadata
- Nested runs - Hyperparameter tuning
- Remote tracking - Collaborate with team
- CI/CD integration - Automated training
- Monitor serving - Track predictions