mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-13 08:52:02 +00:00
Merge 6a2cd8c603 into aeede53112
This commit is contained in:
commit
98bead3985
2 changed files with 123 additions and 5 deletions
|
|
@ -1408,8 +1408,8 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM):
|
|||
super().embedding()
|
||||
try:
|
||||
data: Final = {"model": model, "input": input, **optional_params}
|
||||
max_retries = max_retries or litellm.DEFAULT_MAX_RETRIES
|
||||
if not isinstance(max_retries, int):
|
||||
effective_max_retries: Final = litellm.DEFAULT_MAX_RETRIES if max_retries is None else max_retries
|
||||
if not isinstance(effective_max_retries, int):
|
||||
raise OpenAIError(status_code=422, message="max retries must be an int")
|
||||
## LOGGING
|
||||
logging_obj.pre_call(
|
||||
|
|
@ -1428,7 +1428,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM):
|
|||
api_key=api_key,
|
||||
timeout=timeout,
|
||||
client=client,
|
||||
max_retries=max_retries,
|
||||
max_retries=effective_max_retries,
|
||||
shared_session=shared_session,
|
||||
litellm_params=litellm_params,
|
||||
)
|
||||
|
|
@ -1438,7 +1438,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM):
|
|||
api_key=api_key,
|
||||
api_base=api_base,
|
||||
timeout=timeout,
|
||||
max_retries=max_retries,
|
||||
max_retries=effective_max_retries,
|
||||
client=client,
|
||||
litellm_params=litellm_params,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import os
|
|||
from collections.abc import Awaitable, Callable, Mapping, Sequence
|
||||
from types import ModuleType
|
||||
from typing import Final, Literal, Protocol
|
||||
from unittest.mock import MagicMock, Mock, patch
|
||||
from unittest.mock import AsyncMock, MagicMock, Mock, patch
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
|
@ -1773,6 +1773,124 @@ async def test_async_audio_speech_records_provider_response_headers():
|
|||
_assert_provider_headers_recorded(response)
|
||||
|
||||
|
||||
def _embedding_transport() -> httpx.MockTransport:
|
||||
return httpx.MockTransport(
|
||||
lambda request: httpx.Response(
|
||||
200,
|
||||
json={
|
||||
"object": "list",
|
||||
"model": "embedding-test",
|
||||
"data": [{"object": "embedding", "index": 0, "embedding": [0.1, 0.2]}],
|
||||
"usage": {"prompt_tokens": 1, "total_tokens": 1},
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("max_retries,expected_retries", [(0, 0), (3, 3), (None, litellm.DEFAULT_MAX_RETRIES)])
|
||||
def test_embedding_honors_explicit_retry_limit(max_retries: int | None, expected_retries: int) -> None:
|
||||
with OpenAI(
|
||||
api_key="transport-only",
|
||||
base_url="https://embedding.example/v1",
|
||||
max_retries=7,
|
||||
http_client=httpx.Client(transport=_embedding_transport()),
|
||||
) as client:
|
||||
response: Final = litellm.embedding(
|
||||
model="openai/embedding-test",
|
||||
input=["retry control"],
|
||||
encoding_format="float",
|
||||
client=client,
|
||||
max_retries=max_retries,
|
||||
api_key="transport-only",
|
||||
api_base=str(client.base_url),
|
||||
)
|
||||
|
||||
assert client.max_retries == expected_retries
|
||||
assert response.data == [{"object": "embedding", "index": 0, "embedding": [0.1, 0.2]}]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("max_retries,expected_retries", [(0, 0), (3, 3), (None, litellm.DEFAULT_MAX_RETRIES)])
|
||||
async def test_aembedding_honors_explicit_retry_limit(max_retries: int | None, expected_retries: int) -> None:
|
||||
async with AsyncOpenAI(
|
||||
api_key="transport-only",
|
||||
base_url="https://embedding.example/v1",
|
||||
max_retries=7,
|
||||
http_client=httpx.AsyncClient(transport=_embedding_transport()),
|
||||
) as client:
|
||||
response: Final = await litellm.aembedding(
|
||||
model="openai/embedding-test",
|
||||
input=["retry control"],
|
||||
encoding_format="float",
|
||||
client=client,
|
||||
max_retries=max_retries,
|
||||
api_key="transport-only",
|
||||
api_base=str(client.base_url),
|
||||
)
|
||||
|
||||
assert client.max_retries == expected_retries
|
||||
assert response.data == [{"object": "embedding", "index": 0, "embedding": [0.1, 0.2]}]
|
||||
|
||||
|
||||
def _unavailable_embedding_response(request: httpx.Request) -> httpx.Response:
|
||||
return httpx.Response(503, json={"error": {"message": "temporarily unavailable"}}, request=request)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("max_retries,expected_retries", [(0, 0), (3, 3), (None, litellm.DEFAULT_MAX_RETRIES)])
|
||||
def test_embedding_limits_requests_after_retryable_failure(max_retries: int | None, expected_retries: int) -> None:
|
||||
requests: Final = Mock(side_effect=_unavailable_embedding_response)
|
||||
with (
|
||||
patch("openai._base_client.time.sleep"),
|
||||
OpenAI(
|
||||
api_key="transport-only",
|
||||
base_url="https://embedding.example/v1",
|
||||
max_retries=7,
|
||||
http_client=httpx.Client(transport=httpx.MockTransport(requests)),
|
||||
) as client,
|
||||
pytest.raises(litellm.ServiceUnavailableError) as error,
|
||||
):
|
||||
litellm.embedding(
|
||||
model="openai/embedding-test",
|
||||
input=["retry control"],
|
||||
client=client,
|
||||
max_retries=max_retries,
|
||||
num_retries=0,
|
||||
api_key="transport-only",
|
||||
api_base=str(client.base_url),
|
||||
)
|
||||
|
||||
assert error.value.status_code == 503
|
||||
assert requests.call_count == expected_retries + 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("max_retries,expected_retries", [(0, 0), (3, 3), (None, litellm.DEFAULT_MAX_RETRIES)])
|
||||
async def test_aembedding_limits_requests_after_retryable_failure(
|
||||
max_retries: int | None, expected_retries: int
|
||||
) -> None:
|
||||
requests: Final = Mock(side_effect=_unavailable_embedding_response)
|
||||
with patch("openai._base_client.anyio.sleep", new_callable=AsyncMock):
|
||||
async with AsyncOpenAI(
|
||||
api_key="transport-only",
|
||||
base_url="https://embedding.example/v1",
|
||||
max_retries=7,
|
||||
http_client=httpx.AsyncClient(transport=httpx.MockTransport(requests)),
|
||||
) as client:
|
||||
with pytest.raises(litellm.ServiceUnavailableError) as error:
|
||||
await litellm.aembedding(
|
||||
model="openai/embedding-test",
|
||||
input=["retry control"],
|
||||
client=client,
|
||||
max_retries=max_retries,
|
||||
num_retries=0,
|
||||
api_key="transport-only",
|
||||
api_base=str(client.base_url),
|
||||
)
|
||||
|
||||
assert error.value.status_code == 503
|
||||
assert requests.call_count == expected_retries + 1
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def _vcr_outcome_gate(request, vcr):
|
||||
install_live_call_probe(request, vcr)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue