Spaces:
Running
""" βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 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:
- Adicionar imports (top do arquivo)
- Modificar _get_user_context() (line 2311)
- Modificar _get_history_for_llm() (line 2320+)
- 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' ]