[Bugfix] Fix hermes tool parser handling of non-string argument types (#22002)

Signed-off-by: wangzi <3220100013@zju.edu.cn>
Signed-off-by: David Chen <530634352@qq.com>
Co-authored-by: wangzi <3220100013@zju.edu.cn>
Co-authored-by: Chauncey <chaunceyjiang@gmail.com>
This commit is contained in:
WeiQing Chen
2025-09-22 11:35:39 +08:00
committed by GitHub
parent 793be8d057
commit 0eecb31663
2 changed files with 166 additions and 7 deletions

View File

@@ -368,16 +368,32 @@ class Hermes2ProToolParser(ToolParser):
# case -- we now have the first info about arguments available from
# autocompleting the JSON
elif cur_arguments and not prev_arguments:
# extract the content after {"name": ..., "arguments":
# directly from tool_call_portion as cur_arguments_json,
# since cur_arguments may differ from the original text
# due to partial JSON parsing
# for example, tool_call_portion =
# {"name": "search", "arguments": {"search_request": {"
# but cur_arguments =
# {"search_request": {}}
function_name = current_tool_call.get("name")
match = re.search(
r'\{"name":\s*"' +
re.escape(function_name) + r'"\s*,\s*"arguments":\s*(.*)',
tool_call_portion.strip(), re.DOTALL)
if match:
cur_arguments_json = match.group(1)
else:
cur_arguments_json = json.dumps(cur_arguments,
ensure_ascii=False)
cur_arguments_json = json.dumps(cur_arguments,
ensure_ascii=False)
logger.debug("finding %s in %s", delta_text,
cur_arguments_json)
# get the location where previous args differ from current
if (delta_text not in cur_arguments_json[:-2]):
# get the location where previous args differ from current.
if (delta_text not in cur_arguments_json):
return None
args_delta_start_loc = cur_arguments_json[:-2]. \
args_delta_start_loc = cur_arguments_json. \
rindex(delta_text) + \
len(delta_text)
@@ -397,8 +413,20 @@ class Hermes2ProToolParser(ToolParser):
# last case -- we have an update to existing arguments.
elif cur_arguments and prev_arguments:
if isinstance(delta_text, str) and len(delta_text.rstrip(
)) >= 1 and delta_text.rstrip()[-1] == '}':
# judge whether the tool_call_portion is a complete JSON
try:
json.loads(tool_call_portion)
is_complete_json = True
except Exception:
is_complete_json = False
# if the delta_text ends with a '}' and tool_call_portion is a
# complete JSON, then the last '}' does not belong to the
# arguments, so we should trim it off
if isinstance(delta_text, str) \
and len(delta_text.rstrip()) >= 1 \
and delta_text.rstrip()[-1] == '}' \
and is_complete_json:
delta_text = delta_text.rstrip()[:-1]
logger.debug("got diff %s", delta_text)