diff --git a/poetry.lock b/poetry.lock index 2f94693e61..cca2f49a75 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1823,13 +1823,13 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] [[package]] name = "openai" -version = "1.54.0" +version = "1.56.1" description = "The official Python library for the openai API" optional = false python-versions = ">=3.8" files = [ - {file = "openai-1.54.0-py3-none-any.whl", hash = "sha256:24ed8874b56e919f0fbb80b7136c3fb022dc82ce9f5f21579b7b280ea4bba249"}, - {file = "openai-1.54.0.tar.gz", hash = "sha256:df2a84384314165b706722a7ac8988dc33eba20dd7fc3b939d138110e608b1ce"}, + {file = "openai-1.56.1-py3-none-any.whl", hash = "sha256:38e61183c2a98fedebbbb04a909a052d9f897358b070483fc0caff17300a227c"}, + {file = "openai-1.56.1.tar.gz", hash = "sha256:8b0449f22a0c318441eae8a8a789753c3b2cac86542be51ca45df788e26aa180"}, ] [package.dependencies] @@ -3519,4 +3519,4 @@ proxy = ["PyJWT", "apscheduler", "backoff", "cryptography", "fastapi", "fastapi- [metadata] lock-version = "2.0" python-versions = ">=3.8.1,<4.0, !=3.9.7" -content-hash = "64154f16e1bbea8b77ba3eddf1cbf051af39f019820d92b638c448445fa32c83" +content-hash = "1ba487e48917ce3087fa154534c6c495dad7dc8dc1c5881bbb1f196ba6702b91" diff --git a/pyproject.toml b/pyproject.toml index c84ff303b5..ad605f2190 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,8 @@ documentation = "https://docs.litellm.ai" [tool.poetry.dependencies] python = ">=3.8.1,<4.0, !=3.9.7" -openai = ">=1.54.0" +httpx = ">=0.23.0,<0.28.0" +openai = ">=1.55.3" python-dotenv = ">=0.2.0" tiktoken = ">=0.7.0" importlib-metadata = ">=6.8.0" diff --git a/requirements.txt b/requirements.txt index b22edea09d..7b1abcdc68 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ # LITELLM PROXY DEPENDENCIES # anyio==4.4.0 # openai + http req. +httpx==0.27.0 # Pin Httpx dependency openai==1.55.3 # openai req. fastapi==0.111.0 # server dep backoff==2.2.1 # server dep diff --git a/tests/llm_translation/base_llm_unit_tests.py b/tests/llm_translation/base_llm_unit_tests.py index 028a02535f..a4551378eb 100644 --- a/tests/llm_translation/base_llm_unit_tests.py +++ b/tests/llm_translation/base_llm_unit_tests.py @@ -63,6 +63,20 @@ class BaseLLMChatTest(ABC): response = litellm.completion(**base_completion_call_args, messages=messages) assert response is not None + def test_multilingual_requests(self): + """ + Tests that the provider can handle multilingual requests and invalid utf-8 sequences + + Context: https://github.com/openai/openai-python/issues/1921 + """ + base_completion_call_args = self.get_base_completion_call_args() + response = litellm.completion( + **base_completion_call_args, + messages=[{"role": "user", "content": "你好世界!\ud83e, ö"}], + ) + print("multilingual response: ", response) + assert response is not None + @pytest.mark.parametrize( "response_format", [ diff --git a/tests/llm_translation/test_anthropic_completion.py b/tests/llm_translation/test_anthropic_completion.py index 076219961b..a61bdfd731 100644 --- a/tests/llm_translation/test_anthropic_completion.py +++ b/tests/llm_translation/test_anthropic_completion.py @@ -706,6 +706,14 @@ class TestAnthropicCompletion(BaseLLMChatTest): result = convert_to_anthropic_tool_invoke([tool_call_no_arguments]) print(result) + def test_multilingual_requests(self): + """ + Anthropic API raises a 400 BadRequest error when the request contains invalid utf-8 sequences. + + Todo: if litellm.modify_params is True ensure it's a valid utf-8 sequence + """ + pass + def test_convert_tool_response_to_message_with_values(): """Test converting a tool response with 'values' key to a message""" diff --git a/tests/llm_translation/test_openai.py b/tests/llm_translation/test_openai.py index b07f4c5d23..87e3a8a614 100644 --- a/tests/llm_translation/test_openai.py +++ b/tests/llm_translation/test_openai.py @@ -15,6 +15,7 @@ from respx import MockRouter import litellm from litellm import Choices, Message, ModelResponse +from base_llm_unit_tests import BaseLLMChatTest def test_openai_prediction_param(): @@ -268,3 +269,12 @@ async def test_vision_with_custom_model(): ] assert request_body["model"] == "my-custom-model" assert request_body["max_tokens"] == 10 + + +class TestOpenAIChatCompletion(BaseLLMChatTest): + def get_base_completion_call_args(self) -> dict: + return {"model": "gpt-4o-mini"} + + def test_tool_call_no_arguments(self, tool_call_no_arguments): + """Test that tool calls with no arguments is translated correctly. Relevant issue: https://github.com/BerriAI/litellm/issues/6833""" + pass