1. 项目缘起一个反直觉的AI编码实验1.1 80万行Rust代码是怎么来的先说清楚这个项目的背景。有一个团队做了一次相当激进的尝试让AI Agent从零开始把一个中等规模的TypeScript/Node.js后端服务完整迁移成Rust。不是写几个函数、补几个测试那种小打小闹而是整个服务——包括HTTP路由层、业务逻辑、数据库访问、异步任务调度、错误处理、配置管理——全部重写。最终产出大约80万行Rust代码覆盖了原本几十万行TypeScript所承载的全部功能。这个数字听起来很唬人但真正让我感兴趣的不是“AI能写多少代码”而是这个团队在复盘时反复强调的一件事AI花在“读代码”上的精力是花在“写代码”上的十倍以上。他们原本以为瓶颈在生成速度结果发现瓶颈在理解——理解旧代码的意图、理解类型系统的约束、理解异步模型在两种语言之间的语义鸿沟。这个结论对做AI Agent开发、做代码迁移工具、甚至只是日常用AI辅助编程的人都有非常直接的参考价值。我把它拆开来讲尽量还原这个项目里那些“文档不会写、但踩过才知道”的细节。1.2 为什么是Rust为什么是TypeScript迁移选Rust作为目标语言不是随便挑的。TypeScript到Rust的迁移恰好踩中了几个最难的交叉点类型系统不对等TypeScript是结构化类型Rust是名义化类型加所有权系统。一个interface在TS里可以随便扩展在Rust里你得想清楚是trait、enum还是struct还要处理生命周期。异步模型差异Node.js是单线程事件循环Rust的async是基于Future和运行时比如tokio的。Promise.all在Rust里对应join!还是try_join!错误传播路径完全不同。内存管理哲学TS靠GCRust靠所有权和借用检查。AI在生成Rust代码时最容易犯的错就是“按TS的思路写Rust”结果编译器直接教做人。这个项目之所以值得学是因为它把“AI Agent在真实工程约束下如何工作”这件事暴露得很彻底。下面我按几个核心维度来拆。2. 核心思路拆解AI Agent的“读”与“写”比例为什么是10:12.1 读代码到底在读什么很多人以为AI读代码就是“把源文件塞进上下文窗口”。实际远不止。在这个迁移项目里AI Agent的“读”至少包含四个层次第一层语法结构解析。把TypeScript的AST解析出来识别出函数、类、接口、类型别名、导入导出关系。这一步相对机械但量大。一个几十万行的TS项目AST节点数量是千万级的。第二层语义依赖追踪。一个函数调用了另一个模块的导出那个模块又依赖了第三个模块的类型定义。这种跨文件的依赖图AI必须自己构建。否则它写出来的Rust代码会出现“引用了不存在的类型”或者“循环依赖”这类问题。第三层意图推断。这是最难的。TS代码里一个any类型AI得猜它实际是什么。一个Promise链AI得判断它是串行还是并行语义。一个try-catchAI得决定在Rust里是返回Result还是直接panic。这些都不是语法问题是工程判断。第四层约束提取。旧代码里隐含的业务规则——比如“这个字段不能为空”、“这个操作必须在事务里”、“这个超时是30秒”——AI得从代码、注释、测试用例里把这些约束挖出来然后在Rust里用类型系统或运行时检查重新表达。提示如果你也在做类似的代码迁移不要指望AI一次读一个文件就能写好。它需要反复读、交叉读、带着问题读。这个“读”的token消耗往往是“写”的很多倍。2.2 为什么“写”反而相对简单一旦AI把上面四层“读”的工作做扎实了写Rust代码反而变成了相对确定性的任务。因为Rust编译器本身就是一个极其严格的“审稿人”。你写错了它不让你过。所有权问题、生命周期问题、类型不匹配问题编译器会一条条指出来。这个项目里有个细节很关键AI Agent在生成Rust代码后会进入一个“编译-报错-修正”的循环。平均每个函数要经历3到5轮编译修正才能通过。但每一轮修正AI都在学习——它会把编译器的错误信息当作反馈信号调整自己的生成策略。这其实揭示了一个更普适的规律在强类型、强约束的语言里AI的“写”可以被编译器兜底但在弱约束的环境里AI的“写”就是灾难。这也是为什么这个项目选Rust反而比选Python或JavaScript更容易成功——Rust的编译器替人类做了大量验证工作。2.3 十倍精力读代码的工程含义“十倍”这个数字不是精确统计而是一个量级判断。它意味着如果你打算用AI做代码迁移你的成本预算、时间预算、token预算都要按“读为主、写为辅”来分配。具体来说一个典型的迁移任务里AI的时间大概这样分配阶段占比主要工作代码解析与依赖构建30%AST解析、模块图、类型映射语义理解与意图推断40%业务逻辑提取、约束识别、边界条件Rust代码生成15%结构设计、函数实现、错误处理编译修正与测试15%编译循环、单元测试、集成验证这个分布和很多人直觉相反。大家通常以为“生成”是大头实际上“理解”才是。3. 核心细节解析AI Agent在迁移中到底怎么做3.1 类型系统的映射策略TypeScript到Rust的类型映射是这个项目里最耗精力的部分之一。我整理了几种典型情况和对应的处理方式基础类型映射。string对应String或strnumber对应i32/i64/f64boolean对应bool。这些看起来简单但number在TS里是浮点数在Rust里你得判断它到底是整数还是浮点。AI的做法是先看这个值在代码里怎么用的如果只做整数运算就映射成i64如果涉及除法或小数就映射成f64。联合类型映射。TS的string | number在Rust里对应enum。AI会生成一个枚举类型每个变体对应一种可能。这比用serde_json::Value或者Boxdyn Any要安全得多但代码量会膨胀。可选类型映射。TS的foo?: string对应Rust的OptionString。这个映射很直接但难点在于TS里undefined和null有时候是混用的AI得判断到底是“不存在”还是“存在但为空”。接口与trait。TS的interface如果只是数据结构映射成Rust的struct如果有方法映射成trait。但TS的接口可以被任意对象实现Rust的trait需要显式impl。AI在这里经常需要生成额外的适配层。泛型约束。TS的泛型约束比较宽松Rust的trait bound更严格。AI需要把TS里的extends转换成Rust的where子句有时候还要引入额外的trait来满足约束。注意类型映射不是一一对应的。有些TS类型在Rust里没有直接对应AI需要做“类型重构”——把原来的类型拆成多个Rust类型或者引入新的抽象。这部分工作很难自动化需要人工review。3.2 异步代码的迁移难点Node.js的异步模型和Rust的异步模型表面上看都是async/await但底层语义差别很大。这个项目里AI在处理异步代码时主要遇到几个问题运行时选择。Node.js自带事件循环Rust需要选一个异步运行时。项目里用的是tokio因为生态最成熟。AI在生成代码时需要确保所有异步函数都在tokio的运行时里执行不能混用其他运行时的API。错误传播。Node.js里async函数抛出的异常会被Promise捕获Rust里async函数返回Result。AI需要把TS里的throw转换成Rust的return Err(...)并且确保调用链上的每一层都正确处理了错误。并发控制。TS里的Promise.all对应Rust的futures::join!或tokio::join!但Rust的join!要求所有future都是Unpin的有时候需要Box::pin。AI在生成这类代码时经常需要额外处理Pin的问题。取消语义。Node.js的AbortController和Rust的CancellationToken语义不同。AI需要把取消逻辑重新表达确保在Rust里能正确传播取消信号。阻塞操作。Node.js里可以用worker_threads做CPU密集任务Rust里对应tokio::task::spawn_blocking。AI需要识别哪些操作是阻塞的然后放到正确的执行上下文里。这些细节如果AI没有“读”透原来的异步逻辑写出来的Rust代码要么编译不过要么运行时有微妙的bug。3.3 数据库访问层的重写项目里原本用的是Node.js的ORM类似Prisma或TypeORM迁移到Rust后用的是sqlx。这部分的工作量很大因为ORM的抽象层在Rust里没有完全对等的替代品。AI的做法是先把TS里的实体定义、关系映射、查询逻辑全部提取出来然后在Rust里用sqlx的宏和查询构建器重新实现。sqlx支持编译时检查SQL这对AI来说其实是好事——写错了SQL编译就报错。但难点在于TS的ORM往往有懒加载、级联删除、事务嵌套这些高级特性sqlx需要手动实现。AI在这里需要生成大量的辅助代码比如连接池管理、事务封装、错误映射。提示如果你也在做Node.js到Rust的数据库迁移建议先把ORM的查询日志打开把实际执行的SQL全部抓出来。AI基于真实SQL来生成sqlx代码比基于ORM的抽象API要准确得多。4. 实操过程一个完整迁移任务的拆解4.1 环境准备与工具链搭建这个项目的基础设施不算复杂但每一步都有讲究。我按实际顺序列一下Rust工具链。用rustup安装稳定版工具链cargo作为构建工具。项目里用到了tokio、sqlx、serde、axumHTTP框架、tracing日志这几个核心crate。版本要锁定避免AI生成的代码因为依赖版本变化而编译失败。TypeScript解析工具。用ts-morph或typescript-eslint/parser来解析TS代码生成AST。AI Agent通过这个AST来理解代码结构。项目里还用了madge来生成模块依赖图。AI Agent框架。项目里用的是一种“多轮对话工具调用”的Agent架构。Agent可以调用“读文件”、“解析AST”、“搜索符号”、“生成代码”、“运行编译器”这些工具。每一轮对话Agent根据当前状态决定下一步做什么。编译反馈循环。这是关键。Agent生成Rust代码后自动运行cargo check把错误信息喂回给AgentAgent修正后再检查。这个循环一直持续到编译通过。测试框架。迁移后的Rust代码需要跑单元测试和集成测试。项目里用cargo test并且把原来的TS测试用例也迁移过来作为验证标准。4.2 迁移流程的六个阶段整个迁移不是一次性完成的而是分阶段推进。我把它归纳成六个阶段阶段一代码扫描与清单生成。AI先扫描整个TS项目生成一份“迁移清单”——哪些文件要迁移、哪些模块有依赖关系、哪些类型需要映射。这份清单是后续所有工作的基础。阶段二类型定义迁移。先把所有的interface、type、enum迁移成Rust的struct、enum、trait。这一步不涉及业务逻辑但决定了后续代码的类型基础。阶段三工具函数与基础设施迁移。把日志、配置、错误处理、HTTP客户端这些基础设施先迁移过去。这些模块被业务代码广泛依赖先迁移可以减少后续的阻塞。阶段四业务逻辑迁移。按模块逐个迁移业务逻辑。每个模块迁移完后立即跑测试验证。AI在这里的工作量最大因为它需要理解每个函数的业务意图。阶段五数据库层迁移。把ORM相关的代码迁移到sqlx。这一步需要特别小心因为SQL的正确性直接影响数据。阶段六集成与端到端测试。所有模块迁移完后跑完整的集成测试确保新旧系统的行为一致。每个阶段都有AI的参与但参与程度不同。阶段一和阶段二AI可以高度自动化阶段四和阶段五需要大量人工review。4.3 关键参数与配置示例项目里有一些配置细节值得记录。比如Cargo.toml里的依赖配置[dependencies] tokio { version 1, features [full] } sqlx { version 0.7, features [runtime-tokio, mysql, macros] } serde { version 1, features [derive] } axum 0.6 tracing 0.1 tracing-subscriber 0.3 thiserror 1 anyhow 1sqlx的数据库连接池配置let pool MySqlPoolOptions::new() .max_connections(20) .min_connections(5) .acquire_timeout(Duration::from_secs(10)) .idle_timeout(Duration::from_secs(600)) .connect(database_url) .await?;这些参数不是随便定的。max_connections根据数据库的实际承载能力来定acquire_timeout要略大于业务的最长查询时间idle_timeout要小于数据库的wait_timeout避免连接被数据库端断开。AI在生成这些配置时需要参考原来的Node.js连接池配置以及数据库的实际参数。如果AI没有读到这些信息它生成的配置可能就是拍脑袋的。4.4 编译修正循环的实操记录这是整个项目里最有意思的部分。AI生成Rust代码后编译报错是常态。我记录了几类典型错误和AI的修正方式所有权错误。AI经常写出“移动后使用”的代码。比如把一个String传给函数后又试图使用它。编译器的错误信息会指出具体位置AI的修正方式通常是加.clone()或者改成传引用。生命周期错误。AI生成的函数签名有时候缺少生命周期标注或者标注不正确。编译器会提示“missing lifetime specifier”AI需要根据函数体的实际使用情况来补全。trait bound错误。AI调用的方法在某些类型上不存在因为缺少trait实现。编译器会提示“the trait bound is not satisfied”AI需要引入对应的trait或者换一种实现方式。异步错误。AI有时候会在非异步函数里调用异步函数或者忘记.await。编译器会提示“future cannot be awaited”AI需要调整函数签名或调用方式。类型不匹配。AI生成的类型和期望的类型不一致比如i32和i64混用。编译器会提示“expected i64, found i32”AI需要加类型转换。每一类错误AI都会在修正后重新编译直到通过。这个循环平均每个函数要跑3到5轮复杂的函数可能要10轮以上。提示编译修正循环的token消耗很大。如果你在做类似项目建议把编译器的错误信息做一下过滤和摘要只把关键部分喂给AI避免上下文被错误信息撑爆。5. 常见问题与排查技巧实录5.1 AI生成代码的典型问题速查表问题类型表现排查思路解决方式所有权误用移动后使用、借用冲突看编译器错误位置加clone、改引用、调整作用域生命周期缺失函数签名报错看函数体的实际借用关系补生命周期标注、改所有权异步语义错误future未await、运行时混用检查函数签名和调用链统一运行时、补await类型映射错误i32/i64混用、String/str混用看类型定义和调用点加转换、统一类型错误处理不一致Result/panic混用看错误传播路径统一用Result、定义错误类型数据库查询错误SQL语法或类型不匹配看sqlx编译错误修正SQL、调整参数类型并发安全问题Send/Sync不满足看跨线程传递的类型加Arc/Mutex、调整设计5.2 几个踩过的坑坑一AI会“幻觉”出不存在的API。比如它可能生成tokio::spawn_blocking的某个不存在的参数或者sqlx的某个不存在的宏。这类错误编译器会直接报“no function found”AI修正时通常会换成正确的API。但如果AI连续几次都幻觉同一个API就需要人工介入给它一个正确的示例。坑二AI对TS的隐式类型转换理解不足。TS里1 2会得到12Rust里直接编译不过。AI在迁移这类代码时有时候会忽略类型转换导致编译错误。解决方式是在迁移前先把TS代码里的隐式转换显式化。坑三AI生成的错误类型过于复杂。Rust的错误处理可以用thiserror定义枚举也可以用anyhow做动态错误。AI有时候会生成一个巨大的错误枚举包含几十个变体维护起来很痛苦。建议在项目初期就定好错误处理策略让AI遵循。坑四AI对测试用例的迁移不够重视。项目里发现AI倾向于把测试用例也“翻译”成Rust但翻译后的测试有时候失去了原来的验证意图。建议测试用例的迁移要人工review确保验证的是行为而不是实现。坑五AI在长上下文里会“遗忘”早期约束。当迁移任务持续很长时间AI的上下文里积累了太多信息它可能会忘记最初定下的类型映射规则。解决方式是把关键约束写成“系统提示”或者“项目规范”在每一轮对话里都带上。5.3 人工review的重点AI生成的代码哪些必须人工看我总结了几条涉及资金、权限、数据删除的逻辑这些地方AI出错代价太大必须人工逐行确认。并发和锁的使用AI对Rust的并发安全理解有时候不到位容易写出死锁或数据竞争的代码。错误处理的边界AI倾向于“能编译过就行”但错误处理是否合理需要人工判断。性能敏感路径AI生成的代码可能功能正确但性能差比如不必要的clone、低效的循环。数据库查询SQL的正确性和性能必须人工验证。6. 这个项目对AI Agent开发的启示6.1 “读”的能力比“写”的能力更重要这个项目最核心的启示就是AI Agent的价值不在于它能生成多少代码而在于它能理解多少代码。生成代码这件事随着模型能力提升会越来越便宜。但理解代码——理解意图、理解约束、理解上下文——才是真正的瓶颈。对做AI Agent开发的人来说这意味着你的Agent需要强大的“读”工具。AST解析、依赖分析、符号搜索、类型推断这些能力比“生成”能力更值得投入。6.2 强约束环境是AI的好朋友Rust的编译器是一个极其严格的“审稿人”。它不接受模糊、不接受歧义、不接受“大概能跑”。这种强约束环境反而让AI的工作变得可验证、可迭代。相比之下在JavaScript或Python这种弱约束环境里AI生成的代码可能“看起来对”但运行时才暴露问题。这种反馈循环太慢AI很难从中学习。所以如果你在做AI辅助编程的工具优先选择那些有强类型、强约束的语言和框架。编译器会帮你做大量的质量把关。6.3 迁移是AI Agent的最佳练兵场代码迁移这个场景天然适合AI Agent有明确的输入旧代码、有明确的输出新代码、有明确的验证标准编译通过测试通过。而且迁移过程中AI需要大量“读”的操作正好锻炼它的理解能力。如果你在学习AI Agent开发我建议从一个小型迁移任务开始——比如把一个Python脚本迁移成Rust或者把一个JavaScript工具函数迁移成TypeScript。不要一上来就搞几十万行的项目先从几百行开始把“读-写-编译-修正”这个循环跑通。6.4 工具链的配套比模型本身更关键这个项目里AI模型本身的能力当然重要但更关键的是围绕它的工具链AST解析器、依赖图生成器、编译器反馈循环、测试框架。这些工具让AI的“读”和“写”都有了落脚点。如果你在搭建自己的AI Agent不要只关注模型选型。花更多时间在工具链上——怎么让Agent高效地读文件、怎么把编译错误结构化地喂回去、怎么管理长上下文里的关键约束。这些工程细节往往决定了项目的成败。7. 我个人的几点实操体会做类似项目的时候我踩过几个坑也总结了几条经验不一定对但都是真金白银换来的。第一不要追求“全自动”。一开始我也想着让AI一口气把整个项目迁移完结果发现上下文根本撑不住AI到后面就开始胡言乱语。后来改成“分模块、分阶段、人工review”效率反而高得多。AI适合做“批量理解”和“初稿生成”但关键决策和边界情况还是得人来。第二把约束写成文档。项目里定下的类型映射规则、错误处理策略、命名规范我都写成了一个MIGRATION_GUIDE.md每次让AI生成代码前先把这份文档塞进上下文。这样AI就不会“忘记”之前的约定。这个习惯看起来笨但省了很多返工。第三编译错误要“摘要”后再喂给AI。一开始我把完整的cargo check输出直接给AI结果错误信息太长AI的注意力被分散了。后来我写了个小脚本把错误按文件、按类型聚合只把最关键的信息喂回去。AI的修正效率明显提升。第四测试用例要“行为化”。原来的TS测试里有很多“实现细节”的断言比如“这个函数被调用了3次”。迁移到Rust后这些断言往往不适用。我后来把测试用例改写成“行为断言”——只验证输入输出不验证内部实现。这样AI迁移起来更容易测试也更稳定。第五留出“人工兜底”的时间。不管AI多强总有一些代码它搞不定——复杂的生命周期、微妙的并发逻辑、业务规则密集的模块。这些地方我都是自己上手写。把AI当成一个“高级助手”而不是“替代者”心态会好很多项目也更容易成功。最后再分享一个小技巧如果你也在做代码迁移建议先把旧代码里的“坏味道”清理一遍——重复代码、死代码、过度抽象——再让AI迁移。AI会忠实地把坏味道也迁移过去甚至放大。先清理再迁移事半功倍。
企业数字化 ERP 产品动态
相关推荐
UFO:基于GPT-Vision与pywinauto的Windows自动化新范式 1. 从"点鼠标"到"说句话":UFO到底想解决什么问题Windows 上的自动化工具我折腾过不少,从最早的按键精灵脚本,到 AutoHotkey,再到 pywinauto 这种偏工程化的库,每一代工具都在解决同一个核心矛盾&a… · 2026/9/24 22:46:03
校园跑腿系统开发实战:基于Laravel与ThinkPHP的双端平台设计 1. 项目概述1.1 这是什么项目校园跑腿这个需求,几乎每个大学城都存在。代拿快递、带饭、代买奶茶、打印资料、临时取货,这些都是高频刚需的小事,但就是这些小事占据了大学生的碎片时间。我在做这个校园生活服务系统时,核心思路很简… · 2026/9/24 22:46:03
深度学习新闻分类推荐系统:从TextCNN到个性化推荐 简介:这份基于深度学习的新闻分类推荐系统Python实现源码,是专为课程设计与期末大作业准备的高分项目,下载后无需修改即可运行,适用于需要快速交付完整课题的高校学生。系统涵盖新闻数据预处理、文本分类模型训练、推荐逻辑展示等… · 2026/9/24 23:59:53
汽车电子底层软件开发:AUTOSAR与CAN总线实战解析 1. 这门“汽车电子底层软件开发就业课”到底在教什么?——不是写个LED闪烁就能上岗的很多人看到“汽车电子底层软件开发就业课”这个标题,第一反应是:不就是嵌入式C语言单片机CAN通信?刷几道LeetCode、调通一个STM32 CAN收发例程&… · 2026/9/24 23:59:53
Vim基础操作全攻略:保存退出、模式切换与高频命令实战 1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保… · 2026/9/24 23:59:53
Python+CNN车牌识别实战:从数据预处理到模型训练与部署 简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据… · 2026/9/24 23:59:53
AI元人文:从工具使用到思维重构的深度探索 最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决… · 2026/9/24 23:59:53