mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-21 00:21:49 +00:00
fix(guardrails): treat the stored Javelin api_version default as unset for Azure Content Safety
Guardrails created through POST /guardrails on older releases have api_version "v1" saved in the database, because the writer persists every default. Azure Content Safety never accepts that value, so those guardrails kept answering 404 after the default moved to None. The Azure base now resolves "v1" to 2024-09-01 the same way it resolves a missing value. Also restores the OpenAPI snapshot line that a Python 3.14 regeneration had dedented
This commit is contained in:
parent
6f4d1c5911
commit
24064e3b31
3 changed files with 44 additions and 2 deletions
|
|
@ -19621,7 +19621,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"description": "\nUnified rate-limit error.\n\nEvery rate-limit condition surfaced by litellm \u2014 whether it originated from\nan upstream LLM provider, a vendor batch endpoint, or one of litellm's own\nproxy-side limiters (parallel-requests, dynamic-rate, batch-rate, budget,\nmax-iterations, etc.) \u2014 is raised as an instance of this class.\n\nThe :attr:`category` attribute lets callers distinguish the source. See\n:class:`RateLimitErrorCategory` for the available values.\n"
|
||||
"description": "\n Unified rate-limit error.\n\n Every rate-limit condition surfaced by litellm \u2014 whether it originated from\n an upstream LLM provider, a vendor batch endpoint, or one of litellm's own\n proxy-side limiters (parallel-requests, dynamic-rate, batch-rate, budget,\n max-iterations, etc.) \u2014 is raised as an instance of this class.\n\n The :attr:`category` attribute lets callers distinguish the source. See\n :class:`RateLimitErrorCategory` for the available values.\n "
|
||||
},
|
||||
"500": {
|
||||
"content": {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,13 @@ AZURE_CONTENT_SAFETY_MAX_TEXT_LENGTH: Final = 10000
|
|||
AZURE_CONTENT_SAFETY_TEXT_RECORD_LENGTH: Final = 1000
|
||||
|
||||
AZURE_CONTENT_SAFETY_DEFAULT_API_VERSION: Final = "2024-09-01"
|
||||
JAVELIN_API_VERSION_STORED_BY_OLDER_RELEASES: Final = "v1"
|
||||
|
||||
|
||||
def resolve_content_safety_api_version(configured: str | None) -> str:
|
||||
if not configured or configured == JAVELIN_API_VERSION_STORED_BY_OLDER_RELEASES:
|
||||
return AZURE_CONTENT_SAFETY_DEFAULT_API_VERSION
|
||||
return configured
|
||||
|
||||
|
||||
class AzureGuardrailBase:
|
||||
|
|
@ -58,7 +65,7 @@ class AzureGuardrailBase:
|
|||
Returns:
|
||||
Parsed JSON response dict.
|
||||
"""
|
||||
api_version: Final = self.api_version or AZURE_CONTENT_SAFETY_DEFAULT_API_VERSION
|
||||
api_version: Final = resolve_content_safety_api_version(self.api_version)
|
||||
url: Final = f"{self.api_base}/contentsafety/{endpoint_path}?api-version={api_version}"
|
||||
headers: Final = {
|
||||
"Ocp-Apim-Subscription-Key": self.api_key,
|
||||
|
|
|
|||
|
|
@ -494,3 +494,38 @@ async def test_config_without_api_version_calls_documented_azure_api_version():
|
|||
assert mock_post.call_args.kwargs["url"] == (
|
||||
"https://example.cognitiveservices.azure.com/contentsafety/text:analyze?api-version=2024-09-01"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("stored_api_version", "expected_api_version"),
|
||||
[("v1", "2024-09-01"), ("2023-10-01", "2023-10-01")],
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_guardrail_loaded_with_stored_api_version_calls_azure_at(stored_api_version, expected_api_version):
|
||||
"""Releases before the api_version default fix saved every guardrail created
|
||||
through the API or dashboard with Javelin's "v1", which Azure always answers
|
||||
with 404. A row like that must reach Azure at the documented default, while a
|
||||
real Azure version an admin chose is sent as written."""
|
||||
handler = InMemoryGuardrailHandler()
|
||||
registered = handler.initialize_guardrail(
|
||||
guardrail={
|
||||
"guardrail_name": f"azure-text-moderation-stored-{stored_api_version}",
|
||||
"litellm_params": {
|
||||
"guardrail": "azure/text_moderations",
|
||||
"mode": "pre_call",
|
||||
"api_key": "azure_text_moderation_api_key",
|
||||
"api_base": "https://example.cognitiveservices.azure.com",
|
||||
"api_version": stored_api_version,
|
||||
},
|
||||
}
|
||||
)
|
||||
assert registered is not None
|
||||
guardrail = handler.guardrail_id_to_custom_guardrail[registered["guardrail_id"]]
|
||||
|
||||
with patch.object(guardrail.async_handler, "post", return_value=_moderation_response(0)) as mock_post:
|
||||
result = await guardrail.apply_guardrail(inputs={"texts": ["hello"]}, request_data={}, input_type="request")
|
||||
|
||||
assert result == {"texts": ["hello"]}
|
||||
assert mock_post.call_args.kwargs["url"] == (
|
||||
f"https://example.cognitiveservices.azure.com/contentsafety/text:analyze?api-version={expected_api_version}"
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue