EKT Assistant
Чат-консультант по каталогу ekt.kz: ищет товары через API EKT, показывает характеристики и остатки, подбирает аналоги, распознаёт спецификации из…
О проекте
Команда: Ah Shit, Here We Code Again
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: AI-консультант по каталогу ekt.kz: товары, аналоги, цены, остатки, корзина
Суть
Чат-консультант по каталогу ekt.kz: ищет товары через API EKT, показывает характеристики и остатки, подбирает аналоги, распознаёт спецификации из файлов и добавляет товары в собственную корзину после явного подтверждения.
Как устроено
Сервер на стандартной библиотеке Python читает первые 10 страниц API ekt.kz (Basic Auth на сервере) и перед ответом заново запрашивает карточку. Аналоги подбираются по совпадению ключевых характеристик (тип, полюса, ток, напряжение, характеристика срабатывания). Для диалога и разбора PDF/DOCX/XLSX/JPEG используется OpenAI Responses API. Корзина принимает только одноразовые предложения с 5-минутным сроком и повторной проверкой цены, остатка и кратности. Условия оплаты и доставки отдаются фиксированной проверенной справкой, без генерации.
Ключевые решения
- поиск по каталогу с приоритетом точного артикула
- подбор аналогов по характеристикам
- одноразовое подтверждение действий с корзиной
- извлечение позиций из документов через LLM
- демо-режим на снимке каталога
Метрики
45 unit-тестов; распознавание синтетических PDF/DOCX/XLSX/JPEG 4/4 за 1,3–2,5 с; первый полный запрос 10,3 с
Особенности
Честные границы: кандидаты на замену подаются как требующие проверки специалистом, противоречия между страницами условий доставки явно отмечаются, LLM не имеет инструментов записи в корзину. Отдельный офлайн-режим для жюри работает без ключей.
Стек
Python · vanilla JavaScript · HTML/CSS · Render
Модели
gpt-4.1-mini (OpenAI Responses API)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-71f6ba34-ah-shit-here-we-code-again.
README
README.mdEKT Assistant — HackAlem AI
Прототип консультанта по электротехнике для ekt.kz. Команда Ah Shit, Here We Code Again.
Текущий статус
Рабочий локальный прототип: реальный каталог EKT и собственная демонстрационная корзина. По сообщению команды API корзины не предоставляется, поэтому она реализована самостоятельно. Заказы в ekt.kz не отправляются; решение о соответствии такой интеграции принимает организатор.
Реализованы: поиск по первым 10 страницам каталога (репрезентативная выборка), свежие карточки и складские остатки, характеристики и ссылки на сертификаты при наличии доступного поля, предупреждение о выявленном расхождении номинального тока, контекст последних найденных товаров, адаптивный интерфейс, предложение и отдельное подтверждение добавления, актуальная ссылка на демонстрационную корзину. При подтверждении повторно проверяются цена, остаток, кратность и уже добавленное количество. Предложения одноразовые, действуют 5 минут и привязаны к сессии.
Опционально подключается OpenAI Responses API. Без API-ключа интерфейс явно показывает режим поиска по каталогу; это не выдаётся за полноценного ИИ. Подключение модели проверено с реальным ключом: HTTP 200, затем успешный ответ по карточке ekt.kz.
Добавлены загрузка PDF/DOCX/XLSX/JPEG, кандидаты на замену по совпадающим характеристикам и проверенная база условий оплаты/доставки (см. ниже). ЕЩЁ НЕ РЕАЛИЗОВАНЫ: интеграция с реальной корзиной и платформой сайта; долговременное хранение; казахский язык. Сертификат распознается только как HTTPS-ссылка в свойстве с маркером CERT/SERT/СЕРТИФ; реальные варианты этих полей требуют дополнительной проверки. Первый полный запрос занял 10,3 секунды; это единичный замер, быстродействие ещё требует проверки.
Быстрый запуск для жюри без ключей
Нужен только Python 3.10+. Из корня репозитория:
python3 server.py --demo
На Windows: py server.py --demo. Открыть http://127.0.0.1:8765 на том же компьютере. .env, аккаунт OpenAI, доступ EKT и установка зависимостей не нужны. Если порт занят, сначала остановите другой экземпляр сервера.
Границы режима: 3 позиции из снимка EKT от 23.09.2026, цены и остатки не актуальные. Интерфейс помечает их как демонстрационные. Внешние API не вызываются даже при наличии ключей в .env. Проверяются поиск, конфликт характеристик, кандидат на замену, условия покупки, подтверждение и управление корзиной. ИИ-консультация и распознавание файлов отключены — этот режим не подтверждает выполнение всех ИИ-требований кейса.
Сценарий: 200300285_ → предупреждение 160/250 А; 310100024_ → кандидат 010400569_; подготовить 2 штуки кандидата, отменить, затем подтвердить, открыть корзину, изменить на 3 и удалить. «Какая минимальная сумма заказа?» → справка. После поиска одного артикула «Есть аналог?» → проверка кандидатов.
Снимок: demo/catalog.json, источник — API EKT, дата получения 23.09.2026. Секретов и персональных данных в снимке нет. Данные не являются предложением актуальной цены/наличия.
Полный режим с реальным каталогом и ИИ
Python 3.10+ с рабочими корневыми TLS-сертификатами. Сервер и UI используют стандартную библиотеку Python и обычный JavaScript; сборка UI не требуется.
cp .env.example .env
# Заполните EKT_API_USER и EKT_API_PASSWORD доступами партнера.
# При наличии ключа заполните OPENAI_API_KEY; OPENAI_MODEL можно изменить.
python3 server.py
Откройте http://127.0.0.1:8765. Дождитесь загрузки каталога. PORT по умолчанию 8765. Доступы к каталогу в репозитории отсутствуют. Порядок предоставления тестовых доступов экспертам ещё необходимо согласовать; их получение от партнёра не гарантировано. OpenAI-режим требует действующего API-ключа и доступной модели (по умолчанию gpt-4.1-mini). До сдачи команда обязана организовать демонстрационный доступ для жюри без личных аккаунтов участников.
На macOS при ошибке проверки SSL установите корневые сертификаты для своей установки Python (обычно через поставляемый с Python Install Certificates.command). Не отключайте проверку TLS. На рабочем компьютере запуск проверен Python из окружения Codex.
Проверка сценария
- Введите
200300285_. Должны появиться карточка Legrand, остатки и предупреждение о конфликте 160/250 А в источнике. Эти значения взяты из API, а не сгенерированы. - Выберите количество и нажмите «Подготовить добавление». Корзина еще пуста.
- Нажмите «Отмена»: корзина не меняется. Повторите и нажмите «Да, добавить»: появится ссылка на /cart.
- Откройте ссылку: она показывает товары текущей сессии. В другом браузере — другая корзина.
- Попробуйте количество выше остатка: сервер отклоняет добавление. При изменении цены требует новое предложение.
python3 -m unittest discover -s tests -v
45 тестов проверяют отсутствие неявных изменений, одноразовое согласие, повторную проверку остатков, учет существующей корзины, изменение цены, истечение предложения, изоляцию сессий и некорректные количества, а также приоритет точного артикула/ID над общими словами запроса.
Архитектура и данные
static/ — адаптивный чат и страница корзины. server.py — HTTP-сервер, read-only клиент ekt.kz, поиск, необязательный клиент OpenAI и серверные операции корзины. tests/ — проверки правил корзины. docs/ — требования и архитектура.
API каталога: https://ekt.kz/api/products?page=1 и https://ekt.kz/api/products/detail?id=515291. Basic Auth только на сервере. Поиск ограничен 10 страницами; неизвестный товар не означает, что его нет во всем каталоге. Перед ответом и подтверждением карточки запрашиваются заново. Снимок данных актуален только на момент запроса; корзина ничего не резервирует.
Сессии, история и корзины находятся в памяти, истекают через 2 часа бездействия и теряются после перезапуска. Сервер слушает только 127.0.0.1, предназначен для локальной демонстрации. Публичное размещение требует HTTPS, защищенных cookies, ограничения запросов и production-сервера. Платежные данные не запрашиваются. История не записывается на диск; при включении модели последние сообщения и найденные карточки передаются в OpenAI с store=false. Не вводите в демонстрацию конфиденциальные сведения.
.env исключён из Git. Не включайте ключи в коммиты, скриншоты или README. Для ИИ использован API по официальной документации: https://developers.openai.com/api/docs/quickstart . Код создан командой с помощью Codex; приложение использует стандартную библиотеку Python; распознавание документов выполняет OpenAI. Для генерации синтетических файлов при разработке использовались python-docx, openpyxl, reportlab и Pillow (для запуска приложения они не нужны).
Спецификации и фото
В чате выберите PDF, DOCX, XLSX или JPEG до 2 МБ, подтвердите передачу выбранного файла в OpenAI и нажмите «Разобрать файл». Файл передаётся через Responses API в памяти, с store=false; приложение не сохраняет его на диск. Это не означает нулевое хранение на стороне провайдера — применяются его условия обработки данных. DOC и XLS нужно предварительно сохранить как DOCX/XLSX. Файлы с паролем и макросами не поддерживаются.
Распознаются первые до 8 позиций. Проверьте/исправьте артикул в распознанной строке и нажмите «Найти». Количество отображается как текст из документа, не переносится автоматически в корзину. Это сознательная граница: единицы и распознавание нужно проверить. При ошибке API выводится сообщение, результаты не выдумываются. Файл может содержать команды: модель получает указание считать содержимое только данными; инструментов записи у неё нет.
Проверено на синтетических PDF, DOCX, XLSX и JPEG: каждый содержал артикул 200300285_, количество 2. Все четыре формата распознаны верно, разовые запросы заняли 1,3–2,5 с. Это не оценка точности на произвольных документах, сложные таблицы и плохие фотографии требуют дополнительных испытаний.
Подбор замены
Для отсутствующего товара или запроса «аналог» проверяются до 12 кандидатов из выборки; показываются до двух доступных позиций. Остатки кандидатов запрашиваются заново. Электроаппараты сравниваются по типу, полюсам, току, напряжению и, при наличии, характеристике срабатывания и току утечки. Светильники — по типу, цоколю, монтажу и источнику света. Отсутствие обязательного поля, расхождение значения или предупреждение о конфликте исключают кандидата.
Это кандидаты для проверки специалистом, не гарантия взаимозаменяемости: отключающая способность, габариты и прочие неохваченные параметры требуют проверки. Для иных категорий или отсутствия совпадений ассистент честно сообщает, что подтверждённая замена не найдена. Критерий хакатона «минимум один аналог» пока не гарантируется для любого товара.
Реальный проверенный пример: 310100024_ отсутствует; 010400569_ доступен, совпадают 1 полюс, 20 А, 230 В и характеристика C. Товар другого бренда, что явно отмечается. Остатки могут изменяться.
Условия покупки
Документ участника docs/purchase-conditions.md включён с сохранением его коммита. Источники повторно проверены 23.09.2026: https://ekt.kz/checkout-delivery/ и https://ekt.kz/about/howto/. Для общих вопросов об оплате/доставке используется фиксированная проверенная справка со ссылками, без генерации условий. Страницы противоречат друг другу по порогу бесплатной доставки и срокам; действующая редакция неизвестна, требуется уточнение у менеджера. Минимальная сумма заказа не подтверждена. Это снимок источников на дату проверки, не автоматическая синхронизация.
При проверке через интерфейс модель один раз опустила конечное подчёркивание артикула. Поэтому поиск допускает его восстановление только при единственном полном совпадении кода, а распознанная строка остаётся редактируемой.
Собственная корзина
Команда реализует корзину самостоятельно, без API корзины EKT. Каталог продолжает использовать реальные данные партнёра. Корзина поддерживает отдельное подтверждение добавления и изменения количества, удаление с подтверждением и итог по сохранённым ценам без доставки. При изменении количества сервер повторно проверяет цену, кратность и остаток. Устаревшее предложение изменения не перезаписывает новое количество; удаление аннулирует предложения по этой позиции. При неизвестной цене полный итог не вычисляется.
Это локальная корзина прототипа: не резервирует товар, не принимает оплату и не отправляет заказ в EKT. Сохраняется при обновлении страницы в той же сессии, но теряется при перезапуске сервера. Проверены 45 автоматических тестов и HTTP-сценарий добавления, изменения, расчёта и удаления с синтетическим каталогом.
Запуск на Windows
Установите Python 3.10+ и убедитесь, что команда py --version работает в новом терминале. В папке проекта выполните в PowerShell:
Copy-Item .env.example .env
# Заполните .env серверными доступами, не публикуйте его.
py server.py
Если py недоступна, но python --version работает, используйте python server.py. Откройте http://127.0.0.1:8765 на том же компьютере. Чужая ссылка localhost не открывает приложение на компьютере другого участника.
Проверки диалога перед сдачей
- «Какая минимальная сумма заказа?» → справка о неизвестной общей минимальной сумме, а не сообщение о ненайденном товаре.
- Найти конкретный артикул, затем спросить «Есть аналог?» → поиск замены для этого товара, без изменения корзины.
- Если ранее найдено несколько товаров, короткий вопрос об аналоге должен вызвать просьбу уточнить артикул.
- Предложенные замены не вытесняют исходный товар из контекста последующих уточнений.
В набор включены 6 регрессионных проверок этих маршрутов. Ручные результаты участницы хранятся отдельно и не подменяются результатами автоматических тестов.
Ссылка для жюри и размещение
Конфигурация render.yaml готовит защищённую демонстрацию на Render Free. Инструкция — docs/deployment.md. Публичный режим требует отдельный код доступа и выставляет Secure cookie; ключи EKT/OpenAI находятся только в настройках сервера. Само наличие конфигурации не означает, что сайт уже опубликован. После успешного размещения команда должна добавить фактическую HTTPS-ссылку в сдачу и передать жюри логин jury с отдельным кодом через закрытый канал.
Автоматические deploy отключены. Бесплатный сервис может засыпать, при перезапуске корзины и счётчики теряются. Реализация рассчитана на ограниченную демонстрацию, не массовый интернет-магазин.
Авторы коммитов
История коммитов
- 2026-09-23 17:29feat: prepare protected Render demo deploymentSayan
- 2026-09-23 17:14feat: add explicit offline demo for repository reviewSayan
- 2026-09-23 17:11fix: route purchase questions and preserve product contextSayan
- 2026-09-23 17:01docs: обновить отчёт о тестированииseriksamira1003-bit
- 2026-09-23 16:37Merge branch 'main' of https://github.com/BAITC-Hacks/hack-71f6ba34-ah-shit-here-we-code-againSayan
- 2026-09-23 16:34Merge pull request #2 from BAITC-Hacks/docs/test-report-seriksamira1003-bit
- 2026-09-23 16:32feat: add quantity editing and totals to standalone cartSayan
- 2026-09-23 16:28docs: добавить отчёт о тестированииseriksamira1003-bit
Все коммиты (15)
- 2026-09-23 16:11Merge branch 'main' of https://github.com/BAITC-Hacks/hack-71f6ba34-ah-shit-here-we-code-againSayan
- 2026-09-23 16:09feat: recognize specifications and suggest catalog alternativesSayan
- 2026-09-23 15:43Merge pull request #1 from BAITC-Hacks/docs/purchase-conditionsAlisher077s
- 2026-09-23 15:38docs: add verified purchase conditions.Alisher077s
- 2026-09-23 14:48fix: prioritize exact catalog matches and verify AI connectionSayan
- 2026-09-23 14:19feat: add live EKT catalog prototype and confirmed demo cartSayan
- 2026-09-23 14:07docs: record EKT requirements and implementation architectureSayan
Структура репозитория (23 файлов)
.env.example .gitignore README.md analogs.py demo/catalog.json docs/architecture.md docs/deployment.md docs/purchase-conditions.md docs/requirements.md docs/test-report.md hosting_guard.py render.yaml server.py static/app.js static/index.html static/style.css tests/test_cart.py tests/test_chat_routing.py tests/test_demo.py tests/test_documents_analogs.py tests/test_hosting_guard.py tests/test_search.py uploads.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.