Phase 14 - Lesson 09
Hybrid Memory: Vector + Graph + KV (Mem0)
Mem0 (Chhikara et al., 2025) trata a memória como três armazenamentos em paralelo — vetorial para similaridade semântica, KV para busca rápida de fatos e grafo para raciocínio de entidade-relacionamento. Uma camada de pontuação funde os três na recuperação. Este é o padrão de produção de 2026 para memória externa.
Tipo: Build Linguagens: Python (stdlib) Pré-requisitos: Phase 14 · 07 (MemGPT), Phase 14 · 08 (Letta Blocks) Tempo: ~75 minutos
Objetivos de Aprendizado
- Explicar por que um único armazenamento (apenas vetorial, apenas grafo, apenas KV) é insuficiente para a memória do agente.
- Nomear os três armazenamentos paralelos do Mem0 e o que cada um otimiza.
- Descrever a pontuação de fusão do Mem0 — relevância, importância, recência — e por que é uma soma ponderada, não uma hierarquia.
- Implementar uma memória simples de três armazenamentos em stdlib com um
add()que grava em todos os três e umsearch()que funde os resultados.
O Problema
Um único armazenamento é incorreto para uma de três classes de consulta:
- Similaridade semântica — "o que discutimos sobre agent drift na semana passada?" O vetorial vence; KV e grafo falham.
- Busca de fatos — "qual é o número de telefone do usuário?" O KV vence; o vetorial é um desperdício, o grafo é exagero.
- Raciocínio de relacionamento — "quais clientes compartilham a mesma entidade de cobrança?" O grafo vence; vetorial e KV não conseguem responder.
Agentes em produção emitem todas as três classes em uma única sessão. Uma memória de armazenamento único estará sempre errada para duas delas. A contribuição do Mem0 é conectar as três sob uma única interface de add/search com uma função de pontuação que as funde.
O Conceito
Três armazenamentos em paralelo
Mem0 (arXiv:2504.19413, abril de 2025) no add(text, user_id, metadata):
- Extrai fatos candidatos a partir do texto (uma etapa orientada por LLM).
- Grava cada fato no armazenamento vetorial (embedding) para busca semântica.
- Grava cada fato no armazenamento KV indexado por
(user_id, fact_type, entity)para busca O(1). - Grava cada fato no armazenamento de grafo (Mem0g) como arestas tipadas para consultas de relacionamento.
No search(query, user_id):
- O armazenamento vetorial retorna os top-k pelo cosseno de embedding.
- O armazenamento KV retorna correspondências diretas indexadas pela consulta derivada
(user_id, type, entity). - O armazenamento de grafo retorna o subgrafo alcançável a partir das entidades da consulta.
- Uma camada de pontuação funde os três.
Pontuação de fusão
score = w_relevance * relevance(q, record)
+ w_importance * importance(record)
+ w_recency * recency(record)
- Relevância — cosseno vetorial, correspondência exata de KV, peso de caminho de grafo.
- Importância — marcada no momento da gravação ou aprendida (alguns fatos importam mais: nomes, IDs, políticas).
- Recência — decaimento exponencial ao longo do tempo desde a última gravação ou leitura.
Os pesos são ajustados por produto. Maior w_recency para agentes de chat; maior w_importance para agentes de conformidade (compliance); maior w_relevance para agentes de busca.
Mem0g e raciocínio temporal
O Mem0g adiciona um detector de conflitos. Quando um novo fato contradiz uma aresta existente, a aresta existente é marcada como inválida, mas não é excluída. Consultas temporais ("qual era a cidade do usuário em março?") percorrem o subgrafo válido naquele momento.
Este é o comportamento de nível de conformidade que o padrão de invalidação do Letta generaliza.
Números de benchmark
O artigo do Mem0 relata (2025):
- LoCoMo (memória de conversa longa): 91.6
- LongMemEval (memória episódica de longo horizonte): 93.4
- BEAM 1M (benchmark de memória de 1 milhão de tokens): 64.1
Linhas de base de comparação (LLM de contexto completo de 128k, armazenamento vetorial plano, KV plano) perdem por 10+ pontos. Os benchmarks por si só não justificam a escolha — o formato operacional sim —, mas os números mostram que o design de fusão não é um erro de arredondamento.
Taxonomia de escopo
O Mem0 divide a memória por escopo:
- Memória de usuário (User memory) — persiste entre sessões, indexada em
user_id. - Memória de sessão (Session memory) — persiste dentro de uma thread de conversa.
- Memória de agente (Agent memory) — estado da instância por agente.
Cada gravação escolhe um escopo. A recuperação pode consultar entre escopos com pesos por escopo. Misturar escopos sem critério é a receita para incidentes do tipo "o assistente contou a Alice sobre o projeto do Bob".
Onde este padrão falha
- Desvio de embedding (Embedding drift). Os resultados vetoriais que parecem corretos nas primeiras cem consultas degradam conforme o corpus cresce. Adicione re-embedding periódico dos top-N registros mais usados.
- Crescimento desordenado do esquema KV (KV schema creep).
(user_id, type, entity)parece simples até que cada equipe adicione seu própriotype. Faça uma auditoria do conjunto de tipos trimestralmente. - Explosão de grafo (Graph explosion). Um extrator ruidoso adiciona 50 arestas por mensagem. Limite as gravações de grafo por chamada
add; descarte arestas de baixa confiança.
Build It
code/main.py implementa o padrão de três armazenamentos na biblioteca padrão (stdlib):
VectorStore— similaridade ingênua de sobreposição de tokens como um substituto para embeddings.KVStore— dict indexado por(user_id, fact_type, entity).GraphStore— arestas tipadas (sujeito, relação, objeto, válido).Mem0— fachada de alto nível comadd(),search(), pontuação de fusão e recuperação ciente de escopo.- Uma simulação passo a passo de uma conversa com múltiplos usuários e sessões.
Execute:
python3 code/main.py
A saída mostra três caminhos de recuperação separados mais os top-k fundidos. Altere os pesos de pontuação no topo de main() e assista à classificação mudar.
Use It
- Mem0 (Apache 2.0) — pronto para produção. Hospete por conta própria com Postgres + Qdrant + Neo4j, ou use a nuvem gerenciada.
- Letta — núcleo de três níveis (core/recall/archival); traga seus próprios backends vetoriais e de grafos.
- Zep — alternativa comercial com KG temporal e extração de fatos.
- Builds personalizados — para quando você precisa de controle exato sobre o extrator (conformidade) ou pesos de fusão (agentes de voz onde a recência domina).
Ship It
outputs/skill-hybrid-memory.md gera uma estrutura de memória de três armazenamentos com um pontuador de fusão, taxonomia de escopo e invalidação temporal integrados.
Exercises
- Substitua a similaridade vetorial simulada por um modelo de embedding real (sentence-transformers, Ollama, OpenAI embeddings). Meça o recall@10 em uma conversa longa sintética. A classificação sofre desvio ao longo de 1000 gravações?
- Adicione uma consulta temporal:
search(query, as_of=timestamp). Retorne apenas registros válidos na data/hora especificada ou antes dela. Qual armazenamento precisa de mais trabalho? - Implemente um detector de conflitos: se um fato recebido contradiz uma aresta do grafo, invalide a aresta antiga e registre ambos. Teste com "usuário mora em Berlim" -> "usuário mora em Lisboa."
- Adapte o pontuador de fusão para incluir uma dimensão de feedback do usuário (
user_feedback, ex: polegar para cima nos registros recuperados). Como evitar manipulações (ex: o agente retornar apenas registros que ele já curtiu)? - Leia os documentos do Mem0 (
docs.mem0.ai). Adapte a simulação para chamadas de clientemem0. Compare a qualidade da recuperação nas mesmas 20 consultas de teste.
Key Terms
| Term | What people say | What it actually means |
|---|---|---|
| Hybrid memory | "Vetor mais grafo mais KV" | Três armazenamentos gravados em paralelo, fundidos na recuperação |
| Fact extraction | "Ingestão de memória" | Etapa do LLM que divide o texto em tuplas (entidade, relação, fato) |
| Fusion scoring | "Classificação de relevância" | Soma ponderada de relevância, importância e recência |
| Scope | "Namespace de memória" | user / session / agent — determina quem vê o quê |
| Mem0g | "Grafo de memória" | Arestas tipadas com validade temporal para consultas de relacionamento |
| Temporal invalidation | "Exclusão lógica (soft delete)" | Marcar arestas contraditas como inválidas; nunca excluir |
| Embedding drift | "Rot de recuperação (retrieval rot)" | A qualidade do vetor degrada conforme o corpus cresce; faça re-embedding periodicamente |
Further Reading
- Chhikara et al., Mem0 (arXiv:2504.19413) — o artigo original
- Mem0 docs — API de produção, SDKs, nuvem gerenciada
- Packer et al., MemGPT (arXiv:2310.08560) — o predecessor de contexto virtual
- Letta, Memory Blocks blog — o design irmão de três camadas