一个人、九个月、20 万行代码、每个月烧掉 40 亿+ token——造出一款Harness架构应用
先说个让人有点羞耻的数字:过去九个月,我一个人蹲在工位上,写了大概 20 万行代码,每个月烧掉 40 亿+ token。你没看错,是亿,不是万。这些 token 基本都是喂给了代码生成模型和配套的 Agent 流程,用来帮我完成从需求拆解、接口设计到模块生成、测试修复的所有环节。说句实话,九个月前我也觉得这是一场豪赌,但最后不仅把东西造出来了,还顺手提炼出一套我现在称之为Harness 架构的应用骨架。这篇文章就是想把这段经历拆开揉碎,讲讲为什么必须给 AI 套上“缰绳”,以及那 40 亿 token 到底烧得值不值。
如果你正准备做一款以 AI 生成为核心、但又不希望被 AI 的不可控性拖垮的软件,或者你也在为每天疯狂上涨的 token 账单发愁,那这篇文章应该能给你一些参考。我不会只讲成功学,更多是踩坑实录和工程取舍。适合独立开发者、小团队技术负责人,以及所有对大模型驱动开发感兴趣的人。
1. 为什么要给 AI 套上“缰绳”:Harness 架构的起源
1.1 让 AI 直接写整个项目的教训
最开始,我的想法特别天真:既然大模型那么能写代码,那就让它直接按需求生成一个完整应用好了。我试过用一种“终极提示词”的玩法,把整个项目需求写成几千字的规格书,然后让模型一口气输出几十个文件。结果怎么样?第一天生成的三个核心模块,到了第三天已经完全看不出它们在同一个系统里:一个模块用 Python 写服务端逻辑,另一个模块用 TypeScript 写云函数,还有一个模块甚至自己发明了一个“ORM”,连数据库连接方式都跟另外两个模块完全对不上。
更崩溃的是调试环节。AI 生成的代码在单文件层面看起来有模有样,但一旦有跨模块调用,就会暴露出一堆“幻觉接口”和“命名漂移”。我数了一下,光是修复一个简单的鉴权中间件,就来回跟模型沟通了 17 轮,token 消耗轻松突破 500 万,最终产出的还是 600 行堆着一堆TODO的意大利面。
那一刻我意识到:问题不在模型能力,而在架构失控。真正需要建设的不是“更聪明的提示词”,而是一个能约束 AI 行为、规定输入输出、自动验证结果的运行框架。我当时给这种框架起了个名字——Harness。这个词的本意是“马具”或“保护绳”,用来牵引与约束。Harness 架构的核心就是:AI 模型不再是“自由编码员”,而是框架驱动下的“生成引擎”。
1.2 Harness 架构的三个设计目标
所谓 Harness 架构,本质上是一套围绕 AI 生成过程的控制层。它不是操作系统,也不是微服务架构,而是专门为“大模型参与代码生产”设计的一套工程治理体系。我给自己定了三个硬性目标:
- 确定性接口:AI 只能按照预先定义的接口契约去生成实现,不允许自行发明对外 API。
- 可验证输出:每次生成的结果必须经过编译、静态检查、单元测试三关卡,任何一关失败都不得进入主分支。
- 可审计操作:AI 每一次“写文件”“改文件”“调用工具”的动作都记录在案,出了问题可以追溯,也可以回滚。
听起来很像传统软件工程的 CI/CD,但区别在于:以前我们约束的是人写代码的“结果”,Harness 约束的是 AI 生成代码的“全过程”。
1.3 为什么传统架构撑不住 AI 生成式开发
传统架构的根基是“可预测”。无论是单体、微服务还是 Serverless,开发者都假设代码由人编写,因此可以通过 Code Review、架构评审来卡质量。可当代码由模型自动生成时,你会面临三个传统架构完全没处理过的新问题:
- 不确定性:同一段输入,今天生成的代码和明天生成的代码完全不同。
- 无意识性:AI 根本不知道“自己不知道”,会一本正经地调用并不存在的库。
- 规模化崩溃:AI 生成代码的速度远超人的审查速度,一旦批量生成,问题会指数放大。
这三个问题让我认识到:不能用机械式地“审阅”来应对 AI 生成,而是要从上游把生成行为“圈养”起来。于是我把整个项目的架构改成了以Harness 为核心引擎的形态。后续所有模块,都先定义契约、再让 AI 填肉,最后由 Harness 统一验证发布。这个决定,让我从“被 AI 带着狂奔”的状态回到“骑在 AI 背上控制方向”的状态。
2. 九个月烧掉 40 亿+ token 的账单:钱都花在哪了
2.1 真实消耗拆解:Token 不是花在“写代码”上
四十亿这个数字太抽象,我把它换算成具体的东西:按一次请求平均 5000 字上下文、单轮生成约 2000 字输出算,每月 40 亿 token 大约对应 50 万次 API 请求。这么多请求,真正花在“生成最终代码”上的可能只占三成,其余全浪费在沟通成本、纠错和上下文搬运上。
我从埋点日志里拉了一份消耗分布,大致是这样的:
| 消耗场景 | 占比 | 说明 |
|---|---|---|
| 多轮上下文携带 | 35% | 每次对话都要把系统提示、项目规则、相关代码片段重复发送 |
| Agent 工具调用上下文 | 25% | 检索文件、执行命令、抓取错误信息等工具结果需要写回上下文 |
| 直接生成代码与补全 | 20% | 真正产生有效代码的部分 |
| 错误修复循环 | 15% | 编译失败、测试不通过后的反馈与再生成 |
| 测试生成与解释 | 5% | 生成测试用例和解释性文本 |
看到没?“写代码”本身只占两成,剩下八成都是在解决“如何让模型知道更多信息”和“如何让模型忘记错误信息”。这就是为什么很多人觉得 token 烧得快,真实原因不是模型变贵了,而是整个生产链路太啰嗦。
2.2 我为什么没有靠人肉优化来省 Token
你可能会说:省 token 还不简单?少发几次上下文、精简提示词不就行了?如果只是写几个脚本,确实可以那么干。但我这个项目是 20 万行代码的规模,模块之间彼此依赖,AI 必须理解全局才能生成局部代码。
我一开始试过“极简提示词”策略,结果生成出来的东西完全丢掉了上下文,接口风格混乱,甚至引用已经删掉的历史文件。后来被迫走向另一个极端:每次请求把整个项目的文档都塞进上下文,效率是高了一点点,但 token 消耗直接翻了三倍。那个月账单下来我手都在抖。
真正有效的优化路径,是围绕Harness 架构的分层上下文管理:
- 全局层:只放项目全局规范和接口索引,大约 2 万 token,每次任务固定发送。
- 局部层:每个功能模块的详细设计和相关文件,按需加载,不参与无关任务。
- 即时层:当前编译错误或测试失败的日志,短平快,用后即焚。
这样每一轮对话的平均上下文从 8 万 token 降到了 3 万左右,而生成的代码质量和完整上下文时几乎一致。这一套分级管理,是根治 token 浪费的关键。
2.3 Token 消耗反逼出架构升级
还有一个反直觉的收获:高额 token 账单其实帮了我大忙。因为每个月的花费都在刺激我思考“这段 token 能不能不花”。比如我发现,AI 在修复错误时经常反复犯同一个错,因为它看不到上一次修复的完整“diff”。于是我在 Harness 里加了一块修复记忆区,把过去的失败模式和对应补丁缩存到上下文里。这直接让错误修复循环的 token 消耗降低了 60%,而且错误修复的成功率更高了。
所以你现在看到的 Harness 架构,一半是被 AI 能力推着走,另一半是被每月 40 亿 token 的账单逼出来的。
3. 20 万行代码的工程组织:一个人如何不陷入代码泥潭
3.1 二十万行到底是什么概念
20 万行代码不是一个抽象数字。如果按平均每行代码 30 个字符算,相当于六百万字符,全部打印出来大概是 1200 页 A4 纸。一个人九个月写完,这意味着哪怕不吃不喝纯手写,也需要每天输出 700 行以上高质量代码——这几乎不可能。但借助 AI 生成,一天生成几万行并不难。真正的瓶颈不在“写不写得完”,而在“如何让写完的代码不会互相踩踏”。
我在项目早期因为贪图速度,让 AI 并行生成多个模块。结果两周后,整个代码库里同时存在 4 套时间格式化工具、3 套 HTTP 客户端封装、2 个日志库的混用版本。后来我痛下决心,用 Harness 架构强制统一。
3.2 用“契约优先”来控制模块生成
Harness 架构的模块开发流程,和传统“先设计再实现”最大的区别在于:设计文档不是给人看的,而是给 AI 看的契约体。每个模块启动前,我先用固定的模板定义好:
- 对外暴露的函数签名和数据类型
- 依赖的第三方库及版本区间
- 预期的时间和空间复杂度
- 日志输出规范与错误码范围
- 可接受的单元测试覆盖率阈值
这些规则被写进 Harness 的全局配置里,作为每次生成请求的前置上下文。AI 只能在这些契约的“笼子”里完成实现。一旦它尝试越界,比如擅自引用一个不在白名单里的第三方库,Harness 的静态扫描层会直接拦截并驳回这次生成。
这样做的直接后果,是代码库的模块边界极其清晰。哪怕 AI 生成的两个模块之间毫无交流,它们也能通过统一风格的接口彼此兼容。偶尔需要跨模块调用,我只需要生成一个遵循既定协议的函数签名。这种“契约优先”的开发方式,让我一个人也能维持 20 万行代码的秩序。
3.3 哪些代码必须自己写,哪些可以放心交给 AI
九个月里,我逐渐总结出一个分工原则:
- 基础设施、核心数据结构、算法骨架:这些是整个系统的“地基”,我自己手写。
- 胶水代码、样板代码、CRUD 操作:这些逻辑高度重复,适合完全交给 AI。
- 测试用例:让 AI 生成“常规路径”的测试,边界条件和异常场景我手动补。
- 构建脚本、部署配置:AI 生成初稿,我人工调整细节,防止奇怪的组合。
这样分工以后,代码质量明显上去了一大截。最直观的对比是:早期 100% 靠 AI 生成的分支,bug 修复平均需要 7 轮对话;后来 30% 手写 + 70% AI 生成的分支,修复平均只需要 2 轮。不要以为 AI 会替你解决所有问题,它解决的是“量”,而“质”的底线需要靠人的架构判断守住。
3.4 没有团队 Review,就用自动化流水线兜底
独立开发者最尴尬的是没有第二双眼睛盯着代码。我的解决办法是把 Code Review 的任务“翻译”成一系列自动化关卡:
- 语法检查 + 类型检查(必过)
- ESLint/ Ruff 等规则强制(规则比团队标准还要严一倍)
- 单元测试覆盖率检查(核心模块不得低于 90%)
- 圈复杂度检查(超过阈值自动打回重写)
- 重复代码检测(相似度大于 85% 必须重构)
任何一个 AI 生成的文件,只要没通过五道关卡,就进不了主干。Harness 会把失败原因压缩成一条 200 字以内的错误摘要,重新发给生成模型,让它带着问题重做。这个过程刚开始看着很傻,但反复十几轮后,AI 会逐渐“内化”这些规则,生成的代码一次通过的比率从 35% 上升到 80%。
4. Harness 架构的核心实现:从提示词到代码的闭环
4.1 五层结构的总体设计
如果一句话概括 Harness 架构,那就是:让 AI 像车间工人一样,在固定工位上加工固定零件,而不是让它当自由建筑师。我的实现中有五个核心层:
- 契约层(Contract):定义输入输出、约束和校验规则。
- 状态层(State):记录当前任务的进度、已完成步骤、待办事项和上下文压缩摘要。
- 执行层(Executor):把任务拆解成可执行的小步骤,并调用模型和本地工具完成。
- 验证层(Validator):对生成代码执行编译、测试、静态分析等校验。
- 审计层(Audit):记录每一次模型决策和文件变更,支持回滚。
严格来说,Harness 架构的应用本身也是一个常规应用,它有数据库、API、前端。但所有 AI 相关能力都被这五个层包裹起来。这就像一个“驾驶舱”,大模型只是引擎,而 Harness 是方向盘和刹车。
4.2 一个简化版控制循环示例
我用 TypeScript 写过一个简化原型,感受一下核心逻辑:
class HarnessEngine { private contract: Contract; // 契约 private state: State; // 状态 private validator: Validator; // 验证器 private audit: Audit; // 审计 async run(task: Task): Promise<Result> { // 1. 产出定义好的契约和局部上下文 const prompt = this.buildPrompt(task, this.contract, this.state.getRelevantContext()); // 2. 调用模型生成代码 const rawCode = await this.generateCode(prompt); // 3. 记录原始输出,便于审计 this.audit.log('generate', task, rawCode); // 4. 验证层检查 const validation = await this.validator.validate(rawCode, task.scope); if (!validation.passed) { // 5. 失败则把错误反馈给模型,进入下一次生成 const feedback = this.buildFeedback(validation.errors); this.state.appendFeedback(feedback); return this.run(task); // 重试(有次数上限) } // 6. 通过验证则写入目标文件 this.applyPatch(task, validation.patch); this.state.markCompleted(task); return validation.patch; } }这个循环看着简单,但真正要命的是细节。比如buildPrompt里如何压缩局部上下文、state.appendFeedback时如何避免上下文膨胀、validator.validate中怎样平衡速度与准确性。每一个细节都经历了无数次踩坑,后面我会讲到。
4.3 提示词的结构化:告别自由对话
很多人和 AI 协作时,喜欢像聊天一样把事情丢给模型:“帮我写个 Python 爬虫。”在 Harness 架构里,这种对话方式是被禁止的。所有大模型的输入都必须遵循一个结构化的类型:
{ "task": "generate_implementation", "scope": "module/auth", "contract": { "function_name": "authenticate", "parameters": ["username", "password"], "return_type": "JwtToken", "dependencies": ["crypto-library >= 2.0.0"] }, "code_snippets": ["existing_base64_encoder", "error_codes_from_api"], "constraints": ["no_third_party_orm", "must_pass_eslint_standard"] }这个 JSON 就是 Harness 传给模型的“工单”。模型只需要根据工单产出代码,不需要理解整个项目的宏大背景。经验是:给 AI 的信息越结构化,它的输出就越可控;给它讲一堆模糊理念,它给你返回一堆模糊代码。
另外,我发现把反例放进提示词里非常有效。比如在打回重试时,把上一次的失败错误摘要直接拼接进反馈区,然后附上一句话:“下面是刚才的错误,请不要重现它。”这种“负反馈”比单纯的强调“请正确”有用十倍。我们后面会提到的“token 失效”问题,也是在一次聊天中因为上下文丢失导致模型重复报错,最终靠这种反例提示解决的。
4.4 验证层的设计:AI 生成的代码,如何确保可运行
我遇到的第一个难题,就是验证层的“尺度”。如果验证太严格,AI 产生的代码经常被拒,导致重试次数 skyrocketing;如果验证太宽松,垃圾代码混进来,后期修复的成本更高。
最终我采用“分阶段验证”策略:
- 第 0 级——静态检查(毫秒级):语法解析、文件格式、命名规范。
- 第 1 级——类型检查(秒级):TypeScript 编译、mypy 等。
- 第 2 级——单测验证(分钟级):针对当前模块跑单元测试,快速判断业务逻辑是否符合契约。
- 第 3 级——集成验证(偶尔手动触发):跨模块调用、API 联调,不进入每次生成流程。
大部分问题在 0/1 级就被拦下来,不至于浪费 token 去“验证一个显然错误的实现”。但单测这关不能省,很多 AI 代码“看着没问题”,一跑就挂,所以我坚持每个模块都必须有配套测试。Harness 会在验证不通过时,把测试失败信息压缩成 JSON 里的feedback字段,反馈给模型。这个反馈占用的 token 不多,效果却极其出色。
4.5 工具调用与外部 API 的“马具”:避免 Token 失效悲剧
Harness 架构除了控制代码生成,还要管理所有外部调用,包括大模型 API、文件服务、代码仓库等。这里面最烦人的就是token 失效问题。因为在长任务中,一个访问令牌(Access Token)可能只有几十分钟的有效期,而一个大而全的生成任务可能需要几个小时。如果任务执行到一半令牌过期,之前所有生成和修改全部作废,那种“一地鸡毛”的感觉比丢代码还难受。
我在 Harness 的审计层里加了两个机制:
- 令牌生命周期巡检:每次执行子任务前,检查令牌剩余有效期,低于阈值时先刷新。
- 断点续跑:把整个任务拆成多个“原子操作”,每个原子操作完成后持久化当前状态。这样即使 token 在某个环节失效,重启后也能从断点继续,而不是全部重来。
这两个机制帮我躲过了好几次大面积 token 失效事件。你去看那些错误日志,经常会看到“token exchange failed: error sending request”这类报错。在我这个项目里,这类错误被 Harness 拦截掉,转换成可重试的队列消息,等令牌刷新后再继续。这篇经验就是给那些正在被 token 相关错误折磨的开发者的——千万别让令牌过期毁掉你一整天的生成任务。
5. 踩过的坑:token 失效、上下文爆炸和不可控代码
5.1 Token 失效与刷新机制:一次差点毁掉一个模块的教训
有一次,我写了一个超大规模的模块生成任务,预计要跑两个小时。当时没有断点续跑,所有状态都存在内存里。任务跑到一半,大模型 API 突然抛出一个refresh_token相关的错误——刷新令牌已过期,无法换取新的访问令牌。结果整个进程崩溃,已经生成的十几个文件虽然写入了磁盘,但状态记录全丢了,Harness 无法判断哪些文件是已完成的,哪些是半成品。最终我不得不手动清理所有生成文件,从头再来。
这件事直接催生了 Harness 的“令牌巡检 + 断点续跑”机制。现在每一个左侧的小任务完成后,都会把当前进度和上下文摘要持久化到本地文件。重启后,Harness 会先检查本地是否有未完成的 checkpoint,然后从最后完成的步骤继续。这个机制不仅省 token,还大大提升了任务的成功率。
5.2 上下文爆炸:模型“忘了”你最开始的要求
另一个高频坑,是上下文窗口被塞满导致的“遗忘综合症”。在 Agent 多轮交互中,每一轮工具调用的结果都会追加到上下文里。跑到第 30 轮时,最开始的 2 万字项目规范已经被挤到窗口之外。模型开始胡编乱造,甚至产生了“幻觉依赖”。
我的解法是分层摘要。每完成一步,就把当前对话中最重要的结论压缩成 200 字的摘要,替换掉历史完整信息。实现方式是用一个独立的小模型做摘要,成本很低,但效果立竿见影。后来我发现,很多企业级 AI 应用都需要类似机制,否则长任务必然中途“失忆”。
5.3 AI 生成代码的“风格漂移”与“可维护性陷阱”
如果你让 AI 连续生成几万行代码,它会表现出一种“风格漂移”——今天写的代码和下周写的代码,变量命名习惯都能完全不同。甚至同一个模块里,一会儿用getData,一会儿用fetchData,都指同一个函数。
我最终靠三招遏制:
- 强制规则引擎:通过 eslint/rubocop 等工具内置命名风格检查,不通过直接打回。
- 公共工具函数白名单:所有通用能力必须调用 Harness 框架提供的工具函数,AI 不允许自建“同名方法”。
- 定期重构日:每个月挑一天,让 AI 针对生成的代码做统一重构,输入当前模块最大文件的上下文,要求其输出符合整体风格的版本。
这还不够。更隐蔽的问题是 AI 会生成大量“隐性重复”代码,比如两个模块各自写了一套二分查找。Harness 里加了一个重复代码检测器,只要发现相似度超标的片段,就会自动提取公共方法,并生成补丁替换。这样到项目后期,代码量虽然还有 20 万行,但“有效差异行数”远比实际要少,可维护性也大幅提升。
5.4 第三方依赖“幻觉”:AI 会用不存在的库
最让人头大的一个坑,是 AI 生成代码时随意引用根本不存在的第三方库。比如它可能觉得express-ratelimit-plus这个名字合理,就拿来用,结果npm install直接报 404。比报错更麻烦的是,它可能引用一个真实存在但版本过老的库,导致安全漏洞或者兼容问题。
Harness 的解决方案是在依赖引用之前做一次存在性校验。我在 Validation 层挂了一个查询 npm/pypi registry 的进程,把所有 AI 提议的依赖名和版本号发过去核对。如果名字不存在,直接把错误信息加入反馈,让模型改成白名单内的库。这个环节虽然多占了一点 token,但彻底避免了“编译过了装不上”的低级事故。
5.5 测试用例的盲区:AI 永远不会测试它没想过的边界
AI 生成的测试用例,天然倾向于“顺着实现逻辑走”,很少测试边界条件和异常路径。比如一个parseDate函数,AI 可能会写十几个正常日期用例,却不会测null、空字符串、闰年错误格式。Harness 里没有一个专门的“测试补全器”:它把已有实现和测试代码发给模型,然后强制生成至少 3 个边界用例和 3 个异常用例。刚开始 AI 经常拒绝生成“会让自己代码失败”的用例,后来我发现,只要把“确保测试能暴露失败”明确写进提示词,它就能做得不错。
这些坑,几乎每一个都对应 Harness 架构的一次迭代。从最初只有“生成器+验证器”的两层结构,逐步演化成现在的五层结构,是九个月里被现实一次次教育的结果。
6. 一个人九个月做成这件事,最后想说的几句大实话
如果现在有人问我想不想再来一次,我会说:想,但绝不想用同样的方式再来一次。这九个月里最大的收获不是那 20 万行代码,也不是几十亿 token 烧出来的经验,而是**“如何用框架去驾驭 AI 能力”的工程思维**。
不要迷信“一个人 + AI = 无限生产力”。AI 是引擎,但因为引擎更强大,你对方向盘、刹车和悬挂系统的要求反而更高。Harness 架构说到底,就是你自己给自己造的那套“方向盘、刹车和悬挂”。它不会让 AI 跑得更快,但它能保证 AI 跑得再快也不会翻车。
对于想走同样路线的朋友,我给几个具体的建议,都是拿真金白银换来的教训:
- 第一,先设计契约,再放开生成。没有契约的生成等于盲跑,省下来的时间迟早会在回滚时加倍还回去。
- 第二,把上下文当黄金。每多塞一个词进上下文,就多花一份钱、多一份失忆风险。好好设计分层上下文和压缩机制,比任何提示词技巧都重要。
- 第三,永远留一条手动后门。核心组件、关键数据结构,坚决自己写。AI 可以优化它们、重构它们,但绝不能从零定义它们。
- 第四,对 token 消耗建立“护栏”。别因为生成质量好就无限跑循环。设置单任务重试上限、单日消耗上限,节省的是你的时间和心情。
- 第五,及时写日志。不是给用户看的日志,而是给 AI 看的“重新加载状态”日志。没有这些日志,长任务一断就是灾难。
最后再分享一个小技巧:当 Harness 验证发现错误时,不要直接调用模型“重试”,而是让它先解释“错误可能在哪个环节产生”,然后再给修复指令。这个“先解释原因,再给出修复”的流程,能让失败修复的 token 消耗再降一半。我试过很多次,几乎每次都能稳定生效。
说回开头那个数字——每月 40 亿 token。九个月下来,我已经不会再因为巨大的数字而感到惊讶。真正让我感到惊讶的,是在这个数字之上,通过 Harness 架构,一个人可以撑起一个原本需要一个小型团队才能维护的代码库。那种感觉,大概就是“被 AI 套上缰绳”后的自由吧。