From 3880c1a406516b52082ffd8cb51b9648e2b63f1e Mon Sep 17 00:00:00 2001 From: oobabooga <112222186+oobabooga@users.noreply.github.com> Date: Fri, 6 Mar 2026 02:41:16 -0300 Subject: [PATCH] API: Accept content:null and complex tool definitions in tool calling requests --- extensions/openai/completions.py | 6 +++++- extensions/openai/typing.py | 12 +++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/extensions/openai/completions.py b/extensions/openai/completions.py index 1538b87a..297c9ba7 100644 --- a/extensions/openai/completions.py +++ b/extensions/openai/completions.py @@ -197,7 +197,11 @@ def chat_completions_common(body: dict, is_legacy: bool = False, stream=False, p # Handle multimodal content validation content = m.get('content') if content is None: - raise InvalidRequestError(message="messages: missing content", param='messages') + # OpenAI allows content: null on assistant messages when tool_calls is present + if m['role'] == 'assistant' and m.get('tool_calls'): + m['content'] = '' + else: + raise InvalidRequestError(message="messages: missing content", param='messages') # Validate multimodal content structure if isinstance(content, list): diff --git a/extensions/openai/typing.py b/extensions/openai/typing.py index 8af75ef8..4cf5f997 100644 --- a/extensions/openai/typing.py +++ b/extensions/openai/typing.py @@ -1,8 +1,8 @@ import json import time -from typing import Dict, List, Optional +from typing import Any, Dict, List, Optional -from pydantic import BaseModel, Field, model_validator, validator +from pydantic import BaseModel, ConfigDict, Field, model_validator, validator from modules import shared @@ -65,22 +65,20 @@ class ToolDefinition(BaseModel): class ToolFunction(BaseModel): + model_config = ConfigDict(extra='allow') description: str name: str parameters: 'ToolParameters' class ToolParameters(BaseModel): - properties: Optional[Dict[str, 'ToolProperty']] = None + model_config = ConfigDict(extra='allow') + properties: Optional[Dict[str, Any]] = None required: Optional[list[str]] = None type: str description: Optional[str] = None -class ToolProperty(BaseModel): - description: Optional[str] = None - type: Optional[str] = None # we are faced with definitions like anyOf, e.g. {'type': 'function', 'function': {'name': 'git_create_branch', 'description': 'Creates a new branch from an optional base branch', 'parameters': {'type': 'object', 'properties': {'repo_path': {'title': 'Repo Path', 'type': 'string'}, 'branch_name': {'title': 'Branch Name', 'type': 'string'}, 'base_branch': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'title': 'Base Branch'}}, 'required': ['repo_path', 'branch_name'], 'title': 'GitCreateBranch'}}} - class FunctionCall(BaseModel): name: str