Mit Memory Bank können Sie strukturierte Profile generieren. Das sind Datenstrukturen mit statischen Schemas, die mit LLMs gefüllt und aktualisiert werden. Durch die Definition eines festen Schemas haben Ihre Agenten sofortigen Zugriff mit geringer Latenz auf sich entwickelnde Informationen, ohne dass während einer Sitzung teure Suchvorgänge erforderlich sind.
Wenn Sie dieser Anleitung folgen möchten, sollten Sie zuerst die Schritte unter Für Memory Bank einrichten ausführen.
Übersicht
Wenn Sie strukturierte Profile mit Ihrem Agenten verwenden, sind extrahierte Informationen wie die technischen Stacks oder Präferenzen eines Nutzers schnell, prägnant und in einem einheitlichen Format verfügbar. Sie können beispielsweise Profile abrufen, die folgende Inhalte enthalten:
MemoryProfile(
profile={
"technical_stacks": "ADK, Python",
"preferred_language": "Python",
"tone_preference": "Succinct"
},
schema_id="user-profile"
)
Strukturierte Profile sind für den Abruf mit geringer Latenz optimiert, da die aufwendige Kuratierung der Informationen bei der Generierung erfolgt. Sie eignen sich hervorragend, um eine Interaktion zwischen einem Agenten und einem Nutzer zu initiieren.
Strukturierte Speicherprofile
Strukturierte Profile werden mit denselben Methoden (GenerateMemories und IngestEvents) generiert, die Sie für Erinnerungen in natürlicher Sprache verwenden. Nachdem Sie ein Schema definiert haben, versucht Memory Bank automatisch, Profile zu generieren, die mit Ihrem Schema übereinstimmen, und verwendet dabei die angegebenen Datenquellen.
Bei der Verwendung strukturierter Profile führt Memory Bank während des Merkens von Informationen die folgenden Vorgänge aus:
- Extrahierung: Informationen und Kontext, die zum Schema passen, werden aus der Datenquelle extrahiert. Es werden nur Informationen extrahiert, die mit dem Schema übereinstimmen. Mit Speicherüberarbeitungen können Sie prüfen, welche Informationen und welcher Kontext extrahiert wurden.
- Konsolidierung: Aktualisiert (falls erforderlich) vorhandene Felder im Profil. Ein LLM entscheidet, wie die vorhandenen Inhalte basierend auf den neu extrahierten Informationen und dem Kontext aktualisiert werden sollen. Wenn das Feld noch nicht im Profil vorhanden ist, wird die Konsolidierung übersprungen und das Feld direkt mit den extrahierten Informationen aktualisiert.
Profile werden basierend auf dem scope (z. B. {"user_id": "123"}), den Sie beim Aufnehmen von Daten in Memory Bank angegeben haben, isoliert. Für jedes Schema und jeden Bereich verwaltet Memory Bank ein einzelnes Profil als „Source of Truth“. Ein generiertes Profil besteht aus einer oder mehreren Memory-Instanzen. Jede Memory-Instanz steht für ein einzelnes Feld im Profil, mit dem Sie die Metadaten und den Überarbeitungsverlauf des Felds prüfen können, z. B.:
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={...}
)
Schema definition
Die von Memory Bank generierten Profile stimmen mit dem Schema überein, das beim Erstellen oder Aktualisieren der Agent Platform-Instanz definiert wurde. Mit einem pydantic-Modell können Sie die Felder definieren, die Memory Bank extrahieren und verwalten soll. Beispiel:
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")
Laden Sie das Schema in Memory Bank hoch, wenn Sie Ihre Agent Platform-Instanz erstellen oder aktualisieren. Sie können mehrere unabhängige Profilschemas definieren. Jedes Schema muss durch eine eindeutige ID identifiziert werden:
schema_config = {
"id": "user-profile",
"memory_schema": UserProfile.model_json_schema()
}
memory_bank = client.agent_engines.create(
config={
"context_spec": {
"memory_bank_config": {
"structured_memory_configs": [
{
"schema_configs": [schema_config]
}
]
}
}
}
)
Standardmäßig versucht Memory Bank immer, Erinnerungen in natürlicher Sprache zu extrahieren. Sie können das Merken von Informationen in natürlicher Sprache deaktivieren, wenn Memory Bank nur Profile generieren soll:
memory_bank = client.agent_engines.create(
config={
"context_spec": {
"memory_bank_config": {
"structured_memory_configs": [
{
"schema_configs": [schema_config]
}
],
# Optional: Disable natural language memories.
"customization_configs": [
{"disable_natural_language_memories": True}
]
}
}
}
)
Profilgenerierung
Sie lösen die Generierung strukturierter Erinnerungen aus, indem Sie einen Unterhaltungsverlauf (Ereignisse) an die GenerateMemories oder IngestEvents Methoden übergeben. Wie bei Erinnerungen in natürlicher Sprache verwendet Memory Bank LLMs, um aussagekräftige Informationen aus den Datenquellen zu extrahieren und mit vorhandenen Erinnerungen zu konsolidieren.
Beispiel
Im folgenden Beispiel wird die Generierung von Speicherprofilen mit dem zuvor definierten Schema beschrieben.
In der ersten Reihe von Ereignissen, die für den Bereich {"user_id": "123"} an Memory Bank gesendet werden, gibt der Nutzer an, dass er mit ADK-Agenten arbeitet:
client.agent_engines.memories.generate(
name=memory_bank.api_resource.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?"}]}}]
}
)
Memory Bank extrahiert „ADK“ für das Feld technical_stack im Schema. Andere Felder werden nicht ausgefüllt, da das aufgenommene Ereignis keine relevanten Informationen für den Rest des Schemas enthält. Da dies die erste Interaktion für diesen Bereich ist, wird die Konsolidierung übersprungen und das Profil mit diesem Anfangswert initialisiert.
result = client.agent_engines.memories.retrieve_profiles(
name=memory_bank.api_resource.name,
scope={"user_id": "123"},
)
"""
Returns:
RetrieveProfilesResponse(
profiles={
'user-profile': MemoryProfile(
profile={
'technical_stack': 'ADK'
},
schema_id='user-profile'
)
}
)
"""
In der nächsten Reihe von Ereignissen, die an Memory Bank gesendet werden, gibt der Nutzer an, dass er Student ist und hauptsächlich in Python programmiert:
client.agent_engines.memories.generate(
name=memory_bank.api_resource.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 extrahiert sowohl „Python“ als auch den Status „Student“ aus der Interaktion. Das technical_stack-Fragment wird konsolidiert und „Python“ wird an den vorhandenen Eintrag „ADK“ angehängt. Das System füllt das zuvor leere Feld job_status mit der Enumeration „Student“ aus und überspringt den Konsolidierungsschritt.
result = client.agent_engines.memories.retrieve_profiles(
name=memory_bank.api_resource.name,
scope=scope
)
"""
Returns:
RetrieveProfilesResponse(
profiles={
'user-profile': MemoryProfile(
profile={
'technical_stack': 'ADK, Python',
'job_status': 'student'
},
schema_id='user-profile'
)
}
)
"""
Profilabruf
Nach der Generierung können Sie das konsolidierte Profil für einen bestimmten Bereich mit der Methode RetrieveProfiles abrufen. Dadurch werden die aktuellsten Daten zurückgegeben, die Ihrem Schema zugeordnet sind.
result = client.agent_engines.memories.retrieve_profiles(
name=memory_bank.api_resource.name,
scope={"user_id": "123"},
)
# Accessing the data
for profile in result.profiles.values():
print(profile)
# Output: {'technical_stack': 'ADK, Python', 'job_status': 'student', ...}
Profilprüfung
Im Hintergrund besteht ein Profil aus einzelnen Erinnerungen vom Typ STRUCTURED_PROFILE. Jedes Feld in Ihrem Schema wird einem einzelnen Speicher pro Bereich zugeordnet, was eine detaillierte Beobachtbarkeit ermöglicht.
RetrieveProfiles ist zwar die primäre Methode für den Produktionsabruf von Profilen, Sie können aber auch einzelne Erinnerungen prüfen, um die Entwicklung des Profils zu verfolgen. Dadurch erhalten Sie Zugriff auf Folgendes:
- Metadaten auf Feldebene: Sie können die Gültigkeitsdauer (TTL) und
Memory.metadatafür einzelne Felder im Profil ansehen und aktualisieren. - Überarbeitungsverlauf: Sie können die Herkunft eines Felds nachverfolgen, um frühere Werte und den spezifischen Unterhaltungskontext zu sehen, der die einzelnen Änderungen ausgelöst hat.
Mit RetrieveMemories können Sie beispielsweise alle Erinnerungen abrufen, die Fragmente eines Nutzerprofils enthalten. Standardmäßig ruft RetrieveMemories nur Erinnerungen in natürlicher Sprache ab. Sie müssen also explizit STRUCTURED_PROFILE-Erinnerungen anfordern:
client.agent_engines.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': '1'
},
structured_content=MemoryStructuredContent(
data={
'technical_stack': 'ADK, Python'
},
schema_id='user'
),
update_time=datetime.datetime(...)
)
)]
"""
Anschließend können Sie den Überarbeitungsverlauf dieses strukturierten Profilfragments abrufen, um zu prüfen, wie sich das Profilfeld im Laufe der Zeit geändert hat und welcher Kontext die einzelnen Änderungen ausgelöst hat:
for retrieved_memory in list(results):
list(client.agent_engines.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'
}
)]
"""