Учебное пособие по вызову функций

Вызов функций упрощает получение структурированных выходных данных из генеративных моделей. Затем вы можете использовать эти выходные данные для вызова других API и возврата соответствующих данных ответа в модель. Другими словами, вызов функций помогает подключить генеративные модели к внешним системам, чтобы сгенерированный контент содержал самую актуальную и точную информацию.

Вы можете предоставить модели Gemini описания функций. Это функции, которые вы пишете на языке вашего приложения (то есть они не являются функциями Google Cloud). Модель может попросить вас вызвать функцию и отправить результат обратно, чтобы помочь модели обработать ваш запрос.

Если вы еще этого не сделали, ознакомьтесь с разделом «Введение в вызов функций», чтобы узнать больше. Вы также можете опробовать эту функцию в Google Colab или просмотреть пример кода в репозитории Gemini API Cookbook .

Пример API для управления освещением

Представьте, что у вас есть базовая система управления освещением с интерфейсом прикладного программирования (API), и вы хотите, чтобы пользователи могли управлять освещением с помощью простых текстовых запросов. Вы можете использовать функцию вызова функций для интерпретации запросов на изменение освещения от пользователей и преобразования их в вызовы API для установки значений освещения. Эта гипотетическая система управления освещением позволяет вам контролировать яркость света и его цветовую температуру, определяемую как два отдельных параметра:

Параметр Тип Необходимый Описание
brightness число да Уровень освещенности от 0 до 100. Ноль выключен, 100 — полная яркость.
colorTemperature нить да Цветовая температура светильника может быть daylight , cool или warm .

Для простоты эта воображаемая система освещения имеет только один источник света, поэтому пользователю не нужно указывать комнату или местоположение. Вот пример запроса JSON, который вы можете отправить в API управления освещением, чтобы изменить уровень освещенности на 50%, используя цветовую температуру дневного света:

{
  "brightness": "50",
  "colorTemperature": "daylight"
}

В этом руководстве показано, как настроить вызов функции для API Gemini, чтобы интерпретировать запросы пользователей на освещение и сопоставлять их с настройками API для управления значениями яркости и цветовой температуры источника света.

Прежде чем начать: настройте проект и ключ API.

Прежде чем вызывать API Gemini, вам необходимо настроить проект и ключ API.

Определить функцию API

Создайте функцию, которая выполняет запрос API. Эта функция должна быть определена в коде вашего приложения, но может вызывать службы или API за пределами вашего приложения. API Gemini не вызывает эту функцию напрямую, поэтому вы можете контролировать, как и когда эта функция выполняется, через код вашего приложения. В демонстрационных целях в этом руководстве определяется фиктивная функция API, которая просто возвращает запрошенные значения освещения:

def set_light_values(brightness, color_temp):
    """Set the brightness and color temperature of a room light. (mock API).

    Args:
        brightness: Light level from 0 to 100. Zero is off and 100 is full brightness
        color_temp: Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.

    Returns:
        A dictionary containing the set brightness and color temperature.
    """
    return {
        "brightness": brightness,
        "colorTemperature": color_temp
    }

Когда вы создаете функцию, которая будет использоваться моделью при вызове функции, вам следует включить как можно больше подробностей в описания функций и параметров. Генеративная модель использует эту информацию, чтобы определить, какую функцию выбрать и как предоставить значения параметров при вызове функции.

Объявляйте функции во время инициализации модели

Если вы хотите использовать вызов функций с моделью, вы должны объявить свои функции при инициализации объекта модели. Вы объявляете функции, устанавливая параметр tools модели:

model = genai.GenerativeModel(model_name='gemini-1.5-flash',
                              tools=[set_light_values])

Создать вызов функции

После того как вы инициализировали модель с объявлениями функций, вы можете запросить модель с определенной функцией. Вам следует использовать вызов функций с использованием подсказок чата ( sendMessage() ), поскольку вызов функций обычно выигрывает от наличия контекста предыдущих запросов и ответов.

chat = model.start_chat()
response = chat.send_message('Dim the lights so the room feels cozy and warm.')
response.text

Объект ChatSession Python SDK упрощает управление сеансами чата, обрабатывая историю разговоров за вас. Вы можете использовать enable_automatic_function_calling , чтобы SDK автоматически вызывал функцию.

# Create a chat session that automatically makes suggested function calls
chat = model.start_chat(enable_automatic_function_calling=True)

Параллельный вызов функций

В дополнение к базовому вызову функций, описанному выше, вы также можете вызывать несколько функций за один ход. В этом разделе показан пример использования параллельного вызова функций.

Определите инструменты.

def power_disco_ball(power: bool) -> bool:
    """Powers the spinning disco ball."""
    print(f"Disco ball is {'spinning!' if power else 'stopped.'}")
    return True


def start_music(energetic: bool, loud: bool, bpm: int) -> str:
    """Play some music matching the specified parameters.

    Args:
      energetic: Whether the music is energetic or not.
      loud: Whether the music is loud or not.
      bpm: The beats per minute of the music.

    Returns: The name of the song being played.
    """
    print(f"Starting music! {energetic=} {loud=}, {bpm=}")
    return "Never gonna give you up."


def dim_lights(brightness: float) -> bool:
    """Dim the lights.

    Args:
      brightness: The brightness of the lights, 0.0 is off, 1.0 is full.
    """
    print(f"Lights are now set to {brightness:.0%}")
    return True

Теперь вызовите модель с инструкцией, которая могла бы использовать все указанные инструменты.

# Set the model up with tools.
house_fns = [power_disco_ball, start_music, dim_lights]

model = genai.GenerativeModel(model_name="gemini-1.5-flash", tools=house_fns)

# Call the API.
chat = model.start_chat()
response = chat.send_message("Turn this place into a party!")

# Print out each of the function calls requested from this single call.
for part in response.parts:
    if fn := part.function_call:
        args = ", ".join(f"{key}={val}" for key, val in fn.args.items())
        print(f"{fn.name}({args})")
power_disco_ball(power=True)
start_music(energetic=True, loud=True, bpm=120.0)
dim_lights(brightness=0.3)

Каждый из напечатанных результатов отражает один вызов функции, запрошенный моделью. Чтобы отправить результаты обратно, включите ответы в том же порядке, в котором они были запрошены.

# Simulate the responses from the specified tools.
responses = {
    "power_disco_ball": True,
    "start_music": "Never gonna give you up.",
    "dim_lights": True,
}

# Build the response parts.
response_parts = [
    genai.protos.Part(function_response=genai.protos.FunctionResponse(name=fn, response={"result": val}))
    for fn, val in responses.items()
]

response = chat.send_message(response_parts)
print(response.text)
Let's get this party started! I've turned on the disco ball, started playing some upbeat music, and dimmed the lights. 🎶✨  Get ready to dance! 🕺💃

Сопоставление типов данных вызова функции

Автоматическое извлечение схемы из функций Python работает не во всех случаях. Например: он не обрабатывает случаи, когда вы описываете поля вложенного объекта-словаря, но API это поддерживает. API способен описывать любой из следующих типов:

AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType])

Клиентская библиотека google.ai.generativelanguage предоставляет доступ к типам низкого уровня, предоставляя вам полный контроль.

Сначала загляните в атрибут _tools модели, и вы увидите, как он описывает функции, которые вы передали модели:

def multiply(a:float, b:float):
    """returns a * b."""
    return a*b

model = genai.GenerativeModel(model_name='gemini-1.5-flash',
                             tools=[multiply])

model._tools.to_proto()
[function_declarations {
   name: "multiply"
   description: "returns a * b."
   parameters {
     type_: OBJECT
     properties {
       key: "b"
       value {
         type_: NUMBER
       }
     }
     properties {
       key: "a"
       value {
         type_: NUMBER
       }
     }
     required: "a"
     required: "b"
   }
 }]

Это возвращает список объектов genai.protos.Tool , которые будут отправлены в API. Если печатный формат вам не знаком, то это потому, что это классы Google protobuf. Каждый genai.protos.Tool (в данном случае 1) содержит список genai.protos.FunctionDeclarations , которые описывают функцию и ее аргументы.

Вот объявление той же функции умножения, написанное с использованием классов genai.protos . Обратите внимание, что эти классы просто описывают функцию API, но не включают ее реализацию. Таким образом, использование этого не работает с автоматическим вызовом функций, но функции не всегда нуждаются в реализации.

calculator = genai.protos.Tool(
    function_declarations=[
      genai.protos.FunctionDeclaration(
        name='multiply',
        description="Returns the product of two numbers.",
        parameters=genai.protos.Schema(
            type=genai.protos.Type.OBJECT,
            properties={
                'a':genai.protos.Schema(type=genai.protos.Type.NUMBER),
                'b':genai.protos.Schema(type=genai.protos.Type.NUMBER)
            },
            required=['a','b']
        )
      )
    ])

Аналогично, вы можете описать это как JSON-совместимый объект:

calculator = {'function_declarations': [
      {'name': 'multiply',
       'description': 'Returns the product of two numbers.',
       'parameters': {'type_': 'OBJECT',
       'properties': {
         'a': {'type_': 'NUMBER'},
         'b': {'type_': 'NUMBER'} },
       'required': ['a', 'b']} }]}
genai.protos.Tool(calculator)
function_declarations {
  name: "multiply"
  description: "Returns the product of two numbers."
  parameters {
    type_: OBJECT
    properties {
      key: "b"
      value {
        type_: NUMBER
      }
    }
    properties {
      key: "a"
      value {
        type_: NUMBER
      }
    }
    required: "a"
    required: "b"
  }
}

В любом случае вы передаете представление genai.protos.Tool или список инструментов в

model = genai.GenerativeModel('gemini-1.5-flash', tools=calculator)
chat = model.start_chat()

response = chat.send_message(
    f"What's 234551 X 325552 ?",
)

Как и раньше, модель возвращает genai.protos.FunctionCall вызывая функцию multiply калькулятора:

response.candidates
[index: 0
content {
  parts {
    function_call {
      name: "multiply"
      args {
        fields {
          key: "b"
          value {
            number_value: 325552
          }
        }
        fields {
          key: "a"
          value {
            number_value: 234551
          }
        }
      }
    }
  }
  role: "model"
}
finish_reason: STOP
]

Выполните функцию самостоятельно:

fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'

result = fc.args['a'] * fc.args['b']
result
76358547152.0

Отправьте результат модели, чтобы продолжить разговор:

response = chat.send_message(
    genai.protos.Content(
    parts=[genai.protos.Part(
        function_response = genai.protos.FunctionResponse(
          name='multiply',
          response={'result': result}))]))