From 9ec20d9730db3f41270da12f51f7ce138fb8705c Mon Sep 17 00:00:00 2001 From: oobabooga <112222186+oobabooga@users.noreply.github.com> Date: Sun, 22 Mar 2026 19:16:24 -0700 Subject: [PATCH] Strip thinking blocks before tool-call parsing --- modules/tool_parsing.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/modules/tool_parsing.py b/modules/tool_parsing.py index 7a7ed5d8..ec49f77f 100644 --- a/modules/tool_parsing.py +++ b/modules/tool_parsing.py @@ -2,6 +2,8 @@ import json import random import re +from modules.reasoning import extract_reasoning + def _make_tool_call(name, arguments): return {"type": "function", "function": {"name": name, "arguments": arguments}} @@ -41,6 +43,10 @@ def streaming_tool_buffer_check(text, markers=None, tool_names=None, check_bare_ check_bare_names: Whether to do partial-prefix matching on tool names (for models with unknown template format). ''' + # Strip thinking blocks so tool-call syntax inside doesn't + # trigger false positives. + _, text = extract_reasoning(text) + # Full marker found in text → buffer permanently. # Always checks ALL known markers regardless of template (cheap safety net). for marker in TOOL_CALL_OPENING_MARKERS: @@ -543,12 +549,19 @@ def detect_tool_call_format(template_str): def parse_tool_call(answer: str, tool_names: list[str], return_prefix: bool = False, parsers: list = None): + # Strip thinking blocks so tool-call syntax inside is ignored. + original_answer = answer + _, answer = extract_reasoning(answer) + # Offset between original and stripped text, used to map start_pos + # back to the original string when returning a prefix. + reasoning_offset = len(original_answer) - len(answer) + matches = [] start_pos = None def _return(matches, start_pos): if return_prefix: - prefix = answer[:start_pos] if matches and start_pos is not None else '' + prefix = original_answer[:start_pos + reasoning_offset] if matches and start_pos is not None else '' return matches, prefix return matches