AAYMA
RU
Войти

OrgScope (Optimus)

Сервис сравнивает комплекты документов «до» и «после» реорганизации (Word, PDF, Excel).

Доведённый продукт
Команда «Optimus» 41💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Optimus
Кейс HackAlem.ai: Спецтрек — Казахтелеком
Стадия: Доведённый продукт

Задача кейса: Агент, сравнивающий документы оргструктуры до и после реорганизации

Суть

Сервис сравнивает комплекты документов «до» и «после» реорганизации (Word, PDF, Excel). Он определяет created, kept, removed и reorganized подразделения и находит потерю, перенос и дублирование функций и конфликт интересов. По каждому выводу даётся проверенная кодом цитата, функции сверяются с законами РК, заключение экспортируется в DOCX и PDF.

Как устроено

Extractor на Python/FastAPI (python-docx, pdfplumber, openpyxl) режет документы на фрагменты с точным адресом и восстанавливает автонумерацию Word, после чего фрагменты собираются в пункты. Пятиэтапный конвейер на Node.js: код находит подразделения по паттерну «Название (АББР)», LLM размечает функции. Кандидаты для сопоставления подбираются по точному тексту, лексике и эмбеддингам text-embedding-3-small, а модель-судья решает только по этим кандидатам. Правила кода выводят POTENTIAL_LOSS, MOVED, OVERLAP, POTENTIAL_DUPLICATION и POTENTIAL_CONFLICT. Каждая цитата проверяется на вхождение в текст источника, неподтверждённые выводы отбрасываются, результат хранится в MongoDB.

Ключевые решения

  • извлечение пунктов с адресом источника
  • эмбеддинг-кандидаты + LLM-судья
  • правила отклонений (loss/moved/overlap/duplication/conflict)
  • проверка цитат по тексту
  • сверка с законами РК (adilet.zan.kz)
  • защита от нерелевантных документов

Метрики

Контрольная пара (2 PDF по 25 стр., ~450 пунктов): анализ 3–6 мин, ~60–80 вызовов модели; smoke 36 проверок с моделью, 19 без неё

Особенности

Роли строго разделены: extractor режет текст, код сопоставляет и считает, модель только размечает и судит кандидатов, все числа считает код. Цитаты проверяются по тексту источника. Есть дополнительный модуль сверки с тремя законами РК со ссылками на adilet, а документ неподходящего типа останавливает анализ с ошибкой irrelevant_document. Развёрнуто на Azure с демо-логином.

Стек

Node.js 22 · Express 5 · zod · MongoDB 8 · Python 3.12 · FastAPI · pdfplumber · python-docx · openpyxl · Vue 3 · Vite · Caddy · Docker Compose · Azure VM

Модели

gpt-5.6-terra · gpt-5.6-luna · text-embedding-3-small


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-0592591a-optimus.

README

README.md

Optimus — HackAlem AI

ИИ-агент «Анализ организационной структуры и функционала» (задача 1, владелец — Казахтелеком). В интерфейсе решение называется OrgScope. Полное ТЗ, критерии и архитектурная спецификация — в docs/TASK.md.

Быстрый доступ для жюри

Развёрнутая версияhttps://hackalem-ai-wg.germanywestcentral.cloudapp.azure.com
Логин[email protected]
Парольdemo12345

На развёрнутой версии ключ модели уже настроен: анализ запускается без каких-либо ключей и аккаунтов команды. Контрольный комплект документов для загрузки лежит в репозитории: services/backend/demo/before/redakciya_8.pdf («до») и services/backend/demo/after/redakciya_9.pdf («после»). Пошаговый сценарий — в разделе «Как проверить решение».

Локальный запуск (нужны только Git и Docker):

git clone https://github.com/BAITC-Hacks/hack-0592591a-optimus.git
cd hack-0592591a-optimus
cp .env.example .env
docker compose up --build -d --wait

Интерфейс: http://localhost:3000, тот же логин и пароль. Для запуска анализа локально в .env нужны OPENAI_API_KEY и LLM_MODEL (см. «Доступ для жюри»); без них работают интерфейс, вход, извлечение текста и 19 проверок smoke-скрипта.

1. Краткое описание

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

Optimus принимает комплекты документов «до» и «после» реорганизации (Word, PDF, Excel), определяет созданные, сохранённые, реорганизованные и упразднённые подразделения, сопоставляет их функции, находит возможную потерю функций, дублирование, пересечения зон ответственности и признаки конфликта интересов и формирует аналитическое заключение с рекомендациями. Каждый вывод ссылается на документ и пункт и содержит дословную цитату, которую код проверил по тексту источника. Дополнительно функции новой структуры сверяются с законами РК.

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

2. Что реализовано

  • Загрузка комплектов «до» и «после»: PDF с текстовым слоем, Word (.docx), Excel (.xlsx, .xlsm, .xls); до 10 файлов на сторону, до 20 МБ каждый; формат проверяется по содержимому. Необязательное поле regulations для законов и стандартов, с которыми нужно сверить функции.
  • Извлечение текста с точным адресом источника (сервис extractor): для Word — абзац с восстановленной автонумерацией, для PDF — страница и строки, для Excel — лист, строка и ячейки. Фрагменты собираются в пункты вида 5.3.2 и подпункты 5.3.2.а.
  • Подразделения (M1): код находит пары «Название (АББР)», модель уточняет вид и подчинённость, код сверяет сторону «до» и «после» по аббревиатурам: created / kept / removed; преемники упразднённых единиц оцениваются моделью по структуре и обязанностям и дают статус reorganized.
  • Функции: модель размечает пункты каждого раздела (исполнители, суть, категория из закрытого списка); цитата функции — текст пункта, модель её не пишет.
  • Сопоставление и отклонения (M2, M3): точное совпадение текста → лексические и семантические (эмбеддинги) кандидаты → модель-судья. Код выводит POTENTIAL_LOSS (возможная потеря, в том числе частичная), MOVED (перераспределена), OVERLAP (общая и частная норма), POTENTIAL_DUPLICATION (дублирование у разных подразделений), POTENTIAL_CONFLICT (исполнение аудита и контроль его качества у одного владельца, подтверждается моделью по двум пунктам), NOTE (новая норма о конфликте интересов).
  • Проверка источников (M4): каждая цитата проверяется на вхождение в текст своего пункта с учётом документа и стороны; вывод без подтверждённой цитаты отбрасывается.
  • Заключение и рекомендации (M5, O3): код собирает русское заключение только из проверенных выводов и цитат: итоги, изменения подразделений, потери, дублирование, конфликты, рекомендации по проверке с привязкой к выводам, список исходных документов, дисклеймер. Экспорт в DOCX и PDF.
  • Сверка с законодательством (O1): функции «после» сопоставляются с нормами трёх законов РК из репозитория и с загруженными regulations; модель определяет связь basis / contradicts / none, код цитирует статью и проверяет обе цитаты. Каждая норма показана со статьёй, датой редакции и кнопкой «Открыть на adilet.zan.kz».
  • Защита от неподходящих документов: инструкция, договор или статья вместо положения останавливают анализ с понятной ошибкой irrelevant_document и именем файла.
  • Интерфейс (Vue 3): вход, две зоны загрузки, ход анализа по пяти этапам, экраны Обзор · Структура · Потеря функций · Дублирование и конфликты · Заключение · Рекомендации («Обзор» показывает только критичные выводы, «Структура» — схему подразделений «до → после», «Рекомендации» — карточки с кнопками принять / отклонить; принятые рекомендации попадают в заключение и экспорт), полная таблица «Все сопоставления», просмотр текста любого пункта, модуль «Соответствие законодательству», история запусков пользователя, дисклеймер на экране результатов.
  • Аутентификация: вход по email и паролю, сессия в httpOnly-cookie, демо-аккаунт создаётся при старте; регистрация с экрана входа убрана и доступна только через API (POST /api/auth/signup). API анализа намеренно открыт, чтобы жюри и smoke-скрипт запускали сценарий без аккаунта.
  • Проверки: scripts/smoke.sh (36 HTTP-проверок с моделью, 19 без неё; контрольный набор проверяет scripts/verify-control.py без ключей), scripts/clean-test.sh (чистый клон), scripts/formats-test.sh (Word/PDF/Excel через весь конвейер без ключа), тесты backend и extractor.

3. Как работает решение

  1. Пользователь входит, перетаскивает документы в зоны «До реорганизации» и «После реорганизации» и нажимает «Анализировать».
  2. Backend проверяет тип и размер файлов, создаёт запись анализа (queued), отвечает 202 {"analysis_id"} и запускает конвейер в фоне; страница опрашивает GET /api/analyses/:id каждые 2 с и показывает этап.
  3. Разбор: каждый файл уходит в extractor, фрагменты группируются в пункты; модель проверяет, что документ описывает подразделения и их функции.
  4. Структура: подразделения каждой стороны и их сравнение (created / kept / removed / reorganized).
  5. Функции: модель размечает функции по разделам; цитата — текст пункта.
  6. Сопоставление: код сопоставляет функции «до» и «после», модель судит только кандидатов; код применяет правила отклонений, проверяет каждую цитату и сверяет функции «после» с законами.
  7. Заключение: код собирает заключение и рекомендации из проверенных записей. Результат сохраняется в MongoDB и открывается на экране «Обзор»: вывод, распределение функций «до», критичные выводы «Проверить в первую очередь» с цитатами «до» и «после»; схема подразделений — на экране «Структура», карточки рекомендаций — на экране «Рекомендации».

Принцип: extractor режет, код сопоставляет и считает, модель только размечает и оценивает кандидатов. Все числа на экране считает код. На контрольной паре (два PDF по 25 страниц, около 450 пунктов и 250–300 функций на сторону) анализ занимает примерно 3–6 минут и делает около 60–80 обращений к модели.

4. Технологии

КомпонентТехнологииЗачем
ОркестрацияDocker Compose, один docker-compose.ymlОдинаковый запуск у команды, на VM и у жюри
ВходCaddy (caddy:2-alpine)Единственный опубликованный порт: /api/* → backend, остальное → frontend; HTTPS на VM
BackendNode.js 22 (node:22-alpine), Express 5, zod 4, multer 2, jsonwebtoken 9, драйвер mongodb 6, SDK openai 7API, конвейер анализа, проверка всех входов и ответов модели схемами
МодельOpenAI-совместимый API: chat.completions в режиме JSON и embeddings; провайдер, модель и адрес задаются в .envВ проверочных запусках использовались gpt-5.6-terra и gpt-5.6-luna, эмбеддинги — text-embedding-3-small (OpenAI)
ExtractorPython 3.12 (python:3.12-slim), FastAPI, uvicorn, uv; python-docx, pdfplumber, openpyxl, xlrdРазбор Word, PDF и Excel в фрагменты с точным адресом
FrontendVue 3, Vite 6, marked 18, docx 9; шрифты Manrope, Golos Text, Lora, Nunito Sans, PT Serif (@fontsource)Интерфейс; экспорт заключения; без UI-библиотек и внешних CDN
БазаMongoDB 8 (mongo:8.0)Пользователи, анализы, нормы законодательства
ПроверкиBash, curlimages/curl:8.10.1, python:3.12-slimВсе проверочные команды выполняются в контейнерах

5. Архитектура проекта

flowchart LR
    user[Браузер / smoke-скрипт] -->|HTTP :3000| caddy[Caddy]
    caddy -->|/api/*| backend[Backend: Node.js + Express<br/>конвейер из 5 этапов]
    caddy -->|/*| frontend[Frontend: Vue 3, статика]
    backend -.->|внутренняя сеть| extractor[Extractor: Python + FastAPI]
    backend -->|users, analyses, regulatory_norms| mongo[(MongoDB)]
    backend -->|OPENAI_API_KEY, LLM_MODEL| llm[OpenAI-совместимый API]
  • Caddy (Caddyfile, services/caddy) — единственный сервис с портами на хосте (3000 HTTP, 3443 HTTPS).
  • Backend (services/backend) — маршруты /api/auth/*, /api/documents/extract, /api/analyses*, /api/health; конвейер src/pipeline: clauses.js → structure.js → extract.js → compare.js (+ regulatory.js) → report.js; единственная точка обращения к модели — src/llm.js; промпты — текстовые файлы в src/prompts. При старте создаёт индексы, демо-аккаунт и загружает нормы из data/regulatory.
  • Extractor (services/extractor) — внутренний сервис, POST /extract; наружу не опубликован, вызывается только backend.
  • Frontend (services/frontend) — статическая сборка Vite, раздаётся Caddy; дизайн-система в DESIGN_SYSTEM.md.
  • MongoDB — порт не опубликован, данные в томе mongo-data.

У каждого сервиса есть healthcheck; backend стартует после базы и extractor, Caddy — после backend и frontend.

6. Установка и запуск

Нужны Git, Docker с плагином Compose (проверено на Docker 27 / Compose 2.31) и Bash для скриптов. На хост больше ничего не ставится: сборка, тесты и проверочные запросы выполняются в контейнерах. Нужен доступ в интернет для образов, npm/PyPI при сборке и обращений к модели.

git clone https://github.com/BAITC-Hacks/hack-0592591a-optimus.git
cd hack-0592591a-optimus
cp .env.example .env
# для анализа впишите в .env: OPENAI_API_KEY=… и LLM_MODEL=gpt-5.6-terra
docker compose up --build -d --wait

Откройте http://localhost:3000. Порты 3000 и 3443 должны быть свободны (меняются в .env).

Переменные окружения (.env.example, приложение стартует с ним как есть):

ПеременнаяПо умолчаниюНазначение
SITE_ADDRESS:80Адрес сайта для Caddy. Публичное доменное имя включает автоматический HTTPS
WEB_PORT, HTTPS_PORT3000, 3443Порты на хосте
MONGO_URLmongodb://mongo:27017/hackalemПодключение backend к MongoDB внутри сети Compose
MAX_UPLOAD_MB20Максимальный размер одного документа
AUTH_SECRETdev-only-secret-change-meСекрет подписи cookie сессии; значение по умолчанию только для локального запуска
DEMO_USER_EMAIL, DEMO_USER_PASSWORD, DEMO_USER_NAME[email protected], demo12345, ДемоДемо-аккаунт, создаётся при старте; пустые значения Compose заменяет этими значениями по умолчанию
LLM_PROVIDERopenaiopenai (ключ OPENAI_API_KEY) или nvidia (ключ NVIDIA_API_KEY)
LLM_MODELпустоОбязательна для анализа. Чат-модель с режимом JSON. Пусто: /api/health отвечает "llm":"missing", запуск анализа — 503 llm_unavailable
LLM_BASE_URLпустоАдрес OpenAI-совместимого API; пусто — адрес провайдера по умолчанию
OPENAI_API_KEY / NVIDIA_API_KEYпустоОбязателен для анализа. В репозиторий не входит
EMBEDDING_MODELпустоМодель эмбеддингов для семантических кандидатов (команда использует text-embedding-3-small). Пусто — кандидаты подбираются лексически, анализ выполняется полностью

Полезные команды:

docker compose ps
docker compose logs --tail=100 backend
docker compose down        # остановить, данные сохраняются; -v удаляет данные

7. Как проверить решение

7.1. Сценарий в интерфейсе (контрольный комплект)

  1. Откройте развёрнутую версию или http://localhost:3000 и войдите: [email protected] / demo12345.
  2. Перетащите services/backend/demo/before/redakciya_8.pdf в зону «До реорганизации», services/backend/demo/after/redakciya_9.pdf — в зону «После реорганизации», нажмите «Анализировать». Ход анализа показан по этапам, примерно 3–6 минут.
  3. Ожидаемый результат (эти находки воспроизводились во всех контрольных запусках 23.09.2026; количество функций и второстепенных выводов от запуска к запуску немного меняется, потому что разметку делает модель):
    • Обзор → Изменения структуры: созданы ДИТААД и ДОА (после п. 3.4.а и 3.4.б); сохранены БВА, Главный аудитор, ДНМ, ДККМ; реорганизовано Направление внутреннего аудита (до п. 3.5.а) с преемниками ДИТААД и ДОА.
    • Потеря функций: право ДККМ формировать группы контроля качества — до п. 5.6.2, цитата «формировать группы контроля качества с привлечением работников БВА…»; предложения ДККМ по внешней оценке — до п. 5.6.3; доведение ДНМ результатов консультационных услуг — до п. 5.7.2 (с эмбеддингами модель находит частичный эквивалент в после п. 2.4.7). Могут быть отмечены ещё несколько пунктов ред. 8, которым модель не нашла эквивалента: они требуют проверки сотрудником.
    • Дублирование и конфликты: дублирование — запрос информации у Руководителей Общества у ДНМ и ДККМ (после п. 5.4.3 и 5.5.8); конфликт независимости — ДККМ одновременно проводит проверки (после п. 5.3.x) и контролирует качество аудита (после п. 5.5.2); пересечения общих норм для директоров департаментов (после п. 5.3.x) с частными нормами ДНМ / ДККМ.
    • У каждого вывода — документ, пункт и дословная цитата; строка раскрывается в цитаты «до» и «после», кнопка открывает полный текст пункта.
    • Заключение: разделы «Итоги анализа», «Изменения подразделений», потери, дублирование, конфликты, «Рекомендации», «Исходные документы», раздел «Сверка с законодательством» и дисклеймер; кнопки «Скачать DOCX» и «Скачать PDF».
    • Рекомендации: карточки рекомендаций с кнопками принять / отклонить; принятые попадают в раздел «Принятые рекомендации» заключения при экспорте.
    • Рекомендации → Соответствие законодательству: нормативные основания, например после п. 1.5 (подчинение Главного аудитора Совету директоров) ↔ ст. 61 Закона «Об акционерных обществах» с цитатой статьи и кнопкой «Открыть на adilet.zan.kz».
  4. «История» в шапке показывает запуски пользователя; любой открывается повторно.

7.2. Smoke-скрипт

./scripts/smoke.sh                     # без ключа: 19 проверок инфраструктуры, анализ явно пропускается
./scripts/smoke.sh --require-analysis  # с ключом: 36 проверок, включая полный демо-анализ и контрольный набор

Ожидаемый итог: passed=36 failed=0 с моделью (3–6 минут: выполняется полный демо-анализ через POST /api/analyses/demo, затем scripts/verify-control.py проверяет контрольный набор: созданные ДИТААД и ДОА, сохранённые ДНМ и ДККМ, реорганизацию направления внутреннего аудита, потерю до п. 5.6.2, дублирование после п. 5.4.3 / 5.5.8, конфликт после п. 5.5.2, цитаты и источники всех выводов, сверку с 477 нормами, отказ нерелевантного документа и изоляцию истории) или passed=19 failed=0 без ключа. При другом порте: WEB_PORT=3100 ./scripts/smoke.sh; для развёрнутой версии: BASE_URL=https://hackalem-ai-wg.germanywestcentral.cloudapp.azure.com ./scripts/smoke.sh --require-analysis.

7.3. Демо-анализ через API

docker run --rm --add-host=host.docker.internal:host-gateway curlimages/curl:8.10.1 -sS -X POST http://host.docker.internal:3000/api/analyses/demo

Ответ {"analysis_id":"a_…"}. Подставьте id и повторяйте запрос, пока status не станет done:

docker run --rm --add-host=host.docker.internal:host-gateway curlimages/curl:8.10.1 -sS http://host.docker.internal:3000/api/analyses/a_XXXXXXXXXXXX

Документ анализа содержит documents[] (пункты с текстом и ссылками), units, unit_changes, functions, matches, findings (у каждого citations[] с doc_id, side, clause_id, ref, quote), regulatory, conclusion_md и stats (в контрольных запусках clauses_before = 450, clauses_after = 453, dropped_unverified = 0, regulatory_norms = 477).

7.4. Тесты и проверка чистого клона

docker compose run --rm --no-deps backend node --test       # backend, без ключа: сборка пунктов, структура, сопоставление и отклонения на заглушке модели, проверка цитат, заключение, сверка с законодательством на реальных нормах
docker compose run --rm --no-deps extractor pytest -q       # extractor: автонумерация Word, подпункты, таблицы, Excel, PDF, отказы на неверные файлы
./scripts/formats-test.sh                                    # Word, PDF, Excel и смешанный комплект через весь конвейер без ключа (модель подменяется только в этом тесте)
./scripts/clean-test.sh --env-file /absolute/path/reviewer.env   # чистый клон закоммиченного состояния, сборка без кеша, изолированные порты 3900/3901 и база, smoke --require-analysis; последняя строка «>> Clean-clone main-scenario test passed»
./scripts/clean-test.sh --infrastructure-only                    # то же без ключа: 19 проверок; последняя строка «>> Infrastructure-only check passed; main AI scenario was NOT verified»

Ожидаемый итог: backend — # fail 0; extractor — passed; smoke без ключа — passed=19 failed=0; с ключом и --require-analysis — passed=36 failed=0. Проверено в Docker 23.09.2026: smoke без ключа 19/19, extractor 28 passed, backend 49/49.

reviewer.env — копия .env.example с заполненными OPENAI_API_KEY, LLM_MODEL и, при желании, EMBEDDING_MODEL; Compose читает файл как данные, в репозиторий он не попадает.

8. Данные и интеграции

  • Контрольный комплект — два обезличенных PDF «Положение о внутреннем аудите АО „Компания“» по 25 страниц в services/backend/demo: ред. 8 («до», SHA-256 2257b6fa…17bb1) и ред. 9 («после», SHA-256 84eb8e79…fed3a5). Предоставлены команде 23.09.2026 как демоданные; байты не менялись. Отдельная лицензия в документах не указана. Это входные данные, а не заготовленные ответы: каждый запуск выполняет анализ заново.

  • Модель — единственная внешняя интеграция во время работы: OpenAI-совместимый API через SDK openai (LLM_PROVIDER, LLM_MODEL, LLM_BASE_URL, ключ). Ответы модели не кэшируются.

  • Нормативная база (O1) — services/backend/data/regulatory, три действующих закона РК в JSONL, одна запись на статью или пункт, 477 записей, около 1,2 МБ:

    ФайлАктРедакцияЗаписей
    Z030000415_.jsonlЗакон РК «Об акционерных обществах»от 13.08.2026291
    Z1500000410.jsonlЗакон РК «О противодействии коррупции»от 13.08.2026116
    Z1200000550.jsonlЗакон РК «О Фонде национального благосостояния»от 13.08.202670

    Источник — ИПС «Әділет» (adilet.zan.kz): тексты собраны скрейпингом заранее подготовленным инструментом команды, взяты только акты со статусом «действует», выгрузка от 23.09.2026; каждая запись хранит ссылку на пункт на adilet.zan.kz. Официальные тексты законов не являются объектами авторского права (ст. 8 п. 1 Закона РК «Об авторском праве и смежных правах»). При старте backend проверяет каждую строку и загружает нормы в коллекцию regulatory_norms (идемпотентно; ожидаемая строка в логе — regulatory norms: 477 pieces from 3 acts). Кнопка «Открыть на adilet.zan.kz» ведёт на old.adilet.zan.kz: 23.09.2026 новая версия сайта не открывала пункт по ссылке. Приложение само к adilet.zan.kz не обращается.

  • База — MongoDB hackalem: users, analyses (по документу на запуск), regulatory_norms. Загруженные файлы обрабатываются в памяти и не сохраняются; в базе остаются пункты, подразделения, функции, сопоставления, выводы и заключение.

  • Других внешних сервисов, датасетов и API нет.

9. Ограничения

  • Анализ требует ключа модели: без OPENAI_API_KEY и LLM_MODEL запуск отвечает 503 llm_unavailable; остальное работает.
  • Все выводы рекомендательные. Сильно переформулированную функцию модель-судья может не распознать, и она попадёт в «возможную потерю»; в контрольных запусках помимо трёх ожидаемых потерь отмечались ещё несколько пунктов ред. 8. Число функций и второстепенных выводов (MOVED, OVERLAP) от запуска к запуску немного меняется.
  • Без EMBEDDING_MODEL кандидаты подбираются лексически: контрольный набор воспроизводится, но переформулированные функции чаще попадают в «возможную потерю».
  • Сбой модели после повторных попыток или неполные ответы останавливают анализ с ошибкой (comparison_incomplete, structure_incomplete, report_unverified) вместо неполного результата; интерфейс предлагает запустить заново. Перезапуск сервера прерывает выполняющиеся анализы (interrupted).
  • Сканированные PDF без текстового слоя не распознаются (OCR нет); .doc не поддерживается — пересохраните в .docx. Обрезанный или частично нечитаемый документ останавливает анализ (incomplete_document).
  • Проверка на «неподходящий документ» полагается на модель: положение с нестандартной лексикой в редких случаях может быть отклонено; в сообщении видно, за что.
  • O1: встроены три закона в редакции от 13.08.2026; на adilet.zan.kz может действовать более новая редакция. Ищутся основание или возможное расхождение для функций «после»; обратной проверки (норма требует функцию, которой нет ни в одном пункте) нет. O2 (сравнение со структурами других операторов) не реализовано: данных нет. O3 — рекомендации по проверке каждого вида выводов; оптимальная структура автоматически не проектируется.
  • Анализ занимает 2–4 минуты на пару документов по 25 страниц и растёт линейно с объёмом; кэша ответов модели нет.
  • Аутентификация минимальная: нет восстановления пароля, ограничения попыток и ролей; AUTH_SECRET по умолчанию годится только для локального запуска.

10. Развёрнутая версия

https://hackalem-ai-wg.germanywestcentral.cloudapp.azure.com — тот же docker-compose.yml, пересобирается при каждом push в main; ключ модели и EMBEDDING_MODEL=text-embedding-3-small заданы в окружении VM. Проверено 23.09.2026 в 17:40: /api/health отвечает {"status":"ok","db":"ok","llm":"configured"}, вход демо-аккаунтом работает. Локальный запуск из чистого клона остаётся основным способом проверки.

Соответствие требованиям ТЗ

ТребованиеСтатусГде проверить
M1. Реорганизованные, сохранённые и созданные подразделенияреализованоэкран «Структура»; smoke units ДИТААД and ДОА created, ДНМ and ДККМ kept, audit direction reorganized into ДИТААД and ДОА
M2. Потеря функцийреализованоэкран «Потеря функций»; smoke POTENTIAL_LOSS at до п. 5.6.2 with its quote
M3. Дублирование и конфликт интересовреализованоэкран «Дублирование и конфликты»; smoke POTENTIAL_DUPLICATION после п. 5.4.3 / 5.5.8, POTENTIAL_CONFLICT cites после п. 5.5.2
M4. Источник у каждого выводареализованоцитата и пункт у каждого вывода; smoke every finding has a verified quote
M5. Аналитическое заключениереализованоэкран «Заключение», экспорт DOCX/PDF/Markdown; smoke conclusion covers all findings with valid document-qualified references
O1. Сверка с законодательствомреализовано частично (см. «Ограничения»)модуль «Соответствие законодательству»; smoke O1: legislation check…
O2. Сравнение с другими операторамине реализовано—
O3. Рекомендацииреализованораздел «Рекомендации» заключения и экран «Рекомендации»

Доступ для жюри

  • Без ключей: развёрнутая версия выше, логин [email protected], пароль [скрыто]. Аккаунт синтетический, создаётся автоматически при старте backend (локально тоже).
  • Локально: нужен ключ OpenAI-совместимого API с доступом к чат-модели в режиме JSON: OPENAI_API_KEY и LLM_MODEL в .env (команда проверяла на gpt-5.6-terra; EMBEDDING_MODEL=text-embedding-3-small необязателен). Ключ команды в репозиторий не входит; ограниченную конфигурацию модели (файл reviewer.env с ключом с лимитом расходов) команда передаёт жюри приватно при сдаче работы; тот же файл используется в ./scripts/clean-test.sh --env-file.
  • API анализа (/api/analyses) доступен без входа; вход нужен только для интерфейса и истории.

Надёжность и безопасность

  • Все пять сервисов имеют healthcheck и restart: unless-stopped; наружу опубликованы только порты Caddy.
  • Каждый вход проверяется: JSON до 1 МБ, файлы до MAX_UPLOAD_MB, тип по содержимому до постановки в очередь, строгие zod-схемы тел запросов; extractor отклоняет архивы больше 200 МБ в распакованном виде и PDF больше 300 страниц и разбирает документы в отдельном потоке. Ошибки — JSON {"error":{"code","message"}} без трассировок.
  • Внешние вызовы с таймаутами и повторами: extractor 60 с и два повтора; модель 90 с, два повтора на сетевые ошибки и 429/5xx, не больше 12 параллельных вызовов, проверка каждого ответа схемой с одним повторным запросом.
  • Текст документов передаётся модели как данные внутри блока <document> с указанием не выполнять содержащиеся в нём инструкции; модель возвращает только идентификаторы пунктов и метки, цитаты берёт код. Заключение строится кодом.
  • Пароли — scrypt, сессии — JWT HS256 в cookie HttpOnly; SameSite=Lax (Secure за HTTPS); в фильтры MongoDB попадают только приведённые значения. Ключи читаются только на сервере и в бандл frontend не попадают; .env исключён из Git.

Сторонние и заранее подготовленные материалы

  • До мероприятия подготовлен только шаблон окружения (коммит a6d411c, 23.09.2026 10:48): инструкции для агентов, Compose, Caddyfile, шаблоны документации и скрипты проверки. Всё прикладное (extractor, конвейер, API, интерфейс) написано 23.09.2026 в этом репозитории.
  • Образы и инфраструктура: Docker/Compose, Caddy, MongoDB, curl, python:3.12-slim, node:22-alpine, uv.
  • Backend: express 5, mongodb 6, multer 2, jsonwebtoken 9, zod 4 (MIT/Apache-2.0), openai 7 (Apache-2.0).
  • Frontend: vue 3, vite 6, marked 18, docx 9 (MIT); шрифты Manrope, Golos Text, Lora, Nunito Sans, PT Serif из пакетов @fontsource (SIL OFL 1.1). Иконки нарисованы вручную в стиле Lucide. Логотип OrgScope — условный знак, не логотип Казахтелекома.
  • Extractor: FastAPI, uvicorn, python-multipart, python-docx, pdfplumber, openpyxl, xlrd, pytest, httpx; полный список — services/extractor/uv.lock. Точные версии и транзитивные зависимости всех сервисов зафиксированы в lock-файлах.
  • Модель: gpt-5.6-terra и text-embedding-3-small (OpenAI) через официальный SDK.
  • Данные: два предоставленных обезличенных PDF и тексты трёх законов РК с adilet.zan.kz, выгруженные заранее подготовленным инструментом команды (код инструмента в репозиторий не входит); подробности — в разделе «Данные и интеграции».
  • Инструменты разработки: OpenAI Codex, Claude Code и Cursor; инструкции для них — в AGENTS.md, CLAUDE.md и .claude/.

Команда

Команда Optimus, три участника; авторы коммитов в истории Git — Khazretsultan, kairadio, bolatashim. Распределение: extractor, сборка пунктов, API анализа, сверка с законодательством и smoke — Khazretsultan; модуль модели, этапы конвейера, экран результатов, экспорт и README — kairadio; дизайн-система и экран входа — bolatashim.

Звёзды
⭐ 0
Форки
0
Язык
JavaScript
Последний push
в прошлом месяце
Коммиты
82
Авторы
3
Файлы
121
Ветки
2

Авторы коммитов

Khazretsultan 44kairadio 27bolatashim 11

История коммитов

  • 2026-09-23 17:51style(frontend): brand logo in the accent teal everywhere to match the login pagebolatashim
  • 2026-09-23 17:49docs(readme): backend test count verified on current main (49/49)Khazretsultan
  • 2026-09-23 17:49docs(readme): compact smoke section; login-only screen and lock-file note from mainKhazretsultan
  • 2026-09-23 17:48Merge origin/main into the README branchKhazretsultan
  • 2026-09-23 17:47docs: clarify verification evidence and complete dependency disclosureKhazretsultan
  • 2026-09-23 17:47feat(frontend): remove the API status pill from the login pagebolatashim
  • 2026-09-23 17:45feat(frontend): remove registration from the login page UI; login with the existing account onlybolatashim
  • 2026-09-23 17:45docs(readme): jury-facing README with live link and demo login, trimmed to verified claimsKhazretsultan
Все коммиты (82)
  • 2026-09-23 17:44feat(frontend): recommendation cards with include/reject; Markdown download removedkairadio
  • 2026-09-23 17:43style(frontend): restyle login page to the paper report design (cream page, white sheet, serif display, teal accent)bolatashim
  • 2026-09-23 17:40fix(verification): require full analysis and enforce source-backed acceptanceKhazretsultan
  • 2026-09-23 17:38feat(frontend): structure diagram screen; overview shows only the critical findingskairadio
  • 2026-09-23 17:34feat(frontend): conclusion export as DOCX and PDF; tabs row under the header; logo goes homekairadio
  • 2026-09-23 17:31fix(report): build conclusions from verified findings and unit sourcesKhazretsultan
  • 2026-09-23 17:28fix(frontend): remove control-set launch buttonKhazretsultan
  • 2026-09-23 17:28feat(frontend): brand favicon, cache headers, view survives reload, logo opens last reportKhazretsultan
  • 2026-09-23 17:23fix(sources): preserve document identity in matching and reportsKhazretsultan
  • 2026-09-23 17:21chore(changelog): claim favicon and frontend cachingKhazretsultan
  • 2026-09-23 17:19feat(frontend): align the results UI with the OrgScope design filekairadio
  • 2026-09-23 17:18perf(llm): allow 12 concurrent model calls per analysis (was 6)Khazretsultan
  • 2026-09-23 17:18chore(changelog): claim LLM concurrency increaseKhazretsultan
  • 2026-09-23 17:16fix(structure): assess succession from duties and reject incomplete decisionsKhazretsultan
  • 2026-09-23 17:10feat: per-user run history and an input guard for documents that are not about units and functionskairadio
  • 2026-09-23 16:55fix(pipeline): analyze flat and unnumbered document contentKhazretsultan
  • 2026-09-23 16:51style(frontend): results screens use tokens only, no raw hex outside tokens.csskairadio
  • 2026-09-23 16:51docs(readme, design-system): describe the redesigned results workspace and bundled fontskairadio
  • 2026-09-23 16:50feat(frontend): results workspace redesign: verdict-first summary, priority rows, unit flow, per-unit pagekairadio
  • 2026-09-23 16:42fix(compare): judge semantic changes instead of trusting lexical matchesKhazretsultan
  • 2026-09-23 16:41revert: remove the /#demo demo-data concept UI and vite dev proxybolatashim
  • 2026-09-23 16:39fix(frontend): proxy /api from vite dev server to the compose stackbolatashim
  • 2026-09-23 16:38fix(pipeline): mark analyses interrupted by a restart as failed; smoke poll tolerates slow requestskairadio
  • 2026-09-23 16:38refactor(demo-ui): simpler 4-step flow — no sessions sidebar, doc modal, fewer elementsbolatashim
  • 2026-09-23 16:36feat(o1): «Нормативные требования» tab with «Открыть на adilet.zan.kz»Khazretsultan
  • 2026-09-23 16:28docs(changelog): embeddings enabled and verified; partial-loss rulekairadio
  • 2026-09-23 16:27fix(compare): stop incomplete AI assessments before reporting findingsKhazretsultan
  • 2026-09-23 16:24feat(frontend): demo-data analyst workspace — full 6-step flowbolatashim
  • 2026-09-23 16:20docs(changelog): claim sequential correctness fixesKhazretsultan
  • 2026-09-23 16:17docs(readme): embeddings enabled for the team key; partial losses describedkairadio
  • 2026-09-23 16:17feat(compare): confident partial matches become medium partial-loss findings; embedding calls in statskairadio
  • 2026-09-23 16:14feat(o1): check «после» functions against legislation from adilet.zan.kzKhazretsultan
  • 2026-09-23 16:05fix(pipeline): capitalize unit names; Russian matching-step names on finding cardskairadio
  • 2026-09-23 16:04chore(changelog): claim O1 code (regulatory check, norms loader, adilet tab)Khazretsultan
  • 2026-09-23 15:59docs(changelog): claim the UI visual check; note for bolatashim that the results UI is on mainkairadio
  • 2026-09-23 15:58feat(pipeline): stages 2–5 end to end: units, functions, matching, findings with verified quotes, conclusionkairadio
  • 2026-09-23 15:58feat(frontend): analysis workspace: upload, progress, units / matches / findings / conclusionkairadio
  • 2026-09-23 15:57feat(data): ship O1 regulatory slice from adilet.zan.kz, disclosed in READMEKhazretsultan
  • 2026-09-23 15:55chore(changelog): claim O1 regulatory data export and README disclosureKhazretsultan
  • 2026-09-23 15:54chore(changelog): claim demo-data frontend flow in services/frontendbolatashim
  • 2026-09-23 15:41test(smoke): demo analysis end to end plus analysis API bad inputKhazretsultan
  • 2026-09-23 15:38feat(api): POST /api/analyses, /demo and GET /:id run pipeline stage 1Khazretsultan
  • 2026-09-23 15:23docs(changelog): claim llm.js, pipeline modules 2–5 and the results UIkairadio
  • 2026-09-23 15:23feat(pipeline): stage 1 clauses.js groups extractor fragments into clausesKhazretsultan
  • 2026-09-23 15:18docs(changelog): claim clauses.js and analyses routesKhazretsultan
  • 2026-09-23 15:17docs: team changelog; O1 today on a parallel track, O2 droppedKhazretsultan
  • 2026-09-23 15:15chore(compose): pass LLM and embedding env vars into the backend containerkairadio
  • 2026-09-23 15:05feat(demo): ship supplied anonymized before and after PDFsKhazretsultan
  • 2026-09-23 15:03chore(env): add EMBEDDING_MODEL for the semantic matching fallbackkairadio
  • 2026-09-23 15:02docs(spec): restore mandatory-M3 cut-list wording clobbered in 4b72e48; note sub-item markerkairadio
  • 2026-09-23 15:02docs(spec): embedding fallback before LLM judge, advisory labels, overlap vs duplication, LLM-reviewed conflictskairadio
  • 2026-09-23 14:58docs(agents): make the frontend design system mandatory for UI workbolatashim
  • 2026-09-23 14:56feat(frontend): Kazakhtelecom-styled design system and auth screenbolatashim
  • 2026-09-23 14:54docs(readme): make authentication commands safe to copy into shellsKhazretsultan
  • 2026-09-23 14:52test(extractor): guard health responsiveness during document parsingKhazretsultan
  • 2026-09-23 14:51feat(auth): seed a demo account at startup and document it for the jurykairadio
  • 2026-09-23 14:50fix(extractor): preserve Word numbering overrides in source referencesKhazretsultan
  • 2026-09-23 14:47docs(spec): keep conflict detection mandatory in scope cutsKhazretsultan
  • 2026-09-23 14:44perf(extractor): parse off the event loop; resolve Word styles onceKhazretsultan
  • 2026-09-23 14:41docs(agents): regulatory corpus tool from adilet.zan.kz via ereestr.kzKhazretsultan
  • 2026-09-23 14:39fix(extractor): sub-items carry marker, clause stays null (docx = pdf)Khazretsultan
  • 2026-09-23 14:32docs(spec): escape pipe in API tablekairadio
  • 2026-09-23 14:32docs(spec): build clause parsing on the extractor service; note auth and extractor factskairadio
  • 2026-09-23 14:31feat(auth): email/password signup and login with session cookie, end to endkairadio
  • 2026-09-23 14:28docs: architecture spec for task 1 with 5-module pipeline, rules, control set and diagramskairadio
  • 2026-09-23 14:20feat(backend): POST /api/documents/extract via extractor clientKhazretsultan
  • 2026-09-23 14:18feat(backend): connect to MongoDB and report it in /api/healthkairadio
  • 2026-09-23 14:13feat(extractor): internal Word/PDF/Excel text extraction serviceKhazretsultan
  • 2026-09-23 14:02fix(deploy): rebuild Caddy routing so Vue replaces the placeholderKhazretsultan
  • 2026-09-23 13:57feat(frontend): Vue 3 + Vite app served by Caddy; README describes real stackKhazretsultan
  • 2026-09-23 13:54feat(backend): Node.js/Express API skeleton routed at /api via CaddyKhazretsultan
  • 2026-09-23 13:52docs: add ТЗ, criteria gate and chunked workflowKhazretsultan
  • 2026-09-23 13:22docs: align Russian README and agent guidance with jury requirementsKhazretsultan
  • 2026-09-23 12:48chore: development environment template (prepared before the event)Khazretsultan
Структура репозитория (121 файлов)
.claude/settings.json
.env.example
.gitattributes
.gitignore
AGENTS.md
CLAUDE.md
Caddyfile
README.md
docker-compose.yml
docs/CHANGELOG.md
docs/TASK.md
scripts/clean-test.sh
scripts/formats-test.sh
scripts/smoke.sh
scripts/verify-control.py
services/backend/.dockerignore
services/backend/Dockerfile
services/backend/data/regulatory/Z030000415_.jsonl
services/backend/data/regulatory/Z1200000550.jsonl
services/backend/data/regulatory/Z1500000410.jsonl
services/backend/demo/after/redakciya_9.pdf
services/backend/demo/before/redakciya_8.pdf
services/backend/package-lock.json
services/backend/package.json
services/backend/scripts/verify-formats.mjs
services/backend/src/auth.js
services/backend/src/db.js
services/backend/src/extractorClient.js
services/backend/src/httpError.js
services/backend/src/llm.js
services/backend/src/pipeline/classify.js
services/backend/src/pipeline/clauses.js
services/backend/src/pipeline/compare.js
services/backend/src/pipeline/extract.js
services/backend/src/pipeline/regulatory.js
services/backend/src/pipeline/report.js
services/backend/src/pipeline/run.js
services/backend/src/pipeline/structure.js
services/backend/src/pipeline/util.js
services/backend/src/prompts.js
services/backend/src/prompts/classify.md
services/backend/src/prompts/conflict.md
services/backend/src/prompts/dupjudge.md
services/backend/src/prompts/extract.md
services/backend/src/prompts/judge.md
services/backend/src/prompts/regulatory.md
services/backend/src/prompts/structure.md
services/backend/src/prompts/successors.md
services/backend/src/prompts/system.md
services/backend/src/regulatoryNorms.js
services/backend/src/routes/analyses.js
services/backend/src/routes/auth.js
services/backend/src/routes/documents.js
services/backend/src/schemas.js
services/backend/src/seed.js
services/backend/src/server.js
services/backend/src/upload.js
services/backend/test/classify.test.js
services/backend/test/clauses.test.js
services/backend/test/compare.test.js
services/backend/test/fixtures/redakciya_9_extract.json
services/backend/test/regulatory.test.js
services/backend/test/report.test.js
services/backend/test/run.test.js
services/backend/test/structure.test.js
services/caddy/Dockerfile
services/caddy/Dockerfile.dockerignore
services/extractor/.dockerignore
services/extractor/Dockerfile
services/extractor/app/__init__.py
services/extractor/app/formats.py
services/extractor/app/main.py
services/extractor/app/model.py
services/extractor/app/parsers/__init__.py
services/extractor/app/parsers/docx_parser.py
services/extractor/app/parsers/excel_parser.py
services/extractor/app/parsers/pdf_parser.py
services/extractor/pyproject.toml
services/extractor/tests/generate_format_inputs.py
services/extractor/tests/test_docx_numbering.py
services/extractor/tests/test_extract.py
services/extractor/tests/test_responsiveness.py
services/extractor/uv.lock
services/frontend/.dockerignore
services/frontend/Caddyfile
services/frontend/DESIGN_SYSTEM.md
services/frontend/Dockerfile
services/frontend/index.html
services/frontend/package-lock.json
services/frontend/package.json
services/frontend/public/favicon.svg
services/frontend/src/App.vue
services/frontend/src/AuthPanel.vue
services/frontend/src/BrandMark.vue
services/frontend/src/HealthStatus.vue
services/frontend/src/Icon.vue
services/frontend/src/adilet.js
services/frontend/src/api.js
services/frontend/src/components/ClausePanel.vue
services/frontend/src/components/Conclusion.vue
services/frontend/src/components/FindingCard.vue
services/frontend/src/components/HistoryList.vue
services/frontend/src/components/MatchTable.vue
services/frontend/src/components/ProgressBar.vue
services/frontend/src/components/RegulatoryTab.vue
services/frontend/src/components/UnitsTable.vue
services/frontend/src/components/UploadPanel.vue
services/frontend/src/domain.js
services/frontend/src/export.js
services/frontend/src/main.js
services/frontend/src/results/DistributionBar.vue
services/frontend/src/results/FindingRow.vue
services/frontend/src/results/Recommendations.vue
services/frontend/src/results/StructureView.vue
services/frontend/src/results/SummaryView.vue
services/frontend/src/results/UnitFlow.vue
services/frontend/src/results/UnitPage.vue
services/frontend/src/results/text.js
services/frontend/src/styles/components.css
services/frontend/src/styles/tokens.css
services/frontend/vite.config.js
Ветки (2)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.