File size: 4,817 Bytes
af33c93
 
 
 
75487ef
 
 
 
ec49c23
0a214f3
75487ef
 
64b8b98
193b094
64b8b98
ae075a3
 
 
 
 
 
 
 
75487ef
ec49c23
193b094
af33c93
193b094
af33c93
ec49c23
 
af33c93
 
 
ec49c23
af33c93
 
 
ec49c23
af33c93
 
 
 
 
ec49c23
af33c93
 
 
 
 
 
 
 
 
 
 
 
 
75487ef
ec49c23
 
 
 
6bc4d1a
af33c93
 
 
ec49c23
af33c93
0a214f3
 
 
ec49c23
6bc4d1a
af33c93
ec49c23
6bc4d1a
ec49c23
af33c93
 
 
75487ef
ec49c23
af33c93
 
75487ef
 
af33c93
75487ef
ec49c23
75487ef
 
 
 
af33c93
75487ef
 
6bc4d1a
ec49c23
af33c93
75487ef
193b094
 
 
 
5ec75e6
af33c93
75487ef
 
 
193b094
ec49c23
193b094
af33c93
 
75487ef
 
 
af33c93
 
75487ef
 
af33c93
75487ef
 
af33c93
 
75487ef
 
193b094
 
af33c93
75487ef
 
 
af33c93
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136




import gradio as gr
import json
import os
import tempfile
import img2pdf
from img2pdf import Rotation
from pathlib import Path

# ==============================
# PIPELINE IMPORT
# ==============================
try:
    from working_yolo_pipeline import run_document_pipeline, DEFAULT_LAYOUTLMV3_MODEL_PATH, WEIGHTS_PATH
except ImportError:
    print("Warning: 'working_yolo_pipeline.py' not found. Using dummy paths.")
    def run_document_pipeline(*args):
        return {"error": "Placeholder pipeline function called."}
    DEFAULT_LAYOUTLMV3_MODEL_PATH = "./models/layoutlmv3_model"
    WEIGHTS_PATH = "./weights/yolo_weights.pt"

def process_file(uploaded_files, layoutlmv3_model_path=None):
    """
    Robust handler for multiple or single file uploads.
    """
    if uploaded_files is None:
        return "❌ Error: No files uploaded.", None

    # --- THE ROBUST FIX ---
    # Gradio sometimes sends a single dict even when set to multiple.
    # We force everything into a list so the rest of the logic doesn't break.
    if not isinstance(uploaded_files, list):
        file_list = [uploaded_files]
    else:
        file_list = uploaded_files

    if len(file_list) == 0:
        return "❌ Error: Empty file list.", None
    # ----------------------

    # 1. Resolve all file paths safely
    resolved_paths = []
    for f in file_list:
        try:
            if isinstance(f, dict) and "path" in f:
                resolved_paths.append(f["path"])
            elif hasattr(f, 'path'):
                resolved_paths.append(f.path)
            else:
                resolved_paths.append(str(f))
        except Exception as e:
            print(f"Error resolving path for {f}: {e}")

    if not resolved_paths:
        return "❌ Error: Could not resolve file paths.", None

    # 2. Determine if we should merge into a single PDF
    first_file = Path(resolved_paths[0])
    is_image = first_file.suffix.lower() in ['.jpg', '.jpeg', '.png', '.bmp', '.webp', '.tiff']
    
    try:
        # If it's multiple files or just one image, wrap it in a PDF
        if len(resolved_paths) > 1 or is_image:
            print(f"πŸ“¦ Converting {len(resolved_paths)} image(s) to a single PDF...")
            temp_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
            with open(temp_pdf.name, "wb") as f_out:
                # f_out.write(img2pdf.convert(resolved_paths))
                f_out.write(img2pdf.convert(resolved_paths, rotation=Rotation.ifvalid))

            processing_path = temp_pdf.name
        else:
            # It's a single PDF
            processing_path = resolved_paths[0]

        # 3. Standard Pipeline Checks
        final_model_path = layoutlmv3_model_path or DEFAULT_LAYOUTLMV3_MODEL_PATH
        if not os.path.exists(final_model_path):
            return f"❌ Error: Model not found at {final_model_path}", None

        # 4. Call the pipeline
        print(f"πŸš€ Starting pipeline for: {processing_path}")
        result = run_document_pipeline(processing_path, final_model_path)

        if result is None:
            return "❌ Error: Pipeline returned None.", None

        # 5. Prepare output
        temp_output = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json', prefix='analysis_')
        with open(temp_output.name, 'w', encoding='utf-8') as f:
            json.dump(result, f, indent=2, ensure_ascii=False)

        return json.dumps(result, indent=2, ensure_ascii=False), temp_output.name

    except Exception as e:
        import traceback
        traceback.print_exc()
        return f"❌ Error: {str(e)}", None

# ==============================
# GRADIO INTERFACE
# ==============================
with gr.Blocks(title="Document Analysis Pipeline") as demo:

    gr.Markdown("# πŸ“„ Document & Image Analysis Pipeline")

    with gr.Row():
        with gr.Column(scale=1):
            file_input = gr.File(
                label="Upload PDFs or Images",
                file_types=[".pdf", ".jpg", ".jpeg", ".png", ".bmp", ".webp", ".tiff"],
                file_count="multiple", # Keep this
                type="filepath"       # Keep this
            )

            model_path_input = gr.Textbox(
                label="Model Path",
                value=DEFAULT_LAYOUTLMV3_MODEL_PATH
            )

            process_btn = gr.Button("πŸš€ Process Files", variant="primary")

        with gr.Column(scale=2):
            json_output = gr.Code(label="JSON Output", language="json", lines=20)
            download_output = gr.File(label="Download JSON")

    process_btn.click(
        fn=process_file,
        inputs=[file_input, model_path_input],
        outputs=[json_output, download_output]
    )

if __name__ == "__main__":
    demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True)