rl-template 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.
- rl_template-0.1.0/.gitignore +11 -0
- rl_template-0.1.0/.python-version +1 -0
- rl_template-0.1.0/AGENTS.md +82 -0
- rl_template-0.1.0/PKG-INFO +145 -0
- rl_template-0.1.0/README.md +132 -0
- rl_template-0.1.0/mypy.ini +4 -0
- rl_template-0.1.0/pyproject.toml +22 -0
- rl_template-0.1.0/requirements.txt +79 -0
- rl_template-0.1.0/rl_template/__init__.py +0 -0
- rl_template-0.1.0/rl_template/agent.py +69 -0
- rl_template-0.1.0/rl_template/algorithms/__init__.py +0 -0
- rl_template-0.1.0/rl_template/algorithms/ppo/__init__.py +0 -0
- rl_template-0.1.0/rl_template/algorithms/ppo/ppo.py +183 -0
- rl_template-0.1.0/rl_template/common.py +119 -0
- rl_template-0.1.0/rl_template/config.py +73 -0
- rl_template-0.1.0/rl_template/env.py +52 -0
- rl_template-0.1.0/rl_template/errors.py +26 -0
- rl_template-0.1.0/rl_template/train.py +127 -0
- rl_template-0.1.0/ruff.toml +47 -0
- rl_template-0.1.0/tests/__init__.py +0 -0
- rl_template-0.1.0/tests/test_agent.py +108 -0
- rl_template-0.1.0/tests/test_buffer_integration.py +109 -0
- rl_template-0.1.0/tests/test_common.py +244 -0
- rl_template-0.1.0/tests/test_config.py +124 -0
- rl_template-0.1.0/tests/test_continuous_actions.py +299 -0
- rl_template-0.1.0/tests/test_env.py +113 -0
- rl_template-0.1.0/tests/test_errors.py +55 -0
- rl_template-0.1.0/tests/test_ppo.py +247 -0
- rl_template-0.1.0/tests/test_train.py +160 -0
- rl_template-0.1.0/uv.lock +8 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.11
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Project
|
|
4
|
+
|
|
5
|
+
RL training template built on PyTorch + Gymnasium. Provides abstract base classes (`BaseAgent`, `BaseEnv`, `BaseTrain`) and a concrete PPO (Proximal Policy Optimization) implementation. Includes a full test suite (107 tests, all passing).
|
|
6
|
+
|
|
7
|
+
## Package management
|
|
8
|
+
|
|
9
|
+
- Managed with **uv** (lockfile: `uv.lock`, Python version: `.python-version` → 3.11)
|
|
10
|
+
- Dependencies are pinned in `requirements.txt`, not declared in `pyproject.toml`
|
|
11
|
+
|
|
12
|
+
## Lint / typecheck
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
ruff check rl_template/ # linter (Pyflakes only, ruff.toml)
|
|
16
|
+
mypy rl_template/ # strict: disallow_untyped_defs, warn_unreachable (mypy.ini)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
No pre-commit hooks, no CI, no formatter config beyond ruff defaults.
|
|
20
|
+
|
|
21
|
+
## Import style gotcha
|
|
22
|
+
|
|
23
|
+
- `train.py` uses **relative imports** (`from .env import BaseEnv`) — requires package-level import
|
|
24
|
+
- `ppo.py` uses **relative imports** (`from ...common import Buffer`) — assumes package-level import
|
|
25
|
+
- `algorithms/__init__.py` and `algorithms/ppo/__init__.py` exist (empty) — required for relative imports in `ppo.py` to resolve
|
|
26
|
+
|
|
27
|
+
## Structure
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
rl_template/
|
|
31
|
+
__init__.py # empty package marker
|
|
32
|
+
agent.py # BaseAgent (ABC, nn.Module) — abstract agent interface
|
|
33
|
+
env.py # BaseEnv (ABC) — Gymnasium v1 API wrapper interface
|
|
34
|
+
train.py # BaseTrain (ABC) — rollout/update/save training loop
|
|
35
|
+
common.py # Buffer — pre-allocated numpy rollout buffer with size property
|
|
36
|
+
config.py # PPOConfig (frozen), TrainConfig, WandbConfig dataclasses
|
|
37
|
+
errors.py # EmptyBufferError with detailed __str__
|
|
38
|
+
algorithms/
|
|
39
|
+
__init__.py # package marker (empty)
|
|
40
|
+
ppo/
|
|
41
|
+
__init__.py # package marker (empty)
|
|
42
|
+
ppo.py # PPOTrainer — GAE, clipped surrogate loss, linear LR decay
|
|
43
|
+
tests/
|
|
44
|
+
__init__.py
|
|
45
|
+
test_common.py # Buffer unit tests (21 tests)
|
|
46
|
+
test_config.py # Config dataclass tests (13 tests)
|
|
47
|
+
test_errors.py # EmptyBufferError tests (7 tests)
|
|
48
|
+
test_ppo.py # PPOTrainer tests (12 tests)
|
|
49
|
+
test_buffer_integration.py # Buffer integration tests (10 tests)
|
|
50
|
+
test_agent.py # BaseAgent abstract interface tests (12 tests)
|
|
51
|
+
test_env.py # BaseEnv abstract interface tests (11 tests)
|
|
52
|
+
test_train.py # BaseTrain tests: init, save_model, update_weights (6 tests)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Conventions
|
|
56
|
+
|
|
57
|
+
- Abstract base classes use `@abstractmethod` with concrete bodies (template method pattern) — subclasses override and optionally call `super()`
|
|
58
|
+
- `PPOConfig` is `frozen=True` (immutable); `TrainConfig` uses `__post_init__` for computed fields
|
|
59
|
+
- `Buffer` pre-allocates numpy arrays and uses a slice pointer with a `size` property and bounds checking in `insert()`
|
|
60
|
+
- GPU detection is automatic in `TrainConfig.device`
|
|
61
|
+
- Tests use pytest, import rl_template as a package (`from rl_template.common import Buffer`)
|
|
62
|
+
|
|
63
|
+
## Testing
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
python -m pytest tests/ -v # run all 107 tests
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Fixes applied
|
|
70
|
+
|
|
71
|
+
- Created `algorithms/__init__.py` and `algorithms/ppo/__init__.py` for package resolution
|
|
72
|
+
- Added `size` property to `Buffer` class (returns current element count)
|
|
73
|
+
- Added bounds checking in `Buffer.insert()` — raises `ValueError` when buffer is full
|
|
74
|
+
- Fixed `save_model()` to use `os.makedirs(os.path.dirname(...), exist_ok=True)` instead of creating a `.pt` directory
|
|
75
|
+
- Fixed PPO `update()` loss tracking — `index_loss` now increments correctly, final mean excludes trailing zeros
|
|
76
|
+
- Fixed typo `BaseAgnt` → `BaseAgent` in `agent.py`
|
|
77
|
+
- Fixed `ruff.toml` `target-version` from `"py313"` to `"py311"` to match `.python-version`
|
|
78
|
+
- Removed `print()` side effects from `TrainConfig.__post_init__`
|
|
79
|
+
- Fixed `Buffer.get_all()` actions dtype from `torch.long` to `torch.float32` (continuous actions were silently truncated to integers)
|
|
80
|
+
- Fixed `Distributions` → `Distribution` import typo in `agent.py` (pre-existing bug, class is singular in PyTorch)
|
|
81
|
+
- Changed `train.py` from bare imports to relative imports for package-level compatibility
|
|
82
|
+
- Rewrote all docstrings and comments across source and test files for consistency
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rl-template
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A type-safe, algorithm-agnostic Reinforcement Learning framework
|
|
5
|
+
Author-email: Mohamed Tine <mohamedtine17@gmail.com>
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
8
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Requires-Dist: numpy>=1.24.0
|
|
11
|
+
Requires-Dist: torch>=2.0.0
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# RL Template
|
|
15
|
+
|
|
16
|
+
A modular reinforcement learning training framework built on PyTorch and Gymnasium, providing abstract base classes and a concrete PPO implementation.
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- **Abstract base classes** — `BaseAgent`, `BaseEnv`, `BaseTrain` with template method pattern for easy extension
|
|
21
|
+
- **PPO implementation** — Clipped surrogate loss, GAE, linear LR decay, entropy bonus, gradient clipping
|
|
22
|
+
- **Pre-allocated buffer** — Zero-allocation rollout storage with bounds checking, supports discrete and continuous actions
|
|
23
|
+
- **Frozen configs** — Immutable `PPOConfig` and computed `TrainConfig` dataclasses
|
|
24
|
+
- **Auto GPU detection** — Automatic CUDA/CPU device selection
|
|
25
|
+
- **107 tests** — Full test suite covering all components
|
|
26
|
+
|
|
27
|
+
## Project Structure
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
rl_template/
|
|
31
|
+
__init__.py
|
|
32
|
+
agent.py # BaseAgent — abstract policy/value interface
|
|
33
|
+
env.py # BaseEnv — Gymnasium v1 API wrapper
|
|
34
|
+
train.py # BaseTrain — rollout/update training loop
|
|
35
|
+
common.py # Buffer — pre-allocated numpy rollout buffer
|
|
36
|
+
config.py # PPOConfig, TrainConfig, WandbConfig
|
|
37
|
+
errors.py # EmptyBufferError
|
|
38
|
+
algorithms/
|
|
39
|
+
ppo/
|
|
40
|
+
ppo.py # PPOTrainer — GAE + clipped surrogate loss
|
|
41
|
+
tests/
|
|
42
|
+
test_agent.py # BaseAgent tests (12)
|
|
43
|
+
test_env.py # BaseEnv tests (11)
|
|
44
|
+
test_train.py # BaseTrain tests (6)
|
|
45
|
+
test_common.py # Buffer tests (21)
|
|
46
|
+
test_config.py # Config tests (13)
|
|
47
|
+
test_errors.py # Error tests (7)
|
|
48
|
+
test_ppo.py # PPOTrainer tests (15)
|
|
49
|
+
test_buffer_integration.py # Buffer integration tests (6)
|
|
50
|
+
test_continuous_actions.py # Continuous action tests (16)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
Requires Python 3.11+.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# With uv (recommended)
|
|
59
|
+
uv sync
|
|
60
|
+
|
|
61
|
+
# With pip
|
|
62
|
+
pip install -r requirements.txt
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import numpy as np
|
|
69
|
+
from rl_template.agent import BaseAgent
|
|
70
|
+
from rl_template.env import BaseEnv
|
|
71
|
+
from rl_template.train import BaseTrain
|
|
72
|
+
from rl_template.common import Buffer
|
|
73
|
+
from rl_template.config import TrainConfig, PPOConfig
|
|
74
|
+
from rl_template.algorithms.ppo.ppo import PPOTrainer
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# 1. Implement your agent
|
|
78
|
+
class MyAgent(BaseAgent):
|
|
79
|
+
# Implement forward(), get_distribution()
|
|
80
|
+
...
|
|
81
|
+
|
|
82
|
+
# 2. Implement your environment
|
|
83
|
+
class MyEnv(BaseEnv):
|
|
84
|
+
# Implement reset(), step(), close()
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
# 3. Configure training
|
|
88
|
+
config = TrainConfig(model_name="my_agent", model_saved_path="./checkpoints")
|
|
89
|
+
ppo_config = PPOConfig(lr=3e-4, gamma=0.99, clip_eps=0.2)
|
|
90
|
+
|
|
91
|
+
# 4. Wire everything together
|
|
92
|
+
agent = MyAgent()
|
|
93
|
+
env = MyEnv()
|
|
94
|
+
buffer = Buffer(step=config.rollout_steps, state_shape=(4,))
|
|
95
|
+
ppo_trainer = PPOTrainer(agent, lr=ppo_config.lr, gamma=ppo_config.gamma)
|
|
96
|
+
|
|
97
|
+
# 5. Create trainer and run
|
|
98
|
+
class MyTrain(BaseTrain):
|
|
99
|
+
def rollout_phase(self, state): super().rollout_phase(state)
|
|
100
|
+
def update_weights(self, step): super().update_weights(step)
|
|
101
|
+
def save_model(self): super().save_model()
|
|
102
|
+
|
|
103
|
+
trainer = MyTrain(agent, env, buffer, config, ppo_trainer)
|
|
104
|
+
state, _ = env.reset()
|
|
105
|
+
|
|
106
|
+
for step in range(config.num_update):
|
|
107
|
+
trainer.rollout_phase(state)
|
|
108
|
+
trainer.update_weights(step)
|
|
109
|
+
trainer.save_model()
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Key Classes
|
|
113
|
+
|
|
114
|
+
| Class | Description |
|
|
115
|
+
|-------|-------------|
|
|
116
|
+
| `BaseAgent` | Abstract agent combining ABC and nn.Module. Subclasses implement `forward()` and `get_distribution()`. The `get_action()` template method handles sampling and log-probability computation. |
|
|
117
|
+
| `BaseEnv` | Abstract Gymnasium v1 environment wrapper. Subclasses implement `reset()`, `step()`, and `close()`. |
|
|
118
|
+
| `BaseTrain` | Abstract training loop orchestrating rollout collection, GAE computation, and PPO updates. |
|
|
119
|
+
| `Buffer` | Pre-allocated numpy buffer for rollout data. Supports discrete and continuous actions with automatic dtype handling. |
|
|
120
|
+
| `PPOTrainer` | PPO algorithm implementation with GAE, clipped surrogate loss, value loss, entropy bonus, and linear LR decay. |
|
|
121
|
+
| `PPOConfig` | Frozen (immutable) PPO hyperparameters. |
|
|
122
|
+
| `TrainConfig` | Training configuration with auto-computed `model_path` and `num_update`. |
|
|
123
|
+
|
|
124
|
+
## PPO Algorithm
|
|
125
|
+
|
|
126
|
+
The PPO trainer implements:
|
|
127
|
+
|
|
128
|
+
- **Generalized Advantage Estimation (GAE)** — Blended n-step returns for low-variance advantage estimates
|
|
129
|
+
- **Clipped surrogate loss** — Prevents destructive policy updates
|
|
130
|
+
- **Value function loss** — MSE loss for the critic network
|
|
131
|
+
- **Entropy bonus** — Encourages exploration
|
|
132
|
+
- **Linear LR decay** — Learning rate anneals to zero over training
|
|
133
|
+
- **Gradient clipping** — Max norm of 1.0 for stability
|
|
134
|
+
|
|
135
|
+
## Testing
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
python -m pytest tests/ -v
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
All 107 tests cover unit tests for each component, integration tests for buffer workflows, and continuous action space validation.
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# RL Template
|
|
2
|
+
|
|
3
|
+
A modular reinforcement learning training framework built on PyTorch and Gymnasium, providing abstract base classes and a concrete PPO implementation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Abstract base classes** — `BaseAgent`, `BaseEnv`, `BaseTrain` with template method pattern for easy extension
|
|
8
|
+
- **PPO implementation** — Clipped surrogate loss, GAE, linear LR decay, entropy bonus, gradient clipping
|
|
9
|
+
- **Pre-allocated buffer** — Zero-allocation rollout storage with bounds checking, supports discrete and continuous actions
|
|
10
|
+
- **Frozen configs** — Immutable `PPOConfig` and computed `TrainConfig` dataclasses
|
|
11
|
+
- **Auto GPU detection** — Automatic CUDA/CPU device selection
|
|
12
|
+
- **107 tests** — Full test suite covering all components
|
|
13
|
+
|
|
14
|
+
## Project Structure
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
rl_template/
|
|
18
|
+
__init__.py
|
|
19
|
+
agent.py # BaseAgent — abstract policy/value interface
|
|
20
|
+
env.py # BaseEnv — Gymnasium v1 API wrapper
|
|
21
|
+
train.py # BaseTrain — rollout/update training loop
|
|
22
|
+
common.py # Buffer — pre-allocated numpy rollout buffer
|
|
23
|
+
config.py # PPOConfig, TrainConfig, WandbConfig
|
|
24
|
+
errors.py # EmptyBufferError
|
|
25
|
+
algorithms/
|
|
26
|
+
ppo/
|
|
27
|
+
ppo.py # PPOTrainer — GAE + clipped surrogate loss
|
|
28
|
+
tests/
|
|
29
|
+
test_agent.py # BaseAgent tests (12)
|
|
30
|
+
test_env.py # BaseEnv tests (11)
|
|
31
|
+
test_train.py # BaseTrain tests (6)
|
|
32
|
+
test_common.py # Buffer tests (21)
|
|
33
|
+
test_config.py # Config tests (13)
|
|
34
|
+
test_errors.py # Error tests (7)
|
|
35
|
+
test_ppo.py # PPOTrainer tests (15)
|
|
36
|
+
test_buffer_integration.py # Buffer integration tests (6)
|
|
37
|
+
test_continuous_actions.py # Continuous action tests (16)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
Requires Python 3.11+.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# With uv (recommended)
|
|
46
|
+
uv sync
|
|
47
|
+
|
|
48
|
+
# With pip
|
|
49
|
+
pip install -r requirements.txt
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Usage
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
import numpy as np
|
|
56
|
+
from rl_template.agent import BaseAgent
|
|
57
|
+
from rl_template.env import BaseEnv
|
|
58
|
+
from rl_template.train import BaseTrain
|
|
59
|
+
from rl_template.common import Buffer
|
|
60
|
+
from rl_template.config import TrainConfig, PPOConfig
|
|
61
|
+
from rl_template.algorithms.ppo.ppo import PPOTrainer
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# 1. Implement your agent
|
|
65
|
+
class MyAgent(BaseAgent):
|
|
66
|
+
# Implement forward(), get_distribution()
|
|
67
|
+
...
|
|
68
|
+
|
|
69
|
+
# 2. Implement your environment
|
|
70
|
+
class MyEnv(BaseEnv):
|
|
71
|
+
# Implement reset(), step(), close()
|
|
72
|
+
...
|
|
73
|
+
|
|
74
|
+
# 3. Configure training
|
|
75
|
+
config = TrainConfig(model_name="my_agent", model_saved_path="./checkpoints")
|
|
76
|
+
ppo_config = PPOConfig(lr=3e-4, gamma=0.99, clip_eps=0.2)
|
|
77
|
+
|
|
78
|
+
# 4. Wire everything together
|
|
79
|
+
agent = MyAgent()
|
|
80
|
+
env = MyEnv()
|
|
81
|
+
buffer = Buffer(step=config.rollout_steps, state_shape=(4,))
|
|
82
|
+
ppo_trainer = PPOTrainer(agent, lr=ppo_config.lr, gamma=ppo_config.gamma)
|
|
83
|
+
|
|
84
|
+
# 5. Create trainer and run
|
|
85
|
+
class MyTrain(BaseTrain):
|
|
86
|
+
def rollout_phase(self, state): super().rollout_phase(state)
|
|
87
|
+
def update_weights(self, step): super().update_weights(step)
|
|
88
|
+
def save_model(self): super().save_model()
|
|
89
|
+
|
|
90
|
+
trainer = MyTrain(agent, env, buffer, config, ppo_trainer)
|
|
91
|
+
state, _ = env.reset()
|
|
92
|
+
|
|
93
|
+
for step in range(config.num_update):
|
|
94
|
+
trainer.rollout_phase(state)
|
|
95
|
+
trainer.update_weights(step)
|
|
96
|
+
trainer.save_model()
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Key Classes
|
|
100
|
+
|
|
101
|
+
| Class | Description |
|
|
102
|
+
|-------|-------------|
|
|
103
|
+
| `BaseAgent` | Abstract agent combining ABC and nn.Module. Subclasses implement `forward()` and `get_distribution()`. The `get_action()` template method handles sampling and log-probability computation. |
|
|
104
|
+
| `BaseEnv` | Abstract Gymnasium v1 environment wrapper. Subclasses implement `reset()`, `step()`, and `close()`. |
|
|
105
|
+
| `BaseTrain` | Abstract training loop orchestrating rollout collection, GAE computation, and PPO updates. |
|
|
106
|
+
| `Buffer` | Pre-allocated numpy buffer for rollout data. Supports discrete and continuous actions with automatic dtype handling. |
|
|
107
|
+
| `PPOTrainer` | PPO algorithm implementation with GAE, clipped surrogate loss, value loss, entropy bonus, and linear LR decay. |
|
|
108
|
+
| `PPOConfig` | Frozen (immutable) PPO hyperparameters. |
|
|
109
|
+
| `TrainConfig` | Training configuration with auto-computed `model_path` and `num_update`. |
|
|
110
|
+
|
|
111
|
+
## PPO Algorithm
|
|
112
|
+
|
|
113
|
+
The PPO trainer implements:
|
|
114
|
+
|
|
115
|
+
- **Generalized Advantage Estimation (GAE)** — Blended n-step returns for low-variance advantage estimates
|
|
116
|
+
- **Clipped surrogate loss** — Prevents destructive policy updates
|
|
117
|
+
- **Value function loss** — MSE loss for the critic network
|
|
118
|
+
- **Entropy bonus** — Encourages exploration
|
|
119
|
+
- **Linear LR decay** — Learning rate anneals to zero over training
|
|
120
|
+
- **Gradient clipping** — Max norm of 1.0 for stability
|
|
121
|
+
|
|
122
|
+
## Testing
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
python -m pytest tests/ -v
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
All 107 tests cover unit tests for each component, integration tests for buffer workflows, and continuous action space validation.
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "rl-template"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A type-safe, algorithm-agnostic Reinforcement Learning framework"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
authors = [
|
|
8
|
+
{ name = "Mohamed Tine", email = "mohamedtine17@gmail.com" }
|
|
9
|
+
]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Programming Language :: Python :: 3.11",
|
|
12
|
+
"License :: OSI Approved :: MIT License",
|
|
13
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence"
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"torch>=2.0.0",
|
|
17
|
+
"numpy>=1.24.0"
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[build-system]
|
|
21
|
+
requires = ["hatchling"]
|
|
22
|
+
build-backend = "hatchling.build"
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
alembic==1.18.5
|
|
2
|
+
annotated-types==0.7.0
|
|
3
|
+
bottle==0.13.4
|
|
4
|
+
certifi==2026.6.17
|
|
5
|
+
charset-normalizer==3.4.9
|
|
6
|
+
click==8.4.2
|
|
7
|
+
cloudpickle==3.1.2
|
|
8
|
+
colorlog==6.10.1
|
|
9
|
+
contourpy==1.3.3
|
|
10
|
+
cuda-bindings==13.3.1
|
|
11
|
+
cuda-pathfinder==1.5.6
|
|
12
|
+
cuda-toolkit==13.0.3.0
|
|
13
|
+
cycler==0.12.1
|
|
14
|
+
farama-notifications==0.0.6
|
|
15
|
+
filelock==3.29.7
|
|
16
|
+
fonttools==4.63.0
|
|
17
|
+
fsspec==2026.6.0
|
|
18
|
+
gitdb==4.0.12
|
|
19
|
+
gitpython==3.1.50
|
|
20
|
+
greenlet==3.5.3
|
|
21
|
+
gymnasium==1.3.0
|
|
22
|
+
idna==3.18
|
|
23
|
+
jinja2==3.1.6
|
|
24
|
+
joblib==1.5.3
|
|
25
|
+
kiwisolver==1.5.0
|
|
26
|
+
mako==1.3.12
|
|
27
|
+
markupsafe==3.0.3
|
|
28
|
+
matplotlib==3.11.0
|
|
29
|
+
mpmath==1.3.0
|
|
30
|
+
narwhals==2.23.0
|
|
31
|
+
networkx==3.6.1
|
|
32
|
+
numpy==2.4.6
|
|
33
|
+
nvidia-cublas==13.1.1.3
|
|
34
|
+
nvidia-cuda-cupti==13.0.85
|
|
35
|
+
nvidia-cuda-nvrtc==13.0.88
|
|
36
|
+
nvidia-cuda-runtime==13.0.96
|
|
37
|
+
nvidia-cudnn-cu13==9.20.0.48
|
|
38
|
+
nvidia-cufft==12.0.0.61
|
|
39
|
+
nvidia-cufile==1.15.1.6
|
|
40
|
+
nvidia-curand==10.4.0.35
|
|
41
|
+
nvidia-cusolver==12.0.4.66
|
|
42
|
+
nvidia-cusparse==12.6.3.3
|
|
43
|
+
nvidia-cusparselt-cu13==0.8.1
|
|
44
|
+
nvidia-nccl-cu13==2.29.7
|
|
45
|
+
nvidia-nvjitlink==13.3.33
|
|
46
|
+
nvidia-nvshmem-cu13==3.4.5
|
|
47
|
+
nvidia-nvtx==13.0.85
|
|
48
|
+
optuna==4.9.0
|
|
49
|
+
optuna-dashboard==0.20.0
|
|
50
|
+
packaging==26.2
|
|
51
|
+
pandas==3.0.3
|
|
52
|
+
pillow==12.3.0
|
|
53
|
+
platformdirs==4.10.0
|
|
54
|
+
plotly==6.8.0
|
|
55
|
+
protobuf==7.35.1
|
|
56
|
+
pydantic==2.13.4
|
|
57
|
+
pydantic-core==2.46.4
|
|
58
|
+
pyparsing==3.3.2
|
|
59
|
+
python-dateutil==2.9.0.post0
|
|
60
|
+
pyyaml==6.0.3
|
|
61
|
+
requests==2.34.2
|
|
62
|
+
ruff==0.15.20
|
|
63
|
+
scikit-learn==1.9.0
|
|
64
|
+
scipy==1.17.1
|
|
65
|
+
seaborn==0.13.2
|
|
66
|
+
sentry-sdk==2.64.0
|
|
67
|
+
setuptools==83.0.0
|
|
68
|
+
six==1.17.0
|
|
69
|
+
smmap==5.0.3
|
|
70
|
+
sqlalchemy==2.0.51
|
|
71
|
+
sympy==1.14.0
|
|
72
|
+
threadpoolctl==3.6.0
|
|
73
|
+
torch==2.13.0
|
|
74
|
+
tqdm==4.68.4
|
|
75
|
+
triton==3.7.1
|
|
76
|
+
typing-extensions==4.16.0
|
|
77
|
+
typing-inspection==0.4.2
|
|
78
|
+
urllib3==2.7.0
|
|
79
|
+
wandb==0.28.0
|
|
File without changes
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Abstract base agent interface for reinforcement learning.
|
|
2
|
+
|
|
3
|
+
Provides BaseAgent, an ABC + nn.Module hybrid that enforces a consistent
|
|
4
|
+
policy/value interface for all RL agent implementations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import torch.nn as nn
|
|
9
|
+
from torch.distributions import Distribution
|
|
10
|
+
from torch import Tensor
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BaseAgent(ABC, nn.Module):
|
|
15
|
+
"""Abstract base class for all RL agents.
|
|
16
|
+
|
|
17
|
+
Subclasses must implement forward() and get_distribution(). The
|
|
18
|
+
get_action() template method composes those two to sample actions,
|
|
19
|
+
compute log probabilities, and return critic values.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self):
|
|
23
|
+
super().__init__()
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def forward(self, state: np.ndarray) -> tuple[Tensor, Tensor]:
|
|
27
|
+
"""Compute raw policy logits and value estimate.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
state: Environment observation.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Tuple of (policy_logits, value) tensors.
|
|
34
|
+
"""
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def get_distribution(self, state: np.ndarray) -> tuple[Distribution, Tensor]:
|
|
39
|
+
"""Build a distribution over actions for the given state.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
state: Environment observation.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Tuple of (distribution, value) where distribution is a
|
|
46
|
+
torch.distributions.Distribution instance.
|
|
47
|
+
"""
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
def get_action(self, state: np.ndarray, action: int | None = None) -> tuple[Tensor, Tensor, Tensor, Tensor]:
|
|
51
|
+
"""Sample or evaluate an action under the current policy.
|
|
52
|
+
|
|
53
|
+
Template method: calls get_distribution(), then samples if no
|
|
54
|
+
action is provided.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
state: Environment observation.
|
|
58
|
+
action: Optional pre-selected action. When None, samples from
|
|
59
|
+
the policy distribution.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Tuple of (action, log_prob, entropy, value).
|
|
63
|
+
"""
|
|
64
|
+
dist, value = self.get_distribution(state)
|
|
65
|
+
if action is None:
|
|
66
|
+
action = dist.sample()
|
|
67
|
+
log_prob = dist.log_prob(action)
|
|
68
|
+
dist_entropy = dist.entropy()
|
|
69
|
+
return (action, log_prob, dist_entropy, value)
|
|
File without changes
|
|
File without changes
|