(self, tool_info: ToolCall)
| 199 | return sorted(tools, key=lambda t: (t.get('tool_name', ''), )) |
| 200 | |
| 201 | async def single_call_tool(self, tool_info: ToolCall): |
| 202 | if self._concurrent_limiter is None: |
| 203 | if self._init_lock is None: |
| 204 | self._init_lock = asyncio.Lock() |
| 205 | async with self._init_lock: |
| 206 | if self._concurrent_limiter is None: |
| 207 | self._concurrent_limiter = asyncio.Semaphore( |
| 208 | MAX_CONCURRENT_TOOLS) |
| 209 | |
| 210 | async with self._concurrent_limiter: |
| 211 | brief_info = json.dumps(tool_info, ensure_ascii=False) |
| 212 | if len(brief_info) > 1024: |
| 213 | brief_info = brief_info[:1024] + '...' |
| 214 | try: |
| 215 | tool_name = tool_info['tool_name'] |
| 216 | tool_args = tool_info['arguments'] |
| 217 | while isinstance(tool_args, str): |
| 218 | try: |
| 219 | tool_args = json.loads(tool_args) |
| 220 | except Exception: # noqa |
| 221 | return f'The input {tool_args} is not a valid JSON, fix your arguments and try again' |
| 222 | assert tool_name in self._tool_index, f'Tool name {tool_name} not found' |
| 223 | tool_ins, server_name, _ = self._tool_index[tool_name] |
| 224 | call_args = tool_args |
| 225 | if isinstance(tool_ins, AgentTool): |
| 226 | call_args = dict(tool_args or {}) |
| 227 | call_id = tool_info.get('id') or str(uuid.uuid4()) |
| 228 | call_args['__call_id'] = call_id |
| 229 | response = await asyncio.wait_for( |
| 230 | tool_ins.call_tool( |
| 231 | server_name, |
| 232 | tool_name=tool_name.split(self.TOOL_SPLITER)[1], |
| 233 | tool_args=call_args), |
| 234 | timeout=self.tool_call_timeout) |
| 235 | return response |
| 236 | except asyncio.TimeoutError: |
| 237 | import traceback |
| 238 | logger.warning(traceback.format_exc()) |
| 239 | # TODO: How to get the information printed by the tool before hanging to return to the model? |
| 240 | return f'Execute tool call timeout: {brief_info}' |
| 241 | except Exception as e: |
| 242 | import traceback |
| 243 | logger.warning(traceback.format_exc()) |
| 244 | return f'Tool calling failed: {brief_info}, details: {str(e)}' |
| 245 | |
| 246 | async def parallel_call_tool(self, tool_list: List[ToolCall]): |
| 247 | tasks = [self.single_call_tool(tool) for tool in tool_list] |
no test coverage detected