Я навайбкодил систему для производства квизов

Обо мне

Павел Королев

Android Tech Lead · AI Adoption Lead @ QazCode

t.me/pavelkorolevxyz_channel

Павел Королев выступает на BeeTechConf 2024

Этот доклад о пет-проекте из хобби

Это моя площадка для экспериментов с агентами

План

  • Квизы

  • Масштаб

  • Редактор

  • База данных

  • Экспорт

  • Выводы

01

Квизы

Паб-квиз

ПакетУгадай мелодию «Рок»

  1. Раунд 1Разминка
  2. Раунд 2На букву L / Л
  3. Раунд 3Один главный хит + Страны мира
  4. Раунд 4Цвета
  5. Раунд 5Блиц
    1. 01Назовите группу
    2. 02Назовите исполнительницу
    3. 03Назовите исполнителя
    4. 04Назовите группу
    5. 05Назовите исполнителя
    6. 06Назовите группу
    7. 07Назовите исполнительницу
    8. 08Назовите группу
    9. 09Назовите исполнителя
    10. 10Назовите группу
    1. 01Назовите исполнителя
    2. 02Назовите группу
    3. 03Назовите группу
    4. 04Назовите исполнительницу
    5. 05Назовите исполнителя
    6. 06Назовите группу
    7. 07Назовите исполнительницу
    8. 08Назовите группу
    9. 09Назовите исполнителя
    10. 10Назовите группу
  • Один главный хит

    1. 01Назовите исполнительницу
    2. 02Назовите группу
    3. 03Назовите исполнителя
    4. 04Назовите исполнителя
    5. 05Назовите группу

    Страны мира

    1. 06Назовите группу
    2. 07Назовите исполнительницу
    3. 08Назовите исполнителя
    4. 09Назовите группу
    5. 10Назовите исполнителя
    1. 01Назовите группу
    2. 02Назовите исполнителя
    3. 03Назовите группу
    4. 04Назовите исполнительницу
    5. 05Назовите исполнителя
    6. 06Назовите исполнительницу
    7. 07Назовите группу
    8. 08Назовите исполнителя
    9. 09Назовите группу
    10. 10Назовите исполнительницу
    1. 01Назовите исполнительницу
    2. 02Назовите группу
    3. 03Назовите исполнителя
    4. 04Назовите группу
    5. 05Назовите исполнителя
    6. 06Назовите группу
    7. 07Назовите исполнительницу
    8. 08Назовите исполнителя
    9. 09Назовите исполнительницу
    10. 10Назовите группу

Играется в баре, команды обсуждают вопросы ведущего и сдают ответы в конце раунда на бланках

Экран вопроса

Экран ответа

Квизы в Алматы

Расписание квизов Алматы на неделю в Telegram-канале «Квизы Алматы»

~60игр в неделю

Своя игра (SIGame)

Участники играют друг против друга, а отвечает на каждый вопрос тот, кто первый нажал на кнопку

Каждый игрок рано или поздно хочет написать свой пакет

Потому что в чужих всегда что-то не нравится

02

Масштаб

Всё началось с простой задачи

  1. Сделать свой пакет для SIGame

  2. Редактор был только под Windows

  3. Windows у меня не было

  4. Быстро навайбкодить свой редактор

Это было почти год назад

Один пакет вырос в YouTube-канал с квизами

Хронологическая карта Рок-сцены номер 2: заставка, правила, раунды, вопросы, ответы и финал

Видео по сценам

Проект в цифрах

189 503
строк кода с тестами
4 384
коммитов
3
репозитория

Коммиты по месяцам

ноя 354 дек 122 янв 14 фев 34 мар 6 апр 541 май 1 057 июн 821 июл 695 авг 647

Таймлайн

ноядекянвфевмарапрмайиюниюлавгРедакторЭкспорт SIQФормат QZPДесктопЭкспорт HTMLБаза данныхАвтонарезка аудиоГенерация пакетовПроблемы с производительностьюБенчмарки производительностиАгент проверяет данныеЭкспорт видеоИстория пакетовCLIMindsweep отдельноБенчмарки генерацийМетрики использованияОптимизации рендераНаполнение тематиками

Я не прочитал ни одной строчки кода

Я его не понимаю

03

Редактор

Демо редактора

Проблема

Продуктовая задача

Проблема

С чего начать?

Как я начал

01

Описать идею агенту своими словами

02

Попросить расписать требования

03

Почелленджить себя агентом

04

Обсудить реализацию и план

Стек, который предложил агент

  • TypeScript
  • React
  • Electron
  • Zustand
  • yt-dlp
  • ffmpeg
  • Canvas
  • WaveSurfer
  • Bun
  • IndexedDB
  • JSZip
  • dnd-kit
  • shadcn/ui
  • MediaPipe
  • Essentia.js
  • TensorFlow.js
  • Vite
  • Tailwind CSS
  • Vitest
  • Playwright

Проблема

Без гардрейлов агент будет ломать то, что уже работает

Гардрейлы с первого дня

  • Типизация языка

  • Статический анализ

  • Юнит-тесты

  • Минимальное покрытие тестами

  • Поиск мёртвого кода

  • E2E смоук-тесты

Новые гардрейлы появляются всё время жизни проекта

Проблема

Агенты умеют делать только дженерик дизайн

Первая итерация

Первый экран редактора: название пакета, дата, сложность и две кнопки

Конец первого дня

Редактор к концу первого дня: фиолетовая шапка, метаданные карточкой, раскрытая тема с вопросами

Сегодня

Редактор сегодня: тёмная тема, список пакетов слева, раунды колонками с вопросами и медиа

Страница дизайн-системы редактора: ступени поверхностей, цветовые токены, типографика, кнопки, формы, статусы, оверлеи, тулбар

Дизайн-система

Как собрать дизайн

01

Просим несколько вариантов в одной сессии

02

Отсматриваем глазами, отмечаем удачные

03

Просим собрать лучшее из отмеченных

Референсы

Доска Trello «Design Requests Sample»: четыре списка с карточками, метками и обложками
Trello
Linear: навигация слева, список задач цикла по статусам, справа панель Cycle Details с графиком
Linear

Дизайн не бывает хорошим, если он не контекстный

Проблема

Точечные правки размывают архитектуру

Важные границы стоит задать как можно раньше

Границы бывают двух видов

  • Продуктовые

    Редактор должен работать с любыми типами пакетов
  • Технические

    Модули связаны только контрактами

Агент может сам себя удерживать в этих рамках

01

Попросить ревью архитектуры и его же решений

02

Каждое замечание отдельным пунктом

03

Пункты закрывают другие агенты

04

Умная модель анализирует, простая чинит

Модель данных тоже контракт, и её правки держим под контролем

Понятные контракты делают правки изолированными

Проблема

Агент ломает приложение, в котором уже лежат настоящие данные

Бэкап важного лучше завести как можно раньше

Формат пакета

Архив QZP
Пакет
Раунд
Тема
ВопросаудиоОтветаудио · фото
ВопросаудиоОтветаудио · фото
Вопросаудио · фотоОтветаудио · фото
Тема
ВопросаудиоОтветаудио · фото
ВопросаудиоОтветаудио · фото
Вопросаудио · фотоОтветаудио · фото
Раунд
Тема
ВопросаудиоОтветаудио · фото
ВопросаудиоОтветаудио · фото
Вопросаудио · фотоОтветаудио · фото
Тема
ВопросаудиоОтветаудио · фото
ВопросаудиоОтветаудио · фото
Вопросаудио · фотоОтветаудио · фото
Audioотрезки для вопросов и ответов
Imagesфото артистов
Videoвидео вопросов

Догфудинг с агентом начинается с бэкапа

Проблема

Агент не чувствует, что интерфейсом неудобно пользоваться

Любое действие в приложении стоит покрыть аналитикой

Кнопку нажимают часто

  • Полезная

    Сценарий стоит развивать
  • Вынужденная

    Процесс стоит автоматизировать

Агент по метрикам может накидать идей

Проблема

Фичи делать дёшево, и их становится много

Дешёвый код не делает фичу нужной

Проблема

Когда начинаются проблемы, без понимания кода не сделать ничего

Проблемы производительности

01

Драг-н-дроп, ключевая функция в приложении

02

Начал тормозить из-за лишних перерисовок

03

У агента появилась возможность самому замерять производительность

04

Агент итерируется сам, пока не получит результат

Узлов DOM во время перетаскивания

С метриками агент видит, в ту ли сторону движется

Продуктовая задача

Вырезать нужный отрезок трека прямо в редакторе вопроса

Два отрезка одного трека

Продуктовая задача

Находить фрагмент трека для каждого вопроса автоматически

Из чего складывается оценка отрезка

Демо: отрезок трека в редакторе вопроса

Алгоритм предлагает, человек правит при желании

Как любой продукт, редактор состоит из кучи мелочей

  • Перетаскивание всего
  • Аудиоредактор в карточке
  • Автовыбор фрагмента
  • Почему этот фрагмент
  • Поиск и скачивание с YouTube
  • Загрузки в фоне
  • Автосохранение
  • Бэкап всего проекта
  • Валидация перед экспортом
  • Хоткеи
  • Поиск по пакету
  • Дубль вопроса и пакета
  • Цветные метки
  • Замок на пакет
  • Генерация из источника
  • Замена вопроса через генератор
  • Входящие предложения от агента
  • Прогрессивная загрузка
  • Аналитика без личных данных
  • Экспорт в SIGame, HTML и видео

04

База данных

Демо: база артистов и треков

Продуктовая задача

Подбирать артистов и треки для пакета

Источник данных подключается к редактору как плагин

Редактор
Контракт
База и генератор

Стек второй системы тоже предложил агент

  • Python
  • SQLite
  • JavaScript
  • TypeScript
  • HTML
  • CSS
  • Pi
  • argparse
  • http.server
  • urllib
  • Pillow
  • MediaPipe
  • dataclasses
  • concurrent.futures
  • JSON
  • pre-commit
  • pytest
  • Ruff
  • coverage

Продуктовая задача

Заполнить карточки артистов и треков данными из интернета

Как наполняется база

Код собирает факты из пяти сервисов
Агент проверяет
Сомнительно: поиск в интернете
База

Итог

7 332
артиста
313 765
треков

Агент сам стал звеном пайплайна, который сам и написал

Продуктовая задача

Собрать из базы артистов и треков пакет вопросов

Что учитывает генератор

  • Сложность каждого вопроса

  • Баланс сложности внутри пакета

  • Баланс эпох

  • Баланс языков

  • Артисты не повторяются внутри пакета

  • Треки не повторяются между выпусками

  • Ничего заезженного

  • Темы и механики раундов

Темы генератора

  • Разминка
  • Фото
  • Змейка
  • Лесенка
  • Алфавит
  • Страны мира
  • Классический рок
  • Хард-рок
  • Панк-рок
  • Поп-панк
  • Гранж
  • Инди
  • Альтернатива
  • Пост-панк и new wave
  • Эмо
  • Nu-metal
  • Core
  • Фолк и фолк-рок
  • Хип-хоп
  • Трэп
  • Андеграундный хип-хоп
  • Фонк
  • Грайм и дрилл
  • Поп-хиты
  • Инди-поп
  • Синти-поп
  • Дрим-поп
  • K-pop
  • Поп-рок
  • Один главный хит
  • Женский вокал
  • Мужской вокал
  • Соло-исполнители
  • Группы
  • Космос
  • Профессии
  • Два слова
  • Транспорт
  • Погода
  • Цифры
  • Животные
  • Топонимы
  • Цвета
  • Имена
  • Семейные узы
  • Святые и грешники
  • Символы
  • Удвоенные буквы

Генерация пакета

Агент сам проверяет сценарии генерации бенчмарком

Бенчмарк генерации

Копия базы
Серия пакетов подряд
Метрики повторов и сложности
Спорное разбирает агент

Метрики и бенчмарки нужны даже продуктовым хотелкам

Продуктовая задача

Собрать раунд без его добавления в генератор

Демо: агент присылает раунд

Один вход для агента заменяет фичу под каждую идею

База и генератор тоже состоят из мелочей

  • Один артист под разными именами
  • Каверы, ремиксы, концертники
  • Музыка, закрытая на YouTube
  • Треки не повторяются между выпусками
  • Артисты отдыхают между выпусками
  • Память о сыгранных пакетах
  • Сложность на лету
  • Сложность артиста и трека врозь
  • Свежесть без заезженного
  • Баланс языков
  • Баланс эпох
  • Баланс жанров
  • Аудит пакета
  • Разминка первой, блиц последним
  • Змейка, лесенка, буквы, страны
  • Темы по словам в названии
  • Замена одного вопроса
  • Ревьюер в браузере
  • Картинки из двух источников
  • Кэш запросов

05

Экспорт

Три формата

01

SIQ

02

HTML

03

MP4

Продуктовая задача

Из пакета получать готовое видео прямо в редакторе

Демо: рендер видео

Видео собирает программа

ПакетВопросы, ответы, медиа
Таймлайн сценВопрос, ответ, таймер
Кадры на CanvasСлои: контент, контекст, таймер
ffmpegСклейка, футаж, музыка
MP4Обложка и таймкоды

Первое видео

Первое видео

Через месяц

Агенту достаточно ссылки на референс, разберёт он его сам

Продуктовая задача

Поправить один вопрос после публикации без полного рендера

Раньше заново рендерились все элементы кадраТеперь заново рендерятся только раунд и номер

Чем быстрее шаг пайплайна, тем быстрее и человек, и агент

Из чего собрано видео

  • Кадр на Canvas
  • Сборка через ffmpeg
  • Кэш трёх слоёв
  • Отмена рендера
  • Фоновый футаж
  • Фоновая музыка
  • Логотип и шрифты
  • Кроп по лицам
  • Сетка фото ответа
  • Плашки и счётчик
  • Таймер на экране
  • Плавное появление ответа
  • Заставка, правила, финал
  • Видео внутри вопроса
  • Нормализация громкости
  • Обложка для ролика
  • Таймкоды для YouTube
  • Рендер без окна
  • Смоук на двух вопросах
  • Отчёт рендера

06

Выводы

Вся система

База
Генератор
Редактор
Рендер
Видео

Весь пайплайн доступен из командной строки

# база: собрать пакет вопросов$ quiz-data pack generate --profile rock --difficulty 3 --out rock-scene-7.qzp # редактор: аудио с YouTube, фото артистов, рендер видео$ quiz-builder render rock-scene-7.qzp --preset mindsweep --out rock-scene-7.mp4

CLI даёт агенту быстрый цикл проверки, а мне квиз без спойлеров

Как я удерживал систему

  • Делил по ответственности

  • Связывал контрактами

  • Унифицировал одинаковые операции

  • Удалял ненужное

  • Спорные решения проверял бенчмарками

  • Поддерживал только то, чем пользуюсь

Инструменты новые, инженерные практики прежние

Не весь код одинаково важен

Важны модель данных и стыки между крупными частями, остальное на откуп агенту

Одному человеку с агентами процессные практики не нужны

Тикеты, планы и роадмапы появляются вместе с командой

Каждой задаче своя модель

Вёрстка и дизайн
Claude Opus
Основная работа
GPT Sol
Когда уткнулся
Claude Fable
GPT Astra

Скиллы переоценены

Считается, что вайбкодингом большой проект не сделать

Большой проект вайбкодингом сделать можно

И нужно

Пока я единственный пользователь

  • Ломаю совместимость, когда хочу
  • Удаляю фичи за день

Если выпустить его для профессионалов

  • Совместимость и миграции
  • Тестовый канал и откат
  • Релизы и поддержка

Из идеи сделать один пакет выросла целая система, которая делает видеоквизы автоматически

Или почти

Спасибо за внимание