Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
580 commits
Select commit Hold shift + click to select a range
400a2bc
Add overfit training utility
mooskagh Oct 3, 2025
2a3d6ea
Fix overfit step logging for JAX arrays
mooskagh Oct 3, 2025
91ddabd
Merge pull request #10 from mooskagh/codex/2025-10-03-15-50-59
mooskagh Oct 3, 2025
7e89ce5
Add coin flip overfit mode and stream CSV results
mooskagh Oct 4, 2025
ef8e970
Merge pull request #11 from mooskagh/codex/2025-10-04-06-20-05
mooskagh Oct 4, 2025
312d98f
Do not forward chunks that failed rescoring.
mooskagh Oct 4, 2025
a4b54f5
Merge branch 'master' of github.com:mooskagh/lczero-training
mooskagh Oct 4, 2025
33c464c
Log chunk metadata on rescore failure
mooskagh Oct 4, 2025
68afe10
Merge pull request #12 from mooskagh/codex/2025-10-04-10-54-21
mooskagh Oct 4, 2025
1ffd4dc
Add debug chunk source for synthetic training data
mooskagh Oct 4, 2025
8b8efbf
Merge pull request #13 from mooskagh/codex/2025-10-04-11-05-02
mooskagh Oct 4, 2025
0c7c74c
Add tool to dump V6 chunk files
mooskagh Oct 4, 2025
d3d8349
Merge pull request #14 from mooskagh/codex/2025-10-04-13-04-05
mooskagh Oct 4, 2025
018d411
Wire max_grad_norm into daemon optimizer
mooskagh Oct 4, 2025
6777bf7
Different seed every time.
mooskagh Oct 6, 2025
64c802c
Tool for startpos stats.
mooskagh Oct 6, 2025
0aa468c
Add tests for shuffling chunk pool metrics
mooskagh Oct 6, 2025
3d24e8b
Merge pull request #17 from mooskagh/codex/2025-10-06-20-14-16
mooskagh Oct 6, 2025
1af1d89
Merge branch 'master' of github.com:mooskagh/lczero-training
mooskagh Oct 6, 2025
c448cdb
Fixing what codex did..
mooskagh Oct 6, 2025
d93bd90
Way to debug batches.
mooskagh Oct 6, 2025
daf6e30
More tools
mooskagh Oct 8, 2025
ee82296
Fix deepnorm initializer
mooskagh Oct 9, 2025
a4f042d
Passing deepnorm_beta as parameter. Not sure whetehr better.
mooskagh Oct 9, 2025
8a57b6e
Merge pull request #20 from mooskagh/deepnorm
mooskagh Oct 9, 2025
37cbcb2
Allow shuffling pool startup with fewer chunks
mooskagh Oct 9, 2025
bb1bdfa
Fail shuffling pool startup without any chunks
mooskagh Oct 9, 2025
fccdd17
Merge pull request #21 from mooskagh/codex/2025-10-09-20-06-31
mooskagh Oct 9, 2025
8fc698a
Scale embedding plane 109 during conversions
mooskagh Oct 10, 2025
bcd0c8f
Also scale while converting tensors.
mooskagh Oct 10, 2025
20928f2
Merge pull request #22 from mooskagh/codex/2025-10-10-08-43-39
mooskagh Oct 10, 2025
a5a2578
Use flags for chunk rescoring configuration
mooskagh Oct 10, 2025
3aec2b0
Merge pull request #23 from mooskagh/codex/2025-10-10-19-47-59
mooskagh Oct 10, 2025
a519aff
Add checkpoint migration tool
mooskagh Oct 12, 2025
a16cd7d
Exclude biases and LayerNorm from NadamW decay
mooskagh Oct 9, 2025
b82c429
Configurable weights decay.
mooskagh Oct 9, 2025
cef5223
Statediff was useless.
mooskagh Oct 12, 2025
9cd9429
Merge pull request #19 from mooskagh/codex/2025-10-09-16-39-05
mooskagh Oct 12, 2025
4cbf7bc
Downgrade JAX. Flip default flag
mooskagh Oct 12, 2025
6a5b527
result_distribution
mooskagh Oct 12, 2025
cbf341f
swap planes
mooskagh Oct 13, 2025
fee81fe
Eval tool to compare with ONNX
mooskagh Oct 14, 2025
9e3eb85
Bugfix
mooskagh Oct 14, 2025
85db510
Scale plane 109 by 99
mooskagh Oct 14, 2025
291b8a2
Better position selection
mooskagh Oct 14, 2025
4560066
Put metrics into dict.
mooskagh Oct 15, 2025
2bc2d26
Output grad norm.
mooskagh Oct 15, 2025
b0bcbd5
tensorboard
mooskagh Oct 15, 2025
e1c7477
spec
mooskagh Oct 15, 2025
0c01df2
lr schedule support
mooskagh Oct 15, 2025
1149f1b
Create LR in training, not optimizer.
mooskagh Oct 16, 2025
3b708ef
Exprort LR to tensorboard.
mooskagh Oct 16, 2025
0d265b3
JITtable LR schedule
mooskagh Oct 16, 2025
5f218d8
Tune LR with warmup
mooskagh Oct 16, 2025
d1974d6
Small chunk pool shuffler refactoring
mooskagh Oct 16, 2025
7cef6f2
Hanse sampling
mooskagh Oct 16, 2025
78e1ab4
Support fixed position sampling in chunk unpacker
mooskagh Oct 17, 2025
169e8a9
Merge pull request #25 from mooskagh/codex/2025-10-17-05-29-30
mooskagh Oct 17, 2025
6000317
SWA
mooskagh Oct 17, 2025
a1d69aa
use non-validation loss in lr tuner
mooskagh Oct 18, 2025
bfcc32d
Remove useless flag.
mooskagh Oct 18, 2025
3839723
Merge branch 'master' into tool-separation
mooskagh Oct 18, 2025
7d6e0b4
Phase 1.
mooskagh Oct 18, 2025
6602086
phase 2
mooskagh Oct 18, 2025
e3b6de3
phase 3
mooskagh Oct 18, 2025
ef99da6
Phases 4..9
mooskagh Oct 18, 2025
82635b7
Phase 10
mooskagh Oct 18, 2025
88b469c
p 11
mooskagh Oct 18, 2025
b406951
phase 13
mooskagh Oct 18, 2025
97be016
Other way of running the deamon
mooskagh Oct 19, 2025
1bc0974
Clean up old way of running the scripts.
mooskagh Oct 20, 2025
e4ef4d9
Clean up codex-induced mess.
mooskagh Oct 25, 2025
6c2ba31
ChunkSourceView implementation
mooskagh Oct 25, 2025
018032a
Multuple outputs support.
mooskagh Oct 25, 2025
1fbf8ec
Remove Index() from the ChunkSource API
mooskagh Oct 25, 2025
aa191e6
Chunk source splitter stage.
mooskagh Oct 25, 2025
fbc6340
Add non-blocking Get to the queue class
mooskagh Oct 26, 2025
fd9a42c
Add non-blocking MaybeGetNext() method to DataLoader
mooskagh Oct 26, 2025
561f8bc
Metrics refactoring
mooskagh Oct 26, 2025
870eb73
Backfill metrics.
mooskagh Oct 26, 2025
eaede7d
Allos to specify overflow behaviour for tensor generator.
mooskagh Oct 26, 2025
82723e9
Share output for multiple metrics.
mooskagh Oct 26, 2025
6dbeb36
Share tensors for multiple metrics.
mooskagh Oct 26, 2025
370a2e8
Simple chunk shuffler.
mooskagh Oct 26, 2025
2b31afa
Remove chunk shuffler test while we don't have gmock
mooskagh Oct 26, 2025
0b9f590
import orbax before configuring logging
mooskagh Oct 26, 2025
0fdba68
Always apply migration.
mooskagh Oct 26, 2025
778e590
Sort steps
mooskagh Oct 26, 2025
2661503
Output config unification
mooskagh Oct 27, 2025
26534df
SimpleChunkShuffler → SimpleChunkExtractor
mooskagh Oct 28, 2025
e7f8fe2
WIP documentation.
mooskagh Oct 28, 2025
2b7fff8
Two-phase Stage initialization with SetStages()
mooskagh Oct 31, 2025
eb8a958
Display count metrics with rate and total in TUI
mooskagh Oct 31, 2025
ebc1648
Update example.
mooskagh Oct 31, 2025
b23f9b6
UI updates
mooskagh Oct 31, 2025
185282c
Don't show percentage
mooskagh Oct 31, 2025
5e4c2f0
SetStages → SetInputs
mooskagh Oct 31, 2025
f3e33c7
Wire up stages after creation.
mooskagh Oct 31, 2025
62448ae
Counters bug fix.
mooskagh Oct 31, 2025
08f78df
Implement join stage.
mooskagh Oct 31, 2025
a21c5b4
Cleanup
mooskagh Oct 31, 2025
43ef55f
Fix line buffering.
mooskagh Nov 1, 2025
4bae030
Support request cancellation in queues.
mooskagh Nov 1, 2025
f07836e
Make ThreadPool std::jthread based
mooskagh Nov 1, 2025
490458a
Migrate stop state to ThreadPool
mooskagh Nov 1, 2025
4de5ec6
Migrate remaining stages to ThreadPool
mooskagh Nov 1, 2025
16e816c
Additional fields for shuffler.
mooskagh Nov 1, 2025
ac6101c
Support caching in shuffling chunk pool
mooskagh Nov 2, 2025
8b5dfc9
Add optional prefetch output to ChunkUnpacker stage
mooskagh Nov 2, 2025
df33947
empty name is fine
mooskagh Nov 2, 2025
548286b
Add dataloader-viz visualization tool
mooskagh Nov 2, 2025
723720b
Left-align text in dataloader-viz nodes
mooskagh Nov 2, 2025
161c515
Use HTML labels for left-aligned text in nodes
mooskagh Nov 2, 2025
8c8c262
Add edge labels for named outputs in dataloader-viz
mooskagh Nov 2, 2025
2913b51
Add logging after initial scan in ShufflingChunkPool
mooskagh Nov 2, 2025
9a7db4f
tmp log
mooskagh Nov 2, 2025
1dc14db
log less
mooskagh Nov 2, 2025
043b276
Fix sentinel barrier in multithreaded ChunkSourceLoader
mooskagh Nov 2, 2025
f370a43
Introduce GaugeMetricProto and refactor metrics system
mooskagh Nov 2, 2025
15f3698
Log cleanup.
mooskagh Nov 2, 2025
bd3b0dd
visupd
mooskagh Nov 2, 2025
165e0f6
make descripe print vals
mooskagh Nov 2, 2025
777a992
Rename tools.
mooskagh Nov 2, 2025
f530fc8
Synchronize optimizer step count when loading from leela checkpoint.
mooskagh Nov 2, 2025
293fff4
Set TF_CPP_MIN_LOG_LEVEL=0 for daemon subprocess if not already set.
mooskagh Nov 2, 2025
56faf34
Fix multi-GPU training and refactor run() method
mooskagh Nov 2, 2025
bc0dd7d
Fix sharding spec arity mismatch for multi-GPU training
mooskagh Nov 2, 2025
e650f45
undo what claude did
mooskagh Nov 2, 2025
de89dd9
Work around Flax NNX bug with static_argnames + in_shardings
mooskagh Nov 2, 2025
a9cd9b0
ScaleByScheduleState also contains step number
mooskagh Nov 3, 2025
a8d2ca8
diff focus tool
mooskagh Nov 3, 2025
6013856
Replace num_records with position-weighted sampling in ShufflingChunk…
mooskagh Nov 3, 2025
087424a
Tools cleanup
mooskagh Nov 4, 2025
775d231
UI update
mooskagh Nov 4, 2025
e1753ea
Rename cap to tau
mooskagh Nov 4, 2025
16107f1
Store config in ChunkUnpacker instead of copying fields
mooskagh Nov 4, 2025
3ab9db3
diff focus
mooskagh Nov 4, 2025
6e2073b
Add default_weight to PositionSamplingConfig
mooskagh Nov 5, 2025
bbb11a1
Add gaviota_paths support to ChunkRescorer
mooskagh Nov 5, 2025
0e3fa48
Integrate Gaviota tablebase as a dependency
mooskagh Nov 5, 2025
ddfb52c
Wire up StatisticsRowWidget to display chunk weight statistics
mooskagh Nov 5, 2025
2ae2c46
styling
mooskagh Nov 5, 2025
ff9dd48
Gemini said this would fix the counting.
mooskagh Nov 7, 2025
51ef1c8
Fix protobuf version mismatch and other bugfixes
mooskagh Nov 16, 2025
54c309f
Refactor ChunkSource::GetChunkData to return typed vectors
mooskagh Nov 18, 2025
a9f731f
Support for V7TrainingData (no heads using data from it though)
mooskagh Nov 20, 2025
4df27eb
update lc0 dep
mooskagh Nov 21, 2025
6dce49a
Make it possible to control export filename
mooskagh Nov 21, 2025
3dcf91e
Named heads
mooskagh Nov 22, 2025
136252b
Support all named policy and value heads in leela_to_modelconfig
mooskagh Nov 22, 2025
9832edd
Support shared policy head embeddings
mooskagh Nov 22, 2025
1fd727c
convert multiple head in jax ←→ leela net, allow shared policy embedd…
mooskagh Nov 22, 2025
b647355
Refactor TensorTuple to TrainingTensors with named heads
mooskagh Nov 22, 2025
7cee1b0
Heads description.
mooskagh Nov 23, 2025
926f91f
Refactor loss functions to accept TrainingSample and move WDL conversion
mooskagh Nov 23, 2025
2e2e31d
Refactor loss functions to use head_name/metric_name and shared base …
mooskagh Nov 23, 2025
bd8701c
Add configurable ValueType for value and moves-left losses
mooskagh Nov 23, 2025
8541e16
PolicyLoss refactor
mooskagh Nov 23, 2025
2bc70b1
Update what heads do.
mooskagh Nov 24, 2025
c9cb1b2
Remove test-only rescore_fn parameter from ChunkRescorer.
mooskagh Nov 24, 2025
aaee4cb
Make value head return tuple for future multi-output support.
mooskagh Nov 25, 2025
679e47b
Pass all heads to loss functions
mooskagh Nov 27, 2025
08956f0
Add optional error output to value head.
mooskagh Nov 28, 2025
9ad773d
Add value error loss for training error prediction head.
mooskagh Nov 28, 2025
aa43024
Add optimistic policy weighting to training system.
mooskagh Nov 28, 2025
eaf7f10
Add error output support to value head conversion.
mooskagh Nov 28, 2025
f479c83
Add categorical head support to value head.
mooskagh Nov 29, 2025
050d76a
Add categorical loss function for value head.
mooskagh Nov 29, 2025
bf443b7
Rename proto loss config messages to remove "Weights".
mooskagh Nov 29, 2025
a1c0ca8
Correct initialization of shared state.
mooskagh Nov 29, 2025
636910d
jax2leela tool
mooskagh Nov 29, 2025
f57c63c
export shared policy layer properly
mooskagh Nov 29, 2025
39514dc
A bit of a doc.
mooskagh Nov 30, 2025
2f7ac85
Merge pull request #227 from mooskagh/ice_skate
mooskagh Dec 1, 2025
0800bda
Some more docs.
mooskagh Dec 7, 2025
0ba1026
Weight arithmetics tool, 100% vibe coded.
mooskagh Dec 11, 2025
b6e1adf
Tests update.
mooskagh Dec 12, 2025
04af190
rms metrics
mooskagh Dec 12, 2025
53650ac
Claude says everything works now.
mooskagh Dec 12, 2025
6bd3ce4
Allow missing required fields
mooskagh Dec 12, 2025
da7d9f2
Claude claims it fixed something.
mooskagh Dec 13, 2025
326a417
Add weight decay control for neural network heads.
mooskagh Dec 13, 2025
88171b6
CLaude says again that now it's fixed.
mooskagh Dec 13, 2025
2d4b703
Add checkpoint and SWA options to training init command
mooskagh Dec 22, 2025
87f81f6
Auto-detect checkpoint instead of --from-checkpoint flag
mooskagh Dec 22, 2025
269a17e
fix
mooskagh Dec 22, 2025
cf7ce39
Fix checkpoint overwrite and add ignore-config-mismatch
mooskagh Dec 22, 2025
a842234
Fix tune_lr.py
kayn1208 Dec 24, 2025
8454095
Merge remote-tracking branch 'upstream/master' into heads
mooskagh Jan 24, 2026
c435305
Merge pull request #26 from kayn1208/heads
mooskagh Jan 24, 2026
4b3230a
Revert "Fix tune_lr.py"
mooskagh Feb 3, 2026
8a12e4b
Merge pull request #27 from mooskagh/revert-26-heads
mooskagh Feb 3, 2026
e4a5ce7
Add L2 regularization support
mooskagh Feb 3, 2026
e2d7527
Add Nadam and SGD optimizer support
mooskagh Feb 3, 2026
4dbd4c6
Await async handlers directly instead of spawning tasks
mooskagh Feb 7, 2026
b954e02
Update Python deps and fix Flax 0.12 compatibility
mooskagh Feb 8, 2026
dbfaa58
Replace WeightsSelector bool fields with ordered glob rules
mooskagh Feb 19, 2026
0e33f34
Fix RegularizationLoss crash with Flax 0.12
mooskagh Feb 21, 2026
50f9772
Replace lax.switch with vectorized stack+index in LR schedule
mooskagh Feb 21, 2026
769a524
Re-shard jit_state to replicated before first train_step
mooskagh Feb 21, 2026
57e185d
Log and notify on daemon process exit in TUI
mooskagh Feb 21, 2026
6a97d5f
Merge pull request #231 from mooskagh/heads
mooskagh Feb 26, 2026
ccec55e
Fix --npz-output crash in lc0-test-dataloader
mooskagh Feb 27, 2026
eded384
Merge remote-tracking branch 'upstream/master' into heads
mooskagh Feb 27, 2026
a061c30
Add --io-dump option to TUI for raw daemon IO debugging
mooskagh Feb 28, 2026
5133650
Fix empty statistics_metrics accumulation in ShufflingChunkPool
mooskagh Feb 28, 2026
63c2156
Update minimal python version
mooskagh Mar 1, 2026
28cbfe5
Helper rebuild rule
mooskagh Mar 1, 2026
07b7165
include meson to project
mooskagh Mar 1, 2026
0a7404f
`jax_to_leela.py` — switch to NumPy
mooskagh Mar 1, 2026
c4d91f4
JIT `evaluate_batch` to eliminate repeated XLA compilations
mooskagh Mar 1, 2026
fb41cc1
JIT \`compute_rms\` to eliminate repeated XLA compilations
mooskagh Mar 1, 2026
33820d0
JIT \`update_swa\` to eliminate repeated XLA compilations
mooskagh Mar 1, 2026
ea35598
Fix `TypeError: unhashable type: 'ModelConfig'` in `_make_eval_jit`
mooskagh Mar 1, 2026
6a12a77
Add --memory-profile-dir option to lc0-daemon
mooskagh Mar 1, 2026
9e6639c
Add --daemon-flag passthrough to lc0-tui
mooskagh Mar 1, 2026
2b0944e
Cache graphdef to prevent repeated _eval_jit compilations
mooskagh Mar 1, 2026
2921023
Add datetime prefix to memory profile filenames
mooskagh Mar 1, 2026
0c8a44f
Donate jit_state buffers in training loop to reduce memory fragmentation
mooskagh Mar 2, 2026
76e3d9c
Use module-level jax.jit with static_argnums instead of manual cache
mooskagh Mar 7, 2026
b8da2dd
Revert "Use module-level jax.jit with static_argnums instead of manua…
mooskagh Mar 7, 2026
ac23c8b
Addressing review comments
mooskagh Mar 7, 2026
acb4c6b
Revert "Addressing review comments"
mooskagh Mar 7, 2026
6a3c193
Reapply "Use module-level jax.jit with static_argnums instead of manu…
mooskagh Mar 7, 2026
a15066b
Addressing review comments
mooskagh Mar 7, 2026
1e83626
Update jax and jaxlib to 0.9.1
mooskagh Mar 7, 2026
4ad434a
Merge pull request #232 from mooskagh/heads
mooskagh Mar 7, 2026
a03fc23
Merge remote-tracking branch 'upstream/master' into heads
mooskagh Mar 7, 2026
90be7e4
Fix JIT caching in metrics.py to avoid unhashable ModelConfig
mooskagh Mar 7, 2026
c74ecf2
Simplify _EvaluatingMetric: remove redundant per-instance JIT cache
mooskagh Mar 7, 2026
2cdcce0
Merge pull request #233 from mooskagh/heads
mooskagh Mar 8, 2026
779c1d0
Merge pull request #234 from mooskagh/fix-jit-hashability
mooskagh Mar 8, 2026
71ae329
Add freeze_selector to OptimizerConfig
mooskagh Mar 8, 2026
cfa757d
Add --weight_paths to describe and --dump_*_paths to migrate-checkpoint
mooskagh Mar 8, 2026
8cf0f4e
Merge pull request #235 from mooskagh/freeze
mooskagh Mar 9, 2026
3175301
Merge pull request #236 from mooskagh/migrate-dump
mooskagh Mar 9, 2026
892bddc
Fix freeze_selector: optax.masked passes through raw gradients for fr…
mooskagh Mar 13, 2026
36de7ac
Fix update_optimizer_step traversal through wrapper state types
mooskagh Mar 13, 2026
3eb91b4
Fix false positive in update_optimizer_step assertion
mooskagh Mar 13, 2026
1d274b1
Simplify update_optimizer_step validation
mooskagh Mar 13, 2026
5771095
Merge pull request #237 from mooskagh/fix-freeze-selector
mooskagh Mar 15, 2026
1e819fc
Export training_steps in network exports
mooskagh Mar 17, 2026
4775209
Move mutex to file source
john-sp Mar 15, 2026
beb94e2
Prefetch batch
john-sp Mar 16, 2026
c235eae
Merge pull request #238 from mooskagh/fix-export
mooskagh Mar 19, 2026
215d937
Address PR review
john-sp Mar 20, 2026
1be6b6c
Revert "Prefetch batch"
john-sp Mar 21, 2026
a60c7d2
Merge pull request #239 from john-sp/parallel-tar-fetch
mooskagh Mar 23, 2026
2ad10b7
Fix command in readme
maxencefrenette May 3, 2026
7a091bc
Merge pull request #240 from maxencefrenette/patch-1
john-sp Jul 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BasedOnStyle: Google
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,21 @@ venv.bak/

# protobuf stuff
tf/proto/
**/*_pb2.py
**/*_pb2.pyi

# Meson
builddir/
subprojects/

# LLM Agents
# Use AGENTS.md; symlink other files to it if needed.
.claude/
CLAUDE.local.md
.claude.json
CLAUDE.md
GEMINI.md

# IDE
.vscode/
.idea/
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "libs/lczero-common"]
path = libs/lczero-common
url = https://github.com/LeelaChessZero/lczero-common.git
[submodule "libs/lc0"]
path = libs/lc0
url = https://github.com/LeelaChessZero/lc0.git
59 changes: 59 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# AGENTS.md

This repository contains training script for the Leela Chess Zero project.
They are being rewritten.

* Old code is located in the `tf/` directory.
* New python code is located in the `src/` directory.
* New C++ code is located in the `csrc/` directory.

The old code is Python/TensorFlow-based, new code is Python/JAX-based with
modules written in C++, operating through pybind11.

The build system for C++ code is meson. During development, the project is built
in the `builddir/`.

## Testing and Building

* C++ tests use GTest framework
* Do not insert Sleeps in tests, it slows down presubmit. Instead use e.g.
absl::Notification, or std::future
* Tests are defined in `meson.build` with `test()` function
* When debugging, don't forget to build them before running `meson test` or
`builddir/test`
* Run tests: `meson test -C builddir/`
* Python tests use `pytest` framework
* Do not add custom main function, exception catching to report errors, any
"test passed" messages etc. Use `pytest` fixtures and assertions.
* Build: `meson compile -C builddir/` from build directory
* Format code: `just format`
* There is a commit hook that runs `just pre-commit`, which runs tests and
checks formatting. You may want to run it before attempting to commit.
* We use Google C++ style guide.
* That means 80 columns.
* That means comments should be in full sentences with periods in the end.
* When conditional or loop fits one line, it must be written as one line
without braces, for example:
`if (condition) return value;`
* Prefer `absl` to `std` (e.g. `absl::c_` algorithms, `absl::Mutex`,
`absl::StrCat`, etc.)
* We use `uv` for Python package and venv management, and to running the
application.
* Run TUI app: `uv run tui --config=<path_to_config>`

* Do not attempt to run TUI — it messes up the Agent interface and session has
to be killed. Ask me to check it for you manually instead.

* Do not commit unless explicitly asked.

## IMPORTANT

* NEVER add `# type: ignore` or other ways to mask/silence errors instead of
fixing them.
* Rely on protobuf default values. DO NOT write code like
`config.has_foo() ? config.foo() : default_value;`

## Documentation

* Documentation is in the `docs/` directory.
* The contents is in [The index](docs/index.md)
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,16 @@ The training pipeline will automatically restore from a previous model if it exi
## Supervised training

Generating trainingdata from pgn files is currently broken and has low priority, feel free to create a PR.

## Building 2025-08 version.

1. Make sure `uv` and `justfile` are installed (plus `meson` and other stuff, potentially `protoc`).
2. `git submodule update`
3. `uv venv` (!important! do this before running meson; otherwise meson will build module for wrong python)
4. `uv sync`
5. `CXX=clang++ CC=clang uv run meson setup build/release/ --buildtype=release --native-file=native.ini` (clang is optional, should build fine with default compiler)
6. `just build-proto`
7. `meson compile -C build/release/`
8. `ln -s -T ../../build/release/_lczero_training.cpython-311-x86_64-linux-gnu.so src/lczero_training/_lczero_training.so`

14. Run it! `uv run lc0-tui --config docs/example.textproto`
35 changes: 35 additions & 0 deletions csrc/loader/chunk_source/chunk_source.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include <cstddef>
#include <optional>
#include <string>
#include <vector>

#include "loader/frame_type.h"

namespace lczero {
namespace training {

// Interface for providing training data chunks.
// A chunk source provides access to one or more chunks of training data.
// It's assumed that all chunks in a source for one group for sorting purposes,
// therefore GetChunkSortKey() returns just one key for the entire source. This
// allows to know the key before reading/indexing the chunks.
class ChunkSource {
public:
virtual ~ChunkSource() = default;

// Returns a sort key (e.g. filename or a timestamp).
virtual std::string GetChunkSortKey() const = 0;

// Returns the number of chunks in this source.
virtual size_t GetChunkCount() const = 0;

// Returns the data for the chunk at the given index. Returns std::nullopt if
// the chunk could not be read or if the data size is not a multiple of the
// expected frame size.
virtual std::optional<std::vector<FrameType>> GetChunkData(size_t index) = 0;
};

} // namespace training
} // namespace lczero
47 changes: 47 additions & 0 deletions csrc/loader/chunk_source/chunk_source_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "loader/chunk_source/chunk_source.h"

namespace lczero {
namespace training {

// ChunkSourceView provides a view over another ChunkSource.
// It exposes a remapped subset/order of chunks defined by indices into the
// underlying source. It does not own or copy the data; it forwards calls to
// the wrapped source.
class ChunkSourceView : public ChunkSource {
public:
// Constructs a view over an existing chunk source. The indices vector maps
// local indices in the view to indices of the underlying source.
ChunkSourceView(std::shared_ptr<ChunkSource> source,
std::vector<uint32_t> indices)
: source_(std::move(source)), indices_(std::move(indices)) {}

~ChunkSourceView() override = default;

private:
std::string GetChunkSortKey() const override {
return source_->GetChunkSortKey();
}

size_t GetChunkCount() const override { return indices_.size(); }

std::optional<std::vector<FrameType>> GetChunkData(size_t index) override {
if (index >= indices_.size()) return std::nullopt;
const size_t src_index = static_cast<size_t>(indices_[index]);
return source_->GetChunkData(src_index);
}

std::shared_ptr<ChunkSource> source_;
std::vector<uint32_t> indices_;
};

} // namespace training
} // namespace lczero
57 changes: 57 additions & 0 deletions csrc/loader/chunk_source/debug_chunk_source.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "loader/chunk_source/debug_chunk_source.h"

#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <cstring>
#include <random>
#include <utility>

#include "absl/hash/hash.h"
#include "absl/strings/str_format.h"

namespace lczero {
namespace training {

DebugChunkSource::DebugChunkSource(uint64_t id, double mean_chunk_count)
: id_(id), mean_chunk_count_(mean_chunk_count) {}

std::string DebugChunkSource::GetChunkSortKey() const {
return absl::StrFormat("%08" PRIu64, id_);
}

size_t DebugChunkSource::GetChunkCount() const {
if (!cached_chunk_count_.has_value()) {
std::mt19937_64 rng(id_);
const double stddev = std::max(1.0, mean_chunk_count_ / 4.0);
std::normal_distribution<double> distribution(mean_chunk_count_, stddev);
const double sampled = distribution(rng);
const auto rounded =
static_cast<long long>(std::llround(std::max(sampled, 1.0)));
cached_chunk_count_ = static_cast<size_t>(rounded);
}
return *cached_chunk_count_;
}

std::optional<std::vector<FrameType>> DebugChunkSource::GetChunkData(
size_t index) {
const auto seed_pair = std::make_pair(id_, index);
const uint64_t seed = static_cast<uint64_t>(
absl::Hash<std::pair<uint64_t, size_t>>{}(seed_pair));
std::mt19937_64 rng(seed);
std::uniform_int_distribution<int> frame_count_distribution(1, 200);
const int frame_count = frame_count_distribution(rng);

std::vector<FrameType> result(frame_count);
for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
result[frame_index] = FrameType{};
result[frame_index].planes[0] = static_cast<uint64_t>(id_);
result[frame_index].planes[1] = static_cast<uint64_t>(index);
result[frame_index].planes[2] = static_cast<uint64_t>(frame_index);
}

return result;
}

} // namespace training
} // namespace lczero
41 changes: 41 additions & 0 deletions csrc/loader/chunk_source/debug_chunk_source.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include <cstddef>
#include <cstdint>
#include <optional>
#include <random>
#include <string>

#include "loader/chunk_source/chunk_source.h"

namespace lczero {
namespace training {

// DebugChunkSource synthesizes deterministic pseudo-random chunks for loader
// debugging. Each instance is identified by an integer id. The class produces
// a chunk count sampled from a normal distribution with the provided mean and
// mean / 4 standard deviation. The id serves as the seed, which keeps the
// number of chunks stable across runs. Individual chunks contain a
// pseudo-random number of FrameType frames (between one and 200) that are
// generated on demand. The generation seed depends on both the source id and
// chunk index. This lets shuffling logic exercise variable chunk sizes while
// keeping the content reproducible. Each generated frame is zero-initialized,
// but the first three entries of the planes array encode, respectively, the
// source id, the chunk index, and the frame index within the chunk. This makes
// it easy to reason about ordering and grouping when inspecting chunk payloads.
class DebugChunkSource : public ChunkSource {
public:
DebugChunkSource(uint64_t id, double mean_chunk_count);

private:
std::string GetChunkSortKey() const override;
size_t GetChunkCount() const override;
std::optional<std::vector<FrameType>> GetChunkData(size_t index) override;

uint64_t id_;
double mean_chunk_count_;
mutable std::optional<size_t> cached_chunk_count_;
};

} // namespace training
} // namespace lczero
59 changes: 59 additions & 0 deletions csrc/loader/chunk_source/rawfile_chunk_source.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "loader/chunk_source/rawfile_chunk_source.h"

#include <absl/log/log.h>

#include <fstream>
#include <stdexcept>

#include "trainingdata/trainingdata_v6.h"
#include "utils/files.h"
#include "utils/gz.h"

namespace lczero {
namespace training {

RawFileChunkSource::RawFileChunkSource(
const std::filesystem::path& filename,
ChunkSourceLoaderConfig::FrameFormat frame_format)
: filename_(filename), frame_format_(frame_format) {}

RawFileChunkSource::~RawFileChunkSource() = default;

std::string RawFileChunkSource::GetChunkSortKey() const {
return std::filesystem::path(filename_).filename().string();
}

size_t RawFileChunkSource::GetChunkCount() const { return 1; }

std::optional<std::vector<FrameType>> RawFileChunkSource::GetChunkData(
size_t index) {
if (index != 0) return std::nullopt;
std::string data = ReadFileToString(filename_);
if (data.empty()) return std::nullopt;

const size_t input_size =
frame_format_ == ChunkSourceLoaderConfig::V7TrainingData
? sizeof(V7TrainingData)
: sizeof(V6TrainingData);
if (data.size() % input_size != 0) {
LOG(WARNING) << "File " << filename_ << " size " << data.size()
<< " is not a multiple of input frame size " << input_size;
return std::nullopt;
}

const size_t num_frames = data.size() / input_size;
std::vector<V7TrainingData> result(num_frames);

if (frame_format_ == ChunkSourceLoaderConfig::V7TrainingData) {
std::memcpy(result.data(), data.data(), data.size());
} else {
const auto* v6_data = reinterpret_cast<const V6TrainingData*>(data.data());
for (size_t i = 0; i < num_frames; ++i) {
std::memcpy(&result[i], &v6_data[i], sizeof(V6TrainingData));
}
}
return result;
}

} // namespace training
} // namespace lczero
30 changes: 30 additions & 0 deletions csrc/loader/chunk_source/rawfile_chunk_source.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <filesystem>
#include <string>

#include "loader/chunk_source/chunk_source.h"
#include "proto/data_loader_config.pb.h"

namespace lczero {
namespace training {

// A chunk source that reads a single (potentially gzipped) file as a single
// chunk.
class RawFileChunkSource : public ChunkSource {
public:
RawFileChunkSource(const std::filesystem::path& filename,
ChunkSourceLoaderConfig::FrameFormat frame_format);
~RawFileChunkSource();

private:
std::string GetChunkSortKey() const override;
size_t GetChunkCount() const override;
std::optional<std::vector<FrameType>> GetChunkData(size_t index) override;

std::string filename_;
ChunkSourceLoaderConfig::FrameFormat frame_format_;
};

} // namespace training
} // namespace lczero
Loading