Spelling & sentence correction for mobile keyboards. 13.5M params trained
from scratch, shipped as int8 ONNX (27MB total), ~25ms per sentence on 2 CPU
threads. Also includes lexicons.json: frequency-ranked wordlists and
next-word tables for 10 locales.
Don't use it for Japanese. It makes Japanese text worse.
1import numpy as np, onnxruntime as ort, sentencepiece as spm
2from huggingface_hub import hf_hub_download
3
4repo = "Loke-60000/gl-keyboard-correction"
5enc = ort.InferenceSession(hf_hub_download(repo, "gec-encoder-int8.onnx"))
6dec = ort.InferenceSession(hf_hub_download(repo, "gec-decoder-int8.onnx"))
7sp = spm.SentencePieceProcessor(model_file=hf_hub_download(repo, "spm.model"))
8
9MAX_LEN = 96 # fixed shapes; pad=0, bos=2, eos=3
10
11def correct(text, lang): # lang: en fr de es it pt_br ru ar ko ja
12 src = np.zeros((1, MAX_LEN), dtype=np.int64)
13 ids = [sp.piece_to_id(f"<{lang}>")] + sp.encode(text)
14 src[0, :len(ids)] = ids[:MAX_LEN]
15 memory = enc.run(None, {"src": src})[0]
16 tgt = np.zeros((1, MAX_LEN), dtype=np.int64)
17 tgt[0, 0] = 2
18 out = []
19 for pos in range(min(len(ids) + 8, MAX_LEN - 1)):
20 logits = dec.run(None, {"tgt": tgt, "pos": np.array([pos], dtype=np.int64),
21 "memory": memory, "src": src})[0]
22 nxt = int(logits[0].argmax())
23 if nxt == 3:
24 break
25 tgt[0, pos + 1] = nxt
26 out.append(nxt)
27 return sp.decode(out)
28
29print(correct("i cant beleive its alredy friday", "en"))
30print(correct("das waere schoen, vielen dank fuer alles", "de"))
1import json
2from huggingface_hub import hf_hub_download
3
4lex = json.load(open(hf_hub_download("Loke-60000/gl-keyboard-correction", "lexicons.json")))
5print(lex["en-US"][:10]) # words ranked by frequency
6print(lex["_nextWords"]["en-US"]["thank"]) # next-word prediction
Numbers below are from a real Android integration, measured on device-class
ART (emulator) and a JVM benchmark. Phone CPUs scale roughly 3-5x slower
than the JVM figures.
For the ONNX model: run it only when a sentence is committed, never per
keystroke. Create the two OrtSessions once and reuse them for the process
lifetime; session creation is the expensive part, inference is ~25 ms.
Surface the result as a tappable suggestion, never a silent rewrite, and
show nothing when the output equals the input.
Training data: OPUS OpenSubtitles v2018 (Lison & Tiedemann, 2016). No
subtitle text is included in these files.