mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-12 08:42:18 +00:00
fix(fal_ai): give MiniMax H3 Max video endpoints their own resolution profile (#51348)
* fix(fal_ai): give MiniMax H3 Max video endpoints their own resolution profile Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(fal_ai): keep the H3 Max test signature on one line Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(fal_ai): type the H3 Max test locals and signatures Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
19ffe3a5f2
commit
7c7e02b06f
2 changed files with 59 additions and 2 deletions
|
|
@ -45,7 +45,7 @@ _ALLOWED_ASPECT_RATIOS: Final[frozenset[str]] = frozenset({"auto", "16:9", "9:16
|
|||
class _ModelProfile:
|
||||
resolutions: frozenset[str]
|
||||
resolution_tiers: tuple[tuple[int, str], ...]
|
||||
default_resolution: str
|
||||
default_resolution: str | None
|
||||
integer_duration: bool
|
||||
reference_key: str
|
||||
reference_as_list: bool
|
||||
|
|
@ -67,6 +67,14 @@ _H3_PROFILE: Final[_ModelProfile] = _ModelProfile(
|
|||
reference_key="reference_image_urls",
|
||||
reference_as_list=True,
|
||||
)
|
||||
_H3_MAX_PROFILE: Final[_ModelProfile] = _ModelProfile(
|
||||
resolutions=frozenset({"480P", "768P", "1080P"}),
|
||||
resolution_tiers=((480, "480P"), (768, "768P"), (sys.maxsize, "1080P")),
|
||||
default_resolution=None,
|
||||
integer_duration=False,
|
||||
reference_key="image_url",
|
||||
reference_as_list=False,
|
||||
)
|
||||
_QUEUE_NAMESPACES: Final[frozenset[str]] = frozenset(("workflows", "comfy"))
|
||||
_STATUS_MAP: Final[Mapping[str, str]] = MappingProxyType(
|
||||
{
|
||||
|
|
@ -101,7 +109,11 @@ def _duration_value(value: object) -> str | None:
|
|||
|
||||
|
||||
def _profile_for_model(model: str) -> _ModelProfile:
|
||||
return _H3_PROFILE if model.startswith("minimax/h3/") else _SEEDANCE_PROFILE
|
||||
if model.startswith("minimax/h3/"):
|
||||
return _H3_PROFILE
|
||||
if model.startswith("minimax/h3-max"):
|
||||
return _H3_MAX_PROFILE
|
||||
return _SEEDANCE_PROFILE
|
||||
|
||||
|
||||
def _resolution_for_short_side(short_side: int, profile: _ModelProfile) -> str:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ from litellm.utils import ProviderConfigManager
|
|||
MODEL = "bytedance/seedance-2.5/text-to-video"
|
||||
H3_TEXT_MODEL = "minimax/h3/text-to-video"
|
||||
H3_REFERENCE_MODEL = "minimax/h3/reference-to-video"
|
||||
H3_MAX_TEXT_MODEL = "minimax/h3-max/text-to-video"
|
||||
H3_MAX_TURBO_IMAGE_MODEL = "minimax/h3-max-turbo/image-to-video"
|
||||
H3_MAX_RECAST_MODEL = "minimax/h3-max/recast"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("drop_params", [False, True])
|
||||
|
|
@ -96,6 +99,24 @@ class TestFalAIVideoTransformation:
|
|||
assert mapped["reference_image_urls"] == [url]
|
||||
assert "image_url" not in mapped
|
||||
|
||||
def test_map_openai_params_supports_h3_max_profile(self) -> None:
|
||||
url: Final = "https://example.com/image.png"
|
||||
|
||||
assert self.config.map_openai_params({"size": "768p"}, H3_MAX_TEXT_MODEL, False) == {"resolution": "768P"}
|
||||
assert self.config.map_openai_params({"size": "1920x1080"}, H3_MAX_TEXT_MODEL, False) == {
|
||||
"resolution": "1080P",
|
||||
"aspect_ratio": "16:9",
|
||||
}
|
||||
mapped: Final = self.config.map_openai_params(
|
||||
{"seconds": 5.5, "input_reference": url, "size": "1280x768"},
|
||||
H3_MAX_TURBO_IMAGE_MODEL,
|
||||
False,
|
||||
)
|
||||
assert mapped["resolution"] == "768P"
|
||||
assert mapped["image_url"] == url
|
||||
assert "reference_image_urls" not in mapped
|
||||
assert mapped["duration"] == "5"
|
||||
|
||||
def test_map_openai_params_h3_omits_auto_duration(self):
|
||||
assert self.config.map_openai_params({"seconds": "auto"}, H3_TEXT_MODEL, False) == {}
|
||||
assert self.config.map_openai_params({"seconds": "auto"}, MODEL, False) == {"duration": "auto"}
|
||||
|
|
@ -198,6 +219,30 @@ class TestFalAIVideoTransformation:
|
|||
|
||||
assert video.usage == {"duration_seconds": 5.0, "video_resolution": "2K"}
|
||||
|
||||
def test_transform_video_create_response_h3_max_leaves_default_resolution_to_cost_map(
|
||||
self, local_model_cost_map: None
|
||||
) -> None:
|
||||
response: Final = Mock(spec=httpx.Response)
|
||||
response.json.return_value = {"request_id": "abc"}
|
||||
|
||||
video: Final = self.config.transform_video_create_response(
|
||||
model=H3_MAX_RECAST_MODEL,
|
||||
raw_response=response,
|
||||
logging_obj=self.logging_obj,
|
||||
custom_llm_provider="fal_ai",
|
||||
request_data={"duration": 5},
|
||||
)
|
||||
|
||||
assert video.usage == {"duration_seconds": 5.0}
|
||||
row: Final = litellm.model_cost[f"fal_ai/{H3_MAX_RECAST_MODEL}"]
|
||||
assert default_video_cost_calculator(
|
||||
model=H3_MAX_RECAST_MODEL,
|
||||
duration_seconds=5.0,
|
||||
custom_llm_provider="fal_ai",
|
||||
model_info=None,
|
||||
video_resolution=None,
|
||||
) == pytest.approx(row["output_cost_per_second"] * 5.0)
|
||||
|
||||
def test_status_request_uses_queue_base_path(self):
|
||||
response = Mock(spec=httpx.Response)
|
||||
response.json.return_value = {"request_id": "abc"}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue