docs(architecture): document specialized Qwen2.5-0.5B + CTranslate2 fine-tuning architecture

This commit is contained in:
2026-10-09 15:34:06 +03:00
parent 7871191c90
commit 789960dc74
2 changed files with 110 additions and 0 deletions
+15
View File
@@ -161,3 +161,18 @@ CREATE TABLE IF NOT EXISTS user_grammar_weaknesses (
- [ ] Оффлайн-кэширование аудио предложений в `data/audio_cache/` со сжатием в Opus и автоочисткой по TTL 7 дней (Zero Bloat). - [ ] Оффлайн-кэширование аудио предложений в `data/audio_cache/` со сжатием в Opus и автоочисткой по TTL 7 дней (Zero Bloat).
- [ ] Фоновый экспорт главы в аудиокнигу для дороги и прогулок. - [ ] Фоновый экспорт главы в аудиокнигу для дороги и прогулок.
- [ ] Интерактивный Shadowing (прослушивание $\rightarrow$ повтор в микрофон $\rightarrow$ клиентская проверка). - [ ] Интерактивный 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.
@@ -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.