Spaces:
Running
Running
Update modules/api.py
Browse files- modules/api.py +101 -102
modules/api.py
CHANGED
|
@@ -72,101 +72,101 @@ class MultiAPIManager:
|
|
| 72 |
return apis
|
| 73 |
|
| 74 |
def _construir_prompt(
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
) -> str:
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
# Traduz mês
|
| 90 |
-
meses = {"January":"janeiro","February":"fevereiro","March":"março","April":"abril",
|
| 91 |
-
"May":"maio","June":"junho","July":"julho","August":"agosto",
|
| 92 |
-
"September":"setembro","October":"outubro","November":"novembro","December":"dezembro"}
|
| 93 |
-
for en, pt in meses.items():
|
| 94 |
-
data_hora_atual = data_hora_atual.replace(en, pt)
|
| 95 |
-
|
| 96 |
-
# Info da empresa
|
| 97 |
-
empresa_info = EmpresaInfo()
|
| 98 |
-
info_context = ""
|
| 99 |
-
if any(p in mensagem.lower() for p in ["criou","criador","quem fez","desenvolveu","softedge","isaac"]):
|
| 100 |
-
info_context = f"\n[INFO]: {empresa_info.get_resposta_sobre_empresa(mensagem, analise.get('tom_usuario') == 'formal')}\n"
|
| 101 |
-
|
| 102 |
-
# Reply context adaptado ao payload do index.js
|
| 103 |
-
reply_context_text = ""
|
| 104 |
-
usuario_citado_nome = "desconhecido"
|
| 105 |
-
usuario_citado_numero = "desconhecido"
|
| 106 |
-
eh_resposta_akira = False
|
| 107 |
-
contexto_resposta = "Responda normalmente à mensagem atual."
|
| 108 |
-
|
| 109 |
-
if reply_info:
|
| 110 |
-
eh_resposta_akira = reply_info.get('reply_to_bot', False)
|
| 111 |
-
usuario_citado_nome = reply_info.get('usuario_citado_nome', 'desconhecido')
|
| 112 |
-
usuario_citado_numero = reply_info.get('usuario_citado_numero', 'desconhecido')
|
| 113 |
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
{config.SYSTEM_PROMPT.format(
|
| 171 |
humor=humor_atual,
|
| 172 |
humor_desc=humor_desc,
|
|
@@ -199,14 +199,13 @@ HISTÓRICO:
|
|
| 199 |
{reply_context_text}
|
| 200 |
USUÁRIO ({nome_usuario}): {mensagem}
|
| 201 |
AKIRA:"""
|
| 202 |
-
|
| 203 |
-
|
| 204 |
logger.debug(f"Prompt: {len(prompt)} chars | modo: {modo_resposta} | tipo: {tipo_conversa} | reply: {bool(reply_info)}")
|
| 205 |
return prompt
|
| 206 |
|
| 207 |
def gerar_resposta(self, mensagem, historico, mensagem_citada, analise, usuario, tipo_conversa, reply_info=None) -> str:
|
| 208 |
prompt = self._construir_prompt(mensagem, historico, mensagem_citada, analise, usuario, tipo_conversa, reply_info)
|
| 209 |
-
|
| 210 |
for _ in range(2):
|
| 211 |
for api in config.API_FALLBACK_ORDER:
|
| 212 |
if api not in self.apis_disponiveis:
|
|
@@ -229,7 +228,7 @@ AKIRA:"""
|
|
| 229 |
logger.debug(f"Falha na API {api}: {e}")
|
| 230 |
time.sleep(1)
|
| 231 |
time.sleep(2)
|
| 232 |
-
|
| 233 |
return random.choice(["Ya, tá bom.", "Foda-se.", "Hmm...", "Caralho."])
|
| 234 |
|
| 235 |
def _chamar_mistral(self, prompt: str) -> str:
|
|
@@ -363,16 +362,16 @@ class AkiraAPI:
|
|
| 363 |
if not self.db.pode_usar_reset(numero):
|
| 364 |
# XINGAMENTO AUTOMÁTICO (do config.py)
|
| 365 |
return jsonify({'resposta': 'Só o boss pode usar /reset, puto. Vai sonhar.'})
|
| 366 |
-
|
| 367 |
if not confirmacao:
|
| 368 |
return jsonify({'resposta': 'Quer mesmo apagar tudo? Manda /reset de novo.'})
|
| 369 |
-
|
| 370 |
# Limpa cache
|
| 371 |
self.contexto_cache._store.clear()
|
| 372 |
-
|
| 373 |
# Reseta no banco
|
| 374 |
resultado = self.db.resetar_contexto_usuario(numero, tipo_reset)
|
| 375 |
-
|
| 376 |
return jsonify({'resposta': f"Reset feito! {resultado.get('itens_apagados',0)} itens apagados."})
|
| 377 |
|
| 378 |
def _processar_payload_indexjs(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
|
| 72 |
return apis
|
| 73 |
|
| 74 |
def _construir_prompt(
|
| 75 |
+
self,
|
| 76 |
+
mensagem: str,
|
| 77 |
+
historico: List[Dict[str, str]],
|
| 78 |
+
mensagem_citada: str,
|
| 79 |
+
analise: Dict[str, Any],
|
| 80 |
+
usuario: str,
|
| 81 |
+
tipo_conversa: str,
|
| 82 |
+
reply_info: Optional[Dict] = None
|
| 83 |
+
) -> str:
|
| 84 |
+
"""Constrói prompt usando config.py BRUTAL com adaptação para payload do index.js"""
|
| 85 |
+
from datetime import datetime, timedelta
|
| 86 |
+
agora = datetime.now() + timedelta(hours=config.TIMEZONE_OFFSET_HOURS)
|
| 87 |
+
data_hora_atual = agora.strftime("%d de %B de %Y, %H:%M")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
+
# Traduz mês
|
| 90 |
+
meses = {"January":"janeiro","February":"fevereiro","March":"março","April":"abril",
|
| 91 |
+
"May":"maio","June":"junho","July":"julho","August":"agosto",
|
| 92 |
+
"September":"setembro","October":"outubro","November":"novembro","December":"dezembro"}
|
| 93 |
+
for en, pt in meses.items():
|
| 94 |
+
data_hora_atual = data_hora_atual.replace(en, pt)
|
| 95 |
+
|
| 96 |
+
# Info da empresa
|
| 97 |
+
empresa_info = EmpresaInfo()
|
| 98 |
+
info_context = ""
|
| 99 |
+
if any(p in mensagem.lower() for p in ["criou","criador","quem fez","desenvolveu","softedge","isaac"]):
|
| 100 |
+
info_context = f"\n[INFO]: {empresa_info.get_resposta_sobre_empresa(mensagem, analise.get('tom_usuario') == 'formal')}\n"
|
| 101 |
+
|
| 102 |
+
# Reply context adaptado ao payload do index.js
|
| 103 |
+
reply_context_text = ""
|
| 104 |
+
usuario_citado_nome = "desconhecido"
|
| 105 |
+
usuario_citado_numero = "desconhecido"
|
| 106 |
+
eh_resposta_akira = False
|
| 107 |
+
contexto_resposta = "Responda normalmente à mensagem atual."
|
| 108 |
+
|
| 109 |
+
if reply_info:
|
| 110 |
+
eh_resposta_akira = reply_info.get('reply_to_bot', False)
|
| 111 |
+
usuario_citado_nome = reply_info.get('usuario_citado_nome', 'desconhecido')
|
| 112 |
+
usuario_citado_numero = reply_info.get('usuario_citado_numero', 'desconhecido')
|
| 113 |
+
|
| 114 |
+
if eh_resposta_akira:
|
| 115 |
+
reply_context_text = f"[O USUÁRIO ESTÁ RESPONDENDO A UMA MENSAGEM MINHA ANTERIOR]\n"
|
| 116 |
+
reply_context_text += f"Contexto: Usuário está comentando algo que EU (Akira) disse antes.\n"
|
| 117 |
+
reply_context_text += f"IMPORTANTE: Responda como se estivesse continuando nossa conversa anterior."
|
| 118 |
+
contexto_resposta = "IMPORTANTE: Você está respondendo a alguém que está comentando SUA mensagem anterior. Mantenha continuidade!"
|
| 119 |
+
else:
|
| 120 |
+
reply_context_text = f"[O USUÁRIO ESTÁ CITANDO MENSAGEM DE {usuario_citado_nome.upper()}]\n"
|
| 121 |
+
reply_context_text += f"Contexto: Usuário está respondendo a outra pessoa, NÃO a mim.\n"
|
| 122 |
+
reply_context_text += f"IMPORTANTE: NÃO assuma que fui eu que disse aquilo. É conversa alheia."
|
| 123 |
+
contexto_resposta = "IMPORTANTE: O usuário está falando sobre conversa alheia. Não assuma que foi você!"
|
| 124 |
+
elif mensagem_citada:
|
| 125 |
+
if mensagem_citada.startswith("[Respondendo à Akira:"):
|
| 126 |
+
reply_context_text = f"\n[REPLY AO BOT]: Usuário respondeu à SUA mensagem: '{mensagem_citada[23:100]}...'"
|
| 127 |
+
eh_resposta_akira = True
|
| 128 |
+
contexto_resposta = "IMPORTANTE: Você está respondendo a alguém que está comentando SUA mensagem anterior. Mantenha continuidade!"
|
| 129 |
+
else:
|
| 130 |
+
reply_context_text = f"\n[REPLY]: Usuário citou outra mensagem: '{mensagem_citada[:100]}...'"
|
| 131 |
+
contexto_resposta = "IMPORTANTE: O usuário está falando sobre conversa alheia. Não assuma que foi você!"
|
| 132 |
+
|
| 133 |
+
# Histórico adaptado
|
| 134 |
+
historico_texto = ""
|
| 135 |
+
if historico:
|
| 136 |
+
for msg in historico[-8:]:
|
| 137 |
+
role = msg.get("role", "user").upper()
|
| 138 |
+
content = msg.get("content", "")
|
| 139 |
+
# Remove prefixos do histórico para contexto
|
| 140 |
+
if content.startswith("[REPLY]"):
|
| 141 |
+
content = f"(Respondendo) {content[7:]}"
|
| 142 |
+
historico_texto += f"{role}: {content}\n"
|
| 143 |
+
|
| 144 |
+
# Modo de resposta
|
| 145 |
+
modo_resposta = analise.get("modo_resposta", "normal_ironico")
|
| 146 |
+
modo_cfg = config.MODOS_RESPOSTA.get(modo_resposta, config.MODOS_RESPOSTA["normal_ironico"])
|
| 147 |
+
|
| 148 |
+
humor_atual = analise.get("humor_atualizado", "normal_ironico")
|
| 149 |
+
humor_desc = config.HUMORES_BASE.get(humor_atual, "Irônica e debochada")
|
| 150 |
+
|
| 151 |
+
# Usuário privilegiado
|
| 152 |
+
usuario_privilegiado = analise.get("usuario_privilegiado", False)
|
| 153 |
+
nome_usuario = usuario
|
| 154 |
+
|
| 155 |
+
# Tipo de conversa
|
| 156 |
+
tipo_isolamento = "GRUPO" if tipo_conversa == "grupo" else "PRIVADO"
|
| 157 |
+
|
| 158 |
+
# Tipo de mensagem (áudio/texto)
|
| 159 |
+
tipo_mensagem = analise.get('tipo_mensagem', 'texto')
|
| 160 |
+
contexto_tipo_mensagem = ""
|
| 161 |
+
if tipo_mensagem == 'audio':
|
| 162 |
+
contexto_tipo_mensagem = "\n[NOTA]: O usuário enviou uma mensagem de áudio (transcrita pelo bot)."
|
| 163 |
+
|
| 164 |
+
# === USA PROMPTS DO CONFIG.PY (BRUTAL) ===
|
| 165 |
+
# CORREÇÃO: Use as variáveis EXATAS do SYSTEM_PROMPT
|
| 166 |
+
prompt = f"""{config.PERSONA_BASE.format(
|
| 167 |
+
humor=humor_atual,
|
| 168 |
+
tom_usuario=analise.get("tom_usuario", "neutro")
|
| 169 |
+
)}
|
| 170 |
{config.SYSTEM_PROMPT.format(
|
| 171 |
humor=humor_atual,
|
| 172 |
humor_desc=humor_desc,
|
|
|
|
| 199 |
{reply_context_text}
|
| 200 |
USUÁRIO ({nome_usuario}): {mensagem}
|
| 201 |
AKIRA:"""
|
| 202 |
+
|
|
|
|
| 203 |
logger.debug(f"Prompt: {len(prompt)} chars | modo: {modo_resposta} | tipo: {tipo_conversa} | reply: {bool(reply_info)}")
|
| 204 |
return prompt
|
| 205 |
|
| 206 |
def gerar_resposta(self, mensagem, historico, mensagem_citada, analise, usuario, tipo_conversa, reply_info=None) -> str:
|
| 207 |
prompt = self._construir_prompt(mensagem, historico, mensagem_citada, analise, usuario, tipo_conversa, reply_info)
|
| 208 |
+
|
| 209 |
for _ in range(2):
|
| 210 |
for api in config.API_FALLBACK_ORDER:
|
| 211 |
if api not in self.apis_disponiveis:
|
|
|
|
| 228 |
logger.debug(f"Falha na API {api}: {e}")
|
| 229 |
time.sleep(1)
|
| 230 |
time.sleep(2)
|
| 231 |
+
|
| 232 |
return random.choice(["Ya, tá bom.", "Foda-se.", "Hmm...", "Caralho."])
|
| 233 |
|
| 234 |
def _chamar_mistral(self, prompt: str) -> str:
|
|
|
|
| 362 |
if not self.db.pode_usar_reset(numero):
|
| 363 |
# XINGAMENTO AUTOMÁTICO (do config.py)
|
| 364 |
return jsonify({'resposta': 'Só o boss pode usar /reset, puto. Vai sonhar.'})
|
| 365 |
+
|
| 366 |
if not confirmacao:
|
| 367 |
return jsonify({'resposta': 'Quer mesmo apagar tudo? Manda /reset de novo.'})
|
| 368 |
+
|
| 369 |
# Limpa cache
|
| 370 |
self.contexto_cache._store.clear()
|
| 371 |
+
|
| 372 |
# Reseta no banco
|
| 373 |
resultado = self.db.resetar_contexto_usuario(numero, tipo_reset)
|
| 374 |
+
|
| 375 |
return jsonify({'resposta': f"Reset feito! {resultado.get('itens_apagados',0)} itens apagados."})
|
| 376 |
|
| 377 |
def _processar_payload_indexjs(self, data: Dict[str, Any]) -> Dict[str, Any]:
|