Mit Memory Bank können Sie strukturierte Profile erstellen. Das sind Datenstrukturen mit statischen Schemas, die mit LLMs gefüllt und aktualisiert werden. Durch die Definition eines festen Schemas erhalten Ihre Agenten sofortigen Zugriff mit geringer Latenz auf sich entwickelnde Informationen, ohne dass während einer Sitzung kostspielige 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 Agent verwenden, sind extrahierte Informationen wie die technischen Stacks oder die Einstellungen eines Nutzers schnell, prägnant und in einem einheitlichen Format verfügbar. Sie können beispielsweise Profile abrufen, die Inhalte wie die folgenden 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 niedriger Latenz optimiert, da die Informationen bereits bei der Generierung zusammengestellt werden. Sie eignen sich hervorragend, um eine Interaktion zwischen einem Agent und einem Nutzer zu starten.
Strukturierte Speicherprofile
Strukturierte Profile werden mit denselben Methoden (GenerateMemories und IngestEvents) generiert, die Sie für Erinnerungen in natürlicher Sprache verwenden. Sobald Sie ein Schema definiert haben, versucht Memory Bank automatisch, Profile zu generieren, die mit Ihrem Schema übereinstimmen. Dazu werden die bereitgestellten Datenquellen verwendet.
Bei der Verwendung strukturierter Profile führt Memory Bank während des Merkens von Informationen die folgenden Vorgänge aus:
- Extraktion: Informationen und Kontext, die dem Schema entsprechen, werden aus der Datenquelle extrahiert. Es werden nur Informationen extrahiert, die dem Schema entsprechen. Mit Speicherrevisionen 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 auf Grundlage der neu extrahierten Informationen und des Kontexts aktualisiert werden. Wenn das Feld noch nicht im Profil vorhanden ist, wird die Konsolidierung übersprungen und das Feld direkt mit den extrahierten Informationen aktualisiert.
Profile werden anhand des scope (z. B. {"user_id": "123"}) isoliert, das Sie beim Erfassen von Daten in Memory Bank angegeben haben. Für jedes Schema und jeden Bereich verwaltet Memory Bank ein einzelnes Profil als Quelle der Wahrheit. 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={...}
)
Schemadefinition
Die von Memory Bank generierten Profile entsprechen dem Schema, 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 die Memory Bank hoch, wenn Sie Ihre Agent Platform-Instanz erstellen oder aktualisieren. Sie können mehrere unabhängige Profilschemata definieren. Jedes Schema muss durch eine eindeutige ID identifiziert werden:
schema_config = {
"id": "user-profile",
"memory_schema": UserProfile.model_json_schema()
}
agent_engine = client.agent_engines.create(
config={
"context_spec": {
"memory_bank_config": {
"structured_memory_configs": [
{
"schema_configs": [schema_config]
}
]
}
}
}
)
Standardmäßig versucht die 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 erstellen soll:
agent_engine = 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}
]
}
}
}
)
Profilerstellung
Sie lösen die Generierung strukturierter Erinnerungen aus, indem Sie einen Unterhaltungsverlauf (Ereignisse) für die Methoden GenerateMemories oder IngestEvents bereitstellen. Wie bei Erinnerungen in natürlicher Sprache werden in Memory Bank LLMs verwendet, um aussagekräftige Informationen aus den Datenquellen zu extrahieren und mit vorhandenen Erinnerungen zusammenzuführen.
Beispiel
Im folgenden Beispiel wird die Generierung von Speicherprofilen mit dem zuvor definierten Schema beschrieben.
Im ersten Satz von Ereignissen, die für den Bereich {"user_id": "123"} an Memory Bank gesendet werden, gibt der Nutzer an, dass er mit ADK-Agents arbeitet:
client.agent_engines.memories.generate(
name=agent_engine.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. Es werden keine weiteren Felder 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=agent_engine.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 Gruppe 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=agent_engine.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 dem Enum „student“ und überspringt den Konsolidierungsschritt.
result = client.agent_engines.memories.retrieve_profiles(
name=agent_engine_name,
scope=scope
)
"""
Returns:
RetrieveProfilesResponse(
profiles={
'user-profile': MemoryProfile(
profile={
'technical_stack': 'ADK, Python',
'job_status': 'student'
},
schema_id='user-profile'
)
}
)
"""
Profilabruf
Nachdem das konsolidierte Profil generiert wurde, können Sie es für einen bestimmten Bereich mit der Methode RetrieveProfiles abrufen. So erhalten Sie die aktuellsten Daten, die Ihrem Schema zugeordnet sind.
result = client.agent_engines.memories.retrieve_profiles(
name=agent_engine.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', ...}
Profilüberprüfung
Ein Profil besteht 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 zum Abrufen von Profilen in der Produktion, Sie können aber einzelne Erinnerungen untersuchen, um die Entwicklung des Profils zu prüfen. Dadurch erhalten Sie Zugriff auf:
- Metadaten auf Feldebene: Sie können die Gültigkeitsdauer (Time to Live, TTL) und
Memory.metadatafür einzelne Felder im Profil ansehen und aktualisieren. - Versionsverlauf: Verfolgen Sie die Herkunft eines Felds, um frühere Werte und den spezifischen Unterhaltungskontext zu sehen, der die einzelnen Änderungen ausgelöst hat.
Sie können beispielsweise RetrieveMemories verwenden, um alle Erinnerungen abzurufen, die Fragmente des Profils eines Nutzers enthalten. Standardmäßig ruft RetrieveMemories nur Erinnerungen in natürlicher Sprache ab. Sie müssen STRUCTURED_PROFILE-Erinnerungen also explizit 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 sehen, wie sich das Profilfeld im Laufe der Zeit geändert hat, und den Kontext der einzelnen Änderungen zu prüfen:
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'
}
)]
"""