mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
refactor(types): replace Any with proven types in 157 files (#44798)
* refactor(types): replace Any with proven types in 299 files Clears 871 basedpyright Any errors (reportAny 6,703 to 6,240, reportExplicitAny 1,651 to 1,243) without adding a cast, an ignore or a suppression, and without touching any budget file Most edits are annotation-only: a parameter, return or local goes from Any to object, Mapping[str, object] or the concrete type the value always held. Fourteen files validate untyped JSON once where it enters, through a module-level pydantic TypeAdapter or model_validate, and then use real types No HTTP status, error type or response shape changes. Mistral speech and fal.ai Bria image generation now report a pydantic ValidationError instead of an AttributeError when the provider answers 2xx with a body that is not a JSON object * refactor(types): make the config locals fix effective and trim no-op edits The Mapping[str, object] annotation on `locals().copy()` removed no error, because the checker narrows the variable back to the dict[str, Any] the call returns. 21 provider config constructors now build the same copy with dict(locals()), which the checker infers as object values under that annotation, so each file loses one reportAny. The same annotation is reverted in 31 other config files where it stayed a no-op, together with the tests that were added only to cover those lines, and the one MCP server manager line that no CI coverage shard executes is reverted too. The pull request drops from 345 to 297 changed files. * refactor(types): accept only int in the proxy state setter get_proxy_state_variable is annotated to return int, but set_proxy_state_variable still took Any, so the checker could not hold callers to the type the getter promises. The setter now takes int, which is what its only caller already passes. * refactor(types): index the proxy state key so the getter returns int * refactor(types): keep public annotations and provider error text unchanged Restore every public return, public method parameter, public attribute and exported alias to its annotation on main so code that type-checks against the package keeps type-checking, and take the Mistral speech and fal.ai Bria changes back out so no provider error message differs from main * refactor(types): leave the Vertex RAG chunking read as it is on main Take the chunking format validation back out of the Vertex RAG ingestion path. It needs the vertexai SDK, a storage bucket and a RAG corpus to execute, so nothing here could run it end to end, and it cleared only two errors * test(integration): pin the validated provider boundaries on a live proxy * test(integration): give the held burst a client that outlasts the gate The fault cell holds a burst at the upstream for up to 60 seconds while it kills a worker, but sent the burst through the shared 15 second client, so a slow box could time the survivors out before the gate opened. The burst now goes through its own client whose timeout is twice the gate, and the gate length is one named constant. * refactor(types): keep the license reply handling and experimental MCP signatures as they were The license check validated the whole reply as a mapping, which changed the error text logged for a reply that is not an object. It now validates only the verify value, so every reply is handled and logged exactly as before while the value is still typed. Three files under the experimental MCP server changed annotations on public functions and methods (three returns and three parameters). They go back to their previous content so no public signature in the diff is narrowed. * test(integration): answer the proxy's model-list call in the OpenAI stand-ins Every 300 seconds each proxy worker asks an OpenAI deployment for GET /v1/models. Four new cells own an OpenAI stand-in that accepted only the call under test, so a refresh landing inside a cell failed it. The stand-ins now answer that call through the suite's own helper and the cells count only the provider calls they drive.
This commit is contained in:
parent
126e79c967
commit
d4a791d650
191 changed files with 2852 additions and 290 deletions
|
|
@ -239,7 +239,7 @@ def create_assistants(
|
|||
temperature: float | None = None,
|
||||
top_p: float | None = None,
|
||||
response_format: str | dict[str, str] | None = None,
|
||||
client: Any | None = None,
|
||||
client: object | None = None,
|
||||
api_key: str | None = None,
|
||||
api_base: str | None = None,
|
||||
api_version: str | None = None,
|
||||
|
|
@ -410,7 +410,7 @@ async def adelete_assistant(
|
|||
def delete_assistant(
|
||||
custom_llm_provider: Literal["openai", "azure"],
|
||||
assistant_id: str,
|
||||
client: Any | None = None,
|
||||
client: object | None = None,
|
||||
api_key: str | None = None,
|
||||
api_base: str | None = None,
|
||||
api_version: str | None = None,
|
||||
|
|
@ -1181,7 +1181,7 @@ async def arun_thread(
|
|||
model: str | None = None,
|
||||
stream: bool | None = None,
|
||||
tools: Iterable[AssistantToolParam] | None = None,
|
||||
client: Any | None = None,
|
||||
client: object | None = None,
|
||||
**kwargs,
|
||||
) -> Run:
|
||||
loop: Final = asyncio.get_event_loop()
|
||||
|
|
@ -1246,7 +1246,7 @@ def run_thread(
|
|||
model: str | None = None,
|
||||
stream: bool | None = None,
|
||||
tools: Iterable[AssistantToolParam] | None = None,
|
||||
client: Any | None = None,
|
||||
client: object | None = None,
|
||||
event_handler: AssistantEventHandler | None = None, # for stream=True calls
|
||||
**kwargs,
|
||||
) -> Run:
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ class ValkeySemanticCache(RedisSemanticCache):
|
|||
kwargs.setdefault("metadata", {})["semantic-similarity"] = similarity
|
||||
|
||||
@staticmethod
|
||||
def _embedding_metadata(kwargs: dict[str, Any]) -> dict[str, Any] | None:
|
||||
def _embedding_metadata(kwargs: dict[str, Any]) -> dict[str, object] | None:
|
||||
"""The request metadata forwarded to the embedding call."""
|
||||
return kwargs.get("metadata")
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Computes cosine similarity between the query embedding and each message embeddin
|
|||
|
||||
import math
|
||||
from collections.abc import Mapping
|
||||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
from litellm.caching.dual_cache import DualCache
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ def embedding_score_messages(
|
|||
# Filter out empty texts — replace with a placeholder to maintain indexing
|
||||
processed_texts: Final = [t if t.strip() else "empty" for t in texts]
|
||||
|
||||
kwargs: dict[str, Any] = {
|
||||
kwargs: dict[str, object] = {
|
||||
"model": model,
|
||||
"input": processed_texts,
|
||||
"caching": cache is not None,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ from functools import partial
|
|||
from pathlib import Path
|
||||
from typing import Final, Literal
|
||||
|
||||
from pydantic import ConfigDict, TypeAdapter
|
||||
|
||||
import litellm
|
||||
from litellm.constants import request_timeout as DEFAULT_REQUEST_TIMEOUT
|
||||
from litellm.containers.utils import decode_managed_container_id_for_request
|
||||
|
|
@ -33,13 +35,14 @@ RESPONSE_TYPES: Final[dict[str, type]] = {
|
|||
"ContainerFileObject": ContainerFileObject,
|
||||
"DeleteContainerFileResponse": DeleteContainerFileResponse,
|
||||
}
|
||||
_ENDPOINTS_DOCUMENT: Final = TypeAdapter(dict[str, object], config=ConfigDict(hide_input_in_errors=True))
|
||||
|
||||
|
||||
def _load_endpoints_config() -> dict:
|
||||
"""Load the endpoints configuration from JSON file."""
|
||||
config_path: Final = Path(__file__).parent / "endpoints.json"
|
||||
with open(config_path) as f:
|
||||
return json.load(f)
|
||||
return _ENDPOINTS_DOCUMENT.validate_python(json.load(f))
|
||||
|
||||
|
||||
def create_sync_endpoint_function(endpoint_config: dict) -> Callable:
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class BaseGoogleGenAIGenerateContentStreamingIterator:
|
|||
self.endpoint_type: Final = (
|
||||
EndpointType.GEMINI if custom_llm_provider == litellm.LlmProviders.GEMINI.value else EndpointType.VERTEX_AI
|
||||
)
|
||||
self._hidden_params: dict[str, Any] = hidden_params or {}
|
||||
self._hidden_params: dict[str, object] = hidden_params or {}
|
||||
|
||||
async def _handle_async_streaming_logging(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -628,8 +628,8 @@ class ModelEndpoint:
|
|||
|
||||
def _sdk_kwargs(
|
||||
self, body: Mapping[str, object]
|
||||
) -> dict[str, Any]: # mutable-ok: SDK call kwargs, mutated by _invoke_sdk then splatted
|
||||
kwargs: dict[str, Any] = {**body} # mutable-ok: SDK call kwargs built from the JSON body, then overridden
|
||||
) -> dict[str, object]: # mutable-ok: SDK call kwargs, mutated by _invoke_sdk then splatted
|
||||
kwargs: dict[str, object] = {**body} # mutable-ok: SDK call kwargs built from the JSON body, then overridden
|
||||
if self.model:
|
||||
kwargs["model"] = self.model
|
||||
if self.api_key:
|
||||
|
|
|
|||
|
|
@ -1807,7 +1807,7 @@ Model Info:
|
|||
|
||||
async def _run_scheduled_daily_report(
|
||||
self,
|
||||
llm_router: Any | None = None,
|
||||
llm_router: object | None = None,
|
||||
pod_lock_manager: "PodLockManager | None" = None,
|
||||
):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ gzip JSONEachRow insert, either every `CLICKHOUSE_FLUSH_INTERVAL_SECONDS` or as
|
|||
import asyncio
|
||||
from collections.abc import Mapping, Sequence
|
||||
from contextlib import suppress
|
||||
from typing import Any, ClassVar, Final
|
||||
from typing import ClassVar, Final
|
||||
|
||||
from litellm._logging import verbose_logger
|
||||
from litellm.constants import (
|
||||
|
|
@ -89,7 +89,7 @@ class ClickHouseBatchLogger(CustomBatchLogger):
|
|||
async def async_send_batch(self) -> None:
|
||||
await self.flush_queue()
|
||||
|
||||
async def _insert(self, batch: list[dict[str, Any]]) -> bool:
|
||||
async def _insert(self, batch: list[dict[str, object]]) -> bool:
|
||||
try:
|
||||
await self.storage.insert_rows(self.table, batch)
|
||||
self.rows_written += len(batch)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class CloudZeroStreamer:
|
|||
|
||||
def _group_by_date(self, data: pl.DataFrame) -> dict[str, pl.DataFrame]:
|
||||
"""Group data by date, converting to UTC and validating dates."""
|
||||
daily_batches: Final[dict[str, list[dict[str, Any]]]] = {}
|
||||
daily_batches: Final[dict[str, list[dict[str, object]]]] = {}
|
||||
|
||||
# Ensure we have the required columns
|
||||
if "time/usage_start" not in data.columns:
|
||||
|
|
@ -209,7 +209,7 @@ class CloudZeroStreamer:
|
|||
|
||||
return payload
|
||||
|
||||
def _convert_cbf_to_api_format(self, row: dict[str, Any]) -> dict[str, Any] | None:
|
||||
def _convert_cbf_to_api_format(self, row: dict[str, object]) -> dict[str, Any] | None:
|
||||
"""Convert CBF row to CloudZero API format - keeping CBF field names as CloudZero expects them."""
|
||||
try:
|
||||
# CloudZero expects CBF format field names directly, not converted names
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
"""Database connection and data extraction for LiteLLM."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
import polars as pl
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ class LiteLLMDatabase:
|
|||
ORDER BY dus.date DESC, dus.created_at DESC
|
||||
"""
|
||||
|
||||
params: Final[list[Any]] = [
|
||||
params: Final[list[object]] = [
|
||||
start_time_utc,
|
||||
end_time_utc,
|
||||
]
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class FocusDestinationFactory:
|
|||
def _resolve_config(
|
||||
*,
|
||||
provider: str,
|
||||
overrides: dict[str, Any],
|
||||
overrides: dict[str, object],
|
||||
) -> dict[str, Any]:
|
||||
if provider == "s3":
|
||||
resolved = {
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class GenericPromptManager(CustomPromptManagement):
|
|||
headers["Authorization"] = f"Bearer {self.api_key}"
|
||||
return headers
|
||||
|
||||
def _fetch_prompt_from_api(self, prompt_id: str | None, prompt_spec: PromptSpec | None) -> dict[str, Any]:
|
||||
def _fetch_prompt_from_api(self, prompt_id: str | None, prompt_spec: PromptSpec | None) -> dict[str, object]:
|
||||
"""
|
||||
Fetch a prompt from the API.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import TYPE_CHECKING, Any, Final
|
||||
from typing import TYPE_CHECKING, Final
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from litellm.integrations.custom_prompt_management import CustomPromptManagement
|
||||
|
|
@ -66,7 +66,7 @@ def _gitlab_prompt_initializer(
|
|||
# You can store arbitrary integration-specific config on PromptLiteLLMParams.
|
||||
# If your dataclass doesn't have these attributes, add them or put inside
|
||||
# `litellm_params.extra` and pull them from there.
|
||||
gitlab_config: Final[dict[str, Any]] = getattr(litellm_params, "gitlab_config", None) or {}
|
||||
gitlab_config: Final[dict[str, object]] = getattr(litellm_params, "gitlab_config", None) or {}
|
||||
git_ref: Final[str | None] = getattr(litellm_params, "git_ref", None)
|
||||
|
||||
if not gitlab_config:
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class LangFuseHandler:
|
|||
return globalLangfuseLogger
|
||||
|
||||
credentials_dict: dict[
|
||||
str, Any
|
||||
str, object
|
||||
] = {} # the global langfuse logger uses Environment Variables, there are no dynamic credentials
|
||||
globalLangfuseLogger = in_memory_dynamic_logger_cache.get_cache(
|
||||
credentials=credentials_dict,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import time
|
|||
from collections import OrderedDict
|
||||
from collections.abc import Callable, Iterable, Mapping, Sequence
|
||||
from types import MappingProxyType
|
||||
from typing import TYPE_CHECKING, Any, Final, Literal
|
||||
from typing import TYPE_CHECKING, Final, Literal
|
||||
|
||||
from opentelemetry import _logs, baggage, metrics, trace
|
||||
from opentelemetry._logs import Logger, LoggerProvider, NoOpLoggerProvider
|
||||
|
|
@ -1072,7 +1072,7 @@ def build_metric_reader(config: OpenTelemetryV2Config) -> "MetricReader":
|
|||
)
|
||||
|
||||
tls: Final = resolve_otlp_http_tls("METRICS")
|
||||
exporter: Any = HTTPMetricExporter(
|
||||
exporter: object = HTTPMetricExporter(
|
||||
endpoint=_otlp_metrics_endpoint(config.endpoint),
|
||||
headers=parse_headers(config.headers),
|
||||
certificate_file=tls.certificate_file,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ worker thread, off any event loop — and caches it for the process lifetime.
|
|||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
import httpx
|
||||
from opentelemetry.sdk.trace import ReadableSpan
|
||||
|
|
@ -117,7 +117,7 @@ def _build_agentops_exporter(spec: ExporterSpec) -> SpanExporter:
|
|||
return _LazyAuthAgentOpsExporter(endpoint=spec.endpoint, api_key=options.get("api_key"))
|
||||
|
||||
|
||||
def _fetch_agentops_jwt(api_key: str) -> dict[str, Any]:
|
||||
def _fetch_agentops_jwt(api_key: str) -> dict[str, object]:
|
||||
# Own a short-lived client rather than ``_get_httpx_client()``: that returns
|
||||
# a process-wide cached ``HTTPHandler`` whose connection pool is shared by
|
||||
# every caller, so closing it here would break concurrent/subsequent
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Helpers for the Prometheus integration (extracted to keep ``prometheus.py`` smal
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Final, cast
|
||||
from typing import Final, cast
|
||||
|
||||
from litellm.types.integrations.prometheus import (
|
||||
UserAPIKeyLabelValues,
|
||||
|
|
@ -66,7 +66,7 @@ class PrometheusLabelFactoryContext:
|
|||
for k, v in get_custom_labels_from_tags(enum_values.tags).items():
|
||||
self._tag_labels[k] = _sanitize_prometheus_label_value(v)
|
||||
# Use a dedicated sentinel so `None` can be cached as a computed result.
|
||||
self._resolved_end_user: Any = self._END_USER_NOT_COMPUTED
|
||||
self._resolved_end_user: object = self._END_USER_NOT_COMPUTED
|
||||
|
||||
def get_resolved_end_user(self) -> str | None:
|
||||
if self._resolved_end_user is self._END_USER_NOT_COMPUTED:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ This module handles transforming between:
|
|||
|
||||
from collections.abc import Mapping, Sequence
|
||||
from types import MappingProxyType
|
||||
from typing import Any, Final, cast
|
||||
from typing import Final, cast
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
|
@ -251,7 +251,7 @@ class LiteLLMResponsesInteractionsConfig:
|
|||
|
||||
# Build interactions response — populate both `outputs` (legacy schema) and
|
||||
# `steps` (new schema) so callers work regardless of which schema they expect.
|
||||
interactions_response_dict: Final[dict[str, Any]] = {
|
||||
interactions_response_dict: Final[dict[str, object]] = {
|
||||
"id": getattr(responses_response, "id", ""),
|
||||
"object": "interaction",
|
||||
"status": interactions_status,
|
||||
|
|
@ -274,4 +274,4 @@ class LiteLLMResponsesInteractionsConfig:
|
|||
# Add updated (same as created for now)
|
||||
interactions_response_dict["updated"] = created
|
||||
|
||||
return InteractionsAPIResponse(**interactions_response_dict)
|
||||
return InteractionsAPIResponse.model_validate(interactions_response_dict)
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ def encode_s3_object_key_for_url(object_key: str) -> str:
|
|||
|
||||
|
||||
def should_allow_legacy_cloud_file_ids(
|
||||
litellm_params: Mapping[str, Any] | None = None,
|
||||
litellm_params: Mapping[str, object] | None = None,
|
||||
) -> bool:
|
||||
value = None
|
||||
if isinstance(litellm_params, Mapping):
|
||||
|
|
|
|||
|
|
@ -725,7 +725,7 @@ def redact_nested_match_and_regex_keys(
|
|||
if payload is None or isinstance(payload, str):
|
||||
return payload
|
||||
try:
|
||||
redacted: Final[dict | list[Any] | str | None] = copy.deepcopy(payload)
|
||||
redacted: Final[dict | list[object] | str | None] = copy.deepcopy(payload)
|
||||
except Exception:
|
||||
return payload
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ from types import MappingProxyType
|
|||
from typing import Final, Protocol
|
||||
|
||||
import httpx
|
||||
from pydantic import TypeAdapter
|
||||
from pydantic import ConfigDict, TypeAdapter
|
||||
from typing_extensions import ReadOnly, TypedDict
|
||||
|
||||
from litellm import verbose_logger
|
||||
|
|
@ -40,6 +40,7 @@ from litellm.litellm_core_utils.fallback_generalizations import (
|
|||
|
||||
FALLBACK_GENERALIZATIONS_KEY: Final = "fallback_generalizations"
|
||||
_CATALOG_ADAPTER: Final = TypeAdapter(dict[str, dict[str, object]])
|
||||
_BUNDLED_CATALOG_ADAPTER: Final = TypeAdapter(dict[str, object], config=ConfigDict(hide_input_in_errors=True))
|
||||
_CLI_ENTRYPOINT_NAMES: Final = frozenset({"lite", "litellm-proxy"})
|
||||
|
||||
|
||||
|
|
@ -83,7 +84,7 @@ class GetModelCostMap:
|
|||
@staticmethod
|
||||
def load_local_model_cost_map_with_revision() -> "ModelCostMapReloaded":
|
||||
body: Final = GetModelCostMap.read_local_model_cost_map_bytes()
|
||||
content: Final = json.loads(body)
|
||||
content: Final = _BUNDLED_CATALOG_ADAPTER.validate_python(json.loads(body))
|
||||
return ModelCostMapReloaded(model_cost_map=content, revision=git_blob_id(body))
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -230,7 +231,7 @@ class _FetchAttemptRetryable:
|
|||
|
||||
|
||||
def _parse_retry_after_seconds(response: httpx.Response) -> float | None:
|
||||
header: Final = response.headers.get("Retry-After")
|
||||
header: Final[str | None] = response.headers.get("Retry-After")
|
||||
if header is None:
|
||||
return None
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ _trusted_overlay_callback_params: Final = frozenset(
|
|||
)
|
||||
|
||||
|
||||
def get_trusted_callback_params(kwargs: Mapping[str, Any] | None) -> tuple[tuple[str, str], ...]:
|
||||
def get_trusted_callback_params(kwargs: Mapping[str, object] | None) -> tuple[tuple[str, str], ...]:
|
||||
"""
|
||||
Read callback params the proxy itself stamped from admin-configured team/key callback settings.
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ _DATA_URI_RE: Final = re.compile(r"data:([^;]+);base64,([A-Za-z0-9+/=]+)")
|
|||
_MAX_TRUNCATION_DEPTH: Final = 20
|
||||
|
||||
|
||||
def _base64_data_uri_replacer(match: re.Match) -> str:
|
||||
def _base64_data_uri_replacer(match: re.Match[str]) -> str:
|
||||
"""Replace a single base64 data-URI match with a size placeholder if too long."""
|
||||
mime_type: Final = match.group(1)
|
||||
payload: Final = match.group(2)
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ def should_redact_message_logging(model_call_details: dict) -> bool:
|
|||
return litellm.turn_off_message_logging is True
|
||||
|
||||
|
||||
def redact_message_input_output_from_logging(model_call_details: dict, result, input: Any | None = None) -> Any:
|
||||
def redact_message_input_output_from_logging(model_call_details: dict, result, input: object | None = None) -> Any:
|
||||
"""
|
||||
Removes messages, prompts, input, response from logging. This modifies the data in-place
|
||||
only redacts when litellm.turn_off_message_logging == True
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import json
|
|||
from typing import Any
|
||||
|
||||
|
||||
def safe_json_loads(data: str, default: Any = None) -> Any:
|
||||
def safe_json_loads(data: str, default: object = None) -> Any:
|
||||
"""
|
||||
Safely parse a JSON string. If parsing fails, return the default value (None by default).
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class SensitiveDataMasker:
|
|||
if depth >= max_depth:
|
||||
return data
|
||||
|
||||
masked_data: Final[dict[str, Any]] = {}
|
||||
masked_data: Final[dict[str, object]] = {}
|
||||
for k, v in data.items():
|
||||
try:
|
||||
key_is_sensitive = self.is_sensitive_key(k, excluded_keys)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.llm_cost_calc.utils import resolve_image_model_info
|
||||
|
|
@ -7,7 +7,7 @@ from litellm.types.utils import ImageResponse, ModelInfo
|
|||
|
||||
def cost_calculator(
|
||||
model: str,
|
||||
image_response: Any,
|
||||
image_response: object,
|
||||
model_info: ModelInfo | None = None,
|
||||
) -> float:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
metadata: dict | None = None,
|
||||
system: str | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -1645,7 +1645,7 @@ def strip_thinking_blocks_from_anthropic_messages_request_dict(
|
|||
|
||||
|
||||
def strip_empty_content_blocks_from_anthropic_messages(
|
||||
messages: list[Any],
|
||||
messages: Sequence[object],
|
||||
) -> list[Any]:
|
||||
"""
|
||||
Return a new message list with empty or whitespace-only ``{"type": "text"}``
|
||||
|
|
@ -1760,7 +1760,7 @@ def _sanitize_tool_use_id_content_block(block: object) -> object:
|
|||
return block
|
||||
|
||||
|
||||
def sanitize_tool_use_ids_in_anthropic_messages(messages: list[Any]) -> list[Any]:
|
||||
def sanitize_tool_use_ids_in_anthropic_messages(messages: Sequence[object]) -> list[Any]:
|
||||
"""
|
||||
Return a new message list with ``tool_use`` / ``server_tool_use`` ``id`` and
|
||||
``tool_result`` ``tool_use_id`` values rewritten to satisfy Anthropic's
|
||||
|
|
@ -1934,7 +1934,7 @@ def _flatten_web_search_results_in_message(message: object) -> object:
|
|||
|
||||
|
||||
def flatten_unencrypted_web_search_results_in_anthropic_messages(
|
||||
messages: list[Any],
|
||||
messages: Sequence[object],
|
||||
) -> list[Any]:
|
||||
"""
|
||||
Return a new message list with replayed ``web_search_tool_result`` blocks that
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Litellm provider slug: `anthropic_text/<model_name>`
|
|||
|
||||
import json
|
||||
import time
|
||||
from collections.abc import AsyncIterator, Iterator
|
||||
from collections.abc import AsyncIterator, Iterator, Mapping
|
||||
from typing import TYPE_CHECKING, Final
|
||||
|
||||
import httpx
|
||||
|
|
@ -73,7 +73,7 @@ class AnthropicTextConfig(BaseConfig):
|
|||
top_k: int | None = None,
|
||||
metadata: dict | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -962,7 +962,7 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
)
|
||||
elif isinstance(system_content, list):
|
||||
# Convert Anthropic system content blocks to OpenAI format
|
||||
openai_system_content: Final[list[dict[str, Any]]] = []
|
||||
openai_system_content: Final[list[dict[str, object]]] = []
|
||||
model_name: Final = anthropic_message_request.get("model", "")
|
||||
for block in system_content:
|
||||
if isinstance(block, dict) and block.get("type") == "text":
|
||||
|
|
|
|||
|
|
@ -361,7 +361,7 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
|
|||
self,
|
||||
headers: dict, # mutable-ok: out-param
|
||||
optional_params: dict, # mutable-ok: out-param
|
||||
messages: list[Any], # mutable-ok: mirrors the validate_anthropic_messages_environment contract
|
||||
messages: list[object], # mutable-ok: mirrors the validate_anthropic_messages_environment contract
|
||||
) -> dict: # mutable-ok: out-param
|
||||
if "anthropic-version" not in headers:
|
||||
headers["anthropic-version"] = DEFAULT_ANTHROPIC_API_VERSION
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ Used when the target model is an OpenAI or Azure model.
|
|||
"""
|
||||
|
||||
from collections.abc import AsyncIterator, Coroutine, Mapping
|
||||
from typing import Any, Final, TypeAlias
|
||||
from typing import Final, TypeAlias
|
||||
|
||||
import litellm
|
||||
from litellm.types.llms.anthropic import (
|
||||
|
|
@ -63,7 +63,7 @@ def _build_responses_kwargs(
|
|||
top_p: float | None = None,
|
||||
output_format: AnthropicOutputSchema | None = None,
|
||||
extra_kwargs: Mapping[str, object] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
) -> dict[str, object]:
|
||||
"""
|
||||
Build the kwargs dict to pass directly to litellm.responses() / litellm.aresponses().
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ class LiteLLMAnthropicToResponsesAPIAdapter:
|
|||
)
|
||||
elif isinstance(content, list):
|
||||
user_parts: list[Mapping[str, object]] = []
|
||||
tool_image_parts: list[dict[str, Any]] = [] # mutable-ok: json content parts
|
||||
tool_image_parts: list[dict[str, object]] = [] # mutable-ok: json content parts
|
||||
for block in content:
|
||||
if not isinstance(block, dict):
|
||||
continue
|
||||
|
|
@ -367,7 +367,7 @@ class LiteLLMAnthropicToResponsesAPIAdapter:
|
|||
for _, group in groupby(enumerate(blocks), key=self._assistant_block_group_key)
|
||||
for item in self._assistant_group_to_input_items(tuple(block for _, block in group))
|
||||
)
|
||||
asst_parts: list[dict[str, Any]] = [ # mutable-ok: API message payload
|
||||
asst_parts: list[dict[str, object]] = [ # mutable-ok: API message payload
|
||||
{"type": "output_text", "text": block.get("text", "")}
|
||||
for block in blocks
|
||||
if block.get("type") == "text"
|
||||
|
|
@ -533,7 +533,7 @@ class LiteLLMAnthropicToResponsesAPIAdapter:
|
|||
},
|
||||
)
|
||||
|
||||
responses_kwargs: Final[dict[str, Any]] = {
|
||||
responses_kwargs: Final[dict[str, object]] = {
|
||||
"model": model,
|
||||
"input": input_items,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class AzureOpenAIConfig(BaseConfig):
|
|||
temperature: int | None = None,
|
||||
top_p: int | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import os
|
|||
from collections.abc import Callable, Mapping
|
||||
from functools import lru_cache
|
||||
from types import MappingProxyType
|
||||
from typing import Any, Final, Literal, NamedTuple, cast
|
||||
from typing import Final, Literal, NamedTuple, cast
|
||||
|
||||
import httpx
|
||||
from openai import AsyncAzureOpenAI, AsyncOpenAI, AzureOpenAI, OpenAI
|
||||
|
|
@ -549,7 +549,7 @@ class BaseAzureLLM(BaseOpenAILLM):
|
|||
# on every request (via `_refresh_api_key`), so passing
|
||||
# `azure_ad_token_provider` directly preserves Azure AD token refresh
|
||||
# behavior that the regular AzureOpenAI client provides.
|
||||
v1_api_key: str | Callable[[], Any] | None = (
|
||||
v1_api_key: str | Callable[[], object] | None = (
|
||||
azure_client_params.get("api_key")
|
||||
or azure_client_params.get("azure_ad_token_provider")
|
||||
or azure_client_params.get("azure_ad_token")
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ class AzureTextCompletion(BaseAzureLLM):
|
|||
except Exception as e:
|
||||
status_code: Final = getattr(e, "status_code", 500)
|
||||
error_headers = getattr(e, "headers", None)
|
||||
error_response: Final = getattr(e, "response", None)
|
||||
error_response: Final[object] = getattr(e, "response", None)
|
||||
if error_headers is None and error_response:
|
||||
error_headers = getattr(error_response, "headers", None)
|
||||
raise AzureOpenAIError(status_code=status_code, message=str(e), headers=error_headers)
|
||||
|
|
@ -241,7 +241,7 @@ class AzureTextCompletion(BaseAzureLLM):
|
|||
except Exception as e:
|
||||
status_code: Final = getattr(e, "status_code", 500)
|
||||
error_headers = getattr(e, "headers", None)
|
||||
error_response: Final = getattr(e, "response", None)
|
||||
error_response: Final[object] = getattr(e, "response", None)
|
||||
if error_headers is None and error_response:
|
||||
error_headers = getattr(error_response, "headers", None)
|
||||
raise AzureOpenAIError(status_code=status_code, message=str(e), headers=error_headers)
|
||||
|
|
@ -352,7 +352,7 @@ class AzureTextCompletion(BaseAzureLLM):
|
|||
except Exception as e:
|
||||
status_code: Final = getattr(e, "status_code", 500)
|
||||
error_headers = getattr(e, "headers", None)
|
||||
error_response: Final = getattr(e, "response", None)
|
||||
error_response: Final[object] = getattr(e, "response", None)
|
||||
if error_headers is None and error_response:
|
||||
error_headers = getattr(error_response, "headers", None)
|
||||
raise AzureOpenAIError(status_code=status_code, message=str(e), headers=error_headers)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class AzureOpenAIExceptionMapping:
|
|||
|
||||
# Keep the OpenAI-style body fields populated so downstream (proxy + SDK)
|
||||
# can surface `type` / `code` correctly.
|
||||
openai_style_body: Final[dict[str, Any]] = {
|
||||
openai_style_body: Final[dict[str, object]] = {
|
||||
"message": provider_message,
|
||||
"type": provider_type or "invalid_request_error",
|
||||
"code": provider_code or "content_policy_violation",
|
||||
|
|
@ -54,7 +54,7 @@ class AzureOpenAIExceptionMapping:
|
|||
@staticmethod
|
||||
def _extract_azure_error(
|
||||
original_exception: Exception,
|
||||
) -> tuple[dict[str, Any], dict | None]:
|
||||
) -> tuple[dict[str, object], dict | None]:
|
||||
"""Extract Azure OpenAI error payload and inner error details.
|
||||
|
||||
Azure error formats can vary by endpoint/version. Common shapes:
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ class AzureAIAgentsConfig(BaseConfig):
|
|||
|
||||
converted_messages.append({"role": role, "content": content})
|
||||
|
||||
payload: Final[dict[str, Any]] = {
|
||||
payload: Final[dict[str, object]] = {
|
||||
"agent_id": agent_id,
|
||||
"messages": converted_messages,
|
||||
"api_version": self._get_api_version(optional_params),
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ class AzureAnthropicChatCompletion(AnthropicChatCompletion):
|
|||
status_code: Final = getattr(e, "status_code", 500)
|
||||
error_headers = getattr(e, "headers", None)
|
||||
error_text = getattr(e, "text", str(e))
|
||||
error_response: Final = getattr(e, "response", None)
|
||||
error_response: Final[object] = getattr(e, "response", None)
|
||||
if error_headers is None and error_response:
|
||||
error_headers = getattr(error_response, "headers", None)
|
||||
if error_response and hasattr(error_response, "text"):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.llm_cost_calc.utils import (
|
||||
|
|
@ -23,7 +23,7 @@ def _input_cost_per_pixel(resolved: ModelInfo) -> float:
|
|||
|
||||
def cost_calculator(
|
||||
model: str,
|
||||
image_response: Any,
|
||||
image_response: object,
|
||||
size: str | None = None,
|
||||
n: int | None = None,
|
||||
optional_params: Mapping[str, object] | None = None,
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ def blocked_responses_stream_usage(original_response: object) -> ResponseAPIUsag
|
|||
|
||||
|
||||
def effective_skip_system_message_for_guardrail(guardrail_to_apply: object) -> bool:
|
||||
per: Final = getattr(guardrail_to_apply, "skip_system_message_in_guardrail", None)
|
||||
per: Final[object] = getattr(guardrail_to_apply, "skip_system_message_in_guardrail", None)
|
||||
if per is not None:
|
||||
return bool(per)
|
||||
import litellm
|
||||
|
|
@ -201,7 +201,7 @@ def effective_skip_system_message_for_guardrail(guardrail_to_apply: object) -> b
|
|||
|
||||
|
||||
def effective_skip_tool_message_for_guardrail(guardrail_to_apply: object) -> bool:
|
||||
per: Final = getattr(guardrail_to_apply, "skip_tool_message_in_guardrail", None)
|
||||
per: Final[object] = getattr(guardrail_to_apply, "skip_tool_message_in_guardrail", None)
|
||||
if per is not None:
|
||||
return bool(per)
|
||||
import litellm
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ class BaseResponsesAPIConfig(ABC):
|
|||
"""
|
||||
if not isinstance(input, list):
|
||||
return input
|
||||
out: Final[list[Any]] = []
|
||||
out: Final[list[object]] = []
|
||||
for item in input:
|
||||
if isinstance(item, dict) and item.get("type") == "custom_tool_call":
|
||||
out.append({k: v for k, v in item.items() if k != "namespace"})
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ class BaseAWSLLM(SignsRequestsWithAWS):
|
|||
self,
|
||||
credential_args: Mapping[str, str | bool | tuple[AwsSessionTag, ...] | None],
|
||||
credential_fetcher: Callable[[], tuple[Credentials, int | None]],
|
||||
) -> Any:
|
||||
) -> Credentials:
|
||||
"""
|
||||
Read-through IAM cache on the process-wide ``DualCache``.
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ class AmazonConverseConfig(BaseConfig):
|
|||
topP: int | None = None,
|
||||
topK: int | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import types
|
||||
from collections.abc import Mapping
|
||||
from typing import Final
|
||||
|
||||
from litellm.llms.base_llm.chat.transformation import BaseConfig
|
||||
|
|
@ -46,7 +47,7 @@ class AmazonAI21Config(AmazonInvokeConfig, BaseConfig):
|
|||
presencePenalty: dict | None = None,
|
||||
countPenalty: dict | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import types
|
||||
from collections.abc import Mapping
|
||||
from typing import Final
|
||||
|
||||
from litellm.llms.bedrock.chat.invoke_transformations.base_invoke_transformation import (
|
||||
|
|
@ -27,7 +28,7 @@ class AmazonCohereConfig(AmazonInvokeConfig, CohereChatConfig):
|
|||
temperature: float | None = None,
|
||||
return_likelihood: str | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import types
|
||||
from collections.abc import Mapping
|
||||
from typing import Final
|
||||
|
||||
from litellm.llms.base_llm.chat.transformation import BaseConfig
|
||||
|
|
@ -28,7 +29,7 @@ class AmazonLlamaConfig(AmazonInvokeConfig, BaseConfig):
|
|||
temperature: float | None = None,
|
||||
topP: int | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import types
|
||||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Final
|
||||
|
||||
from litellm.llms.base_llm.chat.transformation import BaseConfig
|
||||
|
|
@ -37,7 +38,7 @@ class AmazonMistralConfig(AmazonInvokeConfig, BaseConfig):
|
|||
top_k: float | None = None,
|
||||
stop: list[str] | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Inherits from `AmazonInvokeConfig`
|
|||
Qwen3 + Invoke API Tutorial: https://docs.aws.amazon.com/bedrock/latest/userguide/invoke-imported-model.html
|
||||
"""
|
||||
|
||||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Final
|
||||
|
||||
import httpx
|
||||
|
|
@ -43,7 +44,7 @@ class AmazonQwen3Config(AmazonInvokeConfig, BaseConfig):
|
|||
top_k: int | None = None,
|
||||
stop: list[str] | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import re
|
||||
import types
|
||||
from collections.abc import Mapping
|
||||
from typing import Final
|
||||
|
||||
import litellm
|
||||
|
|
@ -33,7 +34,7 @@ class AmazonTitanConfig(AmazonInvokeConfig, BaseConfig):
|
|||
temperature: float | None = None,
|
||||
topP: int | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import types
|
||||
from collections.abc import Mapping
|
||||
from typing import Final
|
||||
|
||||
import litellm
|
||||
|
|
@ -36,7 +37,7 @@ class AmazonAnthropicConfig(AmazonInvokeConfig):
|
|||
top_p: int | None = None,
|
||||
anthropic_version: str | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ if TYPE_CHECKING:
|
|||
from litellm.types.llms.bedrock import BedrockCreateBatchRequest
|
||||
|
||||
import httpx
|
||||
from pydantic import TypeAdapter, ValidationError
|
||||
from pydantic import ConfigDict, TypeAdapter, ValidationError
|
||||
|
||||
import litellm
|
||||
from litellm import verbose_logger
|
||||
|
|
@ -1691,6 +1691,9 @@ def get_bedrock_chat_config(model: str):
|
|||
return litellm.AmazonInvokeConfig()
|
||||
|
||||
|
||||
_BOTOCORE_SERVICE_DESCRIPTION: Final = TypeAdapter(Mapping[str, object], config=ConfigDict(hide_input_in_errors=True))
|
||||
|
||||
|
||||
def _load_bedrock_response_stream_shape():
|
||||
"""
|
||||
Load the ResponseStream shape from botocore's bundled bedrock-runtime schema.
|
||||
|
|
@ -1703,7 +1706,9 @@ def _load_bedrock_response_stream_shape():
|
|||
from botocore.model import ServiceModel
|
||||
|
||||
loader: Final = Loader()
|
||||
service_dict: Final = loader.load_service_model("bedrock-runtime", "service-2")
|
||||
service_dict: Final = _BOTOCORE_SERVICE_DESCRIPTION.validate_python(
|
||||
loader.load_service_model("bedrock-runtime", "service-2")
|
||||
)
|
||||
return ServiceModel(service_dict).shape_for("ResponseStream")
|
||||
except Exception as e:
|
||||
verbose_logger.warning(
|
||||
|
|
@ -1856,9 +1861,12 @@ class BedrockEventStreamDecoderBase:
|
|||
return chunk.decode()
|
||||
|
||||
|
||||
_JSON_VALUE: Final = TypeAdapter(object)
|
||||
|
||||
|
||||
def _decoded_json_value(raw: str) -> object:
|
||||
"""Decode a JSON document into an opaque value for isinstance narrowing."""
|
||||
return json.loads(raw)
|
||||
return _JSON_VALUE.validate_python(json.loads(raw))
|
||||
|
||||
|
||||
def get_anthropic_beta_from_headers(headers: dict) -> list[str]:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ Docs - https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-tit
|
|||
"""
|
||||
|
||||
import types
|
||||
from collections.abc import Mapping
|
||||
from typing import Final
|
||||
|
||||
from litellm.types.llms.bedrock import (
|
||||
|
|
@ -27,7 +28,7 @@ class AmazonTitanG1Config:
|
|||
def __init__(
|
||||
self,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ Docs - https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-tit
|
|||
"""
|
||||
|
||||
import types
|
||||
from collections.abc import Mapping
|
||||
from typing import Final
|
||||
|
||||
from litellm.types.llms.bedrock import (
|
||||
|
|
@ -31,7 +32,7 @@ class AmazonTitanV2Config:
|
|||
dimensions: int | None = None
|
||||
|
||||
def __init__(self, normalize: bool | None = None, dimensions: int | None = None) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -855,8 +855,8 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
|
||||
@staticmethod
|
||||
def _merge_message_start_cache_into_delta_usage(
|
||||
delta_usage: dict[str, Any],
|
||||
start_usage: dict[str, Any] | None,
|
||||
delta_usage: dict[str, object],
|
||||
start_usage: Mapping[str, object] | None,
|
||||
) -> None:
|
||||
"""
|
||||
Copy cache breakdown from message_start onto message_delta usage when
|
||||
|
|
@ -885,7 +885,7 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
"""
|
||||
_CACHE_FIELDS: Final = ("cache_creation_input_tokens", "cache_read_input_tokens")
|
||||
pending_delta: dict[str, Any] | None = None
|
||||
start_usage_snapshot: dict[str, Any] | None = None
|
||||
start_usage_snapshot: Mapping[str, object] | None = None
|
||||
|
||||
async for chunk in completion_stream:
|
||||
if not isinstance(chunk, dict):
|
||||
|
|
@ -898,7 +898,7 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
chunk_type = chunk.get("type")
|
||||
|
||||
if chunk_type == "message_start":
|
||||
msg: dict[str, Any] = cast(dict[str, Any], chunk.get("message") or {})
|
||||
msg: dict[str, object] = cast(dict[str, Any], chunk.get("message") or {})
|
||||
u = msg.get("usage")
|
||||
if isinstance(u, dict):
|
||||
start_usage_snapshot = dict(u)
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class CodexStreamState:
|
|||
started: set[str] = field(default_factory=set) # mutable-ok: parser records announced tool items
|
||||
|
||||
|
||||
def _tool_input(item: Mapping[str, Any]) -> tuple[str, str, Mapping[str, Any], bool]:
|
||||
def _tool_input(item: Mapping[str, Any]) -> tuple[str, str, Mapping[str, object], bool]:
|
||||
"""(normalized name, native name, input, builtin) for a tool-like item."""
|
||||
item_type = item.get("type")
|
||||
if item_type == "command_execution":
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class CometAPIConfig(OpenAIGPTConfig):
|
|||
mapped_openai_params: Final = super().map_openai_params(non_default_params, optional_params, model, drop_params)
|
||||
|
||||
# CometAPI-specific parameters (if any)
|
||||
extra_body: Final[dict[str, Any]] = {}
|
||||
extra_body: Final[dict[str, object]] = {}
|
||||
# TODO: Add CometAPI-specific parameter handling here
|
||||
# Example:
|
||||
# custom_param = non_default_params.pop("custom_param", None)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.llm_cost_calc.utils import resolve_image_model_info
|
||||
|
|
@ -7,7 +7,7 @@ from litellm.types.utils import ImageResponse, ModelInfo
|
|||
|
||||
def cost_calculator(
|
||||
model: str,
|
||||
image_response: Any,
|
||||
image_response: object,
|
||||
model_info: ModelInfo | None = None,
|
||||
) -> float:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from pathlib import Path
|
|||
from typing import TYPE_CHECKING, Any, Final
|
||||
|
||||
import httpx
|
||||
from pydantic import TypeAdapter
|
||||
from typing_extensions import NotRequired, ReadOnly, TypedDict
|
||||
|
||||
import litellm
|
||||
|
|
@ -53,6 +54,9 @@ class EndpointsConfig(TypedDict):
|
|||
endpoints: ReadOnly[Sequence[EndpointConfig]]
|
||||
|
||||
|
||||
_ENDPOINTS_CONFIG: Final = TypeAdapter(EndpointsConfig)
|
||||
|
||||
|
||||
class ContainerErrorDetail(TypedDict, total=False):
|
||||
"""The ``error`` object of a container API error body."""
|
||||
|
||||
|
|
@ -81,7 +85,7 @@ def _load_endpoints_config() -> EndpointsConfig:
|
|||
"""Load the endpoints configuration from JSON file."""
|
||||
config_path: Final = Path(__file__).parent.parent.parent / "containers" / "endpoints.json"
|
||||
with open(config_path) as f:
|
||||
return json.load(f)
|
||||
return _ENDPOINTS_CONFIG.validate_python(json.load(f))
|
||||
|
||||
|
||||
def _get_endpoint_config(endpoint_name: str) -> EndpointConfig | None:
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Translates from OpenAI's `/v1/chat/completions` to DashScope's `/v1/chat/complet
|
|||
"""
|
||||
|
||||
from collections.abc import Coroutine
|
||||
from typing import Any, Final, Literal, overload
|
||||
from typing import Final, Literal, overload
|
||||
|
||||
from litellm.secret_managers.main import get_secret_str
|
||||
from litellm.types.llms.openai import AllMessageValues, ChatCompletionToolParam
|
||||
|
|
@ -33,7 +33,7 @@ class DashScopeChatConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -45,7 +45,7 @@ class DashScopeChatConfig(OpenAIGPTConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
if is_async:
|
||||
return super()._transform_messages(messages=messages, model=model, is_async=True)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import json
|
||||
from collections.abc import Coroutine
|
||||
from typing import Any, Final, Literal, cast, overload
|
||||
from collections.abc import Coroutine, Mapping
|
||||
from typing import Final, Literal, cast, overload
|
||||
|
||||
import litellm
|
||||
from litellm.constants import MIN_NON_ZERO_TEMPERATURE
|
||||
|
|
@ -50,7 +50,7 @@ class DeepInfraConfig(OpenAIGPTConfig):
|
|||
tools: list | None = None,
|
||||
tool_choice: str | dict | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
@ -154,7 +154,7 @@ class DeepInfraConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -166,7 +166,7 @@ class DeepInfraConfig(OpenAIGPTConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
"""
|
||||
Transform messages for DeepInfra compatibility.
|
||||
Handles both sync and async transformations.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Translates from OpenAI's `/v1/chat/completions` to DeepSeek's `/v1/chat/completi
|
|||
"""
|
||||
|
||||
from collections.abc import Coroutine, Mapping, Sequence
|
||||
from typing import Any, Final, Literal, cast, overload
|
||||
from typing import Final, Literal, cast, overload
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.prompt_templates.common_utils import (
|
||||
|
|
@ -104,7 +104,7 @@ class DeepSeekChatConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -116,7 +116,7 @@ class DeepSeekChatConfig(OpenAIGPTConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
"""
|
||||
DeepSeek vision models accept image_url content blocks in user
|
||||
messages (https://api-docs.deepseek.com/guides/vision), so those
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class DeepSeekAnthropicMessagesConfig(AnthropicMessagesConfig):
|
|||
return f"{base_url}/v1/messages"
|
||||
|
||||
@staticmethod
|
||||
def _sanitize_tools_for_deepseek(tools: Any) -> Any:
|
||||
def _sanitize_tools_for_deepseek(tools: Any) -> object:
|
||||
if not isinstance(tools, list):
|
||||
return tools
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ Docker Model Runner API Reference: https://docs.docker.com/ai/model-runner/api-r
|
|||
"""
|
||||
|
||||
from collections.abc import Coroutine
|
||||
from typing import Any, Final, Literal, overload
|
||||
from typing import Final, Literal, overload
|
||||
|
||||
from litellm.litellm_core_utils.prompt_templates.common_utils import (
|
||||
handle_messages_with_content_list_to_str_conversion,
|
||||
|
|
@ -27,7 +27,7 @@ class DockerModelRunnerChatConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -39,7 +39,7 @@ class DockerModelRunnerChatConfig(OpenAIGPTConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
"""
|
||||
Docker Model Runner is OpenAI-compatible, so we use standard message transformation.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class FalAIBytedanceBaseConfig(FalAIFluxProV11UltraConfig):
|
|||
|
||||
return optional_params
|
||||
|
||||
def _map_image_size(self, size: Any) -> Any:
|
||||
def _map_image_size(self, size: Any) -> object:
|
||||
if isinstance(size, dict):
|
||||
return size
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class FalAIFluxProV11Config(FalAIFluxProV11UltraConfig):
|
|||
|
||||
return optional_params
|
||||
|
||||
def _map_image_size(self, size: Any) -> Any:
|
||||
def _map_image_size(self, size: Any) -> object:
|
||||
if isinstance(size, dict):
|
||||
return size
|
||||
if not isinstance(size, str):
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class FalAIFluxSchnellConfig(FalAIFluxProV11UltraConfig):
|
|||
|
||||
return optional_params
|
||||
|
||||
def _map_image_size(self, size: Any) -> Any:
|
||||
def _map_image_size(self, size: Any) -> object:
|
||||
if isinstance(size, dict):
|
||||
return size
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ class FalAIIdeogramV3Config(FalAIBaseConfig):
|
|||
|
||||
return optional_params
|
||||
|
||||
def _map_image_size(self, size: Any) -> Any:
|
||||
def _map_image_size(self, size: Any) -> object:
|
||||
if isinstance(size, dict):
|
||||
width = size.get("width")
|
||||
height = size.get("height")
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ class FireworksAIConfig(FireworksAIMixin, OpenAIGPTConfig):
|
|||
top_p=top_p,
|
||||
response_format=response_format,
|
||||
)
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Final, cast
|
||||
|
||||
import litellm
|
||||
|
|
@ -68,7 +69,7 @@ class GoogleAIStudioGeminiConfig(VertexGeminiConfig):
|
|||
candidate_count: int | None = None,
|
||||
stop_sequences: list | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from collections.abc import Mapping, Sequence
|
|||
from typing import Any, Final
|
||||
|
||||
import httpx
|
||||
from pydantic import TypeAdapter
|
||||
|
||||
import litellm
|
||||
from litellm.constants import DEFAULT_MAX_RECURSE_DEPTH
|
||||
|
|
@ -128,9 +129,12 @@ def is_gemini_image_model(model: str) -> bool:
|
|||
return "gemini" in base_model
|
||||
|
||||
|
||||
_JSON_VALUE: Final = TypeAdapter(object)
|
||||
|
||||
|
||||
def _parse_image_config_string(raw_image_config: str, model: str) -> object:
|
||||
try:
|
||||
return json.loads(raw_image_config)
|
||||
return _JSON_VALUE.validate_python(json.loads(raw_image_config))
|
||||
except json.JSONDecodeError as exc:
|
||||
raise litellm.UnsupportedParamsError(
|
||||
model=model,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ else:
|
|||
|
||||
|
||||
class GoogleAIStudioTokenCounter:
|
||||
def _clean_contents_for_gemini_api(self, contents: Any) -> Any:
|
||||
def _clean_contents_for_gemini_api(self, contents: Any) -> object:
|
||||
"""
|
||||
Clean up contents to remove unsupported fields for the Gemini API.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
Gemini Image Edit Cost Calculator
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from litellm.llms.gemini.image_generation.cost_calculator import (
|
||||
cost_calculator as image_generation_cost_calculator,
|
||||
)
|
||||
|
|
@ -12,7 +10,7 @@ from litellm.types.utils import ModelInfo
|
|||
|
||||
def cost_calculator(
|
||||
model: str,
|
||||
image_response: Any,
|
||||
image_response: object,
|
||||
model_info: ModelInfo | None = None,
|
||||
) -> float:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Google AI Image Generation Cost Calculator
|
||||
"""
|
||||
|
||||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
from litellm.litellm_core_utils.llm_cost_calc.utils import (
|
||||
calculate_image_response_cost_from_usage,
|
||||
|
|
@ -14,7 +14,7 @@ from litellm.types.utils import ImageResponse, ModelInfo
|
|||
|
||||
def cost_calculator(
|
||||
model: str,
|
||||
image_response: Any,
|
||||
image_response: object,
|
||||
model_info: ModelInfo | None = None,
|
||||
) -> float:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
from litellm.types.utils import ImageUsage, ImageUsageInputTokensDetails
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ def transform_gemini_image_usage(usage_metadata: dict) -> ImageUsage:
|
|||
if output_tokens > known_output_tokens:
|
||||
output_tokens_details.text_tokens += output_tokens - known_output_tokens
|
||||
|
||||
usage_payload: Final[dict[str, Any]] = {
|
||||
usage_payload: Final[dict[str, object]] = {
|
||||
"input_tokens": usage_metadata.get("promptTokenCount", 0),
|
||||
"input_tokens_details": input_tokens_details,
|
||||
"output_tokens": output_tokens,
|
||||
|
|
@ -62,4 +62,4 @@ def transform_gemini_image_usage(usage_metadata: dict) -> ImageUsage:
|
|||
"completion_tokens_details": output_tokens_details.model_dump(),
|
||||
"output_tokens_details": output_tokens_details.model_dump(),
|
||||
}
|
||||
return ImageUsage(**usage_payload)
|
||||
return ImageUsage.model_validate(usage_payload)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import json
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Any, Final
|
||||
from collections.abc import Sequence
|
||||
from typing import TYPE_CHECKING, Final
|
||||
|
||||
import httpx
|
||||
|
||||
|
|
@ -177,8 +178,8 @@ class GithubCopilotConfig(OpenAIConfig):
|
|||
|
||||
@staticmethod
|
||||
def _parse_anthropic_native_content(
|
||||
content_blocks: list[Any],
|
||||
) -> tuple[str, list[ChatCompletionToolCallChunk], list[Any] | None]:
|
||||
content_blocks: list[object],
|
||||
) -> tuple[str, list[ChatCompletionToolCallChunk], Sequence[object] | None]:
|
||||
"""
|
||||
Parse Anthropic-native content blocks into OpenAI-compatible fields.
|
||||
|
||||
|
|
@ -225,7 +226,7 @@ class GithubCopilotConfig(OpenAIConfig):
|
|||
|
||||
content = ""
|
||||
tool_calls: list[ChatCompletionToolCallChunk] = []
|
||||
thinking_blocks: list[Any] | None = None
|
||||
thinking_blocks: Sequence[object] | None = None
|
||||
raw_content: Final = response_json.get("content")
|
||||
if isinstance(raw_content, list):
|
||||
content, tool_calls, thinking_blocks = cls._parse_anthropic_native_content(raw_content)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Translate from OpenAI's `/v1/chat/completions` to Groq's `/v1/chat/completions`
|
||||
"""
|
||||
|
||||
from collections.abc import AsyncIterator, Coroutine, Iterator
|
||||
from collections.abc import AsyncIterator, Coroutine, Iterator, Mapping
|
||||
from typing import TYPE_CHECKING, Any, Final, Literal, cast, overload
|
||||
|
||||
import httpx
|
||||
|
|
@ -72,7 +72,7 @@ class GroqChatConfig(OpenAILikeChatConfig):
|
|||
tools: list | None = None,
|
||||
tool_choice: str | dict | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
@ -125,7 +125,7 @@ class GroqChatConfig(OpenAILikeChatConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -137,7 +137,7 @@ class GroqChatConfig(OpenAILikeChatConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
for idx, message in enumerate(messages):
|
||||
"""
|
||||
1. Don't pass 'null' function_call assistant message to groq - https://github.com/BerriAI/litellm/issues/5839
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ this is OpenAI compatible - no translation needed / occurs
|
|||
|
||||
import os
|
||||
from collections.abc import Coroutine
|
||||
from typing import Any, Literal, overload
|
||||
from typing import Literal, overload
|
||||
|
||||
from litellm.litellm_core_utils.prompt_templates.common_utils import (
|
||||
handle_messages_with_content_list_to_str_conversion,
|
||||
|
|
@ -24,7 +24,7 @@ class HerokuChatConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -36,7 +36,7 @@ class HerokuChatConfig(OpenAIGPTConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
"""
|
||||
Heroku does not support content in list format.
|
||||
See: https://devcenter.heroku.com/articles/heroku-inference-api-v1-chat-completions#content-object
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ class LangFlowConfig(BaseConfig):
|
|||
|
||||
input_value: Final = self._get_last_user_message(messages)
|
||||
|
||||
payload: Final[dict[str, Any]] = {
|
||||
payload: Final[dict[str, object]] = {
|
||||
"input_value": input_value,
|
||||
"input_type": optional_params.get("input_type", "chat"),
|
||||
"output_type": optional_params.get("output_type", "chat"),
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ class LangGraphConfig(BaseConfig):
|
|||
return parts[1]
|
||||
return model
|
||||
|
||||
def _convert_messages_to_langgraph_format(self, messages: list[AllMessageValues]) -> list[dict[str, Any]]:
|
||||
def _convert_messages_to_langgraph_format(self, messages: list[AllMessageValues]) -> list[dict[str, object]]:
|
||||
"""
|
||||
Convert OpenAI-format messages to LangGraph format.
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ class LangGraphConfig(BaseConfig):
|
|||
|
||||
Preserves per-message ``metadata`` when present (e.g. A2A ``skillId``).
|
||||
"""
|
||||
langgraph_messages: Final[list[dict[str, Any]]] = []
|
||||
langgraph_messages: Final[list[dict[str, object]]] = []
|
||||
for msg in messages:
|
||||
role = msg.get("role", "user")
|
||||
content = msg.get("content", "")
|
||||
|
|
@ -167,7 +167,7 @@ class LangGraphConfig(BaseConfig):
|
|||
if not isinstance(content, str):
|
||||
content = str(content)
|
||||
|
||||
langgraph_message: dict[str, Any] = {
|
||||
langgraph_message: dict[str, object] = {
|
||||
"role": langgraph_role,
|
||||
"content": content,
|
||||
}
|
||||
|
|
@ -202,7 +202,7 @@ class LangGraphConfig(BaseConfig):
|
|||
assistant_id: Final = self._get_assistant_id(model, optional_params)
|
||||
langgraph_messages: Final = self._convert_messages_to_langgraph_format(messages)
|
||||
|
||||
payload: Final[dict[str, Any]] = {
|
||||
payload: Final[dict[str, object]] = {
|
||||
"assistant_id": assistant_id,
|
||||
"input": {"messages": langgraph_messages},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ class SkillPromptInjectionHandler:
|
|||
if len(description) > max_desc_length:
|
||||
description = description[: max_desc_length - 3] + "..."
|
||||
|
||||
input_schema: dict[str, Any] = {
|
||||
input_schema: dict[str, object] = {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": [],
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ Why separate file? Make it easy to see how transformation works
|
|||
Docs - https://docs.mistral.ai/api/
|
||||
"""
|
||||
|
||||
from collections.abc import AsyncIterator, Coroutine, Iterator
|
||||
from typing import TYPE_CHECKING, Any, Final, Literal, cast, get_type_hints, overload
|
||||
from collections.abc import AsyncIterator, Coroutine, Iterator, Mapping
|
||||
from typing import TYPE_CHECKING, Final, Literal, cast, get_type_hints, overload
|
||||
|
||||
import httpx
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ class MistralConfig(OpenAIGPTConfig):
|
|||
response_format: dict | None = None,
|
||||
stop: str | list | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
@ -229,7 +229,7 @@ class MistralConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]:
|
||||
...
|
||||
|
||||
@overload
|
||||
|
|
@ -244,7 +244,7 @@ class MistralConfig(OpenAIGPTConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
"""
|
||||
- handles scenario where content is list and not string
|
||||
- content list is just text, and no images
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Translates from OpenAI's `/v1/chat/completions` to ModelScope's `/v1/chat/comple
|
|||
"""
|
||||
|
||||
from collections.abc import Coroutine
|
||||
from typing import Any, Final, Literal, cast, overload
|
||||
from typing import Final, Literal, cast, overload
|
||||
|
||||
from typing_extensions import override
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ class ModelScopeChatConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -39,7 +39,7 @@ class ModelScopeChatConfig(OpenAIGPTConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
"""
|
||||
Flatten text-only content lists to strings for ModelScope.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Translates from OpenAI's `/v1/chat/completions` to Moonshot AI's `/v1/chat/compl
|
|||
"""
|
||||
|
||||
from collections.abc import Coroutine, Mapping
|
||||
from typing import Any, Final, Literal, cast, overload
|
||||
from typing import Final, Literal, cast, overload
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.prompt_templates.common_utils import (
|
||||
|
|
@ -29,7 +29,7 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -41,7 +41,7 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
"""
|
||||
Moonshot text-only models don't support content in list format.
|
||||
Multimodal models (kimi-k2.5, kimi-latest, etc.) accept the
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ class NvidiaRivaAudioTranscription:
|
|||
message="NvidiaRivaAudioTranscriptionConfig produced an unexpected request payload type.",
|
||||
)
|
||||
|
||||
recognition_config_dict: Final[dict[str, Any]] = request_payload["recognition_config"]
|
||||
recognition_config_dict: Final[dict[str, object]] = request_payload["recognition_config"]
|
||||
# The wire format is fixed by our resampler; override anything stale
|
||||
# the caller passed in so the gRPC config matches the bytes we send.
|
||||
recognition_config_dict["sample_rate_hertz"] = RIVA_TARGET_SAMPLE_RATE_HZ
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Common utilities and exceptions for the NVIDIA Riva STT provider
|
||||
"""
|
||||
|
||||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
from litellm.llms.base_llm.chat.transformation import BaseLLMException
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ _GRPC_STATUS_CODE_TO_HTTP: Final[dict] = {
|
|||
}
|
||||
|
||||
|
||||
def _extract_grpc_status_name(error: Any) -> str | None:
|
||||
def _extract_grpc_status_name(error: object) -> str | None:
|
||||
"""
|
||||
Best-effort extraction of a gRPC StatusCode name from an arbitrary error.
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ def _extract_grpc_status_name(error: Any) -> str | None:
|
|||
return None
|
||||
|
||||
|
||||
def _extract_grpc_details(error: Any) -> str | None:
|
||||
def _extract_grpc_details(error: object) -> str | None:
|
||||
"""Best-effort extraction of a human-readable detail string from a gRPC error."""
|
||||
details_fn: Final = getattr(error, "details", None)
|
||||
if callable(details_fn):
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ parsing, and streaming chunk parsing for models served with
|
|||
|
||||
import datetime
|
||||
import hashlib
|
||||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
import httpx
|
||||
from pydantic import ValidationError
|
||||
|
|
@ -404,7 +404,7 @@ def handle_generic_stream_chunk(dict_chunk: dict) -> ModelResponseStream:
|
|||
# same minimal ``{"id", "type", "function": {"name", "arguments"}}``
|
||||
# shape keeps downstream stream-mergers behaving identically across
|
||||
# GENERIC and Cohere chunks.
|
||||
tool_calls: list[dict[str, Any]] | None = None
|
||||
tool_calls: list[dict[str, object]] | None = None
|
||||
if typed_chunk.message and typed_chunk.message.toolCalls:
|
||||
tool_calls = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ def _normalize_response_format(selected_params: dict, vendor: OCIVendors) -> Non
|
|||
|
||||
if vendor == OCIVendors.COHERE:
|
||||
# OCI Cohere has no JSON_SCHEMA type; a schema rides on JSON_OBJECT.
|
||||
payload: Final[dict[str, Any]] = {"type": "JSON_OBJECT"}
|
||||
payload: Final[dict[str, object]] = {"type": "JSON_OBJECT"}
|
||||
if json_schema is not None and json_schema.get("schema") is not None:
|
||||
payload["schema"] = json_schema["schema"]
|
||||
selected_params["responseFormat"] = payload
|
||||
|
|
@ -212,7 +212,7 @@ def _normalize_response_format(selected_params: dict, vendor: OCIVendors) -> Non
|
|||
# OCI's ResponseJsonSchema accepts only name/description/schema/isStrict.
|
||||
# OpenAI sends `strict` instead of `isStrict`; forwarding it (or any
|
||||
# other extra key) makes OCI reject the whole request with HTTP 400.
|
||||
oci_schema: Final[dict[str, Any]] = {"name": json_schema.get("name") or "response"}
|
||||
oci_schema: Final[dict[str, object]] = {"name": json_schema.get("name") or "response"}
|
||||
if json_schema.get("description") is not None:
|
||||
oci_schema["description"] = json_schema["description"]
|
||||
if json_schema.get("schema") is not None:
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ async def ollama_aembeddings(
|
|||
prompts: list[str],
|
||||
model_response: EmbeddingResponse,
|
||||
optional_params: dict,
|
||||
logging_obj: Any,
|
||||
logging_obj: object,
|
||||
encoding: TokenEncoder | None,
|
||||
):
|
||||
if not api_base.endswith("/api/embed"):
|
||||
|
|
@ -114,7 +114,7 @@ def ollama_embeddings(
|
|||
prompts: list[str],
|
||||
optional_params: dict,
|
||||
model_response: EmbeddingResponse,
|
||||
logging_obj: Any,
|
||||
logging_obj: object,
|
||||
encoding: TokenEncoder | None = None,
|
||||
):
|
||||
if not api_base.endswith("/api/embed"):
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig):
|
|||
top_p: int | None = None,
|
||||
response_format: dict | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ class OpenAIChatCompletionsHandler(BaseTranslation):
|
|||
|
||||
def _not_run_reason(
|
||||
self,
|
||||
messages: Sequence[dict[str, Any]], # mutable-ok: raw request messages consumed by _extract_inputs
|
||||
messages: Sequence[Mapping[str, object]],
|
||||
) -> str | None:
|
||||
"""Why nothing was scanned, or None when the only unscoped content is images, which this handler never scans."""
|
||||
texts: Final[list[str]] = [] # mutable-ok: filled by _extract_inputs
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Translations handled by LiteLLM:
|
|||
"""
|
||||
|
||||
from collections.abc import Coroutine
|
||||
from typing import Any, Final, Literal, cast, overload
|
||||
from typing import Final, Literal, cast, overload
|
||||
|
||||
import litellm
|
||||
from litellm import verbose_logger
|
||||
|
|
@ -126,7 +126,7 @@ class OpenAIOSeriesConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -138,7 +138,7 @@ class OpenAIOSeriesConfig(OpenAIGPTConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
"""
|
||||
Handles limitations of O-1 model family.
|
||||
- modalities: image => drop param (if user opts in to dropping param)
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ class OpenAITextCompletion(BaseLLM):
|
|||
status_code: Final = getattr(e, "status_code", 500)
|
||||
error_headers = getattr(e, "headers", None)
|
||||
error_text: Final = getattr(e, "text", str(e))
|
||||
error_response: Final = getattr(e, "response", None)
|
||||
error_response: Final[object] = getattr(e, "response", None)
|
||||
if error_headers is None and error_response:
|
||||
error_headers = getattr(error_response, "headers", None)
|
||||
raise OpenAIError(status_code=status_code, message=error_text, headers=error_headers)
|
||||
|
|
@ -210,7 +210,7 @@ class OpenAITextCompletion(BaseLLM):
|
|||
status_code: Final = getattr(e, "status_code", 500)
|
||||
error_headers = getattr(e, "headers", None)
|
||||
error_text: Final = getattr(e, "text", str(e))
|
||||
error_response: Final = getattr(e, "response", None)
|
||||
error_response: Final[object] = getattr(e, "response", None)
|
||||
if error_headers is None and error_response:
|
||||
error_headers = getattr(error_response, "headers", None)
|
||||
raise OpenAIError(status_code=status_code, message=error_text, headers=error_headers)
|
||||
|
|
@ -248,7 +248,7 @@ class OpenAITextCompletion(BaseLLM):
|
|||
status_code = getattr(e, "status_code", 500)
|
||||
error_headers = getattr(e, "headers", None)
|
||||
error_text = getattr(e, "text", str(e))
|
||||
error_response = getattr(e, "response", None)
|
||||
error_response: object = getattr(e, "response", None)
|
||||
if error_headers is None and error_response:
|
||||
error_headers = getattr(error_response, "headers", None)
|
||||
raise OpenAIError(status_code=status_code, message=error_text, headers=error_headers)
|
||||
|
|
@ -315,7 +315,7 @@ class OpenAITextCompletion(BaseLLM):
|
|||
status_code: Final = getattr(e, "status_code", 500)
|
||||
error_headers = getattr(e, "headers", None)
|
||||
error_text: Final = getattr(e, "text", str(e))
|
||||
error_response: Final = getattr(e, "response", None)
|
||||
error_response: Final[object] = getattr(e, "response", None)
|
||||
if error_headers is None and error_response:
|
||||
error_headers = getattr(error_response, "headers", None)
|
||||
raise OpenAIError(status_code=status_code, message=error_text, headers=error_headers)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
Support for gpt model family
|
||||
"""
|
||||
|
||||
from collections.abc import Mapping
|
||||
from typing import Final
|
||||
|
||||
from litellm.llms.base_llm.completion.transformation import BaseTextCompletionConfig
|
||||
|
|
@ -69,7 +70,7 @@ class OpenAITextCompletionConfig(BaseTextCompletionConfig, OpenAIGPTConfig):
|
|||
temperature: float | None = None,
|
||||
top_p: float | None = None,
|
||||
) -> None:
|
||||
locals_: Final = locals().copy()
|
||||
locals_: Final[Mapping[str, object]] = dict(locals())
|
||||
for key, value in locals_.items():
|
||||
if key != "self" and value is not None:
|
||||
setattr(self.__class__, key, value)
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
|
|||
)
|
||||
|
||||
# Create ResponseReasoningItem object from the item data
|
||||
reasoning_item: Final = ResponseReasoningItem(**item_data)
|
||||
reasoning_item: Final = ResponseReasoningItem.model_validate(item_data)
|
||||
|
||||
# Convert back to dict with exclude_none=True to exclude None fields
|
||||
dict_reasoning_item: Final = reasoning_item.model_dump(exclude_none=True)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Dynamic configuration class generator for JSON-based providers.
|
|||
"""
|
||||
|
||||
from collections.abc import Coroutine
|
||||
from typing import TYPE_CHECKING, Any, Final, Literal, overload
|
||||
from typing import TYPE_CHECKING, Final, Literal, overload
|
||||
|
||||
from litellm._logging import verbose_logger
|
||||
from litellm.litellm_core_utils.prompt_templates.common_utils import (
|
||||
|
|
@ -30,7 +30,7 @@ def create_config_class(provider: SimpleProviderConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, list[AllMessageValues]]: ...
|
||||
) -> Coroutine[object, object, list[AllMessageValues]]: ...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -42,7 +42,7 @@ def create_config_class(provider: SimpleProviderConfig):
|
|||
|
||||
def _transform_messages(
|
||||
self, messages: list[AllMessageValues], model: str, is_async: bool = False
|
||||
) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
|
||||
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]:
|
||||
"""Transform messages based on special_handling config"""
|
||||
|
||||
# Handle content list to string conversion if configured
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ def build_opencode_config(
|
|||
extra_skills: Final = (skills_path,) if skills_path else ()
|
||||
skill_paths: Final = [*(user_skills.get("paths") or ()), *extra_skills] # mutable-ok: opencode config JSON
|
||||
options: Final = {"baseURL": base_url, "apiKey": "{file:" + token_path + "}"} # mutable-ok: opencode config JSON
|
||||
models: Final[dict[str, Any]] = {model: {}} # mutable-ok: opencode config JSON
|
||||
models: Final[dict[str, Mapping[str, object]]] = {model: {}} # mutable-ok: opencode config JSON
|
||||
provider: Final = { # mutable-ok: opencode config JSON
|
||||
"npm": OPENCODE_PROVIDER_NPM,
|
||||
"name": "LiteLLM",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.llm_cost_calc.utils import resolve_image_model_info
|
||||
|
|
@ -7,7 +7,7 @@ from litellm.types.utils import ImageResponse, ModelInfo
|
|||
|
||||
def cost_calculator(
|
||||
model: str,
|
||||
image_response: Any,
|
||||
image_response: object,
|
||||
model_info: ModelInfo | None = None,
|
||||
) -> float:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.llm_cost_calc.utils import resolve_image_model_info
|
||||
|
|
@ -7,7 +7,7 @@ from litellm.types.utils import ImageResponse, ModelInfo
|
|||
|
||||
def cost_calculator(
|
||||
model: str,
|
||||
image_response: Any,
|
||||
image_response: object,
|
||||
model_info: ModelInfo | None = None,
|
||||
) -> float:
|
||||
"""
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue