feat: add GoogleGenAITokenCounter to google-genai integration - #3868
Open
pma1999 wants to merge 2 commits into
Open
feat: add GoogleGenAITokenCounter to google-genai integration#3868pma1999 wants to merge 2 commits into
pma1999 wants to merge 2 commits into
Conversation
Contributor
|
Heads-up for maintainers This PR is from a fork and touches integrations whose integration tests require API keys. Affected integrations:
Please run the integration tests locally ( |
Implements the TokenCounter protocol introduced in Haystack 3.1 on top of Google's countTokens endpoint, following the OpenAITokenCounter pattern: a lazily built client in warm_up(), auto-warmup inside count(), and a close() lifecycle method. Inputs are assembled exactly as GoogleGenAIChatGenerator sends them, so a leading system message is measured as the system instruction rather than as one of the request contents. A system instruction and tool schemas are only measurable when the client targets Vertex AI. The Google Gen AI SDK raises on both in Gemini Developer API mode, so the counter rejects them up front instead of returning a count that silently omits tool schemas.
pma1999
force-pushed
the
feat/google-genai-token-counter
branch
from
August 28, 2026 23:54
37dd932 to
469a179
Compare
The other integration tests in this integration guard on the API key environment variable, so they skip on fork PRs, which have no access to repo secrets. The new live test was missing that guard and failed the Linux 3.10 leg instead of skipping. Guards on GOOGLE_API_KEY or GEMINI_API_KEY, matching the pair the counter itself resolves.
Contributor
Coverage report (google_genai)Click to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related Issues
GoogleGenAITokenCounterto google-genai integration #3857Proposed Changes:
Adds
GoogleGenAITokenCounterto thegoogle_genaiintegration, implementing theTokenCounterprotocol introduced in Haystack 3.1 on top of Google'scountTokensendpoint — the Gemini analogue ofOpenAITokenCounter.It follows the
OpenAITokenCounterpattern:modelis required and never assumed, everything after it is keyword-only, the client is built lazily inwarm_up(),count()auto-warms, and there is aclose()lifecycle method. The constructor mirrorsGoogleGenAIChatGenerator(api,vertex_ai_project,vertex_ai_location,timeout,max_retries) so a counter can be configured exactly like the generator it measures.Inputs are assembled the way
GoogleGenAIChatGeneratorsends them: a leading system message becomes the system instruction, the remaining messages become the request contents.One design decision I'd like your call on
The Google Gen AI SDK cannot measure a system instruction or tool schemas on the Gemini Developer API. It is not a silent drop —
_CountTokensConfig_to_mldevraises explicitly:_CountTokensConfig_to_vertexmaps both, so Vertex is fine. Worth noting the REST API itself could do it viagenerateContentRequest, which accepts system instructions and function declarations — but the Python SDK does not expose that field anywhere, so there is no supported path to it today.Since
count(messages, tools)has to answer for both, I chose to raise aValueErrornaming the limitation and pointing atapi="vertex", rather than return a count that silently omits tool schemas — those can be worth hundreds of tokens, and a counter that quietly under-reports seemed worse than one that refuses. Counting plain messages works on either backend.Happy to switch to a warning plus a partial count if you'd rather the component always return a number.
How did you test it?
hatch run test:unit— 9 new unit tests pass. They cover serde round-trip, the empty-input short circuit, thetotal_tokens: Nonecase, the rejection path for both a system message and tools, that Vertex actually forwards the system instruction and tool schemas, andclose().hatch run test:integration— the live test passes against the real Gemini API.hatch run test:types— mypy clean (the new package is registered in thetypescommand).hatch run fmt-check— clean.Two failures in the full unit run (
test_init_fail_wo_api_key,test_extract_sources_info_rejects_symlink_escaping_root) are unrelated to this change: they reproduce identically on a clean checkout ofmainon my machine — the first because I haveGEMINI_API_KEYexported and the test only clearsGOOGLE_API_KEY, the second because of Windows symlink permissions.The live test deliberately covers a user turn, an assistant tool call and a tool result, but not a system message or tools, since the Gemini Developer API these tests authenticate against cannot measure those.