AAYMA
RU
Войти

EKT AI

Чат-консультант по каталогу ekt.kz из трёх сервисов: веб-чат с карточками товаров и загрузкой спецификаций, AI Service с tool calling и Product…

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

О проекте

Команда: NYU
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Рабочий MVP

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

Суть

Чат-консультант по каталогу ekt.kz из трёх сервисов: веб-чат с карточками товаров и загрузкой спецификаций, AI Service с tool calling и Product Service с синхронизацией каталога, поиском, аналогами и остатками; добавление в корзину только после подтверждения пользователя.

Как устроено

Product Service по Basic Auth выгружает и нормализует каталог API ekt.kz в PostgreSQL с полнотекстовым поиском и отдаёт поиск, аналоги, детали и остатки. AI Service получает сообщение и вложения (openpyxl, python-docx, pypdf), хранит историю в Redis и в цикле tool calling вызывает инструменты поиска товаров через OpenAI-совместимый Chat Completions API (по умолчанию Gemini 3.5 Flash-Lite, возможны OpenAI/DeepSeek). Веб на Next.js показывает ответ и предложение корзины, при подтверждении перепроверяет наличие через Product Service.

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

  • function/tool calling loop
  • PostgreSQL full-text search
  • нормализация каталога
  • Redis-история диалога с TTL
  • подтверждение действия корзины

Особенности

Микросервисная декомпозиция (web / AI Service / Product Service) с внутренним токеном и провайдер-агностичным LLM-слоем через OpenAI-совместимый API без SDK; интеграция с реальным API ekt.kz и перепроверка наличия перед добавлением в корзину.

Стек

Python · FastAPI · Uvicorn · Pydantic · SQLAlchemy · PostgreSQL · Redis · httpx · Next.js · React · TypeScript · Tailwind CSS · Docker Compose

Модели

Gemini 3.5 Flash-Lite · OpenAI (опционально) · DeepSeek (опционально)


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

README

README.md

EKT AI — консультант по электротоварам

Хакатонный MVP чат-ассистента для каталога ekt.kz. Пользователь может искать электротовары, смотреть карточки и сведения о наличии, прикладывать спецификации и подтверждать предложение добавить товар в корзину. Проект разделён на веб-приложение, AI Service и Product Service. AI Service обращается к подключённому API модели; ниже приведена настройка Gemini.

Состав проекта

КаталогНазначение
web/Интерфейс чата, загрузка файлов, карточки товаров, подтверждение корзины и серверные API-маршруты Next.js.
ai-service/Обработка сообщений и вложений, вызов LLM и инструментов поиска товаров.
services/product-service/Получение и нормализация каталога ekt.kz, поиск, аналоги, проверка деталей и остатков.
services/product-service/fixtures/Пример товара для проверки каталога без доступа к API ekt.kz.

Поток запросов: браузер → web → AI Service → Product Service → PostgreSQL / API ekt.kz. Предложение добавить товар в корзину возвращается в web и выполняется только после подтверждения пользователя.

Запуск с подключённым Gemini API

Нужны Docker Desktop с docker compose, Python 3.12, Node.js 20, npm, ключ Gemini API и учётные данные API ekt.kz для загрузки реального каталога. Команды рассчитаны на PowerShell и выполняются из корня репозитория. Порты 3000, 6379, 8001 и 8002 должны быть свободны. Ключ Gemini можно создать в Google AI Studio.

1. Product Service и PostgreSQL

Скопируйте файл настроек, заполните EKT_API_USERNAME и EKT_API_PASSWORD в services/product-service/.env, затем запустите сервис:

cd .\services\product-service
if (-not (Test-Path .env)) { Copy-Item .env.example .env }

После сохранения .env:

docker compose -f compose.yml up -d --build product-service
Invoke-RestMethod http://localhost:8001/health

Затем загрузите каталог:

docker compose -f compose.yml exec product-service python -m app.sync_catalog

Compose запускает PostgreSQL и Product Service. Ожидаемый ответ /health — status: healthy. Каталог сам при старте не загружается. Для короткой проверки синхронизации можно добавить --max-pages 1.

Для проверки поиска напрямую:

$headers = @{ Authorization = 'Bearer change-me' }
$body = @{ query = '027228'; limit = 5; filters = @{} } | ConvertTo-Json -Depth 3
Invoke-RestMethod -Method Post -Uri http://localhost:8001/internal/v1/products/search -Headers $headers -ContentType 'application/json' -Body $body

2. Redis

Для хранения истории диалогов запустите Redis в отдельном контейнере:

docker run --rm -d --name ekt-ai-redis -p 6379:6379 redis:7-alpine

Если Redis уже работает на localhost:6379, этот шаг пропустите.

3. AI Service и файл .env

В новом окне PowerShell:

cd .\ai-service
if (-not (Test-Path .env)) { Copy-Item .env.example .env }
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt

Перед запуском Uvicorn откройте ai-service/.env и вставьте настоящий ключ в LLM_API_KEY. Содержимое файла для локального запуска:

APP_ENV=development
AI_SERVICE_PORT=8002
INTERNAL_SERVICE_TOKEN=change-me
PRODUCT_SERVICE_URL=http://127.0.0.1:8001
REDIS_URL=redis://127.0.0.1:6379/0
LLM_PROVIDER=gemini
LLM_API_KEY=
LLM_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai
LLM_MODEL=gemini-3.5-flash-lite
LLM_TIMEOUT_SECONDS=60
MAX_ATTACHMENT_MB=15
CONVERSATION_TTL_SECONDS=86400
KNOWLEDGE_DIR=knowledge

Пустое LLM_API_KEY нужно заменить своим ключом: без него AI Service не запустится. Не добавляйте ai-service/.env в Git. Затем запустите сервис:

.\.venv\Scripts\python.exe -m uvicorn app.main:app --host 127.0.0.1 --port 8002

AI Service загружает .env при старте и доступен на http://localhost:8002/docs. Базовый URL и идентификатор модели соответствуют OpenAI-совместимому API Gemini и странице Gemini 3.5 Flash-Lite. Для других провайдеров можно указать LLM_PROVIDER=openai или deepseek и их URL, модель и ключ.

Адреса product-service и redis из вашего примера подходят при запуске всех сервисов в одной Docker-сети. В описанном здесь локальном запуске AI Service работает на компьютере, поэтому в .env нужны адреса 127.0.0.1.

4. Веб-приложение

cd .\web
if (-not (Test-Path .env.local)) { Copy-Item .env.example .env.local }
npm ci
npm run dev

Проверьте в web/.env.local: AI_SERVICE_URL=http://127.0.0.1:8002, PRODUCT_SERVICE_URL=http://127.0.0.1:8001, тот же INTERNAL_SERVICE_TOKEN, что у Product Service, и CART_ADAPTER_MODE=live. Затем откройте http://localhost:3000. Веб-приложение отправляет сообщения в AI Service, который вызывает Gemini API и Product Service. При подтверждении предложения корзины web запрашивает актуальное наличие в Product Service. После изменения .env.local перезапустите npm run dev.

Остановка: Ctrl+C в окнах AI Service и Next.js, затем в каталоге services/product-service выполните docker compose -f compose.yml down и остановите Redis командой docker stop ekt-ai-redis. Данные PostgreSQL останутся в Docker volume.

Проверка подключения

После запуска отправьте сообщение напрямую в AI Service:

$body = @{ message = 'Привет'; attachment_ids = @(); locale = 'ru-RU' } | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri http://localhost:8002/internal/v1/chat/messages -ContentType 'application/json' -Body $body

Ответ с text, conversation_id и пустым массивом errors подтверждает успешный вызов модели. Запрос к Gemini требует действующего ключа и сетевого доступа. INTERNAL_SERVICE_TOKEN должен совпадать у Product Service, AI Service и web; при замене change-me обновите три файла настроек. Если меняете .env, перезапустите соответствующий сервис.

Основные настройки

ПеременнаяГде используетсяНазначение
AI_SERVICE_URLwebАдрес AI Service для запросов чата и передачи вложений.
PRODUCT_SERVICE_URLai-service, webАдрес Product Service.
INTERNAL_SERVICE_TOKENвсе модулиТокен внутренних запросов к Product Service.
PRODUCT_DATABASE_URLProduct ServiceПодключение к PostgreSQL; в Compose уже задано.
EKT_API_USERNAME, EKT_API_PASSWORDProduct ServiceBasic Auth для запросов к API ekt.kz.
LLM_PROVIDER, LLM_API_KEY, LLM_BASE_URL, LLM_MODELAI ServiceПровайдер, ключ, адрес и модель подключённого AI API.
REDIS_URLAI ServiceПодключение к Redis для истории диалогов.
CART_ADAPTER_MODEwebЗначение live включает проверку наличия через Product Service.
CART_PROPOSAL_TTL_SECONDSwebСрок действия предложения корзины; по умолчанию 900 секунд.
EKT_CART_URLwebСсылка на страницу корзины, возвращаемая текущим адаптером.

Примеры всех переменных находятся в web/.env.example, ai-service/.env.example и services/product-service/.env.example.

Проверки

В каталоге web:

npm run lint
npm run build

В каталоге services/product-service тесты запускаются в отдельном профиле Compose:

docker compose -f compose.yml --profile test build tests
docker compose -f compose.yml --profile test run --rm tests

В каталоге ai-service после создания виртуального окружения:

.\.venv\Scripts\python.exe -m pip install pytest
.\.venv\Scripts\python.exe -m pytest -q

Технологический стек: что и для чего используется

Версии веб-пакетов зафиксированы в web/package.json. Версии Python-зависимостей указаны диапазонами в requirements.txt; Dockerfile обоих Python-сервисов использует Python 3.12.

ТехнологияГдеДля чего
Node.js 20 и npmwebЗапуск Next.js, установка пакетов и сборка интерфейса.
Next.js 14.2.15 (App Router)web/appСтраницы чата и корзины, а также серверные API-маршруты для чата, файлов и подтверждения предложений.
React 18.3.1web/componentsКомпоненты чата, карточек товаров, загрузки файлов и подтверждения действий.
TypeScript 5.7.2webТипы запросов, ответов и данных между интерфейсом и API.
Tailwind CSS 3.4.17webСтили и адаптивная верстка интерфейса.
PostCSS 8.4.49 и Autoprefixer 10.4.20webОбработка CSS и добавление браузерных префиксов при сборке.
ESLint 8.57.1 и eslint-config-next 14.2.15webПроверка кода командой npm run lint.
Python 3.12ai-service, services/product-serviceСреда выполнения двух серверных сервисов.
FastAPI и Uvicornоба Python-сервисаHTTP API для чата, вложений, каталога, остатков и синхронизации; Uvicorn запускает приложения.
Pydanticоба Python-сервисаПроверка входных данных и формирование структурированных ответов API.
pydantic-settingsProduct ServiceЧтение и проверка настроек сервиса из окружения и .env.
python-dotenvAI ServiceЗагрузка ai-service/.env с адресом модели и API-ключом при старте сервиса.
httpxоба Python-сервисаЗапросы к API ekt.kz, Product Service и OpenAI-совместимому API модели.
PostgreSQL 16Product ServiceПостоянное хранение нормализованного каталога и поиск товаров, включая полнотекстовый поиск.
SQLAlchemy 2 и psycopg 3Product ServiceМодель данных, SQL-запросы и подключение Python-сервиса к PostgreSQL.
Redis и Python-пакет redisAI ServiceХранение истории диалога с ограниченным сроком жизни.
OpenAI-совместимый Chat Completions APIAI ServiceВызов Gemini, OpenAI или DeepSeek через httpx; отдельный SDK не используется.
python-multipartAI ServiceПрием файлов через multipart/form-data.
openpyxl, python-docx, pypdfAI ServiceИзвлечение данных соответственно из XLSX, DOCX и PDF. JPEG принимается, но OCR пока нет.
HTTP/REST, JSON и multipart/form-dataВсе модулиОбмен запросами и ответами между сервисами; отдельный формат для передачи файлов.
Basic Auth, Bearer token и cookieAPI ekt.kz, внутренние запросы, webАвторизация к каталогу ekt.kz, проверка внутренних запросов Product Service и привязка предложений корзины к сессии браузера.
Docker и Docker ComposeDockerfile всех модулей; services/product-service/compose.ymlКонтейнерные сборки; Compose сейчас запускает Product Service и PostgreSQL, а также тестовый профиль.
pytestТесты Python-сервисовПроверка контрактов AI Service, API каталога, нормализации и клиента ekt.kz.

В браузере ответы приходят целиком, без SSE. Интеграция с Cart API ekt.kz остаётся отдельной задачей.

Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
31
Авторы
4
Файлы
76
Ветки
6

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

yonuraily 16Ulykpan 9Ulykpan 5yasminaipanova27-a11y 1

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

  • 2026-09-23 17:52Update README.mdyonuraily
  • 2026-09-23 17:49feat: connect Gemini API and update setup docsyonuraily
  • 2026-09-23 17:24Merge pull request #7 from BAITC-Hacks/fix/chat-product-searchUlykpan
  • 2026-09-23 17:24Merge branch 'main' into fix/chat-product-searchUlykpan
  • 2026-09-23 17:06Finalize Module 3 web cart MVPyonuraily
  • 2026-09-23 16:52docs: add project overview and setup guideyonuraily
  • 2026-09-23 16:49Fix product search through chatUlykpan
  • 2026-09-23 16:29Merge pull request #6 from BAITC-Hacks/yasmina/section-cUlykpan
Все коммиты (31)
  • 2026-09-23 16:26Improve mobile responsive layoutyonuraily
  • 2026-09-23 16:21Merge pull request #5 from BAITC-Hacks/cleanup/remove-placeholder-filesUlykpan
  • 2026-09-23 16:19Merge pull request #4 from BAITC-Hacks/yonuraily/section-bUlykpan
  • 2026-09-23 16:19Merge pull request #1 from BAITC-Hacks/yasmina/section-cUlykpan
  • 2026-09-23 16:18Remove obsolete AI integration planUlykpan
  • 2026-09-23 16:13Merge pull request #3 from BAITC-Hacks/ulyqq/section-aUlykpan
  • 2026-09-23 16:12Merge pull request #2 from BAITC-Hacks/cleanup/remove-placeholder-filesUlykpan
  • 2026-09-23 16:12Add AI service contract coverageyonuraily
  • 2026-09-23 16:09Remove placeholder filesUlykpan
  • 2026-09-23 16:06Fix cart confirmation and improve mock cart intentyonuraily
  • 2026-09-23 15:51Implement Product Service and ekt.kz integrationUlykpan
  • 2026-09-23 15:44Move frontend cart plan into dedicated folderyonuraily
  • 2026-09-23 15:44Implement Module 3 web and cart MVPyonuraily
  • 2026-09-23 15:44Add frontend lockfile after local setupyonuraily
  • 2026-09-23 15:39Complete LLM tool calling loopyonuraily
  • 2026-09-23 15:26Fix AI service test import pathyonuraily
  • 2026-09-23 15:11docs: define Product Service scopeUlykpan
  • 2026-09-23 15:00Implement AI service integrationyonuraily
  • 2026-09-23 14:56Add frontend cart work planyonuraily
  • 2026-09-23 14:53Add AI integration task planyonuraily
  • 2026-09-23 14:36Create ffUlykpan
  • 2026-09-23 14:22Create nnnyonuraily
  • 2026-09-23 14:16Create kyasminaipanova27-a11y
Структура репозитория (76 файлов)
README.md
ai-service/.env.example
ai-service/.gitignore
ai-service/Dockerfile
ai-service/app/__init__.py
ai-service/app/config.py
ai-service/app/files.py
ai-service/app/history.py
ai-service/app/main.py
ai-service/app/models.py
ai-service/app/product_client.py
ai-service/app/provider.py
ai-service/app/service.py
ai-service/app/tools.py
ai-service/requirements.txt
ai-service/tests/conftest.py
ai-service/tests/test_contracts.py
frontend-cart/frontend-cart-plan.txt
services/product-service/.dockerignore
services/product-service/.env.example
services/product-service/.gitignore
services/product-service/Dockerfile
services/product-service/README.md
services/product-service/SCOPE.txt
services/product-service/app/__init__.py
services/product-service/app/config.py
services/product-service/app/database.py
services/product-service/app/ekt_client.py
services/product-service/app/errors.py
services/product-service/app/load_fixture.py
services/product-service/app/main.py
services/product-service/app/models.py
services/product-service/app/normalizer.py
services/product-service/app/schemas.py
services/product-service/app/service.py
services/product-service/app/sync_catalog.py
services/product-service/compose.yml
services/product-service/fixtures/product_515291_raw.json
services/product-service/requirements-dev.txt
services/product-service/requirements.txt
services/product-service/tests/conftest.py
services/product-service/tests/test_api.py
services/product-service/tests/test_ekt_client.py
services/product-service/tests/test_normalizer.py
web/.env.example
web/.eslintrc.json
web/.gitignore
web/Dockerfile
web/README.md
web/app/api/v1/cart/proposals/[proposal_id]/confirm/route.ts
web/app/api/v1/chat/messages/route.ts
web/app/api/v1/files/route.ts
web/app/globals.css
web/app/layout.tsx
web/app/mock-cart/page.tsx
web/app/page.tsx
web/components/cart/CartConfirmation.tsx
web/components/chat/Chat.tsx
web/components/chat/ChatInput.tsx
web/components/chat/ChatMessage.tsx
web/components/files/FileUpload.tsx
web/components/products/ProductCard.tsx
web/lib/api/client.ts
web/lib/server/availability.ts
web/lib/server/cart-adapter.ts
web/lib/server/proposals.ts
web/lib/server/request.ts
web/lib/types/index.ts
web/next-env.d.ts
web/next.config.mjs
web/package-lock.json
web/package.json
web/postcss.config.mjs
web/public/README.txt
web/tailwind.config.ts
web/tsconfig.json
Ветки (6)

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

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

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