AAYMA
RU
Войти

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

Сервис подбора до 3 подрядчиков мероприятия по городу, дате, формату, категории и бюджету с объяснениями, цитатами из профилей, сравнением карточек…

Доведённый продукт
Команда «Aya & Dilya» 4💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Aya & Dilya
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Доведённый продукт

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

Суть

Сервис подбора до 3 подрядчиков мероприятия по городу, дате, формату, категории и бюджету с объяснениями, цитатами из профилей, сравнением карточек и «Планом Б» (ближайшие даты или минимальный бюджет).

Как устроено

CSV подрядчиков нормализуется в catalog.json и audit.json. POST /api/recommend валидирует запрос, применяет обязательные фильтры (включая занятость на дату) и ранжирует кандидатов по числу подтверждённых тем пожеланий, затем по цене и id. «План Б» меняет ровно одно условие: ищет до двух ближайших дат в календаре или минимальный бюджет. OpenAI (gpt-4.1-mini) по желанию переформулирует объяснения, не меняя состав и порядок выдачи; в браузере есть локальный резервный подбор.

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

  • детерминированная фильтрация и ранжирование
  • сопоставление пожеланий с цитатами
  • поиск альтернатив «План Б»
  • AI-редактор объяснений с проверкой
  • кэш

Особенности

Выдача не дополняется искусственно: если подходят 1–2 подрядчика, сервис объясняет причину. Альтернатива меняет ровно одно условие и применяется только по клику пользователя. Состав и порядок результатов не зависят от AI-ключа. В README есть таблица сценариев для жюри с ожидаемыми ID.

Стек

TypeScript · React 19 · Vite · Node.js · tsx · csv-parse

Модели

gpt-4.1-mini


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

README

README.md

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

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

Проект команды Aya & Dilya для кейса Firebird на HackAlem AI. Он помогает заказчику мероприятия выбрать подрядчика из уже имеющегося каталога: учитывает город, дату, формат, категорию и бюджет, а затем объясняет, почему показанные варианты подходят.

Основной сценарий полностью работает без API-ключей. OpenAI можно подключить дополнительно для формулировки объяснений; он не определяет состав и порядок выдачи.

Что реализовано

  • Подбор по всем обязательным условиям: город, дата, формат мероприятия, категория и бюджет в тенге за одного подрядчика на событие. Дополнительно можно указать язык и длительность.
  • От нуля до трёх уникальных карточек с ценой «от», объяснением и статусом занятости по данным каталога. Если найдено только один или два варианта, сервис объясняет причину и не дополняет список искусственно.
  • Пожелания до 500 символов: распознаваемые темы сопоставляются с описаниями профилей и влияют на порядок подходящих кандидатов. Совпадения сопровождаются дословными цитатами.
  • Необязательные AI-объяснения с маркировкой и раскрываемыми фактами-источниками. При отсутствии ключа или проблемах с моделью используются объяснения по правилам.
  • «План Б» при отсутствии совпадений: ближайшие подходящие даты или изменение бюджета. Новые условия применяются только после нажатия пользователя.
  • Сравнение двух или трёх результатов в таблице: цена, объяснения, подтверждения пожеланий, календарь и происхождение данных.
  • Раздельные состояния для отсутствующей категории, отсутствия подходящих кандидатов, ошибок ввода и технических ошибок.
  • Маркировка синтетических профилей, предположенного города и оценочной цены.
  • Адаптивный русскоязычный интерфейс, быстрые примеры, сохранение условий показанного результата и защита от устаревших ответов при повторном подборе.

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

  1. Пользователь заполняет условия мероприятия или выбирает пример. Пример только заполняет форму — подбор запускается кнопкой «Подобрать подрядчиков».
  2. Сервис проверяет запрос и применяет обязательные фильтры к каталогу. Занятые на выбранную дату профили исключаются. Если max_hours = null, ограничение длительности присутствия неприменимо и профиль по нему не исключается.
  3. Среди прошедших фильтры кандидатов первыми идут профили с большим количеством подтверждённых тем пожеланий, затем — с меньшей начальной ценой. Равенство разрешается по id. Без пожеланий порядок определяется ценой и id.
  4. Сервис возвращает до трёх карточек и объяснение общего результата. У каждой карточки есть обоснование по данным профиля. При настроенном ключе сервер может заменить его проверенным AI-текстом, сохраняя кандидатов и их порядок.
  5. Пользователь изучает цитаты, сравнивает карточки или применяет предложенную альтернативу и запускает подбор с новыми условиями.

Как устроен «План Б»

Каждая альтернатива меняет ровно одно условие:

  • Поиск даты охватывает весь поддерживаемый календарь 23.09.2026–31.12.2026. Показываются до двух ближайших подходящих дат; при равном расстоянии сначала будущая.
  • На выбранную дату вычисляется минимальный бюджет, при котором появляется кандидат. Повышение до 20% может показываться вместе с датами. Более существенное повышение предлагается, только если подходящих дат с исходным бюджетом нет, и явно помечается. При нулевом бюджете процент не вычисляется.

Город, категория, формат, язык, длительность и пожелания сохраняются. Если изменение только даты или только бюджета не помогает, готовой альтернативы нет. При отсутствующей категории «План Б» не предлагается.

Технологии

КомпонентРеализация
ЯзыкTypeScript 6.0.3
ИнтерфейсReact / React DOM 19.2.4, CSS
Разработка и сборкаVite 7.3.6
СерверNode.js, встроенный node:http, запуск TypeScript через tsx
Подготовка данныхcsv-parse 7.0.2, локальные CSV и JSON
AI, необязательноOpenAI Responses API через серверный fetch; модель по умолчанию gpt-4.1-mini
ПроверкиВстроенный тестовый раннер Node.js, node:assert, TypeScript и проверка браузерной сборки

Отдельная база данных не требуется. Подключений к CRM, платёжным системам и внешним календарям в текущей версии нет.

Архитектура

CSV → нормализация → catalog.json + audit.json
                            ↓
Форма React → HTTP-адаптер → POST /api/recommend
                            ↓
                 Валидация → фильтры → ранжирование
                            ↓
                 Карточки, объяснения и «План Б»
                            ↓
                 Необязательный редактор OpenAI
                            ↓
                 Результат и сравнение в интерфейсе

При недоступности HTTP API адаптер выполняет тот же подбор локально в браузере и показывает объяснения по правилам. Серверные секреты в браузерный код не передаются.

ПутьНазначение
src/pages/RecommendationPage.tsxФорма, состояния результатов, применение альтернатив
src/pages/recommendationServiceAdapter.tsОбращение к API, резервный локальный подбор, защита от устаревших ответов
src/components/Карточки и таблица сравнения
src/shared/contracts.tsОбщий контракт запросов, ответов и ошибок
src/core/Валидация, фильтры, ранжирование, пожелания, объяснения и «План Б»
src/data/Исходный CSV, нормализованный каталог, аудит и демозапросы
server/api.tsHTTP API и ограничения запросов
server/ai-explanations.tsОбращение к OpenAI, проверка ответа, кеш и резервные объяснения
server/index.tsРаздача собранного интерфейса, API и /healthz
scripts/, tests/Подготовка данных, воспроизводимые сценарии и проверки

Единый интерфейс сервиса: getCatalogOptions() возвращает справочники и диапазон дат, recommend(request) — Promise<RecommendationResponse>. Бизнес-статусы: matched, category_absent, no_match. Ошибки валидации и технические ошибки обрабатываются отдельно; HTTP API возвращает для них 400 и 500 соответственно.

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

1. Получить проект и установить зависимости

Нужны Git, npm и Node.js 20.x от 20.19.0 либо Node.js от 22.12.0 согласно package.json. Для закрытого репозитория потребуется доступ GitHub.

git clone https://github.com/BAITC-Hacks/hack-34cd10d9-aya-dilya.git
cd hack-34cd10d9-aya-dilya

На момент подготовки README совместная версия находится в ветке codex/smart-integration-check:

git switch codex/smart-integration-check
npm ci

Если проект уже скачан, выполните команды из корня этой версии. Для первой установки зависимостей нужен доступ к npm registry.

2. Запустить без внешнего AI

Для основного сценария .env не нужен:

npm run dev

Откройте адрес, который напечатает Vite, обычно http://localhost:5173. Если порт занят, Vite выберет следующий. Dev-сервер обслуживает и интерфейс, и /api/recommend.

3. При необходимости подключить OpenAI

Если .env ещё нет, создайте его из примера:

cp .env.example .env

Заполните локально:

OPENAI_API_KEY=ваш_ключ
OPENAI_MODEL=gpt-4.1-mini

Перезапустите сервер. Ключ должен находиться только в серверном окружении: не используйте префикс VITE_, не добавляйте ключ в Git. .env исключён через .gitignore. С настроенным ключом запрос пользователя и факты выбранных профилей отправляются OpenAI; вызовы API могут тарифицироваться.

4. Запустить собранное приложение

npm run build
npm run start

По умолчанию приложение доступно на http://127.0.0.1:4173. HOST и PORT задаются окружением или .env. Сервер раздаёт dist, обслуживает API и предоставляет GET /healthz.

Для этого запуска нужны исходные серверные файлы и установленные devDependencies, поскольку tsx находится в них. npm run preview обслуживает только статику, без API; для проверки полной версии используйте npm run start.

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

Сценарии для жюри

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

СценарийУсловияОжидаемый результат
Плотная категорияАлматы · 04.10.2026 · корпоратив · Ведущий · 2 000 000 ₸Подходят 5, показаны 3: HK-29829, HK-35215, HK-27222. Можно раскрыть сравнение.
Изменение датыТе же условия, дата 05.10.2026HK-88430, HK-44733, HK-77838. Прежние три профиля исключены по занятости.
Редкая категорияАлматы · 23.09.2026 · свадьба · Флорист · 350 000 ₸Два результата: HK-39372, HK-90001; третья карточка не добавляется.
Категории нетАстана · 04.10.2026 · корпоратив · Лайв-бэнд · 2 000 000 ₸category_absent, карточек нет.
Все занятыАстана · 02.12.2026 · корпоратив · Флорист · 350 000 ₸no_match, основная выдача пустая; можно проверить предложенные альтернативные даты.
Тематические пожеланияАлматы · 01.10.2026 · корпоратив · Ведущий · 2 000 000 ₸ · пожелание «IT-корпоратив»Первым Джинбей (HK-75012) с цитатой о технологических форумах, затем HK-88430, HK-44923. Без пожелания первым идёт HK-88430.
«План Б» по бюджетуАлматы · 10.10.2026 · корпоратив · Ведущий · 480 000 ₸no_match; предложен бюджет 500 000 ₸ (+4,2%). Только после применения появляется Куррапика (HK-88430).

Идентификаторы приведены для сверки API и автоматических проверок; в интерфейсе показаны имена. Состав и порядок результатов не зависят от наличия AI-ключа, формулировка AI-текста может отличаться.

Автоматические проверки

npm run check
npm run build
npm run demo

npm run check проверяет актуальность данных, типы, 51 тест ядра, сервера и UI-адаптера, а также браузерную сборку ядра. Среди проверок — 6 600 запросов по всем 100 датам календаря, неизменность исходных данных, границы фильтров, ранжирование, альтернативы и обработка ошибок. npm run demo воспроизводит восемь базовых сценариев, проверяет ожидаемые id и печатает замеры локального сервиса без UI и внешнего API.

Для проверки собранного приложения оставьте npm run start запущенным и выполните в другом терминале:

npm run smoke:release -- http://127.0.0.1:4173

Проверяются health endpoint, HTML, IT-подбор, «План Б», применение бюджета и ошибка даты. При настроенном ключе эта команда может вызвать OpenAI.

Отдельная проверка реального AI-вызова:

npm run check:ai

Нужен настроенный ключ. Успех — ai.mode: openai и код завершения 0. Код 2 означает отсутствие ключа, код 1 — переход на резервное объяснение. Обычные автоматические тесты используют подмену ответов OpenAI и не требуют ключа.

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

Источник — предоставленный для кейса анонимизированный CSV, сохранённый в src/data/raw/contractors.csv. Продукт использует подготовленный каталог; статистика и контрольная сумма источника находятся в audit.json.

  • 66 профилей: Алматы — 50, Астана — 15, значение «Зарубежье» — 1.
  • 13 профилей помечены как синтетические, у 8 предположен город, у 18 оценочная цена. Эти группы могут пересекаться.
  • У 9 профилей ограничение длительности присутствия неприменимо.
  • Календарь фиксирован: с 23 сентября по 31 декабря 2026 года включительно.

Нормализация сохраняет флаги происхождения данных. Команда npm run data:check проверяет соответствие подготовленных файлов исходнику; npm run data:prepare пересоздаёт их. Демо использует настоящий каталог, а не заранее зашитые ответы.

Единственная внешняя интеграция приложения — необязательный OpenAI Responses API. Сервер отправляет выбранные факты, требует структурированный ответ, проверяет id, ссылки на факты, числа и некоторые неподтверждённые утверждения. Успешные ответы кешируются на 15 минут, таймаут обращения — 6,5 секунды. При ошибке или отклонении текста возвращаются объяснения по правилам.

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

  • Цена «от» не гарантирует итоговую стоимость. Отсутствие занятой даты в CSV не подтверждает реальную доступность подрядчика; внешнего календаря и актуализации занятости нет.
  • Подбор работает только по данному каталогу и фиксированному диапазону дат. Синтетические и оценочные данные не выдаются за проверенные сведения.
  • Пожелания распознаются словарём из десяти тем, а не универсальным семантическим поиском. Неизвестные темы не влияют на порядок; отрицания и сложные формулировки могут распознаваться неполностью. Цитаты взяты из описаний профилей, а не из отзывов клиентов.
  • AI помогает только с формулировками. Проверки ответа снижают риск неподтверждённых утверждений, но не доказывают смысловую достоверность каждого предложения. При отклонении ответа AI-маркировка не показывается.
  • «План Б» не меняет несколько условий одновременно и не гарантирует альтернативу для любого запроса.
  • Нет регистрации, личного кабинета подрядчика, редактирования каталога, бронирования, оплаты и отправки заявок.
  • API ограничен 30 запросами в минуту на адрес соединения. За прокси пользователи могут делить этот лимит; отдельной авторизации и распределённого контроля расходов нет.
  • Автоматические проверки подтверждают поведение на имеющихся данных, но не измеряют пользовательскую пользу и нагрузочную устойчивость публичного сервиса.

Развёрнутая версия

Публичная deployed-версия не опубликована. Репозиторий содержит рабочие варианты локального запуска с сервером. Адреса localhost и 127.0.0.1 доступны только на машине, где запущен проект, и не являются публичной ссылкой.

Настройки для возможного размещения описаны в docs/release.md.

Дополнительные материалы

Некоторые дополнительные документы фиксируют промежуточные этапы разработки. Инструкция запуска и обзор текущих возможностей приведены в этом README.

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

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

Ayanat Amangeldi 10Dilyara Anetbayeva 4ayanat-amangeldi 1

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

  • 2026-09-23 17:14Merge pull request #3 from BAITC-Hacks/codex/smart-integration-checkayanat-amangeldi
  • 2026-09-23 17:05Document Firebird setup architecture and jury verification in RussianAyanat Amangeldi
  • 2026-09-23 16:58Expand Plan B date search and explain larger budget alternativesAyanat Amangeldi
  • 2026-09-23 16:42Add contractor comparison and accessible card transitionsAyanat Amangeldi
  • 2026-09-23 16:34Polish recommendation UI with quick examples and clearer explanationsAyanat Amangeldi
  • 2026-09-23 16:26docs: record live OpenAI verification and hackathon submission requirementsAyanat Amangeldi
  • 2026-09-23 15:45Prepare deployable release and Firebird defense materialsAyanat Amangeldi
  • 2026-09-23 15:31feat: connect smart matching API, evidence and explicit Plan B actionsDilyara Anetbayeva
Все коммиты (15)
  • 2026-09-23 15:22Add evidence-based preferences, Plan B and optional server OpenAI explanationsAyanat Amangeldi
  • 2026-09-23 14:45test: verify integrated Firebird app and run UI checks by defaultAyanat Amangeldi
  • 2026-09-23 14:35feat: build Russian recommendation UI with real matching serviceDilyara Anetbayeva
  • 2026-09-23 14:17Merge remote-tracking branch 'origin/codex/matching-core' into codex/recommendation-uiDilyara Anetbayeva
  • 2026-09-23 14:13feat: implement deterministic contractor matching with source-backed explanationsAyanat Amangeldi
  • 2026-09-23 13:51chore: scaffold Firebird and define shared recommendation contractAyanat Amangeldi
  • 2026-09-23 13:50docs: plan Firebird recommendation UI and integrationDilyara Anetbayeva
Структура репозитория (57 файлов)
.env.example
.gitignore
README.md
deliverables/Firebird-defense.pptx
docs/backend.md
docs/defense.md
docs/demo-script.md
docs/integration-check.md
docs/release.md
docs/smart-matching.md
docs/ui-plan.md
index.html
package-lock.json
package.json
scripts/check-ai-live.ts
scripts/check-browser-build.ts
scripts/demo.ts
scripts/generate-demos.ts
scripts/prepare-data.ts
scripts/smoke-release.ts
server/ai-explanations.ts
server/api.ts
server/index.ts
src/components/ContractorCard.tsx
src/components/ContractorComparison.tsx
src/core/explanations.ts
src/core/index.ts
src/core/matching.ts
src/core/model.ts
src/core/plan-b.ts
src/core/preferences.ts
src/core/service.ts
src/core/validate-request.ts
src/data/audit.json
src/data/catalog.json
src/data/demo-queries.json
src/data/parse-csv.ts
src/data/raw/contractors.csv
src/data/smart-examples.ts
src/main.tsx
src/pages/RecommendationPage.tsx
src/pages/recommendationServiceAdapter.ts
src/shared/contracts.ts
src/styles/app.css
tests/core/data.test.ts
tests/core/fixtures.ts
tests/core/integration.test.ts
tests/core/service.test.ts
tests/core/smart-matching.test.ts
tests/server/ai.test.ts
tests/server/api.test.ts
tests/ui/browser.html
tests/ui/browser.tsx
tests/ui/http-adapter.test.ts
tests/ui/requests.test.ts
tsconfig.json
vite.config.ts
Ветки (6)

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

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

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