diff --git a/AI_TODO.md b/AI_TODO.md index 35ba4c6..b963f67 100644 --- a/AI_TODO.md +++ b/AI_TODO.md @@ -161,3 +161,18 @@ CREATE TABLE IF NOT EXISTS user_grammar_weaknesses ( - [ ] Оффлайн-кэширование аудио предложений в `data/audio_cache/` со сжатием в Opus и автоочисткой по TTL 7 дней (Zero Bloat). - [ ] Фоновый экспорт главы в аудиокнигу для дороги и прогулок. - [ ] Интерактивный Shadowing (прослушивание $\rightarrow$ повтор в микрофон $\rightarrow$ клиентская проверка). + +--- + +### Этап 8: 🧠 Специализированная микро-модель перевода (Qwen2.5-0.5B + CTranslate2) +- [ ] Полная архитектурная спецификация: `docs/architecture/specialized-translation-model.md` +- [ ] **Цель**: Разгрузить сервер, снизить задержку читалки до 100–150 мс и избавиться от сетевого оверхеда Ollama при чтении. +- [ ] **Разделение ролей**: + - Читалка (контекстный перевод предложений + целевое слово в JSON): `Qwen2.5-0.5B-Instruct` через CTranslate2 (in-process в Python, ~350 МБ RAM). + - Итоги урока (Debrief): `Qwen2.5-3B` on-demand (Ollama `keep_alive: 5m`) или детерминированный движок Мерфи. +- [ ] **Пайплайн реализации**: + - [ ] Сборка синтетического датасета `train.jsonl` (1500–3000 пар `(sentence, word, context, hints) -> JSON`). + - [ ] LoRA-дообучение на CPU VPS (AMD Ryzen 9 5950X, ~25–45 мин). + - [ ] Слияние и конвертация в CTranslate2 `int8` (`ct2-transformers-converter`). + - [ ] Прямая интеграция `ctranslate2.Generator` в `app/ai.py` с сохранением кэша SQLite. + diff --git a/docs/architecture/specialized-translation-model.md b/docs/architecture/specialized-translation-model.md new file mode 100644 index 0000000..2051546 --- /dev/null +++ b/docs/architecture/specialized-translation-model.md @@ -0,0 +1,95 @@ +# 🧠 Специализированная модель перевода и архитектура ИИ (Qwen2.5-0.5B + CTranslate2) + +Архитектурное решение по переходу на узкоспециализированную модель перевода для интерактивной читалки книг и разделению ролей ИИ в платформе Study Qpid Pro (`study.qpid.pro`). + +--- + +## 🎯 Архитектурный выбор: Qwen2.5-0.5B-Instruct vs MarianMT (Helsinki-NLP) + +Исследованы два класса узких моделей для локального размещения на сервере (AMD Ryzen 9 5950X, 6 vCPU, без GPU, ~7.6 GB RAM доступно): + +| Критерий | Helsinki-NLP/opus-mt-en-ru (77M) | Qwen2.5-0.5B-Instruct (~490M) | +| :--- | :--- | :--- | +| **Архитектура** | Seq2Seq (Encoder-Decoder) | Causal LLM (Decoder-only) | +| **Выходной формат** | Только сплошной текст | Строгий JSON (`sentence_ru` + `word_meaning`) | +| **Выделение значения слова** | Требует внешнего aligner / словаря | Выделяет контекстное значение напрямую | +| **Поддержка контекста абзаца**| Слабая (обучена по предложениям) | Отличная (учитывает промпт и контекст) | +| **Инференс на CPU (CTranslate2)**| 10–20 мс | 100–150 мс | +| **Потребление RAM** | ~150 МБ | ~350–400 МБ | + +**Выбор**: **`Qwen2.5-0.5B-Instruct`** с дообучением под задачу контекстного перевода предложений и извлечения целевых слов в структурированный JSON. + +--- + +## 🏗️ Разделение ответственности компонентов (Clean Separation of Concerns) + +1. **Читалка книг (На лету)**: + - **Модель**: Дообученная `Qwen2.5-0.5B-Instruct`. + - **Движок**: **CTranslate2** (`int8`), загруженный in-process прямо в Python-память FastAPI (`app/ai.py`). + - **Задержка**: ~100–150 мс (без оверхеда на HTTP/сокеты/Docker). + - **Задача**: `(sentence, target_word, context, dict_hints) -> JSON {"sentence_ru", "word_meaning"}`. + +2. **Итоговый разбор урока (Debrief)**: + - **Модель**: `Qwen2.5-3B` через Ollama с параметром `keep_alive: "5m"` (подгружается по запросу раз в 20–30 минут, после чего выгружается из памяти). + - **Резерв**: Мгновенный детерминированный движок `generate_deterministic_debrief()` (0 мс, по формулам Мерфи). + +3. **Синтез речи (Озвучка)**: + - **Движок**: Piper Neural TTS (ONNX VITS). + - **Статус**: 100% автономен, не зависит от LLM, задержка 20–40 мс. + +4. **Генерация и проверка тестов**: + - **Принцип**: 100% алгоритмический детерминизм (каталог 142 юнитов Мерфи, алгоритм SM-2/FSRS в SRS, алгоритмический майнер предложений из книг). Нейросети к проверке тестов намеренно не привлекаются для исключения галлюцинаций. + +--- + +## ⚡ Преимущества CTranslate2 над HTTP-демоном Ollama + +1. **In-Process инференс**: `import ctranslate2` прямо в бэкенде. Ноль оверхеда на сеть, TCP-сокеты и сериализацию между контейнерами. +2. **Низкоуровневая оптимизация**: Скомпилирован под AVX2 / FMA для AMD Ryzen. +3. **Квантование int8**: Минимальный расход RAM (~350 МБ) при сохранении 99% точности. + +--- + +## 🛠️ Пайплайн локального дообучения (Fine-Tuning) на VPS + +Поскольку модель имеет всего ~490M параметров, её можно дообучить прямо на процессоре сервера без GPU: + +### 1. Формат обучающего датасета (`train.jsonl`, 1500–3000 примеров) +```json +{ + "messages": [ + { + "role": "system", + "content": "Ты — переводчик художественной литературы. Переведи указанное предложение и выдели значение целевого слова. Ответь строго JSON: {\"sentence_ru\": \"...\", \"word_meaning\": \"...\"}" + }, + { + "role": "user", + "content": "Контекст абзаца: Mr. Dursley stopped dead. Fear flooded him.\nПредложение: He stared at the people in cloaks.\nЦелевое слово: cloaks\nСловарные подсказки: cloak — плащ, мантия" + }, + { + "role": "assistant", + "content": "{\"sentence_ru\": \"Он уставился на людей в мантиях.\", \"word_meaning\": \"мантиях\"}" + } + ] +} +``` + +### 2. Дообучение через PyTorch CPU + PEFT (LoRA) +- Инструменты: `torch (cpu)`, `transformers`, `peft`, `trl`. +- Параметры: `r=16`, `lora_alpha=32`, `target_modules=["q_proj", "k_proj", "v_proj", "o_proj"]`. +- Время обучения на 6 ядрах Ryzen 9 5950X: **~25–45 минут**. +- Расход RAM в процессе: **~3.5–4.5 ГБ** (на сервере доступно ~7.6 ГБ). + +### 3. Конвертация в CTranslate2 +```bash +# 1. Слияние адаптера LoRA с базовой моделью: +python3 merge_lora.py --base Qwen/Qwen2.5-0.5B-Instruct --adapter ./final_adapter --output ./qwen-0.5b-merged + +# 2. Конвертация в int8 CTranslate2 модель: +ct2-transformers-converter --model ./qwen-0.5b-merged \ + --output_dir /home/ai-projects/services/study.qpid.pro/models/qwen05b-ct2 \ + --quantization int8 +``` + +### 4. Подключение в `app/ai.py` +Заменяем сетевой HTTP-клиент к Ollama для читалки на прямой вызов `ctranslate2.Generator`, сохранив кэширование SQLite.