Improve function call validation with better error handling (#6453)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Xingyao Wang
2025-01-27 13:42:45 -05:00
committed by GitHub
parent ffdab28abc
commit 4bde644fab
2 changed files with 265 additions and 8 deletions

View File

@@ -12,7 +12,10 @@ from litellm import (
ModelResponse,
)
from openhands.core.exceptions import FunctionCallNotExistsError
from openhands.core.exceptions import (
FunctionCallNotExistsError,
FunctionCallValidationError,
)
from openhands.core.logger import openhands_logger as logger
from openhands.events.action import (
Action,
@@ -494,15 +497,19 @@ def response_to_actions(response: ModelResponse) -> list[Action]:
f'Failed to parse tool call arguments: {tool_call.function.arguments}'
) from e
if tool_call.function.name == 'execute_bash':
# this is an LLM error: add empty command to avoid breaking the tool call
if 'command' not in arguments:
arguments['command'] = ''
raise FunctionCallValidationError(
f'Missing required argument "command" in tool call {tool_call.function.name}'
)
# convert is_input to boolean
if 'is_input' in arguments:
arguments['is_input'] = arguments['is_input'] == 'true'
action = CmdRunAction(**arguments)
is_input = arguments.get('is_input', 'false') == 'true'
action = CmdRunAction(command=arguments['command'], is_input=is_input)
elif tool_call.function.name == 'execute_ipython_cell':
action = IPythonRunCellAction(**arguments)
if 'code' not in arguments:
raise FunctionCallValidationError(
f'Missing required argument "code" in tool call {tool_call.function.name}'
)
action = IPythonRunCellAction(code=arguments['code'])
elif tool_call.function.name == 'delegate_to_browsing_agent':
action = AgentDelegateAction(
agent='BrowsingAgent',
@@ -511,8 +518,30 @@ def response_to_actions(response: ModelResponse) -> list[Action]:
elif tool_call.function.name == 'finish':
action = AgentFinishAction()
elif tool_call.function.name == 'edit_file':
action = FileEditAction(**arguments)
if 'path' not in arguments:
raise FunctionCallValidationError(
f'Missing required argument "path" in tool call {tool_call.function.name}'
)
if 'content' not in arguments:
raise FunctionCallValidationError(
f'Missing required argument "content" in tool call {tool_call.function.name}'
)
action = FileEditAction(
path=arguments['path'],
content=arguments['content'],
start=arguments.get('start', 1),
end=arguments.get('end', -1),
)
elif tool_call.function.name == 'str_replace_editor':
if 'command' not in arguments:
raise FunctionCallValidationError(
f'Missing required argument "command" in tool call {tool_call.function.name}'
)
if 'path' not in arguments:
raise FunctionCallValidationError(
f'Missing required argument "path" in tool call {tool_call.function.name}'
)
# We implement this in agent_skills, which can be used via Jupyter
# convert tool_call.function.arguments to kwargs that can be passed to file_editor
code = f'print(file_editor(**{arguments}))'
@@ -534,8 +563,16 @@ def response_to_actions(response: ModelResponse) -> list[Action]:
impl_source=FileEditSource.OH_ACI,
)
elif tool_call.function.name == 'browser':
if 'code' not in arguments:
raise FunctionCallValidationError(
f'Missing required argument "code" in tool call {tool_call.function.name}'
)
action = BrowseInteractiveAction(browser_actions=arguments['code'])
elif tool_call.function.name == 'web_read':
if 'url' not in arguments:
raise FunctionCallValidationError(
f'Missing required argument "url" in tool call {tool_call.function.name}'
)
action = BrowseURLAction(url=arguments['url'])
else:
raise FunctionCallNotExistsError(