Skip to content

[BFCL] Function-calling parser returns empty response when tool_calls=[] #1331

@ankush13r

Description

@ankush13r

Describe the issue
_parse_query_response_FC does not correctly handle API responses where message.tool_calls exists but is an empty list ([]). In that case, the current implementation returns model_responses=[] instead of falling back to message.content.

ID datapoint

  1. Datapoint / Model Handler permalink:
  2. Issue: Function-calling parser returns empty model_responses when tool_calls=[]
  3. Gorilla repo commit #: 6ea5797

What is the issue
Some APIs return tool_calls=[] even when the model response is a normal text response available in message.content.

The current code only falls back to message.content inside the except block. However, when tool_calls is present as an empty list, no exception is raised (vllm returns empty tool_calls):

model_responses = [
    {func_call.function.name: func_call.function.arguments}
    for func_call in api_response.choices[0].message.tool_calls
]

This produces:

model_responses = []
tool_call_ids = []

As a result, the parser returns an empty response instead of the actual model content.

Proposed Changes

Add an explicit fallback when model_responses is empty after parsing tool_calls. Also keep the existing try/except behavior for legacy compatibility.

def _parse_query_response_FC(self, api_response: Any) -> dict:
    try:
        message = api_response.choices[0].message

        model_responses = [
            {func_call.function.name: func_call.function.arguments}
            for func_call in message.tool_calls
        ]
        tool_call_ids = [
            func_call.id for func_call in message.tool_calls
        ]

        if not model_responses:
            model_responses = message.content
            tool_call_ids = []

    except Exception:
        message = api_response.choices[0].message
        model_responses = message.content
        tool_call_ids = []

    model_responses_message_for_chat_history = message

    return {
        "model_responses": model_responses,
        "model_responses_message_for_chat_history": model_responses_message_for_chat_history,
        "tool_call_ids": tool_call_ids,
        "input_token": api_response.usage.prompt_tokens,
        "output_token": api_response.usage.completion_tokens,
    }
{
    "previous_datapoint": [],
    "updated_datapoint": [
        {
            "change": "Add fallback to message.content when parsed tool_calls produce an empty model_responses list.",
            "reason": "Some APIs return tool_calls=[] for non-function-call responses, which currently causes the parser to return an empty response instead of the textual content."
        },
        {
            "change": "Keep try/except fallback for legacy response shapes.",
            "reason": "Maintains backward compatibility with APIs that may not expose tool_calls or may use a different response schema."
        }
    ]
}

Additional context
This issue affects function-calling model handlers when the API returns a valid assistant message with content, but also includes tool_calls=[]. The parser should treat an empty tool_calls list the same as no function call and return the text content instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions