- effort-estimate-report.md: updated metrics (~182 files, ~40K LOC), added enhancement breakdown, updated comparative analysis
- spec.md: status → Core + Enhancement complete, added Enhancement Implementation Notes
- plan.md: all enhancement components marked ✅, metrics updated
- tasks.md: all 26 enhancement tasks (T135-T160) → [x], closure summary updated
- quickstart.md: added §10 Direct Database Insert flow
- data-model.md, research.md, contracts/modules.md, ux_reference.md, spec.ru.md, checklists/requirements.md: dates, statuses, metrics aligned
- all documents now reflect 2026-06-11 state: ~174-182 files, ~39-40K LOC, ~580 pytest, ~68 vitest
265 lines
19 KiB
Markdown
265 lines
19 KiB
Markdown
# Спецификация: Сервис LLM-перевода табличных данных
|
||
|
||
**Дата**: 2026-05-18 (актуализация: 2026-06-11)
|
||
**Назначение**: Передача сторонней команде для оценки трудозатрат
|
||
**Фокус**: только требования к конечному результату, без технологий
|
||
**Статус**: Implemented ✅ (~174 файла, ~39 400 строк кода). Core + Enhancement (прямой INSERT в БД + настройки подключений) complete.
|
||
|
||
---
|
||
|
||
## 1. Фронтенд (Web-интерфейс)
|
||
|
||
### 1.1 Управление задачами перевода (Jobs)
|
||
|
||
- Список всех задач перевода с фильтрацией по датасорсу, целевой таблице, статусу.
|
||
- Создание новой задачи перевода:
|
||
- Выбор Superset-датасорса (источник данных).
|
||
- Выбор колонки для перевода (одна, обязательная).
|
||
- Выбор колонок контекста (ноль или более) — их значения передаются LLM для повышения качества.
|
||
- Выбор ключевых колонок (одна или более, composite key) — по ним данные будут сопоставляться при вставке в целевую таблицу.
|
||
- Указание целевой таблицы и целевой колонки.
|
||
- Выбор одного или нескольких языков перевода.
|
||
- Редактирование системного промпта (шаблон сообщения LLM).
|
||
- Выбор LLM-провайдера и модели.
|
||
- Прикрепление одного или нескольких справочников терминов.
|
||
- Указание стратегии UPSERT (skip_existing / overwrite / insert).
|
||
- Редактирование, копирование, удаление задачи.
|
||
|
||
### 1.2 Превью (Quality Gate)
|
||
|
||
- Запуск превью на ограниченной выборке строк (1–100, по умолчанию 10).
|
||
- Отображение source-строк, контекста, обнаруженного языка оригинала и перевода на каждый целевой язык — рядом, в табличном виде.
|
||
- Approve / Edit / Reject для каждой строки превью.
|
||
- Повторный запуск превью с изменёнными настройками (промпт, язык, провайдер).
|
||
- Подтверждение превью (accept) — открывает возможность полного прогона.
|
||
- Предупреждение о стоимости перед запуском полного прогона (оценка токенов и цены).
|
||
|
||
### 1.3 Выполнение (Run)
|
||
|
||
- Запуск полного прогона (только после accepted превью).
|
||
- Живой индикатор прогресса: сколько строк обработано, успешно, с ошибками, процент выполнения.
|
||
- Возможность отмены прогона.
|
||
- Построчный просмотр результатов после завершения:
|
||
- Исходный текст, контекст, перевод по каждому языку.
|
||
- Статус каждой строки (OK / ошибка / пропущена).
|
||
- Сгенерированный SQL (для аудита).
|
||
- Статус вставки в Superset.
|
||
- Повтор проблемных batch-ей (retry failed).
|
||
- Inline-редактирование любой переведённой строки в результатах.
|
||
- Bulk Find & Replace по результатам прогона (с превью замен).
|
||
|
||
### 1.4 Очередь и планировщик
|
||
|
||
- Возможность настроить расписание для задачи:
|
||
- Одноразовый запуск в будущем.
|
||
- Интервальный (каждые N минут/часов/дней).
|
||
- Cron-выражение с выбором часового пояса.
|
||
- Scheduled-прогон создаёт новый Run и выполняет полный цикл.
|
||
- Для scheduled-прогонов: new-key-only (только новые строки, которых нет в последнем успешном прогоне).
|
||
- Если последний успешный прогон старше 90 дней — fallback на полный прогон.
|
||
- Защита от overlap: если предыдущий scheduled-прогон ещё выполняется — пропуск или очередь (1 в очереди).
|
||
- После N последовательных ошибок (по умолч. 3) — автоотключение расписания и уведомление.
|
||
|
||
### 1.5 История и аудит
|
||
|
||
- Список всех прогонов с деталями: датасорс, целевая таблица, кол-во строк, статус, кто запустил.
|
||
- Детальный просмотр прогона: configuration snapshot, промпт, результаты по строкам, сгенерированный SQL, Superset execution reference.
|
||
- Фильтрация по датасорсу, целевой таблице, дате, статусу.
|
||
|
||
### 1.6 Справочники терминов (Dictionaries)
|
||
|
||
- Создание справочника.
|
||
- Добавление пар «термин оригинала → перевод» с указанием языка оригинала и языка перевода.
|
||
- Импорт из CSV/TSV с превью, разрешением конфликтов (overwrite / keep / skip).
|
||
- Inline-редактирование, удаление записей.
|
||
- Прикрепление справочника к задаче перевода.
|
||
- Приоритет справочников (низкий номер = выше приоритет).
|
||
|
||
### 1.7 Коррекция и обратная связь
|
||
|
||
- Из любого завершённого прогона: клик на ячейку перевода → inline-редактирование.
|
||
- После редактирования: кнопка «Отправить в справочник».
|
||
- Popup с предзаполненными: исходный термин, старый перевод, новый перевод, язык оригинала (из строки), язык перевода (из колонки), context_data (из строк, автоматически), usage notes (вручную).
|
||
- Выбор целевого справочника (фильтр по языковой паре).
|
||
- Bulk-режим: массовое редактирование и отправка нескольких терминов за раз.
|
||
- Конфликт при повторной отправке: overwrite / keep existing / cancel.
|
||
|
||
---
|
||
|
||
## 2. Оркестратор (Run Lifecycle)
|
||
|
||
### 2.1 Жизненный цикл прогона
|
||
|
||
1. **Создание**: формируется snapshot конфигурации задачи + snapshot прикреплённых справочников.
|
||
2. **Планирование**: определяются целевые языки, размер batch-ей (динамически, по token budget), порядок обработки.
|
||
3. **Выполнение**:
|
||
- Выборка source-строк: для scheduled new-key-only — только новые ключи; для manual — все строки.
|
||
- Разбивка на batch-и.
|
||
- Для каждого batch:
|
||
a. Запрос к LLM с промптом, контекстом, отфильтрованными записями справочников.
|
||
b. Парсинг структурированного JSON-ответа.
|
||
c. Валидация: все ли строки batch переведены, нет ли дубликатов.
|
||
d. Если ошибка — запись в TranslationBatch как failed.
|
||
- После всех batch-ей: финализация (статус, error_message если все строки упали).
|
||
4. **Вставка (Insert phase)**:
|
||
- Генерация UPSERT SQL под диалект БД (определяется динамически из Superset connection).
|
||
- Отправка SQL через Superset SQL Lab API.
|
||
- Polling статуса выполнения.
|
||
- Запись результата (query reference, статус, ошибка).
|
||
5. **Завершение**: запись метрик, отправка уведомления (опционально), авто-dismiss через N секунд на UI.
|
||
|
||
### 2.2 Snapshot isolation
|
||
|
||
- Все прогоны используют snapshot конфигурации и справочников, взятый на момент старта.
|
||
- Изменения конфигурации во время выполнения прогона НЕ влияют на текущий прогон.
|
||
|
||
### 2.3 Retry
|
||
|
||
- Возможность повторно запустить только failed batch-и (не трогая успешные).
|
||
- При перезапуске можно сменить LLM-провайдера.
|
||
|
||
### 2.4 Data retention
|
||
|
||
- 90 дней — полная детализация (source-строки, переводы, SQL).
|
||
- После 90 дней — агрегация: только метаданные прогона и агрегированные метрики.
|
||
- Перед прунингом — сохранение cumulative snapshot метрик.
|
||
|
||
---
|
||
|
||
## 3. Перевод (LLM)
|
||
|
||
### 3.1 Multi-language
|
||
|
||
- Задача поддерживает N целевых языков (массив, а не один язык).
|
||
- LLM получает исходный текст один раз на batch и возвращает переводы для ВСЕХ целевых языков в одном JSON-ответе.
|
||
- Не нужно N отдельных LLM-вызовов.
|
||
|
||
### 3.2 Автоопределение языка оригинала
|
||
|
||
- LLM определяет язык каждой строки автоматически.
|
||
- Возвращает BCP-47 tag (например, "fr", "de", "und" для неопределённого).
|
||
- Пользователь НЕ указывает язык оригинала вручную.
|
||
|
||
### 3.3 Reference copy
|
||
|
||
- Если язык оригинала включён в список целевых языков — «переводом» для него будет исходный текст (verification copy).
|
||
|
||
### 3.4 Dictionary injection
|
||
|
||
- Перед каждым LLM-запросом выполняется per-batch фильтрация справочника:
|
||
- Отбираются только те записи, чей source_term встречается (case-insensitive substring match) хотя бы в одной строке batch-а.
|
||
- Учитывается языковая пара (source_language записи === detected_language строки, target_language записи === языка промпта).
|
||
- Отфильтрованные записи вставляются в промпт как authoritative glossary.
|
||
- Записи с совпадающим контекстом (context_data) помечаются priority.
|
||
|
||
### 3.4 Превью
|
||
|
||
- Quality gate, а не построчное утверждение.
|
||
- Принятие превью = одобрение настроек (промпт, языки, справочники), после чего полный прогон обрабатывает ВСЕ строки.
|
||
- Редактуры на уровне превью переносятся в полный прогон для тех же строк (carry-forward).
|
||
- Rejected строки превью исключаются из полного прогона (только если были в sample).
|
||
|
||
---
|
||
|
||
## 4. Справочники (Dictionaries)
|
||
|
||
### 4.1 Структура
|
||
|
||
- Справочник содержит пары «термин оригинала → перевод».
|
||
- Каждая запись имеет:
|
||
- source_term — термин на языке оригинала.
|
||
- target_translation — корректный перевод.
|
||
- source_language (BCP-47) — язык термина.
|
||
- target_language (BCP-47) — язык перевода.
|
||
- context_data (JSON, опционально) — значения контекстных колонок из строки, где был найден термин.
|
||
- usage_notes (текст, опционально) — заметки по использованию.
|
||
- has_context (boolean) — есть ли контекстные данные.
|
||
|
||
### 4.2 Привязка к задаче
|
||
|
||
- К задаче можно привязать несколько справочников.
|
||
- Порядок приоритета: чем меньше номер, тем выше приоритет.
|
||
- При конфликте (один source_term в нескольких справочниках) побеждает высший приоритет.
|
||
|
||
### 4.3 Per-batch фильтрация
|
||
|
||
- В каждый LLM-запрос включаются ТОЛЬКО те записи справочника, чей source_term:
|
||
- Встречается хотя бы в одной строке batch-а (substring match).
|
||
- source_language совпадает с detected_language строки.
|
||
- target_language совпадает с языком текущего промпта.
|
||
- Размер справочника не ограничен (фильтрация не даёт промпту расти бесконечно).
|
||
|
||
### 4.4 Контекстная приоритизация
|
||
|
||
- Если context_data записи совпадает с контекстом строки batch-а (Jaccard similarity > 50%) — запись помечается как priority_context.
|
||
- Priority-записи перечисляются первыми с пометкой # PRIORITY.
|
||
- Это soft signal для LLM, не хард-фильтр.
|
||
|
||
### 4.5 Коррекция через результаты прогонов
|
||
|
||
- Из любого завершённого прогона можно отправить исправление в справочник.
|
||
- context_data заполняется автоматически из строки, где был найден термин.
|
||
- Пользователь может отредактировать context_data, добавить usage_notes, убрать контекст.
|
||
- Если context_data превышает 500 токенов — обрезается с пометкой.
|
||
|
||
---
|
||
|
||
## 5. Обработка ошибок (Edge Cases)
|
||
|
||
- NULL в колонке перевода → пропуск строки с логированием.
|
||
- NULL в ключевой колонке → reject строки (не может быть вставлена).
|
||
- LLM вернул неожиданный формат → запрос структурированного JSON, валидация, failed batch.
|
||
- Все строки batch упали → run.error_message с деталями.
|
||
- Редактирование задачи во время выполнения прогона → не влияет на текущий прогон (snapshot isolation).
|
||
- Удаление справочника, привязанного к активной задаче → запрет, предупреждение.
|
||
- Scheduled прогон при недоступном датасорсе → запись ошибки, попытка следующего триггера.
|
||
- Неподдерживаемый диалект БД → блокировка выполнения с сообщением.
|
||
- Вставка через Superset SQL Lab вернула ошибку → insert_status = failed, error_message заполнен.
|
||
- Прямое подключение к БД недоступно (auth error, timeout) → insert_status = failed, [Retry Insert], данные перевода сохранены.
|
||
- Удаление подключения БД, используемого активными задачами → блокировка с указанием имён задач.
|
||
- Изменение пароля подключения БД → прозрачное перешифрование, активные задачи продолжают работу.
|
||
|
||
---
|
||
|
||
## 6. Прямой INSERT в БД (новое)
|
||
|
||
### 6.1 Выбор метода вставки
|
||
|
||
- При конфигурации задачи перевода — выбор метода вставки: «Superset SQL Lab API» (по умолчанию) или «Прямое подключение к БД».
|
||
- При выборе прямого подключения — выбор сохранённого подключения из выпадающего списка.
|
||
- Список подключений фильтруется по диалекту БД (только совместимые подключения).
|
||
- При отсутствии подключений — ссылка в Settings → Connections.
|
||
|
||
### 6.2 Прямое выполнение
|
||
|
||
- SQL генерируется тем же `SQLGenerator` (без дублирования логики).
|
||
- Выполняется через нативные драйверы (asyncpg / clickhouse-connect).
|
||
- Результат: строки вставлены, время выполнения, статус.
|
||
- Superset query reference отсутствует (поле пустое).
|
||
- Ошибка подключения → insert_status = failed, кнопка [Retry Insert].
|
||
|
||
### 6.3 Аудит
|
||
|
||
- `insert_method` сохраняется на `TranslationRun` (sqllab / direct_db).
|
||
- `connection_snapshot` (JSON: name, dialect, host, port, database — без пароля) сохраняется на `TranslationRun` для аудита.
|
||
- Snapshot переживает удаление подключения.
|
||
|
||
---
|
||
|
||
## 7. Настройки подключений БД (новое)
|
||
|
||
### 7.1 Управление подключениями
|
||
|
||
- Новая вкладка «Connections» в Settings.
|
||
- Список подключений: название, хост, порт, БД, диалект, дата, счётчик «используется N задачами».
|
||
- Создание: название, хост, порт, БД, пользователь, пароль (шифруется), диалект, доп. параметры.
|
||
- Редактирование: все поля, пароль — masked (можно заменить).
|
||
- Удаление: блокируется, если подключение используется активными задачами.
|
||
- Тест подключения: `SELECT 1`, результат с latency или ошибкой.
|
||
|
||
### 7.2 Безопасность
|
||
|
||
- Пароль шифруется через `EncryptionManager` (Fernet).
|
||
- В API-ответах пароль всегда маскирован (`********`).
|
||
- Принимается при create/update, никогда не возвращается в plaintext.
|