From 03d6971f230972d384485f10b8085fa53bc949b9 Mon Sep 17 00:00:00 2001 From: ParthSareen Date: Tue, 8 Apr 2025 16:49:45 -0700 Subject: [PATCH 1/4] types: allow items and defs for tools --- ollama/_types.py | 5 ++++- tests/test_utils.py | 8 +++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ollama/_types.py b/ollama/_types.py index 0d802e04..22742765 100644 --- a/ollama/_types.py +++ b/ollama/_types.py @@ -308,14 +308,17 @@ class Function(SubscriptableBaseModel): class Parameters(SubscriptableBaseModel): type: Optional[Literal['object']] = 'object' + defs: Optional[Any] = Field(None, alias='$defs') + items: Optional[Any] = None required: Optional[Sequence[str]] = None class Property(SubscriptableBaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) type: Optional[Union[str, Sequence[str]]] = None + items: Optional[Any] = None description: Optional[str] = None - enum: Optional[Sequence] = None + enum: Optional[Sequence[Any]] = None properties: Optional[Mapping[str, Property]] = None diff --git a/tests/test_utils.py b/tests/test_utils.py index 77fdc29c..e5e0743c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -187,7 +187,7 @@ def only_description(): tool = convert_function_to_tool(only_description).model_dump() assert tool['function']['description'] == 'A function with only a description.' - assert tool['function']['parameters'] == {'type': 'object', 'properties': {}, 'required': None} + assert tool['function']['parameters'] == {'type': 'object', 'defs': None, 'items': None, 'required': None, 'properties': {}} def only_description_with_args(x: int, y: int): """ @@ -199,9 +199,11 @@ def only_description_with_args(x: int, y: int): assert tool['function']['description'] == 'A function with only a description.' assert tool['function']['parameters'] == { 'type': 'object', + 'defs': None, + 'items': None, 'properties': { - 'x': {'type': 'integer', 'description': '', 'enum': None}, - 'y': {'type': 'integer', 'description': '', 'enum': None}, + 'x': {'type': 'integer', 'description': '', 'enum': None, 'items': None}, + 'y': {'type': 'integer', 'description': '', 'enum': None, 'items': None}, }, 'required': ['x', 'y'], } From ca903f0883a9884cfcb7bf43911d846554920514 Mon Sep 17 00:00:00 2001 From: ParthSareen Date: Thu, 10 Apr 2025 11:46:35 -0700 Subject: [PATCH 2/4] client: update chat model dump to include by_alias --- ollama/_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ollama/_client.py b/ollama/_client.py index 541d9c82..c6af0a9b 100644 --- a/ollama/_client.py +++ b/ollama/_client.py @@ -342,7 +342,7 @@ def add_two_numbers(a: int, b: int) -> int: format=format, options=options, keep_alive=keep_alive, - ).model_dump(exclude_none=True), + ).model_dump(exclude_none=True, by_alias=True), stream=stream, ) @@ -846,7 +846,7 @@ def add_two_numbers(a: int, b: int) -> int: format=format, options=options, keep_alive=keep_alive, - ).model_dump(exclude_none=True), + ).model_dump(exclude_none=True, by_alias=True), stream=stream, ) From 8a52e8eabbaa94d22c3e14c2f8a083a5c02e1757 Mon Sep 17 00:00:00 2001 From: ParthSareen Date: Fri, 11 Apr 2025 00:44:06 -0700 Subject: [PATCH 3/4] only do alias dump for parameters instead of top level --- ollama/_client.py | 4 ++-- ollama/_types.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ollama/_client.py b/ollama/_client.py index c6af0a9b..541d9c82 100644 --- a/ollama/_client.py +++ b/ollama/_client.py @@ -342,7 +342,7 @@ def add_two_numbers(a: int, b: int) -> int: format=format, options=options, keep_alive=keep_alive, - ).model_dump(exclude_none=True, by_alias=True), + ).model_dump(exclude_none=True), stream=stream, ) @@ -846,7 +846,7 @@ def add_two_numbers(a: int, b: int) -> int: format=format, options=options, keep_alive=keep_alive, - ).model_dump(exclude_none=True, by_alias=True), + ).model_dump(exclude_none=True), stream=stream, ) diff --git a/ollama/_types.py b/ollama/_types.py index 22742765..8b80bd2d 100644 --- a/ollama/_types.py +++ b/ollama/_types.py @@ -307,6 +307,8 @@ class Function(SubscriptableBaseModel): description: Optional[str] = None class Parameters(SubscriptableBaseModel): + model_config = ConfigDict(populate_by_name=True) + type: Optional[Literal['object']] = 'object' defs: Optional[Any] = Field(None, alias='$defs') items: Optional[Any] = None From 909174999d755520d75f5ea565921137ed20c4da Mon Sep 17 00:00:00 2001 From: ParthSareen Date: Mon, 14 Apr 2025 10:26:41 -0700 Subject: [PATCH 4/4] wrap serialize to use alias --- ollama/_types.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ollama/_types.py b/ollama/_types.py index 8b80bd2d..dfeafcf1 100644 --- a/ollama/_types.py +++ b/ollama/_types.py @@ -308,7 +308,6 @@ class Function(SubscriptableBaseModel): class Parameters(SubscriptableBaseModel): model_config = ConfigDict(populate_by_name=True) - type: Optional[Literal['object']] = 'object' defs: Optional[Any] = Field(None, alias='$defs') items: Optional[Any] = None @@ -330,6 +329,15 @@ class Property(SubscriptableBaseModel): class ChatRequest(BaseGenerateRequest): + @model_serializer(mode='wrap') + def serialize_model(self, nxt): + output = nxt(self) + if 'tools' in output and output['tools']: + for tool in output['tools']: + if 'function' in tool and 'parameters' in tool['function'] and 'defs' in tool['function']['parameters']: + tool['function']['parameters']['$defs'] = tool['function']['parameters'].pop('defs') + return output + messages: Optional[Sequence[Union[Mapping[str, Any], Message]]] = None 'Messages to chat with.'