EventLens
Подбор до трёх подрядчиков для мероприятий в Казахстане: проверка обязательных условий, объяснение оценок, альтернативные даты.
О проекте
Команда: 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.mdEventLens
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 (рекомендуется)
-
При первом запуске создайте
.envв корне проекта:Copy-Item .env.example .envЕсли
.envуже существует, не перезаписывайте его. Файл игнорируется Git. ВпишитеOPENAI_API_KEY=..., если хотите использовать OpenAI. Ключ нужен только backend; не добавляйте его во frontend или переменныеVITE_*. -
Запустите весь стек, включая локальную модель для резервного 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 -
Откройте 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 при наличии ключа, иначе проверенный шаблон. Чтобы использовать локальную модель также для этих текстов, поставьте в.envEXPLANATION_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 и интернет для первой установки зависимостей и загрузки локальной модели.
-
Один раз установите зависимости из корня репозитория:
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ещё нет. При желании добавьте в.envOPENAI_API_KEY=.... Еслиpythonне найден, установите Python с включённым PATH или используйте Windows launcherpy -3.12для создания окружений. -
Откройте четыре терминала 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 -
Откройте http://localhost:5173. Vite перенаправляет
/apiна backendlocalhost: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 не заменяет коммиты в ветках.
Авторы коммитов
История коммитов
- 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
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.