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: 879baf70cf3d
i18n_source_hash: 733cb3c10884
i18n_provenance: human
---
# البنية {#architecture}
@@ -36,13 +36,13 @@ snapotter/
### `@snapotter/ai` {#snapotter-ai}
طبقة جسر تستدعي نصوص Python البرمجية لعمليات التعلّم الآلي. عند أول استخدام، يبدأ الجسر عملية موزِّع Python دائمة تستورد مسبقًا المكتبات الثقيلة (PIL وNumPy وMediaPipe وrembg) بحيث تتخطّى استدعاءات الذكاء الاصطناعي اللاحقة كلفة الاستيراد. إذا لم يكن الموزِّع جاهزًا بعد، يتراجع الجسر إلى إطلاق عملية 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)، وإزالة التشويش، وإزالة العين الحمراء، وترميم الصور، وإنشاء صور جواز السفر، وإصلاح الشفافية (مَطّ BiRefNet عالي الدقة)، وتغيير الحجم المدرك للمحتوى (ثنائي caire المكتوب بلغة Go).
العمليات المدعومة: إزالة الخلفية (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` المستمرة. يستخدم OCR الدقيق عناصر موقعة خاصة بالمنصة؛ لا تتطلب طبقة Tesseract المدمجة تنزيل حزمة النموذج.
### `@snapotter/shared` {#snapotter-shared}
@@ -87,7 +87,7 @@ snapotter/
2. ترسل الواجهة الأمامية طلب POST متعدد الأجزاء إلى `/api/v1/tools/:section/:toolId` مع الملف والإعدادات.
3. يتحقق مسار API من المُدخَل بواسطة Zod، ثم يوزّع المعالجة.
4. بالنسبة للأدوات القياسية، تُدرَج المهمة في مجمّع BullMQ المناسب (image أو media أو docs بحسب الوسيط). يوجّه عامل BullMQ داخل العملية الصورة تلقائيًا بناءً على البيانات الوصفية EXIF، ويشغّل دالة معالجة الأداة، ويعيد النتيجة.
5. بالنسبة لأدوات الذكاء الاصطناعي، يرسل جسر 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`.