mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-13 08:52:02 +00:00
test(router): completion(), anthropic_messages() and the sync responses() retry a 503 the same way
This commit is contained in:
parent
f9cb19ee04
commit
e1cd2cf201
1 changed files with 58 additions and 6 deletions
|
|
@ -1,11 +1,13 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import uuid
|
||||
from collections.abc import Callable
|
||||
from typing import Final
|
||||
|
||||
from integration._support.anthropic_sse import Attempts
|
||||
from integration._support.openai_wire import openai_error, posted_targets, responses_reply
|
||||
import pytest
|
||||
from integration._support.anthropic_sse import Attempts, message_json
|
||||
from integration._support.openai_wire import chat_reply, openai_error, posted_targets, responses_reply
|
||||
from integration._support.wire import Reply, Request, wire_server
|
||||
from litellm import Router
|
||||
from litellm.types.llms.openai import ResponsesAPIResponse
|
||||
|
|
@ -13,13 +15,14 @@ from litellm.types.router import DeploymentTypedDict
|
|||
|
||||
_MODEL: Final = "gpt-5.4"
|
||||
_API_KEY: Final = "sync-responses-retry-test-key"
|
||||
_CLAUDE: Final = "claude-sonnet-4-5"
|
||||
_TEXT: Final = "served after the blip"
|
||||
|
||||
|
||||
def _deployment(model_name: str, api_base: str) -> DeploymentTypedDict:
|
||||
def _deployment(model_name: str, api_base: str, model: str = f"openai/{_MODEL}") -> DeploymentTypedDict:
|
||||
return DeploymentTypedDict(
|
||||
model_name=model_name,
|
||||
litellm_params={"model": f"openai/{_MODEL}", "api_base": api_base, "api_key": _API_KEY},
|
||||
litellm_params={"model": model, "api_base": api_base, "api_key": _API_KEY},
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -28,10 +31,18 @@ def _upstream(fails: Callable[[str, int], bool]) -> Callable[[Request], Reply]:
|
|||
|
||||
def respond(request: Request) -> Reply:
|
||||
group, _, route = request.target.lstrip("/").partition("/")
|
||||
assert (request.method, route) == ("POST", "responses"), request
|
||||
assert request.method == "POST", request
|
||||
if fails(group, attempts.record(group)):
|
||||
return openai_error(503)
|
||||
return responses_reply(f"resp_{group}_{uuid.uuid4().hex}", _MODEL, _TEXT, stream=False)
|
||||
identity: Final = f"{group}_{uuid.uuid4().hex}"
|
||||
match route:
|
||||
case "responses":
|
||||
return responses_reply(f"resp_{identity}", _MODEL, _TEXT, stream=False)
|
||||
case "chat/completions":
|
||||
return chat_reply(f"chatcmpl-{identity}", _MODEL, _TEXT, stream=False)
|
||||
case "v1/messages":
|
||||
return Reply(body=message_json(f"msg_{identity}", _CLAUDE, _TEXT))
|
||||
raise AssertionError(request)
|
||||
|
||||
return respond
|
||||
|
||||
|
|
@ -72,3 +83,44 @@ def test_sync_responses_falls_back_when_the_primary_group_keeps_failing() -> Non
|
|||
|
||||
assert _output_text(response) == _TEXT
|
||||
assert targets == ("/primary/responses", "/backup/responses")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("model", "route", "call"),
|
||||
[
|
||||
pytest.param(
|
||||
f"openai/{_MODEL}",
|
||||
"/my-model/chat/completions",
|
||||
lambda router: router.completion(model="my-model", messages=[{"role": "user", "content": "hi"}]),
|
||||
id="completion",
|
||||
),
|
||||
pytest.param(
|
||||
f"anthropic/{_CLAUDE}",
|
||||
"/my-model/v1/messages",
|
||||
lambda router: asyncio.run(
|
||||
router.anthropic_messages(model="my-model", messages=[{"role": "user", "content": "hi"}], max_tokens=16)
|
||||
),
|
||||
id="anthropic_messages",
|
||||
),
|
||||
pytest.param(
|
||||
f"openai/{_MODEL}",
|
||||
"/my-model/responses",
|
||||
lambda router: router.responses(model="my-model", input="hi"),
|
||||
id="responses",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_every_entry_point_retries_the_group_after_a_503_the_same_way(
|
||||
model: str, route: str, call: Callable[[Router], object]
|
||||
) -> None:
|
||||
with wire_server(_upstream(lambda _group, attempt: attempt == 1)) as wire:
|
||||
router: Final = Router(
|
||||
model_list=[_deployment("my-model", f"{wire.url}/my-model", model)],
|
||||
num_retries=1,
|
||||
retry_after=0,
|
||||
disable_cooldowns=True,
|
||||
)
|
||||
_ = call(router)
|
||||
targets: Final = posted_targets(wire)
|
||||
|
||||
assert targets == (route, route)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue