Gerar recordações

Com o Memory Bank da Agent Platform, é possível criar memórias de longo prazo com base nas conversas entre o usuário e seu agente. Esse processo acontece automaticamente quando acionado, extraindo informações valiosas para interações futuras.

Neste documento, explicamos como a geração de memórias funciona, como personalizar a extração de memórias com temas e como acionar solicitações de geração de memórias.

Para informações sobre como configurar seu ambiente, consulte Configurar o Memory Bank.

Noções básicas sobre a geração de dados de memória

O Memory Bank extrai memórias de dados de origem e organiza memórias para uma coleção específica (definida por um scope) adicionando, atualizando e removendo memórias ao longo do tempo.

Quando você aciona a geração de dados de memória, o Memory Bank realiza as seguintes operações:

  • Extração: extrai informações sobre o usuário das conversas dele com o agente. Somente as informações que corresponderem a pelo menos um dos temas de memória da sua instância serão mantidas.

  • Consolidação: identifica se as recordações atuais com o mesmo escopo devem ser excluídas ou atualizadas com base nas informações extraídas. O banco de memória verifica se as novas recordações não são duplicadas ou contraditórias antes de mesclá-las com as existentes. Se as memórias existentes não se sobrepuserem às novas informações, uma nova memória será criada.

Algoritmo de geração de dados de memória

É possível inspecionar as etapas intermediárias da geração de memórias e ver como uma memória muda em várias solicitações usando revisões de memória. Cada revisão inclui a saída intermediária da etapa de extração (extracted_memories) e a etapa final de consolidação (fact) para cada solicitação de geração de memória.

list(client.memory_banks.memories.revisions.list(
  name="projects/.../locations/.../reasoningEngines/.../memories/.../revisions/..."))

"""
[
  MemoryRevision(
    name="projects/123/locations/us-central1/reasoningEngines/456/memories/789/revision/456",
    fact="This is my updated fact",
    extracted_memories=[
      IntermediateExtractedMemory(
        fact='This is the output of extraction for a single request.'
      ),
    ],
    ...
  ),
  MemoryRevision(
    name="projects/123/locations/us-central1/reasoningEngines/456/memories/789/revision/123",
    fact="This is my original fact",
    extracted_memories=[
      IntermediateExtractedMemory(
        fact='This is my original fact.'
      ),
    ],
    ...
  )
]
"""

Temas das memórias

Os "tópicos de memória" identificam quais informações o Memory Bank considera significativas e, portanto, devem ser mantidas como memórias geradas. O Memory Bank é compatível com dois tipos de temas de memória:

  • Tópicos gerenciados: o rótulo e as instruções são definidos pelo Memory Bank. Basta informar o nome do tópico gerenciado. Exemplo:

    Dicionário

    memory_topic = {
        "managed_memory_topic": {
            "managed_topic_enum": "USER_PERSONAL_INFO"
        }
    }
    

    Com base em classes

    from agentplatform.types import ManagedTopicEnum
    from agentplatform.types import MemoryBankCustomizationConfigMemoryTopic as MemoryTopic
    from agentplatform.types import MemoryBankCustomizationConfigMemoryTopicManagedMemoryTopic as ManagedMemoryTopic
    
    memory_topic = MemoryTopic(
        managed_memory_topic=ManagedMemoryTopic(
            managed_topic_enum=ManagedTopicEnum.USER_PERSONAL_INFO
        )
    )
    
  • Tópicos personalizados: o rótulo e as instruções são definidos por você ao configurar sua instância do Memory Bank. Eles serão usados no comando para a etapa de extração do Memory Bank. Exemplo:

    Dicionário

    memory_topic = {
        "custom_memory_topic": {
            "label": "business_feedback",
            "description": """Specific user feedback about their experience
            at the coffee shop. This includes opinions on drinks, food,
            pastries, ambiance, staff friendliness, service speed,
            cleanliness, and any suggestions for improvement."""
        }
    }
    

    Com base em classes

    from agentplatform.types import MemoryBankCustomizationConfigMemoryTopic as MemoryTopic
    from agentplatform.types import MemoryBankCustomizationConfigMemoryTopicCustomMemoryTopic as CustomMemoryTopic
    
    memory_topic = MemoryTopic(
        custom_memory_topic=CustomMemoryTopic(
            label="business_feedback",
            description="""Specific user feedback about their experience at
            the coffee shop. This includes opinions on drinks, food,
            pastries, ambiance, staff friendliness, service speed,
            cleanliness, and any suggestions for improvement."""
        )
    )
    

    Ao usar tópicos personalizados, também é recomendável fornecer com poucos exemplos (few-shot) para demonstrar como as recordações devem ser extraídas da conversa.

Por padrão, o Memory Bank persiste todos os seguintes tópicos gerenciados:

  • Informações do usuário (USER_PERSONAL_INFO): informações significativas sobre o usuário, como nomes, relacionamentos, hobbies e datas importantes. Por exemplo, "Trabalho no Google" ou "Meu aniversário de casamento é em 31 de dezembro".

  • Preferências do usuário (USER_PREFERENCES): preferências, estilos ou padrões declarados ou implícitos. Por exemplo, "Prefiro o assento do meio".

  • Principais eventos de conversa e resultados de tarefas (KEY_CONVERSATION_DETAILS): Marcos ou conclusões importantes no diálogo. Por exemplo, "Reservei passagens de ida e volta entre JFK e SFO. Vou sair em 1º de junho de 2025 e voltar em 7 de junho de 2025".

  • Instruções explícitas para lembrar / esquecer (EXPLICIT_INSTRUCTIONS): informações que o usuário pede explicitamente para o agente lembrar ou esquecer. Por exemplo, se o usuário disser "Lembre-se de que eu uso principalmente Python", o banco de memória vai gerar uma memória como "Eu uso principalmente Python".

Isso equivale a usar o seguinte conjunto de tópicos sobre memória gerenciada:

Dicionário

  memory_topics = [
      {"managed_memory_topic": {"managed_topic_enum": "USER_PERSONAL_INFO"}},
      {"managed_memory_topic": {"managed_topic_enum": "USER_PREFERENCES"}},
      {"managed_memory_topic": {"managed_topic_enum": "KEY_CONVERSATION_DETAILS"}},
      {"managed_memory_topic": {"managed_topic_enum": "EXPLICIT_INSTRUCTIONS"}},
  ]

Com base em classes

from agentplatform.types import ManagedTopicEnum
from agentplatform.types import MemoryBankCustomizationConfigMemoryTopic as MemoryTopic
from agentplatform.types import MemoryBankCustomizationConfigMemoryTopicManagedMemoryTopic as ManagedMemoryTopic

memory_topics = [
  MemoryTopic(
      managed_memory_topic=ManagedMemoryTopic(
          managed_topic_enum=ManagedTopicEnum.USER_PERSONAL_INFO)),
  MemoryTopic(
      managed_memory_topic=ManagedMemoryTopic(
          managed_topic_enum=ManagedTopicEnum.USER_PREFERENCES)),
  MemoryTopic(
      managed_memory_topic=ManagedMemoryTopic(
          managed_topic_enum=ManagedTopicEnum.KEY_CONVERSATION_DETAILS)),
  MemoryTopic(
      managed_memory_topic=ManagedMemoryTopic(
          managed_topic_enum=ManagedTopicEnum.EXPLICIT_INSTRUCTIONS)),
]

Se quiser personalizar os temas que o Memory Bank mantém, defina os temas de memória na sua configuração de personalização ao configurar o Memory Bank.

Como usar metadados durante a consolidação

É possível anexar metadados às recordações geradas. Os metadados permitem armazenar informações estruturadas (strings, duplos, booleanos ou carimbos de data/hora) junto com um fato de memória. Isso é útil para filtrar ou gerenciar os ciclos de vida das recordações.

Dicionário

import datetime

client.memory_banks.memories.generate(
    ...,
    config={
        "metadata": {
            "my_string_key": {"string_value": "my_string_value"},
            "my_double_key": {"double_value": 123.456},
            "my_boolean_key": {"bool_value": True},
            "my_timestamp_key": {
                "timestamp_value": datetime.datetime(
                    2027, 1, 1, 12, 30, 00, tzinfo=datetime.timezone.utc
                )
            }
        },
        "metadata_merge_strategy": "MERGE"
    },
)

Com base em classes

import datetime

from agentplatform import types

client.memory_banks.memories.generate(
    ...,
    config=types.GenerateMemoriesConfig(
        metadata={
            "my_string_key": types.MemoryMetadataValue(string_value="my_string_value"),
            "my_double_key": types.MemoryMetadataValue(double_value=123.456),
            "my_boolean_key": types.MemoryMetadataValue(bool_value=True),
            "my_timestamp_key": types.MemoryMetadataValue(
                timestamp_value=datetime.datetime(
                    2027, 1, 1, 12, 30, 00, tzinfo=datetime.timezone.utc
                )
            ),
        },
        metadata_merge_strategy=types.MemoryMetadataMergeStrategy.MERGE,
    )
)

Ao usar um metadata_merge_strategy, você controla como os novos metadados interagem com as memórias atuais durante a consolidação:

  • MERGE: (padrão) combina os novos metadados com os existentes. Se uma chave já existir, o novo valor vai substituir o antigo.

  • OVERWRITE: substitua os metadados das recordações atualizadas pelos novos metadados.

  • REQUIRE_EXACT_MATCH: restringe a consolidação a recordações que têm exatamente os mesmos metadados da solicitação. Se uma recordação não tiver os mesmos metadados, ela não poderá ser consolidada e não será atualizada.

Gerar recordações para um subconjunto de temas

Por padrão, a geração de memória extrai dados de todos os temas de memória que você configurou ao criar a instância do Banco de Memórias. Para uma solicitação GenerateMemories específica, é possível restringir a extração a um subconjunto de tópicos configurados. Para configurar os temas permitidos, use o campo allowed_topics.

Dicionário

client.memory_banks.memories.generate(
    ...,
    config={
        "allowed_topics": [
            {"managed_memory_topic": "USER_PERSONAL_INFO"},
            {"custom_memory_topic_label": "business_feedback"}
        ]
    },
)

Com base em classes

from agentplatform import types

client.memory_banks.memories.generate(
    ...,
    config=types.GenerateMemoriesConfig(
        allowed_topics=[
            types.MemoryTopicId(
                managed_memory_topic=types.ManagedTopicEnum.USER_PERSONAL_INFO
            ),
            types.MemoryTopicId(
                custom_memory_topic_label="business_feedback"
            )
        ]
    )
)

Acionando a geração de dados de memória

É possível acionar a geração de memórias usando um dos seguintes métodos:

  • GenerateMemories: ingere dados no Memory Bank e aciona a geração de memória imediatamente. Esse método é útil quando você quer gerar memórias em um momento específico, como no final de uma sessão ou em intervalos regulares dentro de uma sessão.
  • IngestEvents: ingere dados no Memory Bank continuamente e deixe que ele processe quando os critérios de acionamento forem atendidos. Esse método é útil quando você tem um fluxo contínuo de eventos e quer que o Memory Bank processe automaticamente o armazenamento em buffer e acione a geração de memória com base no volume ou no tempo. Para mais informações, consulte Ingerir eventos.

A geração de memória extrai o contexto principal das conversas de origem e o combina com as memórias atuais do mesmo escopo. Por exemplo, é possível criar memórias no nível da sessão usando um escopo como {"user_id": "123", "session_id": "456"}. Memórias com o mesmo escopo podem ser consolidadas e recuperadas juntas.

GenerateMemories é uma operação de longa duração. Quando a operação for concluída, o GenerateMemoriesOperation vai conter uma lista de recordações geradas, se houver:

GenerateMemoriesOperation(
  name="projects/.../locations/.../reasoningEngines/.../operations/...",
  done=True,
  response=GenerateMemoriesResponse(
    generatedMemories=[
      GenerateMemoriesResponseGeneratedMemory(
        memory=Memory(
          "name": "projects/.../locations/.../reasoningEngines/.../memories/..."
        ),
        action="CREATED",
      ),
      GenerateMemoriesResponseGeneratedMemory(
        memory=Memory(
          "name": "projects/.../locations/.../reasoningEngines/.../memories/..."
        ),
        action="UPDATED",
      ),
      GenerateMemoriesResponseGeneratedMemory(
        memory=Memory(
          "name": "projects/.../locations/.../reasoningEngines/.../memories/..."
        ),
        action="DELETED",
      ),
    ]
  )
)

Cada memória gerada inclui a action que foi realizada:

  • CREATED: indica que uma nova recordação foi adicionada, representando um conceito novo que não foi capturado pelas recordações atuais.

  • UPDATED: indica que uma memória foi atualizada, o que acontece se ela cobrir conceitos semelhantes aos das informações extraídas recentemente. O fato da memória pode ser atualizado com novas informações ou permanecer o mesmo.

  • DELETED: indica que a memória atual foi excluída porque as informações dela eram contraditórias em relação às novas informações extraídas da conversa.

Para memórias de CREATED ou UPDATED, use GetMemories para recuperar o conteúdo completo da memória. Recuperar DELETED memórias resulta em um erro 404.

Gerando memórias em segundo plano

GenerateMemories é uma operação de longa duração. Por padrão, client.memory_banks.memories.generate é uma função de bloqueio que pesquisa a operação até que ela seja concluída. Executar a geração de memória como uma operação de bloqueio é útil quando você quer inspecionar manualmente as memórias geradas ou notificar os usuários finais sobre quais memórias foram geradas.

No entanto, para agentes de produção, geralmente é melhor executar a geração de memória em segundo plano como um processo assíncrono. Na maioria dos casos, o cliente não precisa usar a saída da execução atual, então não é necessário incorrer em latência adicional esperando uma resposta. Se você quiser que a geração de memória seja executada em segundo plano, defina wait_for_completion como False:

client.memory_banks.memories.generate(
    ...,
    config={
        "wait_for_completion": False
    }
)

Como alternativa a chamar GenerateMemories de forma assíncrona, use IngestEvents, que separa a ingestão de eventos da geração de memória e processa eventos em segundo plano por padrão.

Fontes de dados

Há várias maneiras de fornecer dados de origem para a geração de memória:

Quando você fornece eventos diretamente no payload ou usa sessões, as informações são extraídas da conversa e consolidadas com as memórias existentes. Se você quiser apenas extrair informações dessas fontes de dados, desative a consolidação:

client.memory_banks.memories.generate(
    ...
    config={
        "disable_consolidation": True
    }
)

Usar eventos no payload como a fonte de dados

Use direct_contents_source quando quiser gerar recordações usando eventos fornecidos diretamente na carga útil. Informações significativas são extraídas desses eventos e consolidadas com as informações atuais do mesmo escopo. Essa abordagem pode ser usada se você estiver usando um armazenamento de sessão diferente das sessões da Agent Platform.

Dicionário

Os eventos precisam incluir dicionários Content.

events =  [
  {
    "content": {
      "role": "user",
      "parts": [
        {"text": "I work with LLM agents!"}
      ]
    }
  }
]

client.memory_banks.memories.generate(
    name=memory_bank.name,
    direct_contents_source={
      "events": EVENTS
    },
    # For example, `scope={"user_id": "123"}`.
    scope=SCOPE,
    config={
        "wait_for_completion": True
    }
)

Substitua:

  • SCOPE: um dicionário que representa o escopo das memórias geradas. Por exemplo, {"session_id": "MY_SESSION"}. Somente memórias com o mesmo escopo são consideradas para consolidação.

Com base em classes

Os eventos precisam incluir objetos Content.

from google import genai
from agentplatform import types

events = [
  types.GenerateMemoriesRequestDirectContentsSourceEvent(
    content=genai.types.Content(
      role="user",
      parts=[
        genai.types.Part.from_text(text="I work with LLM agents!")
      ]
    )
  )
]

client.memory_banks.memories.generate(
    name=memory_bank.name,
    direct_contents_source={
      "events": events
    },
    # For example, `scope={"user_id": "123"}`.
    scope=SCOPE,
    config={
        "wait_for_completion": True
    }
)

Substitua:

  • SCOPE: um dicionário que representa o escopo das recordações geradas. Por exemplo, {"session_id": "MY_SESSION"}. Somente memórias com o mesmo escopo são consideradas para consolidação.

Usar as sessões da Agent Platform como fonte de dados

Com as sessões, o Memory Bank usa eventos de sessão como a conversa de origem para a geração de memória.

Para definir o escopo das memórias geradas, o Memory Bank extrai e usa o ID do usuário da sessão por padrão. Por exemplo, o escopo das recordações é armazenado como {"user_id": "123"} se o user_id da sessão for "123". Você também pode fornecer um scope diretamente, o que substitui o uso do user_id da sessão como escopo.

Dicionário

client.memory_banks.memories.generate(
  name=memory_bank.name,
  vertex_session_source={
      # For example, projects/.../locations/.../reasoningEngines/.../sessions/...
      "session": "SESSION_NAME"
  },
  # Optional when using Sessions. Defaults to {"user_id": session.user_id}.
  scope=SCOPE,
  config={
      "wait_for_completion": True
  }
)

Substitua:

  • SESSION_NAME: o nome da sessão totalmente qualificado.

  • (Opcional) SCOPE: um dicionário que representa o escopo das memórias geradas. Por exemplo, {"session_id": "MY_SESSION"}. Somente as memórias com o mesmo escopo são consideradas para consolidação. Se não for fornecido, {"user_id": session.user_id} será usado.

Com base em classes

from agentplatform import types

client.memory_banks.memories.generate(
  name=memory_bank.name,
  vertex_session_source=types.GenerateMemoriesRequestVertexSessionSource(
      # For example, projects/.../locations/.../reasoningEngines/.../sessions/...
      session="SESSION_NAME"
  ),
  # Optional when using Sessions. Defaults to {"user_id": session.user_id}.
  scope=SCOPE,
  config={
      "wait_for_completion": True
  }
)

Se quiser, você pode fornecer um período indicando quais eventos na sessão devem ser incluídos. Se não forem fornecidos, todos os eventos na sessão serão incluídos.

Dicionário

import datetime

client.memory_banks.memories.generate(
  name=memory_bank.name,
  vertex_session_source={
      "session": "SESSION_NAME",
      # Extract memories from the last hour of events.
      "start_time": datetime.datetime.now(tz=datetime.timezone.utc) - datetime.timedelta(seconds=24 * 60),
      "end_time": datetime.datetime.now(tz=datetime.timezone.utc)
  },
  scope=SCOPE
)

Com base em classes

import datetime

from agentplatform import types

client.memory_banks.memories.generate(
  name=memory_bank.name,
  vertex_session_source=types.GenerateMemoriesRequestVertexSessionSource(
      session="SESSION_NAME",
      # Extract memories from the last hour of events.
      start_time=datetime.datetime.now(tz=datetime.timezone.utc) - datetime.timedelta(seconds=24 * 60),
      end_time=datetime.datetime.now(tz=datetime.timezone.utc)
  ),
  scope=SCOPE
)

Consolidar memórias pré-extraídas

Como alternativa ao processo de extração automática do banco de memória, você pode fornecer diretamente memórias pré-extraídas. As memórias de fonte direta serão consolidadas com as memórias atuais do mesmo escopo. Isso pode ser útil quando você quer que seu agente ou um human-in-the-loop seja responsável por extrair memórias, mas ainda quer aproveitar a consolidação do Memory Bank para garantir que não haja memórias duplicadas ou contraditórias.

client.memory_banks.memories.generate(
    name=memory_bank.name,
    direct_memories_source={"direct_memories": [{"fact": "FACT"}]},
    scope=SCOPE
)

Substitua:

  • FACT: o fato pré-extraído que precisa ser consolidado com as memórias existentes. É possível fornecer até cinco fatos pré-extraídos em uma lista como esta:

    {"direct_memories": [{"fact": "fact 1"}, {"fact": "fact 2"}]}
    
  • SCOPE: um dicionário que representa o escopo das memórias geradas. Por exemplo, {"session_id": "MY_SESSION"}. Somente memórias com o mesmo escopo são consideradas para consolidação.

Como usar a entrada multimodal

É possível extrair recordações de entradas multimodais. No entanto, as memórias são extraídas apenas de texto, arquivos inline e dados de arquivos no conteúdo de origem. Todo o outro conteúdo, incluindo chamadas e respostas de função, é ignorado ao gerar recordações.

As recordações podem ser extraídas de imagens, vídeos e áudios fornecidos pelo usuário. Se o contexto fornecido pela entrada multimodal for considerado pelo Memory Bank como significativo para interações futuras, uma memória textual poderá ser criada, incluindo informações extraídas da entrada. Por exemplo, se o usuário fornecer uma imagem de um golden retriever com o texto "Este é meu cachorro", o Banco de memórias vai gerar uma memória como "Meu cachorro é um golden retriever".

Por exemplo, é possível fornecer uma imagem e o contexto dela no payload:

Dicionário

with open(file_name, "rb") as f:
    inline_data = f.read()

events =  [
  {
    "content": {
      "role": "user",
      "parts": [
        {"text": "This is my dog"},
        {
          "inline_data": {
            "mime_type": "image/jpeg",
            "data": inline_data
          }
        },
        {
          "file_data": {
            "file_uri": "gs://cloud-samples-data/generative-ai/image/dog.jpg",
            "mime_type": "image/jpeg"
          }
        },
      ]
    }
  }
]

Com base em classes

from google import genai
from agentplatform import types

with open(file_name, "rb") as f:
    inline_data = f.read()

events = [
  types.GenerateMemoriesRequestDirectContentsSourceEvent(
    content=genai.types.Content(
      role="user",
      parts=[
        genai.types.Part.from_text(text="This is my dog"),
        genai.types.Part.from_bytes(
          data=inline_data,
          mime_type="image/jpeg",
        ),
        genai.types.Part.from_uri(
          file_uri="gs://cloud-samples-data/generative-ai/image/dog.jpg",
          mime_type="image/jpeg",
        )
      ]
    )
  )
]

A seguir

Guia

Saiba como buscar recordações geradas e enviadas.

Guia

Saiba como configurar o Banco de Memória.

Guia

Saiba como inspecionar revisões de memória.