内存配置文件

您可以使用记忆库生成结构化配置文件,这些配置文件是使用 LLM 填充和更新的具有静态架构的数据结构。通过定义固定架构,您可以确保智能体能够立即以低延迟访问不断变化的信息,而无需在会话期间执行代价高昂的搜索操作。

如需完成本指南中演示的步骤,您必须先按照 设置记忆库中的步骤操作。

概览

将结构化配置文件与智能体搭配使用,可确保快速、简洁地以一致的格式提供提取的信息(例如用户的技术堆栈或偏好设置)。例如,您可以检索包含以下内容的配置文件:

MemoryProfile(
    profile={
        "technical_stacks": "ADK, Python",
        "preferred_language": "Python",
        "tone_preference": "Succinct"
    },
    schema_id="user-profile"
)

结构化配置文件经过优化,可实现低延迟检索,因为整理信息的工作是在生成时完成的。它们非常适合初始化智能体与用户之间的互动。

了解结构化记忆配置文件

结构化配置文件是通过与自然语言记忆相同的方法(GenerateMemoriesIngestEvents)生成的。定义架构后,记忆库将自动尝试使用提供的数据源生成符合您架构的配置文件。

使用结构化配置文件时,记忆库会在记忆生成期间执行以下操作:

  • 提取:从数据源中提取符合架构的信息和上下文。系统只会提取符合架构的信息。您可以使用记忆修订版本检查提取了哪些信息和上下文。
  • 整合:更新(如有必要)配置文件中的现有字段。LLM 将根据新提取的信息和上下文判断如何更新现有内容。如果配置文件中尚不存在该字段,系统将跳过整合,并使用提取的信息直接更新该字段。

配置文件会根据您在将数据注入记忆库时提供的 scope(例如 {"user_id": "123"})进行隔离。对于每个架构和范围,记忆库都会维护一个配置文件作为可靠来源。生成的配置文件由一个或多个 Memory 实例组成。每个 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={
         'language_preference': 'Java'
       },
       schema_id='user-profile'
     ),
     update_time=datetime.datetime(...),
     expire_time=datetime.datetime(...),
     metadata={...}
)

架构定义

记忆库生成的配置文件与创建或更新 Agent Platform 实例时定义的架构一致。您可以使用 pydantic 模型定义您希望记忆库提取和维护的字段。例如:

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")

创建或更新 Agent Platform 实例时,将架构上传到记忆库。您可以定义多个独立的配置文件架构;每个架构都必须使用唯一的 ID 进行标识:

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]
                    }
                ]
            }
        }
    }
)

默认情况下,记忆库始终会尝试提取自然语言记忆。如果您只希望记忆库生成配置文件,可以停用自然语言记忆生成:

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}
                ]
            }
        }
    }
)

配置文件生成

您可以通过向 GenerateMemoriesIngestEvents 方法提供对话历史记录(事件)来触发结构化记忆的生成。与自然语言记忆一样,记忆库使用 LLM 从数据源中提取有意义的信息,并将其与现有记忆整合。

示例

以下示例演示了如何使用之前定义的架构生成记忆配置文件。

在发送给记忆库的第一组事件中,范围为 {"user_id": "123"} 的用户表示他们使用 ADK 智能体:

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?"}]}}]
  }
)

记忆库会为架构中的 technical_stack 字段提取“ADK”。由于注入的事件不包含架构其余部分的相关信息,因此不会填充其他字段。由于这是此范围的首次互动,系统会跳过整合,并使用此初始值初始化配置文件。

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'
    )
  }
)
"""

在发送给记忆库的下一组事件中,用户表示他们是学生,主要使用 Python 进行编码:

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?"}]}}]
  }
)

记忆库会从互动中提取“Python”和“学生”状态。系统会整合 technical_stack 片段,将“Python”附加到现有的“ADK”条目。系统会使用“学生”枚举填充之前为空的 job_status 字段,并跳过整合步骤。

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'
    )
  }
)
"""

配置文件检索

生成后,您可以使用 RetrieveProfiles 方法检索特定范围的整合配置文件。此方法会返回映射到您架构的最新数据。

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', ...}

配置文件检查

在底层,配置文件由类型为 STRUCTURED_PROFILE 的各个记忆组成。架构中的每个字段都会映射到每个范围的单个记忆,从而实现精细的可观测性。

虽然 RetrieveProfiles 是用于在生产环境中检索配置文件的主要方法,但您可以检查各个记忆来审核配置文件的演变过程。这样您就可以访问:

  • 字段级元数据:查看和更新配置文件中各个字段的特定存留时间 (TTL) 和 Memory.metadata
  • 修订历史记录:跟踪字段的沿袭,查看历史值以及触发每次更改的具体对话上下文。

例如,您可以使用 RetrieveMemories 检索包含用户配置文件片段的所有记忆。默认情况下,RetrieveMemories 仅检索自然语言记忆,因此您需要明确请求 STRUCTURED_PROFILE 记忆:

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(...)
   )
 )]
"""

然后,您可以检索此结构化配置文件片段的修订历史记录,以检查配置文件字段随时间的变化情况以及每次更改的相关上下文:

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'
   }
 )]
"""