diff --git a/litellm/main.py b/litellm/main.py index ddd37b47536..33b26b5e4ac 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -4913,8 +4913,10 @@ def embedding( # noqa: PLR0915 if encoding_format is not None: optional_params["encoding_format"] = encoding_format - else: - # Omiting causes openai sdk to add default value of "float" + elif custom_llm_provider == "openai" or custom_llm_provider is None: + # Omitting causes openai sdk to add default value of "float". + # Only suppress for the canonical OpenAI provider — third-party + # providers (together_ai, nvidia_nim, etc.) reject encoding_format=null. optional_params["encoding_format"] = None api_version = None diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index 50dc3c6c6ec..367fdae7173 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -486,6 +486,57 @@ def test_cohere_embedding_optional_params(): assert optional_params is not None +def test_encoding_format_none_not_sent_to_third_party_providers(): + """ + together_ai / nvidia_nim / etc. reject encoding_format=null. + When no encoding_format is given, the None sentinel should only be set + for the canonical OpenAI provider, not third-party providers that share + the same embedding code path. + """ + from unittest.mock import MagicMock, patch + + import litellm + + mock_response = litellm.EmbeddingResponse( + model="text-embedding-3-small", + data=[{"embedding": [0.1, 0.2, 0.3], "index": 0, "object": "embedding"}], + usage=litellm.Usage(prompt_tokens=1, total_tokens=1), + ) + + def get_optional_params(call_args): + return call_args.kwargs.get( + "optional_params", call_args[1].get("optional_params", {}) + ) + + with patch("litellm.main.openai_chat_completions") as mock_oai: + mock_oai.embedding.return_value = mock_response + + # OpenAI — encoding_format=None should be set to suppress SDK default + litellm.embedding(model="text-embedding-3-small", input="hello") + params = get_optional_params(mock_oai.embedding.call_args) + assert "encoding_format" in params + assert params["encoding_format"] is None + + # together_ai — encoding_format key should be absent entirely + mock_oai.reset_mock() + litellm.embedding( + model="together_ai/togethercomputer/m2-bert-80M-8k-retrieval", + input="hello", + ) + params = get_optional_params(mock_oai.embedding.call_args) + assert "encoding_format" not in params + + # Explicit encoding_format should always be forwarded + mock_oai.reset_mock() + litellm.embedding( + model="together_ai/togethercomputer/m2-bert-80M-8k-retrieval", + input="hello", + encoding_format="float", + ) + params = get_optional_params(mock_oai.embedding.call_args) + assert params.get("encoding_format") == "float" + + def validate_model_cost_values(model_data, exceptions=None): """ Validates that cost values in model data do not exceed 1. @@ -1412,8 +1463,7 @@ class TestProxyFunctionCalling: assert result is True, "Resolvable model names work with fallback logic" # Documentation notes: - print( - """ + print(""" PROXY MODEL RESOLUTION BEHAVIOR: ✅ WORKS (with current fallback logic): @@ -1428,8 +1478,7 @@ class TestProxyFunctionCalling: 💡 SOLUTION: Use LiteLLM proxy server with proper model_list configuration that maps custom names to underlying models. - """ - ) + """) @pytest.mark.parametrize( "proxy_model_with_hints,expected_result", @@ -1791,8 +1840,7 @@ class TestProxyFunctionCalling: This test provides documentation on how the proxy server configuration would typically map custom model names to underlying models. """ - print( - """ + print(""" REAL-WORLD PROXY SERVER CONFIGURATION EXAMPLE: =============================================== @@ -1845,8 +1893,7 @@ class TestProxyFunctionCalling: - Consistent request/response format - Enhanced streaming support for function calls - """ - ) + """) # Verify that direct underlying models work as expected bedrock_models = [ @@ -2060,8 +2107,7 @@ class TestProxyFunctionCalling: This test provides documentation on how the proxy server configuration would typically map custom model names to underlying models. """ - print( - """ + print(""" REAL-WORLD PROXY SERVER CONFIGURATION EXAMPLE: =============================================== @@ -2114,8 +2160,7 @@ class TestProxyFunctionCalling: - Consistent request/response format - Enhanced streaming support for function calls - """ - ) + """) # Verify that direct underlying models work as expected bedrock_models = [ @@ -2329,8 +2374,7 @@ class TestProxyFunctionCalling: This test provides documentation on how the proxy server configuration would typically map custom model names to underlying models. """ - print( - """ + print(""" REAL-WORLD PROXY SERVER CONFIGURATION EXAMPLE: =============================================== @@ -2383,8 +2427,7 @@ class TestProxyFunctionCalling: - Consistent request/response format - Enhanced streaming support for function calls - """ - ) + """) # Verify that direct underlying models work as expected bedrock_models = [