我用一天时间,靠 AI 写了一个完整的项目

发布于 阅读 56未分类

一句话结论

先写分解计划,每一步都不超过 AI 的上下文。上下文不丢失,是 AI 不失智的关键。


为什么做这件事

AI 写代码这一年,我反复踩同一个坑:聊到一半,它开始胡说八道——记错我已经做过的决定,生成不存在的 API,或者对一个早就解决的问题重新设计一遍。

后来我才意识到:这不是它变笨了,是上下文丢了

每一次新对话,它都要从零开始「猜」我要什么;猜得准的时候像神,猜不准的时候就一本正经地编。我需要的不是更大的模型,是让它在每一次接棒时都带着完整的记忆

所以我给自己定了一个目标:用一天时间,做一个完整的、能跑的项目,验证「AI 在不丢上下文的前提下,究竟能陪我走多远」。


起因:Token用不完

这个项目的缘起其实特别朴素——

前段时间我买了 MiniMax 的 Token Plan Max 版好友订阅享9折+Builder权益),发现一个问题:用不完

那就得想办法烧一烧。最直接的法子,就是找一个需要大量 AI 调用的真实场景

想来想去,冒出来一个朴素的想法:爬虫 + AI 审核。把一个新闻站的全站文章都爬下来,然后扔给 AI 让它一条一条判断内容有没有问题。Token 消耗量级天然就是「文章数 × 每篇审核成本」,这个量级肯定烧得动

就这样,需求就有了:采集 + 审核 + 落库。剩下的——用什么爬虫、怎么调度、AI 怎么接——都是为这个朴素需求服务的工程细节。

更新于2026年6月14日11:47:33: 事实上我天真了,MiniMax有限流规则,审核新闻经常触发422、速度过快的时候会触发429报错,烧Token的速度远低于我的预估。


项目是什么

一个新闻子站的内容采集 + 审核系统。从一个新闻站出发,顺着站内链接把能抓到的文章都拉回来,正文/图片抽出来,扔给 AI 做内容审核,三档标签(非法 / 存疑 / 正常)落库,然后周期循环。

没什么炫技,就是把「采集 → 解析 → AI → 入库 → 调度」一条链路从头到尾走一遍。 单机、单人、本地数据库,只为验证方法论

跑完一天后,这个东西确实在跑:8 个子站、端到端通过,210+ 个离线测试用例绿。但数字不重要,方法才重要。


怎么做(核心方法论)

我做的事情,只有三步。但每一步都极端刻板。

第 1 步:写分解计划,不写一行代码

这是最反直觉的一步。

正常人(包括以前的我)会打开 IDE,「先搭个骨架吧」。但我做的事是先打开文档,用自然语言把项目切成 31 个阶段,按依赖从下到上排好:

注:「估时」列是基于阶段复杂度的估算,非实测;实测用时未在 handoff 里记录。

#阶段主题一句话产出估时会话大小峰值 token占 200K风险
1L0phase-00-bootstrap工程脚手架包结构、配置、日志~30 min586.1 KB27,80313.9%🟢 安全
2L0phase-00b-test-harness测试 harnesspytest 套件 + cases.yaml~20 min712.3 KB35,74617.9%🟢 安全
3L0phase-01-url-utilsURL 工具规范化、去重~15 min396.4 KB22,28711.1%🟢 安全
4L0phase-02-fetcherfetcher抓取 + 重试 + 限速~40 min371.6 KB23,90212.0%🟢 安全
5L0phase-03-storage存储原始 HTML / 图片落盘~20 min741.1 KB35,46617.7%🟢 安全
6L0phase-04-image-304图片 304ETag 缓存命中~30 min589.2 KB35,20017.6%🟢 安全
7L0phase-05-trs-parsingTRS 解析正文 / 图片抽取~45 min651.3 KB37,53718.8%🟢 安全
8L0phase-06-ad-classifier广告启发式role_confidence > 0.85 跳过~25 min349.0 KB19,6569.8%🟢 安全
9L0phase-07-hash内容 hash重复检测~15 min389.2 KB21,86510.9%🟢 安全
10L0phase-08-db-connectionDB 连接psycopg 连接池~20 min569.0 KB30,61315.3%🟢 安全
11L0phase-09-repositories仓库层各表 CRUD 封装~40 min809.2 KB45,09522.5%🟢 安全
12L1phase-10-promptprompt文本 prompt 模板~20 min517.4 KB29,04914.5%🟢 安全
13L1phase-11-providerproviderLLM/VL 抽象层~40 min285.5 KB18,7299.4%🟢 安全
14L1phase-12-llm-labeler文本审核LLM labeler~30 min576.6 KB32,19116.1%🟢 安全
15L1phase-13-vl-labeler图像审核VL labeler~30 min512.1 KB29,26514.6%🟢 安全
16L2phase-14-review-workflow审核工作流review_queue 流转~60 min586.4 KB34,13617.1%🟢 安全
17L2phase-14a-api-skeletonAPI 骨架FastAPI + auth~45 min942.8 KB43,35421.7%🟢 安全
18L2phase-14b-frontend-skeleton前端骨架Vite + React~40 min686.0 KB34,32617.2%🟢 安全
19L2phase-14c-review-pages复核页人工复核 UI~50 min479.6 KB23,04411.5%🟢 安全
20L2phase-14d-stats-dashboard统计面板stats dashboard~40 min585.2 KB31,58815.8%🟢 安全
21L3phase-15-bfs-queueBFS 队列入口队列 + 边界~45 min512.9 KB36,21818.1%🟢 安全
22L3phase-16-end-to-end端到端单篇最小闭环~30 min765.8 KB47,01023.5%🟢 安全
23L3phase-17-scheduler调度器周期循环~25 min586.6 KB30,30515.2%🟢 安全
24L3phase-18-local-ai本地 AIOllama(qwen3-vl)接入~40 min454.5 KB26,39513.2%🟢 安全
25L4phase-19-cms-profilesCMS profilesTRS 等多套解析~60 min1067.4 KB63,83331.9%🟢 安全
26L4phase-20-entry-discovery入口发现robots / sitemap / RSS / 归档~50 min988.4 KB51,75025.9%🟢 安全
27L4phase-21-baidu-supplement百度补种搜索补 URL~30 min824.8 KB41,21120.6%🟢 安全
28L5phase-22-bfs-progress-failuresBFS 进度 / 失败分轮 100%~35 min后补充的文档
29L5phase-23-422-retry-queue422 重试队列死信队列~30 min后补充的文档
30L5phase-24-crawl-loggingcrawl logging抓取事件~35 min后补充的文档
31L5phase-25-per-site-logs每站独立日志站点隔离日志~30 min后补充的文档

几件值得标注的事:

  • L0(11 个)最重:它要为后续所有阶段铺路,所以单阶段虽小,加起来 ~5 h——约占 1/3。但这部分没做好,后面每一阶段都在补窟窿,所以慢得值。
  • P14(审核工作流)是单阶段最长(~60 min):状态机 + pydantic schema + queue 流转,逻辑密度最大。
  • P19(CMS profiles)第二重(~60 min):从单子站到多子站,本质是一次抽象升级,容错压力陡增。
  • L5 四个加起来 ~2 h:每个都是独立的可观测性模块,但都建立在 L0–L4 已有的事件和日志之上,所以单阶段不重——这是分层切的复利

每个阶段足够小——小到「一段对话之内能讲清楚要做什么、文件树长什么样、代码骨架是什么、要测什么、怎么验收」。

这一步花了我整个晚上的大部分时间。没有这段,后面都是白搭。

这套切法遵循三条原则

① 粒度原则:每阶段都是独立可关闭的盒子

任何一个阶段出 bug,我都能定位到「是 L 几 P 几埋下的」;回滚它,不需要重新拆解整个项目。表里 31 行,等于 31 个独立盒子,互不污染

② 分层原则:下层不变,上层才能稳

L0(基础)稳定前,L1(AI)不动;L1 稳定前,L2(UI)不开。不是「并行交付」,是「串行收敛」——每层都在它的下层彻底固化之后才开始。这跟盖楼一模一样:地基没浇完,不要上来就砌墙。

③ 依赖原则:跨阶段记忆搬到文件系统

同一段对话内,模型靠上下文;跨阶段、跨会话,docs/plans/handoffs/PXX-summary.md。每一棒交付时,都照模板写清「实际决策 / 测试结果 / 已知问题 / fixtures 清单」,下一棒开局强制读上一棒——接力赛交接棒,而不是靠脑子记。

第 2 步:每个阶段都按一个固定模板写文档

每个 phase-XX-xxx.md 都长一个样:

章节内容
§0 目标这个阶段要解决什么问题
§3 文件树新建/修改哪些文件,放在哪
§5 代码骨架关键函数签名 + 关键逻辑
§7 测试用例这次要往 test/cases.yaml 追加哪些
§8 验证步骤跑哪条命令、看什么输出
§10 交付摘要模板下一阶段开头要看的 handoff 长什么样

刻板到令人发指。但这正是价值所在——AI 不需要每次都重新理解「我现在该干嘛」,它照着模板填就行。

第 3 步:每一次开新对话,先用「标准启动 prompt」

这是我最得意的一个设计。每个阶段开始时,我贴一段固定模板:

阅读 docs/plans/phase-XX-xxx.md 拿到本阶段任务; 先读 docs/plans/handoffs/PX(X-1)-summary.md(若存在)拿到上一阶段交付; 然后执行 phase-XX 的所有任务; 完成时照 §10 交付摘要模板产出 handoffs/PXX-summary.md; 最后向我报告本阶段交付、case 通过/失败数、已知问题。

这段 prompt 的关键,是强制它读上一阶段的 handoff

每个阶段结束,我会照着模板把这次的「实际决策 / 测试结果 / 已知问题 / fixtures 清单」写进 handoffs/PXX-summary.md。下一个阶段开局,它打开那份摘要,就像接力赛的交接棒——上一棒跑了什么、有哪些坑、有什么约定,全部在文档里,不需要靠它「记」。


为什么这套打法能跑通

事后回看,我把成功归因于三个克制:

  1. 克制度数:不让任何一次对话背负超过一两个文件的新增/修改。上下文一紧张,模型就开始裁剪,最先被裁的就是你之前告诉它的小约束——这正是它「失智」的真正来源。
  2. 克制风格:每个阶段的文档格式严格一致,让 AI 永远在同一个心智模型里工作。一旦有阶段偏离模板,上下文就开始悄悄变形。
  3. 克制记忆:不依赖「模型自己记住上一阶段做了什么」。所有跨阶段信息全部沉淀到 handoffs/ 目录里——这是机器读得到的记忆,不是模型临时上下文里的草稿。

换句话说,我把「上下文」从「对话窗口」搬到了「文件系统」。窗口会被截断,文件不会。


多模型互校:不迷信任何单一 AI

上面三件事都是「自我克制」。但还有一条更外向的原则——不要只让一个 AI 审你的计划

我自己的做法是:写完计划 → 让 Qoder(挂 Qwen3.7-Max,每天 200 个 Credits 够日常审一两个计划)过一遍 → 它会从另一个角度提一堆问题 → 把这些问题打包带回 Claude Code → 让它自己判断「合理的接、拍脑袋的拒」 → 改完再扔回 Qoder 复审 → 直到它回复「全部修复」

这条流水线看起来啰嗦,但它解决的是单一模型的盲区——

  • 有些问题是真坑,被另一个模型一戳才发现(尤其是跨阶段的依赖、边界条件的死角)
  • 有些问题是模型对模型的偏好(比如 A 觉得函数要拆,B 觉得合在一起更顺)——这种就要靠 Claude Code 自己拿主意,不能让审稿的当作者的
  • 真正关键的是最后一步:「全部修复」不是审稿人说了算,是你说了算。Qoder 说修完了,你再用 Claude Code 的最终判断过一遍——单一信源永远比多源更危险,AI 评审也不例外

所以如果你只有时间做一件事:计划写完,先扔给第二个 AI 审一轮。哪怕只是免费额度的 Qwen、哪怕只是另一个网站上的 Claude 对话窗口——让两个模型在你开工前先吵一架,你当裁判

这跟工程里的 code review 一个道理:一份重要方案,不应该只有一个审稿人。


顺手验证:把这套方法用在自己博客上

写完这篇博文,我顺手让这套系统跑了一下我自己的博客——

顺手让这套系统跑了一下我自己的博客

抓到 76 个页面,正好是这个站点的 76 篇文章,一个不多一个不少。

本来只是想做个 smoke test 验证 schema 没坏,结果意外地干净。最有意思的不是「抓到了多少」,而是「一个我自己都觉得是黑盒的系统,对自己的内容也能精确盘点」——它对你诚实,对自己也诚实。


一天之后,长什么样

  • 26 个阶段,从脚手架到调度器到 Web UI,全部按节奏跑完
  • 84 个 Python 文件,约 8300 行代码(不含 prompt / 文档 / 测试)
  • 210+ 离线测试用例通过
  • 每个阶段都有交付摘要,串起来就是一整本「决策日记」

最后还有一个意外的副产品:因为每阶段都是独立闭环,任何一处出 bug,基本都能定位到「是哪个阶段埋下的」——事后回滚某个阶段,不需要重新拆解整个项目。


给同样想用 AI 写项目的人

如果只能带走一句话:

不要让 AI 帮你写代码,先让它帮你写「写代码的计划」。

具体地讲:

  • 产出阶段文档,产出代码
  • 文档要刻板到能当合同用(目标 / 文件树 / 骨架 / 测试 / 验收 / 交付模板)
  • 阶段之间靠 handoffs/ 交接,不要靠对话记忆
  • 每次开新对话,先贴你的「标准启动 prompt」,强制它读上一棒的交接
  • 计划定稿前,先让第二个 AI 审一轮——多模型互校,你当裁判

AI 不会因为变聪明而帮你完成项目;它会因为每一次接棒时都带着完整上下文而帮你完成项目。


写在最后

这篇文章本身也是用同样的方法写出来的——

先想清楚「读者要知道的三件事」,再决定每节说什么,最后才动笔。

不是为了炫技,是为了在上下文有限的前提下,把该说的事情讲清楚

评论 (0)
0 / 500
暂无评论,快来抢沙发~