Агенты LLM меняют подходы разработчиков к миграции кода, превращая утомительные, подверженные ошибкам рефакторинги в интеллектуальные, полуавтоматизированные рабочие процессы. В этой статье мы показываем, как с помощью агентов перенести кодовую базу Java на TypeScript, проанализировав код, спланировав шаги и выполнив изменения с учетом архитектурных особенностей и проверки на основе CI.
Агенты LLM работают как автономные системы, использующие большие языковые модели для выполнения целенаправленных задач. Эти агенты не просто генерируют текст, они планируют действия, продумывают этапы и принимают решения в рамках сложных рабочих процессов. Разработчики могут использовать их для решения многоэтапных задач, таких как рефакторинг кода, обновление документации или генерация тестов.
В отличие от обычных запросов LLM, агенты объединяют память, инструменты и циклы обратной связи. Они взаимодействуют со средой программирования, оценивают результаты и решают, что делать дальше. Некоторые агенты извлекают документацию. Другие выполняют поиск в базе кода или вносят изменения, основываясь на структурированных целях.
В проектах по миграции кода агенты могут разбивать крупные изменения на более мелкие, управляемые операции. Они анализируют код, предлагают замены и выполняют преобразования с учетом контекста.
Проблема миграции кода
Перенос кода связан не только с обновлением синтаксиса. Большинство миграций связаны с более глубокими изменениями архитектуры, логики и зависимостей.
Команды часто переходят с одного языка на другой, например, с Java на TypeScript, или модернизируют код из более старых версий, например, с Python 2 на Python 3. Каждое изменение сопряжено с рисками. Устаревшие проекты часто содержат тесно связанные модули, недокументированное поведение или устаревшие сторонние библиотеки. Это создает препятствия, которые замедляют процесс миграции.
Ручной рефакторинг негативно сказывается на разработчиках. Инженерам приходится постоянно переключать контексты, интерпретировать незнакомую логику и избегать критических изменений. В результате при тестировании происходят регрессии, что замедляет выпуск нового решения.
Агенты LLM предлагают новый путь для миграции кода. Они могут сканировать кодовую базу, предлагать обновления и вносить повторяющиеся правки. Также агенты помогают командам снизить рабочую нагрузку, выявлять нестандартные ситуации и ускорять миграцию с меньшим количеством регрессий.
Агенты LLM вносят существенный вклад в рабочие процессы миграции кода с использованием искусственного интеллекта, внедряя лучшие практики рефакторинга кода, сочетая автоматизацию с контекстным анализом. Традиционная миграция часто включает в себя утомительные ручные правки, повторяющиеся шаблоны и высокий риск возникновения регрессий. Агенты помогают снизить это бремя, работая как помощники в принятии решений, которые понимают, планируют и действуют во всей вашей кодовой базе.
Почему агенты LLM эффективны
Агенты не рассматривают файлы как изолированные единицы. Они читают информацию по модулям, понимают, как взаимодействуют компоненты, и поддерживают общую картину при внесении изменений.
Как только агент идентифицирует преобразование, скажем, изменение callback на promise, он единообразно применяет этот шаблон ко всему проекту, избегая несоответствий, которые часто возникают при редактировании человеком.
Также, агенты помнят, что они изменили. Если они переименовывают функцию или переносят шаблон, они продолжают использовать эту логику. Это предотвращает дублирование усилий и обеспечивает согласованность архитектурных решений.
Независимо от того, выполняется ли рефакторинг 10 файлов или миграция 1000 файлов, агенты поддерживают контекст. Их можно приостанавливать, возобновлять или запускать повторно, и они не забудут о том, что было сделано и почему.
При этом разработчики могут сосредоточиться на проверке кода и принятии решений более высокого уровня, в то время как агенты обрабатывают повторяющиеся правки, регрессии и логику поиска‑замены с учетом контекста.
Используемые инструменты и фреймворки
В нашем примере использовался модульный стек для создания, запуска и проверки рабочего процесса миграции агента LLM. У каждого компонента была четкая роль, начиная от оркестровки и обработки памяти и заканчивая проверкой CI и статическим анализом.
LangChain
Выполняет функцию управляющего уровня для рабочих процессов агента. Позволяет определить, как агент определяет, запоминает и выполняет задачи шаг за шагом. Поддерживает интеграцию инструментов (например, поиск кода, редактирование файлов) и памяти агента.
GPT-4 / Claude
Эти языковые модели управляют основной логикой. Они интерпретируют исходный код, выводят правила миграции и генерируют модифицированный код с учетом архитектурного контекста. Для большинства многоэтапных рассуждений использовался GPT-4; в некоторых случаях Claude служил в качестве резервной модели или модели проверки.
Векторная база данных (например, Chroma)
Помогает агенту запоминать ранее просмотренные файлы, шаблоны и решения. Фрагменты кода встроены в векторы, которые агент использует для извлечения соответствующего контекста перед выполнением действий. Это позволяет избежать повторной обработки и повышает согласованность.
Docker
Обеспечивает выполнение миграции в изолированной и воспроизводимой среде. При каждом запуске агента запускается контейнер, соответствующий стеку среды выполнения проекта (например, Node.js, Python).
GitHub
Автоматически проверяет изменения, внесенные агентом. Модульные тесты, интеграционные тесты и сборка выполняются после каждого коммита, чтобы выявлять регрессии на ранней стадии и поддерживать доверие к автоматизации.
ESLint + Prettier
Запуск последующей миграции для проверки стиля и выявления синтаксических проблем. ESLint выявляет потенциальные ошибки или устаревшее использование, в то время как Prettier обеспечивает соответствие форматирования кода стандартам команды.
Практический пример: переход с Java на TypeScript
Мы разработали мультиагентную систему с использованием LangChain для автоматизации перехода с Java на TypeScript. В настройке участвовали три специализированных агента, каждый из которых выполнял разные роли в рабочем процессе.
1. Агент для чтения файлов
Этот агент просматривает Java‑проект и преобразовывает файлы в структурированные кодовые представления. Он проиндексирует определения классов, аннотации, методы и зависимости, используя вложения, хранящиеся в векторной базе данных (например, Chroma).
Входные данные — сервисный класс Java:
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User getUser(Long id) {
return userRepository.findById(id).orElse(null);
}
}
В результате получаем следующие метаданные:
{
"class": "UserService",
"annotations": ["@Service"],
"dependencies": ["UserRepository"],
"methods": [
{
"name": "getUser",
"returns": "User",
"params": [{"name": "id", "type": "Long"}],
"calls": ["userRepository.findById"]
}
]
}
2. Агент планировщика
Агент планировщика использует эти индексированные метаданные для построения дорожной карты миграции. Он разбивает систему на логические модули (DAO, службы, контроллеры) и составляет граф зависимостей.
Выходные данные планировщика:
{
"taskQueue": [
"migrate UserRepository.java",
"migrate UserService.java",
"migrate UserController.java"
],
"dependencies": {
"UserController": ["UserService"],
"UserService": ["UserRepository"]
}
}
Эта настройка позволила нам сначала перенести конечные модули и поэтапно устранить зависимости.
3. Агент Migrator
Агент Migrator выполняет фактический перевод Java‑кода в TypeScript, используя синтез кода, генерацию с расширенным поиском (RAG) и контекстно‑зависимые подсказки.
Сгенерированный вывод на TypeScript:
@Injectable()
export class UserService {
constructor(private readonly userRepository: UserRepository) {}
async getUser(id: number): Promise<User | null> {
const user = await this.userRepository.findById(id);
return user ?? null;
}
}
Эта миграция включала в себя:
Добавление асинхронного метода getUser. Возвращаемый тип стал Promise<User | null>.
Использование await для корректной обработки асинхронного вызова findById.
Переход к внедрению зависимостей на основе конструктора.
Использование Null coalescence для репликации Optional.OrElse(null).

Локальная миграция контроллера Spring на TypeScript
В качестве примера давайте перенесем контроллер Spring на контроллер TypeScript Express. Задача заключалась не просто в преобразовании Java в TypeScript, а в том, чтобы сделать это эффективно, с минимальными усилиями и полностью автономно.
Для этого нам потребуется фреймворк Ollama для локального запуска больших языковых моделей (LLM). Его можно загрузить по ссылке: https://ollama.com/download
Затем необходимо выполнить:
ollama pull codellama:latest
Далее создадим рабочее пространство для миграции
mkdir JavaToTypeScript
cd JavaToTypeScript
Внутри создадим следующие папки:

Для запуска LLM агента выполним следующее:
ollama run codellama
Изначально у нас был простой Spring controller, UserController.java, выглядевший следующим образом:
// Before:
@RestController
public class MyController {
@GetMapping("/users")
public List<User> getUsers() {
return userService.getAllUsers();
}
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
}
Я хотел воспроизвести эту функциональность в TypeScript с помощью Express.js, но я не хотел тратить часы на переписывание всего.
Решение: Локально использовать LLM‑агент
После ввода кода в приглашение LLM вернул следующее:
import express from 'express';
import bodyParser from 'body-parser';
const app = express();
app.use(bodyParser.json());
app.get('/users', (req, res) => {
const users = userService.getAllUsers();
res.json(users);
});
app.post('/users', (req, res) => {
const user = req.body;
const createdUser = userService.createUser(user);
res.json(createdUser);
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
Механизмы обработки ошибок и восстановления
Даже при тщательном планировании и интеграции CI при миграции кода, управляемого агентами, могут возникать ошибки, неправильное толкование или структурные проблемы. Чтобы сделать систему устойчивой, мы внедрили многоуровневые стратегии резервного копирования и восстановления, представленные ниже.
Дополнительные LLM:
Если основной LLM (например, GPT-4) не смог выполнить корректную миграцию для модуля, система автоматически повторяет попытку, используя альтернативную модель (например, Claude 3).
Быстрая адаптация:
При первом сбое агент скорректировал свой запрос, введя дополнительные примеры, более строгие правила синтаксиса или базовые шаблоны, прежде чем повторить генерацию.
Устанавливаются пороговые значения достоверности:
Агенты отмечали миграции, в которых показатели достоверности токенов, охвата различий в коде или структурной завершенности были ниже пороговых значений. Эти модули были помечены для проверки вручную.
Режим интерактивной проверки:
Разработчики могли подключаться в отмеченные моменты, просматривать предложения агента и вручную редактировать или утверждать их, прежде чем вводить код.
Команды отмены и повторной попытки:
Если планировщик обнаружит каскадные сбои в зависимых модулях, он может прервать пакетную миграцию, устранить проблемы с исходным кодом и повторно запустить последовательность.
Полное регрессионное тестирование:
После миграции каждого крупного модуля запускались полные регрессионные наборы (модульные тесты + интеграционные тесты) для немедленного обнаружения сбоев во время выполнения.
Теневые развертывания:
Новые службы TypeScript были развернуты наряду с существующими службами Java на предыдущих этапах. Это позволило проводить безопасное тестирование с использованием зеркалирования рабочего трафика без риска простоя.
Безопасность управления версиями:
На каждом этапе миграции создавалась изолированная функциональная ветвь. Отказавшие ветви никогда не объединялись до прохождения проверки, что обеспечивало стабильность основной сети.
Заключение
Агенты LLM демонстрируют реальные перспективы в решении сложной задачи по миграции кода, особенно в крупных устаревших монолитных приложениях. Использование передовых методов работы с инструментами миграции кода может значительно улучшить процесс. Хотя они и не являются идеальным решением, они предлагают разработчикам серьезные преимущества по сравнению с рефакторингом вручную.
Если хочется не просто экспериментировать с агентами, а системно строить LLM-сервисы — от архитектуры и фреймворков вроде LangChain до LLMOps и RAG — эту практику можно развернуть в рамках курса LLM Driven Development. Там те же идеи мультиагентных систем, векторных баз и интеграции AI в backend-продукты разбираются уже на уровне полноценного продакшн-стека.
Для знакомства с форматом обучения и преподавателем приходите на бесплатный демо-урок 19 ноября в 20:00 — «Создание локального сервиса с использованием библиотек искусственного интеллекта на основе телеграмм-бота». Записаться.
Чтобы оставаться в курсе актуальных технологий и трендов, подписывайтесь на Telegram-канал OTUS.