Skip to main content

An observability-first reinforcement-learning training & benchmarking library.

Project description

rlens

PyPI CI Python 3.11+ License: MIT

An observability-first reinforcement-learning library — see what your policy is doing, not just its loss curve.

rlens is a local, zero-setup workbench for understanding, debugging, and comparing RL runs on a single machine. It trains PPO, DQN and SAC on one shared trainer and streams everything to a built-in web dashboard — reward curves, per-layer gradient norms, action distributions, and rollout video, live and overlaid across runs. Built on PyTorch and Gymnasium; runs on a laptop (Apple Silicon / CPU, no CUDA required).

The rlens dashboard: PPO and DQN runs overlaid on CartPole-v1, showing reward curves, the policy-inspector heatmap of a layer's weight distribution over training, and an all-metrics grid

The live dashboard — PPO and DQN overlaid on CartPole-v1: reward curves, the policy inspector (per-layer weight & gradient distributions over training, as a heatmap), an all-metrics grid, and a run-comparison table — updating while you train.

Why rlens

  • See the policy, not just the loss. A zero-setup local dashboard — no W&B account, no TensorBoard process to babysit. Watch per-layer weight & gradient distributions evolve over training in the policy inspector, not just scalar norms (details below).
  • Benchmark & compare. One command runs an (algorithm × env × seed) grid; a sortable comparison table and a config-diff view turn a sweep into a single glance.
  • Reproduced & trustworthy. PPO/DQN/SAC match reference returns on standard envs (benchmarks), and every run snapshots its config, library versions and git SHA.
  • Resumable & robust. Full-state checkpoints, automatic best-policy saving, and crash-safe --resume.
  • One trainer, three algorithms. Adding an algorithm means writing act() and update(); observability comes for free.

Who it's for

Students, educators, and solo researchers working on a single machine — anyone who wants to see and compare what their agents are doing without standing up a tracking service. It stays small, local, and readable by design.

It is not built for distributed / multi-GPU training, large algorithm zoos, or hosted experiment tracking — reach for RLlib, Stable-Baselines3, or Weights & Biases there.

Install

pip install rlens

# optional extras:
pip install "rlens[box2d]"   # LunarLander, BipedalWalker (needs a compiler/swig)
pip install "rlens[atari]"   # Atari / image observations

Requires Python 3.11+. Runs on CPU or Apple Silicon (MPS); no CUDA required.

Quickstart

# 1. train a policy (telemetry streams to ./runs/<run-name>)
rlens train --algo ppo --env CartPole-v1

# 2. in another terminal, watch it learn live
rlens dashboard                       # → http://127.0.0.1:8000

# 3. score the trained policy and record a rollout video
rlens eval runs/<run-name> --episodes 20 --video

# 4. run a benchmark grid, then summarize it as a table
rlens bench configs/bench.yaml --runs-dir runs
rlens report runs --episodes 20

Dashboard

rlens dashboard serves a live, no-build web UI that tails run directories — attach to a running job, a finished one, or a whole benchmark grid:

  • A featured reward curve for any logged metric, overlaying multiple runs, with EMA smoothing and a step ↔ wall-time x-axis toggle.
  • A policy inspector — per-layer weight and gradient distributions rendered as a heatmap over training (x = step, y = value, colour = density). See weights spread or saturate and gradients collapse, layer by layer — the introspection W&B/TensorBoard make you wire up by hand.
  • An all-metrics grid — every logged scalar at once (losses, KL, clipfrac, explained variance, per-layer gradient norms, eval curves, FPS), grouped by namespace and overlaid across runs. The smoothing and x-axis controls apply to the whole grid.
  • A sortable run-comparison table (best/last return, eval score, steps, FPS, status).
  • A config panel showing exactly which hyperparameters produced a curve — with a diff mode that highlights what changed across selected runs.
  • Auto-captured gradient norms, action distributions, and inline rollout video.

It reads the same SQLite stores the trainer writes (WAL mode → safe concurrent reads), so the dashboard is fully decoupled from training and adds no overhead to the hot loop.

Benchmarks

rlens reproduces commonly reported reference returns — headline results (best policy, 3 seeds, CPU):

algorithm env eval return reference status
PPO CartPole-v1 500.0 ± 0.0 ≥ 475 (solved)
DQN CartPole-v1 500.0 ± 0.0 ≥ 475 (solved)
PPO Acrobot-v1 −86.4 ± 4.9 ≥ −100
DQN Acrobot-v1 −81.1 ± 0.6 ≥ −100
SAC Pendulum-v1 −131.4 ± 0.3 ≥ −250
PPO LunarLander-v3 229.9 ± 9.4 ≥ 200 (solved)
DQN LunarLander-v3 251.5 ± 9.7 ≥ 200 (solved)

Full methodology, per-seed numbers, and one-command reproduction are in benchmarks/.

Training & configuration

Set any hyperparameter from the command line with --set key=value. Algorithm knobs (lr, gamma, batch_size, hidden, …) and run-level knobs (num_envs, rollout_len, learning_starts, …) share one namespace and are type-checked against the config schema — an unknown key fails immediately and lists the valid ones:

rlens train --algo sac --env Pendulum-v1 --set lr=3e-4 --set hidden=[256,256] --set tau=0.01

For repeatable runs, keep the config in YAML and override pieces on the command line:

rlens train --config configs/ppo_cartpole.yaml --steps 200000 --set lr=1e-3

Precedence is defaults < --config < explicit flags < --set. The fully-resolved config (plus library versions and git SHA) is saved to each run's run.json.

Evaluation & best policy

Training returns mix in exploration, so they undersell a policy. rlens eval loads a run and scores it greedily:

rlens eval runs/<run-name>                   # mean ± std return over 10 episodes
rlens eval runs/<run-name> --episodes 20 --video
rlens eval runs/<run-name> --stochastic      # sample actions instead of greedy
rlens eval runs/<run-name> --best            # score the best-eval checkpoint

Pass --eval-interval to log a clean eval/return_mean curve during training (distinct from the noisy rollout/episodic_return). When eval is enabled, training also saves best_policy.pt — the highest-scoring policy, not just the last (RL often drifts after it first solves a task):

rlens train --algo dqn --env CartPole-v1 --eval-interval 5000 --eval-episodes 10

Checkpointing & resume

Every run writes a final checkpoint; --checkpoint-interval adds periodic ones. A checkpoint captures the full training state — weights, optimizer momentum, target networks, counters and RNG — so --resume continues exactly where it stopped instead of cold-starting:

rlens train --algo dqn --env CartPole-v1 --steps 500000 --checkpoint-interval 50000
rlens train --resume runs/<run-name>                 # finish the original budget
rlens train --resume runs/<run-name> --steps 1000000 # ...or extend it

The newest few checkpoints are kept (checkpoint_keep, default 3); policy.pt (weights only, for rlens eval) is written separately.

Off-policy throughput

DQN and SAC decouple collection from updates, so you can trade wall-clock against sample-efficiency. The replay ratio (gradient_steps / (update_every × num_envs)) is what matters; defaults match the classic one-update-per-step recipe, and lowering the ratio is dramatically faster — often just as good when the default over-updates. On DQN/CartPole (20k steps, CPU):

--num-envs --update-every --gradient-steps wall eval return
1 1 1 (default) 9.4 s 145.9
8 8 8 8.0 s 169.1
8 4 1 2.3 s 225.4
8 8 1 1.3 s 185.4
rlens train --algo sac --env Pendulum-v1 --num-envs 8 --update-every 8 --gradient-steps 2

Image observations & Atari

Any env with a 3-D Box observation automatically gets a Nature-CNN encoder (Mnih et al. 2015) instead of an MLP. Images travel as uint8 (the encoder normalizes), so replay memory stays feasible, and channels-last frames are transposed to channel-first for you.

pip install "rlens[atari]"
rlens train --algo dqn --env ALE/Breakout-v5     # 84x84 grayscale, 4-frame stack, CNN
rlens train --algo ppo --env ALE/Pong-v5

Atari ids (ALE/...) get the standard 84×84 grayscale + frame-skip + 4-frame-stack pipeline; DQN and PPO handle discrete-action image envs.

Reaching published Atari scores needs ~10M frames and a GPU. On CPU/MPS the full pipeline runs and learns (verified end-to-end on a synthetic image task in the test suite), but reproducing benchmark scores is out of scope for laptop hardware.

Algorithms

Algorithm Type Action space Observations
PPO on-policy discrete + continuous vector + image
DQN off-policy discrete vector + image
SAC off-policy continuous vector

All three share one trainer and one telemetry layer.

Project layout

rlens/
  core/         device, seeding, envs, buffers, networks
  algos/        ppo, dqn, sac (+ base Algorithm)
  trainer.py    shared on-policy / off-policy loop
  telemetry/    recorder, SQLite store, gradient & frame/video capture
  experiment/   config, single-run, benchmark grid, eval, report
  dashboard/    FastAPI server + no-build static SPA
benchmarks/     reproducible benchmark specs + results
configs/        example train / benchmark configs

Development

git clone https://github.com/can2erol/rlens && cd rlens
pip install -e ".[dev]"

ruff check rlens tests     # lint
pytest                     # full suite (CPU; ~1 min)

CI runs ruff + pytest on Python 3.11 and 3.12 for every push and pull request.

Status

Early/alpha — the public API may still change. Issues and contributions are welcome.

License

MIT — see LICENSE. Bundles uPlot (MIT); see THIRD_PARTY.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rlens-0.2.0.tar.gz (88.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rlens-0.2.0-py3-none-any.whl (84.0 kB view details)

Uploaded Python 3

File details

Details for the file rlens-0.2.0.tar.gz.

File metadata

  • Download URL: rlens-0.2.0.tar.gz
  • Upload date:
  • Size: 88.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rlens-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c89ada8dfd06d7dd5c7e041bb84326cc6634654e6b1a692332440ad6bc124407
MD5 32b85e389df198d9420707e05b8f3ddf
BLAKE2b-256 1bc71117ae893f0d6166a34069c4e6accc0371120c2d99e1ea61360a36d99ee9

See more details on using hashes here.

Provenance

The following attestation bundles were made for rlens-0.2.0.tar.gz:

Publisher: publish.yml on can2erol/rlens

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rlens-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: rlens-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 84.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rlens-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 290eaa79056462cc41daa22d1eefca31965d01f51ae33de8e5a9900288803ea0
MD5 d117b7d2b9fd0fdf648f0a8cc7038c3b
BLAKE2b-256 6b536a8547da0fb3611c4e90c1a50b97a5d6eabb2388f58c26396bc0c651bff8

See more details on using hashes here.

Provenance

The following attestation bundles were made for rlens-0.2.0-py3-none-any.whl:

Publisher: publish.yml on can2erol/rlens

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page