11 KiB
Задание агенту: нормализация документов ЦБД Минюста КР
Цель
Реализовать первую рабочую версию воспроизводимого нормализатора локального
архива data/minjust-cbd. Нормализованные данные должны быть пригодны для
последующей загрузки в OpenSearch, backend API и RAG, но подключение этих
сервисов в текущую задачу не входит.
Текущее состояние
- загрузчик находится в
backend/ingestion/minjust_cbd.py; - сырой архив хранится в
data/minjust-cbdи исключён из Git; - в манифесте 209 811 успешно загруженных документов;
- 13 кодов остаются в таблице
errorsи отсутствуют в таблицеdocuments; - документ содержит
metadata.jsonи каталогeditions; - редакция содержит
metadata.json,ru.htmlи/илиky.html, иногда изображения; - HTML создан Microsoft Word, может содержать некорректный
<meta charset=unicode>, служебные стили и неполную разметку; - файлы архива записаны загрузчиком в UTF-8;
- часть документов одноязычная, а часть не содержит HTML-текста.
Обязательные ограничения
- Не изменять и не перезаписывать
data/minjust-cbd. - Не запускать полный проход по архиву во время автоматических тестов.
- Не подключать PostgreSQL, OpenSearch, OCR, embeddings, машинный перевод и сетевые API.
- Сначала использовать стандартную библиотеку. Новая зависимость допустима только если на реальных образцах доказано, что стандартный HTML-парсер не обеспечивает корректность или безопасность.
- Все записи выполнять атомарно.
- Ошибка одного документа не должна останавливать длительный прогон.
- Повторный запуск должен пропускать неизменившиеся документы.
- Не изменять пользовательские файлы
logs/, исходный DOCX и несвязанные незакоммиченные изменения.
Размещение
Использовать существующую backend-структуру:
backend/
normalization/
minjust_cbd.py
Результат по умолчанию:
data/minjust-normalized/
manifest.sqlite3
documents/<document_code>/document.json
documents/<document_code>/editions/<edition_code>/edition.json
documents/<document_code>/editions/<edition_code>/<lang>/content.html
documents/<document_code>/editions/<edition_code>/<lang>/content.txt
documents/<document_code>/editions/<edition_code>/<lang>/fragments.json
Каталог уже покрывается правилом игнорирования data/.
Канонические данные
document.json
Сохранить как минимум:
schema_version;source_code;- двуязычные
class,type,title,name,status; - номера и даты без юридически неподтверждённых выводов;
- флаги публичности;
- органы, публикации, ключевые слова и классификаторы с сохранением дерева;
- пути листьев иерархий для будущих фильтров;
- ссылки из
Referencesбез выдумывания связей; available_languages;- список редакций;
- путь к источнику и SHA-256 исходных файлов;
- версию нормализатора и время обработки.
Пустые строки привести к null, но не переводить значения и не заменять
официальные формулировки собственными.
edition.json
Сохранить:
- исходный код редакции;
- двуязычное название;
- исходный тип;
- доступные языки;
- изображения без бинарных данных;
- контрольные суммы источников;
- признаки качества.
Не считать дату из Name датой вступления редакции в силу и не назначать
актуальную редакцию без подтверждённого правила источника.
Языковой вариант
Для каждого имеющегося ru.html или ky.html сформировать:
content.html— безопасный HTML для frontend;content.txt— извлечённый текст с сохранением смысловых переносов;fragments.json— упорядоченные адресуемые блоки.
Сырой HTML всегда читать как UTF-8, не доверяя его meta charset.
Очистка HTML
- удалить
script,style,meta,link, комментарии и служебные элементы; - удалить обработчики событий, inline-стили и опасные URL;
- разрешить минимальный набор структурных тегов: заголовки, абзацы,
pre, списки, таблицы, безопасные ссылки, изображения и базовое текстовое выделение; - нормализовать Unicode в NFC;
- преобразовать неразрывные пробелы и избыточные пробелы только в
content.txt, не искажая отображаемый юридический текст; - не загружать внешние ресурсы;
- относительные изображения связывать только с файлами внутри редакции;
- неизвестную или сломанную разметку сохранять как текст, а не терять молча.
Фрагменты
Минимальная версия должна создавать фрагмент для каждого содержательного блочного элемента. Распознавание статей и пунктов допускается только простыми проверяемыми правилами RU/KY; обычный абзац является fallback.
Каждый фрагмент содержит:
- стабильный
id; document_code,edition_code,language;- порядковую позицию;
- тип блока;
- чистый текст;
- SHA-256 текста.
Идентификатор должен быть детерминированным и включать документ, редакцию, язык и позицию. Не добавлять сложное сопоставление фрагментов между редакциями — это отдельная будущая задача.
Манифест и возобновление
SQLite-манифест должен хранить:
- код документа;
- SHA-256 набора исходных файлов;
- версию схемы и нормализатора;
- время успешной обработки;
- состояние и текст последней ошибки.
Если checksum и версия нормализатора не изменились, документ пропускается.
После успешной повторной обработки ошибка удаляется. Добавить --limit и
понятный терминальный прогресс, пригодный для долгого запуска.
CLI и импорт из будущего backend
CLI запускается из корня репозитория:
python3 backend/normalization/minjust_cbd.py
Предусмотреть параметры:
--input;--output;--limit;--refresh;--log-level.
Основную функцию можно импортировать без запуска CLI. Не создавать планировщик, очередь задач или framework-интеграцию.
Проверки
Добавить один компактный тестовый модуль, который проверяет:
- русскую редакцию;
- кыргызскую редакцию;
- двуязычную редакцию;
- Word HTML с опасным
script, inline-стилем иjavascript:URL; - документ без HTML;
- повторный запуск и пропуск неизменившегося документа;
- продолжение после ошибки одного документа;
- детерминированные fragment ID и checksums.
Провести пилотный read-only запуск на небольшой реальной выборке через
--limit, не нормализовать весь архив в рамках разработки.
Документация и версия
- описать запуск, структуру результата и ограничения в
backend/README.md; - отметить реализацию в
docs/operations/project-status.md; - это новая обратно совместимая backend-функция: увеличить minor-версию backend по SemVer;
- обновить все отображаемые backend-версии и footer, не меняя версию Telegram-бота;
- frontend по-прежнему помечать как не созданный.
Критерии приёмки
- сырой архив не изменён;
- тесты проходят;
git diff --checkпроходит;- пилотный запуск завершается без остановки на отдельных ошибках;
- повторный пилотный запуск пропускает неизменившиеся документы;
- unsafe HTML не попадает в
content.html; - каждый фрагмент прослеживается до документа, редакции, языка и исходного файла;
- отсутствуют молча потерянные HTML или ошибки;
- реализация не содержит PostgreSQL/OpenSearch/RAG-кода «на будущее».
Акылдаш · Telegram-бот v0.2.2 · Backend v0.7.1 · Frontend — не создан