mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-15 04:19:08 +00:00
feat(moonshot): add Files API support to complete end-to-end batch flow
Batch requires uploading a JSONL file first via /v1/files before calling create_batch. Without Files API support, the complete batch workflow was broken for Moonshot. Adds "moonshot" to all five file operation type literals (create, retrieve, delete, list, content) and a dedicated _get_moonshot_file_credentials() helper in files/main.py that applies the same api_base security guard as the batch branches — caller-supplied api_base is only honoured when the caller also supplies their own api_key, preventing the server-side MOONSHOT_API_KEY from being forwarded to a caller-controlled endpoint. All five operations delegate to openai_files_instance since Moonshot's files API is OpenAI-compatible.
This commit is contained in:
parent
e26d70b09a
commit
40f3248f6b
2 changed files with 107 additions and 4 deletions
|
|
@ -25,10 +25,13 @@ FileCreateProvider = Literal[
|
|||
"hosted_vllm",
|
||||
"manus",
|
||||
"anthropic",
|
||||
"moonshot",
|
||||
]
|
||||
FileRetrieveProvider = Literal["openai", "azure", "gemini", "vertex_ai", "hosted_vllm", "manus", "anthropic"]
|
||||
FileDeleteProvider = Literal["openai", "azure", "gemini", "manus", "anthropic"]
|
||||
FileListProvider = Literal["openai", "azure", "manus", "anthropic"]
|
||||
FileRetrieveProvider = Literal[
|
||||
"openai", "azure", "gemini", "vertex_ai", "hosted_vllm", "manus", "anthropic", "moonshot"
|
||||
]
|
||||
FileDeleteProvider = Literal["openai", "azure", "gemini", "manus", "anthropic", "moonshot"]
|
||||
FileListProvider = Literal["openai", "azure", "manus", "anthropic", "moonshot"]
|
||||
import litellm
|
||||
from litellm import get_secret_str
|
||||
from litellm.files.streaming import FileContentStreamingResponse
|
||||
|
|
@ -84,6 +87,34 @@ bedrock_files_instance = BedrockFilesHandler()
|
|||
#################################################
|
||||
|
||||
|
||||
def _get_moonshot_file_credentials(
|
||||
caller_api_key: str | None,
|
||||
caller_api_base: str | None,
|
||||
) -> tuple[str, str]:
|
||||
"""Resolve Moonshot api_key and api_base for file operations.
|
||||
|
||||
Only trust the caller's api_base when they supply their own api_key.
|
||||
When falling back to the server-side MOONSHOT_API_KEY the base URL is
|
||||
resolved from server config so the key is never forwarded to a
|
||||
caller-controlled endpoint.
|
||||
"""
|
||||
default_base = get_secret_str("MOONSHOT_API_BASE") or "https://api.moonshot.ai/v1"
|
||||
if caller_api_key:
|
||||
api_key = caller_api_key
|
||||
api_base = caller_api_base or default_base
|
||||
else:
|
||||
server_key = get_secret_str("MOONSHOT_API_KEY")
|
||||
if not server_key:
|
||||
raise litellm.exceptions.AuthenticationError(
|
||||
message="No Moonshot API key found. Pass api_key or set MOONSHOT_API_KEY in the environment.",
|
||||
model="n/a",
|
||||
llm_provider="moonshot",
|
||||
)
|
||||
api_key = server_key
|
||||
api_base = default_base
|
||||
return api_key, api_base
|
||||
|
||||
|
||||
def _add_trusted_model_credentials_to_litellm_params(
|
||||
litellm_params_dict: Dict[str, Any], kwargs: Dict[str, Any]
|
||||
) -> None:
|
||||
|
|
@ -227,6 +258,20 @@ def create_file(
|
|||
organization=openai_creds.organization,
|
||||
create_file_data=_create_file_request,
|
||||
)
|
||||
elif custom_llm_provider == "moonshot":
|
||||
api_key, api_base = _get_moonshot_file_credentials(
|
||||
caller_api_key=optional_params.api_key,
|
||||
caller_api_base=optional_params.api_base,
|
||||
)
|
||||
response = openai_files_instance.create_file(
|
||||
_is_async=_is_async,
|
||||
api_base=api_base,
|
||||
api_key=api_key,
|
||||
timeout=timeout,
|
||||
max_retries=optional_params.max_retries,
|
||||
organization=None,
|
||||
create_file_data=_create_file_request,
|
||||
)
|
||||
elif custom_llm_provider == "azure":
|
||||
azure_creds = get_azure_credentials(
|
||||
api_base=optional_params.api_base,
|
||||
|
|
@ -350,6 +395,20 @@ def file_retrieve(
|
|||
max_retries=optional_params.max_retries,
|
||||
organization=openai_creds.organization,
|
||||
)
|
||||
elif custom_llm_provider == "moonshot":
|
||||
api_key, api_base = _get_moonshot_file_credentials(
|
||||
caller_api_key=optional_params.api_key,
|
||||
caller_api_base=optional_params.api_base,
|
||||
)
|
||||
response = openai_files_instance.retrieve_file(
|
||||
file_id=file_id,
|
||||
_is_async=_is_async,
|
||||
api_base=api_base,
|
||||
api_key=api_key,
|
||||
timeout=timeout,
|
||||
max_retries=optional_params.max_retries,
|
||||
organization=None,
|
||||
)
|
||||
elif custom_llm_provider == "azure":
|
||||
azure_creds = get_azure_credentials(
|
||||
api_base=optional_params.api_base,
|
||||
|
|
@ -533,6 +592,20 @@ def file_delete(
|
|||
max_retries=optional_params.max_retries,
|
||||
organization=openai_creds.organization,
|
||||
)
|
||||
elif custom_llm_provider == "moonshot":
|
||||
api_key, api_base = _get_moonshot_file_credentials(
|
||||
caller_api_key=optional_params.api_key,
|
||||
caller_api_base=optional_params.api_base,
|
||||
)
|
||||
response = openai_files_instance.delete_file(
|
||||
file_id=file_id,
|
||||
_is_async=_is_async,
|
||||
api_base=api_base,
|
||||
api_key=api_key,
|
||||
timeout=timeout,
|
||||
max_retries=optional_params.max_retries,
|
||||
organization=None,
|
||||
)
|
||||
elif custom_llm_provider == "azure":
|
||||
azure_creds = get_azure_credentials(
|
||||
api_base=optional_params.api_base,
|
||||
|
|
@ -737,6 +810,20 @@ def file_list(
|
|||
max_retries=optional_params.max_retries,
|
||||
organization=openai_creds.organization,
|
||||
)
|
||||
elif custom_llm_provider == "moonshot":
|
||||
api_key, api_base = _get_moonshot_file_credentials(
|
||||
caller_api_key=optional_params.api_key,
|
||||
caller_api_base=optional_params.api_base,
|
||||
)
|
||||
response = openai_files_instance.list_files(
|
||||
purpose=purpose,
|
||||
_is_async=_is_async,
|
||||
api_base=api_base,
|
||||
api_key=api_key,
|
||||
timeout=timeout,
|
||||
max_retries=optional_params.max_retries,
|
||||
organization=None,
|
||||
)
|
||||
elif custom_llm_provider == "azure":
|
||||
azure_creds = get_azure_credentials(
|
||||
api_base=optional_params.api_base,
|
||||
|
|
@ -939,6 +1026,20 @@ def file_content(
|
|||
max_retries=optional_params.max_retries,
|
||||
organization=openai_creds.organization,
|
||||
)
|
||||
elif custom_llm_provider == "moonshot":
|
||||
api_key, api_base = _get_moonshot_file_credentials(
|
||||
caller_api_key=optional_params.api_key,
|
||||
caller_api_base=optional_params.api_base,
|
||||
)
|
||||
response = openai_files_instance.file_content(
|
||||
_is_async=_is_async,
|
||||
file_content_request=_file_content_request,
|
||||
api_base=api_base,
|
||||
api_key=api_key,
|
||||
timeout=timeout,
|
||||
max_retries=optional_params.max_retries,
|
||||
organization=None,
|
||||
)
|
||||
elif custom_llm_provider == "azure":
|
||||
azure_creds = get_azure_credentials(
|
||||
api_base=optional_params.api_base,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
from typing import AsyncIterator, Dict, Iterator, Literal, NamedTuple, Union
|
||||
|
||||
FileContentProvider = Literal["openai", "azure", "vertex_ai", "bedrock", "hosted_vllm", "anthropic", "manus"]
|
||||
FileContentProvider = Literal[
|
||||
"openai", "azure", "vertex_ai", "bedrock", "hosted_vllm", "anthropic", "manus", "moonshot"
|
||||
]
|
||||
|
||||
|
||||
class FileContentStreamingResult(NamedTuple):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue