О проекте
Команда: BioGraph
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: AI-консультант по каталогу ekt.kz: товары, аналоги, цены, остатки, корзина
Суть
Low-code чат-консультант для ekt.kz на n8n: поиск по каталогу, аналоги при нулевом остатке, условия доставки и оплаты, прототипная корзина с подтверждением. Есть публичная демо-страница.
Как устроено
AI-агент в n8n workflow ekt_assistant (OpenAI Chat Model, Postgres Chat Memory) вызывает инструменты-ноды: search_products, get_product, find_analogs, purchase_terms, prepare_cart_intent, confirm_add_to_cart и get_cart. Каталог лежит в Postgres/Supabase: 40 реальных товаров импортированы из API ekt.kz через Basic Auth, плюс синтетические TEST-*. Поиск строится на русском полнотексте и pg_trgm word_similarity; pgvector подключён, но embeddings не рассчитаны. Корзина меняется только следующим сообщением-согласием с проверкой сессии, 15-минутного срока намерения и остатка.
Ключевые решения
- n8n AI Agent с tool-нодами
- PostgreSQL full-text search
- pg_trgm
- pgvector (без embeddings)
- consent-gated cart
- импорт каталога через Basic Auth API
Особенности
Решение почти без кода, на n8n workflows и SQL. README честно перечисляет ограничения: embeddings не рассчитаны, вложения не обрабатываются, корзина ekt.kz не меняется. Первые коммиты от 19.09 — это подготовка n8n-скаффолда, удалённая к старту.
Стек
n8n · PostgreSQL · Supabase · pgvector · Docker Compose · HTML · GitHub Actions
Модели
OpenAI Chat Model (n8n)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-80d7035f-biograph.
README
README.mdekt.kz AI assistant (https://ekt-assistant-hackalem-2026.koncevojdanila10.chatgpt.site/)
Открыть публичное демо · Каталог товаров · Результаты проверок
Чат-консультант для ekt.kz: поиск товаров, характеристики, остатки по складам, сертификаты, аналоги и условия покупки. Цена и наличие берутся только из базы каталога.
Быстрый запуск
Нужны Docker с Docker Compose и доступ к OpenAI API. Команда docker compose up -d запускает Postgres и n8n; при первом запуске затем нужно вручную создать credentials, импортировать и опубликовать workflows по шагам ниже. Credentials из облачного экземпляра не переносятся с JSON. Статическая страница site/demo/index.html разворачивается отдельно; сервис сайта в Compose пока не включён.
-
Скопируйте шаблон окружения:
Copy-Item .env.example .env -
Замените
POSTGRES_PASSWORDиN8N_ENCRYPTION_KEYв.envна собственные секретные значения. Файл.envне коммитится. -
Запустите локальный стек:
docker compose up -d -
Откройте n8n: http://localhost:5678. При первом запуске создайте владельца n8n.
-
Создайте credential типа Postgres с параметрами из
.env:- Host:
postgres(если n8n запущен через этот Docker Compose); - Port:
5432; - Database: значение
POSTGRES_DB; - User: значение
POSTGRES_USER; - Password: значение
POSTGRES_PASSWORD; - SSL: выключен для локального Docker.
- Host:
-
Создайте credential типа OpenAI со своим API-ключом. Импортируйте
n8n/workflows/ekt_assistant.jsonи назначьте локальный Postgres credential нодамGuard chat and cart confirmation,Postgres Chat Memory,catalog_overview,search_products,get_product,find_analogs,purchase_terms,prepare_cart_intent,confirm_add_to_cartиget_cart. Выберите созданный OpenAI credential вOpenAI Chat Model; при необходимости выберите модель, доступную вашему API-аккаунту. -
Импортируйте и опубликуйте
n8n/workflows/ekt_cart_view.json, назначив Postgres credential нодеLoad cart. Вconfirm_add_to_cartиget_cartзамените базовый URLhttps://marindsain8n.ru/webhook/ekt-cartнаhttp://localhost:5678/webhook/ekt-cart, затем опубликуйтеekt_assistant. Для уже существующей локальной БД (том Docker создан раньше) импортируйтеn8n/workflows/ekt_cart_schema.json, назначьте локальный Postgres credential нодамInstall cart schemaиSync verified purchase termsи выполните workflow вручную. Новые init-скрипты выполняются автоматически только при создании пустого тома; установочный workflow публиковать не нужно. -
Откройте production Chat URL из
Chat Triggerи выполните локальные проверки ниже. Сразу после установки доступны только синтетические артикулыTEST-*. Для реального каталога дополнительно импортируйтеn8n/workflows/ekt_catalog_import.json, создайте HTTP Basic Auth credential с данными, полученными от партнёра, назначьте его нодеFetch product details, а локальный Postgres credential — нодамExisting catalog coverage,Upsert productsиVerify PDF catalog coverage. Затем нажмите Execute workflow. Артикул200300273_используйте в проверках только после успешного импорта.
Уже работающий облачный вариант
На https://marindsain8n.ru создан и опубликован workflow ekt_assistant. Его Postgres credential подключён к Supabase через Session pooler (порт 5432). SQL из db/init.sql, db/cart.sql и db/terms.sql выполнен в Supabase. Повторные проверки 23 сентября 2026 года подтвердили товар по артикулу, аналог при нулевом остатке, составной вопрос о доставке/оплате/минимальной партии, отказ от добавления и запрет количества сверх остатка.
Для загрузки репрезентативной выборки реального каталога используйте n8n/workflows/ekt_catalog_import.json (workflow ekt_catalog_import). Он по нажатию Execute workflow запрашивает детальные данные 40 товаров из предоставленных PDF через Basic Auth API ekt.kz и обновляет products в Supabase по артикулу. Импорт проверен: 40 товаров получили реальные цены и остатки; повторный запуск обновит те же строки. Логин и пароль API хранятся только в HTTP Basic Auth credential n8n. Идентификаторы товаров для выборки находятся в ноде Sample product IDs; для расширения выборки потребуется согласованно обновить ID в Sample product IDs, Existing catalog coverage и Verify PDF catalog coverage. Перед защитой этот список и рабочий импорт не изменяйте.
В API списка есть id, article, name, price и URL карточки. Надёжный остаток по складам и характеристики берутся из /api/products/detail?id=.... Если сертификат в детальном ответе отсутствует, поле сертификата остаётся пустым. Категория для импортируемых товаров выводится из пути URL карточки. Поле embedding у этих 40 товаров пока пустое; find_analogs использует сходство названий через pg_trgm, когда векторов нет. Синтетические записи TEST-* остаются в базе для демонстрационных проверок. Семантические embeddings реального каталога не рассчитаны: search_products выполняет точный/частичный поиск по артикулу и имени, русский полнотекстовый поиск по имени/категории и приблизительное сравнение через word_similarity, а векторное сравнение в find_analogs используется только при наличии совместимых векторов. Установленный pgvector сам по себе не означает, что полноценный семантический поиск уже реализован.
Прототипная корзина
На хостинговом n8n опубликованы ekt_cart_view и обновлённый ekt_assistant. Корзина хранится в нашей БД, не в корзине сайта ekt.kz: предоставленный партнёром API содержит только чтение каталога, без метода изменения корзины. В чат сначала отправляют, например, «Добавь 1 штуку артикула 200300273_». Инструмент prepare_cart_intent проверяет товар и остаток, сохраняет намерение и просит отдельное подтверждение. Лишь на следующем сообщении «Да, добавь» / «Иә, қос» инструмент confirm_add_to_cart сверяет исходный текст клиента, сессию, срок намерения (15 минут), отдельное выполнение и текущий остаток, затем атомарно меняет корзину. При успехе выдаётся ссылка на актуальное состояние корзины. Перед AI узел Guard chat and cart confirmation проверяет формат sessionId и отменяет прежнее неподтверждённое намерение, если текущее сообщение не является явным согласием. После отказа или другого вопроса нужно заново попросить добавить товар. Без согласия и при превышении остатка корзина не меняется. Ссылка содержит случайный токен доступа; не публикуйте её публично. Заказ и оплата в прототипе недоступны.
Локально db/cart.sql и db/terms.sql выполняются при первом запуске пустого Postgres-тома. Скрипты db/cart.sql и db/terms.sql идемпотентны. Не запускайте повторно целиком db/init.sql поверх существующей БД: его исходные демонстрационные записи terms могут дублироваться. На уже созданной БД запустите workflow ekt_cart_schema вручную после db/init.sql: он также обновит проверенные условия покупки и уберёт демонстрационные ссылки на сертификаты. Этот workflow предназначен только для установки схемы и не публикуется. Секреты остаются в credentials n8n и .env.
Данные
При первом создании локальной БД Docker последовательно выполняет db/init.sql, db/cart.sql и db/terms.sql. Они создают и заполняют:
productsс ценой, остатками, характеристиками, сертификатом, ссылкой на карточку и embedding;termsдля доставки, оплаты и минимальной партии; содержимоеdb/terms.sqlсверено с публичными страницами ekt.kz;n8n_chat_historiesдля истории чата по sessionId;cart_sessions,cart_pending,cart_itemsдля прототипной корзины;- синтетические записи
TEST-001,TEST-000,TEST-002иTEST-003.
TEST-000 имеет нулевой остаток, а TEST-002 и TEST-003 пригодны для проверки аналогов. Все TEST-* — синтетические записи, не реальные карточки ekt.kz; фальшивые ссылки на сертификаты удалены. На облачном демо рядом с тестовыми строками уже загружены 40 реальных товаров; тестовые строки оставлены для воспроизводимых проверок. Basic Auth API-данные хранятся только в credentials n8n или .env.
Проверка
В чате workflow отправляйте запросы ниже по одному. «Да, добавь» отправьте отдельным сообщением только после того, как ассистент повторит артикул и количество и попросит подтверждение. Этот набор работает на свежей локальной БД без доступа к API партнёра:
Покажите товар по артикулу TEST-001
У товара TEST-000 нулевой остаток, предложите аналог
Какие условия доставки, оплаты и минимальной партии?
Добавь 1 штуку по артикулу TEST-001
Да, добавь
Ожидается: ответ с данными из БД и явной пометкой тестовых товаров, аналоги при нулевом остатке, условия доставки из terms и добавление в прототипную корзину только после отдельного подтверждения. Откройте полученную ссылку и проверьте товар и количество. Также проверьте отказ («нет») и количество больше остатка — корзина не должна меняться.
Подключение к сайту
Проверен публичный сайт ekt.kz; подготовлены инструкция для владельца сайта и фрагмент для встраивания. У команды пока нет доступа к шаблону/админке, поэтому чат не установлен на ekt.kz. Предоставленный API позволяет только читать каталог, поэтому настоящая корзина ekt.kz не изменяется. Для установки и подключения настоящей корзины нужны доступ владельца сайта и документированный серверный метод добавления товара. Вложения (фото, PDF, Excel, Word) пока не обрабатываются; не заявляйте эту возможность на демонстрации.
Отдельный публичный демо-сайт
Рабочая страница: ekt-assistant-hackalem-2026.koncevojdanila10.chatgpt.site. Исходник: site/demo/index.html, сведения о публикации: site/demo/README.md. Страница использует собственный адаптивный интерфейс чата без iframe. Браузер отправляет в опубликованный Chat Trigger n8n POST JSON с полями action: "sendMessage", sessionId и chatInput; ответ отображается в том же окне. История интерфейса и случайный идентификатор сессии хранятся в sessionStorage этой вкладки, кнопка «Новый диалог» создаёт новый sessionId. Серверный контекст диалога хранится отдельно в Postgres Chat Memory. В интерфейсе предусмотрены ожидание ответа, ошибка соединения и ручное повторение запроса; автоматического повторного добавления в корзину после сетевой ошибки нет.
Товары, цены и остатки приходят из Postgres/Supabase через workflow, а не зашиты в страницу. API-ключи и пароль БД в HTML отсутствуют. Для размещения этой страницы с собственным n8n замените ENDPOINT в site/demo/index.html на production Chat URL своего экземпляра, опубликуйте workflow и разрешите origin сайта в настройках CORS Chat Trigger. По умолчанию исходник обращается к облачному n8n, а не к БД, поднятой локальным Compose.
Сайт публичен по ссылке, но не установлен на ekt.kz; корзина остаётся прототипной без оформления заказа. Полноценный семантический поиск по реальному каталогу и обработка вложений (фото, PDF, Excel, Word) пока не реализованы. Ссылку на сертификат ассистент может вернуть только для товара, у которого она действительно есть в БД.
Импорт всех товаров из предоставленных PDF
23.09.2026 выполнен импорт №3191: до запуска в БД были 8 из 40 выбранных товаров, после — 40/40, список отсутствующих ID пуст. Добавлены 32 товара, прежние 8 обновлены. Подробная карточка ID 515291 входит в эти 40 и не создаёт дубль. Это все товары из двух PDF-страниц списка, а не весь каталог ekt.kz.
Импорт загружает детальные ответы API группами по 5, проверяет полноту/уникальность, сохраняет цены, остатки по складам, свойства, описание, изображение, варианты и URL. Все upsert-запросы идут в одной транзакции. Пустая цена/остаток не преобразуются в ноль. Корзины и TEST-* не изменяются. Basic Auth остаётся в существующем credential n8n.
Назначьте Postgres credential также нодам проверки покрытия до/после импорта. Подробности и перечень всех 40 артикулов: CATALOG_IMPORT_REPORT.md. Для карточки 200300285_ отдельно проверено предупреждение ассистента о противоречии 160 A / 250 A в исходных данных.
Витрина товаров из БД и фотографии
Отдельный демонстрационный сайт показывает каталог под чатом: карточки с фото, названием, артикулом, ценой и остатком; поиск по названию/артикулу, категории и фильтр «Только в наличии». Кнопка «Спросить о товаре» отправляет вопрос в текущий диалог и не добавляет товар в корзину.
Источник витрины — публичный read-only GET https://marindsain8n.ru/webhook/ekt-catalog, workflow ekt_catalog_view (экспорт n8n/workflows/ekt_catalog_view.json). Импортируйте его в n8n, выберите существующий Postgres credential в Read public catalogue и опубликуйте. Запрос читает только импортированные нетестовые строки products: публичные поля карточки, категории и агрегированные счётчики. История диалогов, сессии, корзины и credentials наружу не передаются. Ошибка БД возвращает безопасный HTTP 503, не пустой каталог. Для своего n8n измените CATALOG_ENDPOINT и ENDPOINT в site/demo/index.html; новых переменных окружения нет.
Чат использует catalog_overview для «сколько товаров?»/«что есть?» и отделяет этот запрос от get_cart. Поиск учитывает русские словоформы, нормализованные категории и приблизительное совпадение; синтетические TEST-* не попадают в обычный обзор. Фото передаются в поле image_url и отображаются безопасно, только с HTTPS-домена ekt.kz. Если фото нет или оно не загрузилось, показывается явный текст, без подмены изображением другого товара.
На контрольном снимке: 40 реальных товаров, 22 позиции с положительным остатком, 39 URL фотографий; это выборка из PDF, не весь каталог ekt.kz. Кабелей в ней нет. Цены и остатки читаются из БД и являются снимком последнего импорта, не обещанием наличия в реальном времени.
Финальная проверка и воспроизведение
Для локального запуска сначала скачайте/клонируйте этот репозиторий и откройте терминал в его корневой папке (где лежит docker-compose.yml). Доступ к приватному репозиторию необходимо заранее выдать проверяющему; публичное демо доступно без доступа к GitHub.
После настройки .env и запуска из раздела «Быстрый запуск» проверьте:
docker compose config --quiet
docker compose ps
docker compose exec postgres sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT count(*) AS products FROM products;"'
Postgres должен быть healthy, n8n — running. На свежей БД ожидаются 4 синтетических товара TEST-. После описанного импорта добавятся 40 реальных товаров. Публичная витрина и catalog_overview намеренно исключают TEST-, поэтому до импорта они показывают 0 — это не ошибка подключения.
Для отдельной страницы после настройки обоих URL и публикации workflows (включая ekt_catalog_view) запустите из корня репозитория:
# Требуется установленный Python 3; на macOS/Linux команда может называться python3.
python -m http.server 8080 --bind 127.0.0.1 --directory site/demo
Откройте http://localhost:8080. Для локального запуска используйте production Chat URL локального n8n в ENDPOINT, http://localhost:5678/webhook/ekt-catalog в CATALOG_ENDPOINT; разрешите origin http://localhost:8080 в CORS Chat Trigger. Не открывайте страницу через file://. Иначе при неизменённых URL она продолжит обращаться к облачному демо, а не к вашей локальной БД.
Необязательные автоматические тесты интерфейса (Node.js 18+):
node site/demo/tests.cjs
Статус проверки запуска: облачный опубликованный сценарий и тесты интерфейса выполнены. Полный fresh-install через Docker на машине проверки не выполнен: Docker CLI/Desktop отсутствуют. Compose, переменные и порядок SQL проверены статически. Образ n8n пока указан как latest; его воспроизведение в будущую дату не гарантирует тот же runtime. Перед защитой не обновляйте рабочий инстанс и не удаляйте Docker volumes. Пароли/ключи, случайные ссылки доступа к корзинам и реальные .env не прикладывайте к отчётам.
Авторы коммитов
История коммитов
- 2026-09-23 17:49fix: use high detail for product photo OCRMarFedorovna
- 2026-09-23 17:48test: add portable synthetic attachment smoke checksMarFedorovna
- 2026-09-23 17:45feat: enable safe attachments in public demoMarFedorovna
- 2026-09-23 17:44feat: add validated document and image extraction workflowMarFedorovna
- 2026-09-23 17:39Create smoke.ymlci: verify clean Docker startup and workflow importsMarFedorovna
- 2026-09-23 17:29Update README.mdMarFedorovna
- 2026-09-23 17:28Update README.mdMarFedorovna
- 2026-09-23 17:26docs: final smoke checks and reproducible setupMarFedorovna
Все коммиты (59)
- 2026-09-23 17:25Update README.mdMarFedorovna
- 2026-09-23 17:18docs: record catalogue and photo regression checksMarFedorovna
- 2026-09-23 17:18feat: visible database catalogue with photos and filtersMarFedorovna
- 2026-09-23 17:06fix: catalogue answers, product photos and read-only catalogue APIMarFedorovna
- 2026-09-23 16:57Update README.mdMarFedorovna
- 2026-09-23 16:57docs: record complete PDF catalog importMarFedorovna
- 2026-09-23 16:56feat: import all 40 PDF catalog productsMarFedorovna
- 2026-09-23 16:44feat: responsive public assistant chatMarFedorovna
- 2026-09-23 16:43docs: record demo verification and setupMarFedorovna
- 2026-09-23 16:42fix: guard cart consent and export verified assistantMarFedorovna
- 2026-09-23 16:12docs: link public ekt assistant demo siteMarFedorovna
- 2026-09-23 16:10Checkpoint standalone public demo deployment and API evidencekoncevojdanila10-source
- 2026-09-23 16:10Document public standalone assistant demo deploymentkoncevojdanila10-source
- 2026-09-23 16:08Add standalone public demo page for ekt assistantkoncevojdanila10-source
- 2026-09-23 15:55docs: record 15:55 acceptance test resultskoncevojdanila10-source
- 2026-09-23 15:54docs: update setup, verified tests, and site limitationskoncevojdanila10-source
- 2026-09-23 15:54docs: document safe ekt.kz integration handoffkoncevojdanila10-source
- 2026-09-23 15:54feat(site): prepare official n8n chat embed fragmentkoncevojdanila10-source
- 2026-09-23 15:53fix(n8n): include catalog currency in product toolskoncevojdanila10-source
- 2026-09-23 15:52fix(db): do not seed fake certificate URLskoncevojdanila10-source
- 2026-09-23 15:52build: seed verified terms in fresh local databasekoncevojdanila10-source
- 2026-09-23 15:51feat(db): add verified purchase terms and remove demo certificate linkskoncevojdanila10-source
- 2026-09-23 15:51feat(n8n): sync verified purchase termskoncevojdanila10-source
- 2026-09-23 15:51fix(n8n): repair analog and purchase terms toolskoncevojdanila10-source
- 2026-09-23 15:37docs: explain prototype cart setup and testsmrqey-cmyk
- 2026-09-23 15:36feat(n8n): add consent-gated cart workflowsmrqey-cmyk
- 2026-09-23 15:35feat(db): add consent-gated prototype cartmrqey-cmyk
- 2026-09-23 15:23docs: clarify catalog sample and analog fallbackkoncevojdanila10-source
- 2026-09-23 15:22fix(n8n): search real analogs by name when embeddings absentkoncevojdanila10-source
- 2026-09-23 15:22docs: document verified real catalog importkoncevojdanila10-source
- 2026-09-23 15:22chore(n8n): remove superseded catalog preview exportkoncevojdanila10-source
- 2026-09-23 15:12feat(n8n): export verified ekt catalog importerkoncevojdanila10-source
- 2026-09-23 15:02docs: describe hosted Supabase setup and catalog previewkoncevojdanila10-source
- 2026-09-23 15:01feat(n8n): add credential-safe ekt catalog API previewkoncevojdanila10-source
- 2026-09-23 14:57chore(n8n): export published ekt assistant statekoncevojdanila10-source
- 2026-09-23 14:57fix(n8n): connect Supabase Postgres and verify assistant chatkoncevojdanila10-source
- 2026-09-23 14:31chore(n8n): export analog explanation updatekoncevojdanila10-source
- 2026-09-23 14:30chore(n8n): export updated ekt assistant tool guidancekoncevojdanila10-source
- 2026-09-23 14:29docs: add local setup and ekt assistant test guidekoncevojdanila10-source
- 2026-09-23 14:29docs(config): add local stack environment templatekoncevojdanila10-source
- 2026-09-23 14:29feat(docker): add local n8n and pgvector stackkoncevojdanila10-source
- 2026-09-23 14:29fix(db): enable trigram extension before search indexeskoncevojdanila10-source
- 2026-09-23 14:28feat(db): add ekt assistant schema and demo cataloguekoncevojdanila10-source
- 2026-09-23 14:21checkpoint 15:00: add ekt_assistant n8n workflowkoncevojdanila10-source
- 2026-09-23 14:15checkpoint 14:00: track 10 ekt.kz — TZ, plan, scaffoldMarFedorovna
- 2026-09-22 18:32chore: remove pre-hackathon setupMarFedorovna
- 2026-09-19 21:50fix: place n8n workflow in workflows directoryMarFedorovna
- 2026-09-19 21:50Delete workflows/biograph-healthcheck.json/biograph-healthcheck.jsonMarFedorovna
- 2026-09-19 21:43feat: add n8n health check workflowMarFedorovna
- 2026-09-19 21:42feat: add self-hosted n8n scaffoldMarFedorovna
- 2026-09-19 20:54Create CODEX_ACCESS_TEST.mdMarFedorovna
Структура репозитория (29 файлов)
.env.example .github/workflows/smoke.yml .gitignore AGENTS.md CATALOG_IMPORT_REPORT.md PROGRESS.md README.md TEST_REPORT.md data/.gitkeep db/.gitkeep db/cart.sql db/init.sql db/terms.sql docker-compose.yml docs/SITE_INTEGRATION.md docs/TZ.md n8n/workflows/.gitkeep n8n/workflows/ekt_assistant.json n8n/workflows/ekt_attachment_extract.json n8n/workflows/ekt_cart_schema.json n8n/workflows/ekt_cart_view.json n8n/workflows/ekt_catalog_import.json n8n/workflows/ekt_catalog_view.json site/demo/README.md site/demo/index.html site/demo/tests.cjs site/ekt-chat-embed.html tests/attachment-smoke.py tests/attachment-validation.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.