prithivMLmods commited on
Commit
fb01e72
·
verified ·
1 Parent(s): 44691c0

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -324
app.py DELETED
@@ -1,324 +0,0 @@
1
- import spaces
2
- import json
3
- import math
4
- import os
5
- import traceback
6
- from io import BytesIO
7
- from typing import Any, Dict, List, Optional, Tuple
8
- import re
9
- import time
10
- from threading import Thread
11
- from io import BytesIO
12
- import uuid
13
- import tempfile
14
-
15
- import gradio as gr
16
- import requests
17
- import torch
18
- from PIL import Image
19
- import fitz
20
- import numpy as np
21
-
22
- from transformers import AutoModelForCausalLM, AutoTokenizer, Qwen2VLImageProcessor
23
-
24
- from reportlab.lib.pagesizes import A4
25
- from reportlab.lib.styles import getSampleStyleSheet
26
- from reportlab.platypus import SimpleDocTemplate, Image as RLImage, Paragraph, Spacer
27
- from reportlab.lib.units import inch
28
-
29
- # --- Constants and Model Setup ---
30
- MAX_INPUT_TOKEN_LENGTH = 4096
31
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
32
-
33
- print("CUDA_VISIBLE_DEVICES=", os.environ.get("CUDA_VISIBLE_DEVICES"))
34
- print("torch.__version__ =", torch.__version__)
35
- print("torch.version.cuda =", torch.version.cuda)
36
- print("cuda available:", torch.cuda.is_available())
37
- print("cuda device count:", torch.cuda.device_count())
38
- if torch.cuda.is_available():
39
- print("current device:", torch.cuda.current_device())
40
- print("device name:", torch.cuda.get_device_name(torch.cuda.current_device()))
41
-
42
- print("Using device:", device)
43
-
44
-
45
- # --- Model Loading: tencent/POINTS-Reader ---
46
- MODEL_PATH = 'tencent/POINTS-Reader'
47
-
48
- print(f"Loading model: {MODEL_PATH}")
49
- model = AutoModelForCausalLM.from_pretrained(
50
- MODEL_PATH,
51
- trust_remote_code=True,
52
- torch_dtype=torch.float16,
53
- device_map='auto'
54
- )
55
- tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)
56
- image_processor = Qwen2VLImageProcessor.from_pretrained(MODEL_PATH)
57
- print("Model loaded successfully.")
58
-
59
-
60
- # --- PDF Generation and Preview Utility Function ---
61
- def generate_and_preview_pdf(image: Image.Image, text_content: str, font_size: int, line_spacing: float, alignment: str, image_size: str):
62
- """
63
- Generates a PDF, saves it, and then creates image previews of its pages.
64
- Returns the path to the PDF and a list of paths to the preview images.
65
- """
66
- if image is None or not text_content or not text_content.strip():
67
- raise gr.Error("Cannot generate PDF. Image or text content is missing.")
68
-
69
- # --- 1. Generate the PDF ---
70
- temp_dir = tempfile.gettempdir()
71
- pdf_filename = os.path.join(temp_dir, f"output_{uuid.uuid4()}.pdf")
72
- doc = SimpleDocTemplate(
73
- pdf_filename,
74
- pagesize=A4,
75
- rightMargin=inch, leftMargin=inch,
76
- topMargin=inch, bottomMargin=inch
77
- )
78
- styles = getSampleStyleSheet()
79
- style_normal = styles["Normal"]
80
- style_normal.fontSize = int(font_size)
81
- style_normal.leading = int(font_size) * line_spacing
82
- style_normal.alignment = {"Left": 0, "Center": 1, "Right": 2, "Justified": 4}[alignment]
83
-
84
- story = []
85
-
86
- img_buffer = BytesIO()
87
- image.save(img_buffer, format='PNG')
88
- img_buffer.seek(0)
89
-
90
- page_width, _ = A4
91
- available_width = page_width - 2 * inch
92
- image_widths = {
93
- "Small": available_width * 0.3,
94
- "Medium": available_width * 0.6,
95
- "Large": available_width * 0.9,
96
- }
97
- img_width = image_widths[image_size]
98
- img = RLImage(img_buffer, width=img_width, height=image.height * (img_width / image.width))
99
- story.append(img)
100
- story.append(Spacer(1, 12))
101
-
102
- cleaned_text = re.sub(r'#+\s*', '', text_content).replace("*", "")
103
- text_paragraphs = cleaned_text.split('\n')
104
-
105
- for para in text_paragraphs:
106
- if para.strip():
107
- story.append(Paragraph(para, style_normal))
108
-
109
- doc.build(story)
110
-
111
- # --- 2. Render PDF pages as images for preview ---
112
- preview_images = []
113
- try:
114
- pdf_doc = fitz.open(pdf_filename)
115
- for page_num in range(len(pdf_doc)):
116
- page = pdf_doc.load_page(page_num)
117
- pix = page.get_pixmap(dpi=150)
118
- preview_img_path = os.path.join(temp_dir, f"preview_{uuid.uuid4()}_p{page_num}.png")
119
- pix.save(preview_img_path)
120
- preview_images.append(preview_img_path)
121
- pdf_doc.close()
122
- except Exception as e:
123
- print(f"Error generating PDF preview: {e}")
124
-
125
- return pdf_filename, preview_images
126
-
127
-
128
- # --- Core Application Logic ---
129
- @spaces.GPU
130
- def process_document_stream(
131
- image: Image.Image,
132
- prompt_input: str,
133
- image_scale_factor: float, # New parameter for image scaling
134
- max_new_tokens: int,
135
- temperature: float,
136
- top_p: float,
137
- top_k: int,
138
- repetition_penalty: float
139
- ):
140
- """
141
- Main function that handles model inference using tencent/POINTS-Reader.
142
- """
143
- if image is None:
144
- yield "Please upload an image.", ""
145
- return
146
- if not prompt_input or not prompt_input.strip():
147
- yield "Please enter a prompt.", ""
148
- return
149
-
150
- # --- IMPLEMENTATION: Image Scaling based on user input ---
151
- if image_scale_factor > 1.0:
152
- try:
153
- original_width, original_height = image.size
154
- new_width = int(original_width * image_scale_factor)
155
- new_height = int(original_height * image_scale_factor)
156
- print(f"Scaling image from {image.size} to ({new_width}, {new_height}) with factor {image_scale_factor}.")
157
- # Use a high-quality resampling filter for better results
158
- image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
159
- except Exception as e:
160
- print(f"Error during image scaling: {e}")
161
- # Continue with the original image if scaling fails
162
- pass
163
- # --- END IMPLEMENTATION ---
164
-
165
- temp_image_path = None
166
- try:
167
- # --- FIX: Save the PIL Image to a temporary file ---
168
- # The model expects a file path, not a PIL object.
169
- temp_dir = tempfile.gettempdir()
170
- temp_image_path = os.path.join(temp_dir, f"temp_image_{uuid.uuid4()}.png")
171
- image.save(temp_image_path)
172
-
173
- # Prepare content for the model using the temporary file path
174
- content = [
175
- dict(type='image', image=temp_image_path),
176
- dict(type='text', text=prompt_input)
177
- ]
178
- messages = [
179
- {
180
- 'role': 'user',
181
- 'content': content
182
- }
183
- ]
184
-
185
- # Prepare generation configuration from UI inputs
186
- generation_config = {
187
- 'max_new_tokens': max_new_tokens,
188
- 'repetition_penalty': repetition_penalty,
189
- 'temperature': temperature,
190
- 'top_p': top_p,
191
- 'top_k': top_k,
192
- 'do_sample': True if temperature > 0 else False
193
- }
194
-
195
- # Run inference
196
- response = model.chat(
197
- messages,
198
- tokenizer,
199
- image_processor,
200
- generation_config
201
- )
202
- # Yield the full response at once
203
- yield response, response
204
-
205
- except Exception as e:
206
- traceback.print_exc()
207
- yield f"An error occurred during processing: {str(e)}", ""
208
- finally:
209
- # --- Clean up the temporary image file ---
210
- if temp_image_path and os.path.exists(temp_image_path):
211
- os.remove(temp_image_path)
212
-
213
-
214
- # --- Gradio UI Definition ---
215
- def create_gradio_interface():
216
- """Builds and returns the Gradio web interface."""
217
- css = """
218
- .main-container { max-width: 1400px; margin: 0 auto; }
219
- .process-button { border: none !important; color: white !important; font-weight: bold !important; background-color: blue !important;}
220
- .process-button:hover { background-color: darkblue !important; transform: translateY(-2px) !important; box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important; }
221
- #gallery { min-height: 400px; }
222
- """
223
- with gr.Blocks(theme="bethecloud/storj_theme", css=css) as demo:
224
- gr.HTML(f"""
225
- <div class="title" style="text-align: center">
226
- <h1>Document Conversion with POINTS Reader 📖</h1>
227
- <p style="font-size: 1.1em; color: #6b7280; margin-bottom: 0.6em;">
228
- Using tencent/POINTS-Reader Multimodal for Image Content Extraction
229
- </p>
230
- </div>
231
- """)
232
-
233
- with gr.Row():
234
- # Left Column (Inputs)
235
- with gr.Column(scale=1):
236
- gr.Textbox(
237
- label="Model in Use ⚡",
238
- value="tencent/POINTS-Reader",
239
- interactive=False
240
- )
241
- prompt_input = gr.Textbox(
242
- label="Query Input",
243
- placeholder="✦︎ Enter the prompt",
244
- value="Perform OCR on the image precisely.",
245
- )
246
- image_input = gr.Image(label="Upload Image", type="pil", sources=['upload'])
247
-
248
- with gr.Accordion("Advanced Settings", open=False):
249
- # --- NEW UI ELEMENT: Image Scaling Slider ---
250
- image_scale_factor = gr.Slider(
251
- minimum=1.0,
252
- maximum=3.0,
253
- value=1.0,
254
- step=0.1,
255
- label="Image Upscale Factor",
256
- info="Increases image size before processing. Can improve OCR on small text. Default: 1.0 (no change)."
257
- )
258
- # --- END NEW UI ELEMENT ---
259
- max_new_tokens = gr.Slider(minimum=512, maximum=8192, value=2048, step=256, label="Max New Tokens")
260
- temperature = gr.Slider(label="Temperature", minimum=0.1, maximum=1.0, step=0.05, value=0.7)
261
- top_p = gr.Slider(label="Top-p (nucleus sampling)", minimum=0.05, maximum=1.0, step=0.05, value=0.8)
262
- top_k = gr.Slider(label="Top-k", minimum=1, maximum=100, step=1, value=20)
263
- repetition_penalty = gr.Slider(label="Repetition penalty", minimum=1.0, maximum=2.0, step=0.05, value=1.05)
264
-
265
- gr.Markdown("### PDF Export Settings")
266
- font_size = gr.Dropdown(choices=["8", "10", "12", "14", "16", "18"], value="12", label="Font Size")
267
- line_spacing = gr.Dropdown(choices=[1.0, 1.15, 1.5, 2.0], value=1.15, label="Line Spacing")
268
- alignment = gr.Dropdown(choices=["Left", "Center", "Right", "Justified"], value="Justified", label="Text Alignment")
269
- image_size = gr.Dropdown(choices=["Small", "Medium", "Large"], value="Medium", label="Image Size in PDF")
270
-
271
- process_btn = gr.Button("🚀 Process Image", variant="primary", elem_classes=["process-button"], size="lg")
272
- clear_btn = gr.Button("🗑️ Clear All", variant="secondary")
273
-
274
- # Right Column (Outputs)
275
- with gr.Column(scale=2):
276
- with gr.Tabs() as tabs:
277
- with gr.Tab("📝 Extracted Content"):
278
- raw_output_stream = gr.Textbox(label="Raw Model Output (max T ≤ 120s)", interactive=False, lines=15, show_copy_button=True)
279
- with gr.Row():
280
- examples = gr.Examples(
281
- examples=["examples/1.jpeg",
282
- "examples/2.jpeg",
283
- "examples/3.jpeg",
284
- "examples/4.jpeg",
285
- "examples/5.jpeg"],
286
- inputs=image_input, label="Examples"
287
- )
288
- gr.Markdown("[Report-Bug💻](https://huggingface.co/spaces/prithivMLmods/POINTS-Reader-OCR/discussions) | [prithivMLmods🤗](https://huggingface.co/prithivMLmods)")
289
-
290
- with gr.Tab("📰 README.md"):
291
- with gr.Accordion("(Result.md)", open=True):
292
- markdown_output = gr.Markdown()
293
-
294
- with gr.Tab("📋 PDF Preview"):
295
- generate_pdf_btn = gr.Button("📄 Generate PDF & Render", variant="primary")
296
- pdf_output_file = gr.File(label="Download Generated PDF", interactive=False)
297
- pdf_preview_gallery = gr.Gallery(label="PDF Page Preview", show_label=True, elem_id="gallery", columns=2, object_fit="contain", height="auto")
298
-
299
- # Event Handlers
300
- def clear_all_outputs():
301
- return None, "", "Raw output will appear here.", "", None, None
302
-
303
- process_btn.click(
304
- fn=process_document_stream,
305
- # --- UPDATE: Add the new slider to the inputs list ---
306
- inputs=[image_input, prompt_input, image_scale_factor, max_new_tokens, temperature, top_p, top_k, repetition_penalty],
307
- outputs=[raw_output_stream, markdown_output]
308
- )
309
-
310
- generate_pdf_btn.click(
311
- fn=generate_and_preview_pdf,
312
- inputs=[image_input, raw_output_stream, font_size, line_spacing, alignment, image_size],
313
- outputs=[pdf_output_file, pdf_preview_gallery]
314
- )
315
-
316
- clear_btn.click(
317
- clear_all_outputs,
318
- outputs=[image_input, prompt_input, raw_output_stream, markdown_output, pdf_output_file, pdf_preview_gallery]
319
- )
320
- return demo
321
-
322
- if __name__ == "__main__":
323
- demo = create_gradio_interface()
324
- demo.queue(max_size=50).launch(share=True, show_error=True)