perf(types): defer pydantic schema builds via shared LiteLLMBaseModel (#44720)

* perf(types): defer pydantic schema builds via shared LiteLLMBaseModel

Add LiteLLMBaseModel with defer_build driven by DEFER_PYDANTIC_BUILD (default true) and move litellm and enterprise pydantic models onto it

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(types): build deferred models created by a parent validator; keep lens worker models litellm-free

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* chore(types): link pydantic issue on deferred-build rebuild hook

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: nate <nate@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
devin-ai-integration[bot] 2026-10-05 22:10:08 -07:00 • committed by GitHub
parent d7f69d6ba1
commit c2c0bb583e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
322 changed files with 2169 additions and 1724 deletions

View file

@ -15,11 +15,12 @@ from urllib.parse import urlencode, urlsplit
import httpx
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse, RedirectResponse, Response
from pydantic import BaseModel, ConfigDict, Field, SecretStr, TypeAdapter, ValidationError
from pydantic import ConfigDict, Field, SecretStr, TypeAdapter, ValidationError
from litellm.llms.custom_httpx.http_handler import get_async_httpx_client
from litellm.proxy._experimental.mcp_server.oauth_utils import get_request_base_url
from litellm.proxy._types import LiteLLM_UserTable, LitellmUserRoles, UserAPIKeyAuth
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.proxy.auth.auth_checks import UserNotFoundError
router: Final = APIRouter()
@ -34,14 +35,14 @@ _HEADERS: Final = {
}
class LinkDetails(BaseModel):
class LinkDetails(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, strict=True, extra="forbid")
workspace_id: str = Field(min_length=1, max_length=64)
slack_user_id: str = Field(min_length=1, max_length=64)
email: str = Field(min_length=1, max_length=320)
class AdminSession(BaseModel):
class AdminSession(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
user_id: str
credential: SecretStr

View file

@ -1,12 +1,13 @@
import enum
from typing import Dict, List, Optional
from pydantic import BaseModel, Field
from pydantic import Field
from litellm.proxy._types import WebhookEvent
from litellm.types.llms.base import LiteLLMBaseModel
class EmailParams(BaseModel):
class EmailParams(LiteLLMBaseModel):
logo_url: str
support_contact: str
base_url: str
@ -39,14 +40,14 @@ class EmailEvent(str, enum.Enum):
soft_budget_crossed = "Soft Budget Crossed"
max_budget_alert = "Max Budget Alert"
class EmailEventSettings(BaseModel):
class EmailEventSettings(LiteLLMBaseModel):
event: EmailEvent
enabled: bool
class EmailEventSettingsUpdateRequest(BaseModel):
class EmailEventSettingsUpdateRequest(LiteLLMBaseModel):
settings: List[EmailEventSettings]
class EmailEventSettingsResponse(BaseModel):
class EmailEventSettingsResponse(LiteLLMBaseModel):
settings: List[EmailEventSettings]
class DefaultEmailSettings(BaseModel):
class DefaultEmailSettings(LiteLLMBaseModel):
"""Default settings for email events"""
settings: Dict[EmailEvent, bool] = Field(
default_factory=lambda: {

View file

@ -1,10 +1,12 @@
from datetime import datetime
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field
from pydantic import Field
from litellm.types.llms.base import LiteLLMBaseModel
class AuditLogResponse(BaseModel):
class AuditLogResponse(LiteLLMBaseModel):
"""Response model for a single audit log entry"""
id: str
@ -18,7 +20,7 @@ class AuditLogResponse(BaseModel):
updated_values: Optional[Dict[str, Any]] = None
class PaginatedAuditLogResponse(BaseModel):
class PaginatedAuditLogResponse(LiteLLMBaseModel):
"""Response model for paginated audit logs"""
audit_logs: List[AuditLogResponse]

View file

@ -21,7 +21,7 @@ import time
from collections.abc import AsyncGenerator, AsyncIterator, Awaitable, Callable, Generator, Mapping
from typing import TYPE_CHECKING, Any, Final, Optional, TypeVar
from pydantic import BaseModel, ConfigDict, ValidationError
from pydantic import ConfigDict, ValidationError
import litellm
from litellm._internal_context import post_response_phase
@ -37,6 +37,7 @@ from litellm.litellm_core_utils.logging_utils import (
)
from litellm.types.caching import EMBEDDING_CACHE_FORMAT_VERSION, CachedEmbedding
from litellm.types.integrations.custom_logger import converted_stream_requested
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import ResponsesAPIResponse
from litellm.types.rerank import RerankResponse
from litellm.types.utils import (
@ -68,7 +69,7 @@ from litellm.litellm_core_utils.core_helpers import (
from litellm.litellm_core_utils.streaming_handler import CustomStreamWrapper
class CachingHandlerResponse(BaseModel):
class CachingHandlerResponse(LiteLLMBaseModel):
"""
This is the response object for the caching handler. We need to separate embedding cached responses and (completion / text_completion / transcription) cached responses
@ -172,7 +173,7 @@ def _request_cache_key(request_kwargs: Mapping[str, Any]) -> str | None:
return request_kwargs.get("cache_key", None)
class _CachedEmbeddingRecord(BaseModel):
class _CachedEmbeddingRecord(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
embedding: list[float] | str | None

View file

@ -5,6 +5,7 @@ from typing import Final, Literal
from litellm.litellm_core_utils.env_utils import get_env_int, get_env_int_in_range, get_env_int_or_none
DEFER_PYDANTIC_BUILD: Final = os.getenv("DEFER_PYDANTIC_BUILD", "true") in ("true", "1", "on")
DEFAULT_HEALTH_CHECK_PROMPT: Final = str(os.getenv("DEFAULT_HEALTH_CHECK_PROMPT", "test from litellm"))
AZURE_DEFAULT_RESPONSES_API_VERSION: Final = str(os.getenv("AZURE_DEFAULT_RESPONSES_API_VERSION", "preview"))
AZURE_OPENAI_AUDIO_PROVIDERS: Final = frozenset({"azure", "azure_ai"})

View file

@ -100,7 +100,7 @@ from litellm.llms.xai.cost_calculator import cost_per_token as xai_cost_per_toke
from litellm.responses.utils import ResponseAPILoggingUtils
from litellm.types.agents import LiteLLMSendMessageResponse
from litellm.types.decisions import DecisionsResponse, DecisionsUsage
from litellm.types.llms.base import CachedTokensDetails
from litellm.types.llms.base import CachedTokensDetails, LiteLLMBaseModel
from litellm.types.llms.openai import (
HttpxBinaryResponseContent,
ImageGenerationRequestQuality,
@ -2839,12 +2839,12 @@ class RealtimeAPITokenUsageProcessor(BaseTokenUsageProcessor):
_RESPONSES_WS_BILLABLE_EVENT_TYPES: Final = frozenset({"response.completed", "response.incomplete"})
class _ResponsesWsEventResponse(BaseModel):
class _ResponsesWsEventResponse(LiteLLMBaseModel):
usage: Mapping[str, object] | None = None
service_tier: str | None = None
class _ResponsesWsEvent(BaseModel):
class _ResponsesWsEvent(LiteLLMBaseModel):
type: str = ""
response: _ResponsesWsEventResponse | None = None

View file

@ -5,7 +5,7 @@ from functools import partial
from typing import TYPE_CHECKING, Any, ClassVar, Final
import httpx
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
import litellm
from litellm.constants import request_timeout
@ -17,6 +17,7 @@ from litellm.llms.base_llm.google_genai.transformation import (
BaseGoogleGenAIGenerateContentConfig,
)
from litellm.llms.custom_httpx.llm_http_handler import BaseLLMHTTPHandler
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.router import GenericLiteLLMParams
from litellm.types.utils import CallTypes
from litellm.utils import ProviderConfigManager, client
@ -46,7 +47,7 @@ def _mark_async_entrypoint(logging_obj: LiteLLMLoggingObj | None, marker: str, i
logging_obj.model_call_details.setdefault("litellm_params", {})[marker] = is_async
class GenerateContentSetupResult(BaseModel):
class GenerateContentSetupResult(LiteLLMBaseModel):
"""Internal Type - Result of setting up a generate content call"""
model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True)

View file

@ -12,7 +12,7 @@ from dataclasses import dataclass
from types import MappingProxyType
from typing import Final, Protocol, TypeAlias
from pydantic import BaseModel, ConfigDict, TypeAdapter, ValidationError
from pydantic import ConfigDict, TypeAdapter, ValidationError
import litellm
from litellm.harness.context import SessionContext
@ -28,6 +28,7 @@ from litellm.llms.tool_loop.harness.transformation import (
function_tool,
)
from litellm.types.completion import ChatCompletionMessageParam
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import (
ChatCompletionMessageCustomToolCall,
ChatCompletionMessageToolCall,
@ -52,7 +53,7 @@ _JSON_DECODER: Final = json.JSONDecoder()
_HISTORY_ADAPTER: Final = TypeAdapter(list[dict[str, object]])
class _Usage(BaseModel):
class _Usage(LiteLLMBaseModel):
model_config = ConfigDict(from_attributes=True)
prompt_tokens: int | None = None

View file

@ -2,7 +2,9 @@
from enum import Enum
from typing import Any, ClassVar, Literal
from pydantic import BaseModel, ConfigDict, Field
from pydantic import ConfigDict, Field
from litellm.types.llms.base import LiteLLMBaseModel
class SpanApiType(Enum):
@ -21,7 +23,7 @@ class TraceSpanApiStatus(Enum):
ERRORED = "ERRORED"
class BaseApiSpan(BaseModel):
class BaseApiSpan(LiteLLMBaseModel):
model_config: ClassVar[ConfigDict] = ConfigDict(use_enum_values=True)
uuid: str
@ -44,7 +46,7 @@ class BaseApiSpan(BaseModel):
cost_per_output_token: float | None = Field(None, alias="costPerOutputToken")
class TraceApi(BaseModel):
class TraceApi(LiteLLMBaseModel):
uuid: str
base_spans: list[BaseApiSpan] = Field(alias="baseSpans")
agent_spans: list[BaseApiSpan] = Field(alias="agentSpans")

View file

@ -9,7 +9,7 @@ from datetime import datetime, timezone, tzinfo
from typing import Any, Final, Protocol, cast
import httpx
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter
from pydantic import ConfigDict, Field, TypeAdapter
from typing_extensions import ReadOnly, TypedDict
import litellm
@ -24,6 +24,7 @@ from litellm.llms.custom_httpx.http_handler import (
httpxSpecialProvider,
)
from litellm.types.integrations.base_health_check import IntegrationHealthCheckStatus
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import (
AllMessageValues,
HttpxBinaryResponseContent,
@ -80,7 +81,7 @@ class GalileoStandardLoggingFields(TypedDict, total=False):
endTime: float
class LLMResponse(BaseModel):
class LLMResponse(LiteLLMBaseModel):
latency_ms: int
status_code: int
input_text: str

View file

@ -34,13 +34,14 @@ from opentelemetry.sdk.trace.id_generator import RandomIdGenerator
from opentelemetry.sdk.trace.sampling import ALWAYS_ON, Decision, Sampler, SamplingResult
from opentelemetry.trace import Link, NonRecordingSpan, Span, SpanContext, SpanKind, TraceFlags, Tracer, TraceState
from opentelemetry.util.types import Attributes, AttributeValue
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
import litellm
from litellm._logging import verbose_logger
from litellm.integrations.langfuse.langfuse import PROMPT_CACHE_TTL_ENV, parse_langfuse_debug, whole_number
from litellm.litellm_core_utils.safe_json_dumps import safe_dumps
from litellm.llms.custom_httpx.http_handler import HTTPHandler, _get_httpx_client
from litellm.types.llms.base import LiteLLMBaseModel
__all__ = (
"AuthCheckFailure",
@ -1063,7 +1064,7 @@ def _auth_check_failure(reason: str) -> AuthCheckFailure:
return AuthCheckFailure(reason)
class _ApiErrorDetail(BaseModel):
class _ApiErrorDetail(LiteLLMBaseModel):
"""The status and body of an ``ApiError``, whose own ``str`` also dumps every response header."""
model_config = ConfigDict(frozen=True, from_attributes=True)

View file

@ -4,7 +4,7 @@ from enum import Enum
from functools import lru_cache
from typing import Annotated, Final
from pydantic import AliasChoices, BaseModel, Field, TypeAdapter, ValidationError, field_validator, model_validator
from pydantic import AliasChoices, ConfigDict, Field, TypeAdapter, ValidationError, field_validator, model_validator
from pydantic.fields import FieldInfo
from pydantic_settings import BaseSettings, NoDecode, PydanticBaseSettingsSource, SettingsConfigDict
@ -15,6 +15,7 @@ from litellm.integrations.otel.model.baggage import (
DEFAULT_BAGGAGE_TEAM_METADATA_KEYS,
)
from litellm.integrations.otel.model.spans import POSTGRESQL, db_system
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import OtelSpanScope
#: Master feature-flag env var. The logger is inert until this is truthy.
@ -62,7 +63,7 @@ def is_otel_v2_enabled() -> bool:
return _OTelV2Flag().enabled
class ExporterSpec(BaseModel):
class ExporterSpec(LiteLLMBaseModel):
"""One span-export destination.
The shared ``TracerProvider`` attaches one ``SpanProcessor`` per spec, so
@ -70,7 +71,7 @@ class ExporterSpec(BaseModel):
Phoenix + your own Honeycomb).
"""
model_config = {"extra": "forbid"}
model_config = ConfigDict(extra="forbid")
kind: str = Field(
default="console",

View file

@ -8,12 +8,13 @@ from collections.abc import Mapping
from typing import Final
from urllib.parse import quote
from pydantic import BaseModel, ConfigDict, Field
from pydantic import ConfigDict, Field
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import OtelSpanScope
class OtelDestination(BaseModel):
class OtelDestination(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
endpoint: str

View file

@ -1,12 +1,13 @@
from collections.abc import Mapping, Sequence
from typing import Final, Literal
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, ValidationError
from pydantic import ConfigDict, Field, TypeAdapter, ValidationError
from typing_extensions import ReadOnly, TypedDict
import litellm
from litellm.integrations.otel.mappers.utils import json_or_none
from litellm.proxy.guardrails.anthropic_sse import assemble_anthropic_sse_stream, is_raw_sse_stream
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import ResponseCompletedEvent, ResponsesAPIResponse
from litellm.types.utils import ModelResponse, ModelResponseStream
@ -20,7 +21,7 @@ class _Turn(TypedDict):
content: ReadOnly[object]
class _AnthropicMessage(BaseModel):
class _AnthropicMessage(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
type: Literal["message"] = Field(exclude=True)

View file

@ -24,6 +24,7 @@ from litellm.types.integrations.pointfive import (
PointFiveUploadFailure,
PointFiveUploadTarget,
)
from litellm.types.llms.base import LiteLLMBaseModel
UPLOAD_KIND: Final = "LITELLM"
UPLOAD_URL_PATH: Final = "/upload-url"
@ -31,21 +32,21 @@ PING_PATH: Final = "/ping"
PUT_HEADERS: Final = MappingProxyType({"Content-Type": "application/x-ndjson", "Content-Encoding": "gzip"})
class _PresignRequest(BaseModel):
class _PresignRequest(LiteLLMBaseModel):
kind: str = UPLOAD_KIND
byte_count: int = Field(serialization_alias="byteCount")
class _PingRequest(BaseModel):
class _PingRequest(LiteLLMBaseModel):
kind: str = UPLOAD_KIND
class _TargetPayload(BaseModel):
class _TargetPayload(LiteLLMBaseModel):
upload_url: str = Field(alias="uploadUrl")
object_key: str = Field(alias="objectKey")
class _ErrorPayload(BaseModel):
class _ErrorPayload(LiteLLMBaseModel):
error: str = ""

View file

@ -7,7 +7,7 @@ import time
from datetime import datetime, timedelta
from typing import Final
from pydantic import BaseModel, TypeAdapter
from pydantic import TypeAdapter
from typing_extensions import ReadOnly, TypedDict
from litellm import get_secret
@ -16,6 +16,7 @@ from litellm.llms.custom_httpx.http_handler import (
get_async_httpx_client,
httpxSpecialProvider,
)
from litellm.types.llms.base import LiteLLMBaseModel
PROMETHEUS_URL: Final[str | None] = get_secret("PROMETHEUS_URL")
PROMETHEUS_SELECTED_INSTANCE: Final[str | None] = get_secret("PROMETHEUS_SELECTED_INSTANCE")
@ -24,18 +25,18 @@ async_http_handler: Final = get_async_httpx_client(llm_provider=httpxSpecialProv
_RAW_JSON_PAYLOAD: Final = TypeAdapter(object)
class PrometheusRangeSample(BaseModel):
class PrometheusRangeSample(LiteLLMBaseModel):
"""One ``matrix`` series of the Prometheus HTTP query API."""
metric: dict[str, object]
values: list[tuple[float, str]]
class PrometheusQueryData(BaseModel):
class PrometheusQueryData(LiteLLMBaseModel):
result: list[PrometheusRangeSample]
class PrometheusQueryResponse(BaseModel):
class PrometheusQueryResponse(LiteLLMBaseModel):
data: PrometheusQueryData

View file

@ -40,6 +40,7 @@ from litellm.litellm_core_utils.llm_judge import (
from litellm.litellm_core_utils.redact_messages import should_redact_message_logging
from litellm.llms.base_llm.base_utils import type_to_response_format_param
from litellm.router_utils.common_utils import resolve_model_group_alias
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.management_endpoints.auto_router_endpoints import ShadowEvalDirection
from litellm.types.utils import SHADOW_EVAL_JUDGE_CALL_ORIGIN, SHADOW_EVAL_ROUTER_CALL_ORIGIN
@ -467,7 +468,7 @@ Return ONLY valid JSON in this exact format, no other text:
}"""
class PairwiseVerdict(BaseModel):
class PairwiseVerdict(LiteLLMBaseModel):
"""The judge's blind A/B verdict: the response_format schema sent with the judge call
and the validation contract on its reply. Both fields are required and preference is
closed over the prompt's labels, so a malformed or truncated reply is an
@ -731,7 +732,7 @@ class _JudgeVerdict:
cost: float
class ActiveShadowEvalJob(BaseModel):
class ActiveShadowEvalJob(LiteLLMBaseModel):
"""One active job as the sampling path needs it, validated straight off the untyped
job row: immutable config plus the attempt count as of the cache fill (the turn
budget's staleness is bounded by the cache TTL). Every way a row can be unsamplable

View file

@ -14,7 +14,7 @@ from collections.abc import Callable, Mapping, Sequence
from typing import Final
import httpx
from pydantic import BaseModel, ValidationError
from pydantic import ValidationError
import litellm
from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler
@ -25,12 +25,13 @@ from litellm.types.integrations.zerobus import (
ZerobusConnection,
ZerobusIngestFailure,
)
from litellm.types.llms.base import LiteLLMBaseModel
TOKEN_PATH: Final = "/oidc/v1/token"
OAUTH_SCOPE: Final = "all-apis"
class _TokenResponse(BaseModel):
class _TokenResponse(LiteLLMBaseModel):
access_token: str
expires_in: float = 3600

View file

@ -45,7 +45,7 @@ from datetime import datetime, timezone
from types import MappingProxyType
from typing import TYPE_CHECKING, Final, Literal, Protocol, TypeAlias
from pydantic import BaseModel, ConfigDict, JsonValue, TypeAdapter, ValidationError
from pydantic import ConfigDict, JsonValue, TypeAdapter, ValidationError
from pydantic_core import PydanticSerializationError, to_jsonable_python
from litellm._logging import verbose_logger
@ -57,6 +57,7 @@ from litellm.constants import (
)
from litellm.litellm_core_utils.core_helpers import get_litellm_metadata_from_kwargs
from litellm.types.interactions import InteractionsAPIResponse
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import CustomPricingLiteLLMParams
if TYPE_CHECKING:
@ -73,7 +74,7 @@ _STATUSES_THAT_PRODUCED_OUTPUT: Final = frozenset({"completed", "requires_action
SettlementOutcome: TypeAlias = Literal["billed", "released", "unsettled"]
class BackgroundInteractionCreateContext(BaseModel):
class BackgroundInteractionCreateContext(LiteLLMBaseModel):
"""
The part of a create's logging state that billing its settled result needs,
in a shape any replica can store and rebuild a logging object from. Provider

View file

@ -6,7 +6,9 @@ from dataclasses import dataclass
from itertools import accumulate, groupby
from typing import Final
from pydantic import BaseModel, ConfigDict, TypeAdapter, ValidationError
from pydantic import ConfigDict, TypeAdapter, ValidationError
from litellm.types.llms.base import LiteLLMBaseModel
CUE_MAX_CHARS: Final = 84
CUE_MAX_DURATION_MS: Final = 7000
@ -230,7 +232,7 @@ def render_subtitle_tokens_as_vtt(tokens: Sequence[SubtitleToken]) -> str:
return _render_vtt(group_subtitle_tokens_into_cues(tokens))
class TranscriptionWordTiming(BaseModel):
class TranscriptionWordTiming(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
word: str = ""

View file

@ -20,7 +20,7 @@ from pathlib import Path
from types import MappingProxyType
from typing import Final, TypeAlias
from pydantic import BaseModel, ConfigDict, ValidationError
from pydantic import ConfigDict, ValidationError
from litellm.litellm_core_utils.cli_keyring import (
SYSTEM_KEYRING,
@ -44,6 +44,7 @@ from litellm.litellm_core_utils.private_json import (
stage_private_json,
write_private_json,
)
from litellm.types.llms.base import LiteLLMBaseModel
@dataclass(frozen=True, slots=True)
@ -83,7 +84,7 @@ SecretSave: TypeAlias = SecretWrite | CredentialNotSaved | CredentialNotRecorded
SecretClear: TypeAlias = SecretErase | CredentialNotCleared
class CliTokenRecord(BaseModel):
class CliTokenRecord(LiteLLMBaseModel):
"""A stored CLI credential.
`key is None` means the metadata was found but the secret could not be
@ -104,7 +105,7 @@ class CliTokenRecord(BaseModel):
refresh_token: str | None = None
class CliTokenSecret(BaseModel):
class CliTokenSecret(LiteLLMBaseModel):
"""The secret material as stored in the OS keychain.
`base_url` is duplicated from the metadata file purely as a pairing tag: a

View file

@ -17,21 +17,21 @@ from importlib.resources import files
from typing import Final
import httpx
from pydantic import BaseModel
from litellm import verbose_logger
from litellm.types.llms.base import LiteLLMBaseModel
BLOG_POSTS_TTL_SECONDS: Final[int] = 3600 # 1 hour
class BlogPost(BaseModel):
class BlogPost(LiteLLMBaseModel):
title: str
description: str
date: str
url: str
class BlogPostsResponse(BaseModel):
class BlogPostsResponse(LiteLLMBaseModel):
posts: list[BlogPost]

View file

@ -2,22 +2,23 @@ import math
from collections.abc import Mapping
from typing import Annotated, Final
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, ValidationError
from pydantic import ConfigDict, Field, TypeAdapter, ValidationError
import litellm
from litellm._logging import verbose_logger
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import CostBreakdown
BEDROCK_GUARDRAIL_PRICING_KEY: Final = "bedrock/guardrails"
class GuardrailPricing(BaseModel):
class GuardrailPricing(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
guardrail_cost_per_unit: Mapping[str, float]
class GuardrailCostEntry(BaseModel):
class GuardrailCostEntry(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
guardrail_cost: float | None = None
@ -30,7 +31,7 @@ class GuardrailCostEntry(BaseModel):
_GUARDRAIL_COST_ENTRY_ADAPTER: Final[TypeAdapter[GuardrailCostEntry]] = TypeAdapter(GuardrailCostEntry)
class GuardrailCostByUnitEntry(BaseModel):
class GuardrailCostByUnitEntry(LiteLLMBaseModel):
"""The rollup-side view of a ``guardrail_information`` entry, validated apart from
``GuardrailCostEntry`` so a forged per-counter map can never zero the spend path."""

View file

@ -12,6 +12,7 @@ from types import MappingProxyType
from typing import Any, Final, TypeAlias, TypedDict, cast, overload
from jinja2.sandbox import ImmutableSandboxedEnvironment
from pydantic import BaseModel
import litellm
import litellm.types

View file

@ -6,8 +6,9 @@ from __future__ import annotations
from collections.abc import Sequence
from typing import Final, Literal
from pydantic import BaseModel, TypeAdapter, ValidationError
from pydantic import BaseModel, Field, TypeAdapter, ValidationError
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import ModelResponse, ModelResponseStream
SERVED_OUTPUT_TEXTS_KEY: Final = "served_output_texts"
@ -19,27 +20,27 @@ _TEXTS: Final = TypeAdapter(tuple[str | None, ...])
ServedTexts = tuple[str | None, ...]
class _TextBlock(BaseModel):
class _TextBlock(LiteLLMBaseModel):
type: str
text: str | None = None
class _AnthropicMessage(BaseModel):
class _AnthropicMessage(LiteLLMBaseModel):
type: Literal["message"]
content: list[_TextBlock]
class _ResponsesOutputItem(BaseModel):
class _ResponsesOutputItem(LiteLLMBaseModel):
type: str
content: list[_TextBlock] = []
content: list[_TextBlock] = Field(default=[])
class _ResponsesResponse(BaseModel):
class _ResponsesResponse(LiteLLMBaseModel):
object: Literal["response"]
output: list[_ResponsesOutputItem]
class _ChatChoices(BaseModel):
class _ChatChoices(LiteLLMBaseModel):
choices: list[object]

View file

@ -25,6 +25,7 @@ from litellm.litellm_core_utils.model_response_utils import (
)
from litellm.litellm_core_utils.redact_messages import LiteLLMLoggingObject
from litellm.litellm_core_utils.thread_pool_executor import executor
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import OpenAIChatCompletionChunk
from litellm.types.router import GenericLiteLLMParams
from litellm.types.utils import (
@ -164,7 +165,7 @@ class _VertexChunkLike(Protocol):
candidates: Sequence[_VertexCandidateLike]
class _ParsedChunkHiddenParams(BaseModel):
class _ParsedChunkHiddenParams(LiteLLMBaseModel):
provider_specific_fields: Mapping[str, object] | None = None

View file

@ -7,7 +7,7 @@ from types import MappingProxyType
from typing import Final
from urllib.parse import urlparse
from pydantic import BaseModel, JsonValue, TypeAdapter
from pydantic import JsonValue, TypeAdapter
import litellm
from litellm._internal_context import current_billing_time, pinned_billing_time
@ -25,6 +25,7 @@ from litellm.llms.anthropic.prompt_cache_prediction import (
)
from litellm.proxy.common_utils.prompt_cache_pricing import price_cache_tokens
from litellm.proxy.hooks.prompt_cache_prediction import lookup
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.management_endpoints.prompt_cache_prediction import (
CacheCostScenario,
CacheEvidence,
@ -57,7 +58,7 @@ _NATIVE_OPTIONS: Final = frozenset(
)
class _ModelLimits(BaseModel):
class _ModelLimits(LiteLLMBaseModel):
max_input_tokens: int | None = None
max_output_tokens: int | None = None

View file

@ -12,7 +12,7 @@ from typing import Any, ClassVar, Final, Literal, TypeVar
from urllib.parse import quote
import httpx
from pydantic import BaseModel, ConfigDict, Field, StrictBool, TypeAdapter, ValidationError
from pydantic import ConfigDict, Field, StrictBool, TypeAdapter, ValidationError
import litellm
from litellm.constants import (
@ -51,6 +51,7 @@ from litellm.types.llms.anthropic import (
AnthropicMessagesToolChoice,
AnthropicThinkingParam,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import AllMessageValues
from litellm.types.proxy.auth.special_headers import SpecialHeaders
from litellm.types.proxy.model_listing import ModelInfoResponse
@ -349,11 +350,11 @@ def optionally_handle_anthropic_oauth(headers: dict, api_key: str | None) -> tup
return headers, api_key
class _EagerInputStreamingFunction(BaseModel):
class _EagerInputStreamingFunction(LiteLLMBaseModel):
eager_input_streaming: StrictBool | None = None
class _EagerInputStreamingTool(BaseModel):
class _EagerInputStreamingTool(LiteLLMBaseModel):
eager_input_streaming: StrictBool | None = None
function: _EagerInputStreamingFunction | None = None
@ -388,11 +389,11 @@ def _litellm_params_str(litellm_params: Mapping[str, object] | None, key: str) -
return value if isinstance(value, str) else None
class _AnthropicModelListEntry(BaseModel):
class _AnthropicModelListEntry(LiteLLMBaseModel):
id: str
class _AnthropicModelsPage(BaseModel):
class _AnthropicModelsPage(LiteLLMBaseModel):
data: Sequence[_AnthropicModelListEntry] = Field(default_factory=tuple)
has_more: bool = False
last_id: str | None = None
@ -1784,13 +1785,13 @@ def sanitize_tool_use_ids_in_anthropic_messages(messages: list[Any]) -> list[Any
return out
class _ReplayedSearchQuery(BaseModel):
class _ReplayedSearchQuery(LiteLLMBaseModel):
model_config = ConfigDict(extra="allow")
query: str = ""
class _ReplayedWebSearchResult(BaseModel):
class _ReplayedWebSearchResult(LiteLLMBaseModel):
model_config = ConfigDict(extra="allow")
type: Literal["web_search_result"]
@ -1800,14 +1801,14 @@ class _ReplayedWebSearchResult(BaseModel):
encrypted_content: str = ""
class _ReplayedWebSearchToolResultError(BaseModel):
class _ReplayedWebSearchToolResultError(LiteLLMBaseModel):
model_config = ConfigDict(extra="allow")
type: Literal["web_search_tool_result_error"]
error_code: str = ""
class _ReplayedWebSearchToolResult(BaseModel):
class _ReplayedWebSearchToolResult(LiteLLMBaseModel):
model_config = ConfigDict(extra="allow")
type: Literal["web_search_tool_result"]
@ -1815,7 +1816,7 @@ class _ReplayedWebSearchToolResult(BaseModel):
content: tuple[_ReplayedWebSearchResult, ...] | _ReplayedWebSearchToolResultError
class _ReplayedServerToolUse(BaseModel):
class _ReplayedServerToolUse(LiteLLMBaseModel):
model_config = ConfigDict(extra="allow")
type: Literal["server_tool_use"]
@ -1823,7 +1824,7 @@ class _ReplayedServerToolUse(BaseModel):
input: _ReplayedSearchQuery = _ReplayedSearchQuery()
class _TextBlock(BaseModel):
class _TextBlock(LiteLLMBaseModel):
type: Literal["text"] = "text"
text: str

View file

@ -5,13 +5,14 @@ Helper util for handling anthropic-specific cost calculation
from typing import TYPE_CHECKING, Final, Optional
from pydantic import BaseModel, ValidationError
from pydantic import ValidationError
from litellm.litellm_core_utils.llm_cost_calc.utils import (
generic_cost_per_token,
get_provider_specific_geo_multiplier,
get_web_search_requests_from_usage,
)
from litellm.types.llms.base import LiteLLMBaseModel
if TYPE_CHECKING:
from litellm.types.utils import ModelInfo, Usage
@ -71,15 +72,15 @@ def cost_per_token(
return prompt_cost, completion_cost
class _AnthropicServerToolUseProbe(BaseModel):
class _AnthropicServerToolUseProbe(LiteLLMBaseModel):
web_search_requests: int | None = None
class _AnthropicUsageProbe(BaseModel):
class _AnthropicUsageProbe(LiteLLMBaseModel):
server_tool_use: _AnthropicServerToolUseProbe | None = None
class _AnthropicResponseProbe(BaseModel):
class _AnthropicResponseProbe(LiteLLMBaseModel):
usage: _AnthropicUsageProbe | None = None

View file

@ -6,7 +6,7 @@ from collections import deque
from collections.abc import AsyncIterator, Iterator, Mapping
from typing import TYPE_CHECKING, Any, Final
from pydantic import BaseModel, ConfigDict, field_validator
from pydantic import ConfigDict, field_validator
from litellm import verbose_logger
from litellm._logging import redact_internal_details_from_client_message
@ -22,6 +22,7 @@ from litellm.llms.anthropic.pass_through.messages.utils import (
)
from litellm.responses.streaming_iterator import stream_error_status_and_message
from litellm.types.llms.anthropic_messages.anthropic_response import AnthropicUsage
from litellm.types.llms.base import LiteLLMBaseModel
from .transformation import (
REASONING_SUMMARY_PART_SEPARATOR,
@ -32,7 +33,7 @@ if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObject
class _UpstreamFailure(BaseModel):
class _UpstreamFailure(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
status_code: int | None = None
@ -56,13 +57,13 @@ class _UpstreamFailure(BaseModel):
return value if isinstance(value, str) else None
class _FailedResponse(BaseModel):
class _FailedResponse(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, from_attributes=True)
error: object | None = None
class _FailedResponseEvent(BaseModel):
class _FailedResponseEvent(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, from_attributes=True)
response: _FailedResponse | None = None

View file

@ -3,9 +3,10 @@ from collections.abc import Mapping
from types import MappingProxyType
from typing import TYPE_CHECKING, Final
from pydantic import BaseModel, ConfigDict, ValidationError
from pydantic import ConfigDict, ValidationError
import litellm
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import ModelInfo
if TYPE_CHECKING:
@ -23,7 +24,7 @@ _EFFORT_DEGRADATION_CHAIN: Final[Mapping[str, tuple[str, ...]]] = MappingProxyTy
_THINKING_OFF: Final = "none"
class _ClaudeCodeUserId(BaseModel):
class _ClaudeCodeUserId(LiteLLMBaseModel):
"""The JSON Claude Code packs into ``metadata.user_id``; only ``session_id`` is per conversation."""
model_config = ConfigDict(frozen=True)

View file

@ -10,7 +10,7 @@ from types import MappingProxyType
from typing import Annotated, Final, Literal, Protocol, TypeAlias
import httpx
from pydantic import BaseModel, ConfigDict, Field, JsonValue, StrictInt, TypeAdapter, ValidationError
from pydantic import ConfigDict, Field, JsonValue, StrictInt, TypeAdapter, ValidationError
import litellm
from litellm.llms.anthropic.common_utils import AnthropicModelInfo, is_anthropic_oauth_key
@ -20,6 +20,7 @@ from litellm.llms.anthropic.pass_through.messages.transformation import (
DEFAULT_ANTHROPIC_API_VERSION,
AnthropicMessagesConfig,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.router import LiteLLM_Params
from litellm.types.utils import ModelResponse
from litellm.utils import supports_thinking_cache_preservation
@ -65,7 +66,7 @@ _DEPLOYMENT_OPTIONS: Final = frozenset(
)
class _StrictModel(BaseModel):
class _StrictModel(LiteLLMBaseModel):
model_config = ConfigDict(extra="forbid", frozen=True, strict=True)
@ -455,37 +456,37 @@ def cache_scope(
return _digest((caller_key_hash, deployment_id, provider_key, model, anthropic_version))
class _TTLUsage(BaseModel):
class _TTLUsage(LiteLLMBaseModel):
model_config = ConfigDict(strict=True)
ephemeral_5m_input_tokens: int = Field(default=0, ge=0)
ephemeral_1h_input_tokens: int = Field(default=0, ge=0)
class _CacheUsage(BaseModel):
class _CacheUsage(LiteLLMBaseModel):
model_config = ConfigDict(strict=True)
cached_tokens: int = Field(default=0, ge=0)
cache_creation_tokens: int = Field(default=0, ge=0)
cache_creation_token_details: _TTLUsage | None = None
class _Usage(BaseModel):
class _Usage(LiteLLMBaseModel):
model_config = ConfigDict(strict=True)
prompt_tokens: int = Field(ge=0)
prompt_tokens_details: _CacheUsage
class _Choice(BaseModel):
class _Choice(LiteLLMBaseModel):
finish_reason: str = Field(min_length=1)
class _Response(BaseModel):
class _Response(LiteLLMBaseModel):
model_config = ConfigDict(strict=True)
model: str
usage: _Usage
choices: tuple[_Choice, ...] = Field(min_length=1, strict=False)
class _CountBody(BaseModel):
class _CountBody(LiteLLMBaseModel):
messages: Sequence[Mapping[str, JsonValue]]
tools: Sequence[Mapping[str, JsonValue]] | None = None
system: str | Sequence[Mapping[str, JsonValue]] | None = None
@ -494,7 +495,7 @@ class _CountBody(BaseModel):
output_config: Mapping[str, JsonValue] | None = None
class _CountResult(BaseModel):
class _CountResult(LiteLLMBaseModel):
input_tokens: Annotated[StrictInt, Field(ge=0)]

View file

@ -10,7 +10,7 @@ from types import MappingProxyType
from typing import Final, NoReturn, TypeVar
from urllib.parse import urlsplit, urlunsplit
from pydantic import BaseModel, ConfigDict, ValidationError
from pydantic import ConfigDict, ValidationError
from typing_extensions import assert_never
import litellm
@ -42,6 +42,7 @@ from litellm.llms.base_llm.auth.types import (
TokenTransportError,
)
from litellm.types.llms.anthropic import ANTHROPIC_TOKEN_EXCHANGE_PATH
from litellm.types.llms.base import LiteLLMBaseModel
_JWT_BEARER_GRANT_TYPE: Final = "urn:ietf:params:oauth:grant-type:jwt-bearer"
_DEFAULT_API_BASE: Final = "https://api.anthropic.com"
@ -119,7 +120,7 @@ _EMPTY_PARAMS: Final[Mapping[str, object]] = MappingProxyType({})
_IdentitySourceVariant = TypeVar("_IdentitySourceVariant", bound="InternalIssuerSource | KeycloakSource")
class AnthropicWifParams(BaseModel):
class AnthropicWifParams(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
federation_rule_id: str

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Final, Optional
import httpx
from httpx import Response
from pydantic import BaseModel, ValidationError
from pydantic import ValidationError
from litellm.litellm_core_utils.litellm_logging import Logging
from litellm.llms.azure.common_utils import BaseAzureLLM
@ -17,6 +17,7 @@ from litellm.llms.base_llm.passthrough.transformation import (
strip_leading_model_segment,
)
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import AllMessageValues, ResponsesAPIResponse, ResponsesTerminalEvent
from litellm.types.router import GenericLiteLLMParams
from litellm.types.utils import CallTypes, EmbeddingResponse, ImageResponse
@ -27,11 +28,11 @@ if TYPE_CHECKING:
from litellm.llms.base_llm.passthrough.transformation import LoggedRelayResponse
class RelayedChatRequest(BaseModel):
class RelayedChatRequest(LiteLLMBaseModel):
messages: Sequence[Mapping[str, object]] | None = None
class RelayedCallDetails(BaseModel):
class RelayedCallDetails(LiteLLMBaseModel):
request_data: RelayedChatRequest | None = None

View file

@ -33,7 +33,7 @@ from types import MappingProxyType
from typing import TYPE_CHECKING, Final, Literal
import httpx
from pydantic import BaseModel, ConfigDict, ValidationError
from pydantic import ConfigDict, ValidationError
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.llms.base_llm.search.transformation import (
@ -42,6 +42,7 @@ from litellm.llms.base_llm.search.transformation import (
SearchResult,
)
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
@ -61,7 +62,7 @@ _UPSTREAM_ERROR_STATUS: Final = 502
_RESPONSE_COST_HEADER: Final = "llm_provider-x-litellm-response-cost"
class _Annotation(BaseModel):
class _Annotation(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
type: str = ""
@ -71,7 +72,7 @@ class _Annotation(BaseModel):
end_index: int | None = None
class _ContentPart(BaseModel):
class _ContentPart(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
type: str = ""
@ -79,26 +80,26 @@ class _ContentPart(BaseModel):
annotations: tuple[_Annotation, ...] = ()
class _OutputItem(BaseModel):
class _OutputItem(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
type: str = ""
content: tuple[_ContentPart, ...] = ()
class _ErrorBody(BaseModel):
class _ErrorBody(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
message: str | None = None
class _IncompleteDetails(BaseModel):
class _IncompleteDetails(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
reason: str | None = None
class _ResponsesEnvelope(BaseModel):
class _ResponsesEnvelope(LiteLLMBaseModel):
"""A Foundry Responses API body. `output` is required: a body without it is not a
Responses API response and must not be reported as a successful empty search.
@ -113,7 +114,7 @@ class _ResponsesEnvelope(BaseModel):
incomplete_details: _IncompleteDetails | None = None
class _ErrorEnvelope(BaseModel):
class _ErrorEnvelope(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
error: _ErrorBody | None = None
@ -205,41 +206,41 @@ def _capped(results: tuple[SearchResult, ...], max_results: int | None) -> tuple
return results[:max_results] if max_results is not None else results
class _SearchConfiguration(BaseModel):
class _SearchConfiguration(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
project_connection_id: str
count: int | None = None
class _BingGroundingParams(BaseModel):
class _BingGroundingParams(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
search_configurations: tuple[_SearchConfiguration, ...]
class _BingGroundingTool(BaseModel):
class _BingGroundingTool(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
type: Literal["bing_grounding"] = "bing_grounding"
bing_grounding: _BingGroundingParams
class _UserLocation(BaseModel):
class _UserLocation(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
type: Literal["approximate"] = "approximate"
country: str
class _WebSearchTool(BaseModel):
class _WebSearchTool(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
type: Literal["web_search"] = "web_search"
user_location: _UserLocation | None = None
class _ResponsesRequest(BaseModel):
class _ResponsesRequest(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
model: str

View file

@ -18,7 +18,7 @@ from typing import TYPE_CHECKING, Final, TypeAlias
from urllib.parse import quote, quote_plus, urlencode
import httpx
from pydantic import BaseModel, SecretStr, ValidationError
from pydantic import SecretStr, ValidationError
from typing_extensions import assert_never
from litellm.llms.base_llm.auth.identity_source import KeycloakSource, ref_for_error_message
@ -30,6 +30,7 @@ from litellm.llms.base_llm.auth.token_exchange import (
validate_token_endpoint_url,
)
from litellm.llms.base_llm.auth.types import InsecureTokenUrl, SyncTokenPoster
from litellm.types.llms.base import LiteLLMBaseModel
if TYPE_CHECKING:
from litellm.llms.custom_httpx.http_handler import HTTPHandler
@ -41,7 +42,7 @@ _TIMEOUT_SECONDS: Final = 30.0
_FORM_CONTENT_TYPE: Final = "application/x-www-form-urlencoded"
class _ClientCredentialsResponse(BaseModel):
class _ClientCredentialsResponse(LiteLLMBaseModel):
access_token: str

View file

@ -11,7 +11,9 @@ import hashlib
from enum import Enum
from typing import Annotated, Final, Literal, TypeAlias
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter
from pydantic import ConfigDict, Field, TypeAdapter
from litellm.types.llms.base import LiteLLMBaseModel
_REF_HASH_HEX_LENGTH: Final = 16
_MAX_TTL_SECONDS: Final = 3600
@ -23,7 +25,7 @@ class AnthropicIdentitySourceKind(str, Enum):
keycloak = "keycloak"
class InternalIssuerSource(BaseModel):
class InternalIssuerSource(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="forbid", hide_input_in_errors=True)
kind: Literal[AnthropicIdentitySourceKind.internal_issuer] = AnthropicIdentitySourceKind.internal_issuer
@ -34,7 +36,7 @@ class InternalIssuerSource(BaseModel):
signing_key_ref: str
class KeycloakSource(BaseModel):
class KeycloakSource(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="forbid", hide_input_in_errors=True)
kind: Literal[AnthropicIdentitySourceKind.keycloak] = AnthropicIdentitySourceKind.keycloak

View file

@ -16,9 +16,10 @@ from dataclasses import dataclass
from pathlib import Path
from typing import Final, Protocol
from pydantic import BaseModel, SecretStr, ValidationError
from pydantic import SecretStr, ValidationError
from litellm._logging import verbose_logger
from litellm.types.llms.base import LiteLLMBaseModel
CACHE_DIR_ENV: Final = "LITELLM_TOKEN_EXCHANGE_CACHE_DIR"
@ -43,7 +44,7 @@ class SharedTokenStore(Protocol):
def lock(self, key: str) -> contextlib.AbstractContextManager[None]: ...
class _StoredTokenFile(BaseModel):
class _StoredTokenFile(LiteLLMBaseModel):
access_token: str
expires_at_epoch: float | None
assertion_sha256: str

View file

@ -23,7 +23,7 @@ from typing import TYPE_CHECKING, Final, Protocol, TypeAlias
from urllib.parse import unquote, unquote_plus, urlencode, urlsplit, urlunsplit
import httpx
from pydantic import BaseModel, SecretStr, TypeAdapter, ValidationError
from pydantic import SecretStr, TypeAdapter, ValidationError
from typing_extensions import assert_never
from litellm._logging import verbose_logger
@ -44,6 +44,7 @@ from litellm.llms.base_llm.auth.types import (
TokenExchangeSpec,
TokenTransportError,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.services import ServiceTypes
if TYPE_CHECKING:
@ -86,7 +87,7 @@ _CREDENTIAL_CHARS: Final = re.compile(r"[^A-Za-z0-9._~+/=-]")
_SENTINEL_BODY_MESSAGES: Final = frozenset({_OVERSIZED_BODY_MESSAGE, _NON_OBJECT_BODY_MESSAGE})
class _TokenExchangeResponse(BaseModel):
class _TokenExchangeResponse(LiteLLMBaseModel):
access_token: str
expires_in: int | None = None
token_type: str | None = None

View file

@ -6,8 +6,9 @@ from collections.abc import Callable, Mapping, Sequence
from dataclasses import dataclass
from typing import TYPE_CHECKING, Final, Protocol, TypeAlias
from pydantic import BaseModel, ConfigDict, TypeAdapter, ValidationError
from pydantic import ConfigDict, TypeAdapter, ValidationError
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import CallTypes
from ..base_utils import BaseLLMModelInfo
@ -29,7 +30,7 @@ if TYPE_CHECKING:
RELAYED_JSON_OBJECT: Final = TypeAdapter(Mapping[str, object])
class PassthroughMetadata(BaseModel):
class PassthroughMetadata(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore")
model_group: str = ""

View file

@ -15,7 +15,7 @@ from types import MappingProxyType
from typing import TYPE_CHECKING, Any, ClassVar, Final, Literal, ParamSpec, TypeVar, cast, get_args, overload
import httpx
from pydantic import BaseModel, TypeAdapter, ValidationError
from pydantic import TypeAdapter, ValidationError
from typing_extensions import NotRequired, ReadOnly, TypedDict
from litellm._logging import verbose_logger
@ -33,6 +33,7 @@ from litellm.constants import (
from litellm.litellm_core_utils.aws_partition import contains_bedrock_arn, get_aws_dns_suffix
from litellm.litellm_core_utils.dd_tracing import tracer
from litellm.secret_managers.main import get_secret, get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.bedrock import AWS_AUTH_PARAM_KEYS, AwsAuthParams, AwsSessionTag
if TYPE_CHECKING:
@ -176,7 +177,7 @@ def pop_aws_auth_params(
)
class BedrockRequestTarget(BaseModel):
class BedrockRequestTarget(LiteLLMBaseModel):
aws_region_name: str
aws_bedrock_runtime_endpoint: str | None
@ -194,7 +195,7 @@ def bedrock_bearer_token(api_key: str | None) -> str | None:
return token or None
class _WebIdentityTokenClaims(BaseModel):
class _WebIdentityTokenClaims(LiteLLMBaseModel):
aud: str | list[str] | None = None
iss: str | None = None

View file

@ -9,10 +9,11 @@ from collections.abc import Mapping
from types import MappingProxyType
from typing import Final
from pydantic import BaseModel, ConfigDict, TypeAdapter, ValidationError
from pydantic import ConfigDict, TypeAdapter, ValidationError
from typing_extensions import assert_never
from litellm.llms.bedrock.common_utils import BedrockError
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.bedrock import (
TWELVELABS_MARENGO_3_EMBEDDING_OPTIONS,
TWELVELABS_MARENGO_3_EMBEDDING_SCOPES,
@ -57,7 +58,7 @@ def is_marengo_3_model(model: str | None) -> bool:
return MARENGO_3_MODEL_MARKER in (model or "")
class Marengo3Params(BaseModel):
class Marengo3Params(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
inputType: TWELVELABS_MARENGO_3_INPUT_TYPES | None = None

View file

@ -10,7 +10,7 @@ Marengo 3.0 docs - https://docs.aws.amazon.com/bedrock/latest/userguide/model-pa
from collections.abc import Mapping
from typing import Final, cast
from pydantic import BaseModel, ConfigDict, TypeAdapter
from pydantic import ConfigDict, TypeAdapter
from typing_extensions import assert_never
import litellm
@ -19,6 +19,7 @@ from litellm.llms.bedrock.embed.twelvelabs_marengo_3_transformation import (
build_marengo_3_request,
is_marengo_3_model,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.bedrock import (
TWELVELABS_EMBEDDING_INPUT_TYPES,
TWELVELABS_MARENGO_3_INPUT_TYPES,
@ -32,13 +33,13 @@ from litellm.types.llms.bedrock import (
from litellm.types.utils import Embedding, EmbeddingResponse, PromptTokensDetailsWrapper, Usage
class MarengoEmbeddingItem(BaseModel):
class MarengoEmbeddingItem(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
embedding: tuple[float, ...] | None = None
class MarengoInvokeResponse(BaseModel):
class MarengoInvokeResponse(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
data: tuple[MarengoEmbeddingItem, ...] = ()
@ -53,14 +54,14 @@ class MarengoInvokeResponse(BaseModel):
return tuple(item.embedding for item in self.embeddings if item.embedding is not None)
class MarengoBilledMultiInput(BaseModel):
class MarengoBilledMultiInput(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
inputText: str | None = None
mediaSources: tuple[Mapping[str, object], ...] = ()
class MarengoBilledRequest(BaseModel):
class MarengoBilledRequest(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
inputType: TWELVELABS_MARENGO_3_INPUT_TYPES | None = None

View file

@ -16,7 +16,7 @@ from urllib.parse import quote, unquote, urlencode
import httpx
from httpx import Headers, Response
from openai.types.file_deleted import FileDeleted
from pydantic import BaseModel, ConfigDict, Field
from pydantic import ConfigDict, Field
from typing_extensions import ReadOnly
from litellm._logging import verbose_logger
@ -47,6 +47,7 @@ from litellm.llms.base_llm.files.transformation import (
BaseFilesConfig,
LiteLLMLoggingObj,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.bedrock import AwsAuthParams, BedrockBatchRecordKind
from litellm.types.llms.openai import (
AllMessageValues,
@ -75,7 +76,7 @@ LIST_FILES_PURPOSE_PARAM: Final = "_s3_list_files_purpose"
LIST_FILES_LOCATION_PARAM: Final = "_s3_list_files_location"
class _S3DeleteContext(BaseModel):
class _S3DeleteContext(LiteLLMBaseModel):
file_id: str = Field(min_length=1)
@ -154,7 +155,7 @@ class _S3RequestTarget:
request_params: _BedrockS3RequestParams
class _TrustedS3ModelCredentials(BaseModel):
class _TrustedS3ModelCredentials(LiteLLMBaseModel):
"""The S3 buckets the server trusts file ids against, from the deployment snapshot."""
model_config = ConfigDict(extra="ignore")

View file

@ -10,7 +10,6 @@ import json
from typing import TYPE_CHECKING, Any, Final
import httpx
from pydantic import BaseModel
import litellm
from litellm._logging import verbose_logger
@ -27,6 +26,7 @@ from litellm.llms.custom_httpx.http_handler import (
_get_httpx_client,
get_async_httpx_client,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import ImageResponse
from ..base_aws_llm import BaseAWSLLM, bedrock_bearer_token
@ -38,7 +38,7 @@ else:
AWSPreparedRequest = Any
class BedrockImageEditPreparedRequest(BaseModel):
class BedrockImageEditPreparedRequest(LiteLLMBaseModel):
"""
Internal/Helper class for preparing the request for bedrock image edit
"""

View file

@ -4,7 +4,6 @@ import json
from typing import TYPE_CHECKING, Any, Final
import httpx
from pydantic import BaseModel
import litellm
from litellm._logging import verbose_logger
@ -27,6 +26,7 @@ from litellm.llms.custom_httpx.http_handler import (
_get_httpx_client,
get_async_httpx_client,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import ImageResponse
from ..base_aws_llm import BaseAWSLLM, bedrock_bearer_token
@ -38,7 +38,7 @@ else:
AWSPreparedRequest = Any
class BedrockImagePreparedRequest(BaseModel):
class BedrockImagePreparedRequest(LiteLLMBaseModel):
"""
Internal/Helper class for preparing the request for bedrock image generation
"""

View file

@ -10,7 +10,6 @@ import uuid as uuid_lib
from typing import Final, cast
import httpx
from pydantic import BaseModel
from litellm._logging import verbose_logger
from litellm._uuid import uuid
@ -18,6 +17,7 @@ from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLogging
from litellm.llms.base_llm.realtime.transformation import BaseRealtimeConfig
from litellm.llms.bedrock.common_utils import BedrockError
from litellm.llms.bedrock.realtime.trigger_audio import ready_trigger_pcm
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import (
OpenAIRealtimeContentPartDone,
OpenAIRealtimeDoneEvent,
@ -45,25 +45,25 @@ from litellm.types.realtime import (
)
class BedrockContentEnd(BaseModel):
class BedrockContentEnd(LiteLLMBaseModel):
stopReason: str | None = None
class BedrockUsageTokenDetails(BaseModel):
class BedrockUsageTokenDetails(LiteLLMBaseModel):
speechTokens: int = 0
textTokens: int = 0
class BedrockUsageDetailsTotal(BaseModel):
class BedrockUsageDetailsTotal(LiteLLMBaseModel):
input: BedrockUsageTokenDetails = BedrockUsageTokenDetails()
output: BedrockUsageTokenDetails = BedrockUsageTokenDetails()
class BedrockUsageDetails(BaseModel):
class BedrockUsageDetails(LiteLLMBaseModel):
total: BedrockUsageDetailsTotal = BedrockUsageDetailsTotal()
class BedrockUsageEvent(BaseModel):
class BedrockUsageEvent(LiteLLMBaseModel):
totalInputTokens: int = 0
totalOutputTokens: int = 0
totalTokens: int = 0

View file

@ -14,15 +14,16 @@ import aiohttp.client_exceptions
import aiohttp.http_exceptions
import httpx
from aiohttp.client import ClientResponse, ClientSession
from pydantic import BaseModel, TypeAdapter
from pydantic import TypeAdapter
from typing_extensions import ReadOnly, TypedDict
import litellm
from litellm._logging import verbose_logger
from litellm.secret_managers.main import str_to_bool
from litellm.types.llms.base import LiteLLMBaseModel
class HttpxTimeoutExtension(BaseModel):
class HttpxTimeoutExtension(LiteLLMBaseModel):
connect: float | None = None
read: float | None = None
write: float | None = None

View file

@ -13,12 +13,13 @@ from types import MappingProxyType
from typing import TYPE_CHECKING, Final
import httpx
from pydantic import BaseModel, TypeAdapter
from pydantic import TypeAdapter
import litellm
from litellm.litellm_core_utils.core_helpers import set_response_cost_in_hidden_params
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.llms.openai.chat.gpt_transformation import OpenAIChatCompletionStreamingHandler, OpenAIGPTConfig
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import AllMessageValues
from litellm.types.utils import ModelResponse, ModelResponseStream, Usage
@ -31,11 +32,11 @@ if TYPE_CHECKING:
_OPTIONAL_MAPPING: Final[TypeAdapter[Mapping[str, object] | None]] = TypeAdapter(Mapping[str, object] | None)
class _EdenAIModel(BaseModel):
class _EdenAIModel(LiteLLMBaseModel):
id: str
class _EdenAIModelCatalog(BaseModel):
class _EdenAIModelCatalog(LiteLLMBaseModel):
data: tuple[_EdenAIModel, ...]

View file

@ -7,12 +7,13 @@ from collections.abc import Container, Mapping
from types import MappingProxyType
from typing import Final
from pydantic import AliasChoices, BaseModel, Field, ValidationError
from pydantic import AliasChoices, Field, ValidationError
import litellm
from litellm.exceptions import AuthenticationError
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import LlmProviders
EDENAI_API_BASE: Final = "https://api.edenai.run/v3"
@ -23,7 +24,7 @@ class EdenAIException(BaseLLMException):
pass
class _EdenAIExtras(BaseModel):
class _EdenAIExtras(LiteLLMBaseModel):
cost: float | None = Field(default=None, validation_alias=AliasChoices("cost", EDENAI_COST_HEADER))

View file

@ -10,11 +10,12 @@ from collections.abc import Mapping, Sequence
from typing import TYPE_CHECKING, Final
import httpx
from pydantic import BaseModel, ConfigDict, TypeAdapter
from pydantic import ConfigDict, TypeAdapter
from litellm.litellm_core_utils.core_helpers import map_finish_reason
from litellm.llms.base_llm.chat.transformation import BaseConfig, BaseLLMException
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import AllMessageValues
from litellm.types.utils import Message, ModelResponse, Usage
@ -30,14 +31,14 @@ REASONING_DISABLED_EFFORTS: Final[frozenset[str]] = frozenset(("none", "minimal"
REASONING_ENABLED_EFFORTS: Final[frozenset[str]] = frozenset(("low", "medium", "high"))
class _FalUsage(BaseModel):
class _FalUsage(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
input_tokens: int
output_tokens: int
class _FalChatResponse(BaseModel):
class _FalChatResponse(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
output: str

View file

@ -8,12 +8,13 @@ from collections.abc import Iterable, Mapping, Sequence
from typing import Final
import httpx
from pydantic import BaseModel, ConfigDict, TypeAdapter
from pydantic import ConfigDict, TypeAdapter
from litellm._uuid import uuid
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.llms.base_llm.rerank.transformation import BaseRerankConfig
from litellm.llms.fireworks_ai.common_utils import FireworksAIMixin
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.rerank import (
RerankBilledUnits,
RerankResponse,
@ -24,7 +25,7 @@ from litellm.types.rerank import (
)
class _FireworksAIUsageFields(BaseModel):
class _FireworksAIUsageFields(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True)
total_tokens: int | None = 0
@ -32,7 +33,7 @@ class _FireworksAIUsageFields(BaseModel):
completion_tokens: int | None = 0
class _FireworksAIResultFields(BaseModel):
class _FireworksAIResultFields(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore", frozen=True, hide_input_in_errors=True)
index: int | float | str

View file

@ -16,6 +16,7 @@ from litellm.llms.openai.chat.gpt_transformation import (
)
from litellm.llms.openai.common_utils import OpenAIError
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import (
AllMessageValues,
ChatCompletionAssistantMessage,
@ -32,7 +33,7 @@ if TYPE_CHECKING:
GROQ_COMPOUND_MODELS: Final = frozenset({"compound", "compound-mini"})
class GroqExecutedToolIdentity(BaseModel):
class GroqExecutedToolIdentity(LiteLLMBaseModel):
name: str | None = None
type: str | None = None

View file

@ -1,10 +1,12 @@
from collections.abc import Mapping
from typing import Final
from pydantic import BaseModel, TypeAdapter, ValidationError
from pydantic import TypeAdapter, ValidationError
from litellm.types.llms.base import LiteLLMBaseModel
class _LayaRouting(BaseModel):
class _LayaRouting(LiteLLMBaseModel):
model: str | None = None

View file

@ -6,7 +6,7 @@ from collections.abc import Sequence
from dataclasses import dataclass
from typing import TYPE_CHECKING, Final, TypeAlias
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
from litellm.llms.litellm_proxy.skills.constants import MAX_SKILLS_PER_SEARCH
from litellm.llms.litellm_proxy.skills.handler import LiteLLMSkillsHandler
@ -16,6 +16,7 @@ from litellm.proxy.common_utils.semantic_text_index import (
SemanticTextIndex,
router_embedder,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import LlmProviders
if TYPE_CHECKING:
@ -63,7 +64,7 @@ SkillSearchOutcome: TypeAlias = SkillSearchHits | SkillSearchNotConfigured | Ski
HostedSkillSearchOutcome: TypeAlias = SkillSearchOutcome | SkillSearchUnsupportedProvider
class SkillSearchResult(BaseModel):
class SkillSearchResult(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
skill_id: str

View file

@ -15,12 +15,13 @@ import httpx
from openai.types.batch import BatchRequestCounts
from openai.types.batch import Errors as BatchErrors
from openai.types.batch_error import BatchError
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
from typing_extensions import NotRequired, ReadOnly, TypedDict
from litellm.litellm_core_utils.url_utils import encode_url_path_segment
from litellm.llms.base_llm.batches.transformation import BaseBatchesConfig
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import AllMessageValues, CreateBatchRequest
from litellm.types.utils import LiteLLMBatch, LlmProviders
@ -64,14 +65,14 @@ class MistralPresignedRequest(TypedDict):
headers: ReadOnly[Mapping[str, str]]
class MistralBatchError(BaseModel):
class MistralBatchError(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
message: str
count: int = 1
class MistralBatchJob(BaseModel):
class MistralBatchJob(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
id: str

View file

@ -14,13 +14,14 @@ from typing import Final, Literal, TypeAlias
import httpx
from openai.types.file_deleted import FileDeleted
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
from typing_extensions import ReadOnly, TypedDict
from litellm.litellm_core_utils.prompt_templates.common_utils import extract_file_data
from litellm.litellm_core_utils.url_utils import encode_url_path_segment
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.llms.base_llm.files.transformation import BaseFilesConfig, LiteLLMLoggingObj
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import (
CreateFileRequest,
FileContentRequest,
@ -54,7 +55,7 @@ class MistralMultipartUpload(TypedDict):
purpose: ReadOnly[tuple[None, MistralFilePurpose]]
class MistralFile(BaseModel):
class MistralFile(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
id: str
@ -65,13 +66,13 @@ class MistralFile(BaseModel):
expires_at: int | None = None
class MistralFileList(BaseModel):
class MistralFileList(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
data: tuple[MistralFile, ...] = ()
class MistralFileDeleted(BaseModel):
class MistralFileDeleted(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
id: str

View file

@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Final, Literal, NoReturn
from urllib.parse import quote, urlsplit
import httpx
from pydantic import BaseModel, ConfigDict, TypeAdapter, ValidationError
from pydantic import ConfigDict, TypeAdapter, ValidationError
from litellm.exceptions import AuthenticationError, BadRequestError, ServiceUnavailableError, Timeout
from litellm.llms.base_llm.chat.transformation import BaseLLMException
@ -16,6 +16,7 @@ from litellm.llms.base_llm.vector_store.transformation import (
VectorStoreEmbeddingExecutor,
)
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.router import GenericLiteLLMParams
from litellm.types.utils import EmbeddingResponse
from litellm.types.vector_stores import (
@ -49,13 +50,13 @@ def config_error(message: str) -> BadRequestError:
return BadRequestError(message=message, model=None, llm_provider="mongodb")
class _Content(BaseModel):
class _Content(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, strict=True)
type: Literal["text"]
text: str
class _Result(BaseModel):
class _Result(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, strict=True, allow_inf_nan=False)
score: float | None
content: Sequence[_Content]
@ -63,14 +64,14 @@ class _Result(BaseModel):
filename: str | None
class _SearchResponse(BaseModel):
class _SearchResponse(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, strict=True)
object: Literal["vector_store.search_results.page"]
search_query: str
data: Sequence[_Result]
class _MongoDBSearchParams(BaseModel):
class _MongoDBSearchParams(LiteLLMBaseModel):
"""Typed view over the vector store's litellm_params; unrelated keys are ignored."""
model_config = ConfigDict(frozen=True, extra="ignore")

View file

@ -11,7 +11,7 @@ from types import MappingProxyType
from typing import TYPE_CHECKING, Final
import httpx
from pydantic import BaseModel, ConfigDict, TypeAdapter, ValidationError
from pydantic import ConfigDict, TypeAdapter, ValidationError
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.llms.base_llm.search.transformation import (
@ -20,6 +20,7 @@ from litellm.llms.base_llm.search.transformation import (
SearchResult,
)
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
@ -27,7 +28,7 @@ if TYPE_CHECKING:
_NIMBLE_DOCS_URL: Final = "https://docs.nimbleway.com/api-reference/search/search"
class _NimbleResult(BaseModel):
class _NimbleResult(LiteLLMBaseModel):
"""One entry of Nimble's `results` array. Every field is optional so a single degraded
result degrades to empty strings instead of failing the whole call."""
@ -41,7 +42,7 @@ class _NimbleResult(BaseModel):
additional_data: object = None
class _NimbleSearchResponse(BaseModel):
class _NimbleSearchResponse(LiteLLMBaseModel):
"""Nimble's /v2/search response envelope."""
model_config = ConfigDict(extra="ignore", frozen=True)
@ -51,7 +52,7 @@ class _NimbleSearchResponse(BaseModel):
results: tuple[_NimbleResult, ...]
class _AdditionalData(BaseModel):
class _AdditionalData(LiteLLMBaseModel):
"""The slice of a result's free-form `additional_data` that maps onto SearchResult."""
model_config = ConfigDict(extra="ignore", frozen=True)
@ -59,7 +60,7 @@ class _AdditionalData(BaseModel):
publish_date: str | None = None
class _ErrorEnvelope(BaseModel):
class _ErrorEnvelope(LiteLLMBaseModel):
"""Nimble reports errors as either `{"detail": ...}` (validation) or
`{"success": "false", "task_id": ..., "message": ...}` (collection)."""

View file

@ -13,10 +13,11 @@ from typing import Final, Protocol, runtime_checkable
from urllib.parse import urlparse
import httpx
from pydantic import BaseModel, ConfigDict, Field, JsonValue, TypeAdapter, ValidationError, field_validator
from pydantic import ConfigDict, Field, JsonValue, TypeAdapter, ValidationError, field_validator
from litellm._logging import verbose_logger
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.types.llms.base import LiteLLMBaseModel
try:
from cryptography.hazmat.primitives import hashes, serialization
@ -214,7 +215,7 @@ _OCI_REALM_DOMAINS: Final = MappingProxyType(
)
class OCIRegionMetadata(BaseModel):
class OCIRegionMetadata(LiteLLMBaseModel):
"""One entry of the OCI SDK's region metadata schema, as found in
``~/.oci/regions-config.json`` (a JSON array) or ``OCI_REGION_METADATA`` (one object).
Values are lowercased before validation, as the SDK does."""

View file

@ -4,7 +4,7 @@ from collections.abc import AsyncIterator, Iterator
from typing import TYPE_CHECKING, Any, Final
from httpx._models import Headers, Response
from pydantic import BaseModel, ConfigDict, ValidationError
from pydantic import ConfigDict, ValidationError
import litellm
from litellm._logging import verbose_proxy_logger
@ -23,6 +23,7 @@ from litellm.litellm_core_utils.prompt_templates.image_handling import (
)
from litellm.llms.base_llm.base_model_iterator import BaseModelResponseIterator
from litellm.llms.base_llm.chat.transformation import BaseConfig, BaseLLMException
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import AllMessageValues, ChatCompletionUsageBlock
from litellm.types.utils import (
Delta,
@ -44,7 +45,7 @@ else:
LiteLLMLoggingObj = Any
class _OllamaGenerateReasoning(BaseModel):
class _OllamaGenerateReasoning(LiteLLMBaseModel):
"""The two `/api/generate` fields a reply's reasoning can arrive in."""
model_config = ConfigDict(extra="ignore")

View file

@ -8,7 +8,7 @@ from types import MappingProxyType
from typing import Final, Literal, TypeAlias
import httpx
from pydantic import BaseModel, ConfigDict, ValidationError
from pydantic import ConfigDict, ValidationError
from litellm.constants import (
OPENAI_ORGANIZATION_COSTS_PAGE_LIMIT,
@ -16,6 +16,7 @@ from litellm.constants import (
PROVIDER_BILLING_TIMEOUT_SECONDS,
)
from litellm.llms.custom_httpx.http_handler import get_async_httpx_client
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.custom_http import httpxSpecialProvider
OPENAI_ADMIN_KEY_ENV_VAR: Final = "OPENAI_ADMIN_KEY"
@ -31,27 +32,27 @@ class OpenAICostsRequestFailed:
detail: str
class _OpenAICostAmount(BaseModel):
class _OpenAICostAmount(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
value: float
currency: Literal["usd"]
class _OpenAICostResult(BaseModel):
class _OpenAICostResult(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
amount: _OpenAICostAmount
class _OpenAICostBucket(BaseModel):
class _OpenAICostBucket(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
start_time: int
results: tuple[_OpenAICostResult, ...] = ()
class _OpenAICostsPage(BaseModel):
class _OpenAICostsPage(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
data: tuple[_OpenAICostBucket, ...]

View file

@ -66,6 +66,7 @@ from litellm.llms.openai.responses.guardrail_translation.tool_merge import merge
from litellm.responses.litellm_completion_transformation.transformation import (
LiteLLMCompletionResponsesConfig,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import (
AllMessageValues,
BaseLiteLLMOpenAIResponseObject,
@ -110,14 +111,14 @@ class _ToolCallShape(NamedTuple):
arguments: str
class _ToolCallFunctionFields(BaseModel):
class _ToolCallFunctionFields(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
name: str | None = None
arguments: str = ""
class _ToolCallFields(BaseModel):
class _ToolCallFields(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
function: _ToolCallFunctionFields

View file

@ -26,6 +26,7 @@ from litellm.llms.openai.chat.gpt_5_transformation import is_gpt_reasoning_serie
from litellm.responses.litellm_completion_transformation.custom_tools import TOOL_CALL_ITEM_ID_PREFIX_BY_TYPE
from litellm.responses.litellm_completion_transformation.reasoning_items import is_litellm_minted_reasoning_item
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import *
from litellm.types.responses.main import *
from litellm.types.router import GenericLiteLLMParams
@ -51,7 +52,7 @@ _PROVIDERS_VALIDATING_TOOL_CALL_ITEM_IDS: Final = frozenset({LlmProviders.AZURE,
_PROVIDERS_REPLAYING_ONLY_THEIR_OWN_REASONING: Final = _PROVIDERS_VALIDATING_TOOL_CALL_ITEM_IDS
class _ReasoningSupportEntry(BaseModel):
class _ReasoningSupportEntry(LiteLLMBaseModel):
litellm_provider: str | None = None
supports_reasoning: bool | None = None

View file

@ -5,11 +5,12 @@ from types import MappingProxyType
from typing import Annotated, Final, TypeAlias
import httpx
from pydantic import BaseModel, BeforeValidator, ConfigDict
from pydantic import BeforeValidator, ConfigDict
from litellm._logging import verbose_logger
from litellm.caching.in_memory_cache import InMemoryCache
from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.utils import _add_path_to_api_base # pyright: ignore[reportPrivateUsage] # shared provider URL helper
MODEL_INFO_REFRESH_SECONDS: Final = 300
@ -25,7 +26,7 @@ def _positive_limit(value: object) -> int | None:
_TokenLimit: TypeAlias = Annotated[int | None, BeforeValidator(_positive_limit)]
class _ModelCard(BaseModel):
class _ModelCard(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
id: str
@ -51,7 +52,7 @@ class _ModelCard(BaseModel):
)
class _ModelList(BaseModel):
class _ModelList(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
data: tuple[_ModelCard, ...] = ()

View file

@ -9,7 +9,7 @@ from types import MappingProxyType
from typing import Final, TypedDict
import httpx
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
from typing_extensions import ReadOnly
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
@ -20,9 +20,10 @@ from litellm.llms.base_llm.search.transformation import (
)
from litellm.llms.parallel_ai.search.cost_calculator import PARALLEL_AI_USAGE_PARAM
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
class _ParallelAIV1SearchResult(BaseModel):
class _ParallelAIV1SearchResult(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore")
url: str | None = None
@ -31,7 +32,7 @@ class _ParallelAIV1SearchResult(BaseModel):
excerpts: Sequence[str] | None = None
class _ParallelAIV1SearchResponse(BaseModel):
class _ParallelAIV1SearchResponse(LiteLLMBaseModel):
model_config = ConfigDict(extra="ignore")
search_id: str | None = None

View file

@ -2,7 +2,9 @@ import warnings
from enum import Enum
from typing import Final, Literal
from pydantic import BaseModel, Field, field_validator, model_validator
from pydantic import Field, field_validator, model_validator
from litellm.types.llms.base import LiteLLMBaseModel
def validate_different_content(v: str | dict | list) -> str:
@ -24,30 +26,30 @@ def validate_different_content(v: str | dict | list) -> str:
raise ValueError("Content must be a string")
class TextContent(BaseModel):
class TextContent(LiteLLMBaseModel):
type_: Literal["text"] = Field(default="text", alias="type")
text: str
class ImageURLContent(BaseModel):
class ImageURLContent(LiteLLMBaseModel):
url: str
detail: str = "auto"
class ImageContent(BaseModel):
class ImageContent(LiteLLMBaseModel):
type_: Literal["image_url"] = Field(default="image_url", alias="type")
image_url: ImageURLContent
class FunctionObj(BaseModel):
class FunctionObj(LiteLLMBaseModel):
name: str
arguments: str
class FunctionTool(BaseModel):
class FunctionTool(LiteLLMBaseModel):
description: str = ""
name: str
parameters: dict = {"type": "object", "properties": {}}
parameters: dict = Field(default={"type": "object", "properties": {}})
strict: bool = False
def model_dump(self, **kwargs) -> dict:
@ -67,7 +69,7 @@ class FunctionTool(BaseModel):
return v
class ChatCompletionTool(BaseModel):
class ChatCompletionTool(LiteLLMBaseModel):
type_: Literal["function"] = Field(default="function", alias="type")
function: FunctionTool
@ -76,13 +78,13 @@ class ChatCompletionTool(BaseModel):
return super().model_dump(**kwargs)
class MessageToolCall(BaseModel):
class MessageToolCall(LiteLLMBaseModel):
id: str
type_: Literal["function"] = Field(default="function", alias="type")
function: FunctionObj
class SAPMessage(BaseModel):
class SAPMessage(LiteLLMBaseModel):
"""
Model for SystemChatMessage and DeveloperChatMessage
"""
@ -93,21 +95,21 @@ class SAPMessage(BaseModel):
_content_validator = field_validator("content", mode="before")(validate_different_content)
class SAPUserMessage(BaseModel):
class SAPUserMessage(LiteLLMBaseModel):
role: Literal["user"] = "user"
content: str | TextContent | ImageContent | list[TextContent | ImageContent]
class SAPAssistantMessage(BaseModel):
class SAPAssistantMessage(LiteLLMBaseModel):
role: Literal["assistant"] = "assistant"
content: str = ""
refusal: str = ""
tool_calls: list[MessageToolCall] = []
tool_calls: list[MessageToolCall] = Field(default=[])
_content_validator = field_validator("content", mode="before")(validate_different_content)
class SAPToolChatMessage(BaseModel):
class SAPToolChatMessage(LiteLLMBaseModel):
role: Literal["tool"] = "tool"
tool_call_id: str
content: str
@ -118,23 +120,23 @@ class SAPToolChatMessage(BaseModel):
ChatMessage = SAPMessage | SAPUserMessage | SAPAssistantMessage | SAPToolChatMessage
class ResponseFormat(BaseModel):
class ResponseFormat(LiteLLMBaseModel):
type_: Literal["text", "json_object"] = Field(default="text", alias="type")
class JSONResponseSchema(BaseModel):
class JSONResponseSchema(LiteLLMBaseModel):
description: str = ""
name: str
schema_: dict = Field(default_factory=dict, alias="schema")
strict: bool = False
class ResponseFormatJSONSchema(BaseModel):
class ResponseFormatJSONSchema(LiteLLMBaseModel):
type_: Literal["json_schema"] = Field(default="json_schema", alias="type")
json_schema: JSONResponseSchema
class KeyValueListPair(BaseModel):
class KeyValueListPair(LiteLLMBaseModel):
key: str
value: list[str]
@ -143,7 +145,7 @@ class DocumentMetadataKeyValueListPairs(KeyValueListPair):
select_mode: list[Literal["ignoreIfKeyAbsent"]] | None = None
class GroundingSearchConfig(BaseModel):
class GroundingSearchConfig(LiteLLMBaseModel):
max_chunk_count: int | None = Field(default=None, ge=0)
max_document_count: int | None = Field(default=None, ge=0)
@ -154,7 +156,7 @@ class GroundingSearchConfig(BaseModel):
return self
class DocumentGroundingFilter(BaseModel):
class DocumentGroundingFilter(LiteLLMBaseModel):
id_: str | None = Field(default=None, alias="id")
data_repository_type: Literal["vector", "help.sap.com"]
search_config: GroundingSearchConfig | None = None
@ -164,36 +166,36 @@ class DocumentGroundingFilter(BaseModel):
chunk_metadata: list[KeyValueListPair] | None = None
class DocumentGroundingPlaceholders(BaseModel):
class DocumentGroundingPlaceholders(LiteLLMBaseModel):
input: list[str] = Field(min_length=1)
output: str
class DocumentGroundingConfig(BaseModel):
class DocumentGroundingConfig(LiteLLMBaseModel):
filters: list[DocumentGroundingFilter] | None = None
placeholders: DocumentGroundingPlaceholders
metadata_params: list[str] | None = None
class GroundingModuleConfig(BaseModel):
class GroundingModuleConfig(LiteLLMBaseModel):
type_: Literal["document_grounding_service"] = Field(default="document_grounding_service", alias="type")
config: DocumentGroundingConfig
class Template(BaseModel):
class Template(LiteLLMBaseModel):
template: list[ChatMessage]
defaults: dict[str, str] | None = None
response_format: ResponseFormat | ResponseFormatJSONSchema | None = None
tools: list[ChatCompletionTool] | None = None
class LLMModelDetails(BaseModel):
class LLMModelDetails(LiteLLMBaseModel):
name: str
version: str = "latest"
params: dict | None = None
class PromptTemplatingModuleConfig(BaseModel):
class PromptTemplatingModuleConfig(LiteLLMBaseModel):
prompt: Template
model: LLMModelDetails
@ -285,7 +287,7 @@ class SAPMaskingProfileEntity(str, Enum):
ETHNICITY = "profile-ethnicity"
class DPIMethodConstant(BaseModel):
class DPIMethodConstant(LiteLLMBaseModel):
"""
Replaces the entity with the specified value followed by an incrementing number
"""
@ -294,7 +296,7 @@ class DPIMethodConstant(BaseModel):
value: str
class DPIMethodFabricatedData(BaseModel):
class DPIMethodFabricatedData(LiteLLMBaseModel):
"""
Replaces the entity with a randomly generated value appropriate to its type.
"""
@ -302,7 +304,7 @@ class DPIMethodFabricatedData(BaseModel):
method: Literal["fabricated_data"] = "fabricated_data"
class DPICustomEntity(BaseModel):
class DPICustomEntity(LiteLLMBaseModel):
"""
regex: Regular expression to match the entity
replacement_strategy: Replacement strategy to be used for the entity
@ -312,7 +314,7 @@ class DPICustomEntity(BaseModel):
replacement_strategy: DPIMethodConstant
class DPIStandardEntity(BaseModel):
class DPIStandardEntity(LiteLLMBaseModel):
"""
type: Standard entity type to be masked
replacement_strategy: Replacement strategy to be used for the entity
@ -322,7 +324,7 @@ class DPIStandardEntity(BaseModel):
replacement_strategy: DPIMethodConstant | DPIMethodFabricatedData | None = None
class MaskGroundingInput(BaseModel):
class MaskGroundingInput(LiteLLMBaseModel):
"""
Controls whether the input to the grounding module will be masked with the configuration
supplied in the masking module
@ -331,7 +333,7 @@ class MaskGroundingInput(BaseModel):
enabled: bool = False
class MaskingProviderConfig(BaseModel):
class MaskingProviderConfig(LiteLLMBaseModel):
"""
SAP Data Privacy Integration provider for data masking.
@ -356,7 +358,7 @@ class MaskingProviderConfig(BaseModel):
mask_grounding_input: MaskGroundingInput | None = None
class MaskingModuleConfig(BaseModel):
class MaskingModuleConfig(LiteLLMBaseModel):
"""
Configuration for the data masking module.
@ -417,7 +419,7 @@ class AzureThreshold(int, Enum):
ALLOW_ALL = 6
class AzureContentFilter(BaseModel):
class AzureContentFilter(LiteLLMBaseModel):
"""
Specific filter configuration for Azure Content Safety.
@ -481,7 +483,7 @@ class AzureContentSafetyOutput(AzureContentFilter):
protected_material_code: bool | None = False
class LlamaGuard38bFilter(BaseModel):
class LlamaGuard38bFilter(LiteLLMBaseModel):
"""
Specific implementation of ContentFilter for Llama Guard 3. Llama Guard 3 is a
Llama-3.1-8B pretrained model, fine-tuned for content safety classification.
@ -532,22 +534,22 @@ class LlamaGuard38bFilter(BaseModel):
code_interpreter_abuse: bool = Field(default=False)
class LlamaGuard38bFilterConfig(BaseModel):
class LlamaGuard38bFilterConfig(LiteLLMBaseModel):
type_: Literal["llama_guard_3_8b"] = Field(default="llama_guard_3_8b", alias="type")
config: LlamaGuard38bFilter
class AzureContentSafetyInputFilterConfig(BaseModel):
class AzureContentSafetyInputFilterConfig(LiteLLMBaseModel):
type_: Literal["azure_content_safety"] = Field(default="azure_content_safety", alias="type")
config: AzureContentSafetyInput | None = None
class AzureContentSafetyOutputFilterConfig(BaseModel):
class AzureContentSafetyOutputFilterConfig(LiteLLMBaseModel):
type_: Literal["azure_content_safety"] = Field(default="azure_content_safety", alias="type")
config: AzureContentSafetyOutput | None = None
class FilteringStreamOptions(BaseModel):
class FilteringStreamOptions(LiteLLMBaseModel):
"""
overlap: Number of characters that should be additionally sent to content filtering services
from previous chunks as additional context.
@ -556,7 +558,7 @@ class FilteringStreamOptions(BaseModel):
overlap: int | None = Field(default=0, ge=0, le=10000)
class InputFiltering(BaseModel):
class InputFiltering(LiteLLMBaseModel):
"""Module for managing and applying input content filters.
Args:
@ -566,7 +568,7 @@ class InputFiltering(BaseModel):
filters: list[AzureContentSafetyInputFilterConfig | LlamaGuard38bFilterConfig] = Field(min_length=1)
class OutputFiltering(BaseModel):
class OutputFiltering(LiteLLMBaseModel):
"""Module for managing and applying output content filters.
Args:
@ -579,7 +581,7 @@ class OutputFiltering(BaseModel):
stream_options: FilteringStreamOptions | None = None
class FilteringModuleConfig(BaseModel):
class FilteringModuleConfig(LiteLLMBaseModel):
"""Module for managing and applying content filters.
Args:
@ -603,7 +605,7 @@ class FilteringModuleConfig(BaseModel):
return self
class SAPDocumentTranslationApplyToSelector(BaseModel):
class SAPDocumentTranslationApplyToSelector(LiteLLMBaseModel):
"""
This selector allows you to define the scope of translation, such as specific placeholders or
messages with specific roles.
@ -619,7 +621,7 @@ class SAPDocumentTranslationApplyToSelector(BaseModel):
source_language: str
class InputTranslationConfig(BaseModel):
class InputTranslationConfig(LiteLLMBaseModel):
"""
Configuration for input translation.
@ -634,12 +636,12 @@ class InputTranslationConfig(BaseModel):
apply_to: list[SAPDocumentTranslationApplyToSelector] | None = None
class OutputTranslationConfig(BaseModel):
class OutputTranslationConfig(LiteLLMBaseModel):
source_language: str | None = None
target_language: str | SAPDocumentTranslationApplyToSelector
class SAPDocumentTranslationInput(BaseModel):
class SAPDocumentTranslationInput(LiteLLMBaseModel):
"""
Configuration for input translation
@ -656,7 +658,7 @@ class SAPDocumentTranslationInput(BaseModel):
config: InputTranslationConfig
class SAPDocumentTranslationOutput(BaseModel):
class SAPDocumentTranslationOutput(LiteLLMBaseModel):
"""
Configuration for output translation
@ -670,7 +672,7 @@ class SAPDocumentTranslationOutput(BaseModel):
config: OutputTranslationConfig
class TranslationModuleConfig(BaseModel):
class TranslationModuleConfig(LiteLLMBaseModel):
"""
Configuration for translation module
@ -690,7 +692,7 @@ class TranslationModuleConfig(BaseModel):
return self
class ModuleConfig(BaseModel):
class ModuleConfig(LiteLLMBaseModel):
prompt_templating: PromptTemplatingModuleConfig
filtering: FilteringModuleConfig | None = None
masking: MaskingModuleConfig | None = None
@ -698,17 +700,17 @@ class ModuleConfig(BaseModel):
translation: TranslationModuleConfig | None = None
class GlobalStreamOptions(BaseModel):
class GlobalStreamOptions(LiteLLMBaseModel):
enabled: bool = False
chunk_size: int | None = Field(default=None, ge=1)
delimiters: list[str] | None = None
class OrchestrationConfig(BaseModel):
class OrchestrationConfig(LiteLLMBaseModel):
modules: ModuleConfig | list[ModuleConfig]
stream: GlobalStreamOptions | None = None
class OrchestrationRequest(BaseModel):
class OrchestrationRequest(LiteLLMBaseModel):
config: OrchestrationConfig
placeholder_values: dict[str, str] | None = None

View file

@ -6,13 +6,14 @@ from functools import cached_property
from typing import Final, Literal
import httpx
from pydantic import BaseModel, Field
from pydantic import Field
from litellm.llms.base_llm.embedding.transformation import (
BaseEmbeddingConfig,
LiteLLMLoggingObj,
)
from litellm.llms.sap.chat.models import MaskingModuleConfig
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import AllEmbeddingInputValues
from litellm.types.utils import EmbeddingResponse
@ -20,30 +21,30 @@ from ..chat.handler import GenAIHubOrchestrationError
from ..credentials import get_token_creator
class Usage(BaseModel):
class Usage(LiteLLMBaseModel):
prompt_tokens: int
total_tokens: int
class EmbeddingItem(BaseModel):
class EmbeddingItem(LiteLLMBaseModel):
object: Literal["embedding"]
embedding: list[float] = Field(..., description="Vector of floats (length varies by model).")
index: int
class FinalResult(BaseModel):
class FinalResult(LiteLLMBaseModel):
object: Literal["list"]
data: list[EmbeddingItem]
model: str
usage: Usage
class EmbeddingsResponse(BaseModel):
class EmbeddingsResponse(LiteLLMBaseModel):
request_id: str
final_result: FinalResult
class EmbeddingModel(BaseModel):
class EmbeddingModel(LiteLLMBaseModel):
name: str
version: str = "latest"
params: dict = Field(default_factory=dict)
@ -51,25 +52,25 @@ class EmbeddingModel(BaseModel):
max_retries: int | None = Field(default=None, ge=0, le=5)
class EmbeddingsModelConfig(BaseModel):
class EmbeddingsModelConfig(LiteLLMBaseModel):
model: EmbeddingModel
class EmbeddingsModules(BaseModel):
class EmbeddingsModules(LiteLLMBaseModel):
embeddings: EmbeddingsModelConfig
masking: MaskingModuleConfig | None = None
class EmbeddingInput(BaseModel):
class EmbeddingInput(LiteLLMBaseModel):
text: str | list[str]
type: Literal["text", "document", "query"] | None = None
class EmbeddingConfig(BaseModel):
class EmbeddingConfig(LiteLLMBaseModel):
modules: EmbeddingsModules
class EmbeddingRequest(BaseModel):
class EmbeddingRequest(LiteLLMBaseModel):
config: EmbeddingConfig
input: EmbeddingInput

View file

@ -12,7 +12,7 @@ from types import MappingProxyType
from typing import TYPE_CHECKING, Final, NoReturn
import httpx
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
import litellm
from litellm.llms.base_llm.vector_store.transformation import (
@ -20,6 +20,7 @@ from litellm.llms.base_llm.vector_store.transformation import (
VectorStoreEmbeddingExecutor,
)
from litellm.llms.valkey.common_utils import build_valkey_url, pack_vector
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import EmbeddingResponse
from litellm.types.vector_stores import (
VectorStoreCreateOptionalRequestParams,
@ -79,7 +80,7 @@ def _import_query() -> "type[Query]":
return RedisQuery
class _ValkeySearchParams(BaseModel):
class _ValkeySearchParams(LiteLLMBaseModel):
"""Typed view over the vector store's litellm_params; unrelated keys are ignored."""
model_config = ConfigDict(frozen=True, extra="ignore")

View file

@ -1,15 +1,14 @@
import types
from typing import Final, Literal
from pydantic import BaseModel
from litellm.llms.vertex_ai.common_utils import pop_vertex_request_labels
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.utils import EmbeddingResponse, Usage
from .types import *
class VertexAITextEmbeddingConfig(BaseModel):
class VertexAITextEmbeddingConfig(LiteLLMBaseModel):
"""
Reference: https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/text-embeddings-api#TextEmbeddingInput

View file

@ -6,11 +6,12 @@ from collections.abc import Mapping, Sequence
from typing import Final
from httpx import Headers, Response
from pydantic import BaseModel, ConfigDict, TypeAdapter, ValidationError
from pydantic import ConfigDict, TypeAdapter, ValidationError
import litellm
from litellm.litellm_core_utils.audio_utils.utils import process_audio_file
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import (
AllMessageValues,
OpenAIAudioTranscriptionOptionalParams,
@ -28,7 +29,7 @@ class XAIAudioTranscriptionError(BaseLLMException):
pass
class _XAISttWord(BaseModel):
class _XAISttWord(LiteLLMBaseModel):
model_config = ConfigDict(extra="allow")
text: str = ""
start: float = 0.0
@ -36,7 +37,7 @@ class _XAISttWord(BaseModel):
speaker: int | None = None
class _XAISttResponse(BaseModel):
class _XAISttResponse(LiteLLMBaseModel):
model_config = ConfigDict(extra="allow")
text: str = ""
language: str = "unknown"

View file

@ -15,7 +15,7 @@ import httpx
from openai.types.batch import BatchRequestCounts
from openai.types.batch import Errors as BatchErrors
from openai.types.batch_error import BatchError
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
from typing_extensions import NotRequired, ReadOnly, TypedDict
from litellm.constants import XAI_API_BASE
@ -23,6 +23,7 @@ from litellm.litellm_core_utils.url_utils import encode_url_path_segment
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.llms.xai.common_utils import XAIModelInfo
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import CreateBatchRequest
from litellm.types.utils import LiteLLMBatch
@ -89,7 +90,7 @@ class XAICreateBatchRequest(TypedDict):
input_file_id: NotRequired[ReadOnly[str]]
class XAIBatchState(BaseModel):
class XAIBatchState(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
num_requests: int = 0
@ -99,7 +100,7 @@ class XAIBatchState(BaseModel):
num_cancelled: int = 0
class XAIBatch(BaseModel):
class XAIBatch(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
batch_id: str
@ -112,35 +113,35 @@ class XAIBatch(BaseModel):
input_file_id: str | None = None
class XAIBatchList(BaseModel):
class XAIBatchList(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
batches: tuple[XAIBatch, ...] = ()
pagination_token: str | None = None
class XAIBatchResultError(BaseModel):
class XAIBatchResultError(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
code: int | str | None = None
message: str = ""
class XAIBatchResultData(BaseModel):
class XAIBatchResultData(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
response: Mapping[str, Mapping[str, object]] | None = None
error: XAIBatchResultError | None = None
class XAIBatchResult(BaseModel):
class XAIBatchResult(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
batch_request_id: str
batch_result: XAIBatchResultData = XAIBatchResultData()
class XAIBatchResultsPage(BaseModel):
class XAIBatchResultsPage(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
results: tuple[XAIBatchResult, ...] = ()
@ -202,7 +203,7 @@ def to_litellm_batch(batch: XAIBatch, endpoint: str = DEFAULT_BATCH_ENDPOINT) ->
)
class OpenAIBatchListResponse(BaseModel):
class OpenAIBatchListResponse(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
object: Literal["list"] = "list"

View file

@ -10,13 +10,14 @@ from typing import Final
import httpx
from openai.types.file_deleted import FileDeleted
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
from typing_extensions import ReadOnly, TypedDict
from litellm.litellm_core_utils.prompt_templates.common_utils import extract_file_data
from litellm.litellm_core_utils.url_utils import encode_url_path_segment
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.llms.base_llm.files.transformation import BaseFilesConfig, LiteLLMLoggingObj
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import (
CreateFileRequest,
FileContentRequest,
@ -43,7 +44,7 @@ class XAIMultipartUpload(TypedDict):
purpose: ReadOnly[tuple[None, str]]
class XAIFile(BaseModel):
class XAIFile(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
id: str
@ -54,14 +55,14 @@ class XAIFile(BaseModel):
expires_at: int | None = None
class XAIFileList(BaseModel):
class XAIFileList(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
data: tuple[XAIFile, ...] = ()
pagination_token: str | None = None
class XAIFileDeleted(BaseModel):
class XAIFileDeleted(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
id: str

View file

@ -44,6 +44,7 @@ import litellm
# client must be imported from litellm as it's a decorator used at function definition time
from litellm import client
from litellm.types.llms.base import LiteLLMBaseModel
# Other utils are imported directly to avoid circular imports
from litellm.utils import (
@ -862,11 +863,11 @@ async def _sleep_for_timeout_async(timeout: float | str | httpx.Timeout):
await asyncio.sleep(timeout.connect)
class _AdmissionReservation(BaseModel):
class _AdmissionReservation(LiteLLMBaseModel):
input_tokens: int | None = None
class _AdmissionMetadata(BaseModel):
class _AdmissionMetadata(LiteLLMBaseModel):
user_api_key_budget_reservation: _AdmissionReservation | None = None

View file

@ -5,10 +5,12 @@ Base model class for domain models.
from datetime import datetime
from typing import Any
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
from litellm.types.llms.base import LiteLLMBaseModel
class DomainModel(BaseModel):
class DomainModel(LiteLLMBaseModel):
"""Base class for all domain models."""
model_config = ConfigDict(

View file

@ -7,10 +7,12 @@ layer; ``litellm.types.utils`` re-exports them for backwards compatibility.
from collections.abc import Mapping
from pydantic import BaseModel, Field, model_validator
from pydantic import Field, model_validator
from litellm.types.llms.base import LiteLLMBaseModel
class CredentialBase(BaseModel):
class CredentialBase(LiteLLMBaseModel):
credential_name: str
credential_info: dict
@ -35,7 +37,7 @@ class CreateCredentialItem(CredentialBase):
return values
class UpdateCredentialItem(BaseModel):
class UpdateCredentialItem(LiteLLMBaseModel):
credential_name: str
credential_info: Mapping[str, object]
credential_values: Mapping[str, object] | None = None

View file

@ -7,13 +7,13 @@ Canonical definition for ``litellm_usertable``. Re-exported from
from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field, model_validator
from pydantic import ConfigDict, Field, model_validator
from litellm.models.object_permission import LiteLLM_ObjectPermissionTable
from litellm.models.organization_membership import (
LiteLLM_OrganizationMembershipTable,
)
from litellm.types.llms.base import LiteLLMPydanticObjectBase
from litellm.types.llms.base import LiteLLMBaseModel, LiteLLMPydanticObjectBase
class LiteLLM_UserTable(LiteLLMPydanticObjectBase):
@ -71,7 +71,7 @@ class LiteLLM_UserTable(LiteLLMPydanticObjectBase):
return model_name in self.models
class SCIMPlaceholder(BaseModel):
class SCIMPlaceholder(LiteLLMBaseModel):
"""A user row keyed by a value that names another account by SSO identity or email."""
placeholder_user_id: str

View file

@ -12,7 +12,7 @@ from urllib.parse import parse_qsl, urlencode, urlparse, urlunparse
import httpx
from fastapi import APIRouter, Depends, Form, HTTPException, Request
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse, Response
from pydantic import BaseModel, ConfigDict, Field, SecretStr, TypeAdapter, ValidationError
from pydantic import ConfigDict, Field, SecretStr, TypeAdapter, ValidationError
from litellm._logging import verbose_logger
from litellm.caching.in_memory_cache import InMemoryCache
@ -91,6 +91,7 @@ from litellm.proxy.common_utils.encrypt_decrypt_utils import (
encrypt_value_helper,
)
from litellm.proxy.common_utils.http_parsing_utils import _read_request_body
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.mcp import MCPAuth, MCPCredentials
from litellm.types.mcp_server.mcp_server_manager import MCPServer, MCPTokenEndpointAuthMethod
@ -278,7 +279,7 @@ def decode_state_hash(encrypted_state: str) -> dict:
_BRIDGE_AUTH_CODE_PREFIX: Final = "llm_bcode_"
class _BridgeAuthorizationCode(BaseModel):
class _BridgeAuthorizationCode(LiteLLMBaseModel):
"""Authenticated caller and upstream code sealed for bridge or identity-bound per-user OAuth."""
model_config = ConfigDict(frozen=True)
@ -340,7 +341,7 @@ def open_bridge_authorization_code(code: str) -> _BridgeAuthorizationCode | None
_PASSTHROUGH_AUTH_CODE_PREFIX: Final = "llm_ptcode_"
class PassthroughAuthorizationCode(BaseModel):
class PassthroughAuthorizationCode(LiteLLMBaseModel):
"""The ephemeral DCR client and upstream code the gateway seals into the authorization code it
forwards for a client-forwarded-token server (``true_passthrough`` / ``oauth_delegate``) whose
authorize fell through to gateway-side registration. These modes forbid the gateway from storing
@ -1380,7 +1381,7 @@ async def exchange_token_with_server(
return JSONResponse(result, headers=TOKEN_NO_CACHE_HEADERS)
class _DcrClientRegistration(BaseModel):
class _DcrClientRegistration(LiteLLMBaseModel):
"""RFC 7591 dynamic client registration response, narrowed to the fields the gateway
must persist to authenticate later token-endpoint calls. Extra members are ignored."""
@ -1389,7 +1390,7 @@ class _DcrClientRegistration(BaseModel):
token_endpoint_auth_method: str | None = None
class _PersistedDcrCredentials(BaseModel):
class _PersistedDcrCredentials(LiteLLMBaseModel):
dcr_issuer: str | None = None
dcr_server_url: str | None = None
client_id: str | None = None
@ -1784,7 +1785,7 @@ async def _post_dcr_registration(
return response
class EphemeralDcrClient(BaseModel):
class EphemeralDcrClient(LiteLLMBaseModel):
"""A DCR client minted for a single authorize round trip and never stored by the gateway."""
model_config = ConfigDict(frozen=True)

View file

@ -16,7 +16,7 @@ from typing import Final, Literal, NamedTuple, NoReturn, TypeAlias
import httpx
import httpx2
from mcp.types import Tool as MCPTool
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
from typing_extensions import assert_never
from litellm.proxy._experimental.mcp_server.exceptions import (
@ -24,6 +24,7 @@ from litellm.proxy._experimental.mcp_server.exceptions import (
MCPUpstreamAuthError,
)
from litellm.proxy._experimental.mcp_server.faults.traversal import iter_exception_tree
from litellm.types.llms.base import LiteLLMBaseModel
ListFaultCategory: TypeAlias = Literal[
"auth_required",
@ -35,13 +36,13 @@ ListFaultCategory: TypeAlias = Literal[
]
class ServerListOk(BaseModel):
class ServerListOk(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
tag: Literal["ok"] = "ok"
tool_count: int
class ServerListFault(BaseModel):
class ServerListFault(LiteLLMBaseModel):
"""Why a server contributed nothing to a listing: the caller must authenticate upstream
(``auth_required``/``forbidden``), the upstream did not answer (``timeout``/``unreachable``),
the upstream answered outside its contract (``upstream_error``), or the gateway itself failed

View file

@ -9,7 +9,9 @@ from __future__ import annotations
from typing import Final, Literal, TypeAlias
from pydantic import BaseModel, ConfigDict
from pydantic import ConfigDict
from litellm.types.llms.base import LiteLLMBaseModel
MAX_WIRE_FIELD_CHARS: Final = 500
"""Bound on every upstream-derived string that crosses to a caller or into a log line."""
@ -35,7 +37,7 @@ UPSTREAM_FAULT_CODES: Final[frozenset[str]] = frozenset({"server_error", "tempor
they classify as upstream-reported faults and render on the 5xx their meaning implies."""
class CallerRejected(BaseModel):
class CallerRejected(LiteLLMBaseModel):
"""The upstream spoke the OAuth error contract and the failure is actionable by our caller
(e.g. ``invalid_grant``: re-run authorization). The code and its bounded prose relay on the
4xx status the code itself implies."""
@ -47,7 +49,7 @@ class CallerRejected(BaseModel):
error_uri: str | None = None
class GatewayRejected(BaseModel):
class GatewayRejected(LiteLLMBaseModel):
"""The upstream rejected the request for a cause only the gateway operator can address: the
server's stored client credentials or a gateway capability gap. Not actionable by the caller:
rendered as 502 with gateway-authored prose naming the code; the upstream's prose goes to
@ -58,7 +60,7 @@ class GatewayRejected(BaseModel):
code: str
class UpstreamReportedFault(BaseModel):
class UpstreamReportedFault(LiteLLMBaseModel):
"""The upstream blamed itself in the OAuth vocabulary. Rendered on the 5xx the code implies
(``server_error`` 502, ``temporarily_unavailable`` 503) so blame and status agree."""
@ -67,7 +69,7 @@ class UpstreamReportedFault(BaseModel):
code: Literal["server_error", "temporarily_unavailable"]
class UpstreamProtocolFault(BaseModel):
class UpstreamProtocolFault(LiteLLMBaseModel):
"""The upstream broke the error contract: no JSON ``error`` field, an undecodable body, or a
success response without a usable token. Rendered as 502 with a gateway-authored note; the
upstream body never crosses to the caller."""
@ -77,7 +79,7 @@ class UpstreamProtocolFault(BaseModel):
note: str
class UpstreamRegistrationRefused(BaseModel):
class UpstreamRegistrationRefused(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
tag: Literal["upstream_registration_refused"] = "upstream_registration_refused"
status_code: Literal[401, 403]

View file

@ -92,6 +92,7 @@ from litellm.proxy.common_utils.encrypt_decrypt_utils import (
from litellm.proxy.common_utils.html_forms.native_client_consent import (
render_native_client_consent_page,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.mcp_server.mcp_server_manager import MCPServer
_DCR_CLAIMS_TARGET: Final = "mcp_dcr_claims"
@ -172,7 +173,7 @@ credential that LLM routes accept, instead of the MCP-only session pair."""
ProxyCredentialMintFailure = Literal[ReloadUserFailure, "not_a_member", "team_required"]
class MintedProxyCredential(BaseModel):
class MintedProxyCredential(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
key: str = Field(min_length=1)
expires_in: int = Field(gt=0)
@ -216,13 +217,13 @@ SUBJECT_TOKEN_TYPES: Final = frozenset(
)
class SubjectIdentity(BaseModel):
class SubjectIdentity(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
user_id: str = Field(min_length=1)
team_id: str | None = None
class SubjectTokenRefusal(BaseModel):
class SubjectTokenRefusal(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
error: Literal["unsupported_grant_type", "invalid_request", "temporarily_unavailable"]
description: str = Field(min_length=1)
@ -236,7 +237,7 @@ class ExchangeSubjectToken(Protocol):
def __call__(self, subject_token: str, request: Request, /) -> Awaitable[SubjectIdentity | SubjectTokenRefusal]: ...
class ConsentTeam(BaseModel):
class ConsentTeam(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
team_id: str = Field(min_length=1)
team_alias: str | None = None
@ -276,7 +277,7 @@ async def _unreachable_server(user_id: str, server_id: str) -> bool:
return False
class GatewayDcrClient(BaseModel):
class GatewayDcrClient(LiteLLMBaseModel):
"""The registration record sealed into a gateway DCR ``client_id``.
``extra="forbid"`` so a sealed value of another type (an auth code, a connect flow)
@ -289,7 +290,7 @@ class GatewayDcrClient(BaseModel):
iat: int
class _ConnectFlow(BaseModel):
class _ConnectFlow(LiteLLMBaseModel):
"""One in-flight authorize: the SSO user it belongs to and the client parameters
needed to mint the code at the finish step. Sealed into the per-flow cookie. ``jti``
makes the flow single-use at complete; ``extra="forbid"`` rejects cross-type
@ -307,7 +308,7 @@ class _ConnectFlow(BaseModel):
audience: SessionAudience | None = None
class _GatewayAuthCode(BaseModel):
class _GatewayAuthCode(LiteLLMBaseModel):
"""The gateway-sealed authorization code: the user consent it represents and the
bindings the token endpoint must verify (client, redirect URI, PKCE challenge),
plus a ``jti`` for the single-use guard. ``extra="forbid"`` rejects cross-type

View file

@ -48,7 +48,7 @@ from mcp.types import (
ResourceTemplate,
)
from mcp.types import Tool as MCPTool
from pydantic import AnyUrl, BaseModel, TypeAdapter
from pydantic import AnyUrl, BaseModel, Field, TypeAdapter
from typing_extensions import ReadOnly
import litellm
@ -197,6 +197,7 @@ from litellm.proxy.middleware.per_request_root_path_middleware import (
from litellm.proxy.utils import PrismaClient, ProxyLogging
from litellm.repositories.table_repositories import MCPServerRepository
from litellm.types.integrations.slack_alerting import AlertType
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.custom_http import httpxSpecialProvider
from litellm.types.mcp import (
DEFAULT_SUBJECT_TOKEN_TYPE,
@ -223,13 +224,11 @@ try:
validate_tool_name, # pyright: ignore[reportAssignmentType]
)
except ImportError:
from pydantic import BaseModel
SEP_986_URL = "https://github.com/modelcontextprotocol/protocol/blob/main/proposals/0001-tool-name-validation.md"
class _ToolNameValidationResult(BaseModel):
class _ToolNameValidationResult(LiteLLMBaseModel):
is_valid: bool = True
warnings: list = []
warnings: list = Field(default=[])
def validate_tool_name(name: str) -> _ToolNameValidationResult:
return _ToolNameValidationResult()

View file

@ -14,7 +14,7 @@ from datetime import datetime
from functools import lru_cache
from typing import Final, Literal, TypeAlias
from pydantic import BaseModel, ConfigDict, SecretStr
from pydantic import ConfigDict, SecretStr
from litellm.proxy._experimental.mcp_server.outbound_credentials.envelope import (
EnvelopeIdentity,
@ -32,6 +32,7 @@ from litellm.proxy._experimental.mcp_server.outbound_credentials.envelope import
open_envelope,
open_refresh_envelope,
)
from litellm.types.llms.base import LiteLLMBaseModel
_SIGNING_KEY_DOMAIN: Final = b"litellm-mcp-bridge:envelope-signing:"
_ENCRYPTION_KEY_DOMAIN: Final = b"litellm-mcp-bridge:envelope-encryption:"
@ -110,7 +111,7 @@ def build_bridge_refresh_token_response(
return mint_refresh_envelope(identity, refresh, keys, now)
class BridgeRefreshOpened(BaseModel):
class BridgeRefreshOpened(LiteLLMBaseModel):
"""A valid refresh envelope presented to the token endpoint: the identity to re-validate and renew
under, and the upstream refresh grant to exchange."""
@ -120,7 +121,7 @@ class BridgeRefreshOpened(BaseModel):
refresh: RefreshCredential
class BridgeRefreshInvalid(BaseModel):
class BridgeRefreshInvalid(LiteLLMBaseModel):
"""The presented refresh grant is not a valid refresh envelope for this server (not refresh-shaped,
will not open, or minted for a different server); the token endpoint fails the refresh closed."""
@ -158,14 +159,14 @@ def open_bridge_refresh_envelope(
return BridgeRefreshOpened(identity=opened.identity, refresh=opened.refresh)
class NotBridgeEnvelope(BaseModel):
class NotBridgeEnvelope(LiteLLMBaseModel):
"""The bearer is not an envelope; admission continues on its normal path."""
model_config = ConfigDict(frozen=True)
tag: Literal["not_bridge_envelope"] = "not_bridge_envelope"
class BridgeEnvelopeAdmitted(BaseModel):
class BridgeEnvelopeAdmitted(LiteLLMBaseModel):
"""A valid envelope: the identity to admit under and the full upstream ``Authorization``
value (``token_type access_token``) to forward to the upstream MCP server."""
@ -175,7 +176,7 @@ class BridgeEnvelopeAdmitted(BaseModel):
upstream_authorization: SecretStr
class BridgeEnvelopeInvalid(BaseModel):
class BridgeEnvelopeInvalid(LiteLLMBaseModel):
"""The bearer is envelope-shaped but did not open (expired, tampered, wrong key);
admission must fail closed rather than fall through to normal validation."""

View file

@ -35,7 +35,7 @@ from typing import Annotated, Final, Literal
import httpx
import httpx2
from pydantic import BaseModel, ConfigDict, Field, SecretStr, TypeAdapter, ValidationError
from pydantic import ConfigDict, Field, SecretStr, TypeAdapter, ValidationError
from typing_extensions import assert_never
from litellm._logging import verbose_logger
@ -54,9 +54,10 @@ from litellm.proxy._experimental.mcp_server.outbound_credentials.types import (
CredError,
HeaderCarrier,
)
from litellm.types.llms.base import LiteLLMBaseModel
class TokenEndpointSuccess(BaseModel):
class TokenEndpointSuccess(LiteLLMBaseModel):
"""The endpoint returned a JSON object; field validation is the caller's job."""
model_config = ConfigDict(frozen=True)
@ -64,7 +65,7 @@ class TokenEndpointSuccess(BaseModel):
body: dict[str, object]
class TokenEndpointDenied(BaseModel):
class TokenEndpointDenied(LiteLLMBaseModel):
"""The endpoint answered but did not grant a token (an HTTP error or a non-JSON body)."""
model_config = ConfigDict(frozen=True)
@ -73,7 +74,7 @@ class TokenEndpointDenied(BaseModel):
detail: str
class TokenEndpointUnreachable(BaseModel):
class TokenEndpointUnreachable(LiteLLMBaseModel):
"""The endpoint could not be reached (DNS, TLS, connect/read failure)."""
model_config = ConfigDict(frozen=True)

View file

@ -38,9 +38,10 @@ from datetime import datetime, timedelta
from typing import Final, Literal, TypeAlias
import jwt
from pydantic import BaseModel, ConfigDict, Field, SecretStr, ValidationError
from pydantic import ConfigDict, Field, SecretStr, ValidationError
from litellm.proxy.common_utils.encrypt_decrypt_utils import decrypt_value, encrypt_value
from litellm.types.llms.base import LiteLLMBaseModel
ENVELOPE_PREFIX: Final = "llm_env_"
"""Marker prefix on every serialized ACCESS envelope so the edge can cheaply tell an envelope
@ -98,7 +99,7 @@ runs both through the same live-policy gate, so team/org/budget/revocation enfor
identical either way."""
class EnvelopeIdentity(BaseModel):
class EnvelopeIdentity(LiteLLMBaseModel):
"""The litellm principal the envelope binds the inner grant to.
``subject`` is the principal identifier and ``subject_type`` says how to resolve it: a
@ -125,7 +126,7 @@ def user_identity(server_id: str, user_id: str) -> EnvelopeIdentity:
return EnvelopeIdentity(server_id=server_id, subject_type="user_id", subject=user_id)
class UpstreamTokenGrant(BaseModel):
class UpstreamTokenGrant(LiteLLMBaseModel):
"""The upstream OAuth token response fields sealed inside the envelope.
``expires_in`` must be positive when present; a non-positive value is a programmer
@ -141,7 +142,7 @@ class UpstreamTokenGrant(BaseModel):
expires_in: int | None = Field(default=None, gt=0)
class RefreshCredential(BaseModel):
class RefreshCredential(LiteLLMBaseModel):
"""The upstream refresh grant sealed inside a refresh envelope.
Only the refresh token (plus the scope to re-request and the refresh token's own lifetime, when the
@ -156,7 +157,7 @@ class RefreshCredential(BaseModel):
expires_in: int | None = Field(default=None, gt=0)
class EnvelopeKeys(BaseModel):
class EnvelopeKeys(LiteLLMBaseModel):
"""Injected key material: the HS256 signing key and the symmetric encryption key.
``signing_key`` must be at least 32 bytes: HS256's HMAC-SHA256 has a 256-bit
@ -169,7 +170,7 @@ class EnvelopeKeys(BaseModel):
encryption_key: SecretStr = Field(min_length=1)
class SealedEnvelope(BaseModel):
class SealedEnvelope(LiteLLMBaseModel):
"""A minted envelope: the client-held bearer value and when it expires."""
model_config = ConfigDict(frozen=True)
@ -177,7 +178,7 @@ class SealedEnvelope(BaseModel):
expires_at: datetime
class OpenedEnvelope(BaseModel):
class OpenedEnvelope(LiteLLMBaseModel):
"""A validated access envelope: the identity it was minted for and the recovered grant."""
model_config = ConfigDict(frozen=True)
@ -185,7 +186,7 @@ class OpenedEnvelope(BaseModel):
grant: UpstreamTokenGrant
class OpenedRefreshEnvelope(BaseModel):
class OpenedRefreshEnvelope(LiteLLMBaseModel):
"""A validated refresh envelope: the identity it was minted for and the recovered refresh grant."""
model_config = ConfigDict(frozen=True)
@ -193,7 +194,7 @@ class OpenedRefreshEnvelope(BaseModel):
refresh: RefreshCredential
class EnvelopeTooLarge(BaseModel):
class EnvelopeTooLarge(LiteLLMBaseModel):
"""The serialized envelope exceeded ``MAX_ENVELOPE_BYTES``; carries sizes only."""
model_config = ConfigDict(frozen=True)
@ -202,7 +203,7 @@ class EnvelopeTooLarge(BaseModel):
max_bytes: int
class EnvelopeLifetimeUnrepresentable(BaseModel):
class EnvelopeLifetimeUnrepresentable(LiteLLMBaseModel):
"""A positive provider lifetime cannot be represented as a Python datetime."""
model_config = ConfigDict(frozen=True)
@ -213,28 +214,28 @@ class EnvelopeLifetimeUnrepresentable(BaseModel):
EnvelopeMintError: TypeAlias = EnvelopeTooLarge | EnvelopeLifetimeUnrepresentable
class NotAnEnvelope(BaseModel):
class NotAnEnvelope(LiteLLMBaseModel):
"""The candidate does not carry the envelope prefix."""
model_config = ConfigDict(frozen=True)
tag: Literal["not_an_envelope"] = "not_an_envelope"
class BadSignature(BaseModel):
class BadSignature(LiteLLMBaseModel):
"""The JWT signature does not verify under the provided signing key."""
model_config = ConfigDict(frozen=True)
tag: Literal["bad_signature"] = "bad_signature"
class Expired(BaseModel):
class Expired(LiteLLMBaseModel):
"""The envelope's ``exp`` is not in the future relative to the provided ``now``."""
model_config = ConfigDict(frozen=True)
tag: Literal["expired"] = "expired"
class MalformedPayload(BaseModel):
class MalformedPayload(LiteLLMBaseModel):
"""The token is not a well-formed envelope: undecodable JWT, wrong issuer, missing
or mistyped claims, or a decrypted grant that fails validation."""
@ -242,7 +243,7 @@ class MalformedPayload(BaseModel):
tag: Literal["malformed_payload"] = "malformed_payload"
class DecryptFailed(BaseModel):
class DecryptFailed(LiteLLMBaseModel):
"""The signed ``grant`` blob could not be decrypted under the provided key."""
model_config = ConfigDict(frozen=True)
@ -252,7 +253,7 @@ class DecryptFailed(BaseModel):
EnvelopeOpenError: TypeAlias = NotAnEnvelope | BadSignature | Expired | MalformedPayload | DecryptFailed
class _EnvelopeClaims(BaseModel):
class _EnvelopeClaims(LiteLLMBaseModel):
"""Decoded-claims boundary that pins the exact shape :func:`mint_envelope` emits.
``server_id``/``key_hash`` mirror the ``min_length`` constraints of
@ -279,7 +280,7 @@ class _EnvelopeClaims(BaseModel):
grant: str = Field(min_length=1)
class _GrantWire(BaseModel):
class _GrantWire(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
access_token: str
token_type: str
@ -288,7 +289,7 @@ class _GrantWire(BaseModel):
expires_in: int | None = None
class _RefreshWire(BaseModel):
class _RefreshWire(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
refresh_token: str
scope: str | None = None

View file

@ -20,7 +20,7 @@ from datetime import datetime
from functools import lru_cache
from typing import Final, Literal, TypeAlias
from pydantic import BaseModel, ConfigDict, Field, SecretStr, ValidationError
from pydantic import ConfigDict, Field, SecretStr, ValidationError
from litellm.proxy._experimental.mcp_server.outbound_credentials.session_token import (
AsymmetricSessionKeys,
@ -35,6 +35,7 @@ from litellm.proxy._experimental.mcp_server.outbound_credentials.session_token i
open_session_refresh_token,
open_session_token,
)
from litellm.types.llms.base import LiteLLMBaseModel
_SESSION_SIGNING_KEY_DOMAIN: Final = b"litellm-mcp-gateway:session-signing:"
@ -71,7 +72,7 @@ def session_keys_from_master_key(master_key: str) -> SessionKeys:
return SessionKeys(signing_key=SecretStr(signing))
class SessionSigningPreviousKey(BaseModel):
class SessionSigningPreviousKey(LiteLLMBaseModel):
"""One retired key in ``mcp_session_token_signing.previous_public_keys``: its ``kid``
and the PEM public half (inline or an ``os.environ/`` reference)."""
@ -80,7 +81,7 @@ class SessionSigningPreviousKey(BaseModel):
public_key: str = Field(min_length=1)
class MCPSessionTokenSigningSettings(BaseModel):
class MCPSessionTokenSigningSettings(LiteLLMBaseModel):
"""The ``general_settings.mcp_session_token_signing`` block: opt-in asymmetric signing
for the gateway session tokens. Absent, the gateway keeps the backward-compatible
HS256 key derived from ``master_key``. ``private_key`` and each ``public_key`` accept
@ -93,7 +94,7 @@ class MCPSessionTokenSigningSettings(BaseModel):
previous_public_keys: tuple[SessionSigningPreviousKey, ...] = ()
class SessionSigningConfigError(BaseModel):
class SessionSigningConfigError(LiteLLMBaseModel):
"""``mcp_session_token_signing`` is present but unusable (bad shape, unresolvable
secret reference, or a key that is not a loadable RSA PEM); the caller fails closed
with a server error instead of silently falling back to HS256."""
@ -164,14 +165,14 @@ def active_session_signing_keys(master_key: str) -> SessionSigningKeys | Session
return resolve_session_signing_keys(master_key, general_settings.get("mcp_session_token_signing"))
class NotSessionBearer(BaseModel):
class NotSessionBearer(LiteLLMBaseModel):
"""The bearer is not session-shaped; admission continues on its normal path."""
model_config = ConfigDict(frozen=True)
tag: Literal["not_session_bearer"] = "not_session_bearer"
class SessionBearerAdmitted(BaseModel):
class SessionBearerAdmitted(LiteLLMBaseModel):
"""A valid session access token: the principal to admit under after a live reload."""
model_config = ConfigDict(frozen=True)
@ -179,7 +180,7 @@ class SessionBearerAdmitted(BaseModel):
principal: SessionPrincipal
class SessionBearerInvalid(BaseModel):
class SessionBearerInvalid(LiteLLMBaseModel):
"""The bearer is session-shaped but must not admit (expired, tampered, wrong key, or a
refresh token presented at the tool-call edge); admission fails closed with the
``invalid_token`` challenge rather than falling through to another arm. ``expired``
@ -238,7 +239,7 @@ def resolve_session_bearer(
return SessionBearerInvalid(expired=isinstance(opened, SessionExpired))
class SessionRefreshOpened(BaseModel):
class SessionRefreshOpened(LiteLLMBaseModel):
"""A valid session refresh token presented to the token endpoint: the principal to
re-validate and renew under."""
@ -248,7 +249,7 @@ class SessionRefreshOpened(BaseModel):
jti: str
class SessionRefreshInvalid(BaseModel):
class SessionRefreshInvalid(LiteLLMBaseModel):
"""The presented refresh grant is not a valid session refresh token for this client
(not refresh-shaped, will not open, or bound to a different ``client_id``); the token
endpoint fails the refresh closed."""

View file

@ -43,7 +43,9 @@ import jwt
from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from pydantic import BaseModel, ConfigDict, Field, SecretStr, ValidationError, field_validator, model_validator
from pydantic import ConfigDict, Field, SecretStr, ValidationError, field_validator, model_validator
from litellm.types.llms.base import LiteLLMBaseModel
SESSION_TOKEN_PREFIX: Final = "llm_session_"
"""Marker prefix on every serialized session ACCESS token so the admission edge can cheaply
@ -97,7 +99,7 @@ is read only from the signed claims, never from the request, so a token of one a
never be redeemed as the other."""
class SessionPrincipal(BaseModel):
class SessionPrincipal(LiteLLMBaseModel):
"""The litellm user a session token identifies and the DCR client it was issued to.
``user_id`` is the SSO-established litellm user subject, never a credential: admission
@ -121,7 +123,7 @@ class SessionPrincipal(BaseModel):
team_id: str | None = None
class SessionKeys(BaseModel):
class SessionKeys(LiteLLMBaseModel):
"""Injected key material: the HS256 signing key.
``signing_key`` must be at least 32 bytes: HS256's HMAC-SHA256 has a 256-bit security
@ -133,7 +135,7 @@ class SessionKeys(BaseModel):
signing_key: SecretStr = Field(min_length=32)
class SessionRotatedPublicKey(BaseModel):
class SessionRotatedPublicKey(LiteLLMBaseModel):
"""The public half of a retired signing key, kept verifiable under its ``kid`` during a
rotation window so tokens minted before the rotation stay valid until they expire."""
@ -155,7 +157,7 @@ class SessionRotatedPublicKey(BaseModel):
return value
class AsymmetricSessionKeys(BaseModel):
class AsymmetricSessionKeys(LiteLLMBaseModel):
"""Injected RS256 key material: the issuer-held RSA private key and the stable ``kid``
stamped into every minted token's JOSE header, plus the public halves of previously
rotated keys that verification still accepts while their tokens age out. Downstream
@ -212,7 +214,7 @@ def session_public_key_pem(keys: AsymmetricSessionKeys) -> str:
return _public_key_pem_from_private(keys.private_key_pem.get_secret_value())
class MintedSessionToken(BaseModel):
class MintedSessionToken(LiteLLMBaseModel):
"""A minted session token: the client-held bearer value and when it expires."""
model_config = ConfigDict(frozen=True)
@ -220,7 +222,7 @@ class MintedSessionToken(BaseModel):
expires_at: datetime
class OpenedSessionToken(BaseModel):
class OpenedSessionToken(LiteLLMBaseModel):
"""A validated session token of either kind: the principal it was minted for, the
``jti`` so the token endpoint can enforce single-use rotation on a refresh token, and
the signed ``kind``/``iat``/``exp`` so an introspection response can report the
@ -234,7 +236,7 @@ class OpenedSessionToken(BaseModel):
exp: int
class SessionTokenTooLarge(BaseModel):
class SessionTokenTooLarge(LiteLLMBaseModel):
"""The serialized token exceeded ``MAX_SESSION_TOKEN_BYTES``; carries sizes only. Only
reachable through an oversized ``client_id``, which registration should have bounded."""
@ -247,28 +249,28 @@ class SessionTokenTooLarge(BaseModel):
SessionTokenMintError: TypeAlias = SessionTokenTooLarge
class NotASessionToken(BaseModel):
class NotASessionToken(LiteLLMBaseModel):
"""The candidate does not carry the expected session prefix."""
model_config = ConfigDict(frozen=True)
tag: Literal["not_a_session_token"] = "not_a_session_token"
class SessionBadSignature(BaseModel):
class SessionBadSignature(LiteLLMBaseModel):
"""The JWT signature does not verify under the provided signing key."""
model_config = ConfigDict(frozen=True)
tag: Literal["session_bad_signature"] = "session_bad_signature"
class SessionExpired(BaseModel):
class SessionExpired(LiteLLMBaseModel):
"""The token's ``exp`` is not in the future relative to the provided ``now``."""
model_config = ConfigDict(frozen=True)
tag: Literal["session_expired"] = "session_expired"
class SessionMalformed(BaseModel):
class SessionMalformed(LiteLLMBaseModel):
"""The token is not a well-formed session token: undecodable JWT, wrong issuer, wrong
``kind``, or missing/mistyped/extra claims."""
@ -279,7 +281,7 @@ class SessionMalformed(BaseModel):
SessionTokenOpenError: TypeAlias = NotASessionToken | SessionBadSignature | SessionExpired | SessionMalformed
class _SessionClaims(BaseModel):
class _SessionClaims(LiteLLMBaseModel):
"""Decoded-claims boundary that pins the exact shape the mints emit.
``user_id``/``client_id`` mirror the ``min_length`` constraints of
@ -469,7 +471,7 @@ def _open(
)
class _VerificationMaterial(BaseModel):
class _VerificationMaterial(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
key: SecretStr
algorithm: Literal["HS256", "RS256"]

View file

@ -23,11 +23,12 @@ from datetime import datetime, timezone
from typing import TYPE_CHECKING, Final, Protocol
import jwt
from pydantic import BaseModel, ConfigDict, SecretStr, TypeAdapter, ValidationError
from pydantic import ConfigDict, SecretStr, TypeAdapter, ValidationError
from litellm._logging import verbose_proxy_logger
from litellm.caching.in_memory_cache import InMemoryCache
from litellm.constants import MCP_OAUTH2_TOKEN_CACHE_MAX_SIZE, MCP_SSO_ASSERTION_CACHE_TTL_SECONDS
from litellm.types.llms.base import LiteLLMBaseModel
if TYPE_CHECKING:
from prisma.models import LiteLLM_SSOIdentityAssertion
@ -67,7 +68,7 @@ def _mcp_server_table(prisma_client: PrismaClient) -> _MCPServerTable:
return prisma_client.db.litellm_mcpservertable
class SSOIdentityAssertion(BaseModel):
class SSOIdentityAssertion(LiteLLMBaseModel):
"""The IdP material an EMA exchange needs: ``id_token`` is the RFC 8693 subject token,
``expires_at`` bounds its usefulness, and the refresh token renews it without re-login."""
@ -119,12 +120,12 @@ class SSOAssertionCache:
_ASSERTION_CACHE: Final = SSOAssertionCache()
class _IdTokenClaims(BaseModel):
class _IdTokenClaims(LiteLLMBaseModel):
exp: float | None = None
iss: str | None = None
class _StoredAssertionPayload(BaseModel):
class _StoredAssertionPayload(LiteLLMBaseModel):
id_token: str
refresh_token: str | None = None
issuer: str | None = None

View file

@ -24,7 +24,7 @@ from typing import Final
import httpx
import jwt
from pydantic import BaseModel, TypeAdapter, ValidationError
from pydantic import TypeAdapter, ValidationError
from typing_extensions import assert_never
from litellm._logging import verbose_proxy_logger
@ -50,6 +50,7 @@ from litellm.proxy._experimental.mcp_server.outbound_credentials.types import (
CredError,
PrivateKeyJwtAuth,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.custom_http import httpxSpecialProvider
# The cache stores (fingerprint, token); anything else in the slot is treated as absent.
@ -65,7 +66,7 @@ class ExchangedToken:
expires_in: int | None
class _TokenEndpointResponse(BaseModel):
class _TokenEndpointResponse(LiteLLMBaseModel):
access_token: str
expires_in: int | None = None

View file

@ -32,7 +32,7 @@ from typing import Annotated, Final, Literal
import httpx2
from expression import case, tag, tagged_union
from pydantic import BaseModel, ConfigDict, Field, SecretStr, field_validator
from pydantic import ConfigDict, Field, SecretStr, field_validator
from typing_extensions import assert_never
from litellm.proxy._experimental.mcp_server.outbound_credentials.result import (
@ -40,6 +40,7 @@ from litellm.proxy._experimental.mcp_server.outbound_credentials.result import (
Ok,
Result,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.mcp import (
DEFAULT_CREDENTIAL_HEADER,
DEFAULT_SUBJECT_TOKEN_TYPE,
@ -213,7 +214,7 @@ def validate_header_name(raw: str) -> Result[str, CredError]:
return Ok(normalized)
class HeaderCarrier(BaseModel):
class HeaderCarrier(LiteLLMBaseModel):
"""Where a resolved credential is written upstream, and how its value is formatted.
``Authorization: Bearer`` is only OAuth's *default* conveyance (RFC 6750 section 2.1), not its
@ -319,7 +320,7 @@ class TokenExchangeConfig(HeaderCarrier):
scopes: tuple[str, ...] = ()
class PrivateKeyJwtAuth(BaseModel):
class PrivateKeyJwtAuth(LiteLLMBaseModel):
"""RFC 7523 private-key-JWT client authentication: the gateway signs a `client_assertion`."""
model_config = ConfigDict(frozen=True)
@ -329,7 +330,7 @@ class PrivateKeyJwtAuth(BaseModel):
signing_alg: str = "RS256"
class ClientSecretAuth(BaseModel):
class ClientSecretAuth(LiteLLMBaseModel):
"""`client_secret_post` client authentication: the gateway posts `client_id` + `client_secret`."""
model_config = ConfigDict(frozen=True)
@ -362,7 +363,7 @@ class IdJagConfig(HeaderCarrier):
scopes: tuple[str, ...] = ()
class SharedKey(BaseModel):
class SharedKey(LiteLLMBaseModel):
"""A fixed key configured on the server, identical for every caller."""
model_config = ConfigDict(frozen=True)
@ -370,7 +371,7 @@ class SharedKey(BaseModel):
value: SecretStr
class Byok(BaseModel):
class Byok(LiteLLMBaseModel):
"""A key the user brings via the entry flow, stored per-user and pulled from the credential
store at resolve time. Missing means the user must provide it, a 401 + WWW-Authenticate
challenge."""
@ -393,21 +394,21 @@ class ApiKeyConfig(HeaderCarrier):
key_source: ApiKeySource
class PassthroughConfig(BaseModel):
class PassthroughConfig(LiteLLMBaseModel):
"""Client-driven upstream OAuth; the gateway forwards the client's upstream token."""
model_config = ConfigDict(frozen=True)
kind: Literal[AuthSpecKind.passthrough] = AuthSpecKind.passthrough
class NoneConfig(BaseModel):
class NoneConfig(LiteLLMBaseModel):
"""No upstream credential; the request is sent unauthenticated."""
model_config = ConfigDict(frozen=True)
kind: Literal[AuthSpecKind.none] = AuthSpecKind.none
class StaticKeys(BaseModel):
class StaticKeys(LiteLLMBaseModel):
"""Long-lived AWS access keys configured on the server."""
model_config = ConfigDict(frozen=True)
@ -417,7 +418,7 @@ class StaticKeys(BaseModel):
session_token: SecretStr | None = None
class AssumeRole(BaseModel):
class AssumeRole(LiteLLMBaseModel):
"""An IAM role the gateway assumes via STS for short-lived, auto-refreshed credentials."""
model_config = ConfigDict(frozen=True)
@ -427,7 +428,7 @@ class AssumeRole(BaseModel):
external_id: str | None = None
class Ambient(BaseModel):
class Ambient(LiteLLMBaseModel):
"""The environment's default AWS credential chain (instance profile, IRSA, env vars)."""
model_config = ConfigDict(frozen=True)
@ -437,7 +438,7 @@ class Ambient(BaseModel):
AwsCredentialSource = Annotated[StaticKeys | AssumeRole | Ambient, Field(discriminator="source")]
class AwsSigV4Config(BaseModel):
class AwsSigV4Config(LiteLLMBaseModel):
"""AWS SigV4 per-request signing for an AWS-hosted upstream (e.g. Bedrock AgentCore). The
gateway signs with its own AWS identity, never the caller's; `credentials` selects how that
identity is obtained, defaulting to the ambient credential chain."""
@ -462,7 +463,7 @@ AuthConfig = Annotated[
]
class Subject(BaseModel):
class Subject(LiteLLMBaseModel):
"""The validated inbound principal. NOT the v1 request object and NOT the LiteLLM key."""
model_config = ConfigDict(frozen=True)
@ -474,7 +475,7 @@ class Subject(BaseModel):
inbound_token: SecretStr | None = None
class ServerSpec(BaseModel):
class ServerSpec(LiteLLMBaseModel):
"""The declared upstream. A v2-native type; the v1 -> v2 adapter maps onto this."""
model_config = ConfigDict(frozen=True)

View file

@ -38,6 +38,7 @@ from litellm.types.integrations.otel_span_attributes import (
SpanAttributes as SpanAttributes, # noqa: PLC0414 # public re-export
)
from litellm.types.integrations.slack_alerting import AlertType
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.llms.openai import (
AllMessageValues,
ResponsesAPIResponse,
@ -2599,7 +2600,7 @@ class CallbackDelete(LiteLLMPydanticObjectBase):
callback_name: str
class FieldDetail(BaseModel):
class FieldDetail(LiteLLMBaseModel):
field_name: str
field_type: str
field_description: str
@ -3834,7 +3835,7 @@ class LiteLLM_ProjectTableCachedObj(LiteLLM_ProjectTable):
last_refreshed_at: float | None = None
class LiteLLM_UserTableFiltered(BaseModel): # done to avoid exposing sensitive data
class LiteLLM_UserTableFiltered(LiteLLMBaseModel): # done to avoid exposing sensitive data
user_id: str
user_email: str | None = None
@ -4750,14 +4751,14 @@ class TeamMemberUpdateResponse(MemberUpdateResponse):
temp_budget_expiry: datetime | None = None
class TeamModelAddRequest(BaseModel):
class TeamModelAddRequest(LiteLLMBaseModel):
"""Request to add models to a team"""
team_id: str
models: list[str]
class TeamModelDeleteRequest(BaseModel):
class TeamModelDeleteRequest(LiteLLMBaseModel):
"""Request to delete models from a team"""
team_id: str
@ -4812,20 +4813,20 @@ class TeamInfoMember(Member):
user_alias: str | None = None
class TeamEditUnrestricted(BaseModel):
class TeamEditUnrestricted(LiteLLMBaseModel):
kind: Literal["unrestricted"] = "unrestricted"
class TeamEditAsTeamAdmin(BaseModel):
class TeamEditAsTeamAdmin(LiteLLMBaseModel):
kind: Literal["team_admin"] = "team_admin"
editable_fields: tuple[str, ...]
class TeamEditAsTeamAdminDisabled(BaseModel):
class TeamEditAsTeamAdminDisabled(LiteLLMBaseModel):
kind: Literal["team_admin_disabled"] = "team_admin_disabled"
class TeamEditNone(BaseModel):
class TeamEditNone(LiteLLMBaseModel):
kind: Literal["none"] = "none"
@ -4864,7 +4865,7 @@ class TeamInfoResponseObject(TypedDict):
team_memberships: ReadOnly[tuple[TeamInfoMembership, ...]]
class TeamMemberResetBudgetResponse(BaseModel):
class TeamMemberResetBudgetResponse(LiteLLMBaseModel):
team_id: str
user_id: str
budget_id: str | None
@ -5150,12 +5151,12 @@ class RoleBasedPermissions(OIDCPermissions):
}
class RoleMapping(BaseModel):
class RoleMapping(LiteLLMBaseModel):
role: str
internal_role: RBAC_ROLES
class JWTLiteLLMRoleMap(BaseModel):
class JWTLiteLLMRoleMap(LiteLLMBaseModel):
jwt_role: str
litellm_role: LitellmUserRoles
@ -5168,7 +5169,7 @@ class ScopeMapping(OIDCPermissions):
}
class JWTRoutingOverride(BaseModel):
class JWTRoutingOverride(LiteLLMBaseModel):
"""
Override default auth routing for JWT-shaped bearer tokens.
@ -5187,9 +5188,7 @@ class JWTRoutingOverride(BaseModel):
aud: str | list[str] | None = None
path: Literal["oauth2"] = "oauth2"
model_config = {
"extra": "forbid",
}
model_config = ConfigDict(extra="forbid")
class UnregisteredJWTClientBehavior(str, enum.Enum):
@ -5211,7 +5210,7 @@ class UnregisteredJWTClientBehavior(str, enum.Enum):
AUTO_REGISTER = "auto_register"
class JWTIssuerConfig(BaseModel):
class JWTIssuerConfig(LiteLLMBaseModel):
"""
Issuer-bound JWT validation configuration.
@ -5268,9 +5267,7 @@ class JWTIssuerConfig(BaseModel):
description="Issuer-specific policy when the virtual key claim has no mapping. Falls back to the global policy.",
)
model_config = {
"extra": "forbid",
}
model_config = ConfigDict(extra="forbid")
@model_validator(mode="after")
def validate_audience_configured(self) -> "JWTIssuerConfig":
@ -5567,7 +5564,7 @@ class SpecialManagementEndpointEnums(enum.Enum):
DEFAULT_ORGANIZATION = "default_organization"
class TransformRequestBody(BaseModel):
class TransformRequestBody(LiteLLMBaseModel):
call_type: CallTypes
request_body: dict

View file

@ -13,7 +13,7 @@ from typing import Any, Final
from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field
from pydantic import Field
from litellm._logging import verbose_proxy_logger
from litellm.proxy._types import LitellmUserRoles, UserAPIKeyAuth
@ -24,11 +24,12 @@ from litellm.proxy.a2a.discovery import (
fetch_well_known_card,
)
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.types.llms.base import LiteLLMBaseModel
router: Final = APIRouter()
class DiscoverAgentRequest(BaseModel):
class DiscoverAgentRequest(LiteLLMBaseModel):
url: str = Field(
...,
description=(
@ -58,7 +59,7 @@ class DiscoverAgentRequest(BaseModel):
)
class DiscoverAgentResponse(BaseModel):
class DiscoverAgentResponse(LiteLLMBaseModel):
url: str
agent_card: dict[str, Any]

View file

@ -6,7 +6,7 @@ from collections.abc import Sequence
from dataclasses import dataclass
from typing import TYPE_CHECKING, Final, TypeAlias
from pydantic import BaseModel, ConfigDict, ValidationError
from pydantic import ConfigDict, ValidationError
from litellm.proxy.common_utils.semantic_text_index import (
Embedder,
@ -15,6 +15,7 @@ from litellm.proxy.common_utils.semantic_text_index import (
router_embedder,
)
from litellm.types.agents import AgentResponse
from litellm.types.llms.base import LiteLLMBaseModel
if TYPE_CHECKING:
from litellm.proxy._types import UserAPIKeyAuth
@ -48,7 +49,7 @@ class AgentSearchEmbeddingFailed:
AgentSearchOutcome: TypeAlias = AgentSearchHits | AgentSearchNotConfigured | AgentSearchEmbeddingFailed
class _SearchableSkill(BaseModel):
class _SearchableSkill(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
name: str = ""
@ -56,14 +57,14 @@ class _SearchableSkill(BaseModel):
tags: tuple[str, ...] = ()
class _SearchableCard(BaseModel):
class _SearchableCard(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
description: str = ""
skills: tuple[_SearchableSkill, ...] = ()
class AgentSearchResult(BaseModel):
class AgentSearchResult(LiteLLMBaseModel):
model_config = ConfigDict(frozen=True)
agent_id: str

View file

@ -4,9 +4,10 @@ from collections.abc import Sequence
from datetime import datetime
from typing import Final, Protocol
from pydantic import BaseModel, TypeAdapter
from pydantic import TypeAdapter
from litellm.proxy._types import LiteLLMRoutes
from litellm.types.llms.base import LiteLLMBaseModel
UNKNOWN_CALL_TYPE: Final = "Unknown"
INFO_ROUTES_JSON: Final = json.dumps(LiteLLMRoutes.info_routes.value)
@ -25,7 +26,7 @@ class _SupportsRawQueryDb(Protocol):
def db(self) -> _SupportsQueryRaw: ...
class CacheActivityGroup(BaseModel):
class CacheActivityGroup(LiteLLMBaseModel):
call_type: str
api_requests: int
cache_hits: int
@ -34,7 +35,7 @@ class CacheActivityGroup(BaseModel):
generated_completion_tokens: int
class CacheActivityTotals(BaseModel):
class CacheActivityTotals(LiteLLMBaseModel):
api_requests: int
cache_hits: int
failed_requests: int
@ -42,19 +43,19 @@ class CacheActivityTotals(BaseModel):
cache_hit_ratio: float
class CacheActivityFilterOptions(BaseModel):
class CacheActivityFilterOptions(LiteLLMBaseModel):
key_aliases: list[str]
models: list[str]
class CacheActivityErrorBucket(BaseModel):
class CacheActivityErrorBucket(LiteLLMBaseModel):
call_type: str
error_code: str
error_class: str
count: int
class CacheActivityResponse(BaseModel):
class CacheActivityResponse(LiteLLMBaseModel):
groups: list[CacheActivityGroup]
totals: CacheActivityTotals
filter_options: CacheActivityFilterOptions
@ -131,11 +132,11 @@ MODEL_OPTIONS_SQL: Final = """
"""
class _KeyAliasRow(BaseModel):
class _KeyAliasRow(LiteLLMBaseModel):
key_alias: str
class _ModelRow(BaseModel):
class _ModelRow(LiteLLMBaseModel):
model: str

View file

@ -24,7 +24,7 @@ from typing import Final
from fastapi import APIRouter, Depends, Request, Response
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field, TypeAdapter, ValidationError
from pydantic import Field, TypeAdapter, ValidationError
from litellm._internal_context import with_service_target
from litellm._logging import verbose_proxy_logger
@ -40,6 +40,7 @@ from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.proxy.common_utils.http_parsing_utils import _safe_set_request_parsed_body
from litellm.proxy.management_endpoints.sso_helper_utils import CLI_SSO_SESSIONS_TARGET
from litellm.proxy.management_endpoints.ui_sso import CliSsoTeamDetail
from litellm.types.llms.base import LiteLLMBaseModel
GATEWAY_PREFIX: Final = "/claude_code_gateway"
_DEVICE_CODE_GRANT: Final = "urn:ietf:params:oauth:grant-type:device_code"
@ -52,7 +53,7 @@ _NO_SETTINGS: Final = MappingProxyType({})
_POST_ONLY: Final = ["POST"]
class _GatewaySessionData(BaseModel):
class _GatewaySessionData(LiteLLMBaseModel):
user_id: str
user_role: LitellmUserRoles
models: list[str] = Field(default_factory=list)
@ -67,19 +68,19 @@ class _GatewayLogin:
team: CliSsoTeamDetail
class _OAuthErrorBody(BaseModel):
class _OAuthErrorBody(LiteLLMBaseModel):
error: str
error_description: str | None = None
class _AuthorizationServerMetadata(BaseModel):
class _AuthorizationServerMetadata(LiteLLMBaseModel):
issuer: str
device_authorization_endpoint: str
token_endpoint: str
grant_types_supported: tuple[str, ...]
class _DeviceAuthorizationBody(BaseModel):
class _DeviceAuthorizationBody(LiteLLMBaseModel):
device_code: str
user_code: str
verification_uri: str
@ -88,13 +89,13 @@ class _DeviceAuthorizationBody(BaseModel):
interval: int
class _AccessTokenBody(BaseModel):
class _AccessTokenBody(LiteLLMBaseModel):
access_token: str
expires_in: int
token_type: str = "Bearer"
class _ManagedSettingsBody(BaseModel):
class _ManagedSettingsBody(LiteLLMBaseModel):
uuid: str
checksum: str
settings: dict[str, object]

View file

@ -35,7 +35,7 @@ from collections.abc import Callable, Mapping
from dataclasses import dataclass
from typing import Final
from pydantic import BaseModel, ValidationError
from pydantic import ValidationError
from litellm._logging import verbose_proxy_logger
from litellm.proxy._types import UserAPIKeyAuth
@ -43,13 +43,14 @@ from litellm.proxy.auth.auth_checks import (
_is_model_cost_zero, # pyright: ignore[reportPrivateUsage] # the zero-cost predicate the auth-time budget checks use; no public equivalent
)
from litellm.router import Router
from litellm.types.llms.base import LiteLLMBaseModel
class _RequestMetadata(BaseModel):
class _RequestMetadata(LiteLLMBaseModel):
user_api_key_auth: UserAPIKeyAuth | None = None
class _FallbackBudgetSettings(BaseModel):
class _FallbackBudgetSettings(LiteLLMBaseModel):
enforce_fallback_budget: bool = True

View file

@ -12,19 +12,20 @@ from collections.abc import Callable, Mapping
from dataclasses import dataclass
from typing import Final
from pydantic import BaseModel, ValidationError
from pydantic import ValidationError
from litellm._logging import verbose_proxy_logger
from litellm.proxy._types import ProxyException, UserAPIKeyAuth
from litellm.proxy.auth.auth_checks import can_key_call_resolved_model
from litellm.router import Router
from litellm.types.llms.base import LiteLLMBaseModel
class _RequestMetadata(BaseModel):
class _RequestMetadata(LiteLLMBaseModel):
user_api_key_auth: UserAPIKeyAuth | None = None
class _FallbackAccessSettings(BaseModel):
class _FallbackAccessSettings(LiteLLMBaseModel):
enforce_fallback_model_access: bool = False

View file

@ -5,20 +5,21 @@ from collections.abc import Sequence
from typing import Any, Final
from fastapi import Request
from pydantic import BaseModel, Field
from pydantic import Field
from litellm._logging import verbose_proxy_logger
from litellm.types.llms.base import LiteLLMBaseModel
TrustedProxyNetwork = ipaddress.IPv4Network | ipaddress.IPv6Network
class NetworkContext(BaseModel):
class NetworkContext(LiteLLMBaseModel):
client_ip: str | None = None
host: str | None = None
via_trusted_proxy: bool = False
class TrustedProxyConfig(BaseModel):
class TrustedProxyConfig(LiteLLMBaseModel):
use_forwarded_for: bool = False
trusted_proxy_cidrs: Sequence[str] = Field(default_factory=tuple)

View file

@ -14,7 +14,7 @@ from types import MappingProxyType
from typing import TYPE_CHECKING, Final, NoReturn, Protocol, TypeAlias
from fastapi import HTTPException, status
from pydantic import BaseModel, ValidationError
from pydantic import ValidationError
from pydantic.main import IncEx
from typing_extensions import assert_never
@ -32,6 +32,7 @@ from litellm.proxy.auth.auth_checks import (
get_team_object,
get_user_object,
)
from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.proxy.auth.auth_checks import UserNotFoundError
if TYPE_CHECKING:
@ -133,7 +134,7 @@ GrantOutcome: TypeAlias = ResolvedGrants | GrantDenial | LookupDegraded
_MODELS_COLUMN: Final[Mapping[str, IncEx | bool]] = MappingProxyType({"models": True})
class _UserModelColumn(BaseModel):
class _UserModelColumn(LiteLLMBaseModel):
"""``LiteLLM_UserTable.models`` is a bare ``list``; re-read it with the shape a token's ``models`` takes."""
models: tuple[str, ...] = ()

View file

@ -2,12 +2,13 @@ from __future__ import annotations
from enum import Enum
from pydantic import BaseModel, ConfigDict, Field
from pydantic import ConfigDict, Field
from litellm.proxy._types import UserAPIKeyAuth
from litellm.proxy.auth.auth_method import AuthMethod
from litellm.proxy.auth.network import NetworkContext
from litellm.proxy.auth.roles import Role, TeamRole
from litellm.types.llms.base import LiteLLMBaseModel
class PrincipalType(str, Enum):
@ -15,7 +16,7 @@ class PrincipalType(str, Enum):
SERVICE_ACCOUNT = "service_account"
class UserIdentity(BaseModel):
class UserIdentity(LiteLLMBaseModel):
id: str
external_id: str | None = None
user_name: str | None = None
@ -23,32 +24,32 @@ class UserIdentity(BaseModel):
display_name: str | None = None
class OrganizationIdentity(BaseModel):
class OrganizationIdentity(LiteLLMBaseModel):
id: str
name: str | None = None
class TeamIdentity(BaseModel):
class TeamIdentity(LiteLLMBaseModel):
id: str
name: str | None = None
role: TeamRole = TeamRole.MEMBER
class ProjectIdentity(BaseModel):
class ProjectIdentity(LiteLLMBaseModel):
id: str
name: str | None = None
class EndUserIdentity(BaseModel):
class EndUserIdentity(LiteLLMBaseModel):
id: str
class CredentialRef(BaseModel):
class CredentialRef(LiteLLMBaseModel):
key_id: str | None = None
token_id: str | None = None
class Principal(BaseModel):
class Principal(LiteLLMBaseModel):
"""Normalized caller identity, resolved once per request at the auth seam.
Frozen and constructed fresh per request, never cached or shared. The identity

Some files were not shown because too many files have changed in this diff Show more