Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Lumlflow

Local ML experiment tracking and model management.

Lumlflow gives you a lightweight, self-hosted dashboard to track machine learning experiments, organize them into groups, and manage associated models — all running locally with zero cloud dependencies.

Quickstart

Python 3.12 or later and uv are required. Install lumlflow as an isolated tool, then create a project environment for flow cells before opening the UI:

uv tool install lumlflow
# or: pipx install lumlflow

mkdir churn
cd churn
uv init
uv add pandas pyarrow
lumlflow ui

This starts the web UI at http://127.0.0.1:5000 and opens it with an authenticated URL. The project environment supplies pandas and pyarrow to cells. Add luml-sdk to the project too when a cell declares or consumes an experiment output.

The API is guarded by an access token. The CLI opens a URL containing the token in its fragment; the UI removes it from the address bar and keeps it in the browser for that address. With --no-browser, open the complete URL printed by the CLI. The token is stored in .lumlflow-session-token next to the experiment store, so it survives restarts; lumlflow ui --rotate-token issues a new one and the old links stop working. When the UI has no valid token, it asks for the launch URL. A launcher that must know the token in advance, such as luml.flow.RelayedFlow, sets it through the LUMLFLOW_SESSION_TOKEN environment variable. Only /api/auth/status, which tells whether a platform API key is configured, answers without the token.

Usage

Lumlflow bundles the LUML SDK (luml), so you can start tracking experiments right away.

Classical ML example

The example below trains a gradient-boosted classifier on the Iris dataset (install scikit-learn to run it):

from sklearn.datasets import load_iris
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import accuracy_score, log_loss
from sklearn.model_selection import train_test_split

from luml.experiments.tracker import ExperimentTracker

X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

tracker = ExperimentTracker()

# Start an experiment
tracker.start_experiment(
    name="gbm_baseline",
    group="iris_classification",
    tags=["baseline", "gbm"],
)

# Log hyperparameters
tracker.log_static("n_estimators", 100)
tracker.log_static("learning_rate", 0.1)
tracker.log_static("max_depth", 3)

# Train the model
model = GradientBoostingClassifier(n_estimators=100, learning_rate=0.1, max_depth=3)
model.fit(X_train, y_train)

# Log metrics over training steps
for step, probs in enumerate(model.staged_predict_proba(X_test)):
    loss = log_loss(y_test, probs, labels=[0, 1, 2])
    acc = accuracy_score(y_test, probs.argmax(axis=1))
    tracker.log_dynamic("loss", loss, step=step)
    tracker.log_dynamic("accuracy", acc, step=step)

# Log the trained model
tracker.log_model(model, name="gbm_final", inputs=X_train)

# End the experiment
tracker.end_experiment()

LLM example

The example below evaluates an OpenAI model on a small Q&A dataset. Every LLM call is automatically captured as a trace, and each question is logged as an eval sample with a score (install luml-sdk[tracing], opentelemetry-instrumentation-openai, and openai, then set OPENAI_API_KEY to run it):

from dotenv import load_dotenv
from openai import OpenAI

from luml.experiments.tracker import ExperimentTracker
from luml.experiments.tracing import instrument_openai
from luml.experiments.evaluation.evaluate import evaluate
from luml.experiments.evaluation.scorers.base import (
    supervised_scorer,
    unsupervised_scorer,
)
from luml.experiments.evaluation.types import EvalItem

load_dotenv()

client = OpenAI()

tracker = ExperimentTracker("sqlite://./brandnew_experiments")
tracker.enable_tracing()
instrument_openai()

eval_dataset = [
    EvalItem(
        id="q0",
        inputs={"question": "What is 2 + 2?"},
        expected_output="4",
        metadata={"category": "math"},
    ),
    EvalItem(
        id="q1",
        inputs={"question": "What is the capital of France?"},
        expected_output="Paris",
        metadata={"category": "geography"},
    ),
]


def run_inference(inputs: dict) -> str:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        temperature=0.0,
        messages=[{"role": "user", "content": inputs["question"]}],
    )
    return response.choices[0].message.content.strip()


@supervised_scorer
def exact_match(inputs, expected, output):
    return expected.lower().strip() in output.lower()


@unsupervised_scorer
def answer_length(inputs, output):
    length = len(output.split())
    if length < 1:
        return 0.0
    if length > 50:
        return 0.5
    return 1.0


tracker.start_experiment(
    name="qa_gpt4_baseline",
    group="qa_evaluation",
    tags=["baseline", "gpt-4o-mini"],
)

tracker.log_static("model", "gpt-4o-mini")
tracker.log_static("temperature", 0.0)

eval_results = evaluate(
    eval_dataset=eval_dataset,
    inference_fn=run_inference,
    scorers=[exact_match, answer_length],
    dataset_id="qa_v1",
    experiment_tracker=tracker,
)

for key, value in eval_results.aggregated_scores.items():
    tracker.log_static(f"eval_{key}", value)

tracker.end_experiment()

All logged data is stored locally and visible in the web UI launched by lumlflow ui.

Overview

Lumlflow consists of two parts:

  • CLI — a command-line interface to launch and configure the server
  • Web UI — a browser-based dashboard for viewing and managing experiments

The server exposes a REST API that the UI consumes, so you can also integrate programmatically.

Workspace / flows

The Workspace tab lists the .flow directories beneath the directory passed to lumlflow ui, or beneath the current directory by default. One daemon per user serves every flow opened by path. Each flow runs from the directory that contains it and resolves its interpreter from the nearest .venv or pyproject.toml above that directory.

The flow user guide covers cells, lanes, reactivity, tracker outputs, agent setup, and the files to commit.

CLI Reference

lumlflow ui                          # Start UI at localhost:5000
lumlflow ui --port 8080              # Custom port
lumlflow ui --host 0.0.0.0           # Bind to all interfaces
lumlflow ui --no-browser             # Don't open browser automatically
lumlflow version                     # Show installed version

The tracker API on this port is unauthenticated on a non-loopback bind. Use --host 0.0.0.0 only on a network where that exposure is acceptable.

Features

Experiment Tracking

Run your ML experiments locally while seamlessly tracking their progress in a clear, real-time UI.

The platform gives you full visibility into every experiment as it executes. As your code runs, all experiment data is automatically captured and stored, allowing you to monitor progress, inspect intermediate results, and analyze outcomes in a structured way.

Each experiment can be easily identified by its name and tags, allowing you to quickly find relevant runs, filter them, and organize your workflow.

Each experiment serves as a complete record of a run and can include:

  • Metrics — track performance over time (accuracy, loss, F1, etc.)
  • Parameters — log hyperparameters and configuration settings
  • Models — store produced models and link them to specific runs

Experiment tracking overview

Experiment metrics view

  • Evaluations (Evals) — record evaluation results and comparisons
  • Traces — capture step-by-step execution details for deeper analysis

Evaluations view

  • Attachments — save artifacts like datasets, plots, or logs

Attachments view

All of this is accessible through an interactive web UI where you can explore experiments, analyze metrics, inspect traces, and compare results.

Annotations

Add annotations to evaluation samples and trace spans to capture feedback, expectations, or manual scores.

Use annotations to review experiment quality, document insights, or collaborate with teammates by leaving structured notes with optional rationale.

Annotations in trace span:

Annotations in trace span

Annotations in eval sample:

Annotations in eval sample

Experiment Groups

Organize related experiments into groups for easier navigation and comparison.

Experiment groups list

Experiment groups detail

Uploading to LUML

Use your API key to upload experiments and models from your local environment to the LUML platform.

This allows you to move from local experimentation to shared cloud storage, making it easier to collaborate, persist results, and manage models centrally.

A model a flow cell produced goes the same way: expand the cell, and upload to LUML stands beside download on any output declared model. The kernel packages the stored value with luml (the flavor is detected from the model, as log_model does, and the frame the cell consumed supplies the input schema), so the flow's environment needs luml and the model's own library.

Requirements

  • Python 3.12+
  • uv

Metadata

Release files for lumlflow 0.3.0rc1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for lumlflow 0.3.0rc1
File Interpreter ABI Platform Actions
lumlflow-0.3.0rc1-py3-none-any.whl Python 3 none any Details for lumlflow-0.3.0rc1-py3-none-any.whl

Release files / lumlflow-0.3.0rc1-py3-none-any.whl

Download URL lumlflow-0.3.0rc1-py3-none-any.whl
Size 2.7 MB
Tags Python 3
SHA-256 checksum
How to use checksums
ad976b34dab1c2efa571e0fd81e452405eade9c02cdde9161f468b39bab99a4b
BLAKE2b-256 checksum
How to use checksums
c8ef99669b4bc01d8b684646cc3d53d6c3c83f0a80a8f800f15eaa9e9022ef54
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for lumlflow 0.3.0rc1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page