From d23a0636b410cf9fb6adb9dbb4f6aaa0c7443ef9 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 15:01:55 -0700 Subject: [PATCH] test(integration): azure_ai-route basic translation cases on messages, chat completions and responses (#44658) Co-authored-by: kerry Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- tests/integration/proxy_config.yaml | 30 + .../chat_completions/bases/azure_ai.py | 500 +++++++++++++++ .../test_chat_completions_basic_azure_ai.py | 29 + .../translation/messages/bases/azure_ai.py | 413 +++++++++++++ .../basic/test_messages_basic_azure_ai.py | 29 + .../translation/responses/bases/azure_ai.py | 584 ++++++++++++++++++ .../basic/test_responses_basic_azure_ai.py | 29 + 7 files changed, 1614 insertions(+) create mode 100644 tests/integration/translation/chat_completions/bases/azure_ai.py create mode 100644 tests/integration/translation/chat_completions/basic/test_chat_completions_basic_azure_ai.py create mode 100644 tests/integration/translation/messages/bases/azure_ai.py create mode 100644 tests/integration/translation/messages/basic/test_messages_basic_azure_ai.py create mode 100644 tests/integration/translation/responses/bases/azure_ai.py create mode 100644 tests/integration/translation/responses/basic/test_responses_basic_azure_ai.py diff --git a/tests/integration/proxy_config.yaml b/tests/integration/proxy_config.yaml index a691b155bb2..17ed1d5fb7a 100644 --- a/tests/integration/proxy_config.yaml +++ b/tests/integration/proxy_config.yaml @@ -29,6 +29,36 @@ model_list: model: anthropic/claude-sonnet-4-6 api_base: http://127.0.0.1:8191 api_key: synthetic-anthropic-key + - model_name: azure_ai/claude-haiku-4-5 + litellm_params: + model: azure_ai/claude-haiku-4-5 + api_base: http://127.0.0.1:8191 + api_key: synthetic-azure-ai-key + - model_name: azure_ai/claude-sonnet-4-6 + litellm_params: + model: azure_ai/claude-sonnet-4-6 + api_base: http://127.0.0.1:8191 + api_key: synthetic-azure-ai-key + - model_name: azure_ai/claude-sonnet-5 + litellm_params: + model: azure_ai/claude-sonnet-5 + api_base: http://127.0.0.1:8191 + api_key: synthetic-azure-ai-key + - model_name: azure_ai/claude-opus-4-8 + litellm_params: + model: azure_ai/claude-opus-4-8 + api_base: http://127.0.0.1:8191 + api_key: synthetic-azure-ai-key + - model_name: azure_ai/claude-sonnet-5-5 + litellm_params: + model: azure_ai/claude-sonnet-5-5 + api_base: http://127.0.0.1:8191 + api_key: synthetic-azure-ai-key + - model_name: azure_ai/claude-opus-5-5 + litellm_params: + model: azure_ai/claude-opus-5-5 + api_base: http://127.0.0.1:8191 + api_key: synthetic-azure-ai-key - model_name: bedrock/converse/us.anthropic.claude-haiku-4-5-20251001-v1:0 litellm_params: model: bedrock/converse/us.anthropic.claude-haiku-4-5-20251001-v1:0 diff --git a/tests/integration/translation/chat_completions/bases/azure_ai.py b/tests/integration/translation/chat_completions/bases/azure_ai.py new file mode 100644 index 00000000000..a8cad1ba5ce --- /dev/null +++ b/tests/integration/translation/chat_completions/bases/azure_ai.py @@ -0,0 +1,500 @@ +from typing import Final +from unittest.mock import ANY + +from integration.translation.case import TranslationTestCase + +CLAUDE_HAIKU_4_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/chat/completions", + litellm_request={ + "model": "azure_ai/claude-haiku-4-5", + "max_tokens": 64, + "messages": [ + {"role": "system", "content": "You are a terse assistant."}, + {"role": "user", "content": "Say hello."}, + ], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-haiku-4-5", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-haiku-4-5-20251001", + "id": "msg_011Cfjax6mBrNVhFGQopmVCp", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 17, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 5, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created": ANY, + "model": "azure_ai/claude-haiku-4-5", + "object": "chat.completion", + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": { + "content": "Hello.", + "role": "assistant", + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, + } + ], + "usage": { + "completion_tokens": 5, + "prompt_tokens": 17, + "total_tokens": 22, + "completion_tokens_details": {"reasoning_tokens": 0, "text_tokens": 5}, + "prompt_tokens_details": { + "cached_tokens": 0, + "text_tokens": 17, + "cache_write_tokens": 0, + "cache_creation_tokens": 0, + "cache_creation_token_details": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + }, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "inference_geo": "not_available", + "service_tier": "standard", + }, + }, +) + +CLAUDE_SONNET_4_6_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/chat/completions", + litellm_request={ + "model": "azure_ai/claude-sonnet-4-6", + "max_tokens": 64, + "messages": [ + {"role": "system", "content": "You are a terse assistant."}, + {"role": "user", "content": "Say hello."}, + ], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-sonnet-4-6", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-sonnet-4-6", + "id": "msg_011CfjaxGKedCbjtb7HuAUBC", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello!"}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 18, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 5, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created": ANY, + "model": "azure_ai/claude-sonnet-4-6", + "object": "chat.completion", + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": { + "content": "Hello!", + "role": "assistant", + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, + } + ], + "usage": { + "completion_tokens": 5, + "prompt_tokens": 18, + "total_tokens": 23, + "completion_tokens_details": {"reasoning_tokens": 0, "text_tokens": 5}, + "prompt_tokens_details": { + "cached_tokens": 0, + "text_tokens": 18, + "cache_write_tokens": 0, + "cache_creation_tokens": 0, + "cache_creation_token_details": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + }, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "inference_geo": "not_available", + "service_tier": "standard", + }, + }, +) + +CLAUDE_SONNET_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/chat/completions", + litellm_request={ + "model": "azure_ai/claude-sonnet-5", + "max_tokens": 64, + "messages": [ + {"role": "system", "content": "You are a terse assistant."}, + {"role": "user", "content": "Say hello."}, + ], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-sonnet-5", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-sonnet-5", + "id": "msg_011CfjaxuLcxiEd4m9YZqXaA", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 21, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created": ANY, + "model": "azure_ai/claude-sonnet-5", + "object": "chat.completion", + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": { + "content": "Hello.", + "role": "assistant", + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, + } + ], + "usage": { + "completion_tokens": 6, + "prompt_tokens": 21, + "total_tokens": 27, + "completion_tokens_details": {"reasoning_tokens": 0, "text_tokens": 6}, + "prompt_tokens_details": { + "cached_tokens": 0, + "text_tokens": 21, + "cache_write_tokens": 0, + "cache_creation_tokens": 0, + "cache_creation_token_details": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + }, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "inference_geo": "not_available", + "service_tier": "standard", + }, + }, +) + +CLAUDE_OPUS_4_8_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/chat/completions", + litellm_request={ + "model": "azure_ai/claude-opus-4-8", + "max_tokens": 64, + "messages": [ + {"role": "system", "content": "You are a terse assistant."}, + {"role": "user", "content": "Say hello."}, + ], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-opus-4-8", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-opus-4-8", + "id": "msg_011CfjaxUiYCUsqMC4iqfc2U", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 21, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "global", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created": ANY, + "model": "azure_ai/claude-opus-4-8", + "object": "chat.completion", + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": { + "content": "Hello.", + "role": "assistant", + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, + } + ], + "usage": { + "completion_tokens": 6, + "prompt_tokens": 21, + "total_tokens": 27, + "completion_tokens_details": {"reasoning_tokens": 0, "text_tokens": 6}, + "prompt_tokens_details": { + "cached_tokens": 0, + "text_tokens": 21, + "cache_write_tokens": 0, + "cache_creation_tokens": 0, + "cache_creation_token_details": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + }, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "inference_geo": "global", + "service_tier": "standard", + }, + }, +) + +CLAUDE_SONNET_5_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/chat/completions", + litellm_request={ + "model": "azure_ai/claude-sonnet-5-5", + "max_tokens": 64, + "messages": [ + {"role": "system", "content": "You are a terse assistant."}, + {"role": "user", "content": "Say hello."}, + ], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-sonnet-5-5", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-sonnet-5-5", + "id": "msg_011CfjayBjr8GfdBPi3hbif2", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 23, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created": ANY, + "model": "azure_ai/claude-sonnet-5-5", + "object": "chat.completion", + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": { + "content": "Hello.", + "role": "assistant", + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, + } + ], + "usage": { + "completion_tokens": 6, + "prompt_tokens": 23, + "total_tokens": 29, + "completion_tokens_details": {"reasoning_tokens": 0, "text_tokens": 6}, + "prompt_tokens_details": { + "cached_tokens": 0, + "text_tokens": 23, + "cache_write_tokens": 0, + "cache_creation_tokens": 0, + "cache_creation_token_details": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + }, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "inference_geo": "not_available", + "service_tier": "standard", + }, + }, +) + +CLAUDE_OPUS_5_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/chat/completions", + litellm_request={ + "model": "azure_ai/claude-opus-5-5", + "max_tokens": 64, + "messages": [ + {"role": "system", "content": "You are a terse assistant."}, + {"role": "user", "content": "Say hello."}, + ], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-opus-5-5", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-opus-5-5", + "id": "msg_011CfjayXnc5jLujSNNoJpS2", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 23, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created": ANY, + "model": "azure_ai/claude-opus-5-5", + "object": "chat.completion", + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": { + "content": "Hello.", + "role": "assistant", + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, + } + ], + "usage": { + "completion_tokens": 6, + "prompt_tokens": 23, + "total_tokens": 29, + "completion_tokens_details": {"reasoning_tokens": 0, "text_tokens": 6}, + "prompt_tokens_details": { + "cached_tokens": 0, + "text_tokens": 23, + "cache_write_tokens": 0, + "cache_creation_tokens": 0, + "cache_creation_token_details": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + }, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "inference_geo": "not_available", + "service_tier": "standard", + }, + }, +) diff --git a/tests/integration/translation/chat_completions/basic/test_chat_completions_basic_azure_ai.py b/tests/integration/translation/chat_completions/basic/test_chat_completions_basic_azure_ai.py new file mode 100644 index 00000000000..7696d1c8654 --- /dev/null +++ b/tests/integration/translation/chat_completions/basic/test_chat_completions_basic_azure_ai.py @@ -0,0 +1,29 @@ +import pytest +from integration._support.client import Gateway +from integration._support.provider import SharedProvider +from integration.translation.case import TranslationTestCase +from integration.translation.chat_completions.bases.azure_ai import ( + CLAUDE_HAIKU_4_5_TEST_CASE, + CLAUDE_OPUS_4_8_TEST_CASE, + CLAUDE_OPUS_5_5_TEST_CASE, + CLAUDE_SONNET_4_6_TEST_CASE, + CLAUDE_SONNET_5_5_TEST_CASE, + CLAUDE_SONNET_5_TEST_CASE, +) +from integration.translation.runner import run + + +@pytest.mark.parametrize( + "case", + [ + CLAUDE_HAIKU_4_5_TEST_CASE, + CLAUDE_SONNET_4_6_TEST_CASE, + CLAUDE_SONNET_5_TEST_CASE, + CLAUDE_OPUS_4_8_TEST_CASE, + CLAUDE_SONNET_5_5_TEST_CASE, + CLAUDE_OPUS_5_5_TEST_CASE, + ], + ids=lambda case: case.id, +) +def test_chat_completions_basic_azure_ai(case: TranslationTestCase, gateway: Gateway, provider: SharedProvider) -> None: + run(case, gateway, provider) diff --git a/tests/integration/translation/messages/bases/azure_ai.py b/tests/integration/translation/messages/bases/azure_ai.py new file mode 100644 index 00000000000..6a65ca26421 --- /dev/null +++ b/tests/integration/translation/messages/bases/azure_ai.py @@ -0,0 +1,413 @@ +from typing import Final + +from integration.translation.case import TranslationTestCase + +CLAUDE_HAIKU_4_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/messages", + litellm_request={ + "model": "azure_ai/claude-haiku-4-5", + "max_tokens": 64, + "system": "You are a terse assistant.", + "messages": [{"role": "user", "content": "Say hello."}], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-haiku-4-5", + "max_tokens": 64, + "stream": False, + "system": [{"type": "text", "text": "You are a terse assistant."}], + "messages": [{"role": "user", "content": "Say hello."}], + }, + mock_provider_response={ + "model": "claude-haiku-4-5-20251001", + "id": "msg_011Cfjax2zxeHkddgerkEGRY", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 17, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 5, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "model": "azure_ai/claude-haiku-4-5", + "id": "msg_011Cfjax2zxeHkddgerkEGRY", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 17, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 5, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, +) + +CLAUDE_SONNET_4_6_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/messages", + litellm_request={ + "model": "azure_ai/claude-sonnet-4-6", + "max_tokens": 64, + "system": "You are a terse assistant.", + "messages": [{"role": "user", "content": "Say hello."}], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-sonnet-4-6", + "max_tokens": 64, + "stream": False, + "system": [{"type": "text", "text": "You are a terse assistant."}], + "messages": [{"role": "user", "content": "Say hello."}], + }, + mock_provider_response={ + "model": "claude-sonnet-4-6", + "id": "msg_011CfjaxAknNm3ZLkVxQRj8M", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello!"}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 18, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 5, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "model": "azure_ai/claude-sonnet-4-6", + "id": "msg_011CfjaxAknNm3ZLkVxQRj8M", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello!"}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 18, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 5, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, +) + +CLAUDE_SONNET_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/messages", + litellm_request={ + "model": "azure_ai/claude-sonnet-5", + "max_tokens": 64, + "system": "You are a terse assistant.", + "messages": [{"role": "user", "content": "Say hello."}], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-sonnet-5", + "max_tokens": 64, + "stream": False, + "system": [{"type": "text", "text": "You are a terse assistant."}], + "messages": [{"role": "user", "content": "Say hello."}], + }, + mock_provider_response={ + "model": "claude-sonnet-5", + "id": "msg_011Cfjaxm5HXLX7FBu38pDBJ", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 21, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "model": "azure_ai/claude-sonnet-5", + "id": "msg_011Cfjaxm5HXLX7FBu38pDBJ", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 21, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, +) + +CLAUDE_OPUS_4_8_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/messages", + litellm_request={ + "model": "azure_ai/claude-opus-4-8", + "max_tokens": 64, + "system": "You are a terse assistant.", + "messages": [{"role": "user", "content": "Say hello."}], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-opus-4-8", + "max_tokens": 64, + "stream": False, + "system": [{"type": "text", "text": "You are a terse assistant."}], + "messages": [{"role": "user", "content": "Say hello."}], + }, + mock_provider_response={ + "model": "claude-opus-4-8", + "id": "msg_011CfjaxPE8FBKSJ9KbtQzDE", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 21, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "global", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "model": "azure_ai/claude-opus-4-8", + "id": "msg_011CfjaxPE8FBKSJ9KbtQzDE", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 21, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "global", + }, + "diagnostics": None, + }, +) + +CLAUDE_SONNET_5_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/messages", + litellm_request={ + "model": "azure_ai/claude-sonnet-5-5", + "max_tokens": 64, + "system": "You are a terse assistant.", + "messages": [{"role": "user", "content": "Say hello."}], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-sonnet-5-5", + "max_tokens": 64, + "stream": False, + "system": [{"type": "text", "text": "You are a terse assistant."}], + "messages": [{"role": "user", "content": "Say hello."}], + }, + mock_provider_response={ + "model": "claude-sonnet-5-5", + "id": "msg_011Cfjay3Wzxnz5vkMFngMey", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 23, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "model": "azure_ai/claude-sonnet-5-5", + "id": "msg_011Cfjay3Wzxnz5vkMFngMey", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 23, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, +) + +CLAUDE_OPUS_5_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/messages", + litellm_request={ + "model": "azure_ai/claude-opus-5-5", + "max_tokens": 64, + "system": "You are a terse assistant.", + "messages": [{"role": "user", "content": "Say hello."}], + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-opus-5-5", + "max_tokens": 64, + "stream": False, + "system": [{"type": "text", "text": "You are a terse assistant."}], + "messages": [{"role": "user", "content": "Say hello."}], + }, + mock_provider_response={ + "model": "claude-opus-5-5", + "id": "msg_011CfjayNQ3rbTgxNGMRusPa", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 23, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "model": "azure_ai/claude-opus-5-5", + "id": "msg_011CfjayNQ3rbTgxNGMRusPa", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 23, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, +) diff --git a/tests/integration/translation/messages/basic/test_messages_basic_azure_ai.py b/tests/integration/translation/messages/basic/test_messages_basic_azure_ai.py new file mode 100644 index 00000000000..f8f8cdbb480 --- /dev/null +++ b/tests/integration/translation/messages/basic/test_messages_basic_azure_ai.py @@ -0,0 +1,29 @@ +import pytest +from integration._support.client import Gateway +from integration._support.provider import SharedProvider +from integration.translation.case import TranslationTestCase +from integration.translation.messages.bases.azure_ai import ( + CLAUDE_HAIKU_4_5_TEST_CASE, + CLAUDE_OPUS_4_8_TEST_CASE, + CLAUDE_OPUS_5_5_TEST_CASE, + CLAUDE_SONNET_4_6_TEST_CASE, + CLAUDE_SONNET_5_5_TEST_CASE, + CLAUDE_SONNET_5_TEST_CASE, +) +from integration.translation.runner import run + + +@pytest.mark.parametrize( + "case", + [ + CLAUDE_HAIKU_4_5_TEST_CASE, + CLAUDE_SONNET_4_6_TEST_CASE, + CLAUDE_SONNET_5_TEST_CASE, + CLAUDE_OPUS_4_8_TEST_CASE, + CLAUDE_SONNET_5_5_TEST_CASE, + CLAUDE_OPUS_5_5_TEST_CASE, + ], + ids=lambda case: case.id, +) +def test_messages_basic_azure_ai(case: TranslationTestCase, gateway: Gateway, provider: SharedProvider) -> None: + run(case, gateway, provider) diff --git a/tests/integration/translation/responses/bases/azure_ai.py b/tests/integration/translation/responses/bases/azure_ai.py new file mode 100644 index 00000000000..6d1a2fb94e4 --- /dev/null +++ b/tests/integration/translation/responses/bases/azure_ai.py @@ -0,0 +1,584 @@ +from typing import Final +from unittest.mock import ANY + +from integration.translation.case import TranslationTestCase + +CLAUDE_HAIKU_4_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/responses", + litellm_request={ + "model": "azure_ai/claude-haiku-4-5", + "max_output_tokens": 64, + "instructions": "You are a terse assistant.", + "input": "Say hello.", + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-haiku-4-5", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-haiku-4-5-20251001", + "id": "msg_011Cfjax6mBrNVhFGQopmVCp", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 17, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 5, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created_at": ANY, + "error": None, + "incomplete_details": None, + "instructions": "You are a terse assistant.", + "metadata": {}, + "model": "azure_ai/claude-haiku-4-5", + "object": "response", + "output": [ + { + "type": "message", + "id": ANY, + "status": "completed", + "role": "assistant", + "content": [{"type": "output_text", "text": "Hello.", "annotations": []}], + "phase": None, + } + ], + "parallel_tool_calls": False, + "temperature": None, + "tool_choice": "auto", + "tools": [], + "top_p": None, + "max_output_tokens": 64, + "previous_response_id": None, + "reasoning": None, + "status": "completed", + "text": {}, + "truncation": None, + "usage": { + "input_tokens": 17, + "input_tokens_details": { + "audio_tokens": None, + "cached_tokens": 0, + "cached_tokens_details": None, + "image_tokens": None, + "text_tokens": 17, + "video_tokens": None, + "cache_write_tokens": 0, + }, + "output_tokens": 5, + "output_tokens_details": {"audio_tokens": None, "reasoning_tokens": 0, "text_tokens": 5}, + "total_tokens": 22, + "cost": None, + }, + "user": None, + "store": None, + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, +) + +CLAUDE_SONNET_4_6_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/responses", + litellm_request={ + "model": "azure_ai/claude-sonnet-4-6", + "max_output_tokens": 64, + "instructions": "You are a terse assistant.", + "input": "Say hello.", + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-sonnet-4-6", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-sonnet-4-6", + "id": "msg_011CfjaxGKedCbjtb7HuAUBC", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello!"}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 18, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 5, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created_at": ANY, + "error": None, + "incomplete_details": None, + "instructions": "You are a terse assistant.", + "metadata": {}, + "model": "azure_ai/claude-sonnet-4-6", + "object": "response", + "output": [ + { + "type": "message", + "id": ANY, + "status": "completed", + "role": "assistant", + "content": [{"type": "output_text", "text": "Hello!", "annotations": []}], + "phase": None, + } + ], + "parallel_tool_calls": False, + "temperature": None, + "tool_choice": "auto", + "tools": [], + "top_p": None, + "max_output_tokens": 64, + "previous_response_id": None, + "reasoning": None, + "status": "completed", + "text": {}, + "truncation": None, + "usage": { + "input_tokens": 18, + "input_tokens_details": { + "audio_tokens": None, + "cached_tokens": 0, + "cached_tokens_details": None, + "image_tokens": None, + "text_tokens": 18, + "video_tokens": None, + "cache_write_tokens": 0, + }, + "output_tokens": 5, + "output_tokens_details": {"audio_tokens": None, "reasoning_tokens": 0, "text_tokens": 5}, + "total_tokens": 23, + "cost": None, + }, + "user": None, + "store": None, + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, +) + +CLAUDE_SONNET_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/responses", + litellm_request={ + "model": "azure_ai/claude-sonnet-5", + "max_output_tokens": 64, + "instructions": "You are a terse assistant.", + "input": "Say hello.", + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-sonnet-5", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-sonnet-5", + "id": "msg_011CfjaxuLcxiEd4m9YZqXaA", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 21, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created_at": ANY, + "error": None, + "incomplete_details": None, + "instructions": "You are a terse assistant.", + "metadata": {}, + "model": "azure_ai/claude-sonnet-5", + "object": "response", + "output": [ + { + "type": "message", + "id": ANY, + "status": "completed", + "role": "assistant", + "content": [{"type": "output_text", "text": "Hello.", "annotations": []}], + "phase": None, + } + ], + "parallel_tool_calls": False, + "temperature": None, + "tool_choice": "auto", + "tools": [], + "top_p": None, + "max_output_tokens": 64, + "previous_response_id": None, + "reasoning": None, + "status": "completed", + "text": {}, + "truncation": None, + "usage": { + "input_tokens": 21, + "input_tokens_details": { + "audio_tokens": None, + "cached_tokens": 0, + "cached_tokens_details": None, + "image_tokens": None, + "text_tokens": 21, + "video_tokens": None, + "cache_write_tokens": 0, + }, + "output_tokens": 6, + "output_tokens_details": {"audio_tokens": None, "reasoning_tokens": 0, "text_tokens": 6}, + "total_tokens": 27, + "cost": None, + }, + "user": None, + "store": None, + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, +) + +CLAUDE_OPUS_4_8_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/responses", + litellm_request={ + "model": "azure_ai/claude-opus-4-8", + "max_output_tokens": 64, + "instructions": "You are a terse assistant.", + "input": "Say hello.", + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-opus-4-8", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-opus-4-8", + "id": "msg_011CfjaxUiYCUsqMC4iqfc2U", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 21, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "global", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created_at": ANY, + "error": None, + "incomplete_details": None, + "instructions": "You are a terse assistant.", + "metadata": {}, + "model": "azure_ai/claude-opus-4-8", + "object": "response", + "output": [ + { + "type": "message", + "id": ANY, + "status": "completed", + "role": "assistant", + "content": [{"type": "output_text", "text": "Hello.", "annotations": []}], + "phase": None, + } + ], + "parallel_tool_calls": False, + "temperature": None, + "tool_choice": "auto", + "tools": [], + "top_p": None, + "max_output_tokens": 64, + "previous_response_id": None, + "reasoning": None, + "status": "completed", + "text": {}, + "truncation": None, + "usage": { + "input_tokens": 21, + "input_tokens_details": { + "audio_tokens": None, + "cached_tokens": 0, + "cached_tokens_details": None, + "image_tokens": None, + "text_tokens": 21, + "video_tokens": None, + "cache_write_tokens": 0, + }, + "output_tokens": 6, + "output_tokens_details": {"audio_tokens": None, "reasoning_tokens": 0, "text_tokens": 6}, + "total_tokens": 27, + "cost": None, + }, + "user": None, + "store": None, + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, +) + +CLAUDE_SONNET_5_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/responses", + litellm_request={ + "model": "azure_ai/claude-sonnet-5-5", + "max_output_tokens": 64, + "instructions": "You are a terse assistant.", + "input": "Say hello.", + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-sonnet-5-5", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-sonnet-5-5", + "id": "msg_011CfjayBjr8GfdBPi3hbif2", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 23, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created_at": ANY, + "error": None, + "incomplete_details": None, + "instructions": "You are a terse assistant.", + "metadata": {}, + "model": "azure_ai/claude-sonnet-5-5", + "object": "response", + "output": [ + { + "type": "message", + "id": ANY, + "status": "completed", + "role": "assistant", + "content": [{"type": "output_text", "text": "Hello.", "annotations": []}], + "phase": None, + } + ], + "parallel_tool_calls": False, + "temperature": None, + "tool_choice": "auto", + "tools": [], + "top_p": None, + "max_output_tokens": 64, + "previous_response_id": None, + "reasoning": None, + "status": "completed", + "text": {}, + "truncation": None, + "usage": { + "input_tokens": 23, + "input_tokens_details": { + "audio_tokens": None, + "cached_tokens": 0, + "cached_tokens_details": None, + "image_tokens": None, + "text_tokens": 23, + "video_tokens": None, + "cache_write_tokens": 0, + }, + "output_tokens": 6, + "output_tokens_details": {"audio_tokens": None, "reasoning_tokens": 0, "text_tokens": 6}, + "total_tokens": 29, + "cost": None, + }, + "user": None, + "store": None, + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, +) + +CLAUDE_OPUS_5_5_TEST_CASE: Final = TranslationTestCase( + scenario="basic", + litellm_endpoint="/v1/responses", + litellm_request={ + "model": "azure_ai/claude-opus-5-5", + "max_output_tokens": 64, + "instructions": "You are a terse assistant.", + "input": "Say hello.", + "cache": {"no-cache": True}, + }, + expected_provider_endpoint="/anthropic/v1/messages", + expected_provider_headers={ + "x-api-key": "synthetic-azure-ai-key", + "api-key": "synthetic-azure-ai-key", + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + expected_provider_request={ + "model": "claude-opus-5-5", + "messages": [{"role": "user", "content": [{"type": "text", "text": "Say hello."}]}], + "max_tokens": 64, + "system": [{"type": "text", "text": "You are a terse assistant."}], + }, + mock_provider_response={ + "model": "claude-opus-5-5", + "id": "msg_011CfjayXnc5jLujSNNoJpS2", + "type": "message", + "role": "assistant", + "content": [{"type": "text", "text": "Hello."}], + "container": None, + "stop_reason": "end_turn", + "stop_sequence": None, + "stop_details": None, + "usage": { + "input_tokens": 23, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, + "output_tokens": 6, + "output_tokens_details": {"thinking_tokens": 0}, + "service_tier": "standard", + "inference_geo": "not_available", + }, + "diagnostics": None, + }, + expected_litellm_response={ + "id": ANY, + "created_at": ANY, + "error": None, + "incomplete_details": None, + "instructions": "You are a terse assistant.", + "metadata": {}, + "model": "azure_ai/claude-opus-5-5", + "object": "response", + "output": [ + { + "type": "message", + "id": ANY, + "status": "completed", + "role": "assistant", + "content": [{"type": "output_text", "text": "Hello.", "annotations": []}], + "phase": None, + } + ], + "parallel_tool_calls": False, + "temperature": None, + "tool_choice": "auto", + "tools": [], + "top_p": None, + "max_output_tokens": 64, + "previous_response_id": None, + "reasoning": None, + "status": "completed", + "text": {}, + "truncation": None, + "usage": { + "input_tokens": 23, + "input_tokens_details": { + "audio_tokens": None, + "cached_tokens": 0, + "cached_tokens_details": None, + "image_tokens": None, + "text_tokens": 23, + "video_tokens": None, + "cache_write_tokens": 0, + }, + "output_tokens": 6, + "output_tokens_details": {"audio_tokens": None, "reasoning_tokens": 0, "text_tokens": 6}, + "total_tokens": 29, + "cost": None, + }, + "user": None, + "store": None, + "provider_specific_fields": {"citations": None, "thinking_blocks": None}, + }, +) diff --git a/tests/integration/translation/responses/basic/test_responses_basic_azure_ai.py b/tests/integration/translation/responses/basic/test_responses_basic_azure_ai.py new file mode 100644 index 00000000000..95f4ec91153 --- /dev/null +++ b/tests/integration/translation/responses/basic/test_responses_basic_azure_ai.py @@ -0,0 +1,29 @@ +import pytest +from integration._support.client import Gateway +from integration._support.provider import SharedProvider +from integration.translation.case import TranslationTestCase +from integration.translation.responses.bases.azure_ai import ( + CLAUDE_HAIKU_4_5_TEST_CASE, + CLAUDE_OPUS_4_8_TEST_CASE, + CLAUDE_OPUS_5_5_TEST_CASE, + CLAUDE_SONNET_4_6_TEST_CASE, + CLAUDE_SONNET_5_5_TEST_CASE, + CLAUDE_SONNET_5_TEST_CASE, +) +from integration.translation.runner import run + + +@pytest.mark.parametrize( + "case", + [ + CLAUDE_HAIKU_4_5_TEST_CASE, + CLAUDE_SONNET_4_6_TEST_CASE, + CLAUDE_SONNET_5_TEST_CASE, + CLAUDE_OPUS_4_8_TEST_CASE, + CLAUDE_SONNET_5_5_TEST_CASE, + CLAUDE_OPUS_5_5_TEST_CASE, + ], + ids=lambda case: case.id, +) +def test_responses_basic_azure_ai(case: TranslationTestCase, gateway: Gateway, provider: SharedProvider) -> None: + run(case, gateway, provider)