mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-09 16:24:38 +00:00
feat: add /delete endpoint support for gemini
This commit is contained in:
@@ -9,6 +9,7 @@ import asyncio
|
||||
import contextvars
|
||||
import os
|
||||
import time
|
||||
import uuid
|
||||
from functools import partial
|
||||
from typing import Any, Coroutine, Dict, Literal, Optional, Union, cast
|
||||
|
||||
@@ -61,7 +62,7 @@ async def acreate_file(
|
||||
file: FileTypes,
|
||||
purpose: Literal["assistants", "batch", "fine-tune"],
|
||||
expires_after: Optional[FileExpiresAfter] = None,
|
||||
custom_llm_provider: Literal["openai", "azure", "vertex_ai", "bedrock", "hosted_vllm", "manus"] = "openai",
|
||||
custom_llm_provider: Literal["openai", "azure", "gemini", "vertex_ai", "bedrock", "hosted_vllm", "manus"] = "openai",
|
||||
extra_headers: Optional[Dict[str, str]] = None,
|
||||
extra_body: Optional[Dict[str, str]] = None,
|
||||
**kwargs,
|
||||
@@ -106,7 +107,7 @@ def create_file(
|
||||
file: FileTypes,
|
||||
purpose: Literal["assistants", "batch", "fine-tune"],
|
||||
expires_after: Optional[FileExpiresAfter] = None,
|
||||
custom_llm_provider: Optional[Literal["openai", "azure", "vertex_ai", "bedrock", "hosted_vllm", "manus"]] = None,
|
||||
custom_llm_provider: Optional[Literal["openai", "azure", "gemini", "vertex_ai", "bedrock", "hosted_vllm", "manus"]] = None,
|
||||
extra_headers: Optional[Dict[str, str]] = None,
|
||||
extra_body: Optional[Dict[str, str]] = None,
|
||||
**kwargs,
|
||||
@@ -294,7 +295,7 @@ def create_file(
|
||||
@client
|
||||
async def afile_retrieve(
|
||||
file_id: str,
|
||||
custom_llm_provider: Literal["openai", "azure", "hosted_vllm", "manus"] = "openai",
|
||||
custom_llm_provider: Literal["openai", "azure", "gemini", "hosted_vllm", "manus"] = "openai",
|
||||
extra_headers: Optional[Dict[str, str]] = None,
|
||||
extra_body: Optional[Dict[str, str]] = None,
|
||||
**kwargs,
|
||||
@@ -493,7 +494,7 @@ def file_retrieve(
|
||||
@client
|
||||
async def afile_delete(
|
||||
file_id: str,
|
||||
custom_llm_provider: Literal["openai", "azure", "manus"] = "openai",
|
||||
custom_llm_provider: Literal["openai", "azure", "gemini", "manus"] = "openai",
|
||||
extra_headers: Optional[Dict[str, str]] = None,
|
||||
extra_body: Optional[Dict[str, str]] = None,
|
||||
**kwargs,
|
||||
@@ -537,7 +538,7 @@ async def afile_delete(
|
||||
def file_delete(
|
||||
file_id: str,
|
||||
model: Optional[str] = None,
|
||||
custom_llm_provider: Union[Literal["openai", "azure", "manus"], str] = "openai",
|
||||
custom_llm_provider: Union[Literal["openai", "azure", "gemini", "manus"], str] = "openai",
|
||||
extra_headers: Optional[Dict[str, str]] = None,
|
||||
extra_body: Optional[Dict[str, str]] = None,
|
||||
**kwargs,
|
||||
@@ -680,7 +681,7 @@ def file_delete(
|
||||
)
|
||||
else:
|
||||
raise litellm.exceptions.BadRequestError(
|
||||
message="LiteLLM doesn't support {} for 'file_delete'. Only 'openai', 'azure', and 'manus' are supported.".format(
|
||||
message="LiteLLM doesn't support {} for 'file_delete'. Only 'openai', 'azure', 'gemini', and 'manus' are supported.".format(
|
||||
custom_llm_provider
|
||||
),
|
||||
model="n/a",
|
||||
|
||||
@@ -35,6 +35,26 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig):
|
||||
def custom_llm_provider(self) -> LlmProviders:
|
||||
return LlmProviders.GEMINI
|
||||
|
||||
def validate_environment(
|
||||
self,
|
||||
api_key: Optional[str],
|
||||
headers: dict,
|
||||
model: str,
|
||||
messages: list,
|
||||
optional_params: dict,
|
||||
litellm_params: dict,
|
||||
) -> dict:
|
||||
"""
|
||||
Validate environment and add Gemini API key to headers.
|
||||
Google AI Studio uses x-goog-api-key header for authentication.
|
||||
"""
|
||||
api_key = self.get_api_key(api_key)
|
||||
if not api_key:
|
||||
raise ValueError("GEMINI_API_KEY is required for Google AI Studio file operations")
|
||||
|
||||
headers["x-goog-api-key"] = api_key
|
||||
return headers
|
||||
|
||||
def get_complete_url(
|
||||
self,
|
||||
api_base: Optional[str],
|
||||
@@ -56,10 +76,12 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig):
|
||||
if not api_base:
|
||||
raise ValueError("api_base is required")
|
||||
|
||||
if not api_key:
|
||||
# Get API key from multiple sources
|
||||
final_api_key = api_key or litellm_params.get("api_key") or self.get_api_key()
|
||||
if not final_api_key:
|
||||
raise ValueError("api_key is required")
|
||||
|
||||
url = "{}/{}?key={}".format(api_base, endpoint, api_key)
|
||||
url = "{}/{}?key={}".format(api_base, endpoint, final_api_key)
|
||||
return url
|
||||
|
||||
def get_supported_openai_params(
|
||||
@@ -196,7 +218,41 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig):
|
||||
optional_params: dict,
|
||||
litellm_params: dict,
|
||||
) -> tuple[str, dict]:
|
||||
raise NotImplementedError("GoogleAIStudioFilesHandler does not support file deletion")
|
||||
"""
|
||||
Transform delete file request for Google AI Studio.
|
||||
|
||||
Args:
|
||||
file_id: The file URI (e.g., "files/abc123" or full URI)
|
||||
optional_params: Optional parameters
|
||||
litellm_params: LiteLLM parameters containing api_key
|
||||
|
||||
Returns:
|
||||
tuple[str, dict]: (url, params) for the DELETE request
|
||||
"""
|
||||
api_base = self.get_api_base(litellm_params.get("api_base"))
|
||||
if not api_base:
|
||||
raise ValueError("api_base is required")
|
||||
|
||||
# Get API key from multiple sources (same pattern as get_complete_url)
|
||||
api_key = litellm_params.get("api_key") or self.get_api_key()
|
||||
if not api_key:
|
||||
raise ValueError("api_key is required")
|
||||
|
||||
# Extract file name from URI if full URI is provided
|
||||
# file_id could be "files/abc123" or "https://generativelanguage.googleapis.com/v1beta/files/abc123"
|
||||
if file_id.startswith("http"):
|
||||
# Extract the file path from full URI
|
||||
file_name = file_id.split("/v1beta/")[-1]
|
||||
else:
|
||||
file_name = file_id
|
||||
|
||||
# Construct the delete URL
|
||||
url = f"{api_base}/v1beta/{file_name}"
|
||||
|
||||
# Add API key as header (Google AI Studio uses x-goog-api-key header)
|
||||
params = {}
|
||||
|
||||
return url, params
|
||||
|
||||
def transform_delete_file_response(
|
||||
self,
|
||||
@@ -204,7 +260,34 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig):
|
||||
logging_obj: LiteLLMLoggingObj,
|
||||
litellm_params: dict,
|
||||
) -> FileDeleted:
|
||||
raise NotImplementedError("GoogleAIStudioFilesHandler does not support file deletion")
|
||||
"""
|
||||
Transform Gemini's file delete response into OpenAI-style FileDeleted.
|
||||
|
||||
Google AI Studio returns an empty JSON object {} on successful deletion.
|
||||
"""
|
||||
try:
|
||||
# Google AI Studio returns {} on successful deletion
|
||||
if raw_response.status_code == 200:
|
||||
# Extract file ID from the request URL if possible
|
||||
file_id = "deleted"
|
||||
if hasattr(raw_response, "request") and raw_response.request:
|
||||
url = str(raw_response.request.url)
|
||||
if "/files/" in url:
|
||||
file_id = url.split("/files/")[-1].split("?")[0]
|
||||
# Add the files/ prefix if not present
|
||||
if not file_id.startswith("files/"):
|
||||
file_id = f"files/{file_id}"
|
||||
|
||||
return FileDeleted(
|
||||
id=file_id,
|
||||
deleted=True,
|
||||
object="file"
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Failed to delete file: {raw_response.text}")
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error parsing file delete response: {str(e)}")
|
||||
raise ValueError(f"Error parsing file delete response: {str(e)}")
|
||||
|
||||
def transform_list_files_request(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user