Урок 6

Паттерны API интеграции

Стриминг, ретраи, ошибки

Проблема: Как интегрировать LLM в приложение надёжно? Как быть с таймаутами, rate limits, повторными попытками и стримингом?

Решение: Стандартные методы подключения

API-паттерны — это проверенные подходы для надёжной интеграции LLM в приложения. Они как стандартизированные разъёмы — USB, HDMI или электрические вилки — которые упрощают соединение разных систем. Стриминг снижает ощущаемую задержку, а структурированный вывод обеспечивает предсказуемые ответы.

Представьте это как стандартизированные разъёмы вроде USB или HDMI:

  • 1. Выбрать эндпоинт: Выбрать правильный API: chat completions, embeddings или function calling в зависимости от задачи
  • 2. Настроить стриминг: Стримить токены для UX реального времени — пользователи видят первый токен через ~200мс вместо ожидания секунд
  • 3. Повтор с экспоненциальным backoff: Автоматически повторять при 429 (rate limit), 500 (ошибка сервера), 503 (перегрузка) с возрастающими задержками
  • 4. Добавить таймаут и circuit breaker: Установить таймауты запросов и перестать вызывать падающего провайдера после N последовательных ошибок
  • 5. Обрабатывать rate limits грамотно: Ставить лишние запросы в очередь, применять backpressure и показывать пользователям понятный индикатор ожидания

Где это используется?

  • Чат-боты: Стриминг для отображения ответа в реальном времени
  • Пакетная обработка: Повторы и rate limiting для массовых задач
  • Высокая доступность: Резервные модели и circuit breakers
  • Контроль затрат: Очередь запросов и приоритизация
  • Мульти-провайдерный fallback: Если основной провайдер недоступен, бесшовно переключиться на резервный (напр., Claude → OpenAI → локальная модель)

Интересный факт: Стриминг снижает воспринимаемую задержку в 5-10 раз. Пользователи видят первый токен через ~200мс вместо ожидания 3-5 секунд полного ответа. Это одно изменение часто оказывает наибольшее влияние на удовлетворённость пользователей.

Попробуйте сами!

Используй интерактивный пример ниже, чтобы увидеть разные API-паттерны в действии и понять, как они улучшают надёжность.

Паттерны API интеграции

Стриминг позволяет показывать ответ по мере генерации, улучшая UX

Streaming Response

import anthropic

client = anthropic.Anthropic()

# Stream tokens as they're generated
with client.messages.stream(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Explain vector databases"}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

Лучшие практики

  • Стриминг: Всегда используй для чата и длинных ответов
  • Таймауты: Устанавливай разумные лимиты (30-60s для LLM)
  • Обработка ошибок: Логируй все ошибки, показывай понятные сообщения пользователю
  • Мониторинг: Отслеживай latency, error rate, token usage

Попробуй сам

Интерактивное демо этой техники

Сравнение техник
Демо режим
Предзаписанные ответы
ЗадачаНачинающийКод

Обработать ошибки при вызове LLM API с retry-логикой

Без техники
Без техники
Промпт
Напиши функцию вызова OpenAI API на Python.
Ответ
import openai

def ask_llm(prompt):
    response = openai.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content
Токены:18/55
Время:450ms
Качество:
С API интеграция
С техникой
Промпт
Напиши production-ready функцию вызова OpenAI API на Python: - Exponential backoff (3 попытки: 1s, 2s, 4s) - Обработка: RateLimit (429), ServerError (5xx), Timeout - Логирование каждой попытки - Типизация (return type) Только код с комментариями к retry-логике.
Ответ
import openai
import time
import logging
from typing import Optional

logger = logging.getLogger(__name__)

def ask_llm(prompt: str, max_retries: int = 3) -> Optional[str]:
    """Вызов LLM с exponential backoff."""
    for attempt in range(max_retries):
        try:
            response = openai.chat.completions.create(
                model="gpt-4",
                messages=[{"role": "user", "content": prompt}],
                timeout=30
            )
            return response.choices[0].message.content
        except openai.RateLimitError:      # 429 — слишком много запросов
            wait = 2 ** attempt            # 1s, 2s, 4s
            logger.warning(f"Rate limit, retry {attempt+1}/{max_retries} in {wait}s")
            time.sleep(wait)
        except openai.APIStatusError as e: # 5xx — ошибка сервера
            if e.status_code >= 500:
                wait = 2 ** attempt
                logger.error(f"Server error {e.status_code}, retry in {wait}s")
                time.sleep(wait)
            else:
                raise                       # 4xx (кроме 429) — не ретраим
        except openai.APITimeoutError:
            logger.error(f"Timeout, attempt {attempt+1}/{max_retries}")
    
    logger.critical(f"All {max_retries} retries failed")
    return None
👁️Без retry при 429 (Rate Limit) приложение падает при нагрузке — LLM API регулярно возвращает 429
🧠Exponential backoff: 1s → 2s → 4s — даёт API время восстановиться, не перегружая ещё больше
🔍4xx (кроме 429) — ошибки клиента, retry бесполезен. 5xx — сервер, retry имеет смысл
Production = retry + logging + timeout + graceful degradation (return None)
Токены:70/220
Время:1400ms
Качество:
Почему это работает

В production LLM API вызывается с retry (exponential backoff), разделением ошибок (429 retry vs 400 fail) и logging. Без этого приложение падает при первом rate limit.

1 / 2

Квиз по уроку

1 из 3

1.Какое главное преимущество потоковой передачи ответов API LLM?

Практика

Создайте бесплатный аккаунт для решения челленджей

4 челленджей с AI-проверкой для этого урока

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

Этот урок — часть структурированного курса по LLM.

Мой путь обучения