From 655056985602e72e87f4690821c2bd000ef55a9f Mon Sep 17 00:00:00 2001 From: "Md. Asiqur Rahman Khan" Date: Fri, 21 Aug 2026 00:05:39 +0600 Subject: [PATCH] fix: keep gateway model ids intact for OpenAI-compatible embeddings LiteLLMEmbeddingWrapper dropped the provider prefix whenever the resolved provider was openai, so the raw model id reached litellm.embedding() and LiteLLM re-parsed its first path segment as a provider. Gateway model ids that contain a slash were therefore mangled or rejected before the request left the process: nvidia/llama-nemotron-embed-vl-1b-v2:free -> LLM Provider NOT provided auto/embedding -> LLM Provider NOT provided openrouter/openai/text-embedding-3-small -> routed as provider openrouter, forwarded as openai/text-embedding-3-small Always prefix instead, matching LiteLLMChatWrapper, which is why chat models already work against the same endpoints. LiteLLM strips a recognised openai/ prefix and forwards the remainder verbatim, so plain OpenAI model ids resolve exactly as before. --- models.py | 2 +- tests/test_model_config_api_keys.py | 46 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/models.py b/models.py index e1fa5c4230..62f1db31d7 100644 --- a/models.py +++ b/models.py @@ -795,7 +795,7 @@ def __init__( model_config: Optional[ModelConfig] = None, **kwargs: Any, ): - self.model_name = f"{provider}/{model}" if provider != "openai" else model + self.model_name = f"{provider}/{model}" self.kwargs = kwargs self.a0_model_conf = model_config diff --git a/tests/test_model_config_api_keys.py b/tests/test_model_config_api_keys.py index eb779aba12..99e25a799a 100644 --- a/tests/test_model_config_api_keys.py +++ b/tests/test_model_config_api_keys.py @@ -723,6 +723,52 @@ def test_local_provider_runtime_defaults_and_overrides(monkeypatch): assert custom_vllm_chat.kwargs["api_key"] == "real-local-key" +def test_openai_compatible_embedding_keeps_gateway_model_string(monkeypatch): + """Gateway model ids must reach LiteLLM with an explicit `openai/` provider. + + An OpenAI-compatible gateway owns its own model namespace, so ids such as + `nvidia/...` or `auto/embedding` are model names, not provider prefixes. + Without the prefix LiteLLM re-parses the first segment as a provider and + either raises "LLM Provider NOT provided" or routes to the wrong provider, + mangling the model id before the gateway ever sees it. + """ + monkeypatch.setattr(models, "get_api_key", lambda provider: "None") + + gateway = "https://gateway.example/v1" + for model in ( + "nvidia/llama-nemotron-embed-vl-1b-v2:free", + "openrouter/openai/text-embedding-3-small", + "auto/embedding", + ): + embedding = models.get_embedding_model( + "other", model, api_base=gateway, api_key="gateway-key" + ) + assert embedding.model_name == f"openai/{model}" + assert embedding.kwargs["api_base"] == gateway + + # The bundled OpenRouter embedding provider is affected the same way: it + # resolves to litellm_provider `openai` against OpenRouter's api_base, so an + # OpenRouter-style id has to survive intact. Previously `openai/` was + # handed to LiteLLM bare, which consumed the `openai/` segment and forwarded + # only `` to OpenRouter. + for model in ( + "openai/text-embedding-3-small", + "nvidia/llama-nemotron-embed-vl-1b-v2:free", + ): + openrouter_embedding = models.get_embedding_model("openrouter", model) + assert openrouter_embedding.model_name == f"openai/{model}" + assert openrouter_embedding.kwargs["api_base"] == "https://openrouter.ai/api/v1" + + # Plain OpenAI behaviour is unchanged: LiteLLM strips the `openai/` prefix + # and forwards the bare model id, exactly as it did without a prefix. + openai_embedding = models.get_embedding_model("openai", "text-embedding-3-small") + assert openai_embedding.model_name == "openai/text-embedding-3-small" + + # Providers that do not resolve to `openai` keep their existing prefix. + ollama_embedding = models.get_embedding_model("ollama", "nomic-embed-text") + assert ollama_embedding.model_name == "ollama/nomic-embed-text" + + def test_embedding_config_repairs_sentence_transformer_aliases(monkeypatch): from plugins._model_config.helpers import model_config