В последние годы большие языковые модели (LLM) приобрели огромную популярность благодаря своим впечатляющим способностям генерировать текст, программный код и решать сложные задачи. Однако, несмотря на это, практический опыт показывает, что LLM далеки от идеала и имеют значительно ограниченный потенциал в ряде специфических технических задач. Об этом ярко свидетельствует недавняя статья Джо Маршалла, специалиста в области программирования и компьютерных наук. Его испытания и наблюдения проливают свет на слабые стороны современных LLM, демонстрируя, насколько еще долго они будут уступать опытному программисту при решении узкоспециализированных проблем. Первый представленный Маршаллом кейс касается достаточно простой, на первый взгляд, задачи — упорядочивания определений функций в библиотеке в алфавитном порядке.
Это одна из тех рутинных задач, с которыми ежедневно сталкиваются разработчики ПО для повышения удобства и читаемости кода. Автор предложил языковой модели обработать файл с набором функций и переставить их по алфавиту. Однако ответ LLM оказался неожиданным — модель отказалась выполнять задание, сославшись на неспособность определить границы функций из-за отсутствия у себя внутреннего понимания синтаксиса языка программирования. Такое объяснение можно признать отчасти оправданным, поскольку глубокое понимание синтаксиса действительно требует моделей, специально обученных анализу языков программирования. Тем не менее опытный инженер знает, что для простых языков и типичной структуры кода определить начало и конец функций достаточно легко — они обычно отделены пустыми строками, начинаются с левого края, имеют соблюденные отступы и символы-дизаторы.
Более того, исходный код был создан самой моделью, то есть с учётом ее собственных правил генерации, что делает отказ выглядящим неразумным и неожиданным. Вместо элементарной перестановки блоков текста, что не требует глубокого грамматического анализа, модель предпочла отказаться от действия, продемонстрировав парадоксальные ограничения в базовой обработке текста. Второе и более комплексное испытание Джо Маршалла связаны с генерацией и обработкой грамматики языка программирования Go. Автор запросил LLM сгенерировать серию небольших программ, иллюстрирующих различные конструкции из расширенного BNF-грамматического описания языка Go, а затем — разработать парсер, способный корректно их обрабатывать. На первый этап LLM справилась достаточно хорошо, создав около двадцати программ разной сложности, демонстрируя разнообразие синтаксиса и правильность использования языковых конструкций.
Однако при переходе ко второй части задачи — разработке парсера — модели столкнулись с серьезными трудностями. Парсер должен иметь способность анализировать текст на основе грамматики и корректно разбивать его на составные части, обеспечивая затем дальнейшую обработку кода. Это классическая задача для конструкторов компиляторов и языковых инструментов. Тем не менее, LLM сгенерировала лишь простейший рекурсивный нисходящий парсер, ограниченный обработкой только самых базовых примеров. Любые попытки расширить этот парсер приводили к хаосу: модель начинала блуждать в догадках, генерировать бессвязный и ошибочный код, проявляла признаки так называемой «галлюцинации» — создания информации без подоплеки.
Несмотря на множество попыток корректировать запросы и направлять языковую модель, добиться существенного прогресса не удалось. Попытки заставить LLM самостоятельно улучшить парсер наталкивались на ограниченность её структуры памяти и способности координированно использовать грамматику для построения надежного инструмента анализа. Аналогичный опыт автора, проведённый с разными платформами — такими как Cursor с Claude Sonnet 4 и Gemini CLI с Gemini-2.5 — лишь подтвердил выявленную проблему: модели топорно справляются с генерацией разрозненных фрагментов кода, но плохо компонуют их в цельные сложные системы. Причины подобных неудач сходны и, по сути, лежат в основе архитектуры современных LLM.
Большие языковые модели основываются на статистической вероятности последовательности слов или символов, выявляя паттерны в обучающих данных. Они не обладают внутренним пониманием сути программного кода, грамматических правил и логики построения языков. Их сильная сторона — генерация вероятностно смысленных последовательностей, а не строгий синтаксический или семантический анализ. Это означает, что при решении задач, требующих комплексной внутренней модели и взаимосвязей, LLM быстро исчерпывают свои возможности. Важно отметить, что подобные ограничения не означают бесполезность больших языковых моделей в программировании.
Напротив, они превосходны в генерации шаблонного кода, автоматизации рутинных операций, помощи с примерами и обучением. Задачи вроде быстрого прототипирования или помощи новичкам в обучении программированию — их естественная ниша. Но когда речь заходит о сложных инженерных задачах, требующих глубокого анализа, строгой логики и построения комплексных структур, LLM пока что не способны конкурировать с классическими инструментами и опытными специалистами. Опыт Джо Маршалла отлично демонстрирует необходимость осмотрительности при использовании современных моделей в программировании. Следует понимать, что LLM — мощный инструмент, но обладающий собственным набором ограничений.
Надежность и качество получаемого решения зависит от постановки задачи, характера запроса и понимания моделей их внутренних слабостей. Иногда самые очевидные, казалось бы, проблемы оказываются сложнее для искусственного интеллекта, чем для человека с минимальными знаниями языка. Будущее больших языковых моделей, несомненно, связано с их развитием по направлению глубинного понимания кода, внедрением специализированных механизмов анализа и синтаксиса. Появление гибридных систем, сочетающих статистическое обучение с формальными методами разбора и доказательств, может существенно сократить нынешний разрыв. Пока же опыт экспертов и тех, кто экспериментирует с LLM, как в случае с Джо Маршаллом, дает ценное понимание, где находятся границы возможностей современных систем и как избежать завышенных ожиданий.
В конечном счете, LLM — это инструмент, который нужно использовать с умом, учитывая силу и слабости технологии. Постоянное эксперементирование, тщательная формулировка запросов и комплексное тестирование решений помогут извлечь максимум пользы из моделей, не забывая оглядываться на собственное экспертное знание и классические инженерные подходы к разработке кода и программных систем.