From 17bfd415aeb5a57fb646b5cc67da1c730aa7c50b Mon Sep 17 00:00:00 2001 From: Mateo Wang <277851410+mateo-berri@users.noreply.github.com> Date: Thu, 25 Jun 2026 11:27:43 -0700 Subject: [PATCH] chore: migrate Python formatter from black to ruff format (#31317) --- .github/workflows/test-linting.yml | 4 +- Makefile | 16 +- litellm/__init__.py | 42 ++-- litellm/_redis.py | 11 +- litellm/assistants/main.py | 32 ++- litellm/assistants/utils.py | 4 +- litellm/batches/main.py | 22 +- litellm/budget_manager.py | 4 +- litellm/caching/caching_handler.py | 13 +- litellm/caching/redis_cluster_cache.py | 3 +- .../handler.py | 4 +- .../transformation.py | 22 +- litellm/constants.py | 51 ++-- litellm/cost_calculator.py | 8 +- litellm/files/main.py | 26 +- litellm/fine_tuning/main.py | 41 +++- .../google_genai/adapters/transformation.py | 6 +- litellm/images/main.py | 24 +- .../SlackAlerting/hanging_request_check.py | 8 +- .../SlackAlerting/slack_alerting.py | 22 +- litellm/integrations/braintrust_logging.py | 6 +- .../integrations/braintrust_mock_client.py | 2 +- litellm/integrations/custom_logger.py | 4 +- .../integrations/datadog/datadog_metrics.py | 4 +- .../focus/destinations/vantage_destination.py | 2 +- .../gcs_bucket/gcs_bucket_mock_client.py | 7 +- .../gitlab/gitlab_prompt_manager.py | 29 ++- litellm/integrations/lago.py | 14 +- .../integrations/langfuse/langfuse_handler.py | 6 +- litellm/integrations/langsmith.py | 3 +- litellm/integrations/mock_client_factory.py | 8 +- litellm/integrations/opik/opik.py | 8 +- litellm/integrations/otel/mappers/__init__.py | 2 +- litellm/integrations/otel/mappers/genai.py | 9 +- litellm/integrations/otel/mappers/langfuse.py | 1 - .../integrations/otel/mappers/langtrace.py | 1 - litellm/integrations/otel/model/baggage.py | 8 +- litellm/integrations/prometheus.py | 4 +- litellm/integrations/rubrik.py | 3 +- .../vector_store_pre_call_hook.py | 12 +- litellm/litellm_core_utils/core_helpers.py | 6 +- .../exception_mapping_utils.py | 21 +- .../get_llm_provider_logic.py | 10 +- litellm/litellm_core_utils/litellm_logging.py | 88 +++++-- .../litellm_core_utils/llm_cost_calc/utils.py | 12 +- .../convert_dict_to_response.py | 24 +- .../logging_callback_manager.py | 3 +- .../prompt_templates/factory.py | 14 +- .../litellm_core_utils/realtime_streaming.py | 4 +- litellm/litellm_core_utils/rules.py | 16 +- .../sensitive_data_masker.py | 4 +- .../streaming_chunk_builder_utils.py | 21 +- .../litellm_core_utils/streaming_handler.py | 18 +- litellm/llms/__init__.py | 6 +- .../chat/guardrail_translation/handler.py | 6 +- litellm/llms/anthropic/chat/handler.py | 4 +- litellm/llms/anthropic/chat/transformation.py | 8 +- litellm/llms/anthropic/common_utils.py | 3 +- .../adapters/streaming_iterator.py | 4 +- .../adapters/transformation.py | 18 +- .../messages/streaming_iterator.py | 2 +- .../responses_adapters/streaming_iterator.py | 6 +- litellm/llms/azure/assistants.py | 10 +- litellm/llms/azure/audio_transcriptions.py | 10 +- litellm/llms/azure/azure.py | 30 ++- litellm/llms/azure/batches/handler.py | 4 +- litellm/llms/azure/files/handler.py | 8 +- .../bedrock/chat/agentcore/transformation.py | 9 +- litellm/llms/bedrock/chat/converse_handler.py | 26 +- .../bedrock/chat/converse_transformation.py | 4 +- litellm/llms/bedrock/chat/invoke_handler.py | 56 +++-- litellm/llms/bedrock/embed/embedding.py | 12 +- litellm/llms/bedrock/image_edit/handler.py | 12 +- .../image_edit/stability_transformation.py | 4 +- .../amazon_nova_canvas_transformation.py | 11 +- .../bedrock/image_generation/image_handler.py | 12 +- litellm/llms/bedrock/realtime/handler.py | 4 +- litellm/llms/bedrock/rerank/handler.py | 8 +- .../bedrock/vector_stores/transformation.py | 6 +- litellm/llms/custom_httpx/http_handler.py | 101 ++++++-- litellm/llms/custom_httpx/httpx_handler.py | 5 +- .../llms/fireworks_ai/chat/transformation.py | 10 +- .../llms/gemini/realtime/transformation.py | 6 +- litellm/llms/github_copilot/authenticator.py | 4 +- .../responses/transformation.py | 3 +- litellm/llms/inception/chat/transformation.py | 6 +- litellm/llms/llamafile/chat/transformation.py | 6 +- litellm/llms/moonshot/chat/transformation.py | 6 +- .../llms/nvidia_nim/rerank/transformation.py | 10 +- litellm/llms/oci/chat/cohere.py | 4 +- litellm/llms/oci/chat/transformation.py | 3 +- litellm/llms/oci/common_utils.py | 4 +- litellm/llms/ollama/chat/transformation.py | 4 +- .../llms/ollama/completion/transformation.py | 3 +- litellm/llms/oobabooga/chat/transformation.py | 4 +- .../llms/openai/chat/gpt_transformation.py | 11 +- .../chat/guardrail_translation/handler.py | 10 +- litellm/llms/openai/completion/handler.py | 18 +- .../llms/openai/image_variations/handler.py | 4 +- litellm/llms/openai/openai.py | 40 ++- .../guardrail_translation/handler.py | 6 +- litellm/llms/openai/transcriptions/handler.py | 18 +- litellm/llms/openai_like/embedding/handler.py | 12 +- .../llms/perplexity/chat/transformation.py | 6 +- litellm/llms/replicate/chat/handler.py | 8 +- litellm/llms/sap/chat/transformation.py | 6 +- litellm/llms/sap/credentials.py | 17 +- litellm/llms/sap/embed/transformation.py | 2 +- .../stability/image_edit/transformations.py | 4 +- .../llms/tinyfish/search/transformation.py | 6 +- litellm/llms/vertex_ai/batches/handler.py | 6 +- litellm/llms/vertex_ai/common_utils.py | 3 +- .../vertex_ai_context_caching.py | 8 +- litellm/llms/vertex_ai/cost_calculator.py | 24 +- .../llms/vertex_ai/gemini/transformation.py | 14 +- .../vertex_and_google_ai_studio_gemini.py | 37 +-- .../vertex_embeddings/embedding_handler.py | 24 +- litellm/llms/vertex_ai/vertex_llm_base.py | 26 +- .../llms/volcengine/chat/transformation.py | 6 +- litellm/llms/watsonx/common_utils.py | 4 +- .../llms/watsonx/completion/transformation.py | 2 +- litellm/llms/xai/chat/transformation.py | 1 - litellm/main.py | 32 ++- litellm/passthrough/main.py | 4 +- .../mcp_server/auth/user_api_key_auth_mcp.py | 12 +- litellm/proxy/_experimental/mcp_server/db.py | 3 +- .../mcp_server/mcp_server_manager.py | 2 +- .../proxy/_experimental/mcp_server/server.py | 18 +- litellm/proxy/_types.py | 12 +- .../proxy/agent_endpoints/a2a_endpoints.py | 56 +++-- .../proxy/agent_endpoints/agent_registry.py | 11 +- .../proxy/auth/auth_checks_organization.py | 4 +- litellm/proxy/auth/handle_jwt.py | 27 +- litellm/proxy/batches_endpoints/endpoints.py | 10 +- litellm/proxy/common_request_processing.py | 10 +- litellm/proxy/common_utils/callback_utils.py | 14 +- .../proxy/common_utils/custom_openapi_spec.py | 6 +- .../container_endpoints/handler_factory.py | 13 +- litellm/proxy/db/db_spend_update_writer.py | 12 +- .../daily_spend_update_queue.py | 6 +- .../redis_update_buffer.py | 28 +-- .../spend_update_queue.py | 6 +- litellm/proxy/db/dynamo_db.py | 5 +- litellm/proxy/db/log_db_metrics.py | 4 +- .../proxy/guardrails/guardrail_endpoints.py | 25 +- .../guardrail_hooks/azure/text_moderation.py | 4 +- .../cisco_ai_defense/cisco_ai_defense.py | 15 +- .../litellm_content_filter/content_filter.py | 12 +- .../llm_as_a_judge/__init__.py | 4 +- .../model_armor/model_armor.py | 4 +- .../guardrails/guardrail_hooks/noma/noma.py | 6 +- .../panw_prisma_airs/panw_prisma_airs.py | 2 +- .../guardrails/guardrail_hooks/presidio.py | 41 ++-- .../guardrail_hooks/repelloai/repelloai.py | 14 +- .../proxy/guardrails/guardrail_registry.py | 4 +- litellm/proxy/guardrails/init_guardrails.py | 4 +- litellm/proxy/health_check.py | 9 +- litellm/proxy/hooks/dynamic_rate_limiter.py | 28 +-- .../proxy/hooks/key_management_event_hooks.py | 8 +- .../proxy/hooks/parallel_request_limiter.py | 16 +- .../hooks/parallel_request_limiter_v3.py | 16 +- .../proxy/hooks/prompt_injection_detection.py | 5 +- .../proxy/hooks/proxy_track_cost_callback.py | 14 +- .../hooks/user_management_event_hooks.py | 6 +- litellm/proxy/litellm_pre_call_utils.py | 90 +++---- .../common_daily_activity.py | 34 ++- .../customer_endpoints.py | 19 +- .../internal_user_endpoints.py | 7 +- .../key_management_endpoints.py | 72 +++--- .../mcp_management_endpoints.py | 6 +- .../model_management_endpoints.py | 4 +- .../organization_endpoints.py | 4 +- .../team_callback_endpoints.py | 6 +- .../management_endpoints/team_endpoints.py | 18 +- litellm/proxy/management_endpoints/ui_sso.py | 26 +- .../usage_endpoints/ai_usage_chat.py | 7 +- .../object_permission_utils.py | 8 +- litellm/proxy/management_helpers/utils.py | 14 +- .../openai_files_endpoints/files_endpoints.py | 16 +- .../llm_passthrough_endpoints.py | 4 +- .../openai_passthrough_logging_handler.py | 4 +- .../vertex_passthrough_logging_handler.py | 6 +- .../pass_through_endpoints.py | 8 +- litellm/proxy/prompts/prompt_registry.py | 10 +- litellm/proxy/proxy_cli.py | 5 +- litellm/proxy/proxy_server.py | 231 ++++++++++++++---- .../response_polling/background_streaming.py | 4 +- .../spend_management_endpoints.py | 16 +- .../proxy_setting_endpoints.py | 3 +- litellm/proxy/utils.py | 32 +-- .../proxy/vector_store_endpoints/endpoints.py | 6 +- litellm/rag/ingestion/base_ingestion.py | 4 +- litellm/rag/ingestion/vertex_ai_ingestion.py | 10 +- .../handler.py | 38 ++- .../session_handler.py | 8 +- .../streaming_iterator.py | 13 +- .../transformation.py | 10 +- litellm/responses/main.py | 4 +- .../responses/mcp/mcp_streaming_iterator.py | 6 +- litellm/router.py | 72 +++--- .../router_strategy/base_routing_strategy.py | 4 +- .../evals/eval_complexity_router.py | 2 +- litellm/router_strategy/lowest_latency.py | 6 +- litellm/router_strategy/lowest_tpm_rpm_v2.py | 25 +- .../encrypted_content_affinity_check.py | 6 +- litellm/sandbox/sandbox_tools.py | 13 +- litellm/types/google_genai/main.py | 4 +- litellm/types/integrations/prometheus.py | 12 +- litellm/types/llms/openai.py | 2 +- .../guardrails/guardrail_hooks/xecguard.py | 4 +- litellm/types/router.py | 8 +- litellm/utils.py | 60 +++-- pyproject.toml | 1 - ruff.toml | 11 +- uv.lock | 81 +----- 215 files changed, 1877 insertions(+), 1241 deletions(-) diff --git a/.github/workflows/test-linting.yml b/.github/workflows/test-linting.yml index 47f51598db2..f7c53ff443a 100644 --- a/.github/workflows/test-linting.yml +++ b/.github/workflows/test-linting.yml @@ -50,10 +50,10 @@ jobs: run: | uv sync --frozen - - name: Check Black formatting + - name: Check ruff format run: | cd litellm - uv run --no-sync black --check --exclude '/enterprise/' . + uv run --no-sync ruff format --check --line-length 88 --exclude '/enterprise/' . cd .. - name: Debug - Check file state diff --git a/Makefile b/Makefile index 076eac0f4a7..7c74526e130 100644 --- a/Makefile +++ b/Makefile @@ -20,13 +20,13 @@ help: @echo " make install-test-deps - Install the full local test environment" @echo " make install-helm-unittest - Install helm unittest plugin" @echo " make install-hooks - Install git hooks (Conventional Commits + Branches)" - @echo " make format - Apply Black code formatting" - @echo " make format-check - Check Black code formatting (matches CI)" - @echo " make lint - Run all linting (Ruff, basedpyright, Black check, circular imports, import safety)" + @echo " make format - Apply ruff format code formatting" + @echo " make format-check - Check ruff format code formatting (matches CI)" + @echo " make lint - Run all linting (Ruff, basedpyright, format check, circular imports, import safety)" @echo " make lint-ruff - Run Ruff linting only" @echo " make lint-basedpyright - Run basedpyright strict, gated by per-rule error counts" @echo " make lint-basedpyright-budget-update - Re-capture the basedpyright per-rule budget (ratchet)" - @echo " make lint-black - Check Black formatting (matches CI)" + @echo " make lint-format - Check ruff format formatting (matches CI)" @echo " make lint-ruff-budget - Gate the codebase total of each strict ruff rule against its ceiling" @echo " make lint-gate - Strict ruff gate in CI-parity mode (fetches staging, simulates the merge)" @echo " make lint-ruff-budget-update - Re-capture per-rule baselines in ruff-strict-budget.json (ratchet)" @@ -82,11 +82,13 @@ install-hooks: ./scripts/install_git_hooks.sh # Formatting +# 88-column wrap matches the Black width the whole repo is formatted to; ruff.toml's +# global line-length is 120 (for E501/isort), so 88 is forced here. format: install-dev - cd litellm && $(UV_RUN) black . && cd .. + cd litellm && $(UV_RUN) ruff format --line-length 88 --exclude '/enterprise/' . && cd .. format-check: install-dev - cd litellm && $(UV_RUN) black --check . && cd .. + cd litellm && $(UV_RUN) ruff format --check --line-length 88 --exclude '/enterprise/' . && cd .. # Linting targets lint-ruff: install-dev @@ -131,7 +133,7 @@ lint-basedpyright: install-dev lint-basedpyright-budget-update: install-dev ($(UV_RUN) basedpyright --outputjson || true) | $(UV_RUN) python scripts/type_check_gate.py --update -lint-black: format-check +lint-format: format-check lint-ruff-budget: install-dev $(UV_RUN) python scripts/ruff_strict_gate.py diff --git a/litellm/__init__.py b/litellm/__init__.py index d0513f77b35..9650dc12c97 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -390,12 +390,8 @@ require_managed_files: bool = ( enable_caching_on_provider_specific_optional_params: bool = ( False # feature-flag for caching on optional params - e.g. 'top_k' ) -caching: bool = ( - False # Not used anymore, will be removed in next MAJOR release - https://github.com/BerriAI/litellm/discussions/648 -) -caching_with_models: bool = ( - False # # Not used anymore, will be removed in next MAJOR release - https://github.com/BerriAI/litellm/discussions/648 -) +caching: bool = False # Not used anymore, will be removed in next MAJOR release - https://github.com/BerriAI/litellm/discussions/648 +caching_with_models: bool = False # # Not used anymore, will be removed in next MAJOR release - https://github.com/BerriAI/litellm/discussions/648 cache: Optional["Cache"] = ( None # cache object <- use this - https://docs.litellm.ai/docs/caching ) @@ -416,9 +412,7 @@ forward_traceparent_to_llm_provider: bool = False _current_cost = 0.0 # private variable, used if max budget is set error_logs: Dict = {} -add_function_to_prompt: bool = ( - False # if function calling not supported by api, append function call details to system prompt -) +add_function_to_prompt: bool = False # if function calling not supported by api, append function call details to system prompt client_session: Optional[httpx.Client] = None aclient_session: Optional[httpx.AsyncClient] = None model_fallbacks: Optional[List] = None # Deprecated for 'litellm.fallbacks' @@ -485,9 +479,7 @@ prometheus_end_user_metrics_cleanup_interval_seconds: Optional[float] = 60.0 disable_add_prefix_to_prompt: bool = ( False # used by anthropic, to disable adding prefix to prompt ) -disable_copilot_system_to_assistant: bool = ( - False # If false (default), converts all 'system' role messages to 'assistant' for GitHub Copilot compatibility. Set to true to disable this behavior. -) +disable_copilot_system_to_assistant: bool = False # If false (default), converts all 'system' role messages to 'assistant' for GitHub Copilot compatibility. Set to true to disable this behavior. public_mcp_servers: Optional[List[str]] = None public_mcp_hub_strict_whitelist: bool = True public_model_groups: Optional[List[str]] = None @@ -507,17 +499,13 @@ if TYPE_CHECKING: ######## Networking Settings ######## -use_aiohttp_transport: bool = ( - True # Older variable, aiohttp is now the default. use disable_aiohttp_transport instead. -) +use_aiohttp_transport: bool = True # Older variable, aiohttp is now the default. use disable_aiohttp_transport instead. aiohttp_trust_env: bool = False # set to true to use HTTP_ Proxy settings disable_aiohttp_transport: bool = False # Set this to true to use httpx instead disable_aiohttp_trust_env: bool = ( False # When False, aiohttp will respect HTTP(S)_PROXY env vars ) -force_ipv4: bool = ( - False # when True, litellm will force ipv4 for all LLM requests. Some users have seen httpx ConnectionError when using ipv6. -) +force_ipv4: bool = False # when True, litellm will force ipv4 for all LLM requests. Some users have seen httpx ConnectionError when using ipv6. network_mock: bool = False # When True, use mock transport — no real network calls ####### STOP SEQUENCE LIMIT ####### @@ -551,12 +539,12 @@ output_parse_pii: bool = False from litellm.litellm_core_utils.get_model_cost_map import get_model_cost_map model_cost = get_model_cost_map(url=model_cost_map_url) -cost_discount_config: Dict[str, float] = ( - {} -) # Provider-specific cost discounts {"vertex_ai": 0.05} = 5% discount -cost_margin_config: Dict[str, Union[float, Dict[str, float]]] = ( - {} -) # Provider-specific or global cost margins. Examples: +cost_discount_config: Dict[ + str, float +] = {} # Provider-specific cost discounts {"vertex_ai": 0.05} = 5% discount +cost_margin_config: Dict[ + str, Union[float, Dict[str, float]] +] = {} # Provider-specific or global cost margins. Examples: # Percentage: {"openai": 0.10} = 10% margin # Fixed: {"openai": {"fixed_amount": 0.001}} = $0.001 per request # Global: {"global": 0.05} = 5% global margin on all providers @@ -1457,9 +1445,9 @@ from . import rag from .types.llms.custom_llm import CustomLLMItem custom_provider_map: List[CustomLLMItem] = [] -_custom_providers: List[str] = ( - [] -) # internal helper util, used to track names of custom providers +_custom_providers: List[ + str +] = [] # internal helper util, used to track names of custom providers disable_hf_tokenizer_download: Optional[bool] = ( None # disable huggingface tokenizer download. Defaults to openai clk100 ) diff --git a/litellm/_redis.py b/litellm/_redis.py index 1b6e1a5e4b0..fdae674d55d 100644 --- a/litellm/_redis.py +++ b/litellm/_redis.py @@ -327,7 +327,9 @@ def _get_redis_client_logic(**env_overrides): **env_overrides, } - _startup_nodes: Optional[Union[str, list]] = redis_kwargs.get("startup_nodes", None) or get_secret( # type: ignore + _startup_nodes: Optional[Union[str, list]] = redis_kwargs.get( + "startup_nodes", None + ) or get_secret( # type: ignore "REDIS_CLUSTER_NODES" ) @@ -338,7 +340,9 @@ def _get_redis_client_logic(**env_overrides): elif _startup_nodes is None: redis_kwargs.pop("startup_nodes", None) - _sentinel_nodes: Optional[Union[str, list]] = redis_kwargs.get("sentinel_nodes", None) or get_secret( # type: ignore + _sentinel_nodes: Optional[Union[str, list]] = redis_kwargs.get( + "sentinel_nodes", None + ) or get_secret( # type: ignore "REDIS_SENTINEL_NODES" ) @@ -609,7 +613,8 @@ def get_redis_async_client( # Create async RedisCluster with IAM token as password if available cluster_client = async_redis.RedisCluster( - startup_nodes=new_startup_nodes, **cluster_kwargs # type: ignore + startup_nodes=new_startup_nodes, + **cluster_kwargs, # type: ignore ) return cluster_client diff --git a/litellm/assistants/main.py b/litellm/assistants/main.py index cb9375e6b84..b7dfed6b169 100644 --- a/litellm/assistants/main.py +++ b/litellm/assistants/main.py @@ -184,7 +184,9 @@ def get_assistants( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) @@ -198,7 +200,9 @@ def get_assistants( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) @@ -394,7 +398,9 @@ def create_assistants( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) if response is None: @@ -761,7 +767,9 @@ def create_thread( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response # type: ignore @@ -916,7 +924,9 @@ def get_thread( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response # type: ignore @@ -1103,7 +1113,9 @@ def add_message( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) @@ -1263,7 +1275,9 @@ def get_messages( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) @@ -1478,7 +1492,9 @@ def run_thread( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response # type: ignore diff --git a/litellm/assistants/utils.py b/litellm/assistants/utils.py index f8fc6ee0af7..bde279602ad 100644 --- a/litellm/assistants/utils.py +++ b/litellm/assistants/utils.py @@ -71,9 +71,7 @@ def get_optional_params_add_message( if custom_llm_provider == "openai": optional_params = non_default_params elif custom_llm_provider == "azure": - supported_params = ( - litellm.AzureOpenAIAssistantsAPIConfig().get_supported_openai_create_message_params() - ) + supported_params = litellm.AzureOpenAIAssistantsAPIConfig().get_supported_openai_create_message_params() _check_valid_arg(supported_params=supported_params) optional_params = litellm.AzureOpenAIAssistantsAPIConfig().map_openai_params_create_message_params( non_default_params=non_default_params, optional_params=optional_params diff --git a/litellm/batches/main.py b/litellm/batches/main.py index f124882b5a4..c5f1c86a4e1 100644 --- a/litellm/batches/main.py +++ b/litellm/batches/main.py @@ -359,7 +359,9 @@ def create_batch( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_batch", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_batch", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response @@ -553,7 +555,9 @@ def _handle_retrieve_batch_providers_without_provider_config( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="retrieve_batch", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="retrieve_batch", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response @@ -819,7 +823,11 @@ def list_batches( max_retries=optional_params.max_retries, ) elif custom_llm_provider == "azure": - api_base = optional_params.api_base or litellm.api_base or get_secret_str("AZURE_API_BASE") # type: ignore + api_base = ( + optional_params.api_base + or litellm.api_base + or get_secret_str("AZURE_API_BASE") + ) # type: ignore api_version = ( optional_params.api_version or litellm.api_version @@ -887,7 +895,9 @@ def list_batches( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response @@ -1097,7 +1107,9 @@ def cancel_batch( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="cancel_batch", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="cancel_batch", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response diff --git a/litellm/budget_manager.py b/litellm/budget_manager.py index bbebb6042cb..915c22b90ec 100644 --- a/litellm/budget_manager.py +++ b/litellm/budget_manager.py @@ -67,9 +67,7 @@ class BudgetManager: ) response = response.json() if response["status"] == "error": - self.user_dict = ( - {} - ) # assume this means the user dict hasn't been stored yet + self.user_dict = {} # assume this means the user dict hasn't been stored yet else: self.user_dict = response["data"] diff --git a/litellm/caching/caching_handler.py b/litellm/caching/caching_handler.py index 2a8bd856040..1ff4ee04080 100644 --- a/litellm/caching/caching_handler.py +++ b/litellm/caching/caching_handler.py @@ -79,9 +79,7 @@ class CachingHandlerResponse(BaseModel): cached_result: Optional[Any] = None final_embedding_cached_response: Optional[EmbeddingResponse] = None - embedding_all_elements_cache_hit: bool = ( - False # this is set to True when all elements in the list have a cache hit in the embedding cache, if true return the final_embedding_cached_response no need to make an API call - ) + embedding_all_elements_cache_hit: bool = False # this is set to True when all elements in the list have a cache hit in the embedding cache, if true return the final_embedding_cached_response no need to make an API call in_memory_cache_obj = InMemoryCache() @@ -165,10 +163,11 @@ class LLMCachingHandler: """ # Check if caching should be performed BEFORE doing expensive operations if ( - (kwargs.get("caching", None) is None and litellm.cache is not None) - or kwargs.get("caching", False) is True - ) and ( - kwargs.get("cache", {}).get("no-cache", False) is not True + ( + (kwargs.get("caching", None) is None and litellm.cache is not None) + or kwargs.get("caching", False) is True + ) + and (kwargs.get("cache", {}).get("no-cache", False) is not True) ): # allow users to control returning cached responses from the completion function args = args or () final_embedding_cached_response: Optional[EmbeddingResponse] = None diff --git a/litellm/caching/redis_cluster_cache.py b/litellm/caching/redis_cluster_cache.py index b0f5754f58e..2dc9224e715 100644 --- a/litellm/caching/redis_cluster_cache.py +++ b/litellm/caching/redis_cluster_cache.py @@ -79,7 +79,8 @@ class RedisClusterCache(RedisCache): # Create a fresh Redis Cluster client with current settings redis_client = redis_async.RedisCluster( - startup_nodes=new_startup_nodes, **cluster_kwargs # type: ignore + startup_nodes=new_startup_nodes, + **cluster_kwargs, # type: ignore ) # Test the connection diff --git a/litellm/completion_extras/litellm_responses_transformation/handler.py b/litellm/completion_extras/litellm_responses_transformation/handler.py index d27cfefda73..87ac5d132d7 100644 --- a/litellm/completion_extras/litellm_responses_transformation/handler.py +++ b/litellm/completion_extras/litellm_responses_transformation/handler.py @@ -151,7 +151,9 @@ class ResponsesToCompletionBridgeHandler: custom_llm_provider=custom_llm_provider, ) - def completion(self, *args, **kwargs) -> Union[ + def completion( + self, *args, **kwargs + ) -> Union[ Coroutine[Any, Any, Union["ModelResponse", "CustomStreamWrapper"]], "ModelResponse", "CustomStreamWrapper", diff --git a/litellm/completion_extras/litellm_responses_transformation/transformation.py b/litellm/completion_extras/litellm_responses_transformation/transformation.py index 3fa6b983e5f..f7ac67927b6 100644 --- a/litellm/completion_extras/litellm_responses_transformation/transformation.py +++ b/litellm/completion_extras/litellm_responses_transformation/transformation.py @@ -205,9 +205,9 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): if provider_specific_fields: tool_call_dict["provider_specific_fields"] = provider_specific_fields # Also add to function's provider_specific_fields for consistency - tool_call_dict["function"][ - "provider_specific_fields" - ] = provider_specific_fields + tool_call_dict["function"]["provider_specific_fields"] = ( + provider_specific_fields + ) msg = Message( content=None, @@ -301,7 +301,9 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): { "type": "message", "role": role, - "content": self._convert_content_to_responses_format(content, cast(str, role)), # type: ignore[arg-type] + "content": self._convert_content_to_responses_format( + content, cast(str, role) + ), # type: ignore[arg-type] } ) @@ -1021,7 +1023,11 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): # If string is passed, map with optional summary based on flag/env var if reasoning_effort == "none": - return Reasoning(effort="none", summary="detailed") if auto_summary_enabled else Reasoning(effort="none") # type: ignore + return ( + Reasoning(effort="none", summary="detailed") + if auto_summary_enabled + else Reasoning(effort="none") + ) # type: ignore elif reasoning_effort == "high": return ( Reasoning(effort="high", summary="detailed") @@ -1029,7 +1035,11 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): else Reasoning(effort="high") ) elif reasoning_effort == "xhigh": - return Reasoning(effort="xhigh", summary="detailed") if auto_summary_enabled else Reasoning(effort="xhigh") # type: ignore[typeddict-item] + return ( + Reasoning(effort="xhigh", summary="detailed") + if auto_summary_enabled + else Reasoning(effort="xhigh") + ) # type: ignore[typeddict-item] elif reasoning_effort == "medium": return ( Reasoning(effort="medium", summary="detailed") diff --git a/litellm/constants.py b/litellm/constants.py index 09235106c63..d2f2e89eca3 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -296,7 +296,8 @@ DEFAULT_SSL_CIPHERS = os.getenv( "ECDHE-ECDSA-AES256-GCM-SHA384:" "ECDHE-ECDSA-AES128-GCM-SHA256:" # Priority 3: Additional modern ciphers (good balance) - "ECDHE-RSA-CHACHA20-POLY1305:" "ECDHE-ECDSA-CHACHA20-POLY1305:" + "ECDHE-RSA-CHACHA20-POLY1305:" + "ECDHE-ECDSA-CHACHA20-POLY1305:" # Priority 4: Widely compatible fallbacks (slower but universally supported) "ECDHE-RSA-AES256-SHA384:" # Common fallback "ECDHE-RSA-AES128-SHA256:" # Very widely supported @@ -885,31 +886,29 @@ openai_compatible_providers: List = [ "pinstripes", # Pinstripes - JSON-configured provider "darkbloom", ] -openai_text_completion_compatible_providers: List = ( - [ # providers that support `/v1/completions` - "together_ai", - "fireworks_ai", - "hosted_vllm", - "meta_llama", - "llamafile", - "featherless_ai", - "nebius", - "dashscope", - "modelscope", - "moonshot", - "publicai", - "synthetic", - "tensormesh", - "apertis", - "nano-gpt", - "poe", - "chutes", - "v0", - "lambda_ai", - "hyperbolic", - "wandb", - ] -) +openai_text_completion_compatible_providers: List = [ # providers that support `/v1/completions` + "together_ai", + "fireworks_ai", + "hosted_vllm", + "meta_llama", + "llamafile", + "featherless_ai", + "nebius", + "dashscope", + "modelscope", + "moonshot", + "publicai", + "synthetic", + "tensormesh", + "apertis", + "nano-gpt", + "poe", + "chutes", + "v0", + "lambda_ai", + "hyperbolic", + "wandb", +] _openai_like_providers: List = [ "predibase", "databricks", diff --git a/litellm/cost_calculator.py b/litellm/cost_calculator.py index 27a146df7bf..f95deda0f81 100644 --- a/litellm/cost_calculator.py +++ b/litellm/cost_calculator.py @@ -1020,7 +1020,7 @@ def _apply_cost_discount( if verbose_logger.isEnabledFor(logging.DEBUG): verbose_logger.debug( - f"Applied {discount_percent*100}% discount to {custom_llm_provider}: " + f"Applied {discount_percent * 100}% discount to {custom_llm_provider}: " f"${original_cost:.6f} -> ${final_cost:.6f} (saved ${discount_amount:.6f})" ) @@ -1088,7 +1088,7 @@ def _apply_cost_margin( verbose_logger.debug( f"Applied margin to {custom_llm_provider or 'global'}: " f"${original_cost:.6f} -> ${final_cost:.6f} " - f"(margin: {margin_percent*100 if margin_percent > 0 else 0}% + ${margin_fixed_amount:.6f} = ${margin_total_amount:.6f})" + f"(margin: {margin_percent * 100 if margin_percent > 0 else 0}% + ${margin_fixed_amount:.6f} = ${margin_total_amount:.6f})" ) return final_cost, margin_percent, margin_fixed_amount, margin_total_amount @@ -1621,7 +1621,9 @@ def completion_cost( model in litellm.replicate_models or "replicate" in model ) and model not in litellm.model_cost: # for unmapped replicate model, default to replicate's time tracking logic - return get_replicate_completion_pricing(completion_response, total_time) # type: ignore + return get_replicate_completion_pricing( + completion_response, total_time + ) # type: ignore if model is None: raise ValueError( diff --git a/litellm/files/main.py b/litellm/files/main.py index 669d50dde41..582d9d5cdd0 100644 --- a/litellm/files/main.py +++ b/litellm/files/main.py @@ -264,7 +264,9 @@ def create_file( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_file", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_file", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response @@ -435,7 +437,10 @@ def file_retrieve( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", + url="https://github.com/BerriAI/litellm", + ), # type: ignore ), ) @@ -618,7 +623,10 @@ def file_delete( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", + url="https://github.com/BerriAI/litellm", + ), # type: ignore ), ) return cast(FileDeleted, response) @@ -786,7 +794,9 @@ def file_list( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="file_list", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="file_list", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response @@ -1037,7 +1047,9 @@ def file_content( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response @@ -1118,7 +1130,9 @@ def file_content_streaming( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) diff --git a/litellm/fine_tuning/main.py b/litellm/fine_tuning/main.py index 08373cda782..846a8a504a8 100644 --- a/litellm/fine_tuning/main.py +++ b/litellm/fine_tuning/main.py @@ -245,7 +245,11 @@ def create_fine_tuning_job( ) # Azure OpenAI elif custom_llm_provider == "azure": - api_base = optional_params.api_base or litellm.api_base or get_secret_str("AZURE_API_BASE") # type: ignore + api_base = ( + optional_params.api_base + or litellm.api_base + or get_secret_str("AZURE_API_BASE") + ) # type: ignore api_version = ( optional_params.api_version @@ -340,7 +344,9 @@ def create_fine_tuning_job( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response @@ -458,7 +464,11 @@ def cancel_fine_tuning_job( ) # Azure OpenAI elif custom_llm_provider == "azure": - api_base = optional_params.api_base or litellm.api_base or get_secret("AZURE_API_BASE") # type: ignore + api_base = ( + optional_params.api_base + or litellm.api_base + or get_secret("AZURE_API_BASE") + ) # type: ignore api_version = ( optional_params.api_version @@ -500,7 +510,9 @@ def cancel_fine_tuning_job( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response @@ -621,7 +633,11 @@ def list_fine_tuning_jobs( ) # Azure OpenAI elif custom_llm_provider == "azure": - api_base = optional_params.api_base or litellm.api_base or get_secret_str("AZURE_API_BASE") # type: ignore + api_base = ( + optional_params.api_base + or litellm.api_base + or get_secret_str("AZURE_API_BASE") + ) # type: ignore api_version = ( optional_params.api_version @@ -664,7 +680,9 @@ def list_fine_tuning_jobs( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="create_thread", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) return response @@ -776,7 +794,11 @@ def retrieve_fine_tuning_job( ) # Azure OpenAI elif custom_llm_provider == "azure": - api_base = optional_params.api_base or litellm.api_base or get_secret_str("AZURE_API_BASE") # type: ignore + api_base = ( + optional_params.api_base + or litellm.api_base + or get_secret_str("AZURE_API_BASE") + ) # type: ignore api_version = ( optional_params.api_version @@ -818,7 +840,10 @@ def retrieve_fine_tuning_job( response=httpx.Response( status_code=400, content="Unsupported provider", - request=httpx.Request(method="retrieve_fine_tuning_job", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="retrieve_fine_tuning_job", + url="https://github.com/BerriAI/litellm", + ), # type: ignore ), ) return response diff --git a/litellm/google_genai/adapters/transformation.py b/litellm/google_genai/adapters/transformation.py index c5d9fd124fa..d8f9f1feb0b 100644 --- a/litellm/google_genai/adapters/transformation.py +++ b/litellm/google_genai/adapters/transformation.py @@ -726,9 +726,9 @@ class GoogleGenAIAdapter: wrapper.accumulated_tool_calls[tool_call_index]["name"] = function_name if args_chunk: - wrapper.accumulated_tool_calls[tool_call_index][ - "arguments" - ] += args_chunk + wrapper.accumulated_tool_calls[tool_call_index]["arguments"] += ( + args_chunk + ) # Attempt to parse and emit a complete tool call accumulated_data = wrapper.accumulated_tool_calls[tool_call_index] diff --git a/litellm/images/main.py b/litellm/images/main.py index 8b108ded4c9..34e77ffe8ab 100644 --- a/litellm/images/main.py +++ b/litellm/images/main.py @@ -880,20 +880,20 @@ def image_edit( local_vars.update(kwargs) # Get ImageEditOptionalRequestParams with only valid parameters - image_edit_optional_params: ( - ImageEditOptionalRequestParams - ) = _get_ImageEditRequestUtils().get_requested_image_edit_optional_param( - local_vars + image_edit_optional_params: ImageEditOptionalRequestParams = ( + _get_ImageEditRequestUtils().get_requested_image_edit_optional_param( + local_vars + ) ) # Get optional parameters for the responses API - image_edit_request_params: ( - Dict - ) = _get_ImageEditRequestUtils().get_optional_params_image_edit( - model=model, - image_edit_provider_config=image_edit_provider_config, - image_edit_optional_params=image_edit_optional_params, - drop_params=kwargs.get("drop_params"), - additional_drop_params=kwargs.get("additional_drop_params"), + image_edit_request_params: Dict = ( + _get_ImageEditRequestUtils().get_optional_params_image_edit( + model=model, + image_edit_provider_config=image_edit_provider_config, + image_edit_optional_params=image_edit_optional_params, + drop_params=kwargs.get("drop_params"), + additional_drop_params=kwargs.get("additional_drop_params"), + ) ) # Pre Call logging diff --git a/litellm/integrations/SlackAlerting/hanging_request_check.py b/litellm/integrations/SlackAlerting/hanging_request_check.py index 98f1eb2d551..8c0da9bb4fb 100644 --- a/litellm/integrations/SlackAlerting/hanging_request_check.py +++ b/litellm/integrations/SlackAlerting/hanging_request_check.py @@ -104,10 +104,10 @@ class AlertingHangingRequestCheck: ) for request_id in hanging_requests: - hanging_request_data: Optional[HangingRequestData] = ( - await self.hanging_request_cache.async_get_cache( - key=request_id, - ) + hanging_request_data: Optional[ + HangingRequestData + ] = await self.hanging_request_cache.async_get_cache( + key=request_id, ) if hanging_request_data is None: diff --git a/litellm/integrations/SlackAlerting/slack_alerting.py b/litellm/integrations/SlackAlerting/slack_alerting.py index 2108ebae312..35731306b93 100644 --- a/litellm/integrations/SlackAlerting/slack_alerting.py +++ b/litellm/integrations/SlackAlerting/slack_alerting.py @@ -245,7 +245,7 @@ class SlackAlerting(CustomBatchLogger): return for api_base, latency in _deployment_latency_map.items(): - _message_to_send += f"\n{api_base}: {round(latency,2)}s" + _message_to_send += f"\n{api_base}: {round(latency, 2)}s" _message_to_send = "```" + _message_to_send + "```" return _message_to_send @@ -272,7 +272,7 @@ class SlackAlerting(CustomBatchLogger): if litellm.turn_off_message_logging or litellm.redact_messages_in_exceptions: messages = "Message not logged. litellm.redact_messages_in_exceptions=True" request_info = f"\nRequest Model: `{model}`\nAPI Base: `{api_base}`\nMessages: `{messages}`" - slow_message = f"`Responses are slow - {round(time_difference_float,2)}s response time > Alerting threshold: {self.alerting_threshold}s`" + slow_message = f"`Responses are slow - {round(time_difference_float, 2)}s response time > Alerting threshold: {self.alerting_threshold}s`" alerting_metadata: dict = {} if time_difference_float > self.alerting_threshold: # add deployment latencies to alert @@ -460,7 +460,7 @@ class SlackAlerting(CustomBatchLogger): if api_base is None: api_base = "" value = replaced_failed_values[top_5_failed[i]] - message += f"\t{i+1}. Deployment: `{deployment_name}`, Failed Requests: `{value}`, API Base: `{api_base}`\n" + message += f"\t{i + 1}. Deployment: `{deployment_name}`, Failed Requests: `{value}`, API Base: `{api_base}`\n" message += "\n\n*😅 Top Slowest Deployments:*\n\n" if not top_5_slowest: @@ -479,7 +479,7 @@ class SlackAlerting(CustomBatchLogger): ), ) value = round(replaced_slowest_values[top_5_slowest[i]], 3) - message += f"\t{i+1}. Deployment: `{deployment_name}`, Latency per output token: `{value}s/token`, API Base: `{api_base}`\n\n" + message += f"\t{i + 1}. Deployment: `{deployment_name}`, Latency per output token: `{value}s/token`, API Base: `{api_base}`\n\n" # cache cleanup -> reset values to 0 latency_cache_keys = [(key, 0) for key in latency_keys] @@ -595,9 +595,7 @@ class SlackAlerting(CustomBatchLogger): "projected_limit_exceeded", "soft_budget_crossed", ] - ] = ( - "projected_limit_exceeded" if type == "projected_limit_exceeded" else None - ) + ] = "projected_limit_exceeded" if type == "projected_limit_exceeded" else None webhook_event: Optional[WebhookEvent] = None @@ -854,9 +852,9 @@ class SlackAlerting(CustomBatchLogger): ### UNIQUE CACHE KEY ### cache_key = provider + region_name - outage_value: Optional[ProviderRegionOutageModel] = ( - await self.internal_usage_cache.async_get_cache(key=cache_key) - ) + outage_value: Optional[ + ProviderRegionOutageModel + ] = await self.internal_usage_cache.async_get_cache(key=cache_key) # Convert deployment_ids back to set if it was stored as a list if outage_value is not None: @@ -981,7 +979,9 @@ class SlackAlerting(CustomBatchLogger): max_alerts_size = 10 """ try: - outage_value: Optional[OutageModel] = await self.internal_usage_cache.async_get_cache(key=deployment_id) # type: ignore + outage_value: Optional[ + OutageModel + ] = await self.internal_usage_cache.async_get_cache(key=deployment_id) # type: ignore if ( getattr(exception, "status_code", None) is None or ( diff --git a/litellm/integrations/braintrust_logging.py b/litellm/integrations/braintrust_logging.py index 6a6313f72e1..a69785ba2e3 100644 --- a/litellm/integrations/braintrust_logging.py +++ b/litellm/integrations/braintrust_logging.py @@ -52,9 +52,9 @@ class BraintrustLogger(CustomLogger): "Authorization": "Bearer " + self.api_key, "Content-Type": "application/json", } - self._project_id_cache: Dict[str, str] = ( - {} - ) # Cache mapping project names to IDs + self._project_id_cache: Dict[ + str, str + ] = {} # Cache mapping project names to IDs self.global_braintrust_http_handler = get_async_httpx_client( llm_provider=httpxSpecialProvider.LoggingCallback ) diff --git a/litellm/integrations/braintrust_mock_client.py b/litellm/integrations/braintrust_mock_client.py index 59e0988a10a..1af14deeab6 100644 --- a/litellm/integrations/braintrust_mock_client.py +++ b/litellm/integrations/braintrust_mock_client.py @@ -157,7 +157,7 @@ def create_mock_braintrust_client(): create_mock_braintrust_factory_client() verbose_logger.debug( - f"[BRAINTRUST MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS*1000:.0f}ms" + f"[BRAINTRUST MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS * 1000:.0f}ms" ) verbose_logger.debug( "[BRAINTRUST MOCK] Braintrust mock client initialization complete" diff --git a/litellm/integrations/custom_logger.py b/litellm/integrations/custom_logger.py index 94fb97dff53..6d65b4ec0d2 100644 --- a/litellm/integrations/custom_logger.py +++ b/litellm/integrations/custom_logger.py @@ -981,7 +981,9 @@ class CustomLogger: # https://docs.litellm.ai/docs/observability/custom_callbac verbose_logger.debug( f"Incrementing callback failure metric for {callback_name}" ) - callback_obj.increment_callback_logging_failure(callback_name=callback_name) # type: ignore + callback_obj.increment_callback_logging_failure( + callback_name=callback_name + ) # type: ignore return verbose_logger.debug( diff --git a/litellm/integrations/datadog/datadog_metrics.py b/litellm/integrations/datadog/datadog_metrics.py index d7847027d7e..bd5c165cba2 100644 --- a/litellm/integrations/datadog/datadog_metrics.py +++ b/litellm/integrations/datadog/datadog_metrics.py @@ -256,7 +256,9 @@ class DatadogMetricsLogger(CustomBatchLogger): headers["Content-Encoding"] = "gzip" response = await self.async_client.post( - self.upload_url, content=compressed_data, headers=headers # type: ignore + self.upload_url, + content=compressed_data, + headers=headers, # type: ignore ) response.raise_for_status() diff --git a/litellm/integrations/focus/destinations/vantage_destination.py b/litellm/integrations/focus/destinations/vantage_destination.py index c58e955984c..4e3dd2b6d8b 100644 --- a/litellm/integrations/focus/destinations/vantage_destination.py +++ b/litellm/integrations/focus/destinations/vantage_destination.py @@ -157,7 +157,7 @@ class FocusVantageDestination(FocusDestination): async def _upload_csv( self, client: AsyncHTTPHandler, csv_bytes: bytes, filename: str ) -> None: - url = f"{self.base_url}/v2/integrations/" f"{self.integration_token}/costs.csv" + url = f"{self.base_url}/v2/integrations/{self.integration_token}/costs.csv" headers = { "Authorization": f"Bearer {self.api_key}", } diff --git a/litellm/integrations/gcs_bucket/gcs_bucket_mock_client.py b/litellm/integrations/gcs_bucket/gcs_bucket_mock_client.py index 1761fe010c9..9161455a246 100644 --- a/litellm/integrations/gcs_bucket/gcs_bucket_mock_client.py +++ b/litellm/integrations/gcs_bucket/gcs_bucket_mock_client.py @@ -154,7 +154,10 @@ def create_mock_gcs_client(): This function is idempotent - it only initializes mocks once, even if called multiple times. """ - global _original_async_handler_get, _original_async_handler_delete, _mocks_initialized + global \ + _original_async_handler_get, \ + _original_async_handler_delete, \ + _mocks_initialized # Use factory for POST handler _create_mock_gcs_post() @@ -179,7 +182,7 @@ def create_mock_gcs_client(): verbose_logger.debug("[GCS MOCK] Patched AsyncHTTPHandler.delete") verbose_logger.debug( - f"[GCS MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS*1000:.0f}ms" + f"[GCS MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS * 1000:.0f}ms" ) verbose_logger.debug("[GCS MOCK] GCS mock client initialization complete") diff --git a/litellm/integrations/gitlab/gitlab_prompt_manager.py b/litellm/integrations/gitlab/gitlab_prompt_manager.py index a468741aead..99d9d9b285b 100644 --- a/litellm/integrations/gitlab/gitlab_prompt_manager.py +++ b/litellm/integrations/gitlab/gitlab_prompt_manager.py @@ -372,7 +372,9 @@ class GitLabPromptManager(CustomPromptManagement): if parsed_messages: final_messages: List[AllMessageValues] = parsed_messages else: - final_messages = [{"role": "user", "content": rendered_prompt}] + messages # type: ignore + final_messages = [ + {"role": "user", "content": rendered_prompt} + ] + messages # type: ignore if litellm_params is None: litellm_params = {} @@ -412,24 +414,41 @@ class GitLabPromptManager(CustomPromptManagement): low = line.lower() if low.startswith("system:"): if current_role and current_content: - messages.append({"role": current_role, "content": "\n".join(current_content).strip()}) # type: ignore + messages.append( + { + "role": current_role, + "content": "\n".join(current_content).strip(), + } + ) # type: ignore current_role = "system" current_content = [line[7:].strip()] elif low.startswith("user:"): if current_role and current_content: - messages.append({"role": current_role, "content": "\n".join(current_content).strip()}) # type: ignore + messages.append( + { + "role": current_role, + "content": "\n".join(current_content).strip(), + } + ) # type: ignore current_role = "user" current_content = [line[5:].strip()] elif low.startswith("assistant:"): if current_role and current_content: - messages.append({"role": current_role, "content": "\n".join(current_content).strip()}) # type: ignore + messages.append( + { + "role": current_role, + "content": "\n".join(current_content).strip(), + } + ) # type: ignore current_role = "assistant" current_content = [line[10:].strip()] else: current_content.append(line) if current_role and current_content: - messages.append({"role": current_role, "content": "\n".join(current_content).strip()}) # type: ignore + messages.append( + {"role": current_role, "content": "\n".join(current_content).strip()} + ) # type: ignore if not messages and prompt_content.strip(): messages = [{"role": "user", "content": prompt_content.strip()}] # type: ignore return messages diff --git a/litellm/integrations/lago.py b/litellm/integrations/lago.py index b881193e869..c7c010f9976 100644 --- a/litellm/integrations/lago.py +++ b/litellm/integrations/lago.py @@ -131,9 +131,9 @@ class LagoLogger(CustomLogger): def log_success_event(self, kwargs, response_obj, start_time, end_time): _url = os.getenv("LAGO_API_BASE") - assert _url is not None and isinstance( - _url, str - ), "LAGO_API_BASE missing or not set correctly. LAGO_API_BASE={}".format(_url) + assert _url is not None and isinstance(_url, str), ( + "LAGO_API_BASE missing or not set correctly. LAGO_API_BASE={}".format(_url) + ) if _url.endswith("/"): _url += "api/v1/events" else: @@ -165,10 +165,10 @@ class LagoLogger(CustomLogger): try: verbose_logger.debug("ENTERS LAGO CALLBACK") _url = os.getenv("LAGO_API_BASE") - assert _url is not None and isinstance( - _url, str - ), "LAGO_API_BASE missing or not set correctly. LAGO_API_BASE={}".format( - _url + assert _url is not None and isinstance(_url, str), ( + "LAGO_API_BASE missing or not set correctly. LAGO_API_BASE={}".format( + _url + ) ) if _url.endswith("/"): _url += "api/v1/events" diff --git a/litellm/integrations/langfuse/langfuse_handler.py b/litellm/integrations/langfuse/langfuse_handler.py index 4a809726424..797c1609f80 100644 --- a/litellm/integrations/langfuse/langfuse_handler.py +++ b/litellm/integrations/langfuse/langfuse_handler.py @@ -86,9 +86,9 @@ class LangFuseHandler: if globalLangfuseLogger is not None: return globalLangfuseLogger - credentials_dict: Dict[str, Any] = ( - {} - ) # the global langfuse logger uses Environment Variables, there are no dynamic credentials + credentials_dict: Dict[ + str, Any + ] = {} # the global langfuse logger uses Environment Variables, there are no dynamic credentials globalLangfuseLogger = in_memory_dynamic_logger_cache.get_cache( credentials=credentials_dict, service_name="langfuse", diff --git a/litellm/integrations/langsmith.py b/litellm/integrations/langsmith.py index 81570e462c4..15f92e8b322 100644 --- a/litellm/integrations/langsmith.py +++ b/litellm/integrations/langsmith.py @@ -65,8 +65,7 @@ class LangsmithLogger(CustomBatchLogger): langsmith_tenant_id=langsmith_tenant_id, ) self.sampling_rate: float = ( - langsmith_sampling_rate - or float(os.getenv("LANGSMITH_SAMPLING_RATE")) # type: ignore + langsmith_sampling_rate or float(os.getenv("LANGSMITH_SAMPLING_RATE")) # type: ignore if os.getenv("LANGSMITH_SAMPLING_RATE") is not None and os.getenv("LANGSMITH_SAMPLING_RATE").strip().isdigit() # type: ignore else 1.0 diff --git a/litellm/integrations/mock_client_factory.py b/litellm/integrations/mock_client_factory.py index 9b912ce70c8..3b013f96a79 100644 --- a/litellm/integrations/mock_client_factory.py +++ b/litellm/integrations/mock_client_factory.py @@ -232,7 +232,11 @@ def create_mock_client_factory(config: MockClientConfig): # Create mock client initialization function def create_mock_client(): """Initialize the mock client by patching HTTP handlers.""" - nonlocal _original_async_handler_post, _original_sync_client_post, _original_http_handler_post, _mocks_initialized + nonlocal \ + _original_async_handler_post, \ + _original_sync_client_post, \ + _original_http_handler_post, \ + _mocks_initialized if _mocks_initialized: return @@ -261,7 +265,7 @@ def create_mock_client_factory(config: MockClientConfig): verbose_logger.debug(f"[{config.name} MOCK] Patched HTTPHandler.post") verbose_logger.debug( - f"[{config.name} MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS*1000:.0f}ms" + f"[{config.name} MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS * 1000:.0f}ms" ) verbose_logger.debug( f"[{config.name} MOCK] {config.name} mock client initialization complete" diff --git a/litellm/integrations/opik/opik.py b/litellm/integrations/opik/opik.py index 7b687d34d1c..b15b024ff09 100644 --- a/litellm/integrations/opik/opik.py +++ b/litellm/integrations/opik/opik.py @@ -174,7 +174,9 @@ class OpikLogger(CustomBatchLogger): ) -> None: try: response = self.sync_httpx_client.post( - url=url, headers=headers, json=batch # type: ignore + url=url, + headers=headers, + json=batch, # type: ignore ) response.raise_for_status() if response.status_code != 204: @@ -264,7 +266,9 @@ class OpikLogger(CustomBatchLogger): ) -> None: try: response = await self.async_httpx_client.post( - url=url, headers=headers, json=batch # type: ignore + url=url, + headers=headers, + json=batch, # type: ignore ) response.raise_for_status() diff --git a/litellm/integrations/otel/mappers/__init__.py b/litellm/integrations/otel/mappers/__init__.py index 012e63f1bee..9c728678f47 100644 --- a/litellm/integrations/otel/mappers/__init__.py +++ b/litellm/integrations/otel/mappers/__init__.py @@ -38,7 +38,7 @@ def resolve_mappers(names: Iterable[str]) -> list[AttributeMapper]: factory = _MAPPER_BY_NAME.get(name) if factory is None: raise ValueError( - f"unknown mapper name {name!r}; known: " f"{sorted(_MAPPER_BY_NAME)}" + f"unknown mapper name {name!r}; known: {sorted(_MAPPER_BY_NAME)}" ) out.append(factory()) return out diff --git a/litellm/integrations/otel/mappers/genai.py b/litellm/integrations/otel/mappers/genai.py index d9be68a06c2..75330ebd1bd 100644 --- a/litellm/integrations/otel/mappers/genai.py +++ b/litellm/integrations/otel/mappers/genai.py @@ -35,7 +35,6 @@ from litellm.integrations.otel.model.spans import db_system class GenAIMapper: - _LLM_CALL_ATTRS: dict[str, Callable[[LLMCallSpanData], AttrValue | None]] = { GenAI.OPERATION_NAME: lambda d: d.operation.value, GenAI.PROVIDER_NAME: lambda d: d.provider or None, @@ -81,9 +80,13 @@ class GenAIMapper: f"{LiteLLM.COST_PREFIX}original": lambda d: d.cost.original, f"{LiteLLM.COST_PREFIX}discount_amount": lambda d: d.cost.discount_amount, f"{LiteLLM.COST_PREFIX}discount_percent": lambda d: d.cost.discount_percent, - f"{LiteLLM.COST_PREFIX}margin_fixed_amount": lambda d: d.cost.margin_fixed_amount, + f"{LiteLLM.COST_PREFIX}margin_fixed_amount": lambda d: ( + d.cost.margin_fixed_amount + ), f"{LiteLLM.COST_PREFIX}margin_percent": lambda d: d.cost.margin_percent, - f"{LiteLLM.COST_PREFIX}margin_total_amount": lambda d: d.cost.margin_total_amount, + f"{LiteLLM.COST_PREFIX}margin_total_amount": lambda d: ( + d.cost.margin_total_amount + ), LiteLLM.REQUEST_STREAMING: lambda d: d.is_streaming, } diff --git a/litellm/integrations/otel/mappers/langfuse.py b/litellm/integrations/otel/mappers/langfuse.py index 14c9fd01d05..d0af460f752 100644 --- a/litellm/integrations/otel/mappers/langfuse.py +++ b/litellm/integrations/otel/mappers/langfuse.py @@ -27,7 +27,6 @@ from litellm.integrations.otel.model.payloads import ( class LangfuseMapper: - _LLM_CALL_ATTRS: dict[str, Callable[[LLMCallSpanData], AttrValue | None]] = { "langfuse.observation.type": lambda d: "generation", "langfuse.observation.model.name": lambda d: d.request_model or None, diff --git a/litellm/integrations/otel/mappers/langtrace.py b/litellm/integrations/otel/mappers/langtrace.py index 7c0f30e57dd..ec595439fe5 100644 --- a/litellm/integrations/otel/mappers/langtrace.py +++ b/litellm/integrations/otel/mappers/langtrace.py @@ -20,7 +20,6 @@ from litellm.integrations.otel.model.payloads import LLMCallSpanData class LangtraceMapper: - _LLM_CALL_ATTRS: dict[str, Callable[[LLMCallSpanData], AttrValue | None]] = { "gen_ai.operation.name": lambda d: "chat", "langtrace.service.name": lambda d: d.provider or None, diff --git a/litellm/integrations/otel/model/baggage.py b/litellm/integrations/otel/model/baggage.py index ecab643a26b..77ace736c2f 100644 --- a/litellm/integrations/otel/model/baggage.py +++ b/litellm/integrations/otel/model/baggage.py @@ -29,13 +29,15 @@ _PROMOTABLE: Final[ ] = { LiteLLM.TEAM_ID: lambda identity, model, team_metadata_keys: identity.team_id, LiteLLM.TEAM_ALIAS: lambda identity, model, team_metadata_keys: identity.team_alias, - LiteLLM.TEAM_METADATA: lambda identity, model, team_metadata_keys: _filtered_team_metadata_json( - identity.team_metadata, team_metadata_keys + LiteLLM.TEAM_METADATA: lambda identity, model, team_metadata_keys: ( + _filtered_team_metadata_json(identity.team_metadata, team_metadata_keys) ), LiteLLM.KEY_HASH: lambda identity, model, team_metadata_keys: identity.key_hash, LiteLLM.END_USER: lambda identity, model, team_metadata_keys: identity.end_user, GenAI.REQUEST_MODEL: lambda identity, model, team_metadata_keys: model, - LiteLLM.PROVIDER_MODEL: lambda identity, model, team_metadata_keys: identity.provider_model, + LiteLLM.PROVIDER_MODEL: lambda identity, model, team_metadata_keys: ( + identity.provider_model + ), } # Keys promoted by default (a subset of ``_PROMOTABLE``). ``END_USER`` is diff --git a/litellm/integrations/prometheus.py b/litellm/integrations/prometheus.py index c63f114514a..18fb5d9491e 100644 --- a/litellm/integrations/prometheus.py +++ b/litellm/integrations/prometheus.py @@ -3237,7 +3237,9 @@ class PrometheusLogger(CustomLogger): ) return - async def fetch_keys(page_size: int, page: int) -> Tuple[ + async def fetch_keys( + page_size: int, page: int + ) -> Tuple[ List[Union[str, UserAPIKeyAuth, LiteLLM_DeletedVerificationToken]], Optional[int], ]: diff --git a/litellm/integrations/rubrik.py b/litellm/integrations/rubrik.py index af396ecdc73..922d8f71cf0 100644 --- a/litellm/integrations/rubrik.py +++ b/litellm/integrations/rubrik.py @@ -550,8 +550,7 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger): "response": response_data, } verbose_logger.debug( - f"Sending request to tool blocking service: " - f"{self.tool_blocking_endpoint}" + f"Sending request to tool blocking service: {self.tool_blocking_endpoint}" ) http_response = await self.tool_blocking_client.post( self.tool_blocking_endpoint, diff --git a/litellm/integrations/vector_store_integrations/vector_store_pre_call_hook.py b/litellm/integrations/vector_store_integrations/vector_store_pre_call_hook.py index 482a19c5d72..c54b6e4cced 100644 --- a/litellm/integrations/vector_store_integrations/vector_store_pre_call_hook.py +++ b/litellm/integrations/vector_store_integrations/vector_store_pre_call_hook.py @@ -88,12 +88,12 @@ class VectorStorePreCallHook(CustomLogger): pass # Use database fallback to ensure synchronization across instances - vector_stores_to_run: List[LiteLLM_ManagedVectorStore] = ( - await litellm.vector_store_registry.pop_vector_stores_to_run_with_db_fallback( - non_default_params=non_default_params, - tools=tools, - prisma_client=prisma_client, - ) + vector_stores_to_run: List[ + LiteLLM_ManagedVectorStore + ] = await litellm.vector_store_registry.pop_vector_stores_to_run_with_db_fallback( + non_default_params=non_default_params, + tools=tools, + prisma_client=prisma_client, ) if not vector_stores_to_run: diff --git a/litellm/litellm_core_utils/core_helpers.py b/litellm/litellm_core_utils/core_helpers.py index 98b792efa59..0cdd721598c 100644 --- a/litellm/litellm_core_utils/core_helpers.py +++ b/litellm/litellm_core_utils/core_helpers.py @@ -361,9 +361,9 @@ def safe_deep_copy(data): "litellm_metadata" in data and "litellm_parent_otel_span" in data["litellm_metadata"] ): - data["litellm_metadata"][ - "litellm_parent_otel_span" - ] = litellm_parent_otel_span + data["litellm_metadata"]["litellm_parent_otel_span"] = ( + litellm_parent_otel_span + ) return new_data diff --git a/litellm/litellm_core_utils/exception_mapping_utils.py b/litellm/litellm_core_utils/exception_mapping_utils.py index 9b2a9af4126..a0f9bb00dd2 100644 --- a/litellm/litellm_core_utils/exception_mapping_utils.py +++ b/litellm/litellm_core_utils/exception_mapping_utils.py @@ -272,8 +272,8 @@ def _map_openai_exception( else: message = str(original_exception) - if message is not None and isinstance( - message, str + if ( + message is not None and isinstance(message, str) ): # done to prevent user-confusion. Relevant issue - https://github.com/BerriAI/litellm/issues/1414 message = message.replace("OPENAI", custom_llm_provider.upper()) message = message.replace( @@ -726,7 +726,6 @@ def _map_openai_like_exception( extra_information: str, ) -> None: if "authorization denied for" in error_str: - # Predibase returns the raw API Key in the response - this block ensures it's not returned in the exception if ( error_str is not None @@ -1161,7 +1160,9 @@ def _map_vertex_exception( response=httpx.Response( status_code=500, content=str(original_exception), - request=httpx.Request(method="completion", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="completion", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), litellm_debug_info=extra_information, ) @@ -1327,7 +1328,9 @@ def _map_vertex_exception( response=httpx.Response( status_code=500, content=str(original_exception), - request=httpx.Request(method="completion", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="completion", url="https://github.com/BerriAI/litellm" + ), # type: ignore ), ) if original_exception.status_code == 502: @@ -1965,13 +1968,9 @@ def _map_azure_exception( # content policy violation even when the top-level # code is generic (e.g. "invalid_request_error"). if azure_error_code != "content_policy_violation": - _inner = body_dict["error"].get( - "inner_error" - ) or body_dict[ # type: ignore[index] + _inner = body_dict["error"].get("inner_error") or body_dict[ # type: ignore[index] "error" - ].get( - "innererror" - ) # type: ignore[index] + ].get("innererror") # type: ignore[index] if ( isinstance(_inner, dict) and _inner.get("code") == "ResponsibleAIPolicyViolation" diff --git a/litellm/litellm_core_utils/get_llm_provider_logic.py b/litellm/litellm_core_utils/get_llm_provider_logic.py index bb8b1a82996..061316a69d6 100644 --- a/litellm/litellm_core_utils/get_llm_provider_logic.py +++ b/litellm/litellm_core_utils/get_llm_provider_logic.py @@ -616,7 +616,11 @@ def _get_openai_compatible_provider_info( return model, "aiohttp_openai", api_key, api_base elif custom_llm_provider == "anyscale": # anyscale is openai compatible, we just need to set this to custom_openai and have the api_base be https://api.endpoints.anyscale.com/v1 - api_base = api_base or get_secret_str("ANYSCALE_API_BASE") or "https://api.endpoints.anyscale.com/v1" # type: ignore + api_base = ( + api_base + or get_secret_str("ANYSCALE_API_BASE") + or "https://api.endpoints.anyscale.com/v1" + ) # type: ignore dynamic_api_key = api_key or get_secret_str("ANYSCALE_API_KEY") elif custom_llm_provider == "deepinfra": ( @@ -709,9 +713,7 @@ def _get_openai_compatible_provider_info( ) # type: ignore dynamic_api_key = api_key or get_secret_str("NEBIUS_API_KEY") elif custom_llm_provider == "ollama": - api_base = ( - api_base or get_secret("OLLAMA_API_BASE") or "http://localhost:11434" - ) # type: ignore + api_base = api_base or get_secret("OLLAMA_API_BASE") or "http://localhost:11434" # type: ignore dynamic_api_key = api_key or get_secret_str("OLLAMA_API_KEY") elif (custom_llm_provider == "ai21_chat") or ( custom_llm_provider == "ai21" and model in litellm.ai21_chat_models diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index d750a509054..e860f48a7bd 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -293,7 +293,17 @@ def _get_cached_prometheus_logger(): class Logging(LiteLLMLoggingBaseClass): - global supabaseClient, promptLayerLogger, weightsBiasesLogger, logfireLogger, capture_exception, add_breadcrumb, lunaryLogger, logfireLogger, prometheusLogger, slack_app + global \ + supabaseClient, \ + promptLayerLogger, \ + weightsBiasesLogger, \ + logfireLogger, \ + capture_exception, \ + add_breadcrumb, \ + lunaryLogger, \ + logfireLogger, \ + prometheusLogger, \ + slack_app custom_pricing: bool = False stream_options = None litellm_request_debug: bool = False @@ -359,9 +369,9 @@ class Logging(LiteLLMLoggingBaseClass): ) self.function_id = function_id self.streaming_chunks: List[Any] = [] # for generating complete stream response - self.sync_streaming_chunks: List[Any] = ( - [] - ) # for generating complete stream response + self.sync_streaming_chunks: List[ + Any + ] = [] # for generating complete stream response self.log_raw_request_response = log_raw_request_response # Initialize dynamic callbacks @@ -903,8 +913,11 @@ class Logging(LiteLLMLoggingBaseClass): self.model_call_details["prompt_integration"] = logger.__class__.__name__ return logger - if anthropic_cache_control_logger := AnthropicCacheControlHook.get_custom_logger_for_anthropic_cache_control_hook( - non_default_params + if ( + anthropic_cache_control_logger + := AnthropicCacheControlHook.get_custom_logger_for_anthropic_cache_control_hook( + non_default_params + ) ): self.model_call_details["prompt_integration"] = ( anthropic_cache_control_logger.__class__.__name__ @@ -978,9 +991,7 @@ class Logging(LiteLLMLoggingBaseClass): self.model_call_details["api_key"] = api_key self.model_call_details["additional_args"] = additional_args self.model_call_details["log_event_type"] = "pre_api_call" - if ( - model - ): # if model name was changes pre-call, overwrite the initial model call name with the new one + if model: # if model name was changes pre-call, overwrite the initial model call name with the new one self.model_call_details["model"] = model self.model_call_details["litellm_params"]["api_base"] = ( self._get_masked_api_base(additional_args.get("api_base", "")) @@ -1359,13 +1370,13 @@ class Logging(LiteLLMLoggingBaseClass): for callback in callbacks: try: if isinstance(callback, CustomLogger): - response: Optional[MCPPostCallResponseObject] = ( - await callback.async_post_mcp_tool_call_hook( - kwargs=kwargs, - response_obj=post_mcp_tool_call_response_obj, - start_time=start_time, - end_time=end_time, - ) + response: Optional[ + MCPPostCallResponseObject + ] = await callback.async_post_mcp_tool_call_hook( + kwargs=kwargs, + response_obj=post_mcp_tool_call_response_obj, + start_time=start_time, + end_time=end_time, ) ###################################################################### # if any of the callbacks modify the response, use the modified response @@ -1865,7 +1876,9 @@ class Logging(LiteLLMLoggingBaseClass): self.model_call_details["litellm_params"].setdefault("metadata", {}) if self.model_call_details["litellm_params"]["metadata"] is None: self.model_call_details["litellm_params"]["metadata"] = {} - self.model_call_details["litellm_params"]["metadata"]["hidden_params"] = getattr(logging_result, "_hidden_params", {}) # type: ignore + self.model_call_details["litellm_params"]["metadata"][ + "hidden_params" + ] = getattr(logging_result, "_hidden_params", {}) # type: ignore if self.model_call_details.get("cache_hit") is True: self.model_call_details["response_cost"] = 0.0 @@ -1944,7 +1957,9 @@ class Logging(LiteLLMLoggingBaseClass): ) result = result.model_copy() - transformed_usage = TranscriptionUsageObjectTransformation.transform_transcription_usage_object(result.usage) # type: ignore + transformed_usage = TranscriptionUsageObjectTransformation.transform_transcription_usage_object( + result.usage + ) # type: ignore setattr(result, "usage", transformed_usage) return result @@ -2948,7 +2963,9 @@ class Logging(LiteLLMLoggingBaseClass): for callback_obj in all_callbacks: if hasattr(callback_obj, "increment_callback_logging_failure"): - callback_obj.increment_callback_logging_failure(callback_name=callback_name) # type: ignore + callback_obj.increment_callback_logging_failure( + callback_name=callback_name + ) # type: ignore break # Only increment once except Exception as e: @@ -3292,9 +3309,7 @@ class Logging(LiteLLMLoggingBaseClass): except Exception as e: verbose_logger.exception( "LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure \ - logging {}\nCallback={}".format( - str(e), callback - ) + logging {}\nCallback={}".format(str(e), callback) ) # Track callback logging failures in Prometheus self._handle_callback_failure(callback=callback) @@ -3762,7 +3777,29 @@ def set_callbacks(callback_list, function_id=None): """ Globally sets the callback client """ - global sentry_sdk_instance, capture_exception, add_breadcrumb, slack_app, alerts_channel, traceloopLogger, athinaLogger, heliconeLogger, supabaseClient, lunaryLogger, promptLayerLogger, langFuseLogger, customLogger, weightsBiasesLogger, logfireLogger, dynamoLogger, s3Logger, dataDogLogger, prometheusLogger, greenscaleLogger, openMeterLogger, deepevalLogger + global \ + sentry_sdk_instance, \ + capture_exception, \ + add_breadcrumb, \ + slack_app, \ + alerts_channel, \ + traceloopLogger, \ + athinaLogger, \ + heliconeLogger, \ + supabaseClient, \ + lunaryLogger, \ + promptLayerLogger, \ + langFuseLogger, \ + customLogger, \ + weightsBiasesLogger, \ + logfireLogger, \ + dynamoLogger, \ + s3Logger, \ + dataDogLogger, \ + prometheusLogger, \ + greenscaleLogger, \ + openMeterLogger, \ + deepevalLogger try: for callback in callback_list: @@ -4607,7 +4644,7 @@ def _maybe_auto_initialize_arize_phoenix(_in_memory_loggers: list) -> None: litellm.logging_callback_manager.add_litellm_callback(phoenix_logger) verbose_logger.info( - "Auto-initialized Arize Phoenix logger alongside otel " "(endpoint=%s)", + "Auto-initialized Arize Phoenix logger alongside otel (endpoint=%s)", arize_phoenix_config.endpoint, ) except Exception as e: @@ -5781,7 +5818,8 @@ def get_standard_logging_object_payload( id = f"{id}_cache_hit{time.time()}" # do not duplicate the request id saved_cache_cost = ( logging_obj._response_cost_calculator( - result=init_response_obj, cache_hit=False # type: ignore + result=init_response_obj, + cache_hit=False, # type: ignore ) or 0.0 ) diff --git a/litellm/litellm_core_utils/llm_cost_calc/utils.py b/litellm/litellm_core_utils/llm_cost_calc/utils.py index 7a7fde3087e..19b711f6748 100644 --- a/litellm/litellm_core_utils/llm_cost_calc/utils.py +++ b/litellm/litellm_core_utils/llm_cost_calc/utils.py @@ -131,8 +131,10 @@ def _generic_cost_per_character( assert ( "input_cost_per_character" in model_info and model_info["input_cost_per_character"] is not None - ), "model info for model={} does not have 'input_cost_per_character'-pricing\nmodel_info={}".format( - model, model_info + ), ( + "model info for model={} does not have 'input_cost_per_character'-pricing\nmodel_info={}".format( + model, model_info + ) ) custom_prompt_cost = model_info["input_cost_per_character"] @@ -152,8 +154,10 @@ def _generic_cost_per_character( assert ( "output_cost_per_character" in model_info and model_info["output_cost_per_character"] is not None - ), "model info for model={} does not have 'output_cost_per_character'-pricing\nmodel_info={}".format( - model, model_info + ), ( + "model info for model={} does not have 'output_cost_per_character'-pricing\nmodel_info={}".format( + model, model_info + ) ) custom_completion_cost = model_info["output_cost_per_character"] completion_cost = completion_characters * custom_completion_cost diff --git a/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py b/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py index baf71220506..79c6c665684 100644 --- a/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py +++ b/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py @@ -333,9 +333,15 @@ def convert_to_streaming_response( if "usage" in response_object and response_object["usage"] is not None: setattr(model_response_object, "usage", Usage()) - model_response_object.usage.completion_tokens = response_object["usage"].get("completion_tokens", 0) # type: ignore - model_response_object.usage.prompt_tokens = response_object["usage"].get("prompt_tokens", 0) # type: ignore - model_response_object.usage.total_tokens = response_object["usage"].get("total_tokens", 0) # type: ignore + model_response_object.usage.completion_tokens = response_object["usage"].get( + "completion_tokens", 0 + ) # type: ignore + model_response_object.usage.prompt_tokens = response_object["usage"].get( + "prompt_tokens", 0 + ) # type: ignore + model_response_object.usage.total_tokens = response_object["usage"].get( + "total_tokens", 0 + ) # type: ignore if "id" in response_object: model_response_object.id = response_object["id"] @@ -848,9 +854,15 @@ def convert_to_model_response_object( model_response_object.data = response_object["data"] if "usage" in response_object and response_object["usage"] is not None: - model_response_object.usage.completion_tokens = response_object["usage"].get("completion_tokens", 0) # type: ignore - model_response_object.usage.prompt_tokens = response_object["usage"].get("prompt_tokens", 0) # type: ignore - model_response_object.usage.total_tokens = response_object["usage"].get("total_tokens", 0) # type: ignore + model_response_object.usage.completion_tokens = response_object[ + "usage" + ].get("completion_tokens", 0) # type: ignore + model_response_object.usage.prompt_tokens = response_object[ + "usage" + ].get("prompt_tokens", 0) # type: ignore + model_response_object.usage.total_tokens = response_object["usage"].get( + "total_tokens", 0 + ) # type: ignore if start_time is not None and end_time is not None: model_response_object._response_ms = ( # type: ignore diff --git a/litellm/litellm_core_utils/logging_callback_manager.py b/litellm/litellm_core_utils/logging_callback_manager.py index b7adda3a9a4..f58126ec901 100644 --- a/litellm/litellm_core_utils/logging_callback_manager.py +++ b/litellm/litellm_core_utils/logging_callback_manager.py @@ -68,7 +68,8 @@ class LoggingCallbackManager: Ensures no duplicates are added. """ self._safe_add_callback_to_list( - callback=callback, parent_list=litellm.callbacks # type: ignore + callback=callback, + parent_list=litellm.callbacks, # type: ignore ) def add_litellm_success_callback( diff --git a/litellm/litellm_core_utils/prompt_templates/factory.py b/litellm/litellm_core_utils/prompt_templates/factory.py index b95b73398ac..b4f492bc26f 100644 --- a/litellm/litellm_core_utils/prompt_templates/factory.py +++ b/litellm/litellm_core_utils/prompt_templates/factory.py @@ -1586,7 +1586,9 @@ def convert_to_gemini_tool_call_result( file_data = ( file_content.get("file_data", "") if isinstance(file_content, dict) - else file_content if isinstance(file_content, str) else "" + else file_content + if isinstance(file_content, str) + else "" ) if file_data: @@ -2556,9 +2558,7 @@ def anthropic_messages_pt( ChatCompletionToolMessage, ChatCompletionUserMessage, ChatCompletionFunctionMessage, - ] = messages[ - msg_i - ] # type: ignore + ] = messages[msg_i] # type: ignore if user_message_types_block["role"] == "user": if isinstance(user_message_types_block["content"], list): for m in user_message_types_block["content"]: @@ -4926,8 +4926,10 @@ class BedrockConverseMessagesProcessor: image_url = element["image_url"]["url"] else: image_url = element["image_url"] - assistants_part = await BedrockImageProcessor.process_image_async( # type: ignore - image_url=image_url + assistants_part = ( + await BedrockImageProcessor.process_image_async( # type: ignore + image_url=image_url + ) ) assistants_parts.append(assistants_part) # Add cache point block for assistant content elements diff --git a/litellm/litellm_core_utils/realtime_streaming.py b/litellm/litellm_core_utils/realtime_streaming.py index c56a70177bf..ca7208458d8 100644 --- a/litellm/litellm_core_utils/realtime_streaming.py +++ b/litellm/litellm_core_utils/realtime_streaming.py @@ -169,7 +169,9 @@ class RealTimeStreaming: try: event_type = message_obj.get("type", "") if event_type in self._SESSION_EVENT_TYPES: - typed_obj: OpenAIRealtimeEvents = OpenAIRealtimeStreamSessionEvents(**message_obj) # type: ignore + typed_obj: OpenAIRealtimeEvents = OpenAIRealtimeStreamSessionEvents( + **message_obj + ) # type: ignore else: # Catch-all base object so unknown/new event names never raise. typed_obj = OpenAIRealtimeStreamResponseBaseObject(**message_obj) # type: ignore diff --git a/litellm/litellm_core_utils/rules.py b/litellm/litellm_core_utils/rules.py index 717ff55ab22..75c177c7249 100644 --- a/litellm/litellm_core_utils/rules.py +++ b/litellm/litellm_core_utils/rules.py @@ -33,7 +33,11 @@ class Rules: if callable(rule): decision = rule(input) if decision is False: - raise litellm.APIResponseValidationError(message="LLM Response failed post-call-rule check", llm_provider="", model=model) # type: ignore + raise litellm.APIResponseValidationError( + message="LLM Response failed post-call-rule check", + llm_provider="", + model=model, + ) # type: ignore return True def post_call_rules(self, input: Optional[str], model: str) -> bool: @@ -44,12 +48,18 @@ class Rules: decision = rule(input) if isinstance(decision, bool): if decision is False: - raise litellm.APIResponseValidationError(message="LLM Response failed post-call-rule check", llm_provider="", model=model) # type: ignore + raise litellm.APIResponseValidationError( + message="LLM Response failed post-call-rule check", + llm_provider="", + model=model, + ) # type: ignore elif isinstance(decision, dict): decision_val = decision.get("decision", True) decision_message = decision.get( "message", "LLM Response failed post-call-rule check" ) if decision_val is False: - raise litellm.APIResponseValidationError(message=decision_message, llm_provider="", model=model) # type: ignore + raise litellm.APIResponseValidationError( + message=decision_message, llm_provider="", model=model + ) # type: ignore return True diff --git a/litellm/litellm_core_utils/sensitive_data_masker.py b/litellm/litellm_core_utils/sensitive_data_masker.py index b14e12de7cd..3135b5f831a 100644 --- a/litellm/litellm_core_utils/sensitive_data_masker.py +++ b/litellm/litellm_core_utils/sensitive_data_masker.py @@ -54,9 +54,9 @@ class SensitiveDataMasker: # Handle the case where visible_suffix is 0 to avoid showing the entire string if self.visible_suffix == 0: - return f"{value_str[:self.visible_prefix]}{self.mask_char * masked_length}" + return f"{value_str[: self.visible_prefix]}{self.mask_char * masked_length}" else: - return f"{value_str[:self.visible_prefix]}{self.mask_char * masked_length}{value_str[-self.visible_suffix:]}" + return f"{value_str[: self.visible_prefix]}{self.mask_char * masked_length}{value_str[-self.visible_suffix :]}" def is_sensitive_key( self, key: str, excluded_keys: Optional[Set[str]] = None diff --git a/litellm/litellm_core_utils/streaming_chunk_builder_utils.py b/litellm/litellm_core_utils/streaming_chunk_builder_utils.py index 04f6b1241c3..66abb824610 100644 --- a/litellm/litellm_core_utils/streaming_chunk_builder_utils.py +++ b/litellm/litellm_core_utils/streaming_chunk_builder_utils.py @@ -213,9 +213,9 @@ class ChunkProcessor: self, tool_call_chunks: List[Dict[str, Any]] ) -> List[ChatCompletionMessageToolCall]: tool_calls_list: List[ChatCompletionMessageToolCall] = [] - tool_call_map: Dict[int, Dict[str, Any]] = ( - {} - ) # Map to store tool calls by index + tool_call_map: Dict[ + int, Dict[str, Any] + ] = {} # Map to store tool calls by index for chunk in tool_call_chunks: choices = chunk["choices"] @@ -720,15 +720,16 @@ class ChunkProcessor: returned_usage.prompt_tokens = prompt_tokens or token_counter( model=model, messages=messages ) - except ( - Exception - ): # don't allow this failing to block a complete streaming response from being returned + except Exception: # don't allow this failing to block a complete streaming response from being returned print_verbose("token_counter failed, assuming prompt tokens is 0") returned_usage.prompt_tokens = 0 - returned_usage.completion_tokens = completion_tokens or token_counter( - model=model, - text=completion_output, - count_response_tokens=True, # count_response_tokens is a Flag to tell token counter this is a response, No need to add extra tokens we do for input messages + returned_usage.completion_tokens = ( + completion_tokens + or token_counter( + model=model, + text=completion_output, + count_response_tokens=True, # count_response_tokens is a Flag to tell token counter this is a response, No need to add extra tokens we do for input messages + ) ) returned_usage.total_tokens = ( returned_usage.prompt_tokens + returned_usage.completion_tokens diff --git a/litellm/litellm_core_utils/streaming_handler.py b/litellm/litellm_core_utils/streaming_handler.py index 03a87fb6a39..7d7a8e562cb 100644 --- a/litellm/litellm_core_utils/streaming_handler.py +++ b/litellm/litellm_core_utils/streaming_handler.py @@ -189,9 +189,7 @@ class CustomStreamWrapper: True if self.check_send_stream_usage(self.stream_options) else False ) self.tool_call = False - self.chunks: List = ( - [] - ) # keep track of the returned chunks - used for calculating the input/output tokens for stream options + self.chunks: List = [] # keep track of the returned chunks - used for calculating the input/output tokens for stream options self._repeated_messages_count = 1 self.is_function_call = self.check_is_function_call(logging_obj=logging_obj) self.created: Optional[int] = None @@ -1861,8 +1859,10 @@ class CustomStreamWrapper: Caches the streaming response """ if not cache_hit and self.logging_obj._llm_caching_handler is not None: - await self.logging_obj._llm_caching_handler._add_streaming_response_to_cache( - processed_chunk + await ( + self.logging_obj._llm_caching_handler._add_streaming_response_to_cache( + processed_chunk + ) ) def run_success_logging_and_cache_storage(self, processed_chunk, cache_hit: bool): @@ -2217,7 +2217,9 @@ class CustomStreamWrapper: ) ) # Add MCP metadata to final chunk if present (after hooks) - processed_chunk = self._add_mcp_metadata_to_final_chunk(processed_chunk) # type: ignore[reportArgumentType] + processed_chunk = self._add_mcp_metadata_to_final_chunk( + processed_chunk + ) # type: ignore[reportArgumentType] return processed_chunk raise StopAsyncIteration @@ -2229,7 +2231,9 @@ class CustomStreamWrapper: ): chunk = self.completion_stream else: - chunk = await asyncio.to_thread(_next_sync_or_exhausted, self.completion_stream) # type: ignore[arg-type] + chunk = await asyncio.to_thread( + _next_sync_or_exhausted, self.completion_stream + ) # type: ignore[arg-type] if chunk is _SYNC_ITER_EXHAUSTED: raise StopAsyncIteration if chunk is not None and chunk != b"": diff --git a/litellm/llms/__init__.py b/litellm/llms/__init__.py index 710342bbc78..fead8a79bc3 100644 --- a/litellm/llms/__init__.py +++ b/litellm/llms/__init__.py @@ -63,9 +63,9 @@ def get_cost_for_web_search_request( return None -def discover_guardrail_translation_mappings() -> ( - Dict[CallTypes, Type["BaseTranslation"]] -): +def discover_guardrail_translation_mappings() -> Dict[ + CallTypes, Type["BaseTranslation"] +]: """ Discover guardrail translation mappings by scanning the llms directory structure. diff --git a/litellm/llms/anthropic/chat/guardrail_translation/handler.py b/litellm/llms/anthropic/chat/guardrail_translation/handler.py index 74dadee5ecb..7d5944b4cc2 100644 --- a/litellm/llms/anthropic/chat/guardrail_translation/handler.py +++ b/litellm/llms/anthropic/chat/guardrail_translation/handler.py @@ -288,9 +288,9 @@ class AnthropicMessagesHandler(BaseTranslation): elif isinstance(content, list) and content_idx_optional is not None: # Replace specific text item in list content - messages[msg_idx]["content"][content_idx_optional][ - "text" - ] = guardrail_response + messages[msg_idx]["content"][content_idx_optional]["text"] = ( + guardrail_response + ) async def process_output_response( self, diff --git a/litellm/llms/anthropic/chat/handler.py b/litellm/llms/anthropic/chat/handler.py index 5d14f3cc4ae..e7e0f12c455 100644 --- a/litellm/llms/anthropic/chat/handler.py +++ b/litellm/llms/anthropic/chat/handler.py @@ -624,7 +624,9 @@ class ModelResponseIterator: speed=self.speed, ) - def _content_block_delta_helper(self, chunk: dict) -> Tuple[ + def _content_block_delta_helper( + self, chunk: dict + ) -> Tuple[ str, Optional[ChatCompletionToolCallChunk], List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]], diff --git a/litellm/llms/anthropic/chat/transformation.py b/litellm/llms/anthropic/chat/transformation.py index 822b75b37f4..2b2264e6da9 100644 --- a/litellm/llms/anthropic/chat/transformation.py +++ b/litellm/llms/anthropic/chat/transformation.py @@ -750,7 +750,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): additional_tool_params[k] = v returned_tool = AnthropicHostedTools( - type=tool["type"], name=function_name, **additional_tool_params # type: ignore + type=tool["type"], + name=function_name, + **additional_tool_params, # type: ignore ) elif tool["type"] == "url": # mcp server tool mcp_server = AnthropicMcpServerTool(**tool) # type: ignore @@ -2144,7 +2146,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): filtered_tools = [t for i, t in enumerate(tool_calls) if i not in json_indices] return None, filtered_tools, extra_content - def extract_response_content(self, completion_response: dict) -> Tuple[ + def extract_response_content( + self, completion_response: dict + ) -> Tuple[ str, Optional[List[Any]], Optional[ diff --git a/litellm/llms/anthropic/common_utils.py b/litellm/llms/anthropic/common_utils.py index 0f49ea402ad..eaa762204f2 100644 --- a/litellm/llms/anthropic/common_utils.py +++ b/litellm/llms/anthropic/common_utils.py @@ -502,7 +502,8 @@ class AnthropicModelInfo(BaseLLMModelInfo): "computer_20241022": "computer-use-2024-10-22", } return computer_tool_beta_mapping.get( - computer_tool_version, "computer-use-2024-10-22" # Default fallback + computer_tool_version, + "computer-use-2024-10-22", # Default fallback ) def get_anthropic_beta_list( diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py index a8e2fceb4ee..9860997b1cd 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py @@ -184,9 +184,7 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): # class level) so concurrent streams don't share the same mutable dict # — `_should_start_new_content_block` mutates `tool_block["name"]` in # place, which would otherwise leak across streams. - self.current_content_block_start: ( - "AnthropicStreamWrapper.ContentBlockContentBlockDict" - ) = self.TextBlock( + self.current_content_block_start: "AnthropicStreamWrapper.ContentBlockContentBlockDict" = self.TextBlock( type="text", text="", ) diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py index a4d0c93a3de..46564a565ce 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py @@ -595,9 +595,9 @@ class LiteLLMAnthropicMessagesAdapter: ## ASSISTANT MESSAGE ## assistant_message_str: Optional[str] = None - assistant_content_list: List[Dict[str, Any]] = ( - [] - ) # For content blocks with cache_control + assistant_content_list: List[ + Dict[str, Any] + ] = [] # For content blocks with cache_control has_cache_control_in_text = False tool_calls: List[ChatCompletionAssistantToolCall] = [] thinking_blocks: List[ @@ -1025,7 +1025,9 @@ class LiteLLMAnthropicMessagesAdapter: if openai_system_content: new_messages.insert( 0, - ChatCompletionSystemMessage(role="system", content=openai_system_content), # type: ignore + ChatCompletionSystemMessage( + role="system", content=openai_system_content + ), # type: ignore ) def _translate_metadata_to_openai( @@ -1456,7 +1458,9 @@ class LiteLLMAnthropicMessagesAdapter: "input_tokens": uncached_input_tokens, "output_tokens": usage.completion_tokens or 0, } - anthropic_usage["iterations"] = list(polyfill_result.iterations_usage) + [message_iteration] # type: ignore[typeddict-unknown-key] + anthropic_usage["iterations"] = list(polyfill_result.iterations_usage) + [ + message_iteration + ] # type: ignore[typeddict-unknown-key] translated_obj = AnthropicMessagesResponse( id=response.id, @@ -1672,7 +1676,9 @@ class LiteLLMAnthropicMessagesAdapter: else: usage_delta = UsageDelta(input_tokens=0, output_tokens=0) message_block = MessageBlockDelta( - type="message_delta", delta=delta, usage=usage_delta # type: ignore + type="message_delta", + delta=delta, + usage=usage_delta, # type: ignore ) if applied_edits: message_block["context_management"] = ContextManagementResponse( diff --git a/litellm/llms/anthropic/experimental_pass_through/messages/streaming_iterator.py b/litellm/llms/anthropic/experimental_pass_through/messages/streaming_iterator.py index 978eaab65d8..25109765772 100644 --- a/litellm/llms/anthropic/experimental_pass_through/messages/streaming_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/messages/streaming_iterator.py @@ -87,7 +87,7 @@ class BaseAnthropicMessagesStreamingIterator: """ if isinstance(chunk, dict): event_type: str = str(chunk.get("type", "message")) - payload = f"event: {event_type}\n" f"data: {json.dumps(chunk)}\n\n" + payload = f"event: {event_type}\ndata: {json.dumps(chunk)}\n\n" return payload.encode() else: # For non-dict chunks, return as is diff --git a/litellm/llms/anthropic/experimental_pass_through/responses_adapters/streaming_iterator.py b/litellm/llms/anthropic/experimental_pass_through/responses_adapters/streaming_iterator.py index 04819a416a2..f400dc7804e 100644 --- a/litellm/llms/anthropic/experimental_pass_through/responses_adapters/streaming_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/responses_adapters/streaming_iterator.py @@ -35,9 +35,9 @@ class AnthropicResponsesStreamWrapper: # Map item_id -> content_block_index so we can stop the right block later self._item_id_to_block_index: Dict[str, int] = {} # Track open function_call items by item_id so we can emit tool_use start - self._pending_tool_ids: Dict[str, str] = ( - {} - ) # item_id -> call_id / name accumulator + self._pending_tool_ids: Dict[ + str, str + ] = {} # item_id -> call_id / name accumulator self._sent_message_start = False self._sent_message_stop = False self._chunk_queue: deque = deque() diff --git a/litellm/llms/azure/assistants.py b/litellm/llms/azure/assistants.py index 271cd698e7b..750087b722e 100644 --- a/litellm/llms/azure/assistants.py +++ b/litellm/llms/azure/assistants.py @@ -203,8 +203,11 @@ class AzureAssistantsAPI(BaseAzureLLM): litellm_params=litellm_params, ) - thread_message: OpenAIMessage = await openai_client.beta.threads.messages.create( # type: ignore - thread_id, **message_data # type: ignore + thread_message: OpenAIMessage = ( + await openai_client.beta.threads.messages.create( # type: ignore + thread_id, + **message_data, # type: ignore + ) ) response_obj: Optional[OpenAIMessage] = None @@ -292,7 +295,8 @@ class AzureAssistantsAPI(BaseAzureLLM): ) thread_message: OpenAIMessage = openai_client.beta.threads.messages.create( # type: ignore - thread_id, **message_data # type: ignore + thread_id, + **message_data, # type: ignore ) response_obj: Optional[OpenAIMessage] = None diff --git a/litellm/llms/azure/audio_transcriptions.py b/litellm/llms/azure/audio_transcriptions.py index 70b2f1ccc08..591fe9d03a2 100644 --- a/litellm/llms/azure/audio_transcriptions.py +++ b/litellm/llms/azure/audio_transcriptions.py @@ -79,7 +79,8 @@ class AzureAudioTranscription(AzureChatCompletion): ) response = azure_client.audio.transcriptions.create( - **data, timeout=timeout # type: ignore + **data, + timeout=timeout, # type: ignore ) if isinstance(response, BaseModel): @@ -95,7 +96,12 @@ class AzureAudioTranscription(AzureChatCompletion): original_response=stringified_response, ) hidden_params = {"model": model, "custom_llm_provider": "azure"} - final_response: TranscriptionResponse = convert_to_model_response_object(response_object=stringified_response, model_response_object=model_response, hidden_params=hidden_params, response_type="audio_transcription") # type: ignore + final_response: TranscriptionResponse = convert_to_model_response_object( + response_object=stringified_response, + model_response_object=model_response, + hidden_params=hidden_params, + response_type="audio_transcription", + ) # type: ignore return final_response async def async_audio_transcriptions( diff --git a/litellm/llms/azure/azure.py b/litellm/llms/azure/azure.py index 5be3ce22832..8edab95ef6c 100644 --- a/litellm/llms/azure/azure.py +++ b/litellm/llms/azure/azure.py @@ -817,7 +817,9 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): ) ## COMPLETION CALL - raw_response = azure_client.embeddings.with_raw_response.create(**data, timeout=timeout) # type: ignore + raw_response = azure_client.embeddings.with_raw_response.create( + **data, timeout=timeout + ) # type: ignore headers = dict(raw_response.headers) response = raw_response.parse() if isinstance(response, str): @@ -833,7 +835,12 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): original_response=response, ) - return convert_to_model_response_object(response_object=response.model_dump(), model_response_object=model_response, response_type="embedding", _response_headers=process_azure_headers(headers)) # type: ignore + return convert_to_model_response_object( + response_object=response.model_dump(), + model_response_object=model_response, + response_type="embedding", + _response_headers=process_azure_headers(headers), + ) # type: ignore except AzureOpenAIError as e: raise e except Exception as e: @@ -1296,7 +1303,18 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): is_async=False, ) if aimg_generation is True: - return self.aimage_generation(data=data, input=input, logging_obj=logging_obj, model_response=model_response, api_key=api_key, client=client, azure_client_params=azure_client_params, timeout=timeout, headers=headers, model=model) # type: ignore + return self.aimage_generation( + data=data, + input=input, + logging_obj=logging_obj, + model_response=model_response, + api_key=api_key, + client=client, + azure_client_params=azure_client_params, + timeout=timeout, + headers=headers, + model=model, + ) # type: ignore img_gen_api_base = self.create_azure_base_url( azure_client_params=azure_client_params, @@ -1348,7 +1366,11 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): original_response=response, ) # return response - return convert_to_model_response_object(response_object=response, model_response_object=model_response, response_type="image_generation") # type: ignore + return convert_to_model_response_object( + response_object=response, + model_response_object=model_response, + response_type="image_generation", + ) # type: ignore except AzureOpenAIError as e: raise e except Exception as e: diff --git a/litellm/llms/azure/batches/handler.py b/litellm/llms/azure/batches/handler.py index 6da3670b34a..ea6722839e6 100644 --- a/litellm/llms/azure/batches/handler.py +++ b/litellm/llms/azure/batches/handler.py @@ -75,7 +75,9 @@ class AzureBatchesAPI(BaseAzureLLM): return self.acreate_batch( # type: ignore create_batch_data=create_batch_data, azure_client=azure_client ) - response = cast(Union[AzureOpenAI, OpenAI], azure_client).batches.create(**create_batch_data) # type: ignore[arg-type] + response = cast(Union[AzureOpenAI, OpenAI], azure_client).batches.create( + **create_batch_data + ) # type: ignore[arg-type] return LiteLLMBatch(**response.model_dump()) async def aretrieve_batch( diff --git a/litellm/llms/azure/files/handler.py b/litellm/llms/azure/files/handler.py index 72cbcba8a9a..cca83b8e6fd 100644 --- a/litellm/llms/azure/files/handler.py +++ b/litellm/llms/azure/files/handler.py @@ -45,7 +45,9 @@ class AzureOpenAIFilesAPI(BaseAzureLLM): openai_client: Union[AsyncAzureOpenAI, AsyncOpenAI], ) -> OpenAIFileObject: verbose_logger.debug("create_file_data=%s", create_file_data) - response = await openai_client.files.create(**self._prepare_create_file_data(create_file_data)) # type: ignore[arg-type] + response = await openai_client.files.create( + **self._prepare_create_file_data(create_file_data) + ) # type: ignore[arg-type] verbose_logger.debug("create_file_response=%s", response) return OpenAIFileObject(**response.model_dump()) @@ -86,7 +88,9 @@ class AzureOpenAIFilesAPI(BaseAzureLLM): return self.acreate_file( create_file_data=create_file_data, openai_client=openai_client ) - response = cast(Union[AzureOpenAI, OpenAI], openai_client).files.create(**self._prepare_create_file_data(create_file_data)) # type: ignore[arg-type] + response = cast(Union[AzureOpenAI, OpenAI], openai_client).files.create( + **self._prepare_create_file_data(create_file_data) + ) # type: ignore[arg-type] return OpenAIFileObject(**response.model_dump()) async def afile_content( diff --git a/litellm/llms/bedrock/chat/agentcore/transformation.py b/litellm/llms/bedrock/chat/agentcore/transformation.py index 3cd3a249c33..542af61dd3f 100644 --- a/litellm/llms/bedrock/chat/agentcore/transformation.py +++ b/litellm/llms/bedrock/chat/agentcore/transformation.py @@ -403,8 +403,7 @@ class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM): # skip strategy matching and fall back to raw JSON string if not isinstance(response_json, dict): verbose_logger.warning( - "AgentCore: JSON response is not a dict. " - "Returning raw JSON as content." + "AgentCore: JSON response is not a dict. Returning raw JSON as content." ) return AgentCoreParsedResponse( content=json.dumps(response_json), @@ -940,9 +939,9 @@ class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM): ) parsed = self._parse_json_response(response_json) - async def _json_as_async_stream() -> ( - AsyncGenerator[ModelResponseStream, None] - ): + async def _json_as_async_stream() -> AsyncGenerator[ + ModelResponseStream, None + ]: # Content chunk content_chunk = ModelResponseStream( id=f"chatcmpl-{uuid.uuid4()}", diff --git a/litellm/llms/bedrock/chat/converse_handler.py b/litellm/llms/bedrock/chat/converse_handler.py index 7b1064ccef9..040193f6bcc 100644 --- a/litellm/llms/bedrock/chat/converse_handler.py +++ b/litellm/llms/bedrock/chat/converse_handler.py @@ -51,19 +51,19 @@ def make_sync_call( ) if fake_stream: - model_response: ( - ModelResponse - ) = litellm.AmazonConverseConfig()._transform_response( - model=model, - response=response, - model_response=litellm.ModelResponse(), - stream=True, - logging_obj=logging_obj, - optional_params={}, - api_key="", - data=data, - messages=messages, - encoding=litellm.encoding, + model_response: ModelResponse = ( + litellm.AmazonConverseConfig()._transform_response( + model=model, + response=response, + model_response=litellm.ModelResponse(), + stream=True, + logging_obj=logging_obj, + optional_params={}, + api_key="", + data=data, + messages=messages, + encoding=litellm.encoding, + ) ) # type: ignore completion_stream: Any = MockResponseIterator( model_response=model_response, json_mode=json_mode diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index bb261ec85b2..a700c07d87a 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -1963,7 +1963,9 @@ class AmazonConverseConfig(BaseConfig): return message, returned_finish_reason - def _translate_message_content(self, content_blocks: List[ContentBlock]) -> Tuple[ + def _translate_message_content( + self, content_blocks: List[ContentBlock] + ) -> Tuple[ str, List[ChatCompletionToolCallChunk], Optional[List[BedrockConverseReasoningContentBlock]], diff --git a/litellm/llms/bedrock/chat/invoke_handler.py b/litellm/llms/bedrock/chat/invoke_handler.py index 9fca7bc61af..29e97068100 100644 --- a/litellm/llms/bedrock/chat/invoke_handler.py +++ b/litellm/llms/bedrock/chat/invoke_handler.py @@ -225,19 +225,19 @@ async def make_call( raise BedrockError(status_code=response.status_code, message=response.text) if fake_stream: - model_response: ( - ModelResponse - ) = litellm.AmazonConverseConfig()._transform_response( - model=model, - response=response, - model_response=litellm.ModelResponse(), - stream=True, - logging_obj=logging_obj, - optional_params={}, - api_key="", - data=data, - messages=messages, - encoding=litellm.encoding, + model_response: ModelResponse = ( + litellm.AmazonConverseConfig()._transform_response( + model=model, + response=response, + model_response=litellm.ModelResponse(), + stream=True, + logging_obj=logging_obj, + optional_params={}, + api_key="", + data=data, + messages=messages, + encoding=litellm.encoding, + ) ) # type: ignore completion_stream: Any = MockResponseIterator( model_response=model_response, json_mode=json_mode @@ -321,19 +321,19 @@ def make_sync_call( raise BedrockError(status_code=response.status_code, message=response.text) if fake_stream: - model_response: ( - ModelResponse - ) = litellm.AmazonConverseConfig()._transform_response( - model=model, - response=response, - model_response=litellm.ModelResponse(), - stream=True, - logging_obj=logging_obj, - optional_params={}, - api_key="", - data=data, - messages=messages, - encoding=litellm.encoding, + model_response: ModelResponse = ( + litellm.AmazonConverseConfig()._transform_response( + model=model, + response=response, + model_response=litellm.ModelResponse(), + stream=True, + logging_obj=logging_obj, + optional_params={}, + api_key="", + data=data, + messages=messages, + encoding=litellm.encoding, + ) ) # type: ignore completion_stream: Any = MockResponseIterator( model_response=model_response, json_mode=json_mode @@ -1300,7 +1300,9 @@ class BedrockLLM(BaseAWSLLM): if isinstance(timeout, float) or isinstance(timeout, int): timeout = httpx.Timeout(timeout) _params["timeout"] = timeout - client = get_async_httpx_client(params=_params, llm_provider=litellm.LlmProviders.BEDROCK) # type: ignore + client = get_async_httpx_client( + params=_params, llm_provider=litellm.LlmProviders.BEDROCK + ) # type: ignore else: client = client # type: ignore diff --git a/litellm/llms/bedrock/embed/embedding.py b/litellm/llms/bedrock/embed/embedding.py index b6aa99842d7..bc72f04deac 100644 --- a/litellm/llms/bedrock/embed/embedding.py +++ b/litellm/llms/bedrock/embed/embedding.py @@ -142,7 +142,9 @@ class BedrockEmbedding(BaseAWSLLM): client = client try: - response = await client.post(url=api_base, headers=headers, data=json.dumps(data)) # type: ignore + response = await client.post( + url=api_base, headers=headers, data=json.dumps(data) + ) # type: ignore response.raise_for_status() except httpx.HTTPStatusError as err: error_code = err.response.status_code @@ -451,10 +453,10 @@ class BedrockEmbedding(BaseAWSLLM): batch_data = [] for i in input: if model == "amazon.titan-embed-image-v1": - transformed_request: ( - AmazonEmbeddingRequest - ) = AmazonTitanMultimodalEmbeddingG1Config()._transform_request( - input=i, inference_params=inference_params + transformed_request: AmazonEmbeddingRequest = ( + AmazonTitanMultimodalEmbeddingG1Config()._transform_request( + input=i, inference_params=inference_params + ) ) elif model == "amazon.titan-embed-text-v1": transformed_request = AmazonTitanG1Config()._transform_request( diff --git a/litellm/llms/bedrock/image_edit/handler.py b/litellm/llms/bedrock/image_edit/handler.py index 90344310746..04fa5f803bb 100644 --- a/litellm/llms/bedrock/image_edit/handler.py +++ b/litellm/llms/bedrock/image_edit/handler.py @@ -112,7 +112,11 @@ class BedrockImageEdit(BaseAWSLLM): if client is None or not isinstance(client, HTTPHandler): client = _get_httpx_client() try: - response = client.post(url=prepared_request.endpoint_url, headers=prepared_request.prepped.headers, data=prepared_request.body) # type: ignore + response = client.post( + url=prepared_request.endpoint_url, + headers=prepared_request.prepped.headers, + data=prepared_request.body, + ) # type: ignore response.raise_for_status() except httpx.HTTPStatusError as err: error_code = err.response.status_code @@ -150,7 +154,11 @@ class BedrockImageEdit(BaseAWSLLM): ) try: - response = await async_client.post(url=prepared_request.endpoint_url, headers=prepared_request.prepped.headers, data=prepared_request.body) # type: ignore + response = await async_client.post( + url=prepared_request.endpoint_url, + headers=prepared_request.prepped.headers, + data=prepared_request.body, + ) # type: ignore response.raise_for_status() except httpx.HTTPStatusError as err: error_code = err.response.status_code diff --git a/litellm/llms/bedrock/image_edit/stability_transformation.py b/litellm/llms/bedrock/image_edit/stability_transformation.py index d00d62a8530..e76b2885a88 100644 --- a/litellm/llms/bedrock/image_edit/stability_transformation.py +++ b/litellm/llms/bedrock/image_edit/stability_transformation.py @@ -122,7 +122,9 @@ class BedrockStabilityImageEditConfig(BaseImageEditConfig): if k in param_mapping: # Map param if mapping exists and value is valid if k == "size" and v in OPENAI_SIZE_TO_STABILITY_ASPECT_RATIO: - mapped_params[param_mapping[k]] = OPENAI_SIZE_TO_STABILITY_ASPECT_RATIO[v] # type: ignore + mapped_params[param_mapping[k]] = ( + OPENAI_SIZE_TO_STABILITY_ASPECT_RATIO[v] + ) # type: ignore # Don't copy "size" itself to final dict elif k == "n": # Store for logic but do not add to outgoing params diff --git a/litellm/llms/bedrock/image_generation/amazon_nova_canvas_transformation.py b/litellm/llms/bedrock/image_generation/amazon_nova_canvas_transformation.py index 87ef469beb5..9e06a8e747d 100644 --- a/litellm/llms/bedrock/image_generation/amazon_nova_canvas_transformation.py +++ b/litellm/llms/bedrock/image_generation/amazon_nova_canvas_transformation.py @@ -111,8 +111,10 @@ class AmazonNovaCanvasConfig: **color_guided_generation_params, } try: - color_guided_generation_params_typed = AmazonNovaCanvasColorGuidedGenerationParams( - **color_guided_generation_params # type: ignore + color_guided_generation_params_typed = ( + AmazonNovaCanvasColorGuidedGenerationParams( + **color_guided_generation_params # type: ignore + ) ) except Exception as e: raise ValueError( @@ -171,8 +173,9 @@ class AmazonNovaCanvasConfig: _size = non_default_params.get("size") if _size is not None: width, height = _size.split("x") - optional_params["width"], optional_params["height"] = int(width), int( - height + optional_params["width"], optional_params["height"] = ( + int(width), + int(height), ) if non_default_params.get("n") is not None: optional_params["numberOfImages"] = non_default_params.get("n") diff --git a/litellm/llms/bedrock/image_generation/image_handler.py b/litellm/llms/bedrock/image_generation/image_handler.py index d6053278cbd..0c594d0b142 100644 --- a/litellm/llms/bedrock/image_generation/image_handler.py +++ b/litellm/llms/bedrock/image_generation/image_handler.py @@ -115,7 +115,11 @@ class BedrockImageGeneration(BaseAWSLLM): if client is None or not isinstance(client, HTTPHandler): client = _get_httpx_client() try: - response = client.post(url=prepared_request.endpoint_url, headers=prepared_request.prepped.headers, data=prepared_request.body) # type: ignore + response = client.post( + url=prepared_request.endpoint_url, + headers=prepared_request.prepped.headers, + data=prepared_request.body, + ) # type: ignore response.raise_for_status() except httpx.HTTPStatusError as err: error_code = err.response.status_code @@ -154,7 +158,11 @@ class BedrockImageGeneration(BaseAWSLLM): ) try: - response = await async_client.post(url=prepared_request.endpoint_url, headers=prepared_request.prepped.headers, data=prepared_request.body) # type: ignore + response = await async_client.post( + url=prepared_request.endpoint_url, + headers=prepared_request.prepped.headers, + data=prepared_request.body, + ) # type: ignore response.raise_for_status() except httpx.HTTPStatusError as err: error_code = err.response.status_code diff --git a/litellm/llms/bedrock/realtime/handler.py b/litellm/llms/bedrock/realtime/handler.py index 0e2e06cf62c..5d22f4b3cd9 100644 --- a/litellm/llms/bedrock/realtime/handler.py +++ b/litellm/llms/bedrock/realtime/handler.py @@ -237,9 +237,7 @@ class BedrockRealtime(BaseAWSLLM): # Transform Bedrock format to OpenAI format from litellm.types.realtime import RealtimeResponseTransformInput - realtime_response_transform_input: ( - RealtimeResponseTransformInput - ) = { + realtime_response_transform_input: RealtimeResponseTransformInput = { "current_output_item_id": session_state.get( "current_output_item_id" ), diff --git a/litellm/llms/bedrock/rerank/handler.py b/litellm/llms/bedrock/rerank/handler.py index 812ca116c27..276c6f23c33 100644 --- a/litellm/llms/bedrock/rerank/handler.py +++ b/litellm/llms/bedrock/rerank/handler.py @@ -96,7 +96,13 @@ class BedrockRerankHandler(BaseAWSLLM): ) if _is_async: - return self.arerank(prepared_request, timeout=timeout, client=client if client is not None and isinstance(client, AsyncHTTPHandler) else None) # type: ignore + return self.arerank( + prepared_request, + timeout=timeout, + client=client + if client is not None and isinstance(client, AsyncHTTPHandler) + else None, + ) # type: ignore if client is None or not isinstance(client, HTTPHandler): client = _get_httpx_client() diff --git a/litellm/llms/bedrock/vector_stores/transformation.py b/litellm/llms/bedrock/vector_stores/transformation.py index ec20d76102b..a479d148064 100644 --- a/litellm/llms/bedrock/vector_stores/transformation.py +++ b/litellm/llms/bedrock/vector_stores/transformation.py @@ -253,9 +253,9 @@ class BedrockVectorStoreConfig(BaseVectorStoreConfig, BaseAWSLLM): verbose_logger.debug( "Overriding extra_body retrievalConfiguration.vectorSearchConfiguration.filter with filters from vector_store_search_optional_params" ) - retrieval_config.setdefault("vectorSearchConfiguration", {})[ - "filter" - ] = filters + retrieval_config.setdefault("vectorSearchConfiguration", {})["filter"] = ( + filters + ) if retrieval_config: request_body["retrievalConfiguration"] = cast( BedrockKBRetrievalConfiguration, retrieval_config diff --git a/litellm/llms/custom_httpx/http_handler.py b/litellm/llms/custom_httpx/http_handler.py index 1000ab12803..33601b47609 100644 --- a/litellm/llms/custom_httpx/http_handler.py +++ b/litellm/llms/custom_httpx/http_handler.py @@ -72,9 +72,9 @@ _AIOHTTP_SUPPORTS_SOCKET_FACTORY = ( ) -def _build_aiohttp_keepalive_socket_factory() -> ( - Optional[Callable[[Tuple[Any, ...]], socket.socket]] -): +def _build_aiohttp_keepalive_socket_factory() -> Optional[ + Callable[[Tuple[Any, ...]], socket.socket] +]: """ Build a socket_factory that enables SO_KEEPALIVE on aiohttp TCP sockets. @@ -719,7 +719,14 @@ class AsyncHTTPHandler: ) req = self.client.build_request( - "PUT", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore + "PUT", + url, + data=request_data, + json=json, + params=params, + headers=headers, + timeout=timeout, + content=request_content, # type: ignore ) response = await self.client.send(req) response.raise_for_status() @@ -780,7 +787,14 @@ class AsyncHTTPHandler: ) req = self.client.build_request( - "PATCH", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore + "PATCH", + url, + data=request_data, + json=json, + params=params, + headers=headers, + timeout=timeout, + content=request_content, # type: ignore ) response = await self.client.send(req) response.raise_for_status() @@ -841,7 +855,14 @@ class AsyncHTTPHandler: ) req = self.client.build_request( - "DELETE", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore + "DELETE", + url, + data=request_data, + json=json, + params=params, + headers=headers, + timeout=timeout, + content=request_content, # type: ignore ) response = await self.client.send(req, stream=stream) response.raise_for_status() @@ -888,7 +909,13 @@ class AsyncHTTPHandler: request_data, request_content = _prepare_request_data_and_content(data, content) req = client.build_request( - "POST", url, data=request_data, json=json, params=params, headers=headers, content=request_content # type: ignore + "POST", + url, + data=request_data, + json=json, + params=params, + headers=headers, + content=request_content, # type: ignore ) response = await client.send(req, stream=stream) response.raise_for_status() @@ -1200,7 +1227,14 @@ class HTTPHandler: ) else: req = self.client.build_request( - "POST", url, data=request_data, json=json, params=params, headers=headers, files=files, content=request_content # type: ignore + "POST", + url, + data=request_data, + json=json, + params=params, + headers=headers, + files=files, + content=request_content, # type: ignore ) response = self.client.send(req, stream=stream) response.raise_for_status() @@ -1235,11 +1269,24 @@ class HTTPHandler: if timeout is not None: req = self.client.build_request( - "PATCH", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore + "PATCH", + url, + data=request_data, + json=json, + params=params, + headers=headers, + timeout=timeout, + content=request_content, # type: ignore ) else: req = self.client.build_request( - "PATCH", url, data=request_data, json=json, params=params, headers=headers, content=request_content # type: ignore + "PATCH", + url, + data=request_data, + json=json, + params=params, + headers=headers, + content=request_content, # type: ignore ) response = self.client.send(req, stream=stream) response.raise_for_status() @@ -1274,11 +1321,24 @@ class HTTPHandler: if timeout is not None: req = self.client.build_request( - "PUT", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore + "PUT", + url, + data=request_data, + json=json, + params=params, + headers=headers, + timeout=timeout, + content=request_content, # type: ignore ) else: req = self.client.build_request( - "PUT", url, data=request_data, json=json, params=params, headers=headers, content=request_content # type: ignore + "PUT", + url, + data=request_data, + json=json, + params=params, + headers=headers, + content=request_content, # type: ignore ) response = self.client.send(req, stream=stream) return response @@ -1312,11 +1372,24 @@ class HTTPHandler: if timeout is not None: req = self.client.build_request( - "DELETE", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore + "DELETE", + url, + data=request_data, + json=json, + params=params, + headers=headers, + timeout=timeout, + content=request_content, # type: ignore ) else: req = self.client.build_request( - "DELETE", url, data=request_data, json=json, params=params, headers=headers, content=request_content # type: ignore + "DELETE", + url, + data=request_data, + json=json, + params=params, + headers=headers, + content=request_content, # type: ignore ) response = self.client.send(req, stream=stream) response.raise_for_status() diff --git a/litellm/llms/custom_httpx/httpx_handler.py b/litellm/llms/custom_httpx/httpx_handler.py index ce587946710..6e9f29151cd 100644 --- a/litellm/llms/custom_httpx/httpx_handler.py +++ b/litellm/llms/custom_httpx/httpx_handler.py @@ -54,7 +54,10 @@ class HTTPHandler: ): try: response = await self.client.post( - url, data=data, params=params, headers=headers # type: ignore + url, + data=data, + params=params, + headers=headers, # type: ignore ) return response except Exception as e: diff --git a/litellm/llms/fireworks_ai/chat/transformation.py b/litellm/llms/fireworks_ai/chat/transformation.py index 7e4395959b9..3c93677d6d4 100644 --- a/litellm/llms/fireworks_ai/chat/transformation.py +++ b/litellm/llms/fireworks_ai/chat/transformation.py @@ -578,11 +578,11 @@ class FireworksAIConfig(OpenAIGPTConfig): ## FIREWORKS AI sends tool calls in the content field instead of tool_calls for choice in response.choices: - cast(Choices, choice).message = ( - self._handle_message_content_with_tool_calls( - message=cast(Choices, choice).message, - tool_calls=optional_params.get("tools", None), - ) + cast( + Choices, choice + ).message = self._handle_message_content_with_tool_calls( + message=cast(Choices, choice).message, + tool_calls=optional_params.get("tools", None), ) response._hidden_params = { diff --git a/litellm/llms/gemini/realtime/transformation.py b/litellm/llms/gemini/realtime/transformation.py index e153d00e6ab..a8cb40ac6db 100644 --- a/litellm/llms/gemini/realtime/transformation.py +++ b/litellm/llms/gemini/realtime/transformation.py @@ -1755,9 +1755,9 @@ class GeminiRealtimeConfig(BaseRealtimeConfig): ) tool_call_temperature = tool_call_generation_config.get("temperature") if tool_call_temperature is not None: - tool_call_done_event["response"][ - "temperature" - ] = tool_call_temperature + tool_call_done_event["response"]["temperature"] = ( + tool_call_temperature + ) tool_call_max_output_tokens = tool_call_generation_config.get( "maxOutputTokens" ) diff --git a/litellm/llms/github_copilot/authenticator.py b/litellm/llms/github_copilot/authenticator.py index 9de2987b9f6..3785f9c4657 100644 --- a/litellm/llms/github_copilot/authenticator.py +++ b/litellm/llms/github_copilot/authenticator.py @@ -182,7 +182,7 @@ class Authenticator: ) except httpx.HTTPStatusError as e: verbose_logger.error( - f"HTTP error refreshing API key (attempt {attempt+1}/{max_retries}): {str(e)}" + f"HTTP error refreshing API key (attempt {attempt + 1}/{max_retries}): {str(e)}" ) except Exception as e: verbose_logger.error(f"Unexpected error refreshing API key: {str(e)}") @@ -318,7 +318,7 @@ class Authenticator: and resp_json.get("error") == "authorization_pending" ): verbose_logger.debug( - f"Authorization pending (attempt {attempt+1}/{max_attempts})" + f"Authorization pending (attempt {attempt + 1}/{max_attempts})" ) else: verbose_logger.warning(f"Unexpected response: {resp_json}") diff --git a/litellm/llms/github_copilot/responses/transformation.py b/litellm/llms/github_copilot/responses/transformation.py index 299f346a7eb..d9f759e0a05 100644 --- a/litellm/llms/github_copilot/responses/transformation.py +++ b/litellm/llms/github_copilot/responses/transformation.py @@ -58,8 +58,7 @@ def github_copilot_supports_responses_api(model: str) -> bool: ) except Exception as e: verbose_logger.debug( - "github_copilot_supports_responses_api: get_model_info failed " - "for %s: %s", + "github_copilot_supports_responses_api: get_model_info failed for %s: %s", model, e, ) diff --git a/litellm/llms/inception/chat/transformation.py b/litellm/llms/inception/chat/transformation.py index d591f783a99..ff87060449b 100644 --- a/litellm/llms/inception/chat/transformation.py +++ b/litellm/llms/inception/chat/transformation.py @@ -45,7 +45,11 @@ class InceptionChatConfig(OpenAILikeChatConfig): self, api_base: Optional[str], api_key: Optional[str] ) -> Tuple[Optional[str], Optional[str]]: passed_api_base = api_base - api_base = api_base or get_secret_str("INCEPTION_API_BASE") or "https://api.inceptionlabs.ai/v1" # type: ignore + api_base = ( + api_base + or get_secret_str("INCEPTION_API_BASE") + or "https://api.inceptionlabs.ai/v1" + ) # type: ignore dynamic_api_key = api_key if passed_api_base is None or api_key: dynamic_api_key = ( diff --git a/litellm/llms/llamafile/chat/transformation.py b/litellm/llms/llamafile/chat/transformation.py index 3387a0eb6aa..223f5503c9c 100644 --- a/litellm/llms/llamafile/chat/transformation.py +++ b/litellm/llms/llamafile/chat/transformation.py @@ -27,7 +27,11 @@ class LlamafileChatConfig(OpenAIGPTConfig): If both are None, a default Llamafile server URL is returned. See: https://github.com/Mozilla-Ocho/llamafile/blob/bd1bbe9aabb1ee12dbdcafa8936db443c571eb9d/README.md#L61 """ - return api_base or get_secret_str("LLAMAFILE_API_BASE") or "http://127.0.0.1:8080/v1" # type: ignore + return ( + api_base + or get_secret_str("LLAMAFILE_API_BASE") + or "http://127.0.0.1:8080/v1" + ) # type: ignore def _get_openai_compatible_provider_info( self, api_base: Optional[str], api_key: Optional[str] diff --git a/litellm/llms/moonshot/chat/transformation.py b/litellm/llms/moonshot/chat/transformation.py index da8687bce72..587fa0ed8d6 100644 --- a/litellm/llms/moonshot/chat/transformation.py +++ b/litellm/llms/moonshot/chat/transformation.py @@ -64,7 +64,11 @@ class MoonshotChatConfig(OpenAIGPTConfig): def _get_openai_compatible_provider_info( self, api_base: Optional[str], api_key: Optional[str] ) -> Tuple[Optional[str], Optional[str]]: - api_base = api_base or get_secret_str("MOONSHOT_API_BASE") or "https://api.moonshot.ai/v1" # type: ignore + api_base = ( + api_base + or get_secret_str("MOONSHOT_API_BASE") + or "https://api.moonshot.ai/v1" + ) # type: ignore dynamic_api_key = api_key or get_secret_str("MOONSHOT_API_KEY") return api_base, dynamic_api_key diff --git a/litellm/llms/nvidia_nim/rerank/transformation.py b/litellm/llms/nvidia_nim/rerank/transformation.py index fc317293acc..05f545c2944 100644 --- a/litellm/llms/nvidia_nim/rerank/transformation.py +++ b/litellm/llms/nvidia_nim/rerank/transformation.py @@ -234,12 +234,18 @@ class NvidiaNimRerankConfig(BaseRerankConfig): } # Add optional top_k parameter if provided (already mapped from top_n in map_cohere_rerank_params) - if "top_k" in optional_rerank_params and optional_rerank_params.get("top_k") is not None: # type: ignore + if ( + "top_k" in optional_rerank_params + and optional_rerank_params.get("top_k") is not None + ): # type: ignore request_data["top_k"] = optional_rerank_params.get("top_k") # type: ignore # Add Nvidia-specific truncate parameter if provided # This is passed through from non_default_params, not in base OptionalRerankParams - if "truncate" in optional_rerank_params and optional_rerank_params.get("truncate") is not None: # type: ignore + if ( + "truncate" in optional_rerank_params + and optional_rerank_params.get("truncate") is not None + ): # type: ignore truncate_value = optional_rerank_params.get("truncate") # type: ignore if truncate_value in ["NONE", "END"]: request_data["truncate"] = truncate_value # type: ignore diff --git a/litellm/llms/oci/chat/cohere.py b/litellm/llms/oci/chat/cohere.py index ac92fd22aa8..de8a09b7a3b 100644 --- a/litellm/llms/oci/chat/cohere.py +++ b/litellm/llms/oci/chat/cohere.py @@ -274,7 +274,9 @@ def handle_cohere_response( total_tokens=usage_info.totalTokens, ) else: - model_response.usage = Usage(prompt_tokens=0, completion_tokens=0, total_tokens=0) # type: ignore[attr-defined] + model_response.usage = Usage( + prompt_tokens=0, completion_tokens=0, total_tokens=0 + ) # type: ignore[attr-defined] return model_response diff --git a/litellm/llms/oci/chat/transformation.py b/litellm/llms/oci/chat/transformation.py index d1248b6e518..35d5aefeacb 100644 --- a/litellm/llms/oci/chat/transformation.py +++ b/litellm/llms/oci/chat/transformation.py @@ -529,7 +529,8 @@ class OCIChatConfig(BaseConfig): ) else: selected_params["tools"] = adapt_tool_definition_to_oci_standard( # type: ignore[assignment] - selected_params["tools"], vendor # type: ignore[arg-type] + selected_params["tools"], + vendor, # type: ignore[arg-type] ) # Normalise tool_choice to OCI's flat uppercase dict form diff --git a/litellm/llms/oci/common_utils.py b/litellm/llms/oci/common_utils.py index 8785b1548a5..29c88cbd50f 100644 --- a/litellm/llms/oci/common_utils.py +++ b/litellm/llms/oci/common_utils.py @@ -339,7 +339,9 @@ def sign_with_manual_credentials( private_key = ( load_private_key_from_str(oci_key_content) if oci_key_content - else load_private_key_from_file(oci_key_file) if oci_key_file else None + else load_private_key_from_file(oci_key_file) + if oci_key_file + else None ) if private_key is None: diff --git a/litellm/llms/ollama/chat/transformation.py b/litellm/llms/ollama/chat/transformation.py index e36150a4954..5c0624fe5c9 100644 --- a/litellm/llms/ollama/chat/transformation.py +++ b/litellm/llms/ollama/chat/transformation.py @@ -411,7 +411,9 @@ class OllamaChatConfig(BaseConfig): model_response.choices[0].finish_reason = "tool_calls" model_response.created = int(time.time()) model_response.model = "ollama_chat/" + model - prompt_tokens = response_json.get("prompt_eval_count", litellm.token_counter(messages=messages)) # type: ignore + prompt_tokens = response_json.get( + "prompt_eval_count", litellm.token_counter(messages=messages) + ) # type: ignore completion_tokens = response_json.get( "eval_count", litellm.token_counter(text=response_json["message"]["content"]), diff --git a/litellm/llms/ollama/completion/transformation.py b/litellm/llms/ollama/completion/transformation.py index 7e34af43d43..a8cdbff87d0 100644 --- a/litellm/llms/ollama/completion/transformation.py +++ b/litellm/llms/ollama/completion/transformation.py @@ -337,7 +337,8 @@ class OllamaConfig(BaseConfig): model_response.model = "ollama/" + model _prompt = request_data.get("prompt", "") prompt_tokens = response_json.get( - "prompt_eval_count", len(encoding.encode(_prompt, disallowed_special=())) # type: ignore + "prompt_eval_count", + len(encoding.encode(_prompt, disallowed_special=())), # type: ignore ) completion_tokens = response_json.get( "eval_count", len(response_json.get("message", dict()).get("content", "")) diff --git a/litellm/llms/oobabooga/chat/transformation.py b/litellm/llms/oobabooga/chat/transformation.py index e87b70130ce..0c118efbc35 100644 --- a/litellm/llms/oobabooga/chat/transformation.py +++ b/litellm/llms/oobabooga/chat/transformation.py @@ -65,7 +65,9 @@ class OobaboogaConfig(OpenAIGPTConfig): ) else: try: - model_response.choices[0].message.content = completion_response["choices"][0]["message"]["content"] # type: ignore + model_response.choices[0].message.content = completion_response[ + "choices" + ][0]["message"]["content"] # type: ignore except Exception as e: raise OobaboogaError( message=str(e), diff --git a/litellm/llms/openai/chat/gpt_transformation.py b/litellm/llms/openai/chat/gpt_transformation.py index b8b750b8c12..e4d55404743 100644 --- a/litellm/llms/openai/chat/gpt_transformation.py +++ b/litellm/llms/openai/chat/gpt_transformation.py @@ -379,10 +379,10 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig): List[OpenAIMessageContentListBlock], message_content ) for i, content_item in enumerate(message_content_types): - message_content_types[i] = ( - await self._async_transform_content_item( - cast(OpenAIMessageContentListBlock, content_item), - ) + message_content_types[ + i + ] = await self._async_transform_content_item( + cast(OpenAIMessageContentListBlock, content_item), ) return messages @@ -419,7 +419,8 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig): for i, message in enumerate(messages): messages[i] = cast( - AllMessageValues, filter_value_from_dict(message, "cache_control") # type: ignore + AllMessageValues, + filter_value_from_dict(message, "cache_control"), # type: ignore ) if tools is not None: for i, tool in enumerate(tools): diff --git a/litellm/llms/openai/chat/guardrail_translation/handler.py b/litellm/llms/openai/chat/guardrail_translation/handler.py index 8c9a8228daf..3b5980023c7 100644 --- a/litellm/llms/openai/chat/guardrail_translation/handler.py +++ b/litellm/llms/openai/chat/guardrail_translation/handler.py @@ -259,9 +259,9 @@ class OpenAIChatCompletionsHandler(BaseTranslation): elif isinstance(content, list) and content_idx_optional is not None: # Replace specific text item in list content - messages[msg_idx]["content"][content_idx_optional][ - "text" - ] = guardrail_response + messages[msg_idx]["content"][content_idx_optional]["text"] = ( + guardrail_response + ) async def _apply_guardrail_responses_to_input_tool_calls( self, @@ -746,7 +746,9 @@ class OpenAIChatCompletionsHandler(BaseTranslation): elif isinstance(content, list) and content_idx_optional is not None: # Replace specific text item in list content - choice.message.content[content_idx_optional]["text"] = guardrail_response # type: ignore + choice.message.content[content_idx_optional]["text"] = ( + guardrail_response # type: ignore + ) async def _apply_guardrail_responses_to_output_tool_calls( self, diff --git a/litellm/llms/openai/completion/handler.py b/litellm/llms/openai/completion/handler.py index 63d39151254..f08ef844bb3 100644 --- a/litellm/llms/openai/completion/handler.py +++ b/litellm/llms/openai/completion/handler.py @@ -96,7 +96,19 @@ class OpenAITextCompletion(BaseLLM): organization=organization, ) else: - return self.acompletion(api_base=api_base, data=data, headers=headers, model_response=model_response, api_key=api_key, logging_obj=logging_obj, model=model, timeout=timeout, max_retries=max_retries, organization=organization, client=client) # type: ignore + return self.acompletion( + api_base=api_base, + data=data, + headers=headers, + model_response=model_response, + api_key=api_key, + logging_obj=logging_obj, + model=model, + timeout=timeout, + max_retries=max_retries, + organization=organization, + client=client, + ) # type: ignore elif optional_params.get("stream", False): return self.streaming( logging_obj=logging_obj, @@ -124,7 +136,9 @@ class OpenAITextCompletion(BaseLLM): else: openai_client = client - raw_response = openai_client.completions.with_raw_response.create(**data) # type: ignore + raw_response = openai_client.completions.with_raw_response.create( + **data + ) # type: ignore response = raw_response.parse() response_json = response.model_dump() diff --git a/litellm/llms/openai/image_variations/handler.py b/litellm/llms/openai/image_variations/handler.py index 8b96fb6ef7a..dae3fa9d457 100644 --- a/litellm/llms/openai/image_variations/handler.py +++ b/litellm/llms/openai/image_variations/handler.py @@ -73,7 +73,9 @@ class OpenAIImageVariationsHandler: client=client, init_client_params=init_client_params ) - raw_response = await client.images.with_raw_response.create_variation(**data) # type: ignore + raw_response = await client.images.with_raw_response.create_variation( + **data + ) # type: ignore response = raw_response.parse() response_json = response.model_dump() diff --git a/litellm/llms/openai/openai.py b/litellm/llms/openai/openai.py index ea905d8ebca..59acbac6e15 100644 --- a/litellm/llms/openai/openai.py +++ b/litellm/llms/openai/openai.py @@ -1132,9 +1132,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): data = drop_params_from_unprocessable_entity_error(e, data) else: raise e - except ( - Exception - ) as e: # need to exception handle here. async exceptions don't get caught in sync functions. + except Exception as e: # need to exception handle here. async exceptions don't get caught in sync functions. if isinstance(e, OpenAIError): raise e @@ -1433,7 +1431,11 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): additional_args={"complete_input_dict": data}, original_response=stringified_response, ) - return convert_to_model_response_object(response_object=stringified_response, model_response_object=model_response, response_type="image_generation") # type: ignore + return convert_to_model_response_object( + response_object=stringified_response, + model_response_object=model_response, + response_type="image_generation", + ) # type: ignore except Exception as e: ## LOGGING logging_obj.post_call( @@ -1466,7 +1468,19 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): raise OpenAIError(status_code=422, message="max retries must be an int") if aimg_generation is True: - return self.aimage_generation(data=data, prompt=prompt, logging_obj=logging_obj, model_response=model_response, api_base=api_base, api_key=api_key, timeout=timeout, client=client, max_retries=max_retries, organization=organization, headers=headers) # type: ignore + return self.aimage_generation( + data=data, + prompt=prompt, + logging_obj=logging_obj, + model_response=model_response, + api_base=api_base, + api_key=api_key, + timeout=timeout, + client=client, + max_retries=max_retries, + organization=organization, + headers=headers, + ) # type: ignore openai_client: OpenAI = self._get_openai_client( # type: ignore is_async=False, @@ -1503,7 +1517,11 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): additional_args={"complete_input_dict": data}, original_response=response, ) - return convert_to_model_response_object(response_object=response, model_response_object=model_response, response_type="image_generation") # type: ignore + return convert_to_model_response_object( + response_object=response, + model_response_object=model_response, + response_type="image_generation", + ) # type: ignore except OpenAIError as e: ## LOGGING logging_obj.post_call( @@ -2517,8 +2535,11 @@ class OpenAIAssistantsAPI(BaseLLM): client=client, ) - thread_message: OpenAIMessage = await openai_client.beta.threads.messages.create( # type: ignore - thread_id, **message_data # type: ignore + thread_message: OpenAIMessage = ( + await openai_client.beta.threads.messages.create( # type: ignore + thread_id, + **message_data, # type: ignore + ) ) response_obj: Optional[OpenAIMessage] = None @@ -2596,7 +2617,8 @@ class OpenAIAssistantsAPI(BaseLLM): ) thread_message: OpenAIMessage = openai_client.beta.threads.messages.create( # type: ignore - thread_id, **message_data # type: ignore + thread_id, + **message_data, # type: ignore ) response_obj: Optional[OpenAIMessage] = None diff --git a/litellm/llms/openai/responses/guardrail_translation/handler.py b/litellm/llms/openai/responses/guardrail_translation/handler.py index b5319797cc6..83ec69a9d7a 100644 --- a/litellm/llms/openai/responses/guardrail_translation/handler.py +++ b/litellm/llms/openai/responses/guardrail_translation/handler.py @@ -350,9 +350,9 @@ class OpenAIResponsesHandler(BaseTranslation): elif isinstance(content, list) and content_idx_optional is not None: # Replace specific text item in list content if isinstance(messages[msg_idx]["content"][content_idx_optional], dict): - messages[msg_idx]["content"][content_idx_optional][ - "text" - ] = guardrail_response + messages[msg_idx]["content"][content_idx_optional]["text"] = ( + guardrail_response + ) async def process_output_response( self, diff --git a/litellm/llms/openai/transcriptions/handler.py b/litellm/llms/openai/transcriptions/handler.py index e079a170874..44fb5da8590 100644 --- a/litellm/llms/openai/transcriptions/handler.py +++ b/litellm/llms/openai/transcriptions/handler.py @@ -71,7 +71,9 @@ class OpenAIAudioTranscription(OpenAIChatCompletion): response = raw_response.parse() return headers, response else: - response = openai_client.audio.transcriptions.create(**data, timeout=timeout) # type: ignore + response = openai_client.audio.transcriptions.create( + **data, timeout=timeout + ) # type: ignore return None, response except Exception as e: raise e @@ -160,7 +162,12 @@ class OpenAIAudioTranscription(OpenAIChatCompletion): original_response=stringified_response, ) hidden_params = {"model": model, "custom_llm_provider": "openai"} - final_response: TranscriptionResponse = convert_to_model_response_object(response_object=stringified_response, model_response_object=model_response, hidden_params=hidden_params, response_type="audio_transcription") # type: ignore + final_response: TranscriptionResponse = convert_to_model_response_object( + response_object=stringified_response, + model_response_object=model_response, + hidden_params=hidden_params, + response_type="audio_transcription", + ) # type: ignore return final_response async def async_audio_transcriptions( @@ -220,7 +227,12 @@ class OpenAIAudioTranscription(OpenAIChatCompletion): actual_model = data.get("model", "whisper-1") hidden_params = {"model": actual_model, "custom_llm_provider": "openai"} - return convert_to_model_response_object(response_object=stringified_response, model_response_object=model_response, hidden_params=hidden_params, response_type="audio_transcription") # type: ignore + return convert_to_model_response_object( + response_object=stringified_response, + model_response_object=model_response, + hidden_params=hidden_params, + response_type="audio_transcription", + ) # type: ignore except Exception as e: ## LOGGING logging_obj.post_call( diff --git a/litellm/llms/openai_like/embedding/handler.py b/litellm/llms/openai_like/embedding/handler.py index e3884fa56d7..285595d2791 100644 --- a/litellm/llms/openai_like/embedding/handler.py +++ b/litellm/llms/openai_like/embedding/handler.py @@ -118,7 +118,17 @@ class OpenAILikeEmbeddingHandler(OpenAILikeBase): ) if aembedding is True: - return self.aembedding(data=data, input=input, logging_obj=logging_obj, model_response=model_response, api_base=api_base, api_key=api_key, timeout=timeout, client=client, headers=headers) # type: ignore + return self.aembedding( + data=data, + input=input, + logging_obj=logging_obj, + model_response=model_response, + api_base=api_base, + api_key=api_key, + timeout=timeout, + client=client, + headers=headers, + ) # type: ignore if client is None or isinstance(client, AsyncHTTPHandler): self.client = HTTPHandler(timeout=timeout) # type: ignore else: diff --git a/litellm/llms/perplexity/chat/transformation.py b/litellm/llms/perplexity/chat/transformation.py index 48299529ff4..cc0738697d1 100644 --- a/litellm/llms/perplexity/chat/transformation.py +++ b/litellm/llms/perplexity/chat/transformation.py @@ -25,7 +25,11 @@ class PerplexityChatConfig(OpenAIGPTConfig): def _get_openai_compatible_provider_info( self, api_base: Optional[str], api_key: Optional[str] ) -> Tuple[Optional[str], Optional[str]]: - api_base = api_base or get_secret_str("PERPLEXITY_API_BASE") or "https://api.perplexity.ai" # type: ignore + api_base = ( + api_base + or get_secret_str("PERPLEXITY_API_BASE") + or "https://api.perplexity.ai" + ) # type: ignore dynamic_api_key = ( api_key or get_secret_str("PERPLEXITYAI_API_KEY") diff --git a/litellm/llms/replicate/chat/handler.py b/litellm/llms/replicate/chat/handler.py index cc4c61e397b..a2eddb65a54 100644 --- a/litellm/llms/replicate/chat/handler.py +++ b/litellm/llms/replicate/chat/handler.py @@ -214,7 +214,9 @@ def completion( headers=headers, http_client=httpx_client, ) - return CustomStreamWrapper(_response, model, logging_obj=logging_obj, custom_llm_provider="replicate") # type: ignore + return CustomStreamWrapper( + _response, model, logging_obj=logging_obj, custom_llm_provider="replicate" + ) # type: ignore else: for retry in range(litellm.DEFAULT_REPLICATE_POLLING_RETRIES): time.sleep( @@ -285,7 +287,9 @@ async def async_completion( headers=headers, http_client=async_handler, ) - return CustomStreamWrapper(_response, model, logging_obj=logging_obj, custom_llm_provider="replicate") # type: ignore + return CustomStreamWrapper( + _response, model, logging_obj=logging_obj, custom_llm_provider="replicate" + ) # type: ignore for retry in range(litellm.DEFAULT_REPLICATE_POLLING_RETRIES): await asyncio.sleep( diff --git a/litellm/llms/sap/chat/transformation.py b/litellm/llms/sap/chat/transformation.py index db8c26b7d96..9899e3be9ad 100755 --- a/litellm/llms/sap/chat/transformation.py +++ b/litellm/llms/sap/chat/transformation.py @@ -149,7 +149,9 @@ class GenAIHubOrchestrationConfig(OpenAIGPTConfig): def run_env_setup(self, service_key: Optional[str] = None) -> None: try: - self.token_creator, self._base_url, self._resource_group = get_token_creator(service_key) # type: ignore + self.token_creator, self._base_url, self._resource_group = ( + get_token_creator(service_key) + ) # type: ignore except ValueError as err: raise GenAIHubOrchestrationError(status_code=400, message=err.args[0]) @@ -189,7 +191,7 @@ class GenAIHubOrchestrationConfig(OpenAIGPTConfig): for dep in deployments.get("resources", []): if dep.get("scenarioId") == "orchestration": cfg = client.get( - f'{self.base_url}/lm/configurations/{dep["configurationId"]}', + f"{self.base_url}/lm/configurations/{dep['configurationId']}", headers=self.headers, ).json() if cfg.get("executableId") == "orchestration": diff --git a/litellm/llms/sap/credentials.py b/litellm/llms/sap/credentials.py index dd307ddf496..8cb19f195f2 100644 --- a/litellm/llms/sap/credentials.py +++ b/litellm/llms/sap/credentials.py @@ -102,20 +102,25 @@ CREDENTIAL_VALUES: Final[List[CredentialsValue]] = [ CredentialsValue( "auth_url", ("url",), - transform_fn=lambda url: url.rstrip("/") - + ("" if url.endswith(AUTH_ENDPOINT_SUFFIX) else AUTH_ENDPOINT_SUFFIX), + transform_fn=lambda url: ( + url.rstrip("/") + + ("" if url.endswith(AUTH_ENDPOINT_SUFFIX) else AUTH_ENDPOINT_SUFFIX) + ), ), CredentialsValue( "base_url", ("serviceurls", "AI_API_URL"), - transform_fn=lambda url: url.rstrip("/") - + ("" if url.endswith("/v2") else "/v2"), + transform_fn=lambda url: ( + url.rstrip("/") + ("" if url.endswith("/v2") else "/v2") + ), ), CredentialsValue( "cert_url", ("certurl",), - transform_fn=lambda url: url.rstrip("/") - + ("" if url.endswith(AUTH_ENDPOINT_SUFFIX) else AUTH_ENDPOINT_SUFFIX), + transform_fn=lambda url: ( + url.rstrip("/") + + ("" if url.endswith(AUTH_ENDPOINT_SUFFIX) else AUTH_ENDPOINT_SUFFIX) + ), ), # file paths (kept for config compatibility) CredentialsValue("cert_file_path"), diff --git a/litellm/llms/sap/embed/transformation.py b/litellm/llms/sap/embed/transformation.py index c74f21c3685..4344c2cc545 100644 --- a/litellm/llms/sap/embed/transformation.py +++ b/litellm/llms/sap/embed/transformation.py @@ -109,7 +109,7 @@ class GenAIHubEmbeddingConfig(BaseEmbeddingConfig): if deployment["scenarioId"] == "orchestration": config_details = client.get( self.base_url - + f'/lm/configurations/{deployment["configurationId"]}', + + f"/lm/configurations/{deployment['configurationId']}", headers=self.headers, ).json() if config_details["executableId"] == "orchestration": diff --git a/litellm/llms/stability/image_edit/transformations.py b/litellm/llms/stability/image_edit/transformations.py index 522858b8c2a..9c325c3cdda 100644 --- a/litellm/llms/stability/image_edit/transformations.py +++ b/litellm/llms/stability/image_edit/transformations.py @@ -80,7 +80,9 @@ class StabilityImageEditConfig(BaseImageEditConfig): if k in param_mapping: # Map param if mapping exists and value is valid if k == "size" and v in OPENAI_SIZE_TO_STABILITY_ASPECT_RATIO: - mapped_params[param_mapping[k]] = OPENAI_SIZE_TO_STABILITY_ASPECT_RATIO[v] # type: ignore + mapped_params[param_mapping[k]] = ( + OPENAI_SIZE_TO_STABILITY_ASPECT_RATIO[v] + ) # type: ignore # Don't copy "size" itself to final dict elif k == "n": # Store for logic but do not add to outgoing params diff --git a/litellm/llms/tinyfish/search/transformation.py b/litellm/llms/tinyfish/search/transformation.py index b92f7ca1aff..4a95f519646 100644 --- a/litellm/llms/tinyfish/search/transformation.py +++ b/litellm/llms/tinyfish/search/transformation.py @@ -149,10 +149,8 @@ class TinyfishSearchConfig(BaseSearchConfig): max_results_str: str = "20" if raw_response.request: - raw_param: object = ( - raw_response.request.url.params.get( # any-ok: httpx QueryParams.get() -> Any - "max_results", "20" - ) + raw_param: object = raw_response.request.url.params.get( # any-ok: httpx QueryParams.get() -> Any + "max_results", "20" ) max_results_str = str(raw_param) max_results: int = min(int(max_results_str), 20) diff --git a/litellm/llms/vertex_ai/batches/handler.py b/litellm/llms/vertex_ai/batches/handler.py index c627599da8d..00222faf274 100644 --- a/litellm/llms/vertex_ai/batches/handler.py +++ b/litellm/llms/vertex_ai/batches/handler.py @@ -78,10 +78,8 @@ class VertexAIBatchPrediction(VertexLLM): "Authorization": f"Bearer {access_token}", } - vertex_batch_request: VertexAIBatchPredictionJob = ( - VertexAIBatchTransformation.transform_openai_batch_request_to_vertex_ai_batch_request( - request=create_batch_data - ) + vertex_batch_request: VertexAIBatchPredictionJob = VertexAIBatchTransformation.transform_openai_batch_request_to_vertex_ai_batch_request( + request=create_batch_data ) if _is_async is True: diff --git a/litellm/llms/vertex_ai/common_utils.py b/litellm/llms/vertex_ai/common_utils.py index 5028c0cf5c8..96f016da94d 100644 --- a/litellm/llms/vertex_ai/common_utils.py +++ b/litellm/llms/vertex_ai/common_utils.py @@ -779,7 +779,8 @@ def filter_schema_fields( result[key] = filter_schema_fields(value, valid_fields, processed) elif key == "anyOf" and isinstance(value, list): result[key] = [ - filter_schema_fields(item, valid_fields, processed) for item in value # type: ignore + filter_schema_fields(item, valid_fields, processed) + for item in value # type: ignore ] else: result[key] = value diff --git a/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py b/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py index 103801a1e8d..d29734c0294 100644 --- a/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py +++ b/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py @@ -415,7 +415,9 @@ class ContextCachingEndpoints(VertexBase): try: response = client.post( - url=url, headers=headers, json=cached_content_request_body # type: ignore + url=url, + headers=headers, + json=cached_content_request_body, # type: ignore ) response.raise_for_status() except httpx.HTTPStatusError as err: @@ -566,7 +568,9 @@ class ContextCachingEndpoints(VertexBase): try: response = await client.post( - url=url, headers=headers, json=cached_content_request_body # type: ignore + url=url, + headers=headers, + json=cached_content_request_body, # type: ignore ) response.raise_for_status() except httpx.HTTPStatusError as err: diff --git a/litellm/llms/vertex_ai/cost_calculator.py b/litellm/llms/vertex_ai/cost_calculator.py index 9fa57f6bf96..758fc0bae87 100644 --- a/litellm/llms/vertex_ai/cost_calculator.py +++ b/litellm/llms/vertex_ai/cost_calculator.py @@ -105,8 +105,10 @@ def cost_per_character( "input_cost_per_character_above_128k_tokens" in model_info and model_info["input_cost_per_character_above_128k_tokens"] is not None - ), "model info for model={} does not have 'input_cost_per_character_above_128k_tokens'-pricing for > 128k tokens\nmodel_info={}".format( - model, model_info + ), ( + "model info for model={} does not have 'input_cost_per_character_above_128k_tokens'-pricing for > 128k tokens\nmodel_info={}".format( + model, model_info + ) ) prompt_cost = ( prompt_characters @@ -116,8 +118,10 @@ def cost_per_character( assert ( "input_cost_per_character" in model_info and model_info["input_cost_per_character"] is not None - ), "model info for model={} does not have 'input_cost_per_character'-pricing\nmodel_info={}".format( - model, model_info + ), ( + "model info for model={} does not have 'input_cost_per_character'-pricing\nmodel_info={}".format( + model, model_info + ) ) prompt_cost = prompt_characters * model_info["input_cost_per_character"] except Exception as e: @@ -150,8 +154,10 @@ def cost_per_character( "output_cost_per_character_above_128k_tokens" in model_info and model_info["output_cost_per_character_above_128k_tokens"] is not None - ), "model info for model={} does not have 'output_cost_per_character_above_128k_tokens' pricing\nmodel_info={}".format( - model, model_info + ), ( + "model info for model={} does not have 'output_cost_per_character_above_128k_tokens' pricing\nmodel_info={}".format( + model, model_info + ) ) completion_cost = ( completion_tokens @@ -161,8 +167,10 @@ def cost_per_character( assert ( "output_cost_per_character" in model_info and model_info["output_cost_per_character"] is not None - ), "model info for model={} does not have 'output_cost_per_character'-pricing\nmodel_info={}".format( - model, model_info + ), ( + "model info for model={} does not have 'output_cost_per_character'-pricing\nmodel_info={}".format( + model, model_info + ) ) completion_cost = ( completion_characters * model_info["output_cost_per_character"] diff --git a/litellm/llms/vertex_ai/gemini/transformation.py b/litellm/llms/vertex_ai/gemini/transformation.py index f5a2b268263..79f006a83de 100644 --- a/litellm/llms/vertex_ai/gemini/transformation.py +++ b/litellm/llms/vertex_ai/gemini/transformation.py @@ -881,7 +881,9 @@ def _gemini_convert_messages_with_history( ## MERGE CONSECUTIVE ASSISTANT CONTENT ## while msg_i < len(messages) and messages[msg_i]["role"] == "assistant": if isinstance(messages[msg_i], BaseModel): - msg_dict: Union[ChatCompletionAssistantMessage, dict] = messages[msg_i].model_dump() # type: ignore + msg_dict: Union[ChatCompletionAssistantMessage, dict] = messages[ + msg_i + ].model_dump() # type: ignore else: msg_dict = messages[msg_i] # type: ignore assistant_msg = ChatCompletionAssistantMessage(**msg_dict) # type: ignore @@ -945,7 +947,12 @@ def _gemini_convert_messages_with_history( and len(thought_signatures) > 0 ): # Use the first signature for the text part (Gemini expects one signature per part) - assistant_content.append(PartType(text=assistant_text, thoughtSignature=thought_signatures[0])) # type: ignore + assistant_content.append( + PartType( + text=assistant_text, + thoughtSignature=thought_signatures[0], + ) + ) # type: ignore else: assistant_content.append(PartType(text=assistant_text)) # type: ignore @@ -1201,7 +1208,8 @@ def _transform_request_body( ) if supports_response_schema is False: user_response_schema_message = response_schema_prompt( - model=model, response_schema=optional_params.get("response_schema") # type: ignore + model=model, + response_schema=optional_params.get("response_schema"), # type: ignore ) messages.append({"role": "user", "content": user_response_schema_message}) optional_params.pop("response_schema") diff --git a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py index c171538b9c0..0de34ec257c 100644 --- a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py +++ b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py @@ -823,9 +823,9 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): if google_maps_retrieval_config is not None: if "toolConfig" not in optional_params: optional_params["toolConfig"] = {} - optional_params["toolConfig"][ - "retrievalConfig" - ] = google_maps_retrieval_config + optional_params["toolConfig"]["retrievalConfig"] = ( + google_maps_retrieval_config + ) return _tools_list @@ -1271,7 +1271,8 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): isinstance(value, str) or isinstance(value, dict) ): _tool_choice_value = self.map_tool_choice_values( - model=model, tool_choice=value # type: ignore + model=model, + tool_choice=value, # type: ignore ) if _tool_choice_value is not None: optional_params["tool_choice"] = _tool_choice_value @@ -2195,7 +2196,9 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): from litellm.types.utils import Delta, StreamingChoices annotations = chat_completion_message.get("annotations") # type: ignore - provider_specific_fields = chat_completion_message.get("provider_specific_fields") # type: ignore + provider_specific_fields = chat_completion_message.get( + "provider_specific_fields" + ) # type: ignore # create a streaming choice object choice = StreamingChoices( finish_reason=VertexGeminiConfig._check_finish_reason( @@ -2470,15 +2473,15 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): ) if audio_response is not None: - cast(Dict[str, Any], chat_completion_message)[ - "audio" - ] = audio_response + cast(Dict[str, Any], chat_completion_message)["audio"] = ( + audio_response + ) chat_completion_message["content"] = None # OpenAI spec if image_response is not None: # Handle image response - combine with text content into structured format - cast(Dict[str, Any], chat_completion_message)[ - "images" - ] = image_response + cast(Dict[str, Any], chat_completion_message)["images"] = ( + image_response + ) if content is not None: chat_completion_message["content"] = content @@ -2538,13 +2541,17 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): if thought_signatures is not None: if "provider_specific_fields" not in chat_completion_message: chat_completion_message["provider_specific_fields"] = {} - chat_completion_message["provider_specific_fields"]["thought_signatures"] = thought_signatures # type: ignore + chat_completion_message["provider_specific_fields"][ + "thought_signatures" + ] = thought_signatures # type: ignore # Store server-side tool invocations in provider_specific_fields if server_side_tool_invocations is not None: if "provider_specific_fields" not in chat_completion_message: chat_completion_message["provider_specific_fields"] = {} - chat_completion_message["provider_specific_fields"]["server_side_tool_invocations"] = server_side_tool_invocations # type: ignore + chat_completion_message["provider_specific_fields"][ + "server_side_tool_invocations" + ] = server_side_tool_invocations # type: ignore if isinstance(model_response, ModelResponseStream): choice = VertexGeminiConfig._create_streaming_choice( @@ -3313,7 +3320,9 @@ class VertexLLM(VertexBase): client = client try: - response = client.post(url=url, headers=headers, json=data, logging_obj=logging_obj) # type: ignore + response = client.post( + url=url, headers=headers, json=data, logging_obj=logging_obj + ) # type: ignore response.raise_for_status() except httpx.HTTPStatusError as err: error_code = err.response.status_code diff --git a/litellm/llms/vertex_ai/vertex_embeddings/embedding_handler.py b/litellm/llms/vertex_ai/vertex_embeddings/embedding_handler.py index 696341598e5..729cc9c3ead 100644 --- a/litellm/llms/vertex_ai/vertex_embeddings/embedding_handler.py +++ b/litellm/llms/vertex_ai/vertex_embeddings/embedding_handler.py @@ -92,13 +92,11 @@ class VertexEmbedding(VertexBase): use_psc_endpoint_format=use_psc_endpoint_format, ) headers = self.set_headers(auth_header=auth_header, extra_headers=extra_headers) - vertex_request: VertexEmbeddingRequest = ( - litellm.vertexAITextEmbeddingConfig.transform_openai_request_to_vertex_embedding_request( - input=input, - optional_params=optional_params, - model=model, - litellm_params=litellm_params, - ) + vertex_request: VertexEmbeddingRequest = litellm.vertexAITextEmbeddingConfig.transform_openai_request_to_vertex_embedding_request( + input=input, + optional_params=optional_params, + model=model, + litellm_params=litellm_params, ) _client_params = {} @@ -192,13 +190,11 @@ class VertexEmbedding(VertexBase): use_psc_endpoint_format=use_psc_endpoint_format, ) headers = self.set_headers(auth_header=auth_header, extra_headers=extra_headers) - vertex_request: VertexEmbeddingRequest = ( - litellm.vertexAITextEmbeddingConfig.transform_openai_request_to_vertex_embedding_request( - input=input, - optional_params=optional_params, - model=model, - litellm_params=litellm_params, - ) + vertex_request: VertexEmbeddingRequest = litellm.vertexAITextEmbeddingConfig.transform_openai_request_to_vertex_embedding_request( + input=input, + optional_params=optional_params, + model=model, + litellm_params=litellm_params, ) _async_client_params = {} diff --git a/litellm/llms/vertex_ai/vertex_llm_base.py b/litellm/llms/vertex_ai/vertex_llm_base.py index 990063bb9fb..18a9c98c315 100644 --- a/litellm/llms/vertex_ai/vertex_llm_base.py +++ b/litellm/llms/vertex_ai/vertex_llm_base.py @@ -179,9 +179,7 @@ class VertexBase: scopes=["https://www.googleapis.com/auth/cloud-platform"], ) if project_id is None: - project_id = ( - creds.quota_project_id - ) # authorized user credentials don't have a project_id, only quota_project_id + project_id = creds.quota_project_id # authorized user credentials don't have a project_id, only quota_project_id else: creds = self._credentials_from_service_account( json_obj, @@ -838,12 +836,13 @@ class VertexBase: self._credentials_project_mapping.pop(credential_cache_key, None) try: - _credentials, credential_project_id = ( - await self._load_and_cache_credentials( - credentials=credentials, - project_id=project_id, - credential_cache_key=credential_cache_key, - ) + ( + _credentials, + credential_project_id, + ) = await self._load_and_cache_credentials( + credentials=credentials, + project_id=project_id, + credential_cache_key=credential_cache_key, ) if project_id is None and isinstance(credential_project_id, str): project_id = credential_project_id @@ -1068,10 +1067,11 @@ class VertexBase: # Load credentials if not cached if _credentials is None: - _credentials, credential_project_id = ( - await self._load_and_cache_credentials( - credentials, project_id, credential_cache_key - ) + ( + _credentials, + credential_project_id, + ) = await self._load_and_cache_credentials( + credentials, project_id, credential_cache_key ) # Resolve project_id from credentials if not provided diff --git a/litellm/llms/volcengine/chat/transformation.py b/litellm/llms/volcengine/chat/transformation.py index 7395f9ce75b..d60f54615fa 100644 --- a/litellm/llms/volcengine/chat/transformation.py +++ b/litellm/llms/volcengine/chat/transformation.py @@ -100,9 +100,9 @@ class VolcEngineChatConfig(OpenAILikeChatConfig): in ["enabled", "disabled", "auto"] # legal values, see docs ): # Add thinking parameter to extra_body for all legal cases - optional_params.setdefault("extra_body", {})[ - "thinking" - ] = thinking_value + optional_params.setdefault("extra_body", {})["thinking"] = ( + thinking_value + ) else: # Skip adding thinking parameter when it's not set or has invalid value pass diff --git a/litellm/llms/watsonx/common_utils.py b/litellm/llms/watsonx/common_utils.py index 230c9f4cf6e..2aead929c8d 100644 --- a/litellm/llms/watsonx/common_utils.py +++ b/litellm/llms/watsonx/common_utils.py @@ -372,9 +372,7 @@ class IBMWatsonXMixin: def _prepare_payload(self, model: str, api_params: WatsonXAPIParams) -> dict: payload: dict = {} if model.startswith("deployment/"): - return ( - {} - ) # Deployment models do not support 'space_id' or 'project_id' in their payload + return {} # Deployment models do not support 'space_id' or 'project_id' in their payload payload["model_id"] = model if api_params["project_id"] is not None: payload["project_id"] = api_params["project_id"] diff --git a/litellm/llms/watsonx/completion/transformation.py b/litellm/llms/watsonx/completion/transformation.py index 7180e12162a..8f418567371 100644 --- a/litellm/llms/watsonx/completion/transformation.py +++ b/litellm/llms/watsonx/completion/transformation.py @@ -327,7 +327,7 @@ class IBMWatsonXAIConfig(IBMWatsonXMixin, BaseConfig): except ValueError: # datetime.fromisoformat cannot handle 'Z' in Python 3.10 created_datetime = datetime.fromisoformat( - f'{json_resp["created_at"].rstrip("Z")}+00:00' + f"{json_resp['created_at'].rstrip('Z')}+00:00" ) model_response.created = int(created_datetime.timestamp()) else: diff --git a/litellm/llms/xai/chat/transformation.py b/litellm/llms/xai/chat/transformation.py index 8019bb67991..87b5757ef35 100644 --- a/litellm/llms/xai/chat/transformation.py +++ b/litellm/llms/xai/chat/transformation.py @@ -28,7 +28,6 @@ from ...openai.chat.gpt_transformation import ( class XAIChatConfig(OpenAIGPTConfig): - @property def custom_llm_provider(self) -> Optional[str]: return "xai" diff --git a/litellm/main.py b/litellm/main.py index c3d7ca28c49..1960c456f80 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -5448,8 +5448,9 @@ def completion( # type: ignore provider_config=provider_config, ) - if litellm.add_function_to_prompt and optional_params.get( - "functions_unsupported_model", None + if ( + litellm.add_function_to_prompt + and optional_params.get("functions_unsupported_model", None) ): # if user opts to add it to prompt, when API doesn't support function calling functions_unsupported_model = optional_params.pop( "functions_unsupported_model" @@ -7584,8 +7585,8 @@ def text_completion( kwargs.pop("prompt", None) - if _model is not None and ( - custom_llm_provider == "openai" + if ( + _model is not None and (custom_llm_provider == "openai") ): # for openai compatible endpoints - e.g. vllm, call the native /v1/completions endpoint for text completion calls if _model not in litellm.open_ai_chat_completion_models: model = "text-completion-openai/" + _model @@ -7656,7 +7657,9 @@ async def aadapter_completion( new_kwargs = translation_obj.translate_completion_input_params(kwargs=kwargs) - response: Union[ModelResponse, CustomStreamWrapper] = await acompletion(**new_kwargs) # type: ignore + response: Union[ModelResponse, CustomStreamWrapper] = await acompletion( + **new_kwargs + ) # type: ignore translated_response: Optional[ Union[BaseModel, AdapterCompletionStreamWrapper] ] = None @@ -8062,7 +8065,12 @@ def transcription( ) # set API KEY - api_key = api_key or litellm.api_key or litellm.openai_key or get_secret("OPENAI_API_KEY") # type: ignore + api_key = ( + api_key + or litellm.api_key + or litellm.openai_key + or get_secret("OPENAI_API_KEY") + ) # type: ignore response = openai_audio_transcriptions.audio_transcriptions( model=model, audio_file=file, @@ -8403,7 +8411,9 @@ def speech( ) api_base = api_base or litellm.api_base or get_secret("AZURE_API_BASE") # type: ignore - api_version = api_version or litellm.api_version or get_secret("AZURE_API_VERSION") # type: ignore + api_version = ( + api_version or litellm.api_version or get_secret("AZURE_API_VERSION") + ) # type: ignore api_key = ( api_key @@ -8415,9 +8425,7 @@ def speech( azure_ad_token: Optional[str] = optional_params.get("extra_body", {}).pop( # type: ignore "azure_ad_token", None - ) or get_secret( - "AZURE_AD_TOKEN" - ) + ) or get_secret("AZURE_AD_TOKEN") azure_ad_token_provider = kwargs.get("azure_ad_token_provider", None) if extra_headers: @@ -8874,9 +8882,7 @@ def stream_chunk_builder_text_completion( response["usage"]["prompt_tokens"] = token_counter( model=model, messages=messages ) - except ( - Exception - ): # don't allow this failing to block a complete streaming response from being returned + except Exception: # don't allow this failing to block a complete streaming response from being returned print_verbose("token_counter failed, assuming prompt tokens is 0") response["usage"]["prompt_tokens"] = 0 response["usage"]["completion_tokens"] = token_counter( diff --git a/litellm/passthrough/main.py b/litellm/passthrough/main.py index 3e60988b9e7..b1d4864cea7 100644 --- a/litellm/passthrough/main.py +++ b/litellm/passthrough/main.py @@ -345,7 +345,9 @@ def llm_passthrough_route( ) else: # Sync path - client.client.send returns Response directly - response: httpx.Response = client.client.send(request=request, stream=is_streaming_request) # type: ignore + response: httpx.Response = client.client.send( + request=request, stream=is_streaming_request + ) # type: ignore response.raise_for_status() if ( diff --git a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py index 90108de25c3..19f508e6af9 100644 --- a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py +++ b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py @@ -521,9 +521,9 @@ class MCPRequestHandler: if server_alias not in server_auth_headers: server_auth_headers[server_alias] = {} - server_auth_headers[server_alias][ - auth_header_name - ] = header_value + server_auth_headers[server_alias][auth_header_name] = ( + header_value + ) verbose_logger.debug( f"Found server auth header: {server_alias} -> {auth_header_name}: {header_value[:10]}..." ) @@ -1383,9 +1383,9 @@ class MCPRequestHandler: cache_key = f"agent_object_permission_id:{agent_id}" try: - object_permission_id: Optional[str] = ( - await user_api_key_cache.async_get_cache(key=cache_key) - ) + object_permission_id: Optional[ + str + ] = await user_api_key_cache.async_get_cache(key=cache_key) if object_permission_id == MCPRequestHandler._AGENT_NO_PERMISSION_SENTINEL: return None diff --git a/litellm/proxy/_experimental/mcp_server/db.py b/litellm/proxy/_experimental/mcp_server/db.py index 8edb831a9df..bc1068d77d0 100644 --- a/litellm/proxy/_experimental/mcp_server/db.py +++ b/litellm/proxy/_experimental/mcp_server/db.py @@ -695,7 +695,8 @@ async def update_mcp_server( data_dict["updated_by"] = touched_by updated_mcp_server = await MCPServerRepository(prisma_client).table.update( - where={"server_id": data.server_id}, data=data_dict # type: ignore + where={"server_id": data.server_id}, + data=data_dict, # type: ignore ) _decrypt_env_vars_on_returned_row(updated_mcp_server) diff --git a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py index 8606a18cac1..b9e0379e445 100644 --- a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py +++ b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py @@ -3701,7 +3701,7 @@ class MCPServerManager: return stored_headers except Exception as _lookup_exc: verbose_logger.debug( - "call_tool: per-user token lookup failed for " "user=%s server=%s: %s", + "call_tool: per-user token lookup failed for user=%s server=%s: %s", user_id, mcp_server.server_id, _lookup_exc, diff --git a/litellm/proxy/_experimental/mcp_server/server.py b/litellm/proxy/_experimental/mcp_server/server.py index 1ab260b5f91..d7975303802 100644 --- a/litellm/proxy/_experimental/mcp_server/server.py +++ b/litellm/proxy/_experimental/mcp_server/server.py @@ -138,9 +138,7 @@ try: import weakref # Robust auth lookup keyed by session_object. - _session_obj_auth_storage: ( - "weakref.WeakKeyDictionary[Any, MCPAuthenticatedUser]" - ) = weakref.WeakKeyDictionary() + _session_obj_auth_storage: "weakref.WeakKeyDictionary[Any, MCPAuthenticatedUser]" = weakref.WeakKeyDictionary() active_mcp_session_var: contextvars.ContextVar[Optional[_McpServerSession]] = ( contextvars.ContextVar("active_mcp_session", default=None) @@ -518,7 +516,12 @@ if MCP_AVAILABLE: async def initialize_session_managers(): """Initialize the session managers. Can be called from main app lifespan.""" - global _SESSION_MANAGERS_INITIALIZED, _session_manager_cm, _session_manager_stateful_cm, _sse_session_manager_cm, _stateful_auth_context_cleanup_task + global \ + _SESSION_MANAGERS_INITIALIZED, \ + _session_manager_cm, \ + _session_manager_stateful_cm, \ + _sse_session_manager_cm, \ + _stateful_auth_context_cleanup_task # Use async lock to prevent concurrent initialization async with _INITIALIZATION_LOCK: @@ -547,7 +550,12 @@ if MCP_AVAILABLE: async def shutdown_session_managers(): """Shutdown the session managers.""" - global _SESSION_MANAGERS_INITIALIZED, _session_manager_cm, _session_manager_stateful_cm, _sse_session_manager_cm, _stateful_auth_context_cleanup_task + global \ + _SESSION_MANAGERS_INITIALIZED, \ + _session_manager_cm, \ + _session_manager_stateful_cm, \ + _sse_session_manager_cm, \ + _stateful_auth_context_cleanup_task if _SESSION_MANAGERS_INITIALIZED: verbose_logger.info("Shutting down MCP session managers...") diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index adbae326433..7db0156bbe0 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -1052,9 +1052,9 @@ class GenerateRequestBase(LiteLLMPydanticObjectBase): allowed_cache_controls: Optional[list] = [] config: Optional[dict] = {} permissions: Optional[dict] = {} - model_max_budget: Optional[dict] = ( - {} - ) # {"gpt-4": 5.0, "gpt-3.5-turbo": 5.0}, defaults to {} + model_max_budget: Optional[ + dict + ] = {} # {"gpt-4": 5.0, "gpt-3.5-turbo": 5.0}, defaults to {} model_config = ConfigDict(protected_namespaces=()) model_rpm_limit: Optional[dict] = None @@ -3999,9 +3999,9 @@ class ProviderBudgetResponse(LiteLLMPydanticObjectBase): Maps provider names to their budget configs. """ - providers: Dict[str, ProviderBudgetResponseObject] = ( - {} - ) # Dictionary mapping provider names to their budget configurations + providers: Dict[ + str, ProviderBudgetResponseObject + ] = {} # Dictionary mapping provider names to their budget configurations class ProxyStateVariables(TypedDict): diff --git a/litellm/proxy/agent_endpoints/a2a_endpoints.py b/litellm/proxy/agent_endpoints/a2a_endpoints.py index 7446f61ad1c..b1fb72619b1 100644 --- a/litellm/proxy/agent_endpoints/a2a_endpoints.py +++ b/litellm/proxy/agent_endpoints/a2a_endpoints.py @@ -305,16 +305,19 @@ async def _handle_stream_message( if not A2A_SDK_AVAILABLE: async def _error_stream(): - yield json.dumps( - { - "jsonrpc": "2.0", - "id": request_id, - "error": { - "code": -32603, - "message": "Server error: 'a2a' package not installed", - }, - } - ) + "\n" + yield ( + json.dumps( + { + "jsonrpc": "2.0", + "id": request_id, + "error": { + "code": -32603, + "message": "Server error: 'a2a' package not installed", + }, + } + ) + + "\n" + ) return StreamingResponse(_error_stream(), media_type="application/x-ndjson") @@ -392,9 +395,10 @@ async def _handle_stream_message( else: async for chunk in a2a_stream: if hasattr(chunk, "model_dump"): - yield json.dumps( - chunk.model_dump(mode="json", exclude_none=True) - ) + "\n" + yield ( + json.dumps(chunk.model_dump(mode="json", exclude_none=True)) + + "\n" + ) else: yield json.dumps(chunk) + "\n" except Exception as e: @@ -414,13 +418,19 @@ async def _handle_stream_message( e = transformed_exception if isinstance(e, HTTPException): raise - yield json.dumps( - { - "jsonrpc": "2.0", - "id": request_id, - "error": {"code": -32603, "message": f"Streaming error: {str(e)}"}, - } - ) + "\n" + yield ( + json.dumps( + { + "jsonrpc": "2.0", + "id": request_id, + "error": { + "code": -32603, + "message": f"Streaming error: {str(e)}", + }, + } + ) + + "\n" + ) return StreamingResponse(stream_response(), media_type="application/x-ndjson") @@ -826,9 +836,9 @@ async def invoke_agent_a2a( ) if method == "agent/getAuthenticatedExtendedCard": if isinstance(result.get("result"), dict) and "url" in result["result"]: - result["result"][ - "url" - ] = f"{str(request.base_url).rstrip('/')}/a2a/{agent_id}" + result["result"]["url"] = ( + f"{str(request.base_url).rstrip('/')}/a2a/{agent_id}" + ) from litellm.types.agents import LiteLLMSendMessageResponse response = LiteLLMSendMessageResponse.from_dict( diff --git a/litellm/proxy/agent_endpoints/agent_registry.py b/litellm/proxy/agent_endpoints/agent_registry.py index 11fd01e2369..c1f9c89529b 100644 --- a/litellm/proxy/agent_endpoints/agent_registry.py +++ b/litellm/proxy/agent_endpoints/agent_registry.py @@ -65,7 +65,9 @@ class AgentRegistry: # create a stable hash id for config item config_hash = self._create_agent_id(agent_config_item) - self.register_agent(agent_config=AgentResponse(agent_id=config_hash, **agent_config_item)) # type: ignore + self.register_agent( + agent_config=AgentResponse(agent_id=config_hash, **agent_config_item) + ) # type: ignore def load_agents_from_db_and_config( self, @@ -79,7 +81,12 @@ class AgentRegistry: if not isinstance(agent_config_item, dict): raise ValueError("agent_config must be a list of dictionaries") - self.register_agent(agent_config=AgentResponse(agent_id=self._create_agent_id(agent_config_item), **agent_config_item)) # type: ignore + self.register_agent( + agent_config=AgentResponse( + agent_id=self._create_agent_id(agent_config_item), + **agent_config_item, + ) + ) # type: ignore if db_agents: for db_agent in db_agents: diff --git a/litellm/proxy/auth/auth_checks_organization.py b/litellm/proxy/auth/auth_checks_organization.py index d89afcffa9a..00aac0d48f9 100644 --- a/litellm/proxy/auth/auth_checks_organization.py +++ b/litellm/proxy/auth/auth_checks_organization.py @@ -134,7 +134,9 @@ def get_user_organization_info( for _membership in user_object.organization_memberships: if _membership.organization_id is not None: _user_organizations.append(_membership.organization_id) - _user_organization_role_mapping[_membership.organization_id] = _membership.user_role # type: ignore + _user_organization_role_mapping[_membership.organization_id] = ( + _membership.user_role + ) # type: ignore return _user_organizations, _user_organization_role_mapping diff --git a/litellm/proxy/auth/handle_jwt.py b/litellm/proxy/auth/handle_jwt.py index 90845dfd824..e73c09719f5 100644 --- a/litellm/proxy/auth/handle_jwt.py +++ b/litellm/proxy/auth/handle_jwt.py @@ -1970,9 +1970,8 @@ class JWTAuthManager: """Main authentication and authorization builder""" # Check if OIDC UserInfo endpoint is enabled, but fall back to standard # JWT auth if the token itself is a well-formed JWT (3-part structure). - if ( - jwt_handler.litellm_jwtauth.oidc_userinfo_enabled - and not jwt_handler.is_jwt(token=api_key) + if jwt_handler.litellm_jwtauth.oidc_userinfo_enabled and not jwt_handler.is_jwt( + token=api_key ): verbose_proxy_logger.debug( "OIDC UserInfo is enabled. Fetching user info from UserInfo endpoint." @@ -2173,16 +2172,18 @@ class JWTAuthManager: # If JWT did not resolve team_id, attempt single-team DB fallback. if team_id is None: - team_id, team_object, team_membership_object = ( - await JWTAuthManager._resolve_single_team_fallback( - user_object=user_object, - user_id=user_id, - prisma_client=prisma_client, - user_api_key_cache=user_api_key_cache, - parent_otel_span=parent_otel_span, - proxy_logging_obj=proxy_logging_obj, - team_id_upsert=jwt_handler.litellm_jwtauth.team_id_upsert, - ) + ( + team_id, + team_object, + team_membership_object, + ) = await JWTAuthManager._resolve_single_team_fallback( + user_object=user_object, + user_id=user_id, + prisma_client=prisma_client, + user_api_key_cache=user_api_key_cache, + parent_otel_span=parent_otel_span, + proxy_logging_obj=proxy_logging_obj, + team_id_upsert=jwt_handler.litellm_jwtauth.team_id_upsert, ) ## MAP USER TO TEAMS diff --git a/litellm/proxy/batches_endpoints/endpoints.py b/litellm/proxy/batches_endpoints/endpoints.py index 344f90aa144..6db75eeb3d9 100644 --- a/litellm/proxy/batches_endpoints/endpoints.py +++ b/litellm/proxy/batches_endpoints/endpoints.py @@ -282,7 +282,8 @@ async def create_batch( else: # SCENARIO 3: Fallback to custom_llm_provider (uses env variables) response = await litellm.acreate_batch( - custom_llm_provider=custom_llm_provider, **_create_batch_data # type: ignore + custom_llm_provider=custom_llm_provider, + **_create_batch_data, # type: ignore ) ### CALL HOOKS ### - modify outgoing data @@ -523,7 +524,8 @@ async def retrieve_batch( or "openai" ) response = await litellm.aretrieve_batch( - custom_llm_provider=custom_llm_provider, **data # type: ignore + custom_llm_provider=custom_llm_provider, + **data, # type: ignore ) # FIX: Update the database with the latest state from provider @@ -735,7 +737,9 @@ async def list_batches( ## POST CALL HOOKS ### _response = await proxy_logging_obj.post_call_success_hook( - data=data, user_api_key_dict=user_api_key_dict, response=response # type: ignore + data=data, + user_api_key_dict=user_api_key_dict, + response=response, # type: ignore ) if _response is not None and type(response) is type(_response): response = _response diff --git a/litellm/proxy/common_request_processing.py b/litellm/proxy/common_request_processing.py index 8dec08460b4..92f8dd8df98 100644 --- a/litellm/proxy/common_request_processing.py +++ b/litellm/proxy/common_request_processing.py @@ -1063,9 +1063,9 @@ class ProxyBaseLLMRequestProcessing: self.data[_metadata_variable_name] = {} if not isinstance(self.data[_metadata_variable_name], dict): self.data[_metadata_variable_name] = {} - self.data[_metadata_variable_name][ - "queue_time_seconds" - ] = queue_time_seconds + self.data[_metadata_variable_name]["queue_time_seconds"] = ( + queue_time_seconds + ) self.data["model"] = ( general_settings.get("completion_model", None) # server default @@ -1508,7 +1508,9 @@ class ProxyBaseLLMRequestProcessing: cache_hit=cache_hit, ) - logging_obj._on_deferred_stream_complete = _on_deferred_stream_complete # type: ignore[union-attr] + logging_obj._on_deferred_stream_complete = ( + _on_deferred_stream_complete # type: ignore[union-attr] + ) if route_type == "allm_passthrough_route": # Check if response is an async generator diff --git a/litellm/proxy/common_utils/callback_utils.py b/litellm/proxy/common_utils/callback_utils.py index d48499af6f0..cd41bce97d6 100644 --- a/litellm/proxy/common_utils/callback_utils.py +++ b/litellm/proxy/common_utils/callback_utils.py @@ -186,11 +186,8 @@ def initialize_callbacks_on_proxy( ) init_params = {} - if ( - "lakera_prompt_injection" in callback_specific_params - and isinstance( - callback_specific_params["lakera_prompt_injection"], dict - ) + if "lakera_prompt_injection" in callback_specific_params and isinstance( + callback_specific_params["lakera_prompt_injection"], dict ): init_params = callback_specific_params["lakera_prompt_injection"] lakera_moderations_object = lakeraAI_Moderation(**init_params) @@ -343,11 +340,8 @@ def initialize_callbacks_on_proxy( ) init_params = {} - if ( - "datadog_cost_management" in callback_specific_params - and isinstance( - callback_specific_params["datadog_cost_management"], dict - ) + if "datadog_cost_management" in callback_specific_params and isinstance( + callback_specific_params["datadog_cost_management"], dict ): init_params = callback_specific_params["datadog_cost_management"] datadog_cost_management_obj = DatadogCostManagementLogger(**init_params) diff --git a/litellm/proxy/common_utils/custom_openapi_spec.py b/litellm/proxy/common_utils/custom_openapi_spec.py index fa3cb02195b..ce5d2539fb3 100644 --- a/litellm/proxy/common_utils/custom_openapi_spec.py +++ b/litellm/proxy/common_utils/custom_openapi_spec.py @@ -156,9 +156,9 @@ class CustomOpenAPISpec: filtered_params = [ param for param in existing_params if param.get("in") == "path" ] - openapi_schema["paths"][path]["post"][ - "parameters" - ] = filtered_params + openapi_schema["paths"][path]["post"]["parameters"] = ( + filtered_params + ) @staticmethod def _move_defs_to_components( diff --git a/litellm/proxy/container_endpoints/handler_factory.py b/litellm/proxy/container_endpoints/handler_factory.py index 7eeb11fc372..52bd9d66b7d 100644 --- a/litellm/proxy/container_endpoints/handler_factory.py +++ b/litellm/proxy/container_endpoints/handler_factory.py @@ -390,12 +390,13 @@ async def _process_request( # Validate container_id ownership if present in path_params. if "container_id" in path_params: - original_container_id, resolved_provider = ( - await assert_user_can_access_container( - container_id=path_params["container_id"], - user_api_key_dict=user_api_key_dict, - custom_llm_provider=custom_llm_provider, - ) + ( + original_container_id, + resolved_provider, + ) = await assert_user_can_access_container( + container_id=path_params["container_id"], + user_api_key_dict=user_api_key_dict, + custom_llm_provider=custom_llm_provider, ) data.update( await get_container_forwarding_params( diff --git a/litellm/proxy/db/db_spend_update_writer.py b/litellm/proxy/db/db_spend_update_writer.py index aab92a54577..57a062b509a 100644 --- a/litellm/proxy/db/db_spend_update_writer.py +++ b/litellm/proxy/db/db_spend_update_writer.py @@ -843,9 +843,7 @@ class DBSpendUpdateWriter: daily_org_spend_update_transactions, daily_end_user_spend_update_transactions, daily_agent_spend_update_transactions, - ) = ( - await self.redis_update_buffer.get_all_transactions_from_redis_buffer_pipeline() - ) + ) = await self.redis_update_buffer.get_all_transactions_from_redis_buffer_pipeline() if db_spend_update_transactions is not None: verbose_proxy_logger.info( @@ -960,9 +958,7 @@ class DBSpendUpdateWriter: # Aggregate all in memory spend updates (key, user, end_user, team, team_member, org) and commit to db ################## Spend Update Transactions ################## - db_spend_update_transactions = ( - await self.spend_update_queue.flush_and_get_aggregated_db_spend_update_transactions() - ) + db_spend_update_transactions = await self.spend_update_queue.flush_and_get_aggregated_db_spend_update_transactions() await self._commit_spend_updates_to_db( prisma_client=prisma_client, n_retry_times=n_retry_times, @@ -1089,9 +1085,7 @@ class DBSpendUpdateWriter: ): verbose_proxy_logger.debug("acquired lock for daily tag spend updates") try: - daily_tag_spend_update_transactions = ( - await self.redis_update_buffer.get_all_daily_tag_spend_update_transactions_from_redis_buffer() - ) + daily_tag_spend_update_transactions = await self.redis_update_buffer.get_all_daily_tag_spend_update_transactions_from_redis_buffer() if daily_tag_spend_update_transactions: await DBSpendUpdateWriter.update_daily_tag_spend( diff --git a/litellm/proxy/db/db_transaction_queue/daily_spend_update_queue.py b/litellm/proxy/db/db_transaction_queue/daily_spend_update_queue.py index f47b694d44e..a72ffad7e9b 100644 --- a/litellm/proxy/db/db_transaction_queue/daily_spend_update_queue.py +++ b/litellm/proxy/db/db_transaction_queue/daily_spend_update_queue.py @@ -73,9 +73,9 @@ class DailySpendUpdateQueue(BaseUpdateQueue): Combine all updates in the queue into a single update. This is used to reduce the size of the in-memory queue. """ - updates: List[Dict[str, BaseDailySpendTransaction]] = ( - await self.flush_all_updates_from_in_memory_queue() - ) + updates: List[ + Dict[str, BaseDailySpendTransaction] + ] = await self.flush_all_updates_from_in_memory_queue() aggregated_updates = self.get_aggregated_daily_spend_update_transactions( updates ) diff --git a/litellm/proxy/db/db_transaction_queue/redis_update_buffer.py b/litellm/proxy/db/db_transaction_queue/redis_update_buffer.py index 1e3014dbf3c..6cbfb37396c 100644 --- a/litellm/proxy/db/db_transaction_queue/redis_update_buffer.py +++ b/litellm/proxy/db/db_transaction_queue/redis_update_buffer.py @@ -186,24 +186,12 @@ class RedisUpdateBuffer: return # Get all transactions - db_spend_update_transactions = ( - await spend_update_queue.flush_and_get_aggregated_db_spend_update_transactions() - ) - daily_spend_update_transactions = ( - await daily_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() - ) - daily_team_spend_update_transactions = ( - await daily_team_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() - ) - daily_org_spend_update_transactions = ( - await daily_org_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() - ) - daily_end_user_spend_update_transactions = ( - await daily_end_user_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() - ) - daily_agent_spend_update_transactions = ( - await daily_agent_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() - ) + db_spend_update_transactions = await spend_update_queue.flush_and_get_aggregated_db_spend_update_transactions() + daily_spend_update_transactions = await daily_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() + daily_team_spend_update_transactions = await daily_team_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() + daily_org_spend_update_transactions = await daily_org_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() + daily_end_user_spend_update_transactions = await daily_end_user_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() + daily_agent_spend_update_transactions = await daily_agent_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() verbose_proxy_logger.debug( "ALL DB SPEND UPDATE TRANSACTIONS: %s", db_spend_update_transactions @@ -576,9 +564,7 @@ class RedisUpdateBuffer: """ Flush in-memory daily tag spend updates and append them to Redis. """ - daily_tag_spend_update_transactions = ( - await daily_tag_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() - ) + daily_tag_spend_update_transactions = await daily_tag_spend_update_queue.flush_and_get_aggregated_daily_spend_update_transactions() await self._store_transactions_in_redis( transactions=daily_tag_spend_update_transactions, redis_key=REDIS_DAILY_TAG_SPEND_UPDATE_BUFFER_KEY, diff --git a/litellm/proxy/db/db_transaction_queue/spend_update_queue.py b/litellm/proxy/db/db_transaction_queue/spend_update_queue.py index 8100a1e8a12..727e8dc1d5a 100644 --- a/litellm/proxy/db/db_transaction_queue/spend_update_queue.py +++ b/litellm/proxy/db/db_transaction_queue/spend_update_queue.py @@ -53,9 +53,9 @@ class SpendUpdateQueue(BaseUpdateQueue): async def aggregate_queue_updates(self): """Concatenate all updates in the queue to reduce the size of in-memory queue""" - updates: List[SpendUpdateQueueItem] = ( - await self.flush_all_updates_from_in_memory_queue() - ) + updates: List[ + SpendUpdateQueueItem + ] = await self.flush_all_updates_from_in_memory_queue() aggregated_updates = self._get_aggregated_spend_update_queue_item(updates) for update in aggregated_updates: await self.update_queue.put(update) diff --git a/litellm/proxy/db/dynamo_db.py b/litellm/proxy/db/dynamo_db.py index 628509d9c36..57ebb9678cb 100644 --- a/litellm/proxy/db/dynamo_db.py +++ b/litellm/proxy/db/dynamo_db.py @@ -25,7 +25,10 @@ class DynamoDBWrapper(CustomDB): and database_arguments.write_capacity_units is not None and isinstance(database_arguments.write_capacity_units, int) ): - self.throughput_type = Throughput(read=database_arguments.read_capacity_units, write=database_arguments.write_capacity_units) # type: ignore + self.throughput_type = Throughput( + read=database_arguments.read_capacity_units, + write=database_arguments.write_capacity_units, + ) # type: ignore else: raise Exception( f"Invalid args passed in. Need to set both read_capacity_units and write_capacity_units. Args passed in - {database_arguments}" diff --git a/litellm/proxy/db/log_db_metrics.py b/litellm/proxy/db/log_db_metrics.py index eb4961062df..837e94f1a85 100644 --- a/litellm/proxy/db/log_db_metrics.py +++ b/litellm/proxy/db/log_db_metrics.py @@ -66,9 +66,7 @@ def log_db_metrics(func): elif ( # in litellm custom callbacks kwargs is passed as arg[0] # https://docs.litellm.ai/docs/observability/custom_callback#callback-functions - args is not None - and len(args) > 1 - and isinstance(args[1], dict) + args is not None and len(args) > 1 and isinstance(args[1], dict) ): passed_kwargs = args[1] parent_otel_span = _get_parent_otel_span_from_kwargs( diff --git a/litellm/proxy/guardrails/guardrail_endpoints.py b/litellm/proxy/guardrails/guardrail_endpoints.py index 9f8ea584103..c2175ce95e0 100644 --- a/litellm/proxy/guardrails/guardrail_endpoints.py +++ b/litellm/proxy/guardrails/guardrail_endpoints.py @@ -617,9 +617,7 @@ class GuardrailSubmissionItem(BaseModel): guardrail_name: str status: str # pending_review | active | rejected team_id: Optional[str] = None - team_guardrail: bool = ( - False # True when submitted via team (team_id set); use to distinguish team vs regular guardrails - ) + team_guardrail: bool = False # True when submitted via team (team_id set); use to distinguish team vs regular guardrails litellm_params: Optional[Dict[str, Any]] = None guardrail_info: Optional[Dict[str, Any]] = None submitted_by_user_id: Optional[str] = None @@ -2322,16 +2320,17 @@ async def apply_guardrail( ) request_processor = ProxyBaseLLMRequestProcessing(data=data) - data, litellm_logging_obj = ( - await request_processor.common_processing_pre_call_logic( - request=fastapi_request, - general_settings=general_settings, - user_api_key_dict=user_api_key_dict, - version=version, - proxy_logging_obj=proxy_logging_obj, - proxy_config=proxy_config, - route_type="apply_guardrail", - ) + ( + data, + litellm_logging_obj, + ) = await request_processor.common_processing_pre_call_logic( + request=fastapi_request, + general_settings=general_settings, + user_api_key_dict=user_api_key_dict, + version=version, + proxy_logging_obj=proxy_logging_obj, + proxy_config=proxy_config, + route_type="apply_guardrail", ) if litellm_logging_obj is not None: diff --git a/litellm/proxy/guardrails/guardrail_hooks/azure/text_moderation.py b/litellm/proxy/guardrails/guardrail_hooks/azure/text_moderation.py index 55b446eb529..e21be6ffdbe 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/azure/text_moderation.py +++ b/litellm/proxy/guardrails/guardrail_hooks/azure/text_moderation.py @@ -65,9 +65,7 @@ class AzureContentSafetyTextModerationGuardrail(AzureGuardrailBase, CustomGuardr **kwargs, ) - self.optional_params_request_body: ( - AzureTextModerationRequestBodyOptionalParams - ) = { + self.optional_params_request_body: AzureTextModerationRequestBodyOptionalParams = { "categories": kwargs.get("categories") or [ "Hate", diff --git a/litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense.py b/litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense.py index ba2f531f26e..79e81b6c4c4 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense.py +++ b/litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense.py @@ -531,7 +531,7 @@ class CiscoAIDefenseGuardrail(_CiscoAIDefenseMcpMixin, CustomGuardrail): self.guardrail_name, type(all_chunks[0]).__name__, ) - yield f'data: {json.dumps({"error": {"message": "Cisco AI Defense: unsupported streaming format — response withheld for safety", "type": "guardrail_unsupported_stream", "code": 400, "guardrail": self.guardrail_name}})}\n\n' + yield f"data: {json.dumps({'error': {'message': 'Cisco AI Defense: unsupported streaming format — response withheld for safety', 'type': 'guardrail_unsupported_stream', 'code': 400, 'guardrail': self.guardrail_name}})}\n\n" return assembled = stream_chunk_builder(chunks=all_chunks) @@ -546,7 +546,7 @@ class CiscoAIDefenseGuardrail(_CiscoAIDefenseMcpMixin, CustomGuardrail): self.guardrail_name, type(assembled).__name__, ) - yield f'data: {json.dumps({"error": {"message": "Cisco AI Defense: unsupported streaming format — response withheld for safety", "type": "guardrail_unsupported_stream", "code": 400, "guardrail": self.guardrail_name}})}\n\n' + yield f"data: {json.dumps({'error': {'message': 'Cisco AI Defense: unsupported streaming format — response withheld for safety', 'type': 'guardrail_unsupported_stream', 'code': 400, 'guardrail': self.guardrail_name}})}\n\n" return response_messages = self._extract_response_messages(assembled) @@ -586,14 +586,13 @@ class CiscoAIDefenseGuardrail(_CiscoAIDefenseMcpMixin, CustomGuardrail): return except Exception as exc: verbose_proxy_logger.error( - "Cisco AI Defense guardrail (%s): streaming response " - "scan failed: %s", + "Cisco AI Defense guardrail (%s): streaming response scan failed: %s", self.guardrail_name, exc, ) error_obj = { "message": ( - "Cisco AI Defense streaming scan failed — response " "withheld." + "Cisco AI Defense streaming scan failed — response withheld." ), "type": "guardrail_scan_error", "code": 500, @@ -932,8 +931,7 @@ class CiscoAIDefenseGuardrail(_CiscoAIDefenseMcpMixin, CustomGuardrail): ) from exc except httpx.TimeoutException as exc: raise CiscoAIDefenseGuardrailAPIError( - f"Cisco AI Defense {surface} API call timed out after " - f"{self.timeout}s" + f"Cisco AI Defense {surface} API call timed out after {self.timeout}s" ) from exc except httpx.RequestError as exc: raise CiscoAIDefenseGuardrailAPIError( @@ -1178,8 +1176,7 @@ class CiscoAIDefenseGuardrail(_CiscoAIDefenseMcpMixin, CustomGuardrail): ) if redacted: verbose_proxy_logger.info( - "Cisco AI Defense guardrail (%s): redaction applied " - "(event_id=%s)", + "Cisco AI Defense guardrail (%s): redaction applied (event_id=%s)", context.surface, verdict.event_id, ) diff --git a/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py b/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py index c6dfe141ab5..cc944fb46dc 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py +++ b/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py @@ -212,17 +212,17 @@ class ContentFilterGuardrail(CustomGuardrail): self.image_model = image_model # Store loaded categories self.loaded_categories: Dict[str, CategoryConfig] = {} - self.category_keywords: Dict[str, Tuple[str, str, ContentFilterAction]] = ( - {} - ) # keyword -> (category, severity, action) + self.category_keywords: Dict[ + str, Tuple[str, str, ContentFilterAction] + ] = {} # keyword -> (category, severity, action) # Always-block keywords are checked after exceptions (exceptions take precedence) self.always_block_category_keywords: Dict[ str, Tuple[str, str, ContentFilterAction] ] = {} # Store conditional categories (identifier_words + block_words) - self.conditional_categories: Dict[str, Dict[str, Any]] = ( - {} - ) # category_name -> {identifier_words, block_words, action, severity} + self.conditional_categories: Dict[ + str, Dict[str, Any] + ] = {} # category_name -> {identifier_words, block_words, action, severity} # Competitor intent checker (optional; airline uses major_airlines.json, generic requires competitors) self._competitor_intent_checker: Optional[BaseCompetitorIntentChecker] = None diff --git a/litellm/proxy/guardrails/guardrail_hooks/llm_as_a_judge/__init__.py b/litellm/proxy/guardrails/guardrail_hooks/llm_as_a_judge/__init__.py index 45bdd6dd09f..bc234c0a6f8 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/llm_as_a_judge/__init__.py +++ b/litellm/proxy/guardrails/guardrail_hooks/llm_as_a_judge/__init__.py @@ -68,11 +68,11 @@ def _build_judge_prompt( response_text: str, ) -> str: criteria_block = "\n".join( - f'- {c.get("name", "")} (weight {c.get("weight", 0)}%): {c.get("description", "")}' + f"- {c.get('name', '')} (weight {c.get('weight', 0)}%): {c.get('description', '')}" for c in criteria ) conversation = "\n".join( - f'{m.get("role", "user").upper()}: {_extract_text_from_content(m.get("content", ""))}' + f"{m.get('role', 'user').upper()}: {_extract_text_from_content(m.get('content', ''))}" for m in messages if m.get("content") is not None ) diff --git a/litellm/proxy/guardrails/guardrail_hooks/model_armor/model_armor.py b/litellm/proxy/guardrails/guardrail_hooks/model_armor/model_armor.py index d00e77daa07..7334e82549b 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/model_armor/model_armor.py +++ b/litellm/proxy/guardrails/guardrail_hooks/model_armor/model_armor.py @@ -297,7 +297,9 @@ class ModelArmorGuardrail(CustomGuardrail, VertexBase): filters = ( list(filter_results.values()) if isinstance(filter_results, dict) - else filter_results if isinstance(filter_results, list) else [] + else filter_results + if isinstance(filter_results, list) + else [] ) # Prefer sanitized text from deidentifyResult if present diff --git a/litellm/proxy/guardrails/guardrail_hooks/noma/noma.py b/litellm/proxy/guardrails/guardrail_hooks/noma/noma.py index d80a1a299d5..aadfdf66531 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/noma/noma.py +++ b/litellm/proxy/guardrails/guardrail_hooks/noma/noma.py @@ -185,8 +185,10 @@ class NomaGuardrail(CustomGuardrail): if not messages: return None - input_items, instructions = self._responses_transform_handler.convert_chat_completion_messages_to_responses_api( # type: ignore[arg-type] - messages + input_items, instructions = ( + self._responses_transform_handler.convert_chat_completion_messages_to_responses_api( # type: ignore[arg-type] + messages + ) ) if instructions: diff --git a/litellm/proxy/guardrails/guardrail_hooks/panw_prisma_airs/panw_prisma_airs.py b/litellm/proxy/guardrails/guardrail_hooks/panw_prisma_airs/panw_prisma_airs.py index e8887fa712a..04d68edeb80 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/panw_prisma_airs/panw_prisma_airs.py +++ b/litellm/proxy/guardrails/guardrail_hooks/panw_prisma_airs/panw_prisma_airs.py @@ -1502,7 +1502,7 @@ class PanwPrismaAirsHandler(CustomGuardrail): yield f"data: {json.dumps({'error': error_obj})}\n\n" except Exception as e: verbose_proxy_logger.error(f"PANW Prisma AIRS streaming error: {str(e)}") - yield f'data: {json.dumps({"error": {"message": "Security scan failed - streaming response blocked for safety", "type": "guardrail_scan_error", "code": 500, "guardrail": self.guardrail_name}})}\n\n' + yield f"data: {json.dumps({'error': {'message': 'Security scan failed - streaming response blocked for safety', 'type': 'guardrail_scan_error', 'code': 500, 'guardrail': self.guardrail_name}})}\n\n" async def _scan_tool_calls_for_guardrail( self, diff --git a/litellm/proxy/guardrails/guardrail_hooks/presidio.py b/litellm/proxy/guardrails/guardrail_hooks/presidio.py index a8afe4efe2a..1367f95c5c8 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/presidio.py +++ b/litellm/proxy/guardrails/guardrail_hooks/presidio.py @@ -93,9 +93,7 @@ class _OPTIONAL_PresidioPIIMasking(CustomGuardrail): kwargs["event_hook"] = GuardrailEventHooks.logging_only super().__init__(**kwargs) self.guardrail_provider = "presidio" - self.pii_tokens: dict = ( - {} - ) # mapping of PII token to original text - only used with Presidio `replace` operation + self.pii_tokens: dict = {} # mapping of PII token to original text - only used with Presidio `replace` operation self.mock_redacted_text = mock_redacted_text self.output_parse_pii = output_parse_pii or False self.apply_to_output = apply_to_output @@ -164,15 +162,12 @@ class _OPTIONAL_PresidioPIIMasking(CustomGuardrail): presidio_analyzer_api_base: Optional[str] = None, presidio_anonymizer_api_base: Optional[str] = None, ): - self.presidio_analyzer_api_base: Optional[ - str - ] = presidio_analyzer_api_base or get_secret( - "PRESIDIO_ANALYZER_API_BASE", None + self.presidio_analyzer_api_base: Optional[str] = ( + presidio_analyzer_api_base or get_secret("PRESIDIO_ANALYZER_API_BASE", None) ) # type: ignore - self.presidio_anonymizer_api_base: Optional[ - str - ] = presidio_anonymizer_api_base or litellm.get_secret( - "PRESIDIO_ANONYMIZER_API_BASE", None + self.presidio_anonymizer_api_base: Optional[str] = ( + presidio_anonymizer_api_base + or litellm.get_secret("PRESIDIO_ANONYMIZER_API_BASE", None) ) # type: ignore if self.presidio_analyzer_api_base is None: @@ -762,9 +757,9 @@ class _OPTIONAL_PresidioPIIMasking(CustomGuardrail): if messages is None: return data tasks = [] - task_mappings: List[Tuple[int, Optional[int]]] = ( - [] - ) # Track (message_index, content_index) for each task + task_mappings: List[ + Tuple[int, Optional[int]] + ] = [] # Track (message_index, content_index) for each task for msg_idx, m in enumerate(messages): content = m.get("content", None) @@ -808,9 +803,9 @@ class _OPTIONAL_PresidioPIIMasking(CustomGuardrail): if content is None: continue if isinstance(content, str) and content_idx_optional is None: - messages[msg_idx][ - "content" - ] = r # replace content with redacted string + messages[msg_idx]["content"] = ( + r # replace content with redacted string + ) elif isinstance(content, list) and content_idx_optional is not None: messages[msg_idx]["content"][content_idx_optional]["text"] = r @@ -865,9 +860,9 @@ class _OPTIONAL_PresidioPIIMasking(CustomGuardrail): ): # /chat/completions requests messages: Optional[List] = kwargs.get("messages", None) tasks = [] - task_mappings: List[Tuple[int, Optional[int]]] = ( - [] - ) # Track (message_index, content_index) for each task + task_mappings: List[ + Tuple[int, Optional[int]] + ] = [] # Track (message_index, content_index) for each task if messages is None: return kwargs, result @@ -916,9 +911,9 @@ class _OPTIONAL_PresidioPIIMasking(CustomGuardrail): if content is None: continue if isinstance(content, str) and content_idx_optional is None: - messages[msg_idx][ - "content" - ] = r # replace content with redacted string + messages[msg_idx]["content"] = ( + r # replace content with redacted string + ) elif isinstance(content, list) and content_idx_optional is not None: messages[msg_idx]["content"][content_idx_optional]["text"] = r diff --git a/litellm/proxy/guardrails/guardrail_hooks/repelloai/repelloai.py b/litellm/proxy/guardrails/guardrail_hooks/repelloai/repelloai.py index 34f38036265..a796fedbe27 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/repelloai/repelloai.py +++ b/litellm/proxy/guardrails/guardrail_hooks/repelloai/repelloai.py @@ -203,12 +203,10 @@ class RepelloAIGuardrail(CustomGuardrail): repelloai_response: RepelloAIAnalyzeResponse | None = None try: verbose_proxy_logger.debug("RepelloAI Argus request: %s", request) - raw_response: HttpxResponse | None = ( - await self.async_handler.post( # pyright: ignore[reportUnknownMemberType] - url=endpoint, - headers={"X-API-Key": self.repelloai_api_key}, - json=request, - ) + raw_response: HttpxResponse | None = await self.async_handler.post( # pyright: ignore[reportUnknownMemberType] + url=endpoint, + headers={"X-API-Key": self.repelloai_api_key}, + json=request, ) if raw_response is None: raise ValueError("RepelloAI Argus returned no response") @@ -235,7 +233,9 @@ class RepelloAIGuardrail(CustomGuardrail): return repelloai_response except HTTPException as e: status = "guardrail_failed_to_respond" - guardrail_json_response = str(e.detail) if not isinstance(e.detail, (dict, list)) else e.detail # type: ignore[assignment] + guardrail_json_response = ( + str(e.detail) if not isinstance(e.detail, (dict, list)) else e.detail + ) # type: ignore[assignment] raise except HTTPError as e: status = "guardrail_failed_to_respond" diff --git a/litellm/proxy/guardrails/guardrail_registry.py b/litellm/proxy/guardrails/guardrail_registry.py index b99ea8f14a0..734330a2167 100644 --- a/litellm/proxy/guardrails/guardrail_registry.py +++ b/litellm/proxy/guardrails/guardrail_registry.py @@ -479,7 +479,9 @@ class InMemoryGuardrailHandler: sig = inspect.signature(initializer) if "llm_router" in sig.parameters: custom_guardrail_callback = initializer( - litellm_params, guardrail, llm_router # type: ignore + litellm_params, + guardrail, + llm_router, # type: ignore ) else: custom_guardrail_callback = initializer(litellm_params, guardrail) diff --git a/litellm/proxy/guardrails/init_guardrails.py b/litellm/proxy/guardrails/init_guardrails.py index 83f1281dc02..9e45f18232c 100644 --- a/litellm/proxy/guardrails/init_guardrails.py +++ b/litellm/proxy/guardrails/init_guardrails.py @@ -137,7 +137,9 @@ def initialize_guardrails( if guardrail.logging_only is True: if callback == "presidio": - callback_specific_params["presidio"] = {"logging_only": True} # type: ignore + callback_specific_params["presidio"] = { + "logging_only": True + } # type: ignore default_on_callbacks_list = list(default_on_callbacks) if len(default_on_callbacks_list) > 0: diff --git a/litellm/proxy/health_check.py b/litellm/proxy/health_check.py index 488467e1b99..ed91645eb43 100644 --- a/litellm/proxy/health_check.py +++ b/litellm/proxy/health_check.py @@ -194,7 +194,8 @@ async def _run_model_health_check(model: dict): litellm_params = model["litellm_params"] model_info = model.get("model_info", {}) mode = _resolve_health_check_mode( - model_info, litellm_params # any-ok: untyped router config dict + model_info, + litellm_params, # any-ok: untyped router config dict ) litellm_params = _update_litellm_params_for_health_check(model_info, litellm_params) timeout = model_info.get("health_check_timeout") or HEALTH_CHECK_TIMEOUT_SECONDS @@ -454,11 +455,13 @@ def _update_litellm_params_for_health_check( - for Bedrock models with region routing (bedrock/region/model), strips the litellm routing prefix but preserves the model ID, and pins `custom_llm_provider` to `bedrock` (only when the deployment hasn't already set one, so an explicit `bedrock_converse` survives) so the bare model id still resolves to the provider (e.g. cross-region ids like `us.cohere.embed-v4:0`) """ mode = _resolve_health_check_mode( - model_info, litellm_params # any-ok: untyped router config dict + model_info, + litellm_params, # any-ok: untyped router config dict ) litellm_params["messages"] = _get_random_llm_message() if _should_inject_health_check_max_tokens( - model_info, mode # any-ok: untyped router config dict + model_info, + mode, # any-ok: untyped router config dict ): _resolved_max_tokens = _resolve_health_check_max_tokens( model_info, litellm_params diff --git a/litellm/proxy/hooks/dynamic_rate_limiter.py b/litellm/proxy/hooks/dynamic_rate_limiter.py index b9e2bd12ecf..7edc5f4698c 100644 --- a/litellm/proxy/hooks/dynamic_rate_limiter.py +++ b/litellm/proxy/hooks/dynamic_rate_limiter.py @@ -272,10 +272,10 @@ class _PROXY_DynamicRateLimitHandler(CustomLogger): model_info = self.llm_router.get_model_info( id=response._hidden_params["model_id"] ) - assert ( - model_info is not None - ), "Model info for model with id={} is None".format( - response._hidden_params["model_id"] + assert model_info is not None, ( + "Model info for model with id={} is None".format( + response._hidden_params["model_id"] + ) ) key_priority: Optional[str] = user_api_key_dict.metadata.get( "priority", None @@ -289,16 +289,16 @@ class _PROXY_DynamicRateLimitHandler(CustomLogger): ) = await self.check_available_usage( model=model_info["model_name"], priority=key_priority ) - response._hidden_params["additional_headers"] = ( - { # Add additional response headers - easier debugging - "x-litellm-model_group": model_info["model_name"], - "x-ratelimit-remaining-litellm-project-tokens": available_tpm, - "x-ratelimit-remaining-litellm-project-requests": available_rpm, - "x-ratelimit-remaining-model-tokens": model_tpm, - "x-ratelimit-remaining-model-requests": model_rpm, - "x-ratelimit-current-active-projects": active_projects, - } - ) + response._hidden_params[ + "additional_headers" + ] = { # Add additional response headers - easier debugging + "x-litellm-model_group": model_info["model_name"], + "x-ratelimit-remaining-litellm-project-tokens": available_tpm, + "x-ratelimit-remaining-litellm-project-requests": available_rpm, + "x-ratelimit-remaining-model-tokens": model_tpm, + "x-ratelimit-remaining-model-requests": model_rpm, + "x-ratelimit-current-active-projects": active_projects, + } return response return await super().async_post_call_success_hook( diff --git a/litellm/proxy/hooks/key_management_event_hooks.py b/litellm/proxy/hooks/key_management_event_hooks.py index 6bb9c1f507c..ee6c063e8e7 100644 --- a/litellm/proxy/hooks/key_management_event_hooks.py +++ b/litellm/proxy/hooks/key_management_event_hooks.py @@ -376,10 +376,10 @@ class KeyManagementEventHooks: if key.key_alias is not None: team_id = getattr(key, "team_id", None) if team_id not in team_settings_cache: - team_settings_cache[team_id] = ( - await KeyManagementEventHooks._get_secret_manager_optional_params( - team_id - ) + team_settings_cache[ + team_id + ] = await KeyManagementEventHooks._get_secret_manager_optional_params( + team_id ) optional_params = team_settings_cache[team_id] await litellm.secret_manager_client.async_delete_secret( diff --git a/litellm/proxy/hooks/parallel_request_limiter.py b/litellm/proxy/hooks/parallel_request_limiter.py index d36e9858b5a..37da5671b64 100644 --- a/litellm/proxy/hooks/parallel_request_limiter.py +++ b/litellm/proxy/hooks/parallel_request_limiter.py @@ -263,9 +263,9 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger): if rpm_limit is None: rpm_limit = sys.maxsize - values_to_update_in_cache: List[Tuple[Any, Any]] = ( - [] - ) # values that need to get updated in cache, will run a batch_set_cache after this function + values_to_update_in_cache: List[ + Tuple[Any, Any] + ] = [] # values that need to get updated in cache, will run a batch_set_cache after this function # ------------ # Setup values @@ -901,11 +901,11 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger): current_minute = datetime.now().strftime("%M") precise_minute = f"{current_date}-{current_hour}-{current_minute}" request_count_api_key = f"{api_key}::{precise_minute}::request_count" - current: Optional[CurrentItemRateLimit] = ( - await self.internal_usage_cache.async_get_cache( - key=request_count_api_key, - litellm_parent_otel_span=user_api_key_dict.parent_otel_span, - ) + current: Optional[ + CurrentItemRateLimit + ] = await self.internal_usage_cache.async_get_cache( + key=request_count_api_key, + litellm_parent_otel_span=user_api_key_dict.parent_otel_span, ) key_remaining_rpm_limit: Optional[int] = None diff --git a/litellm/proxy/hooks/parallel_request_limiter_v3.py b/litellm/proxy/hooks/parallel_request_limiter_v3.py index 85d034b7a41..5ca1b2caccf 100644 --- a/litellm/proxy/hooks/parallel_request_limiter_v3.py +++ b/litellm/proxy/hooks/parallel_request_limiter_v3.py @@ -2943,9 +2943,11 @@ class _PROXY_MaxParallelRequestsHandler_v3(CustomLogger): ) if pipeline_operations: - await self.internal_usage_cache.dual_cache.async_increment_cache_pipeline( - increment_list=pipeline_operations, - litellm_parent_otel_span=litellm_parent_otel_span, + await ( + self.internal_usage_cache.dual_cache.async_increment_cache_pipeline( + increment_list=pipeline_operations, + litellm_parent_otel_span=litellm_parent_otel_span, + ) ) if reserved_tokens > 0: self._mark_reservation_released(kwargs) @@ -3104,9 +3106,11 @@ class _PROXY_MaxParallelRequestsHandler_v3(CustomLogger): f"Releasing reserved TPM tokens on proxy-level " f"rejection: {reserved_tokens}" ) - await self.internal_usage_cache.dual_cache.async_increment_cache_pipeline( - increment_list=ops, - litellm_parent_otel_span=user_api_key_dict.parent_otel_span, + await ( + self.internal_usage_cache.dual_cache.async_increment_cache_pipeline( + increment_list=ops, + litellm_parent_otel_span=user_api_key_dict.parent_otel_span, + ) ) self._mark_reservation_released(request_data) except Exception as e: diff --git a/litellm/proxy/hooks/prompt_injection_detection.py b/litellm/proxy/hooks/prompt_injection_detection.py index 6678ccd7e0b..bfe85edf4cb 100644 --- a/litellm/proxy/hooks/prompt_injection_detection.py +++ b/litellm/proxy/hooks/prompt_injection_detection.py @@ -270,7 +270,10 @@ class _OPTIONAL_PromptInjectionDetection(CustomLogger): if isinstance(response, litellm.ModelResponse) and isinstance( response.choices[0], litellm.Choices ): - if self.prompt_injection_params.llm_api_fail_call_string in response.choices[0].message.content: # type: ignore + if ( + self.prompt_injection_params.llm_api_fail_call_string + in response.choices[0].message.content + ): # type: ignore is_prompt_attack = True if is_prompt_attack is True: diff --git a/litellm/proxy/hooks/proxy_track_cost_callback.py b/litellm/proxy/hooks/proxy_track_cost_callback.py index 8fc9d009e67..e3506c78096 100644 --- a/litellm/proxy/hooks/proxy_track_cost_callback.py +++ b/litellm/proxy/hooks/proxy_track_cost_callback.py @@ -281,12 +281,14 @@ class _ProxyDBLogger(CustomLogger): ) ) - await proxy_logging_obj.slack_alerting_instance.customer_spend_alert( - token=user_api_key, - key_alias=key_alias, - end_user_id=end_user_id, - response_cost=response_cost, - max_budget=end_user_max_budget, + await ( + proxy_logging_obj.slack_alerting_instance.customer_spend_alert( + token=user_api_key, + key_alias=key_alias, + end_user_id=end_user_id, + response_cost=response_cost, + max_budget=end_user_max_budget, + ) ) elif budget_reservation is not None: await _release_budget_reservation( diff --git a/litellm/proxy/hooks/user_management_event_hooks.py b/litellm/proxy/hooks/user_management_event_hooks.py index c22fd1d6579..8122c5e68c6 100644 --- a/litellm/proxy/hooks/user_management_event_hooks.py +++ b/litellm/proxy/hooks/user_management_event_hooks.py @@ -123,8 +123,10 @@ class UserManagementEventHooks: use_enterprise_email_hooks = False if use_enterprise_email_hooks and (data.send_invite_email is True): - initialized_email_loggers = litellm.logging_callback_manager.get_custom_loggers_for_type( - callback_type=BaseEmailLogger # type: ignore + initialized_email_loggers = ( + litellm.logging_callback_manager.get_custom_loggers_for_type( + callback_type=BaseEmailLogger # type: ignore + ) ) if len(initialized_email_loggers) > 0: for email_logger in initialized_email_loggers: diff --git a/litellm/proxy/litellm_pre_call_utils.py b/litellm/proxy/litellm_pre_call_utils.py index c0cdf84dfb6..36881765596 100644 --- a/litellm/proxy/litellm_pre_call_utils.py +++ b/litellm/proxy/litellm_pre_call_utils.py @@ -1049,9 +1049,9 @@ class LiteLLMProxyRequestSetup: ) ) data[_metadata_variable_name].update(user_api_key_logged_metadata) - data[_metadata_variable_name][ - "user_api_key" - ] = user_api_key_dict.api_key # this is just the hashed token + data[_metadata_variable_name]["user_api_key"] = ( + user_api_key_dict.api_key + ) # this is just the hashed token # Key-owned agent_id for spend attribution; keep existing (e.g. from header) if key has none _key_agent_id = getattr(user_api_key_dict, "agent_id", None) @@ -1063,9 +1063,9 @@ class LiteLLMProxyRequestSetup: user_api_key_dict, "end_user_max_budget", None ) if user_api_key_dict.budget_reservation is not None: - data[_metadata_variable_name][ - "user_api_key_budget_reservation" - ] = user_api_key_dict.budget_reservation + data[_metadata_variable_name]["user_api_key_budget_reservation"] = ( + user_api_key_dict.budget_reservation + ) # Add the full UserAPIKeyAuth object for MCP server access control data[_metadata_variable_name]["user_api_key_auth"] = user_api_key_dict return data @@ -1140,9 +1140,9 @@ class LiteLLMProxyRequestSetup: if ( key not in data[_metadata_variable_name]["spend_logs_metadata"] ): # don't override k-v pair sent by request (user request) - data[_metadata_variable_name]["spend_logs_metadata"][ - key - ] = value + data[_metadata_variable_name]["spend_logs_metadata"][key] = ( + value + ) else: data[_metadata_variable_name]["spend_logs_metadata"] = key_metadata[ "spend_logs_metadata" @@ -1712,41 +1712,41 @@ async def add_litellm_data_to_request( ) # Team spend, budget - used by prometheus.py - data[_metadata_variable_name][ - "user_api_key_team_max_budget" - ] = user_api_key_dict.team_max_budget - data[_metadata_variable_name][ - "user_api_key_team_spend" - ] = user_api_key_dict.team_spend - data[_metadata_variable_name][ - "user_api_key_request_route" - ] = user_api_key_dict.request_route + data[_metadata_variable_name]["user_api_key_team_max_budget"] = ( + user_api_key_dict.team_max_budget + ) + data[_metadata_variable_name]["user_api_key_team_spend"] = ( + user_api_key_dict.team_spend + ) + data[_metadata_variable_name]["user_api_key_request_route"] = ( + user_api_key_dict.request_route + ) # API Key spend, budget - used by prometheus.py data[_metadata_variable_name]["user_api_key_spend"] = user_api_key_dict.spend - data[_metadata_variable_name][ - "user_api_key_max_budget" - ] = user_api_key_dict.max_budget - data[_metadata_variable_name][ - "user_api_key_model_max_budget" - ] = user_api_key_dict.model_max_budget - data[_metadata_variable_name][ - "user_api_key_end_user_model_max_budget" - ] = user_api_key_dict.end_user_model_max_budget + data[_metadata_variable_name]["user_api_key_max_budget"] = ( + user_api_key_dict.max_budget + ) + data[_metadata_variable_name]["user_api_key_model_max_budget"] = ( + user_api_key_dict.model_max_budget + ) + data[_metadata_variable_name]["user_api_key_end_user_model_max_budget"] = ( + user_api_key_dict.end_user_model_max_budget + ) # User spend, budget - used by prometheus.py # Follow same pattern as team and API key budgets - data[_metadata_variable_name][ - "user_api_key_user_spend" - ] = user_api_key_dict.user_spend - data[_metadata_variable_name][ - "user_api_key_user_max_budget" - ] = user_api_key_dict.user_max_budget + data[_metadata_variable_name]["user_api_key_user_spend"] = ( + user_api_key_dict.user_spend + ) + data[_metadata_variable_name]["user_api_key_user_max_budget"] = ( + user_api_key_dict.user_max_budget + ) data[_metadata_variable_name]["user_api_key_metadata"] = user_api_key_dict.metadata - data[_metadata_variable_name][ - "user_api_key_team_metadata" - ] = user_api_key_dict.team_metadata + data[_metadata_variable_name]["user_api_key_team_metadata"] = ( + user_api_key_dict.team_metadata + ) data[_metadata_variable_name]["user_api_key_object_permission_id"] = getattr( user_api_key_dict, "object_permission_id", None ) @@ -1764,9 +1764,9 @@ async def add_litellm_data_to_request( # OTEL Controls / Tracing # Add the OTEL Parent Trace before sending it LiteLLM - data[_metadata_variable_name][ - "litellm_parent_otel_span" - ] = user_api_key_dict.parent_otel_span + data[_metadata_variable_name]["litellm_parent_otel_span"] = ( + user_api_key_dict.parent_otel_span + ) _add_otel_traceparent_to_data(data, request=request) ### END-USER SPECIFIC PARAMS ### @@ -2578,9 +2578,9 @@ async def move_guardrails_to_metadata( request_body_guardrail_config ) else: - data[_metadata_variable_name][ - "guardrail_config" - ] = request_body_guardrail_config + data[_metadata_variable_name]["guardrail_config"] = ( + request_body_guardrail_config + ) def _is_policy_version_id(s: str) -> bool: @@ -2710,9 +2710,9 @@ def _apply_resolved_guardrails_to_metadata( pipelines ) data[metadata_variable_name]["_guardrail_pipelines"] = pipelines - data[metadata_variable_name][ - "_pipeline_managed_guardrails" - ] = pipeline_managed_guardrails + data[metadata_variable_name]["_pipeline_managed_guardrails"] = ( + pipeline_managed_guardrails + ) verbose_proxy_logger.debug( f"Policy engine: resolved {len(pipelines)} pipeline(s), " f"managed guardrails: {pipeline_managed_guardrails}" diff --git a/litellm/proxy/management_endpoints/common_daily_activity.py b/litellm/proxy/management_endpoints/common_daily_activity.py index 79882909c23..ba41852f6d8 100644 --- a/litellm/proxy/management_endpoints/common_daily_activity.py +++ b/litellm/proxy/management_endpoints/common_daily_activity.py @@ -132,13 +132,11 @@ def update_breakdown_metrics( ), ) ) - breakdown.models[record.model].api_key_breakdown[record.api_key].metrics = ( - update_metrics( - breakdown.models[record.model] - .api_key_breakdown[record.api_key] - .metrics, - record, - ) + breakdown.models[record.model].api_key_breakdown[ + record.api_key + ].metrics = update_metrics( + breakdown.models[record.model].api_key_breakdown[record.api_key].metrics, + record, ) # Update model group breakdown @@ -247,11 +245,11 @@ def update_breakdown_metrics( ), ) ) - breakdown.providers[provider].api_key_breakdown[record.api_key].metrics = ( - update_metrics( - breakdown.providers[provider].api_key_breakdown[record.api_key].metrics, - record, - ) + breakdown.providers[provider].api_key_breakdown[ + record.api_key + ].metrics = update_metrics( + breakdown.providers[provider].api_key_breakdown[record.api_key].metrics, + record, ) # Update endpoint breakdown @@ -338,13 +336,11 @@ def update_breakdown_metrics( ), ) ) - breakdown.entities[entity_value].api_key_breakdown[record.api_key].metrics = ( - update_metrics( - breakdown.entities[entity_value] - .api_key_breakdown[record.api_key] - .metrics, - record, - ) + breakdown.entities[entity_value].api_key_breakdown[ + record.api_key + ].metrics = update_metrics( + breakdown.entities[entity_value].api_key_breakdown[record.api_key].metrics, + record, ) return breakdown diff --git a/litellm/proxy/management_endpoints/customer_endpoints.py b/litellm/proxy/management_endpoints/customer_endpoints.py index 50a1bc23a6d..ecc338c2052 100644 --- a/litellm/proxy/management_endpoints/customer_endpoints.py +++ b/litellm/proxy/management_endpoints/customer_endpoints.py @@ -342,7 +342,8 @@ async def new_end_user( budget_record = await BudgetRepository(prisma_client).table.create( data={ **_new_budget.model_dump(exclude_unset=True), - "created_by": user_api_key_dict.user_id or litellm_proxy_admin_name, # type: ignore + "created_by": user_api_key_dict.user_id + or litellm_proxy_admin_name, # type: ignore "updated_by": user_api_key_dict.user_id or litellm_proxy_admin_name, } @@ -563,10 +564,14 @@ async def update_end_user( # get non default values for key non_default_values = {} for k, v in data_json.items(): - if v is not None and v not in ( - [], - {}, - 0, + if ( + v is not None + and v + not in ( + [], + {}, + 0, + ) ): # models default to [], spend defaults to 0, we should not reset these values non_default_values[k] = v @@ -655,7 +660,9 @@ async def update_end_user( update_end_user_table_data["user_id"] = data.user_id # type: ignore verbose_proxy_logger.debug("In update customer, user_id condition block.") response = await EndUserRepository(prisma_client).table.update( - where={"user_id": data.user_id}, data=update_end_user_table_data, include={"litellm_budget_table": True, "object_permission": True} # type: ignore + where={"user_id": data.user_id}, + data=update_end_user_table_data, + include={"litellm_budget_table": True, "object_permission": True}, # type: ignore ) if response is None: raise ValueError( diff --git a/litellm/proxy/management_endpoints/internal_user_endpoints.py b/litellm/proxy/management_endpoints/internal_user_endpoints.py index 6d7f565fb85..8548d1c672c 100644 --- a/litellm/proxy/management_endpoints/internal_user_endpoints.py +++ b/litellm/proxy/management_endpoints/internal_user_endpoints.py @@ -746,7 +746,7 @@ def _build_user_info_response( user_info = {"spend": spend} returned_keys = _process_keys_for_user_info(keys=keys, all_teams=teams_1) - team_list.sort(key=lambda x: (getattr(x, "team_alias", "") or "")) + team_list.sort(key=lambda x: getattr(x, "team_alias", "") or "") _user_info = ( user_info.model_dump() if isinstance(user_info, BaseModel) else user_info @@ -1053,7 +1053,7 @@ async def _get_user_info_for_proxy_admin(user_api_key_dict: UserAPIKeyAuth): # cast all teams to LiteLLM_TeamTable _teams_in_db: List = results[0]["teams"] or [] _teams_in_db = [LiteLLM_TeamTable(**team) for team in _teams_in_db] - _teams_in_db.sort(key=lambda x: (getattr(x, "team_alias", "") or "")) + _teams_in_db.sort(key=lambda x: getattr(x, "team_alias", "") or "") returned_keys = _process_keys_for_user_info(keys=keys_in_db, all_teams=_teams_in_db) # Get admin's own user_id and user_info @@ -1705,7 +1705,8 @@ async def bulk_user_update( try: # Perform bulk database update await UserRepository(prisma_client).table.update_many( - where={}, data=non_default_values # Update all users + where={}, + data=non_default_values, # Update all users ) # Create individual success results diff --git a/litellm/proxy/management_endpoints/key_management_endpoints.py b/litellm/proxy/management_endpoints/key_management_endpoints.py index cd40f3155ee..db205803a47 100644 --- a/litellm/proxy/management_endpoints/key_management_endpoints.py +++ b/litellm/proxy/management_endpoints/key_management_endpoints.py @@ -229,10 +229,10 @@ def _is_allowed_to_make_key_request( return True if user_id is not None: - assert ( - user_id == user_api_key_dict.user_id - ), "User can only create keys for themselves. Got user_id={}, Your ID={}".format( - user_id, user_api_key_dict.user_id + assert user_id == user_api_key_dict.user_id, ( + "User can only create keys for themselves. Got user_id={}, Your ID={}".format( + user_id, user_api_key_dict.user_id + ) ) if team_id is not None: @@ -382,7 +382,9 @@ def _personal_key_generation_check( ): return True - _personal_key_generation = litellm.key_generation_settings["personal_key_generation"] # type: ignore + _personal_key_generation = litellm.key_generation_settings[ + "personal_key_generation" + ] # type: ignore _personal_key_membership_check( user_api_key_dict, @@ -963,9 +965,7 @@ async def _common_key_generation_helper( response = GenerateKeyResponse(**response) - response.token = ( - response.token_id - ) # remap token to use the hash, and leave the key in the `key` field [TODO]: clean up generate_key_helper_fn to do this + response.token = response.token_id # remap token to use the hash, and leave the key in the `key` field [TODO]: clean up generate_key_helper_fn to do this asyncio.create_task( KeyManagementEventHooks.async_key_generated_hook( @@ -2052,12 +2052,14 @@ async def _process_single_key_update( # Check team member permissions if prisma_client is not None: - await TeamMemberPermissionChecks.can_team_member_execute_key_management_endpoint( - user_api_key_dict=user_api_key_dict, - route=KeyManagementRoutes.KEY_UPDATE, - prisma_client=prisma_client, - existing_key_row=existing_key_row, - user_api_key_cache=user_api_key_cache, + await ( + TeamMemberPermissionChecks.can_team_member_execute_key_management_endpoint( + user_api_key_dict=user_api_key_dict, + route=KeyManagementRoutes.KEY_UPDATE, + prisma_client=prisma_client, + existing_key_row=existing_key_row, + user_api_key_cache=user_api_key_cache, + ) ) # Custom key update hook @@ -2968,12 +2970,14 @@ async def bulk_update_team_keys( models=[], ) ) - await TeamMemberPermissionChecks.can_team_member_execute_key_management_endpoint( - user_api_key_dict=user_api_key_dict, - route=KeyManagementRoutes.KEY_UPDATE, - prisma_client=prisma_client, - existing_key_row=auth_anchor, - user_api_key_cache=user_api_key_cache, + await ( + TeamMemberPermissionChecks.can_team_member_execute_key_management_endpoint( + user_api_key_dict=user_api_key_dict, + route=KeyManagementRoutes.KEY_UPDATE, + prisma_client=prisma_client, + existing_key_row=auth_anchor, + user_api_key_cache=user_api_key_cache, + ) ) # Block metadata.allowed_passthrough_routes for non-admins — the runtime @@ -3980,10 +3984,10 @@ async def delete_verification_tokens( try: if prisma_client: tokens = [_hash_token_if_needed(token=key) for key in tokens] - _keys_being_deleted: List[LiteLLM_VerificationToken] = ( - await VerificationTokenRepository(prisma_client).table.find_many( - where={"token": {"in": tokens}} - ) + _keys_being_deleted: List[ + LiteLLM_VerificationToken + ] = await VerificationTokenRepository(prisma_client).table.find_many( + where={"token": {"in": tokens}} ) if len(_keys_being_deleted) == 0: @@ -4670,12 +4674,14 @@ async def regenerate_key_fn( ) # check if user has permission to regenerate key - await TeamMemberPermissionChecks.can_team_member_execute_key_management_endpoint( - user_api_key_dict=user_api_key_dict, - route=KeyManagementRoutes.KEY_REGENERATE, - prisma_client=prisma_client, - existing_key_row=_key_in_db, - user_api_key_cache=user_api_key_cache, + await ( + TeamMemberPermissionChecks.can_team_member_execute_key_management_endpoint( + user_api_key_dict=user_api_key_dict, + route=KeyManagementRoutes.KEY_REGENERATE, + prisma_client=prisma_client, + existing_key_row=_key_in_db, + user_api_key_cache=user_api_key_cache, + ) ) # check if user has ownership permission to regenerate key @@ -5992,7 +5998,8 @@ async def block_key( ) record = await VerificationTokenRepository(prisma_client).table.update( - where={"token": hashed_token}, data={"blocked": True} # type: ignore + where={"token": hashed_token}, + data={"blocked": True}, # type: ignore ) ## UPDATE KEY CACHE - invalidate so next read re-fetches from DB @@ -6106,7 +6113,8 @@ async def unblock_key( ) record = await VerificationTokenRepository(prisma_client).table.update( - where={"token": hashed_token}, data={"blocked": False} # type: ignore + where={"token": hashed_token}, + data={"blocked": False}, # type: ignore ) ## UPDATE KEY CACHE - invalidate so next read re-fetches from DB diff --git a/litellm/proxy/management_endpoints/mcp_management_endpoints.py b/litellm/proxy/management_endpoints/mcp_management_endpoints.py index f896047a219..4ab308990b5 100644 --- a/litellm/proxy/management_endpoints/mcp_management_endpoints.py +++ b/litellm/proxy/management_endpoints/mcp_management_endpoints.py @@ -2540,9 +2540,9 @@ if MCP_AVAILABLE: if "litellm_settings" not in config or config["litellm_settings"] is None: config["litellm_settings"] = {} - config["litellm_settings"][ - "public_mcp_servers" - ] = litellm.public_mcp_servers + config["litellm_settings"]["public_mcp_servers"] = ( + litellm.public_mcp_servers + ) # Save the updated config await proxy_config.save_config(new_config=config) diff --git a/litellm/proxy/management_endpoints/model_management_endpoints.py b/litellm/proxy/management_endpoints/model_management_endpoints.py index def6e271635..df4d46b9098 100644 --- a/litellm/proxy/management_endpoints/model_management_endpoints.py +++ b/litellm/proxy/management_endpoints/model_management_endpoints.py @@ -518,7 +518,9 @@ async def _add_model_to_db( _data: dict = { "model_id": model_params.model_info.id, "model_name": model_params.model_name, - "litellm_params": model_params.litellm_params.model_dump_json(exclude_none=True), # type: ignore + "litellm_params": model_params.litellm_params.model_dump_json( + exclude_none=True + ), # type: ignore "model_info": model_params.model_info.model_dump_json( # type: ignore exclude_none=True ), diff --git a/litellm/proxy/management_endpoints/organization_endpoints.py b/litellm/proxy/management_endpoints/organization_endpoints.py index 99659121b27..a45382b54d0 100644 --- a/litellm/proxy/management_endpoints/organization_endpoints.py +++ b/litellm/proxy/management_endpoints/organization_endpoints.py @@ -1299,7 +1299,9 @@ async def add_member_to_organization( user_email=member.user_email, ) - _returned_user = await prisma_client.insert_data(data=new_user_defaults, table_name="user") # type: ignore + _returned_user = await prisma_client.insert_data( + data=new_user_defaults, table_name="user" + ) # type: ignore if _returned_user is not None: user_object = LiteLLM_UserTable(**_returned_user.model_dump()) elif existing_user_email_row is not None and len(existing_user_email_row) > 1: diff --git a/litellm/proxy/management_endpoints/team_callback_endpoints.py b/litellm/proxy/management_endpoints/team_callback_endpoints.py index 0c11507697d..94c84387be3 100644 --- a/litellm/proxy/management_endpoints/team_callback_endpoints.py +++ b/litellm/proxy/management_endpoints/team_callback_endpoints.py @@ -251,7 +251,8 @@ async def add_team_callbacks( team_metadata_json = json.dumps(team_metadata) # update team_metadata new_team_row = await TeamRepository(prisma_client).table.update( - where={"team_id": team_id}, data={"metadata": team_metadata_json} # type: ignore + where={"team_id": team_id}, + data={"metadata": team_metadata_json}, # type: ignore ) await _emit_team_callback_audit_log( @@ -355,7 +356,8 @@ async def disable_team_logging( # Update team in database updated_team = await TeamRepository(prisma_client).table.update( - where={"team_id": team_id}, data={"metadata": team_metadata_json} # type: ignore + where={"team_id": team_id}, + data={"metadata": team_metadata_json}, # type: ignore ) if updated_team is None: diff --git a/litellm/proxy/management_endpoints/team_endpoints.py b/litellm/proxy/management_endpoints/team_endpoints.py index 3d90e7b5ab9..249cfdae4eb 100644 --- a/litellm/proxy/management_endpoints/team_endpoints.py +++ b/litellm/proxy/management_endpoints/team_endpoints.py @@ -281,9 +281,9 @@ class TeamMemberBudgetHandler: # Add team_member_budget_id as metadata field to team table if new_team_data_json.get("metadata") is None: new_team_data_json["metadata"] = {} - new_team_data_json["metadata"][ - "team_member_budget_id" - ] = team_member_budget_table.budget_id + new_team_data_json["metadata"]["team_member_budget_id"] = ( + team_member_budget_table.budget_id + ) # Remove team member fields from new_team_data_json TeamMemberBudgetHandler._clean_team_member_fields(new_team_data_json) @@ -3889,7 +3889,8 @@ async def block_team( ) record = await TeamRepository(prisma_client).table.update( - where={"team_id": data.team_id}, data={"blocked": True} # type: ignore + where={"team_id": data.team_id}, + data={"blocked": True}, # type: ignore ) return record @@ -3941,7 +3942,8 @@ async def unblock_team( ) record = await TeamRepository(prisma_client).table.update( - where={"team_id": data.team_id}, data={"blocked": False} # type: ignore + where={"team_id": data.team_id}, + data={"blocked": False}, # type: ignore ) return record @@ -4651,7 +4653,7 @@ async def list_team( verbose_proxy_logger.exception(team_exception) continue # Sort the responses by team_alias - returned_responses.sort(key=lambda x: (getattr(x, "team_alias", "") or "")) + returned_responses.sort(key=lambda x: getattr(x, "team_alias", "") or "") if organization_id is not None: if organization_id == SpecialManagementEndpointEnums.DEFAULT_ORGANIZATION.value: @@ -4692,7 +4694,9 @@ async def get_paginated_teams( # Get paginated teams teams = await TeamRepository(prisma_client).table.find_many( - skip=skip, take=page_size, order={"team_alias": "asc"} # Sort by team_alias + skip=skip, + take=page_size, + order={"team_alias": "asc"}, # Sort by team_alias ) return teams, total_count except Exception as e: diff --git a/litellm/proxy/management_endpoints/ui_sso.py b/litellm/proxy/management_endpoints/ui_sso.py index 199de54ff09..480861fb517 100644 --- a/litellm/proxy/management_endpoints/ui_sso.py +++ b/litellm/proxy/management_endpoints/ui_sso.py @@ -2777,7 +2777,9 @@ class SSOAuthenticationHandler: state_only_params[key] = value # Get the redirect response from fastapi-sso with only state param - redirect_response = await generic_sso.get_login_redirect(**state_only_params) # type: ignore + redirect_response = await generic_sso.get_login_redirect( + **state_only_params + ) # type: ignore # If PKCE is enabled, add PKCE parameters to the redirect URL if code_verifier and "state" in redirect_params: @@ -3204,7 +3206,9 @@ class SSOAuthenticationHandler: user_id = getattr(result, "id", None) user_email = normalize_email(getattr(result, "email", None)) if user_role is None: - _role_from_attr = getattr(result, generic_user_role_attribute_name, None) # type: ignore + _role_from_attr = getattr( + result, generic_user_role_attribute_name, None + ) # type: ignore if _role_from_attr is not None: # Convert enum to string if needed user_role = ( @@ -4539,14 +4543,16 @@ async def debug_sso_callback(request: Request): ) elif generic_client_id is not None: - result, received_response, access_token_payload = ( - await get_generic_sso_response( - request=request, - jwt_handler=jwt_handler, - generic_client_id=generic_client_id, - redirect_url=redirect_url, - sso_jwt_handler=sso_jwt_handler, - ) + ( + result, + received_response, + access_token_payload, + ) = await get_generic_sso_response( + request=request, + jwt_handler=jwt_handler, + generic_client_id=generic_client_id, + redirect_url=redirect_url, + sso_jwt_handler=sso_jwt_handler, ) # If result is None, return a basic error message diff --git a/litellm/proxy/management_endpoints/usage_endpoints/ai_usage_chat.py b/litellm/proxy/management_endpoints/usage_endpoints/ai_usage_chat.py index a50ce1d3c48..c9884c02e14 100644 --- a/litellm/proxy/management_endpoints/usage_endpoints/ai_usage_chat.py +++ b/litellm/proxy/management_endpoints/usage_endpoints/ai_usage_chat.py @@ -197,8 +197,7 @@ def _build_system_prompt(is_admin: bool) -> str: """Build role-appropriate system prompt with today's date.""" tool_desc = _TOOL_DESCRIPTIONS_ADMIN if is_admin else _TOOL_DESCRIPTIONS_BASE return ( - f"{_SYSTEM_PROMPT_BASE}\n\n{tool_desc}" - f"Today's date: {date.today().isoformat()}" + f"{_SYSTEM_PROMPT_BASE}\n\n{tool_desc}Today's date: {date.today().isoformat()}" ) @@ -352,7 +351,9 @@ def _summarise_usage_data(data: Dict[str, Any]) -> str: model_lines = _ranked_lines( models, - lambda n, d: f" - {n}: ${d['spend']:.4f} ({int(d['api_requests'])} reqs, {int(d['total_tokens'])} tokens)", + lambda n, d: ( + f" - {n}: ${d['spend']:.4f} ({int(d['api_requests'])} reqs, {int(d['total_tokens'])} tokens)" + ), TOP_N_MODELS, ) provider_lines = _ranked_lines( diff --git a/litellm/proxy/management_helpers/object_permission_utils.py b/litellm/proxy/management_helpers/object_permission_utils.py index c29d1ac178d..0a61fc5d3dd 100644 --- a/litellm/proxy/management_helpers/object_permission_utils.py +++ b/litellm/proxy/management_helpers/object_permission_utils.py @@ -361,10 +361,10 @@ async def _resolve_team_allowed_mcp_servers( ) direct_servers: List[str] = team_object_permission.mcp_servers or [] - access_group_servers: List[str] = ( - await MCPRequestHandler._get_mcp_servers_from_access_groups( - team_object_permission.mcp_access_groups or [] - ) + access_group_servers: List[ + str + ] = await MCPRequestHandler._get_mcp_servers_from_access_groups( + team_object_permission.mcp_access_groups or [] ) raw_tool_perms = team_object_permission.mcp_tool_permissions or {} if isinstance(raw_tool_perms, str): diff --git a/litellm/proxy/management_helpers/utils.py b/litellm/proxy/management_helpers/utils.py index 830d6f84b85..4ce8633ed57 100644 --- a/litellm/proxy/management_helpers/utils.py +++ b/litellm/proxy/management_helpers/utils.py @@ -256,7 +256,9 @@ async def add_new_member( isinstance(existing_user_row, list) and len(existing_user_row) == 0 ): new_user_defaults["teams"] = [team_id] - _returned_user = await prisma_client.insert_data(data=new_user_defaults, table_name="user") # type: ignore + _returned_user = await prisma_client.insert_data( + data=new_user_defaults, table_name="user" + ) # type: ignore if _returned_user is not None: returned_user = LiteLLM_UserTable(**_returned_user.model_dump()) @@ -433,10 +435,12 @@ async def send_management_endpoint_alert( # replace all "_" with " " and capitalize event_name = _event_name.replace("_", " ").title() - await proxy_logging_obj.slack_alerting_instance.send_virtual_key_event_slack( - key_event=key_event, - event_name=event_name, - alert_type=_event_name, + await ( + proxy_logging_obj.slack_alerting_instance.send_virtual_key_event_slack( + key_event=key_event, + event_name=event_name, + alert_type=_event_name, + ) ) diff --git a/litellm/proxy/openai_files_endpoints/files_endpoints.py b/litellm/proxy/openai_files_endpoints/files_endpoints.py index 7c19804dde3..d8f8726b6b6 100644 --- a/litellm/proxy/openai_files_endpoints/files_endpoints.py +++ b/litellm/proxy/openai_files_endpoints/files_endpoints.py @@ -270,7 +270,9 @@ async def route_create_file( _create_file_request.update(llm_provider_config) _create_file_request.pop("custom_llm_provider", None) # type: ignore # for now use custom_llm_provider=="openai" -> this will change as LiteLLM adds more providers for acreate_batch - response = await litellm.acreate_file(**_create_file_request, custom_llm_provider=custom_llm_provider) # type: ignore + response = await litellm.acreate_file( + **_create_file_request, custom_llm_provider=custom_llm_provider + ) # type: ignore return response @@ -1024,7 +1026,9 @@ async def get_file( # data was initialized with {"file_id": file_id} data.pop("file_id", None) response = await litellm.afile_retrieve( - custom_llm_provider=custom_llm_provider, file_id=file_id, **data # type: ignore + custom_llm_provider=custom_llm_provider, + file_id=file_id, + **data, # type: ignore ) ### ALERTING ### @@ -1228,7 +1232,9 @@ async def delete_file( else: data.pop("file_id", None) response = await litellm.afile_delete( - custom_llm_provider=custom_llm_provider, file_id=file_id, **data # type: ignore + custom_llm_provider=custom_llm_provider, + file_id=file_id, + **data, # type: ignore ) ### ALERTING ### @@ -1410,7 +1416,9 @@ async def list_files( prepare_data_with_credentials(data=data, credentials=team_credentials) response = await litellm.afile_list( - custom_llm_provider=custom_llm_provider, purpose=purpose, **data # type: ignore + custom_llm_provider=custom_llm_provider, + purpose=purpose, + **data, # type: ignore ) if response is None: diff --git a/litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py b/litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py index c7db818a07e..5e688702f13 100644 --- a/litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py +++ b/litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py @@ -2089,7 +2089,9 @@ class BaseOpenAIPassThroughHandler: custom_llm_provider=( custom_llm_provider.value if hasattr(custom_llm_provider, "value") - else str(custom_llm_provider) if custom_llm_provider else None + else str(custom_llm_provider) + if custom_llm_provider + else None ), ) # dynamically construct pass-through endpoint based on incoming path received_value = await endpoint_func( diff --git a/litellm/proxy/pass_through_endpoints/llm_provider_handlers/openai_passthrough_logging_handler.py b/litellm/proxy/pass_through_endpoints/llm_provider_handlers/openai_passthrough_logging_handler.py index b77c6e2f655..1d76165c30c 100644 --- a/litellm/proxy/pass_through_endpoints/llm_provider_handlers/openai_passthrough_logging_handler.py +++ b/litellm/proxy/pass_through_endpoints/llm_provider_handlers/openai_passthrough_logging_handler.py @@ -478,7 +478,9 @@ class OpenAIPassthroughLoggingHandler(BasePassthroughLoggingHandler): endpoint_type = ( "chat_completions" if is_chat_completions - else "image_generation" if is_image_generation else "image_editing" + else "image_generation" + if is_image_generation + else "image_editing" ) verbose_proxy_logger.debug( f"OpenAI passthrough cost tracking - Endpoint: {endpoint_type}, Model: {model}, Cost: ${response_cost:.6f}" diff --git a/litellm/proxy/pass_through_endpoints/llm_provider_handlers/vertex_passthrough_logging_handler.py b/litellm/proxy/pass_through_endpoints/llm_provider_handlers/vertex_passthrough_logging_handler.py index 73d4245670a..538267e9c84 100644 --- a/litellm/proxy/pass_through_endpoints/llm_provider_handlers/vertex_passthrough_logging_handler.py +++ b/litellm/proxy/pass_through_endpoints/llm_provider_handlers/vertex_passthrough_logging_handler.py @@ -219,9 +219,9 @@ class VertexPassthroughLoggingHandler: kwargs["response_cost"] = response_cost kwargs["model"] = "vertex_ai/search_api" logging_obj.model_call_details.setdefault("litellm_params", {}) - logging_obj.model_call_details["litellm_params"][ - "base_model" - ] = "vertex_ai/search_api" + logging_obj.model_call_details["litellm_params"]["base_model"] = ( + "vertex_ai/search_api" + ) logging_obj.model_call_details["response_cost"] = response_cost return { diff --git a/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py b/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py index b84746758fb..a7c7786aa91 100644 --- a/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py +++ b/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py @@ -484,10 +484,10 @@ class HttpPassThroughEndpointHelpers(BasePassthroughUtils): for field_name, field_value in form_data.items(): if isinstance(field_value, (StarletteUploadFile, UploadFile)): - files[field_name] = ( - await HttpPassThroughEndpointHelpers._build_request_files_from_upload_file( - upload_file=field_value - ) + files[ + field_name + ] = await HttpPassThroughEndpointHelpers._build_request_files_from_upload_file( + upload_file=field_value ) else: form_data_dict[field_name] = field_value diff --git a/litellm/proxy/prompts/prompt_registry.py b/litellm/proxy/prompts/prompt_registry.py index 25368c2a834..ae5ce177853 100644 --- a/litellm/proxy/prompts/prompt_registry.py +++ b/litellm/proxy/prompts/prompt_registry.py @@ -97,9 +97,9 @@ class InMemoryPromptRegistry: Prompt id to Prompt object mapping """ - self.prompt_id_to_custom_prompt: Dict[str, Optional[CustomPromptManagement]] = ( - {} - ) + self.prompt_id_to_custom_prompt: Dict[ + str, Optional[CustomPromptManagement] + ] = {} """ Guardrail id to CustomGuardrail object mapping """ @@ -142,7 +142,9 @@ class InMemoryPromptRegistry: raise ValueError( f"CustomPromptManagement is required, got {type(custom_prompt_callback)}" ) - litellm.logging_callback_manager.add_litellm_callback(custom_prompt_callback) # type: ignore + litellm.logging_callback_manager.add_litellm_callback( + custom_prompt_callback + ) # type: ignore else: raise ValueError(f"Unsupported prompt: {prompt_integration}") diff --git a/litellm/proxy/proxy_cli.py b/litellm/proxy/proxy_cli.py index d0281885482..a8efbadb253 100644 --- a/litellm/proxy/proxy_cli.py +++ b/litellm/proxy/proxy_cli.py @@ -438,7 +438,9 @@ class ProxyInitializationHelpers: _endpoint_str = ( f"curl --location 'http://0.0.0.0:{port}/chat/completions' \\" ) - curl_command = _endpoint_str + """ + curl_command = ( + _endpoint_str + + """ --header 'Content-Type: application/json' \\ --data ' { "model": "gpt-3.5-turbo", @@ -451,6 +453,7 @@ class ProxyInitializationHelpers: }' \n """ + ) print() print( '\033[1;34mLiteLLM: Test your local proxy with: "litellm --test" This runs an openai.ChatCompletion request to your proxy [In a new terminal tab]\033[0m\n' diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index cdbc510afe0..b0beaae02cf 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -673,7 +673,21 @@ _description = ( def cleanup_router_config_variables(): - global master_key, user_config_file_path, otel_logging, user_custom_auth, user_custom_auth_path, user_custom_key_generate, user_custom_key_update, user_custom_sso, user_custom_ui_sso_sign_in_handler, use_background_health_checks, use_shared_health_check, health_check_interval, health_check_concurrency, prisma_client + global \ + master_key, \ + user_config_file_path, \ + otel_logging, \ + user_custom_auth, \ + user_custom_auth_path, \ + user_custom_key_generate, \ + user_custom_key_update, \ + user_custom_sso, \ + user_custom_ui_sso_sign_in_handler, \ + use_background_health_checks, \ + use_shared_health_check, \ + health_check_interval, \ + health_check_concurrency, \ + prisma_client # Set all variables to None master_key = None @@ -693,7 +707,12 @@ def cleanup_router_config_variables(): async def proxy_shutdown_event(): - global prisma_client, master_key, user_custom_auth, user_custom_key_generate, user_custom_key_update + global \ + prisma_client, \ + master_key, \ + user_custom_auth, \ + user_custom_key_generate, \ + user_custom_key_update verbose_proxy_logger.info("Shutting down LiteLLM Proxy Server") if prisma_client: verbose_proxy_logger.debug("Disconnecting from Prisma") @@ -763,7 +782,22 @@ async def _initialize_shared_aiohttp_session(): @asynccontextmanager async def proxy_startup_event(app: FastAPI): - global prisma_client, master_key, use_background_health_checks, llm_router, llm_model_list, general_settings, proxy_budget_rescheduler_min_time, proxy_budget_rescheduler_max_time, litellm_proxy_admin_name, db_writer_client, store_model_in_db, premium_user, _license_check, proxy_batch_polling_interval, shared_aiohttp_session + global \ + prisma_client, \ + master_key, \ + use_background_health_checks, \ + llm_router, \ + llm_model_list, \ + general_settings, \ + proxy_budget_rescheduler_min_time, \ + proxy_budget_rescheduler_max_time, \ + litellm_proxy_admin_name, \ + db_writer_client, \ + store_model_in_db, \ + premium_user, \ + _license_check, \ + proxy_batch_polling_interval, \ + shared_aiohttp_session import json init_verbose_loggers() @@ -1917,9 +1951,9 @@ redis_usage_cache: Optional[RedisCache] = ( None # redis cache used for tracking spend, tpm/rpm limits ) polling_via_cache_enabled: Union[Literal["all"], List[str], bool] = False -native_background_mode: List[str] = ( - [] -) # Models that should use native provider background mode instead of polling +native_background_mode: List[ + str +] = [] # Models that should use native provider background mode instead of polling polling_cache_ttl: int = 3600 # Default 1 hour TTL for polling cache user_custom_auth = None user_custom_key_generate = None @@ -3226,13 +3260,9 @@ def _write_health_state_to_router_cache( exception_status = getattr(original_exception, "status_code", 500) - if ( - llm_router.health_check_ignore_transient_errors - and exception_status - in ( - 429, - 408, - ) + if llm_router.health_check_ignore_transient_errors and exception_status in ( + 429, + 408, ): continue @@ -4061,7 +4091,9 @@ class ProxyConfig: # Cast to SearchToolTypedDict for type safety try: - search_tool_typed: SearchToolTypedDict = SearchToolTypedDict(**search_tool) # type: ignore + search_tool_typed: SearchToolTypedDict = SearchToolTypedDict( + **search_tool + ) # type: ignore search_tools_parsed.append(search_tool_typed) except Exception as e: verbose_proxy_logger.error( @@ -4136,7 +4168,35 @@ class ProxyConfig: """ Load config values into proxy global state """ - global master_key, user_config_file_path, otel_logging, user_custom_auth, user_custom_auth_path, user_custom_key_generate, user_custom_key_update, user_custom_sso, user_custom_ui_sso_sign_in_handler, use_background_health_checks, use_shared_health_check, health_check_interval, health_check_concurrency, use_queue, proxy_budget_rescheduler_max_time, proxy_budget_rescheduler_min_time, ui_access_mode, litellm_master_key_hash, proxy_batch_write_at, disable_spend_logs, prompt_injection_detection_obj, redis_usage_cache, store_model_in_db, premium_user, open_telemetry_logger, health_check_details, proxy_batch_polling_interval, config_passthrough_endpoints + global \ + master_key, \ + user_config_file_path, \ + otel_logging, \ + user_custom_auth, \ + user_custom_auth_path, \ + user_custom_key_generate, \ + user_custom_key_update, \ + user_custom_sso, \ + user_custom_ui_sso_sign_in_handler, \ + use_background_health_checks, \ + use_shared_health_check, \ + health_check_interval, \ + health_check_concurrency, \ + use_queue, \ + proxy_budget_rescheduler_max_time, \ + proxy_budget_rescheduler_min_time, \ + ui_access_mode, \ + litellm_master_key_hash, \ + proxy_batch_write_at, \ + disable_spend_logs, \ + prompt_injection_detection_obj, \ + redis_usage_cache, \ + store_model_in_db, \ + premium_user, \ + open_telemetry_logger, \ + health_check_details, \ + proxy_batch_polling_interval, \ + config_passthrough_endpoints config: dict = await self.get_config(config_file_path=config_file_path) @@ -4413,7 +4473,10 @@ class ProxyConfig: pass elif key == "responses": # Initialize global polling via cache settings - global polling_via_cache_enabled, native_background_mode, polling_cache_ttl + global \ + polling_via_cache_enabled, \ + native_background_mode, \ + polling_cache_ttl background_mode = value.get("background_mode", {}) polling_via_cache_enabled = background_mode.get( "polling_via_cache", False @@ -5048,8 +5111,7 @@ class ProxyConfig: ### LOAD FROM GOOGLE KMS ### load_google_kms(use_google_kms=True) elif ( - key_management_system - == KeyManagementSystem.AWS_SECRET_MANAGER.value # noqa: F405 + key_management_system == KeyManagementSystem.AWS_SECRET_MANAGER.value # noqa: F405 ): from litellm.secret_managers.aws_secret_manager_v2 import ( AWSSecretsManagerV2, @@ -6584,10 +6646,10 @@ class ProxyConfig: ) try: - guardrails_in_db: List[Guardrail] = ( - await GuardrailRegistry.get_all_guardrails_from_db( - prisma_client=prisma_client - ) + guardrails_in_db: List[ + Guardrail + ] = await GuardrailRegistry.get_all_guardrails_from_db( + prisma_client=prisma_client ) verbose_proxy_logger.debug( "guardrails from the DB %s", str(guardrails_in_db) @@ -6899,7 +6961,23 @@ async def initialize( use_queue=False, config=None, ): - global user_model, user_api_base, user_debug, user_detailed_debug, user_user_max_tokens, user_request_timeout, user_temperature, user_telemetry, user_headers, experimental, llm_model_list, llm_router, general_settings, master_key, user_custom_auth, prisma_client + global \ + user_model, \ + user_api_base, \ + user_debug, \ + user_detailed_debug, \ + user_user_max_tokens, \ + user_request_timeout, \ + user_temperature, \ + user_telemetry, \ + user_headers, \ + experimental, \ + llm_model_list, \ + llm_router, \ + general_settings, \ + master_key, \ + user_custom_auth, \ + prisma_client from litellm.proxy.common_utils.banner import show_banner show_banner() @@ -7877,7 +7955,8 @@ class ProxyStartupEvent: teams_pydantic_obj = [NewUserRequestTeam(**team) for team in _teams] await update_default_team_member_budget( - teams=teams_pydantic_obj, user_api_key_dict=UserAPIKeyAuth(token=hash_token(master_key)) # type: ignore + teams=teams_pydantic_obj, + user_api_key_dict=UserAPIKeyAuth(token=hash_token(master_key)), # type: ignore ) @classmethod @@ -8710,7 +8789,13 @@ async def model_list( Hiding is presentation-only: a hidden model can still be called directly. """ - global llm_model_list, general_settings, llm_router, prisma_client, user_api_key_cache, proxy_logging_obj + global \ + llm_model_list, \ + general_settings, \ + llm_router, \ + prisma_client, \ + user_api_key_cache, \ + proxy_logging_obj settings = cast(dict[str, object], general_settings) # any-ok: legacy settings @@ -8887,7 +8972,13 @@ async def model_info( scoping, health filtering, paused deployments) drives both endpoints; the listing's public id must resolve to the same internal deployment here. """ - global llm_model_list, general_settings, llm_router, prisma_client, user_api_key_cache, proxy_logging_obj + global \ + llm_model_list, \ + general_settings, \ + llm_router, \ + prisma_client, \ + user_api_key_cache, \ + proxy_logging_obj settings = cast(dict[str, object], general_settings) # any-ok: legacy settings @@ -9038,9 +9129,9 @@ async def chat_completion( hasattr(user_api_key_dict, "organization_alias") and user_api_key_dict.organization_alias is not None ): - data["metadata"][ - "user_api_key_org_alias" - ] = user_api_key_dict.organization_alias + data["metadata"]["user_api_key_org_alias"] = ( + user_api_key_dict.organization_alias + ) if ( hasattr(user_api_key_dict, "agent_id") and user_api_key_dict.agent_id is not None @@ -9222,9 +9313,9 @@ async def completion( hasattr(user_api_key_dict, "organization_alias") and user_api_key_dict.organization_alias is not None ): - data["metadata"][ - "user_api_key_org_alias" - ] = user_api_key_dict.organization_alias + data["metadata"]["user_api_key_org_alias"] = ( + user_api_key_dict.organization_alias + ) if ( hasattr(user_api_key_dict, "agent_id") and user_api_key_dict.agent_id is not None @@ -9438,9 +9529,12 @@ async def embeddings( litellm_params = deployment.get("litellm_params", {}) or {} litellm_model = litellm_params.get("model", "") # Check if this provider supports token arrays - supports_token_arrays = litellm_model in litellm.open_ai_embedding_models or any( - litellm_model.startswith(provider) - for provider in LITELLM_EMBEDDING_PROVIDERS_SUPPORTING_INPUT_ARRAY_OF_TOKENS + supports_token_arrays = ( + litellm_model in litellm.open_ai_embedding_models + or any( + litellm_model.startswith(provider) + for provider in LITELLM_EMBEDDING_PROVIDERS_SUPPORTING_INPUT_ARRAY_OF_TOKENS + ) ) if not supports_token_arrays: # non-openai/azure embedding model called with token input - decode tokens @@ -9473,9 +9567,9 @@ async def embeddings( hasattr(user_api_key_dict, "organization_alias") and user_api_key_dict.organization_alias is not None ): - data["metadata"][ - "user_api_key_org_alias" - ] = user_api_key_dict.organization_alias + data["metadata"]["user_api_key_org_alias"] = ( + user_api_key_dict.organization_alias + ) if ( hasattr(user_api_key_dict, "agent_id") and user_api_key_dict.agent_id is not None @@ -12433,7 +12527,12 @@ async def model_info_v2( } ``` """ - global llm_model_list, general_settings, user_config_file_path, proxy_config, llm_router + global \ + llm_model_list, \ + general_settings, \ + user_config_file_path, \ + proxy_config, \ + llm_router # Return empty data array when no models are configured (graceful handling for fresh installs) if llm_router is None or not llm_router.model_list: @@ -13189,7 +13288,13 @@ async def model_info_v1( ``` """ - global llm_model_list, general_settings, user_config_file_path, proxy_config, llm_router, user_model + global \ + llm_model_list, \ + general_settings, \ + user_config_file_path, \ + proxy_config, \ + llm_router, \ + user_model # Unit tests call this handler directly; FastAPI normally resolves Query defaults. if not isinstance(include_team_models, bool): @@ -13531,7 +13636,12 @@ async def model_group_info( } ``` """ - global llm_model_list, general_settings, user_config_file_path, proxy_config, llm_router + global \ + llm_model_list, \ + general_settings, \ + user_config_file_path, \ + proxy_config, \ + llm_router # Return empty data array when no models are configured (graceful handling for fresh installs) if llm_model_list is None or llm_router is None or not llm_model_list: @@ -14923,7 +15033,14 @@ async def update_config( untouched — this endpoint never persists pre-existing YAML values to DB as a side effect of an unrelated update. """ - global llm_router, llm_model_list, general_settings, proxy_config, proxy_logging_obj, master_key, prisma_client + global \ + llm_router, \ + llm_model_list, \ + general_settings, \ + proxy_config, \ + proxy_logging_obj, \ + master_key, \ + prisma_client try: if user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN: raise HTTPException( @@ -15176,7 +15293,10 @@ async def update_config_general_settings( response = await ConfigRepository(prisma_client).table.upsert( where={"param_name": "general_settings"}, data={ - "create": {"param_name": "general_settings", "param_value": json.dumps(general_settings)}, # type: ignore + "create": { + "param_name": "general_settings", + "param_value": json.dumps(general_settings), + }, # type: ignore "update": {"param_value": json.dumps(general_settings)}, # type: ignore }, ) @@ -15432,9 +15552,9 @@ async def get_config_list( hasattr(sub_field_info, "description") and sub_field_info.description is not None ): - nested_fields[idx].field_description = ( - sub_field_info.description - ) + nested_fields[ + idx + ].field_description = sub_field_info.description idx += 1 _stored_in_db = None @@ -15551,7 +15671,10 @@ async def delete_config_general_settings( response = await ConfigRepository(prisma_client).table.upsert( where={"param_name": "general_settings"}, data={ - "create": {"param_name": "general_settings", "param_value": json.dumps(general_settings)}, # type: ignore + "create": { + "param_name": "general_settings", + "param_value": json.dumps(general_settings), + }, # type: ignore "update": {"param_value": json.dumps(general_settings)}, # type: ignore }, ) @@ -15619,9 +15742,9 @@ async def delete_callback( # Remove callback from success_callback list success_callbacks.remove(callback_name) - config.setdefault("litellm_settings", {})[ - "success_callback" - ] = success_callbacks + config.setdefault("litellm_settings", {})["success_callback"] = ( + success_callbacks + ) # Save the updated configuration await proxy_config.save_config(new_config=config) @@ -15665,7 +15788,13 @@ async def get_config(): # return the callbacks and the env variables for the callback """ - global llm_router, llm_model_list, general_settings, proxy_config, proxy_logging_obj, master_key + global \ + llm_router, \ + llm_model_list, \ + general_settings, \ + proxy_config, \ + proxy_logging_obj, \ + master_key try: all_available_callbacks = AllCallbacks() diff --git a/litellm/proxy/response_polling/background_streaming.py b/litellm/proxy/response_polling/background_streaming.py index a69e6734d71..aedfb26326a 100644 --- a/litellm/proxy/response_polling/background_streaming.py +++ b/litellm/proxy/response_polling/background_streaming.py @@ -92,9 +92,7 @@ async def background_streaming_task( # Process streaming response following OpenAI events format # https://platform.openai.com/docs/api-reference/responses-streaming output_items: dict[str, dict[str, Any]] = {} # Track output items by ID - accumulated_text = ( - {} - ) # Track accumulated text deltas by (item_id, content_index) + accumulated_text = {} # Track accumulated text deltas by (item_id, content_index) # ResponsesAPIResponse fields to extract from response.completed usage_data = None diff --git a/litellm/proxy/spend_tracking/spend_management_endpoints.py b/litellm/proxy/spend_tracking/spend_management_endpoints.py index 0ba77dcd2f0..29fc6d7c30f 100644 --- a/litellm/proxy/spend_tracking/spend_management_endpoints.py +++ b/litellm/proxy/spend_tracking/spend_management_endpoints.py @@ -536,9 +536,7 @@ async def get_global_activity_model( if db_response is None: return [] - model_ui_data: dict = ( - {} - ) # {"gpt-4": {"daily_data": [], "sum_api_requests": 0, "sum_total_tokens": 0}} + model_ui_data: dict = {} # {"gpt-4": {"daily_data": [], "sum_api_requests": 0, "sum_total_tokens": 0}} for row in db_response: _model = row["model_group"] @@ -690,9 +688,7 @@ async def get_global_activity_exceptions_per_deployment( if db_response is None: return [] - model_ui_data: dict = ( - {} - ) # {"gpt-4": {"daily_data": [], "sum_api_requests": 0, "sum_total_tokens": 0}} + model_ui_data: dict = {} # {"gpt-4": {"daily_data": [], "sum_api_requests": 0, "sum_total_tokens": 0}} for row in db_response: _model = row["api_base"] @@ -2218,9 +2214,7 @@ async def ui_view_request_response_for_request_id( request_id=request_id, ) - custom_loggers = ( - litellm.logging_callback_manager.get_active_additional_logging_utils_from_custom_logger() - ) + custom_loggers = litellm.logging_callback_manager.get_active_additional_logging_utils_from_custom_logger() start_date_obj: Optional[datetime] = None end_date_obj: Optional[datetime] = None if start_date is not None: @@ -2418,7 +2412,9 @@ async def view_spend_logs( ): result: dict = {} for record in response: - dt_object = datetime.strptime(str(record["startTime"]), "%Y-%m-%dT%H:%M:%S.%fZ") # type: ignore + dt_object = datetime.strptime( + str(record["startTime"]), "%Y-%m-%dT%H:%M:%S.%fZ" + ) # type: ignore date = dt_object.date() if date not in result: result[date] = {"users": {}, "models": {}} diff --git a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py index cefe349aade..674f7efd837 100644 --- a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py +++ b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py @@ -621,7 +621,8 @@ async def update_internal_user_settings( isinstance(team, NewUserRequestTeam) for team in settings.teams ): await update_default_team_member_budget( - settings.teams, user_api_key_dict=user_api_key_dict # type: ignore + settings.teams, + user_api_key_dict=user_api_key_dict, # type: ignore ) return await _update_litellm_setting( diff --git a/litellm/proxy/utils.py b/litellm/proxy/utils.py index 755602cbcc0..781f0e9f301 100644 --- a/litellm/proxy/utils.py +++ b/litellm/proxy/utils.py @@ -523,7 +523,9 @@ class ProxyLogging: or "outage_alerts" in self.alert_types or "region_outage_alerts" in self.alert_types ): - litellm.logging_callback_manager.add_litellm_callback(self.slack_alerting_instance) # type: ignore + litellm.logging_callback_manager.add_litellm_callback( + self.slack_alerting_instance + ) # type: ignore litellm.logging_callback_manager.add_litellm_success_callback( self.slack_alerting_instance.response_taking_too_long_callback ) @@ -1691,10 +1693,8 @@ class ProxyLogging: for callback in callbacks: if isinstance(callback, str): - resolved: Any = ( - litellm.litellm_core_utils.litellm_logging.get_custom_logger_compatible_class( - cast(_custom_logger_compatible_callbacks_literal, callback) - ) + resolved: Any = litellm.litellm_core_utils.litellm_logging.get_custom_logger_compatible_class( + cast(_custom_logger_compatible_callbacks_literal, callback) ) else: resolved = callback @@ -3627,7 +3627,9 @@ class PrismaClient: return response elif table_name == "user_notification": if query_type == "find_unique": - response = await UserNotificationsRepository(self).table.find_unique( # type: ignore + response = await UserNotificationsRepository( + self + ).table.find_unique( # type: ignore where={"user_id": user_id} # type: ignore ) elif query_type == "find_all": @@ -3831,7 +3833,9 @@ class PrismaClient: print_verbose( "PrismaClient: Before upsert into litellm_verificationtoken" ) - new_verification_token = await VerificationTokenRepository(self).table.upsert( # type: ignore + new_verification_token = await VerificationTokenRepository( + self + ).table.upsert( # type: ignore where={ "token": hashed_token, }, @@ -5717,19 +5721,19 @@ async def update_daily_tag_spend( """ n_retry_times = 3 try: - if ( - proxy_logging_obj.db_spend_update_writer.redis_update_buffer._should_commit_spend_updates_to_redis() - ): + if proxy_logging_obj.db_spend_update_writer.redis_update_buffer._should_commit_spend_updates_to_redis(): await proxy_logging_obj.db_spend_update_writer._commit_daily_tag_spend_to_db_with_redis( prisma_client=prisma_client, n_retry_times=n_retry_times, proxy_logging_obj=proxy_logging_obj, ) else: - await proxy_logging_obj.db_spend_update_writer._commit_daily_tag_spend_to_db( - prisma_client=prisma_client, - n_retry_times=n_retry_times, - proxy_logging_obj=proxy_logging_obj, + await ( + proxy_logging_obj.db_spend_update_writer._commit_daily_tag_spend_to_db( + prisma_client=prisma_client, + n_retry_times=n_retry_times, + proxy_logging_obj=proxy_logging_obj, + ) ) except Exception as e: # NOTE: keep this as a plain ``error`` (no traceback) to match the diff --git a/litellm/proxy/vector_store_endpoints/endpoints.py b/litellm/proxy/vector_store_endpoints/endpoints.py index 9c2d3050346..9c2d297bfa7 100644 --- a/litellm/proxy/vector_store_endpoints/endpoints.py +++ b/litellm/proxy/vector_store_endpoints/endpoints.py @@ -42,9 +42,9 @@ async def _update_request_data_with_litellm_managed_vector_store_registry( Raises: HTTPException: If user doesn't have access to the vector store """ - vector_store_to_run: Optional[LiteLLM_ManagedVectorStore] = ( - await get_litellm_managed_vector_store(vector_store_id=vector_store_id) - ) + vector_store_to_run: Optional[ + LiteLLM_ManagedVectorStore + ] = await get_litellm_managed_vector_store(vector_store_id=vector_store_id) if vector_store_to_run is not None: if user_api_key_dict is not None: await assert_user_can_access_vector_store( diff --git a/litellm/rag/ingestion/base_ingestion.py b/litellm/rag/ingestion/base_ingestion.py index 1de68e2ac94..b49c86b3c8b 100644 --- a/litellm/rag/ingestion/base_ingestion.py +++ b/litellm/rag/ingestion/base_ingestion.py @@ -184,7 +184,9 @@ class BaseRAGIngestion(ABC): # Extract text from pages if hasattr(ocr_response, "pages") and ocr_response.pages: # type: ignore return "\n\n".join( - page.markdown for page in ocr_response.pages if hasattr(page, "markdown") # type: ignore + page.markdown + for page in ocr_response.pages + if hasattr(page, "markdown") # type: ignore ) return None diff --git a/litellm/rag/ingestion/vertex_ai_ingestion.py b/litellm/rag/ingestion/vertex_ai_ingestion.py index 4c79cd26150..b7bd87d1f6c 100644 --- a/litellm/rag/ingestion/vertex_ai_ingestion.py +++ b/litellm/rag/ingestion/vertex_ai_ingestion.py @@ -317,7 +317,7 @@ class VertexAIRAGIngestion(BaseRAGIngestion, VertexBase): # Construct upload URL using vertex base URL helper base_url = get_vertex_base_url(self.location) - url = f"{base_url}/upload/v1beta1/" f"{rag_corpus_id}/ragFiles:upload" + url = f"{base_url}/upload/v1beta1/{rag_corpus_id}/ragFiles:upload" # Build metadata for the file with snake_case keys (as per upload API docs) metadata: Dict[str, Any] = { @@ -423,7 +423,7 @@ class VertexAIRAGIngestion(BaseRAGIngestion, VertexBase): # Construct import URL using vertex base URL helper base_url = get_vertex_base_url(self.location) - url = f"{base_url}/v1beta1/" f"{rag_corpus_id}/ragFiles:import" + url = f"{base_url}/v1beta1/{rag_corpus_id}/ragFiles:import" # Build request body with camelCase keys (Vertex AI API format) request_body: Dict[str, Any] = { @@ -447,9 +447,9 @@ class VertexAIRAGIngestion(BaseRAGIngestion, VertexBase): "max_embedding_requests_per_min" ) if max_embedding_qpm: - request_body["importRagFilesConfig"][ - "maxEmbeddingRequestsPerMin" - ] = max_embedding_qpm + request_body["importRagFilesConfig"]["maxEmbeddingRequestsPerMin"] = ( + max_embedding_qpm + ) verbose_logger.debug(f"Importing files from GCS: {url}") verbose_logger.debug(f"Request body: {json.dumps(request_body, indent=2)}") diff --git a/litellm/responses/litellm_completion_transformation/handler.py b/litellm/responses/litellm_completion_transformation/handler.py index 03a2f339bea..a29f0a01b7a 100644 --- a/litellm/responses/litellm_completion_transformation/handler.py +++ b/litellm/responses/litellm_completion_transformation/handler.py @@ -38,16 +38,14 @@ class LiteLLMCompletionTransformationHandler: Any, Any, Union[ResponsesAPIResponse, BaseResponsesAPIStreamingIterator] ], ]: - litellm_completion_request: dict = ( - LiteLLMCompletionResponsesConfig.transform_responses_api_request_to_chat_completion_request( - model=model, - input=input, - responses_api_request=responses_api_request, - custom_llm_provider=custom_llm_provider, - stream=stream, - extra_headers=extra_headers, - **kwargs, - ) + litellm_completion_request: dict = LiteLLMCompletionResponsesConfig.transform_responses_api_request_to_chat_completion_request( + model=model, + input=input, + responses_api_request=responses_api_request, + custom_llm_provider=custom_llm_provider, + stream=stream, + extra_headers=extra_headers, + **kwargs, ) if _is_async: @@ -69,12 +67,10 @@ class LiteLLMCompletionTransformationHandler: ) if isinstance(litellm_completion_response, ModelResponse): - responses_api_response: ResponsesAPIResponse = ( - LiteLLMCompletionResponsesConfig.transform_chat_completion_response_to_responses_api_response( - chat_completion_response=litellm_completion_response, - request_input=input, - responses_api_request=responses_api_request, - ) + responses_api_response: ResponsesAPIResponse = LiteLLMCompletionResponsesConfig.transform_chat_completion_response_to_responses_api_response( + chat_completion_response=litellm_completion_response, + request_input=input, + responses_api_request=responses_api_request, ) return responses_api_response @@ -119,12 +115,10 @@ class LiteLLMCompletionTransformationHandler: ) if isinstance(litellm_completion_response, ModelResponse): - responses_api_response: ResponsesAPIResponse = ( - LiteLLMCompletionResponsesConfig.transform_chat_completion_response_to_responses_api_response( - chat_completion_response=litellm_completion_response, - request_input=request_input, - responses_api_request=responses_api_request, - ) + responses_api_response: ResponsesAPIResponse = LiteLLMCompletionResponsesConfig.transform_chat_completion_response_to_responses_api_response( + chat_completion_response=litellm_completion_response, + request_input=request_input, + responses_api_request=responses_api_request, ) return responses_api_response diff --git a/litellm/responses/litellm_completion_transformation/session_handler.py b/litellm/responses/litellm_completion_transformation/session_handler.py index 71ff2eb7acf..45ab16b0d4a 100644 --- a/litellm/responses/litellm_completion_transformation/session_handler.py +++ b/litellm/responses/litellm_completion_transformation/session_handler.py @@ -43,10 +43,10 @@ class ResponsesSessionHandler: verbose_proxy_logger.debug( "inside get_chat_completion_message_history_for_previous_response_id" ) - all_spend_logs: List[SpendLogsPayload] = ( - await ResponsesSessionHandler.get_all_spend_logs_for_previous_response_id( - previous_response_id - ) + all_spend_logs: List[ + SpendLogsPayload + ] = await ResponsesSessionHandler.get_all_spend_logs_for_previous_response_id( + previous_response_id ) verbose_proxy_logger.debug( "found %s spend logs for this response id", len(all_spend_logs) diff --git a/litellm/responses/litellm_completion_transformation/streaming_iterator.py b/litellm/responses/litellm_completion_transformation/streaming_iterator.py index 767281d43ab..582144e6cb8 100644 --- a/litellm/responses/litellm_completion_transformation/streaming_iterator.py +++ b/litellm/responses/litellm_completion_transformation/streaming_iterator.py @@ -615,8 +615,13 @@ class LiteLLMCompletionStreamingIterator(ResponsesAPIStreamingIterator): self._cached_item_id = f"msg_{str(uuid.uuid4())}" text = getattr(litellm_complete_object.choices[0].message, "content", "") or "" # type: ignore - reasoning_content = getattr(litellm_complete_object.choices[0].message, "reasoning_content", "") or "" # type: ignore - annotations = getattr(litellm_complete_object.choices[0].message, "annotations", None) # type: ignore + reasoning_content = ( + getattr(litellm_complete_object.choices[0].message, "reasoning_content", "") + or "" + ) # type: ignore + annotations = getattr( + litellm_complete_object.choices[0].message, "annotations", None + ) # type: ignore part: Optional[PART_UNION_TYPES] = None if reasoning_content: @@ -651,7 +656,9 @@ class LiteLLMCompletionStreamingIterator(ResponsesAPIStreamingIterator): self._cached_item_id = f"msg_{str(uuid.uuid4())}" text = self.litellm_model_response.choices[0].message.content or "" # type: ignore - annotations = getattr(self.litellm_model_response.choices[0].message, "annotations", None) # type: ignore + annotations = getattr( + self.litellm_model_response.choices[0].message, "annotations", None + ) # type: ignore response_annotations = LiteLLMCompletionResponsesConfig._transform_chat_completion_annotations_to_response_output_annotations( annotations=annotations diff --git a/litellm/responses/litellm_completion_transformation/transformation.py b/litellm/responses/litellm_completion_transformation/transformation.py index 5b5ff122c50..0bd78e59819 100644 --- a/litellm/responses/litellm_completion_transformation/transformation.py +++ b/litellm/responses/litellm_completion_transformation/transformation.py @@ -1409,7 +1409,9 @@ class LiteLLMCompletionResponsesConfig: if tool.get("defer_loading"): chat_completion_tool["defer_loading"] = tool.get("defer_loading") # type: ignore if tool.get("allowed_callers"): - chat_completion_tool["allowed_callers"] = tool.get("allowed_callers") # type: ignore + chat_completion_tool["allowed_callers"] = tool.get( + "allowed_callers" + ) # type: ignore if tool.get("input_examples"): chat_completion_tool["input_examples"] = tool.get("input_examples") # type: ignore chat_completion_tools.append( @@ -1522,7 +1524,11 @@ class LiteLLMCompletionResponsesConfig: # Pass through provider_specific_fields as-is if present if provider_specific_fields: - setattr(output_tool_call, "provider_specific_fields", provider_specific_fields) # type: ignore + setattr( + output_tool_call, + "provider_specific_fields", + provider_specific_fields, + ) # type: ignore responses_tools.append(output_tool_call) return responses_tools diff --git a/litellm/responses/main.py b/litellm/responses/main.py index 2c46baaada5..3edcbd430f1 100644 --- a/litellm/responses/main.py +++ b/litellm/responses/main.py @@ -307,9 +307,7 @@ async def aresponses_api_with_mcp( # Auto-Execute Tools Handling # If auto-execute tools is True, then we need to execute the tool calls ######################################################### - if should_auto_execute and isinstance( - response, ResponsesAPIResponse - ): # type: ignore + if should_auto_execute and isinstance(response, ResponsesAPIResponse): # type: ignore tool_calls = LiteLLM_Proxy_MCP_Handler._extract_tool_calls_from_response( response=response ) diff --git a/litellm/responses/mcp/mcp_streaming_iterator.py b/litellm/responses/mcp/mcp_streaming_iterator.py index 42c46dff47c..839e0232b04 100644 --- a/litellm/responses/mcp/mcp_streaming_iterator.py +++ b/litellm/responses/mcp/mcp_streaming_iterator.py @@ -632,7 +632,11 @@ class MCPEnhancedStreamingIterator(BaseResponsesAPIStreamingIterator): try: # Extract tool calls from the response if self.collected_response is not None: - tool_calls = LiteLLM_Proxy_MCP_Handler._extract_tool_calls_from_response(self.collected_response) # type: ignore[arg-type] + tool_calls = ( + LiteLLM_Proxy_MCP_Handler._extract_tool_calls_from_response( + self.collected_response + ) + ) # type: ignore[arg-type] else: tool_calls = [] if not tool_calls: diff --git a/litellm/router.py b/litellm/router.py index 6e7b9689415..0008fcaa30b 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -431,9 +431,7 @@ class Router: self.assistants_config = assistants_config self.search_tools = search_tools or [] self.guardrail_list = guardrail_list or [] - self.deployment_names: List = ( - [] - ) # names of models under litellm_params. ex. azure/chatgpt-v-2 + self.deployment_names: List = [] # names of models under litellm_params. ex. azure/chatgpt-v-2 self.deployment_latency_map = {} ### CACHING ### cache_type: Literal["local", "redis", "redis-semantic", "s3", "disk"] = ( @@ -486,9 +484,9 @@ class Router: self.default_max_parallel_requests = default_max_parallel_requests self.provider_default_deployment_ids: List[str] = [] self.pattern_router = PatternMatchRouter() - self.team_pattern_routers: Dict[str, PatternMatchRouter] = ( - {} - ) # {"TEAM_ID": PatternMatchRouter} + self.team_pattern_routers: Dict[ + str, PatternMatchRouter + ] = {} # {"TEAM_ID": PatternMatchRouter} self.auto_routers: Dict[str, "AutoRouter"] = {} self.complexity_routers: Dict[str, "ComplexityRouter"] = {} self.adaptive_routers: Dict[str, "AdaptiveRouter"] = {} @@ -526,9 +524,7 @@ class Router: if "model" in m["litellm_params"]: self.deployment_latency_map[m["litellm_params"]["model"]] = 0 else: - self.model_list: List = ( - [] - ) # initialize an empty list - to allow _add_deployment and delete_deployment to work + self.model_list: List = [] # initialize an empty list - to allow _add_deployment and delete_deployment to work if allowed_fails is not None: self.allowed_fails = allowed_fails @@ -548,9 +544,7 @@ class Router: self.health_state_cache = DeploymentHealthCache( cache=self.cache, staleness_threshold=float(_staleness) ) - self.failed_calls = ( - InMemoryCache() - ) # cache to track failed call per deployment, if num failed calls within 1 minute > allowed fails, then add it to cooldown + self.failed_calls = InMemoryCache() # cache to track failed call per deployment, if num failed calls within 1 minute > allowed fails, then add it to cooldown if num_retries is not None: self.num_retries = num_retries @@ -615,9 +609,7 @@ class Router: self.success_calls: defaultdict = defaultdict( int ) # dict to store success_calls made to each model - self.previous_models: List = ( - [] - ) # list to store failed calls (passed in as metadata to next call) + self.previous_models: List = [] # list to store failed calls (passed in as metadata to next call) # make Router.chat.completions.create compatible for openai.chat.completions.create default_litellm_params = default_litellm_params or {} @@ -2967,9 +2959,7 @@ class Router: """ model_name = None deployment = None - _timeout_debug_deployment_dict = ( - {} - ) # this is a temporary dict to debug timeout issues + _timeout_debug_deployment_dict = {} # this is a temporary dict to debug timeout issues try: input_kwargs_for_streaming_fallback = kwargs.copy() input_kwargs_for_streaming_fallback["model"] = model @@ -3504,7 +3494,11 @@ class Router: _tasks = [] for model in models: # add each task but if the task fails - _tasks.append(_async_completion_no_exceptions(model=model, messages=messages, **kwargs)) # type: ignore + _tasks.append( + _async_completion_no_exceptions( + model=model, messages=messages, **kwargs + ) + ) # type: ignore response = await asyncio.gather(*_tasks) return response elif isinstance(messages, list) and all(isinstance(m, list) for m in messages): @@ -3613,7 +3607,9 @@ class Router: Wrapper around self.acompletion that catches exceptions and returns them as a result """ try: - result = await self.acompletion(model=model, messages=messages, stream=stream, **kwargs) # type: ignore + result = await self.acompletion( + model=model, messages=messages, stream=stream, **kwargs + ) # type: ignore return result except asyncio.CancelledError: verbose_router_logger.debug( @@ -4414,7 +4410,9 @@ class Router: kwargs[k].update(v) # call via litellm.completion() - return litellm.text_completion(**{**data, "prompt": prompt, "caching": self.cache_responses, **kwargs}) # type: ignore + return litellm.text_completion( + **{**data, "prompt": prompt, "caching": self.cache_responses, **kwargs} + ) # type: ignore except Exception as e: raise e @@ -6723,9 +6721,7 @@ class Router: ) verbose_router_logger.info( msg="Got 'ContextWindowExceededError'. No context_window_fallback set. Defaulting \ - to fallbacks, if available.{}".format( - error_message - ) + to fallbacks, if available.{}".format(error_message) ) if litellm.expose_router_debug_in_errors: @@ -6759,9 +6755,7 @@ class Router: ) verbose_router_logger.info( msg="Got 'ContentPolicyViolationError'. No content_policy_fallback set. Defaulting \ - to fallbacks, if available.{}".format( - error_message - ) + to fallbacks, if available.{}".format(error_message) ) if litellm.expose_router_debug_in_errors: @@ -6822,9 +6816,11 @@ class Router: and litellm.expose_router_debug_in_errors ): # add the available fallbacks to the exception - original_exception.message += ". Received Model Group={}\nAvailable Model Group Fallbacks={}".format( # type: ignore - model_group, - fallback_model_group, + original_exception.message += ( + ". Received Model Group={}\nAvailable Model Group Fallbacks={}".format( # type: ignore + model_group, + fallback_model_group, + ) ) if len(fallback_failure_exception_str) > 0: original_exception.message += ( # type: ignore @@ -7609,7 +7605,11 @@ class Router: """ Update RPM usage for a deployment """ - deployment_name = kwargs["litellm_params"]["metadata"].get( + deployment_name = kwargs[ + "litellm_params" + ][ + "metadata" + ].get( "deployment", None ) # handles wildcard routes - by giving the original name sent to `litellm.completion` model_group = kwargs["litellm_params"]["metadata"].get("model_group", None) @@ -7669,9 +7669,7 @@ class Router: for ( k, v, - ) in ( - kwargs.items() - ): # log everything in kwargs except the old previous_models value - prevent nesting + ) in kwargs.items(): # log everything in kwargs except the old previous_models value - prevent nesting if k not in [_metadata_var, "messages", "original_function"]: previous_model[k] = v elif k == _metadata_var and isinstance(v, dict): @@ -9594,7 +9592,8 @@ class Router: ): model_group_info.supports_parallel_function_calling = True if ( - model_info.get("supports_vision", None) is not None and model_info["supports_vision"] is True # type: ignore + model_info.get("supports_vision", None) is not None + and model_info["supports_vision"] is True # type: ignore ): model_group_info.supports_vision = True if ( @@ -9614,7 +9613,8 @@ class Router: model_group_info.supports_url_context = True if ( - model_info.get("supports_reasoning", None) is not None and model_info["supports_reasoning"] is True # type: ignore + model_info.get("supports_reasoning", None) is not None + and model_info["supports_reasoning"] is True # type: ignore ): model_group_info.supports_reasoning = True if ( diff --git a/litellm/router_strategy/base_routing_strategy.py b/litellm/router_strategy/base_routing_strategy.py index 885798d706c..74451729c73 100644 --- a/litellm/router_strategy/base_routing_strategy.py +++ b/litellm/router_strategy/base_routing_strategy.py @@ -211,9 +211,7 @@ class BaseRoutingStrategy(ABC): return # 2. Fetch all current provider spend from Redis to update in-memory cache - cache_keys = ( - self.get_in_memory_keys_to_update() - ) # if no pattern OR redis cache does not support scan_iter, use in-memory keys + cache_keys = self.get_in_memory_keys_to_update() # if no pattern OR redis cache does not support scan_iter, use in-memory keys cache_keys_list = list(cache_keys) diff --git a/litellm/router_strategy/complexity_router/evals/eval_complexity_router.py b/litellm/router_strategy/complexity_router/evals/eval_complexity_router.py index 6c9318e83bb..7c1c8f2907d 100644 --- a/litellm/router_strategy/complexity_router/evals/eval_complexity_router.py +++ b/litellm/router_strategy/complexity_router/evals/eval_complexity_router.py @@ -304,7 +304,7 @@ def run_eval() -> Tuple[int, int, List[dict]]: # Summary print("=" * 70) - print(f"RESULTS: {passed}/{total} passed ({100*passed/total:.1f}%)") + print(f"RESULTS: {passed}/{total} passed ({100 * passed / total:.1f}%)") print("=" * 70) if failures: diff --git a/litellm/router_strategy/lowest_latency.py b/litellm/router_strategy/lowest_latency.py index 3adb8d43920..3f2db97e2bf 100644 --- a/litellm/router_strategy/lowest_latency.py +++ b/litellm/router_strategy/lowest_latency.py @@ -548,9 +548,9 @@ class LowestLatencyLoggingHandler(CustomLogger): deployment = random_valid_deployment[0] metadata_field = self._select_metadata_field(request_kwargs) if request_kwargs is not None and metadata_field in request_kwargs: - request_kwargs[metadata_field][ - "_latency_per_deployment" - ] = _latency_per_deployment + request_kwargs[metadata_field]["_latency_per_deployment"] = ( + _latency_per_deployment + ) return deployment async def async_get_available_deployments( diff --git a/litellm/router_strategy/lowest_tpm_rpm_v2.py b/litellm/router_strategy/lowest_tpm_rpm_v2.py index 22664dcb704..09c2084c095 100644 --- a/litellm/router_strategy/lowest_tpm_rpm_v2.py +++ b/litellm/router_strategy/lowest_tpm_rpm_v2.py @@ -106,7 +106,10 @@ class LowestTPMLoggingHandler_v2(BaseRoutingStrategy, CustomLogger): model_id, deployment.get("model_name", ""), ), - request=httpx.Request(method="tpm_rpm_limits", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="tpm_rpm_limits", + url="https://github.com/BerriAI/litellm", + ), # type: ignore ), ) else: @@ -129,7 +132,10 @@ class LowestTPMLoggingHandler_v2(BaseRoutingStrategy, CustomLogger): deployment_rpm, result, ), - request=httpx.Request(method="tpm_rpm_limits", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="tpm_rpm_limits", + url="https://github.com/BerriAI/litellm", + ), # type: ignore ), ) return deployment @@ -190,7 +196,10 @@ class LowestTPMLoggingHandler_v2(BaseRoutingStrategy, CustomLogger): local_result, ), headers={"retry-after": str(60)}, # type: ignore - request=httpx.Request(method="tpm_rpm_limits", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="tpm_rpm_limits", + url="https://github.com/BerriAI/litellm", + ), # type: ignore ), num_retries=deployment.get("num_retries"), ) @@ -214,7 +223,10 @@ class LowestTPMLoggingHandler_v2(BaseRoutingStrategy, CustomLogger): result, ), headers={"retry-after": str(60)}, # type: ignore - request=httpx.Request(method="tpm_rpm_limits", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="tpm_rpm_limits", + url="https://github.com/BerriAI/litellm", + ), # type: ignore ), num_retries=deployment.get("num_retries"), ) @@ -558,7 +570,10 @@ class LowestTPMLoggingHandler_v2(BaseRoutingStrategy, CustomLogger): status_code=429, content="", headers={"retry-after": str(60)}, # type: ignore - request=httpx.Request(method="tpm_rpm_limits", url="https://github.com/BerriAI/litellm"), # type: ignore + request=httpx.Request( + method="tpm_rpm_limits", + url="https://github.com/BerriAI/litellm", + ), # type: ignore ), ) diff --git a/litellm/router_utils/pre_call_checks/encrypted_content_affinity_check.py b/litellm/router_utils/pre_call_checks/encrypted_content_affinity_check.py index 5fd2be9c6dd..cab2041964f 100644 --- a/litellm/router_utils/pre_call_checks/encrypted_content_affinity_check.py +++ b/litellm/router_utils/pre_call_checks/encrypted_content_affinity_check.py @@ -252,9 +252,9 @@ class EncryptedContentAffinityCheck(CustomLogger): # _get_metadata_variable_name_from_kwargs would pick "litellm_metadata" # over "metadata" where tags are actually stored. if "litellm_metadata" in request_kwargs: - request_kwargs["litellm_metadata"][ - "encrypted_content_affinity_enabled" - ] = True + request_kwargs["litellm_metadata"]["encrypted_content_affinity_enabled"] = ( + True + ) request_input = request_kwargs.get("input") model_id = self._extract_model_id_from_input(request_input) diff --git a/litellm/sandbox/sandbox_tools.py b/litellm/sandbox/sandbox_tools.py index f4a6678f629..509b316ee21 100644 --- a/litellm/sandbox/sandbox_tools.py +++ b/litellm/sandbox/sandbox_tools.py @@ -40,11 +40,14 @@ def _iter_valid_tools(tools: list[dict]) -> Iterator[tuple[str, dict]]: "sandbox_tools: skipping entry missing 'sandbox_provider': %r", tool ) continue - yield name, { - "sandbox_provider": provider, - "api_key": _resolve_secret_value(params.get("api_key")), - "api_base": _resolve_secret_value(params.get("api_base")), - } + yield ( + name, + { + "sandbox_provider": provider, + "api_key": _resolve_secret_value(params.get("api_key")), + "api_base": _resolve_secret_value(params.get("api_base")), + }, + ) def register_sandbox_tools(tools: list[dict]) -> None: diff --git a/litellm/types/google_genai/main.py b/litellm/types/google_genai/main.py index b2e1fb3d46b..5c76736ab90 100644 --- a/litellm/types/google_genai/main.py +++ b/litellm/types/google_genai/main.py @@ -23,7 +23,9 @@ if TYPE_CHECKING: generationConfig: Optional[Any] tools: Optional[ToolConfigDict] # type: ignore[assignment, valid-type] - class GenerateContentResponse(GoogleGenAIGenerateContentResponse, BaseLiteLLMOpenAIResponseObject): # type: ignore[misc, valid-type] + class GenerateContentResponse( + GoogleGenAIGenerateContentResponse, BaseLiteLLMOpenAIResponseObject + ): # type: ignore[misc, valid-type] _hidden_params: dict = {} pass diff --git a/litellm/types/integrations/prometheus.py b/litellm/types/integrations/prometheus.py index 5b1d32cd93c..d203fe73d02 100644 --- a/litellm/types/integrations/prometheus.py +++ b/litellm/types/integrations/prometheus.py @@ -698,9 +698,9 @@ 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, @@ -709,9 +709,9 @@ 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] = [] diff --git a/litellm/types/llms/openai.py b/litellm/types/llms/openai.py index cbb316eec75..36b6bac90ea 100644 --- a/litellm/types/llms/openai.py +++ b/litellm/types/llms/openai.py @@ -1100,7 +1100,7 @@ OpenAIImageGenerationOptionalParams = Literal[ OpenAIImageEditOptionalParams = Literal[ "background", "n", - "mask" "output_compression", + "maskoutput_compression", "output_format", "quality", "partial_images", diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/xecguard.py b/litellm/types/proxy/guardrails/guardrail_hooks/xecguard.py index af199eed55e..697e794a7f1 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/xecguard.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/xecguard.py @@ -33,9 +33,7 @@ class XecGuardConfigModel(GuardrailConfigModel): ) xecguard_model: Optional[str] = Field( default=None, - description=( - "XecGuard scanning model identifier. " "Defaults to 'xecguard_v2'." - ), + description=("XecGuard scanning model identifier. Defaults to 'xecguard_v2'."), ) policy_names: Optional[List[str]] = Field( default=None, diff --git a/litellm/types/router.py b/litellm/types/router.py index b5285f11f8b..a1c571ed7f7 100644 --- a/litellm/types/router.py +++ b/litellm/types/router.py @@ -110,9 +110,7 @@ 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 - db_model: bool = ( - False # used for proxy - to separate models which are stored in the db vs. config. - ) + 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 @@ -439,9 +437,7 @@ class Deployment(BaseModel): elif isinstance(model_info, dict): model_info = ModelInfo(**model_info) - for ( - key - ) in ( + for key in ( SPECIAL_MODEL_INFO_PARAMS ): # ensures custom pricing info is consistently in 'model_info' field = getattr(litellm_params, key, None) diff --git a/litellm/utils.py b/litellm/utils.py index 5c3ab3e1490..e0aa8575473 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -799,7 +799,9 @@ def function_setup( # check if callback is a string - e.g. "lago", "openmeter" if isinstance(callback, str): callback = litellm.litellm_core_utils.litellm_logging._init_custom_logger_compatible_class( # type: ignore - callback, internal_usage_cache=None, llm_router=None # type: ignore + callback, + internal_usage_cache=None, + llm_router=None, # type: ignore ) if callback is None or any( isinstance(cb, type(callback)) @@ -809,13 +811,21 @@ def function_setup( if callback not in litellm.input_callback: litellm.input_callback.append(callback) # type: ignore if callback not in litellm.success_callback: - litellm.logging_callback_manager.add_litellm_success_callback(callback) # type: ignore + litellm.logging_callback_manager.add_litellm_success_callback( + callback + ) # type: ignore if callback not in litellm.failure_callback: - litellm.logging_callback_manager.add_litellm_failure_callback(callback) # type: ignore + litellm.logging_callback_manager.add_litellm_failure_callback( + callback + ) # type: ignore if callback not in litellm._async_success_callback: - litellm.logging_callback_manager.add_litellm_async_success_callback(callback) # type: ignore + litellm.logging_callback_manager.add_litellm_async_success_callback( + callback + ) # type: ignore if callback not in litellm._async_failure_callback: - litellm.logging_callback_manager.add_litellm_async_failure_callback(callback) # type: ignore + litellm.logging_callback_manager.add_litellm_async_failure_callback( + callback + ) # type: ignore print_verbose( f"Initialized litellm callbacks, Async Success Callbacks: {litellm._async_success_callback}" ) @@ -1486,9 +1496,9 @@ def client(original_function): ) # Type assertion: logging_obj is guaranteed to be non-None after function_setup - assert ( - logging_obj is not None - ), "logging_obj should not be None after function_setup" + assert logging_obj is not None, ( + "logging_obj should not be None after function_setup" + ) ## LOAD CREDENTIALS load_credentials_from_list(kwargs) @@ -1810,9 +1820,9 @@ def client(original_function): ) # Type assertion: logging_obj is guaranteed to be non-None after function_setup - assert ( - logging_obj is not None - ), "logging_obj should not be None after function_setup" + assert logging_obj is not None, ( + "logging_obj should not be None after function_setup" + ) modified_kwargs = await async_pre_call_deployment_hook(kwargs, call_type) if modified_kwargs is not None: @@ -2311,7 +2321,9 @@ def create_pretrained_tokenizer( try: tokenizer = Tokenizer.from_pretrained( - identifier, revision=revision, auth_token=auth_token # type: ignore + identifier, + revision=revision, + auth_token=auth_token, # type: ignore ) except Exception as e: verbose_logger.error( @@ -3163,8 +3175,9 @@ def get_optional_params_transcription( keys = list(non_default_params.keys()) for k in keys: if ( - drop_params is True or litellm.drop_params is True - ) and k not in supported_params: # drop the unsupported non-default values + (drop_params is True or litellm.drop_params is True) + and k not in supported_params + ): # drop the unsupported non-default values non_default_params.pop(k, None) elif k not in supported_params: raise UnsupportedParamsError( @@ -3294,8 +3307,9 @@ def get_optional_params_image_gen( keys = list(non_default_params.keys()) for k in keys: if ( - litellm.drop_params is True or drop_params is True - ) and k not in supported_params: # drop the unsupported non-default values + (litellm.drop_params is True or drop_params is True) + and k not in supported_params + ): # drop the unsupported non-default values non_default_params.pop(k, None) passed_params.pop(k, None) elif k not in supported_params: @@ -3971,11 +3985,7 @@ def pre_process_non_default_params( non_default_params, list ): # fixes https://github.com/BerriAI/litellm/issues/4933 tools = non_default_params["tools"] - for ( - tool - ) in ( - tools - ): # clean out 'additionalProperties = False'. Causes vertexai/gemini OpenAI API Schema errors - https://github.com/langchain-ai/langchainjs/issues/5240 + for tool in tools: # clean out 'additionalProperties = False'. Causes vertexai/gemini OpenAI API Schema errors - https://github.com/langchain-ai/langchainjs/issues/5240 tool_function = tool.get("function", {}) parameters = tool_function.get("parameters", None) if parameters is not None: @@ -5740,8 +5750,8 @@ def _get_potential_model_names( model=model, custom_llm_provider=custom_llm_provider ) combined_stripped_model_name = stripped_model_name - elif custom_llm_provider and model.startswith( - custom_llm_provider + "/" + elif ( + custom_llm_provider and model.startswith(custom_llm_provider + "/") ): # handle case where custom_llm_provider is provided and model starts with custom_llm_provider split_model = model.split("/", 1)[1] combined_model_name = model @@ -7938,7 +7948,9 @@ class ModelResponseIterator: def __init__(self, model_response: ModelResponse, convert_to_delta: bool = False): if convert_to_delta is True: _stream_response = ModelResponseStream() - _stream_response.choices[0].delta.content = model_response.choices[0].message.content # type: ignore + _stream_response.choices[0].delta.content = model_response.choices[ + 0 + ].message.content # type: ignore self.model_response: Union[ModelResponse, ModelResponseStream] = ( _stream_response ) diff --git a/pyproject.toml b/pyproject.toml index 1cb39153e83..ae612ae2184 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,7 +148,6 @@ litellm-proxy = "litellm.proxy.client.cli:cli" dev = [ "diff-cover==9.7.2", "flake8==7.3.0", - "black==26.3.1", "basedpyright==1.39.7", "pytest==9.0.3", "pytest-mock==3.15.1", diff --git a/ruff.toml b/ruff.toml index 2db4122a30e..082a8f83a0c 100644 --- a/ruff.toml +++ b/ruff.toml @@ -11,7 +11,16 @@ lint.external = [ "PLC0415", "E402", "BLE001", "ARG002", "S102", "S324", "S606", "D401", "F403", "F405", ] line-length = 120 -exclude = ["litellm/types/*", "litellm/__init__.py", "litellm/proxy/example_config_yaml/*", "tests/*"] + +# `ruff format` (replacing Black) must wrap at 88, the width Black used and the whole +# history is formatted to. The global line-length stays 120 because E501 and the import +# sorter (I001, strict gate) are tuned to it and ruff has no per-formatter line-length, +# so 88 is passed at the `ruff format --line-length 88` call sites (Makefile + CI). +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.per-file-ignores] diff --git a/uv.lock b/uv.lock index cac1696bf34..8193bf14f63 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-06-20T23:16:25.061268Z" +exclude-newer = "2026-06-22T14:51:56.5801Z" exclude-newer-span = "P3D" [manifest] @@ -575,45 +575,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, ] -[[package]] -name = "black" -version = "26.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "mypy-extensions" }, - { name = "packaging" }, - { name = "pathspec" }, - { name = "platformdirs" }, - { name = "pytokens" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e1/c5/61175d618685d42b005847464b8fb4743a67b1b8fdb75e50e5a96c31a27a/black-26.3.1.tar.gz", hash = "sha256:2c50f5063a9641c7eed7795014ba37b0f5fa227f3d408b968936e24bc0566b07", size = 666155, upload-time = "2026-03-12T03:36:03.593Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/a8/11170031095655d36ebc6664fe0897866f6023892396900eec0e8fdc4299/black-26.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:86a8b5035fce64f5dcd1b794cf8ec4d31fe458cf6ce3986a30deb434df82a1d2", size = 1866562, upload-time = "2026-03-12T03:39:58.639Z" }, - { url = "https://files.pythonhosted.org/packages/69/ce/9e7548d719c3248c6c2abfd555d11169457cbd584d98d179111338423790/black-26.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5602bdb96d52d2d0672f24f6ffe5218795736dd34807fd0fd55ccd6bf206168b", size = 1703623, upload-time = "2026-03-12T03:40:00.347Z" }, - { url = "https://files.pythonhosted.org/packages/7f/0a/8d17d1a9c06f88d3d030d0b1d4373c1551146e252afe4547ed601c0e697f/black-26.3.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c54a4a82e291a1fee5137371ab488866b7c86a3305af4026bdd4dc78642e1ac", size = 1768388, upload-time = "2026-03-12T03:40:01.765Z" }, - { url = "https://files.pythonhosted.org/packages/52/79/c1ee726e221c863cde5164f925bacf183dfdf0397d4e3f94889439b947b4/black-26.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:6e131579c243c98f35bce64a7e08e87fb2d610544754675d4a0e73a070a5aa3a", size = 1412969, upload-time = "2026-03-12T03:40:03.252Z" }, - { url = "https://files.pythonhosted.org/packages/73/a5/15c01d613f5756f68ed8f6d4ec0a1e24b82b18889fa71affd3d1f7fad058/black-26.3.1-cp310-cp310-win_arm64.whl", hash = "sha256:5ed0ca58586c8d9a487352a96b15272b7fa55d139fc8496b519e78023a8dab0a", size = 1220345, upload-time = "2026-03-12T03:40:04.892Z" }, - { url = "https://files.pythonhosted.org/packages/17/57/5f11c92861f9c92eb9dddf515530bc2d06db843e44bdcf1c83c1427824bc/black-26.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:28ef38aee69e4b12fda8dba75e21f9b4f979b490c8ac0baa7cb505369ac9e1ff", size = 1851987, upload-time = "2026-03-12T03:40:06.248Z" }, - { url = "https://files.pythonhosted.org/packages/54/aa/340a1463660bf6831f9e39646bf774086dbd8ca7fc3cded9d59bbdf4ad0a/black-26.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf9bf162ed91a26f1adba8efda0b573bc6924ec1408a52cc6f82cb73ec2b142c", size = 1689499, upload-time = "2026-03-12T03:40:07.642Z" }, - { url = "https://files.pythonhosted.org/packages/f3/01/b726c93d717d72733da031d2de10b92c9fa4c8d0c67e8a8a372076579279/black-26.3.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:474c27574d6d7037c1bc875a81d9be0a9a4f9ee95e62800dab3cfaadbf75acd5", size = 1754369, upload-time = "2026-03-12T03:40:09.279Z" }, - { url = "https://files.pythonhosted.org/packages/e3/09/61e91881ca291f150cfc9eb7ba19473c2e59df28859a11a88248b5cbbc4d/black-26.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:5e9d0d86df21f2e1677cc4bd090cd0e446278bcbbe49bf3659c308c3e402843e", size = 1413613, upload-time = "2026-03-12T03:40:10.943Z" }, - { url = "https://files.pythonhosted.org/packages/16/73/544f23891b22e7efe4d8f812371ab85b57f6a01b2fc45e3ba2e52ba985b8/black-26.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:9a5e9f45e5d5e1c5b5c29b3bd4265dcc90e8b92cf4534520896ed77f791f4da5", size = 1219719, upload-time = "2026-03-12T03:40:12.597Z" }, - { url = "https://files.pythonhosted.org/packages/dc/f8/da5eae4fc75e78e6dceb60624e1b9662ab00d6b452996046dfa9b8a6025b/black-26.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e6f89631eb88a7302d416594a32faeee9fb8fb848290da9d0a5f2903519fc1", size = 1895920, upload-time = "2026-03-12T03:40:13.921Z" }, - { url = "https://files.pythonhosted.org/packages/2c/9f/04e6f26534da2e1629b2b48255c264cabf5eedc5141d04516d9d68a24111/black-26.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41cd2012d35b47d589cb8a16faf8a32ef7a336f56356babd9fcf70939ad1897f", size = 1718499, upload-time = "2026-03-12T03:40:15.239Z" }, - { url = "https://files.pythonhosted.org/packages/04/91/a5935b2a63e31b331060c4a9fdb5a6c725840858c599032a6f3aac94055f/black-26.3.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f76ff19ec5297dd8e66eb64deda23631e642c9393ab592826fd4bdc97a4bce7", size = 1794994, upload-time = "2026-03-12T03:40:17.124Z" }, - { url = "https://files.pythonhosted.org/packages/e7/0a/86e462cdd311a3c2a8ece708d22aba17d0b2a0d5348ca34b40cdcbea512e/black-26.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:ddb113db38838eb9f043623ba274cfaf7d51d5b0c22ecb30afe58b1bb8322983", size = 1420867, upload-time = "2026-03-12T03:40:18.83Z" }, - { url = "https://files.pythonhosted.org/packages/5b/e5/22515a19cb7eaee3440325a6b0d95d2c0e88dd180cb011b12ae488e031d1/black-26.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:dfdd51fc3e64ea4f35873d1b3fb25326773d55d2329ff8449139ebaad7357efb", size = 1230124, upload-time = "2026-03-12T03:40:20.425Z" }, - { url = "https://files.pythonhosted.org/packages/f5/77/5728052a3c0450c53d9bb3945c4c46b91baa62b2cafab6801411b6271e45/black-26.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:855822d90f884905362f602880ed8b5df1b7e3ee7d0db2502d4388a954cc8c54", size = 1895034, upload-time = "2026-03-12T03:40:21.813Z" }, - { url = "https://files.pythonhosted.org/packages/52/73/7cae55fdfdfbe9d19e9a8d25d145018965fe2079fa908101c3733b0c55a0/black-26.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8a33d657f3276328ce00e4d37fe70361e1ec7614da5d7b6e78de5426cb56332f", size = 1718503, upload-time = "2026-03-12T03:40:23.666Z" }, - { url = "https://files.pythonhosted.org/packages/e1/87/af89ad449e8254fdbc74654e6467e3c9381b61472cc532ee350d28cfdafb/black-26.3.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f1cd08e99d2f9317292a311dfe578fd2a24b15dbce97792f9c4d752275c1fa56", size = 1793557, upload-time = "2026-03-12T03:40:25.497Z" }, - { url = "https://files.pythonhosted.org/packages/43/10/d6c06a791d8124b843bf325ab4ac7d2f5b98731dff84d6064eafd687ded1/black-26.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:c7e72339f841b5a237ff14f7d3880ddd0fc7f98a1199e8c4327f9a4f478c1839", size = 1422766, upload-time = "2026-03-12T03:40:27.14Z" }, - { url = "https://files.pythonhosted.org/packages/59/4f/40a582c015f2d841ac24fed6390bd68f0fc896069ff3a886317959c9daf8/black-26.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:afc622538b430aa4c8c853f7f63bc582b3b8030fd8c80b70fb5fa5b834e575c2", size = 1232140, upload-time = "2026-03-12T03:40:28.882Z" }, - { url = "https://files.pythonhosted.org/packages/8e/0d/52d98722666d6fc6c3dd4c76df339501d6efd40e0ff95e6186a7b7f0befd/black-26.3.1-py3-none-any.whl", hash = "sha256:2bd5aa94fc267d38bb21a70d7410a89f1a1d318841855f698746f8e7f51acd1b", size = 207542, upload-time = "2026-03-12T03:36:01.668Z" }, -] - [[package]] name = "blinker" version = "1.9.0" @@ -3415,7 +3376,6 @@ ci = [ ] dev = [ { name = "basedpyright" }, - { name = "black" }, { name = "botocore-stubs" }, { name = "diff-cover" }, { name = "fakeredis" }, @@ -3585,7 +3545,6 @@ ci = [ ] dev = [ { name = "basedpyright", specifier = "==1.39.7" }, - { name = "black", specifier = "==26.3.1" }, { name = "botocore-stubs", specifier = "==1.43.14" }, { name = "diff-cover", specifier = "==9.7.2" }, { name = "fakeredis", specifier = "==2.34.1" }, @@ -5259,15 +5218,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7d/eb/b6260b31b1a96386c0a880edebe26f89669098acea8e0318bff6adb378fd/pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2", size = 9592, upload-time = "2025-01-10T18:43:11.88Z" }, ] -[[package]] -name = "pathspec" -version = "1.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, -] - [[package]] name = "pillow" version = "12.2.0" @@ -6265,35 +6215,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6c/a0/4ed6632b70a52de845df056654162acdebaf97c20e3212c559ac43e7216e/python_ulid-3.1.0-py3-none-any.whl", hash = "sha256:e2cdc979c8c877029b4b7a38a6fba3bc4578e4f109a308419ff4d3ccf0a46619", size = 11577, upload-time = "2025-08-18T16:09:25.047Z" }, ] -[[package]] -name = "pytokens" -version = "0.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/24/f206113e05cb8ef51b3850e7ef88f20da6f4bf932190ceb48bd3da103e10/pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5", size = 161522, upload-time = "2026-01-30T01:02:50.393Z" }, - { url = "https://files.pythonhosted.org/packages/d4/e9/06a6bf1b90c2ed81a9c7d2544232fe5d2891d1cd480e8a1809ca354a8eb2/pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe", size = 246945, upload-time = "2026-01-30T01:02:52.399Z" }, - { url = "https://files.pythonhosted.org/packages/69/66/f6fb1007a4c3d8b682d5d65b7c1fb33257587a5f782647091e3408abe0b8/pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c", size = 259525, upload-time = "2026-01-30T01:02:53.737Z" }, - { url = "https://files.pythonhosted.org/packages/04/92/086f89b4d622a18418bac74ab5db7f68cf0c21cf7cc92de6c7b919d76c88/pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7", size = 262693, upload-time = "2026-01-30T01:02:54.871Z" }, - { url = "https://files.pythonhosted.org/packages/b4/7b/8b31c347cf94a3f900bdde750b2e9131575a61fdb620d3d3c75832262137/pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2", size = 103567, upload-time = "2026-01-30T01:02:56.414Z" }, - { url = "https://files.pythonhosted.org/packages/3d/92/790ebe03f07b57e53b10884c329b9a1a308648fc083a6d4a39a10a28c8fc/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440", size = 160864, upload-time = "2026-01-30T01:02:57.882Z" }, - { url = "https://files.pythonhosted.org/packages/13/25/a4f555281d975bfdd1eba731450e2fe3a95870274da73fb12c40aeae7625/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc", size = 248565, upload-time = "2026-01-30T01:02:59.912Z" }, - { url = "https://files.pythonhosted.org/packages/17/50/bc0394b4ad5b1601be22fa43652173d47e4c9efbf0044c62e9a59b747c56/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d", size = 260824, upload-time = "2026-01-30T01:03:01.471Z" }, - { url = "https://files.pythonhosted.org/packages/4e/54/3e04f9d92a4be4fc6c80016bc396b923d2a6933ae94b5f557c939c460ee0/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16", size = 264075, upload-time = "2026-01-30T01:03:04.143Z" }, - { url = "https://files.pythonhosted.org/packages/d1/1b/44b0326cb5470a4375f37988aea5d61b5cc52407143303015ebee94abfd6/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6", size = 103323, upload-time = "2026-01-30T01:03:05.412Z" }, - { url = "https://files.pythonhosted.org/packages/41/5d/e44573011401fb82e9d51e97f1290ceb377800fb4eed650b96f4753b499c/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083", size = 160663, upload-time = "2026-01-30T01:03:06.473Z" }, - { url = "https://files.pythonhosted.org/packages/f0/e6/5bbc3019f8e6f21d09c41f8b8654536117e5e211a85d89212d59cbdab381/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1", size = 255626, upload-time = "2026-01-30T01:03:08.177Z" }, - { url = "https://files.pythonhosted.org/packages/bf/3c/2d5297d82286f6f3d92770289fd439956b201c0a4fc7e72efb9b2293758e/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1", size = 269779, upload-time = "2026-01-30T01:03:09.756Z" }, - { url = "https://files.pythonhosted.org/packages/20/01/7436e9ad693cebda0551203e0bf28f7669976c60ad07d6402098208476de/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9", size = 268076, upload-time = "2026-01-30T01:03:10.957Z" }, - { url = "https://files.pythonhosted.org/packages/2e/df/533c82a3c752ba13ae7ef238b7f8cdd272cf1475f03c63ac6cf3fcfb00b6/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68", size = 103552, upload-time = "2026-01-30T01:03:12.066Z" }, - { url = "https://files.pythonhosted.org/packages/cb/dc/08b1a080372afda3cceb4f3c0a7ba2bde9d6a5241f1edb02a22a019ee147/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b", size = 160720, upload-time = "2026-01-30T01:03:13.843Z" }, - { url = "https://files.pythonhosted.org/packages/64/0c/41ea22205da480837a700e395507e6a24425151dfb7ead73343d6e2d7ffe/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f", size = 254204, upload-time = "2026-01-30T01:03:14.886Z" }, - { url = "https://files.pythonhosted.org/packages/e0/d2/afe5c7f8607018beb99971489dbb846508f1b8f351fcefc225fcf4b2adc0/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1", size = 268423, upload-time = "2026-01-30T01:03:15.936Z" }, - { url = "https://files.pythonhosted.org/packages/68/d4/00ffdbd370410c04e9591da9220a68dc1693ef7499173eb3e30d06e05ed1/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4", size = 266859, upload-time = "2026-01-30T01:03:17.458Z" }, - { url = "https://files.pythonhosted.org/packages/a7/c9/c3161313b4ca0c601eeefabd3d3b576edaa9afdefd32da97210700e47652/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78", size = 103520, upload-time = "2026-01-30T01:03:18.652Z" }, - { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" }, -] - [[package]] name = "pytz" version = "2026.2"