Skip to main content

MillID

Detect the language of any text, offline, in Python. MillID recognises 1,550 languages written in 56 scripts, including hundreds of African, Asian and Indigenous languages that common language detectors do not cover. It runs on a CPU with no PyTorch and no server; the smallest model is 11 MB.

from millid import MillID

model = MillID.from_pretrained("tiny-v1.5")
model.predict("Mo fẹ́ràn láti ka ìwé ní àkókò òmìnira mi.", k=1)
# [Prediction(label='yor_Latn', language='Yoruba', probability=0.973627)]

What is MillID?

MillID (MultiLingual Language IDentifier) is an open language identification model built by Baobab Tech. Give it a piece of text, from a short sentence to a whole document, and it tells you which language the text is written in, with a probability for each answer. Every answer names a language and its script, so Serbian in Cyrillic (srp_Cyrl) and Serbian in Latin (srp_Latn) are told apart.

Developers use it to:

  • send each document to the right translation, OCR or speech model;
  • sort or filter text by language when building a dataset;
  • show an interface in the reader's language, or flag text in an unexpected one;
  • count which languages a collection of documents contains.

What this package does

This package runs MillID on your own machine. The first time you load a model it downloads the model's files from the Hugging Face Hub into the Hugging Face cache; after that it works offline. The model runs in ONNX Runtime, on a CPU or an NVIDIA GPU, with NumPy for the text encoding. There is no API to call and no PyTorch to install, and the text you identify never leaves your machine.

It also gives you a command-line tool and, if you want one, an HTTP service. The JavaScript package @baobabtechai/millid gives the same answers in Node.js and the browser.

Install

pip install "millid[cpu]"           # ONNX Runtime for the CPU
pip install "millid[gpu]"           # ONNX Runtime for NVIDIA GPUs (CUDA 12, its libraries from pip)
pip install "millid[cpu,server]"    # and the HTTP service

Python 3.10 or later. ONNX Runtime comes as an extra because its CPU and GPU builds cannot be installed side by side: choose one.

Quick start

from millid import MillID

model = MillID.from_pretrained("tiny-v1.5")     # downloads 11 MB once

model.predict("Je voudrais réserver une table pour deux personnes ce soir.", k=2)
# [Prediction(label='fra_Latn', language='French', probability=0.954421),
#  Prediction(label='frp_Latn', language='Arpitan', probability=0.001443)]

model.predict(["Lave men ou ak savon anvan ou manje.", "Ndimakonda kuwerenga mabuku nthawi yanga yaulere."], k=1)
# [[Prediction(label='hat_Latn', language='Haitian Creole', probability=0.978552)],
#  [Prediction(label='nya_Latn', language='Nyanja', probability=0.940327)]]

predict(text, k) returns the k most likely languages (3 by default), most likely first. Pass a list to identify many texts in one call: they are batched together, which is much faster than one call per text.

Command line

millid predict "Lave men ou ak savon anvan ou manje." -k 2
# hat_Latn 0.979, crs_Latn 0.000	Lave men ou ak savon anvan ou manje.

cat sentences.txt | millid predict -k 1                     # one text per line
millid predict --document < report.txt                      # the whole file as one document, as JSON
millid predict --model large-v1.5 --device cuda "..."       # another model, on the GPU

Choose a model

Model Download Top-1 accuracy Macro F1 Best for
tiny-v1.5 (default) 11 MB 95.9% 0.955 any CPU, laptops, small servers
medium-v1 455 MB 96.2% 0.958 servers
large-v1.5 764 MB 96.7% 0.965 servers with a GPU: the most accurate

Measured on 240,241 test passages in 1,621 languages, from documents the models never saw in training. Macro F1 weighs every language equally, so it shows how well the small languages are served, not just the large ones. The leaderboard compares the three with GlotLID and Meta's fastText identifier, language by language.

from_pretrained also takes a Hugging Face repo id ("baobabtech/millid-large-v1.5") or a local directory holding config.json, labels.json and onnx/model.onnx, and these options:

model = MillID.from_pretrained(
    "large-v1.5",
    device="cuda",       # "cpu" (the default), "cuda", or "auto": the GPU when there is one
    threads=4,           # CPU threads for ONNX Runtime; its default when omitted
    batch_size=64,       # texts per model call
)

Reading the results

Each answer is a Prediction with three fields:

Field Example Meaning
label 'yor_Latn' the language's ISO 639-3 code and its ISO 15924 script code
language 'Yoruba' the language's English name
probability 0.973627 how likely this answer is, from 0 to 1; the answers for a text add up to at most 1

A few labels end in a script alone, such as und_Tibt: text in that script whose language MillID cannot name more precisely.

Long text and whole documents

predict reads the first 255 bytes of a text, about 250 characters of English or 85 of Hindi. For anything longer, use identify_document: it reads the whole text in windows, gives the document's languages weighted by how much of the text each one covers, and marks where each language runs.

doc = model.identify_document(long_text, k=2)
doc.languages
# [Prediction(label='eng_Latn', language='English', probability=0.576472),
#  Prediction(label='fra_Latn', language='French', probability=0.381211)]
doc.segments
# [Segment(start=0, end=250, label='eng_Latn', language='English', probability=0.952214),
#  Segment(start=251, end=414, label='fra_Latn', language='French', probability=0.96499)]
doc.windows, doc.characters
# (2, 414)

start and end count characters in the text after normalisation (millid.normalize(text)), which collapses whitespace and applies Unicode NFKC.

An HTTP service

millid serve --models "tiny-v1.5=baobabtech/millid-tiny-v1.5@cpu" --port 8050
curl -s localhost:8050/identify -H 'content-type: application/json' -d '{"text": "Lave men ou ak savon anvan ou manje.", "k": 1}'
# {"model": "tiny-v1.5", "results": [{"languages": [{"label": "hat_Latn", "language": "Haitian Creole", "probability": 0.978552}]}]}

POST /identify takes text or texts, k, model, and document: true for a whole document; GET /models describes the loaded models and GET /health reports that the service is up. Requests that arrive together are answered in shared batches, so throughput grows with load. To serve MillID inside an application of your own, build on millid.Registry and millid.MicroBatcher.

Tips

  • Give it a sentence or more. A word or a short greeting carries little evidence: "Bonjour tout le monde" alone comes back as nrm_Latn (Norman) rather than French. A full sentence or more gives much more reliable answers.
  • Treat a low probability as unsure. When the first answer is below 0.5, look at the next ones too, or ask for more text.
  • Close languages share their answers. Swahili and Congo Swahili, or Bosnian and Croatian, differ by a few words; a short passage of either often gets both in its top answers. Ask for k=3 and decide with what you know about your text.
  • Pass the text as it is. Accents, tone marks and the script are much of what the model reads: do not strip, transliterate or romanise it first.
  • One text alone and the same text in a batch can score a little differently. A batch is lower-cased as one string; call predict with one text where scores must not depend on their neighbours.

API

MillID.from_pretrained(ref="tiny-v1.5", revision=None, token=None, **options) Load a model: "tiny-v1.5", "medium-v1", "large-v1.5", a Hugging Face repo id, or a directory. token only for a private repo; options device, threads, batch_size, gpu_mem_limit_mb
model.predict(text, k=3) The k most likely languages of a text, as Predictions. A list of texts gives one list per text
model.identify_document(text, k=3, max_windows=256) A text of any length, as a DocumentResult: languages, segments, windows, characters
model.probabilities(texts) A NumPy array, one row per text, a probability for each label in model.labels
millid.MODELS The released models by short name
millid.normalize, millid.encode_batch The model's input, to run the ONNX file elsewhere

MillID is millid.LanguageIdentifier under a shorter name. A model is safe to call from several threads at once.

How it works

MillID is a small transformer that reads text as UTF-8 bytes rather than words, so there is no vocabulary to outgrow: any script, even one it has rarely seen, is input it can read. Each byte is described by the byte itself, the Unicode script of its character and the character sequences ending there; the network turns a passage into one vector and scores it against a vector for every label, built from the label itself, its language (shared across scripts) and its script. The full design is in the architecture document, and each model's card on the Hub has its evaluation.

Licence

Apache-2.0, for the code and the model weights. Built by Baobab Tech.

Metadata

Release files for millid 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for millid 0.2.0
File Size Uploaded
millid-0.2.0.tar.gz 26.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for millid 0.2.0
File Interpreter ABI Platform
millid-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 54.8 kB

Release files / millid-0.2.0.tar.gz

Download URL millid-0.2.0.tar.gz
Size 26.2 kB
Tags Source
SHA-256 checksum
How to use checksums
0cf59cf5952926e36af94eb207b07f7917a5bbc238b5efb61422ee86ea0a6cca
BLAKE2b-256 checksum
How to use checksums
41dfd2f1797f3efb5a515fff7882b20c9db35843db063351e00054edd0c36395
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / millid-0.2.0-py3-none-any.whl

Download URL millid-0.2.0-py3-none-any.whl
Size 28.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e15d4bdb908fdf6630f3e09d680922d7eb641898508bd160b7ada7cc2b9f6d54
BLAKE2b-256 checksum
How to use checksums
a6a226ed379e48c68b241ee4b54804e1e8c4ee745a54e1647e1ad0130f9ec706
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page