Заголовок вроде «Шестнадцать агентов ИИ создали компилятор C» звучит либо как фокус, либо как начало научно-фантастического сюжета. В действительности же это нечто гораздо более интересное: взгляд на то, как меняется разработка программного обеспечения, когда к модели ИИ можно относиться не как к собеседнику, а как к...рабочая сила— набор полунезависимых агентов, способных планировать, распределять задачи, писать код, проверять работу друг друга и итеративно взаимодействовать.
В этой статье подробно рассматривается, что такое компилятор C, что требуется для его создания, как на практике выглядит работа с «многоагентными» системами и какие проекты эти системы, вероятно, упростят (а какие останутся по-прежнему сложными).
Что такое компилятор, говоря простыми словами?
Компилятор — это программа, которая переводит написанный вами код (а)исходный язык) в форму, которую может выполнить компьютер (а)целевой язык(часто машинный код). Но «перевод» — это еще мягко сказано. Производственный компилятор также должен:
- Отклонить недействительные программы(и объясните почему, в идеале с полезными сообщениями об ошибках).
- Обеспечивать соблюдение языковых правил(типы, область видимости, правила модели памяти, ограничения неопределенного поведения).
- Оптимизироватькод, который работает быстро и использует меньше памяти.
- Целевая аудитория: несколько процессоров и операционных систем(x86-64, ARM64, RISC-V; Linux, macOS, Windows; встроенные системы).
- Интеграция с инструментальными цепочками: компоновщики, ассемблеры, отладчики, системы сборки.
Полезной мысленной моделью является представление компилятора не как чего-то одного, а как конвейера:
- Лексинг: превращает персонажей в токены.
- Парсинг: преобразовать токены в структурированное синтаксическое дерево.
- Семантический анализ: разрешать имена, типы и правила, которые не видны только по синтаксису.
- Промежуточное представление (IR): преобразовать программу в форму, удобную для компилятора.
- Оптимизация: улучшить ИК-спектр.
- Генерация кода: генерировать машинный код (или код на другом целевом языке).
Это классический подход. Инженерный подход добавляет производительность сборки, воспроизводимость, усиление безопасности, диагностику и бесконечную реальность реальных кодовых баз, использующих все возможности языка.
Почему С — жестокая мишень
ЗданиеаСоздание компилятора — сложная задача.СКомпилятор — это особый вид сложности, потому что язык C содержит:
- Большая поверхность с «острыми краями» (указатели, ручное управление памятью).
- Долгая история поведения, зависящего от компилятора.
- Спецификация, полнаянеопределенное поведение— случаи, когда в тексте намеренно не уточняется, что именно происходит.
Неопределенное поведение — это не просто теоретический вопрос. Это своего рода договор: компилятору разрешено предполагать, что неопределенное поведение никогда не происходит, что позволяет проводить оптимизации, но также создает подводные камни, когда реальный код случайно его вызывает.
Компилятор AC, который являетсянемного неправильноЭто не «в основном нормально»; это может привести к появлению слегка некорректных бинарных файлов, которые дают сбои только на определенных уровнях оптимизации, определенных процессорах или при определенных входных данных. Именно поэтому тестирование компиляторов настолько интенсивно: необходимы обширные наборы тестов, фаззинг, дифференциальное тестирование с известными компиляторами (такими как GCC/Clang) и покрытие сборки реальными условиями.
Так что же означает, что «шестнадцать агентов» построили один?
Главная идея заключается не в том, что какая-то одна модель стала умнее в одночасье. Дело в том, что рабочий процесс стал более структурированным.
Типичная схема работы с несколькими агентами выглядит следующим образом:
- Апланировщик/менеджер агентРазбивает проект на модули и этапы.
- Агенты исполнителейНаписать код для конкретных подсистем (лексер, парсер, промежуточное представление, генерация кода, тесты).
- Агенты-рецензентыПроанализируйте проекты и проверьте наличие логических несоответствий.
- Атест/фузз-агентСоздаёт тестовые примеры и отслеживает ошибки.
- Аагент документацииСоставляет документацию по использованию и примеры.
Если вы когда-либо работали над проектом компилятора, это должно показаться вам знакомым — это отражает то, как работают человеческие команды. Разница лишь в том, что вы можете мгновенно создать «коллег по команде», и они готовы выполнять монотонную работу без усталости.
Но не следует путать это с гарантированным качеством. Многоагентные системы по-прежнему могут:
- Создайте код, которыйвыглядит правдоподобноно это неправильно.
- Не учитываются крайние случаи.
- Застрять в локальном оптимуме (архитектура, которая компилируется, но не может быть расширена).
- Переобучение на тестовом наборе (прохождение тестов без корректной реализации языка).
Этот подход предлагает следующее:параллелизмискорость итерацииЕсли команде людей может потребоваться неделя, чтобы создать первый прототип подсистемы, то многоагентная система может создать несколько альтернативных прототипов за день — и тогда вы выбираете наилучшее направление.
Настоящий прорыв: интеграция, а не поколение.
Большинство людей представляют себе прогресс в программировании ИИ как «возможность писать больше строк кода». Для компиляторов количество строк кода не является узким местом. Узким местом являетсяинтеграция:
- Согласованы ли правила токенизации между лексером и парсером?
- Выявляют ли семантические проверки последовательные и поддающиеся исправлению ошибки?
- Сохраняет ли информационный запрос семантику входной программы?
- Сохраняют ли оптимизации неизменность поведения за пределами неопределенных границ поведения?
- Может ли он компилировать большие реальные кодовые базы без превышения времени ожидания или чрезмерного расхода памяти?
Команда из нескольких агентов, способная поддерживать согласованность этих частей, делает нечто качественно отличное от модели, которая может генерировать аккуратный фрагмент кода для парсера.
Как определить, является ли компилятор «настоящим»?
Существует несколько критериев, позволяющих отличить «удобную демонстрацию» от «компилятора, которому можно доверять»:
- Самостоятельное размещениеМожет ли компилятор скомпилировать сам себя?
- Соответствие стандарту CПроходит ли он известные тестовые наборы?
- Дифференциальное тестированиеСоответствуют ли выходные данные GCC/Clang на больших рандомизированных тестовых наборах?
- Отладочная способностьМожет ли оно создавать символы и взаимодействовать с отладчиками?
- Целевая широтаПоддерживает ли он более одного процессора/платформы?
Многие ранние компиляторы в истории были «настоящими» задолго до того, как стали пригодными для использования в производственных целях — поэтому вполне справедливо называть новый компилятор настоящим, даже если он еще не готов для сборки вашего ядра. Но расстояние от «может компилировать небольшие программы на C» до «безопасен для использования в производственных целях» огромно.
Почему это важно, даже если вы никогда не будете использовать этот компилятор
Интересный вывод заключается не в том, что «искусственный интеллект заменил инженеров-разработчиков компиляторов». А в том, чторазработка компиляторовстановится более доступной мишенью для экспериментов.
Исторически сложилось так, что работа компилятора характеризуется высокой энергией активации:
- Вам необходимы глубокие знания в области проектирования языков программирования и семантики.
- Вам потребуется много вспомогательного оборудования: парсеры, инфраструктура информационного поиска, тестовые среды.
- Вам нужно время.
Если многоагентные инструменты способны создавать и поддерживать большую часть такой структуры, то больше людей смогут заниматься исследованиями:
- Нишевые языки (языки, специфичные для конкретной предметной области, встроенные языки сценариев).
- Альтернативные архитектуры компиляторов.
- Инструменты обеспечения безопасности и верификации (например, компиляторы со встроенной проверкой).
- Инструментарий для работы с компиляторами: автоматические минимизаторы ошибок, генераторы тестовых примеров, системы регрессионного анализа.
Это похоже на то, что произошло, когда веб-фреймворки достигли зрелости: вы перестали писать серверы на основе обычных сокетов и начали создавать высокоуровневые компоненты. Это не уничтожило бэкенд-разработку; это изменило её.
Скрытая цена: доверие и происхождение.
Одна из причин чувствительности компиляторов заключается в том, что они лежат в основе программного стека. Если вы не доверяете своему компилятору, вы не доверяете и своему бинарному файлу. Это порождает два неотложных вопроса для проектов компиляторов с поддержкой ИИ:
- ПроисхождениеКто написал какие части? Какую модель? Какие вопросы задавали? Какие проверки проводились людьми?
- БезопасностьКак вы гарантируете отсутствие скрытых лазеек или уязвимостей, возникших случайно (или из-за некорректно работающей зависимости)?
Существует также классическая проблема «доверия доверию»: компилятор может внедрить вредоносное поведение в выходные данные во время компиляции самого себя. Современные инструментальные средства решают эту проблему с помощью таких методов, как разнообразная двойная компиляция и воспроизводимые сборки, — и код, сгенерированный ИИ, вероятно, усилит давление на более широкое внедрение этих практик.
В чём, вероятно, преуспеет многоагентное программирование в будущем?
Многоагентные системы наиболее эффективны, когда:
- Работу можно разложить на модули.
- Интерфейсы понятны.
- Обеспечивается быстрая обратная связь (тесты, сравнительные тесты, фаззеры).
Компиляторы удивительно хорошо подходят для этой задачи: они модульные, основаны на интерфейсах и поддаются тестированию.
Следующая волна, скорее всего, будет выглядеть следующим образом:
- Перенос с помощью агентов«Поддержка ARM64 в Windows» превращается в серию структурированных задач.
- Улучшение автоматизированной диагностики: генерировать и проверять более информативные сообщения об ошибках.
- Циклы фаззера и исправителя: агенты, которые генерируют неработающие программы, минимизируют их и предлагают исправления.
- ИК-исследование: генерация альтернативных вариантов оптимизации и измерение корректности/производительности.
Что это делаетнетсредний (ещё)
Это не значит:
- Любую крупную программную систему можно создать путем «запуска агентов».
- Вы можете пропустить этап составления спецификации.
- Тесты можно игнорировать.
- Проблемы безопасности и ремонтопригодности решены.
Компилятор — отличный объект для демонстрации, поскольку его корректность измерима, а масштаб проекта ограничен. Действительно сложные задачи разработки программного обеспечения часто не имеют границ: запутанные требования, компромиссы в отношении пользовательского опыта, интеграция с множеством вариантов и координация действий человека.
Итог
Создание командой ИИ-агентов работающего компилятора языка C — это значимая веха, не потому что компиляторы внезапно стали простыми, а потому что это демонстрирует изменение рабочего процесса:Искусственный интеллект как скоординированная инженерная командаа не единый механизм автозаполнения. Долгосрочная перспектива по-прежнему заключается в доверии, тестировании и интеграции с реальными инструментами, но направление ясно: всё больше программного обеспечения будет создаваться путем оркестрации систем, а не просто написания кода.