mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
anthropic request body got mutated fix
This commit is contained in:
parent
d228959645
commit
2ab8203fae
2 changed files with 51 additions and 1 deletions
|
|
@ -76,7 +76,8 @@ class AnthropicMessagesHandler(BaseTranslation):
|
|||
|
||||
chat_completion_compatible_request = (
|
||||
LiteLLMAnthropicMessagesAdapter().translate_anthropic_to_openai(
|
||||
anthropic_message_request=cast(AnthropicMessagesRequest, data)
|
||||
# Use a shallow copy to avoid mutating request data (pop on litellm_metadata).
|
||||
anthropic_message_request=cast(AnthropicMessagesRequest, data.copy())
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,26 @@ class MockPassThroughGuardrail(CustomGuardrail):
|
|||
return inputs
|
||||
|
||||
|
||||
class MockDynamicGuardrail(CustomGuardrail):
|
||||
"""Mock guardrail that records dynamic params from request metadata."""
|
||||
|
||||
def __init__(self, guardrail_name: str):
|
||||
super().__init__(guardrail_name=guardrail_name)
|
||||
self.dynamic_params: Optional[dict] = None
|
||||
|
||||
async def apply_guardrail(
|
||||
self,
|
||||
inputs: GenericGuardrailAPIInputs,
|
||||
request_data: dict,
|
||||
input_type: Literal["request", "response"],
|
||||
logging_obj: Optional[Any] = None,
|
||||
) -> GenericGuardrailAPIInputs:
|
||||
self.dynamic_params = self.get_guardrail_dynamic_request_body_params(
|
||||
request_data
|
||||
)
|
||||
return inputs
|
||||
|
||||
|
||||
class TestAnthropicMessagesHandlerStreamingOutputProcessing:
|
||||
"""Test streaming output processing functionality"""
|
||||
|
||||
|
|
@ -70,6 +90,35 @@ class TestAnthropicMessagesHandlerStreamingOutputProcessing:
|
|||
# Should return the responses unchanged
|
||||
assert result == responses_so_far
|
||||
|
||||
|
||||
class TestAnthropicMessagesHandlerInputProcessing:
|
||||
"""Test input processing preserves litellm_metadata for dynamic guardrails."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_process_input_messages_preserves_litellm_metadata_guardrails(self):
|
||||
handler = AnthropicMessagesHandler()
|
||||
guardrail = MockDynamicGuardrail(guardrail_name="cygnal-monitor")
|
||||
|
||||
data = {
|
||||
"model": "claude-3-5-sonnet-20241022",
|
||||
"messages": [{"role": "user", "content": "hello"}],
|
||||
"litellm_metadata": {
|
||||
"guardrails": [
|
||||
{
|
||||
"cygnal-monitor": {
|
||||
"extra_body": {"policy_id": "policy-123"}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
with patch("litellm.proxy.proxy_server.premium_user", True):
|
||||
await handler.process_input_messages(data=data, guardrail_to_apply=guardrail)
|
||||
|
||||
assert data.get("litellm_metadata", {}).get("guardrails")
|
||||
assert guardrail.dynamic_params == {"policy_id": "policy-123"}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_process_output_streaming_response_empty_choices(self):
|
||||
"""Test that streaming response with empty choices doesn't raise IndexError
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue