每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领域的领跑者。点击订阅,与未来同行! 订阅:https://rengongzhineng.io/
生成式AI驱动的工作流程使Google能够更快地迁移代码并更有效地维护代码库
过去几十年,源代码库的规模呈指数级增长。Google的monorepo(单一代码库)就是一个包含数十亿行代码的大型代码数据集的例子。为了适应新的语言版本、框架更新、API和数据类型的变化,对整个庞大代码库进行代码变更(称为“迁移”)的工作极其具有挑战性。
多年来,Google一直使用特殊的基础设施进行大规模的代码迁移。该基础设施利用静态分析和工具如Kythe和Code Search来发现需要更改的位置及其依赖关系,然后使用ClangMR等工具进行更改。
这种方法在结构统一、边缘情况有限的代码变更中效果良好。然而,当迁移具有复杂结构的代码时,例如更改接口及其在多个组件中的使用或更新其测试时,静态分析和简单的迁移脚本会遇到限制。
Google内部介绍了一种新工具,结合了多项AI驱动的任务,帮助Google开发人员进行大规模代码迁移。其目标是辅助工程师,让他们专注于迁移中的复杂方面,而不会将他们从过程中隔离开来。案例研究表明,这种方法可以成功生成迁移所需的大部分新代码,并显著减少人工工作量。
代码迁移工作流程
为了代码迁移,Google构建了一个新的、互补的工具包,以解决标准工具难以处理的变更,并且利用机器学习(ML)模型的能力适应周围代码。
Google将迁移过程概念上分为三个阶段:
- 定位需要修改的代码库位置
- 生成和验证编辑
- 审查和推广更改
尽管每个阶段都能从AI中受益,重点关注第二阶段。
为了生成和验证代码更改,Google利用了经过内部代码和数据微调的Gemini模型版本。
每次迁移需要以下输入:
- 需要更改的位置文件集:文件路径+行号
- 一个或两个描述更改的提示
- [可选]少量示例以决定文件是否需要迁移
用户提供的位置通过结合现有静态工具和人工输入收集。迁移工具包会自动扩展这组文件,包括测试文件、接口文件和其他依赖项。这一步尚未由AI驱动,而是使用符号交叉引用信息。
在许多情况下,用户提供的迁移文件集并不完美。因为过滤输入列表可能非常繁琐,通常会有一些文件已经部分或完全迁移。因此,为了避免重复更改或在编辑生成期间混淆模型,提供少量示例并要求模型预测文件是否需要迁移。
编辑生成和验证步骤是自动系统最有利的地方。模型根据DIDACT方法论训练,使用Google monorepo和相关数据。在推理时,在预期需要更改的每一行标注自然语言指令和模型的一般指令。在每次模型查询中,输入上下文可以包含一个或多个相关文件。
模型预测文件之间的差异(diffs)并更改相关部分,以确保最终代码正确。
这种能力对于加快迁移速度至关重要,因为生成的更改可能与最初请求的位置不一致,但它们会解决意图问题。这减少了手动查找所有需要更改行的需求,相比纯粹基于抽象语法树修改的确定性更改生成是一个巨大的进步。
例如,提示模型仅更新需要更改类型的类的构造函数。在预测的统一diff中,模型还正确修复了类中的私有字段和用法。
不同的提示组合会根据输入上下文产生不同的结果。在某些情况下,提供过多预期更改的位置会导致性能下降,而仅在文件中指定一个位置并提示模型全局应用更改效果更好。
在对数十甚至数百个文件应用更改时,Google实施了一种机制,生成针对每个文件组并行尝试的提示组合。这类似于pass@k策略,在这种情况下,Google不是修改推理温度,而是修改提示策略。
Google自动验证生成的更改。验证是可配置的,通常取决于迁移。最常见的两种验证是编译更改的文件和运行它们的单元测试。每个失败的验证步骤可以选择运行ML驱动的“修复”。模型也已针对大量失败的构建和测试数据以及相应修复的diffs进行了训练。对于遇到的每个构建/测试失败,Google会提示模型更改文件、构建/测试错误,并请求修复。通过这种方法,观察到模型在大量情况下能够修复代码。
由于为每个文件组生成多个更改,Google根据验证对其进行评分,最后决定将哪个更改集传播回最终更改列表(类似于Git中的拉取请求)。
案例研究:将整数从32位迁移到64位
随着Google代码库及其产品的发展,过去(有时超过十年前)做出的假设不再成立。例如,Google Ads有数十种用于用户、商家、广告活动等的唯一“ID”类型,这些ID最初定义为32位整数。但由于当前ID数量的增长,预计它们会比预期更早溢出32位容量。
这一认识导致了一项重大工作,即将这些ID迁移到64位整数。该项目困难重重:
- 数万个位置跨越数千个文件使用这些ID。
- 如果每个团队各自处理数据中的迁移,跟踪所有相关团队的更改将非常困难。
- 这些ID通常被定义为通用数字(在C++中为int32_t,在Java中为Integer),而不是唯一的、易于搜索的类型,通过静态工具找到它们的过程并不简单。
- 需要考虑跨多个文件的类接口更改。
- 需要更新测试以验证64位ID的正确处理。
- 如果手动完成,整个工作预计需要许多年的软件工程时间。
为了加快工作进度,Google使用了AI迁移工具,并制定了以下工作流程:
- 专家工程师识别要迁移的ID,并使用Code Search、Kythe和自定义脚本的组合,确定相对紧密的待迁移文件和位置集合。
- 迁移工具包自主运行,生成通过单元测试验证的更改。有些测试本身也会更新以反映新现实。
- 工程师快速检查更改,可能会更新模型失败或出错的文件。然后将更改分片,并发送给受更改影响代码库部分的多个审阅者。
需要注意的是,内部代码库中使用的ID已经应用了适当的隐私保护。在模型将它们迁移到新类型时,不会更改或公开它们,因此所有隐私保护将保持不变。
在这项工作流中,发现着陆的变更列表(CLs)中80%的代码修改由AI创作,其余由人类创作。工程师报告称,迁移总时间减少了约50%。沟通开销显著减少,因为单个工程师即可生成所有必要的更改。工程师仍需要花时间分析需要更改的文件并进行审查。发现,在Java文件中,模型预测文件需要编辑的准确率为91%。
该工具包已用于创建数百个变更列表,涉及此次及其他迁移。平均而言,成功在monorepo中着陆的AI生成字符更改超过75%。
未来方向
下一步是处理影响多个组件交换数据或需要系统架构更改的更复杂迁移。Google已经在迁移需要非平凡重构的弃用类型以及从旧测试框架迁移中取得了成功。
Google正在研究如何在开发过程的其他部分应用AI,特别是帮助定位更改和更好地过滤不必要的更改。另一个有趣的领域是改进IDE中的迁移用户体验,使变更操作员能够更自由地混合和匹配现有工具。
总的来说,Google看到这项工作的广泛潜在应用,可能超越严格的代码迁移空间,并可能应用于错误修正和大规模的常规代码维护。