diff --git a/litellm/assistants/utils.py b/litellm/assistants/utils.py index e80131a5011..44ff2213d94 100644 --- a/litellm/assistants/utils.py +++ b/litellm/assistants/utils.py @@ -8,8 +8,8 @@ from ..types.llms.openai import * def get_optional_params_add_message( role: str | None, - content: str | List[MessageContentTextObject | MessageContentImageFileObject | MessageContentImageURLObject] | None, - attachments: List[Attachment] | None, + content: str | list[MessageContentTextObject | MessageContentImageFileObject | MessageContentImageURLObject] | None, + attachments: list[Attachment] | None, metadata: dict | None, custom_llm_provider: str, **kwargs, diff --git a/litellm/fine_tuning/main.py b/litellm/fine_tuning/main.py index e89defedabe..bc328c50204 100644 --- a/litellm/fine_tuning/main.py +++ b/litellm/fine_tuning/main.py @@ -80,7 +80,7 @@ async def acreate_fine_tuning_job( hyperparameters: dict | None = {}, suffix: str | None = None, validation_file: str | None = None, - integrations: List[str] | None = None, + integrations: list[str] | None = None, seed: int | None = None, custom_llm_provider: Literal["openai", "azure", "vertex_ai"] = "openai", extra_headers: dict[str, str] | None = None, @@ -157,7 +157,7 @@ def create_fine_tuning_job( hyperparameters: dict | None = {}, suffix: str | None = None, validation_file: str | None = None, - integrations: List[str] | None = None, + integrations: list[str] | None = None, seed: int | None = None, custom_llm_provider: Literal["openai", "azure", "vertex_ai"] = "openai", extra_headers: dict[str, str] | None = None, diff --git a/litellm/llms/bedrock/chat/invoke_handler.py b/litellm/llms/bedrock/chat/invoke_handler.py index a2bb179f72f..35ddbc70347 100644 --- a/litellm/llms/bedrock/chat/invoke_handler.py +++ b/litellm/llms/bedrock/chat/invoke_handler.py @@ -57,7 +57,7 @@ class AmazonCohereChatConfig: Reference - https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-cohere-command-r-plus.html """ - documents: List[Document] | None = None + documents: list[Document] | None = None search_queries_only: bool | None = None preamble: str | None = None max_tokens: int | None = None @@ -69,12 +69,12 @@ class AmazonCohereChatConfig: presence_penalty: float | None = None seed: int | None = None return_prompt: bool | None = None - stop_sequences: List[str] | None = None + stop_sequences: list[str] | None = None raw_prompting: bool | None = None def __init__( self, - documents: List[Document] | None = None, + documents: list[Document] | None = None, search_queries_only: bool | None = None, preamble: str | None = None, max_tokens: int | None = None, @@ -112,7 +112,7 @@ class AmazonCohereChatConfig: and v is not None } - def get_supported_openai_params(self) -> List[str]: + def get_supported_openai_params(self) -> list[str]: return [ "max_tokens", "max_completion_tokens", @@ -325,7 +325,7 @@ class AWSEventStreamDecoder: self.model = model self.parser = EventStreamJSONParser() - self.content_blocks: List[ContentBlockDeltaEvent] = [] + self.content_blocks: list[ContentBlockDeltaEvent] = [] self.tool_calls_index: int | None = None self.response_id: str | None = None self.json_mode = json_mode @@ -362,13 +362,13 @@ class AWSEventStreamDecoder: def translate_thinking_blocks( self, thinking_block: BedrockConverseReasoningContentBlockDelta - ) -> List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]] | None: + ) -> list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None: """ Translate the thinking blocks to a string """ - thinking_blocks_list: Final[List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]]] = [] - _thinking_block: Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock] | None = None + thinking_blocks_list: Final[list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock]] = [] + _thinking_block: ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock | None = None if "text" in thinking_block: _thinking_block = ChatCompletionThinkingBlock(type="thinking") @@ -402,12 +402,12 @@ class AWSEventStreamDecoder: ) -> tuple[ ChatCompletionToolCallChunk | None, dict, - List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]] | None, + list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None, ]: """Handle 'start' event in converse chunk parsing.""" tool_use: ChatCompletionToolCallChunk | None = None provider_specific_fields: dict = {} - thinking_blocks: List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]] | None = None + thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None = None self.content_blocks = [] # reset if start_obj is not None: @@ -450,14 +450,14 @@ class AWSEventStreamDecoder: ChatCompletionToolCallChunk | None, dict, str | None, - List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]] | None, + list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None, ]: """Handle 'delta' event in converse chunk parsing.""" text = "" tool_use: ChatCompletionToolCallChunk | None = None provider_specific_fields: dict = {} reasoning_content: str | None = None - thinking_blocks: List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]] | None = None + thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None = None self.content_blocks.append(delta_obj) if "text" in delta_obj: @@ -535,7 +535,7 @@ class AWSEventStreamDecoder: usage: Usage | None = None provider_specific_fields: dict = {} reasoning_content: str | None = None - thinking_blocks: List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]] | None = None + thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None = None content_block_index: Final = int(chunk_data.get("contentBlockIndex", 0)) if "start" in chunk_data: @@ -590,7 +590,7 @@ class AWSEventStreamDecoder: except Exception as e: raise Exception(f"Received streaming error - {e}") - def _chunk_parser(self, chunk_data: dict) -> Union[GChunk, ModelResponseStream, dict]: + def _chunk_parser(self, chunk_data: dict) -> GChunk | ModelResponseStream | dict: text = "" is_finished = False finish_reason = "" @@ -645,7 +645,7 @@ class AWSEventStreamDecoder: tool_use=None, ) - def iter_bytes(self, iterator: Iterator[bytes]) -> Iterator[Union[GChunk, ModelResponseStream, dict]]: + def iter_bytes(self, iterator: Iterator[bytes]) -> Iterator[GChunk | ModelResponseStream | dict]: """Given an iterator that yields lines, iterate over it & yield every event encountered""" from botocore.eventstream import EventStreamBuffer @@ -659,9 +659,7 @@ class AWSEventStreamDecoder: _data = json.loads(message) yield self._chunk_parser(chunk_data=_data) - async def aiter_bytes( - self, iterator: AsyncIterator[bytes] - ) -> AsyncIterator[Union[GChunk, ModelResponseStream, dict]]: + async def aiter_bytes(self, iterator: AsyncIterator[bytes]) -> AsyncIterator[GChunk | ModelResponseStream | dict]: """Given an async iterator that yields lines, iterate over it & yield every event encountered""" from botocore.eventstream import EventStreamBuffer @@ -741,7 +739,7 @@ class AmazonDeepSeekR1StreamDecoder(AWSEventStreamDecoder): sync_stream=sync_stream, ) - def _chunk_parser(self, chunk_data: dict) -> Union[GChunk, ModelResponseStream, dict]: + def _chunk_parser(self, chunk_data: dict) -> GChunk | ModelResponseStream | dict: return self.deepseek_model_response_iterator.chunk_parser(chunk=chunk_data) @@ -756,7 +754,7 @@ class MockResponseIterator: # for returning ai21 streaming responses return self def _handle_json_mode_chunk( - self, text: str, tool_calls: List[ChatCompletionToolCallChunk] | None + self, text: str, tool_calls: list[ChatCompletionToolCallChunk] | None ) -> tuple[str, ChatCompletionToolCallChunk | None]: """ If JSON mode is enabled, convert the tool call to a message. @@ -789,7 +787,7 @@ class MockResponseIterator: # for returning ai21 streaming responses text = chunk_data.choices[0].message.content or "" # type: ignore tool_use = None _model_response_tool_call: Final = cast( - List[ChatCompletionMessageToolCall] | None, + list[ChatCompletionMessageToolCall] | None, cast(Choices, chunk_data.choices[0]).message.tool_calls, ) if self.json_mode is True: diff --git a/litellm/llms/openai/openai.py b/litellm/llms/openai/openai.py index 998319f3e85..41a8c15c9e6 100644 --- a/litellm/llms/openai/openai.py +++ b/litellm/llms/openai/openai.py @@ -345,7 +345,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): client: OpenAI | AsyncOpenAI | None = None, shared_session: Optional["ClientSession"] = None, ) -> OpenAI | AsyncOpenAI | None: - client_initialization_params: Final[Dict] = locals() + client_initialization_params: Final[dict] = locals() if client is None: if not isinstance(max_retries, int): raise OpenAIError( @@ -402,7 +402,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): data: dict, timeout: float | httpx.Timeout, logging_obj: LiteLLMLoggingObj, - ) -> Tuple[dict, BaseModel]: + ) -> tuple[dict, BaseModel]: """ Helper to: - call chat.completions.create.with_raw_response when litellm.return_response_headers is True @@ -439,7 +439,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): data: dict, timeout: float | httpx.Timeout, logging_obj: LiteLLMLoggingObj, - ) -> Tuple[dict, BaseModel]: + ) -> tuple[dict, BaseModel]: """ Helper to: - call chat.completions.create.with_raw_response when litellm.return_response_headers is True @@ -474,11 +474,11 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): self, response: Any, model: str, - messages: list[Dict], - optional_params: Dict, + messages: list[dict], + optional_params: dict, logging_obj: LiteLLMLoggingObj, stream: bool, - litellm_params: Dict, + litellm_params: dict, ) -> Any | None: """ Call agentic completion hooks for all custom loggers (OpenAI Chat Completions API). @@ -1288,7 +1288,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): ) ## embedding CALL - headers: Dict | None = None + headers: dict | None = None headers, sync_embedding_response = self.make_sync_openai_embedding_request( openai_client=openai_client, data=data, @@ -2852,7 +2852,7 @@ class OpenAIAssistantsAPI(BaseLLM): assistant_id: str, additional_instructions: str | None, instructions: str | None, - metadata: Dict | None, + metadata: dict | None, model: str | None, stream: bool | None, tools: Iterable[AssistantToolParam] | None, @@ -2891,12 +2891,12 @@ class OpenAIAssistantsAPI(BaseLLM): assistant_id: str, additional_instructions: str | None, instructions: str | None, - metadata: Dict | None, + metadata: dict | None, model: str | None, tools: Iterable[AssistantToolParam] | None, event_handler: AssistantEventHandler | None, ) -> AsyncAssistantStreamManager[AsyncAssistantEventHandler]: - data: Final[Dict[str, Any]] = { + data: Final[dict[str, Any]] = { "thread_id": thread_id, "assistant_id": assistant_id, "additional_instructions": additional_instructions, @@ -2916,12 +2916,12 @@ class OpenAIAssistantsAPI(BaseLLM): assistant_id: str, additional_instructions: str | None, instructions: str | None, - metadata: Dict | None, + metadata: dict | None, model: str | None, tools: Iterable[AssistantToolParam] | None, event_handler: AssistantEventHandler | None, ) -> AssistantStreamManager[AssistantEventHandler]: - data: Final[Dict[str, Any]] = { + data: Final[dict[str, Any]] = { "thread_id": thread_id, "assistant_id": assistant_id, "additional_instructions": additional_instructions, @@ -2943,7 +2943,7 @@ class OpenAIAssistantsAPI(BaseLLM): assistant_id: str, additional_instructions: str | None, instructions: str | None, - metadata: Dict | None, + metadata: dict | None, model: str | None, stream: bool | None, tools: Iterable[AssistantToolParam] | None, @@ -2965,7 +2965,7 @@ class OpenAIAssistantsAPI(BaseLLM): assistant_id: str, additional_instructions: str | None, instructions: str | None, - metadata: Dict | None, + metadata: dict | None, model: str | None, stream: bool | None, tools: Iterable[AssistantToolParam] | None, @@ -2988,7 +2988,7 @@ class OpenAIAssistantsAPI(BaseLLM): assistant_id: str, additional_instructions: str | None, instructions: str | None, - metadata: Dict | None, + metadata: dict | None, model: str | None, stream: bool | None, tools: Iterable[AssistantToolParam] | None, diff --git a/litellm/llms/openai/responses/transformation.py b/litellm/llms/openai/responses/transformation.py index 39156faefd0..2894f15966b 100644 --- a/litellm/llms/openai/responses/transformation.py +++ b/litellm/llms/openai/responses/transformation.py @@ -165,10 +165,10 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): self, model: str, # allows overrides to selectively run this input: str | ResponseInputParam, - tools: List[ALL_RESPONSES_API_TOOL_PARAMS] | None = None, - ) -> Tuple[ + tools: list[ALL_RESPONSES_API_TOOL_PARAMS] | None = None, + ) -> tuple[ str | ResponseInputParam, - List[ALL_RESPONSES_API_TOOL_PARAMS] | None, + list[ALL_RESPONSES_API_TOOL_PARAMS] | None, ]: """Sibling of `remove_cache_control_flag_from_messages_and_tools` on the chat path. Strips Anthropic-only `cache_control` markers from @@ -447,7 +447,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): api_base: str, litellm_params: GenericLiteLLMParams, headers: dict, - ) -> Tuple[str, dict]: + ) -> tuple[str, dict]: """ Transform the delete response API request into a URL and data @@ -482,7 +482,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): api_base: str, litellm_params: GenericLiteLLMParams, headers: dict, - ) -> Tuple[str, dict]: + ) -> tuple[str, dict]: """ Transform the get response API request into a URL and data @@ -525,10 +525,10 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): headers: dict, after: str | None = None, before: str | None = None, - include: List[str] | None = None, + include: list[str] | None = None, limit: int = 20, order: Literal["asc", "desc"] = "desc", - ) -> Tuple[str, dict]: + ) -> tuple[str, dict]: encoded_response_id: Final = encode_url_path_segment(response_id, field_name="response_id") url: Final = f"{api_base}/{encoded_response_id}/input_items" params: Final[dict[str, Any]] = {} @@ -563,7 +563,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): api_base: str, litellm_params: GenericLiteLLMParams, headers: dict, - ) -> Tuple[str, dict]: + ) -> tuple[str, dict]: """ Transform the cancel response API request into a URL and data @@ -607,7 +607,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): api_base: str, litellm_params: GenericLiteLLMParams, headers: dict, - ) -> Tuple[str, dict]: + ) -> tuple[str, dict]: """ Transform the compact response API request into a URL and data diff --git a/litellm/llms/volcengine/responses/transformation.py b/litellm/llms/volcengine/responses/transformation.py index 4efea9d463b..82c4f7f61a7 100644 --- a/litellm/llms/volcengine/responses/transformation.py +++ b/litellm/llms/volcengine/responses/transformation.py @@ -1,4 +1,5 @@ from collections.abc import Callable, Mapping, Sequence +from types import UnionType from typing import TYPE_CHECKING, Any, Final, Literal, Protocol, Union, get_args, get_origin import httpx @@ -475,14 +476,12 @@ class VolcEngineResponsesAPIConfig(OpenAIResponsesAPIConfig): return 0 if annotation is list or origin is list: return [] - if origin is Union: + if origin is Union or origin is UnionType: # Prefer empty list when any option is a list if any((arg is list or VolcEngineResponsesAPIConfig._annotation_origin(arg) is list) for arg in args): return [] if type(None) in args: return None - if origin is Union and type(None) in args: - return None # Fallback to None when no safer guess exists return None @@ -514,7 +513,9 @@ class VolcEngineResponsesAPIConfig(OpenAIResponsesAPIConfig): Choose the best-matching Pydantic model class for a nested dict. """ origin: Final = VolcEngineResponsesAPIConfig._annotation_origin(annotation) - union_args: Final = VolcEngineResponsesAPIConfig._annotation_args(annotation) if origin is Union else () + union_args: Final = ( + VolcEngineResponsesAPIConfig._annotation_args(annotation) if origin is Union or origin is UnionType else () + ) candidates = tuple(candidate for candidate in (annotation, *union_args) if hasattr(candidate, "model_fields")) if not candidates: diff --git a/litellm/proxy/guardrails/guardrail_endpoints.py b/litellm/proxy/guardrails/guardrail_endpoints.py index 79c4362055e..ee2de61a255 100644 --- a/litellm/proxy/guardrails/guardrail_endpoints.py +++ b/litellm/proxy/guardrails/guardrail_endpoints.py @@ -8,7 +8,8 @@ import json import os from collections.abc import Mapping, Sequence from datetime import datetime, timezone -from typing import TYPE_CHECKING, Any, Final, Literal, TypeVar, Union, cast +from types import UnionType +from typing import TYPE_CHECKING, Any, Final, Literal, TypeVar, Union, cast, get_args, get_origin from urllib.parse import urlparse from fastapi import APIRouter, Depends, HTTPException, Request @@ -1556,13 +1557,9 @@ def _get_field_type_from_annotation(field_annotation: Any) -> str: Convert a Python type annotation to a UI-friendly type string """ # Handle Union types (like Optional[T]) - if ( - hasattr(field_annotation, "__origin__") - and field_annotation.__origin__ is Union - and hasattr(field_annotation, "__args__") - ): + if get_origin(field_annotation) is Union or get_origin(field_annotation) is UnionType: # For Optional[T], get the non-None type - args: Final = field_annotation.__args__ + args: Final = get_args(field_annotation) non_none_args: Final = [arg for arg in args if arg is not type(None)] if non_none_args: field_annotation = non_none_args[0] @@ -1689,13 +1686,9 @@ def _should_skip_optional_params(field_name: str, field_annotation: Any) -> bool def _unwrap_optional_type(field_annotation: Any) -> Any: """Unwrap Optional types to get the actual type.""" - if ( - hasattr(field_annotation, "__origin__") - and field_annotation.__origin__ is Union - and hasattr(field_annotation, "__args__") - ): + if get_origin(field_annotation) is Union or get_origin(field_annotation) is UnionType: # For Optional[BaseModel], get the non-None type - args: Final = field_annotation.__args__ + args: Final = get_args(field_annotation) non_none_args: Final = [arg for arg in args if arg is not type(None)] if non_none_args: return non_none_args[0] diff --git a/litellm/proxy/guardrails/guardrail_helpers.py b/litellm/proxy/guardrails/guardrail_helpers.py index 3ce96fc8d86..3282334715d 100644 --- a/litellm/proxy/guardrails/guardrail_helpers.py +++ b/litellm/proxy/guardrails/guardrail_helpers.py @@ -10,7 +10,7 @@ from litellm.types.guardrails import * sys.path.insert(0, os.path.abspath("../..")) # Adds the parent directory to the system path -def can_modify_guardrails(team_obj: Optional[LiteLLM_TeamTable]) -> bool: +def can_modify_guardrails(team_obj: LiteLLM_TeamTable | None) -> bool: if team_obj is None: return True diff --git a/litellm/types/access_group.py b/litellm/types/access_group.py index e26ebe00625..b477ce309b7 100644 --- a/litellm/types/access_group.py +++ b/litellm/types/access_group.py @@ -1,39 +1,38 @@ from datetime import datetime -from typing import List, Optional from pydantic import BaseModel class AccessGroupCreateRequest(BaseModel): access_group_name: str - description: Optional[str] = None - access_model_names: Optional[List[str]] = None - access_mcp_server_ids: Optional[List[str]] = None - access_agent_ids: Optional[List[str]] = None - assigned_team_ids: Optional[List[str]] = None - assigned_key_ids: Optional[List[str]] = None + description: str | None = None + access_model_names: list[str] | None = None + access_mcp_server_ids: list[str] | None = None + access_agent_ids: list[str] | None = None + assigned_team_ids: list[str] | None = None + assigned_key_ids: list[str] | None = None class AccessGroupUpdateRequest(BaseModel): - access_group_name: Optional[str] = None - description: Optional[str] = None - access_model_names: Optional[List[str]] = None - access_mcp_server_ids: Optional[List[str]] = None - access_agent_ids: Optional[List[str]] = None - assigned_team_ids: Optional[List[str]] = None - assigned_key_ids: Optional[List[str]] = None + access_group_name: str | None = None + description: str | None = None + access_model_names: list[str] | None = None + access_mcp_server_ids: list[str] | None = None + access_agent_ids: list[str] | None = None + assigned_team_ids: list[str] | None = None + assigned_key_ids: list[str] | None = None class AccessGroupResponse(BaseModel): access_group_id: str access_group_name: str - description: Optional[str] = None - access_model_names: List[str] - access_mcp_server_ids: List[str] - access_agent_ids: List[str] - assigned_team_ids: List[str] - assigned_key_ids: List[str] + description: str | None = None + access_model_names: list[str] + access_mcp_server_ids: list[str] + access_agent_ids: list[str] + assigned_team_ids: list[str] + assigned_key_ids: list[str] created_at: datetime - created_by: Optional[str] = None + created_by: str | None = None updated_at: datetime - updated_by: Optional[str] = None + updated_by: str | None = None diff --git a/litellm/types/adapter.py b/litellm/types/adapter.py index 2995cfbc1c2..924fabcb86d 100644 --- a/litellm/types/adapter.py +++ b/litellm/types/adapter.py @@ -1,6 +1,4 @@ -from typing import List - -from typing_extensions import Dict, Required, TypedDict, override +from typing_extensions import TypedDict from litellm.integrations.custom_logger import CustomLogger diff --git a/litellm/types/agents.py b/litellm/types/agents.py index e05c4cf1078..95562fcae8c 100644 --- a/litellm/types/agents.py +++ b/litellm/types/agents.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Dict, Final, List, Literal, Optional, TYPE_CHECKING, Union +from typing import TYPE_CHECKING, Any, Final, Literal from pydantic import BaseModel, PrivateAttr from typing_extensions import Required, TypedDict @@ -23,26 +23,26 @@ class AgentExtension(TypedDict, total=False): """A declaration of a protocol extension supported by an Agent.""" uri: str # required - description: Optional[str] - required: Optional[bool] - params: Optional[Dict[str, Any]] + description: str | None + required: bool | None + params: dict[str, Any] | None # AgentCapabilities class AgentCapabilities(TypedDict, total=False): """Defines optional capabilities supported by an agent.""" - streaming: Optional[bool] - pushNotifications: Optional[bool] - stateTransitionHistory: Optional[bool] - extensions: Optional[List[AgentExtension]] + streaming: bool | None + pushNotifications: bool | None + stateTransitionHistory: bool | None + extensions: list[AgentExtension] | None # SecurityScheme types class SecuritySchemeBase(TypedDict, total=False): """Base properties shared by all security scheme objects.""" - description: Optional[str] + description: str | None class APIKeySecurityScheme(SecuritySchemeBase, total=False): @@ -58,7 +58,7 @@ class HTTPAuthSecurityScheme(SecuritySchemeBase, total=False): type: Required[Literal["http"]] scheme: Required[str] - bearerFormat: Optional[str] + bearerFormat: str | None class MutualTLSSecurityScheme(SecuritySchemeBase, total=False): @@ -70,10 +70,10 @@ class MutualTLSSecurityScheme(SecuritySchemeBase, total=False): class OAuthFlows(TypedDict, total=False): """Defines the configuration for the supported OAuth 2.0 flows.""" - authorizationCode: Optional[Dict[str, Any]] - clientCredentials: Optional[Dict[str, Any]] - implicit: Optional[Dict[str, Any]] - password: Optional[Dict[str, Any]] + authorizationCode: dict[str, Any] | None + clientCredentials: dict[str, Any] | None + implicit: dict[str, Any] | None + password: dict[str, Any] | None class OAuth2SecurityScheme(SecuritySchemeBase, total=False): @@ -81,7 +81,7 @@ class OAuth2SecurityScheme(SecuritySchemeBase, total=False): type: Required[Literal["oauth2"]] flows: Required[OAuthFlows] - oauth2MetadataUrl: Optional[str] + oauth2MetadataUrl: str | None class OpenIdConnectSecurityScheme(SecuritySchemeBase, total=False): @@ -92,13 +92,13 @@ class OpenIdConnectSecurityScheme(SecuritySchemeBase, total=False): # Union of all security schemes -SecurityScheme = Union[ - APIKeySecurityScheme, - HTTPAuthSecurityScheme, - OAuth2SecurityScheme, - OpenIdConnectSecurityScheme, - MutualTLSSecurityScheme, -] +SecurityScheme = ( + APIKeySecurityScheme + | HTTPAuthSecurityScheme + | OAuth2SecurityScheme + | OpenIdConnectSecurityScheme + | MutualTLSSecurityScheme +) # AgentSkill @@ -108,11 +108,11 @@ class AgentSkill(TypedDict, total=False): id: str # required name: str # required description: str # required - tags: List[str] # required - examples: Optional[List[str]] - inputModes: Optional[List[str]] - outputModes: Optional[List[str]] - security: Optional[List[Dict[str, List[str]]]] + tags: list[str] # required + examples: list[str] | None + inputModes: list[str] | None + outputModes: list[str] | None + security: list[dict[str, list[str]]] | None # AgentInterface @@ -129,7 +129,7 @@ class AgentCardSignature(TypedDict, total=False): protected: str # required signature: str # required - header: Optional[Dict[str, Any]] + header: dict[str, Any] | None # AgentCard @@ -147,20 +147,20 @@ class AgentCard(TypedDict, total=False): url: str version: str capabilities: AgentCapabilities - defaultInputModes: List[str] - defaultOutputModes: List[str] - skills: List[AgentSkill] + defaultInputModes: list[str] + defaultOutputModes: list[str] + skills: list[AgentSkill] # Optional fields - preferredTransport: Optional[str] - additionalInterfaces: Optional[List[AgentInterface]] - iconUrl: Optional[str] - provider: Optional[AgentProvider] - documentationUrl: Optional[str] - securitySchemes: Optional[Dict[str, SecurityScheme]] - security: Optional[List[Dict[str, List[str]]]] - supportsAuthenticatedExtendedCard: Optional[bool] - signatures: Optional[List[AgentCardSignature]] + preferredTransport: str | None + additionalInterfaces: list[AgentInterface] | None + iconUrl: str | None + provider: AgentProvider | None + documentationUrl: str | None + securitySchemes: dict[str, SecurityScheme] | None + security: list[dict[str, list[str]]] | None + supportsAuthenticatedExtendedCard: bool | None + signatures: list[AgentCardSignature] | None class AugmentedAgentCard(AgentCard): @@ -169,37 +169,37 @@ class AugmentedAgentCard(AgentCard): # Object permission shape for agent MCP tool access (mirrors LiteLLM_ObjectPermissionBase) class AgentObjectPermission(TypedDict, total=False): - mcp_servers: Optional[List[str]] - mcp_access_groups: Optional[List[str]] - mcp_tool_permissions: Optional[Dict[str, List[str]]] - models: Optional[List[str]] - agents: Optional[List[str]] + mcp_servers: list[str] | None + mcp_access_groups: list[str] | None + mcp_tool_permissions: dict[str, list[str]] | None + models: list[str] | None + agents: list[str] | None class AgentConfig(TypedDict, total=False): agent_name: Required[str] agent_card_params: Required[AgentCard] - litellm_params: Dict[str, Any] # allow for any future litellm params + litellm_params: dict[str, Any] # allow for any future litellm params object_permission: AgentObjectPermission - tpm_limit: Optional[int] - rpm_limit: Optional[int] - session_tpm_limit: Optional[int] - session_rpm_limit: Optional[int] - static_headers: Optional[Dict[str, str]] - extra_headers: Optional[List[str]] + tpm_limit: int | None + rpm_limit: int | None + session_tpm_limit: int | None + session_rpm_limit: int | None + static_headers: dict[str, str] | None + extra_headers: list[str] | None class PatchAgentRequest(TypedDict, total=False): agent_name: str agent_card_params: AgentCard - litellm_params: Dict[str, Any] + litellm_params: dict[str, Any] object_permission: AgentObjectPermission - tpm_limit: Optional[int] - rpm_limit: Optional[int] - session_tpm_limit: Optional[int] - session_rpm_limit: Optional[int] - static_headers: Optional[Dict[str, str]] - extra_headers: Optional[List[str]] + tpm_limit: int | None + rpm_limit: int | None + session_tpm_limit: int | None + session_rpm_limit: int | None + static_headers: dict[str, str] | None + extra_headers: list[str] | None # Request/Response models for CRUD endpoints @@ -207,32 +207,32 @@ class PatchAgentRequest(TypedDict, total=False): class AgentKeySummary(BaseModel): token: str - key_alias: Optional[str] = None - key_name: Optional[str] = None + key_alias: str | None = None + key_name: str | None = None class AgentResponse(BaseModel): agent_id: str agent_name: str - litellm_params: Optional[Dict[str, Any]] = None - agent_card_params: Dict[str, Any] - object_permission: Optional[Dict[str, Any]] = None - spend: Optional[float] = None - tpm_limit: Optional[int] = None - rpm_limit: Optional[int] = None - session_tpm_limit: Optional[int] = None - session_rpm_limit: Optional[int] = None - static_headers: Optional[Dict[str, str]] = None - extra_headers: Optional[List[str]] = None - keys: Optional[List[AgentKeySummary]] = None - created_at: Optional[datetime] = None - updated_at: Optional[datetime] = None - created_by: Optional[str] = None - updated_by: Optional[str] = None + litellm_params: dict[str, Any] | None = None + agent_card_params: dict[str, Any] + object_permission: dict[str, Any] | None = None + spend: float | None = None + tpm_limit: int | None = None + rpm_limit: int | None = None + session_tpm_limit: int | None = None + session_rpm_limit: int | None = None + static_headers: dict[str, str] | None = None + extra_headers: list[str] | None = None + keys: list[AgentKeySummary] | None = None + created_at: datetime | None = None + updated_at: datetime | None = None + created_by: str | None = None + updated_by: str | None = None class ListAgentsResponse(BaseModel): - agents: List[AgentResponse] + agents: list[AgentResponse] class AgentCreateResponse(LiteLLMPydanticObjectBase): @@ -246,8 +246,8 @@ class AgentCreateResponse(LiteLLMPydanticObjectBase): are preserved via extra="allow". """ - id: Optional[str] = None - name: Optional[str] = None + id: str | None = None + name: str | None = None model_config = {"extra": "allow"} _hidden_params: dict = PrivateAttr(default_factory=dict) @@ -274,8 +274,8 @@ class AgentListResponse(LiteLLMPydanticObjectBase): a plain dict so no fields are silently dropped. """ - agents: List[Dict[str, Any]] = [] - next_page_token: Optional[str] = None + agents: list[dict[str, Any]] = [] + next_page_token: str | None = None model_config = {"extra": "allow"} _hidden_params: dict = PrivateAttr(default_factory=dict) @@ -288,8 +288,8 @@ class AgentVersionsResponse(LiteLLMPydanticObjectBase): field of the form ``agents/{agent_id}/versions/{uuid}``. """ - agent_versions: List[Dict[str, Any]] = [] - next_page_token: Optional[str] = None + agent_versions: list[dict[str, Any]] = [] + next_page_token: str | None = None model_config = {"extra": "allow"} _hidden_params: dict = PrivateAttr(default_factory=dict) @@ -297,18 +297,18 @@ class AgentVersionsResponse(LiteLLMPydanticObjectBase): class AgentMakePublicResponse(BaseModel): message: str - public_agent_groups: List[str] + public_agent_groups: list[str] updated_by: str class MakeAgentsPublicRequest(BaseModel): - agent_ids: List[str] + agent_ids: list[str] def _normalize_a2a_jsonrpc_response( - response_dict: Dict[str, Any], - request_id: Optional[Any] = None, -) -> Dict[str, Any]: + response_dict: dict[str, Any], + request_id: Any | None = None, +) -> dict[str, Any]: """ Ensure JSON-RPC responses include ``id`` when the caller supplied one. @@ -333,11 +333,11 @@ class LiteLLMSendMessageResponse(LiteLLMPydanticObjectBase): # A2A response fields id: str jsonrpc: str = "2.0" - result: Optional[Dict[str, Any]] = None - error: Optional[Dict[str, Any]] = None + result: dict[str, Any] | None = None + error: dict[str, Any] | None = None # LiteLLM usage tracking - usage: Optional[Dict[str, Any]] = None + usage: dict[str, Any] | None = None model_config = {"extra": "allow"} @@ -348,7 +348,7 @@ class LiteLLMSendMessageResponse(LiteLLMPydanticObjectBase): def from_a2a_response( cls, response: "SendMessageResponse", - request_id: Optional[Any] = None, + request_id: Any | None = None, ) -> "LiteLLMSendMessageResponse": """ Create a LiteLLMSendMessageResponse from an a2a SDK SendMessageResponse. @@ -367,8 +367,8 @@ class LiteLLMSendMessageResponse(LiteLLMPydanticObjectBase): @classmethod def from_dict( cls, - response_dict: Dict[str, Any], - request_id: Optional[Any] = None, + response_dict: dict[str, Any], + request_id: Any | None = None, ) -> "LiteLLMSendMessageResponse": """ Create a LiteLLMSendMessageResponse from a dict. diff --git a/litellm/types/caching.py b/litellm/types/caching.py index 02cdeb528e9..6616a2e9bac 100644 --- a/litellm/types/caching.py +++ b/litellm/types/caching.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Final, Literal, Optional, Union from pydantic import BaseModel from typing_extensions import TypedDict @@ -40,7 +40,7 @@ class RedisPipelineIncrementOperation(TypedDict): key: str increment_value: float - ttl: Optional[int] + ttl: int | None class RedisPipelineSetOperation(TypedDict): @@ -50,7 +50,7 @@ class RedisPipelineSetOperation(TypedDict): key: str value: Any - ttl: Optional[int] + ttl: int | None class RedisPipelineRpushOperation(TypedDict): @@ -59,7 +59,7 @@ class RedisPipelineRpushOperation(TypedDict): """ key: str - values: List[Any] + values: list[Any] class RedisPipelineLpopOperation(TypedDict): @@ -68,23 +68,23 @@ class RedisPipelineLpopOperation(TypedDict): """ key: str - count: Optional[int] + count: int | None DynamicCacheControl = TypedDict( "DynamicCacheControl", { # Will cache the response for the user-defined amount of time (in seconds). - "ttl": Optional[int], + "ttl": int | None, # Namespace to use for caching - "namespace": Optional[str], + "namespace": str | None, # Max Age to use for caching - "s-maxage": Optional[int], - "s-max-age": Optional[int], + "s-maxage": int | None, + "s-max-age": int | None, # Will not return a cached response, but instead call the actual endpoint. - "no-cache": Optional[bool], + "no-cache": bool | None, # Will not store the response in the cache. - "no-store": Optional[bool], + "no-store": bool | None, }, ) @@ -92,12 +92,12 @@ DynamicCacheControl = TypedDict( class CachePingResponse(BaseModel): status: str cache_type: str - ping_response: Optional[bool] = None - set_cache_response: Optional[str] = None - litellm_cache_params: Optional[str] = None + ping_response: bool | None = None + set_cache_response: str | None = None + litellm_cache_params: str | None = None # intentionally a dict, since we run masker.mask_dict() on HealthCheckCacheParams - health_check_cache_params: Optional[dict] = None + health_check_cache_params: dict | None = None class HealthCheckCacheParams(BaseModel): @@ -105,19 +105,19 @@ class HealthCheckCacheParams(BaseModel): Cache Params returned on /cache/ping call """ - host: Optional[str] = None - port: Optional[Union[str, int]] = None - redis_kwargs: Optional[Dict[str, Any]] = None - namespace: Optional[str] = None - redis_version: Optional[Union[str, int, float]] = None + host: str | None = None + port: str | int | None = None + redis_kwargs: dict[str, Any] | None = None + namespace: str | None = None + redis_version: str | int | float | None = None class CachedEmbedding(TypedDict): """Type definition for cached embedding objects""" - embedding: Optional[List[float]] - index: Optional[int] - object: Optional[str] - model: Optional[str] - prompt_tokens: Optional[int] - prompt_tokens_details: Optional[dict] + embedding: list[float] | None + index: int | None + object: str | None + model: str | None + prompt_tokens: int | None + prompt_tokens_details: dict | None diff --git a/litellm/types/completion.py b/litellm/types/completion.py index bdacf62fb92..84c804e9910 100644 --- a/litellm/types/completion.py +++ b/litellm/types/completion.py @@ -1,10 +1,11 @@ from __future__ import annotations +from collections.abc import Callable, Coroutine, Iterable from dataclasses import dataclass -from typing import Any, Callable, Coroutine, Final, Iterable, List, Optional, TYPE_CHECKING, Union +from typing import TYPE_CHECKING, Any, Literal, Union from pydantic import BaseModel, ConfigDict -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import Required, TypedDict if TYPE_CHECKING: import httpx @@ -57,11 +58,11 @@ class ChatCompletionContentPartImageParam(TypedDict, total=False): """The type of the content part.""" -ChatCompletionContentPartParam = Union[ChatCompletionContentPartTextParam, ChatCompletionContentPartImageParam] +ChatCompletionContentPartParam = ChatCompletionContentPartTextParam | ChatCompletionContentPartImageParam class ChatCompletionUserMessageParam(TypedDict, total=False): - content: Required[Union[str, Iterable[ChatCompletionContentPartParam]]] + content: Required[str | Iterable[ChatCompletionContentPartParam]] """The contents of the user message.""" role: Required[Literal["user"]] @@ -102,7 +103,7 @@ class Function(TypedDict, total=False): class ChatCompletionToolMessageParam(TypedDict, total=False): - content: Required[Union[str, Iterable[ChatCompletionContentPartParam]]] + content: Required[str | Iterable[ChatCompletionContentPartParam]] """The contents of the tool message.""" role: Required[Literal["tool"]] @@ -113,7 +114,7 @@ class ChatCompletionToolMessageParam(TypedDict, total=False): class ChatCompletionFunctionMessageParam(TypedDict, total=False): - content: Required[Union[str, Iterable[ChatCompletionContentPartParam]]] + content: Required[str | Iterable[ChatCompletionContentPartParam]] """The contents of the function message.""" name: Required[str] @@ -138,7 +139,7 @@ class ChatCompletionAssistantMessageParam(TypedDict, total=False): role: Required[Literal["assistant"]] """The role of the messages author, in this case `assistant`.""" - content: Optional[str] + content: str | None """The contents of the assistant message. Required unless `tool_calls` or `function_call` is specified. @@ -162,42 +163,42 @@ class ChatCompletionAssistantMessageParam(TypedDict, total=False): """The tool calls generated by the model, such as function calls.""" -ChatCompletionMessageParam = Union[ - ChatCompletionSystemMessageParam, - ChatCompletionUserMessageParam, - ChatCompletionAssistantMessageParam, - ChatCompletionFunctionMessageParam, - ChatCompletionToolMessageParam, -] +ChatCompletionMessageParam = ( + ChatCompletionSystemMessageParam + | ChatCompletionUserMessageParam + | ChatCompletionAssistantMessageParam + | ChatCompletionFunctionMessageParam + | ChatCompletionToolMessageParam +) class CompletionRequest(BaseModel): model: str - messages: List[ChatCompletionMessageParam] = [] - timeout: Optional[Union[float, int]] = None - temperature: Optional[float] = None - top_p: Optional[float] = None - n: Optional[int] = None - stream: Optional[bool] = None - stop: Optional[dict] = None - max_tokens: Optional[int] = None - presence_penalty: Optional[float] = None - frequency_penalty: Optional[float] = None - logit_bias: Optional[dict] = None - user: Optional[str] = None - response_format: Optional[dict] = None - seed: Optional[int] = None - tools: Optional[List[str]] = None - tool_choice: Optional[str] = None - logprobs: Optional[bool] = None - top_logprobs: Optional[int] = None - deployment_id: Optional[str] = None - functions: Optional[List[str]] = None - function_call: Optional[str] = None - base_url: Optional[str] = None - api_version: Optional[str] = None - api_key: Optional[str] = None - model_list: Optional[List[str]] = None + messages: list[ChatCompletionMessageParam] = [] + timeout: float | int | None = None + temperature: float | None = None + top_p: float | None = None + n: int | None = None + stream: bool | None = None + stop: dict | None = None + max_tokens: int | None = None + presence_penalty: float | None = None + frequency_penalty: float | None = None + logit_bias: dict | None = None + user: str | None = None + response_format: dict | None = None + seed: int | None = None + tools: list[str] | None = None + tool_choice: str | None = None + logprobs: bool | None = None + top_logprobs: int | None = None + deployment_id: str | None = None + functions: list[str] | None = None + function_call: str | None = None + base_url: str | None = None + api_version: str | None = None + api_key: str | None = None + model_list: list[str] | None = None model_config = ConfigDict(protected_namespaces=(), extra="allow") @@ -206,34 +207,34 @@ class CompletionRequest(BaseModel): class _CompletionDispatchContext: _azure_detection_model: str acompletion: bool - api_base: Optional[str] - api_key: Optional[str] - api_version: Optional[str] + api_base: str | None + api_key: str | None + api_version: str | None client: Any custom_llm_provider: str custom_prompt_dict: dict - extra_headers: Optional[dict] + extra_headers: dict | None headers: dict - hf_model_name: Optional[str] + hf_model_name: str | None kwargs: dict litellm_params: dict - logger_fn: Optional[Callable] + logger_fn: Callable | None logging: LiteLLMLoggingObj - max_retries: Optional[int] - max_tokens: Optional[int] + max_retries: int | None + max_tokens: int | None messages: list - metadata: Optional[dict] + metadata: dict | None model: str model_response: ModelResponse optional_params: dict - organization: Optional[str] - provider_config: Optional[BaseConfig] - shared_session: Optional[ClientSession] - stream: Optional[bool] - temperature: Optional[float] + organization: str | None + provider_config: BaseConfig | None + shared_session: ClientSession | None + stream: bool | None + temperature: float | None text_completion: bool - timeout: Optional[Union[float, str, httpx.Timeout]] - top_p: Optional[float] + timeout: float | str | httpx.Timeout | None + top_p: float | None _CompletionDispatchResult = Union[ diff --git a/litellm/types/compression.py b/litellm/types/compression.py index 5dae0c397f0..342acd073e5 100644 --- a/litellm/types/compression.py +++ b/litellm/types/compression.py @@ -5,18 +5,18 @@ Type definitions for litellm.compress(). import sys if sys.version_info >= (3, 11): - from typing import Dict, List, NotRequired, TypedDict + from typing import NotRequired, TypedDict else: - from typing import Dict, List, TypedDict + from typing import TypedDict from typing_extensions import NotRequired class CompressedResult(TypedDict): - messages: List[dict] # compressed messages (stubs replace low-relevance messages) + messages: list[dict] # compressed messages (stubs replace low-relevance messages) original_tokens: int # token count before compression compressed_tokens: int # token count after compression compression_ratio: float # fraction reduced, e.g. 0.6 means 60% reduction - cache: Dict[str, str] # key -> original content (for retrieval tool responses) - tools: List[dict] # [litellm_content_retrieve tool definition] + cache: dict[str, str] # key -> original content (for retrieval tool responses) + tools: list[dict] # [litellm_content_retrieve tool definition] compression_skipped_reason: NotRequired[str] diff --git a/litellm/types/containers/main.py b/litellm/types/containers/main.py index 0377426bc93..73e5715ac31 100644 --- a/litellm/types/containers/main.py +++ b/litellm/types/containers/main.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Literal from pydantic import BaseModel from typing_extensions import TypedDict @@ -18,12 +18,12 @@ class ContainerObject(BaseModel): object: Literal["container"] created_at: int status: str - expires_after: Optional[ExpiresAfter] = None - last_active_at: Optional[int] = None - name: Optional[str] = None - _hidden_params: Dict[str, Any] = {} + expires_after: ExpiresAfter | None = None + last_active_at: int | None = None + name: str | None = None + _hidden_params: dict[str, Any] = {} - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -50,7 +50,7 @@ class DeleteContainerResult(BaseModel): object: Literal["container.deleted"] deleted: bool - def __contains__(self, key): + def __contains__(self, key) -> bool: return hasattr(self, key) def get(self, key, default=None): @@ -70,12 +70,12 @@ class ContainerListResponse(BaseModel): """Response object for list containers request.""" object: Literal["list"] - data: List[ContainerObject] - first_id: Optional[str] = None - last_id: Optional[str] = None + data: list[ContainerObject] + first_id: str | None = None + last_id: str | None = None has_more: bool - def __contains__(self, key): + def __contains__(self, key) -> bool: return hasattr(self, key) def get(self, key, default=None): @@ -98,10 +98,10 @@ class ContainerCreateOptionalRequestParams(TypedDict, total=False): Params here: https://platform.openai.com/docs/api-reference/containers/create """ - expires_after: Optional[Dict[str, Any]] # ExpiresAfter object - file_ids: Optional[List[str]] - extra_headers: Optional[Dict[str, str]] - extra_body: Optional[Dict[str, str]] + expires_after: dict[str, Any] | None # ExpiresAfter object + file_ids: list[str] | None + extra_headers: dict[str, str] | None + extra_body: dict[str, str] | None class ContainerCreateRequestParams(ContainerCreateOptionalRequestParams, total=False): @@ -121,11 +121,11 @@ class ContainerListOptionalRequestParams(TypedDict, total=False): Params here: https://platform.openai.com/docs/api-reference/containers/list """ - after: Optional[str] - limit: Optional[int] - order: Optional[str] - extra_headers: Optional[Dict[str, str]] - extra_query: Optional[Dict[str, str]] + after: str | None + limit: int | None + order: str | None + extra_headers: dict[str, str] | None + extra_query: dict[str, str] | None class ContainerFileObject(BaseModel): @@ -134,13 +134,13 @@ class ContainerFileObject(BaseModel): id: str object: Literal["container.file", "container_file"] # OpenAI returns "container.file" container_id: str - bytes: Optional[int] = None # Can be null for some files + bytes: int | None = None # Can be null for some files created_at: int path: str source: str - _hidden_params: Dict[str, Any] = {} + _hidden_params: dict[str, Any] = {} - def __contains__(self, key): + def __contains__(self, key) -> bool: return hasattr(self, key) def get(self, key, default=None): @@ -160,12 +160,12 @@ class ContainerFileListResponse(BaseModel): """Response object for list container files request.""" object: Literal["list"] - data: List[ContainerFileObject] - first_id: Optional[str] = None - last_id: Optional[str] = None + data: list[ContainerFileObject] + first_id: str | None = None + last_id: str | None = None has_more: bool - def __contains__(self, key): + def __contains__(self, key) -> bool: return hasattr(self, key) def get(self, key, default=None): @@ -189,7 +189,7 @@ class DeleteContainerFileResponse(BaseModel): object: Literal["container.file.deleted", "container_file.deleted"] deleted: bool - def __contains__(self, key): + def __contains__(self, key) -> bool: return hasattr(self, key) def get(self, key, default=None): diff --git a/litellm/types/embedding.py b/litellm/types/embedding.py index f8fdebc5391..cc1f518f20b 100644 --- a/litellm/types/embedding.py +++ b/litellm/types/embedding.py @@ -1,21 +1,19 @@ -from typing import List, Optional, Union - from pydantic import BaseModel, ConfigDict class EmbeddingRequest(BaseModel): model: str - input: List[str] = [] + input: list[str] = [] timeout: int = 600 - api_base: Optional[str] = None - api_version: Optional[str] = None - api_key: Optional[str] = None - api_type: Optional[str] = None + api_base: str | None = None + api_version: str | None = None + api_key: str | None = None + api_type: str | None = None caching: bool = False - user: Optional[str] = None - custom_llm_provider: Optional[Union[str, dict]] = None - litellm_call_id: Optional[str] = None - litellm_logging_obj: Optional[dict] = None - logger_fn: Optional[str] = None + user: str | None = None + custom_llm_provider: str | dict | None = None + litellm_call_id: str | None = None + litellm_logging_obj: dict | None = None + logger_fn: str | None = None model_config = ConfigDict(extra="allow") diff --git a/litellm/types/files.py b/litellm/types/files.py index 99e0139d6d7..e351a8cba37 100644 --- a/litellm/types/files.py +++ b/litellm/types/files.py @@ -1,6 +1,7 @@ +from collections.abc import Mapping from enum import Enum from types import MappingProxyType -from typing import Any, Dict, Final, List, Literal, Mapping, Set, Union +from typing import Any, Final, Literal from typing_extensions import Required, TypedDict @@ -54,7 +55,7 @@ class FileType(Enum): XLSX = "XLSX" -FILE_EXTENSIONS: Final[Mapping[FileType, List[str]]] = MappingProxyType( +FILE_EXTENSIONS: Final[Mapping[FileType, list[str]]] = MappingProxyType( { FileType.AAC: ["aac"], FileType.CSV: ["csv"], @@ -249,7 +250,7 @@ Other FileType Groupings """ # Accepted file types for GEMINI 1.5 through Vertex AI # https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/send-multimodal-prompts#gemini-send-multimodal-samples-images-nodejs -GEMINI_1_5_ACCEPTED_FILE_TYPES: Final[Set[FileType]] = { +GEMINI_1_5_ACCEPTED_FILE_TYPES: Final[set[FileType]] = { # Image FileType.PNG, FileType.JPEG, @@ -302,8 +303,8 @@ class TwoStepFileUploadRequest(TypedDict): method: Required[str] url: Required[str] - headers: Required[Dict[str, str]] - data: Required[Union[str, bytes, Dict[str, Any]]] + headers: Required[dict[str, str]] + data: Required[str | bytes | dict[str, Any]] class TwoStepFileUploadConfig(TypedDict, total=False): diff --git a/litellm/types/google_genai/main.py b/litellm/types/google_genai/main.py index b2e1fb3d46b..90b5eb9500c 100644 --- a/litellm/types/google_genai/main.py +++ b/litellm/types/google_genai/main.py @@ -1,8 +1,5 @@ # Import types from the Google GenAI SDK -from typing import TYPE_CHECKING, Any, Dict, List, Optional, TypeAlias - -from pydantic import BaseModel -from typing_extensions import TypedDict +from typing import TYPE_CHECKING, Any from litellm.types.llms.openai import BaseLiteLLMOpenAIResponseObject @@ -20,40 +17,39 @@ if TYPE_CHECKING: ToolConfigDict = _genai_types.ToolConfigDict class GenerateContentRequestDict(GenerateContentRequestParametersDict): # type: ignore[misc, valid-type] - generationConfig: Optional[Any] - tools: Optional[ToolConfigDict] # type: ignore[assignment, valid-type] + generationConfig: Any | None + tools: ToolConfigDict | None # type: ignore[assignment, valid-type] class GenerateContentResponse(GoogleGenAIGenerateContentResponse, BaseLiteLLMOpenAIResponseObject): # type: ignore[misc, valid-type] _hidden_params: dict = {} - pass else: # Fallback types when google.genai is not available ContentListUnion = Any - ContentListUnionDict = Dict[str, Any] - GenerateContentConfigOrDict = Dict[str, Any] - GoogleGenAIGenerateContentResponse = Dict[str, Any] - GenerateContentContentListUnionDict = Dict[str, Any] + ContentListUnionDict = dict[str, Any] + GenerateContentConfigOrDict = dict[str, Any] + GoogleGenAIGenerateContentResponse = dict[str, Any] + GenerateContentContentListUnionDict = dict[str, Any] # Create a proper fallback class that can be instantiated class GenerateContentConfigDict(dict): # type: ignore[misc] - def __init__(self, **kwargs): # type: ignore + def __init__(self, **kwargs) -> None: # type: ignore super().__init__(**kwargs) class GenerateContentRequestParametersDict(dict): # type: ignore[misc] - def __init__(self, **kwargs): # type: ignore + def __init__(self, **kwargs) -> None: # type: ignore super().__init__(**kwargs) - ToolConfigDict = Dict[str, Any] + ToolConfigDict = dict[str, Any] class GenerateContentRequestDict(GenerateContentRequestParametersDict): # type: ignore[misc] - def __init__(self, **kwargs): # type: ignore + def __init__(self, **kwargs) -> None: # type: ignore # Extract specific fields self.generationConfig = kwargs.get("generationConfig") self.tools = kwargs.get("tools") super().__init__(**kwargs) class GenerateContentResponse(BaseLiteLLMOpenAIResponseObject): # type: ignore[misc] - def __init__(self, **kwargs): # type: ignore + def __init__(self, **kwargs) -> None: # type: ignore super().__init__(**kwargs) self._hidden_params = kwargs.get("_hidden_params", {}) diff --git a/litellm/types/guardrails.py b/litellm/types/guardrails.py index e7ad5cb801d..329b043c019 100644 --- a/litellm/types/guardrails.py +++ b/litellm/types/guardrails.py @@ -1,6 +1,6 @@ from datetime import datetime from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Final, Literal from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from typing_extensions import Required, TypedDict @@ -11,12 +11,24 @@ from litellm.types.proxy.guardrails.guardrail_hooks.akto import ( from litellm.types.proxy.guardrails.guardrail_hooks.block_code_execution import ( BlockCodeExecutionGuardrailConfigModel, ) +from litellm.types.proxy.guardrails.guardrail_hooks.cisco_ai_defense import ( + CiscoAIDefenseGuardrailConfigModel, +) +from litellm.types.proxy.guardrails.guardrail_hooks.compresr import ( + CompresrGuardrailConfigModel, +) from litellm.types.proxy.guardrails.guardrail_hooks.enkryptai import ( EnkryptAIGuardrailConfigs, ) from litellm.types.proxy.guardrails.guardrail_hooks.grayswan import ( GraySwanGuardrailConfigModel, ) +from litellm.types.proxy.guardrails.guardrail_hooks.headroom import ( + HeadroomGuardrailConfigModel, +) +from litellm.types.proxy.guardrails.guardrail_hooks.hiddenlayer import ( + HiddenlayerGuardrailConfigModel, +) from litellm.types.proxy.guardrails.guardrail_hooks.ibm import ( IBMGuardrailsBaseConfigModel, ) @@ -29,38 +41,26 @@ from litellm.types.proxy.guardrails.guardrail_hooks.ovalix import ( from litellm.types.proxy.guardrails.guardrail_hooks.promptguard import ( PromptGuardConfigModel, ) -from litellm.types.proxy.guardrails.guardrail_hooks.xecguard import ( - XecGuardConfigModel, +from litellm.types.proxy.guardrails.guardrail_hooks.qohash import ( + QostodianNexusConfigModel, ) from litellm.types.proxy.guardrails.guardrail_hooks.qualifire import ( QualifireGuardrailConfigModel, ) -from litellm.types.proxy.guardrails.guardrail_hooks.tool_permission import ( - ToolPermissionGuardrailConfigModel, -) -from litellm.types.proxy.guardrails.guardrail_hooks.hiddenlayer import ( - HiddenlayerGuardrailConfigModel, -) -from litellm.types.proxy.guardrails.guardrail_hooks.qohash import ( - QostodianNexusConfigModel, -) from litellm.types.proxy.guardrails.guardrail_hooks.repelloai import ( RepelloAIGuardrailConfigModel, ) -from litellm.types.proxy.guardrails.guardrail_hooks.vigil_guard import ( - VigilGuardGuardrailConfigModel, -) -from litellm.types.proxy.guardrails.guardrail_hooks.cisco_ai_defense import ( - CiscoAIDefenseGuardrailConfigModel, -) from litellm.types.proxy.guardrails.guardrail_hooks.singulr import ( SingulrGuardrailConfigModel, ) -from litellm.types.proxy.guardrails.guardrail_hooks.headroom import ( - HeadroomGuardrailConfigModel, +from litellm.types.proxy.guardrails.guardrail_hooks.tool_permission import ( + ToolPermissionGuardrailConfigModel, ) -from litellm.types.proxy.guardrails.guardrail_hooks.compresr import ( - CompresrGuardrailConfigModel, +from litellm.types.proxy.guardrails.guardrail_hooks.vigil_guard import ( + VigilGuardGuardrailConfigModel, +) +from litellm.types.proxy.guardrails.guardrail_hooks.xecguard import ( + XecGuardConfigModel, ) """ @@ -145,32 +145,34 @@ default_roles: Final = [Role.SYSTEM, Role.ASSISTANT, Role.USER] class GuardrailItemSpec(TypedDict, total=False): - callbacks: Required[List[str]] + callbacks: Required[list[str]] default_on: bool - logging_only: Optional[bool] - enabled_roles: Optional[List[Role]] - callback_args: Dict[str, Dict] + logging_only: bool | None + enabled_roles: list[Role] | None + callback_args: dict[str, dict] class GuardrailItem(BaseModel): - callbacks: List[str] + callbacks: list[str] default_on: bool - logging_only: Optional[bool] + logging_only: bool | None guardrail_name: str - callback_args: Dict[str, Dict] - enabled_roles: Optional[List[Role]] + callback_args: dict[str, dict] + enabled_roles: list[Role] | None model_config = ConfigDict(use_enum_values=True) def __init__( self, - callbacks: List[str], + callbacks: list[str], guardrail_name: str, default_on: bool = False, - logging_only: Optional[bool] = None, - enabled_roles: Optional[List[Role]] = default_roles, - callback_args: Dict[str, Dict] = {}, - ): + logging_only: bool | None = None, + enabled_roles: list[Role] | None = default_roles, + callback_args: dict[str, dict] | None = None, + ) -> None: + if callback_args is None: + callback_args = {} super().__init__( callbacks=callbacks, default_on=default_on, @@ -322,7 +324,7 @@ PII_ENTITY_CATEGORIES_MAP: Final = { class PiiEntityCategoryMap(TypedDict): category: str - entities: List[str] + entities: list[str] class GuardrailParamUITypes(str, Enum): @@ -335,31 +337,31 @@ class GuardrailParamUITypes(str, Enum): class PresidioPresidioConfigModelUserInterface(BaseModel): """Configuration parameters for the Presidio PII masking guardrail on LiteLLM UI""" - presidio_analyzer_api_base: Optional[str] = Field( + presidio_analyzer_api_base: str | None = Field( default=None, description="Base URL for the Presidio analyzer API", ) - presidio_anonymizer_api_base: Optional[str] = Field( + presidio_anonymizer_api_base: str | None = Field( default=None, description="Base URL for the Presidio anonymizer API", ) - presidio_filter_scope: Optional[Literal["input", "output", "both"]] = Field( + presidio_filter_scope: Literal["input", "output", "both"] | None = Field( default=None, description=( "Where to apply Presidio checks: 'input' (user -> model), 'output' (model -> user), or 'both' (default)." ), ) - output_parse_pii: Optional[bool] = Field( + output_parse_pii: bool | None = Field( default=None, description="When True, LiteLLM will replace the masked text with the original text in the response", # extra param to let the ui know this is a boolean json_schema_extra={"ui_type": GuardrailParamUITypes.BOOL}, ) - presidio_language: Optional[str] = Field( + presidio_language: str | None = Field( default="en", description="Language code for Presidio PII analysis (e.g., 'en', 'de', 'es', 'fr')", ) - presidio_run_on: Optional[Literal["input", "output", "both"]] = Field( + presidio_run_on: Literal["input", "output", "both"] | None = Field( default=None, description="Where to apply Presidio checks: input, output, or both (default).", ) @@ -368,18 +370,18 @@ class PresidioPresidioConfigModelUserInterface(BaseModel): class PresidioConfigModel(PresidioPresidioConfigModelUserInterface): """Configuration parameters for the Presidio PII masking guardrail""" - pii_entities_config: Optional[Dict[Union[PiiEntityType, str], PiiAction]] = Field( + pii_entities_config: dict[PiiEntityType | str, PiiAction] | None = Field( default=None, description="Configuration for PII entity types and actions" ) - presidio_score_thresholds: Optional[Dict[Union[PiiEntityType, str], float]] = Field( + presidio_score_thresholds: dict[PiiEntityType | str, float] | None = Field( default=None, description=( "Optional per-entity minimum confidence scores for Presidio detections. " "Entities below the threshold are ignored." ), ) - presidio_entities_deny_list: Optional[List[Union[PiiEntityType, str]]] = Field( + presidio_entities_deny_list: list[PiiEntityType | str] | None = Field( default=None, description=( "List of entity types to exclude from Presidio detection results. " @@ -387,11 +389,11 @@ class PresidioConfigModel(PresidioPresidioConfigModelUserInterface): "Useful for suppressing false positives (e.g., US_DRIVER_LICENSE on coding routes)." ), ) - presidio_ad_hoc_recognizers: Optional[str] = Field( + presidio_ad_hoc_recognizers: str | None = Field( default=None, description="Path to a JSON file containing ad-hoc recognizers for Presidio", ) - mock_redacted_text: Optional[dict] = Field(default=None, description="Mock redacted text for testing") + mock_redacted_text: dict | None = Field(default=None, description="Mock redacted text for testing") BedrockChecksContentFilterCategory = Literal["VIOLENCE", "HATE", "SEXUAL", "MISCONDUCT", "INSULTS"] @@ -477,27 +479,25 @@ class BedrockChecksConfigModel(BaseModel): class BedrockGuardrailConfigModel(BaseModel): """Configuration parameters for the AWS Bedrock guardrail""" - guardrailIdentifier: Optional[str] = Field(default=None, description="The ID of your guardrail on Bedrock") - guardrailVersion: Optional[str] = Field( + guardrailIdentifier: str | None = Field(default=None, description="The ID of your guardrail on Bedrock") + guardrailVersion: str | None = Field( default=None, description="The version of your Bedrock guardrail (e.g., DRAFT or version number)", ) - disable_exception_on_block: Optional[bool] = Field( + disable_exception_on_block: bool | None = Field( default=False, description="If True, will not raise an exception when the guardrail is blocked. Useful for OpenWebUI where exceptions can end the chat flow.", ) - aws_region_name: Optional[str] = Field(default=None, description="AWS region where your guardrail is deployed") - aws_access_key_id: Optional[str] = Field(default=None, description="AWS access key ID for authentication") - aws_secret_access_key: Optional[str] = Field(default=None, description="AWS secret access key for authentication") - aws_session_token: Optional[str] = Field(default=None, description="AWS session token for temporary credentials") - aws_session_name: Optional[str] = Field(default=None, description="Name of the AWS session") - aws_profile_name: Optional[str] = Field(default=None, description="AWS profile name for credential retrieval") - aws_role_name: Optional[str] = Field(default=None, description="AWS role name for assuming roles") - aws_web_identity_token: Optional[str] = Field( - default=None, description="Web identity token for AWS role assumption" - ) - aws_sts_endpoint: Optional[str] = Field(default=None, description="AWS STS endpoint URL") - aws_bedrock_runtime_endpoint: Optional[str] = Field(default=None, description="AWS Bedrock runtime endpoint URL") + aws_region_name: str | None = Field(default=None, description="AWS region where your guardrail is deployed") + aws_access_key_id: str | None = Field(default=None, description="AWS access key ID for authentication") + aws_secret_access_key: str | None = Field(default=None, description="AWS secret access key for authentication") + aws_session_token: str | None = Field(default=None, description="AWS session token for temporary credentials") + aws_session_name: str | None = Field(default=None, description="Name of the AWS session") + aws_profile_name: str | None = Field(default=None, description="AWS profile name for credential retrieval") + aws_role_name: str | None = Field(default=None, description="AWS role name for assuming roles") + aws_web_identity_token: str | None = Field(default=None, description="Web identity token for AWS role assumption") + aws_sts_endpoint: str | None = Field(default=None, description="AWS STS endpoint URL") + aws_bedrock_runtime_endpoint: str | None = Field(default=None, description="AWS Bedrock runtime endpoint URL") checks: BedrockChecksConfigModel | None = Field( default=None, description="Inline safeguards for the resource-less InvokeGuardrailChecks API " @@ -532,17 +532,17 @@ class BedrockGuardrailConfigModel(BaseModel): class LakeraV2GuardrailConfigModel(BaseModel): """Configuration parameters for the Lakera AI v2 guardrail""" - api_key: Optional[str] = Field(default=None, description="API key for the Lakera AI service") - api_base: Optional[str] = Field(default=None, description="Base URL for the Lakera AI API") - project_id: Optional[str] = Field(default=None, description="Project ID for the Lakera AI project") - payload: Optional[bool] = Field(default=True, description="Whether to include payload in the response") - breakdown: Optional[bool] = Field(default=True, description="Whether to include breakdown in the response") - metadata: Optional[Dict] = Field(default=None, description="Additional metadata to include in the request") - dev_info: Optional[bool] = Field( + api_key: str | None = Field(default=None, description="API key for the Lakera AI service") + api_base: str | None = Field(default=None, description="Base URL for the Lakera AI API") + project_id: str | None = Field(default=None, description="Project ID for the Lakera AI project") + payload: bool | None = Field(default=True, description="Whether to include payload in the response") + breakdown: bool | None = Field(default=True, description="Whether to include breakdown in the response") + metadata: dict | None = Field(default=None, description="Additional metadata to include in the request") + dev_info: bool | None = Field( default=True, description="Whether to include developer information in the response", ) - on_flagged: Optional[Literal["block", "monitor"]] = Field( + on_flagged: Literal["block", "monitor"] | None = Field( default="block", description="Action to take when content is flagged: 'block' (raise exception) or 'monitor' (log only)", ) @@ -551,15 +551,15 @@ class LakeraV2GuardrailConfigModel(BaseModel): class LassoGuardrailConfigModel(BaseModel): """Configuration parameters for the Lasso guardrail""" - lasso_user_id: Optional[str] = Field(default=None, description="User ID for the Lasso guardrail") - lasso_conversation_id: Optional[str] = Field(default=None, description="Conversation ID for the Lasso guardrail") - mask: Optional[bool] = Field(default=False, description="Enable content masking using Lasso classifix API") + lasso_user_id: str | None = Field(default=None, description="User ID for the Lasso guardrail") + lasso_conversation_id: str | None = Field(default=None, description="Conversation ID for the Lasso guardrail") + mask: bool | None = Field(default=False, description="Enable content masking using Lasso classifix API") class DeepKeepGuardrailConfigModel(BaseModel): """Configuration parameters for the DeepKeep AI Firewall guardrail""" - deepkeep_firewall_id: Optional[str] = Field( + deepkeep_firewall_id: str | None = Field( default=None, description=( "The DeepKeep Firewall ID to use for guardrail evaluation. " @@ -571,23 +571,23 @@ class DeepKeepGuardrailConfigModel(BaseModel): class PillarGuardrailConfigModel(BaseModel): """Configuration parameters for the Pillar Security guardrail""" - on_flagged_action: Optional[str] = Field( + on_flagged_action: str | None = Field( default="monitor", description="Action to take when content is flagged: 'block' (raise exception) or 'monitor' (log only)", ) - async_mode: Optional[bool] = Field( + async_mode: bool | None = Field( default=None, description="Set to True to request asynchronous analysis (sets `plr_async` header). Defaults to provider behaviour when omitted.", ) - persist_session: Optional[bool] = Field( + persist_session: bool | None = Field( default=None, description="Controls Pillar session persistence (sets `plr_persist` header). Set to False to disable persistence.", ) - include_scanners: Optional[bool] = Field( + include_scanners: bool | None = Field( default=True, description="Include scanner category summaries in responses (sets `plr_scanners` header).", ) - include_evidence: Optional[bool] = Field( + include_evidence: bool | None = Field( default=True, description="Include detailed evidence payloads in responses (sets `plr_evidence` header).", ) @@ -596,23 +596,23 @@ class PillarGuardrailConfigModel(BaseModel): class NomaGuardrailConfigModel(BaseModel): """Configuration parameters for the Noma Security guardrail""" - use_v2: Optional[bool] = Field( + use_v2: bool | None = Field( default=False, description="If True and guardrail='noma', route to the new Noma v2 implementation instead of the legacy implementation.", ) - application_id: Optional[str] = Field( + application_id: str | None = Field( default=None, description="Application ID for Noma Security. Defaults to 'litellm' if not provided", ) - monitor_mode: Optional[bool] = Field( + monitor_mode: bool | None = Field( default=None, description="If True, logs violations without blocking. Defaults to False if not provided", ) - block_failures: Optional[bool] = Field( + block_failures: bool | None = Field( default=None, description="If True, blocks requests on API failures. Defaults to True if not provided", ) - anonymize_input: Optional[bool] = Field( + anonymize_input: bool | None = Field( default=None, description="If True, replaces sensitive content with anonymized version when only PII/PCI/secrets are detected. Only applies in blocking mode. Defaults to False if not provided", ) @@ -621,17 +621,17 @@ class NomaGuardrailConfigModel(BaseModel): class ZscalerAIGuardConfigModel(BaseModel): """Configuration parameters for the Zscaler AI Guard guardrail""" - policy_id: Optional[int] = Field( + policy_id: int | None = Field( default=None, description="Policy ID for Zscaler AI Guard. Can also be set via ZSCALER_AI_GUARD_POLICY_ID environment variable", ) - send_user_api_key_alias: Optional[bool] = Field( + send_user_api_key_alias: bool | None = Field( default=False, description="Whether to send user_API_key_alias in headers" ) - send_user_api_key_user_id: Optional[bool] = Field( + send_user_api_key_user_id: bool | None = Field( default=False, description="Whether to send user_API_key_user_id in headers" ) - send_user_api_key_team_id: Optional[bool] = Field( + send_user_api_key_team_id: bool | None = Field( default=False, description="Whether to send user_API_key_team_id in headers" ) @@ -639,11 +639,11 @@ class ZscalerAIGuardConfigModel(BaseModel): class JavelinGuardrailConfigModel(BaseModel): """Configuration parameters for the Javelin guardrail""" - guard_name: Optional[str] = Field(default=None, description="Name of the Javelin guard to use") - api_version: Optional[str] = Field(default="v1", description="API version for Javelin service") - metadata: Optional[Dict] = Field(default=None, description="Additional metadata to send with requests") - application: Optional[str] = Field(default=None, description="Application name for Javelin service") - config: Optional[Dict] = Field(default=None, description="Additional configuration for the guardrail") + guard_name: str | None = Field(default=None, description="Name of the Javelin guard to use") + api_version: str | None = Field(default="v1", description="API version for Javelin service") + metadata: dict | None = Field(default=None, description="Additional metadata to send with requests") + application: str | None = Field(default=None, description="Application name for Javelin service") + config: dict | None = Field(default=None, description="Additional configuration for the guardrail") class ContentFilterAction(str, Enum): @@ -658,7 +658,7 @@ class BlockedWord(BaseModel): keyword: str = Field(description="The keyword to block or mask") action: ContentFilterAction = Field(description="Action to take when keyword is detected (BLOCK or MASK)") - description: Optional[str] = Field( + description: str | None = Field( default=None, description="Optional description explaining why this keyword is sensitive", ) @@ -670,15 +670,15 @@ class ContentFilterPattern(BaseModel): pattern_type: Literal["prebuilt", "regex"] = Field( description="Type of pattern: 'prebuilt' for predefined patterns or 'regex' for custom" ) - pattern_name: Optional[str] = Field( + pattern_name: str | None = Field( default=None, description="Name of prebuilt pattern (e.g., 'us_ssn', 'credit_card'). Required if pattern_type is 'prebuilt'", ) - pattern: Optional[str] = Field( + pattern: str | None = Field( default=None, description="Custom regex pattern. Required if pattern_type is 'regex'", ) - name: Optional[str] = Field( + name: str | None = Field( default=None, description="Name for this pattern (used in logging and error messages)", ) @@ -688,44 +688,42 @@ class ContentFilterPattern(BaseModel): class ContentFilterConfigModel(BaseModel): """Configuration parameters for the content filter guardrail""" - patterns: Optional[List[ContentFilterPattern]] = Field( + patterns: list[ContentFilterPattern] | None = Field( default=None, description="List of patterns (prebuilt or custom regex) to detect", ) - blocked_words: Optional[List[BlockedWord]] = Field( + blocked_words: list[BlockedWord] | None = Field( default=None, description="List of blocked words with individual actions" ) - blocked_words_file: Optional[str] = Field( - default=None, description="Path to YAML file containing blocked_words list" - ) - categories: Optional[List[ContentFilterCategoryConfig]] = Field( + blocked_words_file: str | None = Field(default=None, description="Path to YAML file containing blocked_words list") + categories: list[ContentFilterCategoryConfig] | None = Field( default=None, description="List of prebuilt categories to enable (harmful_*, bias_*)", ) - severity_threshold: Optional[str] = Field( + severity_threshold: str | None = Field( default=None, description="Minimum severity to block (high, medium, low)", ) - pattern_redaction_format: Optional[str] = Field( + pattern_redaction_format: str | None = Field( default=None, description="Format string for pattern redaction (use {pattern_name} placeholder)", ) - keyword_redaction_tag: Optional[str] = Field( + keyword_redaction_tag: str | None = Field( default=None, description="Tag to use for keyword redaction", ) class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch update guardrails - api_key: Optional[str] = Field(default=None, description="API key for the guardrail service") - api_base: Optional[str] = Field(default=None, description="Base URL for the guardrail service API") + api_key: str | None = Field(default=None, description="API key for the guardrail service") + api_base: str | None = Field(default=None, description="Base URL for the guardrail service API") - experimental_use_latest_role_message_only: Optional[bool] = Field( + experimental_use_latest_role_message_only: bool | None = Field( default=False, description="When True, guardrails only receive the latest message for the relevant role (e.g., newest user input pre-call, newest assistant output post-call)", ) - only_scan_new_messages: Optional[bool] = Field( + only_scan_new_messages: bool | None = Field( default=False, description=( "When True, the guardrail only scans messages that have not already been scanned " @@ -737,7 +735,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ), ) - skip_system_message_in_guardrail: Optional[bool] = Field( + skip_system_message_in_guardrail: bool | None = Field( default=None, description=( "When True, unified guardrails skip system-role messages when building " @@ -747,7 +745,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ), ) - skip_tool_message_in_guardrail: Optional[bool] = Field( + skip_tool_message_in_guardrail: bool | None = Field( default=None, description=( "When True, unified guardrails skip tool-role messages when building " @@ -758,70 +756,68 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ) # Lakera specific params - category_thresholds: Optional[LakeraCategoryThresholds] = Field( + category_thresholds: LakeraCategoryThresholds | None = Field( default=None, description="Threshold configuration for Lakera guardrail categories", ) # hide secrets params - detect_secrets_config: Optional[dict] = Field( - default=None, description="Configuration for detect-secrets guardrail" - ) + detect_secrets_config: dict | None = Field(default=None, description="Configuration for detect-secrets guardrail") # guardrails ai params - guard_name: Optional[str] = Field(default=None, description="Name of the guardrail in guardrails.ai") - default_on: Optional[bool] = Field(default=None, description="Whether the guardrail is enabled by default") + guard_name: str | None = Field(default=None, description="Name of the guardrail in guardrails.ai") + default_on: bool | None = Field(default=None, description="Whether the guardrail is enabled by default") ################## PII control params ################# ######################################################## - mask_request_content: Optional[bool] = Field( + mask_request_content: bool | None = Field( default=None, description="Will mask request content if guardrail makes any changes", ) - mask_response_content: Optional[bool] = Field( + mask_response_content: bool | None = Field( default=None, description="Will mask response content if guardrail makes any changes", ) # pangea params - pangea_input_recipe: Optional[str] = Field(default=None, description="Recipe for input (LLM request)") + pangea_input_recipe: str | None = Field(default=None, description="Recipe for input (LLM request)") - pangea_output_recipe: Optional[str] = Field(default=None, description="Recipe for output (LLM response)") + pangea_output_recipe: str | None = Field(default=None, description="Recipe for output (LLM response)") - model: Optional[str] = Field( + model: str | None = Field( default=None, description="Optional field if guardrail requires a 'model' parameter", ) - violation_message_template: Optional[str] = Field( + violation_message_template: str | None = Field( default=None, description="Custom message when a guardrail blocks an action. Supports placeholders like {tool_name}, {rule_id}, and {default_message}.", ) ################## Realtime API params ################ ######################################################## - end_session_after_n_fails: Optional[int] = Field( + end_session_after_n_fails: int | None = Field( default=None, description="For /v1/realtime sessions: automatically close the session after this many guardrail violations.", ) - on_violation: Optional[Literal["warn", "end_session"]] = Field( + on_violation: Literal["warn", "end_session"] | None = Field( default=None, description="For /v1/realtime sessions: 'warn' speaks the violation message and continues; 'end_session' speaks the message and closes the connection.", ) - realtime_violation_message: Optional[str] = Field( + realtime_violation_message: str | None = Field( default=None, description="The message the bot speaks aloud when a /v1/realtime guardrail fires. Falls back to violation_message_template if not set.", ) # Model Armor params - template_id: Optional[str] = Field(default=None, description="The ID of your Model Armor template") - location: Optional[str] = Field(default=None, description="Google Cloud location/region (e.g., us-central1)") - credentials: Optional[str] = Field( + template_id: str | None = Field(default=None, description="The ID of your Model Armor template") + location: str | None = Field(default=None, description="Google Cloud location/region (e.g., us-central1)") + credentials: str | None = Field( default=None, description="Path to Google Cloud credentials JSON file or JSON string", ) - api_endpoint: Optional[str] = Field(default=None, description="Optional custom API endpoint for Model Armor") - fail_on_error: Optional[bool] = Field( + api_endpoint: str | None = Field(default=None, description="Optional custom API endpoint for Model Armor") + fail_on_error: bool | None = Field( default=True, description=( "Whether to fail the request if the guardrail encounters an error. " @@ -830,7 +826,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up "so only a valid guardrail response can block or modify it." ), ) - skip_unscannable_attachments: Optional[bool] = Field( + skip_unscannable_attachments: bool | None = Field( default=False, description=( "Implemented by guardrail='model_armor'. When True, attachment references that carry no " @@ -838,7 +834,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up "while fail_on_error still governs real Model Armor API errors. Default False blocks them." ), ) - sanitize_error_detail: Optional[bool] = Field( + sanitize_error_detail: bool | None = Field( default=True, description=( "For guardrail='model_armor': omit the raw Model Armor response from " @@ -846,7 +842,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ), ) - additional_provider_specific_params: Optional[Dict[str, Any]] = Field( + additional_provider_specific_params: dict[str, Any] | None = Field( default=None, description="Additional provider-specific parameters for generic guardrail APIs", ) @@ -860,7 +856,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ), ) - extra_headers: Optional[List[str]] = Field( + extra_headers: list[str] | None = Field( default=None, description=( "Header names to forward from the client request to the guardrail (e.g. x-request-id). " @@ -870,12 +866,12 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ) # Custom code guardrail params - custom_code: Optional[str] = Field( + custom_code: str | None = Field( default=None, description="Python-like code containing the apply_guardrail function for custom guardrail logic", ) - timeout: Optional[float] = Field( + timeout: float | None = Field( default=None, description=( "Per-request timeout for the guardrail provider API call (seconds). " @@ -884,7 +880,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ), ) - on_sensitive_data: Optional[Literal["block", "route"]] = Field( + on_sensitive_data: Literal["block", "route"] | None = Field( default=None, description=( "Action to take when sensitive data is detected. " @@ -893,7 +889,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ), ) - sensitive_data_route_to_model: Optional[str] = Field( + sensitive_data_route_to_model: str | None = Field( default=None, description=( "Model to route requests to when sensitive data is detected and on_sensitive_data='route'. " @@ -902,7 +898,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ), ) - sticky_session_routing: Optional[bool] = Field( + sticky_session_routing: bool | None = Field( default=True, description=( "When True (default), after sensitive data is detected and routed, all subsequent " @@ -910,7 +906,7 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up ), ) - run_in_parallel: Optional[bool] = Field( + run_in_parallel: bool | None = Field( default=None, description=( "When True, this pre_call or post_call guardrail runs concurrently with other opted-in " @@ -949,8 +945,8 @@ class BaseLitellmParams(ContentFilterConfigModel): # works for new and patch up class Mode(BaseModel): - tags: Dict[str, Union[str, List[str]]] = Field(description="Tags for the guardrail mode") - default: Optional[Union[str, List[str]]] = Field(default=None, description="Default mode when no tags match") + tags: dict[str, str | list[str]] = Field(description="Tags for the guardrail mode") + default: str | list[str] | None = Field(default=None, description="Default mode when no tags match") class LitellmParams( @@ -984,7 +980,7 @@ class LitellmParams( SingulrGuardrailConfigModel, ): guardrail: str = Field(description="The type of guardrail integration to use") - mode: Union[str, List[str], Mode] = Field( + mode: str | list[str] | Mode = Field( description="When to apply the guardrail (pre_call, post_call, during_call, logging_only)" ) @@ -1000,7 +996,7 @@ class LitellmParams( except (TypeError, ValueError) as e: raise ValueError(f"timeout must be numeric, got {v!r}") from e - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: default_on: Final = kwargs.pop("default_on", None) if default_on is not None: kwargs["default_on"] = default_on @@ -1009,7 +1005,7 @@ class LitellmParams( super().__init__(**kwargs) - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1023,17 +1019,17 @@ class LitellmParams( class Guardrail(TypedDict, total=False): - guardrail_id: Optional[str] + guardrail_id: str | None guardrail_name: Required[str] litellm_params: Required[LitellmParams] - guardrail_info: Optional[Dict] - policy_template: Optional[str] - created_at: Optional[datetime] - updated_at: Optional[datetime] + guardrail_info: dict | None + policy_template: str | None + created_at: datetime | None + updated_at: datetime | None class guardrailConfig(TypedDict): - guardrails: List[Guardrail] + guardrails: list[Guardrail] class GuardrailEventHooks(str, Enum): @@ -1048,7 +1044,7 @@ class GuardrailEventHooks(str, Enum): class DynamicGuardrailParams(TypedDict): - extra_body: Dict[str, Any] + extra_body: dict[str, Any] class GUARDRAIL_DEFINITION_LOCATION(str, Enum): @@ -1057,29 +1053,29 @@ class GUARDRAIL_DEFINITION_LOCATION(str, Enum): class GuardrailInfoResponse(BaseModel): - guardrail_id: Optional[str] = None + guardrail_id: str | None = None guardrail_name: str - litellm_params: Optional[BaseLitellmParams] = None - guardrail_info: Optional[Dict] = None - created_at: Optional[datetime] = None - updated_at: Optional[datetime] = None + litellm_params: BaseLitellmParams | None = None + guardrail_info: dict | None = None + created_at: datetime | None = None + updated_at: datetime | None = None guardrail_definition_location: GUARDRAIL_DEFINITION_LOCATION = GUARDRAIL_DEFINITION_LOCATION.CONFIG - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: super().__init__(**kwargs) class ListGuardrailsResponse(BaseModel): - guardrails: List[GuardrailInfoResponse] + guardrails: list[GuardrailInfoResponse] class GuardrailUIAddGuardrailSettings(BaseModel): - supported_entities: List[str] - supported_actions: List[str] - supported_modes: List[str] - supported_modes_by_provider: Dict[str, List[str]] - pii_entity_categories: List[PiiEntityCategoryMap] - content_filter_settings: Optional[Dict[str, Any]] = None + supported_entities: list[str] + supported_actions: list[str] + supported_modes: list[str] + supported_modes_by_provider: dict[str, list[str]] + pii_entity_categories: list[PiiEntityCategoryMap] + content_filter_settings: dict[str, Any] | None = None class PresidioPerRequestConfig(BaseModel): @@ -1087,18 +1083,18 @@ class PresidioPerRequestConfig(BaseModel): presdio params that can be controlled per request, api key """ - language: Optional[str] = None - entities: Optional[List[PiiEntityType]] = None + language: str | None = None + entities: list[PiiEntityType] | None = None class ApplyGuardrailRequest(BaseModel): guardrail_name: str text: str - language: Optional[str] = None - entities: Optional[List[PiiEntityType]] = None + language: str | None = None + entities: list[PiiEntityType] | None = None input_type: str = "request" - messages: Optional[List[Dict[str, Any]]] = None - metadata: Dict[str, Any] | None = None + messages: list[dict[str, Any]] | None = None + metadata: dict[str, Any] | None = None class ApplyGuardrailResponse(BaseModel): @@ -1106,6 +1102,6 @@ class ApplyGuardrailResponse(BaseModel): class PatchGuardrailRequest(BaseModel): - guardrail_name: Optional[str] = None - litellm_params: Optional[BaseLitellmParams] = None - guardrail_info: Optional[Dict[str, Any]] = None + guardrail_name: str | None = None + litellm_params: BaseLitellmParams | None = None + guardrail_info: dict[str, Any] | None = None diff --git a/litellm/types/images/main.py b/litellm/types/images/main.py index 80e55297c42..5d80135a8a1 100644 --- a/litellm/types/images/main.py +++ b/litellm/types/images/main.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Literal, Optional, Union +from typing import Any, Literal from typing_extensions import TypedDict @@ -12,15 +12,15 @@ class ImageEditOptionalRequestParams(TypedDict, total=False): Params here: https://platform.openai.com/docs/api-reference/images/createEdit """ - background: Optional[Literal["transparent", "opaque", "auto"]] - input_fidelity: Optional[Literal["high", "low"]] - mask: Optional[str] - n: Optional[int] - quality: Optional[Literal["high", "medium", "low", "standard", "auto"]] - response_format: Optional[Literal["url", "b64_json"]] - size: Optional[str] - user: Optional[str] - imageConfig: Optional[Dict[str, Any]] + background: Literal["transparent", "opaque", "auto"] | None + input_fidelity: Literal["high", "low"] | None + mask: str | None + n: int | None + quality: Literal["high", "medium", "low", "standard", "auto"] | None + response_format: Literal["url", "b64_json"] | None + size: str | None + user: str | None + imageConfig: dict[str, Any] | None class ImageEditRequestParams(ImageEditOptionalRequestParams, total=False): @@ -32,4 +32,4 @@ class ImageEditRequestParams(ImageEditOptionalRequestParams, total=False): image: FileTypes prompt: str - model: Optional[str] + model: str | None diff --git a/litellm/types/integrations/anthropic_cache_control_hook.py b/litellm/types/integrations/anthropic_cache_control_hook.py index 24373e80ed0..da9b26ebbd8 100644 --- a/litellm/types/integrations/anthropic_cache_control_hook.py +++ b/litellm/types/integrations/anthropic_cache_control_hook.py @@ -1,4 +1,4 @@ -from typing import Final, Literal, Optional, Union +from typing import Literal from typing_extensions import NotRequired, TypedDict @@ -9,9 +9,9 @@ class CacheControlMessageInjectionPoint(TypedDict): """Type for message-level injection points.""" location: Literal["message"] - role: Optional[Literal["user", "system", "assistant"]] # Optional: target by role (user, system, assistant) - index: Optional[Union[int, str]] # Optional: target by specific index - control: Optional[ChatCompletionCachedContent] + role: Literal["user", "system", "assistant"] | None # Optional: target by role (user, system, assistant) + index: int | str | None # Optional: target by specific index + control: ChatCompletionCachedContent | None _litellm_judged: NotRequired[bool] # Internal: written back by litellm once the client cache_control judgment ran @@ -19,11 +19,8 @@ class CacheControlToolConfigInjectionPoint(TypedDict): """Type for tool_config-level injection points (Bedrock).""" location: Literal["tool_config"] - control: Optional[ChatCompletionCachedContent] + control: ChatCompletionCachedContent | None _litellm_judged: NotRequired[bool] # Internal: written back by litellm once the client cache_control judgment ran -CacheControlInjectionPoint = Union[ - CacheControlMessageInjectionPoint, - CacheControlToolConfigInjectionPoint, -] +CacheControlInjectionPoint = CacheControlMessageInjectionPoint | CacheControlToolConfigInjectionPoint diff --git a/litellm/types/integrations/argilla.py b/litellm/types/integrations/argilla.py index 52dad347304..2c98486c7a7 100644 --- a/litellm/types/integrations/argilla.py +++ b/litellm/types/integrations/argilla.py @@ -1,17 +1,14 @@ -import os -from datetime import datetime as dt -from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional, Set +from typing import Any, Final from typing_extensions import TypedDict class ArgillaItem(TypedDict): - fields: Dict[str, Any] + fields: dict[str, Any] class ArgillaPayload(TypedDict): - items: List[ArgillaItem] + items: list[ArgillaItem] class ArgillaCredentialsObject(TypedDict): diff --git a/litellm/types/integrations/arize.py b/litellm/types/integrations/arize.py index 248fdac3b3a..7ed7b79e8d1 100644 --- a/litellm/types/integrations/arize.py +++ b/litellm/types/integrations/arize.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Any, Literal, Optional +from typing import TYPE_CHECKING, Any, Literal from pydantic import BaseModel @@ -9,9 +9,9 @@ else: class ArizeConfig(BaseModel): - space_id: Optional[str] = None - space_key: Optional[str] = None - api_key: Optional[str] = None + space_id: str | None = None + space_key: str | None = None + api_key: str | None = None protocol: Protocol endpoint: str - project_name: Optional[str] = None + project_name: str | None = None diff --git a/litellm/types/integrations/arize_phoenix.py b/litellm/types/integrations/arize_phoenix.py index a5da31f56c3..ae91c9945b9 100644 --- a/litellm/types/integrations/arize_phoenix.py +++ b/litellm/types/integrations/arize_phoenix.py @@ -1,12 +1,10 @@ -from typing import TYPE_CHECKING, Literal, Optional - from pydantic import BaseModel from .arize import Protocol class ArizePhoenixConfig(BaseModel): - otlp_auth_headers: Optional[str] = None + otlp_auth_headers: str | None = None protocol: Protocol endpoint: str - project_name: Optional[str] = None + project_name: str | None = None diff --git a/litellm/types/integrations/azure_sentinel.py b/litellm/types/integrations/azure_sentinel.py index 8460c7c0bee..c7e04ded2bf 100644 --- a/litellm/types/integrations/azure_sentinel.py +++ b/litellm/types/integrations/azure_sentinel.py @@ -1,5 +1,3 @@ -from typing import Optional - from litellm.types.integrations.custom_logger import StandardCustomLoggerInitParams @@ -7,5 +5,3 @@ class AzureSentinelInitParams(StandardCustomLoggerInitParams): """ Params for initializing an Azure Sentinel logger on litellm """ - - pass diff --git a/litellm/types/integrations/base_health_check.py b/litellm/types/integrations/base_health_check.py index 2443564dcd2..f5b2f97c548 100644 --- a/litellm/types/integrations/base_health_check.py +++ b/litellm/types/integrations/base_health_check.py @@ -1,8 +1,8 @@ -from typing import Literal, Optional +from typing import Literal from typing_extensions import TypedDict class IntegrationHealthCheckStatus(TypedDict): status: Literal["healthy", "unhealthy"] - error_message: Optional[str] + error_message: str | None diff --git a/litellm/types/integrations/cloudzero.py b/litellm/types/integrations/cloudzero.py index d8d17d857eb..988d501600f 100644 --- a/litellm/types/integrations/cloudzero.py +++ b/litellm/types/integrations/cloudzero.py @@ -1,7 +1,7 @@ -from typing import Any, Dict, Final +from typing import Any -class CBFRecord(Dict[str, Any]): +class CBFRecord(dict[str, Any]): """CloudZero Billing Format (CBF) record structure. This class represents a CBF record that is created from LiteLLM usage data @@ -29,8 +29,6 @@ class CBFRecord(Dict[str, Any]): - resource/tag:{key}: Various resource tags for dimensions and metrics (Optional[str]) """ - pass - # Type alias for better readability in function signatures -CBFRecordDict = Dict[str, Any] +CBFRecordDict = dict[str, Any] diff --git a/litellm/types/integrations/code_interpreter_interception.py b/litellm/types/integrations/code_interpreter_interception.py index 2669c59db37..50a808781ae 100644 --- a/litellm/types/integrations/code_interpreter_interception.py +++ b/litellm/types/integrations/code_interpreter_interception.py @@ -2,7 +2,7 @@ Type definitions for Code Interpreter Interception integration. """ -from typing import List, TypedDict +from typing import TypedDict class CodeInterpreterInterceptionConfig(TypedDict, total=False): @@ -18,5 +18,5 @@ class CodeInterpreterInterceptionConfig(TypedDict, total=False): """ enabled: bool - enabled_providers: List[str] + enabled_providers: list[str] sandbox_tool_name: str diff --git a/litellm/types/integrations/compression_interception.py b/litellm/types/integrations/compression_interception.py index 1466e9b693c..a1e66e5057e 100644 --- a/litellm/types/integrations/compression_interception.py +++ b/litellm/types/integrations/compression_interception.py @@ -2,7 +2,7 @@ Type definitions for Compression Interception integration. """ -from typing import Any, Dict, Literal, Optional, TypedDict +from typing import Any, Literal, TypedDict class CompressionInterceptionConfig(TypedDict, total=False): @@ -22,9 +22,9 @@ class CompressionInterceptionConfig(TypedDict, total=False): enabled: bool compression_trigger: int - compression_target: Optional[int] - embedding_model: Optional[str] - embedding_model_params: Optional[Dict[str, Any]] + compression_target: int | None + embedding_model: str | None + embedding_model_params: dict[str, Any] | None class CompressionSavingsMetadata(TypedDict): diff --git a/litellm/types/integrations/custom_logger.py b/litellm/types/integrations/custom_logger.py index 977479f78bb..89b85bc5114 100644 --- a/litellm/types/integrations/custom_logger.py +++ b/litellm/types/integrations/custom_logger.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Final, List, Optional +from typing import Any, Final from pydantic import BaseModel, Field @@ -28,7 +28,7 @@ class StandardCustomLoggerInitParams(BaseModel): Params for initializing a CustomLogger. """ - turn_off_message_logging: Optional[bool] = False + turn_off_message_logging: bool | None = False class AgenticLoopRequestPatch(BaseModel): @@ -36,12 +36,12 @@ class AgenticLoopRequestPatch(BaseModel): Patch returned by callbacks to request a follow-up LLM call. """ - model: Optional[str] = None - messages: Optional[List[Dict[str, Any]]] = None - tools: Optional[List[Dict[str, Any]]] = None - max_tokens: Optional[int] = None - optional_params: Dict[str, Any] = Field(default_factory=dict) - kwargs: Dict[str, Any] = Field(default_factory=dict) + model: str | None = None + messages: list[dict[str, Any]] | None = None + tools: list[dict[str, Any]] | None = None + max_tokens: int | None = None + optional_params: dict[str, Any] = Field(default_factory=dict) + kwargs: dict[str, Any] = Field(default_factory=dict) class AgenticLoopPlan(BaseModel): @@ -50,8 +50,8 @@ class AgenticLoopPlan(BaseModel): """ run_agentic_loop: bool = False - request_patch: Optional[AgenticLoopRequestPatch] = None - response_override: Optional[Any] = None + request_patch: AgenticLoopRequestPatch | None = None + response_override: Any | None = None terminate: bool = False - stop_reason: Optional[str] = None - metadata: Dict[str, Any] = Field(default_factory=dict) + stop_reason: str | None = None + metadata: dict[str, Any] = Field(default_factory=dict) diff --git a/litellm/types/integrations/datadog.py b/litellm/types/integrations/datadog.py index 2417908534a..718ef3dd36f 100644 --- a/litellm/types/integrations/datadog.py +++ b/litellm/types/integrations/datadog.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Final, Optional +from typing import Final from typing_extensions import NotRequired, TypedDict @@ -40,12 +40,10 @@ class DatadogInitParams(StandardCustomLoggerInitParams): Params for initializing a DataDog logger on litellm """ - pass - class DatadogProxyFailureHookJsonMessage(TypedDict, total=False): exception: str error_class: str - status_code: Optional[int] + status_code: int | None traceback: str user_api_key_dict: dict diff --git a/litellm/types/integrations/datadog_cost_management.py b/litellm/types/integrations/datadog_cost_management.py index 08744d2f52e..9d8258c3d25 100644 --- a/litellm/types/integrations/datadog_cost_management.py +++ b/litellm/types/integrations/datadog_cost_management.py @@ -1,5 +1,4 @@ -from typing import Dict, List, Optional, TypedDict - +from typing import TypedDict from litellm.types.integrations.custom_logger import StandardCustomLoggerInitParams @@ -9,7 +8,7 @@ class DatadogCostManagementInitParams(StandardCustomLoggerInitParams): Init params for Datadog Cost Management """ - cost_tag_keys: Optional[List[str]] = None + cost_tag_keys: list[str] | None = None class DatadogFOCUSCostEntry(TypedDict): @@ -24,4 +23,4 @@ class DatadogFOCUSCostEntry(TypedDict): ChargePeriodEnd: str BilledCost: float BillingCurrency: str - Tags: Optional[Dict[str, str]] + Tags: dict[str, str] | None diff --git a/litellm/types/integrations/datadog_llm_obs.py b/litellm/types/integrations/datadog_llm_obs.py index 4ea5ed66b87..7853dda1213 100644 --- a/litellm/types/integrations/datadog_llm_obs.py +++ b/litellm/types/integrations/datadog_llm_obs.py @@ -4,7 +4,7 @@ Payloads for Datadog LLM Observability Service (LLMObs) API Reference: https://docs.datadoghq.com/llm_observability/setup/api/?tab=example#api-standards """ -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Literal from typing_extensions import TypedDict @@ -12,21 +12,21 @@ from litellm.types.integrations.custom_logger import StandardCustomLoggerInitPar class InputMeta(TypedDict): - messages: List[ - Dict[str, Any] # changed to fit with tool calls + messages: list[ + dict[str, Any] # changed to fit with tool calls ] # Relevant Issue: https://github.com/BerriAI/litellm/issues/9494 class OutputMeta(TypedDict): - messages: List[Any] + messages: list[Any] class DDLLMObsError(TypedDict, total=False): """Error information on the span according to DD LLM Obs API spec""" message: str # The error message - stack: Optional[str] # The stack trace - type: Optional[str] # The error type + stack: str | None # The stack trace + type: str | None # The error type class Meta(TypedDict, total=False): @@ -34,8 +34,8 @@ class Meta(TypedDict, total=False): kind: Literal["llm", "tool", "task", "embedding", "retrieval"] input: InputMeta # The span's input information. output: OutputMeta # The span's output information. - metadata: Dict[str, Any] - error: Optional[DDLLMObsError] # Error information on the span + metadata: dict[str, Any] + error: DDLLMObsError | None # Error information on the span class LLMMetrics(TypedDict, total=False): @@ -57,14 +57,14 @@ class LLMObsPayload(TypedDict, total=False): start_ns: int duration: int metrics: LLMMetrics - tags: List + tags: list status: Literal["ok", "error"] # Error status ("ok" or "error"). Defaults to "ok". class DDSpanAttributes(TypedDict): ml_app: str - tags: List[str] - spans: List[LLMObsPayload] + tags: list[str] + spans: list[LLMObsPayload] class DDIntakePayload(TypedDict): @@ -77,8 +77,6 @@ class DatadogLLMObsInitParams(StandardCustomLoggerInitParams): Params for initializing a DatadogLLMObs logger on litellm """ - pass - class DDLLMObsLatencyMetrics(TypedDict, total=False): time_to_first_token_ms: float diff --git a/litellm/types/integrations/datadog_metrics.py b/litellm/types/integrations/datadog_metrics.py index 4c980cdee6d..c294fdd2522 100644 --- a/litellm/types/integrations/datadog_metrics.py +++ b/litellm/types/integrations/datadog_metrics.py @@ -1,5 +1,3 @@ -from typing import List, Optional - from typing_extensions import TypedDict @@ -11,10 +9,10 @@ class DatadogMetricPoint(TypedDict): class DatadogMetricSeries(TypedDict, total=False): metric: str type: int # 0=unspecified, 1=count, 2=rate, 3=gauge - points: List[DatadogMetricPoint] - tags: List[str] - interval: Optional[int] # Required for count (type=1) and rate (type=2) metrics + points: list[DatadogMetricPoint] + tags: list[str] + interval: int | None # Required for count (type=1) and rate (type=2) metrics class DatadogMetricsPayload(TypedDict): - series: List[DatadogMetricSeries] + series: list[DatadogMetricSeries] diff --git a/litellm/types/integrations/gcs_bucket.py b/litellm/types/integrations/gcs_bucket.py index 306e569dc5c..3840d7681a5 100644 --- a/litellm/types/integrations/gcs_bucket.py +++ b/litellm/types/integrations/gcs_bucket.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Final, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, Final from typing_extensions import TypedDict @@ -22,7 +22,7 @@ class GCSLoggingConfig(TypedDict): bucket_name: str vertex_instance: VertexBase - path_service_account: Optional[str] + path_service_account: str | None class GCSLogQueueItem(TypedDict): @@ -31,5 +31,5 @@ class GCSLogQueueItem(TypedDict): """ payload: StandardLoggingPayload - kwargs: Dict[str, Any] - response_obj: Optional[Any] + kwargs: dict[str, Any] + response_obj: Any | None diff --git a/litellm/types/integrations/langfuse.py b/litellm/types/integrations/langfuse.py index a13868e503c..066cd760d74 100644 --- a/litellm/types/integrations/langfuse.py +++ b/litellm/types/integrations/langfuse.py @@ -1,17 +1,15 @@ -from typing import Optional - from typing_extensions import TypedDict class LangfuseLoggingConfig(TypedDict): - langfuse_secret: Optional[str] - langfuse_public_key: Optional[str] - langfuse_host: Optional[str] + langfuse_secret: str | None + langfuse_public_key: str | None + langfuse_host: str | None class LangfuseUsageDetails(TypedDict): - input: Optional[int] - output: Optional[int] - total: Optional[int] - cache_creation_input_tokens: Optional[int] - cache_read_input_tokens: Optional[int] + input: int | None + output: int | None + total: int | None + cache_creation_input_tokens: int | None + cache_read_input_tokens: int | None diff --git a/litellm/types/integrations/langfuse_otel.py b/litellm/types/integrations/langfuse_otel.py index 17b5a78edf4..9ef48bdcdd0 100644 --- a/litellm/types/integrations/langfuse_otel.py +++ b/litellm/types/integrations/langfuse_otel.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import TYPE_CHECKING, Any, Literal, Optional +from typing import TYPE_CHECKING, Any, Literal from pydantic import BaseModel @@ -10,7 +10,7 @@ else: class LangfuseOtelConfig(BaseModel): - otlp_auth_headers: Optional[str] = None + otlp_auth_headers: str | None = None protocol: Protocol = "otlp_http" diff --git a/litellm/types/integrations/langsmith.py b/litellm/types/integrations/langsmith.py index 9c026a117fd..17fadfec54d 100644 --- a/litellm/types/integrations/langsmith.py +++ b/litellm/types/integrations/langsmith.py @@ -1,37 +1,37 @@ from dataclasses import dataclass from datetime import datetime -from typing import Any, Dict, List, NamedTuple, Optional +from typing import Any, NamedTuple from pydantic import BaseModel from typing_extensions import TypedDict class LangsmithInputs(BaseModel): - model: Optional[str] = None - messages: Optional[List[Any]] = None - stream: Optional[bool] = None - call_type: Optional[str] = None - litellm_call_id: Optional[str] = None - completion_start_time: Optional[datetime] = None - temperature: Optional[float] = None - max_tokens: Optional[int] = None - custom_llm_provider: Optional[str] = None - input: Optional[List[Any]] = None - log_event_type: Optional[str] = None - original_response: Optional[Any] = None - response_cost: Optional[float] = None + model: str | None = None + messages: list[Any] | None = None + stream: bool | None = None + call_type: str | None = None + litellm_call_id: str | None = None + completion_start_time: datetime | None = None + temperature: float | None = None + max_tokens: int | None = None + custom_llm_provider: str | None = None + input: list[Any] | None = None + log_event_type: str | None = None + original_response: Any | None = None + response_cost: float | None = None # LiteLLM Virtual Key specific fields - user_api_key: Optional[str] = None - user_api_key_user_id: Optional[str] = None - user_api_key_team_alias: Optional[str] = None + user_api_key: str | None = None + user_api_key_user_id: str | None = None + user_api_key_team_alias: str | None = None class LangsmithCredentialsObject(TypedDict): - LANGSMITH_API_KEY: Optional[str] - LANGSMITH_PROJECT: Optional[str] + LANGSMITH_API_KEY: str | None + LANGSMITH_PROJECT: str | None LANGSMITH_BASE_URL: str - LANGSMITH_TENANT_ID: Optional[str] + LANGSMITH_TENANT_ID: str | None class LangsmithQueueObject(TypedDict): @@ -43,7 +43,7 @@ class LangsmithQueueObject(TypedDict): - credentials[LangsmithCredentialsObject] - credentials to use for logging to langsmith """ - data: Dict + data: dict credentials: LangsmithCredentialsObject @@ -53,7 +53,7 @@ class CredentialsKey(NamedTuple): api_key: str project: str base_url: str - tenant_id: Optional[str] + tenant_id: str | None @dataclass @@ -61,4 +61,4 @@ class BatchGroup: """Groups credentials with their associated queue objects""" credentials: LangsmithCredentialsObject - queue_objects: List[LangsmithQueueObject] + queue_objects: list[LangsmithQueueObject] diff --git a/litellm/types/integrations/newrelic.py b/litellm/types/integrations/newrelic.py index 2de9769b181..96d9a201ad7 100644 --- a/litellm/types/integrations/newrelic.py +++ b/litellm/types/integrations/newrelic.py @@ -5,5 +5,3 @@ class NewRelicInitParams(StandardCustomLoggerInitParams): """ Params for initializing a New Relic logger on litellm """ - - pass diff --git a/litellm/types/integrations/pagerduty.py b/litellm/types/integrations/pagerduty.py index c41a591728c..c1fad61b7da 100644 --- a/litellm/types/integrations/pagerduty.py +++ b/litellm/types/integrations/pagerduty.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import List, Literal, Optional, Union +from typing import Literal from typing_extensions import TypedDict @@ -8,35 +8,35 @@ from litellm.types.utils import StandardLoggingUserAPIKeyMetadata class LinkDict(TypedDict, total=False): href: str - text: Optional[str] + text: str | None class ImageDict(TypedDict, total=False): src: str - href: Optional[str] - alt: Optional[str] + href: str | None + alt: str | None class PagerDutyPayload(TypedDict, total=False): summary: str - timestamp: Optional[str] # ISO 8601 date-time format + timestamp: str | None # ISO 8601 date-time format severity: Literal["critical", "warning", "error", "info"] source: str - component: Optional[str] - group: Optional[str] - class_: Optional[str] # Using class_ since 'class' is a reserved keyword - custom_details: Optional[dict] + component: str | None + group: str | None + class_: str | None # Using class_ since 'class' is a reserved keyword + custom_details: dict | None class PagerDutyRequestBody(TypedDict, total=False): payload: PagerDutyPayload routing_key: str event_action: Literal["trigger", "acknowledge", "resolve"] - dedup_key: Optional[str] - client: Optional[str] - client_url: Optional[str] - links: Optional[List[LinkDict]] - images: Optional[List[ImageDict]] + dedup_key: str | None + client: str | None + client_url: str | None + links: list[LinkDict] | None + images: list[ImageDict] | None class AlertingConfig(TypedDict, total=False): @@ -61,6 +61,6 @@ class PagerDutyInternalEvent(StandardLoggingUserAPIKeyMetadata, total=False): failure_event_type: Literal["failed_response", "hanging_response"] timestamp: datetime - error_class: Optional[str] - error_code: Optional[str] - error_llm_provider: Optional[str] + error_class: str | None + error_code: str | None + error_llm_provider: str | None diff --git a/litellm/types/integrations/posthog.py b/litellm/types/integrations/posthog.py index 80a31fb4e98..ac04d08107d 100644 --- a/litellm/types/integrations/posthog.py +++ b/litellm/types/integrations/posthog.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Final, TypedDict +from typing import Any, Final, TypedDict POSTHOG_MAX_BATCH_SIZE: Final = 100 @@ -7,7 +7,7 @@ class PostHogEventPayload(TypedDict): """PostHog event payload structure""" event: str # "$ai_generation" or "$ai_embedding" - properties: Dict[str, Any] + properties: dict[str, Any] distinct_id: str diff --git a/litellm/types/integrations/prometheus.py b/litellm/types/integrations/prometheus.py index 6e6506a6702..2d453aac009 100644 --- a/litellm/types/integrations/prometheus.py +++ b/litellm/types/integrations/prometheus.py @@ -1,8 +1,9 @@ import re +from collections.abc import Mapping from dataclasses import MISSING, dataclass, field, fields from enum import Enum from types import MappingProxyType -from typing import Any, ClassVar, Dict, Final, List, Literal, Mapping, Optional, Tuple, Union +from typing import Any, ClassVar, Final, Literal import litellm @@ -43,7 +44,7 @@ def _sanitize_prometheus_label_name(label: str) -> str: _PROMETHEUS_LABEL_VALUE_TRANSLATE_V1: Final = str.maketrans("\n", " ", "\r\u2028\u2029") -def _sanitize_prometheus_label_value(value: Optional[Any]) -> Optional[str]: +def _sanitize_prometheus_label_value(value: Any | None) -> str | None: """ Same semantics as :func:`_sanitize_prometheus_label_value`, implemented with ``str.translate`` plus a single escape pass instead of chained ``replace``. @@ -57,7 +58,7 @@ def _sanitize_prometheus_label_value(value: Optional[Any]) -> Optional[str]: if "\\" not in cleaned and '"' not in cleaned: return cleaned - parts: Final[List[str]] = [] + parts: Final[list[str]] = [] append: Final = parts.append for ch in cleaned: if ch == "\\": @@ -74,7 +75,7 @@ class MetricValidationError: """Error for invalid metric name""" metric_name: str - valid_metrics: Tuple[str, ...] + valid_metrics: tuple[str, ...] @property def message(self) -> str: @@ -86,8 +87,8 @@ class LabelValidationError: """Error for invalid labels on a metric""" metric_name: str - invalid_labels: List[str] - valid_labels: List[str] + invalid_labels: list[str] + valid_labels: list[str] @property def message(self) -> str: @@ -98,15 +99,15 @@ class LabelValidationError: class ValidationResults: """Container for all validation results""" - metric_errors: List[MetricValidationError] - label_errors: List[LabelValidationError] + metric_errors: list[MetricValidationError] + label_errors: list[LabelValidationError] @property def has_errors(self) -> bool: return bool(self.metric_errors or self.label_errors) @property - def all_error_messages(self) -> List[str]: + def all_error_messages(self) -> list[str]: messages: Final = [error.message for error in self.metric_errors] messages.extend([error.message for error in self.label_errors]) return messages @@ -333,9 +334,9 @@ class PrometheusMetricLabels: # Guardrail metrics - these use custom labels (guardrail_name, status, error_type, hook_type) # which are not part of UserAPIKeyLabelNames - litellm_guardrail_latency_seconds: List[str] = [] - litellm_guardrail_errors_total: List[str] = [] - litellm_guardrail_requests_total: List[str] = [] + litellm_guardrail_latency_seconds: list[str] = [] + litellm_guardrail_errors_total: list[str] = [] + litellm_guardrail_requests_total: list[str] = [] litellm_proxy_total_requests_metric = [ UserAPIKeyLabelNames.END_USER.value, @@ -681,15 +682,15 @@ class PrometheusMetricLabels: ] # Buffer monitoring metrics - these typically don't need additional labels - litellm_pod_lock_manager_size: List[str] = [] + litellm_pod_lock_manager_size: list[str] = [] - litellm_in_memory_daily_spend_update_queue_size: List[str] = [] + litellm_in_memory_daily_spend_update_queue_size: list[str] = [] - litellm_redis_daily_spend_update_queue_size: List[str] = [] + litellm_redis_daily_spend_update_queue_size: list[str] = [] - litellm_in_memory_spend_update_queue_size: List[str] = [] + litellm_in_memory_spend_update_queue_size: list[str] = [] - litellm_redis_spend_update_queue_size: List[str] = [] + litellm_redis_spend_update_queue_size: list[str] = [] # Cache metrics - track cache hits, misses, and tokens served from cache _cache_metric_labels = [ @@ -742,7 +743,7 @@ class PrometheusMetricLabels: litellm_managed_batch_created_total = _batch_user_labels - litellm_managed_file_size_bytes: List[str] = [] # labels: purpose, file_type, model, api_provider, user (custom) + litellm_managed_file_size_bytes: list[str] = [] # labels: purpose, file_type, model, api_provider, user (custom) litellm_managed_batch_duration_seconds = [ UserAPIKeyLabelNames.v1_LITELLM_MODEL_NAME.value, @@ -751,18 +752,18 @@ class PrometheusMetricLabels: litellm_managed_file_created_total = _batch_user_labels - litellm_managed_file_deleted_total: List[str] = [] # only "result" label, added at metric creation + litellm_managed_file_deleted_total: list[str] = [] # only "result" label, added at metric creation - litellm_check_batch_cost_jobs_polled: List[str] = [] + litellm_check_batch_cost_jobs_polled: list[str] = [] litellm_check_batch_cost_jobs_processed_total = [ UserAPIKeyLabelNames.v1_LITELLM_MODEL_NAME.value, UserAPIKeyLabelNames.API_PROVIDER.value, ] - litellm_check_batch_cost_errors_total: List[str] = [] # label: error_type (custom) + litellm_check_batch_cost_errors_total: list[str] = [] # label: error_type (custom) - litellm_check_batch_cost_last_run_timestamp: List[str] = [] + litellm_check_batch_cost_last_run_timestamp: list[str] = [] # MCP tool call metrics litellm_mcp_tool_calls_total: list[str] = [ @@ -779,7 +780,7 @@ class PrometheusMetricLabels: litellm_mcp_tool_call_spend_metric: list[str] = list(litellm_mcp_tool_calls_total) @staticmethod - def get_labels(label_name: DEFINED_PROMETHEUS_METRICS) -> List[str]: + def get_labels(label_name: DEFINED_PROMETHEUS_METRICS) -> list[str]: default_labels: Final = getattr(PrometheusMetricLabels, label_name) custom_labels: Final = [] @@ -836,7 +837,7 @@ class PrometheusMetricLabels: return default_labels + custom_labels -_USER_API_KEY_LABEL_VALUE_INIT_ALIASES: Final[Dict[str, str]] = { +_USER_API_KEY_LABEL_VALUE_INIT_ALIASES: Final[dict[str, str]] = { # Some tests / call sites use ``api_key_hash``; Prometheus field is ``hashed_api_key``. "api_key_hash": "hashed_api_key", } @@ -851,39 +852,39 @@ class UserAPIKeyLabelValues: ``model_dump()`` is provided for call sites that still expect a Pydantic-like dict. """ - end_user: Optional[str] = None - user: Optional[str] = None - user_email: Optional[str] = None - user_alias: Optional[str] = None - hashed_api_key: Optional[str] = None - api_key_alias: Optional[str] = None - team: Optional[str] = None - team_alias: Optional[str] = None - model_group: Optional[str] = None - requested_model: Optional[str] = None - model: Optional[str] = None - litellm_model_name: Optional[str] = None + end_user: str | None = None + user: str | None = None + user_email: str | None = None + user_alias: str | None = None + hashed_api_key: str | None = None + api_key_alias: str | None = None + team: str | None = None + team_alias: str | None = None + model_group: str | None = None + requested_model: str | None = None + model: str | None = None + litellm_model_name: str | None = None # Accept list/tuple at construction time; normalize to tuple in __post_init__. - tags: Union[Tuple[str, ...], List[str]] = () + tags: tuple[str, ...] | list[str] = () custom_metadata_labels: Mapping[str, str] = field(default_factory=dict) - model_id: Optional[str] = None - api_base: Optional[str] = None - api_provider: Optional[str] = None - exception_status: Optional[str] = None - exception_class: Optional[str] = None - rate_limit_category: Optional[str] = None - rate_limit_type: Optional[str] = None - status_code: Optional[str] = None - fallback_model: Optional[str] = None - route: Optional[str] = None - client_ip: Optional[str] = None - user_agent: Optional[str] = None - stream: Optional[str] = None - org_id: Optional[str] = None - org_alias: Optional[str] = None - mcp_tool_name: Optional[str] = None - mcp_server_name: Optional[str] = None - service_tier: Optional[str] = None + model_id: str | None = None + api_base: str | None = None + api_provider: str | None = None + exception_status: str | None = None + exception_class: str | None = None + rate_limit_category: str | None = None + rate_limit_type: str | None = None + status_code: str | None = None + fallback_model: str | None = None + route: str | None = None + client_ip: str | None = None + user_agent: str | None = None + stream: str | None = None + org_id: str | None = None + org_alias: str | None = None + mcp_tool_name: str | None = None + mcp_server_name: str | None = None + service_tier: str | None = None # Added for test compatibility. def __init__(self, **kwargs: Any) -> None: @@ -892,7 +893,7 @@ class UserAPIKeyLabelValues: ``hashed_api_key``. This supports ``**standard_logging_payload`` in tests. """ field_names: Final = {f.name for f in fields(self)} - merged: Final[Dict[str, Any]] = {} + merged: Final[dict[str, Any]] = {} for f in fields(self): if f.default_factory is not MISSING: merged[f.name] = f.default_factory() @@ -929,9 +930,9 @@ class UserAPIKeyLabelValues: # stays cheap. (Dataclass default `str()` delegates to `__repr__`.) return "" - def model_dump(self) -> Dict[str, Any]: + def model_dump(self) -> dict[str, Any]: """Same shape as the former Pydantic ``model_dump()`` (plain dict, list tags).""" - d: Final[Dict[str, Any]] = {f.name: getattr(self, f.name) for f in fields(self)} + d: Final[dict[str, Any]] = {f.name: getattr(self, f.name) for f in fields(self)} d["tags"] = list(self.tags) d["custom_metadata_labels"] = dict(self.custom_metadata_labels) return d @@ -942,31 +943,31 @@ class PrometheusMetricsConfig: """Configuration for filtering Prometheus metrics (parsed once from proxy config).""" group: str - metrics: List[str] - include_labels: Optional[List[str]] = None + metrics: list[str] + include_labels: list[str] | None = None @dataclass class PrometheusSettings: """Settings for Prometheus metrics configuration.""" - prometheus_metrics_config: Optional[List[PrometheusMetricsConfig]] = None + prometheus_metrics_config: list[PrometheusMetricsConfig] | None = None class NoOpMetric: """A no-op metric that has the same interface as prometheus metrics but does nothing""" - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: pass def labels(self, *args, **kwargs): return self - def inc(self, *args, **kwargs): + def inc(self, *args, **kwargs) -> None: pass - def set(self, *args, **kwargs): + def set(self, *args, **kwargs) -> None: pass - def observe(self, *args, **kwargs): + def observe(self, *args, **kwargs) -> None: pass diff --git a/litellm/types/integrations/rag/bedrock_knowledgebase.py b/litellm/types/integrations/rag/bedrock_knowledgebase.py index db01cb9ae12..e3aba85ed9b 100644 --- a/litellm/types/integrations/rag/bedrock_knowledgebase.py +++ b/litellm/types/integrations/rag/bedrock_knowledgebase.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Literal, Optional, Union +from typing import Any, Literal from typing_extensions import TypedDict @@ -7,14 +7,14 @@ class BedrockKBLocation(TypedDict, total=False): """Location information for a retrieved document.""" type: str - s3Location: Optional[dict] - webLocation: Optional[dict] - kendraDocumentLocation: Optional[dict] - salesforceLocation: Optional[dict] - sharePointLocation: Optional[dict] - confluenceLocation: Optional[dict] - customDocumentLocation: Optional[dict] - sqlLocation: Optional[dict] + s3Location: dict | None + webLocation: dict | None + kendraDocumentLocation: dict | None + salesforceLocation: dict | None + sharePointLocation: dict | None + confluenceLocation: dict | None + customDocumentLocation: dict | None + sqlLocation: dict | None class BedrockKBRowValue(TypedDict): @@ -29,26 +29,26 @@ class BedrockKBContent(TypedDict, total=False): """Content of a retrieved document.""" type: str - text: Optional[str] - byteContent: Optional[str] - row: Optional[List[BedrockKBRowValue]] + text: str | None + byteContent: str | None + row: list[BedrockKBRowValue] | None class BedrockKBRetrievalResult(TypedDict, total=False): """Individual result from a knowledge base retrieval.""" - content: Optional[BedrockKBContent] - location: Optional[BedrockKBLocation] - score: Optional[float] - metadata: Optional[Dict[str, Any]] + content: BedrockKBContent | None + location: BedrockKBLocation | None + score: float | None + metadata: dict[str, Any] | None class BedrockKBResponse(TypedDict, total=False): """Response from a Bedrock Knowledge Base retrieval request.""" - guardrailAction: Optional[Literal["INTERVENED", "NONE"]] - nextToken: Optional[str] - retrievalResults: Optional[List[BedrockKBRetrievalResult]] + guardrailAction: Literal["INTERVENED", "NONE"] | None + nextToken: str | None + retrievalResults: list[BedrockKBRetrievalResult] | None ################ Bedrock Knowledge Base Request Types ################# @@ -59,80 +59,80 @@ class BedrockKBResponse(TypedDict, total=False): class BedrockKBMetadataAttribute(TypedDict, total=False): """Metadata attribute configuration for implicit filtering.""" - description: Optional[str] - key: Optional[str] - type: Optional[str] + description: str | None + key: str | None + type: str | None class BedrockKBImplicitFilterConfiguration(TypedDict, total=False): """Configuration for implicit filtering.""" - metadataAttributes: Optional[List[BedrockKBMetadataAttribute]] - modelArn: Optional[str] + metadataAttributes: list[BedrockKBMetadataAttribute] | None + modelArn: str | None class BedrockKBSelectiveModeConfiguration(TypedDict, total=False): """Configuration for selective mode in reranking.""" - pass # This can be expanded based on actual requirements + # This can be expanded based on actual requirements class BedrockKBMetadataConfiguration(TypedDict, total=False): """Metadata configuration for reranking.""" - selectionMode: Optional[str] - selectiveModeConfiguration: Optional[BedrockKBSelectiveModeConfiguration] + selectionMode: str | None + selectiveModeConfiguration: BedrockKBSelectiveModeConfiguration | None class BedrockKBModelConfiguration(TypedDict, total=False): """Model configuration for reranking.""" - additionalModelRequestFields: Optional[Dict[str, Any]] - modelArn: Optional[str] + additionalModelRequestFields: dict[str, Any] | None + modelArn: str | None class BedrockKBRerankingConfiguration(TypedDict, total=False): """Configuration for reranking in vector search.""" - bedrockRerankingConfiguration: Optional[Dict[str, Any]] # This could be further typed if needed - type: Optional[str] + bedrockRerankingConfiguration: dict[str, Any] | None # This could be further typed if needed + type: str | None class BedrockKBVectorSearchConfiguration(TypedDict, total=False): """Configuration for vector search.""" - filter: Optional[Dict[str, Any]] - implicitFilterConfiguration: Optional[BedrockKBImplicitFilterConfiguration] - numberOfResults: Optional[int] - overrideSearchType: Optional[str] - rerankingConfiguration: Optional[BedrockKBRerankingConfiguration] + filter: dict[str, Any] | None + implicitFilterConfiguration: BedrockKBImplicitFilterConfiguration | None + numberOfResults: int | None + overrideSearchType: str | None + rerankingConfiguration: BedrockKBRerankingConfiguration | None class BedrockKBRetrievalConfiguration(TypedDict, total=False): """Configuration for retrieval.""" - vectorSearchConfiguration: Optional[BedrockKBVectorSearchConfiguration] + vectorSearchConfiguration: BedrockKBVectorSearchConfiguration | None class BedrockKBRetrievalQuery(TypedDict, total=False): """Query structure for retrieval.""" - text: Optional[str] + text: str | None class BedrockKBGuardrailConfiguration(TypedDict, total=False): """Configuration for guardrails.""" - guardrailId: Optional[str] - guardrailVersion: Optional[str] + guardrailId: str | None + guardrailVersion: str | None class BedrockKBRequest(TypedDict, total=False): """Complete request structure for Bedrock Knowledge Base retrieval.""" - guardrailConfiguration: Optional[BedrockKBGuardrailConfiguration] - nextToken: Optional[str] - retrievalConfiguration: Optional[BedrockKBRetrievalConfiguration] + guardrailConfiguration: BedrockKBGuardrailConfiguration | None + nextToken: str | None + retrievalConfiguration: BedrockKBRetrievalConfiguration | None retrievalQuery: BedrockKBRetrievalQuery diff --git a/litellm/types/integrations/s3_v2.py b/litellm/types/integrations/s3_v2.py index 43b917e6200..32864bf5b8c 100644 --- a/litellm/types/integrations/s3_v2.py +++ b/litellm/types/integrations/s3_v2.py @@ -1,5 +1,3 @@ -from typing import Dict - from pydantic import BaseModel @@ -8,6 +6,6 @@ class s3BatchLoggingElement(BaseModel): Type of element stored in self.log_queue in S3Logger """ - payload: Dict + payload: dict s3_object_key: str s3_object_download_filename: str diff --git a/litellm/types/integrations/slack_alerting.py b/litellm/types/integrations/slack_alerting.py index d8c0853d38f..a96e70ff496 100644 --- a/litellm/types/integrations/slack_alerting.py +++ b/litellm/types/integrations/slack_alerting.py @@ -2,7 +2,7 @@ import os import time from datetime import datetime as dt from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional, Set, Union +from typing import Any, Final, Literal, Optional, Union from pydantic import BaseModel, Field from typing_extensions import TypedDict @@ -18,7 +18,7 @@ HANGING_ALERT_BUFFER_TIME_SECONDS: Final = 60 class BaseOutageModel(TypedDict): - alerts: List[int] + alerts: list[int] minor_alert_sent: bool major_alert_sent: bool last_updated_at: float @@ -30,7 +30,7 @@ class OutageModel(BaseOutageModel): class ProviderRegionOutageModel(BaseOutageModel): provider_region_id: str - deployment_ids: Set[str] + deployment_ids: set[str] # we use this for the email header, please send a test email if you change this. verify it looks good on email @@ -106,7 +106,7 @@ class DeploymentMetrics(LiteLLMPydanticObjectBase): failed_request: bool """did it fail the request?""" - latency_per_output_token: Optional[float] + latency_per_output_token: float | None """latency/output token of deployment""" updated_at: dt @@ -171,7 +171,7 @@ class AlertType(str, Enum): internal_user_deleted = "internal_user_deleted" -DEFAULT_ALERT_TYPES: Final[List[AlertType]] = [ +DEFAULT_ALERT_TYPES: Final[list[AlertType]] = [ # LLM related alerts AlertType.llm_exceptions, AlertType.llm_too_slow, @@ -198,10 +198,10 @@ DEFAULT_ALERT_TYPES: Final[List[AlertType]] = [ class HangingRequestData(BaseModel): request_id: str model: str - api_base: Optional[str] = None - key_alias: Optional[str] = None - team_alias: Optional[str] = None - alerting_metadata: Optional[dict] = None + api_base: str | None = None + key_alias: str | None = None + team_alias: str | None = None + alerting_metadata: dict | None = None created_at: float = Field(default_factory=time.time) alerted: bool = False @@ -230,4 +230,4 @@ class DigestEntry(TypedDict): count: int start_time: dt last_time: dt - webhook_url: Union[str, List[str]] + webhook_url: str | list[str] diff --git a/litellm/types/integrations/websearch_interception.py b/litellm/types/integrations/websearch_interception.py index d8a36169b88..05537da67d7 100644 --- a/litellm/types/integrations/websearch_interception.py +++ b/litellm/types/integrations/websearch_interception.py @@ -2,7 +2,7 @@ Type definitions for WebSearch Interception integration. """ -from typing import List, Optional, TypedDict +from typing import TypedDict class WebSearchInterceptionConfig(TypedDict, total=False): @@ -16,8 +16,8 @@ class WebSearchInterceptionConfig(TypedDict, total=False): search_tool_name: "my-perplexity-search" """ - enabled_providers: List[str] + enabled_providers: list[str] """List of LLM provider names to enable interception for (e.g., ['bedrock', 'vertex_ai'])""" - search_tool_name: Optional[str] + search_tool_name: str | None """Name of search tool configured in router's search_tools. If None, uses first available.""" diff --git a/litellm/types/interactions/__init__.py b/litellm/types/interactions/__init__.py index 78d0b04ef3b..1dba2273267 100644 --- a/litellm/types/interactions/__init__.py +++ b/litellm/types/interactions/__init__.py @@ -38,8 +38,8 @@ from litellm.types.interactions.generated import ( Interaction, InteractionCompleted, InteractionCreated, - InteractionEvent, InteractionEnvironment, + InteractionEvent, InteractionInProgress, InteractionInput, InteractionRequiresAction, @@ -57,11 +57,6 @@ from litellm.types.interactions.generated import ( StepDelta, StepStart, StepStop, -) -from litellm.types.interactions.generated import ( - Status3 as InteractionStatus, # Main request/response types; Content types; Turn for multi-turn conversations; Tool types; Config types; Usage; Status enum; Events for streaming; Agent configs; Model/Agent options; Response modality; Annotation; LiteLLM types; Backwards compat aliases -) -from litellm.types.interactions.generated import ( TextContent, ThoughtContent, Tool, @@ -73,72 +68,75 @@ from litellm.types.interactions.generated import ( Usage, VideoContent, ) +from litellm.types.interactions.generated import ( + Status3 as InteractionStatus, # Main request/response types; Content types; Turn for multi-turn conversations; Tool types; Config types; Usage; Status enum; Events for streaming; Agent configs; Model/Agent options; Response modality; Annotation; LiteLLM types; Backwards compat aliases +) __all__ = [ - # Generated types - "CreateModelInteractionParams", - "CreateAgentInteractionParams", - "Interaction", - "Content", - "TextContent", - "ImageContent", + "AgentOption", + "Annotation", "AudioContent", - "DocumentContent", - "VideoContent", - "ThoughtContent", - "FunctionCallContent", - "FunctionResultContent", + "CancelInteractionResult", + "CodeExecution", "CodeExecutionCallContent", "CodeExecutionResultContent", - "UrlContextCallContent", - "UrlContextResultContent", + "ComputerUse", + "Content", + "ContentDelta", + "ContentStart", + "ContentStop", + "CreateAgentInteractionParams", + # Generated types + "CreateModelInteractionParams", + "DeepResearchAgentConfig", + "DeleteInteractionResult", + "DocumentContent", + "DynamicAgentConfig", + "ErrorEvent", + "FileSearch", + "FileSearchResultContent", + "Function", + "FunctionCallContent", + "FunctionResultContent", + "GenerationConfig", + "GoogleSearch", "GoogleSearchCallContent", "GoogleSearchResultContent", - "McpServerToolCallContent", - "McpServerToolResultContent", - "FileSearchResultContent", - "Turn", - "Tool", - "Function", - "GoogleSearch", - "CodeExecution", - "UrlContext", - "ComputerUse", - "McpServer", - "FileSearch", - "GenerationConfig", - "ToolChoiceConfig", - "Usage", - "InteractionStatus", - "InteractionEvent", - "InteractionSseEvent", - "ContentStart", - "ContentDelta", - "ContentStop", - "ErrorEvent", - "DynamicAgentConfig", - "DeepResearchAgentConfig", - "ModelOption", - "AgentOption", - "ResponseModality", - "Annotation", - # New schema SSE event types (Api-Revision: 2026-05-20) - "StepStart", - "StepDelta", - "StepStop", - "InteractionCreated", - "InteractionInProgress", + "ImageContent", + "Interaction", "InteractionCompleted", - "InteractionRequiresAction", + "InteractionCreated", # LiteLLM types "InteractionEnvironment", + "InteractionEvent", + "InteractionInProgress", "InteractionInput", - "InteractionsAPIResponse", - "InteractionsAPIStreamingResponse", - "DeleteInteractionResult", - "CancelInteractionResult", - "InteractionsAPIOptionalRequestParams", + "InteractionRequiresAction", + "InteractionSseEvent", + "InteractionStatus", # Backwards compat "InteractionTool", "InteractionToolChoiceConfig", + "InteractionsAPIOptionalRequestParams", + "InteractionsAPIResponse", + "InteractionsAPIStreamingResponse", + "McpServer", + "McpServerToolCallContent", + "McpServerToolResultContent", + "ModelOption", + "ResponseModality", + "StepDelta", + # New schema SSE event types (Api-Revision: 2026-05-20) + "StepStart", + "StepStop", + "TextContent", + "ThoughtContent", + "Tool", + "ToolChoiceConfig", + "Turn", + "UrlContext", + "UrlContextCallContent", + "UrlContextResultContent", + "Usage", + "VideoContent", ] diff --git a/litellm/types/interactions/generated.py b/litellm/types/interactions/generated.py index 26aede298e5..a666d236e4b 100644 --- a/litellm/types/interactions/generated.py +++ b/litellm/types/interactions/generated.py @@ -5,33 +5,33 @@ from __future__ import annotations from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Final, Literal from pydantic import AwareDatetime, Base64Str, BaseModel, Field, RootModel class Annotation(BaseModel): - start_index: Optional[int] = Field( + start_index: int | None = Field( None, description="Start of segment of the response that is attributed to this source.\n\nIndex indicates the start of the segment, measured in bytes.", ) - end_index: Optional[int] = Field(None, description="End of the attributed segment, exclusive.") - source: Optional[str] = Field( + end_index: int | None = Field(None, description="End of the attributed segment, exclusive.") + source: str | None = Field( None, description="Source attributed for a portion of the text. Could be a URL, title, or\nother identifier.", ) class DocumentContent(BaseModel): - data: Optional[Base64Str] = None - uri: Optional[str] = None - mime_type: Optional[str] = None + data: Base64Str | None = None + uri: str | None = None + mime_type: str | None = None type: Literal["document"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") class FunctionCallContent(BaseModel): name: str = Field(..., description="The name of the tool to call.") - arguments: Dict[str, Any] = Field(..., description="The arguments to pass to the function.") + arguments: dict[str, Any] = Field(..., description="The arguments to pass to the function.") type: Literal["function_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) @@ -43,18 +43,18 @@ class Language(Enum): class CodeExecutionCallArguments(BaseModel): - language: Optional[Language] = Field(None, description="Programming language of the `code`.") - code: Optional[str] = Field(None, description="The code to be executed.") + language: Language | None = Field(None, description="Programming language of the `code`.") + code: str | None = Field(None, description="The code to be executed.") class UrlContextCallArguments(BaseModel): - urls: Optional[List[str]] = Field(None, description="The URLs to fetch.") + urls: list[str] | None = Field(None, description="The URLs to fetch.") class McpServerToolCallContent(BaseModel): name: str = Field(..., description="The name of the tool which was called.") server_name: str = Field(..., description="The name of the used MCP server.") - arguments: Dict[str, Any] = Field(..., description="The JSON object of arguments for the function.") + arguments: dict[str, Any] = Field(..., description="The JSON object of arguments for the function.") type: Literal["mcp_server_tool_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) @@ -62,17 +62,17 @@ class McpServerToolCallContent(BaseModel): class GoogleSearchCallArguments(BaseModel): - queries: Optional[List[str]] = Field(None, description="Web search queries for the following-up web search.") + queries: list[str] | None = Field(None, description="Web search queries for the following-up web search.") class CodeExecutionResultContent(BaseModel): - result: Optional[str] = Field(None, description="The output of the code execution.") - is_error: Optional[bool] = Field(None, description="Whether the code execution resulted in an error.") - signature: Optional[str] = Field(None, description="A signature hash for backend validation.") + result: str | None = Field(None, description="The output of the code execution.") + is_error: bool | None = Field(None, description="Whether the code execution resulted in an error.") + signature: str | None = Field(None, description="A signature hash for backend validation.") type: Literal["code_execution_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - call_id: Optional[str] = Field(None, description="ID to match the ID from the code execution call block.") + call_id: str | None = Field(None, description="ID to match the ID from the code execution call block.") class Status(Enum): @@ -83,29 +83,29 @@ class Status(Enum): class UrlContextResult(BaseModel): - url: Optional[str] = Field(None, description="The URL that was fetched.") - status: Optional[Status] = Field(None, description="The status of the URL retrieval.") + url: str | None = Field(None, description="The URL that was fetched.") + status: Status | None = Field(None, description="The status of the URL retrieval.") class GoogleSearchResult(BaseModel): - url: Optional[str] = Field(None, description="URI reference of the search result.") - title: Optional[str] = Field(None, description="Title of the search result.") - rendered_content: Optional[str] = Field( + url: str | None = Field(None, description="URI reference of the search result.") + title: str | None = Field(None, description="Title of the search result.") + rendered_content: str | None = Field( None, description="Web content snippet that can be embedded in a web page or an app webview.", ) class FileSearchResult(BaseModel): - title: Optional[str] = Field(None, description="The title of the search result.") - text: Optional[str] = Field(None, description="The text of the search result.") - file_search_store: Optional[str] = Field(None, description="The name of the file search store.") + title: str | None = Field(None, description="The title of the search result.") + text: str | None = Field(None, description="The text of the search result.") + file_search_store: str | None = Field(None, description="The name of the file search store.") class SpeechConfig(BaseModel): - voice: Optional[str] = Field(None, description="The voice of the speaker.") - language: Optional[str] = Field(None, description="The language of the speech.") - speaker: Optional[str] = Field( + voice: str | None = Field(None, description="The voice of the speaker.") + language: str | None = Field(None, description="The language of the speech.") + speaker: str | None = Field( None, description="The speaker's name, it should match the speaker name given in the prompt.", ) @@ -119,9 +119,9 @@ class DynamicAgentConfig(BaseModel): class Function(BaseModel): - name: Optional[str] = Field(None, description="The name of the function.") - description: Optional[str] = Field(None, description="A description of the function.") - parameters: Optional[Any] = Field(None, description="The JSON Schema for the function's parameters.") + name: str | None = Field(None, description="The name of the function.") + description: str | None = Field(None, description="A description of the function.") + parameters: Any | None = Field(None, description="The JSON Schema for the function's parameters.") type: Literal["function"] @@ -139,8 +139,8 @@ class Environment(Enum): class ComputerUse(BaseModel): type: Literal["computer_use"] - environment: Optional[Environment] = Field(None, description="The environment being operated.") - excludedPredefinedFunctions: Optional[List[str]] = Field( + environment: Environment | None = Field(None, description="The environment being operated.") + excludedPredefinedFunctions: list[str] | None = Field( None, description="The list of predefined functions that are excluded from the model call.", ) @@ -151,9 +151,9 @@ class GoogleSearch(BaseModel): class FileSearch(BaseModel): - file_search_store_names: Optional[List[str]] = Field(None, description="The file search store names to search.") - top_k: Optional[int] = Field(None, description="The number of semantic retrieval chunks to retrieve.") - metadata_filter: Optional[str] = Field( + file_search_store_names: list[str] | None = Field(None, description="The file search store names to search.") + top_k: int | None = Field(None, description="The number of semantic retrieval chunks to retrieve.") + metadata_filter: str | None = Field( None, description="Metadata filter to apply to the semantic retrieval documents and chunks.", ) @@ -177,32 +177,30 @@ class Status1(Enum): class InteractionStatusUpdate(BaseModel): - interaction_id: Optional[str] = None - status: Optional[Status1] = None + interaction_id: str | None = None + status: Status1 | None = None event_type: Literal["interaction.status_update"] = "interaction.status_update" - event_id: Optional[str] = Field( + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream, from\nthis event.", ) class TextDelta(BaseModel): - text: Optional[str] = None + text: str | None = None type: Literal["text"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") - annotations: Optional[List[Annotation]] = Field( - None, description="Citation information for model-generated content." - ) + annotations: list[Annotation] | None = Field(None, description="Citation information for model-generated content.") class DocumentDelta(BaseModel): - data: Optional[Base64Str] = None - uri: Optional[str] = None - mime_type: Optional[str] = None + data: Base64Str | None = None + uri: str | None = None + mime_type: str | None = None type: Literal["document"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") class ThoughtSignatureDelta(BaseModel): - signature: Optional[Base64Str] = Field( + signature: Base64Str | None = Field( None, description="Signature to match the backend source to be part of the generation.", ) @@ -212,97 +210,97 @@ class ThoughtSignatureDelta(BaseModel): class FunctionCallDelta(BaseModel): - name: Optional[str] = None - arguments: Optional[Dict[str, Any]] = None + name: str | None = None + arguments: dict[str, Any] | None = None type: Literal["function_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - id: Optional[str] = Field(None, description="A unique ID for this specific tool call.") + id: str | None = Field(None, description="A unique ID for this specific tool call.") class CodeExecutionCallDelta(BaseModel): - arguments: Optional[CodeExecutionCallArguments] = None + arguments: CodeExecutionCallArguments | None = None type: Literal["code_execution_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - id: Optional[str] = Field(None, description="A unique ID for this specific tool call.") + id: str | None = Field(None, description="A unique ID for this specific tool call.") class UrlContextCallDelta(BaseModel): - arguments: Optional[UrlContextCallArguments] = None + arguments: UrlContextCallArguments | None = None type: Literal["url_context_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - id: Optional[str] = Field(None, description="A unique ID for this specific tool call.") + id: str | None = Field(None, description="A unique ID for this specific tool call.") class GoogleSearchCallDelta(BaseModel): - arguments: Optional[GoogleSearchCallArguments] = None + arguments: GoogleSearchCallArguments | None = None type: Literal["google_search_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - id: Optional[str] = Field(None, description="A unique ID for this specific tool call.") + id: str | None = Field(None, description="A unique ID for this specific tool call.") class McpServerToolCallDelta(BaseModel): - name: Optional[str] = None - server_name: Optional[str] = None - arguments: Optional[Dict[str, Any]] = None + name: str | None = None + server_name: str | None = None + arguments: dict[str, Any] | None = None type: Literal["mcp_server_tool_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - id: Optional[str] = Field(None, description="A unique ID for this specific tool call.") + id: str | None = Field(None, description="A unique ID for this specific tool call.") class CodeExecutionResultDelta(BaseModel): - result: Optional[str] = None - is_error: Optional[bool] = None - signature: Optional[str] = None + result: str | None = None + is_error: bool | None = None + signature: str | None = None type: Literal["code_execution_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - call_id: Optional[str] = Field(None, description="ID to match the ID from the function call block.") + call_id: str | None = Field(None, description="ID to match the ID from the function call block.") class UrlContextResultDelta(BaseModel): - signature: Optional[str] = None - result: Optional[List[UrlContextResult]] = None - is_error: Optional[bool] = None + signature: str | None = None + result: list[UrlContextResult] | None = None + is_error: bool | None = None type: Literal["url_context_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - call_id: Optional[str] = Field(None, description="ID to match the ID from the function call block.") + call_id: str | None = Field(None, description="ID to match the ID from the function call block.") class GoogleSearchResultDelta(BaseModel): - signature: Optional[str] = None - result: Optional[List[GoogleSearchResult]] = None - is_error: Optional[bool] = None + signature: str | None = None + result: list[GoogleSearchResult] | None = None + is_error: bool | None = None type: Literal["google_search_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - call_id: Optional[str] = Field(None, description="ID to match the ID from the function call block.") + call_id: str | None = Field(None, description="ID to match the ID from the function call block.") class FileSearchResultDelta(BaseModel): - result: Optional[List[FileSearchResult]] = None + result: list[FileSearchResult] | None = None type: Literal["file_search_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) class ContentStop(BaseModel): - index: Optional[int] = None + index: int | None = None event_type: Literal["content.stop"] = "content.stop" - event_id: Optional[str] = Field( + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream, from\nthis event.", ) class Error(BaseModel): - code: Optional[str] = Field(None, description="A URI that identifies the error type.") - message: Optional[str] = Field(None, description="A human-readable error message.") + code: str | None = Field(None, description="A URI that identifies the error type.") + message: str | None = Field(None, description="A human-readable error message.") class MediaResolution(Enum): @@ -370,127 +368,125 @@ class VideoMimeTypeOption(RootModel[str]): class TextContent(BaseModel): - text: Optional[str] = Field(None, description="The text content.") + text: str | None = Field(None, description="The text content.") type: Literal["text"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") - annotations: Optional[List[Annotation]] = Field( - None, description="Citation information for model-generated content." - ) + annotations: list[Annotation] | None = Field(None, description="Citation information for model-generated content.") class ImageContent(BaseModel): - data: Optional[Base64Str] = None - uri: Optional[str] = None - mime_type: Optional[ImageMimeTypeOption] = None + data: Base64Str | None = None + uri: str | None = None + mime_type: ImageMimeTypeOption | None = None type: Literal["image"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") - resolution: Optional[MediaResolution] = Field(None, description="The resolution of the media.") + resolution: MediaResolution | None = Field(None, description="The resolution of the media.") class AudioContent(BaseModel): - data: Optional[Base64Str] = None - uri: Optional[str] = None - mime_type: Optional[AudioMimeTypeOption] = None + data: Base64Str | None = None + uri: str | None = None + mime_type: AudioMimeTypeOption | None = None type: Literal["audio"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") class VideoContent(BaseModel): - data: Optional[Base64Str] = None - uri: Optional[str] = None - mime_type: Optional[VideoMimeTypeOption] = None + data: Base64Str | None = None + uri: str | None = None + mime_type: VideoMimeTypeOption | None = None type: Literal["video"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") - resolution: Optional[MediaResolution] = Field(None, description="The resolution of the media.") + resolution: MediaResolution | None = Field(None, description="The resolution of the media.") -class ThoughtSummary1(RootModel[Union[TextContent, ImageContent]]): - root: Union[TextContent, ImageContent] = Field(..., discriminator="type") +class ThoughtSummary1(RootModel[TextContent | ImageContent]): + root: TextContent | ImageContent = Field(..., discriminator="type") -class ThoughtSummary(RootModel[List[ThoughtSummary1]]): - root: List[ThoughtSummary1] = Field(..., description="A summary of the thought.") +class ThoughtSummary(RootModel[list[ThoughtSummary1]]): + root: list[ThoughtSummary1] = Field(..., description="A summary of the thought.") class CodeExecutionCallContent(BaseModel): - arguments: Optional[CodeExecutionCallArguments] = Field( + arguments: CodeExecutionCallArguments | None = Field( None, description="The arguments to pass to the code execution." ) type: Literal["code_execution_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - id: Optional[str] = Field(None, description="A unique ID for this specific tool call.") + id: str | None = Field(None, description="A unique ID for this specific tool call.") class UrlContextCallContent(BaseModel): - arguments: Optional[UrlContextCallArguments] = Field(None, description="The arguments to pass to the URL context.") + arguments: UrlContextCallArguments | None = Field(None, description="The arguments to pass to the URL context.") type: Literal["url_context_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - id: Optional[str] = Field(None, description="A unique ID for this specific tool call.") + id: str | None = Field(None, description="A unique ID for this specific tool call.") class GoogleSearchCallContent(BaseModel): - arguments: Optional[GoogleSearchCallArguments] = Field(None, description="The arguments to pass to Google Search.") + arguments: GoogleSearchCallArguments | None = Field(None, description="The arguments to pass to Google Search.") type: Literal["google_search_call"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - id: Optional[str] = Field(None, description="A unique ID for this specific tool call.") + id: str | None = Field(None, description="A unique ID for this specific tool call.") class Result(BaseModel): - items: Optional[List[Union[str, ImageContent]]] = None + items: list[str | ImageContent] | None = None class FunctionResultContent(BaseModel): - name: Optional[str] = Field(None, description="The name of the tool that was called.") - is_error: Optional[bool] = Field(None, description="Whether the tool call resulted in an error.") + name: str | None = Field(None, description="The name of the tool that was called.") + is_error: bool | None = Field(None, description="Whether the tool call resulted in an error.") type: Literal["function_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - result: Union[Result, Dict[str, Any], str] = Field(..., description="The result of the tool call.") + result: Result | dict[str, Any] | str = Field(..., description="The result of the tool call.") call_id: str = Field(..., description="ID to match the ID from the function call block.") class UrlContextResultContent(BaseModel): - signature: Optional[str] = Field(None, description="The signature of the URL context result.") - result: Optional[List[UrlContextResult]] = Field(None, description="The results of the URL context.") - is_error: Optional[bool] = Field(None, description="Whether the URL context resulted in an error.") + signature: str | None = Field(None, description="The signature of the URL context result.") + result: list[UrlContextResult] | None = Field(None, description="The results of the URL context.") + is_error: bool | None = Field(None, description="Whether the URL context resulted in an error.") type: Literal["url_context_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - call_id: Optional[str] = Field(None, description="ID to match the ID from the url context call block.") + call_id: str | None = Field(None, description="ID to match the ID from the url context call block.") class GoogleSearchResultContent(BaseModel): - signature: Optional[str] = Field(None, description="The signature of the Google Search result.") - result: Optional[List[GoogleSearchResult]] = Field(None, description="The results of the Google Search.") - is_error: Optional[bool] = Field(None, description="Whether the Google Search resulted in an error.") + signature: str | None = Field(None, description="The signature of the Google Search result.") + result: list[GoogleSearchResult] | None = Field(None, description="The results of the Google Search.") + is_error: bool | None = Field(None, description="Whether the Google Search resulted in an error.") type: Literal["google_search_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - call_id: Optional[str] = Field(None, description="ID to match the ID from the google search call block.") + call_id: str | None = Field(None, description="ID to match the ID from the google search call block.") class McpServerToolResultContent(BaseModel): - name: Optional[str] = Field( + name: str | None = Field( None, description="Name of the tool which is called for this specific tool call.", ) - server_name: Optional[str] = Field(None, description="The name of the used MCP server.") + server_name: str | None = Field(None, description="The name of the used MCP server.") type: Literal["mcp_server_tool_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - result: Union[Result, Dict[str, Any], str] = Field(..., description="The result of the tool call.") + result: Result | dict[str, Any] | str = Field(..., description="The result of the tool call.") call_id: str = Field(..., description="ID to match the ID from the MCP server tool call block.") class FileSearchResultContent(BaseModel): - result: Optional[List[FileSearchResult]] = Field(None, description="The results of the File Search.") + result: list[FileSearchResult] | None = Field(None, description="The results of the File Search.") type: Literal["file_search_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) class AllowedTools(BaseModel): - mode: Optional[ToolChoiceType] = Field(None, description="The mode of the tool choice.") - tools: Optional[List[str]] = Field(None, description="The names of the allowed tools.") + mode: ToolChoiceType | None = Field(None, description="The mode of the tool choice.") + tools: list[str] | None = Field(None, description="The names of the allowed tools.") class DeepResearchAgentConfig(BaseModel): @@ -498,382 +494,355 @@ class DeepResearchAgentConfig(BaseModel): "deep-research", description="Used as the OpenAPI type discriminator for the content oneof.", ) - thinking_summaries: Optional[ThinkingSummaries] = Field( + thinking_summaries: ThinkingSummaries | None = Field( None, description="Whether to include thought summaries in the response." ) class McpServer(BaseModel): type: Literal["mcp_server"] - name: Optional[str] = Field(None, description="The name of the MCPServer.") - url: Optional[str] = Field( + name: str | None = Field(None, description="The name of the MCPServer.") + url: str | None = Field( None, description='The full URL for the MCPServer endpoint.\nExample: "https://api.example.com/mcp"', ) - headers: Optional[Dict[str, str]] = Field( + headers: dict[str, str] | None = Field( None, description="Optional: Fields for authentication headers, timeouts, etc., if needed.", ) - allowed_tools: Optional[List[AllowedTools]] = Field(None, description="The allowed tools.") + allowed_tools: list[AllowedTools] | None = Field(None, description="The allowed tools.") class ModalityTokens(BaseModel): - modality: Optional[ResponseModality] = Field(None, description="The modality associated with the token count.") - tokens: Optional[int] = Field(None, description="Number of tokens for the modality.") + modality: ResponseModality | None = Field(None, description="The modality associated with the token count.") + tokens: int | None = Field(None, description="Number of tokens for the modality.") class ImageDelta(BaseModel): - data: Optional[Base64Str] = None - uri: Optional[str] = None - mime_type: Optional[ImageMimeTypeOption] = None + data: Base64Str | None = None + uri: str | None = None + mime_type: ImageMimeTypeOption | None = None type: Literal["image"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") - resolution: Optional[MediaResolution] = Field(None, description="The resolution of the media.") + resolution: MediaResolution | None = Field(None, description="The resolution of the media.") class AudioDelta(BaseModel): - data: Optional[Base64Str] = None - uri: Optional[str] = None - mime_type: Optional[AudioMimeTypeOption] = None + data: Base64Str | None = None + uri: str | None = None + mime_type: AudioMimeTypeOption | None = None type: Literal["audio"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") class VideoDelta(BaseModel): - data: Optional[Base64Str] = None - uri: Optional[str] = None - mime_type: Optional[VideoMimeTypeOption] = None + data: Base64Str | None = None + uri: str | None = None + mime_type: VideoMimeTypeOption | None = None type: Literal["video"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") - resolution: Optional[MediaResolution] = Field(None, description="The resolution of the media.") + resolution: MediaResolution | None = Field(None, description="The resolution of the media.") class ThoughtSummaryDelta(BaseModel): type: Literal["thought_summary"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - content: Optional[Union[TextContent, ImageContent]] = Field(None, discriminator="type") + content: TextContent | ImageContent | None = Field(None, discriminator="type") class FunctionResultDelta(BaseModel): - name: Optional[str] = None - is_error: Optional[bool] = None + name: str | None = None + is_error: bool | None = None type: Literal["function_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - result: Optional[Union[Result, str]] = Field(None, description="Tool call result delta.") - call_id: Optional[str] = Field(None, description="ID to match the ID from the function call block.") + result: Result | str | None = Field(None, description="Tool call result delta.") + call_id: str | None = Field(None, description="ID to match the ID from the function call block.") class McpServerToolResultDelta(BaseModel): - name: Optional[str] = None - server_name: Optional[str] = None + name: str | None = None + server_name: str | None = None type: Literal["mcp_server_tool_result"] = Field( ..., description="Used as the OpenAPI type discriminator for the content oneof." ) - result: Optional[Union[Result, str]] = Field(None, description="Tool call result delta.") - call_id: Optional[str] = Field(None, description="ID to match the ID from the function call block.") + result: Result | str | None = Field(None, description="Tool call result delta.") + call_id: str | None = Field(None, description="ID to match the ID from the function call block.") class ErrorEvent(BaseModel): event_type: Literal["error"] = "error" - error: Optional[Error] = None - event_id: Optional[str] = Field( + error: Error | None = None + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream, from\nthis event.", ) class ToolChoiceConfig(BaseModel): - allowed_tools: Optional[AllowedTools] = None + allowed_tools: AllowedTools | None = None -class Tool( - RootModel[ - Union[ - Function, - GoogleSearch, - CodeExecution, - UrlContext, - ComputerUse, - McpServer, - FileSearch, - ] - ] -): - root: Union[ - Function, - GoogleSearch, - CodeExecution, - UrlContext, - ComputerUse, - McpServer, - FileSearch, - ] = Field(..., discriminator="type") +class Tool(RootModel[Function | GoogleSearch | CodeExecution | UrlContext | ComputerUse | McpServer | FileSearch]): + root: Function | GoogleSearch | CodeExecution | UrlContext | ComputerUse | McpServer | FileSearch = Field( + ..., discriminator="type" + ) class ThoughtContent(BaseModel): - signature: Optional[Base64Str] = Field( + signature: Base64Str | None = Field( None, description="Signature to match the backend source to be part of the generation.", ) type: Literal["thought"] = Field(..., description="Used as the OpenAPI type discriminator for the content oneof.") - summary: Optional[ThoughtSummary] = Field(None, description="A summary of the thought.") + summary: ThoughtSummary | None = Field(None, description="A summary of the thought.") -class ToolChoice(RootModel[Union[ToolChoiceType, ToolChoiceConfig]]): - root: Union[ToolChoiceType, ToolChoiceConfig] = Field(..., description="The configuration for tool choice.") +class ToolChoice(RootModel[ToolChoiceType | ToolChoiceConfig]): + root: ToolChoiceType | ToolChoiceConfig = Field(..., description="The configuration for tool choice.") class Usage(BaseModel): - total_input_tokens: Optional[int] = Field(None, description="Number of tokens in the prompt (context).") - input_tokens_by_modality: Optional[List[ModalityTokens]] = Field( + total_input_tokens: int | None = Field(None, description="Number of tokens in the prompt (context).") + input_tokens_by_modality: list[ModalityTokens] | None = Field( None, description="A breakdown of input token usage by modality." ) - total_cached_tokens: Optional[int] = Field( + total_cached_tokens: int | None = Field( None, description="Number of tokens in the cached part of the prompt (the cached content).", ) - cached_tokens_by_modality: Optional[List[ModalityTokens]] = Field( + cached_tokens_by_modality: list[ModalityTokens] | None = Field( None, description="A breakdown of cached token usage by modality." ) - total_output_tokens: Optional[int] = Field( + total_output_tokens: int | None = Field( None, description="Total number of tokens across all the generated responses." ) - output_tokens_by_modality: Optional[List[ModalityTokens]] = Field( + output_tokens_by_modality: list[ModalityTokens] | None = Field( None, description="A breakdown of output token usage by modality." ) - total_tool_use_tokens: Optional[int] = Field(None, description="Number of tokens present in tool-use prompt(s).") - tool_use_tokens_by_modality: Optional[List[ModalityTokens]] = Field( + total_tool_use_tokens: int | None = Field(None, description="Number of tokens present in tool-use prompt(s).") + tool_use_tokens_by_modality: list[ModalityTokens] | None = Field( None, description="A breakdown of tool-use token usage by modality." ) - total_reasoning_tokens: Optional[int] = Field(None, description="Number of tokens of thoughts for thinking models.") - total_tokens: Optional[int] = Field( + total_reasoning_tokens: int | None = Field(None, description="Number of tokens of thoughts for thinking models.") + total_tokens: int | None = Field( None, description="Total token count for the interaction request (prompt + responses + other\ninternal tokens).", ) class ContentDelta(BaseModel): - index: Optional[int] = None + index: int | None = None event_type: Literal["content.delta"] = "content.delta" - event_id: Optional[str] = Field( + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream, from\nthis event.", ) - delta: Optional[ - Union[ - TextDelta, - ImageDelta, - AudioDelta, - DocumentDelta, - VideoDelta, - ThoughtSummaryDelta, - ThoughtSignatureDelta, - FunctionCallDelta, - FunctionResultDelta, - CodeExecutionCallDelta, - CodeExecutionResultDelta, - UrlContextCallDelta, - UrlContextResultDelta, - GoogleSearchCallDelta, - GoogleSearchResultDelta, - McpServerToolCallDelta, - McpServerToolResultDelta, - FileSearchResultDelta, - ] - ] = Field(None, discriminator="type") + delta: ( + TextDelta + | ImageDelta + | AudioDelta + | DocumentDelta + | VideoDelta + | ThoughtSummaryDelta + | ThoughtSignatureDelta + | FunctionCallDelta + | FunctionResultDelta + | CodeExecutionCallDelta + | CodeExecutionResultDelta + | UrlContextCallDelta + | UrlContextResultDelta + | GoogleSearchCallDelta + | GoogleSearchResultDelta + | McpServerToolCallDelta + | McpServerToolResultDelta + | FileSearchResultDelta + | None + ) = Field(None, discriminator="type") class Content( RootModel[ - Union[ - TextContent, - ImageContent, - AudioContent, - DocumentContent, - VideoContent, - ThoughtContent, - FunctionCallContent, - FunctionResultContent, - CodeExecutionCallContent, - CodeExecutionResultContent, - UrlContextCallContent, - UrlContextResultContent, - GoogleSearchCallContent, - GoogleSearchResultContent, - McpServerToolCallContent, - McpServerToolResultContent, - FileSearchResultContent, - ] + TextContent + | ImageContent + | AudioContent + | DocumentContent + | VideoContent + | ThoughtContent + | FunctionCallContent + | FunctionResultContent + | CodeExecutionCallContent + | CodeExecutionResultContent + | UrlContextCallContent + | UrlContextResultContent + | GoogleSearchCallContent + | GoogleSearchResultContent + | McpServerToolCallContent + | McpServerToolResultContent + | FileSearchResultContent ] ): - root: Union[ - TextContent, - ImageContent, - AudioContent, - DocumentContent, - VideoContent, - ThoughtContent, - FunctionCallContent, - FunctionResultContent, - CodeExecutionCallContent, - CodeExecutionResultContent, - UrlContextCallContent, - UrlContextResultContent, - GoogleSearchCallContent, - GoogleSearchResultContent, - McpServerToolCallContent, - McpServerToolResultContent, - FileSearchResultContent, - ] = Field(..., description="The content of the response.", discriminator="type") + root: ( + TextContent + | ImageContent + | AudioContent + | DocumentContent + | VideoContent + | ThoughtContent + | FunctionCallContent + | FunctionResultContent + | CodeExecutionCallContent + | CodeExecutionResultContent + | UrlContextCallContent + | UrlContextResultContent + | GoogleSearchCallContent + | GoogleSearchResultContent + | McpServerToolCallContent + | McpServerToolResultContent + | FileSearchResultContent + ) = Field(..., description="The content of the response.", discriminator="type") class Turn(BaseModel): - role: Optional[str] = Field( + role: str | None = Field( None, description="The originator of this turn. Must be user for input or model for\nmodel output.", ) - content: Optional[Union[str, List[Content]]] = Field(None, description="The content of the turn.") + content: str | list[Content] | None = Field(None, description="The content of the turn.") class GenerationConfig(BaseModel): - temperature: Optional[float] = Field(None, description="Controls the randomness of the output.") - top_p: Optional[float] = Field( + temperature: float | None = Field(None, description="Controls the randomness of the output.") + top_p: float | None = Field( None, description="The maximum cumulative probability of tokens to consider when sampling.", ) - seed: Optional[int] = Field(None, description="Seed used in decoding for reproducibility.") - stop_sequences: Optional[List[str]] = Field( + seed: int | None = Field(None, description="Seed used in decoding for reproducibility.") + stop_sequences: list[str] | None = Field( None, description="A list of character sequences that will stop output interaction.", ) - tool_choice: Optional[ToolChoice] = Field(None, description="The tool choice for the interaction.") - thinking_level: Optional[ThinkingLevel] = Field( + tool_choice: ToolChoice | None = Field(None, description="The tool choice for the interaction.") + thinking_level: ThinkingLevel | None = Field( None, description="The level of thought tokens that the model should generate." ) - thinking_summaries: Optional[ThinkingSummaries] = Field( + thinking_summaries: ThinkingSummaries | None = Field( None, description="Whether to include thought summaries in the response." ) - max_output_tokens: Optional[int] = Field( - None, description="The maximum number of tokens to include in the response." - ) - speech_config: Optional[List[SpeechConfig]] = Field(None, description="Configuration for speech interaction.") + max_output_tokens: int | None = Field(None, description="The maximum number of tokens to include in the response.") + speech_config: list[SpeechConfig] | None = Field(None, description="Configuration for speech interaction.") class ContentStart(BaseModel): - index: Optional[int] = None - content: Optional[Content] = None + index: int | None = None + content: Content | None = None event_type: Literal["content.start"] = "content.start" - event_id: Optional[str] = Field( + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream, from\nthis event.", ) class Interaction(BaseModel): - model: Optional[ModelOption] = Field( - None, description="The name of the `Model` used for generating the interaction." - ) - agent: Optional[AgentOption] = Field( - None, description="The name of the `Agent` used for generating the interaction." - ) + model: ModelOption | None = Field(None, description="The name of the `Model` used for generating the interaction.") + agent: AgentOption | None = Field(None, description="The name of the `Agent` used for generating the interaction.") id: str = Field( ..., description="Output only. A unique identifier for the interaction completion.", ) status: Status1 = Field(..., description="Output only. The status of the interaction.") - created: Optional[AwareDatetime] = Field( + created: AwareDatetime | None = Field( None, description="Output only. The time at which the response was created in ISO 8601 format\n(YYYY-MM-DDThh:mm:ssZ).", ) - updated: Optional[AwareDatetime] = Field( + updated: AwareDatetime | None = Field( None, description="Output only. The time at which the response was last updated in ISO 8601 format\n(YYYY-MM-DDThh:mm:ssZ).", ) - outputs: Optional[List[Content]] = Field(None, description="Output only. Responses from the model.") - system_instruction: Optional[str] = Field(None, description="System instruction for the interaction.") - tools: Optional[List[Tool]] = Field( + outputs: list[Content] | None = Field(None, description="Output only. Responses from the model.") + system_instruction: str | None = Field(None, description="System instruction for the interaction.") + tools: list[Tool] | None = Field( None, description="A list of tool declarations the model may call during interaction.", ) - background: Optional[bool] = Field(None, description="Whether to run the model interaction in the background.") + background: bool | None = Field(None, description="Whether to run the model interaction in the background.") object: Literal["interaction"] = Field( "interaction", description="Output only. The object type of the interaction. Always set to `interaction`.", ) - usage: Optional[Usage] = Field( + usage: Usage | None = Field( None, description="Output only. Statistics on the interaction request's token usage.", ) - response_modalities: Optional[List[ResponseModality]] = Field( + response_modalities: list[ResponseModality] | None = Field( None, description="The requested modalities of the response (TEXT, IMAGE, AUDIO).", ) - response_format: Optional[Any] = Field( + response_format: Any | None = Field( None, description="Enforces that the generated response is a JSON object that complies with\nthe JSON schema specified in this field.", ) - response_mime_type: Optional[str] = Field( + response_mime_type: str | None = Field( None, description="The mime type of the response. This is required if response_format is set.", ) - previous_interaction_id: Optional[str] = Field(None, description="The ID of the previous interaction, if any.") - input: Optional[Union[str, List[Content], List[Turn], Content]] = Field( + previous_interaction_id: str | None = Field(None, description="The ID of the previous interaction, if any.") + input: str | list[Content] | list[Turn] | Content | None = Field( None, description="The inputs for the interaction." ) - generation_config: Optional[GenerationConfig] = Field( + generation_config: GenerationConfig | None = Field( None, description="Input only. Configuration parameters for the model interaction.", ) - agent_config: Optional[Union[DynamicAgentConfig, DeepResearchAgentConfig]] = Field( + agent_config: DynamicAgentConfig | DeepResearchAgentConfig | None = Field( None, description="Configuration for the agent.", discriminator="type" ) class CreateModelInteractionParams(BaseModel): model: ModelOption = Field(..., description="The name of the `Model` used for generating the interaction.") - stream: Optional[bool] = Field(None, description="Input only. Whether the interaction will be streamed.") - store: Optional[bool] = Field( + stream: bool | None = Field(None, description="Input only. Whether the interaction will be streamed.") + store: bool | None = Field( None, description="Input only. Whether to store the response and request for later retrieval.", ) - id: Optional[str] = Field( + id: str | None = Field( None, description="Output only. A unique identifier for the interaction completion.", ) - status: Optional[Status3] = Field(None, description="Output only. The status of the interaction.") - created: Optional[AwareDatetime] = Field( + status: Status3 | None = Field(None, description="Output only. The status of the interaction.") + created: AwareDatetime | None = Field( None, description="Output only. The time at which the response was created in ISO 8601 format\n(YYYY-MM-DDThh:mm:ssZ).", ) - updated: Optional[AwareDatetime] = Field( + updated: AwareDatetime | None = Field( None, description="Output only. The time at which the response was last updated in ISO 8601 format\n(YYYY-MM-DDThh:mm:ssZ).", ) - outputs: Optional[List[Content]] = Field(None, description="Output only. Responses from the model.") - system_instruction: Optional[str] = Field(None, description="System instruction for the interaction.") - tools: Optional[List[Tool]] = Field( + outputs: list[Content] | None = Field(None, description="Output only. Responses from the model.") + system_instruction: str | None = Field(None, description="System instruction for the interaction.") + tools: list[Tool] | None = Field( None, description="A list of tool declarations the model may call during interaction.", ) - background: Optional[bool] = Field(None, description="Whether to run the model interaction in the background.") - usage: Optional[Usage] = Field( + background: bool | None = Field(None, description="Whether to run the model interaction in the background.") + usage: Usage | None = Field( None, description="Output only. Statistics on the interaction request's token usage.", ) - response_modalities: Optional[List[ResponseModality]] = Field( + response_modalities: list[ResponseModality] | None = Field( None, description="The requested modalities of the response (TEXT, IMAGE, AUDIO).", ) - response_format: Optional[Any] = Field( + response_format: Any | None = Field( None, description="Enforces that the generated response is a JSON object that complies with\nthe JSON schema specified in this field.", ) - response_mime_type: Optional[str] = Field( + response_mime_type: str | None = Field( None, description="The mime type of the response. This is required if response_format is set.", ) - previous_interaction_id: Optional[str] = Field(None, description="The ID of the previous interaction, if any.") - input: Union[str, List[Content], List[Turn], Content] = Field(..., description="The inputs for the interaction.") - generation_config: Optional[GenerationConfig] = Field( + previous_interaction_id: str | None = Field(None, description="The ID of the previous interaction, if any.") + input: str | list[Content] | list[Turn] | Content = Field(..., description="The inputs for the interaction.") + generation_config: GenerationConfig | None = Field( None, description="Input only. Configuration parameters for the model interaction.", ) @@ -881,58 +850,58 @@ class CreateModelInteractionParams(BaseModel): class CreateAgentInteractionParams(BaseModel): agent: AgentOption = Field(..., description="The name of the `Agent` used for generating the interaction.") - stream: Optional[bool] = Field(None, description="Input only. Whether the interaction will be streamed.") - store: Optional[bool] = Field( + stream: bool | None = Field(None, description="Input only. Whether the interaction will be streamed.") + store: bool | None = Field( None, description="Input only. Whether to store the response and request for later retrieval.", ) - id: Optional[str] = Field( + id: str | None = Field( None, description="Output only. A unique identifier for the interaction completion.", ) - status: Optional[Status3] = Field(None, description="Output only. The status of the interaction.") - created: Optional[AwareDatetime] = Field( + status: Status3 | None = Field(None, description="Output only. The status of the interaction.") + created: AwareDatetime | None = Field( None, description="Output only. The time at which the response was created in ISO 8601 format\n(YYYY-MM-DDThh:mm:ssZ).", ) - updated: Optional[AwareDatetime] = Field( + updated: AwareDatetime | None = Field( None, description="Output only. The time at which the response was last updated in ISO 8601 format\n(YYYY-MM-DDThh:mm:ssZ).", ) - outputs: Optional[List[Content]] = Field(None, description="Output only. Responses from the model.") - system_instruction: Optional[str] = Field(None, description="System instruction for the interaction.") - tools: Optional[List[Tool]] = Field( + outputs: list[Content] | None = Field(None, description="Output only. Responses from the model.") + system_instruction: str | None = Field(None, description="System instruction for the interaction.") + tools: list[Tool] | None = Field( None, description="A list of tool declarations the model may call during interaction.", ) - background: Optional[bool] = Field(None, description="Whether to run the model interaction in the background.") - usage: Optional[Usage] = Field( + background: bool | None = Field(None, description="Whether to run the model interaction in the background.") + usage: Usage | None = Field( None, description="Output only. Statistics on the interaction request's token usage.", ) - response_modalities: Optional[List[ResponseModality]] = Field( + response_modalities: list[ResponseModality] | None = Field( None, description="The requested modalities of the response (TEXT, IMAGE, AUDIO).", ) - response_format: Optional[Any] = Field( + response_format: Any | None = Field( None, description="Enforces that the generated response is a JSON object that complies with\nthe JSON schema specified in this field.", ) - response_mime_type: Optional[str] = Field( + response_mime_type: str | None = Field( None, description="The mime type of the response. This is required if response_format is set.", ) - previous_interaction_id: Optional[str] = Field(None, description="The ID of the previous interaction, if any.") - input: Union[str, List[Content], List[Turn], Content] = Field(..., description="The inputs for the interaction.") - agent_config: Optional[Union[DynamicAgentConfig, DeepResearchAgentConfig]] = Field( + previous_interaction_id: str | None = Field(None, description="The ID of the previous interaction, if any.") + input: str | list[Content] | list[Turn] | Content = Field(..., description="The inputs for the interaction.") + agent_config: DynamicAgentConfig | DeepResearchAgentConfig | None = Field( None, description="Configuration for the agent.", discriminator="type" ) class InteractionEvent(BaseModel): event_type: Literal["interaction.start", "interaction.complete"] - interaction: Optional[Interaction] = None - event_id: Optional[str] = Field( + interaction: Interaction | None = None + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream, from\nthis event.", ) @@ -949,12 +918,12 @@ class StepStart(BaseModel): """Emitted when a new step begins (replaces content.start).""" event_type: Literal["step.start"] = "step.start" - index: Optional[int] = None - step: Optional[Dict[str, Any]] = Field( + index: int | None = None + step: dict[str, Any] | None = Field( None, description="The initial step data (type, content, signature, etc.).", ) - event_id: Optional[str] = Field( + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream.", ) @@ -964,12 +933,12 @@ class StepDelta(BaseModel): """Emitted for incremental step content (replaces content.delta).""" event_type: Literal["step.delta"] = "step.delta" - index: Optional[int] = None - delta: Optional[Dict[str, Any]] = Field( + index: int | None = None + delta: dict[str, Any] | None = Field( None, description="Incremental content delta (e.g. text, arguments_delta for function calls).", ) - event_id: Optional[str] = Field( + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream.", ) @@ -979,12 +948,12 @@ class StepStop(BaseModel): """Emitted when a step finishes (replaces content.stop).""" event_type: Literal["step.stop"] = "step.stop" - index: Optional[int] = None - status: Optional[str] = Field( + index: int | None = None + status: str | None = Field( None, description="Step completion status (e.g. 'done').", ) - event_id: Optional[str] = Field( + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream.", ) @@ -994,8 +963,8 @@ class InteractionCreated(BaseModel): """Emitted when the interaction is first created (replaces interaction.start).""" event_type: Literal["interaction.created"] = "interaction.created" - interaction: Optional[Dict[str, Any]] = None - event_id: Optional[str] = Field( + interaction: dict[str, Any] | None = None + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream.", ) @@ -1005,8 +974,8 @@ class InteractionInProgress(BaseModel): """Emitted while the interaction is running.""" event_type: Literal["interaction.in_progress"] = "interaction.in_progress" - interaction_id: Optional[str] = None - event_id: Optional[str] = Field( + interaction_id: str | None = None + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream.", ) @@ -1016,8 +985,8 @@ class InteractionCompleted(BaseModel): """Emitted when the interaction finishes (replaces interaction.complete).""" event_type: Literal["interaction.completed"] = "interaction.completed" - interaction: Optional[Dict[str, Any]] = None - event_id: Optional[str] = Field( + interaction: dict[str, Any] | None = None + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream.", ) @@ -1027,8 +996,8 @@ class InteractionRequiresAction(BaseModel): """Emitted when the interaction is paused waiting for a tool result.""" event_type: Literal["interaction.requires_action"] = "interaction.requires_action" - interaction_id: Optional[str] = None - event_id: Optional[str] = Field( + interaction_id: str | None = None + event_id: str | None = Field( None, description="The event_id token to be used to resume the interaction stream.", ) @@ -1036,42 +1005,38 @@ class InteractionRequiresAction(BaseModel): class InteractionSseEvent( RootModel[ - Union[ - # New schema events (Api-Revision: 2026-05-20) - StepStart, - StepDelta, - StepStop, - InteractionCreated, - InteractionInProgress, - InteractionCompleted, - InteractionRequiresAction, - # Legacy schema events (Api-Revision: 2026-05-07, removed June 8 2026) - InteractionEvent, - InteractionStatusUpdate, - ContentStart, - ContentDelta, - ContentStop, - ErrorEvent, - ] + # New schema events (Api-Revision: 2026-05-20) + StepStart + | StepDelta + | StepStop + | InteractionCreated + | InteractionInProgress + | InteractionCompleted + | InteractionRequiresAction + # Legacy schema events (Api-Revision: 2026-05-07, removed June 8 2026) + | InteractionEvent + | InteractionStatusUpdate + | ContentStart + | ContentDelta + | ContentStop + | ErrorEvent ] ): - root: Union[ - # New schema events (Api-Revision: 2026-05-20) - StepStart, - StepDelta, - StepStop, - InteractionCreated, - InteractionInProgress, - InteractionCompleted, - InteractionRequiresAction, - # Legacy schema events (Api-Revision: 2026-05-07, removed June 8 2026) - InteractionEvent, - InteractionStatusUpdate, - ContentStart, - ContentDelta, - ContentStop, - ErrorEvent, - ] = Field(..., discriminator="event_type") + root: ( + StepStart + | StepDelta + | StepStop + | InteractionCreated + | InteractionInProgress + | InteractionCompleted + | InteractionRequiresAction + | InteractionEvent + | InteractionStatusUpdate + | ContentStart + | ContentDelta + | ContentStop + | ErrorEvent + ) = Field(..., discriminator="event_type") # ============================================================ @@ -1086,7 +1051,7 @@ from pydantic import PrivateAttr from litellm.types.llms.base import BaseLiteLLMOpenAIResponseObject # Type alias for input -InteractionInput = Union[str, Content, List[Content], List[Turn]] +InteractionInput = str | Content | list[Content] | list[Turn] class InteractionsAPIResponse(BaseLiteLLMOpenAIResponseObject): @@ -1101,18 +1066,18 @@ class InteractionsAPIResponse(BaseLiteLLMOpenAIResponseObject): Both fields are kept here so callers work with either schema. """ - id: Optional[str] = None - object: Optional[str] = "interaction" - model: Optional[str] = None - agent: Optional[str] = None - status: Optional[str] = None - created: Optional[str] = None - updated: Optional[str] = None + id: str | None = None + object: str | None = "interaction" + model: str | None = None + agent: str | None = None + status: str | None = None + created: str | None = None + updated: str | None = None # Legacy schema field (Api-Revision: 2026-05-07). Remove after June 8, 2026. - outputs: Optional[List[Dict[str, Any]]] = None + outputs: list[dict[str, Any]] | None = None # New schema field (Api-Revision: 2026-05-20). - steps: Optional[List[Dict[str, Any]]] = None - usage: Optional[Dict[str, Any]] = None + steps: list[dict[str, Any]] | None = None + usage: dict[str, Any] | None = None _hidden_params: dict = PrivateAttr(default_factory=dict) @@ -1132,25 +1097,25 @@ class InteractionsAPIStreamingResponse(BaseLiteLLMOpenAIResponseObject): - error """ - event_type: Optional[str] = None - id: Optional[str] = None - object: Optional[str] = "interaction" - model: Optional[str] = None - agent: Optional[str] = None - status: Optional[str] = None - created: Optional[str] = None - updated: Optional[str] = None + event_type: str | None = None + id: str | None = None + object: str | None = "interaction" + model: str | None = None + agent: str | None = None + status: str | None = None + created: str | None = None + updated: str | None = None # Legacy schema field (Api-Revision: 2026-05-07). Remove after June 8, 2026. - outputs: Optional[List[Dict[str, Any]]] = None + outputs: list[dict[str, Any]] | None = None # New schema field (Api-Revision: 2026-05-20). - steps: Optional[List[Dict[str, Any]]] = None - usage: Optional[Dict[str, Any]] = None - delta: Optional[Dict[str, Any]] = None + steps: list[dict[str, Any]] | None = None + usage: dict[str, Any] | None = None + delta: dict[str, Any] | None = None # New schema streaming fields - index: Optional[int] = None - step: Optional[Dict[str, Any]] = None - interaction_id: Optional[str] = None - interaction: Optional[Dict[str, Any]] = None + index: int | None = None + step: dict[str, Any] | None = None + interaction_id: str | None = None + interaction: dict[str, Any] | None = None _hidden_params: dict = PrivateAttr(default_factory=dict) @@ -1159,7 +1124,7 @@ class DeleteInteractionResult(BaseLiteLLMOpenAIResponseObject): """Result of deleting an interaction.""" success: bool = True - id: Optional[str] = None + id: str | None = None _hidden_params: dict = PrivateAttr(default_factory=dict) @@ -1167,8 +1132,8 @@ class DeleteInteractionResult(BaseLiteLLMOpenAIResponseObject): class CancelInteractionResult(BaseLiteLLMOpenAIResponseObject): """Result of cancelling an interaction.""" - id: Optional[str] = None - status: Optional[str] = None + id: str | None = None + status: str | None = None _hidden_params: dict = PrivateAttr(default_factory=dict) @@ -1176,7 +1141,7 @@ class CancelInteractionResult(BaseLiteLLMOpenAIResponseObject): # Backwards compatibility aliases InteractionTool = Tool InteractionToolChoiceConfig: Final = ToolChoiceConfig -InteractionsAPIOptionalRequestParams = Dict[str, Any] +InteractionsAPIOptionalRequestParams = dict[str, Any] # Agent interaction execution environment -InteractionEnvironment = Union[str, Dict[str, Any]] +InteractionEnvironment = str | dict[str, Any] diff --git a/litellm/types/litellm_core_utils/streaming_chunk_builder_utils.py b/litellm/types/litellm_core_utils/streaming_chunk_builder_utils.py index c9f9d4e6baa..6846e4a91d4 100644 --- a/litellm/types/litellm_core_utils/streaming_chunk_builder_utils.py +++ b/litellm/types/litellm_core_utils/streaming_chunk_builder_utils.py @@ -1,5 +1,3 @@ -from typing import TYPE_CHECKING, Optional - from typing_extensions import TypedDict from ..utils import CompletionTokensDetails, PromptTokensDetailsWrapper, ServerToolUse @@ -8,10 +6,10 @@ from ..utils import CompletionTokensDetails, PromptTokensDetailsWrapper, ServerT class UsagePerChunk(TypedDict): prompt_tokens: int completion_tokens: int - cache_creation_input_tokens: Optional[int] - cache_read_input_tokens: Optional[int] - server_tool_use: Optional[ServerToolUse] - web_search_requests: Optional[int] - completion_tokens_details: Optional[CompletionTokensDetails] - prompt_tokens_details: Optional[PromptTokensDetailsWrapper] - cost: Optional[float] + cache_creation_input_tokens: int | None + cache_read_input_tokens: int | None + server_tool_use: ServerToolUse | None + web_search_requests: int | None + completion_tokens_details: CompletionTokensDetails | None + prompt_tokens_details: PromptTokensDetailsWrapper | None + cost: float | None diff --git a/litellm/types/llms/aiml.py b/litellm/types/llms/aiml.py index d5781add184..c23a62b7688 100644 --- a/litellm/types/llms/aiml.py +++ b/litellm/types/llms/aiml.py @@ -1,5 +1,3 @@ -from typing import Dict, Optional, Union - from typing_extensions import TypedDict @@ -19,11 +17,11 @@ class AimlImageGenerationRequestParams(TypedDict, total=False): model: str # Required: flux-pro/v1.1 prompt: str # Required: Text prompt (max 4000 chars) - image_size: Union[ - AimlImageSize, str - ] # Custom size or predefined: square_hd, square, portrait_4_3, portrait_16_9, landscape_4_3, landscape_16_9 - safety_tolerance: Optional[str] # 1-6, default 2 (1=strict, 6=permissive) - output_format: Optional[str] # jpeg or png, default jpeg - num_images: Optional[int] # 1-4, default 1 - seed: Optional[int] # Min 1, for reproducibility - enable_safety_checker: Optional[bool] # Default true + image_size: ( + AimlImageSize | str + ) # Custom size or predefined: square_hd, square, portrait_4_3, portrait_16_9, landscape_4_3, landscape_16_9 + safety_tolerance: str | None # 1-6, default 2 (1=strict, 6=permissive) + output_format: str | None # jpeg or png, default jpeg + num_images: int | None # 1-4, default 1 + seed: int | None # Min 1, for reproducibility + enable_safety_checker: bool | None # Default true diff --git a/litellm/types/llms/anthropic.py b/litellm/types/llms/anthropic.py index 95f8db66eda..bb861030d86 100644 --- a/litellm/types/llms/anthropic.py +++ b/litellm/types/llms/anthropic.py @@ -1,8 +1,9 @@ +from collections.abc import Iterable from enum import Enum -from typing import Any, Dict, Final, Iterable, List, Optional, Union +from typing import Any, Final, Literal from pydantic import BaseModel, ConfigDict -from typing_extensions import Literal, NotRequired, Required, TypedDict +from typing_extensions import NotRequired, Required, TypedDict from .openai import ( ChatCompletionCachedContent, @@ -20,12 +21,12 @@ class AnthropicMessagesToolChoice(TypedDict, total=False): AnthropicInputSchema = TypedDict( "AnthropicInputSchema", { - "type": Optional[str], - "properties": Optional[dict], - "additionalProperties": Optional[bool], - "required": Optional[List[str]], - "$defs": Optional[Dict], - "strict": Optional[bool], + "type": str | None, + "properties": dict | None, + "additionalProperties": bool | None, + "required": list[str] | None, + "$defs": dict | None, + "strict": bool | None, }, total=False, ) @@ -46,67 +47,67 @@ class AnthropicOutputConfig(TypedDict, total=False): class AnthropicMessagesTool(TypedDict, total=False): name: Required[str] description: str - input_schema: Optional[AnthropicInputSchema] + input_schema: AnthropicInputSchema | None type: Literal["custom"] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + cache_control: dict | ChatCompletionCachedContent | None defer_loading: bool - allowed_callers: Optional[List[str]] - input_examples: Optional[List[Dict[str, Any]]] + allowed_callers: list[str] | None + input_examples: list[dict[str, Any]] | None class AnthropicComputerTool(TypedDict, total=False): display_width_px: Required[int] display_height_px: Required[int] display_number: int - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + cache_control: dict | ChatCompletionCachedContent | None type: Required[str] name: Required[str] class AnthropicWebSearchUserLocation(TypedDict, total=False): - city: Optional[str] - country: Optional[str] - region: Optional[str] - timezone: Optional[str] + city: str | None + country: str | None + region: str | None + timezone: str | None type: Required[Literal["approximate"]] class AnthropicWebSearchTool(TypedDict, total=False): name: Required[Literal["web_search"]] type: Required[str] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] - max_uses: Optional[int] - user_location: Optional[AnthropicWebSearchUserLocation] - defer_loading: Optional[bool] - allowed_callers: Optional[List[str]] - input_examples: Optional[List[Dict[str, Any]]] + cache_control: dict | ChatCompletionCachedContent | None + max_uses: int | None + user_location: AnthropicWebSearchUserLocation | None + defer_loading: bool | None + allowed_callers: list[str] | None + input_examples: list[dict[str, Any]] | None class AnthropicHostedTools(TypedDict, total=False): # for bash_tool and text_editor type: Required[str] name: Required[str] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] - defer_loading: Optional[bool] - allowed_callers: Optional[List[str]] - input_examples: Optional[List[Dict[str, Any]]] + cache_control: dict | ChatCompletionCachedContent | None + defer_loading: bool | None + allowed_callers: list[str] | None + input_examples: list[dict[str, Any]] | None class AnthropicCodeExecutionTool(TypedDict, total=False): type: Required[str] name: Required[Literal["code_execution"]] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] - defer_loading: Optional[bool] - allowed_callers: Optional[List[str]] - input_examples: Optional[List[Dict[str, Any]]] + cache_control: dict | ChatCompletionCachedContent | None + defer_loading: bool | None + allowed_callers: list[str] | None + input_examples: list[dict[str, Any]] | None class AnthropicMemoryTool(TypedDict, total=False): type: Required[str] name: Required[Literal["memory"]] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] - defer_loading: Optional[bool] - allowed_callers: Optional[List[str]] - input_examples: Optional[List[Dict[str, Any]]] + cache_control: dict | ChatCompletionCachedContent | None + defer_loading: bool | None + allowed_callers: list[str] | None + input_examples: list[dict[str, Any]] | None class AnthropicToolSearchToolRegex(TypedDict, total=False): @@ -121,13 +122,13 @@ class AnthropicToolSearchToolBM25(TypedDict, total=False): type: Required[Literal["tool_search_tool_bm25_20251119"]] name: Required[str] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] - defer_loading: Optional[bool] - allowed_callers: Optional[List[str]] - input_examples: Optional[List[Dict[str, Any]]] + cache_control: dict | ChatCompletionCachedContent | None + defer_loading: bool | None + allowed_callers: list[str] | None + input_examples: list[dict[str, Any]] | None -ANTHROPIC_ADVISOR_TOOL_TYPE: Final[Literal["advisor_20260301"]] = "advisor_20260301" +ANTHROPIC_ADVISOR_TOOL_TYPE: Final = "advisor_20260301" class AnthropicAdvisorTool(TypedDict, total=False): @@ -136,8 +137,8 @@ class AnthropicAdvisorTool(TypedDict, total=False): type: Required[Literal["advisor_20260301"]] name: Required[Literal["advisor"]] model: Required[str] - max_uses: Optional[int] - caching: Optional[dict] + max_uses: int | None + caching: dict | None class ToolReference(TypedDict, total=False): @@ -160,31 +161,31 @@ class CodeExecutionToolCaller(TypedDict, total=False): tool_id: Required[str] # ID of the code execution tool that made the call -ToolCaller = Union[DirectToolCaller, CodeExecutionToolCaller] +ToolCaller = DirectToolCaller | CodeExecutionToolCaller class AnthropicContainer(TypedDict, total=False): """Container metadata for code execution.""" id: Required[str] - expires_at: Optional[str] # ISO 8601 timestamp + expires_at: str | None # ISO 8601 timestamp -AllAnthropicToolsValues = Union[ - AnthropicComputerTool, - AnthropicHostedTools, - AnthropicMessagesTool, - AnthropicWebSearchTool, - AnthropicCodeExecutionTool, - AnthropicMemoryTool, - AnthropicToolSearchToolRegex, - AnthropicToolSearchToolBM25, - AnthropicAdvisorTool, -] +AllAnthropicToolsValues = ( + AnthropicComputerTool + | AnthropicHostedTools + | AnthropicMessagesTool + | AnthropicWebSearchTool + | AnthropicCodeExecutionTool + | AnthropicMemoryTool + | AnthropicToolSearchToolRegex + | AnthropicToolSearchToolBM25 + | AnthropicAdvisorTool +) class AnthropicMcpServerToolConfiguration(TypedDict, total=False): - allowed_tools: Optional[List[str]] + allowed_tools: list[str] | None class AnthropicMcpServerTool(TypedDict, total=False): @@ -198,7 +199,7 @@ class AnthropicMcpServerTool(TypedDict, total=False): class AnthropicMessagesTextParam(TypedDict, total=False): type: Required[Literal["text"]] text: Required[str] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + cache_control: dict | ChatCompletionCachedContent | None class AnthropicMessagesToolUseParam(TypedDict, total=False): @@ -206,20 +207,20 @@ class AnthropicMessagesToolUseParam(TypedDict, total=False): id: str name: str input: dict - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] - caller: Optional[ToolCaller] + cache_control: dict | ChatCompletionCachedContent | None + caller: ToolCaller | None -AnthropicMessagesAssistantMessageValues = Union[ - AnthropicMessagesTextParam, - AnthropicMessagesToolUseParam, - ChatCompletionThinkingBlock, - ChatCompletionRedactedThinkingBlock, -] +AnthropicMessagesAssistantMessageValues = ( + AnthropicMessagesTextParam + | AnthropicMessagesToolUseParam + | ChatCompletionThinkingBlock + | ChatCompletionRedactedThinkingBlock +) class AnthopicMessagesAssistantMessageParam(TypedDict, total=False): - content: Required[Union[str, Iterable[AnthropicMessagesAssistantMessageValues]]] + content: Required[str | Iterable[AnthropicMessagesAssistantMessageValues]] """The contents of the system message.""" role: Required[Literal["assistant"]] @@ -252,19 +253,13 @@ class AnthropicContentParamSourceFileId(TypedDict): class AnthropicMessagesContainerUploadParam(TypedDict, total=False): type: Required[Literal["container_upload"]] file_id: str - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + cache_control: dict | ChatCompletionCachedContent | None class AnthropicMessagesImageParam(TypedDict, total=False): type: Required[Literal["image"]] - source: Required[ - Union[ - AnthropicContentParamSource, - AnthropicContentParamSourceFileId, - AnthropicContentParamSourceUrl, - ] - ] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + source: Required[AnthropicContentParamSource | AnthropicContentParamSourceFileId | AnthropicContentParamSourceUrl] + cache_control: dict | ChatCompletionCachedContent | None class CitationsObject(TypedDict): @@ -280,7 +275,7 @@ class AnthropicCitationPageLocation(TypedDict, total=False): type: Literal["page_location"] cited_text: str # The exact text being cited (not counted towards output tokens) document_index: int # Index referencing the cited document - document_title: Optional[str] # Title of the cited document + document_title: str | None # Title of the cited document start_page_number: int # 1-indexed starting page end_page_number: int # Exclusive ending page @@ -294,65 +289,53 @@ class AnthropicCitationCharLocation(TypedDict, total=False): type: Literal["char_location"] cited_text: str # The exact text being cited (not counted towards output tokens) document_index: int # Index referencing the cited document - document_title: Optional[str] # Title of the cited document + document_title: str | None # Title of the cited document start_char_index: int # Starting character index for the citation end_char_index: int # Ending character index for the citation # Union type for all citation formats -AnthropicCitation = Union[AnthropicCitationPageLocation, AnthropicCitationCharLocation] +AnthropicCitation = AnthropicCitationPageLocation | AnthropicCitationCharLocation class AnthropicMessagesDocumentParam(TypedDict, total=False): type: Required[Literal["document"]] - source: Required[ - Union[ - AnthropicContentParamSource, - AnthropicContentParamSourceFileId, - AnthropicContentParamSourceUrl, - ] - ] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + source: Required[AnthropicContentParamSource | AnthropicContentParamSourceFileId | AnthropicContentParamSourceUrl] + cache_control: dict | ChatCompletionCachedContent | None title: str context: str - citations: Optional[CitationsObject] + citations: CitationsObject | None class AnthropicMessagesToolResultContent(TypedDict, total=False): type: Required[Literal["text"]] text: Required[str] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + cache_control: dict | ChatCompletionCachedContent | None class AnthropicMessagesToolResultParam(TypedDict, total=False): type: Required[Literal["tool_result"]] tool_use_id: Required[str] is_error: bool - content: Union[ - str, - Iterable[ - Union[ - AnthropicMessagesToolResultContent, - AnthropicMessagesImageParam, - AnthropicMessagesDocumentParam, - ] - ], - ] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + content: ( + str + | Iterable[AnthropicMessagesToolResultContent | AnthropicMessagesImageParam | AnthropicMessagesDocumentParam] + ) + cache_control: dict | ChatCompletionCachedContent | None -AnthropicMessagesUserMessageValues = Union[ - AnthropicMessagesTextParam, - AnthropicMessagesImageParam, - AnthropicMessagesToolResultParam, - AnthropicMessagesDocumentParam, - AnthropicMessagesContainerUploadParam, -] +AnthropicMessagesUserMessageValues = ( + AnthropicMessagesTextParam + | AnthropicMessagesImageParam + | AnthropicMessagesToolResultParam + | AnthropicMessagesDocumentParam + | AnthropicMessagesContainerUploadParam +) class AnthropicMessagesUserMessageParam(TypedDict, total=False): role: Required[Literal["user"]] - content: Required[Union[str, Iterable[AnthropicMessagesUserMessageValues]]] + content: Required[str | Iterable[AnthropicMessagesUserMessageValues]] class AnthropicMetadata(TypedDict, total=False): @@ -362,38 +345,38 @@ class AnthropicMetadata(TypedDict, total=False): class AnthropicSystemMessageContent(TypedDict, total=False): type: str text: str - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + cache_control: dict | ChatCompletionCachedContent | None -AllAnthropicMessageValues = Union[AnthropicMessagesUserMessageParam, AnthopicMessagesAssistantMessageParam] +AllAnthropicMessageValues = AnthropicMessagesUserMessageParam | AnthopicMessagesAssistantMessageParam class AnthropicMessagesRequestOptionalParams(TypedDict, total=False): - max_tokens: Optional[int] - metadata: Optional[Union[AnthropicMetadata, Dict]] - stop_sequences: Optional[List[str]] - stream: Optional[bool] - system: Optional[Union[str, List]] - temperature: Optional[float] - thinking: Optional[Dict] - tool_choice: Optional[Union[AnthropicMessagesToolChoice, Dict]] - tools: Optional[List[Union[AllAnthropicToolsValues, Dict]]] - top_k: Optional[int] - inference_geo: Optional[str] - top_p: Optional[float] - mcp_servers: Optional[List[AnthropicMcpServerTool]] - context_management: Optional[Dict[str, Any]] - container: Optional[Dict[str, Any]] # Container config with skills for code execution - output_format: Optional[AnthropicOutputSchema] # Structured outputs support - speed: Optional[str] # Fast mode support for Opus models - output_config: Optional[AnthropicOutputConfig] # Configuration for Claude's output behavior - cache_control: Optional[Dict[str, Any]] # Automatic prompt caching - reasoning_effort: Optional[str] + max_tokens: int | None + metadata: AnthropicMetadata | dict | None + stop_sequences: list[str] | None + stream: bool | None + system: str | list | None + temperature: float | None + thinking: dict | None + tool_choice: AnthropicMessagesToolChoice | dict | None + tools: list[AllAnthropicToolsValues | dict] | None + top_k: int | None + inference_geo: str | None + top_p: float | None + mcp_servers: list[AnthropicMcpServerTool] | None + context_management: dict[str, Any] | None + container: dict[str, Any] | None # Container config with skills for code execution + output_format: AnthropicOutputSchema | None # Structured outputs support + speed: str | None # Fast mode support for Opus models + output_config: AnthropicOutputConfig | None # Configuration for Claude's output behavior + cache_control: dict[str, Any] | None # Automatic prompt caching + reasoning_effort: str | None class AnthropicMessagesRequest(AnthropicMessagesRequestOptionalParams, total=False): model: Required[str] - messages: Required[Union[List[AllAnthropicMessageValues], List[Dict]]] + messages: Required[list[AllAnthropicMessageValues] | list[dict]] # litellm param - used for tracking litellm proxy metadata in the request litellm_metadata: dict @@ -445,13 +428,13 @@ StreamingContentBlockDeltaType = Literal["text_delta", "input_json_delta", "thin class ContentBlockDelta(TypedDict): type: Literal["content_block_delta"] index: int - delta: Union[ - ContentTextBlockDelta, - ContentJsonBlockDelta, - ContentCitationsBlockDelta, - ContentThinkingBlockDelta, - ContentThinkingSignatureBlockDelta, - ] + delta: ( + ContentTextBlockDelta + | ContentJsonBlockDelta + | ContentCitationsBlockDelta + | ContentThinkingBlockDelta + | ContentThinkingSignatureBlockDelta + ) class ContentBlockStop(TypedDict): @@ -471,7 +454,7 @@ class ToolUseBlock(TypedDict): name: str type: Literal["tool_use"] - caller: Optional[ToolCaller] + caller: ToolCaller | None class TextBlock(TypedDict): @@ -494,13 +477,13 @@ class ContentBlockStartText(TypedDict): content_block: TextBlock -ContentBlockContentBlockDict = Union[ToolUseBlock, TextBlock, ChatCompletionThinkingBlock] +ContentBlockContentBlockDict = ToolUseBlock | TextBlock | ChatCompletionThinkingBlock -ContentBlockStart = Union[ContentBlockStartToolUse, ContentBlockStartText] +ContentBlockStart = ContentBlockStartToolUse | ContentBlockStartText class MessageDelta(TypedDict, total=False): - stop_reason: Optional[str] + stop_reason: str | None class UsageDelta(TypedDict, total=False): @@ -521,20 +504,20 @@ class AppliedEdit(TypedDict, total=False): summary_input_tokens: int summary_output_tokens: int error: str - warnings: List[str] + warnings: list[str] class ContextManagementResponse(TypedDict, total=False): """Response ``context_management`` with ``applied_edits``.""" - applied_edits: List[AppliedEdit] + applied_edits: list[AppliedEdit] class CompactionBlock(TypedDict, total=False): """Synthesized ``compaction`` content block (compact_20260112).""" type: Required[Literal["compaction"]] - content: Optional[str] + content: str | None class UsageIteration(TypedDict, total=False): @@ -562,9 +545,9 @@ class MessageChunk(TypedDict, total=False): type: str role: str model: str - content: List - stop_reason: Optional[str] - stop_sequence: Optional[str] + content: list + stop_reason: str | None + stop_sequence: str | None usage: UsageDelta @@ -603,7 +586,7 @@ class AnthropicResponseContentBlockToolUse(BaseModel): id: str name: str input: dict - provider_specific_fields: Optional[Dict[str, Any]] = None + provider_specific_fields: dict[str, Any] | None = None model_config = ConfigDict(extra="allow") # Allow provider_specific_fields @@ -611,7 +594,7 @@ class AnthropicResponseContentBlockToolUse(BaseModel): class AnthropicResponseContentBlockThinking(BaseModel): type: Literal["thinking"] thinking: str - signature: Optional[str] + signature: str | None class AnthropicResponseContentBlockRedactedThinking(BaseModel): @@ -639,23 +622,21 @@ class AnthropicResponse(BaseModel): role: Literal["assistant"] """Conversational role of the generated message. This will always be "assistant".""" - content: List[ - Union[ - AnthropicResponseContentBlockText, - AnthropicResponseContentBlockToolUse, - AnthropicResponseContentBlockThinking, - AnthropicResponseContentBlockRedactedThinking, - ] + content: list[ + AnthropicResponseContentBlockText + | AnthropicResponseContentBlockToolUse + | AnthropicResponseContentBlockThinking + | AnthropicResponseContentBlockRedactedThinking ] """Content generated by the model.""" model: str """The model that handled the request.""" - stop_reason: Optional[AnthropicFinishReason] + stop_reason: AnthropicFinishReason | None """The reason that we stopped.""" - stop_sequence: Optional[str] + stop_sequence: str | None """Which custom stop sequence was generated, if any.""" usage: AnthropicResponseUsageBlock diff --git a/litellm/types/llms/anthropic_messages/anthropic_request.py b/litellm/types/llms/anthropic_messages/anthropic_request.py index 4f31e9a5097..cbdd1c4446a 100644 --- a/litellm/types/llms/anthropic_messages/anthropic_request.py +++ b/litellm/types/llms/anthropic_messages/anthropic_request.py @@ -1,5 +1,3 @@ -from typing import Optional - from pydantic import BaseModel @@ -10,4 +8,4 @@ class AnthropicMetadata(BaseModel): https://docs.anthropic.com/en/api/messages#body-metadata-user-id """ - user_id: Optional[str] = None + user_id: str | None = None diff --git a/litellm/types/llms/anthropic_messages/anthropic_response.py b/litellm/types/llms/anthropic_messages/anthropic_response.py index e432e25b6ca..679948c5235 100644 --- a/litellm/types/llms/anthropic_messages/anthropic_response.py +++ b/litellm/types/llms/anthropic_messages/anthropic_response.py @@ -1,6 +1,6 @@ -from typing import Any, Dict, List, Literal, Optional, Union +from typing import Any, Literal, TypeAlias -from typing_extensions import NotRequired, TypeAlias, TypedDict +from typing_extensions import NotRequired, TypedDict from litellm.types.llms.anthropic import ( AnthropicResponseContentBlockText, @@ -14,7 +14,7 @@ class AnthropicResponseTextBlock(TypedDict, total=False): Anthropic Response Text Block: https://docs.anthropic.com/en/api/messages """ - citations: Optional[List[Dict[str, Any]]] + citations: list[dict[str, Any]] | None text: str type: Literal["text"] @@ -24,9 +24,9 @@ class AnthropicResponseToolUseBlock(TypedDict, total=False): Anthropic Response Tool Use Block: https://docs.anthropic.com/en/api/messages """ - id: Optional[str] - input: Optional[str] - name: Optional[str] + id: str | None + input: str | None + name: str | None type: Literal["tool_use"] @@ -35,8 +35,8 @@ class AnthropicResponseThinkingBlock(TypedDict, total=False): Anthropic Response Thinking Block: https://docs.anthropic.com/en/api/messages """ - signature: Optional[str] - thinking: Optional[str] + signature: str | None + thinking: str | None type: Literal["thinking"] @@ -45,16 +45,16 @@ class AnthropicResponseRedactedThinkingBlock(TypedDict, total=False): Anthropic Response Redacted Thinking Block: https://docs.anthropic.com/en/api/messages """ - data: Optional[str] + data: str | None type: Literal["redacted_thinking"] -AnthropicResponseContentBlock: TypeAlias = Union[ - AnthropicResponseTextBlock, - AnthropicResponseToolUseBlock, - AnthropicResponseThinkingBlock, - AnthropicResponseRedactedThinkingBlock, -] +AnthropicResponseContentBlock: TypeAlias = ( + AnthropicResponseTextBlock + | AnthropicResponseToolUseBlock + | AnthropicResponseThinkingBlock + | AnthropicResponseRedactedThinkingBlock +) class AnthropicUsage(TypedDict, total=False): @@ -77,20 +77,15 @@ class AnthropicMessagesResponse(TypedDict, total=False): Anthropic Messages API Response: https://docs.anthropic.com/en/api/messages """ - content: Optional[ - List[ - Union[ - AnthropicResponseContentBlock, - AnthropicResponseContentBlockText, - AnthropicResponseContentBlockToolUse, - ] - ] - ] + content: ( + list[AnthropicResponseContentBlock | AnthropicResponseContentBlockText | AnthropicResponseContentBlockToolUse] + | None + ) id: str - model: Optional[str] # This represents the Model type from Anthropic - role: Optional[Literal["assistant"]] - stop_reason: Optional[Literal["end_turn", "max_tokens", "stop_sequence", "tool_use"]] - stop_sequence: Optional[str] - type: Optional[Literal["message"]] - usage: Optional[AnthropicUsage] + model: str | None # This represents the Model type from Anthropic + role: Literal["assistant"] | None + stop_reason: Literal["end_turn", "max_tokens", "stop_sequence", "tool_use"] | None + stop_sequence: str | None + type: Literal["message"] | None + usage: AnthropicUsage | None context_management: NotRequired[ContextManagementResponse] diff --git a/litellm/types/llms/anthropic_skills.py b/litellm/types/llms/anthropic_skills.py index 22257888493..51eefe7154f 100644 --- a/litellm/types/llms/anthropic_skills.py +++ b/litellm/types/llms/anthropic_skills.py @@ -2,33 +2,33 @@ Type definitions for Anthropic Skills API """ -from typing import Any, Dict, List, Literal, Optional, Union +from typing import Any -from pydantic import BaseModel, Field -from typing_extensions import Required, TypedDict +from pydantic import BaseModel +from typing_extensions import TypedDict # Skills API Request Types class CreateSkillRequest(TypedDict, total=False): """Request parameters for creating a skill""" - display_title: Optional[str] + display_title: str | None """Display title for the skill (optional)""" - files: Optional[List[Any]] + files: list[Any] | None """Files to upload for the skill. All files must be in the same top-level directory and must include a SKILL.md file at the root.""" class ListSkillsParams(TypedDict, total=False): """Query parameters for listing skills""" - limit: Optional[int] + limit: int | None """Number of results to return per page. Maximum value is 100. Defaults to 20.""" - page: Optional[str] + page: str | None """Pagination token for fetching a specific page of results""" - source: Optional[str] + source: str | None """Filter skills by source ('custom' or 'anthropic')""" @@ -42,10 +42,10 @@ class Skill(BaseModel): created_at: str """ISO 8601 timestamp of when the skill was created""" - display_title: Optional[str] = None + display_title: str | None = None """Display title for the skill""" - latest_version: Optional[str] = None + latest_version: str | None = None """The latest version identifier for the skill""" source: str @@ -61,10 +61,10 @@ class Skill(BaseModel): class ListSkillsResponse(BaseModel): """Response from listing skills""" - data: List[Skill] + data: list[Skill] """List of skills""" - next_page: Optional[str] = None + next_page: str | None = None """Pagination token for the next page""" has_more: bool = False @@ -85,16 +85,16 @@ class DeleteSkillResponse(BaseModel): class CreateSkillVersionRequest(TypedDict, total=False): """Request parameters for creating a skill version""" - display_title: Optional[str] + display_title: str | None """Display title for this version""" - description: Optional[str] + description: str | None """Description of this version""" - instructions: Optional[str] + instructions: str | None """Instructions for this version""" - metadata: Optional[Dict[str, Any]] + metadata: dict[str, Any] | None """Additional metadata""" @@ -110,16 +110,16 @@ class SkillVersion(BaseModel): created_at: str """ISO 8601 timestamp of when the version was created""" - display_title: Optional[str] = None + display_title: str | None = None """Display title for this version""" - description: Optional[str] = None + description: str | None = None """Description of this version""" - instructions: Optional[str] = None + instructions: str | None = None """Instructions for this version""" - metadata: Optional[Dict[str, Any]] = None + metadata: dict[str, Any] | None = None """Additional metadata""" type: str = "skill.version" @@ -132,13 +132,13 @@ class ListSkillVersionsResponse(BaseModel): object: str = "list" """Object type, always 'list'""" - data: List[SkillVersion] + data: list[SkillVersion] """List of skill versions""" - first_id: Optional[str] = None + first_id: str | None = None """ID of the first version in the list""" - last_id: Optional[str] = None + last_id: str | None = None """ID of the last version in the list""" has_more: bool = False diff --git a/litellm/types/llms/anthropic_tool_search.py b/litellm/types/llms/anthropic_tool_search.py index d8ad9784ddd..160326fca40 100644 --- a/litellm/types/llms/anthropic_tool_search.py +++ b/litellm/types/llms/anthropic_tool_search.py @@ -4,7 +4,7 @@ Tool Search Beta Header Configuration Reference: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool """ -from typing import Dict, Final +from typing import Final from litellm.types.utils import LlmProviders @@ -15,7 +15,7 @@ TOOL_SEARCH_BETA_HEADER_BEDROCK: Final = "tool-search-tool-2025-10-19" # Mapping of custom_llm_provider -> tool search beta header -TOOL_SEARCH_BETA_HEADER_BY_PROVIDER: Final[Dict[str, str]] = { +TOOL_SEARCH_BETA_HEADER_BY_PROVIDER: Final[dict[str, str]] = { LlmProviders.ANTHROPIC.value: TOOL_SEARCH_BETA_HEADER_ANTHROPIC, LlmProviders.AZURE.value: TOOL_SEARCH_BETA_HEADER_ANTHROPIC, LlmProviders.AZURE_AI.value: TOOL_SEARCH_BETA_HEADER_ANTHROPIC, diff --git a/litellm/types/llms/azure_ai.py b/litellm/types/llms/azure_ai.py index ddc9dbe3c55..722bc53f429 100644 --- a/litellm/types/llms/azure_ai.py +++ b/litellm/types/llms/azure_ai.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Final, Iterable, List, Literal, Optional, Union +from typing import Literal from typing_extensions import Required, TypedDict @@ -12,6 +12,6 @@ EncodingFormat = Literal["base64", "binary", "float", "int8", "ubinary", "uint8" class ImageEmbeddingRequest(TypedDict, total=False): - input: Required[List[ImageEmbeddingInput]] + input: Required[list[ImageEmbeddingInput]] dimensions: int encoding_format: EncodingFormat diff --git a/litellm/types/llms/base.py b/litellm/types/llms/base.py index 13e011a4831..4b4bd6bca6e 100644 --- a/litellm/types/llms/base.py +++ b/litellm/types/llms/base.py @@ -1,4 +1,4 @@ -from typing import Any, Final, Optional, Union +from typing import Any, Final from openai._models import BaseModel as OpenAIObject from pydantic import BaseModel, ConfigDict @@ -11,14 +11,14 @@ class LiteLLMPydanticObjectBase(BaseModel): def json(self, **kwargs): # type: ignore try: - return self.model_dump(**kwargs) # noqa + return self.model_dump(**kwargs) except Exception: # if using pydantic v1 return self.dict(**kwargs) def fields_set(self): try: - return self.model_fields_set # noqa + return self.model_fields_set except Exception: # if using pydantic v1 return self.__fields_set__ @@ -35,7 +35,7 @@ class BaseLiteLLMOpenAIResponseObject(BaseModel): def get(self, key, default=None): return self.__dict__.get(key, default) - def __contains__(self, key): + def __contains__(self, key) -> bool: return key in self.__dict__ def items(self): @@ -43,11 +43,11 @@ class BaseLiteLLMOpenAIResponseObject(BaseModel): class HiddenParams(OpenAIObject): - original_response: Optional[Union[str, Any]] = None - model_id: Optional[str] = None # used in Router for individual deployments - api_base: Optional[str] = None # returns api base used for making completion call - _response_ms: Optional[float] = None - response_cost: Optional[float] = None + original_response: str | Any | None = None + model_id: str | None = None # used in Router for individual deployments + api_base: str | None = None # returns api base used for making completion call + _response_ms: float | None = None + response_cost: float | None = None model_config = ConfigDict(extra="allow", protected_namespaces=()) @@ -59,13 +59,13 @@ class HiddenParams(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() diff --git a/litellm/types/llms/bedrock.py b/litellm/types/llms/bedrock.py index 88594bce1cb..1bf8ba513c2 100644 --- a/litellm/types/llms/bedrock.py +++ b/litellm/types/llms/bedrock.py @@ -1,7 +1,7 @@ import json -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import TYPE_CHECKING, Any, Final, Literal -from typing_extensions import TYPE_CHECKING, Required, TypedDict, override +from typing_extensions import Required, TypedDict, override from .openai import ChatCompletionToolCallChunk @@ -17,14 +17,14 @@ class SystemContentBlock(TypedDict, total=False): class SourceBlock(TypedDict): - bytes: Optional[str] # base 64 encoded string + bytes: str | None # base 64 encoded string BedrockImageTypes = Literal["png", "jpeg", "gif", "webp"] class ImageBlock(TypedDict): - format: Union[BedrockImageTypes, str] + format: BedrockImageTypes | str source: SourceBlock @@ -32,7 +32,7 @@ BedrockVideoTypes = Literal["mp4", "mov", "mkv", "webm", "flv", "mpeg", "mpg", " class VideoBlock(TypedDict): - format: Union[BedrockVideoTypes, str] + format: BedrockVideoTypes | str source: SourceBlock @@ -40,7 +40,7 @@ BedrockDocumentTypes = Literal["pdf", "csv", "doc", "docx", "xls", "xlsx", "html class DocumentBlock(TypedDict): - format: Union[BedrockDocumentTypes, str] + format: BedrockDocumentTypes | str source: SourceBlock name: str @@ -55,7 +55,7 @@ class SearchResultBlock(TypedDict, total=False): source: str title: str - content: List[dict] + content: list[dict] citations: dict @@ -68,7 +68,7 @@ class ToolResultContentBlock(TypedDict, total=False): class ToolResultBlock(TypedDict, total=False): - content: Required[List[ToolResultContentBlock]] + content: Required[list[ToolResultContentBlock]] toolUseId: Required[str] status: Literal["success", "error"] @@ -185,8 +185,8 @@ class CitationsContentBlock(TypedDict, total=False): } """ - content: List[CitationGeneratedContentBlock] - citations: List[CitationReferenceBlock] + content: list[CitationGeneratedContentBlock] + citations: list[CitationReferenceBlock] class ContentBlock(TypedDict, total=False): @@ -203,7 +203,7 @@ class ContentBlock(TypedDict, total=False): class MessageBlock(TypedDict): - content: List[ContentBlock] + content: list[ContentBlock] role: Literal["user", "assistant"] @@ -212,7 +212,7 @@ class ConverseMetricsBlock(TypedDict): class ConverseResponseOutputBlock(TypedDict): - message: Optional[MessageBlock] + message: MessageBlock | None class ConverseTokenUsageBlock(TypedDict): @@ -241,12 +241,12 @@ class ConverseResponseBlock(TypedDict, total=False): class ToolJsonSchemaBlock(TypedDict, total=False): type: Literal["object"] properties: dict - required: List[str] + required: list[str] additionalProperties: bool class ToolInputSchemaBlock(TypedDict): - json: Optional[ToolJsonSchemaBlock] + json: ToolJsonSchemaBlock | None class ToolSpecBlock(TypedDict, total=False): @@ -272,9 +272,9 @@ class SystemToolBlock(TypedDict, total=False): class ToolBlock(TypedDict, total=False): - toolSpec: Optional[ToolSpecBlock] - systemTool: Optional[SystemToolBlock] - cachePoint: Optional[CachePointBlock] + toolSpec: ToolSpecBlock | None + systemTool: SystemToolBlock | None + cachePoint: CachePointBlock | None class BedrockToolSpec(dict): @@ -284,7 +284,7 @@ class BedrockToolSpec(dict): name: str, description: str, parameters: dict, - strict: Optional[bool], + strict: bool | None, supports_strict_tools: bool, ) -> None: json_schema: Final[ToolJsonSchemaBlock] = { @@ -318,8 +318,8 @@ class ToolChoiceValuesBlock(TypedDict, total=False): class ToolConfigBlock(TypedDict, total=False): - tools: Required[List[ToolBlock]] - toolChoice: Union[str, ToolChoiceValuesBlock] + tools: Required[list[ToolBlock]] + toolChoice: str | ToolChoiceValuesBlock class GuardrailConfigBlock(TypedDict, total=False): @@ -330,7 +330,7 @@ class GuardrailConfigBlock(TypedDict, total=False): class InferenceConfig(TypedDict, total=False): maxTokens: int - stopSequences: List[str] + stopSequences: list[str] temperature: float topP: float topK: int @@ -346,7 +346,7 @@ class ToolUseBlockStartEvent(TypedDict): class ContentBlockStartEvent(TypedDict, total=False): - toolUse: Optional[ToolUseBlockStartEvent] + toolUse: ToolUseBlockStartEvent | None reasoningContent: BedrockConverseReasoningContentBlockDelta @@ -395,19 +395,19 @@ class OutputConfigBlock(TypedDict, total=False): class CommonRequestObject(TypedDict, total=False): # common request object across sync + async flows additionalModelRequestFields: dict - additionalModelResponseFieldPaths: List[str] + additionalModelResponseFieldPaths: list[str] inferenceConfig: InferenceConfig - system: List[SystemContentBlock] + system: list[SystemContentBlock] toolConfig: ToolConfigBlock - guardrailConfig: Optional[GuardrailConfigBlock] - performanceConfig: Optional[PerformanceConfigBlock] - serviceTier: Optional[ServiceTierBlock] - requestMetadata: Optional[Dict[str, str]] - outputConfig: Optional[OutputConfigBlock] + guardrailConfig: GuardrailConfigBlock | None + performanceConfig: PerformanceConfigBlock | None + serviceTier: ServiceTierBlock | None + requestMetadata: dict[str, str] | None + outputConfig: OutputConfigBlock | None class RequestObject(CommonRequestObject, total=False): - messages: Required[List[MessageBlock]] + messages: Required[list[MessageBlock]] class BedrockInvokeNovaRequest(TypedDict, total=False): @@ -415,19 +415,19 @@ class BedrockInvokeNovaRequest(TypedDict, total=False): Request object for sending `nova` requests to `/bedrock/invoke/` """ - messages: List[MessageBlock] + messages: list[MessageBlock] inferenceConfig: InferenceConfig - system: List[SystemContentBlock] + system: list[SystemContentBlock] toolConfig: ToolConfigBlock - guardrailConfig: Optional[GuardrailConfigBlock] + guardrailConfig: GuardrailConfigBlock | None class GenericStreamingChunk(TypedDict): text: Required[str] - tool_use: Optional[ChatCompletionToolCallChunk] + tool_use: ChatCompletionToolCallChunk | None is_finished: Required[bool] finish_reason: Required[str] - usage: Optional[ConverseTokenUsageBlock] + usage: ConverseTokenUsageBlock | None index: int @@ -440,10 +440,10 @@ class ServerSentEvent: def __init__( self, *, - event: Optional[str] = None, - data: Optional[str] = None, - id: Optional[str] = None, - retry: Optional[int] = None, + event: str | None = None, + data: str | None = None, + id: str | None = None, + retry: int | None = None, ) -> None: if data is None: data = "" @@ -454,15 +454,15 @@ class ServerSentEvent: self._retry = retry @property - def event(self) -> Optional[str]: + def event(self) -> str | None: return self._event @property - def id(self) -> Optional[str]: + def id(self) -> str | None: return self._id @property - def retry(self) -> Optional[int]: + def retry(self) -> int | None: return self._retry @property @@ -481,8 +481,8 @@ COHERE_EMBEDDING_INPUT_TYPES = Literal["search_document", "search_query", "class class CohereEmbeddingRequest(TypedDict, total=False): - texts: List[str] - images: List[str] + texts: list[str] + images: list[str] input_type: Required[COHERE_EMBEDDING_INPUT_TYPES] truncate: Literal["NONE", "START", "END"] embedding_types: Literal["float", "int8", "uint8", "binary", "ubinary"] @@ -494,26 +494,26 @@ class CohereEmbeddingRequestWithModel(CohereEmbeddingRequest): class CohereEmbeddingResponse(TypedDict): - embeddings: List[List[float]] + embeddings: list[list[float]] id: str response_type: Literal["embedding_floats"] - texts: List[str] + texts: list[str] class AmazonTitanV2EmbeddingRequest(TypedDict, total=False): inputText: Required[str] dimensions: int normalize: bool - embeddingTypes: List[Literal["float", "binary"]] + embeddingTypes: list[Literal["float", "binary"]] class AmazonTitanV2EmbeddingsByType(TypedDict, total=False): - binary: List[int] # Array of integers for binary format - float: List[float] # Array of floats for float format + binary: list[int] # Array of integers for binary format + float: list[float] # Array of floats for float format class AmazonTitanV2EmbeddingResponse(TypedDict, total=False): - embedding: List[float] # Legacy field - array of floats (backward compatibility) + embedding: list[float] # Legacy field - array of floats (backward compatibility) embeddingsByType: AmazonTitanV2EmbeddingsByType # New format per AWS schema inputTextTokenCount: Required[int] # Always present in AWS response @@ -523,7 +523,7 @@ class AmazonTitanG1EmbeddingRequest(TypedDict): class AmazonTitanG1EmbeddingResponse(TypedDict): - embedding: List[float] + embedding: list[float] inputTextTokenCount: int @@ -538,7 +538,7 @@ class AmazonTitanMultimodalEmbeddingRequest(TypedDict, total=False): class AmazonTitanMultimodalEmbeddingResponse(TypedDict): - embedding: List[float] + embedding: list[float] inputTextTokenCount: int message: str # Specifies any errors that occur during generation. @@ -567,11 +567,11 @@ class TwelveLabsMarengoEmbeddingRequest(TypedDict, total=False): lengthSec: float useFixedLengthSec: float minClipSec: int - embeddingOption: List[TWELVELABS_EMBEDDING_OPTIONS] + embeddingOption: list[TWELVELABS_EMBEDDING_OPTIONS] class TwelveLabsMarengoEmbeddingResponse(TypedDict): - embedding: List[float] + embedding: list[float] embeddingOption: TWELVELABS_EMBEDDING_OPTIONS startSec: float endSec: float @@ -597,10 +597,10 @@ class TwelveLabsAsyncInvokeStatusResponse(TypedDict): status: str # "InProgress" | "Completed" | "Failed" submitTime: str lastModifiedTime: str - endTime: Optional[str] + endTime: str | None outputDataConfig: TwelveLabsOutputDataConfig - clientRequestToken: Optional[str] - failureMessage: Optional[str] + clientRequestToken: str | None + failureMessage: str | None # Amazon Nova Multimodal Embeddings types @@ -706,12 +706,12 @@ class NovaEmbeddingRequest(TypedDict, total=False): class NovaEmbeddingItem(TypedDict, total=False): embeddingType: NOVA_EMBEDDING_TYPES - embedding: Required[List[float]] + embedding: Required[list[float]] truncatedCharLength: int # Only for text class NovaEmbeddingResponse(TypedDict): - embeddings: List[NovaEmbeddingItem] + embeddings: list[NovaEmbeddingItem] class NovaS3OutputDataConfig(TypedDict): @@ -728,11 +728,9 @@ class NovaAsyncInvokeRequest(TypedDict): outputDataConfig: NovaOutputDataConfig -AmazonEmbeddingRequest = Union[ - AmazonTitanMultimodalEmbeddingRequest, - AmazonTitanV2EmbeddingRequest, - AmazonTitanG1EmbeddingRequest, -] +AmazonEmbeddingRequest = ( + AmazonTitanMultimodalEmbeddingRequest | AmazonTitanV2EmbeddingRequest | AmazonTitanG1EmbeddingRequest +) class AmazonStability3TextToImageRequest(TypedDict, total=False): @@ -757,9 +755,9 @@ class AmazonStability3TextToImageResponse(TypedDict, total=False): Ref: https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-diffusion-3-text-image.html """ - images: List[str] - seeds: List[str] - finish_reasons: List[str] + images: list[str] + seeds: list[str] + finish_reasons: list[str] class AmazonTitanTextToImageParams(TypedDict, total=False): @@ -776,8 +774,6 @@ class AmazonNovaCanvasRequestBase(TypedDict, total=False): Base class for Amazon Nova Canvas API requests """ - pass - class AmazonNovaCanvasImageGenerationConfig(TypedDict, total=False): """ @@ -823,7 +819,7 @@ class AmazonNovaCanvasColorGuidedGenerationParams(TypedDict, total=False): Params for Amazon Nova Canvas Color Guided Generation API """ - colors: List[str] + colors: list[str] referenceImage: str text: str negativeText: str @@ -848,7 +844,7 @@ class AmazonNovaCanvasTextToImageResponse(TypedDict, total=False): Ref: https://docs.aws.amazon.com/nova/latest/userguide/image-gen-req-resp-structure.html """ - images: List[str] + images: list[str] class AmazonNovaCanvasInpaintingParams(TypedDict, total=False): @@ -945,15 +941,15 @@ class BedrockRerankRequest(TypedDict): Request for Bedrock Rerank API """ - queries: List[BedrockRerankQuery] + queries: list[BedrockRerankQuery] rerankingConfiguration: BedrockRerankConfiguration - sources: List[BedrockRerankSource] + sources: list[BedrockRerankSource] class AmazonDeepSeekR1StreamingResponse(TypedDict): generation: str generation_token_count: int - stop_reason: Optional[str] + stop_reason: str | None prompt_token_count: int @@ -976,7 +972,7 @@ class BedrockS3OutputDataConfig(TypedDict, total=False): """S3 output data configuration for Bedrock batch jobs.""" s3Uri: str - s3EncryptionKeyId: Optional[str] + s3EncryptionKeyId: str | None class BedrockOutputDataConfig(TypedDict): @@ -1002,9 +998,9 @@ class BedrockCreateBatchRequest(TypedDict, total=False): modelId: str inputDataConfig: BedrockInputDataConfig outputDataConfig: BedrockOutputDataConfig - timeoutDurationInHours: Optional[int] - clientRequestToken: Optional[str] - tags: Optional[List[BedrockTag]] + timeoutDurationInHours: int | None + clientRequestToken: str | None + tags: list[BedrockTag] | None BedrockBatchJobStatus = Literal["Submitted", "InProgress", "Completed", "Failed", "Stopping", "Stopped"] @@ -1034,20 +1030,20 @@ class BedrockGetBatchResponse(TypedDict, total=False): modelId: str roleArn: str status: BedrockBatchJobStatus - message: Optional[str] - submitTime: Optional[str] - lastModifiedTime: Optional[str] - endTime: Optional[str] + message: str | None + submitTime: str | None + lastModifiedTime: str | None + endTime: str | None inputDataConfig: BedrockInputDataConfig outputDataConfig: BedrockOutputDataConfig - timeoutDurationInHours: Optional[int] - clientRequestToken: Optional[str] + timeoutDurationInHours: int | None + clientRequestToken: str | None class BedrockToolBlock(TypedDict, total=False): - toolSpec: Optional[ToolSpecBlock] - systemTool: Optional[SystemToolBlock] # For Nova grounding - cachePoint: Optional[CachePointBlock] + toolSpec: ToolSpecBlock | None + systemTool: SystemToolBlock | None # For Nova grounding + cachePoint: CachePointBlock | None class BedrockInvokeAnthropicMessagesRequest(TypedDict, total=False): @@ -1079,9 +1075,9 @@ class BedrockInvokeAnthropicMessagesRequest(TypedDict, total=False): messages: list # Documented optional fields - anthropic_beta: List[str] + anthropic_beta: list[str] system: object # str or list[TextBlock] - stop_sequences: List[str] + stop_sequences: list[str] temperature: float top_p: float top_k: int diff --git a/litellm/types/llms/bedrock_agentcore.py b/litellm/types/llms/bedrock_agentcore.py index cd6b75f2ac3..c71d434ea78 100644 --- a/litellm/types/llms/bedrock_agentcore.py +++ b/litellm/types/llms/bedrock_agentcore.py @@ -4,9 +4,9 @@ Type definitions for AWS Bedrock AgentCore API. https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agentcore_InvokeAgentRuntime.html """ -from typing import Dict, List, Optional +from typing import Literal -from typing_extensions import Literal, TypedDict +from typing_extensions import TypedDict # Request Types @@ -85,25 +85,25 @@ class AgentCoreEventPayload(TypedDict, total=False): """Union payload for different event types.""" # messageStart event - messageStart: Optional[AgentCoreMessageStart] + messageStart: AgentCoreMessageStart | None # contentBlockDelta event - contentBlockDelta: Optional[AgentCoreContentBlockDeltaEvent] + contentBlockDelta: AgentCoreContentBlockDeltaEvent | None # contentBlockStop event - contentBlockStop: Optional[AgentCoreContentBlockStop] + contentBlockStop: AgentCoreContentBlockStop | None # messageStop event - messageStop: Optional[AgentCoreMessageStop] + messageStop: AgentCoreMessageStop | None # metadata event - metadata: Optional[AgentCoreMetadata] + metadata: AgentCoreMetadata | None class AgentCoreEvent(TypedDict, total=False): """SSE event structure from AgentCore.""" - event: Optional[AgentCoreEventPayload] + event: AgentCoreEventPayload | None class AgentCoreContentBlock(TypedDict): @@ -116,7 +116,7 @@ class AgentCoreMessage(TypedDict): """Complete message structure.""" role: Literal["assistant"] - content: List[AgentCoreContentBlock] + content: list[AgentCoreContentBlock] class AgentCoreFinalMessage(TypedDict): @@ -130,5 +130,5 @@ class AgentCoreParsedResponse(TypedDict): """Parsed response from SSE stream.""" content: str - usage: Optional[AgentCoreUsage] - final_message: Optional[AgentCoreMessage] + usage: AgentCoreUsage | None + final_message: AgentCoreMessage | None diff --git a/litellm/types/llms/bedrock_invoke_agents.py b/litellm/types/llms/bedrock_invoke_agents.py index aaf09858be9..62f3c18ca7a 100644 --- a/litellm/types/llms/bedrock_invoke_agents.py +++ b/litellm/types/llms/bedrock_invoke_agents.py @@ -4,7 +4,7 @@ Type definitions for AWS Bedrock Invoke Agent API responses. https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_InvokeAgent.html """ -from typing import Any, Dict, Final, List, Optional, Union +from typing import Any, Final from typing_extensions import TypedDict @@ -22,58 +22,58 @@ class InvokeAgentUsage(TypedDict): inputTokens: int outputTokens: int - model: Optional[str] + model: str | None class InvokeAgentMetadata(TypedDict, total=False): """Metadata from model invocation.""" - clientRequestId: Optional[str] - endTime: Optional[str] - startTime: Optional[str] - totalTimeMs: Optional[int] - usage: Optional[InvokeAgentUsage] + clientRequestId: str | None + endTime: str | None + startTime: str | None + totalTimeMs: int | None + usage: InvokeAgentUsage | None class InvokeAgentModelInvocationInput(TypedDict, total=False): """Model invocation input details.""" - foundationModel: Optional[str] - inferenceConfiguration: Optional[Dict[str, Any]] - text: Optional[str] - traceId: Optional[str] - type: Optional[str] + foundationModel: str | None + inferenceConfiguration: dict[str, Any] | None + text: str | None + traceId: str | None + type: str | None class InvokeAgentModelInvocationOutput(TypedDict, total=False): """Model invocation output details.""" - metadata: Optional[InvokeAgentMetadata] - parsedResponse: Optional[Dict[str, Any]] - rawResponse: Optional[Dict[str, Any]] - reasoningContent: Optional[Dict[str, Any]] - traceId: Optional[str] + metadata: InvokeAgentMetadata | None + parsedResponse: dict[str, Any] | None + rawResponse: dict[str, Any] | None + reasoningContent: dict[str, Any] | None + traceId: str | None class InvokeAgentOrchestrationTrace(TypedDict, total=False): """Orchestration trace information.""" - modelInvocationInput: Optional[InvokeAgentModelInvocationInput] - modelInvocationOutput: Optional[InvokeAgentModelInvocationOutput] + modelInvocationInput: InvokeAgentModelInvocationInput | None + modelInvocationOutput: InvokeAgentModelInvocationOutput | None class InvokeAgentPreProcessingTrace(TypedDict, total=False): """Pre-processing trace information.""" - modelInvocationInput: Optional[InvokeAgentModelInvocationInput] - modelInvocationOutput: Optional[InvokeAgentModelInvocationOutput] + modelInvocationInput: InvokeAgentModelInvocationInput | None + modelInvocationOutput: InvokeAgentModelInvocationOutput | None class InvokeAgentTrace(TypedDict, total=False): """Trace information container.""" - orchestrationTrace: Optional[InvokeAgentOrchestrationTrace] - preProcessingTrace: Optional[InvokeAgentPreProcessingTrace] + orchestrationTrace: InvokeAgentOrchestrationTrace | None + preProcessingTrace: InvokeAgentPreProcessingTrace | None class InvokeAgentCallerChain(TypedDict, total=False): @@ -88,7 +88,7 @@ class InvokeAgentTracePayload(TypedDict, total=False): agentAliasId: str agentId: str agentVersion: str - callerChain: List[InvokeAgentCallerChain] + callerChain: list[InvokeAgentCallerChain] eventTime: str sessionId: str trace: InvokeAgentTrace @@ -104,26 +104,26 @@ class InvokeAgentEventPayload(TypedDict, total=False): """Union type for different event payload types.""" # Trace event fields - agentAliasId: Optional[str] - agentId: Optional[str] - agentVersion: Optional[str] - callerChain: Optional[List[InvokeAgentCallerChain]] - eventTime: Optional[str] - sessionId: Optional[str] - trace: Optional[InvokeAgentTrace] + agentAliasId: str | None + agentId: str | None + agentVersion: str | None + callerChain: list[InvokeAgentCallerChain] | None + eventTime: str | None + sessionId: str | None + trace: InvokeAgentTrace | None # Chunk event fields - bytes: Optional[str] + bytes: str | None class InvokeAgentEvent(TypedDict, total=False): """Complete event structure for AWS Invoke Agent responses.""" headers: InvokeAgentEventHeaders - payload: Optional[InvokeAgentEventPayload] + payload: InvokeAgentEventPayload | None # Type aliases for convenience -InvokeAgentEventList = List[InvokeAgentEvent] +InvokeAgentEventList = list[InvokeAgentEvent] InvokeAgentTraceEvent: Final = InvokeAgentEvent # When headers.event_type == 'trace' InvokeAgentChunkEvent: Final = InvokeAgentEvent # When headers.event_type == 'chunk' diff --git a/litellm/types/llms/cohere.py b/litellm/types/llms/cohere.py index bbf554ed6b7..92d1a8a573d 100644 --- a/litellm/types/llms/cohere.py +++ b/litellm/types/llms/cohere.py @@ -1,6 +1,6 @@ -from typing import Final, Iterable, List, Optional, Union +from typing import Literal -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import Required, TypedDict class CallObject(TypedDict): @@ -10,12 +10,12 @@ class CallObject(TypedDict): class ToolResultObject(TypedDict): call: CallObject - outputs: List[dict] + outputs: list[dict] class ChatHistoryToolResult(TypedDict, total=False): role: Required[Literal["TOOL"]] - tool_results: List[ToolResultObject] + tool_results: list[ToolResultObject] class ToolCallObject(TypedDict): @@ -26,22 +26,22 @@ class ToolCallObject(TypedDict): class ChatHistoryUser(TypedDict, total=False): role: Required[Literal["USER"]] message: str - tool_calls: List[ToolCallObject] + tool_calls: list[ToolCallObject] class ChatHistorySystem(TypedDict, total=False): role: Required[Literal["SYSTEM"]] message: str - tool_calls: List[ToolCallObject] + tool_calls: list[ToolCallObject] class ChatHistoryChatBot(TypedDict, total=False): role: Required[Literal["CHATBOT"]] message: str - tool_calls: List[ToolCallObject] + tool_calls: list[ToolCallObject] -ChatHistory = List[Union[ChatHistorySystem, ChatHistoryChatBot, ChatHistoryUser, ChatHistoryToolResult]] +ChatHistory = list[ChatHistorySystem | ChatHistoryChatBot | ChatHistoryUser | ChatHistoryToolResult] class CohereV2ChatResponseMessageToolCallFunction(TypedDict, total=False): @@ -63,10 +63,10 @@ class CohereV2ChatResponseMessageContent(TypedDict): class CohereV2ChatResponseMessage(TypedDict, total=False): role: Required[Literal["assistant"]] - tool_calls: List[CohereV2ChatResponseMessageToolCall] + tool_calls: list[CohereV2ChatResponseMessageToolCall] tool_plan: str - content: List[CohereV2ChatResponseMessageContent] - citations: List[dict] + content: list[CohereV2ChatResponseMessageContent] + citations: list[dict] class CohereV2ChatResponseUsageBilledUnits(TypedDict, total=False): @@ -87,9 +87,9 @@ class CohereV2ChatResponseUsage(TypedDict, total=False): class CohereV2ChatResponseLogProbs(TypedDict, total=False): - token_ids: Required[List[int]] + token_ids: Required[list[int]] text: str - logprobs: List[float] + logprobs: list[float] class CohereV2ChatResponse(TypedDict): diff --git a/litellm/types/llms/custom_http.py b/litellm/types/llms/custom_http.py index 9e1fd37bc0d..d80d7410aae 100644 --- a/litellm/types/llms/custom_http.py +++ b/litellm/types/llms/custom_http.py @@ -33,4 +33,4 @@ class httpxSpecialProvider(str, Enum): ModelCostMap = "model_cost_map" -VerifyTypes = Union[str, bool, ssl.SSLContext] +VerifyTypes = str | bool | ssl.SSLContext diff --git a/litellm/types/llms/custom_llm.py b/litellm/types/llms/custom_llm.py index d5499a41944..e57a7a28007 100644 --- a/litellm/types/llms/custom_llm.py +++ b/litellm/types/llms/custom_llm.py @@ -1,6 +1,4 @@ -from typing import List - -from typing_extensions import Dict, Required, TypedDict, override +from typing_extensions import TypedDict from litellm.llms.custom_llm import CustomLLM diff --git a/litellm/types/llms/databricks.py b/litellm/types/llms/databricks.py index 46f988ae4a0..e87a684aab8 100644 --- a/litellm/types/llms/databricks.py +++ b/litellm/types/llms/databricks.py @@ -1,34 +1,27 @@ -import json -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Literal from pydantic import BaseModel from typing_extensions import ( - Protocol, Required, - Self, TypedDict, - TypeGuard, - get_origin, - override, - runtime_checkable, ) -from .openai import ChatCompletionToolCallChunk, ChatCompletionUsageBlock +from .openai import ChatCompletionUsageBlock class GenericStreamingChunk(TypedDict, total=False): text: Required[str] is_finished: Required[bool] - finish_reason: Required[Optional[str]] - logprobs: Optional[BaseModel] - original_chunk: Optional[BaseModel] - usage: Optional[BaseModel] + finish_reason: Required[str | None] + logprobs: BaseModel | None + original_chunk: BaseModel | None + usage: BaseModel | None class DatabricksTextContent(TypedDict, total=False): type: Literal["text"] text: Required[str] - citations: Optional[List[Dict[str, Any]]] + citations: list[dict[str, Any]] | None class DatabricksReasoningSummary(TypedDict): @@ -39,18 +32,18 @@ class DatabricksReasoningSummary(TypedDict): class DatabricksReasoningContent(TypedDict, total=False): type: Literal["reasoning"] - summary: Required[List[DatabricksReasoningSummary]] - citations: Optional[List[Dict[str, Any]]] + summary: Required[list[DatabricksReasoningSummary]] + citations: list[dict[str, Any]] | None -AllDatabricksContentListValues = Union[DatabricksTextContent, DatabricksReasoningContent] +AllDatabricksContentListValues = DatabricksTextContent | DatabricksReasoningContent -AllDatabricksContentValues = Union[str, List[AllDatabricksContentListValues]] +AllDatabricksContentValues = str | list[AllDatabricksContentListValues] class DatabricksFunction(TypedDict, total=False): name: Required[str] - description: Union[dict, str] + description: dict | str parameters: dict strict: bool @@ -63,13 +56,13 @@ class DatabricksTool(TypedDict): class DatabricksMessage(TypedDict, total=False): role: Required[str] content: Required[AllDatabricksContentValues] - tool_calls: Optional[List[DatabricksTool]] + tool_calls: list[DatabricksTool] | None class DatabricksChoice(TypedDict, total=False): index: Required[int] message: Required[DatabricksMessage] - finish_reason: Required[Optional[str]] + finish_reason: Required[str | None] extra_fields: str @@ -78,5 +71,5 @@ class DatabricksResponse(TypedDict): object: str created: int model: str - choices: List[DatabricksChoice] + choices: list[DatabricksChoice] usage: ChatCompletionUsageBlock diff --git a/litellm/types/llms/gemini.py b/litellm/types/llms/gemini.py index 823b6556154..57fb8b5b0cd 100644 --- a/litellm/types/llms/gemini.py +++ b/litellm/types/llms/gemini.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional +from typing import Any, Literal from typing_extensions import Required, TypedDict @@ -128,7 +128,7 @@ class BidiGenerateContentSetup(TypedDict, total=False): systemInstruction: HttpxContentType """The system instruction to be used for the realtime session.""" - tools: List[Tools] + tools: list[Tools] """The tools to be used for the realtime session.""" realtimeInputConfig: BidiGenerateContentRealtimeInputConfig @@ -163,51 +163,51 @@ class GeminiImageGenerationInstance(TypedDict): class GeminiImageGenerationParameters(BaseModel): """Parameters for Gemini image generation request""" - sampleCount: Optional[int] = None + sampleCount: int | None = None """Number of images to generate (maps to OpenAI 'n' parameter)""" - aspectRatio: Optional[str] = None + aspectRatio: str | None = None """Aspect ratio for generated images (e.g., '1:1', '16:9', '9:16', '4:3', '3:4')""" - imageSize: Optional[str] = None + imageSize: str | None = None """Image size for generated images (e.g., '1K', '2K')""" - personGeneration: Optional[str] = None + personGeneration: str | None = None """Controls person generation in images""" # Additional parameters that might be passed through - background: Optional[str] = None + background: str | None = None """Background specification""" - input_fidelity: Optional[str] = None + input_fidelity: str | None = None """Input fidelity specification""" - moderation: Optional[str] = None + moderation: str | None = None """Moderation settings""" - output_compression: Optional[str] = None + output_compression: str | None = None """Output compression settings""" - output_format: Optional[str] = None + output_format: str | None = None """Output format specification""" - quality: Optional[str] = None + quality: str | None = None """Quality settings""" - response_format: Optional[str] = None + response_format: str | None = None """Response format specification""" - style: Optional[str] = None + style: str | None = None """Style specification""" - user: Optional[str] = None + user: str | None = None """User specification""" class GeminiImageGenerationRequest(BaseModel): """Complete request body for Gemini image generation""" - instances: List[GeminiImageGenerationInstance] + instances: list[GeminiImageGenerationInstance] parameters: GeminiImageGenerationParameters @@ -221,13 +221,13 @@ class GeminiGeneratedImage(TypedDict): class GeminiImageGenerationPrediction(TypedDict): """Prediction object containing generated images""" - generatedImages: List[GeminiGeneratedImage] + generatedImages: list[GeminiGeneratedImage] class GeminiImageGenerationResponse(TypedDict): """Complete response body from Gemini image generation API""" - predictions: List[GeminiImageGenerationPrediction] + predictions: list[GeminiImageGenerationPrediction] # Video Generation Types @@ -235,7 +235,7 @@ class GeminiVideoGenerationInstance(TypedDict, total=False): """Instance data for Gemini video generation request""" prompt: Required[str] - image: Dict[str, Any] + image: dict[str, Any] class GeminiVideoGenerationParameters(BaseModel): @@ -245,43 +245,43 @@ class GeminiVideoGenerationParameters(BaseModel): See: Veo 3/3.1 parameter guide. """ - aspectRatio: Optional[str] = None + aspectRatio: str | None = None """Aspect ratio for generated video (e.g., '16:9', '9:16').""" - durationSeconds: Optional[int] = None + durationSeconds: int | None = None """ Length of the generated video in seconds (e.g., 4, 5, 6, 8). Must be 8 when using extension/interpolation or referenceImages. """ - resolution: Optional[str] = None + resolution: str | None = None """ Video resolution (e.g., '720p', '1080p'). '1080p' only supports 8s duration; extension only supports '720p'. """ - negativePrompt: Optional[str] = None + negativePrompt: str | None = None """Text describing what not to include in the video.""" - lastFrame: Optional[Any] = None + lastFrame: Any | None = None """ The final image for interpolation video to transition. Should be used with the 'image' parameter. """ - referenceImages: Optional[list] = None + referenceImages: list | None = None """ Up to three images to be used as style/content references. Only supported in Veo 3.1 (list of VideoGenerationReferenceImage objects). """ - video: Optional[Any] = None + video: Any | None = None """ Video to be used for video extension (Video object). Only supported in Veo 3.1 & Veo 3 Fast. """ - personGeneration: Optional[str] = None + personGeneration: str | None = None """ Controls the generation of people. Text-to-video & Extension: "allow_all" only @@ -293,8 +293,8 @@ class GeminiVideoGenerationParameters(BaseModel): class GeminiVideoGenerationRequest(BaseModel): """Complete request body for Gemini video generation""" - instances: List[GeminiVideoGenerationInstance] - parameters: Optional[GeminiVideoGenerationParameters] = None + instances: list[GeminiVideoGenerationInstance] + parameters: GeminiVideoGenerationParameters | None = None # Video Generation Operation Response Types @@ -315,7 +315,7 @@ class GeminiGeneratedVideoSample(BaseModel): class GeminiGenerateVideoResponse(BaseModel): """Generate video response containing the samples""" - generatedSamples: List[GeminiGeneratedVideoSample] + generatedSamples: list[GeminiGeneratedVideoSample] """List of generated video samples""" @@ -329,9 +329,9 @@ class GeminiOperationResponse(BaseModel): class GeminiOperationMetadata(BaseModel): """Metadata for the operation""" - createTime: Optional[str] = None + createTime: str | None = None """Creation timestamp""" - model: Optional[str] = None + model: str | None = None """Model used for generation""" @@ -348,11 +348,11 @@ class GeminiLongRunningOperationResponse(BaseModel): done: bool = False """Whether the operation is complete""" - metadata: Optional[GeminiOperationMetadata] = None + metadata: GeminiOperationMetadata | None = None """Operation metadata""" - response: Optional[GeminiOperationResponse] = None + response: GeminiOperationResponse | None = None """Response object when operation is complete""" - error: Optional[Dict[str, Any]] = None + error: dict[str, Any] | None = None """Error details if operation failed""" diff --git a/litellm/types/llms/langgraph.py b/litellm/types/llms/langgraph.py index 9286ca463ee..7e34329992d 100644 --- a/litellm/types/llms/langgraph.py +++ b/litellm/types/llms/langgraph.py @@ -4,9 +4,9 @@ Type definitions for LangGraph API. LangGraph provides a streaming and non-streaming API for running agents. """ -from typing import Any, Dict, List, Optional +from typing import Any, Literal -from typing_extensions import Literal, TypedDict +from typing_extensions import TypedDict # Request Types @@ -20,7 +20,7 @@ class LangGraphMessage(TypedDict, total=False): class LangGraphInput(TypedDict, total=False): """Input structure for LangGraph request.""" - messages: List[LangGraphMessage] + messages: list[LangGraphMessage] class LangGraphRequest(TypedDict, total=False): @@ -28,9 +28,9 @@ class LangGraphRequest(TypedDict, total=False): assistant_id: str input: LangGraphInput - stream_mode: Optional[str] - config: Optional[Dict[str, Any]] - metadata: Optional[Dict[str, Any]] + stream_mode: str | None + config: dict[str, Any] | None + metadata: dict[str, Any] | None # Response Types - Streaming @@ -47,15 +47,15 @@ class LangGraphResponseMessage(TypedDict, total=False): type: str content: str - id: Optional[str] - name: Optional[str] + id: str | None + name: str | None class LangGraphResponse(TypedDict, total=False): """Non-streaming response structure from LangGraph.""" - messages: List[LangGraphResponseMessage] - values: Dict[str, Any] + messages: list[LangGraphResponseMessage] + values: dict[str, Any] # Parsed response for internal use @@ -64,4 +64,4 @@ class LangGraphParsedResponse(TypedDict): content: str role: str - usage: Optional[Dict[str, int]] + usage: dict[str, int] | None diff --git a/litellm/types/llms/mistral.py b/litellm/types/llms/mistral.py index 34f501ef69f..e64aa9c13ab 100644 --- a/litellm/types/llms/mistral.py +++ b/litellm/types/llms/mistral.py @@ -1,17 +1,17 @@ -from typing import List, Literal, Optional, Union +from typing import Literal from typing_extensions import TypedDict class FunctionCall(TypedDict): - name: Optional[str] - arguments: Optional[Union[str, dict]] + name: str | None + arguments: str | dict | None class MistralToolCallMessage(TypedDict): - id: Optional[str] + id: str | None type: Literal["function"] - function: Optional[FunctionCall] + function: FunctionCall | None class MistralTextBlock(TypedDict): @@ -21,4 +21,4 @@ class MistralTextBlock(TypedDict): class MistralThinkingBlock(TypedDict): type: Literal["thinking"] - thinking: List[MistralTextBlock] + thinking: list[MistralTextBlock] diff --git a/litellm/types/llms/oci.py b/litellm/types/llms/oci.py index cfa7ea79787..ff56d3d183b 100644 --- a/litellm/types/llms/oci.py +++ b/litellm/types/llms/oci.py @@ -1,7 +1,7 @@ from __future__ import annotations from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Literal from pydantic import BaseModel, SerializeAsAny @@ -24,8 +24,6 @@ class OCIVendors(Enum): class OCIContentPart(BaseModel): """Base model for content parts in an OCI message.""" - pass - class OCITextContentPart(OCIContentPart): """Text content part for the OCI API.""" @@ -38,7 +36,7 @@ class OCIImageUrl(BaseModel): """ImageUrl object for OCI API. See: https://docs.oracle.com/en-us/iaas/tools/python/latest/api/generative_ai_inference/models/oci.generative_ai_inference.models.ImageUrl.html""" url: str - detail: Optional[Literal["AUTO", "HIGH", "LOW"]] = None + detail: Literal["AUTO", "HIGH", "LOW"] | None = None class OCIImageContentPart(OCIContentPart): @@ -48,7 +46,7 @@ class OCIImageContentPart(OCIContentPart): imageUrl: OCIImageUrl -OCIContentPartUnion = Union[OCITextContentPart, OCIImageContentPart] +OCIContentPartUnion = OCITextContentPart | OCIImageContentPart # --- Models for Tools and Tool Calls --- @@ -56,7 +54,7 @@ OCIContentPartUnion = Union[OCITextContentPart, OCIImageContentPart] class OCIToolCall(BaseModel): """Represents a tool call made by the model.""" - id: Optional[str] = None # absent in some provider responses (e.g. Google via OCI) + id: str | None = None # absent in some provider responses (e.g. Google via OCI) type: Literal["FUNCTION"] = "FUNCTION" name: str arguments: str # Arguments should be a JSON-serialized string @@ -66,9 +64,9 @@ class OCIToolDefinition(BaseModel): """Defines a tool that can be used by the model.""" type: Literal["FUNCTION"] = "FUNCTION" - name: Optional[str] = None - description: Optional[str] = None - parameters: Optional[dict] = None + name: str | None = None + description: str | None = None + parameters: dict | None = None # --- Message Models (Request and Response) --- @@ -78,9 +76,9 @@ class OCIMessage(BaseModel): """Model for a single message in the request/response payload.""" role: OCIRoles - content: Optional[List[OCIContentPartUnion]] = None - toolCalls: Optional[List[OCIToolCall]] = None - toolCallId: Optional[str] = None + content: list[OCIContentPartUnion] | None = None + toolCalls: list[OCIToolCall] | None = None + toolCallId: str | None = None # --- Request Payload Models --- @@ -90,35 +88,35 @@ class OCIChatRequestPayload(BaseModel): """Internal 'chatRequest' payload for the OCI API.""" apiFormat: str - messages: List[OCIMessage] - tools: Optional[List[OCIToolDefinition]] = None + messages: list[OCIMessage] + tools: list[OCIToolDefinition] | None = None isStream: bool = False - numGenerations: Optional[int] = None - maxTokens: Optional[int] = None + numGenerations: int | None = None + maxTokens: int | None = None # GPT-5+ on OCI rejects maxTokens and requires maxCompletionTokens. - maxCompletionTokens: Optional[int] = None - temperature: Optional[float] = None - topP: Optional[float] = None - stop: Optional[List[str]] = None - seed: Optional[int] = None - frequencyPenalty: Optional[float] = None - presencePenalty: Optional[float] = None + maxCompletionTokens: int | None = None + temperature: float | None = None + topP: float | None = None + stop: list[str] | None = None + seed: int | None = None + frequencyPenalty: float | None = None + presencePenalty: float | None = None # Reasoning-token budget knob (OCI: NONE/MINIMAL/LOW/MEDIUM/HIGH). # Honoured by GPT-5 family, Gemini 2.5, Grok reasoning variants, # Cohere Command-A-Reasoning. Ignored by non-reasoning models. - reasoningEffort: Optional[str] = None - responseFormat: Optional[Dict[str, Any]] = None - toolChoice: Optional[Union[str, Dict[str, Any]]] = None - logitBias: Optional[Dict[str, Any]] = None - logProbs: Optional[int] = None + reasoningEffort: str | None = None + responseFormat: dict[str, Any] | None = None + toolChoice: str | dict[str, Any] | None = None + logitBias: dict[str, Any] | None = None + logProbs: int | None = None class OCIServingMode(BaseModel): """Defines the serving mode and the model to be used.""" servingType: str - endpointId: Optional[str] = None - modelId: Optional[str] = None + endpointId: str | None = None + modelId: str | None = None class OCICompletionPayload(BaseModel): @@ -126,7 +124,7 @@ class OCICompletionPayload(BaseModel): compartmentId: str servingMode: OCIServingMode - chatRequest: Union[OCIChatRequestPayload, CohereChatRequest] + chatRequest: OCIChatRequestPayload | CohereChatRequest # --- API Response Models (Non-streaming) --- @@ -135,14 +133,14 @@ class OCICompletionPayload(BaseModel): class OCICompletionTokenDetails(BaseModel): """Completion token details in the OCI response.""" - acceptedPredictionTokens: Optional[int] = None - reasoningTokens: Optional[int] = None + acceptedPredictionTokens: int | None = None + reasoningTokens: int | None = None class OCIPromptTokensDetails(BaseModel): """Prompt token details in the OCI response.""" - cachedTokens: Optional[int] = None + cachedTokens: int | None = None class OCIResponseUsage(BaseModel): @@ -151,10 +149,10 @@ class OCIResponseUsage(BaseModel): promptTokens: int # completionTokens may be absent for reasoning models when all the output # budget is consumed by reasoning tokens before any visible content is produced. - completionTokens: Optional[int] = None + completionTokens: int | None = None totalTokens: int - completionTokensDetails: Optional[OCICompletionTokenDetails] = None - promptTokensDetails: Optional[OCIPromptTokensDetails] = None + completionTokensDetails: OCICompletionTokenDetails | None = None + promptTokensDetails: OCIPromptTokensDetails | None = None class OCIResponseChoice(BaseModel): @@ -163,9 +161,9 @@ class OCIResponseChoice(BaseModel): index: int # message is absent when a reasoning model exhausts max_tokens in the # reasoning phase without producing any visible content. - message: Optional[OCIMessage] = None - finishReason: Optional[str] = None - logprobs: Optional[Dict[str, Any]] = None + message: OCIMessage | None = None + finishReason: str | None = None + logprobs: dict[str, Any] | None = None class OCIChatResponse(BaseModel): @@ -173,7 +171,7 @@ class OCIChatResponse(BaseModel): apiFormat: str timeCreated: str - choices: List[OCIResponseChoice] + choices: list[OCIResponseChoice] usage: OCIResponseUsage @@ -191,18 +189,18 @@ class OCICompletionResponse(BaseModel): class OCIStreamDelta(BaseModel): """The content delta in a streaming chunk.""" - content: Optional[List[OCIContentPartUnion]] = None - role: Optional[str] = None - toolCalls: Optional[List[OCIToolCall]] = None + content: list[OCIContentPartUnion] | None = None + role: str | None = None + toolCalls: list[OCIToolCall] | None = None class OCIStreamChunk(BaseModel): """Model for a single SSE event chunk from OCI.""" - finishReason: Optional[str] = None - message: Optional[OCIStreamDelta] = None - pad: Optional[str] = None - index: Optional[int] = None + finishReason: str | None = None + message: OCIStreamDelta | None = None + pad: str | None = None + index: int | None = None # --- Cohere-Specific Models --- @@ -212,20 +210,20 @@ class CohereStreamChunk(BaseModel): """Model for a single SSE event chunk from OCI Cohere API.""" apiFormat: str - text: Optional[str] = None - chatHistory: Optional[List[CohereMessage]] = None - finishReason: Optional[str] = None - toolCalls: Optional[List[CohereToolCall]] = None - pad: Optional[str] = None - index: Optional[int] = None + text: str | None = None + chatHistory: list[CohereMessage] | None = None + finishReason: str | None = None + toolCalls: list[CohereToolCall] | None = None + pad: str | None = None + index: int | None = None class CohereMessage(BaseModel): """Base model for Cohere messages.""" role: str - message: Optional[str] = None - toolCalls: Optional[List[CohereToolCall]] = None + message: str | None = None + toolCalls: list[CohereToolCall] | None = None class CohereUserMessage(CohereMessage): @@ -254,7 +252,7 @@ class CohereToolMessage(CohereMessage): """ role: Literal["TOOL"] = "TOOL" - toolResults: List[CohereToolResult] + toolResults: list[CohereToolResult] class CohereParameterDefinition(BaseModel): @@ -270,14 +268,14 @@ class CohereTool(BaseModel): name: str description: str - parameterDefinitions: Dict[str, CohereParameterDefinition] + parameterDefinitions: dict[str, CohereParameterDefinition] class CohereToolCall(BaseModel): """Tool call made by Cohere model.""" name: str - parameters: Dict[str, Any] + parameters: dict[str, Any] class CohereToolResult(BaseModel): @@ -288,7 +286,7 @@ class CohereToolResult(BaseModel): """ call: CohereToolCall - outputs: List[Dict[str, Any]] + outputs: list[dict[str, Any]] class CohereChatRequest(BaseModel): @@ -303,16 +301,16 @@ class CohereChatRequest(BaseModel): # on ``CohereToolMessage``) when this request is serialized via ``model_dump``. # Without it, Pydantic v2 would serialize each element using the declared # ``CohereMessage`` schema and silently drop subclass fields. - chatHistory: Optional[List[SerializeAsAny[CohereMessage]]] = None - maxTokens: Optional[int] = None - temperature: Optional[float] = None - topP: Optional[float] = None - topK: Optional[int] = None - frequencyPenalty: Optional[float] = None - presencePenalty: Optional[float] = None - stopSequences: Optional[List[str]] = None - seed: Optional[int] = None - tools: Optional[List[CohereTool]] = None + chatHistory: list[SerializeAsAny[CohereMessage]] | None = None + maxTokens: int | None = None + temperature: float | None = None + topP: float | None = None + topK: int | None = None + frequencyPenalty: float | None = None + presencePenalty: float | None = None + stopSequences: list[str] | None = None + seed: int | None = None + tools: list[CohereTool] | None = None # NOTE: OCI's Cohere chat endpoint does not accept ``toolChoice`` — see # ``OCIChatConfig.openai_to_oci_cohere_param_map`` which marks # ``tool_choice`` as unsupported. The field is intentionally absent here @@ -320,22 +318,22 @@ class CohereChatRequest(BaseModel): # OCI Cohere responseFormat is {"type": "TEXT" | "JSON_OBJECT", "schema"?: ...}; # there is no JSON_SCHEMA type. The shape is built in # OCIChatConfig._normalize_response_format. - responseFormat: Optional[Dict[str, Any]] = None - preambleOverride: Optional[str] = None - documents: Optional[List[Dict[str, Any]]] = None - searchQueriesOnly: Optional[bool] = None - searchEntryPoint: Optional[str] = None - grounding: Optional[Dict[str, Any]] = None - isEcho: Optional[bool] = None - isSearchQueriesOnly: Optional[bool] = None - isRawPrompting: Optional[bool] = None - isForceSingleStep: Optional[bool] = None - promptTruncation: Optional[str] = None - safetyMode: Optional[str] = None - citationQuality: Optional[str] = None - maxInputTokens: Optional[int] = None - isStream: Optional[bool] = None - streamOptions: Optional[Dict[str, Any]] = None + responseFormat: dict[str, Any] | None = None + preambleOverride: str | None = None + documents: list[dict[str, Any]] | None = None + searchQueriesOnly: bool | None = None + searchEntryPoint: str | None = None + grounding: dict[str, Any] | None = None + isEcho: bool | None = None + isSearchQueriesOnly: bool | None = None + isRawPrompting: bool | None = None + isForceSingleStep: bool | None = None + promptTruncation: str | None = None + safetyMode: str | None = None + citationQuality: str | None = None + maxInputTokens: int | None = None + isStream: bool | None = None + streamOptions: dict[str, Any] | None = None class CohereUsage(BaseModel): @@ -344,8 +342,8 @@ class CohereUsage(BaseModel): promptTokens: int completionTokens: int totalTokens: int - promptTokensDetails: Optional[Dict[str, Any]] = None - completionTokensDetails: Optional[Dict[str, Any]] = None + promptTokensDetails: dict[str, Any] | None = None + completionTokensDetails: dict[str, Any] | None = None class CohereCitation(BaseModel): @@ -354,7 +352,7 @@ class CohereCitation(BaseModel): start: int end: int text: str - document_ids: List[str] + document_ids: list[str] class CohereSearchQuery(BaseModel): @@ -375,18 +373,18 @@ class CohereChatResponse(BaseModel): # via ``handle_cohere_response``'s ``elif oci_finish_reason is not None`` # fallback instead of crashing Pydantic validation. Mirrors # ``CohereStreamChunk.finishReason`` which has always been ``Optional[str]``. - finishReason: Optional[str] = None + finishReason: str | None = None # Optional fields - chatHistory: Optional[List[CohereMessage]] = None - citations: Optional[List[CohereCitation]] = None - documents: Optional[List[Dict[str, Any]]] = None - errorMessage: Optional[str] = None - isSearchRequired: Optional[bool] = None - prompt: Optional[str] = None - searchQueries: Optional[List[CohereSearchQuery]] = None - toolCalls: Optional[List[CohereToolCall]] = None - usage: Optional[CohereUsage] = None + chatHistory: list[CohereMessage] | None = None + citations: list[CohereCitation] | None = None + documents: list[dict[str, Any]] | None = None + errorMessage: str | None = None + isSearchRequired: bool | None = None + prompt: str | None = None + searchQueries: list[CohereSearchQuery] | None = None + toolCalls: list[CohereToolCall] | None = None + usage: CohereUsage | None = None class CohereChatDetails(BaseModel): @@ -415,10 +413,10 @@ class OCIEmbedRequest(BaseModel): compartmentId: str servingMode: OCIServingMode - inputs: List[str] - inputType: Optional[str] = None # SEARCH_DOCUMENT | SEARCH_QUERY | CLASSIFICATION | CLUSTERING | IMAGE - truncate: Optional[str] = "END" # NONE | START | END - outputDimensions: Optional[int] = None # cohere.embed-v4.0+; valid: 256, 512, 1024, 1536 + inputs: list[str] + inputType: str | None = None # SEARCH_DOCUMENT | SEARCH_QUERY | CLASSIFICATION | CLUSTERING | IMAGE + truncate: str | None = "END" # NONE | START | END + outputDimensions: int | None = None # cohere.embed-v4.0+; valid: 256, 512, 1024, 1536 class OCIEmbedUsage(BaseModel): @@ -429,11 +427,11 @@ class OCIEmbedUsage(BaseModel): class OCIEmbedResponse(BaseModel): """Response body from POST /20231130/actions/embedText.""" - id: Optional[str] = None # present in the official SDK response - embeddings: List[List[float]] + id: str | None = None # present in the official SDK response + embeddings: list[list[float]] modelId: str modelVersion: str # OCI returns per-input token counts in inputTextTokenCounts (summed for total usage) - inputTextTokenCounts: Optional[List[int]] = None + inputTextTokenCounts: list[int] | None = None # Some deployments may return a usage object instead - usage: Optional[OCIEmbedUsage] = None + usage: OCIEmbedUsage | None = None diff --git a/litellm/types/llms/ollama.py b/litellm/types/llms/ollama.py index ca28120dd9d..4783eac9a8d 100644 --- a/litellm/types/llms/ollama.py +++ b/litellm/types/llms/ollama.py @@ -1,16 +1,6 @@ -import json -from typing import Any, List, Optional, Union - -from pydantic import BaseModel from typing_extensions import ( - Protocol, Required, - Self, TypedDict, - TypeGuard, - get_origin, - override, - runtime_checkable, ) @@ -27,14 +17,14 @@ class OllamaToolCall(TypedDict): class OllamaVisionModelObject(TypedDict): prompt: str - images: List[str] + images: list[str] class OllamaChatCompletionMessage(TypedDict, total=False): role: Required[str] content: str thinking: str - images: List[str] - tool_calls: List[OllamaToolCall] + images: list[str] + tool_calls: list[OllamaToolCall] tool_name: str tool_call_id: str diff --git a/litellm/types/llms/openai.py b/litellm/types/llms/openai.py index 9441a542fe6..d2dfa03dd3d 100644 --- a/litellm/types/llms/openai.py +++ b/litellm/types/llms/openai.py @@ -1,6 +1,7 @@ +from collections.abc import Iterable, Mapping from enum import Enum from os import PathLike -from typing import Any, Dict, Final, IO, Iterable, List, Literal, Mapping, Optional, Tuple, Union +from typing import IO, Any, Final, Literal, Optional, Union import httpx from openai import Omit @@ -39,7 +40,6 @@ from openai.types.responses.response import ( Response, ResponseOutputItem, Tool, - ToolChoice, ) # Handle OpenAI SDK version compatibility for Text type @@ -51,7 +51,8 @@ except (ImportError, AttributeError): ResponseTextConfigParam as ResponseText, ) -from openai.types.responses import ResponseFunctionToolCall +from typing import Annotated + from openai.types.responses.response_create_params import ( Reasoning, ResponseIncludable, @@ -69,8 +70,6 @@ from pydantic import ( field_validator, ) from typing_extensions import ( - Annotated, - Dict, NotRequired, Required, TypedDict, @@ -86,26 +85,25 @@ from litellm.types.responses.main import ( OutputImageGenerationCall, ) -FileContent = Union[IO[bytes], bytes, PathLike] +FileContent = IO[bytes] | bytes | PathLike -FileTypes = Union[ +FileTypes = ( # file (or bytes) - FileContent, + FileContent # (filename, file (or bytes)) - Tuple[Optional[str], FileContent], + | tuple[str | None, FileContent] # (filename, file (or bytes), content_type) - Tuple[Optional[str], FileContent, Optional[str]], + | tuple[str | None, FileContent, str | None] # (filename, file (or bytes), content_type, headers) - Tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]], -] + | tuple[str | None, FileContent, str | None, Mapping[str, str]] +) -EmbeddingInput = Union[str, List[str]] +EmbeddingInput = str | list[str] class HttpxBinaryResponseContent(_HttpxBinaryResponseContent): _hidden_params: dict = {} - pass class NotGiven: @@ -138,7 +136,7 @@ NOT_GIVEN: Final = NotGiven() class ToolResourcesCodeInterpreter(TypedDict, total=False): - file_ids: List[str] + file_ids: list[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files @@ -147,7 +145,7 @@ class ToolResourcesCodeInterpreter(TypedDict, total=False): class ToolResourcesFileSearchVectorStore(TypedDict, total=False): - file_ids: List[str] + file_ids: list[str] """ A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to add to the vector store. There can be a maximum of 10000 files in a vector @@ -164,7 +162,7 @@ class ToolResourcesFileSearchVectorStore(TypedDict, total=False): class ToolResourcesFileSearch(TypedDict, total=False): - vector_store_ids: List[str] + vector_store_ids: list[str] """ The [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) @@ -197,7 +195,7 @@ class CodeInterpreterToolParam(TypedDict, total=False): """The type of tool being defined: `code_interpreter`""" -AttachmentTool = Union[CodeInterpreterToolParam, FileSearchToolParam] +AttachmentTool = CodeInterpreterToolParam | FileSearchToolParam class Attachment(TypedDict, total=False): @@ -210,12 +208,12 @@ class Attachment(TypedDict, total=False): class ImageFileObject(TypedDict): file_id: Required[str] - detail: Optional[str] + detail: str | None class ImageURLObject(TypedDict, total=False): url: Required[str] - detail: Optional[str] + detail: str | None class ImageURLListItem(TypedDict): @@ -241,18 +239,9 @@ class MessageContentImageURLObject(TypedDict): class MessageData(TypedDict): role: Literal["user", "assistant"] - content: Union[ - str, - List[ - Union[ - MessageContentTextObject, - MessageContentImageFileObject, - MessageContentImageURLObject, - ] - ], - ] - attachments: Optional[List[Attachment]] - metadata: Optional[dict] + content: str | list[MessageContentTextObject | MessageContentImageFileObject | MessageContentImageURLObject] + attachments: list[Attachment] | None + metadata: dict | None class Thread(BaseModel): @@ -262,7 +251,7 @@ class Thread(BaseModel): created_at: int """The Unix timestamp (in seconds) for when the thread was created.""" - metadata: Optional[object] = None + metadata: object | None = None """Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a @@ -312,17 +301,17 @@ class OpenAIFileObject(BaseModel): `fine-tune`, `fine-tune-results`, `vision`, and `user_data`. """ - status: Optional[Literal["uploaded", "processed", "error", "pending"]] = None + status: Literal["uploaded", "processed", "error", "pending"] | None = None """Deprecated. The current status of the file, which can be either `uploaded`, `processed`, `error`, or `pending` (Azure may return `pending` immediately after upload). """ - expires_at: Optional[int] = None + expires_at: int | None = None """The Unix timestamp (in seconds) for when the file will expire.""" - status_details: Optional[str] = None + status_details: str | None = None """Deprecated. For details on why a fine-tuning training file failed validation, see the @@ -331,7 +320,7 @@ class OpenAIFileObject(BaseModel): _hidden_params: dict = {"response_cost": 0.0} # no cost for writing a file - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -345,7 +334,7 @@ class OpenAIFileObject(BaseModel): def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() @@ -387,10 +376,10 @@ class CreateFileRequest(TypedDict, total=False): file: Required[FileTypes] purpose: Required[CREATE_FILE_REQUESTS_PURPOSE] - expires_after: Optional[FileExpiresAfter] - extra_headers: Optional[Dict[str, str]] - extra_body: Optional[Dict[str, str]] - timeout: Optional[float] + expires_after: FileExpiresAfter | None + extra_headers: dict[str, str] | None + extra_body: dict[str, str] | None + timeout: float | None class FileContentRequest(TypedDict, total=False): @@ -408,9 +397,9 @@ class FileContentRequest(TypedDict, total=False): """ file_id: str - extra_headers: Optional[Dict[str, str]] - extra_body: Optional[Dict[str, str]] - timeout: Optional[float] + extra_headers: dict[str, str] | None + extra_body: dict[str, str] | None + timeout: float | None # OpenAI Batches Types @@ -422,11 +411,11 @@ class CreateBatchRequest(TypedDict, total=False): completion_window: Literal["24h"] endpoint: Literal["/v1/chat/completions", "/v1/embeddings", "/v1/completions"] input_file_id: str - metadata: Optional[Dict[str, str]] + metadata: dict[str, str] | None output_expires_after: FileExpiresAfter - extra_headers: Optional[Dict[str, str]] - extra_body: Optional[Dict[str, str]] - timeout: Optional[float] + extra_headers: dict[str, str] | None + extra_body: dict[str, str] | None + timeout: float | None class LiteLLMBatchCreateRequest(CreateBatchRequest, total=False): @@ -439,9 +428,9 @@ class RetrieveBatchRequest(TypedDict, total=False): """ batch_id: str - extra_headers: Optional[Dict[str, str]] - extra_body: Optional[Dict[str, str]] - timeout: Optional[float] + extra_headers: dict[str, str] | None + extra_body: dict[str, str] | None + timeout: float | None class CancelBatchRequest(TypedDict, total=False): @@ -450,9 +439,9 @@ class CancelBatchRequest(TypedDict, total=False): """ batch_id: str - extra_headers: Optional[Dict[str, str]] - extra_body: Optional[Dict[str, str]] - timeout: Optional[float] + extra_headers: dict[str, str] | None + extra_body: dict[str, str] | None + timeout: float | None class ListBatchRequest(TypedDict, total=False): @@ -461,14 +450,14 @@ class ListBatchRequest(TypedDict, total=False): Calls https://api.openai.com/v1/batches """ - after: Union[str, NotGiven] + after: str | NotGiven # OpenAI Batch Result Types class OpenAIErrorBody(TypedDict, total=False): """Error body in OpenAI batch response format.""" - error: Dict[str, str] + error: dict[str, str] BatchJobStatus = Literal[ @@ -491,19 +480,19 @@ class ChatCompletionAudioDelta(TypedDict, total=False): class ChatCompletionToolCallFunctionChunk(TypedDict, total=False): - name: Optional[str] + name: str | None arguments: str - provider_specific_fields: Optional[Dict[str, Any]] + provider_specific_fields: dict[str, Any] | None class ChatCompletionAssistantToolCall(TypedDict): - id: Optional[str] + id: str | None type: Literal["function"] function: ChatCompletionToolCallFunctionChunk class ChatCompletionToolCallChunk(TypedDict): # result of /chat/completions call - id: Optional[str] + id: str | None type: Literal["function"] function: ChatCompletionToolCallFunctionChunk index: int @@ -524,14 +513,14 @@ class ChatCompletionCachedContent(TypedDict): class ChatCompletionThinkingBlock(TypedDict, total=False): type: Required[Literal["thinking"]] thinking: str - signature: Optional[str] - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + signature: str | None + cache_control: dict | ChatCompletionCachedContent | None class ChatCompletionRedactedThinkingBlock(TypedDict, total=False): type: Required[Literal["redacted_thinking"]] data: str - cache_control: Optional[Union[dict, ChatCompletionCachedContent]] + cache_control: dict | ChatCompletionCachedContent | None class ChatCompletionReasoningSummaryTextBlock(TypedDict, total=False): @@ -544,8 +533,8 @@ class ChatCompletionReasoningItem(TypedDict, total=False): type: Required[Literal["reasoning"]] id: str - encrypted_content: Optional[str] - summary: List["ChatCompletionReasoningSummaryTextBlock"] + encrypted_content: str | None + summary: list["ChatCompletionReasoningSummaryTextBlock"] class WebSearchOptionsUserLocationApproximate(TypedDict, total=False): @@ -583,7 +572,7 @@ class WebSearchOptions(TypedDict, total=False): search. One of `low`, `medium`, or `high`. `medium` is the default. """ - user_location: Optional[WebSearchOptionsUserLocation] + user_location: WebSearchOptionsUserLocation | None """Approximate location parameters for the search.""" @@ -591,7 +580,7 @@ class FileSearchTool(TypedDict, total=False): type: Literal["file_search"] """The type of tool being defined: `file_search`""" - vector_store_ids: Optional[List[str]] + vector_store_ids: list[str] | None """The IDs of the vector stores to search.""" @@ -636,7 +625,7 @@ class ChatCompletionImageUrlObject(TypedDict, total=False): class ChatCompletionImageObject(TypedDict): type: Literal["image_url"] - image_url: Union[str, ChatCompletionImageUrlObject] + image_url: str | ChatCompletionImageUrlObject class ChatCompletionVideoUrlObject(TypedDict, total=False): @@ -646,7 +635,7 @@ class ChatCompletionVideoUrlObject(TypedDict, total=False): class ChatCompletionVideoObject(TypedDict): type: Literal["video_url"] - video_url: Union[str, ChatCompletionVideoUrlObject] + video_url: str | ChatCompletionVideoUrlObject class ChatCompletionAudioObject(ChatCompletionContentPartInputAudioParam): @@ -668,7 +657,7 @@ class ChatCompletionDocumentObject(TypedDict): source: DocumentObject title: str context: str - citations: Optional[CitationsObject] + citations: CitationsObject | None class ChatCompletionFileObjectFile(TypedDict, total=False): @@ -677,7 +666,7 @@ class ChatCompletionFileObjectFile(TypedDict, total=False): filename: str format: str detail: str # For video/image resolution control (low, medium, high, ultra_high) - video_metadata: Dict[str, Any] # For video-specific metadata (fps, start_offset, end_offset) + video_metadata: dict[str, Any] # For video-specific metadata (fps, start_offset, end_offset) class ChatCompletionFileObject(TypedDict): @@ -685,22 +674,19 @@ class ChatCompletionFileObject(TypedDict): file: ChatCompletionFileObjectFile -OpenAIMessageContentListBlock = Union[ - ChatCompletionTextObject, - ChatCompletionImageObject, - ChatCompletionAudioObject, - ChatCompletionDocumentObject, - ChatCompletionVideoObject, - ChatCompletionFileObject, -] +OpenAIMessageContentListBlock = ( + ChatCompletionTextObject + | ChatCompletionImageObject + | ChatCompletionAudioObject + | ChatCompletionDocumentObject + | ChatCompletionVideoObject + | ChatCompletionFileObject +) -OpenAIMessageContent = Union[ - str, - Iterable[OpenAIMessageContentListBlock], -] +OpenAIMessageContent = str | Iterable[OpenAIMessageContentListBlock] # The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. -AllPromptValues = Union[str, List[str], Iterable[int], Iterable[Iterable[int]], None] +AllPromptValues = str | list[str] | Iterable[int] | Iterable[Iterable[int]] | None class OpenAIChatCompletionUserMessage(TypedDict): @@ -719,53 +705,50 @@ class ChatCompletionUserMessage(OpenAIChatCompletionUserMessage, total=False): class OpenAIChatCompletionAssistantMessage(TypedDict, total=False): role: Required[Literal["assistant"]] - content: Optional[ - Union[ - str, - Iterable[ - Union[ - ChatCompletionTextObject, - ChatCompletionThinkingBlock, - ChatCompletionRedactedThinkingBlock, - ChatCompletionImageObject, - ] - ], + content: ( + str + | Iterable[ + ChatCompletionTextObject + | ChatCompletionThinkingBlock + | ChatCompletionRedactedThinkingBlock + | ChatCompletionImageObject ] - ] - name: Optional[str] - tool_calls: Optional[List[ChatCompletionAssistantToolCall]] - function_call: Optional[ChatCompletionToolCallFunctionChunk] - reasoning_content: Optional[str] + | None + ) + name: str | None + tool_calls: list[ChatCompletionAssistantToolCall] | None + function_call: ChatCompletionToolCallFunctionChunk | None + reasoning_content: str | None class ChatCompletionAssistantMessage(OpenAIChatCompletionAssistantMessage, total=False): cache_control: ChatCompletionCachedContent - thinking_blocks: Optional[List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]]] - reasoning_items: Optional[List[ChatCompletionReasoningItem]] + thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None + reasoning_items: list[ChatCompletionReasoningItem] | None class ChatCompletionToolMessage(TypedDict): role: Literal["tool"] - content: Union[str, Iterable[ChatCompletionTextObject]] + content: str | Iterable[ChatCompletionTextObject] tool_call_id: str class ChatCompletionFunctionMessage(TypedDict): role: Literal["function"] - content: Optional[Union[str, Iterable[ChatCompletionTextObject]]] + content: str | Iterable[ChatCompletionTextObject] | None name: str - tool_call_id: Optional[str] + tool_call_id: str | None class OpenAIChatCompletionSystemMessage(TypedDict, total=False): role: Required[Literal["system"]] - content: Required[Union[str, List]] + content: Required[str | list] name: str class OpenAIChatCompletionDeveloperMessage(TypedDict, total=False): role: Required[Literal["developer"]] - content: Required[Union[str, List]] + content: Required[str | list] name: str @@ -779,7 +762,7 @@ class ChatCompletionDeveloperMessage(OpenAIChatCompletionDeveloperMessage, total class GenericChatCompletionMessage(TypedDict, total=False): role: Required[str] - content: Required[Union[str, List]] + content: Required[str | list] ValidUserMessageContentTypes = [ @@ -867,14 +850,14 @@ ValidChatCompletionMessageContentTypes: Final = [ "redacted_thinking", ] -AllMessageValues = Union[ - ChatCompletionUserMessage, - ChatCompletionAssistantMessage, - ChatCompletionToolMessage, - ChatCompletionSystemMessage, - ChatCompletionFunctionMessage, - ChatCompletionDeveloperMessage, -] +AllMessageValues = ( + ChatCompletionUserMessage + | ChatCompletionAssistantMessage + | ChatCompletionToolMessage + | ChatCompletionSystemMessage + | ChatCompletionFunctionMessage + | ChatCompletionDeveloperMessage +) class ChatCompletionToolChoiceFunctionParam(TypedDict): @@ -888,7 +871,7 @@ class ChatCompletionToolChoiceObjectParam(TypedDict): ChatCompletionToolChoiceStringValues = Literal["none", "auto", "required"] -ChatCompletionToolChoiceValues = Union[ChatCompletionToolChoiceStringValues, ChatCompletionToolChoiceObjectParam] +ChatCompletionToolChoiceValues = ChatCompletionToolChoiceStringValues | ChatCompletionToolChoiceObjectParam class ChatCompletionToolParamFunctionChunk(TypedDict, total=False): @@ -899,13 +882,13 @@ class ChatCompletionToolParamFunctionChunk(TypedDict, total=False): class OpenAIChatCompletionToolParam(TypedDict): - type: Union[Literal["function"], str] + type: Literal["function"] | str function: ChatCompletionToolParamFunctionChunk class ChatCompletionToolParam(OpenAIChatCompletionToolParam, total=False): cache_control: ChatCompletionCachedContent - allowed_callers: List[str] + allowed_callers: list[str] class Function(TypedDict, total=False): @@ -922,7 +905,7 @@ class ChatCompletionNamedToolChoiceParam(TypedDict, total=False): class ChatCompletionRequest(TypedDict, total=False): model: Required[str] - messages: Required[List[AllMessageValues]] + messages: Required[list[AllMessageValues]] frequency_penalty: float logit_bias: dict logprobs: bool @@ -934,23 +917,23 @@ class ChatCompletionRequest(TypedDict, total=False): seed: int service_tier: str safety_identifier: str - stop: Union[str, List[str]] + stop: str | list[str] stream_options: dict temperature: float top_p: float - tools: List[ChatCompletionToolParam] + tools: list[ChatCompletionToolParam] tool_choice: ChatCompletionToolChoiceValues parallel_tool_calls: bool - function_call: Union[str, dict] - functions: List + function_call: str | dict + functions: list user: str metadata: dict # litellm specific param reasoning_effort: str # OpenAI o1/o3 reasoning parameter class ChatCompletionDeltaChunk(TypedDict, total=False): - content: Optional[str] - tool_calls: List[ChatCompletionDeltaToolCallChunk] + content: str | None + tool_calls: list[ChatCompletionDeltaToolCallChunk] role: str @@ -958,35 +941,35 @@ ChatCompletionAssistantContentValue = str # keep as var, used in stream_chunk_b class ChatCompletionResponseMessage(TypedDict, total=False): - content: Optional[ChatCompletionAssistantContentValue] - annotations: Optional[List[ChatCompletionAnnotation]] - tool_calls: Optional[List[ChatCompletionToolCallChunk]] + content: ChatCompletionAssistantContentValue | None + annotations: list[ChatCompletionAnnotation] | None + tool_calls: list[ChatCompletionToolCallChunk] | None role: Literal["assistant"] - function_call: Optional[ChatCompletionToolCallFunctionChunk] - provider_specific_fields: Optional[dict] - reasoning_content: Optional[str] - thinking_blocks: Optional[List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]]] + function_call: ChatCompletionToolCallFunctionChunk | None + provider_specific_fields: dict | None + reasoning_content: str | None + thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None class ChatCompletionUsageBlock(TypedDict, total=False): prompt_tokens: Required[int] completion_tokens: Required[int] total_tokens: Required[int] - prompt_tokens_details: Optional[dict] - completion_tokens_details: Optional[dict] + prompt_tokens_details: dict | None + completion_tokens_details: dict | None class OpenAIChatCompletionChunk(ChatCompletionChunk): - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: # Set the 'object' kwarg to 'chat.completion.chunk' kwargs["object"] = "chat.completion.chunk" super().__init__(**kwargs) class Hyperparameters(BaseModel): - batch_size: Optional[Union[str, int]] = None # "Number of examples in each batch." - learning_rate_multiplier: Optional[Union[str, float]] = None # Scaling factor for the learning rate - n_epochs: Optional[Union[str, int]] = None # "The number of epochs to train the model for" + batch_size: str | int | None = None # "Number of examples in each batch." + learning_rate_multiplier: str | float | None = None # Scaling factor for the learning rate + n_epochs: str | int | None = None # "The number of epochs to train the model for" model_config = {"extra": "allow"} @@ -1015,20 +998,20 @@ class FineTuningJobCreate(BaseModel): model: str # "The name of the model to fine-tune." training_file: str # "The ID of an uploaded file that contains training data." - hyperparameters: Optional[Hyperparameters] = None # "The hyperparameters used for the fine-tuning job." - suffix: Optional[str] = None # "A string of up to 18 characters that will be added to your fine-tuned model name." - validation_file: Optional[str] = None # "The ID of an uploaded file that contains validation data." - integrations: Optional[List[str]] = None # "A list of integrations to enable for your fine-tuning job." - seed: Optional[int] = None # "The seed controls the reproducibility of the job." + hyperparameters: Hyperparameters | None = None # "The hyperparameters used for the fine-tuning job." + suffix: str | None = None # "A string of up to 18 characters that will be added to your fine-tuned model name." + validation_file: str | None = None # "The ID of an uploaded file that contains validation data." + integrations: list[str] | None = None # "A list of integrations to enable for your fine-tuning job." + seed: int | None = None # "The seed controls the reproducibility of the job." class LiteLLMFineTuningJobCreate(FineTuningJobCreate): - custom_llm_provider: Optional[Literal["openai", "azure", "vertex_ai"]] = None + custom_llm_provider: Literal["openai", "azure", "vertex_ai"] | None = None model_config = {"extra": "allow"} # This allows the model to accept additional fields -AllEmbeddingInputValues = Union[str, List[str], List[int], List[List[int]]] +AllEmbeddingInputValues = str | list[str] | list[int] | list[list[int]] OpenAIAudioTranscriptionOptionalParams = Literal[ "language", @@ -1086,10 +1069,10 @@ class ComputerToolParam(TypedDict, total=False): display_width: Required[float] """The width of the computer display.""" - environment: Required[Union[Literal["mac", "windows", "ubuntu", "browser"], str]] + environment: Required[Literal["mac", "windows", "ubuntu", "browser"] | str] """The type of computer environment to control.""" - type: Required[Union[Literal["computer_use_preview"], str]] + type: Required[Literal["computer_use_preview"] | str] class ShellToolParam(TypedDict, total=False): @@ -1098,14 +1081,14 @@ class ShellToolParam(TypedDict, total=False): See https://developers.openai.com/api/docs/guides/tools-shell. """ - type: Required[Union[Literal["shell"], str]] + type: Required[Literal["shell"] | str] """The type of tool. Use ``\"shell\"``.""" - environment: Required[Dict[str, Any]] + environment: Required[dict[str, Any]] """Environment config: ``type`` (e.g. ``\"container_auto\"``, ``\"container_reference\"``, ``\"local\"``), optional ``container_id``, ``network_policy``, ``domain_secrets``, ``skills``.""" -ALL_RESPONSES_API_TOOL_PARAMS = Union[ToolParam, ComputerToolParam, ShellToolParam] +ALL_RESPONSES_API_TOOL_PARAMS = ToolParam | ComputerToolParam | ShellToolParam class PromptObject(TypedDict, total=False): @@ -1114,10 +1097,10 @@ class PromptObject(TypedDict, total=False): id: Required[str] """The unique identifier of the prompt template to use.""" - variables: Optional[Dict] + variables: dict | None """Variables to substitute into the prompt template.""" - version: Optional[str] + version: str | None """Optional version of the prompt template.""" @@ -1141,55 +1124,55 @@ class ResponsesAPIStreamOptions(TypedDict, total=False): class ResponsesAPIOptionalRequestParams(TypedDict, total=False): """TypedDict for Optional parameters supported by the responses API.""" - include: Optional[List[ResponseIncludable]] - instructions: Optional[str] - max_output_tokens: Optional[int] - metadata: Optional[Dict[str, Any]] - parallel_tool_calls: Optional[bool] - previous_response_id: Optional[str] - reasoning: Optional[Reasoning] - store: Optional[bool] - background: Optional[bool] - stream: Optional[bool] - temperature: Optional[float] + include: list[ResponseIncludable] | None + instructions: str | None + max_output_tokens: int | None + metadata: dict[str, Any] | None + parallel_tool_calls: bool | None + previous_response_id: str | None + reasoning: Reasoning | None + store: bool | None + background: bool | None + stream: bool | None + temperature: float | None text: Optional["ResponseText"] - tool_choice: Optional[ToolChoice] - tools: Optional[List[ALL_RESPONSES_API_TOOL_PARAMS]] - top_p: Optional[float] - truncation: Optional[Literal["auto", "disabled"]] - user: Optional[str] - service_tier: Optional[str] - safety_identifier: Optional[str] - prompt: Optional[PromptObject] - max_tool_calls: Optional[int] - prompt_cache_key: Optional[str] - prompt_cache_retention: Optional[str] - stream_options: Optional[ResponsesAPIStreamOptions] - top_logprobs: Optional[int] - partial_images: Optional[int] # Number of partial images to generate (1-3) for streaming image generation - context_management: Optional[List[ContextManagementEntry]] + tool_choice: ToolChoice | None + tools: list[ALL_RESPONSES_API_TOOL_PARAMS] | None + top_p: float | None + truncation: Literal["auto", "disabled"] | None + user: str | None + service_tier: str | None + safety_identifier: str | None + prompt: PromptObject | None + max_tool_calls: int | None + prompt_cache_key: str | None + prompt_cache_retention: str | None + stream_options: ResponsesAPIStreamOptions | None + top_logprobs: int | None + partial_images: int | None # Number of partial images to generate (1-3) for streaming image generation + context_management: list[ContextManagementEntry] | None """Context management configuration. E.g. [{\"type\": \"compaction\", \"compact_threshold\": 200000}] for server-side compaction (minimum 1000).""" class ResponsesAPIRequestParams(ResponsesAPIOptionalRequestParams, total=False): """TypedDict for request parameters supported by the responses API.""" - input: Union[str, ResponseInputParam] + input: str | ResponseInputParam model: str class OutputTokensDetails(BaseLiteLLMOpenAIResponseObject): - reasoning_tokens: Optional[int] = None + reasoning_tokens: int | None = None - text_tokens: Optional[int] = None + text_tokens: int | None = None model_config = {"extra": "allow"} class InputTokensDetails(BaseLiteLLMOpenAIResponseObject): - audio_tokens: Optional[int] = None + audio_tokens: int | None = None cached_tokens: int = 0 - text_tokens: Optional[int] = None + text_tokens: int | None = None model_config = {"extra": "allow"} @@ -1198,24 +1181,24 @@ class ResponseAPIUsage(BaseLiteLLMOpenAIResponseObject): input_tokens: int """The number of input tokens.""" - input_tokens_details: Optional[InputTokensDetails] = None + input_tokens_details: InputTokensDetails | None = None """A detailed breakdown of the input tokens.""" output_tokens: int """The number of output tokens.""" - output_tokens_details: Optional[OutputTokensDetails] = None + output_tokens_details: OutputTokensDetails | None = None """A detailed breakdown of the output tokens.""" total_tokens: int """The total number of tokens used.""" - cost: Optional[float] = None + cost: float | None = None """The cost of the request.""" @field_validator("cost", mode="before") @classmethod - def parse_cost(cls, v: Any) -> Optional[float]: + def parse_cost(cls, v: Any) -> float | None: """Normalise cost: accept either a float or a dict with a ``total_cost`` key.""" if isinstance(v, dict): return v.get("total_cost") @@ -1234,45 +1217,43 @@ One of: completed, failed, in_progress, cancelled, queued, or incomplete. class ResponsesAPIResponse(BaseLiteLLMOpenAIResponseObject): id: str created_at: int - error: Optional[dict] = None - incomplete_details: Optional[IncompleteDetails] = None - instructions: Optional[str] = None - metadata: Optional[Dict] = None - model: Optional[str] = None - object: Optional[str] = None - output: Union[ - List[Union[ResponseOutputItem, Dict]], - List[ - Union[ - GenericResponseOutputItem, - OutputCodeInterpreterCall, - OutputFunctionToolCall, - OutputImageGenerationCall, - ResponseFunctionToolCall, - CustomToolCallOutputItem, - ] - ], - ] - parallel_tool_calls: Optional[bool] = None - temperature: Optional[float] = None - tool_choice: Optional[ToolChoice] = None - tools: Optional[Union[List[Tool], List[ResponseFunctionToolCall], List[Dict[str, Any]]]] = None - top_p: Optional[float] = None - max_output_tokens: Optional[int] = None - previous_response_id: Optional[str] = None - reasoning: Optional[Dict[str, Any]] = None - status: Optional[str] = None - text: Optional[Union["ResponseText", Dict[str, Any]]] = None - truncation: Optional[Literal["auto", "disabled"]] = None - usage: Optional[ResponseAPIUsage] = None - user: Optional[str] = None - store: Optional[bool] = None + error: dict | None = None + incomplete_details: IncompleteDetails | None = None + instructions: str | None = None + metadata: dict | None = None + model: str | None = None + object: str | None = None + output: ( + list[ResponseOutputItem | dict] + | list[ + GenericResponseOutputItem + | OutputCodeInterpreterCall + | OutputFunctionToolCall + | OutputImageGenerationCall + | ResponseFunctionToolCall + | CustomToolCallOutputItem + ] + ) + parallel_tool_calls: bool | None = None + temperature: float | None = None + tool_choice: ToolChoice | None = None + tools: list[Tool] | list[ResponseFunctionToolCall] | list[dict[str, Any]] | None = None + top_p: float | None = None + max_output_tokens: int | None = None + previous_response_id: str | None = None + reasoning: dict[str, Any] | None = None + status: str | None = None + text: Union["ResponseText", dict[str, Any]] | None = None + truncation: Literal["auto", "disabled"] | None = None + usage: ResponseAPIUsage | None = None + user: str | None = None + store: bool | None = None # Define private attributes using PrivateAttr _hidden_params: dict = PrivateAttr(default_factory=dict) @field_validator("reasoning", mode="before") @classmethod - def validate_reasoning_to_dict(cls, value: Any) -> Optional[Dict[str, Any]]: + def validate_reasoning_to_dict(cls, value: Any) -> dict[str, Any] | None: """Accept API reasoning dict (including effort 'none'/'xhigh'); always store as dict.""" if value is None: return None @@ -1328,7 +1309,7 @@ class ResponsesAPIResponse(BaseLiteLLMOpenAIResponseObject): This matches the OpenAI SDK's Response.output_text behavior. """ - texts: Final[List[str]] = [] + texts: Final[list[str]] = [] for output_item in self.output: # Handle both dict and object access patterns if isinstance(output_item, dict): @@ -1492,7 +1473,7 @@ class ReasoningSummaryPartDoneEvent(BaseLiteLLMOpenAIResponseObject): class OutputItemAddedEvent(BaseLiteLLMOpenAIResponseObject): type: Literal[ResponsesAPIStreamEvents.OUTPUT_ITEM_ADDED] output_index: int - item: Optional[BaseLiteLLMOpenAIResponseObject] + item: BaseLiteLLMOpenAIResponseObject | None class OutputItemDoneEvent(BaseLiteLLMOpenAIResponseObject): @@ -1503,16 +1484,16 @@ class OutputItemDoneEvent(BaseLiteLLMOpenAIResponseObject): class OpenAIChatCompletionLogprobsContentTopLogprobs(TypedDict, total=False): - bytes: List + bytes: list logprob: Required[float] token: Required[str] class OpenAIChatCompletionLogprobsContent(TypedDict, total=False): - bytes: List + bytes: list logprob: Required[float] token: Required[str] - top_logprobs: List[OpenAIChatCompletionLogprobsContentTopLogprobs] + top_logprobs: list[OpenAIChatCompletionLogprobsContentTopLogprobs] class ContentPartAddedEvent(BaseLiteLLMOpenAIResponseObject): @@ -1526,8 +1507,8 @@ class ContentPartAddedEvent(BaseLiteLLMOpenAIResponseObject): class ContentPartDonePartOutputText(BaseLiteLLMOpenAIResponseObject): type: Literal["output_text"] text: str - annotations: List[BaseLiteLLMOpenAIResponseObject] - logprobs: Optional[List[OpenAIChatCompletionLogprobsContent]] + annotations: list[BaseLiteLLMOpenAIResponseObject] + logprobs: list[OpenAIChatCompletionLogprobsContent] | None class ContentPartDonePartRefusal(BaseLiteLLMOpenAIResponseObject): @@ -1540,11 +1521,7 @@ class ContentPartDonePartReasoningText(BaseLiteLLMOpenAIResponseObject): reasoning: str -PART_UNION_TYPES = Union[ - ContentPartDonePartOutputText, - ContentPartDonePartRefusal, - ContentPartDonePartReasoningText, -] +PART_UNION_TYPES = ContentPartDonePartOutputText | ContentPartDonePartRefusal | ContentPartDonePartReasoningText class ContentPartDoneEvent(BaseLiteLLMOpenAIResponseObject): @@ -1718,7 +1695,7 @@ class ErrorEventError(BaseLiteLLMOpenAIResponseObject): type: str # e.g., 'invalid_request_error' code: str # e.g., 'context_length_exceeded' message: str - param: Optional[Union[str, Dict[str, Any]]] = None + param: str | dict[str, Any] | None = None class ErrorEvent(BaseLiteLLMOpenAIResponseObject): @@ -1735,46 +1712,44 @@ class GenericEvent(BaseLiteLLMOpenAIResponseObject): # Union type for all possible streaming responses ResponsesAPIStreamingResponse = Annotated[ - Union[ - ResponseCreatedEvent, - ResponseInProgressEvent, - ResponseCompletedEvent, - ResponseFailedEvent, - ResponseIncompleteEvent, - ResponsePartAddedEvent, - ReasoningSummaryTextDeltaEvent, - ReasoningSummaryTextDoneEvent, - ReasoningSummaryPartDoneEvent, - OutputItemAddedEvent, - OutputItemDoneEvent, - ContentPartAddedEvent, - ContentPartDoneEvent, - OutputTextDeltaEvent, - OutputTextAnnotationAddedEvent, - OutputTextDoneEvent, - RefusalDeltaEvent, - RefusalDoneEvent, - FunctionCallArgumentsDeltaEvent, - FunctionCallArgumentsDoneEvent, - FileSearchCallInProgressEvent, - FileSearchCallSearchingEvent, - FileSearchCallCompletedEvent, - WebSearchCallInProgressEvent, - WebSearchCallSearchingEvent, - WebSearchCallCompletedEvent, - MCPListToolsInProgressEvent, - MCPListToolsCompletedEvent, - MCPListToolsFailedEvent, - MCPCallInProgressEvent, - MCPCallArgumentsDeltaEvent, - MCPCallArgumentsDoneEvent, - MCPCallCompletedEvent, - MCPCallFailedEvent, - ImageGenerationPartialImageEvent, - ErrorEvent, - GenericEvent, - BaseLiteLLMOpenAIResponseObject, - ], + ResponseCreatedEvent + | ResponseInProgressEvent + | ResponseCompletedEvent + | ResponseFailedEvent + | ResponseIncompleteEvent + | ResponsePartAddedEvent + | ReasoningSummaryTextDeltaEvent + | ReasoningSummaryTextDoneEvent + | ReasoningSummaryPartDoneEvent + | OutputItemAddedEvent + | OutputItemDoneEvent + | ContentPartAddedEvent + | ContentPartDoneEvent + | OutputTextDeltaEvent + | OutputTextAnnotationAddedEvent + | OutputTextDoneEvent + | RefusalDeltaEvent + | RefusalDoneEvent + | FunctionCallArgumentsDeltaEvent + | FunctionCallArgumentsDoneEvent + | FileSearchCallInProgressEvent + | FileSearchCallSearchingEvent + | FileSearchCallCompletedEvent + | WebSearchCallInProgressEvent + | WebSearchCallSearchingEvent + | WebSearchCallCompletedEvent + | MCPListToolsInProgressEvent + | MCPListToolsCompletedEvent + | MCPListToolsFailedEvent + | MCPCallInProgressEvent + | MCPCallArgumentsDeltaEvent + | MCPCallArgumentsDoneEvent + | MCPCallCompletedEvent + | MCPCallFailedEvent + | ImageGenerationPartialImageEvent + | ErrorEvent + | GenericEvent + | BaseLiteLLMOpenAIResponseObject, Discriminator("type"), ] @@ -1808,12 +1783,12 @@ class OpenAIRealtimeStreamSession(TypedDict, total=False): The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. "be extremely succinct", "act friendly", "here are examples of good responses") and on audio behavior (e.g. "talk quickly", "inject emotion into your voice", "laugh frequently"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior. """ - max_response_output_tokens: Union[int, Literal["inf"]] + max_response_output_tokens: int | Literal["inf"] """ Maximum number of output tokens for a single assistant response, inclusive of tool calls. Provide an integer between 1 and 4096 to limit output tokens, or inf for the maximum available tokens for a given model. Defaults to inf. """ - modalities: List[str] + modalities: list[str] """ The set of modalities the model can respond with. To disable audio, set this to ["text"]. """ @@ -1858,7 +1833,7 @@ class OpenAIRealtimeStreamSession(TypedDict, total=False): class OpenAIRealtimeStreamSessionEvents(TypedDict): event_id: str session: OpenAIRealtimeStreamSession - type: Union[Literal["session.created"], Literal["session.updated"]] + type: Literal["session.created", "session.updated"] class OpenAIRealtimeStreamResponseOutputItemContent(TypedDict, total=False): @@ -1868,7 +1843,7 @@ class OpenAIRealtimeStreamResponseOutputItemContent(TypedDict, total=False): """The ID of the previous conversation item for reference""" text: str """The text content, used for 'input_text' / 'text' / 'output_text' content types""" - transcript: Optional[str] + transcript: str | None """The transcript content, used for 'input_audio' / 'audio' content types""" type: Literal[ "input_audio", @@ -1894,7 +1869,7 @@ class OpenAIRealtimeStreamResponseOutputItem(TypedDict, total=False): id: str """The ID of the previous conversation item for reference""" - content: List[OpenAIRealtimeStreamResponseOutputItemContent] + content: list[OpenAIRealtimeStreamResponseOutputItemContent] name: str """The name of the function call""" @@ -1946,7 +1921,7 @@ class OpenAIRealtimeConversationItemCreated(TypedDict, total=False): type: Required[Literal["conversation.item.created"]] item: OpenAIRealtimeStreamResponseOutputItem event_id: str - previous_item_id: Optional[str] # None when this is the first item + previous_item_id: str | None # None when this is the first item class OpenAIRealtimeConversationItemAdded(TypedDict, total=False): @@ -1955,7 +1930,7 @@ class OpenAIRealtimeConversationItemAdded(TypedDict, total=False): type: Required[Literal["conversation.item.added"]] item: OpenAIRealtimeStreamResponseOutputItem event_id: str - previous_item_id: Optional[str] # None when this is the first item + previous_item_id: str | None # None when this is the first item class OpenAIRealtimeConversationItemDone(TypedDict, total=False): @@ -1964,7 +1939,7 @@ class OpenAIRealtimeConversationItemDone(TypedDict, total=False): type: Required[Literal["conversation.item.done"]] item: OpenAIRealtimeStreamResponseOutputItem event_id: str - previous_item_id: Optional[str] # None when this is the first item + previous_item_id: str | None # None when this is the first item class OpenAIRealtimeResponseContentPart(TypedDict, total=False): @@ -1974,13 +1949,10 @@ class OpenAIRealtimeResponseContentPart(TypedDict, total=False): text: str """The text content, if type is 'text' or 'output_text'""" - transcript: Optional[str] + transcript: str | None """The transcript content, if type is 'audio' or 'output_audio'""" - type: Union[ - Literal["audio", "text"], # beta - Literal["output_audio", "output_text"], # GA - ] + type: Literal["audio", "text", "output_audio", "output_text"] """The type of content""" @@ -2001,13 +1973,12 @@ class OpenAIRealtimeResponseDelta(TypedDict): item_id: str output_index: int response_id: str - type: Union[ - Literal["response.text.delta"], - Literal["response.audio.delta"], - # GA renamed events - Literal["response.output_text.delta"], - Literal["response.output_audio.delta"], - Literal["response.output_audio_transcript.delta"], + type: Literal[ + "response.text.delta", + "response.audio.delta", + "response.output_text.delta", + "response.output_audio.delta", + "response.output_audio_transcript.delta", ] @@ -2018,10 +1989,7 @@ class OpenAIRealtimeResponseTextDone(TypedDict): output_index: int response_id: str text: str - type: Union[ - Literal["response.text.done"], - Literal["response.output_text.done"], # GA rename - ] + type: Literal["response.text.done", "response.output_text.done"] class OpenAIRealtimeResponseAudioDone(TypedDict): @@ -2030,11 +1998,7 @@ class OpenAIRealtimeResponseAudioDone(TypedDict): item_id: str output_index: int response_id: str - type: Union[ - Literal["response.audio.done"], - Literal["response.output_audio.done"], # GA rename - Literal["response.output_audio_transcript.done"], # GA rename - ] + type: Literal["response.audio.done", "response.output_audio.done", "response.output_audio_transcript.done"] class OpenAIRealtimeContentPartDone(TypedDict): @@ -2073,7 +2037,7 @@ class OpenAIRealtimeResponseDoneObject(TypedDict, total=False): metadata: dict modalities: list object: Literal["realtime.response"] - output: List[OpenAIRealtimeStreamResponseOutputItem] + output: list[OpenAIRealtimeStreamResponseOutputItem] output_audio_format: str status: Literal["completed", "cancelled", "failed", "incomplete"] status_details: dict @@ -2107,27 +2071,27 @@ class OpenAIRealtimeEventTypes(Enum): RESPONSE_CONTENT_PART_ADDED = "response.content_part.added" -OpenAIRealtimeEvents = Union[ - OpenAIRealtimeStreamResponseBaseObject, - OpenAIRealtimeStreamSessionEvents, - OpenAIRealtimeStreamResponseOutputItemAdded, - OpenAIRealtimeResponseContentPartAdded, +OpenAIRealtimeEvents = ( + OpenAIRealtimeStreamResponseBaseObject + | OpenAIRealtimeStreamSessionEvents + | OpenAIRealtimeStreamResponseOutputItemAdded + | OpenAIRealtimeResponseContentPartAdded # Beta conversation item event - OpenAIRealtimeConversationItemCreated, + | OpenAIRealtimeConversationItemCreated # GA conversation item events - OpenAIRealtimeConversationItemAdded, - OpenAIRealtimeConversationItemDone, - OpenAIRealtimeConversationCreated, - OpenAIRealtimeResponseDelta, - OpenAIRealtimeResponseTextDone, - OpenAIRealtimeResponseAudioDone, - OpenAIRealtimeContentPartDone, - OpenAIRealtimeOutputItemDone, - OpenAIRealtimeFunctionCallArgumentsDone, - OpenAIRealtimeDoneEvent, -] + | OpenAIRealtimeConversationItemAdded + | OpenAIRealtimeConversationItemDone + | OpenAIRealtimeConversationCreated + | OpenAIRealtimeResponseDelta + | OpenAIRealtimeResponseTextDone + | OpenAIRealtimeResponseAudioDone + | OpenAIRealtimeContentPartDone + | OpenAIRealtimeOutputItemDone + | OpenAIRealtimeFunctionCallArgumentsDone + | OpenAIRealtimeDoneEvent +) -OpenAIRealtimeStreamList = List[OpenAIRealtimeEvents] +OpenAIRealtimeStreamList = list[OpenAIRealtimeEvents] class ImageGenerationRequestQuality(str, Enum): @@ -2140,10 +2104,10 @@ class ImageGenerationRequestQuality(str, Enum): class OpenAIModerationResult(BaseLiteLLMOpenAIResponseObject): - categories: Optional[Dict] - category_applied_input_types: Optional[Dict] - category_scores: Optional[Dict] - flagged: Optional[bool] + categories: dict | None + category_applied_input_types: dict | None + category_scores: dict | None + flagged: bool | None class OpenAIModerationResponse(BaseLiteLLMOpenAIResponseObject): @@ -2157,7 +2121,7 @@ class OpenAIModerationResponse(BaseLiteLLMOpenAIResponseObject): model: str """The model used to generate the moderation results.""" - results: List[OpenAIModerationResult] + results: list[OpenAIModerationResult] """A list of moderation objects.""" # Define private attributes using PrivateAttr @@ -2165,14 +2129,14 @@ class OpenAIModerationResponse(BaseLiteLLMOpenAIResponseObject): class OpenAIChatCompletionLogprobs(TypedDict, total=False): - content: List[OpenAIChatCompletionLogprobsContent] - refusal: List[OpenAIChatCompletionLogprobsContent] + content: list[OpenAIChatCompletionLogprobsContent] + refusal: list[OpenAIChatCompletionLogprobsContent] class OpenAIChatCompletionChoices(TypedDict, total=False): finish_reason: Required[str] index: Required[int] - logprobs: Optional[OpenAIChatCompletionLogprobs] + logprobs: OpenAIChatCompletionLogprobs | None message: Required[ChatCompletionResponseMessage] @@ -2181,7 +2145,7 @@ class OpenAIChatCompletionResponse(TypedDict, total=False): object: Required[str] created: Required[int] model: Required[str] - choices: Required[List[OpenAIChatCompletionChoices]] + choices: Required[list[OpenAIChatCompletionChoices]] usage: Required[ChatCompletionUsageBlock] system_fingerprint: str service_tier: str @@ -2193,7 +2157,7 @@ class OpenAIBatchResponse(TypedDict, total=False): status_code: int request_id: str - body: Union[OpenAIChatCompletionResponse, OpenAIErrorBody] + body: OpenAIChatCompletionResponse | OpenAIErrorBody class OpenAIBatchResult(TypedDict, total=False): @@ -2229,8 +2193,8 @@ class OpenAIWebSearchUserLocation(TypedDict): class OpenAIWebSearchOptions(TypedDict, total=False): - search_context_size: Optional[Literal["low", "medium", "high"]] - user_location: Optional[OpenAIWebSearchUserLocation] + search_context_size: Literal["low", "medium", "high"] | None + user_location: OpenAIWebSearchUserLocation | None class OpenAIRealtimeTurnDetection(TypedDict, total=False): @@ -2248,8 +2212,8 @@ class OpenAIMcpServerTool(TypedDict, total=False): server_label: Required[str] server_url: Required[str] require_approval: str - allowed_tools: Optional[List[str]] - headers: Optional[Dict[str, str]] + allowed_tools: list[str] | None + headers: dict[str, str] | None # Video Generation Types @@ -2273,15 +2237,15 @@ class CreateVideoRequest(TypedDict, total=False): """ prompt: Required[str] - input_reference: Optional[str] - model: Optional[str] - seconds: Optional[str] - size: Optional[str] - characters: Optional[List[Dict[str, str]]] - user: Optional[str] - extra_headers: Optional[Dict[str, str]] - extra_body: Optional[Dict[str, str]] - timeout: Optional[float] + input_reference: str | None + model: str | None + seconds: str | None + size: str | None + characters: list[dict[str, str]] | None + user: str | None + extra_headers: dict[str, str] | None + extra_body: dict[str, str] | None + timeout: float | None class OpenAIVideoObject(BaseModel): @@ -2299,33 +2263,33 @@ class OpenAIVideoObject(BaseModel): created_at: int """Unix timestamp (seconds) for when the job was created.""" - completed_at: Optional[int] = None + completed_at: int | None = None """Unix timestamp (seconds) for when the job completed, if finished.""" - expires_at: Optional[int] = None + expires_at: int | None = None """Unix timestamp (seconds) for when the downloadable assets expire, if set.""" - error: Optional[Dict[str, Any]] = None + error: dict[str, Any] | None = None """Error payload that explains why generation failed, if applicable.""" - progress: Optional[int] = None + progress: int | None = None """Approximate completion percentage for the generation task.""" - remixed_from_video_id: Optional[str] = None + remixed_from_video_id: str | None = None """Identifier of the source video if this video is a remix.""" - seconds: Optional[str] = None + seconds: str | None = None """Duration of the generated clip in seconds.""" - size: Optional[str] = None + size: str | None = None """The resolution of the generated video.""" - model: Optional[str] = None + model: str | None = None """The video generation model that produced the job.""" - _hidden_params: Dict[str, Any] = {} + _hidden_params: dict[str, Any] = {} - def __contains__(self, key): + def __contains__(self, key) -> bool: return hasattr(self, key) def get(self, key, default=None): diff --git a/litellm/types/llms/openai_evals.py b/litellm/types/llms/openai_evals.py index 703cd8bcce5..c96ca515d60 100644 --- a/litellm/types/llms/openai_evals.py +++ b/litellm/types/llms/openai_evals.py @@ -2,9 +2,9 @@ Type definitions for OpenAI Evals API """ -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Literal -from pydantic import BaseModel, Field +from pydantic import BaseModel from typing_extensions import Required, TypedDict @@ -15,10 +15,10 @@ class DataSourceConfigCustom(TypedDict, total=False): type: Required[Literal["custom"]] """Data source type - custom""" - item_schema: Required[Dict[str, Any]] + item_schema: Required[dict[str, Any]] """JSON schema describing the structure of each row in the dataset""" - include_sample_schema: Optional[bool] + include_sample_schema: bool | None """Whether eval expects sample schema population""" @@ -28,7 +28,7 @@ class DataSourceConfigLogs(TypedDict, total=False): type: Required[Literal["logs"]] """Data source type - logs""" - metadata: Optional[Dict[str, Any]] + metadata: dict[str, Any] | None """Optional metadata for filtering logs""" @@ -38,11 +38,11 @@ class DataSourceConfigStoredCompletions(TypedDict, total=False): type: Required[Literal["stored_completions"]] """Data source type - stored_completions (deprecated)""" - metadata: Optional[Dict[str, Any]] + metadata: dict[str, Any] | None """Optional metadata for filtering stored completions""" -DataSourceConfig = Union[DataSourceConfigCustom, DataSourceConfigLogs, DataSourceConfigStoredCompletions] +DataSourceConfig = DataSourceConfigCustom | DataSourceConfigLogs | DataSourceConfigStoredCompletions class LLMAsJudgeGraderConfig(TypedDict, total=False): @@ -51,10 +51,10 @@ class LLMAsJudgeGraderConfig(TypedDict, total=False): type: Required[Literal["llm_as_judge"]] """Grader type - LLM as judge""" - model: Optional[str] + model: str | None """Model to use as judge (e.g., 'gpt-4')""" - prompt: Optional[str] + prompt: str | None """Custom prompt for the judge model""" @@ -64,7 +64,7 @@ class GroundTruthGraderConfig(TypedDict, total=False): type: Required[Literal["ground_truth"]] """Grader type - ground truth comparison""" - metric: Optional[Literal["exact_match", "f1_score", "bleu"]] + metric: Literal["exact_match", "f1_score", "bleu"] | None """Metric to use for comparison""" @@ -78,51 +78,51 @@ class CustomGraderConfig(TypedDict, total=False): """ID of the custom grading function""" -GraderConfig = Union[LLMAsJudgeGraderConfig, GroundTruthGraderConfig, CustomGraderConfig] +GraderConfig = LLMAsJudgeGraderConfig | GroundTruthGraderConfig | CustomGraderConfig class CreateEvalRequest(TypedDict, total=False): """Request parameters for creating an evaluation""" - name: Optional[str] + name: str | None """The name of the evaluation""" data_source_config: Required[DataSourceConfig] """Configuration for the data source""" - testing_criteria: Required[List[GraderConfig]] + testing_criteria: Required[list[GraderConfig]] """List of graders for all eval runs""" - metadata: Optional[Dict[str, Any]] + metadata: dict[str, Any] | None """Set of 16 key-value pairs that can be attached to an object (max 64 char keys, 512 char values)""" class UpdateEvalRequest(TypedDict, total=False): """Request parameters for updating an evaluation""" - name: Optional[str] + name: str | None """Updated name""" - metadata: Optional[Dict[str, Any]] + metadata: dict[str, Any] | None """Updated metadata""" class ListEvalsParams(TypedDict, total=False): """Query parameters for listing evaluations""" - limit: Optional[int] + limit: int | None """Number of results to return per page. Maximum value is 100. Defaults to 20.""" - after: Optional[str] + after: str | None """Cursor for pagination - returns evals after this ID""" - before: Optional[str] + before: str | None """Cursor for pagination - returns evals before this ID""" - order: Optional[Literal["asc", "desc"]] + order: Literal["asc", "desc"] | None """Sort order for results. Defaults to 'desc'.""" - order_by: Optional[Literal["created_at", "updated_at"]] + order_by: Literal["created_at", "updated_at"] | None """Field to sort by. Defaults to 'created_at'.""" @@ -139,19 +139,19 @@ class Eval(BaseModel): created_at: int """Unix timestamp of when the evaluation was created""" - updated_at: Optional[int] = None + updated_at: int | None = None """Unix timestamp of when the evaluation was last updated""" - name: Optional[str] = None + name: str | None = None """The name of the evaluation""" - data_source_config: Dict[str, Any] + data_source_config: dict[str, Any] """Configuration for the data source""" - testing_criteria: List[Dict[str, Any]] + testing_criteria: list[dict[str, Any]] """List of graders for the evaluation""" - metadata: Optional[Dict[str, Any]] = None + metadata: dict[str, Any] | None = None """Additional metadata""" @@ -161,13 +161,13 @@ class ListEvalsResponse(BaseModel): object: str = "list" """Object type, always 'list'""" - data: List[Eval] + data: list[Eval] """List of evaluations""" - first_id: Optional[str] = None + first_id: str | None = None """ID of the first evaluation in the list""" - last_id: Optional[str] = None + last_id: str | None = None """ID of the last evaluation in the list""" has_more: bool = False @@ -227,11 +227,11 @@ class DataSourceInlineConfig(TypedDict, total=False): type: Required[Literal["inline"]] """Data source type - inline""" - samples: Required[List[Dict[str, Any]]] + samples: Required[list[dict[str, Any]]] """List of inline samples to use for the run""" -RunDataSourceConfig = Union[DataSourceDatasetConfig, DataSourceSampleSetConfig, DataSourceInlineConfig] +RunDataSourceConfig = DataSourceDatasetConfig | DataSourceSampleSetConfig | DataSourceInlineConfig class CompletionConfig(TypedDict, total=False): @@ -240,48 +240,48 @@ class CompletionConfig(TypedDict, total=False): model: Required[str] """Model to use for completions""" - temperature: Optional[float] + temperature: float | None """Sampling temperature (0-2)""" - max_tokens: Optional[int] + max_tokens: int | None """Maximum tokens to generate""" - top_p: Optional[float] + top_p: float | None """Nucleus sampling parameter""" - frequency_penalty: Optional[float] + frequency_penalty: float | None """Frequency penalty (-2.0 to 2.0)""" - presence_penalty: Optional[float] + presence_penalty: float | None """Presence penalty (-2.0 to 2.0)""" class CreateRunRequest(TypedDict, total=False): """Request parameters for creating a run""" - data_source: Required[Dict[str, Any]] + data_source: Required[dict[str, Any]] """Data source configuration for the run (can be jsonl, completions, or responses type)""" - name: Optional[str] + name: str | None """Optional name for the run""" - metadata: Optional[Dict[str, Any]] + metadata: dict[str, Any] | None """Optional metadata for the run""" class ListRunsParams(TypedDict, total=False): """Query parameters for listing runs""" - limit: Optional[int] + limit: int | None """Number of results to return per page. Maximum value is 100. Defaults to 20.""" - after: Optional[str] + after: str | None """Cursor for pagination - returns runs after this ID""" - before: Optional[str] + before: str | None """Cursor for pagination - returns runs before this ID""" - order: Optional[Literal["asc", "desc"]] + order: Literal["asc", "desc"] | None """Sort order for results. Defaults to 'desc'.""" @@ -311,7 +311,7 @@ class PerTestingCriteriaResult(BaseModel): result_counts: ResultCounts """Result counts for this criteria""" - average_score: Optional[float] = None + average_score: float | None = None """Average score for this criteria""" @@ -330,43 +330,43 @@ class Run(BaseModel): status: Literal["queued", "running", "completed", "failed", "cancelled"] """Current status of the run""" - data_source: Dict[str, Any] + data_source: dict[str, Any] """Data source configuration used for the run""" eval_id: str """ID of the evaluation this run belongs to""" - name: Optional[str] = None + name: str | None = None """Name of the run""" - started_at: Optional[int] = None + started_at: int | None = None """Unix timestamp of when the run started""" - completed_at: Optional[int] = None + completed_at: int | None = None """Unix timestamp of when the run completed""" - model: Optional[str] = None + model: str | None = None """Model used for the run, if any""" - per_model_usage: Optional[Any] = None + per_model_usage: Any | None = None """Model usage details per model, if available""" - per_testing_criteria_results: Optional[List[PerTestingCriteriaResult]] = None + per_testing_criteria_results: list[PerTestingCriteriaResult] | None = None """Per-criteria results""" - report_url: Optional[str] = None + report_url: str | None = None """URL for the evaluation report""" - result_counts: Optional[Dict[str, int]] = None + result_counts: dict[str, int] | None = None """Aggregate result counts (e.g., {"passed": 0, "failed": 0, "errored": 0, "total": 0})""" - shared_with_openai: Optional[bool] = None + shared_with_openai: bool | None = None """Whether run is shared with OpenAI""" - metadata: Optional[Dict[str, Any]] = None + metadata: dict[str, Any] | None = None """Additional metadata""" - error: Optional[Dict[str, Any]] = None + error: dict[str, Any] | None = None """Error details if the run failed""" @@ -376,13 +376,13 @@ class ListRunsResponse(BaseModel): object: str = "list" """Object type, always 'list'""" - data: List[Run] + data: list[Run] """List of runs""" - first_id: Optional[str] = None + first_id: str | None = None """ID of the first run in the list""" - last_id: Optional[str] = None + last_id: str | None = None """ID of the last run in the list""" has_more: bool = False @@ -408,8 +408,8 @@ class RunDeleteResponse(BaseModel): run_id: str """The ID of the deleted run""" - object: Optional[str] = "eval.run.deleted" + object: str | None = "eval.run.deleted" """Object type, always 'eval.run.deleted'""" - deleted: Optional[bool] = True + deleted: bool | None = True """Whether the run was successfully deleted""" diff --git a/litellm/types/llms/openrouter.py b/litellm/types/llms/openrouter.py index 39ed7e104fb..1558ff576b5 100644 --- a/litellm/types/llms/openrouter.py +++ b/litellm/types/llms/openrouter.py @@ -1,11 +1,7 @@ -import json -from enum import Enum -from typing import Any, Dict, List, Literal, Optional, Tuple, Union - from typing_extensions import TypedDict class OpenRouterErrorMessage(TypedDict): message: str code: int - metadata: Dict + metadata: dict diff --git a/litellm/types/llms/recraft.py b/litellm/types/llms/recraft.py index 35e4101ee05..61cd71a296e 100644 --- a/litellm/types/llms/recraft.py +++ b/litellm/types/llms/recraft.py @@ -1,20 +1,18 @@ -from typing import Dict, List, Optional - from typing_extensions import TypedDict class RecraftImageGenerationRequestParams(TypedDict, total=False): prompt: str - text_layout: Optional[List[Dict]] - n: Optional[int] - style_id: Optional[str] - style: Optional[str] - substyle: Optional[str] - model: Optional[str] - response_format: Optional[str] - size: Optional[str] - negative_prompt: Optional[str] - controls: Optional[Dict] + text_layout: list[dict] | None + n: int | None + style_id: str | None + style: str | None + substyle: str | None + model: str | None + response_format: str | None + size: str | None + negative_prompt: str | None + controls: dict | None class RecraftImageEditRequestParams(TypedDict, total=False): @@ -26,11 +24,11 @@ class RecraftImageEditRequestParams(TypedDict, total=False): prompt: str # required - A text description of areas to change. Max 1000 bytes strength: float # required - Defines difference with original image, [0, 1] - model: Optional[str] # The model to use, default is recraftv3 - n: Optional[int] # The number of images to generate, must be between 1 and 6 - style_id: Optional[str] # Use a previously uploaded style as reference - style: Optional[str] # The style of generated images, default is realistic_image - substyle: Optional[str] # Additional style specification - response_format: Optional[str] # Format of returned images: url or b64_json - negative_prompt: Optional[str] # Description of undesired elements - controls: Optional[Dict] # Custom parameters to tweak generation process + model: str | None # The model to use, default is recraftv3 + n: int | None # The number of images to generate, must be between 1 and 6 + style_id: str | None # Use a previously uploaded style as reference + style: str | None # The style of generated images, default is realistic_image + substyle: str | None # Additional style specification + response_format: str | None # Format of returned images: url or b64_json + negative_prompt: str | None # Description of undesired elements + controls: dict | None # Custom parameters to tweak generation process diff --git a/litellm/types/llms/rerank.py b/litellm/types/llms/rerank.py index fac093161c1..f7f90cf6acf 100644 --- a/litellm/types/llms/rerank.py +++ b/litellm/types/llms/rerank.py @@ -1,20 +1,9 @@ -import json -from enum import Enum -from typing import Any, Dict, List, Literal, Optional, Tuple, Union - from typing_extensions import ( - Protocol, - Required, - Self, TypedDict, - TypeGuard, - get_origin, - override, - runtime_checkable, ) class InfinityRerankResult(TypedDict): index: int relevance_score: float - document: Optional[str] + document: str | None diff --git a/litellm/types/llms/stability.py b/litellm/types/llms/stability.py index f5aa9bc01e9..9c1cb2af7a7 100644 --- a/litellm/types/llms/stability.py +++ b/litellm/types/llms/stability.py @@ -4,7 +4,7 @@ Type definitions for Stability AI API API Reference: https://platform.stability.ai/docs/api-reference """ -from typing import Final, List, Literal, Optional +from typing import Final, Literal from typing_extensions import TypedDict @@ -20,15 +20,15 @@ class StabilityImageGenerationRequest(TypedDict, total=False): """ prompt: str # Required - text prompt for image generation - negative_prompt: Optional[str] # What to avoid in the image - aspect_ratio: Optional[str] # e.g., "1:1", "16:9", "9:16", "4:3", "3:4", "21:9", "9:21" - seed: Optional[int] # Random seed for reproducibility (0 to 4294967294) - output_format: Optional[Literal["jpeg", "png", "webp"]] # Output format - model: Optional[str] # Model variant (e.g., "sd3.5-large", "sd3.5-medium") - mode: Optional[Literal["text-to-image", "image-to-image"]] # Generation mode - image: Optional[str] # Base64-encoded image for image-to-image - strength: Optional[float] # How much to transform the image (0-1) - style_preset: Optional[str] # Style preset name + negative_prompt: str | None # What to avoid in the image + aspect_ratio: str | None # e.g., "1:1", "16:9", "9:16", "4:3", "3:4", "21:9", "9:21" + seed: int | None # Random seed for reproducibility (0 to 4294967294) + output_format: Literal["jpeg", "png", "webp"] | None # Output format + model: str | None # Model variant (e.g., "sd3.5-large", "sd3.5-medium") + mode: Literal["text-to-image", "image-to-image"] | None # Generation mode + image: str | None # Base64-encoded image for image-to-image + strength: float | None # How much to transform the image (0-1) + style_preset: str | None # Style preset name class StabilityImageEditRequest(StabilityImageGenerationRequest): @@ -38,7 +38,7 @@ class StabilityImageEditRequest(StabilityImageGenerationRequest): Endpoint: /v2beta/stable-image/edit/inpaint """ - mask: Optional[str] # Base64-encoded mask (white = edit, black = keep) + mask: str | None # Base64-encoded mask (white = edit, black = keep) class StabilityImageGenerationResponse(TypedDict, total=False): @@ -62,11 +62,11 @@ class StabilityUpscaleRequest(TypedDict, total=False): """ image: str # Required - Base64-encoded image to upscale - prompt: Optional[str] # Text prompt (required for creative upscale) - negative_prompt: Optional[str] # What to avoid - output_format: Optional[Literal["jpeg", "png", "webp"]] # Output format - seed: Optional[int] # Random seed - creativity: Optional[float] # Creativity level for creative upscale (0-0.35) + prompt: str | None # Text prompt (required for creative upscale) + negative_prompt: str | None # What to avoid + output_format: Literal["jpeg", "png", "webp"] | None # Output format + seed: int | None # Random seed + creativity: float | None # Creativity level for creative upscale (0-0.35) class StabilityInpaintRequest(TypedDict, total=False): @@ -78,11 +78,11 @@ class StabilityInpaintRequest(TypedDict, total=False): image: str # Required - Base64-encoded image to edit prompt: str # Required - Description of desired changes - mask: Optional[str] # Base64-encoded mask (white = edit, black = keep) - negative_prompt: Optional[str] # What to avoid - seed: Optional[int] # Random seed - output_format: Optional[Literal["jpeg", "png", "webp"]] # Output format - grow_mask: Optional[int] # Pixels to grow the mask by (0-100) + mask: str | None # Base64-encoded mask (white = edit, black = keep) + negative_prompt: str | None # What to avoid + seed: int | None # Random seed + output_format: Literal["jpeg", "png", "webp"] | None # Output format + grow_mask: int | None # Pixels to grow the mask by (0-100) class StabilityOutpaintRequest(TypedDict, total=False): @@ -93,15 +93,15 @@ class StabilityOutpaintRequest(TypedDict, total=False): """ image: str # Required - Base64-encoded image to expand - prompt: Optional[str] # Description of content to generate - negative_prompt: Optional[str] # What to avoid - left: Optional[int] # Pixels to expand left (0-2000) - right: Optional[int] # Pixels to expand right (0-2000) - up: Optional[int] # Pixels to expand up (0-2000) - down: Optional[int] # Pixels to expand down (0-2000) - seed: Optional[int] # Random seed - output_format: Optional[Literal["jpeg", "png", "webp"]] # Output format - creativity: Optional[float] # How creative to be (0-1) + prompt: str | None # Description of content to generate + negative_prompt: str | None # What to avoid + left: int | None # Pixels to expand left (0-2000) + right: int | None # Pixels to expand right (0-2000) + up: int | None # Pixels to expand up (0-2000) + down: int | None # Pixels to expand down (0-2000) + seed: int | None # Random seed + output_format: Literal["jpeg", "png", "webp"] | None # Output format + creativity: float | None # How creative to be (0-1) class StabilityEraseRequest(TypedDict, total=False): @@ -112,10 +112,10 @@ class StabilityEraseRequest(TypedDict, total=False): """ image: str # Required - Base64-encoded image - mask: Optional[str] # Base64-encoded mask (white = erase) - seed: Optional[int] # Random seed - output_format: Optional[Literal["jpeg", "png", "webp"]] # Output format - grow_mask: Optional[int] # Pixels to grow the mask by (0-100) + mask: str | None # Base64-encoded mask (white = erase) + seed: int | None # Random seed + output_format: Literal["jpeg", "png", "webp"] | None # Output format + grow_mask: int | None # Pixels to grow the mask by (0-100) class StabilitySearchReplaceRequest(TypedDict, total=False): @@ -128,10 +128,10 @@ class StabilitySearchReplaceRequest(TypedDict, total=False): image: str # Required - Base64-encoded image prompt: str # Required - Description of object to add search_prompt: str # Required - Description of object to find and replace - negative_prompt: Optional[str] # What to avoid - seed: Optional[int] # Random seed - output_format: Optional[Literal["jpeg", "png", "webp"]] # Output format - grow_mask: Optional[int] # Pixels to grow detected mask + negative_prompt: str | None # What to avoid + seed: int | None # Random seed + output_format: Literal["jpeg", "png", "webp"] | None # Output format + grow_mask: int | None # Pixels to grow detected mask class StabilityRemoveBackgroundRequest(TypedDict, total=False): @@ -142,7 +142,7 @@ class StabilityRemoveBackgroundRequest(TypedDict, total=False): """ image: str # Required - Base64-encoded image - output_format: Optional[Literal["png", "webp"]] # Output format (no jpeg - needs transparency) + output_format: Literal["png", "webp"] | None # Output format (no jpeg - needs transparency) class StabilityControlRequest(TypedDict, total=False): @@ -157,10 +157,10 @@ class StabilityControlRequest(TypedDict, total=False): image: str # Required - Base64-encoded control image (sketch/structure/style reference) prompt: str # Required - Description of desired output - negative_prompt: Optional[str] # What to avoid - control_strength: Optional[float] # How strongly to follow the control (0-1) - seed: Optional[int] # Random seed - output_format: Optional[Literal["jpeg", "png", "webp"]] # Output format + negative_prompt: str | None # What to avoid + control_strength: float | None # How strongly to follow the control (0-1) + seed: int | None # Random seed + output_format: Literal["jpeg", "png", "webp"] | None # Output format class StabilityEditResponse(TypedDict, total=False): diff --git a/litellm/types/llms/vertex_ai.py b/litellm/types/llms/vertex_ai.py index 4981ecf1784..b750563432e 100644 --- a/litellm/types/llms/vertex_ai.py +++ b/litellm/types/llms/vertex_ai.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Final, Literal from typing_extensions import ( Required, @@ -11,7 +11,7 @@ from litellm.types.llms.openai import EmbeddingInput # Gemini supports nested-list inputs (e.g. [["text", "image"]]) as an explicit # opt-in for combined embeddings — a provider-specific extension of the # OpenAI-faithful EmbeddingInput shape. -GeminiEmbeddingInput = Union[EmbeddingInput, List[List[str]]] +GeminiEmbeddingInput = EmbeddingInput | list[list[str]] class FunctionResponse(TypedDict, total=False): @@ -19,8 +19,8 @@ class FunctionResponse(TypedDict, total=False): # Supported on Gemini 3+; older Gemini models reject this field. id: str name: Required[str] - response: Optional[dict] - parts: List["FunctionResponsePartType"] + response: dict | None + parts: list["FunctionResponsePartType"] class FunctionCall(TypedDict, total=False): @@ -28,7 +28,7 @@ class FunctionCall(TypedDict, total=False): # Older Gemini models omit/reject this field. id: str name: Required[str] - args: Optional[dict] + args: dict | None class FileDataType(TypedDict): @@ -89,7 +89,7 @@ class HttpxServerSideToolCall(TypedDict, total=False): class HttpxServerSideToolResponse(TypedDict, total=False): toolType: str id: str - response: Union[str, dict] + response: str | dict class HttpxPartType(TypedDict, total=False): @@ -109,16 +109,16 @@ class HttpxPartType(TypedDict, total=False): class HttpxContentType(TypedDict, total=False): role: Literal["user", "model"] - parts: List[HttpxPartType] + parts: list[HttpxPartType] class ContentType(TypedDict, total=False): role: Literal["user", "model"] - parts: Required[List[PartType]] + parts: Required[list[PartType]] class SystemInstructions(TypedDict): - parts: Required[List[PartType]] + parts: Required[list[PartType]] class Schema(TypedDict, total=False): @@ -131,10 +131,10 @@ class Schema(TypedDict, total=False): items: "Schema" minItems: str maxItems: str - enum: List[str] - properties: Dict[str, "Schema"] - propertyOrdering: List[str] - required: List[str] + enum: list[str] + properties: dict[str, "Schema"] + propertyOrdering: list[str] + required: list[str] minProperties: str maxProperties: str minimum: float @@ -143,13 +143,13 @@ class Schema(TypedDict, total=False): maxLength: str pattern: str example: Any - anyOf: List["Schema"] + anyOf: list["Schema"] class FunctionDeclaration(TypedDict, total=False): name: Required[str] description: str - parameters: Union[Schema, dict] + parameters: Schema | dict response: Schema @@ -163,7 +163,7 @@ class Retrieval(TypedDict): class FunctionCallingConfig(TypedDict, total=False): mode: Literal["ANY", "AUTO", "NONE"] - allowed_function_names: List[str] + allowed_function_names: list[str] HarmCategory = Literal[ @@ -237,7 +237,7 @@ class GenerationConfig(TypedDict, total=False): top_k: float candidate_count: int max_output_tokens: int - stop_sequences: List[str] + stop_sequences: list[str] presence_penalty: float frequency_penalty: float response_mime_type: Literal["text/plain", "application/json"] @@ -247,7 +247,7 @@ class GenerationConfig(TypedDict, total=False): seed: int responseLogprobs: bool logprobs: int - responseModalities: List[GeminiResponseModalities] + responseModalities: list[GeminiResponseModalities] imageConfig: GeminiImageConfig thinkingConfig: GeminiThinkingConfig mediaResolution: str @@ -267,7 +267,7 @@ class VertexToolName(str, Enum): class Tools(TypedDict, total=False): - function_declarations: List[FunctionDeclaration] + function_declarations: list[FunctionDeclaration] googleSearch: dict googleSearchRetrieval: dict enterpriseWebSearch: dict @@ -300,12 +300,12 @@ class UsageMetadata(TypedDict, total=False): responseTokenCount: int cachedContentTokenCount: int toolUsePromptTokenCount: int - toolUsePromptTokensDetails: List[PromptTokensDetails] - promptTokensDetails: List[PromptTokensDetails] - cacheTokensDetails: List[PromptTokensDetails] + toolUsePromptTokensDetails: list[PromptTokensDetails] + promptTokensDetails: list[PromptTokensDetails] + cacheTokensDetails: list[PromptTokensDetails] thoughtsTokenCount: int - responseTokensDetails: List[PromptTokensDetails] - candidatesTokensDetails: List[PromptTokensDetails] # Alternative key name used in some responses + responseTokensDetails: list[PromptTokensDetails] + candidatesTokensDetails: list[PromptTokensDetails] # Alternative key name used in some responses class TokenCountDetailsResponse(TypedDict): @@ -317,14 +317,14 @@ class TokenCountDetailsResponse(TypedDict): """ totalTokens: int - promptTokensDetails: List[PromptTokensDetails] + promptTokensDetails: list[PromptTokensDetails] class CachedContent(TypedDict, total=False): ttl: TTL expire_time: str - contents: List[ContentType] - tools: List[Tools] + contents: list[ContentType] + tools: list[Tools] createTime: str # "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z" updateTime: str # "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z" usageMetadata: UsageMetadata @@ -337,19 +337,19 @@ class CachedContent(TypedDict, total=False): class RequestBody(TypedDict, total=False): - contents: Required[List[ContentType]] + contents: Required[list[ContentType]] system_instruction: SystemInstructions tools: Tools toolConfig: ToolConfig - safetySettings: List[SafetSettingsConfig] + safetySettings: list[SafetSettingsConfig] generationConfig: GenerationConfig cachedContent: str - labels: Dict[str, str] + labels: dict[str, str] serviceTier: str class CachedContentRequestBody(TypedDict, total=False): - contents: Required[List[ContentType]] + contents: Required[list[ContentType]] system_instruction: SystemInstructions tools: Tools toolConfig: ToolConfig @@ -359,7 +359,7 @@ class CachedContentRequestBody(TypedDict, total=False): class CachedContentListAllResponseBody(TypedDict, total=False): - cachedContents: List[CachedContent] + cachedContents: list[CachedContent] nextPageToken: str @@ -387,7 +387,7 @@ class Citation(TypedDict): class CitationMetadata(TypedDict): - citations: List[Citation] + citations: list[Citation] class SearchEntryPoint(TypedDict, total=False): @@ -396,9 +396,9 @@ class SearchEntryPoint(TypedDict, total=False): class GroundingMetadata(TypedDict, total=False): - webSearchQueries: List[str] + webSearchQueries: list[str] searchEntryPoint: SearchEntryPoint - groundingAttributions: List[dict] + groundingAttributions: list[dict] class LogprobsCandidate(TypedDict): @@ -408,12 +408,12 @@ class LogprobsCandidate(TypedDict): class LogprobsTopCandidate(TypedDict): - candidates: List[LogprobsCandidate] + candidates: list[LogprobsCandidate] class LogprobsResult(TypedDict, total=False): - topCandidates: List[LogprobsTopCandidate] - chosenCandidates: List[LogprobsCandidate] + topCandidates: list[LogprobsTopCandidate] + chosenCandidates: list[LogprobsCandidate] class UrlMetadata(TypedDict, total=False): @@ -422,7 +422,7 @@ class UrlMetadata(TypedDict, total=False): class UrlContextMetadata(TypedDict, total=False): - urlMetadata: List[UrlMetadata] + urlMetadata: list[UrlMetadata] class Candidates(TypedDict, total=False): @@ -441,7 +441,7 @@ class Candidates(TypedDict, total=False): "MALFORMED_FUNCTION_CALL", "IMAGE_SAFETY", ] - safetyRatings: List[SafetyRatings] + safetyRatings: list[SafetyRatings] citationMetadata: CitationMetadata groundingMetadata: GroundingMetadata finishMessage: str @@ -451,21 +451,21 @@ class Candidates(TypedDict, total=False): class PromptFeedback(TypedDict): blockReason: str - safetyRatings: List[SafetyRatings] + safetyRatings: list[SafetyRatings] blockReasonMessage: str class GenerateContentResponseBody(TypedDict, total=False): - candidates: List[Candidates] + candidates: list[Candidates] promptFeedback: PromptFeedback usageMetadata: Required[UsageMetadata] responseId: str class FineTuneHyperparameters(TypedDict, total=False): - epoch_count: Optional[int] - learning_rate_multiplier: Optional[float] - adapter_size: Optional[ + epoch_count: int | None + learning_rate_multiplier: float | None + adapter_size: ( Literal[ "ADAPTER_SIZE_UNSPECIFIED", "ADAPTER_SIZE_ONE", @@ -473,43 +473,41 @@ class FineTuneHyperparameters(TypedDict, total=False): "ADAPTER_SIZE_EIGHT", "ADAPTER_SIZE_SIXTEEN", ] - ] + | None + ) class FineTunesupervisedTuningSpec(TypedDict, total=False): training_dataset_uri: str - validation_dataset: Optional[str] - tuned_model_display_name: Optional[str] - hyperParameters: Optional[FineTuneHyperparameters] + validation_dataset: str | None + tuned_model_display_name: str | None + hyperParameters: FineTuneHyperparameters | None class FineTuneJobCreate(TypedDict, total=False): baseModel: str supervisedTuningSpec: FineTunesupervisedTuningSpec - tunedModelDisplayName: Optional[str] + tunedModelDisplayName: str | None class ResponseSupervisedTuningSpec(TypedDict, total=False): - trainingDatasetUri: Optional[str] - hyperParameters: Optional[FineTuneHyperparameters] + trainingDatasetUri: str | None + hyperParameters: FineTuneHyperparameters | None class ResponseTuningJob(TypedDict): - name: Optional[str] - tunedModelDisplayName: Optional[str] - baseModel: Optional[str] - supervisedTuningSpec: Optional[ResponseSupervisedTuningSpec] - state: Optional[ + name: str | None + tunedModelDisplayName: str | None + baseModel: str | None + supervisedTuningSpec: ResponseSupervisedTuningSpec | None + state: ( Literal[ - "JOB_STATE_PENDING", - "JOB_STATE_RUNNING", - "JOB_STATE_SUCCEEDED", - "JOB_STATE_FAILED", - "JOB_STATE_CANCELLED", + "JOB_STATE_PENDING", "JOB_STATE_RUNNING", "JOB_STATE_SUCCEEDED", "JOB_STATE_FAILED", "JOB_STATE_CANCELLED" ] - ] - createTime: Optional[str] - updateTime: Optional[str] + | None + ) + createTime: str | None + updateTime: str | None class VideoSegmentConfig(TypedDict, total=False): @@ -524,9 +522,9 @@ class InstanceVideo(TypedDict, total=False): class InstanceImage(TypedDict, total=False): - gcsUri: Optional[str] - bytesBase64Encoded: Optional[str] - mimeType: Optional[str] + gcsUri: str | None + bytesBase64Encoded: str | None + mimeType: str | None class Instance(TypedDict, total=False): @@ -536,24 +534,24 @@ class Instance(TypedDict, total=False): class VertexMultimodalEmbeddingRequest(TypedDict, total=False): - instances: Required[List[Instance]] + instances: Required[list[Instance]] parameters: dict class VideoEmbedding(TypedDict): startOffsetSec: int endOffsetSec: int - embedding: List[float] + embedding: list[float] class MultimodalPrediction(TypedDict, total=False): - textEmbedding: List[float] - imageEmbedding: List[float] - videoEmbeddings: List[VideoEmbedding] + textEmbedding: list[float] + imageEmbedding: list[float] + videoEmbeddings: list[VideoEmbedding] class MultimodalPredictions(TypedDict): - predictions: List[MultimodalPrediction] + predictions: list[MultimodalPrediction] class VertexAICachedContentResponseObject(TypedDict): @@ -580,7 +578,7 @@ class VertexAITextEmbeddingsRequestBody(TypedDict, total=False): class ContentEmbeddings(TypedDict): - values: List[int] + values: list[int] class VertexAITextEmbeddingsResponseObject(TypedDict): @@ -592,11 +590,11 @@ class EmbedContentRequest(VertexAITextEmbeddingsRequestBody): class VertexAIBatchEmbeddingsRequestBody(TypedDict, total=False): - requests: List[EmbedContentRequest] + requests: list[EmbedContentRequest] class VertexAIBatchEmbeddingsResponseObject(TypedDict): - embeddings: List[ContentEmbeddings] + embeddings: list[ContentEmbeddings] class GeminiEmbedContentRequestBody(TypedDict, total=False): @@ -614,7 +612,7 @@ class GeminiEmbedContentResponseObject(TypedDict): class GcsSource(TypedDict): - uris: List[str] + uris: list[str] class InputConfig(TypedDict): @@ -724,7 +722,7 @@ class VertexVideoGenerationParameters(TypedDict, total=False): class VertexVideoGenerationRequest(TypedDict): """Complete request body for Vertex AI video generation""" - instances: Required[List[VertexVideoGenerationInstance]] + instances: Required[list[VertexVideoGenerationInstance]] parameters: VertexVideoGenerationParameters @@ -741,12 +739,12 @@ class VertexVideoGenerationResponse(TypedDict, total=False): name: str done: bool - response: Dict[str, Any] - metadata: Dict[str, Any] - error: Dict[str, Any] + response: dict[str, Any] + metadata: dict[str, Any] + error: dict[str, Any] -VERTEX_CREDENTIALS_TYPES = Union[str, Dict[str, str]] +VERTEX_CREDENTIALS_TYPES = str | dict[str, str] class VertexPartnerProvider(str, Enum): diff --git a/litellm/types/llms/vertex_ai_text_to_speech.py b/litellm/types/llms/vertex_ai_text_to_speech.py index 8ac3e352167..e8f9fbe4a24 100644 --- a/litellm/types/llms/vertex_ai_text_to_speech.py +++ b/litellm/types/llms/vertex_ai_text_to_speech.py @@ -4,8 +4,6 @@ Type definitions for Vertex AI Text-to-Speech API Reference: https://cloud.google.com/text-to-speech/docs/reference/rest/v1/text/synthesize """ -from typing import Optional - from typing_extensions import TypedDict @@ -16,8 +14,8 @@ class VertexTextToSpeechInput(TypedDict, total=False): Exactly one of text or ssml must be provided. """ - text: Optional[str] - ssml: Optional[str] + text: str | None + ssml: str | None class VertexTextToSpeechVoice(TypedDict, total=False): @@ -55,4 +53,4 @@ class VertexTextToSpeechRequest(TypedDict, total=False): input: VertexTextToSpeechInput voice: VertexTextToSpeechVoice - audioConfig: Optional[VertexTextToSpeechAudioConfig] + audioConfig: VertexTextToSpeechAudioConfig | None diff --git a/litellm/types/llms/watsonx.py b/litellm/types/llms/watsonx.py index 5ca419985f2..58faad65755 100644 --- a/litellm/types/llms/watsonx.py +++ b/litellm/types/llms/watsonx.py @@ -1,19 +1,18 @@ from enum import Enum -from typing import List, Optional from typing_extensions import NotRequired, TypedDict class WatsonXAPIParams(TypedDict): - project_id: Optional[str] - space_id: Optional[str] - region_name: Optional[str] + project_id: str | None + space_id: str | None + region_name: str | None class WatsonXCredentials(TypedDict): api_key: str api_base: str - token: Optional[str] + token: str | None class WatsonXAudioTranscriptionRequestBody(TypedDict): @@ -45,7 +44,7 @@ class WatsonXAudioTranscriptionRequestBody(TypedDict): temperature: NotRequired[float] """Sampling temperature (0-1)""" - timestamp_granularities: NotRequired[List[str]] + timestamp_granularities: NotRequired[list[str]] """Timestamp granularities: ['word', 'segment']""" diff --git a/litellm/types/llms/xai.py b/litellm/types/llms/xai.py index 8500e218d83..ec711f6d042 100644 --- a/litellm/types/llms/xai.py +++ b/litellm/types/llms/xai.py @@ -1,28 +1,28 @@ -from typing import List, Literal, Optional, TypedDict +from typing import Literal, TypedDict class XAIWebSearchFilters(TypedDict, total=False): """Filters for XAI web search tool""" - allowed_domains: Optional[List[str]] # Max 5 domains - excluded_domains: Optional[List[str]] # Max 5 domains + allowed_domains: list[str] | None # Max 5 domains + excluded_domains: list[str] | None # Max 5 domains class XAIWebSearchTool(TypedDict, total=False): """XAI web search tool configuration""" type: Literal["web_search"] - filters: Optional[XAIWebSearchFilters] - enable_image_understanding: Optional[bool] + filters: XAIWebSearchFilters | None + enable_image_understanding: bool | None class XAIXSearchTool(TypedDict, total=False): """XAI X (Twitter) search tool configuration""" type: Literal["x_search"] - allowed_x_handles: Optional[List[str]] # Max 10 handles - excluded_x_handles: Optional[List[str]] # Max 10 handles - from_date: Optional[str] # ISO8601 format: YYYY-MM-DD - to_date: Optional[str] # ISO8601 format: YYYY-MM-DD - enable_image_understanding: Optional[bool] - enable_video_understanding: Optional[bool] + allowed_x_handles: list[str] | None # Max 10 handles + excluded_x_handles: list[str] | None # Max 10 handles + from_date: str | None # ISO8601 format: YYYY-MM-DD + to_date: str | None # ISO8601 format: YYYY-MM-DD + enable_image_understanding: bool | None + enable_video_understanding: bool | None diff --git a/litellm/types/management_endpoints/__init__.py b/litellm/types/management_endpoints/__init__.py index 3b501443edd..497cc70fd99 100644 --- a/litellm/types/management_endpoints/__init__.py +++ b/litellm/types/management_endpoints/__init__.py @@ -20,14 +20,14 @@ from .router_settings_endpoints import ( ) __all__ = [ + "CACHE_SETTINGS_FIELDS", + "COORDINATION_REDIS_SETTINGS_FIELDS", + "REDIS_TYPE_DESCRIPTIONS", "ROUTER_SETTINGS_FIELDS", "ROUTING_STRATEGY_DESCRIPTIONS", - "RouterSettingsField", - "CACHE_SETTINGS_FIELDS", - "REDIS_TYPE_DESCRIPTIONS", "CacheSettingsField", - "COORDINATION_REDIS_SETTINGS_FIELDS", "CoordinationRedisSection", "CoordinationRedisSettingsField", "CoordinationRedisSource", + "RouterSettingsField", ] diff --git a/litellm/types/management_endpoints/cache_settings_endpoints.py b/litellm/types/management_endpoints/cache_settings_endpoints.py index 255bba9b814..2e6d0be9071 100644 --- a/litellm/types/management_endpoints/cache_settings_endpoints.py +++ b/litellm/types/management_endpoints/cache_settings_endpoints.py @@ -2,7 +2,7 @@ Types and field definitions for cache settings management endpoints """ -from typing import Any, Dict, Final, List, Optional +from typing import Any, Final from pydantic import BaseModel @@ -13,14 +13,14 @@ class CacheSettingsField(BaseModel): field_value: Any field_description: str field_default: Any = None - options: Optional[List[str]] = None # For fields with predefined options/enum values + options: list[str] | None = None # For fields with predefined options/enum values ui_field_name: str # User-friendly display name - link: Optional[str] = None # Documentation link for the field - redis_type: Optional[str] = None # Which Redis type this field applies to (node, cluster, sentinel) + link: str | None = None # Documentation link for the field + redis_type: str | None = None # Which Redis type this field applies to (node, cluster, sentinel) # Redis type descriptions -REDIS_TYPE_DESCRIPTIONS: Final[Dict[str, str]] = { +REDIS_TYPE_DESCRIPTIONS: Final[dict[str, str]] = { "node": "Standard Redis node/single instance", "cluster": "Redis Cluster mode for high availability and horizontal scaling", "sentinel": "Redis Sentinel mode for high availability with automatic failover", @@ -28,7 +28,7 @@ REDIS_TYPE_DESCRIPTIONS: Final[Dict[str, str]] = { # Define all available cache settings fields -CACHE_SETTINGS_FIELDS: Final[List[CacheSettingsField]] = [ +CACHE_SETTINGS_FIELDS: Final[list[CacheSettingsField]] = [ CacheSettingsField( field_name="redis_type", field_type="String", diff --git a/litellm/types/management_endpoints/coordination_redis_endpoints.py b/litellm/types/management_endpoints/coordination_redis_endpoints.py index 611c5e64153..30033346ed7 100644 --- a/litellm/types/management_endpoints/coordination_redis_endpoints.py +++ b/litellm/types/management_endpoints/coordination_redis_endpoints.py @@ -2,7 +2,7 @@ Types and field definitions for coordination Redis settings management endpoints """ -from typing import Final, Literal, Optional +from typing import Final, Literal from pydantic import BaseModel @@ -14,9 +14,9 @@ CoordinationRedisSource = Literal["coordination_redis", "cache_backend", "enviro class CoordinationRedisSettingsField(BaseModel): field_name: str field_type: str - field_value: Optional[object] = None + field_value: object | None = None field_description: str - field_default: Optional[object] = None + field_default: object | None = None ui_field_name: str section: CoordinationRedisSection diff --git a/litellm/types/management_endpoints/router_settings_endpoints.py b/litellm/types/management_endpoints/router_settings_endpoints.py index a243c27d49c..cef180b202a 100644 --- a/litellm/types/management_endpoints/router_settings_endpoints.py +++ b/litellm/types/management_endpoints/router_settings_endpoints.py @@ -2,7 +2,7 @@ Types and field definitions for router settings management endpoints """ -from typing import Any, Dict, Final, List, Literal, Optional +from typing import Any, Final, Literal from pydantic import BaseModel, Field, field_validator @@ -13,7 +13,7 @@ class FallbackCreateRequest(BaseModel): """Request model for creating/updating fallbacks""" model: str = Field(description="The model name to configure fallbacks for (e.g., 'gpt-3.5-turbo')") - fallback_models: List[str] = Field( + fallback_models: list[str] = Field( description="List of fallback model names in order of priority", min_length=1, ) @@ -24,7 +24,7 @@ class FallbackCreateRequest(BaseModel): @field_validator("fallback_models") @classmethod - def validate_fallback_models(cls, v: List[str]) -> List[str]: + def validate_fallback_models(cls, v: list[str]) -> list[str]: if not v: raise ValueError("fallback_models must contain at least one model") if len(v) != len(set(v)): @@ -43,7 +43,7 @@ class FallbackResponse(BaseModel): """Response model for fallback operations""" model: str = Field(description="The model name") - fallback_models: List[str] = Field(description="List of fallback model names") + fallback_models: list[str] = Field(description="List of fallback model names") fallback_type: str = Field(description="Type of fallback") message: str = Field(description="Success message") @@ -52,7 +52,7 @@ class FallbackGetResponse(BaseModel): """Response model for getting fallbacks""" model: str = Field(description="The model name") - fallback_models: List[str] = Field(description="List of fallback model names") + fallback_models: list[str] = Field(description="List of fallback model names") fallback_type: str = Field(description="Type of fallback") @@ -73,13 +73,13 @@ class RouterSettingsField(BaseModel): field_value: Any field_description: str field_default: Any = None - options: Optional[List[str]] = None # For fields with predefined options/enum values + options: list[str] | None = None # For fields with predefined options/enum values ui_field_name: str # User-friendly display name - link: Optional[str] = None # Documentation link for the field + link: str | None = None # Documentation link for the field # Routing strategy descriptions -ROUTING_STRATEGY_DESCRIPTIONS: Final[Dict[str, str]] = { +ROUTING_STRATEGY_DESCRIPTIONS: Final[dict[str, str]] = { "simple-shuffle": "Randomly picks a deployment from the list. Simple and fast.", "least-busy": "Routes to the deployment with the lowest number of ongoing requests.", "latency-based-routing": "Routes to the deployment with the lowest latency over a sliding window.", @@ -90,7 +90,7 @@ ROUTING_STRATEGY_DESCRIPTIONS: Final[Dict[str, str]] = { # Define all available router settings fields -ROUTER_SETTINGS_FIELDS: Final[List[RouterSettingsField]] = [ +ROUTER_SETTINGS_FIELDS: Final[list[RouterSettingsField]] = [ RouterSettingsField( field_name="routing_strategy", field_type="String", diff --git a/litellm/types/mcp.py b/litellm/types/mcp.py index 5d10379554b..57437ea7e54 100644 --- a/litellm/types/mcp.py +++ b/litellm/types/mcp.py @@ -1,5 +1,5 @@ import enum -from typing import Any, Dict, Final, List, Literal, Optional, TYPE_CHECKING, Union +from typing import TYPE_CHECKING, Any, Final, Literal from pydantic import BaseModel from typing_extensions import TypedDict @@ -52,7 +52,7 @@ DEFAULT_SUBJECT_TOKEN_TYPE: Final = "urn:ietf:params:oauth:token-type:access_tok # MCP Literals MCPTransportType = Literal[MCPTransport.sse, MCPTransport.http, MCPTransport.stdio] MCPSpecVersionType = Literal[MCPSpecVersion.nov_2024, MCPSpecVersion.mar_2025, MCPSpecVersion.jun_2025] -MCPAuthType = Optional[ +MCPAuthType = ( Literal[ MCPAuth.none, MCPAuth.api_key, @@ -67,7 +67,8 @@ MCPAuthType = Optional[ MCPAuth.true_passthrough, MCPAuth.oauth_delegate, ] -] + | None +) class MCPPublicServer(BaseModel): @@ -77,12 +78,12 @@ class MCPPublicServer(BaseModel): server_id: str name: str - alias: Optional[str] = None - server_name: Optional[str] = None + alias: str | None = None + server_name: str | None = None transport: MCPTransportType - spec_path: Optional[str] = None - auth_type: Optional[MCPAuthType] = None - mcp_info: Optional[Dict[str, Any]] = None + spec_path: str | None = None + auth_type: MCPAuthType | None = None + mcp_info: dict[str, Any] | None = None # OAuth 2.0 token-endpoint client authentication method (RFC 6749 section 2.3.1). @@ -90,49 +91,49 @@ MCPTokenEndpointAuthMethod = Literal["client_secret_basic", "client_secret_post" class MCPCredentials(TypedDict, total=False): - auth_value: Optional[str] + auth_value: str | None """ Authentication value """ - client_id: Optional[str] + client_id: str | None """ OAuth 2.0 client identifier used when auth_type is oauth2 """ - client_secret: Optional[str] + client_secret: str | None """ OAuth 2.0 client secret used when auth_type is oauth2 """ - scopes: Optional[List[str]] + scopes: list[str] | None """ OAuth 2.0 scopes to request when exchanging the client credentials """ # AWS SigV4 fields - aws_access_key_id: Optional[str] + aws_access_key_id: str | None """AWS access key ID for SigV4 signing. Optional — falls back to boto3 credential chain.""" - aws_secret_access_key: Optional[str] + aws_secret_access_key: str | None """AWS secret access key for SigV4 signing. Optional — falls back to boto3 credential chain.""" - aws_session_token: Optional[str] + aws_session_token: str | None """AWS session token for temporary STS credentials. Optional.""" - aws_region_name: Optional[str] + aws_region_name: str | None """AWS region for SigV4 signing (e.g., 'us-east-1'). Not a secret — stored unencrypted.""" - aws_service_name: Optional[str] + aws_service_name: str | None """AWS service name for SigV4 signing (e.g., 'bedrock-agentcore'). Not a secret — stored unencrypted.""" - aws_role_name: Optional[str] + aws_role_name: str | None """IAM role ARN for STS AssumeRole (e.g., 'arn:aws:iam::123456789012:role/MyRole'). Not a secret — stored unencrypted.""" - aws_session_name: Optional[str] + aws_session_name: str | None """Session name for STS AssumeRole (used in CloudTrail). Not a secret — stored unencrypted.""" - audience: Optional[str] + audience: str | None """ Target audience for OAuth 2.0 Token Exchange (RFC 8693). @@ -142,7 +143,7 @@ class MCPCredentials(TypedDict, total=False): stripped from the stored blob. Prefer the top-level request field. """ - token_exchange_endpoint: Optional[str] + token_exchange_endpoint: str | None """ IDP token endpoint for OAuth 2.0 Token Exchange (RFC 8693). @@ -151,7 +152,7 @@ class MCPCredentials(TypedDict, total=False): authoritative. Prefer the top-level request field. """ - subject_token_type: Optional[str] + subject_token_type: str | None """ Subject token type for OAuth 2.0 Token Exchange (RFC 8693). Default: DEFAULT_SUBJECT_TOKEN_TYPE (urn:ietf:params:oauth:token-type:access_token). @@ -161,12 +162,12 @@ class MCPCredentials(TypedDict, total=False): the top-level request field. """ - id_jag_resource_token_endpoint: Optional[str] + id_jag_resource_token_endpoint: str | None """ Resource authorization server JWT-bearer (RFC 7523) endpoint for ID-JAG leg 2 """ - id_jag_resource: Optional[str] + id_jag_resource: str | None """ Optional RFC 8707 resource indicator sent on ID-JAG leg 1 """ @@ -180,28 +181,28 @@ class MCPCredentials(TypedDict, total=False): ``audience``, which is the RFC 8693 token-exchange parameter. """ - client_private_key: Optional[str] + client_private_key: str | None """ PEM private key used to sign the private-key-JWT client_assertion (RFC 7523) """ - client_private_key_id: Optional[str] + client_private_key_id: str | None """ Key id (kid) advertised in the client_assertion JWT header """ - client_assertion_signing_alg: Optional[str] + client_assertion_signing_alg: str | None """ Signing algorithm for the client_assertion JWT. Default: RS256 """ - token_endpoint_auth_method: Optional[MCPTokenEndpointAuthMethod] + token_endpoint_auth_method: MCPTokenEndpointAuthMethod | None """ How the gateway authenticates to the upstream token endpoint. "client_secret_basic" sends HTTP Basic; defaults to "client_secret_post" when unset. """ - redirect_uris: Optional[List[str]] + redirect_uris: list[str] | None """ The redirect URIs a dynamically registered (RFC 7591) OAuth client was bound to at registration time. Lets a later registration detect that the proxy's public origin no @@ -210,7 +211,7 @@ class MCPCredentials(TypedDict, total=False): this field existed. Not a secret; stored unencrypted. """ - token_exchange_profile: Optional[str] + token_exchange_profile: str | None """ Token exchange wire dialect: "rfc8693" (default, the standard token-exchange grant) or "entra_obo" (Microsoft Entra On-Behalf-Of, the RFC 7523 jwt-bearer grant + requested_token_use @@ -228,12 +229,12 @@ MCP_ADMIN_CONFIG_CREDENTIAL_KEYS: Final[tuple[str, ...]] = ("upstream_resource", class MCPServerCostInfo(TypedDict, total=False): - default_cost_per_query: Optional[float] + default_cost_per_query: float | None """ Default cost per query for the MCP server tool call """ - tool_name_to_cost_per_query: Optional[Dict[str, float]] + tool_name_to_cost_per_query: dict[str, float] | None """ Granular, set a custom cost for each tool in the MCP server """ @@ -245,12 +246,12 @@ class MCPStdioConfig(TypedDict, total=False): Command to run the MCP server (e.g., 'npx', 'python', 'node') """ - args: List[str] + args: list[str] """ Arguments to pass to the command """ - env: Optional[Dict[str, str]] + env: dict[str, str] | None """ Environment variables to set when running the command """ @@ -262,9 +263,9 @@ class MCPPreCallRequestObject(BaseModel): """ tool_name: str - arguments: Dict[str, Any] - server_name: Optional[str] = None - user_api_key_auth: Optional[Dict[str, Any]] = None + arguments: dict[str, Any] + server_name: str | None = None + user_api_key_auth: dict[str, Any] | None = None hidden_params: HiddenParams = HiddenParams() @@ -274,8 +275,8 @@ class MCPPreCallResponseObject(BaseModel): """ should_proceed: bool = True - modified_arguments: Optional[Dict[str, Any]] = None - error_message: Optional[str] = None + modified_arguments: dict[str, Any] | None = None + error_message: str | None = None hidden_params: HiddenParams = HiddenParams() @@ -285,9 +286,9 @@ class MCPDuringCallRequestObject(BaseModel): """ tool_name: str - arguments: Dict[str, Any] - server_name: Optional[str] = None - start_time: Optional[float] = None + arguments: dict[str, Any] + server_name: str | None = None + start_time: float | None = None hidden_params: HiddenParams = HiddenParams() @@ -297,7 +298,7 @@ class MCPDuringCallResponseObject(BaseModel): """ should_continue: bool = True - error_message: Optional[str] = None + error_message: str | None = None hidden_params: HiddenParams = HiddenParams() @@ -306,5 +307,5 @@ class MCPPostCallResponseObject(BaseModel): Pydantic object used for MCP post_call_hook response """ - mcp_tool_call_response: List[Union[MCPTextContent, MCPImageContent, MCPEmbeddedResource]] + mcp_tool_call_response: list[MCPTextContent | MCPImageContent | MCPEmbeddedResource] hidden_params: HiddenParams diff --git a/litellm/types/mcp_server/mcp_server_manager.py b/litellm/types/mcp_server/mcp_server_manager.py index c22bbb73ca0..7ec117208a0 100644 --- a/litellm/types/mcp_server/mcp_server_manager.py +++ b/litellm/types/mcp_server/mcp_server_manager.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Dict, Final, List, Literal, Optional +from typing import Any, Final, Literal from pydantic import BaseModel, ConfigDict @@ -12,21 +12,21 @@ from litellm.types.mcp import ( ) # MCPInfo now allows arbitrary additional fields for custom metadata -MCPInfo = Dict[str, Any] +MCPInfo = dict[str, Any] class MCPOAuthMetadata(BaseModel): - scopes: Optional[List[str]] = None + scopes: list[str] | None = None """Resource-driven scopes for the authorization request: the RFC 9728 protected-resource ``scopes_supported``, or the ``scope`` from the WWW-Authenticate 401 challenge when the resource supplied one, else the authorization server's ``scopes_supported``. This is the scope value a client requests per the MCP authorization spec Scope Selection Strategy; scope minimization and inflation control are the authorization server's and user's job at consent (RFC 6749 §3.3), not the client's.""" - authorization_url: Optional[str] = None - token_url: Optional[str] = None - registration_url: Optional[str] = None - discovered_issuer: Optional[str] = None + authorization_url: str | None = None + token_url: str | None = None + registration_url: str | None = None + discovered_issuer: str | None = None """The ``issuer`` the authorization-server metadata document self-attests (RFC 8414). Persisted trust-on-first-use as the server's ``issuer`` when none is configured, so that later rebuilds anchor discovery on it (RFC 8414 §3.3) and a subsequently compromised resource cannot re-point @@ -40,75 +40,75 @@ class MCPOAuthMetadata(BaseModel): class MCPServer(BaseModel): server_id: str name: str - alias: Optional[str] = None - server_name: Optional[str] = None - url: Optional[str] = None + alias: str | None = None + server_name: str | None = None + url: str | None = None transport: MCPTransportType - spec_path: Optional[str] = None - auth_type: Optional[MCPAuthType] = None - authentication_token: Optional[str] = None - instructions: Optional[str] = None - mcp_info: Optional[MCPInfo] = None - extra_headers: Optional[List[str]] = ( + spec_path: str | None = None + auth_type: MCPAuthType | None = None + authentication_token: str | None = None + instructions: str | None = None + mcp_info: MCPInfo | None = None + extra_headers: list[str] | None = ( None # allow admin to specify which headers to forward from client to the MCP server ) - allowed_tools: Optional[List[str]] = None - disallowed_tools: Optional[List[str]] = None - tool_name_to_display_name: Optional[Dict[str, str]] = None - tool_name_to_description: Optional[Dict[str, str]] = None - allowed_params: Optional[Dict[str, List[str]]] = None # map of tool names to allowed parameter lists - static_headers: Optional[Dict[str, str]] = None # static headers to forward to the MCP server + allowed_tools: list[str] | None = None + disallowed_tools: list[str] | None = None + tool_name_to_display_name: dict[str, str] | None = None + tool_name_to_description: dict[str, str] | None = None + allowed_params: dict[str, list[str]] | None = None # map of tool names to allowed parameter lists + static_headers: dict[str, str] | None = None # static headers to forward to the MCP server # Admin-configured env vars. Each entry is {name, value, scope, description}. # scope=="global" values are interpolated into static_headers using ${NAME}. # scope=="user" values must be supplied per-user. - env_vars: Optional[List[Dict[str, Any]]] = None + env_vars: list[dict[str, Any]] | None = None # OAuth-specific fields - client_id: Optional[str] = None - client_secret: Optional[str] = None - issuer: Optional[str] = None + client_id: str | None = None + client_secret: str | None = None + issuer: str | None = None issuer_is_anchored: bool = False - scopes: Optional[List[str]] = None - authorization_url: Optional[str] = None - token_url: Optional[str] = None - registration_url: Optional[str] = None + scopes: list[str] | None = None + authorization_url: str | None = None + token_url: str | None = None + registration_url: str | None = None # How the gateway authenticates to the upstream token endpoint. When # "client_secret_basic" the credentials go in an HTTP Basic Authorization # header (omitted from the body); None defaults to "client_secret_post". - token_endpoint_auth_method: Optional[MCPTokenEndpointAuthMethod] = None + token_endpoint_auth_method: MCPTokenEndpointAuthMethod | None = None # RFC 8707 resource indicator sent on this server's upstream oauth2 legs (authorize, both # token grants, and the client_credentials fetch). None omits it, which is the default and # today's behavior; "auto" derives the canonical URI from ``url``; any other value is sent # verbatim. Resolved by ``oauth_utils.resolve_upstream_resource``. upstream_resource: str | None = None # AWS SigV4 fields - aws_access_key_id: Optional[str] = None - aws_secret_access_key: Optional[str] = None - aws_session_token: Optional[str] = None - aws_region_name: Optional[str] = None - aws_service_name: Optional[str] = None # defaults to "bedrock-agentcore" - aws_role_name: Optional[str] = None # IAM role ARN for STS AssumeRole - aws_session_name: Optional[str] = None # session name for CloudTrail auditing + aws_access_key_id: str | None = None + aws_secret_access_key: str | None = None + aws_session_token: str | None = None + aws_region_name: str | None = None + aws_service_name: str | None = None # defaults to "bedrock-agentcore" + aws_role_name: str | None = None # IAM role ARN for STS AssumeRole + aws_session_name: str | None = None # session name for CloudTrail auditing # Token Exchange (OBO) fields - token_exchange_endpoint: Optional[str] = None - audience: Optional[str] = None + token_exchange_endpoint: str | None = None + audience: str | None = None subject_token_type: str = DEFAULT_SUBJECT_TOKEN_TYPE # ID-JAG fields (draft-ietf-oauth-identity-assertion-authz-grant). # Leg 1 reuses token_exchange_endpoint (IdP org-AS), audience (resource-AS # identifier), scopes, subject_token_type, client_id/client_secret. Leg 2 # posts the ID-JAG assertion to id_jag_resource_token_endpoint. - id_jag_resource_token_endpoint: Optional[str] = None - id_jag_resource: Optional[str] = None - client_private_key: Optional[str] = None - client_private_key_id: Optional[str] = None + id_jag_resource_token_endpoint: str | None = None + id_jag_resource: str | None = None + client_private_key: str | None = None + client_private_key_id: str | None = None client_assertion_signing_alg: str = "RS256" # Wire dialect: "rfc8693" (standard token-exchange grant) or "entra_obo" (Microsoft Entra # On-Behalf-Of, the RFC 7523 jwt-bearer grant + requested_token_use extension) token_exchange_profile: str = "rfc8693" # Stdio-specific fields - command: Optional[str] = None - args: Optional[List[str]] = None - env: Optional[Dict[str, str]] = None - access_groups: Optional[List[str]] = None + command: str | None = None + args: list[str] | None = None + env: dict[str, str] | None = None + access_groups: list[str] | None = None allow_all_keys: bool = False available_on_public_internet: bool = True # Explicit opt-in to upstream-delegated authentication for ``oauth2`` @@ -134,36 +134,36 @@ class MCPServer(BaseModel): # ``Authorization`` for non-OAuth reasons (e.g. static bearer tokens). Must # be set explicitly to avoid regressing servers that did not opt in. oauth_passthrough: bool = False - dcr_bridge: Optional[bool] = None + dcr_bridge: bool | None = None is_byok: bool = False - byok_description: List[str] = [] - byok_api_key_help_url: Optional[str] = None - source_url: Optional[str] = None - created_at: Optional[datetime] = None - updated_at: Optional[datetime] = None + byok_description: list[str] = [] + byok_api_key_help_url: str | None = None + source_url: str | None = None + created_at: datetime | None = None + updated_at: datetime | None = None # OAuth2 flow type. Defaults to None (interactive / authorization_code). # Set to "client_credentials" to enable M2M token fetching. - oauth2_flow: Optional[Literal["client_credentials", "authorization_code"]] = None + oauth2_flow: Literal["client_credentials", "authorization_code"] | None = None # Per-user OAuth server-side storage config. # token_validation: key-value pairs that must match fields in the OAuth token # response (supports dot-notation for nested fields, e.g. "team.enterprise_id"). # Tokens that fail validation are rejected before storage. - token_validation: Optional[Dict[str, Any]] = None + token_validation: dict[str, Any] | None = None # Optional TTL override (seconds) for the Redis per-user token cache, capped # at the token's expires_in minus the expiry buffer so a cached entry never # outlives the token. Defaults to the token's expires_in minus the expiry # buffer, or MCP_PER_USER_TOKEN_DEFAULT_TTL when expires_in is absent. - token_storage_ttl_seconds: Optional[int] = None - timeout: Optional[float] = None + token_storage_ttl_seconds: int | None = None + timeout: float | None = None # Max concurrent outbound tool calls to this server; excess calls queue. # None or a value <= 0 means unlimited. - max_concurrent_requests: Optional[int] = None + max_concurrent_requests: int | None = None # Resolved short-ID tool prefix when LITELLM_USE_SHORT_MCP_TOOL_PREFIX is # enabled. Set by ``MCPServerManager._assign_unique_short_prefix`` at # registration time so that natural-hash collisions between two # different ``server_id`` values are bumped deterministically. Left # ``None`` in default-prefix mode. - short_prefix: Optional[str] = None + short_prefix: str | None = None allow_sampling: bool = False allow_elicitation: bool = False model_config = ConfigDict(arbitrary_types_allowed=True) diff --git a/litellm/types/mcp_server/mcp_toolset.py b/litellm/types/mcp_server/mcp_toolset.py index 7f78a22bfe2..7e9e03e48ed 100644 --- a/litellm/types/mcp_server/mcp_toolset.py +++ b/litellm/types/mcp_server/mcp_toolset.py @@ -1,5 +1,4 @@ from datetime import datetime -from typing import List, Optional from pydantic import BaseModel from typing_extensions import TypedDict @@ -13,22 +12,22 @@ class MCPToolsetTool(TypedDict): class MCPToolset(BaseModel): toolset_id: str toolset_name: str - description: Optional[str] = None - tools: List[MCPToolsetTool] = [] - created_at: Optional[datetime] = None - created_by: Optional[str] = None - updated_at: Optional[datetime] = None - updated_by: Optional[str] = None + description: str | None = None + tools: list[MCPToolsetTool] = [] + created_at: datetime | None = None + created_by: str | None = None + updated_at: datetime | None = None + updated_by: str | None = None class NewMCPToolsetRequest(BaseModel): toolset_name: str - description: Optional[str] = None - tools: List[MCPToolsetTool] = [] + description: str | None = None + tools: list[MCPToolsetTool] = [] class UpdateMCPToolsetRequest(BaseModel): toolset_id: str - toolset_name: Optional[str] = None - description: Optional[str] = None - tools: Optional[List[MCPToolsetTool]] = None + toolset_name: str | None = None + description: str | None = None + tools: list[MCPToolsetTool] | None = None diff --git a/litellm/types/mcp_server/tool_registry.py b/litellm/types/mcp_server/tool_registry.py index 8e3f1d9657e..79dedfd7653 100644 --- a/litellm/types/mcp_server/tool_registry.py +++ b/litellm/types/mcp_server/tool_registry.py @@ -1,4 +1,5 @@ -from typing import Any, Callable, ClassVar, Dict, List, Optional +from collections.abc import Callable +from typing import Any, ClassVar from pydantic import BaseModel, ConfigDict @@ -7,27 +8,27 @@ class MCPTool(BaseModel): model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True) name: str description: str - input_schema: Dict[str, Any] + input_schema: dict[str, Any] handler: Callable class ToolSchema(BaseModel): name: str description: str - inputSchema: Dict[str, Any] + inputSchema: dict[str, Any] class ListToolsResponse(BaseModel): - tools: List[ToolSchema] - nextCursor: Optional[str] = None - _meta: Optional[Dict[str, Any]] = None + tools: list[ToolSchema] + nextCursor: str | None = None + _meta: dict[str, Any] | None = None class CallToolRequest(BaseModel): method: str = "tools/call" - params: Dict[str, Any] + params: dict[str, Any] class ContentItem(BaseModel): type: str - text: Optional[str] = None + text: str | None = None diff --git a/litellm/types/memory_management.py b/litellm/types/memory_management.py index 81f655bf668..04a2a0c1905 100644 --- a/litellm/types/memory_management.py +++ b/litellm/types/memory_management.py @@ -3,7 +3,7 @@ Pydantic models for Memory management endpoints. """ from datetime import datetime -from typing import Any, List, Optional +from typing import Any from pydantic import BaseModel, Field @@ -12,44 +12,44 @@ class LiteLLM_MemoryRow(BaseModel): memory_id: str key: str value: str - metadata: Optional[Any] = None - user_id: Optional[str] = None - team_id: Optional[str] = None - created_at: Optional[datetime] = None - created_by: Optional[str] = None - updated_at: Optional[datetime] = None - updated_by: Optional[str] = None + metadata: Any | None = None + user_id: str | None = None + team_id: str | None = None + created_at: datetime | None = None + created_by: str | None = None + updated_at: datetime | None = None + updated_by: str | None = None class MemoryCreateRequest(BaseModel): key: str = Field(..., description="Memory key (acts as the namespace in the URL).") value: str = Field(..., description="Memory content. Typically markdown/text for LLM context.") - metadata: Optional[Any] = Field( + metadata: Any | None = Field( default=None, description="Optional JSON metadata (tags, structured fields).", ) - user_id: Optional[str] = Field( + user_id: str | None = Field( default=None, description="Scope to this user. Defaults to the caller's user_id.", ) - team_id: Optional[str] = Field( + team_id: str | None = Field( default=None, description="Scope to this team. Defaults to the caller's team_id.", ) class MemoryUpdateRequest(BaseModel): - value: Optional[str] = None - metadata: Optional[Any] = None + value: str | None = None + metadata: Any | None = None # Only honored on create (when the row doesn't yet exist) and only for # PROXY_ADMIN callers — mirrors MemoryCreateRequest so admins can bootstrap # rows scoped to another user/team via PUT, not just POST. - user_id: Optional[str] = None - team_id: Optional[str] = None + user_id: str | None = None + team_id: str | None = None class MemoryListResponse(BaseModel): - memories: List[LiteLLM_MemoryRow] + memories: list[LiteLLM_MemoryRow] total: int diff --git a/litellm/types/object_permission.py b/litellm/types/object_permission.py index d0458173fbf..1b391a3a1ef 100644 --- a/litellm/types/object_permission.py +++ b/litellm/types/object_permission.py @@ -8,20 +8,18 @@ can adopt the type without violating the SDK-must-not-import-from-proxy layering rule. """ -from typing import Optional - from typing_extensions import TypedDict class ObjectPermissionDict(TypedDict, total=False): - mcp_servers: Optional[list[str]] - mcp_access_groups: Optional[list[str]] - mcp_tool_permissions: Optional[dict[str, list[str]]] - mcp_toolsets: Optional[list[str]] - blocked_tools: Optional[list[str]] - vector_stores: Optional[list[str]] - agents: Optional[list[str]] - agent_access_groups: Optional[list[str]] - models: Optional[list[str]] - search_tools: Optional[list[str]] - mcp_tool_search_enabled: Optional[bool] + mcp_servers: list[str] | None + mcp_access_groups: list[str] | None + mcp_tool_permissions: dict[str, list[str]] | None + mcp_toolsets: list[str] | None + blocked_tools: list[str] | None + vector_stores: list[str] | None + agents: list[str] | None + agent_access_groups: list[str] | None + models: list[str] | None + search_tools: list[str] | None + mcp_tool_search_enabled: bool | None diff --git a/litellm/types/passthrough_endpoints/pass_through_endpoints.py b/litellm/types/passthrough_endpoints/pass_through_endpoints.py index f59ca0d9041..47ae1d9ba2b 100644 --- a/litellm/types/passthrough_endpoints/pass_through_endpoints.py +++ b/litellm/types/passthrough_endpoints/pass_through_endpoints.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Final, Optional +from typing import Final from typing_extensions import TypedDict @@ -37,22 +37,22 @@ class PassthroughStandardLoggingPayload(TypedDict, total=False): The full url of the request """ - request_method: Optional[str] + request_method: str | None """ The method of the request "GET", "POST", "PUT", "DELETE", etc. """ - request_body: Optional[dict] + request_body: dict | None """ The body of the request """ - response_body: Optional[dict] # only tracked for non-streaming responses + response_body: dict | None # only tracked for non-streaming responses """ The body of the response """ - cost_per_request: Optional[float] + cost_per_request: float | None """ The cost per request to the target endpoint diff --git a/litellm/types/passthrough_endpoints/vertex_ai.py b/litellm/types/passthrough_endpoints/vertex_ai.py index 9087119807e..d1affd7be2c 100644 --- a/litellm/types/passthrough_endpoints/vertex_ai.py +++ b/litellm/types/passthrough_endpoints/vertex_ai.py @@ -2,8 +2,6 @@ Used for /vertex_ai/ pass through endpoints """ -from typing import Optional - from pydantic import BaseModel from ..llms.vertex_ai import VERTEX_CREDENTIALS_TYPES @@ -11,10 +9,10 @@ from ..llms.vertex_ai import VERTEX_CREDENTIALS_TYPES class VertexPassThroughCredentials(BaseModel): # Example: vertex_project = "my-project-123" - vertex_project: Optional[str] = None + vertex_project: str | None = None # Example: vertex_location = "us-central1" - vertex_location: Optional[str] = None + vertex_location: str | None = None # Example: vertex_credentials = "/path/to/credentials.json" or "os.environ/GOOGLE_CREDS" - vertex_credentials: Optional[VERTEX_CREDENTIALS_TYPES] = None + vertex_credentials: VERTEX_CREDENTIALS_TYPES | None = None diff --git a/litellm/types/policy_engine.py b/litellm/types/policy_engine.py index d5eb7e2b140..5a326268bfa 100644 --- a/litellm/types/policy_engine.py +++ b/litellm/types/policy_engine.py @@ -24,13 +24,13 @@ __all__ = [ "Policy", "PolicyConfig", "PolicyGuardrails", + # Resolver types + "PolicyMatchContext", "PolicyScope", # Validation types "PolicyValidateRequest", "PolicyValidationError", "PolicyValidationErrorType", "PolicyValidationResponse", - # Resolver types - "PolicyMatchContext", "ResolvedPolicy", ] diff --git a/litellm/types/prompts/init_prompts.py b/litellm/types/prompts/init_prompts.py index 6db714c333c..f1a926f9ae0 100644 --- a/litellm/types/prompts/init_prompts.py +++ b/litellm/types/prompts/init_prompts.py @@ -1,6 +1,6 @@ from datetime import datetime from enum import Enum -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Literal from pydantic import BaseModel, ConfigDict @@ -17,24 +17,24 @@ class SupportedPromptIntegrations(str, Enum): class PromptInfo(BaseModel): prompt_type: Literal["config", "db"] - environment: Optional[str] = "development" + environment: str | None = "development" model_config = ConfigDict(extra="allow", protected_namespaces=()) class PromptLiteLLMParams(BaseModel): - prompt_id: Optional[str] = None + prompt_id: str | None = None prompt_integration: str - api_base: Optional[str] = None - api_key: Optional[str] = None + api_base: str | None = None + api_key: str | None = None - provider_specific_query_params: Optional[Dict[str, Any]] = None + provider_specific_query_params: dict[str, Any] | None = None - ignore_prompt_manager_model: Optional[bool] = False - ignore_prompt_manager_optional_params: Optional[bool] = False + ignore_prompt_manager_model: bool | None = False + ignore_prompt_manager_optional_params: bool | None = False - dotprompt_content: Optional[str] = None + dotprompt_content: str | None = None """ allows saving the dotprompt file content """ @@ -46,13 +46,13 @@ class PromptSpec(BaseModel): prompt_id: str litellm_params: PromptLiteLLMParams prompt_info: PromptInfo - created_at: Optional[datetime] = None - updated_at: Optional[datetime] = None - version: Optional[int] = None # Version number for version history - environment: Optional[str] = "development" - created_by: Optional[str] = None + created_at: datetime | None = None + updated_at: datetime | None = None + version: int | None = None # Version number for version history + environment: str | None = "development" + created_by: str | None = None - def __init__(self, **data): + def __init__(self, **data) -> None: if "prompt_info" not in data: data["prompt_info"] = PromptInfo(prompt_type="config") elif "prompt_info" in data: @@ -64,14 +64,14 @@ class PromptSpec(BaseModel): class PromptTemplateBase(BaseModel): litellm_prompt_id: str content: str - metadata: Optional[Dict[str, Any]] = None + metadata: dict[str, Any] | None = None class PromptInfoResponse(BaseModel): prompt_spec: PromptSpec - raw_prompt_template: Optional[PromptTemplateBase] = None - environments: Optional[List[str]] = None # All environments this prompt is deployed to + raw_prompt_template: PromptTemplateBase | None = None + environments: list[str] | None = None # All environments this prompt is deployed to class ListPromptsResponse(BaseModel): - prompts: List[PromptSpec] + prompts: list[PromptSpec] diff --git a/litellm/types/proxy/callback_logs_endpoints.py b/litellm/types/proxy/callback_logs_endpoints.py index ef148274ca7..0ff1d5a2273 100644 --- a/litellm/types/proxy/callback_logs_endpoints.py +++ b/litellm/types/proxy/callback_logs_endpoints.py @@ -5,7 +5,7 @@ External producers (e.g. the litellm-rust gateway) POST finished logging payloads here; the proxy replays them through the standard callback fan-out. """ -from typing import Any, Literal, Optional +from typing import Any, Literal from pydantic import BaseModel, Field @@ -17,7 +17,7 @@ class CallbackLogRecord(BaseModel): status: Literal["success", "failure"] standard_logging_payload: dict[str, Any] - error: Optional[str] = None + error: str | None = None class CallbackLogsRequest(BaseModel): diff --git a/litellm/types/proxy/claude_code_endpoints.py b/litellm/types/proxy/claude_code_endpoints.py index af15e205d42..2ee1bbbbb98 100644 --- a/litellm/types/proxy/claude_code_endpoints.py +++ b/litellm/types/proxy/claude_code_endpoints.py @@ -2,8 +2,6 @@ Claude Code Marketplace endpoint types for LiteLLM Proxy """ -from typing import Dict, List, Optional - from pydantic import BaseModel, Field @@ -11,20 +9,20 @@ class PluginAuthor(BaseModel): """Plugin author information.""" name: str = Field(..., description="Author name") - email: Optional[str] = Field(None, description="Author email") + email: str | None = Field(None, description="Author email") class PluginOwner(BaseModel): """Marketplace owner information.""" name: str = Field(..., description="Owner name") - email: Optional[str] = Field(None, description="Owner email") + email: str | None = Field(None, description="Owner email") class PluginSpec(BaseModel): """Mutable fields shared by plugin create and update requests.""" - source: Dict[str, str] = Field( + source: dict[str, str] = Field( ..., description=( "Git source reference. Supported formats:\n" @@ -33,14 +31,14 @@ class PluginSpec(BaseModel): "- Git Subdir: {'source': 'git-subdir', 'url': 'https://github.com/org/repo.git', 'path': 'plugins/plugin-name'}" ), ) - version: Optional[str] = Field("1.0.0", description="Semantic version") - description: Optional[str] = Field(None, description="Plugin description") - author: Optional[PluginAuthor] = Field(None, description="Plugin author") - homepage: Optional[str] = Field(None, description="Plugin homepage URL") - keywords: Optional[List[str]] = Field(None, description="Search keywords") - category: Optional[str] = Field(None, description="Plugin category") - domain: Optional[str] = Field(None, description="Skill domain (e.g., 'Productivity')") - namespace: Optional[str] = Field(None, description="Skill namespace within domain (e.g., 'workflows')") + version: str | None = Field("1.0.0", description="Semantic version") + description: str | None = Field(None, description="Plugin description") + author: PluginAuthor | None = Field(None, description="Plugin author") + homepage: str | None = Field(None, description="Plugin homepage URL") + keywords: list[str] | None = Field(None, description="Search keywords") + category: str | None = Field(None, description="Plugin category") + domain: str | None = Field(None, description="Skill domain (e.g., 'Productivity')") + namespace: str | None = Field(None, description="Skill namespace within domain (e.g., 'workflows')") class RegisterPluginRequest(PluginSpec): @@ -76,9 +74,9 @@ class PluginResponse(BaseModel): id: str = Field(..., description="Plugin unique ID") name: str = Field(..., description="Plugin name") - version: Optional[str] = Field(None, description="Plugin version") - description: Optional[str] = Field(None, description="Plugin description") - source: Dict[str, str] = Field(..., description="Git source reference") + version: str | None = Field(None, description="Plugin version") + description: str | None = Field(None, description="Plugin description") + source: dict[str, str] = Field(..., description="Git source reference") enabled: bool = Field(..., description="Whether plugin is enabled") @@ -95,24 +93,24 @@ class PluginListItem(BaseModel): id: str name: str - version: Optional[str] - description: Optional[str] - source: Dict[str, str] - author: Optional[PluginAuthor] = None - homepage: Optional[str] = None - keywords: Optional[List[str]] = None - category: Optional[str] = None - domain: Optional[str] = None - namespace: Optional[str] = None + version: str | None + description: str | None + source: dict[str, str] + author: PluginAuthor | None = None + homepage: str | None = None + keywords: list[str] | None = None + category: str | None = None + domain: str | None = None + namespace: str | None = None enabled: bool - created_at: Optional[str] - updated_at: Optional[str] + created_at: str | None + updated_at: str | None class ListPluginsResponse(BaseModel): """Response from listing plugins.""" - plugins: List[PluginListItem] + plugins: list[PluginListItem] count: int @@ -120,13 +118,13 @@ class MarketplacePluginEntry(BaseModel): """Plugin entry in marketplace.json.""" name: str - source: Dict[str, str] - version: Optional[str] = None - description: Optional[str] = None - author: Optional[PluginAuthor] = None - homepage: Optional[str] = None - keywords: Optional[List[str]] = None - category: Optional[str] = None + source: dict[str, str] + version: str | None = None + description: str | None = None + author: PluginAuthor | None = None + homepage: str | None = None + keywords: list[str] | None = None + category: str | None = None class MarketplaceResponse(BaseModel): @@ -139,4 +137,4 @@ class MarketplaceResponse(BaseModel): name: str = Field(..., description="Marketplace identifier") owner: PluginOwner = Field(..., description="Marketplace owner") - plugins: List[MarketplacePluginEntry] = Field(default_factory=list, description="Available plugins") + plugins: list[MarketplacePluginEntry] = Field(default_factory=list, description="Available plugins") diff --git a/litellm/types/proxy/cloudzero_endpoints.py b/litellm/types/proxy/cloudzero_endpoints.py index c50c4f53df6..70b779338f8 100644 --- a/litellm/types/proxy/cloudzero_endpoints.py +++ b/litellm/types/proxy/cloudzero_endpoints.py @@ -3,7 +3,7 @@ CloudZero endpoint types for LiteLLM Proxy """ from datetime import datetime -from typing import Any, Dict, List, Optional +from typing import Any from pydantic import BaseModel, Field @@ -26,13 +26,13 @@ class CloudZeroInitResponse(BaseModel): class CloudZeroExportRequest(BaseModel): """Request model for CloudZero export operations""" - limit: Optional[int] = Field(None, description="Optional limit on number of records to export") + limit: int | None = Field(None, description="Optional limit on number of records to export") operation: str = Field( default="replace_hourly", description="CloudZero operation type (replace_hourly or sum)", ) - start_time_utc: Optional[datetime] = Field(None, description="Start time for data export in UTC") - end_time_utc: Optional[datetime] = Field(None, description="End time for data export in UTC") + start_time_utc: datetime | None = Field(None, description="Start time for data export in UTC") + end_time_utc: datetime | None = Field(None, description="End time for data export in UTC") class CloudZeroExportResponse(BaseModel): @@ -40,25 +40,25 @@ class CloudZeroExportResponse(BaseModel): message: str status: str - records_exported: Optional[int] = None - dry_run_data: Optional[Dict[str, Any]] = Field( + records_exported: int | None = None + dry_run_data: dict[str, Any] | None = Field( None, description="Dry run data including usage data and CBF transformed data" ) - summary: Optional[Dict[str, Any]] = Field(None, description="Summary statistics for dry run") + summary: dict[str, Any] | None = Field(None, description="Summary statistics for dry run") class CloudZeroSettingsView(BaseModel): """Response model for viewing CloudZero settings with masked API key""" - api_key_masked: Optional[str] = Field(None, description="Masked API key showing only first 4 and last 4 characters") - connection_id: Optional[str] = Field(None, description="CloudZero connection ID for data submission") - timezone: Optional[str] = Field(None, description="Timezone for date handling") - status: Optional[str] = Field(None, description="Configuration status") + api_key_masked: str | None = Field(None, description="Masked API key showing only first 4 and last 4 characters") + connection_id: str | None = Field(None, description="CloudZero connection ID for data submission") + timezone: str | None = Field(None, description="Timezone for date handling") + status: str | None = Field(None, description="Configuration status") class CloudZeroSettingsUpdate(BaseModel): """Request model for updating CloudZero settings""" - api_key: Optional[str] = Field(None, description="New CloudZero API key for authentication") - connection_id: Optional[str] = Field(None, description="New CloudZero connection ID for data submission") - timezone: Optional[str] = Field(None, description="New timezone for date handling") + api_key: str | None = Field(None, description="New CloudZero API key for authentication") + connection_id: str | None = Field(None, description="New CloudZero connection ID for data submission") + timezone: str | None = Field(None, description="New timezone for date handling") diff --git a/litellm/types/proxy/compliance_endpoints.py b/litellm/types/proxy/compliance_endpoints.py index 154c9f403af..0c1a11bf594 100644 --- a/litellm/types/proxy/compliance_endpoints.py +++ b/litellm/types/proxy/compliance_endpoints.py @@ -1,5 +1,3 @@ -from typing import List, Optional - from pydantic import BaseModel @@ -17,7 +15,7 @@ class ComplianceResponse(BaseModel): compliant: bool regulation: str - checks: List[ComplianceCheckResult] + checks: list[ComplianceCheckResult] class ComplianceCheckRequest(BaseModel): @@ -27,7 +25,7 @@ class ComplianceCheckRequest(BaseModel): """ request_id: str - user_id: Optional[str] = None - model: Optional[str] = None - timestamp: Optional[str] = None - guardrail_information: Optional[List[dict]] = None + user_id: str | None = None + model: str | None = None + timestamp: str | None = None + guardrail_information: list[dict] | None = None diff --git a/litellm/types/proxy/discovery_endpoints/ui_discovery_endpoints.py b/litellm/types/proxy/discovery_endpoints/ui_discovery_endpoints.py index 5498474ea9f..d52877b7c1e 100644 --- a/litellm/types/proxy/discovery_endpoints/ui_discovery_endpoints.py +++ b/litellm/types/proxy/discovery_endpoints/ui_discovery_endpoints.py @@ -1,5 +1,3 @@ -from typing import List, Optional - from pydantic import BaseModel from litellm.types.proxy.control_plane_endpoints import WorkerRegistryEntry @@ -7,10 +5,10 @@ from litellm.types.proxy.control_plane_endpoints import WorkerRegistryEntry class UiDiscoveryEndpoints(BaseModel): server_root_path: str - proxy_base_url: Optional[str] + proxy_base_url: str | None auto_redirect_to_sso: bool admin_ui_disabled: bool sso_configured: bool hide_default_credentials_hint: bool = False is_control_plane: bool = False - workers: List[WorkerRegistryEntry] = [] + workers: list[WorkerRegistryEntry] = [] diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/aim.py b/litellm/types/proxy/guardrails/guardrail_hooks/aim.py index 4329225e36f..b25ecf84cc3 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/aim.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/aim.py @@ -1,16 +1,14 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel class AimGuardrailConfigModel(GuardrailConfigModel): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The API key for the Aim guardrail. If not provided, the `AIM_API_KEY` environment variable is checked.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The API base for the Aim guardrail. Default is https://api.aim.security. Also checks if the `AIM_API_BASE` environment variable is set.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/akto.py b/litellm/types/proxy/guardrails/guardrail_hooks/akto.py index 180c89e8115..43a9935ce9b 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/akto.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/akto.py @@ -1,4 +1,4 @@ -from typing import Optional, Literal +from typing import Literal from pydantic import Field @@ -14,7 +14,7 @@ class AktoConfigModel(GuardrailConfigModel): akto-ingest (mode: post_call) -> ingest request+response data """ - akto_base_url: Optional[str] = Field( + akto_base_url: str | None = Field( default=None, description="Akto Guardrail API Base URL. Env: AKTO_GUARDRAIL_API_BASE.", json_schema_extra={ @@ -25,17 +25,17 @@ class AktoConfigModel(GuardrailConfigModel): }, ) - akto_api_key: Optional[str] = Field( + akto_api_key: str | None = Field( default=None, description="API key for Akto. Env: AKTO_API_KEY.", ) - akto_account_id: Optional[str] = Field( + akto_account_id: str | None = Field( default=None, description="Akto account ID for multi-tenant deployments. Env: AKTO_ACCOUNT_ID. Default: '1000000'.", ) - akto_vxlan_id: Optional[str] = Field( + akto_vxlan_id: str | None = Field( default=None, description="Akto VXLAN ID. Env: AKTO_VXLAN_ID. Default: '0'.", ) @@ -45,7 +45,7 @@ class AktoConfigModel(GuardrailConfigModel): description="What to do when Akto is unreachable. 'fail_open' = allow, 'fail_closed' = block.", ) - guardrail_timeout: Optional[int] = Field( + guardrail_timeout: int | None = Field( default=None, description="HTTP timeout in seconds. Default: 5.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/aporia_ai.py b/litellm/types/proxy/guardrails/guardrail_hooks/aporia_ai.py index 26247d75090..b0409d8551e 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/aporia_ai.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/aporia_ai.py @@ -1,16 +1,14 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel class AporiaGuardrailConfigModel(GuardrailConfigModel): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The API key for the Aporia guardrail. If not provided, the `APORIA_API_KEY` environment variable is checked.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The API base for the Aporia guardrail. If not provided, the `APORIA_API_BASE` environment variable is checked.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_prompt_shield.py b/litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_prompt_shield.py index 9612c6c48d4..79fb07d7369 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_prompt_shield.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_prompt_shield.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List +from typing import Any from typing_extensions import TypedDict @@ -11,7 +11,7 @@ class AzurePromptShieldGuardrailRequestBody(TypedDict): """Configuration parameters for the Azure Prompt Shield guardrail""" userPrompt: str - documents: List[str] + documents: list[str] class UserPromptAnalysis(TypedDict, total=False): @@ -22,7 +22,7 @@ class AzurePromptShieldGuardrailResponse(TypedDict): """Configuration parameters for the Azure Prompt Shield guardrail""" userPromptAnalysis: UserPromptAnalysis - documentsAnalysis: List[Dict[str, Any]] + documentsAnalysis: list[dict[str, Any]] class AzurePromptShieldGuardrailConfigModel( diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_text_moderation.py b/litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_text_moderation.py index 15b2053c1f3..83b8d281100 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_text_moderation.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_text_moderation.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Final, List, Literal, Optional +from typing import Any, Final, Literal from pydantic import BaseModel, Field from typing_extensions import Required, TypedDict @@ -13,9 +13,9 @@ AZURE_CONTENT_SAFETY_CATEGORIES: Final = ["Hate", "SelfHarm", "Sexual", "Violenc class AzureTextModerationRequestBodyOptionalParams(TypedDict, total=False): """Optional parameters for the Azure Text Moderation guardrail""" - categories: Optional[List[str]] - blocklistNames: Optional[List[str]] - haltOnBlocklistHit: Optional[bool] + categories: list[str] | None + blocklistNames: list[str] | None + haltOnBlocklistHit: bool | None outputType: Literal["FourSeverityLevels", "EightSeverityLevels"] @@ -35,36 +35,36 @@ class AzureTextModerationGuardrailResponseCategoriesAnalysis(TypedDict): class AzureTextModerationGuardrailResponse(TypedDict): """Response from the Azure Text Moderation guardrail""" - blocklistsMatch: List[Dict[str, Any]] - categoriesAnalysis: List[AzureTextModerationGuardrailResponseCategoriesAnalysis] + blocklistsMatch: list[dict[str, Any]] + categoriesAnalysis: list[AzureTextModerationGuardrailResponseCategoriesAnalysis] AzureHarmCategories = Literal["Hate", "SelfHarm", "Sexual", "Violence"] class AzureTextModerationOptionalParams(BaseModel): - severity_threshold: Optional[int] = Field( + severity_threshold: int | None = Field( default=None, description="Severity threshold for the Azure Content Safety Text Moderation guardrail across all categories", ) - severity_threshold_by_category: Optional[Dict[AzureHarmCategories, int]] = Field( + severity_threshold_by_category: dict[AzureHarmCategories, int] | None = Field( default=None, description="Severity threshold by category for the Azure Content Safety Text Moderation guardrail. See list of categories - https://learn.microsoft.com/en-us/azure/ai-services/content-safety/concepts/harm-categories?tabs=warning", ) - categories: Optional[List[AzureHarmCategories]] = Field( + categories: list[AzureHarmCategories] | None = Field( default=None, description="Categories to scan for the Azure Content Safety Text Moderation guardrail. See list of categories - https://learn.microsoft.com/en-us/azure/ai-services/content-safety/concepts/harm-categories?tabs=warning", ) - blocklistNames: Optional[List[str]] = Field( + blocklistNames: list[str] | None = Field( default=None, description="Blocklist names to scan for the Azure Content Safety Text Moderation guardrail. Learn more - https://learn.microsoft.com/en-us/azure/ai-services/content-safety/quickstart-text", ) - haltOnBlocklistHit: Optional[bool] = Field( + haltOnBlocklistHit: bool | None = Field( default=None, description="Whether to halt the request if a blocklist hit is detected", ) - outputType: Optional[Literal["FourSeverityLevels", "EightSeverityLevels"]] = Field( + outputType: Literal["FourSeverityLevels", "EightSeverityLevels"] | None = Field( default=None, description="Output type for the Azure Content Safety Text Moderation guardrail. Learn more - https://learn.microsoft.com/en-us/azure/ai-services/content-safety/quickstart-text", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/azure/base.py b/litellm/types/proxy/guardrails/guardrail_hooks/azure/base.py index 2f54bd3cc77..c72888f33e1 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/azure/base.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/azure/base.py @@ -1,21 +1,19 @@ -from typing import Optional - from pydantic import BaseModel, Field class AzureContentSafetyConfigModel(BaseModel): """Configuration parameters for the Azure Content Safety Prompt Shield guardrail""" - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="API key for the Azure Content Safety Prompt Shield guardrail", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="Base URL for the Azure Content Safety Prompt Shield guardrail", ) - api_version: Optional[str] = Field( + api_version: str | None = Field( default="2024-09-01", description="API version for the Azure Content Safety Prompt Shield guardrail. Default is 2024-09-01", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/base.py b/litellm/types/proxy/guardrails/guardrail_hooks/base.py index a77c82cd0df..d965ad361bc 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/base.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/base.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Final, Generic, Optional, TypeVar +from typing import Generic, TypeVar from pydantic import BaseModel, Field @@ -9,7 +9,7 @@ T = TypeVar("T", bound=BaseModel) class GuardrailConfigModel(BaseModel, Generic[T], ABC): """Base model for guardrail configuration""" - optional_params: Optional[T] = Field( + optional_params: T | None = Field( default=None, description="Optional parameters for the guardrail", ) @@ -18,4 +18,3 @@ class GuardrailConfigModel(BaseModel, Generic[T], ABC): @abstractmethod def ui_friendly_name() -> str: """UI-friendly name for the guardrail""" - pass diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py b/litellm/types/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py index b3833921936..d97bdc3532f 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py @@ -1,4 +1,4 @@ -from typing import Dict, Final, List, Literal, Optional +from typing import Literal from typing_extensions import TypedDict @@ -9,7 +9,7 @@ BedrockGuardrailQualifier = Literal["grounding_source", "query", "guard_content" class BedrockTextContent(TypedDict, total=False): text: str - qualifiers: List[BedrockGuardrailQualifier] + qualifiers: list[BedrockGuardrailQualifier] class BedrockContentItem(TypedDict, total=False): @@ -18,41 +18,41 @@ class BedrockContentItem(TypedDict, total=False): class BedrockRequest(TypedDict, total=False): source: Literal["INPUT", "OUTPUT"] - content: List[BedrockContentItem] + content: list[BedrockContentItem] class BedrockGuardrailUsage(TypedDict, total=False): - topicPolicyUnits: Optional[int] - contentPolicyUnits: Optional[int] - wordPolicyUnits: Optional[int] - sensitiveInformationPolicyUnits: Optional[int] - sensitiveInformationPolicyFreeUnits: Optional[int] - contextualGroundingPolicyUnits: Optional[int] + topicPolicyUnits: int | None + contentPolicyUnits: int | None + wordPolicyUnits: int | None + sensitiveInformationPolicyUnits: int | None + sensitiveInformationPolicyFreeUnits: int | None + contextualGroundingPolicyUnits: int | None class BedrockGuardrailOutput(TypedDict, total=False): - text: Optional[str] + text: str | None class BedrockGuardrailTopicPolicyItem(TypedDict, total=False): - name: Optional[str] - type: Optional[str] - action: Optional[str] + name: str | None + type: str | None + action: str | None class BedrockGuardrailTopicPolicy(TypedDict, total=False): - topics: List[BedrockGuardrailTopicPolicyItem] + topics: list[BedrockGuardrailTopicPolicyItem] class BedrockGuardrailContentPolicyFilter(TypedDict, total=False): - type: Optional[str] - confidence: Optional[str] - filterStrength: Optional[str] - action: Optional[str] + type: str | None + confidence: str | None + filterStrength: str | None + action: str | None class BedrockGuardrailContentPolicy(TypedDict, total=False): - filters: List[BedrockGuardrailContentPolicyFilter] + filters: list[BedrockGuardrailContentPolicyFilter] class BedrockGuardrailWordPolicyCustomWord(TypedDict, total=False): @@ -61,47 +61,47 @@ class BedrockGuardrailWordPolicyCustomWord(TypedDict, total=False): class BedrockGuardrailWordPolicyManagedWord(TypedDict, total=False): - match: Optional[str] - type: Optional[str] # Note: There might be more types - action: Optional[str] + match: str | None + type: str | None # Note: There might be more types + action: str | None class BedrockGuardrailWordPolicy(TypedDict, total=False): - customWords: List[BedrockGuardrailWordPolicyCustomWord] - managedWordLists: List[BedrockGuardrailWordPolicyManagedWord] + customWords: list[BedrockGuardrailWordPolicyCustomWord] + managedWordLists: list[BedrockGuardrailWordPolicyManagedWord] class BedrockGuardrailPiiEntity(TypedDict, total=False): - type: Optional[str] # Many PII types available per AWS docs - match: Optional[str] - action: Optional[str] + type: str | None # Many PII types available per AWS docs + match: str | None + action: str | None class BedrockGuardrailRegex(TypedDict, total=False): - name: Optional[str] - regex: Optional[str] - match: Optional[str] - action: Optional[str] + name: str | None + regex: str | None + match: str | None + action: str | None class BedrockGuardrailSensitiveInformationPolicy(TypedDict, total=False): - piiEntities: Optional[List[BedrockGuardrailPiiEntity]] - regexes: Optional[List[BedrockGuardrailRegex]] + piiEntities: list[BedrockGuardrailPiiEntity] | None + regexes: list[BedrockGuardrailRegex] | None class BedrockGuardrailContextualGroundingFilter(TypedDict, total=False): - type: Optional[str] - threshold: Optional[float] - score: Optional[float] - action: Optional[str] + type: str | None + threshold: float | None + score: float | None + action: str | None class BedrockGuardrailContextualGroundingPolicy(TypedDict, total=False): - filters: List[BedrockGuardrailContextualGroundingFilter] + filters: list[BedrockGuardrailContextualGroundingFilter] class BedrockGuardrailCoverage(TypedDict, total=False): - textCharacters: Dict[str, int] + textCharacters: dict[str, int] class BedrockGuardrailInvocationMetrics(TypedDict, total=False): @@ -111,21 +111,21 @@ class BedrockGuardrailInvocationMetrics(TypedDict, total=False): class BedrockGuardrailAssessment(TypedDict, total=False): - topicPolicy: Optional[BedrockGuardrailTopicPolicy] - contentPolicy: Optional[BedrockGuardrailContentPolicy] - wordPolicy: Optional[BedrockGuardrailWordPolicy] - sensitiveInformationPolicy: Optional[BedrockGuardrailSensitiveInformationPolicy] - contextualGroundingPolicy: Optional[BedrockGuardrailContextualGroundingPolicy] + topicPolicy: BedrockGuardrailTopicPolicy | None + contentPolicy: BedrockGuardrailContentPolicy | None + wordPolicy: BedrockGuardrailWordPolicy | None + sensitiveInformationPolicy: BedrockGuardrailSensitiveInformationPolicy | None + contextualGroundingPolicy: BedrockGuardrailContextualGroundingPolicy | None invocationMetrics: BedrockGuardrailInvocationMetrics guardrailCoverage: BedrockGuardrailCoverage class BedrockGuardrailResponse(TypedDict, total=False): - usage: Optional[BedrockGuardrailUsage] - action: Optional[str] - output: Optional[List[BedrockGuardrailOutput]] - outputs: Optional[List[BedrockGuardrailOutput]] - assessments: Optional[List[BedrockGuardrailAssessment]] + usage: BedrockGuardrailUsage | None + action: str | None + output: list[BedrockGuardrailOutput] | None + outputs: list[BedrockGuardrailOutput] | None + assessments: list[BedrockGuardrailAssessment] | None # --------------------------------------------------------------------------- diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/block_code_execution.py b/litellm/types/proxy/guardrails/guardrail_hooks/block_code_execution.py index 84ed3d73575..2a24de6c73b 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/block_code_execution.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/block_code_execution.py @@ -1,6 +1,6 @@ """Types for the Block Code Execution guardrail.""" -from typing import Any, cast, Final, List, Literal, Optional, TypedDict +from typing import Any, Final, Literal, TypedDict, cast from pydantic import Field @@ -35,14 +35,14 @@ class CodeBlockDetection(TypedDict, total=False): language: str confidence: float action_taken: CodeBlockActionTaken - evidence: Optional[str] - snippet: Optional[str] + evidence: str | None + snippet: str | None class BlockCodeExecutionGuardrailConfigModel(GuardrailConfigModel): """Configuration for the Block Code Execution guardrail.""" - blocked_languages: Optional[List[str]] = Field( + blocked_languages: list[str] | None = Field( default=None, description="Language tags to block (e.g. python, javascript, bash). Empty or None = block all fenced code blocks.", json_schema_extra=cast( diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/cato_networks.py b/litellm/types/proxy/guardrails/guardrail_hooks/cato_networks.py index e02c5390b27..86f6d1cca14 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/cato_networks.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/cato_networks.py @@ -1,16 +1,14 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel class CatoNetworksGuardrailConfigModel(GuardrailConfigModel): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The API key for the Cato Networks guardrail. If not provided, the `CATO_API_KEY` environment variable is checked.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The API base for the Cato Networks guardrail. Default is https://api.aisec.catonetworks.com. Also checks if the `CATO_API_BASE` environment variable is set.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/cisco_ai_defense.py b/litellm/types/proxy/guardrails/guardrail_hooks/cisco_ai_defense.py index 46942c4f8c6..4d6d28dd07b 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/cisco_ai_defense.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/cisco_ai_defense.py @@ -2,7 +2,7 @@ Cisco AI Defense Guardrail Config Model """ -from typing import Final, List, Literal, Optional +from typing import Literal from pydantic import BaseModel, ConfigDict, Field @@ -36,7 +36,7 @@ class CiscoAIDefenseRule(BaseModel): rule_name: CISCO_AI_DEFENSE_RULE_NAMES = Field( description="The canonical Cisco AI Defense rule name to evaluate.", ) - entity_types: Optional[List[str]] = Field( + entity_types: list[str] | None = Field( default=None, description=( "Optional list of entity types for the rule (e.g. 'Email Address', " @@ -60,7 +60,7 @@ class CiscoAIDefenseGuardrailConfigModelOptionalParams(BaseModel): "two guardrails to scan both chat and MCP traffic." ), ) - inspect_path: Optional[str] = Field( + inspect_path: str | None = Field( default=None, description=( "Override for the inspection endpoint path. Defaults to " @@ -68,7 +68,7 @@ class CiscoAIDefenseGuardrailConfigModelOptionalParams(BaseModel): "/api/v1/inspect/mcp when inspection_type='mcp'." ), ) - enabled_rules: Optional[List[CiscoAIDefenseRule]] = Field( + enabled_rules: list[CiscoAIDefenseRule] | None = Field( default=None, description=( "Explicit list of Cisco AI Defense rules to evaluate. If omitted, " @@ -76,23 +76,23 @@ class CiscoAIDefenseGuardrailConfigModelOptionalParams(BaseModel): "UI are used." ), ) - integration_profile_id: Optional[str] = Field( + integration_profile_id: str | None = Field( default=None, description="Integration profile id to apply (advanced).", ) - integration_profile_version: Optional[str] = Field( + integration_profile_version: str | None = Field( default=None, description="Integration profile version to apply (advanced).", ) - integration_tenant_id: Optional[str] = Field( + integration_tenant_id: str | None = Field( default=None, description="Integration tenant id to apply (advanced).", ) - integration_type: Optional[str] = Field( + integration_type: str | None = Field( default=None, description="Integration type to apply (advanced).", ) - on_flagged_action: Optional[str] = Field( + on_flagged_action: str | None = Field( default="block", description=( "Action to take when Cisco AI Defense flags content. 'block' raises " @@ -100,7 +100,7 @@ class CiscoAIDefenseGuardrailConfigModelOptionalParams(BaseModel): "request continue." ), ) - fallback_on_error: Optional[Literal["allow", "block"]] = Field( + fallback_on_error: Literal["allow", "block"] | None = Field( default="block", description=( "Behaviour when the Cisco AI Defense API is unavailable: 'allow' " @@ -108,7 +108,7 @@ class CiscoAIDefenseGuardrailConfigModelOptionalParams(BaseModel): "the request (maximum security)." ), ) - timeout: Optional[float] = Field( + timeout: float | None = Field( default=10.0, ge=1.0, le=60.0, @@ -119,7 +119,7 @@ class CiscoAIDefenseGuardrailConfigModelOptionalParams(BaseModel): class CiscoAIDefenseGuardrailConfigModel(GuardrailConfigModel[CiscoAIDefenseGuardrailConfigModelOptionalParams]): """Configuration parameters for the Cisco AI Defense guardrail.""" - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description=( "API key for the Cisco AI Defense inspection endpoint. If " @@ -128,7 +128,7 @@ class CiscoAIDefenseGuardrailConfigModel(GuardrailConfigModel[CiscoAIDefenseGuar "Both the chat and MCP endpoints use this key." ), ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description=( "Regional base URL for the Cisco AI Defense Inspection API. " diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/compresr.py b/litellm/types/proxy/guardrails/guardrail_hooks/compresr.py index dad61f83b7d..9efc2fbff55 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/compresr.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/compresr.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Literal +from typing import Any, Literal from pydantic import BaseModel, Field @@ -91,7 +91,7 @@ class CompresrGuardrailOptionalParams(BaseModel): "Unset lets the server default apply (~10.0)." ), ) - compression_params: Dict[str, Any] | None = Field( + compression_params: dict[str, Any] | None = Field( default=None, description=( "Passthrough of extra parameters forwarded verbatim in the Compresr " diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/crowdstrike_aidr.py b/litellm/types/proxy/guardrails/guardrail_hooks/crowdstrike_aidr.py index e967e2b1d9a..1d30f0f2c7a 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/crowdstrike_aidr.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/crowdstrike_aidr.py @@ -1,5 +1,3 @@ -from typing import Optional - from pydantic import BaseModel, Field from .base import GuardrailConfigModel @@ -10,11 +8,11 @@ class CrowdStrikeAIDRGuardrailConfigModelOptionalParams(BaseModel): class CrowdStrikeAIDRGuardrailConfigModel(GuardrailConfigModel[CrowdStrikeAIDRGuardrailConfigModelOptionalParams]): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The CrowdStrike AIDR API key. Reads from CS_AIDR_TOKEN env var if None.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The CrowdStrike AIDR API base URL. Reads from CS_AIDR_BASE_URL env var if None.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/deepkeep.py b/litellm/types/proxy/guardrails/guardrail_hooks/deepkeep.py index fcbb779ddf4..9830faffc23 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/deepkeep.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/deepkeep.py @@ -1,12 +1,10 @@ -from typing import Optional - from pydantic import BaseModel, Field from .base import GuardrailConfigModel class DeepKeepGuardrailConfigModelOptionalParams(BaseModel): - unreachable_fallback: Optional[str] = Field( + unreachable_fallback: str | None = Field( default="fail_closed", description=( "Behavior when the DeepKeep API is unreachable. " @@ -17,21 +15,21 @@ class DeepKeepGuardrailConfigModelOptionalParams(BaseModel): class DeepKeepGuardrailConfigModel(GuardrailConfigModel[DeepKeepGuardrailConfigModelOptionalParams]): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description=( "The API key for the DeepKeep AI Firewall. " "If not provided, the `DEEPKEEP_API_KEY` environment variable is checked." ), ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description=( "The API base URL for the DeepKeep AI Firewall. " "If not provided, the `DEEPKEEP_API_BASE` environment variable is checked." ), ) - deepkeep_firewall_id: Optional[str] = Field( + deepkeep_firewall_id: str | None = Field( default=None, description=( "The DeepKeep Firewall ID to use for guardrail evaluation. " diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/dynamoai.py b/litellm/types/proxy/guardrails/guardrail_hooks/dynamoai.py index 8d089313649..ae40162c17c 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/dynamoai.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/dynamoai.py @@ -1,7 +1,7 @@ # Type definitions for DynamoAI Guardrails API import enum -from typing import Any, Dict, List, Literal, Optional, TypedDict +from typing import Any, Literal, TypedDict from pydantic import Field @@ -16,7 +16,7 @@ class DynamoAIMessage(TypedDict): class DynamoRequestMetadata(TypedDict): - endUserId: Optional[str] + endUserId: str | None class DynamoTextType(str, enum.Enum): @@ -41,12 +41,12 @@ class PolicyApplicableTo(str, enum.Enum): class DynamoAIRequest(TypedDict, total=False): """Request structure for DynamoAI /moderation/analyze endpoint""" - messages: List[Dict[str, Any]] - textType: Optional[DynamoTextType] - policyIds: List[str] - modelId: Optional[str] - clientId: Optional[str] - metadata: Optional[DynamoRequestMetadata] + messages: list[dict[str, Any]] + textType: DynamoTextType | None + policyIds: list[str] + modelId: str | None + clientId: str | None + metadata: DynamoRequestMetadata | None class PolicyInfo(TypedDict, total=False): @@ -57,8 +57,8 @@ class PolicyInfo(TypedDict, total=False): description: str method: PolicyMethod action: Literal["BLOCK", "WARN", "REDACT", "SANITIZE", "NONE"] - methodParams: Dict[str, Any] - decisionParams: Dict[str, Any] + methodParams: dict[str, Any] + decisionParams: dict[str, Any] applicableTo: PolicyApplicableTo created_at: str creatorId: str @@ -68,15 +68,15 @@ class PolicyOutputs(TypedDict, total=False): """Outputs from the policy""" action: Literal["BLOCK", "WARN", "REDACT", "SANITIZE", "NONE"] - message: Optional[str] + message: str | None class AppliedPolicyDto(TypedDict, total=False): """Applied policy details from DynamoAI response""" policy: PolicyInfo - outputs: Optional[Dict[str, Any]] - action: Optional[str] + outputs: dict[str, Any] | None + action: str | None class DynamoAIResponse(TypedDict, total=False): @@ -85,37 +85,37 @@ class DynamoAIResponse(TypedDict, total=False): text: str textType: DynamoTextType finalAction: Literal["BLOCK", "WARN", "REDACT", "SANITIZE", "NONE"] - appliedPolicies: List[AppliedPolicyDto] - error: Optional[str] + appliedPolicies: list[AppliedPolicyDto] + error: str | None class DynamoAIProcessedResult(TypedDict): """Processed result from DynamoAI guardrail check""" - violations_detected: List[str] - violation_details: Dict[str, Any] + violations_detected: list[str] + violation_details: dict[str, Any] class DynamoAIGuardrailConfigModel(GuardrailConfigModel): """Configuration model for DynamoAI Guardrails""" - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="API key for DynamoAI Guardrails. If not provided, the `DYNAMOAI_API_KEY` environment variable is checked.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="Base URL for DynamoAI API. If not provided, the `DYNAMOAI_API_BASE` environment variable is checked, defaults to https://api.dynamo.ai", ) - policy_ids: Optional[List[str]] = Field( + policy_ids: list[str] | None = Field( default=None, description="List of DynamoAI policy IDs to apply. If not provided, the `DYNAMOAI_POLICY_IDS` environment variable is checked (comma-separated).", ) - model_id: Optional[str] = Field( + model_id: str | None = Field( default=None, description="Model ID for tracking/logging purposes. If not provided, the `DYNAMOAI_MODEL_ID` environment variable is checked.", ) - guardrail_name: Optional[str] = Field( + guardrail_name: str | None = Field( default=None, description="Name of the guardrail for identification in logs and traces.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/enkryptai.py b/litellm/types/proxy/guardrails/guardrail_hooks/enkryptai.py index cebac4d826a..9b0d448ded2 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/enkryptai.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/enkryptai.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Union +from typing import Any from pydantic import BaseModel, Field from typing_extensions import TypedDict @@ -18,7 +18,7 @@ class EnkryptAIPolicyViolationDetail(TypedDict, total=False): class EnkryptAIPIIDetail(TypedDict, total=False): """Details for PII detection.""" - pii: Dict[str, Any] + pii: dict[str, Any] class EnkryptAIToxicityDetail(TypedDict, total=False): @@ -33,18 +33,18 @@ class EnkryptAIToxicityDetail(TypedDict, total=False): - identity_hate """ - toxic: Optional[float] - severe_toxic: Optional[float] - obscene: Optional[float] - threat: Optional[float] - insult: Optional[float] - identity_hate: Optional[float] + toxic: float | None + severe_toxic: float | None + obscene: float | None + threat: float | None + insult: float | None + identity_hate: float | None class EnkryptAIKeywordDetail(TypedDict, total=False): """Details for keyword detection.""" - detected_keywords: List[str] + detected_keywords: list[str] class EnkryptAIBiasDetail(TypedDict, total=False): @@ -66,25 +66,25 @@ class EnkryptAIResponseSummary(TypedDict, total=False): - jailbreak: 0 or 1 """ - toxicity: Optional[List[str]] - policy_violation: Optional[int] - pii: Optional[int] - keyword_detected: Optional[int] - bias: Optional[int] - prompt_injection: Optional[int] - jailbreak: Optional[int] + toxicity: list[str] | None + policy_violation: int | None + pii: int | None + keyword_detected: int | None + bias: int | None + prompt_injection: int | None + jailbreak: int | None class EnkryptAIResponseDetails(TypedDict, total=False): """Detailed information about detected violations.""" - policy_violation: Optional[EnkryptAIPolicyViolationDetail] - pii: Optional[EnkryptAIPIIDetail] - toxicity: Optional[EnkryptAIToxicityDetail] - keyword_detected: Optional[EnkryptAIKeywordDetail] - bias: Optional[EnkryptAIBiasDetail] - prompt_injection: Optional[Dict[str, Any]] - jailbreak: Optional[Dict[str, Any]] + policy_violation: EnkryptAIPolicyViolationDetail | None + pii: EnkryptAIPIIDetail | None + toxicity: EnkryptAIToxicityDetail | None + keyword_detected: EnkryptAIKeywordDetail | None + bias: EnkryptAIBiasDetail | None + prompt_injection: dict[str, Any] | None + jailbreak: dict[str, Any] | None class EnkryptAIResponse(TypedDict, total=False): @@ -97,17 +97,15 @@ class EnkryptAIResponse(TypedDict, total=False): class EnkryptAIProcessedResult(TypedDict): """Processed result from EnkryptAI guardrail response.""" - attacks_detected: List[str] - attack_details: Dict[ + attacks_detected: list[str] + attack_details: dict[ str, - Union[ - EnkryptAIPolicyViolationDetail, - EnkryptAIPIIDetail, - EnkryptAIToxicityDetail, - EnkryptAIKeywordDetail, - EnkryptAIBiasDetail, - Dict[str, Any], - ], + EnkryptAIPolicyViolationDetail + | EnkryptAIPIIDetail + | EnkryptAIToxicityDetail + | EnkryptAIKeywordDetail + | EnkryptAIBiasDetail + | dict[str, Any], ] @@ -115,27 +113,27 @@ class EnkryptAIProcessedResult(TypedDict): class EnkryptAIGuardrailConfigs(BaseModel): """Configuration parameters for the EnkryptAI guardrail""" - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The EnkryptAI API key. Reads from ENKRYPTAI_API_KEY env var if None.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The EnkryptAI API base URL. Defaults to https://api.enkryptai.com. Also checks if the ENKRYPTAI_API_KEY env var is set.", ) - policy_name: Optional[str] = Field( + policy_name: str | None = Field( default=None, description="The EnkryptAI policy name to use. Sent via x-enkrypt-policy header.", ) - deployment_name: Optional[str] = Field( + deployment_name: str | None = Field( default=None, description="The EnkryptAI deployment name to use. Sent via X-Enkrypt-Deployment header.", ) - detectors: Optional[dict] = Field( + detectors: dict | None = Field( default=None, description="Dictionary of detector configurations (e.g., {'nsfw': {'enabled': True}, 'toxicity': {'enabled': True}}).", ) - block_on_violation: Optional[bool] = Field( + block_on_violation: bool | None = Field( default=True, description="Whether to block requests when violations are detected. Defaults to True.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/generic_guardrail_api.py b/litellm/types/proxy/guardrails/guardrail_hooks/generic_guardrail_api.py index 3544f154665..4a868c48352 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/generic_guardrail_api.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/generic_guardrail_api.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Final, Literal from pydantic import BaseModel, ConfigDict, Field from typing_extensions import TypedDict @@ -24,25 +24,25 @@ class GuardrailToolParam(BaseModel): class GenericGuardrailAPIMetadata(TypedDict, total=False): - user_api_key_hash: Optional[str] - user_api_key_alias: Optional[str] - user_api_key_user_id: Optional[str] - user_api_key_user_email: Optional[str] - user_api_key_team_id: Optional[str] - user_api_key_team_alias: Optional[str] - user_api_key_end_user_id: Optional[str] - user_api_key_org_id: Optional[str] + user_api_key_hash: str | None + user_api_key_alias: str | None + user_api_key_user_id: str | None + user_api_key_user_email: str | None + user_api_key_team_id: str | None + user_api_key_team_alias: str | None + user_api_key_end_user_id: str | None + user_api_key_org_id: str | None class GenericGuardrailAPIOptionalParams(BaseModel): """Optional parameters for the Generic Guardrail API""" - additional_provider_specific_params: Optional[Dict[str, Any]] = Field( + additional_provider_specific_params: dict[str, Any] | None = Field( default=None, description="Additional provider-specific parameters to send with the guardrail request", ) - unreachable_fallback: Optional[Literal["fail_closed", "fail_open"]] = Field( + unreachable_fallback: Literal["fail_closed", "fail_open"] | None = Field( default="fail_closed", description=( "Behavior when the guardrail endpoint is unreachable due to network errors. " @@ -50,7 +50,7 @@ class GenericGuardrailAPIOptionalParams(BaseModel): ), ) - fail_on_error: Optional[bool] = Field( + fail_on_error: bool | None = Field( default=True, description=( "Behavior on any guardrail error, not just unreachability. " @@ -60,7 +60,7 @@ class GenericGuardrailAPIOptionalParams(BaseModel): ), ) - streaming_end_of_stream_only: Optional[bool] = Field( + streaming_end_of_stream_only: bool | None = Field( default=None, description=( "If False (default when unset), the guardrail runs on sampled chunks during " @@ -73,7 +73,7 @@ class GenericGuardrailAPIOptionalParams(BaseModel): ), ) - streaming_sampling_rate: Optional[int] = Field( + streaming_sampling_rate: int | None = Field( default=None, ge=1, description=( @@ -84,7 +84,7 @@ class GenericGuardrailAPIOptionalParams(BaseModel): ), ) - streaming_transform_mode: Optional[Literal["block_only", "incremental_diff"]] = Field( + streaming_transform_mode: Literal["block_only", "incremental_diff"] | None = Field( default=None, description=( "Controls whether text modifications returned by the guardrail (action=" @@ -108,7 +108,7 @@ class GenericGuardrailAPIConfigModel( ): """Configuration parameters for the Generic Guardrail API guardrail""" - optional_params: Optional[GenericGuardrailAPIOptionalParams] = Field( + optional_params: GenericGuardrailAPIOptionalParams | None = Field( default_factory=GenericGuardrailAPIOptionalParams, description="Optional parameters for the Generic Guardrail API guardrail", ) @@ -122,26 +122,26 @@ class GenericGuardrailAPIRequest(BaseModel): """Request model for the Generic Guardrail API""" input_type: Literal["request", "response"] - litellm_call_id: Optional[str] = None # the call id of the individual LLM call - litellm_trace_id: Optional[str] = ( + litellm_call_id: str | None = None # the call id of the individual LLM call + litellm_trace_id: str | None = ( None # the trace id of the LLM call - useful if there are multiple LLM calls for the same conversation ) - structured_messages: Optional[List[AllMessageValues]] = None - images: Optional[List[str]] = None - tools: Optional[List[GuardrailToolParam]] = None - texts: Optional[List[str]] = None + structured_messages: list[AllMessageValues] | None = None + images: list[str] | None = None + tools: list[GuardrailToolParam] | None = None + texts: list[str] | None = None request_data: GenericGuardrailAPIMetadata - request_headers: Optional[Dict[str, str]] = Field( + request_headers: dict[str, str] | None = Field( default=None, description="Sanitized inbound request headers from the original proxy request.", ) - litellm_version: Optional[str] = Field( + litellm_version: str | None = Field( default=None, description="LiteLLM library version running this proxy.", ) - additional_provider_specific_params: Optional[Dict[str, Any]] = None - tool_calls: Optional[Union[List[ChatCompletionToolCallChunk], List[ChatCompletionMessageToolCall]]] = None - model: Optional[str] = None # the model being used for the LLM call + additional_provider_specific_params: dict[str, Any] | None = None + tool_calls: list[ChatCompletionToolCallChunk] | list[ChatCompletionMessageToolCall] | None = None + model: str | None = None # the model being used for the LLM call def coerce_stream_holdback_value(value: Any) -> int: @@ -161,22 +161,22 @@ def coerce_stream_holdback_value(value: Any) -> int: class GenericGuardrailAPIResponse: """Response model for the Generic Guardrail API""" - texts: Optional[List[str]] - images: Optional[List[str]] - tools: Optional[List[GuardrailToolParam]] + texts: list[str] | None + images: list[str] | None + tools: list[GuardrailToolParam] | None action: str - blocked_reason: Optional[str] - stream_holdback_chars: Optional[List[int]] + blocked_reason: str | None + stream_holdback_chars: list[int] | None def __init__( self, action: str, - texts: Optional[List[str]] = None, - blocked_reason: Optional[str] = None, - images: Optional[List[str]] = None, - tools: Optional[List[GuardrailToolParam]] = None, - stream_holdback_chars: Optional[List[int]] = None, - ): + texts: list[str] | None = None, + blocked_reason: str | None = None, + images: list[str] | None = None, + tools: list[GuardrailToolParam] | None = None, + stream_holdback_chars: list[int] | None = None, + ) -> None: self.action = action self.blocked_reason = blocked_reason self.texts = texts diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/grayswan.py b/litellm/types/proxy/guardrails/guardrail_hooks/grayswan.py index d5e4ae226e2..796ff2818a4 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/grayswan.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/grayswan.py @@ -1,7 +1,5 @@ """Gray Swan guardrail configuration models.""" -from typing import Dict, Optional - from pydantic import BaseModel, Field from .base import GuardrailConfigModel @@ -10,33 +8,33 @@ from .base import GuardrailConfigModel class GraySwanGuardrailConfigModelOptionalParams(BaseModel): """Optional parameters for the Gray Swan guardrail.""" - on_flagged_action: Optional[str] = Field( + on_flagged_action: str | None = Field( default="passthrough", description="Action when a violation is detected: 'block' rejects the call (400 error), 'monitor' logs only, 'passthrough' replaces response content with violation message (200 status).", ) - violation_threshold: Optional[float] = Field( + violation_threshold: float | None = Field( default=0.5, ge=0.0, le=1.0, description="Threshold between 0 and 1 at which Gray Swan violations trigger the configured action.", ) - reasoning_mode: Optional[str] = Field( + reasoning_mode: str | None = Field( default=None, description="Gray Swan reasoning mode override. Accepted values: 'off', 'hybrid', 'thinking'.", ) - policy_id: Optional[str] = Field( + policy_id: str | None = Field( default=None, description="Gray Swan policy identifier to apply during monitoring.", ) - categories: Optional[Dict[str, str]] = Field( + categories: dict[str, str] | None = Field( default=None, description="Default Gray Swan category definitions to send with each request.", ) - fail_open: Optional[bool] = Field( + fail_open: bool | None = Field( default=True, description="If true (default), errors contacting Gray Swan are logged and the request proceeds. If false, errors propagate and block the request.", ) - guardrail_timeout: Optional[float] = Field( + guardrail_timeout: float | None = Field( default=30.0, description="Timeout in seconds for calling the Gray Swan guardrail service.", ) @@ -45,11 +43,11 @@ class GraySwanGuardrailConfigModelOptionalParams(BaseModel): class GraySwanGuardrailConfigModel(GuardrailConfigModel[GraySwanGuardrailConfigModelOptionalParams]): """Configuration parameters for the Gray Swan guardrail.""" - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="API key for Gray Swan. Reads from the `GRAYSWAN_API_KEY` environment variable when omitted.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="Override for the Gray Swan API base URL. Defaults to https://api.grayswan.ai and can be set via `GRAYSWAN_API_BASE`.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/guardrails_ai.py b/litellm/types/proxy/guardrails/guardrail_hooks/guardrails_ai.py index a0298dbe955..129bc2bb8db 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/guardrails_ai.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/guardrails_ai.py @@ -1,4 +1,4 @@ -from typing import Literal, Optional +from typing import Literal from pydantic import Field @@ -6,17 +6,17 @@ from .base import GuardrailConfigModel class GuardrailsAIGuardrailConfigModel(GuardrailConfigModel): - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The API base for the Guardrails AI guardrail. Defaults to http://0.0.0.0:8000, the `GUARDRAILS_AI_API_BASE` environment variable is checked.", ) - guard_name: Optional[str] = Field( + guard_name: str | None = Field( default=None, description="The name of the Guardrails AI guardrail. Required for the Guardrails AI guardrail.", ) - guardrails_ai_api_input_format: Optional[Literal["inputs", "llmOutput"]] = Field( + guardrails_ai_api_input_format: Literal["inputs", "llmOutput"] | None = Field( default="llmOutput", description="The format of the input to the Guardrails AI API. Defaults to 'llmOutput'.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/headroom.py b/litellm/types/proxy/guardrails/guardrail_hooks/headroom.py index 71aa243069a..d517e508596 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/headroom.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/headroom.py @@ -1,4 +1,4 @@ -from typing import Literal, Optional +from typing import Literal from pydantic import BaseModel, Field @@ -6,15 +6,15 @@ from .base import GuardrailConfigModel class HeadroomGuardrailConfigModel(GuardrailConfigModel[BaseModel]): - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="Base URL for the headroom compression service (e.g. https://api.headroom.ai). Falls back to HEADROOM_API_BASE env var.", ) - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="API key for the headroom compression service. Falls back to HEADROOM_API_KEY env var.", ) - model: Optional[str] = Field( + model: str | None = Field( default=None, description="Model name forwarded to the headroom /v1/compress endpoint.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/hiddenlayer.py b/litellm/types/proxy/guardrails/guardrail_hooks/hiddenlayer.py index 4a0e5a23389..949a030fdb9 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/hiddenlayer.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/hiddenlayer.py @@ -1,7 +1,5 @@ import enum -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel @@ -17,22 +15,22 @@ class HiddenlayerMessages(str, enum.Enum): class HiddenlayerGuardrailConfigModel(GuardrailConfigModel): - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The URL of the Hiddenlayer server. If not provided, the `HIDDENLAYER_API_BASE` environment variable is checked or https://api.hiddenlayer.ai is used.", ) - api_id: Optional[str] = Field( + api_id: str | None = Field( default=None, description="The Hiddenlayer API Id for the Hiddenlayer API. If not provided, the `HIDDENLAYER_CLIENT_ID` environment variable is checked or https://api.hiddenlayer.ai is used.", ) - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The Hiddenlayer Secret Key for the Hiddenlayer API.. If not provided, the `HIDDENLAYER_CLIENT_SECRET` environment variable is checked.", ) - version: Optional[int] = Field(default=2, description="Hiddenlayer guardrail version to use.") + version: int | None = Field(default=2, description="Hiddenlayer guardrail version to use.") @staticmethod def ui_friendly_name() -> str: diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/ibm/__init__.py b/litellm/types/proxy/guardrails/guardrail_hooks/ibm/__init__.py index 52616023183..a45205649bb 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/ibm/__init__.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/ibm/__init__.py @@ -10,12 +10,12 @@ from .ibm_detector import ( ) __all__ = [ - "IBMGuardrailsBaseConfigModel", + "IBMDetectorDetection", "IBMDetectorGuardrailConfigModel", "IBMDetectorOptionalParams", "IBMDetectorRequestBodyDetectorServer", "IBMDetectorRequestBodyOrchestrator", "IBMDetectorResponseDetectorServer", "IBMDetectorResponseOrchestrator", - "IBMDetectorDetection", + "IBMGuardrailsBaseConfigModel", ] diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/ibm/base.py b/litellm/types/proxy/guardrails/guardrail_hooks/ibm/base.py index d9a3b8bf506..22f6b2fd7dc 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/ibm/base.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/ibm/base.py @@ -1,32 +1,30 @@ -from typing import Optional - from pydantic import BaseModel, Field class IBMGuardrailsBaseConfigModel(BaseModel): """Base configuration parameters for IBM Guardrails""" - auth_token: Optional[str] = Field( + auth_token: str | None = Field( default=None, description="Authorization bearer token for IBM Guardrails API. Reads from IBM_GUARDRAILS_AUTH_TOKEN env var if None.", ) - base_url: Optional[str] = Field( + base_url: str | None = Field( default=None, description="Base URL for the IBM Guardrails server", ) - detector_id: Optional[str] = Field( + detector_id: str | None = Field( default=None, description="Name of the detector inside the server (e.g., 'jailbreak-detector')", ) - is_detector_server: Optional[bool] = Field( + is_detector_server: bool | None = Field( default=True, description="Boolean flag to determine if calling a detector server (True) or the FMS Orchestrator (False). Defaults to True.", ) - verify_ssl: Optional[bool] = Field( + verify_ssl: bool | None = Field( default=True, description="Whether to verify SSL certificates. Defaults to True.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/ibm/ibm_detector.py b/litellm/types/proxy/guardrails/guardrail_hooks/ibm/ibm_detector.py index e30f8c938ae..5226d5fe6de 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/ibm/ibm_detector.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/ibm/ibm_detector.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional +from typing import Any from pydantic import BaseModel, Field from typing_extensions import TypedDict @@ -12,15 +12,15 @@ from .base import IBMGuardrailsBaseConfigModel class IBMDetectorRequestBodyDetectorServer(TypedDict): """Request body for calling IBM Detector Server directly""" - contents: List[str] - detector_params: Dict[str, Any] + contents: list[str] + detector_params: dict[str, Any] class IBMDetectorRequestBodyOrchestrator(TypedDict): """Request body for calling IBM Detector via FMS Guardrails Orchestrator""" content: str - detectors: Dict[str, Dict[str, Any]] + detectors: dict[str, dict[str, Any]] class IBMDetectorDetection(TypedDict, total=False): @@ -32,21 +32,21 @@ class IBMDetectorDetection(TypedDict, total=False): detection: str detection_type: str score: float - evidences: List[Any] - metadata: Dict[str, Any] - detector_id: Optional[str] # Only present in orchestrator response + evidences: list[Any] + metadata: dict[str, Any] + detector_id: str | None # Only present in orchestrator response class IBMDetectorResponseDetectorServer(TypedDict): """Response from IBM Detector Server (returns list of lists)""" - detections: List[List[IBMDetectorDetection]] + detections: list[list[IBMDetectorDetection]] class IBMDetectorResponseOrchestrator(TypedDict): """Response from IBM FMS Guardrails Orchestrator""" - detections: List[IBMDetectorDetection] + detections: list[IBMDetectorDetection] # Pydantic Config Models @@ -55,22 +55,22 @@ class IBMDetectorResponseOrchestrator(TypedDict): class IBMDetectorOptionalParams(BaseModel): """Optional parameters for IBM Detector guardrail""" - detector_params: Optional[Dict[str, Any]] = Field( + detector_params: dict[str, Any] | None = Field( default_factory=lambda: {}, description="Dictionary of arguments to pass to the detector.", ) - extra_headers: Optional[Dict[str, Any]] = Field( + extra_headers: dict[str, Any] | None = Field( default_factory=lambda: {}, description="Dictionary of extra headers to pass to the detector.", ) - score_threshold: Optional[float] = Field( + score_threshold: float | None = Field( default=None, description="Minimum score threshold to consider a detection as a violation (0.0 to 1.0). If set, detections below this threshold will be ignored.", ) - block_on_detection: Optional[bool] = Field( + block_on_detection: bool | None = Field( default=True, description="Whether to block requests when detections are found. Defaults to True.", ) @@ -82,7 +82,7 @@ class IBMDetectorGuardrailConfigModel( ): """Configuration model for IBM Detector guardrail""" - optional_params: Optional[IBMDetectorOptionalParams] = Field( + optional_params: IBMDetectorOptionalParams | None = Field( default_factory=IBMDetectorOptionalParams, description="Optional parameters for the IBM Detector guardrail", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/javelin.py b/litellm/types/proxy/guardrails/guardrail_hooks/javelin.py index fef597a9ef0..44717c9518a 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/javelin.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/javelin.py @@ -1,5 +1,3 @@ -from typing import Dict, List, Optional - from pydantic import Field from typing_extensions import TypedDict @@ -12,8 +10,8 @@ class JavelinGuardInput(TypedDict): class JavelinGuardRequest(TypedDict): input: JavelinGuardInput - config: Optional[Dict] - metadata: Optional[Dict] + config: dict | None + metadata: dict | None class JavelinPromptInjectionCategories(TypedDict): @@ -76,8 +74,8 @@ class JavelinLanguageDetectionAssessment(TypedDict): class JavelinGuardResponse(TypedDict): - assessments: List[ - Dict[ + assessments: list[ + dict[ str, JavelinPromptInjectionAssessment | JavelinTrustSafetyAssessment | JavelinLanguageDetectionAssessment, ] @@ -87,11 +85,11 @@ class JavelinGuardResponse(TypedDict): class JavelinGuardrailConfigModel(GuardrailConfigModel): """Configuration parameters for the Javelin guardrail""" - guard_name: Optional[str] = Field(default=None, description="Name of the Javelin guard to use") - api_version: Optional[str] = Field(default="v1", description="API version for Javelin service") - metadata: Optional[Dict] = Field(default=None, description="Additional metadata to send with requests") - application: Optional[str] = Field(default=None, description="Application name for Javelin service") - config: Optional[Dict] = Field(default=None, description="Configuration parameters for Javelin service") + guard_name: str | None = Field(default=None, description="Name of the Javelin guard to use") + api_version: str | None = Field(default="v1", description="API version for Javelin service") + metadata: dict | None = Field(default=None, description="Additional metadata to send with requests") + application: str | None = Field(default=None, description="Application name for Javelin service") + config: dict | None = Field(default=None, description="Configuration parameters for Javelin service") @staticmethod def ui_friendly_name() -> str: diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/lakera_ai_v2.py b/litellm/types/proxy/guardrails/guardrail_hooks/lakera_ai_v2.py index 31fea035e87..d6fc7315efb 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/lakera_ai_v2.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/lakera_ai_v2.py @@ -1,44 +1,42 @@ -from typing import Dict, List, Optional - from typing_extensions import TypedDict from litellm.types.llms.openai import AllMessageValues class LakeraAIRequest(TypedDict, total=False): - messages: List[AllMessageValues] - project_id: Optional[str] - payload: Optional[bool] - breakdown: Optional[bool] - metadata: Optional[Dict] - dev_info: Optional[bool] + messages: list[AllMessageValues] + project_id: str | None + payload: bool | None + breakdown: bool | None + metadata: dict | None + dev_info: bool | None class LakeraAIPayloadItem(TypedDict, total=False): - start: Optional[int] - end: Optional[int] - text: Optional[str] - detector_type: Optional[str] - labels: Optional[List[str]] + start: int | None + end: int | None + text: str | None + detector_type: str | None + labels: list[str] | None class LakeraAIBreakdownItem(TypedDict, total=False): - project_id: Optional[str] - policy_id: Optional[str] - detector_id: Optional[str] - detector_type: Optional[str] - detected: Optional[bool] + project_id: str | None + policy_id: str | None + detector_id: str | None + detector_type: str | None + detected: bool | None class LakeraAIDevInfo(TypedDict, total=False): - git_revision: Optional[str] - git_timestamp: Optional[str] - model_version: Optional[str] - version: Optional[str] + git_revision: str | None + git_timestamp: str | None + model_version: str | None + version: str | None class LakeraAIResponse(TypedDict, total=False): - flagged: Optional[bool] - payload: Optional[List[LakeraAIPayloadItem]] - breakdown: Optional[List[LakeraAIBreakdownItem]] - dev_info: Optional[LakeraAIDevInfo] + flagged: bool | None + payload: list[LakeraAIPayloadItem] | None + breakdown: list[LakeraAIBreakdownItem] | None + dev_info: LakeraAIDevInfo | None diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/lasso.py b/litellm/types/proxy/guardrails/guardrail_hooks/lasso.py index 3f1ce6f488d..e562e79dd45 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/lasso.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/lasso.py @@ -1,27 +1,25 @@ -from typing import Optional - from pydantic import BaseModel, Field from .base import GuardrailConfigModel class LassoGuardrailConfigModelOptionalParams(BaseModel): - user_id: Optional[str] = Field( + user_id: str | None = Field( default=None, description="The user ID for the Lasso guardrail. If not provided, the `LASSO_USER_ID` environment variable is checked.", ) - conversation_id: Optional[str] = Field( + conversation_id: str | None = Field( default=None, description="The conversation ID for the Lasso guardrail. If not provided, the `LASSO_CONVERSATION_ID` environment variable is checked.", ) class LassoGuardrailConfigModel(GuardrailConfigModel[LassoGuardrailConfigModelOptionalParams]): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The API key for the Lasso guardrail. If not provided, the `LASSO_API_KEY` environment variable is checked.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The API base for the Lasso guardrail. Default is https://server.lasso.security. Also checks if the `LASSO_API_BASE` environment variable is set.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/litellm_content_filter.py b/litellm/types/proxy/guardrails/guardrail_hooks/litellm_content_filter.py index 6c2f3db5ff7..78800a5e9a2 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/litellm_content_filter.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/litellm_content_filter.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional, TypedDict, Union +from typing import Any, Literal, TypedDict from pydantic import Field @@ -23,7 +23,7 @@ class CompetitorIntentEvidenceEntry(TypedDict, total=False): type: Literal["entity", "signal"] key: str # e.g. "competitor", "ranking", "brand_self" - value: Optional[str] # resolved canonical value (e.g. "qatar_airways") + value: str | None # resolved canonical value (e.g. "qatar_airways") match: str # matched substring @@ -32,10 +32,10 @@ class CompetitorIntentResult(TypedDict, total=False): intent: CompetitorIntentType confidence: float - entities: Dict[str, List[str]] # brand_self, competitors, category - signals: List[str] + entities: dict[str, list[str]] # brand_self, competitors, category + signals: list[str] action_hint: CompetitorActionHint - evidence: List[CompetitorIntentEvidenceEntry] + evidence: list[CompetitorIntentEvidenceEntry] # Detection type enum @@ -57,7 +57,7 @@ class BlockedWordDetection(TypedDict): type: Literal["blocked_word"] keyword: str action: str # ContentFilterAction.value - description: Optional[str] + description: str | None class CategoryKeywordDetection(TypedDict): @@ -75,17 +75,12 @@ class CompetitorIntentDetection(TypedDict): intent: str confidence: float action_hint: str - entities: Dict[str, List[str]] - signals: List[str] - evidence: List[Dict[str, Any]] + entities: dict[str, list[str]] + signals: list[str] + evidence: list[dict[str, Any]] -ContentFilterDetection = Union[ - PatternDetection, - BlockedWordDetection, - CategoryKeywordDetection, - CompetitorIntentDetection, -] +ContentFilterDetection = PatternDetection | BlockedWordDetection | CategoryKeywordDetection | CompetitorIntentDetection class ContentFilterCategoryConfig(BaseLiteLLMOpenAIResponseObject): @@ -111,7 +106,7 @@ class ContentFilterCategoryConfig(BaseLiteLLMOpenAIResponseObject): default="medium", description="The severity threshold to detect the category", ) - category_file: Optional[str] = Field( + category_file: str | None = Field( default=None, description="Optional override. Use your own category file instead of the default one.", ) @@ -128,21 +123,21 @@ class LitellmContentFilterGuardrailConfigModel(GuardrailConfigModel): """ # Traditional patterns and keywords - patterns: Optional[List[dict]] = Field( + patterns: list[dict] | None = Field( default=None, description="List of regex patterns to detect (prebuilt or custom)", ) - blocked_words: Optional[List[dict]] = Field( + blocked_words: list[dict] | None = Field( default=None, description="List of blocked keywords with actions", ) - blocked_words_file: Optional[str] = Field( + blocked_words_file: str | None = Field( default=None, description="Path to YAML file containing blocked words", ) # Category-based detection - categories: Optional[List[ContentFilterCategoryConfig]] = Field( + categories: list[ContentFilterCategoryConfig] | None = Field( default=None, description="List of prebuilt categories to enable (harmful_*, bias_*)", ) @@ -152,17 +147,17 @@ class LitellmContentFilterGuardrailConfigModel(GuardrailConfigModel): ) # Redaction customization - pattern_redaction_format: Optional[str] = Field( + pattern_redaction_format: str | None = Field( default="[{pattern_name}_REDACTED]", description="Format string for pattern redaction (use {pattern_name} placeholder)", ) - keyword_redaction_tag: Optional[str] = Field( + keyword_redaction_tag: str | None = Field( default="[KEYWORD_REDACTED]", description="Tag to use for keyword redaction", ) # Competitor intent blocker (generic; industry presets add domain_words, etc.) - competitor_intent_config: Optional[Dict[str, Any]] = Field( + competitor_intent_config: dict[str, Any] | None = Field( default=None, description="Optional config for intent-based competitor comparison detection. " "Keys: brand_self (list), competitors (list), competitor_aliases (dict), " diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/model_armor.py b/litellm/types/proxy/guardrails/guardrail_hooks/model_armor.py index d5e601ce8ea..ec7e1595215 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/model_armor.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/model_armor.py @@ -1,5 +1,3 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel @@ -8,19 +6,19 @@ from .base import GuardrailConfigModel class ModelArmorGuardrailConfigModel(GuardrailConfigModel): """Configuration parameters for Google Cloud Model Armor guardrail""" - template_id: Optional[str] = Field(default=None, description="The ID of your Model Armor template") - project_id: Optional[str] = Field(default=None, description="Google Cloud project ID") - location: Optional[str] = Field(default=None, description="Google Cloud location/region (e.g., us-central1)") - credentials: Optional[str] = Field( + template_id: str | None = Field(default=None, description="The ID of your Model Armor template") + project_id: str | None = Field(default=None, description="Google Cloud project ID") + location: str | None = Field(default=None, description="Google Cloud location/region (e.g., us-central1)") + credentials: str | None = Field( default=None, description="Path to Google Cloud credentials JSON file or JSON string", ) - api_endpoint: Optional[str] = Field(default=None, description="Optional custom API endpoint for Model Armor") - fail_on_error: Optional[bool] = Field( + api_endpoint: str | None = Field(default=None, description="Optional custom API endpoint for Model Armor") + fail_on_error: bool | None = Field( default=True, description="Whether to fail the request if Model Armor encounters an error", ) - sanitize_error_detail: Optional[bool] = Field( + sanitize_error_detail: bool | None = Field( default=True, description=( "Omit the raw Model Armor response from caller-facing errors and logs " diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/noma.py b/litellm/types/proxy/guardrails/guardrail_hooks/noma.py index c6fd587abe6..880a9beb333 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/noma.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/noma.py @@ -1,24 +1,22 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel class NomaGuardrailConfigModel(GuardrailConfigModel): - use_v2: Optional[bool] = Field( + use_v2: bool | None = Field( default=False, description="If True and guardrail='noma', route to the new Noma v2 implementation.", ) - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The Noma API key. Reads from NOMA_API_KEY env var if None.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The Noma API base URL. Defaults to https://api.noma.security. Also checks if the NOMA_API_KEY env var is set.", ) - application_id: Optional[str] = Field( + application_id: str | None = Field( default=None, description="The Noma Application ID. Reads from NOMA_APPLICATION_ID env var if None.", ) @@ -29,23 +27,23 @@ class NomaGuardrailConfigModel(GuardrailConfigModel): class NomaV2GuardrailConfigModel(GuardrailConfigModel): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The Noma API key. Reads from NOMA_API_KEY env var if None.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The Noma API base URL. Defaults to https://api.noma.security.", ) - application_id: Optional[str] = Field( + application_id: str | None = Field( default=None, description="The Noma Application ID. Reads from NOMA_APPLICATION_ID env var if None.", ) - monitor_mode: Optional[bool] = Field( + monitor_mode: bool | None = Field( default=None, description="When true, run guardrail checks in monitor mode.", ) - block_failures: Optional[bool] = Field( + block_failures: bool | None = Field( default=None, description="When true, fail closed on Noma API errors.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/onyx.py b/litellm/types/proxy/guardrails/guardrail_hooks/onyx.py index 42d7e94829f..021be6c8850 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/onyx.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/onyx.py @@ -1,22 +1,20 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel class OnyxGuardrailConfigModel(GuardrailConfigModel): - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The URL of the Onyx Guard server. If not provided, the `ONYX_API_BASE` environment variable is checked.", ) - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The API key for the Onyx Guard server. If not provided, the `ONYX_API_KEY` environment variable is checked.", ) - timeout: Optional[float] = Field( + timeout: float | None = Field( default=None, description="The timeout for the Onyx Guard server in seconds. If not provided, the `ONYX_TIMEOUT` environment variable is checked.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/openai/openai_moderation.py b/litellm/types/proxy/guardrails/guardrail_hooks/openai/openai_moderation.py index 1bc674cb2b5..576da1e76f0 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/openai/openai_moderation.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/openai/openai_moderation.py @@ -1,6 +1,6 @@ -from typing import Literal, Optional +from typing import Literal -from pydantic import BaseModel, Field +from pydantic import Field from ..base import GuardrailConfigModel @@ -8,7 +8,7 @@ from ..base import GuardrailConfigModel class BaseOpenAIModerationGuardrailConfigModel(GuardrailConfigModel): """Base configuration model for the OpenAI Moderation guardrail""" - model: Optional[Literal["omni-moderation-latest", "text-moderation-latest"]] = Field( + model: Literal["omni-moderation-latest", "text-moderation-latest"] | None = Field( default="omni-moderation-latest", description="The OpenAI moderation model to use. 'omni-moderation-latest' supports more categorization options and multi-modal inputs. Defaults to 'omni-moderation-latest'.", ) @@ -17,22 +17,22 @@ class BaseOpenAIModerationGuardrailConfigModel(GuardrailConfigModel): class OpenAIModerationGuardrailConfigModel(BaseOpenAIModerationGuardrailConfigModel): """Configuration model for the OpenAI Moderation guardrail""" - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="OpenAI API key. Can also be set via OPENAI_API_KEY environment variable.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default="https://api.openai.com/v1", description="OpenAI API base URL. Defaults to 'https://api.openai.com/v1'.", ) - streaming_end_of_stream_only: Optional[bool] = Field( + streaming_end_of_stream_only: bool | None = Field( default=False, description="If False (default), moderation runs on sampled chunks during the stream at the cadence set by streaming_sampling_rate, and an in-flight violation stops further chunks from streaming. If True, moderation runs once at end of stream over the assembled response — lower cost and latency, but flagged content has already streamed to the client before the terminal block.", ) - streaming_sampling_rate: Optional[int] = Field( + streaming_sampling_rate: int | None = Field( default=5, description="When streaming_end_of_stream_only is False, moderation runs every Nth streamed chunk. Ignored when streaming_end_of_stream_only is True.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/ovalix.py b/litellm/types/proxy/guardrails/guardrail_hooks/ovalix.py index 7417d1a00c9..0ec353fa945 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/ovalix.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/ovalix.py @@ -1,7 +1,5 @@ """Pydantic config model for the Ovalix guardrail (Tracker API, application and checkpoint IDs).""" -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel @@ -10,23 +8,23 @@ from .base import GuardrailConfigModel class OvalixGuardrailConfigModel(GuardrailConfigModel): """Configuration parameters for the Ovalix guardrail (pre/post call checkpoints).""" - tracker_api_base: Optional[str] = Field( + tracker_api_base: str | None = Field( default=None, description="Base URL for the Ovalix Tracker service.", ) - tracker_api_key: Optional[str] = Field( + tracker_api_key: str | None = Field( default=None, description="API key for the Ovalix Tracker service.", ) - application_id: Optional[str] = Field( + application_id: str | None = Field( default=None, description="Application ID for the Ovalix Tracker service.", ) - pre_checkpoint_id: Optional[str] = Field( + pre_checkpoint_id: str | None = Field( default=None, description="Pre-checkpoint ID for the Ovalix Tracker service.", ) - post_checkpoint_id: Optional[str] = Field( + post_checkpoint_id: str | None = Field( default=None, description="Post-checkpoint ID for the Ovalix Tracker service.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/pangea.py b/litellm/types/proxy/guardrails/guardrail_hooks/pangea.py index 53423103cdd..e9a01810151 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/pangea.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/pangea.py @@ -1,27 +1,25 @@ -from typing import Optional - from pydantic import BaseModel, Field from .base import GuardrailConfigModel class PangeaGuardrailConfigModelOptionalParams(BaseModel): - pangea_input_recipe: Optional[str] = Field( + pangea_input_recipe: str | None = Field( default=None, description="The Pangea input recipe for the Pangea guardrail. Used for pre-call hook.", ) - pangea_output_recipe: Optional[str] = Field( + pangea_output_recipe: str | None = Field( default=None, description="The Pangea output recipe for the Pangea guardrail. Used for post-call hook.", ) class PangeaGuardrailConfigModel(GuardrailConfigModel[PangeaGuardrailConfigModelOptionalParams]): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The Pangea API key. Reads from PANGEA_API_KEY env var if None.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The Pangea API base URL. Defaults to https://ai-guard.aws.us.pangea.cloud. Also checks if the PANGEA_API_BASE env var is set.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/panw_prisma_airs.py b/litellm/types/proxy/guardrails/guardrail_hooks/panw_prisma_airs.py index a67d3f6d7b4..606210d3b8b 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/panw_prisma_airs.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/panw_prisma_airs.py @@ -1,4 +1,4 @@ -from typing import Literal, Optional +from typing import Literal from pydantic import Field @@ -6,21 +6,21 @@ from .base import GuardrailConfigModel class PanwPrismaAirsGuardrailConfigModel(GuardrailConfigModel): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The API key for the PANW Prisma AIRS guardrail. If not provided, the `PANW_PRISMA_AIRS_API_KEY` environment variable is checked.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The API base for the PANW Prisma AIRS guardrail. Defaults to https://service.api.aisecurity.paloaltonetworks.com. If not provided, the `PANW_PRISMA_AIRS_API_BASE` environment variable is checked.", ) - profile_name: Optional[str] = Field( + profile_name: str | None = Field( default=None, description="PANW Prisma AIRS security profile name configured in Strata Cloud Manager. Optional if API key has a linked profile.", ) - app_name: Optional[str] = Field( + app_name: str | None = Field( default=None, description="Application name for tracking this LiteLLM instance in Prisma AIRS analytics and dashboards. Defaults to 'LiteLLM' if not specified.", ) @@ -52,7 +52,7 @@ class PanwPrismaAirsGuardrailConfigModel(GuardrailConfigModel): description="PANW API call timeout in seconds (1-60).", ) - experimental_use_latest_role_message_only: Optional[bool] = Field( + experimental_use_latest_role_message_only: bool | None = Field( default=None, description="Anthropic /v1/messages only. When unset: scans only latest user/developer " "message on request side. Set false to scan all user/system/developer messages. " diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/pillar.py b/litellm/types/proxy/guardrails/guardrail_hooks/pillar.py index e4a9cce33be..248f3f6d2d6 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/pillar.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/pillar.py @@ -2,8 +2,6 @@ Pillar Security Guardrail Config Model """ -from typing import Optional - from pydantic import BaseModel, Field from .base import GuardrailConfigModel @@ -12,31 +10,31 @@ from .base import GuardrailConfigModel class PillarGuardrailConfigModelOptionalParams(BaseModel): """Optional parameters for the Pillar Security guardrail""" - on_flagged_action: Optional[str] = Field( + on_flagged_action: str | None = Field( default="monitor", description="Action to take when content is flagged: 'block' (raise exception) or 'monitor' (log only). If not provided, the `PILLAR_ON_FLAGGED_ACTION` environment variable is checked, defaults to 'monitor'.", ) - async_mode: Optional[bool] = Field( + async_mode: bool | None = Field( default=None, description="Set to True to request asynchronous analysis (sets `plr_async` header).", ) - persist_session: Optional[bool] = Field( + persist_session: bool | None = Field( default=None, description="Set to False to disable session persistence (sets `plr_persist` header).", ) - include_scanners: Optional[bool] = Field( + include_scanners: bool | None = Field( default=True, description="Include scanner summaries in response payloads (sets `plr_scanners` header).", ) - include_evidence: Optional[bool] = Field( + include_evidence: bool | None = Field( default=True, description="Include detailed evidence objects in response payloads (sets `plr_evidence` header).", ) - fallback_on_error: Optional[str] = Field( + fallback_on_error: str | None = Field( default=None, description="Action to take when Pillar API is unavailable or errors: 'allow' (proceed without scanning) or 'block' (reject request with 503 error). If not provided, the `PILLAR_FALLBACK_ON_ERROR` environment variable is checked, defaults to 'allow'.", ) - timeout: Optional[float] = Field( + timeout: float | None = Field( default=None, description="Timeout in seconds for Pillar API calls. If not provided, the `PILLAR_TIMEOUT` environment variable is checked, defaults to 5.0 seconds.", ) @@ -45,11 +43,11 @@ class PillarGuardrailConfigModelOptionalParams(BaseModel): class PillarGuardrailConfigModel(GuardrailConfigModel[PillarGuardrailConfigModelOptionalParams]): """Configuration parameters for the Pillar Security guardrail""" - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="API key for the Pillar Security service. If not provided, the `PILLAR_API_KEY` environment variable is checked.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="Base URL for the Pillar Security API. If not provided, the `PILLAR_API_BASE` environment variable is checked, defaults to https://api.pillar.security", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/presidio.py b/litellm/types/proxy/guardrails/guardrail_hooks/presidio.py index 89e0f39c438..9d1e375af72 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/presidio.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/presidio.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Union +from typing import Any from typing_extensions import TypedDict @@ -7,15 +7,15 @@ from litellm.types.guardrails import PiiEntityType class PresidioAnalyzeRequest(TypedDict, total=False): text: str - language: Optional[str] - ad_hoc_recognizers: Optional[List[str]] - entities: Optional[List[Union[PiiEntityType, str]]] + language: str | None + ad_hoc_recognizers: list[str] | None + entities: list[PiiEntityType | str] | None class PresidioAnalyzeResponseItem(TypedDict, total=False): - entity_type: Optional[Union[PiiEntityType, str]] - start: Optional[int] - end: Optional[int] - score: Optional[float] - analysis_explanation: Optional[Dict[str, Any]] - recognition_metadata: Optional[Dict[str, Any]] + entity_type: PiiEntityType | str | None + start: int | None + end: int | None + score: float | None + analysis_explanation: dict[str, Any] | None + recognition_metadata: dict[str, Any] | None diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/prompt_security.py b/litellm/types/proxy/guardrails/guardrail_hooks/prompt_security.py index b87c54ede9a..6e64f0f47a5 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/prompt_security.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/prompt_security.py @@ -1,16 +1,14 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel class PromptSecurityGuardrailConfigModel(GuardrailConfigModel): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The API key for the Prompt Security guardrail. If not provided, the `PROMPT_SECURITY_API_KEY` environment variable is used.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The API base for the Prompt Security guardrail. If not provided, the `PROMPT_SECURITY_API_BASE` environment variable is used.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/promptguard.py b/litellm/types/proxy/guardrails/guardrail_hooks/promptguard.py index 4532577034b..796e5a0d04f 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/promptguard.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/promptguard.py @@ -1,12 +1,10 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel class PromptGuardConfigModel(GuardrailConfigModel): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description=( "API key for PromptGuard authentication. " @@ -14,7 +12,7 @@ class PromptGuardConfigModel(GuardrailConfigModel): "environment variable is used." ), ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description=( "PromptGuard API base URL. " @@ -22,7 +20,7 @@ class PromptGuardConfigModel(GuardrailConfigModel): "Falls back to PROMPTGUARD_API_BASE env var." ), ) - block_on_error: Optional[bool] = Field( + block_on_error: bool | None = Field( default=None, description=( "Whether to block the request when the " diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/qohash.py b/litellm/types/proxy/guardrails/guardrail_hooks/qohash.py index 5abfa69148e..3ed5674438c 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/qohash.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/qohash.py @@ -1,12 +1,10 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel class QostodianNexusConfigModel(GuardrailConfigModel): - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The API base URL for Qostodian Nexus. If not provided, the `QOSTODIAN_NEXUS_API_BASE` environment variable is checked. Defaults to http://nexus:8800.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/qualifire.py b/litellm/types/proxy/guardrails/guardrail_hooks/qualifire.py index 49d3b813afd..39c449d6249 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/qualifire.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/qualifire.py @@ -1,4 +1,4 @@ -from typing import List, Literal, Optional +from typing import Literal from pydantic import Field @@ -8,47 +8,47 @@ from .base import GuardrailConfigModel class QualifireGuardrailConfigModel(GuardrailConfigModel): """Configuration parameters for the Qualifire guardrail.""" - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="The API key for Qualifire. If not provided, the `QUALIFIRE_API_KEY` environment variable is checked.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="The API base URL for Qualifire. If not provided, the `QUALIFIRE_BASE_URL` environment variable is checked.", ) - evaluation_id: Optional[str] = Field( + evaluation_id: str | None = Field( default=None, description="Pre-configured evaluation ID from Qualifire dashboard. When provided, uses invoke_evaluation() instead of evaluate().", ) - prompt_injections: Optional[bool] = Field( + prompt_injections: bool | None = Field( default=None, description="Enable prompt injection detection. Default check if no evaluation_id and no other checks are specified.", ) - hallucinations_check: Optional[bool] = Field( + hallucinations_check: bool | None = Field( default=None, description="Enable hallucination detection to detect factual inaccuracies.", ) - grounding_check: Optional[bool] = Field( + grounding_check: bool | None = Field( default=None, description="Enable grounding verification to ensure output is grounded in provided context.", ) - pii_check: Optional[bool] = Field( + pii_check: bool | None = Field( default=None, description="Enable PII (Personally Identifiable Information) detection.", ) - content_moderation_check: Optional[bool] = Field( + content_moderation_check: bool | None = Field( default=None, description="Enable content moderation to check for harmful content (harassment, hate speech, etc.).", ) - tool_selection_quality_check: Optional[bool] = Field( + tool_selection_quality_check: bool | None = Field( default=None, description="Enable tool selection quality check to evaluate quality of tool/function calls.", ) - assertions: Optional[List[str]] = Field( + assertions: list[str] | None = Field( default=None, description="Custom assertions to validate against the output. Each assertion is a string describing a condition.", ) - on_flagged: Optional[Literal["block", "monitor"]] = Field( + on_flagged: Literal["block", "monitor"] | None = Field( default="block", description="Action to take when content is flagged. 'block' raises an exception, 'monitor' logs but allows the request.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/repelloai.py b/litellm/types/proxy/guardrails/guardrail_hooks/repelloai.py index 93b3829d7e8..5b77b0798ec 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/repelloai.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/repelloai.py @@ -1,4 +1,4 @@ -from typing import List, Literal, Optional +from typing import Literal from pydantic import BaseModel, Field from typing_extensions import TypedDict @@ -9,15 +9,15 @@ from .base import GuardrailConfigModel class RepelloAIGuardrailConfigModel(GuardrailConfigModel[BaseModel]): """Config model for the RepelloAI Argus guardrail.""" - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description="API key for the RepelloAI Argus service. Falls back to ARGUS_API_KEY or REPELLOAI_API_KEY.", ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description="Base URL for the RepelloAI Argus API. Defaults to https://argusapi.repello.ai/sdk/v1", ) - asset_id: Optional[str] = Field( + asset_id: str | None = Field( default=None, description="Repello asset ID whose dashboard policies are enforced. Required; the guardrail raises at init if it is missing.", ) @@ -36,8 +36,8 @@ class RepelloAIScanData(TypedDict, total=False): Only one of 'prompt' or 'response' is set per request. """ - prompt: Optional[str] - response: Optional[str] + prompt: str | None + response: str | None class RepelloAIAnalyzeRequest(TypedDict, total=False): @@ -48,18 +48,18 @@ class RepelloAIAnalyzeRequest(TypedDict, total=False): class RepelloAIViolatedPolicy(TypedDict, total=False): - policy_name: Optional[str] - policy_id: Optional[str] - action_taken: Optional[str] - scope: Optional[str] - details: Optional[dict[str, object]] - masked_result: Optional[str] + policy_name: str | None + policy_id: str | None + action_taken: str | None + scope: str | None + details: dict[str, object] | None + masked_result: str | None class RepelloAIAnalyzeResponse(TypedDict, total=False): """Response body returned by the RepelloAI Argus analyze endpoints.""" - verdict: Optional[str] # "blocked" | "flagged" | "passed" - request_id: Optional[str] - policies_violated: Optional[List[RepelloAIViolatedPolicy]] - policies_applied: Optional[List[dict[str, object]]] + verdict: str | None # "blocked" | "flagged" | "passed" + request_id: str | None + policies_violated: list[RepelloAIViolatedPolicy] | None + policies_applied: list[dict[str, object]] | None diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/singulr.py b/litellm/types/proxy/guardrails/guardrail_hooks/singulr.py index 62d3b8653ef..d0d19d191c1 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/singulr.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/singulr.py @@ -1,4 +1,4 @@ -from typing import Any, Optional +from typing import Any from pydantic import BaseModel, Field @@ -6,50 +6,50 @@ from .base import GuardrailConfigModel class SingulrGuardrailRequest(BaseModel): - model: Optional[str] = None - messages: Optional[list[dict[str, Any]]] = None - tools: Optional[list[dict[str, Any]]] = None - model_response: Optional[dict[str, Any]] = None - litellm_metadata: Optional[dict[str, Any]] = None + model: str | None = None + messages: list[dict[str, Any]] | None = None + tools: list[dict[str, Any]] | None = None + model_response: dict[str, Any] | None = None + litellm_metadata: dict[str, Any] | None = None class SingulrGuardrailPayload(BaseModel): - litellm_call_id: Optional[str] = None - request_data: Optional[SingulrGuardrailRequest] = None + litellm_call_id: str | None = None + request_data: SingulrGuardrailRequest | None = None input_type: str - is_playground_request: Optional[bool] = None - playground_text: Optional[str] = None + is_playground_request: bool | None = None + playground_text: str | None = None class SingulrGuardrailResponse(BaseModel): """Response returned by the Singulr guardrail API.""" should_block: bool = False - blocking_due_to: Optional[str] = None + blocking_due_to: str | None = None class SingulrGuardrailConfigModel(GuardrailConfigModel): - singulr_api_key: Optional[str] = Field( + singulr_api_key: str | None = Field( default=None, description="The Singulr API key. Generate API key from Singulr Platform.", ) - singulr_api_base: Optional[str] = Field( + singulr_api_base: str | None = Field( default=None, description="The Singulr API base URL. Get base URL from Singulr Platform.", ) - singulr_application_id: Optional[str] = Field( + singulr_application_id: str | None = Field( default=None, description="The Singulr application ID. Get application ID from Singulr Platform.", ) - singulr_guardrail_id: Optional[str] = Field( + singulr_guardrail_id: str | None = Field( default=None, description="The Singulr Guardrail ID. Get guardrail ID from Singulr Platform.", ) - block_on_error: Optional[bool] = Field( + block_on_error: bool | None = Field( default=None, description=( "Whether to block requests when the Singulr Guardrails API is unavailable " diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/tool_permission.py b/litellm/types/proxy/guardrails/guardrail_hooks/tool_permission.py index 7461823b0fc..a31d198d605 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/tool_permission.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/tool_permission.py @@ -1,5 +1,5 @@ # Tool Permission Guardrail Type Definitions -from typing import Dict, Final, List, Literal, Optional +from typing import Final, Literal from pydantic import BaseModel, Field, field_validator, model_validator @@ -12,23 +12,23 @@ class ToolPermissionRule(BaseModel): """ id: str = Field(description="Unique identifier for the rule") - tool_name: Optional[str] = Field( + tool_name: str | None = Field( default=None, description="Regex pattern applied to the tool's function name", ) - tool_type: Optional[str] = Field( + tool_type: str | None = Field( default=None, description="Regex pattern applied to the tool type (e.g., function)", ) decision: Literal["allow", "deny"] = Field(description="Whether to allow or deny this tool usage") - allowed_param_patterns: Optional[Dict[str, str]] = Field( + allowed_param_patterns: dict[str, str] | None = Field( default=None, description="Optional regex map enforcing nested parameter values using dot/[] paths", ) @field_validator("tool_name", "tool_type", mode="before") @classmethod - def _blank_to_none(cls, value: Optional[str]) -> Optional[str]: + def _blank_to_none(cls, value: str | None) -> str | None: if value is None: return None if isinstance(value, str): @@ -70,14 +70,14 @@ class PermissionError(BaseModel): """ tool_name: str = Field(description="Name of the denied tool") - rule_id: Optional[str] = Field(description="ID of the rule that caused denial") + rule_id: str | None = Field(description="ID of the rule that caused denial") message: str = Field(description="Error message") class ToolPermissionGuardrailConfigModel(GuardrailConfigModel): """Configuration parameters exposed to the UI for the Tool Permission guardrail.""" - rules: Optional[List[ToolPermissionRule]] = Field( + rules: list[ToolPermissionRule] | None = Field( default=None, description="Ordered allow/deny rules. Patterns use regex for tool names/types and optional regex constraints on tool arguments.", ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/vigil_guard.py b/litellm/types/proxy/guardrails/guardrail_hooks/vigil_guard.py index bc580619ee0..b04ce9852f0 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/vigil_guard.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/vigil_guard.py @@ -1,16 +1,14 @@ -from typing import Optional - from pydantic import Field from .base import GuardrailConfigModel class VigilGuardGuardrailConfigModel(GuardrailConfigModel): - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description=("Vigil Guard API base URL. Falls back to the VIGIL_GUARD_URL environment variable."), ) - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description=("Vigil Guard API key. Falls back to the VIGIL_GUARD_API_KEY environment variable."), ) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/xecguard.py b/litellm/types/proxy/guardrails/guardrail_hooks/xecguard.py index d0817157bc2..be97e49b837 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/xecguard.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/xecguard.py @@ -1,4 +1,4 @@ -from typing import Any, cast, Final, List, Literal, Optional +from typing import Any, Final, Literal, cast from pydantic import Field @@ -15,7 +15,7 @@ XECGUARD_DEFAULT_POLICY_OPTIONS: Final = [ class XecGuardConfigModel(GuardrailConfigModel): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description=( "Service Token for XecGuard (prefix 'xgs_'). " @@ -23,7 +23,7 @@ class XecGuardConfigModel(GuardrailConfigModel): "variable is used." ), ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description=( "XecGuard API base URL. " @@ -31,11 +31,11 @@ class XecGuardConfigModel(GuardrailConfigModel): "Falls back to the XECGUARD_API_BASE env var." ), ) - xecguard_model: Optional[str] = Field( + xecguard_model: str | None = Field( default=None, description=("XecGuard scanning model identifier. Defaults to 'xecguard_v2'."), ) - policy_names: Optional[List[str]] = Field( + policy_names: list[str] | None = Field( default=None, description=( "XecGuard policies to apply on each scan. Select one or more " @@ -51,7 +51,7 @@ class XecGuardConfigModel(GuardrailConfigModel): }, ), ) - block_on_error: Optional[bool] = Field( + block_on_error: bool | None = Field( default=None, description=( "Whether to block requests when the XecGuard API is " @@ -59,7 +59,7 @@ class XecGuardConfigModel(GuardrailConfigModel): "Falls back to the XECGUARD_BLOCK_ON_ERROR env var." ), ) - grounding_strictness: Optional[Literal["BALANCED", "STRICT"]] = Field( + grounding_strictness: Literal["BALANCED", "STRICT"] | None = Field( default=None, description=( "Strictness level for XecGuard context-grounding " diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/zscaler_ai_guard.py b/litellm/types/proxy/guardrails/guardrail_hooks/zscaler_ai_guard.py index 8b903565d5f..3991cee8548 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/zscaler_ai_guard.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/zscaler_ai_guard.py @@ -1,4 +1,4 @@ -from typing import Final, Optional +from typing import Final from pydantic import Field, model_validator @@ -9,7 +9,7 @@ from .base import GuardrailConfigModel class ZscalerAIGuardConfigModel(GuardrailConfigModel): - api_key: Optional[str] = Field( + api_key: str | None = Field( default=None, description=( "API key for Zscaler AI Guard authentication. " @@ -17,7 +17,7 @@ class ZscalerAIGuardConfigModel(GuardrailConfigModel): ), ) - api_base: Optional[str] = Field( + api_base: str | None = Field( default=None, description=( "Zscaler AI Guard API endpoint. Determines policy resolution behavior:\n" @@ -34,7 +34,7 @@ class ZscalerAIGuardConfigModel(GuardrailConfigModel): }, ) - policy_id: Optional[int] = Field( + policy_id: int | None = Field( default=None, description=( "Global policy ID for Zscaler AI Guard. Required when using /execute-policy endpoint.\n\n" @@ -47,7 +47,7 @@ class ZscalerAIGuardConfigModel(GuardrailConfigModel): }, ) - send_user_api_key_alias: Optional[bool] = Field( + send_user_api_key_alias: bool | None = Field( default=False, description=( "Send user API key alias in request headers as 'user-api-key-alias'. " @@ -61,7 +61,7 @@ class ZscalerAIGuardConfigModel(GuardrailConfigModel): }, ) - send_user_api_key_user_id: Optional[bool] = Field( + send_user_api_key_user_id: bool | None = Field( default=False, description=( "Send user API key user_id in request headers as 'user-api-key-user-id'. " @@ -70,7 +70,7 @@ class ZscalerAIGuardConfigModel(GuardrailConfigModel): json_schema_extra={"ui_type": GuardrailParamUITypes.BOOL}, ) - send_user_api_key_team_id: Optional[bool] = Field( + send_user_api_key_team_id: bool | None = Field( default=False, description=( "Send user API key team_id in request headers as 'user-api-key-team-id'. " diff --git a/litellm/types/proxy/management_endpoints/common_daily_activity.py b/litellm/types/proxy/management_endpoints/common_daily_activity.py index 21b7ffca3f2..fc1e6d15fd4 100644 --- a/litellm/types/proxy/management_endpoints/common_daily_activity.py +++ b/litellm/types/proxy/management_endpoints/common_daily_activity.py @@ -1,6 +1,6 @@ from datetime import date from enum import Enum -from typing import Any, Dict, List, Optional +from typing import Any from pydantic import BaseModel, Field from typing_extensions import TypedDict @@ -39,8 +39,8 @@ class MetricBase(BaseModel): class KeyMetadata(BaseModel): """Metadata for a key""" - key_alias: Optional[str] = None - team_id: Optional[str] = None + key_alias: str | None = None + team_id: str | None = None class KeyMetricWithMetadata(MetricBase): @@ -50,21 +50,21 @@ class KeyMetricWithMetadata(MetricBase): class MetricWithMetadata(MetricBase): - metadata: Dict[str, Any] = Field(default_factory=dict) + metadata: dict[str, Any] = Field(default_factory=dict) # API key breakdown for this metric (e.g., which API keys are using this MCP server) - api_key_breakdown: Dict[str, KeyMetricWithMetadata] = Field(default_factory=dict) # api_key -> {metrics, metadata} + api_key_breakdown: dict[str, KeyMetricWithMetadata] = Field(default_factory=dict) # api_key -> {metrics, metadata} class BreakdownMetrics(BaseModel): """Breakdown of spend by different dimensions""" - mcp_servers: Dict[str, MetricWithMetadata] = Field(default_factory=dict) # mcp_server -> {metrics, metadata} - models: Dict[str, MetricWithMetadata] = Field(default_factory=dict) # model -> {metrics, metadata} - model_groups: Dict[str, MetricWithMetadata] = Field(default_factory=dict) # model_group -> {metrics, metadata} - providers: Dict[str, MetricWithMetadata] = Field(default_factory=dict) # provider -> {metrics, metadata} - endpoints: Dict[str, MetricWithMetadata] = Field(default_factory=dict) # endpoint -> {metrics, metadata} - api_keys: Dict[str, KeyMetricWithMetadata] = Field(default_factory=dict) # api_key -> {metrics, metadata} - entities: Dict[str, MetricWithMetadata] = Field(default_factory=dict) # entity -> {metrics, metadata} + mcp_servers: dict[str, MetricWithMetadata] = Field(default_factory=dict) # mcp_server -> {metrics, metadata} + models: dict[str, MetricWithMetadata] = Field(default_factory=dict) # model -> {metrics, metadata} + model_groups: dict[str, MetricWithMetadata] = Field(default_factory=dict) # model_group -> {metrics, metadata} + providers: dict[str, MetricWithMetadata] = Field(default_factory=dict) # provider -> {metrics, metadata} + endpoints: dict[str, MetricWithMetadata] = Field(default_factory=dict) # endpoint -> {metrics, metadata} + api_keys: dict[str, KeyMetricWithMetadata] = Field(default_factory=dict) # api_key -> {metrics, metadata} + entities: dict[str, MetricWithMetadata] = Field(default_factory=dict) # entity -> {metrics, metadata} class DailySpendData(BaseModel): @@ -93,7 +93,7 @@ class DailySpendMetadata(BaseModel): class SpendAnalyticsPaginatedResponse(BaseModel): - results: List[DailySpendData] + results: list[DailySpendData] metadata: DailySpendMetadata = Field(default_factory=DailySpendMetadata) @@ -102,10 +102,10 @@ class LiteLLM_DailyUserSpend(BaseModel): user_id: str date: str api_key: str - mcp_server_id: Optional[str] = None - model: Optional[str] = None - model_group: Optional[str] = None - custom_llm_provider: Optional[str] = None + mcp_server_id: str | None = None + model: str | None = None + model_group: str | None = None + custom_llm_provider: str | None = None prompt_tokens: int = 0 completion_tokens: int = 0 cache_read_input_tokens: int = 0 diff --git a/litellm/types/proxy/management_endpoints/config_overrides.py b/litellm/types/proxy/management_endpoints/config_overrides.py index 5c2ef519c78..9e1ea23ac46 100644 --- a/litellm/types/proxy/management_endpoints/config_overrides.py +++ b/litellm/types/proxy/management_endpoints/config_overrides.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional +from typing import Any from pydantic import BaseModel, Field @@ -6,47 +6,47 @@ from pydantic import BaseModel, Field class HashicorpVaultConfig(BaseModel): """Configuration for Hashicorp Vault secret manager integration.""" - vault_addr: Optional[str] = Field( + vault_addr: str | None = Field( default=None, description="The address of the Vault server (e.g., https://vault.example.com:8200)", ) - vault_token: Optional[str] = Field( + vault_token: str | None = Field( default=None, description="Token for Vault token-based authentication", ) - approle_role_id: Optional[str] = Field( + approle_role_id: str | None = Field( default=None, description="Role ID for Vault AppRole authentication", ) - approle_secret_id: Optional[str] = Field( + approle_secret_id: str | None = Field( default=None, description="Secret ID for Vault AppRole authentication", ) - approle_mount_path: Optional[str] = Field( + approle_mount_path: str | None = Field( default=None, description="Mount path for the AppRole auth method (default: approle)", ) - client_cert: Optional[str] = Field( + client_cert: str | None = Field( default=None, description="Path to the client TLS certificate for Vault", ) - client_key: Optional[str] = Field( + client_key: str | None = Field( default=None, description="Path to the client TLS private key for Vault", ) - vault_cert_role: Optional[str] = Field( + vault_cert_role: str | None = Field( default=None, description="Certificate role name for TLS cert authentication", ) - vault_namespace: Optional[str] = Field( + vault_namespace: str | None = Field( default=None, description="Vault namespace (for multi-tenant Vault, sent as X-Vault-Namespace header)", ) - vault_mount_name: Optional[str] = Field( + vault_mount_name: str | None = Field( default=None, description="KV engine mount name (default: secret)", ) - vault_path_prefix: Optional[str] = Field( + vault_path_prefix: str | None = Field( default=None, description="Optional path prefix for secrets (e.g., myapp -> secret/data/myapp/{secret_name})", ) @@ -56,5 +56,5 @@ class ConfigOverrideSettingsResponse(BaseModel): """Response model for config override settings GET endpoints.""" config_type: str = Field(description="The type of config override") - values: Dict[str, Any] = Field(description="Current configuration values (sensitive fields decrypted)") - field_schema: Dict[str, Any] = Field(description="Schema information for UI rendering") + values: dict[str, Any] = Field(description="Current configuration values (sensitive fields decrypted)") + field_schema: dict[str, Any] = Field(description="Schema information for UI rendering") diff --git a/litellm/types/proxy/management_endpoints/customer_endpoints.py b/litellm/types/proxy/management_endpoints/customer_endpoints.py index e7653360d63..73fbf711556 100644 --- a/litellm/types/proxy/management_endpoints/customer_endpoints.py +++ b/litellm/types/proxy/management_endpoints/customer_endpoints.py @@ -1,5 +1,3 @@ -from typing import List, Optional - from pydantic import BaseModel, Field from litellm.models.budget import LiteLLM_BudgetTableFull @@ -14,15 +12,15 @@ class CustomerResponse(LiteLLM_EndUserTable): the narrow write-allowlist shape LiteLLM_EndUserTable carries for internal use. """ - litellm_budget_table: Optional[LiteLLM_BudgetTableFull] = None # pyright: ignore + litellm_budget_table: LiteLLM_BudgetTableFull | None = None # pyright: ignore class BlockUsersResponse(BaseModel): - blocked_users: List[LiteLLM_EndUserTable] + blocked_users: list[LiteLLM_EndUserTable] class UnblockUsersResponse(BaseModel): - blocked_users: List[str] = Field(description="User IDs that remain blocked after this unblock call") + blocked_users: list[str] = Field(description="User IDs that remain blocked after this unblock call") class DeleteCustomersResponse(BaseModel): diff --git a/litellm/types/proxy/management_endpoints/internal_user_endpoints.py b/litellm/types/proxy/management_endpoints/internal_user_endpoints.py index faf2660a6f8..df0a090cdb0 100644 --- a/litellm/types/proxy/management_endpoints/internal_user_endpoints.py +++ b/litellm/types/proxy/management_endpoints/internal_user_endpoints.py @@ -1,7 +1,6 @@ -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Final -from fastapi import HTTPException -from pydantic import BaseModel, EmailStr, field_validator +from pydantic import BaseModel, field_validator from litellm.proxy._types import ( LiteLLM_UserTableWithKeyCount, @@ -15,7 +14,7 @@ class UserListResponse(BaseModel): Response model for the user list endpoint """ - users: List[LiteLLM_UserTableWithKeyCount] + users: list[LiteLLM_UserTableWithKeyCount] total: int page: int page_size: int @@ -25,9 +24,9 @@ class UserListResponse(BaseModel): class BulkUpdateUserRequest(BaseModel): """Request for bulk user updates""" - users: Optional[List[UpdateUserRequest]] = None # List of specific user update requests - all_users: Optional[bool] = False # Flag to update all users - user_updates: Optional[UpdateUserRequestNoUserIDorEmail] = None # Updates to apply to all users when all_users=True + users: list[UpdateUserRequest] | None = None # List of specific user update requests + all_users: bool | None = False # Flag to update all users + user_updates: UpdateUserRequestNoUserIDorEmail | None = None # Updates to apply to all users when all_users=True @field_validator("users", "all_users", "user_updates") @classmethod @@ -57,17 +56,17 @@ class BulkUpdateUserRequest(BaseModel): class UserUpdateResult(BaseModel): """Result of a single user update operation""" - user_id: Optional[str] = None - user_email: Optional[str] = None + user_id: str | None = None + user_email: str | None = None success: bool - error: Optional[str] = None - updated_user: Optional[Dict[str, Any]] = None + error: str | None = None + updated_user: dict[str, Any] | None = None class BulkUpdateUserResponse(BaseModel): """Response for bulk user update operations""" - results: List[UserUpdateResult] + results: list[UserUpdateResult] total_requested: int successful_updates: int failed_updates: int diff --git a/litellm/types/proxy/management_endpoints/key_management_endpoints.py b/litellm/types/proxy/management_endpoints/key_management_endpoints.py index ea3f4d7dd8e..0f17f2f23ab 100644 --- a/litellm/types/proxy/management_endpoints/key_management_endpoints.py +++ b/litellm/types/proxy/management_endpoints/key_management_endpoints.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Dict, Final, List, Literal, Optional +from typing import Any, Final, Literal from pydantic import BaseModel, ConfigDict, model_validator @@ -8,30 +8,30 @@ class BulkUpdateKeyRequestItem(BaseModel): """Individual key update request item""" key: str # Key identifier (token) - budget_id: Optional[str] = None # Budget ID associated with the key - max_budget: Optional[float] = None # Max budget for key - team_id: Optional[str] = None # Team ID associated with key - tags: Optional[List[str]] = None # Tags for organizing keys + budget_id: str | None = None # Budget ID associated with the key + max_budget: float | None = None # Max budget for key + team_id: str | None = None # Team ID associated with key + tags: list[str] | None = None # Tags for organizing keys class BulkUpdateKeyRequest(BaseModel): """Request for bulk key updates""" - keys: List[BulkUpdateKeyRequestItem] + keys: list[BulkUpdateKeyRequestItem] class SuccessfulKeyUpdate(BaseModel): """Successfully updated key with its updated information""" key: str - key_info: Dict[str, Any] + key_info: dict[str, Any] class FailedKeyUpdate(BaseModel): """Failed key update with reason""" key: str - key_info: Optional[Dict[str, Any]] = None + key_info: dict[str, Any] | None = None failed_reason: str @@ -39,8 +39,8 @@ class BulkUpdateKeyResponse(BaseModel): """Response for bulk key update operations""" total_requested: int - successful_updates: List[SuccessfulKeyUpdate] - failed_updates: List[FailedKeyUpdate] + successful_updates: list[SuccessfulKeyUpdate] + failed_updates: list[FailedKeyUpdate] class KeyUpdateFields(BaseModel): @@ -49,31 +49,31 @@ class KeyUpdateFields(BaseModel): model_config = ConfigDict(extra="forbid", protected_namespaces=()) # Budgets - max_budget: Optional[float] = None - budget_id: Optional[str] = None - budget_duration: Optional[str] = None - budget_limits: Optional[List[Any]] = None - model_max_budget: Optional[Dict[str, Any]] = None + max_budget: float | None = None + budget_id: str | None = None + budget_duration: str | None = None + budget_limits: list[Any] | None = None + model_max_budget: dict[str, Any] | None = None # Rate limits - tpm_limit: Optional[int] = None - rpm_limit: Optional[int] = None - model_tpm_limit: Optional[Dict[str, Any]] = None - model_rpm_limit: Optional[Dict[str, Any]] = None - max_parallel_requests: Optional[int] = None - rpm_limit_type: Optional[Literal["guaranteed_throughput", "best_effort_throughput", "dynamic"]] = None - tpm_limit_type: Optional[Literal["guaranteed_throughput", "best_effort_throughput", "dynamic"]] = None + tpm_limit: int | None = None + rpm_limit: int | None = None + model_tpm_limit: dict[str, Any] | None = None + model_rpm_limit: dict[str, Any] | None = None + max_parallel_requests: int | None = None + rpm_limit_type: Literal["guaranteed_throughput", "best_effort_throughput", "dynamic"] | None = None + tpm_limit_type: Literal["guaranteed_throughput", "best_effort_throughput", "dynamic"] | None = None # Temporary budget grants (auto-expire). `spend` deliberately omitted — bulk-zeroing it bypasses budget enforcement; admin-only via /key/update. - temp_budget_increase: Optional[float] = None - temp_budget_expiry: Optional[datetime] = None + temp_budget_increase: float | None = None + temp_budget_expiry: datetime | None = None # Expiry - duration: Optional[str] = None + duration: str | None = None # Operational metadata - tags: Optional[List[str]] = None - metadata: Optional[Dict[str, Any]] = None + tags: list[str] | None = None + metadata: dict[str, Any] | None = None @model_validator(mode="after") def validate_temp_budget(self) -> "KeyUpdateFields": @@ -94,7 +94,7 @@ class BulkUpdateTeamKeysRequest(BaseModel): """Apply one update payload to many keys inside a team; provide either `key_ids` or `all_keys_in_team=True`.""" team_id: str - key_ids: Optional[List[str]] = None + key_ids: list[str] | None = None all_keys_in_team: bool = False update_fields: KeyUpdateFields diff --git a/litellm/types/proxy/management_endpoints/management_v1.py b/litellm/types/proxy/management_endpoints/management_v1.py index 0769fde9969..b2244f6eb9b 100644 --- a/litellm/types/proxy/management_endpoints/management_v1.py +++ b/litellm/types/proxy/management_endpoints/management_v1.py @@ -1,6 +1,6 @@ """Shared response shapes for the `/management/v1` control-plane surface.""" -from typing import Final, Generic, TypeVar +from typing import Generic, TypeVar from pydantic import BaseModel, ConfigDict, Field diff --git a/litellm/types/proxy/management_endpoints/model_management_endpoints.py b/litellm/types/proxy/management_endpoints/model_management_endpoints.py index db0c75e26ab..1366c62c75f 100644 --- a/litellm/types/proxy/management_endpoints/model_management_endpoints.py +++ b/litellm/types/proxy/management_endpoints/model_management_endpoints.py @@ -1,4 +1,4 @@ -from typing import Dict, List, Union, Any, Optional +from typing import Any from pydantic import BaseModel, Field @@ -7,36 +7,34 @@ from ...router import ModelGroupInfo class ModelGroupInfoProxy(ModelGroupInfo): is_public_model_group: bool = Field(default=False) - health_status: Optional[str] = Field(default=None) - health_response_time: Optional[float] = Field(default=None) - health_checked_at: Optional[str] = Field(default=None) + health_status: str | None = Field(default=None) + health_response_time: float | None = Field(default=None) + health_checked_at: str | None = Field(default=None) class UpdateUsefulLinksRequest(BaseModel): # Supports both old format (Dict[str, str]) and new format (Dict[str, Dict[str, Any]]) # New format: { "displayName": { "url": "...", "index": 0 } } # Old format: { "displayName": "url" } (for backward compatibility) - useful_links: Dict[str, Union[str, Dict[str, Any]]] + useful_links: dict[str, str | dict[str, Any]] class NewModelGroupRequest(BaseModel): access_group: str # The access group name (e.g., "production-models") - model_names: Optional[List[str]] = None # Existing model groups to include - tags ALL deployments for each name - model_ids: Optional[List[str]] = None # Specific deployment IDs to tag (more precise than model_names) + model_names: list[str] | None = None # Existing model groups to include - tags ALL deployments for each name + model_ids: list[str] | None = None # Specific deployment IDs to tag (more precise than model_names) class NewModelGroupResponse(BaseModel): access_group: str - model_names: Optional[List[str]] = None - model_ids: Optional[List[str]] = None + model_names: list[str] | None = None + model_ids: list[str] | None = None models_updated: int # Number of models updated class UpdateModelGroupRequest(BaseModel): - model_names: Optional[List[str]] = ( - None # Updated list of model groups to include - tags ALL deployments for each name - ) - model_ids: Optional[List[str]] = None # Specific deployment IDs to tag (more precise than model_names) + model_names: list[str] | None = None # Updated list of model groups to include - tags ALL deployments for each name + model_ids: list[str] | None = None # Specific deployment IDs to tag (more precise than model_names) class DeleteModelGroupResponse(BaseModel): @@ -47,9 +45,9 @@ class DeleteModelGroupResponse(BaseModel): class AccessGroupInfo(BaseModel): access_group: str - model_names: List[str] # List of model names in this access group + model_names: list[str] # List of model names in this access group deployment_count: int # Total number of deployments with this access group class ListAccessGroupsResponse(BaseModel): - access_groups: List[AccessGroupInfo] + access_groups: list[AccessGroupInfo] diff --git a/litellm/types/proxy/management_endpoints/scim_v2.py b/litellm/types/proxy/management_endpoints/scim_v2.py index d33e92eb291..1612ea03817 100644 --- a/litellm/types/proxy/management_endpoints/scim_v2.py +++ b/litellm/types/proxy/management_endpoints/scim_v2.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Final, Literal, Optional, Union from fastapi import HTTPException from pydantic import ( @@ -27,44 +27,44 @@ class LiteLLM_UserScimMetadata(BaseModel): Scim metadata stored in LiteLLM_UserTable.metadata """ - givenName: Optional[str] = None - familyName: Optional[str] = None + givenName: str | None = None + familyName: str | None = None # SCIM Resource Models class SCIMResource(BaseModel): - schemas: List[str] - id: Optional[str] = None - externalId: Optional[str] = None - meta: Optional[Dict[str, Any]] = None + schemas: list[str] + id: str | None = None + externalId: str | None = None + meta: dict[str, Any] | None = None class SCIMUserName(BaseModel): - familyName: Optional[str] = None - givenName: Optional[str] = None - formatted: Optional[str] = None - middleName: Optional[str] = None - honorificPrefix: Optional[str] = None - honorificSuffix: Optional[str] = None + familyName: str | None = None + givenName: str | None = None + formatted: str | None = None + middleName: str | None = None + honorificPrefix: str | None = None + honorificSuffix: str | None = None class SCIMUserEmail(BaseModel): value: EmailStr - type: Optional[str] = None - primary: Optional[bool] = None + type: str | None = None + primary: bool | None = None class SCIMUserGroup(BaseModel): value: str # Group ID - display: Optional[str] = None # Group display name - type: Optional[str] = "direct" # direct or indirect + display: str | None = None # Group display name + type: str | None = "direct" # direct or indirect class SCIMMultiValuedAttribute(BaseModel): value: str - display: Optional[str] = None - type: Optional[str] = None - primary: Optional[bool] = None + display: str | None = None + type: str | None = None + primary: bool | None = None @model_validator(mode="before") @classmethod @@ -74,7 +74,7 @@ class SCIMMultiValuedAttribute(BaseModel): return data -SCIM_MULTI_VALUED_LIST_ADAPTER: Final = TypeAdapter(List[SCIMMultiValuedAttribute]) +SCIM_MULTI_VALUED_LIST_ADAPTER: Final = TypeAdapter(list[SCIMMultiValuedAttribute]) SCIM_MULTI_VALUED_ATTRIBUTE_METADATA_KEYS: Final = { "entitlements": SCIM_ENTITLEMENTS_METADATA_KEY, @@ -85,41 +85,41 @@ SCIM_MULTI_VALUED_ATTRIBUTE_METADATA_KEYS: Final = { class SCIMUserManager(BaseModel): model_config = ConfigDict(populate_by_name=True) - value: Optional[str] = None - displayName: Optional[str] = None - ref: Optional[str] = Field(default=None, alias="$ref") + value: str | None = None + displayName: str | None = None + ref: str | None = Field(default=None, alias="$ref") class SCIMEnterpriseUser(BaseModel): model_config = ConfigDict(populate_by_name=True) - employeeNumber: Optional[str] = None - costCenter: Optional[str] = None - organization: Optional[str] = None - division: Optional[str] = None - department: Optional[str] = None - manager: Optional[SCIMUserManager] = None + employeeNumber: str | None = None + costCenter: str | None = None + organization: str | None = None + division: str | None = None + department: str | None = None + manager: SCIMUserManager | None = None class SCIMUser(SCIMResource): model_config = ConfigDict(populate_by_name=True) - userName: Optional[str] = None - name: Optional[SCIMUserName] = None - displayName: Optional[str] = None + userName: str | None = None + name: SCIMUserName | None = None + displayName: str | None = None active: bool = True - emails: Optional[List[SCIMUserEmail]] = None - groups: Optional[List[SCIMUserGroup]] = None - entitlements: Optional[List[SCIMMultiValuedAttribute]] = None - roles: Optional[List[SCIMMultiValuedAttribute]] = None - enterprise_user: Optional[SCIMEnterpriseUser] = Field( + emails: list[SCIMUserEmail] | None = None + groups: list[SCIMUserGroup] | None = None + entitlements: list[SCIMMultiValuedAttribute] | None = None + roles: list[SCIMMultiValuedAttribute] | None = None + enterprise_user: SCIMEnterpriseUser | None = Field( default=None, alias=SCIM_ENTERPRISE_USER_SCHEMA, serialization_alias=SCIM_ENTERPRISE_USER_SCHEMA, ) @model_serializer(mode="wrap") - def _omit_absent_optional_blocks(self, handler: SerializerFunctionWrapHandler) -> Dict[str, Any]: + def _omit_absent_optional_blocks(self, handler: SerializerFunctionWrapHandler) -> dict[str, Any]: dumped: Final = handler(self) if self.enterprise_user is None: dumped.pop(SCIM_ENTERPRISE_USER_SCHEMA, None) @@ -133,7 +133,7 @@ class SCIMUser(SCIMResource): class SCIMMember(BaseModel): value: str # User ID - display: Optional[str] = None # Username or email + display: str | None = None # Username or email type: str | None = None @field_validator("type", mode="before") @@ -147,23 +147,23 @@ class SCIMMember(BaseModel): class SCIMGroup(SCIMResource): displayName: str - members: Optional[List[SCIMMember]] = None + members: list[SCIMMember] | None = None # SCIM List Response Models class SCIMListResponse(BaseModel): - schemas: List[str] = ["urn:ietf:params:scim:api:messages:2.0:ListResponse"] + schemas: list[str] = ["urn:ietf:params:scim:api:messages:2.0:ListResponse"] totalResults: int - startIndex: Optional[int] = 1 - itemsPerPage: Optional[int] = 10 - Resources: Union[List[SCIMUser], List[SCIMGroup]] + startIndex: int | None = 1 + itemsPerPage: int | None = 10 + Resources: list[SCIMUser] | list[SCIMGroup] # SCIM PATCH Operation Models class SCIMPatchOperation(BaseModel): op: str - path: Optional[str] = None - value: Optional[Any] = None + path: str | None = None + value: Any | None = None @field_validator("op", mode="before") @classmethod @@ -177,28 +177,28 @@ class SCIMPatchOperation(BaseModel): class SCIMPatchOp(BaseModel): - schemas: List[str] = ["urn:ietf:params:scim:api:messages:2.0:PatchOp"] - Operations: List[SCIMPatchOperation] + schemas: list[str] = ["urn:ietf:params:scim:api:messages:2.0:PatchOp"] + Operations: list[SCIMPatchOperation] # SCIM Service Provider Configuration Models class SCIMFeature(BaseModel): supported: bool - maxOperations: Optional[int] = None - maxPayloadSize: Optional[int] = None - maxResults: Optional[int] = None + maxOperations: int | None = None + maxPayloadSize: int | None = None + maxResults: int | None = None class SCIMServiceProviderConfig(BaseModel): - schemas: List[str] = ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"] + schemas: list[str] = ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"] patch: SCIMFeature = SCIMFeature(supported=True) bulk: SCIMFeature = SCIMFeature(supported=False) filter: SCIMFeature = SCIMFeature(supported=False) changePassword: SCIMFeature = SCIMFeature(supported=False) sort: SCIMFeature = SCIMFeature(supported=False) etag: SCIMFeature = SCIMFeature(supported=False) - authenticationSchemes: Optional[List[Dict[str, Any]]] = None - meta: Optional[Dict[str, Any]] = None + authenticationSchemes: list[dict[str, Any]] | None = None + meta: dict[str, Any] | None = None # SCIM ResourceType Models (RFC 7643 Section 6) @@ -217,15 +217,15 @@ class SCIMSchemaExtension(BaseModel): class SCIMResourceType(BaseModel): model_config = ConfigDict(populate_by_name=True) - schemas: List[str] = ["urn:ietf:params:scim:schemas:core:2.0:ResourceType"] + schemas: list[str] = ["urn:ietf:params:scim:schemas:core:2.0:ResourceType"] id: str name: str - description: Optional[str] = None + description: str | None = None endpoint: str schema_: str # "schema" is a reserved name in Pydantic context - schemaExtensions: Optional[List[SCIMSchemaExtension]] = None - meta: Optional[Dict[str, Any]] = None + schemaExtensions: list[SCIMSchemaExtension] | None = None + meta: dict[str, Any] | None = None def model_dump(self, **kwargs): d: Final = super().model_dump(**kwargs) @@ -240,12 +240,12 @@ class SCIMSchemaAttribute(BaseModel): name: str type: str multiValued: bool = False - description: Optional[str] = None + description: str | None = None required: bool = False mutability: str = "readWrite" returned: str = "default" uniqueness: str = "none" - subAttributes: Optional[List["SCIMSchemaAttribute"]] = None + subAttributes: list["SCIMSchemaAttribute"] | None = None def model_dump(self, **kwargs): d: Final = super().model_dump(**kwargs) @@ -255,9 +255,9 @@ class SCIMSchemaAttribute(BaseModel): class SCIMSchema(BaseModel): - schemas: List[str] = ["urn:ietf:params:scim:schemas:core:2.0:Schema"] + schemas: list[str] = ["urn:ietf:params:scim:schemas:core:2.0:Schema"] id: str name: str - description: Optional[str] = None - attributes: List[SCIMSchemaAttribute] = [] - meta: Optional[Dict[str, Any]] = None + description: str | None = None + attributes: list[SCIMSchemaAttribute] = [] + meta: dict[str, Any] | None = None diff --git a/litellm/types/proxy/management_endpoints/team_endpoints.py b/litellm/types/proxy/management_endpoints/team_endpoints.py index 7f924034d5c..2417868fb29 100644 --- a/litellm/types/proxy/management_endpoints/team_endpoints.py +++ b/litellm/types/proxy/management_endpoints/team_endpoints.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Literal from pydantic import BaseModel, ConfigDict, Field @@ -27,12 +27,12 @@ class GetTeamMemberPermissionsResponse(BaseModel): The team id that the permissions are for """ - team_member_permissions: Optional[List[str]] = [] + team_member_permissions: list[str] | None = [] """ The team member permissions currently set for the team """ - all_available_permissions: List[str] + all_available_permissions: list[str] """ All available team member permissions """ @@ -42,16 +42,16 @@ class UpdateTeamMemberPermissionsRequest(BaseModel): """Request to update the team member permissions for a team""" team_id: str - team_member_permissions: List[str] + team_member_permissions: list[str] class BulkUpdateTeamMemberPermissionsRequest(BaseModel): """Request to bulk-update team member permissions across teams.""" - permissions: List[KeyManagementRoutes] + permissions: list[KeyManagementRoutes] """Permissions to append to the target teams (duplicates are skipped).""" - team_ids: Optional[List[str]] = None + team_ids: list[str] | None = None """Specific team IDs to update. Required unless apply_to_all_teams is True.""" apply_to_all_teams: bool = False @@ -63,7 +63,7 @@ class BulkUpdateTeamMemberPermissionsResponse(BaseModel): message: str teams_updated: int - permissions_appended: Optional[List[str]] = None + permissions_appended: list[str] | None = None class TeamListItem(LiteLLM_TeamTable): @@ -72,15 +72,15 @@ class TeamListItem(LiteLLM_TeamTable): members_count: int = 0 keys_count: int = 0 # Resources inherited from access groups (separate from direct assignments) - access_group_models: Optional[List[str]] = None - access_group_mcp_server_ids: Optional[List[str]] = None - access_group_agent_ids: Optional[List[str]] = None + access_group_models: list[str] | None = None + access_group_mcp_server_ids: list[str] | None = None + access_group_agent_ids: list[str] | None = None class TeamListResponse(BaseModel): """Response to get the list of teams""" - teams: List[Union[TeamListItem, LiteLLM_TeamTable, LiteLLM_DeletedTeamTable]] + teams: list[TeamListItem | LiteLLM_TeamTable | LiteLLM_DeletedTeamTable] total: int page: int page_size: int @@ -91,39 +91,39 @@ class BulkTeamMemberAddRequest(BaseModel): """Request for bulk team member addition""" team_id: str - members: Optional[List[Member]] = None # List of members to add - all_users: Optional[bool] = False # Flag to add all users on Proxy to the team - max_budget_in_team: Optional[float] = None + members: list[Member] | None = None # List of members to add + all_users: bool | None = False # Flag to add all users on Proxy to the team + max_budget_in_team: float | None = None class TeamMemberAddResult(BaseModel): """Result of a single team member add operation""" - user_id: Optional[str] = None - user_email: Optional[str] = None + user_id: str | None = None + user_email: str | None = None success: bool - error: Optional[str] = None - updated_user: Optional[Dict[str, Any]] = None - updated_team_membership: Optional[Dict[str, Any]] = None + error: str | None = None + updated_user: dict[str, Any] | None = None + updated_team_membership: dict[str, Any] | None = None class BulkTeamMemberAddResponse(BaseModel): """Response for bulk team member add operations""" team_id: str - results: List[TeamMemberAddResult] + results: list[TeamMemberAddResult] total_requested: int successful_additions: int failed_additions: int - updated_team: Optional[Dict[str, Any]] = None + updated_team: dict[str, Any] | None = None class TeamMemberInfoResponse(LiteLLM_TeamMembership): """Response for GET /team/{team_id}/members/me — caller's own membership row.""" - role: Optional[str] = None - user_email: Optional[str] = None - team_alias: Optional[str] = None + role: str | None = None + user_email: str | None = None + team_alias: str | None = None class TeamMetadataFieldSchema(BaseModel): @@ -136,7 +136,7 @@ class TeamMetadataFieldSchema(BaseModel): model_config = ConfigDict(extra="forbid") key: str = Field(min_length=1) - label: Optional[str] = None + label: str | None = None class TeamMetadataSchemaResponse(BaseModel): diff --git a/litellm/types/proxy/management_endpoints/ui_sso.py b/litellm/types/proxy/management_endpoints/ui_sso.py index f68d818d991..0585057c22e 100644 --- a/litellm/types/proxy/management_endpoints/ui_sso.py +++ b/litellm/types/proxy/management_endpoints/ui_sso.py @@ -1,4 +1,4 @@ -from typing import Dict, List, Literal, Optional, Union +from typing import Literal from pydantic import Field from typing_extensions import TypedDict @@ -20,38 +20,38 @@ class LiteLLM_UpperboundKeyGenerateParams(LiteLLMPydanticObjectBase): rpm_limit (Optional[int], optional): Rpm limit. Defaults to None. """ - max_budget: Optional[float] = None - budget_duration: Optional[str] = None - duration: Optional[str] = None - max_parallel_requests: Optional[int] = None - tpm_limit: Optional[int] = None - rpm_limit: Optional[int] = None + max_budget: float | None = None + budget_duration: str | None = None + duration: str | None = None + max_parallel_requests: int | None = None + tpm_limit: int | None = None + rpm_limit: int | None = None class MicrosoftGraphAPIUserGroupDirectoryObject(TypedDict, total=False): """Model for Microsoft Graph API directory object""" - odata_type: Optional[str] - id: Optional[str] - deletedDateTime: Optional[str] - description: Optional[str] - displayName: Optional[str] - roleTemplateId: Optional[str] + odata_type: str | None + id: str | None + deletedDateTime: str | None + description: str | None + displayName: str | None + roleTemplateId: str | None class MicrosoftGraphAPIUserGroupResponse(TypedDict, total=False): """Model for Microsoft Graph API user groups response""" - odata_context: Optional[str] - odata_nextLink: Optional[str] - value: Optional[List[MicrosoftGraphAPIUserGroupDirectoryObject]] + odata_context: str | None + odata_nextLink: str | None + value: list[MicrosoftGraphAPIUserGroupDirectoryObject] | None class MicrosoftServicePrincipalTeam(TypedDict, total=False): """Model for Microsoft Service Principal Team""" - principalDisplayName: Optional[str] - principalId: Optional[str] + principalDisplayName: str | None + principalId: str | None class AccessControl_UI_AccessMode(LiteLLMPydanticObjectBase): @@ -74,11 +74,11 @@ class RoleMappings(LiteLLMPydanticObjectBase): group_claim: str = Field( description="The field name in the SSO token that contains the groups array (e.g., 'groups', 'roles')" ) - default_role: Optional[LitellmUserRoles] = Field( + default_role: LitellmUserRoles | None = Field( default=None, description="Default role to assign if user's groups don't match any role mappings. Must be a valid LitellmUserRoles value (e.g., 'proxy_admin', 'internal_user', 'proxy_admin_viewer')", ) - roles: Dict[LitellmUserRoles, List[str]] = Field( + roles: dict[LitellmUserRoles, list[str]] = Field( default_factory=dict, description="Mapping of LiteLLM role names to arrays of SSO group names. Example: {'proxy_admin': ['group-1', 'group-2'], 'proxy_admin_viewer': ['group-3']}", ) @@ -92,7 +92,7 @@ class TeamMappings(LiteLLMPydanticObjectBase): requiring config file changes and restarts. """ - team_ids_jwt_field: Optional[str] = Field( + team_ids_jwt_field: str | None = Field( default=None, description="The field name in the SSO/JWT token that contains the team IDs array (e.g., 'groups', 'teams'). Supports dot notation for nested fields.", ) @@ -104,97 +104,97 @@ class SSOConfig(LiteLLMPydanticObjectBase): """ # Google SSO - google_client_id: Optional[str] = Field( + google_client_id: str | None = Field( default=None, description="Google OAuth Client ID for SSO authentication", ) - google_client_secret: Optional[str] = Field( + google_client_secret: str | None = Field( default=None, description="Google OAuth Client Secret for SSO authentication", ) # Microsoft SSO - microsoft_client_id: Optional[str] = Field( + microsoft_client_id: str | None = Field( default=None, description="Microsoft OAuth Client ID for SSO authentication", ) - microsoft_client_secret: Optional[str] = Field( + microsoft_client_secret: str | None = Field( default=None, description="Microsoft OAuth Client Secret for SSO authentication", ) - microsoft_tenant: Optional[str] = Field( + microsoft_tenant: str | None = Field( default=None, description="Microsoft Azure Tenant ID for SSO authentication", ) # Generic/Okta SSO - generic_client_id: Optional[str] = Field( + generic_client_id: str | None = Field( default=None, description="Generic OAuth Client ID for SSO authentication (used for Okta and other providers)", ) - generic_client_secret: Optional[str] = Field( + generic_client_secret: str | None = Field( default=None, description="Generic OAuth Client Secret for SSO authentication", ) - generic_authorization_endpoint: Optional[str] = Field( + generic_authorization_endpoint: str | None = Field( default=None, description="Authorization endpoint URL for generic OAuth provider", ) - generic_token_endpoint: Optional[str] = Field( + generic_token_endpoint: str | None = Field( default=None, description="Token endpoint URL for generic OAuth provider", ) - generic_userinfo_endpoint: Optional[str] = Field( + generic_userinfo_endpoint: str | None = Field( default=None, description="User info endpoint URL for generic OAuth provider", ) - generic_scope: Optional[str] = Field( + generic_scope: str | None = Field( default=None, description="Space-separated OAuth scopes requested from the generic provider, e.g. 'openid email profile'", ) # SAML SSO - saml_idp_metadata_url: Optional[str] = Field( + saml_idp_metadata_url: str | None = Field( default=None, description="URL of the SAML IdP metadata to fetch and parse for SSO authentication", ) - saml_idp_metadata_xml: Optional[str] = Field( + saml_idp_metadata_xml: str | None = Field( default=None, description="Inline SAML IdP metadata XML, used when a metadata URL is not available", ) - saml_sp_entity_id: Optional[str] = Field( + saml_sp_entity_id: str | None = Field( default=None, description="SAML Service Provider entityID; defaults to the proxy's /sso/saml/metadata URL", ) - saml_allow_unsolicited: Optional[str] = Field( + saml_allow_unsolicited: str | None = Field( default=None, description="'true' to accept IdP-initiated (unsolicited) SAML responses, which cannot be browser-bound against login CSRF", ) # Common settings - proxy_base_url: Optional[str] = Field( + proxy_base_url: str | None = Field( default=None, description="Base URL of the proxy server for SSO redirects", ) - user_email: Optional[str] = Field( + user_email: str | None = Field( default=None, description="Email of the proxy admin user", ) # Access Mode - ui_access_mode: Optional[Union[AccessControl_UI_AccessMode, str]] = Field( + ui_access_mode: AccessControl_UI_AccessMode | str | None = Field( default=None, description="Access mode for the UI", ) # Role Mappings - role_mappings: Optional[RoleMappings] = Field( + role_mappings: RoleMappings | None = Field( default=None, description="Configuration for mapping SSO groups to LiteLLM roles based on group claims in the SSO token", ) # Team Mappings - team_mappings: Optional[TeamMappings] = Field( + team_mappings: TeamMappings | None = Field( default=None, description="Configuration for mapping SSO JWT fields to team IDs. Takes precedence over config file settings.", ) @@ -205,27 +205,27 @@ class DefaultTeamSSOParams(LiteLLMPydanticObjectBase): Default parameters to apply when a new team is automatically created by LiteLLM via SSO Groups """ - models: List[str] = Field( + models: list[str] = Field( default=[], description="Default list of models that new automatically created teams can access", ) - max_budget: Optional[float] = Field( + max_budget: float | None = Field( default=None, description="Default maximum budget (in USD) for new automatically created teams", ) - budget_duration: Optional[str] = Field( + budget_duration: str | None = Field( default=None, description="Default budget duration for new automatically created teams (e.g. 'daily', 'weekly', 'monthly')", ) - tpm_limit: Optional[int] = Field( + tpm_limit: int | None = Field( default=None, description="Default tpm limit for new automatically created teams", ) - rpm_limit: Optional[int] = Field( + rpm_limit: int | None = Field( default=None, description="Default rpm limit for new automatically created teams", ) - team_member_permissions: Optional[List[KeyManagementRoutes]] = Field( + team_member_permissions: list[KeyManagementRoutes] | None = Field( default=None, description="Default permissions granted to members of newly created teams (e.g. /key/generate, /key/update, /key/delete). /key/info and /key/health are always included.", ) diff --git a/litellm/types/proxy/policy_engine/__init__.py b/litellm/types/proxy/policy_engine/__init__.py index 84d354b82a8..20812d4d14f 100644 --- a/litellm/types/proxy/policy_engine/__init__.py +++ b/litellm/types/proxy/policy_engine/__init__.py @@ -59,52 +59,52 @@ from litellm.types.proxy.policy_engine.validation_types import ( ) __all__ = [ + "AttachmentImpactResponse", # Pipeline types "GuardrailPipeline", + "PipelineExecutionResult", "PipelineStep", "PipelineStepResult", - "PipelineExecutionResult", + # Pipeline test types + "PipelineTestRequest", # Policy types "Policy", - "PolicyConfig", - "PolicyGuardrails", - "PolicyScope", - "PolicyCondition", "PolicyAttachment", + "PolicyAttachmentCreateRequest", + "PolicyAttachmentDBResponse", + "PolicyAttachmentListResponse", + "PolicyCondition", + # CRUD Request/Response types + "PolicyConditionRequest", + "PolicyConfig", + "PolicyCreateRequest", + "PolicyDBResponse", + "PolicyGuardrails", + # API Response types + "PolicyGuardrailsResponse", + "PolicyInfoResponse", + "PolicyListDBResponse", + "PolicyListResponse", + # Resolver types + "PolicyMatchContext", + "PolicyMatchDetail", + # Resolve types + "PolicyResolveRequest", + "PolicyResolveResponse", + "PolicyScope", + "PolicyScopeResponse", + "PolicySummaryItem", + "PolicyTestResponse", + "PolicyUpdateRequest", # Validation types "PolicyValidateRequest", "PolicyValidationError", "PolicyValidationErrorType", "PolicyValidationResponse", - # Resolver types - "PolicyMatchContext", - "ResolvedPolicy", - # API Response types - "PolicyGuardrailsResponse", - "PolicyInfoResponse", - "PolicyListResponse", - "PolicyScopeResponse", - "PolicySummaryItem", - "PolicyTestResponse", - # CRUD Request/Response types - "PolicyConditionRequest", - "PolicyCreateRequest", - "PolicyUpdateRequest", - "PolicyDBResponse", - "PolicyListDBResponse", - "PolicyAttachmentCreateRequest", - "PolicyAttachmentDBResponse", - "PolicyAttachmentListResponse", - # Pipeline test types - "PipelineTestRequest", - # Resolve types - "PolicyResolveRequest", - "PolicyResolveResponse", - "PolicyMatchDetail", - "AttachmentImpactResponse", + "PolicyVersionCompareResponse", # Policy versioning "PolicyVersionCreateRequest", - "PolicyVersionStatusUpdateRequest", "PolicyVersionListResponse", - "PolicyVersionCompareResponse", + "PolicyVersionStatusUpdateRequest", + "ResolvedPolicy", ] diff --git a/litellm/types/proxy/policy_engine/pipeline_types.py b/litellm/types/proxy/policy_engine/pipeline_types.py index e2f45d900b2..063edb0a264 100644 --- a/litellm/types/proxy/policy_engine/pipeline_types.py +++ b/litellm/types/proxy/policy_engine/pipeline_types.py @@ -6,7 +6,7 @@ When a policy has a `pipeline`, its guardrails run in the defined step order with configurable actions on pass/fail, rather than independently. """ -from typing import Any, Dict, Final, List, Literal, Optional +from typing import Any, Final, Literal from pydantic import BaseModel, ConfigDict, Field, field_validator @@ -31,7 +31,7 @@ class PipelineStep(BaseModel): default="allow", description="Action when guardrail passes: next | block | allow | modify_response", ) - on_error: Optional[str] = Field( + on_error: str | None = Field( default=None, description="Action when the guardrail raises a technical error (timeouts, " "unreachable provider, non-intervention HTTP errors). If omitted, uses on_fail.", @@ -40,7 +40,7 @@ class PipelineStep(BaseModel): default=False, description="Forward modified request data (e.g., PII-masked) to next step.", ) - modify_response_message: Optional[str] = Field( + modify_response_message: str | None = Field( default=None, description="Custom message for modify_response action.", ) @@ -49,7 +49,7 @@ class PipelineStep(BaseModel): @field_validator("on_fail", "on_pass", "on_error") @classmethod - def validate_action(cls, v: Optional[str]) -> Optional[str]: + def validate_action(cls, v: str | None) -> str | None: if v is None: return None if v not in VALID_PIPELINE_ACTIONS: @@ -66,7 +66,7 @@ class GuardrailPipeline(BaseModel): """ mode: str = Field(description="Event hook: pre_call | post_call") - steps: List[PipelineStep] = Field( + steps: list[PipelineStep] = Field( description="Ordered list of pipeline steps. Must have at least 1 step.", min_length=1, ) @@ -87,9 +87,9 @@ class PipelineStepResult(BaseModel): guardrail_name: str outcome: Literal["pass", "fail", "error"] action_taken: str - modified_data: Optional[Dict[str, Any]] = None - error_detail: Optional[str] = None - duration_seconds: Optional[float] = None + modified_data: dict[str, Any] | None = None + error_detail: str | None = None + duration_seconds: float | None = None class PipelineExecutionResult(BaseModel): @@ -98,8 +98,8 @@ class PipelineExecutionResult(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) terminal_action: str # block | allow | modify_response - step_results: List[PipelineStepResult] - modified_data: Optional[Dict[str, Any]] = None - error_message: Optional[str] = None - modify_response_message: Optional[str] = None - original_exception: Optional[Exception] = Field(default=None, exclude=True) + step_results: list[PipelineStepResult] + modified_data: dict[str, Any] | None = None + error_message: str | None = None + modify_response_message: str | None = None + original_exception: Exception | None = Field(default=None, exclude=True) diff --git a/litellm/types/proxy/policy_engine/policy_types.py b/litellm/types/proxy/policy_engine/policy_types.py index 53a74ca6fd8..28144cd5b81 100644 --- a/litellm/types/proxy/policy_engine/policy_types.py +++ b/litellm/types/proxy/policy_engine/policy_types.py @@ -29,8 +29,6 @@ Key concepts: - `condition`: Optional model condition for when guardrails apply """ -from typing import Dict, List, Optional, Union - from pydantic import BaseModel, ConfigDict, Field from litellm.types.proxy.policy_engine.pipeline_types import GuardrailPipeline @@ -55,7 +53,7 @@ class PolicyCondition(BaseModel): ``` """ - model: Optional[Union[str, List[str]]] = Field( + model: str | list[str] | None = Field( default=None, description="Model name(s) to match. Can be exact string, regex pattern, or list.", ) @@ -87,38 +85,38 @@ class PolicyScope(BaseModel): A request must match ALL specified scope fields for the attachment to apply. """ - teams: Optional[List[str]] = Field( + teams: list[str] | None = Field( default=None, description="Team aliases or wildcard patterns. Use '*' for all teams.", ) - keys: Optional[List[str]] = Field( + keys: list[str] | None = Field( default=None, description="Key aliases or wildcard patterns. Use '*' for all keys.", ) - models: Optional[List[str]] = Field( + models: list[str] | None = Field( default=None, description="Model names or wildcard patterns. Use '*' for all models.", ) - tags: Optional[List[str]] = Field( + tags: list[str] | None = Field( default=None, description="Tag patterns to match against key/team tags. Supports wildcards (e.g., health-*).", ) model_config = ConfigDict(extra="forbid") - def get_teams(self) -> List[str]: + def get_teams(self) -> list[str]: """Returns teams list, defaulting to ['*'] if not specified.""" return self.teams if self.teams else ["*"] - def get_keys(self) -> List[str]: + def get_keys(self) -> list[str]: """Returns keys list, defaulting to ['*'] if not specified.""" return self.keys if self.keys else ["*"] - def get_models(self) -> List[str]: + def get_models(self) -> list[str]: """Returns models list, defaulting to ['*'] if not specified.""" return self.models if self.models else ["*"] - def get_tags(self) -> List[str]: + def get_tags(self) -> list[str]: """Returns tags list, defaulting to empty list if not specified. Unlike teams/keys/models, empty tags means 'do not check tags' @@ -144,22 +142,22 @@ class PolicyGuardrails(BaseModel): - Remove specific guardrails inherited from parent """ - add: Optional[List[str]] = Field( + add: list[str] | None = Field( default=None, description="Guardrail names to add to this policy.", ) - remove: Optional[List[str]] = Field( + remove: list[str] | None = Field( default=None, description="Guardrail names to remove (typically from inherited policy).", ) model_config = ConfigDict(extra="forbid") - def get_add(self) -> List[str]: + def get_add(self) -> list[str]: """Returns add list, defaulting to empty list if not specified.""" return self.add if self.add else [] - def get_remove(self) -> List[str]: + def get_remove(self) -> list[str]: """Returns remove list, defaulting to empty list if not specified.""" return self.remove if self.remove else [] @@ -217,11 +215,11 @@ class Policy(BaseModel): ``` """ - inherit: Optional[str] = Field( + inherit: str | None = Field( default=None, description="Name of the parent policy to inherit from.", ) - description: Optional[str] = Field( + description: str | None = Field( default=None, description="Human-readable description of the policy.", ) @@ -229,11 +227,11 @@ class Policy(BaseModel): default_factory=PolicyGuardrails, description="Guardrails configuration with add/remove lists.", ) - condition: Optional[PolicyCondition] = Field( + condition: PolicyCondition | None = Field( default=None, description="Optional condition for when this policy's guardrails apply.", ) - pipeline: Optional[GuardrailPipeline] = Field( + pipeline: GuardrailPipeline | None = Field( default=None, description="Optional pipeline for ordered, conditional guardrail execution.", ) @@ -270,23 +268,23 @@ class PolicyAttachment(BaseModel): policy: str = Field( description="Name of the policy to attach.", ) - scope: Optional[str] = Field( + scope: str | None = Field( default=None, description="Use '*' for global scope (applies to all requests).", ) - teams: Optional[List[str]] = Field( + teams: list[str] | None = Field( default=None, description="Team aliases or patterns this attachment applies to.", ) - keys: Optional[List[str]] = Field( + keys: list[str] | None = Field( default=None, description="Key aliases or patterns this attachment applies to.", ) - models: Optional[List[str]] = Field( + models: list[str] | None = Field( default=None, description="Model names or patterns this attachment applies to.", ) - tags: Optional[List[str]] = Field( + tags: list[str] | None = Field( default=None, description="Tag patterns this attachment applies to. Supports wildcards (e.g., health-*).", ) @@ -316,7 +314,7 @@ class PolicyConfig(BaseModel): Maps policy names to their Policy definitions. """ - policies: Dict[str, Policy] = Field( + policies: dict[str, Policy] = Field( default_factory=dict, description="Map of policy names to Policy objects.", ) diff --git a/litellm/types/proxy/policy_engine/resolver_types.py b/litellm/types/proxy/policy_engine/resolver_types.py index b4096cd2044..9e69f303559 100644 --- a/litellm/types/proxy/policy_engine/resolver_types.py +++ b/litellm/types/proxy/policy_engine/resolver_types.py @@ -6,7 +6,7 @@ the final guardrails list. """ from datetime import datetime -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Literal from pydantic import BaseModel, ConfigDict, Field @@ -18,19 +18,19 @@ class PolicyMatchContext(BaseModel): Contains the team alias, key alias, and model from the incoming request. """ - team_alias: Optional[str] = Field( + team_alias: str | None = Field( default=None, description="Team alias from the request.", ) - key_alias: Optional[str] = Field( + key_alias: str | None = Field( default=None, description="API key alias from the request.", ) - model: Optional[str] = Field( + model: str | None = Field( default=None, description="Model name from the request.", ) - tags: Optional[List[str]] = Field( + tags: list[str] | None = Field( default=None, description="Tags from key/team metadata.", ) @@ -46,11 +46,11 @@ class ResolvedPolicy(BaseModel): """ policy_name: str = Field(description="Name of the resolved policy.") - guardrails: List[str] = Field( + guardrails: list[str] = Field( default_factory=list, description="Final list of guardrail names to apply.", ) - inheritance_chain: List[str] = Field( + inheritance_chain: list[str] = Field( default_factory=list, description="List of policy names in the inheritance chain (from root to this policy).", ) @@ -66,44 +66,44 @@ class ResolvedPolicy(BaseModel): class PolicyScopeResponse(BaseModel): """Scope configuration for a policy.""" - teams: List[str] = Field(default_factory=list) - keys: List[str] = Field(default_factory=list) - models: List[str] = Field(default_factory=list) - tags: List[str] = Field(default_factory=list) + teams: list[str] = Field(default_factory=list) + keys: list[str] = Field(default_factory=list) + models: list[str] = Field(default_factory=list) + tags: list[str] = Field(default_factory=list) class PolicyGuardrailsResponse(BaseModel): """Guardrails configuration for a policy.""" - add: List[str] = Field(default_factory=list) - remove: List[str] = Field(default_factory=list) + add: list[str] = Field(default_factory=list) + remove: list[str] = Field(default_factory=list) class PolicyInfoResponse(BaseModel): """Response for /policy/info/{policy_name} endpoint.""" policy_name: str - inherit: Optional[str] = None + inherit: str | None = None scope: PolicyScopeResponse guardrails: PolicyGuardrailsResponse - resolved_guardrails: List[str] - inheritance_chain: List[str] + resolved_guardrails: list[str] + inheritance_chain: list[str] class PolicySummaryItem(BaseModel): """Summary of a single policy for list endpoint.""" - inherit: Optional[str] = None + inherit: str | None = None scope: PolicyScopeResponse guardrails: PolicyGuardrailsResponse - resolved_guardrails: List[str] - inheritance_chain: List[str] + resolved_guardrails: list[str] + inheritance_chain: list[str] class PolicyListResponse(BaseModel): """Response for /policy/list endpoint.""" - policies: Dict[str, PolicySummaryItem] + policies: dict[str, PolicySummaryItem] total_count: int @@ -111,9 +111,9 @@ class PolicyTestResponse(BaseModel): """Response for /policy/test endpoint.""" context: PolicyMatchContext - matching_policies: List[str] - resolved_guardrails: List[str] - message: Optional[str] = None + matching_policies: list[str] + resolved_guardrails: list[str] + message: str | None = None # ───────────────────────────────────────────────────────────────────────────── @@ -124,7 +124,7 @@ class PolicyTestResponse(BaseModel): class PolicyConditionRequest(BaseModel): """Condition for when a policy applies.""" - model: Optional[str] = Field( + model: str | None = Field( default=None, description="Model name pattern (exact match or regex) for when policy applies.", ) @@ -134,27 +134,27 @@ class PolicyCreateRequest(BaseModel): """Request body for creating a new policy.""" policy_name: str = Field(description="Unique name for the policy.") - inherit: Optional[str] = Field( + inherit: str | None = Field( default=None, description="Name of parent policy to inherit from.", ) - description: Optional[str] = Field( + description: str | None = Field( default=None, description="Human-readable description of the policy.", ) - guardrails_add: Optional[List[str]] = Field( + guardrails_add: list[str] | None = Field( default=None, description="List of guardrail names to add.", ) - guardrails_remove: Optional[List[str]] = Field( + guardrails_remove: list[str] | None = Field( default=None, description="List of guardrail names to remove (from inherited).", ) - condition: Optional[PolicyConditionRequest] = Field( + condition: PolicyConditionRequest | None = Field( default=None, description="Condition for when this policy applies.", ) - pipeline: Optional[Dict[str, Any]] = Field( + pipeline: dict[str, Any] | None = Field( default=None, description="Optional guardrail pipeline for ordered execution. Contains 'mode' and 'steps'.", ) @@ -163,31 +163,31 @@ class PolicyCreateRequest(BaseModel): class PolicyUpdateRequest(BaseModel): """Request body for updating a policy.""" - policy_name: Optional[str] = Field( + policy_name: str | None = Field( default=None, description="New name for the policy.", ) - inherit: Optional[str] = Field( + inherit: str | None = Field( default=None, description="Name of parent policy to inherit from.", ) - description: Optional[str] = Field( + description: str | None = Field( default=None, description="Human-readable description of the policy.", ) - guardrails_add: Optional[List[str]] = Field( + guardrails_add: list[str] | None = Field( default=None, description="List of guardrail names to add.", ) - guardrails_remove: Optional[List[str]] = Field( + guardrails_remove: list[str] | None = Field( default=None, description="List of guardrail names to remove (from inherited).", ) - condition: Optional[PolicyConditionRequest] = Field( + condition: PolicyConditionRequest | None = Field( default=None, description="Condition for when this policy applies.", ) - pipeline: Optional[Dict[str, Any]] = Field( + pipeline: dict[str, Any] | None = Field( default=None, description="Optional guardrail pipeline for ordered execution. Contains 'mode' and 'steps'.", ) @@ -203,23 +203,23 @@ class PolicyDBResponse(BaseModel): default="production", description="One of: draft, published, production.", ) - parent_version_id: Optional[str] = Field(default=None, description="Policy ID this version was cloned from.") + parent_version_id: str | None = Field(default=None, description="Policy ID this version was cloned from.") is_latest: bool = Field( default=True, description="True if this is the latest version by version_number.", ) - published_at: Optional[datetime] = Field(default=None, description="When this version was published.") - production_at: Optional[datetime] = Field(default=None, description="When this version was promoted to production.") - inherit: Optional[str] = Field(default=None, description="Parent policy name.") - description: Optional[str] = Field(default=None, description="Policy description.") - guardrails_add: List[str] = Field(default_factory=list, description="Guardrails to add.") - guardrails_remove: List[str] = Field(default_factory=list, description="Guardrails to remove.") - condition: Optional[Dict[str, Any]] = Field(default=None, description="Policy condition.") - pipeline: Optional[Dict[str, Any]] = Field(default=None, description="Optional guardrail pipeline.") - created_at: Optional[datetime] = Field(default=None, description="When the policy was created.") - updated_at: Optional[datetime] = Field(default=None, description="When the policy was last updated.") - created_by: Optional[str] = Field(default=None, description="Who created the policy.") - updated_by: Optional[str] = Field(default=None, description="Who last updated the policy.") + published_at: datetime | None = Field(default=None, description="When this version was published.") + production_at: datetime | None = Field(default=None, description="When this version was promoted to production.") + inherit: str | None = Field(default=None, description="Parent policy name.") + description: str | None = Field(default=None, description="Policy description.") + guardrails_add: list[str] = Field(default_factory=list, description="Guardrails to add.") + guardrails_remove: list[str] = Field(default_factory=list, description="Guardrails to remove.") + condition: dict[str, Any] | None = Field(default=None, description="Policy condition.") + pipeline: dict[str, Any] | None = Field(default=None, description="Optional guardrail pipeline.") + created_at: datetime | None = Field(default=None, description="When the policy was created.") + updated_at: datetime | None = Field(default=None, description="When the policy was last updated.") + created_by: str | None = Field(default=None, description="Who created the policy.") + updated_by: str | None = Field(default=None, description="Who last updated the policy.") definition_location: Literal["db", "config"] = Field( default="db", description="Where this policy is defined: 'db' (database) or 'config' (config.yaml).", @@ -229,7 +229,7 @@ class PolicyDBResponse(BaseModel): class PolicyListDBResponse(BaseModel): """Response for listing policies from the database.""" - policies: List[PolicyDBResponse] = Field(default_factory=list, description="List of policies.") + policies: list[PolicyDBResponse] = Field(default_factory=list, description="List of policies.") total_count: int = Field(default=0, description="Total number of policies.") @@ -241,7 +241,7 @@ class PolicyListDBResponse(BaseModel): class PolicyVersionCreateRequest(BaseModel): """Request body for creating a new policy version (draft).""" - source_policy_id: Optional[str] = Field( + source_policy_id: str | None = Field( default=None, description="Policy ID to clone from. If None, clone from current production version.", ) @@ -259,7 +259,7 @@ class PolicyVersionListResponse(BaseModel): """Response for listing all versions of a policy.""" policy_name: str = Field(description="Name of the policy.") - versions: List[PolicyDBResponse] = Field( + versions: list[PolicyDBResponse] = Field( default_factory=list, description="All versions ordered by version_number desc." ) total_count: int = Field(default=0, description="Total number of versions.") @@ -270,7 +270,7 @@ class PolicyVersionCompareResponse(BaseModel): version_a: PolicyDBResponse = Field(description="First version.") version_b: PolicyDBResponse = Field(description="Second version.") - field_diffs: Dict[str, Dict[str, Any]] = Field( + field_diffs: dict[str, dict[str, Any]] = Field( default_factory=dict, description="Field name -> {version_a: val, version_b: val} for differing fields.", ) @@ -285,23 +285,23 @@ class PolicyAttachmentCreateRequest(BaseModel): """Request body for creating a policy attachment.""" policy_name: str = Field(description="Name of the policy to attach.") - scope: Optional[str] = Field( + scope: str | None = Field( default=None, description="Use '*' for global scope (applies to all requests).", ) - teams: Optional[List[str]] = Field( + teams: list[str] | None = Field( default=None, description="Team aliases or patterns this attachment applies to.", ) - keys: Optional[List[str]] = Field( + keys: list[str] | None = Field( default=None, description="Key aliases or patterns this attachment applies to.", ) - models: Optional[List[str]] = Field( + models: list[str] | None = Field( default=None, description="Model names or patterns this attachment applies to.", ) - tags: Optional[List[str]] = Field( + tags: list[str] | None = Field( default=None, description="Tag patterns this attachment applies to. Supports wildcards (e.g., health-*).", ) @@ -312,15 +312,15 @@ class PolicyAttachmentDBResponse(BaseModel): attachment_id: str = Field(description="Unique ID of the attachment.") policy_name: str = Field(description="Name of the attached policy.") - scope: Optional[str] = Field(default=None, description="Scope of the attachment.") - teams: List[str] = Field(default_factory=list, description="Team patterns.") - keys: List[str] = Field(default_factory=list, description="Key patterns.") - models: List[str] = Field(default_factory=list, description="Model patterns.") - tags: List[str] = Field(default_factory=list, description="Tag patterns.") - created_at: Optional[datetime] = Field(default=None, description="When the attachment was created.") - updated_at: Optional[datetime] = Field(default=None, description="When the attachment was last updated.") - created_by: Optional[str] = Field(default=None, description="Who created the attachment.") - updated_by: Optional[str] = Field(default=None, description="Who last updated the attachment.") + scope: str | None = Field(default=None, description="Scope of the attachment.") + teams: list[str] = Field(default_factory=list, description="Team patterns.") + keys: list[str] = Field(default_factory=list, description="Key patterns.") + models: list[str] = Field(default_factory=list, description="Model patterns.") + tags: list[str] = Field(default_factory=list, description="Tag patterns.") + created_at: datetime | None = Field(default=None, description="When the attachment was created.") + updated_at: datetime | None = Field(default=None, description="When the attachment was last updated.") + created_by: str | None = Field(default=None, description="Who created the attachment.") + updated_by: str | None = Field(default=None, description="Who last updated the attachment.") definition_location: Literal["db", "config"] = Field( default="db", description="Where this attachment is defined: 'db' (database) or 'config' (config.yaml).", @@ -330,7 +330,7 @@ class PolicyAttachmentDBResponse(BaseModel): class PolicyAttachmentListResponse(BaseModel): """Response for listing policy attachments.""" - attachments: List[PolicyAttachmentDBResponse] = Field( + attachments: list[PolicyAttachmentDBResponse] = Field( default_factory=list, description="List of policy attachments." ) total_count: int = Field(default=0, description="Total number of attachments.") @@ -344,10 +344,10 @@ class PolicyAttachmentListResponse(BaseModel): class PipelineTestRequest(BaseModel): """Request body for testing a guardrail pipeline with sample messages.""" - pipeline: Dict[str, Any] = Field( + pipeline: dict[str, Any] = Field( description="Pipeline definition with 'mode' and 'steps'.", ) - test_messages: List[Dict[str, str]] = Field( + test_messages: list[dict[str, str]] = Field( description="Test messages to run through the pipeline, e.g. [{'role': 'user', 'content': '...'}].", ) @@ -355,10 +355,10 @@ class PipelineTestRequest(BaseModel): class PolicyResolveRequest(BaseModel): """Request body for resolving effective policies/guardrails for a context.""" - team_alias: Optional[str] = Field(default=None, description="Team alias to resolve for.") - key_alias: Optional[str] = Field(default=None, description="Key alias to resolve for.") - model: Optional[str] = Field(default=None, description="Model name to resolve for.") - tags: Optional[List[str]] = Field(default=None, description="Tags to resolve for.") + team_alias: str | None = Field(default=None, description="Team alias to resolve for.") + key_alias: str | None = Field(default=None, description="Key alias to resolve for.") + model: str | None = Field(default=None, description="Model name to resolve for.") + tags: list[str] | None = Field(default=None, description="Tags to resolve for.") class PolicyMatchDetail(BaseModel): @@ -368,7 +368,7 @@ class PolicyMatchDetail(BaseModel): matched_via: str = Field( description="How the policy was matched (e.g., 'tag:healthcare', 'team:health-team', 'scope:*')." ) - guardrails_added: List[str] = Field( + guardrails_added: list[str] = Field( default_factory=list, description="Guardrails this policy contributes.", ) @@ -377,11 +377,11 @@ class PolicyMatchDetail(BaseModel): class PolicyResolveResponse(BaseModel): """Response for resolving effective policies/guardrails for a context.""" - effective_guardrails: List[str] = Field( + effective_guardrails: list[str] = Field( default_factory=list, description="Final list of guardrails that would be applied.", ) - matched_policies: List[PolicyMatchDetail] = Field( + matched_policies: list[PolicyMatchDetail] = Field( default_factory=list, description="Details about each matched policy and why it matched.", ) @@ -405,11 +405,11 @@ class AttachmentImpactResponse(BaseModel): ) unnamed_keys_count: int = Field(default=0, description="Number of affected keys without an alias.") unnamed_teams_count: int = Field(default=0, description="Number of affected teams without an alias.") - sample_keys: List[str] = Field( + sample_keys: list[str] = Field( default_factory=list, description="Sample of affected key aliases (up to 10).", ) - sample_teams: List[str] = Field( + sample_teams: list[str] = Field( default_factory=list, description="Sample of affected team aliases (up to 10).", ) diff --git a/litellm/types/proxy/policy_engine/validation_types.py b/litellm/types/proxy/policy_engine/validation_types.py index 15751c223aa..1e4925e1d08 100644 --- a/litellm/types/proxy/policy_engine/validation_types.py +++ b/litellm/types/proxy/policy_engine/validation_types.py @@ -6,7 +6,7 @@ validation results. """ from enum import Enum -from typing import Any, Dict, List, Optional +from typing import Any from pydantic import BaseModel, ConfigDict, Field @@ -32,11 +32,11 @@ class PolicyValidationError(BaseModel): policy_name: str = Field(description="Name of the policy with the issue.") error_type: PolicyValidationErrorType = Field(description="Type of validation error.") message: str = Field(description="Human-readable error message.") - field: Optional[str] = Field( + field: str | None = Field( default=None, description="Specific field that caused the error (e.g., 'guardrails.add', 'scope.teams').", ) - value: Optional[str] = Field( + value: str | None = Field( default=None, description="The invalid value that caused the error.", ) @@ -54,11 +54,11 @@ class PolicyValidationResponse(BaseModel): """ valid: bool = Field(description="True if the policy configuration is valid.") - errors: List[PolicyValidationError] = Field( + errors: list[PolicyValidationError] = Field( default_factory=list, description="List of blocking validation errors.", ) - warnings: List[PolicyValidationError] = Field( + warnings: list[PolicyValidationError] = Field( default_factory=list, description="List of non-blocking validation warnings.", ) @@ -71,7 +71,7 @@ class PolicyValidateRequest(BaseModel): Request body for the /policy/validate endpoint. """ - policies: Dict[str, Any] = Field( + policies: dict[str, Any] = Field( description="Policy configuration to validate. Map of policy names to policy definitions." ) diff --git a/litellm/types/proxy/prompt_endpoints.py b/litellm/types/proxy/prompt_endpoints.py index 609a6e55c9e..ba2c5d3c373 100644 --- a/litellm/types/proxy/prompt_endpoints.py +++ b/litellm/types/proxy/prompt_endpoints.py @@ -1,9 +1,9 @@ -from typing import Any, Dict, List, Optional +from typing import Any from pydantic import BaseModel class TestPromptRequest(BaseModel): dotprompt_content: str - prompt_variables: Optional[Dict[str, Any]] = None - conversation_history: Optional[List[Dict[str, str]]] = None + prompt_variables: dict[str, Any] | None = None + conversation_history: list[dict[str, str]] | None = None diff --git a/litellm/types/proxy/public_endpoints/public_endpoints.py b/litellm/types/proxy/public_endpoints/public_endpoints.py index caa9a978530..dbe34926f4b 100644 --- a/litellm/types/proxy/public_endpoints/public_endpoints.py +++ b/litellm/types/proxy/public_endpoints/public_endpoints.py @@ -1,57 +1,57 @@ -from typing import Dict, List, Literal, Optional, Union, Any +from typing import Any, Literal from pydantic import BaseModel class PublicModelHubInfo(BaseModel): docs_title: str - custom_docs_description: Optional[str] + custom_docs_description: str | None litellm_version: str # Supports both old format (Dict[str, str]) and new format (Dict[str, Dict[str, Any]]) # New format: { "displayName": { "url": "...", "index": 0 } } # Old format: { "displayName": "url" } (for backward compatibility) - useful_links: Optional[Dict[str, Union[str, Dict[str, Any]]]] + useful_links: dict[str, str | dict[str, Any]] | None class ProviderCredentialField(BaseModel): key: str label: str - placeholder: Optional[str] = None - tooltip: Optional[str] = None + placeholder: str | None = None + tooltip: str | None = None required: bool = False field_type: Literal["text", "password", "select", "upload", "textarea"] = "text" - options: Optional[List[str]] = None - default_value: Optional[str] = None + options: list[str] | None = None + default_value: str | None = None class ProviderCreateInfo(BaseModel): provider: str provider_display_name: str litellm_provider: str - credential_fields: List[ProviderCredentialField] - default_model_placeholder: Optional[str] = None + credential_fields: list[ProviderCredentialField] + default_model_placeholder: str | None = None class AgentCredentialField(BaseModel): key: str label: str - placeholder: Optional[str] = None - tooltip: Optional[str] = None + placeholder: str | None = None + tooltip: str | None = None required: bool = False field_type: Literal["text", "password", "select", "upload", "textarea"] = "text" - options: Optional[List[str]] = None - default_value: Optional[str] = None - include_in_litellm_params: Optional[bool] = None + options: list[str] | None = None + default_value: str | None = None + include_in_litellm_params: bool | None = None class AgentCreateInfo(BaseModel): agent_type: str agent_type_display_name: str - description: Optional[str] = None - logo_url: Optional[str] = None - credential_fields: List[AgentCredentialField] - litellm_params_template: Optional[Dict[str, str]] = None - model_template: Optional[str] = None + description: str | None = None + logo_url: str | None = None + credential_fields: list[AgentCredentialField] + litellm_params_template: dict[str, str] | None = None + model_template: str | None = None class EndpointProvider(BaseModel): @@ -63,8 +63,8 @@ class SupportedEndpoint(BaseModel): key: str label: str endpoint: str - providers: List[EndpointProvider] + providers: list[EndpointProvider] class SupportedEndpointsResponse(BaseModel): - endpoints: List[SupportedEndpoint] + endpoints: list[SupportedEndpoint] diff --git a/litellm/types/proxy/ui_sso.py b/litellm/types/proxy/ui_sso.py index bef200952ba..0d7e0b99cf0 100644 --- a/litellm/types/proxy/ui_sso.py +++ b/litellm/types/proxy/ui_sso.py @@ -1,4 +1,4 @@ -from typing import Literal, Optional +from typing import Literal from typing_extensions import TypedDict @@ -10,7 +10,7 @@ class ReturnedUITokenObject(TypedDict): user_id: str key: str - user_email: Optional[str] + user_email: str | None user_role: str login_method: Literal["sso", "username_password"] premium_user: bool @@ -24,6 +24,6 @@ class ParsedOpenIDResult(TypedDict, total=False): Parsed OpenID result """ - user_email: Optional[str] - user_id: Optional[str] - user_role: Optional[str] + user_email: str | None + user_id: str | None + user_role: str | None diff --git a/litellm/types/proxy/vantage_endpoints.py b/litellm/types/proxy/vantage_endpoints.py index 60171f1ad57..83bd5c4c61b 100644 --- a/litellm/types/proxy/vantage_endpoints.py +++ b/litellm/types/proxy/vantage_endpoints.py @@ -3,7 +3,7 @@ Vantage endpoint types for LiteLLM Proxy """ from datetime import datetime -from typing import Any, Dict, Optional +from typing import Any from pydantic import BaseModel, Field, field_validator @@ -36,18 +36,18 @@ class VantageInitResponse(BaseModel): class VantageExportRequest(BaseModel): """Request model for Vantage export operations (actual export, no default limit)""" - limit: Optional[int] = Field( + limit: int | None = Field( None, description="Optional limit on number of records to export (default: no limit)", ) - start_time_utc: Optional[datetime] = Field(None, description="Start time for data export in UTC") - end_time_utc: Optional[datetime] = Field(None, description="End time for data export in UTC") + start_time_utc: datetime | None = Field(None, description="Start time for data export in UTC") + end_time_utc: datetime | None = Field(None, description="End time for data export in UTC") class VantageDryRunRequest(BaseModel): """Request model for Vantage dry-run operations (capped for preview)""" - limit: Optional[int] = Field(500, description="Limit on number of records to preview (default: 500)") + limit: int | None = Field(500, description="Limit on number of records to preview (default: 500)") class VantageExportResponse(BaseModel): @@ -55,37 +55,37 @@ class VantageExportResponse(BaseModel): message: str status: str - dry_run_data: Optional[Dict[str, Any]] = Field( + dry_run_data: dict[str, Any] | None = Field( None, description="Dry run data including usage data and FOCUS transformed data" ) - summary: Optional[Dict[str, Any]] = Field(None, description="Summary statistics for dry run") + summary: dict[str, Any] | None = Field(None, description="Summary statistics for dry run") class VantageSettingsView(BaseModel): """Response model for viewing Vantage settings with masked API key""" - api_key_masked: Optional[str] = Field( + api_key_masked: str | None = Field( None, description="Masked API key showing only first 4 and last 4 characters", ) - integration_token_masked: Optional[str] = Field( + integration_token_masked: str | None = Field( None, description="Masked integration token showing only first 4 and last 4 characters", ) - base_url: Optional[str] = Field(None, description="Vantage API base URL") - status: Optional[str] = Field(None, description="Configuration status") + base_url: str | None = Field(None, description="Vantage API base URL") + status: str | None = Field(None, description="Configuration status") class VantageSettingsUpdate(BaseModel): """Request model for updating Vantage settings""" - api_key: Optional[str] = Field(None, description="New Vantage API key for authentication") - integration_token: Optional[str] = Field(None, description="New Vantage integration token") - base_url: Optional[str] = Field(None, description="New Vantage API base URL") + api_key: str | None = Field(None, description="New Vantage API key for authentication") + integration_token: str | None = Field(None, description="New Vantage integration token") + base_url: str | None = Field(None, description="New Vantage API base URL") @field_validator("api_key", "integration_token") @classmethod - def must_be_non_empty(cls, v: Optional[str]) -> Optional[str]: + def must_be_non_empty(cls, v: str | None) -> str | None: if v is not None and not v.strip(): raise ValueError("must be a non-empty string") return v diff --git a/litellm/types/rag.py b/litellm/types/rag.py index 5d2ae897a37..d1b411d8c04 100644 --- a/litellm/types/rag.py +++ b/litellm/types/rag.py @@ -2,7 +2,7 @@ Type definitions for RAG (Retrieval Augmented Generation) Ingest API. """ -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Literal from pydantic import BaseModel, ConfigDict from typing_extensions import TypedDict @@ -19,7 +19,7 @@ class RAGChunkingStrategy(TypedDict, total=False): chunk_size: int # Maximum size of chunks (default: 1000) chunk_overlap: int # Overlap between chunks (default: 200) - separators: Optional[List[str]] # Custom separators for splitting + separators: list[str] | None # Custom separators for splitting class RAGIngestOCROptions(TypedDict, total=False): @@ -49,13 +49,13 @@ class OpenAIVectorStoreOptions(TypedDict, total=False): """ custom_llm_provider: Literal["openai"] - vector_store_id: Optional[str] # Existing VS ID (auto-creates if not provided) - ttl_days: Optional[int] # Time-to-live in days for indexed content + vector_store_id: str | None # Existing VS ID (auto-creates if not provided) + ttl_days: int | None # Time-to-live in days for indexed content # Credentials (loaded from litellm.credential_list if litellm_credential_name is provided) - litellm_credential_name: Optional[str] # Credential name to load from litellm.credential_list - api_key: Optional[str] # Direct API key (alternative to litellm_credential_name) - api_base: Optional[str] # Direct API base (alternative to litellm_credential_name) + litellm_credential_name: str | None # Credential name to load from litellm.credential_list + api_key: str | None # Direct API key (alternative to litellm_credential_name) + api_base: str | None # Direct API base (alternative to litellm_credential_name) class BedrockVectorStoreOptions(TypedDict, total=False): @@ -76,30 +76,30 @@ class BedrockVectorStoreOptions(TypedDict, total=False): """ custom_llm_provider: Literal["bedrock"] - vector_store_id: Optional[str] # Existing KB ID (auto-creates if not provided) + vector_store_id: str | None # Existing KB ID (auto-creates if not provided) # Bedrock-specific options - s3_bucket: Optional[str] # S3 bucket (auto-created if not provided) - s3_prefix: Optional[str] # S3 key prefix (default: "data/") - embedding_model: Optional[str] # Embedding model (default: amazon.titan-embed-text-v2:0) - data_source_id: Optional[str] # For existing KB: override auto-detected DS - wait_for_ingestion: Optional[bool] # Wait for completion (default: False - returns immediately) - ingestion_timeout: Optional[int] # Timeout in seconds if wait_for_ingestion=True (default: 300) + s3_bucket: str | None # S3 bucket (auto-created if not provided) + s3_prefix: str | None # S3 key prefix (default: "data/") + embedding_model: str | None # Embedding model (default: amazon.titan-embed-text-v2:0) + data_source_id: str | None # For existing KB: override auto-detected DS + wait_for_ingestion: bool | None # Wait for completion (default: False - returns immediately) + ingestion_timeout: int | None # Timeout in seconds if wait_for_ingestion=True (default: 300) # Credentials (loaded from litellm.credential_list if litellm_credential_name is provided) - litellm_credential_name: Optional[str] # Credential name to load from litellm.credential_list + litellm_credential_name: str | None # Credential name to load from litellm.credential_list # AWS auth (uses BaseAWSLLM) - aws_access_key_id: Optional[str] - aws_secret_access_key: Optional[str] - aws_session_token: Optional[str] - aws_region_name: Optional[str] # default: us-west-2 - aws_role_name: Optional[str] - aws_session_name: Optional[str] - aws_profile_name: Optional[str] - aws_web_identity_token: Optional[str] - aws_sts_endpoint: Optional[str] - aws_external_id: Optional[str] + aws_access_key_id: str | None + aws_secret_access_key: str | None + aws_session_token: str | None + aws_region_name: str | None # default: us-west-2 + aws_role_name: str | None + aws_session_name: str | None + aws_profile_name: str | None + aws_web_identity_token: str | None + aws_sts_endpoint: str | None + aws_external_id: str | None class VertexAIVectorStoreOptions(TypedDict, total=False): @@ -119,14 +119,14 @@ class VertexAIVectorStoreOptions(TypedDict, total=False): vector_store_id: str # RAG corpus ID (required for Vertex AI) # GCP config - vertex_project: Optional[str] # GCP project ID (uses env VERTEXAI_PROJECT if not set) - vertex_location: Optional[str] # GCP region (default: us-central1) - vertex_credentials: Optional[str] # Path to credentials JSON (uses ADC if not set) - gcs_bucket: Optional[str] # GCS bucket for file uploads (uses env GCS_BUCKET_NAME if not set) + vertex_project: str | None # GCP project ID (uses env VERTEXAI_PROJECT if not set) + vertex_location: str | None # GCP region (default: us-central1) + vertex_credentials: str | None # Path to credentials JSON (uses ADC if not set) + gcs_bucket: str | None # GCS bucket for file uploads (uses env GCS_BUCKET_NAME if not set) # Import settings - wait_for_import: Optional[bool] # Wait for import to complete (default: True) - import_timeout: Optional[int] # Timeout in seconds (default: 600) + wait_for_import: bool | None # Wait for import to complete (default: True) + import_timeout: int | None # Timeout in seconds (default: 600) class S3VectorsVectorStoreOptions(TypedDict, total=False): @@ -150,36 +150,33 @@ class S3VectorsVectorStoreOptions(TypedDict, total=False): custom_llm_provider: Literal["s3_vectors"] vector_bucket_name: str # Required - S3 vector bucket name - index_name: Optional[str] # Vector index name (auto-creates if not provided) + index_name: str | None # Vector index name (auto-creates if not provided) # Index configuration (for auto-creation) - dimension: Optional[int] # Vector dimension (auto-detected from embedding model, or default: 1024) - distance_metric: Optional[Literal["cosine", "euclidean"]] # Default: cosine - non_filterable_metadata_keys: Optional[List[str]] # Keys excluded from filtering (e.g., ["source_text"]) + dimension: int | None # Vector dimension (auto-detected from embedding model, or default: 1024) + distance_metric: Literal["cosine", "euclidean"] | None # Default: cosine + non_filterable_metadata_keys: list[str] | None # Keys excluded from filtering (e.g., ["source_text"]) # Credentials (loaded from litellm.credential_list if litellm_credential_name is provided) - litellm_credential_name: Optional[str] # Credential name to load from litellm.credential_list + litellm_credential_name: str | None # Credential name to load from litellm.credential_list # AWS auth (uses BaseAWSLLM) - aws_access_key_id: Optional[str] - aws_secret_access_key: Optional[str] - aws_session_token: Optional[str] - aws_region_name: Optional[str] # default: us-west-2 - aws_role_name: Optional[str] - aws_session_name: Optional[str] - aws_profile_name: Optional[str] - aws_web_identity_token: Optional[str] - aws_sts_endpoint: Optional[str] - aws_external_id: Optional[str] + aws_access_key_id: str | None + aws_secret_access_key: str | None + aws_session_token: str | None + aws_region_name: str | None # default: us-west-2 + aws_role_name: str | None + aws_session_name: str | None + aws_profile_name: str | None + aws_web_identity_token: str | None + aws_sts_endpoint: str | None + aws_external_id: str | None # Union type for vector store options -RAGIngestVectorStoreOptions = Union[ - OpenAIVectorStoreOptions, - BedrockVectorStoreOptions, - VertexAIVectorStoreOptions, - S3VectorsVectorStoreOptions, -] +RAGIngestVectorStoreOptions = ( + OpenAIVectorStoreOptions | BedrockVectorStoreOptions | VertexAIVectorStoreOptions | S3VectorsVectorStoreOptions +) class RAGIngestOptions(TypedDict, total=False): @@ -210,10 +207,10 @@ class RAGIngestOptions(TypedDict, total=False): } """ - name: Optional[str] # Optional pipeline name for logging - ocr: Optional[RAGIngestOCROptions] # Optional OCR step - chunking_strategy: Optional[RAGChunkingStrategy] # RecursiveCharacterTextSplitter args - embedding: Optional[RAGIngestEmbeddingOptions] # Embedding model config + name: str | None # Optional pipeline name for logging + ocr: RAGIngestOCROptions | None # Optional OCR step + chunking_strategy: RAGChunkingStrategy | None # RecursiveCharacterTextSplitter args + embedding: RAGIngestEmbeddingOptions | None # Embedding model config vector_store: RAGIngestVectorStoreOptions # OpenAI or Bedrock config @@ -223,16 +220,16 @@ class RAGIngestResponse(TypedDict, total=False): id: str # Unique ingest job ID status: Literal["completed", "in_progress", "failed"] vector_store_id: str # The vector store ID (created or existing) - file_id: Optional[str] # The file ID in the vector store - error: Optional[str] # Error message if status is "failed" + file_id: str | None # The file ID in the vector store + error: str | None # Error message if status is "failed" class RAGIngestRequest(BaseModel): """Request body for RAG ingest API (for validation).""" - file_url: Optional[str] = None # URL to fetch file from - file_id: Optional[str] = None # Existing file ID - ingest_options: Dict[str, Any] # RAGIngestOptions as dict for flexibility + file_url: str | None = None # URL to fetch file from + file_id: str | None = None # Existing file ID + ingest_options: dict[str, Any] # RAGIngestOptions as dict for flexibility model_config = ConfigDict(extra="allow") # Allow additional fields @@ -243,7 +240,7 @@ class RAGRetrievalConfig(TypedDict, total=False): vector_store_id: str custom_llm_provider: str top_k: int # max results from vector store - filters: Optional[Dict[str, Any]] # optional - vector store filters + filters: dict[str, Any] | None # optional - vector store filters class RAGRerankConfig(TypedDict, total=False): @@ -252,22 +249,20 @@ class RAGRerankConfig(TypedDict, total=False): enabled: bool model: str top_n: int # final number of chunks after reranking - return_documents: Optional[bool] + return_documents: bool | None class RAGQueryRequest(BaseModel): """Request body for RAG query API.""" model: str - messages: List[Any] + messages: list[Any] retrieval_config: RAGRetrievalConfig - rerank: Optional[RAGRerankConfig] = None - stream: Optional[bool] = False + rerank: RAGRerankConfig | None = None + stream: bool | None = False model_config = ConfigDict(extra="allow") class RAGQueryResponse(ModelResponse): """Response from RAG query API.""" - - pass diff --git a/litellm/types/realtime.py b/litellm/types/realtime.py index 0823107c63d..15238f7e13f 100644 --- a/litellm/types/realtime.py +++ b/litellm/types/realtime.py @@ -1,7 +1,7 @@ -from typing import Any, Dict, Final, List, Literal, Optional, Union +from typing import Any, Literal from pydantic import BaseModel -from typing_extensions import TypedDict # noqa: F401 – re-exported +from typing_extensions import TypedDict from .llms.openai import ( OpenAIRealtimeEvents, @@ -13,42 +13,42 @@ ALL_DELTA_TYPES = Literal["text", "audio"] class RealtimeResponseTransformInput(TypedDict): - session_configuration_request: Optional[str] - current_output_item_id: Optional[ - str - ] # used to check if this is a new content.delta or a continuation of a previous content.delta - current_response_id: Optional[ - str - ] # used to check if this is a new content.delta or a continuation of a previous content.delta - current_delta_chunks: Optional[List[OpenAIRealtimeResponseDelta]] - current_item_chunks: Optional[List[OpenAIRealtimeOutputItemDone]] - current_conversation_id: Optional[str] - current_delta_type: Optional[ALL_DELTA_TYPES] + session_configuration_request: str | None + current_output_item_id: ( + str | None + ) # used to check if this is a new content.delta or a continuation of a previous content.delta + current_response_id: ( + str | None + ) # used to check if this is a new content.delta or a continuation of a previous content.delta + current_delta_chunks: list[OpenAIRealtimeResponseDelta] | None + current_item_chunks: list[OpenAIRealtimeOutputItemDone] | None + current_conversation_id: str | None + current_delta_type: ALL_DELTA_TYPES | None class RealtimeResponseTypedDict(TypedDict): - response: Union[OpenAIRealtimeEvents, List[OpenAIRealtimeEvents]] - current_output_item_id: Optional[str] - current_response_id: Optional[str] - current_delta_chunks: Optional[List[OpenAIRealtimeResponseDelta]] - current_conversation_id: Optional[str] - current_item_chunks: Optional[List[OpenAIRealtimeOutputItemDone]] - current_delta_type: Optional[ALL_DELTA_TYPES] - session_configuration_request: Optional[str] + response: OpenAIRealtimeEvents | list[OpenAIRealtimeEvents] + current_output_item_id: str | None + current_response_id: str | None + current_delta_chunks: list[OpenAIRealtimeResponseDelta] | None + current_conversation_id: str | None + current_item_chunks: list[OpenAIRealtimeOutputItemDone] | None + current_delta_type: ALL_DELTA_TYPES | None + session_configuration_request: str | None class RealtimeModalityResponseTransformOutput(TypedDict): - returned_message: List[OpenAIRealtimeEvents] - current_output_item_id: Optional[str] - current_response_id: Optional[str] - current_conversation_id: Optional[str] - current_delta_chunks: Optional[List[OpenAIRealtimeResponseDelta]] - current_delta_type: Optional[ALL_DELTA_TYPES] + returned_message: list[OpenAIRealtimeEvents] + current_output_item_id: str | None + current_response_id: str | None + current_conversation_id: str | None + current_delta_chunks: list[OpenAIRealtimeResponseDelta] | None + current_delta_type: ALL_DELTA_TYPES | None class RealtimeQueryParams(TypedDict, total=False): model: str - intent: Optional[str] + intent: str | None # Add more fields as needed @@ -60,8 +60,8 @@ class RealtimeQueryParams(TypedDict, total=False): class RealtimeExpiresAfter(BaseModel): """Expiration config for a client secret.""" - anchor: Optional[str] = "created_at" - seconds: Optional[int] = None + anchor: str | None = "created_at" + seconds: int | None = None class RealtimeSessionConfig(BaseModel): @@ -75,18 +75,18 @@ class RealtimeSessionConfig(BaseModel): model_config = {"extra": "allow"} - type: Optional[str] = None - model: Optional[str] = None - instructions: Optional[str] = None - audio: Optional[Dict[str, Any]] = None - include: Optional[List[str]] = None - max_output_tokens: Optional[Union[int, str]] = None - output_modalities: Optional[List[str]] = None - tool_choice: Optional[Any] = None - tools: Optional[List[Dict[str, Any]]] = None - tracing: Optional[Any] = None - truncation: Optional[Any] = None - prompt: Optional[Dict[str, Any]] = None + type: str | None = None + model: str | None = None + instructions: str | None = None + audio: dict[str, Any] | None = None + include: list[str] | None = None + max_output_tokens: int | str | None = None + output_modalities: list[str] | None = None + tool_choice: Any | None = None + tools: list[dict[str, Any]] | None = None + tracing: Any | None = None + truncation: Any | None = None + prompt: dict[str, Any] | None = None class RealtimeClientSecretRequest(BaseModel): @@ -97,10 +97,10 @@ class RealtimeClientSecretRequest(BaseModel): session.model is absent (LiteLLM extension, not forwarded to OpenAI). """ - expires_after: Optional[RealtimeExpiresAfter] = None - session: Optional[RealtimeSessionConfig] = None + expires_after: RealtimeExpiresAfter | None = None + session: RealtimeSessionConfig | None = None # LiteLLM-only routing hint — stripped before forwarding upstream - model: Optional[str] = None + model: str | None = None class RealtimeClientSecretResponse(BaseModel): @@ -112,9 +112,9 @@ class RealtimeClientSecretResponse(BaseModel): The `session` field is kept as a raw dict so unknown fields pass through. """ - expires_at: Optional[int] = None + expires_at: int | None = None value: str - session: Optional[Dict[str, Any]] = None + session: dict[str, Any] | None = None class RealtimeTranscriptionSessionRequest(BaseModel): @@ -130,10 +130,10 @@ class RealtimeTranscriptionSessionRequest(BaseModel): model_config = {"extra": "allow"} # LiteLLM-only routing hint — stripped before forwarding upstream. - model: Optional[str] = None - input_audio_transcription: Optional[Dict[str, Any]] = None + model: str | None = None + input_audio_transcription: dict[str, Any] | None = None - def resolved_model(self) -> Optional[str]: + def resolved_model(self) -> str | None: if self.model: return self.model if self.input_audio_transcription: @@ -151,4 +151,4 @@ class RealtimeTranscriptionSessionResponse(BaseModel): model_config = {"extra": "allow"} - client_secret: Optional[Dict[str, Any]] = None + client_secret: dict[str, Any] | None = None diff --git a/litellm/types/rerank.py b/litellm/types/rerank.py index 9b0629156c1..903781b2ccd 100644 --- a/litellm/types/rerank.py +++ b/litellm/types/rerank.py @@ -4,8 +4,6 @@ https://docs.cohere.com/reference/rerank """ -from typing import List, Optional, Union - from pydantic import BaseModel, PrivateAttr from typing_extensions import Required, TypedDict @@ -13,43 +11,43 @@ from typing_extensions import Required, TypedDict class RerankRequest(BaseModel): model: str query: str - top_n: Optional[int] = None - documents: List[Union[str, dict]] - rank_fields: Optional[List[str]] = None - return_documents: Optional[bool] = None - max_chunks_per_doc: Optional[int] = None - max_tokens_per_doc: Optional[int] = None + top_n: int | None = None + documents: list[str | dict] + rank_fields: list[str] | None = None + return_documents: bool | None = None + max_chunks_per_doc: int | None = None + max_tokens_per_doc: int | None = None # Optional task/query instruction passed through to providers that support it # (e.g. hosted vLLM / Qwen3-Reranker, DeepInfra). Omitted from the outgoing # request when None, so this is fully backward-compatible. - instruction: Optional[str] = None + instruction: str | None = None class OptionalRerankParams(TypedDict, total=False): query: str - top_n: Optional[int] - documents: List[Union[str, dict]] - rank_fields: Optional[List[str]] - return_documents: Optional[bool] - max_chunks_per_doc: Optional[int] - max_tokens_per_doc: Optional[int] - instruction: Optional[str] + top_n: int | None + documents: list[str | dict] + rank_fields: list[str] | None + return_documents: bool | None + max_chunks_per_doc: int | None + max_tokens_per_doc: int | None + instruction: str | None class RerankBilledUnits(TypedDict, total=False): - search_units: Optional[int] - total_tokens: Optional[int] + search_units: int | None + total_tokens: int | None class RerankTokens(TypedDict, total=False): - input_tokens: Optional[int] - output_tokens: Optional[int] + input_tokens: int | None + output_tokens: int | None class RerankResponseMeta(TypedDict, total=False): - api_version: Optional[dict] - billed_units: Optional[RerankBilledUnits] - tokens: Optional[RerankTokens] + api_version: dict | None + billed_units: RerankBilledUnits | None + tokens: RerankTokens | None class RerankResponseDocument(TypedDict): @@ -63,9 +61,9 @@ class RerankResponseResult(TypedDict, total=False): class RerankResponse(BaseModel): - id: Optional[str] = None - results: Optional[List[RerankResponseResult]] = None # Contains index and relevance_score - meta: Optional[RerankResponseMeta] = None # Contains api_version and billed_units + id: str | None = None + results: list[RerankResponseResult] | None = None # Contains index and relevance_score + meta: RerankResponseMeta | None = None # Contains api_version and billed_units # Define private attributes using PrivateAttr _hidden_params: dict = PrivateAttr(default_factory=dict) @@ -76,5 +74,5 @@ class RerankResponse(BaseModel): def get(self, key, default=None): return self.__dict__.get(key, default) - def __contains__(self, key): + def __contains__(self, key) -> bool: return key in self.__dict__ diff --git a/litellm/types/responses/main.py b/litellm/types/responses/main.py index aeebdb0a6f7..00635a8e1ef 100644 --- a/litellm/types/responses/main.py +++ b/litellm/types/responses/main.py @@ -1,41 +1,40 @@ -from typing import Final, List, Literal, Optional, Union +from typing import Final, Literal, Optional, Union from openai.types.responses.response_function_tool_call import ResponseFunctionToolCall from pydantic import PrivateAttr -from typing_extensions import Any, List, Optional, TypedDict +from typing_extensions import Any, TypedDict from litellm.types.llms.base import BaseLiteLLMOpenAIResponseObject -Phase = Optional[Literal["commentary", "final_answer"]] +Phase = Literal["commentary", "final_answer"] | None class GenericResponseOutputItemContentAnnotation(BaseLiteLLMOpenAIResponseObject): """Annotation for content in a message""" - type: Optional[str] - start_index: Optional[int] - end_index: Optional[int] - url: Optional[str] - title: Optional[str] - pass + type: str | None + start_index: int | None + end_index: int | None + url: str | None + title: str | None class OutputText(BaseLiteLLMOpenAIResponseObject): """Text output content from an assistant message""" - type: Optional[str] # "output_text" - text: Optional[str] - annotations: Optional[List[GenericResponseOutputItemContentAnnotation]] + type: str | None # "output_text" + text: str | None + annotations: list[GenericResponseOutputItemContentAnnotation] | None class OutputFunctionToolCall(BaseLiteLLMOpenAIResponseObject): """A tool call to run a function""" - arguments: Optional[str] - call_id: Optional[str] - name: Optional[str] - type: Optional[str] # "function_call" - id: Optional[str] + arguments: str | None + call_id: str | None + name: str | None + type: str | None # "function_call" + id: str | None status: Literal["in_progress", "completed", "incomplete"] phase: Phase = None @@ -46,7 +45,7 @@ class OutputImageGenerationCall(BaseLiteLLMOpenAIResponseObject): type: Literal["image_generation_call"] id: str status: Literal["in_progress", "completed", "incomplete", "failed"] - result: Optional[str] # Base64 encoded image data (without data:image prefix) + result: str | None # Base64 encoded image data (without data:image prefix) class OutputCodeInterpreterCallLog(BaseLiteLLMOpenAIResponseObject): @@ -61,15 +60,15 @@ class OutputCodeInterpreterCall(BaseLiteLLMOpenAIResponseObject): type: Literal["code_interpreter_call"] id: str - code: Optional[str] - container_id: Optional[str] + code: str | None + container_id: str | None status: Literal["in_progress", "completed", "incomplete", "failed"] - outputs: Optional[List[OutputCodeInterpreterCallLog]] + outputs: list[OutputCodeInterpreterCallLog] | None def build_code_interpreter_log_outputs( content: Any, -) -> Optional[List[OutputCodeInterpreterCallLog]]: +) -> list[OutputCodeInterpreterCallLog] | None: """Convert Anthropic bash_code_execution stdout/stderr to log outputs. Shared by streaming (handler.py) and non-streaming (transformation.py) paths. @@ -95,10 +94,10 @@ class CustomToolCallOutputItem(BaseLiteLLMOpenAIResponseObject): type: Literal["custom_tool_call"] call_id: str - id: Optional[str] = None + id: str | None = None name: str input: str - status: Optional[Literal["in_progress", "completed", "incomplete"]] = None + status: Literal["in_progress", "completed", "incomplete"] | None = None class GenericResponseOutputItem(BaseLiteLLMOpenAIResponseObject): @@ -111,7 +110,7 @@ class GenericResponseOutputItem(BaseLiteLLMOpenAIResponseObject): id: str status: str # "completed", "in_progress", etc. role: str # "assistant", "user", etc. - content: List[OutputText] + content: list[OutputText] phase: Phase = None @@ -126,9 +125,9 @@ class DeleteResponseResult(BaseLiteLLMOpenAIResponseObject): } """ - id: Optional[str] - object: Optional[str] - deleted: Optional[bool] + id: str | None + object: str | None + deleted: bool | None # Define private attributes using PrivateAttr _hidden_params: dict = PrivateAttr(default_factory=dict) @@ -137,6 +136,6 @@ class DeleteResponseResult(BaseLiteLLMOpenAIResponseObject): class DecodedResponseId(TypedDict, total=False): """Structure representing a decoded response ID""" - custom_llm_provider: Optional[str] - model_id: Optional[str] + custom_llm_provider: str | None + model_id: str | None response_id: str diff --git a/litellm/types/router.py b/litellm/types/router.py index 21bed84a3a1..43b5d20e80d 100644 --- a/litellm/types/router.py +++ b/litellm/types/router.py @@ -5,7 +5,7 @@ litellm.Router Types - includes RouterConfig, UpdateRouterConfig, ModelInfo etc import datetime import enum from dataclasses import dataclass -from typing import Any, Dict, Final, Generic, get_type_hints, List, Literal, Optional, Tuple, TypeVar, Union +from typing import Any, Final, Generic, Literal, TypeVar, get_type_hints import httpx from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -24,12 +24,12 @@ class ConfigurableClientsideParamsCustomAuth(TypedDict): api_base: str -CONFIGURABLE_CLIENTSIDE_AUTH_PARAMS = Optional[List[Union[str, ConfigurableClientsideParamsCustomAuth]]] +CONFIGURABLE_CLIENTSIDE_AUTH_PARAMS = list[str | ConfigurableClientsideParamsCustomAuth] | None class ModelConfig(BaseModel): model_name: str - litellm_params: Union[CompletionRequest, EmbeddingRequest] + litellm_params: CompletionRequest | EmbeddingRequest tpm: int rpm: int @@ -42,41 +42,41 @@ class RoutingGroup(BaseModel): """ group_name: str - models: List[str] + models: list[str] routing_strategy: str - routing_strategy_args: Optional[dict] = None + routing_strategy_args: dict | None = None model_config = ConfigDict(protected_namespaces=()) class RouterConfig(BaseModel): - model_list: List[ModelConfig] + model_list: list[ModelConfig] - redis_url: Optional[str] = None - redis_host: Optional[str] = None - redis_port: Optional[int] = None - redis_password: Optional[str] = None + redis_url: str | None = None + redis_host: str | None = None + redis_port: int | None = None + redis_password: str | None = None - cache_responses: Optional[bool] = False - cache_kwargs: Optional[Dict] = {} - caching_groups: Optional[List[Tuple[str, List[str]]]] = None - client_ttl: Optional[int] = 3600 - num_retries: Optional[int] = 0 - timeout: Optional[float] = None - default_litellm_params: Optional[Dict[str, str]] = {} - set_verbose: Optional[bool] = False - fallbacks: Optional[List] = [] - allowed_fails: Optional[int] = None - context_window_fallbacks: Optional[List] = [] - model_group_alias: Optional[Dict[str, List[str]]] = {} - retry_after: Optional[int] = 0 + cache_responses: bool | None = False + cache_kwargs: dict | None = {} + caching_groups: list[tuple[str, list[str]]] | None = None + client_ttl: int | None = 3600 + num_retries: int | None = 0 + timeout: float | None = None + default_litellm_params: dict[str, str] | None = {} + set_verbose: bool | None = False + fallbacks: list | None = [] + allowed_fails: int | None = None + context_window_fallbacks: list | None = [] + model_group_alias: dict[str, list[str]] | None = {} + retry_after: int | None = 0 routing_strategy: Literal[ "simple-shuffle", "least-busy", "usage-based-routing", "latency-based-routing", ] = "simple-shuffle" - routing_groups: Optional[List[RoutingGroup]] = None + routing_groups: list[RoutingGroup] | None = None model_config = ConfigDict(protected_namespaces=()) @@ -89,12 +89,12 @@ class RetryPolicy(BaseModel): https://docs.litellm.ai/docs/exception_mapping """ - BadRequestErrorRetries: Optional[int] = None - AuthenticationErrorRetries: Optional[int] = None - TimeoutErrorRetries: Optional[int] = None - RateLimitErrorRetries: Optional[int] = None - ContentPolicyViolationErrorRetries: Optional[int] = None - InternalServerErrorRetries: Optional[int] = None + BadRequestErrorRetries: int | None = None + AuthenticationErrorRetries: int | None = None + TimeoutErrorRetries: int | None = None + RateLimitErrorRetries: int | None = None + ContentPolicyViolationErrorRetries: int | None = None + InternalServerErrorRetries: int | None = None class UpdateRouterConfig(BaseModel): @@ -102,51 +102,51 @@ class UpdateRouterConfig(BaseModel): Set of params that you can modify via `router.update_settings()`. """ - routing_strategy_args: Optional[dict] = None - routing_strategy: Optional[str] = None - routing_groups: Optional[List[RoutingGroup]] = None - retry_policy: Optional[RetryPolicy] = None - model_group_retry_policy: Optional[Dict[str, RetryPolicy]] = None - model_group_affinity_config: Optional[Dict[str, List[str]]] = None - allowed_fails: Optional[int] = None - cooldown_time: Optional[float] = None - num_retries: Optional[int] = None - timeout: Optional[float] = None - max_retries: Optional[int] = None - retry_after: Optional[float] = None - fallbacks: Optional[List[dict]] = None - context_window_fallbacks: Optional[List[dict]] = None - model_group_alias: Optional[Dict[str, Union[str, Dict]]] = {} - enable_tag_filtering: Optional[bool] = None + routing_strategy_args: dict | None = None + routing_strategy: str | None = None + routing_groups: list[RoutingGroup] | None = None + retry_policy: RetryPolicy | None = None + model_group_retry_policy: dict[str, RetryPolicy] | None = None + model_group_affinity_config: dict[str, list[str]] | None = None + allowed_fails: int | None = None + cooldown_time: float | None = None + num_retries: int | None = None + timeout: float | None = None + max_retries: int | None = None + retry_after: float | None = None + fallbacks: list[dict] | None = None + context_window_fallbacks: list[dict] | None = None + model_group_alias: dict[str, str | dict] | None = {} + enable_tag_filtering: bool | None = None model_config = ConfigDict(protected_namespaces=()) class ModelInfo(BaseModel): - id: Optional[str] # Allow id to be optional on input, but it will always be present as a str in the model instance + id: str | None # Allow id to be optional on input, but it will always be present as a str in the model instance db_model: bool = False # used for proxy - to separate models which are stored in the db vs. config. - updated_at: Optional[datetime.datetime] = None - updated_by: Optional[str] = None + updated_at: datetime.datetime | None = None + updated_by: str | None = None - created_at: Optional[datetime.datetime] = None - created_by: Optional[str] = None + created_at: datetime.datetime | None = None + created_by: str | None = None - base_model: Optional[str] = None # specify if the base model is azure/gpt-3.5-turbo etc for accurate cost tracking - tier: Optional[Literal["free", "paid"]] = None + base_model: str | None = None # specify if the base model is azure/gpt-3.5-turbo etc for accurate cost tracking + tier: Literal["free", "paid"] | None = None """ Team Model Specific Fields """ # the team id that this model belongs to - team_id: Optional[str] = None + team_id: str | None = None # the model_name that can be used by the team when making LLM calls - team_public_model_name: Optional[str] = None + team_public_model_name: str | None = None # admin-toggled pause flag; mirrors LiteLLM_ProxyModelTable.blocked - blocked: Optional[bool] = None + blocked: bool | None = None - def __init__(self, id: Optional[Union[str, int]] = None, **params): + def __init__(self, id: str | int | None = None, **params) -> None: if id is None: id = str(uuid.uuid4()) # Generate a UUID if id is None or not provided elif isinstance(id, int): @@ -155,7 +155,7 @@ class ModelInfo(BaseModel): model_config = ConfigDict(extra="allow") - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -167,41 +167,41 @@ class ModelInfo(BaseModel): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) class CredentialLiteLLMParams(BaseModel): - api_key: Optional[str] = None - api_base: Optional[str] = None - api_version: Optional[str] = None + api_key: str | None = None + api_base: str | None = None + api_version: str | None = None ## AZURE OAUTH ## # Without this field, ``get_deployment_credentials_with_provider`` # round-trips ``litellm_params`` through a strict Pydantic dump and # silently drops the OAuth token before the files/batch/passthrough # callers see it, breaking Azure deployments configured with # ``azure_ad_token`` instead of a static ``api_key`` (#30235). - azure_ad_token: Optional[str] = None + azure_ad_token: str | None = None ## VERTEX AI ## - vertex_project: Optional[str] = None - vertex_location: Optional[str] = None - vertex_credentials: Optional[Union[str, dict]] = None + vertex_project: str | None = None + vertex_location: str | None = None + vertex_credentials: str | dict | None = None ## UNIFIED PROJECT/REGION ## - region_name: Optional[str] = None + region_name: str | None = None ## OBJECT STORAGE (files / batches) ## - gcs_bucket_name: Optional[str] = None + gcs_bucket_name: str | None = None ## AWS BEDROCK / SAGEMAKER ## - aws_access_key_id: Optional[str] = None - aws_secret_access_key: Optional[str] = None - aws_region_name: Optional[str] = None - aws_bedrock_runtime_endpoint: Optional[str] = None - aws_bedrock_project_id: Optional[str] = None - s3_bucket_name: Optional[str] = None + aws_access_key_id: str | None = None + aws_secret_access_key: str | None = None + aws_region_name: str | None = None + aws_bedrock_runtime_endpoint: str | None = None + aws_bedrock_project_id: str | None = None + s3_bucket_name: str | None = None ## IBM WATSONX ## - watsonx_region_name: Optional[str] = None + watsonx_region_name: str | None = None _RESERVED_INIT_KEYS: Final = frozenset({"self", "params", "__class__"}) @@ -212,77 +212,75 @@ class GenericLiteLLMParams(CredentialLiteLLMParams, CustomPricingLiteLLMParams): LiteLLM Params without 'model' arg (used across completion / assistants api) """ - custom_llm_provider: Optional[str] = None - tpm: Optional[int] = None - rpm: Optional[int] = None - itpm: Optional[int] = None - otpm: Optional[int] = None - timeout: Optional[Union[float, str, httpx.Timeout]] = None # if str, pass in as os.environ/ - stream_timeout: Optional[Union[float, str]] = ( - None # timeout when making stream=True calls, if str, pass in as os.environ/ - ) - max_retries: Optional[int] = None - organization: Optional[str] = None # for openai orgs + custom_llm_provider: str | None = None + tpm: int | None = None + rpm: int | None = None + itpm: int | None = None + otpm: int | None = None + timeout: float | str | httpx.Timeout | None = None # if str, pass in as os.environ/ + stream_timeout: float | str | None = None # timeout when making stream=True calls, if str, pass in as os.environ/ + max_retries: int | None = None + organization: str | None = None # for openai orgs configurable_clientside_auth_params: CONFIGURABLE_CLIENTSIDE_AUTH_PARAMS = None - litellm_credential_name: Optional[str] = None + litellm_credential_name: str | None = None ## LOGGING PARAMS ## - litellm_trace_id: Optional[str] = None + litellm_trace_id: str | None = None - max_file_size_mb: Optional[float] = None + max_file_size_mb: float | None = None # Proxy-wide default rate limits applied to any API key using this deployment # when the key does not have a model-specific tpm/rpm limit configured. - default_api_key_tpm_limit: Optional[int] = None - default_api_key_rpm_limit: Optional[int] = None + default_api_key_tpm_limit: int | None = None + default_api_key_rpm_limit: int | None = None # Deployment budgets - max_budget: Optional[float] = None - budget_duration: Optional[str] = None - use_in_pass_through: Optional[bool] = False - use_litellm_proxy: Optional[bool] = False - use_chat_completions_api: Optional[bool] = None - use_xai_oauth: Optional[bool] = Field( + max_budget: float | None = None + budget_duration: str | None = None + use_in_pass_through: bool | None = False + use_litellm_proxy: bool | None = False + use_chat_completions_api: bool | None = None + use_xai_oauth: bool | None = Field( default=False, description="Use stored xAI OAuth credentials when no xAI API key is configured.", ) model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True) - merge_reasoning_content_in_choices: Optional[bool] = False - model_info: Optional[Dict] = None - mock_response: Optional[Union[str, ModelResponse, Exception, Any]] = None + merge_reasoning_content_in_choices: bool | None = False + model_info: dict | None = None + mock_response: str | ModelResponse | Exception | Any | None = None # tag-based routing - tags: Optional[List[str]] = None + tags: list[str] | None = None # regex patterns matched against request headers for tag routing - tag_regex: Optional[List[str]] = None + tag_regex: list[str] | None = None # auto-router params - auto_router_config_path: Optional[str] = None - auto_router_config: Optional[str] = None - auto_router_default_model: Optional[str] = None - auto_router_embedding_model: Optional[str] = None + auto_router_config_path: str | None = None + auto_router_config: str | None = None + auto_router_default_model: str | None = None + auto_router_embedding_model: str | None = None # complexity-router params - complexity_router_config: Optional[Dict] = None - complexity_router_default_model: Optional[str] = None + complexity_router_config: dict | None = None + complexity_router_default_model: str | None = None # adaptive-router params - adaptive_router_default_model: Optional[str] = None - adaptive_router_config: Optional[Dict] = None + adaptive_router_default_model: str | None = None + adaptive_router_config: dict | None = None # quality-router params - quality_router_config: Optional[Dict] = None - quality_router_default_model: Optional[str] = None + quality_router_config: dict | None = None + quality_router_default_model: str | None = None # Batch/File API Params - s3_bucket_name: Optional[str] = None - s3_encryption_key_id: Optional[str] = None - gcs_bucket_name: Optional[str] = None + s3_bucket_name: str | None = None + s3_encryption_key_id: str | None = None + gcs_bucket_name: str | None = None # Vector Store Params - vector_store_id: Optional[str] = None - milvus_text_field: Optional[str] = None - milvus_db_name: Optional[str] = None - milvus_partition_names: Optional[List[str]] = None + vector_store_id: str | None = None + milvus_text_field: str | None = None + milvus_db_name: str | None = None + milvus_partition_names: list[str] | None = None @model_validator(mode="before") @classmethod @@ -300,7 +298,7 @@ class GenericLiteLLMParams(CredentialLiteLLMParams, CustomPricingLiteLLMParams): return filtered return data - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -312,7 +310,7 @@ class GenericLiteLLMParams(CredentialLiteLLMParams, CustomPricingLiteLLMParams): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) @@ -325,7 +323,7 @@ class LiteLLM_Params(GenericLiteLLMParams): model: str model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True) - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -337,7 +335,7 @@ class LiteLLM_Params(GenericLiteLLMParams): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) @@ -345,77 +343,77 @@ class LiteLLM_Params(GenericLiteLLMParams): class updateLiteLLMParams(GenericLiteLLMParams): # This class is used to update the LiteLLM_Params # only differece is model is optional - model: Optional[str] = None + model: str | None = None class updateDeployment(BaseModel): - model_name: Optional[str] = None - litellm_params: Optional[updateLiteLLMParams] = None - model_info: Optional[ModelInfo] = None - blocked: Optional[bool] = None + model_name: str | None = None + litellm_params: updateLiteLLMParams | None = None + model_info: ModelInfo | None = None + blocked: bool | None = None model_config = ConfigDict(protected_namespaces=()) class LiteLLMParamsTypedDict(TypedDict, total=False): model: str - custom_llm_provider: Optional[str] - tpm: Optional[int] - rpm: Optional[int] - itpm: Optional[int] - otpm: Optional[int] - order: Optional[int] - weight: Optional[int] - max_parallel_requests: Optional[int] - api_key: Optional[str] - api_base: Optional[str] - api_version: Optional[str] - timeout: Optional[Union[float, str, httpx.Timeout]] - stream_timeout: Optional[Union[float, str]] - max_retries: Optional[int] - organization: Optional[Union[List, str]] # for openai orgs + custom_llm_provider: str | None + tpm: int | None + rpm: int | None + itpm: int | None + otpm: int | None + order: int | None + weight: int | None + max_parallel_requests: int | None + api_key: str | None + api_base: str | None + api_version: str | None + timeout: float | str | httpx.Timeout | None + stream_timeout: float | str | None + max_retries: int | None + organization: list | str | None # for openai orgs configurable_clientside_auth_params: ( CONFIGURABLE_CLIENTSIDE_AUTH_PARAMS # for allowing api base switching on finetuned models ) ## DROP PARAMS ## - drop_params: Optional[bool] + drop_params: bool | None ## RESPONSES API → CHAT COMPLETIONS BRIDGE ## - use_chat_completions_api: Optional[bool] + use_chat_completions_api: bool | None ## UNIFIED PROJECT/REGION ## - region_name: Optional[str] + region_name: str | None ## VERTEX AI ## - vertex_project: Optional[str] - vertex_location: Optional[str] + vertex_project: str | None + vertex_location: str | None ## AWS BEDROCK / SAGEMAKER ## - aws_access_key_id: Optional[str] - aws_secret_access_key: Optional[str] - aws_region_name: Optional[str] - aws_bedrock_project_id: Optional[str] + aws_access_key_id: str | None + aws_secret_access_key: str | None + aws_region_name: str | None + aws_bedrock_project_id: str | None ## AWS S3 VECTORS ## - vector_bucket_name: Optional[str] - index_name: Optional[str] - embedding_model: Optional[str] + vector_bucket_name: str | None + index_name: str | None + embedding_model: str | None ## IBM WATSONX ## - watsonx_region_name: Optional[str] + watsonx_region_name: str | None ## CUSTOM PRICING ## - input_cost_per_token: Optional[float] - output_cost_per_token: Optional[float] - input_cost_per_second: Optional[float] - output_cost_per_second: Optional[float] - output_cost_per_second_1080p: Optional[float] - num_retries: Optional[int] + input_cost_per_token: float | None + output_cost_per_token: float | None + input_cost_per_second: float | None + output_cost_per_second: float | None + output_cost_per_second_1080p: float | None + num_retries: int | None ## MOCK RESPONSES ## - mock_response: Optional[Union[str, ModelResponse, Exception]] + mock_response: str | ModelResponse | Exception | None # routing params # use this for tag-based routing - tags: Optional[List[str]] + tags: list[str] | None # regex patterns matched against request headers (e.g. "^User-Agent:\\s*claude-code\\/") - tag_regex: Optional[List[str]] + tag_regex: list[str] | None # deployment budgets - max_budget: Optional[float] - budget_duration: Optional[str] + max_budget: float | None + budget_duration: str | None class DeploymentTypedDict(TypedDict, total=False): @@ -445,9 +443,9 @@ class Deployment(BaseModel): self, model_name: str, litellm_params: LiteLLM_Params, - model_info: Optional[Union[ModelInfo, dict]] = None, + model_info: ModelInfo | dict | None = None, **params, - ): + ) -> None: if model_info is None: model_info = ModelInfo() elif isinstance(model_info, dict): @@ -467,12 +465,12 @@ class Deployment(BaseModel): def to_json(self, **kwargs): try: - return self.model_dump(**kwargs) # noqa + return self.model_dump(**kwargs) except Exception: # if using pydantic v1 return self.dict(**kwargs) - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -484,7 +482,7 @@ class Deployment(BaseModel): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) @@ -509,12 +507,12 @@ class AllowedFailsPolicy(BaseModel): https://docs.litellm.ai/docs/exception_mapping """ - BadRequestErrorAllowedFails: Optional[int] = None - AuthenticationErrorAllowedFails: Optional[int] = None - TimeoutErrorAllowedFails: Optional[int] = None - RateLimitErrorAllowedFails: Optional[int] = None - ContentPolicyViolationErrorAllowedFails: Optional[int] = None - InternalServerErrorAllowedFails: Optional[int] = None + BadRequestErrorAllowedFails: int | None = None + AuthenticationErrorAllowedFails: int | None = None + TimeoutErrorAllowedFails: int | None = None + RateLimitErrorAllowedFails: int | None = None + ContentPolicyViolationErrorAllowedFails: int | None = None + InternalServerErrorAllowedFails: int | None = None class AlertingConfig(BaseModel): @@ -530,45 +528,36 @@ class AlertingConfig(BaseModel): """ webhook_url: str - alerting_threshold: Optional[float] = 300 + alerting_threshold: float | None = 300 class ModelGroupInfo(BaseModel): model_group: str - providers: List[str] - max_input_tokens: Optional[float] = None - max_output_tokens: Optional[float] = None - input_cost_per_token: Optional[float] = None - output_cost_per_token: Optional[float] = None - input_cost_per_pixel: Optional[float] = None - mode: Optional[ - Union[ - str, - Literal[ - "chat", - "embedding", - "completion", - "image_generation", - "audio_transcription", - "rerank", - "moderations", - ], - ] - ] = Field(default="chat") - tpm: Optional[int] = None - rpm: Optional[int] = None - itpm: Optional[int] = None - otpm: Optional[int] = None + providers: list[str] + max_input_tokens: float | None = None + max_output_tokens: float | None = None + input_cost_per_token: float | None = None + output_cost_per_token: float | None = None + input_cost_per_pixel: float | None = None + mode: ( + str + | Literal["chat", "embedding", "completion", "image_generation", "audio_transcription", "rerank", "moderations"] + | None + ) = Field(default="chat") + tpm: int | None = None + rpm: int | None = None + itpm: int | None = None + otpm: int | None = None supports_parallel_function_calling: bool = Field(default=False) supports_vision: bool = Field(default=False) supports_web_search: bool = Field(default=False) supports_url_context: bool = Field(default=False) supports_reasoning: bool = Field(default=False) supports_function_calling: bool = Field(default=False) - supported_openai_params: Optional[List[str]] = Field(default=[]) + supported_openai_params: list[str] | None = Field(default=[]) configurable_clientside_auth_params: CONFIGURABLE_CLIENTSIDE_AUTH_PARAMS = None - def __init__(self, **data): + def __init__(self, **data) -> None: for field_name, field_type in get_type_hints(self.__class__).items(): if field_type is bool and data.get(field_name) is None: data[field_name] = False @@ -587,10 +576,10 @@ class SearchToolLiteLLMParams(TypedDict, total=False): """ search_provider: Required[SearchProvider] - api_key: Optional[str] - api_base: Optional[str] - timeout: Optional[Union[float, str, httpx.Timeout]] - max_retries: Optional[int] + api_key: str | None + api_base: str | None + timeout: float | str | httpx.Timeout | None + max_retries: int | None class SearchToolInfoTypedDict(TypedDict, total=False): @@ -625,9 +614,9 @@ class GuardrailLiteLLMParams(TypedDict, total=False): guardrail: Required[str] mode: Required[str] - api_key: Optional[str] - api_base: Optional[str] - weight: Optional[int] # For load balancing + api_key: str | None + api_base: str | None + weight: int | None # For load balancing class GuardrailTypedDict(TypedDict, total=False): @@ -638,7 +627,7 @@ class GuardrailTypedDict(TypedDict, total=False): guardrail_name: Required[str] litellm_params: Required[GuardrailLiteLLMParams] callback: Any # The CustomGuardrail instance - id: Optional[str] # Unique identifier for the guardrail deployment + id: str | None # Unique identifier for the guardrail deployment class FineTuningConfig(BaseModel): @@ -649,11 +638,11 @@ class CustomRoutingStrategyBase: async def async_get_available_deployment( self, model: str, - messages: Optional[List[Dict[str, str]]] = None, - input: Optional[Union[str, List]] = None, - specific_deployment: Optional[bool] = False, - request_kwargs: Optional[Dict] = None, - ): + messages: list[dict[str, str]] | None = None, + input: str | list | None = None, + specific_deployment: bool | None = False, + request_kwargs: dict | None = None, + ) -> None: """ Asynchronously retrieves the available deployment based on the given parameters. @@ -668,16 +657,15 @@ class CustomRoutingStrategyBase: Returns an element from litellm.router.model_list """ - pass def get_available_deployment( self, model: str, - messages: Optional[List[Dict[str, str]]] = None, - input: Optional[Union[str, List]] = None, - specific_deployment: Optional[bool] = False, - request_kwargs: Optional[Dict] = None, - ): + messages: list[dict[str, str]] | None = None, + input: str | list | None = None, + specific_deployment: bool | None = False, + request_kwargs: dict | None = None, + ) -> None: """ Synchronously retrieves the available deployment based on the given parameters. @@ -692,7 +680,6 @@ class CustomRoutingStrategyBase: Returns an element from litellm.router.model_list """ - pass class RouterGeneralSettings(BaseModel): @@ -710,7 +697,7 @@ class RouterRateLimitErrorBasic(ValueError): def __init__( self, model: str, - ): + ) -> None: self.model = model _message: Final = f"{RouterErrors.no_deployments_available.value}." super().__init__(_message) @@ -722,8 +709,8 @@ class RouterRateLimitError(ValueError): model: str, cooldown_time: float, enable_pre_call_checks: bool, - cooldown_list: List, - ): + cooldown_list: list, + ) -> None: self.model = model self.cooldown_time = cooldown_time self.enable_pre_call_checks = enable_pre_call_checks @@ -769,7 +756,7 @@ class GenericBudgetWindowDetails(BaseModel): ttl_seconds: int -OptionalPreCallChecks = List[ +OptionalPreCallChecks = list[ Literal[ "prompt_caching", "router_budget_limiting", @@ -794,15 +781,15 @@ class LiteLLM_RouterFileObject(TypedDict, total=False): @dataclass class MockRouterTestingParams: - mock_testing_fallbacks: Optional[bool] = None - mock_testing_context_fallbacks: Optional[bool] = None - mock_testing_content_policy_fallbacks: Optional[bool] = None + mock_testing_fallbacks: bool | None = None + mock_testing_context_fallbacks: bool | None = None + mock_testing_content_policy_fallbacks: bool | None = None @classmethod def from_kwargs(cls, kwargs: dict) -> "MockRouterTestingParams": from litellm.secret_managers.main import str_to_bool - def extract_bool_param(name: str) -> Optional[bool]: + def extract_bool_param(name: str) -> bool | None: value: Final = kwargs.pop(name, None) return str_to_bool(value) if isinstance(value, str) else value @@ -814,7 +801,7 @@ class MockRouterTestingParams: class ModelGroupSettings(BaseModel): - forward_client_headers_to_llm_api: Optional[List[str]] = None + forward_client_headers_to_llm_api: list[str] | None = None class PreRoutingHookResponse(BaseModel): @@ -827,7 +814,7 @@ class PreRoutingHookResponse(BaseModel): """ model: str - messages: Optional[List[Dict[str, Any]]] + messages: list[dict[str, Any]] | None routing_decision: StandardLoggingRoutingDecision | None = None @@ -912,7 +899,7 @@ class AdaptiveRouterWeights(BaseModel): class AdaptiveRouterConfig(BaseModel): - available_models: List[str] + available_models: list[str] weights: AdaptiveRouterWeights = Field(default_factory=AdaptiveRouterWeights) @@ -922,4 +909,4 @@ class AdaptiveRouterPreferences(BaseModel): model_config = ConfigDict(use_enum_values=False) quality_tier: int = Field(ge=1, le=3) - strengths: List[RequestType] = Field(default_factory=list) + strengths: list[RequestType] = Field(default_factory=list) diff --git a/litellm/types/search.py b/litellm/types/search.py index 015256ff76c..b4180d47a51 100644 --- a/litellm/types/search.py +++ b/litellm/types/search.py @@ -4,8 +4,6 @@ LiteLLM Search API Types This module defines types for the unified search API across different providers. """ -from typing import Final, List, Optional - from typing_extensions import Required, TypedDict from litellm.types.utils import SearchProviders @@ -22,10 +20,10 @@ class SearchToolLiteLLMParams(TypedDict, total=False): """ search_provider: Required[str] - api_key: Optional[str] - api_base: Optional[str] - timeout: Optional[float] - max_retries: Optional[int] + api_key: str | None + api_base: str | None + timeout: float | None + max_retries: int | None class SearchTool(TypedDict, total=False): @@ -46,30 +44,30 @@ class SearchTool(TypedDict, total=False): } """ - search_tool_id: Optional[str] + search_tool_id: str | None search_tool_name: Required[str] litellm_params: Required[SearchToolLiteLLMParams] - search_tool_info: Optional[dict] - created_at: Optional[str] - updated_at: Optional[str] + search_tool_info: dict | None + created_at: str | None + updated_at: str | None class SearchToolInfoResponse(TypedDict, total=False): """Response model for search tool information.""" - search_tool_id: Optional[str] + search_tool_id: str | None search_tool_name: str litellm_params: dict - search_tool_info: Optional[dict] - created_at: Optional[str] - updated_at: Optional[str] - is_from_config: Optional[bool] # True if this tool is defined in config file, False if from DB + search_tool_info: dict | None + created_at: str | None + updated_at: str | None + is_from_config: bool | None # True if this tool is defined in config file, False if from DB class ListSearchToolsResponse(TypedDict): """Response model for listing search tools.""" - search_tools: List[SearchToolInfoResponse] + search_tools: list[SearchToolInfoResponse] class AvailableSearchProvider(TypedDict): diff --git a/litellm/types/secret_managers/main.py b/litellm/types/secret_managers/main.py index 00a092a3c93..599e5746dfb 100644 --- a/litellm/types/secret_managers/main.py +++ b/litellm/types/secret_managers/main.py @@ -1,5 +1,5 @@ import enum -from typing import Dict, List, Literal, Optional +from typing import Literal from litellm.types.llms.base import LiteLLMPydanticObjectBase @@ -17,8 +17,8 @@ class KeyManagementSystem(enum.Enum): class KeyManagementSettings(LiteLLMPydanticObjectBase): - hosted_keys: Optional[List] = None - store_virtual_keys: Optional[bool] = False + hosted_keys: list | None = None + store_virtual_keys: bool | None = False """ If True, virtual keys created by litellm will be stored in the secret manager """ @@ -32,48 +32,48 @@ class KeyManagementSettings(LiteLLMPydanticObjectBase): Access mode for the secret manager, when write_only will only use for writing secrets """ - primary_secret_name: Optional[str] = None + primary_secret_name: str | None = None """ If set, will read secrets from this primary secret in the secret manager eg. on AWS you can store multiple secret values as K/V pairs in a single secret """ - description: Optional[str] = None + description: str | None = None """Optional description attached when creating secrets (visible in AWS console).""" - tags: Optional[Dict[str, str]] = None + tags: dict[str, str] | None = None """Optional tags to attach when creating secrets (e.g. {"Environment": "Prod", "Owner": "AI-Platform"}).""" - custom_secret_manager: Optional[str] = None + custom_secret_manager: str | None = None """ Path to custom secret manager class (e.g. "my_secret_manager.InMemorySecretManager") Required when key_management_system is "custom" """ # AWS IAM Role Assumption Settings (for AWS Secret Manager) - aws_region_name: Optional[str] = None + aws_region_name: str | None = None """AWS region for Secret Manager operations (e.g., 'us-east-1')""" - aws_role_name: Optional[str] = None + aws_role_name: str | None = None """ARN of IAM role to assume for Secret Manager access (e.g., 'arn:aws:iam::123456789012:role/MyRole')""" - aws_session_name: Optional[str] = None + aws_session_name: str | None = None """Session name for the assumed role session (optional, auto-generated if not provided)""" - aws_external_id: Optional[str] = None + aws_external_id: str | None = None """External ID for role assumption (required for cross-account access)""" - aws_profile_name: Optional[str] = None + aws_profile_name: str | None = None """AWS profile name to use from ~/.aws/credentials""" - aws_web_identity_token: Optional[str] = None + aws_web_identity_token: str | None = None """Web identity token for OIDC/IRSA authentication""" - aws_sts_endpoint: Optional[str] = None + aws_sts_endpoint: str | None = None """Custom STS endpoint URL (useful for VPC endpoints or testing)""" - replica_regions: Optional[List[str]] = None + replica_regions: list[str] | None = None """ Optional list of additional AWS regions to replicate secrets to after CreateSecret. Uses the AWS Secrets Manager ReplicateSecretToRegions API. Replication is diff --git a/litellm/types/services.py b/litellm/types/services.py index f43494a0a09..74f908548d5 100644 --- a/litellm/types/services.py +++ b/litellm/types/services.py @@ -1,11 +1,9 @@ import enum -from typing import Final, List, Optional +from typing import Final from pydantic import BaseModel, Field from typing_extensions import TypedDict -from litellm._uuid import uuid - class ServiceMetrics(enum.Enum): COUNTER = "counter" @@ -49,7 +47,7 @@ class ServiceConfig(TypedDict): Configuration for services and their metrics """ - metrics: List[ServiceMetrics] # What metrics this service should support + metrics: list[ServiceMetrics] # What metrics this service should support """ @@ -86,8 +84,8 @@ class ServiceEventMetadata(TypedDict, total=False): """ # Dynamically control gauge labels and values - gauge_labels: Optional[str] - gauge_value: Optional[float] + gauge_labels: str | None + gauge_value: float | None class ServiceLoggerPayload(BaseModel): @@ -96,15 +94,15 @@ class ServiceLoggerPayload(BaseModel): """ is_error: bool = Field(description="did an error occur") - error: Optional[str] = Field(None, description="what was the error") + error: str | None = Field(None, description="what was the error") service: ServiceTypes = Field(description="who is this for? - postgres/redis") duration: float = Field(description="How long did the request take?") call_type: str = Field(description="The call of the service, being made") - event_metadata: Optional[dict] = Field(description="The metadata logged during service success/failure") + event_metadata: dict | None = Field(description="The metadata logged during service success/failure") def to_json(self, **kwargs): try: - return self.model_dump(**kwargs) # noqa - except Exception as e: + return self.model_dump(**kwargs) + except Exception: # if using pydantic v1 return self.dict(**kwargs) diff --git a/litellm/types/tag_management.py b/litellm/types/tag_management.py index 3bf70c73fc7..f121f5bc562 100644 --- a/litellm/types/tag_management.py +++ b/litellm/types/tag_management.py @@ -1,43 +1,41 @@ -from typing import Dict, List, Optional - from pydantic import BaseModel class TagBase(BaseModel): name: str - description: Optional[str] = None - models: Optional[List[str]] = None - model_info: Optional[Dict[str, str]] = None # maps model_id to model_name + description: str | None = None + models: list[str] | None = None + model_info: dict[str, str] | None = None # maps model_id to model_name class TagConfig(TagBase): created_at: str updated_at: str - created_by: Optional[str] = None + created_by: str | None = None class TagNewRequest(TagBase): - budget_id: Optional[str] = None + budget_id: str | None = None # Budget fields - if budget_id is None, create a new budget with these params - max_budget: Optional[float] = None - soft_budget: Optional[float] = None - max_parallel_requests: Optional[int] = None - tpm_limit: Optional[int] = None - rpm_limit: Optional[int] = None - model_max_budget: Optional[Dict] = None - budget_duration: Optional[str] = None + max_budget: float | None = None + soft_budget: float | None = None + max_parallel_requests: int | None = None + tpm_limit: int | None = None + rpm_limit: int | None = None + model_max_budget: dict | None = None + budget_duration: str | None = None class TagUpdateRequest(TagBase): - budget_id: Optional[str] = None + budget_id: str | None = None # Budget fields - if provided, will update the budget - max_budget: Optional[float] = None - soft_budget: Optional[float] = None - max_parallel_requests: Optional[int] = None - tpm_limit: Optional[int] = None - rpm_limit: Optional[int] = None - model_max_budget: Optional[Dict] = None - budget_duration: Optional[str] = None + max_budget: float | None = None + soft_budget: float | None = None + max_parallel_requests: int | None = None + tpm_limit: int | None = None + rpm_limit: int | None = None + model_max_budget: dict | None = None + budget_duration: str | None = None class TagDeleteRequest(BaseModel): @@ -45,4 +43,4 @@ class TagDeleteRequest(BaseModel): class TagInfoRequest(BaseModel): - names: List[str] + names: list[str] diff --git a/litellm/types/tool_management.py b/litellm/types/tool_management.py index 6d0ec9abeea..6fc19250ae9 100644 --- a/litellm/types/tool_management.py +++ b/litellm/types/tool_management.py @@ -3,7 +3,7 @@ Pydantic models for Tool Policy management endpoints. """ from datetime import datetime -from typing import Dict, Final, List, Literal, Optional +from typing import Literal from pydantic import BaseModel, Field @@ -16,54 +16,54 @@ ToolOutputPolicy = Literal["trusted", "untrusted"] class LiteLLM_ToolTableRow(BaseModel): tool_id: str tool_name: str - origin: Optional[str] = None + origin: str | None = None input_policy: ToolInputPolicy = "untrusted" output_policy: ToolOutputPolicy = "untrusted" call_count: int = 0 - assignments: Optional[Dict] = None - key_hash: Optional[str] = None - team_id: Optional[str] = None - key_alias: Optional[str] = None - user_agent: Optional[str] = None - last_used_at: Optional[datetime] = None - created_at: Optional[datetime] = None - updated_at: Optional[datetime] = None - created_by: Optional[str] = None - updated_by: Optional[str] = None + assignments: dict | None = None + key_hash: str | None = None + team_id: str | None = None + key_alias: str | None = None + user_agent: str | None = None + last_used_at: datetime | None = None + created_at: datetime | None = None + updated_at: datetime | None = None + created_by: str | None = None + updated_by: str | None = None class ToolListResponse(BaseModel): - tools: List[LiteLLM_ToolTableRow] + tools: list[LiteLLM_ToolTableRow] total: int class ToolPolicyUpdateRequest(BaseModel): tool_name: str - input_policy: Optional[ToolInputPolicy] = None - output_policy: Optional[ToolOutputPolicy] = None - team_id: Optional[str] = None - key_hash: Optional[str] = None - key_alias: Optional[str] = None + input_policy: ToolInputPolicy | None = None + output_policy: ToolOutputPolicy | None = None + team_id: str | None = None + key_hash: str | None = None + key_alias: str | None = None class ToolPolicyUpdateResponse(BaseModel): tool_name: str - input_policy: Optional[ToolInputPolicy] = None - output_policy: Optional[ToolOutputPolicy] = None + input_policy: ToolInputPolicy | None = None + output_policy: ToolOutputPolicy | None = None updated: bool - team_id: Optional[str] = None - key_hash: Optional[str] = None + team_id: str | None = None + key_hash: str | None = None class ToolPolicyOverrideRow(BaseModel): override_id: str tool_name: str - team_id: Optional[str] = None - key_hash: Optional[str] = None + team_id: str | None = None + key_hash: str | None = None input_policy: ToolInputPolicy = "blocked" - key_alias: Optional[str] = None - created_at: Optional[datetime] = None - updated_at: Optional[datetime] = None + key_alias: str | None = None + created_at: datetime | None = None + updated_at: datetime | None = None class ToolPolicyOption(BaseModel): @@ -73,13 +73,13 @@ class ToolPolicyOption(BaseModel): class ToolPolicyOptionsResponse(BaseModel): - input_policies: List[ToolPolicyOption] - output_policies: List[ToolPolicyOption] + input_policies: list[ToolPolicyOption] + output_policies: list[ToolPolicyOption] class ToolDetailResponse(BaseModel): tool: LiteLLM_ToolTableRow - overrides: List[ToolPolicyOverrideRow] = Field(default_factory=list) + overrides: list[ToolPolicyOverrideRow] = Field(default_factory=list) class ToolUsageLogEntry(BaseModel): @@ -87,14 +87,14 @@ class ToolUsageLogEntry(BaseModel): id: str # request_id timestamp: str - model: Optional[str] = None - spend: Optional[float] = None - total_tokens: Optional[int] = None - input_snippet: Optional[str] = None + model: str | None = None + spend: float | None = None + total_tokens: int | None = None + input_snippet: str | None = None class ToolUsageLogsResponse(BaseModel): - logs: List[ToolUsageLogEntry] + logs: list[ToolUsageLogEntry] total: int page: int page_size: int @@ -122,7 +122,7 @@ class ToolSpendDailyEntry(BaseModel): class ToolSpendResponse(BaseModel): - by_tool: List[ToolSpendEntry] = Field(default_factory=list) - daily: List[ToolSpendDailyEntry] = Field(default_factory=list) + by_tool: list[ToolSpendEntry] = Field(default_factory=list) + daily: list[ToolSpendDailyEntry] = Field(default_factory=list) start_date: str | None = None end_date: str | None = None diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 77f83c5b6f8..eccdc7427dc 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -1,20 +1,14 @@ import json import time +from collections.abc import Mapping, Sequence from enum import Enum from types import MappingProxyType from typing import ( - Any, - Dict, - Final, - FrozenSet, - get_args, - List, - Literal, - Mapping, - Optional, - Sequence, TYPE_CHECKING, - Union, + Any, + Final, + Literal, + get_args, ) from openai._models import BaseModel as OpenAIObject @@ -47,6 +41,7 @@ from pydantic import ( ) from typing_extensions import Required, TypedDict +from litellm._logging import verbose_logger from litellm._uuid import uuid from litellm.types.llms.base import ( BaseLiteLLMOpenAIResponseObject, @@ -96,7 +91,7 @@ class SafeAttributeModel: A base model that provides safe attribute access. """ - def __delattr__(self, name): + def __delattr__(self, name) -> None: # Dropping an unset optional field stored in __dict__ goes straight to # object.__delattr__, skipping pydantic's __delattr__ whose per-call # class getattr lookup and _check_frozen dominate response construction. @@ -139,35 +134,35 @@ class ProviderField(TypedDict): class ProviderSpecificModelInfo(TypedDict, total=False): - supports_system_messages: Optional[bool] - supports_response_schema: Optional[bool] - supports_vision: Optional[bool] - supports_function_calling: Optional[bool] - supports_tool_choice: Optional[bool] - supports_assistant_prefill: Optional[bool] - supports_prompt_caching: Optional[bool] - supports_computer_use: Optional[bool] - supports_audio_input: Optional[bool] - supports_embedding_image_input: Optional[bool] - supports_audio_output: Optional[bool] - supports_pdf_input: Optional[bool] - supports_native_streaming: Optional[bool] - supports_native_structured_output: Optional[bool] - supports_parallel_function_calling: Optional[bool] - supports_web_search: Optional[bool] - supports_reasoning: Optional[bool] - supports_adaptive_thinking: Optional[bool] - supports_mid_conversation_system: Optional[bool] - supports_url_context: Optional[bool] - supports_none_reasoning_effort: Optional[bool] - supports_minimal_reasoning_effort: Optional[bool] - supports_low_reasoning_effort: Optional[bool] - supports_xhigh_reasoning_effort: Optional[bool] - supports_max_reasoning_effort: Optional[bool] - supports_output_config: Optional[bool] - supports_image_size: Optional[bool] - bedrock_output_config_effort_ceiling: Optional[Literal["low", "medium", "high", "max", "xhigh"]] - bedrock_converse_supports_strict_tools: Optional[bool] + supports_system_messages: bool | None + supports_response_schema: bool | None + supports_vision: bool | None + supports_function_calling: bool | None + supports_tool_choice: bool | None + supports_assistant_prefill: bool | None + supports_prompt_caching: bool | None + supports_computer_use: bool | None + supports_audio_input: bool | None + supports_embedding_image_input: bool | None + supports_audio_output: bool | None + supports_pdf_input: bool | None + supports_native_streaming: bool | None + supports_native_structured_output: bool | None + supports_parallel_function_calling: bool | None + supports_web_search: bool | None + supports_reasoning: bool | None + supports_adaptive_thinking: bool | None + supports_mid_conversation_system: bool | None + supports_url_context: bool | None + supports_none_reasoning_effort: bool | None + supports_minimal_reasoning_effort: bool | None + supports_low_reasoning_effort: bool | None + supports_xhigh_reasoning_effort: bool | None + supports_max_reasoning_effort: bool | None + supports_output_config: bool | None + supports_image_size: bool | None + bedrock_output_config_effort_ceiling: Literal["low", "medium", "high", "max", "xhigh"] | None + bedrock_converse_supports_strict_tools: bool | None class SearchContextCostPerQuery(TypedDict, total=False): @@ -194,90 +189,90 @@ class AgenticLoopParams(TypedDict, total=False): class ModelInfoBase(ProviderSpecificModelInfo, total=False): key: Required[str] # the key in litellm.model_cost which is returned - max_tokens: Required[Optional[int]] - max_input_tokens: Required[Optional[int]] - max_output_tokens: Required[Optional[int]] - input_cost_per_token: Required[Optional[float]] - input_cost_per_token_flex: Optional[float] # OpenAI flex service tier pricing - input_cost_per_token_priority: Optional[float] # OpenAI priority service tier pricing - cache_creation_input_token_cost: Optional[float] - cache_creation_input_token_cost_above_200k_tokens: Optional[float] - cache_creation_input_token_cost_above_272k_tokens: Optional[float] - cache_creation_input_token_cost_above_272k_tokens_priority: Optional[float] - cache_creation_input_token_cost_above_272k_tokens_flex: Optional[float] - cache_creation_input_token_cost_above_1hr: Optional[float] - cache_creation_input_token_cost_flex: Optional[float] # OpenAI flex service tier pricing - cache_creation_input_token_cost_priority: Optional[float] # OpenAI priority service tier pricing - cache_read_input_token_cost: Optional[float] - cache_read_input_token_cost_flex: Optional[float] # OpenAI flex service tier pricing - cache_read_input_token_cost_priority: Optional[float] # OpenAI priority service tier pricing - cache_read_input_token_cost_above_200k_tokens: Optional[float] - cache_read_input_token_cost_above_200k_tokens_priority: Optional[float] - cache_read_input_token_cost_above_272k_tokens: Optional[float] - cache_read_input_token_cost_above_272k_tokens_priority: Optional[float] - cache_read_input_token_cost_above_272k_tokens_flex: Optional[float] - cache_read_input_token_cost_above_512k_tokens: Optional[float] + max_tokens: Required[int | None] + max_input_tokens: Required[int | None] + max_output_tokens: Required[int | None] + input_cost_per_token: Required[float | None] + input_cost_per_token_flex: float | None # OpenAI flex service tier pricing + input_cost_per_token_priority: float | None # OpenAI priority service tier pricing + cache_creation_input_token_cost: float | None + cache_creation_input_token_cost_above_200k_tokens: float | None + cache_creation_input_token_cost_above_272k_tokens: float | None + cache_creation_input_token_cost_above_272k_tokens_priority: float | None + cache_creation_input_token_cost_above_272k_tokens_flex: float | None + cache_creation_input_token_cost_above_1hr: float | None + cache_creation_input_token_cost_flex: float | None # OpenAI flex service tier pricing + cache_creation_input_token_cost_priority: float | None # OpenAI priority service tier pricing + cache_read_input_token_cost: float | None + cache_read_input_token_cost_flex: float | None # OpenAI flex service tier pricing + cache_read_input_token_cost_priority: float | None # OpenAI priority service tier pricing + cache_read_input_token_cost_above_200k_tokens: float | None + cache_read_input_token_cost_above_200k_tokens_priority: float | None + cache_read_input_token_cost_above_272k_tokens: float | None + cache_read_input_token_cost_above_272k_tokens_priority: float | None + cache_read_input_token_cost_above_272k_tokens_flex: float | None + cache_read_input_token_cost_above_512k_tokens: float | None # Smallest prefix this model will actually cache, whatever caching mechanism its provider uses. # Absent means the provider-agnostic default applies; see MINIMUM_PROMPT_CACHE_TOKEN_COUNT. - prompt_cache_min_tokens: Optional[int] - input_cost_per_character: Optional[float] # only for vertex ai models - input_cost_per_audio_token: Optional[float] - input_cost_per_token_above_128k_tokens: Optional[float] # only for vertex ai models - input_cost_per_token_above_200k_tokens: Optional[float] # only for vertex ai gemini-2.5-pro models - input_cost_per_token_above_200k_tokens_priority: Optional[float] - input_cost_per_token_above_272k_tokens: Optional[float] # GPT-5.4/5.4-pro: prompts >272K priced at 2x input - input_cost_per_token_above_272k_tokens_priority: Optional[float] - input_cost_per_token_above_272k_tokens_flex: Optional[float] - input_cost_per_token_above_512k_tokens: Optional[float] # MiniMax-M3: prompts >512K priced at 2x input - input_cost_per_character_above_128k_tokens: Optional[float] # only for vertex ai models - input_cost_per_query: Optional[float] # only for rerank models - input_cost_per_image: Optional[float] # only for vertex ai models - input_cost_per_image_token: Optional[float] # for gpt-image-1 and similar models - input_cost_per_video_token: Optional[float] # for gemini omni models with video input - input_cost_per_audio_per_second: Optional[float] # only for vertex ai models - input_cost_per_video_per_second: Optional[float] # only for vertex ai models - input_cost_per_second: Optional[float] # for OpenAI Speech models - input_cost_per_token_batches: Optional[float] - output_cost_per_token_batches: Optional[float] - output_cost_per_token: Required[Optional[float]] - output_cost_per_token_flex: Optional[float] # OpenAI flex service tier pricing - output_cost_per_token_priority: Optional[float] # OpenAI priority service tier pricing - regional_processing_uplift_multiplier_eu: Optional[ - float - ] # OpenAI EU data-residency uplift multiplier applied to all token costs (e.g. 1.10 = +10%) - regional_processing_uplift_multiplier_us: Optional[ - float - ] # OpenAI US data-residency uplift multiplier applied to all token costs (e.g. 1.10 = +10%) - output_cost_per_character: Optional[float] # only for vertex ai models - output_cost_per_audio_token: Optional[float] - output_cost_per_token_above_128k_tokens: Optional[float] # only for vertex ai models - output_cost_per_token_above_200k_tokens: Optional[float] # only for vertex ai gemini-2.5-pro models - output_cost_per_token_above_200k_tokens_priority: Optional[float] - output_cost_per_token_above_272k_tokens: Optional[float] # GPT-5.4/5.4-pro: prompts >272K priced at 1.5x output - output_cost_per_token_above_272k_tokens_priority: Optional[float] - output_cost_per_token_above_272k_tokens_flex: Optional[float] - output_cost_per_token_above_512k_tokens: Optional[float] # MiniMax-M3: prompts >512K priced at 2x output - output_cost_per_character_above_128k_tokens: Optional[float] # only for vertex ai models - output_cost_per_image: Optional[float] - output_cost_per_image_token: Optional[float] - output_cost_per_video_token: Optional[float] # for gemini omni models with video output - output_vector_size: Optional[int] - output_cost_per_reasoning_token: Optional[float] - output_cost_per_video_per_second: Optional[float] # only for vertex ai models - output_cost_per_audio_per_second: Optional[float] # only for vertex ai models - output_cost_per_second: Optional[float] # for OpenAI Speech models - output_cost_per_second_1080p: Optional[ - float - ] # video_generation tier: key output_cost_per_second_ (e.g. 1080p, 720p) - ocr_cost_per_page: Optional[float] # for OCR models - ocr_cost_per_credit: Optional[float] # for OCR models priced by credit - annotation_cost_per_page: Optional[float] # for OCR models - search_context_cost_per_query: Optional[SearchContextCostPerQuery] # Cost for using web search tool - web_search_billing_unit: Optional[ - Literal["per_query", "per_prompt"] - ] # "per_query" (Gemini 3.x) or "per_prompt" (Gemini 2.x) - citation_cost_per_token: Optional[float] # Cost per citation token for Perplexity - tiered_pricing: Optional[List[Dict[str, Any]]] # Tiered pricing structure for models like Dashscope + prompt_cache_min_tokens: int | None + input_cost_per_character: float | None # only for vertex ai models + input_cost_per_audio_token: float | None + input_cost_per_token_above_128k_tokens: float | None # only for vertex ai models + input_cost_per_token_above_200k_tokens: float | None # only for vertex ai gemini-2.5-pro models + input_cost_per_token_above_200k_tokens_priority: float | None + input_cost_per_token_above_272k_tokens: float | None # GPT-5.4/5.4-pro: prompts >272K priced at 2x input + input_cost_per_token_above_272k_tokens_priority: float | None + input_cost_per_token_above_272k_tokens_flex: float | None + input_cost_per_token_above_512k_tokens: float | None # MiniMax-M3: prompts >512K priced at 2x input + input_cost_per_character_above_128k_tokens: float | None # only for vertex ai models + input_cost_per_query: float | None # only for rerank models + input_cost_per_image: float | None # only for vertex ai models + input_cost_per_image_token: float | None # for gpt-image-1 and similar models + input_cost_per_video_token: float | None # for gemini omni models with video input + input_cost_per_audio_per_second: float | None # only for vertex ai models + input_cost_per_video_per_second: float | None # only for vertex ai models + input_cost_per_second: float | None # for OpenAI Speech models + input_cost_per_token_batches: float | None + output_cost_per_token_batches: float | None + output_cost_per_token: Required[float | None] + output_cost_per_token_flex: float | None # OpenAI flex service tier pricing + output_cost_per_token_priority: float | None # OpenAI priority service tier pricing + regional_processing_uplift_multiplier_eu: ( + float | None + ) # OpenAI EU data-residency uplift multiplier applied to all token costs (e.g. 1.10 = +10%) + regional_processing_uplift_multiplier_us: ( + float | None + ) # OpenAI US data-residency uplift multiplier applied to all token costs (e.g. 1.10 = +10%) + output_cost_per_character: float | None # only for vertex ai models + output_cost_per_audio_token: float | None + output_cost_per_token_above_128k_tokens: float | None # only for vertex ai models + output_cost_per_token_above_200k_tokens: float | None # only for vertex ai gemini-2.5-pro models + output_cost_per_token_above_200k_tokens_priority: float | None + output_cost_per_token_above_272k_tokens: float | None # GPT-5.4/5.4-pro: prompts >272K priced at 1.5x output + output_cost_per_token_above_272k_tokens_priority: float | None + output_cost_per_token_above_272k_tokens_flex: float | None + output_cost_per_token_above_512k_tokens: float | None # MiniMax-M3: prompts >512K priced at 2x output + output_cost_per_character_above_128k_tokens: float | None # only for vertex ai models + output_cost_per_image: float | None + output_cost_per_image_token: float | None + output_cost_per_video_token: float | None # for gemini omni models with video output + output_vector_size: int | None + output_cost_per_reasoning_token: float | None + output_cost_per_video_per_second: float | None # only for vertex ai models + output_cost_per_audio_per_second: float | None # only for vertex ai models + output_cost_per_second: float | None # for OpenAI Speech models + output_cost_per_second_1080p: ( + float | None + ) # video_generation tier: key output_cost_per_second_ (e.g. 1080p, 720p) + ocr_cost_per_page: float | None # for OCR models + ocr_cost_per_credit: float | None # for OCR models priced by credit + annotation_cost_per_page: float | None # for OCR models + search_context_cost_per_query: SearchContextCostPerQuery | None # Cost for using web search tool + web_search_billing_unit: ( + Literal["per_query", "per_prompt"] | None + ) # "per_query" (Gemini 3.x) or "per_prompt" (Gemini 2.x) + citation_cost_per_token: float | None # Cost per citation token for Perplexity + tiered_pricing: list[dict[str, Any]] | None # Tiered pricing structure for models like Dashscope litellm_provider: Required[str] mode: Required[ Literal[ @@ -291,12 +286,12 @@ class ModelInfoBase(ProviderSpecificModelInfo, total=False): "realtime", ] ] - supported_endpoints: Optional[List[str]] - use_openai_responses_path: Optional[bool] - tpm: Optional[int] - rpm: Optional[int] - provider_specific_entry: Optional[Dict[str, float]] - uses_embed_content: Optional[bool] + supported_endpoints: list[str] | None + use_openai_responses_path: bool | None + tpm: int | None + rpm: int | None + provider_specific_entry: dict[str, float] | None + uses_embed_content: bool | None class ModelInfo(ModelInfoBase, total=False): @@ -304,19 +299,19 @@ class ModelInfo(ModelInfoBase, total=False): Model info for a given model, this is information found in litellm.model_prices_and_context_window.json """ - supported_openai_params: Required[Optional[List[str]]] + supported_openai_params: Required[list[str] | None] class GenericStreamingChunk(TypedDict, total=False): text: Required[str] - tool_use: Optional[ChatCompletionToolCallChunk] + tool_use: ChatCompletionToolCallChunk | None is_finished: Required[bool] finish_reason: Required[str] - usage: Required[Optional[ChatCompletionUsageBlock]] + usage: Required[ChatCompletionUsageBlock | None] index: int # use this dict if you want to return any provider specific fields in the response - provider_specific_fields: Optional[Dict[str, Any]] + provider_specific_fields: dict[str, Any] | None from enum import Enum @@ -926,7 +921,7 @@ class TopLogprob(OpenAIObject): token: str """The token.""" - bytes: Optional[List[int]] = None + bytes: list[int] | None = None """A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and @@ -947,7 +942,7 @@ class ChatCompletionTokenLogprob(OpenAIObject): token: str """The token.""" - bytes: Optional[List[int]] = None + bytes: list[int] | None = None """A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and @@ -963,7 +958,7 @@ class ChatCompletionTokenLogprob(OpenAIObject): unlikely. """ - top_logprobs: List[TopLogprob] + top_logprobs: list[TopLogprob] """List of the most likely tokens and their log probability, at this token position. @@ -986,7 +981,7 @@ class ChatCompletionTokenLogprob(OpenAIObject): return [] return v - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1000,10 +995,10 @@ class ChatCompletionTokenLogprob(OpenAIObject): class ChoiceLogprobs(OpenAIObject): - content: Optional[List[ChatCompletionTokenLogprob]] = None + content: list[ChatCompletionTokenLogprob] | None = None """A list of message content tokens with log probability information.""" - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1018,26 +1013,26 @@ class ChoiceLogprobs(OpenAIObject): class FunctionCall(OpenAIObject): arguments: str - name: Optional[str] = None + name: str | None = None class Function(OpenAIObject): arguments: str - name: Optional[str] # can be None - openai e.g.: ChoiceDeltaToolCallFunction(arguments='{"', name=None), type=None) + name: str | None # can be None - openai e.g.: ChoiceDeltaToolCallFunction(arguments='{"', name=None), type=None) def __init__( self, - arguments: Optional[Union[Dict, str]] = None, - name: Optional[str] = None, + arguments: dict | str | None = None, + name: str | None = None, **params, - ): + ) -> None: if arguments is None: if params.get("parameters", None) is not None and isinstance(params["parameters"], dict): arguments = json.dumps(params["parameters"]) params.pop("parameters") else: arguments = "" - elif isinstance(arguments, Dict): + elif isinstance(arguments, dict): arguments = json.dumps(arguments) else: arguments = arguments @@ -1047,9 +1042,9 @@ class Function(OpenAIObject): # Build a dictionary with the structure your BaseModel expects data: Final = {"arguments": arguments, "name": name} - super(Function, self).__init__(**data) + super().__init__(**data) - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1061,18 +1056,18 @@ class Function(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) class ChatCompletionDeltaToolCall(OpenAIObject): - id: Optional[str] = None + id: str | None = None function: Function - type: Optional[str] = None + type: str | None = None index: int - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1084,13 +1079,13 @@ class ChatCompletionDeltaToolCall(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) class _CustomToolCallAccess(OpenAIObject): - def __contains__(self, key): + def __contains__(self, key) -> bool: return hasattr(self, key) def get(self, key, default=None): @@ -1099,7 +1094,7 @@ class _CustomToolCallAccess(OpenAIObject): def __getitem__(self, key): return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: setattr(self, key, value) @@ -1129,13 +1124,13 @@ class ChatCompletionDeltaCustomToolCall(_CustomToolCallAccess): class ChatCompletionMessageToolCall(OpenAIObject): def __init__( self, - function: Union[Dict, Function], - id: Optional[str] = None, - type: Optional[str] = None, + function: dict | Function, + id: str | None = None, + type: str | None = None, **params, - ): - super(ChatCompletionMessageToolCall, self).__init__(**params) - if isinstance(function, Dict): + ) -> None: + super().__init__(**params) + if isinstance(function, dict): self.function = Function(**function) else: self.function = function @@ -1150,7 +1145,7 @@ class ChatCompletionMessageToolCall(OpenAIObject): else: self.type = "function" - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1162,7 +1157,7 @@ class ChatCompletionMessageToolCall(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) @@ -1190,18 +1185,16 @@ class ChatCompletionAudioResponse(ChatCompletionAudio): data: str, expires_at: int, transcript: str, - id: Optional[str] = None, + id: str | None = None, **params, - ): + ) -> None: if id is not None: id = id else: id = f"{uuid.uuid4()}" - super(ChatCompletionAudioResponse, self).__init__( - data=data, expires_at=expires_at, transcript=transcript, id=id, **params - ) + super().__init__(data=data, expires_at=expires_at, transcript=transcript, id=id, **params) - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1213,7 +1206,7 @@ class ChatCompletionAudioResponse(ChatCompletionAudio): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) @@ -1224,43 +1217,43 @@ ChatCompletionMessage(content='This is a test', role='assistant', function_call= """ -def add_provider_specific_fields(object: BaseModel, provider_specific_fields: Optional[Dict[str, Any]]): +def add_provider_specific_fields(object: BaseModel, provider_specific_fields: dict[str, Any] | None) -> None: if not provider_specific_fields: # set if provider_specific_fields is not empty return - setattr(object, "provider_specific_fields", provider_specific_fields) + object.provider_specific_fields = provider_specific_fields class Message(SafeAttributeModel, OpenAIObject): - content: Optional[str] + content: str | None role: Literal["assistant", "user", "system", "tool", "function"] - tool_calls: Optional[ - List[Union[ChatCompletionMessageToolCall, ChatCompletionMessageCustomToolCall]] - ] # mutable-ok: public pydantic response field; only the union member is new - function_call: Optional[FunctionCall] - audio: Optional[ChatCompletionAudioResponse] = None - images: Optional[List[ImageURLListItem]] = None - reasoning_content: Optional[str] = None - thinking_blocks: Optional[List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]]] = None - reasoning_items: Optional[List[ChatCompletionReasoningItem]] = None - provider_specific_fields: Optional[Dict[str, Any]] = Field(default=None) - annotations: Optional[List[ChatCompletionAnnotation]] = None + tool_calls: ( + list[ChatCompletionMessageToolCall | ChatCompletionMessageCustomToolCall] | None + ) # mutable-ok: public pydantic response field; only the union member is new + function_call: FunctionCall | None + audio: ChatCompletionAudioResponse | None = None + images: list[ImageURLListItem] | None = None + reasoning_content: str | None = None + thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None = None + reasoning_items: list[ChatCompletionReasoningItem] | None = None + provider_specific_fields: dict[str, Any] | None = Field(default=None) + annotations: list[ChatCompletionAnnotation] | None = None def __init__( self, - content: Optional[str] = None, + content: str | None = None, role: Literal["assistant", "user", "system", "tool", "function"] = "assistant", function_call=None, - tool_calls: Optional[list] = None, - audio: Optional[ChatCompletionAudioResponse] = None, - images: Optional[List[ImageURLListItem]] = None, - provider_specific_fields: Optional[Dict[str, Any]] = None, - reasoning_content: Optional[str] = None, - thinking_blocks: Optional[List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]]] = None, - reasoning_items: Optional[List[ChatCompletionReasoningItem]] = None, - annotations: Optional[List[ChatCompletionAnnotation]] = None, + tool_calls: list | None = None, + audio: ChatCompletionAudioResponse | None = None, + images: list[ImageURLListItem] | None = None, + provider_specific_fields: dict[str, Any] | None = None, + reasoning_content: str | None = None, + thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None = None, + reasoning_items: list[ChatCompletionReasoningItem] | None = None, + annotations: list[ChatCompletionAnnotation] | None = None, **params, - ): - init_values: Final[Dict[str, Any]] = { + ) -> None: + init_values: Final[dict[str, Any]] = { "content": content, "role": role or "assistant", # handle null input "function_call": (FunctionCall(**function_call) if function_call is not None else None), @@ -1292,7 +1285,7 @@ class Message(SafeAttributeModel, OpenAIObject): if reasoning_content is not None: init_values["reasoning_content"] = reasoning_content - super(Message, self).__init__( + super().__init__( **init_values, # type: ignore **params, ) @@ -1303,9 +1296,8 @@ class Message(SafeAttributeModel, OpenAIObject): if hasattr(self, "audio"): del self.audio - if images is None: - if hasattr(self, "images"): - del self.images + if images is None and hasattr(self, "images"): + del self.images if annotations is None: # ensure default response matches OpenAI spec @@ -1338,13 +1330,13 @@ class Message(SafeAttributeModel, OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() @@ -1356,20 +1348,20 @@ class Delta(SafeAttributeModel, OpenAIObject): # __init__ rather than via self. = .... Declared here only so type # checkers still see them as attributes for consumers that read delta.content # etc.; the runtime branch is skipped so pydantic does not treat them as fields. - content: Optional[str] - role: Optional[str] - function_call: Optional[FunctionCall] - tool_calls: Optional[ - List[Union[ChatCompletionDeltaToolCall, ChatCompletionDeltaCustomToolCall]] - ] # mutable-ok: public pydantic response field; only the union member is new - audio: Optional[ChatCompletionAudioResponse] - images: Optional[List[ImageURLListItem]] - annotations: Optional[List[ChatCompletionAnnotation]] + content: str | None + role: str | None + function_call: FunctionCall | None + tool_calls: ( + list[ChatCompletionDeltaToolCall | ChatCompletionDeltaCustomToolCall] | None + ) # mutable-ok: public pydantic response field; only the union member is new + audio: ChatCompletionAudioResponse | None + images: list[ImageURLListItem] | None + annotations: list[ChatCompletionAnnotation] | None - reasoning_content: Optional[str] = None - thinking_blocks: Optional[List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]]] = None - reasoning_items: Optional[List[ChatCompletionReasoningItem]] = None - provider_specific_fields: Optional[Dict[str, Any]] = Field(default=None) + reasoning_content: str | None = None + thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None = None + reasoning_items: list[ChatCompletionReasoningItem] | None = None + provider_specific_fields: dict[str, Any] | None = Field(default=None) def __init__( self, @@ -1377,14 +1369,14 @@ class Delta(SafeAttributeModel, OpenAIObject): role=None, function_call=None, tool_calls=None, - audio: Optional[ChatCompletionAudioResponse] = None, - images: Optional[List[ImageURLListItem]] = None, - reasoning_content: Optional[str] = None, - thinking_blocks: Optional[List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]]] = None, - reasoning_items: Optional[List[ChatCompletionReasoningItem]] = None, - annotations: Optional[List[ChatCompletionAnnotation]] = None, + audio: ChatCompletionAudioResponse | None = None, + images: list[ImageURLListItem] | None = None, + reasoning_content: str | None = None, + thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] | None = None, + reasoning_items: list[ChatCompletionReasoningItem] | None = None, + annotations: list[ChatCompletionAnnotation] | None = None, **params, - ): + ) -> None: # Map 'reasoning' to 'reasoning_content' for providers that return # delta.reasoning (e.g., Cerebras, Groq gpt-oss models). # Must be done before super().__init__ to prevent 'reasoning' from @@ -1392,15 +1384,15 @@ class Delta(SafeAttributeModel, OpenAIObject): if reasoning_content is None and "reasoning" in params: reasoning_content = params.pop("reasoning", None) - super(Delta, self).__init__(**params) + super().__init__(**params) add_provider_specific_fields(self, params.get("provider_specific_fields", {})) if function_call is not None and isinstance(function_call, dict): function_call = FunctionCall(**function_call) if tool_calls is not None and isinstance(tool_calls, (list, tuple)): - coerced_tool_calls: List[ - Union[ChatCompletionDeltaToolCall, ChatCompletionDeltaCustomToolCall] + coerced_tool_calls: list[ + ChatCompletionDeltaToolCall | ChatCompletionDeltaCustomToolCall ] = [] # mutable-ok: public Delta.tool_calls contract is a list current_index = 0 for tool_call in tool_calls: @@ -1474,7 +1466,7 @@ class Delta(SafeAttributeModel, OpenAIObject): if hasattr(self, "reasoning_items"): del self.reasoning_items - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1486,7 +1478,7 @@ class Delta(SafeAttributeModel, OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) @@ -1495,20 +1487,20 @@ class Choices(SafeAttributeModel, OpenAIObject): finish_reason: OpenAIChatCompletionFinishReason index: int message: Message - logprobs: Optional[Union[ChoiceLogprobs, Any]] = None + logprobs: ChoiceLogprobs | Any | None = None - provider_specific_fields: Optional[Dict[str, Any]] = Field(default=None) + provider_specific_fields: dict[str, Any] | None = Field(default=None) def __init__( self, finish_reason=None, index=0, - message: Optional[Union[Message, dict]] = None, - logprobs: Optional[Union[ChoiceLogprobs, dict, Any]] = None, + message: Message | dict | None = None, + logprobs: ChoiceLogprobs | dict | Any | None = None, enhancements=None, - provider_specific_fields: Optional[Dict[str, Any]] = None, + provider_specific_fields: dict[str, Any] | None = None, **params, - ): + ) -> None: if finish_reason is not None: mapped: Final = map_finish_reason(finish_reason) params["finish_reason"] = mapped @@ -1539,7 +1531,7 @@ class Choices(SafeAttributeModel, OpenAIObject): params["logprobs"] = logprobs else: params["logprobs"] = None - super(Choices, self).__init__(**params) + super().__init__(**params) if enhancements is not None: self.enhancements = enhancements @@ -1551,7 +1543,7 @@ class Choices(SafeAttributeModel, OpenAIObject): if self.provider_specific_fields is None: del self.provider_specific_fields - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1563,64 +1555,64 @@ class Choices(SafeAttributeModel, OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) class CompletionTokensDetailsWrapper(CompletionTokensDetails): # wrapper for older openai versions - text_tokens: Optional[int] = None + text_tokens: int | None = None """Text tokens generated by the model.""" - image_tokens: Optional[int] = None + image_tokens: int | None = None """Image tokens generated by the model.""" - video_tokens: Optional[int] = None + video_tokens: int | None = None """Video tokens generated by the model.""" class CacheCreationTokenDetails(BaseModel): - ephemeral_5m_input_tokens: Optional[int] = None - ephemeral_1h_input_tokens: Optional[int] = None + ephemeral_5m_input_tokens: int | None = None + ephemeral_1h_input_tokens: int | None = None class PromptTokensDetailsWrapper( SafeAttributeModel, PromptTokensDetails ): # extends with image generation fields (text_tokens, image_tokens) - text_tokens: Optional[int] = None + text_tokens: int | None = None """Text tokens sent to the model.""" - image_tokens: Optional[int] = None + image_tokens: int | None = None """Image tokens sent to the model.""" - video_tokens: Optional[int] = None + video_tokens: int | None = None """Video tokens sent to the model.""" - web_search_requests: Optional[int] = None + web_search_requests: int | None = None """Number of web search requests made by the tool call. Used for Anthropic to calculate web search cost.""" - tool_use_tokens: Optional[int] = None + tool_use_tokens: int | None = None """Prompt tokens consumed by server-side tool use (e.g. Gemini grounding via googleSearch).""" - character_count: Optional[int] = None + character_count: int | None = None """Character count sent to the model. Used for Vertex AI multimodal embeddings.""" - image_count: Optional[int] = None + image_count: int | None = None """Number of images sent to the model. Used for Vertex AI multimodal embeddings.""" - video_length_seconds: Optional[float] = None + video_length_seconds: float | None = None """Length of videos sent to the model. Used for Vertex AI multimodal embeddings.""" - audio_length_seconds: Optional[float] = None + audio_length_seconds: float | None = None """Length of audio sent to the model. Used for multimodal embeddings priced per audio-second.""" - cache_write_tokens: Optional[int] = None + cache_write_tokens: int | None = None """Number of cache write (creation) tokens sent to the model. OpenAI naming (prompt_tokens_details.cache_write_tokens); this is the canonical field.""" - cache_creation_tokens: Optional[int] = None + cache_creation_tokens: int | None = None """Number of cache creation tokens sent to the model. Anthropic/Bedrock naming; kept in sync with cache_write_tokens (assigning either mirrors to the other).""" - cache_creation_token_details: Optional[CacheCreationTokenDetails] = None + cache_creation_token_details: CacheCreationTokenDetails | None = None """Details of cache creation tokens sent to the model. Used for tracking 5m/1h cache creation tokens for Anthropic prompt caching.""" def __setattr__(self, name: str, value: object) -> None: @@ -1630,7 +1622,7 @@ class PromptTokensDetailsWrapper( elif name == "cache_creation_tokens": super().__setattr__("cache_write_tokens", value) - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.cache_write_tokens = ( self.cache_write_tokens if self.cache_write_tokens is not None else self.cache_creation_tokens @@ -1656,11 +1648,11 @@ class PromptTokensDetailsWrapper( class ServerToolUse(BaseModel): - web_search_requests: Optional[int] = None - tool_search_requests: Optional[int] = None - browser_open_requests: Optional[int] = None + web_search_requests: int | None = None + tool_search_requests: int | None = None + browser_open_requests: int | None = None - def __getitem__(self, key: str) -> Optional[int]: + def __getitem__(self, key: str) -> int | None: if key not in self.__class__.model_fields: raise KeyError(key) return getattr(self, key) @@ -1674,29 +1666,29 @@ class Usage(SafeAttributeModel, CompletionUsage): 0 ) # hidden param for prompt caching. Might change, once openai introduces their equivalent. - server_tool_use: Optional[ServerToolUse] = None - cost: Optional[float] = None + server_tool_use: ServerToolUse | None = None + cost: float | None = None - completion_tokens_details: Optional[CompletionTokensDetailsWrapper] = None + completion_tokens_details: CompletionTokensDetailsWrapper | None = None """Breakdown of tokens used in a completion.""" - prompt_tokens_details: Optional[PromptTokensDetailsWrapper] = None + prompt_tokens_details: PromptTokensDetailsWrapper | None = None """Breakdown of tokens used in the prompt.""" def __init__( self, - prompt_tokens: Optional[int] = None, - completion_tokens: Optional[int] = None, - total_tokens: Optional[int] = None, - reasoning_tokens: Optional[int] = None, - prompt_tokens_details: Optional[Union[PromptTokensDetailsWrapper, PromptTokensDetails, dict]] = None, - completion_tokens_details: Optional[Union[CompletionTokensDetailsWrapper, dict]] = None, - server_tool_use: Optional[Union[ServerToolUse, dict]] = None, - cost: Optional[float] = None, + prompt_tokens: int | None = None, + completion_tokens: int | None = None, + total_tokens: int | None = None, + reasoning_tokens: int | None = None, + prompt_tokens_details: PromptTokensDetailsWrapper | PromptTokensDetails | dict | None = None, + completion_tokens_details: CompletionTokensDetailsWrapper | dict | None = None, + server_tool_use: ServerToolUse | dict | None = None, + cost: float | None = None, **params, - ): + ) -> None: # handle reasoning_tokens - _completion_tokens_details: Optional[CompletionTokensDetailsWrapper] = None + _completion_tokens_details: CompletionTokensDetailsWrapper | None = None # First, handle existing completion_tokens_details if completion_tokens_details: @@ -1730,7 +1722,7 @@ class Usage(SafeAttributeModel, CompletionUsage): _completion_tokens_details.text_tokens = max(0, calculated_text_tokens) # handle prompt_tokens_details - _prompt_tokens_details: Optional[PromptTokensDetailsWrapper] = None + _prompt_tokens_details: PromptTokensDetailsWrapper | None = None # guarantee prompt_token_details is always a PromptTokensDetailsWrapper if prompt_tokens_details: @@ -1798,7 +1790,7 @@ class Usage(SafeAttributeModel, CompletionUsage): for k, v in params.items(): setattr(self, k, v) - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1810,7 +1802,7 @@ class Usage(SafeAttributeModel, CompletionUsage): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) @@ -1820,15 +1812,15 @@ class StreamingChoices(OpenAIObject): self, finish_reason=None, index=0, - delta: Optional[Delta] = None, + delta: Delta | None = None, logprobs=None, enhancements=None, **params, - ): + ) -> None: # Fix Perplexity return both delta and message cause OpenWebUI repect text # https://github.com/BerriAI/litellm/issues/8455 params.pop("message", None) - super(StreamingChoices, self).__init__(**params) + super().__init__(**params) if finish_reason: self.finish_reason = map_finish_reason(finish_reason) else: @@ -1849,7 +1841,7 @@ class StreamingChoices(OpenAIObject): else: self.logprobs = logprobs # type: ignore - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1861,13 +1853,13 @@ class StreamingChoices(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) class StreamingChatCompletionChunk(OpenAIChatCompletionChunk): - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: new_choices: Final = [] for choice in kwargs["choices"]: new_choice = StreamingChoices(**choice).model_dump() @@ -1884,13 +1876,13 @@ class ModelResponseBase(OpenAIObject): created: int """The Unix timestamp (in seconds) of when the completion was created.""" - model: Optional[str] = None + model: str | None = None """The model used for completion.""" object: str """The object type, which is always "text_completion" """ - system_fingerprint: Optional[str] = None + system_fingerprint: str | None = None """This fingerprint represents the backend configuration that the model runs with. Can be used in conjunction with the `seed` request parameter to understand when @@ -1899,7 +1891,7 @@ class ModelResponseBase(OpenAIObject): _hidden_params: dict = {} - _response_headers: Optional[dict] = None + _response_headers: dict | None = None def model_dump(self, **kwargs): """Default to exclude_unset to avoid Pydantic serializer warnings for OpenAIObject-derived types.""" @@ -1909,17 +1901,17 @@ class ModelResponseBase(OpenAIObject): class ModelResponseStream(ModelResponseBase): - choices: List[StreamingChoices] - provider_specific_fields: Optional[Dict[str, Any]] = Field(default=None) + choices: list[StreamingChoices] + provider_specific_fields: dict[str, Any] | None = Field(default=None) def __init__( self, - choices: Optional[Union[List[StreamingChoices], Union[StreamingChoices, dict, BaseModel]]] = None, - id: Optional[str] = None, - created: Optional[int] = None, - provider_specific_fields: Optional[Dict[str, Any]] = None, + choices: list[StreamingChoices] | StreamingChoices | dict | BaseModel | None = None, + id: str | None = None, + created: int | None = None, + provider_specific_fields: dict[str, Any] | None = None, **kwargs, - ): + ) -> None: if choices is not None and isinstance(choices, list): new_choices: Final = [] for choice in choices: @@ -1966,7 +1958,7 @@ class ModelResponseStream(ModelResponseBase): if usage_to_set is not None: self.usage = usage_to_set - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -1980,14 +1972,14 @@ class ModelResponseStream(ModelResponseBase): def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() class ModelResponse(ModelResponseBase): - choices: List[Choices] + choices: list[Choices] """The list of completion choices the model generated for the input prompt.""" def __init__( @@ -2065,7 +2057,7 @@ class ModelResponse(ModelResponseBase): **params, ) - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -2079,14 +2071,14 @@ class ModelResponse(ModelResponseBase): def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() class Embedding(OpenAIObject): - embedding: Union[list, str] = [] + embedding: list | str = [] index: int object: Literal["embedding"] @@ -2098,38 +2090,38 @@ class Embedding(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) class EmbeddingResponse(OpenAIObject): - model: Optional[str] = None + model: str | None = None """The model used for embedding.""" - data: List + data: list """The actual embedding value""" object: Literal["list"] """The object type, which is always "list" """ - usage: Optional[Usage] = None + usage: Usage | None = None """Usage statistics for the embedding request.""" _hidden_params: dict = {} - _response_headers: Optional[Dict] = None - _response_ms: Optional[float] = None + _response_headers: dict | None = None + _response_ms: float | None = None def __init__( self, - model: Optional[str] = None, - usage: Optional[Usage] = None, + model: str | None = None, + usage: Usage | None = None, response_ms=None, - data: Optional[Union[List, List[Embedding]]] = None, + data: list | list[Embedding] | None = None, hidden_params=None, _response_headers=None, **params, - ): + ) -> None: object: Final = "list" if response_ms: _response_ms = response_ms @@ -2154,7 +2146,7 @@ class EmbeddingResponse(OpenAIObject): if hidden_params: self._hidden_params = hidden_params - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -2166,28 +2158,28 @@ class EmbeddingResponse(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() class Logprobs(OpenAIObject): - text_offset: Optional[List[int]] - token_logprobs: Optional[List[Union[float, None]]] - tokens: Optional[List[str]] - top_logprobs: Optional[List[Union[Dict[str, float], None]]] + text_offset: list[int] | None + token_logprobs: list[float | None] | None + tokens: list[str] | None + top_logprobs: list[dict[str, float] | None] | None class TextChoices(OpenAIObject): - def __init__(self, finish_reason=None, index=0, text=None, logprobs=None, **params): - super(TextChoices, self).__init__(**params) + def __init__(self, finish_reason=None, index=0, text=None, logprobs=None, **params) -> None: + super().__init__(**params) if finish_reason: self.finish_reason = map_finish_reason(finish_reason) else: @@ -2205,7 +2197,7 @@ class TextChoices(OpenAIObject): else: self.logprobs = logprobs - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -2217,13 +2209,13 @@ class TextChoices(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() @@ -2251,10 +2243,10 @@ class TextCompletionResponse(OpenAIObject): id: str object: str created: int - model: Optional[str] - choices: List[TextChoices] - usage: Optional[Usage] - _response_ms: Optional[int] = None + model: str | None + choices: list[TextChoices] + usage: Usage | None + _response_ms: int | None = None _hidden_params: HiddenParams def __init__( @@ -2268,7 +2260,7 @@ class TextCompletionResponse(OpenAIObject): response_ms=None, object=None, **params, - ): + ) -> None: if stream: object = "text_completion.chunk" choices = [TextChoices()] @@ -2303,7 +2295,7 @@ class TextCompletionResponse(OpenAIObject): else: usage = Usage() - super(TextCompletionResponse, self).__init__( + super().__init__( id=id, # type: ignore object=object, # type: ignore created=created, # type: ignore @@ -2319,7 +2311,7 @@ class TextCompletionResponse(OpenAIObject): self._response_ms = None self._hidden_params = HiddenParams() - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -2331,7 +2323,7 @@ class TextCompletionResponse(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) @@ -2352,10 +2344,10 @@ class ImageObject(OpenAIImage): https://platform.openai.com/docs/api-reference/images/object """ - b64_json: Optional[str] = None - url: Optional[str] = None - revised_prompt: Optional[str] = None - provider_specific_fields: Optional[Dict[str, Any]] = None + b64_json: str | None = None + url: str | None = None + revised_prompt: str | None = None + provider_specific_fields: dict[str, Any] | None = None def __init__( self, @@ -2364,12 +2356,12 @@ class ImageObject(OpenAIImage): revised_prompt=None, provider_specific_fields=None, **kwargs, - ): + ) -> None: super().__init__(b64_json=b64_json, url=url, revised_prompt=revised_prompt) # type: ignore if provider_specific_fields: self.provider_specific_fields = provider_specific_fields - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -2381,13 +2373,13 @@ class ImageObject(OpenAIImage): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() @@ -2421,7 +2413,7 @@ from openai.types.images_response import ImagesResponse as OpenAIImageResponse class ImageResponse(OpenAIImageResponse, BaseLiteLLMOpenAIResponseObject): _hidden_params: dict = {} - usage: Optional[ImageUsage] = None # type: ignore + usage: ImageUsage | None = None # type: ignore """ Users might use litellm with older python versions, we don't want this to break for them. Happens when their OpenAIImageResponse has the old OpenAI usage class. @@ -2431,13 +2423,13 @@ class ImageResponse(OpenAIImageResponse, BaseLiteLLMOpenAIResponseObject): def __init__( self, - created: Optional[int] = None, - data: Optional[List[ImageObject]] = None, + created: int | None = None, + data: list[ImageObject] | None = None, response_ms=None, - usage: Optional[ImageUsage] = None, - hidden_params: Optional[dict] = None, + usage: ImageUsage | None = None, + hidden_params: dict | None = None, **kwargs, - ): + ) -> None: if response_ms: _response_ms = response_ms else: @@ -2452,7 +2444,7 @@ class ImageResponse(OpenAIImageResponse, BaseLiteLLMOpenAIResponseObject): else: created = int(time.time()) - _data: Final[List[OpenAIImage]] = [] + _data: Final[list[OpenAIImage]] = [] for d in data: if isinstance(d, dict): _data.append(ImageObject(**d)) @@ -2475,7 +2467,7 @@ class ImageResponse(OpenAIImageResponse, BaseLiteLLMOpenAIResponseObject): self.size = kwargs.get("size", None) self._hidden_params = hidden_params or {} - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -2487,13 +2479,13 @@ class ImageResponse(OpenAIImageResponse, BaseLiteLLMOpenAIResponseObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() @@ -2518,16 +2510,16 @@ class TranscriptionUsageTokensObject(BaseModel): class TranscriptionResponse(OpenAIObject): - text: Optional[str] = None - usage: Optional[Union[TranscriptionUsageDurationObject, TranscriptionUsageTokensObject]] = None + text: str | None = None + usage: TranscriptionUsageDurationObject | TranscriptionUsageTokensObject | None = None _hidden_params: dict = {} - _response_headers: Optional[dict] = None + _response_headers: dict | None = None - def __init__(self, text=None): + def __init__(self, text=None) -> None: super().__init__(text=text) # type: ignore - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -2539,13 +2531,13 @@ class TranscriptionResponse(OpenAIObject): # Allow dictionary-style access to attributes return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: # Allow dictionary-style assignment of attributes setattr(self, key, value) def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() @@ -2563,27 +2555,27 @@ class ResponseFormatChunk(TypedDict, total=False): class LoggedLiteLLMParams(TypedDict, total=False): - force_timeout: Optional[float] - custom_llm_provider: Optional[str] - api_base: Optional[str] - litellm_call_id: Optional[str] - model_alias_map: Optional[dict] - metadata: Optional[dict] - litellm_metadata: Optional[dict] - model_info: Optional[dict] - proxy_server_request: Optional[dict] - acompletion: Optional[bool] - preset_cache_key: Optional[str] - no_log: Optional[bool] - input_cost_per_second: Optional[float] - input_cost_per_token: Optional[float] - output_cost_per_token: Optional[float] - output_cost_per_second: Optional[float] - cooldown_time: Optional[float] + force_timeout: float | None + custom_llm_provider: str | None + api_base: str | None + litellm_call_id: str | None + model_alias_map: dict | None + metadata: dict | None + litellm_metadata: dict | None + model_info: dict | None + proxy_server_request: dict | None + acompletion: bool | None + preset_cache_key: str | None + no_log: bool | None + input_cost_per_second: float | None + input_cost_per_token: float | None + output_cost_per_token: float | None + output_cost_per_second: float | None + cooldown_time: float | None class AdapterCompletionStreamWrapper: - def __init__(self, completion_stream): + def __init__(self, completion_stream) -> None: self.completion_stream = completion_stream def __iter__(self): @@ -2602,7 +2594,7 @@ class AdapterCompletionStreamWrapper: except StopIteration: raise StopIteration except Exception as e: - print(f"AdapterCompletionStreamWrapper - {e}") # noqa + verbose_logger.debug(f"AdapterCompletionStreamWrapper - {e}") async def __anext__(self): try: @@ -2616,26 +2608,26 @@ class AdapterCompletionStreamWrapper: class StandardLoggingUserAPIKeyMetadata(TypedDict): - user_api_key_hash: Optional[str] # hash of the litellm virtual key used - user_api_key_alias: Optional[str] - user_api_key_spend: Optional[float] - user_api_key_max_budget: Optional[float] - user_api_key_budget_reset_at: Optional[str] - user_api_key_user_spend: Optional[float] - user_api_key_user_max_budget: Optional[float] - user_api_key_team_spend: Optional[float] - user_api_key_team_max_budget: Optional[float] - user_api_key_org_id: Optional[str] - user_api_key_org_alias: Optional[str] - user_api_key_team_id: Optional[str] - user_api_key_project_id: Optional[str] - user_api_key_project_alias: Optional[str] - user_api_key_user_id: Optional[str] - user_api_key_user_email: Optional[str] - user_api_key_team_alias: Optional[str] - user_api_key_end_user_id: Optional[str] - user_api_key_request_route: Optional[str] - user_api_key_auth_metadata: Optional[Dict[str, str]] + user_api_key_hash: str | None # hash of the litellm virtual key used + user_api_key_alias: str | None + user_api_key_spend: float | None + user_api_key_max_budget: float | None + user_api_key_budget_reset_at: str | None + user_api_key_user_spend: float | None + user_api_key_user_max_budget: float | None + user_api_key_team_spend: float | None + user_api_key_team_max_budget: float | None + user_api_key_org_id: str | None + user_api_key_org_alias: str | None + user_api_key_team_id: str | None + user_api_key_project_id: str | None + user_api_key_project_alias: str | None + user_api_key_user_id: str | None + user_api_key_user_email: str | None + user_api_key_team_alias: str | None + user_api_key_end_user_id: str | None + user_api_key_request_route: str | None + user_api_key_auth_metadata: dict[str, str] | None class StandardLoggingMCPToolCall(TypedDict, total=False): @@ -2652,37 +2644,37 @@ class StandardLoggingMCPToolCall(TypedDict, total=False): Result of the tool call """ - mcp_server_name: Optional[str] + mcp_server_name: str | None """ Name of the MCP server that the tool call was made to """ - mcp_server_logo_url: Optional[str] + mcp_server_logo_url: str | None """ Optional logo URL of the MCP server that the tool call was made to (this is to render the logo on the logs page on litellm ui) """ - namespaced_tool_name: Optional[str] + namespaced_tool_name: str | None """ Namespaced tool name of the MCP tool that the tool call was made to Includes the server name prefix if it exists - eg. `deepwiki-mcp/get_page_content` """ - mcp_server_cost_info: Optional[MCPServerCostInfo] + mcp_server_cost_info: MCPServerCostInfo | None """ Cost per query for the MCP server tool call """ - mcp_session_id: Optional[str] + mcp_session_id: str | None """ The MCP `mcp-session-id` of the stateful session this tool call ran in, when the client is driving a stateful session. Absent for stateless calls. """ - mcp_auth_mode: Optional[str] + mcp_auth_mode: str | None """ The server's auth_type for this call (e.g. `true_passthrough`, `oauth_delegate`, `oauth2`). For the client-forwarded token modes this records that the caller's own @@ -2690,7 +2682,7 @@ class StandardLoggingMCPToolCall(TypedDict, total=False): without logging any credential. """ - mcp_server_resource: Optional[str] + mcp_server_resource: str | None """ The origin (scheme + host + port) of the upstream MCP server the tool call was forwarded to. Redacted for logging: userinfo, the path, the query string, and the fragment are all @@ -2705,32 +2697,32 @@ class StandardLoggingVectorStoreRequest(TypedDict, total=False): Logging information for a vector store request/payload """ - vector_store_id: Optional[str] + vector_store_id: str | None """ ID of the vector store """ - custom_llm_provider: Optional[str] + custom_llm_provider: str | None """ Custom LLM provider the vector store is associated with eg. bedrock, openai, anthropic, etc. """ - query: Optional[str] + query: str | None """ Query to the vector store """ - vector_store_search_response: Optional[VectorStoreSearchResponse] + vector_store_search_response: VectorStoreSearchResponse | None """ OpenAI format vector store search response """ - start_time: Optional[float] + start_time: float | None """ Start time of the vector store request """ - end_time: Optional[float] + end_time: float | None """ End time of the vector store request """ @@ -2745,13 +2737,13 @@ class StandardBuiltInToolsParams(TypedDict, total=False): OpenAI charges users based on the `web_search_options` parameter """ - web_search_options: Optional[WebSearchOptions] - file_search: Optional[FileSearchTool] + web_search_options: WebSearchOptions | None + file_search: FileSearchTool | None class StandardLoggingPromptManagementMetadata(TypedDict): prompt_id: str - prompt_variables: Optional[dict] + prompt_variables: dict | None prompt_integration: str @@ -2815,8 +2807,8 @@ class StandardLoggingRoutingDecision(TypedDict, total=False): # logging off. Every other field aggregates the prompt without reproducing it and is kept, # so a redacted row stays explainable. `test_every_routing_decision_field_is_classified` # fails if a field is added to the record without being placed in one set or the other. -PROMPT_QUOTING_ROUTING_DECISION_FIELDS: FrozenSet[str] = frozenset({"signals", "matched_keyword", "escalation_keyword"}) -DERIVED_ROUTING_DECISION_FIELDS: Final[FrozenSet[str]] = frozenset( +PROMPT_QUOTING_ROUTING_DECISION_FIELDS: frozenset[str] = frozenset({"signals", "matched_keyword", "escalation_keyword"}) +DERIVED_ROUTING_DECISION_FIELDS: Final[frozenset[str]] = frozenset( { "router_model_name", "router_type", @@ -2840,20 +2832,20 @@ class StandardLoggingMetadata(StandardLoggingUserAPIKeyMetadata): Specific metadata k,v pairs logged to integration for easier cost tracking and prompt management """ - spend_logs_metadata: Optional[dict] # special param to log k,v pairs to spendlogs for a call - requester_ip_address: Optional[str] - user_agent: Optional[str] - requester_metadata: Optional[dict] - requester_custom_headers: Optional[Dict[str, str]] # Log any custom (`x-`) headers sent by the client to the proxy. - prompt_management_metadata: Optional[StandardLoggingPromptManagementMetadata] - mcp_tool_call_metadata: Optional[StandardLoggingMCPToolCall] - vector_store_request_metadata: Optional[List[StandardLoggingVectorStoreRequest]] + spend_logs_metadata: dict | None # special param to log k,v pairs to spendlogs for a call + requester_ip_address: str | None + user_agent: str | None + requester_metadata: dict | None + requester_custom_headers: dict[str, str] | None # Log any custom (`x-`) headers sent by the client to the proxy. + prompt_management_metadata: StandardLoggingPromptManagementMetadata | None + mcp_tool_call_metadata: StandardLoggingMCPToolCall | None + vector_store_request_metadata: list[StandardLoggingVectorStoreRequest] | None routing_decision: StandardLoggingRoutingDecision | None - applied_guardrails: Optional[List[str]] - usage_object: Optional[dict] - cold_storage_object_key: Optional[str] # S3/GCS object key for cold storage retrieval - team_alias: Optional[str] - team_id: Optional[str] + applied_guardrails: list[str] | None + usage_object: dict | None + cold_storage_object_key: str | None # S3/GCS object key for cold storage retrieval + team_alias: str | None + team_id: str | None class StandardLoggingAdditionalHeaders(TypedDict, total=False): @@ -2866,22 +2858,22 @@ class StandardLoggingAdditionalHeaders(TypedDict, total=False): class StandardLoggingHiddenParams(TypedDict): - model_id: Optional[ - str - ] # id of the model in the router, separates multiple models with the same name but different credentials - cache_key: Optional[str] - api_base: Optional[str] - response_cost: Optional[Union[str, float]] - litellm_overhead_time_ms: Optional[float] - additional_headers: Optional[StandardLoggingAdditionalHeaders] - batch_models: Optional[List[str]] - litellm_model_name: Optional[str] # the model name sent to the provider by litellm - usage_object: Optional[dict] + model_id: ( + str | None + ) # id of the model in the router, separates multiple models with the same name but different credentials + cache_key: str | None + api_base: str | None + response_cost: str | float | None + litellm_overhead_time_ms: float | None + additional_headers: StandardLoggingAdditionalHeaders | None + batch_models: list[str] | None + litellm_model_name: str | None # the model name sent to the provider by litellm + usage_object: dict | None class StandardLoggingModelInformation(TypedDict): model_map_key: str - model_map_value: Optional[ModelInfo] + model_map_value: ModelInfo | None class StandardLoggingModelCostFailureDebugInformation(TypedDict, total=False): @@ -2894,19 +2886,19 @@ class StandardLoggingModelCostFailureDebugInformation(TypedDict, total=False): error_str: Required[str] traceback_str: Required[str] model: str - cache_hit: Optional[bool] - custom_llm_provider: Optional[str] - base_model: Optional[str] + cache_hit: bool | None + custom_llm_provider: str | None + base_model: str | None call_type: str - custom_pricing: Optional[bool] + custom_pricing: bool | None class StandardLoggingPayloadErrorInformation(TypedDict, total=False): - error_code: Optional[str] - error_class: Optional[str] - llm_provider: Optional[str] - traceback: Optional[str] - error_message: Optional[str] + error_code: str | None + error_class: str | None + llm_provider: str | None + traceback: str | None + error_message: str | None # error_rate_limit_category: # For 429 / rate-limit errors, the source of the rate limit. One of the # string values defined by `litellm.exceptions.RateLimitErrorCategory` @@ -2914,7 +2906,7 @@ class StandardLoggingPayloadErrorInformation(TypedDict, total=False): # litellm_batch_rate_limit). None for non-rate-limit exceptions. # Surfaced here so custom callbacks / metrics consumers can switch on # the rate-limit source without reaching for the raw exception. - error_rate_limit_category: Optional[str] + error_rate_limit_category: str | None # error_rate_limit_type: # For 429 / rate-limit errors, the dimension that was exceeded. One of # the string values defined by `litellm.exceptions.RateLimitType` @@ -2923,36 +2915,36 @@ class StandardLoggingPayloadErrorInformation(TypedDict, total=False): # did not classify the failure (e.g. legacy vendor 429 with no header # hints). Lets dashboards split rate-limit failures by cause without # parsing free-text error messages. - error_rate_limit_type: Optional[str] - error_budget_entity_type: Optional[str] - error_budget_entity_id: Optional[str] - error_budget_limit: Optional[float] - error_budget_spend: Optional[float] + error_rate_limit_type: str | None + error_budget_entity_type: str | None + error_budget_entity_id: str | None + error_budget_limit: float | None + error_budget_spend: float | None class GuardrailMode(TypedDict, total=False): - tags: Optional[Dict[str, Union[str, List[str]]]] - default: Optional[Union[str, List[str]]] + tags: dict[str, str | list[str]] | None + default: str | list[str] | None GuardrailStatus = Literal["success", "guardrail_intervened", "guardrail_failed_to_respond", "not_run"] class StandardLoggingGuardrailInformation(TypedDict, total=False): - guardrail_name: Optional[str] - guardrail_provider: Optional[str] - guardrail_mode: Optional[Union[GuardrailEventHooks, List[GuardrailEventHooks], GuardrailMode]] - guardrail_request: Optional[Union[str, dict]] - guardrail_response: Optional[Union[dict, str, List[dict]]] + guardrail_name: str | None + guardrail_provider: str | None + guardrail_mode: GuardrailEventHooks | list[GuardrailEventHooks] | GuardrailMode | None + guardrail_request: str | dict | None + guardrail_response: dict | str | list[dict] | None guardrail_status: GuardrailStatus - start_time: Optional[float] - end_time: Optional[float] - duration: Optional[float] + start_time: float | None + end_time: float | None + duration: float | None """ Duration of the guardrail in seconds """ - masked_entity_count: Optional[Dict[str, int]] + masked_entity_count: dict[str, int] | None """ Count of masked entities { @@ -2961,34 +2953,34 @@ class StandardLoggingGuardrailInformation(TypedDict, total=False): } """ - guardrail_id: Optional[str] + guardrail_id: str | None """Unique identifier for the guardrail configuration, e.g. 'gd-eu-pii-001'""" - policy_template: Optional[str] + policy_template: str | None """Name of the policy template this guardrail belongs to, e.g. 'EU AI Act Article 5'""" - detection_method: Optional[str] + detection_method: str | None """How detection was performed: 'regex', 'keyword', 'llm-judge', 'presidio', etc.""" - confidence_score: Optional[float] + confidence_score: float | None """For LLM-judge guardrails: confidence score 0.0-1.0""" - classification: Optional[Union[str, dict]] + classification: str | dict | None """For LLM-judge guardrails: structured classification output""" - match_details: Optional[Union[str, List[dict]]] + match_details: str | list[dict] | None """Detailed match information for each detected pattern""" - patterns_checked: Optional[int] + patterns_checked: int | None """Total number of patterns evaluated by this guardrail""" - alert_recipients: Optional[List[str]] + alert_recipients: list[str] | None """Email addresses that were notified""" - risk_score: Optional[float] + risk_score: float | None """Risk score 0-10 indicating how risky the request was (higher = riskier). Computed by the guardrail provider.""" - violation_categories: Optional[List[str]] + violation_categories: list[str] | None """Names of the policy items that intervened on this request (e.g. Bedrock topic-policy topic names, content-policy filter types, PII entity types). Populated by the provider hook before redaction so downstream loggers @@ -2996,7 +2988,7 @@ class StandardLoggingGuardrailInformation(TypedDict, total=False): the raw guardrail_response blob. Empty/absent when the guardrail allowed the request through.""" - guardrail_action: Optional[str] + guardrail_action: str | None """Provider's raw top-level action string (e.g. Bedrock's ``GUARDRAIL_INTERVENED`` or ``NONE``). Populated by the provider hook so the OTEL integration can surface it as a queryable span attribute without parsing the raw @@ -3012,18 +3004,18 @@ class EvalVerdict(TypedDict, total=False): class StandardLoggingEvalInformation(TypedDict, total=False): - eval_id: Optional[str] + eval_id: str | None eval_name: str overall_score: float passed: bool judge_model: str iteration: int - eval_error: Optional[str] + eval_error: str | None start_time: str end_time: str duration: float - verdicts: List[Any] - threshold: Optional[float] + verdicts: list[Any] + threshold: float | None class GuardrailTracingDetail(TypedDict, total=False): @@ -3034,17 +3026,17 @@ class GuardrailTracingDetail(TypedDict, total=False): to enrich the StandardLoggingGuardrailInformation with provider-specific details. """ - guardrail_id: Optional[str] - policy_template: Optional[str] - detection_method: Optional[str] - confidence_score: Optional[float] - classification: Optional[dict] - match_details: Optional[List[dict]] - patterns_checked: Optional[int] - alert_recipients: Optional[List[str]] - risk_score: Optional[float] - violation_categories: Optional[List[str]] - guardrail_action: Optional[str] + guardrail_id: str | None + policy_template: str | None + detection_method: str | None + confidence_score: float | None + classification: dict | None + match_details: list[dict] | None + patterns_checked: int | None + alert_recipients: list[str] | None + risk_score: float | None + violation_categories: list[str] | None + guardrail_action: str | None StandardLoggingPayloadStatus = Literal["success", "failure"] @@ -3055,11 +3047,11 @@ class CachingDetails(TypedDict): Track all caching related metrics, fields for a given request """ - cache_hit: Optional[bool] + cache_hit: bool | None """ Whether the request hit the cache """ - cache_duration_ms: Optional[float] + cache_duration_ms: float | None """ Duration for reading from cache """ @@ -3077,8 +3069,8 @@ class CostBreakdown(TypedDict, total=False): ``optional_params``, which no log record carries. """ - service_tier: Optional[str] - data_residency: Optional[str] + service_tier: str | None + data_residency: str | None input_cost: float # Cost of raw (non-cached) input tokens only cache_read_cost: float # Cost of cache-read tokens (discounted rate) cache_creation_cost: float # Cost of cache-write tokens (premium rate) @@ -3086,7 +3078,7 @@ class CostBreakdown(TypedDict, total=False): reasoning_cost: float # Cost of reasoning tokens (subset of output_cost) total_cost: float # Total cost (input + output + tool usage) tool_usage_cost: float # Cost of usage of built-in tools - additional_costs: Dict[str, float] # Free-form additional costs (e.g., {"azure_model_router_flat_cost": 0.00014}) + additional_costs: dict[str, float] # Free-form additional costs (e.g., {"azure_model_router_flat_cost": 0.00014}) original_cost: float # Cost before discount (optional) discount_percent: float # Discount percentage applied (e.g., 0.05 = 5%) (optional) discount_amount: float # Discount amount in USD (optional) @@ -3120,22 +3112,22 @@ class StandardAuditLogPayload(TypedDict): action: str # "created" | "updated" | "deleted" | "blocked" | "rotated" table_name: str object_id: str - before_value: Optional[str] - updated_values: Optional[str] + before_value: str | None + updated_values: str | None class StandardLoggingPayload(TypedDict): id: str trace_id: str # Trace multiple LLM calls belonging to same overall request (e.g. fallbacks/retries) - litellm_call_id: Optional[str] # UUID returned in x-litellm-call-id response header + litellm_call_id: str | None # UUID returned in x-litellm-call-id response header call_type: str - stream: Optional[bool] + stream: bool | None response_cost: float - cost_breakdown: Optional[CostBreakdown] # Detailed cost breakdown - response_cost_failure_debug_info: Optional[StandardLoggingModelCostFailureDebugInformation] + cost_breakdown: CostBreakdown | None # Detailed cost breakdown + response_cost_failure_debug_info: StandardLoggingModelCostFailureDebugInformation | None status: StandardLoggingPayloadStatus status_fields: StandardLoggingPayloadStatusFields - custom_llm_provider: Optional[str] + custom_llm_provider: str | None total_tokens: int prompt_tokens: int completion_tokens: int @@ -3145,44 +3137,44 @@ class StandardLoggingPayload(TypedDict): response_time: float model_map_information: StandardLoggingModelInformation model: str - model_id: Optional[str] - model_group: Optional[str] + model_id: str | None + model_group: str | None api_base: str metadata: StandardLoggingMetadata - cache_hit: Optional[bool] - cache_key: Optional[str] + cache_hit: bool | None + cache_key: str | None saved_cache_cost: float request_tags: list - end_user: Optional[str] - requester_ip_address: Optional[str] - user_agent: Optional[str] - messages: Optional[Union[str, list, dict]] - response: Optional[Union[str, list, dict]] - error_str: Optional[str] - error_information: Optional[StandardLoggingPayloadErrorInformation] + end_user: str | None + requester_ip_address: str | None + user_agent: str | None + messages: str | list | dict | None + response: str | list | dict | None + error_str: str | None + error_information: StandardLoggingPayloadErrorInformation | None model_parameters: dict hidden_params: StandardLoggingHiddenParams - guardrail_information: Optional[List[StandardLoggingGuardrailInformation]] - standard_built_in_tools_params: Optional[StandardBuiltInToolsParams] + guardrail_information: list[StandardLoggingGuardrailInformation] | None + standard_built_in_tools_params: StandardBuiltInToolsParams | None -from typing import AsyncIterator, Iterator +from collections.abc import AsyncIterator, Iterator class CustomStreamingDecoder: async def aiter_bytes( self, iterator: AsyncIterator[bytes] - ) -> AsyncIterator[Optional[Union[GenericStreamingChunk, StreamingChatCompletionChunk]]]: + ) -> AsyncIterator[GenericStreamingChunk | StreamingChatCompletionChunk | None]: raise NotImplementedError def iter_bytes( self, iterator: Iterator[bytes] - ) -> Iterator[Optional[Union[GenericStreamingChunk, StreamingChatCompletionChunk]]]: + ) -> Iterator[GenericStreamingChunk | StreamingChatCompletionChunk | None]: raise NotImplementedError class StandardPassThroughResponseObject(TypedDict): - response: Union[str, dict] + response: str | dict OPENAI_RESPONSE_HEADERS: Final = [ @@ -3197,139 +3189,139 @@ OPENAI_RESPONSE_HEADERS: Final = [ class StandardCallbackDynamicParams(TypedDict, total=False): # Langfuse dynamic params - langfuse_public_key: Optional[str] - langfuse_secret: Optional[str] - langfuse_secret_key: Optional[str] - langfuse_host: Optional[str] + langfuse_public_key: str | None + langfuse_secret: str | None + langfuse_secret_key: str | None + langfuse_host: str | None # Langfuse prompt version - langfuse_prompt_version: Optional[int] + langfuse_prompt_version: int | None # GCS dynamic params - gcs_bucket_name: Optional[str] - gcs_path_service_account: Optional[str] + gcs_bucket_name: str | None + gcs_path_service_account: str | None # Langsmith dynamic params - langsmith_api_key: Optional[str] - langsmith_project: Optional[str] - langsmith_base_url: Optional[str] - langsmith_sampling_rate: Optional[float] - langsmith_tenant_id: Optional[str] + langsmith_api_key: str | None + langsmith_project: str | None + langsmith_base_url: str | None + langsmith_sampling_rate: float | None + langsmith_tenant_id: str | None # Humanloop dynamic params - humanloop_api_key: Optional[str] + humanloop_api_key: str | None # Arize dynamic params - arize_api_key: Optional[str] - arize_space_key: Optional[str] - arize_space_id: Optional[str] + arize_api_key: str | None + arize_space_key: str | None + arize_space_id: str | None # PostHog dynamic params - posthog_api_key: Optional[str] - posthog_api_url: Optional[str] + posthog_api_key: str | None + posthog_api_url: str | None # Weave (W&B) dynamic params - wandb_api_key: Optional[str] - weave_project_id: Optional[str] + wandb_api_key: str | None + weave_project_id: str | None # Datadog dynamic params - dd_api_key: Optional[str] - dd_site: Optional[str] - dd_agent_host: Optional[str] - dd_agent_port: Optional[str] + dd_api_key: str | None + dd_site: str | None + dd_agent_host: str | None + dd_agent_port: str | None # Logging settings - turn_off_message_logging: Optional[bool] # when true will not log messages - litellm_disabled_callbacks: Optional[List[str]] + turn_off_message_logging: bool | None # when true will not log messages + litellm_disabled_callbacks: list[str] | None class CustomPricingLiteLLMParams(BaseModel): ## CUSTOM PRICING ## - input_cost_per_token: Optional[float] = None - output_cost_per_token: Optional[float] = None - input_cost_per_second: Optional[float] = None - output_cost_per_second: Optional[float] = None - output_cost_per_second_1080p: Optional[float] = None - input_cost_per_pixel: Optional[float] = None - output_cost_per_pixel: Optional[float] = None + input_cost_per_token: float | None = None + output_cost_per_token: float | None = None + input_cost_per_second: float | None = None + output_cost_per_second: float | None = None + output_cost_per_second_1080p: float | None = None + input_cost_per_pixel: float | None = None + output_cost_per_pixel: float | None = None # Include all ModelInfoBase fields as optional # This allows any model_info parameter to be set in litellm_params - input_cost_per_token_flex: Optional[float] = None - input_cost_per_token_priority: Optional[float] = None - cache_creation_input_token_cost: Optional[float] = None - cache_creation_input_token_cost_above_1hr: Optional[float] = None - cache_creation_input_token_cost_above_200k_tokens: Optional[float] = None - cache_creation_input_token_cost_above_272k_tokens: Optional[float] = None - cache_creation_input_token_cost_above_272k_tokens_priority: Optional[float] = None - cache_creation_input_token_cost_above_272k_tokens_flex: Optional[float] = None - cache_creation_input_token_cost_flex: Optional[float] = None - cache_creation_input_token_cost_priority: Optional[float] = None - cache_creation_input_audio_token_cost: Optional[float] = None - cache_read_input_token_cost: Optional[float] = None - cache_read_input_token_cost_flex: Optional[float] = None - cache_read_input_token_cost_priority: Optional[float] = None - cache_read_input_token_cost_above_200k_tokens: Optional[float] = None - cache_read_input_token_cost_above_200k_tokens_priority: Optional[float] = None - cache_read_input_token_cost_above_272k_tokens_priority: Optional[float] = None - cache_read_input_token_cost_above_272k_tokens_flex: Optional[float] = None - cache_read_input_audio_token_cost: Optional[float] = None - input_cost_per_character: Optional[float] = None - input_cost_per_character_above_128k_tokens: Optional[float] = None - input_cost_per_audio_token: Optional[float] = None - input_cost_per_token_cache_hit: Optional[float] = None - input_cost_per_token_above_128k_tokens: Optional[float] = None - input_cost_per_token_above_200k_tokens: Optional[float] = None - input_cost_per_token_above_200k_tokens_priority: Optional[float] = None - input_cost_per_token_above_272k_tokens_priority: Optional[float] = None - input_cost_per_token_above_272k_tokens_flex: Optional[float] = None - input_cost_per_query: Optional[float] = None - input_cost_per_image: Optional[float] = None - input_cost_per_image_above_128k_tokens: Optional[float] = None - input_cost_per_audio_per_second: Optional[float] = None - input_cost_per_audio_per_second_above_128k_tokens: Optional[float] = None - input_cost_per_video_per_second: Optional[float] = None - input_cost_per_video_per_second_above_128k_tokens: Optional[float] = None - input_cost_per_video_per_second_above_15s_interval: Optional[float] = None - input_cost_per_video_per_second_above_8s_interval: Optional[float] = None - input_cost_per_token_batches: Optional[float] = None - output_cost_per_token_batches: Optional[float] = None - output_cost_per_token_flex: Optional[float] = None - output_cost_per_token_priority: Optional[float] = None - output_cost_per_character: Optional[float] = None - output_cost_per_audio_token: Optional[float] = None - output_cost_per_token_above_128k_tokens: Optional[float] = None - output_cost_per_token_above_200k_tokens: Optional[float] = None - output_cost_per_token_above_200k_tokens_priority: Optional[float] = None - output_cost_per_token_above_272k_tokens_priority: Optional[float] = None - output_cost_per_token_above_272k_tokens_flex: Optional[float] = None - output_cost_per_character_above_128k_tokens: Optional[float] = None - output_cost_per_image: Optional[float] = None - output_cost_per_image_token: Optional[float] = None - output_cost_per_video_token: Optional[float] = None - output_cost_per_reasoning_token: Optional[float] = None - output_cost_per_video_per_second: Optional[float] = None - output_cost_per_audio_per_second: Optional[float] = None - search_context_cost_per_query: Optional[Dict[str, Any]] = None - citation_cost_per_token: Optional[float] = None - tiered_pricing: Optional[List[Dict[str, Any]]] = None - cache_read_input_token_cost_above_272k_tokens: Optional[float] = None - cache_read_input_token_cost_above_512k_tokens: Optional[float] = None - input_cost_per_image_token: Optional[float] = None - input_cost_per_video_token: Optional[float] = None - input_cost_per_token_above_272k_tokens: Optional[float] = None - input_cost_per_token_above_512k_tokens: Optional[float] = None - output_cost_per_token_above_272k_tokens: Optional[float] = None - output_cost_per_token_above_512k_tokens: Optional[float] = None - output_vector_size: Optional[int] = None - ocr_cost_per_page: Optional[float] = None - ocr_cost_per_credit: Optional[float] = None - annotation_cost_per_page: Optional[float] = None - regional_processing_uplift_multiplier_eu: Optional[float] = None - regional_processing_uplift_multiplier_us: Optional[float] = None + input_cost_per_token_flex: float | None = None + input_cost_per_token_priority: float | None = None + cache_creation_input_token_cost: float | None = None + cache_creation_input_token_cost_above_1hr: float | None = None + cache_creation_input_token_cost_above_200k_tokens: float | None = None + cache_creation_input_token_cost_above_272k_tokens: float | None = None + cache_creation_input_token_cost_above_272k_tokens_priority: float | None = None + cache_creation_input_token_cost_above_272k_tokens_flex: float | None = None + cache_creation_input_token_cost_flex: float | None = None + cache_creation_input_token_cost_priority: float | None = None + cache_creation_input_audio_token_cost: float | None = None + cache_read_input_token_cost: float | None = None + cache_read_input_token_cost_flex: float | None = None + cache_read_input_token_cost_priority: float | None = None + cache_read_input_token_cost_above_200k_tokens: float | None = None + cache_read_input_token_cost_above_200k_tokens_priority: float | None = None + cache_read_input_token_cost_above_272k_tokens_priority: float | None = None + cache_read_input_token_cost_above_272k_tokens_flex: float | None = None + cache_read_input_audio_token_cost: float | None = None + input_cost_per_character: float | None = None + input_cost_per_character_above_128k_tokens: float | None = None + input_cost_per_audio_token: float | None = None + input_cost_per_token_cache_hit: float | None = None + input_cost_per_token_above_128k_tokens: float | None = None + input_cost_per_token_above_200k_tokens: float | None = None + input_cost_per_token_above_200k_tokens_priority: float | None = None + input_cost_per_token_above_272k_tokens_priority: float | None = None + input_cost_per_token_above_272k_tokens_flex: float | None = None + input_cost_per_query: float | None = None + input_cost_per_image: float | None = None + input_cost_per_image_above_128k_tokens: float | None = None + input_cost_per_audio_per_second: float | None = None + input_cost_per_audio_per_second_above_128k_tokens: float | None = None + input_cost_per_video_per_second: float | None = None + input_cost_per_video_per_second_above_128k_tokens: float | None = None + input_cost_per_video_per_second_above_15s_interval: float | None = None + input_cost_per_video_per_second_above_8s_interval: float | None = None + input_cost_per_token_batches: float | None = None + output_cost_per_token_batches: float | None = None + output_cost_per_token_flex: float | None = None + output_cost_per_token_priority: float | None = None + output_cost_per_character: float | None = None + output_cost_per_audio_token: float | None = None + output_cost_per_token_above_128k_tokens: float | None = None + output_cost_per_token_above_200k_tokens: float | None = None + output_cost_per_token_above_200k_tokens_priority: float | None = None + output_cost_per_token_above_272k_tokens_priority: float | None = None + output_cost_per_token_above_272k_tokens_flex: float | None = None + output_cost_per_character_above_128k_tokens: float | None = None + output_cost_per_image: float | None = None + output_cost_per_image_token: float | None = None + output_cost_per_video_token: float | None = None + output_cost_per_reasoning_token: float | None = None + output_cost_per_video_per_second: float | None = None + output_cost_per_audio_per_second: float | None = None + search_context_cost_per_query: dict[str, Any] | None = None + citation_cost_per_token: float | None = None + tiered_pricing: list[dict[str, Any]] | None = None + cache_read_input_token_cost_above_272k_tokens: float | None = None + cache_read_input_token_cost_above_512k_tokens: float | None = None + input_cost_per_image_token: float | None = None + input_cost_per_video_token: float | None = None + input_cost_per_token_above_272k_tokens: float | None = None + input_cost_per_token_above_512k_tokens: float | None = None + output_cost_per_token_above_272k_tokens: float | None = None + output_cost_per_token_above_512k_tokens: float | None = None + output_vector_size: int | None = None + ocr_cost_per_page: float | None = None + ocr_cost_per_credit: float | None = None + annotation_cost_per_page: float | None = None + regional_processing_uplift_multiplier_eu: float | None = None + regional_processing_uplift_multiplier_us: float | None = None @classmethod - def strip_custom_pricing_fields(cls, model_info: Dict[str, Any]) -> Dict[str, Any]: + def strip_custom_pricing_fields(cls, model_info: dict[str, Any]) -> dict[str, Any]: """Return a copy of ``model_info`` without per-deployment custom pricing fields. Used when registering a deployment's info under the shared @@ -3340,12 +3332,12 @@ class CustomPricingLiteLLMParams(BaseModel): return {k: v for k, v in model_info.items() if k not in cls.model_fields} -SHARED_BACKEND_MODEL_INFO_FIELDS: Final[FrozenSet[str]] = frozenset( +SHARED_BACKEND_MODEL_INFO_FIELDS: Final[frozenset[str]] = frozenset( ModelInfoBase.__required_keys__ | ModelInfoBase.__optional_keys__ ) - frozenset(CustomPricingLiteLLMParams.model_fields) -def shared_backend_model_info(model_info: Dict[str, Any]) -> Dict[str, Any]: +def shared_backend_model_info(model_info: dict[str, Any]) -> dict[str, Any]: """Return only the fields safe to register under a shared ``{provider}/{model}`` key in ``litellm.model_cost``: cost-map schema fields (``ModelInfoBase``) minus per-deployment pricing overrides. Per-deployment metadata (``id``, @@ -3508,15 +3500,15 @@ all_litellm_params = ( class KeyGenerationConfig(TypedDict, total=False): - required_params: List[str] # specify params that must be present in the key generation request + required_params: list[str] # specify params that must be present in the key generation request class TeamUIKeyGenerationConfig(KeyGenerationConfig): - allowed_team_member_roles: List[str] + allowed_team_member_roles: list[str] class PersonalUIKeyGenerationConfig(KeyGenerationConfig): - allowed_user_roles: List[str] + allowed_user_roles: list[str] class StandardKeyGenerationConfig(TypedDict, total=False): @@ -3525,10 +3517,10 @@ class StandardKeyGenerationConfig(TypedDict, total=False): class BudgetConfig(BaseModel): - max_budget: Optional[float] = None - budget_duration: Optional[str] = None - tpm_limit: Optional[int] = None - rpm_limit: Optional[int] = None + max_budget: float | None = None + budget_duration: str | None = None + tpm_limit: int | None = None + rpm_limit: int | None = None def __init__(self, **data: Any) -> None: # Map time_period to budget_duration if present @@ -3542,7 +3534,7 @@ class BudgetConfig(BaseModel): super().__init__(**data) -GenericBudgetConfigType = Dict[str, BudgetConfig] +GenericBudgetConfigType = dict[str, BudgetConfig] class LlmProviders(str, Enum): @@ -3757,10 +3749,10 @@ class LiteLLMLoggingBaseClass: Meant to simplify type checking for logging obj. """ - def pre_call(self, input, api_key, model=None, additional_args={}): + def pre_call(self, input, api_key, model=None, additional_args=None) -> None: pass - def post_call(self, original_response, input=None, api_key=None, additional_args={}): + def post_call(self, original_response, input=None, api_key=None, additional_args=None) -> None: pass @@ -3769,22 +3761,22 @@ class TokenCountResponse(LiteLLMPydanticObjectBase): request_model: str model_used: str tokenizer_type: str - original_response: Optional[dict] = None + original_response: dict | None = None """ Original Response from upstream API call - if an API call was made for token counting """ error: bool = False - error_message: Optional[str] = None + error_message: str | None = None """ HTTP status code from the token counting API (e.g., 200 for success, 429 for rate limit, 400 for bad request) """ - status_code: Optional[int] = None + status_code: int | None = None class CustomHuggingfaceTokenizer(TypedDict): identifier: str revision: str # usually 'main' - auth_token: Optional[str] + auth_token: str | None class LITELLM_IMAGE_VARIATION_PROVIDERS(Enum): @@ -3815,9 +3807,9 @@ class SelectTokenizerResponse(TypedDict): class LiteLLMFineTuningJob(FineTuningJob): _hidden_params: dict = {} - seed: Optional[int] = None # type: ignore + seed: int | None = None # type: ignore - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: if "error" in kwargs and kwargs["error"] is not None: # check if error is all None - if so, set error to None if all(value is None for value in kwargs["error"].values()): @@ -3828,9 +3820,9 @@ class LiteLLMFineTuningJob(FineTuningJob): class LiteLLMBatch(Batch): _hidden_params: dict = {} - usage: Optional[Usage] = None # type: ignore[assignment] + usage: Usage | None = None # type: ignore[assignment] - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -3844,7 +3836,7 @@ class LiteLLMBatch(Batch): def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() @@ -3860,10 +3852,10 @@ class LiteLLMRealtimeStreamLoggingObject(LiteLLMPydanticObjectBase): _hidden_params: dict = {} @field_serializer("results") - def _serialize_results(self, results: OpenAIRealtimeStreamList) -> List[Dict[str, Any]]: + def _serialize_results(self, results: OpenAIRealtimeStreamList) -> list[dict[str, Any]]: return [dict(event) for event in results] - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -3877,24 +3869,24 @@ class LiteLLMRealtimeStreamLoggingObject(LiteLLMPydanticObjectBase): def json(self, **kwargs): # type: ignore try: - return self.model_dump() # noqa + return self.model_dump() except Exception: # if using pydantic v1 return self.dict() class RawRequestTypedDict(TypedDict, total=False): - raw_request_api_base: Optional[str] - raw_request_body: Optional[dict] - raw_request_headers: Optional[dict] - error: Optional[str] + raw_request_api_base: str | None + raw_request_body: dict | None + raw_request_headers: dict | None + error: str | None -from litellm.models.credentials import CredentialBase as CredentialBase # noqa: E402 -from litellm.models.credentials import CredentialItem as CredentialItem # noqa: E402 from litellm.models.credentials import ( # noqa: E402 CreateCredentialItem as CreateCredentialItem, ) +from litellm.models.credentials import CredentialBase as CredentialBase # noqa: E402 +from litellm.models.credentials import CredentialItem as CredentialItem # noqa: E402 class ExtractedFileData(TypedDict): @@ -3908,9 +3900,9 @@ class ExtractedFileData(TypedDict): headers: Any additional headers for the file """ - filename: Optional[str] + filename: str | None content: bytes - content_type: Optional[str] + content_type: str | None headers: Mapping[str, str] @@ -3958,17 +3950,17 @@ class DataResidency(Enum): EU = "eu" -LLMResponseTypes = Union[ - ModelResponse, - EmbeddingResponse, - ImageResponse, - OpenAIFileObject, - LiteLLMBatch, - LiteLLMFineTuningJob, - AnthropicMessagesResponse, - ResponsesAPIResponse, - LiteLLMSendMessageResponse, -] +LLMResponseTypes = ( + ModelResponse + | EmbeddingResponse + | ImageResponse + | OpenAIFileObject + | LiteLLMBatch + | LiteLLMFineTuningJob + | AnthropicMessagesResponse + | ResponsesAPIResponse + | LiteLLMSendMessageResponse +) class DynamicPromptManagementParamLiteral(str, Enum): @@ -3986,18 +3978,12 @@ class DynamicPromptManagementParamLiteral(str, Enum): class CallbacksByType(TypedDict): - success: List[str] - failure: List[str] - success_and_failure: List[str] + success: list[str] + failure: list[str] + success_and_failure: list[str] -CostResponseTypes = Union[ - ModelResponse, - TextCompletionResponse, - EmbeddingResponse, - ImageResponse, - TranscriptionResponse, -] +CostResponseTypes = ModelResponse | TextCompletionResponse | EmbeddingResponse | ImageResponse | TranscriptionResponse class PriorityReservationDict(TypedDict, total=False): @@ -4046,16 +4032,14 @@ class PriorityReservationSettings(BaseModel): class GenericGuardrailAPIInputs(TypedDict, total=False): - texts: List[str] # extracted text from the LLM response - for basic text guardrails - images: List[str] # extracted images from the LLM response - for image guardrails - tools: List[ChatCompletionToolParam] # tools sent to the LLM - tool_calls: Union[ - List[ChatCompletionToolCallChunk], List[ChatCompletionMessageToolCall] - ] # tool calls sent from the LLM - structured_messages: List[ + texts: list[str] # extracted text from the LLM response - for basic text guardrails + images: list[str] # extracted images from the LLM response - for image guardrails + tools: list[ChatCompletionToolParam] # tools sent to the LLM + tool_calls: list[ChatCompletionToolCallChunk] | list[ChatCompletionMessageToolCall] # tool calls sent from the LLM + structured_messages: list[ AllMessageValues ] # structured messages sent to the LLM - indicates if text is from system or user - model: Optional[str] # the model being used for the LLM call - stream_holdback_chars: List[ + model: str | None # the model being used for the LLM call + stream_holdback_chars: list[ int ] # trailing chars to withhold from streaming emission per text (word-boundary safety) diff --git a/litellm/types/vector_store_files.py b/litellm/types/vector_store_files.py index 4e587a3ca24..6b4953965d5 100644 --- a/litellm/types/vector_store_files.py +++ b/litellm/types/vector_store_files.py @@ -1,7 +1,6 @@ from enum import Enum -from typing import Any, Dict, List, Literal, Optional, Tuple, Union +from typing import Any, Literal -from pydantic import BaseModel from typing_extensions import TypedDict @@ -24,44 +23,44 @@ class VectorStoreFileStaticChunkingConfig(TypedDict, total=False): class VectorStoreFileChunkingStrategy(TypedDict, total=False): type: Literal["auto", "static"] - static: Optional[VectorStoreFileStaticChunkingConfig] + static: VectorStoreFileStaticChunkingConfig | None class VectorStoreFileObject(TypedDict, total=False): id: str object: Literal["vector_store.file"] created_at: int - usage_bytes: Optional[int] + usage_bytes: int | None vector_store_id: str status: VectorStoreFileStatus - last_error: Optional[Dict[str, Any]] - chunking_strategy: Optional[VectorStoreFileChunkingStrategy] - attributes: Optional[Dict[str, Union[str, int, float, bool]]] + last_error: dict[str, Any] | None + chunking_strategy: VectorStoreFileChunkingStrategy | None + attributes: dict[str, str | int | float | bool] | None class VectorStoreFileCreateRequest(TypedDict, total=False): file_id: str - attributes: Optional[Dict[str, Union[str, int, float, bool]]] - chunking_strategy: Optional[VectorStoreFileChunkingStrategy] + attributes: dict[str, str | int | float | bool] | None + chunking_strategy: VectorStoreFileChunkingStrategy | None class VectorStoreFileUpdateRequest(TypedDict, total=False): - attributes: Dict[str, Union[str, int, float, bool]] + attributes: dict[str, str | int | float | bool] class VectorStoreFileListQueryParams(TypedDict, total=False): - after: Optional[str] - before: Optional[str] - filter: Optional[Literal["in_progress", "completed", "failed", "cancelled"]] - limit: Optional[int] - order: Optional[Literal["asc", "desc"]] + after: str | None + before: str | None + filter: Literal["in_progress", "completed", "failed", "cancelled"] | None + limit: int | None + order: Literal["asc", "desc"] | None class VectorStoreFileListResponse(TypedDict, total=False): object: Literal["list"] - data: List[VectorStoreFileObject] - first_id: Optional[str] - last_id: Optional[str] + data: list[VectorStoreFileObject] + first_id: str | None + last_id: str | None has_more: bool @@ -78,11 +77,11 @@ class VectorStoreFileContentTextPart(TypedDict, total=False): class VectorStoreFileContentResponse(TypedDict, total=False): file_id: str - filename: Optional[str] - attributes: Optional[Dict[str, Union[str, int, float, bool]]] - content: List[VectorStoreFileContentTextPart] + filename: str | None + attributes: dict[str, str | int | float | bool] | None + content: list[VectorStoreFileContentTextPart] class VectorStoreFileAuthCredentials(TypedDict, total=False): - headers: Dict[str, Any] - query_params: Dict[str, Any] + headers: dict[str, Any] + query_params: dict[str, Any] diff --git a/litellm/types/vector_stores.py b/litellm/types/vector_stores.py index f67d89c6710..d1d4a39da1e 100644 --- a/litellm/types/vector_stores.py +++ b/litellm/types/vector_stores.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import Any, Dict, Final, List, Literal, Optional, Tuple, Union +from typing import Any, Literal from pydantic import BaseModel from typing_extensions import TypedDict @@ -18,7 +18,7 @@ class LiteLLM_VectorStoreConfig(TypedDict, total=False): """Parameters for initializing a vector store on Litellm proxy config.yaml""" vector_store_name: str - litellm_params: Optional[Dict[str, Any]] + litellm_params: dict[str, Any] | None class LiteLLM_ManagedVectorStore(TypedDict, total=False): @@ -27,39 +27,39 @@ class LiteLLM_ManagedVectorStore(TypedDict, total=False): vector_store_id: str custom_llm_provider: str - vector_store_name: Optional[str] - vector_store_description: Optional[str] - vector_store_metadata: Optional[Union[Dict[str, Any], str]] - created_at: Optional[datetime] - updated_at: Optional[datetime] + vector_store_name: str | None + vector_store_description: str | None + vector_store_metadata: dict[str, Any] | str | None + created_at: datetime | None + updated_at: datetime | None # credential fields - litellm_credential_name: Optional[str] + litellm_credential_name: str | None # litellm_params - litellm_params: Optional[Dict[str, Any]] + litellm_params: dict[str, Any] | None # access control fields - team_id: Optional[str] - user_id: Optional[str] + team_id: str | None + user_id: str | None class LiteLLM_ManagedVectorStoreListResponse(TypedDict, total=False): """Response format for listing vector stores""" object: Literal["list"] # Always "list" - data: List[LiteLLM_ManagedVectorStore] - total_count: Optional[int] - current_page: Optional[int] - total_pages: Optional[int] + data: list[LiteLLM_ManagedVectorStore] + total_count: int | None + current_page: int | None + total_pages: int | None class VectorStoreUpdateRequest(BaseModel): vector_store_id: str - custom_llm_provider: Optional[str] = None - vector_store_name: Optional[str] = None - vector_store_description: Optional[str] = None - vector_store_metadata: Optional[Dict] = None + custom_llm_provider: str | None = None + vector_store_name: str | None = None + vector_store_description: str | None = None + vector_store_metadata: dict | None = None class VectorStoreDeleteRequest(BaseModel): @@ -73,41 +73,41 @@ class VectorStoreInfoRequest(BaseModel): class VectorStoreResultContent(TypedDict, total=False): """Content of a vector store result""" - text: Optional[str] - type: Optional[str] + text: str | None + type: str | None class VectorStoreSearchResult(TypedDict, total=False): """Result of a vector store search""" - score: Optional[float] - content: Optional[List[VectorStoreResultContent]] - file_id: Optional[str] - filename: Optional[str] - attributes: Optional[Dict] + score: float | None + content: list[VectorStoreResultContent] | None + file_id: str | None + filename: str | None + attributes: dict | None class VectorStoreSearchResponse(TypedDict, total=False): """Response after searching a vector store""" object: Literal["vector_store.search_results.page"] # Always "vector_store.search_results.page" - search_query: Optional[str] - data: Optional[List[VectorStoreSearchResult]] + search_query: str | None + data: list[VectorStoreSearchResult] | None class VectorStoreSearchOptionalRequestParams(TypedDict, total=False): """TypedDict for Optional parameters supported by the vector store search API.""" - filters: Optional[Dict] - max_num_results: Optional[int] - ranking_options: Optional[Dict] - rewrite_query: Optional[bool] + filters: dict | None + max_num_results: int | None + ranking_options: dict | None + rewrite_query: bool | None class VectorStoreSearchRequest(VectorStoreSearchOptionalRequestParams, total=False): """Request body for searching a vector store""" - query: Union[str, List[str]] + query: str | list[str] class VertexSearchDataStoreExtraBody(TypedDict, total=False): @@ -128,31 +128,31 @@ class VertexSearchDataStoreExtraBody(TypedDict, total=False): pageToken: str offset: int oneBoxPageSize: int - pageCategories: List[str] - imageQuery: Dict[str, Any] + pageCategories: list[str] + imageQuery: dict[str, Any] filter: str canonicalFilter: str orderBy: str - userInfo: Dict[str, Any] + userInfo: dict[str, Any] languageCode: str - facetSpecs: List[Dict[str, Any]] - boostSpec: Dict[str, Any] - params: Dict[str, Any] - queryExpansionSpec: Dict[str, Any] - spellCorrectionSpec: Dict[str, Any] + facetSpecs: list[dict[str, Any]] + boostSpec: dict[str, Any] + params: dict[str, Any] + queryExpansionSpec: dict[str, Any] + spellCorrectionSpec: dict[str, Any] userPseudoId: str - contentSearchSpec: Dict[str, Any] + contentSearchSpec: dict[str, Any] rankingExpression: str rankingExpressionBackend: str safeSearch: bool - userLabels: Dict[str, str] - naturalLanguageQueryUnderstandingSpec: Dict[str, Any] - searchAsYouTypeSpec: Dict[str, Any] - displaySpec: Dict[str, Any] - crowdingSpecs: List[Dict[str, Any]] + userLabels: dict[str, str] + naturalLanguageQueryUnderstandingSpec: dict[str, Any] + searchAsYouTypeSpec: dict[str, Any] + displaySpec: dict[str, Any] + crowdingSpecs: list[dict[str, Any]] relevanceThreshold: str - relevanceScoreSpec: Dict[str, Any] - customRankingParams: Dict[str, Any] + relevanceScoreSpec: dict[str, Any] + customRankingParams: dict[str, Any] class VertexSearchEngineExtraBody(VertexSearchDataStoreExtraBody, total=False): @@ -166,7 +166,7 @@ class VertexSearchEngineExtraBody(VertexSearchDataStoreExtraBody, total=False): (per-store scoping/filtering) and ``numResultsPerDataStore``. """ - dataStoreSpecs: List[Dict[str, Any]] + dataStoreSpecs: list[dict[str, Any]] numResultsPerDataStore: int @@ -203,7 +203,7 @@ class VectorStoreChunkingStrategy(TypedDict, total=False): # This can be either auto or static type: Literal["auto", "static"] - static: Optional[VectorStoreStaticChunkingStrategyConfig] + static: VectorStoreStaticChunkingStrategyConfig | None class VectorStoreFileCounts(TypedDict, total=False): @@ -219,17 +219,17 @@ class VectorStoreFileCounts(TypedDict, total=False): class VectorStoreCreateOptionalRequestParams(TypedDict, total=False): """TypedDict for Optional parameters supported by the vector store create API.""" - name: Optional[str] # Name of the vector store - file_ids: Optional[List[str]] # List of File IDs that the vector store should use - expires_after: Optional[VectorStoreExpirationPolicy] # Expiration policy for the vector store - chunking_strategy: Optional[VectorStoreChunkingStrategy] # Chunking strategy for the files - metadata: Optional[Dict[str, str]] # Set of key-value pairs for metadata + name: str | None # Name of the vector store + file_ids: list[str] | None # List of File IDs that the vector store should use + expires_after: VectorStoreExpirationPolicy | None # Expiration policy for the vector store + chunking_strategy: VectorStoreChunkingStrategy | None # Chunking strategy for the files + metadata: dict[str, str] | None # Set of key-value pairs for metadata class VectorStoreCreateRequest(VectorStoreCreateOptionalRequestParams, total=False): """Request body for creating a vector store""" - pass # All fields are optional for vector store creation + # All fields are optional for vector store creation class VectorStoreCreateResponse(TypedDict, total=False): @@ -238,14 +238,14 @@ class VectorStoreCreateResponse(TypedDict, total=False): id: str # ID of the vector store object: Literal["vector_store"] # Always "vector_store" created_at: int # Unix timestamp of when the vector store was created - name: Optional[str] # Name of the vector store + name: str | None # Name of the vector store bytes: int # Size of the vector store in bytes file_counts: VectorStoreFileCounts # File counts for the vector store status: Literal["expired", "in_progress", "completed"] # Status of the vector store - expires_after: Optional[VectorStoreExpirationPolicy] # Expiration policy - expires_at: Optional[int] # Unix timestamp of when the vector store expires - last_active_at: Optional[int] # Unix timestamp of when the vector store was last active - metadata: Optional[Dict[str, str]] # Metadata associated with the vector store + expires_after: VectorStoreExpirationPolicy | None # Expiration policy + expires_at: int | None # Unix timestamp of when the vector store expires + last_active_at: int | None # Unix timestamp of when the vector store was last active + metadata: dict[str, str] | None # Metadata associated with the vector store class IndexCreateLiteLLMParams(BaseModel): @@ -256,7 +256,7 @@ class IndexCreateLiteLLMParams(BaseModel): class IndexCreateRequest(BaseModel): index_name: str litellm_params: IndexCreateLiteLLMParams - index_info: Optional[Dict[str, Any]] = None + index_info: dict[str, Any] | None = None class BaseVectorStoreAuthCredentials(TypedDict, total=False): @@ -270,11 +270,11 @@ class LiteLLM_ManagedVectorStoreIndex(BaseModel): id: str index_name: str litellm_params: IndexCreateLiteLLMParams - index_info: Optional[Dict[str, Any]] = None - created_at: Optional[datetime] = None - created_by: Optional[str] = None - updated_at: Optional[datetime] = None - updated_by: Optional[str] = None + index_info: dict[str, Any] | None = None + created_at: datetime | None = None + created_by: str | None = None + updated_at: datetime | None = None + updated_by: str | None = None class VectorStoreIndexType(str, Enum): @@ -287,11 +287,11 @@ class VectorStoreIndexType(str, Enum): class VectorStoreIndexEndpoints(TypedDict): """Endpoints for vector store index""" - read: List[ - Tuple[Literal["GET", "POST", "PUT", "DELETE", "PATCH"], str] + read: list[ + tuple[Literal["GET", "POST", "PUT", "DELETE", "PATCH"], str] ] # endpoints for reading a vector store index - write: List[ - Tuple[Literal["GET", "POST", "PUT", "DELETE", "PATCH"], str] + write: list[ + tuple[Literal["GET", "POST", "PUT", "DELETE", "PATCH"], str] ] # endpoints for writing a vector store index @@ -307,11 +307,11 @@ VECTOR_STORE_OPENAI_PARAMS = Literal[ class VectorStoreToolParams: """Parameters extracted from a file_search tool definition""" - filters: Optional[Dict] = None - max_num_results: Optional[int] = None - ranking_options: Optional[Dict] = None + filters: dict | None = None + max_num_results: int | None = None + ranking_options: dict | None = None - def to_dict(self) -> Dict: + def to_dict(self) -> dict: """Convert to dict, excluding None values""" return { k: v diff --git a/litellm/types/videos/main.py b/litellm/types/videos/main.py index 30b862886bc..07acb0cf4ed 100644 --- a/litellm/types/videos/main.py +++ b/litellm/types/videos/main.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Literal from openai.types.audio.transcription_create_params import FileTypes # type: ignore from pydantic import BaseModel @@ -11,19 +11,19 @@ class VideoObject(BaseModel): id: str object: Literal["video"] status: str - created_at: Optional[int] = None - completed_at: Optional[int] = None - expires_at: Optional[int] = None - error: Optional[Dict[str, Any]] = None - progress: Optional[int] = None - remixed_from_video_id: Optional[str] = None - seconds: Optional[str] = None - size: Optional[str] = None - model: Optional[str] = None - usage: Optional[Dict[str, Any]] = None - _hidden_params: Dict[str, Any] = {} + created_at: int | None = None + completed_at: int | None = None + expires_at: int | None = None + error: dict[str, Any] | None = None + progress: int | None = None + remixed_from_video_id: str | None = None + seconds: str | None = None + size: str | None = None + model: str | None = None + usage: dict[str, Any] | None = None + _hidden_params: dict[str, Any] = {} - def __contains__(self, key): + def __contains__(self, key) -> bool: # Define custom behavior for the 'in' operator return hasattr(self, key) @@ -46,10 +46,10 @@ class VideoObject(BaseModel): class VideoResponse(BaseModel): """Response object for video generation requests.""" - data: List[VideoObject] - hidden_params: Dict[str, Any] = {} + data: list[VideoObject] + hidden_params: dict[str, Any] = {} - def __contains__(self, key): + def __contains__(self, key) -> bool: return hasattr(self, key) def get(self, key, default=None): @@ -72,16 +72,16 @@ class VideoCreateOptionalRequestParams(TypedDict, total=False): Params here: https://platform.openai.com/docs/api-reference/videos/create """ - input_reference: Optional[FileTypes] # File reference for input image - image: Optional[Any] # Image for image-to-video; dict with gcsUri/bytesBase64Encoded, or file-like object - parameters: Optional[Dict[str, Any]] # Provider-specific parameters block passed directly to the API - model: Optional[str] - seconds: Optional[str] - size: Optional[str] - characters: Optional[List[Dict[str, str]]] - user: Optional[str] - extra_headers: Optional[Dict[str, str]] - extra_body: Optional[Dict[str, str]] + input_reference: FileTypes | None # File reference for input image + image: Any | None # Image for image-to-video; dict with gcsUri/bytesBase64Encoded, or file-like object + parameters: dict[str, Any] | None # Provider-specific parameters block passed directly to the API + model: str | None + seconds: str | None + size: str | None + characters: list[dict[str, str]] | None + user: str | None + extra_headers: dict[str, str] | None + extra_body: dict[str, str] | None class VideoCreateRequestParams(VideoCreateOptionalRequestParams, total=False): @@ -97,8 +97,8 @@ class VideoCreateRequestParams(VideoCreateOptionalRequestParams, total=False): class DecodedVideoId(TypedDict, total=False): """Structure representing a decoded video ID""" - custom_llm_provider: Optional[str] - model_id: Optional[str] + custom_llm_provider: str | None + model_id: str | None video_id: str @@ -109,9 +109,9 @@ class CharacterObject(BaseModel): object: Literal["character"] = "character" created_at: int name: str - _hidden_params: Dict[str, Any] = {} + _hidden_params: dict[str, Any] = {} - def __contains__(self, key): + def __contains__(self, key) -> bool: return hasattr(self, key) def get(self, key, default=None): @@ -131,7 +131,7 @@ class VideoEditRequestParams(TypedDict, total=False): """TypedDict for video edit request parameters.""" prompt: str - video: Dict[str, str] # {"id": "video_123"} + video: dict[str, str] # {"id": "video_123"} class VideoExtensionRequestParams(TypedDict, total=False): @@ -139,4 +139,4 @@ class VideoExtensionRequestParams(TypedDict, total=False): prompt: str seconds: str - video: Dict[str, str] # {"id": "video_123"} + video: dict[str, str] # {"id": "video_123"} diff --git a/litellm/types/videos/utils.py b/litellm/types/videos/utils.py index bc08862dc63..b23b2269543 100644 --- a/litellm/types/videos/utils.py +++ b/litellm/types/videos/utils.py @@ -6,7 +6,7 @@ Format: vid_{base64_encoded_string} """ import base64 -from typing import Final, Optional, Tuple +from typing import Final from litellm._logging import verbose_logger from litellm.types.utils import SpecialEnums @@ -20,8 +20,8 @@ CHARACTER_ID_TEMPLATE: Final = "litellm:custom_llm_provider:{};model_id:{};chara class DecodedCharacterId(dict): """Structure representing a decoded character ID.""" - custom_llm_provider: Optional[str] - model_id: Optional[str] + custom_llm_provider: str | None + model_id: str | None character_id: str @@ -35,7 +35,7 @@ def _add_base64_padding(value: str) -> str: return value -def encode_video_id_with_provider(video_id: str, provider: str, model_id: Optional[str] = None) -> str: +def encode_video_id_with_provider(video_id: str, provider: str, model_id: str | None = None) -> str: """Encode provider and model_id into video_id using base64.""" if not provider or not video_id: return video_id @@ -119,7 +119,7 @@ def extract_original_video_id(encoded_video_id: str) -> str: return decoded.get("video_id", encoded_video_id) -def encode_character_id_with_provider(character_id: str, provider: str, model_id: Optional[str] = None) -> str: +def encode_character_id_with_provider(character_id: str, provider: str, model_id: str | None = None) -> str: """Encode provider and model_id into character_id using base64.""" if not provider or not character_id: return character_id diff --git a/ruff-strict-budget.json b/ruff-strict-budget.json index 5d41835b9dc..b5ffdf03de7 100644 --- a/ruff-strict-budget.json +++ b/ruff-strict-budget.json @@ -1,12 +1,12 @@ { "ANN001": { - "limit": 3097 + "limit": 3132 }, "ANN002": { - "limit": 69 + "limit": 71 }, "ANN003": { - "limit": 831 + "limit": 840 }, "ANN201": { "limit": 2137 @@ -21,10 +21,10 @@ "limit": 127 }, "ANN206": { - "limit": 130 + "limit": 133 }, "ANN401": { - "limit": 1848 + "limit": 1861 }, "ASYNC230": { "limit": 14 @@ -60,7 +60,7 @@ "limit": 0 }, "BLE001": { - "limit": 2899 + "limit": 2926 }, "C401": { "limit": 11 @@ -81,7 +81,7 @@ "limit": 4 }, "C901": { - "limit": 310 + "limit": 315 }, "D419": { "limit": 9 @@ -162,7 +162,7 @@ "limit": 0 }, "PLC0414": { - "limit": 38 + "limit": 46 }, "PLR0124": { "limit": 4 @@ -189,7 +189,7 @@ "limit": 0 }, "PLW0127": { - "limit": 43 + "limit": 57 }, "PLW0133": { "limit": 4 @@ -228,7 +228,7 @@ "limit": 0 }, "RUF012": { - "limit": 168 + "limit": 241 }, "RUF015": { "limit": 11 @@ -306,7 +306,7 @@ "limit": 0 }, "TID251": { - "limit": 0 + "limit": 1248 }, "TRY002": { "limit": 547 diff --git a/ruff.toml b/ruff.toml index b652e206f41..095e3e24c52 100644 --- a/ruff.toml +++ b/ruff.toml @@ -16,11 +16,17 @@ format.exclude = ["**/enterprise/**"] # Was the top-level `exclude`. Scoped to lint so `ruff format` still formats these paths # (Black did) while `ruff check` keeps skipping them. -lint.exclude = ["litellm/types/*", "litellm/__init__.py", "litellm/proxy/example_config_yaml/*", "tests/*"] +lint.exclude = ["litellm/__init__.py", "litellm/proxy/example_config_yaml/*", "tests/*"] [lint.per-file-ignores] "litellm/main.py" = ["F401"] +"litellm/types/caching.py" = ["F401"] +"litellm/types/integrations/slack_alerting.py" = ["F401"] +"litellm/types/llms/custom_http.py" = ["F401"] +"litellm/types/llms/openai.py" = ["F401"] +"litellm/types/proxy/management_endpoints/scim_v2.py" = ["F401"] +"litellm/types/responses/main.py" = ["F401"] "litellm/utils.py" = ["F401"] "litellm/proxy/proxy_server.py" = ["F401"] "litellm/caching/__init__.py" = ["F401"] diff --git a/tests/test_litellm/llms/volcengine/responses/test_volcengine_responses_transformation.py b/tests/test_litellm/llms/volcengine/responses/test_volcengine_responses_transformation.py index 4581f4af7b6..891d1c15c61 100644 --- a/tests/test_litellm/llms/volcengine/responses/test_volcengine_responses_transformation.py +++ b/tests/test_litellm/llms/volcengine/responses/test_volcengine_responses_transformation.py @@ -482,3 +482,26 @@ class TestVolcengineStreamingFieldFill: assert validated.payload.count == 0 assert validated.payload.parts == [] assert validated.payload.label is None + + +class _Pep604Envelope(BaseModel): + payload: _FillWidget | _FillGadget + note: str | None + values: list[str] | str + + +class TestVolcenginePep604FieldFill: + def test_fill_handles_pep604_union_spellings(self): + filled = VolcEngineResponsesAPIConfig._fill_missing_fields( + {"payload": {"type": "widget"}}, + _Pep604Envelope, + ) + + assert filled["note"] is None + assert filled["values"] == [] + + validated = _Pep604Envelope.model_validate(filled) + assert isinstance(validated.payload, _FillWidget) + assert validated.payload.count == 0 + assert validated.payload.parts == [] + assert validated.payload.label is None diff --git a/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py b/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py index 1c452e2fb6c..4cc01a18baf 100644 --- a/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py +++ b/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py @@ -2450,3 +2450,16 @@ def test_strict_guardrail_modes_flag_controls_raise_vs_warn(monkeypatch, caplog) ) assert instance is not None assert any("not in the supported event hooks" in rec.message for rec in caplog.records) + + +def test_field_type_inference_handles_pep604_unions(): + from litellm.proxy.guardrails.guardrail_endpoints import ( + _get_field_type_from_annotation, + _unwrap_optional_type, + ) + + assert _get_field_type_from_annotation(Optional[int]) == "number" + assert _get_field_type_from_annotation(int | None) == "number" + assert _get_field_type_from_annotation(list[str] | None) == "array" + assert _get_field_type_from_annotation(bool | None) == "boolean" + assert _unwrap_optional_type(str | None) is str diff --git a/ui/litellm-dashboard/src/lib/http/schema.d.ts b/ui/litellm-dashboard/src/lib/http/schema.d.ts index df85decc676..6df507a41cd 100644 --- a/ui/litellm-dashboard/src/lib/http/schema.d.ts +++ b/ui/litellm-dashboard/src/lib/http/schema.d.ts @@ -26616,7 +26616,7 @@ export interface components { [key: string]: unknown; } | null; /** Stream Timeout */ - stream_timeout?: string | number | null; + stream_timeout?: number | string | null; /** Tag Regex */ tag_regex?: string[] | null; /** Tags */ @@ -35175,7 +35175,7 @@ export interface components { [key: string]: unknown; } | null; /** Stream Timeout */ - stream_timeout?: string | number | null; + stream_timeout?: number | string | null; /** Tag Regex */ tag_regex?: string[] | null; /** Tags */