diff --git a/litellm/proxy/common_request_processing.py b/litellm/proxy/common_request_processing.py index ef1d64335b4..9d69f4c97ba 100644 --- a/litellm/proxy/common_request_processing.py +++ b/litellm/proxy/common_request_processing.py @@ -32,6 +32,7 @@ from litellm.constants import ( STREAM_SSE_DATA_PREFIX, ) from litellm.integrations.custom_guardrail import CustomGuardrail +from litellm.integrations.websearch_interception.tools import is_web_search_tool from litellm.litellm_core_utils.dd_tracing import NullTracer, tracer from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.litellm_core_utils.llm_response_utils.get_headers import ( @@ -922,6 +923,23 @@ class ProxyBaseLLMRequestProcessing: ): self.data["model"] = user_api_key_dict.aliases[self.data["model"]] + ### WEB SEARCH REDIRECT (per-deployment force) ### + # if request only contains a web_search tool and has any deployment that has + # `force_websearch_model`, redirect to that model. + if ( + isinstance(self.data.get("model"), str) + and llm_router is not None + and self.data.get("tools") + and all( + isinstance(t, dict) and is_web_search_tool(t) + for t in self.data["tools"] + ) + ): + for dep in llm_router.get_model_list(model_name=self.data["model"]) or []: + if model := dep.get("litellm_params", {}).get("force_websearch_model"): + self.data["model"] = model + break + self.data["litellm_call_id"] = request.headers.get( "x-litellm-call-id", str(uuid.uuid4()) ) diff --git a/litellm/types/router.py b/litellm/types/router.py index 6601f552b52..bd6e96e567a 100644 --- a/litellm/types/router.py +++ b/litellm/types/router.py @@ -222,6 +222,7 @@ class GenericLiteLLMParams(CredentialLiteLLMParams, CustomPricingLiteLLMParams): use_chat_completions_api: Optional[bool] = None model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True) merge_reasoning_content_in_choices: Optional[bool] = False + force_websearch_model: Optional[str] = None model_info: Optional[Dict] = None mock_response: Optional[Union[str, ModelResponse, Exception, Any]] = None @@ -351,6 +352,8 @@ class LiteLLMParamsTypedDict(TypedDict, total=False): drop_params: Optional[bool] ## RESPONSES API → CHAT COMPLETIONS BRIDGE ## use_chat_completions_api: Optional[bool] + ## WEB SEARCH REDIRECT ## + force_websearch_model: Optional[str] ## UNIFIED PROJECT/REGION ## region_name: Optional[str] ## VERTEX AI ##