Text Generation
Transformers
Safetensors
English
nano-spell
spelling-correction
tiny
byte-level
from-scratch
code-generated-data
Instructions to use vukrosic/nano-spell with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use vukrosic/nano-spell with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="vukrosic/nano-spell")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("vukrosic/nano-spell", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use vukrosic/nano-spell with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "vukrosic/nano-spell" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "vukrosic/nano-spell", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/vukrosic/nano-spell
- SGLang
How to use vukrosic/nano-spell with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "vukrosic/nano-spell" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "vukrosic/nano-spell", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "vukrosic/nano-spell" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "vukrosic/nano-spell", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use vukrosic/nano-spell with Docker Model Runner:
docker model run hf.co/vukrosic/nano-spell
Upload data_spell.py with huggingface_hub
Browse files- data_spell.py +148 -0
data_spell.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""spell — a code-generated supervised task: a misspelled word -> the correct word.
|
| 2 |
+
|
| 3 |
+
The honest nano-task test: correcting a typo needs a learned lexicon AND a sense of
|
| 4 |
+
which real word a misspelling most likely meant. The realistic script baseline is
|
| 5 |
+
"nearest dictionary word by edit distance" — but it has no frequency prior, so when a
|
| 6 |
+
typo lands as close to a wrong word as to the right one (`bcak` -> back? buck? beck?)
|
| 7 |
+
it guesses, and it breaks on transpositions and double-letters. The model packs a
|
| 8 |
+
frequency-weighted vocabulary into ~1M params and ranks the correction.
|
| 9 |
+
|
| 10 |
+
Each example is one line::
|
| 11 |
+
|
| 12 |
+
recieve => receive
|
| 13 |
+
teh => the
|
| 14 |
+
definately => definitely
|
| 15 |
+
|
| 16 |
+
Generation is answer-first and correct by construction: sample a real word from a
|
| 17 |
+
fixed, frequency-ordered vocabulary (Zipf-weighted so common words dominate), then
|
| 18 |
+
apply 1-2 realistic typo edits (delete, insert, substitute a keyboard neighbour,
|
| 19 |
+
transpose adjacent, double a letter). Because we start from the real word, the label
|
| 20 |
+
is ground truth. ~15% of examples are the identity (already-correct word) so the
|
| 21 |
+
model learns to leave correct words alone. The prompt is everything up to and
|
| 22 |
+
including ``" => "``; the target is the correct word. Byte-level vocab (256).
|
| 23 |
+
``spell_pairs`` is imported by both the dataset and the eval so train and test share
|
| 24 |
+
one data path. The vocabulary is the same frequency-ordered ~480-word list used
|
| 25 |
+
across the nano-* lexicon models.
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
from __future__ import annotations
|
| 29 |
+
|
| 30 |
+
import numpy as np
|
| 31 |
+
|
| 32 |
+
_VOWELS = frozenset("aeiou")
|
| 33 |
+
|
| 34 |
+
# A fixed, roughly frequency-ordered vocabulary of common English words (most
|
| 35 |
+
# common first). This list IS the lexicon prior the model learns; earlier words
|
| 36 |
+
# are sampled more often (Zipf), so corrections resolve toward the common word.
|
| 37 |
+
_RAW = """
|
| 38 |
+
the be to of and a in that have it for not on with he as you do at this but his by
|
| 39 |
+
from they we say her she or an will my one all would there their what so up out if
|
| 40 |
+
about who get which go me when make can like time no just him know take people into
|
| 41 |
+
year your good some could them see other than then now look only come its over think
|
| 42 |
+
also back after use two how our work first well way even new want because any these
|
| 43 |
+
give day most us man find here thing tell very big small great little own under last
|
| 44 |
+
right move place such again off play move where turn need start show point try kind
|
| 45 |
+
hand high old life feel three world school still state never become between high
|
| 46 |
+
really something most family leave word both water side without head house seem
|
| 47 |
+
end ask group never word turn problem child city week company system program question
|
| 48 |
+
during number course company point case fact night area money story result job book
|
| 49 |
+
word eye door health person art war history party result change morning reason
|
| 50 |
+
research girl guy moment air teacher force education foot boy age policy music
|
| 51 |
+
market sense nation plan college interest death course experience effort water late
|
| 52 |
+
example heart paper space ground form event official matter center couple site
|
| 53 |
+
project activity star table court produce stock paint deep base camp signal critic
|
| 54 |
+
gold storm phone north union deal author cover plant flag worth wide class
|
| 55 |
+
green field add light cross hard early hold listen body keep watch human seven send
|
| 56 |
+
build stay fall reach kill remain suggest raise pass sell require report decide
|
| 57 |
+
pull return explain hope develop carry break receive agree support hit produce
|
| 58 |
+
eat cover catch draw choose cause point talk lead serve die remember love
|
| 59 |
+
consider appear buy wait serve die send expect build stay fall cut reach
|
| 60 |
+
read spend grow open walk win offer remember love consider appear wear
|
| 61 |
+
green blue red black white brown gray pink quick brave clean clear close
|
| 62 |
+
deep dry fair fine flat fresh full glad hot huge late loud nice plain proud
|
| 63 |
+
rare rich ripe rough safe sharp short slow soft sour sweet tall thick thin tight
|
| 64 |
+
warm weak wet wild wise young above across along among around behind below beneath
|
| 65 |
+
beside beyond inside outside toward within against during except toward
|
| 66 |
+
animal apple bird boat bread brother bridge button camera candle carpet castle
|
| 67 |
+
cattle circle cloud coast color corner cotton cousin danger dinner doctor dollar
|
| 68 |
+
dragon dream eagle earth engine farmer feather finger flower forest friend garden
|
| 69 |
+
ghost glass grass guard heaven honey island jacket jungle ladder leather letter
|
| 70 |
+
lion magic market mirror monkey mother mountain needle nephew object ocean office
|
| 71 |
+
orange palace parent pencil pepper picture pillow planet pocket potato prince queen
|
| 72 |
+
rabbit rather record river rocket sailor school season silver singer sister snake
|
| 73 |
+
spider spring statue summer sunset symbol table teacher temple thread throat thunder
|
| 74 |
+
ticket tiger toast tower travel turtle uncle valley village voice wagon weather
|
| 75 |
+
window winter wizard wonder yellow zebra ocean orange forest planet flower garden
|
| 76 |
+
""".split()
|
| 77 |
+
|
| 78 |
+
# rough QWERTY left/right neighbours for substitution typos
|
| 79 |
+
_NEIGHBORS = {
|
| 80 |
+
"a": "sq", "b": "vn", "c": "xv", "d": "sf", "e": "wr", "f": "dg", "g": "fh",
|
| 81 |
+
"h": "gj", "i": "uo", "j": "hk", "k": "jl", "l": "k", "m": "n", "n": "bm",
|
| 82 |
+
"o": "ip", "p": "o", "q": "wa", "r": "et", "s": "ad", "t": "ry", "u": "yi",
|
| 83 |
+
"v": "cb", "w": "qe", "x": "zc", "y": "tu", "z": "x",
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def _build_vocab() -> list[str]:
|
| 88 |
+
"""De-duplicate `_RAW` keeping first (most-frequent) occurrence, drop words with
|
| 89 |
+
no consonant skeleton (matches the shared nano-* lexicon build exactly, so the
|
| 90 |
+
Zipf indices line up with the training data). Order = rough frequency rank."""
|
| 91 |
+
seen: set[str] = set()
|
| 92 |
+
vocab: list[str] = []
|
| 93 |
+
for w in _RAW:
|
| 94 |
+
if w in seen:
|
| 95 |
+
continue
|
| 96 |
+
seen.add(w)
|
| 97 |
+
if len("".join(c for c in w if c not in _VOWELS)) >= 1: # need a consonant
|
| 98 |
+
vocab.append(w)
|
| 99 |
+
return vocab
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
_WORDS = _build_vocab()
|
| 103 |
+
_RANKS = np.arange(1, len(_WORDS) + 1, dtype=np.float64)
|
| 104 |
+
_WEIGHTS = 1.0 / (_RANKS + 5.0)
|
| 105 |
+
_WEIGHTS /= _WEIGHTS.sum()
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def _typo(rng, w: str) -> str:
|
| 109 |
+
"""Apply one realistic single-character typo to `w`."""
|
| 110 |
+
if len(w) < 2:
|
| 111 |
+
return w
|
| 112 |
+
kind = rng.integers(5)
|
| 113 |
+
i = int(rng.integers(len(w)))
|
| 114 |
+
if kind == 0: # delete
|
| 115 |
+
return w[:i] + w[i + 1:]
|
| 116 |
+
if kind == 1: # insert a random letter
|
| 117 |
+
c = chr(int(rng.integers(26)) + 97)
|
| 118 |
+
return w[:i] + c + w[i:]
|
| 119 |
+
if kind == 2: # substitute a keyboard neighbour
|
| 120 |
+
opts = _NEIGHBORS.get(w[i], "")
|
| 121 |
+
if not opts:
|
| 122 |
+
return w[:i] + chr(int(rng.integers(26)) + 97) + w[i + 1:]
|
| 123 |
+
return w[:i] + opts[int(rng.integers(len(opts)))] + w[i + 1:]
|
| 124 |
+
if kind == 3 and i < len(w) - 1: # transpose adjacent
|
| 125 |
+
return w[:i] + w[i + 1] + w[i] + w[i + 2:]
|
| 126 |
+
# double a letter
|
| 127 |
+
return w[:i] + w[i] + w[i:]
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
def spell_pairs(seed: int, n: int) -> list[tuple[str, str]]:
|
| 131 |
+
"""`n` deterministic (prompt, correct-word) pairs from `seed`.
|
| 132 |
+
|
| 133 |
+
The prompt is ``<misspelling> => `` and the target is the correct word. ~15% are
|
| 134 |
+
the identity (already-correct) so the model learns to leave good words alone.
|
| 135 |
+
"""
|
| 136 |
+
rng = np.random.default_rng(seed)
|
| 137 |
+
idx = rng.choice(len(_WORDS), size=n, p=_WEIGHTS)
|
| 138 |
+
out: list[tuple[str, str]] = []
|
| 139 |
+
for i in idx:
|
| 140 |
+
word = _WORDS[int(i)]
|
| 141 |
+
if rng.random() < 0.15:
|
| 142 |
+
typo = word # already correct
|
| 143 |
+
else:
|
| 144 |
+
typo = _typo(rng, word)
|
| 145 |
+
if rng.random() < 0.3: # sometimes a second edit
|
| 146 |
+
typo = _typo(rng, typo)
|
| 147 |
+
out.append((f"{typo} => ", word))
|
| 148 |
+
return out
|