Техническая ветка для разработчиков Собрать руками
Как устроен LLM API
LLM API — это не «волшебный чат», а надёжный сервис с чётким контрактом. Разберём, как он устроен внутри, как его использовать без боли и как не сломать прод.
Что такое LLM API
LLM API — это HTTP-интерфейс, через который приложение отправляет текст (промпт) и получает сгенерированный текст от большой языковой модели. Это не «модель в облаке», а строгий контракт: метод POST, JSON-тело, токены, таймауты и retry-политики. В CodeVibers мы используем его как «движок» для агентов, RAG, генерации контента и автоматизации.
Как проходит запрос
flowchart TD
A[Клиент: POST /v1/chat/completions] --> B[API Gateway]
B --> C[Auth: API key / OAuth]
C --> D[Rate Limiter]
D --> E[Tokenizer: text → tokens]
E --> F[LLM Inference: model + context]
F --> G[Detokenizer: tokens → text]
G --> H[Post-processing: safety, filtering]
H --> I[Response: JSON with content + usage]
Важно: токенизация — не просто «считать слова». Разные модели (GPT, Claude, Llama) используют разные токенайзеры. Один символ может быть 0.3 токена, а эмодзи — 2. Это влияет на лимиты и стоимость.
Минимальный запрос (Python)
import requests
import os
response = requests.post(
"https://api.openai.com/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}",
"Content-Type": "application/json"
},
json={
"model": "gpt-4o-mini",
"messages": [
{"role": "system", "content": "Ты — ассистент для технической документации."},
{"role": "user", "content": "Объясни, что такое RAG за 3 предложения."}
],
"temperature": 0.3,
"max_tokens": 256
}
)
if response.ok:
data = response.json()
print(data["choices"][0]["message"]["content"])
print("Токенов использовано:", data["usage"]["total_tokens"])
else:
print("Ошибка:", response.status_code, response.text)
Типичные ошибки (и как их избежать)
- Токен-переполнение: промпт + ответ > лимит модели → ошибка. Решение: считать токены заранее, использовать `max_tokens` и `truncation`.
- Нет retry-логики: API падает из-за `429` или `503`. Решение: экспоненциальная задержка + jitter (например, `backoff` в Python).
- Игнорирование `usage`: не отслеживать `prompt_tokens`, `completion_tokens`, `total_tokens` → нет контроля затрат.
- Нет валидации структуры: модель возвращает JSON, но без `type: object` в `response_format` — можно получить «`{ "data": "не JSON" }`».
Пример: обработка ответа с fallback
def safe_llm_call(messages, max_retries=3):
for attempt in range(max_retries):
try:
resp = requests.post(API_URL, json={
"model": "gpt-4o-mini",
"messages": messages,
"response_format": {"type": "json_object"}
}, timeout=10)
resp.raise_for_status()
data = resp.json()
# Проверка структуры
content = data["choices"][0]["message"]["content"]
return json.loads(content) # → dict
except (json.JSONDecodeError, KeyError) as e:
if attempt == max_retries - 1:
raise ValueError("Некорректный ответ модели") from e
time.sleep(2 ** attempt + random.random())
except requests.exceptions.RequestException as e:
if attempt == max_retries - 1:
raise RuntimeError("API недоступен") from e
time.sleep(2 ** attempt + random.random())
В CodeVibers такие обёртки — стандарт. Они превращают «нестабильный API» в надёжный сервис.
Чеклист для production-ready LLM API
- [ ] Используется `response_format` для структурированных выходов (JSON mode)
- [ ] Есть таймауты (не более 10–15 сек для чата)
- [ ] Реализован retry с экспоненциальной задержкой
- [ ] Логируются `usage` и `model` для аудита и оптимизации
- [ ] Проверка `finish_reason` («length» = обрезано, «stop» = норм)
- [ ] Обработка `content_filter` (OpenAI) или `safety` (Claude)
- [ ] Кэширование идентичных запросов (если допустимо бизнесом)
Следующий шаг
Теперь, когда вы понимаете, как работает LLM API «под капотом», можно собирать на его основе агентов. Переходите к Академии CodeVibers и изучайте «Как собрать агента с tool-calling» — там мы соединяем API, логику и внешние инструменты.