Coverage for .venv/lib/python3.13/site-packages/litellm/proxy/decisions_endpoints/endpoints.py: 75%
53 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
1from collections.abc import Mapping
2from typing import Annotated, Final
4from fastapi import APIRouter, Depends, Request, Response
5from fastapi.responses import ORJSONResponse # pyright: ignore[reportDeprecated] # required endpoint contract
6from pydantic import TypeAdapter, ValidationError
8from litellm.exceptions import BadRequestError
9from litellm.proxy.auth.user_api_key_auth import UserAPIKeyAuth, user_api_key_auth
10from litellm.proxy.common_request_processing import ProxyBaseLLMRequestProcessing
11from litellm.types.decisions import DecisionsRequestBody, OpenAIDecisionRequestBody
13router: Final = APIRouter()
14_REQUEST_DATA_ADAPTER: Final[TypeAdapter[dict[str, object]]] = TypeAdapter(dict[str, object])
15_DECISIONS_REQUEST_BODY_ADAPTER: Final[TypeAdapter[DecisionsRequestBody]] = TypeAdapter(DecisionsRequestBody)
16_OPENAI_DECISION_REQUEST_BODY_ADAPTER: Final[TypeAdapter[OpenAIDecisionRequestBody]] = TypeAdapter(
17 OpenAIDecisionRequestBody
18)
19_GENERAL_SETTINGS_ADAPTER: Final[TypeAdapter[dict[str, object]]] = TypeAdapter(dict[str, object])
20_OPTIONAL_STRING_ADAPTER: Final[TypeAdapter[str | None]] = TypeAdapter(str | None)
21_OPTIONAL_FLOAT_ADAPTER: Final[TypeAdapter[float | None]] = TypeAdapter(float | None)
24async def _invalid_request(
25 raw_data: Mapping[str, object], error: ValidationError, user_api_key_dict: UserAPIKeyAuth
26) -> Exception:
27 from litellm.proxy.proxy_server import proxy_logging_obj, version
29 return await ProxyBaseLLMRequestProcessing(data=dict(raw_data))._handle_llm_api_exception(
30 e=BadRequestError(
31 message=f"Invalid Decisions request: {error}",
32 model=str(raw_data.get("model", "")),
33 llm_provider="",
34 ),
35 user_api_key_dict=user_api_key_dict,
36 proxy_logging_obj=proxy_logging_obj,
37 version=version,
38 )
41async def _request_data(request: Request, user_api_key_dict: UserAPIKeyAuth) -> dict[str, object]:
42 body: Final = await request.body()
43 try:
44 return _REQUEST_DATA_ADAPTER.validate_json(body)
45 except ValidationError as error:
46 raise await _invalid_request(raw_data={}, error=error, user_api_key_dict=user_api_key_dict)
49async def _process_decisions(
50 request: Request,
51 fastapi_response: Response,
52 user_api_key_dict: UserAPIKeyAuth,
53 body_adapter: TypeAdapter[DecisionsRequestBody] | TypeAdapter[OpenAIDecisionRequestBody],
54) -> object:
55 from litellm.proxy.proxy_server import (
56 general_settings as proxy_general_settings,
57 )
58 from litellm.proxy.proxy_server import (
59 llm_router,
60 proxy_config,
61 proxy_logging_obj,
62 user_max_tokens,
63 user_request_timeout,
64 version,
65 )
66 from litellm.proxy.proxy_server import (
67 user_api_base as proxy_user_api_base,
68 )
69 from litellm.proxy.proxy_server import (
70 user_model as proxy_user_model,
71 )
72 from litellm.proxy.proxy_server import (
73 user_temperature as proxy_user_temperature,
74 )
76 data: Final = await _request_data(request, user_api_key_dict)
77 try:
78 body_adapter.validate_python(data)
79 except ValidationError as error:
80 raise await _invalid_request(raw_data=data, error=error, user_api_key_dict=user_api_key_dict)
81 general_settings: Final = _GENERAL_SETTINGS_ADAPTER.validate_python(proxy_general_settings)
82 user_api_base: Final = _OPTIONAL_STRING_ADAPTER.validate_python(proxy_user_api_base)
83 user_model: Final = _OPTIONAL_STRING_ADAPTER.validate_python(proxy_user_model)
84 user_temperature: Final = _OPTIONAL_FLOAT_ADAPTER.validate_python(proxy_user_temperature)
85 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
86 try:
87 return await processor.base_process_llm_request(
88 request=request,
89 fastapi_response=fastapi_response,
90 user_api_key_dict=user_api_key_dict,
91 route_type="adecisions",
92 proxy_logging_obj=proxy_logging_obj,
93 llm_router=llm_router,
94 general_settings=general_settings,
95 proxy_config=proxy_config,
96 select_data_generator=None,
97 model=None,
98 user_model=user_model,
99 user_temperature=user_temperature,
100 user_request_timeout=user_request_timeout,
101 user_max_tokens=user_max_tokens,
102 user_api_base=user_api_base,
103 version=version,
104 )
105 except Exception as error:
106 raise await processor._handle_llm_api_exception(
107 e=error,
108 user_api_key_dict=user_api_key_dict,
109 proxy_logging_obj=proxy_logging_obj,
110 version=version,
111 )
114@router.post(
115 "/v1/systemone",
116 dependencies=[Depends(user_api_key_auth)],
117 response_class=ORJSONResponse, # pyright: ignore[reportDeprecated] # required endpoint contract
118 tags=["decisions"],
119)
120@router.post(
121 "/systemone",
122 dependencies=[Depends(user_api_key_auth)],
123 response_class=ORJSONResponse, # pyright: ignore[reportDeprecated] # required endpoint contract
124 tags=["decisions"],
125)
126async def systemone(
127 request: Request,
128 fastapi_response: Response,
129 user_api_key_dict: Annotated[UserAPIKeyAuth, Depends(user_api_key_auth)],
130):
131 return await _process_decisions(
132 request=request,
133 fastapi_response=fastapi_response,
134 user_api_key_dict=user_api_key_dict,
135 body_adapter=_DECISIONS_REQUEST_BODY_ADAPTER,
136 )
139@router.post(
140 "/v1/decisions",
141 dependencies=[Depends(user_api_key_auth)],
142 response_class=ORJSONResponse, # pyright: ignore[reportDeprecated] # required endpoint contract
143 tags=["decisions"],
144)
145@router.post(
146 "/decisions",
147 dependencies=[Depends(user_api_key_auth)],
148 response_class=ORJSONResponse, # pyright: ignore[reportDeprecated] # required endpoint contract
149 tags=["decisions"],
150)
151async def decisions(
152 request: Request,
153 fastapi_response: Response,
154 user_api_key_dict: Annotated[UserAPIKeyAuth, Depends(user_api_key_auth)],
155):
156 return await _process_decisions(
157 request=request,
158 fastapi_response=fastapi_response,
159 user_api_key_dict=user_api_key_dict,
160 body_adapter=_OPENAI_DECISION_REQUEST_BODY_ADAPTER,
161 )