rehan953 commited on
Commit
6d7f99b
·
verified ·
1 Parent(s): 9b21413

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -5
app.py CHANGED
@@ -72,18 +72,21 @@ logging.basicConfig(level=logging.INFO)
72
  # Settings — tuned for dense financial PDFs; applies to every document
73
  # ---------------------------------------------------------------------------
74
 
 
75
  GLMOCR_API_KEY = "cee1d52dd91a4ab591b3f6e105f8ad89.LgbQTECuzX0zrito"
76
  if not GLMOCR_API_KEY:
77
- log.warning("GLMOCR_API_KEY is not set; GlmOcr() will fail until you export it.")
 
 
78
 
79
  # Rasterization: higher scale = more pixels per PDF point (helps small type,
80
  # boxed headers, and narrow columns). Same constant for all uploads.
81
- RENDER_SCALE = 3.12
82
 
83
  # White margin as a fraction of page width/height after render. Extra right
84
  # margin helps right-aligned currency columns that hug the page edge.
85
  PAD_LEFT_FRAC = 0.035
86
- PAD_RIGHT_FRAC = 0.11
87
  PAD_TOP_FRAC = 0.018
88
  PAD_BOTTOM_FRAC = 0.018
89
 
@@ -144,7 +147,10 @@ def get_parser():
144
  if _parser is None:
145
  from glmocr import GlmOcr
146
 
147
- _parser = GlmOcr(api_key=GLMOCR_API_KEY, mode="maas")
 
 
 
148
  return _parser
149
 
150
 
@@ -575,6 +581,74 @@ def stabilize_table_markup(md: str, rounds: int = 4) -> str:
575
  return cur
576
 
577
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  def looks_like_markdown_table(block: str) -> bool:
579
  lines = [ln.rstrip() for ln in block.strip().splitlines() if ln.strip()]
580
  if len(lines) < 2:
@@ -644,7 +718,10 @@ def light_stabilize_markdown(page_md: str) -> str:
644
  else:
645
  out_blocks.append(b)
646
  merged = close_unclosed_html("\n\n".join(out_blocks))
647
- return stabilize_table_markup(merged, rounds=4)
 
 
 
648
 
649
 
650
  def render_pdf_pages_to_images(pdf_path: str) -> Tuple[List[str], List[int]]:
@@ -784,6 +861,8 @@ def run_ocr(uploaded_file):
784
  merged = "\n\n---page-separator---\n\n".join(all_pages) if all_pages else "(No content)"
785
  if merged and merged != "(No content)" and not merged.lstrip().startswith("Error:"):
786
  merged = stabilize_table_markup(merged, rounds=4)
 
 
787
  return merged
788
 
789
  except Exception as e:
 
72
  # Settings — tuned for dense financial PDFs; applies to every document
73
  # ---------------------------------------------------------------------------
74
 
75
+ # Never commit secrets: Space / local runs use ZHIPU_API_KEY or GLMOCR_API_KEY.
76
  GLMOCR_API_KEY = "cee1d52dd91a4ab591b3f6e105f8ad89.LgbQTECuzX0zrito"
77
  if not GLMOCR_API_KEY:
78
+ log.warning(
79
+ "No ZHIPU_API_KEY or GLMOCR_API_KEY in environment; GlmOcr() will fail until you set one."
80
+ )
81
 
82
  # Rasterization: higher scale = more pixels per PDF point (helps small type,
83
  # boxed headers, and narrow columns). Same constant for all uploads.
84
+ RENDER_SCALE = 3.35
85
 
86
  # White margin as a fraction of page width/height after render. Extra right
87
  # margin helps right-aligned currency columns that hug the page edge.
88
  PAD_LEFT_FRAC = 0.035
89
+ PAD_RIGHT_FRAC = 0.125
90
  PAD_TOP_FRAC = 0.018
91
  PAD_BOTTOM_FRAC = 0.018
92
 
 
147
  if _parser is None:
148
  from glmocr import GlmOcr
149
 
150
+ kw = {"mode": "maas"}
151
+ if GLMOCR_API_KEY:
152
+ kw["api_key"] = GLMOCR_API_KEY
153
+ _parser = GlmOcr(**kw)
154
  return _parser
155
 
156
 
 
581
  return cur
582
 
583
 
584
+ _THEAD_BLOCK = re.compile(r"<thead\b[^>]*>.*?</thead>", re.IGNORECASE | re.DOTALL)
585
+ _CURRENCY_SNIFF = re.compile(r"[\$€£]")
586
+
587
+
588
+ def repair_thead_cell_semantics(md: str) -> str:
589
+ """
590
+ Normalize header rows: cells inside <thead> should use <th>. Stray <td>
591
+ from OCR breaks rectangular header grids for parsers that expect <th> only
592
+ in thead. Institution-agnostic HTML repair only.
593
+ """
594
+ if not md or "<thead" not in md.lower():
595
+ return md
596
+
597
+ def fix_block(m: re.Match) -> str:
598
+ block = m.group(0)
599
+ block = re.sub(r"<td(\b[^>]*?>)", r"<th\1", block, flags=re.IGNORECASE)
600
+ block = re.sub(r"</td\s*>", "</th>", block, flags=re.IGNORECASE)
601
+ return block
602
+
603
+ return _THEAD_BLOCK.sub(fix_block, md)
604
+
605
+
606
+ def _table_cell_plain_texts(full_table: str) -> List[str]:
607
+ return [_cell_plain_text(m.group(0)) for m in _CELL.finditer(full_table)]
608
+
609
+
610
+ def strip_degenerate_html_tables(md: str) -> str:
611
+ """
612
+ Drop tables that are almost certainly non-ledger layout: all-empty grids,
613
+ or large sparse grids with no digits and no currency symbols (blank
614
+ worksheets / decorative boxes). Pattern-based only; no bank or product
615
+ names. Conservative thresholds to avoid removing real sparse tables.
616
+ """
617
+ if not md or "<table" not in md.lower():
618
+ return md
619
+
620
+ def should_drop(full: str) -> bool:
621
+ texts = _table_cell_plain_texts(full)
622
+ n = len(texts)
623
+ if n < 1:
624
+ return False
625
+ nonempty = sum(1 for t in texts if t.strip())
626
+ if nonempty == 0:
627
+ return True
628
+ joined = " ".join(texts)
629
+ compact = re.sub(r"\s+", " ", joined).strip()
630
+ L = len(compact)
631
+ financial = bool(re.search(r"\d", joined)) or bool(_CURRENCY_SNIFF.search(joined))
632
+ if financial:
633
+ return False
634
+ if n >= 12 and nonempty <= max(2, int(n * 0.06)):
635
+ return True
636
+ if n >= 8 and nonempty <= 1 and L < 80:
637
+ return True
638
+ return False
639
+
640
+ def repl_table(m: re.Match) -> str:
641
+ return "" if should_drop(m.group(0)) else m.group(0)
642
+
643
+ out = re.sub(
644
+ r"<table\b[^>]*>.*?</table>",
645
+ repl_table,
646
+ md,
647
+ flags=re.IGNORECASE | re.DOTALL,
648
+ )
649
+ return re.sub(r"\n{3,}", "\n\n", out)
650
+
651
+
652
  def looks_like_markdown_table(block: str) -> bool:
653
  lines = [ln.rstrip() for ln in block.strip().splitlines() if ln.strip()]
654
  if len(lines) < 2:
 
718
  else:
719
  out_blocks.append(b)
720
  merged = close_unclosed_html("\n\n".join(out_blocks))
721
+ merged = repair_thead_cell_semantics(merged)
722
+ merged = stabilize_table_markup(merged, rounds=4)
723
+ merged = strip_degenerate_html_tables(merged)
724
+ return merged
725
 
726
 
727
  def render_pdf_pages_to_images(pdf_path: str) -> Tuple[List[str], List[int]]:
 
861
  merged = "\n\n---page-separator---\n\n".join(all_pages) if all_pages else "(No content)"
862
  if merged and merged != "(No content)" and not merged.lstrip().startswith("Error:"):
863
  merged = stabilize_table_markup(merged, rounds=4)
864
+ merged = repair_thead_cell_semantics(merged)
865
+ merged = strip_degenerate_html_tables(merged)
866
  return merged
867
 
868
  except Exception as e: