news 2026/10/3 23:44:56

Harness架构实战:一个人九个月写20万行代码与40亿token的取舍

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Harness架构实战:一个人九个月写20万行代码与40亿token的取舍

去年我给自己定了个几乎不可能完成的目标:一个人用九个月时间,写出一款基于Harness架构的应用,顺便把代码量堆到20万行。现在回头看,最难的不是写代码,而是每个月要烧掉40亿+ token,跟模型“对话”烧出来的钱和心智,比任何一行代码都贵。这篇文章不晒项目截图,只讲清楚三个问题:Harness架构到底是什么、一个人怎么扛下20万行代码、token到底烧在哪。

1. 先把“Harness架构”说人话

1.1 为什么叫Harness,不叫Framework或Platform

“Harness”这个词,玩过攀岩、跳伞的人应该不陌生,它是一套把人跟安全绳、装备牢牢绑在一起的吊带。掉下去的时候,真正救你的不是那根绳子,而是绳子跟身体之间的这个连接结构——它保证力量能传递、动作能控制、危险能被卸掉。

软件里的Harness架构做的也是同一件事:把模型、数据源、工具、外部API这些容易失控的组件,统一装进一个“安全吊带”里。它不是框架,不强迫你用一套模板把代码写死;它也不是平台,不给你提供服务器和运行环境。它是一层薄薄的契约:所有内部模块要暴露能力,必须实现这个契约;所有外部调用要进出系统,也必须经过这个契约。任何组件崩了,Harness能接住、能熔断、能降级;任何一次调用都能被追踪,token花了多少、在哪一步出错,全部有据可查。

那为什么不直接叫“中间件”或者“网关”?因为中间件更像是“插在中间的一层”,而Harness强调的是一种“约束关系”——不是帮你转发请求,而是把所有东西绑在一条可控的边界上。这个边界就是安全网,没有它,一旦工作流里某个适配器悄悄改了返回格式,或者某个模型开始输出乱码,整个链路就散了。

1.2 我做的这个应用到底解决什么问题

准确说,我做的是一款“个人AI工作流控制台”。它能干的活听起来不复杂:把本地文件、RSS订阅、数据库、模型调用、定时任务、通知推送,全部挂到统一的Harness下,用一套DSL定义工作流。比如“每天早上八点抓取行业新闻,调用模型生成摘要,推送到IM群”,或者“监控某个网页变化,内容变了就用模型对比差异,发一封邮件”。

但一旦要支持几十个工作流并发执行、几十个数据源轮流接入、模型随时升降级、失败自动重试和降级,“听起来不复杂”的事就变得极其复杂。如果没有Harness层,这些功能最后一定会散落在各种独立脚本里,每个脚本自己处理定时、重试、日志、token计费,最后变成意大利面代码。有了Harness层,每个工作流只是一个声明式配置,真正的执行逻辑全部收敛到同一套调度器里。我只需要保证这一层是稳的,上面挂再多东西都不怕。

这个应用不是给普通用户用的,它的目标用户是像我一样的“重度自动化爱好者”:愿意用配置文件而不是按钮来控制一切,希望所有AI调用能被审计、被配额、被观测的人。说实话,市面上也有不少类似工具,但我需要的是极致的可控性,所以最终决定自己造。

1.3 20万行代码都花在哪了

很多人听到20万行就会觉得这是天文数字,其实拆开看,分布非常典型。我统计过项目里的代码占比:核心Harness运行时大概占35%,各类适配器——包括数据源适配器、模型适配器、输出端适配器——加起来占30%,DSL解析器与校验器占15%,前端控制台占10%,剩下的测试与工具脚本占10%。

这个分布能说明一个问题:真正属于“骨架”的代码只有三分之一,剩下的大头全在“跟外部世界打交道”。每接一个新的数据源,就要处理它的认证、分页、限流、字段映射;每接一个新的模型,就要处理它的参数差异、流式输出、错误码、计费规则。一个人不可能凭手写快速覆盖这么多适配器,但AI辅助下,这种机械性的适配代码反而成了最容易批量生成的部分。20万行听起来吓人,去掉适配器,核心复杂度只属于“一个人可以掌控”的范畴。

2. 一个人为什么敢写20万行代码

2.1 20万行不是敲出来的,是“review”出来的

先算笔账:九个月大概270天,20万行分摊到每天,是740行。纯手动敲键盘,这个量基本不可能,而且就算敲出来,人也废了。我实际的工作流是:先把模块的接口定义、依赖关系、边界条件写成清晰的文档,然后基于文档让模型生成代码,我来做代码审查、修并发问题、补异常分支、跑测试。

每个月烧掉的40亿token,大部分不是用来“写代码”的,而是烧在“让模型理解上下文”上。比如我想改一个已经写了5000行的核心模块,我可能要把这个模块的源码、相关测试、设计文档、最近几个issue的讨论全部丢给模型,让它基于完整上下文给出重构方案。这一步的输入token就是几千甚至几万。再比如调试一个偶发bug,我要把堆栈日志、相关数据样本、模型输出记录一起喂进去,让它帮我猜根因。这种“上下文密集型”的用法,token消耗远比生成代码要恐怖。

所以“AI辅助编程”的正确姿势不是让AI从头写一个巨大文件,而是把它当成一个记忆力极好、代码基本功扎实的结对搭档。你负责方向和决策,它负责写初稿和找资料。10万行代码里,可能有7万行初稿是模型写的,但每一行都经过我的审查和修改。这个工作量依然很大,但量级从“不可能”变成了“拼一拼可以”。

2.2 用代码结构对抗“三个月后自己看不懂”

一个人维护大型代码库,最大的敌人不是写不出来,而是三个月后回头看,自己都不认识自己写的东西。我的解决方案是把Harness架构当成项目管理工具来用。

具体做法是:每个模块严格自包含。接口定义、实现、测试、文档、示例代码都放在同一个目录包内,模块之间只允许依赖Harness核心层暴露的公开API,禁止跨模块直接import内部实现。这个约束我写在CI脚本里,违反就直接构建失败。这样做的效果是:当我需要重构任何一个模块时,只需要打开那一个目录,不需要去全局搜索谁引用了我的内部类。

这个约束看起来简单,执行起来非常考验自制力。因为有的时候赶进度,你会忍不住想“就这一次,直接import一下省事”。但只要放纵一次,一个模块的边界就被破坏,后续所有模块都开始互相纠缠。到了第三个月,已经没有办法安全地修改任何代码了。所以我在项目里专门留了一个工具脚本,每次提交前自动检查模块依赖边界,这可能是整个项目里最值得的一百行代码。

2.3 九个月的时间线:打怪升级式推进

我的时间分配大概是这样的:前两个月搭核心Harness运行时和DSL解析器,这两个月是地基,不能求快,每天写得很少但要求每行都经过推敲;第三到第五个月集中写适配器和前端控制台,这段时期代码量增长最快,因为适配器都是一套模式复制粘贴再修改,很适合AI批量产出;第六到第七个月做联调和压测,主要发现一些分布式场景下的问题,比如并发调度冲突、token配额失效、网络重试风暴;第八到第九个月做文档、示例、发布准备。

每个阶段我都设了硬性退出条件,不满足不许进入下一阶段。比如“核心Harness必须通过故障注入测试”的意思是,我会随机杀掉某个数据源连接,观察工作流会不会卡死、能不能降级;“适配器覆盖率”要求所有主流数据源必须能跑通端到端。没有这些闸门,项目很容易陷入“前面偷工减料,后面疯狂填坑”的恶性循环。

3. 核心工程细节:Harness层的设计与实现

3.1 统一接入协议:所有外部能力都是插拔的

Harness层最核心的设计是三个抽象接口:数据源Source、输出端Sink、模型端点ModelEndpoint。

Source统一暴露connect()、poll()、parse()三个方法,无论你连接的是数据库、RSS还是网页文件;Sink统一暴露send(),无论是发邮件、发IM消息还是写入数据库;ModelEndpoint统一暴露complete()、stream()、cost(),无论底层是哪个大模型。每个组件还必须上报自己的健康状态、最后成功时间、错误计数。

这套设计的价值在于:当我需要把某个模型从A换成B时,不需要修改任何工作流定义,只需要写一个新的ModelEndpoint适配器,在配置里切换实现即可。数据源同理。整个Harness核心从来不需要知道某个具体适配器怎么实现,它只要按统一契约去调用。这样,适配器的增删不会影响核心稳定性,核心的升级也不会破坏现有适配器。这就是可插拔的力量。

你可能觉得这套接口设计平平无奇,但真正关键的是错误处理也统一了。所有适配器抛出的异常都会被Harness捕获,包装成带错误码、上下文、重试次数的统一错误对象。工作流可以针对不同错误码走不同策略:超时走重试,认证失败走刷新token,限流走退避,数据格式错误走告警。没有这个统一包装,每个适配器自己写异常逻辑,那就真的失控了。

3.2 上下文管理与token配额控制:烧出40亿的核心原因

为什么一个月能烧出40亿token?因为执行一个工作流时,必须把任务描述、数据样本、历史结果、工具定义全部塞给模型。如果无脑灌,一次调用就可能吃掉上万token,几十个工作流跑一天,几千万token就没了。

我的对策是“分层上下文”。第一层是常驻指令,只放最核心的1000 token,描述整体角色和任务目标;第二层是数据明细,按需从数据源流式取,不一次性全部注入;第三层是历史记录,用摘要折叠的方式压缩,只保留最近5轮的关键节点;第四层是工具定义,只在模型需要调用工具时才注入相关schema。

每一层都设置了预算上限,超了就拒绝执行,而不是静默截断。给每个工作流还设了单次执行token上限、每日总预算。一旦某个死循环或者异常逻辑开始疯狂调用,它会先触达配额,被Harness熔断,而不是把当月额度烧光。这套配额系统大概花了三周时间实现,但它是在第二个月下旬才做的,前几周确实出现过一天烧掉几百万token的血泪教训。

3.3 可观测性三件套:再贵的token也要花得明明白白

没有可观测性,40亿token花哪去了根本说不清。因此Harness层对每一次模型调用、数据拉取、输出发送,都统一输出七个字段:组件名、操作类型、输入token、输出token、耗时、错误码、重试次数。汇总之后,前端控制台实时展示每个工作流的花费排行。

我在关键链路上还埋了“span id”,一个工作流从触发到结束,所有日志都带着同一个ID。一旦出错,我可以把日志里所有相关记录串成一条完整链路,看到底是哪个环节慢了、哪个调用返回了垃圾数据、哪个token在哪个环节消耗最多。

这套系统帮我在后期排查了大量问题。举个例子,有一次我发现某个工作流每天固定烧掉几百万token,排查后发现是历史消息把每次的完整输出都追加到上下文里,导致上下文越来越长。因为可观测性里能看到该工作流的输入token曲线持续上涨,我很快定位到这个问题。如果没有这套数据,这种问题可能会被我忽略很久。

4. token烧了40亿+,钱花在哪,怎么省

4.1 40亿token的真实账本:时间比token贵

每个月40多亿token,听起来很疯狂。折算成费用,如果大部分调用高端模型,按市场价大概是每月几万到十几万元人民币的规模;如果混合使用平价模型,会低不少,但依然是普通人无法承受的成本。个人项目烧到这个量,需要特别清醒地认识到一个逻辑:时间其实比token贵得多。

比如有一个模块,我手写可能要一周,模型辅助写加我来改可能只要一天,中间烧掉几百万token。这一周的人力时间成本,远远超过那几百万token的费用,所以这个交换是划算的。反过来,如果只是改一个README或者调一个CSS颜色,也要开一个十几万token的对话,那就是纯浪费。我的原则是:只在“上下文复杂、需要快速产出初稿、需要快速理解陌生代码”的时候重度使用模型,简单的机械操作绝不浪费token。这台账最后算下来,40亿token换来的是一年之内完成了原本需要团队做两三年的工作量。

4.2 省token三板斧:缓存、批处理、上下文压缩

第一板斧是缓存。相同输入、相同请求参数的调用结果,写进Redis缓存,命中直接返回。模型输出有很大的重复性,尤其是摘要类任务、固定格式生成类任务,缓存命中率能达到30%~40%。这部分省下来的token等于白赚的。

第二板斧是批处理。很多场景不需要实时响应,比如“批量审核十篇文章并打标签”,完全可以并发拆成多个子任务,然后在同一个上下文里合并处理,或者直接用模型服务商提供的batch接口。实践下来,批处理的token总量能比逐条调用省将近一半,因为请求头、指令、公共上下文只需要传一次。

第三板斧是上下文压缩。历史消息不要无限追加,每次对话结束后,先用模型把这一轮的重要结论压成300字摘要,下一轮只带摘要和最新消息。这跟人脑遗忘曲线很像,既保留了关键信息,又控制住了上下文膨胀。这三板斧是我在第二个月做完的,之后token消耗的速度才算是被压住了。

4.3 别被“上下文越长越好”骗了:4k能解决就绝不用32k

长上下文是token黑洞,也是效果陷阱。同样的任务,4k token能解决的,非塞进32k上下文,成本直接翻几倍,而且模型并不一定做得更好。上下文越长,模型越容易在无关信息里迷失重点,输出质量反而可能下降。

我刚开始做的时候,总是怕模型信息不足,把一堆文档全部塞进去。后来发现,很多场景下,模型只需要几条关键规则和少量示例。所以后来我立了一个规矩:任何工作流先写最小上下文,能跑通再逐步加。每次加内容都要观察效果指标——如果效果没有实质提升,立即回滚。这个原则帮我省下了大概20%~30%的token消耗,也让很多任务的输出质量更稳定。记住,给模型的“资料”不是越多越好,而是越精准越好。

5. 常见坑与排查实录

5.1 token失效与续签的疑难杂症

应用要调用大量外部API,token管理是绕不开的坑。我几乎把所有经典报错都踩了一遍。

“sign-in could not be completed token exchange failed: error sending request for url”这类错误,九成是网络超时或者服务商临时故障,重试时要带指数退避,不要立刻原地重试;“token endpoint returned 403 forbidden: country, region, or territory not supported”说明被地域限制拦截,没有别的办法,只能切换到合规的接入区域;“failed to refresh token: 400 bad request: invalid 'refresh_token': empty string”这种,多半是把过期access token又当成refresh_token传了过去,或者存储时字段写串了。

还有JWT续签的经典陷阱:refresh token不要放在前端localStorage,很容易被偷;续签接口必须校验refresh token是否已撤销;access token过期时间要设置一个合理的滑动窗口,不能等到最后一秒才去刷新。这些坑我都记录在项目wiki里,基本每一条都花费了我几个小时到一天的排查时间。对单体开发者来说,这种“token玄学”问题最消耗意志力。

5.2 长上下文丢失与格式错误的排查

当工作流里需要模型处理长文档时,最常见的问题是输出截断、JSON格式错误、字段串位。一开始我以为是模型不行,后来排查下来发现,往往是因为上下文里混入了旧版的输出示例,或者输出schema没有做严格校验。

对策有两个。第一,所有模型输出先过一层schema校验器,校验失败就自动重试一次,同时把具体的失败原因——比如“第3行缺少required字段summary”——写回给模型,让它修正。第二,维护一个“输出示例库”,每次生成时,把最新、最成功的示例注入到上下文里,而不是让模型凭印象输出。这两个改动落地以后,低级的格式错误率下降了80%以上。在AI应用里,严格要求输出格式,与严格要求接口协议同样重要。

5.3 一个人维护20万行代码的取舍

九个月写出来不算本事,后续继续维护才是真本事。我的经验第一条是:学会删代码比写代码更重要。20万行里其实有一部分是“试错产物”,一旦证明某条路走不通,我会毫不犹豫地删掉整个模块,而不是想着“以后可能还用得上”。留着僵尸代码的后果是,每次全局搜索都会多出一堆干扰项,心智负担越来越大。

第二条是“单人重构规则”:每次改动影响超过5个文件,先停下来画依赖图,评估是不是该拆模块了。一个人没有团队review,必须用纪律代替监督。你可以给自己写一个checklist,每次大改动之前强制核对:接口是否兼容、测试是否覆盖、文档是否更新、依赖是否越界。这4条每次都能筛出一堆问题。

还有一条心得是:每天只允许自己花两个小时“扫尾”,剩下时间必须用于业务功能推进。因为一个人太容易陷入无关紧要的完美主义,比如调某个控制台的圆角,或者给某个工具函数写花哨的装饰器。这些事放到最后再做,核心链路才是决定项目生死的东西。

如果非要给后来者一句建议,我会说:别把20万行代码当目标,把它当结果。你在解决真实问题、持续迭代的过程中,代码量自然会生长到这个体量。token烧多少也同理,它不是KPI,只是你换取时间和稳定性的成本。把注意力放在架构边界和可观测性上,烧掉的token才能变成真正推进项目的力量。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 23:27:01

灰狼算法优化VMD参数:Python实现自适应信号分解

简介:这份资源面向信号处理、故障诊断与算法开发方向的学习者,提供用灰狼算法(GWO)自动优化变分模态分解(VMD)参数的Python实现。VMD虽能自适应提取非线性、非平稳信号的频率成分,但中心频率、正…

作者头像 李华
网站建设 2026/10/3 23:26:59

基于NSGA-Ⅲ的梯级水火联合多目标调度Matlab实现与解析

干电力系统调度这块的人应该都清楚,水火联合调度是个老问题,但也是个始终没被彻底解决好的问题。过去我们靠人工经验排计划,后来用线性规划、动态规划,再往后越来越多的人开始尝试多目标进化算法。这个项目做的就是基于NSGA-Ⅲ优化…

作者头像 李华
网站建设 2026/10/3 23:17:46

基于深度学习的个人贷款违约预测系统:Python源码实现与避坑指南

简介:这份资源是面向计算机、人工智能、自动化等专业学生与从业者的深度学习实战项目包,以个人贷款违约预测为主题,可用于课程设计、大作业或毕业设计参考。项目代码经过调试测试,注释详尽,并附有运行教程文档&#xf…

作者头像 李华
网站建设 2026/10/3 22:40:35

如何为 Magpie 编写自定义效果:MagpieFX HLSL 效果格式完全指南

如何为 Magpie 编写自定义效果:MagpieFX HLSL 效果格式完全指南 【免费下载链接】Magpie Unofficial experimental Magpie fork with colour-only DLSS, FSR2 and NVIDIA RTX Video integrations 项目地址: https://gitcode.com/gh_mirrors/magpie27/Magpie …

作者头像 李华
网站建设 2026/10/3 22:23:03

门窗保温---凭啥别人做的比你好!(下)

门窗保温---凭啥别人做的比你好!(下) 如何提高门窗保温性(戳这回顾),那到底这么个提高法呢?且看。 首先是室内热量通过对流和辐射传递给门窗内表面,那么是不是可以通过改变这两种传热方式来降低热量传递强度呢? 答案是可以。 从降低辐射传热角度,Low-E玻璃膜层可位…

作者头像 李华
网站建设 2026/10/3 22:17:45

Agent Reach:给 OpenClaw 一键装上“互联网能力”的 Skill 配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华