From 43cd9bf66829b7e38b8ae74863b69030729f66f2 Mon Sep 17 00:00:00 2001 From: la1ty Date: Mon, 18 May 2026 13:17:19 +0800 Subject: [PATCH 1/4] Draft: parsing tool_calls arguments Add parsing for JSON-encoded arguments in tool_calls. --- xinference/model/llm/utils.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/xinference/model/llm/utils.py b/xinference/model/llm/utils.py index 700d75cffc..96e171a7a4 100644 --- a/xinference/model/llm/utils.py +++ b/xinference/model/llm/utils.py @@ -811,6 +811,22 @@ def _transform_messages( ) new_message = dict(msg) new_message["content"] = new_content if new_content else None + # Parse JSON-encoded arguments in tool_calls to dicts, + # so Jinja2 templates can iterate them with |items. + if new_message.get("tool_calls"): + tool_calls = [] + for tc in new_message["tool_calls"]: + tc = dict(tc) + func = tc.get("function") + if func and isinstance(func.get("arguments"), str): + func = dict(func) + try: + func["arguments"] = json.loads(func["arguments"]) + except (json.JSONDecodeError, TypeError): + pass + tc["function"] = func + tool_calls.append(tc) + new_message["tool_calls"] = tool_calls transformed_messages.append(new_message) return transformed_messages From 871b4a4e906a18fa7eed2c3a2eea0c54b1e3bd64 Mon Sep 17 00:00:00 2001 From: la1ty Date: Mon, 18 May 2026 13:35:02 +0800 Subject: [PATCH 2/4] Apply suggestion from @gemini-code-assist[bot] Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- xinference/model/llm/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xinference/model/llm/utils.py b/xinference/model/llm/utils.py index 96e171a7a4..d0e977002a 100644 --- a/xinference/model/llm/utils.py +++ b/xinference/model/llm/utils.py @@ -818,10 +818,12 @@ def _transform_messages( for tc in new_message["tool_calls"]: tc = dict(tc) func = tc.get("function") - if func and isinstance(func.get("arguments"), str): + if isinstance(func, dict) and isinstance(func.get("arguments"), str): func = dict(func) try: - func["arguments"] = json.loads(func["arguments"]) + parsed_args = json.loads(func["arguments"]) + if isinstance(parsed_args, dict): + func["arguments"] = parsed_args except (json.JSONDecodeError, TypeError): pass tc["function"] = func From b0a77f3c262e43cd52eceb852425108fcb1448a1 Mon Sep 17 00:00:00 2001 From: la1ty Date: Mon, 18 May 2026 13:46:35 +0800 Subject: [PATCH 3/4] fix linting --- xinference/model/llm/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xinference/model/llm/utils.py b/xinference/model/llm/utils.py index d0e977002a..6cd4980da0 100644 --- a/xinference/model/llm/utils.py +++ b/xinference/model/llm/utils.py @@ -818,7 +818,9 @@ def _transform_messages( for tc in new_message["tool_calls"]: tc = dict(tc) func = tc.get("function") - if isinstance(func, dict) and isinstance(func.get("arguments"), str): + if isinstance(func, dict) and isinstance( + func.get("arguments"), str + ): func = dict(func) try: parsed_args = json.loads(func["arguments"]) From 9cc4e0fd86b865e103c7b572862e14283f5e6c7a Mon Sep 17 00:00:00 2001 From: la1ty Date: Tue, 19 May 2026 12:16:21 +0800 Subject: [PATCH 4/4] fix test --- xinference/model/llm/tests/test_utils.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/xinference/model/llm/tests/test_utils.py b/xinference/model/llm/tests/test_utils.py index 6b0ccaf05d..5cf252639c 100644 --- a/xinference/model/llm/tests/test_utils.py +++ b/xinference/model/llm/tests/test_utils.py @@ -79,7 +79,16 @@ def test_transform_messages_preserves_tool_call_fields(): assert transformed[1] == { "role": "assistant", "content": None, - "tool_calls": messages[1]["tool_calls"], + "tool_calls": [ + { + "id": "call_bed4c5f1", + "function": { + "arguments": {"file_path": "README*"}, + "name": "view_file_in_detail", + }, + "type": "function", + } + ], } assert transformed[2] == { "role": "tool",