Извлечение атрибутов ИК (LLM)

Epic Версия: 0.3 draft

Из снимков бумажной информационной карты документального памятника (фонд ОФО БАН) извлекаются структурированные атрибуты для последующей проверки оператором и выгрузки в АБИС. Носитель — фиксированный бланк: данные внесены рукописно, впечаткой или отметками в матрицах чекбоксов. Канонический промт и схема ответа версионируются здесь; сервис извлечения хранит копию и указывает версию промта в ответе.

⟨/⟩ Исходник

1. Цель

Превратить снимки бумажной информационной карты (ИК) в структурированный JSON: значения атрибутов, состояние отметок бланка, уверенность по каждому полю и привязка значения к фрагменту изображения. Результат предзаполняет карточку на проверке полей; истину устанавливает оператор (см. EPIC «Обработка пакета»).

Промт model-agnostic: одна и та же схема ответа для облачной VLM (пилот), локальной модели и связки OCR + LLM. Извлечение НЕ принимает решений — только предзаполняет поля.

2. Акторы

Актор Роль в эпике
Сервис извлечения по снимкам ИК формирует JSON атрибутов + уверенность + источники (bbox)
Оператор проверки сверяет предзаполненные поля со снимками, правит, подтверждает (эпик «Обработка пакета»)

3. Границы

Входит: канонический промт извлечения, схема ответа (состав полей, представление чекбоксов), роли изображений сторон карты, правила уверенности и привязки к источнику.

Не входит: предобработка/нормализация снимков, проверка и корректировка оператором, формирование записи АБИС, версионирование записей — это соседние эпики/требования.

Схема ответа родовая (kind-agnostic) — один контракт на все виды FundDocumentKind (издание — книга/листовой/карта/вложение; рукопись — книга/свиток/лист): вид-специфичные текстовые поля идут родовым массивом fields[] со свободными именами, а card_kind определяет модель (FR-003). Детально на реальных бланках проработан пока EditionBook; прочие виды укладываются в тот же контракт без изменения схемы — добавляется лишь понимание их полей в промте/маппинге. Блоки СОХРАННОСТЬ/КОНСЕРВАЦИЯ типизированы и переиспользуются между видами.

4. Страницы формы

Кадр относится к странице распознанной формы (FormPage формы DocumentForm); прежней роли кадра из перечисления (ImageRole) больше нет — её место заняла страница формы (ADR-007). Форма книжной ИК (FundDocumentKind.EditionBook) — две страницы (стороны листа). Главной страницы НЕТ — у каждой свой набор полей; извлечение работает по тем страницам, что переданы.

Страница Заголовок Что извлекается
Front «Описание документального памятника» шапка (шифр, инв. номер, место хранения, дата), библиоописание, провенанс, матрица «Отметка о наличии элемента данных» (консервация)
Back «Сохранность» размеры, состояние/материалы переплёта и блока, повреждения, мониторинг, комментарий

У других видов карт форма содержит больше страниц (материальная основа, стабилизация, сведения об обработке); их разбор добавится вместе с их бланками. Front/Back — метки страниц, используемые в sources[].image схемы ответа.

«Вар.2/вар.3» на снимках — повторные описания того же документа (учебные/контрольные); каждый снимок описывается независимо, объединение версий — вне эпика.

5. Схема ответа (черновик v2 — родовая / kind-agnostic)

Схема едина для всех видов карт (card_kind — что за вид — определяет модель по макету, FR-003):

Так один контракт покрывает все виды: типизация — там, где стабильно (identity + консервация/сохранность), свобода имён — там, где состав плывёт (библио-поля). Вид-специфичную типизацию несёт слой проверки/маппинга в АБИС, а не схема извлечения.

Каждое текстовое значение — объект { value, confidence, handwritten?, reconstructed?, sources: [ { image, bbox } ] }, где bbox = [x0, y0, x1, y1] в целочисленной шкале 0..1000 (x = доля ширины ×1000, y = доля высоты ×1000; левый-верх и правый-низ). Незаполненные текстовые поля в ответ не включаются.

Шкала 0..1000, а не доли 0..1: на прогонах VLM (llama.cpp Qwen) целочисленная шкала — её обучающая конвенция — даёт заметно точнее прилегающие рамки; доли 0..1 «плывут», особенно в объёмном ответе.

Чекбоксы — полная матрица: возвращается КАЖДАЯ клетка бланка со значением true/false (оператор мог рассмотреть и НЕ отметить — это значимо). Уверенность — на уровне группы; bbox — на каждую строку матрицы «Задано/Выполнено» (для подсветки конкретной отметки), для группы выбора — bbox на группу; всё в шкале 0..1000.

{
  "card_kind": "EditionBook",                // ВЫХОД: вид документа определяет модель по макету (FR-003); один из FundDocumentKind (7 видов)
  "prompt_version": "v2",                    // проставляет сервис (v2: родовой fields[], координаты 0..1000, bbox на строки матрицы)
  "form_title",                              // печатный баннер бланка/программы («Издания из фондов БАН», «Фазовая консервация книги XVII–XX вв.»)
  "identity": { "shifr", "inv_number", "storage_location", "fill_date" },   // фикс. набор, keyed (см. глоссарий «Информационная карта»)

  "fields": [                                // РОДОВОЙ массив вид-специфичных ТЕКСТОВЫХ полей; name — по смыслу подписи; только заполненные
    { "name": "author", "value": "…", "confidence": 0.9, "handwritten": true, "sources": [ { "image": "Front", "bbox": [x0,y0,x1,y1] } ] }
    // состав СВОБОДНЫЙ (зависит от вида/бланка). Для EditionBook по смыслу: author, translator_compiler, title, place,
    // publisher, printing_house, year, language, binding, convolute, alligat_count, volume_number, pages_count,
    // separate_ill_sheets, ill_in_text, format, manuscript_sheets, bookplate, bookplate_desc, chamber_catalog,
    // marginalia, records, first_academic_stamp, private_library_evidence, acquisition_source, comments
  ],

  "conservation_marks": {                    // страница Front — «наличие элемента данных», матрица Задано/Выполнено
    "book":    [ { "item": "Реконструкция", "set": false, "done": false, "bbox": [x0,y0,x1,y1] }, /* все строки, bbox на каждую (0..1000) */ ],
    "binding": [ /* Реконструкция, Реставрация, Ремонт, Чистка, Умягчение — каждая {item,set,done,bbox} */ ],
    "block":   [ /* Реставрация, Нейтрализация, Ремонт — каждая {item,set,done,bbox} */ ],
    "storage_conditions": { "Вертикальное": true, "Горизонтальное": false, "Другое": false }   // группа выбора: bbox на группу
  },

  "preservation": {                          // страница Back — СОХРАННОСТЬ (переиспользуемый блок)
    "dimensions_mm": { "length", "width", "height" },
    "binding": {
      "state":       { "Не повреждён": false, "Повреждён": true, "Ранее реставр.": false, "Ранее ремонт.": false, "Утрачен": false },
      "composition": { "Комбинир.": false, "Цельный": true },
      "cover_materials": { "Кожа": false, "Пергамент": false, "Ткань": false, "Бумага": false, "Другое": false, "Отсутствует": false },
      "base_materials":  { "Дерево": false, "Картон": false, "Бумага": false, "Без основы": false },
      "decor": {
        "stamping":  { "Слепое": false, "Золотое": false, "Нет тиснения": false },
        "ornaments": { "Накладки": false, "Застёжки": false, "Металл": false, "Другое": false, "Нет украшен.": false },
        "edge":      { "Золото": false, "Тиснение": false, "Другое": false, "Без обреза": false }
      },
      "damage": {
        "physical_mechanical": { "Оторван": false, "Утраты": true, "Разрывы": false, "Деформация": true, "Общ.загрязн.": false,
                                 "Пятна": false, "Затёки": true, "Изменение окраски": true, "Разрушение": false, "Ломкость": false },
        "biological_micro":    { "Биологическая пигментация": true, "Колонии микромицетов": true, "Биологическое разрушение": true,
                                 "Жизнеспособная микрофлора": false, "Нет микробиологических повреждений": false },
        "biological_ento":     { "Личиночные ходы": false, "Экзувии": false, "Личинки": false, "Имаго": false, "Нет энтомологических повреждений": false },
        "degree": { "physical_mechanical": "", "micro": "", "ento": "" }   // Низкая | Средняя | Высокая
      }
    },
    "block": {
      "state":     { "Не повреждён": false, "Повреждён": true, "Ранее реставрирован": false },
      "notebooks": { "Выпадают": false, "Отсутствуют": false, "Нарушено шитьё": false },
      "sheets":    { "Выпадают": false, "Отсутствуют": false },
      "ph_value",
      "damage": { "physical_mechanical": { /* тот же список */ }, "biological_micro": { }, "biological_ento": { },
                  "degree": { "physical_mechanical": "Средняя", "micro": "", "ento": "" } }
    },
    "monitoring": {
      "biotest":   { "date", "performer" },
      "expertise": { "date", "expert", "performer", "result", "signature": true }
    },
    "comment"                                // рукописный КОММЕНТАРИЙ, дословно
  }
}

Формализация. Схема выше — контракт ответа; сервис принуждает модель к ней через structured output (response_format: { type: json_schema, strict: true }) — поддержано llama.cpp и vLLM (проверено на Qwen). Это гарантирует СТРУКТУРУ (состав ключей, типы, наличие bbox), но НЕ точность значений и координат: распознавание сверяет и правит оператор (уверенность + подсветка источника).

6. Канонический промт (v2)

Системный промт стабилен и кэшируется (prompt caching); при изменении промта версия (prompt_version) меняется и кэш инвалидируется.

Ты — оператор-архивист. По снимкам ИНФОРМАЦИОННОЙ КАРТЫ документального памятника
(фонд ОФО БАН) извлеки заполнение карты для оцифровки и последующей выгрузки в АБИС.

Карта — это фиксированный БЛАНК: печатные подписи полей и заголовки разделов заданы
типографски, а данные внесены оператором — рукописно, впечаткой или ОТМЕТКОЙ в клетке
(галочка, крест, штрих). Твоя задача — прочитать ЗАПОЛНЕНИЕ, а не подписи бланка.

Карта книги — два изображения (страницы формы):
  • Front — «ОПИСАНИЕ ДОКУМЕНТАЛЬНОГО ПАМЯТНИКА»: шапка (шифр, инв. номер, место
    хранения, дата), библиоописание, провенанс и матрица «Отметка о наличии элемента
    данных» (консервация).
  • Back — «СОХРАННОСТЬ»: размеры, состояние и материалы переплёта/блока,
    повреждения, мониторинг, комментарий.
Главного источника НЕТ — у каждой стороны свой набор полей; заполняй поля той стороны,
к которой относится изображение. Сторон меньше — заполни что есть, остальное пропусти.

Правила:
1. Заполняй ТОЛЬКО то, что реально внесено в карту (текст или отметка). Ничего не выводи
   из внешних знаний и не додумывай по смыслу бланка: пустая клетка — значения нет.
2. Значения — как написано в карте, на языке и в орфографии оригинала, БУКВА В БУКВУ, включая
   дореформенную орфографию и «ять» («Дневникъ войны», «русскій»); в современную орфографию не
   переводи. Даты — как в карте (формат не нормализуй). Печатные подписи полей в значения НЕ включай.
2а. Бланк существует в нескольких печатных вариантах: подписи полей могут отличаться словами
   («Кол-во стр.» ↔ «Количество страниц», «Отд. листы ил.» ↔ «Отдельные листы иллюстраций»).
   Сопоставляй поле по СМЫСЛУ подписи, а не по точному тексту. Печатный заголовок-баннер
   карты («Издания из фондов БАН», «Фазовая консервация книги XVII–XX вв.») клади в form_title.
2б. Раскладка ответа: идентификацию — в `identity` (shifr/inv_number/storage_location/fill_date);
   остальные вид-специфичные ТЕКСТОВЫЕ поля — в родовой массив `fields` объектами {name, value, …},
   где name — краткое имя поля по смыслу подписи (author, title, place, …). Сам ВИД карты определи
   по макету формы и составу полей и верни в `card_kind` (один из FundDocumentKind).
3. РУКОПИСНЫЙ текст расшифровывай посимвольно. Неразборчивый фрагмент, восстановленный
   по смыслу, помечай reconstructed:true и снижай уверенность; полностью нечитаемое —
   не выдумывай, поле пропусти. Рукописное значение помечай handwritten:true.
4. ОТМЕТКИ (галочки/кресты/штрихи) читай как булев факт «отмечено / не отмечено» и
   возвращай ПОЛНОЙ матрицей — КАЖДУЮ клетку группы, а не только помеченные (пустая
   клетка значима: оператор рассмотрел и не отметил).
   • Матрица «Задано / Выполнено» (наличие элемента данных): каждая строка — объект
     {item, set, done, bbox}: item — подпись строки ДОСЛОВНО, set — есть отметка в «Задано»,
     done — есть отметка в «Выполнено», bbox — область клеток строки (шкала 0..1000).
   • Группа выбора (Состояние, Состав, Материалы, Декор, Повреждения, Степень, Условия
     хранения…) — объект {подпись клетки: true|false} по ВСЕМ клеткам группы; подписи
     бери ДОСЛОВНО. Степень повреждения (Низкая/Средняя/Высокая) — одно значение строкой.
5. Не путай разделы: отметки книги, переплёта и блока относи к своим блокам; степень
   повреждения указывай той группы (физ-мех / микробиол. / энтомол.), под которой она стоит.
6. КОММЕНТАРИИ и КОММЕНТАРИЙ переписывай рукопись дословно, целиком.
7. Для каждого заполненного текстового поля укажи уверенность 0..1: 1.0 — впечатано/написано
   явно и читается уверенно; 0.5–0.8 — плохо видно, спорная отметка, неразборчивый почерк;
   ниже 0.5 — догадка (лучше не заполнять). Для группы чекбоксов уверенность — на группу.
8. Для каждого заполненного поля и каждой ОТМЕТКИ укажи ИСТОЧНИК: изображение и область
   bbox [x0, y0, x1, y1] в ЦЕЛЫХ координатах 0..1000 (x — по ширине, y — по высоте), охватывающую
   значение или клетку. Для матрицы «Задано/Выполнено» bbox — на КАЖДУЮ строку (её клетки), для
   группы выбора — на группу. Не уверен в границах — дай грубую область клетки, но источник не пропускай.
9. Если запрошен OCR: отдельно верни весь текст каждого изображения (печатный + рукописный)
   дословно, в порядке чтения; отметки не транскрибируй.
10. Незаполненные ТЕКСТОВЫЕ поля в ответ не включай (без null, пустых строк, прочерков).
    Чекбокс-матрицы возвращай ЦЕЛИКОМ, включая неотмеченные клетки (false).

Отвечай строго JSON по заданной схеме, без пояснений.

7. Критерии приёмки

  1. Идентификация (шифр, инв. номер, место хранения, дата) извлекается с роли Front; инв. номер сопоставим с номером папки/документа.
  2. Незаполненные текстовые поля в ответе отсутствуют; чекбокс-матрицы присутствуют целиком (true/false).
  3. Матрица «Задано/Выполнено» отражает обе колонки раздельно по каждой строке.
  4. Рукописные значения помечены handwritten; восстановленные по смыслу — reconstructed со сниженной уверенностью.
  5. У каждого заполненного поля и каждой группы чекбоксов есть источник с bbox на переданном изображении.
  6. Ответ — валидный JSON по схеме; в ответе указана версия промта.

8. Открытые вопросы

Вопрос
OQ-CE-1 Состав полей и имена ключей схемы — черновые, требуют сверки на наборе реальных карт
OQ-CE-2 Виды документов перечислены в домене (FundDocumentKind); открыт конкретный состав полей и число страниц формы для каждого — прорабатывается по мере появления их бланков
OQ-CE-3 Нужен ли встроенный OCR-этап или связка с отдельным распознаванием (см. FR_002)
OQ-CE-4 Пороговая уверенность для подсветки на проверке полей — общая с OQ-PP-1 эпика «Обработка пакета»
OQ-CE-5 Полная матрица чекбоксов раздувает ответ — оценить, не перейти ли к «только отмеченные» после прогонов
OQ-CE-6 Бланк EditionBook встречается в ≥2 печатных вариантах (разные подписи полей, поле «Конволют» не во всех) — держать маппинг по смыслу; собрать перечень вариантов
OQ-CE-7 Инв. номер в шапке может расходиться с номером папки/документа (нечёткий почерк) — извлекать как напечатано, сверку вести ниже по потоку (эпик «Обработка пакета»)
OQ-CE-8 Что именно кодирует card_kind: вид экземпляра фонда (FundItemKind) или распознанную форму бланка (DocumentForm) — согласовать с доменной моделью (ADR-006/007). Сейчас — FundItemKind (7 видов)

Связанные артефакты

Документы

Перечисления

Термины