- BrainTools - https://www.braintools.ru -

От OCR к смыслу: как мы научили модель понимать, кто кому отец, мать, жених и свидетель

От OCR к смыслу: как мы научили модель понимать, кто кому отец, мать, жених и свидетель - 1

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

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

Теперь в Поиске по архивам работает новая модель распознавания документов. Она не только распознаёт текст архивного файла, но и структурирует информацию из него. Например, понимает роли и связи между разными людьми: «родившийся», «отец» и «мать» для рождения или «жених», «невеста», «свидетель» для брака. 

Меня зовут Даша Виноградова, я руковожу универсальными применениями компьютерного зрения [1] в Яндексе. Вместе с Аней Сидоровой, главным разработчиком распознавания архивов, мы расскажем, как мы сделали шаг от распознавания текста к извлечению структуры и смысла из архивных документов: как мы перестраивали OCR‑пайплайн, почему нам не подошли универсальные VLM‑модели и как пытались разобраться, кто есть кто: отец, мать, жених или свидетель.


С какими данными мы работаем

Основные типы документов, которые мы используем, — это метрические книги, ревизские сказки и исповедные ведомости. О них мы уже рассказывали в нашем предыдущем материале [2], но я напомню, что это за источники:

  • Метрические книги — документы для актовых записей о рождении, браке или смерти в период с начала XVIII века по 1918 год.

  • Ревизские сказки — результаты проведения подушных переписей населения Российской империи начала XVIII — второй половины XIX века. 

  • Исповедные ведомости — ежегодный отчёт по каждому приходу православной церкви в Российской империи в XVIII — начале XX века. 

На момент публикации статьи мы работаем с архивами из 24 регионов, а всего оцифровали и распознали уже примерно 23 млн сканов.

Архивные тексты сложны для человеческого восприятия [3] — не то что для автоматической разметки. Особенности записи, старая грамматика, разные почерки — всё это добавляет сложностей. Поэтому нам помогают эксперты по работе с архивными документами: они расшифровывают тексты и размечают сканы для создания обучающей выборки.

В прошлый раз мы писали о первой версии разметки: мы смотрели только на строки рукописного текста. Сейчас же мы сосредоточились на том, чтобы сделать шаг в анализе и понимании структуры рукописного текста, чтобы вычленять его суть. Эта задача сложна тем, что должна находить информацию, расшифровывать её и выделять контекст. Для этого нужно было пересмотреть весь пайплайн: от формата разметки до архитектуры модели.

Распознавание структур

Что есть на старте

До сих пор мы предлагали пользователям работать только с распознанным текстом скана, состоящим из отдельных отрывков. Искать ФИО интересующих людей приходилось среди всего, что упомянуто на скане, — порядковых номеров, пометок, имён священников и свидетелей события. Другими словами, результат поиска был довольно шумным.

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

Запись о радостном событии в семье Ворониных

Запись о радостном событии в семье Ворониных

Имя родившейся (Параскева) внесено в отдельную колонку, а её отчество и фамилия (Александрова, Воронина) в принципе не существуют в распознанном тексте как отдельные слова. Конечно, прочитав имя отца, легко понять, что полное имя родившейся — Параскева Александрова Воронина. Однако с точки зрения поиска слова «Александр», «Егоров», «Воронин», «Дмитров» — абсолютно равнозначные. Так что в указанном отрывке можно с одинаковым успехом искать Параскеву Александрову, Параскеву Егорову, Параскеву Воронину и Параскеву Дмитрову.

Аналогичная ситуация происходит не только с родившимися детьми: например, полное ФИО матери — Воронина Акилина Тимофеева — тоже не упомянуто в тексте впрямую.

Ещё один специфичный, но нередкий случай: прадед пользователя был тёзкой священника, ведущего записи в документах всего прихода. А это сильно усложняет поиск, ведь в таком случае на нашем портале могла найтись сотня, тысяча, а то и десяток тысяч страниц, где встречалось искомое ФИО, но не участника события, а в качестве служебной записи о церковнослужителе.

Священник Алексей Птицын упомянут на скане 20 раз!

Священник Алексей Птицын упомянут на скане 20 раз!

Конечно, можно попробовать некими эвристиками вытащить из распознанного текста имена и фамилии участников событий, но есть нюанс. В условиях разнообразия метрических книг, при наличии половинчатых и расположенных под углом сканов, иногда находящих друг на друга записей обойти погрешности распознавания невозможно. Поэтому метод эвристик не способен обеспечить здесь хорошее качество.

В то же время на дворе 2026 год. Современное решение очевидно: нам нужно задействовать мощь моделей, которые смогут не просто распознать текст, но и осознанно извлечь из него информацию.

Решение

По сути, перед нами стоит KIE‑задача (Key Information Extraction): нужно по изображению документа и заданной инструкции извлечь из него ключевую информацию, а такой формат хорошо подходит для большой мультимодальной модели. Но в нашем случае есть важное ограничение: распознавание русского архивного рукописного текста — слишком специфичный домен, чтобы внешние универсальные модели могли показать хорошее качество.

Впрочем, для нас это не стало проблемой. В нашем распоряжении есть собственная VLM‑модель Alice AI [4], которая хорошо понимает русский язык и умеет работать с изображениями. Благодаря этим базовым навыкам модель можно довольно быстро доучить под нашу задачу, не собирая для этого гигантскую обучающую выборку.

Гораздо серьёзнее оказался другой вопрос — размер контекста. Типичный архивный скан — это изображение со стороной больше 2500 пикселей, на котором размещено сразу несколько записей, а в них суммарно может упоминаться до 30–35 человек. Это довольно большое количество информации и на входе, и на выходе.

Пример стандартного архивного скана

Пример стандартного архивного скана

Отсюда вытекает сразу несколько рисков:

  • С большой вероятностью модель не сможет справиться с таким разрешением входной картинки.

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

  • Обработка каждого скана будет долгой и достаточно дорогой с точки зрения вычислений, ведь генерация каждого следующего токена будет происходить с учётом всех прошлых токенов. Последнее, конечно, полезно, когда выдаётся информация о людях, относящихся к одному событию, но бессмысленно при обработке несвязанных между собой записей со страницы.

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

Поэтому мы решили съесть нашего архивного слона по частям: сначала находить на странице отдельные записи, а уже потом извлекать информацию о людях из каждой выделенной области. Заодно такой подход дал нам хороший граундинг — то есть точные координаты самих записей.

Выделили нужные нам фрагменты

Выделили нужные нам фрагменты

Наш итоговый пайплайн работы со сканом выглядит так:

  1. Модель распознавания сначала расшифровывает текст на скане. Это важный отдельный этап: архивный рукописный текст — очень сложный домен, и мультимодальная модель заметно лучше справляется с задачей, если получает на вход результат работы специализированного OCR.

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

  3. После этого для каждой найденной записи мы вырезаем соответствующий фрагмент исходного скана и добавляем к нему текст, который OCR‑модель получила на первом этапе. Этот текст служит для VLM внешней подсказкой и помогает точнее понять содержимое записи.

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

Таким образом, мы извлекаем лучшее из всех наших моделей: получаем распознанный текст от специализированной OCR‑модели, а затем понимаем и структурируем полученную информацию при помощи VLM‑модели.

Желаемый формат

Следуя логике [5] нашего пайплайна, в качестве целевой сущности мы сначала выбрали запись о событии. У каждого из трёх типов событий есть свой стандартный набор ролей: в записи о рождении это ребёнок, его родители и пара восприемников, то есть крёстных; в записи о бракосочетании — жених, невеста и поручители; в записи о смерти роль, как правило, одна — умерший.

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

Возвращаемся к Параскеве Ворониной

Возвращаемся к Параскеве Ворониной

Для уже знакомой нам записи минимальный набор полей будет такой:

{
"имя ребенка": "Параскева",
"имя отца": "Александр",
"отчество отца": "Егоров",
"фамилия отца": "Воронин",
"гео отца": "город Дмитров",
"инфо об отце": "мещанин из цыган",
"имя матери": "Акилина",
"отчество матери": "Тимофеева",
...
}

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

  • у незаконнорожденного ребёнка в графе родителей были указаны мать и муж матери;

  • у крёстной матери очень часто дополнительно упоминался её муж или отец — а это довольно важная информация о семейных связях;

  • запись была сделана не в честь рождения, а в честь перехода человека из католической в православную веру;

  • у усыновлённых детей указывались только приёмные родители;

  • родилась двойня.

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

К слову, данные о бракосочетаниях и смертях добавили непредсказуемости:

  • Практика показала, что у числа поручителей (свидетелей) на свадьбе нет верхней границы. Текущий обнаруженный нами рекорд — 13 поручителей!

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

  • В одной записи о смерти могут быть упомянуты муж или отец, а также встречаются упоминания сразу нескольких умерших: например, «крестьянина Ивана Саврасова дети: сын Михаил, дочь Аксинья».

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

  • ФИО,

  • пол,

  • возраст,

  • роль в событии (статус),

  • географическое положение,

  • дополнительную информацию (профессию, социальный статус и тому подобное).

Соответственно, одна запись — это список из некоторого количества людей. И на уже знакомом нам примере можно посмотреть финальный вид разметки.

От OCR к смыслу: как мы научили модель понимать, кто кому отец, мать, жених и свидетель - 7
[
    {
"status" = "родившийся";
"name" = "Параскева";
"second_name" = "Александрова";
"surname" = "Воронина";
"sex" = "ж";
    };
    {
"status" = "отец";
"name" = "Александр";
        "second_name" = "Егоров";
"surname" = "Воронин";
"geo" = "город Дмитров";
 "info" = "мещанин из цыган";
"sex" = "м";
    };
    ...
]

Это сильно упростило задачу. Вместо трёх похожих сценариев, у каждого из которых был свой набор полей, мы получили один универсальный: нужно выписать всех людей из записи и для каждого человека заполнить 8 полей.

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

Работа специалиста по разметке

Работа специалиста по разметке

Но и распределение по полям способно доставить хлопоты. Попробуйте разобраться в этой записи о крещении:

Восприемниками были: 5-й бригады корпуса морской Артилеріи Канонир Елисей Аникъевъ, и Арестантской роты прапорщика Ивана Дуванова денщика Саввы Антонова сына Карчавина, жена Марія Исаева дочь

Правильный ответ
{
        "status" = "крестный отец";
        "name" = "Елисей";
        "second_name" = "Аникеев";
        "sex" = "м";
        "info" = "5-й бригады корпуса морской артиллерии канонир";
 };
{
         "status" = "муж крестной матери";
        "name" = "Савва";
        "second_name" = "Антонов";
"surname" = "Карчавин"
        "sex" = "м";
        "info" = "денщик прапорщика арестантской роты Ивана Дуванова";
    };
{
         "status" = "крестная мать";
        "name" = "Мария";
        "second_name" = "Исаева";
"surname" = "Карчавина"
        "sex" = "ж";
    }

В итоге для обучения [6] текущей модели мы собрали разметку для 3000 записей. Ещё 3000 записей были размечены для тестовой выборки.

Результат и метрики 

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

В итоге мы сформулировали её так: это доля людей, которых можно найти по ФИО в нашем сервисе. Для этого мы сравниваем записи о людях из ground‑truth‑разметки со сведениями, которые предсказала модель. При этом учитываем не только точные, но и неточные совпадения — по тем же правилам, которые уже используются в поиске Поиска по архивам.

Получившиеся числа радуют:

  • для рождений — 92,7%

  • для свадеб — 89,7%

  • для смертей — 87,2%

Итого по всем категориям — 90,5%

Имена собственные — традиционно один из самых сложных типов данных в распознавании архивных текстов, поэтому такой результат нас, конечно, очень радует. При этом мы видим, что «потерянные» люди — это обычно более редкие участники события, например мужья крёстных матерей или поручители в записях, где их особенно много. Значит, именно на таких случаях нам и нужно продолжать работу.

Бонус: статистика по именам

Новый подход открывает пространство для различных исследований. Например, во время работы над новой моделью мы собрали интересную статистику: какие имена у детей были популярны в Москве 200 лет назад. Для сравнения — статистика по именам за прошлый год:

1825

2025

Мужские

Иван, Василий, Петр

Михаил, Александр, Лев

Женские

Мария, Анна, Евдокия

Анна, София/Софья, Мария

Переход к блоковой модели

Зачем нужны блоки 

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

Пока то же самое верно и для OCR: специализированные модели распознавания текста работают заметно быстрее больших VLM и в своих доменных задачах часто показывают более высокое качество. Поэтому мы используем распознанный текст как дополнительный источник информации [7]. Собственно, по этой причине нам важно улучшать и сам этап расшифровки.

В задаче OCR сейчас существует два основных подхода. 

  • Модель разбивает документ на отдельные фрагменты по порядку чтения, например абзацы, таблицы и другие блоки, а затем распознаёт каждый из них отдельно. Так задачу распознавания всего документа удаётся разложить на обработку более компактных частей и тем самым уменьшить проблемы, связанные со слишком длинным контекстом. По такому принципу, например, устроены PaddleOCR [8] и MinerU [9]: в них детекция и распознавание — это отдельные этапы, за которые отвечают разные модели.

  • End‑to‑end‑распознавание, которое сразу превращает изображение документа в текст без промежуточных этапов. Так, например, работают DeepSeekOCR [10] и Qianfan‑OCR [10]

Оба подхода объединяет то, что современные OCR‑модели стараются использовать как можно больше контекста. Вместо отдельных символов или строк они анализируют целые фрагменты документа, учитывая расположение текста на странице, её структуру и визуальные зависимости между элементами.

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

Со временем мы упёрлись в новый класс проблем. Ошибки [11] в итоговом тексте всё чаще возникали не потому, что модель плохо распознаёт строки, а из‑за ограничений архитектуры нашего подхода.

Например, одна из частых и довольно нелепых для человеческого глаза ошибок — лишние пробелы внутри слов. Это связано с особенностью метрических книг: в них, как правило, нет знаков переноса.

Типичный пример отсутствия знаков переноса

Типичный пример отсутствия знаков переноса

Распознанный текст блока: 

Дъревни Калмиковой у крестья_нина Ивана Михайлова Лаза_рева и жены его Неонилы Стефа_новой Сынъ тимофъй

Если смотреть на этот результат с позиции, что модель распознавания обрабатывала отдельные строки, — распознавание идеальное. Но итоговый текст всё равно выглядит плохо: несмотря на отсутствие переноса на скане, легко понять, что нужно склеить слова «крестьянина», «Лазарева» и «Стефановой». Однако подобная склейка происходит на этапе постпроцессинга и сборки финального текста при одном условии — наличии знака переноса.

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

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

Например, при прочтении отдельной строки…

От OCR к смыслу: как мы научили модель понимать, кто кому отец, мать, жених и свидетель - 10

…сложно распознать последнее слово без ошибки. Но если увидеть целый отрывок, то становится значительно проще:

От OCR к смыслу: как мы научили модель понимать, кто кому отец, мать, жених и свидетель - 11

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

От OCR к смыслу: как мы научили модель понимать, кто кому отец, мать, жених и свидетель - 12

Кроме того, мы работаем и с довольно специфичными документами XVII века — они написаны скорописью. Этому виду письма свойственно большое количество сокращений, выносные буквы, лигатуры (соединение двух или более букв или их элементов в одну графическую форму), использование титла (надстрочного знака для сокращений). Чтобы правильно распознать такой текст, модели нужно видеть не одну строку, а сразу весь нужный контекст: и основную строку, и ту, где находятся выносные буквы. Для таких документов значение контекста особенно велико.

Пример записи скорописью. Здесь написано «от священника»

Пример записи скорописью. Здесь написано «от священника»

Всё это подтолкнуло нас к переходу от строкового пайплайна к блоковому. Теперь детектор выделяет не отдельные строки, а целые текстовые блоки, а модель распознавания умеет работать именно с ними.

Переход и результаты

Дополнительным плюсом пайплайна стало то, что мы сокращали его на целый шаг. Мы пропускали группировку строк и их частей в отдельные блоки, уменьшая количество используемых моделей и сокращая процессинг в обработке скана.

Существующий детектор блоков пришлось переучивать, причём гораздо строже, чем раньше. Если в старом пайплайне его ошибка обычно приводила к тому, что какие‑то строки не склеивались в итоговый блок, то теперь цена ошибки стала выше — можно полностью потерять текст нужного фрагмента.

Архитектура модели распознавания при этом осталась трансформерной, но сам блок оказался гораздо менее предсказуемой единицей, чем строка. Он может состоять из одного короткого слова и из десятка длинных строк, поэтому размер входа по пикселям меняется очень сильно — от маленького квадрата 20 × 20 до большого блока 2000 × 2000. Из‑за этого нам пришлось отдельно решать две важные подзадачи: подобрать энкодер, который хорошо работает с таким разбросом размеров, и оптимизировать словарь токенов вместе с его наполнением. Это важно потому, что генерировать текст для целого блока символ за символом довольно затратно с точки зрения вычислений.

После перехода на блочную архитектуру мы замерили результаты, и они нас порадовали. Для оценки у нас есть две рукописные тестовые корзины: первая собрана в тех же пропорциях типов документов, в каких они представлены в нашей базе, а вторая специально смещена в сторону более сложных случаев. Качество на них мы считаем следующим образом: metric = hits / (hits + deletions + substitutions), где hits — это слова, которые совпали у модели и в референсе, deletions — слова, которые модель пропустила, а substitutions — лишние или неправильно распознанные слова.

На обеих тестовых корзинах переход на новый пайплайн дал рост качества: на потоковой выборке мы получили recall 93,2%, а на сложной — 88,1%.


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

Сейчас мы уже переобошли наши базы с использованием обоих новых подходов и надеемся, что поиск по архивам стал точнее и удобнее. Очень надеемся, что это поможет вам узнать что‑то новое о своих родственниках. Будем рады вашим отзывам и репортам.

Но самое главное, что поиск по архивам теперь не просто поиск словосочетания в тексте. Теперь это поиск человека среди людей.

Автор: dara-orange

Источник [12]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/30823

URLs in this post:

[1] зрения: http://www.braintools.ru/article/6238

[2] предыдущем материале: https://habr.com/ru/companies/yandex/articles/712510/

[3] восприятия: http://www.braintools.ru/article/7534

[4] VLM‑модель Alice AI: https://habr.com/ru/companies/yandex/articles/974594/

[5] логике: http://www.braintools.ru/article/7640

[6] обучения: http://www.braintools.ru/article/5125

[7] источник информации: http://www.braintools.ru/article/8616

[8] PaddleOCR: https://arxiv.org/abs/2601.21957

[9] MinerU: https://arxiv.org/abs/2509.22186v2

[10] DeepSeekOCR: https://arxiv.org/abs/2603.13398

[11] Ошибки: http://www.braintools.ru/article/4192

[12] Источник: https://habr.com/ru/companies/yandex/articles/1038044/?utm_campaign=1038044&utm_source=habrahabr&utm_medium=rss

www.BrainTools.ru

Rambler's Top100