ONNX export of cis-lmu/glotlidmodel_v3.bin, a fastText supervised language identifier that covers 2102
labels in the form iso639-3_Script (for example eng_Latn, por_Latn,
glg_Latn).
The licence is Apache-2.0, inherited from GlotLID. Please cite the GlotLID
authors if you use this model.
What the graph does and does not do
fastText inference has five steps. The ONNX graph holds only the last two:
Step
Where
1. Tokenize the text
Python (glotlid_hash.py)
2. Character n-grams per word (minn..maxn)
Python
3. Hash the n-grams into buckets
Python
4. Average the embedding rows of all feature ids
ONNX
5. Multiply by the output matrix, then softmax
ONNX
Steps 1 to 3 are string processing. ONNX has no portable operator for
fastText's FNV-1a byte hash over UTF-8, so that work stays in Python. The
split keeps the graph a pure numeric pipeline:
glotlid_hash.py is the reference implementation of steps 1 to 3. It
reproduces fastText's Dictionary::getLine, Dictionary::computeSubwords
and Dictionary::hash. Two details are easy to get wrong:
fastText casts each byte to a signedint8_t before the FNV-1a XOR, so
bytes >= 0x80 are sign-extended. Without this, every non-ASCII n-gram lands
in the wrong bucket.
Each line ends with the </s> end-of-sentence token, and that token
contributes its own vocabulary row.
1import json
2import numpy as np
3import onnxruntime as ort
4from huggingface_hub import snapshot_download
56from glotlid_hash import GlotLIDFeaturizer
78d = snapshot_download("TigreGotico/glotlid-onnx")9feat = GlotLIDFeaturizer.from_files(f"{d}/vocab.txt",f"{d}/config.json")10labels = json.load(open(f"{d}/labels.json", encoding="utf-8"))11sess = ort.InferenceSession(f"{d}/glotlid.onnx", providers=["CPUExecutionProvider"])1213defdetect(text, k=5):14 probs = sess.run(None,{"input_ids": feat(text)})[0]15 top = np.argsort(-probs)[:k]16return[(labels[i],float(probs[i]))for i in top]1718print(detect("O tempo está moi bo hoxe en Santiago"))19# [('__label__glg_Latn', 0.98...), ...]
Each sample was compared against fasttext_model.predict(text, k=5).
Model
Top-1 agreement
Top-5 identical order
Mean abs. prob delta (top-1)
Max
glotlid.onnx (fp32)
100.00 % (78/78)
83.3 %
1.03e-05
1.39e-05
glotlid.int8.onnx
100.00 % (78/78)
67.9 %
6.08e-04
1.81e-02
The fp32 probability delta of about 1e-05 is not export error. fastText
returns probabilities through a 512-entry logarithm lookup table whose entries
carry a +1e-5 term, so its reported values sit about 1e-5 above the true
softmax. The ONNX graph returns the exact softmax. This also explains the
top-5 order differences: they occur only among labels whose probabilities are
below the resolution of that table, where fastText's own ranking is arbitrary.
The int8 graph keeps every top-1 decision but its probability values move by
up to 0.018, so use fp32 if you threshold on confidence.
Reproduction
glotlid_hash.py was validated against fastText's own get_subwords() on
2006 tokens (2000 sampled from the vocabulary plus out-of-vocabulary strings
in Greek, Devanagari, Han, Latin-extended and Inuktitut syllabics): 0
mismatches in the full feature-id lists.