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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • ФИО,

  • пол,

  • возраст,

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

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

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

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

[
    {
"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" = "ж";
    }

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

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

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

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

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

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

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

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

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

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

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

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

1825

2025

Мужские

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

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

Женские

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

Комментарии (4)


  1. YuMo
    28.05.2026 05:23

    Спасибо за работу, пожалуй добавлю ссылку на вас. https://ya.ru/archive


  1. MS03
    28.05.2026 05:23

    Хорошая, большая работа!


  1. dei
    28.05.2026 05:23

    open source модели?
    По сравнению с архивом Финляндии - у вас хуже/лучше получается?
    https://huggingface.co/Kansallisarkisto/cyrillic-htr-model


  1. andy_p
    28.05.2026 05:23

    Да, пользуюсь вашим архивом при составлении генеалогического древа. Нашел много документов о своих предках.