Тихая сосна — помощник по каталогу EKT
Чат-консультант по каталогу ekt.kz: FastAPI-сервер ищет товары, аналоги и наличие, а расширение для Chromium встраивает чат с карточками товаров в…
О проекте
Команда: Tikhaya Sosna
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Прототип
Задача кейса: AI-консультант по каталогу ekt.kz: товары, аналоги, цены, остатки, корзина
Суть
Чат-консультант по каталогу ekt.kz: FastAPI-сервер ищет товары, аналоги и наличие, а расширение для Chromium встраивает чат с карточками товаров в страницы EKT. Корзина реализована только на сервере, в виде предложения действия.
Как устроено
Расширение (WXT, React 19, Shadow DOM, Manifest V3) передаёт текст и контекст страницы через background service worker на POST /api/v1/chat. Серверный оркестратор разбирает запрос (query_parser), ищет товары в локальном каталоге или PostgreSQL, синхронизированном из EKT API, ранжирует их, подбирает альтернативы и проверяет остатки. Ответ собирается по правилам, генеративная модель в рабочем маршруте не подключена. Предложения add2basket создаются и проверяются на сервере, но из расширения не вызываются.
Ключевые решения
- query parsing
- catalog search and ranking
- alternatives matching
- tool-based orchestrator
- Zod response validation
- EKT API sync
Особенности
Формат интеграции необычный: консультант встроен прямо в сайт ekt.kz как браузерное расширение, а не отдельный чат. README честно признаёт, что схемы ответа backend и расширения не совпадают и сквозная демонстрация не завершена.
Стек
Python · FastAPI · Pydantic · HTTPX · PostgreSQL · Docker Compose · TypeScript · React · WXT · Chrome Extension MV3 · Zod · Vitest
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-a97f6ff9-tikhaya-sosna.
README
README.mdТихая сосна — помощник по каталогу EKT
Прототип для пользователей каталога EKT: помогает найти товар по запросу, артикулу или ID, посмотреть доступные сведения о нём и получить текстовый ответ. Проект состоит из FastAPI-сервера и расширения для Chromium, которое показывает чат прямо на страницах EKT.
Состояние текущей версии. Серверный API реализован как отдельный компонент, а расширение содержит чат и карточки товаров. После последнего изменения серверного
/api/v1/chatих товарные ответы не совпадают по схеме: сервер отдаётid,name,price,quantity,url, а валидатор расширения ожидает поля прежнего ответаProductListItemлибо более полный канонический формат. Ответ с найденными товарами сейчас может завершиться в расширении ошибкойBACKEND_INVALID_RESPONSE. Ниже приведён проверяемый сценарий для API; сквозную демонстрацию поиска через расширение нельзя считать завершённой.
Что реализовано
| Компонент | Возможности в репозитории |
|---|---|
| Backend | Поиск каталога по ID, артикулу и тексту; выдача списка и деталей товара; получение деталей и складских данных через EKT API при настроенном доступе; подбор альтернатив и ответы на запросы о наличии с учётом подтверждённых данных. |
| Ассистент | Обработка текстового запроса, обращение к поиску и каталогу, формирование ответа и списка товаров. Ответ собирается по правилам из данных каталога; запущенная конфигурация не подключает генеративную модель. |
| Расширение | Чат на страницах EKT в Shadow DOM, отправка запроса через фоновый процесс, сессия в хранилище браузера, карточки товаров для поддерживаемого ответа, безопасная обработка ссылок, состояния загрузки и ошибки, защита от двойной отправки. |
| Корзина | На сервере есть создание, проверка и отмена предложения действия после проверки остатков. Расширение не добавляет товар в корзину: подтверждение и вызов add2basket не включены. |
Сервер также содержит маршруты GET /health, GET /api/v1/products/, GET /api/v1/products/search, GET /api/v1/products/{id}, GET /api/v1/products/{id}/detail и POST /api/v1/chat. Интерактивная схема доступна по /docs после запуска API.
Как работает решение
- Пользователь открывает страницу EKT и вводит вопрос в чат расширения. Расширение отправляет текст, идентификатор сессии и минимальный контекст страницы в свой фоновый процесс.
- Фоновый процесс делает
POST /api/v1/chatна указанный при сборке адрес FastAPI. Cookies EKT и учётные данные EKT в этот запрос не включаются. - Серверный оркестратор разбирает запрос, ищет товары в локальном каталоге или PostgreSQL. Для отдельных запросов он обращается к деталям EKT API и проверяет наличие по доступным данным.
- API возвращает текст и список товаров. Расширение проверяет ответ перед показом карточек. На текущем
mainшаг отображения найденных товаров блокируется несовпадением схем, указанным выше; отсутствие совпадений может отображаться без карточек.
Страница EKT → content script (React, Shadow DOM)
→ сообщения расширения → background service worker
→ FastAPI /api/v1/chat → оркестратор → каталог / PostgreSQL / EKT API
← проверенный ответ ← JSON
Технологии и интеграции
- Сервер: Python, FastAPI, Pydantic, Uvicorn, HTTPX,
python-dotenv, Psycopg 3. PostgreSQL 16 доступен черезdocker-compose.yml; его можно не подключать для базового запуска API. - Расширение: TypeScript, React 19, WXT, Chrome Manifest V3, Zod; сборка через pnpm, тесты написаны на Vitest и React Testing Library.
- Внешние данные: EKT API для списка и деталей товаров. Его учётные данные используются только сервером и задаются локально через переменные окружения. База PostgreSQL хранит синхронизированный каталог и данные действий корзины, если настроена.
- AI-модель: в текущем запуске не используется. Класс оркестратора допускает внешний генератор текста, но
backend/app/main.pyсоздаёт его без генератора; интеграции с OpenAI или другой моделью в рабочем маршруте нет.
Установка и запуск локально
Нужны Python 3.10+, Node.js 20+, pnpm и браузер на Chromium. Docker Compose нужен, если используется пример подключения к PostgreSQL. Команды ниже выполняются из корня репозитория.
1. Запустить API
python -m venv .venv
source .venv/bin/activate
python -m pip install -r backend/requirements.txt
cp .env.example .env
docker compose up -d postgres
python -m uvicorn app.main:app --app-dir backend --reload
В PowerShell используйте .venv\Scripts\Activate.ps1 и Copy-Item .env.example .env вместо source и cp. Файл .env храните только локально. Для доступа к реальному каталогу заполните в нём EKT_API_USERNAME и EKT_API_PASSWORD выданными команде значениями. Пример .env.example также задаёт подключение к PostgreSQL: если база не запущена, удалите или отключите DATABASE_URL перед стартом API. Без EKT-доступа, синхронизированной базы или локальных файлов data/products.json каталог может быть пустым; эти файлы данных в репозиторий не включены.
При наличии EKT-доступа и PostgreSQL каталог можно предварительно загрузить командой:
PYTHONPATH=backend python -m app.db.sync_catalog
В PowerShell сначала задайте $env:PYTHONPATH = 'backend', затем выполните python -m app.db.sync_catalog. Синхронизация обращается к EKT API и требует настроенных учётных данных.
2. Собрать и открыть расширение
pnpm --dir apps/extension install --frozen-lockfile
WXT_BACKEND_BASE_URL=http://localhost:8000 pnpm --dir apps/extension run build
В PowerShell задайте $env:WXT_BACKEND_BASE_URL = 'http://localhost:8000' и выполните pnpm.cmd --dir apps/extension run build. Затем откройте chrome://extensions, включите режим разработчика, выберите «Загрузить распакованное расширение» и укажите apps/extension/.output/chrome-mv3. Значение WXT_BACKEND_BASE_URL должно быть только адресом backend без /api/v1/chat; при смене адреса нужна новая сборка. Для удалённого адреса конфигурация расширения требует HTTPS.
Как проверить
-
После запуска API откройте
http://localhost:8000/health: ожидаемый ответ —{"status":"ok"}. Откройтеhttp://localhost:8000/docsдля проверки маршрутов через Swagger UI. -
Если EKT-доступ настроен, вызовите в
/docsGET /api/v1/products/?page=1и возьмите ID из полученного списка. Если доступ не настроен и локальных данных нет, список может быть пустым — это не демонстрация поиска. -
В
/docsвызовитеPOST /api/v1/chat, заменивID_ИЗ_СПИСКАреальным числом:{ "session_id": "jury-demo", "message": "Найди товар id:ID_ИЗ_СПИСКА", "attachment_ids": [], "page_context": {} }Проверьте текст ответа и
productsв JSON. Полеquantityможет бытьnull, если наличие не подтверждено; это не нулевой остаток. -
Откройте
ekt.kzс установленным расширением: должен появиться чат, который можно открыть и закрыть. Текущую сквозную выдачу карточек через этот чат не следует использовать как успешный критерий до согласования формата ответа backend и расширения. Проверка в настоящем браузере и с живым EKT в рамках подготовки этого README не проводилась.
Ограничения текущей версии
- Формат товарного ответа текущего
/api/v1/chatне поддерживается валидатором расширения. API и UI следует проверять отдельно до исправления контракта. - В репозитории нет готового каталога. Поиск по названию без EKT-доступа, локальных данных или предварительной синхронизации PostgreSQL может не вернуть товары.
- Корзина из расширения недоступна: текущая проверка действия не возвращает подтверждённое значение
kratnost, необходимое для безопасного EKTadd2basket. Никакая покупка или оформление заказа не выполняются. - Загрузка вложений не доступна:
backend/app/api/files.pyпуст, маршрут не подключён, а расширение отправляет пустой списокattachment_ids. Наличие парсеров PDF, DOCX, XLSX и изображений в исходниках не означает работающий пользовательский сценарий загрузки. - Сессия расширения не является пользовательской аутентификацией. Публичное развёртывание требует отдельной проверки доступа и защиты backend.
- Подтверждённой ссылки на опубликованную версию в репозитории нет; проект запускается локально по инструкции выше.
Дополнительные инструкции по сборке: README расширения.
Авторы коммитов
История коммитов
- 2026-09-23 17:57readmekutenchik
- 2026-09-23 17:47Merge remote-tracking branch 'origin/main'kutenchik
- 2026-09-23 17:38feat(extension): finish hackathon extension [EXT-FINAL]kutenchik
- 2026-09-23 17:32fix: support Windows sync and configurable postgres portkutenchik
- 2026-09-23 17:07fix(extension): support merged backend chat response [EXT-05-06F]kutenchik
- 2026-09-23 17:02feat(assistant): integrate chat with catalog and cart proposalsNikita Bychkov
- 2026-09-23 16:56merge: integrate backend and AI workkutenchik
- 2026-09-23 16:41feat(extension): connect backend chat and product cards [EXT-05-06]kutenchik
Все коммиты (21)
- 2026-09-23 16:35Merge pull request #1 from BAITC-Hacks/ai-solutionsNikita Bychkov
- 2026-09-23 16:35Merge branch 'main' into ai-solutionsNikita Bychkov
- 2026-09-23 16:27smart aiNikita Bychkov
- 2026-09-23 16:09feat(extension): add session storage and page context [EXT-04]kutenchik
- 2026-09-23 15:56fix: сохранять артикул и характеристики при обновлении каталогаDiyar Zhumatayev
- 2026-09-23 15:56chore(repo): ignore local environment fileskutenchik
- 2026-09-23 15:51feat(extension): implement Shadow DOM chat shell [EXT-03]kutenchik
- 2026-09-23 15:33feat(extension): add typed runtime messaging [EXT-02]kutenchik
- 2026-09-23 15:28feat: добавить API каталога EKT и проверку действий корзиныDiyar Zhumatayev
- 2026-09-23 15:21feat(extension): bootstrap WXT application [EXT-01]kutenchik
- 2026-09-23 15:11fix(extension): make EXT-00 unittest target importable [EXT-00F]kutenchik
- 2026-09-23 15:07chore(extension): establish Codex workflow [EXT-00]kutenchik
- 2026-09-23 14:49apiDiyar Zhumatayev
Структура репозитория (128 файлов)
.env.example .gitignore AGENTS.md README.md apps/extension/.env.example apps/extension/.gitignore apps/extension/AGENTS.md apps/extension/README.md apps/extension/components/App.test.tsx apps/extension/components/App.tsx apps/extension/components/ChatComposer/ChatComposer.test.tsx apps/extension/components/ChatComposer/ChatComposer.tsx apps/extension/components/ChatLauncher/ChatLauncher.tsx apps/extension/components/ChatWidget/ChatWidget.test.tsx apps/extension/components/ChatWidget/ChatWidget.tsx apps/extension/components/MessageList/MessageList.test.tsx apps/extension/components/MessageList/MessageList.tsx apps/extension/components/ProductCard/ProductCard.test.tsx apps/extension/components/ProductCard/ProductCard.tsx apps/extension/config/backend.test.ts apps/extension/config/backend.ts apps/extension/contracts/backend.test.ts apps/extension/contracts/backend.ts apps/extension/contracts/chat.ts apps/extension/contracts/ekt-url.ts apps/extension/contracts/index.ts apps/extension/contracts/limits.ts apps/extension/contracts/product.test.ts apps/extension/contracts/product.ts apps/extension/contracts/runtime.test.ts apps/extension/contracts/runtime.ts apps/extension/contracts/session.ts apps/extension/entrypoints/background.ts apps/extension/entrypoints/chat.content/index.tsx apps/extension/entrypoints/chat.content/style.css apps/extension/package.json apps/extension/pnpm-lock.yaml apps/extension/public/.gitkeep apps/extension/services/backend-client.test.ts apps/extension/services/backend-client.ts apps/extension/services/chat-context.test.ts apps/extension/services/chat-context.ts apps/extension/services/chat-service.test.ts apps/extension/services/chat-service.ts apps/extension/services/index.ts apps/extension/services/page-context.test.ts apps/extension/services/page-context.ts apps/extension/services/runtime-client.test.ts apps/extension/services/runtime-client.ts apps/extension/services/runtime-listener.test.ts apps/extension/services/runtime-listener.ts apps/extension/services/runtime-router.test.ts apps/extension/services/runtime-router.ts apps/extension/services/widget-mount.test.tsx apps/extension/services/widget-mount.tsx apps/extension/state/chat-reducer.test.ts apps/extension/state/chat-reducer.ts apps/extension/state/index.ts apps/extension/storage/index.ts apps/extension/storage/session-storage.test.ts apps/extension/storage/session-storage.ts apps/extension/styles/tokens.css apps/extension/styles/widget.css apps/extension/tests/fixtures/backend-chat-error.json apps/extension/tests/fixtures/backend-chat-legacy-success.json apps/extension/tests/fixtures/backend-chat-success.json apps/extension/tests/setup.ts apps/extension/tsconfig.json apps/extension/vitest.config.ts apps/extension/wxt.config.ts backend/app/ai/assistant.py backend/app/ai/prompts.py backend/app/ai/schemas.py backend/app/ai/tools.py backend/app/api/cart.py backend/app/api/chat.py backend/app/api/files.py backend/app/api/health.py backend/app/api/products.py backend/app/assistant/orchestrator.py backend/app/assistant/prompts.py backend/app/assistant/response_models.py backend/app/assistant/tools.py backend/app/db/database.py backend/app/db/sync_catalog.py backend/app/documents/__init__.py backend/app/documents/excel_parser.py backend/app/documents/image_parser.py backend/app/documents/pdf_parser.py backend/app/documents/word_parser.py backend/app/integrations/ekt/cart_client.py backend/app/integrations/ekt/client.py backend/app/integrations/ekt/mapper.py backend/app/integrations/ekt/schemas.py backend/app/main.py backend/app/repositories/cart_repository.py backend/app/repositories/chat_repository.py backend/app/repositories/product_repository.py backend/app/repositories/terms_repository.py backend/app/search/alternatives.py backend/app/search/query_parser.py backend/app/search/ranking.py backend/app/services/alternative_service.py backend/app/services/cart_service.py backend/app/services/catalog_service.py backend/app/services/certificate_service.py backend/app/services/file_service.py backend/app/services/purchase_terms_service.py backend/app/services/search_service.py backend/app/services/stock_service.py backend/requirements.txt docker-compose.yml docs/extension/API_CONTRACT.md docs/extension/ARCHITECTURE.md docs/extension/BACKEND_CHAT.md docs/extension/CODEX_REPORT_TEMPLATE.md docs/extension/FINAL_STATUS.md docs/extension/RUNTIME_PROTOCOL.md docs/extension/SECURITY.md docs/extension/SESSION_CONTEXT.md docs/extension/TASKS.md docs/extension/TESTING.md docs/extension/UI_SHELL.md scripts/check_ekt_products.py scripts/package_task_artifacts.py tests/__init__.py tests/scripts/__init__.py tests/scripts/test_package_task_artifacts.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.