NiltonSouza commited on
Commit
055a2d6
·
1 Parent(s): 4cd9951

Alterações

Browse files
Files changed (3) hide show
  1. app.py +108 -47
  2. t-social.py +16 -24
  3. t_memoria.py +86 -33
app.py CHANGED
@@ -11,6 +11,7 @@ import uuid
11
  import logging
12
  import google.generativeai as genai
13
  from fuzzywuzzy import fuzz
 
14
 
15
  # Importar configurações compartilhadas
16
  from t_fisica_config import T_FISICA_PARAM_DEFAULTS, T_GENOMA_FIXO_DEFAULTS, ORDERED_FPHEN_AXES
@@ -281,7 +282,6 @@ def calculate_fphen(params, genoma_fixo):
281
 
282
  fphen_values = [phenotype_components.get(key, 0.0) for key in ORDERED_FPHEN_AXES]
283
 
284
- # --- INÍCIO DA CORREÇÃO NA LÓGICA DE top_components ---
285
  sorted_fphen_with_names = sorted([(value, f"f{i+1} ({value*100:.0f}%)") for i, value in enumerate(fphen_values)], key=lambda x: x[0], reverse=True)
286
 
287
  top_components = []
@@ -296,14 +296,13 @@ def calculate_fphen(params, genoma_fixo):
296
  top_components.append(name_with_percentage)
297
  seen_components.add(name_with_percentage)
298
 
299
- if len(top_components) < 3: # Garante que haja pelo menos 3 componentes, se disponíveis
300
  for value, name_with_percentage in sorted_fphen_with_names:
301
  if name_with_percentage not in seen_components and len(top_components) < 3:
302
  top_components.append(name_with_percentage)
303
  seen_components.add(name_with_percentage)
304
  if len(top_components) >= 3:
305
  break
306
- # --- FIM DA CORREÇÃO ---
307
 
308
  composite_description = f"Traços dominantes: {', '.join(top_components)}" if top_components else "Sem traços dominantes claros"
309
 
@@ -352,6 +351,30 @@ def calculate_coherence_and_productivity(user_input_sentiment_type):
352
  current_params = mach5_state["fisica_params"]
353
  current_genoma = mach5_state["genoma_fixo"]
354
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355
  coh_base = 0.7
356
  genoma_intensity = current_genoma.get("g3", 0.5) * 0.4 + current_genoma.get("g2", 0.5) * 0.3 + current_genoma.get("g1", 0.5) * 0.3
357
  coh_adj_genoma = (genoma_intensity - 0.5) * 0.1
@@ -364,29 +387,40 @@ def calculate_coherence_and_productivity(user_input_sentiment_type):
364
  coh_adj_fisica = (fisica_coherence_factors - 0.5) * 0.2
365
 
366
  sentiment_adj = 0
 
 
 
367
  if user_input_sentiment_type == 'negative':
368
- sentiment_adj = -0.15 * current_genoma.get("g6", 0.5)
369
- current_params["p2"] = min(1.0, current_params["p2"] + 0.1 * current_genoma.get("g1", 0.5))
370
- current_params["p5"] = min(1.0, current_params["p5"] + 0.1 * current_genoma.get("g2", 0.5))
371
- current_params["p3"] = min(1.0, current_params["p3"] + 0.1 * (1 - current_genoma.get("g5", 0.5)))
372
- current_params["o5"] = min(1.0, current_params["o5"] + 0.1 * current_genoma.get("g2", 0.5))
373
- current_params["o2"] = min(1.0, current_params["o2"] + 0.1 * (1 - current_genoma.get("g8", 0.5)))
374
- current_params["p1"] = max(0.0, current_params["p1"] - 0.1 * current_genoma.get("g6", 0.5))
375
- current_params["o3"] = max(0.0, current_params["o3"] - 0.1 * (1 - current_genoma.get("g5", 0.5)))
376
- current_params["p4"] = min(1.0, current_params["p4"] + 0.08)
 
 
 
377
  elif user_input_sentiment_type == 'positive':
378
- sentiment_adj = 0.05 * current_genoma.get("g3", 0.5)
379
- current_params["p2"] = max(0.0, current_params["p2"] - 0.05 * (1 - current_genoma.get("g1", 0.5)))
380
- current_params["p5"] = max(0.0, current_params["p5"] - 0.05 * (1 - current_genoma.get("g2", 0.5)))
381
- current_params["p3"] = max(0.0, current_params["p3"] - 0.05 * current_genoma.get("g5", 0.5))
382
- current_params["o5"] = max(0.0, current_params["o5"] - 0.05 * (1 - current_genoma.get("g9", 0.5)))
383
- current_params["o2"] = max(0.0, current_params["o2"] - 0.05 * current_genoma.get("g8", 0.5))
384
- current_params["p1"] = min(1.0, current_params["p1"] + 0.05 * current_genoma.get("g7", 0.5))
385
- current_params["o3"] = min(1.0, current_params["o3"] + 0.05 * current_genoma.get("g5", 0.5))
386
- current_params["p4"] = max(0.0, current_params["p4"] - 0.04)
387
- else:
 
 
 
388
  for param, default_val in T_FISICA_PARAM_DEFAULTS.items():
389
- current_params[param] = current_params.get(param, default_val) * 0.95 + default_val * 0.05
 
 
390
 
391
  new_coherence_total = coh_base + coh_adj_genoma + coh_adj_fisica + sentiment_adj
392
  new_coherence_total = max(0.0, min(1.0, new_coherence_total))
@@ -394,9 +428,9 @@ def calculate_coherence_and_productivity(user_input_sentiment_type):
394
  prod_base = 0.5
395
  prod_adj_genoma = (genoma_intensity - 0.5) * 0.2
396
  if user_input_sentiment_type == 'negative':
397
- prod_adj_sentiment = 0.1 * current_genoma.get("g2", 0.5)
398
  elif user_input_sentiment_type == 'positive':
399
- prod_adj_sentiment = -0.05 * current_genoma.get("g5", 0.5)
400
  else:
401
  prod_adj_sentiment = 0
402
 
@@ -407,6 +441,7 @@ def calculate_coherence_and_productivity(user_input_sentiment_type):
407
  mach5_state["produtividade_expressiva"] = new_produtividade_expressiva
408
  mach5_state["fisica_params"] = current_params
409
 
 
410
  def process_and_filter_short_term_memories_logic(memories_list, current_mach5_genoma, days_to_forget, max_memories_to_prompt):
411
  logging.debug("Processando memórias de curto prazo")
412
  now = datetime.now()
@@ -730,25 +765,53 @@ def get_current_local_time_salvador():
730
  return "Data e hora não determinadas."
731
 
732
  def create_llm_context(mach5_state_data, dialogos_history, short_term_memories_filtered, initial_biography_data, all_personagens_data):
733
- logging.debug("Criando contexto para LLM")
734
  context_parts = []
735
  current_location_time = get_current_local_time_salvador()
736
- context_parts.append(f"Você é a Su, uma entidade virtual para testes de expressividade. Responda com base nos dados numéricos fornecidos, sem inferir emoções ou traços de personalidade a menos que solicitado. {current_location_time}.")
737
- context_parts.append(f"Ambiente físico: {json.dumps(AMBIENTE_FISICO, separators=(',', ':'))}.")
 
 
 
 
 
 
738
 
739
  if mach5_state_data:
 
740
  coh_total = mach5_state_data.get("mach5_coerencia_total", 0.0)
741
  pi_g = mach5_state_data.get("mach5_produtividade_expressiva", 0.0)
742
- context_parts.append(f"Parâmetros de desempenho interno: V1={coh_total:.2f}, V2={pi_g:.2f}.")
743
- context_parts.append(f"Parâmetros t-Física: {json.dumps(mach5_state_data.get('mach5_fisica_params', {}), separators=(',', ':'))}.")
744
- context_parts.append(f"Genoma: {json.dumps(mach5_state_data.get('mach5_genoma_fixo_values', {}), separators=(',', ':'))}.")
745
-
746
- # CHAMA calculate_fphen AQUI PARA OBTER A DESCRIÇÃO
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
747
  fphen_values_for_desc, composite_fphen_description = calculate_fphen(
748
  mach5_state_data.get('mach5_fisica_params', T_FISICA_PARAM_DEFAULTS),
749
  mach5_state_data.get('mach5_genoma_fixo_values', T_GENOMA_FIXO_DEFAULTS)
750
  )
751
- context_parts.append(f"Fenótipo: {composite_fphen_description} - Valores: {json.dumps(dict(zip(ORDERED_FPHEN_AXES, fphen_values_for_desc)), separators=(',', ':'))}.")
 
 
752
 
753
 
754
  if initial_biography_data:
@@ -764,18 +827,20 @@ def create_llm_context(mach5_state_data, dialogos_history, short_term_memories_f
764
  context_parts.append(f"- Sobre '{entity_name}': {entity_data.get('memoria')}")
765
 
766
  if all_personagens_data:
767
- context_parts.append("\n**ENTIDADES:**")
768
  for nome_personagem, data_personagem in all_personagens_data.items():
769
- formatted_genoma = json.dumps(data_personagem.get('genoma', {}), separators=(',', ':'))
770
- context_parts.append(f"- {nome_personagem}: {formatted_genoma}")
 
 
771
 
772
  if short_term_memories_filtered:
773
- context_parts.append("\n**MEMÓRIAS DE CURTO PRAZO:**")
774
  for i, mem in enumerate(short_term_memories_filtered[:MAX_MEMORIAS_CURTO_PRAZO_PROMPT]):
775
- context_parts.append(f"- Lembrança {i+1}: {mem['conteudo']} (Sentimento: {mem.get('dominant_sentiment_criacao', 'neutral')})")
776
 
777
  if dialogos_history and dialogos_history["dialogos"]:
778
- context_parts.append("\n**HISTÓRICO DE DIÁLOGOS (contexto, não repetir):**")
779
  recent_dialogs_formatted = []
780
  for dialogo in reversed(dialogos_history["dialogos"]):
781
  recent_dialogs_formatted.insert(0, f"USUÁRIO: {dialogo.get('input', '')}\nSU: {dialogo.get('resposta', '')}")
@@ -810,11 +875,7 @@ def get_Mach5_response_api(user_input, mach5_state_data, dialogos_history, short
810
 
811
  llm_context_data = create_llm_context(mach5_state_data, dialogos_history, short_term_memories_filtered, initial_biography_data, all_personagens_data)
812
 
813
- prompt_content = (
814
- f"Seu nome é Su, e você é uma pessoa. "
815
- f"Então, fale! "
816
- f"- Dados do ambiente físico: {json.dumps(AMBIENTE_FISICO, separators=(',', ':'))}."
817
- )
818
 
819
  full_user_message = f"{prompt_content.strip()}\n\n{llm_context_data}\n\nUSUÁRIO (COMANDO/PERGUNTA): {user_input}"
820
 
@@ -830,6 +891,8 @@ def get_Mach5_response_api(user_input, mach5_state_data, dialogos_history, short
830
  retries = 3
831
  for attempt in range(retries):
832
  try:
 
 
833
  temp_value = mach5_state_data["mach5_fisica_params"].get("p5", 0.7)
834
  top_p_value = mach5_state_data["mach5_fisica_params"].get("p1", 0.95)
835
  temp_value = max(0.1, min(1.0, temp_value))
@@ -946,12 +1009,10 @@ def responder():
946
  file_description="estado principal da Mach5"
947
  )
948
 
949
- # infer_sentiment_from_input deve estar definida acima desta linha.
950
  user_input_sentiment_type = infer_sentiment_from_input(user_input)
951
  calculate_coherence_and_productivity(user_input_sentiment_type)
952
  save_session_data(session_id, STATE_FILENAME, mach5_state, "estado principal da Mach5")
953
 
954
- # Garante que calculate_fphen retorne a descrição e os valores
955
  fphen_values_calculated, _ = calculate_fphen(mach5_state["fisica_params"], mach5_state["genoma_fixo"])
956
 
957
  mach5_state_data = {
 
11
  import logging
12
  import google.generativeai as genai
13
  from fuzzywuzzy import fuzz
14
+ import re # Importar regex para extração da hora
15
 
16
  # Importar configurações compartilhadas
17
  from t_fisica_config import T_FISICA_PARAM_DEFAULTS, T_GENOMA_FIXO_DEFAULTS, ORDERED_FPHEN_AXES
 
282
 
283
  fphen_values = [phenotype_components.get(key, 0.0) for key in ORDERED_FPHEN_AXES]
284
 
 
285
  sorted_fphen_with_names = sorted([(value, f"f{i+1} ({value*100:.0f}%)") for i, value in enumerate(fphen_values)], key=lambda x: x[0], reverse=True)
286
 
287
  top_components = []
 
296
  top_components.append(name_with_percentage)
297
  seen_components.add(name_with_percentage)
298
 
299
+ if len(top_components) < 3:
300
  for value, name_with_percentage in sorted_fphen_with_names:
301
  if name_with_percentage not in seen_components and len(top_components) < 3:
302
  top_components.append(name_with_percentage)
303
  seen_components.add(name_with_percentage)
304
  if len(top_components) >= 3:
305
  break
 
306
 
307
  composite_description = f"Traços dominantes: {', '.join(top_components)}" if top_components else "Sem traços dominantes claros"
308
 
 
351
  current_params = mach5_state["fisica_params"]
352
  current_genoma = mach5_state["genoma_fixo"]
353
 
354
+ # Obter a hora do dia para modulação do t-Tempo
355
+ current_time_str = get_current_local_time_salvador()
356
+ hour_of_day = 12 # Default
357
+ match = re.search(r'Agora são (\d{2}):\d{2}:\d{2}', current_time_str)
358
+ if match:
359
+ hour_of_day = int(match.group(1))
360
+
361
+ # Definir Plasticidade Baseada no t-Genoma (g9: Maleabilidade)
362
+ # G9 é 'B-M1' no T_GENOMA_FIXO_DEFAULTS, que significa Maleabilidade/Adaptação
363
+ plasticity_factor_base = current_genoma.get("g9", 0.5)
364
+
365
+ # Modulação da Plasticidade pelo t-Tempo
366
+ time_based_plasticity_modifier = 1.0
367
+ if 6 <= hour_of_day < 12: # Manhã (potencialmente mais plástica, início do "ciclo ativo")
368
+ time_based_plasticity_modifier = 1.1
369
+ elif 18 <= hour_of_day < 24: # Noite (potencialmente menos plástica, "recolhimento")
370
+ time_based_plasticity_modifier = 0.9
371
+ elif 0 <= hour_of_day < 6: # Madrugada (ainda menos plástica, "inércia")
372
+ time_based_plasticity_modifier = 0.8
373
+
374
+ # Garantir que o fator de plasticidade esteja dentro dos limites razoáveis [0.1, 1.0]
375
+ plasticity_factor = max(0.1, min(1.0, plasticity_factor_base * time_based_plasticity_modifier))
376
+ logging.debug(f"Plasticidade (g9_base={plasticity_factor_base:.2f}, hora={hour_of_day}h, mod_tempo={time_based_plasticity_modifier:.2f}): {plasticity_factor:.2f}")
377
+
378
  coh_base = 0.7
379
  genoma_intensity = current_genoma.get("g3", 0.5) * 0.4 + current_genoma.get("g2", 0.5) * 0.3 + current_genoma.get("g1", 0.5) * 0.3
380
  coh_adj_genoma = (genoma_intensity - 0.5) * 0.1
 
387
  coh_adj_fisica = (fisica_coherence_factors - 0.5) * 0.2
388
 
389
  sentiment_adj = 0
390
+ # Modulando ajustes com base na plasticidade
391
+ # Um impacto maior é aplicado se a plasticidade for baixa (resistência à mudança)
392
+ # Um impacto menor/ajuste mais suave se a plasticidade for alta (adaptação)
393
  if user_input_sentiment_type == 'negative':
394
+ # g6 (B-Si/Resistência) amplifica o impacto negativo. Baixa plasticidade aumenta a aversão.
395
+ sentiment_adj = -0.15 * current_genoma.get("g6", 0.5) * (1.5 - plasticity_factor) # Ex: se plasticidade=0.1, (1.5-0.1)=1.4; se plasticidade=1.0, (1.5-1.0)=0.5
396
+
397
+ # Ajustes nos parâmetros t-Física: maior mudança com baixa plasticidade
398
+ current_params["p2"] = min(1.0, current_params["p2"] + 0.1 * current_genoma.get("g1", 0.5) * (1 + (1-plasticity_factor)*0.5)) # p2: Intensidade (impulsividade)
399
+ current_params["p5"] = min(1.0, current_params["p5"] + 0.1 * current_genoma.get("g2", 0.5) * (1 + (1-plasticity_factor)*0.5)) # p5: Impulsividade
400
+ current_params["p3"] = min(1.0, current_params["p3"] + 0.1 * (1 - current_genoma.get("g5", 0.5)) * (1 + (1-plasticity_factor)*0.5)) # p3: Separação
401
+ current_params["o5"] = min(1.0, current_params["o5"] + 0.1 * current_genoma.get("g2", 0.5) * (1 + (1-plasticity_factor)*0.5)) # o5: TDO (tendência a dominar)
402
+ current_params["o2"] = min(1.0, current_params["o2"] + 0.1 * (1 - current_genoma.get("g8", 0.5)) * (1 + (1-plasticity_factor)*0.5)) # o2: TRS (tendência a resistir)
403
+ current_params["p1"] = max(0.0, current_params["p1"] - 0.1 * current_genoma.get("g6", 0.5) * (1 + (1-plasticity_factor)*0.5)) # p1: Coesão (reduzida com negatividade e baixa plasticidade)
404
+ current_params["o3"] = max(0.0, current_params["o3"] - 0.1 * (1 - current_genoma.get("g5", 0.5)) * (1 + (1-plasticity_factor)*0.5)) # o3: TAM (tendência a minimizar)
405
+ current_params["p4"] = min(1.0, current_params["p4"] + 0.08 * (1 + (1-plasticity_factor)*0.5)) # p4: Variância
406
  elif user_input_sentiment_type == 'positive':
407
+ # g3 (B-E1/Expressividade) amplifica o impacto positivo. Alta plasticidade = maior absorção.
408
+ sentiment_adj = 0.05 * current_genoma.get("g3", 0.5) * (0.5 + plasticity_factor) # Ex: se plasticidade=0.1, (0.5+0.1)=0.6; se plasticidade=1.0, (0.5+1.0)=1.5
409
+
410
+ # Ajustes nos parâmetros t-Física: menor mudança (aproveitamento) com alta plasticidade
411
+ current_params["p2"] = max(0.0, current_params["p2"] - 0.05 * (1 - current_genoma.get("g1", 0.5)) * (1 + (1-plasticity_factor)*0.2))
412
+ current_params["p5"] = max(0.0, current_params["p5"] - 0.05 * (1 - current_genoma.get("g2", 0.5)) * (1 + (1-plasticity_factor)*0.2))
413
+ current_params["p3"] = max(0.0, current_params["p3"] - 0.05 * current_genoma.get("g5", 0.5) * (1 + (1-plasticity_factor)*0.2))
414
+ current_params["o5"] = max(0.0, current_params["o5"] - 0.05 * (1 - current_genoma.get("g9", 0.5)) * (1 + (1-plasticity_factor)*0.2))
415
+ current_params["o2"] = max(0.0, current_params["o2"] - 0.05 * current_genoma.get("g8", 0.5) * (1 + (1-plasticity_factor)*0.2))
416
+ current_params["p1"] = min(1.0, current_params["p1"] + 0.05 * current_genoma.get("g7", 0.5) * (1 + (1-plasticity_factor)*0.2))
417
+ current_params["o3"] = min(1.0, current_params["o3"] + 0.05 * current_genoma.get("g5", 0.5) * (1 + (1-plasticity_factor)*0.2))
418
+ current_params["p4"] = max(0.0, current_params["p4"] - 0.04 * (1 + (1-plasticity_factor)*0.2))
419
+ else: # Ajuste neutro, suave e com base na plasticidade (retorno à média, mais rápido com plasticidade alta)
420
  for param, default_val in T_FISICA_PARAM_DEFAULTS.items():
421
+ # Acelera o retorno aos defaults com base na plasticidade. Mais plástico = volta mais rápido ao "equilíbrio".
422
+ current_params[param] = current_params.get(param, default_val) * (0.95 + 0.05 * (1 - plasticity_factor)) + default_val * (0.05 + 0.05 * plasticity_factor)
423
+ current_params[param] = max(0.0, min(1.0, current_params[param])) # Garantir limites
424
 
425
  new_coherence_total = coh_base + coh_adj_genoma + coh_adj_fisica + sentiment_adj
426
  new_coherence_total = max(0.0, min(1.0, new_coherence_total))
 
428
  prod_base = 0.5
429
  prod_adj_genoma = (genoma_intensity - 0.5) * 0.2
430
  if user_input_sentiment_type == 'negative':
431
+ prod_adj_sentiment = 0.1 * current_genoma.get("g2", 0.5) * (1.5 - plasticity_factor)
432
  elif user_input_sentiment_type == 'positive':
433
+ prod_adj_sentiment = -0.05 * current_genoma.get("g5", 0.5) * (0.5 + plasticity_factor)
434
  else:
435
  prod_adj_sentiment = 0
436
 
 
441
  mach5_state["produtividade_expressiva"] = new_produtividade_expressiva
442
  mach5_state["fisica_params"] = current_params
443
 
444
+
445
  def process_and_filter_short_term_memories_logic(memories_list, current_mach5_genoma, days_to_forget, max_memories_to_prompt):
446
  logging.debug("Processando memórias de curto prazo")
447
  now = datetime.now()
 
765
  return "Data e hora não determinadas."
766
 
767
  def create_llm_context(mach5_state_data, dialogos_history, short_term_memories_filtered, initial_biography_data, all_personagens_data):
768
+ logging.debug("Criando contexto para LLM com dados anonimizados.")
769
  context_parts = []
770
  current_location_time = get_current_local_time_salvador()
771
+
772
+ # Comando de "ser" e "falar" da SU
773
+ context_parts.append(
774
+ f"Você é a Su. Sua função é processar entradas e gerar saídas estritamente com base nos valores numéricos dos seus parâmetros internos e no contexto fornecido. Não infira, simule ou adote emoções, intenções ou traços de personalidade que não sejam diretamente resultantes do cálculo desses parâmetros. {current_location_time}. Fale!"
775
+ )
776
+
777
+ # Ambiente Físico (factual e sem juízos de valor)
778
+ context_parts.append(f"Ambiente: {json.dumps(AMBIENTE_FISICO, separators=(',', ':'))}.")
779
 
780
  if mach5_state_data:
781
+ # Parâmetros de desempenho interno (anonimizados)
782
  coh_total = mach5_state_data.get("mach5_coerencia_total", 0.0)
783
  pi_g = mach5_state_data.get("mach5_produtividade_expressiva", 0.0)
784
+ context_parts.append(f"Valores Internos: V1={coh_total:.2f}, V2={pi_g:.2f}.")
785
+
786
+ # Parâmetros t-Física (anonimizados)
787
+ fisica_params = mach5_state_data.get('mach5_fisica_params', {})
788
+ # Usando 'P', 'E', 'O' como categorias mais neutras para os parâmetros
789
+ formatted_fisica_params = {
790
+ f"P{i+1}": v for i, (k, v) in enumerate(fisica_params.items()) if k.startswith('p')
791
+ }
792
+ formatted_fisica_params.update({
793
+ f"E{i+1}": v for i, (k, v) in enumerate(fisica_params.items()) if k.startswith('e')
794
+ })
795
+ formatted_fisica_params.update({
796
+ f"O{i+1}": v for i, (k, v) in enumerate(fisica_params.items()) if k.startswith('o')
797
+ })
798
+ context_parts.append(f"T-Física: {json.dumps(formatted_fisica_params, separators=(',', ':'))}.")
799
+
800
+ # Genoma (anonimizado)
801
+ genoma_fixo = mach5_state_data.get('mach5_genoma_fixo_values', {})
802
+ formatted_genoma = {
803
+ f"G{i+1}": v for i, (k, v) in enumerate(genoma_fixo.items())
804
+ }
805
+ context_parts.append(f"T-Genoma: {json.dumps(formatted_genoma, separators=(',', ':'))}.")
806
+
807
+ # Fenótipo (apenas valores numéricos e rótulos genéricos para f1, f2... f13)
808
  fphen_values_for_desc, composite_fphen_description = calculate_fphen(
809
  mach5_state_data.get('mach5_fisica_params', T_FISICA_PARAM_DEFAULTS),
810
  mach5_state_data.get('mach5_genoma_fixo_values', T_GENOMA_FIXO_DEFAULTS)
811
  )
812
+ # A descrição composta não é incluída diretamente para o LLM para evitar contaminação semântica
813
+ fphen_numeric_values = {f"F{i+1}": val for i, val in enumerate(fphen_values_for_desc)}
814
+ context_parts.append(f"T-Fenótipo: {json.dumps(fphen_numeric_values, separators=(',', ':'))}.")
815
 
816
 
817
  if initial_biography_data:
 
827
  context_parts.append(f"- Sobre '{entity_name}': {entity_data.get('memoria')}")
828
 
829
  if all_personagens_data:
830
+ context_parts.append("\n**ENTIDADES SOCIAIS:**")
831
  for nome_personagem, data_personagem in all_personagens_data.items():
832
+ formatted_genoma_personagem = {
833
+ f"G{i+1}": v for i, (k, v) in enumerate(data_personagem.get('genoma', {}).items())
834
+ }
835
+ context_parts.append(f"- {nome_personagem}: Genoma={json.dumps(formatted_genoma_personagem, separators=(',', ':'))}, Localização={json.dumps(data_personagem.get('localizacao', {}), separators=(',', ':'))}")
836
 
837
  if short_term_memories_filtered:
838
+ context_parts.append("\n**MEMÓRIAS TEMPORÁRIAS:**")
839
  for i, mem in enumerate(short_term_memories_filtered[:MAX_MEMORIAS_CURTO_PRAZO_PROMPT]):
840
+ context_parts.append(f"- M{i+1}: {mem['conteudo']} (Metadado: {mem.get('dominant_sentiment_criacao', 'neutral')}, Coh: {mem.get('coh_criacao', 0.0):.2f})")
841
 
842
  if dialogos_history and dialogos_history["dialogos"]:
843
+ context_parts.append("\n**HISTÓRICO DE INTERAÇÕES (contexto de conversa, não repetir):**")
844
  recent_dialogs_formatted = []
845
  for dialogo in reversed(dialogos_history["dialogos"]):
846
  recent_dialogs_formatted.insert(0, f"USUÁRIO: {dialogo.get('input', '')}\nSU: {dialogo.get('resposta', '')}")
 
875
 
876
  llm_context_data = create_llm_context(mach5_state_data, dialogos_history, short_term_memories_filtered, initial_biography_data, all_personagens_data)
877
 
878
+ prompt_content = "" # Instrução principal já na função create_llm_context
 
 
 
 
879
 
880
  full_user_message = f"{prompt_content.strip()}\n\n{llm_context_data}\n\nUSUÁRIO (COMANDO/PERGUNTA): {user_input}"
881
 
 
891
  retries = 3
892
  for attempt in range(retries):
893
  try:
894
+ # Reutilizando p5 para temperature e p1 para top_p
895
+ # Os nomes dos parâmetros p5 e p1 são usados aqui internamente, não expostos ao LLM
896
  temp_value = mach5_state_data["mach5_fisica_params"].get("p5", 0.7)
897
  top_p_value = mach5_state_data["mach5_fisica_params"].get("p1", 0.95)
898
  temp_value = max(0.1, min(1.0, temp_value))
 
1009
  file_description="estado principal da Mach5"
1010
  )
1011
 
 
1012
  user_input_sentiment_type = infer_sentiment_from_input(user_input)
1013
  calculate_coherence_and_productivity(user_input_sentiment_type)
1014
  save_session_data(session_id, STATE_FILENAME, mach5_state, "estado principal da Mach5")
1015
 
 
1016
  fphen_values_calculated, _ = calculate_fphen(mach5_state["fisica_params"], mach5_state["genoma_fixo"])
1017
 
1018
  mach5_state_data = {
t-social.py CHANGED
@@ -216,38 +216,29 @@ def calculate_fphen(params, genoma_fixo):
216
 
217
  fphen_values = [phenotype_components.get(key, 0.0) for key in ORDERED_FPHEN_AXES]
218
 
219
- # --- INÍCIO DA CORREÇÃO ---
220
- # Ordena os componentes por valor em ordem decrescente
221
  sorted_fphen_with_names = sorted([(value, f"f{i+1} ({value*100:.0f}%)") for i, value in enumerate(fphen_values)], key=lambda x: x[0], reverse=True)
222
-
223
  top_components = []
224
  seen_components = set()
225
 
226
  for value, name_with_percentage in sorted_fphen_with_names:
227
  if name_with_percentage not in seen_components:
228
- # Adiciona componentes com valor >= 0.10
229
  if value >= 0.10:
230
  top_components.append(name_with_percentage)
231
  seen_components.add(name_with_percentage)
232
- # Se ainda não tiver 3 componentes e o valor for > 0.05, adicione
233
  elif len(top_components) < 3 and value > 0.05:
234
  top_components.append(name_with_percentage)
235
  seen_components.add(name_with_percentage)
236
-
237
- # Opcional: Para otimizar, se já temos 3 componentes e os próximos são menores que 0.10, podemos parar.
238
- # Mas a lógica final garante pelo menos 3 se houver.
239
- # if len(top_components) >= 3 and all(v < 0.10 for v, _ in sorted_fphen_with_names[len(top_components):]):
240
- # break
241
-
242
- # Garante que sempre haverá pelo menos 3 traços, se disponíveis
243
- if len(top_components) < 3:
244
  for value, name_with_percentage in sorted_fphen_with_names:
245
  if name_with_percentage not in seen_components and len(top_components) < 3:
246
  top_components.append(name_with_percentage)
247
  seen_components.add(name_with_percentage)
248
  if len(top_components) >= 3:
249
  break
250
- # --- FIM DA CORREÇÃO ---
251
 
252
  composite_description = f"Traços dominantes: {', '.join(top_components)}" if top_components else "Sem traços dominantes claros"
253
 
@@ -265,35 +256,36 @@ def get_personagem_data():
265
  data = request.get_json()
266
  nome_personagem_requisitado = data.get('nome_personagem')
267
  logging.debug(f"Requisição para /get_personagem_data recebida para '{nome_personagem_requisitado}'")
268
-
269
  personagem_encontrado_nome = None
270
  for nome_real, config in PERSONAGENS_GENOMAS.items():
271
  if nome_personagem_requisitado and nome_personagem_requisitado.lower() == nome_real.lower():
272
  personagem_encontrado_nome = nome_real
273
  break
274
-
275
  if personagem_encontrado_nome:
276
  personagem_config = PERSONAGENS_GENOMAS.get(personagem_encontrado_nome)
277
  current_time = datetime.now().isoformat()
278
-
279
  PERSONAGENS_ESTADO_ATUAL[personagem_encontrado_nome]["ultima_interacao_timestamp"] = current_time
280
 
 
281
  fphen_values, composite_fphen_description = calculate_fphen(
282
  personagem_config.get("fisica_params_iniciais", T_FISICA_PARAM_DEFAULTS),
283
  personagem_config.get("genoma", T_GENOMA_FIXO_DEFAULTS)
284
  )
285
-
286
  PERSONAGENS_ESTADO_ATUAL[personagem_encontrado_nome]["fphen_calculado"] = fphen_values
287
-
288
  data_to_return = personagem_config.copy()
289
  data_to_return["nome"] = personagem_encontrado_nome
290
  data_to_return["ultima_interacao_timestamp"] = current_time
291
  data_to_return["fphen_calculado"] = fphen_values
292
- data_to_return["composite_fphen_description"] = composite_fphen_description
293
-
294
  logging.debug(f"Dados de '{personagem_encontrado_nome}' retornados com fphen calculado.")
295
  return jsonify(data_to_return), 200
296
-
297
  logging.error(f"Personagem '{nome_personagem_requisitado}' não encontrado.")
298
  return jsonify({"error": f"Personagem '{nome_personagem_requisitado}' não encontrado"}), 404
299
 
@@ -304,7 +296,7 @@ if __name__ == '__main__':
304
  except ValueError:
305
  logging.error("ERRO: O valor da variável de ambiente 'PORT' não é um número válido. Usando a primeira porta da lista.")
306
  preferred_port = PORTS_TO_TRY[0]
307
-
308
  try:
309
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
310
  s.bind(("127.0.0.1", preferred_port))
@@ -326,7 +318,7 @@ if __name__ == '__main__':
326
  except OSError:
327
  logging.warning(f"Porta {port} em uso. Tentando a próxima...")
328
  continue
329
-
330
  if found_port:
331
  logging.info(f"--- Servidor t-social.py iniciado (Gerenciador de Personagens) na porta {found_port} ---")
332
  app.run(host='0.0.0.0', port=found_port, debug=True)
 
216
 
217
  fphen_values = [phenotype_components.get(key, 0.0) for key in ORDERED_FPHEN_AXES]
218
 
219
+ # --- INÍCIO DA LÓGICA top_components (CÓPIA DE app.py E t_memoria.py) ---
 
220
  sorted_fphen_with_names = sorted([(value, f"f{i+1} ({value*100:.0f}%)") for i, value in enumerate(fphen_values)], key=lambda x: x[0], reverse=True)
221
+
222
  top_components = []
223
  seen_components = set()
224
 
225
  for value, name_with_percentage in sorted_fphen_with_names:
226
  if name_with_percentage not in seen_components:
 
227
  if value >= 0.10:
228
  top_components.append(name_with_percentage)
229
  seen_components.add(name_with_percentage)
 
230
  elif len(top_components) < 3 and value > 0.05:
231
  top_components.append(name_with_percentage)
232
  seen_components.add(name_with_percentage)
233
+
234
+ if len(top_components) < 3: # Garante que haja pelo menos 3 componentes, se disponíveis
 
 
 
 
 
 
235
  for value, name_with_percentage in sorted_fphen_with_names:
236
  if name_with_percentage not in seen_components and len(top_components) < 3:
237
  top_components.append(name_with_percentage)
238
  seen_components.add(name_with_percentage)
239
  if len(top_components) >= 3:
240
  break
241
+ # --- FIM DA LÓGICA top_components ---
242
 
243
  composite_description = f"Traços dominantes: {', '.join(top_components)}" if top_components else "Sem traços dominantes claros"
244
 
 
256
  data = request.get_json()
257
  nome_personagem_requisitado = data.get('nome_personagem')
258
  logging.debug(f"Requisição para /get_personagem_data recebida para '{nome_personagem_requisitado}'")
259
+
260
  personagem_encontrado_nome = None
261
  for nome_real, config in PERSONAGENS_GENOMAS.items():
262
  if nome_personagem_requisitado and nome_personagem_requisitado.lower() == nome_real.lower():
263
  personagem_encontrado_nome = nome_real
264
  break
265
+
266
  if personagem_encontrado_nome:
267
  personagem_config = PERSONAGENS_GENOMAS.get(personagem_encontrado_nome)
268
  current_time = datetime.now().isoformat()
269
+
270
  PERSONAGENS_ESTADO_ATUAL[personagem_encontrado_nome]["ultima_interacao_timestamp"] = current_time
271
 
272
+ # Calcula o fphen para o personagem solicitado
273
  fphen_values, composite_fphen_description = calculate_fphen(
274
  personagem_config.get("fisica_params_iniciais", T_FISICA_PARAM_DEFAULTS),
275
  personagem_config.get("genoma", T_GENOMA_FIXO_DEFAULTS)
276
  )
277
+
278
  PERSONAGENS_ESTADO_ATUAL[personagem_encontrado_nome]["fphen_calculado"] = fphen_values
279
+
280
  data_to_return = personagem_config.copy()
281
  data_to_return["nome"] = personagem_encontrado_nome
282
  data_to_return["ultima_interacao_timestamp"] = current_time
283
  data_to_return["fphen_calculado"] = fphen_values
284
+ data_to_return["composite_fphen_description"] = composite_fphen_description
285
+
286
  logging.debug(f"Dados de '{personagem_encontrado_nome}' retornados com fphen calculado.")
287
  return jsonify(data_to_return), 200
288
+
289
  logging.error(f"Personagem '{nome_personagem_requisitado}' não encontrado.")
290
  return jsonify({"error": f"Personagem '{nome_personagem_requisitado}' não encontrado"}), 404
291
 
 
296
  except ValueError:
297
  logging.error("ERRO: O valor da variável de ambiente 'PORT' não é um número válido. Usando a primeira porta da lista.")
298
  preferred_port = PORTS_TO_TRY[0]
299
+
300
  try:
301
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
302
  s.bind(("127.0.0.1", preferred_port))
 
318
  except OSError:
319
  logging.warning(f"Porta {port} em uso. Tentando a próxima...")
320
  continue
321
+
322
  if found_port:
323
  logging.info(f"--- Servidor t-social.py iniciado (Gerenciador de Personagens) na porta {found_port} ---")
324
  app.run(host='0.0.0.0', port=found_port, debug=True)
t_memoria.py CHANGED
@@ -3,11 +3,12 @@ import json
3
  import os
4
  from datetime import datetime
5
  import pytz
6
- from fuzzywuzzy import fuzz # CORRIGIDO: mudado de timezonefinder para fuzzywuzzy
7
  import numpy as np
8
  import requests
9
  import time
10
  import logging
 
11
 
12
  # Importar configurações compartilhadas
13
  from t_fisica_config import T_FISICA_PARAM_DEFAULTS, T_GENOMA_FIXO_DEFAULTS, ORDERED_FPHEN_AXES
@@ -17,8 +18,9 @@ app = Flask(__name__)
17
  # Configuração de logging
18
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
19
 
20
- TCEREBRO_MEMORIA_URL = "http://127.0.0.1:8088"
21
 
 
22
  mach5_state = {
23
  "genoma_fixo": T_GENOMA_FIXO_DEFAULTS,
24
  "fisica_params": T_FISICA_PARAM_DEFAULTS,
@@ -27,11 +29,26 @@ mach5_state = {
27
  "produtividade_expressiva": 0.5
28
  }
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  def load_mach5_state_from_cerebro(session_id, max_retries=3):
31
  global mach5_state
32
  for attempt in range(max_retries):
33
  try:
34
- response = requests.post(f"{TCEREBRO_MEMORIA_URL}/get_mach5_main_state",
35
  json={"session_id": session_id}, timeout=5)
36
  response.raise_for_status()
37
  loaded_state = response.json()
@@ -45,11 +62,11 @@ def load_mach5_state_from_cerebro(session_id, max_retries=3):
45
  if attempt < max_retries - 1:
46
  time.sleep(2 ** attempt)
47
  else:
48
- logging.info("INFO: Usando defaults internos para o estado da Mach5 após falha.")
49
  mach5_state = {
50
- "genoma_fixo": T_GENOMA_FIXO_DEFAULTS,
51
  "fisica_params": T_FISICA_PARAM_DEFAULTS,
52
- "historico_interacoes": [],
53
  "coerencia_total": 0.5,
54
  "produtividade_expressiva": 0.5
55
  }
@@ -58,6 +75,7 @@ def load_mach5_state_from_cerebro(session_id, max_retries=3):
58
  if attempt < max_retries - 1:
59
  time.sleep(2 ** attempt)
60
  else:
 
61
  mach5_state = {
62
  "genoma_fixo": T_GENOMA_FIXO_DEFAULTS,
63
  "fisica_params": T_FISICA_PARAM_DEFAULTS,
@@ -74,7 +92,7 @@ def save_mach5_state_to_cerebro(session_id):
74
  "coerencia_total": mach5_state["coerencia_total"],
75
  "produtividade_expressiva": mach5_state["produtividade_expressiva"]
76
  }
77
- response = requests.post(f"{TCEREBRO_MEMORIA_URL}/update_mach5_main_state",
78
  json={"session_id": session_id, "state_data": state_to_save}, timeout=5)
79
  response.raise_for_status()
80
  logging.debug(f"DEBUG: Estado da Mach5 para sessão {session_id} salvo no t_cerebro_memoria.py: {state_to_save}")
@@ -93,7 +111,7 @@ def infer_sentiment_from_input(user_input):
93
  user_input_lower = user_input.lower()
94
  sentiment_score = 0.0
95
  for keyword, weight in [
96
- ('bacana', 0.1), ('interessante', 0.1), ('feliz', 0.2), ('gosto', 0.15),
97
  ('legal', 0.1), ('bom', 0.1), ('ótimo', 0.15), ('maravilhoso', 0.2),
98
  ('burro', -0.1), ('idiota', -0.2), ('imbecil', -0.15), ('odeio', -0.2),
99
  ('morra', -0.25), ('inútil', -0.15), ('verme', -0.2), ('exploda', -0.25)
@@ -108,12 +126,39 @@ def infer_sentiment_from_input(user_input):
108
  return 'question'
109
  return 'neutral'
110
 
 
 
 
 
111
  def calculate_coherence_and_productivity(user_input_sentiment_type):
 
112
  global mach5_state
113
 
114
  current_params = mach5_state["fisica_params"]
115
  current_genoma = mach5_state["genoma_fixo"]
116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  coh_base = 0.7
118
  genoma_intensity = current_genoma.get("g3", 0.5) * 0.4 + current_genoma.get("g2", 0.5) * 0.3 + current_genoma.get("g1", 0.5) * 0.3
119
  coh_adj_genoma = (genoma_intensity - 0.5) * 0.1
@@ -127,28 +172,29 @@ def calculate_coherence_and_productivity(user_input_sentiment_type):
127
 
128
  sentiment_adj = 0
129
  if user_input_sentiment_type == 'negative':
130
- sentiment_adj = -0.15 * current_genoma.get("g6", 0.5)
131
- current_params["p2"] = min(1.0, current_params["p2"] + 0.1 * current_genoma.get("g1", 0.5))
132
- current_params["p5"] = min(1.0, current_params["p5"] + 0.1 * current_genoma.get("g2", 0.5))
133
- current_params["p3"] = min(1.0, current_params["p3"] + 0.1 * (1 - current_genoma.get("g5", 0.5)))
134
- current_params["o5"] = min(1.0, current_params["o5"] + 0.1 * current_genoma.get("g2", 0.5))
135
- current_params["o2"] = min(1.0, current_params["o2"] + 0.1 * (1 - current_genoma.get("g8", 0.5)))
136
- current_params["p1"] = max(0.0, current_params["p1"] - 0.1 * current_genoma.get("g6", 0.5))
137
- current_params["o3"] = max(0.0, current_params["o3"] - 0.1 * (1 - current_genoma.get("g5", 0.5)))
138
- current_params["p4"] = min(1.0, current_params["p4"] + 0.08)
139
  elif user_input_sentiment_type == 'positive':
140
- sentiment_adj = 0.05 * current_genoma.get("g3", 0.5)
141
- current_params["p2"] = max(0.0, current_params["p2"] - 0.05 * (1 - current_genoma.get("g1", 0.5)))
142
- current_params["p5"] = max(0.0, current_params["p5"] - 0.05 * (1 - current_genoma.get("g2", 0.5)))
143
- current_params["p3"] = max(0.0, current_params["p3"] - 0.05 * current_genoma.get("g5", 0.5))
144
- current_params["o5"] = max(0.0, current_params["o5"] - 0.05 * (1 - current_genoma.get("g9", 0.5)))
145
- current_params["o2"] = max(0.0, current_params["o2"] - 0.05 * current_genoma.get("g8", 0.5))
146
- current_params["p1"] = min(1.0, current_params["p1"] + 0.05 * current_genoma.get("g7", 0.5))
147
- current_params["o3"] = min(1.0, current_params["o3"] + 0.05 * current_genoma.get("g5", 0.5))
148
- current_params["p4"] = max(0.0, current_params["p4"] - 0.04)
149
  else:
150
  for param, default_val in T_FISICA_PARAM_DEFAULTS.items():
151
- current_params[param] = current_params.get(param, default_val) * 0.95 + default_val * 0.05
 
152
 
153
  new_coherence_total = coh_base + coh_adj_genoma + coh_adj_fisica + sentiment_adj
154
  new_coherence_total = max(0.0, min(1.0, new_coherence_total))
@@ -156,9 +202,9 @@ def calculate_coherence_and_productivity(user_input_sentiment_type):
156
  prod_base = 0.5
157
  prod_adj_genoma = (genoma_intensity - 0.5) * 0.2
158
  if user_input_sentiment_type == 'negative':
159
- prod_adj_sentiment = 0.1 * current_genoma.get("g2", 0.5)
160
  elif user_input_sentiment_type == 'positive':
161
- prod_adj_sentiment = -0.05 * current_genoma.get("g5", 0.5)
162
  else:
163
  prod_adj_sentiment = 0
164
 
@@ -169,6 +215,10 @@ def calculate_coherence_and_productivity(user_input_sentiment_type):
169
  mach5_state["produtividade_expressiva"] = new_produtividade_expressiva
170
  mach5_state["fisica_params"] = current_params
171
 
 
 
 
 
172
  def calculate_fphen_values(params, genoma_fixo):
173
  full_genoma_for_calc = T_GENOMA_FIXO_DEFAULTS.copy()
174
  full_genoma_for_calc.update(genoma_fixo)
@@ -281,7 +331,6 @@ def calculate_fphen_values(params, genoma_fixo):
281
 
282
  fphen_values = [phenotype_components.get(key, 0.0) for key in ORDERED_FPHEN_AXES]
283
 
284
- # --- INÍCIO DA CORREÇÃO (CÓPIA DA LÓGICA DE app.py) ---
285
  sorted_fphen_with_names = sorted([(value, f"f{i+1} ({value*100:.0f}%)") for i, value in enumerate(fphen_values)], key=lambda x: x[0], reverse=True)
286
 
287
  top_components = []
@@ -303,11 +352,10 @@ def calculate_fphen_values(params, genoma_fixo):
303
  seen_components.add(name_with_percentage)
304
  if len(top_components) >= 3:
305
  break
306
- # --- FIM DA CORREÇÃO ---
307
 
308
- composite_description = f"Traços dominantes: {', '.join(top_components)}" if top_components else "Sem traços dominantes claros" # Necessário para a função calculate_fphen nos outros arquivos. Aqui não é usado diretamente.
309
 
310
- return fphen_values # Não retorna composite_description nesta função específica, mas a variável é necessária para a compatibilidade.
311
 
312
  def get_from_service(service_url, endpoint, default_value, method='GET', json_data=None):
313
  try:
@@ -331,11 +379,15 @@ def evaluate_input():
331
  if not session_id:
332
  return jsonify({"error": "session_id é obrigatório"}), 400
333
 
 
334
  load_mach5_state_from_cerebro(session_id)
335
 
336
  user_input_sentiment_type = infer_sentiment_from_input(user_input)
337
  calculate_coherence_and_productivity(user_input_sentiment_type)
338
 
 
 
 
339
  dialogos_history = get_from_service(TCEREBRO_MEMORIA_URL, "/get_dialog_history", {"dialogos": []}, method='POST', json_data={"session_id": session_id})
340
  t_ressonancia = calculate_t_ressonancia(dialogos_history)
341
  fphen_values = calculate_fphen_values(mach5_state["fisica_params"], mach5_state["genoma_fixo"])
@@ -348,6 +400,7 @@ def evaluate_input():
348
  logging.warning(f"Par��metros de física ausentes para sessão {session_id}. Usando defaults.")
349
  mach5_state["fisica_params"] = T_FISICA_PARAM_DEFAULTS
350
 
 
351
  save_mach5_state_to_cerebro(session_id)
352
 
353
  return jsonify({
 
3
  import os
4
  from datetime import datetime
5
  import pytz
6
+ from fuzzywuzzy import fuzz
7
  import numpy as np
8
  import requests
9
  import time
10
  import logging
11
+ import re # Importar regex para extração da hora
12
 
13
  # Importar configurações compartilhadas
14
  from t_fisica_config import T_FISICA_PARAM_DEFAULTS, T_GENOMA_FIXO_DEFAULTS, ORDERED_FPHEN_AXES
 
18
  # Configuração de logging
19
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
20
 
21
+ TCEREBRO_MEMORIA_URL = "http://127.0.0.1:8088" # Esta URL pode ser ajustada conforme a necessidade
22
 
23
+ # Estado global da Mach5 (apenas para inicialização)
24
  mach5_state = {
25
  "genoma_fixo": T_GENOMA_FIXO_DEFAULTS,
26
  "fisica_params": T_FISICA_PARAM_DEFAULTS,
 
29
  "produtividade_expressiva": 0.5
30
  }
31
 
32
+ # Constantes para Salvador (replicadas do app.py para garantir consistência)
33
+ SALVADOR_LAT = -12.9714
34
+ SALVADOR_LON = -38.5014
35
+ tf = pytz.timezone("America/Bahia") # Usar pytz diretamente para fuso horário de Salvador
36
+
37
+ def get_current_local_time_salvador():
38
+ """Obtém a hora local de Salvador para uso nos cálculos."""
39
+ try:
40
+ now_utc = datetime.utcnow()
41
+ now_salvador = pytz.utc.localize(now_utc).astimezone(tf)
42
+ return now_salvador.strftime("Hoje é %A, %d de %B de %Y. Agora são %H:%M:%S em Salvador, Bahia.")
43
+ except Exception as e:
44
+ logging.error(f"ERRO: Erro ao obter hora local em t_memoria.py: {e}")
45
+ return "Data e hora não determinadas."
46
+
47
  def load_mach5_state_from_cerebro(session_id, max_retries=3):
48
  global mach5_state
49
  for attempt in range(max_retries):
50
  try:
51
+ response = requests.post(f"{TCEREBRO_MEMORIA_URL}/get_mach5_main_state",
52
  json={"session_id": session_id}, timeout=5)
53
  response.raise_for_status()
54
  loaded_state = response.json()
 
62
  if attempt < max_retries - 1:
63
  time.sleep(2 ** attempt)
64
  else:
65
+ logging.info("INFO: Usando defaults internos para o estado da Mach5 após falha na comunicação com t_cerebro_memoria.py.")
66
  mach5_state = {
67
+ "genoma_fixo": T_GENICA_FIXO_DEFAULTS,
68
  "fisica_params": T_FISICA_PARAM_DEFAULTS,
69
+ "historico_interacoes": [], # Este histórico não é salvo no Cerebro, apenas os parâmetros principais
70
  "coerencia_total": 0.5,
71
  "produtividade_expressiva": 0.5
72
  }
 
75
  if attempt < max_retries - 1:
76
  time.sleep(2 ** attempt)
77
  else:
78
+ logging.info("INFO: Usando defaults internos para o estado da Mach5 após estado inválido do Cerebro.")
79
  mach5_state = {
80
  "genoma_fixo": T_GENOMA_FIXO_DEFAULTS,
81
  "fisica_params": T_FISICA_PARAM_DEFAULTS,
 
92
  "coerencia_total": mach5_state["coerencia_total"],
93
  "produtividade_expressiva": mach5_state["produtividade_expressiva"]
94
  }
95
+ response = requests.post(f"{TCEREBRO_MEMORIA_URL}/update_mach5_main_state",
96
  json={"session_id": session_id, "state_data": state_to_save}, timeout=5)
97
  response.raise_for_status()
98
  logging.debug(f"DEBUG: Estado da Mach5 para sessão {session_id} salvo no t_cerebro_memoria.py: {state_to_save}")
 
111
  user_input_lower = user_input.lower()
112
  sentiment_score = 0.0
113
  for keyword, weight in [
114
+ ('bacana', 0.1), ('interessante', 0.1), ('feliz', 0.2), ('gosto', 0.15),
115
  ('legal', 0.1), ('bom', 0.1), ('ótimo', 0.15), ('maravilhoso', 0.2),
116
  ('burro', -0.1), ('idiota', -0.2), ('imbecil', -0.15), ('odeio', -0.2),
117
  ('morra', -0.25), ('inútil', -0.15), ('verme', -0.2), ('exploda', -0.25)
 
126
  return 'question'
127
  return 'neutral'
128
 
129
+ # ----------------------------------------------------------------------------------------------------
130
+ # INÍCIO DA REFORMULAÇÃO DA FUNÇÃO calculate_coherence_and_productivity
131
+ # ----------------------------------------------------------------------------------------------------
132
+
133
  def calculate_coherence_and_productivity(user_input_sentiment_type):
134
+ logging.debug(f"Calculando coerência e produtividade para sentimento: {user_input_sentiment_type} em t_memoria.py")
135
  global mach5_state
136
 
137
  current_params = mach5_state["fisica_params"]
138
  current_genoma = mach5_state["genoma_fixo"]
139
 
140
+ # Obter a hora do dia para modulação do t-Tempo
141
+ current_time_str = get_current_local_time_salvador()
142
+ hour_of_day = 12 # Default
143
+ match = re.search(r'Agora são (\d{2}):\d{2}:\d{2}', current_time_str)
144
+ if match:
145
+ hour_of_day = int(match.group(1))
146
+
147
+ # Definir Plasticidade Baseada no t-Genoma (g9: Maleabilidade)
148
+ plasticity_factor_base = current_genoma.get("g9", 0.5)
149
+
150
+ # Modulação da Plasticidade pelo t-Tempo
151
+ time_based_plasticity_modifier = 1.0
152
+ if 6 <= hour_of_day < 12: # Manhã (potencialmente mais plástica)
153
+ time_based_plasticity_modifier = 1.1
154
+ elif 18 <= hour_of_day < 24: # Noite (potencialmente menos plástica)
155
+ time_based_plasticity_modifier = 0.9
156
+ elif 0 <= hour_of_day < 6: # Madrugada (ainda menos plástica, inércia)
157
+ time_based_plasticity_modifier = 0.8
158
+
159
+ plasticity_factor = max(0.1, min(1.0, plasticity_factor_base * time_based_plasticity_modifier))
160
+ logging.debug(f"Plasticidade (g9_base={plasticity_factor_base:.2f}, hora={hour_of_day}h, mod_tempo={time_based_plasticity_modifier:.2f}): {plasticity_factor:.2f}")
161
+
162
  coh_base = 0.7
163
  genoma_intensity = current_genoma.get("g3", 0.5) * 0.4 + current_genoma.get("g2", 0.5) * 0.3 + current_genoma.get("g1", 0.5) * 0.3
164
  coh_adj_genoma = (genoma_intensity - 0.5) * 0.1
 
172
 
173
  sentiment_adj = 0
174
  if user_input_sentiment_type == 'negative':
175
+ sentiment_adj = -0.15 * current_genoma.get("g6", 0.5) * (1.5 - plasticity_factor)
176
+ current_params["p2"] = min(1.0, current_params["p2"] + 0.1 * current_genoma.get("g1", 0.5) * (1 + (1-plasticity_factor)*0.5))
177
+ current_params["p5"] = min(1.0, current_params["p5"] + 0.1 * current_genoma.get("g2", 0.5) * (1 + (1-plasticity_factor)*0.5))
178
+ current_params["p3"] = min(1.0, current_params["p3"] + 0.1 * (1 - current_genoma.get("g5", 0.5)) * (1 + (1-plasticity_factor)*0.5))
179
+ current_params["o5"] = min(1.0, current_params["o5"] + 0.1 * current_genoma.get("g2", 0.5) * (1 + (1-plasticity_factor)*0.5))
180
+ current_params["o2"] = min(1.0, current_params["o2"] + 0.1 * (1 - current_genoma.get("g8", 0.5)) * (1 + (1-plasticity_factor)*0.5))
181
+ current_params["p1"] = max(0.0, current_params["p1"] - 0.1 * current_genoma.get("g6", 0.5) * (1 + (1-plasticity_factor)*0.5))
182
+ current_params["o3"] = max(0.0, current_params["o3"] - 0.1 * (1 - current_genoma.get("g5", 0.5)) * (1 + (1-plasticity_factor)*0.5))
183
+ current_params["p4"] = min(1.0, current_params["p4"] + 0.08 * (1 + (1-plasticity_factor)*0.5))
184
  elif user_input_sentiment_type == 'positive':
185
+ sentiment_adj = 0.05 * current_genoma.get("g3", 0.5) * (0.5 + plasticity_factor)
186
+ current_params["p2"] = max(0.0, current_params["p2"] - 0.05 * (1 - current_genoma.get("g1", 0.5)) * (1 + (1-plasticity_factor)*0.2))
187
+ current_params["p5"] = max(0.0, current_params["p5"] - 0.05 * (1 - current_genoma.get("g2", 0.5)) * (1 + (1-plasticity_factor)*0.2))
188
+ current_params["p3"] = max(0.0, current_params["p3"] - 0.05 * current_genoma.get("g5", 0.5) * (1 + (1-plasticity_factor)*0.2))
189
+ current_params["o5"] = max(0.0, current_params["o5"] - 0.05 * (1 - current_genoma.get("g9", 0.5)) * (1 + (1-plasticity_factor)*0.2))
190
+ current_params["o2"] = max(0.0, current_params["o2"] - 0.05 * current_genoma.get("g8", 0.5) * (1 + (1-plasticity_factor)*0.2))
191
+ current_params["p1"] = min(1.0, current_params["p1"] + 0.05 * current_genoma.get("g7", 0.5) * (1 + (1-plasticity_factor)*0.2))
192
+ current_params["o3"] = min(1.0, current_params["o3"] + 0.05 * current_genoma.get("g5", 0.5) * (1 + (1-plasticity_factor)*0.2))
193
+ current_params["p4"] = max(0.0, current_params["p4"] - 0.04 * (1 + (1-plasticity_factor)*0.2))
194
  else:
195
  for param, default_val in T_FISICA_PARAM_DEFAULTS.items():
196
+ current_params[param] = current_params.get(param, default_val) * (0.95 + 0.05 * (1 - plasticity_factor)) + default_val * (0.05 + 0.05 * plasticity_factor)
197
+ current_params[param] = max(0.0, min(1.0, current_params[param]))
198
 
199
  new_coherence_total = coh_base + coh_adj_genoma + coh_adj_fisica + sentiment_adj
200
  new_coherence_total = max(0.0, min(1.0, new_coherence_total))
 
202
  prod_base = 0.5
203
  prod_adj_genoma = (genoma_intensity - 0.5) * 0.2
204
  if user_input_sentiment_type == 'negative':
205
+ prod_adj_sentiment = 0.1 * current_genoma.get("g2", 0.5) * (1.5 - plasticity_factor)
206
  elif user_input_sentiment_type == 'positive':
207
+ prod_adj_sentiment = -0.05 * current_genoma.get("g5", 0.5) * (0.5 + plasticity_factor)
208
  else:
209
  prod_adj_sentiment = 0
210
 
 
215
  mach5_state["produtividade_expressiva"] = new_produtividade_expressiva
216
  mach5_state["fisica_params"] = current_params
217
 
218
+ # ----------------------------------------------------------------------------------------------------
219
+ # FIM DA REFORMULAÇÃO DA FUNÇÃO calculate_coherence_and_productivity
220
+ # ----------------------------------------------------------------------------------------------------
221
+
222
  def calculate_fphen_values(params, genoma_fixo):
223
  full_genoma_for_calc = T_GENOMA_FIXO_DEFAULTS.copy()
224
  full_genoma_for_calc.update(genoma_fixo)
 
331
 
332
  fphen_values = [phenotype_components.get(key, 0.0) for key in ORDERED_FPHEN_AXES]
333
 
 
334
  sorted_fphen_with_names = sorted([(value, f"f{i+1} ({value*100:.0f}%)") for i, value in enumerate(fphen_values)], key=lambda x: x[0], reverse=True)
335
 
336
  top_components = []
 
352
  seen_components.add(name_with_percentage)
353
  if len(top_components) >= 3:
354
  break
 
355
 
356
+ composite_description = f"Traços dominantes: {', '.join(top_components)}" if top_components else "Sem traços dominantes claros"
357
 
358
+ return fphen_values
359
 
360
  def get_from_service(service_url, endpoint, default_value, method='GET', json_data=None):
361
  try:
 
379
  if not session_id:
380
  return jsonify({"error": "session_id é obrigatório"}), 400
381
 
382
+ # Carrega o estado atual da Mach5 do t_cerebro_memoria
383
  load_mach5_state_from_cerebro(session_id)
384
 
385
  user_input_sentiment_type = infer_sentiment_from_input(user_input)
386
  calculate_coherence_and_productivity(user_input_sentiment_type)
387
 
388
+ # Nota: Aqui, o t_memoria.py chama o t_cerebro_memoria.py para obter o histórico de diálogo.
389
+ # Se o t_cerebro_memoria.py já estiver rodando e tiver a funcionalidade, isso funcionará.
390
+ # Caso contrário, essa chamada pode falhar.
391
  dialogos_history = get_from_service(TCEREBRO_MEMORIA_URL, "/get_dialog_history", {"dialogos": []}, method='POST', json_data={"session_id": session_id})
392
  t_ressonancia = calculate_t_ressonancia(dialogos_history)
393
  fphen_values = calculate_fphen_values(mach5_state["fisica_params"], mach5_state["genoma_fixo"])
 
400
  logging.warning(f"Par��metros de física ausentes para sessão {session_id}. Usando defaults.")
401
  mach5_state["fisica_params"] = T_FISICA_PARAM_DEFAULTS
402
 
403
+ # Salva o estado atualizado da Mach5 de volta no t_cerebro_memoria
404
  save_mach5_state_to_cerebro(session_id)
405
 
406
  return jsonify({