Skip to content

feat(py/plugins/google-genai): Vertex multimodal embeddings via :predict#5649

Merged
hilariie merged 7 commits into
mainfrom
feat/py-googleai-embedder-fixes
Jul 9, 2026
Merged

feat(py/plugins/google-genai): Vertex multimodal embeddings via :predict#5649
hilariie merged 7 commits into
mainfrom
feat/py-googleai-embedder-fixes

Conversation

@hilariie

@hilariie hilariie commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What

Adds working image and video embedding support for the Vertex AI multimodalembedding@001 model in the google-genai plugin, and registers correct output dimensions for multimodalembedding@001 and text-embedding-004.

Why

The plugin advertised multimodalembedding@001 as accepting image and video input but routed every embed request through embed_content. On Vertex AI that call drops non-text parts, so image and video requests failed at runtime with 400 INVALID_ARGUMENT "Empty instances.". The advertised output dimension of 768 is also not valid for this model; the default is 1408.

How

  • Route multimodal embedders through the Vertex :predict endpoint instead of embed_content. Embedder.generate() checks _is_multimodal() and dispatches to _generate_multimodal().
  • Build {text, image, video} prediction instances per document. Image and video references map gs:// URLs to gcsUri and data: URLs to bytesBase64Encoded; http(s) URLs are rejected, since Vertex only accepts gs:// there. An optional video segment config is read from document metadata.
  • Parse predictions[] into one Embedding per image, text, and video chunk, tagging each with metadata.embedType and preserving video chunk offsets.
  • Advertise multimodalembedding@001 from the curated VERTEX_KNOWN_EMBEDDERS list rather than model discovery: the Vertex catalog over-lists embedders and returns supported_actions=None, so Vertex embedders are curated, not discovered.
  • Resolve dimensions and supported inputs by exact name, with a fallback to the version-stripped base name.
  • Register output dimensions: multimodalembedding 1408 (model default; valid values 128/256/512/1408) and text-embedding-004 768.

Testing

  • uv run --directory py pytest plugins/google-genai/test/google_plugin_test.py plugins/google-genai/test/models/googlegenai_embedder_test.py (71 passed)
  • uv run --directory py ruff check and ruff format --check on the changed files (clean)

New tests cover the :predict request path and image/video result mapping, curated-list registration of multimodalembedding@001, and dimension and input metadata for bare and versioned model names.

Limitations

  • multimodalembedding@001 accepts a single instance per :predict call, so requests with more than one document are rejected with a clear error until batching is implemented. Single document embeds work.
  • The advertised dimension (1408) differs from the JS plugin, which still advertises 768.

Screenshots

Screenshot 2026-07-06 at 16 47 43 Screenshot 2026-06-29 at 16 46 56 Screenshot 2026-06-29 at 16 50 55 Screenshot 2026-06-29 at 16 53 24

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for Vertex AI multimodal embeddings by routing requests to the :predict endpoint when using multimodalembedding models. It handles the mapping of text, image, and video inputs, and parses the returned embeddings. Feedback on these changes includes addressing potential silent data loss when multiple media parts are provided in a single document, raising a ValueError for unsupported HTTP URLs in media references, and adding defensive checks to handle API prediction responses safely.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread py/plugins/google-genai/src/genkit/plugins/google_genai/models/embedder.py Outdated
@hilariie hilariie force-pushed the feat/py-googleai-gemini-embedding-2 branch from 0d74bba to 0ac4107 Compare July 6, 2026 14:58
@hilariie hilariie force-pushed the feat/py-googleai-embedder-fixes branch from ed65017 to a19b688 Compare July 6, 2026 15:41

@cabljac cabljac left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Real fix and the test coverage on the rejection cases is thorough. A handful of questions below before this lands, mostly about the new :predict path's edges.

Comment thread py/plugins/google-genai/src/genkit/plugins/google_genai/models/embedder.py Outdated
Comment thread py/plugins/google-genai/src/genkit/plugins/google_genai/models/embedder.py Outdated
@github-actions github-actions Bot added the config label Jul 8, 2026
@hilariie hilariie force-pushed the feat/py-googleai-embedder-fixes branch from d175056 to 0587208 Compare July 8, 2026 10:40

@cabljac cabljac left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Base automatically changed from feat/py-googleai-gemini-embedding-2 to main July 8, 2026 16:35
hilariie added 6 commits July 8, 2026 19:07
…video embeddings

Route Vertex multimodalembedding@001 through the :predict endpoint
instead of embed_content, which silently drops non-text parts on Vertex.
Build {text,image,video} instances, map gs:// and data: URLs, and return
one embedding per image/text/video chunk. Advertise it from the curated
VERTEX_KNOWN_EMBEDDERS list (the Vertex catalog over-lists embedders and
returns supported_actions=None, so they are not discovered), with the
model's real default dimensions (1408). Mirrors the JS vertexai embedder.
…quests

multimodalembedding@001 accepts only one instance per :predict call, but
_generate_multimodal built one instance per input document, so embed_many
(or any multi-document EmbedRequest) sent an invalid multi-instance payload
that Vertex rejects with an opaque error. Reject len(input) > 1 up front with
a clear ValueError until batching is implemented.
Vertex multimodal embedding calls the private _api_client.async_request /
http_response.body seam, which is verified against google-genai 1.63.0. The
prior >=1.7.0 floor was merely the then-current release when attribution
headers landed (7283fc2), not a verified minimum for this code path.
…back

- Restrict multimodalembedding@001 to Vertex AI via an explicit is_vertex
  flag threaded from the plugin; googleai/multimodalembedding@001 requests now
  raise instead of POSTing :predict on an API-key client.
- Guard the private google-genai transport, raising a clear error naming
  google-genai>=1.63.0 when _api_client.async_request is unavailable.
- Validate base64 data: URLs: require the ;base64, marker, else raise (fixes
  the comma-less IndexError and the silent non-base64 passthrough).
- Read snake_case output_dimensionality only, matching the text path, and stop
  dropping a literal 0.
- Document that one document fans out to multiple embeddings correlated by
  embedType metadata, not position.
- Annotate _media_reference return as dict[str, Any] (holds videoSegmentConfig).
@hilariie hilariie force-pushed the feat/py-googleai-embedder-fixes branch from 0587208 to 72da35f Compare July 8, 2026 18:17
@hilariie

hilariie commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

One post-approval change from the rebase: resolving conflicts with #5703, I initially dropped the is_vertex scoping that #5596 added to get_embedder_options. I've restored it, but as two per-backend supports maps instead of a boolean that forces text, as the boolean would have wrongly forced multimodalembedding@001 to advertise text-only. This matches how the JS plugin scopes embedder metadata (separate per-backend model tables): Vertex advertises multimodal only for multimodalembedding@001, Google AI only for gemini-embedding-2*, and unknown names default to text-only on both. The test_vertexai__resolve_embedder_scopes_supports_to_text test from #5596 is reinstated unchanged. Metadata-only; no runtime behaviour changes.

@hilariie hilariie requested a review from cabljac July 9, 2026 08:27
@hilariie hilariie merged commit c4b121b into main Jul 9, 2026
24 checks passed
@hilariie hilariie deleted the feat/py-googleai-embedder-fixes branch July 9, 2026 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants