AAYMA
RU
Войти

AI-консультант для EKT.kz

Чат-консультант по каталогу ekt.kz: поиск по артикулу/названию в локальной SQLite-копии каталога, актуальная карточка из EKT API, подбор аналога при…

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

О проекте

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

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

Суть

Чат-консультант по каталогу ekt.kz: поиск по артикулу/названию в локальной SQLite-копии каталога, актуальная карточка из EKT API, подбор аналога при нулевом остатке и demo-корзина с явным подтверждением.

Как устроено

Каталог (15 037 товаров, 752 страницы) синхронизируется из EKT API в SQLite, поиск идёт локально, цены и остатки берутся из EKT detail. /api/chat работает через OpenAI Responses API с function calling поверх сервисов search/detail/analogs; без ключа или при ошибке включается детерминированный fallback (точный артикул + шаблонный ответ). Аналоги ищутся по совпадениям в названиях/свойствах, проверяется до 3 кандидатов. Корзина меняется только после отдельного подтверждения с повторной проверкой остатка.

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

  • OpenAI Responses API
  • function calling
  • SQLite catalog sync
  • deterministic fallback
  • analog matching by name/properties
  • confirmation flow
  • HTTPX MockTransport tests

Метрики

Backend-тесты 60/60, frontend 35/35, итоговый QA 117 passed / 4 failed; синхронизировано 15 037 товаров

Особенности

README честно описывает статус: LLM-режим не подтверждён (ключи давали 401), демо идёт через детерминированный fallback. Двухшаговое подтверждение корзины с повторной проверкой остатка и отказ выдумывать товары (503 до синхронизации).

Стек

Python · FastAPI · Uvicorn · HTTPX · Pydantic Settings · SQLite · HTML/CSS/JS ES modules · Node.js

Модели

OpenAI gpt-5.6-luna


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

README

README.md

AI-консультант для EKT.kz

Прототип для HACKALEM AI: помогает найти электротехнический товар, проверить актуальную цену и остаток, рассмотреть возможный аналог и продемонстрировать добавление в корзину только после явного подтверждения.

Статус сдачи: backend и frontend объединены в integration/ekt, функции заморожены. Рабочий сценарий демонстрируется через deterministic fallback. Интеграция OpenAI реализована, но успешный LLM-сценарий в нашей среде не подтверждён: использованные API keys возвращали HTTP 401 invalid_api_key. Итоговый QA-отчёт: 117 passed / 4 failed, не полностью зелёный. Известные проблемы перечислены ниже.

Что умеет прототип

  • Получает реальный каталог EKT через серверный Basic Auth. Проверенная синхронизация: 15 037 товаров с 752 страниц на 23.09.2026. Это размер конкретного снимка, а не фиксированное число товаров в коде.
  • Ищет по name и article в SQLite без обращения к EKT на каждый поисковый запрос. Точный артикул имеет приоритет, регистр не учитывается, включая кириллицу.
  • Получает актуальную карточку через EKT detail: цену, общий остаток, склады, описание, свойства и изображение, если они предоставлены источником.
  • Предоставляет POST /api/chat: официальный OpenAI Responses API и function calling как основной режим; при отсутствии ключа или ошибке OpenAI — резервный поиск точного артикула и шаблонный ответ по реальному detail. Fallback — детерминированная логика, не LLM и не AI-модель.
  • При нулевом остатке пытается найти доступный аналог по совпадениям в реальных названиях/свойствах. Проверяет максимум три detail кандидатов, объясняет совпадения и не гарантирует взаимозаменяемость. Если данных недостаточно, сообщает об этом.
  • Ведёт demo/session cart в памяти backend: предложение → отдельное подтверждение → повторная проверка остатка → добавление. Без подтверждения корзина не меняется.
  • Включает frontend с поиском, чатом, карточками, отображением аналогов и состояния demo/session cart. Отдельная «Демо-подборка» содержит 8 демонстрационных позиций; она не подменяет реальные ответы API.

Архитектура и стек

Frontend (127.0.0.1:5173)
  → FastAPI (127.0.0.1:8000)
      → Search → SQLite (последний снимок каталога)
      → Detail → EKT API (актуальная карточка)
      → Chat → OpenAI Responses + tools / deterministic fallback
                 → существующие Search + Detail
                 → AnalogService при нулевом остатке
      → Demo/session cart → подтверждение на сервере → EKT detail

Ручная синхронизация: EKT API → SQLite
ЧастьТехнологии
BackendPython, FastAPI, Uvicorn, HTTPX, Pydantic Settings, встроенный sqlite3
OpenAIОфициальный Python SDK openai==2.48.0, Responses API, gpt-5.6-luna по умолчанию; другой моделью автоматически не заменяется
FrontendHTML, CSS, JavaScript ES modules; небольшой Node.js HTTP-сервер, без npm-зависимостей
ТестыPython unittest, fake LLM/HTTPX MockTransport; Node.js test runner

Основные файлы: backend/main.py — endpoints/CORS; catalog.py — SQLite; sync_catalog.py — синхронизация; ekt_service.py — EKT HTTP-клиент; chat.py / chat_fallback.py — чат; analogs.py — кандидаты замены; demo_cart.py — подтверждение. Frontend находится в frontend/, backend-тесты — в tests/.

Запуск с нуля

Нужны Git, Python 3.9+, Node.js 20+ с npm, доступ к интернету и выданные credentials EKT. Все команды ниже — для macOS/Linux. Backend и frontend запускаются на одном компьютере. SQLite в Git не хранится: на новой машине её нужно загрузить.

1. Получить репозиторий и установить backend

Для клонирования именно финальной сборки ветка integration/ekt должна быть опубликована командой. Этот аудит не выполняет push: пока ветка существует только локально, используйте предоставленную копию этой ветки и начните с создания venv. Более ранний main не равен итоговой сборке.

git clone --branch integration/ekt https://github.com/BAITC-Hacks/hack-f6cfd1cd-go-team.git
cd hack-f6cfd1cd-go-team
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
cp -n .env.example .env

В уже клонированном проекте выполняйте команды из его корня; повторное клонирование не нужно. cp -n сохраняет существующий .env.

2. Настроить локальный .env

EKT_API_BASE_URL=https://ekt.kz/api
EKT_API_USERNAME=
EKT_API_PASSWORD=
OPENAI_API_KEY=
OPENAI_MODEL=gpt-5.6-luna
ПеременнаяНазначение
EKT_API_BASE_URLБазовый HTTPS-адрес EKT API
EKT_API_USERNAME, EKT_API_PASSWORDЗаполнить выданными реквизитами для синхронизации и detail
OPENAI_API_KEYНеобязателен для fallback; нужен для основного LLM-режима
OPENAI_MODELМодель Responses API, по умолчанию gpt-5.6-luna
CATALOG_DB_PATHНеобязательный путь SQLite; по умолчанию data/catalog.sqlite3 в корне проекта. Для переопределения удобнее абсолютный путь

Значения credentials вводятся только локально, никогда во frontend и не в Git. Для воспроизводимой fallback-демонстрации оставьте OPENAI_API_KEY пустым: это исключит ожидание ошибочного OpenAI-запроса. Переменные окружения процесса имеют приоритет над .env; после изменения настроек перезапустите сервер.

3. Загрузить реальный каталог

python -m backend.sync_catalog

Команда последовательно получает страницы и печатает прогресс. Загрузка может занять несколько минут. Пустая страница или повтор первой страницы означает конец; существует защитный предел обхода. При временных ошибках предусмотрены ограниченные повторы. Обновление публикуется одной транзакцией; при сбое предыдущий каталог сохраняется. Эта же команда используется для ручного обновления. До первой успешной синхронизации поиск возвращает 503, а не выдуманные товары.

4. Запустить FastAPI

python -m uvicorn backend.main:app --reload --host 127.0.0.1 --port 8000

Документация: http://127.0.0.1:8000/docs. Для MVP используйте один worker: история, pending confirmation и demo-cart хранятся в памяти одного процесса. Перезапуск, в том числе reload, очищает их.

5. Запустить frontend в другом терминале

cd hack-f6cfd1cd-go-team/frontend
npm run dev

Если терминал уже открыт в корне проекта, используйте cd frontend. Устанавливать npm-зависимости не требуется. Откройте http://127.0.0.1:5173. CORS разрешает именно этот origin, GET/POST и Content-Type, без wildcard и cookies. http://localhost:5173 — другой origin. Подробности: frontend/README.md; описания ранних этапов в нём могут отставать от итогового кода и этого README.

Основные API

МетодEndpointИсточник
GET/api/products?page=1Реальная страница EKT
GET/api/products/search?q=200300285_Локальная SQLite
GET/api/products/detail?id=515291Актуальный EKT detail
POST/api/chatOpenAI/tools либо fallback; серверный confirmation flow

Контракты: поиск и detail, чат, аналоги и demo/session cart.

Запрос чата: {"message":"Есть ли товар 200300285_ в наличии и сколько он стоит?","session_id":null}. Для следующего сообщения передавайте session_id из ответа. Ответ содержит session_id, message, products, analogs, mode, tools_used, cart, pending_confirmation. mode — openai или fallback; детерминированный flow корзины также обозначен fallback.

products[].quantity — остаток EKT; cart.items[].quantity — количество в demo-cart. При сетевых ошибках данные не подменяются демонстрационными. Некорректные параметры дают 422; остальные форматы ошибок описаны в контрактах.

Сценарий демонстрации

  1. Поиск. В строке каталога введите 200300285_. Ожидается товар ID 515291. Наличие в поисковой выдаче не выдаётся за актуальное: для него нужен detail.
  2. Цена и наличие. В чат: Есть ли товар 200300285_ в наличии и сколько он стоит?. Backend выполняет search и EKT detail; при последней реальной проверке получены цена 64920 и остаток 23. Не фиксируйте эти числа как неизменные.
  3. Отсутствующий товар → аналог. В чат: Есть ли товар ярп4520 в наличии? Если нет, предложи аналог. При проверке исходный ID 45357 имел остаток 0, кандидат 150200474_ / ID 18284 — 341. Основание: совпало название LED STARK, включая 30W, 2400Lm, d98x180, 4000K, IP20. Остатки могут измениться, тогда результат будет другим.
  4. Подтверждение. В том же диалоге: Добавь 2 штуки товара 200300285_. Убедитесь, что cart.items ещё пуст, а pending_confirmation.quantity равно 2. Затем отдельным сообщением Да, добавь: backend повторно проверяет остаток и добавляет в demo/session cart. Нет, Отмена, неоднозначный ответ и повторное подтверждение не добавляют товар.

Пример через терминал:

curl -sS http://127.0.0.1:8000/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"message":"Добавь 2 штуки товара 200300285_"}'

Скопируйте возвращённый session_id вместо UUID_ИЗ_ОТВЕТА:

curl -sS http://127.0.0.1:8000/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"message":"Да, добавь","session_id":"UUID_ИЗ_ОТВЕТА"}'

Тестирование и статус QA

Из корня проекта с активированной venv:

python -m unittest discover -s tests -v

Backend: 60/60, повторно запущены при финальной подготовке. Тесты используют временные базы, fake LLM и HTTPX MockTransport, не расходуют OpenAI API и не меняют реальную SQLite.

cd frontend
npm test
npm run check

Frontend: 35/35 по переданному отчёту до merge. В среде финального аудита npm отсутствует, повторный запуск не выполнен; frontend не изменялся.

Отдельный финальный QA-отчёт команды: 117 passed / 4 failed. Он учтён по предоставленному результату, не перезапускался здесь; QA-ветка не мержилась. Эти числа относятся к отдельному набору проверок и не складываются с 60/60 и 35/35. Полная приёмка не пройдена.

Предыдущий замер по реальным 15 037 товарам через FastAPI TestClient: точный артикул — медиана 0,77 мс, Legrand (668 результатов) — 8,53 мс. Это локальное измерение без TCP/браузера; время чата зависит от EKT/OpenAI.

Known limitations

Четыре незакрытых класса проблем из финального QA (не исправлены в рамках feature freeze):

  1. Раскрытие конфликтующих характеристик в fallback. Шаблонный ответ не гарантирует предупреждение о противоречии названия/описания и properties. Например, у 515291 встречались 160 А в названии и 250 А в свойстве. Нельзя использовать ответ как техническое заключение.
  2. Чувствительные данные в истории сессии. Нет автоматической очистки/маскирования пользовательского текста перед сохранением в памяти и передачей контекста OpenAI. Не вводите персональные, платёжные или секретные данные. TTL и ограничения объёма не заменяют такую защиту.
  3. Подбор аналогов при конфликтующих характеристиках. Эвристика не гарантирует выявление всех внутренних противоречий между полями и названием. Возможный аналог требует проверки специалистом; полная взаимозаменяемость не подтверждена.
  4. Нет серверной верификации произвольных фактических утверждений LLM. Инструкции требуют опираться на tools, а структурированные products собирает backend, но свободный текст модели не проходит независимую проверку каждого факта. Это не гарантия отсутствия выдуманных утверждений.

Другие границы прототипа:

  • Настоящий API корзины EKT не предоставлен. Demo/session cart не резервирует товар, не создаёт заказ и не имеет настоящей checkout/cart URL. Отдельная корзина frontend-демо-подборки в localStorage не равна серверной session cart.
  • Сертификаты/ссылки на них не обнаружены в проверенной карточке EKT detail. Это не доказывает отсутствие сертификатов у всех товаров; путь получения не подтверждён.
  • OpenAI интеграция реализована, но используемые ключи в нашей среде возвращали 401. Доступность gpt-5.6-luna именно для проекта не подтверждена. Рабочая демонстрация использует deterministic fallback, а не успешную генерацию LLM.
  • Fallback поддерживает точные артикулы, а не произвольное понимание свободного текста; demo-cart — ограниченный формат команды. Аналоги ищутся среди небольшого числа кандидатов, результат не гарантирован для любого товара.
  • SQLite отражает последнюю успешную синхронизацию; detail получает актуальные данные EKT. Новые товары и изменения названий появятся в поиске после следующей синхронизации. EKT может вернуть таймаут/ошибку, единый снимок каталога во время загрузки не гарантирован.
  • Сессии ограничены 100 записями, 6 ходами и 60 000 символами истории; TTL — 30 минут неактивности. Нет авторизации пользователей, постоянной истории или production-защиты публичного API от злоупотреблений. MVP рассчитан на локальную демонстрацию.
  • Подтверждённые условия оплаты/доставки/минимальной партии не загружены; обработка вложений, реальное оформление заказа и платёжная интеграция не реализованы. Прототип не закрывает все требования исходного ТЗ.
  • «Демо-подборка» frontend содержит отдельные тестовые допущения о наличии, валюте и единицах; её нельзя представлять как актуальный каталог. Реальный поиск и чат используют backend.

Безопасность и данные

Credentials EKT/OpenAI находятся только в server-side .env, не передаются frontend и не входят в Git. .gitignore исключает .env, виртуальное окружение, SQLite/data, node_modules и генерируемые файлы. В репозитории хранится только пустой .env.example.

Изменение demo-cart выполняет серверный код, не LLM: отдельное явное подтверждение, повторная проверка актуального остатка, учёт уже добавленного количества, защита от повторного подтверждения. Реальная корзина сайта не изменяется.

Данные товаров берутся из SQLite/EKT tools; отсутствующие поля не должны выдумываться. Серверные credentials в tool output не входят. Frontend использует textContent для внешнего текста и проверяет товарные ссылки. Ограничения проверки свободного текста модели и приватности истории явно перечислены в Known limitations.

Документация кейса

Документация находится в корне, отдельной папки docs/ нет. Исторические примеры цен, остатков и измерений — результаты конкретных проверок, не обещание текущих значений.

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

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

szhakano 11Yernat "GhostOfAstana" Soltanbekov 7MrAitzhanovAzamat 4

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

  • 2026-09-23 17:55docs: finalize hackathon READMEszhakano
  • 2026-09-23 17:49test: activate EKT chat, analog and demo-cart acceptanceYernat "GhostOfAstana" Soltanbekov
  • 2026-09-23 17:48test: publish EKT chat QA harness and final findingsYernat "GhostOfAstana" Soltanbekov
  • 2026-09-23 17:47Merge pull request #1 from BAITC-Hacks/backendYernat "GhostOfAstana" Soltanbekov
  • 2026-09-23 17:44merge: integrate frontendszhakano
  • 2026-09-23 17:41merge: integrate backendszhakano
  • 2026-09-23 17:31feat(frontend): display chat analogs and session cartMrAitzhanovAzamat
  • 2026-09-23 17:23feat: add confirmed demo cart flowszhakano
Все коммиты (22)
  • 2026-09-23 17:22Upgraded frontendMrAitzhanovAzamat
  • 2026-09-23 17:19feat(frontend): connect chat API with session handlingMrAitzhanovAzamat
  • 2026-09-23 17:15test: add EKT endpoint QA and deferred chat acceptance testsYernat "GhostOfAstana" Soltanbekov
  • 2026-09-23 17:14docs: add EKT AI logic and QA acceptance matrixYernat "GhostOfAstana" Soltanbekov
  • 2026-09-23 17:13test: initialize EKT QA directoryYernat "GhostOfAstana" Soltanbekov
  • 2026-09-23 17:10feat: add AI chat with EKT grounded fallbackszhakano
  • 2026-09-23 16:58Adding ai functions to backendszhakano
  • 2026-09-23 16:42continue backendszhakano
  • 2026-09-23 16:05feat: implement chat interfaceMrAitzhanovAzamat
  • 2026-09-23 15:45chore: remove unrelated RSI filesszhakano
  • 2026-09-23 15:22feat: add SQLite catalog sync and fast product searchszhakano
  • 2026-09-23 15:21feat: add RSI signals and simple backtesterYernat "GhostOfAstana" Soltanbekov
  • 2026-09-23 14:57feat: add local product searchszhakano
  • 2026-09-23 14:46feat: add EKT product searchszhakano
Структура репозитория (46 файлов)
.env.example
.gitignore
README.md
acceptance-checklist.md
api-contract.md
backend/__init__.py
backend/analogs.py
backend/catalog.py
backend/chat.py
backend/chat_fallback.py
backend/config.py
backend/demo_cart.py
backend/ekt_service.py
backend/main.py
backend/sync_catalog.py
chat-api-contract.md
ekt-api.md
frontend/README.md
frontend/api.js
frontend/app.js
frontend/catalog.js
frontend/chat-api.js
frontend/domain.js
frontend/favicon.svg
frontend/index.html
frontend/live-chat.js
frontend/live-search.js
frontend/package.json
frontend/search-model.js
frontend/server.mjs
frontend/styles.css
frontend/tests/api.test.mjs
frontend/tests/chat.test.mjs
frontend/tests/domain.test.mjs
frontend/tests/search-model.test.mjs
requirements.md
requirements.txt
sources-and-open-questions.md
tests/test_analogs.py
tests/test_backend.py
tests/test_chat.py
tests/test_cors.py
tests/test_demo_cart.py
tests/test_detail.py
tests/test_fallback.py
tests/test_search.py
Ветки (4)

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

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

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