google-gemini / generative-ai-python

The official Python library for the Google Gemini API
https://pypi.org/project/google-generativeai/
Apache License 2.0
1.65k stars 330 forks source link

Function calling doesn't work with functions that take no arguments. #423

Closed xiaokang00010 closed 4 months ago

xiaokang00010 commented 5 months ago

Description of the bug:

My app ran well with function calling 12 days ago. However, when I tried to use this app today, Gemini API raised an InvalidArgument exception. And I managed to figure out it will only occurs when tools argument is not empty.

Actual vs expected behavior:

It raises an InvalidArgument exception. The expected behaviour is that it should return a normal response like it used to.

Any other information you'd like to share?

Minimal reproducible example:

import models, chatModel
import tools

def calculate(expression: str) -> int | float | str:
    """
    Calculate an expression using Python 3 and return the number value.
    You can use the following operators: +, -, *, /, **, %, //, and ().
    You are allowed to use math library.

    Args:
        expression (str): The expression to evaluate.

    Returns:
        int | float | str: The result of the expression.
    """
    return eval(expression, globals(), locals())

def time() -> str:
    """
    Get the current time in HH:MM:SS format.

    Returns:
        str: The current time in HH:MM:SS format.
    """
    return tools.TimeProvider()

m = genai.GenerativeModel(model_name=config.USE_MODEL, system_instruction='You are an AI chatbot named Yoi.', safety_settings=models.MODEL_SAFETY_SETTING, generation_config={
            'temperature': 0.9,
        }, tools=[calculate, time])

s = m.start_chat()
print(s.send_message("Hello?"))

Log:

Logger: using stdout
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
Traceback (most recent call last):
  File "/home/chou/CyberWaifu-v2/aaa.py", line 38, in <module>
    print(s.send_message("What is the time?"))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/generativeai/generative_models.py", line 578, in send_message
    response = self.model.generate_content(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/generativeai/generative_models.py", line 331, in generate_content
    response = self._client.generate_content(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/ai/generativelanguage_v1beta/services/generative_service/client.py", line 827, in generate_content
    response = rpc(
               ^^^^
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/api_core/gapic_v1/method.py", line 131, in __call__
    return wrapped_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/api_core/retry/retry_unary.py", line 293, in retry_wrapped_func
    return retry_target(
           ^^^^^^^^^^^^^
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/api_core/retry/retry_unary.py", line 153, in retry_target
    _retry_error_helper(
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/api_core/retry/retry_base.py", line 212, in _retry_error_helper
    raise final_exc from source_exc
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/api_core/retry/retry_unary.py", line 144, in retry_target
    result = target()
             ^^^^^^^^
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/api_core/timeout.py", line 120, in func_with_timeout
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/chou/miniconda3/envs/cyberWaifuV2/lib/python3.12/site-packages/google/api_core/grpc_helpers.py", line 78, in error_remapped_callable
    raise exceptions.from_grpc_error(exc) from exc
google.api_core.exceptions.InvalidArgument: 400 Request contains an invalid argument.
xiaokang00010 commented 5 months ago

I found that it is directly related to the time function in my example. I don't know why, but if I add time into tools list, it just won't work. However, if there's only calculate function. It works again.

xiaokang00010 commented 5 months ago

Okay, I found that it can correctly invoke tool function if there's any param in the function declaration like the code in below. But why is that?

def getTime(arg: str) -> str:
    """
    Get the current time.

    Args:
        arg (str): random string

    Returns:
        str: The current time
    """
    return '1970-01-01 00:00:00'
MarkDaoust commented 4 months ago

This was fixed by #406