fix(vertex-ai): gate resolution inference by pricing metadata

This commit is contained in:
Emerson Gomes 2026-07-15 21:22:39 -05:00
parent 9012842c2f
commit d6e859cc97
No known key found for this signature in database
GPG key ID: D3DF28AB5D1B5E17
2 changed files with 49 additions and 7 deletions

View file

@ -12,6 +12,7 @@ from typing import TYPE_CHECKING, Any, Final, cast
import httpx
from httpx._types import RequestFiles
import litellm
from litellm.constants import DEFAULT_GOOGLE_VIDEO_DURATION_SECONDS
from litellm.images.utils import ImageEditRequestUtils
from litellm.llms.base_llm.videos.transformation import BaseVideoConfig
@ -146,7 +147,7 @@ class VertexAIVideoConfig(BaseVideoConfig, VertexBase):
- prompt prompt (in instances)
- input_reference image (in instances)
- size aspectRatio (e.g., "1280x720" "16:9")
- size resolution for Veo 3 models when inferable
- size resolution for models with resolution-tier pricing when inferable
("1280x720"/"720x1280" "720p", "1920x1080"/"1080x1920" "1080p");
skipped if ``resolution`` is already set
- seconds durationSeconds (defaults to 4 seconds if not provided)
@ -177,7 +178,7 @@ class VertexAIVideoConfig(BaseVideoConfig, VertexBase):
has_resolution = "resolution" in mapped_params or (
isinstance(nested_params, dict) and nested_params.get("resolution") is not None
)
supports_resolution = model.removeprefix("vertex_ai/").startswith("veo-3.")
supports_resolution = self._supports_resolution_inference(model)
if supports_resolution and not has_resolution:
inferred_resolution = self._convert_size_to_resolution(size)
if inferred_resolution is not None:
@ -210,6 +211,12 @@ class VertexAIVideoConfig(BaseVideoConfig, VertexBase):
def _convert_size_to_resolution(self, size: str) -> str | None:
return self._OPENAI_VIDEO_SIZE_TO_RESOLUTION.get(size)
@staticmethod
def _supports_resolution_inference(model: str) -> bool:
model_key = model if model.startswith("vertex_ai/") else f"vertex_ai/{model}"
model_info = litellm.model_cost.get(model_key, {})
return model_info.get("output_cost_per_second_1080p") is not None
def validate_environment(
self,
headers: dict,

View file

@ -288,15 +288,33 @@ class TestVertexAIVideoConfig:
assert "resolution" not in mapped
@pytest.mark.parametrize(
("size", "expected_resolution"),
(("1280x720", "720p"), ("1920x1080", "1080p")),
("model", "size", "expected_resolution"),
(
(VEO_31_LITE_VERTEX_MODEL, "1280x720", "720p"),
(
VEO_31_LITE_VERTEX_MODEL.removeprefix("vertex_ai/"),
"1920x1080",
"1080p",
),
),
)
def test_map_openai_size_to_resolution_for_veo_3(
self, size: str, expected_resolution: str
def test_map_openai_size_to_resolution_for_resolution_tier_model(
self,
model: str,
size: str,
expected_resolution: str,
monkeypatch: pytest.MonkeyPatch,
):
model_cost = _load_model_cost_map(BACKUP_MODEL_COST_PATH)
monkeypatch.setitem(
litellm.model_cost,
VEO_31_LITE_VERTEX_MODEL,
dict(model_cost[VEO_31_LITE_VERTEX_MODEL]),
)
mapped = self.config.map_openai_params(
video_create_optional_params={"size": size},
model=VEO_31_LITE_VERTEX_MODEL,
model=model,
drop_params=False,
)
@ -313,6 +331,23 @@ class TestVertexAIVideoConfig:
assert mapped["aspectRatio"] == "16:9"
assert "resolution" not in mapped
def test_map_openai_size_does_not_infer_resolution_for_existing_veo_3(
self, monkeypatch: pytest.MonkeyPatch
):
model = "veo-3.1-generate-001"
model_key = f"vertex_ai/{model}"
model_cost = _load_model_cost_map(BACKUP_MODEL_COST_PATH)
monkeypatch.setitem(litellm.model_cost, model_key, dict(model_cost[model_key]))
mapped = self.config.map_openai_params(
video_create_optional_params={"size": "1920x1080"},
model=model,
drop_params=False,
)
assert mapped["aspectRatio"] == "16:9"
assert "resolution" not in mapped
def test_map_openai_size_does_not_override_provider_resolution(self):
mapped = self.config.map_openai_params(
video_create_optional_params={