mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
test(integration): anthropic-route basic translation cases for six Claude models on messages, chat completions and responses (#44607)
* test(integration): add anthropic-route /v1/messages basic cases for haiku-4-5, sonnet-5, opus-4-8 and sonnet-5-5 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): add anthropic-route /v1/chat/completions and /v1/responses basic cases with generated-field matchers Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): skip anthropic-route /v1/responses basic cases on LIT-9231 and expect the echoed request params Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): write LiteLLM-generated ids and timestamps as mock.ANY and drop matchers.py Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: kerry <kerry@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
a99bccacea
commit
14913548d1
14 changed files with 1452 additions and 2 deletions
|
|
@ -1,4 +1,24 @@
|
|||
model_list:
|
||||
- model_name: anthropic/claude-haiku-4-5
|
||||
litellm_params:
|
||||
model: anthropic/claude-haiku-4-5
|
||||
api_base: http://127.0.0.1:8191
|
||||
api_key: synthetic-anthropic-key
|
||||
- model_name: anthropic/claude-sonnet-5
|
||||
litellm_params:
|
||||
model: anthropic/claude-sonnet-5
|
||||
api_base: http://127.0.0.1:8191
|
||||
api_key: synthetic-anthropic-key
|
||||
- model_name: anthropic/claude-opus-4-8
|
||||
litellm_params:
|
||||
model: anthropic/claude-opus-4-8
|
||||
api_base: http://127.0.0.1:8191
|
||||
api_key: synthetic-anthropic-key
|
||||
- model_name: anthropic/claude-sonnet-5-5
|
||||
litellm_params:
|
||||
model: anthropic/claude-sonnet-5-5
|
||||
api_base: http://127.0.0.1:8191
|
||||
api_key: synthetic-anthropic-key
|
||||
- model_name: anthropic/claude-opus-5-5
|
||||
litellm_params:
|
||||
model: anthropic/claude-opus-5-5
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
These tests check one request through the proxy as literals on a `TranslationTestCase`: the `litellm_endpoint` and `litellm_request` the test sends, the `expected_provider_endpoint`, `expected_provider_headers` and `expected_provider_request` the fake provider must receive, the `mock_provider_response` it answers with, and the `expected_litellm_status_code` and `expected_litellm_response` the test must get back. The runner compares the provider request body, every provider header other than transport headers, and the LiteLLM response body in full, so an added, removed, renamed or moved field fails. Folders follow the client endpoint and then the feature, for example `translation/messages/reasoning/`. Each endpoint keeps one complete base case per model in `<endpoint>/bases/<provider>.py`, named `<MODEL>_TEST_CASE` (for example `CLAUDE_SONNET_4_6_TEST_CASE`), which `<endpoint>/basic/` runs on its own. A feature case is `<MODEL>_<SCENARIO>_TEST_CASE = dataclasses.replace(<MODEL>_TEST_CASE, ...)`, imports the base under its own name rather than as `BASE`, and lists only the fields it changes
|
||||
|
||||
Some response fields are generated by LiteLLM on every run, such as a chat completion's `id` and `created` or a response's `id`, `created_at` and output message `id`. A case writes those as `unittest.mock.ANY`, so the field must still be present but any value passes. Use `ANY` only for a value LiteLLM generates, never for one copied from the provider reply
|
||||
|
||||
Deployments used by translation tests are shared by the whole suite and declared in `proxy_config.yaml` under `model_list`, with `model_name` equal to the litellm model string, `api_base: http://127.0.0.1:8191` and a synthetic key. A case names the deployment literally in its client request. The fake provider behind them is the `provider` fixture: one `wire_server` on port 8191 inside the pytest process, started the first time a test asks for it. A test queues its replies with `provider.expect(...)` and reads what the proxy sent with `provider.received()`. Tests that use it run one at a time. After each test the fixture fails if a queued reply was never requested or a received request was never read, and before each test it fails if a request arrived in between, naming the previous test. It refuses to start under pytest-xdist, so the `mcp` and `cost` groups cannot use it. Client requests carry `"cache": {"no-cache": True}` because the proxy caches responses in Redis
|
||||
|
||||
Provider responses in translation cases are captured once from the real provider and stored verbatim. First run the new case against the fake provider; the body the proxy sends is the case's `expected_provider_request`. Send that exact body to the real provider endpoint with a key from the 1Password `Shared` vault (`/qa-keys`), and only store the case when the provider answers 2xx. Keep only the response body and drop every response header, since headers carry account identifiers such as the organization id and rate limits. Never print or save the request headers you sent. Before committing, check the body contains no key and no account identifier, such as an organization id, an AWS account id inside an ARN, a GCP project id or an Azure resource name, and that the prompt is synthetic. Paste the body as the case's `mock_provider_response` without shortening ids, token counts or signatures, and move long opaque values such as thinking signatures into module-level constants used by both `mock_provider_response` and `expected_litellm_response`. Do not commit the script used for the capture
|
||||
|
|
|
|||
|
|
@ -0,0 +1,494 @@
|
|||
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": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzBnuPYc7TdysZFRpo",
|
||||
"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": "anthropic/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": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzH3AcaSNXtvurLgAG",
|
||||
"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": "global",
|
||||
},
|
||||
"diagnostics": None,
|
||||
},
|
||||
expected_litellm_response={
|
||||
"id": ANY,
|
||||
"created": ANY,
|
||||
"model": "anthropic/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": "global",
|
||||
"service_tier": "standard",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
CLAUDE_SONNET_5_TEST_CASE: Final = TranslationTestCase(
|
||||
scenario="basic",
|
||||
litellm_endpoint="/v1/chat/completions",
|
||||
litellm_request={
|
||||
"model": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzPkj2HxBq8qGJsGSi",
|
||||
"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": "anthropic/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": "global",
|
||||
"service_tier": "standard",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
CLAUDE_OPUS_4_8_TEST_CASE: Final = TranslationTestCase(
|
||||
scenario="basic",
|
||||
litellm_endpoint="/v1/chat/completions",
|
||||
litellm_request={
|
||||
"model": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzV9vZCkuQJt15n3Z1",
|
||||
"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": "anthropic/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": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzd9tYt5h3TSZTehYZ",
|
||||
"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": "global",
|
||||
},
|
||||
"diagnostics": None,
|
||||
},
|
||||
expected_litellm_response={
|
||||
"id": ANY,
|
||||
"created": ANY,
|
||||
"model": "anthropic/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": "global",
|
||||
"service_tier": "standard",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
CLAUDE_OPUS_5_5_TEST_CASE: Final = TranslationTestCase(
|
||||
scenario="basic",
|
||||
litellm_endpoint="/v1/chat/completions",
|
||||
litellm_request={
|
||||
"model": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzp3URQ38dAAc8F3RP",
|
||||
"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": "global",
|
||||
},
|
||||
"diagnostics": None,
|
||||
},
|
||||
expected_litellm_response={
|
||||
"id": ANY,
|
||||
"created": ANY,
|
||||
"model": "anthropic/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": "global",
|
||||
"service_tier": "standard",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
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.anthropic 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_anthropic(
|
||||
case: TranslationTestCase, gateway: Gateway, provider: SharedProvider
|
||||
) -> None:
|
||||
run(case, gateway, provider)
|
||||
|
|
@ -137,3 +137,277 @@ CLAUDE_SONNET_4_6_TEST_CASE: Final = TranslationTestCase(
|
|||
"diagnostics": None,
|
||||
},
|
||||
)
|
||||
|
||||
CLAUDE_HAIKU_4_5_TEST_CASE: Final = TranslationTestCase(
|
||||
scenario="basic",
|
||||
litellm_endpoint="/v1/messages",
|
||||
litellm_request={
|
||||
"model": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-key",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json",
|
||||
},
|
||||
expected_provider_request={
|
||||
"model": "claude-haiku-4-5",
|
||||
"max_tokens": 64,
|
||||
"stream": False,
|
||||
"system": "You are a terse assistant.",
|
||||
"messages": [{"role": "user", "content": "Say hello."}],
|
||||
},
|
||||
mock_provider_response={
|
||||
"model": "claude-haiku-4-5-20251001",
|
||||
"id": "msg_011CfgDz9Vj8wXvKzhoM4MQA",
|
||||
"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": "anthropic/claude-haiku-4-5",
|
||||
"id": "msg_011CfgDz9Vj8wXvKzhoM4MQA",
|
||||
"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_5_TEST_CASE: Final = TranslationTestCase(
|
||||
scenario="basic",
|
||||
litellm_endpoint="/v1/messages",
|
||||
litellm_request={
|
||||
"model": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-key",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json",
|
||||
},
|
||||
expected_provider_request={
|
||||
"model": "claude-sonnet-5",
|
||||
"max_tokens": 64,
|
||||
"stream": False,
|
||||
"system": "You are a terse assistant.",
|
||||
"messages": [{"role": "user", "content": "Say hello."}],
|
||||
},
|
||||
mock_provider_response={
|
||||
"model": "claude-sonnet-5",
|
||||
"id": "msg_011CfgDzLXmJmnHRTpeBoDmZ",
|
||||
"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": "anthropic/claude-sonnet-5",
|
||||
"id": "msg_011CfgDzLXmJmnHRTpeBoDmZ",
|
||||
"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_OPUS_4_8_TEST_CASE: Final = TranslationTestCase(
|
||||
scenario="basic",
|
||||
litellm_endpoint="/v1/messages",
|
||||
litellm_request={
|
||||
"model": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-key",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json",
|
||||
},
|
||||
expected_provider_request={
|
||||
"model": "claude-opus-4-8",
|
||||
"max_tokens": 64,
|
||||
"stream": False,
|
||||
"system": "You are a terse assistant.",
|
||||
"messages": [{"role": "user", "content": "Say hello."}],
|
||||
},
|
||||
mock_provider_response={
|
||||
"model": "claude-opus-4-8",
|
||||
"id": "msg_011CfgDzSFYYPC3aYE9rH98J",
|
||||
"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": "anthropic/claude-opus-4-8",
|
||||
"id": "msg_011CfgDzSFYYPC3aYE9rH98J",
|
||||
"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": "anthropic/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="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-key",
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json",
|
||||
},
|
||||
expected_provider_request={
|
||||
"model": "claude-sonnet-5-5",
|
||||
"max_tokens": 64,
|
||||
"stream": False,
|
||||
"system": "You are a terse assistant.",
|
||||
"messages": [{"role": "user", "content": "Say hello."}],
|
||||
},
|
||||
mock_provider_response={
|
||||
"model": "claude-sonnet-5-5",
|
||||
"id": "msg_011CfgDzY6H6Rnp7FC7LsZvm",
|
||||
"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": "global",
|
||||
},
|
||||
"diagnostics": None,
|
||||
},
|
||||
expected_litellm_response={
|
||||
"model": "anthropic/claude-sonnet-5-5",
|
||||
"id": "msg_011CfgDzY6H6Rnp7FC7LsZvm",
|
||||
"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": "global",
|
||||
},
|
||||
"diagnostics": None,
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,10 +2,28 @@ 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.anthropic import CLAUDE_OPUS_5_5_TEST_CASE, CLAUDE_SONNET_4_6_TEST_CASE
|
||||
from integration.translation.messages.bases.anthropic 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_OPUS_5_5_TEST_CASE, CLAUDE_SONNET_4_6_TEST_CASE], ids=lambda case: case.id)
|
||||
@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_anthropic(case: TranslationTestCase, gateway: Gateway, provider: SharedProvider) -> None:
|
||||
run(case, gateway, provider)
|
||||
|
|
|
|||
0
tests/integration/translation/responses/__init__.py
Normal file
0
tests/integration/translation/responses/__init__.py
Normal file
578
tests/integration/translation/responses/bases/anthropic.py
Normal file
578
tests/integration/translation/responses/bases/anthropic.py
Normal file
|
|
@ -0,0 +1,578 @@
|
|||
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": "anthropic/claude-haiku-4-5",
|
||||
"max_output_tokens": 64,
|
||||
"instructions": "You are a terse assistant.",
|
||||
"input": "Say hello.",
|
||||
"cache": {"no-cache": True},
|
||||
},
|
||||
expected_provider_endpoint="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzBnuPYc7TdysZFRpo",
|
||||
"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": "anthropic/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": "anthropic/claude-sonnet-4-6",
|
||||
"max_output_tokens": 64,
|
||||
"instructions": "You are a terse assistant.",
|
||||
"input": "Say hello.",
|
||||
"cache": {"no-cache": True},
|
||||
},
|
||||
expected_provider_endpoint="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzH3AcaSNXtvurLgAG",
|
||||
"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": "global",
|
||||
},
|
||||
"diagnostics": None,
|
||||
},
|
||||
expected_litellm_response={
|
||||
"id": ANY,
|
||||
"created_at": ANY,
|
||||
"error": None,
|
||||
"incomplete_details": None,
|
||||
"instructions": "You are a terse assistant.",
|
||||
"metadata": {},
|
||||
"model": "anthropic/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": "anthropic/claude-sonnet-5",
|
||||
"max_output_tokens": 64,
|
||||
"instructions": "You are a terse assistant.",
|
||||
"input": "Say hello.",
|
||||
"cache": {"no-cache": True},
|
||||
},
|
||||
expected_provider_endpoint="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzPkj2HxBq8qGJsGSi",
|
||||
"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": "anthropic/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": "anthropic/claude-opus-4-8",
|
||||
"max_output_tokens": 64,
|
||||
"instructions": "You are a terse assistant.",
|
||||
"input": "Say hello.",
|
||||
"cache": {"no-cache": True},
|
||||
},
|
||||
expected_provider_endpoint="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzV9vZCkuQJt15n3Z1",
|
||||
"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": "anthropic/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": "anthropic/claude-sonnet-5-5",
|
||||
"max_output_tokens": 64,
|
||||
"instructions": "You are a terse assistant.",
|
||||
"input": "Say hello.",
|
||||
"cache": {"no-cache": True},
|
||||
},
|
||||
expected_provider_endpoint="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzd9tYt5h3TSZTehYZ",
|
||||
"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": "global",
|
||||
},
|
||||
"diagnostics": None,
|
||||
},
|
||||
expected_litellm_response={
|
||||
"id": ANY,
|
||||
"created_at": ANY,
|
||||
"error": None,
|
||||
"incomplete_details": None,
|
||||
"instructions": "You are a terse assistant.",
|
||||
"metadata": {},
|
||||
"model": "anthropic/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": "anthropic/claude-opus-5-5",
|
||||
"max_output_tokens": 64,
|
||||
"instructions": "You are a terse assistant.",
|
||||
"input": "Say hello.",
|
||||
"cache": {"no-cache": True},
|
||||
},
|
||||
expected_provider_endpoint="/v1/messages",
|
||||
expected_provider_headers={
|
||||
"x-api-key": "synthetic-anthropic-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_011CfgDzp3URQ38dAAc8F3RP",
|
||||
"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": "global",
|
||||
},
|
||||
"diagnostics": None,
|
||||
},
|
||||
expected_litellm_response={
|
||||
"id": ANY,
|
||||
"created_at": ANY,
|
||||
"error": None,
|
||||
"incomplete_details": None,
|
||||
"instructions": "You are a terse assistant.",
|
||||
"metadata": {},
|
||||
"model": "anthropic/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},
|
||||
},
|
||||
)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
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.anthropic 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_anthropic(case: TranslationTestCase, gateway: Gateway, provider: SharedProvider) -> None:
|
||||
pytest.skip(
|
||||
"BUG: LIT-9231 the chat-completions bridge returns instructions and max_output_tokens as null"
|
||||
" and temperature as 0.0 instead of echoing the request"
|
||||
)
|
||||
run(case, gateway, provider)
|
||||
Loading…
Add table
Reference in a new issue