Files
akyldash/backend/README.md

9.3 KiB
Raw Blame History

Backend Акылдаш

Версия: 0.4.1

Первая backend-область проекта — загрузка правовых документов из официального Open Data API ЦБД Минюста Кыргызской Республики. Код расположен в ingestion/minjust_cbd.py: его можно запускать как CLI сейчас и импортировать из будущего планировщика backend без запуска отдельного процесса.

Пробная загрузка

Из корня репозитория:

python3 backend/ingestion/minjust_cbd.py --limit 10

В интерактивном терминале отображаются процент, количество документов, ошибки, скорость и примерное оставшееся время.

Полная загрузка выполняется без --limit. По умолчанию архив сохраняется в data/minjust-cbd, который исключён из Git. Повторный запуск пропускает уже загруженные документы; --refresh принудительно проверяет их заново. Если временный идентификатор списка API истечёт или запрос страницы исчерпает повторы во время многодневной загрузки, скрипт пересоздаст список на текущей странице и продолжит автоматически.

В версии 0.1.0 обновление существующих документов выполняется полной проверкой через --refresh. Инкрементальную проверку по lastmod из sitemap следует добавить вместе с backend-планировщиком, когда будет определена частота запуска.

Защита API

Запросы выполняются последовательно, по умолчанию не чаще одного в секунду. Timeout одного ответа — 60 секунд, число попыток — 5, задержка между повторами растёт экспоненциально. При HTTP 429 учитывается заголовок Retry-After. Лимит действует на один процесс, поэтому одновременно следует запускать только один экземпляр загрузчика.

Более осторожный режим:

python3 backend/ingestion/minjust_cbd.py --requests-per-second 0.5

Вызов из будущего backend

from ingestion.minjust_cbd import sync_archive

result = sync_archive(output_path)

Планировщик, очередь задач и PostgreSQL пока не добавлены: модуль не зависит от выбора будущего backend-фреймворка.

Нормализация архива

Нормализатор читает исходный архив без изменений и создаёт отдельный набор данных для будущих поиска, API и RAG:

python3 backend/normalization/minjust_cbd.py --limit 10
python3 backend/normalization/minjust_cbd.py

По умолчанию источник читается из data/minjust-cbd, а результат записывается в data/minjust-normalized. Пути можно изменить параметрами --input и --output; --refresh принудительно обрабатывает неизменившиеся документы, --log-level задаёт уровень журнала. Каталоги --input и --output не должны совпадать, содержать друг друга или пересекаться через разрешённые абсолютные пути.

data/minjust-normalized/
  manifest.sqlite3
  documents/<code>/document.json
  documents/<code>/editions/<edition>/edition.json
  documents/<code>/editions/<edition>/<lang>/content.html
  documents/<code>/editions/<edition>/<lang>/content.txt
  documents/<code>/editions/<edition>/<lang>/fragments.json

content.html содержит только разрешённую безопасную разметку, content.txt — текст для поиска, а fragments.json — адресуемые блоки с детерминированными ID и SHA-256. Манифест пропускает документы с неизменившимися исходниками и повторяет документы, обработка которых завершилась ошибкой.

Первая версия не выполняет OCR, перевод, юридические выводы о редакциях, сопоставление фрагментов, загрузку в PostgreSQL/OpenSearch и построение RAG. Внешние и встроенные data:-изображения из HTML удаляются; сведения и пути к локальным изображениям исходного архива сохраняются в edition.json.

Проверка

PYTHONPATH=backend python3 -m unittest backend/test_minjust_cbd.py -v
PYTHONPATH=backend python3 -m unittest backend/test_minjust_normalization.py -v
PYTHONPATH=backend python3 -m unittest backend/test_minjust_opensearch.py -v

Подготовка индекса OpenSearch

Mapping поискового индекса находится в search/minjust-fragments-index.json. Для кыргызского текста он использует icu_analyzer, поэтому в OpenSearch должен быть установлен плагин analysis-icu.

Потоковый экспорт в формат Bulk API без внешних Python-зависимостей:

python3 backend/search/minjust_opensearch.py

По умолчанию создаётся data/opensearch/minjust-fragments.ndjson. Экспорт атомарный и детерминированный; для проверки можно передать --limit 1. Для прямой загрузки без большого промежуточного файла используется --url:

python3 backend/search/minjust_opensearch.py \
  --url http://127.0.0.1:9200 \
  --index akyldash-fragments-dev-v1 \
  --limit 1

Запросы Bulk API ограничены 25 МБ и не разрывают пару action/source. Для полного прохода убрать --limit и выбрать новое имя версионного индекса. После проверки production-индекса следует переключать alias, чтобы удалённые фрагменты не оставались в поиске.

После каждого принятого Bulk-пакета загрузчик атомарно сохраняет checkpoint и печатает код безопасного возобновления. При временных HTTP 429/5xx, timeout и обрыве соединения запрос повторяется автоматически. Прерванную загрузку можно продолжить без ручного выбора документа:

python3 backend/search/minjust_opensearch.py \
  --url http://127.0.0.1:9200 \
  --index akyldash-fragments-v1 \
  --resume

По умолчанию checkpoint хранится в data/opensearch/<index>.checkpoint.json; путь можно изменить через --checkpoint. Checkpoint привязан к URL, cluster UUID, index UUID, --limit и SHA-256 нормализованного manifest. Resume отклоняется при любом несовпадении: для обновлённого корпуса или пересозданного индекса нужно создать новый версионный индекс, проверить его и переключить alias. Это не оставляет удалённые trailing-фрагменты старых документов.

Локальный OpenSearch

Стенд использует один узел OpenSearch без Dashboards, устанавливает analysis-icu, выделяет JVM 8 ГБ и доступен только на 127.0.0.1:9200. Индекс хранится в data/opensearch-node на диске проекта.

sudo sysctl -w vm.max_map_count=262144
docker compose -f deploy/local-opensearch/compose.yaml up -d --build
curl http://127.0.0.1:9200/_cluster/health

Security plugin отключён только для локальной разработки; этот compose нельзя публиковать в сеть или использовать в production. Mapping локального стенда также задаёт одну shard и ноль replicas; для production число shard следует рассчитать по размеру корпуса и настроить не менее одной replica.


Акылдаш · Backend v0.4.1 · Frontend — не создан