Skip to content

Repository files navigation

Интеллектуальный сервис подбора закупок (backend)

Репозиторий содержит только backend по контракту RLT 2026 (contract (3).md): FastAPI + PostgreSQL/pgvector + rubert-tiny2 (sentence-transformers).

Пайплайн: pgvector — отбор топ-K кандидатов (по умолчанию 20) → rubert-tiny2 — точное косинусное реранжирование → топ-3 и поле reason. Работа offline, без внешних LLM API; при сборке Docker-образа модель кэшируется под /models.


Быстрый старт (Docker)

Требования

  • Docker 20.10+ и Docker Compose v2
  • ~4 GB RAM для контейнера api

1. Файл закупок (обязательно)

В ./data/ должен лежать CSV закупок с именем по умолчанию:

Закупки для интенсива_сжатые.csv в каталоге ./data/

(при необходимости задайте другой путь в TENDERS_FILE в .env).

Демо-хардкод тендеров отключён: без файла сервис не стартует.

Строки закупок всегда различаются по pn_lot (основной ключ), если эта колонка есть в CSV; пустые pn_lot отбрасываются. Без колонки pn_lot используется только lot_number (в лог пишется предупреждение).

2. Окружение

copy .env.example .env

3. Запуск

docker compose up --build

Первый старт: загрузка модели + полная векторизация всех лотов из CSV (батчи по TENDER_EMBED_BATCH, по умолчанию 256). На большом файле это может занять десятки минут и больше; при нехватке памяти уменьшите батч (например 128) в .env / docker-compose.


Соответствие контракту (backend)

Требование Реализация
ИИ только локально, rubert-tiny2 + sentence-transformers app/services/matcher.py, загрузка один раз в lifespan
PostgreSQL + pgvector, vector(312), ivfflat app/database.py, ensure_ivfflat_index() после загрузки тендеров
Два этапа: pgvector → rubert → топ-3 get_candidates() → matcher.match_item() (пересчёт cosine по кандидатам)
get_candidates(query_embedding, top_k=20) app/database.py
ОКПД2 — пред-фильтр по первым 4 цифрам get_candidates + при малом числе кандидатов — поиск без фильтра
text_for_matching номенклатуры: category + name + char values TenderMatcher.build_item_text в matcher.py
Все 5 эндпоинтов /health, /upload-nomenclature, /match, /results, /export/csv
Экспорт Excel GET /export/csv → openpyxl / pandas.ExcelWriter
asyncio.run_in_executor для матчинга app/routers/matching.py
Структура app/, matcher.py в services/ app/main.py, app/services/matcher.py
docker-compose: app + postgresql docker-compose.yml
.env.example, MODEL_PATH / MODEL_NAME .env.example, Dockerfile / compose

Фронтенд в этом репозитории не ведётся (по отдельному решению команды).


API

Метод Путь Описание
GET /health status, tenders_loaded, model_ready, embedding_dim, tenders_file, version
POST /upload-nomenclature CSV → nomenclature_items + эмбеддинги
POST /match Тело: { "item_ids": [] } — пустой список = все товары; JSON по контракту
GET /results?min_score= История match_results
GET /export/csv Скачать .xlsx
curl http://localhost:8000/health

Локальная разработка (API)

python -m venv .venv
.venv\Scripts\activate
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install -r requirements.txt
docker run -d --name pg -e POSTGRES_PASSWORD=procurement -e POSTGRES_USER=procurement -e POSTGRES_DB=procurement -p 5432:5432 pgvector/pgvector:pg16
set DATABASE_URL=postgresql://procurement:procurement@localhost:5432/procurement
set TENDERS_FILE=C:\Users\ASUS\Desktop\hackatone\data\Закупки для интенсива_сжатые.csv
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Структура

app/
  main.py
  database.py          # модели, init_db, get_candidates, ivfflat
  routers/
    nomenclature.py
    matching.py
  services/
    matcher.py         # rubert + реранжирование + reason
    tenders_loader.py  # CSV/XLSX тендеров, группировка по lot_number, эмбеддинги
requirements.txt
.env.example
docker-compose.yml
Dockerfile

Переменные окружения: см. .env.example (DATABASE_URL, TENDERS_FILE, TENDER_EMBED_BATCH, MODEL_NAME, MODEL_PATH, PGVECTOR_TOP_K, API_PORT).

Сборка: failed to resolve python:3.11-slim / EOF с registry-1.docker.io

Это сетевой сбой или лимит Docker Hub. По умолчанию API собирается с AWS Public ECR (public.ecr.aws/docker/library/python:3.11-slim). Если нужен именно Hub:

set PYTHON_IMAGE=python:3.11-slim
docker compose build --no-cache api

Либо зеркало Google: PYTHON_IMAGE=mirror.gcr.io/library/python:3.11-slim. Повторите docker compose up --build.

About

Semantic matching of company product nomenclature to government procurement lots: two-stage search with pgvector ANN + rubert-tiny2 reranking, fully local — no external LLM APIs

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages