Smart Contractor
Сервис детерминированного подбора до трёх event-подрядчиков с объяснениями и модулем «План Б», предлагающим смягчить параметры при пустой выдаче.
О проекте
Команда: zxc
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Рабочий MVP
Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор
Суть
Сервис детерминированного подбора до трёх event-подрядчиков с объяснениями и модулем «План Б», предлагающим смягчить параметры при пустой выдаче.
Как устроено
FastAPI читает contractors.csv (66 профилей), фильтрует по городу/категории, занятости, формату, бюджету, языку и длительности; текстовые пожелания сопоставляются с описаниями через TF-IDF и cosine similarity, затем детерминированное ранжирование. Статусы matched / category_absent / no_match с диагностикой отсева; «План Б» перебирает альтернативы по дате, бюджету, языку, длительности, городу и возвращает варианты, которые UI применяет одной кнопкой.
Ключевые решения
- TF-IDF
- cosine similarity
- hard filters
- детерминированное ранжирование
- Plan B relaxation
Особенности
Автоматический «План Б» со смягчением ограничений и применением прямо из интерфейса; локальное TF-IDF-сопоставление пожеланий без внешних LLM.
Стек
Python · FastAPI · Pydantic · pandas · scikit-learn · HTML · CSS · JavaScript · pytest
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-e94993ef-zxc.
README
README.mdSmart Contractor
Объяснимый сервис подбора event-подрядчиков по параметрам конкретного мероприятия.
1. Название проекта
Smart Contractor — сервис детерминированного подбора подрядчиков с объяснением результата и автоматическим «Планом Б» для слишком строгих запросов.
2. Краткое описание
Пользователю сложно вручную сравнивать подрядчиков одновременно по городу, дате, формату мероприятия, бюджету, языку и длительности работы. Smart Contractor принимает параметры заказа, исключает неподходящие профили и возвращает до трёх подходящих вариантов.
Сервис не ограничивается обычной фильтрацией: для каждого результата формируется конкретное объяснение, почему подрядчик подходит под запрос. Если подходящих кандидатов нет или их меньше трёх, модуль «План Б» анализирует ограничения и предлагает изменение параметров, которое может расширить выбор.
3. Что реализовано
- фильтрация подрядчиков по городу и категории;
- проверка занятости на выбранную дату;
- фильтрация по формату мероприятия;
- проверка бюджета;
- опциональная фильтрация по языку;
- опциональная фильтрация по длительности;
- дополнительные текстовые пожелания пользователя;
- TF-IDF и cosine similarity для сопоставления пожеланий с описаниями подрядчиков;
- детерминированное ранжирование кандидатов;
- выдача до трёх карточек подрядчиков;
- конкретные объяснения причин рекомендации;
- три различимых состояния результата:
matched— подходящие подрядчики найдены;category_absent— выбранной категории нет в указанном городе;no_match— категория существует, но никто не проходит заданные условия;
- диагностика причин, по которым кандидаты были отсеяны;
- «План Б» с альтернативами по дате, бюджету, языку, длительности, городу или комбинации даты и бюджета;
- применение предложенного варианта «Плана Б» прямо из интерфейса;
- отображение признаков
synthetic,city_imputed,price_imputed; - адаптивный web-интерфейс;
- REST API на FastAPI;
- API-тесты через pytest и FastAPI
TestClient.
4. Как работает решение
- Пользователь задаёт город, дату, формат мероприятия, категорию подрядчика и бюджет.
- При необходимости добавляет длительность, язык и текстовые пожелания.
- Backend выбирает подрядчиков нужной категории в указанном городе.
- Последовательно проверяются обязательные ограничения: дата, формат, бюджет, язык и длительность.
- Для текстовых пожеланий рассчитывается TF-IDF-сходство с описанием подрядчика.
- Подходящие кандидаты ранжируются детерминированно.
- Пользователь получает до трёх карточек с объяснением причин выбора.
- Если подходящих вариантов недостаточно, модуль «План Б» проверяет альтернативные параметры и предлагает изменения, которые дают дополнительные результаты.
Одинаковый запрос возвращает одинаковый порядок рекомендаций.
5. Технологии
Backend
- Python
- FastAPI
- Pydantic
- Uvicorn
- pandas
AI / NLP
- scikit-learn
TfidfVectorizercosine_similarity
Внешние LLM и внешние AI API не используются. Смысловое сопоставление выполняется локально на основе TF-IDF.
Frontend
- HTML5
- CSS3
- Vanilla JavaScript
- Fetch API
Тестирование
- pytest
- FastAPI
TestClient - httpx
6. Архитектура проекта
Текущая структура ветки main:
hack-e94993ef-zxc/
├── backend/
│ ├── __init__.py
│ ├── data_loader.py
│ ├── main.py
│ ├── models.py
│ └── recommender.py
│
├── data/
│ └── contractors.csv
│
├── frontend/
│ ├── app.js
│ ├── index.html
│ └── styles.css
│
├── tests/
│ └── test_api.py
│
├── .gitignore
├── README.md
├── pytest.ini
└── run.bat
Назначение основных компонентов
backend/main.py— создание FastAPI-приложения, API endpoints и раздача frontend;backend/data_loader.py— чтение и нормализация CSV-датасета;backend/models.py— Pydantic-модели запросов, результатов и «Плана Б»;backend/recommender.py— фильтрация, TF-IDF, ранжирование, объяснения и логика «Плана Б»;frontend/index.html— структура пользовательского интерфейса;frontend/styles.css— визуальное оформление и адаптивность;frontend/app.js— работа формы, обращения к API, вывод карточек и применение «Плана Б»;data/contractors.csv— локальный каталог подрядчиков;tests/test_api.py— проверка health/meta endpoints, обычной рекомендации и возврата «Плана Б».
Взаимодействие компонентов
Пользователь
↓
frontend/index.html + styles.css + app.js
↓ POST /api/recommend
backend/main.py
↓
RecommendationRequest
↓
ContractorRecommender
├── город / категория
├── занятость
├── формат
├── бюджет
├── язык
├── длительность
├── TF-IDF
├── детерминированное ранжирование
└── Plan B analyzer
↓
Top-3 + explanations + plan_b
↓
JSON → frontend
Frontend обслуживается самим FastAPI-приложением, поэтому отдельный frontend-сервер для локального запуска не требуется.
7. Установка и запуск
Требования
- Python 3.11+
- pip
1. Клонировать репозиторий
git clone https://github.com/BAITC-Hacks/hack-e94993ef-zxc.git
cd hack-e94993ef-zxc
2. Создать виртуальное окружение
Windows:
python -m venv .venv
.venv\Scripts\activate
Linux/macOS:
python3 -m venv .venv
source .venv/bin/activate
3. Установить зависимости
В текущей структуре main отдельный requirements.txt отсутствует, поэтому зависимости можно установить напрямую:
pip install fastapi uvicorn pandas scikit-learn pytest httpx
4. Запустить приложение
Windows:
run.bat
Или напрямую:
python -m uvicorn backend.main:app --reload --host 127.0.0.1 --port 8000
5. Открыть приложение
http://127.0.0.1:8000
Swagger UI:
http://127.0.0.1:8000/docs
6. Запустить тесты
Из корня проекта:
python -m pytest -q
pytest.ini добавляет корень проекта в Python path и указывает папку tests как каталог тестов.
8. Как проверить решение
Сценарий 1 — плотная категория
Город: Алматы
Дата: 15.10.2026
Тип мероприятия: корпоратив
Категория: Ведущий
Бюджет: 1 500 000 ₸
Длительность: 6 ч
Язык: русский
Пожелания: интеллигентный юмор импровизация современная подача
Ожидаемый результат: статус matched и от одной до трёх карточек. Повторный запуск с теми же параметрами должен возвращать тот же порядок.
Сценарий 2 — редкая категория
Город: Алматы
Дата: 15.10.2026
Тип мероприятия: свадьба
Категория: Флорист
Бюджет: 500 000 ₸
Язык: русский
Пожелания: авторское оформление цветы
Ожидаемый результат: подходящие профили отображаются вместе с конкретным объяснением.
Сценарий 3 — строгий запрос и «План Б»
Город: Астана
Дата: 31.12.2026
Тип мероприятия: свадьба
Категория: Ведущий
Бюджет: 300 000 ₸
Длительность: 10 ч
Язык: казахский
Ожидаемый результат: no_match. Интерфейс показывает причины отсутствия результата и возвращённые backend-варианты «Плана Б». Кнопка «Применить» переносит предложенные параметры в форму и выполняет новый поиск.
9. Данные и интеграции
Источник данных:
data/contractors.csv
Backend использует следующие поля профиля подрядчика:
id;anon_name;categories;city;city_imputed;synthetic;price_from_kzt;price_imputed;event_formats;languages;max_hours;busy_dates;description.
Датасет содержит 66 профилей подрядчиков. Все вычисления выполняются локально; внешняя база данных, LLM API и сторонние сервисы для работы рекомендательной логики не используются.
10. Ограничения
- каталог хранится в локальном CSV;
- календарь доступности ограничен датами, содержащимися в датасете;
- бронирование, заявки и уведомления подрядчикам не реализованы;
- нет авторизации и пользовательских аккаунтов;
- нет постоянной базы данных;
- нет административного интерфейса;
- TF-IDF основан на лексическом сходстве и не является полноценной embedding-моделью;
- стоимость берётся из
price_from_kzt, индивидуальная смета не рассчитывается; - доступность не синхронизируется с внешними календарями;
- «План Б» строит предложения только на основе текущего каталога и реализованных правил;
- в текущей структуре репозитория автоматические тесты находятся в одном файле
tests/test_api.py.
11. Deployed-версия
Публичная deployed-версия в текущем репозитории не указана.
Для локального запуска используется:
http://127.0.0.1:8000
API
После запуска приложения доступны:
GET /api/health
GET /api/meta
POST /api/recommend
Полное интерактивное описание API доступно в Swagger:
http://127.0.0.1:8000/docs
Финальная проверка
python -m pytest -q
python -m uvicorn backend.main:app --host 127.0.0.1 --port 8000
После запуска:
- интерфейс:
http://127.0.0.1:8000; - Swagger:
http://127.0.0.1:8000/docs.
Авторы коммитов
История коммитов
- 2026-09-23 16:42измененияferylov
- 2026-09-23 16:33dataferylov
- 2026-09-23 16:22:updtimaplay
- 2026-09-23 16:06:fix data loadtimaplay
- 2026-09-23 15:56измененияferylov
- 2026-09-23 15:52документация проектаferylov
- 2026-09-23 15:51cкрипт запуска приложенияferylov
- 2026-09-23 15:51Добавить тесты APIferylov
Все коммиты (30)
- 2026-09-23 15:51Добавить логику интерфейса и План Бferylov
- 2026-09-23 15:51Добавить адаптивные стили интерфейсаferylov
- 2026-09-23 15:51Добавить современный интерфейс поиска подрядчиковferylov
- 2026-09-23 15:51Добавить API и подключение интерфейсаferylov
- 2026-09-23 15:50Настроить запуск тестовferylov
- 2026-09-23 15:50исключения для Gitferylov
- 2026-09-23 14:58:data updtimaplay
- 2026-09-23 14:57фронт через fastapiferylov
- 2026-09-23 14:51отправка параметров мероприятия из frontend в APIferylov
- 2026-09-23 14:49stylesferylov
- 2026-09-23 14:48fixferylov
- 2026-09-23 14:41add contractor search formferylov
- 2026-09-23 14:22:updtimaplay
- 2026-09-23 14:08Implement contractor filtering and rankingtimaplay
- 2026-09-23 14:03demo uiferylov
- 2026-09-23 13:57удалены тестовые файлыferylov
- 2026-09-23 13:28я поменял test 2ferylov
- 2026-09-23 13:27:test.txttimaplay
- 2026-09-23 13:10:test2.txttimaplay
- 2026-09-23 13:03:test2.txttimaplay
- 2026-09-23 12:58:test2timaplay
- 2026-09-23 12:55testferylov
Структура репозитория (14 файлов)
.gitignore README.md backend/__init__.py backend/data_loader.py backend/main.py backend/models.py backend/recommender.py data/contractors.csv frontend/app.js frontend/index.html frontend/styles.css pytest.ini run.bat tests/test_api.py
Ветки (3)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.