AI-инжиниринг

Интеграция с LLM API: OpenAI, Anthropic, open-source модели

Цели урока

  • Научиться вызывать Chat Completions API из Node.js
  • Понять роли сообщений (system, user, assistant) и управление контекстом
  • Реализовать streaming для real-time отображения ответов
  • Освоить обработку ошибок и retry-стратегии для LLM API
  • Спроектировать абстракцию для переключения между провайдерами

Предварительные знания

  • Как работают LLM изнутри
  • LLM Fundamentals

Первый вызов OpenAI API - 10 строк кода. Первый production-ready вызов с retry, timeout и fallback - 200 строк. Разница между demo и продуктом, который не падает, когда стартап попадает на HackerNews и за ночь получает 10 000 пользователей. API key - не просто строка: это прямой доступ к счёту. Утечка в GitHub - и через час придёт счёт на тысячи долларов. Именно эту разницу - между «работает у меня» и «работает в production» - и разбирает этот урок.

  • Notion AI - интегрировал GPT в существующий продукт, +100M ARR за первый год, без единого ML-инженера
  • Stripe использует GPT-4 для автоматической классификации support-тикетов - минус 40% нагрузки на команду
  • Duolingo перевёл объяснения ошибок на GPT-4 - сэкономил месяцы работы контент-команды
  • Cursor (AI IDE) - 100M ARR на правильно выстроенной архитектуре поверх LLM API

API, открывший индустрию

**2020 год**: OpenAI запустил первый в мире коммерческий LLM API на базе GPT-3. Модель стала доступна через HTTP - без GPU, без обучения, без PhD. Это был момент, когда AI перестал быть инструментом исследователей и стал инструментом разработчиков. **30 ноября 2022**: ChatGPT как публичное демо - 1 миллион пользователей за 5 дней. **1 марта 2023**: API для GPT-3.5-turbo по цене `0.002` за 1K токенов - настоящий старт рынка AI-as-a-Service. За первую неделю зарегистрировались сотни тысяч разработчиков. К концу 2023 года через API проходило больше запросов, чем через сам ChatGPT. OpenAI создал не просто модель - он создал рынок.

Chat Completions API - основной интерфейс

Первый вызов OpenAI API - 10 строк кода. Первый production-ready вызов с retry, timeout, fallback - 200 строк. Именно этот разрыв разделяет demo и продукт, который не падает ночью.

Все современные LLM работают через **Chat Completions API** - отправляется массив сообщений, приходит ответ. OpenAI, Anthropic, локальная модель через Ollama - интерфейс почти одинаковый. Это не случайность: OpenAI задал стандарт, остальные его приняли.

Ответ - не просто строка. Это объект с метаданными, и самое важное в нём - `usage`:

**usage.total_tokens** - именно это считается в счёте. При 100 000 запросах в день по 800 токенов - это 80M токенов в месяц. gpt-4o обойдётся в `200 USD.` gpt-4o-mini - в `12 USD.` Всегда логируй usage в production с первого дня.

Какое поле в ответе Chat Completions API показывает количество потраченных токенов?

Роли сообщений: system, user, assistant

Chat API принимает массив **messages**. У каждого сообщения есть **role** - и от этого зависит, как модель его интерпретирует.

RoleНазначениеКогда использовать
systemИнструкция для модели. Задаёт поведение, тон, ограниченияОдин раз, первым сообщением
userСообщение от пользователяКаждый запрос пользователя
assistantОтвет модели (или пример ответа)История диалога, few-shot примеры

Модель **stateless**. Она не помнит ничего между запросами - как HTTP. Разработчик сам передаёт весь контекст каждый раз. Это не баг - это архитектурное решение, которое делает API масштабируемым.

**System prompt - главный инструмент.** Хороший system prompt превращает generic модель в специализированного ассистента. Плохой - даёт галлюцинации и нерелевантные ответы. Character.ai строит на system prompt'ах персонажей с 20 миллиардами сообщений в день. Подробнее - в уроке про промпт-паттерны.

Модель «помнит» предыдущие сообщения в диалоге потому что:

Streaming: ответ по токенам в реальном времени

Без streaming пользователь ждёт 5-15 секунд пустого экрана, пока модель генерирует полный ответ. С streaming - видит текст, который появляется токен за токеном, как в ChatGPT. TTFT (time-to-first-token) падает с 10 секунд до 200-500 мс. Один параметр меняет восприятие продукта.

В **NestJS** стриминг отдаётся клиенту через Server-Sent Events (SSE) - один из стандартных способов доставить поток данных по HTTP без WebSocket:

**Streaming не меняет стоимость** - количество токенов одинаковое. Но метрика TTFT (time-to-first-token) - это разница между продуктом, который ощущается живым, и продуктом, который «завис». Notion AI, Linear, Cursor - все используют streaming именно за это ощущение отклика.

Streaming в LLM API нужен для:

Ошибки API: retry, rate limits, fallbacks

2023 год. Стартап запустил AI-фичу. Первые 500 пользователей - всё работает. Ночью продукт попал в HackerNews. За час пришло 5000 одновременных запросов. Каждый запрос бил в OpenAI напрямую. Прилетело 429. Фронтенд показал пустой экран. Продукт ушёл в оффлайн. Утром основатели смотрели в логи и не понимали что случилось.

LLM API - это **внешний сервис**. Он падает, тормозит и возвращает ошибки. Production-ready интеграция обязана это учитывать с первого коммита.

HTTP CodeПричинаЧто делать
400Невалидный запрос (плохой prompt)Исправить запрос. Не ретраить
401Невалидный API keyПроверить .env. Не ретраить
429Rate limit - слишком много запросовРетрай с exponential backoff
500Ошибка на стороне OpenAIРетрай 2-3 раза с задержкой
503Сервис перегруженРетрай или fallback на другую модель

**Rate limits у OpenAI** зависят от тарифа: от 500 RPM (requests per minute) на Tier 1 до 10 000 RPM на Tier 5. Если продукт масштабируется - закладывай BullMQ-очередь с самого начала, не после первого инцидента.

При получении 429 (Rate Limit) ошибки от LLM API правильная стратегия:

OpenAI vs Anthropic vs Open Source: выбор провайдера

Привязка к одному провайдеру - это **vendor lock-in**. OpenAI поднял цены в 2023 - и сотни компаний обнаружили, что их юнит-экономика сломалась за неделю. Умный AI-инженер проектирует систему так, чтобы переключиться за 30 минут, а не за 30 дней.

**Ключевые различия API:**

АспектOpenAIAnthropic
System promptВ массиве messagesОтдельное поле system
Ответchoices[0].message.contentcontent[0].text
Лимит выходных токеновmax_tokens (опционально)max_tokens (обязательно!)
Streamingstream: truestream: true
Function callingtools + tool_choicetools + tool_choice
МоделиGPT-4o, GPT-4o-miniClaude Sonnet, Claude Haiku

Начни с OpenAI (больше документации, примеров). Но сразу пиши абстракцию - добавить Anthropic или локальную llama через Ollama займёт 30 минут вместо дней рефакторинга. Это не overengineering - это страховка от vendor lock-in.

Зачем создавать абстрактный LLMProvider интерфейс вместо прямого вызова OpenAI SDK?

API key - это просто строка для авторизации

API key - это прямой доступ к платёжному счёту. Утечка в публичный репозиторий = счёт на тысячи долларов за несколько часов

Боты сканируют GitHub каждые несколько минут в поисках открытых API ключей. OpenAI не возмещает расходы от утечек. Правило: API ключи только в .env, .env в .gitignore, никогда в коде, никогда в логах. Для production - переменные окружения через секрет-менеджер (AWS Secrets Manager, Vault).

Итоги

  • Chat Completions API - универсальный интерфейс: messages in - text out. OpenAI задал стандарт, Anthropic и open-source его приняли
  • System prompt задаёт поведение, user - запрос, assistant - история. Модель stateless: каждый вызов независим
  • Streaming через SSE даёт TTFT 200-500мс вместо 5-15с ожидания - это разница в восприятии продукта
  • 429/500/503 - retry с exponential backoff (2с - 4с - 8с). 400/401 - чини код, не ретрай
  • Абстракция LLMProvider - переключение провайдера за 30 минут, а не за дни рефакторинга
  • API key в .env, usage.total_tokens в логи - это не опционально, это базовая гигиена production

Вопросы для размышления

  • Если LLM API вернул 429 три раза подряд с exponential backoff - что делать дальше? Fallback на другую модель или вернуть ошибку пользователю?
  • При каком объёме запросов в день имеет смысл добавить очередь (BullMQ/Bull) между API и LLM?
  • Как защитить API key, если бекенд развёрнут в Docker на VPS - какой путь от .env до контейнера без попадания ключа в образ?

Что дальше

API подключён, ответы приходят, ошибки обработаны. Следующий шаг - научиться писать промпты, которые стабильно работают в production: не ad-hoc, а архитектурно.

  • Промпт-паттерны для production — Архитектурные паттерны промптов - few-shot, chain-of-thought, structured output
  • Streaming: продвинутые паттерны — Продвинутые паттерны streaming - backpressure, cancellation, WebSocket
  • Стоимость и оптимизация — Как не разориться на LLM API - кеширование, model routing, prompt compression

Связанные уроки

  • aie-03-llm-fundamentals — Понимание работы LLM лежит в основе каждого вызова API
  • aie-08-streaming — Стриминг ответов строится поверх chat completions API
  • aie-07-structured-output — Function calling здесь открывает типизированный JSON-вывод
  • aie-29-cost-management — Использование API определяет стоимость токенов под контроль
  • net-21-http-basics — LLM API это HTTP запрос-ответ поверх JSON
  • sd-10-microservices — Провайдер LLM это ещё одна внешняя сервисная зависимость
Интеграция с LLM API: OpenAI, Anthropic, open-source модели

0

1

Войти