test(perf): add chat_completions_2rps, responses_2rps and messages_2rps direct vs bridge cases (#47752)

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Kerry Lu 2026-10-20 19:32:03 -07:00 • committed by GitHub
parent f768fb32ef
commit 8d9b9926d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 96 additions and 0 deletions

View file

@ -46,6 +46,11 @@ model_list:
model: openai/gpt-6-luna
api_base: os.environ/E2E_PERF_MOCK_OPENAI_URL
api_key: perf-mock-not-checked
- model_name: gpt-6-luna-responses
litellm_params:
model: openai/responses/gpt-6-luna
api_base: os.environ/E2E_PERF_MOCK_OPENAI_URL
api_key: perf-mock-not-checked
- model_name: claude-sonnet-5
litellm_params:
model: anthropic/claude-sonnet-5
@ -58,6 +63,13 @@ model_list:
aws_region_name: us-east-1
aws_access_key_id: perf-mock-not-checked
aws_secret_access_key: perf-mock-not-checked
- model_name: claude-sonnet-5-bedrock-converse
litellm_params:
model: bedrock/converse/anthropic.claude-sonnet-5
aws_bedrock_runtime_endpoint: os.environ/E2E_PERF_MOCK_BEDROCK_URL
aws_region_name: us-east-1
aws_access_key_id: perf-mock-not-checked
aws_secret_access_key: perf-mock-not-checked
guardrails:
- guardrail_name: perf-pre
litellm_params:

View file

@ -0,0 +1,15 @@
"""`/v1/chat/completions` at 2 rps: `gpt-6-luna` is served by the OpenAI mock's chat completions
route, `gpt-6-luna-responses` (`openai/responses/gpt-6-luna`) is bridged to its Responses route."""
from __future__ import annotations
from typing import Final
from .direct_vs_bridge import direct_vs_bridge
CASE: Final = direct_vs_bridge(
"chat_completions_2rps",
"chat_completions",
direct="gpt-6-luna",
bridge="gpt-6-luna-responses",
)

View file

@ -0,0 +1,31 @@
"""The mixed case's traffic on one public API, half of it on a deployment the gateway serves on
that provider's own API (direct) and half on a deployment it has to translate to another provider
API (bridge). Same 2 rps, request count, shapes, stream share, callers, guardrails and limits as
`mixed_size_requests_2rps`, so a gap between the two halves and the mixed baseline is the
translation's cost."""
from __future__ import annotations
from dataclasses import replace
from setup.performance_test_case import Endpoint, PerformanceTestCase, VirtualKey
from .mixed_size_requests_2rps import CASE as MIXED
def _scoped(key: VirtualKey, direct: str) -> VirtualKey:
return replace(key, models=(direct,)) if key.models else key
def direct_vs_bridge(name: str, endpoint: Endpoint, *, direct: str, bridge: str) -> PerformanceTestCase:
return replace(
MIXED,
name=name,
teams=(
replace(MIXED.team("team-a"), models=(direct, bridge)),
replace(MIXED.team("team-b"), models=(bridge,)),
),
virtual_keys=tuple(_scoped(key, direct) for key in MIXED.virtual_keys),
model_groups=(direct, bridge),
traffic=replace(MIXED.traffic, endpoints={endpoint: 1.0}),
)

View file

@ -0,0 +1,16 @@
"""`/v1/messages` at 2 rps: `claude-sonnet-5` is served by the Anthropic mock's Messages route,
`claude-sonnet-5-bedrock-converse` (`bedrock/converse/anthropic.claude-sonnet-5`) is bridged to the
Bedrock mock's Converse route."""
from __future__ import annotations
from typing import Final
from .direct_vs_bridge import direct_vs_bridge
CASE: Final = direct_vs_bridge(
"messages_2rps",
"messages",
direct="claude-sonnet-5",
bridge="claude-sonnet-5-bedrock-converse",
)

View file

@ -0,0 +1,15 @@
"""`/v1/responses` at 2 rps: `gpt-6-luna` is served by the OpenAI mock's Responses route,
`claude-sonnet-5` is bridged to the Anthropic mock's Messages route."""
from __future__ import annotations
from typing import Final
from .direct_vs_bridge import direct_vs_bridge
CASE: Final = direct_vs_bridge(
"responses_2rps",
"responses",
direct="gpt-6-luna",
bridge="claude-sonnet-5",
)

View file

@ -565,6 +565,7 @@ def _diagnostics(observation: Observation) -> list[str]:
return [
" diagnostics (not limits):",
f" bodies off reply {observation.bodies_off_reply()}",
f" mock routes {_mock_routes(observation)}",
f" guardrail calls per request {len(observation.guardrail_calls) / count:.3f}",
f" guardrail missed {observation.guardrail_missed() if observation.guardrail_calls else 'n/a'}",
f" retried share {len(observation.retried_markers) / count:.4f}",
@ -575,6 +576,12 @@ def _diagnostics(observation: Observation) -> list[str]:
]
def _mock_routes(observation: Observation) -> str:
"""Which provider route each request landed on, so a direct-vs-bridge case shows its split."""
counts: Final = Counter(f"{seen.provider}/{seen.route}" for seen in observation.mock_requests)
return ", ".join(f"{route} {count}" for route, count in sorted(counts.items())) or "n/a"
def _datastore_lines(observation: Observation) -> list[str]:
"""What the per-request Postgres and Redis counts are made of, so a red run names the statement or
command that grew. `plumbing` (BEGIN, COMMIT, session settings) and `unclassified` count in neither limit."""