一个人、九个月、20万行代码、每个月烧掉40亿+的token。这几个数字放到一起,懂行的朋友应该马上意识到,这不可能是一笔一笔手敲出来的代码量,背后一定是AI辅助开发加上一套非常克制的工程约束在撑着。这个项目是我一个人做的一款基于Harness架构的应用,所谓Harness,简单说就是给大模型套上缰绳和鞍具,让它在一个既定的工作流里稳定地产出代码,而不是靠概率发挥。这篇文章我把这段经历的核心部分彻底摊开:Harness架构到底解决了什么问题、一个人怎么扛住20万行代码的工程复杂度、40亿token烧在了哪里以及怎么止损、九个月的时间线是怎么切分的。无论你是独立开发者、正在带团队做AI工程化的技术负责人,还是单纯对“一个人怎么用AI造大型项目”这件事感兴趣,这篇里都有能直接拿走用的东西。
1. 先搞懂Harness架构到底解决什么问题
1.1 把AI编程从打地鼠变成流水线
最近几个月陆续有朋友问我,Harness架构是不是又一个包装出来的新概念。我的感受恰恰相反,它不是新框架,而是把AI辅助编程这件事从“手工作坊”变成“流水线”的一整套约束机制。
在没有约束的状态下直接让AI写20万行代码,你会经历什么呢?上下文丢失、代码风格漂移、接口定义反复推倒、改一个功能崩三个模块。我自己最早期就是这么过来的,第一个月写了大概两万行代码,第二个月删了一半——因为不同模块对同一份数据的处理方式各写各的,有的用字典硬解,有的定义了一堆dataclass,最后连我自己都分不清该信哪一套。
Harness的核心可以拆成三件事。第一,约束生成模板。每次让模型写代码,都走到同一套prompt模板里,包结构、命名规范、错误处理习惯、日志方式全是预设好的,模型没有发挥空间。第二,约束工具调用链路。从“人肉把代码粘贴给AI”变成标准化的读取、生成、校验、提交循环,每一步都有明确的输入输出格式。第三,分层管理上下文。长期记忆放架构决策,中期记忆放模块接口定义,短期记忆只放当前任务,三者各归各的桶,不互相污染。这三条做到位,AI产出的代码才具备“可预期”这个最珍贵的属性。
1.2 为什么一个人必须走Harness路线
独立开发者最大的敌人其实不是代码量,而是“我自己也记不住我自己写了什么”。
当你一个人面对20万行代码的时候,如果每个模块都是AI自由发挥生成的,三个月后再回来看自己写的代码,感觉跟看别人的项目一模一样。Harness架构对我来说很重要的一个价值在于:因为每次生成都走同一套模板和管线,整份代码的“指纹”是一致的。接口命名风格一致、目录组织方式一致、连注释的语气都是一路的。后期维护的时候,我可以在任何一个模块里快速定位到同类问题,不需要重新理解一套新风格。
说得直白一点,Harness不会让AI写出更惊艳的代码,它会让AI稳定地产出80分的代码,而不是今天90分明天40分。对于一个九个月的长周期项目来说,稳定比惊艳重要得多。九个月里我大概经历过三四次“想推倒重来”的冲动,最后都是因为harness的约束框架还在、骨架没有散,才坚持着在一个个模块上做修补而不是整体重写。
1.3 架构落地时的关键技术决策
这个项目里有一个关键的取舍想重点讲一下:我并没有从零手写一整套harness运行时框架,而是在DeepSeek开源实践的基础上做的裁剪落地。最近很多人搜deepseek harness和harness anything,也能看出来这条路线关注度确实很高。
我当时选型的逻辑很简单:社区里已经验证过的prompt编排引擎、沙箱执行环境、插件加载机制,直接用现成的;我自己真正要写的是和业务强耦合的部分——领域数据schema、代码生成模板库、质量校验规则集、token预算控制模块。这种“骨架继承+血肉自研”的方式,让我省掉了至少两个月的框架踩坑时间,把精力集中在这个应用本身的业务逻辑上。
还有一个容易被忽视的决策是编程语言和运行时的选择。因为我做的这个应用要跑在不同架构的机器上,包括x86和aarch64,所以依赖链上每一个库都提前确认了多架构支持。热词里有人搜aarch64架构mysql-5.7.44下载,其实这类问题我也遇到过,后面会在问题排查部分专门展开说。
2. 20万行代码一个人怎么“熬”出来
2.1 先搭脚手架,再让AI进场
很多人用AI写代码的姿势是一上来就甩需求:“帮我写个订单系统”,然后看着AI吐出一坨结构混乱的东西。我这个项目完全不同,前六周几乎没有让AI写任何业务代码,全部时间都在手工搭建脚手架和接口合同。
具体做法是:先把项目拆成8个主模块,每个模块手工定义好目录结构、核心类型、对外接口签名、数据流边界。这些骨架代码大概一万多行,全部是我自己写的,没有用AI。等骨架稳定了,再让AI在骨架里“填肉”。
这样做的好处是,AI面对的是一张有边界的考卷。它不需要自己设计模块划分,不需要拍板接口签名,只需要在指定目录、指定类型约束下完成函数实现。越界的情况几乎为零,因为骨架已经定死了结构。这个阶段AI生成的代码质量明显提升,因为它的精力全部集中在算法实现和逻辑正确性上,而不是花在“这个项目该怎么组织”这种它并不擅长的事情上。
2.2 代码量分布的真实账单
九个月下来,仓库里总代码量刚好过了20万行。这20万行不是均匀分布的,拆分下来大概是这个构成:
| 代码类别 | 行数(约) | 说明 |
|---|---|---|
| Harness框架与工具链 | 1.5万 | prompt模板、校验器、缓存、鉴权重试模块 |
| 业务模块实现 | 12万 | 8个主模块的实际逻辑代码 |
| 测试代码 | 4万 | 单元测试、集成测试、契约测试 |
| 脚本配置与文档 | 2.5万 | 部署脚本、CI配置、架构文档 |
这个比例里最有意思的是测试代码占了20%,这个比例是我刻意守住的。AI生成的代码里有相当一部分属于“看起来对,边界条件全是坑”,没有足够的测试兜底,后期重构的时候根本不敢动。我现在回头看,4万行测试代码可能比那12万行业务代码更值钱,因为正是它们给了我在第六个月敢大规模重构的底气。
2.3 质量守门:让小步提交成为肌肉记忆
一个人开发最大的风险是提交次数太少、每次diff太大。一旦出了bug,都不知道是哪个决策导致的。所以我在项目里立了一条铁律:每个AI生成的diff,合入前必须过三道门。
第一道门是静态检查和单元测试,这个交给脚本自动跑。第二道门是人工review,重点看边界条件、资源释放、异常分支——这些是AI最薄弱的地方。第三道门是diff影响声明,每次合入前必须写清楚:这个改动影响哪些模块、有没有补测试、有没有引入新依赖。
这三道门听起来简单,但真要坚持九个月很难。尤其到后期,面对那些只剩一两行改动的diff,人会本能地偷懒跳过声明。我的破解办法是写了个pre-commit钩子,凡是没有填影响声明的commit一律拦截。这种“机器管机器”的方式,比我靠自觉靠谱得多。
3. 40亿+ token的消耗拆解与省钱实操
3.1 这些token到底烧在了哪里
每个月40亿+的token消耗,乍一听很吓人,拆开看其实每一笔都有去处。我按月均水平做过统计,消耗占比大致是这样的:
| 消耗场景 | 占比 | 说明 |
|---|---|---|
| 业务代码生成 | 45% | 核心的“填肉”工作,量大且必要 |
| 上下文重放与重复输入 | 25% | 最可压缩的部分,纯粹是浪费 |
| 调试与错误修复对话 | 20% | 来回拉锯,优化空间大 |
| 测试生成与修复 | 10% | 必要开销,但可以通过脚手架压缩 |
这个账单里最刺眼的是25%的上下文重放。什么叫重放?就是同一个项目背景、同一个模块设计、同一段报错日志,在每一轮新对话里都要重新发给模型一遍。模型没有记忆,每次对话都是“初相识”,你必须把背景从头讲一遍。
3.2 token当钱算:成本模型与预算思维
关于40亿这个数字,很多人第一反应是问花了多少钱。按我当时用的主流模型API公开价格粗算——输入token和输出token价格不一样,输出贵得多——每个月折算下来大概在六位数人民币级别。这个成本是不是可控,完全取决于你的工程手段。
这里要分享一个核心成本认知:输入token便宜、输出token贵。所以省钱的第一优先级永远是“减少无意义的重复输入”,而不是想方设法缩短生成内容。同样的优化投入,砍掉一次100万token的重复上下文,比调整prompt让模型少输出几百行代码要省得多。换句话说,上下文管理是所有token优化手段里单位收益最高的一件事。
3.3 我实践下来最有效的六个省token手段
第一,分层上下文设计。把项目文档拆成三个层级:架构索引只写目录级信息和全局约定;模块文档只描述本模块的职责和接口;任务描述只讲当前要做的具体改动。不同任务只带对应层级的内容,绝不全部塞进上下文。
第二,diff驱动,不是文件驱动。每次提交给模型做修改时,只粘贴相关代码片段和报错信息,绝不把整个文件丢进去。这招能把单次输入量压缩60%以上。
第三,缓存与快照。harness框架里做了prompt模板的预编译缓存,重复模板只算一次token消耗;对话上下文在命中的情况下直接复用历史快照,而不是重新组装。
第四,模板代码本地化。像创建新模块、新测试文件这类格式固定的工作,我用本地脚本生成,不消耗任何token。AI只负责写逻辑,不负责写套路。
第五,要求“先方案后代码”。在prompt里明确约束:模型先输出实现思路和改动范围,我确认后才允许写代码。这个约束能拦下一大批方向跑偏的浪费。
第六,强制会话轮次上限。单个对话超过一定轮次后,harness会强制做总结归档、开启新会话。上下文一旦膨胀,不仅消耗大,生成质量也会明显下滑。
3.4 关于token交换与续签的工程处理
这里必须说一下“token”这个词的两层含义。前面讲的是大模型调用的token,还有另一类token是API鉴权用的JWT和refresh token。九个月高密度开发里,鉴权类报错我遇到的频率远超想象。
热词里很多人搜token exchange failed、sign-in could not be completed、failed to refresh token。这类问题的真实原因,我在项目里排查下来,绝大多数不是密钥错误,而是几个非常隐蔽的细节:
第一,系统时钟偏差。JWT有个exp字段,如果你的机器时钟和服务器时间差得太远,token校验直接失败,报错还很抽象。这个最隐蔽,因为排查方向很容易跑偏。
第二,refresh_token过期后没有完整重走登录流程。很多实现只做了token静默续签,refresh_token一旦过期就死循环。
第三,配置读取空值。我遇到过failed to refresh token: 400 bad request invalid 'refresh_token': empty string,查了半天发现是配置文件里refresh_token字段被环境变量覆盖成了空字符串。
第四,同一密钥在多处并发使用触发服务端限流策略,也会导致token换取403。
针对这些问题,我在harness框架里单独写了一个鉴权重试模块,几百行代码,做了三件事:指数退避重试、本地凭证缓存自清理、时钟偏差检测告警。这个模块几乎让我后期彻底告别了“无头苍蝇式”的鉴权排查。
4. 九个月的时间线复盘:里程碑怎么切
4.1 前三个月:架构、骨架、harness框架
第一阶段的目标是“地基不动摇”。前六周我手工完成了技术选型、模块划分、接口合同定义、脚手架搭建,并完成harness框架的核心裁剪。这个阶段几乎不写业务代码,但进度感其实最强,因为每一行代码都是在为后面九个模块铺路。
中间六周开始打磨harness的prompt模板和质量校验规则。这段是最枯燥的,因为你在调试“AI产出的稳定性”——同一个任务跑五遍,要求五遍结果在接口层面完全一致。我记得光错误处理模板就迭代了七八版,才找到一套让AI稳定输出“先判参数、再走主逻辑、最后兜底异常”的固定格式。
4.2 中间四个月:批量生成与自测
第四到第七个月是业务模块的高产期,也是token消耗的峰值区间。每个模块的推进路径都是固定的:读架构文档、看接口合同、让AI填肉、跑测试、人工review、合入。一个中等模块大概一到两周完成,全部8个模块大概覆盖了15万行代码。
这四个月里我踩过最大的坑是“多模块并行”。有一段时间我试图同时推进三个模块的AI生成任务,以为能提高效率,结果就是上下文切换成本暴涨,每个模块的接口约定都开始变得模糊,出错的概率大很多。后来强制改成单模块串行推进,一个模块彻底收口再开下一个,整体效率反而翻了一倍。
4.3 最后两个月:集成、重构、瘦身
第八个月的主要工作是全模块集成和端到端联调。问题集中爆发在这个阶段,因为单模块自测永远发现不了跨模块的接口字段不一致、数据流环路上的隐性耦合。这一个月也是重构动作最频繁的时期,好消息是前面积累的4万行测试此刻发挥了巨大作用,每次重构后跑一遍全量回归,能快速定位破坏点。
第九个月我做了一件很多人不理解的件事:主动删代码。删掉了大约8000行“看起来有用但实际上没有任何调用方”的死代码,顺手把一批过度设计的抽象接口做了瘦身。这个阶段的经验是:AI辅助开发的项目特别容易“过度生长”,因为生成新代码的成本太低,低到你会忘记每一行代码都是负债。删完这8000行,整个应用启动速度快了15%,维护起来也轻松得多。
5. 高频踩坑与排查实录
5.1 环境类问题:dll缺失、多架构兼容
开发中期在Windows环境上运行时,系统报过一个很经典的错:由于找不到msvcp140.dll无法继续执行代码。这个问题的本质是VC++运行库缺失,Python的很多C扩展、CI里的编译工具链都依赖它。解决方案没有任何捷径——装对应版本的Microsoft Visual C++ Redistributable,装完重启进程即可,千万不要手动去网上乱下载dll文件覆盖,版本不对还会引入更多问题。
多架构兼容是另一个高频坑。热词里有人搜aarch64架构mysql-5.7.44下载,我在项目里也遇到过类似场景:需要在ARM机器上跑同一套服务,一开始有几个依赖库只能从源码编译,编译时间还特别长。后来我的处理方式是单独开一个aarch64的编译镜像,把依赖链的编译产物做成离线缓存,避免每次部署都重新编译一遍。这类问题提前规划,比临时硬解要省很多时间。
5.2 Harness框架类问题:插件加载失败
如果你在用现成的harness框架,大概率会遇到harness failed to load plugins这类报错。我印象最深的一次是提示"web boot: 2 entries did not activate",整个界面都加载不出来。
排查路径供参考:第一步看日志确认插件是否被扫描到——如果连扫描到的记录都没有,问题出在插件目录路径或目录权限上;第二步看依赖是否完整——很多插件激活失败是因为找不到它依赖的类库或版本冲突;第三步才是看插件代码本身的逻辑问题。大部分情况不是代码bug,而是环境配置对不上。
这类问题我后来总结了一个预防机制:每次升级harness版本,先在一个隔离环境里跑一遍完整插件激活测试,再应用到主开发环境。用一条命令完成全量插件的自检,省去了无数重复手工排查。
5.3 单人开发的心态类问题:如何撑过第九个月
最后想说点代码之外的事。九个月的单人高强度开发,技术问题其实都有解法,真正难的是心态曲线。
我自己经历的最危险的阶段是第六个月到第七个月之间,那时项目处于“能跑了但哪里都不完美”的状态,每天睁眼都是新bug,成就感极低。那阵子我的应对方式是切换任务类型——暂停bug修复,去做几天文档编写和测试补全。这些任务正反馈来得特别快,能有效拉回“项目在向前走”的感觉。
到了第九个月,又出现一种微妙的心态:对代码产生厌倦,看到那些AI生成的老模块就想推翻重写,觉得用现在的prompt模板来写会更漂亮。这种“重写诱惑”一定要克制。我当时给自己立了一条规矩:除非修复bug或者有明确的性能指标需求,否则不碰老模块的代码。正是这条规矩保住了最后两个月的稳定性。
最后再分享一个我到现在都很受用的体会:与其纠结“AI写的代码够不够好”,不如把注意力放在“我搭的harness能不能让AI稳定产出80分的代码”。这套思路跑完九个月之后,我已经把它沉淀成了自己新项目的启动模板——先花两周时间把harness骨架搭好,再让AI进场填肉。如果你也准备用AI辅助做一个体量偏大的项目,我强烈建议你先认真对待“约束”这件事,而不是急着让AI吐代码。好的harness是你的第二条命。