Spaces:
Sleeping
Sleeping
File size: 8,187 Bytes
476fea0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
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() |