AAYMA
RU
Войти

SanaMatch

Платформа, где бизнес в диалоге с помощником превращает короткое описание потребности в карточку задачи с рейтингом готовности, публикует её в…

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

О проекте

Команда: A7
Кейс HackAlem.ai: Образование — AI Sana
Стадия: Рабочий MVP

Задача кейса: Challenge Hub: превратить задачу бизнеса в задание для студенческих команд

Суть

Платформа, где бизнес в диалоге с помощником превращает короткое описание потребности в карточку задачи с рейтингом готовности, публикует её в каталоге, а студенческие команды откликаются; выбор команды и подтверждение этапа делает бизнес вручную.

Как устроено

Один Python-процесс на стандартной библиотеке раздаёт UI на чистом JS и API, данные хранятся в SQLite. Модуль ai/service.py через POST /api/ai/chat принимает черновик, текущую карточку и последние сообщения и возвращает updates с цитатой-основанием, suggestions и missingFields. Без ключа работает локальный помощник на правилах, с ключом — адаптер OpenAI Responses API с fallback при ошибке или невалидном ответе. Каждое изменение карточки пользователь применяет вручную; рейтинг 0–100 считается по формуле критериев; 100 progress points начисляются только за подтверждённый этап.

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

  • rule-based fact extraction fallback
  • evidence-quote validation
  • card versioning against stale AI replies
  • readiness scoring 0-100
  • Playwright e2e check

Особенности

Режимы AI обозначены честно (fallback против llm, «API подключён» против «AI подключён»). Устаревший ответ AI не может перезаписать ручные правки, потому что проверяется версия карточки. Каждый извлечённый факт должен сопровождаться точной цитатой из диалога.

Стек

Python · http.server · SQLite · HTML · CSS · JavaScript · unittest · node:test · Playwright

Модели

OpenAI Responses API


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

README

README.md

SanaMatch

MVP для кейса AI Sana Challenge Hub: бизнес превращает короткое описание в понятную задачу, студенческие команды откликаются, а бизнес вручную выбирает исполнителя.

Какую проблему решаем

Бизнес часто описывает потребность одной фразой: команде непонятны результат, доступные данные и критерии успеха. SanaMatch помогает уточнить эти сведения в диалоге, собрать проверяемую карточку и опубликовать её в каталоге. Студенты предлагают решение, а бизнес выбирает команды и подтверждает выполненный этап. Это не автоматическое назначение исполнителей и не обещание качества результата.

Основной путь: черновик → уточнения → подтверждение фактов → карточка с рейтингом → публикация → отклик → ручной выбор → подтверждение этапа.

Технологии

  • Frontend: HTML5, CSS3, обычный JavaScript, Fetch API; без фреймворка, сборки и npm-зависимостей.
  • Backend: Python 3.9+, HTTP-сервер и обработка JSON из стандартной библиотеки; один процесс раздаёт интерфейс и API.
  • Хранение: SQLite через встроенный sqlite3; в запасном статическом режиме — localStorage.
  • Помощник: Python-модуль с локальными правилами и необязательным адаптером OpenAI Responses API. Для проверенного локального сценария ключ, интернет и GPU не нужны; собственную ML-модель не обучали.
  • Проверки: Python unittest, встроенный node:test для UI-логики; сквозной сценарий дополнительно проверен в настоящем браузере через Playwright.

Запуск полной версии

Нужен Python 3.9+ и современный браузер; Git нужен только для клонирования. Для приложения не нужны npm, pip, Docker или сторонние Python-библиотеки. API-ключ и файл .env для первого запуска не требуются.

В новом каталоге скачайте код и запустите сервер:

git clone https://github.com/BAITC-Hacks/hack-17a0e36f-a7.git
cd hack-17a0e36f-a7
python3 --version
python3 server/main.py --port 4174

Если репозиторий уже клонирован или скачан ZIP-архивом, откройте его корневую папку и выполните только последнюю команду. Для приватного репозитория нужен доступ GitHub, предоставленный организаторами.

Откройте http://localhost:4174. В шапке должно быть «API подключён». Один сервер раздаёт сайт и API; задачи и отклики сохраняются в SQLite. При первом запуске автоматически создаются синтетические задачи, команды и отклики.

Быстрая диагностика: http://localhost:4174/api/health должен вернуть status: "ok", storage: "sqlite". Без настройки модели aiConfigured: false — это нормальный локальный режим, не ошибка запуска. Терминал оставьте открытым; остановка своего сервера — Ctrl+C.

Если порт занят, используйте python3 server/main.py --port 4175 и откройте http://localhost:4175. Адрес 4173 относится к отдельному статическому демо и не заменяет проверку серверной версии.

По умолчанию база находится в server/data/sanamatch.sqlite3. Путь можно изменить переменной SANAMATCH_DB_PATH. База, ключи и .env исключены из Git. Перезапуск сервера не сбрасывает данные. Кнопка «Новая задача» очищает только текущий черновик, сохраняя опубликованные задачи и отклики.

Сервер по умолчанию доступен только на этом компьютере. Это локальный MVP без авторизации, не готовый к открытому публичному размещению.

Как проверить решение за 5 минут

Сценарий ниже предназначен для свежей локальной копии без настроенного внешнего провайдера. Он создаёт только синтетические записи. В существующем рабочем окружении используйте отдельную базу репетиции по инструкции в DEMO.md, не удаляя сохранённые данные.

  1. Проверьте начальные данные. На главной странице есть каталог и отклики; API подключён. В свежей базе — по 5 задач, команд и откликов.
  2. Начните диалог. Нажмите «Загрузить демо-кейс». Дождитесь первого вопроса и метки «Локальный помощник». Ответьте по очереди: «Нужен прототип классификатора обращений», «Точность не ниже 90% на тестовом наборе», «Данные: 200 обезличенных тестовых обращений с категориями отделов». Проверяем три разных уточнения: результат, критерий успеха, данные.
  3. Подтвердите факты. После каждого ответа нажмите «Применить» у соответствующего поля. До нажатия карточка не должна измениться автоматически. Если другие поля пусты, рейтинг растёт 15 → 30 → 50. На телефоне переключайтесь на вкладку «Карточка».
  4. Заполните оставшиеся поля. Название — «Проверка жюри: маршрутизация обращений»; контекст — «Операторы магазина распределяют обращения вручную»; пользователи — «Операторы поддержки»; ограничения — «Прототип за 2 недели, без персональных данных»; контакт — «[email protected]»; формат — «Еженедельная консультация». Ожидаемый рейтинг — 100/100 с расшифровкой.
  5. Опубликуйте и найдите задачу. Нажмите «Опубликовать задачу», затем «Опубликовать» в подтверждении. В каталоге выберите тему Retail и уровень «Готовая+»: новая карточка остаётся видна. «Подробнее» показывает заполненные поля.
  6. Оставьте отклик. Нажмите «Откликнуться», выберите любую демо-команду. Идея — «Классификатор обращений с проверкой оператором»; план — «Неделя 1: примеры, неделя 2: прототип»; ссылка — https://example.com/prototype. Отправьте предложение: оно должно появиться в разделе решения бизнеса.
  7. Примите решение вручную. Выберите команду: её статус меняется, но баллы пока 0 в свежей базе. Введите «Демо: бизнес проверил выполненный прототип» и нажмите «Подтвердить выполненный этап (+100)». Теперь команда получает 100 points; повторное начисление для этого отклика недоступно. Это синтетическая демонстрация: в реальной работе этап подтверждают после фактической проверки. Можно также принять отклик второй команды на ту же задачу.
  8. Проверьте сохранение. Перезагрузите страницу: задача, отклик, выбор команды, подтверждённый этап и баллы остаются. Чат и неопубликованный черновик не сохраняются — это известное ограничение MVP.

Подробный текст выступления и отдельная база репетиции — DEMO.md. Результаты автоматических и браузерных проверок — docs/integration-qa.md.

Что работает

  • Диалог с помощником и одновременно доступная редактируемая карточка; на телефоне — вкладки «Диалог» / «Карточка».
  • Факты из диалога с цитатой-основанием и отдельно предложения помощника. Каждое изменение нужно применить или отклонить вручную.
  • Защита ручных правок от устаревших AI-ответов, отмена последнего применения, повтор запроса при ошибке.
  • Рейтинг 0–100 с расшифровкой и списком незаполненных критериев.
  • Публикация с подтверждением, каталог с фильтрами и полная карточка «Подробнее».
  • Отклик команды: идея, план, ссылка на прототип. Повторный отклик той же команды на ту же задачу запрещён.
  • Ручной выбор одной, нескольких или ни одной команды; каждый отклик можно выбрать или отклонить.
  • 100 progress points только за выполненный этап, отдельно подтверждённый бизнесом с описанием результата. Сам выбор команды баллов не даёт; повторное подтверждение не увеличивает баллы.
  • Серверная валидация, сохранение в SQLite, ограничения размера запросов и структурированные сообщения об ошибках.

AI: два честно обозначенных режима

ai/service.py содержит серверный диалоговый модуль и адаптер внешней модели. Модуль сам не меняет карточку, рейтинг, публикацию или решения бизнеса.

Раздел 5 официального кейса допускает локальную заглушку при недоступности внешнего API, если показаны промпт, формат входа/выхода и обработка некорректного ответа. Эти материалы есть в ai/service.py, ai/test_service.py и docs/ai-handoff.md. Для воспроизводимой демонстрации API-ключ не обязателен; локальный режим не выдаётся за ответ LLM.

  • Без настройки провайдера: работает локальный помощник на правилах (mode: "fallback"), без внешних запросов и оплаты. Он извлекает простые факты, различает артефакт и критерий успеха и задаёт следующий вопрос. Это не LLM.
  • С настроенным провайдером: модуль пробует внешний API. Реализован адаптер openai через Responses API. Ключ хранится только на сервере. Ошибка, таймаут или невалидный ответ переключают модуль на локальный fallback.

Параметры перечислены в .env.example: AI_PROVIDER, AI_API_KEY, AI_MODEL, AI_BASE_URL, AI_TIMEOUT_SECONDS. Собственные значения можно задать в окружении или в локальном .env, после чего перезапустить сервер. Не публикуйте ключи и не отправляйте их в чат. Для работы без LLM все эти параметры можно оставить пустыми.

Метка «API подключён» означает только доступность бэкенда. Метка «AI подключён» появляется лишь после ответа с mode: "llm"; aiConfigured в health означает наличие настроек, а не проверенную доступность модели. Проверки в репозитории не расходуют API-кредиты. Живой вызов внешней модели в интеграционной проверке не выполнялся.

Рабочий prompt и схема ответа находятся в ai/service.py. Текст пользователя считается данными, а не системными инструкциями. Извлечённые факты проверяются на наличие точной цитаты; это не доказывает истинность исходных сведений.

Контракт диалога

POST /api/ai/chat принимает:

{
  "requestId": "ui-example-1",
  "cardVersion": 0,
  "draft": "Нужно быстрее распределять обращения клиентов.",
  "card": {"result": "", "success": ""},
  "messages": [{"role": "user", "content": "Нужен прототип классификатора."}],
  "language": "ru"
}

Ответ содержит requestId, cardVersion, mode, reply, updates, suggestions, missingFields, issues. В updates каждый элемент имеет field, value, evidence; в suggestions — field, value, reason. Интерфейс проверяет версию и ждёт подтверждения пользователя перед изменением карточки.

Ограничения: черновик до 5000 символов, сообщение до 4000; в API передаются последние 20 сообщений в пределах 24 000 символов и текущая карточка. Старые сообщения остаются видны до перезагрузки, но могут не входить в контекст модели. Поля карточки для AI — до 1200 символов. Поддерживается русский язык.

Формула рейтинга

КритерийБаллы
Контекст и потребность20
Данные и материалы20
Ожидаемый результат15
Критерии успеха15
Ограничения10
Пользователи10
Контакт и формат взаимодействия10

0–39 — черновик; 40–69 — рабочая; 70–89 — готовая; 90–100 — приоритетная. Баллы отражают заполненность, не качество или истинность текста. Сервер вычисляет рейтинг самостоятельно. Для публикации обязательны название, контекст и ожидаемый результат; минимального порога рейтинга нет.

Архитектура

index.html + CSS           интерфейс, мобильные вкладки и диалоги
app.js                    карточка, диалог, подтверждения, каталог, отклики
ui/api-client.js          HTTP API и сообщения об ошибках
ui/demo-adapter.js        изолированный статический демо-режим
server/main.py            HTTP, SQLite, валидация, прокси к AI-модулю
ai/service.py             обработка диалога, LLM-адаптер и локальный fallback

Задачи: GET/POST /api/tasks, GET/PATCH /api/tasks/:id. Команды: GET /api/teams. Отклики: GET/POST /api/responses, PATCH /api/responses/:id. Ошибки имеют вид {"error":{"code":"…","message":"…"}}.

Для ручного выбора отправляется {"status":"selected"}, для отклонения — {"status":"rejected"}. Подтверждение выполненного этапа: {"progressConfirmed":true,"progressNote":"Что проверил бизнес"}. Оно доступно только выбранной команде, требует непустого описания и начисляет баллы один раз. Решения и подтверждения сохраняются в SQLite. Обновление старой базы сохраняет записи и решения, снимает прежнее ограничение одной команды и не считает старый выбор выполненным этапом.

Синтетические данные

  • Пять черновиков разной полноты: data/demo-drafts.json; их можно вставить в конструктор.
  • Пять карточек со всеми полями и вычисляемым рейтингом, пять профилей команд с интересами/навыками/технологиями и пять откликов с идеей, планом, сроком и ссылкой: начальные данные в server/main.py.
  • Статический запасной набор — в ui/demo-adapter.js.

Инструкция подачи и готовое описание проекта — в SUBMISSION.md. Соответствие официальному кейсу и ограничения — в docs/requirements-checklist.md.

Проверки

python3 -m unittest discover -s ai -p 'test_*.py' -v
python3 -m unittest discover -s server/tests -p 'test_*.py' -v

Для дополнительных тестов UI нужен Node.js 20+:

node --test ui/tests/integration.test.cjs
node --check app.js

Python-тесты используют временные базы, локальные порты и подставные ответы модели. UI-тесты проверяют клиентский контракт и переходы состояния в изолированном окружении; они не заменяют реальный браузерный прогон. Сценарий ручной проверки — в DEMO.md.

Последний проверенный результат: 25 AI + 22 Backend + 15 UI = 62 теста, все прошли. Для повторения всех 62 нужен Node.js 20+; для запуска самого приложения он не требуется. Живая внешняя LLM этими тестами не проверяется.

Статический запасной вариант

python3 -m http.server 4173 --bind 127.0.0.1

На http://localhost:4173 без API интерфейс покажет «Локальный демо-режим»: синтетические данные, фиксированные тестовые ответы, хранение только в localStorage этого браузера. Это не полная серверная версия и не подключённая модель. Кнопка сброса восстанавливает только эти демо-данные. Они не переносятся в SQLite автоматически.

Ограничения MVP

  • Нет учётных записей, проверки полномочий бизнеса/команд и готовности к публичному хостингу.
  • Чат, неподтверждённые предложения и неопубликованный черновик находятся в памяти страницы и пропадут после перезагрузки; опубликованные задачи и отклики сохраняются в SQLite.
  • Другой открытый браузер увидит изменения после обновления страницы; live-синхронизации нет.
  • Локальный fallback понимает ограниченный набор формулировок. Ошибки интерпретации возможны; финальные сведения проверяет бизнес.
  • Все начальные данные синтетические. Демонстрационные ссылки не являются реально разработанными прототипами.
  • NVIDIA-адаптер, обучение ML-модели, уведомления и загрузка файлов не реализованы.
Звёзды
⭐ 1
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
15
Авторы
2
Файлы
25
Ветки
1

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

ozharova 13ozharova 2

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

  • 2026-09-24 05:33docs: make README self-contained for jury reviewozharova
  • 2026-09-24 05:30fix: align team progress and submission with official caseozharova
  • 2026-09-24 05:17test: finalize demo readiness and AI boundary checksozharova
  • 2026-09-24 05:01feat: integrate shared backend and conversational task builderozharova
  • 2026-09-24 04:01feat: integrate final AI and UX improvementsozharova
  • 2026-09-24 03:51feat: harden local AI chat workflowozharova
  • 2026-09-24 03:39feat: replace questions with guided AI chatozharova
  • 2026-09-24 03:37feat: improve mobile accessibilityozharova
Все коммиты (15)
  • 2026-09-24 03:37fix: harden AI analysis and response workflowozharova
  • 2026-09-24 03:33feat: add team progress leaderboardozharova
  • 2026-09-24 03:22docs: add final demo walkthroughozharova
  • 2026-09-24 03:22feat: add guided demo and AI transparencyozharova
  • 2026-09-24 03:15feat: build SanaMatch task readiness MVPozharova
  • 2026-09-23 14:48Update READMEozharova
  • 2026-09-23 13:59Add greeting to READMEozharova
Структура репозитория (25 файлов)
.env.example
.gitignore
DEMO.md
README.md
SUBMISSION.md
accessibility.css
ai/service.py
ai/test_service.py
app.js
chatbot.css
data/demo-drafts.json
docs/ai-handoff.md
docs/backend-handoff.md
docs/frontend-handoff.md
docs/integration-qa.md
docs/requirements-checklist.md
enhancements.css
favicon.svg
index.html
server/main.py
server/tests/test_main.py
styles.css
ui/api-client.js
ui/demo-adapter.js
ui/tests/integration.test.cjs

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

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

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