""" ═══════════════════════════════════════════════════════════════════════ ARQUITETURA VISUAL DA SOLUÇÃO ═══════════════════════════════════════════════════════════════════════ """ # ═══════════════════════════════════════════════════════════════════════ # 🏗️ ARQUITETURA GERAL # ═══════════════════════════════════════════════════════════════════════ ARQUITETURA = """ 🌐 DISCORD / WHATSAPP / TELEGRAM | | ┌─────────────────────┐ │ discord-ts/ │ │ APIClient.ts │ │ (Node.js) │ └──────────┬──────────┘ | (POST /akira + novos campos) | ┌──────────▼──────────┐ │ AKIRA-SOFTEDGE │ │ api.py POST /akira│ ◄─ AQUI INTEGRA └──────────┬──────────┘ | ┌─────────────────────────┼─────────────────────────┐ | | | ▼ ▼ ▼ ┌────────┐ ┌──────────────────┐ ┌──────────────┐ │ DADOS │ │ ListenStream │ │ Log/Stats │ │BÁSICOS │ │ Processor ◄─────┼────┐ │ │ └────────┘ └──────────┬───────┘ │ └──────────────┘ | | Classifica | como DIRECT │ ou CONTEXTUAL │ | │ ┌──────────▼─────────┐ │ │ ContextManagerV2 │◄─┘ │ (Singleton) │ └──────────┬─────────┘ | ┌─────────────────────┼─────────────────────┐ | | | ▼ ▼ ▼ ┌────────────┐ ┌──────────┐ ┌─────────────┐ │ Context │ │ Context │ │ Cache & │ │ Isaac │ │ Stefânio │ │ Cleanup │ │ (DIRECT) │ │(CONTEXT) │ │ Thread │ └────────────┘ │ │ └─────────────┘ ├─ msg1 @AKIRA │ ├─ msg2 │ ├─ msg3 @AKIRA │ │(CONTEXTUAL) │ └─ conv_id_hash1 │ └─ conv_id_hash2 │ | ┌──────────────┼──────────────┐ │ │ │ ▼ ▼ ▼ [ISOLATED] [NO CONTAMINATION] [THREAD-SAFE] FLUXO DETALHADO: ════════════════════════════════════════════════════════════════ Entrada: ┌─────────────────────────────────────────────────────────────┐ │ POST /akira │ │ { │ │ "usuario": "Isaac", │ │ "numero": "202391978787009", │ │ "texto": "@AKIRA qual é a capital?", │ │ "tipo_conversa": "grupo", │ │ "grupo_id": "g_abc123", │ │ "referenced_message_author": null │ │ } │ └──────────────────────┬────────────────────────────────────┘ │ ▼ LISTEN STREAM PROCESSOR listen_processor.processar_mensagem_chegando() │ ┌───────────────┼───────────────┐ │ │ │ STEP1 STEP2 STEP3 Extract Classify Register Dados Mensagem │ │ │ ▼ ▼ ▼ usuario Detecta @AKIRA ctx_manager numero (DIRECT) adiciona texto SEM @AKIRA mensagem tipo (CONTEXTUAL) grupo_id │ ▼ DECISION: deve_processar? │ ┌───────────┴───────────┐ │ │ SIM NÃO (DIRECT) (CONTEXTUAL) │ │ ▼ ▼ OBTER CONTEXTO APENAS ISOLADO POR REGISTRA conversation_id NÃO RESPONDE │ ▼ HISTÓRICO FILTRADO ├─ Apenas mensagens │ direcionadas │ a AKIRA └─ Com conversation_id isolado │ ▼ LLM CHAIN Gera resposta │ ▼ RESPOSTA AKIRA ISOLAÇÃO DE CONTEXTO - EXEMPLO REAL: ════════════════════════════════════════════════════════════════ Grupo "g_projeto": Isaac + Stefânio + João Timeline: ───────────────────────────────────────────────────────────── T1: Isaac "Qual é a capital de PT?" ├─ Detecta: conversation_id_isaac_1 ├─ Tipo: DIRECT (@AKIRA não foi mencionado, mas é PV context) ├─ Adiciona: ctx.direct_messages └─ Processa: ✅ SIM → AKIRA responde "Lisboa" T2: Stefânio "Bacano" ├─ Detecta: conversation_id_stefanio_1 ├─ Tipo: CONTEXTUAL (grupo, sem @AKIRA) ├─ Adiciona: ctx.contextual_messages ├─ Processa: ❌ NÃO └─ AKIRA NÃO responde, apenas escuta T3: João "Mas Portugal é bonito?" ├─ Detecta: conversation_id_joao_1 ├─ Tipo: CONTEXTUAL ├─ Adiciona: ctx.contextual_messages └─ Processa: ❌ NÃO T4: Isaac "Qual é a capital de FR?" ├─ Detecta: conversation_id_isaac_1 (MESMO) ├─ Tipo: DIRECT ├─ Adiciona: ctx.direct_messages ├─ Histórico obtido: │ - msg1: "Qual é a capital de PT?" │ - msg2: "Qual é a capital de FR?" │ - ❌ NÃO inclui: Stefânio "Bacano" │ - ❌ NÃO inclui: João "Mas Portugal..." └─ Processa: ✅ SIM → AKIRA responde "Paris" T5: Stefânio "@AKIRA também quer saber a capital da Itália?" ├─ Detecta: conversation_id_stefanio_1 (MESMO) ├─ Tipo: DIRECT (@AKIRA mencionado) ├─ Muda tipo: Agora é DIRECT (primeira vez Stefânio @ Akira) ├─ Adiciona: ctx.direct_messages ├─ Histórico obtido: │ - msg1: "Bacano" (contextual, ignored) │ - msg2: "@AKIRA também quer saber..." │ - ❌ NÃO inclui: Isaac's messages (outro user!) └─ Processa: ✅ SIM → AKIRA responde "Roma" RESULTADO FINAL: ──────────────────────────────────────────────────────────── ISAAC's context_manager[conversation_id_isaac_1]: ├─ DIRECT messages: 2 │ ├─ "Qual é a capital de PT?" │ └─ "Qual é a capital de FR?" ├─ CONTEXTUAL messages: 0 └─ ✅ Isolado: SEM contamination de Stefânio/João STEFÂNIO's context_manager[conversation_id_stefanio_1]: ├─ DIRECT messages: 1 │ └─ "@AKIRA também quer saber..." ├─ CONTEXTUAL messages: 1 │ └─ "Bacano" └─ ✅ Isolado: SEM contamination de Isaac/João JOÃO's context_manager[conversation_id_joao_1]: ├─ DIRECT messages: 0 ├─ CONTEXTUAL messages: 1 │ └─ "Mas Portugal é bonito?" └─ ✅ Isolado: SEM contamination de Isaac/Stefânio GRUPO context (shared understanding): ├─ Participants: [Isaac, Stefânio, João] ├─ Topics: [capital, Portugal, França, Itália] └─ ✅ Entendimento amplo SEM misturar respostas """ print(ARQUITETURA) # ═══════════════════════════════════════════════════════════════════════ # 🔄 COMPONENTES: ANTES vs DEPOIS # ═══════════════════════════════════════════════════════════════════════ COMPONENTES = """ COMPONENTE 1: MESSAGE OBJECT ════════════════════════════════════════════════════════════════ ANTES (apenas dados brutos): ┌──────────────────┐ │ id: msg_123 │ │ texto: "Hi" │ │ usuario: Isaac │ │ timestamp: 123 │ └──────────────────┘ DEPOIS (com metadados completos): ┌──────────────────────────────────────┐ │ id: msg_123 │ │ texto: "Hi" │ │ usuario: Isaac │ │ numero: 202391978787009 │ │ tipo: MessageType.DIRECT │ ◄─ NOVO │ timestamp: 123 │ │ conversation_id: conv_hash_123 │ ◄─ NOVO │ context_type: ContextType.GROUP │ ◄─ NOVO │ quoted_message_id: msg_100 │ ◄─ NOVO │ quoted_author: "João" │ ◄─ NOVO │ is_reply_to_akira: False │ ◄─ NOVO │ is_akira_message: False │ ◄─ NOVO │ relevance_score: 0.95 │ ◄─ NOVO (0.0-1.0) │ related_users: [Isaac, João] │ ◄─ NOVO │ topic_hint: "capital Portugal" │ ◄─ NOVO └──────────────────────────────────────┘ COMPONENTE 2: CONVERSATION CONTEXT ════════════════════════════════════════════════════════════════ ANTES (tudo junto, sem isolação): ┌────────────────────────────────────┐ │ User Context (Isaac) │ │ ├─ msg1: "qual capital PT?" │ │ ├─ msg2: "Bacano" (Stefânio) ❌ │ │ ├─ msg3: "qual capital FR?" │ │ ├─ msg4: "Bacano" (João) ❌ │ │ └─ msg5: "valeu AKIRA" │ │ PROBLEMA: Tudo junto! │ └────────────────────────────────────┘ DEPOIS (separado por tipo): ┌────────────────────────────────────┐ │ ConversationContext (Isaac) │ │ conversation_id: hash_xyz │ │ │ │ DIRECT_MESSAGES (respostas): │ │ ├─ msg1: "@AKIRA qual capital PT?" │ │ ├─ msg3: "@AKIRA qual capital FR?" │ │ └─ msg5: "@AKIRA valeu!" │ │ │ │ CONTEXTUAL_MESSAGES (escuta): │ │ ├─ msg_ctx1: "Bacano" (Stefânio) │ │ └─ msg_ctx2: "Mas Portugal..." ✅ │ │ │ │ RESULTADO: Isolado e limpo! │ └────────────────────────────────────┘ COMPONENTE 3: LISTEN STREAM PROCESSOR ════════════════════════════════════════════════════════════════ ANTES (sem classificação): ┌──────────────────────────────────┐ │ Entrada: texto + usuario │ │ Saída: apenas registra no DB │ │ Lógica: nenhuma │ └──────────────────────────────────┘ DEPOIS (com inteligência): ┌───────────────────────────────────────────────┐ │ ListenStreamProcessor │ │ │ │ processar_mensagem_chegando(evento) │ │ ├─ Extrai: usuario, numero, texto, ... │ │ │ │ │ ├─ Classifica: │ │ │ ├─ Menciona @AKIRA? → DIRECT │ │ │ ├─ Reply a AKIRA? → DIRECT │ │ │ ├─ Em grupo sem mention? → CONTEXTUAL │ │ │ └─ Em PV? → DIRECT (sempre) │ │ │ │ │ ├─ Registra ao ctx_manager │ │ │ │ │ └─ Retorna: │ │ ├─ deve_processar: bool │ │ ├─ tipo_message: enum │ │ ├─ conversation_id: str │ │ └─ contexto_grupo: dict │ │ │ │ obter_contexto_para_resposta() │ │ └─ Retorna histórico ISOLADO │ └───────────────────────────────────────────────┘ COMPONENTE 4: CONTEXT MANAGER V2 ════════════════════════════════════════════════════════════════ ANTES (Dictionary simples): ┌────────────────────────┐ │ self.contexto_cache │ │ { │ │ "Isaac": Context() │ │ "João": Context() │ │ } │ │ PROBLEMA: Sem isolação │ │ por conversation_id │ └────────────────────────┘ DEPOIS (Singleton robusto): ┌──────────────────────────────────────┐ │ ContextManagerV2 (Singleton) │ │ │ │ self.contexts { │ │ "hash_isaac_pv": Context(), │ │ "hash_isaac_grupo_1": Context(), │ │ "hash_stefanio_grupo_1": Context()│ │ "hash_reply_chain_1": Context(), │ │ } │ │ │ │ ├─ Determinístico (sempre mesmo hash)│ │ ├─ Thread-safe (RLock) │ │ ├─ Cache inteligente (TTL) │ │ ├─ Cleanup automático (daemon) │ │ └─ Escalável (1000+ contextos) │ └──────────────────────────────────────┘ """ print(COMPONENTES) # ═══════════════════════════════════════════════════════════════════════ # 📊 DIFERENÇAS DE BEHAVIOR # ═══════════════════════════════════════════════════════════════════════ BEHAVIOR = """ CENÁRIO: Isaac + Stefânio + AKIRA no Grupo "Discussão" ANTES (Buggy): ──────────────────────────────────────────────────────────────── Isaac: "@AKIRA qual é a capital de Portugal?" Stefânio: "Bacano" Isaac: "@AKIRA valeu!" AKIRA's Memory (MISTURADO): ├─ Isaac: "qual é a capital de Portugal?" ├─ Stefânio: "Bacano" ├─ Isaac: "valeu!" └─ Responde com mix de contextos → ERRADO ❌ Quando Stefânio pergunta após: Stefânio: "@AKIRA qual é a capital de FR?" AKIRA's Memory (AINDA MISTURADO): ├─ Isaac: "qual é a capital de Portugal?" ├─ Stefânio: "Bacano" ├─ Isaac: "valeu!" ├─ Stefânio: "qual é a capital de FR?" └─ Responde considerando mensagens de Isaac → CONFUNDE ❌ DEPOIS (Robusto): ──────────────────────────────────────────────────────────────── Isaac: "@AKIRA qual é a capital de Portugal?" Stefânio: "Bacano" Isaac: "@AKIRA valeu!" ISAAC's Memory (ISOLADO): ├─ "@AKIRA qual é a capital de Portugal?" ├─ "@AKIRA valeu!" └─ Responde com APENAS contexto Isaac → PERFEITO ✅ STEFÂNIO's Memory (ISOLADO): ├─ "Bacano" (contextual, não processa) └─ Não contamina histórico direto ✅ Quando Stefânio pergunta após: Stefânio: "@AKIRA qual é a capital de FR?" STEFÂNIO's Memory (ISOLADO): ├─ "@AKIRA qual é a capital de FR?" └─ Responde com APENAS contexto Stefânio → PERFEITO ✅ ISAAC's Memory (INTACTO): ├─ "@AKIRA qual é a capital de Portugal?" ├─ "@AKIRA valeu!" └─ Não contamina com Stefânio → SEGURO ✅ """ print(BEHAVIOR) __all__ = ['ARQUITETURA', 'COMPONENTES', 'BEHAVIOR']