О проекте
Команда: ApexAI
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: AI-консультант по каталогу ekt.kz: товары, аналоги, цены, остатки, корзина
Суть
Чат-консультант по каталогу ekt.kz: поиск по артикулу и параметрам, подбор аналогов, голосовой ввод, поиск по фото и документам, корзина с подтверждением и проверкой остатка.
Как устроено
Браузер (vanilla JS) → Python HTTP-сервер → адаптер catalog.py к read-only API ekt.kz (Basic Auth, пагинация до 100 страниц, догрузка карточки с остатками по складам) и OpenAI Responses API. Корзина в SQLite, менять её может только серверный код, модели доступ на запись не дан. Товар добавляется в два шага: модель предлагает, пользователь подтверждает, остаток проверяется ещё раз. Кратность берётся из KRATNOST_MIN. Если API недоступен, включается явно помеченный демокаталог.
Ключевые решения
- OpenAI Responses API
- speech-to-text
- распознавание маркировки на фото (vision)
- анализ PDF/DOCX/XLSX
- двухшаговое подтверждение корзины
- адаптер live/demo/auto с fallback
Особенности
Модель не может менять корзину: запись делает только сервер после явного «Да» и повторной проверки остатка. Интеграция проверена на реальном API ekt.kz (товар 515291). Фото и документы уходят в OpenAI только по отдельной кнопке, это экономит платные вызовы.
Стек
Python · SQLite · JavaScript · HTML/CSS · Render
Модели
OpenAI Responses API · OpenAI speech-to-text
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-9f858e1f-apexai.
README
README.mdEKT AI Assistant
Прототип команды ApexAI для HackAlem AI: ИИ-консультант по электротехнике для сайта ekt.kz. Ищет товары в каталоге партнёра, помогает разобрать запрос голосом, по фото или по документу и предлагает локальный список покупок с явным подтверждением.
Что умеет проект
- Искать электротехнические товары по артикулу, названию и параметрам; показывать данные каталога EKT.
- Находить кандидатов на замену с объяснением совпадающих параметров. Совместимость нужно дополнительно проверить.
- Принимать голосовой запрос: запись отправляется на распознавание после остановки, текст можно проверить перед отправкой.
- Прикреплять PDF, Word, Excel и JPEG. Пользователь сам нажимает отдельную кнопку анализа; документы и фото отправляются в OpenAI только после этого явного действия.
- Предлагать вопросы о кабеле, монтаже и сертификате после выбора товара. Эти подсказки не добавляют ничего в корзину.
- Добавлять товар в локальный список покупок только после отдельного подтверждения и повторной проверки остатка.
- Показывать официальные контакты EKT.
Цены, наличие и карточки товаров берутся из ответа EKT или помеченного демокаталога. Ассистент не оформляет заказ и не принимает оплату: API партнёра доступен только для чтения.
Запуск
Нужен Python 3.10 или новее. Внешние Python/JavaScript зависимости для этой версии не нужны.
cp .env.example .env
# Заполните EKT_USER и EKT_PASSWORD из документа партнёра.
# Для ответов модели добавьте OPENAI_API_KEY. Ключ не отправлять в чат и не коммитить.
python3 server.py
Ключ можно ввести без отображения в терминале командой python3 setup_key.py, затем перезапустить сервер.
Открыть http://127.0.0.1:8766. По умолчанию сервер доступен только на этом компьютере (HOST=127.0.0.1), порт — 8766.
Для автономного показа: EKT_MODE=demo python3 server.py.
В режиме auto ошибка API включает явно обозначенный демонстрационный каталог. EKT_MODE=live запрещает fallback. Важно: после смены .env сервер нужно перезапустить.
Источники данных
Документ партнёра предоставляет Basic Auth и только read-only endpoints:
https://ekt.kz/api/productshttps://ekt.kz/api/products?page=2и следующие страницыhttps://ekt.kz/api/products/detail?id=515291
catalog.py загружает страницы до конца/повторения/100 страниц, отражает полноту загрузки в статусе, перепроверяет карточку при подтверждении. Неизвестная схема или сетевой сбой не превращаются в нулевую цену или выдуманный остаток. 23 сентября 2026 после первоначальных таймаутов успешно проверены реальные список и карточка товара 515291: цена 64 920 ₸, quantity=23, stores с остатками по складам. Загружены первые 100 страниц (2000 товаров); это часть каталога. В списке нет остатков: карточка догружается перед показом наличия, подбором аналога и операцией корзины. Минимальная кратность берётся из properties.KRATNOST_MIN.
data/demo.json — четыре демонстрационные позиции, перенесённые из исходного прототипа; не актуальные цены/остатки магазина. data/demo-policy.json — отдельно помеченные синтетические условия покупки. Раздел 6 задания разрешает синтетические данные для прототипа. В live-режиме условия ekt.kz не выдумываются: партнёр должен предоставить подтверждённую политику оплаты/доставки/минимальной партии.
Архитектура
Браузер (index.html, app.js, styles.css) → Python HTTP API (server.py) → EKT adapter (catalog.py) / OpenAI Responses API. SQLite в .runtime/cart.sqlite3 хранит корзины, ожидающие подтверждения предложения и ограниченный контекст. Корзину меняет только код сервера, модель доступа к записи не имеет.
Секреты — локальная .env или переменные окружения. .env и .runtime/ исключены из Git. Не использовать python -m http.server в корне проекта: запускайте только server.py, который отдаёт ограниченный список публичных файлов.
Документация OpenAI: https://developers.openai.com/api/reference/cli/resources/responses/methods/create
Проверка
python3 -m unittest discover -s tests -v
Тесты покрывают поиск, аналоги, подтверждение корзины и складские ограничения, документы и голосовой запрос, изоляцию сессий, контракт API и защиту сервера.
Сценарий показа в деморежиме:
- «Есть ли 027228?» → карточка: 23 шт., 64 920 ₸.
- «Подбери аналог LED STARK 30W» → исходный товар отсутствует, предложен светильник 30W/2400Lm/4000K/IP20; автоматический выключатель не предлагается.
- «Какие условия доставки и оплаты?» → явно помеченные демонстрационные условия.
- «Добавь 23 шт 027228» → до подтверждения корзина пуста.
- «Да, добавь» → 23 шт.; ссылка открывает ту же корзину. Обновить страницу — позиции сохраняются.
- «Добавь 1 шт 027228» → отказ: суммарное количество превысит 23.
- Новый запрос или «Отмена» не подтверждают старое предложение.
Границы версии и интеграция
Это рабочая корзина прототипа, не корзина производственного ekt.kz. Партнёр не предоставил write API, механизм авторизации корзины или контракт checkout. Ссылка на внешний ekt.kz не переносит товары и не создаёт заказ. CSV позволяет передать список вручную. Для внедрения нужен серверный адаптер к официальному API корзины, с сохранением явного подтверждения и проверок остатка.
23 сентября 2026 проверен настоящий вызов OpenAI Responses API с локальным ключом, затем сквозной запрос через /api/chat на работающем сервере: «Характеристики 027228». Модель вернула описание Legrand DRX250 MT, 3 полюса, 160 А, 18 кА, 400 В AC по реальной карточке EKT. Проверка выполнена отдельно от 16 автоматических тестов с имитацией внешних API. Для запуска на другом компьютере нужен собственный OPENAI_API_KEY; ключи и локальная база в репозиторий не входят.
Можно прикрепить до пяти файлов PDF, Word, Excel или JPEG размером до 6 МБ каждый. Они сохраняются только в локальной .runtime/ и не выдаются HTTP-сервером; для PDF/DOCX/XLSX доступен небольшой ознакомительный фрагмент. После загрузки JPEG пользователь может явно нажать «Найти товар по фото»: OpenAI извлекает видимую маркировку и ищет её в каталоге. На это выполняется один платный запрос к OpenAI; без явного нажатия изображение туда не отправляется. Не загружайте платёжные данные. Поиск без LLM консервативный; для свободных формулировок требуется ключ. Нет бронирования складского остатка, оплаты или создания заказа. База хранит локальный контекст, без аккаунтов и синхронизации устройств. SQLite рассчитана на один процесс; текущая блокировка сериализует запросы. HTTP-сервер предназначен для локального хакатонного показа. Перед публичным размещением нужны production-сервер, HTTPS/Secure cookies, лимиты запросов, сроки удаления сессий, мониторинг и подтверждённые интеграционные контракты.
У PDF, Word и Excel после загрузки есть отдельная кнопка «Анализировать». Только это явное действие отправляет последний прикреплённый документ в OpenAI и расходует API-кредит. Ассистент извлекает видимые артикулы и параметры, не придумывает наличие/цену и показывает карточки только из каталога EKT. PDF отправляется с экономным уровнем детализации low.
Голосовая запись ограничена 10 МБ, поддерживаются WebM, MP3, M4A, WAV и MP4. Она не хранится на диске и не отправляется до явного завершения записи пользователем. Распознанный текст сначала помещается в поле ввода — пользователь может его исправить и лишь потом отправить запрос. Официальная документация по распознаванию: https://developers.openai.com/api/docs/guides/speech-to-text
Публикация для жюри
Для публикации подготовлен render.yaml (Render Blueprint, Python, тариф Free). Публичная ссылка появится после создания Blueprint в Render:
- Войти в Render и выбрать New → Blueprint.
- Подключить GitHub, выбрать
BAITC-Hacks/hack-9f858e1f-apexai, веткуmain. - Применить Blueprint из
render.yamlи ввести значенияOPENAI_API_KEY,EKT_USER,EKT_PASSWORDв защищённые поля Render. OpenAI-ключ берётся из OpenAI Platform, доступ к EKT API — из документов партнёра. Не добавляйте их в GitHub и не отправляйте в чат. - Дождаться успешного Deploy; Render покажет публичный адрес
*.onrender.com.
Публичная ссылка появится после успешного Deploy. Для этого нужен вход в аккаунт Render и подключение приватного GitHub-репозитория; секреты вводятся в Render Dashboard напрямую.
Бесплатный Render-сервис засыпает после 15 минут без запросов и его локальные файлы теряются при перезапуске/сне. Поэтому SQLite-корзина и загруженные документы на Free-тарифе временные; при пробуждении сайт может загружаться около минуты. Это демо-размещение, не постоянная база заказов. Ограничения бесплатного тарифа Render.
Учитывайте: после настройки OPENAI_API_KEY публичные посетители смогут вызывать ИИ и расходовать API-кредит. Следите за лимитами расходов OpenAI. HTTPS для Render Web Service настраивается платформой автоматически.
Авторы коммитов
История коммитов
- 2026-09-23 17:50Document Render deployment for jury demoMeruert Umarova
- 2026-09-23 17:48Polish project README and hosting notesMeruert Umarova
- 2026-09-23 17:44Add Central Asian countries and English UI and assistant supportunarzhaneskendirova-cmyk
- 2026-09-23 17:39Add EKT branding and first-visit country and language preferencesunarzhaneskendirova-cmyk
- 2026-09-23 17:37Update README.mdsymbat
- 2026-09-23 17:35Add free Render deployment configuration for EKT demounarzhaneskendirova-cmyk
- 2026-09-23 17:33Rename website and browser title to EKTunarzhaneskendirova-cmyk
- 2026-09-23 17:31Keep cart in normal flow so it cannot cover contact detailsunarzhaneskendirova-cmyk
Все коммиты (21)
- 2026-09-23 17:30Make consultant greet users and preserve clarifying dialogueunarzhaneskendirova-cmyk
- 2026-09-23 17:20Add official EKT contact section with phone, email and social linksunarzhaneskendirova-cmyk
- 2026-09-23 17:17Add explicit document analysisMeruert Umarova
- 2026-09-23 17:03Add editorial EKT storefront inspired by Lacoste compositionunarzhaneskendirova-cmyk
- 2026-09-23 16:56Add voice SOS query and companion promptsMeruert Umarova
- 2026-09-23 16:53Redesign assistant workspace with refined typography and responsive cartunarzhaneskendirova-cmyk
- 2026-09-23 16:33Add photo-based product lookupMeruert Umarova
- 2026-09-23 16:03Add local document uploads to assistantMeruert Umarova
- 2026-09-23 15:39Merge pull request #1 from BAITC-Hacks/codex/ekt-catalog-confirmed-cartunarzhaneskendirova-cmyk
- 2026-09-23 15:34Document verified OpenAI integration and secure local key setupunarzhaneskendirova-cmyk
- 2026-09-23 15:18Add live EKT catalog adapter and persistent confirmed cartunarzhaneskendirova-cmyk
- 2026-09-23 14:05Handle explicit item quantities safelyMeruert Umarova
- 2026-09-23 14:05Build ekt AI shopping assistant prototypeMeruert Umarova
Структура репозитория (14 файлов)
.env.example .gitignore README.md app.js catalog.py data/demo-policy.json data/demo.json index.html render.yaml server.py setup_key.py styles.css tests/test_app.py translations-en.json
Ветки (2)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.