AAYMA
RU
Войти

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

FastAPI-бэкенд подбирает до 3 event-подрядчиков из анонимизированного каталога (66 профилей) по городу, дате, формату, категории и бюджету и…

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

О проекте

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

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

Суть

FastAPI-бэкенд подбирает до 3 event-подрядчиков из анонимизированного каталога (66 профилей) по городу, дате, формату, категории и бюджету и генерирует объяснения через LLM; веб-интерфейса нет, проверка через /docs.

Как устроено

Запрос валидируется, детерминированный фильтр исключает профили по городу, категории, занятой дате, бюджету, формату, языку и длительности, затем стабильное ранжирование по фиксированным правилам. LLM (OpenAI SDK или совместимый NVIDIA endpoint) пишет 1–2 предложения объяснения по фактам профиля; при сбое — локальный fallback. Различаются три исхода: подобраны, категории нет в городе, кандидаты не прошли условия.

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

  • deterministic filtering
  • stable ranking
  • LLM explanation
  • rejection reason analysis

Стек

Python · FastAPI · Uvicorn · pytest

Модели

OpenAI · NVIDIA API


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

README

README.md

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

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

[!IMPORTANT] В репозитории уже есть backend с фильтрацией, FastAPI и подключённым модулем объяснений. Пользовательского веб-интерфейса пока нет; проверить API можно на странице /docs.

Что реализует решение

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

Бронирование, отправка заявок и уведомления подрядчиков не входят в текущий сценарий.

Как работает решение

  1. Клиент отправляет параметры мероприятия в HTTP API.
  2. Сервис валидирует запрос и загружает каталог подрядчиков.
  3. Детерминированный фильтр исключает неподходящие профили: другой город или категория, занятая дата, превышенный бюджет, неподдерживаемый формат, язык или длительность.
  4. Оставшиеся кандидаты ранжируются по фиксированным правилам. LLM не решает, кто допускается в выдачу, поэтому не может вернуть занятого или слишком дорогого подрядчика.
  5. Для лучших кандидатов LLM формирует по 1–2 предложения на основе фактов профиля и параметров запроса. Общие формулировки вроде «отличный выбор» не используются.
  6. API возвращает до трёх карточек либо понятную причину, почему результатов нет или их меньше трёх.

Одинаковый запрос должен давать один и тот же порядок карточек. Изменение даты может менять выдачу из-за календаря занятости.

Архитектура

flowchart LR
    A[Клиент или интерфейс] --> B[Валидация запроса]
    D[(Каталог JSONL/CSV)] --> C[Детерминированный фильтр]
    B --> C
    C --> E[Стабильное ранжирование]
    E --> F[LLM-объяснения]
    F --> G[До 3 карточек]
    C --> H[Анализ причин отказа]
    H --> I[Понятный пустой результат]

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

hackathon-contractors/
├── api.py
├── main.py
├── demo.py
├── data/
│   ├── hackathon-dataset-anonymized.csv
│   └── hackathon-dataset-anonymized.jsonl
├── src/
│   ├── __init__.py
│   ├── data_loader.py
│   ├── filter_engine.py
│   ├── llm_contract.py
│   ├── llm_explainer.py
│   ├── models.py
│   └── recommendation_service.py
├── docs/
├── examples/
├── tests/
├── requirements.txt
├── .env.example
└── README.md
КомпонентОтветственность
api.pyHTTP API для проверки доступности, параметров и рекомендаций
src/filter_engine.pyфильтрация, причины отказа и стабильное ранжирование
src/recommendation_service.pyсоединяет фильтрацию и объяснения
src/llm_explainer.pyобъяснения по переданным фактам и локальный fallback
data/анонимизированный каталог подрядчиков и их календарь занятости

Технологии

Используемые технологии:

  • Python 3.10+;
  • FastAPI и Uvicorn — HTTP API;
  • OpenAI SDK — OpenAI API или совместимый NVIDIA endpoint;
  • LLM API — генерация коротких объяснений;
  • python-dotenv — локальная конфигурация API-ключей;
  • JSONL/CSV — формат данных подрядчиков.

Зависимости и версии указаны в requirements.txt. Настройки провайдера и модели — в .env.example.

Данные и интеграции

В исходном анонимизированном датасете содержится 66 профилей подрядчиков:

  • 17 категорий;
  • 50 профилей из Алматы, 15 из Астаны и 1 профиль из категории «Зарубежье»;
  • 13 полностью синтетических профилей с признаком synthetic: true;
  • 8 восстановленных значений города и 18 восстановленных цен;
  • цены от 100 000 до 6 000 000 ₸;
  • календарь занятости с 23 сентября по 31 декабря 2026 года.

Основные поля: id, anon_name, categories, city, price_from_kzt, event_formats, languages, max_hours, busy_dates, description, synthetic, city_imputed, price_imputed.

Персональные данные отсутствуют: имена вымышлены, дополнительная анонимизация не требуется. API-ключ LLM хранится только в локальном .env и не должен попадать в Git.

Установка и запуск

Команды для Windows PowerShell:

# Windows PowerShell
py -3.11 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txt
Copy-Item .env.example .env

Для macOS/Linux:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
cp .env.example .env

В .env укажите свой OPENAI_API_KEY, затем запустите API:

python -m uvicorn api:app --reload --host 127.0.0.1 --port 8000

Откройте http://127.0.0.1:8000/docs и отправьте запрос через POST /recommendations. Подробная инструкция находится в BACKEND_README.md.

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

Ниже приведены сценарии, которые можно отправить через страницу API /docs на исходном датасете.

1. Плотная категория

ПараметрЗначение
ГородАлматы
Дата18.10.2026
Тип мероприятиякорпоратив
КатегорияВедущий
Бюджет1 300 000 ₸
Язык и длительностьне указывать

Ожидается три карточки из нескольких подходящих профилей. Повторный запуск должен сохранить их порядок и объяснения должны ссылаться на разные факты из профилей.

2. Редкая категория

ПараметрЗначение
ГородАлматы
Дата15.10.2026
Тип мероприятиясвадьба
КатегорияФлорист
Бюджет500 000 ₸
Языкрусский

В исходном датасете условия проходят два профиля. API должен вернуть обе карточки и объяснить, почему результатов меньше трёх.

3. Кандидаты есть, но условия не проходят

ПараметрЗначение
ГородАлматы
Дата26.12.2026
Тип мероприятиясвадьба
КатегорияВедущий
Бюджет100 000 ₸
Языкрусский
Длительность6 часов

В Алматы есть ведущие, однако запрос не должен вернуть карточки. Пользователь должен увидеть конкретные причины: бюджет, занятость, формат или сочетание ограничений.

Дополнительно можно проверить отдельный исход «в городе нет такой категории» запросом на декоратора в Астане.

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

Ограничения

  • каталог содержит только 66 профилей и не является полноценной базой рынка;
  • данные ограничены Алматы, Астаной и одним зарубежным профилем;
  • календарь покрывает только период 23.09.2026–31.12.2026;
  • цена price_from_kzt является стартовой и не заменяет итоговый расчёт подрядчика;
  • часть городов и цен была восстановлена при подготовке датасета;
  • качество объяснений зависит от доступности и поведения внешнего LLM API;
  • решение не выполняет бронирование, оплату и коммуникацию с подрядчиком;
  • полноценный пользовательский веб-интерфейс пока не добавлен;
  • внешняя LLM используется только для объяснений; при отсутствии ключа или сбое остаются локальные сообщения.

Deployed-версия

Публичная deployed-версия пока не опубликована.

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

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

dimash 8lioshka-alt 2m1tello 1

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

  • 2026-09-23 17:58docs: preserve project guide with accurate API instructionsdimash
  • 2026-09-23 17:57docs: update project README for integrated APIdimash
  • 2026-09-23 17:56Merge project README contributiondimash
  • 2026-09-23 17:56Merge contractor filtering backend and LLM integrationdimash
  • 2026-09-23 17:46Connect recommendation API to team LLM module and verify integrationlioshka-alt
  • 2026-09-23 17:29Add deterministic contractor filtering backend and datasetlioshka-alt
  • 2026-09-23 17:18Merge remote-tracking branch 'team/main' # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting wdimash
  • 2026-09-23 17:14docs: add project READMEm1tello
Все коммиты (11)
  • 2026-09-23 17:11Add OpenAI LLM explainerdimash
  • 2026-09-23 16:36feat: add LLM explainer moduledimash
  • 2026-09-23 15:58первый коммитdimash
Структура репозитория (38 файлов)
.env.example
.gitignore
BACKEND_README.md
README.md
api.py
data/hackathon-dataset-anonymized.csv
data/hackathon-dataset-anonymized.jsonl
demo.py
docs/DEFENSE.md
docs/TEAM_INTEGRATION.md
docs/VALIDATION.md
docs/demo-results.json
docs/integration-results.json
examples/01_dense_request.json
examples/01_dense_response.json
examples/02_rare_request.json
examples/03_no_matches_request.json
examples/04_no_category_request.json
examples/05_other_date_request.json
examples/06_languages_duration_request.json
main.py
pytest.ini
requirements-dev.txt
requirements-lock.txt
requirements.txt
src/__init__.py
src/data_loader.py
src/filter_engine.py
src/llm_contract.py
src/llm_explainer.py
src/models.py
src/recommendation_service.py
tests/conftest.py
tests/test_api.py
tests/test_backend.py
tests/test_pipeline.py
tests/test_team_integration.py
uwh.py
Ветки (3)

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

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

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