Dev48
ЯЗЫК
  • О нас
  • Услуги
  • Индустрии
  • Технологии
  • Статьи
  • Контакты
Забронировать звонок
    Главная/Статьи/Modernizatsiya slozhnogo ustarevshego koda s pomoschyu ii agentov
Dev48

© 2026 · All rights reserved.

Модернизация сложного устаревшего кода с помощью ИИ-агентов.

Источник: Mistral

Модернизация сложного устаревшего кода с помощью ИИ-агентов.

Источник: Mistral

Mistral помогла европейскому оператору энергосистем перенести 40 000 строк кода на Fortran 77 в C++. Узнайте, как это было сделано и какие выводы стоит извлечь.

25 сентября 2026 г.

Устаревшие научные кодовые базы накапливаются десятилетиями, и когда первоначальные авторы уходят, заложенные в коде знания становится трудно восстановить. Более того, использование языков без активной экосистемы разработчиков означает упущенную возможность создавать решения на базе чужих наработок. Mistral помогла европейскому оператору энергосистем перенести 40 000 строк кода на Fortran 77 в C++, представляющего собой ресурсоемкий симулятор пласта без набора тестов и централизованной документации.

Выход за рамки простого перевода кода при модернизации устаревших систем.

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

Fortran 77 был стандартизирован в 1977 году, как можно понять из названия, и написанный на нем код напрямую отражает эти ограничения: никаких модулей, пространств имен и структурированных типов. Состояние хранится в блоках COMMON — глобальной памяти, общей для всей программы. Типы переменных определяются неявно по их первой букве, поэтому опечатка в имени создает новую переменную молча, вместо того чтобы вызвать ошибку компилятора.

В качестве простого, но наглядного примера рассмотрим следующую реализацию разложения Тейлора первого порядка. Входные и выходные данные являются глобальными в блоке COMMON, а IC является целым числом только потому, что его имя начинается с буквы в диапазоне от I до N. Имена переменных довольно загадочны, так как их длина ограничена 6 символами.

SUBROUTINE GASDEN

INCLUDE 'common.h'

DO 10 IC = 1, NCELL

10 RHOG(IC) = ROG(IV) + DROG(IV)*(P(IC)-PTAB(IV))

END

В C++ можно задействовать явные типы, писать объектно-ориентированный код и возвращать значение напрямую вместо записи в глобальную переменную:

double gasDensity(const GasProperties& gas, double pressure) {

size_t i = lookup(gas.pressure, pressure);

return gas.density[i] + gas.slope[i] * (pressure - gas.pressure[i]);

Разрозненные массивы COMMON превращаются в единый параметр GasProperties, а цикл по сетке выносится на уровень вызывающего кода, поэтому здесь нет поэлементного соответствия для проверки, что и делает верификацию миграции сложной задачей.

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

  • Как доказать, что мигрированная кодовая база совпадает с исходной с точки зрения численных результатов

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

  • Как разбить миграцию на управляемые части

Как разбить миграцию на управляемые части

  • Как лучше всего использовать автономных агентов для ускорения процесса

Как лучше всего использовать автономных агентов для ускорения процесса

Создание инфраструктуры проверки паритета перед миграцией устаревшего кода.

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

Мы добавили:

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

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

  • тестовый фреймворк для загрузки контрольных точек (чекпоинтов) в C++

тестовый фреймворк для загрузки контрольных точек (чекпоинтов) в C++

  • файлы Skill.md для направления агентов к их правильному использованию

файлы Skill.md для направления агентов к их правильному использованию

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

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

Приведенный ниже пример иллюстрирует это. Сначала мы вставили в код на Fortran строку для выгрузки значения переменной RHOG (в данном запуске равного 42.71834), а затем использовали это же значение в качестве эталонной контрольной точки при тестировании перенесенного модуля C++.

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

Документация проекта была разбросана по старым PDF-файлам и комментариям, спрятанным в самом Fortran, и одним из главных побочных достижений всей работы стало приведение этой документации в порядок и размещение ее рядом с кодом.

К счастью, процедурный код вроде Fortran обладает удобным свойством: всю программу можно представить в виде единого дерева вызовов (caller-callee). Мы сгенерировали это дерево, разобрав кодовую базу с помощью кастомного парсера, а затем использовали Vibe CLI для запуска более чем сотни агентов с целью ее документирования. Каждый агент мог подтягивать соответствующие PDF-файлы через библиотеки документов и Mistral OCR.

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

Использование ИИ-агентов для модернизации кода.

При первой попытке мы предоставили агентам полную автономность: по одному агенту на каждую подпрограмму на Fortran, причем каждый независимо переводил свою функцию на C++ в течение недели. Результат оказался рабочим, но модернизацией кода это назвать было нельзя. Блоки COMMON превратились в глобальные структуры один к одному. Управление на основе GOTO осталось прежним вместо реструктуризации в циклы или ранние возвраты. Это выглядело как Fortran, переписанный в синтаксисе C++, а не как современный код.

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

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

Запуск структурированных рабочих процессов ИИ-агентов для миграции сложного кода.

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

Совместно с инженерами заказчика по разработке месторождений мы использовали дерево вызовов для определения независимых модулей — самодостаточных поддеревьев управляемого размера (эмпирически — менее ~10 000 строк на Fortran). Каждый модуль проходил через один и тот же рабочий процесс:

  • Сгенерировать целевую архитектуру C++.

Сгенерируйте целевую архитектуру на C++.

  • Согласуйте ее с инженером по разработке нефтяных и газовых месторождений.

Согласуйте ее с инженером по разработке нефтяных и газовых месторождений.

  • После утверждения разбейте ее на очередь задач.

После утверждения разбейте ее на очередь задач.

  • Запускайте подпроцесс реализации для каждой задачи: планирование → реализация → тестирование → повтор.

Запускайте подпроцесс реализации для каждой задачи: планирование → реализация → тестирование → повтор.

  • Человек проверяет полученные PR (пулл-реквесты) и запрашивает изменения до тех пор, пока они не будут приняты.

Человек проверяет полученные PR (пулл-реквесты) и запрашивает изменения до тех пор, пока они не будут приняты.

Осознание ограничений модернизации устаревшего кода с помощью ИИ.

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

Применение трех принципов для модернизации сложных устаревших систем.

Три урока из этого проекта должны быть перенесены на любую масштабную миграцию устаревшего ПО.

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

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

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

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

  • И в таком масштабе структурированные рабочие процессы с контрольными точками проверки человеком превосходят как полную автономность, так и ручные сеансы.

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

Мы нанимаем сотрудников!

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

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

← Все статьи