vault: auto-sync 2026-03-19 02:00

This commit is contained in:
lizikk 2026-03-19 02:00:01 +08:00
parent 4c1f2d707c
commit ab44aca650
2 changed files with 575 additions and 0 deletions

View File

@ -0,0 +1,413 @@
---
id: "2026-03-18-autoresearch-dao-analysis"
title: "Autoresearch 道-法-术-器深度剖析"
slug: "autoresearch-dao-analysis"
status: "inbox"
content_type: "article"
channels: []
language: "zh-CN"
source_urls:
- "https://github.com/karpathy/autoresearch"
assets: []
cover_image: ""
template: "article"
owner: "content-forge"
created_at: "2026-03-18T00:00:00+08:00"
updated_at: "2026-03-18T00:00:00+08:00"
published_at: null
tags:
- "ai-research"
- "autonomous-agent"
- "karpathy"
- "llm-training"
- "dao-analysis"
---
# Autoresearch 道-法-术-器深度剖析
> 分析对象:[karpathy/autoresearch](https://github.com/karpathy/autoresearch) — AI Agent 自主 LLM 研究框架
> 分析框架:道-法-术-器 8 层结构化分析
> 分析日期2026-03-18
---
## 项目概要
Karpathy 于 2026 年 3 月发布的实验项目。核心思想:
> **让 AI Agent 自主进行 LLM 训练研究**——Agent 修改代码、训练 5 分钟、检查结果、保留或丢弃,循环往复。你睡一觉醒来,收获 ~100 次实验结果。
### 架构(极简三文件)
```
autoresearch/
├── prepare.py # 固定不变数据下载、BPE tokenizer、dataloader、评估函数
├── train.py # Agent 唯一可修改的文件GPT 模型 + Muon/AdamW 优化器 + 训练循环
├── program.md # 人类唯一修改的文件Agent 的"技能指令"
└── pyproject.toml # 依赖PyTorch 2.9.1 + CUDA 12.8
```
分工边界:
- **人类** → 编辑 `program.md`(定义研究策略、约束、指令)
- **Agent** → 编辑 `train.py`(修改架构/超参/优化器/batch size 等一切)
- **固定**`prepare.py`(评估函数 `evaluate_bpb` 是铁律,不可改)
### 技术栈train.py ~430 行)
| 组件 | 实现 |
|------|------|
| 模型 | GPTRoPE + Flash Attention 3 + RMS Norm + Sliding Window |
| 优化器 | MuonAdamW 混合:矩阵参数用 MuonPolar Express 正交化),其余用 AdamW |
| 激活函数 | ReLU² (`F.relu(x).square()`) |
| Value Embedding | ResFormer 式 Value Residual交替层gated |
| 残差连接 | 可学习 `resid_lambdas` + `x0_lambdas`x0 residual shortcut |
| Logit 处理 | Soft capping at 15 (`15 * tanh(logits/15)`) |
| 默认配置 | 8 层、768 dim、6 头、~50M 参数 |
| 训练时长 | 固定 300 秒5 分钟 wall clock不含启动/编译) |
| 评估指标 | `val_bpb`bits per bytevocab-size 无关,低更好) |
### 实验循环
```
LOOP FOREVER:
1. 读 git 状态
2. 修改 train.py一个实验想法
3. git commit
4. uv run train.py > run.log 2>&1 (固定 5 分钟训练)
5. grep val_bpb / peak_vram_mb run.log
6. 崩溃?→ tail -n 50 run.log 修复或跳过
7. 记录 results.tsv
8. val_bpb 改善 → keep推进 branch
val_bpb 未改善 → discardgit reset 回退)
关键约束NEVER STOP人类可能在睡觉
```
---
## 证据表 E#
| E# | 原句/要点 | 类型 | 可信度 |
|----|-----------|------|--------|
| E1 | "The idea: give an AI agent a small but real LLM training setup and let it experiment autonomously overnight" | 事实 | 高README 原文) |
| E2 | "you're not touching any of the Python files like you normally would as a researcher. Instead, you are programming the `program.md` Markdown files that provide context to the AI agents" | 观点 | 高(核心设计意图,作者明确陈述) |
| E3 | 固定 5 分钟时间预算(`TIME_BUDGET = 300`),不论硬件不同,始终 300 秒 wall clock | 事实 | 高(`prepare.py:36` 硬编码常量) |
| E4 | 评估指标 `val_bpb`bits per byte——vocab-size 无关,排除 special tokens | 事实 | 高(`prepare.py:341-362` 实现) |
| E5 | "NEVER STOP: Once the experiment loop has begun, do NOT pause to ask the human... The loop runs until the human interrupts you, period." | 事实 | 高(`program.md` 原文) |
| E6 | "Simplicity criterion: All else being equal, simpler is better. A small improvement that adds ugly complexity is not worth it." | 观点 | 高(`program.md` 原文,核心设计哲学) |
| E7 | 三文件架构prepare.py固定、train.pyAgent 编辑、program.md人类编辑 | 事实 | 高README + 代码一致) |
| E8 | MuonAdamW 混合优化器——矩阵参数用 MuonPolar Express 正交化 + NorMuon 方差减少),其余用 AdamW | 事实 | 高(`train.py:209-300` 实现) |
| E9 | 模型包含多项前沿技术Value EmbeddingResFormer、可学习残差 λ、x0 shortcut、ReLU²、Logit soft capping | 事实 | 高(`train.py:36-200` 实现) |
| E10 | 实验结果记录为 TSVcommit/val_bpb/memory_gb/status/descriptiongit branch 管理,改善推进/未改善回退 | 事实 | 高(`program.md` 原文) |
| E11 | "The downside is that your runs (and results) become not comparable to other people running on other compute platforms" | 观点 | 高README 作者自述 tradeoff |
| E12 | "VRAM is a soft constraint. Some increase is acceptable for meaningful val_bpb gains, but it should not blow up dramatically" | 观点 | 高(`program.md` 原文) |
| E13 | 社区已从 "weekend experiment" 演变为 "community-driven framework",有 macOS/MLX fork | 事实 | 中zread 社区报告,非一手数据) |
| E14 | "autoresearch's value proposition is the research loop, not the training infrastructure" | 观点 | 中(社区总结,非作者原话) |
| E15 | `program.md` 被 Karpathy 定义为 "essentially a super lightweight skill" | 事实 | 高README 原文) |
---
## L0 无极:信息边界与缺口
**主题范围**autoresearch 是一个让 AI Agent 自主进行 LLM 预训练研究的实验框架,覆盖"如何用 Agent 做受控实验循环",不覆盖分布式训练、多 Agent 协作、或超越单 GPU 的研究范式。
**缺口清单**
1. **实验成果数据缺失**——README/代码中无具体实验记录val_bpb 从多少降到多少),无法评估"自主研究"的实际收益
2. **Agent 选择策略不透明**——`program.md` 只说 "think harder, try combining previous near-misses",但 Agent 如何选择下一个实验方向的认知过程是黑箱
3. **规模边界未定义**——5 分钟 + 单 GPU 是当前约束,但 Karpathy 暗示 "adding more agents to the mix",多 Agent 协作的设计尚未展开
**风险提示**
1. **幸存者偏差**——只有成功改善的实验被 keepdiscarded 实验的信息可能包含重要负面知识
2. **Karpathy 光环效应**——项目简洁性可能被过度归因为"天才设计",而非"早期实验阶段的合理简化"
3. **硬件偏见**——默认 H100 测试val_bpb 结果不可跨硬件比较E11社区复现价值受限
---
## L1 太极:第一性矛盾
**核心矛盾**
```
人类研究者的认知带宽 AI Agent 的计算带宽
(深度洞察 + 直觉 + 睡觉) <──────> (暴力搜索 + 不休息 + 无直觉)
```
**目标方向**:倾向 AI Agent 侧——用"数量×速度"弥补"深度×直觉"的缺失。E1: "let it experiment autonomously overnight"
但 Karpathy 做了一个精妙的平衡:**人类不退出研究循环,而是上移到元层——编程 `program.md` 而非编程 `train.py`**E2。这不是"AI 替代人类研究",而是"人类从研究者变成研究策略的设计者"。
---
## L2 道Why目的、价值、取舍
**D1: 研究的瓶颈不是想法,而是验证速度**
- 取舍:宁可牺牲实验深度(每个只跑 5 分钟),也要最大化实验吞吐量(~12 次/小时)
- 证据E1, E3, E5
**D2: 可比性比绝对性能更重要**
- 取舍宁可放弃跨硬件可比性E11也要保证同一硬件上的实验间严格可比E3: 固定时间预算E4: 固定评估函数)
- 证据E3, E4, E11
**D3: 简洁是不可妥协的约束,不是"有则更好"的特性**
- 取舍:宁可放弃 0.001 bpb 改善,也不接受 20 行 hacky 代码E6宁可不支持多平台也要保持单文件可审查E7
- 证据E6, E7, E12
**D4: 人类应当设计研究策略,而非执行研究步骤**
- 取舍:宁可让 Agent 走弯路(无直觉引导),也要解放人类的注意力(睡觉时运行)
- 证据E2, E5, E15
---
## L3 法What世界模型、因果假设
**M1: 固定预算 + 单一标量 = Agent 可自主优化**
- 关键变量:时间预算 T、评估指标 val_bpb、搜索空间 Strain.py 的所有可修改参数)
- 因果方向T 固定 + val_bpb 单调可比 → Agent 可做贪心搜索keep/discard→ 分支单调不退化
- 证据E3, E4, E10
- 可证伪信号:若 Agent 频繁陷入局部最优(连续 20+ 次 discard则贪心搜索在此空间失效
**M2: 约束面越小Agent 犯致命错误的概率越低**
- 关键变量:可修改文件数 F、代码行数 L、依赖数 D
- 因果方向F=1只改 train.py+ D 固定(不可装新包)→ 错误范围被物理隔离 → 崩溃可恢复git reset
- 证据E7, E10
- 可证伪信号:若 Agent 的修改导致 prepare.py 的隐含假设被违反(如改变 vocab_size则单文件隔离不够
**M3: Git 分支 = 免费的实验版本管理 + 回滚机制**
- 关键变量git commit 粒度、branch 策略、results.tsv 日志
- 因果方向:每次实验 = 一次 commit → keep 推进 branch / discard 回退 → 实验历史完全可审计
- 证据E10
- 可证伪信号:若 git 操作本身引入错误merge conflict、detached HEAD则 Agent 可能无法自行恢复
**M4: program.md 是"研究组织的源代码"——元编程层**
- 关键变量指令精确度、约束明确性、Agent 理解能力
- 因果方向program.md 质量 → Agent 行为质量 → 实验选择质量 → val_bpb 下降速度
- 证据E2, E5, E15
- 可证伪信号:若不同 program.md 版本的实验结果无统计显著差异,则"元编程"价值不成立
**M5: 时间预算固定使得架构-效率 tradeoff 成为 Agent 的隐含优化目标**
- 关键变量:模型大小 N、训练步数 S、每步时间 t
- 因果方向T 固定 → S = T/t → 大模型步数少 vs 小模型步数多 → Agent 必须同时优化模型质量和训练效率
- 证据E3, E9当前 baseline 已包含多项效率优化Flash Attention 3、ReLU²、sliding window
- 可证伪信号:若存在一个模型大到几乎不训练(<10 val_bpb 极低则此 tradeoff 被打破
---
## L4 术How原则、策略、决策规则
**P1: 单文件隔离原则**
- 规则Agent 只改 train.py永远不碰 prepare.py 和 pyproject.toml
- 前提评估函数和数据管线已经正确且足够M2
- 边界:若 prepare.py 的设计成为瓶颈(如 dataloader 效率),此原则会阻碍进步
- 映射D3简洁约束+ M2约束面小→错误少
- 证据E7
**P2: 贪心搜索 + 即时回滚**
- 规则:改善 → keep推进 branch不改善 → discardgit reset无中间态
- 前提val_bpb 是充分的评估指标5 分钟足够产生有意义的信号M1
- 边界:不适用于需要多步才能见效的改动(如先重构再优化),贪心会在第一步就 discard
- 映射D1验证速度优先+ M1固定预算→贪心可行
- 证据E10
**P3: 时间预算而非步数预算**
- 规则:训练固定 300 秒 wall clock不管跑了多少步
- 前提:同一硬件上 wall clock 是公平的比较基准M5
- 边界跨硬件不可比E11JIT 编译时间被排除(前 10 步不计时),但若架构变化导致编译时间剧增,会偷走训练时间
- 映射D2可比性>绝对性能)+ M5时间固定→效率成为隐含目标
- 证据E3, E11
**P4: 简洁性门控**
- 规则:若 val_bpb 改善 < 0.001 且代码复杂度增加 > 20 行 → discard若删代码且效果持平 → keep
- 前提代码可读性有长期价值Agent 需要理解自己之前的修改D3
- 边界在研究早期baseline 很差时),应放宽此门控,允许大改动
- 映射D3简洁不可妥协+ M4program.md 定义行为质量)
- 证据E6
**P5: NEVER STOP 自主循环**
- 规则:一旦进入实验循环,不得暂停询问人类;卡住时要"think harder",不是停下来
- 前提人类可能不在电脑前E5: "The human might be asleep"
- 边界:若 Agent 进入死循环(连续 crash 无法修复),会无意义地消耗 API 调用
- 映射D4人类设计策略不执行步骤+ D1吞吐量优先
- 证据E5
**P6: 软约束 VRAM 策略**
- 规则VRAM 增加可接受,但不能 "blow up dramatically"
- 前提val_bpb 改善与 VRAM 增加需要人为判断比例M1
- 边界:无明确阈值("dramatic" 未定义),依赖 Agent 的判断力
- 映射D1验证速度>资源节约)+ M5效率是隐含目标
- 证据E12
**P7: 元编程迭代——人类优化 program.md 而非 train.py**
- 规则:人类的研究贡献通过修改 program.md 实现,不直接改代码
- 前提Agent 能正确理解并执行 Markdown 指令M4
- 边界:若 program.md 的指令过于抽象Agent 可能产生无意义的实验
- 映射D4人类上移到元层+ M4program.md = 研究组织源代码)
- 证据E2, E15
---
## L5 器Do动作、工具、流程
**T1: 实验环境初始化工具包**
- 触发场景:首次 clone 或新实验分支
- 目标:从零到可运行的实验环境
- 步骤:
1. `curl -LsSf https://astral.sh/uv/install.sh | sh`
2. `uv sync`
3. `uv run prepare.py`(下载数据 + 训练 tokenizer~2 分钟)
4. `uv run train.py`(验证 baseline 可运行)
5. 确认 `~/.cache/autoresearch/` 包含 data shards + tokenizer
- 常见误用:跳过 `prepare.py` 直接跑 `train.py` → tokenizer 不存在crash
- 映射P1单文件隔离prepare.py 只跑一次)
**T2: 实验循环执行模板**
- 触发场景Agent 进入自主研究模式
- 目标:无限循环产出 keep/discard 决策
- 步骤:
1. `git checkout -b autoresearch/<tag>`
2. 读取 README.md + prepare.py + train.py 全量上下文
3. 创建 `results.tsv`header only
4. 首次运行 `uv run train.py > run.log 2>&1` 建立 baseline
5. 循环:修改 → commit → 运行 → `grep "^val_bpb:\|^peak_vram_mb:" run.log` → 记录 → keep/discard
- 常见误用:用 `tee` 或让输出 flood context window → context 爆炸Agent 失忆
- 映射P2贪心搜索+ P5NEVER STOP
**T3: 结果记录与回退模板**
- 触发场景:每次实验完成后
- 目标:结构化记录 + 干净的 git 历史
- 步骤:
- keep`results.tsv` 追加一行commit/bpb/mem/keep/desc→ branch 推进
- discard`results.tsv` 追加一行commit/bpb/mem/discard/desc`git reset` 回退
- crash`tail -n 50 run.log` → 尝试修复 → 修不好则记录 crash 跳过
- 常见误用:用 CSV逗号分隔而非 TSV → description 中的逗号破坏格式
- 映射P2即时回滚+ P4简洁性门控决定 keep/discard
**T4: program.md 迭代模板**
- 触发场景:人类审查实验结果后,想引导 Agent 探索新方向
- 目标:通过修改 Markdown 改变 Agent 行为
- 步骤:
1. 阅读 `results.tsv`,识别趋势(哪些方向有效/无效)
2. 在 `program.md` 中添加/修改指令(如"优先探索 optimizer 变体"或"避免增加模型深度"
3. Agent 在下次循环读取更新后的 program.md
- 常见误用:指令过于具体("把 learning rate 改成 0.05")——这等于人类直接改代码,违背 D4
- 映射P7元编程迭代
**T5: 崩溃恢复流程**
- 触发场景:`grep "^val_bpb:" run.log` 输出为空
- 目标:快速判断是否可修复
- 步骤:
1. `tail -n 50 run.log` 读取 stack trace
2. 若 OOM → 减少 batch size 或模型大小 → 重试
3. 若 typo/import error → 修复 → 重试
4. 若根本性问题(架构不兼容)→ log crash → git reset → 继续下一个想法
5. 超过 3 次修复尝试 → 放弃此方向
- 常见误用:反复尝试修复同一个根本性错误 → 浪费时间
- 映射P2即时回滚+ P5不停下来问人类
---
## L6 加速度-速度-位移:指标与反馈
**加速度指标(驱动变化的变化)**
| 指标 | 记录方式 | 周期 | 阈值 | 对应 |
|------|---------|------|------|------|
| A1: val_bpb 下降率的变化 | `results.tsv` 中相邻 keep 实验的 Δbpb 差值趋势 | 每 10 次实验 | 若连续 3 个窗口 Δbpb 递减 → 研究饱和 | T2, T3 |
| A2: keep/discard 比率的变化 | 滑动窗口 keep/(keep+discard) | 每 10 次实验 | 比率 < 10% 持续 2 个窗口 Agent 需要新方向 | T4 |
**速度指标(行为频率与强度)**
| 指标 | 记录方式 | 周期 | 阈值 | 对应 |
|------|---------|------|------|------|
| V1: 实验吞吐量 | `results.tsv` 行数 / 小时 | 每小时 | 期望 ~12/h< 8/h 说明 crash startup 开销过大 | T2 |
| V2: crash 频率 | `results.tsv` 中 crash 行占比 | 每 20 次实验 | > 30% crash → Agent 探索策略过于激进 | T5 |
**位移指标(结果与状态)**
| 指标 | 记录方式 | 周期 | 阈值 | 对应 |
|------|---------|------|------|------|
| S1: 当前最佳 val_bpb | `results.tsv` 中 keep 行的最低值 | 每次 keep | 与 baseline 相比的绝对改善量 | T3 |
| S2: VRAM 变化 | `results.tsv` 中 memory_gb 列 | 每次 keep | 相比 baseline 增长 > 50% → 需要审查 | P6 |
---
## L7 生生不息:迭代律
### 复盘模板5 问)
1. **最佳实验是什么?** 哪次 keep 的 Δbpb 最大?它改了什么?
2. **最意外的失败是什么?** 预期应该改善但 discard 的实验,根因是什么?
3. **Agent 有没有探索盲区?** train.py 中哪些组件从未被修改过?
4. **简洁性守住了吗?** 当前 train.py 行数相比 baseline 增加了多少?
5. **program.md 需要更新吗?** 基于实验趋势Agent 的探索方向需要调整吗?
### 更新规则
| 信号 | 动作 | 指向 |
|------|------|------|
| 连续 20+ 次 discard | 在 program.md 中添加"尝试更激进的架构变化" | P7, T4 |
| crash 率 > 30% | 在 program.md 中添加"优先小步修改,避免同时改多个组件" | P4, T5 |
| val_bpb 停滞但 VRAM 持续增长 | 在 program.md 中强调简洁性准则,要求 Agent 先尝试删减 | P4, P6 |
| 发现 Agent 从未修改 optimizer | 在 program.md 中显式提示"考虑 optimizer 变体" | T4 |
| 某类修改(如 attention 变体)成功率 > 50% | 在 program.md 中鼓励深挖此方向 | P7 |
### 7 天最小实验
**做什么**:在自己的 GPU哪怕只有 RTX 3090上运行 autoresearch 一整晚8 小时,~96 次实验)
**记录什么**
- `results.tsv` 完整保存
- 记录 Agent 的行为模式(它倾向改什么?避免改什么?)
- 记录 val_bpb 曲线的拐点
**如何判定有效**
- val_bpb 相比 baseline 有 ≥ 0.5% 改善 → 自主研究有效
- Agent 产出的最佳 train.py 中包含人类未曾想到的修改 → 发现价值成立
- 若 val_bpb 无改善但 train.py 更简洁 → 简洁性价值成立
---
## 收束总纲
> **在"让 AI 做 LLM 研究"的情境下,优先最大化实验吞吐量(固定时间 + 贪心循环 + 不停歇)而非追求单次实验的深度(精心设计 + 人工审查 + 谨慎推进)。**
>
> 对应D1验证速度 > 实验深度)+ M1固定预算 + 单标量 → 贪心可行)+ P2即时 keep/discard
---
## 附:对 content-forge 的启示
| autoresearch 设计 | content-forge 对应 | 可借鉴点 |
|---|---|---|
| `program.md`(人类写指令) | `write-article/SKILL.md`(人类写 skill | 同一元编程范式:人写 MarkdownAgent 执行 |
| 固定 5 分钟 + val_bpb 单标量 | 缺少固定评估周期和单一质量标量 | 可考虑为文章质量定义一个"综合得分",实现自动化 keep/discard |
| 贪心 keep/discard + git reset | 手动审核(/review | 审稿环节可借鉴自动回退机制revision_count ≤ 3 已有雏形) |
| NEVER STOP 循环 | 无自主循环 | 适用于批量生产场景(如一次生成 10 个选题变体,自动筛选最佳) |
| 三文件约束面 | Vault 多目录 + 多 skill | content-forge 约束面更大,但 "Agents Read, Humans Write" 与 "人写 program.md, Agent 改 train.py" 同源 |
---
## 映射总览
```
E# (证据) ─────────────────────────────────────────────────────────
├─► D1 验证速度优先 ──────► M1 固定预算+单标量 ──► P2 贪心搜索
│ M5 时间固定→效率目标 ──► P3 时间预算
├─► D2 可比性>绝对性能 ──► M1 ─────────────────► P3 时间预算
├─► D3 简洁不可妥协 ──────► M2 约束面小→错误少 ──► P1 单文件隔离
│ P4 简洁性门控
└─► D4 人类上移到元层 ───► M4 program.md=元编程 ─► P5 NEVER STOP
P7 元编程迭代
T1-T5 具体工具包
L6 指标A1,A2,V1,V2,S1,S2
L7 迭代(复盘+更新规则+7天实验
```

View File

@ -0,0 +1,162 @@
---
id: 2026-03-18-opencli-research
title: OpenCLI 深度研究:把任何网站变成 CLI
slug: opencli-research
status: inbox
content_type: article
language: zh-CN
source_urls:
- https://github.com/jackwener/opencli
tags:
- cli-tool
- browser-automation
- ai-agent
- web-scraping
- open-source
created_at: 2026-03-18T00:00:00+08:00
updated_at: 2026-03-18T00:00:00+08:00
---
# OpenCLI 深度研究:把任何网站变成 CLI
> Make any website your CLI. Zero risk · Reuse Chrome login · AI-powered discovery
## 项目信息
- 仓库: git@github.com:jackwener/opencli.git
- npm: @jackwener/opencli
- 协议: BSD-3-Clause
- Node.js >= 18
## 核心定位
把任何网站变成命令行工具——复用 Chrome 登录态零风险AI 驱动自动发现 API。
## 架构总览
```
┌────────────────────────────────────────────────────────────────────────┐
│ opencli CLI (main.ts) │
│ Commander.js 命令树 │
├──────────┬─────────────┬──────────────┬───────────────────────────────┤
│ 内置命令 │ 动态站点命令 │ AI Agent 命令 │ 管理命令 │
│ list │ bilibili/* │ explore │ validate / verify │
│ doctor │ twitter/* │ synthesize │ setup │
│ setup │ zhihu/* │ generate │ │
│ │ ...18 sites │ cascade │ │
├──────────┴─────────────┴──────────────┴───────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Engine │ │ Registry │ │ Output │ │
│ │ (engine.ts) │────▶│ (registry.ts) │────▶│ (output.ts) │ │
│ │ │ │ │ │ │ │
│ │ • Manifest快速路径│ │ • cli() 注册函数 │ │ • table (默认) │ │
│ │ • FS扫描回退 │ │ • Map<key,Cmd> │ │ • json / yaml │ │
│ │ • YAML 自动解析 │ │ • Strategy enum │ │ • markdown / csv│ │
│ │ • TS 惰性加载 │ │ • Arg 接口 │ │ │ │
│ └────────┬────────┘ └─────────────────┘ └─────────────────┘ │
│ │ │
│ ┌────────▼────────┐ ┌─────────────────┐ │
│ │ Pipeline │ │ Browser │ │
│ │ (pipeline/) │ │ (browser.ts) │ │
│ │ │ │ │ │
│ │ YAML 声明式引擎 │◀───▶│ PlaywrightMCP │ │
│ │ 14 种 Step │ │ JSON-RPC ↔ Chrome│ │
│ │ 模板表达式 │ │ Page 抽象层 │ │
│ └─────────────────┘ └─────────────────┘ │
└────────────────────────────────────────────────────────────────────────┘
```
## 核心设计 1双引擎
YAML 声明式 + TypeScript 编程式双引擎,共享同一个 Registry 和 Browser 抽象层。
数据结构 CliCommand 的 func 和 pipeline 二选一——消除引擎切换的特殊情况处理。
- YAML: src/clis/<site>/<name>.yaml14 种 Pipeline Step放入即自动注册
- TS: src/clis/<site>/<name>.ts通过 cli() 函数注册,首次执行时才惰性加载
- 发现机制: cli-manifest.json 快速路径 + FS scan 回退(生产零开销 + 开发热加载)
Pipeline 步骤:
- 数据获取: navigate, fetch, evaluate, snapshot, intercept, tap
- 数据变换: select, map, filter, sort, limit
- UI 操作: click, type, wait, press
- 模板语法: \${{ item.field }}, \${{ args.limit }}, \${{ index + 1 }}
## 核心设计 25 级认证策略
```
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ PUBLIC │───▶│ COOKIE │───▶│ HEADER │───▶│INTERCEPT │───▶│ UI │
│ Tier 1 │ │ Tier 2 │ │ Tier 3 │ │ Tier 4 │ │ Tier 5 │
│ ~1s ⚡ │ │ ~7s 🔄 │ │ ~7s 🔄 │ │ ~10s 🔄 │ │ ~15s+ 🐌│
├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤
│HackerNews│ │ Bilibili │ │ Twitter │ │ 小红书 │ │ 遗留站点 │
│ V2EX/BBC │ │ Zhihu │ │ GraphQL │ │ Pinia+ │ │ │
│ GitHub │ │ Reddit │ │ │ │ XHR Hook │ │ │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
```
cascade 命令自动逐级探测:对目标 URL 依次尝试 PUBLIC → COOKIE → HEADER第一个成功的就是最佳策略。
## 核心设计 3AI 自动发现
```
explore <url> → 导航 + 自动滚动 + fuzzing + 网络捕获 + 框架检测 + 端点评分 + 能力推理
synthesize <site> → 从 explore 产物生成 YAML 候选
generate <url> → explore + synthesize + register 一键完成
```
端点评分系统: JSON +10, API路径 +3, 搜索参数 +3, 分页 +2, 有数据 +5, 空数据 -3反爬检测。阈值 ≥5 才保留。
## 核心设计 4拦截器系统
三种拦截模式:
- 全局拦截: installInterceptor() — 持久 monkey-patch累积捕获
- 读取+清空: getInterceptedRequests() — 读取后清空
- tap 拦截: 临时拦截 + Promise 等待 + 自动恢复原函数
tap 步骤是最精妙的设计——不自己构造签名,而是调用目标站点的 Pinia/Vuex Store Action让前端框架自己完成鉴权再拦截网络响应取数据。「用敌人的武器打败敌人」。
## 浏览器层
通过 Playwright MCP Bridge Chrome 扩展连接用户已登录的浏览器——不启动新浏览器实例,复用用户的 Cookie/Session/登录态。这是「零风险」的核心保障。
Page 抽象层 (IPage): goto, evaluate, snapshot, click, autoScroll, installInterceptor, getInterceptedRequests
## 支持站点18 个100+ 命令)
Public无需浏览器: hackernews, bbc, github, v2ex(部分)
Browser需 Chrome 登录):
- bilibili (11 cmds): hot, search, me, favorite, history, feed, subtitle, dynamic, ranking, following, user-videos
- twitter (17 cmds!): trending, bookmarks, profile, search, timeline, following, followers, notifications, post, reply, delete, like, article, follow, unfollow, bookmark, unbookmark
- zhihu (3), xiaohongshu (5), xueqiu (6), reddit (4), weibo, boss, coupang, youtube, yahoo-finance, reuters, smzdm, ctrip, v2ex(部分)
## 技术栈
CLI: Commander.js | 浏览器: Playwright MCP Bridge | YAML: js-yaml | 输出: cli-table3 + chalk | 构建: TypeScript | 测试: Vitest (~52 E2E) | 运行时: Node.js >= 18
## 架构亮点
1. CliCommand 的 func/pipeline 二选一——消除引擎切换 if/elseGood Taste
2. Manifest 快速路径 + FS scan 回退——零开销启动 + 无缝开发
3. 5 级策略 + cascade 自动探测——认证复杂度分层管理
4. tap 步骤Store Action Bridge——用框架自己的能力绕过签名
5. Page 抽象层 (IPage)——浏览器操作解耦,方便测试 mock
6. explore 端点评分——把 AI 发现从「试错」降为「打分排序」
## 潜在问题
- Twitter Bearer Token 硬编码(轮换风险)
- evaluate 步骤 JS 注入用字符串拼接XSS 向量,虽运行在用户自己浏览器)
- 无重试机制(网络抖动直接失败)
- E2E 测试依赖真实站点(站点改版易失败)
## 选题角度思考
- 「把任何网站变成 CLI」的产品思路——从 API wrapper 到 AI 自动发现的演进
- 双引擎设计的 Good Taste——YAML 声明式 vs TS 编程式的边界在哪里
- 5 级认证策略——Web 反爬对抗的分层哲学
- tap 步骤的精妙设计——用前端框架自己的能力打败它
- 对 AI Agent 工具生态的启示——explore + synthesize + cascade 三件套