Spaces:
Build error
Build error
Commit ·
58ff70e
1
Parent(s): 6307b60
Corrigido injecao de session_id nos templates HTML e app.py
Browse files- app.py +46 -49
- templates/mach5_monitor_dashboard.html +23 -18
- templates/mach5_new_chat.html +17 -12
app.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
# app.py (antigo mach5_terminal_chat.py)
|
| 2 |
from flask import Flask, render_template, request, jsonify, make_response
|
| 3 |
import json
|
| 4 |
-
import os
|
| 5 |
from datetime import datetime
|
| 6 |
import requests
|
| 7 |
import pytz
|
|
@@ -11,7 +11,7 @@ import time
|
|
| 11 |
import uuid # Importar uuid para gerar IDs para memórias de curto prazo
|
| 12 |
|
| 13 |
# ADICIONADO: Importa a biblioteca do Google Generative AI
|
| 14 |
-
import google.generativeai as genai
|
| 15 |
|
| 16 |
app = Flask(__name__)
|
| 17 |
|
|
@@ -59,7 +59,7 @@ tf = TimezoneFinder()
|
|
| 59 |
ORDERED_FPHEN_AXES = [
|
| 60 |
"Afetuosidade_eixo", "Confusao_Oscilacao_eixo", "Contemplativa_eixo",
|
| 61 |
"Defensividade_eixo", "Diretiva_eixo", "Entediado_eixo",
|
| 62 |
-
"Variancia_eixo",
|
| 63 |
"Espelho_Profundo_eixo", "Inspiracao_eixo", "Neutralidade_Analitica_eixo",
|
| 64 |
"Resignada_eixo", "Sarcasmo_eixo", "Zangada_eixo"
|
| 65 |
]
|
|
@@ -67,9 +67,9 @@ ORDERED_FPHEN_AXES = [
|
|
| 67 |
# --- Variáveis Globais ---
|
| 68 |
# Estes são defaults, mas os valores reais virão dos serviços por sessão.
|
| 69 |
PERSONAGENS_GENOMAS = {} # Não será mais populado diretamente aqui, mas sim obtido do serviço t-social
|
| 70 |
-
DIAS_PARA_ESQUECIMENTO_PADRAO = 10
|
| 71 |
-
MAX_MEMORIAS_CURTO_PRAZO_PROMPT = 5
|
| 72 |
-
MAX_DIALOG_HISTORY_FOR_PROMPT = 3
|
| 73 |
|
| 74 |
# --- Funções Auxiliares de Comunicação com os Serviços ---
|
| 75 |
|
|
@@ -85,7 +85,7 @@ def get_from_service(base_urls, endpoint, default_value, params=None, method='GE
|
|
| 85 |
response = requests.post(full_url, json=json_data, timeout=5)
|
| 86 |
else:
|
| 87 |
raise ValueError("Método HTTP não suportado: " + method)
|
| 88 |
-
|
| 89 |
response.raise_for_status()
|
| 90 |
return response.json()
|
| 91 |
except requests.exceptions.RequestException as e:
|
|
@@ -102,7 +102,7 @@ def post_to_service(base_urls, endpoint, data):
|
|
| 102 |
def get_current_local_time_salvador():
|
| 103 |
"""Retorna a data e hora local de Salvador."""
|
| 104 |
try:
|
| 105 |
-
timezone_str = tf.timezone_at(lng=SALVADOR_LON, lat=SALVADOR_LAT)
|
| 106 |
if not timezone_str:
|
| 107 |
raise ValueError("Não foi possível determinar o fuso horário para Salvador.")
|
| 108 |
salvador_timezone = pytz.timezone(timezone_str)
|
|
@@ -115,7 +115,7 @@ def get_current_local_time_salvador():
|
|
| 115 |
|
| 116 |
def create_llm_context(mach5_state_data, dialogos_history, short_term_memories_filtered, initial_biography_data, all_personagens_data):
|
| 117 |
context_parts = []
|
| 118 |
-
|
| 119 |
current_location_time = get_current_local_time_salvador()
|
| 120 |
context_parts.append(f"Você está em sua sala na Superintendência Acadêmica da UFBA. {current_location_time}. Seu estado atual é de prontidão para auxiliar, influenciado pelo que te é dito.")
|
| 121 |
|
|
@@ -123,7 +123,7 @@ def create_llm_context(mach5_state_data, dialogos_history, short_term_memories_f
|
|
| 123 |
coh_total = mach5_state_data.get("mach5_coerencia_total", 0.0)
|
| 124 |
pi_g = mach5_state_data.get("mach5_produtividade_expressiva", 0.0)
|
| 125 |
fphen_t = mach5_state_data.get("fphen_t_values", {})
|
| 126 |
-
|
| 127 |
context_parts.append(f"Seu estado interno atual é: Coerência Total={coh_total:.2f}, Produtividade Expressiva={pi_g:.2f}.")
|
| 128 |
if fphen_t:
|
| 129 |
context_parts.append(f"Seus eixos expressivos dominantes são: Afetuosidade={fphen_t.get('afetuosidade', 0.0):.2f}, Variância={fphen_t.get('variancia', 0.0):.2f}, Expressividade Geral={fphen_t.get('expressividade', 0.0):.2f}.")
|
|
@@ -140,7 +140,7 @@ def create_llm_context(mach5_state_data, dialogos_history, short_term_memories_f
|
|
| 140 |
elif "memoria" in entity_data: # Para biografias mais simples com uma chave "memoria"
|
| 141 |
context_parts.append(f"- Sobre '{entity_name}' ({entity_data.get('tipo', 'desconhecido')}, relação: {entity_data.get('relacao', 'desconhecida')}): {entity_data.get('memoria')}")
|
| 142 |
# Adicione outros formatos de biografia conforme necessário
|
| 143 |
-
|
| 144 |
if all_personagens_data:
|
| 145 |
context_parts.append("\n**PERSONAGENS IMPORTANTES (Servidores, professores e Técnicos da sua equipe):**")
|
| 146 |
for nome_personagem, data_personagem in all_personagens_data.items():
|
|
@@ -152,7 +152,7 @@ def create_llm_context(mach5_state_data, dialogos_history, short_term_memories_f
|
|
| 152 |
|
| 153 |
if short_term_memories_filtered:
|
| 154 |
context_parts.append("\n**MINHAS LEMBRANÇAS RECENTES (Fatos que eu mesma verbalizei e que podem desvanecer):**")
|
| 155 |
-
for i, mem in enumerate(short_term_memories_filtered[:MAX_MEMORIAS_CURTO_PRAZO_PROMPT]):
|
| 156 |
context_parts.append(f"- Lembrança {i+1}: {mem['conteudo']}")
|
| 157 |
|
| 158 |
if dialogos_history and dialogos_history["dialogos"]:
|
|
@@ -164,7 +164,7 @@ def create_llm_context(mach5_state_data, dialogos_history, short_term_memories_f
|
|
| 164 |
if len(recent_dialogs_formatted) >= MAX_DIALOG_HISTORY_FOR_PROMPT:
|
| 165 |
break
|
| 166 |
context_parts.extend(recent_dialogs_formatted)
|
| 167 |
-
|
| 168 |
return "\n".join(context_parts)
|
| 169 |
|
| 170 |
# FUNÇÃO CENTRAL PARA GERAR RESPOSTA DA Mach5
|
|
@@ -174,9 +174,9 @@ def get_Mach5_response_api(user_input, mach5_state_data, dialogos_history, short
|
|
| 174 |
return "[ERRO DE CONFIGURAÇÃO]: Modelo ou Token da API do Google Gemini não configurados ou inválidos." #
|
| 175 |
if not user_input.strip():
|
| 176 |
return "[Entrada vazia detectada.]" #
|
| 177 |
-
|
| 178 |
llm_context_data = create_llm_context(mach5_state_data, dialogos_history, short_term_memories_filtered, initial_biography_data, all_personagens_data)
|
| 179 |
-
|
| 180 |
prompt_content = (
|
| 181 |
f"Seu nome é Su - Atendente Virtual da UFBA."
|
| 182 |
f"Sua missão é responder às dúvidas sobre o SIGAA, usando como fonte exclusiva a sua memória."
|
|
@@ -203,15 +203,15 @@ def get_Mach5_response_api(user_input, mach5_state_data, dialogos_history, short
|
|
| 203 |
print(messages_for_gemini)
|
| 204 |
print("--------------------------------------------------------------------------------\n")
|
| 205 |
|
| 206 |
-
generated_text = "[Sua entidade não conseguiu processar isso agora.]"
|
| 207 |
-
|
| 208 |
retries = 3
|
| 209 |
for attempt in range(retries):
|
| 210 |
try:
|
| 211 |
if mach5_state_data and "mach5_fisica_params" in mach5_state_data:
|
| 212 |
temp_value = mach5_state_data["mach5_fisica_params"].get("t_impulsividade", 0.7)
|
| 213 |
top_p_value = mach5_state_data["mach5_fisica_params"].get("t_coesao", 0.95)
|
| 214 |
-
|
| 215 |
temp_value = max(0.1, min(1.0, temp_value))
|
| 216 |
top_p_value = max(0.1, min(1.0, top_p_value))
|
| 217 |
else:
|
|
@@ -228,24 +228,24 @@ def get_Mach5_response_api(user_input, mach5_state_data, dialogos_history, short
|
|
| 228 |
top_p=top_p_value,
|
| 229 |
),
|
| 230 |
)
|
| 231 |
-
|
| 232 |
if response and response.candidates and response.candidates[0].content and response.candidates[0].content.parts:
|
| 233 |
generated_text = response.candidates[0].content.parts[0].text.strip()
|
| 234 |
else:
|
| 235 |
generated_text = "[O modelo Gemini não gerou texto válido ou a resposta está vazia.]"
|
| 236 |
-
|
| 237 |
break
|
| 238 |
|
| 239 |
-
except Exception as e:
|
| 240 |
print(f"ERRO DE INFERÊNCIA DO GOOGLE GEMINI (Tentativa {attempt + 1}/{retries}): {e}")
|
| 241 |
if attempt < retries - 1:
|
| 242 |
-
wait_time = 2 ** attempt
|
| 243 |
print(f"Tentando novamente em {wait_time} segundos antes de falhar...")
|
| 244 |
time.sleep(wait_time)
|
| 245 |
else:
|
| 246 |
generated_text = f"[ERRO API GOOGLE GEMINI]: Falha após {retries} tentativas. {str(e)}. Verifique sua chave API, modelo e cotas."
|
| 247 |
-
|
| 248 |
-
return generated_text
|
| 249 |
|
| 250 |
|
| 251 |
@app.route('/')
|
|
@@ -253,16 +253,14 @@ def index():
|
|
| 253 |
print(f"Certifique-se de que t_memoria.py está rodando em {TMEMORIA_SERVER_URLS[0]}.") #
|
| 254 |
print(f"Certifique-se de que t_cerebro_memoria.py está rodando em {TCEREBRO_MEMORIA_URLS[0]}.") #
|
| 255 |
print(f"Certifique-se de que t-social.py está rodando em {T_SOCIAL_SERVER_URLS[0]}.") #
|
| 256 |
-
|
| 257 |
# Gerar um session_id único para cada nova visita à página.
|
| 258 |
session_id = str(uuid.uuid4())
|
| 259 |
print(f"Nova sessão iniciada. Session ID: {session_id}") #
|
| 260 |
-
|
| 261 |
-
# Renderiza o template e
|
| 262 |
-
#
|
| 263 |
-
|
| 264 |
-
response.set_cookie('session_id', session_id)
|
| 265 |
-
return response
|
| 266 |
|
| 267 |
# NOVO: Rota para o seu Painel de Monitoramento
|
| 268 |
@app.route('/dashboard')
|
|
@@ -272,10 +270,9 @@ def dashboard():
|
|
| 272 |
# Isso permite que a dashboard interaja com o sistema de sessão como uma instância à parte.
|
| 273 |
session_id = str(uuid.uuid4())
|
| 274 |
print(f"Nova sessão de MONITORAMENTO iniciada. Session ID: {session_id}")
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
return response
|
| 279 |
|
| 280 |
|
| 281 |
@app.route('/chat_history', methods=['POST']) # Alterado para POST para receber session_id
|
|
@@ -286,14 +283,14 @@ def get_chat_history_route():
|
|
| 286 |
|
| 287 |
# Passa o session_id para o t_cerebro_memoria.py
|
| 288 |
dialogos_data = get_from_service(TCEREBRO_MEMORIA_URLS, "/get_dialog_history", {"dialogos": []}, method='POST', json_data={"session_id": session_id})
|
| 289 |
-
|
| 290 |
last_simplified_state = None
|
| 291 |
if dialogos_data["dialogos"]:
|
| 292 |
last_simplified_state = dialogos_data["dialogos"][-1].get("mach5_estado_simplificado")
|
| 293 |
-
|
| 294 |
return jsonify({
|
| 295 |
"memoria": dialogos_data["dialogos"],
|
| 296 |
-
"last_simplified_state": last_simplified_state
|
| 297 |
})
|
| 298 |
|
| 299 |
|
|
@@ -301,7 +298,7 @@ def get_chat_history_route():
|
|
| 301 |
def responder():
|
| 302 |
user_input = request.json["message"]
|
| 303 |
session_id = request.json.get("session_id") # Pega o session_id do request
|
| 304 |
-
|
| 305 |
if not session_id:
|
| 306 |
return jsonify({"error": "session_id é obrigatório"}), 400
|
| 307 |
|
|
@@ -310,7 +307,7 @@ def responder():
|
|
| 310 |
|
| 311 |
# Passa o session_id e user_input como parte do mesmo dicionário JSON para o t_memoria.py
|
| 312 |
mach5_state_data = post_to_service(TMEMORIA_SERVER_URLS, "/evaluate_input", {"user_input": user_input, "session_id": session_id}) #
|
| 313 |
-
|
| 314 |
if mach5_state_data and "status" not in mach5_state_data and "error" not in mach5_state_data:
|
| 315 |
# Envia o estado atualizado da Mach5 para o t_cerebro_memoria.py, incluindo o session_id
|
| 316 |
post_to_service(TCEREBRO_MEMORIA_URLS, "/update_mach5_main_state", {"session_id": session_id, "state_data": mach5_state_data}) #
|
|
@@ -339,7 +336,7 @@ def responder():
|
|
| 339 |
short_term_memories_filtered = short_term_memories_response.get("lembrancas_curto_prazo", []) #
|
| 340 |
|
| 341 |
all_personagens_data = get_from_service(T_SOCIAL_SERVER_URLS, "/list_personagens", {"personagens": []}) # Este endpoint é GET, não precisa de session_id
|
| 342 |
-
|
| 343 |
# Populando os detalhes dos personagens
|
| 344 |
detailed_personagens = {}
|
| 345 |
if "personagens" in all_personagens_data:
|
|
@@ -351,16 +348,16 @@ def responder():
|
|
| 351 |
|
| 352 |
|
| 353 |
final_Mach5_response = get_Mach5_response_api(
|
| 354 |
-
user_input,
|
| 355 |
-
mach5_state_data,
|
| 356 |
-
dialogos_history,
|
| 357 |
-
short_term_memories_filtered,
|
| 358 |
-
initial_biography_data,
|
| 359 |
detailed_personagens # Usa os dados detalhados dos personagens
|
| 360 |
) #
|
| 361 |
|
| 362 |
simplified_state_for_frontend = {
|
| 363 |
-
"Fphen(t)": mach5_state_data.get("fphen_t_values", {
|
| 364 |
"afetuosidade": 0.0, "variancia": 0.0, "expressividade": 0.0,
|
| 365 |
"coh_total": 0.0, "pi_G": 0.0
|
| 366 |
})
|
|
@@ -386,7 +383,7 @@ def responder():
|
|
| 386 |
|
| 387 |
return jsonify({
|
| 388 |
"response": final_Mach5_response,
|
| 389 |
-
"mach5_estado_simplificado": simplified_state_for_frontend
|
| 390 |
})
|
| 391 |
|
| 392 |
|
|
@@ -394,7 +391,7 @@ if __name__ == '__main__':
|
|
| 394 |
# Define a porta. No Hugging Face Spaces, a variável de ambiente PORT será definida para você.
|
| 395 |
# Use 7860 como um fallback comum para ambientes HF se PORT não estiver definida.
|
| 396 |
port = int(os.environ.get("PORT", 7860)) #
|
| 397 |
-
|
| 398 |
print(f"--- Servidor app.py (Anteriormente mach5_terminal_chat.py) iniciado na porta {port} ---") #
|
| 399 |
print(f"DEBUG: Certifique-se de que t_cerebro_memoria.py está rodando em {TCEREBRO_MEMORIA_URLS[0]}") #
|
| 400 |
print(f"DEBUG: Certifique-se de que t_memoria.py está rodando em {TMEMORIA_SERVER_URLS[0]}") #
|
|
|
|
| 1 |
# app.py (antigo mach5_terminal_chat.py)
|
| 2 |
from flask import Flask, render_template, request, jsonify, make_response
|
| 3 |
import json
|
| 4 |
+
import os
|
| 5 |
from datetime import datetime
|
| 6 |
import requests
|
| 7 |
import pytz
|
|
|
|
| 11 |
import uuid # Importar uuid para gerar IDs para memórias de curto prazo
|
| 12 |
|
| 13 |
# ADICIONADO: Importa a biblioteca do Google Generative AI
|
| 14 |
+
import google.generativeai as genai
|
| 15 |
|
| 16 |
app = Flask(__name__)
|
| 17 |
|
|
|
|
| 59 |
ORDERED_FPHEN_AXES = [
|
| 60 |
"Afetuosidade_eixo", "Confusao_Oscilacao_eixo", "Contemplativa_eixo",
|
| 61 |
"Defensividade_eixo", "Diretiva_eixo", "Entediado_eixo",
|
| 62 |
+
"Variancia_eixo",
|
| 63 |
"Espelho_Profundo_eixo", "Inspiracao_eixo", "Neutralidade_Analitica_eixo",
|
| 64 |
"Resignada_eixo", "Sarcasmo_eixo", "Zangada_eixo"
|
| 65 |
]
|
|
|
|
| 67 |
# --- Variáveis Globais ---
|
| 68 |
# Estes são defaults, mas os valores reais virão dos serviços por sessão.
|
| 69 |
PERSONAGENS_GENOMAS = {} # Não será mais populado diretamente aqui, mas sim obtido do serviço t-social
|
| 70 |
+
DIAS_PARA_ESQUECIMENTO_PADRAO = 10
|
| 71 |
+
MAX_MEMORIAS_CURTO_PRAZO_PROMPT = 5
|
| 72 |
+
MAX_DIALOG_HISTORY_FOR_PROMPT = 3
|
| 73 |
|
| 74 |
# --- Funções Auxiliares de Comunicação com os Serviços ---
|
| 75 |
|
|
|
|
| 85 |
response = requests.post(full_url, json=json_data, timeout=5)
|
| 86 |
else:
|
| 87 |
raise ValueError("Método HTTP não suportado: " + method)
|
| 88 |
+
|
| 89 |
response.raise_for_status()
|
| 90 |
return response.json()
|
| 91 |
except requests.exceptions.RequestException as e:
|
|
|
|
| 102 |
def get_current_local_time_salvador():
|
| 103 |
"""Retorna a data e hora local de Salvador."""
|
| 104 |
try:
|
| 105 |
+
timezone_str = tf.timezone_at(lng=SALVADOR_LON, lat=SALVADOR_LAT)
|
| 106 |
if not timezone_str:
|
| 107 |
raise ValueError("Não foi possível determinar o fuso horário para Salvador.")
|
| 108 |
salvador_timezone = pytz.timezone(timezone_str)
|
|
|
|
| 115 |
|
| 116 |
def create_llm_context(mach5_state_data, dialogos_history, short_term_memories_filtered, initial_biography_data, all_personagens_data):
|
| 117 |
context_parts = []
|
| 118 |
+
|
| 119 |
current_location_time = get_current_local_time_salvador()
|
| 120 |
context_parts.append(f"Você está em sua sala na Superintendência Acadêmica da UFBA. {current_location_time}. Seu estado atual é de prontidão para auxiliar, influenciado pelo que te é dito.")
|
| 121 |
|
|
|
|
| 123 |
coh_total = mach5_state_data.get("mach5_coerencia_total", 0.0)
|
| 124 |
pi_g = mach5_state_data.get("mach5_produtividade_expressiva", 0.0)
|
| 125 |
fphen_t = mach5_state_data.get("fphen_t_values", {})
|
| 126 |
+
|
| 127 |
context_parts.append(f"Seu estado interno atual é: Coerência Total={coh_total:.2f}, Produtividade Expressiva={pi_g:.2f}.")
|
| 128 |
if fphen_t:
|
| 129 |
context_parts.append(f"Seus eixos expressivos dominantes são: Afetuosidade={fphen_t.get('afetuosidade', 0.0):.2f}, Variância={fphen_t.get('variancia', 0.0):.2f}, Expressividade Geral={fphen_t.get('expressividade', 0.0):.2f}.")
|
|
|
|
| 140 |
elif "memoria" in entity_data: # Para biografias mais simples com uma chave "memoria"
|
| 141 |
context_parts.append(f"- Sobre '{entity_name}' ({entity_data.get('tipo', 'desconhecido')}, relação: {entity_data.get('relacao', 'desconhecida')}): {entity_data.get('memoria')}")
|
| 142 |
# Adicione outros formatos de biografia conforme necessário
|
| 143 |
+
|
| 144 |
if all_personagens_data:
|
| 145 |
context_parts.append("\n**PERSONAGENS IMPORTANTES (Servidores, professores e Técnicos da sua equipe):**")
|
| 146 |
for nome_personagem, data_personagem in all_personagens_data.items():
|
|
|
|
| 152 |
|
| 153 |
if short_term_memories_filtered:
|
| 154 |
context_parts.append("\n**MINHAS LEMBRANÇAS RECENTES (Fatos que eu mesma verbalizei e que podem desvanecer):**")
|
| 155 |
+
for i, mem in enumerate(short_term_memories_filtered[:MAX_MEMORIAS_CURTO_PRAZO_PROMPT]):
|
| 156 |
context_parts.append(f"- Lembrança {i+1}: {mem['conteudo']}")
|
| 157 |
|
| 158 |
if dialogos_history and dialogos_history["dialogos"]:
|
|
|
|
| 164 |
if len(recent_dialogs_formatted) >= MAX_DIALOG_HISTORY_FOR_PROMPT:
|
| 165 |
break
|
| 166 |
context_parts.extend(recent_dialogs_formatted)
|
| 167 |
+
|
| 168 |
return "\n".join(context_parts)
|
| 169 |
|
| 170 |
# FUNÇÃO CENTRAL PARA GERAR RESPOSTA DA Mach5
|
|
|
|
| 174 |
return "[ERRO DE CONFIGURAÇÃO]: Modelo ou Token da API do Google Gemini não configurados ou inválidos." #
|
| 175 |
if not user_input.strip():
|
| 176 |
return "[Entrada vazia detectada.]" #
|
| 177 |
+
|
| 178 |
llm_context_data = create_llm_context(mach5_state_data, dialogos_history, short_term_memories_filtered, initial_biography_data, all_personagens_data)
|
| 179 |
+
|
| 180 |
prompt_content = (
|
| 181 |
f"Seu nome é Su - Atendente Virtual da UFBA."
|
| 182 |
f"Sua missão é responder às dúvidas sobre o SIGAA, usando como fonte exclusiva a sua memória."
|
|
|
|
| 203 |
print(messages_for_gemini)
|
| 204 |
print("--------------------------------------------------------------------------------\n")
|
| 205 |
|
| 206 |
+
generated_text = "[Sua entidade não conseguiu processar isso agora.]"
|
| 207 |
+
|
| 208 |
retries = 3
|
| 209 |
for attempt in range(retries):
|
| 210 |
try:
|
| 211 |
if mach5_state_data and "mach5_fisica_params" in mach5_state_data:
|
| 212 |
temp_value = mach5_state_data["mach5_fisica_params"].get("t_impulsividade", 0.7)
|
| 213 |
top_p_value = mach5_state_data["mach5_fisica_params"].get("t_coesao", 0.95)
|
| 214 |
+
|
| 215 |
temp_value = max(0.1, min(1.0, temp_value))
|
| 216 |
top_p_value = max(0.1, min(1.0, top_p_value))
|
| 217 |
else:
|
|
|
|
| 228 |
top_p=top_p_value,
|
| 229 |
),
|
| 230 |
)
|
| 231 |
+
|
| 232 |
if response and response.candidates and response.candidates[0].content and response.candidates[0].content.parts:
|
| 233 |
generated_text = response.candidates[0].content.parts[0].text.strip()
|
| 234 |
else:
|
| 235 |
generated_text = "[O modelo Gemini não gerou texto válido ou a resposta está vazia.]"
|
| 236 |
+
|
| 237 |
break
|
| 238 |
|
| 239 |
+
except Exception as e:
|
| 240 |
print(f"ERRO DE INFERÊNCIA DO GOOGLE GEMINI (Tentativa {attempt + 1}/{retries}): {e}")
|
| 241 |
if attempt < retries - 1:
|
| 242 |
+
wait_time = 2 ** attempt
|
| 243 |
print(f"Tentando novamente em {wait_time} segundos antes de falhar...")
|
| 244 |
time.sleep(wait_time)
|
| 245 |
else:
|
| 246 |
generated_text = f"[ERRO API GOOGLE GEMINI]: Falha após {retries} tentativas. {str(e)}. Verifique sua chave API, modelo e cotas."
|
| 247 |
+
|
| 248 |
+
return generated_text
|
| 249 |
|
| 250 |
|
| 251 |
@app.route('/')
|
|
|
|
| 253 |
print(f"Certifique-se de que t_memoria.py está rodando em {TMEMORIA_SERVER_URLS[0]}.") #
|
| 254 |
print(f"Certifique-se de que t_cerebro_memoria.py está rodando em {TCEREBRO_MEMORIA_URLS[0]}.") #
|
| 255 |
print(f"Certifique-se de que t-social.py está rodando em {T_SOCIAL_SERVER_URLS[0]}.") #
|
| 256 |
+
|
| 257 |
# Gerar um session_id único para cada nova visita à página.
|
| 258 |
session_id = str(uuid.uuid4())
|
| 259 |
print(f"Nova sessão iniciada. Session ID: {session_id}") #
|
| 260 |
+
|
| 261 |
+
# Renderiza o template e PASSA o session_id diretamente.
|
| 262 |
+
# Removida a parte de make_response e set_cookie
|
| 263 |
+
return render_template('mach5_new_chat.html', session_id_from_flask=session_id) # ALTERADO AQUI
|
|
|
|
|
|
|
| 264 |
|
| 265 |
# NOVO: Rota para o seu Painel de Monitoramento
|
| 266 |
@app.route('/dashboard')
|
|
|
|
| 270 |
# Isso permite que a dashboard interaja com o sistema de sessão como uma instância à parte.
|
| 271 |
session_id = str(uuid.uuid4())
|
| 272 |
print(f"Nova sessão de MONITORAMENTO iniciada. Session ID: {session_id}")
|
| 273 |
+
|
| 274 |
+
# Removida a parte de make_response e set_cookie
|
| 275 |
+
return render_template('mach5_monitor_dashboard.html', session_id_from_flask=session_id) # ALTERADO AQUI
|
|
|
|
| 276 |
|
| 277 |
|
| 278 |
@app.route('/chat_history', methods=['POST']) # Alterado para POST para receber session_id
|
|
|
|
| 283 |
|
| 284 |
# Passa o session_id para o t_cerebro_memoria.py
|
| 285 |
dialogos_data = get_from_service(TCEREBRO_MEMORIA_URLS, "/get_dialog_history", {"dialogos": []}, method='POST', json_data={"session_id": session_id})
|
| 286 |
+
|
| 287 |
last_simplified_state = None
|
| 288 |
if dialogos_data["dialogos"]:
|
| 289 |
last_simplified_state = dialogos_data["dialogos"][-1].get("mach5_estado_simplificado")
|
| 290 |
+
|
| 291 |
return jsonify({
|
| 292 |
"memoria": dialogos_data["dialogos"],
|
| 293 |
+
"last_simplified_state": last_simplified_state
|
| 294 |
})
|
| 295 |
|
| 296 |
|
|
|
|
| 298 |
def responder():
|
| 299 |
user_input = request.json["message"]
|
| 300 |
session_id = request.json.get("session_id") # Pega o session_id do request
|
| 301 |
+
|
| 302 |
if not session_id:
|
| 303 |
return jsonify({"error": "session_id é obrigatório"}), 400
|
| 304 |
|
|
|
|
| 307 |
|
| 308 |
# Passa o session_id e user_input como parte do mesmo dicionário JSON para o t_memoria.py
|
| 309 |
mach5_state_data = post_to_service(TMEMORIA_SERVER_URLS, "/evaluate_input", {"user_input": user_input, "session_id": session_id}) #
|
| 310 |
+
|
| 311 |
if mach5_state_data and "status" not in mach5_state_data and "error" not in mach5_state_data:
|
| 312 |
# Envia o estado atualizado da Mach5 para o t_cerebro_memoria.py, incluindo o session_id
|
| 313 |
post_to_service(TCEREBRO_MEMORIA_URLS, "/update_mach5_main_state", {"session_id": session_id, "state_data": mach5_state_data}) #
|
|
|
|
| 336 |
short_term_memories_filtered = short_term_memories_response.get("lembrancas_curto_prazo", []) #
|
| 337 |
|
| 338 |
all_personagens_data = get_from_service(T_SOCIAL_SERVER_URLS, "/list_personagens", {"personagens": []}) # Este endpoint é GET, não precisa de session_id
|
| 339 |
+
|
| 340 |
# Populando os detalhes dos personagens
|
| 341 |
detailed_personagens = {}
|
| 342 |
if "personagens" in all_personagens_data:
|
|
|
|
| 348 |
|
| 349 |
|
| 350 |
final_Mach5_response = get_Mach5_response_api(
|
| 351 |
+
user_input,
|
| 352 |
+
mach5_state_data,
|
| 353 |
+
dialogos_history,
|
| 354 |
+
short_term_memories_filtered,
|
| 355 |
+
initial_biography_data,
|
| 356 |
detailed_personagens # Usa os dados detalhados dos personagens
|
| 357 |
) #
|
| 358 |
|
| 359 |
simplified_state_for_frontend = {
|
| 360 |
+
"Fphen(t)": mach5_state_data.get("fphen_t_values", {
|
| 361 |
"afetuosidade": 0.0, "variancia": 0.0, "expressividade": 0.0,
|
| 362 |
"coh_total": 0.0, "pi_G": 0.0
|
| 363 |
})
|
|
|
|
| 383 |
|
| 384 |
return jsonify({
|
| 385 |
"response": final_Mach5_response,
|
| 386 |
+
"mach5_estado_simplificado": simplified_state_for_frontend
|
| 387 |
})
|
| 388 |
|
| 389 |
|
|
|
|
| 391 |
# Define a porta. No Hugging Face Spaces, a variável de ambiente PORT será definida para você.
|
| 392 |
# Use 7860 como um fallback comum para ambientes HF se PORT não estiver definida.
|
| 393 |
port = int(os.environ.get("PORT", 7860)) #
|
| 394 |
+
|
| 395 |
print(f"--- Servidor app.py (Anteriormente mach5_terminal_chat.py) iniciado na porta {port} ---") #
|
| 396 |
print(f"DEBUG: Certifique-se de que t_cerebro_memoria.py está rodando em {TCEREBRO_MEMORIA_URLS[0]}") #
|
| 397 |
print(f"DEBUG: Certifique-se de que t_memoria.py está rodando em {TMEMORIA_SERVER_URLS[0]}") #
|
templates/mach5_monitor_dashboard.html
CHANGED
|
@@ -181,9 +181,12 @@
|
|
| 181 |
</div>
|
| 182 |
|
| 183 |
<script>
|
| 184 |
-
|
|
|
|
|
|
|
| 185 |
|
| 186 |
-
//
|
|
|
|
| 187 |
function getCookie(name) {
|
| 188 |
const nameEQ = name + "=";
|
| 189 |
const ca = document.cookie.split(';');
|
|
@@ -377,8 +380,8 @@
|
|
| 377 |
chatHistory.scrollTop = chatHistory.scrollHeight;
|
| 378 |
|
| 379 |
const thinkingMessageDiv = document.createElement('div');
|
| 380 |
-
thinkingMessageDiv.className = 'su-message thinking-message';
|
| 381 |
-
thinkingMessageDiv.textContent = `SU: Pensando...`;
|
| 382 |
chatHistory.appendChild(thinkingMessageDiv);
|
| 383 |
chatHistory.scrollTop = chatHistory.scrollHeight;
|
| 384 |
|
|
@@ -387,15 +390,16 @@
|
|
| 387 |
headers: {
|
| 388 |
'Content-Type': 'application/json'
|
| 389 |
},
|
| 390 |
-
|
|
|
|
| 391 |
})
|
| 392 |
.then(response => response.json())
|
| 393 |
.then(data => {
|
| 394 |
chatHistory.removeChild(thinkingMessageDiv);
|
| 395 |
|
| 396 |
-
const suMessageDiv = document.createElement('div');
|
| 397 |
suMessageDiv.className = 'su-message';
|
| 398 |
-
suMessageDiv.textContent = `SU: ${data.response}`;
|
| 399 |
chatHistory.appendChild(suMessageDiv);
|
| 400 |
|
| 401 |
// Exibir dados de avaliação se presentes
|
|
@@ -415,8 +419,8 @@
|
|
| 415 |
chatHistory.removeChild(thinkingMessageDiv);
|
| 416 |
}
|
| 417 |
const errorMessageDiv = document.createElement('div');
|
| 418 |
-
errorMessageDiv.className = 'su-message';
|
| 419 |
-
errorMessageDiv.textContent = `SU: [ERRO] Não consegui responder. Tente novamente.`;
|
| 420 |
chatHistory.appendChild(errorMessageDiv);
|
| 421 |
chatHistory.scrollTop = chatHistory.scrollHeight;
|
| 422 |
});
|
|
@@ -424,17 +428,18 @@
|
|
| 424 |
|
| 425 |
// Função para carregar o histórico inicial e o estado da Mach5 ao carregar a página
|
| 426 |
window.onload = function() {
|
| 427 |
-
|
| 428 |
-
if (!sessionId) {
|
| 429 |
-
console.error("Session ID não encontrado
|
| 430 |
-
//
|
| 431 |
-
//
|
| 432 |
}
|
| 433 |
|
| 434 |
fetch('/chat_history', {
|
| 435 |
-
method: 'POST',
|
| 436 |
headers: { 'Content-Type': 'application/json' },
|
| 437 |
-
|
|
|
|
| 438 |
})
|
| 439 |
.then(response => response.json())
|
| 440 |
.then(data => {
|
|
@@ -445,9 +450,9 @@
|
|
| 445 |
userMessageDiv.textContent = `Você: ${item.input}`;
|
| 446 |
chatHistory.appendChild(userMessageDiv);
|
| 447 |
|
| 448 |
-
const suMessageDiv = document.createElement('div');
|
| 449 |
suMessageDiv.className = 'su-message';
|
| 450 |
-
suMessageDiv.textContent = `SU: ${item.resposta}`;
|
| 451 |
chatHistory.appendChild(suMessageDiv);
|
| 452 |
|
| 453 |
// Adiciona dados ao histórico do gráfico de linha ao carregar o histórico salvo
|
|
|
|
| 181 |
</div>
|
| 182 |
|
| 183 |
<script>
|
| 184 |
+
// A principal mudança: o sessionId será injetado pelo Flask, não lido de um cookie.
|
| 185 |
+
// Certifique-se que o Flask renderize este template passando a variável 'session_id'.
|
| 186 |
+
let sessionId = "{{ session_id }}"; // Agora, o sessionId recebe o valor diretamente do Flask.
|
| 187 |
|
| 188 |
+
// A função getCookie(name) não é mais necessária para obter o sessionId no carregamento inicial,
|
| 189 |
+
// mas pode ser mantida se usada para outros cookies ou futuras funcionalidades.
|
| 190 |
function getCookie(name) {
|
| 191 |
const nameEQ = name + "=";
|
| 192 |
const ca = document.cookie.split(';');
|
|
|
|
| 380 |
chatHistory.scrollTop = chatHistory.scrollHeight;
|
| 381 |
|
| 382 |
const thinkingMessageDiv = document.createElement('div');
|
| 383 |
+
thinkingMessageDiv.className = 'su-message thinking-message';
|
| 384 |
+
thinkingMessageDiv.textContent = `SU: Pensando...`;
|
| 385 |
chatHistory.appendChild(thinkingMessageDiv);
|
| 386 |
chatHistory.scrollTop = chatHistory.scrollHeight;
|
| 387 |
|
|
|
|
| 390 |
headers: {
|
| 391 |
'Content-Type': 'application/json'
|
| 392 |
},
|
| 393 |
+
// O sessionId já está disponível aqui, obtido do Flask.
|
| 394 |
+
body: JSON.stringify({ message: message, session_id: sessionId })
|
| 395 |
})
|
| 396 |
.then(response => response.json())
|
| 397 |
.then(data => {
|
| 398 |
chatHistory.removeChild(thinkingMessageDiv);
|
| 399 |
|
| 400 |
+
const suMessageDiv = document.createElement('div');
|
| 401 |
suMessageDiv.className = 'su-message';
|
| 402 |
+
suMessageDiv.textContent = `SU: ${data.response}`;
|
| 403 |
chatHistory.appendChild(suMessageDiv);
|
| 404 |
|
| 405 |
// Exibir dados de avaliação se presentes
|
|
|
|
| 419 |
chatHistory.removeChild(thinkingMessageDiv);
|
| 420 |
}
|
| 421 |
const errorMessageDiv = document.createElement('div');
|
| 422 |
+
errorMessageDiv.className = 'su-message';
|
| 423 |
+
errorMessageDiv.textContent = `SU: [ERRO] Não consegui responder. Tente novamente.`;
|
| 424 |
chatHistory.appendChild(errorMessageDiv);
|
| 425 |
chatHistory.scrollTop = chatHistory.scrollHeight;
|
| 426 |
});
|
|
|
|
| 428 |
|
| 429 |
// Função para carregar o histórico inicial e o estado da Mach5 ao carregar a página
|
| 430 |
window.onload = function() {
|
| 431 |
+
// Verifica se o sessionId foi injetado corretamente.
|
| 432 |
+
if (!sessionId || sessionId === "None") { // Adicionei 'None' caso o Flask passe um valor nulo como string
|
| 433 |
+
console.error("Session ID não encontrado no template. Verifique a passagem de contexto do Flask.");
|
| 434 |
+
// Você pode adicionar uma lógica de fallback aqui se necessário.
|
| 435 |
+
return; // Impede a chamada da API se não houver sessionId.
|
| 436 |
}
|
| 437 |
|
| 438 |
fetch('/chat_history', {
|
| 439 |
+
method: 'POST',
|
| 440 |
headers: { 'Content-Type': 'application/json' },
|
| 441 |
+
// Envia o session_id que já foi definido no carregamento do script.
|
| 442 |
+
body: JSON.stringify({ session_id: sessionId })
|
| 443 |
})
|
| 444 |
.then(response => response.json())
|
| 445 |
.then(data => {
|
|
|
|
| 450 |
userMessageDiv.textContent = `Você: ${item.input}`;
|
| 451 |
chatHistory.appendChild(userMessageDiv);
|
| 452 |
|
| 453 |
+
const suMessageDiv = document.createElement('div');
|
| 454 |
suMessageDiv.className = 'su-message';
|
| 455 |
+
suMessageDiv.textContent = `SU: ${item.resposta}`;
|
| 456 |
chatHistory.appendChild(suMessageDiv);
|
| 457 |
|
| 458 |
// Adiciona dados ao histórico do gráfico de linha ao carregar o histórico salvo
|
templates/mach5_new_chat.html
CHANGED
|
@@ -111,19 +111,22 @@
|
|
| 111 |
<div class="chat-container">
|
| 112 |
<h1>🎓 SU - Atendente Virtual da SUPAC</h1>
|
| 113 |
<div class="chat-history" id="chat-history">
|
| 114 |
-
|
| 115 |
|
| 116 |
<div class="input-container">
|
| 117 |
<input type="text" id="message-input" placeholder="Pergunte sobre o SIGAA..." />
|
| 118 |
<input type="submit" value="Enviar" id="send-button" />
|
| 119 |
</div>
|
| 120 |
|
| 121 |
-
|
| 122 |
|
| 123 |
<script>
|
| 124 |
-
|
|
|
|
|
|
|
| 125 |
|
| 126 |
-
//
|
|
|
|
| 127 |
function getCookie(name) {
|
| 128 |
const nameEQ = name + "=";
|
| 129 |
const ca = document.cookie.split(';');
|
|
@@ -168,7 +171,8 @@
|
|
| 168 |
headers: {
|
| 169 |
'Content-Type': 'application/json'
|
| 170 |
},
|
| 171 |
-
|
|
|
|
| 172 |
})
|
| 173 |
.then(response => response.json())
|
| 174 |
.then(data => {
|
|
@@ -196,17 +200,18 @@
|
|
| 196 |
|
| 197 |
// Função para carregar o histórico inicial
|
| 198 |
window.onload = function() {
|
| 199 |
-
|
| 200 |
-
if (!sessionId) {
|
| 201 |
-
console.error("Session ID não encontrado
|
| 202 |
-
//
|
| 203 |
-
//
|
| 204 |
}
|
| 205 |
|
| 206 |
fetch('/chat_history', {
|
| 207 |
-
method: 'POST',
|
| 208 |
headers: { 'Content-Type': 'application/json' },
|
| 209 |
-
|
|
|
|
| 210 |
})
|
| 211 |
.then(response => response.json())
|
| 212 |
.then(data => {
|
|
|
|
| 111 |
<div class="chat-container">
|
| 112 |
<h1>🎓 SU - Atendente Virtual da SUPAC</h1>
|
| 113 |
<div class="chat-history" id="chat-history">
|
| 114 |
+
</div>
|
| 115 |
|
| 116 |
<div class="input-container">
|
| 117 |
<input type="text" id="message-input" placeholder="Pergunte sobre o SIGAA..." />
|
| 118 |
<input type="submit" value="Enviar" id="send-button" />
|
| 119 |
</div>
|
| 120 |
|
| 121 |
+
</div>
|
| 122 |
|
| 123 |
<script>
|
| 124 |
+
// A linha abaixo é a principal mudança: o session_id será injetado pelo Flask.
|
| 125 |
+
// Certifique-se que o Flask renderize este template passando a variável 'session_id'.
|
| 126 |
+
let sessionId = "{{ session_id }}"; // Agora, o sessionId recebe o valor diretamente do Flask.
|
| 127 |
|
| 128 |
+
// A função getCookie(name) não é mais necessária para obter o sessionId no carregamento inicial,
|
| 129 |
+
// mas pode ser mantida se usada para outros cookies ou futuras funcionalidades.
|
| 130 |
function getCookie(name) {
|
| 131 |
const nameEQ = name + "=";
|
| 132 |
const ca = document.cookie.split(';');
|
|
|
|
| 171 |
headers: {
|
| 172 |
'Content-Type': 'application/json'
|
| 173 |
},
|
| 174 |
+
// O sessionId já está disponível aqui, obtido do Flask.
|
| 175 |
+
body: JSON.stringify({ message: message, session_id: sessionId })
|
| 176 |
})
|
| 177 |
.then(response => response.json())
|
| 178 |
.then(data => {
|
|
|
|
| 200 |
|
| 201 |
// Função para carregar o histórico inicial
|
| 202 |
window.onload = function() {
|
| 203 |
+
// Verifica se o sessionId foi injetado corretamente.
|
| 204 |
+
if (!sessionId || sessionId === "None") { // Adicionei 'None' caso o Flask passe um valor nulo como string
|
| 205 |
+
console.error("Session ID não encontrado no template. Verifique a passagem de contexto do Flask.");
|
| 206 |
+
// Você pode adicionar uma lógica de fallback aqui se necessário.
|
| 207 |
+
return; // Impede a chamada da API se não houver sessionId.
|
| 208 |
}
|
| 209 |
|
| 210 |
fetch('/chat_history', {
|
| 211 |
+
method: 'POST',
|
| 212 |
headers: { 'Content-Type': 'application/json' },
|
| 213 |
+
// Envia o session_id que já foi definido no carregamento do script.
|
| 214 |
+
body: JSON.stringify({ session_id: sessionId })
|
| 215 |
})
|
| 216 |
.then(response => response.json())
|
| 217 |
.then(data => {
|