AAYMA
RU
Войти

Тихая сосна — помощник по каталогу EKT

Чат-консультант по каталогу ekt.kz: FastAPI-сервер ищет товары, аналоги и наличие, а расширение для Chromium встраивает чат с карточками товаров в…

Прототип
Команда «Tikhaya Sosna» 12💬 0 комментариевс 23 сентября 2026 г.

О проекте

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

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

  1. Пользователь открывает страницу EKT и вводит вопрос в чат расширения. Расширение отправляет текст, идентификатор сессии и минимальный контекст страницы в свой фоновый процесс.
  2. Фоновый процесс делает POST /api/v1/chat на указанный при сборке адрес FastAPI. Cookies EKT и учётные данные EKT в этот запрос не включаются.
  3. Серверный оркестратор разбирает запрос, ищет товары в локальном каталоге или PostgreSQL. Для отдельных запросов он обращается к деталям EKT API и проверяет наличие по доступным данным.
  4. 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.

Как проверить

  1. После запуска API откройте http://localhost:8000/health: ожидаемый ответ — {"status":"ok"}. Откройте http://localhost:8000/docs для проверки маршрутов через Swagger UI.

  2. Если EKT-доступ настроен, вызовите в /docs GET /api/v1/products/?page=1 и возьмите ID из полученного списка. Если доступ не настроен и локальных данных нет, список может быть пустым — это не демонстрация поиска.

  3. В /docs вызовите POST /api/v1/chat, заменив ID_ИЗ_СПИСКА реальным числом:

    {
      "session_id": "jury-demo",
      "message": "Найди товар id:ID_ИЗ_СПИСКА",
      "attachment_ids": [],
      "page_context": {}
    }
    

    Проверьте текст ответа и products в JSON. Поле quantity может быть null, если наличие не подтверждено; это не нулевой остаток.

  4. Откройте ekt.kz с установленным расширением: должен появиться чат, который можно открыть и закрыть. Текущую сквозную выдачу карточек через этот чат не следует использовать как успешный критерий до согласования формата ответа backend и расширения. Проверка в настоящем браузере и с живым EKT в рамках подготовки этого README не проводилась.

Ограничения текущей версии

  • Формат товарного ответа текущего /api/v1/chat не поддерживается валидатором расширения. API и UI следует проверять отдельно до исправления контракта.
  • В репозитории нет готового каталога. Поиск по названию без EKT-доступа, локальных данных или предварительной синхронизации PostgreSQL может не вернуть товары.
  • Корзина из расширения недоступна: текущая проверка действия не возвращает подтверждённое значение kratnost, необходимое для безопасного EKT add2basket. Никакая покупка или оформление заказа не выполняются.
  • Загрузка вложений не доступна: backend/app/api/files.py пуст, маршрут не подключён, а расширение отправляет пустой список attachment_ids. Наличие парсеров PDF, DOCX, XLSX и изображений в исходниках не означает работающий пользовательский сценарий загрузки.
  • Сессия расширения не является пользовательской аутентификацией. Публичное развёртывание требует отдельной проверки доступа и защиты backend.
  • Подтверждённой ссылки на опубликованную версию в репозитории нет; проект запускается локально по инструкции выше.

Дополнительные инструкции по сборке: README расширения.

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

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

kutenchik 14Nikita Bychkov 4Diyar Zhumatayev 3

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

  • 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
Ветки (4)

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

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

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