Skip to content

fix(utils): emit multi-type tool params as JSON array, not a comma-joined string#695

Open
anxkhn wants to merge 1 commit into
ollama:mainfrom
anxkhn:fix/tool-multi-type-array
Open

fix(utils): emit multi-type tool params as JSON array, not a comma-joined string#695
anxkhn wants to merge 1 commit into
ollama:mainfrom
anxkhn:fix/tool-multi-type-array

Conversation

@anxkhn

@anxkhn anxkhn commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What

convert_function_to_tool serializes a tool parameter that has more than one type
(for example int | str) as the comma-joined string 'integer, string' instead of
the JSON-Schema array ['integer', 'string'].

Why this is a bug

The generated type string is not valid JSON Schema. The Ollama server parses a
parameter type that is a JSON string as a single type name, so 'integer, string'
is read as one (nonexistent) type and the multi-type constraint is silently dropped.
The array form is the shape the schema expects: Tool.Function.Parameters.Property.type
is Optional[Union[str, Sequence[str]]] (ollama/_types.py), and an array is already
used as the canonical multi-type input elsewhere in the tests
(tests/test_client.py, 'type': ['integer', 'number']).

There is also a non-determinism bug: types is built as a set, so the same
function could serialize to 'integer, string' on one run and 'string, integer'
on the next.

Fix

In ollama/_utils.py, sort the types set and emit:

  • a single type as a bare string (unchanged behavior), and
  • multiple types as a sorted list (a real JSON array).

Sorting also makes the output deterministic. The empty-types edge case (a
parameter typed only None) keeps its prior '' output via ''.join([]).

sorted_types = sorted(types)
schema['properties'][k] = {
  'description': parsed_docstring[k],
  'type': sorted_types if len(sorted_types) > 1 else ''.join(sorted_types),
}

Tests

Updated tests/test_utils.py::test_function_with_all_types so the multi-type
parameter (v: int | str | None on Python >= 3.10) is asserted to be a JSON array:

assert isinstance(tool['function']['parameters']['properties']['v']['type'], list)
assert tool['function']['parameters']['properties']['v']['type'] == ['integer', 'string']

This replaces the previous fragile string-parsing assertion (which stripped
brackets and split on commas). The new assertion fails on the old comma-joined
string and passes with the fix.

Verified locally:

  • uv run pytest ollama tests -q -> 97 passed (doctests included)
  • uvx hatch fmt --check -f (format) and uvx hatch fmt --check -l (lint) -> pass
  • uv lock --check -> ok; uv export vs requirements.txt -> no diff

Single-type parameters (e.g. x: int -> 'integer') are unaffected.

convert_function_to_tool serialized a parameter with a union type (e.g.
Union[int, str]) as the comma-joined string "integer, string" instead of the
JSON-Schema array ["integer", "string"]. The server's PropertyType.UnmarshalJSON
reads that as a single, invalid type name, so the parameter's type constraint is
silently dropped. Because types is a set, the joined string order also varied
between runs.

Emit a single type as a bare string (unchanged) and multiple types as a sorted
list, which matches Tool.Function.Parameters.Property.type (Union[str,
Sequence[str]]) and the array form the server expects. Sorting removes the
non-determinism. Update test_function_with_all_types to assert the multi-type
property is the array ['integer', 'string'] rather than parsing a string.

Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>

@vaderollama vaderollama left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — fixes a real bug where multi-type tool params (e.g. int | str) were serialized as the comma-joined string 'integer, string' instead of the JSON-Schema array ['integer', 'string']. The server parses a string type as a single type name, so the multi-type constraint was silently dropped. Using sorted() for determinism is a nice touch. Tests updated to assert the array format.

@ParthSareen — ready to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants