AAYMA
RU
Войти

EKTiQ

Интернет-магазин и AI-консультант по каталогу ekt.kz: поиск по артикулу и параметрам, аналоги, сравнение до 4 товаров, цены и остатки по городам…

Доведённый продукт
Команда «Aegis» 20💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Aegis
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Доведённый продукт

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

Суть

Интернет-магазин и AI-консультант по каталогу ekt.kz: поиск по артикулу и параметрам, аналоги, сравнение до 4 товаров, цены и остатки по городам, корзина с двухэтапным подтверждением, импорт спецификаций и OCR маркировки.

Как устроено

Скрипт syncCatalog выгружает список товаров EKT API в локальный catalog.json, по нему backend ищет кандидатов, а цена, свойства и остатки дозапрашиваются через /products/detail. OpenAI Responses API со structured outputs переводит запрос в структурированные условия (цена, бренд, ток, полюса, город) и объясняет результат; проверка фактов программная (constraintEngine). При добавлении в корзину данные перепроверяются, количество ограничено остатком. Импорт XLSX/DOCX/PDF/CSV и OCR Tesseract.js выполняются в браузере.

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

  • OpenAI Responses API structured outputs
  • локальный снимок каталога + проверка через EKT API
  • constraint engine
  • Tesseract.js OCR
  • pdfjs-dist парсинг документов
  • двухэтапное подтверждение корзины

Особенности

LLM не служит источником цен и остатков: он только разбирает запрос, а каждое значение перепроверяется по EKT API. Конфликты между текстом и характеристиками показываются пользователю, а не выбираются молча. Есть загрузка спецификаций (XLSX/DOCX/PDF) и распознавание фото маркировки прямо в браузере.

Стек

TypeScript · React 19 · Vite · Express 5 · Node.js · Playwright

Модели

OpenAI (модель через OPENAI_MODEL)


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

README

README.md

EKTiQ — помощник по закупке электротехнического оборудования

EKTiQ помогает перейти от потребности или спецификации к проверенным товарам каталога EKT. Решение объединяет интерфейс интернет-магазина, поиск по локальной копии каталога и проверку характеристик и остатков через API EKT. AI помогает понять запрос и объяснить найденные данные, а корзина меняется только после подтверждения пользователя.

Для кого и какую проблему решает

Проект предназначен для специалистов по закупкам, монтажников и инженеров, которым нужно подобрать электротехническое оборудование по артикулу, названию или техническим параметрам. Вместо ручного поиска по большому каталогу пользователь задаёт условия, изучает найденные товары и проверяет их цену, характеристики и доступность по городу.

Что реализовано

  • Поиск и просмотр товаров из локального каталога EKT, фильтры и сортировка.
  • Страница товара с деталями, характеристиками и наличием по складам, получаемыми из API EKT.
  • Ассистент для поиска по текстовому запросу, артикулу и условиям вроде цены, бренда, тока, числа полюсов, напряжения, наличия и города. При настроенном OpenAI API модель интерпретирует запрос и формирует объяснение по проверенным данным; без него доступен ограниченный локальный разбор.
  • Сравнение до четырёх товаров по техническим свойствам, складам, сертификатам и конфликтующим характеристикам.
  • Фильтры каталога по цене, наличию в выбранном городе и доступным техническим параметрам. Проверяемые кандидаты запрашиваются у EKT; интерфейс показывает охват частичного поиска.
  • Подбор кандидатов для аналога. Совпадение параметров не объявляется гарантией взаимозаменяемости.
  • Избранное, корзина и выбор города в интерфейсе.
  • Двухэтапное добавление в корзину: запрос, затем явное подтверждение. Перед подтверждением цена и наличие проверяются повторно; изменение данных требует нового подтверждения.
  • Импорт XLSX, DOCX, PDF с текстовым слоем, CSV и TXT для извлечения текста и последующего поиска строк в каталоге.
  • Распознавание текста русской и английской маркировки на JPG/PNG с помощью Tesseract.js в браузере.
  • Экспорт выбранных позиций как JSON и подготовка текстового черновика закупочной заявки.

Как работает решение

  1. Пользователь вводит запрос, артикул или загружает файл/фотографию маркировки.
  2. Для обычного поиска backend находит кандидатов в локальном каталоге. Для фильтров по цене, остаткам и характеристикам запрашивает детали выбранных кандидатов в EKT API.
  3. Если настроен OpenAI, модель преобразует сообщение в структурированные условия поиска и может объяснить результат. Проверка цен, остатков и свойств выполняется программно по ответам каталога/API.
  4. Пользователь изучает карточки, характеристики, доступность и предупреждения о неполных или противоречивых данных.
  5. При добавлении товара пользователь указывает количество и явно подтверждает действие. Backend повторно запрашивает данные EKT для выбранного города; количество ограничивается подтверждённым остатком.

Для импорта файла текст извлекается в браузере и показывается пользователю для проверки. В backend отправляются строки поиска только после нажатия кнопки поиска. Фотография обрабатывается OCR в браузере; распознавание маркировки само по себе не устанавливает точную модель или совместимость.

Технологии и интеграции

  • Frontend: React 19, TypeScript, Vite, React Router, lucide-react, CSS.
  • Backend: Node.js, TypeScript, Express 5, tsx, dotenv, cors.
  • Документы и изображения: pdfjs-dist, fflate, Tesseract.js.
  • AI: OpenAI Responses API через пакет openai. Конкретная модель задаётся параметром OPENAI_MODEL; она должна поддерживать structured outputs. Название модели в репозитории не зафиксировано.
  • Каталог и проверка товара: API EKT с Basic Auth; учётные данные используются только на backend.
  • Хранение состояния: локальный JSON-снимок каталога на backend; чат хранится в памяти процесса, состояние магазина — в памяти браузера.

Архитектура

Пользователь
    │
    ├── текстовый запрос ──► React-интерфейс ──► Express API
    │                                           ├── локальный каталог EKT
    │                                           ├── интерпретация/объяснение OpenAI (опционально)
    │                                           └── API деталей EKT: цена, остатки, свойства
    │
    └── файл/фото ──► извлечение текста в браузере ──► проверка пользователем
                                                        └── строки запроса в Express API

Подтверждённые товары ──► карточки/сравнение ──► явное подтверждение ──► корзина в браузере

Синхронизация каталога (backend/src/scripts/syncCatalog.ts) загружает страницы списка EKT и записывает их в backend/data/catalog.json. Локальная копия используется для поиска кандидатов, поскольку список API не предоставляет нужный проекту поиск. Подробные данные товара запрашиваются отдельно. При конфликте между текстом и техническими свойствами код сохраняет конфликт для показа, а не выбирает значение молча.

Установка и запуск

Требуются Node.js 22 или новее и npm. Откройте два терминала из корня репозитория.

1. Настроить backend

cd backend
npm ci
cp .env.example .env

Заполните backend/.env:

PORT=3001
CORS_ORIGINS=http://localhost:5173
EKT_API_URL=https://ekt.kz/api
EKT_API_USER=ваш_логин
EKT_API_PASSWORD=ваш_пароль
OPENAI_API_KEY=
OPENAI_MODEL=

Переменные EKT нужны для синхронизации каталога и проверки деталей, цены и остатков. OPENAI_API_KEY и OPENAI_MODEL нужны только для AI-интерпретации и объяснений; базовый локальный разбор условий работает и без них. Не добавляйте секреты в frontend-переменные VITE_* и не коммитьте .env.

В репозитории уже есть backend/data/catalog.json. Если нужно обновить локальный снимок, выполните из папки backend:

npm run sync:catalog

Запустите API (также из backend):

npm run dev

Backend слушает http://localhost:3001 по умолчанию.

2. Настроить frontend

Во втором терминале:

cd frontend
npm ci
npm run dev

Vite обычно запускает сайт на http://localhost:5173. По умолчанию frontend обращается к API по адресу http://localhost:3001. При необходимости адрес можно переопределить переменной VITE_API_URL.

Как проверить решение

  1. Запустите backend и frontend по инструкции выше.
  2. Откройте http://localhost:5173, перейдите в каталог и найдите товар по артикулу или названию.
  3. Откройте карточку товара и проверьте, что цена, характеристики и наличие загружаются из EKT. Для этого должны быть настроены EKT-переменные окружения.
  4. В ассистенте попробуйте запрос, например: «автоматические выключатели дешевле 50 000 ₸». При подключённом OpenAI можно продолжить: «только Legrand», затем «только в наличии в Алматы». Без OpenAI доступен более ограниченный разбор запросов.
  5. Добавьте товар в корзину, задайте количество и подтвердите его в диалоге. Проверьте, что при изменившихся данных требуется повторное подтверждение.
  6. Для проверки сравнения выберите несколько товаров и откройте /compare. Для импорта откройте /specification или /identify.

Локальные проверки из папки backend: npm run typecheck и npm test. Из папки frontend: npm run build и npm run lint. Браузерные проверки: сначала npx playwright install chromium, затем npm run test:e2e из frontend. Большинство browser-тестов используют тестовые ответы API и не подтверждают доступность EKT.

Данные и источники

  • Локальный каталог: backend/data/catalog.json, снимок списка товаров EKT. Он содержит данные для поиска, но не является источником актуального складского остатка.
  • EKT API: GET /products, GET /products?page=N используются для синхронизации каталога; GET /products/detail?id=PRODUCT_ID — для деталей товара. Доступ выполняется через Basic Auth на backend.
  • Подтверждение данных: цена, свойства и остатки берутся из ответа EKT. Остаток по городу вычисляется только по складам, явно связанным с этим городом. Неизвестные значения не подменяются нулём или общим остатком.
  • OpenAI API: используется только если заданы ключ и модель. AI интерпретирует запрос и формулирует объяснение на основе переданных подтверждённых данных; он не является источником цены или наличия.
  • OCR-языковые данные: для первого запуска распознавания Tesseract.js может загрузить языковые данные из интернета. Сама фотография обрабатывается локально в браузере.

Ограничения текущей версии

  • У проекта нет подключённого API оформления заказа, оплаты или резервирования товара. Корзина — локальный пользовательский список, а скачиваемая заявка не отправляется в EKT.
  • Проверка остатков — снимок на момент ответа, а не гарантия резерва. Остаток может измениться после подтверждения. Изменение количества и удаление товара из корзины требуют отдельного подтверждения.
  • Корзина, избранное, сравнение и профиль не привязаны к аккаунту и не имеют серверного постоянного хранения.
  • Для строгих фильтров по цене/наличию/свойствам backend по умолчанию проверяет все текстовые кандидаты из локального снимка каталога. Это может занять несколько минут для широкого запроса. Явный параметр scan ограничивает проверку; ошибки API также отражаются в покрытии, а результаты ограничены локальным снимком и правилами текстового поиска.
  • Группировка категорий частично основана на правилах по названию, так как в локальном индексе нет идентификаторов категорий.
  • Импорт документов извлекает текст и помогает искать строки, но не строит автоматически гарантированно корректную спецификацию/BOM. Поддерживаются XLSX, DOCX, PDF с текстовым слоем, CSV и TXT до 10 МБ; старые XLS/DOC нужно пересохранить. PDF ограничен 50 страницами.
  • Фото-функция распознаёт текст маркировки JPG/PNG, но не идентифицирует оборудование только по внешнему виду.
  • Подбор аналога выдаёт кандидатов для проверки, но не подтверждает электрическую взаимозаменяемость. Конфликтующие характеристики требуют внимания специалиста.
  • Условия поставки и оплаты не подтверждаются интеграцией; их нужно уточнять у EKT. Сведения из AI также следует сверять с показанными характеристиками и источниками. Фильтр отклоняет некоторые распознаваемые платёжные реквизиты в чате и комментарии к заявке, но не гарантирует обнаружение всех форматов чувствительных данных.
  • Ограничения частоты запросов и состояние чата хранятся в памяти процесса; это прототипная конфигурация, не рассчитанная на масштабирование нескольких экземпляров backend.

Развёрнутая версия

Ссылка на deployed-версию в репозитории не указана. Для запуска используйте локальную инструкцию выше.

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

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

Olzhas Amankeldin 3rvhimzhvn 1zhaksylykyasin 1

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

  • 2026-09-23 17:59docs: add Russian project READMErvhimzhvn
  • 2026-09-23 17:57feat: search all catalog candidates and strengthen procurement safeguardszhaksylykyasin
  • 2026-09-23 17:34feat: add verified catalog filters, city stock and procurement workflowsOlzhas Amankeldin
  • 2026-09-23 16:52feat: improve contextual assistant and verified product comparisonOlzhas Amankeldin
  • 2026-09-23 15:34feat: add EKTiQ marketplace and procurement assistantOlzhas Amankeldin
Структура репозитория (71 файлов)
.gitignore
README.md
backend/.env.example
backend/.gitignore
backend/data/catalog.json
backend/package-lock.json
backend/package.json
backend/src/index.ts
backend/src/scripts/syncCatalog.ts
backend/src/services/aiService.ts
backend/src/services/assistantService.ts
backend/src/services/catalogService.ts
backend/src/services/chat.test.ts
backend/src/services/constraintEngine.ts
backend/src/services/conversationService.ts
backend/src/services/ektApi.ts
backend/src/services/fullSearch.test.ts
backend/src/services/privacy.test.ts
backend/src/services/privacy.ts
backend/src/services/productFilters.test.ts
backend/src/services/productFilters.ts
backend/src/services/requirementParser.ts
backend/src/services/technicalFacts.ts
backend/src/services/verifiedCatalog.ts
backend/src/services/verifiedProduct.ts
backend/tsconfig.json
frontend/.gitignore
frontend/.oxlintrc.json
frontend/README.md
frontend/index.html
frontend/package-lock.json
frontend/package.json
frontend/playwright.config.ts
frontend/public/favicon.svg
frontend/public/icons.svg
frontend/src/App.tsx
frontend/src/components/AssistantPanel.tsx
frontend/src/components/CartConfirmModal.tsx
frontend/src/components/Header.tsx
frontend/src/components/ImportWorkbench.tsx
frontend/src/components/Layout.tsx
frontend/src/components/ProductCard.tsx
frontend/src/context/ShopContext.tsx
frontend/src/data/products.ts
frontend/src/index.css
frontend/src/lib/api.ts
frontend/src/lib/chat.ts
frontend/src/lib/download.ts
frontend/src/lib/readDocument.ts
frontend/src/main.tsx
frontend/src/pages/AnaloguePage.tsx
frontend/src/pages/CartPage.tsx
frontend/src/pages/CatalogPage.tsx
frontend/src/pages/CheckoutPage.tsx
frontend/src/pages/ComparePage.tsx
frontend/src/pages/FavoritesPage.tsx
frontend/src/pages/HomePage.tsx
frontend/src/pages/IdentifyPage.tsx
frontend/src/pages/InfoPage.tsx
frontend/src/pages/ProductPage.tsx
frontend/src/pages/ProfilePage.tsx
frontend/src/pages/SpecificationPage.tsx
frontend/src/tasks.css
frontend/src/types/catalog.ts
frontend/src/types/product.ts
frontend/src/verified.css
frontend/tests/buttons.spec.ts
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vite.config.ts

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

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

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