Vous pouvez utiliser Memory Bank pour générer des profils structurés, qui sont des structures de données avec des schémas statiques renseignés et mis à jour à l'aide de LLM. En définissant un schéma fixe, vous vous assurez que vos agents ont un accès immédiat et à faible latence aux informations évolutives, sans avoir besoin d'opérations de recherche coûteuses pendant une session.
Pour suivre les étapes décrites dans ce guide, vous devez d'abord suivre les étapes de la section Configurer Memory Bank.
Présentation
L'utilisation de profils structurés avec votre agent garantit que les informations extraites (comme les piles techniques ou les préférences d'un utilisateur) sont disponibles rapidement, de manière succincte et dans un format cohérent. Par exemple, vous pouvez récupérer des profils qui incluent des contenus tels que :
MemoryProfile(
profile={
"technical_stacks": "ADK, Python",
"preferred_language": "Python",
"tone_preference": "Succinct"
},
schema_id="user-profile"
)
Les profils structurés sont optimisés pour une récupération à faible latence, car le travail de curation des informations est effectué au moment de la génération. Ils sont parfaits pour initialiser une interaction entre un agent et un utilisateur.
Comprendre les profils de mémoire structurés
Les profils structurés sont générés à l'aide des mêmes méthodes (GenerateMemories et IngestEvents) que celles que vous utilisez pour les souvenirs en langage naturel. Une fois que vous avez défini un schéma, Memory Bank essaie automatiquement de générer des profils correspondant à votre schéma à l'aide des sources de données fournies.
Lorsque vous utilisez des profils structurés, Memory Bank effectue les opérations suivantes lors de la génération de la mémoire :
- Extraction : extrait de la source de données les informations et le contexte qui correspondent au schéma. Seules les informations correspondant au schéma seront extraites. Vous pouvez inspecter les informations et le contexte extraits à l'aide des révisions de la mémoire.
- Consolidation : met à jour (si nécessaire) les champs existants dans le profil. Un LLM déterminera comment mettre à jour le contenu existant en fonction des informations et du contexte nouvellement extraits. Si le champ n'existe pas déjà dans le profil, la consolidation sera ignorée et le champ sera mis à jour directement avec les informations extraites.
Les profils sont isolés en fonction de l'scope (comme {"user_id": "123"}) que vous avez fourni lors de l'ingestion des données dans la banque de mémoire. Pour chaque schéma et chaque champ d'application, la banque de mémoire gère un seul profil comme source de vérité. Un profil généré est composé d'une ou de plusieurs instances Memory. Chaque instance Memory représente un seul champ du profil que vous pouvez utiliser pour inspecter les métadonnées et l'historique des révisions du champ, par exemple :
Memory(
create_time=datetime.datetime(...),
memory_type=<MemoryType.STRUCTURED_PROFILE: 'STRUCTURED_PROFILE'>,
name='projects/.../locations/.../reasoningEngines/.../memories/...',
scope={
'user_id': '123'
},
structured_content=MemoryStructuredContent(
data={
'language_preference': 'Java'
},
schema_id='user-profile'
),
update_time=datetime.datetime(...),
expire_time=datetime.datetime(...),
metadata={...}
)
Définition du schéma
Les profils générés par Memory Bank s'alignent sur les schémas définis sur votre instance Memory Bank. Vous pouvez définir plusieurs schémas de profil indépendants. Chaque schéma doit avoir un ID unique. Notez que l'ajout ou la mise à jour d'un schéma n'entraîne pas le remplissage rétroactif des profils à partir des informations mémorisées antérieures.
Console
Pour ajouter ou modifier des schémas de profil sur une instance Memory Bank autonome dans la console Google Cloud (nécessite aiplatform.reasoningEngines.update pour enregistrer les modifications) :
Dans la console Google Cloud , accédez à la page Memory Bank d'Agent Platform, puis cliquez sur votre instance Memory Bank.
Cliquez sur Schémas dans la barre d'action (ou dans la section Génération de l'onglet Configuration).
Cliquez sur Ajouter un schéma pour créer un schéma avec un identifiant unique, ou cliquez sur l'en-tête d'une fiche de schéma existante pour la développer.
Définissez ou modifiez les champs du schéma à l'aide de la vue Simple ou JSON, puis cliquez sur Enregistrer.
SDK Agent Platform
Vous pouvez utiliser un modèle pydantic pour définir les champs que vous souhaitez que Memory Bank extraie et conserve. Exemple :
from pydantic import BaseModel, Field
from typing import Literal
class UserProfile(BaseModel):
name: str = Field(
description="Name of the user.")
technical_stack: str = Field(
description="Comma-separated list tools or languages used by the user.")
primary_goal: str = Field(
description="The main objective the user is pursuing.")
expertise_level: str = Field(
description="Current skill level (e.g., Junior, Senior).")
job_status: Literal['unemployed', 'part_time', 'full_time', 'student'] = Field(
description="The job status of the individual")
Importez le schéma dans Memory Bank lorsque vous créez ou mettez à jour votre instance Memory Bank :
schema_config = {
"id": "user-profile",
"memory_schema": UserProfile.model_json_schema()
}
memory_bank = client.memory_banks.create(
managed_semantic_memory_config={
"structured_memory_configs": [
{
"schema_configs": [schema_config]
}
]
}
)
Par défaut, Memory Bank extrait les informations mémorisées en langage naturel. Vous pouvez désactiver la génération de mémoire en langage naturel si vous souhaitez que Memory Bank ne génère que des profils :
memory_bank = client.memory_banks.create(
managed_semantic_memory_config={
"structured_memory_configs": [
{
"schema_configs": [schema_config]
}
],
# Optional: Turn off natural language memories.
"unstructured_memory_configs": [
{"disable_natural_language_memories": True}
]
}
)
Génération de profils
Vous déclenchez la génération d'informations mémorisées structurées en fournissant un historique des conversations (événements) aux méthodes GenerateMemories ou IngestEvents. Comme pour les souvenirs en langage naturel, Memory Bank utilise des LLM pour extraire des informations utiles des sources de données et les consolider avec les souvenirs existants.
Exemple
L'exemple suivant décrit la génération d'un profil de mémoire à l'aide du schéma défini précédemment.
Dans le premier ensemble d'événements envoyés à Memory Bank pour le champ d'application {"user_id": "123"}, l'utilisateur indique qu'il travaille avec des agents ADK :
client.memory_banks.memories.generate(
name=memory_bank.name,
scope={"user_id": "123"},
direct_contents_source={
"events": [
{"content": {
"parts": [{
"text": "Can you help me build an ADK agent that organizes my daily tasks?"}]}}]
}
)
La banque de mémoire extrait "ADK" pour le champ technical_stack du schéma. Aucun autre champ n'est renseigné, car l'événement ingéré ne contient pas d'informations pertinentes pour le reste du schéma. Comme il s'agit de la première interaction pour ce champ d'application, la consolidation est ignorée et le profil est initialisé avec cette valeur initiale.
result = client.memory_banks.memories.retrieve_profiles(
name=memory_bank.name,
scope={"user_id": "123"},
)
"""
Returns:
RetrieveProfilesResponse(
profiles={
'user-profile': MemoryProfile(
profile={
'technical_stack': 'ADK'
},
schema_id='user-profile'
)
}
)
"""
Dans l'ensemble d'événements suivant envoyé à Memory Bank, l'utilisateur indique qu'il est étudiant et qu'il code principalement en Python :
client.memory_banks.memories.generate(
name=memory_bank.name,
scope={"user_id": "123"},
direct_contents_source={
"events": [
{"content": {
"parts": [
{"text": "Do you have any career recommendations for students that specialize in Python?"}]}}]
}
)
Memory Bank extrait de l'interaction à la fois"Python " et le statut d'étudiant. Le fragment technical_stack est consolidé, en ajoutant "Python" à l'entrée "ADK" existante. Le système remplit le champ job_status, qui était vide, avec l'énumération "student" et ignore l'étape de consolidation.
result = client.memory_banks.memories.retrieve_profiles(
name=memory_bank.name,
scope=scope
)
"""
Returns:
RetrieveProfilesResponse(
profiles={
'user-profile': MemoryProfile(
profile={
'technical_stack': 'ADK, Python',
'job_status': 'student'
},
schema_id='user-profile'
)
}
)
"""
Récupération du profil
Une fois généré, vous pouvez récupérer le profil consolidé pour un champ d'application spécifique à l'aide de la méthode RetrieveProfiles. Cette opération renvoie les données les plus récentes mappées à votre schéma.
result = client.memory_banks.memories.retrieve_profiles(
name=memory_bank.name,
scope={"user_id": "123"},
)
# Accessing the data
for profile in result.profiles.values():
print(profile)
# Output: {'technical_stack': 'ADK, Python', 'job_status': 'student', ...}
Inspection du profil
En arrière-plan, un profil est composé de souvenirs individuels de type STRUCTURED_PROFILE. Chaque champ de votre schéma est mappé à une seule mémoire par champ d'application, ce qui offre une observabilité précise.
Bien que RetrieveProfiles soit la méthode principale pour récupérer des profils en production, vous pouvez inspecter des souvenirs individuels dans la consoleGoogle Cloud ou avec le SDK Agent Platform pour auditer l'évolution du profil :
- Métadonnées au niveau du champ : affichez et mettez à jour la valeur TTL (Time To Live) et la valeur
Memory.metadataspécifiques pour chaque champ du profil. Historique des révisions : suivez la traçabilité d'un champ pour afficher les valeurs historiques et le contexte de conversation spécifique qui a déclenché chaque modification.
Console
Dans la console Google Cloud , ouvrez votre instance autonome sur la page Banque de mémoire ou votre agent déployé sur la page Déploiements, puis sélectionnez l'onglet Mémoires.
Sélectionnez Structuré, puis choisissez des valeurs pour toutes les clés du champ d'application cible (ou appliquez un filtre de champ d'application dans Non structuré et cliquez sur Rechercher dans les mémoires structurées). Les lignes de profil correspondantes affichent les éléments Schéma, Type, Contenu, Créé et Mis à jour.
Cliquez sur Afficher sur une ligne de profil pour ouvrir le panneau Détails de la mémoire, qui affiche le chip de champ d'application, un lien vers le schéma, les faits de mémoire individuels (avec Afficher les révisions pour chaque fait) et le fichier JSON du profil consolidé.
SDK Agent Platform
Utilisez RetrieveMemories pour récupérer les souvenirs contenant des fragments du profil d'un utilisateur. Par défaut, RetrieveMemories ne récupère que les souvenirs en langage naturel. Demandez donc explicitement les souvenirs STRUCTURED_PROFILE :
client.memory_banks.memories.retrieve(
name="...",
scope={"user_id": "123"},
config={
"memory_types": ["STRUCTURED_PROFILE"]
}
)
"""
Returns:
[RetrieveMemoriesResponseRetrievedMemory(
memory=Memory(
create_time=datetime.datetime(...),
memory_type=<MemoryType.STRUCTURED_PROFILE: 'STRUCTURED_PROFILE'>,
name='projects/.../locations/.../reasoningEngines/.../memories/...',
scope={
'user_id': '123'
},
structured_content=MemoryStructuredContent(
data={
'technical_stack': 'ADK, Python'
},
schema_id='user'
),
update_time=datetime.datetime(...)
)
)]
"""
Ensuite, récupérez l'historique des révisions d'un fragment de profil structuré pour inspecter l'évolution du champ de profil au fil du temps et le contexte de chaque modification :
for retrieved_memory in list(results):
list(client.memory_banks.memories.revisions.list(
name=retrieved_memory.memory.name
))
"""
Returns:
[MemoryRevision(
create_time=datetime.datetime(...),
expire_time=datetime.datetime(...),
extracted_memories=[
IntermediateExtractedMemory(
context='The user indicated that they have expertise in Python when asking about career options.',
structured_data={
'technical_stack': 'Python'
}
),
],
name='projects/.../locations/.../reasoningEngines/.../memories/.../revisions/...',
structured_data={
'technical_stack': 'ADK, Python'
}
),
MemoryRevision(
create_time=datetime.datetime(...),
expire_time=datetime.datetime(...),
extracted_memories=[
IntermediateExtractedMemory(
context='The user indicated that they need help building an ADK agent',
structured_data={
'technical_stack': 'ADK'
}
),
],
name='projects/.../locations/.../reasoningEngines/.../memories/.../revisions/...',
structured_data={
'technical_stack': 'ADK'
}
)]
"""