test_azure_responses_api_status_error

This commit is contained in:
Ishaan Jaffer 2025-10-11 10:41:15 -07:00
parent 86881a8fc1
commit ce6102d54f
2 changed files with 122 additions and 14 deletions

View file

@ -41,12 +41,10 @@ class AzureOpenAIResponsesAPIConfig(OpenAIResponsesAPIConfig):
def _handle_reasoning_item(self, item: Dict[str, Any]) -> Dict[str, Any]:
"""
Handle reasoning items specifically to filter out status=None using OpenAI's model.
Handle reasoning items to filter out the status field.
Issue: https://github.com/BerriAI/litellm/issues/13484
OpenAI API does not accept ReasoningItem(status=None), so we need to:
1. Check if the item is a reasoning type
2. Create a ResponseReasoningItem object with the item data
3. Convert it back to dict with exclude_none=True to filter None values
Azure OpenAI API does not accept 'status' field in reasoning input items.
"""
if item.get("type") == "reasoning":
try:
@ -82,6 +80,30 @@ class AzureOpenAIResponsesAPIConfig(OpenAIResponsesAPIConfig):
}
return filtered_item
return item
def _validate_input_param(
self, input: Union[str, ResponseInputParam]
) -> Union[str, ResponseInputParam]:
"""
Override parent method to also filter out 'status' field from message items.
Azure OpenAI API does not accept 'status' field in input messages.
"""
# First call parent's validation
validated_input = super()._validate_input_param(input)
# Then filter out status from message items
if isinstance(validated_input, list):
filtered_input = []
for item in validated_input:
if isinstance(item, dict) and item.get("type") == "message":
# Filter out status field from message items
filtered_item = {k: v for k, v in item.items() if k != "status"}
filtered_input.append(filtered_item)
else:
filtered_input.append(item)
return filtered_input # type: ignore
return validated_input
def transform_responses_api_request(
self,

View file

@ -50,9 +50,11 @@ async def test_azure_responses_api_preview_api_version():
@pytest.mark.asyncio
async def test_azure_responses_api_status_error():
"""
Ensure new azure preview api version is working
Test that 'status' field is not sent in the final request body to Azure API.
The status field should be filtered out from input messages before making the API call.
"""
litellm._turn_on_debug()
from unittest.mock import AsyncMock, MagicMock
import json
request_data = {
"model": "computer-use-preview",
@ -88,11 +90,95 @@ async def test_azure_responses_api_status_error():
"stream": False,
"tools": [],
}
response = await litellm.aresponses(
model="azure/computer-use-preview",
truncation="auto",
api_version="preview",
api_base=os.getenv("AZURE_RESPONSES_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_RESPONSES_OPENAI_API_KEY"),
input=request_data["input"],
# Mock response
mock_response_data = {
"id": "resp_123",
"object": "response",
"created_at": 1234567890,
"model": "computer-use-preview",
"status": "completed",
"output": [
{
"id": "msg_123",
"role": "assistant",
"type": "message",
"status": "completed",
"content": [{"type": "output_text", "text": "Here's an interesting fact."}],
}
],
}
captured_request_body = {}
async def mock_post(*args, **kwargs):
# Capture the request body
nonlocal captured_request_body
if "json" in kwargs:
captured_request_body = kwargs["json"]
elif "data" in kwargs:
captured_request_body = json.loads(kwargs["data"])
import httpx
# Create a proper httpx Response object
response_content = json.dumps(mock_response_data).encode("utf-8")
response = httpx.Response(
status_code=200,
headers={"content-type": "application/json"},
content=response_content,
request=httpx.Request(method="POST", url="https://test.openai.azure.com"),
)
return response
from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler
from unittest.mock import patch
with patch.object(AsyncHTTPHandler, "post", new=mock_post):
response = await litellm.aresponses(
model="azure/computer-use-preview",
truncation="auto",
api_version="preview",
api_base="https://test.openai.azure.com",
api_key="test-key",
input=request_data["input"],
)
# Verify that 'status' field is not present in any of the input messages
print("Final request body:", json.dumps(captured_request_body, indent=4, default=str))
assert "input" in captured_request_body, "Request body should contain 'input' field"
expected_input = [
{
"content": "tell me an interesting fact",
"role": "user"
},
{
"id": "rs_0ab687487834d9df0068e462a1b2d88197aabbc832c9ba5316",
"summary": [],
"type": "reasoning"
},
{
"id": "msg_0ab687487834d9df0068e462a1df188197b74b1eef05102c18",
"content": [
{
"annotations": [],
"text": "very good morning",
"type": "output_text",
"logprobs": []
}
],
"role": "assistant",
"type": "message"
},
{
"role": "user",
"content": "tell me another"
}
]
assert captured_request_body["input"] == expected_input, (
f"Request body input should match expected format without 'status' field.\n"
f"Expected: {json.dumps(expected_input, indent=2)}\n"
f"Got: {json.dumps(captured_request_body['input'], indent=2)}"
)