О проекте
Команда: Nomad
Кейс HackAlem.ai: Спецтрек — Казахтелеком
Стадия: Рабочий MVP
Задача кейса: Агент, сравнивающий документы оргструктуры до и после реорганизации
Суть
Streamlit-сервис, который сравнивает документы оргструктуры ДО и ПОСЛЕ реорганизации (PDF/DOCX/XLSX). Он показывает созданные, удалённые и преобразованные подразделения, перераспределение функций и гипотезы о рисках, и к каждому выводу прикладывает проверяемую ссылку на исходный фрагмент.
Как устроено
Парсеры PyMuPDF, python-docx и openpyxl режут документы на SourceChunk с метаданными: страница, пункт, лист/строка, детерминированный chunk_id. Затем идёт поэтапная работа с OpenAI Responses API и Structured Outputs: сначала извлекается структура подразделений, потом функции с привязкой к подтверждённым подразделениям, потом семантическое сравнение, потеря и дублирование функций, конфликты интересов. После каждого этапа код проверяет схемы Pydantic и существование ссылок, а неподтверждённые объекты отбрасывает. Результаты кэшируются в session_state по хешам файлов, модели и версиям кода. Итоговое заключение собирается без дополнительного вызова AI.
Ключевые решения
- OpenAI Responses API
- Structured Outputs
- Pydantic schemas
- source-chunk traceability
- citation validation
- staged extraction (structure → functions → comparison)
- hash-based session cache
Особенности
Принцип «AI интерпретирует — система проверяет источники»: каждый chunk_id, который вернул LLM, валидируется, а цитата в UI берётся из текста парсера, а не из ответа модели. Кандидаты на потерю функции дополнительно проверяются на перенос в другие подразделения ПОСЛЕ. Кэш учитывает отпечатки файлов реализации.
Стек
Python · Streamlit · PyMuPDF · python-docx · openpyxl · OpenAI SDK · Pydantic · unittest
Модели
gpt-4.1-mini
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-427ac9f6-nomad.
README
README.mdОргАналитик AI
AI-сервис для анализа организационной структуры и функций до и после реорганизации. HackAlem MVP: два документа, сравнение изменений и проверяемые ссылки на исходный текст.
Проблема
Ручное сравнение организационных документов требует сопоставлять подразделения, обязанности и формулировки из разных редакций. При реорганизации могут возникать потери функций, дублирование, пересечение ответственности и потенциальные конфликты интересов. Одного текстового diff недостаточно для интерпретации таких изменений.
Решение
Документы ДО/ПОСЛЕ → парсинг → извлечение организационной структуры → анализ функций и ответственности → сравнение → проверка источников → потенциальные риски и рекомендации.
«AI интерпретирует — система проверяет источники.»
Каждый отображаемый содержательный вывод связан с исходными фрагментами документов. Проверка ссылок выполняется при извлечении и сравнении. Она подтверждает наличие источника, но не доказывает, что интерпретация AI верна: окончательное решение принимает человек.
Возможности
- Загрузка документов ДО/ПОСЛЕ в PDF, DOCX и XLSX, до 20 МБ каждый.
- Извлечение структурных подразделений, поддержанных источником наименований и алиасов.
- Извлечение функций с привязкой к подтверждённым подразделениям.
- Сравнение структуры: сохранение, создание, удаление и преобразование подразделений.
- Анализ изменений и перераспределения ответственности по исходному тексту.
- Гипотезы о возможной потере функций, дублировании и конфликтах интересов; рекомендации по проверке.
- Просмотр оригинальных фрагментов, имени документа, страницы, пункта или другого указателя.
- Русский интерфейс, единый запуск анализа и сравнения с этапами прогресса.
- Раздельный кэш успешного извлечения и завершённого сравнения в текущей сессии.
- Итоговое аналитическое заключение из уже проверенных результатов: структура, функции, риски, существующие рекомендации и ограничения; без дополнительного AI-запроса.
Архитектура
flowchart TD
User["Пользователь"] --> UI["Streamlit UI"]
subgraph Code["Детерминированный Python-код"]
UI --> Parser["Парсеры PDF / DOCX / XLSX"]
Parser --> Chunks["SourceChunk: текст и метаданные"]
Chunks --> Structure["Извлечение структуры"]
Structure --> Functions["Извлечение функций"]
Functions --> Compare["Сравнение структуры и ответственности"]
Chunks --> Compare
Compare --> Validator["Валидация ссылок на источники"]
Validator --> Findings["Выводы и рекомендации с источниками"]
Findings --> UI
UI <--> Cache["Кэш и результаты в session_state"]
end
subgraph AI["AI inference — внешний сервис"]
API["OpenAI Responses API / Structured Outputs"]
end
Structure <--> API
Functions <--> API
Compare <--> API
Узлы извлечения и сравнения — Python-оркестраторы: смысловые ответы формирует OpenAI, а код задаёт схему, проверяет владельцев и ссылки. Валидация также выполняется после каждого этапа извлечения, до передачи данных дальше. Подробности: архитектура.
Как работает AI
| Детерминированный код | AI |
|---|---|
| Читает файлы и выделяет текст | Интерпретирует организационную структуру |
| Сохраняет метаданные и распознаёт номера пунктов | Выделяет обязанности и их владельцев |
| Формирует порции контекста и проверяет схемы ответов | Семантически сравнивает ответственность |
| Проверяет существование ссылок и допустимые подразделения | Формулирует гипотезы о рисках и рекомендации |
| Обслуживает кэш, состояние и интерфейс | Возвращает ссылки на предоставленные источники |
AI не является источником доказательств. Сначала для каждого документа извлекается структура, затем функции с использованием полного проверенного реестра подразделений. Должности не становятся подразделениями автоматически; обязанности руководителя могут относиться к подразделению при явной связи в источнике.
Сравнение использует подразделения и исходные фрагменты напрямую, поэтому не ограничено списком извлечённых функций. Кандидаты на потерю проходят дополнительную проверку переноса на другие подразделения ПОСЛЕ. Анализ дублирования и конфликтов использует документ ПОСЛЕ.
Traceability / Explainability
SourceChunk хранит chunk_id, document_id, filename, page, section, locator, text.
Например, before_p006_003 — детерминированный идентификатор позиции фрагмента, который
разрешается в контексте конкретного документа. Идентификатор документа учитывает сторону,
имя файла и содержимое; один chunk_id не является глобальным ID всех загрузок.
Подразделения, функции и результаты сравнения ссылаются на эти фрагменты. Неизвестные ссылки отклоняются; объекты без достаточных допустимых подтверждений не показываются как проверенные результаты. Цитата в «Показать подтверждение» берётся из сохранённого текста парсера, а не генерируется AI. Для DOCX/XLSX вместо номера страницы используется абзац либо лист и строка. Номер пункта может отсутствовать.
Tech Stack
- Python 3.10+; локальные проверки выполнены в Python 3.12.
- Streamlit — интерфейс и состояние сессии.
- PyMuPDF — PDF; python-docx — DOCX; openpyxl — XLSX.
- OpenAI Python SDK — Responses API и Structured Outputs.
- Pydantic — схемы ответов; dataclasses — внутренние модели.
- python-dotenv — чтение
.env. - unittest, unittest.mock и Streamlit AppTest — автоматические проверки.
Базы данных, векторного хранилища, embeddings, OCR и аутентификации нет.
Структура проекта
app.py # единый пользовательский сценарий
requirements.txt # зависимости с диапазонами версий
.env.example # шаблон без ключа
.gitignore
.streamlit/config.toml # тема и лимит загрузки
src/
config.py # настройки из окружения и .env
models.py # документы, фрагменты, результаты
ui_common.py # общие элементы UI и источники
comparison_ui.py # вкладки результатов
parsers/
parser_factory.py # проверка загрузки и выбор парсера
pdf_parser.py
docx_parser.py
xlsx_parser.py
services/
chunking.py # фрагменты и номера пунктов
extraction.py # структура, затем функции
comparison.py # сравнение, риски, проверка потерь
pipeline.py # последовательность и кэш
tests/ # unittest и AppTest
docs/
architecture.md
demo.md
Быстрый запуск
Нужны Python 3.10+, доступ к сети для установки пакетов и OpenAI API, а также действующий API-ключ с доступом к выбранной модели. Команды выполняются из корня репозитория. Реальный анализ отправляет текст в OpenAI и может быть платным.
Windows PowerShell:
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
# Только если .env ещё не существует:
Copy-Item .env.example .env
В локальном .env укажите собственный ключ (не коммитьте его):
OPENAI_API_KEY=your-key-here
OPENAI_MODEL=gpt-4.1-mini
.\.venv\Scripts\python.exe -m streamlit run app.py
macOS/Linux:
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
# Только если .env ещё не существует:
cp .env.example .env
# Заполните .env своим ключом перед анализом.
.venv/bin/python -m streamlit run app.py
Откройте адрес, выведенный Streamlit, обычно http://localhost:8501.
Активация виртуального окружения не требуется: команды используют его Python напрямую.
Переменные окружения
| Переменная | Назначение | Значение по умолчанию |
|---|---|---|
OPENAI_API_KEY | Ключ доступа к OpenAI; необходим для запуска анализа | Нет |
OPENAI_MODEL | Модель с поддержкой используемых структурированных ответов | gpt-4.1-mini |
Переменные процесса имеют приоритет над .env в корне репозитория. Настройки читаются
при явном запуске анализа. При отсутствии ключа интерфейс сообщает об ошибке настройки.
Поддерживаемые форматы
| Формат | Что извлекается | Ограничения |
|---|---|---|
| Текст страниц с разделением по распознанным номерам пунктов | Нет OCR; PDF с паролем не поддерживается; порядок текста зависит от вёрстки | |
| DOCX | Непустые абзацы тела документа с физическими индексами | Таблицы, колонтитулы, текстовые поля и автоматические номера списков не извлекаются |
| XLSX | Непустые строки, лист, номер строки и буквы столбцов | Формулы сохраняются как текст, не вычисляются |
Пустые, повреждённые, неподдерживаемые файлы и файлы свыше 20 МБ отклоняются. В смешанном PDF страницы без доступного текстового слоя не анализируются.
Сценарий проверки
- Запустите приложение.
- Загрузите исходный документ в «До реорганизации».
- Загрузите новую редакцию в «После реорганизации».
- Нажмите «Провести анализ».
- Дождитесь этапов чтения, определения структуры и функций, сравнения, формирования рисков и рекомендаций.
- В «Результаты сравнения» изучите вкладку «ОБЗОР ИЗМЕНЕНИЙ».
- Откройте «ИЗМЕНЕНИЯ ФУНКЦИЙ» и проверьте перераспределение ответственности.
- На вкладке «РИСКИ И РЕКОМЕНДАЦИИ» изучите карточки найденных гипотез, если они есть.
- Раскройте «Показать подтверждение».
- Сверьте документ, страницу/локатор, пункт и исходный фрагмент с выводом.
Повторите запуск с той же парой в той же сессии: завершённые этапы берутся из кэша без повторных запросов. Ключ включает хеши обоих файлов, исходные имена, модель, версии обработки и отпечатки файлов реализации. Хранятся до трёх пар на каждый кэш; переименование файла тоже вызывает новый анализ, чтобы не перепутать источники. Обычные rerun интерфейса не повторяют запросы. Для завершённого сравнения каждое извлечённое подразделение ДО/ПОСЛЕ должно быть покрыто принятым сопоставлением. Неполное сопоставление явно отмечается предупреждением и счётчиками покрытия; при пустом результате вместо нулей структуры показывается «—». Полезные частичные результаты сохраняются, но не кэшируются как успешно завершённое сравнение. Код не назначает отсутствующие статусы автоматически. Ошибки не кэшируются; после сбоя сравнения успешное извлечение сохраняется и используется при повторной попытке.
Сценарий демонстрации на 3 минуты.
Тестирование
Windows:
.\.venv\Scripts\python.exe -m unittest discover -s tests -v
macOS/Linux:
.venv/bin/python -m unittest discover -s tests -v
Финальный локальный прогон 23.09.2026: 92 теста, все прошли, Python 3.12,
существующее изолированное окружение .venv-h2. Проверены парсеры на генерируемых
PDF/DOCX/XLSX, проверки источников, роли и алиасы, принадлежность функций, сравнение,
обработка ошибок, русский UI, кэш и сохранение результатов при rerun, полнота покрытия
структуры и детерминированное итоговое заключение.
OpenAI в тестах замокан: API-кредиты не расходуются. Эти тесты не доказывают качество
реального анализа редакций 8/9 и не измеряют его скорость.
Дополнительно проверены импорт app.py, запуск Streamlit и ответ ok на health endpoint,
соответствие установленных версий requirements.txt и pip check без конфликтов.
Локальная среда: Python 3.12.14, Streamlit 1.64.0, PyMuPDF 1.28.2, python-docx 1.2.0,
openpyxl 3.1.5, openai 2.54.0, python-dotenv 1.2.3, Pydantic 2.13.5.
Чистая установка в новое окружение и запуск на macOS/Linux в этой проверке не выполнялись.
Команды сверены с путями и точкой входа проекта; Mermaid проверен по структуре текста,
без отдельного рендерера диаграмм. Реальные запросы OpenAI в финальной QA не выполнялись.
Ограничения
Решение — прототип поддержки принятия решений. Выводы AI являются гипотезами и рекомендациями, а не установленными фактами или юридическими заключениями. Итоговые организационные выводы должен проверить ответственный сотрудник по оригинальным документам.
- Время первого анализа. На реальных организационных документах первый AI-анализ может занимать несколько минут; по результатам реального тестирования в одном запуске он превысил 7 минут. Время зависит от размера и структуры документов, количества выделенных разделов, числа этапов AI-анализа, задержек OpenAI API и сети. Конкретная максимальная длительность не гарантируется.
- Кэш сессии. Успешные результаты кэшируются только в текущей Streamlit-сессии, поэтому повторный анализ тех же документов в той же сессии может быть быстрее. Кэш теряется при новой сессии или перезапуске сервера; постоянного кэша нет.
- Вариативность AI. Извлечение структуры и функций выполняет LLM. При новых запусках AI одни и те же документы могут дать разное количество кандидатов в подразделения и функции. Проверка источников и явная маркировка неполного сравнения не гарантируют смысловой полноты или детерминированного ответа AI. Результаты требуют проверки человеком.
- Неполное сравнение. Если подразделения не удалось уверенно сопоставить, приложение показывает предупреждение о частичном анализе и доступные подтверждённые результаты. Отсутствующие сопоставления не трактуются как «ноль изменений». При неполном контексте ПОСЛЕ гипотезы о потенциальной потере функций могут быть скрыты.
- Точность зависит от структуры, качества текста и однозначности описания ответственности.
- Извлечение выполняется порциями контекста; дальние связи и семантические дубликаты могут быть пропущены.
- Для больших документов сравнение использует выбранные исходные фрагменты — до 65 000 UTF-8 байт на сторону. При неполном покрытии ПОСЛЕ выводы о потере скрываются. Чрезмерный контекст может привести к отказу обработки.
- Нет экспорта отчётов, БД и управления пользователями. MVP рассчитан на доверенные локальные документы.
- Зависимости заданы диапазонами, без lock-файла; побитовая воспроизводимость окружения не гарантируется.
Дальнейшее развитие
Возможные будущие улучшения; перечисленное ниже не реализовано:
- асинхронная или фоновая обработка;
- постоянный кэш результатов;
- оптимизация разбиения на порции и выбора контекста;
- предварительное детерминированное сопоставление точных имён и алиасов подразделений;
- оценка модели на размеченном контрольном наборе данных;
- мониторинг качества извлечения и времени обработки.
Безопасность
Ключ хранится в переменных окружения или локальном .env, который игнорируется Git.
.env.example содержит пустой OPENAI_API_KEY; реальный ключ в репозиторий добавлять нельзя.
Проверка текущих отслеживаемых файлов на распространённые признаки ключей и секретов
не выявила совпадений; это не полный аудит истории Git или безопасности приложения.
Для inference исходный текст и организационные данные передаются в OpenAI; используйте
документы, которые разрешено обрабатывать таким способом. Вызовы используют store=False;
это не заявление о полной политике хранения внешнего сервиса. Кэш и результаты находятся
в памяти сессии. Ссылки доказательств проверяются по распарсенным источникам, а показываемый
текст берётся из них напрямую. Аутентификация не реализована: не публикуйте локальный MVP
как открытый многопользовательский сервис без отдельной доработки безопасности.
Авторы коммитов
История коммитов
- 2026-09-23 17:53docs: document runtime limitations and development roadmapTuDi01
- 2026-09-23 17:40fix: validate comparison completeness and add analytical conclusionTuDi01
- 2026-09-23 17:06docs: finalize README architecture and demo guideTuDi01
- 2026-09-23 16:57feat: finalize Russian UI and optimize demo flowTuDi01
- 2026-09-23 16:21feat: add evidence-backed organizational comparison and findingsTuDi01
- 2026-09-23 15:59feat: add AI structure extraction with evidence traceabilityTuDi01
- 2026-09-23 14:33feat: add document upload parsing and source traceabilityTuDi01
- 2026-09-23 14:05Build H1 Streamlit document extraction and source previewsTuDi01
Все коммиты (9)
- 2026-09-23 12:34chore: initialize hackathon projectTuDi01
Структура репозитория (34 файлов)
.env.example .gitignore .streamlit/config.toml README.md app.py docs/architecture.md docs/demo.md requirements.txt src/__init__.py src/comparison_ui.py src/config.py src/models.py src/parsers/__init__.py src/parsers/docx_parser.py src/parsers/parser_factory.py src/parsers/pdf_parser.py src/parsers/xlsx_parser.py src/services/__init__.py src/services/chunking.py src/services/comparison.py src/services/conclusion.py src/services/extraction.py src/services/pipeline.py src/ui_common.py tests/stage_mocks.py tests/test_h1.py tests/test_h2.py tests/test_h21.py tests/test_h22.py tests/test_h23.py tests/test_h3.py tests/test_h41.py tests/test_h4_ui.py tests/test_p0.py
Ветки (2)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.