Умный подбор подрядчиков
Go-сервис подбора до трёх event-подрядчиков из каталога на 66 профилей, с режимом сборки комплекта на общий бюджет и текстовым или голосовым поиском…
О проекте
Команда: Kak to tak
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Рабочий MVP
Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор
Суть
Go-сервис подбора до трёх event-подрядчиков из каталога на 66 профилей, с режимом сборки комплекта на общий бюджет и текстовым или голосовым поиском через OpenAI.
Как устроено
Детерминированный движок на Go применяет обязательные фильтры и календарь, различает отсутствующую категорию и неподходящих кандидатов, пожелания ищет по описанию через небольшой словарь близких формулировок и ранжирует по цене, затем по ID. Режим «Собрать мероприятие» выбирает комбинацию по одному подрядчику на категорию с суммой в пределах бюджета. Альтернативы ищутся по дате в пределах ±3 дня и по бюджету при превышении не более 100 000 ₸. OpenAI только разбирает свободный текст или транскрипт речи (Speech-to-Text) в структурированный запрос для того же движка.
Ключевые решения
- детерминированные фильтры и ранжирование
- перебор комбинации комплекта под бюджет
- словарь синонимов для пожеланий
- OpenAI structured parsing
- OpenAI Speech-to-Text
Особенности
Режим сборки целого мероприятия на общий бюджет с расчётом минимальной суммы полного набора и голосовой ввод запроса, при этом выбор подрядчиков остаётся детерминированным и OpenAI не получает каталог.
Стек
Go · JavaScript · HTML/CSS · PowerShell
Модели
OpenAI (structured parsing) · OpenAI Speech-to-Text
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-7511029a-kak-to-tak.
README
README.mdУмный подбор подрядчиков — Kak to tak
Прототип для HackAlem AI, трек #79-lite. Помогаем выбрать до трёх event-подрядчиков из предоставленного каталога и объяснить выбор.
Первый этап
Реализованы загрузка 66 профилей, обязательные фильтры, проверка календаря,
различение отсутствующей категории и неподходящих кандидатов. Пользователь может
описать пожелание своими словами: совпадение ищется по описанию профиля с
небольшим прозрачным словарём близких формулировок, а найденный фрагмент
показывается в объяснении. Списки внутри CSV
разделены |; пустая длительность означает неприменимость ограничения.
Исходные признаки synthetic, city_imputed, price_imputed сохранены.
Порядок пока базовый: начальная цена, затем ID. Это не окончательное смысловое ранжирование. Модель не выдумывает сведения: объяснения опираются на поля каталога. Веб-интерфейс также предлагает отдельно доступного, но немного более дорогого подрядчика или ближайшую свободную дату для занятого профиля. Бронирование в задачу не входит.
Режимы продукта
Интерфейс поддерживает два режима без перезагрузки страницы:
- «Найти подрядчика» — до трёх строго подходящих профилей для одной категории;
- «Собрать мероприятие» — по одному реальному подрядчику на выбранную категорию.
В режиме комплекта общий бюджет не делится поровну: выбирается детерминированная комбинация, у которой сумма price_from_kzt не превышает бюджет. Для каждой выбранной категории задаётся собственная длительность; проверка max_hours выполняется отдельно для каждого подрядчика, а null означает отсутствие ограничения. Если полный комплект не помещается, показывается максимально полный доступный набор и рассчитывается минимальная сумма полного набора. Альтернативы по дате проверяются только в диапазоне ±3 дня. Бюджетная альтернатива допускается только при превышении не более 100 000 ₸.
AI-поиск (опционально)
OpenAI используется только для распознавания естественного языка и Speech-to-Text. После structured parsing запрос передаётся в существующий deterministic matching engine; OpenAI не выбирает подрядчиков и не получает весь каталог. Без ключа ручные формы продолжают работать, а AI-панель показывает понятный fallback.
Создайте .env.local по примеру .env.example и задайте server-side переменные OPENAI_API_KEY, OPENAI_MODEL и OPENAI_TRANSCRIBE_MODEL. Текстовый flow: текст → OpenAI structured parsing → validation → deterministic matching. Голосовой flow: audio → OpenAI Speech-to-Text → transcript → тот же parser → тот же matching engine. API-ключ не передаётся во frontend и не должен попадать в Git.
Запуск
Нужен Go 1.22 или новее. Выполнять из корня репозитория:
В Windows PowerShell запустите powershell -NoProfile -ExecutionPolicy Bypass -File ./start.ps1: скрипт загрузит настройки из .env.local.
Для AI-поиска серверу нужен доступ к https://api.openai.com.
При запуске напрямую через Go переменные OPENAI_* должны быть заданы в окружении:
go run .
Откройте http://127.0.0.1:8080 в браузере. Заполните форму или нажмите один из
трёх примеров. Результат — карточки подрядчиков и причины исключения остальных.
Сервер работает, пока открыт терминал; остановка — Ctrl+C.
Другой порт: go run . -serve -addr 127.0.0.1:8081.
Консольный режим для проверки данных:
go run . -city Алматы -category Ведущий -date 2026-10-15 -format корпоратив -budget 1000000
go test ./...
Ответ — JSON. Необязательные параметры: -language русский, -hours 6.
Календарь известен только для 23.09.2026–31.12.2026; другие даты отклоняются.
Цена «от» не гарантирует итоговую стоимость. Причины исключения могут пересекаться.
Для ручной проверки режима комплекта откройте веб-интерфейс, переключите «Собрать мероприятие», выберите несколько категорий и общий бюджет. Подбор использует тот же CSV-каталог и календарь, что и основной режим.
Данные
data/contractors.csv — исходный CSV организаторов без изменений, 66 профилей.
Имена анонимизированы, 13 профилей помечены синтетическими организаторами.
Добавленных командой профилей пока нет. Часть цен и городов заполнена при
подготовке датасета; соответствующие признаки сохраняются в ответе.
Следующие этапы
- Смысловое соответствие пожеланиям, объяснения с опорой на факты профиля.
- Веб-форма и карточки, понятные причины отсутствия результатов.
- Демосценарии: плотная и редкая категории, пустая выдача, смена даты.
- Проверка полного сценария, документация запуска и подготовка защиты.
Авторы коммитов
История коммитов
- 2026-09-23 17:56fix: run contractor search after AI parsingtkiyakov
- 2026-09-23 17:40fix: restore OpenAI search and load local configuration on startuptkiyakov
- 2026-09-23 17:23feat: add OpenAI text and voice searchsyuldashev
- 2026-09-23 16:18feat: support category-specific event durationssyuldashev
- 2026-09-23 15:46feat: add event bundle matching and smart alternativessyuldashev
- 2026-09-23 14:25Add preference-based contractor recommendationstkiyakov
- 2026-09-23 13:40Add contractor catalog and deterministic matching baselinetkiyakov
- 2026-09-23 11:40Add empty main.gotkiyakov
Структура репозитория (15 файлов)
.env.example .gitignore README.md ai.go data/contractors.csv go.mod main.go main_test.go start.ps1 web.go web/app.js web/extras.css web/index.html web/style.css web_test.go
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.