О проекте
Команда: JJStan
Кейс HackAlem.ai: Логистика — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: Автоматический расчёт заказов поставщикам для пополнения склада, с утверждением менеджером
Суть
Streamlit-приложение закупщика: загрузка архивов и XLSX Systeme Electric и IEK, расчёт рекомендуемого заказа, редактирование и утверждение менеджером, экспорт утверждённого CSV. Есть диагностика качества данных и опциональные AI-пояснения.
Как устроено
data_loader.py читает выгрузки поставщиков и сверяет месячные отчёты с операциями. engine.py рассчитывает заказ с учётом тренда, аномалий, восстановления stockout, сроков поставки, страхового запаса и MOQ/кратности. ui_integration и order_review привязывают правки к (supplier, sku) и блокируют утверждение при NaN или insufficient. export.py выгружает только утверждённый снимок (UTF-8 BOM, «;», защита от формул). AI-пояснения через OpenAI Responses API со строгой JSON Schema выбирают только порядок заранее проверенных тезисов с evidence_id, свободный текст модели не показывается. По умолчанию AI выключен.
Ключевые решения
- расчёт пополнения с трендом и stockout
- исключение аномалий
- MOQ/кратность
- human-in-the-loop утверждение
- Structured Outputs (JSON Schema)
- grounded-пояснения с evidence_id
- отчёт о блокерах качества данных
Метрики
На предоставленных архивах обработано 3 909 товаров; все рекомендации заблокированы ошибками качества или нехваткой данных
Особенности
Честно показано, что на реальных данных все рекомендации заблокированы, и это не подменяется демо. Для каждого замечания есть классификация «блокирует / требует проверки / вне периода» и CSV-отчёт для владельцев данных. LLM жёстко ограничена выбором из проверенных тезисов.
Стек
Python 3.12 · Streamlit · OpenAI SDK · pytest
Модели
OpenAI
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-024d5bf9-jjstan.
README
README.mdStockPilot — заказы поставщикам
Приложение закупщика для HackAlem AI. Нурасыл: данные. Гапар: engine. Рамазан: интерфейс и интеграция.
Запуск
Python 3.12. Команды из корня репозитория:
Основная ветка запуска — main. PR №1, №3 и №4 объединены. Получите обновления через git fetch origin, переключитесь командой git switch main, выполните git pull --ff-only origin main и перезапустите Streamlit из обновлённой папки. Обновление Git само по себе не перезапускает сервер.
py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m streamlit run app.py
Откройте напечатанный адрес, обычно http://127.0.0.1:8501. Сервер слушает только локальный компьютер. Остановка: Ctrl+C.
Для macOS/Linux после создания окружения используйте .venv/bin/python вместо .venv\Scripts\python.exe.
Работа с приложением
- При запуске открывается «Демонстрация»: 8 вымышленных товаров двух поставщиков. Расчёт выполняет настоящий
engine.py. - Для реальных данных выберите «Мои файлы» и загрузите
Systeme electric.zip,IEK.zipили XLSX. Для отдельного XLSX без поставщика в имени выберите IEK / Systeme Electric под загрузчиком. Выбор сохраняется в идентификаторе входов и передаётся loader через безопасную временную папку поставщика. Изменение выбора требует пересчёта и отменяет старое утверждение/AI-пояснение. ZIP с исходной структурой работает без такого выбора. Временные копии удаляются после чтения. - Укажите дату снимка, сроки поставки, период пересчёта и страховой запас. Нажмите «Рассчитать заказ».
- Во вкладке «Заказы» используйте поиск и фильтры. Колонка «Расчёт» содержит рекомендацию, «К заказу» — редактируемое количество. Подробности доступны по горизонтальной прокрутке или в полноэкранном режиме таблицы.
- Выберите строки. «Выбрать» выбирает доступные положительные рекомендации только среди видимых строк. Ранее выбранные строки сохраняются при смене фильтра; весь состав виден в раскрывающемся списке перед утверждением.
- Проверьте количество, единицы, ограничения и предупреждения; отметьте подтверждение и нажмите «Утвердить выбранные позиции».
- Скачайте CSV. Он содержит именно утверждённый снимок, сгруппирован по поставщику, включает дату расчёта и отметку источника. Нулевые количества означают отказ от закупки и в CSV не попадают.
Изменение параметров или файлов делает предыдущий расчёт устаревшим. Ручные правки и изменение выбранного состава отменяют утверждение. Для нового экспорта нужно утвердить заказ заново. Состояние хранится в текущей браузерной сессии; перезагрузка страницы/сервера может его сбросить, поэтому скачайте готовый файл.
Вкладка «Объяснение SKU» показывает слагаемые формулы, месячную историю, отдельный дневной прогноз и ограничения. Вкладка «Данные» содержит источники, размеры таблиц и диагностику.
Во вкладке «Данные» блок «Что мешает расчёту и что проверить» показывает сводку по типам проблем, фильтры поставщика/товара и разбор отдельного замечания: источник, период, исходное сообщение и необходимую проверку. Для расхождений продаж доступны месячный отчёт, сумма операций и разница из сверки loader; неизвестные значения остаются пропусками.
- Блокирует расчёт — engine явно назвал это замечание причиной недостаточных данных.
- Требует проверки — замечание есть, но отдельная блокирующая роль не подтверждена; engine мог остановиться раньше.
- Вне выбранного периода — engine выдал точное исключение для этого поставщика, SKU и текста ошибки. Исходный
severity=errorсохраняется; это не исправление источника и не разрешение заказа. - Информация — пояснение расчёта, которое само по себе не определяет допуск заказа.
Повторы одного замечания из loader и engine объединяются с сохранением источников. Общие замечания поставщика относятся только к его товарам. В сводке считаются уникальные пары поставщик + код 1С; один товар может попасть в несколько типов проблем, поэтому строки сводки нельзя суммировать. Несвязанные записи не исчезают и не увеличивают число товаров. Исходные таблицы и полная диагностика доступны ниже.
«Скачать полный список проблем (CSV)» выгружает все замечания выполненного расчёта, независимо от фильтров, с датой и отметкой демонстрационных/реальных данных. Это отчёт для проверки, не заказ поставщику. После изменения файлов или параметров скачивание блокируется до пересчёта. Просмотр отчёта не меняет количества, исходные ошибки или утверждение. Даже полный список найденных замечаний не доказывает, что проверены все возможные проблемы: расчёт может остановиться на первой причине.
В боковой панели есть «Подтверждённые условия поставщиков»: единый складской контур и недостающие минимум/кратность. Настройки включаются только явным подтверждением менеджера и должны соответствовать проверенным условиям. Условия из файлов имеют приоритет; ошибки продаж, неизвестные единицы и отсутствие остатков этим не исправляются. Проверка ручных количеств использует те же условия, что и расчёт.
Контракт и границы ответственности
dataset = load_data(paths) # Нурасыл
result = calculate_orders(dataset, settings) # Гапар
Схемы перечислены в TEAM_PLAN.md.
Файлы data_loader.py, engine.py, тесты и документы их авторов сохранены без правок. Наша граница интеграции — ui_integration.py:
- переводит явный маркер общего контура
*all*в__all__в копиях таблиц; - для SKU с текущим снимком передаёт engine текущие снимки, оставляя исторические таблицы в исходном dataset для просмотра;
- блокирует использование снимка на другую дату без подтверждённого обновления;
- сохраняет неизвестные склады, пропуски, ограничения MOQ и все ошибки loader; значения не выдумывает.
order_review.py отвечает за привязку правок к (supplier, sku), проверку выбора и количества. export.py создаёт CSV только после проверки снимка утверждения; текстовые поля защищены от интерпретации как формул. CSV в UTF-8 с BOM и разделителем ;. При импорте в Excel задайте колонкам кодов текстовый формат для сохранения ведущих нулей. Совместимость с конкретным импортом 1С не заявляется без проверки шаблона.
Ограничения текущих модулей
Подключён engine Гапара cc15fe0: устойчивый тренд, аномалии и восстановление подтверждённых stockout. UI читает ENGINE_CAPABILITIES и передаёт реальные настройки: тренд по умолчанию включён, исключение аномалий и восстановление stockout выключены до выбора пользователя. Карточка SKU показывает таблицу аномалий. Пустая таблица не доказывает отсутствие аномалий; отсутствие stockout/customer_id в источниках остаётся ограничением.
recommended_qty=NaN или data_quality=insufficient блокируют утверждение даже после ручного ввода количества. Недостающие минимум/кратность не подставляются автоматически. Общая сумма количества для разных единиц не вычисляется; закупочная стоимость без подтверждённых цен не показывается.
На предоставленных архивах проверка 23.09.2026 обработала 3 909 товаров; все рекомендации заблокированы исходными ошибками качества/нехваткой данных. Это не подменяется деморезультатом. Отчёт интеграции содержит детали и задачи владельцам данных/алгоритма.
AI-пояснения OpenAI
На защите AI оставляем выключенным: переключатель экспериментальных пояснений по умолчанию выключен. Известное ограничение: при сокращении до 24 issues пояснение неприменимости исторической ошибки может потеряться. Поэтому AI пока нельзя использовать как надёжное объяснение статуса при большом числе замечаний. Расчёт и утверждение от него не зависят. Живой запрос не проверен.
Во вкладке SKU доступны «Объяснить простыми словами» для готовой рекомендации и «Что нужно уточнить» для insufficient. Первая причина блокировки и все конкретные замечания товара/поставщика видны без AI. Чтение пояснения не изменяет черновик и утверждённый CSV.
Настройте OPENAI_API_KEY и OPENAI_MODEL в окружении процесса Streamlit либо в локальном .streamlit/secrets.toml по образцу .streamlit/secrets.toml.example. Реальный файл уже исключён из Git. Не отправляйте ключ в чат и не записывайте в документацию. При изменении окружения перезапустите сервер; secrets читаются при следующем действии в приложении. Модель также можно явно изменить в боковой панели. Без настройки доступны исходные формула и диагностика.
При первом нажатии кнопки проверяется доступ аккаунта к выбранной модели через models.retrieve, затем вызывается официальный SDK / Responses API со строгой JSON Schema и store=False. Успех запроса подтверждает совместимость конкретной модели; приложение не подменяет её другой. Responses API, Structured Outputs, проверка модели.
Это ограниченный AI-помощник: модель выбирает приоритет и порядок проверенных тезисов и вопросов. Текст и числа собираются локально из этих тезисов и фактов расчёта, а произвольный текст модели не отображается. Проверяются структура, разрешённые тезисы, evidence_id и согласованность фактов. Для insufficient нет тезиса с рекомендуемым количеством. При невалидном ответе, отказе API или таймауте остаются обычные пояснения. Контракт для Гапара: docs/ai_contract.md.
В OpenAI отправляется сводка одного SKU: числовые факты, обезличенный ID, классифицированные проблемы. Названия товаров, сырые сообщения, архивы, клиенты, документы, пути и ключи не входят в запрос. Только кнопка вызывает сеть; не более одного запроса одновременно, общий таймаут около 15 секунд и максимум один повтор временной ошибки. Кэш ограничен текущей сессией и включает расчёт, поставщика, SKU, вопрос, модель, провайдера и версию prompt. Смена входов очищает AI-кэш; смена модели сохраняет числовой заказ и утверждение.
Первый live smoke-test проводится только в «Демонстрации» на синтетическом SKU с ответом 72. Unit-тесты используют mock SDK и не делают платных вызовов. Наличие ключа не означает успешного подключения: готовность подтверждается ответом status=ok.
NVIDIA: в текущей сборке NVIDIA inference не подключён. Brev Billing относится к вычислительным ресурсам и общему балансу организации; он не подтверждает наличие hosted inference endpoint. Баланс и купон не проверялись, пользовательские coupon-ссылки не сохраняются. Отдельный Brev-эксперимент можно показывать только с фактическим результатом и подписью «офлайн-эксперимент». Документация Brev.
Финальная сборка
23.09.2026 Нурасыл объединил PR №1, №3 и №4 в main; merge-коммит полной сборки — d317b24. Loader соответствует feat/data@5f1265b, engine и примеры — feat/engine@be75d23, интерфейс — feat/ui@a801a00. Все 28 файлов объединённой сборки сверены с проверенными версиями.
После объединения: 152 passed, без пропусков, включая оба приватных архива. Все 8 примеров engine успешны. Через Streamlit AppTest проверены расчёт 72, ручная правка до 84, утверждение и CSV с 84, отмена утверждения при сбросе состава и смене срока. Сервер Streamlit проверен на локальном адресе. Отдельный сквозной прогон обоих реальных архивов снова дал 3 909 insufficient и 3 909 ошибок при попытке утверждения без подтверждённых условий. AI по умолчанию выключен; живой API не проверялся. Подробности — финальная передача.
Проверки
.\.venv\Scripts\python.exe -m pytest -q
Синтетические тесты не требуют коммерческих файлов. Для отдельной проверки реальных архивов:
$env:STOCKPILOT_SOURCE_DIR = 'C:\path\to\private\archives'
.\.venv\Scripts\python.exe -m pytest tests/test_data.py::test_actual_archives_when_available -q
AppTest проверяет загрузку интерфейса, выбор, утверждение, сброс после изменения параметров и состояние ошибки. Тесты экспорта проверяют ручные и дробные количества, нулевой отказ, запрет недостаточных данных и обработку формул в CSV.
Архивы, .env, .venv, секреты и локальные журналы исключены из Git. В репозитории только синтетические примеры.
Демо за 3 минуты
В режиме «Демонстрация» выберите «Сценарий демонстрации»:
- Обзор · 8 товаров — прежний сценарий расчёта, правки, утверждения и CSV.
- Разовый крупный заказ — исключение аномалии: 5232 → 72.
- Отсутствие товара (stockout) — восстановление упущенного спроса: 0 → 72.
- Устойчивый рост спроса — учёт тренда: 192 → 336.
При смене сценария устанавливаются его синтетические данные, дата и начальные параметры; старое утверждение отменяется. Нажмите «Рассчитать заказ»: под общими показателями появятся два результата с выключенной и включённой коррекцией. Оба рассчитываются настоящим engine при одинаковых остальных параметрах. Чтобы применить коррекцию к таблице заказа, включите соответствующий флажок в «Возможностях прогноза» и пересчитайте. Изменение параметров скрывает устаревшее сравнение до пересчёта. Числа выше относятся к исходным настройкам примеров; при изменении срока или страховки они пересчитываются. Примеры используют engine_examples.py, работают без API и не подтверждают пригодность реальных выгрузок.
Контроль алгоритмов: python engine_examples.py — восемь проверок, включая 72, аномалии 5232 → 72, stockout 0 → 72, тренд 192 → 336 и неизвестный остаток. Примеры синтетические; они не разрешают сокращать реальную историю. Подробности: docs/engine_handoff.md.
Открыть деморежим → показать 4 рекомендации и одну позицию без остатка → объяснить DEMO-001 с заказом 72 → выбрать доступные → изменить количество с соблюдением кратности → утвердить → скачать CSV → изменить срок поставки и показать блокировку старого утверждения → открыть диагностику.
Авторы коммитов
История коммитов
- 2026-09-23 17:59feat: explain data quality blockers and export remediation reportNurikoks
- 2026-09-23 17:34feat: demonstrate anomaly, stockout and trend effects in UINurikoks
- 2026-09-23 17:21Delete FRONTEND_PLAN_RAMAZAN.mdTenma24
- 2026-09-23 17:05docs: record final main validation and launch instructionsNurikoks
- 2026-09-23 17:00Merge pull request #4: StockPilot integrated application and final demoNurikoks
- 2026-09-23 17:00Merge pull request #3: engine v2 and reproducible defense examplesNurikoks
- 2026-09-23 17:00Merge pull request #1: supplier data adapters and reconciliationNurikoks
- 2026-09-23 16:55chore(ui): prepare final demo with AI disabled by defaultTenma24
Все коммиты (26)
- 2026-09-23 16:51Merge remote-tracking branch 'origin/feat/engine' into feat/uiTenma24
- 2026-09-23 16:30feat(ui): add grounded AI explanations and connect engine capabilitiesTenma24
- 2026-09-23 16:30feat(data): integrate Nurasyl monthly reconciliation evidenceTenma24
- 2026-09-23 16:27feat(data): expose monthly reconciliation evidence and affected periodsNurikoks
- 2026-09-23 16:27docs(engine): publish reproducible defense cases and UI handoff contractGAPO_SABYN
- 2026-09-23 16:25Merge remote-tracking branch 'origin/feat/engine' into feat/uiTenma24
- 2026-09-23 16:05feat(engine): add regular demand algorithms and strict data applicability checksGAPO_SABYN
- 2026-09-23 15:22feat(ui): add StockPilot order review, approval and CSV exportTenma24
- 2026-09-23 15:17Merge remote-tracking branch 'origin/feat/engine' into feat/uiTenma24
- 2026-09-23 14:59fix: integrate loader scopes, seasonal profiles and explicit order constraintsGAPO_SABYN
- 2026-09-23 14:55Merge remote-tracking branch 'origin/feat/data' into feat/uiTenma24
- 2026-09-23 14:55Merge remote-tracking branch 'origin/main' into feat/uiTenma24
- 2026-09-23 14:49Merge pull request #2 from BAITC-Hacks/feat/engineTenma24
- 2026-09-23 14:46docs: add Ramazan frontend implementation planTenma24
- 2026-09-23 14:39feat: add baseline replenishment engine with 25 testsGAPO_SABYN
- 2026-09-23 14:37fix(data): validate real archives and prevent duplicate inventory and salesNurikoks
- 2026-09-23 14:25feat(data): add supplier Excel adapters and contract fixturesNurikoks
- 2026-09-23 14:10docs: add five-hour team plan and responsibilitiesTenma24
Структура репозитория (30 файлов)
.gitignore .streamlit/config.toml .streamlit/secrets.toml.example README.md TEAM_PLAN.md ai_assistant.py app.py data_loader.py demo_data.py docs/FINAL_RELEASE.md docs/ai_contract.md docs/data_notes.md docs/engine_handoff.md docs/integration_review.md docs/methodology.md docs/progress.md engine.py engine_examples.py export.py order_review.py quality_review.py requirements.txt tests/test_ai_assistant.py tests/test_data.py tests/test_demo_scenarios.py tests/test_engine.py tests/test_export.py tests/test_frontend.py tests/test_quality_review.py ui_integration.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.