注入事件

IngestEvents API 可将事件提取与记忆库中的记忆生成分离开来。您可以持续向记忆库流式传输内容,当满足触发条件时,系统会自动运行生成过程。

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

本页中的示例使用 agentplatform SDK,该 SDK 提供最新的 IngestEvents 配置选项。使用 agentplatform 初始化客户端:

import agentplatform

client = agentplatform.Client(
    project="PROJECT_ID",
    location="LOCATION",
)

了解事件提取

使用 GenerateMemories API 时,系统会立即触发记忆生成过程。此方法可让您直接控制记忆生成的时间。IngestEvents 提供了一种将事件提取与记忆生成分离的流式处理模式:

  • 持续提取:每当有新数据可用时,您都可以持续将上下文信息流式传输到记忆库。
  • 去重:记忆库会根据共享的事件 ID 自动检测并忽略重叠的对话记录。
  • 自动触发:仅当满足特定条件(例如达到事件数量阈值或空闲时间)时,系统才会自动触发生成。
  • 异步生成:在后台处理事件。该 API 会立即返回一个长时间运行的操作 (LRO),您可以轮询或监控该操作,直到满足触发条件并生成记忆。

流和长时间运行的操作 (LRO)

流充当隔离的缓冲区,用于累积多个请求中的事件。每个数据流都由其 scopestream_id 的组合唯一确定。如果您未提供信息流 ID,记忆库将使用 default 作为 ID。只有当事件具有完全相同的范围和 ID 时,它们才会一起暂存和“刷新”,从而确保在内存生成期间实现严格隔离。

在触发并完成记忆生成之前,对同一信息流的多次提取调用会返回相同的 LRO。完成后,此 IngestEvents LRO 将包含 GenerateMemories API 调用的下游 LRO。后续向该数据流发出的任何提取请求都将返回新的 LRO。

触发记忆生成

如果未满足任何触发条件,系统会在摄取最后一个事件 24 小时后自动刷新数据流中的所有待处理事件。此限制可确保记忆库处理所有事件,包括已放弃的事件。

generation_trigger_config 决定了何时刷新和处理收集的事件以生成内存。您可以配置以下触发条件:

  • 事件数 (event_count):当累积的唯一身份事件数达到限额时,系统会触发一次生成。
  • 非活跃时间idle_duration,以秒为单位,精确到分钟,这意味着您必须指定 60 的倍数):当流在指定时长(例如 "300s")后未收到新事件时,系统会触发生成操作。
  • 固定间隔fixed_interval,以秒为单位,精确到分钟,这意味着您必须指定 60 的倍数):生成操作以固定节奏执行,在每个指定时长(例如 "300s")后轮询增量事件。
  • 强制刷新 (force_flush):立即刷新所有待处理的事件。

您可以在同一 generation_rule 中将基于事件计数的规则与基于时间的规则相结合。例如,您可以同时设置 event_countidle_duration。如果配置了多个条件,那么只要满足其中任何一个条件,系统就会触发生成操作,无论哪个条件先满足。这两种基于时间的条件互斥:一条规则只能指定 idle_durationfixed_interval,但不能同时指定这两者。force_flush 字段不受这些规则的约束,始终会立即刷新待处理的事件。

该 API 使用 event_id 自动对数据进行去重。通过为每个事件提供唯一 ID,只有新事件会被添加到缓冲区。

在生成窗口之间沿用上下文

默认情况下,每个生成窗口仅处理自上次刷新以来累积的事件。为了在连续的生成窗口中保持记忆的一致性,您可以通过在 generation_rule 中设置 overlap_event_count,将上下文从一个窗口传递到下一个窗口。这会在下一个窗口的开头重新纳入最后 N 个已处理的事件。

结转的事件不会计入触发条件。overlap_event_count 值必须是小于 event_count 的正整数,并且需要 event_count 或基于时间的规则(idle_durationfixed_interval)。

数据源

借助 IngestEvents,您可以通过在直接载荷中使用 direct_contents_source 在应用请求中直接提交事件来提供内容。

以下示例展示了不同的触发器。

示例:事件数触发器

此示例使用自定义流,并在流中累积了 10 个唯一事件时触发生成。

字典

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source={
        "events": [
            {
                "content": {
                    "role": "user",
                    "parts": [{"text": "My favorite color is blue."}]
                },
                "event_id": "event-1" # Optional, used for deduplication.
            }
        ]
    },
    generation_trigger_config={
        "generation_rule": {
            "event_count": 10
        }
    },
    scope={"user_id": "123"}
)

基于类

from google import genai
from agentplatform import types

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source=types.IngestionDirectContentsSource(
        events=[
            types.IngestionDirectContentsSourceEvent(
                content=genai.types.Content(
                    role="user",
                    parts=[genai.types.Part.from_text(text="My favorite color is blue.")]
                ),
                event_id="event-1" # Optional, used for deduplication.
            )
        ]
    ),
    generation_trigger_config=types.MemoryGenerationTriggerConfig(
        generation_rule=types.MemoryGenerationTriggerConfigGenerationTriggerRule(
            event_count=10
        )
    ),
    scope={"user_id": "123"}
)

示例:基于时间的空闲时长触发器

此示例会在数据流 5 分钟 (300s) 未收到新事件时触发生成操作。它还会设置自定义 stream_id

字典

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source={
        "events": [
            {
                "content": {
                    "role": "user",
                    "parts": [{"text": "I will be back in a bit."}]
                },
                "event_id": "event-2" # Optional, used for deduplication.
            }
        ]
    },
    generation_trigger_config={
        "generation_rule": {
            "idle_duration": "300s"
        }
    },
    scope={"user_id": "123"}
)

基于类

from google import genai
from agentplatform import types

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source=types.IngestionDirectContentsSource(
        events=[
            types.IngestionDirectContentsSourceEvent(
                content=genai.types.Content(
                    role="user",
                    parts=[genai.types.Part.from_text(text="I will be back in a bit.")]
                ),
                event_id="event-2" # Optional, used for deduplication.
            )
        ]
    ),
    generation_trigger_config=types.MemoryGenerationTriggerConfig(
        generation_rule=types.MemoryGenerationTriggerConfigGenerationTriggerRule(
            idle_duration="300s"
        )
    ),
    scope={"user_id": "123"}
)

示例:结合使用基于事件的触发器和基于时间的触发器

此示例在同一请求中配置了两个触发条件。当累积了 10 个唯一身份事件或数据流空闲 5 分钟 (300s) 时(以先到者为准),系统会运行生成过程。

字典

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source={
        "events": [
            {
                "content": {
                    "role": "user",
                    "parts": [{"text": "Let's keep this conversation going."}]
                },
                "event_id": "event-3" # Optional, used for deduplication.
            }
        ]
    },
    generation_trigger_config={
        "generation_rule": {
            "event_count": 10,
            "idle_duration": "300s"
        }
    },
    scope={"user_id": "123"}
)

基于类

from google import genai
from agentplatform import types

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source=types.IngestionDirectContentsSource(
        events=[
            types.IngestionDirectContentsSourceEvent(
                content=genai.types.Content(
                    role="user",
                    parts=[genai.types.Part.from_text(text="Let's keep this conversation going.")]
                ),
                event_id="event-3" # Optional, used for deduplication.
            )
        ]
    ),
    generation_trigger_config=types.MemoryGenerationTriggerConfig(
        generation_rule=types.MemoryGenerationTriggerConfigGenerationTriggerRule(
            event_count=10,
            idle_duration="300s"
        )
    ),
    scope={"user_id": "123"}
)

示例:强制刷新事件

此示例无条件绕过所有触发条件,并立即强制刷新和处理流中的所有待处理事件。

字典

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source={
        "events": [
            {
                "content": {
                    "role": "user",
                    "parts": [{"text": "That's all for today!"}]
                },
            }
        ]
    },
    config={
        "force_flush": True
    },
    scope={"user_id": "123"}
)

基于类

from google import genai
from agentplatform import types

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source=types.IngestionDirectContentsSource(
        events=[
            types.IngestionDirectContentsSourceEvent(
                content=genai.types.Content(
                    role="user",
                    parts=[genai.types.Part.from_text(text="That's all for today!")]
                ),
            )
        ]
    ),
    config=types.IngestEventsConfig(
        force_flush=True
    ),
    scope={"user_id": "123"}
)

示例:在窗口之间传递上下文

此示例每 10 个唯一事件触发一次生成,并在下一个窗口中重新包含最后 2 个已处理的事件,以便回忆在各个窗口中保持连贯性。

字典

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source={
        "events": [
            {
                "content": {
                    "role": "user",
                    "parts": [{"text": "Let's continue where we left off."}]
                },
            }
        ]
    },
    generation_trigger_config={
        "generation_rule": {
            "event_count": 10,
            "overlap_event_count": 2
        }
    },
    scope={"user_id": "123"}
)

基于类

from google import genai
from agentplatform import types

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source=types.IngestionDirectContentsSource(
        events=[
            types.IngestionDirectContentsSourceEvent(
                content=genai.types.Content(
                    role="user",
                    parts=[genai.types.Part.from_text(text="Let's continue where we left off.")]
                ),
            )
        ]
    ),
    generation_trigger_config=types.MemoryGenerationTriggerConfig(
        generation_rule=types.MemoryGenerationTriggerConfigGenerationTriggerRule(
            event_count=10,
            overlap_event_count=2
        )
    ),
    scope={"user_id": "123"}
)

配置内存修订版本

GenerateMemories 类似,IngestEvents 会为生成的记忆创建记忆修订版本。您可以在 config 中设置以下字段,以配置因提取请求而产生的修订版本:

  • 修订版本标签 (revision_labels):应用于生成的内存修订版本的键值对。例如,您可以为修订版本添加数据源标签,以便日后按该标签过滤修订版本
  • 修订版本失效时间revision_expire_timerevision_ttl):控制生成的记忆修订版本何时失效。如果您未设置过期时间,记忆库将使用实例配置或默认的存留时间 (TTL)(365 天)。
  • 停用修订版本 (disable_memory_revisions):如果值为 True,记忆库不会为根据此请求生成的记忆创建修订版本。

以下示例会为生成的修订版本添加数据源标签,并将其保留 30 天:

字典

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source={
        "events": [
            {
                "content": {
                    "role": "user",
                    "parts": [{"text": "My favorite color is blue."}]
                },
            }
        ]
    },
    generation_trigger_config={
        "generation_rule": {
            "event_count": 10
        }
    },
    config={
        "revision_labels": {"data_source": "321"},
        # Persist memory revisions for 30 days after they're created.
        "revision_ttl": f"{30 * 60 * 60 * 24}s"
    },
    scope={"user_id": "123"}
)

基于类

from google import genai
from agentplatform import types

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source=types.IngestionDirectContentsSource(
        events=[
            types.IngestionDirectContentsSourceEvent(
                content=genai.types.Content(
                    role="user",
                    parts=[genai.types.Part.from_text(text="My favorite color is blue.")]
                ),
            )
        ]
    ),
    generation_trigger_config=types.MemoryGenerationTriggerConfig(
        generation_rule=types.MemoryGenerationTriggerConfigGenerationTriggerRule(
            event_count=10
        )
    ),
    config=types.IngestEventsConfig(
        revision_labels={"data_source": "321"},
        # Persist memory revisions for 30 days after they're created.
        revision_ttl=f"{30 * 60 * 60 * 24}s"
    ),
    scope={"user_id": "123"}
)

将元数据附加到生成的记忆

您可以将元数据附加到根据已提取的事件生成的记忆中。借助元数据,您可以将结构化信息(字符串、双精度浮点数、布尔值或时间戳)与记忆事实一起存储,这对于过滤或管理记忆的生命周期非常有用。

使用 metadata_merge_strategy 控制元数据在整合期间如何与现有记忆互动。您可以将其设置为 OVERWRITE(未设置时的默认值)、MERGEREQUIRE_EXACT_MATCH。如需了解详情,请参阅在整合期间使用元数据

字典

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source={
        "events": [
            {
                "content": {
                    "role": "user",
                    "parts": [{"text": "My favorite color is blue."}]
                },
            }
        ]
    },
    generation_trigger_config={
        "generation_rule": {
            "event_count": 10
        }
    },
    config={
        "metadata": {
            "my_string_key": {"string_value": "my_string_value"},
            "my_boolean_key": {"bool_value": True}
        },
        "metadata_merge_strategy": "MERGE"
    },
    scope={"user_id": "123"}
)

基于类

from google import genai
from agentplatform import types

client.agent_engines.memories.ingest_events(
    name=memory_bank.api_resource.name,
    stream_id="my-custom-stream",
    direct_contents_source=types.IngestionDirectContentsSource(
        events=[
            types.IngestionDirectContentsSourceEvent(
                content=genai.types.Content(
                    role="user",
                    parts=[genai.types.Part.from_text(text="My favorite color is blue.")]
                ),
            )
        ]
    ),
    generation_trigger_config=types.MemoryGenerationTriggerConfig(
        generation_rule=types.MemoryGenerationTriggerConfigGenerationTriggerRule(
            event_count=10
        )
    ),
    config=types.IngestEventsConfig(
        metadata={
            "my_string_key": types.MemoryMetadataValue(string_value="my_string_value"),
            "my_boolean_key": types.MemoryMetadataValue(bool_value=True)
        },
        metadata_merge_strategy=types.MemoryMetadataMergeStrategy.MERGE
    ),
    scope={"user_id": "123"}
)

后续步骤