fix: make OCR portable and reliable across AMD64 and ARM64 (#519)

* fix: make OCR portable and reliable

* fix: harden OCR installation portability

* fix: pin OCR partials across downloads

* fix: make OCR execution reliably asynchronous

* fix: harden OCR portability and docs routes

* fix: preserve decoder and docs safeguards
This commit is contained in:
SnapOtter
2026-07-15 03:34:24 +08:00
committed by GitHub
parent 58121f205f
commit 991c981529
409 changed files with 67151 additions and 8076 deletions
+6 -6
View File
@@ -1,8 +1,8 @@
---
description: "Структура монорепозитория, архитектура приложений и пакетов, жизненный цикл запроса и потребление ресурсов SnapOtter."
i18n_source_hash: 9e8f80499a37
i18n_provenance: human
i18n_output_hash: c47f9f3041c4
i18n_source_hash: 733cb3c10884
i18n_provenance: human
---
# Архитектура {#architecture}
@@ -36,13 +36,13 @@ snapotter/
### `@snapotter/ai` {#snapotter-ai}
Прослойка, которая вызывает Python-скрипты для ML-операций. При первом использовании прослойка запускает постоянный процесс-диспетчер Python, который предварительно импортирует тяжёлые библиотеки (PIL, NumPy, MediaPipe, rembg), чтобы последующие вызовы AI не несли накладных расходов на импорт. Если диспетчер ещё не готов, прослойка возвращается к порождению нового подпроцесса Python на каждый запрос.
Уровень моста, который вызывает собственную среду выполнения Python и ML. Большинство инструментов Python используют постоянный dispatcher, который предварительно импортирует тяжелые библиотеки (PIL, NumPy, MediaPipe, rembg), поэтому последующие вызовы пропускают накладные расходы на импорт. OCR изолирован от этой изменяемой общей среды: `fast` вызывает собственный Tesseract, а `balanced` и `best` используют выделенный постоянный JSONL dispatcher, прикрепленный к активному неизменяемому поколению RapidOCR/ONNX. Каждый запрос содержит generation lease. Активация сначала запускает smoke test на кандидате, затем атомарно переключается на его dispatcher. Предыдущий dispatcher истощается до того, как его генерация будет утилизирована.
**Модели не загружаются заранее.** Каждый скрипт инструмента загружает веса своей модели с диска в момент запроса и освобождает их после завершения запроса. Полный профиль памяти см. в разделе [Потребление ресурсов](#resource-footprint).
Поддерживаемые операции: удаление фона (rembg/BiRefNet), апскейлинг (RealESRGAN), размытие лиц (MediaPipe), улучшение лиц (GFPGAN/CodeFormer), стирание объектов (LaMa ONNX), OCR (PaddleOCR/Tesseract), колоризация (DDColor), удаление шума, удаление эффекта красных глаз, реставрация фотографий, создание фото на паспорт, исправление прозрачности (HR-маттинг BiRefNet) и изменение размера с учётом содержимого (Go-бинарник caire).
Поддерживаемые операции: удаление фона (rembg/BiRefNet), масштабирование (RealESRGAN), размытие лица (MediaPipe), улучшение лица (GFPGAN/CodeFormer), стирание объекта (LaMa ONNX), OCR (Tesseract и RapidOCR с моделями PP-OCR ONNX), раскрашивание (DDColor), удаление шума, удаление эффекта красных глаз, восстановление фотографий, создание фотографий на паспорт, исправление прозрачности (BiRefNet HR-matting) и изменение размера с учетом содержимого (двоичный файл Go caire).
Python-скрипты находятся в `packages/ai/python/`. Образ Docker предварительно загружает все веса моделей во время сборки, поэтому контейнер полностью работает офлайн.
Скрипты Python находятся в `packages/ai/python/`. Большие дополнительные пакеты моделей устанавливаются по требованию в постоянный том `/data/ai`. В Accurate OCR используются подписанные артефакты, специфичные для платформы; встроенный уровень Tesseract не требует загрузки пакета моделей.
### `@snapotter/shared` {#snapotter-shared}
@@ -87,7 +87,7 @@ Python-скрипты находятся в `packages/ai/python/`. Образ Do
2. Фронтенд отправляет multipart-POST на `/api/v1/tools/:section/:toolId` с файлом и настройками.
3. Маршрут API проверяет входные данные с помощью Zod, затем запускает обработку.
4. Для стандартных инструментов задача ставится в соответствующий пул BullMQ (image, media или docs в зависимости от модальности). Внутрипроцессный воркер BullMQ автоматически ориентирует изображение на основе метаданных EXIF, выполняет функцию обработки инструмента и возвращает результат.
5. Для AI-инструментов прослойка TypeScript отправляет запрос постоянному диспетчеру Python (или в качестве запасного варианта порождает новый подпроцесс), ждёт его завершения и читает выходной файл.
5. Для большинства инструментов ИИ мост TypeScript отправляет запрос на постоянный Python dispatcher. Вместо этого быстрый OCR вызывает Tesseract, а точный OCR запускает закрепленный исполняемый файл из активного неизменяемого поколения OCR. Запрошенный уровень OCR фиксируется при входе и никогда не изменяется автоматически во время выполнения.
6. Прогресс задачи сохраняется в таблицу `jobs` в PostgreSQL, поэтому состояние переживает перезапуски контейнера. Обновления в реальном времени доставляются через SSE по адресу `/api/v1/jobs/:jobId/progress`.
7. API возвращает `jobId` и `downloadUrl`. Пользователь скачивает обработанный файл из `/api/v1/download/:jobId/:filename`.