Firebird / Event Match («рядом.»)
API, CLI и веб-страница подбора до трёх event-подрядчиков с объяснением проверяемыми фактами и дословными цитатами.
О проекте
Команда: Refrigerators
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Доведённый продукт
Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор
Суть
API, CLI и веб-страница подбора до трёх event-подрядчиков с объяснением проверяемыми фактами и дословными цитатами. Если подходящих мало, предлагает проверенные альтернативы: другую дату, больший бюджет или меньшую длительность. Задеплоен на Vercel с Supabase.
Как устроено
Запрос (город, дата, формат, категория, бюджет, опционально язык, длительность, brief) сначала проходит фильтры по фактам каталога: занятость, бюджет, формат, язык. Затем кандидаты ранжируются символьным TF-IDF в детерминированном порядке, до трёх карточек получают объяснения с проверенными цитатами. При 0–2 подходящих отдельный модуль alternatives перебирает соседние даты, бюджет и длительность и возвращает до трёх готовых запросов с числом кандидатов. Исходы: matched, category_absent, no_eligible, плюс единый формат ошибок.
Ключевые решения
- символьный TF-IDF
- жёсткие фильтры по условиям
- поиск альтернатив Plan B (дата/бюджет/длительность)
- объяснения с дословными цитатами
- request tracing с X-Request-ID
- CLI doctor для самодиагностики
Особенности
Главная фишка — «что изменить, чтобы появился выбор»: проверенные варианты смены условий с готовым запросом (например, 19.12 даёт 1 кандидата, а 17.12 даёт 3). Готовы контракт для фронтенда (OpenAPI, TS-типы, примеры ответов), строгая валидация и адаптеры LLM, но публичное демо на локальных объяснениях.
Стек
Python · FastAPI · Pydantic · HTML · CSS · JavaScript · Supabase · PostgreSQL · Vercel · Node.js test runner · TypeScript · OpenAPI
Модели
OpenAI · NVIDIA Build · Brev/NIM
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-0105a7f9-refrigerators.
README
README.mdFirebird — умный подбор event-подрядчиков
Помогаем выбрать подрядчика для мероприятия и найти проверенный запасной вариант, если на нужную дату или бюджет подходящих людей мало.
🚀 Открыть сайт и попробовать подбор
Без установки и регистрации. Документация API.
Для быстрой проверки: Алматы → Ведущий → корпоратив → 15.10.2026 → 1 200 000 ₸. Получите 3 карточки из 6 подходящих. Измените дату на 19.12.2026: останется 1; во вкладке «Запасные варианты» примените 17.12.2026 — появятся 3. Публичное демо использует Supabase и локальные объяснения с проверенными цитатами; платная AI-модель не вызывается.
API и CLI для Firebird / HackAlem AI (#79-lite). Из городского каталога сервис выбирает до трёх подходящих подрядчиков и объясняет выбор проверяемыми фактами. Исходный CSV содержит 66 профилей, в том числе 13 синтетических; собственных профилей в рабочие данные не добавлено.
Навигация: Возможности · Технологии · Быстрый запуск · API · Проверки · Ограничения.
Что умеет сервис
- Принимает город, дату, формат, категорию и бюджет; учитывает язык, длительность и пожелания.
- Проверяет занятость и обязательные условия, затем показывает до трёх карточек.
- Объясняет выбор фактами и дословными фрагментами описаний; отмечает, что нужно уточнить.
- При недостаточном выборе предлагает проверенное изменение даты, бюджета или длительности.
- Различает отсутствие категории в городе и отсутствие кандидатов, подходящих под условия.
Технологии
| Часть | Что используется |
|---|---|
| Backend | Python, FastAPI, Pydantic; общий алгоритм для REST API и CLI |
| Frontend | HTML, CSS, JavaScript; адаптивная страница «рядом.» |
| Подбор | Фильтры по фактам каталога, символьный TF-IDF, детерминированный порядок |
| Данные | 66 исходных профилей; Supabase / PostgreSQL в облаке, CSV для локального запуска |
| Публикация | Vercel Hobby + Supabase Free |
| Проверки | Python unittest, Node.js test runner, OpenAPI и TypeScript-контракт |
| AI-адаптеры | Подготовлены OpenAI, NVIDIA Build и Brev/NIM; публичное демо использует локальные объяснения |
Схема работы
flowchart LR
A["Условия мероприятия"] --> B["Проверка каталога и фильтры"]
B --> C["Ранжирование TF-IDF"]
C --> D["До трёх карточек с объяснениями"]
B --> E["Если подходят меньше трёх: проверка других условий"]
E --> F["Альтернатива по выбору пользователя"]
F --> A
Веб-страница
Готовый интерфейс находится в web/. Он сохраняет серверный порядок карточек и использует integration/api-client.mjs: вертикальная форма с пожеланиями, основная подборка, вкладка с проверенными запасными вариантами и пояснениями по пожеланиям. Запускайте страницу и API локально по инструкции в web/README.md; GitHub Actions для проверки не требуется.
Для команды фронтенда и Codex
Начните с AGENTS.md и инструкции подключения интерфейса. В integration/ готовы HTTP-клиент без привязки к фреймворку, TypeScript-типы, OpenAPI и реальные примеры ответов для вёрстки. Справочник формы, подбор и альтернативы предоставляет Python API; дизайн и компоненты разрабатывает команда.
Локально разрешены браузерные запросы с localhost и 127.0.0.1 на портах 3000, 4317, 5173. Другие адреса задаются через CORS_ALLOWED_ORIGINS — точные origins через запятую, без *. После изменения перезапустите backend. Инструкция описывает также подключение через /api proxy и обработку ошибок, отмены и устаревших ответов.
Главная фишка: что изменить, чтобы появился выбор
При 0–2 подходящих профилях сервис проверяет другую дату, больший бюджет и меньшую длительность. Возвращает до трёх проверенных вариантов с готовым запросом и числом кандидатов. Исходные карточки остаются ответом на исходные условия.
.\.venv\Scripts\python.exe -m contractor_match.demo --story
Реальная история из каталога: ведущий Алматы за 1 200 000 ₸ — 15 октября подходят 6 → 19 декабря 1 → предложенная дата 17 декабря даёт 3. Флорист Астаны 15 октября за 100 000 ₸ — 0; только сочетание 16 октября + 300 000 ₸ даёт 1. Повышение бюджета само по себе занятость не исправляет.
Быстрый запуск
Python 3.11 или новее и Git. Сначала скачайте проект:
git clone https://github.com/BAITC-Hacks/hack-0105a7f9-refrigerators.git
cd hack-0105a7f9-refrigerators
Репозиторий приватный: для клонирования нужен доступ команды. Публичное демо выше открывается без доступа к GitHub. Дальше все команды выполняются из корня проекта. Они запускают сайт и API вместе, с CSV и локальными объяснениями; ключи не нужны.
Windows PowerShell:
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements-lock.txt
$env:AI_PROVIDER = 'local'
$env:RANKING_PROVIDER = 'tfidf'
$env:CATALOGUE_PROVIDER = 'csv'
.\.venv\Scripts\python.exe run_web.py --no-browser
Linux / macOS:
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements-lock.txt
AI_PROVIDER=local RANKING_PROVIDER=tfidf CATALOGUE_PROVIDER=csv .venv/bin/python run_web.py --no-browser
requirements-lock.txt и requirements.txt содержат одинаковые зафиксированные версии проверенного окружения. Плоский список нужен сборщику Vercel. При обновлении зависимостей повторите тесты и проверку экспорта: схема может зависеть от версии FastAPI/Pydantic.
Откройте локальный сайт. Терминал оставьте открытым.
Документация запросов: Swagger UI.
Если порт занят, добавьте --port 8001 к команде run_web.py.
GET /health проверяет готовность без обращения к модели.
GET /catalogue/options возвращает города, категории по городам, форматы, языки и окно календаря.
При запуске проверяются CSV и конфигурация, затем строится индекс. С повреждённым каталогом или неизвестным AI_PROVIDER сервер не стартует. Данные и индекс хранятся в памяти: после изменения CSV требуется перезапуск. Общий парсер допускает маленькие тестовые каталоги; рабочий загрузчик дополнительно проверяет исходные 66 профилей и 13 синтетических.
CLI и демонстрация
Самодиагностика без сетевых вызовов:
.\.venv\Scripts\python.exe -m contractor_match doctor --frontend-origin http://localhost:5173
.\.venv\Scripts\python.exe -m contractor_match doctor --json
Doctor проверяет Python, зависимости, настройки, CORS, исходный каталог и локальный индекс. Команда работает и до установки пакетов: сообщает об отсутствующих зависимостях. Наличие ключа не означает проверки доступа к модели. Код выхода 1 — ошибка, 0 — локальные проверки пройдены или есть предупреждения.
У ответов API есть X-Request-ID для поиска в логах и X-Process-Time-Ms для времени до начала ответа. Клиент предоставляет ApiClientError.requestId. В stderr пишутся JSON-события с этапами подбора, причинами fallback и безопасным местом сбоя. Инструкция по диагностике показывает, как сохранить журнал и найти ошибку. CLI --json сохраняет чистый результат в stdout.
.\.venv\Scripts\python.exe -m contractor_match recommend --city Алматы --date 2026-10-15 --event-format корпоратив --category Ведущий --budget-kzt 1200000 --brief 'спокойный ведущий делового форума'
.\.venv\Scripts\python.exe -m contractor_match.demo
.\.venv\Scripts\python.exe -m contractor_match.demo --json
На Linux / macOS замените путь к Python на .venv/bin/python.
Команда recommend с --json выводит тот же контракт, что API.
Демо вызывает настоящий pipeline на восьми запросах: ведущий осенью и в декабре, флорист, отсутствующая категория, невыполненные условия, площадка, отрицательное пожелание и фотограф. Первые два запроса отличаются только датой. На 15 октября подходят шесть ведущих Алматы, показываются три; на 19 декабря — один. Демо всегда локальное по умолчанию, даже если в окружении есть ключи.
Запрос и три исхода
POST /recommendations:
{
"city": "Алматы",
"date": "2026-10-15",
"event_format": "корпоратив",
"category": "Ведущий",
"budget_kzt": 1200000,
"duration_hours": 6,
"language": "русский",
"brief": "спокойный ведущий делового форума"
}
Первые пять полей обязательны. Форматы и языки перечислены в справочнике.
Город, категория, формат и язык принимаются в любом регистре с нормализацией пробелов.
Дата — календарная строка ГГГГ-ММ-ДД от 2026-09-23 до 2026-12-31 включительно.
Бюджет — положительное целое JSON-число до 9 007 199 254 740 991 включительно (без потери точности в JavaScript); boolean и числовые строки отклоняются. Тело POST ограничено 64 КиБ; превышение возвращает 413 request_too_large.
Длительность — положительное конечное число; null отключает этот входной фильтр.
Город и категория ограничены 100 символами, brief — 500; неизвестные поля запроса запрещены.
| Результат | HTTP | Значение |
|---|---|---|
| matched | 200 | Есть 1–3 подходящие карточки |
| category_absent | 200 | Известной категории нет в выбранном городе |
| no_eligible | 200 | Категория есть, но все кандидаты исключены условиями |
| invalid_request | 422 | Некорректные параметры или неизвестный город/категория справочника |
| request_too_large | 413 | Тело запроса превышает 64 КиБ |
| catalogue_unavailable | 503 | Не удалось загрузить проверенный каталог из Supabase |
| service_misconfigured | 503 | Неверная конфигурация сервиса; при старте она предотвращает запуск |
| internal_error | 500 | Неожиданная ошибка сервера; безопасное сообщение без внутренних деталей |
Например, «Декоратор» в Астане — category_absent; неизвестная категория с опечаткой — 422. Значения не исправляются догадками.
Ошибки API имеют один формат (включая 404 и 405):
{
"error": {
"code": "invalid_request",
"message": "Проверьте параметры запроса.",
"details": [{"field": "budget_kzt", "message": "Укажите целое число."}]
}
}
Успешный бизнес-ответ сохраняет поля status, message, cards, reasons и ai_mode. Добавлены:
counts: category_total, eligible_total, returned_total и excluded_total. Последний — число уникальных исключённых профилей.ai_reason: безопасная причина выбранного режима объяснений.cards[].evidence_note: ограничение доказательства, если оно есть; тот же текст виден в объяснении.understanding: распознанные стили, нежелательные элементы, языки, применённый язык и источник этого решения.cards[].why_fits,to_clarify,differences: проверенные основания, вопросы к подрядчику и сравнение с показанными карточками.alternatives: changes (field/from_value/to_value), полный request, eligible_count, added_count, candidate_ids, message. ID перечислены для проверки условий, не ранжированы как новая выдача. Повторный POST с request применяет вариант.alternatives_note: границы поиска и правило выбора компромисса.ranking_mode,ranking_reason: фактический способ ранжирования и причина fallback, отдельно от режима объяснений.
Причины busy, over_budget, wrong_format, wrong_language и too_short могут пересекаться. Сумма reasons не равна числу исключённых. Сообщение показывает число занятых на запрошенную дату, даже если удалось вернуть три карточки. Если подходят больше трёх, message отдельно сообщает об ограничении выдачи.
Как работает подбор
- Проверка входа и локальный разбор пожелания, загрузка проверенного каталога.
- Локальные фильтры: город, членство в категории, дата, формат, стартовая цена, язык и длительность. Описание и AI не могут отменить фильтр. У площадок действует тот же календарь.
- Детерминированное символьное TF-IDF сходство описания с запросом, затем меньшая стартовая цена и стабильный id. Версия базового ранжирования: char-tfidf-3-5-v1. Режим объяснений не меняет порядок. По явному RANKING_PROVIDER=brev доступен экспериментальный NIM reranker после фильтров; при сбое используется TF-IDF.
- Для выбранных профилей выделяются точные фрагменты описания. Локальные текстовые подсказки помогают искать стиль, опыт и подход; общая реклама получает меньший приоритет. До трёх фрагментов каждого профиля образуют список, из которого выбирает AI либо локальный алгоритм.
- Общая проверка для обоих режимов подтверждает набор id, длину цитаты, точное вхождение в исходное описание и принадлежность списку. Невалидный AI-ответ заменяется проверенным локальным.
- Объяснение собирается из структурированных фактов и цитаты. Повторяющиеся цитаты по возможности заменяются другими допустимыми; если это невозможно, отсутствие подтверждённого отличия обозначается явно.
TF-IDF и словарь подсказок не доказывают смысловое выполнение всего brief. Пожелание с отрицанием, например «без шумных конкурсов», всегда сопровождается уточнением: его нужно подтвердить у подрядчика. Это не новый жёсткий фильтр. Строки brief и description передаются модели только как данные, без ключей и переписки.
Пожелания и альтернативы
«Нужен спокойный ведущий, без конкурсов, на русском» распознаётся локальными правилами: стиль — спокойный; нежелательно — без конкурсов; язык — русский. Если language не указан, однозначная фраза «на русском/казахском/английском» становится языковым фильтром и явно отражается в understanding. Отдельное поле language имеет приоритет; противоречие с текстом отмечается. При нескольких языках требуется уточнение — система не выбирает один сама.
Это ограниченный словарь, не полноценное понимание произвольного текста: стили спокойный/креативный/традиционный, распространённые отрицания и три языка. Неподтверждённые пожелания попадают в to_clarify; цитата не означает гарантии выполнения. Разница стартовых цен сравнивается только среди показанных. Собственная цитата не доказывает, что у остальных нет такого же опыта.
Альтернативы используют тот же фильтр, что основные карточки; город, категория, формат и язык не меняются. По каждому отдельному полю предлагается наименьшее изменение, увеличивающее общее число подходящих: ближайшая дата в окне (при равной дистанции — более поздняя), минимальный бюджет до следующего подходящего ценового порога, наименьшее сокращение часов. max_hours=null не создаёт ограничения.
Если ни одно поле отдельно не помогает, перебираются сочетания двух, затем трёх полей. Исключаются варианты, у которых все изменения не меньше, чем у другого проверенного варианта; остаётся до трёх с приоритетом расстояния по дате, повышения бюджета, сокращения часов. Это явно описанный компромисс, а не универсальная оценка удобства заказчика. При 3+ подходящих альтернативы не нужны. Пустой список не обещает невозможность решения вообще: проверен только этот набор изменений в исходном каталоге. Цена по-прежнему «от»; доступность — по датасету.
AI и локальный режим
Конфигурация централизована в contractor_match/config.py. Приложение читает переменные окружения; файл .env.example — образец, .env автоматически не загружается.
- local — локальные объяснения; вместе с RANKING_PROVIDER=tfidf весь подбор работает без сети.
- openai / nvidia — явный провайдер.
- brev — явно настроенный NIM chat-сервис; auto его не выбирает. Подключение Brev/NIM.
- auto (по умолчанию) — OpenAI при непустом ключе, иначе NVIDIA, иначе локальный режим. Эта последовательность применяется до вызова; переключений и повторов после ошибки нет.
$env:AI_PROVIDER = 'openai'
$env:OPENAI_API_KEY = '<локально сохранённый API-ключ>'
# либо
$env:AI_PROVIDER = 'nvidia'
$env:NVIDIA_API_KEY = '<ключ NVIDIA Build nvapi-…>'
На Linux / macOS: export AI_PROVIDER=openai и соответствующая переменная ключа. Ключи не добавляйте в проект.
Сохранены адаптеры OpenAI gpt-4o-mini через Responses со структурированным выводом и NVIDIA mistralai/mistral-nemotron через Chat Completions. Модели переопределяются OPENAI_MODEL и NVIDIA_MODEL. Вызовы требуют доступа конкретного аккаунта; тариф OpenAI зависит от модели. Живой доступ команды к обоим провайдерам пока не проверен. Brev-ключ и купон не заменяют inference-ключ: см. документацию Brev.
На внешнюю часть установлен общий срок 6 секунд: опциональный reranker — максимум 2 секунды, объяснения — оставшееся время. Синхронный endpoint FastAPI работает в worker-потоке; при прямом вызове из async-кода используйте await asyncio.to_thread(recommend, request).
| ai_mode | ai_reason |
|---|---|
| openai / nvidia / brev | success — проверенный ответ провайдера |
| not_used | not_needed — карточек нет, модель не вызывалась |
| fallback | local_requested — выбран local; missing_key — нет ключа |
| fallback | timeout, auth_error, rate_limited, network_error, provider_error |
| fallback | invalid_response — повреждённый формат; invalid_evidence — неверные id/цитаты |
Логи отказов содержат провайдера, код причины и request_id. Отдельная запись подбора показывает времена этапов и счётчики. Ключи, brief, сырые ответы сервера и текст исключений в журналы приложения не попадают.
Отдельный живой прогон при настроенном ключе:
.\.venv\Scripts\python.exe -m contractor_match.demo --provider openai
# либо --provider nvidia
Этот явный флаг разрешает сетевые вызовы из демо, которые могут расходовать API-баланс. Команда завершается с кодом 1 при fallback в живом режиме или ответе дольше 10 секунд; отсутствие ключа даёт ошибку до первого запроса.
Проверка по критериям задачи
Локальное демо python -m contractor_match.demo выполняет эти сценарии через настоящий pipeline:
| Сценарий | Запрос | Что проверить |
|---|---|---|
| Плотная категория | Ведущий, Алматы, 15.10.2026, 1 200 000 ₸ | Три карточки с разными подтверждающими цитатами; повтор сохраняет порядок. |
| Смена даты | Тот же запрос на 19.12.2026 | Остаётся один подходящий; сообщение показывает число занятых. |
| Редкая категория | Флорист, Алматы, 15.10.2026, 300 000 ₸ | Один кандидат и причина короткой выдачи. |
| Нет подходящих | Флорист, Астана, 15.10.2026, 100 000 ₸ | no_eligible, пустые карточки и причины словами. |
| Нет категории | Декоратор, Астана | Отдельный исход category_absent. |
Для оценки объяснений скройте имена: цитаты должны помогать отличать кандидатов. Если исходные описания не дают подтверждённых различий, сервис отмечает это ограничение. Ориентир ответа — до 10 секунд; демо измеряет время каждого реального вызова. Сетевое время живого AI проверяется отдельно.
Проверка
.\.venv\Scripts\python.exe -m unittest discover -s tests -v
.\.venv\Scripts\python.exe -m contractor_match.export_contract --check
node --test integration/tests/api-client.test.mjs
Для тестов клиента нужен Node.js 22+. Тесты работают без интернета и настоящих ключей. Проверяются фильтры и их границы, 0/1/2/3 карточки, все три исхода, повреждённый CSV, повторные id, тайм-аут и ошибки AI, локальные цитаты, неизменность порядка при перезапуске, смене регистра и режима объяснений. Проверки интеграции охватывают CORS, безопасные ошибки, контракт, преобразование формы, отмену и запоздавшие ответы.
После изменения схемы обновите файлы для фронтенда командой python -m contractor_match.export_contract и включите их в тот же коммит. Режим --check обнаруживает расхождение без записи. Экспорт принудительно использует local + tfidf, даже при наличии ключей.
GitHub Actions отключён: тесты и локальное демо запускаются в рабочей среде без расходов на GitHub. На 23.09.2026 локально прошли 70 Python-тестов и 19 тестов JavaScript-клиента, включая матрицу из 264 сценариев на исходном каталоге. Отчёт о проверке, состояние проекта.
Объединённые работы команды
В main сохранена история обеих веток codex/*. Рабочий сайт — web/, мобильные концепты — future-app-figma/, ранний автономный вариант — prototypes/offline-web/. Архивный подборщик не используется публичным сайтом. Обзор работ.
Соответствие исходному ТЗ, измерения и оценка объяснений, состояние проекта.
Ограничения данных
Цена указана «от» за мероприятие, это не почасовой тариф и не окончательная смета. max_hours = null означает, что ограничение присутствия на площадке неприменимо. Отсутствие даты в busy_dates подтверждает доступность только в окне датасета. synthetic, city_imputed и price_imputed сохраняются в карточках; восстановленные значения не подтверждены подрядчиком. Бронирование, заявки и живое обновление календаря не реализованы.
Источник — приложенные материалы HackAlem AI: DOCX определяет ТЗ, CSV — факты, HTML служит превью. Диагностика, строгая схема входа и дополнительные проверки — инженерные улучшения команды, а не новые требования организаторов.
Публикация для команды
Сайт и API можно запустить вместе: python -m uvicorn app:app --port 8000 и открыть
http://127.0.0.1:8000/. Бесплатный облачный запуск Vercel + Supabase:
инструкция. Текущее состояние публикации — в PROJECT_STATE.
Автодеплой из GitHub пока не подключён: после изменения кода требуется повторная
публикация через Vercel CLI по инструкции выше.
Авторы коммитов
История коммитов
- 2026-09-23 17:39Improve README overview, technology table and fullstack quick startairsmooth
- 2026-09-23 17:12Record verified production deployment and merged branch auditairsmooth
- 2026-09-23 17:09Fix stale selections, validate API payloads and harden public requests; document full auditairsmooth
- 2026-09-23 16:48Merge web branch and mobile designs; retain offline prototype separately from live API siteairsmooth
- 2026-09-23 16:47Merge criteria branch history preserving integrated recommendation improvementsairsmooth
- 2026-09-23 16:40Record latest team card layout in repository reviewairsmooth
- 2026-09-23 16:39Merge remote-tracking branch 'origin/main'airsmooth
- 2026-09-23 16:39Document live Vercel and Supabase deployment and repository reviewairsmooth
Все коммиты (42)
- 2026-09-23 16:37Organize contractor details and move match summary below cardskanvarova
- 2026-09-23 16:31Merge team single-process launcher with shared cloud entrypointairsmooth
- 2026-09-23 16:30Prepare Vercel fullstack deployment and verified Supabase catalogueairsmooth
- 2026-09-23 16:24Serve web UI and recommendations API from one local processkanvarova
- 2026-09-23 16:12Add future mobile app designs and Figma import assetsmadinasatualdypova
- 2026-09-23 16:01Merge team web interface and show diagnostic request IDsairsmooth
- 2026-09-23 15:58Add request tracing, safe pipeline logs and offline doctor diagnosticsairsmooth
- 2026-09-23 15:54Add event matching web page with live API recommendations and alternativeskanvarova
- 2026-09-23 15:37Prepare frontend handoff, shared API client and safe browser integrationairsmooth
- 2026-09-23 15:31Simplify web interface and sync current local recommendation logicmadinasatualdypova
- 2026-09-23 15:08Clarify evaluation baseline and current test countsairsmooth
- 2026-09-23 15:07Merge team decision to keep verification localairsmooth
- 2026-09-23 15:05Add verified alternatives, brief interpretation and opt-in Brev NIM adaptersairsmooth
- 2026-09-23 14:59Add interactive Event Match web app with verified Plan B alternativesmadinasatualdypova
- 2026-09-23 14:51Document local-only verification in docs/REQUIREMENTS.mdkanvarova
- 2026-09-23 14:50Document local-only verification in docs/EVALUATION.mdkanvarova
- 2026-09-23 14:50Document local-only verification in docs/PROJECT_STATE.mdkanvarova
- 2026-09-23 14:50Document local-only verification in README.mdkanvarova
- 2026-09-23 14:50Use local verification instead of GitHub Actionskanvarova
- 2026-09-23 14:46Document verified CI billing blocker [skip ci]airsmooth
- 2026-09-23 14:42Merge judging-criteria improvements with backend hardeningairsmooth
- 2026-09-23 14:35Harden recommendation evidence and add reproducible offline evaluationairsmooth
- 2026-09-23 14:30Improve recommendations against HackAlem judging criteriakanvarova
- 2026-09-23 14:21Keep CI outside this PR until repository runners are availablekanvarova
- 2026-09-23 14:13Run recommendation tests on pull requestskanvarova
- 2026-09-23 14:13Document judging scenarios and recommendation pipelinekanvarova
- 2026-09-23 14:13Check live demo scenarios and evidencekanvarova
- 2026-09-23 14:13Prefer specific contractor evidencekanvarova
- 2026-09-23 14:12Choose distinct evidence across recommendation cardskanvarova
- 2026-09-23 14:12Explain calendar availability and starting priceskanvarova
- 2026-09-23 14:07Validate catalogue at startup and unify request errorsairsmooth
- 2026-09-23 13:58Improve recommendation API resilience and input handlingairsmooth
- 2026-09-23 13:43Clarify NVIDIA Build and Brev credentialsairsmooth
- 2026-09-23 13:41Add event contractor recommendation API and CLIairsmooth
Структура репозитория (91 файлов)
.env.example .gitignore .python-version .vercelignore AGENTS.md README.md app.py contractor_match/__init__.py contractor_match/__main__.py contractor_match/alternatives.py contractor_match/api.py contractor_match/catalogue.py contractor_match/cli.py contractor_match/config.py contractor_match/demo.py contractor_match/doctor.py contractor_match/eligibility.py contractor_match/explanations.py contractor_match/export_contract.py contractor_match/models.py contractor_match/nim.py contractor_match/observability.py contractor_match/preferences.py contractor_match/ranking.py contractor_match/request_limits.py contractor_match/service.py contractor_match/supabase_catalogue.py data/contractors.csv docs/BREV.md docs/DEBUGGING.md docs/DEBUG_REPORT.md docs/DEPLOYMENT.md docs/EVALUATION.md docs/FRONTEND_HANDOFF.md docs/PROJECT_STATE.md docs/REPOSITORY_REVIEW.md docs/REQUIREMENTS.md future-app-figma/README.md future-app-figma/android/01-главная.svg future-app-figma/android/02-поиск.svg future-app-figma/android/03-результаты.svg future-app-figma/android/04-резюме.svg future-app-figma/android/05-сравнение.svg future-app-figma/android/06-другие-условия.svg future-app-figma/android/07-избранное.svg future-app-figma/android/08-команда.svg future-app-figma/event-match-mobile.zip future-app-figma/index.html future-app-figma/ios/01-главная.svg future-app-figma/ios/02-поиск.svg future-app-figma/ios/03-результаты.svg future-app-figma/ios/04-резюме.svg future-app-figma/ios/05-сравнение.svg future-app-figma/ios/06-другие-условия.svg future-app-figma/ios/07-избранное.svg future-app-figma/ios/08-команда.svg future-app-figma/overview.png integration/README.md integration/api-client.d.mts integration/api-client.mjs integration/api-types.d.ts integration/examples/brief_understanding.json integration/examples/catalogue_options.json integration/examples/category_absent.json integration/examples/invalid_request.json integration/examples/matched.json integration/examples/no_eligible.json integration/examples/short_with_alternative.json integration/openapi.json integration/tests/api-client.test.mjs prototypes/offline-web/README.md prototypes/offline-web/tests/planner.test.mjs requirements-lock.txt requirements.txt run_web.py start-web.cmd supabase/migrations/202609230001_contractors.sql tests/test_catalogue_matrix.py tests/test_deployment.py tests/test_doctor.py tests/test_frontend_contract.py tests/test_hardening.py tests/test_observability.py tests/test_public_safety.py tests/test_recommendations.py tests/test_rescue.py vercel.json web/README.md web/app.js web/index.html web/styles.css
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.