03. Руководство teacher
Аудитория. Автор курсов внутри школы. Пишет исходники, запускает AI-пайплайн, редактирует результат, публикует версии, следит за качеством и адаптирует курс под реальные сложности студентов.
Что делает teacher
- Создаёт черновик курса (
course_drafts). - Запускает генерацию через AI-пайплайн (Harvester → Critic → Publisher).
- Правит сгенерированный контент в UI-редакторе (autosave).
- Добавляет/удаляет блоки 11 типов.
- Генерирует медиа (картинки / аудио / видео).
- Локализует курс на другой язык.
- Публикует новую версию.
- Смотрит аналитику своих курсов.
Доступ
Учётка в dev:teacher@local / change_me_locally (демо-школа).
Фронт: http://127.0.0.1:3500/login.
1. Создать курс
На сегодня у teacher'а два практических способа получить курс, оба через UI-редактор:
1a. Открыть пустой черновик и править руками
- Зайди на
/courses. - В блоке «Открыть / создать черновик» вбей
course_id(латиница/цифры/-), напримерmy-first-course. - Жми «Открыть редактор» → попадёшь на
/courses/my-first-course/edit. - API под капотом:
POST /courses/{course_id}/draft— идемпотентно открывает существующий открытый черновик или создаёт новый. Если такойcourse_idуже опубликован — черновик будет склонирован с последней опубликованной версии. - Дальше правь в редакторе (см. §2 ниже).
1b. Склонировать существующий опубликованный курс
curl -X POST "http://127.0.0.1:55400/courses/<src_course_id>/copy" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"new_course_id":"my-fork","new_title":"Моя правка"}'
Это сразу создаёт опубликованный клон (v1), дальше открываешь его в редакторе.
1c. Сгенерировать курс AI-пайплайном (CourseGenerationWorkflow)
Сейчас нет готовой CLI-обёртки и UI-кнопки для запуска CourseGenerationWorkflow из коробки. Workflow зарегистрирован в packages.workflows.worker, но стартуется либо:
- из теста
tests/test_course_generation_workflow.py(end-to-end с моками LLM), - либо кастомным Python-скриптом через
temporalio.client.Client.start_workflow(...).
Типичные агенты пайплайна (для понимания что происходит): Harvester → DocumentIngestor → EmbeddingComputer → Curator → Architect → Composer → NarrativeKeeper → GlossaryCurator → Critic → Publisher.
Удобный CLI-запуск — в roadmap (Phase 6).
2. Редактор курса
URL: /courses/[id]/edit
Возможности:
- Autosave — любое изменение сохраняется в
course_draftsавтоматически (debounce ~500ms). - Дерево модулей/лекций/блоков слева, редактор блока справа.
- 11 типов блоков (детальнее — ниже):
text— форматированный текст с{{term:id|surface}}для глоссарияquiz_single— один правильный вариантquiz_multi— несколько правильных вариантовflashcard_deck— набор карточек front/backordering— упорядочить элементыmatching— сопоставить парыfill_in_the_blank— заполнить пропускиcode_runner— запуск кода через Judge0 + Monacoimage— сгенерированное/загруженное изображение (Nano Banana)audio— аудио (Gemini TTS / Lyria)embed— встроенное видео (YouTube / Veo)
Для каждого типа есть:
schema.py— Pydantic-модель контента (канон).generator.py— промпт + пост-обработка генерации.validator.py— дополнительные проверки.renderer.tsx— React-компонент для студента.- Редактор в
frontend/app/courses/[id]/edit/blocks/<type>/.
Добавить блок
В редакторе → «+ Добавить блок» → выбрать тип → заполнить поля → autosave.
Удалить блок
Кнопка корзины на блоке. Курс остаётся в course_drafts до публикации.
Критик-баннер
Если Critic при последнем прогоне вернул замечания — на блоке показывается .lms-banner--rework с указанием проблемы. Исправь и попроси пересгенерировать (если блок был AI-generated) либо правь руками.
3. Генерация медиа
Изображения — Gemini Nano Banana (gemini-3.1-flash-image-preview).
Аудио — Gemini TTS (gemini-3.1-flash-tts-preview) / Lyria.
Видео — Veo.
В dev по умолчанию LMS_TEST_MODE=1 → Veo и Lyria заблокированы, Nano Banana — лимит 3 картинки на тест (cost guard, ADR-0013 / manifest §18). Для настоящей генерации:
- в
.env.localпоставьLMS_TEST_MODE=0; - проверь
MAX_DAILY_USD; - запусти генерацию через
/demo/media(UI) или API/media/image,/media/audio,/media/video.
Все сгенерированные артефакты кладутся в MinIO, в media_assets пишется запись с s3_uri, mime, prompt_hash, cost_usd.
4. Локализация
Агент Localizer переводит курс на другой язык с сохранением:
- структуры (
modules/lectures/blocks); - глоссарных вставок
{{term:id|surface}}; - корректного перевода терминов согласно
glossary_entries.
Переводы хранятся в course_translations. На фронте — language switcher.
Запуск: через HTTP-эндпоинты /courses/{id}/translations (POST — создать перевод, GET — список). CLI-обёртки нет.
5. Публикация новой версии
Когда доволен — жми Publish в редакторе. Это:
- Запускает
Criticещё раз (обязательный чек). - Если
APPROVE—Publisherпишет новую строку вpublished_courses(version = MAX+1). - Старая версия остаётся доступна по
/courses/[id]/v/[N].
Если REJECT — редактор показывает список замечаний критика, версия не создаётся. Исправь и опубликуй снова.
6. Адаптивное обучение
Когда студент ошибается на блоке — фронт может нажать «Нужна подсказка?» → идёт запрос на POST /adaptive/supplement. Агент AdaptiveSupplementer на лету генерирует дополнительный блок (текст-пояснение / мини-quiz / flashcard). Результат:
- кэшируется в
adaptive_blocks(UNIQUE по user+src_block); - имеет лимит 5/студент/день (
429 adaptive_daily_cap_reached); - показывается студенту прямо под исходным блоком.
Teacher'у виден суммарный эффект: в /analytics блоки с высоким fail_rate — кандидаты на переработку основы, а не только подсказок.
7. Типичные ошибки teacher'ов
| Проблема | Причина | Решение |
|---|---|---|
| Пайплайн зависает | Gemini API лимит | Проверить CostReport; LMS_TEST_MODE=1 если это dev-проба |
| Критик всё REJECT'ит | Слабые исходники | Добавить больше материалов; проверить что Curator отобрал что надо |
{{term:...}} ломается |
Нет записи в glossary_entries | Запустить GlossaryCurator ещё раз |
| Картинки не генерятся | Тест-режим | LMS_TEST_MODE=0 + достаточный MAX_DAILY_USD |
| Публикация не применяется | Critic вернул REJECT | Читать список замечаний в UI |
Ссылки
- Студенческий опыт: 04-student.md
- API: 07-api-reference.md
- Под капотом:
docs/agents/*,packages/agents/*,packages/block_types/*