Skip to content

Commit 55d99cf

Browse files
committed
fix(utils): stop double-counting cumulative cache invocation counters
1 parent 86a47f6 commit 55d99cf

2 files changed

Lines changed: 77 additions & 5 deletions

File tree

‎src/google/adk/utils/cache_performance_analyzer.py‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,15 @@ async def analyze_agent_cache_performance(
148148
total_cached_tokens / total_requests if total_requests > 0 else 0.0
149149
)
150150

151-
invocations_used = [
152-
c.invocations_used
153-
for c in cache_history
154-
if c.invocations_used is not None
155-
]
151+
# Each response carries the cumulative counter for its cache, not an
152+
# additional invocation count. Keep one total per cache instance.
153+
cache_invocations: dict[str, int] = {}
154+
for cache in cache_history:
155+
if cache.cache_name is not None and cache.invocations_used is not None:
156+
cache_invocations[cache.cache_name] = max(
157+
cache_invocations.get(cache.cache_name, 0), cache.invocations_used
158+
)
159+
invocations_used = list(cache_invocations.values())
156160
total_invocations = sum(invocations_used)
157161

158162
return {

‎tests/unittests/utils/test_cache_performance_analyzer.py‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,80 @@
2121
from google.adk.events.event import Event
2222
from google.adk.models.cache_metadata import CacheMetadata
2323
from google.adk.sessions.base_session_service import BaseSessionService
24+
from google.adk.sessions.in_memory_session_service import InMemorySessionService
2425
from google.adk.sessions.session import Session
2526
from google.adk.utils.cache_performance_analyzer import CachePerformanceAnalyzer
2627
from google.genai import types
2728
import pytest
2829

2930

31+
@pytest.mark.parametrize(
32+
"snapshots,expected_total,expected_average",
33+
[
34+
([("cache1", 1), ("cache1", 2), ("cache1", 3)], 3, 3.0),
35+
([("cache1", 1), ("cache1", 1), ("cache1", 2)], 2, 2.0),
36+
([("cache1", 1), ("cache1", 2), ("cache2", 1)], 3, 1.5),
37+
([("cache1", 3)], 3, 3.0),
38+
([("cache1", 3), ("cache1", 2)], 3, 3.0),
39+
([(None, None), ("cache1", 2), (None, None)], 2, 2.0),
40+
([(None, None)], 0, 0),
41+
([("cache1", 0), ("cache1", 0)], 0, 0),
42+
],
43+
ids=[
44+
"successive-invocations",
45+
"multiple-responses-per-invocation",
46+
"cache-refresh-with-same-fingerprint",
47+
"single-snapshot",
48+
"out-of-order-snapshots",
49+
"fingerprint-only-around-active-cache",
50+
"fingerprint-only",
51+
"unused-cache",
52+
],
53+
)
54+
async def test_cache_invocation_totals_count_each_cache_once(
55+
snapshots: list[tuple[str | None, int | None]],
56+
expected_total: int,
57+
expected_average: float,
58+
) -> None:
59+
"""Cumulative cache counters are not added once per response."""
60+
service = InMemorySessionService()
61+
session = await service.create_session(app_name="app", user_id="user")
62+
for cache_name, count in snapshots:
63+
await service.append_event(
64+
session=session,
65+
event=Event(
66+
author="agent",
67+
invocation_id=f"invocation{count}",
68+
cache_metadata=CacheMetadata(
69+
cache_name=cache_name,
70+
invocations_used=count,
71+
expire_time=2_000_000_000 if cache_name is not None else None,
72+
fingerprint="prefix",
73+
contents_count=2,
74+
),
75+
usage_metadata=types.GenerateContentResponseUsageMetadata(
76+
prompt_token_count=100,
77+
cached_content_token_count=80 if cache_name is not None else 0,
78+
),
79+
),
80+
)
81+
82+
result = await CachePerformanceAnalyzer(
83+
service
84+
).analyze_agent_cache_performance(session.id, "user", "app", "agent")
85+
86+
assert result["total_invocations"] == expected_total
87+
assert result["avg_invocations_used"] == expected_average
88+
assert result["cache_refreshes"] == len(
89+
{name for name, _ in snapshots if name is not None}
90+
)
91+
assert result["total_requests"] == len(snapshots)
92+
assert result["total_prompt_tokens"] == 100 * len(snapshots)
93+
assert result["total_cached_tokens"] == 80 * sum(
94+
name is not None for name, _ in snapshots
95+
)
96+
97+
3098
class TestCachePerformanceAnalyzer:
3199
"""Test suite for CachePerformanceAnalyzer."""
32100

0 commit comments

Comments
 (0)