# app.py import gradio as gr import pandas as pd import os import asyncio from typing import Optional # Importações de nossos módulos locais from utils import Historico, setup_font, gerar_pdf_report from workflow import executar_consulta from llama_index.core import Settings from llama_index.llms.groq import Groq # --- 1. CONFIGURAÇÃO INICIAL --- # Carrega a chave da API dos Secrets do Hugging Face API_KEY = os.environ.get("GROQ_API_KEY") # Prepara a fonte para geração do PDF FONT_PATH = setup_font() # Configura o LLM do LlamaIndex if API_KEY: Settings.llm = Groq(model="meta-llama/llama-4-scout-17b-16e-instruct", api_key=API_KEY) print("✅ LLM configurado com sucesso!") else: print("❌ AVISO: A chave GROQ_API_KEY não foi encontrada nos Secrets. A aplicação não funcionará.") # --- 2. FUNÇÕES DE CALLBACK DA INTERFACE --- def carregar_dados(file, df_estado): if file is None: return "❌ Nenhum arquivo selecionado", df_estado try: df_local = pd.read_csv(file.name) return f"✅ Arquivo carregado! {df_local.shape[0]} linhas.", df_local except Exception as e: return f"❌ Erro ao carregar: {str(e)}", df_estado def processar_pergunta(pergunta: str, df_local: Optional[pd.DataFrame], historico: Historico): if df_local is None: resposta = "❌ Por favor, carregue um arquivo CSV primeiro." return resposta, historico if not pergunta.strip(): resposta = "❌ Por favor, digite uma pergunta válida." return resposta, historico resultado = asyncio.run(executar_consulta(pergunta, df_local)) resposta = resultado.get("resposta_final", "❌ Erro: a resposta não foi gerada.") historico.adicionar(pergunta, resposta) return resposta, historico def chat_interface(pergunta, chat_history, df_local, historico_obj): chat_history.append({"role": "user", "content": pergunta}) resposta, historico_obj_atualizado = processar_pergunta(pergunta, df_local, historico_obj) chat_history.append({"role": "assistant", "content": resposta}) return "", chat_history, historico_obj_atualizado def gerar_pdf_callback(historico: Historico): return gerar_pdf_report(historico, FONT_PATH) def limpar_conversa(): return Historico(), None # --- 3. DEFINIÇÃO DA INTERFACE GRADIO --- with gr.Blocks(title="Pandas CSV Analyzer", theme=gr.themes.Soft()) as app: gr.Markdown( """

🐼 Pandas CSV Analyzer (LlamaIndex)

Faça upload de um arquivo CSV, faça perguntas em linguagem natural e baixe o relatório!

""" ) df_estado = gr.State() historico_estado = gr.State(value=Historico()) with gr.Row(): with gr.Column(scale=1): input_arquivo = gr.File(label="1. Faça upload do CSV", file_types=[".csv"]) upload_status = gr.Textbox(label="Status", interactive=False) botao_gerar_pdf = gr.Button("📄 Gerar e Baixar PDF", variant="secondary") output_pdf = gr.File(label="Baixar Relatório", interactive=False) with gr.Column(scale=3): chatbot = gr.Chatbot(label="Histórico da Conversa", height=550, type='messages') with gr.Row(): input_pergunta = gr.Textbox(scale=4, show_label=False, placeholder="Ex: Qual o total de vendas por filial?", container=False) botao_enviar = gr.Button("Enviar", variant="primary", scale=1, min_width=100) # Conexões dos Eventos input_arquivo.upload(fn=carregar_dados, inputs=[input_arquivo, df_estado], outputs=[upload_status, df_estado]) botao_enviar.click(fn=chat_interface, inputs=[input_pergunta, chatbot, df_estado, historico_estado], outputs=[input_pergunta, chatbot, historico_estado]) input_pergunta.submit(fn=chat_interface, inputs=[input_pergunta, chatbot, df_estado, historico_estado], outputs=[input_pergunta, chatbot, historico_estado]) botao_gerar_pdf.click(fn=gerar_pdf_callback, inputs=[historico_estado], outputs=[output_pdf]) chatbot.clear(fn=limpar_conversa, inputs=[], outputs=[historico_estado, output_pdf]) # --- 4. LANÇAR A APLICAÇÃO --- if __name__ == "__main__": if not API_KEY: print("A aplicação não pode iniciar sem a chave GROQ_API_KEY. Por favor, configure-a nos secrets do seu Space.") else: app.launch()