Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -126,6 +126,9 @@ Primary goals for reconcile rate:
|
|
| 126 |
Gap between tables must not contain another <table> or page-separator.
|
| 127 |
- Fix MD-2: Skip blank-header column merge for YOUR CHECKS SEQUENCED–style tables (title + repeated
|
| 128 |
Amount columns + blank th between triplets); merge was collapsing multi-column check rows.
|
|
|
|
|
|
|
|
|
|
| 129 |
"""
|
| 130 |
|
| 131 |
# Patch asyncio first (before Gradio imports it) to suppress Python 3.13 cleanup noise
|
|
@@ -4918,6 +4921,74 @@ def _fix29_move_debit_heading_before_orphan_table(text: str) -> str:
|
|
| 4918 |
return text
|
| 4919 |
|
| 4920 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4921 |
def _strip_check_image_ocr_junk_html(text: str) -> str:
|
| 4922 |
"""
|
| 4923 |
Fix 31: Remove hallucinated rows on scanned check/receipt regions and normalize amount cells.
|
|
@@ -5219,6 +5290,7 @@ def stabilize_tables_and_text(page_md: str) -> str:
|
|
| 5219 |
stabilized = _strip_orphan_continued_da3_flatline(stabilized)
|
| 5220 |
stabilized = _strip_standalone_continued_banner_line(stabilized)
|
| 5221 |
stabilized = _strip_check_image_ocr_junk_html(stabilized) # Fix 31
|
|
|
|
| 5222 |
stabilized = _fix_markdown_fidelity_typos_and_escapes(stabilized)
|
| 5223 |
return close_unclosed_html(stabilized)
|
| 5224 |
|
|
@@ -5354,6 +5426,7 @@ def run_ocr(uploaded_file):
|
|
| 5354 |
stabilized = _fix29_move_debit_heading_before_orphan_table(stabilized) # Fix 29
|
| 5355 |
stabilized = _strip_standalone_continued_banner_line(stabilized)
|
| 5356 |
stabilized = _strip_check_image_ocr_junk_html(stabilized) # Fix 31
|
|
|
|
| 5357 |
elif is_pdf and is_nfcu_doc:
|
| 5358 |
nfcu_summary = _extract_nfcu_summary_table(path, page_num)
|
| 5359 |
if nfcu_summary:
|
|
@@ -5436,6 +5509,7 @@ def run_ocr(uploaded_file):
|
|
| 5436 |
merged = _strip_orphan_continued_da3_flatline(merged)
|
| 5437 |
merged = _strip_standalone_continued_banner_line(merged)
|
| 5438 |
merged = _strip_check_image_ocr_junk_html(merged) # Fix 31
|
|
|
|
| 5439 |
return merged
|
| 5440 |
|
| 5441 |
except Exception as e:
|
|
|
|
| 126 |
Gap between tables must not contain another <table> or page-separator.
|
| 127 |
- Fix MD-2: Skip blank-header column merge for YOUR CHECKS SEQUENCED–style tables (title + repeated
|
| 128 |
Amount columns + blank th between triplets); merge was collapsing multi-column check rows.
|
| 129 |
+
- Fix MD-3: Check image pages — GLM often emits  plus <div align="center"> fragments
|
| 130 |
+
(e.g. 2293 $6,721.00 4/29/2025). Collapse detected gallery pages into one Check #|Amount|Date
|
| 131 |
+
table when bbox/image markers + repeated check lines are present; skips chunks with YOUR CHECKS SEQUENCED.
|
| 132 |
"""
|
| 133 |
|
| 134 |
# Patch asyncio first (before Gradio imports it) to suppress Python 3.13 cleanup noise
|
|
|
|
| 4921 |
return text
|
| 4922 |
|
| 4923 |
|
| 4924 |
+
_CHECK_IMAGE_GALLERY_LINE_RE = re.compile(
|
| 4925 |
+
r"(?<![\d])(\d{3,5})\s*\$\s*([\d,]+\.\d{2})\s*(\d{1,2}/\d{1,2}/\d{4})",
|
| 4926 |
+
re.IGNORECASE,
|
| 4927 |
+
)
|
| 4928 |
+
|
| 4929 |
+
|
| 4930 |
+
def _normalize_check_image_gallery_pages(text: str) -> str:
|
| 4931 |
+
"""
|
| 4932 |
+
Fix MD-3: Replace GLM check-scan page noise (markdown images with bbox + scattered div/line text)
|
| 4933 |
+
with a single HTML table when the page looks like a check image gallery, not a structured table.
|
| 4934 |
+
"""
|
| 4935 |
+
if not text or ("bbox=" not in text and ":
|
| 4936 |
+
return text
|
| 4937 |
+
try:
|
| 4938 |
+
sep = "---page-separator---"
|
| 4939 |
+
parts = text.split(sep)
|
| 4940 |
+
out: List[str] = []
|
| 4941 |
+
for chunk in parts:
|
| 4942 |
+
out.append(_maybe_convert_check_image_gallery_chunk(chunk))
|
| 4943 |
+
return sep.join(out)
|
| 4944 |
+
except Exception as e:
|
| 4945 |
+
log.warning("_normalize_check_image_gallery_pages failed: %s", e)
|
| 4946 |
+
return text
|
| 4947 |
+
|
| 4948 |
+
|
| 4949 |
+
def _maybe_convert_check_image_gallery_chunk(chunk: str) -> str:
|
| 4950 |
+
if not chunk or not chunk.strip():
|
| 4951 |
+
return chunk
|
| 4952 |
+
if "YOUR CHECKS SEQUENCED" in chunk.upper():
|
| 4953 |
+
return chunk
|
| 4954 |
+
|
| 4955 |
+
matches = list(_CHECK_IMAGE_GALLERY_LINE_RE.finditer(chunk))
|
| 4956 |
+
if len(matches) < 2:
|
| 4957 |
+
return chunk
|
| 4958 |
+
|
| 4959 |
+
bbox_hits = chunk.count("bbox=")
|
| 4960 |
+
img_hits = len(re.findall(r"!\[\]\s*\(", chunk))
|
| 4961 |
+
if bbox_hits < 2 and img_hits < 2:
|
| 4962 |
+
return chunk
|
| 4963 |
+
|
| 4964 |
+
rows: List[Tuple[str, str, str]] = []
|
| 4965 |
+
seen = set()
|
| 4966 |
+
for m in matches:
|
| 4967 |
+
key = (m.group(1), m.group(2), m.group(3))
|
| 4968 |
+
if key in seen:
|
| 4969 |
+
continue
|
| 4970 |
+
seen.add(key)
|
| 4971 |
+
rows.append(key)
|
| 4972 |
+
|
| 4973 |
+
pos_img = chunk.find("
|
| 4974 |
+
pos_first = matches[0].start()
|
| 4975 |
+
if pos_img == -1:
|
| 4976 |
+
start = pos_first
|
| 4977 |
+
else:
|
| 4978 |
+
start = min(pos_img, pos_first)
|
| 4979 |
+
|
| 4980 |
+
prefix = chunk[:start].rstrip()
|
| 4981 |
+
lines = [
|
| 4982 |
+
"<table>",
|
| 4983 |
+
"<tr><th>Check #</th><th>Amount</th><th>Date</th></tr>",
|
| 4984 |
+
]
|
| 4985 |
+
for num, amt, dt in rows:
|
| 4986 |
+
lines.append(f"<tr><td>{num}</td><td>{amt}</td><td>{dt}</td></tr>")
|
| 4987 |
+
lines.append("</table>")
|
| 4988 |
+
table_html = "\n".join(lines)
|
| 4989 |
+
return (prefix + "\n\n" + table_html) if prefix else table_html
|
| 4990 |
+
|
| 4991 |
+
|
| 4992 |
def _strip_check_image_ocr_junk_html(text: str) -> str:
|
| 4993 |
"""
|
| 4994 |
Fix 31: Remove hallucinated rows on scanned check/receipt regions and normalize amount cells.
|
|
|
|
| 5290 |
stabilized = _strip_orphan_continued_da3_flatline(stabilized)
|
| 5291 |
stabilized = _strip_standalone_continued_banner_line(stabilized)
|
| 5292 |
stabilized = _strip_check_image_ocr_junk_html(stabilized) # Fix 31
|
| 5293 |
+
stabilized = _normalize_check_image_gallery_pages(stabilized) # Fix MD-3
|
| 5294 |
stabilized = _fix_markdown_fidelity_typos_and_escapes(stabilized)
|
| 5295 |
return close_unclosed_html(stabilized)
|
| 5296 |
|
|
|
|
| 5426 |
stabilized = _fix29_move_debit_heading_before_orphan_table(stabilized) # Fix 29
|
| 5427 |
stabilized = _strip_standalone_continued_banner_line(stabilized)
|
| 5428 |
stabilized = _strip_check_image_ocr_junk_html(stabilized) # Fix 31
|
| 5429 |
+
stabilized = _normalize_check_image_gallery_pages(stabilized) # Fix MD-3
|
| 5430 |
elif is_pdf and is_nfcu_doc:
|
| 5431 |
nfcu_summary = _extract_nfcu_summary_table(path, page_num)
|
| 5432 |
if nfcu_summary:
|
|
|
|
| 5509 |
merged = _strip_orphan_continued_da3_flatline(merged)
|
| 5510 |
merged = _strip_standalone_continued_banner_line(merged)
|
| 5511 |
merged = _strip_check_image_ocr_junk_html(merged) # Fix 31
|
| 5512 |
+
merged = _normalize_check_image_gallery_pages(merged) # Fix MD-3
|
| 5513 |
return merged
|
| 5514 |
|
| 5515 |
except Exception as e:
|