Memory Management
O módulo memory_management fornece uma interface estruturada e segura para manipular a memória de sessões de conversação. Oferece métodos organizados para armazenar, recuperar e gerenciar dados da sessão com controle rigoroso de limites e suporte a objetos Pydantic estruturados.
Visão Geral
O sistema de memória funciona como um dicionário hierárquico que permite:
- Armazenamento estruturado de dados da sessão
- Categorização automática por tipo de informação
- Validação com modelos Pydantic
- Controle de limites para evitar sobrecarga
- Operações aninhadas de qualquer profundidade
🏗️ Estrutura e Conceitos Básicos
MemoryCategories
Chaves padrão para organização da memória:
class MemoryCategories:
USER_INFO = "informacoes_usuario" # Dados pessoais do usuário
CONVERSATION_FACTS = "fatos_da_conversa" # Fatos coletados durante a conversa
WORKFLOW_PROGRESS = "progresso_workflow" # Estado de workflows em andamento
USER_PREFERENCES = "preferencias_usuario" # Preferências configuradas
CONTEXT_HINTS = "dicas_contexto" # Dicas para o LLM
As categorias acima são apenas facilitadores. Você pode criar e usar qualquer chave que faça sentido para seu caso de uso:
# Exemplos de chaves personalizadas
memory_manager.update("historico_transacoes", transacoes)
memory_manager.update("configuracoes_produto", config)
memory_manager.update("dados_integracoes.api_externa", resultado)
memory_manager.update("metricas_performance", stats)
MemoryLimitExceededException
Exceção lançada quando operações excederiam o limite de memória:
try:
memory_manager.update("dados", dados_grandes)
except MemoryLimitExceededException as e:
print(f"Limite excedido: {e.attempted_chars} chars (máx: {e.max_chars})")
🔧 Métodos Principais
get(path, default=None, model_class=None)
Recupera valores da memória com suporte a caminhos aninhados e conversão para objetos Pydantic.
Parâmetros:
path(str|list): Caminho para o valor (ex: "usuario.documento.cpf" ou ["usuario", "documento", "cpf"])default(Any): Valor padrão se não encontrar (padrão: None)model_class(Type[BaseModel]): Classe Pydantic para conversão automática (opcional)
Quando utilizar:
- Recuperar dados específicos da memória
- Converter dados para objetos estruturados
- Navegação em estruturas aninhadas
- Obter valores com fallback seguro
Resultado esperado:
- Valor encontrado no caminho especificado
- Objeto Pydantic se
model_classfornecido defaultse caminho não existe
Exemplos:
# Recuperação simples
user_name = memory_manager.get("informacoes_usuario.nome")
# Com valor padrão
telefone = memory_manager.get("informacoes_usuario.telefone", "Não informado")
# Navegação aninhada profunda
documento = memory_manager.get("informacoes_usuario.documentos.cpf.numero")
# Conversão para objeto Pydantic
from pydantic import BaseModel
class UserInfo(BaseModel):
nome: str
email: str
telefone: str
user_obj = memory_manager.get("informacoes_usuario", model_class=UserInfo)
# Retorna: UserInfo(nome="João", email="joao@email.com", telefone="11999999999")
# Lista de caminhos
status = memory_manager.get(["progresso_workflow", "cadastro", "current_step"])
update(path, value, model_class=None)
Atualiza ou insere valores na memória com validação automática de limites.
Parâmetros:
path(str|list): Caminho onde inserir o valorvalue(Any|BaseModel): Valor a ser armazenado (pode ser objeto Pydantic)model_class(Type[BaseModel]): Classe para validação antes do armazenamento (opcional)
Quando utilizar:
- Armazenar novos dados na memória
- Atualizar informações existentes
- Criar estruturas aninhadas automaticamente
- Validar dados antes do armazenamento
Resultado esperado:
Truese operação bem-sucedida- Estrutura aninhada criada automaticamente se necessário
- Dados validados e convertidos se
model_classfornecido
Erros:
MemoryLimitExceededException: Se exceder limite de memóriaValidationError: Se validação Pydantic falhar
Exemplos:
# Atualização simples
memory_manager.update("informacoes_usuario.nome", "João Silva")
# Criação de estrutura aninhada automática
memory_manager.update("usuario.documentos.cpf.numero", "123.456.789-00")
# Cria automaticamente: usuario -> documentos -> cpf -> numero
# Com objeto Pydantic
class UserData(BaseModel):
nome: str
idade: int
email: str
user = UserData(nome="Maria", idade=30, email="maria@email.com")
memory_manager.update("informacoes_usuario", user)
# Com validação
class DocumentoInfo(BaseModel):
tipo: str
numero: str
valido: bool = True
# Valida antes de armazenar
memory_manager.update(
"documentos.rg",
{"tipo": "RG", "numero": "12.345.678-9"},
model_class=DocumentoInfo
)
# Estruturas complexas
progress_data = {
"step": "validacao_documento",
"completed": ["dados_pessoais", "endereco"],
"next": "confirmacao"
}
memory_manager.update("progresso_workflow.cadastro", progress_data)
delete(path)
Remove valores da memória com navegação aninhada.
Parâmetros:
path(str|list): Caminho do valor a ser removido
Quando utilizar:
- Limpar dados desnecessários
- Remover informações sensíveis
- Resetar estado de workflows
- Limpeza seletiva da memória
Resultado esperado:
- Valor removido (se existia)
Nonese valor não existia
Exemplos:
# Remoção simples
removed_phone = memory_manager.delete("informacoes_usuario.telefone")
# Remoção aninhada
removed_doc = memory_manager.delete("usuario.documentos.cpf")
# Remoção de workflow
progress = memory_manager.delete("progresso_workflow.cadastro")
# Limpeza de categoria inteira
all_facts = memory_manager.delete("fatos_da_conversa")
merge(path, data)
Faz merge de dicionários na memória, combinando dados existentes com novos.
Parâmetros:
path(str|list): Caminho onde fazer o mergedata(Dict|BaseModel): Dados para combinar
Quando utilizar:
- Atualizar parcialmente estruturas existentes
- Combinar configurações
- Adicionar campos sem sobrescrever existentes
- Merge de objetos Pydantic
Resultado esperado:
Truese operação bem-sucedida- Dados combinados preservando valores existentes
- Novos campos adicionados aos existentes
Erros:
MemoryLimitExceededException: Se exceder limite de memória
Exemplos:
# Merge básico
existing_user = {"nome": "João", "idade": 30}
memory_manager.update("informacoes_usuario", existing_user)
new_data = {"email": "joao@email.com", "telefone": "11999999999"}
memory_manager.merge("informacoes_usuario", new_data)
# Resultado: {"nome": "João", "idade": 30, "email": "joao@email.com", "telefone": "11999999999"}
# Merge de estruturas aninhadas
workflow_data = {
"cadastro": {"step": "dados_pessoais", "completed": ["inicio"]},
"onboarding": {"step": "apresentacao"}
}
memory_manager.update("progresso_workflow", workflow_data)
update_data = {
"cadastro": {"completed": ["inicio", "dados_pessoais"]},
"tutorial": {"step": "primeiro_acesso"}
}
memory_manager.merge("progresso_workflow", update_data)
# Merge com objeto Pydantic
class ContactUpdate(BaseModel):
telefone: str
endereco: str
contact = ContactUpdate(telefone="11888888888", endereco="Rua A, 123")
memory_manager.merge("informacoes_usuario", contact)
📝 Métodos de Conveniência
Fatos da Conversa
store_conversation_fact(fact, metadata=None)
Armazena fatos importantes coletados durante a conversa.
Parâmetros:
fact(str): Fato a ser armazenadometadata(Dict): Metadados adicionais (opcional)
Quando utilizar:
- Registrar informações importantes mencionadas pelo usuário
- Manter histórico de decisões
- Documentar preferências reveladas
- Tracking de eventos da conversa
Exemplos:
# Fato simples
memory_manager.store_conversation_fact("Cliente prefere atendimento por WhatsApp")
# Com metadados
memory_manager.store_conversation_fact(
"Cliente tem urgência no processo",
metadata={"priority": "alta", "deadline": "2024-01-15"}
)
# Fatos específicos
memory_manager.store_conversation_fact(
"Cliente já possui conta em outro banco",
metadata={"banco": "Banco XYZ", "tipo_conta": "poupança"}
)
get_conversation_facts(limit=None)
Recupera fatos da conversa ordenados cronologicamente.
Parâmetros:
limit(int): Número máximo de fatos a retornar (opcional)
Exemplos:
# Todos os fatos
all_facts = memory_manager.get_conversation_facts()
# Retorna: [{"content": "fato1", "timestamp": "...", "metadata": {...}}, ...]
# Últimos 5 fatos
recent_facts = memory_manager.get_conversation_facts(limit=5)
# Processar fatos
for fact in recent_facts:
print(f"[{fact['timestamp']}] {fact['content']}")
if fact['metadata']:
print(f" Detalhes: {fact['metadata']}")
Informações do Usuário
store_user_info(key, value)
Armazena informações pessoais do usuário.
Exemplos:
# Informações básicas
memory_manager.store_user_info("nome", "João Silva")
memory_manager.store_user_info("email", "joao@email.com")
memory_manager.store_user_info("telefone", "11999999999")
# Informações estruturadas
endereco = {
"rua": "Rua das Flores, 123",
"cidade": "São Paulo",
"cep": "01234-567"
}
memory_manager.store_user_info("endereco", endereco)
# Documentos
memory_manager.store_user_info("cpf", "123.456.789-00")
memory_manager.store_user_info("rg", "12.345.678-9")
get_user_info(key=None)
Recupera informações do usuário.
Exemplos:
# Informação específica
nome = memory_manager.get_user_info("nome")
# Todas as informações
user_data = memory_manager.get_user_info()
# Retorna: {"nome": "João Silva", "email": "joao@email.com", ...}
# Com conversão para objeto
class User(BaseModel):
nome: str
email: str
telefone: str
user_obj = memory_manager.get("informacoes_usuario", model_class=User)
Progresso de Workflows
store_workflow_progress(workflow_name, step, data)
Armazena o progresso de workflows em andamento.
Parâmetros:
workflow_name(str): Nome do workflowstep(str): Etapa atualdata(Dict): Dados da etapa
Exemplos:
# Workflow de cadastro
memory_manager.store_workflow_progress(
"cadastro_cliente",
"validacao_documento",
{
"completed_steps": ["dados_pessoais", "endereco"],
"documento_enviado": True,
"documento_aprovado": False
}
)
# Workflow de onboarding
memory_manager.store_workflow_progress(
"onboarding",
"tutorial_navegacao",
{
"tutorials_completed": ["introducao", "menu_principal"],
"current_tutorial": "tutorial_navegacao",
"progress_percentage": 60
}
)
# Workflow de solicitação
memory_manager.store_workflow_progress(
"solicitacao_cartao",
"aguardando_aprovacao",
{
"tipo_cartao": "gold",
"renda_informada": 5000,
"documentos_anexados": ["comprovante_renda", "identidade"],
"protocolo": "CART-2024-001"
}
)
get_workflow_progress(workflow_name=None)
Recupera progresso de workflows.
Exemplos:
# Workflow específico
cadastro_progress = memory_manager.get_workflow_progress("cadastro_cliente")
# Retorna: {"current_step": "validacao_documento", "data": {...}, "updated_at": "..."}
# Todos os workflows
all_progress = memory_manager.get_workflow_progress()
# Verificar etapa atual
if cadastro_progress and cadastro_progress["current_step"] == "validacao_documento":
print("Cliente está na validação de documento")
🏗️ Objetos Pydantic Estruturados
Vantagens dos Objetos Pydantic
✅ Validação Automática:
class UserData(BaseModel):
nome: str
idade: int = Field(ge=0, le=120) # Entre 0 e 120 anos
email: str = Field(pattern=r'^[\w\.-]+@[\w\.-]+\.\w+$')
# Validação automática no armazenamento
try:
memory_manager.update("usuario", UserData(nome="João", idade=-5, email="invalid"))
except ValidationError as e:
print(f"Dados inválidos: {e}")
✅ Type Safety:
# IDE detecta tipos automaticamente
user: UserData = memory_manager.get("informacoes_usuario", model_class=UserData)
print(user.nome) # ✅ IDE sabe que é string
print(user.idade + 10) # ✅ IDE sabe que é int
✅ Documentação Automática:
class DocumentInfo(BaseModel):
"""Informações de documento do usuário"""
tipo: str = Field(description="Tipo do documento (CPF, RG, CNH)")
numero: str = Field(description="Número do documento")
valido: bool = Field(default=True, description="Se o documento foi validado")
data_validacao: Optional[str] = Field(description="Data da validação")
# Schema automaticamente documentado
print(DocumentInfo.model_json_schema())
✅ Conversão Automática:
# Armazenamento automático como dict
doc = DocumentInfo(tipo="CPF", numero="123.456.789-00")
memory_manager.update("documento", doc) # Converte automaticamente para dict
# Recuperação como objeto
doc_obj = memory_manager.get("documento", model_class=DocumentInfo)
print(type(doc_obj)) # <class 'DocumentInfo'>
📝 Como a Memória é Apresentada para o LLM
Conversão Automática: Dicionário → Markdown
O sistema automaticamente converte a memória estruturada em dicionário para um formato markdown legível que o LLM pode compreender facilmente.
Como funciona:
- Você organiza os dados em dicionário (usando os métodos do MemoryManager)
- O sistema converte automaticamente para markdown quando necessário
- O LLM recebe um contexto estruturado e legível
Como sua estrutura vira contexto para o LLM
Exemplos de Conversão
Exemplo 1: Dados do Usuário Simples
Entrada (Dicionário):
memory_dict = {
"informacoes_usuario": {
"nome": "João Silva",
"cpf": "123.456.789-00",
"telefone": "11999999999"
}
}
Saída (Markdown):
## Informacoes Usuario
nome: João Silva
cpf: 123.456.789-00
telefone: 11999999999
Exemplo 2: Estrutura Hierárquica
Entrada (Dicionário):
memory_dict = {
"informacoes_usuario": {
"nome": "Maria Santos",
"endereco": {
"rua": "Rua das Flores, 123",
"cidade": "São Paulo",
"cep": "01234-567",
"complemento": {
"numero": "123",
"andar": "5º andar"
}
}
}
}
Saída (Markdown):
## Informacoes Usuario
nome: Maria Santos
### Endereco
rua: Rua das Flores, 123
cidade: São Paulo
cep: 01234-567
#### Complemento
numero: 123
andar: 5º andar
Exemplo 3: Listas com Tradução Automática
Entrada (Dicionário):
memory_dict = {
"fatos_da_conversa": [
{
"content": "Cliente prefere atendimento por WhatsApp",
"timestamp": "2024-01-15T10:30:00",
"metadata": {"priority": "alta"}
},
{
"content": "Cliente tem urgência no processo",
"timestamp": "2024-01-15T10:32:00"
}
]
}
Saída (Markdown):
## Fatos Da Conversa
• Conteúdo: Cliente prefere atendimento por WhatsApp
Data/Hora: 2024-01-15T10:30:00
Informações Adicionais: {'priority': 'alta'}
• Conteúdo: Cliente tem urgência no processo
Data/Hora: 2024-01-15T10:32:00
Exemplo 4: Workflows Complexos
Entrada (Dicionário):
memory_dict = {
"progresso_workflow": {
"cadastro_cliente": {
"current_step": "validacao_documento",
"created_at": "2024-01-15T10:00:00",
"updated_at": "2024-01-15T10:45:00",
"data": {
"completed_steps": ["dados_pessoais", "endereco"],
"documento_enviado": True,
"documento_aprovado": False
}
},
"onboarding": {
"current_step": "tutorial_concluido",
"updated_at": "2024-01-15T11:00:00",
"data": {
"progress_percentage": 100,
"tutorials_completed": ["intro", "navegacao", "funcionalidades"]
}
}
}
}
Saída (Markdown):
## Progresso Workflow
### Cadastro Cliente
current_step: validacao_documento
Criado em: 2024-01-15T10:00:00
Atualizado em: 2024-01-15T10:45:00
#### Data
completed_steps: ['dados_pessoais', 'endereco']
documento_enviado: True
documento_aprovado: False
### Onboarding
current_step: tutorial_concluido
Atualizado em: 2024-01-15T11:00:00
#### Data
progress_percentage: 100
tutorials_completed: ['intro', 'navegacao', 'funcionalidades']
Exemplo 5: Lista de Strings Simples
Entrada (Dicionário):
memory_dict = {
"preferencias": {
"canais_comunicacao": ["whatsapp", "email", "telefone"],
"horarios_preferidos": ["manha", "tarde"]
}
}
Saída (Markdown):
## Preferencias
### Canais Comunicacao
- whatsapp
- email
- telefone
### Horarios Preferidos
- manha
- tarde
Regras de Apresentação para o LLM
📝 Campos Simples:
# Sua estrutura:
{"nome": "João", "cpf": "123.456.789-00"}
# Vira para o LLM:
# nome: João
# cpf: 123.456.789-00
📁 Estruturas Aninhadas:
# Sua estrutura:
{
"endereco": {
"rua": "Rua das Flores",
"numero": "123"
}
}
# Vira para o LLM:
# ## Endereco
# rua: Rua das Flores
# numero: 123
📋 Listas de Objetos:
# Sua estrutura:
{
"fatos_da_conversa": [
{"content": "Cliente prefere WhatsApp", "timestamp": "2024-01-15"},
{"content": "Tem urgência", "timestamp": "2024-01-15"}
]
}
# Vira para o LLM:
# ## Fatos Da Conversa
# • Conteúdo: Cliente prefere WhatsApp
# Data/Hora: 2024-01-15
#
# • Conteúdo: Tem urgência
# Data/Hora: 2024-01-15
Tradução Automática
Alguns campos são automaticamente traduzidos para o LLM:
content→ "Conteúdo"timestamp→ "Data/Hora"created_at→ "Criado em"updated_at→ "Atualizado em"
Exemplo Prático Completo
Como você organiza:
memory_manager.store_user_info("nome", "Carlos Silva")
memory_manager.store_conversation_fact("Cliente quer conta empresarial")
memory_manager.store_workflow_progress("abertura_conta", "documentos", {
"cnpj": "12.345.678/0001-90",
"documentos_enviados": ["contrato_social"]
})
Como o LLM recebe:
## Informacoes Usuario
nome: Carlos Silva
## Fatos Da Conversa
• Conteúdo: Cliente quer conta empresarial
Data/Hora: 2024-01-15T14:30:00
## Progresso Workflow
### Abertura Conta
current_step: documentos
Atualizado em: 2024-01-15T14:31:00
#### Data
cnpj: 12.345.678/0001-90
documentos_enviados: ['contrato_social']
Organize bem sua estrutura de dados - a forma como você armazena na memória é exatamente como o LLM vai interpretar o contexto. Estruturas bem organizadas resultam em contexto mais claro para o LLM tomar decisões!