Skip to content

Fix Gemini/Vertex estimated cost excluding thinking tokens#920

Open
colinbennettbrain wants to merge 1 commit into
mainfrom
colin-google-converter
Open

Fix Gemini/Vertex estimated cost excluding thinking tokens#920
colinbennettbrain wants to merge 1 commit into
mainfrom
colin-google-converter

Conversation

@colinbennettbrain

Copy link
Copy Markdown
Contributor

Summary

Vertex/Gemini thinking (reasoning) tokens were excluded from estimated LLM cost. geminiUsageToOpenAIUsage mapped completion_tokens from candidatesTokenCount only, which per Google's usage metadata excludes thoughtsTokenCount (totalTokenCount = prompt + candidates + toolUse + thoughts). Since every cost path prices completion_tokens, thinking tokens were never charged — undercounting cost for Gemini thinking models on Vertex (e.g. gemini-3.1-pro-preview).

Root cause / fix

The canonical convention across the codebase is that completion_tokens is the total billable output including reasoning, with reasoning_tokens as a subset breakdown:

  • OpenAIcompletion_tokens already includes reasoning (pass-through).
  • Anthropiccompletion_tokens = output_tokens, which includes thinking.
  • Linguacompletion_tokens = candidates + thoughts.

The legacy Gemini converter was the lone violator. This aligns it with the convention:

completion_tokens:
  (usageMetadata.candidatesTokenCount || 0) + (thoughtsTokenCount || 0),

reasoning_tokens stays the subset breakdown. This corrects every downstream cost path at once (proxy metric logging, ingestion, query-time, and UI) without touching the cost logic — and deliberately avoids adding reasoning inside the cost paths, which would double-count for OpenAI/Anthropic/Lingua where reasoning is already part of completion_tokens.

Tests

Added streaming + non-streaming regression tests covering the reported payload (candidatesTokenCount=50, thoughtsTokenCount=25completion_tokens=75, reasoning_tokens=25).

Follow-up

Fixes new logs going forward via the proxy. Historical spans keep the undercounted completion_tokens and would need a separate backfill if corrected cost is required. A submodule bump in braintrustdata/braintrust is the deploy step after this merges.

Pylon #18680

geminiUsageToOpenAIUsage mapped completion_tokens from candidatesTokenCount
only, which excludes thoughtsTokenCount. Every cost path prices
completion_tokens, so thinking tokens were never charged, undercounting
cost for Gemini thinking models on Vertex.

Follow the OpenAI/Anthropic/Lingua convention where completion_tokens
includes reasoning and reasoning_tokens is the subset breakdown, so all
downstream cost paths (proxy metrics, ingestion, query, UI) price thinking
tokens correctly. Add streaming + non-streaming regression tests.

Pylon #18680
@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ai-proxy Ready Ready Preview, Comment Jul 6, 2026 9:40pm

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant