Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import os | |
| import time | |
| import fitz # PyMuPDF | |
| from docx import Document | |
| from docx.shared import Inches | |
| from docx.oxml import OxmlElement | |
| from docx.oxml.ns import qn | |
| from tqdm import tqdm | |
| from dotenv import load_dotenv | |
| from modelo_clip import ValidatorVITImgTexto | |
| from openai import OpenAI | |
| import re | |
| from threading import Thread | |
| from queue import Queue | |
| from gradio_pdf import PDF | |
| # 🔹 Carregar variáveis de ambiente | |
| load_dotenv() | |
| secretk = os.environ.get("OPENAI_API_KEY") | |
| cliente_openai = OpenAI(api_key=secretk) | |
| # 🔹 Criar pastas para armazenar arquivos | |
| os.makedirs("uploads", exist_ok=True) | |
| os.makedirs("clippings", exist_ok=True) | |
| # 🔹 Justificar parágrafos no Word | |
| def justify_paragraph(paragraph): | |
| p = paragraph._element | |
| pPr = p.get_or_add_pPr() | |
| jc = OxmlElement('w:jc') | |
| jc.set(qn('w:val'), 'both') | |
| pPr.append(jc) | |
| # 🔹 Função para extrair texto do PDF | |
| def extract_content(pdf_path): | |
| doc = fitz.open(pdf_path) | |
| extracted_data = [] | |
| for page_num, page in enumerate(doc, start=1): | |
| page_data = { | |
| "page_number": page_num, | |
| "text": page.get_text("text"), | |
| "link": f"{os.path.basename(pdf_path)}#page={page_num}" | |
| } | |
| extracted_data.append(page_data) | |
| return extracted_data | |
| # 🔹 Função para identificar palavras-chave no texto | |
| def find_keywords(text, keywords): | |
| detected = [kw for kw in keywords if kw.lower() in text.lower()] | |
| return detected | |
| # 🔹 Função para gerar resumos via OpenAI | |
| def generate_summary(text): | |
| prompt = f"Resuma o seguinte texto em poucas frases mantendo os pontos principais:\n\n{text}" | |
| try: | |
| response = cliente_openai.chat.completions.create( | |
| model="gpt-4o", | |
| messages=[{"role": "system", "content": "Você é um assistente que resume textos de forma objetiva."}, | |
| {"role": "user", "content": prompt}], | |
| temperature=0.3, | |
| max_tokens=150 | |
| ) | |
| return response.choices[0].message.content.strip() | |
| except Exception as e: | |
| return f"Erro ao gerar resumo: {e}" | |
| # 🔹 Filtrar conteúdo com base nas palavras-chave e gerar resumos | |
| def filter_content(extracted_data, keywords): | |
| filtered_data = [] | |
| for page in extracted_data: | |
| detected_keywords = find_keywords(page["text"], keywords) | |
| if detected_keywords: | |
| summary = generate_summary(page["text"]) | |
| filtered_data.append({ | |
| "page_number": page["page_number"], | |
| "summary": summary, | |
| "text": page["text"], | |
| "keywords": ", ".join(detected_keywords), | |
| "link": page["link"] | |
| }) | |
| return filtered_data | |
| # 🔹 Criar um documento Word com os resumos | |
| def generate_word_from_summary(filtered_data, output_path): | |
| doc = Document() | |
| if not filtered_data: | |
| doc.add_paragraph("Nenhum conteúdo relevante encontrado.") | |
| else: | |
| for page in filtered_data: | |
| doc.add_heading(f"Resumo da Página {page['page_number']}", level=2) | |
| doc.add_paragraph(f"**Palavras-chave encontradas:** {page['keywords']}") | |
| doc.add_paragraph(f"**Resumo:** {page['summary']}") | |
| doc.add_paragraph(f"📎 [Acesse a Página]({page['link']})") | |
| doc.add_paragraph("-" * 50) | |
| doc.save(output_path) | |
| def generate_clickable_link(pdf_path, page_number): | |
| """ | |
| Gera um link funcional para acessar uma página específica do PDF dentro do Gradio. | |
| """ | |
| pdf_filename = os.path.basename(pdf_path) # Pega apenas o nome do arquivo | |
| link = f'<a href="{pdf_filename}#page={page_number}" target="_blank">📄 Acesse a Página {page_number}</a>' | |
| return link | |
| # 🔹 Processamento do PDF no Gradio | |
| def process_pdf(uploaded_pdf): | |
| if not uploaded_pdf: | |
| return "Nenhum arquivo enviado.", None | |
| pdf_path = uploaded_pdf | |
| output_docx = os.path.join("clippings", f"clipping_{int(time.time())}.docx") | |
| keywords = ["Governo Federal", "Ceará", "infraestrutura", "saúde", "educação", "segurança pública"] | |
| extracted_data = extract_content(pdf_path) | |
| filtered_data = filter_content(extracted_data, keywords) | |
| generate_word_from_summary(filtered_data, output_docx) | |
| resumos = [] | |
| for page in extracted_data: | |
| summary = generate_summary(page["text"]) | |
| resumos.append({ | |
| "page_number": page["page_number"], | |
| "summary": summary | |
| }) | |
| return resumos | |
| # 🔹 Criar botões e resumos interativos em Markdown com HTML | |
| def create_summary_buttons(resumos): | |
| markdown_content = "" | |
| for r in resumos: | |
| page_num = r["page_number"] | |
| summary = r["summary"] | |
| markdown_content += f""" | |
| <button style='padding:5px;margin:5px;' onclick=' | |
| const pages = document.querySelectorAll(".pdf-container .page"); | |
| if(pages && pages.length >= {page_num}){{ | |
| pages[{page_num}-1].scrollIntoView({{ behavior: "smooth" }}); | |
| }} | |
| '>📄 Ir para Página {page_num}</button> | |
| <strong>🔑 Resumo:</strong> {summary}<br><hr> | |
| """ | |
| return markdown_content if markdown_content else "Nenhum resumo disponível." | |
| # 🔹 Interface Gradio | |
| with gr.Blocks() as demo: | |
| gr.Markdown("### 📑 Clipapptor - IA para Resumo de PDFs") | |
| with gr.Row(): | |
| with gr.Column(scale=1): # Lado esquerdo | |
| uploaded_pdf = PDF(label="📤 Faça upload do PDF", interactive=True, height=650) | |
| #page_input = gr.Number(value=1, label="Página", interactive=True) | |
| #go_to_page_button = gr.Button("Ir para Página", elem_id="go-to-page-button") | |
| with gr.Column(scale=1): # Lado direito | |
| process_button = gr.Button("📄 Gerar Clippings do Jornal") | |
| resumo_output = gr.Markdown("Aguardando resumos...", render=True, height=650) | |
| # 🔹 Função para navegação no PDF | |
| # def go_to_page(page_number): | |
| # return page_number | |
| def process_and_create_buttons(pdf): | |
| resumos = process_pdf(pdf) | |
| return create_summary_buttons(resumos) | |
| process_button.click( | |
| fn=process_and_create_buttons, | |
| inputs=[uploaded_pdf], | |
| outputs=[resumo_output] | |
| ) | |
| # go_to_page_button.click(fn=go_to_page, inputs=[page_input], outputs=[page_input]) | |
| demo.launch(share=True) | |