Skip to content

Commit 72c5f48

Browse files
author
Atome LM Team
committed
Atome LM v0.3.0 — initial public release
0 parents  commit 72c5f48

126 files changed

Lines changed: 14931 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
jobs:
11+
pytest:
12+
name: pytest (Python ${{ matrix.python-version }})
13+
runs-on: ubuntu-latest
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
python-version: ["3.10", "3.11", "3.12"]
18+
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Set up Python ${{ matrix.python-version }}
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version: ${{ matrix.python-version }}
27+
cache: pip
28+
29+
- name: Install build essentials + qemu-system-arm
30+
run: |
31+
sudo apt-get update
32+
sudo apt-get install -y --no-install-recommends \
33+
build-essential gcc-arm-none-eabi qemu-system-arm
34+
35+
- name: Install CPU-only PyTorch
36+
run: |
37+
python -m pip install --upgrade pip
38+
pip install --index-url https://download.pytorch.org/whl/cpu \
39+
"torch>=2.0"
40+
41+
- name: Install atome-llm + test deps
42+
run: pip install -e ".[dev]"
43+
44+
- name: Environment check
45+
run: python check_env.py
46+
47+
- name: pytest
48+
run: pytest -q

.gitignore

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
__pycache__/
2+
*.pyc
3+
*.pyo
4+
*.egg-info/
5+
.pytest_cache/
6+
build/
7+
8+
# Trained checkpoints — too big and binary, EXCEPT the three released artifacts
9+
# (944K demo blob + its PyTorch source + the vanilla FP32 baseline used for
10+
# the HONEST_RESULTS reversal A/B). These are tracked.
11+
checkpoints/*.pt
12+
checkpoints/*.atome
13+
checkpoints/*.atome2
14+
checkpoints/*.bin
15+
checkpoints/ab_sweep/
16+
!checkpoints/atome_944k.bin
17+
!checkpoints/atome_1m_v1.pt
18+
!checkpoints/vanilla_1m_v1.pt
19+
20+
# Generated corpus + on-disk fetch cache (sample.txt is intentionally tracked)
21+
data/*.txt
22+
!data/sample.txt
23+
.corpus_cache/
24+
25+
# Generated firmware artifacts
26+
c_engine/targets/*/model_data.h
27+
c_engine/targets/*/prompt_data.h
28+
c_engine/targets/*/firmware.elf
29+
c_engine/targets/*/firmware.map
30+
c_engine/targets/*/*.o
31+
32+
# Distribution kit zips and source tarballs
33+
atome-research-kit-*.zip
34+
atomelm-site.zip
35+
dist/*.tar.gz
36+
dist/*.zip
37+
38+
# Drafts and editor cruft
39+
*.draft.txt
40+
.DS_Store
41+
.idea/
42+
.vscode/
43+
44+
# Local venv
45+
.venv/
46+
venv/
47+

CITATION.cff

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
cff-version: 1.2.0
2+
title: "Atome LM: a tiny ternary language model for microcontroller deployment"
3+
message: "If you use this software, please cite it as below."
4+
type: software
5+
authors:
6+
- name: "Atome LM contributors"
7+
url: "https://atomelm.com"
8+
version: "0.3.0"
9+
date-released: 2026-05-21
10+
license: Apache-2.0
11+
keywords:
12+
- "language model"
13+
- "ternary"
14+
- "bitnet"
15+
- "microcontroller"
16+
- "edge-ai"
17+
- "tinyml"

CODE_OF_CONDUCT.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Code of Conduct
2+
3+
This project follows the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
4+
5+
In short: be respectful, assume good faith, and focus discussion on the work. Everyone is welcome to contribute regardless of background or identity. Reports of unacceptable behavior can be sent privately to **hello@atomelm.com** and will be reviewed promptly and confidentially.
6+
7+
The full text of the Contributor Covenant — including the complete enforcement guidelines — is at the link above and applies to this project in full.

CONTRIBUTING.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Contributing to Atome LM
2+
3+
Thanks for considering a contribution. This is a small, focused project — a tiny ternary language model + a C99 inference engine that talks to it bit-exactly. Read `PROJECT_CONTENT.md` first; it covers what you must not break.
4+
5+
## Quick start
6+
7+
```bash
8+
git clone https://github.com/atome-lm/atome-llm-kit
9+
cd atome-llm-kit
10+
./install.sh
11+
. .venv/bin/activate
12+
pytest -q # expect: 146 passed (or 145 + 1 skipped without qemu-system-arm)
13+
```
14+
15+
## Reporting bugs
16+
17+
Open an issue on GitHub with:
18+
19+
- what you ran (exact command)
20+
- what you expected
21+
- what happened (full error, not paraphrased)
22+
- your platform: OS, Python version, and `python -c "import torch; print(torch.__version__)"`
23+
24+
If you hit a parity failure (Python forward ≠ C forward), please attach the failing seed and any checkpoint you trained — these are the highest-priority bugs.
25+
26+
## Submitting a pull request
27+
28+
1. Fork the repo and create a branch off `main`.
29+
2. Make your change.
30+
3. Run the full test suite — every PR must keep `pytest -q` green.
31+
4. If your change touches `atome_llm/core/`, `c_engine/upstream/`, or the export format, **specifically confirm** these tests still pass:
32+
- `tests/test_parity_with_c.py` — single-forward Python ↔ C parity
33+
- `tests/test_parity_multitoken.py` — multi-token Python ↔ C parity
34+
- `tests/test_export_format.py` — binary format + header generation
35+
5. Open the PR. CI will rerun the suite on Python 3.10 / 3.11 / 3.12.
36+
37+
## Scope of acceptable changes
38+
39+
Welcome:
40+
41+
- Bug fixes
42+
- New test coverage (especially fuzz cases on the C parser and edge inputs to `atome_predict_next` / `atome_generate`)
43+
- Performance improvements that preserve bit-exact parity
44+
- Documentation fixes and clarifications
45+
- New MCU target boards under `c_engine/targets/`, *as long as they don't change the upstream engine*
46+
- New baselines under `atome_llm/baselines/` for honest A/B comparison
47+
48+
Out of scope, please don't open PRs for these:
49+
50+
- Adding heap allocation, dynamic memory, or libc dependencies to `c_engine/upstream/`
51+
- Adding "shouldn't happen" fallbacks to deterministic code paths
52+
- Bundling new tokenizers (BPE / sentencepiece) — the byte tokenizer is a load-bearing design choice for MCU flash budget
53+
- Changes that break Python ↔ C parity, even if they improve a benchmark
54+
- New features that promote code from `c_engine/experiments/` into `c_engine/upstream/` without full parity + bounds-check coverage
55+
56+
## Coding standards
57+
58+
- Python: keep it simple, no helper layers, no decorators-for-style. Match the existing voice — small functions, no premature abstraction, comments only when the *why* is non-obvious.
59+
- C: C99 only, no GNU extensions, no libc beyond `<string.h>` / `<math.h>` / `<stdint.h>`. Static buffers sized by compile-time `ATOME_*` macros. Bounds-check all public API inputs.
60+
61+
## Security
62+
63+
If you find a security issue (anything that lets a malicious checkpoint or `.atome` blob compromise a host running the engine), please email **hello@atomelm.com** instead of filing a public issue. We'll coordinate disclosure.
64+
65+
## License
66+
67+
By submitting a contribution you agree it will be released under the Apache License 2.0 (the project license — see `LICENSE`).

FRONTIER.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Atome LM — Frontier Findings
2+
3+
> **Update 2026-05-11 — scale-up A/B at 944K reverses the headline.**
4+
> Same recipe, same val slice, same fairness audit, a 944K-param vanilla
5+
> GPT-FP32 baseline (950,608 params, +0.63 % vs Atome's 944,640) reaches
6+
> val loss 0.9337 / ppl 2.54, beating Atome ternary at 944K by 11.4 %
7+
> in loss and 11.5 % in perplexity. The +22 % param-fair / +52 %
8+
> flash-fair gains below hold at the **60K-param MCU regime** and only
9+
> that regime. Above ~1M params the inductive bias of the 3-pathway
10+
> block stops substituting for capacity and starts constraining it.
11+
> The honest framing is: *Atome's bet is the small-model regime —
12+
> sub-1M params, MCU-class deployment, no network.* See
13+
> [`HONEST_RESULTS.md`](HONEST_RESULTS.md) for the full 944K reading.
14+
> Multi-seed pending.
15+
16+
**Date.** 2026-05-09. CPU only, no GPU.
17+
**Hardware.** 4-thread CPU box. PyTorch 2.x, FP32 reference path.
18+
**Corpus.** TinyStories validation slice, 500 KB UTF-8 (~99.9 % ASCII).
19+
Train/eval split 90/10 over 64-byte chunks → 7,030 train chunks /
20+
782 held-out chunks.
21+
**Optimizer.** AdamW, lr 3e-4, batch 16, seq 64, 3,000 steps.
22+
**Single seed** (seed 0). Results have not been replicated across seeds.
23+
24+
This document reports the first apples-to-apples A/B between Atome's
25+
3-pathway ternary architecture and vanilla decoder-only Transformers
26+
(FP32) at fixed parameter count and at fixed flash budget. The closest
27+
published peer is Andrej Karpathy's `Stories260K` — a 260 K-parameter
28+
FP32 plain transformer trained on TinyStories. Atome's frontier claim
29+
is "smaller flash, better quality, smaller bits-per-weight, *and*
30+
deployable on a $2 microcontroller." This page tests the first three
31+
of those claims directly; MCU deployment is verified separately via
32+
bit-exact Python ↔ C ↔ Cortex-M3 (QEMU) parity (see `tests/test_qemu_parity.py`).
33+
34+
## TL;DR
35+
36+
| Model | Params | Bits/wt | Disk | bpb ↓ | Perplexity ↓ |
37+
|---|---:|---:|---:|---:|---:|
38+
| **Atome 3-pathway, ternary** | **60,800** | **1.58** | **15.1 KB**¹ / **17.2 KB**² | **2.66** | **6.31** |
39+
| Vanilla GPT, FP32 (param-fair) | 60,808 | 32 | 237.5 KB | 3.02 | 8.12 |
40+
| Vanilla GPT, FP32 (flash-fair) | 5,968 | 32 | 23.3 KB | 3.71 | 13.10 |
41+
42+
¹ ATOME01, 4 trits/byte (current C engine reads this).
43+
² ATOME02, 5 trits/byte base-3 packing — 14.4 % smaller, near
44+
information-theoretic floor of `log2(3) ≈ 1.585` bits/trit. Python
45+
encoder + decoder shipped today; C decoder is a future change.
46+
47+
## What this proves
48+
49+
1. **At the same parameter count, the 3-pathway ternary architecture
50+
beats a plain transformer by 22 % on perplexity (6.31 vs 8.12)
51+
while using 16× less disk.**
52+
53+
The vanilla baseline is *not* over-parameterized — it's matched at
54+
60.8 K params (`d_model=44, n_layers=3, n_heads=4, d_ff=44`,
55+
selected by brute-force search to land within 8 params of the
56+
target). This is the same architecture every public tiny-LM paper
57+
(`Stories260K`, the TinyStories paper, BitNet at small scale) uses,
58+
modulo trivia.
59+
60+
2. **At the same flash budget, the 3-pathway ternary architecture beats
61+
a plain transformer by 52 % on perplexity (6.31 vs 13.10).**
62+
63+
The flash-fair vanilla baseline is `d_model=8, n_layers=2,
64+
n_heads=4, d_ff=24`. It sits in the same 20–25 KB on-disk budget as
65+
the Atome ATOME01 binary (15.1 KB) and ATOME02 binary (17.2 KB).
66+
67+
3. **The 1.58-bit weights cost ~22 % perplexity vs FP32 at the same
68+
architecture parameters** — but the FP32 version costs 16× more
69+
flash. On any device where flash is the bottleneck (every MCU we
70+
target), ternary wins. On any device where compute is the
71+
bottleneck and flash is free (server CPUs), FP32 wins on quality.
72+
73+
4. **ATOME02 base-3 packing reaches 1.6 bits/trit — within 1 % of the
74+
information-theoretic floor of 1.585 bits/trit** — and reduces the
75+
on-disk binary from 20.1 KB to 17.2 KB on the same trained
76+
60.8 K-param model. C decoder still pending.
77+
78+
## What this does NOT prove
79+
80+
- **Single seed only.** All three numbers are seed 0. We have not run
81+
multi-seed yet to estimate variance. The 22 % / 52 % gaps are very
82+
large compared to typical seed-noise at this scale, but the variance
83+
is unmeasured.
84+
- **Single corpus.** TinyStories is a forgiving target — short stories
85+
with restricted vocabulary. Wider-domain or code corpora may favor
86+
vanilla attention. We have not measured.
87+
- **Single training horizon.** 3,000 steps is well short of
88+
convergence. The relative ranking might swap or amplify with more
89+
training. A 10 K-step run is in flight; we'll update this page if it
90+
changes the headline.
91+
- **No real silicon.** All MCU claims are verified on QEMU
92+
Cortex-M3, not on physical RP2040 / STM32 hardware. Tokens/sec and
93+
Joules/token on real silicon are still pending.
94+
- **Stories260K direct comparison still pending.** Karpathy's exact
95+
setup is `Stories260K` at 260 K params + a 32 K-token SentencePiece
96+
vocab. Our byte-tokenizer + 60 K config is ~4× smaller. A direct
97+
apples-to-apples vs `Stories260K` would need either (a) us to scale
98+
up to 260 K params and a SentencePiece tokenizer, or (b) Karpathy's
99+
setup retrained at 60 K params with a byte tokenizer. Neither is
100+
done.
101+
102+
## Comparison with the published frontier
103+
104+
| System | Smallest target | Params | Bits/wt | Real MCU? | Architecture beats vanilla? |
105+
|---|---|---:|---:|---|---|
106+
| Microsoft BitNet b1.58 | server CPU | 700 M – 3 B | 1.58 | no | (matches at scale) |
107+
| Meta MobileLLM | smartphone | 125 M – 1 B | 4–8 | no | yes (vs same-size vanilla) |
108+
| Karpathy `Stories260K` | laptop / browser | 260 K | 32 | no firmware | n/a (is the vanilla baseline) |
109+
| llama.cpp on RP2040 (hobby) | RP2040 + SD | ~1 B (swapped) | 4 | yes (slow, requires SD) | not measured |
110+
| TFLite Micro / Edge Impulse | Cortex-M0+ || 8 | yes | no language tasks |
111+
| **Atome LM (this work)** | **Cortex-M0+, 16 KB SRAM** | **60 K** | **1.58** | **QEMU yes, silicon pending** | **+22 % at param-fair, +52 % at flash-fair** |
112+
113+
Smaller, more bit-efficient, *and* architecturally beats vanilla at
114+
the budgets we target. To our knowledge, the smallest published LM
115+
where the routed-architecture win has been measured directly against
116+
a vanilla baseline at the same flash budget.
117+
118+
## Reproduce
119+
120+
```bash
121+
# from the repository root
122+
PYTHONPATH=. python3 scripts/build_corpus.py --source tinystories \
123+
--max-bytes 500000 --output data/tinystories.txt
124+
125+
PYTHONPATH=. python3 scripts/run_ab_sweep.py \
126+
--train data/tinystories.txt --steps 3000 \
127+
--output ab_results.json
128+
```
129+
130+
`ab_results.json` will contain the same numbers as in the table above
131+
(modulo platform-dependent rounding in PyTorch's matmul kernels).
132+
133+
## Open questions / next pushes
134+
135+
- **A1.** Multi-seed (3 seeds × 3 configs) to estimate variance on the
136+
22 % / 52 % gaps.
137+
- **A2.** Train all three to ≥ 10 K steps. Does the gap close, hold,
138+
or widen?
139+
- **A3.** Ablate: which of the three pathways (local conv, diagonal
140+
SSM, top-k sparse attention) carries most of the architecture win?
141+
Drop each, measure.
142+
- **A4.** Ship a C decoder for ATOME02. Cuts the demo binary from
143+
20.1 KB to 17.2 KB without code changes elsewhere.
144+
- **A5.** Real silicon. Flash an RP2040 with the engine + this 60.8 K
145+
ckpt. Measure tokens/sec, Joules/token. **The headline number that
146+
turns the claim from "frontier" into a fact.**
147+
- **A6.** Distillation from a strong teacher LLM (10 MB of curated
148+
narrow-domain text generated by a frontier model) into the same 60 K Atome.
149+
Open question: does the architecture advantage compound under
150+
distillation?
151+
- **A7.** Bug A fix (Python `generate` ↔ C `atome_generate`
152+
short-prompt SSM divergence). Touches the bit-exact-parity
153+
contract — needs explicit user sign-off.
154+
155+
## Files of record
156+
157+
- `ab_results.json` — exact numbers and config of the run reported here.
158+
- Trained A/B checkpoints (`atome_60k_ternary`, `vanilla_60k_fp32`,
159+
`vanilla_6k_fp32`) are *not* shipped — regenerate them with the harness
160+
below (this kit is train-from-scratch).
161+
- `atome_llm/baselines/vanilla_transformer.py` — the baseline.
162+
- `scripts/run_ab_sweep.py` — the harness.
163+
- `tests/test_vanilla_baseline.py` — 10 sanity tests on the baseline.
164+
- `tests/test_export_packed.py` — 5 tests on ATOME02 round-trip.
165+
- `tests/test_trit_packing.py` — 11 tests on the base-3 packer.

0 commit comments

Comments
 (0)