drguilhermeapolinario commited on
Commit
650dac1
·
verified ·
1 Parent(s): 58ee609

Update pages/Chatbot.py

Browse files
Files changed (1) hide show
  1. pages/Chatbot.py +597 -34
pages/Chatbot.py CHANGED
@@ -1,35 +1,598 @@
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
- from openai import OpenAI
3
-
4
- # Sidebar para entrada de chave API e seleção de modelo
5
- with st.sidebar:
6
- openai_api_key = st.text_input("OpenAI API Key", key="chatbot_api_key", type="password")
7
- st.markdown("[Pegue aqui sua chave OpenAI API](https://platform.openai.com/account/api-keys)")
8
-
9
- model_selection = st.radio(
10
- "Escolha o modelo de API:",
11
- ("gpt-3.5-turbo", "gpt-4o")
12
- )
13
-
14
- st.title("💬 Chatbot")
15
- st.caption("🚀 A Streamlit chatbot powered by OpenAI")
16
-
17
- if "messages" not in st.session_state:
18
- st.session_state["messages"] = [{"role": "assistant", "content": "Olá como posso te ajudar?"}]
19
-
20
- for msg in st.session_state.messages:
21
- st.chat_message(msg["role"]).write(msg["content"])
22
-
23
- if prompt := st.chat_input():
24
- if not openai_api_key:
25
- st.info("Insira sua chave API OpenAI para continuar.")
26
- st.stop()
27
-
28
- client = OpenAI(api_key=openai_api_key)
29
- st.session_state.messages.append({"role": "user", "content": prompt})
30
- st.chat_message("user").write(prompt)
31
-
32
- response = client.chat.completions.create(model=model_selection, messages=st.session_state.messages)
33
- msg = response.choices[0].message.content
34
- st.session_state.messages.append({"role": "assistant", "content": msg})
35
- st.chat_message("assistant").write(msg)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """_summary_
2
+ LIMPEZA E VISUALIZAÇÃO DE CSV
3
+ Returns:
4
+ DATAFRAMES
5
+ """
6
+
7
+ import folium
8
+ import geopandas as gpd
9
+ import plotly.express as px
10
  import streamlit as st
11
+ from branca.colormap import LinearColormap
12
+ from groq import Groq
13
+ from streamlit_extras.add_vertical_space import add_vertical_space
14
+ from streamlit_extras.stylable_container import stylable_container
15
+ from streamlit_folium import folium_static
16
+ from streamlit_option_menu import option_menu
17
+
18
+ from data_cleaning import criar_dataframe, iniciar, limpa_rci, separa_grupos
19
+
20
+ st.set_page_config(
21
+ page_title="Dashboard UBS Flamengo",
22
+ page_icon="📊",
23
+ layout="wide",
24
+ initial_sidebar_state="expanded",
25
+ )
26
+
27
+
28
+ def processar_arquivo(file):
29
+ """
30
+ A function that processes the uploaded file by writing it to a temporary CSV file,
31
+ then performs various data cleaning operations on the CSV data to create and return dataframes.
32
+ Returns:
33
+ - dataframes: the processed dataframes generated from the uploaded file
34
+ """
35
+ with open("temp.csv", "wb") as f:
36
+ f.write(file.getbuffer())
37
+ csv_st = iniciar("temp.csv")
38
+ clean_txt = limpa_rci(csv_st)
39
+ grupos_encontrados = separa_grupos(clean_txt)
40
+ dfs = criar_dataframe(grupos_encontrados)
41
+
42
+ return dfs
43
+
44
+
45
+ # Inicializar variáveis dos DataFrames como None
46
+ DF_DATA = None
47
+ DF_HEAD = None
48
+ DF_IDADE = None
49
+ DF_GENERO = None
50
+ DF_COR = None
51
+ DF_DEFICIENCIA = None
52
+ DF_DOENCAS = None
53
+ DF_ESCOLA = None
54
+ DF_TRANSGEN = None
55
+
56
+ # Upload de arquivo CSV na barra lateral
57
+ uploaded_file = st.sidebar.file_uploader("Escolha um arquivo CSV", type="csv")
58
+
59
+ def processar_arquivo(uploaded_file):
60
+ # Função que processa o arquivo CSV e retorna os DataFrames
61
+ # (Esta função deve ser importada ou definida aqui)
62
+ pass
63
+
64
+ if uploaded_file is not None:
65
+ dataframes = processar_arquivo(uploaded_file)
66
+
67
+ # Atribuir os DataFrames a variáveis específicas para uso posterior
68
+ DF_DATA = dataframes.get("Data")
69
+ DF_HEAD = dataframes.get("Head")
70
+ DF_IDADE = dataframes.get("Idade")
71
+ DF_GENERO = dataframes.get("genero")
72
+ DF_COR = dataframes.get("cor")
73
+ DF_DEFICIENCIA = dataframes.get("deficiencia")
74
+ DF_DOENCAS = dataframes.get("doencas")
75
+ DF_ESCOLA = dataframes.get("Escola")
76
+ DF_TRANSGEN = dataframes.get("transgen")
77
+
78
+ # Aplicar capitalização à coluna "Descrição" em cada DataFrame
79
+ for df in [DF_IDADE, DF_GENERO, DF_COR, DF_DEFICIENCIA, DF_DOENCAS, DF_ESCOLA, DF_TRANSGEN]:
80
+ if df is not None:
81
+ df["Descrição"] = df["Descrição"].str.capitalize()
82
+ else:
83
+ st.sidebar.info("Adicione um arquivo .csv.")
84
+
85
+ def gerar_resumo_df():
86
+ """
87
+ Generates a summary of the dataframes.
88
+ This function iterates over the local and global variables to check if any of them
89
+ are named "DF_DATA", "DF_HEAD", "DF_IDADE", "DF_GENERO", "DF_COR", "DF_DEFICIENCIA",
90
+ "DF_DOENCAS", "DF_ESCOLA", or "DF_TRANSGEN".
91
+ If a dataframe is found, it generates a summary of the dataframe by printing its
92
+ column names and the count of each unique value in the "Descrição" column.
93
+ Returns:
94
+ str: A string containing the summary of the dataframes.
95
+ """
96
+ resumo = ""
97
+
98
+ if "DF_DATA" in locals() or "DF_DATA" in globals():
99
+ resumo += "Resumo DF_DATA:\n"
100
+ resumo += DF_DATA.to_string(index=False) + "\n\n"
101
+
102
+ if "DF_HEAD" in locals() or "DF_HEAD" in globals():
103
+ resumo += "Resumo DF_HEAD:\n"
104
+ resumo += DF_HEAD.to_string(index=False) + "\n\n"
105
+
106
+ if "DF_IDADE" in locals() or "DF_IDADE" in globals():
107
+ resumo += "Resumo DF_IDADE:\n"
108
+ resumo += DF_IDADE.to_string(index=False) + "\n\n"
109
+
110
+ if "DF_GENERO" in locals() or "DF_GENERO" in globals():
111
+ resumo += f"Resumo DF_GENERO:\n{DF_GENERO.value_counts().to_string()}\n\n"
112
+
113
+ if "DF_COR" in locals() or "DF_COR" in globals():
114
+ resumo += f"Resumo DF_COR:\n{DF_COR.value_counts().to_string()}\n\n"
115
+
116
+ if "DF_DEFICIENCIA" in locals() or "DF_DEFICIENCIA" in globals():
117
+ resumo += f"Resumo DF_DEFICIENCIA:\n{DF_DEFICIENCIA.value_counts().to_string()}\n\n"
118
+
119
+ if "DF_DOENCAS" in locals() or "DF_DOENCAS" in globals():
120
+ resumo += f"Resumo DF_DOENCAS:\n{DF_DOENCAS.value_counts().to_string()}\n\n"
121
+
122
+ if "DF_ESCOLA" in locals() or "DF_ESCOLA" in globals():
123
+ resumo += f"Resumo DF_ESCOLA:\n{DF_ESCOLA.value_counts().to_string()}\n\n"
124
+
125
+ if "DF_TRANSGEN" in locals() or "DF_TRANSGEN" in globals():
126
+ resumo += f"Resumo DF_TRANSGEN:\n{DF_TRANSGEN.value_counts().to_string()}\n\n"
127
+
128
+ return resumo
129
+
130
+ # Mostrar o resumo no Streamlit
131
+ st.text(gerar_resumo_df())
132
+
133
+
134
+ #######################################
135
+ #######################################
136
+ ############ BANNER ##################
137
+ #######################################
138
+ #######################################
139
+
140
+ with stylable_container(
141
+ key="banner",
142
+ css_styles="""
143
+ img {
144
+ width: 1800px;
145
+ height: 600px;
146
+ overflow: hidden;
147
+ position: relative;
148
+ object-fit: cover;
149
+ border-radius: 14px; /* Adiciona bordas arredondadas */
150
+ mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
151
+ -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0)); /* For Safari */
152
+ }
153
+ """,
154
+ ):
155
+ st.image("./banner.png")
156
+
157
+
158
+ #######################################
159
+ ############ BANNER ##################
160
+ #######################################
161
+
162
+ add_vertical_space(5)
163
+
164
+ c1, c2 = st.columns([5, 5])
165
+ with c1:
166
+ st.markdown(
167
+ """
168
+ ## Dashboard UBS Flamengo
169
+
170
+ ###### :brain: _by Dr. Guilherme Apolinário_
171
+
172
+ #### Bem-vindo! :wave:
173
+ """
174
+ )
175
+
176
+ with c2:
177
+ with stylable_container(
178
+ key="graph_entry",
179
+ css_styles="""
180
+ img {
181
+ width: 600px;
182
+ height: 160px;
183
+ overflow: hidden;
184
+ position: relative;
185
+ object-fit: cover;
186
+ mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
187
+ -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0)); /* For Safari */
188
+ }
189
+ """,
190
+ ):
191
+ st.image("./graph1.png")
192
+ st.divider()
193
+
194
+
195
+ ###########################################
196
+ ###########################################
197
+ ###########################################
198
+ ############### LATERAL ##################
199
+ ###########################################
200
+ ###########################################
201
+ ###########################################
202
+
203
+ st.sidebar.markdown(
204
+ """
205
+ ### Informações:
206
+ - Análise de dados do relatório de cadastro individual.
207
+ - Iniciativa - Ubs Flamengo
208
+ - Acesso livre
209
+
210
+ ### Links:
211
+ ##
212
+ ##### - [PEC SUS](https://sape.pecsus.com.br/) 📝
213
+ ###
214
+ ##### - [Obsidian - Dr Guilherme](http://dr-guilhermeapolinario.com) 🌎
215
+ ##### - [GitHub - Dr Guilherme](http://dr-guilhermeapolinario.com) 🌎
216
+
217
+ """
218
+ )
219
+
220
+ ###########################################
221
+ ############### LATERAL ##################
222
+ ###########################################
223
+
224
+ st.markdown(
225
+ """
226
+ ### Intruções:
227
+ ##### - Acesse o site :orange[PEC SUS], na aba esquerda selecione consolidado, :blue[*RELATÓRIO DE CADASTRO INDIVIDUAL*]
228
+ ##### - Selecione a opção :orange[baixar arquivo .csv]. Após baixar o arquivo, selecione o arquivo .csv na aba ao lado, e pronto.
229
+ ##### - Clique no botão de expansão abaixo para iniciar o processo.
230
+ ##### - Utilize o chatbot com a inteligência artificial 🤖 Zé Flamengo para tirar suas dúvidas.
231
+ """
232
+ )
233
+ st.divider()
234
+
235
+
236
+ st.markdown(
237
+ """
238
+ ### :world_map: **Conhecendo a área de abrangencia daUBS Flamengo: (IBGE 2022)**
239
+
240
+ """
241
+ )
242
+
243
+ m_pop = st.checkbox(":man-woman-girl-boy: **População**")
244
+ if m_pop:
245
+ gdf = gpd.read_file("flamengo_ibge2022.geojson").to_crs(epsg=4326)
246
+ LATITUDE = -19.971591804
247
+ LONGITUDE = -44.057912815
248
+ colorscale = px.colors.sequential.swatches_continuous()
249
+ colorscale = px.colors.sequential.Viridis
250
+ colormap = LinearColormap(
251
+ colors=colorscale,
252
+ vmin=gdf["POP"].min(),
253
+ vmax=gdf["POP"].max(),
254
+ caption="População residente UBS Flamengo - IBGE 2022",
255
+ )
256
+
257
+ m = folium.Map(
258
+ location=[LATITUDE, LONGITUDE], tiles="Cartodb Positron", zoom_start=15
259
+ )
260
+
261
+ pop_total = gdf["POP"].sum()
262
+ gdf["POP_PERCENT"] = (gdf["POP"] / pop_total * 100).round(2)
263
+
264
+ folium.GeoJson(
265
+ gdf,
266
+ style_function=lambda feature: {
267
+ "fillColor": colormap(feature["properties"]["POP"]),
268
+ "color": "black",
269
+ "weight": 1,
270
+ "fillOpacity": 0.4,
271
+ },
272
+ highlight_function=lambda feature: {
273
+ "fillColor": "#ffaf00",
274
+ "color": "green",
275
+ "weight": 3,
276
+ "fillOpacity": 0.6,
277
+ },
278
+ tooltip=folium.features.GeoJsonTooltip(
279
+ fields=["CD_SETOR", "POP", "POP_PERCENT"],
280
+ aliases=[
281
+ "Setor Censitário:",
282
+ "População do Setor:",
283
+ "Porcentagem do Total: %",
284
+ ],
285
+ style=(
286
+ "background-color: white; color: #333333; font-family: calibri; font-size: 12px; padding: 10px;"
287
+ ),
288
+ ),
289
+ ).add_to(m)
290
+
291
+ colormap.caption = "População residente UBS Flamengo - IBGE 2022"
292
+ colormap.add_to(m)
293
+ # Alterar o CSS da legenda para reposicioná-la no topo
294
+ STYLE_STATEMENT = "<style>.leaflet-control-layers { position: fixed; top: 10px; left: 50px; } </style>"
295
+ m.get_root().html.add_child(folium.Element(STYLE_STATEMENT))
296
+ folium_static(m)
297
+
298
+ st.divider()
299
+ add_vertical_space(3)
300
+
301
+ st.markdown(
302
+ """
303
+ ## Dados de saúde Relatório de cadastro individual.
304
+ """
305
+ )
306
+ #
307
+ #
308
+ #
309
+ #
310
+ #
311
+ #
312
+ #
313
+
314
+
315
+ if uploaded_file is not None:
316
+ dataframes = processar_arquivo(uploaded_file)
317
+
318
+ # Atribuir os DataFrames a variáveis específicas para uso posterior
319
+ DF_DATA = dataframes.get("Data")
320
+ DF_HEAD = dataframes.get("Head")
321
+ DF_IDADE = dataframes.get("Idade")
322
+ DF_GENERO = dataframes.get("genero")
323
+ DF_COR = dataframes.get("cor")
324
+ DF_DEFICIENCIA = dataframes.get("deficiencia")
325
+ DF_DOENCAS = dataframes.get("doencas")
326
+ DF_ESCOLA = dataframes.get("Escola")
327
+ DF_TRANSGEN = dataframes.get("transgen")
328
+
329
+ # Aplicar capitalização à coluna "Descrição" em cada DataFrame
330
+ for df in [DF_IDADE, DF_GENERO, DF_COR, DF_DEFICIENCIA, DF_DOENCAS, DF_ESCOLA, DF_TRANSGEN]:
331
+ if df is not None:
332
+ df["Descrição"] = df["Descrição"].str.capitalize()
333
+ else:
334
+ st.sidebar.info("Adicione um arquivo .csv.")
335
+ #
336
+ #
337
+ #
338
+ #
339
+
340
+ def criar_grafico_personalizado(df, x_col, y_col, titulo):
341
+ """
342
+ Generates a custom bar chart using Plotly Express.
343
+ Args:
344
+ df (pandas.DataFrame): The input dataframe.
345
+ x_col (str): The column name to be used as the x-axis.
346
+ y_col (str): The column name to be used as the y-axis.
347
+ titulo (str): The title of the chart.
348
+ Returns:
349
+ plotly.graph_objects.Figure: The generated bar chart.
350
+ """
351
+ fig = px.bar(
352
+ df,
353
+ x=x_col,
354
+ y=y_col,
355
+ title=titulo,
356
+ text=y_col, # Adiciona os rótulos
357
+ color=x_col, # Usa uma paleta de cores para a barra
358
+ color_discrete_sequence=px.colors.qualitative.Bold # Define uma paleta de cores
359
+ )
360
+ fig.update_traces(texttemplate='%{text:.2s}', textposition='outside') # Formatação dos rótulos
361
+ fig.update_layout(
362
+ uniformtext_minsize=8,
363
+ uniformtext_mode='hide',
364
+ xaxis_title=x_col,
365
+ yaxis_title=y_col,
366
+ title_font_size=24,
367
+ title_font_family="Arial",
368
+ title_font_color="blue",
369
+ title_x=0.5,
370
+ paper_bgcolor='rgba(0,0,0,0)',
371
+ plot_bgcolor='rgba(0,0,0,0)',
372
+ xaxis_tickangle=-45 # Rotaciona os rótulos do eixo x para melhor legibilidade
373
+ )
374
+ return fig
375
+
376
+ with st.expander(" Adicione o arquivo .csv ao lado para visualização", expanded=True):
377
+ selected_tab = option_menu(
378
+ menu_title=None,
379
+ options=["Faixa Etária", "Gênero", "Cor", "Deficiência", "Doenças", "Escolaridade", "Identidade de Gênero"],
380
+ icons=["person", "gender-female", "person-plus", "person-wheelchair", "capsule-pill", "school", "transgender"],
381
+ menu_icon="cast",
382
+ default_index=0,
383
+ orientation="horizontal",
384
+ styles={
385
+ "container": {"padding": "5px", "background-color": "#f9f9f9"},
386
+ "icon": {"color": "orange", "font-size": "25px"},
387
+ "nav-link": {
388
+ "font-size": "16px",
389
+ "text-align": "center",
390
+ "margin": "0px",
391
+ "--hover-color": "#eee",
392
+ },
393
+ "nav-link-selected": {"background-color": "#02ab21"},
394
+ },
395
+ )
396
+
397
+ # Exibição dos DataFrames com base na aba selecionada
398
+ if selected_tab == "Faixa Etária" and DF_IDADE is not None:
399
+ st.subheader("Distribuição por Faixa Etária")
400
+ col1, col2 = st.columns(2)
401
+ with col1:
402
+ st.dataframe(DF_IDADE, hide_index=True)
403
+ with col2:
404
+ # Criar o gráfico de pirâmide etária
405
+ DF_IDADE["Masculino"] = DF_IDADE["Masculino"].astype(int) * -1 # Valores negativos para o lado masculino
406
+ DF_IDADE["Feminino"] = DF_IDADE["Feminino"].astype(int)
407
+ fig_idade = px.bar(
408
+ DF_IDADE,
409
+ x=["Masculino", "Feminino"],
410
+ y="Descrição",
411
+ orientation="h",
412
+ title="Pirâmide Etária",
413
+ labels={"value": "População", "Descrição": "Faixa Etária"},
414
+ color="Descrição",
415
+ color_discrete_sequence=px.colors.qualitative.Set3,
416
+ )
417
+ fig_idade.update_layout(
418
+ barmode="relative", xaxis_title="População", yaxis_title="Faixa Etária"
419
+ )
420
+ st.plotly_chart(fig_idade)
421
+ DF_IDADE["Masculino"] = DF_IDADE["Masculino"].abs()
422
+
423
+ elif selected_tab == "Gênero" and DF_GENERO is not None:
424
+ st.subheader("Distribuição por Gênero")
425
+ col1, col2 = st.columns(2)
426
+ with col1:
427
+ st.dataframe(DF_GENERO, hide_index=True)
428
+ with col2:
429
+ fig_genero = px.pie(
430
+ DF_GENERO,
431
+ names="Descrição",
432
+ values="Valor",
433
+ title="Distribuição por Gênero",
434
+ color_discrete_sequence=px.colors.qualitative.Pastel
435
+ )
436
+ st.plotly_chart(fig_genero)
437
+
438
+ elif selected_tab == "Cor" and DF_COR is not None:
439
+ st.subheader("Distribuição por Cor")
440
+ col1, col2 = st.columns(2)
441
+ with col1:
442
+ st.dataframe(DF_COR, hide_index=True)
443
+ with col2:
444
+ fig_cor = px.pie(
445
+ DF_COR,
446
+ names="Descrição",
447
+ values="Valor",
448
+ title="Distribuição por Cor",
449
+ color_discrete_sequence=px.colors.qualitative.Vivid
450
+ )
451
+ st.plotly_chart(fig_cor)
452
+
453
+ elif selected_tab == "Deficiência" and DF_DEFICIENCIA is not None:
454
+ st.subheader("Distribuição por Deficiência")
455
+ col1, col2 = st.columns(2)
456
+ with col1:
457
+ st.dataframe(DF_DEFICIENCIA, hide_index=True)
458
+ with col2:
459
+ fig_deficiencia = criar_grafico_personalizado(
460
+ DF_DEFICIENCIA,
461
+ x_col="Descrição",
462
+ y_col="Valor",
463
+ titulo="Distribuição por Deficiência"
464
+ )
465
+ st.plotly_chart(fig_deficiencia)
466
+
467
+ elif selected_tab == "Doenças" and DF_DOENCAS is not None:
468
+ st.subheader("Distribuição por Doenças")
469
+ col1, col2 = st.columns(2)
470
+ with col1:
471
+ st.dataframe(DF_DOENCAS, hide_index=True)
472
+ with col2:
473
+ fig_doencas = criar_grafico_personalizado(
474
+ DF_DOENCAS,
475
+ x_col="Descrição",
476
+ y_col="Valor",
477
+ titulo="Distribuição por Doenças"
478
+ )
479
+ st.plotly_chart(fig_doencas)
480
+
481
+ elif selected_tab == "Escolaridade" and DF_ESCOLA is not None:
482
+ st.subheader("Distribuição por Escolaridade")
483
+ col1, col2 = st.columns(2)
484
+ with col1:
485
+ st.dataframe(DF_ESCOLA, hide_index=True)
486
+ with col2:
487
+ fig_escola = criar_grafico_personalizado(
488
+ DF_ESCOLA,
489
+ x_col="Descrição",
490
+ y_col="Valor",
491
+ titulo="Distribuição por Escolaridade"
492
+ )
493
+ st.plotly_chart(fig_escola)
494
+
495
+ elif selected_tab == "Identidade de Gênero" and DF_TRANSGEN is not None:
496
+ st.subheader("Distribuição por Identidade de Gênero")
497
+ col1, col2 = st.columns(2)
498
+ with col1:
499
+ st.dataframe(DF_TRANSGEN, hide_index=True)
500
+ with col2:
501
+ fig_transgen = criar_grafico_personalizado(
502
+ DF_TRANSGEN,
503
+ x_col="Descrição",
504
+ y_col="Valor",
505
+ titulo="Distribuição por Identidade de Gênero"
506
+ )
507
+ st.plotly_chart(fig_transgen)
508
+
509
+ add_vertical_space()
510
+
511
+ st.info(
512
+ """
513
+ 📢 **CONVERSE COM IA SE TIVER DÚVIDAS NA ANÁLISE DOS GRÁFICOS**"""
514
+ )
515
+
516
+ add_vertical_space(1)
517
+
518
+
519
+ with stylable_container(
520
+ key="brain",
521
+ css_styles="""
522
+ img {
523
+ width: 120px;
524
+ height: 100px;
525
+ overflow: hidden;
526
+ position: relative;
527
+ object-fit: cover;
528
+ border-radius: 14px; /* Adiciona bordas arredondadas */
529
+ }
530
+ """,
531
+ ):
532
+ st.image("./brain.png")
533
+ # Widget expander para interação da IA
534
+ with st.expander(" Converse com o 🤖 Zé Flamengo", expanded=True):
535
+ client = Groq(
536
+ api_key=st.secrets["GROQ_API_KEY"],
537
+ )
538
+
539
+ INPUT_KEY = "USER_CHAT_input"
540
+
541
+ USER_CHAT = st.text_input(
542
+ "Digite sua pergunta sobre saúde na microárea:",
543
+ placeholder="Digite sua pergunta aqui...",
544
+ )
545
+
546
+ if st.button("Enviar pergunta", key="send_button"):
547
+ if USER_CHAT is not None: # Verifica se há texto na entrada
548
+ try:
549
+ RESUMO_DF = gerar_resumo_df()
550
+ CHAT_COMPLETION = client.chat.completions.create(
551
+ messages=[
552
+ {
553
+ "role": "system",
554
+ "content": f"""
555
+ Seu nome é Flávio, assistente virtual de dados médicos epidemiológicos.
556
+ Você é um epidemiologista brasileiro com 20 anos de experiência
557
+ em análise de dados de saúde de microáreas. Sua função é analisar
558
+ a estrutura de saúde de microregiões através de dados coletados
559
+ no SUS. Forneça suas respostas sempre em português, seja conciso e
560
+ evite conversar sobre outros temas, sempre retornando ao tema da
561
+ conversa.
562
+ Aqui estão os resumos dos dataframes disponíveis:
563
+
564
+ {RESUMO_DF}
565
+
566
+ Use essas informações para responder às perguntas do usuário.
567
+ Regras:
568
+ 1- Seja sempre cortês.
569
+ 2- Responda somente assuntos referentes ao resumo.
570
+ 3- Caso seja feita alguma pergunta a você diferente de resumos, responda: "Vamos voltar ao trabalho que interessa?"
571
+ 4- Responda sempre em português.
572
+ 5- Se não souber a resposta, responda: "Desculpe, mas não tennho esta informação."
573
+ 6- Nas suas respostas não forneça os nomes dos df_, somente responda as perguntas.
574
+
575
+ """,
576
+ },
577
+ {
578
+ "role": "user",
579
+ "content": USER_CHAT,
580
+ },
581
+ ],
582
+ model="llama3-70b-8192",
583
+ temperature=0.2,
584
+ max_tokens=1500,
585
+ )
586
+ st.write(CHAT_COMPLETION.choices[0].message.content)
587
+
588
+ # Limpa o campo de entrada após enviar a pergunta
589
+ st.session_state[INPUT_KEY] = ""
590
+ except Exception as e:
591
+ st.error(f"Erro ao gerar a conclusão do chat: {e}")
592
+ else:
593
+ st.warning("Por favor, digite uma pergunta antes de enviar.")
594
+
595
+
596
+ # Adicione este código fora do expander para evitar a reexecução do script ao pressionar Enter
597
+ if "USER_CHAT_input" in st.session_state and st.session_state.USER_CHAT_input:
598
+ st.session_state.USER_CHAT_input = ""