网盘存量代码迁移实战:我们如何用三层架构管住 AI 的输出

导读 introduction

复杂工程场景下,AI 不是一个"问一句答一句"的黑盒,而是一套需要被精心设计的技术体系。本文以网盘 Android 存量代码转 KMP 项目为实践载体,分享 Skill、SubAgent、Agent Team 三项 AI 技术的应用心得------它们分别回答"怎么稳定执行"、"怎么调度不失控"、"怎么协作提效"三个层次的问题,组合起来,构成一套从原子执行到并行协作的完整方案。

前言

我们用 AI 助力网盘存量代码迁移,走完这段路才真正搞明白一件事:

让 AI 持续产出可用东西,靠的不仅是更好的 Prompt,还需要一套能管住它的工程结构。

这篇文章不讲概念,只讲我们在真实项目里踩过的坑、走通的路,以及最终沉淀下来的三层架构方案。

01 存量代码向 KMP 迁移:AI 接入的背景与挑战

网盘主端积累了大量存量代码,在推进 KMP 多端复用的过程中,面临的核心挑战不是"能不能迁",而是"迁得稳不稳"。

一个页面的迁移通常涉及 UI 层、布局文件、业务逻辑和资源文件,各模块依赖关系错综复杂,稍有遗漏就会在后续编译阶段集中暴露问题。如果靠人工逐文件梳理,效率低、遗漏率高;靠 AI 直接生成,又容易出现"看起来能跑,接进工程就不行"的情况。

我们最早的做法是直接让 AI 协助迁移,但很快发现几个规律性的问题:

  • 同一类操作,不同对话结果不一样。AI 每次都在重新理解任务,上下文稍有变化,输出就漂移;

  • 任务越复杂,后期幻觉越多。迁移一个页面要加载几十个文件,到后期早期的文件细节被压缩,AI 开始生成"不存在的方法";

  • 并行处理没有机制支撑。UI、布局、业务逻辑本可以同时处理,但只有一个对话窗口,只能串行,效率上不去。

这三个问题,最终对应了我们后来落地的三个方向:Skill、SubAgent、Agent Team。

02 三层方案全貌:Skill、SubAgent 与 Agent Team 如何协作

在讲每一层具体怎么做之前,先把整体方案的轮廓摆出来。

我们最终形成的是三层组合:Skill 负责执行、SubAgent 负责调度、Agent Team 负责协作。三者不是替代关系,而是分别解决不同层次的问题。

执行层 · Skill

解决:单点执行不稳定

位置:所有具体任务的执行单元

调度层 · SubAgent

解决:长链路上下文膨胀

位置:转化阶段的串行步骤调度

协作层 · Agent Team

解决:多类型任务串行效率低

位置:提取阶段的并行分工

整个迁移流程分两个大阶段:提取阶段 用 Agent Team 四路并行,把一个页面涉及的 UI、布局、业务逻辑、资源同时提取;转化阶段用 SubAgent 串行推进,按模块生成 → 资源转化 → 业务代码迁移 → UI 转化的顺序依次执行,步骤之间通过 Memory 传递关键产出。两个阶段的每个执行节点,都由 Skill 来保证输出的稳定性。

选型的判断依据只有一条:任务之间有没有强依赖

  • 任务之间有依赖、需要串行 → SubAgent

  • 任务之间无强依赖、可以并行 → Agent Team

  • 具体的执行动作 → Skill

整个方案的稳定性,最终由 Skill 的规范质量决定。SubAgent 和 Agent Team提供的是调度骨架,骨架上每个节点能不能稳定输出,取决于 Skill 本身有没有真正约束执行过程,而不只是描述了执行目标。

接下来分别展开每一层是怎么做的、做的过程中踩了哪些坑。

03 Skill:先解决"同一件事做十遍结果不一样"

为什么输出会不稳定?

最开始我们以为是 Prompt 写得不够好,于是反复调整措辞,有时候有用,有时候没用。后来想清楚了:AI 每次都在"重新理解"任务,上下文不同、表达方式略有差异,它对任务的理解就不一样,输出自然不稳定。

这不是模型的问题,是我们没有把"这件事怎么做"固化下来。

Skill 解决的就是这件事:把一类任务的执行方式写成可复用的规范文件,AI 调用时按规范走,不再每次重新理解。它是无状态的,没有对话历史,只做一件事------被调用时稳定输出。

写 Skill 最有用的一个动作:加 Checklist

我们试过只写"你需要做什么",试过写"参考以下示例",最后发现最有效的约束是 Checklist------把每个步骤拆成可以逐项打勾的检查项。

AI 在多步骤任务里很容易跳步,不是不会,是在执行序列里漏掉了某个环节。有了 Checklist,每完成一步对照一项,遗漏率明显下降。

另一个有效做法是分层管理文件:核心规则放主文件,边界情况和细节处理放 references 目录。Skill 文件一旦太长,AI 的注意力会分散,关键规则被稀释。

代码提取中的一个关键决策:把提取和校验拆开

存量代码提取的难点在于力度控制------提少了依赖链路断,提多了包体膨胀,靠感觉很难把握。

一开始我们把提取和校验写在同一个 Skill 里,结果发现 AI 在"自己审查自己",天然倾向于认为结果没问题。这个问题和代码 Review 里作者自审容易放过问题是一个道理。

后来我们把提取拆成三个独立 Skill:

  • extractor:以调用语句为入口扫描依赖,生成初始提取包

  • validator:独立校验提取结果,关注"还缺什么"而不是"提了什么"

  • fixer:只处理 validator 指出的缺口,定向补充

三者视角天然不同,validator 不受 extractor 思路的干扰,能独立发现遗漏。更重要的是,出问题时能直接定位是哪一层的问题,不用在一个大 Skill 里全部排查。

这个"提取→校验→修复"的三层结构,后来在代码转化阶段也沿用了:converter → validator → fixer,证明这个拆分逻辑是通用的。

提效心得: Skill 的价值不在于 AI 能做多难的事,而在于同一件事 AI 能做多稳。规范写好之后,新加入的同学也可以直接复用,不用重新总结一遍。Skill 也不是提前规划出来的,而是被真实错误倒逼出来的------某个场景反复出错、发现"这类问题每次都要纠正"时,就是需要固化成 Skill 的信号。

04 SubAgent:上下文膨胀不是偶发问题,是必然的

一个页面包含大量文件,到后期 AI 开始"忘事"

我们有段时间在同一个对话里处理完整的迁移流程,前期运行得不错,但到了后期开始出现奇怪的错误------生成的代码引用了不存在的方法,资源 ID 映射关系对不上,有时候前面刚讲过的约束后面就不管用了。

排查后发现是上下文膨胀的问题。当加载的文件超过一定量,AI 对早期信息的记忆开始模糊,用"看起来合理"的内容来填充被压缩的细节------这就是幻觉的来源,它比输出明显错误更难处理,因为看起来像对的。

SubAgent 的思路是把长链路任务按步骤拆开,每个步骤交给一个独立的 SubAgent 处理,各自有完全隔离的上下文,互不干扰。

隔离之后的问题:步骤之间怎么传信息

上下文隔离解决了膨胀,但带来了新问题:SubAgent 之间信息割裂,后续步骤不知道前序步骤做了什么。

我们的解决方式是 Agent-Memory:每个 SubAgent 完成工作后,把关键信息提炼成结构化文件存下来,下一个 SubAgent 启动时读取这份文件,在自己的独立上下文里继续推进。

一个具体的例子:资源转化(strings.xml、colors.xml 等)和 UI 转化是前后依赖的两个步骤。UI 代码大量引用资源 ID,如果 UI 转化的 SubAgent 不知道资源映射关系,就只能猜------这是幻觉的典型触发场景。

实际做法是:资源转化的 SubAgent 完成后,把资源 ID 映射表写入 Memory 文件;UI 转化的 SubAgent 启动时读取这份映射表,在自己的上下文里准确处理引用,不用猜,也不用重复劳动。

Memory 文件不是对话记录的备份,而是"后续步骤需要什么"的提炼------这个区别比较重要。如果只是把聊天记录原样存下来再读进去,上下文一样会膨胀。有效的做法是只提炼结构化的关键信息,比如资源映射表、模块结构配置、已确认的接口契约,这类信息可以精确消费,不会引入噪声。

提效心得: SubAgent 适合有前后依赖的串行流程。判断标准很简单:这个步骤的输入,是不是依赖上一个步骤的产出?是就用 SubAgent 拆开,步骤之间通过 Memory 传递关键信息。及早拆分任务,比等到幻觉出现再排查效率高很多。

05 Agent Team:四路并行,收益比预期大

串行模式的天花板:一个页面提取要等多久

解决了上下文膨胀之后,我们遇到了效率问题。

页面代码提取涉及四类文件:UI 组件、布局文件、业务逻辑、资源文件。这四类文件的提取逻辑完全不同,但彼此之间没有强依赖------布局提取不需要等 UI 提取完,资源提取也不需要等业务逻辑提取完。

如果串行处理,总耗时是四段的累加,而且单个 SubAgent 需要同时处理四类文件,上下文依然会膨胀,专注度也会分散。

Agent Team 的方式是把四类提取任务分给四个专业 Teammate 并行执行,各自独立上下文,只关注自己负责的那类文件。

四个 Teammate 各司其职

各自只处理一类文件,上下文体积可控,对这类文件的依赖模式理解也更深------比如专注布局的 Teammate 对 include 嵌套引用的识别比"什么都做"的通用 Agent 准确很多。

跨 Teammate 的依赖怎么处理

四路并行并不是完全独立的。实际跑起来会遇到跨类型依赖:UI 提取 Teammate 发现代码里动态创建了一个 Dialog,需要通知布局提取 Teammate 补充这个 Dialog 的布局文件;业务逻辑里发现 API 调用引用了某个字符串资源,需要通知资源提取 Teammate 补充。

这类协调通过 Mailbox 消息通道实时处理,不需要等一个提取全部完成再补充,也不需要重新启动一轮。

实际效果

相比串行,总耗时接近四类任务里最慢的那条路径,而不是四段累加。并行最初是为了提速,但实际跑下来发现专注度提升带来的提取质量改善比速度收益更明显 ------ 一个 Teammate 只盯一类文件,对该类型的依赖模式会建立更强的识别,这是混合处理时很难做到的。

提效心得: Agent Team 和 SubAgent 的选择依据只有一条:任务之间有没有强依赖。有依赖需要串行,用 SubAgent;没有强依赖可以并行,用 Agent Team。并行不只是效率问题,专注分工本身也会提升单类任务的处理质量。

06 经验总结

回头看整个过程,几件事比较确定:

Skill 是被真实错误倒逼出来的,不是提前规划出来的

前期的规范很粗糙,在反复纠错里逐步补充边界条件和反例,这个迭代过程本身就是价值------它把团队踩过的坑沉淀成了下次不会再踩的规则。

上下文膨胀的临界点比想象中早,漂移比崩溃更危险。

幻觉出现时不是突然全错,而是逐渐偏离,每一步看起来都还好,到最后才发现方向不对。这种错误比明显报错难处理得多,及早拆分任务是更划算的选择。

Memory 文件要提炼,不要备份。

把对话历史原样传递没有意义,有效的是只传递"后续步骤需要消费的结构化信息",这条原则在实践中需要反复强化。

并行的收益不只在速度上。

分工带来的专注度提升,对任务质量的改善往往比缩短的时间更重要。

相关推荐
武子康5 小时前
Java-03 深入浅出 MyBatis 增删改查与映射配置详解
java·后端
Maiko Star6 小时前
* SpringBoot整合LangChain4j
java·spring boot·后端·langchain4j
明月_清风7 小时前
Go语言空接口与类型断言完全指南:从"万能容器"到"类型还原"
后端·go
每天进步一点_JL7 小时前
Spring Boot 缓存体系
后端
百珏7 小时前
[灰度发布]:全链路透传组件:APM、自研方案与 Java Agent 的实现取舍
后端·设计模式·架构
正在走向自律7 小时前
DISTINCT 去重查询为什么这么慢?聊聊我能理解的几种优化思路
后端
OpsEye7 小时前
数据库连接池爆了,这3个命令能救你一次
运维·数据库·后端
绝知此事7 小时前
【产品更名】通义灵码升级为 Qoder CN:AI 编码助手新时代,附大模型收费与 Spring Boot 支持全对比
人工智能·spring boot·后端·idea·ai编程
~|Bernard|8 小时前
GO语言中哪些类型是可比较类型的(==和!=)
开发语言·后端·golang