mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
Merge 00beee9d4e into dd31692282
This commit is contained in:
commit
d71c4f4d79
3 changed files with 116 additions and 9 deletions
|
|
@ -122,7 +122,8 @@ class ExceptionCheckers:
|
|||
known_exception_substrings: Final = [
|
||||
"content_policy_violation",
|
||||
"responsibleaipolicyviolation",
|
||||
"the response was filtered due to the prompt triggering azure openai's content management",
|
||||
"contentfiltered",
|
||||
"the response was filtered due to the prompt triggering azure openai",
|
||||
"your task failed as a result of our safety system",
|
||||
"the model produced invalid content",
|
||||
"content_filter_policy",
|
||||
|
|
@ -1923,6 +1924,10 @@ def _map_vllm_exception(
|
|||
)
|
||||
|
||||
|
||||
_AZURE_CONTENT_POLICY_ERROR_CODES: Final = frozenset(("content_policy_violation", "content_filter"))
|
||||
_AZURE_CONTENT_POLICY_INNER_CODES: Final = frozenset(("ResponsibleAIPolicyViolation", "ContentFiltered"))
|
||||
|
||||
|
||||
def _map_azure_exception(
|
||||
*,
|
||||
model: str,
|
||||
|
|
@ -1949,13 +1954,9 @@ def _map_azure_exception(
|
|||
if isinstance(body_dict, dict):
|
||||
if isinstance(body_dict.get("error"), dict):
|
||||
azure_error_code = body_dict["error"].get("code")
|
||||
# Also check inner_error for
|
||||
# ResponsibleAIPolicyViolation which indicates a
|
||||
# content policy violation even when the top-level
|
||||
# code is generic (e.g. "invalid_request_error").
|
||||
if azure_error_code != "content_policy_violation":
|
||||
if azure_error_code not in _AZURE_CONTENT_POLICY_ERROR_CODES:
|
||||
_inner: Final = body_dict["error"].get("inner_error") or body_dict["error"].get("innererror")
|
||||
if isinstance(_inner, dict) and _inner.get("code") == "ResponsibleAIPolicyViolation":
|
||||
if isinstance(_inner, dict) and _inner.get("code") in _AZURE_CONTENT_POLICY_INNER_CODES:
|
||||
azure_error_code = "content_policy_violation"
|
||||
else:
|
||||
azure_error_code = body_dict.get("code")
|
||||
|
|
@ -1986,8 +1987,9 @@ def _map_azure_exception(
|
|||
litellm_debug_info=extra_information,
|
||||
response=getattr(original_exception, "response", None),
|
||||
)
|
||||
elif azure_error_code == "content_policy_violation" or ExceptionCheckers.is_azure_content_policy_violation_error(
|
||||
error_str
|
||||
elif (
|
||||
azure_error_code in _AZURE_CONTENT_POLICY_ERROR_CODES
|
||||
or ExceptionCheckers.is_azure_content_policy_violation_error(error_str)
|
||||
):
|
||||
from litellm.llms.azure.exception_mapping import (
|
||||
AzureOpenAIExceptionMapping,
|
||||
|
|
|
|||
|
|
@ -171,9 +171,11 @@ class TestExceptionCheckers:
|
|||
error_strings = [
|
||||
"invalid_request_error content_policy_violation occurred",
|
||||
"The response was filtered due to the prompt triggering Azure OpenAI's content management policy",
|
||||
"The response was filtered due to the prompt triggering Azure OpenAI’s content management policy",
|
||||
"Your task failed as a result of our safety system detecting harmful content",
|
||||
"The model produced invalid content that violates our policy",
|
||||
"Request blocked due to content_filter_policy restrictions",
|
||||
"innererror code ContentFiltered",
|
||||
]
|
||||
|
||||
for error_str in error_strings:
|
||||
|
|
@ -186,8 +188,10 @@ class TestExceptionCheckers:
|
|||
error_strings = [
|
||||
"INVALID_REQUEST_ERROR CONTENT_POLICY_VIOLATION",
|
||||
"The Response Was Filtered Due To The Prompt Triggering Azure OpenAI's Content Management",
|
||||
"The Response Was Filtered Due To The Prompt Triggering Azure OpenAI’s Content Management",
|
||||
"YOUR TASK FAILED AS A RESULT OF OUR SAFETY SYSTEM",
|
||||
"Content_Filter_Policy restriction detected",
|
||||
"CONTENTFILTERED",
|
||||
]
|
||||
|
||||
for error_str in error_strings:
|
||||
|
|
|
|||
|
|
@ -403,6 +403,107 @@ class TestAzureExceptionMapping:
|
|||
assert "optional_pre_call_checks" in error.message
|
||||
assert "docs.litellm.ai" in error.message
|
||||
|
||||
def test_azure_prompt_content_filter_maps_to_content_policy_violation(self):
|
||||
mock_exception = Exception("Bad request")
|
||||
mock_exception.body = {
|
||||
"error": {
|
||||
"message": (
|
||||
"The response was filtered due to the prompt triggering "
|
||||
"Azure OpenAI’s content management policy. Please modify your prompt and retry."
|
||||
),
|
||||
"type": "invalid_request_error",
|
||||
"param": "prompt",
|
||||
"code": "content_filter",
|
||||
"content_filters": [
|
||||
{
|
||||
"blocked": True,
|
||||
"source_type": "prompt",
|
||||
"content_filter_results": {
|
||||
"hate": {"filtered": False, "severity": "safe"},
|
||||
"sexual": {"filtered": False, "severity": "safe"},
|
||||
"violence": {"filtered": False, "severity": "safe"},
|
||||
"self_harm": {"filtered": False, "severity": "safe"},
|
||||
"jailbreak": {"detected": True, "filtered": True},
|
||||
},
|
||||
}
|
||||
],
|
||||
"innererror": {"code": "ContentFiltered"},
|
||||
}
|
||||
}
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 400
|
||||
mock_exception.response = mock_response
|
||||
|
||||
with pytest.raises(ContentPolicyViolationError) as exc_info:
|
||||
exception_type(
|
||||
model="azure/gpt-4",
|
||||
original_exception=mock_exception,
|
||||
custom_llm_provider="azure",
|
||||
)
|
||||
|
||||
e = exc_info.value
|
||||
assert e.provider_specific_fields is not None
|
||||
assert e.provider_specific_fields["innererror"]["code"] == "ContentFiltered"
|
||||
assert e.provider_specific_fields["inner_error"]["code"] == "ContentFiltered"
|
||||
|
||||
def test_azure_content_filtered_innererror_without_top_code(self):
|
||||
mock_exception = Exception("Bad request")
|
||||
mock_exception.body = {
|
||||
"error": {
|
||||
"code": "invalid_request_error",
|
||||
"innererror": {"code": "ContentFiltered"},
|
||||
"message": "The request was rejected.",
|
||||
"type": "invalid_request_error",
|
||||
}
|
||||
}
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 400
|
||||
mock_exception.response = mock_response
|
||||
|
||||
with pytest.raises(ContentPolicyViolationError) as exc_info:
|
||||
exception_type(
|
||||
model="azure/gpt-4",
|
||||
original_exception=mock_exception,
|
||||
custom_llm_provider="azure",
|
||||
)
|
||||
|
||||
e = exc_info.value
|
||||
assert e.provider_specific_fields is not None
|
||||
assert e.provider_specific_fields["innererror"]["code"] == "ContentFiltered"
|
||||
|
||||
def test_azure_ordinary_invalid_request_stays_bad_request(self):
|
||||
from litellm.exceptions import BadRequestError
|
||||
|
||||
mock_exception = Exception(
|
||||
"Error code: 400 - {'error': {'message': \"Invalid 'temperature': decimal above maximum value. "
|
||||
"Expected a value <= 2, but got 200 instead.\", 'type': 'invalid_request_error', "
|
||||
"'param': 'temperature', 'code': 'decimal_above_max_value'}}"
|
||||
)
|
||||
mock_exception.body = {
|
||||
"error": {
|
||||
"message": (
|
||||
"Invalid 'temperature': decimal above maximum value. "
|
||||
"Expected a value <= 2, but got 200 instead."
|
||||
),
|
||||
"type": "invalid_request_error",
|
||||
"param": "temperature",
|
||||
"code": "decimal_above_max_value",
|
||||
}
|
||||
}
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 400
|
||||
mock_exception.response = mock_response
|
||||
mock_exception.status_code = 400
|
||||
|
||||
with pytest.raises(BadRequestError) as exc_info:
|
||||
exception_type(
|
||||
model="azure/gpt-4",
|
||||
original_exception=mock_exception,
|
||||
custom_llm_provider="azure",
|
||||
)
|
||||
|
||||
assert not isinstance(exc_info.value, ContentPolicyViolationError)
|
||||
|
||||
def test_openai_invalid_encrypted_content_error(self):
|
||||
"""Test that OpenAI invalid_encrypted_content errors also get helpful guidance."""
|
||||
from litellm.exceptions import BadRequestError
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue