cds-interpret 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.
- cds_interpret-0.1.0/.gitignore +29 -0
- cds_interpret-0.1.0/CHANGELOG.md +85 -0
- cds_interpret-0.1.0/CONTRIBUTING.md +109 -0
- cds_interpret-0.1.0/LICENSE +21 -0
- cds_interpret-0.1.0/PKG-INFO +194 -0
- cds_interpret-0.1.0/README.md +154 -0
- cds_interpret-0.1.0/THIRD_PARTY.md +33 -0
- cds_interpret-0.1.0/assets/banner.png +0 -0
- cds_interpret-0.1.0/assets/overlay-panel.svg +1 -0
- cds_interpret-0.1.0/docs/README.md +35 -0
- cds_interpret-0.1.0/docs/api.md +334 -0
- cds_interpret-0.1.0/docs/coming-from.md +74 -0
- cds_interpret-0.1.0/docs/concepts.md +137 -0
- cds_interpret-0.1.0/docs/howto/bring-your-own-policy.md +162 -0
- cds_interpret-0.1.0/docs/howto/causal-tests.md +129 -0
- cds_interpret-0.1.0/docs/howto/check-your-tools.md +135 -0
- cds_interpret-0.1.0/docs/howto/customize-the-panel.md +261 -0
- cds_interpret-0.1.0/docs/howto/figures.md +76 -0
- cds_interpret-0.1.0/docs/howto/name-features.md +293 -0
- cds_interpret-0.1.0/docs/howto/overlay.md +142 -0
- cds_interpret-0.1.0/docs/howto/probes.md +159 -0
- cds_interpret-0.1.0/docs/howto/record-moments.md +137 -0
- cds_interpret-0.1.0/docs/howto/sae-features.md +107 -0
- cds_interpret-0.1.0/docs/howto/track-training.md +140 -0
- cds_interpret-0.1.0/docs/howto/what-decisions-rest-on.md +107 -0
- cds_interpret-0.1.0/docs/labels.md +101 -0
- cds_interpret-0.1.0/docs/quickstart.md +279 -0
- cds_interpret-0.1.0/docs/troubleshooting.md +215 -0
- cds_interpret-0.1.0/examples/rlbot_demo_bot/README.md +14 -0
- cds_interpret-0.1.0/examples/rlbot_demo_bot/bot.py +59 -0
- cds_interpret-0.1.0/examples/rlbot_demo_bot/bot.toml +15 -0
- cds_interpret-0.1.0/examples/rlbot_demo_bot/make_pack.py +44 -0
- cds_interpret-0.1.0/examples/rlbot_demo_bot/thoughts.bot.toml +16 -0
- cds_interpret-0.1.0/examples/rlbot_demo_bot/thoughts.npz +0 -0
- cds_interpret-0.1.0/pyproject.toml +108 -0
- cds_interpret-0.1.0/scripts/render_panel.py +81 -0
- cds_interpret-0.1.0/scripts/train_demo_policy.py +32 -0
- cds_interpret-0.1.0/src/cds_interpret/__init__.py +106 -0
- cds_interpret-0.1.0/src/cds_interpret/__main__.py +5 -0
- cds_interpret-0.1.0/src/cds_interpret/_rlbot.py +186 -0
- cds_interpret-0.1.0/src/cds_interpret/_version.py +1 -0
- cds_interpret-0.1.0/src/cds_interpret/analysis.py +244 -0
- cds_interpret-0.1.0/src/cds_interpret/attribution.py +525 -0
- cds_interpret-0.1.0/src/cds_interpret/behavior.py +181 -0
- cds_interpret-0.1.0/src/cds_interpret/cli.py +130 -0
- cds_interpret-0.1.0/src/cds_interpret/crosscoder.py +192 -0
- cds_interpret-0.1.0/src/cds_interpret/curriculum.py +190 -0
- cds_interpret-0.1.0/src/cds_interpret/demo/__init__.py +260 -0
- cds_interpret-0.1.0/src/cds_interpret/demo/demo_policy.pt +0 -0
- cds_interpret-0.1.0/src/cds_interpret/dict_eval.py +160 -0
- cds_interpret-0.1.0/src/cds_interpret/effects.py +194 -0
- cds_interpret-0.1.0/src/cds_interpret/emergence.py +534 -0
- cds_interpret-0.1.0/src/cds_interpret/erasure.py +105 -0
- cds_interpret-0.1.0/src/cds_interpret/errors.py +53 -0
- cds_interpret-0.1.0/src/cds_interpret/frames.py +289 -0
- cds_interpret-0.1.0/src/cds_interpret/hooks.py +276 -0
- cds_interpret-0.1.0/src/cds_interpret/intervene.py +232 -0
- cds_interpret-0.1.0/src/cds_interpret/labels.py +556 -0
- cds_interpret-0.1.0/src/cds_interpret/moments.py +276 -0
- cds_interpret-0.1.0/src/cds_interpret/names.py +297 -0
- cds_interpret-0.1.0/src/cds_interpret/overlay/__init__.py +49 -0
- cds_interpret-0.1.0/src/cds_interpret/overlay/bot.py +166 -0
- cds_interpret-0.1.0/src/cds_interpret/overlay/pack.py +244 -0
- cds_interpret-0.1.0/src/cds_interpret/overlay/panel.py +600 -0
- cds_interpret-0.1.0/src/cds_interpret/overlay/panel_example.toml +97 -0
- cds_interpret-0.1.0/src/cds_interpret/overlay/worker.py +204 -0
- cds_interpret-0.1.0/src/cds_interpret/policy.py +383 -0
- cds_interpret-0.1.0/src/cds_interpret/probes.py +575 -0
- cds_interpret-0.1.0/src/cds_interpret/py.typed +0 -0
- cds_interpret-0.1.0/src/cds_interpret/readout.py +217 -0
- cds_interpret-0.1.0/src/cds_interpret/record/__init__.py +20 -0
- cds_interpret-0.1.0/src/cds_interpret/record/_builder.py +111 -0
- cds_interpret-0.1.0/src/cds_interpret/record/rlbot.py +160 -0
- cds_interpret-0.1.0/src/cds_interpret/record/rlgym_env.py +105 -0
- cds_interpret-0.1.0/src/cds_interpret/record/scripted.py +52 -0
- cds_interpret-0.1.0/src/cds_interpret/record/sim.py +278 -0
- cds_interpret-0.1.0/src/cds_interpret/report.py +336 -0
- cds_interpret-0.1.0/src/cds_interpret/rlgym.py +133 -0
- cds_interpret-0.1.0/src/cds_interpret/sae.py +373 -0
- cds_interpret-0.1.0/src/cds_interpret/store.py +171 -0
- cds_interpret-0.1.0/src/cds_interpret/study.py +781 -0
- cds_interpret-0.1.0/src/cds_interpret/tracking.py +61 -0
- cds_interpret-0.1.0/src/cds_interpret/viz/__init__.py +6 -0
- cds_interpret-0.1.0/src/cds_interpret/viz/field.py +217 -0
- cds_interpret-0.1.0/src/cds_interpret/viz/gallery.py +55 -0
- cds_interpret-0.1.0/src/cds_interpret/viz/plots.py +217 -0
- cds_interpret-0.1.0/tests/conftest.py +39 -0
- cds_interpret-0.1.0/tests/test_attribution.py +111 -0
- cds_interpret-0.1.0/tests/test_core.py +454 -0
- cds_interpret-0.1.0/tests/test_crosscoder.py +37 -0
- cds_interpret-0.1.0/tests/test_effects_readout.py +89 -0
- cds_interpret-0.1.0/tests/test_emergence.py +166 -0
- cds_interpret-0.1.0/tests/test_erasure_mlp.py +48 -0
- cds_interpret-0.1.0/tests/test_examples.py +52 -0
- cds_interpret-0.1.0/tests/test_friendly.py +114 -0
- cds_interpret-0.1.0/tests/test_names_survive.py +154 -0
- cds_interpret-0.1.0/tests/test_overlay.py +218 -0
- cds_interpret-0.1.0/tests/test_panel_names.py +211 -0
- cds_interpret-0.1.0/tests/test_policy_study.py +172 -0
- cds_interpret-0.1.0/tests/test_record.py +101 -0
- cds_interpret-0.1.0/tests/test_sae_variants.py +70 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
.ruff_cache/
|
|
11
|
+
.mypy_cache/
|
|
12
|
+
.coverage
|
|
13
|
+
htmlcov/
|
|
14
|
+
|
|
15
|
+
# what the toolkit writes when you use it
|
|
16
|
+
cds-demo/
|
|
17
|
+
recordings/
|
|
18
|
+
runs/
|
|
19
|
+
*.html
|
|
20
|
+
!docs/**/*.html
|
|
21
|
+
examples/rlbot_demo_bot/recordings/
|
|
22
|
+
|
|
23
|
+
# editors and OS
|
|
24
|
+
.vscode/
|
|
25
|
+
.idea/
|
|
26
|
+
.DS_Store
|
|
27
|
+
Thumbs.db
|
|
28
|
+
|
|
29
|
+
collision_meshes/
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to cds-interpret are written down here. The project follows
|
|
4
|
+
[Semantic Versioning](https://semver.org); before 1.0, minor versions may change the API (each change is listed).
|
|
5
|
+
|
|
6
|
+
## [0.1.0] - 2026-10-17
|
|
7
|
+
|
|
8
|
+
The first public version: the interpretability toolkit of the Cat Distribution System, on its own, for any PyTorch
|
|
9
|
+
Rocket League bot.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Bring your own policy** (`Policy`): any eager PyTorch network, a function from game state to its input, its
|
|
14
|
+
action table and what its output means (logits, probabilities, log-probabilities or continuous controls).
|
|
15
|
+
`eager_copy` turns a TorchScript MLP back into hookable modules; `lookup_table()` builds the common 90-action
|
|
16
|
+
table; `describe_action` says an action in words.
|
|
17
|
+
- **Game state** (`Frames`) from RLGym v1 / v2 states, RLBot v5 packets or plain arrays, and back to RLGym v2 states
|
|
18
|
+
(`cds_interpret.rlgym`, with `obs_fn` to run any RLGym ObsBuilder on any moment).
|
|
19
|
+
- **Concept labels** for any bot's moments, from the game state alone: the ball's landing, time to the ball, last man
|
|
20
|
+
back, goal side, threats and shots, demolition chances, kickoffs, car state - and future labels from recorded play
|
|
21
|
+
(a shot, a touch, a demolition, a goal for or against soon; an `outlook` for bots without a critic).
|
|
22
|
+
`register_label` adds your own.
|
|
23
|
+
- **Recorders**: `record.rocketsim` (your bot in RocketSim against itself, another policy or a scripted player, with
|
|
24
|
+
RocketSim's ball prediction for the labels), `record.with_recorder` (your RLBot v5 bot class records the real game,
|
|
25
|
+
unchanged) and `record.rlgym` (your own RLGym v2 environment). `Moments` save and load as `.npy` column shards.
|
|
26
|
+
- **Probes** with game-wise held-out scores, the raw-input and random-network baselines, and steadiness numbers for
|
|
27
|
+
probes shown live (weight norm, noise sensitivity, jitter against the label's own); the penalty acts on one scale
|
|
28
|
+
for the whole layer by default, so a near-silent unit cannot earn a giant weight.
|
|
29
|
+
- **Sparse autoencoders** (top-k, with AuxK), their checks (variance explained, the policy run on the reconstruction)
|
|
30
|
+
and feature analysis (label relations, name guesses, strongest distinct moments, firing thresholds,
|
|
31
|
+
`causal_targets`).
|
|
32
|
+
- **Edits** for causal tests: replace with an SAE's reconstruction, ablate or scale features, clamp, steer, project
|
|
33
|
+
out or scale a probe's direction, mean-ablate; their effect on the policy (`edit_effect`), `editing(...)` for
|
|
34
|
+
whole games, and `bootstrap_share` / `rate_ratio_ci` for intervals.
|
|
35
|
+
- **`Study`**: the whole flow in a few calls, and an HTML **report** (light and dark, no internet needed) whose
|
|
36
|
+
sections are extensible (`report.section`).
|
|
37
|
+
- **The live thoughts overlay** for any RLBot v5 bot (`overlay.with_thoughts`): the outlook, the next move and how
|
|
38
|
+
sure it is, the features firing (held 0.6 s), probes as bars, and where the network thinks the ball will land.
|
|
39
|
+
Display only: read-only hooks, a low-priority worker process that is never sent anything before it is ready and
|
|
40
|
+
is written to by a thread of its own, nothing drawn on a decision's tick. Packs are plain `.npz` files.
|
|
41
|
+
- **A panel you design yourself**: rows, names, colours, firing thresholds, hold time, position, width, smoothing,
|
|
42
|
+
title and markers in a small TOML file, without touching library code (`cds-interpret panel` writes an example of
|
|
43
|
+
every option, which draws the default panel), plus Python hooks for rows and markers of your own. Mistakes show
|
|
44
|
+
when the file loads, with where they are and what you probably meant; `cds-interpret check-panel` (and the overlay
|
|
45
|
+
at start) lists rows and styles naming probes or features the pack doesn't have.
|
|
46
|
+
- **Naming features, end to end** (`names`): suggested names from the labels with warnings (a feature that fires
|
|
47
|
+
mostly at kickoffs, say), each different suggestion before any repeats, a gallery page of each feature's strongest
|
|
48
|
+
moments, a names file you confirm names in (with each feature's sizes, so thresholds can be picked), and
|
|
49
|
+
`Study.check_feature` (turn a feature off and up and see what the bot does differently - by number or by name)
|
|
50
|
+
and `make_pack(names=...)`. Names stay on their features: `Study.features` is seeded, `FeatureSet.save` /
|
|
51
|
+
`Study.load_features` keep a dictionary for good, and a names file records its dictionary's code
|
|
52
|
+
(`sae.fingerprint`) and refuses to go on any other. A threshold the feature never reaches is refused too.
|
|
53
|
+
- **Tracking** a concept across training snapshots.
|
|
54
|
+
- **Following a bot through its training** (`emergence`): its dispositions on a fixed bank of moments (the action
|
|
55
|
+
classes it puts its probability on in a demo chance, an aerial chance, a 50/50 ...), its habits in recorded games
|
|
56
|
+
with intervals (demolitions, air and wall play, flip resets, hard hits, kickoffs and kickoff goals, the goal share in
|
|
57
|
+
open play, contact), the health of its
|
|
58
|
+
layers (dead / dormant units, effective rank, CKA to another snapshot, weight norms) and the critic's calibration
|
|
59
|
+
against the next goal, and `interval_changes` for what moved beyond its intervals since the last snapshot.
|
|
60
|
+
`docs/howto/track-training.md`.
|
|
61
|
+
- **Choosing what to practise** (`curriculum`): a situation map for both sides of recorded games (how often each side
|
|
62
|
+
is in each situation, and what follows), what is over-represented before the goals a bot concedes (`enrichment`),
|
|
63
|
+
a small `kmeans` to group those moments and `eta_squared` to compare descriptions of a state.
|
|
64
|
+
- **Friendly by default**: plain-words errors that say what to do (with "did you mean" for layers and labels),
|
|
65
|
+
probes scored only when the held-out games have enough examples (and the skipped ones listed with the reason),
|
|
66
|
+
recordings that are never mixed up by accident (`if_exists`, with `"reuse"` for scripts you run again), a probe
|
|
67
|
+
table that separates what the network worked out from what its input already gave, and a step-by-step demo whose
|
|
68
|
+
edits come with a random-direction control.
|
|
69
|
+
- **What a decision rests on** (`attribution`, `Study.attribution`, a report section): the ball, the bot's car and
|
|
70
|
+
boost, the opponents and the team-mates swapped for another moment's through the bot's own obs function, every
|
|
71
|
+
combination run, exact Shapley shares, and a faithfulness score for any ranking (1 = the best possible order).
|
|
72
|
+
`docs/howto/what-decisions-rest-on.md`.
|
|
73
|
+
- **What each feature makes the bot do** (`effects`): every active feature removed on its own, its change in each
|
|
74
|
+
control and in the chosen action; the features a decision rests on; rankings scored by removing them together;
|
|
75
|
+
attribution patching as the cheap estimate. `hooks.tail` gives the network after a layer.
|
|
76
|
+
- **Checks for the tools themselves** (`docs/howto/check-your-tools.md`): `sae.downstream_check`, `sae.finetune_kl`
|
|
77
|
+
and a KL term in `train_sae` (a dictionary faithful to the decisions), `sae.BatchTopKSAE`, `dict_eval` (seed
|
|
78
|
+
stability by decoder and by firing, single-feature label detection, liveness), `erasure` (LEACE with a same-rank
|
|
79
|
+
placebo: does the policy use what a probe reads?), `probes.mlp_probe`, and `readout` (calibrated gauges -
|
|
80
|
+
`calibrate_pack_probe` - smoothing with its measured lag, flag flicker).
|
|
81
|
+
- **A crosscoder over training snapshots** (`crosscoder`): one dictionary over the same layer of several snapshots;
|
|
82
|
+
each feature's decoder norm per snapshot says when it is there.
|
|
83
|
+
- **The demo bot**: a tiny network trained to imitate a scripted player, so everything runs without anyone's weights;
|
|
84
|
+
`cds-interpret demo` runs the whole tour and `cds-interpret doctor` says what is ready. A complete RLBot v5 bot
|
|
85
|
+
folder for it in `examples/rlbot_demo_bot`.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Contributing to cds-interpret
|
|
2
|
+
|
|
3
|
+
Thank you for wanting to make it better. New techniques, new labels, new recorders, fixes, docs and examples are all
|
|
4
|
+
welcome. This page says how the code is laid out, where new things slot in, and what a change needs before it is
|
|
5
|
+
merged.
|
|
6
|
+
|
|
7
|
+
## Set up
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/adventure-gpt/cds-interpret
|
|
11
|
+
cd cds-interpret
|
|
12
|
+
python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
13
|
+
pip install torch --index-url https://download.pytorch.org/whl/cpu # a CPU build is all the tests need
|
|
14
|
+
pip install -e ".[sim,rlgym,rlbot]" pytest ruff mypy # rlgym needs Python 3.11-3.12
|
|
15
|
+
pytest # about two minutes on a laptop CPU
|
|
16
|
+
ruff check src tests scripts examples
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The tests that need RocketSim's collision meshes or RLBot skip themselves when those are missing; CI runs them on
|
|
20
|
+
Python 3.12 with every extra installed.
|
|
21
|
+
|
|
22
|
+
## How the package is laid out
|
|
23
|
+
|
|
24
|
+
One module per technique, each usable on its own with plain arrays and tensors; `Study` ties them together.
|
|
25
|
+
|
|
26
|
+
| module | what it is |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `frames.py` | `Frames`, the one game-state format, and its adapters (RLGym, RLBot, arrays) |
|
|
29
|
+
| `labels.py` | concept labels from game state, future labels, and the label registry |
|
|
30
|
+
| `policy.py` | `Policy` (bring your own network), action tables, `eager_copy` |
|
|
31
|
+
| `hooks.py` | `LayerTap` and friends: reading and editing layers through forward hooks |
|
|
32
|
+
| `moments.py`, `store.py` | recorded moments and the column store under them |
|
|
33
|
+
| `record/` | one module per source: `sim.py` (RocketSim), `rlbot.py` (the real game), `rlgym_env.py`, `scripted.py` |
|
|
34
|
+
| `probes.py` | linear probes, held-out metrics, steadiness |
|
|
35
|
+
| `sae.py` | top-k sparse autoencoders |
|
|
36
|
+
| `intervene.py` | edits and their effect on the policy |
|
|
37
|
+
| `analysis.py` | features against labels, top moments, causal target selection |
|
|
38
|
+
| `names.py` | suggested feature names, the names file |
|
|
39
|
+
| `behavior.py` | habit counts from game state alone |
|
|
40
|
+
| `tracking.py` | probes across training snapshots |
|
|
41
|
+
| `emergence.py` | habits, dispositions and layer health, snapshot after snapshot |
|
|
42
|
+
| `curriculum.py` | situations, outcomes and enrichment: what to practise next |
|
|
43
|
+
| `study.py` | `Study`, `ProbeResults`, `FeatureSet`: the high-level flow |
|
|
44
|
+
| `report.py` | the HTML report and its section registry |
|
|
45
|
+
| `viz/` | dependency-free SVG charts, field drawings, the feature gallery |
|
|
46
|
+
| `overlay/` | the live thoughts overlay: `pack.py` (what is read), `panel.py` (how it is drawn, and its TOML config), `worker.py`, `bot.py` |
|
|
47
|
+
| `demo/` | the demo bot and the tour |
|
|
48
|
+
| `_rlbot.py` | what the RLBot recorder and the overlay share |
|
|
49
|
+
|
|
50
|
+
## Where new things slot in
|
|
51
|
+
|
|
52
|
+
- **A new technique** (say, attribution or a new kind of probe): a new module next to `probes.py` / `sae.py` that
|
|
53
|
+
works on arrays and tensors and knows nothing of `Study`. Then, if it belongs in the everyday flow, a small
|
|
54
|
+
`Study` method that calls it on `self.activations(layer)`, `self.labels`, `self.train` / `self.test`, and a report
|
|
55
|
+
section:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from cds_interpret.report import section
|
|
59
|
+
|
|
60
|
+
@section("Attributions", order=35) # built-in sections: 0, 10, 20, 30, 40, 50, 90
|
|
61
|
+
def _attributions(study):
|
|
62
|
+
res = getattr(study, "attribution_results", None)
|
|
63
|
+
return "" if res is None else render(res) # return "" to leave the section out
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- **A new label**: `labels.register_label("name", kind="bin" | "reg", doc="...")` on a function of a `LabelInput`
|
|
67
|
+
(frames, the car of each moment, team-frame positions, the ball's path, the built-in labels). A label that every
|
|
68
|
+
bot needs belongs in `concept_labels` itself, with a line in the module docstring's table, `LABEL_KIND` and
|
|
69
|
+
`LABEL_DOC`, and a test with a hand-made moment.
|
|
70
|
+
- **A new recorder** (another simulator, replays): a module in `record/` that fills a
|
|
71
|
+
`record._builder.Recording` - `add_step` for every decision step (all cars, with events), `add_moment` for the
|
|
72
|
+
moments the bot decided at - and returns `recording.finish()`. Labels and future labels then come for free.
|
|
73
|
+
- **A new edit**: a function in `intervene.py` returning `edit(x) -> x'`; `edit_effect` and `editing` work with it
|
|
74
|
+
unchanged.
|
|
75
|
+
- **The overlay**: what is read lives in the pack (`overlay/pack.py`); how it is drawn in `overlay/panel.py`. A new
|
|
76
|
+
kind of panel row is a branch in `Panel._row`, a name in `ROW_KINDS`, a line in `panel_example.toml` and a row in
|
|
77
|
+
`docs/howto/customize-the-panel.md`. Keep the rules of `overlay/bot.py`: read-only hooks, the work after the
|
|
78
|
+
controls are sent, nothing that can block the bot.
|
|
79
|
+
|
|
80
|
+
## What a change needs
|
|
81
|
+
|
|
82
|
+
- **Tests** for the new behaviour, on tiny hand-made inputs where possible (`tests/conftest.py` has helpers). A
|
|
83
|
+
read-only hook must leave a network's outputs bit for bit the same - test it when you add one.
|
|
84
|
+
- **Type hints** on public functions, and a docstring that says what goes in and what comes out (shapes in
|
|
85
|
+
brackets: `[N, D]`).
|
|
86
|
+
- **Friendly errors**: raise `CDSInterpretError` (or `ShapeError`, `LayerNotFound`, `MissingDependency`) with a
|
|
87
|
+
message in plain words that says what went wrong and what to do, like the docs; import optional packages through
|
|
88
|
+
`errors.require`.
|
|
89
|
+
- **Friendly docs**: lead with what the reader gets, then a snippet that runs and the output it prints, then the
|
|
90
|
+
explanation. Plain words and short sentences; explain a term the first time it appears.
|
|
91
|
+
- **Safe defaults**: CPU, small threads, nothing written outside the paths a user gives, no pickled code in files
|
|
92
|
+
meant to be shared (`torch.load(..., weights_only=True)`, `np.load(..., allow_pickle=False)`).
|
|
93
|
+
- **Docs**: the how-to that covers it, `docs/api.md`, and a line in `CHANGELOG.md` under "not yet released".
|
|
94
|
+
- `ruff check` clean, `pytest` green.
|
|
95
|
+
- Nothing from other people's bots: no other authors' code, weights, ports or replays, and no machine-specific paths
|
|
96
|
+
or personal data in code, tests, docs or commit messages.
|
|
97
|
+
|
|
98
|
+
## Working on the same branch as others
|
|
99
|
+
|
|
100
|
+
Several people may be porting improvements at the same time. Pull before you push
|
|
101
|
+
(`git pull --rebase`), keep commits small and about one thing, and say in the message what changed and why.
|
|
102
|
+
|
|
103
|
+
## Releasing (maintainers)
|
|
104
|
+
|
|
105
|
+
1. Move the "not yet released" section of `CHANGELOG.md` under the new version and date; set
|
|
106
|
+
`src/cds_interpret/_version.py`.
|
|
107
|
+
2. `python -m build` and check the wheel installs in a clean environment (`pip install dist/*.whl`;
|
|
108
|
+
`cds-interpret demo`).
|
|
109
|
+
3. Tag `vX.Y.Z` and push the tag.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 adventure-gpt
|
|
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,194 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: cds-interpret
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Look inside any PyTorch Rocket League bot: concept labels, robust probes, sparse-autoencoder features, causal tests and a live in-game thoughts overlay
|
|
5
|
+
Project-URL: Homepage, https://github.com/adventure-gpt/cds-interpret
|
|
6
|
+
Project-URL: Documentation, https://github.com/adventure-gpt/cds-interpret/tree/main/docs
|
|
7
|
+
Project-URL: Changelog, https://github.com/adventure-gpt/cds-interpret/blob/main/CHANGELOG.md
|
|
8
|
+
Project-URL: Issues, https://github.com/adventure-gpt/cds-interpret/issues
|
|
9
|
+
Author: adventure-gpt
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
License-File: THIRD_PARTY.md
|
|
13
|
+
Keywords: interpretability,mechanistic-interpretability,probing,pytorch,reinforcement-learning,rlbot,rlgym,rocket-league,rocketsim,sparse-autoencoder
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Requires-Dist: numpy>=1.24
|
|
26
|
+
Requires-Dist: torch>=2.1
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: rlbot>=2.0.0b54; extra == 'all'
|
|
29
|
+
Requires-Dist: rlgym-api>=2.0; (python_version < '3.13') and extra == 'all'
|
|
30
|
+
Requires-Dist: rlgym-rocket-league[sim]>=2.0; (python_version < '3.13') and extra == 'all'
|
|
31
|
+
Requires-Dist: rocketsim>=2.1; extra == 'all'
|
|
32
|
+
Provides-Extra: rlbot
|
|
33
|
+
Requires-Dist: rlbot>=2.0.0b54; extra == 'rlbot'
|
|
34
|
+
Provides-Extra: rlgym
|
|
35
|
+
Requires-Dist: rlgym-api>=2.0; (python_version < '3.13') and extra == 'rlgym'
|
|
36
|
+
Requires-Dist: rlgym-rocket-league[sim]>=2.0; (python_version < '3.13') and extra == 'rlgym'
|
|
37
|
+
Provides-Extra: sim
|
|
38
|
+
Requires-Dist: rocketsim>=2.1; extra == 'sim'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
<img src="assets/banner.png" alt="Cat Distribution System - with an interpretability toolkit" width="100%">
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
# CDS-interpret
|
|
46
|
+
|
|
47
|
+
**See what your Rocket League bot is thinking.**
|
|
48
|
+
|
|
49
|
+
Your bot's brain is a neural network: thousands of numbers that somehow turn into saves, shots and demos. CDS-interpret
|
|
50
|
+
lets you look inside it. You can ask it questions ("does it know the ball is about to go in my goal?"), find the ideas
|
|
51
|
+
it has learned on its own, switch one off to see what changes - and watch all of it live, on screen, while it plays.
|
|
52
|
+
|
|
53
|
+
<p align="center">
|
|
54
|
+
<img src="assets/overlay-panel.svg" alt="The thoughts panel: outlook, next move, what it is noticing, and a few readings" width="300">
|
|
55
|
+
<br><sub>The thoughts panel, drawn in the corner of the screen during a match. (Shown here outside the game.)</sub>
|
|
56
|
+
</p>
|
|
57
|
+
|
|
58
|
+
CDS-interpret is the interpretability toolkit from the Cat Distribution System (CDS), published on its own while the
|
|
59
|
+
bigger CDS framework is still being finished. It works with **any bot whose brain is a PyTorch network** - one trained
|
|
60
|
+
with RLGym (the Python toolkit most Rocket League bots are trained with), rlgym-ppo, a C++ trainer whose network you
|
|
61
|
+
can load into PyTorch, or your own code - and shows its thoughts live in RLBot, the framework that runs bots in the
|
|
62
|
+
real game. It runs on an ordinary CPU; no GPU needed.
|
|
63
|
+
|
|
64
|
+
## Try it in five minutes
|
|
65
|
+
|
|
66
|
+
You need Python 3.11 or newer. The first install also downloads PyTorch, which takes a while; the five minutes start
|
|
67
|
+
after that.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python -m venv .venv
|
|
71
|
+
.venv\Scripts\activate # on macOS / Linux: source .venv/bin/activate
|
|
72
|
+
pip install "cds-interpret[rlgym,rlbot] @ git+https://github.com/adventure-gpt/cds-interpret"
|
|
73
|
+
cds-interpret demo
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
(On Linux, pip picks PyTorch's GPU build, several GB. For the small CPU build, run
|
|
77
|
+
`pip install torch --index-url https://download.pytorch.org/whl/cpu` before the line above.)
|
|
78
|
+
|
|
79
|
+
The demo takes a tiny built-in bot, records a few games of it in RocketSim (a fast Rocket League simulator), and
|
|
80
|
+
looks inside it. In a few minutes you'll see something like this:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
Step 2 of 4 - asking every layer questions about the game (probes)
|
|
84
|
+
concept layer score input random measure steady
|
|
85
|
+
Worked out by the network (at least 0.05 better than both):
|
|
86
|
+
ball_dist (distance to the ball) body.1 0.89 -0.04 0.50 R2 yes
|
|
87
|
+
...
|
|
88
|
+
Step 4 of 4 - switching ideas off to see whether the bot uses them (edits)
|
|
89
|
+
'goal_side' probe direction removed at body.3: the bot's choice changes on 15% of moments (KL 0.125)
|
|
90
|
+
a random direction removed at body.3 (the control; 3 tries): the bot's choice changes on 10% of moments (KL 0.022)
|
|
91
|
+
...
|
|
92
|
+
All done. The full picture - every probe, the features with their moments drawn on the field, the edits - is in
|
|
93
|
+
cds-demo\report.html
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
How to read it: each row asks the bot one question, here "how far away is the ball?". **score** is how well its best
|
|
97
|
+
layer answers, on games it never learned from (for a number that's R2: 0 is a guess, 1 perfect; for a yes / no
|
|
98
|
+
question, AUROC: 0.5 is a guess, 1 perfect). **input** and **random** ask the same question of the bot's raw input and
|
|
99
|
+
of a copy of the network with random weights - so 0.89 against -0.04 and 0.50 means the network worked the distance
|
|
100
|
+
out for itself. In step 4, **KL** measures how far the bot's choices moved when an idea was switched off (0 is not at
|
|
101
|
+
all): removing the "goal side" direction moves them about six times as much as removing a random one.
|
|
102
|
+
|
|
103
|
+
Open `cds-demo/report.html` in your browser. It shows what the bot knows, the ideas it uses, and moments from its games
|
|
104
|
+
drawn from above.
|
|
105
|
+
|
|
106
|
+
On Python 3.13, leave out `rlgym` (`pip install "cds-interpret[rlbot] @ git+..."`): RLGym doesn't support 3.13 yet,
|
|
107
|
+
so the demo uses random game moments instead of recorded games. Everything else works.
|
|
108
|
+
|
|
109
|
+
## Then on your own bot
|
|
110
|
+
|
|
111
|
+
Tell the toolkit three things about your bot: its network, how it builds its input from the game, and its list of
|
|
112
|
+
actions.
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import cds_interpret as ci
|
|
116
|
+
|
|
117
|
+
policy = ci.Policy(
|
|
118
|
+
my_network, # your torch.nn.Module
|
|
119
|
+
obs=my_obs, # my_obs(frames, me): your bot's input, built from the game state
|
|
120
|
+
actions=ci.lookup_table(), # the controls behind each action number (or your bot's own table)
|
|
121
|
+
)
|
|
122
|
+
moments = ci.record.rocketsim(policy, games=20, seconds=120) # watch it play 20 games
|
|
123
|
+
study = ci.Study(policy, moments)
|
|
124
|
+
print(study.probes().summary()) # what each layer knows
|
|
125
|
+
study.report("my-bot.html") # everything, on one page
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Don't want to write `my_obs`? Record your bot in the real game instead; the recorder keeps the exact inputs your
|
|
129
|
+
network saw. The [quickstart](docs/quickstart.md) walks through both ways, step by step.
|
|
130
|
+
|
|
131
|
+
## What you can do with it
|
|
132
|
+
|
|
133
|
+
- **Ask your bot questions.** A *probe* is a small readout that asks the network one question, like "will the ball
|
|
134
|
+
land near me?" or "am I first to the ball?". The toolkit asks dozens of them at every layer, scores the answers on
|
|
135
|
+
games it never trained on, and asks the same of the bot's raw input and of a random copy of the network - so you
|
|
136
|
+
learn what the network *worked out*, not what was already in its input.
|
|
137
|
+
- **Find the ideas it uses.** A *sparse autoencoder* is a tool that finds the separate ideas a network uses - one for
|
|
138
|
+
"lined up for a shot", another for "about to lose the ball". The toolkit suggests a name for each idea from the
|
|
139
|
+
game, draws its strongest moments on the field, and keeps your confirmed names in a small names file.
|
|
140
|
+
[Name your bot's features](docs/howto/name-features.md).
|
|
141
|
+
- **Check that it really uses them.** Switch an idea off, or turn it up, and see what the bot does differently - on
|
|
142
|
+
recorded moments, or over whole games with a proper error bar.
|
|
143
|
+
- **Watch it think, live.** Wrap your RLBot bot in one line and its thoughts appear on screen while it plays: its
|
|
144
|
+
outlook, its next move and how sure it is, what it is noticing, where it thinks the ball will land. It reads your
|
|
145
|
+
network without changing it, so your bot plays exactly the same.
|
|
146
|
+
- **Design your own panel.** Pick the rows, names, colours, size and position in a small TOML file, or draw your own
|
|
147
|
+
rows in Python. [Customize the panel](docs/howto/customize-the-panel.md).
|
|
148
|
+
- **Record games three ways.** In RocketSim against itself or a scripted opponent, in the real game through RLBot, or
|
|
149
|
+
in your own RLGym environment.
|
|
150
|
+
- **See what a decision rests on.** Was it the ball, its own car or the opponent? Which of its ideas tipped it?
|
|
151
|
+
Shapley values - a fair way of splitting credit between things that act together - say, with a score for how far
|
|
152
|
+
to trust the answer.
|
|
153
|
+
[See what a decision rests on](docs/howto/what-decisions-rest-on.md).
|
|
154
|
+
- **See what your bot learns between checkpoints.** What each new checkpoint picked up, in its habits and in its
|
|
155
|
+
choices on the same moments; how healthy its layers are; and which situations it should practise next.
|
|
156
|
+
[Follow a bot through training](docs/howto/track-training.md).
|
|
157
|
+
- **Check your tools.** Every technique has a quiet way to mislead; the toolkit measures each one - autoencoders
|
|
158
|
+
true to the bot's choices, features that a second run finds again, probes the bot really uses, and panel readings
|
|
159
|
+
whose 40% really means 40%.
|
|
160
|
+
[Check your tools](docs/howto/check-your-tools.md).
|
|
161
|
+
- **Share what you find.** Every study becomes one HTML page with charts and field drawings, light and dark.
|
|
162
|
+
|
|
163
|
+
## Documentation
|
|
164
|
+
|
|
165
|
+
| | |
|
|
166
|
+
|---|---|
|
|
167
|
+
| [Quickstart](docs/quickstart.md) | five minutes on the demo bot, then your own |
|
|
168
|
+
| [How it works](docs/concepts.md) | the ideas behind it, in plain words |
|
|
169
|
+
| [Bring your own bot](docs/howto/bring-your-own-policy.md) | wrapping any network: actor-critics, TorchScript, RLGym observations |
|
|
170
|
+
| [Record games](docs/howto/record-moments.md) | RocketSim, the real game, your RLGym env, your own data |
|
|
171
|
+
| [Ask questions with probes](docs/howto/probes.md) | probing layers, and probes steady enough to show live |
|
|
172
|
+
| [Find the ideas it uses](docs/howto/sae-features.md) | sparse autoencoders and their features |
|
|
173
|
+
| [Name your bot's features](docs/howto/name-features.md) | from numbers to names you trust, end to end |
|
|
174
|
+
| [Test what it relies on](docs/howto/causal-tests.md) | switching ideas off and up, in moments and in games |
|
|
175
|
+
| [See what a decision rests on](docs/howto/what-decisions-rest-on.md) | the ball, its car, the opponents; and what each feature does |
|
|
176
|
+
| [Check your tools](docs/howto/check-your-tools.md) | how to tell when a technique is misleading you |
|
|
177
|
+
| [Watch it think in RLBot](docs/howto/overlay.md) | the live thoughts overlay |
|
|
178
|
+
| [Customize the panel](docs/howto/customize-the-panel.md) | every option of the panel's TOML file, and Python hooks |
|
|
179
|
+
| [Reports and drawings](docs/howto/figures.md) | the HTML page, its sections, the drawings |
|
|
180
|
+
| [See what it learns between checkpoints](docs/howto/track-training.md) | checkpoint after checkpoint, and what to practise next |
|
|
181
|
+
| [Labels](docs/labels.md) | every game-state fact the toolkit works out, and adding your own |
|
|
182
|
+
| [Coming from rlgym-ppo or GigaLearn](docs/coming-from.md) | where the things you know fit |
|
|
183
|
+
| [API reference](docs/api.md) | every function and class |
|
|
184
|
+
| [When something goes wrong](docs/troubleshooting.md) | error messages and what to do |
|
|
185
|
+
|
|
186
|
+
## Contributing
|
|
187
|
+
|
|
188
|
+
New techniques, labels, recorders, fixes and docs are all welcome. [CONTRIBUTING.md](CONTRIBUTING.md) explains where
|
|
189
|
+
new things slot in. Changes are listed in [CHANGELOG.md](CHANGELOG.md).
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT - see [LICENSE](LICENSE). The libraries it uses keep their own licenses: see [THIRD_PARTY.md](THIRD_PARTY.md).
|
|
194
|
+
Rocket League is a trademark of Psyonix. This project is not affiliated with Psyonix, Epic Games, RLBot or RLGym.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/banner.png" alt="Cat Distribution System - with an interpretability toolkit" width="100%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# CDS-interpret
|
|
6
|
+
|
|
7
|
+
**See what your Rocket League bot is thinking.**
|
|
8
|
+
|
|
9
|
+
Your bot's brain is a neural network: thousands of numbers that somehow turn into saves, shots and demos. CDS-interpret
|
|
10
|
+
lets you look inside it. You can ask it questions ("does it know the ball is about to go in my goal?"), find the ideas
|
|
11
|
+
it has learned on its own, switch one off to see what changes - and watch all of it live, on screen, while it plays.
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<img src="assets/overlay-panel.svg" alt="The thoughts panel: outlook, next move, what it is noticing, and a few readings" width="300">
|
|
15
|
+
<br><sub>The thoughts panel, drawn in the corner of the screen during a match. (Shown here outside the game.)</sub>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
CDS-interpret is the interpretability toolkit from the Cat Distribution System (CDS), published on its own while the
|
|
19
|
+
bigger CDS framework is still being finished. It works with **any bot whose brain is a PyTorch network** - one trained
|
|
20
|
+
with RLGym (the Python toolkit most Rocket League bots are trained with), rlgym-ppo, a C++ trainer whose network you
|
|
21
|
+
can load into PyTorch, or your own code - and shows its thoughts live in RLBot, the framework that runs bots in the
|
|
22
|
+
real game. It runs on an ordinary CPU; no GPU needed.
|
|
23
|
+
|
|
24
|
+
## Try it in five minutes
|
|
25
|
+
|
|
26
|
+
You need Python 3.11 or newer. The first install also downloads PyTorch, which takes a while; the five minutes start
|
|
27
|
+
after that.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
python -m venv .venv
|
|
31
|
+
.venv\Scripts\activate # on macOS / Linux: source .venv/bin/activate
|
|
32
|
+
pip install "cds-interpret[rlgym,rlbot] @ git+https://github.com/adventure-gpt/cds-interpret"
|
|
33
|
+
cds-interpret demo
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
(On Linux, pip picks PyTorch's GPU build, several GB. For the small CPU build, run
|
|
37
|
+
`pip install torch --index-url https://download.pytorch.org/whl/cpu` before the line above.)
|
|
38
|
+
|
|
39
|
+
The demo takes a tiny built-in bot, records a few games of it in RocketSim (a fast Rocket League simulator), and
|
|
40
|
+
looks inside it. In a few minutes you'll see something like this:
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
Step 2 of 4 - asking every layer questions about the game (probes)
|
|
44
|
+
concept layer score input random measure steady
|
|
45
|
+
Worked out by the network (at least 0.05 better than both):
|
|
46
|
+
ball_dist (distance to the ball) body.1 0.89 -0.04 0.50 R2 yes
|
|
47
|
+
...
|
|
48
|
+
Step 4 of 4 - switching ideas off to see whether the bot uses them (edits)
|
|
49
|
+
'goal_side' probe direction removed at body.3: the bot's choice changes on 15% of moments (KL 0.125)
|
|
50
|
+
a random direction removed at body.3 (the control; 3 tries): the bot's choice changes on 10% of moments (KL 0.022)
|
|
51
|
+
...
|
|
52
|
+
All done. The full picture - every probe, the features with their moments drawn on the field, the edits - is in
|
|
53
|
+
cds-demo\report.html
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
How to read it: each row asks the bot one question, here "how far away is the ball?". **score** is how well its best
|
|
57
|
+
layer answers, on games it never learned from (for a number that's R2: 0 is a guess, 1 perfect; for a yes / no
|
|
58
|
+
question, AUROC: 0.5 is a guess, 1 perfect). **input** and **random** ask the same question of the bot's raw input and
|
|
59
|
+
of a copy of the network with random weights - so 0.89 against -0.04 and 0.50 means the network worked the distance
|
|
60
|
+
out for itself. In step 4, **KL** measures how far the bot's choices moved when an idea was switched off (0 is not at
|
|
61
|
+
all): removing the "goal side" direction moves them about six times as much as removing a random one.
|
|
62
|
+
|
|
63
|
+
Open `cds-demo/report.html` in your browser. It shows what the bot knows, the ideas it uses, and moments from its games
|
|
64
|
+
drawn from above.
|
|
65
|
+
|
|
66
|
+
On Python 3.13, leave out `rlgym` (`pip install "cds-interpret[rlbot] @ git+..."`): RLGym doesn't support 3.13 yet,
|
|
67
|
+
so the demo uses random game moments instead of recorded games. Everything else works.
|
|
68
|
+
|
|
69
|
+
## Then on your own bot
|
|
70
|
+
|
|
71
|
+
Tell the toolkit three things about your bot: its network, how it builds its input from the game, and its list of
|
|
72
|
+
actions.
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import cds_interpret as ci
|
|
76
|
+
|
|
77
|
+
policy = ci.Policy(
|
|
78
|
+
my_network, # your torch.nn.Module
|
|
79
|
+
obs=my_obs, # my_obs(frames, me): your bot's input, built from the game state
|
|
80
|
+
actions=ci.lookup_table(), # the controls behind each action number (or your bot's own table)
|
|
81
|
+
)
|
|
82
|
+
moments = ci.record.rocketsim(policy, games=20, seconds=120) # watch it play 20 games
|
|
83
|
+
study = ci.Study(policy, moments)
|
|
84
|
+
print(study.probes().summary()) # what each layer knows
|
|
85
|
+
study.report("my-bot.html") # everything, on one page
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Don't want to write `my_obs`? Record your bot in the real game instead; the recorder keeps the exact inputs your
|
|
89
|
+
network saw. The [quickstart](docs/quickstart.md) walks through both ways, step by step.
|
|
90
|
+
|
|
91
|
+
## What you can do with it
|
|
92
|
+
|
|
93
|
+
- **Ask your bot questions.** A *probe* is a small readout that asks the network one question, like "will the ball
|
|
94
|
+
land near me?" or "am I first to the ball?". The toolkit asks dozens of them at every layer, scores the answers on
|
|
95
|
+
games it never trained on, and asks the same of the bot's raw input and of a random copy of the network - so you
|
|
96
|
+
learn what the network *worked out*, not what was already in its input.
|
|
97
|
+
- **Find the ideas it uses.** A *sparse autoencoder* is a tool that finds the separate ideas a network uses - one for
|
|
98
|
+
"lined up for a shot", another for "about to lose the ball". The toolkit suggests a name for each idea from the
|
|
99
|
+
game, draws its strongest moments on the field, and keeps your confirmed names in a small names file.
|
|
100
|
+
[Name your bot's features](docs/howto/name-features.md).
|
|
101
|
+
- **Check that it really uses them.** Switch an idea off, or turn it up, and see what the bot does differently - on
|
|
102
|
+
recorded moments, or over whole games with a proper error bar.
|
|
103
|
+
- **Watch it think, live.** Wrap your RLBot bot in one line and its thoughts appear on screen while it plays: its
|
|
104
|
+
outlook, its next move and how sure it is, what it is noticing, where it thinks the ball will land. It reads your
|
|
105
|
+
network without changing it, so your bot plays exactly the same.
|
|
106
|
+
- **Design your own panel.** Pick the rows, names, colours, size and position in a small TOML file, or draw your own
|
|
107
|
+
rows in Python. [Customize the panel](docs/howto/customize-the-panel.md).
|
|
108
|
+
- **Record games three ways.** In RocketSim against itself or a scripted opponent, in the real game through RLBot, or
|
|
109
|
+
in your own RLGym environment.
|
|
110
|
+
- **See what a decision rests on.** Was it the ball, its own car or the opponent? Which of its ideas tipped it?
|
|
111
|
+
Shapley values - a fair way of splitting credit between things that act together - say, with a score for how far
|
|
112
|
+
to trust the answer.
|
|
113
|
+
[See what a decision rests on](docs/howto/what-decisions-rest-on.md).
|
|
114
|
+
- **See what your bot learns between checkpoints.** What each new checkpoint picked up, in its habits and in its
|
|
115
|
+
choices on the same moments; how healthy its layers are; and which situations it should practise next.
|
|
116
|
+
[Follow a bot through training](docs/howto/track-training.md).
|
|
117
|
+
- **Check your tools.** Every technique has a quiet way to mislead; the toolkit measures each one - autoencoders
|
|
118
|
+
true to the bot's choices, features that a second run finds again, probes the bot really uses, and panel readings
|
|
119
|
+
whose 40% really means 40%.
|
|
120
|
+
[Check your tools](docs/howto/check-your-tools.md).
|
|
121
|
+
- **Share what you find.** Every study becomes one HTML page with charts and field drawings, light and dark.
|
|
122
|
+
|
|
123
|
+
## Documentation
|
|
124
|
+
|
|
125
|
+
| | |
|
|
126
|
+
|---|---|
|
|
127
|
+
| [Quickstart](docs/quickstart.md) | five minutes on the demo bot, then your own |
|
|
128
|
+
| [How it works](docs/concepts.md) | the ideas behind it, in plain words |
|
|
129
|
+
| [Bring your own bot](docs/howto/bring-your-own-policy.md) | wrapping any network: actor-critics, TorchScript, RLGym observations |
|
|
130
|
+
| [Record games](docs/howto/record-moments.md) | RocketSim, the real game, your RLGym env, your own data |
|
|
131
|
+
| [Ask questions with probes](docs/howto/probes.md) | probing layers, and probes steady enough to show live |
|
|
132
|
+
| [Find the ideas it uses](docs/howto/sae-features.md) | sparse autoencoders and their features |
|
|
133
|
+
| [Name your bot's features](docs/howto/name-features.md) | from numbers to names you trust, end to end |
|
|
134
|
+
| [Test what it relies on](docs/howto/causal-tests.md) | switching ideas off and up, in moments and in games |
|
|
135
|
+
| [See what a decision rests on](docs/howto/what-decisions-rest-on.md) | the ball, its car, the opponents; and what each feature does |
|
|
136
|
+
| [Check your tools](docs/howto/check-your-tools.md) | how to tell when a technique is misleading you |
|
|
137
|
+
| [Watch it think in RLBot](docs/howto/overlay.md) | the live thoughts overlay |
|
|
138
|
+
| [Customize the panel](docs/howto/customize-the-panel.md) | every option of the panel's TOML file, and Python hooks |
|
|
139
|
+
| [Reports and drawings](docs/howto/figures.md) | the HTML page, its sections, the drawings |
|
|
140
|
+
| [See what it learns between checkpoints](docs/howto/track-training.md) | checkpoint after checkpoint, and what to practise next |
|
|
141
|
+
| [Labels](docs/labels.md) | every game-state fact the toolkit works out, and adding your own |
|
|
142
|
+
| [Coming from rlgym-ppo or GigaLearn](docs/coming-from.md) | where the things you know fit |
|
|
143
|
+
| [API reference](docs/api.md) | every function and class |
|
|
144
|
+
| [When something goes wrong](docs/troubleshooting.md) | error messages and what to do |
|
|
145
|
+
|
|
146
|
+
## Contributing
|
|
147
|
+
|
|
148
|
+
New techniques, labels, recorders, fixes and docs are all welcome. [CONTRIBUTING.md](CONTRIBUTING.md) explains where
|
|
149
|
+
new things slot in. Changes are listed in [CHANGELOG.md](CHANGELOG.md).
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
MIT - see [LICENSE](LICENSE). The libraries it uses keep their own licenses: see [THIRD_PARTY.md](THIRD_PARTY.md).
|
|
154
|
+
Rocket League is a trademark of Psyonix. This project is not affiliated with Psyonix, Epic Games, RLBot or RLGym.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Third-party software and notices
|
|
2
|
+
|
|
3
|
+
cds-interpret's own code, documentation and demo weights are under the MIT license (`LICENSE`, copyright
|
|
4
|
+
adventure-gpt). No third-party code is carried in this repository. The projects below are dependencies installed by
|
|
5
|
+
pip (or by you), each under its own license, and nothing of theirs is redistributed here.
|
|
6
|
+
|
|
7
|
+
## Dependencies
|
|
8
|
+
|
|
9
|
+
| project | license | used for | installed by |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| [PyTorch](https://pytorch.org) | BSD-3-Clause | networks, hooks, sparse autoencoders | always |
|
|
12
|
+
| [NumPy](https://numpy.org) | BSD-3-Clause | arrays, labels, probes | always |
|
|
13
|
+
| [RocketSim](https://github.com/ZealanL/RocketSim) (the `rocketsim` Python package) by ZealanL | MIT | recording games in a simulator | the `sim` extra |
|
|
14
|
+
| [RLGym](https://rlgym.org) (`rlgym-api`, `rlgym-rocket-league`) | Apache-2.0 | the RLGym v2 bridges and the RLGym recorder; its simulator package also ships RocketSim's collision meshes | the `rlgym` extra |
|
|
15
|
+
| [RLBot](https://rlbot.org) (`rlbot`, `rlbot_flatbuffers`) | MIT | the live thoughts overlay and recording in the real game | the `rlbot` extra |
|
|
16
|
+
|
|
17
|
+
Development only: [pytest](https://pytest.org) (MIT), [Ruff](https://docs.astral.sh/ruff/) (MIT),
|
|
18
|
+
[mypy](https://mypy-lang.org) (MIT), [Hatchling](https://hatch.pypa.io) (MIT).
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
|
|
22
|
+
- **Collision meshes.** RocketSim needs Rocket League's arena collision meshes. They are game assets: this
|
|
23
|
+
repository does not carry them. Use the copy your own install of `rlgym-rocket-league` brings, or dump them from
|
|
24
|
+
your own copy of the game.
|
|
25
|
+
- **Fair play.** RocketSim's author asks that it be used for machine learning and hobby projects that respect
|
|
26
|
+
Rocket League's terms of use, never to sell a playable clone, and never to cheat in online matches. The same goes
|
|
27
|
+
for anything built with this toolkit.
|
|
28
|
+
- **The action table.** `cds_interpret.lookup_table()` builds a discrete action table in the layout that is common
|
|
29
|
+
across Rocket League bots; it is this project's own code. A bot trained with another table should pass that table.
|
|
30
|
+
- **The demo bot.** Its network (`src/cds_interpret/demo/demo_policy.pt`) was trained by this project's
|
|
31
|
+
`scripts/train_demo_policy.py` to imitate this project's scripted player; it contains no other bot's weights.
|
|
32
|
+
- Rocket League is a trademark of Psyonix, LLC. This project is not affiliated with or endorsed by Psyonix, Epic
|
|
33
|
+
Games, RLBot or RLGym.
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="9 304 354 365" width="496" role="img" aria-label="The thoughts overlay's panel"><defs><linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#3b5a7a"/><stop offset="1" stop-color="#1d2b3a"/></linearGradient></defs><rect x="9" y="304" width="354" height="365" fill="url(#bg)" rx="10"/><g font-family="Consolas, Menlo, 'DejaVu Sans Mono', monospace"><rect x="23.0" y="317.5" width="326.4" height="337.1" fill="rgb(0,0,0)" fill-opacity="0.69"/><text x="34.6" y="343.2" font-size="20.4" text-anchor="start" fill="rgb(255,255,255)">DEMO BOT'S MIND</text><text x="34.6" y="375.1" font-size="17.0" text-anchor="start" fill="rgb(215,215,215)">Outlook</text><text x="337.9" y="375.1" font-size="17.0" text-anchor="end" fill="rgb(90,220,120)">good</text><rect x="34.6" y="389.3" width="303.4" height="9.7" fill="rgb(70,70,70)" fill-opacity="0.86"/><rect x="186.2" y="389.3" width="83.4" height="9.7" fill="rgb(90,220,120)" fill-opacity="1.00"/><rect x="184.7" y="386.1" width="3.1" height="16.2" fill="rgb(255,255,255)" fill-opacity="1.00"/><text x="34.6" y="426.1" font-size="17.0" text-anchor="start" fill="rgb(215,215,215)">Next move</text><text x="337.9" y="426.1" font-size="17.0" text-anchor="end" fill="rgb(255,255,255)">81%</text><text x="49.9" y="454.2" font-size="17.0" text-anchor="start" fill="rgb(255,255,255)">throttle, steer right, boost</text><text x="34.6" y="487.9" font-size="17.0" text-anchor="start" fill="rgb(215,215,215)">Noticing</text><text x="42.2" y="515.9" font-size="17.0" text-anchor="start" fill="rgb(255,196,64)">> lined up for a shot</text><text x="34.6" y="549.6" font-size="17.0" text-anchor="start" fill="rgb(215,215,215)">Threat on goal</text><text x="337.9" y="549.6" font-size="17.0" text-anchor="end" fill="rgb(255,255,255)">8%</text><rect x="34.6" y="563.9" width="303.4" height="9.7" fill="rgb(70,70,70)" fill-opacity="0.86"/><rect x="34.6" y="563.9" width="24.3" height="9.7" fill="rgb(240,90,80)" fill-opacity="1.00"/><text x="34.6" y="595.0" font-size="17.0" text-anchor="start" fill="rgb(215,215,215)">First to the ball</text><text x="337.9" y="595.0" font-size="17.0" text-anchor="end" fill="rgb(255,255,255)">74%</text><rect x="34.6" y="609.2" width="303.4" height="9.7" fill="rgb(70,70,70)" fill-opacity="0.86"/><rect x="34.6" y="609.2" width="224.5" height="9.7" fill="rgb(90,220,120)" fill-opacity="1.00"/><text x="34.6" y="640.3" font-size="17.0" text-anchor="start" fill="rgb(215,215,215)">Time to the ball</text><text x="337.9" y="640.3" font-size="17.0" text-anchor="end" fill="rgb(255,255,255)">0.9 s</text></g></svg>
|