Skip to content

Commit 887a4bf

Browse files
enystadityasoni9998
authored andcommitted
Simplify fn calling usage (All-Hands-AI#6596)
1 parent c5ae222 commit 887a4bf

File tree

3 files changed

+14
-33
lines changed

3 files changed

+14
-33
lines changed

openhands/agenthub/codeact_agent/codeact_agent.py

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,7 @@ def __init__(
9090
self.pending_actions: deque[Action] = deque()
9191
self.reset()
9292

93-
self.mock_function_calling = False
94-
if not self.llm.is_function_calling_active():
95-
logger.info(
96-
f'Function calling not enabled for model {self.llm.config.model}. '
97-
'Mocking function calling via prompting.'
98-
)
99-
self.mock_function_calling = True
100-
101-
# Function calling mode
93+
# Retrieve the enabled tools
10294
self.tools = codeact_function_calling.get_tools(
10395
codeact_enable_browsing=self.config.codeact_enable_browsing,
10496
codeact_enable_jupyter=self.config.codeact_enable_jupyter,
@@ -311,10 +303,7 @@ def get_observation_message(
311303
and len(obs.set_of_marks) > 0
312304
and self.config.enable_som_visual_browsing
313305
and self.llm.vision_is_active()
314-
and (
315-
self.mock_function_calling
316-
or self.llm.is_visual_browser_tool_active()
317-
)
306+
and self.llm.is_visual_browser_tool_supported()
318307
):
319308
text += 'Image: Current webpage screenshot (Note that only visible portion of webpage is present in the screenshot. You may need to scroll to view the remaining portion of the web-page.)\n'
320309
message = Message(
@@ -400,8 +389,6 @@ def step(self, state: State) -> Action:
400389
'messages': self.llm.format_messages_for_llm(messages),
401390
}
402391
params['tools'] = self.tools
403-
if self.mock_function_calling:
404-
params['mock_function_calling'] = True
405392
response = self.llm.completion(**params)
406393
actions = codeact_function_calling.response_to_actions(response)
407394
for action in actions:

openhands/llm/llm.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def wrapper(*args, **kwargs):
197197
from openhands.core.utils import json
198198

199199
messages: list[dict[str, Any]] | dict[str, Any] = []
200-
mock_function_calling = kwargs.pop('mock_function_calling', False)
200+
mock_function_calling = not self.is_function_calling_active()
201201

202202
# some callers might send the model and messages directly
203203
# litellm allows positional args, like completion(model, messages, **kwargs)
@@ -216,18 +216,21 @@ def wrapper(*args, **kwargs):
216216

217217
# ensure we work with a list of messages
218218
messages = messages if isinstance(messages, list) else [messages]
219+
220+
# handle conversion of to non-function calling messages if needed
219221
original_fncall_messages = copy.deepcopy(messages)
220222
mock_fncall_tools = None
221-
if mock_function_calling:
222-
assert (
223-
'tools' in kwargs
224-
), "'tools' must be in kwargs when mock_function_calling is True"
223+
# if the agent or caller has defined tools, and we mock via prompting, convert the messages
224+
if mock_function_calling and 'tools' in kwargs:
225225
messages = convert_fncall_messages_to_non_fncall_messages(
226226
messages, kwargs['tools']
227227
)
228228
kwargs['messages'] = messages
229+
230+
# add stop words if the model supports it
229231
if self.config.model not in MODELS_WITHOUT_STOP_WORDS:
230232
kwargs['stop'] = STOP_WORDS
233+
231234
mock_fncall_tools = kwargs.pop('tools')
232235

233236
# if we have no messages, something went very wrong
@@ -256,9 +259,10 @@ def wrapper(*args, **kwargs):
256259
self.metrics.add_response_latency(latency, response_id)
257260

258261
non_fncall_response = copy.deepcopy(resp)
259-
if mock_function_calling:
262+
263+
# if we mocked function calling, and we have tools, convert the response back to function calling format
264+
if mock_function_calling and mock_fncall_tools is not None:
260265
assert len(resp.choices) == 1
261-
assert mock_fncall_tools is not None
262266
non_fncall_response_message = resp.choices[0].message
263267
fn_call_messages_with_response = (
264268
convert_non_fncall_messages_to_fncall_messages(
@@ -488,7 +492,7 @@ def is_function_calling_active(self) -> bool:
488492
"""
489493
return self._function_calling_active
490494

491-
def is_visual_browser_tool_active(self) -> bool:
495+
def is_visual_browser_tool_supported(self) -> bool:
492496
return (
493497
self.config.model in VISUAL_BROWSING_TOOL_SUPPORTED_MODELS
494498
or self.config.model.split('/')[-1] in VISUAL_BROWSING_TOOL_SUPPORTED_MODELS

tests/unit/test_codeact_agent.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -464,16 +464,6 @@ def test_browser_tool():
464464
assert 'description' in BrowserTool['function']['parameters']['properties']['code']
465465

466466

467-
def test_mock_function_calling():
468-
# Test mock function calling when LLM doesn't support it
469-
llm = Mock()
470-
llm.is_function_calling_active = lambda: False
471-
config = AgentConfig()
472-
config.enable_prompt_extensions = False
473-
agent = CodeActAgent(llm=llm, config=config)
474-
assert agent.mock_function_calling is True
475-
476-
477467
def test_response_to_actions_invalid_tool():
478468
# Test response with invalid tool call
479469
mock_response = Mock()

0 commit comments

Comments
 (0)