akra35567 commited on
Commit
c2ebc82
·
verified ·
1 Parent(s): 750d4eb

Update modules/api.py

Browse files
Files changed (1) hide show
  1. modules/api.py +96 -14
modules/api.py CHANGED
@@ -1,11 +1,12 @@
1
- # modules/api.py — AKIRA V21 FINAL INTEGRADO (Dezembro 2025)
2
  """
3
- ✅ TOTALMENTE INTEGRADO com config.py, database.py, contexto.py e treinamento.py atualizados
4
- ✅ CORREÇÃO: Usa métodos corretos do Database
5
  ✅ COMPATÍVEL com index.js e reply_metadata
6
  ✅ Sistema multi-API com fallback
7
  ✅ Cache de contexto otimizado
8
  ✅ Treinamento automático integrado
 
9
  """
10
 
11
  import time
@@ -93,6 +94,7 @@ class MultiAPIManager:
93
  """
94
  try:
95
  logger.debug(f"📝 Construindo prompt para: {usuario}")
 
96
 
97
  # Usa a função do config.py
98
  prompt = config.construir_prompt_api(
@@ -139,6 +141,7 @@ RESPONDA COMO AKIRA (IRÔNICA, SEM FILTRO, 1-2 LINHAS):"""
139
  ) -> str:
140
  """Gera resposta usando multi-API fallback"""
141
  logger.info(f"🎯 Gerando resposta para {usuario}")
 
142
 
143
  # Construir prompt
144
  prompt = self._construir_prompt(
@@ -154,23 +157,28 @@ RESPONDA COMO AKIRA (IRÔNICA, SEM FILTRO, 1-2 LINHAS):"""
154
  # Obter parâmetros
155
  parametros = self._obter_parametros_api(analise)
156
 
 
 
157
  # Tentar APIs em ordem
158
  for api_name in config.API_FALLBACK_ORDER:
159
  if api_name not in self.apis_disponiveis:
160
  continue
161
 
162
  try:
 
163
  resposta = self._chamar_api(api_name, prompt, parametros)
164
  if resposta:
165
  resposta_limpa = self._limpar_resposta(resposta)
166
  logger.info(f"✅ API {api_name} respondeu: {resposta_limpa[:80]}...")
167
  return resposta_limpa
168
  except Exception as e:
169
- logger.warning(f"❌ API {api_name} falhou: {e}")
170
  continue
171
 
172
  # Fallback contextual
173
- return self._gerar_fallback_contextual(mensagem, mensagem_citada, reply_info)
 
 
174
 
175
  def _chamar_api(self, api_name: str, prompt: str, params: Dict[str, Any]) -> str:
176
  """Chama API específica"""
@@ -340,7 +348,7 @@ class AkiraAPI:
340
  self.api = Blueprint("akira_api", __name__)
341
  self.contexto_cache = SimpleTTLCache(ttl_seconds=300)
342
 
343
- # Inicializa Database com caminho CORRETO
344
  self.db = Database(config.DB_PATH)
345
  self.llm_manager = MultiAPIManager()
346
 
@@ -358,7 +366,7 @@ class AkiraAPI:
358
  self.treinador = None
359
 
360
  self._setup_routes()
361
- logger.success("🚀 AKIRA V21 FINAL inicializada")
362
 
363
  def _get_user_context(self, numero: str, tipo_conversa: str, grupo_id: str = "") -> Contexto:
364
  """Obtém contexto isolado"""
@@ -401,7 +409,7 @@ class AkiraAPI:
401
  }
402
 
403
  def _extrair_payload_indexjs(self, data: Dict[str, Any]) -> Dict[str, Any]:
404
- """Extrai dados do payload do index.js"""
405
  payload = {
406
  'numero': str(data.get('numero', '')).strip(),
407
  'usuario': data.get('usuario', 'Anônimo').strip(),
@@ -445,7 +453,7 @@ class AkiraAPI:
445
 
446
  @self.api.route('/akira', methods=['POST'])
447
  def akira_endpoint():
448
- """Endpoint principal"""
449
  try:
450
  # Recebe payload
451
  data = request.get_json() or {}
@@ -532,7 +540,15 @@ class AkiraAPI:
532
  if payload['reply_metadata']:
533
  reply_to_bot = payload['reply_metadata'].get('reply_to_bot', False)
534
 
535
- # Atualiza contexto
 
 
 
 
 
 
 
 
536
  contexto.atualizar_contexto(
537
  mensagem=payload['mensagem'],
538
  resposta=resposta,
@@ -542,6 +558,38 @@ class AkiraAPI:
542
  reply_to_bot=reply_to_bot
543
  )
544
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  # Registra interação para treinamento
546
  if hasattr(self, 'treinador') and self.treinador:
547
  try:
@@ -558,6 +606,7 @@ class AkiraAPI:
558
  reply_to_bot=reply_to_bot,
559
  reply_metadata=payload['reply_metadata']
560
  )
 
561
  except Exception as e:
562
  logger.warning(f"⚠️ Erro ao registrar interação: {e}")
563
 
@@ -582,8 +631,10 @@ class AkiraAPI:
582
  "status": "✅ AKIRA V21 ONLINE",
583
  "hora_luanda": agora.strftime("%H:%M"),
584
  "versao": config.VERSAO,
 
585
  "apis_disponiveis": self.llm_manager.apis_disponiveis,
586
- "cache_size": len(self.contexto_cache._store)
 
587
  })
588
 
589
  @self.api.route('/reset', methods=['POST'])
@@ -616,11 +667,13 @@ class AkiraAPI:
616
  "desenvolvedor": "Isaac Quarenta",
617
  "empresa": "Softedge",
618
  "versao": config.VERSAO,
 
619
  "endpoints": ["/akira", "/health", "/reset", "/info"],
620
  "configuracoes": {
621
  "temperatura_padrao": config.TEMPERATURE,
622
  "max_tokens": config.MAX_TOKENS,
623
- "timezone_offset": config.TIMEZONE_OFFSET_HOURS
 
624
  }
625
  })
626
 
@@ -692,7 +745,7 @@ def gerar_resposta_direta(
692
  # ============================================================================
693
  if __name__ == "__main__":
694
  print("=" * 80)
695
- print("TESTANDO API.PY - FINAL INTEGRADO")
696
  print("=" * 80)
697
 
698
  # Teste simples
@@ -723,11 +776,40 @@ if __name__ == "__main__":
723
  print(f"📝 Mensagem: {test_payload['mensagem']}")
724
  print(f"💬 Resposta: {resposta}")
725
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
726
  except Exception as e:
727
  print(f"❌ Erro: {e}")
728
  import traceback
729
  traceback.print_exc()
730
 
731
  print("\n" + "=" * 80)
732
- print("API.PY - INTEGRADO E PRONTO PARA USO")
733
  print("=" * 80)
 
1
+ # modules/api.py — AKIRA V21 FINAL INTEGRADO (Dezembro 2025) - CORRIGIDO
2
  """
3
+ ✅ TOTALMENTE INTEGRADO com database.py corrigido (message_id sem UNIQUE)
4
+ ✅ CORREÇÃO: Usa métodos corretos do Database atualizado
5
  ✅ COMPATÍVEL com index.js e reply_metadata
6
  ✅ Sistema multi-API com fallback
7
  ✅ Cache de contexto otimizado
8
  ✅ Treinamento automático integrado
9
+ ✅ Resolve problema de UNIQUE constraint failed
10
  """
11
 
12
  import time
 
94
  """
95
  try:
96
  logger.debug(f"📝 Construindo prompt para: {usuario}")
97
+ logger.debug(f"📝 Mensagem citada: {mensagem_citada[:80] if mensagem_citada else '[Nenhuma]'}...")
98
 
99
  # Usa a função do config.py
100
  prompt = config.construir_prompt_api(
 
141
  ) -> str:
142
  """Gera resposta usando multi-API fallback"""
143
  logger.info(f"🎯 Gerando resposta para {usuario}")
144
+ logger.info(f"📤 Mensagem: {mensagem[:80]}...")
145
 
146
  # Construir prompt
147
  prompt = self._construir_prompt(
 
157
  # Obter parâmetros
158
  parametros = self._obter_parametros_api(analise)
159
 
160
+ logger.debug(f"🔧 Parâmetros: {parametros}")
161
+
162
  # Tentar APIs em ordem
163
  for api_name in config.API_FALLBACK_ORDER:
164
  if api_name not in self.apis_disponiveis:
165
  continue
166
 
167
  try:
168
+ logger.debug(f"🔄 Tentando API: {api_name}")
169
  resposta = self._chamar_api(api_name, prompt, parametros)
170
  if resposta:
171
  resposta_limpa = self._limpar_resposta(resposta)
172
  logger.info(f"✅ API {api_name} respondeu: {resposta_limpa[:80]}...")
173
  return resposta_limpa
174
  except Exception as e:
175
+ logger.warning(f"❌ API {api_name} falhou: {str(e)[:100]}")
176
  continue
177
 
178
  # Fallback contextual
179
+ fallback = self._gerar_fallback_contextual(mensagem, mensagem_citada, reply_info)
180
+ logger.info(f"🔄 Usando fallback: {fallback}")
181
+ return fallback
182
 
183
  def _chamar_api(self, api_name: str, prompt: str, params: Dict[str, Any]) -> str:
184
  """Chama API específica"""
 
348
  self.api = Blueprint("akira_api", __name__)
349
  self.contexto_cache = SimpleTTLCache(ttl_seconds=300)
350
 
351
+ # Inicializa Database CORRETAMENTE
352
  self.db = Database(config.DB_PATH)
353
  self.llm_manager = MultiAPIManager()
354
 
 
366
  self.treinador = None
367
 
368
  self._setup_routes()
369
+ logger.success("🚀 AKIRA V21 FINAL inicializada (Database corrigido)")
370
 
371
  def _get_user_context(self, numero: str, tipo_conversa: str, grupo_id: str = "") -> Contexto:
372
  """Obtém contexto isolado"""
 
409
  }
410
 
411
  def _extrair_payload_indexjs(self, data: Dict[str, Any]) -> Dict[str, Any]:
412
+ """Extrai dados do payload do index.js - ATUALIZADO"""
413
  payload = {
414
  'numero': str(data.get('numero', '')).strip(),
415
  'usuario': data.get('usuario', 'Anônimo').strip(),
 
453
 
454
  @self.api.route('/akira', methods=['POST'])
455
  def akira_endpoint():
456
+ """Endpoint principal - CORRIGIDO para usar database atualizado"""
457
  try:
458
  # Recebe payload
459
  data = request.get_json() or {}
 
540
  if payload['reply_metadata']:
541
  reply_to_bot = payload['reply_metadata'].get('reply_to_bot', False)
542
 
543
+ # Mede tempo de resposta
544
+ tempo_resposta_ms = int((time.time() - request.start_time) * 1000) if hasattr(request, 'start_time') else 0
545
+
546
+ # CORREÇÃO: Prepara reply_info_json para o Database
547
+ reply_info_json = None
548
+ if payload['reply_metadata']:
549
+ reply_info_json = json.dumps(payload['reply_metadata'], ensure_ascii=False)
550
+
551
+ # Atualiza contexto usando o Database CORRIGIDO
552
  contexto.atualizar_contexto(
553
  mensagem=payload['mensagem'],
554
  resposta=resposta,
 
558
  reply_to_bot=reply_to_bot
559
  )
560
 
561
+ # Salva mensagem diretamente no banco (backup)
562
+ try:
563
+ # Gera message_id único com timestamp e random
564
+ timestamp = int(time.time() * 1000)
565
+ random_suffix = random.randint(1000, 9999)
566
+ message_id = f"{payload['numero']}_{timestamp}_{random_suffix}"
567
+
568
+ self.db.salvar_mensagem(
569
+ usuario=payload['usuario'],
570
+ mensagem=payload['mensagem'],
571
+ resposta=resposta,
572
+ numero=payload['numero'],
573
+ is_reply=is_reply,
574
+ mensagem_original=payload['mensagem_citada'],
575
+ reply_to_bot=reply_to_bot,
576
+ humor=analise.get('humor_atualizado', 'normal_ironico'),
577
+ modo_resposta=analise.get('modo_resposta', 'normal_ironico'),
578
+ emocao_detectada=analise.get('emocao_primaria', 'neutral'),
579
+ confianca_emocao=analise.get('confianca_emocao', 0.5),
580
+ tipo_mensagem=payload['tipo_mensagem'],
581
+ reply_info_json=reply_info_json,
582
+ usuario_nome=payload['usuario'],
583
+ grupo_id=payload['grupo_id'],
584
+ grupo_nome=payload['grupo_nome'],
585
+ tipo_conversa=payload['tipo_conversa'],
586
+ message_id=message_id,
587
+ bot_response_time_ms=tempo_resposta_ms
588
+ )
589
+ logger.debug(f"✅ Mensagem salva no banco com message_id: {message_id}")
590
+ except Exception as db_error:
591
+ logger.warning(f"⚠️ Erro ao salvar mensagem no banco: {db_error}")
592
+
593
  # Registra interação para treinamento
594
  if hasattr(self, 'treinador') and self.treinador:
595
  try:
 
606
  reply_to_bot=reply_to_bot,
607
  reply_metadata=payload['reply_metadata']
608
  )
609
+ logger.debug("✅ Interação registrada para treinamento")
610
  except Exception as e:
611
  logger.warning(f"⚠️ Erro ao registrar interação: {e}")
612
 
 
631
  "status": "✅ AKIRA V21 ONLINE",
632
  "hora_luanda": agora.strftime("%H:%M"),
633
  "versao": config.VERSAO,
634
+ "database": "Corrigido (message_id sem UNIQUE)",
635
  "apis_disponiveis": self.llm_manager.apis_disponiveis,
636
+ "cache_size": len(self.contexto_cache._store),
637
+ "treinamento_ativo": hasattr(self, 'treinador') and self.treinador is not None
638
  })
639
 
640
  @self.api.route('/reset', methods=['POST'])
 
667
  "desenvolvedor": "Isaac Quarenta",
668
  "empresa": "Softedge",
669
  "versao": config.VERSAO,
670
+ "database_status": "Corrigido - message_id sem UNIQUE constraint",
671
  "endpoints": ["/akira", "/health", "/reset", "/info"],
672
  "configuracoes": {
673
  "temperatura_padrao": config.TEMPERATURE,
674
  "max_tokens": config.MAX_TOKENS,
675
+ "timezone_offset": config.TIMEZONE_OFFSET_HOURS,
676
+ "treinamento_auto": config.START_PERIODIC_TRAINER
677
  }
678
  })
679
 
 
745
  # ============================================================================
746
  if __name__ == "__main__":
747
  print("=" * 80)
748
+ print("TESTANDO API.PY - FINAL INTEGRADO E CORRIGIDO")
749
  print("=" * 80)
750
 
751
  # Teste simples
 
776
  print(f"📝 Mensagem: {test_payload['mensagem']}")
777
  print(f"💬 Resposta: {resposta}")
778
 
779
+ # Teste com mensagem citada
780
+ test_payload2 = {
781
+ "numero": "244978787009",
782
+ "usuario": "Isaac Quarenta",
783
+ "mensagem": "Você disse que gosta de futebol?",
784
+ "tipo_conversa": "pv",
785
+ "tipo_mensagem": "texto",
786
+ "mensagem_citada": "Sim, gosto do Petro de Luanda.",
787
+ "reply_metadata": {
788
+ "is_reply": True,
789
+ "reply_to_bot": True,
790
+ "quoted_author_name": "Akira"
791
+ }
792
+ }
793
+
794
+ resposta2 = gerar_resposta_direta(
795
+ mensagem=test_payload2["mensagem"],
796
+ usuario=test_payload2["usuario"],
797
+ numero=test_payload2["numero"],
798
+ tipo_conversa=test_payload2["tipo_conversa"],
799
+ mensagem_citada=test_payload2["mensagem_citada"],
800
+ reply_metadata=test_payload2["reply_metadata"]
801
+ )
802
+
803
+ print(f"\n✅ Teste com reply OK")
804
+ print(f"📝 Mensagem: {test_payload2['mensagem']}")
805
+ print(f"📝 Mensagem citada: {test_payload2['mensagem_citada']}")
806
+ print(f"💬 Resposta: {resposta2}")
807
+
808
  except Exception as e:
809
  print(f"❌ Erro: {e}")
810
  import traceback
811
  traceback.print_exc()
812
 
813
  print("\n" + "=" * 80)
814
+ print("API.PY - INTEGRADO, CORRIGIDO E PRONTO PARA USO")
815
  print("=" * 80)