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

Початок роботиПосібник

Перший запит до CheapTokens у Python з requests, без SDK

Скрипт Python на 20 рядків лише з requests: одне завершення чату, тайм-аут, обробка HTTP-помилок, а також надруковані відповідь, finish_reason і usage.

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

Скрипт Python, що викликає ендпоінт завершень чату CheapTokens через requests
На цій сторінці
  1. Весь скрипт
  2. Що робить кожен рядок
  3. Читання відповіді
  4. Коли не працює
  5. Скільки коштує один виклик
  6. Куди рухатися далі

Вам не потрібен пакет openai, щоб звертатися до API, сумісного з OpenAI. Достатньо одного виклику requests.post, Bearer-ключа та JSON-тіла, і ви бачите точно, що йде по дроту. Цей посібник створює такий скрипт для CheapTokens (https://api.cheaptokens.dev/v1/chat/completions) і завершується тим, що він друкує відповідь, finish_reason та використання токенів.

Це гарний варіант, якщо ви на заблокованій машині, де встановлено лише requests, якщо невелике завдання cron не повинно тягнути SDK, або якщо ви просто хочете зрозуміти, що SDK робить за вас. Посібник із першого запиту охоплює SDK, curl і Node; це — варіант на чистому Python.

Весь скрипт#

Спочатку покладіть ключ у змінну середовища (див. як безпечно зберігати API-ключ), потім збережіть це як ask.py:

python
import os
import requests

url = "https://api.cheaptokens.dev/v1/chat/completions"
headers = {"Authorization": f"Bearer {os.environ['CHEAPTOKENS_API_KEY']}"}
payload = {
    "model": "deepseek-ai/DeepSeek-V4-Flash-0731",
    "messages": [
        {"role": "user", "content": "Explain what a token is in two sentences."}
    ],
    "max_tokens": 200,
}

try:
    r = requests.post(url, headers=headers, json=payload, timeout=30)
    r.raise_for_status()
except requests.exceptions.Timeout:
    raise SystemExit("No reply within 30 seconds - try again or raise the timeout")
except requests.exceptions.HTTPError as e:
    raise SystemExit(f"HTTP {e.response.status_code}: {e.response.text}")

data = r.json()
choice = data["choices"][0]
print(choice["message"]["content"])
print("finish_reason:", choice["finish_reason"])
print("usage:", data["usage"])

Запустіть python ask.py. Ідентифікатор моделі — це повний ідентифікатор шлюзу, deepseek-ai/DeepSeek-V4-Flash-0731; якщо ви не впевнені, що туди вписати, перелічіть моделі за допомогою GET /v1/models. Щоб спробувати іншу модель, підставте zai-org/GLM-5.3-Flash і більше нічого не змінюйте: один баланс покриває всі моделі.

Шлях одного запиту: ключ, POST, raise_for_status, choices, usage
Один запит від вашого скрипта до надрукованої відповіді

Що робить кожен рядок#

Ось п'ять ідей, на які спирається скрипт. Quickstart requests (жива документація, перевірено 2 листопада 2026 року) пояснює більшість із них, а довідка Chat Completions від OpenAI визначає поля у відповіді.

Флеш-картки

П'ять речей у скрипті

Третій пункт — той, який люди пропускають. Скрипт, що зависає назавжди в завданні cron, набагато гірший за той, що гучно падає через 30 секунд.

Читання відповіді#

Успішна відповідь — це JSON. Частини, які вас цікавлять, згідно з довідкою Chat Completions:

  • choices[0].message.content — це текст. Він може бути null, тож не викликайте рядкові методи на ньому наосліп.
  • choices[0].finish_reason каже, чому модель зупинилася: stop (завершила), length (обмеження max_tokens обірвало її), tool_calls, content_filter.
  • usage.prompt_tokens, usage.completion_tokens і usage.total_tokens — це те, за що ви платите: вхід, вихід та їхня сума.

Відповідь має таку форму (числа — заповнювачі):

json
{
  "choices": [
    {
      "message": {"role": "assistant", "content": "A token is a small piece of text..."},
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 18, "completion_tokens": 52, "total_tokens": 70}
}
Спробуйте саміСпробуйте: встановіть max_tokens у 5 і запустіть скрипт знову. Що каже finish_reason?Показати відповідь

Він каже length: модель було зупинено вашим обмеженням max_tokens, тож відповідь обривається посеред речення. Підніміть обмеження, і ви знову отримаєте stop. Повна історія — у Відповідь AI обірвана? Виправте finish_reason "length".

Коли не працює#

Скрипт перетворює більшість збоїв на один рядок виводу. Ось що зазвичай означає кожен із них:

З'єднайте пари

Зіставте кожне повідомлення з його звичайною причиною

  • HTTP 401Ключ відсутній, введений з помилкою або не той, який ви мали намір надіслати
  • HTTP 404Неправильний шлях URL або ідентифікатор моделі
  • requests.exceptions.TimeoutЖодного байта не надійшло протягом тайм-ауту
  • KeyError: 'CHEAPTOKENS_API_KEY'Змінна середовища не встановлена в цьому терміналі

Щодо фактичних тіл помилок і покрокової перевірки ключа, базового URL та ідентифікатора моделі скористайтеся Помилка API 401 або 404: неправильний ключ, базовий URL або ідентифікатор моделі. Дві менші пастки: якщо ви бачите KeyError: 'choices', ви розібрали тіло помилки як успіх, що означає, що raise_for_status() було пропущено. А якщо на вашій машині є файл ~/.netrc, requests може використати його облікові дані замість заголовка Authorization, який ви встановили.

Скільки коштує один виклик#

З числами-заповнювачами з відповіді вище (близько 18 токенів на вході, 52 на виході) один виклик DeepSeek-V4-Flash коштує $0.0000055. Це число, яке ви не відчуєте, тож масштабуйте його. Скажімо, ваш скрипт підсумовує 1 000 звернень до підтримки на день, приблизно 800 токенів на вході та 300 на виході кожне:

Модель За запит 1 000 запитів OpenRouter, 1 000 запитів
GLM-5.3-Flash $0.000028 $0.028 $0.0517
DeepSeek-V4-Flash $0.000042 $0.042 $0.098
MiniMax-M2.7 $0.000085 $0.085 $1.02

800 вхідних і 300 вихідних токенів на запит. Ціни за 1 млн токенів актуальні та змінюються разом із нашими тарифами; стовпець OpenRouter показує довідкові ціни для того самого навантаження.

Ціни фіксовані для кожної моделі, без пікових годин, тож той самий скрипт коштує однаково о 3-й ночі та опівдні. Поточні ціни для кожної моделі — на сторінці цін, а документація перелічує ендпоінти.

Куди рухатися далі#

Коли це запрацює, звичайні наступні кроки — цикл по багатьох вхідних даних, повторна спроба при 429 (див. 429 Too Many Requests: повторні спроби з backoff) або той самий виклик зі стрімінгом. Якщо ви не хочете керувати HTTP самостійно, шлях через SDK — це лише одна зміна base_url.