Учебник

GPT обрабатывает ваши документы: OpenAI API с нуля

Ваш менеджер тратит часы на ручную обработку заявок, договоров и писем. Подключаем OpenAI API к вашему бизнесу: получаем ключ, отправляем первый запрос, получаем ответ в строгом формате. Без курсов и теории - конкретный шаг для внедрения.

Макс Космов··8 мин чтения

У ваших менеджеров уходит по 4 часа в день на ручную обработку заявок, договоров и писем - половина теряется или вводится с ошибками. Вот как за вечер подключить GPT к вашему бизнесу через API и автоматизировать эту рутину. Разберём на примере стройфирмы: у вас есть прайс на работы и типовой договор подряда - нужно извлечь из входящих писем заявки и сразу заполнить договор. Без программиста, без курсов на полгода.

Зачем это нужно вашему бизнесу

OpenAI API - это способ встроить языковую модель прямо в ваши бизнес-процессы, а не открывать отдельный чат на сайте. Типичные задачи: автоматическая обработка входящих заявок и писем, классификация документов по категориям, генерация описаний товаров для каталога, ответы в корпоративном боте поддержки.

Чем это отличается от подписки на ChatGPT: API позволяет обрабатывать тысячи документов автоматически, встраивать языковую модель в ваши системы и управлять расходами точно - платите только за то, что использовали.

Получение API-ключа и безопасное хранение

Перейдите на platform.openai.com, зарегистрируйтесь и создайте ключ в разделе API Keys. Ключ начинается с sk- и выдаётся один раз - скопируйте сразу, потом не посмотреть.

Хранить ключ в коде - плохая идея. Если код попадёт в публичный репозиторий (хранилище кода, например на GitHub), боты сканируют его в реальном времени и найдут ключ за минуты. Правильный способ - переменная окружения, то есть системная переменная компьютера, недоступная из кода напрямую:

export OPENAI_API_KEY="sk-..."

Для проектов удобнее файл .env с библиотекой python-dotenv:

from dotenv import load_dotenv
import os

load_dotenv() # читает .env из текущей папки
api_key = os.environ["OPENAI_API_KEY"]

Добавьте .env в .gitignore сразу при создании проекта. .gitignore - список файлов, которые система контроля версий игнорирует и не загружает в публичное хранилище. Убедитесь, что строка .env стоит в этом файле до первого коммита.

Тарификация идёт за токены. Один токен - примерно 4 символа английского текста или 2-3 символа русского. Страница текста - около 750 токенов. GPT-4o в 2026 году стоит $2.50 за 1M (миллион) input-токенов (то, что вы отправляете) и $10.00 за 1M output-токенов (то, что модель генерирует). gpt-4o-mini - $0.15 / $0.60. Для разработки и тестов mini подходит в большинстве случаев и обходится в 10-15 раз дешевле.

openai.OpenAI() клиент: параметры и инициализация

Сначала устанавливаем SDK (Software Development Kit - библиотеку для работы с API): pip install openai. Инициализация клиента:

Этот код создаёт клиента для работы с OpenAI, настраивает таймаут в 30 секунд и автоматические повторы при ошибках сервера.

from openai import OpenAI

client = OpenAI(
 api_key=os.environ["OPENAI_API_KEY"], # по умолчанию берёт из env
 timeout=30.0, # секунды до ошибки httpx.Timeout
 max_retries=2, # автоматические повторы при 5xx
)

Параметр base_url нужен, когда работаете через прокси или совместимый сервис (Azure OpenAI, Groq, local LM Studio). Например:

client = OpenAI(
 api_key="lm-studio",
 base_url="http://localhost:1234/v1"
)

Клиент thread-safe (безопасен при параллельном использовании из нескольких потоков), создавайте один экземпляр на приложение и переиспользуйте. Для async-кода (асинхронного кода, где несколько задач выполняются без блокировки друг друга) используйте AsyncOpenAI с теми же параметрами.

chat.completions.create: обязательные и важные параметры

Основной вызов для генерации текста. Каждый раз, когда ваше приложение обращается к GPT, оно делает именно этот вызов.

Фрагмент ниже отправляет системную инструкцию и вопрос пользователя модели, задаёт температуру ответа и ограничивает длину ответа.

response = client.chat.completions.create(
 model="gpt-4o",
 messages=[
 {"role": "system", "content": "Ты помощник по Python."},
 {"role": "user", "content": "Как открыть файл?"},
 ],
 temperature=0.7, # 0.0 = детерминированно, 2.0 = хаотично
 max_tokens=1024, # максимум токенов в ответе
)

Параметр model - строка с именем модели: gpt-4o, gpt-4o-mini, gpt-4-turbo. Список актуальных моделей всегда на platform.openai.com/docs/models.

Структура messages - список словарей с role и content. Роли: system (инструкция модели, её личность и правила поведения), user (сообщение от пользователя), assistant (ответ модели в истории диалога). Для мультитёрн-диалога (разговора из нескольких шагов) добавляйте все предыдущие обмены:

messages = [
 {"role": "system", "content": "Отвечай кратко."},
 {"role": "user", "content": "Что такое рекурсия?"},
 {"role": "assistant", "content": "Функция, вызывающая сама себя."},
 {"role": "user", "content": "Дай пример на Python"},
]

API stateless (без состояния) - история хранится на вашей стороне. При каждом запросе вы передаёте всю историю разговора целиком. Если история растёт и количество токенов превышает лимит модели, обрезайте старые сообщения или делайте суммаризацию.

temperature управляет разнообразием: для структурированных задач (код, JSON, классификация) ставьте 0.0-0.3, для творческих - 0.7-1.2. Значения выше 1.5 дают нестабильные результаты.

Разбор объекта ответа

Ответ модели - это структурированный объект с несколькими полями. Важно проверять не только текст, но и причину остановки.

Этот код извлекает текст ответа, причину остановки генерации, количество потраченных токенов и сколько из них пришло из кэша.

response = client.chat.completions.create(...)

text = response.choices[0].message.content
finish = response.choices[0].finish_reason # 'stop', 'length', 'tool_calls'
input_tok = response.usage.prompt_tokens
output_tok = response.usage.completion_tokens
total_tok = response.usage.total_tokens
cached_tok = response.usage.prompt_tokens_details.cached_tokens # 0 если не было кэша

finish_reason важно проверять: stop - нормальное завершение, модель сама решила остановиться. length - модель упёрлась в max_tokens и ответ обрезан. Если ответ неполный - увеличьте max_tokens или разбейте задачу на части.

Стоимость конкретного запроса считается по формуле:

Этот код рассчитывает точную стоимость одного запроса в долларах на основе потраченных токенов.

INPUT_PRICE = 2.50 / 1_000_000 # $ за токен для gpt-4o
OUTPUT_PRICE = 10.00 / 1_000_000

cost = input_tok * INPUT_PRICE + output_tok * OUTPUT_PRICE
print(f"${cost:.6f}")

Поле cached_tokens показывает, сколько входных токенов было прочитано из кэша. Кэшированные токены стоят $1.25 за 1M вместо $2.50 - автоматически для запросов длиннее 1024 токенов с одинаковым началом. Это полезно, если вы каждый раз передаёте одинаковый большой system prompt - OpenAI кэширует его и берёт вдвое меньше.

AsyncOpenAI: для веб-приложений и FastAPI

Если ваше приложение обрабатывает несколько запросов одновременно (веб-сервис, Telegram-бот), синхронный клиент блокирует выполнение на время ожидания ответа. AsyncOpenAI решает это: пока один запрос ждёт ответа от OpenAI, сервер обрабатывает другие запросы.

Этот код создаёт асинхронный FastAPI-эндпоинт: пока модель генерирует ответ для одного пользователя, сервер не блокируется и может принять следующий запрос.

from openai import AsyncOpenAI
from fastapi import FastAPI

app = FastAPI()
aclient = AsyncOpenAI()

@app.post("/ask")
async def ask(question: str) -> dict:
 response = await aclient.chat.completions.create(
 model="gpt-4o-mini",
 messages=[{"role": "user", "content": question}],
 max_tokens=512,
 )
 return {"answer": response.choices[0].message.content}

API и параметры у AsyncOpenAI идентичны синхронному OpenAI - разница только в том, что вызовы нужно ожидать через await. Один экземпляр AsyncOpenAI на приложение - потокобезопасен.

Structured Outputs: строгий JSON из модели

JSON (JavaScript Object Notation) - текстовый формат для передачи структурированных данных. Когда вам нужны не свободные ответы, а данные в строгом формате - например, извлечь из договора: стороны, сумму, срок, тип договора - нужен гарантированный JSON.

Старый способ - response_format={"type": "json_object"} - заставляет модель отдавать JSON, но не гарантирует схему. Поля могут называться по-другому или отсутствовать. Structured Outputs с json_schema гарантирует точную структуру.

Этот код просит модель извлечь имя и возраст из текста и гарантирует, что ответ всегда будет содержать именно эти два поля в нужном формате.

response = client.chat.completions.create(
 model="gpt-4o",
 messages=[{"role": "user", "content": "Извлеки имя и возраст: Алексей, 34 года"}],
 response_format={
 "type": "json_schema",
 "json_schema": {
 "name": "person",
 "strict": True,
 "schema": {
 "type": "object",
 "properties": {
 "name": {"type": "string"},
 "age": {"type": "integer"}
 },
 "required": ["name", "age"],
 "additionalProperties": False
 }
 }
 }
)

import json
data = json.loads(response.choices[0].message.content)

Ограничения схемы при strict=True: additionalProperties должно быть False (запрет лишних полей), все поля должны быть в required. Опциональные поля делаются через anyOf: [{"type": "string"}, {"type": "null"}].

Когда использовать: извлечение данных из документов, классификация с фиксированными категориями, парсинг неструктурированного текста в базу данных. Если после ответа модели вы всегда делаете json.loads() - используйте Structured Outputs и избавьтесь от ошибок парсинга.

Pydantic-интеграция: автоматический парсинг

Pydantic - Python-библиотека для описания структур данных и их валидации (проверки корректности). Вместо ручного написания JSON-схемы вы описываете класс, SDK сам генерирует схему и парсит ответ.

Этот код описывает структуру данных о человеке через класс и просит модель заполнить её - SDK сам конвертирует класс в JSON-схему и разбирает ответ обратно в Python-объект.

from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class Person(BaseModel):
 name: str
 age: int
 city: str | None = None

response = client.beta.chat.completions.parse(
 model="gpt-4o",
 messages=[{"role": "user", "content": "Алексей, 34 года, Москва"}],
 response_format=Person,
)

person = response.choices[0].message.parsed
print(person.name, person.age) # Алексей 34

parsed содержит готовый объект Pydantic. Если модель не смогла заполнить структуру - .parsed будет None, проверяйте перед использованием.

Structured Outputs в 2026 году поддерживают: gpt-4o (все версии с октября 2024), gpt-4o-mini, o1, o3. Старые модели типа gpt-3.5-turbo - нет.

Обработка ошибок и повторные попытки

Внешние API отказывают - это нормально. Rate limit (ограничение частоты запросов), временная перегрузка сервера, сетевые сбои. Продакшн-код должен уметь подождать и повторить.

Этот код реализует устойчивый вызов с экспоненциально нарастающим временем ожидания: 1, 2, 4, 8, 16 секунд между попытками.

import openai
import time

def call_with_retry(client, **kwargs):
 for attempt in range(5):
 try:
 return client.chat.completions.create(**kwargs)
 except openai.RateLimitError:
 wait = 2 ** attempt # 1, 2, 4, 8, 16 секунд
 print(f"Rate limit, жду {wait}с...")
 time.sleep(wait)
 except openai.APIStatusError as e:
 if e.status_code >= 500:
 time.sleep(2 ** attempt)
 else:
 raise # 4xx не надо повторять
 raise RuntimeError("Не удалось выполнить запрос после 5 попыток")

RateLimitError (HTTP 429) возникает при превышении RPM (запросов в минуту) или TPM (токенов в минуту). Лимиты зависят от тира (уровня) аккаунта: на Tier 1 gpt-4o - 500 RPM и 30 000 TPM. На Tier 5 - 10 000 RPM и 2 000 000 TPM. Повышение тира происходит автоматически при достижении порогов оплаты.

APIStatusError ловит все HTTP-ошибки. Проверяйте e.status_code: 400 - неверный запрос (смотрите текст ошибки), 401 - неверный ключ, 503 - перегрузка сервера.

Что делать при 401: проверьте, что переменная OPENAI_API_KEY установлена (echo $OPENAI_API_KEY в терминале) и что ключ не истёк и не был отозван на platform.openai.com.

Реальные числа: сколько стоит задача

Считать токены в абстракции сложно. Вот конкретные примеры для типичных задач.

Классификация одного отзыва (100 токенов входа, 5 токенов выхода) на gpt-4o-mini: 100 × $0.15/1M + 5 × $0.60/1M = $0.000015 + $0.000003 = $0.000018. Тысяча отзывов - $0.018, то есть меньше двух центов.

Генерация описания товара для каталога (200 токенов входа с параметрами товара, 300 токенов выхода) на gpt-4o: $0.0005 + $0.003 = $0.0035 за карточку. Тысяча карточек - $3.50.

Анализ страницы договора (2000 токенов входа, 400 токенов выхода) на gpt-4o: $0.005 + $0.004 = $0.009 за страницу. Сто договоров по 5 страниц - $4.50.

Для большинства задач расходы на токены незначительны по сравнению с зарплатой сотрудника, который делал бы ту же работу вручную. Важнее контролировать, что модель не генерирует лишние токены - проверяйте finish_reason и ставьте разумный max_tokens.

Частые вопросы

Чем отличается response_format json_object от json_schema?

json_object гарантирует только то, что ответ парсится как JSON. Структура может быть любой - поля могут называться иначе или отсутствовать. json_schema с strict=True гарантирует точное соответствие указанной схеме - поля, типы, обязательность. Для продакшена используйте json_schema.

Почему finish_reason='length' и как предотвратить?

Модель упёрлась в ограничение max_tokens. Увеличьте параметр. GPT-4o поддерживает до 16 384 выходных токенов. Если задача требует длинного ответа, рассмотрите разбивку на части или streaming.

Как передать контекст из нескольких шагов диалога?

Добавляйте все предыдущие обмены в список messages с чередованием role: user и role: assistant. Контекст хранится на стороне клиента, API stateless.

Какие модели поддерживают Structured Outputs?

GPT-4o (с 2024-08-06), gpt-4o-mini, o1, o3-mini, o3. Для остальных используйте json_object и парсите вручную.

Можно ли использовать несколько ключей для обхода rate limits?

Технически да, но OpenAI запрещает обход лимитов в условиях использования. Правильный путь - повысить тир аккаунта или использовать Batch API для офлайн-задач.

Что дальше

Следующий шаг - Anthropic Claude API: Sonnet, Haiku, Opus: другой SDK, другая структура ответа, обязательный max_tokens. Если нужна тема промптов - Claude: основы промптинга.

AI Компас (t.me/kosmoslab_ai) - канал для предпринимателей в РФ и СНГ, которые применяют AI в своём бизнесе без программиста. Разбираем инструменты и схемы - без курсов и теории.