Spaces:
Sleeping
Sleeping
| import requests | |
| import gradio as gr | |
| import os | |
| import uuid | |
| import PyPDF2 | |
| from PIL import Image | |
| import imageio | |
| import random | |
| from gtts import gTTS | |
| from reportlab.lib.pagesizes import letter | |
| from reportlab.platypus import SimpleDocTemplate, Paragraph | |
| from reportlab.lib.styles import getSampleStyleSheet | |
| # Configuração da API do Google Gemini | |
| API_KEYS = [ | |
| 'AIzaSyAgmf1ZvNrvzAmlNCQvQbyZDJJPdMwecqY', | |
| 'AIzaSyB18Z-Ct2-IKYGZ9vKaChcee-BDVS77Ksg', | |
| 'AIzaSyBB5Tp0xdXcemLMGDm8_cL6L37wTe_8sjg', | |
| 'AIzaSyCefvhXMsgHmAF_0KVkZ0UAeZ5nNC41v-A', | |
| ] | |
| def escolher_chave_api(): | |
| return random.choice(API_KEYS) | |
| GEMINI_API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key={}" | |
| class AssistenteAcademico: | |
| def __init__(self): | |
| self.contexto_atual = {} | |
| self.ultima_imagem_path = None | |
| self.pasta_temp = 'assistente_temp' | |
| for pasta in [self.pasta_temp, 'audios_assistente', 'pdfs_respostas']: | |
| os.makedirs(pasta, exist_ok=True) | |
| def gerar_pdf_resposta(self, texto, nome_arquivo=None): | |
| try: | |
| nome_arquivo = nome_arquivo or f'resposta_{uuid.uuid4()}.pdf' | |
| caminho_pdf = os.path.join('pdfs_respostas', nome_arquivo) | |
| doc = SimpleDocTemplate(caminho_pdf, pagesize=letter) | |
| styles = getSampleStyleSheet() | |
| story = [Paragraph(texto.replace('\n', '<br/>'), styles['Normal'])] | |
| doc.build(story) | |
| return caminho_pdf | |
| except Exception as e: | |
| return f"Erro ao criar PDF: {str(e)}" | |
| def texto_para_audio(self, texto, nome_arquivo=None): | |
| try: | |
| nome_arquivo = nome_arquivo or f'audio_{uuid.uuid4()}.mp3' | |
| caminho_audio = os.path.join('audios_assistente', nome_arquivo) | |
| tts = gTTS(texto, lang='pt-br') | |
| tts.save(caminho_audio) | |
| return caminho_audio | |
| except Exception as e: | |
| return f"Erro ao criar áudio: {str(e)}" | |
| def codificar_imagem(self, imagem_path): | |
| try: | |
| if not os.path.exists(imagem_path): | |
| raise ValueError("Arquivo de imagem não encontrado") | |
| extensao = os.path.splitext(imagem_path)[1].lower() | |
| formatos_suportados = {'.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff', '.webp'} | |
| if extensao not in formatos_suportados: | |
| raise ValueError(f"Formato de imagem não suportado: {extensao}") | |
| imagem = imageio.imread(imagem_path) | |
| imagem_pil = Image.fromarray(imagem) | |
| imagem_pil.thumbnail((800, 800), Image.Resampling.LANCZOS) | |
| temp_path = os.path.join(self.pasta_temp, f'temp_image_{uuid.uuid4()}{extensao}') | |
| imagem_pil.convert('RGB').save(temp_path, quality=95) | |
| return temp_path | |
| except Exception as e: | |
| return f"Erro ao codificar imagem: {str(e)}" | |
| def extrair_texto_pdf(self, arquivo_pdf): | |
| try: | |
| if not arquivo_pdf or not os.path.exists(arquivo_pdf): | |
| return "Nenhum PDF válido fornecido" | |
| leitor_pdf = PyPDF2.PdfReader(arquivo_pdf) | |
| texto = "\n".join(pagina.extract_text() or "" for pagina in leitor_pdf.pages) | |
| return texto if texto.strip() else "Nenhum texto extraído do PDF" | |
| except Exception as e: | |
| return f"Erro ao extrair texto do PDF: {str(e)}" | |
| def processar_input(self, pergunta, pdf=None, imagem=None): | |
| try: | |
| if not pergunta: | |
| return "Por favor, forneça uma pergunta", None, None | |
| # Preparar o conteúdo para a API | |
| conteudo = [{"role": "user", "parts": [{"text": self.contexto_atual.get('pdf_texto', '')}]}] | |
| if pdf: | |
| texto_pdf = self.extrair_texto_pdf(pdf) | |
| self.contexto_atual['pdf_texto'] = texto_pdf | |
| conteudo[0]["parts"].append({"text": texto_pdf}) | |
| if imagem: | |
| if self.ultima_imagem_path and os.path.exists(self.ultima_imagem_path): | |
| os.remove(self.ultima_imagem_path) | |
| imagem_path = self.codificar_imagem(imagem) | |
| if isinstance(imagem_path, str) and os.path.exists(imagem_path): | |
| self.ultima_imagem_path = imagem_path | |
| with open(imagem_path, "rb") as img_file: | |
| conteudo[0]["parts"].append({ | |
| "inline_data": { | |
| "mime_type": f"image/{os.path.splitext(imagem_path)[1][1:]}", | |
| "data": base64.b64encode(img_file.read()).decode('utf-8') | |
| } | |
| }) | |
| prompt = f"""Como um assistente acadêmico avançado: | |
| - Seja objetivo e acadêmico | |
| - Forneça explicações claras | |
| - Use linguagem técnica quando apropriado | |
| - Cite referências se possível | |
| - Mantenha a explicação acessível | |
| Pergunta atual: {pergunta} | |
| """ | |
| conteudo[0]["parts"].append({"text": prompt}) | |
| # Fazer a requisição à API | |
| headers = {"Content-Type": "application/json"} | |
| api_key = escolher_chave_api() | |
| response = requests.post( | |
| GEMINI_API_URL.format(api_key), | |
| json={"contents": conteudo}, | |
| headers=headers | |
| ) | |
| if response.status_code != 200: | |
| return f"Erro na API: {response.status_code} - {response.text}", None, None | |
| resposta_json = response.json() | |
| texto_resposta = resposta_json["candidates"][0]["content"]["parts"][0]["text"] | |
| caminho_audio = self.texto_para_audio(texto_resposta) | |
| caminho_pdf = self.gerar_pdf_resposta(texto_resposta) | |
| return texto_resposta, caminho_audio, caminho_pdf | |
| except Exception as e: | |
| return f"Erro no processamento: {str(e)}", None, None | |
| def limpar_arquivos_temporarios(self): | |
| import time | |
| pastas = [self.pasta_temp, 'audios_assistente', 'pdfs_respostas'] | |
| for pasta in pastas: | |
| for arquivo in os.listdir(pasta): | |
| caminho = os.path.join(pasta, arquivo) | |
| if os.path.isfile(caminho) and time.time() - os.path.getctime(caminho) > 3600: | |
| try: | |
| os.remove(caminho) | |
| except: | |
| pass | |
| def chatbot_interface(self): | |
| with gr.Blocks(title="Assistente Acadêmico") as interface: | |
| gr.Markdown("# 🎓 Assistente Acadêmico\nFaça suas perguntas e carregue arquivos para análise.") | |
| chatbot = gr.Chatbot(label="Conversa") | |
| with gr.Row(): | |
| audio_output = gr.Audio(label="Resposta em Áudio") | |
| pdf_output = gr.File(label="Resposta em PDF") | |
| with gr.Row(): | |
| msg = gr.Textbox(label="Pergunta", placeholder="Digite sua pergunta...") | |
| pdf_input = gr.File(file_types=['.pdf'], label="Carregar PDF") | |
| img_input = gr.File(file_types=['.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff', '.webp'], | |
| label="Carregar Imagem") | |
| submit_btn = gr.Button("Enviar") | |
| def responder(mensagem, historico, pdf=None, imagem=None): | |
| resposta, audio, pdf_file = self.processar_input(mensagem, pdf, imagem) | |
| historico.append((mensagem, resposta)) | |
| self.limpar_arquivos_temporarios() | |
| return "", historico, audio, pdf_file | |
| submit_btn.click( | |
| fn=responder, | |
| inputs=[msg, chatbot, pdf_input, img_input], | |
| outputs=[msg, chatbot, audio_output, pdf_output] | |
| ) | |
| return interface | |
| if __name__ == "__main__": | |
| assistente = AssistenteAcademico() | |
| interface = assistente.chatbot_interface() | |
| print("🚀 Assistente Acadêmico inicializado!") | |
| interface.launch(debug=True, share=True) |