Spaces:
Paused
Paused
| from io import BufferedReader, BytesIO | |
| from typing import Any, Dict, 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: | |
| def get_optional_params_image_edit( | |
| model: str, | |
| image_edit_provider_config: BaseImageEditConfig, | |
| image_edit_optional_params: ImageEditOptionalRequestParams, | |
| ) -> Dict: | |
| """ | |
| Get optional parameters for the image edit API. | |
| Args: | |
| params: Dictionary of all parameters | |
| model: The model name | |
| image_edit_provider_config: The provider configuration for image edit API | |
| Returns: | |
| A dictionary of supported parameters for the image edit API | |
| """ | |
| # Remove None values and internal parameters | |
| # Get supported parameters for the model | |
| supported_params = image_edit_provider_config.get_supported_openai_params(model) | |
| # Check for unsupported parameters | |
| unsupported_params = [ | |
| param | |
| for param in image_edit_optional_params | |
| if param not in supported_params | |
| ] | |
| if unsupported_params: | |
| raise litellm.UnsupportedParamsError( | |
| model=model, | |
| message=f"The following parameters are not supported for model {model}: {', '.join(unsupported_params)}", | |
| ) | |
| # Map parameters to provider-specific format | |
| mapped_params = image_edit_provider_config.map_openai_params( | |
| image_edit_optional_params=image_edit_optional_params, | |
| model=model, | |
| drop_params=litellm.drop_params, | |
| ) | |
| return mapped_params | |
| 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) | |
| 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] | |