mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
fix(health): use provider default mode for checks
This commit is contained in:
parent
8a7801395b
commit
df8e815d8c
5 changed files with 81 additions and 7 deletions
|
|
@ -283,7 +283,9 @@ class HealthCheckHelpers:
|
|||
),
|
||||
"responses": lambda: litellm.aresponses(
|
||||
**_filter_model_params(model_params=model_params),
|
||||
input=[{"role": "user", "content": prompt or "test"}],
|
||||
input=[
|
||||
{"role": "user", "content": prompt or "test"},
|
||||
],
|
||||
),
|
||||
"anthropic_messages": lambda: litellm.anthropic_messages(
|
||||
**{
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ class BaseConfig(ABC):
|
|||
def __init__(self):
|
||||
pass
|
||||
|
||||
def get_health_check_mode(self) -> str | None:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def get_config(cls):
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ class ChatGPTConfig(OpenAIConfig):
|
|||
def api_base_without_login(self) -> str:
|
||||
return self.authenticator.get_api_base()
|
||||
|
||||
def get_health_check_mode(self) -> str:
|
||||
return "responses"
|
||||
|
||||
def _get_openai_compatible_provider_info(
|
||||
self,
|
||||
model: str,
|
||||
|
|
|
|||
|
|
@ -8810,12 +8810,16 @@ async def ahealth_check(
|
|||
api_base=api_base_from_params,
|
||||
api_key=api_key_from_params,
|
||||
)
|
||||
|
||||
model_params["cache"] = {"no-cache": True} # don't used cached responses for making health check calls
|
||||
# chatgpt provider uses the Responses API exclusively; default to "responses" so the
|
||||
# health check doesn't send a Chat Completions payload that the backend rejects.
|
||||
if mode is None and custom_llm_provider == "chatgpt":
|
||||
mode = "responses"
|
||||
if mode is None and custom_llm_provider in {provider.value for provider in LlmProviders}:
|
||||
provider_config: Final = ProviderConfigManager.get_provider_chat_config(
|
||||
model=model,
|
||||
provider=LlmProviders(custom_llm_provider),
|
||||
)
|
||||
if provider_config is not None:
|
||||
mode = ( # rebind-ok: resolve provider-config default
|
||||
provider_config.get_health_check_mode()
|
||||
)
|
||||
mode = mode or default_health_check_mode(
|
||||
requested_model=requested_model, model=model, custom_llm_provider=custom_llm_provider
|
||||
)
|
||||
|
|
|
|||
|
|
@ -151,6 +151,68 @@ async def test_ahealth_check_supports_image_edit_mode():
|
|||
|
||||
assert "error" not in result
|
||||
assert "Mode image_edit not supported" not in str(result)
|
||||
@pytest.mark.asyncio
|
||||
async def test_ahealth_check_uses_provider_mode_and_responses_message_input():
|
||||
mock_response = MagicMock()
|
||||
mock_response._hidden_params = {}
|
||||
mock_aresponses = AsyncMock(return_value=mock_response)
|
||||
mock_acompletion = AsyncMock()
|
||||
|
||||
with (
|
||||
patch( # test-quality-ok: isolate provider and handler calls for focused health-check routing
|
||||
"litellm.main.get_llm_provider",
|
||||
return_value=("gpt-5.6-sol", "chatgpt", None, None),
|
||||
),
|
||||
patch.object( # test-quality-ok: isolate health-check metadata plumbing for routing assertion
|
||||
HealthCheckHelpers,
|
||||
"_update_model_params_with_health_check_tracking_information",
|
||||
side_effect=lambda model_params: model_params,
|
||||
),
|
||||
patch("litellm.aresponses", new=mock_aresponses), # test-quality-ok: verify provider-mode dispatch
|
||||
patch("litellm.acompletion", new=mock_acompletion), # test-quality-ok: verify chat fallback dispatch
|
||||
):
|
||||
result = await ahealth_check(
|
||||
model_params={"model": "chatgpt/gpt-5.6-sol"},
|
||||
mode=None,
|
||||
prompt="health check",
|
||||
)
|
||||
|
||||
assert "error" not in result
|
||||
mock_aresponses.assert_awaited_once()
|
||||
assert mock_aresponses.await_args.kwargs["input"] == [
|
||||
{"role": "user", "content": "health check"}
|
||||
]
|
||||
mock_acompletion.assert_not_awaited()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ahealth_check_provider_without_default_mode_keeps_chat():
|
||||
mock_response = MagicMock()
|
||||
mock_response._hidden_params = {}
|
||||
mock_aresponses = AsyncMock()
|
||||
mock_acompletion = AsyncMock(return_value=mock_response)
|
||||
|
||||
with (
|
||||
patch( # test-quality-ok: isolate provider and handler calls for focused health-check routing
|
||||
"litellm.main.get_llm_provider",
|
||||
return_value=("custom-model", "custom", None, None),
|
||||
),
|
||||
patch.object( # test-quality-ok: isolate health-check metadata plumbing for routing assertion
|
||||
HealthCheckHelpers,
|
||||
"_update_model_params_with_health_check_tracking_information",
|
||||
side_effect=lambda model_params: model_params,
|
||||
),
|
||||
patch("litellm.aresponses", new=mock_aresponses), # test-quality-ok: verify provider-mode dispatch
|
||||
patch("litellm.acompletion", new=mock_acompletion), # test-quality-ok: verify chat fallback dispatch
|
||||
):
|
||||
result = await ahealth_check(
|
||||
model_params={"model": "custom/custom-model"},
|
||||
mode=None,
|
||||
)
|
||||
|
||||
assert "error" not in result
|
||||
mock_acompletion.assert_awaited_once()
|
||||
mock_aresponses.assert_not_awaited()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -472,7 +534,7 @@ async def test_realtime_health_check_uses_model_level_vertex_params():
|
|||
"websockets.connect",
|
||||
lambda url, **kwargs: _FakeWebsocketConnect(connect_calls, url, **kwargs),
|
||||
),
|
||||
patch.object(
|
||||
patch.object( # test-quality-ok: isolate health-check metadata plumbing for routing assertion
|
||||
HealthCheckHelpers,
|
||||
"update_model_params_with_health_check_tracking_information",
|
||||
staticmethod(lambda model_params: model_params),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue