diff --git a/litellm/llms/jina_ai/embedding/transformation.py b/litellm/llms/jina_ai/embedding/transformation.py index 8f84c9ce3e1..26f512979e5 100644 --- a/litellm/llms/jina_ai/embedding/transformation.py +++ b/litellm/llms/jina_ai/embedding/transformation.py @@ -82,10 +82,7 @@ class JinaAIEmbeddingConfig(BaseEmbeddingConfig): """ api_base = api_base or get_secret_str("JINA_AI_API_BASE") or "https://api.jina.ai/v1" dynamic_api_key: Final = api_key or ( - get_secret_str("JINA_AI_API_KEY") - or get_secret_str("JINA_AI_API_KEY") - or get_secret_str("JINA_AI_API_KEY") - or get_secret_str("JINA_AI_TOKEN") + get_secret_str("JINA_AI_API_KEY") or get_secret_str("JINA_API_KEY") or get_secret_str("JINA_AI_TOKEN") ) return LlmProviders.JINA_AI.value, api_base, dynamic_api_key diff --git a/tests/test_litellm/llms/jina_ai/embedding/test_jina_embedding_transformation.py b/tests/test_litellm/llms/jina_ai/embedding/test_jina_embedding_transformation.py index 715d12043d0..9e761817ef5 100644 --- a/tests/test_litellm/llms/jina_ai/embedding/test_jina_embedding_transformation.py +++ b/tests/test_litellm/llms/jina_ai/embedding/test_jina_embedding_transformation.py @@ -2,12 +2,20 @@ import os import sys from unittest.mock import MagicMock -sys.path.insert( - 0, os.path.abspath("../../../../../..") -) # Adds the parent directory to the system path +import pytest + +sys.path.insert(0, os.path.abspath("../../../../../..")) # Adds the parent directory to the system path from litellm.llms.jina_ai.embedding.transformation import JinaAIEmbeddingConfig +JINA_KEY_ENV_NAMES = ("JINA_AI_API_KEY", "JINA_API_KEY", "JINA_AI_TOKEN") + + +@pytest.fixture +def no_jina_env(monkeypatch: pytest.MonkeyPatch) -> None: + for name in JINA_KEY_ENV_NAMES: + monkeypatch.delenv(name, raising=False) + class TestJinaAIEmbeddingTransform: def setup_method(self): @@ -54,9 +62,7 @@ class TestJinaAIEmbeddingTransform: headers={}, ) expected_input = [ - { - "image": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" - } + {"image": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="} ] expected_result = { "model": self.model, @@ -64,6 +70,50 @@ class TestJinaAIEmbeddingTransform: } assert result == expected_result + @pytest.mark.parametrize("env_name", JINA_KEY_ENV_NAMES) + def test_every_accepted_env_name_resolves_a_key( + self, + env_name: str, + no_jina_env: None, + monkeypatch: pytest.MonkeyPatch, + ): + """Each accepted spelling must be reachable on its own, not shadowed by a repeated read of another name.""" + sentinel = f"resolved-via-{env_name.lower()}" + monkeypatch.setenv(env_name, sentinel) + + _, _, dynamic_api_key = self.config._get_openai_compatible_provider_info(api_base=None, api_key=None) + + assert dynamic_api_key == sentinel + + def test_env_name_precedence_is_stable( + self, + no_jina_env: None, + monkeypatch: pytest.MonkeyPatch, + ): + """Earlier names in the chain win, so adding later fallbacks never re-points an already working install.""" + for name in JINA_KEY_ENV_NAMES: + monkeypatch.setenv(name, f"resolved-via-{name.lower()}") + + for expected_name in JINA_KEY_ENV_NAMES: + _, _, dynamic_api_key = self.config._get_openai_compatible_provider_info(api_base=None, api_key=None) + assert dynamic_api_key == f"resolved-via-{expected_name.lower()}" + monkeypatch.delenv(expected_name) + + def test_explicit_api_key_beats_every_env_name( + self, + no_jina_env: None, + monkeypatch: pytest.MonkeyPatch, + ): + """An api_key passed by the caller short-circuits the whole environment chain.""" + for name in JINA_KEY_ENV_NAMES: + monkeypatch.setenv(name, f"resolved-via-{name.lower()}") + + _, _, dynamic_api_key = self.config._get_openai_compatible_provider_info( + api_base=None, api_key="passed-in-by-caller" + ) + + assert dynamic_api_key == "passed-in-by-caller" + def test_transform_embedding_request_mixed_input(self): """Test transformation of a mixed text and image embedding request""" # a fake base64 string for testing purposes @@ -77,9 +127,7 @@ class TestJinaAIEmbeddingTransform: ) expected_input = [ {"text": "hello world"}, - { - "image": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" - }, + {"image": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="}, ] expected_result = { "model": self.model,