3,583 papers
arXiv:2512.06902 77 7 дек. 2025 г. FREE

BabelCoder: перевод кода через естественно-языковое описание логики

КЛЮЧЕВАЯ СУТЬ
Парадокс: LLM лучше переводит Python→Java через промежуточный шаг — сначала превратить код в описание логики словами, потом описание в целевой язык. Прямой перевод даёт код который компилируется, но ломается на edge cases (пустые строки, спецсимволы). Метод BabelCoder позволяет переводить сложную логику с вложенными циклами и условиями между языками так, чтобы работало одинаково — не копируя синтаксис исходника. Фишка: NL-Specification (описание логики на естественном языке) разрывает связь между синтаксисами. Модель не может механически скопировать структуру Python в Java — она должна понять намерение и выразить его идиоматично для целевого языка. Точность 94.16% на бенчмарках vs типичные 60-70% при прямом переводе.
Адаптировать под запрос

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


📋 Дайджест исследования

Ключевая суть

Парадокс: LLM лучше переводит Python→Java через промежуточный шаг — сначала превратить код в описание логики словами, потом описание в целевой язык. Прямой перевод даёт код который компилируется, но ломается на edge cases (пустые строки, спецсимволы). Метод BabelCoder позволяет переводить сложную логику с вложенными циклами и условиями между языками так, чтобы работало одинаково — не копируя синтаксис исходника. Фишка: NL-Specification (описание логики на естественном языке) разрывает связь между синтаксисами. Модель не может механически скопировать структуру Python в Java — она должна понять намерение и выразить его идиоматично для целевого языка. Точность 94.16% на бенчмарках vs типичные 60-70% при прямом переводе.

Принцип работы

Не гони код напрямую из языка в язык — заставь модель сначала пересказать логику словами. Формат: каждая строка кода → одно предложение на человеческом языке без синтаксиса. Например, for x in items if x > 0 превращается в «Для каждого элемента из списка: если элемент положительный, обработать». Потом переводишь не Python-код, а это описание в Java — модель генерирует идиоматичный код целевого языка, потому что не видит исходный синтаксис. После перевода — валидация: сравниваешь описание логики и финальный код построчно. Если «описание говорит обработать пустые строки отдельно», а в коде этого нет — несоответствие очевидно.

Почему работает

LLM при прямом переводе страдает от синтаксической слепоты. Видит for x in list — думает «цикл», переводит в for (x : list) механически, но не анализирует тело цикла и можно ли выразить это по-другому. Модель цепляется за структуру исходного языка, тащит его идиомы в целевой (Python list comprehension → Java stream API, хотя простой цикл правильнее). Естественный язык — core-компетенция LLM. Когда модель видит описание «если элемент больше текущего максимума, обновить максимум», она понимает намерение чище, чем когда парсит if arr[i] > max_val. Промежуточное описание логики заставляет модель думать о семантике («что делает код»), а не о синтаксисе («как написано»). В исследовании на задачах с вложенными условиями прямой перевод давал 67% корректных программ, через NL-Specification — 94%.

Когда применять

Перевод кода между языками (Python ↔ Java, C++, Go) → конкретно для функций со сложной логикой, особенно когда много вложенных циклов, условий, обработка edge cases (пустые данные, спецсимволы, границы диапазонов). Сильно на корпоративных задачах: портирование легаси Python-скриптов в Java для интеграции в enterprise-систему, миграция C++ алгоритмов в Go для микросервисов. НЕ подходит для тривиального кода на 3-5 строк — там прямой перевод быстрее и достаточен.

Мини-рецепт

1. Создай NL-Specification: Возьми исходный код и опиши каждую строку словами. Формат — «Если условие X, то действие Y». Сохрани структуру через отступы (вложенность блоков). Без упоминания синтаксических конструкций исходного языка (list comprehension, lambda, stream API).

2. Переведи описание: Дай модели NL-Specification (НЕ исходный код) и попроси перевести в целевой язык. Укажи: «Используй идиоматичный стиль для {язык}».

3. Валидация построчно: Сравни NL-Specification и переведённый код. Для каждой строки описания проверь: есть ли соответствующая логика в коде? Если описание говорит «обработать пустую строку отдельно», а в коде нет проверки — несоответствие, исправь.

4. Опционально — тесты: Если можешь запустить код, сгенерируй тест-кейсы (corner cases: пустой массив, один элемент, все одинаковые значения). Прогони исходный код → получи эталонные результаты. Прогони переведённый → сравни. Если не совпадает — локализуй баг (Input Processing / Output Formatting / Loop / Conditional) и исправь через модель.

Примеры

[ПЛОХО] : Переведи эту Python-функцию в Java + вставка кода → модель напрямую копирует структуру, получается Java-код который компилируется, но неправильно обрабатывает пустые строки
[ХОРОШО] : Используем двухшаговый подход. ШАГ 1: Создай NL-Specification — построчное описание логики на естественном языке, без синтаксиса Python. Формат: отступы показывают вложенность, описывай ЧТО делает строка, не КАК написано. Вот код: [вставить]. ШАГ 2: Переведи NL-Specification (не исходный Python-код) в Java. ШАГ 3: Проверь построчно — соответствует ли Java-код описанию логики? Если есть расхождения, исправь. → модель выдаёт три блока: описание логики, Java-код на основе описания (не копия Python-синтаксиса), проверка соответствия с указанием расхождений
Источник: BabelCoder: Agentic Code Translation with Specification Alignment
ArXiv ID: 2512.06902 | Сгенерировано: 2026-01-08 22:22

Проблемы LLM

ПроблемаСутьКак обойти
Модель копирует синтаксис вместо понимания логикиПереводишь код между языками. Модель видит структуру исходника и переносит её буквально. Python-код с list comprehension Java через stream API, хотя простой цикл был бы правильнее. Модель парсит "как написано", но не всегда понимает "что делает". Особенно заметно в сложной логике — путает границы блоков, порядок операций. Проблема: перевод компилируется, но работает неправильно на граничных случаяхНе переводи напрямую. Сначала попроси модель описать логику кода словами (построчно, без синтаксиса). Потом переведи ЭТО описание в целевой язык. Промежуточный шаг через естественный язык заставляет модель думать о смысле, а не о синтаксисе

Методы

МетодСуть
Двухшаговый перевод кода через описание логикиШаг 1: Попроси модель создать описание на естественном языке — что делает каждая строка кода. Формат: сохрани отступы (показывают вложенность), опиши ЧТО делает строка, не КАК написано синтаксически. Без упоминания конструкций исходного языка. Шаг 2: Переведи описание (не исходный код!) в целевой язык. Шаг 3: Сравни построчно — описание vs переведённый код. Если логика расходится — исправь. Почему работает: Модель отлично генерирует код из естественно-языковых описаний — это её core-компетенция. Промежуточное представление разрывает связь "синтаксис исходника синтаксис цели". Модель не может механически скопировать структуру, она должна понять и пересказать. Когда применять: сложная логика (вложенные циклы, много условий, обработка граничных случаев), перевод между языками с разными парадигмами (Python Java, функциональный императивный). Когда не работает: тривиальный код (3-5 строк), прямой перевод быстрее и точнее
📖 Простыми словами

BabelCoder: перевод кода через естественно-языковое описание логики

arXiv: 2512.06902

Прямой перевод кода из Python в Java — это ловушка, в которую попадают даже топовые нейронки. Проблема в том, что модели страдают синтаксической слепотой: они видят структуру строк, но не вдупляют в саму логику. В итоге получается «код с акцентом» — когда программа на C++ выглядит и ведет себя как кривой перевод с Python, спотыкаясь на типах данных или управлении памятью. BabelCoder меняет правила игры, вводя промежуточный слой — NL-Specification. Это когда код сначала пересказывается на человеческом языке как детальная инструкция, а уже потом эта инструкция превращается в целевой язык.

Это как если бы ты переводил стихи с китайского на русский. Если переводить слова в лоб, получится бессвязная чушь. Правильный путь — сначала понять смысл и образы, записать их прозой, а уже потом заново собрать из этого рифмованный текст на другом языке. В программировании это работает так же: мы отрываемся от синтаксиса оригинала, чтобы не тащить его ошибки в новый код. Формально всё на месте, но дьявол в деталях, и именно эти детали BabelCoder вытаскивает через «человеческое» описание.

Внутри системы пашут три агента, которые не дают друг другу халтурить. Переводчик набрасывает код, тестировщик генерирует проверки и ищет баги, а рефайнер (шлифовщик) исправляет косяки, пока тесты не пройдут. Главная фишка здесь — выравнивание спецификации. Если в Python-скрипте была хитрая регулярка для парсинга логов, агент-тестировщик не просто смотрит, компилируется ли Java-код, он проверяет, выдает ли он тот же результат на краевых кейсах. Это превращает процесс из слепого копирования в осознанное переписывание с проверкой фактов.

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

Короче, хватит надеяться, что ChatGPT просто «поймет» твой код и выдаст рабочий аналог на другом языке. Без промежуточного этапа осмысления и итеративной проверки тестами ты получишь неработающий мусор в красивой обертке. BabelCoder доказывает: чтобы код работал правильно, нейронка должна сначала объяснить его сама себе словами. Кто продолжит переводить «в лоб», тот так и будет тратить недели на поиск фантомных багов, возникших из-за разницы в архитектуре языков.

Работа с исследованием

Адаптируйте исследование под ваши задачи или создайте готовый промпт на основе техник из исследования.

0 / 2000
~0.5-2 N-токенов ~10-30с
~0.3-1 N-токенов ~5-15с