Sana
Маркетплейс бизнес-задач для студентов с регистрацией и ролями.
О проекте
Команда: BATTERY
Кейс HackAlem.ai: Образование — AI Sana
Стадия: Рабочий MVP
Задача кейса: Challenge Hub: превратить задачу бизнеса в задание для студенческих команд
Суть
Маркетплейс бизнес-задач для студентов с регистрацией и ролями. Бизнес получает от LLM уточняющие вопросы и карточку задачи, видит детерминированную оценку готовности 0–100 и публикует задачу. Студенческие команды откликаются, а бизнес вручную принимает одну команду.
Как устроено
Сервер на стандартной библиотеке Python (http.server, sqlite3, urllib) раздаёт статику и API. generateQuestions и generateTaskCard вызывают OpenAI Responses API (gpt-4o-mini) и нормализуют ответ, неизвестные факты остаются пустыми. evaluateTaskCard начисляет баллы по весам: контекст 20, данные 20, результат 15, критерии 15, ограничения 10, пользователи 10, контакт 10. Есть уровни draft/working/ready/priority. В режиме offline используются 5 фиксированных вопросов без обращения к AI.
Ключевые решения
- OpenAI Responses API
- deterministic weighted readiness scoring
- PBKDF2-HMAC-SHA256 password hashing
- CSRF/Origin checks
- offline/online/auto AI modes
- SQLite migrations
Особенности
Ноль сторонних зависимостей и при этом полноценная авторизация: солёные хеши PBKDF2 с 600 000 итераций, HttpOnly-сессии, CSRF, миграции существующей БД.
Стек
Python · SQLite · HTML · CSS · JavaScript · unittest
Модели
gpt-4o-mini
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-43d89dff-battery.
README
README.mdSana — бизнес-задачи для студенческих команд
Sana — MVP для кейса AI Sana: геймификация подготовки практических бизнес-задач. Платформа помогает представителю бизнеса превратить сырое описание проблемы в понятную карточку, а студентам — найти задачу и предложить способ её решения.
Бизнесу часто трудно сформулировать ожидаемый результат, доступные данные и критерии успеха. Студентам сложно оценить такой запрос и начать работу. Sana задаёт уточняющие вопросы, структурирует ответы и показывает, чего ещё не хватает в постановке.
Баллы получает готовность задачи к работе. Чем полнее карточка, тем выше её оценка и позиция в каталоге. Команду всегда выбирает представитель бизнеса вручную.
Быстрый доступ для жюри
Локальная версия после запуска: http://127.0.0.1:8000/. Нажмите Sign in и используйте один из демо-аккаунтов.
| Роль | Профиль | Пароль | |
|---|---|---|---|
| Студент 1 | Orbit Team | [email protected] | 8iuyHVIQp8S7d01Jx-yJk75y |
| Студент 2 | Nova Team | [email protected] | 7-KKiO2p8DgKMFq-HaULZ_eC |
| Бизнес | Sana Demo Business | [email protected] | Qwqp42cT9g0X-v-om3A1WQRJ |
Это открытые демонстрационные учётные записи. Каждый студент имеет личный аккаунт и отдельный связанный профиль команды. Для переключения нажмите My account → Sign out, затем войдите под другой учётной записью. Вкладки одного браузера используют общую сессию; для одновременной проверки разных ролей используйте разные профили браузера.
Аккаунты уже созданы в локальной базе проекта. База SQLite не хранится в Git, поэтому в новой копии репозитория сначала выполните команду подготовки демо-аккаунтов из раздела установки. Она создаёт только аккаунты и профили, без задач и заявок.
Что реализовано
- Регистрация и вход для бизнеса и студентов, выход и восстановление сессии после перезагрузки страницы.
- Разделение доступа: бизнес управляет собственными задачами и заявками на них; студент отправляет заявки от связанной команды и видит их статусы.
- Ввод исходного описания задачи и получение 3–5 уточняющих вопросов.
- Формирование редактируемой карточки из описания, вопросов и ответов.
- Детерминированная оценка готовности от 0 до 100, разбивка баллов и рекомендации по заполнению пробелов.
- Подтверждение карточки бизнесом перед публикацией.
- Открытый каталог с поиском, фильтрами по отрасли, навыкам и готовности, сортировкой и пагинацией.
- Заявки команд: обоснование, подход к решению, предполагаемые сроки и ссылки на портфолио.
- Ручное принятие или отклонение заявки бизнесом. Для одной задачи можно принять только одну команду.
- Сохранение данных в SQLite и миграции существующей базы.
- Адаптивный интерфейс на HTML/CSS/JavaScript без сборки и установки frontend-зависимостей.
Как работает решение
Бизнес входит в аккаунт и описывает проблему
→ получает уточняющие вопросы
→ отвечает минимум на три вопроса
→ получает карточку и оценку готовности
→ редактирует, подтверждает и публикует карточку
→ студенты находят задачу и отправляют заявки
→ бизнес рассматривает заявки и вручную выбирает команду
Карточка содержит контекст, бизнес-потребность, целевых пользователей, навыки, данные, ограничения, ожидаемый результат, критерии успеха и формат взаимодействия с бизнесом. Ответы имеют приоритет над исходным описанием. Промпты требуют сохранять неизвестные факты незаполненными; результат генерации нормализуется перед сохранением и требует проверки человеком.
Как начисляются баллы
Оценку рассчитывает Python-код, без обращения к AI-модели.
| Критерий | Максимум |
|---|---|
| Контекст и бизнес-потребность | 20 |
| Данные и материалы: описание, источники, условия доступа | 20 |
| Ожидаемый результат | 15 |
| Критерии успеха: метрика, целевое значение, способ проверки | 15 |
| Ограничения | 10 |
| Целевые пользователи | 10 |
| Контакт бизнеса и формат взаимодействия | 10 |
| Итого | 100 |
Уровни: draft — 0–39, working — 40–69, ready — 70–89, priority — 90–100. По умолчанию каталог показывает задачи с более высокой оценкой первыми. Низкая оценка сама по себе не запрещает публикацию: требуется подтверждение карточки владельцем.
Баллы отражают заполненность полей, а не доказанную достоверность информации или качество будущего решения.
Технологии
| Компонент | Использование |
|---|---|
| Python 3.11+ | Сервер, бизнес-логика, генерация, оценка и тесты |
| Стандартная библиотека Python | http.server, sqlite3, urllib.request, hashlib, secrets, unittest; сторонние Python-пакеты не требуются |
| HTML, CSS, JavaScript | Интерфейс, маршрутизация по URL-фрагменту #, формы и обращения к API через fetch |
| SQLite | Аккаунты, профили, сессии, задачи и заявки |
| OpenAI Responses API | Генерация уточняющих вопросов и карточки в онлайн-режиме |
gpt-4o-mini | Модель по умолчанию в коде; изменяется переменной окружения OPENAI_MODEL |
| Google Fonts | Шрифт Inter; при недоступности используются системные шрифты |
React, Vue, Django, Flask, ORM и отдельный сборщик в текущем проекте не используются. Собственного обучения моделей и векторной базы нет.
Архитектура проекта
Браузер: frontend/index.html + обычные JS-скрипты
│ HTTP / JSON, cookie сессии, CSRF-заголовок
▼
backend/api.py — единая точка входа: статические файлы и API
├── auth.py — аккаунты, проверка паролей, сессии
└── service.py — права доступа и правила работы с задачами/заявками
├── models/generateQuestions.py — уточняющие вопросы
├── models/generateTaskCard.py — генерация и нормализация карточки
├── models/evaluateTaskCard.py — детерминированная оценка
└── database.py → SQLite
| Путь | Назначение |
|---|---|
frontend/app.js | Каталог, публичные страницы, маршрутизация, общие UI-функции |
frontend/api.js | Обращения к API и состояние текущей сессии в памяти |
frontend/auth.js | Формы регистрации/входа и проверки роли в интерфейсе |
frontend/workspace.js | Создание и публикация задач, отправка и рассмотрение заявок |
frontend/examples.js | Явно обозначенные вымышленные примеры для пустого/недоступного каталога |
backend/api.py | Канонический запуск приложения и HTTP-маршруты |
backend/server.py | Совместимый альтернативный запуск того же приложения |
backend/seed_demo.py | Явная подготовка трёх демо-аккаунтов для жюри |
tests/ | Проверки бизнес-сценариев, API, авторизации, моделей и миграций |
| agents.md | Подробная документация структуры и контрактов для дальнейшей разработки |
Основные API: /api/auth/register, /api/auth/login, /api/auth/session, /api/auth/logout, /api/catalog, /api/tasks, действия /answers, /card, /confirm, /publish, а также /proposals и /api/proposals/{id}/decision. Полная таблица маршрутов находится в agents.md.
Пароли хранятся как солёные хеши PBKDF2-HMAC-SHA256 с 600 000 итераций. Сессии действуют семь дней; cookie имеет HttpOnly и SameSite=Lax, в базе хранится только хеш токена. Изменяющие запросы проверяют Origin и, при действующей сессии, CSRF-токен. Публичный каталог не возвращает исходные черновики и ответы бизнеса.
Установка и запуск
Команды ниже выполняются из корня репозитория в терминале macOS/Linux. Требуется Python 3.11 или новее. Если python3 запускает старую версию, используйте python3.11 вместо него во всех командах.
1. Проверьте Python
python3 --version
Установка через pip или npm не нужна.
2. Подготовьте демо-аккаунты
python3 -m backend.seed_demo
Команда создаёт отсутствующие демо-аккаунты и проверяет вход в существующие. Повторный запуск не сбрасывает пароли и не удаляет данные. Если указанный email уже занят аккаунтом с другим паролем, команда сообщает об ошибке, сохраняя существующий аккаунт.
3. Запустите демонстрацию без API-ключа
MARKETPLACE_AI_MODE=offline python3 -m backend.api
Откройте http://127.0.0.1:8000/. Проверка доступности сервера: http://127.0.0.1:8000/health.
В offline нет обращений к AI API: используются пять фиксированных вопросов на английском и детерминированная сборка карточки. Это режим проверки полного пользовательского сценария; адаптивную генерацию вопросов нужно проверять в онлайн-режиме.
4. Онлайн-режим с AI
Добавьте свой ключ в .env в корне проекта:
OPENAI_API_KEY=ваш_ключ
Затем запустите:
MARKETPLACE_AI_MODE=online python3 -m backend.api
Другую модель можно указать через переменную окружения:
OPENAI_MODEL=gpt-4o-mini MARKETPLACE_AI_MODE=online python3 -m backend.api
.env исключён из Git. Онлайн-режим требует доступа к интернету и действующего ключа. Режим по умолчанию — auto; генерация вопросов в нём также обращается к провайдеру и при отсутствии ключа возвращает ошибку. Для демонстрации без ключа явно выбирайте offline.
Настройки
| Переменная | По умолчанию | Назначение |
|---|---|---|
MARKETPLACE_HOST | 127.0.0.1 | Адрес HTTP-сервера |
MARKETPLACE_PORT | 8000 | Порт |
MARKETPLACE_DB_PATH | data/marketplace.sqlite3 | Путь к базе; одинаковый для подготовки аккаунтов и запуска сервера |
MARKETPLACE_AI_MODE | auto | offline, online или auto |
OPENAI_API_KEY | Не задан | Ключ API; читается из окружения или .env |
OPENAI_MODEL | gpt-4o-mini | Модель для онлайн-генерации; читается из окружения |
MARKETPLACE_COOKIE_SECURE | Не задан | Значение 1 добавляет Secure к cookie при обслуживании через HTTPS |
CORS_ORIGIN | Не задан | Дополнительный явно разрешённый origin; по умолчанию frontend и API работают на одном origin |
База создаётся автоматически. SQLite-файлы и журналы исключены из Git. При занятом порте можно задать MARKETPLACE_PORT=8080 и открыть соответствующий адрес.
Как проверить решение: сценарий для жюри
-
Запустите приложение и войдите как Sana Demo Business по таблице выше.
-
Нажмите Post a task и вставьте пример описания:
Наш интернет-магазин обрабатывает обращения покупателей вручную в общем почтовом ящике. Срочные запросы теряются среди остальных, поэтому клиентам приходится долго ждать ответа. Задача предназначена для сотрудников поддержки.
-
Нажмите Clarify my task. В офлайн-режиме появятся пять фиксированных вопросов. Для воспроизводимой проверки можно использовать следующие вымышленные ответы:
О чём вопрос Пример ответа Данные и доступ Есть CSV-выгрузка из системы поддержки: 2 000 обезличенных обращений с текстом и меткой приоритета. Доступ к папке выдаётся команде в начале проекта. Ожидаемый результат Рабочий прототип, который импортирует CSV и присваивает обращениям низкий, средний или высокий приоритет, плюс инструкция по запуску. Критерии успеха Не менее 85% совпадений с исходными метками на 200 отложенных обращениях, которые не использовались при разработке. Контекст, потребность и пользователи Операторы поддержки вручную разбирают общую очередь. Нужно быстрее находить срочные обращения и уменьшить задержки ответа клиентам. Ограничения и взаимодействие Срок — четыре недели, использовать только обезличенные данные. Контакт — Айда, руководитель поддержки; обратная связь на еженедельном видеозвонке. -
Нажмите Build task card. Проверьте полученную карточку, исправьте неточности, добавьте недостающие поля и нажмите Save & update score. Посмотрите, как меняются баллы и рекомендации.
-
Подтвердите карточку через Confirm task card, затем опубликуйте её. Задача появится в открытом каталоге.
-
Выйдите из бизнес-аккаунта. Войдите как Student One / Orbit Team, откройте опубликованную задачу и отправьте заявку: опишите, почему команда подходит и как будет решать задачу.
-
Повторите отправку от Student Two / Nova Team, предложив другой подход.
-
Снова войдите как бизнес, откройте свою задачу в My workspace и рассмотрите обе заявки. Нажмите Accept team у одной и при желании Decline proposal у другой.
-
Войдите под студентами и проверьте статусы в My proposals. Принятие одной команды не отклоняет другую автоматически.
Все изменения сохраняются в базе. После повторного входа бизнес видит свои задачи, студенты — свои заявки. Оценка после генерации зависит от заполнения карточки; пример не гарантирует заранее заданный балл.
Карточки с пометкой примера в пустом каталоге доступны только для просмотра. Для проверки заявок опубликуйте собственную задачу по сценарию выше.
Автоматические проверки
python3 -B -m unittest discover -s tests -v
Тесты проверяют оценку готовности, полный путь от черновика до принятия команды, права доступа, вход/выход и срок сессии, обработку некорректных ответов модели, защиту HTTP API и миграции SQLite. Тесты используют временные базы и не требуют реального API-ключа.
При установленном Node.js можно дополнительно проверить синтаксис frontend:
node --check frontend/api.js
node --check frontend/auth.js
node --check frontend/examples.js
node --check frontend/workspace.js
node --check frontend/app.js
Данные и интеграции
- Данные бизнеса: текст задачи, ответы на уточняющие вопросы и исправления карточки. Автоматического подключения к CRM или корпоративным источникам нет.
- Данные студентов: профиль команды и текст заявки, сроки, ссылки на портфолио.
- OpenAI Responses API: онлайн-запросы отправляются на
https://api.openai.com/v1/responses; провайдер получает текст, необходимый для генерации вопросов и карточки. В запросах заданоstore: false. - Локальная SQLite: хранит аккаунты, профили, сессии, задачи, оценки и заявки. Пароли и сессионные токены сохраняются в виде хешей.
- Демонстрационные карточки: вымышленные данные из
frontend/examples.js; не записываются в базу и не принимают заявки. - Google Fonts: внешний источник шрифта Inter; отсутствие шрифта не блокирует приложение.
CSV и набор обращений из сценария выше — описание вымышленной бизнес-задачи. Сам датасет не включён в репозиторий. Sana помогает сформулировать задачу; она не обучает классификатор обращений и не измеряет его точность.
Ограничения текущей версии
- Это хакатонный MVP, а не готовая производственная платформа.
- Интерфейс сейчас на английском. Онлайн-промпт вопросов просит сохранить язык исходного описания; отдельного переключателя языка нет. Офлайн-вопросы фиксированы и написаны на английском.
- У студента один связанный профиль команды. Приглашения, совместное членство, редактирование профиля и смена роли не реализованы.
- Нет подтверждения email, восстановления пароля, чата, уведомлений, календаря и загрузки файлов. Портфолио указывается ссылками.
- Опубликованные карточки нельзя редактировать или генерировать заново. Отзыв заявки отдельным действием не реализован.
- AI-результат требует проверки человеком. Наличие поля приносит баллы, но не подтверждает правдивость его содержимого.
- Каталог рассчитан на небольшой объём: сервер фильтрует прочитанные опубликованные записи в Python, frontend дополнительно фильтрует и разбивает загруженный список на страницы.
- Ограничение частоты попыток входа работает внутри одного процесса. Инфраструктура производственного развёртывания и встроенный HTTPS не настроены.
Развёрнутая версия
Публичная deployed-ссылка в текущем репозитории не указана. Проверить решение можно локально по адресу http://127.0.0.1:8000/ после запуска. Это адрес на компьютере, где работает сервер, а не публичный сайт.
Авторы коммитов
История коммитов
- 2026-09-23 17:53Developed ReadMEadletserikbai
- 2026-09-23 17:48almost finaladletserikbai
- 2026-09-23 17:29fixed llm communicationArman Issayev
- 2026-09-23 17:15fixed llm communicationArman Issayev
- 2026-09-23 17:02updated agents.mdadletserikbai
- 2026-09-23 16:55Developed front-endadletserikbai
- 2026-09-23 16:22fixed backendArman Issayev
- 2026-09-23 16:11Developed generateQuestions.pyadletserikbai
Все коммиты (13)
- 2026-09-23 16:06Added backend and updated agents.mdArman Issayev
- 2026-09-23 15:19Created agents.mdArman Issayev
- 2026-09-23 15:15Improved generateTaskCard.pyArman Issayev
- 2026-09-23 14:44developed basic generateTaskCard.pyArman Issayev
- 2026-09-23 14:09created the structureArman Issayev
Структура репозитория (28 файлов)
.gitignore README.md agents.md backend/__init__.py backend/api.py backend/auth.py backend/database.py backend/models/__init__.py backend/models/evaluateTaskCard.py backend/models/generateQuestions.py backend/models/generateTaskCard.py backend/seed_demo.py backend/server.py backend/service.py frontend/api.js frontend/app.js frontend/auth.js frontend/examples.js frontend/favicon.svg frontend/index.html frontend/styles.css frontend/workspace.js tests/fixtures/legacy_schema.sql tests/test_auth.py tests/test_evaluate_task_card.py tests/test_http_api.py tests/test_marketplace_workflow.py tests/test_model_boundaries.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.