我们构建 Helix 是为了帮助大语言模型(LLM(大语言模型))用 Swift 和 Kotlin 重建 Shopify 应用,通过小型检查点和严格的质量门禁来确保代码可交付。

我们正在将移动应用从 React Native 迁回原生 Swift 和 Kotlin。我们已经在 Shop 上完成了这一迁移,仅用 12 周就重建并发布了该应用。现在我们正将经验应用到 Shopify App 上,这是我们最大的应用,拥有超过 300 个屏幕。
我们使用大语言模型(LLM)来重建它,因为它们现在确实非常强大;但要开箱即用地获得一致、高质量且可维护的结果是很困难的。它们需要工具和护栏。这就是我们构建 Helix 的原因。
Helix 是一套工具和技能,帮助大语言模型(LLM)从 React Native 应用迁移功能和屏幕,同时遵循我们为新原生应用设计的高度定制化架构。
大多数工具试图收集尽可能多的信息,将其转化为规格说明和任务文件,实现整个功能,然后期望第一次结果就能正常工作。工程师拿到一大块代码,所有内容都还有待测试。
Helix 采取了不同的方法。它不期望第一次输出就是正确的。它将工作分解,在过程中向工程师学习,并且每正确完成一步就自动化更多任务。目标是在保持高质量结果的同时,将工程师加速到以前不可能达到的速度。
那么,为什么这能奏效?Helix 构建了一个循环,在这个循环中,不完美的尝试无法向前推进,直到它变成好的结果。
一次迁移的工作流程如下:


Helix 将屏幕重建为原生代码,分为四个检查点
有两个理念让这一切得以运转:小到可以一眼审阅的检查点,以及严格到足以阻止任何未经证实内容的关卡。这背后是一套我们有明确主张的架构,并且我们已经对其进行了详尽文档化,以便审阅者有可执行的标准。让我们详细看看这两者。
Helix 迁移从现有的 React Native 代码和正在运行的应用开始。工程师选择目标——整个屏幕或单个子屏幕——Helix 将其拆分为复杂度递增的检查点。第一个检查点通常是屏幕骨架;第二个是一个刻意保持很小的部分。后续检查点只有在早期决策通过审阅后才会扩展。

每个检查点只用几个词来描述,这是有意为之。在这个阶段,工程师只需要检查顺序是否合理。没有人能有效审阅一整屏生成的文本。我们宁愿给某人一个可以做出的决定,而不是十页他们只会略读的内容。
小检查点也能放进较小的上下文窗口,让智能体可以直接阅读参考代码的相关部分,而不是依赖庞大的规格文件或任务列表来代表代码。参考代码就是规格。
在幕后,一个子智能体会阅读参考代码并为每个检查点生成测试用例。这些测试用例作为集成测试运行,从用户视角描述并测试该功能。这些测试是一个机会,可以引导智能体更深入地研究该功能,发现正常路径之外的边缘情况。这确保每个检查点都得到彻底审阅。
每个检查点都必须达到我们的质量标准,智能体才能继续推进。Helix 通过确保每个检查点按顺序通过四个关卡来强制执行这些标准。

如果某个关卡失败,智能体会使用反馈来修复实现,然后再次运行检查。它可以根据需要重试任意多次,但不能仅仅因为自己认为结果足够好就覆盖失败的检查。
我们的 CLI 暴露与应用程序相同的屏幕状态和操作。例如,主屏幕可能会暴露分析信息以及导航到应用程序其他部分的操作。智能体分析参考应用的工作方式,复现它,并通过 CLI 行为测试验证功能。为检查点生成的测试用例定义了“已证实”的含义,并且每个相关用例都必须通过。

CLI 不需要模拟器,这使得这个循环很快。智能体可以在截取一张屏幕截图之前,对行为进行数十次迭代。

这是 Helix 最有趣的部分,也是输出结果能够如此接近 1:1 的主要原因。
UI 等价性几乎无法被精确描述。当标题太小、分隔线太深或图标略有偏差时,人类能立刻察觉,但这些细节几乎从不会出现在提示词中。像素级对比也不可行,因为两个 UI 框架不会产生字节完全一致的输出。
在训练智能体操作模拟器的过程中,我们发现当前的 Gemini 模型对这类问题具有非常好的空间感知能力。它们能够捕捉到多种 UI 细微差异,例如 margin / padding 问题,并估算差异程度。因此我们围绕它构建了一个关卡。编排器(GPT)在匹配状态下截取实现截图和参考截图,然后让 Gemini 充当一位完美主义的设计审查者,检查结构、间距和对齐等细节。它根据每张截图的尺寸按比例判断大小,因此也能检测出文字过小或过大的问题。
Gemini 必须列出它发现的每一处差异,每处差异都附带严重程度和屏幕上的位置。如果某个视觉差异可以通过代码修复,该关卡默认将其视为阻塞项。
如果编排器发送的是不同区域或不同状态的截图,Gemini 也可以将比较标记为 INVALID。例如,一张截图可能显示未完成的订单,另一张显示已完成的订单。编排器随后会在相同状态下截取两个应用,并重新运行比较。

编排器将每次比较限制在检查点已构建的范围内。对于骨架检查点,它可能只要求审查者检查导航栏和标题,因为参考应用有完整屏幕,而新应用还没有。检查范围随着每个检查点逐步扩大。
首次渲染不需要完美。系统能够看到问题所在、描述问题、定位问题,并要求再次尝试。这比在实现开始前试图指定每一个视觉细节要可靠得多。
假设智能体让一切正常运行,并且看起来几乎像素级完美。但底层代码可能仍然很差,这个关卡的存在就是为了捕捉这种情况。
我们投入建设了一种便于智能体实现的架构,并对其进行了详尽文档化。这份文档使对抗性审查变得可执行。两个独立且上下文隔离的审查智能体根据文档检查新代码,包括拥有自身指南的 UI 代码。每一处发现都必须修复。修复后重新运行受影响的测试,如果有任何可见变化,UI 审查关卡也会再次运行。
随后审查者再次检查修改后的代码。这个循环重复进行,直到两位审查者都批准为止。

当一个检查点到达工程师手中时,它已经处于良好状态:UI 与参考设计几乎 1:1 一致,代码遵循规范,行为已通过测试验证。这个循环迫使它达到这一标准。
工程师查看代码和运行中的应用,判断结果是否符合预期。他们的反馈流向两个地方:智能体处理反馈并重新运行关卡,Helix 将其记录到记忆中,以改进后续每一个检查点。

这种记忆使得迁移过程中的自主性可以逐步增长。早期检查点需要更多工程师关注,因为不确定性高且可学习的已批准工作很少。随着已批准的代码和反馈不断积累,后续检查点可以在更少监督下运行,如果工程师选择自主模式,有些检查点甚至可以完全跳过审批。
每个检查点最终都会产生一次提交,大多数工程师从那里开始创建分支并提交 PR。
这让 Helix 对工程师更友好。一次性工具把所有工作都堆到最后:工程师必须审查一个庞大且不确定的 diff,涵盖产品行为、视觉保真度、两个平台和架构。Helix 将反馈移到最早的有用节点。智能体处理重复的实现工作、运行检查并回应审查者。工程师可以专注于范围、产品判断和品味,同时引导那些已经过验证的小改动,使其成为下一个改动的基础。
虽然默认情况下工程师审批是强制性的,但这可以更改。可以要求 Helix 一次性完成接下来的三个检查点,或完全跳过审批,它就能持续工作数小时甚至整夜。而且即使无人监督,关卡也不会变得宽松。每个检查点仍然必须证明其行为、通过 UI 审查,并满足两位对抗性审查者的要求,才能开始下一个检查点。
迁移也可以并行运行。Helix 不限于一次处理一个屏幕,因此多个屏幕可以同时进行,并通过各自的关卡独立收敛。
自主运行结束后,Helix 会提供一系列已提交的检查点供审查,而不是一个巨大的 diff。每个检查点都附带证据:归档的 UI 审查、通过的测试和审查者结论。
这个循环中的任何内容都不是迁移特有的。对于新功能,Helix 可以使用设计稿和产品文档作为参考,并遵循相同的流程。它也可以用相同的检查点和关卡策略来处理架构迁移和重构。仅涉及逻辑的变更只需跳过 UI 审查关卡。
这是 Helix 带来的真正教训。我们不再为完美的首次尝试而优化,而是开始致力于可靠的收敛。一次尝试可以出错,但在它不出错之前,不允许发布。
随着我们将应用从 React Native 迁移到原生,我们会继续分享所学到的经验。如果你想帮助构建 Shopify 的下一代移动应用,我们正在招聘移动工程师、基础设施工程师,以及在 AI 与软件工程交叉领域工作的开发者。
转载声明:本文为转载整理,原文版权归原作者及原站点所有。
原文来源:Shopify Engineering
原文作者:Shopify Engineering;如有侵权,请联系管理员删除。