Spaces:
Running
Running
Update modules/treinamento.py
Browse files- modules/treinamento.py +199 -50
modules/treinamento.py
CHANGED
|
@@ -6,6 +6,7 @@
|
|
| 6 |
✅ Detecção de padrões de conversa
|
| 7 |
✅ Compatível com STT/TTS
|
| 8 |
✅ Otimizado para produção
|
|
|
|
| 9 |
"""
|
| 10 |
|
| 11 |
import json
|
|
@@ -54,7 +55,7 @@ class Treinamento:
|
|
| 54 |
logger.info(f"✅ Treinamento inicializado (intervalo: {interval_hours}h)")
|
| 55 |
|
| 56 |
# ========================================================================
|
| 57 |
-
# 📝 REGISTRO DE INTERAÇÕES (ADAPTADO AO INDEX.JS)
|
| 58 |
# ========================================================================
|
| 59 |
|
| 60 |
def registrar_interacao(
|
|
@@ -69,7 +70,8 @@ class Treinamento:
|
|
| 69 |
tipo_conversa: str = 'pv',
|
| 70 |
tipo_mensagem: str = 'texto',
|
| 71 |
reply_to_bot: bool = False,
|
| 72 |
-
reply_metadata: Optional[Dict] = None
|
|
|
|
| 73 |
):
|
| 74 |
"""
|
| 75 |
Registra interação para treinamento - TOTALMENTE COMPATÍVEL
|
|
@@ -86,6 +88,7 @@ class Treinamento:
|
|
| 86 |
tipo_mensagem: 'texto', 'audio', etc
|
| 87 |
reply_to_bot: Se é reply ao bot
|
| 88 |
reply_metadata: Metadata do reply (do index.js)
|
|
|
|
| 89 |
"""
|
| 90 |
try:
|
| 91 |
numero = str(numero).strip()
|
|
@@ -98,11 +101,14 @@ class Treinamento:
|
|
| 98 |
if reply_metadata and reply_metadata.get('reply_to_bot') is not None:
|
| 99 |
reply_to_bot = reply_metadata.get('reply_to_bot', False)
|
| 100 |
|
|
|
|
|
|
|
|
|
|
| 101 |
# Determina emoção e qualidade
|
| 102 |
emocao_detectada, confianca_emocao = self._detectar_emocao(mensagem)
|
| 103 |
qualidade = self._calcular_qualidade_resposta(mensagem, resposta, tipo_mensagem)
|
| 104 |
|
| 105 |
-
# Salva no banco usando método CORRETO
|
| 106 |
self.db.salvar_mensagem(
|
| 107 |
usuario=usuario,
|
| 108 |
mensagem=mensagem,
|
|
@@ -115,12 +121,25 @@ class Treinamento:
|
|
| 115 |
modo_resposta=contexto.get('modo_resposta', 'normal_ironico'),
|
| 116 |
emocao_detectada=emocao_detectada,
|
| 117 |
confianca_emocao=confianca_emocao,
|
|
|
|
|
|
|
| 118 |
tipo_mensagem=tipo_mensagem,
|
| 119 |
usuario_nome=usuario,
|
| 120 |
tipo_conversa=tipo_conversa,
|
| 121 |
reply_info_json=json.dumps(reply_metadata) if reply_metadata else None
|
| 122 |
)
|
| 123 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
# Adiciona ao dataset se qualidade boa
|
| 125 |
if qualidade >= QUALIDADE_MINIMA:
|
| 126 |
self._adicionar_ao_dataset(
|
|
@@ -136,16 +155,18 @@ class Treinamento:
|
|
| 136 |
tipo_conversa=tipo_conversa,
|
| 137 |
is_reply=is_reply,
|
| 138 |
reply_to_bot=reply_to_bot,
|
| 139 |
-
reply_metadata=reply_metadata
|
|
|
|
| 140 |
)
|
| 141 |
|
| 142 |
-
# Salva exemplo de treinamento
|
| 143 |
if tipo_mensagem == 'texto' and len(resposta) > 10:
|
| 144 |
self.db.salvar_training_example(
|
| 145 |
input_text=mensagem,
|
| 146 |
output_text=resposta,
|
| 147 |
humor=contexto.get('humor_atualizado', 'normal_ironico'),
|
| 148 |
modo_resposta=contexto.get('modo_resposta', 'normal_ironico'),
|
|
|
|
| 149 |
emocao_contexto=emocao_detectada,
|
| 150 |
qualidade_score=qualidade,
|
| 151 |
contexto_super_claro={
|
|
@@ -153,10 +174,26 @@ class Treinamento:
|
|
| 153 |
'reply_to_bot': reply_to_bot,
|
| 154 |
'tipo_conversa': tipo_conversa,
|
| 155 |
'tipo_mensagem': tipo_mensagem,
|
| 156 |
-
'reply_metadata': reply_metadata
|
|
|
|
|
|
|
| 157 |
}
|
| 158 |
)
|
| 159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
# Analisa padrões
|
| 161 |
self._analisar_padroes_usuario(
|
| 162 |
numero=numero,
|
|
@@ -168,10 +205,11 @@ class Treinamento:
|
|
| 168 |
tipo_conversa=tipo_conversa,
|
| 169 |
is_reply=is_reply,
|
| 170 |
reply_to_bot=reply_to_bot,
|
| 171 |
-
reply_metadata=reply_metadata
|
|
|
|
| 172 |
)
|
| 173 |
|
| 174 |
-
logger.debug(f"✅ Interação registrada: {usuario[:10]} |
|
| 175 |
|
| 176 |
except Exception as e:
|
| 177 |
logger.error(f"❌ Erro ao registrar interação: {e}")
|
|
@@ -258,7 +296,7 @@ class Treinamento:
|
|
| 258 |
return round(qualidade, 2)
|
| 259 |
|
| 260 |
# ========================================================================
|
| 261 |
-
# 💾 ADICIONAR AO DATASET
|
| 262 |
# ========================================================================
|
| 263 |
|
| 264 |
def _adicionar_ao_dataset(
|
|
@@ -275,10 +313,11 @@ class Treinamento:
|
|
| 275 |
tipo_conversa: str,
|
| 276 |
is_reply: bool,
|
| 277 |
reply_to_bot: bool,
|
| 278 |
-
reply_metadata: Optional[Dict] = None
|
|
|
|
| 279 |
):
|
| 280 |
"""
|
| 281 |
-
Adiciona exemplo ao dataset de treinamento
|
| 282 |
|
| 283 |
Args:
|
| 284 |
mensagem: Mensagem do usuário
|
|
@@ -294,6 +333,7 @@ class Treinamento:
|
|
| 294 |
is_reply: Se é reply
|
| 295 |
reply_to_bot: Se é reply ao bot
|
| 296 |
reply_metadata: Metadata do reply
|
|
|
|
| 297 |
"""
|
| 298 |
try:
|
| 299 |
humor = contexto.get("humor_atualizado", "normal_ironico")
|
|
@@ -312,12 +352,13 @@ class Treinamento:
|
|
| 312 |
if modo == "casual_amigavel":
|
| 313 |
modo = "normal_ironico"
|
| 314 |
|
| 315 |
-
# Prepara metadados com reply_metadata
|
| 316 |
metadata = {
|
| 317 |
"usuario": usuario[:20],
|
| 318 |
"numero_hash": hashlib.md5(numero.encode()).hexdigest()[:8],
|
| 319 |
"humor": humor,
|
| 320 |
"modo_resposta": modo,
|
|
|
|
| 321 |
"emocao_detectada": emocao_detectada,
|
| 322 |
"confianca_emocao": confianca_emocao,
|
| 323 |
"qualidade_score": qualidade,
|
|
@@ -337,6 +378,15 @@ class Treinamento:
|
|
| 337 |
"reply_metadata_context": reply_metadata.get('context_hint', '')
|
| 338 |
})
|
| 339 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 340 |
entry = {
|
| 341 |
"input": mensagem.strip(),
|
| 342 |
"output": resposta.strip(),
|
|
@@ -369,13 +419,13 @@ class Treinamento:
|
|
| 369 |
with open(DATASET_PATH, "w", encoding="utf-8") as f:
|
| 370 |
json.dump(dataset, f, ensure_ascii=False, indent=2)
|
| 371 |
|
| 372 |
-
logger.debug(f"✅ Exemplo adicionado ao dataset | qualidade: {qualidade:.2f}")
|
| 373 |
|
| 374 |
except Exception as e:
|
| 375 |
logger.warning(f"⚠️ Erro ao adicionar ao dataset: {e}")
|
| 376 |
|
| 377 |
# ========================================================================
|
| 378 |
-
# 🔍 ANÁLISE DE PADRÕES
|
| 379 |
# ========================================================================
|
| 380 |
|
| 381 |
def _analisar_padroes_usuario(
|
|
@@ -389,10 +439,11 @@ class Treinamento:
|
|
| 389 |
tipo_conversa: str,
|
| 390 |
is_reply: bool,
|
| 391 |
reply_to_bot: bool,
|
| 392 |
-
reply_metadata: Optional[Dict] = None
|
|
|
|
| 393 |
):
|
| 394 |
"""
|
| 395 |
-
Analisa padrões de comunicação do usuário
|
| 396 |
|
| 397 |
Args:
|
| 398 |
numero: Número do usuário
|
|
@@ -405,6 +456,7 @@ class Treinamento:
|
|
| 405 |
is_reply: Se é reply
|
| 406 |
reply_to_bot: Se é reply ao bot
|
| 407 |
reply_metadata: Metadata do reply
|
|
|
|
| 408 |
"""
|
| 409 |
try:
|
| 410 |
# 1. REGISTRAR TOM
|
|
@@ -425,22 +477,25 @@ class Treinamento:
|
|
| 425 |
except Exception as e:
|
| 426 |
logger.warning(f"Erro ao salvar gíria: {e}")
|
| 427 |
|
| 428 |
-
# 3. REGISTRAR HUMOR
|
| 429 |
if "humor_atualizado" in contexto:
|
| 430 |
humor = contexto["humor_atualizado"]
|
| 431 |
humor_atual = self.db.recuperar_humor_atual(numero)
|
| 432 |
-
|
|
|
|
|
|
|
| 433 |
self.db.salvar_transicao_humor(
|
| 434 |
numero=numero,
|
| 435 |
humor_anterior=humor_atual,
|
| 436 |
humor_novo=humor,
|
|
|
|
|
|
|
| 437 |
emocao_trigger=emocao_detectada,
|
| 438 |
confianca_emocao=contexto.get('confianca_emocao', 0.5),
|
| 439 |
-
|
| 440 |
-
razao=f"Interação {tipo_conversa}"
|
| 441 |
)
|
| 442 |
|
| 443 |
-
# 4. APRENDER PADRÕES DE REPLY
|
| 444 |
if is_reply:
|
| 445 |
self._aprender_padrao_reply(
|
| 446 |
numero=numero,
|
|
@@ -449,7 +504,18 @@ class Treinamento:
|
|
| 449 |
resposta=resposta,
|
| 450 |
reply_to_bot=reply_to_bot,
|
| 451 |
tipo_conversa=tipo_conversa,
|
| 452 |
-
reply_metadata=reply_metadata
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 453 |
)
|
| 454 |
|
| 455 |
except Exception as e:
|
|
@@ -525,10 +591,11 @@ class Treinamento:
|
|
| 525 |
resposta: str,
|
| 526 |
reply_to_bot: bool,
|
| 527 |
tipo_conversa: str,
|
| 528 |
-
reply_metadata: Optional[Dict] = None
|
|
|
|
| 529 |
):
|
| 530 |
"""
|
| 531 |
-
Aprende padrões de reply
|
| 532 |
|
| 533 |
Args:
|
| 534 |
numero: Número do usuário
|
|
@@ -538,6 +605,7 @@ class Treinamento:
|
|
| 538 |
reply_to_bot: Se é reply ao bot
|
| 539 |
tipo_conversa: Tipo da conversa
|
| 540 |
reply_metadata: Metadata do reply
|
|
|
|
| 541 |
"""
|
| 542 |
try:
|
| 543 |
# Define padrão com base no reply_metadata
|
|
@@ -561,10 +629,13 @@ class Treinamento:
|
|
| 561 |
tipo = "conversa_alheia"
|
| 562 |
contexto_extra = ""
|
| 563 |
|
|
|
|
|
|
|
|
|
|
| 564 |
# Prepara texto com contexto
|
| 565 |
-
input_text_com_contexto = f"[CONTEXTO: {padrao.upper()}] {contexto_extra} {mensagem}"
|
| 566 |
|
| 567 |
-
# Salva aprendizado
|
| 568 |
self.db.salvar_aprendizado_detalhado(
|
| 569 |
input_text=input_text_com_contexto,
|
| 570 |
output_text=resposta,
|
|
@@ -575,17 +646,64 @@ class Treinamento:
|
|
| 575 |
'reply_to_bot': reply_to_bot,
|
| 576 |
'tipo_conversa': tipo_conversa,
|
| 577 |
'tipo': tipo,
|
| 578 |
-
'reply_metadata': reply_metadata
|
|
|
|
| 579 |
},
|
| 580 |
qualidade_score=0.8,
|
| 581 |
-
tipo_aprendizado=f"reply_{tipo}"
|
| 582 |
)
|
| 583 |
|
| 584 |
-
logger.debug(f"
|
| 585 |
|
| 586 |
except Exception as e:
|
| 587 |
logger.warning(f"⚠️ Erro ao aprender padrão de reply: {e}")
|
| 588 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 589 |
# ========================================================================
|
| 590 |
# 🔄 TREINAMENTO PERIÓDICO
|
| 591 |
# ========================================================================
|
|
@@ -636,7 +754,7 @@ class Treinamento:
|
|
| 636 |
logger.warning("⚠️ Nenhum exemplo com qualidade suficiente")
|
| 637 |
return
|
| 638 |
|
| 639 |
-
# Gera arquivo JSONL
|
| 640 |
with open("training_dataset_akira_v21.jsonl", "w", encoding="utf-8") as f:
|
| 641 |
for ex in exemplos[:500]:
|
| 642 |
if ex.get("score", 0) >= 0.7:
|
|
@@ -645,6 +763,7 @@ class Treinamento:
|
|
| 645 |
"output": ex.get("output", ""),
|
| 646 |
"humor": ex.get("humor", "normal_ironico"),
|
| 647 |
"modo": ex.get("modo", "normal_ironico"),
|
|
|
|
| 648 |
"metadata": {
|
| 649 |
"score": ex.get("score", 0.5),
|
| 650 |
"timestamp": time.time(),
|
|
@@ -652,7 +771,7 @@ class Treinamento:
|
|
| 652 |
}
|
| 653 |
}, ensure_ascii=False) + "\n")
|
| 654 |
|
| 655 |
-
logger.info(f"✅ Dataset gerado: {len(exemplos)} exemplos")
|
| 656 |
self.db.marcar_examples_como_usados()
|
| 657 |
|
| 658 |
except Exception as e:
|
|
@@ -667,7 +786,7 @@ class Treinamento:
|
|
| 667 |
with open(DATASET_PATH, "r", encoding="utf-8") as f:
|
| 668 |
dataset = json.load(f)
|
| 669 |
|
| 670 |
-
# Análise estatística
|
| 671 |
padroes = {
|
| 672 |
"total": len(dataset),
|
| 673 |
"reply_to_bot": 0,
|
|
@@ -676,7 +795,11 @@ class Treinamento:
|
|
| 676 |
"grupo": 0,
|
| 677 |
"pv": 0,
|
| 678 |
"audio": 0,
|
| 679 |
-
"texto": 0
|
|
|
|
|
|
|
|
|
|
|
|
|
| 680 |
}
|
| 681 |
|
| 682 |
for e in dataset:
|
|
@@ -698,6 +821,17 @@ class Treinamento:
|
|
| 698 |
padroes["audio"] += 1
|
| 699 |
else:
|
| 700 |
padroes["texto"] += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 701 |
|
| 702 |
# Log estatísticas
|
| 703 |
logger.info(f"📊 Estatísticas do dataset:")
|
|
@@ -707,6 +841,7 @@ class Treinamento:
|
|
| 707 |
logger.info(f" Com reply_metadata: {padroes['reply_with_metadata']}")
|
| 708 |
logger.info(f" Grupo: {padroes['grupo']} | PV: {padroes['pv']}")
|
| 709 |
logger.info(f" Áudio: {padroes['audio']} | Texto: {padroes['texto']}")
|
|
|
|
| 710 |
|
| 711 |
except Exception as e:
|
| 712 |
logger.error(f"❌ Erro na análise global: {e}")
|
|
@@ -721,12 +856,12 @@ class Treinamento:
|
|
| 721 |
logger.warning(f"⚠️ Erro na otimização: {e}")
|
| 722 |
|
| 723 |
# ========================================================================
|
| 724 |
-
# 🔧 FUNÇÃO PARA USO DIRETO DA API
|
| 725 |
# ========================================================================
|
| 726 |
|
| 727 |
def processar_interacao_api(self, payload: Dict, resposta: str) -> Dict:
|
| 728 |
"""
|
| 729 |
-
Processa interação da API para treinamento
|
| 730 |
|
| 731 |
Args:
|
| 732 |
payload: Payload da requisição
|
|
@@ -753,10 +888,11 @@ class Treinamento:
|
|
| 753 |
|
| 754 |
is_reply = bool(payload.get('mensagem_citada')) or bool(reply_metadata)
|
| 755 |
|
| 756 |
-
# Contexto da análise
|
| 757 |
contexto_analise = payload.get('analise', {})
|
|
|
|
| 758 |
|
| 759 |
-
# Registra interação
|
| 760 |
self.registrar_interacao(
|
| 761 |
usuario=usuario,
|
| 762 |
mensagem=mensagem,
|
|
@@ -768,13 +904,15 @@ class Treinamento:
|
|
| 768 |
tipo_conversa=tipo_conversa,
|
| 769 |
tipo_mensagem=tipo_mensagem,
|
| 770 |
reply_to_bot=reply_to_bot,
|
| 771 |
-
reply_metadata=reply_metadata
|
|
|
|
| 772 |
)
|
| 773 |
|
| 774 |
return {
|
| 775 |
'status': 'success',
|
| 776 |
'message': 'Interação registrada',
|
| 777 |
'usuario': usuario,
|
|
|
|
| 778 |
'timestamp': time.time()
|
| 779 |
}
|
| 780 |
|
|
@@ -809,7 +947,7 @@ def get_treinamento_instance(db: Database = None):
|
|
| 809 |
return _treinamento_instance
|
| 810 |
|
| 811 |
# ============================================================================
|
| 812 |
-
# 🎯 FUNÇÃO DE INTEGRAÇÃO RÁPIDA
|
| 813 |
# ============================================================================
|
| 814 |
def registrar_interacao_rapida(
|
| 815 |
usuario: str,
|
|
@@ -821,10 +959,11 @@ def registrar_interacao_rapida(
|
|
| 821 |
tipo_conversa: str = 'pv',
|
| 822 |
tipo_mensagem: str = 'texto',
|
| 823 |
contexto: Dict = None,
|
| 824 |
-
reply_metadata: Optional[Dict] = None
|
|
|
|
| 825 |
) -> bool:
|
| 826 |
"""
|
| 827 |
-
Registra interação rapidamente
|
| 828 |
|
| 829 |
Args:
|
| 830 |
usuario: Nome do usuário
|
|
@@ -837,6 +976,7 @@ def registrar_interacao_rapida(
|
|
| 837 |
tipo_mensagem: Tipo da mensagem
|
| 838 |
contexto: Contexto da conversa
|
| 839 |
reply_metadata: Metadata do reply
|
|
|
|
| 840 |
|
| 841 |
Returns:
|
| 842 |
True se sucesso, False caso contrário
|
|
@@ -853,9 +993,10 @@ def registrar_interacao_rapida(
|
|
| 853 |
tipo_conversa=tipo_conversa,
|
| 854 |
tipo_mensagem=tipo_mensagem,
|
| 855 |
contexto=contexto,
|
| 856 |
-
reply_metadata=reply_metadata
|
|
|
|
| 857 |
)
|
| 858 |
-
logger.debug(f"✅ Interação rápida registrada: {usuario[:10]}")
|
| 859 |
return True
|
| 860 |
except Exception as e:
|
| 861 |
logger.error(f"❌ Erro no registro rápido: {e}")
|
|
@@ -866,7 +1007,7 @@ def registrar_interacao_rapida(
|
|
| 866 |
# ============================================================================
|
| 867 |
if __name__ == "__main__":
|
| 868 |
print("=" * 80)
|
| 869 |
-
print("TESTANDO TREINAMENTO.PY -
|
| 870 |
print("=" * 80)
|
| 871 |
|
| 872 |
from .database import Database
|
|
@@ -876,7 +1017,7 @@ if __name__ == "__main__":
|
|
| 876 |
db = Database(":memory:")
|
| 877 |
treinamento = Treinamento(db)
|
| 878 |
|
| 879 |
-
# Simula payload do api.py com reply_metadata
|
| 880 |
payload_teste = {
|
| 881 |
"usuario": "Isaac Teste",
|
| 882 |
"numero": "244978787009",
|
|
@@ -891,20 +1032,27 @@ if __name__ == "__main__":
|
|
| 891 |
},
|
| 892 |
"analise": {
|
| 893 |
"humor_atualizado": "normal_ironico",
|
| 894 |
-
"modo_resposta": "normal_ironico"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 895 |
}
|
| 896 |
}
|
| 897 |
|
| 898 |
resposta_teste = "Tudo e tu, puto?"
|
| 899 |
|
| 900 |
-
# Processa interação
|
| 901 |
resultado = treinamento.processar_interacao_api(payload_teste, resposta_teste)
|
| 902 |
|
| 903 |
print(f"✅ Teste OK: {resultado}")
|
| 904 |
print(f"📝 Mensagem: {payload_teste['mensagem']}")
|
| 905 |
print(f"💬 Resposta: {resposta_teste}")
|
|
|
|
| 906 |
|
| 907 |
-
# Teste com registro rápido
|
| 908 |
sucesso = registrar_interacao_rapida(
|
| 909 |
usuario="Teste 2",
|
| 910 |
numero="244000000000",
|
|
@@ -912,7 +1060,8 @@ if __name__ == "__main__":
|
|
| 912 |
resposta="Nada, cota.",
|
| 913 |
is_reply=True,
|
| 914 |
reply_to_bot=True,
|
| 915 |
-
reply_metadata={"quoted_author_name": "Akira", "is_reply": True}
|
|
|
|
| 916 |
)
|
| 917 |
|
| 918 |
print(f"✅ Registro rápido: {'Sucesso' if sucesso else 'Falhou'}")
|
|
@@ -923,5 +1072,5 @@ if __name__ == "__main__":
|
|
| 923 |
traceback.print_exc()
|
| 924 |
|
| 925 |
print("\n" + "=" * 80)
|
| 926 |
-
print("TREINAMENTO.PY - COMPLETO
|
| 927 |
print("=" * 80)
|
|
|
|
| 6 |
✅ Detecção de padrões de conversa
|
| 7 |
✅ Compatível com STT/TTS
|
| 8 |
✅ Otimizado para produção
|
| 9 |
+
✅ CORREÇÃO: Suporte para nivel_transicao adicionado
|
| 10 |
"""
|
| 11 |
|
| 12 |
import json
|
|
|
|
| 55 |
logger.info(f"✅ Treinamento inicializado (intervalo: {interval_hours}h)")
|
| 56 |
|
| 57 |
# ========================================================================
|
| 58 |
+
# 📝 REGISTRO DE INTERAÇÕES (ADAPTADO AO INDEX.JS) - CORRIGIDO
|
| 59 |
# ========================================================================
|
| 60 |
|
| 61 |
def registrar_interacao(
|
|
|
|
| 70 |
tipo_conversa: str = 'pv',
|
| 71 |
tipo_mensagem: str = 'texto',
|
| 72 |
reply_to_bot: bool = False,
|
| 73 |
+
reply_metadata: Optional[Dict] = None,
|
| 74 |
+
nivel_transicao: int = 0 # NOVO PARÂMETRO ADICIONADO
|
| 75 |
):
|
| 76 |
"""
|
| 77 |
Registra interação para treinamento - TOTALMENTE COMPATÍVEL
|
|
|
|
| 88 |
tipo_mensagem: 'texto', 'audio', etc
|
| 89 |
reply_to_bot: Se é reply ao bot
|
| 90 |
reply_metadata: Metadata do reply (do index.js)
|
| 91 |
+
nivel_transicao: Nível de transição do usuário privilegiado
|
| 92 |
"""
|
| 93 |
try:
|
| 94 |
numero = str(numero).strip()
|
|
|
|
| 101 |
if reply_metadata and reply_metadata.get('reply_to_bot') is not None:
|
| 102 |
reply_to_bot = reply_metadata.get('reply_to_bot', False)
|
| 103 |
|
| 104 |
+
# Extrai info_transicao do contexto
|
| 105 |
+
info_transicao = contexto.get('info_transicao', {})
|
| 106 |
+
|
| 107 |
# Determina emoção e qualidade
|
| 108 |
emocao_detectada, confianca_emocao = self._detectar_emocao(mensagem)
|
| 109 |
qualidade = self._calcular_qualidade_resposta(mensagem, resposta, tipo_mensagem)
|
| 110 |
|
| 111 |
+
# Salva no banco usando método CORRETO com nivel_transicao
|
| 112 |
self.db.salvar_mensagem(
|
| 113 |
usuario=usuario,
|
| 114 |
mensagem=mensagem,
|
|
|
|
| 121 |
modo_resposta=contexto.get('modo_resposta', 'normal_ironico'),
|
| 122 |
emocao_detectada=emocao_detectada,
|
| 123 |
confianca_emocao=confianca_emocao,
|
| 124 |
+
nivel_transicao=nivel_transicao, # PARÂMETRO ADICIONADO
|
| 125 |
+
info_transicao=info_transicao, # INFO DE TRANSIÇÃO
|
| 126 |
tipo_mensagem=tipo_mensagem,
|
| 127 |
usuario_nome=usuario,
|
| 128 |
tipo_conversa=tipo_conversa,
|
| 129 |
reply_info_json=json.dumps(reply_metadata) if reply_metadata else None
|
| 130 |
)
|
| 131 |
|
| 132 |
+
# Atualiza contexto com nivel_transicao
|
| 133 |
+
self.db.atualizar_contexto(
|
| 134 |
+
numero=numero,
|
| 135 |
+
humor_atual=contexto.get('humor_atualizado', 'normal_ironico'),
|
| 136 |
+
modo_resposta=contexto.get('modo_resposta', 'normal_ironico'),
|
| 137 |
+
nivel_transicao=nivel_transicao,
|
| 138 |
+
info_transicao=info_transicao,
|
| 139 |
+
tom=contexto.get('tom', 'normal'),
|
| 140 |
+
emocao_tendencia=emocao_detectada
|
| 141 |
+
)
|
| 142 |
+
|
| 143 |
# Adiciona ao dataset se qualidade boa
|
| 144 |
if qualidade >= QUALIDADE_MINIMA:
|
| 145 |
self._adicionar_ao_dataset(
|
|
|
|
| 155 |
tipo_conversa=tipo_conversa,
|
| 156 |
is_reply=is_reply,
|
| 157 |
reply_to_bot=reply_to_bot,
|
| 158 |
+
reply_metadata=reply_metadata,
|
| 159 |
+
nivel_transicao=nivel_transicao # ADICIONADO
|
| 160 |
)
|
| 161 |
|
| 162 |
+
# Salva exemplo de treinamento com nivel_transicao
|
| 163 |
if tipo_mensagem == 'texto' and len(resposta) > 10:
|
| 164 |
self.db.salvar_training_example(
|
| 165 |
input_text=mensagem,
|
| 166 |
output_text=resposta,
|
| 167 |
humor=contexto.get('humor_atualizado', 'normal_ironico'),
|
| 168 |
modo_resposta=contexto.get('modo_resposta', 'normal_ironico'),
|
| 169 |
+
nivel_transicao=nivel_transicao, # ADICIONADO
|
| 170 |
emocao_contexto=emocao_detectada,
|
| 171 |
qualidade_score=qualidade,
|
| 172 |
contexto_super_claro={
|
|
|
|
| 174 |
'reply_to_bot': reply_to_bot,
|
| 175 |
'tipo_conversa': tipo_conversa,
|
| 176 |
'tipo_mensagem': tipo_mensagem,
|
| 177 |
+
'reply_metadata': reply_metadata,
|
| 178 |
+
'nivel_transicao': nivel_transicao,
|
| 179 |
+
'info_transicao': info_transicao
|
| 180 |
}
|
| 181 |
)
|
| 182 |
|
| 183 |
+
# Registra interação para treinamento
|
| 184 |
+
self.db.registrar_interacao(
|
| 185 |
+
numero=numero,
|
| 186 |
+
mensagem=mensagem,
|
| 187 |
+
resposta=resposta,
|
| 188 |
+
humor=contexto.get('humor_atualizado', 'normal_ironico'),
|
| 189 |
+
modo_resposta=contexto.get('modo_resposta', 'normal_ironico'),
|
| 190 |
+
nivel_transicao=nivel_transicao, # PARÂMETRO ADICIONADO
|
| 191 |
+
emocao_detectada=emocao_detectada,
|
| 192 |
+
tipo_conversa=tipo_conversa,
|
| 193 |
+
reply_info_json=json.dumps(reply_metadata) if reply_metadata else None,
|
| 194 |
+
qualidade_score=qualidade
|
| 195 |
+
)
|
| 196 |
+
|
| 197 |
# Analisa padrões
|
| 198 |
self._analisar_padroes_usuario(
|
| 199 |
numero=numero,
|
|
|
|
| 205 |
tipo_conversa=tipo_conversa,
|
| 206 |
is_reply=is_reply,
|
| 207 |
reply_to_bot=reply_to_bot,
|
| 208 |
+
reply_metadata=reply_metadata,
|
| 209 |
+
nivel_transicao=nivel_transicao # ADICIONADO
|
| 210 |
)
|
| 211 |
|
| 212 |
+
logger.debug(f"✅ Interação registrada: {usuario[:10]} | Nível: {nivel_transicao} | reply: {is_reply}")
|
| 213 |
|
| 214 |
except Exception as e:
|
| 215 |
logger.error(f"❌ Erro ao registrar interação: {e}")
|
|
|
|
| 296 |
return round(qualidade, 2)
|
| 297 |
|
| 298 |
# ========================================================================
|
| 299 |
+
# 💾 ADICIONAR AO DATASET (ATUALIZADO)
|
| 300 |
# ========================================================================
|
| 301 |
|
| 302 |
def _adicionar_ao_dataset(
|
|
|
|
| 313 |
tipo_conversa: str,
|
| 314 |
is_reply: bool,
|
| 315 |
reply_to_bot: bool,
|
| 316 |
+
reply_metadata: Optional[Dict] = None,
|
| 317 |
+
nivel_transicao: int = 0 # NOVO PARÂMETRO
|
| 318 |
):
|
| 319 |
"""
|
| 320 |
+
Adiciona exemplo ao dataset de treinamento - ATUALIZADO
|
| 321 |
|
| 322 |
Args:
|
| 323 |
mensagem: Mensagem do usuário
|
|
|
|
| 333 |
is_reply: Se é reply
|
| 334 |
reply_to_bot: Se é reply ao bot
|
| 335 |
reply_metadata: Metadata do reply
|
| 336 |
+
nivel_transicao: Nível de transição do usuário
|
| 337 |
"""
|
| 338 |
try:
|
| 339 |
humor = contexto.get("humor_atualizado", "normal_ironico")
|
|
|
|
| 352 |
if modo == "casual_amigavel":
|
| 353 |
modo = "normal_ironico"
|
| 354 |
|
| 355 |
+
# Prepara metadados com reply_metadata e nivel_transicao
|
| 356 |
metadata = {
|
| 357 |
"usuario": usuario[:20],
|
| 358 |
"numero_hash": hashlib.md5(numero.encode()).hexdigest()[:8],
|
| 359 |
"humor": humor,
|
| 360 |
"modo_resposta": modo,
|
| 361 |
+
"nivel_transicao": nivel_transicao, # ADICIONADO
|
| 362 |
"emocao_detectada": emocao_detectada,
|
| 363 |
"confianca_emocao": confianca_emocao,
|
| 364 |
"qualidade_score": qualidade,
|
|
|
|
| 378 |
"reply_metadata_context": reply_metadata.get('context_hint', '')
|
| 379 |
})
|
| 380 |
|
| 381 |
+
# Adiciona info_transicao se disponível
|
| 382 |
+
info_transicao = contexto.get('info_transicao', {})
|
| 383 |
+
if info_transicao:
|
| 384 |
+
metadata.update({
|
| 385 |
+
"info_transicao_desc": info_transicao.get('desc', ''),
|
| 386 |
+
"info_transicao_modo": info_transicao.get('modo', ''),
|
| 387 |
+
"info_transicao_deve_transicionar": info_transicao.get('deve_transicionar', False)
|
| 388 |
+
})
|
| 389 |
+
|
| 390 |
entry = {
|
| 391 |
"input": mensagem.strip(),
|
| 392 |
"output": resposta.strip(),
|
|
|
|
| 419 |
with open(DATASET_PATH, "w", encoding="utf-8") as f:
|
| 420 |
json.dump(dataset, f, ensure_ascii=False, indent=2)
|
| 421 |
|
| 422 |
+
logger.debug(f"✅ Exemplo adicionado ao dataset | nível: {nivel_transicao} | qualidade: {qualidade:.2f}")
|
| 423 |
|
| 424 |
except Exception as e:
|
| 425 |
logger.warning(f"⚠️ Erro ao adicionar ao dataset: {e}")
|
| 426 |
|
| 427 |
# ========================================================================
|
| 428 |
+
# 🔍 ANÁLISE DE PADRÕES (ATUALIZADA)
|
| 429 |
# ========================================================================
|
| 430 |
|
| 431 |
def _analisar_padroes_usuario(
|
|
|
|
| 439 |
tipo_conversa: str,
|
| 440 |
is_reply: bool,
|
| 441 |
reply_to_bot: bool,
|
| 442 |
+
reply_metadata: Optional[Dict] = None,
|
| 443 |
+
nivel_transicao: int = 0 # NOVO PARÂMETRO
|
| 444 |
):
|
| 445 |
"""
|
| 446 |
+
Analisa padrões de comunicação do usuário - ATUALIZADA
|
| 447 |
|
| 448 |
Args:
|
| 449 |
numero: Número do usuário
|
|
|
|
| 456 |
is_reply: Se é reply
|
| 457 |
reply_to_bot: Se é reply ao bot
|
| 458 |
reply_metadata: Metadata do reply
|
| 459 |
+
nivel_transicao: Nível de transição do usuário
|
| 460 |
"""
|
| 461 |
try:
|
| 462 |
# 1. REGISTRAR TOM
|
|
|
|
| 477 |
except Exception as e:
|
| 478 |
logger.warning(f"Erro ao salvar gíria: {e}")
|
| 479 |
|
| 480 |
+
# 3. REGISTRAR TRANSIÇÃO DE HUMOR COM nivel_transicao
|
| 481 |
if "humor_atualizado" in contexto:
|
| 482 |
humor = contexto["humor_atualizado"]
|
| 483 |
humor_atual = self.db.recuperar_humor_atual(numero)
|
| 484 |
+
nivel_atual = self.db.recuperar_nivel_transicao(numero)
|
| 485 |
+
|
| 486 |
+
if humor != humor_atual or nivel_transicao != nivel_atual:
|
| 487 |
self.db.salvar_transicao_humor(
|
| 488 |
numero=numero,
|
| 489 |
humor_anterior=humor_atual,
|
| 490 |
humor_novo=humor,
|
| 491 |
+
nivel_transicao_anterior=nivel_atual,
|
| 492 |
+
nivel_transicao_novo=nivel_transicao,
|
| 493 |
emocao_trigger=emocao_detectada,
|
| 494 |
confianca_emocao=contexto.get('confianca_emocao', 0.5),
|
| 495 |
+
razao=f"Transição nível {nivel_atual}→{nivel_transicao} | {tipo_conversa}"
|
|
|
|
| 496 |
)
|
| 497 |
|
| 498 |
+
# 4. APRENDER PADRÕES DE REPLY COM nivel_transicao
|
| 499 |
if is_reply:
|
| 500 |
self._aprender_padrao_reply(
|
| 501 |
numero=numero,
|
|
|
|
| 504 |
resposta=resposta,
|
| 505 |
reply_to_bot=reply_to_bot,
|
| 506 |
tipo_conversa=tipo_conversa,
|
| 507 |
+
reply_metadata=reply_metadata,
|
| 508 |
+
nivel_transicao=nivel_transicao # ADICIONADO
|
| 509 |
+
)
|
| 510 |
+
|
| 511 |
+
# 5. ANALISAR TRANSIÇÕES DE USUÁRIOS PRIVILEGIADOS
|
| 512 |
+
if nivel_transicao > 0:
|
| 513 |
+
self._analisar_transicao_privilegiado(
|
| 514 |
+
numero=numero,
|
| 515 |
+
usuario=usuario,
|
| 516 |
+
nivel_transicao=nivel_transicao,
|
| 517 |
+
mensagem=mensagem,
|
| 518 |
+
contexto=contexto
|
| 519 |
)
|
| 520 |
|
| 521 |
except Exception as e:
|
|
|
|
| 591 |
resposta: str,
|
| 592 |
reply_to_bot: bool,
|
| 593 |
tipo_conversa: str,
|
| 594 |
+
reply_metadata: Optional[Dict] = None,
|
| 595 |
+
nivel_transicao: int = 0 # NOVO PARÂMETRO
|
| 596 |
):
|
| 597 |
"""
|
| 598 |
+
Aprende padrões de reply - ATUALIZADO
|
| 599 |
|
| 600 |
Args:
|
| 601 |
numero: Número do usuário
|
|
|
|
| 605 |
reply_to_bot: Se é reply ao bot
|
| 606 |
tipo_conversa: Tipo da conversa
|
| 607 |
reply_metadata: Metadata do reply
|
| 608 |
+
nivel_transicao: Nível de transição do usuário
|
| 609 |
"""
|
| 610 |
try:
|
| 611 |
# Define padrão com base no reply_metadata
|
|
|
|
| 629 |
tipo = "conversa_alheia"
|
| 630 |
contexto_extra = ""
|
| 631 |
|
| 632 |
+
# Adiciona info de transição se disponível
|
| 633 |
+
transicao_info = f"[Nível transição: {nivel_transicao}]" if nivel_transicao > 0 else ""
|
| 634 |
+
|
| 635 |
# Prepara texto com contexto
|
| 636 |
+
input_text_com_contexto = f"[CONTEXTO: {padrao.upper()}] {transicao_info} {contexto_extra} {mensagem}"
|
| 637 |
|
| 638 |
+
# Salva aprendizado com nivel_transicao
|
| 639 |
self.db.salvar_aprendizado_detalhado(
|
| 640 |
input_text=input_text_com_contexto,
|
| 641 |
output_text=resposta,
|
|
|
|
| 646 |
'reply_to_bot': reply_to_bot,
|
| 647 |
'tipo_conversa': tipo_conversa,
|
| 648 |
'tipo': tipo,
|
| 649 |
+
'reply_metadata': reply_metadata,
|
| 650 |
+
'nivel_transicao': nivel_transicao # ADICIONADO
|
| 651 |
},
|
| 652 |
qualidade_score=0.8,
|
| 653 |
+
tipo_aprendizado=f"reply_{tipo}_nivel_{nivel_transicao}"
|
| 654 |
)
|
| 655 |
|
| 656 |
+
logger.debug(f"✅ Padrão de reply aprendido: {padrao} | Nível: {nivel_transicao}")
|
| 657 |
|
| 658 |
except Exception as e:
|
| 659 |
logger.warning(f"⚠️ Erro ao aprender padrão de reply: {e}")
|
| 660 |
|
| 661 |
+
def _analisar_transicao_privilegiado(
|
| 662 |
+
self,
|
| 663 |
+
numero: str,
|
| 664 |
+
usuario: str,
|
| 665 |
+
nivel_transicao: int,
|
| 666 |
+
mensagem: str,
|
| 667 |
+
contexto: Dict
|
| 668 |
+
):
|
| 669 |
+
"""
|
| 670 |
+
Analisa transições de usuários privilegiados
|
| 671 |
+
|
| 672 |
+
Args:
|
| 673 |
+
numero: Número do usuário
|
| 674 |
+
usuario: Nome do usuário
|
| 675 |
+
nivel_transicao: Nível atual de transição
|
| 676 |
+
mensagem: Mensagem enviada
|
| 677 |
+
contexto: Contexto da conversa
|
| 678 |
+
"""
|
| 679 |
+
try:
|
| 680 |
+
# Recupera histórico de transições
|
| 681 |
+
transicoes = self.db._execute_with_retry(
|
| 682 |
+
"""
|
| 683 |
+
SELECT nivel_transicao_anterior, nivel_transicao_novo, timestamp, razao
|
| 684 |
+
FROM transicoes_humor
|
| 685 |
+
WHERE numero = ?
|
| 686 |
+
ORDER BY timestamp DESC
|
| 687 |
+
LIMIT 10
|
| 688 |
+
""",
|
| 689 |
+
(numero,),
|
| 690 |
+
fetch=True
|
| 691 |
+
)
|
| 692 |
+
|
| 693 |
+
# Analisa padrão de transição
|
| 694 |
+
if len(transicoes) >= 3:
|
| 695 |
+
niveis = [t[1] for t in transicoes] # Últimos níveis novos
|
| 696 |
+
mudancas = sum(1 for i in range(len(niveis)-1) if niveis[i] != niveis[i+1])
|
| 697 |
+
|
| 698 |
+
# Se muitas mudanças, usuário é volátil
|
| 699 |
+
if mudancas >= 2:
|
| 700 |
+
logger.info(f"⚠️ Usuário {usuario} é volátil em transições: {mudancas} mudanças")
|
| 701 |
+
|
| 702 |
+
logger.debug(f"📊 Transição privilegiado: {usuario} → Nível {nivel_transicao}")
|
| 703 |
+
|
| 704 |
+
except Exception as e:
|
| 705 |
+
logger.warning(f"⚠️ Erro na análise de transição: {e}")
|
| 706 |
+
|
| 707 |
# ========================================================================
|
| 708 |
# 🔄 TREINAMENTO PERIÓDICO
|
| 709 |
# ========================================================================
|
|
|
|
| 754 |
logger.warning("⚠️ Nenhum exemplo com qualidade suficiente")
|
| 755 |
return
|
| 756 |
|
| 757 |
+
# Gera arquivo JSONL com nivel_transicao
|
| 758 |
with open("training_dataset_akira_v21.jsonl", "w", encoding="utf-8") as f:
|
| 759 |
for ex in exemplos[:500]:
|
| 760 |
if ex.get("score", 0) >= 0.7:
|
|
|
|
| 763 |
"output": ex.get("output", ""),
|
| 764 |
"humor": ex.get("humor", "normal_ironico"),
|
| 765 |
"modo": ex.get("modo", "normal_ironico"),
|
| 766 |
+
"nivel_transicao": ex.get("nivel_transicao", 0), # ADICIONADO
|
| 767 |
"metadata": {
|
| 768 |
"score": ex.get("score", 0.5),
|
| 769 |
"timestamp": time.time(),
|
|
|
|
| 771 |
}
|
| 772 |
}, ensure_ascii=False) + "\n")
|
| 773 |
|
| 774 |
+
logger.info(f"✅ Dataset gerado: {len(exemplos)} exemplos (com nível transição)")
|
| 775 |
self.db.marcar_examples_como_usados()
|
| 776 |
|
| 777 |
except Exception as e:
|
|
|
|
| 786 |
with open(DATASET_PATH, "r", encoding="utf-8") as f:
|
| 787 |
dataset = json.load(f)
|
| 788 |
|
| 789 |
+
# Análise estatística com nivel_transicao
|
| 790 |
padroes = {
|
| 791 |
"total": len(dataset),
|
| 792 |
"reply_to_bot": 0,
|
|
|
|
| 795 |
"grupo": 0,
|
| 796 |
"pv": 0,
|
| 797 |
"audio": 0,
|
| 798 |
+
"texto": 0,
|
| 799 |
+
"transicao_nivel_0": 0,
|
| 800 |
+
"transicao_nivel_1": 0,
|
| 801 |
+
"transicao_nivel_2": 0,
|
| 802 |
+
"transicao_nivel_3": 0
|
| 803 |
}
|
| 804 |
|
| 805 |
for e in dataset:
|
|
|
|
| 821 |
padroes["audio"] += 1
|
| 822 |
else:
|
| 823 |
padroes["texto"] += 1
|
| 824 |
+
|
| 825 |
+
# Analisa nível de transição
|
| 826 |
+
nivel = meta.get("nivel_transicao", 0)
|
| 827 |
+
if nivel == 0:
|
| 828 |
+
padroes["transicao_nivel_0"] += 1
|
| 829 |
+
elif nivel == 1:
|
| 830 |
+
padroes["transicao_nivel_1"] += 1
|
| 831 |
+
elif nivel == 2:
|
| 832 |
+
padroes["transicao_nivel_2"] += 1
|
| 833 |
+
elif nivel == 3:
|
| 834 |
+
padroes["transicao_nivel_3"] += 1
|
| 835 |
|
| 836 |
# Log estatísticas
|
| 837 |
logger.info(f"📊 Estatísticas do dataset:")
|
|
|
|
| 841 |
logger.info(f" Com reply_metadata: {padroes['reply_with_metadata']}")
|
| 842 |
logger.info(f" Grupo: {padroes['grupo']} | PV: {padroes['pv']}")
|
| 843 |
logger.info(f" Áudio: {padroes['audio']} | Texto: {padroes['texto']}")
|
| 844 |
+
logger.info(f" Níveis transição: 0={padroes['transicao_nivel_0']} | 1={padroes['transicao_nivel_1']} | 2={padroes['transicao_nivel_2']} | 3={padroes['transicao_nivel_3']}")
|
| 845 |
|
| 846 |
except Exception as e:
|
| 847 |
logger.error(f"❌ Erro na análise global: {e}")
|
|
|
|
| 856 |
logger.warning(f"⚠️ Erro na otimização: {e}")
|
| 857 |
|
| 858 |
# ========================================================================
|
| 859 |
+
# 🔧 FUNÇÃO PARA USO DIRETO DA API (ATUALIZADA)
|
| 860 |
# ========================================================================
|
| 861 |
|
| 862 |
def processar_interacao_api(self, payload: Dict, resposta: str) -> Dict:
|
| 863 |
"""
|
| 864 |
+
Processa interação da API para treinamento - ATUALIZADA
|
| 865 |
|
| 866 |
Args:
|
| 867 |
payload: Payload da requisição
|
|
|
|
| 888 |
|
| 889 |
is_reply = bool(payload.get('mensagem_citada')) or bool(reply_metadata)
|
| 890 |
|
| 891 |
+
# Contexto da análise com nivel_transicao
|
| 892 |
contexto_analise = payload.get('analise', {})
|
| 893 |
+
nivel_transicao = contexto_analise.get('nivel_transicao', 0)
|
| 894 |
|
| 895 |
+
# Registra interação com nivel_transicao
|
| 896 |
self.registrar_interacao(
|
| 897 |
usuario=usuario,
|
| 898 |
mensagem=mensagem,
|
|
|
|
| 904 |
tipo_conversa=tipo_conversa,
|
| 905 |
tipo_mensagem=tipo_mensagem,
|
| 906 |
reply_to_bot=reply_to_bot,
|
| 907 |
+
reply_metadata=reply_metadata,
|
| 908 |
+
nivel_transicao=nivel_transicao # ADICIONADO
|
| 909 |
)
|
| 910 |
|
| 911 |
return {
|
| 912 |
'status': 'success',
|
| 913 |
'message': 'Interação registrada',
|
| 914 |
'usuario': usuario,
|
| 915 |
+
'nivel_transicao': nivel_transicao,
|
| 916 |
'timestamp': time.time()
|
| 917 |
}
|
| 918 |
|
|
|
|
| 947 |
return _treinamento_instance
|
| 948 |
|
| 949 |
# ============================================================================
|
| 950 |
+
# 🎯 FUNÇÃO DE INTEGRAÇÃO RÁPIDA (ATUALIZADA)
|
| 951 |
# ============================================================================
|
| 952 |
def registrar_interacao_rapida(
|
| 953 |
usuario: str,
|
|
|
|
| 959 |
tipo_conversa: str = 'pv',
|
| 960 |
tipo_mensagem: str = 'texto',
|
| 961 |
contexto: Dict = None,
|
| 962 |
+
reply_metadata: Optional[Dict] = None,
|
| 963 |
+
nivel_transicao: int = 0 # NOVO PARÂMETRO
|
| 964 |
) -> bool:
|
| 965 |
"""
|
| 966 |
+
Registra interação rapidamente - ATUALIZADA
|
| 967 |
|
| 968 |
Args:
|
| 969 |
usuario: Nome do usuário
|
|
|
|
| 976 |
tipo_mensagem: Tipo da mensagem
|
| 977 |
contexto: Contexto da conversa
|
| 978 |
reply_metadata: Metadata do reply
|
| 979 |
+
nivel_transicao: Nível de transição do usuário
|
| 980 |
|
| 981 |
Returns:
|
| 982 |
True se sucesso, False caso contrário
|
|
|
|
| 993 |
tipo_conversa=tipo_conversa,
|
| 994 |
tipo_mensagem=tipo_mensagem,
|
| 995 |
contexto=contexto,
|
| 996 |
+
reply_metadata=reply_metadata,
|
| 997 |
+
nivel_transicao=nivel_transicao # ADICIONADO
|
| 998 |
)
|
| 999 |
+
logger.debug(f"✅ Interação rápida registrada: {usuario[:10]} | Nível: {nivel_transicao}")
|
| 1000 |
return True
|
| 1001 |
except Exception as e:
|
| 1002 |
logger.error(f"❌ Erro no registro rápido: {e}")
|
|
|
|
| 1007 |
# ============================================================================
|
| 1008 |
if __name__ == "__main__":
|
| 1009 |
print("=" * 80)
|
| 1010 |
+
print("TESTANDO TREINAMENTO.PY - COMPLETO COM nivel_transicao")
|
| 1011 |
print("=" * 80)
|
| 1012 |
|
| 1013 |
from .database import Database
|
|
|
|
| 1017 |
db = Database(":memory:")
|
| 1018 |
treinamento = Treinamento(db)
|
| 1019 |
|
| 1020 |
+
# Simula payload do api.py com reply_metadata e nivel_transicao
|
| 1021 |
payload_teste = {
|
| 1022 |
"usuario": "Isaac Teste",
|
| 1023 |
"numero": "244978787009",
|
|
|
|
| 1032 |
},
|
| 1033 |
"analise": {
|
| 1034 |
"humor_atualizado": "normal_ironico",
|
| 1035 |
+
"modo_resposta": "normal_ironico",
|
| 1036 |
+
"nivel_transicao": 2,
|
| 1037 |
+
"info_transicao": {
|
| 1038 |
+
"desc": "Nível 2 - Formal Relaxado",
|
| 1039 |
+
"modo": "tecnico_formal",
|
| 1040 |
+
"deve_transicionar": False
|
| 1041 |
+
}
|
| 1042 |
}
|
| 1043 |
}
|
| 1044 |
|
| 1045 |
resposta_teste = "Tudo e tu, puto?"
|
| 1046 |
|
| 1047 |
+
# Processa interação com nivel_transicao
|
| 1048 |
resultado = treinamento.processar_interacao_api(payload_teste, resposta_teste)
|
| 1049 |
|
| 1050 |
print(f"✅ Teste OK: {resultado}")
|
| 1051 |
print(f"📝 Mensagem: {payload_teste['mensagem']}")
|
| 1052 |
print(f"💬 Resposta: {resposta_teste}")
|
| 1053 |
+
print(f"🎯 Nível transição: {payload_teste['analise']['nivel_transicao']}")
|
| 1054 |
|
| 1055 |
+
# Teste com registro rápido com nivel_transicao
|
| 1056 |
sucesso = registrar_interacao_rapida(
|
| 1057 |
usuario="Teste 2",
|
| 1058 |
numero="244000000000",
|
|
|
|
| 1060 |
resposta="Nada, cota.",
|
| 1061 |
is_reply=True,
|
| 1062 |
reply_to_bot=True,
|
| 1063 |
+
reply_metadata={"quoted_author_name": "Akira", "is_reply": True},
|
| 1064 |
+
nivel_transicao=3
|
| 1065 |
)
|
| 1066 |
|
| 1067 |
print(f"✅ Registro rápido: {'Sucesso' if sucesso else 'Falhou'}")
|
|
|
|
| 1072 |
traceback.print_exc()
|
| 1073 |
|
| 1074 |
print("\n" + "=" * 80)
|
| 1075 |
+
print("TREINAMENTO.PY - COMPLETO COM SUPORTE A nivel_transicao")
|
| 1076 |
print("=" * 80)
|