AAYMA
RU
Войти

EKT Ассистент

Чат-ассистент для покупателей ekt.kz: поиск товаров по названию, артикулу и характеристикам, карточки товаров в ответах, кандидаты в аналоги…

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

О проекте

Команда: 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.md

EKT Ассистент — консультант по электротехническому каталогу

Прототип чат-ассистента для сайта 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 проверки.

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

  1. Пользователь открывает интерфейс, а backend создаёт для него сессию.
  2. Пользователь вводит запрос, например автомат C16, или загружает список товаров.
  3. Backend ищет совпадения в выбранном JSON-каталоге и возвращает ответ вместе с карточками товаров.
  4. Если товар отсутствует, backend может показать кандидатов в аналоги. Их взаимозаменяемость не объявляется подтверждённой.
  5. По команде Добавь DEMO-004 2 штуки сервер создаёт временное предложение. Корзина на этом шаге остаётся пустой.
  6. Только кнопка «Да, добавить» вызывает отдельный endpoint подтверждения. Сервер заново проверяет товар и остаток, после чего меняет demo-корзину.
  7. Пользователь может открыть страницу 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.json40 нормализованных записей из переданных данных EKT
data/products.json8 вымышленных 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-режим:

  1. Запустите python run.py --demo и откройте http://127.0.0.1:8002/.
  2. В чате напишите Есть ли в наличии DEMO-003?.
  3. Убедитесь, что исходный товар имеет нулевой demo-остаток, а ассистент показывает кандидата в аналог.
  4. Напишите Добавь DEMO-004 2 штуки.
  5. Откройте корзину: до отдельного подтверждения она должна оставаться пустой.
  6. Напишите в чат да или подтверждаю: корзина всё ещё не должна измениться.
  7. Нажмите «Да, добавить» в отдельном блоке подтверждения.
  8. Откройте demo-корзину и проверьте, что добавлены ровно 2 единицы выбранного товара.
  9. Загрузите 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.
Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
17
Авторы
3
Файлы
59
Ветки
1

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

casslex 13EKT Assistant Team 3aligarkinbek-blip 1

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

  • 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 комментариев

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

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