AAYMA
RU
Войти

EventLens

Подбор до трёх подрядчиков для мероприятий в Казахстане: проверка обязательных условий, объяснение оценок, альтернативные даты.

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

О проекте

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

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

Суть

Подбор до трёх подрядчиков для мероприятий в Казахстане: проверка обязательных условий, объяснение оценок, альтернативные даты. Есть поиск по свободному описанию и AI-чат.

Как устроено

Запрос на естественном языке превращается в поля через LLM, и backend проверяет каждое значение по точной цитате и справочникам. Незаполненные обязательные поля пользователь дополняет вручную. Бэкенд на FastAPI применяет правила-фильтры и взвешенный скоринг, TF-IDF-сервис (порт 8100) добавляет текстовое сходство. Constraint doctor предлагает другие даты. Объяснения пишет OpenAI, локальный Qwen2.5-0.5B-Instruct или шаблон, подбор от LLM не зависит.

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

  • rule-based constraint filtering
  • weighted scoring
  • TF-IDF similarity
  • NL field extraction with quote verification
  • alternative dates search
  • score contribution trace

Особенности

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

Стек

Python · FastAPI · React · TypeScript · Vite · PyTorch (CPU) · Docker Compose · nginx · mypy

Модели

gpt-4.1-mini · Qwen2.5-0.5B-Instruct


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

README

README.md

EventLens

EventLens подбирает подрядчиков для мероприятий в Казахстане: проверяет обязательные условия, показывает до трёх вариантов, объясняет оценки и предлагает другие даты. Во frontend также доступны компактные готовые сценарии, поиск по описанию, подробный разбор ранжирования и AI-чат. Правила подбора и API описаны в архитектуре.

В поиске по описанию можно написать, например: «Нужен ведущий на корпоратив в Алматы 15 ноября 2026, бюджет до 800 000 ₸, на 6 часов». AI извлекает поля, а backend проверяет каждое значение по точной цитате из запроса и справочникам. Незаполненные условия не берутся из примера или текущей формы: если не хватает обязательных полей, пользователь дополняет их вручную. Поиск запускается автоматически только при полном и проверенном запросе. При наличии ключа используется OpenAI, иначе — локальная модель из профиля local-llm.

Что понадобится

  • Для варианта с Docker: Docker Desktop с запущенным Docker Engine и docker compose.
  • Для варианта без Docker: Python 3.12+ и Node.js 22+ с npm.
  • Свободные порты: 8000 (backend), 8100 (сервис сходства), 8200 (локальная модель); frontend использует 3000 в Docker или 5173 без Docker.
  • Интернет при первой сборке образов и первой загрузке весов локальной модели.

Все команды ниже выполняются из корня репозитория — папки, где находятся docker-compose.yml, backend/ и frontend/. На Windows откройте PowerShell в этой папке. npm start в корне не работает: package.json лежит в frontend/.

Вариант 1. Запуск с Docker (рекомендуется)

  1. При первом запуске создайте .env в корне проекта:

    Copy-Item .env.example .env
    

    Если .env уже существует, не перезаписывайте его. Файл игнорируется Git. Впишите OPENAI_API_KEY=..., если хотите использовать OpenAI. Ключ нужен только backend; не добавляйте его во frontend или переменные VITE_*.

  2. Запустите весь стек, включая локальную модель для резервного AI-чата:

    docker compose --profile local-llm up -d --build
    

    При первом запуске локальный контейнер скачает Qwen2.5-0.5B-Instruct и установит CPU-зависимости — это может занять несколько минут. Весы хранятся в Docker volume huggingface-cache и не лежат в Git-репозитории. Дождитесь состояния healthy у backend, ai-service и local-explainer:

    docker compose --profile local-llm ps
    
  3. Откройте http://localhost:3000. Документация API — http://localhost:8000/docs. Быстрая проверка:

    Invoke-RestMethod http://localhost:8000/api/health
    Invoke-RestMethod http://localhost:8100/health
    Invoke-RestMethod http://localhost:8200/health
    

    Чат сначала пробует OpenAI при наличии ключа, затем локальную модель. Без ключа будет использоваться локальная модель. Подбор подрядчиков не зависит от AI-чата. Для текстов «Почему этот подрядчик подходит» режим auto использует OpenAI при наличии ключа, иначе проверенный шаблон. Чтобы использовать локальную модель также для этих текстов, поставьте в .env EXPLANATION_MODE=local и перезапустите стек.

Остановить контейнеры без удаления сохранённых весов:

docker compose --profile local-llm down

Если нужна только версия с OpenAI без локальной модели, достаточно docker compose up -d --build и ключа в .env. В этом режиме при отказе OpenAI AI-чат будет недоступен; основной поиск продолжит работать. Не используйте down -v, если хотите сохранить скачанные веса.

Вариант 2. Запуск без Docker

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

  1. Один раз установите зависимости из корня репозитория:

    python -m venv backend/.venv
    backend/.venv/Scripts/python.exe -m pip install -r backend/requirements-dev.txt
    python -m venv services/ai/.venv
    services/ai/.venv/Scripts/python.exe -m pip install "torch>=2.4,<3" --index-url https://download.pytorch.org/whl/cpu
    services/ai/.venv/Scripts/python.exe -m pip install -r services/ai/requirements-local.txt
    npm --prefix frontend ci
    Copy-Item .env.example .env
    

    Последнюю команду выполняйте только если .env ещё нет. При желании добавьте в .env OPENAI_API_KEY=.... Если python не найден, установите Python с включённым PATH или используйте Windows launcher py -3.12 для создания окружений.

  2. Откройте четыре терминала PowerShell в корне репозитория и запустите по одной команде в каждом:

    # Терминал 1 — backend, загружает .env
    backend/.venv/Scripts/python.exe -m uvicorn backend.app.main:app --reload --port 8000 --env-file .env
    
    # Терминал 2 — детерминированное текстовое сходство
    services/ai/.venv/Scripts/python.exe -m uvicorn app.main:app --app-dir services/ai --port 8100
    
    # Терминал 3 — локальная модель для AI-чата
    services/ai/.venv/Scripts/python.exe -m uvicorn app.local_explainer:app --app-dir services/ai --port 8200 --env-file .env
    
    # Терминал 4 — Vite frontend
    npm --prefix frontend run dev
    
  3. Откройте http://localhost:5173. Vite перенаправляет /api на backend localhost:8000; менять VITE_API_URL для обычного локального запуска не требуется. Проверки API и локальной модели — те же URL, что в варианте с Docker. Для остановки нажмите Ctrl+C в каждом терминале.

На macOS/Linux используйте python3 -m venv ... и замените .../Scripts/python.exe на .../bin/python, а Copy-Item .env.example .env на cp .env.example .env; остальные команды аналогичны. Если локальная модель не нужна, третий терминал и установку CPU PyTorch можно пропустить, но AI-чат тогда требует действующий ключ OpenAI.

Настройки и диагностика

Корневой .env.example описывает настройки сервера. OPENAI_MODEL по умолчанию равен gpt-4.1-mini. Для API нужен отдельный ключ OpenAI Platform — подписка ChatGPT сама по себе его не предоставляет. EXPLANATION_MODE=auto|local|openai|template управляет только текстом объяснений карточек, не порядком подбора и не приоритетом провайдеров AI-чата. SEMANTIC_MODE=tfidf использует локальный сервис сходства на порту 8100; при его недоступности backend сообщает о fallback. Чат получает параметры поиска и историю беседы, но пока не получает сам список выданных подрядчиков — он не должен утверждать, что видел результаты.

Если порт занят, остановите другой процесс/контейнер на нём или измените проброс порта и соответствующий URL. Если Docker не отвечает, сначала запустите Docker Desktop. Если frontend показывает ошибку API, проверьте /api/health и docker compose --profile local-llm logs backend (Docker) или вывод первого терминала (без Docker). Если AI-чат недоступен, проверьте OPENAI_API_KEY, состояние local-explainer и его /health.

Проверки проекта

Из корня репозитория на Windows:

backend/.venv/Scripts/python.exe -m unittest discover -s backend/tests -v
backend/.venv/Scripts/python.exe -m mypy --strict backend/app
Push-Location services/ai
./.venv/Scripts/python.exe -m unittest discover -s tests -v
Pop-Location
npm --prefix frontend test
npm --prefix frontend run lint
npm --prefix frontend run build

После намеренного изменения backend-контракта или данных обновляйте контракт и фикстуры командами из backend/scripts/.

Синхронизация веток

После push в main workflow .github/workflows/sync-main.yml пытается влить изменения в arys и damir без force-push. При конфликте или запрете записи GitHub Actions соответствующее задание завершится ошибкой; ветку нужно разрешить вручную. Workflow не заменяет коммиты в ветках.

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

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

Artem Khloptsev 35DamirKus0 8LMNK 7

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

  • 2026-09-23 20:09Improve Search3Artem Khloptsev
  • 2026-09-23 20:05Improve SearchArtem Khloptsev
  • 2026-09-23 19:57Improve READMEArtem Khloptsev
  • 2026-09-23 19:54ImproveArtem Khloptsev
  • 2026-09-23 19:44added chat with aiArtem Khloptsev
  • 2026-09-23 19:25added ai model with api and localyArtem Khloptsev
  • 2026-09-23 17:22chore: checkpoint local ai explanation changesLMNK
  • 2026-09-23 17:20added chatbot sidebarLMNK
Все коммиты (50)
  • 2026-09-23 16:52added glassLMNK
  • 2026-09-23 16:42feat(backend): expose sequential constraint funnel detailsDamirKus0
  • 2026-09-23 16:42feat(backend): find alternative dates with shared constraintsDamirKus0
  • 2026-09-23 16:42feat(backend): provide top-three comparison and ranking reasonsDamirKus0
  • 2026-09-23 16:42feat(backend): generate verified demo presets from catalogDamirKus0
  • 2026-09-23 16:42feat(backend): add opt-in match trace and integration checksDamirKus0
  • 2026-09-23 16:42feat(backend): expose evidence and exact score contributionsDamirKus0
  • 2026-09-23 16:25added footerLMNK
  • 2026-09-23 16:11Merge branch 'arys' of https://github.com/BAITC-Hacks/hack-ca321387-default into arysLMNK
  • 2026-09-23 16:11added faviconLMNK
  • 2026-09-23 18:02Merge main into arys and resolve frontend conflictsArtem Khloptsev
  • 2026-09-23 15:44added frontendLMNK
  • 2026-09-23 17:33Removed unnessary packagesArtem Khloptsev
  • 2026-09-23 15:30Added backendDamirKus0
  • 2026-09-23 17:30Added the git flowArtem Khloptsev
  • 2026-09-23 17:24Merge pull request #14 from BAITC-Hacks/arysArtem Khloptsev
  • 2026-09-23 17:00UpdateArtem Khloptsev
  • 2026-09-23 16:55Automate main sync to team branchesArtem Khloptsev
  • 2026-09-23 16:54Merge pull request #13 from BAITC-Hacks/mainArtem Khloptsev
  • 2026-09-23 16:53Merge pull request #12 from BAITC-Hacks/arysArtem Khloptsev
  • 2026-09-23 16:48Merge origin/main into mainArtem Khloptsev
  • 2026-09-23 16:48Merge pull request #11 from BAITC-Hacks/mainArtem Khloptsev
  • 2026-09-23 16:47Merge pull request #10 from BAITC-Hacks/damirArtem Khloptsev
  • 2026-09-23 16:43Addede frontendArtem Khloptsev
  • 2026-09-23 16:16Merge pull request #9 from BAITC-Hacks/arysArtem Khloptsev
  • 2026-09-23 14:15Merge pull request #2 from BAITC-Hacks/damirDamirKus0
  • 2026-09-23 16:10Added update into servicesArtem Khloptsev
  • 2026-09-23 15:54Added CPArtem Khloptsev
  • 2026-09-23 15:54Merge pull request #8 from BAITC-Hacks/arysArtem Khloptsev
  • 2026-09-23 15:32Merge pull request #7 from BAITC-Hacks/damirArtem Khloptsev
  • 2026-09-23 15:20Added documentationArtem Khloptsev
  • 2026-09-23 14:52Merge pull request #6 from BAITC-Hacks/mainArtem Khloptsev
  • 2026-09-23 14:51Merge pull request #5 from BAITC-Hacks/mainArtem Khloptsev
  • 2026-09-23 14:34Added the initial infrastructureArtem Khloptsev
  • 2026-09-23 14:29Restructure project architectureArtem Khloptsev
  • 2026-09-23 14:23Merge remote main into full stack setupArtem Khloptsev
  • 2026-09-23 14:20Add full stack project setupArtem Khloptsev
  • 2026-09-23 14:13Merge pull request #3 from BAITC-Hacks/mainArtem Khloptsev
  • 2026-09-23 14:11Merge pull request #1 from BAITC-Hacks/mainArtem Khloptsev
  • 2026-09-23 14:10Move application to repository rootArtem Khloptsev
  • 2026-09-23 14:06Merge project structure into mainArtem Khloptsev
  • 2026-09-23 13:51Added first structureArtem Khloptsev
Структура репозитория (132 файлов)
.DS_Store
.dockerignore
.env.example
.gitignore
AGENTS.md
README.md
backend/.env.example
backend/Dockerfile
backend/app/__init__.py
backend/app/catalog.py
backend/app/chat.py
backend/app/discovery.py
backend/app/explanations.py
backend/app/feature_schemas.py
backend/app/main.py
backend/app/match_details.py
backend/app/matching.py
backend/app/request_extraction.py
backend/app/rules.py
backend/app/schemas.py
backend/app/semantic.py
backend/app/trace.py
backend/docs/matching-features.md
backend/requirements-dev.txt
backend/requirements.txt
backend/scripts/export_contract.py
backend/scripts/export_fixtures.py
backend/scripts/http_smoke.py
backend/tests/test_chat.py
backend/tests/test_discovery.py
backend/tests/test_feature_routes.py
backend/tests/test_match_features.py
backend/tests/test_matching.py
backend/tests/test_openai_explanations.py
backend/tests/test_request_extraction.py
docker-compose.yml
docs/ARCHITECTURE.md
docs/EventLens_HackAlemAI_TZ.pdf
docs/HackAlem AI_ Хакатон-задача_ умный подбор подрядчиков.docx
docs/hackathon dataset anonymized .csv
docs/hackathon dataset preview.html
frontend/.env.example
frontend/Dockerfile
frontend/eslint.config.js
frontend/index.html
frontend/nginx.conf
frontend/package-lock.json
frontend/package.json
frontend/public/favicon.svg
frontend/public/icons.svg
frontend/src/app/App.tsx
frontend/src/app/providers.tsx
frontend/src/app/theme.ts
frontend/src/assets/hero.png
frontend/src/assets/react.svg
frontend/src/features/chat/ChatComposer.tsx
frontend/src/features/chat/ChatMessages.tsx
frontend/src/features/chat/ChatSidebar.tsx
frontend/src/features/chat/ChatWelcome.tsx
frontend/src/features/chat/chat.api.ts
frontend/src/features/chat/chat.css
frontend/src/features/chat/chat.types.ts
frontend/src/features/chat/useChat.ts
frontend/src/features/diagnostics/AvailabilityDates.tsx
frontend/src/features/diagnostics/ConstraintDoctor.tsx
frontend/src/features/matching/ContractorCard.tsx
frontend/src/features/matching/RankingDetails.tsx
frontend/src/features/matching/ResultsSection.tsx
frontend/src/features/matching/matching.css
frontend/src/features/matching/useMatch.ts
frontend/src/features/search/DemoPresets.tsx
frontend/src/features/search/NaturalLanguageSearch.tsx
frontend/src/features/search/SearchFields.tsx
frontend/src/features/search/SearchForm.tsx
frontend/src/features/search/extract.api.ts
frontend/src/features/search/search.constants.ts
frontend/src/features/search/search.css
frontend/src/features/search/useMetadata.ts
frontend/src/features/settings/AppearanceSettings.tsx
frontend/src/features/settings/SettingsContext.ts
frontend/src/features/settings/SettingsDrawer.tsx
frontend/src/features/settings/SettingsProvider.tsx
frontend/src/features/settings/ThemeToggle.tsx
frontend/src/features/settings/settings.css
frontend/src/features/settings/useSettings.ts
frontend/src/index.css
frontend/src/main.tsx
frontend/src/mocks/catalog.json
frontend/src/mocks/engine.ts
frontend/src/mocks/fixtures.json
frontend/src/pages/MatchPage.tsx
frontend/src/shared/api/client.ts
frontend/src/shared/api/discovery.api.ts
frontend/src/shared/api/match.api.ts
frontend/src/shared/api/metadata.api.ts
frontend/src/shared/format.ts
frontend/src/shared/layout/AppFooter.tsx
frontend/src/shared/layout/AppHeader.tsx
frontend/src/shared/layout/AppShell.tsx
frontend/src/shared/layout/layout.css
frontend/src/shared/types/match.ts
frontend/src/shared/types/settings.ts
frontend/src/shared/ui/GlassPanel.tsx
frontend/src/shared/ui/glass.css
frontend/src/vite-env.d.ts
frontend/tests/contract.test.mjs
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vite.config.ts
services/ai/.dockerignore
services/ai/Dockerfile
services/ai/Dockerfile.local
services/ai/README.md
services/ai/app/__init__.py
services/ai/app/constraint_doctor/__init__.py
services/ai/app/constraint_doctor/doctor.py
services/ai/app/explanations/__init__.py
services/ai/app/explanations/evidence.py
services/ai/app/explanations/generator.py
services/ai/app/local_explainer.py
services/ai/app/main.py
services/ai/app/ranking/__init__.py
services/ai/app/ranking/scorer.py
services/ai/app/ranking/semantic.py
services/ai/app/ranking/weights.py
services/ai/app/schemas/__init__.py
services/ai/app/schemas/models.py
services/ai/requirements-local.txt
services/ai/requirements.txt
services/ai/tests/test_local_explainer.py
services/ai/tests/test_similarity.py
Ветки (3)

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

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

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