From 5e83b0a3639c91d8a2ee1cdc8ad693934d237f3f Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Wed, 28 Oct 2026 12:32:35 -0700 Subject: [PATCH] fix(dashscope): keep an explicit compatible-api rerank base as given --- litellm/llms/dashscope/common_utils.py | 13 ++++--- .../test_dashscope_rerank_transformation.py | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/litellm/llms/dashscope/common_utils.py b/litellm/llms/dashscope/common_utils.py index cfcd54bbb80..c0865dfe4c6 100644 --- a/litellm/llms/dashscope/common_utils.py +++ b/litellm/llms/dashscope/common_utils.py @@ -96,12 +96,19 @@ def resolve_dashscope_endpoints(api_base: str | None) -> DashScopeEndpoints | No ) +def _is_compatible_api_base(api_base: str) -> bool: + path: Final = urlparse(api_base).path.rstrip("/") + return path == DASHSCOPE_COMPATIBLE_API_PATH or path.startswith(f"{DASHSCOPE_COMPATIBLE_API_PATH}/") + + def resolve_dashscope_openai_api_base( api_base: str | None, env_var: str = "DASHSCOPE_API_BASE", default: str = f"{DASHSCOPE_DEFAULT_ORIGIN}{DASHSCOPE_CHAT_COMPATIBLE_PATH}", ) -> str: candidate: Final = api_base or get_secret_str(env_var) + if candidate and _is_compatible_api_base(candidate): + return candidate endpoints: Final = resolve_dashscope_endpoints(candidate) if endpoints is not None: return endpoints.openai @@ -146,12 +153,8 @@ def _rerank_origin(api_base: str | None) -> str | None: return endpoints.origin if endpoints is not None else _chat_shaped_aliyun_origin(api_base) -def _is_rerank_url(api_base: str) -> bool: - return urlparse(api_base).path.rstrip("/") == DASHSCOPE_RERANK_PATH - - def resolve_dashscope_family_rerank_api_base(api_base: str | None, env_var: str, default_rerank_base: str) -> str: - if api_base is not None and _is_rerank_url(api_base): + if api_base is not None and _is_compatible_api_base(api_base): return api_base origin: Final = _rerank_origin(api_base) if origin is not None: diff --git a/tests/unit/llms/dashscope/test_dashscope_rerank_transformation.py b/tests/unit/llms/dashscope/test_dashscope_rerank_transformation.py index bdec779558f..f7d4b700242 100644 --- a/tests/unit/llms/dashscope/test_dashscope_rerank_transformation.py +++ b/tests/unit/llms/dashscope/test_dashscope_rerank_transformation.py @@ -8,8 +8,10 @@ from unittest.mock import MagicMock import httpx import pytest +import respx from pydantic import ValidationError +import litellm from litellm.llms.dashscope.common_utils import DashScopeError from litellm.llms.dashscope.rerank.transformation import ( @@ -450,3 +452,35 @@ def test_transform_rerank_response_shape_errors_do_not_echo_the_payload(): _transform({"results": [["leaked document text"]]}) assert "leaked document text" not in str(exc_info.value) + + +@pytest.mark.parametrize( + ("provider", "rerank_env"), + [ + ("dashscope", "DASHSCOPE_API_BASE_RERANK"), + ("qwencloud", "QWENCLOUD_API_BASE_RERANK"), + ("qwen_ai_platform", "QWEN_AI_PLATFORM_API_BASE_RERANK"), + ], +) +@pytest.mark.parametrize( + "api_base", + [ + "https://dashscope-intl.aliyuncs.com/compatible-api/v1/reranks", + "https://dashscope-intl.aliyuncs.com/compatible-api/v1", + ], +) +def test_rerank_sends_an_explicit_compatible_api_base_over_the_rerank_env( + monkeypatch: pytest.MonkeyPatch, provider: str, rerank_env: str, api_base: str +): + monkeypatch.setenv("DASHSCOPE_API_BASE", "https://dashscope-intl.aliyuncs.com") + monkeypatch.setenv(rerank_env, DEFAULT_RERANK_URL) + + with respx.mock(assert_all_called=True) as upstream: + upstream.post("https://dashscope-intl.aliyuncs.com/compatible-api/v1/reranks").respond( + 200, json={"id": "r1", "results": [{"index": 0, "relevance_score": 0.9}], "usage": {"total_tokens": 5}} + ) + response: Final = litellm.rerank( + model=f"{provider}/qwen3-rerank", query="q", documents=["a"], api_base=api_base, api_key="sk-test" + ) + + assert response.results == [{"index": 0, "relevance_score": 0.9}]