mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-14 09:03:16 +00:00
fix(minimax): satisfy type discipline checks
This commit is contained in:
parent
aab5d68eb4
commit
890ee4b423
2 changed files with 73 additions and 60 deletions
|
|
@ -6,7 +6,7 @@ from litellm.llms.base_llm.image_generation.transformation import (
|
|||
|
||||
from .transformation import MinimaxImageGenerationConfig
|
||||
|
||||
__all__ = ["MinimaxImageGenerationConfig", "get_minimax_image_generation_config"]
|
||||
__all__ = ("MinimaxImageGenerationConfig", "get_minimax_image_generation_config")
|
||||
|
||||
|
||||
def get_minimax_image_generation_config(model: str) -> BaseImageGenerationConfig:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ Response format:
|
|||
Reference: https://platform.minimax.io/docs/api-reference/image-generation-t2i
|
||||
"""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from types import MappingProxyType
|
||||
from typing import TYPE_CHECKING, Final
|
||||
|
||||
import httpx
|
||||
|
||||
|
|
@ -43,17 +44,15 @@ from litellm.types.utils import ImageObject, ImageResponse
|
|||
if TYPE_CHECKING:
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
|
||||
|
||||
LiteLLMLoggingObj = _LiteLLMLoggingObj
|
||||
LiteLLMLoggingObj = _LiteLLMLoggingObj # rebind-ok: conditional runtime/type-checking alias
|
||||
else:
|
||||
LiteLLMLoggingObj = object
|
||||
LiteLLMLoggingObj = object # rebind-ok: conditional runtime/type-checking alias
|
||||
|
||||
DEFAULT_API_BASE = "https://api.minimax.io"
|
||||
IMAGE_GENERATION_ENDPOINT = "/v1/image_generation"
|
||||
DEFAULT_API_BASE: Final = "https://api.minimax.io"
|
||||
IMAGE_GENERATION_ENDPOINT: Final = "/v1/image_generation"
|
||||
|
||||
# OpenAI uses "b64_json", MiniMax uses "base64".
|
||||
OPENAI_TO_MINIMAX_RESPONSE_FORMAT = {
|
||||
"b64_json": "base64",
|
||||
}
|
||||
OPENAI_TO_MINIMAX_RESPONSE_FORMAT: Final = MappingProxyType({"b64_json": "base64"})
|
||||
|
||||
|
||||
class MinimaxImageGenerationException(BaseLLMException):
|
||||
|
|
@ -63,7 +62,7 @@ class MinimaxImageGenerationException(BaseLLMException):
|
|||
self,
|
||||
status_code: int,
|
||||
message: str,
|
||||
headers: dict | httpx.Headers | None = None,
|
||||
headers: dict | httpx.Headers | None = None, # mutable-ok: BaseLLMException interface requires dict
|
||||
) -> None:
|
||||
super().__init__(status_code=status_code, message=message, headers=headers)
|
||||
|
||||
|
|
@ -73,16 +72,25 @@ class MinimaxImageGenerationConfig(BaseImageGenerationConfig):
|
|||
Configuration for MiniMax image generation models (image-01, image-01-live).
|
||||
"""
|
||||
|
||||
def get_supported_openai_params(self, model: str) -> list[OpenAIImageGenerationOptionalParams]:
|
||||
return ["n", "size", "response_format", "seed", "user", "aspect_ratio"]
|
||||
def get_supported_openai_params(
|
||||
self, model: str
|
||||
) -> list[OpenAIImageGenerationOptionalParams]: # mutable-ok: BaseImageGenerationConfig returns list
|
||||
return [ # mutable-ok: BaseImageGenerationConfig returns a mutable parameter list
|
||||
"n",
|
||||
"size",
|
||||
"response_format",
|
||||
"seed",
|
||||
"user",
|
||||
"aspect_ratio",
|
||||
]
|
||||
|
||||
def map_openai_params(
|
||||
self,
|
||||
non_default_params: dict,
|
||||
optional_params: dict,
|
||||
non_default_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
optional_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
model: str,
|
||||
drop_params: bool,
|
||||
) -> dict:
|
||||
) -> dict: # mutable-ok: BaseImageGenerationConfig interface returns dict
|
||||
"""
|
||||
Map OpenAI image generation params to MiniMax params.
|
||||
|
||||
|
|
@ -90,77 +98,82 @@ class MinimaxImageGenerationConfig(BaseImageGenerationConfig):
|
|||
- `response_format` "b64_json" is mapped to "base64"
|
||||
- remaining supported params are passed through
|
||||
"""
|
||||
supported_params = self.get_supported_openai_params(model)
|
||||
supported_params: Final = self.get_supported_openai_params(model)
|
||||
mapped_params: Final = dict( # mutable-ok: provider interface returns a mutable request mapping
|
||||
optional_params
|
||||
)
|
||||
for k, v in non_default_params.items():
|
||||
if k in optional_params:
|
||||
if k in mapped_params:
|
||||
continue
|
||||
if k not in supported_params:
|
||||
continue
|
||||
if k == "size":
|
||||
width, height = self._parse_size(v)
|
||||
if width is not None and height is not None:
|
||||
optional_params["width"] = width
|
||||
optional_params["height"] = height
|
||||
mapped_params["width"] = width
|
||||
mapped_params["height"] = height
|
||||
elif k == "response_format":
|
||||
optional_params["response_format"] = OPENAI_TO_MINIMAX_RESPONSE_FORMAT.get(v, v)
|
||||
mapped_params["response_format"] = OPENAI_TO_MINIMAX_RESPONSE_FORMAT.get(v, v)
|
||||
else:
|
||||
optional_params[k] = v
|
||||
return optional_params
|
||||
mapped_params[k] = v
|
||||
return mapped_params
|
||||
|
||||
def get_complete_url(
|
||||
self,
|
||||
api_base: str | None,
|
||||
api_key: str | None,
|
||||
model: str,
|
||||
optional_params: dict,
|
||||
litellm_params: dict,
|
||||
optional_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
litellm_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
stream: bool | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Build the MiniMax image generation endpoint URL.
|
||||
"""
|
||||
base_url: str = api_base or get_secret_str("MINIMAX_API_BASE") or DEFAULT_API_BASE
|
||||
base_url = base_url.rstrip("/")
|
||||
if base_url.endswith(IMAGE_GENERATION_ENDPOINT):
|
||||
base_url = base_url.removesuffix(IMAGE_GENERATION_ENDPOINT)
|
||||
if not base_url.endswith("/v1"):
|
||||
base_url = f"{base_url}/v1"
|
||||
return f"{base_url}/image_generation"
|
||||
configured_base_url: Final = api_base or get_secret_str("MINIMAX_API_BASE") or DEFAULT_API_BASE
|
||||
endpoint_base_url: Final = configured_base_url.rstrip("/").removesuffix(IMAGE_GENERATION_ENDPOINT)
|
||||
versioned_base_url: Final = (
|
||||
endpoint_base_url if endpoint_base_url.endswith("/v1") else f"{endpoint_base_url}/v1"
|
||||
)
|
||||
return f"{versioned_base_url}/image_generation"
|
||||
|
||||
def validate_environment(
|
||||
self,
|
||||
headers: dict,
|
||||
headers: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
model: str,
|
||||
messages: list[AllMessageValues],
|
||||
optional_params: dict,
|
||||
litellm_params: dict,
|
||||
messages: list[AllMessageValues], # mutable-ok: BaseImageGenerationConfig interface requires list
|
||||
optional_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
litellm_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
api_key: str | None = None,
|
||||
api_base: str | None = None,
|
||||
) -> dict:
|
||||
) -> dict: # mutable-ok: BaseImageGenerationConfig interface returns dict
|
||||
"""
|
||||
Validate the MiniMax environment and set auth headers.
|
||||
"""
|
||||
final_api_key: str | None = api_key or get_secret_str("MINIMAX_API_KEY") or litellm.api_key
|
||||
final_api_key: Final[str | None] = api_key or get_secret_str("MINIMAX_API_KEY") or litellm.api_key
|
||||
if not final_api_key:
|
||||
raise ValueError(
|
||||
"MiniMax API key is required. Set MINIMAX_API_KEY environment variable or pass api_key parameter."
|
||||
)
|
||||
headers["Authorization"] = f"Bearer {final_api_key}"
|
||||
headers["Content-Type"] = "application/json"
|
||||
return headers
|
||||
validated_headers: Final = dict( # mutable-ok: provider interface returns fresh mutable headers
|
||||
headers
|
||||
)
|
||||
validated_headers["Authorization"] = f"Bearer {final_api_key}"
|
||||
validated_headers["Content-Type"] = "application/json"
|
||||
return validated_headers
|
||||
|
||||
def transform_image_generation_request(
|
||||
self,
|
||||
model: str,
|
||||
prompt: str,
|
||||
optional_params: dict,
|
||||
litellm_params: dict,
|
||||
headers: dict,
|
||||
) -> dict:
|
||||
optional_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
litellm_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
headers: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
) -> dict: # mutable-ok: BaseImageGenerationConfig interface returns dict
|
||||
"""
|
||||
Build the MiniMax image generation request body.
|
||||
"""
|
||||
request_data: dict = {
|
||||
request_data: Final = { # mutable-ok: request payload is assembled before being returned
|
||||
"model": model,
|
||||
"prompt": prompt,
|
||||
}
|
||||
|
|
@ -168,13 +181,13 @@ class MinimaxImageGenerationConfig(BaseImageGenerationConfig):
|
|||
for k, v in optional_params.items():
|
||||
if v is None:
|
||||
continue
|
||||
if k in {"extra_headers", "extra_body", "user"}:
|
||||
if k in ("extra_headers", "extra_body", "user"):
|
||||
continue
|
||||
request_data[k] = v
|
||||
|
||||
extra_body = optional_params.get("extra_body")
|
||||
extra_body: Final = optional_params.get("extra_body")
|
||||
if isinstance(extra_body, dict):
|
||||
request_data.update({k: v for k, v in extra_body.items() if v is not None})
|
||||
request_data.update((k, v) for k, v in extra_body.items() if v is not None)
|
||||
|
||||
return request_data
|
||||
|
||||
|
|
@ -184,9 +197,9 @@ class MinimaxImageGenerationConfig(BaseImageGenerationConfig):
|
|||
raw_response: httpx.Response,
|
||||
model_response: ImageResponse,
|
||||
logging_obj: LiteLLMLoggingObj,
|
||||
request_data: dict,
|
||||
optional_params: dict,
|
||||
litellm_params: dict,
|
||||
request_data: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
optional_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
litellm_params: dict, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
encoding: object,
|
||||
api_key: str | None = None,
|
||||
json_mode: bool | None = None,
|
||||
|
|
@ -198,7 +211,7 @@ class MinimaxImageGenerationConfig(BaseImageGenerationConfig):
|
|||
`data.image_base64` (response_format=base64).
|
||||
"""
|
||||
try:
|
||||
response_data = raw_response.json()
|
||||
response_data: Final = raw_response.json()
|
||||
except ValueError as e:
|
||||
raise self.get_error_class(
|
||||
error_message=f"Failed to parse MiniMax image generation response: {e}",
|
||||
|
|
@ -206,8 +219,8 @@ class MinimaxImageGenerationConfig(BaseImageGenerationConfig):
|
|||
headers=raw_response.headers,
|
||||
)
|
||||
|
||||
base_resp = response_data.get("base_resp") or {}
|
||||
status_code = base_resp.get("status_code")
|
||||
base_resp: Final = response_data.get("base_resp") or MappingProxyType({})
|
||||
status_code: Final = base_resp.get("status_code")
|
||||
if status_code not in (None, 0, "0"):
|
||||
raise self.get_error_class(
|
||||
error_message=str(base_resp.get("status_msg") or response_data),
|
||||
|
|
@ -216,12 +229,12 @@ class MinimaxImageGenerationConfig(BaseImageGenerationConfig):
|
|||
)
|
||||
|
||||
if not model_response.data:
|
||||
model_response.data = []
|
||||
model_response.data = [] # mutable-ok: ImageResponse schema requires list # rebind-ok: transformer populates the supplied response
|
||||
|
||||
data = response_data.get("data") or {}
|
||||
for image_url in data.get("image_urls") or []:
|
||||
data: Final = response_data.get("data") or MappingProxyType({})
|
||||
for image_url in data.get("image_urls") or ():
|
||||
model_response.data.append(ImageObject(url=image_url))
|
||||
for image_base64 in data.get("image_base64") or []:
|
||||
for image_base64 in data.get("image_base64") or ():
|
||||
model_response.data.append(ImageObject(b64_json=image_base64))
|
||||
|
||||
return model_response
|
||||
|
|
@ -230,7 +243,7 @@ class MinimaxImageGenerationConfig(BaseImageGenerationConfig):
|
|||
self,
|
||||
error_message: str,
|
||||
status_code: int,
|
||||
headers: dict | httpx.Headers,
|
||||
headers: dict | httpx.Headers, # mutable-ok: BaseImageGenerationConfig interface requires dict
|
||||
) -> BaseLLMException:
|
||||
return MinimaxImageGenerationException(
|
||||
status_code=status_code,
|
||||
|
|
@ -247,7 +260,7 @@ class MinimaxImageGenerationConfig(BaseImageGenerationConfig):
|
|||
"""
|
||||
if not isinstance(size, str) or "x" not in size:
|
||||
return None, None
|
||||
parts = size.split("x")
|
||||
parts: Final = size.split("x")
|
||||
if len(parts) != 2:
|
||||
return None, None
|
||||
try:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue