программирование

Manchester Baby: что за компьютер

Вчера я писал про Манчестерскую малую экспериментальную машину по прозвищу «Малышка», но не написал, что этот компьютер из себя представлял.

Если бы вы встретили его в какой-то из комнат какого-нибудь заброшенного НИИ, вряд ли поняли бы, что это компьютер: несмотря на свои не впечатляющие сейчас характеристики (память — 32 32-битных слова, производительность — 830 инструкций в секунду), он занимал несколько шкафов и весил одну тонну.

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

Машина запустила первую в мире сохранённую программу примерно в 11:00 утра в понедельник, 21 июня 1948 года. Программа вычисляла наибольший собственный делитель числа 218, перебирая все числа от 218 в обратном порядке.

Программа состояла из семнадцати инструкций и выполнялась около 52 минут, пока не выдала правильный ответ — 131 072. За это время компьютер выполнил около 3,5 миллиона операций.

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

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

Ввод был устроен тоже просто: 32 кнопки, позволяющие выставить 32 бита в текущем слове, кнопки прохода по памяти, «запуск», переключение режима дисплея и так далее.

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

Ряд из восьми высоких металлических шкафов с электронными компонентами, лампами и проводами, установленных на деревянном полу перед красной стеной; видны маркировки R4, M3, C3, J2.
Реплика Манчестерской малой экспериментальной машины

2 комментария

Manchester Baby

Мне кажется, нейросети потенциально могут породить такое явление: зачем искать и скачивать программу, если проще её написать? Когда-то мы копили всё скачанное, потому что качать было долго. Сейчас я не храню ничего, что можно скачать повторно. Вполне возможно, скоро так же будет и с программами.

Я уже начал лениться. Я тут недавно писал про «компьютерную шею» в фильме про Швейка 1957 года, а сегодня прочитал про эмулятор компьютера 1948 года — Манчестерской малой экспериментальной машины. Я о ней никогда не слышал и не то, чтобы это что-то меняло в моём восприятии фильма про Швейка, но стало интересно — что там вообще можно было на ней запрограммировать в 1948 году.

Я знаю только о компьютерах Конрада Цузе того же времени, на этом мои познания заканчиваются, но о его работе никто и не знал — война помешала, а тут что-то более мейнстримовое.

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

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

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

Светящиеся фиолетовые точки на чёрном фоне образуют абстрактный узор с горизонтальными линиями и вертикальными столбцами, напоминающими цифровую сетку или пиксельную графику.
Программа, выводящая слово «BOLK»

1 комментарий

Программирование на одной GPU

Интересная штука встречается очень часто. Мне сложно её принять, хотя я понимаю, почему так произошло. Для людей нейросети слились в одно большое атомарное явление. Ну, знаете, как «учёные»: «Учёные заявили…». Какие учёные? Может, там биолог про математику говорит? Многим неважно, есть ли консенсус среди учёных по этому вопросу и насколько проверены данные, на основании которых «учёные заявили».

Так же и тут. Как будто бы многие считают, что нейросети одинаковые: видел одну — видел все. Разумеется, это не так. Они разные по размеру, а значит, и по способностям. У большинства есть специализация, они обучались на разных данных и обладают разным «опытом». И то, что вы можете развернуть у себя на ноутбуке, в подмётки не годится большинству из того, что есть в «облаках».

Мы недавно провели эксперимент среди нейросетей для программирования, которые можно развернуть на одной Nvidia H100. У неё 96 ГБ видеопамяти, и это сейчас один из самых главных критериев — размер памяти, а не мощность самой карты.

Даже в этом сегменте результаты сильно различаются. Мы попробовали следующие сети:

  1. openai/gpt-oss-120b — четыре бита на параметр
  2. Qwen/Qwen3-Coder-Next-FP8
  3. zai-org/GLM-4.7-Flash
  4. Qwen/Qwen3-Coder-30B-A3B-Instruct
  5. gemma-4-31B-it

Среди этих почти одинаковых по параметрам сетей — выбивается только OSS со своими 120 миллиардами параметров, но в сильно урезанном виде — есть явный и безусловный лидер: Qwen3-Coder-Next-FP8. Про более крупные сети и говорить не приходится: их архитектура и данные для обучения уносят их куда дальше по способностям и аналогам знаний о предмете.

Я веду к тому, что если вы попробовали что-то делать с какой-то нейросеткой и у вас плохой опыт, то дело в вас — вы неправильно подобрали себе исполнителя.

Оставить комментарий

Браузер «Арахна»

Вряд ли на свете много людей, которые в 2026 году добровольно пытаются выйти в интернет из ДОСа. Но меня эта идея почему-то всегда цепляла. Есть в этом что-то очень уютное: современный интернет, гигабитные сети, беспроводной доступ, — и рядом с этим чёрный экран, AUTOEXEC.BAT, CONFIG.SYS и ощущение, что если где-то ошибёшься в одной цифре IRQ, то ничего не взлетит.

Не то чтобы меня прямо сильно тянуло «пользоваться интернетом из ДОСа». Понятно, что практического смысла в этом почти никакого нет. Но как эксперимент — очень интересно. Я давно знал, что для ДОСа существуют браузеры. Наверное, даже не один. Значит, теоретически это всё можно собрать: поставить ДОС, настроить сеть, добыть TCP/IP-стек, запустить какой-нибудь браузер и посмотреть, как это вообще выглядит.

Сложностей, в общем-то, не так уж много. Главная — аккуратно собрать по всему интернету кучу старого софта, разложить его по каталогам и не перепутать, что должно грузиться в CONFIG.SYS, что — в AUTOEXEC.BAT, а что надо запускать руками. Для усидчивого человека это не проблема, но процесс очень характерный: вроде бы ты просто хочешь открыть сайт, а в итоге сидишь и думаешь, какой драйвер мыши занимает меньше базовой памяти.

Я наскоро состряпал виртуалку в 86Box, накатил туда MS-DOS 6.22, добавил драйвер сидирома, мышь, Volkov Commander и начал оживлять сеть. В качестве сетевой карты выбрал эмулируемую NE2000 — это такой классический вариант для подобных экспериментов. В 86Box удобно включить SLiRP, и тогда не надо отдельно городить мосты на хостовой машине: виртуальная ДОС-машина получает сеть как будто через маленький виртуальный роутер.

Дальше понадобились две вещи: пакетный драйвер для NE2000 и mTCP. Пакетный драйвер — это такая прослойка, которая даёт ДОС-программам доступ к сетевой карте. А mTCP уже даёт нормальные утилиты поверх TCP/IP: DHCP, ping и прочие радости цивилизации. Я делал по одной из инструкций, только с поправками под свою конфигурацию.

Софт пришлось собирать из разных мест. Почти всё нашлось на old-dos.ru, туда же сходил за Volkov Commander. Без него в ДОСе быстро становится тоскливо: можно, конечно, всё делать командами, но двухпанельный файловый менеджер сразу возвращает ощущение нормальной жизни. Для мыши поставил CuteMouse v2.1b4 — в первую очередь потому, что он маленький. В ДОСе это всё ещё имеет значение: каждый драйвер отъедает кусок базовой памяти, а её всего 640 КБ, и браузеру потом тоже где-то надо жить.

Отдельный маленький квест — освободить побольше базовой памяти. Может показаться, что 640 КБ — это просто анекдот про Билла Гейтса, но в мире ДОСа это очень важная штука. Поэтому HIMEM.SYS, EMM386 и прочее снова становятся не музейными словами, тут придётся всё настроить как надо.

Я вынес наверх всё, что получилось: драйвер сидирома, MSCDEX, клавиатуру, мышь, сетевой драйвер. В CONFIG.SYS у меня в итоге появились HIMEM.SYS, EMM386, DOS=HIGH,UMB и DEVICEHIGH для части драйверов. В AUTOEXEC.BAT — загрузка SMARTDRV, путь к mTCP, русская кодовая страница, драйвер NE2000, DHCP и CuteMouse. Всё что можно загружается командой LH.

После всех этих манипуляций mem стал показывать уже вполне приличную картину: около 609 КБ свободной базовой памяти и ДОС, живущий в HMA. Раньше с этим так много возились не потому что это было интересно, а потому что иначе программы могли просто не запуститься.

Сеть завелась неожиданно буднично. NE2000 загрузился почти сразу (в первой попытке я указал не совсем верные параметры), mTCP через DHCP получил настройки, после чего стало понятно, что ДОС-машина действительно видит внешний мир.

Самый странный момент — набирать ping в чистом ДОСе. Оно не просто запускается, а реально пингует. Мозг немного сопротивляется.

После этого я поставил браузер «Арахна». И вот тут эксперимент стал совсем прекрасным. Потому что это уже не просто «я настроил сеть». Это настоящий интернет.

Конечно, пользоваться этим всерьёз невозможно — браузер по современным меркам совсем примитивный, поддержки HTTPS нет, но посмотреть было интересно.

Скриншот веб-страницы NeverSSL в браузере Arachne 1.99: объяснение, что сайт использует незашифрованный HTTP для обхода проблем с Wi-Fi, и почему это небезопасно.
Браузер «Arachne» — один из немногих, работающих под ДОС

12 комментариев

Забавные часы: утечка памяти

Обратил внимание, что мои «Забавные часы» иногда как будто вылетают: дважды по утрам я приходил, а на терминале — «Андроид», без часов. Я сразу заподозрил, что моё приложение «течёт»: накапливает ресурсы и не освобождает их, пока система его не прибивает из-за нехватки памяти.

Нейросеть мне на слово не поверила — я использовал ГПТ-5.5. Видимо, она уже начала подозревать, что человека не всегда стоит слушать. Упёрлась — и всё: «Нет, — говорит, — у тебя не утечки, это всё кеши приложения». Никаких моих приказов не слушалась. Пришлось запустить замеры на четыре часа и построить график потребления памяти.

Только после этого она начала разбираться в проблеме. Неожиданно оказалось, что причина — в компоненте работы с камерой фреймворка «Флаттер», на котором построено это приложение. Камера используется для мониторинга освещённости: в моём устройстве нет соответствующего датчика, поэтому приложение переключает фон, определяя уровень света с помощью камеры.

Как мы ни крутили этот модуль, за два дня работы с камерой ресурсы всё равно выедались подчистую. Пришлось заменить компонент на нативный для «Андроида».

График изменения TOTAL PSS (синяя линия) и Native Heap (розовая линия) приложения FancyClock после исправления Camera2 в течение ~4 часов с интервалом 5 минут.
График потребления памяти за четыре часа

Оставить комментарий

Brainfuck: оптимизирующий интепретатор

Удивительно, как некоторые бесполезные идеи иногда накрепко захватывают наш ум. Я тут в качестве примера хотел привести игру «Жизнь» Конвея, но при всей своей кажущейся бесполезности она в своё время сильно продвинула математику.

Меня в своё время захватила идея языка программирования «Брейнфак». Оглядываясь назад, думаю, её тоже нельзя объявить полностью бесполезной: в своё время я немало поломал голову над созданием оптимизирующего интерпретатора для этого языка.

Для начала — про сам язык. Я узнал о нём примерно в 2000 году, когда была мода на так называемые «эзотерические языки» — языки, разработанные в качестве шутки или для исследования какой-нибудь абсурдной идеи. «Брейнфак» как раз из таких: в нём всего восемь инструкций, но при этом это полноценный язык. Нейросеть мне на нём даже написала «Тетрис».

«Брейнфак» оперирует ячейкой в массиве, индекс которой можно сдвигать при помощи конструкций < и >. Кроме того, ячейку можно декрементировать (-), инкрементировать (+), вывести на экран символ, код которой записан в ячейке (.), либо записать код введённого с клавиатуры символа (,).

Кроме того, в «Брейнфаке» можно организовывать циклы при помощи парных инструкций [ и ] неограниченной вложенности. [ проверяет значение текущей ячейки, если там не ноль, выполняет тело цикла. Например, [-] записывает в текущую ячейку ноль, декрементируя значение в цикле.

Так как это единственная управляющая конструкция, циклов в обычной программе на «Брейнфаке» — огромное количество. Например, вот так выглядит минимальный «квайн», программа, которая при запуске выведет саму себя:

->++>+++>+>+>++>>+>+>+++>>+>+>++>+++>+++>+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>+>+
+>>>+++>>>>>+++>+>>>>>>>>>>>>>>>>>>>>>>+++>>>>>>>++>+++>+++>+>>+++>>>+++>+>+++>+
>++>+++>>>+>+>+>+>++>+++>+>+>>+++>>>>>>>+>+>>>+>+>++>+++>+++>+>>+++>+++>+>+++>+>
++>+++>++>>+>+>++>+++>+>+>>+++>>>+++>+>>>++>+++>+++>+>>+++>>>+++>+>+++>+>>+++>>+
++>>+[[>>+[>]+>+[<]<-]>>[>]<+<+++[<]<<+]>>+[>]+++[++++++++++>++[-<++++++++++++++
++>]<.<-<]

Я задумался об оптимизации программ на «Брейнфаке» ещё в начале 2000-х, запрограммировав свои идеи на ДжаваСкрипте.

Первые мысли были вполне очевидными — объединять одинаковые конструкции. Вместо того чтобы последовательно инкрементировать ячейку десять раз, на этапе предпроцессинга можно сразу подсчитать количество «плюсов» и прибавить сколько требуется.

Потом я начал транслировать идиомы Brainfuck напрямую в ДжаваСкрипт, что тоже заметно повысило производительность. Например, конструкцию [-] можно заменить простой записью нуля в текущую ячейку — без выполнения цикла.

Настоящий прорыв случился, когда я понял: так можно оптимизировать не только отдельные идиомы, а вообще все циклы без ввода-вывода, если после выполнения цикла указатель возвращается в ту же ячейку, с которой начал. Например, [->+++++<] превращается во что-то вроде d[i+1] = d[i] * 5; d[i] = 0.

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

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

Проект лежит у меня на «ГитХабе».

1 комментарий

Забавные часы

Купил себе на «Авито» бывший платёжный терминал — на борту «Андроид», так что мысль была запрограммировать себе (при помощи нейросетей, разумеется) какую-нибудь несложную развлекуху, типа «Мира в бутылке», чтобы на моём столе что-нибудь постоянно двигалось.

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

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

Скачал с «Гуглфонтса» 1500 случайных шрифтов, выдрал из них цифры и сварганил приложение на «Флаттере», которое выводит цифры случайным шрифтом и в случайном контрастном цвете. В приложении два фона — светлый и тёмный, выбираются автоматически в зависимости от освещённости, которая измеряется камерой.

Цифровые часы на стойке показывают время 14:52, где цифры «14» белые, а «52» — красные, на тёмном фоне экрана.

Проект выложен у меня на «Гитхабе».

7 комментариев

«Тетрис» на Brainfuck ★

Ну разумеется я вчера не смог уснуть без того, чтобы не посмотреть что ещё мог бы написать ИИ на «Брейнфаке»! Попробовал написать «Тетрис», тем более что у меня были готовые идеи как это сделать. Правда для этого пришлось модифицировать интерпретатор. Свой собственным, разумеется, который я начал писать ещё в 2001-м году, надо бы про него рассказать тоже однажды.

Дело в том, что у «Брейнфака» нет рандомизации и ввод устроен очень просто — есть инструкцию чтения символа и всё. Правда сам язык не определяет подробности чтения символа, поэтому реализации отличаются. В основном авторы интерпретаторов делают буферизированный ввод, дожидаясь нажатия кнопки «Ввод». Правда тут тоже есть нюансы — где-то можно ввести строку, а где-то «Ввод» надо нажимать после введения каждого символа.

Чтобы приступить к «Тетрису» пришлось сделать две модификации.

Во-первых, ввести команду @, которая записывает случайное число в текущую ячейку («Брейнфак» всё сохраняет в ячейках, двигаясь по ней при помощи специальных команд). В таком расширении языка нет ничего необычного — когда он был на волне популярности, ему постоянно придумывали всякие расширения.

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

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

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

Скриншот игры BF TETRIS: цветные блоки заполняют поле, справа — управление (←/→ move, ↑ rotate, ↓ drop, q quit), следующий блок и счётчик линий (lines 4).

Как легко догадаться по скриншотам, нейросеть (я использовал «ГПТ-5.5») отлично справилась с задачей. Но что интересно, чтобы это сделать она реализовала ровно ту идею, про которую я писал в прошлый раз — написала генератор на ПХП, при помощи которого сгенерировала программу на «Брейнфаке». Немудрено — программа получилась монументальной — под сотню мегабайт в первой попытке.

Я даже сделал в своём интерпретаторе поддержку сжатия исходников. Наверное никому раньше не приходило в голову этим заниматься — как правило программы на «Брейнфаке» пишут люди и до таких размеров они их не доводят.

Трансляция такого огромного файла и применение оптимизаций занималось около 15—20 секунд на моём ноутбуке, так что пришлось применить ряд оптимизаций — немного переписать парсер интерпрератора, сделать кеширование и поработать над уменьшением размера кода «Тетриса».

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

Единственное о чём надо рассказать — как регулируется скорость игры. В «Брейнфаке» нет ничего, чтобы создавать паузы заданной длительности, но некоторые программы работают ощутимо долго. Хотя у меня и оптимизирующий интерпретатор, всё оптимизировать он не может. Поэтому мы с нейросетью просто «на глазок» подобрали код, который достаточно плохо оптимизируется и тормозит на моём ноутбуке ровно насколько, чтобы играть было комфортно.

Оставить комментарий

ИИ: Brainfuck

Три года назад я в шутку предлагал программистам переходить на «Брейнфак» — эзотерический язык программирования из восьми конструкций, который плохо давался нейросеткам. Что-то похожее на программу на этом языке они писали, но получался мусор.

Я пропустил момент, когда модели научились на нём писать. Буквально вчера догадался снова попробовать, оказалось — могут! Программу на скриншоте мне «Курсор» написал в режиме «Авто», где выбираются, в основном, слабые модели. Топовые справляются даже с такими заданиями как написать несложный эмулятор командной строки с несколькими основными командами и небольшой файловой системой!

Для человека это уже какой-то запредельный уровень. Если бы я решал эту задачу, я бы написал себе сначала какой-нибудь макроязык с трансляцией в «Брейнфак» и уже на нём написал то, что требуется.

Скриншот терминала с командой Brainfuck, генерирующей ASCII-арт из символов + и -, и подписью «Вот и всё ребята

Две вещи, с которыми модели ещё не справляются — это написание «квайна» (программы, которая выводит сама себя) и оптимизация программ на «Брейнфаке» по размеру. Даже топовые модели наотрез у меня отказываются такое писать. Даже после прямого приказа.

Интересно будет помучить этой задачкой новую модель «Антропика», которая должна появиться летом — я считаю их модели лучшими, хотя их последний «Опус» несколько разочаровал.

Добавлено позднее: справедливости ради насколько простую программу, как на картинке выше, нейросети и сейчас могут написать оптимальнее:

Скриншот терминала с командой Brainfuck, запущенной через PHP, и выводом «Вот и всё ребята» — юмористический пример использования esoteric-языка программирования.

10 комментариев

Коммунистический массив

Я тут в мемах, которые кинули бывшие коллеги, увидел «коммунистическую сортировку» — она каждому присваивает среднее значение, и не смог пройти мимо. Написал «коммунистический массив»:

class CommunistArray extends \ArrayObject
{
    public function __construct(array $array = [])
    {
        parent::__construct(self::createCommunistArray($array));
    }

    public function offsetSet(mixed $key, mixed $value): void
    {
        parent::offsetSet($key, $value);
        $this->redistribute();
    }

    public function offsetUnset(mixed $key): void
    {
        $first = $this->getIterator()->key();

        if ($first !== null) {
            $this[$first] += $this[$key];
            parent::offsetUnset($key);
            $this->redistribute();
        }
    }

    private static function createCommunistArray(array $array): array
    {
        if ($array) {
            $avg = array_sum($array) / sizeof($array);
            return array_fill_keys(array_keys($array), $avg);
        }

        return [];
    }

    private function redistribute(): void
    {
        (void) $this->exchangeArray(self::createCommunistArray((array) $this));
    }
}

Он делает всех равными и перераспределяет блага автоматически:

$comrades = new CommunistArray([0b1, 0o0, 3e1, 0x45]);

print_r($comrades); # 25, 25, 25, 25

$comrades[2] = 4;
print_r($comrades); # 19.75, 19.75, 19.75, 19.75

unset($comrades[0]);
print_r($comrades); # 24.6875, 24.6875, 24.6875

8 комментариев

Мир в бутылке: графика

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

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

нарисуй 10 характерных персонажей-человечков в пиксельном стиле маленького размера. референс в картинке

В качестве референса был приложен первый попавшийся скрин из какой-то бродилки времён ДОСа и, если честно, я не ожидал, что результат мне понравится настолько, что, по сути, определит всех будущих персонажей:

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

Собственно, этот спрайт плюс небольшое текстовое техническое задание, где я поверхностно описал, какими возможностями будут обладать будущие персонажи, я и подал на вход «Опусу 4.7».

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

Травку, камешки, насекомых и игровые предметы мне рисовал уже «Опус». С мелкими предметами он справился хорошо, а с теми, что покрупнее, — хуже. В итоге котёл, костёр, сундук и так далее я снова попросил нарисовать «ЧатГПТ». На мой взгляд, он их нарисовал слишком детализированно:

Пиксельные иконки: кувшин, закрытый и открытый сундук, надгробие, костёр, котёл, мишень, чучело и пень на белом фоне.

Поскольку их надо было сделать сильно меньше, «Опус» перерисовал новую версию «по мотивам». В итоге качество меня устроило. Текущий вариант лучше, чем было раньше, но выглядит менее натурально, чем то, что нарисовал «ЧатГПТ». В силу того, что я придерживаюсь ретро-стиля, как будто бы нужный баланс достигнут.

Гидру я рисовал в «Нанобанане 2», приложив как референс картинки персонажей. Текущий результат получился примерно с четвёртой или пятой попытки и, если честно, не кажется мне идеальным, но мне больше хотелось проектировать мир, а не возиться с графикой настолько долго.

Претензия всё та же: по сравнению с персонажами гидра чересчур детализирована.

Пиксельные спрайты гидры с тремя и пятью головами, а также двух вариантов пещеры гидры: многоуровневой с одним входом и одноуровневой с тремя входами.

Что делать дальше я пока не решил. Либо доделаю этот мир — там осталась ещё одна нереализованная задумка, либо перейду на другую платформу (кое-что заказал на «Авито») и спроектирую что-то там (идеи, опять же, есть).

4 комментария

Мир в бутылке: поведение ведьмы

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

Обидно, досадно, но ладно. Там было пространство для манёвра, но слишком медленно тренируется. Чтобы ускорить, нужно переписывать весь игровой мир на какой-нибудь фреймворк для ускорения через видеокарту, а это долго даже с нейросетками. Да и качество такого переноса потом не проверишь.

Решил пойти другим путём — попробовать «дерево решений», оно легче в обучении и его проще потом разбирать. Это помогло — эксперименты пошли бойчее, и я довольно быстро увеличил метрику с 1,715601 до 1,933353, что довольно много на самом деле. Метрика там по простенькой формуле учитывает результативность кампании — удалось ли убить гидру и сколько народу выжило.

Потом «Курсор» просто разобрал мне получившееся дерево и перенес ту же логику в правила. Следующий шаг — хочу расширить количество «решений», которые может принять ведьма и посмотреть что получится.

Дерево решений Witch Policy Tree с узлами условий и цветными листьями действий (stay, deposit, revive_danger). Пиксельный маг в углу.
Визуализированное дерево решений эксперимента №2 (в данный моменту у меня кончается эксперимент №4)

Оставить комментарий

ИИ: Claude Mythos и поиск уязвимостей

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

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

Я сразу заподозрил в этом заявлении изрядную долю маркетинга и оказался прав: как показало исследование, изрядную часть уязвимостей, которые раскрыли, нашли также и модели предыдущего поколения. Тем не менее я охотно верю, что «Мифос» сильнее «Опуса», просто не думаю, что настолько, насколько это хотят показать.

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

Оставить комментарий

Мир в бутылке: гидра и ведьма

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

Пиксельная сцена: персонажи на зелёном поле с тропой, сундуком, пещерой, надписью «HELP!» и водяным знаком Bolkleis.dev.
Мир в текущем его виде: появился «босс» — гидра

Эта гидра — то, что называется «боссом», то есть сильный монстр, для убийства которого требуются усилия большинства персонажей. Гидра сильно спутала мне карты, так как, по сути, все мои персонажи — одиночки. Да, они могут подлечивать друг друга и воскрешать, но основной алгоритм у них написан так, чтобы зачищать свою окрестность от врагов и не умирать.

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

Не бог весть какая стратегия, но я до сих пор с ней бьюсь. Пришлось выделить поведенческий код в отдельный модуль и проводить симуляции на тысячах прогонов, чтобы отладить логику. Так удалось отладить поведение лекаря (я в разговоре с ИИ называю её «девочка»), а вот ведьма пока далека от идеала.

Скриншот терминала с результатами симуляции: успех BASELINE 36%, FIX:girl-range only 39,9%, FIX:girl-range+route 99,9%; ниже — анализ ошибок и комментарий про ведьму и гидру.
Процесс общения с «Курсором» по поводу изолированной симуляции поведения персонажей

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

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

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

Я как-то не думал, что это займёт столько времени, но планирую экспериментировать до успеха.

Оставить комментарий

Мир в бутылке: а где лошадка?

Пока программировал свой «Мир в бутылке», пришли жена и дочка и, как фанатки лошадей, потребовали ввести в игру лошадку. Я согласился с условием, что дочка нарисует прототип и хоть немного продумает механику — как именно лошадка будет себя вести.

В итоге, дочка по-быстрому нарисовала как она видит лошадь, а я двумя проходами вместе с нейросеткой довёл её до пиксельного совершенства.

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

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

Оставить комментарий

Мир в бутылке: сжатие в картинку

Вчера я писал, что код и вероятности перехода в цепях Маркова упакованы в картинку, но не объяснил что это и для чего сделано.

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

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

Скриншот консоли: вывод сборки проекта bolklet, показывающий размеры файлов (JS, модель, спрайты), выбор формата PNG/RGB как оптимального и итоговое сжатие изображения на 89%.
Процесс сжатия в картинку — выбираем формат, который сжимает эффективнее

Сжатие при этом реализовывать в ДжаваСкрипте не нужно — браузер за нас распаковывается картинку, а мы её просто попиксельно читаем.

Поскольку веса для цепей Маркова занимают аж 3,5 мегабайта в джейсоне, я воспользовался этой идеей, чтобы поэффективнее его ужать, бинарно сериализуя его в картинку, а потом затянул туда и остальное — основной код и спрайты.

Оставить комментарий

Мир в бутылке

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

При запуске такие программы чаще всего отображали какое-то интерактивное животное — котёнка, который прыгал по вашим окнам или тараканов, которые прятались за ними.

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

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

В процессе написания идея модифицировалась — персонажи поселились на полоске внизу страницы, у них появились враги и некоторая специализация. Всё это полностью сделано «Опусом», я только направлял, тестировал и давал идеи.

Технически всё упаковано в одну картинку (так оказалось эффективнее) из которой читается и код, и спрайты, и вероятности перехода между состояниями для цепей Маркова.

Пиксельная сцена: зелёное поле с тропинкой, персонажами, сундуками, прудом и знаком с символами.

Оставить комментарий

Развернуть видео

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

Его надо выполнять в консоли браузера, которая вызывается через «Инструменты разработчика».

document.querySelectorAll('*,iframe').forEach(e=>(e?.shadowRoot||e).
querySelectorAll('video').forEach(v=>v.style.transform = 'scaleX(-1)'))

Оставить комментарий

ИИ: а где же «коленка»?

Один из бывших коллег, который следит за моими перипетиями в отношении нейросетей, прочитав прошлую заметку с заголовком «Собрано на коленке», совершенно закономерно спросил меня: а что, собственно, у меня там на коленке собрано-то?

Я перечитал — и оказалось, что из-за усталости я совершенно упустил из виду, что не посвятил «коленке» ни полабзаца.

Скриншот интерфейса с логами, таблицами процессов и метриками сравнения PHP и Python (точность, F1-score), включая детали экспериментов.

Что дашборд я стихийно собрал нейросеткой просто под эту задачу — наверное, можно догадаться, — это действительно не какой-то готовый продукт, а скрипт на «Пайтоне», написанный нейросеткой, входящей в мою подписку. Как я сказал, учусь чаще использовать более дешёвые сети, и это — одна из задач, с которой справляется собственная сеть «Курсора» — «Композер 2», а она очень простенькая.

То есть он вполне «собран на коленке».

Но ещё более наколеночно устроен деплой, то есть развёртывание новых гипотез на подключённых мощностях. По сути, это россыпь документации плюс шелл-скрипты, срабатывающие на хуки при коммите. Всё, опять же, написано вайбкодингом, в основном, тремя сетями: всё простое я поручал «Композеру 2», сложнее — «Кодексу 5.3», ещё сложнее — «ГПТ 5.4».

Почему я не стал использовать что-то готовое? А зачем? Надо было быстро, у меня не было времени сравнивать решения, выбирать лучшее под задачу (машины доступны только по ssh, друг друга не видят, перекачивать информацию можно только через мой ноубук), но главное — разбираться, если возникнут проблемы.

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

Кстати, вот ещё вывод, в добавление к тому, что я писал в прошлый раз: иногда надо давать ИИ приказы! Это не вполне очевидно.

Например, когда я давал указание занять GPU0 на одной из машин, нейросеть могла сделать то, чего я не ожидал. Например, увидев, что память там почти занята, поставить задачу в цикл ожидания освобождения памяти. Мне это не нужно — я понимал, что задача поместится, и ставил её туда сознательно.

Реальный случай, кстати. И таких примеров у меня было несколько.

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

6 комментариев

ИИ: собрано на коленке

Может, видели такую штуку, как «навесной монтаж» — когда люди собирают схемы не на печатной плате, а напаивают их одну на другую в воздухе? Я такое в детстве делал часто: много паял, а когда надо что-то быстро протестировать — ни времени, ни смысла делать печатную плату и паять на неё нет.

Я последние несколько дней занимаюсь похожей штукой. Ну или мне кажется, что это примерно одно и то же.

Скриншот чата с ИИ-агентом: обсуждение запуска GPU-задач, мониторинг процессов и метрик моделей на разных хостах, включая RTX 6000 и H100.

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

В проверке гипотез мне помогает курсор и куча оборудования — я оккупировал под свои цели три ускорителя H100 и три RTX 6000 Pro. Благо вечерами нагрузки никакой, а часть из этого оборудования вообще пока простаивает. Чтобы видеть куда и какие эксперименты пускать, я написал себе дашборд. При помощи тех же нейросетей, разумеется.

На скриншоте видно плохо, потому что дашборд с панелью «Курсора» выведены на 6К-монитор, поэтому немного расскажу. На дашборде я вижу текущее оборудование, включая ЦПУ, где кое-какие эксперименты тоже можно ставить — на одной из машин 190 ядер, а под оборудованием — текущие эксперименты и цифры по ним.

Всё обновляется в реальном времени.

Если прокрутить ниже, будет ещё один блок экспериментов, план запусков и блок, написанный «Квеном 3.5-35» в виде отчёта научного руководителя эксперимента. Кстати, краткие описания к запускам в таблице оборудования тоже генерируются им на лету.

А теперь пара выводов.

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

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

4 комментария

← 1 2 3 4 5 6 67 →