Введение в Function Calling: Подключение внешних инструментов

50 минут Урок 12

Введение: Когда слов недостаточно

Добро пожаловать в третий модуль. До этого момента мы взаимодействовали с Gemini в основном как с «мозгом в банке». Модель могла писать стихи, анализировать тексты и даже генерировать код, но она была изолирована от внешнего мира. Она не знала, какая сейчас погода в Токио, не могла проверить остаток на вашем банковском счете и уж точно не могла отправить письмо за вас.

Function Calling (Вызов функций) — это мост, соединяющий интеллект модели с реальными действиями и данными. Это механизм, который превращает LLM из чат-бота в агента.

Как это работает на самом деле?

Важно сразу развеять популярный миф: Gemini не выполняет ваш код внутри своих нейронов. Модель не запускает Python-скрипты сама по себе.

Процесс выглядит иначе:

  1. Вы описываете модели инструменты (функции), которые у вас есть (например, send_email или get_stock_price).
  2. Вы задаете вопрос, требующий использования инструмента.
  3. Модель понимает намерение и вместо текстового ответа возвращает структурированный запрос: «Пожалуйста, вызови функцию get_stock_price с аргументом 'AAPL'».
  4. Ваше приложение выполняет эту функцию.
  5. Вы возвращаете результат работы функции обратно модели.
  6. Модель формирует финальный ответ для пользователя, используя полученные данные.

В этом уроке мы научимся настраивать этот диалог.

Шаг 1: Определение инструментов

Для Gemini инструмент (Tool) — это описание функции. Модель полагается на названия функций, названия параметров и, что критически важно, на docstrings (строки документации), чтобы понять, что делает код.

Если вы назовете функцию func1 и параметр a, модель вряд ли догадается, как её использовать. Если же вы назовете её find_coffee_shops с параметром location, модель поймет семантику.

Давайте посмотрим, как объявить простую функцию, которую мы захотим «скармливать» модели.

python
# Представим, что это наша локальная база данных или API

def get_product_info(product_id: str):
    """
    Получает информацию о продукте по его ID.
    
    Args:
        product_id: Уникальный идентификатор товара (например, 'A-123').
    """
    # В реальном приложении здесь был бы запрос к БД
    mock_db = {
        "A-123": {"name": "Умная колонка", "price": 5000, "stock": 12},
        "B-456": {"name": "Беспроводные наушники", "price": 8000, "stock": 0}
    }
    return mock_db.get(product_id, {"error": "Product not found"})

# Этот словарь инструментов мы будем передавать модели
tools_list = [get_product_info]

Шаг 2: Подключение инструментов к Gemini

В SDK Google Generative AI (Python) процесс подключения максимально упрощен. Вам не нужно вручную писать JSON-схемы (хотя под капотом происходит именно это). Библиотека сама конвертирует сигнатуру вашей Python-функции в формат, понятный модели.

Мы передаем список функций через параметр tools при создании объекта модели.

python
import google.generativeai as genai
import os

# Настройка API ключа
genai.configure(api_key=os.environ["GOOGLE_API_KEY"])

# Инициализация модели с инструментами
model = genai.GenerativeModel(
    model_name='gemini-1.5-flash',
    tools=tools_list  # Передаем нашу функцию get_product_info
)

# Создаем чат-сессию с включенным автоматическим выполнением функций
# enable_automatic_function_execution=True позволяет SDK самому 
# вызывать функцию и возвращать ответ модели, скрывая от нас рутину.
chat = model.start_chat(enable_automatic_function_execution=True)

Режим автоматического выполнения vs Ручной контроль

В коде выше мы использовали enable_automatic_function_execution=True. Это отличная фича SDK для быстрого старта. Она создает цикл:

  • Модель просит вызвать функцию -> SDK вызывает -> SDK отправляет результат -> Модель отвечает текстом.

Однако в Enterprise-решениях часто требуется ручной контроль (Manual Mode). Почему?

  • Безопасность: Вы хотите проверить аргументы перед тем, как функция выполнится (например, чтобы не удалить случайно данные).
  • Асинхронность: Функция может выполняться долго, и вы хотите отправить пользователю сообщение «Подождите, ищу информацию...».
  • Клиент-серверная архитектура: Модель работает на сервере, а функцию нужно выполнить на устройстве клиента (например, включить фонарик на телефоне).

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

python
# Эмуляция диалога
response = chat.send_message("Сколько стоят наушники с id B-456 и есть ли они в наличии?")

# Благодаря автоматическому режиму, мы сразу получим финальный ответ
print(f"Ответ модели: {response.text}")

# В консоли мы увидим что-то вроде:
# "Стоимость беспроводных наушников составляет 8000, но, к сожалению, их сейчас нет в наличии."

Анатомия запроса (Под капотом)

Если бы мы отключили автоматическое выполнение, первый ответ от Gemini (response.parts) содержал бы не текст, а объект FunctionCall. Он выглядел бы примерно так:

name: "get_product_info"
args {
  fields {
    key: "product_id"
    value {
      string_value: "B-456"
    }
  }
}

Это ключевой момент: модель не галлюцинирует данные, она запрашивает их получение через четко структурированный интерфейс.

Лучшие практики описания функций

Качество работы Function Calling напрямую зависит от того, как вы описали функции. Это называется «Prompt Engineering для кода».

  • Имена: Используйте понятные глаголы (get_, set_, find_, calculate_).
  • Type Hints: Всегда указывайте типы аргументов (str, int, bool). Gemini использует их для валидации.
  • Docstrings: Это самое важное. Описывайте не только что делает функция, но и в каком формате должен быть аргумент (например, "Дата в формате YYYY-MM-DD").

Упражнение

Создайте ассистента для управления умным домом. Вам нужно:<br>1. Написать функцию `set_light_color(room: str, color: str, brightness: int)`, которая принимает название комнаты, цвет и яркость (от 0 до 100). Функция должна просто возвращать строку подтверждения (имитация).<br>2. Инициализировать модель Gemini 1.5 Flash с этим инструментом.<br>3. Спросить модель: «Включи в гостиной мягкий вечерний свет» (модель должна сама догадаться о параметрах, например, теплый цвет и средняя яркость, или уточнить их).

Вопрос

Кто выполняет программный код функции (например, обращение к базе данных) при использовании Function Calling?