О проекте
Команда: Miras and Dastan
Кейс HackAlem.ai: Логистика — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: Автоматический расчёт заказов поставщикам для пополнения склада, с утверждением менеджером
Суть
Веб-продукт для расчёта заказов поставщикам. Из истории продаж, остатков, товаров в пути и условий поставщиков он делает объяснимые рекомендации по пополнению, собирает черновики заказов по поставщикам для согласования и проверяет прогноз на истории.
Как устроено
Выбросы (разовые крупные продажи) отсекаются по IQR и modified Z-score и заменяются регулярным уровнем. Прогноз строится взвешенным скользящим средним за 8 недель. Страховой запас считается как z·σ·√lead time, дальше точка заказа, целевой запас минус позиция и округление под MOQ и кратность упаковки. Черновик заказа группируется по поставщику, экспортируется в CSV или текст письма и требует пересмотра при изменении расчёта. ИИ-агент на OpenAI Responses API с function calling вызывает серверные детерминированные инструменты, сам количества не считает. Модуль stockpilot-backtest сравнивает этот прогноз с обычным средним.
Ключевые решения
- IQR + modified Z-score
- weighted moving average
- safety stock
- reorder point
- MOQ/pack size
- backtest
- OpenAI Responses API function calling
- сценарии задержки поставки
Особенности
LLM отделена от расчётов: количества считает только детерминированный движок, модель выбирает инструменты и объясняет. Если после сценария меняется расчёт, черновик блокируется до пересборки, поэтому подмена не проходит незаметно. Импорт принимает только продажи, недостающие склады не выдумываются.
Стек
Next.js · React · TypeScript · pnpm · Vite · Vitest
Модели
OpenAI (например gpt-4.1-mini)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-9b68f051-miras-and-dastan.
README
README.mdStockPilot AI
Hackathon-ready веб-продукт для кейса «Автоматический расчёт заказов поставщикам для пополнения склада» компании «Электрокомплект».
Hackathon team repository for Miras and Dastan.
Что решает
StockPilot AI превращает историю продаж, остатки, товар в пути и условия поставщиков в объяснимые рекомендации по пополнению. Разовые крупные продажи выявляются как выбросы и не раздувают регулярный прогноз.
Главное
- Детерминированные TypeScript-расчёты: IQR + modified Z-score, взвешенное скользящее среднее, safety stock, reorder point, MOQ и pack size.
- Воспроизводимый демонабор: 32 SKU, до 36 недель истории, поставщики, товары в пути и кейс
CAB-NYM-3X2.5с продажей 176 шт. УSOCKET-FLOOR8 недель; уSURGE-3Pнет поставщика. - Семь рабочих разделов: «Обзор», «Рекомендации», «ИИ-агент», «Проверка на истории», «Сценарии», «Черновики заказов», «Данные». Раздел отражается в URL; набор данных, поиск и параметры сохраняются при переходах.
- Полная таблица с поиском, фильтрами, сортировкой, пагинацией и выбором допустимых строк. Карточка товара показывает график исходных/очищенных продаж и объяснение количества.
- Импорт продаж
.xlsx,.xls, UTF-8.csv: файл → колонки → проверка → подтверждение. Предпросмотр таблицей, реальные счётчики ошибок и явное подтверждение исключения некорректных строк. - Черновик из выбранных допустимых позиций с группировкой по поставщику, безопасным CSV и копированием текста письма. Изменение расчёта требует пересмотра черновика; заказ автоматически не отправляется.
- Историческое сравнение обычного среднего и основного прогноза StockPilot через существующий модуль
stockpilot-backtest. - Demo Mode работает без API key. С настроенными ключом и моделью «ИИ-агент» использует OpenAI Responses API с function calling: выбирает серверные инструменты для сводки, объяснения SKU, плана и сценария. Количества вычисляет детерминированный движок, не модель. В карточке товара также сохранено AI-объяснение.
Архитектура
React UI → /api/agent + /api/agent/stream → OpenAI Responses API → разрешённые tools → deterministic analytics in lib/analytics.
LLM не видит исходный Excel и не производит количественные расчёты. Внешнему API передаются вопрос и результаты инструментов; нормализованный набор для расчёта хранится в памяти сервера в изолированной сессии. API key остаётся на сервере; store: false включён.
Запуск
В корне используется существующий pnpm-lock.yaml:
pnpm install --frozen-lockfile
pnpm dev
Для необязательного AI-объяснения скопируйте .env.example в .env.local и задайте ключ. Без ключа демонстрация и расчёты работают полностью. Не добавляйте .env.local в git.
Проверки:
pnpm run typecheck
pnpm run lint
pnpm test
pnpm run build
Переменные окружения
OPENAI_API_KEY— необязательный ключ. При его отсутствии включается Demo Mode.OPENAI_MODEL— имя доступной text-модели (для агента обязательно вместе с ключом).
Режим объяснения не меняет источник данных: интерфейс отдельно обозначает демонабор или импортированный файл. При ошибке внешнего сервиса показывается ошибка; расчётное объяснение остаётся доступно.
Формулы и ограничения
- Выбросы: IQR и modified Z-score. Они заменяются средней регулярной продажей в cleaned series.
- Прогноз: weighted moving average по последним 8 неделям.
- Safety stock:
z × σ спроса × √lead time. - Reorder point: спрос на lead time + safety stock.
- Рекомендация: target stock − stock position, после чего применяется MOQ и кратность упаковки.
Это MVP принятия решений. В production нужны согласованные уровни сервиса, проверка исходных данных, ассортиментные ограничения и бизнес-валидация формул.
Сценарий демонстрации
- Нажмите «Открыть демо». В «Обзоре» показаны вычисленные приоритеты и первые рабочие строки.
- В «Рекомендациях» найдите
CAB-NYM-3X2.5и нажмите название товара. В базовом сценарии рекомендовано 50 шт.; разовая продажа 176 шт. отмечена на графике. Покажите цепочку от целевого запаса и позиции до итогового количества. - Закройте карточку. В «Сценариях» установите «Дополнительная задержка, дней» = 7, нажмите «Применить сценарий». Рекомендация для кабеля становится 70 шт., исходные продажи не меняются.
- Вернитесь в «Рекомендации», выберите checkbox только у
CAB-NYM-3X2.5и нажмите «Создать черновик». В «Черновиках заказов» проверьте единственную выбранную позицию, поставщика, количество и сумму. - Нажмите «Скачать CSV» либо скопируйте текст письма. Это подготовка к согласованию, не отправка заказа.
- Измените задержку на 14 дней и примените сценарий. Прежний черновик помечается как требующий пересмотра; экспорт заблокирован до действия «Пересобрать по текущему расчёту». Его состав не подменяется незаметно.
- Откройте «Проверка на истории», выберите товар, проверьте период, начальный запас и условия, затем нажмите «Запустить сравнение». Покажите линии запаса, проигрывание по неделям и фактические итоги обеих стратегий.
50/70 шт. — результаты закреплённого демонабора и сценариев, а не числа, встроенные в UI.
Импорт и хранение данных
Импорт открывается с начального экрана («Импортировать Excel / CSV») и из «Данных» («Импортировать данные»). Используется первый лист; заголовки должны быть в первой строке. Обязательны дата, SKU и количество; без названия отображается SKU.
Поддерживаются даты ГГГГ-ММ-ДД, ДД.ММ.ГГГГ и числовые даты Excel. Невозможная дата, пустое количество или отрицательное значение не принимаются. Явный 0 допускается. CSV должен быть UTF-8 с BOM или без него. Ограничение — 10 МБ и 100 000 строк.
Импортируются только продажи. Остатки, резервы, поставки и поставщики не создаются из предположений и не копируются из демо. Для такого набора закупочные действия заблокированы; неизвестные складские показатели не показаны как подтверждённые нули. Неудачный или отменённый импорт не заменяет текущие данные.
Для недельного прогноза и исторического сравнения нужна одна строка на SKU за каждую последовательную неделю с шагом 7 дней. Дневные продажи, дубли и разрывы требуют подготовки файла. Неизвестные недели не заполняются нулями. Исключение ошибочных строк требует явного подтверждения неполноты истории.
Тестовый файл: tests/fixtures/sales-import.csv. В нём 9 строк: 8 корректных недель и 1 ошибочная дата. Ожидаемая проверка — 8 принятых и 1 отклонённая строка.
Данные и один активный черновик находятся в памяти вкладки. Перезагрузка очищает их. При открытии ИИ-агента набор передаётся в серверную сессию в памяти с ограниченным временем жизни. Постоянное серверное сохранение, автоматический localStorage, отправка писем и ERP-интеграция не реализованы.
Что проверяется на истории
В основном приложении createStockPilotStrategy использует настоящие detectOutliers, weightedForecast, stdDev, mean из lib/analytics.ts. Стратегии называются «Обычное среднее» и «StockPilot · основной прогноз». Они получают только завершённую историю до недели решения и используют общую политику пополнения.
Это сравнение прогнозов при одинаковых правилах закупки, а не проверка всей системы с бюджетным отбором и выбором поставщика. Начальный запас — допущение эксперимента; коммерческие условия — текущие допущения, а не восстановленные исторические договоры. Параметры раздела «Сценарии» не переносятся в отдельный исторический эксперимент.
Если цена неизвестна, стоимости не вычисляются. Итоги всего периода отделены от текущей недели проигрывания, изменение доли обслуживания выражается в процентных пунктах. Скрытый спрос при историческом отсутствии товара неизвестен: продажи используются как его приближение.
Независимый модуль сохраняет собственный запуск и существующий package-lock.json:
cd stockpilot-backtest
npm ci
npm run dev
Там доступны шесть отдельных демонаборов и встроенная демонстрационная стратегия; основной прогноз подключается через публичные интерфейсы. Источники имеют отдельные метки. Подробнее: INTEGRATION.md.
Проверки из директории модуля:
npm run typecheck
npm run lint
npm test
npm run build
Сохранение математического поведения
Редизайн сохраняет генератор демоданных и ядро симуляции. Интеграция агента дополнительно запрещает закупку при неизвестных остатках и трактует явный бюджет 0 как отсутствие бюджета, а не безлимит. Полный результат трёх фиксированных сценариев сравнивается с исходным коммитом 09ff771 в регрессионных тестах.
Существующие ограничения также сохранены: очистка может не найти всплеск в плоском ряду с нулевыми IQR/MAD, а некоторые комбинации MOQ и упаковки дают несовместимое количество. Интерфейс блокирует оформление количества, не соответствующего условиям; исправление модели должно быть отдельной задачей.
Эвристическая оценка оснований не является измеренной точностью. Уменьшение стоимости плана не доказывает прибыль или улучшение обслуживания. estimatedStockoutDate — прогнозируемая дата дефицита, не дата прибытия заказа.
Подробности проверок: REDESIGN_VERIFICATION.md.
Проверка реального ИИ
- Настройте
.env.local:OPENAI_API_KEYиOPENAI_MODEL(например,gpt-4.1-mini). Перезапустите сервер. - Откройте демо → «ИИ-агент» → «Что требует внимания?».
- Дождитесь ответа и метки
OpenAI · <модель>. В журнале видны фактически вызванные инструменты. Без настройки отображается локальный тестовый режим.
Данные агентной сессии не переживают перезапуск сервера. NVIDIA-review пока недоступен без подключения отдельного адаптера; агент честно сообщает об этом. Agent drafts пока не связаны с экспортом UI: для CSV используйте «Рекомендации» → «Черновики заказов». Подробнее: OPENAI_INTEGRATION.md.
Авторы коммитов
История коммитов
- 2026-09-23 17:24Merge latest procurement workspace and expose OpenAI agentStockPilot AI
- 2026-09-23 17:15Add server-side procurement agent with verified calculation toolsStockPilot AI
- 2026-09-23 16:33Merge procurement redesign into main preserving latest teammate integrationDastan
- 2026-09-23 16:29Redesign StockPilot procurement workspace and complete validated demo flowDastan
- 2026-09-23 15:51Create еннрDastan
- 2026-09-23 15:28Create привет мирасDastan
- 2026-09-23 14:46Delete приветDastan
- 2026-09-23 14:42Create приветDastan
Все коммиты (18)
- 2026-09-23 14:25feat: add StockPilot AI procurement prototypeDastan
- 2026-09-23 13:38Update README.mdDastan
- 2026-09-23 16:14Merge pull request #1 from BAITC-Hacks/codex/stockpilot-backtest845yfjy6m8-crypto
- 2026-09-23 15:56Connect backtest UI and add data selection navigation845yfjy6m8-crypto
- 2026-09-23 15:52Delete еннр845yfjy6m8-crypto
- 2026-09-23 15:28Delete привет мирас845yfjy6m8-crypto
- 2026-09-23 15:02Add isolated StockPilot backtest module and integration adapters845yfjy6m8-crypto
- 2026-09-23 14:23Delete BacktestPanel.tsx845yfjy6m8-crypto
- 2026-09-23 14:16Create BacktestPanel.tsx845yfjy6m8-crypto
- 2026-09-23 14:14Update README.md845yfjy6m8-crypto
Структура репозитория (98 файлов)
.env.example .gitignore AGENTS.md IMPLEMENTATION_PLAN.md README.md REDESIGN_VERIFICATION.md app/api/agent/route.ts app/api/agent/stream/route.ts app/globals.css app/layout.tsx app/page.tsx components/DraftPanel.tsx components/HistoryPanel.tsx components/ImportPanel.module.css components/ImportPanel.tsx components/PreviewBacktest.module.css components/PreviewBacktest.tsx components/PreviewNavigation.module.css components/PreviewNavigation.tsx components/PurchaseApiPanel.module.css components/PurchaseApiPanel.tsx components/RecommendationsTable.tsx components/ScenarioPanel.tsx components/SkuDrawer.module.css components/SkuDrawer.tsx components/Workspace.module.css components/openai/AgentWorkspace.module.css components/openai/AgentWorkspace.tsx components/ui.module.css components/ui.tsx docs/OPENAI_INTEGRATION.md docs/WORKSPACE_NAVIGATION.md eslint.config.mjs hooks/useSection.ts lib/analytics.ts lib/demo-data.ts lib/import-data.ts lib/navigation.ts lib/openai/adapters/nvidia.ts lib/openai/config.ts lib/openai/contracts.ts lib/openai/orchestrator.ts lib/openai/session/store.ts lib/openai/tool-registry.ts lib/presentation.ts lib/sku-presentation.ts lib/types.ts next-env.d.ts next.config.ts package.json pnpm-lock.yaml pnpm-workspace.yaml stockpilot-backtest/.gitignore stockpilot-backtest/.npmrc stockpilot-backtest/FILES_CREATED.txt stockpilot-backtest/IMPLEMENTATION_PLAN.md stockpilot-backtest/INTEGRATION.md stockpilot-backtest/README.md stockpilot-backtest/VERIFICATION.md stockpilot-backtest/data/demo/generate.ts stockpilot-backtest/data/demo/observations.json stockpilot-backtest/eslint.config.js stockpilot-backtest/examples/StockPilotBacktestBridge.tsx.example stockpilot-backtest/index.html stockpilot-backtest/package-lock.json stockpilot-backtest/package.json stockpilot-backtest/src/BacktestPanel.module.css stockpilot-backtest/src/BacktestPanel.module.css.d.ts stockpilot-backtest/src/BacktestPanel.tsx stockpilot-backtest/src/adapter.ts stockpilot-backtest/src/contracts.ts stockpilot-backtest/src/core.ts stockpilot-backtest/src/csv.ts stockpilot-backtest/src/engine.ts stockpilot-backtest/src/index.ts stockpilot-backtest/src/main.tsx stockpilot-backtest/src/standalone.css stockpilot-backtest/src/stockpilot.ts stockpilot-backtest/src/strategies.ts stockpilot-backtest/tests/backtest.checks.ts stockpilot-backtest/tests/panel.checks.ts stockpilot-backtest/tests/stockpilot.checks.ts stockpilot-backtest/tsconfig.json stockpilot-backtest/vite.config.mjs stockpilot-backtest/vitest.config.mjs tests/agent-route.test.ts tests/analytics.test.ts tests/backtest-integration.test.ts tests/fixtures/sales-import.csv tests/forecast-integration.test.ts tests/import-data.test.ts tests/navigation.test.ts tests/openai/orchestrator.test.ts tests/openai/safety.test.ts tests/openai/tools.test.ts tests/presentation.test.ts tests/sku-presentation.test.ts tsconfig.json
Ветки (2)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.