AAYMA
RU
Войти

EKT · Консультант по каталогу

Чат-консультант по каталогу электротехники ekt.kz.

Рабочий MVP
Команда «Олжасхан» 13💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Олжасхан
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Рабочий MVP

Задача кейса: AI-консультант по каталогу ekt.kz: товары, аналоги, цены, остатки, корзина

Суть

Чат-консультант по каталогу электротехники ekt.kz. Показывает цены, остатки по складам, характеристики и сертификаты, подбирает объяснимые аналоги и понимает вложения (XLSX, DOCX, PDF, фото этикеток). Товар попадает в корзину только после явного подтверждения.

Как устроено

Консультацию и корзину ведут детерминированные правила в assistant.ts, у LLM нет права записи. Поиск распознаёт SKU и подбирает аналоги: совпадать должны все известные характеристики, категория и источник. Каталог берётся из демо-набора (9 SKU) или из live-API партнёра по Basic Auth с бюджетом 3,5 с на запрос. Gemini опционально уточняет поисковый запрос, но цен и остатков не выдаёт. Вложения разбирает изолированный worker, этикетки читает OCR Tesseract. Подтверждение привязано к SKU, количеству и цене, действует 5 минут и срабатывает один раз.

Ключевые решения

  • детерминированный подбор аналогов по характеристикам
  • двухшаговое подтверждение корзины
  • OCR Tesseract
  • изолированные парсеры в worker threads
  • HttpOnly-сессии
  • виджет для встраивания

Особенности

Строгая защита корзины: простое «да» не принимается, при смене цены нужно новое подтверждение, команды внутри вложений игнорируются. Готов виджет /widget.js для встраивания на сайт.

Стек

Next.js · TypeScript · Node.js · pnpm · Vitest · Playwright · Tesseract

Модели

gemini-3.8-flash


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-9bd2c351-team.

README

README.md

EKT · Консультант по каталогу

Рабочий прототип для кейса HackAlem: подбор электротехнической продукции, остатки по складам, характеристики и документы, объяснимые аналоги и добавление в корзину после отдельного подтверждения.

Ветка: feature/aldiyar. Использует существующий Next.js-проект и адаптер партнёрского API из main. Референс VIVPM/ecommerce-agent использован как ориентир для диалога, карточек, контекста и поиска по вложениям. Его Python-код и инфраструктура Neon/Pinecone не копировались: здесь один сервер Next.js и локальная обработка файлов.

Запуск

Нужен Node.js 22.16+, рекомендуется Node.js 24, и pnpm 11.25.0. При установленном Corepack: corepack enable.

pnpm install --frozen-lockfile
cp .env.example .env.local
pnpm dev

Открыть http://localhost:3000. Демо работает без ключей и внешних сервисов. Сервер использует Node.js worker threads для файлов; Edge runtime и статический экспорт не подходят.

pnpm typecheck
pnpm test
pnpm build
pnpm start

Для браузерных тестов на запущенном сервере:

pnpm exec playwright install chromium
pnpm test:e2e
# Или использовать установленный Chrome на macOS:
CHROME_PATH='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' pnpm test:e2e

При проверке production-сервера используйте HTTPS (cookie помечается Secure). Chromium разрешает Secure cookie на локальном loopback. Внешний HTTP для production не поддерживается.

Сценарий демонстрации и соответствие ТЗ

ТребованиеПроверка
Наличие, характеристики, сертификатПокажи EKT-CB-16A: 2 450 ₸, Алматы 24, Астана 11; 1P, 16 A, 6 kA, C. Документ открывается из карточки.
Аналог отсутствующего товараЕсть EKT-CB-20A?: предложен EKT-CB-20A-PRO, объяснены совпадающие параметры. Автомат 16 A не предлагается как эквивалент 20 A.
Условия покупкиОплата, доставка и минимальная партия?: ответ на все три вопроса, явно отмеченный как демо-условия.
Только явное подтверждениеДобавь 2 EKT-CB-16A: корзина пуста. да, добавь или кнопка «Да, добавить»: 2 единицы в корзине. Простое да/okay не применяется.
Учёт количества и остатковДобавь 100 EKT-CB-16A отклоняется. Учитывается уже добавленное количество. Кабель продаётся кратно 5 м.
Прямая ссылка на актуальную корзинуПосле подтверждения — /cart. Открытие, обновление и возврат в чат сохраняют сессию.
Свободная формулировка и контекстНужен автомат 16А, затем Добавь его 3 шт. SKU можно вводить на русском или английском; поиск понимает распространённые названия категорий.
ВложенияXLSX, DOCX, PDF с текстом, JPEG/PNG с читаемой этикеткой: поиск по извлечённым артикулам, без выполнения команд из файла.
Desktop/mobile и единое окноАдаптивный интерфейс, встроенная версия /embed, виджет /widget.js.

Кнопка «Выбрать» готовит предложение, а не добавляет товар. Подтверждение действует 5 минут, привязано к SKU, количеству, цене и источнику, используется один раз. Новый запрос или «Отмена» отменяет старое предложение. При изменении цены нужно новое подтверждение; при изменении остатка/кратности добавление отклоняется. Запросы одной сессии выполняются последовательно, поэтому двойной клик не удваивает добавление.

Архитектура

  • src/components/chat-workspace.tsx: диалог, восстановление истории, вложения и подтверждение.
  • src/components/product-card.tsx: цены, склады, параметры, документы, обоснования аналогов.
  • src/app/api/chat/route.ts: ограничения запросов, обработка текста/вложений, история.
  • src/lib/assistant.ts: детерминированные правила корзины и консультации; модель не имеет права записи.
  • src/lib/catalog.ts: поиск, точное распознавание SKU, объяснимый подбор, бюджет live-запроса 3,5 с.
  • src/lib/ekt-api.ts: Basic Auth, валидация и отображение партнёрского каталога.
  • src/lib/language.ts: необязательное уточнение поисковых слов через Gemini с таймаутом 4 с. Модель возвращает только запрос, не цены/остатки/условия.
  • src/lib/attachments.ts + scripts/extract-file.mjs: изолированные парсеры и OCR.
  • src/lib/sessions.ts: сессии и блокировки одного процесса, срок неактивности 2 часа, последние 40 сообщений.
  • /api/session, /api/cart: чтение состояния по HttpOnly-cookie. Клиентские sessionId не принимаются, в URL токенов нет.

Цены, остатки и сертификаты формируются из данных каталога, а не из текста LLM. Аналоги должны совпадать по всем известным характеристикам и иметь ту же категорию и источник. Условия покупки сейчас только синтетические — реальные политика оплаты, доставка и минимальные партии партнёром не предоставлены.

Данные и live-интеграция

src/data/products.ts содержит 9 синтетических позиций: автоматы, УЗО, кабель, лампы и розетка. У каждой есть артикул, название, категория, цена в тенге, складские остатки и параметры. Два SKU недоступны и имеют совместимые аналоги. Файлы public/certificates/*.txt — демонстрационные образцы, не реальные документы соответствия.

Для реального каталога установите CATALOG_MODE=live и заполните EKT_API_* в .env.local. Секреты используются только сервером; не создавайте NEXT_PUBLIC_* с ключами. Партнёрские credentials не включены в репозиторий.

Адаптер использует GET products?page=N и GET products/detail?id=…. Ожидаемые поля списка: page, per_page, count, items; count — число элементов страницы. Поля товара: article, name, price, quantity, stores, properties, необязательные категория и документы. Несогласованные общие и складские остатки не считаются проверенными. Кратность берётся из packSize, pack_size, minimum_quantity или properties.KRATNOST_MIN.

Live-поиск ограничен бюджетом времени и максимум 100 страницами; ранее увиденные SKU позволяют сразу запросить детали. При полном каталоге партнёра нужен фоновый индекс или поисковый endpoint: текущий прототип может не просмотреть все страницы. Live-аналоги подбираются только из уже доступной части каталога. При сбое допустим явно подписанный fallback только для специально указанных демо-SKU. Добавление, предложенное по live-данным, не может переключиться на демо при подтверждении.

Этот проект пока ведёт локальную корзину прототипа, а не корзину ekt.kz: контракт записи/авторизации корзины сайта не предоставлен. Реальные checkout, заказ, платёж и резервирование не выполняются. Нужно подключить серверный адаптер корзины ekt.kz, сохранив существующие проверки и отдельное подтверждение.

Вложения и приватность

  • До 5 МБ; PDF до 20 страниц; изображения до 12 Мп; XLSX до 2000 строк и 50 ячеек на строку.
  • DOCX/XLSX: проверка ZIP, до 32 МБ распакованных данных, до 2000 записей. Формулы не исполняются, внешние ссылки не открываются.
  • Локальный OCR Tesseract для английских и русских этикеток; языковые модели устанавливаются как зависимости. Фотография без читаемого артикула/подписи может не дать совпадений. Визуального определения модели товара по внешнему виду нет.
  • Старые .xls/.doc нужно сохранить как .xlsx/.docx. Для сканированного PDF без текстового слоя загрузите фото этикетки или введите артикул.
  • Парсинг в отдельном worker с лимитом памяти и дедлайном 20 с, одновременно не более двух файлов. OCR может занять дольше обычного текстового ответа.
  • Файлы и извлечённый текст не записываются на диск/в историю. Временная папка OCR содержит только общедоступные языковые модели и удаляется.
  • Вложения не подтверждают и не готовят корзину, даже если содержат «да, добавь» или другие инструкции. Количество пользователь сообщает отдельно.
  • По умолчанию данные не отправляются AI-провайдеру. Если задать GEMINI_API_KEY, текст поискового запроса и идентификатор предыдущего товара могут передаваться Google; это показано под полем ввода. Содержимое файлов не передаётся.
  • Запросы с похожими на платёжные реквизиты числовыми последовательностями отклоняются до записи истории. Не отправляйте персональные/платёжные данные. Такая проверка эвристическая, не система DLP.

Встраивание

Для same-origin размещения через reverse proxy на текущем сайте:

<script src="/widget.js" defer></script>

Виджет открывает /embed. На том же origin должны обслуживаться /embed, /api/*, /cart, /_next/*, /certificates/* и /widget.js. Кросс-доменный iframe с third-party cookies не поддерживается. Для реального ekt.kz нужно согласовать пути, CSP и связать корзину с авторизацией сайта. Виджет проверяется отдельно от дизайна и CSP действующего сайта, доступа к которым здесь нет.

Границы прототипа

Один долгоживущий Node-процесс. При перезапуске теряются история, pending-запросы и корзины. Несколько инстансов/serverless требуют общего хранилища и распределённых блокировок. Ограничение 30 сообщений/минуту на сессию — базовая защита; публичному серверу нужен также лимит по IP на reverse proxy. Production требует HTTPS; за TLS reverse proxy задайте APP_ORIGIN=https://ваш-домен для проверки источника запросов.

Казахский интерфейс, история авторизованных пользователей, реальная передача менеджеру, резервирование и оформление заказа не реализованы. Базовые казахские подтверждения поддерживаются, но полноценное двуязычие не заявляется. Содержимое демо не подтверждает пригодность оборудования для конкретного электрощита.

Документация дополнительного AI-поиска: структурированный вывод Gemini, доступные модели. По умолчанию выбран gemini-3.8-flash; модель можно заменить через окружение.

Звёзды
⭐ 0
Форки
0
Язык
TypeScript
Последний push
в прошлом месяце
Коммиты
7
Авторы
4
Файлы
45
Ветки
4

Авторы коммитов

Aldiyar Meirambek 2bryanDecs 2MAKLUBE 2aldiyarww 1

История коммитов

  • 2026-09-23 17:57Merge pull request #2 from BAITC-Hacks/feature/aldiyaraldiyarww
  • 2026-09-23 17:54Implement EKT catalog assistant with confirmed cart updatesAldiyar Meirambek
  • 2026-09-23 17:54Document prototype setup and specification coverageAldiyar Meirambek
  • 2026-09-23 16:55Merge pull request #1 from BAITC-Hacks/feature/sultanbryanDecs
  • 2026-09-23 16:54Add EKT partner catalog adapterbryanDecs
  • 2026-09-23 15:23Just skeleton of projectMAKLUBE
  • 2026-09-23 14:36Where is my codex proMAKLUBE
Структура репозитория (45 файлов)
.env.example
.gitignore
.node-version
AGENTS.md
CLAUDE.md
README.md
next-env.d.ts
next.config.ts
package-lock.json
package.json
playwright.config.ts
pnpm-lock.yaml
pnpm-workspace.yaml
public/certificates/EKT-CB-16A.txt
public/certificates/EKT-CB-20A-PRO.txt
public/widget.js
scripts/extract-file.mjs
src/app/api/cart/route.ts
src/app/api/chat/route.ts
src/app/api/session/route.ts
src/app/cart/page.tsx
src/app/embed/page.tsx
src/app/globals.css
src/app/layout.tsx
src/app/page.tsx
src/components/chat-workspace.tsx
src/components/icons.tsx
src/components/product-card.tsx
src/data/products.ts
src/lib/assistant.test.ts
src/lib/assistant.ts
src/lib/attachments.test.ts
src/lib/attachments.ts
src/lib/catalog.ts
src/lib/ekt-api.test.ts
src/lib/ekt-api.ts
src/lib/http.test.ts
src/lib/http.ts
src/lib/language.test.ts
src/lib/language.ts
src/lib/sessions.ts
src/lib/types.ts
tests/chat.spec.ts
tsconfig.json
vitest.config.ts
Ветки (4)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.