mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
refactor: move hidden params helpers to core utils
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
03752c17f9
commit
b46587cb35
16 changed files with 144 additions and 83 deletions
|
|
@ -29,13 +29,13 @@ from litellm._logging import print_verbose, verbose_logger
|
|||
from litellm.caching import InMemoryCache
|
||||
from litellm.caching.caching import S3Cache, response_cache_phase
|
||||
from litellm.constants import CACHE_WRITE_SHUTDOWN_FLUSH_TIMEOUT_SECONDS
|
||||
from litellm.litellm_core_utils.hidden_params import get_hidden_params
|
||||
from litellm.litellm_core_utils.llm_response_utils.response_metadata import (
|
||||
update_response_metadata,
|
||||
)
|
||||
from litellm.litellm_core_utils.logging_utils import (
|
||||
_assemble_complete_response_from_streaming_chunks,
|
||||
)
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_hidden_params
|
||||
from litellm.types.caching import EMBEDDING_CACHE_FORMAT_VERSION, CachedEmbedding
|
||||
from litellm.types.integrations.custom_logger import converted_stream_requested
|
||||
from litellm.types.llms.openai import ResponsesAPIResponse
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from pydantic import BaseModel
|
|||
import litellm
|
||||
from litellm import ModelResponse
|
||||
from litellm._logging import verbose_logger
|
||||
from litellm.litellm_core_utils.hidden_params import get_or_create_hidden_params
|
||||
from litellm.litellm_core_utils.prompt_templates.common_utils import (
|
||||
responses_reasoning_items_from_thinking_blocks,
|
||||
)
|
||||
|
|
@ -37,7 +38,6 @@ from litellm.responses.sse_output_recovery import (
|
|||
record_output_text_chunk,
|
||||
)
|
||||
from litellm.responses.utils import ResponsesAPIRequestUtils, normalize_responses_api_stream_options
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_or_create_hidden_params
|
||||
from litellm.types.llms.openai import (
|
||||
ChatCompletionAnnotation,
|
||||
ChatCompletionReasoningItem,
|
||||
|
|
|
|||
27
litellm/litellm_core_utils/hidden_params.py
Normal file
27
litellm/litellm_core_utils/hidden_params.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
from typing import Final
|
||||
|
||||
_HIDDEN_PARAMS_ATTR: Final = "_hidden_params"
|
||||
HIDDEN_PARAMS_ATTR: Final = _HIDDEN_PARAMS_ATTR
|
||||
|
||||
|
||||
def get_hidden_params(obj: object) -> dict[str, object] | None:
|
||||
hidden_params: Final = (
|
||||
obj.get(_HIDDEN_PARAMS_ATTR) if isinstance(obj, dict) else getattr(obj, _HIDDEN_PARAMS_ATTR, None)
|
||||
)
|
||||
return hidden_params if isinstance(hidden_params, dict) else None
|
||||
|
||||
|
||||
def set_hidden_params(obj: object, hidden_params: dict[str, object]) -> None:
|
||||
if isinstance(obj, dict):
|
||||
obj[_HIDDEN_PARAMS_ATTR] = hidden_params
|
||||
else:
|
||||
setattr(obj, _HIDDEN_PARAMS_ATTR, hidden_params)
|
||||
|
||||
|
||||
def get_or_create_hidden_params(obj: object) -> dict[str, object]:
|
||||
hidden_params: Final = get_hidden_params(obj)
|
||||
if hidden_params is not None:
|
||||
return hidden_params
|
||||
created_hidden_params: Final[dict[str, object]] = {}
|
||||
set_hidden_params(obj, created_hidden_params)
|
||||
return created_hidden_params
|
||||
|
|
@ -8,11 +8,11 @@ from typing import TYPE_CHECKING, Any, Final, Literal, TypeAlias, TypeVar, cast
|
|||
from pydantic import JsonValue, TypeAdapter
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.hidden_params import get_hidden_params
|
||||
from litellm.llms.anthropic.pass_through.utils import (
|
||||
is_reasoning_auto_summary_enabled,
|
||||
prompt_cache_key_from_user_id,
|
||||
)
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_hidden_params
|
||||
|
||||
# OpenAI has a 64-character limit for function/tool names
|
||||
# Anthropic does not have this limit, so we need to truncate long names
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@ import httpx
|
|||
from typing_extensions import ReadOnly
|
||||
|
||||
from litellm._logging import verbose_logger
|
||||
from litellm.litellm_core_utils.hidden_params import get_or_create_hidden_params
|
||||
from litellm.litellm_core_utils.url_utils import encode_url_path_segment
|
||||
from litellm.llms.azure_ai.agents.transformation import (
|
||||
AzureAIAgentsConfig,
|
||||
AzureAIAgentsError,
|
||||
)
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_or_create_hidden_params
|
||||
from litellm.types.llms.openai import (
|
||||
ChatCompletionAnnotation,
|
||||
ChatCompletionAnnotationURLCitation,
|
||||
|
|
|
|||
|
|
@ -72,13 +72,14 @@ class AzureModelRouterConfig(AzureAIStudioConfig):
|
|||
Also stamps that model onto ``_hidden_params`` so downstream consumers (spend logs,
|
||||
response restamping) can read it instead of guessing the route from the model string.
|
||||
"""
|
||||
from litellm.litellm_core_utils.hidden_params import (
|
||||
get_hidden_params,
|
||||
set_hidden_params,
|
||||
)
|
||||
from litellm.llms.azure_ai.common_utils import (
|
||||
AZURE_MODEL_ROUTER_SELECTED_MODEL_KEY,
|
||||
AzureFoundryModelInfo,
|
||||
)
|
||||
from litellm.router_utils.add_retry_fallback_headers import (
|
||||
get_hidden_params_dict,
|
||||
)
|
||||
|
||||
# Get base model for the parent call (strips routing prefixes for API compatibility)
|
||||
base_model: Final[str] = AzureFoundryModelInfo.get_base_model(model)
|
||||
|
|
@ -100,12 +101,14 @@ class AzureModelRouterConfig(AzureAIStudioConfig):
|
|||
)
|
||||
selected_model: Final = transformed_response.model
|
||||
if selected_model:
|
||||
# Rebuilt rather than mutated in place: ModelResponseBase declares _hidden_params as a
|
||||
# class-level dict, so an in-place write can bleed into unrelated responses.
|
||||
transformed_response._hidden_params = { # pyright: ignore[reportPrivateUsage] # ModelResponse exposes no public hidden-params setter
|
||||
**get_hidden_params_dict(transformed_response),
|
||||
AZURE_MODEL_ROUTER_SELECTED_MODEL_KEY: selected_model,
|
||||
}
|
||||
transformed_hidden_params: Final = get_hidden_params(transformed_response) or {}
|
||||
set_hidden_params(
|
||||
transformed_response,
|
||||
{
|
||||
**transformed_hidden_params,
|
||||
AZURE_MODEL_ROUTER_SELECTED_MODEL_KEY: selected_model,
|
||||
},
|
||||
)
|
||||
return transformed_response
|
||||
|
||||
def calculate_additional_costs(self, model: str, prompt_tokens: int, completion_tokens: int) -> dict | None:
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ import httpx
|
|||
from typing_extensions import ReadOnly, TypedDict
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.hidden_params import get_or_create_hidden_params
|
||||
from litellm.litellm_core_utils.llm_cost_calc.tool_call_cost_tracking import (
|
||||
StandardBuiltInToolCostTracking,
|
||||
)
|
||||
from litellm.litellm_core_utils.url_utils import encode_url_path_segment
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_or_create_hidden_params
|
||||
from litellm.secret_managers.main import get_secret_str
|
||||
from litellm.types.containers.main import (
|
||||
ContainerCreateOptionalRequestParams,
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ from typing import Any, Final, cast
|
|||
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
from litellm._uuid import uuid as uuid_module
|
||||
from litellm.litellm_core_utils.hidden_params import get_or_create_hidden_params
|
||||
from litellm.llms.base_llm.files.storage_backend import BaseFileStorageBackend
|
||||
from litellm.llms.base_llm.files.storage_backend_factory import get_storage_backend
|
||||
from litellm.llms.base_llm.files.transformation import BaseFileEndpoints
|
||||
from litellm.proxy._types import ProxyException, UserAPIKeyAuth
|
||||
from litellm.proxy.utils import PrismaClient, ProxyLogging
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_or_create_hidden_params
|
||||
from litellm.types.llms.openai import OpenAIFileObject, OpenAIFilesPurpose
|
||||
from litellm.types.utils import ExtractedFileData, SpecialEnums
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import httpx
|
|||
|
||||
import litellm
|
||||
from litellm import stream_chunk_builder
|
||||
from litellm.litellm_core_utils.hidden_params import get_or_create_hidden_params
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
|
||||
from litellm.litellm_core_utils.litellm_logging import (
|
||||
get_standard_logging_object_payload,
|
||||
|
|
@ -17,7 +18,6 @@ from litellm.llms.cohere.common_utils import (
|
|||
)
|
||||
from litellm.llms.cohere.embed.v1_transformation import CohereEmbeddingConfig
|
||||
from litellm.proxy._types import PassThroughEndpointLoggingTypedDict
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_or_create_hidden_params
|
||||
from litellm.types.passthrough_endpoints.pass_through_endpoints import (
|
||||
PassthroughStandardLoggingPayload,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import httpx
|
|||
|
||||
import litellm
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
from litellm.litellm_core_utils.hidden_params import get_hidden_params, get_or_create_hidden_params
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
|
||||
from litellm.litellm_core_utils.litellm_logging import (
|
||||
get_standard_logging_object_payload,
|
||||
|
|
@ -28,7 +29,6 @@ from litellm.proxy.pass_through_endpoints.llm_provider_handlers.base_passthrough
|
|||
from litellm.proxy.pass_through_endpoints.success_handler import (
|
||||
PassThroughEndpointLogging,
|
||||
)
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_hidden_params, get_or_create_hidden_params
|
||||
from litellm.types.llms.openai import ResponsesAPIResponse
|
||||
from litellm.types.passthrough_endpoints.pass_through_endpoints import (
|
||||
EndpointType,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from collections.abc import Sequence
|
|||
from typing import Any, Final, cast
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.hidden_params import get_or_create_hidden_params
|
||||
from litellm.main import stream_chunk_builder
|
||||
from litellm.responses.litellm_completion_transformation.custom_tools import (
|
||||
build_tool_call_item_kwargs,
|
||||
|
|
@ -17,7 +18,6 @@ from litellm.responses.litellm_completion_transformation.transformation import (
|
|||
)
|
||||
from litellm.responses.streaming_iterator import ResponsesAPIStreamingIterator
|
||||
from litellm.responses.utils import ResponsesAPIRequestUtils
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_or_create_hidden_params
|
||||
from litellm.types.llms.openai import (
|
||||
PART_UNION_TYPES,
|
||||
BaseLiteLLMOpenAIResponseObject,
|
||||
|
|
|
|||
|
|
@ -88,6 +88,13 @@ from litellm.litellm_core_utils.get_llm_provider_logic import (
|
|||
declared_authenticating_provider,
|
||||
is_registered_custom_provider,
|
||||
)
|
||||
from litellm.litellm_core_utils.hidden_params import (
|
||||
HIDDEN_PARAMS_ATTR as _HIDDEN_PARAMS_ATTR,
|
||||
)
|
||||
from litellm.litellm_core_utils.hidden_params import (
|
||||
get_hidden_params,
|
||||
set_hidden_params,
|
||||
)
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLogging
|
||||
from litellm.litellm_core_utils.llm_cost_calc.utils import SERVICE_TIER_COST_KEY_SUFFIXES
|
||||
from litellm.litellm_core_utils.ptu_pricing import (
|
||||
|
|
@ -153,12 +160,10 @@ from litellm.router_utils.add_retry_fallback_headers import (
|
|||
apply_response_model_id,
|
||||
complexity_router_decision_headers,
|
||||
ensure_response_additional_headers,
|
||||
get_hidden_params,
|
||||
get_hidden_params_dict,
|
||||
prepare_response_for_header_attachment,
|
||||
replace_complexity_router_headers,
|
||||
response_total_token_count,
|
||||
set_hidden_params,
|
||||
)
|
||||
from litellm.router_utils.auto_router_model_naming import (
|
||||
AUTO_ROUTER_MODEL_PREFIX,
|
||||
|
|
@ -2901,13 +2906,11 @@ class Router:
|
|||
fallback_item: object,
|
||||
prepared_fallback_hidden_params: tuple[dict[str, object], dict[str, object]],
|
||||
) -> None:
|
||||
if fallback_item is None:
|
||||
if fallback_item is None or not hasattr(fallback_item, _HIDDEN_PARAMS_ATTR):
|
||||
return
|
||||
|
||||
fallback_hidden_params, fallback_headers = prepared_fallback_hidden_params
|
||||
item_hidden_params: Final = get_hidden_params(fallback_item)
|
||||
if item_hidden_params is None:
|
||||
return
|
||||
item_hidden_params: Final = get_hidden_params_dict(fallback_item)
|
||||
item_headers = item_hidden_params.get("additional_headers")
|
||||
if not isinstance(item_headers, dict):
|
||||
item_headers = {}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@ from typing import Any, Final, TypedDict, cast
|
|||
|
||||
from pydantic import BaseModel, TypeAdapter, ValidationError
|
||||
|
||||
from litellm.litellm_core_utils.hidden_params import (
|
||||
HIDDEN_PARAMS_ATTR as _HIDDEN_PARAMS_ATTR,
|
||||
)
|
||||
from litellm.litellm_core_utils.hidden_params import (
|
||||
set_hidden_params,
|
||||
)
|
||||
|
||||
|
||||
class FallbackErrorInfo(TypedDict):
|
||||
message: str
|
||||
|
|
@ -14,7 +21,6 @@ class FallbackErrorInfo(TypedDict):
|
|||
code: str | None
|
||||
|
||||
|
||||
_HIDDEN_PARAMS_ATTR: Final = "_hidden_params"
|
||||
_EMPTY_OBJECT_MAPPING: Final[Mapping[str, object]] = MappingProxyType({})
|
||||
_ROUTING_HEADER_MAPPING: Final = TypeAdapter(Mapping[str, object])
|
||||
_COMPLEXITY_ROUTER_HEADER_PREFIX: Final = "x-litellm-complexity-router-"
|
||||
|
|
@ -206,29 +212,6 @@ def get_hidden_params_dict(
|
|||
return hidden_params
|
||||
|
||||
|
||||
def get_hidden_params(obj: object) -> dict[str, object] | None:
|
||||
hidden_params: Final = (
|
||||
obj.get(_HIDDEN_PARAMS_ATTR) if isinstance(obj, dict) else getattr(obj, _HIDDEN_PARAMS_ATTR, None)
|
||||
)
|
||||
return hidden_params if isinstance(hidden_params, dict) else None
|
||||
|
||||
|
||||
def set_hidden_params(obj: object, hidden_params: dict[str, object]) -> None:
|
||||
if isinstance(obj, dict):
|
||||
obj[_HIDDEN_PARAMS_ATTR] = hidden_params
|
||||
else:
|
||||
setattr(obj, _HIDDEN_PARAMS_ATTR, hidden_params)
|
||||
|
||||
|
||||
def get_or_create_hidden_params(obj: object) -> dict[str, object]:
|
||||
hidden_params: Final = get_hidden_params(obj)
|
||||
if hidden_params is not None:
|
||||
return hidden_params
|
||||
created_hidden_params: Final[dict[str, object]] = {}
|
||||
set_hidden_params(obj, created_hidden_params)
|
||||
return created_hidden_params
|
||||
|
||||
|
||||
def _write_hidden_params(response: object, hidden_params: dict[str, object]) -> None:
|
||||
if isinstance(response, dict) or hasattr(response, _HIDDEN_PARAMS_ATTR):
|
||||
set_hidden_params(response, hidden_params)
|
||||
|
|
|
|||
52
tests/unit/litellm_core_utils/test_hidden_params.py
Normal file
52
tests/unit/litellm_core_utils/test_hidden_params.py
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
from typing import Final
|
||||
|
||||
from litellm.litellm_core_utils.hidden_params import (
|
||||
get_hidden_params,
|
||||
get_or_create_hidden_params,
|
||||
set_hidden_params,
|
||||
)
|
||||
from litellm.types.decisions import DecisionsResponse
|
||||
from litellm.types.utils import ModelResponse
|
||||
|
||||
|
||||
def test_get_and_set_hidden_params_on_plain_object() -> None:
|
||||
class PlainResponse:
|
||||
def __init__(self) -> None:
|
||||
self._hidden_params = {"existing": True}
|
||||
|
||||
response: Final = PlainResponse()
|
||||
stored: Final = get_hidden_params(response)
|
||||
assert stored is response._hidden_params
|
||||
|
||||
replacement: Final = {"replacement": True}
|
||||
set_hidden_params(response, replacement)
|
||||
|
||||
assert response._hidden_params is replacement
|
||||
assert get_hidden_params(response) is replacement
|
||||
|
||||
|
||||
def test_get_or_create_hidden_params_sets_empty_dict_on_plain_object() -> None:
|
||||
class PlainResponse:
|
||||
pass
|
||||
|
||||
response: Final = PlainResponse()
|
||||
hidden_params: Final = get_or_create_hidden_params(response)
|
||||
|
||||
assert response._hidden_params is hidden_params
|
||||
assert hidden_params == {}
|
||||
|
||||
|
||||
def test_get_hidden_params_preserves_model_response_identity() -> None:
|
||||
response: Final = ModelResponse()
|
||||
|
||||
assert get_hidden_params(response) is response.hidden_params
|
||||
|
||||
|
||||
def test_set_hidden_params_replaces_frozen_decisions_response_private_attr() -> None:
|
||||
response: Final = DecisionsResponse(model="decider", answers={}, usage=None)
|
||||
replacement: Final = {"replacement": True}
|
||||
|
||||
set_hidden_params(response, replacement)
|
||||
|
||||
assert response.hidden_params is replacement
|
||||
assert response._hidden_params is replacement
|
||||
|
|
@ -11,13 +11,10 @@ from litellm.router_utils.add_retry_fallback_headers import (
|
|||
complexity_router_decision_headers,
|
||||
ensure_response_additional_headers,
|
||||
get_fallback_errors_from_headers,
|
||||
get_hidden_params,
|
||||
get_hidden_params_dict,
|
||||
replace_complexity_router_headers,
|
||||
set_hidden_params,
|
||||
)
|
||||
from litellm.types.decisions import DecisionsResponse
|
||||
from litellm.types.utils import ModelResponse
|
||||
|
||||
|
||||
class StreamingWrapper:
|
||||
|
|
@ -223,38 +220,6 @@ def test_get_hidden_params_dict_with_no_hidden_params():
|
|||
assert get_hidden_params_dict(PlainResponse()) == {}
|
||||
|
||||
|
||||
def test_get_and_set_hidden_params_on_plain_object() -> None:
|
||||
class PlainResponse:
|
||||
def __init__(self) -> None:
|
||||
self._hidden_params = {"existing": True}
|
||||
|
||||
response: Final = PlainResponse()
|
||||
stored: Final = get_hidden_params(response)
|
||||
assert stored is response._hidden_params
|
||||
|
||||
replacement: Final = {"replacement": True}
|
||||
set_hidden_params(response, replacement)
|
||||
|
||||
assert response._hidden_params is replacement
|
||||
assert get_hidden_params(response) is replacement
|
||||
|
||||
|
||||
def test_get_hidden_params_preserves_model_response_identity() -> None:
|
||||
response: Final = ModelResponse()
|
||||
|
||||
assert get_hidden_params(response) is response.hidden_params
|
||||
|
||||
|
||||
def test_set_hidden_params_replaces_frozen_decisions_response_private_attr() -> None:
|
||||
response: Final = DecisionsResponse(model="decider", answers={}, usage=None)
|
||||
replacement: Final = {"replacement": True}
|
||||
|
||||
set_hidden_params(response, replacement)
|
||||
|
||||
assert response.hidden_params is replacement
|
||||
assert response._hidden_params is replacement
|
||||
|
||||
|
||||
def test_add_fallback_headers_when_no_existing_additional_headers():
|
||||
class NoHeadersWrapper:
|
||||
def __init__(self):
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import litellm
|
|||
from litellm.proxy.proxy_server import _should_include_fallback_errors
|
||||
from litellm.router import Router
|
||||
from litellm.router_utils.add_retry_fallback_headers import get_hidden_params_dict
|
||||
from litellm.types.llms.base import HiddenParams
|
||||
|
||||
|
||||
def test_apply_fallback_hidden_params_copies_from_fallback_response():
|
||||
|
|
@ -86,6 +87,33 @@ def test_apply_fallback_hidden_params_updates_plain_duck_chunk():
|
|||
}
|
||||
|
||||
|
||||
def test_apply_fallback_hidden_params_normalizes_hidden_params_on_plain_duck_chunk():
|
||||
class PlainChunk:
|
||||
def __init__(self) -> None:
|
||||
self._hidden_params = HiddenParams(
|
||||
api_base="https://original.example",
|
||||
model_id="original-model-id",
|
||||
additional_headers={"x-existing-chunk-header": "keep"},
|
||||
)
|
||||
|
||||
chunk: Final = PlainChunk()
|
||||
Router._apply_fallback_hidden_params_to_item(
|
||||
fallback_item=chunk,
|
||||
prepared_fallback_hidden_params=(
|
||||
{"api_base": "https://fallback.example", "model_id": "fallback-model-id"},
|
||||
{"x-litellm-attempted-fallbacks": 1},
|
||||
),
|
||||
)
|
||||
|
||||
assert isinstance(chunk._hidden_params, dict)
|
||||
assert chunk._hidden_params["api_base"] == "https://fallback.example"
|
||||
assert chunk._hidden_params["model_id"] == "fallback-model-id"
|
||||
assert chunk._hidden_params["additional_headers"] == {
|
||||
"x-existing-chunk-header": "keep",
|
||||
"x-litellm-attempted-fallbacks": 1,
|
||||
}
|
||||
|
||||
|
||||
def _two_group_fallback_router() -> Router:
|
||||
return litellm.Router(
|
||||
model_list=[
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue