AlemEdu
Площадка, где заказчик описывает проблему, уточняет её с AI-помощником и публикует структурированную задачу, а студенческие команды откликаются.
О проекте
Команда: 1465
Кейс HackAlem.ai: Образование — AI Sana
Стадия: Доведённый продукт
Задача кейса: Challenge Hub: превратить задачу бизнеса в задание для студенческих команд
Суть
Площадка, где заказчик описывает проблему, уточняет её с AI-помощником и публикует структурированную задачу, а студенческие команды откликаются. Заказчик вручную выбирает или отклоняет отклики.
Как устроено
Backend на Laravel (TaskEditor, TaskScorer) пересчитывает полноту описания 0–100 с разбивкой по критериям. AiQuestions генерирует 3–7 уточняющих вопросов через OpenAI Responses API с JSON Schema, в автономном режиме работает MockAiQuestions. Сущности Task / Team / Offer хранятся в SQLite. Фронтенд на Vue 3 отдаётся тем же сервером. Статус задачи не зависит от рейтинга, AI не назначает исполнителя.
Ключевые решения
- Structured Outputs / JSON Schema
- прозрачный скоринг полноты
- детерминированный mock-режим AI
- e2e-тесты Playwright
Особенности
Жюри получает рабочую демоверсию через Cloudflare Tunnel и запуск одной командой START.cmd. AI-режим (openai/mock/auto) явно помечен в интерфейсе, при ошибке OpenAI ответ не подменяется заглушкой молча. Открыто сказано, что Codex использовался для разработки.
Стек
PHP · Laravel 12 · SQLite · Vue 3 · Vite · Docker Compose · Render · Cloudflare Tunnel · PHPUnit · Vitest · Playwright
Модели
gpt-5.4-mini
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-c8a98f95-1465.
README
README.mdAlemEdu
Площадка образовательных задач для организаций и студенческих команд. Прототип для HackAlem AI.
Открыть сайт для жюри · Показ до 5 минут · Памятка жюри
Репозиторий: BAITC-Hacks/hack-c8a98f95-1465. Итоговая версия находится в ветке main.
Ссылка выше ведёт на работающую демоверсию через временный HTTPS-туннель. Компьютер организатора должен оставаться включённым и онлайн. На публичном показе используется явно обозначенный AI-деморежим, а не ответы внешней модели.
Краткое описание
Учебным организациям нужно понятно формулировать реальные потребности, а студенческим командам нужны задачи для практики. AlemEdu соединяет эти стороны: заказчик описывает проблему, уточняет её с помощником, публикует задачу и рассматривает предложения команд.
Проект предназначен для школ, колледжей, университетов и команд разработчиков. Рейтинг показывает полноту подтверждённого описания, а не качество будущего решения. Выбор исполнителя всегда остаётся за заказчиком.
Что реализовано
- Создание и редактирование черновиков, подтверждение сведений и отдельное действие публикации.
- Карточки с учреждением, регионом, охватом, категорией и готовностью описания.
- Каталог опубликованных задач с поиском, фильтрами и сортировкой.
- Прозрачная оценка полноты описания от 0 до 100 с разбивкой по критериям.
- AI-помощник: 3–7 уточняющих вопросов; подключение OpenAI и отдельный автономный деморежим.
- Отклики команд: идея, план, сроки и необязательная ссылка на прототип.
- Панель заказчика со списком откликов, фильтрами и кнопками «Выбрать» / «Отклонить», отправляющими решение в API.
- Кабинеты заказчика и команды; решения сохраняются после перезагрузки.
- Проверки прав выбранного демопрофиля, валидация запросов, состояния загрузки, ошибки и повтор запросов.
- Адаптивный интерфейс, синтетические демоданные, автоматические тесты и единый запуск сайта с API.
Правила, важные для кейса
Task.status принимает только draft или published и не зависит от рейтинга. Можно опубликовать задачу с 0 баллов, если заполнены необходимые основные реквизиты и заказчик подтвердил публикацию.
Охват institution означает задачу для своего учреждения, но не закрывает её от других команд. После публикации они тоже видят задачу и могут откликнуться.
Решение по отклику: pending, selected или rejected. Можно выбрать несколько команд и пересмотреть решение. Другие отклики не отклоняются автоматически. AI и рейтинг не назначают исполнителя.
Как работает решение
- Заказчик вводит название и описание проблемы, сохраняет черновик.
- Помощник предлагает уточняющие вопросы. Заказчик самостоятельно дополняет поля и подтверждает проверенные сведения.
- Backend пересчитывает полноту описания; заказчик отдельно подтверждает публикацию.
- Задача появляется в каталоге. Команда изучает её и отправляет предложение.
- Заказчик рассматривает отклики и вручную выбирает или отклоняет команды.
- Решение сохраняется через API и отображается в кабинете команды.
Вход: описание образовательной потребности и сведения заказчика.
Результат: опубликованная структурированная задача, предложения команд и сохранённое решение заказчика.
Технологии
| Часть | Используется |
|---|---|
| Интерфейс | JavaScript, Vue 3, Vue Router, Vite, Axios, CSS, иконки @lucide/vue |
| Backend | PHP 8.2+, Laravel 12, Eloquent, JSON REST API |
| Хранение | SQLite, миграции и сидеры Laravel |
| AI | OpenAI Responses API, JSON Schema / Structured Outputs; модель по умолчанию gpt-5.4-mini, настраивается через OPENAI_MODEL |
| Автономный режим | Локальный детерминированный генератор вопросов |
| Тестирование | PHPUnit, Laravel Pint, Vitest, Vue Test Utils, Playwright |
| Запуск и размещение | PowerShell, Docker Compose, PHP/Apache в контейнере, конфигурация Render, Cloudflare Tunnel для текущего показа |
| Разработка | AI-агент Codex использовался для реализации, интеграции, тестов и документации |
NVIDIA API, CUDA и GPU-инференс в текущей реализации не используются. Обучения собственной модели нет.
Архитектура проекта
Браузер: Vue
|
| HTTP JSON /api
v
Laravel: проверка роли и входных данных
|
+-- TaskEditor / TaskScorer --> SQLite: Task, Team, Offer
|
+-- AiQuestions --> OpenAiQuestions --> OpenAI Responses API
\-> MockAiQuestions: автономный режим
В едином запуске Laravel отдаёт собранный frontend, а браузер обращается к API на том же домене. Отдельные адреса frontend/backend и настройка CORS жюри не нужны.
| Путь | Назначение |
|---|---|
frontend/src/views/ | Каталог, редактор, карточка задачи, кабинеты и панель откликов |
frontend/src/lib/api.js | Обращения к backend и обработка ошибок |
backend/routes/api.php | Маршруты JSON API |
backend/routes/web.php | Выдача frontend и поддержка прямых ссылок |
backend/app/Services/ | Рейтинг, публикация и AI-помощник |
backend/resources/prompts/task-questions.txt | Готовый промпт для OpenAI |
backend/database/ | Миграции и синтетические демоданные |
backend/tests/, frontend/e2e/ | Автоматические проверки |
start.ps1, START.cmd | Единый запуск на Windows |
Dockerfile, compose.yaml, render.yaml, deploy/ | Контейнер и конфигурация размещения |
Основные сущности: Task хранит задачу и полноту её описания; Team хранит команду и компетенции; Offer связывает задачу с командой и хранит предложение и решение. Полный состав полей и API описан в контракте.
Установка и запуск
Самый быстрый способ для жюри
Откройте демоверсию в браузере. Установка и регистрация не нужны: роль выбирается через демопрофиль в меню.
Windows: один запуск
Требуются Node.js 22.12+, npm, PHP 8.2+ и Composer 2. PHP-расширения: pdo_sqlite, mbstring, openssl, fileinfo, dom, xml, xmlwriter; curl и zip рекомендуются для установки зависимостей. Для первой установки нужен интернет.
git clone https://github.com/BAITC-Hacks/hack-c8a98f95-1465.git
cd hack-c8a98f95-1465
.\START.cmd
Если проект уже скачан, достаточно дважды нажать START.cmd. При закрытом репозитории для клонирования нужен доступ GitHub.
Скрипт находит PHP в PATH, локальной папке AlemEdu или XAMPP, при необходимости устанавливает зависимости, подготавливает SQLite и демоданные, собирает frontend и запускает один сервер.
Сайт: http://127.0.0.1:8080. Проверка API: http://127.0.0.1:8080/api/health. Оставьте терминал открытым; остановка через Ctrl+C. Обычный повторный запуск не сбрасывает базу.
Если порт занят:
powershell -NoProfile -ExecutionPolicy Bypass -File .\start.ps1 -Port 8085
Для отдельной демонстрационной базы и AI без внешних запросов:
powershell -NoProfile -ExecutionPolicy Bypass -File .\start.ps1 -Demo
Этот режим использует .run/jury.sqlite, не рабочую базу backend.
Linux / macOS
С теми же зависимостями, из корня репозитория:
cd backend
composer install
composer setup
cd ../frontend
npm ci
VITE_API_URL=/api npm run build:unified
cd ../backend
php artisan serve --host=127.0.0.1 --port=8080 --no-reload
Откройте http://127.0.0.1:8080. Режим разработки с Vite описан в frontend/README.md и backend/README.md.
Docker
Подготовлен единый контейнер; отдельно устанавливать PHP, Node.js и Composer не требуется:
docker compose up --build -d
docker compose logs --tail 50 app
Адрес: http://localhost:8080. SQLite и ключ приложения сохраняются в volume alemedu-data. Остановка без удаления данных:
docker compose down
Не используйте down -v для обычной остановки: этот параметр удаляет volume с базой. Контейнерная сборка пока не подтверждена запуском: локально Docker отсутствовал, а GitHub Actions не предоставил runner из-за ограничения аккаунта. Проверены единый Windows-запуск и опубликованная версия.
Подключение настоящего OpenAI
Не требуется для запуска демо. Из backend/:
php artisan ai:configure
php artisan ai:check
На Windows без PHP в PATH используйте & C:\xampp\php\php.exe вместо php.
Первая команда запрашивает ключ скрыто и сохраняет его в локальный backend/.env. Вторая отправляет один платный запрос с синтетическим описанием. После настройки перезапустите backend.
Режимы: auto выбирает OpenAI при наличии ключа, иначе демо; openai требует рабочий API; mock не обращается к внешним сервисам. При ошибке OpenAI ответ не подменяется заглушкой. Полная настройка и промпт.
Не публикуйте API-ключи в GitHub и не помещайте их в VITE_*. Файлы .env исключены из Git и Docker-контекста. Для публичного доступа с платным ключом сначала нужна настоящая защита доступа.
Как проверить решение
Полный сценарий для жюри
- Откройте сайт, выберите «Демо-заказчик 1», затем «Создать задачу».
- Название: «Разговорная практика первокурсников». Организация: оставить из профиля. Регион: Алматы. Тема: Языки. Охват: Одно учреждение.
- Описание: «Первокурсникам не хватает регулярной разговорной практики английского. Нужен простой тренажёр для занятий в парах».
- Сохраните черновик. Убедитесь, что появились уточняющие вопросы и отметка текущего AI-режима. Остальные содержательные поля можно оставить пустыми.
- Подтвердите публикацию. Ожидаемый результат: задача доступна в каталоге с низким рейтингом, который не блокирует публикацию.
- Переключитесь на Qadam из другого учреждения. Откройте задачу и отправьте отклик: идея «Веб-тренажёр парных диалогов», план «Уточнение сценария, прототип, тестирование», сроки «Три недели».
- Вернитесь к заказчику: «Мой кабинет» → отклики новой задачи → «Выбрать». Обновите страницу: решение должно сохраниться.
- Переключитесь на Qadam и откройте кабинет команды: ожидаемый статус отклика «Команда выбрана».
- Для проверки отклонения откройте от заказчика задачу «Расписание консультаций» (
/tasks/2/offers), отклоните один из готовых откликов и обновите страницу.
Так проверяется полный путь: входные данные → публикация → доступ команды другого учреждения → отклик → решение заказчика. Сценарий показа на 4:45.
Автоматические проверки
Из backend/:
php artisan test
php vendor/bin/pint --test
composer validate --strict
Из frontend/:
npm test
npm run build
npx playwright install chromium
npm run test:e2e
На Windows допустимы npm.cmd и npx.cmd. По умолчанию Playwright запускает отдельный API на 18082, сайт на 5174 и временную SQLite, не меняя рабочую базу. Нужны установленные backend-зависимости и PHP; XAMPP находится автоматически, другой путь задаётся через E2E_PHP.
Тесты охватывают рейтинг и публикацию, права демопрофилей, каталог, отклики, решения, ошибки API, AI-контракт и адаптивность. Внешние AI-запросы имитируются: тесты не расходуют OpenAI-квоту. Браузерный отчёт создаётся в frontend/playwright-report/.
Данные и интеграции
Используются синтетические данные, включённые в репозиторий: исходные описания и сидер. Персональных данных реальных студентов в демонаборе нет. Упомянутые в описаниях CSV, планы корпусов и прототипы являются содержанием демонстрационных задач, а не реализованными внешними интеграциями.
На новой базе: 2 заказчика, 5 команд, 5 задач и 5 откликов.
| ID | Задача | Статус | Баллы |
|---|---|---|---|
| 1 | Разговорный английский | draft | 20 |
| 2 | Расписание консультаций | published | 60 |
| 3 | Поиск учебных книг | published | 75 |
| 4 | Обратная связь по занятиям | published | 90 |
| 5 | Навигация по кампусу | published | 100 |
Команды: Steppe Coders, Qadam, Bilim Lab, Orken, Campus Makers. Qadam и Orken относятся к демо-колледжу «Самғау», остальные к демо-университету «Алем».
- OpenAI: необязательная внешняя интеграция для уточняющих вопросов. Поле
contactне отправляется модели; произвольный текст остальных полей автоматически не обезличивается. - Cloudflare Tunnel: HTTPS-доступ к текущей демоверсии.
- GitHub: исходный код и конфигурации проверок.
- Render: подготовлена конфигурация размещения, но постоянный сервис не развёрнут.
- NVIDIA: интеграция в коде отсутствует.
Дополнительная документация: API и модели, REST-примеры, AI, размещение.
Известные ограничения
- Демопрофили заменяют регистрацию и реальную аутентификацию. Проверка роли по демонстрационным заголовкам не является защитой для production.
- На публичном показе и в Docker по умолчанию
AI_PROVIDER=mock. Настоящее подключение требует ключа, доступа к модели, сети и квоты API; реальный ответ OpenAI не подтверждён текущими автоматическими тестами. - AI предлагает вопросы, а не готовое решение образовательной задачи. Он не редактирует карточку автоматически, не выставляет рейтинг и не выбирает команду.
- Нет интеграции с информационными системами учреждений, загрузки файлов, чата, почтовых уведомлений и платежей.
- SQLite и демонстрационный сервер не проверялись под промышленной нагрузкой. Демоданные общие: действия посетителей видны другим участникам показа.
- Временная публичная ссылка перестанет работать при остановке сервера/туннеля или отключении компьютера.
- Docker/Render-конфигурация подготовлена, но успешная контейнерная сборка не подтверждена. Наличие workflow в GitHub не означает, что облачные проверки прошли.
Развёрнутая версия
https://minute-wifi-reserves-throughout.trycloudflare.com
Это текущий доступный показ через временный туннель, а не постоянный независимый хостинг. Локальный запасной адрес после START.cmd: http://127.0.0.1:8080.
Для отдельного облачного сервиса подготовлена кнопка Deploy to Render. Нужны аккаунт, доступ Render к репозиторию и подтверждение деплоя. Конфигурация бесплатного демосервиса не включает постоянный диск; не рассчитывайте на сохранность пользовательских изменений SQLite после перезапуска. Подробности в инструкции размещения.
Авторы коммитов
История коммитов
- 2026-09-23 17:51Document HackAlem AI submission criteria for juryCodex
- 2026-09-23 17:42Simplify jury launch and add single-container deploymentCodex
- 2026-09-23 17:32Integrate OpenAI task assistant with secure setup and testsCodex
- 2026-09-23 17:13Complete customer decisions and integrated demo workflowCodex
- 2026-09-23 16:28Redesign frontend with guided SaaS experience for customers and teamsYerassyl88
- 2026-09-23 16:05Add Vue frontend with API-connected task and team workflowsYerassyl88
- 2026-09-23 15:19Document Windows startup with process-scoped script executionSabokanms
- 2026-09-23 15:17Implement AlemEdu Laravel backend API and demo workflowSabokanms
Структура репозитория (150 файлов)
.dockerignore .gitattributes .github/workflows/backend.yml .github/workflows/deploy-check.yml .github/workflows/frontend.yml .gitignore Dockerfile README.md START.cmd backend/.editorconfig backend/.env.example backend/.gitattributes backend/.gitignore backend/README.md backend/app/Console/Commands/CheckAi.php backend/app/Console/Commands/ConfigureAi.php backend/app/Exceptions/AiUnavailable.php backend/app/Http/Controllers/AiController.php backend/app/Http/Controllers/Controller.php backend/app/Http/Controllers/DemoController.php backend/app/Http/Controllers/OfferController.php backend/app/Http/Controllers/TaskController.php backend/app/Http/Middleware/DemoIdentity.php backend/app/Http/Middleware/JsonInput.php backend/app/Http/Requests/TaskWriteRequest.php backend/app/Http/Resources/OfferResource.php backend/app/Http/Resources/TaskResource.php backend/app/Http/Resources/TeamResource.php backend/app/Models/Offer.php backend/app/Models/Task.php backend/app/Models/Team.php backend/app/Providers/AppServiceProvider.php backend/app/Services/AiQuestions.php backend/app/Services/MockAiQuestions.php backend/app/Services/OpenAiQuestions.php backend/app/Services/TaskEditor.php backend/app/Services/TaskScorer.php backend/artisan backend/bootstrap/app.php backend/bootstrap/cache/.gitignore backend/bootstrap/providers.php backend/composer.json backend/composer.lock backend/config/ai.php backend/config/app.php backend/config/auth.php backend/config/cache.php backend/config/cors.php backend/config/database.php backend/config/demo.php backend/config/filesystems.php backend/config/logging.php backend/config/mail.php backend/config/queue.php backend/config/services.php backend/config/session.php backend/database/.gitignore backend/database/migrations/2026_09_23_000001_create_alemedu_tables.php backend/database/seeders/DatabaseSeeder.php backend/database/seeders/DemoSeeder.php backend/database/seeders/data/briefs.json backend/docs/AI.md backend/docs/API.md backend/docs/alemedu.http backend/docs/examples/ai-questions.json backend/docs/examples/decision.json backend/docs/examples/offer-create.json backend/docs/examples/publish.json backend/docs/examples/task-create.json backend/docs/examples/task-response.json backend/docs/examples/task-update.json backend/lang/ru/validation.php backend/phpunit.xml backend/public/.htaccess backend/public/favicon.ico backend/public/index.php backend/public/robots.txt backend/resources/prompts/task-questions.txt backend/routes/api.php backend/routes/web.php backend/scripts/prepare.php backend/scripts/smoke.php backend/start.ps1 backend/storage/app/.gitignore backend/storage/app/private/.gitignore backend/storage/app/public/.gitignore backend/storage/framework/.gitignore backend/storage/framework/cache/.gitignore backend/storage/framework/cache/data/.gitignore backend/storage/framework/sessions/.gitignore backend/storage/framework/testing/.gitignore backend/storage/framework/views/.gitignore backend/storage/logs/.gitignore backend/tests/Feature/ApiTest.php backend/tests/Feature/ConfigureAiTest.php backend/tests/Feature/OpenAiTest.php backend/tests/Feature/SingleServerTest.php backend/tests/TestCase.php backend/tests/Unit/TaskScorerTest.php compose.yaml deploy/apache.conf deploy/container-prepare.php deploy/entrypoint.sh deploy/php.ini deploy/ports.conf docs/DEMO.md docs/DEPLOY.md docs/JURY.md frontend/.env.example frontend/.gitignore frontend/.gitkeep frontend/README.md frontend/e2e/ai.spec.js frontend/e2e/catalogue.spec.js frontend/e2e/decisions.spec.js frontend/e2e/flow.spec.js frontend/e2e/onboarding.spec.js frontend/index.html frontend/package-lock.json frontend/package.json frontend/playwright.config.js frontend/public/favicon.svg frontend/scripts/check-deployment.mjs frontend/scripts/e2e-backend.mjs frontend/src/App.vue frontend/src/components/ApiError.vue frontend/src/components/Icon.vue frontend/src/components/ScorePanel.vue frontend/src/components/TaskCard.vue frontend/src/components/__tests__/ScorePanel.test.js frontend/src/lib/__tests__/api.test.js frontend/src/lib/api.js frontend/src/lib/editorState.js frontend/src/lib/fields.js frontend/src/lib/session.js frontend/src/main.js frontend/src/router.js frontend/src/style.css frontend/src/views/CatalogView.vue frontend/src/views/GuideView.vue frontend/src/views/HomeView.vue frontend/src/views/NotFoundView.vue frontend/src/views/TaskDetailView.vue frontend/src/views/TaskEditorView.vue frontend/src/views/TaskOffersView.vue frontend/src/views/WorkspaceView.vue frontend/src/views/__tests__/TaskOffersView.test.js frontend/vite.config.js render.yaml start.ps1
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.