一句话结论
先写分解计划,每一步都不超过 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 | 风险 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | L0 | phase-00-bootstrap | 工程脚手架 | 包结构、配置、日志 | ~30 min | 586.1 KB | 27,803 | 13.9% | 🟢 安全 |
| 2 | L0 | phase-00b-test-harness | 测试 harness | pytest 套件 + cases.yaml | ~20 min | 712.3 KB | 35,746 | 17.9% | 🟢 安全 |
| 3 | L0 | phase-01-url-utils | URL 工具 | 规范化、去重 | ~15 min | 396.4 KB | 22,287 | 11.1% | 🟢 安全 |
| 4 | L0 | phase-02-fetcher | fetcher | 抓取 + 重试 + 限速 | ~40 min | 371.6 KB | 23,902 | 12.0% | 🟢 安全 |
| 5 | L0 | phase-03-storage | 存储 | 原始 HTML / 图片落盘 | ~20 min | 741.1 KB | 35,466 | 17.7% | 🟢 安全 |
| 6 | L0 | phase-04-image-304 | 图片 304 | ETag 缓存命中 | ~30 min | 589.2 KB | 35,200 | 17.6% | 🟢 安全 |
| 7 | L0 | phase-05-trs-parsing | TRS 解析 | 正文 / 图片抽取 | ~45 min | 651.3 KB | 37,537 | 18.8% | 🟢 安全 |
| 8 | L0 | phase-06-ad-classifier | 广告启发式 | role_confidence > 0.85 跳过 | ~25 min | 349.0 KB | 19,656 | 9.8% | 🟢 安全 |
| 9 | L0 | phase-07-hash | 内容 hash | 重复检测 | ~15 min | 389.2 KB | 21,865 | 10.9% | 🟢 安全 |
| 10 | L0 | phase-08-db-connection | DB 连接 | psycopg 连接池 | ~20 min | 569.0 KB | 30,613 | 15.3% | 🟢 安全 |
| 11 | L0 | phase-09-repositories | 仓库层 | 各表 CRUD 封装 | ~40 min | 809.2 KB | 45,095 | 22.5% | 🟢 安全 |
| 12 | L1 | phase-10-prompt | prompt | 文本 prompt 模板 | ~20 min | 517.4 KB | 29,049 | 14.5% | 🟢 安全 |
| 13 | L1 | phase-11-provider | provider | LLM/VL 抽象层 | ~40 min | 285.5 KB | 18,729 | 9.4% | 🟢 安全 |
| 14 | L1 | phase-12-llm-labeler | 文本审核 | LLM labeler | ~30 min | 576.6 KB | 32,191 | 16.1% | 🟢 安全 |
| 15 | L1 | phase-13-vl-labeler | 图像审核 | VL labeler | ~30 min | 512.1 KB | 29,265 | 14.6% | 🟢 安全 |
| 16 | L2 | phase-14-review-workflow | 审核工作流 | review_queue 流转 | ~60 min | 586.4 KB | 34,136 | 17.1% | 🟢 安全 |
| 17 | L2 | phase-14a-api-skeleton | API 骨架 | FastAPI + auth | ~45 min | 942.8 KB | 43,354 | 21.7% | 🟢 安全 |
| 18 | L2 | phase-14b-frontend-skeleton | 前端骨架 | Vite + React | ~40 min | 686.0 KB | 34,326 | 17.2% | 🟢 安全 |
| 19 | L2 | phase-14c-review-pages | 复核页 | 人工复核 UI | ~50 min | 479.6 KB | 23,044 | 11.5% | 🟢 安全 |
| 20 | L2 | phase-14d-stats-dashboard | 统计面板 | stats dashboard | ~40 min | 585.2 KB | 31,588 | 15.8% | 🟢 安全 |
| 21 | L3 | phase-15-bfs-queue | BFS 队列 | 入口队列 + 边界 | ~45 min | 512.9 KB | 36,218 | 18.1% | 🟢 安全 |
| 22 | L3 | phase-16-end-to-end | 端到端 | 单篇最小闭环 | ~30 min | 765.8 KB | 47,010 | 23.5% | 🟢 安全 |
| 23 | L3 | phase-17-scheduler | 调度器 | 周期循环 | ~25 min | 586.6 KB | 30,305 | 15.2% | 🟢 安全 |
| 24 | L3 | phase-18-local-ai | 本地 AI | Ollama(qwen3-vl)接入 | ~40 min | 454.5 KB | 26,395 | 13.2% | 🟢 安全 |
| 25 | L4 | phase-19-cms-profiles | CMS profiles | TRS 等多套解析 | ~60 min | 1067.4 KB | 63,833 | 31.9% | 🟢 安全 |
| 26 | L4 | phase-20-entry-discovery | 入口发现 | robots / sitemap / RSS / 归档 | ~50 min | 988.4 KB | 51,750 | 25.9% | 🟢 安全 |
| 27 | L4 | phase-21-baidu-supplement | 百度补种 | 搜索补 URL | ~30 min | 824.8 KB | 41,211 | 20.6% | 🟢 安全 |
| 28 | L5 | phase-22-bfs-progress-failures | BFS 进度 / 失败 | 分轮 100% | ~35 min | — | — | — | 后补充的文档 |
| 29 | L5 | phase-23-422-retry-queue | 422 重试队列 | 死信队列 | ~30 min | — | — | — | 后补充的文档 |
| 30 | L5 | phase-24-crawl-logging | crawl logging | 抓取事件 | ~35 min | — | — | — | 后补充的文档 |
| 31 | L5 | phase-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。下一个阶段开局,它打开那份摘要,就像接力赛的交接棒——上一棒跑了什么、有哪些坑、有什么约定,全部在文档里,不需要靠它「记」。
为什么这套打法能跑通
事后回看,我把成功归因于三个克制:
- 克制度数:不让任何一次对话背负超过一两个文件的新增/修改。上下文一紧张,模型就开始裁剪,最先被裁的就是你之前告诉它的小约束——这正是它「失智」的真正来源。
- 克制风格:每个阶段的文档格式严格一致,让 AI 永远在同一个心智模型里工作。一旦有阶段偏离模板,上下文就开始悄悄变形。
- 克制记忆:不依赖「模型自己记住上一阶段做了什么」。所有跨阶段信息全部沉淀到
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 不会因为变聪明而帮你完成项目;它会因为每一次接棒时都带着完整上下文而帮你完成项目。
写在最后
这篇文章本身也是用同样的方法写出来的——
先想清楚「读者要知道的三件事」,再决定每节说什么,最后才动笔。
不是为了炫技,是为了在上下文有限的前提下,把该说的事情讲清楚。
