Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions google/genai/_extra_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,10 +472,13 @@ def should_disable_afc(
not config_model.automatic_function_calling
or config_model.automatic_function_calling.disable is None
):
return False
afc_disabled = False
else:
afc_disabled = bool(config_model.automatic_function_calling.disable)

if (
config_model.automatic_function_calling.disable
afc_disabled
and config_model.automatic_function_calling
and config_model.automatic_function_calling.maximum_remote_calls
is not None
# exclude the case where max_remote_calls is set to 10 by default.
Expand All @@ -496,7 +499,23 @@ def should_disable_afc(
' `automatic_function_calling.maximum_remote_calls` unset.'
)

return config_model.automatic_function_calling.disable
if (
not afc_disabled
and config_model.tool_config
and config_model.tool_config.function_calling_config
and config_model.tool_config.function_calling_config.mode
in (types.FunctionCallingConfigMode.ANY, 'ANY', 'any')
):
logger.warning(
'`tool_config.function_calling_config.mode` is set to `ANY` with'
' automatic function calling enabled. The model is forced to call a'
' function on every turn and cannot return a text response, which will'
' exhaust `maximum_remote_calls` and return empty text. If you want the'
' model to answer with text, use mode=`AUTO`, or disable automatic'
' function calling to manually orchestrate tool calls.'
)

return afc_disabled


def get_max_remote_calls_afc(
Expand Down
55 changes: 55 additions & 0 deletions google/genai/tests/afc/test_should_disable_afc.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

"""Tests for should_disable_afc."""

import logging
import pytest
from .. import pytest_helper
from ... import types
Expand Down Expand Up @@ -213,3 +214,57 @@ def test_afc_enable_true_max_1():
)
is False
)


def test_afc_mode_any_warns(caplog):
with caplog.at_level(logging.WARNING, logger='google_genai.models'):
config = types.GenerateContentConfig(
tool_config=types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(mode='ANY')
)
)
result = should_disable_afc(config)
assert result is False
assert len(caplog.records) == 1
assert '`tool_config.function_calling_config.mode` is set to `ANY`' in caplog.records[0].message


def test_afc_mode_any_dict_warns(caplog):
with caplog.at_level(logging.WARNING, logger='google_genai.models'):
config = {
'tool_config': {
'function_calling_config': {'mode': 'ANY'}
}
}
result = should_disable_afc(config)
assert result is False
assert len(caplog.records) == 1
assert '`tool_config.function_calling_config.mode` is set to `ANY`' in caplog.records[0].message


def test_afc_mode_any_disabled_no_warn(caplog):
with caplog.at_level(logging.WARNING, logger='google_genai.models'):
config = types.GenerateContentConfig(
tool_config=types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(mode='ANY')
),
automatic_function_calling=types.AutomaticFunctionCallingConfig(
disable=True
),
)
result = should_disable_afc(config)
assert result is True
assert len(caplog.records) == 0


def test_afc_mode_auto_no_warn(caplog):
with caplog.at_level(logging.WARNING, logger='google_genai.models'):
config = types.GenerateContentConfig(
tool_config=types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(mode='AUTO')
)
)
result = should_disable_afc(config)
assert result is False
assert len(caplog.records) == 0

Loading