Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f493be9
Export rare-balanced source model
ealmloff May 16, 2026
392d044
Fix confusion matrix colorbar layout
ealmloff May 16, 2026
481b945
Export guesslang balanced model
ealmloff May 17, 2026
a70160a
Export pruned guesslang fs model
ealmloff May 18, 2026
22357e2
Wire pruned guesslang model into runtime
ealmloff May 18, 2026
7ae5e92
Restore by-size confusion report
ealmloff May 18, 2026
3b9afa3
Align README metrics with exported eval
ealmloff May 18, 2026
2908d30
Split overall confusion matrix image
ealmloff May 18, 2026
d0f70ff
Restore dark scale layout
ealmloff May 18, 2026
5ce6b39
Strip model metadata from runtime asset
ealmloff May 18, 2026
49009ef
Invert confusion matrix palette
ealmloff May 18, 2026
a018493
Merge branch 'main' into export-rare-balanced-model
ealmloff May 18, 2026
f6bb00a
Merge remote-tracking branch 'origin/export-rare-balanced-model' into…
ealmloff May 18, 2026
3a05f68
Remove unused model artifacts
ealmloff May 18, 2026
a68c0a9
Fix training script typo
ealmloff May 18, 2026
1257df6
Format model imports
ealmloff May 18, 2026
58b4179
Refactor model helpers for clippy
ealmloff May 18, 2026
b1dc8bd
fix merge conflicts
ealmloff May 18, 2026
13e2387
update docs
ealmloff May 18, 2026
32378b6
move confusion matrix up
ealmloff May 18, 2026
575b527
use rayon in the cli example
ealmloff May 18, 2026
cbb1b90
much faster for small files
ealmloff May 18, 2026
a7c3d2e
refactor tokenizer and unify forward pass
ealmloff May 18, 2026
a14f157
fuzz tokenizer
ealmloff May 18, 2026
f43f36f
switch scratch space to the heap
ealmloff May 18, 2026
277371a
final cleanup
ealmloff May 18, 2026
cbb92da
bump version
ealmloff May 18, 2026
92da743
align classes
ealmloff May 18, 2026
0e157e0
use range and ascii utils
ealmloff May 18, 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
50 changes: 14 additions & 36 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,17 @@ concurrency:
cancel-in-progress: true

jobs:
docs-hygiene:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check spelling
uses: crate-ci/typos@master
- name: Check links
uses: lycheeverse/lychee-action@v2
with:
args: >-
--no-progress
--exclude https://docs.rs/betlang
--exclude https://crates.io/crates/betlang
README.md
MODEL_CARD.md
RELEASING.md
scripts/TRAINING.md

rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Check formatting
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Test
run: cargo test --all-targets --all-features
- name: Docs
run: cargo doc --no-deps --all-features
env:
RUSTDOCFLAGS: -Dwarnings
- name: Package
run: cargo package --locked
check:
uses: dioxuslabs/dioxus-ci/.github/workflows/check.yml@v0.1.0

test:
uses: dioxuslabs/dioxus-ci/.github/workflows/test.yml@v0.1.0

fmt:
uses: dioxuslabs/dioxus-ci/.github/workflows/fmt.yml@v0.1.0

docs:
uses: dioxuslabs/dioxus-ci/.github/workflows/docs.yml@v0.1.0

clippy:
uses: dioxuslabs/dioxus-ci/.github/workflows/clippy.yml@v0.1.0
80 changes: 79 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "betlang"
version = "0.0.1"
version = "0.1.0"
edition = "2024"
rust-version = "1.88"
license = "MIT"
Expand All @@ -20,6 +20,7 @@ include = [
"/README.md",
"/RELEASING.md",
"/assets/confusion-by-size.png",
"/assets/confusion-overall.png",
"/assets/magika/source-student-q4.bin",
"/benches/detect.rs",
"/examples/*.rs",
Expand All @@ -34,6 +35,8 @@ fearless_simd = "0.4"
[dev-dependencies]
criterion = { version = "0.5", default-features = false, features = ["cargo_bench_support"] }
ignore = "0.4.25"
rand = "0.8"
rayon = "1.10"

[lib]
name = "betlang"
Expand Down
19 changes: 8 additions & 11 deletions MODEL_CARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
## Artifact

- File: `assets/magika/source-student-q4.bin`
- Format: raw quantized tensor payload
- Size: 100,444 bytes
- SHA-256: `e2498dc23a60cc32ae21a448c3763ee7080a6fbf9f813b63a066ef195e1e44a0`
- Architecture: `wordseq-b1536-k3-m2048-med-3conv-hidden`
- Format: weights-only MSQ1 quantized tensor payload
- Size: 47,840 bytes
- SHA-256: `59ef24167bddd1364eb9c1650add8a67e1a542b5155fac67f5e1cda07df0c0f0`
- Architecture: `wordseq-b1024-k3-m2048-tiny-3conv-hidden`
- Tokenizer: word-unit tokenizer version 3
- Classes: 67 embedded model classes mapped to 59 public `Language` variants
- Output head: 48 model labels exposed one-to-one as public `Language` variants

## Intended Use

Expand All @@ -30,10 +30,10 @@ derived from the training corpus and Magika teacher.

## Evaluation

Held-out `bigorig` test split:
Manifest-aligned held-out filesystem-label test split:

- `test_teacher_parity=0.967618`
- `test_fs_accuracy=0.962517`
- `test_fs_accuracy=0.965238`
- `macro_recall=0.965411`

The README confusion matrix groups the same held-out split by file-size bucket.

Expand All @@ -43,9 +43,6 @@ The README confusion matrix groups the same held-out split by file-size bucket.
non-whitespace bytes are available.
- Ambiguous snippets can put several languages close together even when a human
can infer the language from file naming context.
- Public variants may combine multiple model classes. For example, `jsonl`
maps to `json`, `shell` maps to `bash`, and several Ruby packaging/template
classes map to `ruby`.
- The classifier uses content only. It does not inspect file names, extensions,
shebangs outside the model window, repository metadata, or build-system
context.
Expand Down
48 changes: 23 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
[![Crates.io](https://img.shields.io/crates/v/betlang.svg)](https://crates.io/crates/betlang)
[![Docs.rs](https://docs.rs/betlang/badge.svg)](https://docs.rs/betlang)

CPU source-language detection for code with a tiny 100kb model.
CPU source-language detection for code with a tiny 50kb model.

```toml
[dependencies]
betlang = "0.0.1"
betlang = "0.1.0"
```

```rust
Expand All @@ -16,10 +16,8 @@ let detection = betlang::detect("fn main() { println!(\"hi\"); }");
assert_eq!(detection.language(), Some(betlang::Language::Rust));
```

Use `betlang::detect(source)` for UTF-8 source strings. Use
`betlang::detect_bytes(bytes)` for scanners that already work with file bytes
and should not reject non-UTF-8 input before classification. Both return a
`Detection`; call `Detection::language()` to read the top language.
Use `betlang::detect(source)` for UTF-8 source strings or byte slices. It
returns a `Detection`; call `Detection::language()` to read the top language.
Call `Detection::top_languages()` when you need ranked probabilities.

## Supported Languages
Expand All @@ -30,32 +28,32 @@ Slugs parse through the standard `FromStr` implementation:
assert_eq!("rust".parse::<betlang::Language>(), Ok(betlang::Language::Rust));
```

`asm`, `awk`, `batch`, `bash`, `c`, `c-sharp`, `clojure`, `cmake`, `cobol`,
`commonlisp`, `cpp`, `css`, `dart`, `diff`, `dockerfile`, `elixir`, `erlang`,
`go`, `groovy`, `haskell`, `hcl`, `html`, `ini`, `java`, `javascript`,
`jinja2`, `json`, `julia`, `kotlin`, `lua`, `markdown`, `matlab`, `objc`,
`ocaml`, `perl`, `php`, `postscript`, `powershell`, `prolog`, `python`, `r`,
`ruby`, `rust`, `scala`, `scss`, `solidity`, `sql`, `starlark`, `swift`,
`textproto`, `toml`, `typescript`, `vb`, `verilog`, `vhdl`, `vue`, `xml`,
`yaml`, `zig`.
`asm`, `batch`, `c`, `clojure`, `cmake`, `cobol`, `cpp`, `cs`, `css`, `dart`,
`dockerfile`, `elixir`, `erlang`, `gemfile`, `gemspec`, `go`, `gradle`,
`groovy`, `haskell`, `html`, `ini`, `java`, `javascript`, `json`, `julia`,
`kotlin`, `lisp`, `lua`, `markdown`, `objectivec`, `ocaml`, `perl`, `php`,
`powershell`, `python`, `r`, `ruby`, `rust`, `scala`, `shell`, `sql`, `swift`,
`toml`, `typescript`, `vba`, `verilog`, `xml`, `yaml`.

Several embedded model classes intentionally map to one public language. For
example, `erb`, `gemfile`, and `gemspec` map to `ruby`; `jsonl` maps to `json`;
`shell` maps to `bash`; and project-file classes such as `csproj` and `vcxproj`
map to `xml`.
These are the model's 48 output labels. Runtime detections expose them
one-to-one with no label aggregation.

The confusion matrix uses the same labels:

![Betlang wordseq confusion](https://raw.githubusercontent.com/ealmloff/betlang/v0.1.0/assets/confusion-overall.png)

## Model

The embedded model is `assets/magika/source-student-q4.bin`, a 100,444-byte
raw tensor payload with SHA-256:
The embedded model is `assets/magika/source-student-q4.bin`, a 47,840-byte
weights-only MSQ1 payload with SHA-256:

```text
e2498dc23a60cc32ae21a448c3763ee7080a6fbf9f813b63a066ef195e1e44a0
59ef24167bddd1364eb9c1650add8a67e1a542b5155fac67f5e1cda07df0c0f0
```

Architecture: `wordseq-b1536-k3-m2048-med-3conv-hidden`, tokenizer version 3.
On the held-out `bigorig` test split it reaches
`test_teacher_parity=0.967618` and `test_fs_accuracy=0.962517`.
Architecture: `wordseq-b1024-k3-m2048-tiny-3conv-hidden`, tokenizer version 3.
On the manifest-aligned held-out filesystem-label test split it reaches
`test_fs_accuracy=0.965238` with `macro_recall=0.965411`.

See [MODEL_CARD.md](MODEL_CARD.md) for the training and evaluation summary.

Expand All @@ -82,4 +80,4 @@ split. Each panel is a row-normalized confusion matrix for one file-size
bucket: actual labels are rows, predicted labels are columns, and the diagonal
is correct classification.

![Betlang wordseq confusion by file size](assets/confusion-by-size.png)
![Betlang wordseq confusion by file size](https://raw.githubusercontent.com/ealmloff/betlang/v0.1.0/assets/confusion-by-size.png)
Binary file modified assets/confusion-by-size.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/confusion-overall.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/magika/source-student-q4.bin
Binary file not shown.
Loading
Loading