Распознавание документов (паспорт, водительское, диплом) в 1С через нейросеть: LLM + OCR локально

Приём одного сотрудника на работу — это 40 минут ручного ввода: оператор перепечатывает в 1С паспорт, водительское удостоверение, диплом, трудовую книжку, а у иностранцев документов ещё больше. Ошибиться в серии паспорта или дате — легко, а отвечать за это потом бухгалтерии.

Задачу «сфотографировал документ → получил заполненную карточку в 1С» сегодня закрывает связка Vision-LLM + OCR. Причём — полностью локально, без отправки персональных данных в облако. Ниже разберём, как это устроено: подходы к распознаванию через языковые модели, гибридный pipeline YOLO + LLM, живые примеры кода и честный разговор про точность. В конце — где научиться собирать такой проект с нуля.

Распознавание документов (паспорт, водительское, диплом) в 1С через нейросеть
Видео: Распознавание документов (паспорт, водительское, диплом) в 1С через нейросеть

Почему не облачный сервис распознавания

Соблазн отправить скан паспорта в облачный OCR-сервис большой — там всё «из коробки». Но паспорт, водительское, диплом — это персональные данные. По 152-ФЗ и требованиям к трансграничной передаче отправлять сканы документов на зарубежные серверы нельзя. Значит, распознавание должно жить внутри контура компании.

Хорошая новость: современные открытые Vision-модели (Qwen3-VL, семейство *-VL, специализированные OCR-модели) запускаются на локальном железе и по качеству близки к облачным. В кейсе, который мы разбираем, крутится Qwen3-VL на 27 млрд параметров в кванте UD-Q8 — она помещается на связку из трёх видеокарт (3090 + две 5070 Ti), а веса и контекст распределяются по картам через tensor split.

Итог: локальная нейросеть даёт «облачное» качество распознавания документов, не нарушая закон о персональных данных.

Три подхода к распознаванию документов

Прежде чем собирать систему, полезно понять, чем распознавание через LLM отличается от классического OCR. Сравните три подхода — переключайте критерии и смотрите, кто выигрывает:

Коротко:

  • Классический OCR (Tesseract, шаблоны по координатам). Быстрый и дешёвый (работает на CPU), но ломается на любом новом макете и почти не берёт рукопись. Хорош там, где бланк строго фиксирован.
  • Чистая Vision-LLM. Отправляем всю картинку в мультимодальную модель и промптом просим вернуть JSON. Не зависит от расположения полей, читает рукописную кириллицу, легко меняется под новые поля. Минусы — тяжёлая (нужен GPU) и иногда «плывёт» на мелком тексте вроде вертикального номера паспорта.
  • Гибрид YOLO + LLM. Сначала детектор находит и вырезает поля, потом LLM читает каждый мелкий кроп отдельно. Именно этот подход даёт максимальную точность на «сложных» полях и лежит в основе разбираемого проекта.

Общий принцип: как LLM «читает» документ

Мультимодальная модель принимает на вход картинку и текстовый промпт, а на выходе отдаёт текст. Весь фокус — заставить её вернуть строго структурированный JSON, а не свободный рассказ. Для этого в промпте:

  1. Задаём роль и задачу («ты извлекаешь данные из паспорта РФ»).
  2. Явно перечисляем поля и их формат (даты — ДД.ММ.ГГГГ, серия/номер — цифрами).
  3. Просим вернуть только JSON по заданной схеме и ничего лишнего.

Вот минимальный пример вызова локальной модели через Ollama (OpenAI-совместимый API):

import base64, json
from openai import OpenAI

client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")

def encode(path: str) -> str:
    with open(path, "rb") as f:
        return base64.b64encode(f.read()).decode()

PROMPT = """Ты извлекаешь данные из фотографии паспорта РФ.
Верни СТРОГО JSON по схеме, без пояснений:
{"series": "0000", "number": "000000", "surname": "", "name": "",
 "patronymic": "", "birth_date": "ДД.ММ.ГГГГ", "issued_by": ""}
Если поле не читается — верни пустую строку."""

resp = client.chat.completions.create(
    model="qwen3-vl:27b",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": PROMPT},
            {"type": "image_url",
             "image_url": {"url": f"data:image/jpeg;base64,{encode('passport.jpg')}"}},
        ],
    }],
    temperature=0,               # нам нужен детерминизм, не креатив
    response_format={"type": "json_object"},
)

data = json.loads(resp.choices[0].message.content)
print(data)
# {'series': '4509', 'number': '123458', 'surname': 'Иванов', ...}

Ключевые детали: temperature=0 (распознавание — это не творчество), response_format=json_object (модель обязана вернуть валидный JSON), и явная схема прямо в промпте. Этого уже достаточно, чтобы распознать водительское удостоверение хорошего качества почти идеально.

Гибридный pipeline: детекция → кроп → LLM

Чистая LLM спотыкается на мелких полях. Решение — сначала найти поля детектором YOLO11 OBB (ориентированные рамки — ловят текст даже под наклоном), вырезать каждое поле в отдельную картинку и только потом отдавать в языковую модель. Пройдите шаги пайплайна для разных документов:

Детекция полей — отдельный микросервис на YOLO. Он обучается на своём датасете, размеченном в CVAT, и возвращает координаты полей:

from ultralytics import YOLO

model = YOLO("weights_dir/passport/best.pt")   # дообученная модель полей паспорта
result = model(image)[0]

crops = []
for box in result.obb:                          # OBB — oriented bounding boxes
    cls = model.names[int(box.cls)]             # 'series_number', 'surname', 'name'...
    xy = box.xyxyxyxy.cpu().numpy().reshape(-1, 2)
    crops.append({"field": cls, "image": crop_by_polygon(image, xy)})

Каждый кроп — это уже маленькая понятная картинка (только серия и номер, только фамилия). LLM читает такой фрагмент заметно точнее, чем весь разворот сразу. Это и есть главный лайфхак гибрида.

Живая демонстрация: что возвращает модель

Ниже — симуляция ответа Vision-LLM на реальных примерах. Нажмите «Распознать» и посмотрите, как поля заполняются с оценкой уверенности. Обратите внимание: на плохом скане модель честно ошибается — и такие поля система помечает для оператора, а не выдаёт за истину:

Сам эндпоинт распознавания — обычная ручка FastAPI, которую одинаково легко дёрнуть из 1С, с сайта или из мобильного приложения:

from fastapi import APIRouter, UploadFile

router = APIRouter(prefix="/api/v1/ocr")

@router.post("/passport/yolo/")
async def recognize_passport(file: UploadFile):
    image = await read_image(file)
    crops = detect_fields(image)               # YOLO: нарезка полей
    fields = {}
    for crop in crops:
        fields[crop["field"]] = read_with_llm(crop["image"], crop["field"])
    return normalize(fields)                    # даты, регистр, валидация

Пример ответа для 1С:

{
  "doc_type": "passport_rf",
  "series": "4509",
  "number": "123458",
  "surname": "Иванов",
  "name": "Пётр",
  "needs_review": ["number"]
}

Поле needs_review — ключевое для продакшена. Оператор в 1С видит заполненную форму и сверяет только помеченные поля, а не набирает всё вручную. Приём одного человека сокращается с 40 до примерно 10 минут.

Рукописный текст и «умная» постобработка

Самый сложный кейс — диплом: часть данных вписана от руки, макеты у всех разные. Здесь классический OCR бессилен, а Vision-LLM читает рукописную кириллицу — пусть и с ошибками на редких фамилиях и названиях вузов (например, «Истринский» модель может прочитать как «Решинский»).

Лечится это постобработкой через эмбеддинги: распознанное название ищем по справочнику всех учебных заведений и заменяем на ближайшее реальное.

# Справочник вузов заранее переведён в векторы (эмбеддинги)
query_vec = embed(recognized_name)                  # "Решинский пед. колледж"
best = max(institutions, key=lambda x: cosine(query_vec, x.vec))
if cosine(query_vec, best.vec) > 0.82:
    recognized_name = best.title                    # → "Истринский пед. колледж"

Тот же приём работает и для кодов специальностей: модель извлекает название квалификации, а мы находим по нему официальный код в справочнике. Так система сама исправляет часть своих же ошибок распознавания.

Про железо: что нужно для локальной модели

Vision-LLM на 27B — это GPU. В разбираемом кейсе модель в кванте UD-Q8 распределена по трём картам (3090 + 5070 Ti + 5070 Ti) через tensor split, с контекстом 65 000 токенов (связка тянет и 260 000). Если хочется дешевле — можно взять модель поменьше (4B–8B) или использовать гибрид, где в LLM уходит не весь лист, а только мелкие кропы: нагрузка на видеопамять заметно падает.

Точность честно: человек в контуре

Ни одна OCR-система не даёт 100% на «боевых» фото. Поэтому правильная архитектура — human-in-the-loop: модель распознаёт и оценивает свою уверенность, спорные поля помечает, а финальное решение принимает оператор. Это не «костыль», а норма для документооборота: даже 90% автозаполнения экономят колоссальное время, если оставшиеся 10% удобно проверить и поправить.

Где научиться собирать такое с нуля

Проект из этой статьи построен на основе учебного проекта, который разбирается пошагово — от локального запуска модели и промптинга до детекции YOLO, разметки в CVAT, дообучения и интеграции с 1С — на курсе «ChatGPT и нейросети для 1С». Там вы соберёте свой pipeline распознавания документов и научитесь встраивать LLM в реальные бизнес-процессы.

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

Можно ли распознавать документы полностью локально, без интернета?
Да. Открытые Vision-модели (Qwen3-VL и аналоги) запускаются на своём сервере с GPU. Персональные данные не покидают контур компании — это соответствует 152-ФЗ.

Насколько точно нейросеть распознаёт паспорт и водительское удостоверение?
На хорошем скане водительское распознаётся практически идеально. У паспорта слабое место — мелкий вертикальный номер; гибрид YOLO + LLM вырезает это поле отдельно и повышает точность. Спорные поля система помечает для проверки оператором.

Читает ли модель рукописный текст?
Да, Vision-LLM распознаёт рукописную кириллицу — например, рукописные поля в дипломе. На редких фамилиях и названиях возможны ошибки, которые лечатся постобработкой через эмбеддинг-поиск по справочнику.

Как результат распознавания попадает в 1С?
Сервис возвращает JSON, который одинаково легко подтянуть в 1С, на сайт или в мобильное приложение. В 1С оператор видит заполненную карточку и сверяет только помеченные поля.

Что лучше — классический OCR или LLM?
Для строго фиксированных бланков быстрее и дешевле классический OCR. Для потока разных документов (паспорта, ВУ, дипломы, рукопись) выигрывает LLM или гибрид YOLO + LLM — он не зависит от макета и читает рукописный текст.


Хотите разобраться в разработке AI-проектов для 1С глубже — приходите на курс «ChatGPT и нейросети для 1С».