From d5b2e951bc108e8a871884682455877224d63004 Mon Sep 17 00:00:00 2001
From: Andre Wisplinghoff <andre.wisplinghoff@commerzbank.com>
Date: Thu, 27 Feb 2025 04:42:39 +0100
Subject: [PATCH] Fix "Invalid value for 'content': expected a string, got
 null." openai error in case of empty assistant messages (#17921)

---
 .../llama_index/llms/openai/utils.py             |  9 +++++++--
 .../llms/llama-index-llms-openai/pyproject.toml  |  2 +-
 .../tests/test_openai_utils.py                   | 16 ++++++++++++++++
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/llama-index-integrations/llms/llama-index-llms-openai/llama_index/llms/openai/utils.py b/llama-index-integrations/llms/llama-index-llms-openai/llama_index/llms/openai/utils.py
index febd688a2..7fde73a16 100644
--- a/llama-index-integrations/llms/llama-index-llms-openai/llama_index/llms/openai/utils.py
+++ b/llama-index-integrations/llms/llama-index-llms-openai/llama_index/llms/openai/utils.py
@@ -323,11 +323,16 @@ def to_openai_message_dict(
             raise ValueError(msg)
 
     # NOTE: Sending a null value (None) for Tool Message to OpenAI will cause error
-    # It's only Allowed to send None if it's an Assistant Message
+    # It's only Allowed to send None if it's an Assistant Message and either a function call or tool calls were performed
     # Reference: https://platform.openai.com/docs/api-reference/chat/create
     content_txt = (
         None
-        if content_txt == "" and message.role == MessageRole.ASSISTANT
+        if content_txt == ""
+        and message.role == MessageRole.ASSISTANT
+        and (
+            "function_call" in message.additional_kwargs
+            or "tool_calls" in message.additional_kwargs
+        )
         else content_txt
     )
 
diff --git a/llama-index-integrations/llms/llama-index-llms-openai/pyproject.toml b/llama-index-integrations/llms/llama-index-llms-openai/pyproject.toml
index 9024a5658..572492a36 100644
--- a/llama-index-integrations/llms/llama-index-llms-openai/pyproject.toml
+++ b/llama-index-integrations/llms/llama-index-llms-openai/pyproject.toml
@@ -29,7 +29,7 @@ exclude = ["**/BUILD"]
 license = "MIT"
 name = "llama-index-llms-openai"
 readme = "README.md"
-version = "0.3.20"
+version = "0.3.21"
 
 [tool.poetry.dependencies]
 python = ">=3.9,<4.0"
diff --git a/llama-index-integrations/llms/llama-index-llms-openai/tests/test_openai_utils.py b/llama-index-integrations/llms/llama-index-llms-openai/tests/test_openai_utils.py
index c255b7e61..a9a114212 100644
--- a/llama-index-integrations/llms/llama-index-llms-openai/tests/test_openai_utils.py
+++ b/llama-index-integrations/llms/llama-index-llms-openai/tests/test_openai_utils.py
@@ -156,6 +156,22 @@ def test_to_openai_message_dicts_basic_string() -> None:
     ]
 
 
+def test_to_openai_message_dicts_empty_content() -> None:
+    """If neither `tool_calls` nor `function_call` is set, content must not be set to None,
+    see: https://platform.openai.com/docs/api-reference/chat/create"""
+    chat_messages = [
+        ChatMessage(role="user", content="test question"),
+        ChatMessage(role="assistant", content=""),
+    ]
+    openai_messages = to_openai_message_dicts(
+        chat_messages,
+    )
+    assert openai_messages == [
+        {"role": "user", "content": "test question"},
+        {"role": "assistant", "content": ""},
+    ]
+
+
 def test_to_openai_message_dicts_function_calling(
     chat_messages_with_function_calling: List[ChatMessage],
     openai_message_dicts_with_function_calling: List[ChatCompletionMessageParam],
-- 
GitLab