chore: initial public snapshot for github upload
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
from io import BufferedReader, BytesIO
|
||||
from typing import Any, Dict, List, Optional, cast, get_type_hints
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.token_counter import get_image_type
|
||||
from litellm.llms.base_llm.image_edit.transformation import BaseImageEditConfig
|
||||
from litellm.types.files import FILE_MIME_TYPES, FileType
|
||||
from litellm.types.images.main import ImageEditOptionalRequestParams
|
||||
|
||||
|
||||
class ImageEditRequestUtils:
|
||||
@staticmethod
|
||||
def get_optional_params_image_edit(
|
||||
model: str,
|
||||
image_edit_provider_config: BaseImageEditConfig,
|
||||
image_edit_optional_params: ImageEditOptionalRequestParams,
|
||||
drop_params: Optional[bool] = None,
|
||||
additional_drop_params: Optional[List[str]] = None,
|
||||
) -> Dict:
|
||||
"""
|
||||
Get optional parameters for the image edit API.
|
||||
|
||||
Args:
|
||||
model: The model name
|
||||
image_edit_provider_config: The provider configuration for image edit API
|
||||
image_edit_optional_params: The optional parameters for the image edit API
|
||||
drop_params: If True, silently drop unsupported parameters instead of raising
|
||||
additional_drop_params: List of additional parameter names to drop
|
||||
|
||||
Returns:
|
||||
A dictionary of supported parameters for the image edit API
|
||||
"""
|
||||
supported_params = image_edit_provider_config.get_supported_openai_params(model)
|
||||
|
||||
should_drop = litellm.drop_params is True or drop_params is True
|
||||
|
||||
filtered_optional_params = dict(image_edit_optional_params)
|
||||
if additional_drop_params:
|
||||
for param in additional_drop_params:
|
||||
filtered_optional_params.pop(param, None)
|
||||
|
||||
unsupported_params = [
|
||||
param for param in filtered_optional_params if param not in supported_params
|
||||
]
|
||||
|
||||
if unsupported_params:
|
||||
if should_drop:
|
||||
for param in unsupported_params:
|
||||
filtered_optional_params.pop(param, None)
|
||||
else:
|
||||
raise litellm.UnsupportedParamsError(
|
||||
model=model,
|
||||
message=f"The following parameters are not supported for model {model}: {', '.join(unsupported_params)}",
|
||||
)
|
||||
|
||||
mapped_params = image_edit_provider_config.map_openai_params(
|
||||
image_edit_optional_params=cast(
|
||||
ImageEditOptionalRequestParams, filtered_optional_params
|
||||
),
|
||||
model=model,
|
||||
drop_params=should_drop,
|
||||
)
|
||||
|
||||
return mapped_params
|
||||
|
||||
@staticmethod
|
||||
def get_requested_image_edit_optional_param(
|
||||
params: Dict[str, Any],
|
||||
) -> ImageEditOptionalRequestParams:
|
||||
"""
|
||||
Filter parameters to only include those defined in ImageEditOptionalRequestParams.
|
||||
|
||||
Args:
|
||||
params: Dictionary of parameters to filter
|
||||
|
||||
Returns:
|
||||
ImageEditOptionalRequestParams instance with only the valid parameters
|
||||
"""
|
||||
valid_keys = get_type_hints(ImageEditOptionalRequestParams).keys()
|
||||
filtered_params = {
|
||||
k: v for k, v in params.items() if k in valid_keys and v is not None
|
||||
}
|
||||
return cast(ImageEditOptionalRequestParams, filtered_params)
|
||||
|
||||
@staticmethod
|
||||
def get_image_content_type(image_data: Any) -> str:
|
||||
"""
|
||||
Detect the content type of image data using existing LiteLLM utils.
|
||||
|
||||
Args:
|
||||
image_data: Can be BytesIO, bytes, BufferedReader, or other file-like objects
|
||||
|
||||
Returns:
|
||||
The MIME type string (e.g., "image/png", "image/jpeg")
|
||||
"""
|
||||
try:
|
||||
# Extract bytes for content type detection
|
||||
if isinstance(image_data, BytesIO):
|
||||
# Save current position
|
||||
current_pos = image_data.tell()
|
||||
image_data.seek(0)
|
||||
bytes_data = image_data.read(
|
||||
100
|
||||
) # First 100 bytes are enough for detection
|
||||
# Restore position
|
||||
image_data.seek(current_pos)
|
||||
elif isinstance(image_data, BufferedReader):
|
||||
# Save current position
|
||||
current_pos = image_data.tell()
|
||||
image_data.seek(0)
|
||||
bytes_data = image_data.read(100)
|
||||
# Restore position
|
||||
image_data.seek(current_pos)
|
||||
elif isinstance(image_data, bytes):
|
||||
bytes_data = image_data[:100]
|
||||
else:
|
||||
# For other types, try to read if possible
|
||||
if hasattr(image_data, "read"):
|
||||
current_pos = getattr(image_data, "tell", lambda: 0)()
|
||||
if hasattr(image_data, "seek"):
|
||||
image_data.seek(0)
|
||||
bytes_data = image_data.read(100)
|
||||
if hasattr(image_data, "seek"):
|
||||
image_data.seek(current_pos)
|
||||
else:
|
||||
return FILE_MIME_TYPES[FileType.PNG] # Default fallback
|
||||
|
||||
# Use the existing get_image_type function to detect image type
|
||||
image_type_str = get_image_type(bytes_data)
|
||||
|
||||
if image_type_str is None:
|
||||
return FILE_MIME_TYPES[FileType.PNG] # Default if detection fails
|
||||
|
||||
# Map detected type string to FileType enum and get MIME type
|
||||
type_mapping = {
|
||||
"png": FileType.PNG,
|
||||
"jpeg": FileType.JPEG,
|
||||
"gif": FileType.GIF,
|
||||
"webp": FileType.WEBP,
|
||||
"heic": FileType.HEIC,
|
||||
}
|
||||
|
||||
file_type = type_mapping.get(image_type_str)
|
||||
if file_type is None:
|
||||
return FILE_MIME_TYPES[FileType.PNG] # Default to PNG if unknown
|
||||
|
||||
return FILE_MIME_TYPES[file_type]
|
||||
|
||||
except Exception:
|
||||
# If anything goes wrong, default to PNG
|
||||
return FILE_MIME_TYPES[FileType.PNG]
|
||||
Reference in New Issue
Block a user