О проекте
Команда: 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.mdEKTiQ — помощник по закупке электротехнического оборудования
EKTiQ помогает перейти от потребности или спецификации к проверенным товарам каталога EKT. Решение объединяет интерфейс интернет-магазина, поиск по локальной копии каталога и проверку характеристик и остатков через API EKT. AI помогает понять запрос и объяснить найденные данные, а корзина меняется только после подтверждения пользователя.
Для кого и какую проблему решает
Проект предназначен для специалистов по закупкам, монтажников и инженеров, которым нужно подобрать электротехническое оборудование по артикулу, названию или техническим параметрам. Вместо ручного поиска по большому каталогу пользователь задаёт условия, изучает найденные товары и проверяет их цену, характеристики и доступность по городу.
Что реализовано
- Поиск и просмотр товаров из локального каталога EKT, фильтры и сортировка.
- Страница товара с деталями, характеристиками и наличием по складам, получаемыми из API EKT.
- Ассистент для поиска по текстовому запросу, артикулу и условиям вроде цены, бренда, тока, числа полюсов, напряжения, наличия и города. При настроенном OpenAI API модель интерпретирует запрос и формирует объяснение по проверенным данным; без него доступен ограниченный локальный разбор.
- Сравнение до четырёх товаров по техническим свойствам, складам, сертификатам и конфликтующим характеристикам.
- Фильтры каталога по цене, наличию в выбранном городе и доступным техническим параметрам. Проверяемые кандидаты запрашиваются у EKT; интерфейс показывает охват частичного поиска.
- Подбор кандидатов для аналога. Совпадение параметров не объявляется гарантией взаимозаменяемости.
- Избранное, корзина и выбор города в интерфейсе.
- Двухэтапное добавление в корзину: запрос, затем явное подтверждение. Перед подтверждением цена и наличие проверяются повторно; изменение данных требует нового подтверждения.
- Импорт XLSX, DOCX, PDF с текстовым слоем, CSV и TXT для извлечения текста и последующего поиска строк в каталоге.
- Распознавание текста русской и английской маркировки на JPG/PNG с помощью Tesseract.js в браузере.
- Экспорт выбранных позиций как JSON и подготовка текстового черновика закупочной заявки.
Как работает решение
- Пользователь вводит запрос, артикул или загружает файл/фотографию маркировки.
- Для обычного поиска backend находит кандидатов в локальном каталоге. Для фильтров по цене, остаткам и характеристикам запрашивает детали выбранных кандидатов в EKT API.
- Если настроен OpenAI, модель преобразует сообщение в структурированные условия поиска и может объяснить результат. Проверка цен, остатков и свойств выполняется программно по ответам каталога/API.
- Пользователь изучает карточки, характеристики, доступность и предупреждения о неполных или противоречивых данных.
- При добавлении товара пользователь указывает количество и явно подтверждает действие. 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.
Как проверить решение
- Запустите backend и frontend по инструкции выше.
- Откройте
http://localhost:5173, перейдите в каталог и найдите товар по артикулу или названию. - Откройте карточку товара и проверьте, что цена, характеристики и наличие загружаются из EKT. Для этого должны быть настроены EKT-переменные окружения.
- В ассистенте попробуйте запрос, например: «автоматические выключатели дешевле 50 000 ₸». При подключённом OpenAI можно продолжить: «только Legrand», затем «только в наличии в Алматы». Без OpenAI доступен более ограниченный разбор запросов.
- Добавьте товар в корзину, задайте количество и подтвердите его в диалоге. Проверьте, что при изменившихся данных требуется повторное подтверждение.
- Для проверки сравнения выберите несколько товаров и откройте
/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-версию в репозитории не указана. Для запуска используйте локальную инструкцию выше.
Авторы коммитов
История коммитов
- 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 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.