analisa_dados / app.py
marioluciofjr's picture
Create app.py
476fea0 verified
from llama_index.llms.groq import Groq
from llama_index.core import PromptTemplate
from llama_index.experimental.query_engine.pandas import PandasInstructionParser
from llama_index.core.query_pipeline import (QueryPipeline as QP, Link, InputComponent)
import gradio as gr
import pandas as pd
from fpdf import FPDF
from datetime import datetime
import os
# API KEY do GROQ
api_key = os.getenv("secret_key")
# Configuração inicial do QP
llm = Groq(model="llama3-70b-8192", api_key=api_key)
# Pipeline de consulta
def descrição_colunas(df):
descrição = '\n'.join([f"`{col}`: {str(df[col].dtype)}" for col in df.columns])
return "Aqui estão os detalhes das colunas do dataframe:\n" + descrição
def pipeline_consulta(df):
instruction_str = (
"1. Converta a consulta para código Python executável usando Pandas.\n"
"2. A linha final do código deve ser uma expressão Python que possa ser chamada com a função `eval()`.\n"
"3. O código deve representar uma solução para a consulta.\n"
"4. IMPRIMA APENAS A EXPRESSÃO.\n"
"5. Não coloque a expressão entre aspas.\n")
pandas_prompt_str = (
"Você está trabalhando com um dataframe do pandas em Python chamado `df`.\n"
"{colunas_detalhes}\n\n"
"Este é o resultado de `print(df.head())`:\n"
"{df_str}\n\n"
"Siga estas instruções:\n"
"{instruction_str}\n"
"Consulta: {query_str}\n\n"
"Expressão:"
)
response_synthesis_prompt_str = (
"Dada uma pergunta de entrada, atue como analista de dados e elabore uma resposta a partir dos resultados da consulta.\n"
"Responda de forma natural, sem introduções como 'A resposta é:' ou algo semelhante.\n"
"Consulta: {query_str}\n\n"
"Instruções do Pandas (opcional):\n{pandas_instructions}\n\n"
"Saída do Pandas: {pandas_output}\n\n"
"Resposta: \n\n"
"Ao final, exibir o código usado em para gerar a resposta, no formato: O código utilizado foi `{pandas_instructions}`"
)
pandas_prompt = PromptTemplate(pandas_prompt_str).partial_format(
instruction_str=instruction_str,
df_str=df.head(5),
colunas_detalhes=descrição_colunas(df)
)
pandas_output_parser = PandasInstructionParser(df)
response_synthesis_prompt = PromptTemplate(response_synthesis_prompt_str)
# Criação do QueryPipeline
qp = QP(
modules={
"input": InputComponent(),
"pandas_prompt": pandas_prompt,
"llm1": llm,
"pandas_output_parser": pandas_output_parser,
"response_synthesis_prompt": response_synthesis_prompt,
"llm2": llm,
},
verbose=True,
)
qp.add_chain(["input", "pandas_prompt", "llm1", "pandas_output_parser"])
qp.add_links(
[
Link("input", "response_synthesis_prompt", dest_key="query_str"),
Link("llm1", "response_synthesis_prompt", dest_key="pandas_instructions"),
Link("pandas_output_parser", "response_synthesis_prompt", dest_key="pandas_output"),
]
)
qp.add_link("response_synthesis_prompt", "llm2")
return qp
# Função para carregar os dados
def carregar_dados(caminho_arquivo, df_estado):
if caminho_arquivo is None or caminho_arquivo == "":
return "Por favor, faça o upload de um arquivo CSV para analisar.", pd.DataFrame(), df_estado
try:
df = pd.read_csv(caminho_arquivo)
return "Arquivo carregado com sucesso!", df.head(), df
except Exception as e:
return f"Erro ao carregar arquivo: {str(e)}", pd.DataFrame(), df_estado
# Função para processar a pergunta
def processar_pergunta(pergunta, df_estado):
if df_estado is not None and pergunta:
qp = pipeline_consulta(df_estado)
resposta = qp.run(query_str=pergunta)
return resposta.message.content
return ""
# Função para adicionar a pergunta e a resposta ao histórico
def add_historico(pergunta, resposta, historico_estado):
if pergunta and resposta:
historico_estado.append((pergunta, resposta))
gr.Info("Adicionado ao PDF!", duration=2)
return historico_estado
# Função para gerar o PDF
def gerar_pdf(historico_estado):
if not historico_estado:
return "Nenhum dado para adicionar ao PDF.", None
# Gerar nome de arquivo com timestamp
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
caminho_pdf = f"relatorio_perguntas_respostas_{timestamp}.pdf"
pdf = FPDF()
pdf.add_page()
pdf.set_auto_page_break(auto=True, margin=15)
for pergunta, resposta in historico_estado:
pdf.set_font("Arial", 'B', 14)
pdf.multi_cell(0, 8, txt=pergunta)
pdf.ln(2)
pdf.set_font("Arial", '', 12)
pdf.multi_cell(0, 8, txt=resposta)
pdf.ln(6)
pdf.output(caminho_pdf)
return caminho_pdf
# Função para limpar a pergunta e a resposta
def limpar_pergunta_resposta():
return "", ""
# Função para resetar a aplicação
def resetar_aplicação():
return None, "A aplicação foi resetada. Por favor, faça upload de um novo arquivo CSV.", pd.DataFrame(), "", None, [], ""
# Criação da interface gradio
with gr.Blocks(theme='Soft') as app:
# Título da app
gr.Markdown("# Analisando os dados🔎🎲")
# Descrição
gr.Markdown('''
Carregue um arquivo CSV e faça perguntas sobre os dados. A cada pergunta, você poderá
visualizar a resposta e, se desejar, adicionar essa interação ao PDF final, basta clicar
em "Adicionar ao histórico do PDF". Para fazer uma nova pergunta, clique em "Limpar pergunta e resultado".
Após definir as perguntas e respostas no histórico, clique em "Gerar PDF". Assim, será possível
baixar um PDF com o registro completo das suas interações. Se você quiser analisar um novo dataset,
basta clicar em "Quero analisar outro dataset" ao final da página.
''')
# Campo de entrada de arquivos
input_arquivo = gr.File(file_count="single", type="filepath", label="Upload CSV")
# Status de upload
upload_status = gr.Textbox(label="Status do Upload:")
# Tabela de dados
tabela_dados = gr.DataFrame()
# Exemplos de perguntas
gr.Markdown("""
Exemplos de perguntas:
1. Qual é o número de registros no arquivo?
2. Quais são os tipos de dados das colunas?
3. Quais são as estatísticas descritivas das colunas numéricas?
""")
# Campo de entrada de texto
input_pergunta = gr.Textbox(label="Digite sua pergunta sobre os dados")
# Botão de envio posicionado após a pergunta
botao_submeter = gr.Button("Enviar")
# Componente de resposta
output_resposta = gr.Textbox(label="Resposta")
# Botões para limpar a pergunta e a resposta, adicionar ao historico e gerar o PDF
with gr.Row():
botao_limpeza = gr.Button("Limpar pergunta e resultado")
botao_add_pdf = gr.Button("Adicionar ao histórico do PDF")
botao_gerar_pdf = gr.Button("Gerar PDF")
# Componente de download
arquivo_pdf = gr.File(label="Download do PDF")
# Botão para resetar a aplicação
botao_resetar = gr.Button("Quero analisar outro dataset!")
# Gerenciamento de estados
df_estado = gr.State(value=None)
historico_estado = gr.State(value=[])
# Conectando funções aos componentes
input_arquivo.change(fn=carregar_dados, inputs=[input_arquivo, df_estado], outputs=[upload_status, tabela_dados, df_estado])
botao_submeter.click(fn=processar_pergunta, inputs=[input_pergunta, df_estado], outputs=output_resposta)
botao_limpeza.click(fn=limpar_pergunta_resposta, inputs=[], outputs=[input_pergunta, output_resposta])
botao_add_pdf.click(fn=add_historico, inputs=[input_pergunta, output_resposta, historico_estado], outputs=historico_estado)
botao_gerar_pdf.click(fn=gerar_pdf, inputs=[historico_estado], outputs=arquivo_pdf)
botao_resetar.click(fn=resetar_aplicação, inputs=[], outputs=[input_arquivo, upload_status, tabela_dados, output_resposta, arquivo_pdf, historico_estado, input_pergunta])
if __name__ == "__main__":
app.launch()