Skip to content

Commit 14d4bf5

Browse files
committed
ajustes Gemini flash
1 parent 03657e2 commit 14d4bf5

9 files changed

Lines changed: 227 additions & 90 deletions

File tree

.DS_Store

4 KB
Binary file not shown.

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
.streamlit/
2-
base_consolidada_ufsc.json
2+
base_consolidada_ufsc.json
3+
.claude/
4+
.agent/

CLAUDE.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## graphify
2+
3+
This project has a graphify knowledge graph at graphify-out/.
4+
5+
Rules:
6+
- Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure
7+
- If graphify-out/wiki/index.md exists, navigate it instead of reading raw files
8+
- After modifying code files in this session, run `graphify update .` to keep the graph current (AST-only, no API cost)
2.04 KB
Binary file not shown.
17 Bytes
Binary file not shown.

backend.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,7 @@ def calcular_sna_global(_dados_lista):
20902090

20912091
return resultado
20922092

2093+
20932094
@st.cache_data(show_spinner=False)
20942095
def _construir_grafo_historico(dados_lista: tuple):
20952096
"""

gemini_utils.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
from app_config import get_gemini_api_key
44

5-
DEFAULT_TEXT_MODELS = ("gemini-2.5-flash",)
6-
DEFAULT_FAST_MODELS = ("gemini-2.5-flash-lite", "gemini-2.5-flash",)
5+
DEFAULT_TEXT_MODELS = ("gemini-2.5-flash-lite",)
6+
DEFAULT_FAST_MODELS = (
7+
"gemini-2.5-flash-lite",
8+
"gemini-3.1-flash-lite-preview",
9+
)
710

811
USE_NEW_SDK = False
912

1013
try:
1114
from google import genai
1215
from google.genai import types
16+
1317
USE_NEW_SDK = True
1418
except ImportError:
1519
import google.generativeai as legacy_genai

pages/1_Avançado.py

Lines changed: 80 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import json
99
import re
1010
from collections import Counter
11-
import itertools # CORRIGIDO: importação duplicada removida
11+
import itertools # importação duplicada removida
1212
import streamlit.components.v1 as components
1313
from streamlit_agraph import agraph, Node, Edge, Config
1414
import numpy as np
@@ -46,7 +46,7 @@
4646
)
4747

4848
# --- INICIALIZAÇÃO DEFENSIVA DE ESTADO ---
49-
# CORRIGIDO: sna_global, df_grid e tipo_foresight_grid adicionados ao bloco
49+
# sna_global, df_grid e tipo_foresight_grid adicionados ao bloco
5050
# defensivo para evitar recálculos custosos e perda de resultados no rerender.
5151
chaves_necessarias = {
5252
'grafo_pronto': False,
@@ -205,7 +205,7 @@
205205
st.markdown("### 🧬 Métricas de Ecologia Profunda (SNA Avançado)")
206206
st.caption("Diagnóstico estrutural e físico da maturidade do ecossistema de conhecimento.")
207207

208-
# CORRIGIDO: sna_global agora é cacheado em session_state para evitar
208+
# sna_global agora é cacheado em session_state para evitar
209209
# recálculo duplo quando o usuário navega para a aba Fluxos/Foresight.
210210
if st.session_state['sna_global'] is None:
211211
with st.spinner("Calculando leis de escala e correlações topológicas..."):
@@ -290,7 +290,7 @@
290290
linhas_tabela = []
291291
macrotemas_unicos = set([d.get('macrotema', 'Multidisciplinar / Transversal') for d in dados_completos])
292292

293-
# CORRIGIDO: top_ql movida para fora do loop. Defini-la dentro do loop
293+
# top_ql movida para fora do loop. Defini-la dentro do loop
294294
# a redefinia desnecessariamente a cada iteração (antipattern Python).
295295
def top_ql(entidades_na_mt, contagem_global, O_k, O_total):
296296
max_ql = -1
@@ -745,7 +745,7 @@ def top_ql(entidades_na_mt, contagem_global, O_k, O_total):
745745

746746
df_bt = calcular_burt(dados_gerais)
747747
if not df_bt.empty:
748-
# CORRIGIDO: template alterado de "plotly_dark" para "streamlit" para
748+
# template alterado de "plotly_dark" para "streamlit" para
749749
# suportar os modos claro e escuro da interface de forma consistente
750750
# com o restante dos gráficos do arquivo.
751751
st.plotly_chart(
@@ -947,16 +947,27 @@ def top_ql(entidades_na_mt, contagem_global, O_k, O_total):
947947

948948
col_for1, col_for2 = st.columns(2)
949949
with col_for1:
950-
tipo_foresight = st.selectbox("Analisar Emergência de:", ["Palavra-chave", "Macrotema"])
950+
tipo_foresight = st.selectbox("Analisar Emergência de:", ["Palavra-chave", "Macrotema", "Artefatos (Ontologia IA)"])
951951
with col_for2:
952952
janela_anos = st.slider("Janela Recente (Últimos X anos para medir):", min_value=1, max_value=10, value=3)
953953

954-
# CÓDIGO NOVO — com controle de bootstrap
955-
sna_global = st.session_state['sna_global']
956-
if sna_global is None:
957-
with st.spinner("Sincronizando topologia para o Radar..."):
958-
sna_global = calcular_sna_global(dados_gerais)
959-
st.session_state['sna_global'] = sna_global
954+
# --- VERIFICAÇÃO DE SEGURANÇA DA ONTOLOGIA ---
955+
tem_ontologia = True
956+
if tipo_foresight == "Artefatos (Ontologia IA)":
957+
# Verifica se pelo menos 1 documento na base possui os dados da IA
958+
tem_ontologia = any('ontologia_ia' in d and d['ontologia_ia'] for d in dados_gerais)
959+
if not tem_ontologia:
960+
st.warning("⚠️ O catálogo ontológico ainda não foi gerado nesta sessão.")
961+
st.info("Para analisar a emergência de Artefatos, vá até a aba **'🧬 Memética'** e processe um lote com o Gemini ou faça o upload do seu CSV.")
962+
963+
# Indentamos o resto do Radar para só rodar se passar na verificação
964+
if tem_ontologia:
965+
# Com controle de bootstrap
966+
sna_global = st.session_state['sna_global']
967+
if sna_global is None:
968+
with st.spinner("Sincronizando topologia para o Radar..."):
969+
sna_global = calcular_sna_global(dados_gerais)
970+
st.session_state['sna_global'] = sna_global
960971

961972
# Controle de robustez estatística (3ª coluna no layout)
962973
col_for3 = st.columns(1)[0]
@@ -992,7 +1003,7 @@ def top_ql(entidades_na_mt, contagem_global, O_k, O_total):
9921003
bet_bootstrap=bet_bootstrap # NOVO
9931004
)
9941005

995-
# CORRIGIDO: guard substituído de .sum() == 0 (frágil para floats próximos
1006+
# guard substituído de .sum() == 0 (frágil para floats próximos
9961007
# de zero por imprecisão numérica) para .max() < 1e-9 (numericamente robusto).
9971008
if df_foresight.empty or df_foresight['Novidade (Estrutural * IDF)'].max() < 1e-9:
9981009
st.info("Não há dados recentes ou de rede suficientes para plotar o Radar de Prospecção.")
@@ -1083,12 +1094,12 @@ def top_ql(entidades_na_mt, contagem_global, O_k, O_total):
10831094
x_mid = mom_mediano
10841095
y_mid = nov_mediana
10851096

1086-
# CORRIGIDO: hover_data agora é construído dinamicamente para evitar
1097+
# hover_data construído dinamicamente para evitar
10871098
# ValueError se o backend retornar um dataframe sem essas colunas.
10881099
colunas_hover_desejadas = ["Tração (%)", "Aparições Recentes"]
10891100
hover_cols = [c for c in colunas_hover_desejadas if c in df_foresight.columns]
10901101

1091-
# CORRIGIDO: template alterado de "plotly_dark" para "streamlit" para
1102+
# template alterado de "plotly_dark" para "streamlit" para
10921103
# consistência com o tema da aplicação (suporte a light/dark mode).
10931104
fig_radar = px.scatter(
10941105
df_foresight,
@@ -1111,7 +1122,7 @@ def top_ql(entidades_na_mt, contagem_global, O_k, O_total):
11111122
fig_radar.add_vline(x=x_mid, line_dash="dash", line_color="#7F8C8D", line_width=1)
11121123
fig_radar.add_hline(y=y_mid, line_dash="dash", line_color="#7F8C8D", line_width=1)
11131124

1114-
# CORRIGIDO: anotações migradas para coordenadas de paper (0.0–1.0)
1125+
# anotações migradas para coordenadas de paper (0.0–1.0)
11151126
# em vez de coordenadas de dados (x_max, y_min, etc.). Isso garante
11161127
# que os rótulos fiquem sempre nos cantos do gráfico, sem sobrepor
11171128
# os pontos de dados mais extremos — que são exatamente os mais importantes.
@@ -1161,7 +1172,7 @@ def top_ql(entidades_na_mt, contagem_global, O_k, O_total):
11611172
""")
11621173

11631174
if st.button("🚀 Executar Bateria de Testes (Auto-Otimização)", type="primary"):
1164-
# CORRIGIDO: mensagens de progresso movidas para dentro de um callback
1175+
# mensagens de progresso movidas para dentro de um callback
11651176
# sequencial com st.empty() para refletir o progresso real da operação,
11661177
# em vez de exibir todos os passos concluídos antes do processamento.
11671178
_status_placeholder = st.empty()
@@ -1173,12 +1184,12 @@ def top_ql(entidades_na_mt, contagem_global, O_k, O_total):
11731184
_status_placeholder.error("❌ Dados insuficientes para rodar o Grid Search no histórico.")
11741185
else:
11751186
_status_placeholder.success("✅ Bateria de Testes Concluída!")
1176-
# CORRIGIDO: resultado e tipo utilizado persistidos em session_state
1187+
# resultado e tipo utilizado persistidos em session_state
11771188
# para sobreviver à navegação entre abas e rerenders do Streamlit.
11781189
st.session_state['df_grid'] = df_grid_resultado
11791190
st.session_state['tipo_foresight_grid'] = tipo_foresight
11801191

1181-
# CORRIGIDO: renderização dos resultados movida para fora do bloco do botão.
1192+
# renderização dos resultados movida para fora do bloco do botão.
11821193
# Assim os resultados permanecem visíveis após qualquer rerender, enquanto o
11831194
# usuário não acionar um novo Grid Search.
11841195
if st.session_state.get('df_grid') is not None and not st.session_state['df_grid'].empty:
@@ -1262,10 +1273,57 @@ def highlight_first(s):
12621273

12631274
st.markdown("---")
12641275

1265-
# --- TABELA DE VISUALIZAÇÃO E EXPORTAÇÃO DA IA (BLINDADA) ---
1276+
# --- TABELA DE VISUALIZAÇÃO, UPLOAD E EXPORTAÇÃO DA IA ---
12661277
st.markdown("#### 🗂️ Catálogo de Artefatos Extraídos (Base de Conhecimento)")
1267-
st.caption("Verifique e baixe o que a inteligência artificial conseguiu encontrar nos documentos processados até o momento.")
1278+
st.caption("Verifique e baixe o que a inteligência artificial encontrou, ou faça upload de um catálogo pré-processado.")
1279+
1280+
# --- MÓDULO DE UPLOAD DE CSV ---
1281+
with st.expander("⬆️ Fazer Upload de Catálogo Existente (CSV)"):
1282+
st.markdown("Já possui um catálogo processado anteriormente? Faça o upload do arquivo CSV para injetar os dados diretamente na base atual sem gastar cotas da API.")
1283+
arquivo_up = st.file_uploader("Selecione o arquivo CSV do Catálogo Ontológico", type=["csv"])
1284+
1285+
if arquivo_up is not None:
1286+
try:
1287+
df_up = pd.read_csv(arquivo_up)
1288+
colunas_necessarias = ['Título', 'Teorias e Modelos', 'Ferramentas e Artefatos', 'Métodos e Técnicas']
1289+
1290+
if all(col in df_up.columns for col in colunas_necessarias):
1291+
with st.spinner("Injetando dados na rede..."):
1292+
docs_atualizados = 0
1293+
# Converte a base atual para acesso rápido por título
1294+
mapa_titulos = {str(d.get('titulo', '')).strip().lower(): d for d in dados_gerais}
1295+
1296+
for index, row in df_up.iterrows():
1297+
titulo_csv = str(row['Título']).strip().lower()
1298+
if titulo_csv in mapa_titulos:
1299+
d = mapa_titulos[titulo_csv]
1300+
1301+
# Função auxiliar para reverter a string do CSV (separada por vírgula) para Lista
1302+
def parse_str_to_list(s):
1303+
if pd.isna(s) or str(s).strip() == "": return []
1304+
return [item.strip() for item in str(s).split(",")]
1305+
1306+
# Atualiza o documento com a ontologia lida do CSV
1307+
d['ontologia_ia'] = {
1308+
'teorias_e_modelos': parse_str_to_list(row['Teorias e Modelos']),
1309+
'ferramentas_e_artefatos': parse_str_to_list(row['Ferramentas e Artefatos']),
1310+
'metodos_e_tecnicas': parse_str_to_list(row['Métodos e Técnicas'])
1311+
}
1312+
docs_atualizados += 1
1313+
1314+
if docs_atualizados > 0:
1315+
st.session_state['dados_completos'] = dados_gerais
1316+
st.success(f"✅ Sucesso! {docs_atualizados} documentos foram enriquecidos com o catálogo carregado.")
1317+
time.sleep(2)
1318+
st.rerun()
1319+
else:
1320+
st.warning("⚠️ O upload foi lido, mas nenhum 'Título' do CSV coincidiu com a base atual que está carregada na memória.")
1321+
else:
1322+
st.error("O CSV não possui as colunas estruturais corretas. Certifique-se de usar o arquivo gerado pelo botão 'Exportar Catálogo' desta plataforma.")
1323+
except Exception as e:
1324+
st.error(f"Erro ao ler o arquivo CSV: {e}")
12681325

1326+
# Lógica de renderização da tabela atual
12691327
dados_ontologia = []
12701328
for d in dados_gerais:
12711329
if 'ontologia_ia' in d and d['ontologia_ia']:
@@ -1322,7 +1380,7 @@ def safe_join(item):
13221380

13231381
fonte_param = "Artefatos Extraídos" if "IA" in fonte_selecionada else "Palavras-chave"
13241382

1325-
# CORRIGIDO: dupla chamada idêntica de calcular_metricas_memeticas removida.
1383+
# dupla chamada idêntica de calcular_metricas_memeticas removida.
13261384
# A primeira chamada (linhas 1151-1153 originais) era imediatamente sobrescrita
13271385
# pela segunda, causando processamento duplo desnecessário.
13281386
df_fecundidade, df_longevidade, mortos, vivos, df_mortos, df_vivos = calcular_metricas_memeticas(

0 commit comments

Comments
 (0)