Как и большинство серьёзных спикеров в IT, я внимательно слежу за тем, какую роль могут сыграть в разработке ПО системы генеративного искусственного интеллекта. Думаю, возникновение больших языковых моделей (LLM) повлияет на разработку ПО примерно в той же степени, что и переход с ассемблера на первые высокоуровневые языки программирования. Чем дальше развиваются языки и фреймворки, тем сильнее абстрагируется наш код и, соответственно, возрастает продуктивность, но такие изменения пока не касаются самой природы программирования. При применении LLM – уже касаются, но я хочу поговорить о том, что LLM не только повышают уровень абстракции. Пользуясь ими, приходится учитывать, как выглядит программирование с использованием недетерминированных инструментов.
Как я уже говорил, высокоуровневые языки программирования вывели нас на совершенно новый уровень абстракции. Работая с ассемблером, я думаю о наборе инструкций для конкретной машинной архитектуры. Мне приходится продумывать даже самые простые действия, размышляя, как я буду осуществлять те или иные последовательности действий, записывая данные в нужные регистры. Но при работе с высокоуровневыми языками появилась возможность обдумывать программу как последовательность команд, в которой предусмотрены условные операторы, чтобы выбирать альтернативы для продолжения. Также в программе есть итерации, чтобы раз за разом применять команды к наборам значений данных. Многие элементы кода можно именовать, чтобы было ясно, что именно понимается под теми или иными значениями. Ранние языки программирования явно были в чём-то ограничены. Я начинал программировать на Fortran IV, где у операторов «IF» не было условия «ELSE». Поэтому мне приходилось как-то запоминать мои целочисленные переменные, и я начинал их с букв от «I» до «N».
Когда условия стали менее строгими, и код приобрёл блочную структуру («У меня после IF может идти более одной команды»), программировать стало проще и интереснее, но принципиально программирование осталось прежним. Сейчас я почти не пишу циклов, а инстинктивно передаю функции как данные — но по-прежнему общаюсь с машиной примерно в таком же стиле, как тогда давным-давно на дорсетских болотах, когда моим языком был Fortran. Язык Ruby гораздо более изощрённый, чем Fortran, но Ruby свойственен такой дух, которого нет у Fortran и машинных инструкций PDP-11.
Пока мне довелось лишь слегка поболтать с самыми современными генеративными инструментами, но я очень ими увлечён и люблю слушать, как друзья и коллеги делятся впечатлениями о работе с ними. Думаю, это очередное фундаментальное изменение: общение с машиной на языке промптов настолько же отличается от программирования на Ruby, насколько Fortran отличается от ассемблера. Но это не только большой прыжок в том, что касается уровня абстракции. Написав функцию на Fortran, я мог сто раз её скомпилировать, и каждый раз в ней всё равно проявлялись одни и те же баги. Используя большие языковые модели, приходится иметь дело с недетерминированными абстракциями, так что я не могу просто сохранить мои промпты в git и быть уверен, что они всякий раз будут давать одинаковое поведение. Как выразилась моя коллега Биргитта , мы не просто движемся вверх по лестнице абстракций, мы одновременно движемся вбок по направлению к недетерминизму.

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