Skip to main content

sakhaspell — спелчекер якутского языка

sakhaspell.michill.ru — попробовать в браузере

Проверка орфографии для якутского (саха тыла). Два слоя: словарный работает офлайн на CPU, нейросетевой добавляет контекст.

Спелчекера для якутского до этого не было. Есть морфология — apertium-sah и yakutmorph, обе GPL-3 — но hunspell-словаря, расширения для редакторов и нейрокорректора нет; ни Яндекс.Спеллер, ни LanguageTool якутский не поддерживают. Разбор поля — docs/research.md.

Что умеет

$ python -m sakhaspell check "Ого уорэгэ кисиэхэ сана кыагы биэрэр"
1:0   Ого      →  Оҕо      [lexicon]   ещё: Ооо, Оо, Ошо
1:4   уорэгэ   →  үөрэҕэ   [lexicon]   ещё: үөрэнэ, үөрэрэ, үрэҕэ
1:11  кисиэхэ  →  киһиэхэ  [lexicon]   ещё: кимиэхэ, киниэхэ, биһиэхэ
1:19  сана     →  саҥа     [lexicon]   ещё: аана, саха, сара
1:24  кыагы    →  кыаҕы    [lexicon]   ещё: кыаны, кыргы, кыаһы

Три сценария:

  • восстановление ҕ ҥ ө һ ү — текст набран с русской раскладки;
  • постобработка OCR и ASR — машинные искажения (см. оговорку ниже);
  • проверка при наборе — подчёркивание с подсказками.

Результаты

SakhaSpellBench, отложенный test, 800 предложений на задачу. Метрики пословные, как в SAGE.

задача F1 (словарь) F1 (+ тэггер) детекция ложные
clean — чистый текст — — — 1.33%
denorm_full — без раскладки 93.05% 96.51% 99.44% 1.51%
denorm_mixed — как пишут 92.78% 95.87% 99.67% 1.68%
mixed — опечатки поверх 87.68% 90.23% 96.13% 1.46%
typo — опечатки 76.30% 76.00% 86.39% 1.35%
real — ошибки из корпуса 67.15% 66.94% 65.35% 1.78%

Тэггер добавляет 3.5 пункта на деноминализации и не стоит ничего в ложных срабатываниях: 1.33% с ним и без него. На задачах опечаток он корректно бездействует — там ошибка не в спецбуквах.

Главная колонка — последняя. Ложные срабатывания на заведомо правильном тексте: 1.33% против 8.96% у apertium-sah (LREC 2022) и 4.89% помеченных токенов у bashspell, где ~46% помеченного ложно. Именно эта метрика решает, оставит пользователь спелчекер включённым или нет.

Скорость на CPU: проверка слова 0.0016 мс (у bashspell 0.17–0.21 мс), подсказки 51 мс медиана (у bashspell 115–132 мс), 392 слова/с на сплошном тексте. Память 470 МБ. Тэггер — 10.8M параметров, посимвольный F1 0.9919.

Оговорка про ASR

Задача постобработки ASR собрана из настоящих выходов распознавателя проекта STT, и чекер на ней проваливается: F1 1.9%. Причина не в чекере — эталонные расшифровки грязнее, чем выход модели. В 50.9% расхождений не является словом именно эталон (против 13.6% у гипотезы), и 19.1% эталонов — деноминализованные написания (против 0.7%).

Полный аудит 8 417 расшифровок: 46.0% содержат орфографическую ошибку, 6.74% всех слов. Артефакты для починки — data/asr_audit/ref_issues.jsonl и top_bad_words.tsv. Для проекта ASR это значит, что WER завышен: модель штрафуется за слова, которые написала правильно.

Устройство

L0  нормализация      NFC, невидимые символы, чужие кириллические буквы
                      (ѳ→ө, ң→ҥ, ғ→ҕ), латинские гомоглифы внутри слова
L1  словарь           301k словоформ из корпуса + фильтр теней искажения,
                      кандидаты через префиксное дерево со взвешенным
                      расстоянием, CPU, миллисекунды
L2  тэггер            посимвольная разметка: для каждой буквы решает, это «г»
                      или «ҕ». Неавторегрессивный, 10.8M параметров

Три решения, которые определили результат:

Первичный акцептор — словоформы, а не FST. У apertium-sah точность 98.52%, но наивное покрытие на газетах 91.04%: FST-акцептор подчёркивает 9% правильного текста. Корпусный лексикон даёт 1.33%.

Фильтр теней искажения. Систематическая ошибка письма без раскладки проникает в лексикон: сана (378 вхождений), киси (21), ого (17) попали в словарь, потому что так пишут во всех источниках сразу, и правило «подтверждено двумя источниками» против этого бессильно. Отдельная проверка находит формы, которые являются искажением гораздо более частой формы, и убирает их. Это дало +27.7 пункта F1 и обрушило долю «невидимых без контекста» ошибок деноминализации с 41.2% до 1.5%.

L2 — разметка, а не переписывание. Задача восстановления ҕҥөһү посимвольная по своей природе, и разметка ей точно соответствует: модель физически не может изменить символ, которому предсказала «оставить». Seq2seq переписывает текст целиком и правит то, о чём не просили.

Подробности с цифрами — docs/experiments.md.

Установка

pip install sakhaspell

Словарь на 300 304 словоформы встроен в пакет — скачивать и настраивать нечего. У словарного слоя нет зависимостей вообще, только стандартная библиотека.

sakhaspell check "Ого уорэгэ кисиэхэ"       # показать ошибки
sakhaspell fix --file статья.txt --in-place # исправить на месте
sakhaspell repl                             # интерактивно
cat текст.txt | sakhaspell fix > исправлено.txt

Из Python:

from sakhaspell import SpellChecker, Lexicon

checker = SpellChecker(Lexicon.load())
checker.correct("Ого уорэгэ кисиэхэ")       # 'Оҕо үөрэҕэ киһиэхэ'

for issue in checker.check("Мин огом онгор"):
    print(issue.token.start, issue.token.text, issue.best)

Позиции правок в исходном тексте — для подсветки в редакторе:

from sakhaspell import Pipeline

p = Pipeline()
for c in p.corrections("Ого уорэгэ кисиэхэ"):
    print(c.start, c.end, c.before, "→", c.after, c.alternatives)

Контекстная модель

Даёт +3.5 пункта F1 на восстановлении ҕҥөһү. Чекпоинт в пакет не входит: обучается за 33 минуты на одной H200 через scripts/train_tagger.py.

pip install "sakhaspell[tagger]"
sakhaspell --tagger runs/tagger_v2 check "текст"

HTTP-сервис

pip install "sakhaspell[server]"
uvicorn sakhaspell.server:app --port 8080

POST /check — проверка текста с позициями, POST /spell — быстрый вердикт по словам для подсветки, POST /suggest — подсказки по требованию. Разнесено намеренно: проверка стоит 0.0016 мс на слово, подсказки — 51 мс.

Сборка с нуля

Данные и обучение — на поде H200 (docs/experiments.md). Корпус — 8.2 млн предложений из 18 источников.

python scripts/prep_sentences.py  --corpus corpus_sah.jsonl --out data/sent --procs 90
python scripts/build_lexicon.py   --sent data/sent --out data/lexicon
python scripts/mine_errors.py     --sent data/sent --lexicon data/lexicon --out data/errors
python scripts/find_shadows.py    --lexicon data/lexicon --out data/lexicon
python scripts/build_bench.py     --lexicon data/lexicon --errors data/errors --out data/bench
python scripts/eval_bench.py      --lexicon data/lexicon --bench data/bench --split dev
python scripts/train_tagger.py    --sent data/sent --out runs/tagger_v2 --steps 30000

Готовый словарь лежит в sakhaspell/data/ сжатым и подхватывается сам; Lexicon.load("свой/каталог") берёт другой.

Сборка и выкладка

Что Когда Куда
test.yml push и PR pytest на 3.10–3.13, плюс macOS и Windows
publish.yml релиз с тегом PyPI через доверенную публикацию
deploy.yml изменения в docs/ GitHub Pages и sakhaspell.michill.ru

Тесты проверяют не только код: отдельный шаг грузит встроенный словарь и прогоняет через него фиксированные пары, чтобы порча данных не проехала молча.

Страница

docs/ — статическая страница: sakhaspell.michill.ru, зеркало на GitHub Pages. Словарь пережат во фронт-кодированный формат и весит 864 КБ на все 300 тысяч форм, поэтому проверка идёт целиком в браузере и текст никуда не отправляется. Пересборка:

python scripts/build_web_assets.py --lexicon data/lexicon --out docs/data

Что не работает

  • Постобработка ASR. Не потому, что чекер плох: эталонные расшифровки оказались грязнее выхода модели (см. оговорку выше).
  • Постобработка OCR не проверена — нет пар «выход против эталона». Модель ошибок OCR добыта (52 015 пар), но проверить не на чем.
  • Опечатки — 76% F1. Ошибку видим в 86% случаев, но верный вариант ставим первым не всегда: ранжирование учитывает цену правки и частоту, но не контекст.
  • Пунктуация и регистр не восстанавливаются.

Лицензии

Код проекта свой. apertium-sah и yakutmorph — GPL-3, в рантайме не используются: лексикон построен из корпуса, поэтому результат не заражается.

Release files for sakhaspell 0.1.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 sakhaspell 0.1.0
File Size Uploaded
sakhaspell-0.1.0.tar.gz 7.7 MB Details

Built distribution (wheel)

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

Total release size: 15.3 MB

Release files / sakhaspell-0.1.0.tar.gz

Download URL sakhaspell-0.1.0.tar.gz
Size 7.7 MB
Tags Source
SHA-256 checksum
How to use checksums
d3d36db793d391a2c30e71a550425c1a540ae3e02a02a8e04eaadb39394bc007
BLAKE2b-256 checksum
How to use checksums
b50bfaf34bd25aeb4a54278c9af6f03e1402bf6b89d2379b1aa3cd5bab129df3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

Release files / sakhaspell-0.1.0-py3-none-any.whl

Download URL sakhaspell-0.1.0-py3-none-any.whl
Size 7.6 MB
Tags Python 3
SHA-256 checksum
How to use checksums
18778c63ab57de1f2ed1c0776c399d0f0348467b002bafbcfef577a6c48a8c90
BLAKE2b-256 checksum
How to use checksums
00b1026e2bd9ada7a84011e1d28f53712520d453eab7599c969da5624258305c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.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