Views
No views yet

pip install wldetect1git clone https://github.com/dleemiller/WordLlamaDetect.git
2cd WordLlamaDetect
3uv sync1from wldetect import WLDetect
2
3# Load bundled model (no path needed)
4wld = WLDetect.load()
5
6# Detect language for single text
7lang, confidence = wld.predict("Hello, how are you today?")
8# ('eng_Latn', 0.9564036726951599)1# Detect from text
2uv run wldetect detect --text "Bonjour le monde"
3
4# Detect from file
5uv run wldetect detect --file input.txteng_Latn, cmn_Hans, arb_Arab)[!TIP] See docs/languages.md for the complete list of supported languages with performance metrics.
[!NOTE]
Gemma3 is a good choice for this application, because it was trained on over 140 languages. The tokenizer, vocab size (262k) and multi-language training are critical for performance.
exp((embeddings * token_weights) @ projection.T + bias),
where embeddings are frozen token embeddings from Gemma3, trained with focal loss on OpenLID-v2.
During training, token vectors are aggregated using logsumexp pooling along the sequence dimension.[!IMPORTANT]
To optimize artifact size and compute, we performexp(logits)before saving the lookup table. Then we apply a threshold to make the table sparse. This reduces the artifact size 10x (~130mb -> 13mb), with negligable performance degradation.
| Split | Accuracy | F1 (macro) | F1 (weighted) | Samples |
|---|---|---|---|---|
| dev | 92.92% | 92.74% | 92.75% | 150,547 |
| devtest | 92.86% | 92.71% | 92.69% | 153,824 |
eng_Latn, cmn_Hans, arb_Arab).1# CPU or default CUDA version
2uv sync --extra training
3
4# With CUDA 12.8 (Blackwell)
5uv sync --extra cu128configs/models/custom-config.yaml:1model:
2 name: google/gemma-3-27b-pt
3 hidden_dim: 5376
4 shard_pattern: model-00001-of-00012.safetensors
5 embedding_layer_name: language_model.model.embed_tokens.weight
6
7languages:
8 eng_Latn: 0
9 spa_Latn: 1
10 fra_Latn: 2
11 # ... add more languages
12
13inference:
14 max_sequence_length: 512
15 pooling: logsumexpconfigs/training/custom-training.yaml:1model_config_path: "configs/models/custom-model.yaml"
2
3dataset:
4 name: "laurievb/OpenLID-v2"
5 filter_languages: true
6
7training:
8 batch_size: 1536
9 learning_rate: 0.002
10 epochs: 2uv run wldetect train --config configs/training/custom-training.yamlartifacts/:lookup_table_exp.safetensors - Sparse exp lookup table (for inference)projection.safetensors - Projection matrix (fp32, for fine-tuning)model_config.yaml - Model configurationmodel.pt - Full PyTorch checkpoint1# Train model
2uv run wldetect train --config configs/training/gemma3-27b.yaml
3
4# Evaluate on FLORES+
5uv run wldetect eval --model-path artifacts/ --split dev
6
7# Generate sparse lookup table from checkpoint (default: threshold=10.0)
8uv run wldetect create-lookup \
9 --checkpoint artifacts/checkpoints/checkpoint_step_100000.pt \
10 --config configs/training/gemma3-27b.yaml \
11 --output-dir artifacts/1@software{miller2025wordllamadetect,
2 author = {Miller, D. Lee},
3 title = {WordLlama Detect: The Language of the Token},
4 year = {2025},
5 url = {https://github.com/dleemiller/WordLlamaDetect},
6 version = {0.1.0}
7}