mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-09 22:31:41 +00:00
fix(azure): route image generation and edits through /openai/v1 for v1 api versions
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
ea6ac3dd99
commit
80fd9970c2
4 changed files with 101 additions and 2 deletions
|
|
@ -1113,6 +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={"api_version": api_version},
|
||||
route="/openai/images/generations",
|
||||
)
|
||||
|
||||
if "/openai/deployments/" in api_base:
|
||||
base_url_with_deployment = api_base
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -93,8 +93,6 @@ class AzureImageEditConfig(OpenAIImageEditConfig):
|
|||
raise ValueError(
|
||||
f"api_base is required for Azure AI Studio. Please set the api_base parameter. Passed `api_base={api_base}`"
|
||||
)
|
||||
original_url: Final = httpx.URL(api_base)
|
||||
|
||||
# Resolve api_version: litellm_params > litellm.api_version > AZURE_API_VERSION env > default.
|
||||
# Mirrors the fallback chain used by the Azure chat path in common_utils.py,
|
||||
# so callers that set a global / env api_version don't get an unversioned URL.
|
||||
|
|
@ -105,6 +103,15 @@ 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={"api_version": api_version},
|
||||
route="/openai/images/edits",
|
||||
)
|
||||
|
||||
original_url: Final = httpx.URL(api_base)
|
||||
|
||||
# Create a new dictionary with existing params
|
||||
query_params: Final = dict(original_url.params)
|
||||
|
||||
|
|
|
|||
|
|
@ -233,3 +233,56 @@ 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)
|
||||
config = AzureImageEditConfig()
|
||||
|
||||
for api_version in ("v1", "preview", "latest"):
|
||||
url = config.get_complete_url(
|
||||
model=_FALLBACK_MODEL,
|
||||
api_base=_FALLBACK_API_BASE,
|
||||
litellm_params={"api_version": api_version},
|
||||
)
|
||||
assert urllib.parse.urlparse(url).path == "/openai/v1/images/edits"
|
||||
assert _query_params(url) == {"api-version": api_version}
|
||||
assert config.finalize_image_edit_request_data({"model": _FALLBACK_MODEL, "prompt": "x"}, url) == {
|
||||
"model": _FALLBACK_MODEL,
|
||||
"prompt": "x",
|
||||
}
|
||||
|
||||
|
||||
def test_v1_api_version_from_global_uses_v1_route(monkeypatch):
|
||||
monkeypatch.setattr(litellm, "api_version", "preview", raising=False)
|
||||
monkeypatch.delenv("AZURE_API_VERSION", raising=False)
|
||||
|
||||
url = AzureImageEditConfig().get_complete_url(
|
||||
model=_FALLBACK_MODEL,
|
||||
api_base=_FALLBACK_API_BASE,
|
||||
litellm_params={},
|
||||
)
|
||||
|
||||
assert urllib.parse.urlparse(url).path == "/openai/v1/images/edits"
|
||||
|
||||
|
||||
def test_dated_api_version_still_uses_deployment_route(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=_FALLBACK_API_BASE,
|
||||
litellm_params={"api_version": "2024-10-21"},
|
||||
)
|
||||
|
||||
assert urllib.parse.urlparse(url).path == f"/openai/deployments/{_FALLBACK_MODEL}/images/edits"
|
||||
|
|
|
|||
|
|
@ -433,3 +433,35 @@ async def test_azure_aimage_generation_base_model_vs_deployment_name():
|
|||
wire_json = post_kwargs.get("json") or {}
|
||||
assert "model" not in wire_json
|
||||
assert data.get("model") == base_model
|
||||
|
||||
|
||||
@pytest.mark.parametrize("api_version", ["v1", "preview", "latest"])
|
||||
def test_azure_image_generation_v1_api_version_uses_v1_route(api_version):
|
||||
"""The v1 Azure surface exposes /openai/v1/images/generations and routes by body ``model``."""
|
||||
url = AzureChatCompletion().create_azure_base_url(
|
||||
azure_client_params={
|
||||
"azure_endpoint": "https://my-resource.openai.azure.com",
|
||||
"api_version": api_version,
|
||||
},
|
||||
model="gpt-image-1",
|
||||
base_model=None,
|
||||
)
|
||||
assert url == f"https://my-resource.openai.azure.com/openai/v1/images/generations?api-version={api_version}"
|
||||
data = {"model": "gpt-image-1", "prompt": "x"}
|
||||
assert azure_deployment_image_generation_json_body(url, data) == data
|
||||
|
||||
|
||||
def test_azure_image_generation_dated_api_version_uses_deployment_route():
|
||||
url = AzureChatCompletion().create_azure_base_url(
|
||||
azure_client_params={
|
||||
"azure_endpoint": "https://my-resource.openai.azure.com",
|
||||
"api_version": "2024-10-21",
|
||||
},
|
||||
model="gpt-image-1",
|
||||
base_model=None,
|
||||
)
|
||||
assert (
|
||||
url
|
||||
== "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"})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue