О проекте
Команда: HackMac
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: AI-консультант по каталогу ekt.kz: товары, аналоги, цены, остатки, корзина
Суть
Клиентский веб-консультант по каталогу ekt.kz: поиск и фильтры товаров, цены и остатки по городам и складам, корзина, подбор аналогов, инженерный калькулятор 220/380 В и чат «ИИ-инженер EKT» с голосовым вводом. Есть также Android-приложение с отдельным консультантом на Gemini.
Как устроено
FastAPI получает каталог и остатки из EKT API (HTTP Basic Auth), подбирает аналоги по категории и характеристикам и хранит корзину в памяти. Express-сервер обслуживает чат /api/chat: отправляет запрос в Google Gemini, извлекает из ответа рекомендованные товары и применяет их к каталогу. Без ключа работает локальный набор инженерных правил. Голосовой ввод и озвучка ответа работают через Web Speech API и Speech Synthesis API браузера.
Ключевые решения
- Gemini chat
- rule-based fallback
- analog matching по категории и характеристикам
- electrical load calculator
- Web Speech API
Особенности
Сделан инженерный калькулятор: по мощности и cos φ считает ток, номинал автомата и сечение кабеля, а результат сразу фильтрует каталог. Помимо веба есть нативное Android-приложение.
Стек
TypeScript · React 19 · Vite · Express · Tailwind CSS · Python · FastAPI · HTTPX · Kotlin · Jetpack Compose · Room · Retrofit
Модели
Gemini (gemini-3.8-flash, gemini-3.5-flash)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-b2008944-hackmac.
README
README.mdEKT.kz — ИИ-консультант по электротехнике
Веб-приложение для подбора электротехнического оборудования EKT.kz. Проект помогает электрикам, проектировщикам, монтажникам, снабженцам и частным клиентам искать товары, проверять наличие, выполнять базовые расчёты нагрузки и получать рекомендации ИИ-консультанта.
Что реализовано
- каталог товаров с поиском, фильтрами, сортировкой и пагинацией;
- выбор города и склада: Астана, Алматы, Шымкент, Караганда и другие города Казахстана;
- карточки товаров с ценой, характеристиками, изображениями и остатками;
- корзина с добавлением товаров, изменением количества и удалением позиций;
- инженерный калькулятор для сетей 220 В и 380 В: ток, номинал автомата и ориентировочное сечение кабеля;
- чат «ИИ-инженер EKT» с подбором товаров по запросу;
- голосовой ввод и озвучивание ответа в браузере;
- подбор возможных аналогов товара по категории и характеристикам;
- локальный rule-based fallback, если Gemini недоступен;
- Android-приложение на Jetpack Compose с отдельным Gemini-консультантом.
Как работает
Пользователь вводит запрос, параметры фильтра или данные нагрузки. Frontend отправляет запрос в локальный FastAPI backend. Backend получает каталог и остатки через EKT API. Для консультации сообщение передаётся Express-серверу: он обращается к Google Gemini, извлекает рекомендованные товары и показывает их в интерфейсе. При отсутствии ключа Gemini используется локальный набор инженерных правил. Результат можно применить к каталогу и добавить товар в корзину.
Технологии
- Frontend: TypeScript, React 19, Vite, Express, Tailwind CSS,
lucide-react,motion. - Backend: Python, FastAPI, Uvicorn, Pydantic, HTTPX.
- AI: Google Gemini через
@google/genai; в Express-коде указана модельgemini-3.8-flash, в Android-клиенте —gemini-3.5-flash. - Android: Kotlin, Jetpack Compose, Material 3, Room, Retrofit, OkHttp, Moshi, Coil, Coroutines.
- Браузерные API: Web Speech API и Speech Synthesis API.
Архитектура
React/Vite + Express (frontend:3000)
├─ /api/chat → Gemini или локальный fallback
└─ src/services/api.ts → FastAPI (backend:8000)
├─ каталог и детали товаров
├─ корзина
└─ аналоги товаров
↓
EKT API: https://ekt.kz/api
Android Compose-приложение → локальные данные/Room → Gemini API
Основные компоненты: frontend/src содержит интерфейс и клиент API; frontend/server.ts обслуживает React и чат; backend/main.py содержит HTTP-маршруты; backend/ekt_client.py работает с EKT API; backend/analog_service.py подбирает аналоги; backend/cart_store.py хранит корзины в памяти.
Установка и запуск
Backend
В PowerShell из корня проекта:
python -m venv backend\.venv
backend\.venv\Scripts\python.exe -m pip install -r backend\requirements.txt
Copy-Item backend\.env.example backend\.env
backend\.venv\Scripts\python.exe -m uvicorn backend.main:app --host 127.0.0.1 --port 8000 --reload
При необходимости заполните backend\.env:
EKT_API_URL=https://ekt.kz/api
EKT_API_USERNAME=
EKT_API_PASSWORD=
Frontend
Во втором терминале:
Set-Location frontend
npm install
Copy-Item .env.example .env
npm run dev
Для ИИ укажите в frontend\.env:
GEMINI_API_KEY=ваш_ключ_Gemini
Откройте http://localhost:3000. Проверка сборки и типов:
npm run build
npm run lint
Android
Откройте каталог app/apps в Android Studio, создайте .env на основе app/apps/.env.example, дождитесь синхронизации Gradle и запустите модуль app на эмуляторе или устройстве. Для release-сборки нужны KEYSTORE_PATH, STORE_PASSWORD и KEY_PASSWORD.
Как проверить
- Запустите backend и frontend.
- В каталоге найдите
Legrand, откройте карточку товара и добавьте его в корзину. - Откройте калькулятор, выберите
3 фазы (380 В), укажите30 кВтиcos φ = 0.85; примените рассчитанный номинал к каталогу. - В чате отправьте:
Реле контроля сухого хода насоса. - Проверьте ответ консультанта и рекомендованные товары.
- Проверьте API: http://127.0.0.1:8000/health должен вернуть
{"status":"ok"}. Документация доступна по http://127.0.0.1:8000/docs.
Данные и интеграции
- живой каталог и остатки:
https://ekt.kz/api; - авторизация EKT API:
EKT_API_USERNAMEиEKT_API_PASSWORDчерез HTTP Basic Auth; - frontend обращается к FastAPI по
http://127.0.0.1:8000; - Express предоставляет
/api/chat, локальные маршруты каталога и городов; - Gemini используется для генерации консультаций, а демонстрационные товары из
frontend/src/data/mockProducts.tsвходят в базу знаний frontend-консультанта; - корзина frontend сохраняется в
localStorage, backend-корзина хранится в памяти процесса.
Ограничения
- Подтверждённой production/deployed-ссылки web-версии в репозитории нет; для демонстрации используется локальный адрес
http://localhost:3000. - Для живого каталога может потребоваться действующая авторизация EKT API.
- Оформление заказа, оплата и интеграция с личным кабинетом EKT не реализованы.
- Backend-корзина хранится только в RAM и очищается после перезапуска сервера.
- Поиск и подбор аналогов ограничены просмотренными страницами каталога; аналоги требуют технической проверки перед заменой.
- Расчёты являются ориентировочными и не заменяют полноценное проектирование электроснабжения.
- Адрес backend зафиксирован на
127.0.0.1:8000; для публикации потребуется настроить reverse proxy, CORS и production-конфигурацию.
Deployed-версия
В текущем репозитории подтверждённая deployed-версия web-приложения не указана.
Авторы коммитов
История коммитов
- 2026-09-23 18:00Revise README for EKT.kz project overviewtimkamad
- 2026-09-23 17:57App and aiermek144
- 2026-09-23 17:46Delete appad1k4
- 2026-09-23 17:45Create appad1k4
- 2026-09-23 17:42New front and backad1k4
- 2026-09-23 17:41feat: integrate frontend with EKT backendad1k4
- 2026-09-23 17:03updated frontTemirlan
- 2026-09-23 17:00add ekt.kz frontTemirlan
Все коммиты (22)
- 2026-09-23 16:02feat: add product analogs and frontend CORSad1k4
- 2026-09-23 15:59Delete ппermek144
- 2026-09-23 15:59Delete ekt-ai-frontend directoryermek144
- 2026-09-23 15:53feat: add cart item removalad1k4
- 2026-09-23 15:41feat: add confirmed cart with stock validationad1k4
- 2026-09-23 15:24Merge pull request #4 from BAITC-Hacks/feature/product-searchad1k4
- 2026-09-23 15:21feat: add product searchad1k4
- 2026-09-23 15:05temirlan add fronttimkamad
- 2026-09-23 15:04Update frontend UITemirlan
- 2026-09-23 15:03Merge pull request #2 from BAITC-Hacks/feature/backendad1k4
- 2026-09-23 15:00feat: connect backend to EKT products APIad1k4
- 2026-09-23 14:38Merge pull request #1 from BAITC-Hacks/feature/frontendtimkamad
- 2026-09-23 14:34Create ппermek144
- 2026-09-23 14:31Temirlan add frontendTemirlan
Структура репозитория (93 файлов)
.gitignore README.md ai.md app/apps/.env.example app/apps/.gitignore app/apps/README.md app/apps/app/.gitignore app/apps/app/build.gradle.kts app/apps/app/proguard-rules.pro app/apps/app/src/androidTest/java/com/example/ExampleInstrumentedTest.kt app/apps/app/src/main/AndroidManifest.xml app/apps/app/src/main/java/com/example/MainActivity.kt app/apps/app/src/main/java/com/example/data/calculator/ElectricalCalculators.kt app/apps/app/src/main/java/com/example/data/local/AppDatabase.kt app/apps/app/src/main/java/com/example/data/local/Daos.kt app/apps/app/src/main/java/com/example/data/local/Entities.kt app/apps/app/src/main/java/com/example/data/model/EctCatalogData.kt app/apps/app/src/main/java/com/example/data/model/Product.kt app/apps/app/src/main/java/com/example/data/remote/GeminiApiClient.kt app/apps/app/src/main/java/com/example/data/remote/GeminiModels.kt app/apps/app/src/main/java/com/example/data/repository/EctRepository.kt app/apps/app/src/main/java/com/example/ui/components/ProductCard.kt app/apps/app/src/main/java/com/example/ui/components/ProductDetailSheet.kt app/apps/app/src/main/java/com/example/ui/screens/CalculatorScreen.kt app/apps/app/src/main/java/com/example/ui/screens/CartScreen.kt app/apps/app/src/main/java/com/example/ui/screens/CatalogScreen.kt app/apps/app/src/main/java/com/example/ui/screens/ChatScreen.kt app/apps/app/src/main/java/com/example/ui/screens/MainScreen.kt app/apps/app/src/main/java/com/example/ui/theme/Color.kt app/apps/app/src/main/java/com/example/ui/theme/Theme.kt app/apps/app/src/main/java/com/example/ui/theme/Type.kt app/apps/app/src/main/java/com/example/ui/viewmodel/EctAppViewModel.kt app/apps/app/src/main/res/drawable/ic_launcher_background.xml app/apps/app/src/main/res/drawable/ic_launcher_foreground.xml app/apps/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml app/apps/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml app/apps/app/src/main/res/mipmap-hdpi/ic_launcher.webp app/apps/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp app/apps/app/src/main/res/mipmap-mdpi/ic_launcher.webp app/apps/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp app/apps/app/src/main/res/mipmap-xhdpi/ic_launcher.webp app/apps/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp app/apps/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp app/apps/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp app/apps/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp app/apps/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp app/apps/app/src/main/res/values/colors.xml app/apps/app/src/main/res/values/strings.xml app/apps/app/src/main/res/values/themes.xml app/apps/app/src/main/res/xml/backup_rules.xml app/apps/app/src/main/res/xml/data_extraction_rules.xml app/apps/app/src/test/java/com/example/ExampleRobolectricTest.kt app/apps/app/src/test/java/com/example/ExampleUnitTest.kt app/apps/app/src/test/java/com/example/GreetingScreenshotTest.kt app/apps/app/src/test/screenshots/greeting.png app/apps/build.gradle.kts app/apps/gradle.properties app/apps/gradle/libs.versions.toml app/apps/gradle/wrapper/gradle-wrapper.properties app/apps/metadata.json app/apps/settings.gradle.kts backend/.env.example backend/analog_service.py backend/cart_store.py backend/ekt_client.py backend/main.py backend/requirements.txt frontend/.env.example frontend/.gitignore frontend/TEAM.md frontend/index.html frontend/metadata.json frontend/package-lock.json frontend/package.json frontend/server.ts frontend/src/App.tsx frontend/src/components/AIConsultantChat.tsx frontend/src/components/CartModal.tsx frontend/src/components/CatalogSection.tsx frontend/src/components/ElectricalCalculatorModal.tsx frontend/src/components/Footer.tsx frontend/src/components/Header.tsx frontend/src/components/HeroBanner.tsx frontend/src/components/ProductCard.tsx frontend/src/components/ProductDetailModal.tsx frontend/src/components/TeamModal.tsx frontend/src/data/mockProducts.ts frontend/src/index.css frontend/src/main.tsx frontend/src/services/api.ts frontend/src/types/index.ts frontend/tsconfig.json frontend/vite.config.ts
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.