← back to Exo
send error finish reason on failing to parse a tool call (#1785)
509533d49e678e9b16224ee5a46741a744778c6a · 2026-03-24 17:21:39 +0000 · Evan Quiney
a simplification of #1757 which is now stale
Files touched
M src/exo/worker/engines/mlx/utils_mlx.pyM src/exo/worker/runner/llm_inference/model_output_parsers.pyM src/exo/worker/tests/unittests/test_runner/test_parse_tool_calls.py
Diff
commit 509533d49e678e9b16224ee5a46741a744778c6a
Author: Evan Quiney <evanev7@gmail.com>
Date: Tue Mar 24 17:21:39 2026 +0000
send error finish reason on failing to parse a tool call (#1785)
a simplification of #1757 which is now stale
---
src/exo/worker/engines/mlx/utils_mlx.py | 7 ++-----
src/exo/worker/runner/llm_inference/model_output_parsers.py | 7 +++++--
.../worker/tests/unittests/test_runner/test_parse_tool_calls.py | 1 +
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/exo/worker/engines/mlx/utils_mlx.py b/src/exo/worker/engines/mlx/utils_mlx.py
index 91e6fd60..e34b4a43 100644
--- a/src/exo/worker/engines/mlx/utils_mlx.py
+++ b/src/exo/worker/engines/mlx/utils_mlx.py
@@ -740,12 +740,9 @@ def _parse_kimi_tool_calls(text: str):
if func_args_match is None:
raise ValueError("No tool call arguments found.")
func_args = func_args_match.group(1)
- try:
- arg_dct = json.loads(func_args) # pyright: ignore[reportAny]
- except Exception:
- arg_dct = None
+ arg_dct = json.loads(func_args) # pyright: ignore[reportAny]
- return dict(id=tool_call_id, name=func_name, arguments=arg_dct)
+ return dict(id=tool_call_id, name=func_name, arguments=arg_dct) # pyright: ignore[reportAny]
tool_matches = _tool_call_split_regex.findall(text)
if tool_matches:
diff --git a/src/exo/worker/runner/llm_inference/model_output_parsers.py b/src/exo/worker/runner/llm_inference/model_output_parsers.py
index c6c7dd4e..b5729697 100644
--- a/src/exo/worker/runner/llm_inference/model_output_parsers.py
+++ b/src/exo/worker/runner/llm_inference/model_output_parsers.py
@@ -358,8 +358,10 @@ def parse_tool_calls(
if parsed is None:
logger.warning(f"tool call parsing failed for text {combined}")
- yield response.model_copy(update={"text": combined})
- continue
+ yield response.model_copy(
+ update={"text": combined, "token": 0, "finish_reason": "error"}
+ )
+ break
yield ToolCallResponse(
tool_calls=parsed, usage=response.usage, stats=response.stats
@@ -374,6 +376,7 @@ def parse_tool_calls(
update={
"text": "".join(tool_call_text_parts),
"token": 0,
+ "finish_reason": "error",
}
)
yield response
diff --git a/src/exo/worker/tests/unittests/test_runner/test_parse_tool_calls.py b/src/exo/worker/tests/unittests/test_runner/test_parse_tool_calls.py
index 03be01bd..49655f03 100644
--- a/src/exo/worker/tests/unittests/test_runner/test_parse_tool_calls.py
+++ b/src/exo/worker/tests/unittests/test_runner/test_parse_tool_calls.py
@@ -87,6 +87,7 @@ class TestParseToolCalls:
assert len(results) == 1
assert isinstance(results[0], GenerationResponse)
assert results[0].text == "<tool_call>bad content</tool_call>"
+ assert results[0].finish_reason == "error"
def test_tool_schema_coerces_string_arguments_to_expected_types(self):
"""Tool argument values should be coerced using provided JSON schema."""
← b6240a97 Prevent Qwen3.5 looping by using mlx lm fork (#1784)
·
back to Exo
·
override macmon in flake (#1747) 7ee88c1f →