mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-15 04:19:08 +00:00
fix: anthropic_messages_handler only treated litellm_params.mock_respons
Addresses #31976.
This commit is contained in:
parent
4e53ae98a7
commit
262e596b9b
2 changed files with 44 additions and 3 deletions
|
|
@ -362,6 +362,18 @@ async def anthropic_messages(
|
|||
return response
|
||||
|
||||
|
||||
def _get_mock_response_content(
|
||||
mock_response: Optional[Union[str, litellm.ModelResponse, Exception, Any]],
|
||||
) -> Optional[str]:
|
||||
if isinstance(mock_response, str):
|
||||
return mock_response
|
||||
if isinstance(mock_response, litellm.ModelResponse):
|
||||
first_choice = mock_response.choices[0]
|
||||
if isinstance(first_choice, litellm.Choices):
|
||||
return first_choice.message.content
|
||||
return None
|
||||
|
||||
|
||||
def validate_anthropic_api_metadata(metadata: Optional[Dict] = None) -> Optional[Dict]:
|
||||
"""
|
||||
Validate Anthropic API metadata - This is done to ensure only allowed `metadata` fields are passed to Anthropic API
|
||||
|
|
@ -466,12 +478,13 @@ def anthropic_messages_handler(
|
|||
if kwargs.get("_websearch_interception_converted_stream", False):
|
||||
litellm_logging_obj.model_call_details["websearch_interception_converted_stream"] = True
|
||||
|
||||
if litellm_params.mock_response and isinstance(litellm_params.mock_response, str):
|
||||
mock_response_content = _get_mock_response_content(litellm_params.mock_response)
|
||||
if mock_response_content is not None:
|
||||
return mock_response(
|
||||
model=model,
|
||||
messages=messages,
|
||||
max_tokens=max_tokens,
|
||||
mock_response=litellm_params.mock_response,
|
||||
mock_response=mock_response_content,
|
||||
)
|
||||
|
||||
anthropic_messages_provider_config: Optional[BaseAnthropicMessagesConfig] = None
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||
|
||||
from litellm.anthropic_interface import messages
|
||||
from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler
|
||||
from litellm.types.utils import Delta, ModelResponse, StreamingChoices
|
||||
from litellm.types.utils import Choices, Delta, Message, ModelResponse, StreamingChoices
|
||||
|
||||
|
||||
def test_anthropic_experimental_pass_through_messages_handler():
|
||||
|
|
@ -648,6 +648,34 @@ def test_handler_skips_strip_when_presanitized():
|
|||
assert result is not None
|
||||
|
||||
|
||||
def test_handler_short_circuits_on_model_response_mock_response():
|
||||
"""Regression test for #31976. BedrockGuardrail with
|
||||
disable_exception_on_block=True sets a ModelResponse (not a str) as
|
||||
litellm_params.mock_response to block a request without raising. The
|
||||
handler must honor it instead of silently calling the real model."""
|
||||
from litellm.llms.anthropic.experimental_pass_through.messages import handler
|
||||
|
||||
blocked_response = ModelResponse(
|
||||
choices=[Choices(message=Message(content="Blocked by guardrail"))],
|
||||
model="bedrock-guardrail",
|
||||
)
|
||||
|
||||
with patch.object(
|
||||
handler.base_llm_http_handler,
|
||||
"anthropic_messages_handler",
|
||||
) as mock_base_handler:
|
||||
result = handler.anthropic_messages_handler(
|
||||
max_tokens=10,
|
||||
messages=[{"role": "user", "content": "some blocked content"}],
|
||||
model="anthropic/claude-3-5-sonnet-20241022",
|
||||
custom_llm_provider="anthropic",
|
||||
mock_response=blocked_response,
|
||||
)
|
||||
|
||||
mock_base_handler.assert_not_called()
|
||||
assert result["content"][0]["text"] == "Blocked by guardrail"
|
||||
|
||||
|
||||
def test_presanitized_flag_not_leaked_to_provider_params():
|
||||
"""The private sentinel must be popped, never forwarded as a request param."""
|
||||
from litellm.llms.anthropic.experimental_pass_through.messages import handler
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue