AAYMA
RU
Войти

Умный подбор подрядчиков

Streamlit-приложение подбора до 3 подрядчиков на мероприятие с объяснениями и причинами отсева, дополненное двусторонним маркетплейсом с…

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

О проекте

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

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

Суть

Streamlit-приложение подбора до 3 подрядчиков на мероприятие с объяснениями и причинами отсева, дополненное двусторонним маркетплейсом с регистрацией подрядчиков.

Как устроено

core/generator.py фильтрует каталог по категории, городу, занятости busy_dates, бюджету, формату, языку и длительности, затем начисляет оценку по цене относительно бюджета, языку и лимиту часов и сортирует детерминированно (оценка, цена, ID). Объяснения собираются из фактов профиля без LLM. safe_pipeline_call() валидирует ввод и ответ, при ошибке или таймауте 15 с отдаёт резервный демо-ответ с fallback=True.

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

  • жёсткие фильтры
  • детерминированный скоринг
  • шаблонные объяснения
  • fallback-обёртка пайплайна

Особенности

Разделение Core/helpers с явным контрактом и защитным fallback при сбоях; 36 тестов, включая регрессию демо-сценария со сменой даты.

Стек

Python · Streamlit · unittest


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

README

README.md

Умный подбор подрядчиков

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

Интерфейс работает на Streamlit. Подбор и объяснения выполняются локально, без LLM и ключей внешних API.

Быстрый запуск

Выполняйте команды из корня проекта — папки с app.py и requirements.txt. Нужен Python с модулями venv и pip.

1. Создайте виртуальное окружение:

python -m venv .venv

2. Активируйте его командой для вашей системы:

Linux / macOS:

source .venv/bin/activate

Windows PowerShell:

.venv\Scripts\Activate.ps1

Windows cmd:

.venv\Scripts\activate.bat

3. Установите зависимости и запустите приложение:

python -m pip install -r requirements.txt
python -m streamlit run app.py

Откройте адрес из терминала — обычно http://localhost:8501. Для остановки нажмите Ctrl+C в терминале. Единственная прямая внешняя зависимость проекта — streamlit; остальные пакеты установятся вместе с ней.

Если появилась ошибка No module named 'streamlit', активируйте окружение и повторите установку через python -m pip install -r requirements.txt.

Как пользоваться

  1. Укажите город, дату, формат мероприятия, категорию услуг и бюджет в тенге.
  2. При необходимости задайте язык и длительность в блоке «Дополнительные параметры».
  3. Нажмите «Подобрать подрядчиков».

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

Демо за несколько минут

Используйте эти параметры для подбора:

ПараметрЗначение
ГородАлматы
Дата2026-11-14
Форматсвадьба
КатегорияФотограф
Бюджет400 000 ₸
Длительность8 часов
Языкрусский

На исходном каталоге результат содержит HK-68220, HK-76268, HK-91112 в этом порядке.

Измените только дату на 2026-11-15 и повторите подбор. Останутся HK-68220 и HK-91112: у HK-76268 новая дата указана в busy_dates. Оба запроса возвращают matched и fallback=False.

Как устроен подбор

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

Оставшиеся кандидаты получают оценку по начальной цене относительно бюджета, языку и лимиту часов. Кандидаты упорядочиваются по убыванию оценки; при равенстве — по возрастанию цены, затем ID. При одинаковых данных и запросе результат одинаковый. Объяснения составляются из фактов профиля и условий запроса.

СтатусЧто означает
matchedНайдено от 1 до 3 подходящих подрядчиков.
no_category_in_cityВ выбранном городе нет подрядчиков этой категории.
no_eligible_candidatesКатегория в городе есть, но никто не прошёл остальные условия.

Защита от сбоев

safe_pipeline_call() проверяет входные данные и ответ Core. При ошибке, некорректном ответе или ожидании дольше 15 секунд возвращает резервный ответ из helpers/mock_data.json с признаком fallback=True.

Резервная подборка — заранее подготовленный демо-сценарий. Её параметры могут отличаться от текущего запроса; интерфейс сообщает о переходе в демо-режим. Если резервные данные тоже недоступны или невалидны, helpers возвращает пустой ответ с fallback=True.

Данные и хранение

ФайлНазначение
helpers/contractors.jsonИсходный каталог: 66 профилей, из них 13 синтетических. Не изменяется при работе приложения.
helpers/mock_data.jsonРезервный ответ для демо при сбое подбора.
given_data/Исходный анонимизированный CSV и HTML-превью.

Данные проходят нормализацию и валидацию. Занятые даты busy_dates сохраняются в формате YYYY-MM-DD и участвуют в фильтрации. Флаги synthetic, city_imputed и price_imputed сохраняют сведения о синтетических профилях и восстановленных городах и ценах. UI отмечает синтетические профили и позволяет посмотреть, какие поля были восстановлены.

load_contractors() возвращает 66 исходных профилей. Загрузка каталога и выполнение подбора не изменяют исходный JSON-файл.

Архитектура и контракт

app.py — Streamlit: форма запроса, карточки и сообщения
  │
  ├── helpers/utils.py — загрузка, нормализация и валидация
  │     └── contractors.json — исходные 66 профилей
  │
  └── helpers/utils.py — safe_pipeline_call()
        ├── core/generator.py — фильтры → оценка → top-3 → объяснения
        └── mock_data.json   — резервный ответ при сбое

Пример запроса к run_pipeline(request, contractors) через safe_pipeline_call:

{
  "city": "Алматы",
  "date": "2026-11-14",
  "event_format": "свадьба",
  "category": "Фотограф",
  "budget_kzt": 400000,
  "duration_hours": 8,
  "language": "русский"
}

Первые пять полей обязательны. Бюджет — положительное целое число в тенге. duration_hours и language можно не передавать или указать как null.

Основные поля ответа через safe_pipeline_call:

ПолеСодержимое
statusОдин из трёх статусов выше.
queryПараметры запроса, которому соответствует ответ.
resultsДо трёх карточек с оценкой и объяснением; пустой список при отсутствии рекомендаций.
metaЧисло кандидатов и результатов, диагностика причин отказа.
fallbackFalse при штатном ответе Core, True при резервном ответе.

Тесты

Из корня проекта выполните:

python -m unittest discover -v

На момент обновления README: 36 тестов, все проходят. Они проверяют сохранность данных, фильтры, ранжирование, объяснения, статусы, fallback, смену даты и интеграцию Core с helpers.

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

Основные файлы и папки:

.
├── app.py                       # Streamlit-интерфейс
├── core/
│   ├── generator.py             # Алгоритм рекомендаций
│   ├── INTEGRATION.md
│   ├── test_catalog.py
│   └── test_generator.py
├── helpers/
│   ├── utils.py                 # Загрузка, валидация и fallback
│   ├── prepare_data.py          # Подготовка исходных данных
│   ├── contractors.json
│   ├── mock_data.json
│   ├── README.md
│   ├── test_core_integration.py
│   ├── test_dataset.py
│   └── test_utils.py
├── docs/                        # Дополнительные материалы проекта
├── given_data/
├── requirements.txt
└── README.md

Подробности реализации: интеграция Core и работа с данными.

Ограничения текущей версии

  • Приложение рекомендует подрядчиков. Бронирования, оплаты и аккаунтов нет.
  • Доступность определяется только сохранёнными busy_dates.
  • Выбор дат в UI ограничен диапазоном 23.09.2026–31.12.2026.
  • Бюджет сравнивается с ценой «от», которая не является итоговой сметой заказа.
  • max_hours: null означает, что часовой лимит не указан; такой профиль не исключается по длительности.
Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
40
Авторы
3
Файлы
25
Ветки
5

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

Minato7879 17scirtor 14Light 9

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

  • 2026-09-23 17:53docs: clarify setup and usage for stable mainscirtor
  • 2026-09-23 17:50docs: clarify setup and marketplace workflowsscirtor
  • 2026-09-23 17:39feat(ui): polish marketplace UX and visual hierarchyscirtor
  • 2026-09-23 17:22docs(ui): document marketplace user flowsLight
  • 2026-09-23 17:22docs(core): document marketplace recommendation featuresMinato7879
  • 2026-09-23 17:22docs(data): document marketplace storage featuresscirtor
  • 2026-09-23 17:17docs(ui): document marketplace user flowsLight
  • 2026-09-23 17:15docs(core): document marketplace recommendation featuresMinato7879
Все коммиты (40)
  • 2026-09-23 17:13docs(data): document marketplace storage featuresscirtor
  • 2026-09-23 16:57fix(ui): repair contractor role navigationMinato7879
  • 2026-09-23 16:48Merge remote-tracking branch 'origin/feature/marketplace' into feature/marketplaceMinato7879
  • 2026-09-23 16:33Merge remote-tracking branch 'origin/feature/marketplace' into feature/marketplaceMinato7879
  • 2026-09-23 16:28Merge remote-tracking branch 'origin/main' into feature/marketplaceMinato7879
  • 2026-09-23 16:27Merge remote-tracking branch 'origin/main' into feature/marketplaceLight
  • 2026-09-23 16:22docs: document data reliability guaranteesscirtor
  • 2026-09-23 16:19feat(ui): robust role synchronization and contractor registration handlingLight
  • 2026-09-23 16:19test(data): add feature storage regression coveragescirtor
  • 2026-09-23 16:12test(core): verify persisted feature catalog integrationMinato7879
  • 2026-09-23 16:08feat(ui): implement two-sided marketplace flow with role selector and contractor registrationLight
  • 2026-09-23 16:05feat: add separate feature contractor storagescirtor
  • 2026-09-23 16:04test(core): verify user-submitted contractor integrationMinato7879
  • 2026-09-23 15:56test(core): add final integration regressionMinato7879
  • 2026-09-23 15:45chore(ui): document stable demo scenarioLight
  • 2026-09-23 15:23docs: add project READMEscirtor
  • 2026-09-23 15:05test(core): add final demo regression coverageMinato7879
  • 2026-09-23 15:01fix(ui): use st.html and dedent for raw HTML cards renderingLight
  • 2026-09-23 14:35chore: add runtime dependenciesscirtor
  • 2026-09-23 14:17Merge remote-tracking branch 'origin/main' into lightLight
  • 2026-09-23 14:12Merge contractor recommendation core into mainMinato7879
  • 2026-09-23 14:10test: verify core integration with shared helpersMinato7879
  • 2026-09-23 14:09Merge remote-tracking branch 'origin/main' into feature/authMinato7879
  • 2026-09-23 14:07test: verify core against shared contractor catalogMinato7879
  • 2026-09-23 14:05Merge remote-tracking branch 'origin/main' into feature/authMinato7879
  • 2026-09-23 14:03feat: prepare normalized contractor datasetscirtor
  • 2026-09-23 14:02Merge branch 'main' into scirtorscirtor
  • 2026-09-23 14:01data: share anonymized contractor source datasetscirtor
  • 2026-09-23 14:01feat: build contractor recommendation demo UILight
  • 2026-09-23 13:58feat: add validation and fallback utilitiesscirtor
  • 2026-09-23 13:54feat: implement contractor recommendation pipelineMinato7879
  • 2026-09-23 13:52Create Test1Minato7879
Структура репозитория (25 файлов)
README.md
Test1
app.py
core/INTEGRATION.md
core/__init__.py
core/generator.py
core/test_catalog.py
core/test_generator.py
docs/CORE_FEATURES.md
docs/DATA_FEATURES.md
docs/UI_FEATURES.md
given_data/.gitignore
given_data/README.md
given_data/hackathon dataset anonymized .csv
given_data/hackathon dataset preview.html
helpers/README.md
helpers/__init__.py
helpers/contractors.json
helpers/mock_data.json
helpers/prepare_data.py
helpers/test_core_integration.py
helpers/test_dataset.py
helpers/test_utils.py
helpers/utils.py
requirements.txt
Ветки (5)

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

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

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