heerjtdev commited on
Commit
af33c93
Β·
verified Β·
1 Parent(s): ab7d396

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +201 -67
app.py CHANGED
@@ -1,3 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import json
3
  import os
@@ -19,128 +170,111 @@ except ImportError:
19
 
20
  def process_file(uploaded_files, layoutlmv3_model_path=None):
21
  """
22
- Converts multiple images into a single PDF (if necessary) and routes
23
- the result to the YOLO/OCR pipeline as a single entity.
24
  """
25
- if not uploaded_files:
26
  return "❌ Error: No files uploaded.", None
27
 
28
- # Ensure we are working with a list of files (Gradio file_count="multiple" returns a list)
 
 
29
  if not isinstance(uploaded_files, list):
30
- uploaded_files = [uploaded_files]
 
 
31
 
32
- # 1. Resolve all file paths
 
 
 
 
33
  resolved_paths = []
34
- for f in uploaded_files:
35
- if hasattr(f, 'path'):
36
- resolved_paths.append(f.path)
37
- elif isinstance(f, dict):
38
- resolved_paths.append(f.get("path"))
39
- else:
40
- resolved_paths.append(str(f))
 
 
 
 
 
 
41
 
42
  # 2. Determine if we should merge into a single PDF
43
- # We merge if there are multiple files OR if the single file is an image
44
  first_file = Path(resolved_paths[0])
45
  is_image = first_file.suffix.lower() in ['.jpg', '.jpeg', '.png', '.bmp', '.webp', '.tiff']
46
 
47
- processing_path = None
48
-
49
  try:
50
- if len(resolved_paths) > 1 or (len(resolved_paths) == 1 and is_image):
51
- print(f"πŸ“¦ Converting {len(resolved_paths)} image(s) to a single PDF entity...")
 
52
  temp_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
53
- # img2pdf.convert converts a list of image paths into PDF bytes
54
- with open(temp_pdf.name, "wb") as f:
55
- f.write(img2pdf.convert(resolved_paths))
56
  processing_path = temp_pdf.name
57
  else:
58
- # It's a single PDF, process directly
59
  processing_path = resolved_paths[0]
60
 
61
  # 3. Standard Pipeline Checks
62
- if not layoutlmv3_model_path:
63
- layoutlmv3_model_path = DEFAULT_LAYOUTLMV3_MODEL_PATH
64
-
65
- if not os.path.exists(layoutlmv3_model_path):
66
- return f"❌ Error: LayoutLMv3 model not found at {layoutlmv3_model_path}", None
67
-
68
- if not os.path.exists(WEIGHTS_PATH):
69
- return f"❌ Error: YOLO weights not found at {WEIGHTS_PATH}", None
70
-
71
- print(f"πŸš€ Starting pipeline for merged entity: {processing_path}")
72
 
73
  # 4. Call the pipeline
74
- result = run_document_pipeline(processing_path, layoutlmv3_model_path)
 
75
 
76
  if result is None:
77
- return "❌ Error: Pipeline failed to process the document.", None
78
 
79
  # 5. Prepare output
80
  temp_output = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json', prefix='analysis_')
81
  with open(temp_output.name, 'w', encoding='utf-8') as f:
82
  json.dump(result, f, indent=2, ensure_ascii=False)
83
 
84
- json_display = json.dumps(result, indent=2, ensure_ascii=False)
85
- return json_display, temp_output.name
86
 
87
  except Exception as e:
88
  import traceback
89
  traceback.print_exc()
90
- return f"❌ Error during processing: {str(e)}", None
91
 
92
  # ==============================
93
  # GRADIO INTERFACE
94
  # ==============================
95
  with gr.Blocks(title="Document Analysis Pipeline") as demo:
96
 
97
- gr.Markdown("""
98
- # πŸ“„ Document & Image Analysis Pipeline
99
- Upload **multiple images** or a **PDF**. Multiple images will be processed together as a single continuous document.
100
- """)
101
 
102
  with gr.Row():
103
  with gr.Column(scale=1):
104
  file_input = gr.File(
105
  label="Upload PDFs or Images",
106
  file_types=[".pdf", ".jpg", ".jpeg", ".png", ".bmp", ".webp", ".tiff"],
107
- type="filepath",
108
- file_count="multiple" # ALLOWS MULTIPLE FILES
109
  )
110
 
111
  model_path_input = gr.Textbox(
112
- label="LayoutLMv3 Model Path (optional)",
113
- placeholder=DEFAULT_LAYOUTLMV3_MODEL_PATH,
114
- value=DEFAULT_LAYOUTLMV3_MODEL_PATH,
115
- interactive=True
116
  )
117
 
118
- process_btn = gr.Button("πŸš€ Process Files", variant="primary", size="lg")
119
 
120
  with gr.Column(scale=2):
121
- json_output = gr.Code(
122
- label="Combined Structured JSON Output",
123
- language="json",
124
- lines=25
125
- )
126
-
127
- download_output = gr.File(
128
- label="Download Full JSON",
129
- interactive=False
130
- )
131
 
132
- # UI Logic
133
  process_btn.click(
134
  fn=process_file,
135
  inputs=[file_input, model_path_input],
136
- outputs=[json_output, download_output],
137
- api_name="process_document"
138
  )
139
 
140
  if __name__ == "__main__":
141
- demo.launch(
142
- server_name="0.0.0.0",
143
- server_port=7860,
144
- share=False,
145
- show_error=True
146
- )
 
1
+ # import gradio as gr
2
+ # import json
3
+ # import os
4
+ # import tempfile
5
+ # import img2pdf
6
+ # from pathlib import Path
7
+
8
+ # # ==============================
9
+ # # PIPELINE IMPORT
10
+ # # ==============================
11
+ # try:
12
+ # from working_yolo_pipeline import run_document_pipeline, DEFAULT_LAYOUTLMV3_MODEL_PATH, WEIGHTS_PATH
13
+ # except ImportError:
14
+ # print("Warning: 'working_yolo_pipeline.py' not found. Using dummy paths.")
15
+ # def run_document_pipeline(*args):
16
+ # return {"error": "Placeholder pipeline function called."}
17
+ # DEFAULT_LAYOUTLMV3_MODEL_PATH = "./models/layoutlmv3_model"
18
+ # WEIGHTS_PATH = "./weights/yolo_weights.pt"
19
+
20
+ # def process_file(uploaded_files, layoutlmv3_model_path=None):
21
+ # """
22
+ # Converts multiple images into a single PDF (if necessary) and routes
23
+ # the result to the YOLO/OCR pipeline as a single entity.
24
+ # """
25
+ # if not uploaded_files:
26
+ # return "❌ Error: No files uploaded.", None
27
+
28
+ # # Ensure we are working with a list of files (Gradio file_count="multiple" returns a list)
29
+ # if not isinstance(uploaded_files, list):
30
+ # uploaded_files = [uploaded_files]
31
+
32
+ # # 1. Resolve all file paths
33
+ # resolved_paths = []
34
+ # for f in uploaded_files:
35
+ # if hasattr(f, 'path'):
36
+ # resolved_paths.append(f.path)
37
+ # elif isinstance(f, dict):
38
+ # resolved_paths.append(f.get("path"))
39
+ # else:
40
+ # resolved_paths.append(str(f))
41
+
42
+ # # 2. Determine if we should merge into a single PDF
43
+ # # We merge if there are multiple files OR if the single file is an image
44
+ # first_file = Path(resolved_paths[0])
45
+ # is_image = first_file.suffix.lower() in ['.jpg', '.jpeg', '.png', '.bmp', '.webp', '.tiff']
46
+
47
+ # processing_path = None
48
+
49
+ # try:
50
+ # if len(resolved_paths) > 1 or (len(resolved_paths) == 1 and is_image):
51
+ # print(f"πŸ“¦ Converting {len(resolved_paths)} image(s) to a single PDF entity...")
52
+ # temp_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
53
+ # # img2pdf.convert converts a list of image paths into PDF bytes
54
+ # with open(temp_pdf.name, "wb") as f:
55
+ # f.write(img2pdf.convert(resolved_paths))
56
+ # processing_path = temp_pdf.name
57
+ # else:
58
+ # # It's a single PDF, process directly
59
+ # processing_path = resolved_paths[0]
60
+
61
+ # # 3. Standard Pipeline Checks
62
+ # if not layoutlmv3_model_path:
63
+ # layoutlmv3_model_path = DEFAULT_LAYOUTLMV3_MODEL_PATH
64
+
65
+ # if not os.path.exists(layoutlmv3_model_path):
66
+ # return f"❌ Error: LayoutLMv3 model not found at {layoutlmv3_model_path}", None
67
+
68
+ # if not os.path.exists(WEIGHTS_PATH):
69
+ # return f"❌ Error: YOLO weights not found at {WEIGHTS_PATH}", None
70
+
71
+ # print(f"πŸš€ Starting pipeline for merged entity: {processing_path}")
72
+
73
+ # # 4. Call the pipeline
74
+ # result = run_document_pipeline(processing_path, layoutlmv3_model_path)
75
+
76
+ # if result is None:
77
+ # return "❌ Error: Pipeline failed to process the document.", None
78
+
79
+ # # 5. Prepare output
80
+ # temp_output = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json', prefix='analysis_')
81
+ # with open(temp_output.name, 'w', encoding='utf-8') as f:
82
+ # json.dump(result, f, indent=2, ensure_ascii=False)
83
+
84
+ # json_display = json.dumps(result, indent=2, ensure_ascii=False)
85
+ # return json_display, temp_output.name
86
+
87
+ # except Exception as e:
88
+ # import traceback
89
+ # traceback.print_exc()
90
+ # return f"❌ Error during processing: {str(e)}", None
91
+
92
+ # # ==============================
93
+ # # GRADIO INTERFACE
94
+ # # ==============================
95
+ # with gr.Blocks(title="Document Analysis Pipeline") as demo:
96
+
97
+ # gr.Markdown("""
98
+ # # πŸ“„ Document & Image Analysis Pipeline
99
+ # Upload **multiple images** or a **PDF**. Multiple images will be processed together as a single continuous document.
100
+ # """)
101
+
102
+ # with gr.Row():
103
+ # with gr.Column(scale=1):
104
+ # file_input = gr.File(
105
+ # label="Upload PDFs or Images",
106
+ # file_types=[".pdf", ".jpg", ".jpeg", ".png", ".bmp", ".webp", ".tiff"],
107
+ # type="filepath",
108
+ # file_count="multiple" # ALLOWS MULTIPLE FILES
109
+ # )
110
+
111
+ # model_path_input = gr.Textbox(
112
+ # label="LayoutLMv3 Model Path (optional)",
113
+ # placeholder=DEFAULT_LAYOUTLMV3_MODEL_PATH,
114
+ # value=DEFAULT_LAYOUTLMV3_MODEL_PATH,
115
+ # interactive=True
116
+ # )
117
+
118
+ # process_btn = gr.Button("πŸš€ Process Files", variant="primary", size="lg")
119
+
120
+ # with gr.Column(scale=2):
121
+ # json_output = gr.Code(
122
+ # label="Combined Structured JSON Output",
123
+ # language="json",
124
+ # lines=25
125
+ # )
126
+
127
+ # download_output = gr.File(
128
+ # label="Download Full JSON",
129
+ # interactive=False
130
+ # )
131
+
132
+ # # UI Logic
133
+ # process_btn.click(
134
+ # fn=process_file,
135
+ # inputs=[file_input, model_path_input],
136
+ # outputs=[json_output, download_output],
137
+ # api_name="process_document"
138
+ # )
139
+
140
+ # if __name__ == "__main__":
141
+ # demo.launch(
142
+ # server_name="0.0.0.0",
143
+ # server_port=7860,
144
+ # share=False,
145
+ # show_error=True
146
+ # )
147
+
148
+
149
+
150
+
151
+
152
  import gradio as gr
153
  import json
154
  import os
 
170
 
171
  def process_file(uploaded_files, layoutlmv3_model_path=None):
172
  """
173
+ Robust handler for multiple or single file uploads.
 
174
  """
175
+ if uploaded_files is None:
176
  return "❌ Error: No files uploaded.", None
177
 
178
+ # --- THE ROBUST FIX ---
179
+ # Gradio sometimes sends a single dict even when set to multiple.
180
+ # We force everything into a list so the rest of the logic doesn't break.
181
  if not isinstance(uploaded_files, list):
182
+ file_list = [uploaded_files]
183
+ else:
184
+ file_list = uploaded_files
185
 
186
+ if len(file_list) == 0:
187
+ return "❌ Error: Empty file list.", None
188
+ # ----------------------
189
+
190
+ # 1. Resolve all file paths safely
191
  resolved_paths = []
192
+ for f in file_list:
193
+ try:
194
+ if isinstance(f, dict) and "path" in f:
195
+ resolved_paths.append(f["path"])
196
+ elif hasattr(f, 'path'):
197
+ resolved_paths.append(f.path)
198
+ else:
199
+ resolved_paths.append(str(f))
200
+ except Exception as e:
201
+ print(f"Error resolving path for {f}: {e}")
202
+
203
+ if not resolved_paths:
204
+ return "❌ Error: Could not resolve file paths.", None
205
 
206
  # 2. Determine if we should merge into a single PDF
 
207
  first_file = Path(resolved_paths[0])
208
  is_image = first_file.suffix.lower() in ['.jpg', '.jpeg', '.png', '.bmp', '.webp', '.tiff']
209
 
 
 
210
  try:
211
+ # If it's multiple files or just one image, wrap it in a PDF
212
+ if len(resolved_paths) > 1 or is_image:
213
+ print(f"πŸ“¦ Converting {len(resolved_paths)} image(s) to a single PDF...")
214
  temp_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
215
+ with open(temp_pdf.name, "wb") as f_out:
216
+ f_out.write(img2pdf.convert(resolved_paths))
 
217
  processing_path = temp_pdf.name
218
  else:
219
+ # It's a single PDF
220
  processing_path = resolved_paths[0]
221
 
222
  # 3. Standard Pipeline Checks
223
+ final_model_path = layoutlmv3_model_path or DEFAULT_LAYOUTLMV3_MODEL_PATH
224
+ if not os.path.exists(final_model_path):
225
+ return f"❌ Error: Model not found at {final_model_path}", None
 
 
 
 
 
 
 
226
 
227
  # 4. Call the pipeline
228
+ print(f"πŸš€ Starting pipeline for: {processing_path}")
229
+ result = run_document_pipeline(processing_path, final_model_path)
230
 
231
  if result is None:
232
+ return "❌ Error: Pipeline returned None.", None
233
 
234
  # 5. Prepare output
235
  temp_output = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json', prefix='analysis_')
236
  with open(temp_output.name, 'w', encoding='utf-8') as f:
237
  json.dump(result, f, indent=2, ensure_ascii=False)
238
 
239
+ return json.dumps(result, indent=2, ensure_ascii=False), temp_output.name
 
240
 
241
  except Exception as e:
242
  import traceback
243
  traceback.print_exc()
244
+ return f"❌ Error: {str(e)}", None
245
 
246
  # ==============================
247
  # GRADIO INTERFACE
248
  # ==============================
249
  with gr.Blocks(title="Document Analysis Pipeline") as demo:
250
 
251
+ gr.Markdown("# πŸ“„ Document & Image Analysis Pipeline")
 
 
 
252
 
253
  with gr.Row():
254
  with gr.Column(scale=1):
255
  file_input = gr.File(
256
  label="Upload PDFs or Images",
257
  file_types=[".pdf", ".jpg", ".jpeg", ".png", ".bmp", ".webp", ".tiff"],
258
+ file_count="multiple", # Keep this
259
+ type="filepath" # Keep this
260
  )
261
 
262
  model_path_input = gr.Textbox(
263
+ label="Model Path",
264
+ value=DEFAULT_LAYOUTLMV3_MODEL_PATH
 
 
265
  )
266
 
267
+ process_btn = gr.Button("πŸš€ Process Files", variant="primary")
268
 
269
  with gr.Column(scale=2):
270
+ json_output = gr.Code(label="JSON Output", language="json", lines=20)
271
+ download_output = gr.File(label="Download JSON")
 
 
 
 
 
 
 
 
272
 
 
273
  process_btn.click(
274
  fn=process_file,
275
  inputs=[file_input, model_path_input],
276
+ outputs=[json_output, download_output]
 
277
  )
278
 
279
  if __name__ == "__main__":
280
+ demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True)