Что это за система
Практикум по SQL, где задания придумывает LLM, а правильность ответа решает не она. Автор собирает практику в локальной студии, движок разворачивает десятки вариантов данных и прогоняет по ним эталонное решение. Студент решает задания у себя в Docker и коммитит папку с решениями — CI преподавателя проверяет их тем же кодом.
Три вещи, из которых всё состоит
| Что это | Где живёт | |
|---|---|---|
| Студия автора | FastAPI + SPA на localhost, три шага подготовки практики, вызовы LLM и эфемерный Postgres в контейнере | машина автора |
| Раннер студента | Docker-образ: FastAPI + SPA + Postgres, живая база для экспериментов и чистая для проверок | машина студента, GitLab CI |
| Пак практики | git-каталог: описание базы, задания, эталоны, варианты данных, проверки, оформление | репозиторий с паками |
Общего сервера нет. Пак — это папка в git, и она же контракт: студия только пишет её, раннер только читает. Обе стороны зависят от одной библиотеки packcore, поэтому «у меня проверка проходит, а в CI нет» не бывает по построению.
Почему LLM не проверяет ответы
Языковая модель отвечает за формулировки и за эталонное решение — за то, где человек всё равно проверит глазами. Всё, что дальше, детерминировано:
- Данные генерирует движок по спеке и seed'у, а не модель: один и тот же seed даёт один и тот же набор строк на любой машине.
- Ожидаемый результат каждого варианта получается прогоном эталонного решения, а не пересказом.
- Результаты нормализуются перед сравнением: порядок строк, точность чисел, регистр имён колонок,
NULL— всё канонизируется, чтобы40.00и40не считались разными ответами.
Из-за этого «правильно» значит одно и то же у студента, у автора и в CI.
Почему вариантов данных десятки
Задание, проверенное на одном наборе строк, проверено плохо: запрос без WHERE пройдёт, если в таблице и так нет лишних строк. Поэтому спека данных объявляет классы строк (активна кофейня или нет, есть регион у партии или NULL), а движок строит из них варианты — систематические крайности плюс случайные комбинации квот.
Три варианта открыты студенту как «Примеры данных». Остальные скрыты, и скрытый вариант раскрывается ровно тогда, когда решение на нём упало — чтобы разобраться было можно, а подобрать ответ под данные нельзя.