tuff-rl 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. tuff_rl-0.1.0/LICENSE +21 -0
  2. tuff_rl-0.1.0/MANIFEST.in +2 -0
  3. tuff_rl-0.1.0/PKG-INFO +171 -0
  4. tuff_rl-0.1.0/README.md +136 -0
  5. tuff_rl-0.1.0/pyproject.toml +66 -0
  6. tuff_rl-0.1.0/setup.cfg +4 -0
  7. tuff_rl-0.1.0/src/tuff_rl.egg-info/PKG-INFO +171 -0
  8. tuff_rl-0.1.0/src/tuff_rl.egg-info/SOURCES.txt +42 -0
  9. tuff_rl-0.1.0/src/tuff_rl.egg-info/dependency_links.txt +1 -0
  10. tuff_rl-0.1.0/src/tuff_rl.egg-info/entry_points.txt +2 -0
  11. tuff_rl-0.1.0/src/tuff_rl.egg-info/requires.txt +8 -0
  12. tuff_rl-0.1.0/src/tuff_rl.egg-info/top_level.txt +1 -0
  13. tuff_rl-0.1.0/src/tuffrl/__init__.py +53 -0
  14. tuff_rl-0.1.0/src/tuffrl/__main__.py +3 -0
  15. tuff_rl-0.1.0/src/tuffrl/board/__init__.py +5 -0
  16. tuff_rl-0.1.0/src/tuffrl/board/launch.py +144 -0
  17. tuff_rl-0.1.0/src/tuffrl/board/lock.py +40 -0
  18. tuff_rl-0.1.0/src/tuffrl/board/server.py +189 -0
  19. tuff_rl-0.1.0/src/tuffrl/board/static/assets/index-D4-8ALNT.js +1 -0
  20. tuff_rl-0.1.0/src/tuffrl/board/static/assets/index-DWNZ33px.js +1 -0
  21. tuff_rl-0.1.0/src/tuffrl/board/static/assets/index-fGqPXvQK.js +38 -0
  22. tuff_rl-0.1.0/src/tuffrl/board/static/assets/index-xWSStQ1s.css +1 -0
  23. tuff_rl-0.1.0/src/tuffrl/board/static/index.html +18 -0
  24. tuff_rl-0.1.0/src/tuffrl/board/store.py +193 -0
  25. tuff_rl-0.1.0/src/tuffrl/capture/__init__.py +6 -0
  26. tuff_rl-0.1.0/src/tuffrl/capture/stdout.py +71 -0
  27. tuff_rl-0.1.0/src/tuffrl/capture/system.py +90 -0
  28. tuff_rl-0.1.0/src/tuffrl/cli.py +50 -0
  29. tuff_rl-0.1.0/src/tuffrl/compat.py +82 -0
  30. tuff_rl-0.1.0/src/tuffrl/events/__init__.py +21 -0
  31. tuff_rl-0.1.0/src/tuffrl/events/crc32c.py +52 -0
  32. tuff_rl-0.1.0/src/tuffrl/events/proto.py +108 -0
  33. tuff_rl-0.1.0/src/tuffrl/events/reader.py +75 -0
  34. tuff_rl-0.1.0/src/tuffrl/events/records.py +68 -0
  35. tuff_rl-0.1.0/src/tuffrl/events/schema.py +353 -0
  36. tuff_rl-0.1.0/src/tuffrl/events/writer.py +79 -0
  37. tuff_rl-0.1.0/src/tuffrl/run.py +183 -0
  38. tuff_rl-0.1.0/tests/conftest.py +5 -0
  39. tuff_rl-0.1.0/tests/helpers.py +19 -0
  40. tuff_rl-0.1.0/tests/test_board.py +84 -0
  41. tuff_rl-0.1.0/tests/test_compat.py +76 -0
  42. tuff_rl-0.1.0/tests/test_events.py +87 -0
  43. tuff_rl-0.1.0/tests/test_run.py +56 -0
  44. tuff_rl-0.1.0/tests/test_store.py +68 -0
tuff_rl-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Talex-Touch contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ graft tests
2
+ global-exclude __pycache__ *.py[cod]
tuff_rl-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,171 @@
1
+ Metadata-Version: 2.4
2
+ Name: tuff-rl
3
+ Version: 0.1.0
4
+ Summary: Training logs as TensorBoard event files, and a live board that follows them
5
+ Author: TalexDreamSoul
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/talex-touch/tuff-rl
8
+ Project-URL: Repository, https://github.com/talex-touch/tuff-rl
9
+ Project-URL: Issues, https://github.com/talex-touch/tuff-rl/issues
10
+ Project-URL: Changelog, https://github.com/talex-touch/tuff-rl/blob/main/CHANGELOG.md
11
+ Keywords: reinforcement-learning,tensorboard,tfevents,experiment-tracking,training-dashboard,machine-learning
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Web Environment
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
+ Classifier: Topic :: Scientific/Engineering :: Visualization
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Provides-Extra: system
29
+ Requires-Dist: psutil>=5.9; extra == "system"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=8.0; extra == "dev"
32
+ Requires-Dist: tensorboard>=2.15; extra == "dev"
33
+ Requires-Dist: tensorboardX>=2.6; extra == "dev"
34
+ Dynamic: license-file
35
+
36
+ # tuff-rl
37
+
38
+ **Training logs as TensorBoard event files, and a live board that follows them.**
39
+
40
+ [English](https://github.com/talex-touch/tuff-rl/blob/main/README.md) · [简体中文](https://github.com/talex-touch/tuff-rl/blob/main/README.zh.md)
41
+
42
+ [![PyPI](https://img.shields.io/pypi/v/tuff-rl)](https://pypi.org/project/tuff-rl/)
43
+ [![Python](https://img.shields.io/pypi/pyversions/tuff-rl)](https://pypi.org/project/tuff-rl/)
44
+ [![CI](https://github.com/talex-touch/tuff-rl/actions/workflows/ci.yml/badge.svg)](https://github.com/talex-touch/tuff-rl/actions/workflows/ci.yml)
45
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/talex-touch/tuff-rl/blob/main/LICENSE)
46
+
47
+ ![The board following six CartPole runs while they train](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-live.gif)
48
+
49
+ One call in a training script writes everything about the run into TensorBoard event files
50
+ under `logs/`: the metrics, the config, what the script prints, and the CPU, memory and GPU
51
+ it used. The same call starts a board in your browser that follows those files as they grow.
52
+ `tensorboard --logdir logs` opens the same files, and the board opens directories that
53
+ TensorBoard, tensorboardX or PyTorch wrote. The package has no dependencies.
54
+
55
+ ## Install
56
+
57
+ ```bash
58
+ pip install tuff-rl
59
+ pip install "tuff-rl[system]" # adds CPU and memory metrics, through psutil
60
+ ```
61
+
62
+ ## Quick start
63
+
64
+ ```python
65
+ import tuffrl
66
+
67
+ run = tuffrl.init(logdir="logs", group="cartpole/lr-0.5", name="seed-0", config={"lr": 0.5, "gamma": 0.99})
68
+ for step in range(10_000):
69
+ ...
70
+ run.log({"train": {"loss": loss, "return": episode_return}}, step=step)
71
+ run.finish()
72
+ ```
73
+
74
+ The first script to start opens the board at <http://127.0.0.1:6066>; scripts started later
75
+ join it, so a sweep of many processes shares one board. A run that ends with an exception is
76
+ marked failed, and one stopped with Ctrl-C is marked stopped. Under `torch.distributed`, only
77
+ rank 0 starts the board.
78
+
79
+ Code that already uses PyTorch's `SummaryWriter` changes only its import:
80
+
81
+ ```python
82
+ from tuffrl import SummaryWriter
83
+ ```
84
+
85
+ The shim covers `add_scalar`, `add_scalars`, `add_text`, `add_hparams`, `flush` and `close`.
86
+
87
+ ## Try the demo
88
+
89
+ ```bash
90
+ pip install "tuff-rl[system]"
91
+ curl -O https://raw.githubusercontent.com/talex-touch/tuff-rl/main/examples/cartpole.py
92
+ python cartpole.py
93
+ ```
94
+
95
+ REINFORCE on CartPole in plain Python: two learning rates, three seeds each, six processes
96
+ in parallel. It takes about 35 seconds.
97
+
98
+ ## The board
99
+
100
+ | | |
101
+ | --- | --- |
102
+ | ![Two learning rates, each drawn as the mean of three seeds with a band for their spread](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-groups.png) | ![The config of six runs side by side, with the two differing keys marked](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-config.png) |
103
+ | Runs in one directory form a group. Merged, a group is drawn as its mean with a band for the spread of its runs. | The config of every run side by side, with the keys that differ marked. |
104
+ | ![The printed output of one run, with stderr in red](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-output.png) | ![CPU and memory charts for the runs](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-system.png) |
105
+ | What each run printed, stdout and stderr in order, searchable, following new lines. | CPU and memory of the training machine and process, and the GPUs that `nvidia-smi` reports. |
106
+
107
+ Charts smooth with an exponential moving average and can also show the raw values and a log
108
+ x-axis. Drag across a chart to zoom in, and double-click it to zoom back out. The board
109
+ follows the system's light or dark theme.
110
+
111
+ ## Training on another machine
112
+
113
+ Over SSH the board starts on the training machine and does not open a browser. Instead it
114
+ prints the command that forwards its port to your own machine:
115
+
116
+ ```text
117
+ [tuffrl] board: http://127.0.0.1:6066 (logdir /data/logs)
118
+ [tuffrl] from your own machine: ssh -N -L 6066:127.0.0.1:6066 you@gpu-box then open http://127.0.0.1:6066
119
+ ```
120
+
121
+ The board has no login. It listens on 127.0.0.1 unless `TUFFRL_BOARD_HOST` says otherwise;
122
+ listening on another address shows your logs and config to anyone who can reach that port.
123
+
124
+ ## Command line and settings
125
+
126
+ ```bash
127
+ tuff-rl board logs # serve a log directory, including one TensorBoard wrote
128
+ tuff-rl stop logs # stop the board serving it
129
+ ```
130
+
131
+ | Variable | Effect |
132
+ | --- | --- |
133
+ | `TUFFRL_BOARD=0` | Training scripts do not start the board. |
134
+ | `TUFFRL_OPEN_BROWSER=0` | The board starts but no browser opens. |
135
+ | `TUFFRL_BOARD_PORT` | Port to try first (default 6066); the next free one is used when it is taken. |
136
+ | `TUFFRL_BOARD_HOST` | Address to listen on (default 127.0.0.1). |
137
+
138
+ ## How it works
139
+
140
+ - **Event files.** The writer frames records the way TFRecord does (length, CRC32C, data,
141
+ CRC32C) and encodes the `Event` and `Summary` protobufs by hand, so neither TensorFlow nor
142
+ protobuf is needed. Metrics are scalar summaries, printed output uses the text plugin, and
143
+ the config is an HParams session, so TensorBoard's HParams tab lists the runs and groups
144
+ them by `group`.
145
+ - **The board.** A standard-library HTTP server reads each event file from where it stopped,
146
+ and the page receives a snapshot followed by a stream of new points (server-sent events).
147
+ The page is a Vue app built on [TuffEx](https://www.npmjs.com/package/@talex-touch/tuffex)
148
+ and ships inside the wheel.
149
+ - **One board per log directory.** `logs/.tuffrl/board.json` records which board serves the
150
+ directory. Scripts starting at the same moment agree on one of them to launch it, and the
151
+ board keeps running after training ends until `tuff-rl stop`.
152
+
153
+ ## Status
154
+
155
+ 0.1 is an alpha. The board reads images and audio but does not show them yet; that and the
156
+ rest of the plan are in the [roadmap issues](https://github.com/talex-touch/tuff-rl/issues?q=is%3Aissue+label%3Aroadmap).
157
+
158
+ ## Development
159
+
160
+ ```bash
161
+ cd web && pnpm install && pnpm build && cd .. # builds the board page into src/tuffrl/board/static
162
+ pip install -e ".[dev,system]"
163
+ python -m pytest
164
+ uvx ruff check .
165
+ ```
166
+
167
+ See [CONTRIBUTING.md](https://github.com/talex-touch/tuff-rl/blob/main/CONTRIBUTING.md) for the rest, including how a release is made.
168
+
169
+ ## License
170
+
171
+ [MIT](https://github.com/talex-touch/tuff-rl/blob/main/LICENSE)
@@ -0,0 +1,136 @@
1
+ # tuff-rl
2
+
3
+ **Training logs as TensorBoard event files, and a live board that follows them.**
4
+
5
+ [English](https://github.com/talex-touch/tuff-rl/blob/main/README.md) · [简体中文](https://github.com/talex-touch/tuff-rl/blob/main/README.zh.md)
6
+
7
+ [![PyPI](https://img.shields.io/pypi/v/tuff-rl)](https://pypi.org/project/tuff-rl/)
8
+ [![Python](https://img.shields.io/pypi/pyversions/tuff-rl)](https://pypi.org/project/tuff-rl/)
9
+ [![CI](https://github.com/talex-touch/tuff-rl/actions/workflows/ci.yml/badge.svg)](https://github.com/talex-touch/tuff-rl/actions/workflows/ci.yml)
10
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/talex-touch/tuff-rl/blob/main/LICENSE)
11
+
12
+ ![The board following six CartPole runs while they train](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-live.gif)
13
+
14
+ One call in a training script writes everything about the run into TensorBoard event files
15
+ under `logs/`: the metrics, the config, what the script prints, and the CPU, memory and GPU
16
+ it used. The same call starts a board in your browser that follows those files as they grow.
17
+ `tensorboard --logdir logs` opens the same files, and the board opens directories that
18
+ TensorBoard, tensorboardX or PyTorch wrote. The package has no dependencies.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install tuff-rl
24
+ pip install "tuff-rl[system]" # adds CPU and memory metrics, through psutil
25
+ ```
26
+
27
+ ## Quick start
28
+
29
+ ```python
30
+ import tuffrl
31
+
32
+ run = tuffrl.init(logdir="logs", group="cartpole/lr-0.5", name="seed-0", config={"lr": 0.5, "gamma": 0.99})
33
+ for step in range(10_000):
34
+ ...
35
+ run.log({"train": {"loss": loss, "return": episode_return}}, step=step)
36
+ run.finish()
37
+ ```
38
+
39
+ The first script to start opens the board at <http://127.0.0.1:6066>; scripts started later
40
+ join it, so a sweep of many processes shares one board. A run that ends with an exception is
41
+ marked failed, and one stopped with Ctrl-C is marked stopped. Under `torch.distributed`, only
42
+ rank 0 starts the board.
43
+
44
+ Code that already uses PyTorch's `SummaryWriter` changes only its import:
45
+
46
+ ```python
47
+ from tuffrl import SummaryWriter
48
+ ```
49
+
50
+ The shim covers `add_scalar`, `add_scalars`, `add_text`, `add_hparams`, `flush` and `close`.
51
+
52
+ ## Try the demo
53
+
54
+ ```bash
55
+ pip install "tuff-rl[system]"
56
+ curl -O https://raw.githubusercontent.com/talex-touch/tuff-rl/main/examples/cartpole.py
57
+ python cartpole.py
58
+ ```
59
+
60
+ REINFORCE on CartPole in plain Python: two learning rates, three seeds each, six processes
61
+ in parallel. It takes about 35 seconds.
62
+
63
+ ## The board
64
+
65
+ | | |
66
+ | --- | --- |
67
+ | ![Two learning rates, each drawn as the mean of three seeds with a band for their spread](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-groups.png) | ![The config of six runs side by side, with the two differing keys marked](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-config.png) |
68
+ | Runs in one directory form a group. Merged, a group is drawn as its mean with a band for the spread of its runs. | The config of every run side by side, with the keys that differ marked. |
69
+ | ![The printed output of one run, with stderr in red](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-output.png) | ![CPU and memory charts for the runs](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-system.png) |
70
+ | What each run printed, stdout and stderr in order, searchable, following new lines. | CPU and memory of the training machine and process, and the GPUs that `nvidia-smi` reports. |
71
+
72
+ Charts smooth with an exponential moving average and can also show the raw values and a log
73
+ x-axis. Drag across a chart to zoom in, and double-click it to zoom back out. The board
74
+ follows the system's light or dark theme.
75
+
76
+ ## Training on another machine
77
+
78
+ Over SSH the board starts on the training machine and does not open a browser. Instead it
79
+ prints the command that forwards its port to your own machine:
80
+
81
+ ```text
82
+ [tuffrl] board: http://127.0.0.1:6066 (logdir /data/logs)
83
+ [tuffrl] from your own machine: ssh -N -L 6066:127.0.0.1:6066 you@gpu-box then open http://127.0.0.1:6066
84
+ ```
85
+
86
+ The board has no login. It listens on 127.0.0.1 unless `TUFFRL_BOARD_HOST` says otherwise;
87
+ listening on another address shows your logs and config to anyone who can reach that port.
88
+
89
+ ## Command line and settings
90
+
91
+ ```bash
92
+ tuff-rl board logs # serve a log directory, including one TensorBoard wrote
93
+ tuff-rl stop logs # stop the board serving it
94
+ ```
95
+
96
+ | Variable | Effect |
97
+ | --- | --- |
98
+ | `TUFFRL_BOARD=0` | Training scripts do not start the board. |
99
+ | `TUFFRL_OPEN_BROWSER=0` | The board starts but no browser opens. |
100
+ | `TUFFRL_BOARD_PORT` | Port to try first (default 6066); the next free one is used when it is taken. |
101
+ | `TUFFRL_BOARD_HOST` | Address to listen on (default 127.0.0.1). |
102
+
103
+ ## How it works
104
+
105
+ - **Event files.** The writer frames records the way TFRecord does (length, CRC32C, data,
106
+ CRC32C) and encodes the `Event` and `Summary` protobufs by hand, so neither TensorFlow nor
107
+ protobuf is needed. Metrics are scalar summaries, printed output uses the text plugin, and
108
+ the config is an HParams session, so TensorBoard's HParams tab lists the runs and groups
109
+ them by `group`.
110
+ - **The board.** A standard-library HTTP server reads each event file from where it stopped,
111
+ and the page receives a snapshot followed by a stream of new points (server-sent events).
112
+ The page is a Vue app built on [TuffEx](https://www.npmjs.com/package/@talex-touch/tuffex)
113
+ and ships inside the wheel.
114
+ - **One board per log directory.** `logs/.tuffrl/board.json` records which board serves the
115
+ directory. Scripts starting at the same moment agree on one of them to launch it, and the
116
+ board keeps running after training ends until `tuff-rl stop`.
117
+
118
+ ## Status
119
+
120
+ 0.1 is an alpha. The board reads images and audio but does not show them yet; that and the
121
+ rest of the plan are in the [roadmap issues](https://github.com/talex-touch/tuff-rl/issues?q=is%3Aissue+label%3Aroadmap).
122
+
123
+ ## Development
124
+
125
+ ```bash
126
+ cd web && pnpm install && pnpm build && cd .. # builds the board page into src/tuffrl/board/static
127
+ pip install -e ".[dev,system]"
128
+ python -m pytest
129
+ uvx ruff check .
130
+ ```
131
+
132
+ See [CONTRIBUTING.md](https://github.com/talex-touch/tuff-rl/blob/main/CONTRIBUTING.md) for the rest, including how a release is made.
133
+
134
+ ## License
135
+
136
+ [MIT](https://github.com/talex-touch/tuff-rl/blob/main/LICENSE)
@@ -0,0 +1,66 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "tuff-rl"
7
+ dynamic = ["version"]
8
+ description = "Training logs as TensorBoard event files, and a live board that follows them"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "TalexDreamSoul" }]
14
+ keywords = ["reinforcement-learning", "tensorboard", "tfevents", "experiment-tracking", "training-dashboard", "machine-learning"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Environment :: Web Environment",
18
+ "Intended Audience :: Developers",
19
+ "Intended Audience :: Science/Research",
20
+ "Operating System :: MacOS",
21
+ "Operating System :: POSIX :: Linux",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
28
+ "Topic :: Scientific/Engineering :: Visualization",
29
+ ]
30
+ # The writer, the reader and the board run on the standard library alone, so the package
31
+ # installs on any training machine without touching its environment.
32
+ dependencies = []
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/talex-touch/tuff-rl"
36
+ Repository = "https://github.com/talex-touch/tuff-rl"
37
+ Issues = "https://github.com/talex-touch/tuff-rl/issues"
38
+ Changelog = "https://github.com/talex-touch/tuff-rl/blob/main/CHANGELOG.md"
39
+
40
+ [project.optional-dependencies]
41
+ # Process and machine metrics; without it the board records only what the standard library sees.
42
+ system = ["psutil>=5.9"]
43
+ dev = ["pytest>=8.0", "tensorboard>=2.15", "tensorboardX>=2.6"]
44
+
45
+ [project.scripts]
46
+ tuff-rl = "tuffrl.cli:main"
47
+
48
+ [tool.setuptools.packages.find]
49
+ where = ["src"]
50
+
51
+ [tool.setuptools.package-data]
52
+ # Built from web/ (pnpm build) before packaging; the release workflow checks it is there.
53
+ tuffrl = ["board/static/**/*"]
54
+
55
+ [tool.setuptools.dynamic]
56
+ version = { attr = "tuffrl.__version__" }
57
+
58
+ [tool.pytest.ini_options]
59
+ testpaths = ["tests"]
60
+
61
+ [tool.ruff]
62
+ line-length = 160
63
+ target-version = "py310"
64
+
65
+ [tool.ruff.lint]
66
+ select = ["E4", "E7", "E9", "F", "W", "I", "UP", "B", "SIM", "ARG", "A", "N", "BLE"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,171 @@
1
+ Metadata-Version: 2.4
2
+ Name: tuff-rl
3
+ Version: 0.1.0
4
+ Summary: Training logs as TensorBoard event files, and a live board that follows them
5
+ Author: TalexDreamSoul
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/talex-touch/tuff-rl
8
+ Project-URL: Repository, https://github.com/talex-touch/tuff-rl
9
+ Project-URL: Issues, https://github.com/talex-touch/tuff-rl/issues
10
+ Project-URL: Changelog, https://github.com/talex-touch/tuff-rl/blob/main/CHANGELOG.md
11
+ Keywords: reinforcement-learning,tensorboard,tfevents,experiment-tracking,training-dashboard,machine-learning
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Web Environment
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
+ Classifier: Topic :: Scientific/Engineering :: Visualization
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Provides-Extra: system
29
+ Requires-Dist: psutil>=5.9; extra == "system"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=8.0; extra == "dev"
32
+ Requires-Dist: tensorboard>=2.15; extra == "dev"
33
+ Requires-Dist: tensorboardX>=2.6; extra == "dev"
34
+ Dynamic: license-file
35
+
36
+ # tuff-rl
37
+
38
+ **Training logs as TensorBoard event files, and a live board that follows them.**
39
+
40
+ [English](https://github.com/talex-touch/tuff-rl/blob/main/README.md) · [简体中文](https://github.com/talex-touch/tuff-rl/blob/main/README.zh.md)
41
+
42
+ [![PyPI](https://img.shields.io/pypi/v/tuff-rl)](https://pypi.org/project/tuff-rl/)
43
+ [![Python](https://img.shields.io/pypi/pyversions/tuff-rl)](https://pypi.org/project/tuff-rl/)
44
+ [![CI](https://github.com/talex-touch/tuff-rl/actions/workflows/ci.yml/badge.svg)](https://github.com/talex-touch/tuff-rl/actions/workflows/ci.yml)
45
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/talex-touch/tuff-rl/blob/main/LICENSE)
46
+
47
+ ![The board following six CartPole runs while they train](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-live.gif)
48
+
49
+ One call in a training script writes everything about the run into TensorBoard event files
50
+ under `logs/`: the metrics, the config, what the script prints, and the CPU, memory and GPU
51
+ it used. The same call starts a board in your browser that follows those files as they grow.
52
+ `tensorboard --logdir logs` opens the same files, and the board opens directories that
53
+ TensorBoard, tensorboardX or PyTorch wrote. The package has no dependencies.
54
+
55
+ ## Install
56
+
57
+ ```bash
58
+ pip install tuff-rl
59
+ pip install "tuff-rl[system]" # adds CPU and memory metrics, through psutil
60
+ ```
61
+
62
+ ## Quick start
63
+
64
+ ```python
65
+ import tuffrl
66
+
67
+ run = tuffrl.init(logdir="logs", group="cartpole/lr-0.5", name="seed-0", config={"lr": 0.5, "gamma": 0.99})
68
+ for step in range(10_000):
69
+ ...
70
+ run.log({"train": {"loss": loss, "return": episode_return}}, step=step)
71
+ run.finish()
72
+ ```
73
+
74
+ The first script to start opens the board at <http://127.0.0.1:6066>; scripts started later
75
+ join it, so a sweep of many processes shares one board. A run that ends with an exception is
76
+ marked failed, and one stopped with Ctrl-C is marked stopped. Under `torch.distributed`, only
77
+ rank 0 starts the board.
78
+
79
+ Code that already uses PyTorch's `SummaryWriter` changes only its import:
80
+
81
+ ```python
82
+ from tuffrl import SummaryWriter
83
+ ```
84
+
85
+ The shim covers `add_scalar`, `add_scalars`, `add_text`, `add_hparams`, `flush` and `close`.
86
+
87
+ ## Try the demo
88
+
89
+ ```bash
90
+ pip install "tuff-rl[system]"
91
+ curl -O https://raw.githubusercontent.com/talex-touch/tuff-rl/main/examples/cartpole.py
92
+ python cartpole.py
93
+ ```
94
+
95
+ REINFORCE on CartPole in plain Python: two learning rates, three seeds each, six processes
96
+ in parallel. It takes about 35 seconds.
97
+
98
+ ## The board
99
+
100
+ | | |
101
+ | --- | --- |
102
+ | ![Two learning rates, each drawn as the mean of three seeds with a band for their spread](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-groups.png) | ![The config of six runs side by side, with the two differing keys marked](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-config.png) |
103
+ | Runs in one directory form a group. Merged, a group is drawn as its mean with a band for the spread of its runs. | The config of every run side by side, with the keys that differ marked. |
104
+ | ![The printed output of one run, with stderr in red](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-output.png) | ![CPU and memory charts for the runs](https://raw.githubusercontent.com/talex-touch/tuff-rl/main/docs/images/board-system.png) |
105
+ | What each run printed, stdout and stderr in order, searchable, following new lines. | CPU and memory of the training machine and process, and the GPUs that `nvidia-smi` reports. |
106
+
107
+ Charts smooth with an exponential moving average and can also show the raw values and a log
108
+ x-axis. Drag across a chart to zoom in, and double-click it to zoom back out. The board
109
+ follows the system's light or dark theme.
110
+
111
+ ## Training on another machine
112
+
113
+ Over SSH the board starts on the training machine and does not open a browser. Instead it
114
+ prints the command that forwards its port to your own machine:
115
+
116
+ ```text
117
+ [tuffrl] board: http://127.0.0.1:6066 (logdir /data/logs)
118
+ [tuffrl] from your own machine: ssh -N -L 6066:127.0.0.1:6066 you@gpu-box then open http://127.0.0.1:6066
119
+ ```
120
+
121
+ The board has no login. It listens on 127.0.0.1 unless `TUFFRL_BOARD_HOST` says otherwise;
122
+ listening on another address shows your logs and config to anyone who can reach that port.
123
+
124
+ ## Command line and settings
125
+
126
+ ```bash
127
+ tuff-rl board logs # serve a log directory, including one TensorBoard wrote
128
+ tuff-rl stop logs # stop the board serving it
129
+ ```
130
+
131
+ | Variable | Effect |
132
+ | --- | --- |
133
+ | `TUFFRL_BOARD=0` | Training scripts do not start the board. |
134
+ | `TUFFRL_OPEN_BROWSER=0` | The board starts but no browser opens. |
135
+ | `TUFFRL_BOARD_PORT` | Port to try first (default 6066); the next free one is used when it is taken. |
136
+ | `TUFFRL_BOARD_HOST` | Address to listen on (default 127.0.0.1). |
137
+
138
+ ## How it works
139
+
140
+ - **Event files.** The writer frames records the way TFRecord does (length, CRC32C, data,
141
+ CRC32C) and encodes the `Event` and `Summary` protobufs by hand, so neither TensorFlow nor
142
+ protobuf is needed. Metrics are scalar summaries, printed output uses the text plugin, and
143
+ the config is an HParams session, so TensorBoard's HParams tab lists the runs and groups
144
+ them by `group`.
145
+ - **The board.** A standard-library HTTP server reads each event file from where it stopped,
146
+ and the page receives a snapshot followed by a stream of new points (server-sent events).
147
+ The page is a Vue app built on [TuffEx](https://www.npmjs.com/package/@talex-touch/tuffex)
148
+ and ships inside the wheel.
149
+ - **One board per log directory.** `logs/.tuffrl/board.json` records which board serves the
150
+ directory. Scripts starting at the same moment agree on one of them to launch it, and the
151
+ board keeps running after training ends until `tuff-rl stop`.
152
+
153
+ ## Status
154
+
155
+ 0.1 is an alpha. The board reads images and audio but does not show them yet; that and the
156
+ rest of the plan are in the [roadmap issues](https://github.com/talex-touch/tuff-rl/issues?q=is%3Aissue+label%3Aroadmap).
157
+
158
+ ## Development
159
+
160
+ ```bash
161
+ cd web && pnpm install && pnpm build && cd .. # builds the board page into src/tuffrl/board/static
162
+ pip install -e ".[dev,system]"
163
+ python -m pytest
164
+ uvx ruff check .
165
+ ```
166
+
167
+ See [CONTRIBUTING.md](https://github.com/talex-touch/tuff-rl/blob/main/CONTRIBUTING.md) for the rest, including how a release is made.
168
+
169
+ ## License
170
+
171
+ [MIT](https://github.com/talex-touch/tuff-rl/blob/main/LICENSE)
@@ -0,0 +1,42 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ src/tuff_rl.egg-info/PKG-INFO
6
+ src/tuff_rl.egg-info/SOURCES.txt
7
+ src/tuff_rl.egg-info/dependency_links.txt
8
+ src/tuff_rl.egg-info/entry_points.txt
9
+ src/tuff_rl.egg-info/requires.txt
10
+ src/tuff_rl.egg-info/top_level.txt
11
+ src/tuffrl/__init__.py
12
+ src/tuffrl/__main__.py
13
+ src/tuffrl/cli.py
14
+ src/tuffrl/compat.py
15
+ src/tuffrl/run.py
16
+ src/tuffrl/board/__init__.py
17
+ src/tuffrl/board/launch.py
18
+ src/tuffrl/board/lock.py
19
+ src/tuffrl/board/server.py
20
+ src/tuffrl/board/store.py
21
+ src/tuffrl/board/static/index.html
22
+ src/tuffrl/board/static/assets/index-D4-8ALNT.js
23
+ src/tuffrl/board/static/assets/index-DWNZ33px.js
24
+ src/tuffrl/board/static/assets/index-fGqPXvQK.js
25
+ src/tuffrl/board/static/assets/index-xWSStQ1s.css
26
+ src/tuffrl/capture/__init__.py
27
+ src/tuffrl/capture/stdout.py
28
+ src/tuffrl/capture/system.py
29
+ src/tuffrl/events/__init__.py
30
+ src/tuffrl/events/crc32c.py
31
+ src/tuffrl/events/proto.py
32
+ src/tuffrl/events/reader.py
33
+ src/tuffrl/events/records.py
34
+ src/tuffrl/events/schema.py
35
+ src/tuffrl/events/writer.py
36
+ tests/conftest.py
37
+ tests/helpers.py
38
+ tests/test_board.py
39
+ tests/test_compat.py
40
+ tests/test_events.py
41
+ tests/test_run.py
42
+ tests/test_store.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ tuff-rl = tuffrl.cli:main
@@ -0,0 +1,8 @@
1
+
2
+ [dev]
3
+ pytest>=8.0
4
+ tensorboard>=2.15
5
+ tensorboardX>=2.6
6
+
7
+ [system]
8
+ psutil>=5.9
@@ -0,0 +1 @@
1
+ tuffrl