Type a word or a sentence and get the emoji that fits. Tuned for to-dos,
calendar entries, notes, and message drafts across 22 languages (including
CJK, Arabic, Thai, Hindi, and more). The whole thing, model and tokenizer,
is small (5MB on Apple via Core ML, 11MB via LiteRT elsewhere) and runs in well under 2ms on device.
"Dentist appointment" → 🦷 · "réserver un vol pour Tokyo" → ✈️ · "犬の散歩" → 🐕 · "จองโรงแรม" → 🏨
1npm i @desert-ant-labs/emo @litertjs/core # browser2npm i @desert-ant-labs/emo # Node, prebuilt native core
Files
File
Format
Size
Contents
emo.tflite
LiteRT / TFLite (int8)
10.2MB
Fixed-window n-gram + masked semantic inputs, softmax probabilities output; runs on Android, Linux, Node, and the web (bundled by default in the Kotlin SDK; downloaded on demand by the JavaScript SDK)
emo.mlmodelc
Compiled Core ML
4.6MB
Mixed 4-/8-bit-palettized transformer, ready to load on Apple platforms (used by the Swift SDK)
Older revisions (tags v0.6.0 and earlier) carry Emo.mlmodelc and emo.safetensors for SDK versions that predate the unified cross-platform migration.
Architecture
A compact two-stream classifier - no large encoder, just a tiny transformer over the semantic tokens:
Lexical stream: script-aware character/word n-grams (Latin, Han·Kana, Hangul
jamo, Devanagari clusters, SE-Asian, …) hashed into a fixed multi-hash signed
embedding table. Its size is independent of the number of languages.
Semantic stream: a frozen multilingual static embedding (Model2Vec
potion-multilingual-128M,
distilled from BAAI bge-m3), PCA-reduced to 128 dims and vocab-pruned to the
48k tokens that matter for the 22 target languages. Gives cross-lingual
generalization and handles out-of-vocabulary words. The matching 750KB unigram
tokenizer ships alongside (emo_tokenizer.bin).
Semantic pooling: a small 2-layer transformer encoder runs over the semantic
token sequence, then an attention pool - order-aware, so it composes phrases and
idioms instead of averaging tokens.
Head: a small MLP fusing the two streams into a softmax over a curated vocabulary of 812 everyday emojis (the emojis that actually come up most across the
training phrases). Trained with n-gram dropout so the head relies on the semantic
stream, which is what makes it generalize across languages.
Inputs and outputs
Input: a plain text string. Best on short, intent-oriented text.
Output: a probability distribution over the 812-emoji vocabulary; take the
top-1 (or top-k). Optimized for top-1 relevance.