AAYMA
RU
Войти

Smart Contractor Recommendation

FastAPI и Streamlit: подбирает до трёх подрядчиков из каталога по городу, дате, формату, категории, бюджету, языку и длительности, объясняет каждый…

Рабочий MVP
Команда «BaiterekAI» 3💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: BaiterekAI
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Рабочий MVP

Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор

Суть

FastAPI и Streamlit: подбирает до трёх подрядчиков из каталога по городу, дате, формату, категории, бюджету, языку и длительности, объясняет каждый выбор и возвращает сводку причин отсева.

Как устроено

Цепочка обязательных фильтров: город, категория, дата и busy_dates, бюджет, формат, язык, max_hours. Оставшиеся профили ранжируются по score, берутся топ-3. Объяснение собирается по шаблону из полей профиля. Возвращаются статусы found, category_not_found или no_match и rejection_summary со счётчиками отсева по каждой причине. LLM не используется, порядок детерминирован.

Ключевые решения

  • каскад фильтров
  • детерминированный скоринг
  • шаблонные объяснения
  • rejection summary

Особенности

rejection_summary показывает, сколько профилей отсеяно по каждой причине, и это делает пустую выдачу объяснимой.

Стек

Python · FastAPI · Pydantic · Uvicorn · Streamlit · pytest


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-c119ee0f-baiterekai.

README

README.md

Smart Contractor Recommendation

Smart Contractor Recommendation — веб-приложение для подбора подрядчиков для мероприятий.

Пользователь указывает город, дату, тип мероприятия, категорию подрядчика, бюджет, а также при необходимости язык и длительность. Система анализирует каталог предоставленных подрядчиков, отбирает подходящие варианты и показывает до 3 результатов с объяснением, почему каждый подрядчик соответствует запросу.

Система использует только реальные профили из предоставленного каталога и не создаёт вымышленных подрядчиков.

Как запустить проект

1. Установить зависимости

В корневой папке проекта выполните:

python -m pip install -r requirements.txt

2. Запустить Backend

Откройте первый терминал в корневой папке проекта.

Для Windows PowerShell:

$env:CONTRACTORS_CSV_PATH = "$PWD\data\contractors.csv"
python -m uvicorn app.main:app --reload

После запуска FastAPI будет доступен по адресу:

http://127.0.0.1:8000

Документация API:

http://127.0.0.1:8000/docs

3. Запустить Frontend

Откройте второй терминал в корневой папке проекта:

python -m streamlit run frontend/app.py

После запуска откроется веб-интерфейс приложения.

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

Для проверки рекомендуется выполнить следующие сценарии через веб-интерфейс.

Сценарий 1 — обычный подбор

Введите:

  • Город: Алматы
  • Дата: 2026-11-14
  • Тип мероприятия: свадьба
  • Категория: Фотограф
  • Бюджет: 500000
  • Язык: русский
  • Длительность: 6 часов

Ожидаемый результат: система находит до 3 подходящих фотографов. Для каждого результата отображаются имя, категория, город, стартовая цена, score и объяснение.

Сценарий 2 — регистр букв не влияет на поиск

Текстовые параметры запроса можно вводить в любом регистре.

Например, следующие значения должны обрабатываться одинаково:

  • Фотограф
  • фотограф
  • ФОТОГРАФ

То же относится к типу мероприятия, например:

  • Свадьба
  • свадьба
  • СВАДЬБА

А также к городу, языку и другим текстовым параметрам.

При этом поиск не исправляет опечатки: меняется только регистр букв.

Сценарий 3 — редкая категория

Введите:

  • Город: Алматы
  • Дата: 2026-11-14
  • Тип мероприятия: свадьба
  • Категория: Флорист
  • Бюджет: 500000
  • Язык: русский
  • Длительность: 6 часов

Ожидаемый результат: найден 1 подходящий подрядчик.

Система не создаёт дополнительные вымышленные результаты, если в каталоге подходит только один профиль.

Сценарий 4 — отсутствие подходящих вариантов

Используйте:

  • Город: Алматы
  • Дата: 2026-11-14
  • Тип мероприятия: свадьба
  • Категория: Фотограф
  • Бюджет: 1
  • Язык: русский
  • Длительность: 6 часов

Ожидаемый результат:

  • подходящих подрядчиков нет;
  • статус — no_match;
  • количество результатов — 0;
  • система показывает причины, по которым профили были исключены.

Сценарий 5 — проверка занятости

Для проверки календаря подрядчиков выполните один и тот же запрос для двух дат.

Сначала:

  • Город: Алматы
  • Дата: 2026-11-12
  • Тип мероприятия: свадьба
  • Категория: Фотограф
  • Бюджет: 500000
  • Язык: русский
  • Длительность: 6 часов

Затем измените только дату на:

  • 2026-11-14

В каталоге подрядчик HK-68220 занят 12 ноября и свободен 14 ноября.

Поэтому 12 ноября он не должен отображаться среди результатов, а 14 ноября может появиться.

Этот сценарий демонстрирует, что система учитывает busy_dates и действительно меняет рекомендации в зависимости от даты мероприятия.

Что делает система

После отправки формы запрос проходит следующие этапы:

Параметры пользователя → фильтрация подрядчиков → проверка города → проверка категории → проверка даты и занятости → проверка бюджета → проверка формата мероприятия → проверка языка → проверка длительности → ранжирование → выбор до 3 результатов → формирование объяснений → отображение результата.

Система сначала применяет обязательные фильтры, после чего ранжирует оставшиеся подходящие профили.

Учитываются:

  • город;
  • категория;
  • дата;
  • занятость подрядчика;
  • бюджет;
  • формат мероприятия;
  • язык;
  • длительность.

Текстовые параметры сравниваются без учёта регистра букв.

Если у подрядчика отсутствует ограничение max_hours, длительность не используется как ограничение.

Одинаковый запрос возвращает одинаковый порядок результатов.

Объяснение результатов

Для каждого найденного подрядчика система формирует конкретное объяснение на основе данных его профиля.

Например:

Город — Алматы; категория — «Фотограф»; формат — «свадьба»; по календарю свободен на 2026-11-14; цена от 190 000 ₸ при бюджете 500 000 ₸; указан запрошенный язык — русский; запрошено 6 ч, доступная длительность — до 12 ч.

В объяснениях также может использоваться информация из описания профиля.

Цена является стартовой и может требовать уточнения у подрядчика.

Обработка отсутствия результатов

Система использует три статуса:

  • found — подходящие подрядчики найдены.
  • category_not_found — указанной категории нет в каталоге.
  • no_match — категория существует, но после применения параметров запроса подходящих подрядчиков не осталось.

Если подходящих вариантов меньше трёх, система показывает только найденные варианты.

Если подходящих вариантов нет, система не создаёт вымышленные профили, а возвращает пустой результат и причины отсева.

Rejection Summary

Для анализа причин отсева система возвращает rejection_summary.

Например:

{
  "city": 16,
  "category": 42,
  "busy": 5,
  "budget": 3,
  "event_format": 0,
  "language": 0,
  "duration": 0
}

Это показывает, сколько профилей было исключено по каждой причине.

Архитектура

Приложение состоит из трёх основных частей:

Streamlit Frontend
        ↓
FastAPI API
        ↓
Recommendation Engine
        ↓
Contractor Catalog

Frontend отвечает за взаимодействие с пользователем.

FastAPI принимает и валидирует запросы и передаёт их в Recommendation Engine.

Recommendation Engine выполняет фильтрацию, ранжирование и формирование объяснений.

Каталог подрядчиков хранится в data/contractors.csv.

API

Основной endpoint:

POST /recommend

Пример запроса:

{
  "city": "Алматы",
  "date": "2026-11-14",
  "event_type": "свадьба",
  "category": "Фотограф",
  "budget": 500000,
  "language": "русский",
  "duration": 6
}

Пример ответа:

{
  "status": "found",
  "count": 3,
  "results": [
    {
      "id": "HK-68220",
      "name": "Рок Ли",
      "category": "Фотограф",
      "city": "Алматы",
      "price": 190000,
      "score": 0.62,
      "explanation": "..."
    }
  ],
  "rejection_summary": {}
}

Дополнительный endpoint:

GET /health

Ответ:

{
  "status": "ok"
}

Данные

Каталог находится в:

data/contractors.csv

Для каждого профиля используются данные о:

  • идентификаторе;
  • имени;
  • категориях;
  • городе;
  • стартовой цене;
  • форматах мероприятий;
  • языках;
  • максимальной длительности;
  • занятых датах;
  • описании;
  • дополнительных признаках данных.

Система использует только предоставленный каталог.

Технологии

  • Python
  • FastAPI
  • Pydantic
  • Uvicorn
  • Streamlit
  • CSV

Структура проекта

hack-c119ee0f-baiterekai/
├── app/
│   ├── main.py
│   ├── api/
│   │   └── routes.py
│   ├── schemas/
│   │   └── recommendation.py
│   ├── recommender/
│   │   ├── engine.py
│   │   ├── filters.py
│   │   ├── scoring.py
│   │   └── explanations.py
│   └── data/
│       ├── loader.py
│       └── models.py
├── frontend/
│   ├── app.py
│   ├── api_client.py
│   └── components.py
├── data/
│   └── contractors.csv
├── tests/
├── requirements.txt
└── README.md

Ограничения

  • Приложение не выполняет бронирование.
  • Приложение не отправляет уведомления.
  • Система не создаёт новых подрядчиков.
  • Цена в каталоге является стартовой и может измениться после уточнения условий.
  • Максимальное количество рекомендаций — 3.
  • Результаты зависят от полноты и качества предоставленного каталога.
  • Нечувствительность к регистру не означает исправление опечаток.

Быстрый сценарий демонстрации для жюри

  1. Запустить Backend.
  2. Запустить Streamlit Frontend.
  3. Выполнить обычный поиск фотографа в Алматы на 14.11.2026 с бюджетом 500000 ₸.
  4. Показать 3 результата и объяснения.
  5. Повторить тот же запрос, написав фотограф с маленькой буквы, и показать, что результат остаётся тем же.
  6. Выбрать категорию «Флорист» и показать, что система корректно возвращает только существующий подходящий профиль.
  7. Установить бюджет 1 ₸ и показать no_match с причинами отсева.
  8. Сравнить одинаковый запрос для 12.11.2026 и 14.11.2026 и показать влияние busy_dates.

Таким образом можно проверить основные требования решения: подбор по параметрам, ограничение бюджета, категории, языка и длительности, нечувствительность к регистру, проверку занятости, работу с редкими категориями, отсутствие вымышленных результатов, обработку пустого результата и объяснение рекомендаций.

Команда

Проект разработан в рамках хакатона HackAlem.

Основные направления разработки:

  • Backend / FastAPI
  • Recommendation Engine / Data
  • Streamlit Frontend

Ссылки

Страница хакатона: https://edu.astanahub.com/hackathons/df4743f5-c492-415c-b45a-1f13adb78e06

Telegram хакатона: https://t.me/+rLHvxHMpZdtiYThi

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

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

whyquas 7Practicum 3Akhmetov Nurali 3kasym0055 3

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

  • 2026-09-23 17:42fix: improve numeric input fieldswhyquas
  • 2026-09-23 17:10Delete .env.examplewhyquas
  • 2026-09-23 17:00docs: add project READMEwhyquas
  • 2026-09-23 16:57Fix case-insensitive contractor matchingPracticum
  • 2026-09-23 16:42Merge pull request #7 from BAITC-Hacks/fix/frontend-api-contractAkhmetov Nurali
  • 2026-09-23 16:38fix: align frontend with recommendation APIPracticum
  • 2026-09-23 16:14Merge pull request #6 from BAITC-Hacks/feature/backend-apikasym0055
  • 2026-09-23 16:08feat: integrate recommendation enginewhyquas
Все коммиты (16)
  • 2026-09-23 15:57Merge pull request #5 from BAITC-Hacks/feature/frontendkasym0055
  • 2026-09-23 15:51Merge pull request #4 from BAITC-Hacks/feature/backend-apikasym0055
  • 2026-09-23 15:49Merge pull request #3 from BAITC-Hacks/feature/recommendation-enginewhyquas
  • 2026-09-23 15:46feat: add deterministic contractor recommendation enginePracticum
  • 2026-09-23 15:42feat: add Streamlit recommendation frontendnurabp
  • 2026-09-23 15:02feat: add recommendation APIwhyquas
  • 2026-09-23 14:52Merge pull request #1 from BAITC-Hacks/feature/project-architectureAkhmetov Nurali
  • 2026-09-23 14:50chore: add project architecturewhyquas
Структура репозитория (24 файлов)
.gitignore
README.md
app/__init__.py
app/api/__init__.py
app/api/routes.py
app/data/__init__.py
app/data/loader.py
app/data/models.py
app/main.py
app/recommender/__init__.py
app/recommender/engine.py
app/recommender/explanations.py
app/recommender/filters.py
app/recommender/scoring.py
app/schemas/__init__.py
app/schemas/recommendation.py
data/.gitkeep
data/contractors.csv
frontend/api_client.py
frontend/app.py
frontend/components.py
requirements.txt
tests/test_api.py
tests/test_recommender.py
Ветки (6)

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

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

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