Умный подбор event-подрядчиков
Лёгкий локальный MVP на стандартной библиотеке Python: по городу, дате, формату, категории и бюджету возвращает до 3 свободных подрядчиков с…
О проекте
Команда: USAnlog
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Рабочий MVP
Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор
Суть
Лёгкий локальный MVP на стандартной библиотеке Python: по городу, дате, формату, категории и бюджету возвращает до 3 свободных подрядчиков с объяснениями либо статус no_catalog/no_match с причинами.
Как устроено
Сервер на http.server читает DataProviders.csv, отбирает записи по городу и категории, исключает синтетические и отсеивает кандидатов по busy_dates, цене выше бюджета, формату, языку и длительности. При наличии ключа text-embedding-3-small (с кэшем в .cache/embeddings.json) только переупорядочивает прошедших фильтр, gpt-4o-mini формулирует объяснения по фактам карточек; без ключа порядок идёт по цене и ID, объяснения собираются по правилам. smoke_check.py офлайн проверяет три исхода и стабильность порядка.
Ключевые решения
- жёсткие фильтры по календарю, бюджету и формату
- ранжирование эмбеддингами
- rule-based fallback объяснений
- кэш эмбеддингов
Особенности
Нулевые зависимости (только stdlib Python и HTML без сборщика), при этом явно различаются три исхода (recommendations / no_catalog / no_match), а флаги price_imputed/city_imputed показываются как ориентировочные.
Стек
Python · http.server · HTML/CSS/JavaScript
Модели
gpt-4o-mini · text-embedding-3-small
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-10f83c80-usanlog.
README
README.mdУмный подбор event-подрядчиков
Локальный MVP агрегатора подрядчиков для мероприятий в Казахстане. Пользователь задаёт город, дату, формат события, категорию и бюджет; длительность и язык — по желанию. Приложение показывает до трёх свободных вариантов и объясняет совпадения фактами из каталога.
Состав проекта
.
├── server.py # HTTP-сервер, фильтры, эмбеддинги и генерация объяснений
├── index.html # форма и карточки результатов; без frontend-библиотек
├── DataProviders.csv # исходный каталог из 66 записей
├── smoke_check.py # автономная проверка основных сценариев
├── .env.example # названия переменных для API
└── .gitignore
Технологии
- Python 3.9+ и стандартная библиотека:
http.server,csv,urllib; зависимости устанавливать не нужно. - HTML, CSS и JavaScript без сборщика и внешних frontend-пакетов.
- OpenAI-compatible API, если задать
OPENAI_API_KEY:[скрыто]используется для семантического порядка среди уже прошедших фильтры кандидатов,gpt-4o-mini— для формулировки объяснений по фактам каталога. - Без ключа приложение работает локально: применяет те же ограничения и выводит короткие объяснения по полям каталога. Запросы к внешнему API не выполняются.
Запуск локально
Из корневой папки проекта:
python3 --version
python3 server.py
Откройте http://localhost:8000. Остановить сервер можно сочетанием Ctrl+C в терминале.
Если порт 8000 занят, задайте другой перед запуском:
PORT=8001 python3 server.py
Подключение LLM и эмбеддингов
Настройка необязательна. Переменные задаются в том же терминале, из которого запускается сервер; .env.example служит списком имён и автоматически не загружается.
export OPENAI_API_KEY="ваш-ключ"
export EMBEDDING_MODEL="text-embedding-3-small"
export LLM_MODEL="gpt-4o-mini"
python3 server.py
Для совместимого провайдера можно также задать OPENAI_BASE_URL, указав адрес API с окончанием /v1. Ключ не добавляйте в код или CSV. Первый запрос может занять больше времени: описания подрядчиков отправляются в API эмбеддингов и сохраняются в локальном .cache/embeddings.json; повторные запросы используют кэш. Объяснения LLM каждый раз строятся только по карточкам, прошедшим фильтры. Если API недоступен, приложение возвращается к объяснениям по правилам.
Как формируется рекомендация
- Отбираются записи по городу и категории; синтетические записи исключаются.
- Кандидат исключается, если дата есть в
busy_dates, цена выше бюджета, формат не указан вevent_formatsили не совпадает, а также если заданные язык или длительность не подтверждаются данными карточки. - Если кандидатов нет в городе и категории, API возвращает
no_catalog. Если исходные кандидаты есть, но условиям не соответствует ни один —no_matchсо списком причин. Иначе возвращаетсяrecommendationsс максимум тремя карточками. - При настроенном API эмбеддинги влияют только на порядок прошедших фильтры кандидатов. При равных оценках порядок определяется ценой и ID. Без API порядок также стабилен: сначала цена, затем ID.
- Признаки
price_imputedиcity_imputedотображаются как ориентировочные значения. Площадки представлены обычными категориями, с тем же календарным фильтром.
Бронирования, заявки и уведомления подрядчикам не выполняются. В исходной строке Ани Форджер добавлена занятая дата 2026-09-25 для сценария проверки календаря.
Проверка воспроизводимости
В отдельном терминале из корневой папки выполните:
python3 smoke_check.py
Скрипт отключает API для проверки, поэтому не расходует токены и работает офлайн. Он проверяет три состояния (recommendations, no_catalog, no_match), максимум три карточки, стабильность порядка и исключение Ани Форджер на 25 сентября 2026 года.
Также API можно вызвать напрямую. Пример запроса, для которого в каталоге есть фотографы:
curl -s http://localhost:8000/api/recommend \
-H 'Content-Type: application/json' \
-d '{"city":"Алматы","event_date":"2026-09-24","event_type":"свадьба","category":"Фотограф","budget_kzt":500000}'
Форма автоматически загружает доступные города, категории, форматы и языки через GET /api/options. Рекомендации возвращаются через POST /api/recommend.
Данные и ограничения
Каталог содержит 66 анкет, категорий, площадок, цен и занятых дат. Занятость задаётся датами ISO (YYYY-MM-DD), разделёнными символом |. Чтобы обновить наличие, меняйте DataProviders.csv и перезапускайте сервер: CSV считывается при запуске. Данные и календарь учебные, поэтому перед реальным бронированием их нужно сверить с подрядчиком — само приложение бронь не оформляет.
Авторы коммитов
История коммитов
- 2026-09-23 17:30Update index.htmlalens0809-design
- 2026-09-23 17:21Update server.pywonderdeadkp
- 2026-09-23 17:21Fix typos and formatting in README.mdwonderdeadkp
- 2026-09-23 17:13Main datawonderdeadkp
- 2026-09-23 17:10Add files via uploadwonderdeadkp
- 2026-09-23 17:01Add offline smoke checks for recommendation outcomesUlbolsyn
- 2026-09-23 16:58Modified version: Handling the requirmentswonderdeadkp
- 2026-09-23 16:45Fix formatting and punctuation in README.mdUlbolsyn
Все коммиты (14)
- 2026-09-23 16:44Fix punctuation in project descriptionUlbolsyn
- 2026-09-23 15:47Add example environment variables for OpenAI APIUlbolsyn
- 2026-09-23 15:24Revise README for project overview and setupUlbolsyn
- 2026-09-23 14:27Veb versionUlbolsyn
- 2026-09-23 14:21the first version of definitionUlbolsyn
- 2026-09-23 14:05Filtration programm by requestUlbolsyn
Структура репозитория (6 файлов)
.env.example DataProviders.csv README.md index.html server.py smoke_check.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.