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.
- tuff_rl-0.1.0/LICENSE +21 -0
- tuff_rl-0.1.0/MANIFEST.in +2 -0
- tuff_rl-0.1.0/PKG-INFO +171 -0
- tuff_rl-0.1.0/README.md +136 -0
- tuff_rl-0.1.0/pyproject.toml +66 -0
- tuff_rl-0.1.0/setup.cfg +4 -0
- tuff_rl-0.1.0/src/tuff_rl.egg-info/PKG-INFO +171 -0
- tuff_rl-0.1.0/src/tuff_rl.egg-info/SOURCES.txt +42 -0
- tuff_rl-0.1.0/src/tuff_rl.egg-info/dependency_links.txt +1 -0
- tuff_rl-0.1.0/src/tuff_rl.egg-info/entry_points.txt +2 -0
- tuff_rl-0.1.0/src/tuff_rl.egg-info/requires.txt +8 -0
- tuff_rl-0.1.0/src/tuff_rl.egg-info/top_level.txt +1 -0
- tuff_rl-0.1.0/src/tuffrl/__init__.py +53 -0
- tuff_rl-0.1.0/src/tuffrl/__main__.py +3 -0
- tuff_rl-0.1.0/src/tuffrl/board/__init__.py +5 -0
- tuff_rl-0.1.0/src/tuffrl/board/launch.py +144 -0
- tuff_rl-0.1.0/src/tuffrl/board/lock.py +40 -0
- tuff_rl-0.1.0/src/tuffrl/board/server.py +189 -0
- tuff_rl-0.1.0/src/tuffrl/board/static/assets/index-D4-8ALNT.js +1 -0
- tuff_rl-0.1.0/src/tuffrl/board/static/assets/index-DWNZ33px.js +1 -0
- tuff_rl-0.1.0/src/tuffrl/board/static/assets/index-fGqPXvQK.js +38 -0
- tuff_rl-0.1.0/src/tuffrl/board/static/assets/index-xWSStQ1s.css +1 -0
- tuff_rl-0.1.0/src/tuffrl/board/static/index.html +18 -0
- tuff_rl-0.1.0/src/tuffrl/board/store.py +193 -0
- tuff_rl-0.1.0/src/tuffrl/capture/__init__.py +6 -0
- tuff_rl-0.1.0/src/tuffrl/capture/stdout.py +71 -0
- tuff_rl-0.1.0/src/tuffrl/capture/system.py +90 -0
- tuff_rl-0.1.0/src/tuffrl/cli.py +50 -0
- tuff_rl-0.1.0/src/tuffrl/compat.py +82 -0
- tuff_rl-0.1.0/src/tuffrl/events/__init__.py +21 -0
- tuff_rl-0.1.0/src/tuffrl/events/crc32c.py +52 -0
- tuff_rl-0.1.0/src/tuffrl/events/proto.py +108 -0
- tuff_rl-0.1.0/src/tuffrl/events/reader.py +75 -0
- tuff_rl-0.1.0/src/tuffrl/events/records.py +68 -0
- tuff_rl-0.1.0/src/tuffrl/events/schema.py +353 -0
- tuff_rl-0.1.0/src/tuffrl/events/writer.py +79 -0
- tuff_rl-0.1.0/src/tuffrl/run.py +183 -0
- tuff_rl-0.1.0/tests/conftest.py +5 -0
- tuff_rl-0.1.0/tests/helpers.py +19 -0
- tuff_rl-0.1.0/tests/test_board.py +84 -0
- tuff_rl-0.1.0/tests/test_compat.py +76 -0
- tuff_rl-0.1.0/tests/test_events.py +87 -0
- tuff_rl-0.1.0/tests/test_run.py +56 -0
- 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.
|
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
|
+
[](https://pypi.org/project/tuff-rl/)
|
|
43
|
+
[](https://pypi.org/project/tuff-rl/)
|
|
44
|
+
[](https://github.com/talex-touch/tuff-rl/actions/workflows/ci.yml)
|
|
45
|
+
[](https://github.com/talex-touch/tuff-rl/blob/main/LICENSE)
|
|
46
|
+
|
|
47
|
+

|
|
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
|
+
|  |  |
|
|
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
|
+
|  |  |
|
|
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)
|
tuff_rl-0.1.0/README.md
ADDED
|
@@ -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
|
+
[](https://pypi.org/project/tuff-rl/)
|
|
8
|
+
[](https://pypi.org/project/tuff-rl/)
|
|
9
|
+
[](https://github.com/talex-touch/tuff-rl/actions/workflows/ci.yml)
|
|
10
|
+
[](https://github.com/talex-touch/tuff-rl/blob/main/LICENSE)
|
|
11
|
+
|
|
12
|
+

|
|
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
|
+
|  |  |
|
|
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
|
+
|  |  |
|
|
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"]
|
tuff_rl-0.1.0/setup.cfg
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
|
+
[](https://pypi.org/project/tuff-rl/)
|
|
43
|
+
[](https://pypi.org/project/tuff-rl/)
|
|
44
|
+
[](https://github.com/talex-touch/tuff-rl/actions/workflows/ci.yml)
|
|
45
|
+
[](https://github.com/talex-touch/tuff-rl/blob/main/LICENSE)
|
|
46
|
+
|
|
47
|
+

|
|
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
|
+
|  |  |
|
|
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
|
+
|  |  |
|
|
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 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
tuffrl
|