← back to Exo
fix glm5 tool calling (#1612)
73e50df8275cd0a95124c970b82797b70c41e8b9 · 2026-02-24 18:21:18 +0000 · Evan Quiney
glm5 is a deepseekv32 model, so was parsing dsml style tool calls
instead of glm style tool calls. fix it!!
Files touched
M src/exo/worker/runner/llm_inference/runner.pyM src/exo/worker/runner/llm_inference/tool_parsers.py
Diff
commit 73e50df8275cd0a95124c970b82797b70c41e8b9
Author: Evan Quiney <evanev7@gmail.com>
Date: Tue Feb 24 18:21:18 2026 +0000
fix glm5 tool calling (#1612)
glm5 is a deepseekv32 model, so was parsing dsml style tool calls
instead of glm style tool calls. fix it!!
---
src/exo/worker/runner/llm_inference/runner.py | 25 ++++++++++++----------
.../worker/runner/llm_inference/tool_parsers.py | 13 +++++------
2 files changed, 21 insertions(+), 17 deletions(-)
diff --git a/src/exo/worker/runner/llm_inference/runner.py b/src/exo/worker/runner/llm_inference/runner.py
index 4c762de2..5fb1459f 100644
--- a/src/exo/worker/runner/llm_inference/runner.py
+++ b/src/exo/worker/runner/llm_inference/runner.py
@@ -97,6 +97,7 @@ def main(
bound_instance.bound_runner_id,
bound_instance.bound_shard,
)
+ model_id = shard_metadata.model_card.model_id
device_rank = shard_metadata.device_rank
logger.info("hello from the runner")
if getattr(shard_metadata, "immediate_exception", False):
@@ -281,7 +282,7 @@ def main(
ChunkGenerated(
command_id=command_id,
chunk=PrefillProgressChunk(
- model=shard_metadata.model_card.model_id,
+ model=model_id,
processed_tokens=processed,
total_tokens=total,
),
@@ -325,7 +326,10 @@ def main(
# Model-specific output parsing for tool calls.
if isinstance(inference_model, GptOssModel):
mlx_generator = parse_gpt_oss(mlx_generator)
- elif isinstance(inference_model, DeepseekV32Model):
+ elif (
+ isinstance(inference_model, DeepseekV32Model)
+ and "deepseek" in model_id.normalize().lower()
+ ):
mlx_generator = parse_deepseek_v32(mlx_generator)
elif tool_parser:
mlx_generator = parse_tool_calls(mlx_generator, tool_parser)
@@ -355,7 +359,7 @@ def main(
command_id=command_id,
chunk=ErrorChunk(
error_message=response.text,
- model=shard_metadata.model_card.model_id,
+ model=model_id,
),
)
)
@@ -370,7 +374,7 @@ def main(
ChunkGenerated(
command_id=command_id,
chunk=TokenChunk(
- model=shard_metadata.model_card.model_id,
+ model=model_id,
text=response.text,
token_id=response.token,
usage=response.usage,
@@ -389,7 +393,7 @@ def main(
command_id=command_id,
chunk=ToolCallChunk(
tool_calls=response.tool_calls,
- model=shard_metadata.model_card.model_id,
+ model=model_id,
usage=response.usage,
stats=response.stats,
),
@@ -405,7 +409,7 @@ def main(
ChunkGenerated(
command_id=command_id,
chunk=ErrorChunk(
- model=shard_metadata.model_card.model_id,
+ model=model_id,
finish_reason="error",
error_message=str(e),
),
@@ -727,7 +731,7 @@ def parse_tool_calls(
in_tool_call = False
tool_call_text_parts: list[str] = []
for response in responses:
- if response.text.startswith(tool_parser.start_parsing):
+ if not in_tool_call and response.text.startswith(tool_parser.start_parsing):
in_tool_call = True
if in_tool_call:
@@ -765,10 +769,9 @@ def parse_tool_calls(
)
yield response
- continue
-
- # fallthrough
- yield response
+ else:
+ # fallthrough
+ yield response
EXO_RUNNER_MUST_FAIL = "EXO RUNNER MUST FAIL"
diff --git a/src/exo/worker/runner/llm_inference/tool_parsers.py b/src/exo/worker/runner/llm_inference/tool_parsers.py
index 88cbf0be..ee6d1bb5 100644
--- a/src/exo/worker/runner/llm_inference/tool_parsers.py
+++ b/src/exo/worker/runner/llm_inference/tool_parsers.py
@@ -58,15 +58,16 @@ def _flatten(p: dict[str, Any]) -> dict[str, str]:
}
-json_tool_parser = ToolParser(
- start_parsing="<tool_call>",
- end_parsing="</tool_call>",
- parse_tool_calls=_parse_json_calls,
-)
+def make_json_parser() -> ToolParser:
+ return ToolParser(
+ start_parsing="<tool_call>",
+ end_parsing="</tool_call>",
+ parse_tool_calls=_parse_json_calls,
+ )
def infer_tool_parser(chat_template: str) -> ToolParser | None:
"""Attempt to auto-infer a tool parser from the chat template."""
if "<tool_call>" in chat_template and "tool_call.name" in chat_template:
- return json_tool_parser
+ return make_json_parser()
return None
← 2b417f28 fix: sync model selectors between sidebar and chat input (#1
·
back to Exo
·
update mlx 2 (#1611) 14526d28 →