LLM辅助代码迁移:降低迁移疲劳的实践方法与边界 做迁移久了都会有一种感觉真正让人累的不是某一次大改造而是那些零散的、重复的、看起来不难却很耗神的琐碎工作。数据库字段要换、旧接口要下线、配置文件要重写、几百个调用点要逐个调整稍不留神就会漏掉一个分支。这种状态可以被叫做迁移疲劳。LLM 能不能帮忙避免我的判断是能但不是靠它一把梭把整个迁移做完而是靠它把迁移过程中最机械、最容易出错的那部分工作分摊掉让人只负责判断和兜底。这篇文章会用一次常见的接口迁移场景拆一遍我会怎么用 LLM 降低疲劳感也会说清楚哪些环节不能依赖它。1. 先理解迁移疲劳到底发生在哪一层很多人以为迁移是一个大项目启动会开完排期一做干就完了。实际做过一次就知道迁移最磨人的不是那一次“切换”而是切换前漫长的琐碎处理。1.1 迁移不是一场大动作而是几百个小动作以一次很普通的数据库字段迁移为例看起来只是把user_name改成username实际上要处理的是建表语句和初始化脚本要改。ORM 实体类、Mapper 或 Repository 要改。十几个 SQL 查询要改。前端接口文档、后端响应结构要同步改。历史数据要清洗、回填。依赖旧字段的报表和定时任务要排查。任何一个环节漏掉都不会立刻报错而是等到某个深夜任务突然失败或者某个统计数字对不上时你才意识到当初少改了一处。这种“不知道还有多少处没改”的心理压力是迁移疲劳的真正来源。1.2 LLM 的边界能做可预测转换不能做业务判断用 LLM 之前要先接受一个前提它擅长的是“有明确规则的转换”不擅长“需要业务语义判断的决策”。比如把createPayment(params)改成新接口的paymentClient.create(request)字段名、参数顺序、返回结构都能从代码和文档里推出来这类转换 LLM 做起来很快。但“这个字段在旧系统里代表什么含义新系统里应该映射到哪个业务概念”这种问题必须由人来回答。所以我的原则是LLM 负责从“旧格式 A”转换到“新格式 B”而 A 和 B 是什么、转换结果是否正确由人来定义和验证。这个边界立住了LLM 就是帮手边界模糊LLM 就会变成隐患来源。2. 适合用 LLM 处理的四类迁移任务不是所有迁移任务都适合交给 LLM。我实际用过之后觉得下面这四类最值得试因为它们重复度高、规则明确、做起来又非常容易疲劳。2.1 代码语法和框架接口转换最常见的就是老 SDK 升级、框架版本升级、语言迁移。比如把 Java 8 的写法调整到 Java 17 支持的写法把旧版 HTTP 客户端调用改造成新版客户端的调用把 Python 2 时代的代码迁到 Python 3 兼容风格。这类任务的特点是有明确的映射关系旧方法名对应新方法名旧参数类型对应新参数类型旧异常类型对应新异常类型。LLM 在读代码上下文之后可以一次处理一个文件或一个模块生成转换后的版本。2.2 配置文件和数据结构映射迁移经常涉及配置格式变化比如properties文件改成yaml环境变量改名JSON 结构中的字段重命名。纯粹手工改容易眼花而且配置项通常不会在编译期报错等运行到某个分支时才暴露问题。LLM 可以按你给定的映射表批量转换还能把“旧配置值”和“新配置项”放在一起输出方便人工复核。2.3 报错日志与迁移日志摘要迁移过程中最耗精力的其实是排错。一批任务跑下来日志里几百行报错有重复、有噪音、有真正致命的问题。人肉翻日志十分钟以后就头晕。我一般会把报错日志按批次丢给 LLM让它先做分类哪些是同一类问题、哪些是输入数据问题、哪些是配置缺失、哪些是代码逻辑问题。它不需要帮你直接改代码只要把“下一步该排查哪里”给出来就能省掉大量时间。2.4 测试用例和回滚脚本生成迁移完不能直接上生产要有验证手段。LLM 可以根据“迁移前函数”和“迁移后函数”的输入输出样例生成一组对比测试用例也可以把手工执行过的迁移语句整理成可重复执行的脚本。这里要特别注意生成测试用例有效不代表测试用例足够。LLM 生成的用例通常覆盖的是常规路径和它见过的样例边界条件、异常输入、并发场景还要人来补。任务类型手工做的疲劳点LLM 的价值人需要盯住的点代码转换逐文件改重复度高批量生成转换代码业务逻辑语义是否被改坏配置映射字段容易漏、眼花按映射表批量输出默认值、环境差异日志摘要海量重复报错分类、聚类、定位方向是否隐藏了低频但致命错误测试生成手写用例慢快速生成对比用例边界和异常覆盖是否足够这四类不是每次迁移都会同时出现但只要你做的迁移属于其中任意一类就值得先把 LLM 用起来。3. 一条能照抄的迁移辅助流程我自己跑过几次迁移之后总结出一条比较稳的流程先盘点再小样本再批量最后留痕。顺序不能乱。3.1 第一步先盘点迁移面不急着写提示词很多人拿到任务直接打开 LLM 开始问结果问出来的答案要么太宽泛要么不贴合项目。正确做法是先摸清楚这次迁移涉及的范围。我会在项目目录里用脚本把关键调用点全部抓出来比如grep -rn createPayment --include*.java ./src把所有命中的文件、行号、参数列表整理成一张表。这个环节有两个目的一是知道总量有多少方便估计工作量二是知道自己会在什么范围内使用 LLM避免让它凭空发挥。这时候也可以顺手确认依赖版本、目标框架、目标接口文档。LLM 不知道你项目里的具体版本你需要把关键信息喂给它而不是让它猜。3.2 第二步用小样本建立“正确输出”对照不要一上来就喂几十个文件。先挑 3 到 5 个具有代表性的文件跑一轮 LLM人工检查输出质量。这 3 到 5 个文件要尽量覆盖不同情况一个是最简单的基础调用一个是带异常处理的一个是参数比较复杂的。看 LLM 在这几个典型场景下能不能稳定产出符合预期的代码。小样本跑完之后把其中质量最高的输出作为“标准示例”后续批量生成时把这份示例一起发给 LLM作为 few-shot 参考。这一步能让后续结果稳定很多。3.3 第三步批量生成后用差异对比和单测兜底小样本没问题再进入批量阶段。但批量不是把全部代码一次性丢进去而是按模块分组一组一组来。每组生成后我会先做三件事用diff工具对比迁移前后的代码重点看有没有非预期的逻辑变化。跑一遍编译或语法检查保证没有基础错误。跑相关单测确认行为没有变化。只有这三项全部通过才继续下一组。如果某一组报错先排查是输入样例的问题还是提示词的问题而不是盲目重试。3.4 第四步把迁移过程留痕方便回查迁移后出了问题时最怕的就是查不到当初是怎么改的。所以在用 LLM 辅助迁移时我会把每次生成的输入、输出、采用或拒绝的结果都记录下来。不需要很复杂一个简单的目录结构就可以migration/ inputs/ 001_createPayment.java 002_refundRequest.java outputs/ 001_createPayment_new.java 002_refundRequest_new.java review/ 001_review.md这样既能追溯每一处改动的来源也能在后续遇到同类迁移时复用以前的提示词和判断标准。迁移疲劳的很大一部分来自“心里没底”留痕是让心里有底的最直接办法。4. 提示词怎么写才能让 LLM 少犯错同样的迁移任务不同提示词写出来的效果可能差很多。我总结了几个关键点。4.1 给足上下文但不能一次性塞太多LLM 对上下文敏感但塞太多文件会让它注意力分散。更好的做法是把目标代码片段、相关接口定义、约束条件分开给。如果一次只能处理一个函数就明确告诉它“只处理这个函数不要改动其他函数”。如果它能看到新接口的签名就把签名贴出来不要让它从记忆里猜。4.2 明确输入输出格式和失败约定我会要求 LLM 用固定格式输出特别是遇到不确定项时不要硬编。下面是一个我常用的提示词模板你是一个代码迁移助手。下面是旧接口的调用代码和参数说明。 请将其迁移到新接口并遵守以下规则 1. 新接口要求所有金额字段单位为分不要修改业务逻辑。 2. 超时参数从 timeout 改为 timeoutMs。 3. 如果遇到无法确定的字段输出到“不确定项”列表不要猜测。 4. 不要新增、删除或重命名本次迁移范围之外的变量。 输出格式 【迁移后的代码】 代码块 【改动说明】 逐条列出改动 【不确定项】 需要人工确认的问题这个模板的关键在于“不要猜测”和“输出不确定项”。LLM 在上下文不足时倾向于补全一个看起来合理的答案这恰恰是迁移场景最危险的。强行要求它把不确定点暴露出来问题就能提前暴露在人工审核阶段而不是上线之后。4.3 用对比表辅助 schema 映射如果迁移涉及字段映射比纯文字描述更稳的是给一张映射表。旧字段新字段类型变化转换规则user_nameusernamestring直接改名amountamount_centsint乘以 100保留整数is_activestatusstring0 转为 disabled1 转为 activeLLM 对表格式的映射理解通常比一段自然语言更准因为它能直接按行处理。迁移时如果遇到几十个字段先用脚本生成映射表再让 LLM 基于这张表批量生成。4.4 要求 LLM 提供改动说明而不是只给代码只给代码的迁移结果人工 review 时很难快速判断它改了什么。要求它输出“改动说明”和“不确定项”等于给 review 过程加了一层索引。我见过太多人拿到 LLM 生成的代码直接合入十分钟后出问题又回头骂模型。实际上问题不在模型而在流程里缺了一个“让改动可解释”的步骤。这个步骤花不了多少时间但能挡住大多数低级错误。5. 哪些环节不能交给 LLM以及怎么兜底LLM 能降低疲劳但它不是万能钥匙。迁移过程中有几类事情我建议无论模型多强都不要让它自主决策。5.1 高危操作删数据、改权限、替换核心算法凡是涉及数据删除、权限变更、核心算法替换的环节必须人工完成或者至少由人工逐行确认。LLM 可以帮你起草一个清理脚本可以帮你生成权限变更申请但不能让它直接执行或直接决定策略。原因很简单LLM 没有你业务的上下文它不知道哪张表的数据其实还在被别的系统引用也不知道某个权限变更会影响哪个下游系统。这些判断必须由了解业务的人来下。5.2 验证清单至少跑通编译、单元测试、样例回归每次 LLM 辅助生成的迁移结果都要过一遍固定的验证清单语法检查通过。编译通过。相关单元测试通过。至少用一组真实业务样例做回归。检查“不确定项”列表是否为空不为空时逐个确认。这套清单看起来基础但很多迁移事故恰恰是因为跳过了第 4 步或第 5 步。尤其是“不确定项”很多人看到 LLM 生成了完整代码就默认它没问题结果漏掉了它标注出来的隐患。5.3 回归测试和灰度顺序要单独设计迁移完成不代表结束还需要设计上线后的验证节奏。我的建议是先小范围灰度观察日志、错误率、耗时、资源占用确认稳定后再扩大范围。灰度期间不要只看“功能没报错”还要看慢查询、超时、内存增长这类指标。迁移经常引入性能变化因为新框架或新接口的内部实现和旧版本不同。功能正确但性能劣化也是需要回滚的信号。6. 从一次迁移到长期效率把 LLM 变成团队协作工具用 LLM 辅助一次迁移只能解决眼前的问题。真正降低长期迁移疲劳是把这套做法沉淀成团队都能用的工具和规范。6.1 沉淀自己的迁移提示词模板每个人做过的迁移类型都不同适合团队沉淀的提示词模板也不同。比如数据库字段迁移模板。接口 SDK 升级模板。配置文件格式转换模板。错误日志分类模板。每完成一次迁移把效果好的提示词保存下来形成一个小型提示词库。下次遇到类似任务直接基于模板修改而不是从零开始写提示词。6.2 配合代码评审和 CI 把风险挡住LLM 生成的内容应该走和普通代码一样的流程代码评审、静态检查、CI 测试。不要因为“这是 AI 生成的”就放松标准也不要因为“这是 AI 生成的”就额外怀疑标准应该一视同仁。我倾向于在评审时重点关注 diff 中“看似合理但没有对应映射依据”的改动。这类改动通常是 LLM 脑补出来的人工 review 时最容易一眼放过。6.3 最后的判断疲劳感下降多少才是真正有效判断 LLM 辅助迁移是否有效不看用了多少提示词也不看生成了多少代码而是看三件事整个迁移周期缩短了多少。线上和测试环境暴露的问题数量是否下降。参与迁移的人是不是不再害怕“还有几百处没改”。迁移疲劳的本质不是体力消耗而是那种“不知道还剩多少未知问题”的焦虑。LLM 真正的作用是把未知变成已知能转换的快速转换不能确定的明确标出来让人的精力集中在真正需要判断的地方。踩过几次之后我发现很多迁移问题不是工具能力不够而是前置环境和输入材料没有处理干净。LLM 不是替你承担判断责任而是帮你把判断所需要的上下文整理得更清楚。把它放在这个位置上迁移这件事至少不会再让人一想到就开始犯困。