fly-ftl-extract
Drop-in replacement for ftl-extract 0.12.1 — the
same ftl extract <code> <locales>, with the same options and byte-for-byte the same output —
in which the decision "is this a Fluent key" is made not by a parser but by a simulated
fruit-fly mushroom body: LIF neurons on the real FlyWire FAFB v783 connectome (124 projection
neurons → 2597 Kenyon cells ⇄ 1 APL → 48 MBONs), a readout on the MBONs trained with
"dopamine" (delta rule). The tokenizer only proposes candidates (string literals and
attribute chains before () and encodes their context into an odour; the fly decides which
of them is a key and which kwarg is placeable. This is a joke — but a joke that is literally true.
Switch the fly off and no keys are found: the hot path has neither ast nor rules about
i18n.get; the test tests/test_no_ast_in_hot_path.py checks that a plain ftl extract
loads neither the AST reference nor the audit.
How it works
Python file ──tokenize──▶ candidate + window (6 tokens before · focus · 3 after)
│
▼ feature hashing → 14 puffs × 124 PN (rate coding, tanh)
┌─────────────────────────────────────────────────────────────────────┐
│ PN 124 ──ACh──▶ KC 2597 ──ACh──▶ MBON 48 mushroom body │
│ Poisson, LIF, τm 20 ms, LIF of FlyWire │
│ ≤ 200 Hz V_th −45 mV ▲ FAFB v783, │
│ │ ▲ │ right hemisphere │
│ ▼ │ GABA ×0.5 │ syn_count ≥ 5 │
│ APL 1 ───┘ │ │
│ (feedback inhibition, │ │
│ 8–10 % of KCs active per puff) │ │
│ │ │
│ DAN 165 — teaching signal only ───────────┘ (sim current = 0) │
└─────────────────────────────────────────────────────────────────────┘
│ KC spike counts per puff (14 × 2597)
▼
readout w · [KC spiked, log1p(spikes)] + b → margin
|margin| < θ → "sniff again" (up to 5 extra trials with other seeds), vote = Σ margin
margin > 0 → key / kwarg placeable
- Temporal coding. The window = 14 puffs of 40 ms with no silence between them + 10 ms of
silence (570 ms, 5700 steps of 0.1 ms): 6 puffs of context before the candidate, 5 puffs of
focus (
[root][attr1][attr2][attr3][summary]for a chain,[<STR>][silence×3][summary]for a string), 3 puffs after. The membrane is not reset between puffs — that is the memory of the preceding tokens. Every puff is a 124-PN vector: hashed slot features (normalised token, token + distance, type, bracket depth, bigram), 2 buckets per feature, ≈ 10 active PNs per puff. - Normalisation, not rules.
--i18n-keys,-p,--ignore-attributes,--ignore-kwargsaffect only the tokens (i18n→<I18N>,self→<PREFIX>,set_locale→<IGNORE>,when→<IGNORE_KW>), so-k LFsmells the same asi18n. The decision is the sign of the margin. - Resniff. θ is chosen on val so that ≤ 10 % of windows get extra sniffs; trial seed = sha256(file bytes, candidate index, encoder version) — two runs give the same output.
- Details: CLAUDE.md (the contract), docs/CONNECTOME.md (the subgraph), docs/BENCH.md (calibration, speed), docs/ODOR.md (the encoder), docs/METRICS.md (training), docs/FORMAT.md (what exactly the original does and what is reproduced).
Installation
Python 3.14 is required (requires-python = ">=3.14,<3.15"). From PyPI:
pip install fly-ftl-extract # into a 3.14 venv, or
uv tool install --python 3.14 fly-ftl-extract # as an isolated tool
The same wheel is attached to every GitHub release;
the repository itself installs too (uv build → dist/):
uv tool install --python 3.14 ./fly_ftl_extract-0.1.0-py3-none-any.whl
uv tool install --python 3.14 git+https://github.com/andrew000/FLY-FTL-Extract
The wheel contains the connectome (fly_ftl_extract/data/mb_fafb783.npz, 106 KB), its
metadata (meta.json) and the trained weights (mbon_weights.npz, 598 KB); runtime
dependencies are numpy, scipy, rich, click and fluent.syntax.
Entry-point conflict. The package installs the scripts ftl and fly-ftl. The original
ftl-extract also installs ftl; in one environment the last one installed wins, so do not
put both into one venv — keep them in separate uv tool environments or call ours as
fly-ftl.
Usage
Everything works as in the original 0.12.1 (the FTL-Extract README): ftl extract CODE_PATH LOCALES_PATH, -l/--language, -k/--i18n-keys, -K, -p/--i18n-keys-prefix, -e/-E,
-i/-I, --ignore-kwargs, --default-ftl-file, --comment-keys-mode {comment,warn},
--line-endings, --dry-run, --cache/--cache-path/--clear-cache,
--allow-parse-errors, -v, the global --config, the [tool.ftl-extract.extract] section
in pyproject.toml (CLI > pyproject > defaults), ftl config sample. Output, exit codes and
the .ftl tree match the Rust binary; after its ✅ Done line the block [INFO fly] Fly statistics: is appended (neurons, files, candidates, trials, resniffs, trials/s, brain time).
ftl extract app/bot app/bot/locales -l en -l uk # drop-in
ftl extract app locales --fly-audit # run the AST reference alongside, differences → stderr, exit 1
ftl extract app locales -v --fly-no-tui # the margin of every window after ✅ Done
Our options (all prefixed --fly-):
| option | what it does |
|---|---|
--fly-audit |
the AST reference (fly_ftl_extract.reference) runs alongside; every difference is a [WARN fly::audit] … line, exit 1 |
--fly-no-tui |
a plain log even in a terminal (without a tty the TUI switches itself off) |
--fly-workers N |
processes for the brain (spawn; default CPU−2, ≤ 16); below 128 windows always a single process |
--fly-batch N |
trials per brain call (256 in a single process, 64 in a worker, 16 under the TUI) |
--fly-trials N |
base trials per window before the resniff rule (the margins are summed) |
--fly-seed S |
a salt on every trial seed — "another nose"; 0 = the production seeds |
TUI
In a terminal ftl extract draws a live panel (rich, ≤ 15 fps): a spike raster of the
Kenyon cells (one dot = one cell that spiked in the trial's summary puff, one row = one
trial), the PN/KC/APL/MBON activity of the last trial, an event log (ODOR → MBON margin →
KEY / NOT A KEY / placeable, RESNIFF) and counters. All numbers are real — from the
connectome, the spikes and the readout; the TUI module never imports random.
Accuracy
Dataset grammar-5: 20 000 synthetic snippets labelled by the AST reference (460 672
candidates, 147 876 kwargs; split 80/10/10 by snippet). The golden fixtures from tests/ and
the real bot's code are not part of the dataset — they are the holdout.
| what | result | source |
|---|---|---|
| keys, test, with resniff (≤ 5 extra trials, 9.8 % of windows) | P 0.9987 · R 1.0000 (tp 11554, fp 15, fn 0, tn 34354) | METRICS.md §1 |
| keys, test, without resniff | P 0.9949 · R 0.9978 | same |
| kwargs (placeable / ignore), test | P 1.0000 · R 1.0000 | same |
| golden fixtures through the whole fly | 24 / 24 files match the reference | tests/test_judge_on_fixtures.py |
the real ftl 0.12.1 against ours on every fixture |
31 / 31 runs byte for byte (exit, stderr, tree), config sample too |
COMPARE.md |
| a real aiogram bot (280 files, 9 992 candidates, 538 keys) | 0 differences from the reference (--fly-audit); the fly trained on the previous corpus (grammar-4) had 13 on the same code (all of them L("…") in dict values, constructor fields and decorator arguments), 15 in the first run |
REAL_PROJECT.md — the honest before/after story |
the old weights (grammar-4) on the grammar-5 test |
keys R 0.870 (1503 misses) — the price of call positions that were not in the corpus | METRICS.md §8 |
Limitations
- One hemisphere (right: 2597 KCs vs 2580 in the left); the left one is not used.
- 15 GABAergic iPNs per side are excluded from the PNs (three have ≥ 5 synapses onto KCs and would break the rule "PN→KC only positive").
syn_scale = 5.0andapl_scale = 0.5are calibrated on our odours (8–10 % KCs per puff, APL inhibits ≥ 2×), not taken from Shiu et al.; the APL weight is scaled separately.- A 40 ms puff, not 20: at 20 ms the per-puff KC code was not reproducible (same-candidate Jaccard 0.34).
- Synapse threshold
syn_count ≥ 5per neuron pair; DANs carry no current in the forward simulation. - Speed ≈ 50 trials/s per process (one trial = 5700 LIF steps), 290–410 trials/s on 16 processes depending on machine load; a bot with ~10 000 candidates takes 24–34 s versus 0.02 s for the Rust original.
ftl stubandftl checkare not implemented (a message and exit 2).- The
--cachecache is written to the same file as in the original, but the format is ours and not compatible with the original. -vdoes not reproduce the original's debug lines (globset,Saved …); our margin lines are printed instead.i18n.get("dotted.key.name")and other invalid Fluent identifiers are written as is — the original does the same (the next run of either will fail reading the.ftl).- The fly makes mistakes. On the
grammar-5test split (with resniff) 15 false keys among 34 369 negatives and 0 misses among 11 554 positives; all 10 worst false keys areself.get("…")/cls.get("…")with-p self -p cls(margin up to +10.5; for the reference a prefix without an i18n name right after it is not a key). The fly learns only what is in the grammar: the first version (grammar-4) missed on the real bot everyL("…", _path=…)in dict values and in constructor fields (description=L(…)on the line after a recognisedname=L(…), margin −1…−31),LF("…")as the first argument of the decorator@router.message((−8…−32), and flagged a string inside a tuple,("captcha_timeout_task", …), with no call at all, as a key (+7.00). This was fixed not by adding rules to the code but by extending the corpus (grammar-5) with these positions and their negative twins: on the same bot it became 0 differences, and the same 13 windows give +5.7…+40.7 (REAL_PROJECT.md). The next unseen construct will likewise be a miss until it gets into the grammar.
Citations and licences
- Connectome: FlyWire FAFB v783, Zenodo 10676866, CC-BY 4.0. Dorkenwald S. et al. Neuronal wiring diagram of an adult brain. Nature 634, 124–138 (2024). Schlegel P. et al. Whole-brain annotation and multi-connectome cell typing of Drosophila. Nature 634, 139–152 (2024) — neuron annotations (flyconnectome/flywire_annotations).
- Neuron model and parameters: Shiu P. K. et al. A Drosophila computational brain model reveals sensorimotor processing. Nature 634, 210–219 (2024) (philshiu/Drosophila_brain_model).
- Inspiration (the mushroom body as a hash function): Dasgupta S., Stevens C. F., Navlakha S. A neural algorithm for a fundamental computing problem. Science 358, 793–796 (2017).
- Fluent: python-fluent (
fluent.syntax, Apache 2.0) — parser and serializer, byte-for-byte compatible with fluent-rs on every golden file. - The original: FTL-Extract © andrew000, MIT. The output format, key order (
FxHashMap), file walk and message texts are reproduced from the behaviour of the 0.12.1 binary. - This package is MIT. The data
fly_ftl_extract/data/mb_fafb783.npzis a derivative work of FlyWire (CC-BY 4.0).
How to reproduce
Everything is deterministic (the seeds are fixed); the times are from the author's machine (Ryzen 9 9950X3D, 32 threads) (train.py: 30 processes for the brain; the ftl extract pool: 16).
| step | command | what it does | time |
|---|---|---|---|
| 1 | download proofread_connections_783.feather (852 MB), proofread_root_ids_783.npy, Supplemental_file1_neuron_annotations.tsv into .cache/flywire/ |
raw FlyWire data | — |
| 2 | uv run --extra connectome python scripts/build_connectome.py |
the mushroom-body subgraph → data/mb_fafb783.npz + meta.json, docs/CONNECTOME.md |
≈ 4 s (the feather is read through a memory map in batches, only the needed columns); a repeated run gives byte-for-byte the same npz, only the build date changes in meta.json |
| 3 | uv run python scripts/make_dataset.py |
20 000 snippets of the grammar-5 grammar (14 grammar-4 mutation families + 10 call-position families), labelling by the AST reference, encoding → data/dataset/ |
12 s generation + 212 s labelling and encoding |
| 4 | uv run python scripts/train.py --lr 0.005 --epochs 100 --patience 10 --train-seeds 6 [--baseline-weights old.npz] |
the brain on every window (train × 6 seeds, val, test; state cache in .cache/brain_states/, ≈ 8 GB per corpus), delta rule, θ, fixtures → data/mbon_weights.npz, docs/METRICS.md |
12 260 s (3.4 h) without the state cache, 30 processes: brain keys 4466 s (2.3 M trials, ≈ 665 trials/s), kwargs 1310 s, readout keys 5506 s (86 epochs, early stopping), kwargs 223 s, fixtures 23 s; with the state cache — only the readout |
| 5 | uv run pytest -q |
297 tests (296 passed + 1 diagnostic xfail), among them golden through the fly and --fly-audit on the fixtures |
≈ 3 min |
| 6 | uv run python scripts/compare_with_reference.py |
the real ftl 0.12.1 (via uv tool run) against ours → docs/COMPARE.md |
≈ 45 s |
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fly_ftl_extract-0.1.0.tar.gz.
File metadata
- Download URL: fly_ftl_extract-0.1.0.tar.gz
- Upload date:
- Size: 857.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8dc8000eb0f468bce30e220d2eda2e6908101f946ae4047317fc7158e49945b4
|
|
| MD5 |
f76406d664d2df7ae9f399125b9240f8
|
|
| BLAKE2b-256 |
f2acd39ed42e7d328d3ff2708ca4e2eca08a543d4c7248c4969884fdac80054e
|
Provenance
The following attestation bundles were made for fly_ftl_extract-0.1.0.tar.gz:
Publisher:
pypi-release.yml on andrew000/FLY-FTL-Extract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fly_ftl_extract-0.1.0.tar.gz -
Subject digest:
8dc8000eb0f468bce30e220d2eda2e6908101f946ae4047317fc7158e49945b4 - Sigstore transparency entry: 2883818751
- Sigstore integration time:
-
Permalink:
andrew000/FLY-FTL-Extract@7d6942ce68a60efb4a2ce9a9b5d298f7d812da2b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/andrew000
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-release.yml@7d6942ce68a60efb4a2ce9a9b5d298f7d812da2b -
Trigger Event:
release
-
Statement type:
File details
Details for the file fly_ftl_extract-0.1.0-py3-none-any.whl.
File metadata
- Download URL: fly_ftl_extract-0.1.0-py3-none-any.whl
- Upload date:
- Size: 639.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5e5cb758388583c0661e6a0ca825d98cdd75b0c4210db1b3293067ea9e44e9e
|
|
| MD5 |
0c8aa69de30ef9a9af7e14e6d046abca
|
|
| BLAKE2b-256 |
404deb8e015cb240663a2598f283b879709b12f8a699730ab20867e77ffa21a0
|
Provenance
The following attestation bundles were made for fly_ftl_extract-0.1.0-py3-none-any.whl:
Publisher:
pypi-release.yml on andrew000/FLY-FTL-Extract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fly_ftl_extract-0.1.0-py3-none-any.whl -
Subject digest:
f5e5cb758388583c0661e6a0ca825d98cdd75b0c4210db1b3293067ea9e44e9e - Sigstore transparency entry: 2883818799
- Sigstore integration time:
-
Permalink:
andrew000/FLY-FTL-Extract@7d6942ce68a60efb4a2ce9a9b5d298f7d812da2b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/andrew000
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-release.yml@7d6942ce68a60efb4a2ce9a9b5d298f7d812da2b -
Trigger Event:
release
-
Statement type: