Методология

Почему QuizPilot не обёртка над ИИ

Превратить неаккуратный экзаменационный документ в корректный тест, это в основном задача не для языковой модели. Вот система, которая это делает, и почему примерно один документ из трёх вообще не обращается к модели.

Команда Pilot AI8 мин чтения

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

Начнём с выбрасывания, потому что именно это упускают. У вызова модели есть жёсткий потолок на то, сколько она может выдать за один раз. Попросите её вытащить все вопросы из банка на 500 вопросов за один проход, и она не откажется, она просто упрётся в потолок и остановится, вернув лишь часть, иногда всего несколько десятков, и молча отбросив остальное. Эта одна огромная генерация ещё и единый долгий вызов, и вы платите за прогон всего документа через модель при каждом запуске. Медленно, дорого и с потерями, всё сразу.

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

Поэтому QuizPilot относится к извлечению сначала как к инженерной задаче и лишь в последнюю очередь как к задаче для модели. Детерминированный код читает текст, разделяет его по границам вопросов, чтобы ни один вопрос не был разрезан пополам, и подаёт модели небольшие пакеты параллельно вместо одного огромного документа. Модель привлекают для единственного, в чём она действительно сильнее парсера, по маленькому кусочку за раз, и не более того.

Что происходит с документом

Каждый документ идёт кратчайшим путём, который даёт корректный результат. Его читают в зависимости от типа файла, проверяют, есть ли в нём уже вопросы, и классифицируют по типу содержимого, потому что лист по физике требует иных правил форматирования, чем тест по истории.

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

  1. 1

    Чтение файла

    Отдельные извлекатели для PDF, изображений, DOCX, XLSX и PPTX.

  2. 2

    Проверка на вопросы

    Определить, есть ли в документе уже вопросы, и оценить их количество.

  3. 3

    Определение типа содержимого

    Математика и физика форматируются иначе, чем обычный текст, поэтому правила подстраиваются.

  4. 4

    Каскад детерминированных парсеров

    без ИИ

    Одиннадцать форматных парсеров пробуют по очереди. Побеждает первое чистое совпадение, без обращения к модели.

  5. 5

    Разбор структуры, одно решение

    ИИ, ограниченно

    Код извлекает вопросы и варианты. Модель лишь выбирает, какой вариант верный.

  6. 6

    Пакетное извлечение

    ИИ, ограниченно

    Только когда не подошёл ни один парсер. Документ разделяется по границам вопросов и читается параллельно.

  7. 7

    Резерв на зрении

    ИИ, ограниченно

    Отсканированные или искажённые страницы отрисовываются и читаются моделью зрения.

  8. 8

    Проверка, дедупликация, перемешивание, сохранение

    Каждый вопрос проверяется, близкие дубликаты удаляются, а позиции ответов перемешиваются.

Документ идёт кратчайшим путём к корректному результату. Детерминированный каскад решает большинство из них без обращения к модели. Этапы ниже, это запасные варианты, и каждый сужает то, что модели позволено решать.

Одна ограниченная задача для модели

Именно это слово обёртка передаёт неверно. У модели в QuizPilot маленькая, чётко ограниченная задача. Она вычитывает варианты из фрагмента текста, а на этапе разбора структуры делает лишь одно: выбирает, какой вариант верный. Она не решает, где заканчивается один вопрос и начинается следующий, какие ответы дублируются и достаточно ли результат хорош, чтобы его отдать. Всем этим владеет детерминированный код, вместе с извлечением из файла, распознаванием, сегментацией, проверкой, дедупликацией, перемешиванием ответов, кэшированием и метриками.

Результат измерим. Примерно один загруженный файл из трёх превращается в тест вообще без обращения к модели извлечения, разобранный от начала до конца детерминированным каскадом. Для остальных модель, это один ограниченный шаг внутри конвейера, который проверяет её работу, а не сам конвейер.

Когда модель нужна, основной извлекатель, это Gemini 2.5 Flash-Lite, с автоматическим переключением на второго провайдера, если он перегружен или отказывает, и отдельная модель зрения для отсканированных страниц. Интересно здесь не то, какую модель мы вызываем. Интересно, как мало мы у неё просим. Меньшая задача дешевле, быстрее и оставляет меньше места для ошибки.

~1 из 3загруженных файлов становятся тестом без единого обращения к модели извлечения

Почему это действительно сложно

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

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

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

Неправильный ответ хуже, чем его отсутствие

Это одно правило объясняет весь слой проверки. Прежде чем тест будет отдан, проверяется каждый вопрос. У него должны быть настоящие варианты, не заглушки и не пустые. Варианты должны быть уникальны. Индекс правильного ответа должен указывать на существующий вариант, с автоматической поправкой на частый случай, когда модель считает с единицы вместо нуля. Вопросы со слишком малым числом вариантов или с разбором структуры, в котором модель не уверена, отбрасываются, а не угадываются.

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

Чтобы дойти до этого, потребовалась работа, которой не видно на демонстрации. Разделитель, идущий от границ и уважающий, где вопросы действительно начинаются, сократил разрывы посреди вопроса на 18 процентов и уменьшил число обращений к модели на 13 процентов. Обучение его обрабатывать склеенные и пронумерованные решёткой вопросы сократило эти разрывы ещё на 33 процента.

+335документов+5.4 пункта покрытия
+141документов+1.7 пункта покрытия
Каждый проход цикла по корпусу переводит больше форматов документов на детерминированный путь без ИИ. Два недавних релиза добавили 335 и 141 документ покрытия.

Покрытие, которое накапливается

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

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

Преимущество, это сама система

Ничто из этого не значит, что QuizPilot избегает ИИ. Он использует его, осознанно и узко, для решений, в которых модель сильна, и детерминированный код делает всё вокруг и проверяет результат. Честное утверждение не в том, что результат идеален. Оно в том, что ответы на детерминированном пути привязаны к метке в исходнике, а не выведены, а путь с моделью ограничен и проверен, а не принят на веру.

Вместе хирургически точное применение ИИ, региональные форматы и процесс, который накапливается, скопировать куда труднее, чем любой отдельный вызов модели. В этом и разница между обёрткой и системой. Одна отдаёт то, что сказала модель. Другая спроектирована быть правой.

Примечания

  1. Цифра один из трёх взвешена по трафику и измерена по производственным метрикам извлечения за недавний период. Она считает реальные загрузки, разобранные без обращения к модели извлечения, и не является лабораторным эталоном.
  2. Основное извлечение работает на Gemini 2.5 Flash-Lite, с автоматическим переключением на второго провайдера, и отдельной моделью зрения для отсканированных страниц. Конкретные правила парсеров, пороги и подсказки модели намеренно оставлены за рамками этого материала.
  3. Цифры покрытия считают форматы документов, переведённые на детерминированный путь, и зафиксированы на момент выпуска каждого изменения.

Иногда присылаем новости

Короткое письмо, когда мы выпускаем что-то достойное вашего внимания: новые продукты, крупные функции и иногда истории из жизни команды. Без лишнего шума.

Мы используем вашу почту только для этих писем. Отписаться можно в любой момент.