marioluciofjr commited on
Commit
476fea0
·
verified ·
1 Parent(s): 2f1f23d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +208 -0
app.py ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from llama_index.llms.groq import Groq
2
+ from llama_index.core import PromptTemplate
3
+ from llama_index.experimental.query_engine.pandas import PandasInstructionParser
4
+ from llama_index.core.query_pipeline import (QueryPipeline as QP, Link, InputComponent)
5
+ import gradio as gr
6
+ import pandas as pd
7
+ from fpdf import FPDF
8
+ from datetime import datetime
9
+ import os
10
+
11
+ # API KEY do GROQ
12
+ api_key = os.getenv("secret_key")
13
+
14
+ # Configuração inicial do QP
15
+ llm = Groq(model="llama3-70b-8192", api_key=api_key)
16
+
17
+ # Pipeline de consulta
18
+ def descrição_colunas(df):
19
+ descrição = '\n'.join([f"`{col}`: {str(df[col].dtype)}" for col in df.columns])
20
+ return "Aqui estão os detalhes das colunas do dataframe:\n" + descrição
21
+
22
+ def pipeline_consulta(df):
23
+ instruction_str = (
24
+ "1. Converta a consulta para código Python executável usando Pandas.\n"
25
+ "2. A linha final do código deve ser uma expressão Python que possa ser chamada com a função `eval()`.\n"
26
+ "3. O código deve representar uma solução para a consulta.\n"
27
+ "4. IMPRIMA APENAS A EXPRESSÃO.\n"
28
+ "5. Não coloque a expressão entre aspas.\n")
29
+
30
+ pandas_prompt_str = (
31
+ "Você está trabalhando com um dataframe do pandas em Python chamado `df`.\n"
32
+ "{colunas_detalhes}\n\n"
33
+ "Este é o resultado de `print(df.head())`:\n"
34
+ "{df_str}\n\n"
35
+ "Siga estas instruções:\n"
36
+ "{instruction_str}\n"
37
+ "Consulta: {query_str}\n\n"
38
+ "Expressão:"
39
+ )
40
+
41
+ response_synthesis_prompt_str = (
42
+ "Dada uma pergunta de entrada, atue como analista de dados e elabore uma resposta a partir dos resultados da consulta.\n"
43
+ "Responda de forma natural, sem introduções como 'A resposta é:' ou algo semelhante.\n"
44
+ "Consulta: {query_str}\n\n"
45
+ "Instruções do Pandas (opcional):\n{pandas_instructions}\n\n"
46
+ "Saída do Pandas: {pandas_output}\n\n"
47
+ "Resposta: \n\n"
48
+ "Ao final, exibir o código usado em para gerar a resposta, no formato: O código utilizado foi `{pandas_instructions}`"
49
+ )
50
+
51
+ pandas_prompt = PromptTemplate(pandas_prompt_str).partial_format(
52
+ instruction_str=instruction_str,
53
+ df_str=df.head(5),
54
+ colunas_detalhes=descrição_colunas(df)
55
+ )
56
+
57
+ pandas_output_parser = PandasInstructionParser(df)
58
+ response_synthesis_prompt = PromptTemplate(response_synthesis_prompt_str)
59
+
60
+ # Criação do QueryPipeline
61
+
62
+ qp = QP(
63
+ modules={
64
+ "input": InputComponent(),
65
+ "pandas_prompt": pandas_prompt,
66
+ "llm1": llm,
67
+ "pandas_output_parser": pandas_output_parser,
68
+ "response_synthesis_prompt": response_synthesis_prompt,
69
+ "llm2": llm,
70
+ },
71
+ verbose=True,
72
+ )
73
+ qp.add_chain(["input", "pandas_prompt", "llm1", "pandas_output_parser"])
74
+ qp.add_links(
75
+ [
76
+ Link("input", "response_synthesis_prompt", dest_key="query_str"),
77
+ Link("llm1", "response_synthesis_prompt", dest_key="pandas_instructions"),
78
+ Link("pandas_output_parser", "response_synthesis_prompt", dest_key="pandas_output"),
79
+ ]
80
+ )
81
+ qp.add_link("response_synthesis_prompt", "llm2")
82
+ return qp
83
+
84
+ # Função para carregar os dados
85
+ def carregar_dados(caminho_arquivo, df_estado):
86
+ if caminho_arquivo is None or caminho_arquivo == "":
87
+ return "Por favor, faça o upload de um arquivo CSV para analisar.", pd.DataFrame(), df_estado
88
+ try:
89
+ df = pd.read_csv(caminho_arquivo)
90
+ return "Arquivo carregado com sucesso!", df.head(), df
91
+ except Exception as e:
92
+ return f"Erro ao carregar arquivo: {str(e)}", pd.DataFrame(), df_estado
93
+
94
+ # Função para processar a pergunta
95
+ def processar_pergunta(pergunta, df_estado):
96
+ if df_estado is not None and pergunta:
97
+ qp = pipeline_consulta(df_estado)
98
+ resposta = qp.run(query_str=pergunta)
99
+ return resposta.message.content
100
+ return ""
101
+
102
+ # Função para adicionar a pergunta e a resposta ao histórico
103
+ def add_historico(pergunta, resposta, historico_estado):
104
+ if pergunta and resposta:
105
+ historico_estado.append((pergunta, resposta))
106
+ gr.Info("Adicionado ao PDF!", duration=2)
107
+ return historico_estado
108
+
109
+ # Função para gerar o PDF
110
+ def gerar_pdf(historico_estado):
111
+ if not historico_estado:
112
+ return "Nenhum dado para adicionar ao PDF.", None
113
+
114
+ # Gerar nome de arquivo com timestamp
115
+ timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
116
+ caminho_pdf = f"relatorio_perguntas_respostas_{timestamp}.pdf"
117
+
118
+ pdf = FPDF()
119
+ pdf.add_page()
120
+ pdf.set_auto_page_break(auto=True, margin=15)
121
+
122
+ for pergunta, resposta in historico_estado:
123
+ pdf.set_font("Arial", 'B', 14)
124
+ pdf.multi_cell(0, 8, txt=pergunta)
125
+ pdf.ln(2)
126
+ pdf.set_font("Arial", '', 12)
127
+ pdf.multi_cell(0, 8, txt=resposta)
128
+ pdf.ln(6)
129
+
130
+ pdf.output(caminho_pdf)
131
+ return caminho_pdf
132
+
133
+ # Função para limpar a pergunta e a resposta
134
+ def limpar_pergunta_resposta():
135
+ return "", ""
136
+
137
+ # Função para resetar a aplicação
138
+ def resetar_aplicação():
139
+ return None, "A aplicação foi resetada. Por favor, faça upload de um novo arquivo CSV.", pd.DataFrame(), "", None, [], ""
140
+
141
+ # Criação da interface gradio
142
+ with gr.Blocks(theme='Soft') as app:
143
+
144
+ # Título da app
145
+ gr.Markdown("# Analisando os dados🔎🎲")
146
+
147
+ # Descrição
148
+ gr.Markdown('''
149
+ Carregue um arquivo CSV e faça perguntas sobre os dados. A cada pergunta, você poderá
150
+ visualizar a resposta e, se desejar, adicionar essa interação ao PDF final, basta clicar
151
+ em "Adicionar ao histórico do PDF". Para fazer uma nova pergunta, clique em "Limpar pergunta e resultado".
152
+ Após definir as perguntas e respostas no histórico, clique em "Gerar PDF". Assim, será possível
153
+ baixar um PDF com o registro completo das suas interações. Se você quiser analisar um novo dataset,
154
+ basta clicar em "Quero analisar outro dataset" ao final da página.
155
+ ''')
156
+
157
+ # Campo de entrada de arquivos
158
+ input_arquivo = gr.File(file_count="single", type="filepath", label="Upload CSV")
159
+
160
+ # Status de upload
161
+ upload_status = gr.Textbox(label="Status do Upload:")
162
+
163
+ # Tabela de dados
164
+ tabela_dados = gr.DataFrame()
165
+
166
+ # Exemplos de perguntas
167
+ gr.Markdown("""
168
+ Exemplos de perguntas:
169
+ 1. Qual é o número de registros no arquivo?
170
+ 2. Quais são os tipos de dados das colunas?
171
+ 3. Quais são as estatísticas descritivas das colunas numéricas?
172
+ """)
173
+
174
+ # Campo de entrada de texto
175
+ input_pergunta = gr.Textbox(label="Digite sua pergunta sobre os dados")
176
+
177
+ # Botão de envio posicionado após a pergunta
178
+ botao_submeter = gr.Button("Enviar")
179
+
180
+ # Componente de resposta
181
+ output_resposta = gr.Textbox(label="Resposta")
182
+
183
+ # Botões para limpar a pergunta e a resposta, adicionar ao historico e gerar o PDF
184
+ with gr.Row():
185
+ botao_limpeza = gr.Button("Limpar pergunta e resultado")
186
+ botao_add_pdf = gr.Button("Adicionar ao histórico do PDF")
187
+ botao_gerar_pdf = gr.Button("Gerar PDF")
188
+
189
+ # Componente de download
190
+ arquivo_pdf = gr.File(label="Download do PDF")
191
+
192
+ # Botão para resetar a aplicação
193
+ botao_resetar = gr.Button("Quero analisar outro dataset!")
194
+
195
+ # Gerenciamento de estados
196
+ df_estado = gr.State(value=None)
197
+ historico_estado = gr.State(value=[])
198
+
199
+ # Conectando funções aos componentes
200
+ input_arquivo.change(fn=carregar_dados, inputs=[input_arquivo, df_estado], outputs=[upload_status, tabela_dados, df_estado])
201
+ botao_submeter.click(fn=processar_pergunta, inputs=[input_pergunta, df_estado], outputs=output_resposta)
202
+ botao_limpeza.click(fn=limpar_pergunta_resposta, inputs=[], outputs=[input_pergunta, output_resposta])
203
+ botao_add_pdf.click(fn=add_historico, inputs=[input_pergunta, output_resposta, historico_estado], outputs=historico_estado)
204
+ botao_gerar_pdf.click(fn=gerar_pdf, inputs=[historico_estado], outputs=arquivo_pdf)
205
+ botao_resetar.click(fn=resetar_aplicação, inputs=[], outputs=[input_arquivo, upload_status, tabela_dados, output_resposta, arquivo_pdf, historico_estado, input_pergunta])
206
+
207
+ if __name__ == "__main__":
208
+ app.launch()