Spaces:
Sleeping
Sleeping
Pointf5ive commited on
Commit ·
560aea7
1
Parent(s): db8f498
Prevent indefinite OCR hangs with hard tesseract batch timeout
Browse files- smoke_signal_tab.py +61 -8
smoke_signal_tab.py
CHANGED
|
@@ -771,6 +771,10 @@ try:
|
|
| 771 |
SS_TESSERACT_MIN_CONF_KEEP = max(0.0, min(1.0, float(os.environ.get("SS_TESSERACT_MIN_CONF_KEEP", "0.58"))))
|
| 772 |
except Exception:
|
| 773 |
SS_TESSERACT_MIN_CONF_KEEP = 0.58
|
|
|
|
|
|
|
|
|
|
|
|
|
| 774 |
|
| 775 |
|
| 776 |
def _load_surya_runtime():
|
|
@@ -1004,14 +1008,47 @@ def _run_tesseract_batch(images):
|
|
| 1004 |
return [_ocr_single(img) for img in images]
|
| 1005 |
|
| 1006 |
outputs = [None] * len(images)
|
| 1007 |
-
|
| 1008 |
-
|
| 1009 |
-
|
| 1010 |
-
|
| 1011 |
-
|
| 1012 |
-
|
| 1013 |
-
|
| 1014 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1015 |
|
| 1016 |
return outputs
|
| 1017 |
|
|
@@ -1230,6 +1267,7 @@ def run_ocr(progress=gr.Progress(track_tqdm=False)) -> tuple:
|
|
| 1230 |
)
|
| 1231 |
else:
|
| 1232 |
fallback_preds = _run_tesseract_batch(batch_images)
|
|
|
|
| 1233 |
for item, pred in zip(batch_items_with_images, fallback_preds):
|
| 1234 |
ocr_lookup[item["page_num"]] = pred
|
| 1235 |
ocr_processed_pages += 1
|
|
@@ -1237,11 +1275,19 @@ def run_ocr(progress=gr.Progress(track_tqdm=False)) -> tuple:
|
|
| 1237 |
(total_pages_planned + ocr_processed_pages, total_work_units),
|
| 1238 |
desc=f"Tesseract {book_id} p{item['page_num']}",
|
| 1239 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1240 |
except Exception as e:
|
| 1241 |
# If Surya batch fails, try Tesseract for this batch before giving up.
|
| 1242 |
if surya is not None:
|
| 1243 |
log.append(log_line(f" ⚠ {book_id} batch {batch_pages[0]}-{batch_pages[-1]} Surya error: {e}; retrying with Tesseract"))
|
| 1244 |
fallback_preds = _run_tesseract_batch(batch_images)
|
|
|
|
| 1245 |
for item, pred in zip(batch_items_with_images, fallback_preds):
|
| 1246 |
ocr_lookup[item["page_num"]] = pred
|
| 1247 |
ocr_processed_pages += 1
|
|
@@ -1249,6 +1295,13 @@ def run_ocr(progress=gr.Progress(track_tqdm=False)) -> tuple:
|
|
| 1249 |
(total_pages_planned + ocr_processed_pages, total_work_units),
|
| 1250 |
desc=f"Tesseract retry {book_id} p{item['page_num']}",
|
| 1251 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1252 |
else:
|
| 1253 |
for item in batch_items_with_images:
|
| 1254 |
ocr_lookup[item["page_num"]] = {
|
|
|
|
| 771 |
SS_TESSERACT_MIN_CONF_KEEP = max(0.0, min(1.0, float(os.environ.get("SS_TESSERACT_MIN_CONF_KEEP", "0.58"))))
|
| 772 |
except Exception:
|
| 773 |
SS_TESSERACT_MIN_CONF_KEEP = 0.58
|
| 774 |
+
try:
|
| 775 |
+
SS_TESSERACT_BATCH_HARD_TIMEOUT_SEC = max(15, int(os.environ.get("SS_TESSERACT_BATCH_HARD_TIMEOUT_SEC", "90")))
|
| 776 |
+
except Exception:
|
| 777 |
+
SS_TESSERACT_BATCH_HARD_TIMEOUT_SEC = 90
|
| 778 |
|
| 779 |
|
| 780 |
def _load_surya_runtime():
|
|
|
|
| 1008 |
return [_ocr_single(img) for img in images]
|
| 1009 |
|
| 1010 |
outputs = [None] * len(images)
|
| 1011 |
+
executor = concurrent.futures.ThreadPoolExecutor(max_workers=max_workers)
|
| 1012 |
+
futures = {executor.submit(_ocr_single, img): idx for idx, img in enumerate(images)}
|
| 1013 |
+
pending = set(futures.keys())
|
| 1014 |
+
batch_timeout = max(
|
| 1015 |
+
SS_TESSERACT_BATCH_HARD_TIMEOUT_SEC,
|
| 1016 |
+
int((len(images) / max(max_workers, 1)) * SS_TESSERACT_TIMEOUT_SEC * 2 + 15),
|
| 1017 |
+
)
|
| 1018 |
+
deadline = time.monotonic() + batch_timeout
|
| 1019 |
+
|
| 1020 |
+
try:
|
| 1021 |
+
while pending and time.monotonic() < deadline:
|
| 1022 |
+
just_done, pending = concurrent.futures.wait(
|
| 1023 |
+
pending,
|
| 1024 |
+
timeout=0.75,
|
| 1025 |
+
return_when=concurrent.futures.FIRST_COMPLETED,
|
| 1026 |
+
)
|
| 1027 |
+
if not just_done:
|
| 1028 |
+
continue
|
| 1029 |
+
for future in just_done:
|
| 1030 |
+
idx = futures[future]
|
| 1031 |
+
try:
|
| 1032 |
+
outputs[idx] = future.result()
|
| 1033 |
+
except Exception as e:
|
| 1034 |
+
outputs[idx] = {"regions": [], "confidence": 0.0, "method": f"error-tesseract-future ({e})"}
|
| 1035 |
+
|
| 1036 |
+
if pending:
|
| 1037 |
+
for future in pending:
|
| 1038 |
+
idx = futures[future]
|
| 1039 |
+
outputs[idx] = {
|
| 1040 |
+
"regions": [],
|
| 1041 |
+
"confidence": 0.0,
|
| 1042 |
+
"method": f"error-tesseract-batch-timeout ({batch_timeout}s)",
|
| 1043 |
+
}
|
| 1044 |
+
future.cancel()
|
| 1045 |
+
finally:
|
| 1046 |
+
# Avoid blocking the OCR run forever if one worker hangs in external OCR process.
|
| 1047 |
+
executor.shutdown(wait=False, cancel_futures=True)
|
| 1048 |
+
|
| 1049 |
+
for i, out in enumerate(outputs):
|
| 1050 |
+
if out is None:
|
| 1051 |
+
outputs[i] = {"regions": [], "confidence": 0.0, "method": "error-tesseract-missing-output"}
|
| 1052 |
|
| 1053 |
return outputs
|
| 1054 |
|
|
|
|
| 1267 |
)
|
| 1268 |
else:
|
| 1269 |
fallback_preds = _run_tesseract_batch(batch_images)
|
| 1270 |
+
timeout_count = sum(1 for pred in fallback_preds if "batch-timeout" in str(pred.get("method", "")))
|
| 1271 |
for item, pred in zip(batch_items_with_images, fallback_preds):
|
| 1272 |
ocr_lookup[item["page_num"]] = pred
|
| 1273 |
ocr_processed_pages += 1
|
|
|
|
| 1275 |
(total_pages_planned + ocr_processed_pages, total_work_units),
|
| 1276 |
desc=f"Tesseract {book_id} p{item['page_num']}",
|
| 1277 |
)
|
| 1278 |
+
if timeout_count:
|
| 1279 |
+
log.append(
|
| 1280 |
+
log_line(
|
| 1281 |
+
f" ⚠ {book_id} batch {batch_pages[0]}-{batch_pages[-1]}: "
|
| 1282 |
+
f"{timeout_count}/{len(fallback_preds)} tesseract timeouts"
|
| 1283 |
+
)
|
| 1284 |
+
)
|
| 1285 |
except Exception as e:
|
| 1286 |
# If Surya batch fails, try Tesseract for this batch before giving up.
|
| 1287 |
if surya is not None:
|
| 1288 |
log.append(log_line(f" ⚠ {book_id} batch {batch_pages[0]}-{batch_pages[-1]} Surya error: {e}; retrying with Tesseract"))
|
| 1289 |
fallback_preds = _run_tesseract_batch(batch_images)
|
| 1290 |
+
timeout_count = sum(1 for pred in fallback_preds if "batch-timeout" in str(pred.get("method", "")))
|
| 1291 |
for item, pred in zip(batch_items_with_images, fallback_preds):
|
| 1292 |
ocr_lookup[item["page_num"]] = pred
|
| 1293 |
ocr_processed_pages += 1
|
|
|
|
| 1295 |
(total_pages_planned + ocr_processed_pages, total_work_units),
|
| 1296 |
desc=f"Tesseract retry {book_id} p{item['page_num']}",
|
| 1297 |
)
|
| 1298 |
+
if timeout_count:
|
| 1299 |
+
log.append(
|
| 1300 |
+
log_line(
|
| 1301 |
+
f" ⚠ {book_id} batch {batch_pages[0]}-{batch_pages[-1]} retry: "
|
| 1302 |
+
f"{timeout_count}/{len(fallback_preds)} tesseract timeouts"
|
| 1303 |
+
)
|
| 1304 |
+
)
|
| 1305 |
else:
|
| 1306 |
for item in batch_items_with_images:
|
| 1307 |
ocr_lookup[item["page_num"]] = {
|