fccoelho aider (anthropic/claude-sonnet-4-20250514) commited on
Commit
33f14fa
·
1 Parent(s): a68e0ce

feat: adicionar destaque de referências regex no texto extraído

Browse files

Co-authored-by: aider (anthropic/claude-sonnet-4-20250514) <aider@aider.chat>

Files changed (1) hide show
  1. app.py +106 -10
app.py CHANGED
@@ -197,16 +197,113 @@ def extract_references_with_regex(text):
197
  except Exception as e:
198
  return [{"error": f"Erro na extração por regex: {str(e)}"}]
199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  def process_pdf(pdf_file, model_name):
201
  """Função principal que processa o PDF e retorna resultados"""
202
  if pdf_file is None:
203
- return {"error": "Nenhum arquivo enviado"}, pd.DataFrame(), pd.DataFrame(), "❌ Nenhum arquivo enviado", ""
204
 
205
  # Extrair texto do PDF
206
  text, metadata = extract_pdf_text(pdf_file)
207
 
208
  if text is None:
209
- return metadata, pd.DataFrame(), pd.DataFrame(), "❌ Erro ao processar PDF", ""
210
 
211
  # Adicionar modelo selecionado aos metadados
212
  metadata["modelo_usado"] = model_name
@@ -219,6 +316,9 @@ def process_pdf(pdf_file, model_name):
219
  # Extrair referências com Regex
220
  regex_references = extract_references_with_regex(text)
221
 
 
 
 
222
  # Converter para DataFrames
223
  if llm_references and not any("error" in ref for ref in llm_references):
224
  llm_df = pd.DataFrame(llm_references)
@@ -236,7 +336,7 @@ def process_pdf(pdf_file, model_name):
236
 
237
  status = f"📊 **Resultados da Extração:**\n- LLM ({model_name}): {llm_count} referências\n- Regex: {regex_count} referências"
238
 
239
- return metadata, llm_df, regex_df, status, text
240
 
241
  def create_interface():
242
  """Cria a interface Gradio"""
@@ -272,13 +372,9 @@ def create_interface():
272
  with gr.Column():
273
  metadata_output = gr.JSON(label="📋 Metadados do Artigo")
274
  with gr.Column():
275
- extracted_text_output = gr.Textbox(
276
- label="📄 Texto Extraído do PDF",
277
- lines=15,
278
- max_lines=20,
279
- show_copy_button=True,
280
- placeholder="O texto extraído do PDF aparecerá aqui...",
281
- interactive=False
282
  )
283
 
284
  with gr.Row():
 
197
  except Exception as e:
198
  return [{"error": f"Erro na extração por regex: {str(e)}"}]
199
 
200
+ def create_highlighted_text(text, regex_references):
201
+ """Cria HTML com texto destacado onde foram encontradas referências por regex"""
202
+ try:
203
+ # Encontrar a seção de referências
204
+ references_section = ""
205
+ section_start = 0
206
+
207
+ # Padrões para identificar início da seção de referências
208
+ ref_patterns = [
209
+ r'(?i)references?\s*\n',
210
+ r'(?i)bibliography\s*\n',
211
+ r'(?i)literatura\s+citada\s*\n',
212
+ r'(?i)referências\s+bibliográficas\s*\n'
213
+ ]
214
+
215
+ for pattern in ref_patterns:
216
+ match = re.search(pattern, text)
217
+ if match:
218
+ section_start = match.start()
219
+ references_section = text[match.end():]
220
+ break
221
+
222
+ if not references_section:
223
+ # Se não encontrou seção específica, usar últimos 30% do texto
224
+ section_start = int(len(text) * 0.7)
225
+ references_section = text[section_start:]
226
+
227
+ # Criar HTML base
228
+ html_text = text.replace('\n', '<br>')
229
+
230
+ # Cores para diferentes tipos de matches
231
+ colors = ['#ffeb3b', '#4caf50', '#2196f3', '#ff9800', '#9c27b0']
232
+
233
+ # Padrões para destacar
234
+ patterns = [
235
+ (r'([A-Z][^.]*?)\.\s*\((\d{4})\)\.\s*([^.]+)\.\s*([^.]+?)(?:\.|$)', 'Padrão básico'),
236
+ (r'\[\d+\]\s*([A-Z][^.]*?)\.\s*\((\d{4})\)\.\s*([^.]+)\.\s*([^.]+?)(?:\.|$)', 'Padrão numerado'),
237
+ (r'([A-Z][A-Za-z\s,&]+)\s+\((\d{4})\)[.,]\s*([^.]+)[.,]\s*([^.]+?)(?:\.|$)', 'Padrão alternativo'),
238
+ (r'(?i)references?\s*\n', 'Seção de referências'),
239
+ (r'(?i)bibliography\s*\n', 'Bibliografia')
240
+ ]
241
+
242
+ # Aplicar destaques
243
+ for i, (pattern, description) in enumerate(patterns):
244
+ color = colors[i % len(colors)]
245
+
246
+ # Encontrar matches no texto da seção de referências
247
+ section_html = references_section.replace('\n', '<br>')
248
+ matches = list(re.finditer(pattern, references_section, re.MULTILINE | re.DOTALL))
249
+
250
+ # Destacar matches (processar de trás para frente para não afetar posições)
251
+ for match in reversed(matches):
252
+ start, end = match.span()
253
+ matched_text = references_section[start:end]
254
+ highlighted = f'<span style="background-color: {color}; padding: 2px; border-radius: 3px;" title="{description}">{matched_text.replace(chr(10), "<br>")}</span>'
255
+
256
+ # Calcular posição no texto completo
257
+ full_start = section_start + start
258
+ full_end = section_start + end
259
+
260
+ # Substituir no HTML completo
261
+ before = html_text[:full_start].replace('\n', '<br>')
262
+ after = html_text[full_end:].replace('\n', '<br>')
263
+ html_text = before + highlighted + after
264
+
265
+ # Criar HTML final com estilo
266
+ styled_html = f"""
267
+ <div style="
268
+ font-family: 'Courier New', monospace;
269
+ font-size: 12px;
270
+ line-height: 1.4;
271
+ max-height: 400px;
272
+ overflow-y: auto;
273
+ padding: 15px;
274
+ border: 1px solid #ddd;
275
+ border-radius: 5px;
276
+ background-color: #fafafa;
277
+ white-space: pre-wrap;
278
+ ">
279
+ <div style="margin-bottom: 10px; font-weight: bold; color: #333;">
280
+ 📄 Texto Extraído com Destaques das Referências
281
+ </div>
282
+ <div style="margin-bottom: 15px; font-size: 11px; color: #666;">
283
+ <span style="background-color: #ffeb3b; padding: 2px;">■</span> Padrão básico &nbsp;
284
+ <span style="background-color: #4caf50; padding: 2px;">■</span> Padrão numerado &nbsp;
285
+ <span style="background-color: #2196f3; padding: 2px;">■</span> Padrão alternativo &nbsp;
286
+ <span style="background-color: #ff9800; padding: 2px;">■</span> Seção referências
287
+ </div>
288
+ {html_text}
289
+ </div>
290
+ """
291
+
292
+ return styled_html
293
+
294
+ except Exception as e:
295
+ return f"<div style='color: red;'>Erro ao criar texto destacado: {str(e)}</div>"
296
+
297
  def process_pdf(pdf_file, model_name):
298
  """Função principal que processa o PDF e retorna resultados"""
299
  if pdf_file is None:
300
+ return {"error": "Nenhum arquivo enviado"}, pd.DataFrame(), pd.DataFrame(), "❌ Nenhum arquivo enviado", "<div>Nenhum texto para exibir</div>"
301
 
302
  # Extrair texto do PDF
303
  text, metadata = extract_pdf_text(pdf_file)
304
 
305
  if text is None:
306
+ return metadata, pd.DataFrame(), pd.DataFrame(), "❌ Erro ao processar PDF", "<div style='color: red;'>Erro ao extrair texto</div>"
307
 
308
  # Adicionar modelo selecionado aos metadados
309
  metadata["modelo_usado"] = model_name
 
316
  # Extrair referências com Regex
317
  regex_references = extract_references_with_regex(text)
318
 
319
+ # Criar HTML com destaques
320
+ highlighted_html = create_highlighted_text(text, regex_references)
321
+
322
  # Converter para DataFrames
323
  if llm_references and not any("error" in ref for ref in llm_references):
324
  llm_df = pd.DataFrame(llm_references)
 
336
 
337
  status = f"📊 **Resultados da Extração:**\n- LLM ({model_name}): {llm_count} referências\n- Regex: {regex_count} referências"
338
 
339
+ return metadata, llm_df, regex_df, status, highlighted_html
340
 
341
  def create_interface():
342
  """Cria a interface Gradio"""
 
372
  with gr.Column():
373
  metadata_output = gr.JSON(label="📋 Metadados do Artigo")
374
  with gr.Column():
375
+ extracted_text_output = gr.HTML(
376
+ label="📄 Texto Extraído com Destaques",
377
+ show_copy_button=True
 
 
 
 
378
  )
379
 
380
  with gr.Row():