mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
fix(websearch): prevent internal _websearch_interception flags from leaking to provider API
The websearch interception deployment hook sets kwargs["_websearch_interception_converted_stream"] = True to track stream conversion. This internal flag was leaking into extra_body via add_provider_specific_params_to_optional_params, causing OpenAI to reject requests with "Unknown parameter: '_websearch_interception_converted_stream'". Skip underscore-prefixed keys when building extra_body, since they are internal flags and should never be forwarded to providers. Fixes #28458
This commit is contained in:
parent
b0b25ae4b9
commit
59f3bb6b22
2 changed files with 128 additions and 1 deletions
|
|
@ -4839,7 +4839,11 @@ def add_provider_specific_params_to_optional_params(
|
|||
):
|
||||
extra_body = passed_params.pop("extra_body", None) or {}
|
||||
for k in passed_params.keys():
|
||||
if k not in openai_params and passed_params[k] is not None:
|
||||
if (
|
||||
k not in openai_params
|
||||
and passed_params[k] is not None
|
||||
and not k.startswith("_")
|
||||
):
|
||||
extra_body[k] = passed_params[k]
|
||||
if not isinstance(optional_params.get("extra_body"), dict):
|
||||
optional_params["extra_body"] = {}
|
||||
|
|
|
|||
123
tests/test_litellm/test_websearch_interception_stream_param.py
Normal file
123
tests/test_litellm/test_websearch_interception_stream_param.py
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
"""
|
||||
Unit tests for fix #28458: Internal _websearch_interception_converted_stream flag
|
||||
must NOT leak into extra_body when building provider-specific params.
|
||||
|
||||
The websearch interception deployment hook sets
|
||||
kwargs["_websearch_interception_converted_stream"] = True to track that stream
|
||||
was converted from True to False. This internal flag was leaking through
|
||||
add_provider_specific_params_to_optional_params into extra_body, causing
|
||||
OpenAI to reject the request with "Unknown parameter:
|
||||
'_websearch_interception_converted_stream'".
|
||||
|
||||
The fix filters out any key starting with '_' from being added to extra_body,
|
||||
since underscore-prefixed keys are internal flags, not provider params.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from litellm.utils import add_provider_specific_params_to_optional_params
|
||||
|
||||
|
||||
class TestInternalFlagsNotInExtraBody:
|
||||
"""Verify internal _-prefixed flags are excluded from extra_body."""
|
||||
|
||||
def test_websearch_flag_excluded_from_extra_body(self):
|
||||
"""_websearch_interception_converted_stream must not appear in extra_body."""
|
||||
passed_params = {
|
||||
"temperature": 0.7,
|
||||
"_websearch_interception_converted_stream": True,
|
||||
}
|
||||
optional_params = {}
|
||||
openai_params = ["temperature", "model", "messages"]
|
||||
|
||||
result = add_provider_specific_params_to_optional_params(
|
||||
optional_params=optional_params,
|
||||
passed_params=passed_params,
|
||||
custom_llm_provider="openai",
|
||||
openai_params=openai_params,
|
||||
)
|
||||
|
||||
extra_body = result.get("extra_body", {})
|
||||
assert "_websearch_interception_converted_stream" not in extra_body
|
||||
|
||||
def test_regular_non_openai_params_still_in_extra_body(self):
|
||||
"""Non-underscore, non-OpenAI params should still go to extra_body."""
|
||||
passed_params = {
|
||||
"temperature": 0.7,
|
||||
"custom_provider_param": "value",
|
||||
}
|
||||
optional_params = {}
|
||||
openai_params = ["temperature", "model", "messages"]
|
||||
|
||||
result = add_provider_specific_params_to_optional_params(
|
||||
optional_params=optional_params,
|
||||
passed_params=passed_params,
|
||||
custom_llm_provider="openai",
|
||||
openai_params=openai_params,
|
||||
)
|
||||
|
||||
extra_body = result.get("extra_body", {})
|
||||
assert extra_body.get("custom_provider_param") == "value"
|
||||
|
||||
def test_all_underscore_prefixed_flags_excluded(self):
|
||||
"""Any key starting with _ should be excluded from extra_body."""
|
||||
passed_params = {
|
||||
"_websearch_interception_converted_stream": True,
|
||||
"_websearch_interception_other_flag": "test",
|
||||
"_some_other_internal_flag": 42,
|
||||
"valid_param": "keep",
|
||||
}
|
||||
optional_params = {}
|
||||
openai_params = ["model", "messages"]
|
||||
|
||||
result = add_provider_specific_params_to_optional_params(
|
||||
optional_params=optional_params,
|
||||
passed_params=passed_params,
|
||||
custom_llm_provider="openai",
|
||||
openai_params=openai_params,
|
||||
)
|
||||
|
||||
extra_body = result.get("extra_body", {})
|
||||
assert "_websearch_interception_converted_stream" not in extra_body
|
||||
assert "_websearch_interception_other_flag" not in extra_body
|
||||
assert "_some_other_internal_flag" not in extra_body
|
||||
assert extra_body.get("valid_param") == "keep"
|
||||
|
||||
def test_openai_compatible_providers_also_filtered(self):
|
||||
"""Internal flags should also be filtered for openai-compatible providers."""
|
||||
passed_params = {
|
||||
"_websearch_interception_converted_stream": True,
|
||||
"custom_param": "value",
|
||||
}
|
||||
optional_params = {}
|
||||
openai_params = ["model", "messages"]
|
||||
|
||||
result = add_provider_specific_params_to_optional_params(
|
||||
optional_params=optional_params,
|
||||
passed_params=passed_params,
|
||||
custom_llm_provider="azure",
|
||||
openai_params=openai_params,
|
||||
)
|
||||
|
||||
extra_body = result.get("extra_body", {})
|
||||
assert "_websearch_interception_converted_stream" not in extra_body
|
||||
assert extra_body.get("custom_param") == "value"
|
||||
|
||||
def test_no_extra_body_when_only_internal_flags(self):
|
||||
"""If only internal flags exist (besides openai params), extra_body should be empty."""
|
||||
passed_params = {
|
||||
"temperature": 0.7,
|
||||
"_websearch_interception_converted_stream": True,
|
||||
}
|
||||
optional_params = {}
|
||||
openai_params = ["temperature", "model", "messages"]
|
||||
|
||||
result = add_provider_specific_params_to_optional_params(
|
||||
optional_params=optional_params,
|
||||
passed_params=passed_params,
|
||||
custom_llm_provider="openai",
|
||||
openai_params=openai_params,
|
||||
)
|
||||
|
||||
extra_body = result.get("extra_body", {})
|
||||
assert len(extra_body) == 0
|
||||
Loading…
Add table
Reference in a new issue