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 的 monorepo 结构、应用与包架构、请求生命周期以及资源占用。"
i18n_source_hash: 9e8f80499a37
i18n_provenance: human
i18n_output_hash: bc9e6a754251
i18n_source_hash: 733cb3c10884
i18n_provenance: human
---
# 架构 {#architecture}
@@ -36,13 +36,13 @@ snapotter/
### `@snapotter/ai` {#snapotter-ai}
一个用于为 ML 操作调用 Python 脚本的桥接层。首次使用时,桥接层会启动一个常驻的 Python dispatcher 进程,预先导入重量级库(PIL、NumPy、MediaPipe、rembg),从而让后续的 AI 调用跳过导入开销。如果 dispatcher 尚未就绪,桥接层会回退到为每个请求生成一个全新的 Python 子进程
调用本机和 Python ML 运行时的桥接层。 大多数 Python 工具使用持久性 dispatcher 来预导入重库(PIL、NumPy、MediaPipe、rembg),因此后续调用跳过导入开销。 OCR 与可变共享环境隔离:`fast` 调用本机 Tesseract,而 `balanced``best` 使用固定到活动不可变 RapidOCR/ONNX 生成的专用持久 JSONL dispatcher。 每个请求都包含一个 generation lease。 激活首先在候选者上运行 smoke test,然后自动切换到其 dispatcher。 先前的 dispatcher 在其生成被垃圾收集之前耗尽
**模型不会被预加载。** 每个工具脚本在请求时从磁盘加载其模型权重,并在请求结束时释放。完整的内存概况见[资源占用](#resource-footprint)。
支持的操作:背景移除(rembg/BiRefNet、放大RealESRGAN、人脸模糊MediaPipe、人脸增强GFPGAN/CodeFormer、对象擦除LaMa ONNX、OCRPaddleOCR/Tesseract)、上色(DDColor、噪声除、红眼除、照片修复、证件照生成、透明度修复(BiRefNet HR-matting以及内容感知缩放Go caire 二进制)。
支持的操作:背景去除 (rembg/BiRefNet)、放大 (RealESRGAN)、人脸模糊 (MediaPipe)、人脸增强 (GFPGAN/CodeFormer)、对象擦除 (LaMa ONNX)、OCR带有 PP-OCR ONNX 型号的 Tesseract 和 RapidOCR)、着色 (DDColor)、噪声除、红眼除、照片修复、护照照片生成、透明度修复(BiRefNet HR-matting内容感知调整大小Go caire 二进制)。
Python 脚本位于 `packages/ai/python/`。Docker 镜像会在构建期间预下载所有模型权重,因此容器可完全离线工作
Python 脚本位于 `packages/ai/python/` 中。大型可选模型包根据需要安装到持久 `/data/ai` 卷中。准确的 OCR 使用签名的、特定于平台的工件;内置 Tesseract 层无需下载模型包
### `@snapotter/shared` {#snapotter-shared}
@@ -87,7 +87,7 @@ Python 脚本位于 `packages/ai/python/`。Docker 镜像会在构建期间预
2. 前端向 `/api/v1/tools/:section/:toolId` 发送一个包含文件和设置的 multipart POST。
3. API 路由使用 Zod 校验输入,然后分派处理。
4. 对于标准工具,作业会被入队到相应的 BullMQ 池(根据模态选择 image、media 或 docs)。进程内的 BullMQ worker 会根据 EXIF 元数据自动定向图像、运行该工具的处理函数并返回结果。
5. 对于 AI 工具,TypeScript 桥接层会向常驻的 Python dispatcher 发送请求(或作为回退生成一个全新的子进程),等待其完成,并读取输出文件
5. 对于大多数 AI 工具,TypeScript 桥会向持久 Python dispatcher 发送请求。 快速 OCR 而是调用 Tesseract,而准确的 OCR 从活动的不可变 OCR 生成中启动固定的可执行文件。 请求的 OCR 层在入口处固定,并且在执行期间永远不会默默更改
6. 作业进度会被持久化到 PostgreSQL 中的 `jobs` 表,因此状态可在容器重启后保留。实时更新通过 `/api/v1/jobs/:jobId/progress` 处的 SSE 传递。
7. API 返回一个 `jobId``downloadUrl`。用户从 `/api/v1/download/:jobId/:filename` 下载处理后的文件。