windowcapture
исходный код / TSF_AND_TINY_NN_DESIGN.md

TSF_AND_TINY_NN_DESIGN.md

141 строк · 15,558 байт · модуль Docs
  1# Универсальная in-place автозамена + крошечная нейросеть-«мозг»
  2
  3> Ответ на запрос: **вариант 2 (универсальная in-place правка)** по образцу системных автозамен, плюс
  4> продвинутый «мозг» на **уже существующей** супер-маленькой нейросети, и мнение об алгоритме их работы.
  5
  6---
  7
  8## 1. По образцу какой системы (три референса)
  9
 10| Система | «Мозг» (что выбирает слово) | Размер | Как доставляется в поле |
 11|---|---|---|---|
 12| **Apple iOS 17** (WWDC 2023) | трансформер-LM, правит **на каждое нажатие**, на уровне предложения, учит привычки пользователя | **~34M параметров, hidden 512** (Neural Engine) | системно (клавиатура — часть ОС); EN/FR/ES |
 13| **Google Gboard** | **FST-декодер** + нейро-«spatial model» (касание→клавиша, как акустическая модель в ASR) + LM; в 2024 «Neural Search Space» вшивает NN-LM прямо в FST на лету | сети «×10 меньше, ×6 быстрее» после итераций | системно |
 14| **Windows TSF** | — (TSF = **канал**, не мозг) | — | text-service (TIP) DLL грузится `ctfmon`-ом **в каждый процесс**, имеет доступ к буферу документа |
 15
 16**Главный вывод:** «умная автозамена крошечной сетью» (Apple) и «универсальная in-place доставка»
 17(TSF) — **ортогональны**. TSF — это *как* доставить правку в любое приложение; нейросеть — это *что*
 18исправлять. Полная система = **TSF (доставка) + крошечная LM (мозг)**.
 19
 20---
 21
 22## 2. Мнение об алгоритме их работы
 23
 24Все три — **один и тот же 3-ступенчатый noisy-channel конвейер**. Различаются лишь начинкой ступеней:
 25
 261. **Генерация кандидатов** — «что человек мог иметь в виду».
 27   - Сенсорная клавиатура → нейро-spatial model (вероятности касаний по клавишам).
 28   - Физическая клавиатура → edit-distance + соседство клавиш (ЙЦУКЕН) + фонетика.
 29   - **У нас это уже есть и сильное:** `Helpers/SpellScore.cs` + `CompactSpell.Lookup` (62% на батарее).
 30   - Кандидаты берутся **только из словаря** ⇒ система не может выдумать несуществующее слово.
 31
 322. **Контекстное переранжирование** — «что осмысленно именно здесь». Тут живёт LM, считающая
 33   P(слово | контекст): n-gram (старые) → трансформер 34M (Apple) → NN-LM-в-FST (Gboard 2024).
 34   - **У нас тут пусто** — только грубый bigram-нудж. ← **узкое место.**
 35
 363. **Решение / гейт точности** — «стоит ли вообще трогать». Авто-замена только при большом margin
 37   между лучшим и вторым кандидатом; обучение на отменах пользователя; отступление для сленга/аббревиатур.
 38   - **Это и есть вся «безотказность».** Именно консервативный гейт сделал iOS 17 «менее агрессивным».
 39   - У нас есть зачатки (precision-first gate), но без настоящей ступени 2 он слепой.
 40
 41**Моё мнение по существу:** все смотрят на нейросеть (ступень 2), но качество продукта живёт в
 42**ступенях 1 и 3**. Сеть Apple **крошечная (34M) именно потому**, что кандидаты уже ограничены словарём
 43(ступень 1), а гейт консервативен (ступень 3). Большая модель + слабый гейт = бесит и портит текст.
 44Вывод для WindowCapture: у нас сильная ступень 1 и зачаток ступени 3 — **не хватает ступени 2**.
 45Поставить туда крошечную контекстную LM = **самый высокорычажный апгрейд**, и он ставит нас в тот же
 46архитектурный класс, что и iOS 17 — только двусторонний (для *исправления* лучше) и русскоязычный.
 47
 48---
 49
 50## 3. Существующая супер-маленькая нейросеть (мозг) — РЕАЛИЗОВАНО
 51
 52**`cointegrated/rubert-tiny2`****~29M параметров** (embed 312, vocab 83828), русская, MLM.
 53Это **тот же класс размера, что и боевой автокорректор Apple (34M)**, только уже существует и русская.
 54(Ещё меньше — `cointegrated/rubert-tiny`, 12M/45МБ, для CPU-only.)
 55
 56Используется как **masked-LM переранжировщик** (НЕ генератор):
 57- подаём `левый_контекст [MASK] правый_контекст`, считаем pseudo-log-likelihood каждого кандидата
 58  из ступени 1 (по сабвордам, length-normalized, один батч-проход);
 59- **двусторонний контекст** (Apple — только левый) → для исправления лучше: видим и слово справа;
 60- **ноль галлюцинаций** — сеть только *оценивает* словарные кандидаты;
 61- **быстро** — один батч-forward на ~5 кандидатов; ~единицы мс на RTX 4080, десятки мс на CPU;
 62- это честный множитель P(слово|контекст), который мы раньше грубо заменяли биграммой.
 63
 64### Что именно сделано (ветка fix/audit-phase2)
 65- `Spell/wc_spell_server.py`: эндпоинт **`/rescore`** — lazy-load rubert-tiny2 (env `WC_RESCORE_MODEL`),
 66  батч-PLL, авто-устройство cuda/cpu с откатом. SAGE (`/`) и rescore (`/rescore`) живут в **одном**
 67  тёплом процессе; модель ступени-2 грузится только при первом обращении.
 68- `Helpers/RescoreClient.cs`: клиент `/rescore` (переиспользует процесс `SageClient` через
 69  `SageClient.EnsurePort()`); `Rescore(left,right,cands)``double[]`; `null` на любой сбой; не бросает.
 70- `Helpers/TextProcessor.cs` (`ProcessWord`): ступень 2 — после bigram-нуджа, при `Settings.ContextNnRescore`
 71  и валидном контексте, топ-6 кандидатов переранжируются по P(слово|контекст). Кандидаты только из словаря.
 72- `Models/Settings.cs`: флаг `ContextNnRescore` (по умолч. **выкл**) + Load/Save/Reset.
 73- `App/TrayApp.cs`: тумблер «Контекстная нейро-правка слов (rubert-tiny2, эксп.)» + прогрев.
 74
 75### Эмпирическая проверка (`Spell/test_rescore.py`, rubert-tiny2, CPU) — 6/8
 76Ранжирование неоднозначных пар по контексту:
 77- `мама мыла`**раму**>рому; `я ел суп`**ложкой**>лодкой; `он играл на`**гитаре**>гитари; `я выпил стакан`**воды**>моды.
 78- **склонение переключается контекстом:** `я думаю о`**тебе**, `я люблю`**тебя** (это и есть «учёт склонения» из запроса).
 79- `кот поймал`→мошь>мышь — но «мошь» **не слово**, в конвейере кандидаты только из словаря (такого кандидата нет).
 80- `мы плыли на`→ложке>лодке — **реальный предел 29M-модели** (оба слова существуют).
 81
 82Вывод: модель доказанно ловит контекст/склонение; промахи 29M ожидаемы и **смягчены тем, что NN-оценка
 83складывается с noisy-channel (ступень 1) и проходит гейт (ступень 3), а не решает единолично**. Для большей
 84точности — `WC_RESCORE_MODEL=cointegrated/rubert-base-cased` (≈178M) ценой размера/скорости.
 85
 86⚠️ Честно: флаг по умолчанию выключен; **живьём в GUI не протестировано** (computer-use отключён).
 87Эффект ступени-2 не виден в `Tools/TestSpellCheck` (тот без контекста) — проверяется отдельным
 88тестом эндпоинта `/rescore`. Доставка пока — инъекция в каретку (уже универсальна и неинвазивна).
 89
 90---
 91
 92## 4. Универсальная in-place правка (вариант 2) = TSF TIP
 93
 94> **СТАТУС: Milestone 1 СДЕЛАН** — TIP пишется на C++ (`Tip/WCTip.cpp` + `Tip/Correct.h` + `Tip/WCTip.def`),
 95> собирается (`build_tip.ps1` → `bin\WCTip.dll`, MSVC 2022 + Windows SDK, EXIT=0) и проходит **headless
 96> self-test 12/12** (`Tip/_selftest.cpp`: кодировка таблицы + class factory + создание `ITfTextInputProcessorEx`
 97> + QueryInterface по обоим интерфейсам + баланс ref-count `DllCanUnloadNow==S_OK`). Сам in-place edit через
 98> `ITfRange` не протестирован вживую (нужно TSF-приложение). Сборка/регистрация/тест — `Tip/README_TSF.md`.
 99>
100> **СТАТУС: Milestone 2 ТОЖЕ СДЕЛАН** — TIP подключён к настоящему мозгу. На границе слова `BrainCorrect`
101> (WinHTTP) POST-ит «слово\nлевый_контекст» в C#-мост (`Helpers/TipBridge.cs`, localhost TCP :8766,
102> `POST /correctword`), который зовёт `TextProcessor.CorrectWordForTip` (RulesEngine/forcedFix + noisy-channel
103> `CompactSpell` + rubert-tiny2 rescore + precision-gate — тот же мозг, что при живом наборе), и заменяет слово
104> на месте. Мост недоступен → откат на встроенную таблицу. Тумблер «TSF-мост для in-place правки»
105> (`Settings.TsfBridge`, выкл по умолч.). Собирается: C# `EXIT=0`, TIP `EXIT=0`, self-test 12/12.
106> C#-плечо моста проверено headless (`Tools/TestTipBridge.cs`): **5/5** (ответ моста == прямому вызову;
107> `превет`→`Привет` через мост — реальный мозг, не таблица). Сам in-place edit через `ITfRange` и
108> WinHTTP-вызов из C++ вживую не тестированы (нужен GUI).
109
110Чтобы править «на месте в любом приложении как системная автозамена», надо стать **TSF Text Input
111Processor (TIP)** — текст-сервис, который `ctfmon` грузит в процессы и который имеет доступ к буферу
112документа (`ITfContext`/`ITfRange`) и может менять текст без буфера обмена и без смены фокуса.
113
114**Шаги:**
1151. **C++ COM-DLL** (TIP практически всегда C++; .NET-TIP неподдерживаем/болезнен): реализовать
116   `ITfTextInputProcessor(Ex)`, `ITfThreadMgrEventSink`, `ITfTextEditSink`, `ITfKeyEventSink`.
1172. Регистрация языкового профиля (`ITfInputProcessorProfiles`) + CLSID в реестре → пользователь
118   выбирает «WindowCapture» как метод ввода (как IME).
1193. На правках/границах слов — читать диапазон через `ITfRange`, прогонять через **тот же** мозг
120   (ступени 1–3 выше; вызов нашего тёплого сервера), писать обратно через `ITfRange::SetText`
121   в составе edit-session (атомарно, корректно для undo приложения).
1224. Подсказки/реконверсия через UI TSF; учёт композиции (важно для CJK, нам — упрощённо).
123
124**Честная оценка стоимости/риска:**
125- Это **самый рискованный и крупный компонент проекта**: отдельный C++/COM-проект, системный метод
126  ввода, регистрация в реестре, тестирование только живьём.
127- **Не тестируется без живого GUI** (computer-use сейчас отключён).
128- Совместимость: TSF-aware приложения — да; чистый Win32 EDIT без TSF — деградация на keystroke-доставку.
129
130**Рекомендация по последовательности:**
1311. **Сейчас:** мозг (ступень 2, rubert-tiny2) на текущей доставке keystroke-в-каретку — уже универсально
132   и неинвазивно, даёт основной прирост качества, дни а не недели, без рискованного системного компонента.
1332. **Потом, по «го»:** TSF TIP как отдельный трек, когда keystroke-доставки окажется мало на практике.
134
135---
136
137## Источники
138- Apple iOS 17 transformer autocorrect — [NPR](https://www.npr.org/2023/06/07/1180791069/apple-autocorrect-ducking), [Michael Tsai blog (34M, hidden 512, per-keystroke)](https://mjtsai.com/blog/2023/09/18/apples-new-transformer-powered-predictive-text-model/), [MacRumors](https://www.macrumors.com/guide/ios-17-keyboard/)
139- Gboard — [The Machine Intelligence Behind Gboard (Google Research)](https://research.google/blog/the-machine-intelligence-behind-gboard/), [Neural Search Space in Gboard Decoder (arXiv 2410.15575)](https://arxiv.org/abs/2410.15575)
140- Windows TSF — [Microsoft Learn: Text Services Framework](https://learn.microsoft.com/en-us/windows/win32/tsf/text-services-framework), [MS Edge TSF1 explainer](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/TSF1/explainer.md)
141- rubert-tiny2 — [cointegrated/rubert-tiny2 (HF)](https://huggingface.co/cointegrated/rubert-tiny2), [cointegrated/rubert-tiny (12M/45MB)](https://huggingface.co/cointegrated/rubert-tiny)