Repository: abetlen/llama-cpp-python
Issue category: Bug Report

Assistant message with tool_calls and without content raises an error
# Prerequisites

Please answer the following questions for yourself before submitting an issue.

- [x] I am running the latest code. Development is very rapid so there are no tagged versions as of now.
- [x] I carefully followed the [README.md](https://github.com/abetlen/llama-cpp-python/blob/main/README.md).
- [x] I [searched using keywords relevant to my issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/filtering-and-searching-issues-and-pull-requests) to make sure that I am creating a new issue that is not already open (or closed).
- [x] I reviewed the [Discussions](https://github.com/abetlen/llama-cpp-python/discussions), and have a new bug or useful enhancement to share.

# Expected Behavior

Sending this request:

```
{
  "model" : my-model,
  "messages" : [ {
    "role" : "system",
    "content" : "You are an helpful assistant"
  }, {
    "role" : "user",
    "content" : "What is the square root of 101?"
  }, {
    "role" : "assistant",
    "tool_calls" : [ {
      "id" : "call__0_sqrt_cmpl-c359a11f-68fa-4b8e-9960-1917b96a8b23",
      "type" : "function",
      "function" : {
        "name" : "sqrt",
        "arguments" : "{\"arg0\": 101}"
      }
    } ]
  }, {
    "role" : "tool",
    "tool_call_id" : "call__0_sqrt_cmpl-c359a11f-68fa-4b8e-9960-1917b96a8b23",
    "content" : "10.05"
  } ],
  "temperature" : 0.7
}
```

the request should be valid.



# Current Behavior

The request raises the following error:

```
{
  "error":{
    "message":"[
      {
        'type': 'literal_error', 
        'loc': ('body', 'messages', 2, 'typed-dict', 'role'), 
        'msg': \"Input should be 'system'\", 
        'input': 'assistant', 
        'ctx': {'expected': \"'system'\"}
      }, {
        'type': 'missing', 
        'loc': ('body', 'messages', 2, 'typed-dict', 'content'), 
        'msg': 'Field required', 
        'input': {'role': 'assistant', 'tool_calls': [{'id': 'call__0_sqrt_cmpl-c359a11f-68fa-4b8e-9960-1917b96a8b23', 'type': 'function', 'function': {'name': 'sqrt', 'arguments': '{\"arg0\": 101}'}}]}
     }, {
       'type': 'literal_error', 
       'loc': ('body', 'messages', 2, 'typed-dict', 'role'), 
       'msg': \"Input should be 'user'\", 
       'input': 'assistant', 
       'ctx': {'expected': \"'user'\"}
     }, {
       'type': 'missing', 
       'loc': ('body', 'messages', 2, 'typed-dict', 'content'), 
       'msg': 'Field required', 
       'input': {'role': 'assistant', 'tool_calls': [{'id': 'call__0_sqrt_cmpl-c359a11f-68fa-4b8e-9960-1917b96a8b23', 'type': 'function', 'function': {'name': 'sqrt', 'arguments': '{\"arg0\": 101}'}}]}
     }, {
       'type': 'missing',
       'loc': ('body', 'messages', 2, 'typed-dict', 'content'), 
       'msg': 'Field required', 
       'input': {'role': 'assistant', 'tool_calls': [{'id': 'call__0_sqrt_cmpl-c359a11f-68fa-4b8e-9960-1917b96a8b23', 'type': 'function', 'function': {'name': 'sqrt', 'arguments': '{\"arg0\": 101}'}}]}
     }, {
       'type': 'literal_error', 
       'loc': ('body', 'messages', 2, 'typed-dict', 'role'),
       'msg': \"Input should be 'tool'\", 
       'input': 'assistant', 
       'ctx': {'expected': \"'tool'\"}
     }, {
       'type': 'missing', 
       'loc': ('body', 'messages', 2, 'typed-dict', 'content'), 
       'msg': 'Field required', 
       'input': {'role': 'assistant', 'tool_calls': [{'id': 'call__0_sqrt_cmpl-c359a11f-68fa-4b8e-9960-1917b96a8b23', 'type': 'function', 'function': {'name': 'sqrt', 'arguments': '{\"arg0\": 101}'}}]}
     }, {
       'type': 'missing', 
       'loc': ('body', 'messages', 2, 'typed-dict', 'tool_call_id'), 
       'msg': 'Field required', 
       'input': {'role': 'assistant', 'tool_calls': [{'id': 'call__0_sqrt_cmpl-c359a11f-68fa-4b8e-9960-1917b96a8b23', 'type': 'function', 'function': {'name': 'sqrt', 'arguments': '{\"arg0\": 101}'}}]}
     }, {
       'type': 'literal_error', 
       'loc': ('body', 'messages', 2, 'typed-dict', 'role'),
       'msg': \"Input should be 'function'\", 'input': 'assistant', 'ctx': {'expected': \"'function'\"}}, {'type': 'missing', 'loc': ('body', 'messages', 2, 'typed-dict', 'content'), 'msg': 'Field required', 'input': {'role': 'assistant', 'tool_calls': [{'id': 'call__0_sqrt_cmpl-c359a11f-68fa-4b8e-9960-1917b96a8b23', 'type': 'function', 'function': {'name': 'sqrt', 'arguments': '{\"arg0\": 101}'}}]}
     }, {
       'type': 'missing', 
       'loc': ('body', 'messages', 2, 'typed-dict', 'name'), 
       'msg': 'Field required', 
       'input': {'role': 'assistant', 'tool_calls': [{'id': 'call__0_sqrt_cmpl-c359a11f-68fa-4b8e-9960-1917b96a8b23', 'type': 'function', 'function': {'name': 'sqrt', 'arguments': '{\"arg0\": 101}'}}]}
    }
    ]","type":"internal_server_error","param":null,"code":null}}
```

Note that if  `"content": null` is added to the third message (the one with `tool_calls`), the request succeeds.


The same request on GPT API works. 



Functions to edit:
llama_cpp/llama_types.py:ChatCompletionRequestAssistantMessage

Patch:
diff --git a/llama_cpp/llama_types.py b/llama_cpp/llama_types.py
index bbb58afc3..57836ee76 100644
--- a/llama_cpp/llama_types.py
+++ b/llama_cpp/llama_types.py
@@ -214,7 +214,7 @@ class ChatCompletionRequestAssistantMessageFunctionCall(TypedDict):
 
 class ChatCompletionRequestAssistantMessage(TypedDict):
     role: Literal["assistant"]
-    content: Optional[str]
+    content: NotRequired[str]
     tool_calls: NotRequired[ChatCompletionMessageToolCalls]
     function_call: NotRequired[
         ChatCompletionRequestAssistantMessageFunctionCall