mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-08 22:21:35 +00:00
fix(azure): drop deployment path from api_base when building v1 image routes
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
a6e68b1b0e
commit
5802cf0d8d
5 changed files with 63 additions and 22 deletions
|
|
@ -2,7 +2,6 @@ import asyncio
|
|||
import json
|
||||
import time
|
||||
from collections.abc import Callable, Coroutine
|
||||
from types import MappingProxyType
|
||||
from typing import Any, Final
|
||||
|
||||
import httpx
|
||||
|
|
@ -1114,12 +1113,13 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM):
|
|||
api_version=api_version,
|
||||
)
|
||||
|
||||
if BaseAzureLLM._is_azure_v1_api_version(api_version):
|
||||
return BaseAzureLLM._get_base_azure_url(
|
||||
api_base=api_base,
|
||||
litellm_params=MappingProxyType({"api_version": api_version}),
|
||||
route="/openai/images/generations",
|
||||
)
|
||||
v1_url: Final = BaseAzureLLM.get_azure_v1_image_url(
|
||||
api_base=api_base,
|
||||
api_version=api_version,
|
||||
route="/openai/images/generations",
|
||||
)
|
||||
if v1_url is not None:
|
||||
return v1_url
|
||||
|
||||
if "/openai/deployments/" in api_base:
|
||||
base_url_with_deployment = api_base
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import json
|
|||
import os
|
||||
from collections.abc import Callable, Mapping
|
||||
from functools import lru_cache
|
||||
from types import MappingProxyType
|
||||
from typing import Any, Final, Literal, NamedTuple, cast
|
||||
|
||||
import httpx
|
||||
|
|
@ -789,6 +790,28 @@ class BaseAzureLLM(BaseOpenAILLM):
|
|||
|
||||
return str(final_url)
|
||||
|
||||
@staticmethod
|
||||
def get_azure_v1_image_url(api_base: str, api_version: str | None, route: str) -> str | None:
|
||||
"""
|
||||
Azure's v1 surface serves images at ``/openai/v1/images/{generations,edits}`` and routes by
|
||||
``model`` in the request body, so any deployment path in ``api_base`` has to be dropped.
|
||||
|
||||
Returns None when ``api_version`` is a dated one, which still uses the deployment route.
|
||||
"""
|
||||
if not BaseAzureLLM._is_azure_v1_api_version(api_version):
|
||||
return None
|
||||
|
||||
base_url: Final = httpx.URL(api_base)
|
||||
openai_path_start: Final = base_url.path.find("/openai")
|
||||
resource_base: Final = (
|
||||
api_base if openai_path_start == -1 else str(base_url.copy_with(path=base_url.path[:openai_path_start]))
|
||||
)
|
||||
return BaseAzureLLM._get_base_azure_url(
|
||||
api_base=resource_base,
|
||||
litellm_params=MappingProxyType({"api_version": api_version}),
|
||||
route=route,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _is_azure_v1_api_version(api_version: str | None) -> bool:
|
||||
if api_version is None:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
from types import MappingProxyType
|
||||
from typing import Final, cast
|
||||
|
||||
import httpx
|
||||
|
|
@ -104,12 +103,13 @@ class AzureImageEditConfig(OpenAIImageEditConfig):
|
|||
or litellm.AZURE_DEFAULT_API_VERSION
|
||||
)
|
||||
|
||||
if BaseAzureLLM._is_azure_v1_api_version(api_version):
|
||||
return BaseAzureLLM._get_base_azure_url(
|
||||
api_base=api_base,
|
||||
litellm_params=MappingProxyType({"api_version": api_version}),
|
||||
route="/openai/images/edits",
|
||||
)
|
||||
v1_url: Final = BaseAzureLLM.get_azure_v1_image_url(
|
||||
api_base=api_base,
|
||||
api_version=api_version,
|
||||
route="/openai/images/edits",
|
||||
)
|
||||
if v1_url is not None:
|
||||
return v1_url
|
||||
|
||||
original_url: Final = httpx.URL(api_base)
|
||||
|
||||
|
|
|
|||
|
|
@ -235,14 +235,6 @@ def test_api_version_in_api_base_query_is_preserved(monkeypatch):
|
|||
assert _query_params(url) == {"api-version": "2024-05-01-preview"}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Azure v1 API surface (api_version in {"v1", "preview", "latest"})
|
||||
#
|
||||
# The v1 surface exposes /openai/v1/images/edits and routes by ``model`` in the
|
||||
# multipart form. Building the deployment-scoped path instead makes Azure 404.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_v1_api_version_uses_v1_route_and_keeps_model(monkeypatch):
|
||||
monkeypatch.setattr(litellm, "api_version", None, raising=False)
|
||||
monkeypatch.delenv("AZURE_API_VERSION", raising=False)
|
||||
|
|
@ -286,3 +278,17 @@ def test_dated_api_version_still_uses_deployment_route(monkeypatch):
|
|||
)
|
||||
|
||||
assert urllib.parse.urlparse(url).path == f"/openai/deployments/{_FALLBACK_MODEL}/images/edits"
|
||||
|
||||
|
||||
def test_v1_api_version_replaces_deployment_scoped_api_base(monkeypatch):
|
||||
monkeypatch.setattr(litellm, "api_version", None, raising=False)
|
||||
monkeypatch.delenv("AZURE_API_VERSION", raising=False)
|
||||
|
||||
url = AzureImageEditConfig().get_complete_url(
|
||||
model=_FALLBACK_MODEL,
|
||||
api_base=f"{_FALLBACK_API_BASE}/openai/deployments/{_FALLBACK_MODEL}/images/edits",
|
||||
litellm_params={"api_version": "preview"},
|
||||
)
|
||||
|
||||
assert urllib.parse.urlparse(url).path == "/openai/v1/images/edits"
|
||||
assert _query_params(url) == {"api-version": "preview"}
|
||||
|
|
|
|||
|
|
@ -465,3 +465,15 @@ def test_azure_image_generation_dated_api_version_uses_deployment_route():
|
|||
== "https://my-resource.openai.azure.com/openai/deployments/gpt-image-1/images/generations?api-version=2024-10-21"
|
||||
)
|
||||
assert "model" not in azure_deployment_image_generation_json_body(url, {"model": "gpt-image-1", "prompt": "x"})
|
||||
|
||||
|
||||
def test_azure_image_generation_v1_api_version_replaces_deployment_scoped_api_base():
|
||||
url = AzureChatCompletion().create_azure_base_url(
|
||||
azure_client_params={
|
||||
"azure_endpoint": "https://my-resource.openai.azure.com/openai/deployments/gpt-image-1/images/generations",
|
||||
"api_version": "preview",
|
||||
},
|
||||
model="gpt-image-1",
|
||||
base_model=None,
|
||||
)
|
||||
assert url == "https://my-resource.openai.azure.com/openai/v1/images/generations?api-version=preview"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue