Skip to content

Repository files navigation

SW-catalog

SW-catalog — B2B SaaS-платформа для оптимизации закупочной деятельности в малом и среднем бизнесе. Платформа агрегирует внутренние закупочные данные компании, структурирует проекты, позиции и поставщиков и поднимает ИИ-агента, который ищет альтернативных поставщиков из открытых источников и сравнивает их с уже существующими условиями. Базовый референс — fashion-бренды (закупка тканей, фурнитуры, упаковки, услуг отшива), но модель данных универсальная: можно использовать для электроники, мебели, любых составных изделий.

Что умеет система

  • Каталог проектов и изделий. У каждого проекта есть свой состав (компоненты, позиции для закупки), бюджет, статус, тираж, валюта.
  • Загрузка данных сверху: вставьте текст, BOM, прайс-лист или таблицу — ИИ-агент-парсер разнесёт это в проекты, позиции и поставщиков.
  • Карточка проекта с тремя колонками: компоненты слева, детали выбранной позиции по центру, поставщики по этой позиции справа. У каждого поставщика — переключатель мониторинга.
  • ИИ-агент discovery запускается «именно на пункт внутри проекта»: ищет альтернативных поставщиков через веб-поиск и читалку страниц, проверяет каждого и сохраняет карточку поставщика с ценой, сроком, страной, контактом, ссылкой.
  • ИИ-агент мониторинга по расписанию обходит «галочками отмеченных» поставщиков и пишет в журнал изменения цены/сроков. Изменения видны в таблице на странице проекта и на главной.
  • Поиск изображения товара через XMLStock Yandex Live: ИИ берёт название и спецификацию позиции, скачивает первую подходящую картинку и привязывает её к позиции.
  • Сводный отчёт об экономии: каждой позиции выбирается лучший по цене вариант, базовая стоимость считается по «текущим» поставщикам, экономия = базовая − лучшая. Отображается в дашборде и карточке проекта.
  • Глобальные настройки: профиль бренда, регионы, категории, валюта, периодичность мониторинга, список постоянных площадок-источников (B2B-маркетплейсы, дистрибьюторы и т. п.).

Архитектура

  • agent_server/ FastAPI-бэкенд, scheduler, агентный runtime, парсер загрузок, тулы (reader, search, image search), слой хранения.
  • frontend/ React + TypeScript SPA. Sidebar-навигация: Главная / Проекты / Поставщики / Отчёты / Настройки.
  • data/ Локальное файловое хранилище (монтируется в backend-контейнер).
  • references/ Референсы интерфейса.
  • docker-compose-api.yml Основной compose-файл для локального запуска.

Хранилище

Бэкенд хранит данные в ./data:

  • data/config.json — глобальные настройки и список постоянных площадок-источников.
  • data/projects.json — проекты с составом (позиции для закупки).
  • data/suppliers.json — карточки поставщиков, привязанные к (project_id, item_id).
  • data/uploads.json + data/uploads/<id>.txt — сырые загрузки и история парсинга.
  • data/changes.json — журнал изменений цен/условий по отслеживаемым поставщикам.
  • data/runs/<run_id>.json + data/events/<run_id>.json — журнал запусков ИИ-агента.
  • data/notes/item-<item_id>.txt — переиспользуемые заметки агента по конкретной позиции.
  • data/images/<file> — скачанные изображения позиций, отдаются по /static/images/....

ИИ-агенты

Item discovery / monitoring agent

Запускается «на позицию внутри проекта». В контекст получает профиль бренда, проект, позицию, её спецификацию, целевую цену, уже известных поставщиков и список постоянных площадок.

Tools:

  • search_supplier_web(query, ...) — поиск через XMLSearch / XMLStock.
  • read_supplier_page(url) — reader-цепочка: Jina → direct httpx + Trafilatura → Playwright + Trafilatura.
  • add_supplier(name, price_text, currency, lead_time, country, url, ...) — сохраняет или обновляет карточку поставщика для текущей позиции. Дедупликация по нормализованному URL, иначе по имени.
  • write_item_notes(content) — переписывает короткое reusable-резюме по позиции (видно в карточке позиции и используется на следующем запуске).

В режиме monitor агент проходит по уже отслеживаемым поставщикам и обновляет цены/сроки. Если цена изменилась, пишется запись в data/changes.json.

Upload parser

Когда пользователь загружает текст/таблицу через дашборд, бэкенд кладёт файл в data/uploads/, запускает LLM (chat completions с response_format=json_object) с системным промптом из prompts.UPLOAD_PARSER_PROMPT и получает JSON {projects: [...], summary: ...}. Структура напрямую превращается в проекты, позиции и упомянутые «текущие» поставщики (флаг is_existing=true).

Если OPENAI_API_KEY не задан, бэкенд использует простой fallback: каждая непустая строка становится отдельной позицией одного проекта.

Image search agent

/api/projects/{id}/items/{id}/image запускает фоновый таск, который:

  1. Идёт в XMLStock Yandex Live (порт парсера tools/xml_images.py из C:/Users/JGSnapp/Desktop/Stroki).
  2. Берёт первую URL-картинку из ответа, скачивает её через httpx в data/images/<item_id>.<ext>.
  3. Привязывает локальный URL (/static/images/...) к позиции.

API

  • GET /health
  • GET /api/state — агрегированное состояние для фронта.
  • GET/PUT /api/config
  • Projects: GET /api/projects, POST /api/projects, GET/PUT/DELETE /api/projects/{id}
  • Items: POST/PUT/DELETE /api/projects/{id}/items[...]
    • POST /api/projects/{id}/items/{item_id}/discover — запуск discovery-агента
    • POST /api/projects/{id}/items/{item_id}/image — поиск изображения
    • GET /api/projects/{id}/items/{item_id}/notes — текущие заметки агента
  • Suppliers: GET /api/suppliers, GET /api/items/{id}/suppliers, POST /api/projects/{id}/items/{id}/suppliers, PUT /api/suppliers/{id}, PUT /api/suppliers/{id}/monitor, PUT /api/suppliers/{id}/status, DELETE /api/suppliers/{id}
  • Sites: POST /api/sites, PUT/DELETE /api/sites/{id}
  • Uploads: GET /api/uploads, POST /api/uploads, GET /api/uploads/{id}/raw
  • Runs: GET /api/runs, GET /api/runs/{id}/events
  • Changes: GET /api/changes
  • Image debug: GET /api/images/search?query=...

Переменные окружения

Скопируйте пример:

cp env.example .env

Основные переменные:

  • OPENAI_API_KEY, OPENAI_BASE_URL, AGENT_MODEL — прямой OpenAI-compatible endpoint.
  • PROXY_API_KEY, PROXY_BASE_URL, PROXY_MODEL, PROXY_FALLBACK_MODEL — ProxyAPI endpoint. Для OpenRouter используйте PROXY_BASE_URL=https://api.proxyapi.ru/openrouter/v1 и модель вида qwen/qwen3-235b-a22b-2507; код автоматически переключается на Chat Completions. Если PROXY_FALLBACK_MODEL задана, backend повторит текстовый запрос на ней при ошибке основной модели.
  • JINA_READER_BASE_URL, DIRECT_READER_ENABLED, PLAYWRIGHT_READER_ENABLED — настройки reader-цепочки для парсинга страниц поставщиков.
  • XMLSTOCK_GOOGLE_URL — endpoint поиска по веб-страницам (для discovery-агента).
  • XMLSTOCK_YANDEXLIVE_URL — endpoint поиска по картинкам (для image-агента, порт парсера из Stroki/XMLSearch).
  • DATA_DIR — путь до файлового хранилища внутри backend-контейнера. По умолчанию /data.

Запуск через Docker Compose

docker compose -f docker-compose-api.yml up --build

Сервисы:

Остановка:

docker compose -f docker-compose-api.yml down

Логика фронтенда

Sidebar-навигация: Главная / Проекты / Поставщики / Отчёты / Настройки.

  • Главная: сверху форма загрузки данных (текст, таблица или файл), три карточки KPI (Оценка закупок · Поставщиков · Активных проектов), таблица проектов, под ней свежие изменения по отслеживаемым поставщикам.
  • Проекты: тот же каталог проектов в полноэкранной таблице.
  • Карточка проекта: breadcrumb, заголовок со статусом, 6 mini-KPI (компоненты, поставщики, на мониторинге, оценка закупки, экономия, бюджет). Ниже — three-column grid:
    • слева Компоненты товара: позиции с миниатюрой, нижней меткой цены и ссылкой «фото» для запуска поиска изображения;
    • в центре детали выбранной позиции: спецификация, диапазон цен по найденным поставщикам, кнопки «Найти поставщиков» и «Найти картинку», блок с заметками ИИ-агента;
    • справа Поставщики для позиции: карточки, отсортированные по цене; toggle мониторинга; плашка «текущий / ИИ / мониторинг».
  • Поставщики: глобальный список со всех проектов и фильтром.
  • Отчёты: история запусков ИИ-агента и загрузок.
  • Настройки: глобальные параметры (профиль, регионы, валюта, периодичность) и список постоянных площадок-источников.

Алгоритм экономии

Для каждой позиции, по которой есть хотя бы два поставщика с распознанной ценой:

  • best_price = min(price_i)
  • baseline_price = max(price_i по текущим/preferred-поставщикам или по всем, если таких нет)
  • savings += max(0, (baseline_price - best_price) * quantity)

baseline_estimate и spent_estimate агрегируются по всем проектам и показываются в дашборде вместе с savings_pct = savings / baseline * 100.

Алгоритм намеренно консервативный: если у позиции пока один поставщик, экономия по ней нулевая. Когда ИИ-агент находит более дешёвый вариант, экономия начинает расти.

Замечания по разработке

  • Scheduler работает внутри backend-процесса (apscheduler) и каждые 5 минут проверяет позиции, у которых пора снова обновить отслеживаемых поставщиков.
  • Один и тот же item не запускается параллельно — повторный запуск возвращает 409.
  • Состояние «running» хранится в памяти, без распределённой блокировки.
  • Все длинные тексты (notes, описания, summary) пишутся на русском — это зафиксировано в prompts.ITEM_DISCOVERY_PROMPT.

Проверка

python3 -m compileall agent_server
docker compose -f docker-compose-api.yml up --build

Текущие ограничения

  • Файловое хранилище, без БД. Подходит для одного бренда / небольшой команды.
  • Image search и веб-поиск требуют действующих XMLStock endpoints.
  • Парсер загрузок берёт первые 12 000 символов входа; для больших BOM-таблиц это можно расширить.
  • Нет пользовательской авторизации — это single-tenant дашборд под одну команду.

About

B2B SaaS-платформа для оптимизации закупочной деятельности в малом и среднем бизнесе

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages