NaserNajeh commited on
Commit
95c55af
·
verified ·
1 Parent(s): 7d26757

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -53
app.py CHANGED
@@ -3,6 +3,7 @@ import gradio as gr
3
  import fitz # PyMuPDF
4
  from PIL import Image
5
  import numpy as np
 
6
 
7
  # =======================
8
  # 1) EasyOCR (CPU - مجاني)
@@ -25,58 +26,83 @@ def ocr_easyocr(pil_img: Image.Image) -> str:
25
 
26
  # ===============================================
27
  # 2) Inference API (يستهلك اعتمادات PRO بدل دقائق GPU)
28
- # نستخدم TrOCR عربي عبر image_to_text فقط
29
  # ===============================================
30
- from huggingface_hub import InferenceClient
31
- _INFER_CLIENT = None
32
- # يمكنك تغييره من Settings → Variables بوضع INFER_MODEL، الافتراضي أدناه TrOCR عربي:
33
  INFER_MODEL = os.environ.get("INFER_MODEL", "David-Magdy/TR_OCR_LARGE")
34
 
35
- def get_infer_client():
36
- """تهيئة عميل الاستدلال مع مهلة أطول ورسالة واضحة إن غاب التوكين."""
37
- global _INFER_CLIENT
38
- if _INFER_CLIENT is None:
39
- token = os.environ.get("HF_TOKEN")
40
- if not token:
41
- raise RuntimeError("لا يوجد HF_TOKEN في Secrets. أضِفه من Settings → Variables and secrets.")
42
- _INFER_CLIENT = InferenceClient(model=INFER_MODEL, token=token, timeout=120)
43
- return _INFER_CLIENT
44
-
45
  def ocr_infer_api(pil_img: Image.Image) -> str:
46
  """
47
- استدعاء Inference API لنموذج OCR عربي (TrOCR) عبر image_to_text فقط،
48
- مع معالجة حالة التحميل/المهلة بإعادة محاولة واحدة.
 
 
49
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  try:
51
- client = get_infer_client()
52
-
53
- # حضّر الصورة كـ BytesIO
54
- buf = io.BytesIO()
55
- pil_img.save(buf, format="PNG")
56
- buf.seek(0)
57
-
58
- # المحاولة الأولى
59
- try:
60
- out = client.image_to_text(image=buf)
61
- txt = (out or "").strip()
62
- if txt:
63
- return txt
64
- except Exception as e1:
65
- last = repr(e1)
66
-
67
- # إعادة المحاولة (أحيانًا الموديل يكون في حالة "loading")
68
- time.sleep(3)
69
- buf.seek(0)
70
- try:
71
- out = client.image_to_text(image=buf)
72
- txt = (out or "").strip()
73
- if txt:
74
- return txt
75
- except Exception as e2:
76
- last = repr(e2)
77
-
78
- return f"حدث خطأ أثناء استدعاء Inference API (image_to_text): {last}"
79
-
80
  except Exception as e:
81
  return f"حدث خطأ أثناء استدعاء Inference API: {repr(e)}"
82
 
@@ -168,13 +194,14 @@ def ocr_pdf(pdf_file, dpi, limit_pages, backend):
168
  # زر تشخيص Inference API
169
  # =======================
170
  def diag_infer():
171
- import sys, requests, huggingface_hub
172
  info = []
173
  token = os.environ.get("HF_TOKEN")
174
  info.append(f"HF_TOKEN: {'موجود' if token else 'مفقود'}")
175
  info.append(f"INFER_MODEL: {INFER_MODEL}")
176
  info.append(f"huggingface_hub: {huggingface_hub.__version__}")
177
  info.append(f"Python: {sys.version.split()[0]}")
 
178
  try:
179
  r = requests.get(
180
  f"https://api-inference.huggingface.co/models/{INFER_MODEL}",
@@ -188,13 +215,6 @@ def diag_infer():
188
  info.append("Response is not JSON.")
189
  except Exception as e:
190
  info.append(f"HTTP check error: {repr(e)}")
191
- try:
192
- client = get_infer_client()
193
- # ping بسيط (قد يفشل لبعض النماذج؛ الهدف اختبار المصادقة والاتصال)
194
- _ = client.text_generation("ping", max_new_tokens=1)
195
- info.append("basic text_generation ping: OK")
196
- except Exception as e:
197
- info.append(f"text_generation ping error: {repr(e)}")
198
  return "\n".join(str(x) for x in info)
199
 
200
 
 
3
  import fitz # PyMuPDF
4
  from PIL import Image
5
  import numpy as np
6
+ import requests
7
 
8
  # =======================
9
  # 1) EasyOCR (CPU - مجاني)
 
26
 
27
  # ===============================================
28
  # 2) Inference API (يستهلك اعتمادات PRO بدل دقائق GPU)
29
+ # نستخدم TrOCR عربي عبر نداء HTTP مباشر لمهمة image-to-text
30
  # ===============================================
31
+ # الموديل الافتراضي (يمكن تغييره من Settings → Variables بوضع INFER_MODEL)
 
 
32
  INFER_MODEL = os.environ.get("INFER_MODEL", "David-Magdy/TR_OCR_LARGE")
33
 
 
 
 
 
 
 
 
 
 
 
34
  def ocr_infer_api(pil_img: Image.Image) -> str:
35
  """
36
+ استدعاء HF Inference API مباشرة على endpoint:
37
+ POST https://api-inference.huggingface.co/models/{INFER_MODEL}
38
+ مع تمرير الصورة كبايتات (image/png) وفق مهمة image-to-text.
39
+ نعيد المحاولة مرة واحدة إذا كانت الحالة 503 (loading).
40
  """
41
+ token = os.environ.get("HF_TOKEN")
42
+ if not token:
43
+ return "حدث خطأ أثناء استدعاء Inference API: لا يوجد HF_TOKEN في Secrets."
44
+
45
+ url = f"https://api-inference.huggingface.co/models/{INFER_MODEL}"
46
+ headers = {
47
+ "Authorization": f"Bearer {token}",
48
+ "Accept": "application/json",
49
+ # لا تحدد Content-Type كنص JSON؛ سنرسل الصورة خامًا:
50
+ # "Content-Type": "application/octet-stream" # يُمكن تركه، Requests سيعيّنه تلقائيًا
51
+ }
52
+
53
+ # حضّر الصورة في BytesIO (PNG)
54
+ buf = io.BytesIO()
55
+ # توحيد الوضع إلى RGB لتجنّب مشاكل بعض النماذج
56
+ pil_img = pil_img.convert("RGB")
57
+ pil_img.save(buf, format="PNG")
58
+ img_bytes = buf.getvalue()
59
+
60
+ def call_once():
61
+ r = requests.post(url, headers=headers, data=img_bytes, timeout=120)
62
+ if r.status_code == 200:
63
+ # عادةً يرجع شكل مثل: [{"generated_text": "..."}]
64
+ try:
65
+ js = r.json()
66
+ except Exception:
67
+ # لو لم يكن JSON (نادرًا) نعيد النص كما هو
68
+ return r.text.strip()
69
+
70
+ if isinstance(js, list) and js and isinstance(js[0], dict):
71
+ txt = js[0].get("generated_text", "")
72
+ return (txt or "").strip()
73
+ elif isinstance(js, dict) and "generated_text" in js:
74
+ return (js.get("generated_text") or "").strip()
75
+ else:
76
+ # أحيانًا يرجع هيكل مختلف؛ نطبع ما تم إرجاعه
77
+ return str(js).strip()
78
+
79
+ elif r.status_code == 503:
80
+ # الموديل قيد التحميل
81
+ try:
82
+ js = r.json()
83
+ est = js.get("estimated_time", 5)
84
+ except Exception:
85
+ est = 5
86
+ return {"_retry_after": min(int(est) + 1, 10)}
87
+ else:
88
+ # خطأ واضح من الخادم
89
+ try:
90
+ js = r.json()
91
+ msg = js.get("error", r.text)
92
+ except Exception:
93
+ msg = r.text
94
+ raise RuntimeError(f"{r.status_code}: {msg}")
95
+
96
+ # المحاولة الأولى
97
  try:
98
+ out = call_once()
99
+ if isinstance(out, dict) and "_retry_after" in out:
100
+ time.sleep(out["_retry_after"])
101
+ out = call_once()
102
+ if isinstance(out, dict):
103
+ # لو بقي dict حتى الآن نعيده كنص
104
+ return f"حدث خطأ أثناء استدعاء Inference API: {out}"
105
+ return out if out else "لم يرجع الموديل أي نص."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  except Exception as e:
107
  return f"حدث خطأ أثناء استدعاء Inference API: {repr(e)}"
108
 
 
194
  # زر تشخيص Inference API
195
  # =======================
196
  def diag_infer():
197
+ import sys, huggingface_hub
198
  info = []
199
  token = os.environ.get("HF_TOKEN")
200
  info.append(f"HF_TOKEN: {'موجود' if token else 'مفقود'}")
201
  info.append(f"INFER_MODEL: {INFER_MODEL}")
202
  info.append(f"huggingface_hub: {huggingface_hub.__version__}")
203
  info.append(f"Python: {sys.version.split()[0]}")
204
+ # فحص حالة الموديل
205
  try:
206
  r = requests.get(
207
  f"https://api-inference.huggingface.co/models/{INFER_MODEL}",
 
215
  info.append("Response is not JSON.")
216
  except Exception as e:
217
  info.append(f"HTTP check error: {repr(e)}")
 
 
 
 
 
 
 
218
  return "\n".join(str(x) for x in info)
219
 
220