想象一下,你正试图将一份复杂的食谱从一种语言(如法语)翻译成另一种语言(如日语)。你拥有原始食谱(即源代码),但你知道,有时仅凭查看法语单词还不足以让日语翻译完美无缺。你可能需要一个中间步骤:用简单、通俗的英语描述该食谱的意图(即自然语言规范)。
本文提出了一个重大问题:添加这个“通俗英语”中间步骤,是否真的能帮助大语言模型(LLM)更好地翻译代码?
以下是他们研究发现的分解,使用了日常类比:
设置:三种翻译方式
研究人员测试了三种不同的方式,要求 AI 翻译代码:
- 直接方法:“这是法语食谱。将其翻译成日语。”(仅源代码)
- 摘要方法:“这是食谱的通俗英语摘要。现在写出日语版本。”(仅自然语言规范)
- 混合方法:“这是法语食谱,以及通俗英语摘要。将其翻译成日语。”(源代码 + 自然语言规范)
他们用许多不同的“语言”(Python、C++、Java 等)和不同的 AI 模型进行了测试。
大惊喜:中间人并不总是有帮助
你可能会认为,拥有一个清晰、简单的摘要总会带来帮助。事实并非如此。
- “仅摘要”陷阱:当 AI 尝试仅根据通俗英语摘要(而未查看原始代码)进行翻译时,它经常失败。这就像试图仅凭口头描述重建一台复杂的机器;你会丢失具体细节(如螺丝的确切尺寸或操作顺序)。AI 失去了正确完成所需的“结构上下文”。
- “混合”最佳点:将摘要与原始代码一起添加,在某些特定情况下有所帮助,但并非所有情况。
- 何时有效:这就像一位乐于助人的导游。对于复杂、混乱的代码(尤其是Python和C++),摘要充当了“去噪过滤器”。它帮助 AI 忽略令人困惑的语法,专注于主要思想。
- 何时失效:对于非常严格或冗长的语言(如C或Java),摘要往往会丢弃关键的底层细节(如内存管理)。在这些情况下,摘要实际上使翻译变得更糟,因为它隐藏了重要规则。
结论:“直接方法”(仅源代码)实际上在整体上最为可靠。摘要是一个“补充信号”——它有助于解决特定问题,但它并非适用于所有情况的灵丹妙药。
“垃圾进,垃圾出”问题
研究人员发现,翻译的质量完全取决于摘要的质量。
- 良好场景:如果 AI 生成了完美、准确的摘要,翻译质量就会提高。
- 糟糕场景:如果 AI 在摘要中犯了一个小错误(例如算错了一个数学步骤),该错误就会被固化到最终代码中。AI 会忠实地遵循错误的指令,就像厨师遵循有缺陷的食谱一样。
“维修店”
研究的一个重要部分是修复错误。他们发现,许多翻译失败仅仅是“拼写错误”或小语法错误(例如缺少分号)。
- 他们构建了一个系统,充当代码的拼写检查器。如果翻译无法编译,AI 会被要求修复特定错误。
- 结果:这个简单的“修复步骤”修复了大量错误(将准确率提高了约 6–8%)。这表明 AI 通常理解逻辑,但只是在语法上出错。
质量检查(SonarQube)
最后,他们使用名为 SonarQube 的工具检查了翻译代码的“卫生状况”(该工具扫描安全漏洞和不良实践)。
- 发现:翻译方法并没有显著改变代码的“整洁”程度。
- C 语言激增:然而,他们注意到,翻译为 C 语言会导致显著更多的安全警告(如不安全的内存访问)。似乎无论是否使用摘要,AI 都难以遵循 C 语言严格的安全规则。
面向普通受众的总结
将这项研究想象成测试一个机器人团队的翻译新策略。
- 旧方法:机器人查看原始文本并猜测翻译。
- 新方法:机器人先阅读摘要,然后进行翻译。
- 结论:当原始文本令人困惑时,摘要有用,但当文本非常技术性或精确时,它往往有害。最佳策略通常是坚持使用原始文本,但将摘要作为棘手之处的备用方案。而且,就像人类编辑一样,机器人需要在最后进行“拼写检查”步骤,以捕捉他们的小错误。
该论文得出结论,虽然使用自然语言摘要是一个有趣的想法,但它并不能取代对原始代码的需求。它是一个有用的工具,但只有在谨慎使用并应用于正确情境时才有效。
技术摘要:由大型语言模型驱动的规范驱动代码翻译
1. 问题陈述
将遗留代码库迁移到现代编程语言是软件工程中一项关键但极具挑战性的任务。虽然大型语言模型(LLM)在代码生成和翻译方面已展现出强大的能力,但现有方法主要将翻译视为一种保留语法的转换,几乎完全依赖源代码。这往往限制了模型捕捉高层程序意图的能力,尤其是对于语义复杂的代码。
本文研究了使用自然语言(NL)规范作为中间表示是否能改善代码翻译。虽然自然语言是 LLM 训练的主要模态,也是表达程序意图的自然方式,但目前尚不清楚将代码转换为自然语言再转换为目标语言(或在源代码之外使用自然语言),是否比直接的源到目标翻译具有普遍的性能优势,或者这些优势是否高度依赖于上下文。
2. 方法论
实验设计
本研究评估了三个数据集(Avatar-Verified、CodeNet和EvalPlus),涵盖五种编程语言(C、C++、Go、Java、Python)以及 29 种语言对排列。实验使用了三种不同的 LLM:GPT-4(闭源)、DeepSeek-Coder和Magicoder-S-DS-6.7B(开源)。
工作流程
所提出的工作流程包含三个主要阶段:
- NL 规范生成:LLM 根据源代码生成类伪代码的自然语言规范。提示敏感性研究表明,基于伪代码的提示(结构化、逐行描述,保留控制流和变量更新)优于抽象的自然语言描述。
- 翻译策略:研究比较了三种提示策略:
- 仅源代码:直接从源代码翻译到目标语言。
- 仅 NL 规范:仅根据生成的 NL 规范翻译到目标语言(不使用源代码)。
- 混合模式:同时使用源代码和生成的 NL 规范进行翻译。
- 迭代修复:为了隔离输入表示的影响,研究采用了一个自动化修复流程,仅限于修复编译错误、测试不匹配、运行时错误和无限循环。针对每种错误类型,LLM 最多允许进行三次修复迭代。
评估指标
- 计算准确性(CA):通过所有相应测试用例的翻译代码的百分比。
- 代码质量:使用SonarQube分析,统计“阻塞(Blocker)”和“严重(Critical)”级别的问题数量(按每 1,000 行非注释代码标准化),以评估语义和安全缺陷。
- 统计分析:使用成对显著性检验(经 Holm-Bonferroni 校正的 McNemar 精确检验)和效应量分析(Cliff's delta)来确定策略的互补性。
3. 主要贡献
- NL 规范的实证特征:本研究系统地评估了 NL 规范作为中间表示的效果,发现它们并不能普遍提高翻译准确性。
- 条件有效性:研究指出,NL 规范仅对特定的源语言( notably Python和C++)和特定的语言对有益。对于其他语言(如 C、Go),这种抽象往往导致信息丢失和性能下降。
- 质量与错误分析:本文提供了对失败模式的详细分析,表明生成的 NL 规范中的错误会确定性地传播到最终翻译中。研究还强调,与其他语言相比,C 语言翻译表现出显著更高的缺陷密度(安全和内存问题)。
- 修复影响:研究量化了翻译后修复的影响,结果显示,仅修复编译错误即可使“仅 NL 规范”方法的准确性平均提高8.5%,使混合方法的准确性平均提高6.1%。
4. 主要结果
翻译准确性(RQ1 & RQ2)
- 仅源代码基线:在所有数据集和模型中,仅源代码方法实现了最高的平均翻译准确性。
- 混合方法:将 NL 规范与源代码结合,在某些语言对(例如 Python 到其他语言,C++ 到其他语言)中带来了改进,但在所有排列中并未始终优于仅源代码的基线。
- 仅 NL 方法:与仅源代码翻译相比,单独使用 NL 规范始终降低了性能,这表明从代码到 NL 的转换引入了信息丢失,特别是在低级操作和特定于语言的构造方面。
- 成功与失败:当 NL 规范正确简化了复杂逻辑时(例如 Python 中的同时元组赋值),它们起到了帮助作用。然而,当生成的规范不正确时(由于 LLM 推理能力的限制),错误会传播到目标代码,使得翻译效果比仅源代码更差。
代码质量(RQ3)
- 问题密度:不同策略(仅源代码与混合模式)之间以及修复前后的严重(阻塞/严重)问题数量基本保持不变。
- 特定于语言的缺陷:
- C/C++:涉及 C 的翻译显示出缺陷显著激增(通常每 1,000 行非注释代码超过 30 个),主要与不安全的内存访问、受污染的值以及不可重入函数的使用(例如
strtok)有关。
- Go:主要由无效变量名和高认知复杂度主导。
- Java:问题集中在日志记录实践和命名约定上。
- Python:频繁出现潜在的索引错误。
- 源语言影响:源语言对目标语言中问题的类型影响微乎其微;目标语言的具体范式和标准决定了缺陷的分布。
5. 意义与主张
本文适度主张,在代码翻译任务中,NL 规范不应被视为源代码的通用替代品。相反,它作为一种互补信号,可以扩展特定、逻辑密集型场景(特别是涉及 Python 和 C++ 源代码时)的覆盖范围,但如果规范生成不准确,则可能导致性能下降。
对从业者的关键启示:
- 采用“源代码优先”的工作流程:将仅源代码翻译作为主要步骤。
- 针对性回退:仅在复杂逻辑或已显示增益的特定语言对中,将 NL 规范方法作为回退方案使用。
- 上下文至关重要:NL 规范的优势取决于生成规范的正确性以及源语言的性质。
- 修复必不可少:自动化修复编译和运行时错误是恢复正确性的关键步骤,特别是在使用中间表示时。
研究结论指出,虽然多跳或中间表示策略(如 InterTrans)可能通过大量的模型调用实现更高的准确性,但直接的源到目标方法总体上仍最为稳健。未来的工作应致力于提高规范的保真度,并将这些发现整合到仓库级翻译系统中。
每周获取最佳 computer science 论文。
受到斯坦福、剑桥和法国科学院研究人员的信赖。
请查收邮箱确认订阅。
出了点问题,再试一次?
无垃圾邮件,随时退订。