Подключение OCR API выглядит как «отправить картинку, получить текст», но судьбу проекта решают другие вещи: формат и размер изображения, синхронный или асинхронный вызов, определение координат и полей, а также запасной план при нестабильном результате. На этапе демо это незаметно, но реальные счета и сканы быстро выявляют проблемы.
Ниже на примере OpenAI-совместимого интерфейса и типичных OCR-сервисов разобрана цепочка от загрузки до структурированного вывода, приведены примеры, предобработка, разбор ошибок и проверка при миграции.
Примечание: OpenAI, Google, Microsoft, Alibaba Cloud, Tencent Cloud, Baidu и другие упомянутые бренды — товарные знаки их правообладателей. Статья носит технический характер и не означает аффилированности с производителями; интерфейсы, модели, ограничения изображений и правила тарификации смотрите в официальной документации платформ и на страницах сайта.
1. Интерфейс и аутентификация
Есть две распространённые формы OCR, сначала определите свою:
- Специализированный OCR-интерфейс: отдельная точка распознавания, на входе изображение или PDF, на выходе текстовые блоки, координаты и уверенность; часть поддерживает шаблоны счетов, документов и таблиц.
- Мультимодальный диалоговый интерфейс: через
/v1/chat/completions, изображение помещается в сообщение, визуальная модель выдаёт текст или JSON; подходит для сложной вёрстки, рукописного текста и задач с пониманием.
Аутентификация OpenAI-совместимого интерфейса обычно такая:
POST https://ai.zhongshangqihang.com/v1/chat/completions
Authorization: Bearer sk-ваш-ключ
Content-Type: application/json
Base URL указывайте только до /v1 и не собирайте путь вручную перед передачей в SDK, иначе легко получить 404. Некоторые облачные провайдеры используют подпись Access Key + Secret Key или сначала обменивают данные на access_token; схему Bearer туда напрямую применить нельзя, ориентируйтесь на официальную документацию.
2. Как передавать изображение: URL, Base64 и загрузка файла
Есть три распространённых способа; выбор зависит от того, где находится изображение и что поддерживает интерфейс:
| Способ | Когда подходит | На что обратить внимание |
|---|---|---|
| Публичный URL | Изображение уже в объектном хранилище или CDN | Сервер должен иметь доступ; срок действия ссылки должен быть достаточным; не публикуйте чувствительные изображения |
| Base64 data URL | Локальные файлы, изображения внутренней сети, временные тесты | Объём растёт примерно на треть; ошибка префикса или кодирования даёт 400 |
| multipart-загрузка файла | Специализированные OCR-интерфейсы провайдера | Имя поля, кодирование и размер — по документации |
Формат Base64 обычно data:image/jpeg;base64,<закодированные данные>. Частые ошибки: пропущен префикс, в строку попали переводы строк или использовано URL-safe кодирование без обратного преобразования.
Из форматов чаще всего встречаются JPEG, PNG и WebP; GIF, TIFF, BMP и PDF зависят от интерфейса. Размер одного файла обычно от нескольких МБ до 20 МБ; превышение даёт 413 или 400. Разрешение не всегда «чем выше, тем лучше»: слишком большое сервер может уменьшить. Для сканов обычно 200–300 DPI, для фотографий с телефона начинайте с длинной стороны 1600–2400 пикселей и проверяйте на реальных образцах.
3. Синхронно или асинхронно
Синхронный интерфейс подходит для одного изображения и интерактивных сценариев: отправили запрос и ждёте результат. Риск — тайм-аут, особенно при больших изображениях, многостраничных PDF или очереди на сервере: соединение может быть разорвано заранее.
Асинхронный интерфейс подходит для пакетов и многостраничных документов. Процесс обычно такой:
- Отправить изображение или файл и получить ID задачи.
- Опрашивать статус или ждать уведомления по callback.
- После завершения скачать или запросить результат.
- Результат обычно хранится ограниченное время; сохраняйте его в свою базу вовремя.
Не смотрите только на простоту интерфейса. Если запрос может выполняться десятки секунд, синхронный вызов занимает соединение и поток, а повторы усиливают нагрузку. В асинхронном режиме нужно продумать идемпотентность, повторную отправку, паузы при опросе и истечение результата. В production рекомендуется завести таблицу задач с ID, статусом и местом хранения результата.
4. Пример вызова curl
Ниже распознавание изображения через OpenAI-совместимый интерфейс. Имя модели смотрите на странице тарифов; выбирайте модель с поддержкой изображений:
export ZSQH_API_KEY="sk-ваш-ключ"
curl "https://ai.zhongshangqihang.com/v1/chat/completions" \
-H "Authorization: Bearer $ZSQH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "Распознай текст на изображении, выведи построчно, без пояснений."},
{"type": "image_url", "image_url": {"url": "https://example.com/invoice.jpg"}}
]
}
]
}'
При 401 сначала проверьте ключ и заголовок; при 400 — доступность URL изображения и поддержку формата; при 404 — Base URL и повторное склеивание пути.
5. Вызов на Python и структурированный вывод
Реальному проекту редко нужен только текст, чаще — поля. Можно попросить модель вывести JSON по схеме и проверить его локально:
import base64
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ZSQH_API_KEY"],
base_url="https://ai.zhongshangqihang.com/v1",
)
with open("invoice.jpg", "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
schema_hint = '{"invoice_no": "", "date": "", "amount": "", "seller": ""}'
resp = client.chat.completions.create(
model=os.environ["OCR_MODEL"], # имя модели с поддержкой изображений со страницы тарифов
messages=[{
"role": "user",
"content": [
{"type": "text", "text": f"Распознай документ и выведи по этой JSON-схеме, отсутствующие поля заполни null: {schema_hint}"},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_b64}"}},
],
}],
)
data = json.loads(resp.choices[0].message.content)
print(data)
Код запускается, но это не значит, что его можно выводить в production. Модель может добавить блок кода, пояснения или лишние поля, и json.loads сразу упадёт. На практике: используйте поддерживаемый платформой JSON-режим или структурированный вывод; перед разбором убирайте маркеры блоков кода; проверяйте типы через Pydantic или jsonschema; при ошибке возвращайте сообщение модели на один повтор, затем переводите на ручную проверку. Суммы, даты и налоговые номера дополнительно сверяйте.
6. Координаты, таблицы и структурированные поля
Классический OCR возвращает содержимое текстовых блоков, координаты и уверенность; мультимодальная модель выводит по промпту, и координаты не всегда надёжны. Сначала уточните формат координат: четырёхточечный полигон, [x1, y1, x2, y2] или [x, y, w, h]; единицы — пиксели или нормализация до 0–1000; где начало координат — в левом верхнем углу; после поворота и обрезки координаты нужно пересчитывать.
Если перед распознаванием изображение масштабировали, координаты нужно пропорционально вернуть к исходному размеру, иначе рамка подсветки сместится. Для таблиц заранее определите правила строк, столбцов, объединённых ячеек и пустых значений; сложные таблицы лучше распознавать специализированным интерфейсом, а затем передавать модели для упорядочивания.
Схему структурированных полей определяйте заранее: имя поля, тип, обязательность, представление пустого значения, нормализация дат и сумм. Для счетов также важны валюта, налог и связь суммы с налогом. Уверенность можно использовать для маршрутизации: поля с низкой уверенностью отправлять на ручную проверку, а не отбрасывать.
7. Предобработка: сделать распознавание стабильнее
Большая часть ошибок распознавания предопределена до запроса. Обрабатывайте в таком порядке:
- Прочитайте ориентацию EXIF и поверните изображение, чтобы документ не лежал на боку.
- Обрежьте до области документа, уберите большой фон и посторонние объекты.
- Выполните коррекцию небольшого наклона; при заметном перекосе сначала определите края.
- Управляйте разрешением: сканы 200–300 DPI, фото с телефона — от 1600–2400 пикселей по длинной стороне.
- Выцветшие и низкоконтрастные документы можно перевести в оттенки серого и умеренно повысить контраст.
- Многостраничные PDF и длинные скриншоты делите по страницам с небольшим перекрытием на стыках.
Размытое изображение не спасти повышением резкости, а текст низкого разрешения не приобретёт детали при увеличении. Цель предобработки — уменьшить помехи, а не сделать картинку красивой. При каждом изменении параметров сравнивайте точность полей на одной и той же партии реальных образцов.
8. Частые ошибки и диагностика
| Ошибка | Частая причина | Что делать |
|---|---|---|
401 Unauthorized |
Неверный или просроченный ключ, неверный заголовок | Проверить формат Bearer, пробелы и переменные окружения |
403 Forbidden |
Нет прав на модель, ограничение региона, недостаточно прав субаккаунта | Проверить авторизацию модели и политику аккаунта |
400 ошибка изображения |
Неверный префикс Base64, повреждённый файл, неподдерживаемый формат | Проверить заголовок файла после декодирования, перейти на JPEG или PNG |
413 Payload Too Large |
Превышен размер изображения или тела запроса | Сжать, уменьшить, обрезать или перейти на загрузку файла/асинхронный режим |
429 Too Many Requests |
Превышена частота или параллелизм | Снизить параллелизм, повторять с экспоненциальной паузой |
Тайм-аут или 502 |
Большое изображение, длинный документ, очередь на сервере | Перейти на асинхронную задачу или уменьшить запрос |
| Пустой или перепутанный результат | Неверная ориентация, низкое разрешение, сложная вёрстка | Повернуть, повысить чёткость, разбить на колонки |
При диагностике сначала фиксируйте request ID, имя модели, размер изображения и длительность. Часто «плохое качество модели» оказывается неверно переданным изображением, непересчитанными координатами или несовпадением схемы.
9. Миграция и проверка перед запуском
Переход от одного OCR-сервиса к другому обычно не ограничивается заменой base_url и api_key. Перед запуском проверьте:
- Новый интерфейс специализированный OCR или диалоговый визуальный; совместима ли структура запроса.
- Какие форматы изображений поддерживаются, какие ограничения на размер, число страниц и разрешение.
- Синхронный или асинхронный режим, сколько хранится результат, нужен ли публичный адрес для callback.
- Совпадают ли формат координат, единицы и начало отсчёта со старым сервисом.
- Покрывают ли схема полей, языки и типы документов текущий бизнес.
- Есть ли схема постепенного переключения, чтобы сначала пустить часть трафика и сравнить точность.
- Есть ли путь отката; старый ключ и интерфейс сохраняются на время.
Рекомендуется обернуть OCR в отдельный клиент, например recognize(image, schema) -> Result, и спрятать различия провайдеров в адаптере; тогда при смене сервиса бизнес-код не придётся переписывать. Модели, ограничения и цены — на странице тарифов.
Частые вопросы
Поддерживает ли OCR API PDF?
Зависит от интерфейса. Специализированные OCR-сервисы обычно поддерживают PDF, многостраничные документы чаще идут асинхронно; OpenAI-совместимый диалоговый интерфейс обычно работает с изображениями, поэтому PDF нужно разбить на страницы и преобразовать в изображения или использовать файловый интерфейс. Ориентируйтесь на документацию.
Какой максимальный размер изображения можно передать?
У разных провайдеров по-разному; обычно от нескольких МБ до 20 МБ на файл, плюс ограничения по пикселям и страницам. Рекомендуется сжимать и уменьшать до загрузки, чтобы снизить тайм-ауты и затраты на передачу.
Почему порядок распознанного текста нарушен?
Частые причины — несколько колонок, таблицы и смешанная вёрстка. Классический OCR сортирует по координатам, мультимодальная модель генерирует в порядке чтения; оба могут ошибаться. Можно делить на колонки, просить вывод по областям или использовать интерфейс с анализом вёрстки.
Какой способ структурированных полей самый надёжный?
Сначала определите схему, попросите модель вывести JSON и проверьте типы, регулярные выражения и бизнес-правила локально. Если платформа поддерживает структурированный вывод, используйте его; иначе добавьте один повтор с текстом ошибки, затем переводите на ручную проверку.
Что менять при переходе с одного OCR-сервиса на другой?
Помимо Base URL и ключа проверьте структуру запроса, синхронность, ограничения изображений, формат координат, схему и правила лимитов. Сначала постепенное переключение и сравнение точности полей на реальных образцах, затем полный переход.
Что дальше
Чтобы выполнить первый запрос, создайте ключ с небольшим лимитом на странице регистрации и проверьте на реальном счёте загрузку, распознавание и JSON-вывод. Для выбора тарифа смотрите цены и сравните точность полей на небольшой размеченной партии изображений. Цены меняются; ориентируйтесь на информацию сайта.
Читайте также:
- API Key для OCR: создание и безопасная настройка
- Бесплатные лимиты OCR и их ограничения
- Настройка LangChain для RAG-приложений
Примечание: OpenAI, Google, Microsoft, Alibaba Cloud, Tencent Cloud, Baidu и другие упомянутые бренды — товарные знаки их правообладателей. Статья носит технический характер; ограничения и правила тарификации определяются официальной документацией платформ.
