mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
feat: Add intra-invocation compaction and token compaction pre-request
Compact session events before LLM calls when token threshold is exceeded Co-authored-by: George Weale <gweale@google.com> PiperOrigin-RevId: 873095899
This commit is contained in:
committed by
Copybara-Service
parent
bbdf0ea257
commit
485fcb84e3
@@ -24,6 +24,7 @@ from pydantic import ConfigDict
|
||||
from pydantic import Field
|
||||
from pydantic import PrivateAttr
|
||||
|
||||
from ..apps.app import EventsCompactionConfig
|
||||
from ..apps.app import ResumabilityConfig
|
||||
from ..artifacts.base_artifact_service import BaseArtifactService
|
||||
from ..auth.credential_service.base_credential_service import BaseCredentialService
|
||||
@@ -200,6 +201,12 @@ class InvocationContext(BaseModel):
|
||||
resumability_config: Optional[ResumabilityConfig] = None
|
||||
"""The resumability config that applies to all agents under this invocation."""
|
||||
|
||||
events_compaction_config: Optional[EventsCompactionConfig] = None
|
||||
"""The compaction config for this invocation."""
|
||||
|
||||
token_compaction_checked: bool = False
|
||||
"""Whether token-threshold compaction ran during this invocation."""
|
||||
|
||||
plugin_manager: PluginManager = Field(default_factory=PluginManager)
|
||||
"""The manager for keeping track of plugins in this invocation."""
|
||||
|
||||
|
||||
+266
-131
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,58 @@
|
||||
# Copyright 2026 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Request processor that runs token-threshold event compaction."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import AsyncGenerator
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ...apps.compaction import _has_token_threshold_config
|
||||
from ...apps.compaction import _run_compaction_for_token_threshold_config
|
||||
from ...events.event import Event
|
||||
from ._base_llm_processor import BaseLlmRequestProcessor
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ...agents.invocation_context import InvocationContext
|
||||
from ...models.llm_request import LlmRequest
|
||||
|
||||
|
||||
class CompactionRequestProcessor(BaseLlmRequestProcessor):
|
||||
"""Compacts session events before contents are prepared for model calls."""
|
||||
|
||||
async def run_async(
|
||||
self, invocation_context: InvocationContext, llm_request: LlmRequest
|
||||
) -> AsyncGenerator[Event, None]:
|
||||
del llm_request
|
||||
config = invocation_context.events_compaction_config
|
||||
if not _has_token_threshold_config(config):
|
||||
return
|
||||
yield # Required for AsyncGenerator.
|
||||
|
||||
token_compacted = await _run_compaction_for_token_threshold_config(
|
||||
config=config,
|
||||
session=invocation_context.session,
|
||||
session_service=invocation_context.session_service,
|
||||
agent=invocation_context.agent,
|
||||
agent_name=invocation_context.agent.name,
|
||||
current_branch=invocation_context.branch,
|
||||
)
|
||||
if token_compacted:
|
||||
invocation_context.token_compaction_checked = True
|
||||
return
|
||||
yield # Required for AsyncGenerator.
|
||||
|
||||
|
||||
request_processor = CompactionRequestProcessor()
|
||||
@@ -22,6 +22,7 @@ from . import _code_execution
|
||||
from . import _nl_planning
|
||||
from . import _output_schema_processor
|
||||
from . import basic
|
||||
from . import compaction
|
||||
from . import contents
|
||||
from . import context_cache_processor
|
||||
from . import identity
|
||||
@@ -42,6 +43,9 @@ def _create_request_processors():
|
||||
request_confirmation.request_processor,
|
||||
instructions.request_processor,
|
||||
identity.request_processor,
|
||||
# Compaction should run before contents so compacted events are reflected
|
||||
# in the model request context.
|
||||
compaction.request_processor,
|
||||
contents.request_processor,
|
||||
# Context cache processor sets up cache config and finds
|
||||
# existing cache metadata.
|
||||
|
||||
@@ -553,7 +553,10 @@ class Runner:
|
||||
if self.app and self.app.events_compaction_config:
|
||||
logger.debug('Running event compactor.')
|
||||
await _run_compaction_for_sliding_window(
|
||||
self.app, session, self.session_service
|
||||
self.app,
|
||||
session,
|
||||
self.session_service,
|
||||
skip_token_compaction=invocation_context.token_compaction_checked,
|
||||
)
|
||||
|
||||
async with Aclosing(_run_with_trace(new_message, invocation_id)) as agen:
|
||||
@@ -1362,6 +1365,9 @@ class Runner:
|
||||
credential_service=self.credential_service,
|
||||
plugin_manager=self.plugin_manager,
|
||||
context_cache_config=self.context_cache_config,
|
||||
events_compaction_config=(
|
||||
self.app.events_compaction_config if self.app else None
|
||||
),
|
||||
invocation_id=invocation_id,
|
||||
agent=self.agent,
|
||||
session=session,
|
||||
|
||||
Reference in New Issue
Block a user