feat(client)!: replace google-generativeai formatter with google-genai - #15085
Conversation
Adds a new `google_genai` SDK option for prompt formatting that uses the new `google-genai` package (google.genai.types) instead of the legacy `google-generativeai` package, which conflicts with modern protobuf requirements (e.g. langgraph-api requires protobuf>=6 while the legacy SDK requires protobuf<6). - Add phoenix.client.helpers.sdk.google_genai.generate_content with message, tool, tool-config, and schema conversions targeting google.genai.types - Route PromptVersion.format(sdk="google_genai") to the new formatter via a new GoogleGenAIPrompt dataclass - Keep GOOGLE's default SDK as google_generativeai for backwards compatibility, falling back to google_genai when only the new package is installed - Wire tools and tool_config into GenerateContentConfig, and extract system messages into config.system_instruction without going through role conversion (which rejects the system role) - Add canary tests, tox env, and CI matrix entry for google_genai Fixes #15040 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P6GyGpRZboFCLUJnjbLND1
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
Addresses review findings on the new google_genai formatter, using the server-side converter in playground_clients.py as the reference: - Emit function_call / function_response parts for tool_call and tool_result content instead of dropping them. Previously such messages collapsed to Content(parts=[]), which Gemini rejects, so every multi-turn tool-calling prompt failed at call time. Tool results are matched to their originating call by function name, which is how Google identifies them, and never yield an empty Content. - Send tool parameters via FunctionDeclaration.parameters_json_schema so constructs genai_types.Schema cannot express (anyOf, $ref/$defs, default) survive verbatim. An Optional[...] property previously became an empty untyped Schema. The lossy Schema.to_google direction is now unused and removed; from_google is kept for the reverse direction. - Propagate the thinking_config invocation parameter, guarding thinking_level behind google-genai>=1.50.0 where it was introduced. - Propagate response_format as response_mime_type/response_json_schema, matching the OpenAI formatter. - Support raw tools via Tool.model_validate, omit tool_config when no function declarations are present (Google rejects it for built-in tools such as google_search), and stop emitting a degenerate Tool(function_declarations=[]). - Correct the _default_google_sdk docstring: the two Google SDKs do not conflict with each other; the legacy package's protobuf<6 pin is what conflicts with protobuf>=6 consumers. Tests now cover the to_google direction, which the round-trip tests could not reach. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P6GyGpRZboFCLUJnjbLND1
|
Pushed b9c441c, which closes six conversion gaps found while reviewing the new formatter. I used the server-side converter in Two were functional bugs I reproduced before fixing:
Also: I also corrected the One finding I deliberately left alone, since it's your call: Tests now cover the Generated by Claude Code |
|
Flagged priority: high — @RogerHYang you're the assignee on this one, please take a review pass. Raised during standup triage on 2026-08-10. |
The maintained google-genai integration is now the sole Google formatter, removing the deprecated SDK and its incompatible protobuf constraint.
Release automation owns the client changelog, so the breaking change remains communicated through the pull request description.
Keep package instructions and prompt examples aligned with the maintained Google SDK after removing the legacy formatter.
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
Run client and canary formatter checks against the current supported Google GenAI SDK release.
Test-environment maintenance should not trigger an arize-phoenix release.
…ebook The Google migration rewrote the import cell and dropped `to_chat_messages_and_kwargs`, leaving five cells (OpenAI, Anthropic, HuggingFace, Ollama, Mistral) calling an undefined name, which failed ruff F821 and the Format and Lint gate. Rather than restore that import, those cells now use `prompt_version.format(variables=..., sdk=...)`, matching the migrated Google cell. The old helper was imported from `phoenix.client.utils`, which has never exported it, so the cells were broken at runtime regardless. Also runs ruff format/check and the notebook cleaner over the two notebooks touched by the migration, so `Format and Lint` and `Clean Jupyter Notebooks` both pass with no residual diff. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P6GyGpRZboFCLUJnjbLND1
|
Pushed fe04d0d to green up What was broken: the migration rewrote cell 0's imports in How I fixed it: rather than restore that import, those five cells now use I also ran ruff format/check and the notebook cleaner over both notebooks the migration touched. The import ordering ( Confirmed locally on top of e12fdb1: Two notes on the earlier red checks, for the record: most of the Generated by Claude Code |
Exercise the public PromptVersion path so Google prompts use the maintained SDK without an explicit formatter selection.
Exercise persisted Google prompts through the same public-client integration suite as other prompt round-trip behavior.
Support creating prompt versions from Google GenAI generate-content parameters and validate the public client round trip.
Reject unsupported content explicitly and extend round-trip coverage so Google prompt imports do not silently lose data.
Raise a stable error for file-based system instructions rather than crashing while converting them.
The new Google GenAI integration coverage placed the phoenix.client imports after pydantic and typing_extensions, which ruff's isort rules reject in this directory. Applies `ruff check --fix` so `Format and Lint` passes with no residual diff. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P6GyGpRZboFCLUJnjbLND1
Preserve supported schemas and tool results, while rejecting forms Phoenix cannot represent faithfully.
Fail explicitly for thought and unsupported response-format inputs rather than dropping their semantics.
Use function names as stable Phoenix tool-call keys when the Google SDK omits response IDs.
The id-less function response guard exceeded the 100 character line limit, failing `Format and Lint`. Rewraps the string without changing the message, so the `pytest.raises(match="id, name")` assertion still holds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P6GyGpRZboFCLUJnjbLND1
|
@RogerHYang I've pushed two follow-up commits to keep One request that would save us both a round trip: running I reviewed the conversion work in e80bcf0, 8d3d6dd, d13a1d0, f9ad471, and 31fe20e and it looks sound to me. Resolving id-less function responses by name against preceding calls is the right call — Google matches on name, and the paired Also flagging one stale line in the PR description, since it's now the reviewer-facing record: it says the migration is recorded in the client changelog, but 87e6f90 removed that entry on the grounds that release automation owns it. Generated by Claude Code |
Keep explicit null schema defaults and id-less tool calls stable across round trips while aligning server types and tutorial usage with the current SDK.
The canary pyright config pins pythonVersion to 3.9, so the `str | None` annotation added for the id-less function response assertions failed the `google_genai` canary job with reportGeneralTypeIssues. Uses `Optional[str]` instead and notes why. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P6GyGpRZboFCLUJnjbLND1
Align SDK checks with the supported Python 3.10 floor and satisfy the newer release's stricter unknown-type diagnostics.
The latest release surfaces 51 existing strict-mode diagnostics in the client package; defer that upgrade to a dedicated cleanup.
Preserve empty text parts and reject empty messages instead of silently dropping them during prompt conversion.
Card links checkNo broken Card links found. Checked external links in 16.9s |
Resolves #15040
Summary
Phoenix prompt formatting now supports only the maintained
google-genaiSDK. This removes the deprecatedgoogle-generativeaiformatter, whose protobuf constraint conflicts with LangGraph environments requiring protobuf 6 or newer.Breaking change
PromptVersion.format(sdk=\"google_generativeai\")is removed.PromptVersion.from_google_generativeai()is removed.google-genai; installgoogle-genaiand callPromptVersion.format()(or passsdk=\"google_genai\").Changes
model_provider=\"GOOGLE\"directly to the Google Gen AI formatter.Testing
uvx tox run -e phoenix_client_canary_tests_sdk_google_genaiuvx tox run -e phoenix_client -- -ra -x