rehan953 commited on
Commit
6edb1f6
Β·
verified Β·
1 Parent(s): 97441ba

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +117 -127
app.py CHANGED
@@ -2,208 +2,198 @@ import gradio as gr
2
  import yaml
3
  import re
4
  import os
5
- import json
6
 
 
7
  import glmocr
8
- GLMOCR_BASE = os.path.dirname(glmocr.__file__)
9
- config_path = os.path.join(GLMOCR_BASE, "config.yaml")
10
  formatter_path = os.path.join(GLMOCR_BASE, "postprocess", "result_formatter.py")
11
 
 
12
  with open(config_path, "r") as f:
13
  config = yaml.safe_load(f)
 
14
  config["pipeline"]["maas"]["enabled"] = True
15
  config["pipeline"]["maas"]["api_key"] = "4570c28bdea5493c9efae9dae68edc66.sGbA9DLlcX1GlvqV"
 
16
  config["pipeline"]["result_formatter"]["abandon"] = [
17
- "number", "footnote", "aside_text", "reference", "footer_image", "header_image",
 
18
  ]
19
  config["pipeline"]["enable_layout"] = True
 
20
  with open(config_path, "w") as f:
21
  yaml.dump(config, f, default_flow_style=False, sort_keys=False)
22
 
 
 
 
23
  with open(formatter_path, "r") as f:
24
  source = f.read()
25
- for label in ['"header"', "'header'", '"footer"', "'footer'", '"doc_header"', "'doc_header'", '"doc_footer"', "'doc_footer'"]:
 
 
 
 
 
 
 
26
  source = re.sub(r',\s*' + re.escape(label), '', source)
27
  source = re.sub(re.escape(label) + r'\s*,', '', source)
28
  source = re.sub(re.escape(label), '', source)
 
29
  with open(formatter_path, "w") as f:
30
  f.write(source)
31
 
32
- ABANDON = set(config["pipeline"]["result_formatter"]["abandon"])
33
 
 
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  def run_ocr(uploaded_file):
36
  if uploaded_file is None:
37
  return "Please upload a file.", "No regions detected."
38
- api_key = "4570c28bdea5493c9efae9dae68edc66.sGbA9DLlcX1GlvqV"
39
- if not api_key:
40
- return "Error: API key not set.", "Failed."
41
  try:
42
  from glmocr import parse
 
43
  path = uploaded_file.name if hasattr(uploaded_file, "name") else str(uploaded_file)
 
 
44
  if path.lower().endswith(".pdf"):
45
  import fitz
 
46
  doc = fitz.open(path)
47
  page_images = []
48
  for i in range(len(doc)):
49
- pix = doc[i].get_pixmap(matrix=fitz.Matrix(1.5, 1.5), alpha=False)
50
  img_path = f"/tmp/maas_page_{i}.png"
51
  pix.save(img_path)
52
  page_images.append(img_path)
53
  doc.close()
54
  result = parse(page_images)
55
  else:
 
56
  result = parse(path)
57
 
58
- debug_lines = ["========== DEBUG =========="]
59
- debug_lines.append(f"1. result type: {type(result).__name__}")
60
- debug_lines.append(f"2. result length: {len(result) if isinstance(result, list) else 'N/A'}")
61
- if isinstance(result, list) and len(result) > 0:
62
- first = result[0]
63
- debug_lines.append(f"3. first element type: {type(first).__name__}")
64
- debug_lines.append(f"4. has markdown_result: {hasattr(first, 'markdown_result')}")
65
- debug_lines.append(f"5. has json_result: {hasattr(first, 'json_result')}")
66
- if hasattr(first, "markdown_result"):
67
- md = getattr(first, "markdown_result", None)
68
- debug_lines.append(f"6. markdown_result len: {len(md) if md else 0}")
69
- if hasattr(first, "json_result"):
70
- j = getattr(first, "json_result", None)
71
- debug_lines.append(f"7. json_result len: {len(j) if j else 0}")
72
- debug_lines.append("==========================")
73
-
74
- r0 = result[0] if (isinstance(result, list) and len(result) > 0) else None
75
- raw_resp = getattr(r0, '_maas_response', None) if r0 else None
76
- if raw_resp is not None:
77
- try:
78
- resp_str = json.dumps(raw_resp, indent=2, ensure_ascii=False)
79
- except Exception:
80
- resp_str = str(raw_resp)
81
- if len(resp_str) > 15000:
82
- resp_str = resp_str[:15000] + "\n\n... (truncated, total " + str(len(resp_str)) + " chars)"
83
- debug_lines.append("10. FULL API RESPONSE (first page):")
84
- debug_lines.append(resp_str)
85
- else:
86
- debug_lines.append("10. FULL API RESPONSE: not available (no _maas_response)")
87
-
88
- if not isinstance(result, list):
89
- result = [result]
90
- if not result:
91
- return "(No content)", "\n".join(debug_lines)
92
-
93
- first = result[0]
94
- has_markdown = getattr(first, "markdown_result", None) is not None
95
- has_json = getattr(first, "json_result", None) is not None
96
-
97
- if has_markdown or has_json:
98
- markdown_parts = []
99
- pages_data = []
100
- for r in result:
101
- md = getattr(r, "markdown_result", None) or ""
102
- markdown_parts.append(md.strip() if md else "(empty page)")
103
- j = getattr(r, "json_result", None) or []
104
- for page in j:
105
- pages_data.append(page)
106
- markdown = "\n\n---\n\n".join(markdown_parts)
107
-
108
- labels_seen = set()
109
- for page in pages_data:
110
- if not isinstance(page, list):
111
- continue
112
- for r in page:
113
- if isinstance(r, dict):
114
- labels_seen.add(r.get("label", ""))
115
- debug_lines.append(f"8. ALL labels from API: {sorted(labels_seen)}")
116
- debug_lines.append(f"9. markdown_parts: {len(markdown_parts)}, pages_data: {len(pages_data)}")
117
-
118
- total_headers = 0
119
- total_footers = 0
120
- all_summary = []
121
- for page_num, page_regions in enumerate(pages_data):
122
- if not isinstance(page_regions, list):
123
- page_regions = [page_regions] if page_regions else []
124
- page_summary = [f"── PAGE {page_num + 1} of {len(pages_data)} ──"]
125
- for region in page_regions:
126
- if not isinstance(region, dict):
127
- continue
128
- label = region.get("label", region.get("type", "text"))
129
- content = str(region.get("content", region.get("text", "")))
130
- if label in ABANDON:
131
- continue
132
- if label == "header":
133
- total_headers += 1
134
- page_summary.append(f"πŸ”΅ HEADER: {content[:100]}")
135
- elif label == "footer":
136
- total_footers += 1
137
- page_summary.append(f"🟒 FOOTER: {content[:100]}")
138
- else:
139
- page_summary.append(f"[{label}]: {content[:100]}")
140
- all_summary.extend(page_summary)
141
- all_summary.append("")
142
- summary_body = (
143
- f"Total pages : {len(pages_data)}\n"
144
- f"Headers found : {total_headers}\n"
145
- f"Footers found : {total_footers}\n"
146
- f"{'─'*40}\n" + "\n".join(all_summary)
147
- )
148
- summary = "\n".join(debug_lines) + "\n\n" + summary_body
149
- return markdown, summary
150
-
151
- pages_data = result if isinstance(result, list) else []
152
  total_headers = 0
153
  total_footers = 0
154
- all_markdown = []
155
- all_summary = []
 
156
  for page_num, page_regions in enumerate(pages_data):
157
  if not isinstance(page_regions, list):
158
  page_regions = [page_regions] if page_regions else []
159
- page_md = []
 
160
  page_summary = [f"── PAGE {page_num + 1} of {len(pages_data)} ──"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  for region in page_regions:
162
  if not isinstance(region, dict):
163
  continue
164
- label = region.get("label", "text")
165
  content = str(region.get("content", ""))
 
166
  if label in ABANDON:
167
  continue
 
 
 
168
  if label == "header":
169
  total_headers += 1
170
- page_summary.append(f"πŸ”΅ HEADER: {content[:100]}")
171
- page_md.append(f"<!-- HEADER -->\n{content}")
172
  elif label == "footer":
173
  total_footers += 1
174
- page_summary.append(f"🟒 FOOTER: {content[:100]}")
175
- page_md.append(f"<!-- FOOTER -->\n{content}")
176
  else:
177
- page_summary.append(f"[{label}]: {content[:100]}")
178
  page_md.append(content)
 
179
  all_markdown.append("\n\n".join(page_md))
180
  all_summary.extend(page_summary)
181
  all_summary.append("")
182
- summary_body = (
183
- f"Total pages : {len(pages_data)}\n"
184
- f"Headers found : {total_headers}\n"
185
- f"Footers found : {total_footers}\n"
186
- f"{'─'*40}\n" + "\n".join(all_summary)
 
 
187
  )
 
188
  markdown = "\n\n---\n\n".join(all_markdown) if all_markdown else "(No content)"
189
- summary = "\n".join(debug_lines) + "\n\n" + summary_body
190
  return markdown, summary
191
 
192
  except Exception as e:
193
  import traceback
194
- return f"Error: {str(e)}\n\n{traceback.format_exc()}", "Failed."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
 
196
-
197
- with gr.Blocks(title="GLM-OCR β€” MaaS") as demo:
198
- gr.Markdown("# πŸ” GLM-OCR β€” Zhipu MaaS\nUpload PDF or image.")
199
- file_input = gr.File(label="Upload PDF or Image", file_types=[".pdf", ".png", ".jpg", ".jpeg", ".tiff", ".bmp"])
200
- run_btn = gr.Button("β–Ά Run OCR", variant="primary", size="lg")
201
  with gr.Row():
202
  with gr.Column():
203
  gr.Markdown("### πŸ“„ Markdown Output")
204
  markdown_out = gr.Textbox(lines=30, label="")
205
  with gr.Column():
206
- gr.Markdown("### πŸ—‚οΈ Detected Regions (+ Debug)")
207
  regions_out = gr.Textbox(lines=30, label="")
208
- run_btn.click(fn=run_ocr, inputs=file_input, outputs=[markdown_out, regions_out])
 
 
 
209
  demo.launch()
 
2
  import yaml
3
  import re
4
  import os
 
5
 
6
+ # Paths from installed glmocr package
7
  import glmocr
8
+ GLMOCR_BASE = os.path.dirname(glmocr.__file__)
9
+ config_path = os.path.join(GLMOCR_BASE, "config.yaml")
10
  formatter_path = os.path.join(GLMOCR_BASE, "postprocess", "result_formatter.py")
11
 
12
+ # ── STEP 1: Fix config ────────────────────────────────────────
13
  with open(config_path, "r") as f:
14
  config = yaml.safe_load(f)
15
+
16
  config["pipeline"]["maas"]["enabled"] = True
17
  config["pipeline"]["maas"]["api_key"] = "4570c28bdea5493c9efae9dae68edc66.sGbA9DLlcX1GlvqV"
18
+
19
  config["pipeline"]["result_formatter"]["abandon"] = [
20
+ "number", "footnote", "aside_text",
21
+ "reference", "footer_image", "header_image",
22
  ]
23
  config["pipeline"]["enable_layout"] = True
24
+
25
  with open(config_path, "w") as f:
26
  yaml.dump(config, f, default_flow_style=False, sort_keys=False)
27
 
28
+ print("βœ… config.yaml fixed")
29
+
30
+ # ── STEP 2: Fix result_formatter.py ──────────────────────────
31
  with open(formatter_path, "r") as f:
32
  source = f.read()
33
+
34
+ labels_to_remove = [
35
+ '"header"', "'header'",
36
+ '"footer"', "'footer'",
37
+ '"doc_header"', "'doc_header'",
38
+ '"doc_footer"', "'doc_footer'"
39
+ ]
40
+ for label in labels_to_remove:
41
  source = re.sub(r',\s*' + re.escape(label), '', source)
42
  source = re.sub(re.escape(label) + r'\s*,', '', source)
43
  source = re.sub(re.escape(label), '', source)
44
+
45
  with open(formatter_path, "w") as f:
46
  f.write(source)
47
 
48
+ print("βœ… result_formatter.py fixed")
49
 
50
+ ABANDON = set(config["pipeline"]["result_formatter"]["abandon"])
51
 
52
+ # ── STEP 3: Extract header/footer from PDF text layer ─────────
53
+ # The MaaS API only returns 'text' and 'table' labels β€” it never
54
+ # labels anything as 'header' or 'footer'. So we extract those
55
+ # directly from the PDF text layer using PyMuPDF instead.
56
+ def extract_pdf_headers(path):
57
+ import fitz
58
+ page_headers = []
59
+ doc = fitz.open(path)
60
+ for page in doc:
61
+ page_rect = page.rect
62
+ page_height = page_rect.height
63
+ # Top 12% = header area
64
+ header_rect = fitz.Rect(0, 0, page_rect.width, page_height * 0.12)
65
+ # Bottom 12% = footer area
66
+ footer_rect = fitz.Rect(0, page_height * 0.88, page_rect.width, page_height)
67
+ header_text = page.get_text(clip=header_rect).strip()
68
+ footer_text = page.get_text(clip=footer_rect).strip()
69
+ page_headers.append({"header": header_text, "footer": footer_text})
70
+ doc.close()
71
+ return page_headers
72
+
73
+ # ── STEP 4: Main OCR function ─────────────────────────────────
74
  def run_ocr(uploaded_file):
75
  if uploaded_file is None:
76
  return "Please upload a file.", "No regions detected."
77
+
 
 
78
  try:
79
  from glmocr import parse
80
+
81
  path = uploaded_file.name if hasattr(uploaded_file, "name") else str(uploaded_file)
82
+
83
+ # Convert PDF to images + extract headers from text layer
84
  if path.lower().endswith(".pdf"):
85
  import fitz
86
+ pdf_headers = extract_pdf_headers(path)
87
  doc = fitz.open(path)
88
  page_images = []
89
  for i in range(len(doc)):
90
+ pix = doc[i].get_pixmap(matrix=fitz.Matrix(1.5, 1.5), alpha=False)
91
  img_path = f"/tmp/maas_page_{i}.png"
92
  pix.save(img_path)
93
  page_images.append(img_path)
94
  doc.close()
95
  result = parse(page_images)
96
  else:
97
+ pdf_headers = []
98
  result = parse(path)
99
 
100
+ # Parse result
101
+ pages_data = result.json_result if hasattr(result, "json_result") else []
102
+ if not isinstance(pages_data, list):
103
+ pages_data = [pages_data] if pages_data else []
104
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  total_headers = 0
106
  total_footers = 0
107
+ all_markdown = []
108
+ all_summary = []
109
+
110
  for page_num, page_regions in enumerate(pages_data):
111
  if not isinstance(page_regions, list):
112
  page_regions = [page_regions] if page_regions else []
113
+
114
+ page_md = []
115
  page_summary = [f"── PAGE {page_num + 1} of {len(pages_data)} ──"]
116
+
117
+ # Inject header/footer from PDF text layer
118
+ # (API never returns these as separate labeled regions)
119
+ if pdf_headers and page_num < len(pdf_headers):
120
+ hdr = pdf_headers[page_num]["header"]
121
+ ftr = pdf_headers[page_num]["footer"]
122
+ if hdr:
123
+ total_headers += 1
124
+ page_md.append("<!-- HEADER -->\n" + hdr)
125
+ page_summary.append("πŸ”΅ HEADER: " + hdr[:100])
126
+ if ftr:
127
+ total_footers += 1
128
+ page_md.append("<!-- FOOTER -->\n" + ftr)
129
+ page_summary.append("🟒 FOOTER: " + ftr[:100])
130
+
131
+ # Process API regions (text, table, etc.)
132
  for region in page_regions:
133
  if not isinstance(region, dict):
134
  continue
135
+ label = region.get("label", "text")
136
  content = str(region.get("content", ""))
137
+
138
  if label in ABANDON:
139
  continue
140
+
141
+ # API returns 'header'/'footer' labels in some docs
142
+ # Keep them too in case the API does label them
143
  if label == "header":
144
  total_headers += 1
145
+ page_summary.append("πŸ”΅ HEADER (API): " + content[:100])
146
+ page_md.append("<!-- HEADER -->\n" + content)
147
  elif label == "footer":
148
  total_footers += 1
149
+ page_summary.append("🟒 FOOTER (API): " + content[:100])
150
+ page_md.append("<!-- FOOTER -->\n" + content)
151
  else:
152
+ page_summary.append("[" + label + "]: " + content[:100])
153
  page_md.append(content)
154
+
155
  all_markdown.append("\n\n".join(page_md))
156
  all_summary.extend(page_summary)
157
  all_summary.append("")
158
+
159
+ summary = (
160
+ "Total pages : " + str(len(pages_data)) + "\n"
161
+ "Headers found : " + str(total_headers) + "\n"
162
+ "Footers found : " + str(total_footers) + "\n"
163
+ + "─" * 40 + "\n"
164
+ + "\n".join(all_summary)
165
  )
166
+
167
  markdown = "\n\n---\n\n".join(all_markdown) if all_markdown else "(No content)"
 
168
  return markdown, summary
169
 
170
  except Exception as e:
171
  import traceback
172
+ return "Error: " + str(e) + "\n\n" + traceback.format_exc(), "Failed."
173
+
174
+ # ── STEP 5: Gradio UI ─────────────────────────────────────────
175
+ with gr.Blocks(title="GLM-OCR β€” MaaS (Header & Footer)") as demo:
176
+ gr.Markdown("""
177
+ # πŸ” GLM-OCR β€” Zhipu MaaS
178
+ Upload PDF or image. Headers πŸ”΅ and Footers 🟒 now appear in output.
179
+ Multi-page PDFs fully supported.
180
+ """)
181
+
182
+ file_input = gr.File(
183
+ label="Upload PDF or Image",
184
+ file_types=[".pdf", ".png", ".jpg", ".jpeg", ".tiff", ".bmp"]
185
+ )
186
+ run_btn = gr.Button("β–Ά Run OCR", variant="primary", size="lg")
187
 
 
 
 
 
 
188
  with gr.Row():
189
  with gr.Column():
190
  gr.Markdown("### πŸ“„ Markdown Output")
191
  markdown_out = gr.Textbox(lines=30, label="")
192
  with gr.Column():
193
+ gr.Markdown("### πŸ—‚οΈ Detected Regions")
194
  regions_out = gr.Textbox(lines=30, label="")
195
+
196
+ run_btn.click(fn=run_ocr, inputs=file_input,
197
+ outputs=[markdown_out, regions_out])
198
+
199
  demo.launch()