Skip to main content

TrainLens

TrainLens turns AI training runs into research-grade notebook reports, directly inside Jupyter.

TrainLens is a lightweight library for understanding, documenting, and comparing model-training experiments. It reads the state already present in a notebook, normalizes common metrics, detects useful evidence, redacts likely secrets, and can use an OpenAI-compatible LLM to draft a scientific report or improvement plan.

It is meant for research workflows where experiments move quickly and the important context lives in Python variables, not in a separate dashboard.

CI PyPI version Python License: Apache-2.0

What It Does

Feature Purpose
Notebook reports Explain training metrics, signals, limitations, and next steps.
Framework adapters Read Keras, Hugging Face, and Lightning training objects without hard dependencies.
Run comparison Compare baseline and experiment metrics with improvement/regression labels.
Export Write Markdown, HTML, JSON, and optional PDF artifacts.
Privacy guardrails Redact likely secrets before LLM prompts are created.
Built-in prompts Select and customize explanations for different training objectives.
Real-time monitoring Stream metrics and detect training anomalies while a run is active.
Next-experiment planning Turn run evidence into a controlled, measurable follow-up.

TrainLens has two layers:

  1. A local deterministic layer for metric extraction, framework detection, heuristics, comparison, and export.
  2. An optional LLM layer for paper-style reports and experiment suggestions.

Install

pip install trainlens

Optional PDF support:

pip install "trainlens[pdf]"

Quickstart

history = {
    "train_loss": [0.61, 0.50, 0.25],
    "eval_loss": [0.62, 0.52, 0.28],
    "accuracy": [0.89, 0.91, 0.92],
    "val_accuracy": [0.82, 0.83, 0.92],
}
%load_ext trainlens.magic.extension
%explain_training
%suggest_improvements
%compare_runs

%explain_training captures a run. After two captured runs, %compare_runs compares the latest run with the previous one.

To enable LLM reports, configure any OpenAI-compatible endpoint:

import os

os.environ["TRAINLENS_LLM_BASE_URL"] = "https://api.openai.com/v1"
os.environ["TRAINLENS_LLM_API_KEY"] = "your-api-key"
os.environ["TRAINLENS_LLM_MODEL"] = "your-model"

Local endpoints such as Ollama, LM Studio, vLLM, and llama.cpp server work with the same environment variables.

Framework Adapters

TrainLens can inspect common training objects already present in a notebook:

# Keras / TensorFlow
history = model.fit(x_train, y_train, validation_data=(x_val, y_val))

# Hugging Face
trainer.train()  # reads trainer.state.log_history

# PyTorch Lightning
trainer.fit(module, datamodule=datamodule)  # reads callback/logged metrics

# Plain PyTorch
# Keep model, optimizer, scheduler, and train_loader in the notebook namespace.
# TrainLens reads parameter counts, optimizer groups, current learning rates,
# scheduler epoch, batching settings, and dataset size without importing PyTorch.

%explain_training

Adapters use duck typing and module names. TrainLens does not require TensorFlow, PyTorch, Transformers, or Lightning as package dependencies.

Python API

Build and export notebook reports:

from trainlens import build_paper_report, write_report

paper = build_paper_report(max_metric_points=12)
write_report(paper, "trainlens-report.html")
write_report(paper, "trainlens-report.json")

Long metric histories are summarized with their endpoints, extrema, observation count, and an ordered sample. Adjust max_metric_points to trade prompt size for curve detail; values below 2 are rejected so training endpoints are always kept.

Compare runs:

from trainlens import compare_runs, render_run_comparison

comparison = compare_runs(
    {"validation_loss": 0.52, "validation_accuracy": 0.84},
    {"validation_loss": 0.47, "validation_accuracy": 0.87},
    baseline_name="baseline",
    experiment_name="lower learning rate",
)

print(render_run_comparison(comparison))

Export comparisons through the same report API:

from trainlens import write_report

write_report(comparison, "comparison.html")
write_report(comparison, "comparison.json")

Metric direction is inferred from common names: loss-like metrics are better when they decrease; accuracy, F1, recall, precision, AUC, and score-like metrics are better when they increase. Unknown metrics are shown with deltas but without an improvement/regression claim.

Built-in prompts

TrainLens includes prompts for scientific reporting, improvement planning, training diagnosis, and controlled experiment design. Discover the available prompts and their intended use:

from trainlens import show_trainlens_prompts

for prompt in show_trainlens_prompts():
    print(f"{prompt.name}: {prompt.description}")

Choose a built-in prompt and parameterize it for the goal of the analysis:

from trainlens import PromptOptions, build_paper_report

options = PromptOptions(
    prompt_name="training_diagnosis",
    objective="Explain why validation loss rose after epoch 8.",
    model_family="vision transformer fine-tune",
    audience="computer-vision researchers",
    tone="concise, technical, and cautious",
    focus_areas=("overfitting", "learning-rate schedule", "augmentation"),
    rules=(
        "Use only evidence contained in the notebook context.",
        "Rank each hypothesis by confidence.",
    ),
    return_instructions=(
        "Return observations, ranked hypotheses, verification checks, and next actions.",
    ),
)

report = build_paper_report(globals(), prompt_options=options)
print(report.markdown)

The configurable fields are prompt_name, objective, heading, model_family, audience, tone, rules, focus_areas, and return_instructions. Use get_trainlens_prompt(name) to inspect one built-in definition. Prompt construction still applies TrainLens secret redaction before notebook context is sent to an LLM provider.

Real-time monitoring

TrainLensMonitor processes metrics incrementally instead of waiting for a run to finish. It currently detects non-finite values, stagnant losses, and possible overfitting when training loss falls while validation loss rises. Every alert contains a stable code, severity, step, message, and the evidence that triggered it.

from trainlens import MonitorConfig, TrainLensMonitor

monitor = TrainLensMonitor(MonitorConfig(patience=3, min_delta=0.01))

for epoch, metrics in enumerate(training_loop()):
    alerts = monitor.observe(epoch, metrics)
    for alert in alerts:
        print(alert.severity, alert.message, alert.evidence)

TrainLensCallback provides dependency-free hooks shaped for Keras, Hugging Face Transformers, and PyTorch Lightning. It can collect alerts, request a stop after a critical anomaly, and invoke an application-defined handler periodically through explain_every.

from trainlens import TrainLensCallback

def explain_snapshot(observation):
    print(f"Explain step {observation.step}: {dict(observation.metrics)}")

callback = TrainLensCallback(
    alerts=True,
    explain_every=5,
    on_explain=explain_snapshot,
    stop_on_anomaly=False,
)

# Keras-style hook
callback.on_epoch_end(epoch, logs)

# Transformers-style hook
callback.on_log(state=trainer_state, control=trainer_control, logs=logs)

# Lightning-style hook
callback.on_train_epoch_end(trainer)

Automatic stopping is opt-in and currently applies only to critical alerts, such as a NaN or infinite metric. The monitoring engine is local and deterministic; explain_every calls the supplied handler but does not contact an LLM unless that handler explicitly does so.

Next-experiment recommendations

TrainLens can turn completed runs into a structured proposal for the next controlled experiment. Recommendations contain a hypothesis, one parameter change, parameters to keep constant, measurable success criteria, estimated cost, confidence, and the evidence used to make the proposal.

from trainlens import (
    ExperimentRun,
    experiment_config,
    render_next_experiment,
    suggest_next_experiment,
)

runs = [
    ExperimentRun(
        name="baseline",
        metrics={"train_loss": 0.20, "validation_loss": 0.50},
        parameters={"learning_rate": 1e-3, "dropout": 0.10, "batch_size": 32},
        estimated_cost="medium",
    ),
]

recommendation = suggest_next_experiment(
    runs,
    objective_metric="validation_loss",
    minimum_improvement=0.01,
)

print(render_next_experiment(recommendation))

next_config = experiment_config(
    recommendation,
    base_parameters=runs[0].parameters,
)

The initial implementation is local and deterministic. It selects the strongest source run for the objective, detects evidence such as a generalization gap, and changes only one variable so that the result is easier to interpret. It does not claim that a recommendation is guaranteed to improve the model; its confidence and evidence fields are intended to make that uncertainty explicit.

What TrainLens Inspects

TrainLens looks for lightweight evidence:

  • metric histories in dictionaries, lists, logs, and trace-like events
  • model-like objects with fit, predict, score, state_dict, or transformer config
  • labels such as y_train, labels, or target
  • metadata such as model names, dataset notes, and training parameters

Common aliases such as eval_loss, val_loss, validation_loss, train/accuracy, and eval-accuracy are normalized automatically.

Privacy

Local extraction, framework adapters, run comparison, and export do not contact an external service. LLM calls happen only when you use an LLM report helper or magic with a configured provider.

TrainLens redacts likely secrets and truncates large literals before prompt construction. Do not store real API keys in notebooks or committed files.

Development

pip install -e ".[dev]"
python -m pytest
python -m ruff check .
mypy src/trainlens
rm -rf dist
python -m build --no-isolation
python -m twine check dist/*

New framework support should stay optional and be tested with fake objects or duck typing fixtures instead of adding heavy ML frameworks as required dependencies.

License

Apache License 2.0. See LICENSE.

Release files for trainlens 0.8.0

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

Source distribution (sdist)

Source distribution for trainlens 0.8.0
File Size Uploaded
trainlens-0.8.0.tar.gz 62.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for trainlens 0.8.0
File Interpreter ABI Platform
trainlens-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 123.6 kB

Release files / trainlens-0.8.0.tar.gz

Download URL trainlens-0.8.0.tar.gz
Size 62.2 kB
Tags Source
SHA-256 checksum
How to use checksums
e14e3167db427aa788b3ee423b7e10a69c15efdd7f8a396a4082b8c4c51a36c1
BLAKE2b-256 checksum
How to use checksums
09c123656cb911676a92d73cfd5916b315de5af47791f018db81dde4fdb35261
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 17, 2026.

Transparency log

Release files / trainlens-0.8.0-py3-none-any.whl

Download URL trainlens-0.8.0-py3-none-any.whl
Size 61.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1f973b0d7be65ca47751388c3ceb651cb8622231c4f71d53144e7e40f2391a62
BLAKE2b-256 checksum
How to use checksums
4a471ca22424aa8f11890a14ba2d431ad4cf89d95b4bb55e4684adf69a24cdaa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 17, 2026.

Transparency log

Release history Release notifications | RSS feed

0.9.0

2 release files

0.8.4

2 release files

0.8.3

2 release files

0.8.2

2 release files

0.8.1

2 release files

This release

0.8.0 This release

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

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