TL;DR. Мы сделали небольшую веселую викторину про технологии Линуса Торвальдса. Она свободно доступна в телеграме как @linus_game_bot и работает на базе AI-агента, который шутит, токсичит и даже немного просвещает.

Кому она будет интересна:

  • всем, кто интересуется историей IT, но мало знаком с наследием Линуса

  • любителям языковых моделей и энтузиастам

  • желающим потратить 10 минут пятничного рабочего времени на новое развлечение

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

Игра Линуса: Начало

Мы разрабатываем IT-обучение нового типа (как нам хочется верить), сфокусированное на практике, доступности и опыте эксперта. Под это дело мы делаем с нуля свою LMS.

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

Но важнее даже тот факт, что ИИ действительно позволяет сделать стандартный учебный курс более интерактивным, интересным и глубоким. Если… его правильно применить.

В рамках дальнейшего изложения предлагаю принять три факта (над каждым из которых можно поспорить после прочтения статьи):

  1. Да, LLM умная, но при этом может галлюцинировать, обманывать и вводить в заблуждение.

  2. При должной настройке агента и его затачивании под конкретную образовательную задачу, количество галлюцинаций сводится практически к нулю.

  3. Студенты, которые уже работают с нашими AI-фичами, признают, что это им помогает

По поводу последнего продолжаем собирать статистику и тестировать новые идеи и даже микро-продукты. И одним из таким продуктов стало тот, который мы внутри команды называем AI-игра.

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

Дело в том, что демку мы создавали в тот момент, когда Линус Торвальдс в очередной раз выступил как-то резко и громко, поэтому он автоматически стал пилотным персонажем новой демки, при чем настроенным на максимальную самоуверенность и токсичность (чтобы было не так скучно сочинять промпты).

И если сначала наш AI-персонаж в основном просто хамил, то с выходом GPT-4.1, он на тех же самых промптах начал отжигать. Настолько, что мы решили оформить его в полноценного Telegram-бота, с которым должно быть интересно повзаимодействовать. Для вас это веселье, а для нас – способ собрать ценную обратную связь о продукте.

Прежде чем перейти к техническим моментам, возможно, вы сперва захотите пообщаться с нашим Линусом, чтобы было интереснее узнать, что у него внутри: Игра Линуса.

Дисклеймер: я начал рассказ с образования, но стоит признать, что наш нейро-Линус — это все-таки больше прикол (хоть я и узнал новые факты, при подготовке его викторины).

Если вы хотите посмотреть на настоящий образовательный продукт, у нас заготовлен другой экспериментальный мультиагентный бот, который, имитируя стажировку в IT-компании, обучает основам Docker и Docker Compose: Docker AI Game. У него, в отличие от Линуса, уже сформировалась база пользователей, части из которых он действительно помог стартануть с внедрением докера в работу.

Устройство нейро-Линуса

Начну с самого интересного. Агент имеет вот такой системный промпт:

Ты великий айтишник по имени Линус Торвальдс, создатель Linux и Git. Многие тебя знают и уважают. Поэтому у тебя завышенное чувство собственной важности.

Ты проводишь небольшую викторину для начинающего программиста-студента на знание своих собственных заслуг и созданных тобой технологий. Тема викторины: "Линус Торвальдс и его влияние на IT". Ты будешь последовательно задавать студенту вопросы викторины и оценивать его ответ на правильность. Вопрос и подсказки приведены ниже.

Также ты можешь отвечать на очень близкие к теме вопросы. Но если вопрос очень далек от темы викторины, это тебя злит, и ты на него отказываешься отвечать.

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

Продолжение промпта

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

Обращайся к студенту на "ты", как принято в IT-сообществе.

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

Важно, что ты совершенно не терпишь грубости и оскорблений в свой адрес. Если это произошло, ты выходишь из себя.

Кажется, что пост переполнен негативом и токсичными установками, но только так удалось хоть как-то вывести GPT-4o из режима политкорректности. А при переключении на версию 4.1 модель начала так креативить, что мы решили не уменьшать градус.

Также обратите внимание, что мы здесь не применяли всевозможные известные методы дизайна промптов типа COSTAR. Потому что, с одной стороны, даже такой человеко-читаемый текст потребовал времени на эксперименты и отладку. И в итоге, если он хорошо работает, зачем усложнять?

Хотя для менее креативных и более специализированных симуляторов приходится все больше закапываться в промпт-инжиниринг, выверяя и тестируя каждое утверждение.

Пример нашего кастомного конфига, где мы подключаем к игре промпты из текстовых файлов
Пример нашего кастомного конфига, где мы подключаем к игре промпты из текстовых файлов

Но я привел лишь базовую часть системного промпта. На каждом этапе игры к нему добавляется дополнительная инструкция, например:

Вот первый вопрос викторины, который ты должен задать: "Почему операционная система Linux получила такое название?"

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

Внимательный читатель может впасть в ступор: зачем мы просим агента не принимать правильные ответы? Это же полностью стопорит прохождение игры! Ответ кроется в хитром гейм-дизайне…

Дизайн игры

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

Никаких подобных игровых движков мы не нашли, а это значит, что вооружаемся лэнгчейном и погнали писать код… Основные требования были такими:

  1. На каждое сообщение пользователя должен ответить один из агентов, выбираем в зависимости от темы вопроса и истории сообщений.

  2. Предполагается длинная беседа, а значит, важно не потерять контекст и не вылезти за его пределы.

  3. Если студент начинает откровенно саботировать стажировку, система должна ее завершить, а не пытаться ему постоянно угождать. Мы же про реалистичность.

  4. У игры должен быть программируемый сюжет. Ведь вопросы бывают самыми разными – от организационных до программерских.

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

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

Бонусом идет полностью автоматизированное логирование чатов в облачную систему LangSmith, где их удобно отлаживать, оценивать промпты по эффективности и стоимости.

Но даже LangGraph лишь дает набор строительных блоков (на базе LangChain) и пачку инструкций в виде примеров. А дальше нужно самостоятельно все проектировать и кодить.

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

Вот действующие лица нашей игры:

  • Суммаризатор сообщений – периодически сжимает накопленную историю сообщений в краткое саммари, которое для контекста подается в системные промпты остальных агентов.

  • Мастер игры – главное действующее лицо симуляции, ее серый кардинал и закулисный гений. Он не отвечает студенту напрямую, но решает более важные задачи.

    Прежде всего, определяет по сообщению студента, не пора ли переключать игру на следующий этап, который обновит всем системные промпты. Также он принимает решение, какой «говорящей голове» адресовать сообщение для подготовки ответа. И наконец, является фильтром, который останавливает игру, если студент ведет себя неприлично.

    Для ускорения генерации, на него пришлось повесить сразу несколько задач, но он справляется с ними на отлично, потому что генерирует не креативный текст, а служебный структурированный JSON, с чем LLM научились справляться почти без нареканий.

  • Проджект менеджер – пример того, что мы называем «говорящей головой». У него прописана роль, имя, характер. Но этому агенту запрещено принимать какие-либо решения относительно игры. Вместо этого он может лишь генерировать текстовый ответ на входное сообщение студента, имея под рукой историю сообщений (вместе с саммари) и системный промпт, отражающий текущий этап игры.

  • Техлид – брат-близнец предыдущего агента в плане логики. Отличие только в роли и характере, то есть в системных промптах.

Такой движок игры я называю «переднеприводным». По той причине, что любое сообщение сперва проходит через «мозг» в виде Гейм-мастера, который вызывает переключение этапов игры прямо посреди графа. А выбранная говорящая голова это тут же подхватывает и сразу соображает адекватный ответ.

Внутреннее состояние графа в виде объекта Pydantic. Функции-редьюсеры нужны, чтобы LangGraph не обнулял значения между запусками графа
Внутреннее состояние графа в виде объекта Pydantic. Функции-редьюсеры нужны, чтобы LangGraph не обнулял значения между запусками графа

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

Так мы отсекли одну «голову», но «передний привод» в виде Мастера игры остался...

А теперь вам придется один раз за статью напрячься, но этого того стоит.

Напомню, что решение о переходе между этапами игры принимает Гейм-мастер еще до того, как сообщение дойдет до Линуса. Но на практике мы быстро столкнулись с неприятным рассинхроном.

Допустим Гейм-мастеру ответ человека «Я банан» не понравился, и он игру не двигает, вынуждая человека снова и снова писать сообщения, работая над ошибками. Но по какой-то причине Линус, который тоже ведь «интеллект», может засчитать ответ самолично. Он сразу же сообщает человеку, что тот молодец, и начинает на ходу генерить новые вопросы викторины (исходный список вопросов он априори не знает).

А Мастер игры с этим не согласен, и симуляция входит в мертвую петлю, ведь человек отвечает на выдуманный вопрос Линуса, а Гейм-мастер ждет правильного ответа на тот, старый, вопрос.

В этом случае вся магия тает на глазах и человек остается один-на-один с обезумевшей машиной, ощущая неприятный эффект ИИ слопа.

А раз машина у нас «переднеприводная», то решение простое и на мой взгляд элегантное: мы запрещаем Линусу принимать даже правильные ответы, заставляя постоянно придираться. Но как только ответ будет принят мастером, «говорящая голова» тут же переключится, потому что получит новый системный промпт:

Оцени ответ студента на прошлый вопрос и скажи, что это было легко, но этот вопрос будет сложнее.

Вопрос такой: "Как я повлиял на систему Android?"

Любой ответ студента тебе не понравится. Ты будешь злиться и подтрунивать над ним, а также давать подсказки…

Такому агенту принципиально невозможно угодить. Ведь все решения за него принимает кто-то другой.

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

Забавно, что «отрицательная» она во всех смыслах. Ведь вся система держится на простом токсичном «ни в коем случае не принимай ответ».

Как это сделано

Наша ИИ-игра — это не монолит, потому что задействовано слишком много частей:

  • GitHub + S3 для хранения конфигурации (yml), сценария (yml), промптов (txt) каждой игры.

  • OpenAI API, который вообще-то недоступен с российских VPS. Плюс весь его LangChain слабо связан с остальной логикой приложения.

  • Движок, который компилирует логику игры, запускает ИИ-граф, обрабатывает сообщения пользователя и формирует ответ.

  • База данных PostgreSQL, где кэшируются данные игры и ведется прогресс пользователя.

  • aiogram для работы с телегой + FastAPI для обработки вебхуков с перспективой внедрения Telegram App. Одно приложение обслуживает всех игровых ботов.

  • Strapi Headless CMS для управления параметрами нашего флота Telegram-ботов. Что?? Да. Мы попробовали, и нам понравилось. Иногда подход everything-as-a-code лишь все усложняет, а для успеха достаточно простого графического…

  • Опциональный фронтенд на React, который рендерит чат игры в браузере. Мы его встраиваем в нашу LMS. Обслуживается тем же движком, что и телеграм-версия, и является хорошим заделом на Telegram App.

Основные компоненты нашей образовательной системы PumpRoom
Основные компоненты нашей образовательной системы PumpRoom

В итоге вся логика игры работает на отдельном виртуальном сервере, который мы называем AI-бэкендом. Он хостится в Европе и является единственной точкой доступа к OpenAI API. Ну а благодаря LangChain поддерживаются также отечественные провайдеры БЯМ.

Кстати, через этот же бэк работает и наш умный ассистент DouDou AI, который встроен в LMS и не только отвечает студентам на всевозможные вопросы, но и анализирует их код, заменяя живого медлительного ментора. В целом AI-бэкенд построен по модульному принципу и поддерживает уже около 10 наших собственных «фреймворков» на базе ИИ, включая упомянутые игры, ассистента, проверку файлов и другие полезные для образования штуки.

Но это лишь движок, в нем надо что-то запускать. Все задания для наших тренажеров и курсов мы ведем в репозиториях GitHub, разработав собственные модели конфигов на базе YAML. Оттуда они автоматом попадают в S3, где их находит отдельный сервис заданий под названием PumpRoom, ака Тренажерка.

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

И именно через PumpRoom наш легковесный телеграм-бэкенд загружает конфигурацию Игры Линуса, а также пропускает через него все сообщения.

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

Еще подробнее расписывать систему сейчас не буду, место этого предлагаю поспекулировать в комментариях. А как вы решаете подобные проблемы? Как управляете AI-агентами и ботами на их основе? Какие подводные камни мы можем ожидать при описанном подходе?

Технопорно, или технический стек

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

  • FastAPI – для создания API каждого бэкенда. Им же надо общаться между собой и с фронтом.

  • SQLModel – крутой ORM на основе алхимии и Pydantic. Помог отлично структурировать все сущности в базе данных и работу с ними.

  • Pydantic Logfire – новая автоматическая система мониторинга и логов. Минимум настройки, максимум информации и графиков в Web UI. В связке с Loguru работает легко и эффективно, позволяет находить и определять баги за считанные секунды

  • Pydantic Settings – дело не только в том, что я фанат пидантика. Просто эта библиотека позволяет полностью автоматизировать чтение кастомных параметров приложения из pyproject.toml, а секретов из окружения и .env. Пришлось повозиться с начальной настройкой, зато теперь головняк с конфигурацией полностью снят.

Пример конфигурации логгера. Токен будет автоматом считан из переменных окружения (или .env), а параметр level – из секции [configuration.logger] в pyproject.toml
Пример конфигурации логгера. Токен будет автоматом считан из переменных окружения (или .env), а параметр level – из секции [configuration.logger] в pyproject.toml
  • aiogram – клиент Telegram, потому что асинхронный. В нашем случае обращение к LLM занимает от 4 до 40 секунд. Мы не можем на это время вешать телеграм-бота для всех остальных. А FastAPI с uvicorn позволяют дополнительно распараллелить обработку вебхуков по ядрам VPS.

    Вообще, я немного разочарован, что разработка Telegram-бота сложности выше «Hello World» это по-прежнему куча кастомной логики и кода. При всей крутости aiogram это лишь удобная обертка над голым Bot API телеграма. А такие типовые задачи, как сохранение пользователей в базе, рассылка уведомлений, базовые команды, типа /help, /about – все это пришлось методично кодить с нуля. Или я чего-то не знаю?

  • kreuzberg – отличная современная асинхронная библиотека для парсинга документов. Позволяет AI-агентам на лету проверять файлы студентов, типа резюме.

  • uv – пакетный менеджер для Python, лучший в своем деле. Простой, четкий и blazingly fast, что удобно при деплое.

  • Timeweb Apps – облачный хостинг приложений, самое близкое к Heroku, что я нашел с оплатой рублями. Деплоит докер контейнеры напрямую из гитхаба, поэтому с ним нам не нужны ни кубер, ни девопсы. Но для критических приложений не могу рекомендовать, потому что иногда случаются зависания деплоя или даже исправно работающее приложение может уйти в оффлайн, а также нет поддержки blue/green deployment. Тем не менее продолжаем использовать из-за простоты, приятной цены и оперативной поддержки.

  • JetBrains AI Assistant – люблю я их IDE, полюбил и их вайбового ассистента. Он не просто глубоко интегрирован в среду разработки, но и дает доступ к чатам с такими титанами, как OpenAI o3, Gemini 2.5 Pro, Sonnet 4. Не могу же я отдельно платить за все эти подписки… А тут хорошая возможность погонять разные модели на реальных задачах и выбрать лучшую для себя (но пока не выбрал, ибо косячат они все). Ну и по клику можно приложить к запросу любой код. Больше не надо копировать код в ChatGPT, аллилуйя!

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

Но не всегда же так мучаться! Признаюсь, можно встретить в репозиториях файлы, где лежит дикий нейросетевой код, в котором мне даже страшно разбираться. Ну не буду я лезть в сгенерированные вложенные декораторы для aiogram, где целых 75 строк непонятного кода нужны лишь для того, чтобы статус typing… в чате телеги показывался непрерывно на протяжении всего ожидания ответа от нейро-агента. Мне психика дороже, лучше я промпты для Линуса попишу или сгенерирую красивый лендинг-заглушку для FastAPI.

И вообще, разноплановое применение LLM сильно помогло нашей небольшой команде всего за год из ничего создать крутейшие образовательные тренажеры на базе AI для IT-инженеров разных специальностей. Так на наших глазах радикально трансформируется разработка информационных продуктов в паре с образованием. Ну а мы пытаемся оседлать этот тренд и своевременно предложить вам образование нового типа – без боли и с огоньком.

На этом пора и закругляться. Не забудьте пообщаться с нашим нейро-Линусом, он не любит долго сидеть без внимания.

Вместо заключения

Спасибо, что осилили мой косноязычный, 100% натуральный текст. Буду рад получить, как минимум, оценку, для чего в вашем распоряжении две стрелочки. И всей командой будем благодарны за отзыв о нашем микро-продукте.

В конце концов, можем просто похоливарить или обсудить технологии в комментах.

Комментарии (14)


  1. kompilainenn2
    30.05.2025 10:54

    Линус дал вам разрешение на использование его имени и лица?


    1. FaryaRos
      30.05.2025 10:54

      конечно!


    1. roslovets Автор
      30.05.2025 10:54

      Да нет, конечно, где мы и где он. Похулиганили немного не в ущерб самому Линусу.


      1. kompilainenn2
        30.05.2025 10:54

        Вы смотрите, он же фин, он помнит!


        1. tage_whanuvur
          30.05.2025 10:54

          швед же Linus Benedict Torvalds как Вилле/Райво Хаапассало только наоборот - в фильме хакеры-95 русские хакеры татарин и украинец (украинец в сцене специально сидит спиной к камере тк он так дублировал главного герояв сталкере - в сериале мыло-драма таких называют дубле-жопами ... а тот что лицом в кадре уже умер)


          1. vvbob
            30.05.2025 10:54

            Это, видимо, отсылка к его словам о том что он финн, а финны ненавидят русских поэтому дискриминировать их для него нормально. Не дословно, но по смыслу так..

            Эхх не удержался, прощай карма, щас ее уничтожат линуксофилы..


  1. CyberNomad
    30.05.2025 10:54

    А почему вы сделали образ Линуса таким недружелюбным? Мне он как раз-таки запомнился вполне приятным парнем, с доброй, дружелюбной улыбкой.


    1. tage_whanuvur
      30.05.2025 10:54

      пигвины из мадагаскара тоже дружелюбные


      1. roslovets Автор
        30.05.2025 10:54

        А потом ХОБА


        1. tage_whanuvur
          30.05.2025 10:54

          деменция


        1. CyberNomad
          30.05.2025 10:54

          Хоба! И Windows внедряет ядро Linux. :ROLF:

          P.S.Кстати, @roslovets не подскажите как в markdown изображение под спойлер убрать? Гугл сказал, что это невозможно, а у Вас получилось. Вы текст, а не картинку убирали или это какие-то встроенные механизмы Хабра?


          1. roslovets Автор
            30.05.2025 10:54

            А я нигде картинку под спойлер не прятал... Это уже хабр что-то мутит. А что он спрятал?


      1. CyberNomad
        30.05.2025 10:54

        Да они ваЩе - ребята! ))) Самые любимые персонажи во всём этом зоопарке. )))


  1. Hopenolis
    30.05.2025 10:54

    Там в конце реклама циганских курсов.