S1-DeepResearch-32B / inference /server /tool_execution.py
ScienceOne-AI's picture
Upload 61 files
816198f verified
from typing import Any, Tuple
import json
import asyncio
import os
import uuid
import importlib.util
from pathlib import Path
from utils.configs import USE_NLP_FORMAT_RETURN
async def execute_tool_call(name: Any, arguments: Any, all_tools, logger=None, USE_NLP_FORMAT_RETURN: bool | None = None, query_id = "") -> Tuple[str, str]:
"""
Execute a single tool call locally. Returns (tool_name, tool_response_json_str).
"""
if USE_NLP_FORMAT_RETURN is None:
USE_NLP_FORMAT_RETURN = USE_NLP_FORMAT_RETURN
if name == "parse_error_tool_call":
if USE_NLP_FORMAT_RETURN:
result = f"Error: Tool call is not a valid JSON. Tool call must contain a valid \"name\" and \"arguments\" field. Parse error: {arguments.get('parse_error', '')}"
else:
result = json.dumps({"error": f"Parse error: {arguments.get('parse_error', '')}", "raw": arguments.get('raw', '')}, ensure_ascii=False)
if logger:
logger.error(result)
return name or "parse_error_tool_call", result
tool = all_tools.get(name)
if tool is None:
result = json.dumps({"error": f"Unknown tool: {name}"}, ensure_ascii=False)
if logger:
logger.error(result)
return name or "unknown", result
# Ensure arguments is a dict
if not isinstance(arguments, dict):
arguments = {"_": arguments}
import functools
loop = asyncio.get_running_loop()
arguments["conversation_id"] = query_id
func = functools.partial(tool['function'], **arguments)
# 根据工具名称选择不同的超时时间
if name == "browse_url":
timeout = 5400 # browse 是 1.5 小时
else:
timeout = 1800 # 其他工具就是 30 分钟
try:
out = await asyncio.wait_for(loop.run_in_executor(None, func), timeout=timeout)
result = out if isinstance(out, str) else json.dumps(out, ensure_ascii=False) # 返回结果一定是字符串
except asyncio.TimeoutError:
if USE_NLP_FORMAT_RETURN:
result = f"The tool call timed out: execution exceeded {timeout} seconds for tool '{name}'."
else:
result = json.dumps({"error": f"Tool call timeout: exceeded {timeout}s", "tool": name, "arguments": arguments}, ensure_ascii=False)
if logger:
logger.error(result)
except TypeError as te:
if USE_NLP_FORMAT_RETURN:
result = f"Tool '{name}' failed due to argument mismatch: {str(te)}. Input arguments: {arguments}."
else:
result = json.dumps({"error": f"Argument mismatch for tool '{name}': {str(te)}", "received": arguments}, ensure_ascii=False)
if logger:
logger.error(result)
except Exception as e:
if USE_NLP_FORMAT_RETURN:
result = f"Tool '{name}' encountered an error: {str(e)}."
else:
result = json.dumps({"error": f"Tool '{name}' raised an exception: {str(e)}"}, ensure_ascii=False)
if logger:
logger.error(result)
return name, result