Skip to content

Commit

Permalink
[BFCL] Resolve Issue in Gemini Model When No Model Output (#809)
Browse files Browse the repository at this point in the history
When the Gemini models output no content, the `api_response.candidates`
will be `[]`, and so calling `api_response.candidates[0].content.parts`
will give `IndexError: list index out of range`. We should check if
there is a candidate before accessing its content.
  • Loading branch information
HuanzhiMao authored Dec 3, 2024
1 parent dd7c892 commit d7e52e5
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 21 deletions.
2 changes: 1 addition & 1 deletion berkeley-function-call-leaderboard/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ FIREWORKS_API_KEY=
ANTHROPIC_API_KEY=
NVIDIA_API_KEY=nvapi-XXXXXX
YI_API_KEY=
GROK_API_KEY=
GROK_API_KEY=xai-XXXXXX
GOGOAGENT_API_KEY=
WRITER_API_KEY=

Expand Down
1 change: 1 addition & 0 deletions berkeley-function-call-leaderboard/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
All notable changes to the Berkeley Function Calling Leaderboard will be documented in this file.

- [Dec 3, 2024] [#810](https://github.com/ShishirPatil/gorilla/pull/810): Add new model `grok-beta` to the leaderboard.
- [Dec 2, 2024] [#809](https://github.com/ShishirPatil/gorilla/pull/809): Resolve issue in Gemini model when no model output.
- [Dec 2, 2024] [#808](https://github.com/ShishirPatil/gorilla/pull/808): Improve latency measurement accuracy.
- [Nov 26, 2024] [#755](https://github.com/ShishirPatil/gorilla/pull/755): Add new model `palmyra-x-004` to the leaderboard.
- [Nov 25, 2024] [#718](https://github.com/ShishirPatil/gorilla/pull/718): Add new model `openbmb/MiniCPM3-4B-FC` to the leaderboard.
Expand Down
2 changes: 1 addition & 1 deletion berkeley-function-call-leaderboard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ FIREWORKS_API_KEY=
ANTHROPIC_API_KEY=
NVIDIA_API_KEY=nvapi-XXXXXX
YI_API_KEY=
GROK_API_KEY=
GROK_API_KEY=xai-XXXXXX
GOGOAGENT_API_KEY=
WRITER_API_KEY=

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import time

from bfcl.model_handler.model_style import ModelStyle
from bfcl.model_handler.oss_model.base_oss_handler import OSSHandler
Expand Down Expand Up @@ -114,9 +115,11 @@ def _query_prompting(self, inference_data: dict):
"function": function,
}

start_time = time.time()
api_response = self.client.completion(messages=message, tools=function)
end_time = time.time()

return api_response
return api_response, end_time - start_time


# fmt: off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def _query_FC(self, inference_data: dict):
generation_config=GenerationConfig(
temperature=self.temperature,
),
tools=tools
tools=tools,
)

def _pre_query_processing_FC(self, inference_data: dict, test_entry: dict) -> dict:
Expand Down Expand Up @@ -152,33 +152,38 @@ def _compile_tools(self, inference_data: dict, test_entry: dict) -> dict:
return inference_data

def _parse_query_response_FC(self, api_response: any) -> dict:
response_function_call_content = api_response.candidates[0].content
tool_call_func_names = []
fc_parts = []
text_parts = []
for part in api_response.candidates[0].content.parts:
# part.function_call is a FunctionCall object, so it will always be True even if it contains no function call
# So we need to check if the function name is empty `""` to determine if Gemini returned a function call
if part.function_call and part.function_call.name:
part_func_name = part.function_call.name
part_func_args = part.function_call.args
part_func_args_dict = {k: v for k, v in part_func_args.items()}

fc_parts.append({part_func_name: part_func_args_dict})
tool_call_func_names.append(part_func_name)
else:
text_parts.append(part.text)

model_responses = fc_parts if fc_parts else text_parts

if len(api_response.candidates[0].content.parts) == 0:
if (
len(api_response.candidates) > 0
and len(api_response.candidates[0].content.parts) > 0
):
response_function_call_content = api_response.candidates[0].content

for part in api_response.candidates[0].content.parts:
# part.function_call is a FunctionCall object, so it will always be True even if it contains no function call
# So we need to check if the function name is empty `""` to determine if Gemini returned a function call
if part.function_call and part.function_call.name:
part_func_name = part.function_call.name
part_func_args = part.function_call.args
part_func_args_dict = {k: v for k, v in part_func_args.items()}

fc_parts.append({part_func_name: part_func_args_dict})
tool_call_func_names.append(part_func_name)
else:
text_parts.append(part.text)
else:
response_function_call_content = Content(
role="model",
parts=[
Part.from_text("The model did not return any response."),
],
)

model_responses = fc_parts if fc_parts else text_parts

return {
"model_responses": model_responses,
"model_responses_message_for_chat_history": response_function_call_content,
Expand Down Expand Up @@ -288,7 +293,10 @@ def _pre_query_processing_prompting(self, test_entry: dict) -> dict:
return {"message": []}

def _parse_query_response_prompting(self, api_response: any) -> dict:
if len(api_response.candidates[0].content.parts) > 0:
if (
len(api_response.candidates) > 0
and len(api_response.candidates[0].content.parts) > 0
):
model_responses = api_response.text
else:
model_responses = "The model did not return any response."
Expand Down

0 comments on commit d7e52e5

Please sign in to comment.