Skip to content

Commit c14258d

Browse files
haiyuan-eng-googlecopybara-github
authored andcommitted
feat(bigquery): expose thinking and tool-use token columns in analytics views
Add usage_thinking_tokens and usage_tool_use_tokens to the LLM_RESPONSE analytics view, sourced from the usage_metadata proto the plugin already logs to attributes.usage_metadata (thoughts_token_count and tool_use_prompt_token_count). Per the genai GenerateContentResponseUsageMetadata contract, total_token_count = prompt_token_count + candidates_token_count + tool_use_prompt_token_count + thoughts_token_count, so thinking and tool-use tokens are separate addends rather than subsets of prompt/candidates. Surfacing them lets analytics account for them without double counting. Both fields are optional and resolve to NULL for models/responses that do not report them, so the change stays model-agnostic. No plugin logging change is needed since the full usage_metadata is already persisted to attributes. Co-authored-by: Haiyuan Cao <haiyuan@google.com> PiperOrigin-RevId: 943493796
1 parent 2aeb1e1 commit c14258d

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

src/google/adk/plugins/bigquery_agent_analytics_plugin.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,16 @@ def _parse_custom_metadata_allowlist(
20602060
" '$.usage_metadata.cached_content_token_count') AS INT64) AS"
20612061
" usage_cached_tokens"
20622062
),
2063+
(
2064+
"CAST(JSON_VALUE(attributes,"
2065+
" '$.usage_metadata.thoughts_token_count') AS INT64) AS"
2066+
" usage_thinking_tokens"
2067+
),
2068+
(
2069+
"CAST(JSON_VALUE(attributes,"
2070+
" '$.usage_metadata.tool_use_prompt_token_count') AS INT64) AS"
2071+
" usage_tool_use_tokens"
2072+
),
20632073
(
20642074
"SAFE_DIVIDE(CAST(JSON_VALUE(attributes,"
20652075
" '$.usage_metadata.cached_content_token_count') AS"

tests/unittests/plugins/test_bigquery_agent_analytics_plugin.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5978,6 +5978,26 @@ def test_view_sql_contains_correct_event_filter(self):
59785978
view_name = "v_" + event_type.lower()
59795979
assert view_name in all_sql, f"View {view_name} not found in SQL"
59805980

5981+
def test_llm_response_view_exposes_token_usage_columns(self):
5982+
"""LLM_RESPONSE view surfaces cached/thinking/tool-use token columns.
5983+
5984+
These are read from the full ``usage_metadata`` proto that is already
5985+
logged to ``attributes.usage_metadata``, so they are sourced from
5986+
``attributes`` rather than the ``content.usage`` summary.
5987+
"""
5988+
plugin = self._make_plugin(create_views=True)
5989+
plugin.client.get_table.side_effect = cloud_exceptions.NotFound("not found")
5990+
plugin.client.query.return_value = mock.MagicMock()
5991+
5992+
plugin._ensure_schema_exists()
5993+
5994+
all_sql = " ".join(c[0][0] for c in plugin.client.query.call_args_list)
5995+
assert "usage_cached_tokens" in all_sql
5996+
assert "usage_thinking_tokens" in all_sql
5997+
assert "usage_tool_use_tokens" in all_sql
5998+
assert "$.usage_metadata.thoughts_token_count" in all_sql
5999+
assert "$.usage_metadata.tool_use_prompt_token_count" in all_sql
6000+
59816001
def test_config_create_views_default_true(self):
59826002
"""Config create_views defaults to True."""
59836003
config = bigquery_agent_analytics_plugin.BigQueryLoggerConfig()

0 commit comments

Comments
 (0)