akira / modules /API_PATCH_DETAILED.md
akra35567's picture
Upload 55 files
bbbdd24 verified
|
Raw
History Blame Contribute Delete
15.6 kB
"""
═══════════════════════════════════════════════════════════════════════
PATCH ESPECÍFICO PARA api.py β€” APLICAR LINHA POR LINHA
═══════════════════════════════════════════════════════════════════════
Este arquivo mostra as MODIFICAÇÕES EXATAS no api.py existente.
Arquivo: i:\\Isaac Quarenta\\ProgramaΓ§Γ£o\\AKIRA-SOFTEDGE\\modules\\api.py
MODIFICATIONS:
1. Adicionar imports (top do arquivo)
2. Modificar _get_user_context() (line 2311)
3. Modificar _get_history_for_llm() (line 2320+)
4. Modificar akira_endpoint() - parte de obtΓ©m histΓ³rico
═══════════════════════════════════════════════════════════════════════
"""
# ═══════════════════════════════════════════════════════════════════════
# MODIFICATION 1: ADICIONAR IMPORTS (TOP DO ARQUIVO)
# ═══════════════════════════════════════════════════════════════════════
"""
LocalizaΓ§Γ£o: PrΓ³ximo aos outros imports do modules/
ANTES:
────────────────────────────────────────────────────────────────
import json
import hashlib
import logging
from skills_registry import SkillsRegistry
...
DEPOIS (ADICIONAR ESTAS LINHAS):
────────────────────────────────────────────────────────────────
import json
import hashlib
import logging
from skills_registry import SkillsRegistry
# βœ… NOVOS IMPORTS PARA CONTEXT V2
from modules.context_manager_v2 import (
ContextManagerV2,
get_context_manager,
MessageType,
ContextType
)
from modules.listen_stream_processor import (
ListenStreamProcessor,
get_listen_processor
)
# Inicializa singletons
ctx_manager = get_context_manager()
listen_processor = get_listen_processor()
...
"""
# ═══════════════════════════════════════════════════════════════════════
# MODIFICATION 2: ATUALIZAR _get_user_context (line 2311)
# ═══════════════════════════════════════════════════════════════════════
"""
LocalizaΓ§Γ£o: api.py::_get_user_context (line 2311)
ANTES:
────────────────────────────────────────────────────────────────
def _get_user_context(self, usuario, conversation_id=None):
# πŸ”§ FIX: Usa conversation_id como chave primΓ‘ria para isolamento total
cache_key = conversation_id if conversation_id else usuario
if cache_key not in self.contexto_cache:
db_path = getattr(self.config, 'DB_PATH', 'akira.db')
db = Database(db_path)
# Passa conversation_id para o objeto Contexto para persistΓͺncia isolada
self.contexto_cache[cache_key] = Contexto(db, usuario=usuario, conversation_id=conversation_id)
return self.contexto_cache[cache_key]
DEPOIS:
────────────────────────────────────────────────────────────────
def _get_user_context(self, usuario, numero, conversation_id=None,
tipo_conversa='pv', grupo_id=None):
# πŸ”§ FIX V2: Usa novo ContextManagerV2 para isolamento robusto
# Legacy: mantΓ©m cache para compatibilidade
cache_key = conversation_id if conversation_id else usuario
if cache_key not in self.contexto_cache:
db_path = getattr(self.config, 'DB_PATH', 'akira.db')
db = Database(db_path)
self.contexto_cache[cache_key] = Contexto(db, usuario=usuario, conversation_id=conversation_id)
# NOVO: Retorna contexto isolado via ContextManagerV2
contexto_isolado = ctx_manager.obter_ou_criar_contexto(
numero=numero,
tipo_conversa=tipo_conversa,
grupo_id=grupo_id,
usuario=usuario
)
# Retorna ambos para compatibilidade backward
return {
'legacy_contexto': self.contexto_cache[cache_key], # Compatibilidade
'novo_contexto_manager': contexto_isolado,
'numero': numero,
'tipo_conversa': tipo_conversa,
'grupo_id': grupo_id,
}
NOTA: A assinatura da funΓ§Γ£o MUDA. Precisa ser atualizada
em TODOS os lugares que chamam _get_user_context()
"""
# ═══════════════════════════════════════════════════════════════════════
# MODIFICATION 3: INTEGRAR LISTEN STREAM EM akira_endpoint
# ═══════════════════════════════════════════════════════════════════════
"""
LocalizaΓ§Γ£o: api.py::akira_endpoint() - apΓ³s extrair dados (line ~1250)
ANTES (buggy):
────────────────────────────────────────────────────────────────
usuario = validate_sender_name(usuario, numero, "usuario_principal")
...
# Captura contexto aqui (BUGGY - sem isolaΓ§Γ£o)
contexto = self._get_user_context(usuario)
# HistΓ³rico SEM FILTRO (PROBLEMA!)
historico = contexto.obter_historico()
# Process LLM...
DEPOIS (robusto):
────────────────────────────────────────────────────────────────
usuario = validate_sender_name(usuario, numero, "usuario_principal")
...
# βœ… NOVO: PROCESSA VIA LISTEN STREAM
evento = {
'usuario': usuario,
'numero': numero,
'texto': mensagem,
'tipo_conversa': tipo_conversa,
'grupo_id': grupo_id,
'referenced_message_author': quoted_author_name,
'referenced_message_texto': mensagem_citada,
'referenced_message_id': data.get('message_id_citada', ''),
}
resultado_processamento = listen_processor.processar_mensagem_chegando(evento)
self.logger.info(
f"πŸ” ClassificaΓ§Γ£o Listen: {resultado_processamento['tipo_message']} | "
f"Deve processar: {resultado_processamento['deve_processar']}"
)
# βœ… SE NΓƒO FOR DIRETO, NΓƒO PROCESSA
if not resultado_processamento['deve_processar']:
self.logger.info(f"πŸ“š Mensagem contextual (escuta). NΓ£o respondendo.")
return jsonify({
'resposta': '',
'status': 'context_registered',
'tipo': 'contextual',
'modelo_usado': 'listen_stream',
'conversation_id': resultado_processamento['conversation_id']
})
# βœ… Γ‰ DIRETO: ObtΓ©m contexto ISOLADO
conversation_id = resultado_processamento['conversation_id']
contexto_data = listen_processor.obter_contexto_para_resposta(
numero=numero,
tipo_conversa=tipo_conversa,
grupo_id=grupo_id,
include_contextual=True
)
# Extrai histΓ³rico ISOLADO
historico = contexto_data['direct_messages']
# Context enriquecido com fluxo do grupo
contexto_grupo_info = contexto_data.get('grupo_flow', {})
participants = contexto_data.get('participants', [])
# Se em grupo, inclui info de participantes
if tipo_conversa == "grupo":
self.logger.info(f"πŸ‘₯ Contexto grupo: {len(participants)} participantes")
# LEGACY: obtΓ©m tambΓ©m via contexto_cache para compatibilidade
contexto = self._get_user_context(
usuario=usuario,
numero=numero,
conversation_id=conversation_id,
tipo_conversa=tipo_conversa,
grupo_id=grupo_id
)
# Process LLM...
"""
# ═══════════════════════════════════════════════════════════════════════
# MODIFICATION 4: ACEITAR NOVOS CAMPOS NO PAYLOAD
# ═══════════════════════════════════════════════════════════════════════
"""
LocalizaΓ§Γ£o: api.py::akira_endpoint() - seΓ§Γ£o data extraction (line ~1240)
ANTES:
────────────────────────────────────────────────────────────────
usuario = data.get('usuario', 'anonimo')
numero = data.get('numero', '')
mensagem = data.get('mensagem', '')
message_id = data.get('message_id', '')
tipo_conversa = data.get('tipo_conversa', 'pv')
grupo_id = data.get('grupo_id') or data.get('contexto_grupo') or ''
imagem_dados = data.get('imagem', {})
...
DEPOIS (adiciona suporte):
────────────────────────────────────────────────────────────────
usuario = data.get('usuario', 'anonimo')
numero = data.get('numero', '')
mensagem = data.get('mensagem', '')
message_id = data.get('message_id', '')
tipo_conversa = data.get('tipo_conversa', 'pv')
grupo_id = data.get('grupo_id') or data.get('contexto_grupo') or ''
# βœ… NOVOS CAMPOS PARA LISTEN STREAM
# ReferΓͺncia a outra mensagem (reply)
referenced_message_author = data.get('referenced_message_author',
data.get('quoted_author_name', ''))
referenced_message_texto = data.get('referenced_message_texto',
data.get('mensagem_citada', ''))
referenced_message_id = data.get('referenced_message_id',
data.get('message_id_citada', ''))
imagem_dados = data.get('imagem', {})
...
"""
# ═══════════════════════════════════════════════════════════════════════
# MODIFICATION 5: ATUALIZAR PAYLOAD DO RESPOSTA
# ═══════════════════════════════════════════════════════════════════════
"""
LocalizaΓ§Γ£o: api.py::akira_endpoint() - retorno jsonify (line ~1400+)
ADICIONAR CAMPO:
────────────────────────────────────────────────────────────────
return jsonify({
'resposta': resposta,
'modelo_usado': modelo,
'confidence': confidence,
'conversation_id': conversation_id, # βœ… NOVO
'tipo_message': resultado_processamento['tipo_message'], # βœ… NOVO
'participants': participants if tipo_conversa == 'grupo' else [], # βœ… NOVO
...
})
"""
# ═══════════════════════════════════════════════════════════════════════
# QUICK CHECKLIST
# ═══════════════════════════════════════════════════════════════════════
"""
ANTES DE APLICAR ESTAS MUDANÇAS:
β–‘ Verificar que context_manager_v2.py existe e estΓ‘ correto
β–‘ Verificar que listen_stream_processor.py existe e estΓ‘ correto
β–‘ Fazer BACKUP do api.py ANTES DE MODIFICAR
β–‘ Testar com um grupo de teste (nΓ£o produΓ§Γ£o)
APΓ“S APLICAR:
β–‘ Testar endpoint POST /akira com payload novo
β–‘ Testar com tipo_conversa='pv' (deve ser DIRECT)
β–‘ Testar com tipo_conversa='grupo' sem @AKIRA (deve ser CONTEXTUAL)
β–‘ Testar com tipo_conversa='grupo' com @AKIRA (deve ser DIRECT)
β–‘ Verificar logs para "πŸ” ClassificaΓ§Γ£o Listen"
β–‘ Verificar que histΓ³rico Γ© isolado por conversation_id
β–‘ Monitorar para memory leaks no context_manager (stats)
TROUBLESHOOTING:
❌ ImportError: context_manager_v2
β†’ Verificar que arquivo estΓ‘ em modules/
β†’ Verificar import path
❌ NameError: ctx_manager not defined
β†’ Verificar que get_context_manager() foi chamado no top
β†’ Verificar que imports foram adicionados
❌ Contexto ainda estÑ misturado
β†’ Verificar que listen_processor.processar_mensagem_chegando() foi integrado
β†’ Verificar que resultado_processamento['deve_processar'] Γ© respeitado
β†’ Verificar conversation_id estΓ‘ sendo passado corretamente
"""
__all__ = [
'PATCH_INSTRUCTIONS'
]