# 🔗 Análise: Bancos Vetoriais + Grafos de Relacionamento ## 📋 Resumo Executivo Este documento analisa a implementação atual do sistema de memória e propõe a integração de **grafos de relacionamento** com o **banco de dados vetorial (Qdrant)** existente para melhorar significativamente a capacidade dos agentes de IA em encontrar, classificar e contextualizar informações. --- ## 🔍 Situação Atual ### Arquitetura Existente O sistema **Antigravity Brain** atualmente utiliza: 1. **Banco Vetorial (Qdrant)**: - Armazena embeddings de memórias e conhecimento - Busca por similaridade semântica via `SearchMemoryTool` - Integrado via **Mem0** (`src/memory/wrapper.py`) 2. **Metadados Básicos**: - `source`: origem da memória (agent_execution, telegram_chat) - `type`: tipo de informação (insight, learned_insight) - `chat_id`: ID do chat (quando aplicável) - `user_id`: escopo do projeto 3. **Limitações Identificadas**: - ❌ Não captura **relacionamentos** entre entidades - ❌ Não permite navegação entre memórias relacionadas - ❌ Busca apenas por similaridade semântica (pode perder contexto estrutural) - ❌ Dificuldade em rastrear cadeias causais (problema → solução → agente) --- ## 🎯 Benefícios da Integração Vetor + Grafo ### 1. **Busca Híbrida Mais Poderosa** **Cenário Atual:** ``` Usuário: "Mostre problemas relacionados ao Zabbix" → Busca vetorial encontra memórias sobre "Zabbix" → Mas não mostra relacionamentos: qual problema levou a qual solução, qual agente resolveu, etc. ``` **Com Grafo:** ``` Usuário: "Mostre problemas relacionados ao Zabbix" → Busca vetorial inicial encontra memórias sobre "Zabbix" → Navegação de grafo expande: Problema → Solução → Agente → Outros problemas similares → Retorna contexto completo com relacionamentos ``` ### 2. **Redução de Alucinações** Grafos fornecem **estrutura explícita** que reduz a necessidade de o LLM "inventar" conexões: - ✅ Relacionamentos documentados explicitamente - ✅ Contexto estruturado disponível para o LLM - ✅ Validação de conexões antes de inferências ### 3. **Rastreabilidade e Auditoria** Com grafos, é possível: - Rastrear **cadeias de decisões**: "Como chegamos nesta solução?" - Identificar **padrões**: "Problemas similares foram resolvidos da mesma forma?" - Mapear **responsabilidades**: "Qual agente resolveu problemas de tipo X?" ### 4. **Classificação Melhorada** Agentes podem usar grafos para: - Classificar com base em relacionamentos existentes - Identificar novos padrões ao conectar memórias desconectadas - Criar taxonomias dinâmicas baseadas em estrutura --- ## 🏗️ Arquitetura Proposta ### Opção 1: Neo4j + Qdrant (Recomendado) ``` ┌─────────────────┐ │ Qdrant (Vector)│ ← Busca Semântica │ Embeddings │ └────────┬─────────┘ │ │ Sync IDs ▼ ┌─────────────────┐ │ Neo4j (Graph) │ ← Relacionamentos │ Nodes & Edges │ └─────────────────┘ ``` **Vantagens:** - ✅ Neo4j tem suporte nativo para vector search (Neo4j 5.x+) - ✅ Cypher é poderoso para queries de relacionamento - ✅ Ecossistema maduro e bem documentado - ✅ Integração Python via `neo4j` driver **Estrutura do Grafo:** ```cypher // Exemplo de estrutura (:Memory)-[:RELATES_TO]->(:Memory) (:Memory)-[:SOLVES]->(:Problem) (:Memory)-[:CREATED_BY]->(:Agent) (:Problem)-[:LEADS_TO]->(:Solution) (:Agent)-[:RESOLVED]->(:Problem) ``` ### Opção 2: Qdrant com Metadata Relacional (Mais Simples) Manter Qdrant, mas enriquecer metadados com referências: ```python metadata = { "source": "agent_execution", "type": "insight", "related_memory_ids": ["mem_123", "mem_456"], # IDs relacionados "entity_type": "solution", # solution, problem, rule, etc. "entity_relationships": { "solves": "prob_zabbix_001", "created_by": "arthur_mendes" } } ``` **Vantagens:** - ✅ Sem nova infraestrutura - ✅ Implementação mais rápida - ✅ Mantém tudo no Qdrant **Desvantagens:** - ❌ Queries de relacionamento são limitadas - ❌ Não aproveita otimizações de grafos para navegação ### Opção 3: PostgreSQL com pgvector + Relações (Híbrido) PostgreSQL com extensão `pgvector` + tabelas relacionais: ```sql CREATE TABLE memories ( id UUID PRIMARY KEY, content TEXT, embedding vector(1536), metadata JSONB ); CREATE TABLE memory_relationships ( from_memory_id UUID REFERENCES memories(id), to_memory_id UUID REFERENCES memories(id), relationship_type VARCHAR(50), created_at TIMESTAMP ); ``` **Vantagens:** - ✅ Tudo em um banco - ✅ PostgreSQL já é preferido no projeto (ver `database_standards.md`) - ✅ Suporte a JSONB para flexibilidade --- ## 💡 Casos de Uso Específicos ### Caso 1: Rastreamento de Problemas **Problema Atual:** ``` Agente busca: "problemas de Zabbix" → Encontra memórias isoladas → Não consegue conectar: problema A → solução B → implementação C ``` **Com Grafo:** ```cypher MATCH (p:Problem {category: "Zabbix"})-[:SOLVED_BY]->(s:Solution) -[:IMPLEMENTED_BY]->(a:Agent) RETURN p, s, a, collect(s.related_problems) as related ``` ### Caso 2: Classificação Inteligente **Problema Atual:** ``` Router precisa classificar: "Precisamos melhorar a performance do Zabbix" → Classifica como "Infra Engineering" (correto) → Mas não sabe que existem 3 problemas similares já resolvidos ``` **Com Grafo:** ``` 1. Busca vetorial encontra memórias sobre "Zabbix performance" 2. Grafo identifica: problemas similares → crew que resolveu → padrões 3. Router classifica com contexto: "Infra Engineering, histórico: 3 casos similares resolvidos" ``` ### Caso 3: Aprendizado Incremental **Problema Atual:** ``` Novo insight salvo: "Solução X funciona para problemas de tipo Y" → Fica isolado, não conecta com problemas anteriores ``` **Com Grafo:** ``` 1. Ao salvar novo insight, LLM extrai entidades 2. Sistema cria nós: Problem, Solution, Agent 3. Conecta com nós existentes por similaridade vetorial 4. Agora: buscar "problemas tipo Y" retorna solução X automaticamente ``` --- ## 🔧 Implementação Recomendada (Neo4j) ### Fase 1: Setup Inicial 1. **Adicionar Neo4j ao docker-compose.yml**: ```yaml neo4j: image: neo4j:5.15 container_name: antigravity_neo4j ports: - "7474:7474" # Browser - "7687:7687" # Bolt environment: - NEO4J_AUTH=neo4j/password - NEO4J_PLUGINS=["apoc", "graph-data-science"] volumes: - neo4j_data:/data networks: - antigravity_net ``` 2. **Atualizar requirements.txt**: ```txt neo4j neo4j-vector-search # Se usar Neo4j vector search nativo ``` ### Fase 2: Criar Graph Wrapper Criar `src/memory/graph_wrapper.py`: ```python from neo4j import GraphDatabase import logging class GraphWrapper: """Gerencia relacionamentos entre memórias no Neo4j""" def __init__(self): self.driver = GraphDatabase.driver( os.getenv("NEO4J_URI", "bolt://localhost:7687"), auth=(os.getenv("NEO4J_USER", "neo4j"), os.getenv("NEO4J_PASSWORD", "password")) ) def create_memory_node(self, memory_id: str, content: str, metadata: dict): """Cria nó de memória""" with self.driver.session() as session: session.run(""" CREATE (m:Memory { id: $memory_id, content: $content, type: $type, source: $source, created_at: datetime() }) """, memory_id=memory_id, content=content, type=metadata.get("type"), source=metadata.get("source")) def link_memories(self, from_id: str, to_id: str, relationship: str): """Cria relacionamento entre memórias""" with self.driver.session() as session: session.run(""" MATCH (a:Memory {id: $from_id}) MATCH (b:Memory {id: $to_id}) CREATE (a)-[r:RELATES_TO {type: $rel_type}]->(b) """, from_id=from_id, to_id=to_id, rel_type=relationship) def find_related_memories(self, memory_id: str, depth: int = 2): """Encontra memórias relacionadas via grafo""" with self.driver.session() as session: result = session.run(""" MATCH path = (m:Memory {id: $id})-[*1..2]-(related:Memory) RETURN related, length(path) as distance ORDER BY distance LIMIT 10 """, id=memory_id) return [record["related"] for record in result] ``` ### Fase 3: Integrar com SearchMemoryTool Modificar `SearchMemoryTool` para busca híbrida: ```python def _run(self, query: str) -> str: # 1. Busca vetorial inicial (como antes) vector_results = client.search(query, limit=5) # 2. Para cada resultado, buscar relacionamentos no grafo enriched_results = [] graph = GraphWrapper() for result in vector_results: memory_id = result['id'] related = graph.find_related_memories(memory_id, depth=2) enriched_results.append({ 'memory': result, 'related': related, 'context': f"Found {len(related)} related memories" }) return format_results(enriched_results) ``` ### Fase 4: Extração Automática de Relacionamentos Ao salvar memória, usar LLM para extrair entidades e relacionamentos: ```python def _run(self, fact: str) -> str: # Salvar no Mem0 (como antes) memory_id = client.add(fact, metadata={...}) # Extrair relacionamentos com LLM extraction_prompt = f""" Analise este fato e extraia: 1. Tipo de entidade (Problem, Solution, Rule, Agent, etc.) 2. Relacionamentos com outras memórias conhecidas 3. Entidades mencionadas Fato: {fact} Retorne JSON: {{ "entity_type": "...", "relationships": [ {{"type": "solves", "target": "problema_zabbix_001"}}, {{"type": "created_by", "target": "arthur_mendes"}} ] }} """ # Usar LLM para extrair relationships = llm_call(extraction_prompt) # Criar nós e relacionamentos no Neo4j graph.create_memory_node(memory_id, fact, metadata) for rel in relationships: graph.link_memories(memory_id, rel['target'], rel['type']) return "Successfully saved to memory with relationships." ``` --- ## 📊 Comparação de Opções | Critério | Neo4j | Qdrant Metadata | PostgreSQL | |----------|-------|-----------------|------------| | **Busca Vetorial** | Nativa (5.x+) | Nativa | pgvector | | **Navegação de Grafo** | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ | | **Complexidade Setup** | Média | Baixa | Baixa | | **Performance Queries** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | | **Custo Infra** | +1 container | 0 | 0 | | **Manutenibilidade** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | --- ## 🎯 Recomendação Final **Implementação Gradual:** 1. **Curto Prazo (1-2 semanas)**: - Implementar **Opção 2** (Qdrant Metadata) para validar conceito - Adicionar campos `related_memory_ids` e `entity_type` aos metadados - Modificar `SearchMemoryTool` para considerar relacionamentos 2. **Médio Prazo (1 mês)**: - Avaliar necessidade de upgrade para **Neo4j** (se relacionamentos ficarem complexos) - Implementar extração automática de relacionamentos com LLM 3. **Longo Prazo (2-3 meses)**: - Migrar para **Neo4j** se métricas mostrarem benefício - Criar dashboard de visualização de relacionamentos - Implementar queries avançadas (pattern matching, path finding) --- ## 🔗 Referências - [Neo4j Vector Search Documentation](https://neo4j.com/docs/cypher-manual/current/indexes-for-vector-search/) - [IBM: Vector Databases](https://www.ibm.com/topics/vector-database) - [Microsoft: Azure Cosmos DB AI Graph](https://learn.microsoft.com/en-us/azure/cosmos-db/gen-ai/cosmos-ai-graph) - [InforChannel: Neo4j Pesquisa Vetorial](https://inforchannel.com.br/2023/08/22/neo4j-pesquisa-vetorial-com-solucoes-de-ia-generativa-e-anexada-a-banco-de-dados-grafos/) --- **Documento criado em:** 2025-01-XX **Autor:** Análise Técnica - Sistema Antigravity Brain **Status:** Proposta para Revisão