О проекте
Команда: znayushie pobedi
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: AI-консультант по каталогу ekt.kz: товары, аналоги, цены, остатки, корзина
Суть
Чат-ассистент для покупателей ekt.kz: поиск товаров по названию, артикулу и характеристикам, карточки товаров в ответах, кандидаты в аналоги, проверка остатка и двухшаговое добавление в demo-корзину; умеет разбирать загруженные списки товаров из XLSX/DOCX/PDF/CSV и фото.
Как устроено
FastAPI-бэкенд ищет совпадения локально по нормализованному JSON-снимку каталога EKT (40 записей) или demo-каталогу (8 товаров), без векторной БД и embeddings. Ответы формирует OpenAI Responses API или NVIDIA API, либо детерминированный demo-режим без ключа; OCR фото и сканов PDF через OpenAI, текстовые документы разбираются локально (pypdf, xlrd, defusedxml) с лимитами и блокировкой активного содержимого. Команда «добавь» только создаёт предложение, корзина меняется лишь отдельным endpoint с confirm: true и повторной проверкой остатка; фронтенд на ванильном JS и встраиваемый виджет.
Ключевые решения
- keyword catalog search
- analog candidates
- two-step cart confirmation
- OCR
- document parsing
Особенности
Подтверждение корзины сделано безопасно: текст «да» в чате не меняет корзину, нужен отдельный запрос для конкретного неизменяемого предложения с повторной проверкой остатка. Загрузка заявок из офисных файлов и сканов через OCR с защитой от активного содержимого.
Стек
Python · FastAPI · Uvicorn · pypdf · Pillow · JavaScript · HTML · CSS · Pytest
Модели
OpenAI Responses API · NVIDIA API
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-f05c02cc-znayushie-pobedi.
README
README.mdEKT Ассистент — консультант по электротехническому каталогу
Прототип чат-ассистента для сайта ekt.kz. Он помогает покупателю найти товар по названию, артикулу и характеристикам, проверить доступные сведения об остатке, увидеть кандидатов в аналоги и подготовить товар к добавлению в корзину.
Проект решает проблему долгого выбора электротехнических товаров: часть типовых вопросов покупатель может закрыть в чате без переписки с менеджером. Критическое действие защищено двухшаговым подтверждением: сообщение в чат лишь создаёт предложение, а корзина меняется только после отдельного нажатия «Да, добавить».
Текущая версия является хакатонным прототипом. Она не оформляет реальный заказ на ekt.kz и не подтверждает актуальные цены или остатки магазина.
Что реализовано
- каталог товаров и поиск по названию, артикулу и характеристикам;
- карточки товаров в ответах чат-ассистента;
- просмотр характеристик, доступных сведений о наличии и документов товара;
- подбор кандидатов в аналоги с пояснением и предупреждением о необходимости технической проверки;
- сессии пользователя и восстановление истории сообщений;
- демонстрационная корзина, которая хранится на сервере в рамках сессии;
- двухшаговое добавление: подготовка предложения и отдельное подтверждение;
- повторная проверка остатка при подтверждении и защита от повторного добавления при повторном запросе;
- загрузка списков товаров в
XLSX,XLS,DOCX, текстовомPDF,CSVиTXT; - OCR для изображений
JPG/PNGи сканированных PDF при настроенном OpenAI API; - ограничения размера и сложности загружаемых файлов, блокировка активного содержимого Office/PDF;
- ответы через OpenAI или NVIDIA API, а также полностью локальный детерминированный demo-режим;
- встроенный адаптивный веб-интерфейс и отдельный вариант чат-виджета для встраивания;
- API-контракт для отдельного фронтенда и автоматические backend/frontend проверки.
Как работает решение
- Пользователь открывает интерфейс, а backend создаёт для него сессию.
- Пользователь вводит запрос, например
автомат C16, или загружает список товаров. - Backend ищет совпадения в выбранном JSON-каталоге и возвращает ответ вместе с карточками товаров.
- Если товар отсутствует, backend может показать кандидатов в аналоги. Их взаимозаменяемость не объявляется подтверждённой.
- По команде
Добавь DEMO-004 2 штукисервер создаёт временное предложение. Корзина на этом шаге остаётся пустой. - Только кнопка «Да, добавить» вызывает отдельный endpoint подтверждения. Сервер заново проверяет товар и остаток, после чего меняет demo-корзину.
- Пользователь может открыть страницу demo-корзины. Реальный заказ на ekt.kz не создаётся.
Текст да, подтверждаю или похожая фраза в чате не подтверждает добавление. Подтверждение принимается только отдельным запросом с confirm: true для конкретного неизменяемого предложения.
Технологии
Backend
- Python 3.10+;
- FastAPI и Uvicorn;
- Pydantic-модели FastAPI для проверки запросов;
python-dotenvдля локальной конфигурации;- официальный Python SDK
openai; python-multipartдля загрузки файлов;pypdf,Pillow,defusedxml,xlrd,olefileдля безопасного разбора документов;- Pytest и FastAPI TestClient для автоматических проверок.
Frontend
- HTML5, CSS3 и JavaScript ES modules без обязательного этапа сборки;
- адаптивная верстка для настольного и мобильного режима;
- Node.js test runner используется только для frontend-тестов.
AI и внешние API
- OpenAI Responses API — ответы ассистента и OCR изображений/сканов;
- NVIDIA API с OpenAI-совместимым endpoint — альтернативный провайдер текстовых ответов;
- конкретные модели не зашиты в код и задаются через
OPENAI_MODELилиNVIDIA_MODEL; AI_PROVIDER=demoзапускает решение без внешней модели и без API-ключа.
Векторная база, embeddings и база данных в этой версии не используются. Поиск выполняется локально по нормализованному JSON-каталогу.
Архитектура
Браузер / чат-виджет
│ HTTP / JSON / multipart
▼
FastAPI (`app/main.py`)
├── чат и ответы по каталогу (`assistant.py`, `conversation.py`)
├── каталог и поиск (`catalog.py` → `ekt_catalog/`)
├── сессии, предложения и demo-корзина (`sessions.py`)
├── разбор файлов и OCR (`attachments.py`)
└── условия покупки (`terms.py`)
│
├── JSON-каталог EKT или синтетический demo-каталог
└── OpenAI / NVIDIA API, если провайдер включён
Основные каталоги проекта:
| Путь | Назначение |
|---|---|
app/ | FastAPI endpoints, чат, сессии, корзина и обработка файлов |
ekt_catalog/ | Нормализация и поиск по переданному снимку каталога |
ekt_catalog/data/products.normalized.json | 40 нормализованных записей из переданных данных EKT |
data/products.json | 8 вымышленных demo-товаров для сценария с корзиной |
frontend/ | Встроенный каталог, чат-виджет и frontend-тесты |
demo-files/ | Примеры файлов для проверки загрузки |
tests/ | Backend-тесты API, каталога и безопасности файлов |
docs/ | Локальные демонстрационные материалы |
Сессии, история и корзина хранятся в памяти процесса. Сырые загруженные файлы и извлечённый из них текст не сохраняются.
Установка и запуск
1. Требования
- Python 3.10 или новее;
- Node.js нужен только для запуска frontend-тестов;
- API-ключ не требуется для demo-режима.
2. Создайте окружение и установите зависимости
PowerShell, из корня проекта:
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
3. Создайте локальную конфигурацию
Copy-Item .env.example .env.local
Для запуска без внешнего ИИ оставьте в .env.local:
AI_PROVIDER=demo
CATALOG_MODE=normalized
Для OpenAI укажите свои значения:
AI_PROVIDER=openai
OPENAI_API_KEY=ваш_ключ
OPENAI_MODEL=имя_доступной_модели
ATTACHMENT_OCR_ENABLED=true
Для NVIDIA:
AI_PROVIDER=nvidia
NVIDIA_API_KEY=ваш_ключ
NVIDIA_MODEL=имя_доступной_модели
Ключ хранится только в локальном .env.local. Этот файл исключён из Git и не должен попадать в архив или frontend.
4. Запустите приложение
Режим с нормализованным снимком каталога EKT:
.\.venv\Scripts\python.exe run.py
Откройте http://127.0.0.1:8001/.
Хакатонный demo-режим с известными остатками и работающей demo-корзиной:
.\.venv\Scripts\python.exe run.py --demo
Откройте http://127.0.0.1:8002/.
127.0.0.1 — это текущий компьютер. Сервер останавливается сочетанием Ctrl+C в терминале.
Как проверить решение
Для повторяемого сценария жюри используйте demo-режим:
- Запустите
python run.py --demoи откройтеhttp://127.0.0.1:8002/. - В чате напишите
Есть ли в наличии DEMO-003?. - Убедитесь, что исходный товар имеет нулевой demo-остаток, а ассистент показывает кандидата в аналог.
- Напишите
Добавь DEMO-004 2 штуки. - Откройте корзину: до отдельного подтверждения она должна оставаться пустой.
- Напишите в чат
даилиподтверждаю: корзина всё ещё не должна измениться. - Нажмите «Да, добавить» в отдельном блоке подтверждения.
- Откройте demo-корзину и проверьте, что добавлены ровно 2 единицы выбранного товара.
- Загрузите
demo-files/sample.xlsx,sample.docxилиsample.pdf: ассистент найдёт позиции, но не добавит их автоматически.
Интерактивная документация API доступна по адресу http://127.0.0.1:8002/docs.
Автоматические проверки
.\.venv\Scripts\python.exe -m pytest
node --test frontend/tests/core.test.mjs
API-контракт
| Метод | Путь | Назначение |
|---|---|---|
GET | /health | Состояние сервера, режим каталога и возможности загрузки |
POST | /api/sessions | Создать сессию |
GET | /api/sessions/{sid}/messages | Получить историю сообщений |
GET | /api/products | Получить товары с пагинацией |
GET/POST | /api/products/search | Искать товары, в том числе со структурными фильтрами |
GET | /api/products/{id} | Получить карточку товара |
GET | /api/products/{id}/alternatives | Получить кандидатов в аналоги |
GET | /api/products/{id}/stock | Проверить доступный остаток |
POST | /api/chat | Отправить сообщение ассистенту |
POST | /api/sessions/{sid}/attachments | Загрузить один документ или изображение |
POST | /api/sessions/{sid}/cart/proposals | Подготовить добавление товара |
POST | /api/sessions/{sid}/cart/proposals/{pid}/confirm | Подтвердить предложение с confirm: true |
DELETE | /api/sessions/{sid}/cart/proposals/{pid} | Отменить предложение |
GET | /api/sessions/{sid}/cart | Получить demo-корзину и ссылку на неё |
GET | /api/purchase-terms | Получить доступные сведения об оплате и доставке |
Минимальный запрос к чату:
{
"message": "автомат C16"
}
Если сессия уже создана:
{
"session_id": "идентификатор-сессии",
"message": "добавь DEMO-004 2 штуки"
}
Данные и интеграции
products.normalized.jsonсодержит 40 записей нормализованного снимка данных, переданного командой AI/каталога.- В снимке у большинства записей нет подтверждённого актуального остатка; валюта, единица продажи и дата актуальности также могут отсутствовать.
data/products.jsonсодержит 8 отдельных вымышленных товаров только для демонстрации корзины и известных остатков.- Прямого live-запроса к каталогу ekt.kz в текущем runtime нет: приложение работает с локальным JSON-снимком.
- Реальный API корзины ekt.kz не подключён.
- OpenAI и NVIDIA используются только при выборе соответствующего провайдера и наличии ключа/имени модели.
- OCR фотографий и сканированных PDF реализован через OpenAI; текстовые документы разбираются локально.
Ограничения текущей версии
- нет production-развёртывания, авторизации и постоянной базы данных;
- сессии, история и корзины очищаются при перезапуске backend;
- demo-корзина не связана с реальной корзиной ekt.kz;
- нормализованный каталог является снимком и не подтверждает текущую цену или наличие;
- аналоги являются кандидатами и требуют проверки специалистом;
- распознавание фото и сканов зависит от доступности и лимитов OpenAI API;
- загружается один файл размером до 10 МБ; действуют дополнительные лимиты страниц, строк и сложности документа;
- интерфейс и ответы прототипа ориентированы на русский язык.
Развёрнутая версия
Публичная deployed-версия в текущем репозитории не указана. Решение запускается локально на http://127.0.0.1:8001 или в demo-режиме на http://127.0.0.1:8002.
Безопасность ключей
- не публикуйте
.env.local; - не вставляйте API-ключ во frontend-код;
- человеку, который разрабатывает frontend, ключ не нужен;
- если ключ закончился или был отозван, замените его только в локальном
.env.localи перезапустите сервер; - при отсутствии рабочего ключа используйте
AI_PROVIDER=demo.
Авторы коммитов
История коммитов
- 2026-09-23 17:29Delete EKT-Assistant-Full-Project.zipcasslex
- 2026-09-23 17:24Create README.mdcasslex
- 2026-09-23 17:24Add files via uploadcasslex
- 2026-09-23 17:23Delete complete/README.mdcasslex
- 2026-09-23 17:18Add complete frontend and FastAPI backend archiveEKT Assistant Team
- 2026-09-23 17:12Delete ekt-assistant-backend-updated.zipcasslex
- 2026-09-23 17:12Delete frontend directorycasslex
- 2026-09-23 17:11Delete EKT-Assistant-Frontend-Source.zipcasslex
Все коммиты (17)
- 2026-09-23 17:11Delete README.mdcasslex
- 2026-09-23 17:11Delete products.normalized.jsoncasslex
- 2026-09-23 17:09Add integrated EKT Assistant prototypeEKT Assistant Team
- 2026-09-23 16:16Add EKT Assistant frontend prototypeEKT Assistant Team
- 2026-09-23 16:12Add files via uploadcasslex
- 2026-09-23 16:06Delete ekt-assistant-backend.zipcasslex
- 2026-09-23 15:40Add files via uploadaligarkinbek-blip
- 2026-09-23 15:31Add files via uploadcasslex
- 2026-09-23 15:24Add files via uploadcasslex
Структура репозитория (59 файлов)
README.md complete/.env.example complete/.gitignore complete/README.md complete/app/__init__.py complete/app/assistant.py complete/app/attachments.py complete/app/catalog.py complete/app/conversation.py complete/app/main.py complete/app/models.py complete/app/sessions.py complete/app/terms.py complete/app/upload_limit.py complete/data/products.json complete/data/purchase_terms.demo.json complete/demo-files/README.md complete/demo-files/sample.docx complete/demo-files/sample.jpg complete/demo-files/sample.pdf complete/demo-files/sample.xlsx complete/docs/COMPLETION_STATUS.md complete/docs/INTEGRATION_RESULTS.md complete/docs/catalog-response-examples.json complete/docs/catalog-source-readme.md complete/ekt_catalog/__init__.py complete/ekt_catalog/api_router.py complete/ekt_catalog/data/products.normalized.json complete/ekt_catalog/data/products.schema.json complete/ekt_catalog/normalize.py complete/ekt_catalog/service.py complete/frontend/README.md complete/frontend/index.html complete/frontend/package.json complete/frontend/public/assets/breaker.jpg complete/frontend/public/assets/bulb.jpg complete/frontend/public/assets/cable.jpg complete/frontend/public/assets/ekt-45357.jpg complete/frontend/public/assets/ekt-515279.jpg complete/frontend/public/assets/ekt-58380.jpg complete/frontend/public/assets/socket.jpg complete/frontend/public/documents/demo-certificate.html complete/frontend/public/embed-demo.html complete/frontend/public/embed.js complete/frontend/src/app.js complete/frontend/src/core.js complete/frontend/src/integration.css complete/frontend/src/style.css complete/frontend/tests/core.test.mjs complete/requirements.txt complete/run.py complete/tests/fixtures/attachments/synthetic-request.xls complete/tests/test_api.py complete/tests/test_attachments.py complete/tests/test_case_acceptance.py complete/tests/test_catalog_acceptance.py complete/tests/test_catalog_integration.py complete/tests/test_frontend_serving.py complete/tests/test_person1_core.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.