Назад до блогу

API та SDKПосібник

Function calling на Python із сумісним з OpenAI API

Надсилайте інструменти, читайте tool_calls і повертайте результат із роллю tool: двокроковий цикл function calling на Python з MiniMax-M2.7.

Автор: CheapTokens TeamОпубліковано Оновлено 5 хв читання

Діаграма двокрокового циклу виклику інструментів: надіслати інструменти, прочитати tool_calls, повернути результат як повідомлення інструменту
На цій сторінці
  1. Як працює function calling
  2. Налаштування клієнта
  3. Оголошення функції та надсилання першого запиту
  4. Що ви маєте побачити
  5. Кілька викликів і довші цикли
  6. Чому MiniMax-M2.7 підходить для циклів з інструментами
  7. Якщо не працює
  8. Наступні кроки

Function calling (виклик інструментів) дозволяє моделі попросити ваш код виконати функцію. Ви надсилаєте список tools разом із запитом, модель відповідає tool_calls замість тексту, ви самі запускаєте функцію та надсилаєте її результат назад у повідомленні з role: tool. Потім модель пише остаточну відповідь. Цей посібник показує весь цикл на Python із використанням сумісного з OpenAI ендпоінту https://api.cheaptokens.dev/v1/chat/completions з MiniMax-M2.7 (id MiniMaxAI/MiniMax-M2.7, контекст 180K, до 8 192 вихідних токенів на відповідь).

Виклик інструментів позначено як підтримуваний для кожної моделі в каталозі (CheapTokens docs, перевірено 22 жовтня 2026 року). Вам потрібен API-ключ; якщо ви ще не робили запитів, почніть із вашого першого API-запиту.

Як працює function calling#

Модель нічого не виконує. Вона лише створює структурований запит: "виклич get_weather з {\"city\": \"Paris\"}". Ваша програма виконує реальну роботу та повідомляє результат. Це утворює цикл із двох запитів:

  1. Запит 1. Ви надсилаєте повідомлення користувача разом зі списком tools. Модель або відповідає текстом, або повертає один чи кілька tool_calls.
  2. Ваш код. Ви розбираєте кожен виклик, запускаєте відповідну функцію та збираєте результат.
  3. Запит 2. Ви знову надсилаєте всю розмову: оригінальні повідомлення, повідомлення асистента з tool_calls та одне повідомлення role: tool на кожен виклик. Модель використовує результати, щоб написати остаточну відповідь.

Кожен запит повторно надсилає всю історію, тому цикли з інструментами використовують більше вхідних токенів, ніж одне запитання. Якщо це для вас нове, прочитайте що таке токен.

Налаштування клієнта#

Встановіть OpenAI SDK (pip install openai) і помістіть ключ у змінну середовища, а не у вихідний код:

bash
export CHEAPTOKENS_API_KEY="your-key-here"

Базова URL-адреса — https://api.cheaptokens.dev/v1. Беріть id моделі з документації CheapTokens: різні провайдери називають ту саму модель по-різному. У цьому посібнику використовується MiniMaxAI/MiniMax-M2.7.

Оголошення функції та надсилання першого запиту#

Функція описується в масиві tools. Кожен елемент має type: function та об'єкт function з name, description та parameters, записаними як JSON Schema. Опис — це те, що читає модель, щоб вирішити, коли викликати функцію, тому пишіть його коротким і конкретним реченням.

Нижче наведено повний скрипт. Функція погоди — це заглушка з фіктивними даними, тому приклад не потребує додаткових сервісів:

python
import json
import os

from openai import OpenAI

client = OpenAI(
    base_url='https://api.cheaptokens.dev/v1',
    api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'MiniMaxAI/MiniMax-M2.7'


def get_weather(city: str) -> dict:
    # Stub with fake data: replace with a real lookup
    fake = {'Paris': 14, 'Tokyo': 19}
    return {'city': city, 'temp_c': fake.get(city, 10)}


FUNCTIONS = {'get_weather': get_weather}

tools = [
    {
        'type': 'function',
        'function': {
            'name': 'get_weather',
            'description': 'Get the current temperature in Celsius for a city.',
            'parameters': {
                'type': 'object',
                'properties': {
                    'city': {'type': 'string', 'description': 'City name, for example Paris'},
                },
                'required': ['city'],
            },
        },
    }
]

messages = [{'role': 'user', 'content': 'What is the weather in Paris right now?'}]

# Step 1: the model decides whether to call a function
first = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = first.choices[0].message

if not message.tool_calls:
    print(message.content)
    raise SystemExit

# Step 2: run every requested call and send the results back
messages.append(message)
for call in message.tool_calls:
    args = json.loads(call.function.arguments)
    result = FUNCTIONS[call.function.name](**args)
    messages.append({
        'role': 'tool',
        'tool_call_id': call.id,
        'content': json.dumps(result),
    })

final = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
print(final.choices[0].message.content)

Три деталі визначають, чи працює цикл:

  • call.function.arguments — це рядок JSON, а не словник. Розберіть його за допомогою json.loads.
  • Кожне повідомлення role: tool має містити tool_call_id виклику, на який воно відповідає, а це call.id.
  • content повідомлення інструменту — це рядок. Використовуйте json.dumps для структурованих результатів.

Що ви маєте побачити#

Якщо ви надрукуєте поля після першого запиту, вони виглядатимуть так (id виклику відрізняється при кожному запуску):

text
finish_reason: tool_calls
call.id: call_abc123
call.function.name: get_weather
call.function.arguments: {"city": "Paris"}

Потім скрипт друкує остаточну відповідь — просте речення на кшталт "Зараз у Парижі 14 °C." Формулювання змінюється від запуску до запуску; число надходить із вашої функції.

Кілька викликів і довші цикли#

Модель може повернути більше одного виклику в одній відповіді, наприклад, коли ви запитуєте про погоду в двох містах. Ось чому приклад перебирає message.tool_calls і відповідає на кожен виклик за його власним id. Посібник OpenAI з function calling описує ту саму поведінку: із типовим значенням tool_choice, що дорівнює auto, модель може викликати нуль, одну або кілька функцій (документація OpenAI, перевірено 22 жовтня 2026 року; на сторінці немає дати останнього оновлення, і вона описує новішу форму Responses API, тоді як цей посібник використовує форму Chat Completions ендпоінту /v1/chat/completions).

Агенти повторюють ці два кроки, доки модель не перестане запитувати інструменти. Обгорніть запити в цикл і завжди встановлюйте ліміт кроків:

python
for _ in range(5):  # safety limit against endless loops
    response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
    message = response.choices[0].message
    if not message.tool_calls:
        print(message.content)
        break
    messages.append(message)
    for call in message.tool_calls:
        args = json.loads(call.function.arguments)
        result = FUNCTIONS[call.function.name](**args)
        messages.append({'role': 'tool', 'tool_call_id': call.id, 'content': json.dumps(result)})

Якщо ви хочете, щоб відповідь з'являлася токен за токеном, поєднайте це з потоковою передачею в Python.

Чому MiniMax-M2.7 підходить для циклів з інструментами#

Цикл з інструментами надсилає багато запитів із зростаючою історією. Для цього шаблону CheapTokens пропонує MiniMax-M2.7: контекст 180K, до 8 192 вихідних токенів на відповідь, одна ціна в будь-який час доби без пікових годин і один баланс для всіх моделей. Вхідні та вихідні токени разом узяті, це дешевше за довідкову ціну OpenRouter (порівняння цін CheapTokens, перевірено 31 жовтня 2026 року).

Поточні ціни за 1M токенів: вхідні $0.05, вихідні $0.15. Як приклад робочого навантаження (не вимірювання), описаний вище цикл із двох запитів із загалом приблизно 2 700 вхідних і 350 вихідних токенів коштує $0.00019. Повний список цін на сторінці цін.

Щоб спробувати іншу модель, змініть лише id; список id на сторінці моделей.

Якщо не працює#

  • message.tool_calls — це None. Модель відповіла текстом. Зробіть опис функції description конкретнішим і переконайтеся, що запитання справді потребує функції.
  • json.JSONDecodeError на arguments. Модель згенерувала недійсний JSON. Обгорніть json.loads у try/except і надішліть текст помилки назад як результат інструменту, щоб модель могла повторити спробу з виправленими аргументами.
  • Другий запит не вдається або модель ігнорує результат. Перевірте, що кожен виклик має рівно одне повідомлення role: tool з відповідним tool_call_id, і що повідомлення асистента з tool_calls є в історії перед ними.
  • KeyError у FUNCTIONS[...]. Модель назвала функцію, яку ви не зареєстрували. Поверніть короткий рядок помилки як результат інструменту замість аварійного завершення.
  • Відповідь обрізана. Перевірте finish_reason: значення length означає, що досягнуто ліміту вихідних токенів. Дивіться чому відповідь AI обривається на півслові.
  • 401 або помилки автентифікації. Перевірте, що ключ є в CHEAPTOKENS_API_KEY і що базова URL-адреса закінчується на /v1.

Наступні кроки#

Замініть заглушку реальною функцією: запитом до бази даних, викликом пошуку або калькулятором. Додайте більше елементів до tools та до FUNCTIONS і тримайте кожен результат функції коротким, оскільки він повертається в історію при кожному наступному запиті. Щоб отримати ключ і зробити перший виклик, відкрийте документацію CheapTokens.