TL;DR
BabelCoder — система перевода кода между языками программирования (Python ↔ Java, C++, C, Go), которая работает через промежуточный шаг: сначала код превращается в построчное описание логики на естественном языке (NL-Specification), потом это описание переводится в целевой язык. Система использует три агента: переводчик, тестировщик и рефайнер, которые итеративно улучшают результат через генерацию тестов и исправление багов.
Прямой перевод кода между языками часто ломается, потому что LLM цепляется за синтаксис исходного языка и переносит его паттерны в целевой. Например, Python-код с list comprehension LLM может буквально перевести в Java через stream API, хотя простой цикл был бы правильнее. Модель видит "как написано", но не всегда понимает "что делает". Особенно это заметно в сложной логике с вложенными циклами и условиями — LLM путает границы блоков и порядок операций.
BabelCoder решает через языково-агностичное представление: NL-Specification описывает каждую строку кода словами ("если элемент больше текущего максимума, обновить максимум"), без привязки к синтаксису. Дальше система переводит это описание в целевой язык, а тестировщик генерирует тесты из исходного кода и проверяет корректность. Если тесты не прошли — рефайнер локализует баг (определяет scope: обработка ввода, форматирование вывода, циклы, условия) и исправляет через LLM. Система показала 94.16% точности на бенчмарках.
Схема метода
АГЕНТ 1 (Translation): Первичный перевод
├─ Получить NL-Specification от Агента 2
└─ Перевести в целевой язык
АГЕНТ 2 (Refinement): Валидация и исправления
├─ Генерация NL-Specification из исходного кода
├─ Валидация спецификации через тесты
├─ Определение scope бага (Input/Output/Loop/Conditional)
└─ Итеративное исправление
АГЕНТ 3 (Test): Проверка корректности
├─ Генерация тест-кейсов (corner cases, edge cases)
├─ Запуск исходного кода → получение эталонных результатов
└─ Запуск переведённого кода → сравнение с эталоном
(Система исследовалась с автоматическим запуском кода, но принципы применимы в чате — см. секцию "Пример применения")
Пример применения
Задача: Переводишь Python-скрипт для парсинга логов в Java для интеграции в корпоративную систему мониторинга. В коде куча вложенных условий и регулярок — прямой перевод через ChatGPT выдаёт код, который компилируется, но неправильно обрабатывает edge cases (пустые строки, спецсимволы).
Промпт:
Мне нужно перевести Python-функцию в Java. Используем двухшаговый подход:
ШАГ 1: Создай NL-Specification — построчное описание логики на естественном языке без синтаксиса Python.
Формат:
- Сохрани структуру (отступы показывают вложенность)
- Опиши ЧТО делает каждая строка, не КАК написано в Python
- Без упоминания Python-специфичных конструкций (list comprehension, lambda, etc)
Вот код:
[вставь свой Python-код]
ШАГ 2: После того как создашь NL-Specification, переведи ЕГО (не исходный Python-код) в Java.
ШАГ 3: Проверь: соответствует ли Java-код NL-Specification построчно? Если есть расхождения — исправь.
Результат:
Модель выдаст три блока: 1. NL-Specification — описание логики типа "Если строка не пустая → разбить по разделителю → для каждого элемента проверить соответствие паттерну → если соответствует, добавить в результат" 2. Java-код — перевод на основе описания, не прямое копирование Python-синтаксиса 3. Проверка соответствия — модель сама сравнит NL-Specification и Java-код, укажет где логика разошлась
Ты получишь более точный перевод, потому что модель сначала "поняла" логику абстрактно, потом выразила её идиоматично для Java.
Почему это работает
LLM при прямом переводе кода страдает от "синтаксической слепоты": видит for x in list, думает "цикл", переводит в for (x : list) в Java, но не анализирует что делает тело цикла и можно ли это выразить иначе. Модель цепляется за структуру исходного языка, переносит его идиомы в целевой, даже если там есть более естественные способы.
LLM отлично работает с естественным языком и умеет генерировать код из описаний — это core-компетенция. Когда видит "если элемент больше текущего максимума", модель понимает намерение чище, чем когда парсит if arr[i] > max_val.
NL-Specification разрывает связь "исходный синтаксис → целевой синтаксис". Вместо Python → Java получается: Python → описание логики → Java. Промежуточное языково-агностичное представление заставляет модель думать о семантике, а не о синтаксисе. Модель не может механически скопировать структуру, она должна понять и пересказать.
Валидация через NL-Specification работает как спецификация-оракул: если описание говорит "обработать пустые строки отдельно", а в Java-коде этого нет — несоответствие очевидно. Это семантическая проверка, не просто запуск тестов.
Рычаги управления: - Детальность NL-Specification — "построчно" vs "по блокам логики". Для простого кода достаточно блоками, для сложного — построчно. - Scope бага (Input Processing, Output Formatting, Loop, Conditional) — можно задать вручную, если знаешь где проблема, вместо автоматического определения. - Порядок шагов — можно менять: сначала NL-Spec → перевод (как в оригинале), или сначала перевод → потом NL-Spec для валидации.
Шаблон промпта
Переведи код из {исходный_язык} в {целевой_язык} через двухшаговый процесс:
ШАГ 1: СОЗДАНИЕ NL-SPECIFICATION
Проанализируй исходный код и создай построчное описание логики на естественном языке.
Требования:
- Сохрани структуру: отступы показывают вложенность блоков
- Опиши ЧТО делает каждая строка, не КАК это написано синтаксически
- Без упоминания специфичных конструкций исходного языка
- Фокус на логике: условия, циклы, преобразования данных
Исходный код:
{код}
ШАГ 2: ПЕРЕВОД NL-SPECIFICATION
Переведи созданную NL-Specification в {целевой_язык}, используя идиоматичный стиль целевого языка.
ШАГ 3: ВАЛИДАЦИЯ
Сравни построчно:
- NL-Specification (что должно делаться)
- Переведённый код (что реально делается)
Если есть расхождения — исправь код, чтобы точно соответствовал логике из NL-Specification.
Выведи три блока:
1. NL-Specification
2. Переведённый код
3. Результат валидации (OK / Исправления)
Плейсхолдеры:
- {исходный_язык}, {целевой_язык} — названия языков программирования
- {код} — исходный код для перевода
🚀 Быстрый старт — вставь в чат:
Вот шаблон для перевода кода через NL-Specification. Адаптируй под мою задачу: [опиши что переводишь: язык, суть функции, что должно работать].
Задавай уточняющие вопросы про код.
[вставить шаблон выше]
LLM спросит про исходный и целевой язык, попросит код, уточнит критичные детали (обработка ошибок, edge cases) — потому что для создания точной NL-Specification нужно понимать ожидаемое поведение. Она возьмёт паттерн из шаблона и адаптирует под твою функцию.
Ограничения
⚠️ Требуется валидация вручную: Без автоматических тестов ты не можешь быть на 100% уверен, что перевод корректен. NL-Specification помогает, но финальную проверку делаешь ты через ручное тестирование или написание тестов.
⚠️ Не для тривиального кода: Если функция — 3-5 строк простой логики, двухшаговый подход избыточен. Прямой перевод будет быстрее и точнее. Метод сильнее всего на сложной логике (вложенные циклы, много условий, edge cases).
⚠️ Языково-специфичные библиотеки: NL-Specification описывает логику, но не подскажет какую библиотеку использовать в целевом языке. Если Python-код использует pandas, модель опишет логику преобразований, но выбор аналога в Java (Apache Commons, Stream API, etc) — на твоём усмотрении.
⚠️ Объём контекста: Для больших файлов (500+ строк) построчная NL-Specification может не влезть в контекст. Нужно делить на функции и переводить по частям.
Как исследовали
Команда протестировала BabelCoder на четырёх датасетах (Avatar, CodeNet, EvalPlus, TransCoder) с переводом между пятью языками: Python, Java, C++, C, Go. Взяли 2,107 примеров функций и файлов с тест-кейсами и сравнили с четырьмя baseline-методами: LIT (прямой перевод через GPT-4), UniTrans (перевод + автоматические исправления), TransAgent (multi-agent система без NL-Specification), InterTrans (перевод через несколько промежуточных языков).
Идея эксперимента: измерить Computational Accuracy (CA) — процент корректно переведённых программ, где "корректно" = проходят все оригинальные тест-кейсы. Это жёсткая метрика: код может компилироваться и выглядеть правильно, но если хоть один edge case сломан — считается ошибкой.
Ключевой результат: BabelCoder выиграл в 94% пар (датасет × язык), показав на 0.5-13.5% выше точность чем лучший baseline. Средняя точность — 94.16% против 86-92% у конкурентов. Особенно большой отрыв был на EvalPlus (задачи с edge cases) — там baseline проваливались на вложенных условиях, а BabelCoder благодаря NL-Specification правильно переводил логику.
Почему NL-Specification сработала? Исследователи вручную проанализировали 50 случаев, где baseline ошиблись, а BabelCoder исправил. В 76% случаев проблема была в semantic mismatch: baseline переводил синтаксически похоже, но логически неправильно (например, перепутал порядок проверок в условии или границы цикла). NL-Specification заставила модель явно описать логику — "сначала проверить X, потом Y" — и это предотвратило ошибки.
Неожиданная находка: Многошаговый подход InterTrans (Python → C → Java) иногда работал хуже чем прямой перевод, потому что ошибки накапливались на каждом шаге. BabelCoder показал, что один промежуточный шаг (NL-Specification) эффективнее нескольких языковых переводов, если этот шаг делает логику явной.
Практический инсайт: Когда LLM переводит код напрямую, она работает как "синтаксический транслятор". Когда через NL-Specification — как "понимающий интерпретатор". Второй подход медленнее (больше токенов), но точнее, особенно для сложной логики.
Адаптации и экстраполяции
🔧 Техника: Scope-based bug fixing для отладки кода
Исследование показало сильный приём для локализации багов через LLM: вместо поиска конкретной строки, определить SCOPE бага (категорию: Input Processing, Output Formatting, Variable Declaration, Loop, Conditional). Это применимо не только к переводу, но к любой отладке кода.
У меня баг в функции. Помоги локализовать scope проблемы.
Анализируй исходный код, ошибку и определи наиболее вероятную категорию бага:
1. Input Processing — парсинг, валидация входных данных
2. Output Formatting — формирование результата, преобразование типов
3. Variable Declaration — инициализация переменных, область видимости
4. Loop Blocks — логика циклов, границы, условия выхода
5. Conditional Blocks — условия if/else, порядок проверок
Код:
{код_с_багом}
Ошибка:
{описание_ошибки_или_неправильного_поведения}
Выведи:
- Категория scope (одна из пяти)
- Примерные строки кода (диапазон)
- Объяснение почему эта категория наиболее вероятна
Это полезно когда у тебя большая функция (50-100 строк) и непонятно где искать баг. Scope сужает поиск с "где-то в коде" до "скорее всего в обработке ввода, строки 5-12".
🔧 Техника: NL-Specification для рефакторинга легаси-кода
Принцип "код → естественное описание → новый код" работает не только для перевода между языками, но и для рефакторинга внутри одного языка.
У меня сложная легаси-функция, которую нужно рефакторить. Используем NL-Specification:
ШАГ 1: Создай построчную NL-Specification этой функции — опиши логику без привязки к текущей реализации.
ШАГ 2: Проанализируй NL-Specification и найди:
- Повторяющиеся паттерны (можно вынести в отдельные функции)
- Сложные вложенные блоки (можно упростить early returns)
- Неочевидную логику (нужны комментарии)
ШАГ 3: Перепиши функцию на {язык}, используя NL-Specification как спецификацию, но с улучшенной структурой.
Легаси-код:
{твой_код}
Здесь NL-Specification работает как промежуточное представление для осмысления логики. Когда ты видишь описание "выполнить действие A, потом действие B, потом действие C, потом снова действие A" — сразу очевидно, что action A дублируется. В коде это может быть размазано по 50 строкам и не бросаться в глаза.
Ресурсы
BabelCoder: Agentic Code Translation with Specification Alignment
Fazle Rabbi, Soumit Kanti Saha, Tri Minh Triet Pham, Song Wang, Jinqiu Yang
Concordia University (Canada), York University (Canada)
Исследование упоминает предшествующие работы: - Lost in Translation (LIT) — Pan et al., оценка переводов GPT - UniTrans — Yang et al., перевод с автоматическими тестами - TransAgent — система multi-agent перевода без NL-Specification - InterTrans — перевод через промежуточные языки программирования
Датасеты: AVATAR, CodeNet, EvalPlus (расширенный HumanEval), TransCoder
Код и датасеты: https://github.com/anonprox/babelcoder
