Все уроки · 44
Путь 3 · Дорожная карта AI-инженера·Урок 7 из 33

API и SDK: как код разговаривает с моделями

Стандарт, совместимый с OpenAI, Claude Messages API, Gemini API и экосистема Hugging Face — с рабочим кодом, который можно скопировать и запустить.

УровеньСреднийВремя~15 мин

Один случайный стандарт

Сначала три слова, которые вы будете встречать повсюду, — простым языком:

  • API — способ, которым ваш код может попросить что-то у другого компьютера и получить ответ. Вы отправляете запрос — получаете ответ. Как форма на сайте, только заполняет её ваша программа.
  • Endpoint (конечная точка) — конкретный адрес, на который отправляется запрос, вроде URL.
  • SDK — готовая библиотека для вашего языка программирования, которая скрывает «сырую» работу с HTTP. Без SDK вы собираете запрос вручную; с ним вы пишете client.chat.completions.create(...), а остальное библиотека делает сама.

Больше за этими словами ничего нет. Всё дальнейшее строится на них.

В 2023 году OpenAI выпустила свой чат-API, и формат запроса оказался настолько удобным, что его переняла почти вся индустрия. Сегодня множество провайдеров — включая серверы открытых моделей вроде Ollama и vLLM — предоставляют OpenAI-совместимый endpoint: адрес, который принимает запросы в том же виде.

Для вас это значит: выучите один формат запроса — и сможете общаться с десятками моделей. Вот этот формат:

  • название модели (model),
  • список сообщений (messages), у каждого из которых есть роль (role: system, user, assistant, tool) и содержимое (content),
  • необязательные параметры сэмплирования (temperature, max tokens — всё из предыдущего урока),
  • ответ, в котором есть сообщение и объект usage с количеством токенов.

Ещё одно слово, прежде чем перейти к коду: этот формат обычно записывают в JSON — текстовом формате для структурированных данных. В фигурных скобках находится «объект» (набор именованных полей), в квадратных — список, а каждое поле записывается как "name": "value". Это выглядит как код, но это просто форма, заполненная текстом, — намеренно скучная, чтобы её мог прочитать любой язык программирования и любой сервер. Когда ниже вы увидите {"role": "user", "content": "..."}, это JSON: крошечная форма с двумя полями — role и content.

Запрос такого вида и есть тот самый единственный вызов, на котором строится всё остальное. Один POST-запрос: на входе текст, в ответ — одно продолжение; никакого второго вида запросов нет. Окно чата, агент, RAG-пайплайн — всё это программы, которые снова и снова делают один и тот же вызов с разным текстом. SDK — всего лишь обёртка, которая собирает этот текст и запускает цикл за вас. Вся идея в одном месте: Один вызов: как на самом деле работают все ИИ-продукты.

OpenAI-совместимый API на практике

три способа поздороваться
1from openai import OpenAI
2 
3client = OpenAI() # читает OPENAI_API_KEY из переменной окружения
4 
5response = client.chat.completions.create(
6 model=#98c379">"gpt-4o-mini",
7 messages=[
8 {#98c379">"role": "system", "content": "You are a concise assistant."},
9 {#98c379">"role": "user", "content": "Explain prompt caching in 2 sentences."}
10 ],
11 temperature=0.7,
12 max_tokens=200,
13)
14 
15print(response.choices[0].message.content)
16print(response.usage.total_tokens, #98c379">"tokens")

Не обращайте внимания на синтаксис и посмотрите на общий скелет: модель, сообщения (messages или contents), несколько параметров, ответ с текстом и данными об использовании (usage). Различия, которые стоит запомнить:

  • Claude: системный промпт — отдельный параметр верхнего уровня, а не сообщение с ролью. Параметр max_tokens нужно передавать всегда.
  • Gemini: более плоский стиль — в простых случаях contents может быть обычной строкой; параметры передаются в config.
  • OpenAI-совместимый формат: system — просто первое сообщение. На этом «диалекте» говорит большинство сторонних провайдеров.

Что такое API-ключ

API-ключ — это длинная секретная строка, по которой провайдер вас узнаёт: отчасти логин, отчасти банковская карта. Её передаёт каждый запрос, а провайдер выставляет счёт тому, кому ключ принадлежит. Вот и весь механизм.

Из этого прямо следуют два правила:

  1. Ключ — это деньги. Любой, у кого он есть, может потратить ваш баланс. Боты круглосуточно сканируют публичные репозитории GitHub в поисках случайно закоммиченных ключей; утёкший ключ обычно начинают использовать в течение нескольких минут.
  2. Не храните его в коде. Положите его в переменную окружения — значение, которое хранится на самой машине, вне ваших файлов, и которое программа читает при запуске. Поэтому в примерах выше клиент создаётся без видимого ключа: SDK сам берёт OPENAI_API_KEY из окружения. Кодом можно делиться, а секрет вместе с ним не уходит.

Где ключу не место

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

Как запрос уходит и возвращается

Код выше хорош, но что именно передаётся по сети? Нажимайте «отправить →»: это один цикл «запрос — ответ», тот самый, который ваш код выполняет каждый раз. Первая строка, POST /v1/chat/completions, — это просто адрес (endpoint) плюс тип запроса: POST означает «создай что-то по этим данным» — этот глагол ваш код использует, когда просит модель сгенерировать ответ. Ничего похожего на чат в человеческом смысле здесь нет: модель понятия не имеет, что раньше был какой-то другой запрос.

Simulated conversation
press the button below to send the first message
sent to the modelnothing yet — every message is sent in full

Обратите внимание на две вещи, которые часто упускают:

  • Системное сообщение — это просто элемент списка, а не особая настройка (кроме Claude, где это отдельный параметр).
  • usage показывает, за что именно вы только что заплатили. Это самое полезное поле во всём ответе — и то, которое проще всего проигнорировать.

Потоковая передача в Node

Для интерактивных интерфейсов нужна потоковая передача (см. предыдущий урок). Вот как буднично она выглядит в JavaScript:

streaming.js
import OpenAI from "openai";

const client = new OpenAI();

const stream = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Write a haiku about tokens." }],
stream: true,
});

for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content ?? "";
process.stdout.write(delta); // выводит токен за токеном
}

Весь секрет эффекта «ИИ печатает» — в этом цикле: каждый фрагмент содержит несколько токенов, и интерфейс дописывает их по мере поступления.

Экосистема Hugging Face

Hugging Face для открытых моделей — то же, что GitHub для кода. AI-инженеру важны три части:

  • Hub — больше миллиона наборов весов моделей, датасетов и демо. Llama, Mistral, DeepSeek, дообученные версии всего подряд: если веса опубликованы, они есть здесь.
  • Inference — запуск открытых моделей прямо на платформе через простой API (клиент huggingface_hub или endpoint в формате чата): модели можно пробовать, ничего не скачивая.
  • Transformers / Transformers.js — библиотека, которая загружает модель локально и запускает её на Python. Transformers.js даже запускает небольшие модели прямо в браузере через WebGPU — вообще без сервера.

Когда стоит обратиться к Hugging Face

Когда вам нужны открытые веса: эксперименты перед self-hosting, локальный запуск небольшой модели эмбеддингов или ранжирования (reranking), либо функция, которая должна работать офлайн прямо в браузере. Для повседневной работы с API обычно проще описанный выше OpenAI-совместимый путь.

Минимум для выживания при работе с API

У какого бы провайдера вы ни работали, в каждом реальном проекте возникают одни и те же четыре заботы:

  • Лимиты запросов — предел того, сколько можно отправить за минуту. Вы обязательно на них наткнётесь. С первого дня реализуйте повторные попытки с экспоненциальной задержкой (exponential backoff): если вызов не удался, подождите 1 с, затем 2 с, затем 4 с, вместо того чтобы забрасывать сервер запросами. Официальные SDK часто делают это за вас.
  • Ошибки и тайм-ауты — до моделей добираются по сети. Исходите из того, что любой вызов может не удаться, и заранее решите, что покажет интерфейс, если генерация не сработала.
  • Учёт токенов — читайте поле usage, записывайте его в лог, суммируйте. Неожиданные расходы — одна из главных причин, по которым проекты на LLM закрывают.
  • Фиксация версии — названия моделей меняются, а сами модели снимают с поддержки. Указывайте в конфигурации точную версию модели (название с датой вроде gpt-4o-mini-2024-07-18, а не «плавающую» метку) и заранее продумайте, как будете переходить на другую модель, пока не пришло уведомление о снятии с поддержки.

Проверьте себя

Проверьте себя

Почему «OpenAI-совместимый endpoint» так важен на практике?

Вы случайно закоммитили свой API-ключ в публичный репозиторий, а потом удалили файл. Что делать?

В день запуска ваше приложение получает ошибку «rate limit exceeded». Какой порядок действий правильный?