From feb351737c55a45344b9fed0d22a98996ee18362 Mon Sep 17 00:00:00 2001 From: Bagatur <22008038+baskaryan@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:06:03 -0700 Subject: [PATCH] core[patch]: fix empty OpenAI tools when strict=True (#26287) Fix #26232 --------- Co-authored-by: Eugene Yurtsev --- .../langchain_core/utils/function_calling.py | 8 ++++++-- .../unit_tests/utils/test_function_calling.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/libs/core/langchain_core/utils/function_calling.py b/libs/core/langchain_core/utils/function_calling.py index 67ac7ebd7f966..9e239eba37264 100644 --- a/libs/core/langchain_core/utils/function_calling.py +++ b/libs/core/langchain_core/utils/function_calling.py @@ -605,9 +605,13 @@ def _recursive_set_additional_properties_false( schema: Dict[str, Any], ) -> Dict[str, Any]: if isinstance(schema, dict): - # Check if 'required' is a key at the current level - if "required" in schema: + # Check if 'required' is a key at the current level or if the schema is empty, + # in which case additionalProperties still needs to be specified. + if "required" in schema or ( + "properties" in schema and not schema["properties"] + ): schema["additionalProperties"] = False + # Recursively check 'properties' and 'items' if they exist if "properties" in schema: for value in schema["properties"].values(): diff --git a/libs/core/tests/unit_tests/utils/test_function_calling.py b/libs/core/tests/unit_tests/utils/test_function_calling.py index 9570c52d4c273..fee5f4778b103 100644 --- a/libs/core/tests/unit_tests/utils/test_function_calling.py +++ b/libs/core/tests/unit_tests/utils/test_function_calling.py @@ -793,3 +793,22 @@ def magic_function(input: int | float) -> str: assert result["parameters"]["properties"]["input"] == { "anyOf": [{"type": "integer"}, {"type": "number"}] } + + +def test_convert_to_openai_function_no_args() -> None: + @tool + def empty_tool() -> str: + """No args""" + return "foo" + + actual = convert_to_openai_function(empty_tool, strict=True) + assert actual == { + "name": "empty_tool", + "description": "No args", + "parameters": { + "properties": {}, + "additionalProperties": False, + "type": "object", + }, + "strict": True, + }