vicmanmkt commited on
Commit
10ba768
·
verified ·
1 Parent(s): 9ff372a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +241 -0
app.py ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import fitz # PyMuPDF
3
+ from pathlib import Path
4
+ import gradio as gr
5
+ import google.generativeai as genai
6
+ import time
7
+ import tempfile
8
+ from PIL import Image
9
+
10
+ class PDFTranscriberGradio:
11
+ def __init__(self):
12
+ self.temp_files = []
13
+
14
+ def get_selected_model(self, model_choice):
15
+ """Retorna o ID do modelo selecionado"""
16
+ return model_choice.split(" - ")[0].strip()
17
+
18
+ def convert_pdf_page_to_image(self, pdf_document, page_number):
19
+ """Converte uma página do PDF em imagem e salva temporariamente"""
20
+ page = pdf_document[page_number]
21
+ pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
22
+ img_data = pix.tobytes("png")
23
+
24
+ # Criar arquivo temporário com nome único baseado no timestamp
25
+ temp_filename = f'page_{page_number}_{int(time.time()*1000)}.png'
26
+ temp_path = os.path.join(tempfile.gettempdir(), temp_filename)
27
+
28
+ with open(temp_path, 'wb') as temp_file:
29
+ temp_file.write(img_data)
30
+
31
+ # Adicionar à lista de arquivos temporários
32
+ self.temp_files.append(temp_path)
33
+ return temp_path
34
+
35
+ def analyze_page_with_gemini(self, image_path, page_num, model_name, temperature, top_p, top_k):
36
+ """Analisa uma página usando o modelo Gemini selecionado"""
37
+ try:
38
+ # Carregar a imagem
39
+ img = Image.open(image_path)
40
+
41
+ # Configurar o modelo Gemini
42
+ model = genai.GenerativeModel(model_name)
43
+
44
+ # Criar prompt
45
+ prompt = """Analise esta página do documento em detalhes. Por favor, inclua:
46
+ 1. Conteúdo textual e sua organização
47
+ 2. Layout e estrutura visual
48
+ 3. Elementos gráficos, tabelas ou imagens
49
+ 4. Informações importantes ou destaques
50
+ 5. Formatação e estilo do documento"""
51
+
52
+ # Gerar resposta
53
+ response = model.generate_content([prompt, img], generation_config={
54
+ 'temperature': temperature,
55
+ 'max_output_tokens': 4096,
56
+ 'top_p': top_p,
57
+ 'top_k': int(top_k),
58
+ })
59
+
60
+ # Fechar a imagem explicitamente
61
+ img.close()
62
+
63
+ return response.text
64
+
65
+ except Exception as e:
66
+ return f"Erro ao analisar página {page_num}: {str(e)}"
67
+
68
+ def cleanup_temp_files(self):
69
+ """Limpa todos os arquivos temporários"""
70
+ for temp_file in self.temp_files:
71
+ try:
72
+ if os.path.exists(temp_file):
73
+ # Tentar várias vezes em caso de arquivo em uso
74
+ for _ in range(3):
75
+ try:
76
+ os.unlink(temp_file)
77
+ break
78
+ except PermissionError:
79
+ time.sleep(0.5)
80
+ except Exception as e:
81
+ print(f"Aviso: Não foi possível remover arquivo temporário {temp_file}: {e}")
82
+ self.temp_files = []
83
+
84
+ def extract_text_from_pdf(self, pdf_path):
85
+ try:
86
+ doc = fitz.open(pdf_path)
87
+ text = ""
88
+ for page in doc:
89
+ text += page.get_text()
90
+ return text
91
+ except Exception as e:
92
+ raise Exception(f"Erro ao extrair texto do PDF: {str(e)}")
93
+
94
+ def process_pdf(self, pdf_file, api_key, model_choice, temperature, top_p, top_k):
95
+ status_updates = ["Iniciando processamento..."]
96
+ yield "\n".join(status_updates), None, None
97
+
98
+ try:
99
+ # Verificar se o arquivo foi fornecido
100
+ if pdf_file is None:
101
+ raise Exception("Nenhum arquivo enviado")
102
+
103
+ # Configurar API Gemini
104
+ if not api_key or api_key.strip() == "":
105
+ raise Exception("API Key não fornecida")
106
+ genai.configure(api_key=api_key)
107
+
108
+ # Obter o modelo selecionado
109
+ model_name = self.get_selected_model(model_choice)
110
+
111
+ # Abrir o PDF
112
+ # Gradio retorna um objeto NamedString, precisamos usar o caminho do arquivo
113
+ doc = fitz.open(pdf_file.name)
114
+
115
+ # Extrair texto tradicional
116
+ status_updates.append("Extraindo texto do PDF...")
117
+ yield "\n".join(status_updates), None, None
118
+
119
+ text_content = ""
120
+ for page in doc:
121
+ text_content += page.get_text()
122
+
123
+ # Analisar cada página como imagem
124
+ status_updates.append("Analisando páginas como imagens...")
125
+ yield "\n".join(status_updates), None, None
126
+
127
+ page_analyses = []
128
+
129
+ for page_num in range(len(doc)):
130
+ status_updates.append(f"Processando página {page_num + 1} de {len(doc)}...")
131
+ yield "\n".join(status_updates), None, None
132
+
133
+ image_path = self.convert_pdf_page_to_image(doc, page_num)
134
+ analysis = self.analyze_page_with_gemini(
135
+ image_path,
136
+ page_num + 1,
137
+ model_name,
138
+ temperature,
139
+ top_p,
140
+ top_k
141
+ )
142
+ page_analyses.append(f"\n=== Análise da Página {page_num + 1} ===\n{analysis}")
143
+
144
+ # Combinar resultados
145
+ final_output = "=== CONTEÚDO TEXTUAL ===\n\n"
146
+ final_output += text_content
147
+ final_output += "\n\n=== ANÁLISE VISUAL DAS PÁGINAS ===\n"
148
+ final_output += "\n".join(page_analyses)
149
+
150
+ # Gerar nome para arquivo de saída
151
+ output_filename = f"analise_pdf_{int(time.time())}.txt"
152
+ output_path = os.path.join(tempfile.gettempdir(), output_filename)
153
+
154
+ # Salvar resultado
155
+ with open(output_path, 'w', encoding='utf-8') as f:
156
+ f.write(final_output)
157
+
158
+ status_updates.append(f"Análise completa! Arquivo salvo temporariamente.")
159
+
160
+ # Retornar o conteúdo e o caminho do arquivo para download
161
+ yield "\n".join(status_updates), final_output, output_path
162
+
163
+ except Exception as e:
164
+ error_msg = f"Erro: {str(e)}"
165
+ status_updates.append(error_msg)
166
+ yield "\n".join(status_updates), None, None
167
+
168
+ finally:
169
+ # Limpar arquivos temporários
170
+ self.cleanup_temp_files()
171
+
172
+ def create_interface(self):
173
+ with gr.Blocks(title="Transcritor de PDF com Gemini API") as interface:
174
+ gr.Markdown("# Transcritor de PDF com Gemini API")
175
+
176
+ with gr.Row():
177
+ with gr.Column():
178
+ api_key = gr.Textbox(label="API Key Gemini", type="password")
179
+ pdf_file = gr.File(label="Arquivo PDF", file_types=[".pdf"])
180
+
181
+ with gr.Row():
182
+ model_choice = gr.Dropdown(
183
+ label="Modelo",
184
+ choices=[
185
+ "gemini-2.0-flash-exp - Última geração (Experimental)",
186
+ "gemini-1.5-flash - Rápido e versátil",
187
+ "gemini-1.5-flash-8b - Alto volume",
188
+ "gemini-1.5-pro - Raciocínio complexo"
189
+ ],
190
+ value="gemini-1.5-pro - Raciocínio complexo"
191
+ )
192
+
193
+ with gr.Row():
194
+ temperature = gr.Slider(
195
+ label="Temperatura",
196
+ minimum=0.0,
197
+ maximum=1.0,
198
+ step=0.1,
199
+ value=0.4
200
+ )
201
+
202
+ with gr.Row():
203
+ top_p = gr.Slider(
204
+ label="Top P",
205
+ minimum=0.0,
206
+ maximum=1.0,
207
+ step=0.1,
208
+ value=0.8
209
+ )
210
+
211
+ top_k = gr.Slider(
212
+ label="Top K",
213
+ minimum=1,
214
+ maximum=40,
215
+ step=1,
216
+ value=32
217
+ )
218
+
219
+ process_button = gr.Button("Transcrever e Analisar")
220
+
221
+ with gr.Column():
222
+ status_output = gr.Textbox(label="Status", lines=10)
223
+ result_output = gr.Textbox(label="Resultado", lines=20)
224
+ file_output = gr.File(label="Download do Resultado")
225
+
226
+ process_button.click(
227
+ fn=self.process_pdf,
228
+ inputs=[pdf_file, api_key, model_choice, temperature, top_p, top_k],
229
+ outputs=[status_output, result_output, file_output],
230
+ show_progress=True
231
+ )
232
+
233
+ return interface
234
+
235
+ def run(self):
236
+ interface = self.create_interface()
237
+ interface.launch()
238
+
239
+ if __name__ == "__main__":
240
+ app = PDFTranscriberGradio()
241
+ app.run()