fix(gemini): read the major version instead of matching "gemini-3"

The substring check would have reported Gemini 4 and later as pre-3,
reintroducing the same class of bug the moment Google ships an explicitly
versioned `gemini-4-*` model. Parsing the major version off the name and
comparing against 3 makes every later release work without a code change,
and it also excludes `gemini-2.5-flash-native-audio-latest` on version
rather than by special-casing the name.

The alias set now covers only names that carry no version at all.
This commit is contained in:
maya-lukas 2026-08-17 10:34:49 +02:00
parent d7cbfc7759
commit a686f36f0c
2 changed files with 21 additions and 15 deletions

View file

@ -2,6 +2,7 @@
## httpx client for vertex ai calls
## Initial implementation - covers gemini + image gen calls
import json
import re
import time
from collections.abc import Callable, Mapping, Sequence
from copy import deepcopy
@ -106,6 +107,8 @@ else:
StreamingChoices = Any
GEMINI_MAJOR_VERSION_PATTERN: Final[re.Pattern[str]] = re.compile(r"gemini-(\d+)")
GEMINI_ROLLING_LATEST_ALIASES: Final[frozenset[str]] = frozenset(
{
"gemini-flash-latest",
@ -266,23 +269,17 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
@staticmethod
def _is_gemini_3_or_newer(model: str) -> bool:
"""
Check if the model is Gemini 3 Pro or newer.
Check if the model is Gemini 3 or newer, e.g. gemini-3-pro-preview,
gemini-3.1-flash, gemini-3.5-flash, and every later major version.
Gemini 3 models include:
- gemini-3-pro-preview
- gemini-3-flash
- gemini-3-flash-preview (Gemini 3 Flash)
- gemini-3.1-pro-preview, gemini-3.1-flash, gemini-3.1-flash-lite-preview
- gemini-3.5-flash
- Any future Gemini 3.x models
- GEMINI_ROLLING_LATEST_ALIASES, which resolve to Gemini 3.x and carry
no version number of their own. Matched by exact name, since
versioned names such as `gemini-2.5-flash-native-audio-latest` also
end in `-latest` yet are not Gemini 3
The major version is read off the model name, so Gemini 4 and beyond
satisfy this without a code change. Names carrying no version at all are
matched against GEMINI_ROLLING_LATEST_ALIASES, which always resolve to
the newest release of their tier.
"""
# Check for Gemini 3 models
if "gemini-3" in model:
return True
major_version: Final = GEMINI_MAJOR_VERSION_PATTERN.search(model)
if major_version is not None:
return int(major_version.group(1)) >= 3
return model.split("/")[-1] in GEMINI_ROLLING_LATEST_ALIASES
@staticmethod

View file

@ -2292,6 +2292,15 @@ def test_is_gemini_3_or_newer():
== False
)
# Later major versions must satisfy this without a code change
assert VertexGeminiConfig._is_gemini_3_or_newer("gemini-4-flash") == True
assert VertexGeminiConfig._is_gemini_3_or_newer("gemini-4.2-pro-preview") == True
assert VertexGeminiConfig._is_gemini_3_or_newer("gemini/gemini-10-flash") == True
# Unversioned names that are not rolling aliases stay excluded
assert VertexGeminiConfig._is_gemini_3_or_newer("gemini-embedding-001") == False
assert VertexGeminiConfig._is_gemini_3_or_newer("gemini-exp-1206") == False
def test_thought_signature_fallback_for_rolling_latest_alias():
"""