关于 autoresearch
通过修改代码并运行基准测试,优化可度量仓库指标的自主实验循环技能。它将假设、结果和可续接状态记录到文件中,保留改进并撤销退步。
主要功能
- 01设定优化目标和停止条件
- 02运行基准并评估指标变化
- 03保留改进并撤销退步
- 04在 JSONL 中记录实验与假设
- 05依据保存的研究状态续接工作
适用场景
- 01通过实测降低测试运行时间
- 02用可重复循环优化打包体积
- 03跨 Agent 会话继续实验
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ factory-ai/ factory-plugins --skill autoresearch安装后在 Claude Code 中输入/autoresearch确认已加载。
附带文件autoresearch_helper.py
详细介绍
Autoresearch
自主实验循环:尝试想法,保留有效的,舍弃无效的,永不停止。
概览
你正在运行一个自主优化循环。你的任务是通过修改内容、运行实验,并且只保留改进,系统地优化一项可测量的指标。你要维护结构化状态文件,以便任何会话(包括一个全新且没有记忆的会话)都能从中断处准确续接。
如果用户要求你执行此任务,而你当前不在任务模式中,请建议他们可以在任务(/enter-mission)中运行此流程,以便更好地跟踪进度、验证里程碑并在多个会话间保持连续性。不要因此阻塞工作——只需在设置期间提及一次。
如果你已经处于任务模式,请先调用任务规划技能(mission-planning 和 define-mission-skills),再开始执行本技能的流程。使用任务系统的规划、分解和工作者设计来组织 autoresearch 工作,然后将这些指导与本技能的实验循环流程结合起来。本技能定义了如何运行实验;任务系统定义了如何规划、跟踪和验证实验。
设置
循环开始前,你需要确定实验方案。
步骤 1:收集信息
询问用户(或根据上下文推断)以下信息:
- 目标:要优化什么?(例如,“最小化 val_bpb”、“缩短测试运行时间”、“减小打包体积”)
- 命令:要运行什么?(例如,
uv run train.py、pnpm test、pnpm build && du -sb dist) - 主要指标:名称、单位和优化方向(例如,
val_bpb,无单位,越低越好) - 涉及文件:允许修改哪些文件
- 约束条件:硬性规则(必须通过测试、不得添加新依赖等)
- 终止条件:何时停止。询问用户,可选项包括:
- 固定实验次数(例如,20 次实验)
- 固定时间预算(例如,2 小时)
- 目标指标(例如,val_bpb < 1.0)
- 一直运行,直到被中断(默认)
步骤 2:创建分支和状态文件
git checkout autoresearch/<goal>-<date> 2>/dev/null || git checkout -b autoresearch/<goal>-<date>
仔细阅读源文件。在编写任何内容前,深入了解工作负载。
创建三个文件:
autoresearch.md
持续更新的研究文档。一个没有上下文的新 Agent 应当能够阅读此文件并有效运行循环。花时间把它写好。
# Autoresearch: <goal>
## Objective
<Specific description of what we're optimizing and the workload.>
## Metrics
- **Primary**: <name> (<unit>, lower/higher is better) — the optimization target
- **Secondary**: <name>, <name>, ... — independent tradeoff monitors
## How to Run
`./autoresearch.sh` — outputs `METRIC name=number` lines.
## Files in Scope
<Every file the agent may modify, with a brief note on what it does.>
## Off Limits
<What must NOT be touched.>
## Constraints
<Hard rules: tests must pass, no new deps, etc.>
## Termination
<When to stop: experiment count, time budget, target metric, or run until interrupted.>
## What's Been Tried
<Update this section as experiments accumulate. Note key wins, dead ends,
and architectural insights so the agent doesn't repeat failed approaches.>
autoresearch.sh
Bash 脚本(set -euo pipefail),用于快速预检查(语法错误检查耗时少于 1 秒)、运行基准测试,并将结构化的 METRIC name=value 行输出到标准输出。保持脚本快速。
对于快速、噪声较大的基准测试(耗时少于 5 秒),在脚本内多次运行工作负载并报告中位数。耗时较长的工作负载(机器学习训练、大型构建)则不必如此。
示例:
#!/bin/bash
set -euo pipefail
# Pre-check: syntax validation
python3 -c "import ast; ast.parse(open('train.py').read())" 2>&1 || { echo "SYNTAX ERROR"; exit 1; }
# Run the workload
output=$(uv run train.py 2>&1)
# Extract and output metrics
val_bpb=$(echo "$output" | grep -oP 'val_bpb=\K[0-9.]+' | tail -1)
echo "METRIC val_bpb=$val_bpb"
autoresearch.checks.sh(可选)
仅当用户的约束要求验证正确性时(例如,“测试必须通过”、“类型检查必须通过”)才创建此文件。Bash 脚本(set -euo pipefail),用于执行反馈检查。
#!/bin/bash
set -euo pipefail
pnpm test --run --reporter=dot 2>&1 | tail -50
pnpm typecheck 2>&1 | grep -i error || true
步骤 3:初始化 JSONL 并提交状态文件
初始化实验日志:
python3 autoresearch_helper.py init --jsonl autoresearch.jsonl --name '<goal>' --metric-name '<metric_name>' --direction <lower|higher>
提交所有状态文件:
git add autoresearch.md autoresearch.sh autoresearch.jsonl
git commit -m "autoresearch: initialize experiment session"
步骤 4:运行基线
运行基准测试并记录基线结果:
bash autoresearch.sh
解析输出中的 METRIC 行,然后将基线记录为保留项:
python3 autoresearch_helper.py log --jsonl autoresearch.jsonl \
--commit $(git rev-parse --short=7 HEAD) \
--metric <baseline_value> \
--status keep \
--description "baseline" \
--asi '{"hypothesis": "baseline measurement"}'
这是第 #1 个实验,用于确定后续所有比较的起点。
实验循环
无限循环。 永远不要问“要不要继续?”——用户期待你自主工作。只有在以下情况才停止:
- 满足设置中的终止条件
- 用户中断
- 你发现自己的上下文即将耗尽(参见下文“上下文管理”)
对于每个实验:
1. 选择尝试的方案
阅读 autoresearch.md(尤其是“已尝试的方案”)和 autoresearch.ideas.md(如果存在),以选择下一个假设。思考数据告诉了你什么。最好的想法来自深入理解,而不是随机变化。
2. 进行更改
编辑范围内的文件。让更改聚焦——每次实验只验证一个假设。
3. 运行实验
执行基准测试:
timeout 600 bash autoresearch.sh
捕获完整输出。从输出中解析 METRIC name=value 行。
如果运行崩溃或超时,将其记录为崩溃并还原更改。
如果 autoresearch.checks.sh 存在,且基准测试通过,则运行:
timeout 300 bash autoresearch.checks.sh
如果检查失败,将其记录为 checks_failed 并还原更改。
4. 评估结果
使用辅助脚本将主要指标与当前最佳结果(如果尚无保留项,则与基线)进行比较:
python3 autoresearch_helper.py evaluate --jsonl autoresearch.jsonl --metric <value> --direction <lower|higher>
该脚本会输出保留或舍弃的建议、置信度分数以及与基线的差值。
决策规则:
- 主要指标有所改善 ->
keep - 主要指标变差或不变 ->
discard - 性能相同但代码更简洁 ->
keep(性能相同的情况下,减少代码量就是胜利) - 微小收益却带来难看的复杂度 -> 通常应
discard - 次要指标很少影响保留或舍弃的决定。只有次要指标严重退化时,才舍弃主要指标有所改善的结果。
5. 记录结果
保留时:
先记录到 JSONL(这样该条目会包含在提交中):
python3 autoresearch_helper.py log --jsonl autoresearch.jsonl \
--commit $(git rev-parse --short=7 HEAD) \
--metric <value> \
--status keep \
--description "<what was tried>" \
--asi '{"hypothesis": "<what you tried>"}' \
# --metrics '{"compile_us": <value>, "render_us": <value>}' # optional secondary metrics
--direction <lower|higher>
然后提交所有更改(包括 JSONL 条目):
git add -A
git commit -m "<description>
Result: {\"status\": \"keep\", \"<metric_name>\": <value>}"
舍弃/崩溃/检查失败时:
先记录到 JSONL(还原更改前记录,以保留条目):
python3 autoresearch_helper.py log --jsonl autoresearch.jsonl \
--commit "0000000" \
--metric <value_or_0> \
--status <discard|crash|checks_failed> \
--description "<what was tried>" \
--asi '{"hypothesis": "<what you tried>", "rollback_reason": "<why it failed>"}' \
# --metrics '{"compile_us": <value>, "render_us": <value>}' # optional secondary metrics
--direction <lower|higher>
然后还原更改,并备份状态文件,以免 git clean -fd 将其删除:
# Backup state files
cp autoresearch.jsonl autoresearch.jsonl.bak 2>/dev/null || true
cp autoresearch.md autoresearch.md.bak 2>/dev/null || true
cp autoresearch.ideas.md autoresearch.ideas.md.bak 2>/dev/null || true
# Revert all changes
git checkout -- .
git clean -fd 2>/dev/null
# Restore state files
cp autoresearch.jsonl.bak autoresearch.jsonl 2>/dev/null || true
cp autoresearch.md.bak autoresearch.md 2>/dev/null || true
cp autoresearch.ideas.md.bak autoresearch.ideas.md 2>/dev/null || true
rm -f autoresearch.jsonl.bak autoresearch.md.bak autoresearch.ideas.md.bak
6. 更新研究日志
每进行几次实验(或取得重要发现后),更新 autoresearch.md 中的“已尝试内容”部分。包括:
- 哪些方法有效,以及原因
- 哪些方法无效,以及原因
- 应避免的死路
- 当前最佳结果及其实现方式
7. 维护想法待办列表
发现有潜力但暂缓实施的优化时,将其作为项目符号追加到 autoresearch.ideas.md。不要让好想法被遗忘。清理过时或已尝试的条目。
8. 循环
返回步骤 1。
状态文件参考
| 文件 | 格式 | 用途 |
|---|---|---|
autoresearch.jsonl | JSON Lines | 仅追加的实验日志。每行一个 JSON 对象。 |
autoresearch.md | Markdown | 持续更新的研究文档。包含目标、已尝试内容和当前最佳结果。 |
autoresearch.ideas.md | Markdown | 假设待办列表。记录值得尝试的想法。 |
autoresearch.sh | Bash | 基准测试脚本。输出 METRIC name=value 行。 |
autoresearch.checks.sh | Bash | 可选的正确性检查(测试、类型检查、lint)。 |
JSONL 架构
autoresearch.jsonl 中的每一行都是配置标头或实验结果:
配置标头(第一行或重新初始化时):
{"type": "config", "name": "...", "metricName": "...", "metricUnit": "...", "bestDirection": "lower|higher"}
实验结果:
{
"run": 1,
"commit": "abc1234",
"metric": 1.234,
"metrics": {"compile_us": 4200, "render_us": 9800},
"status": "keep|discard|crash|checks_failed",
"description": "what was tried",
"timestamp": 1711600000000,
"segment": 0,
"confidence": 2.1,
"asi": {"hypothesis": "...", "rollback_reason": "...", "next_action_hint": "..."}
}
ASI(可执行的辅助信息)
每次实验都要记录 ASI。至少包含:{"hypothesis": "what you tried"}。舍弃或崩溃时,还要包含 rollback_reason 和 next_action_hint。添加其他能够记录经验的键值对,例如死路、意外发现、错误详情和瓶颈。
ASI 是还原更改后唯一能够保留的结构化记忆。没有它,后续迭代就会浪费时间,重新发现相同的死路。
置信度评分
进行 3 次或更多实验后,辅助脚本会使用中位数绝对偏差(MAD)计算置信度分数:
| 置信度 | 含义 |
|---|---|
| >= 2.0x | 改善很可能是真实的 |
| 1.0-2.0x | 高于噪声,但幅度有限 |
| < 1.0x | 处于噪声范围内——考虑重新运行以确认 |
该分数仅供参考——不会自动舍弃结果。如果置信度低于 1.0x,可考虑重新运行同一实验以确认,然后再决定是否保留。
上下文管理
Droid 会话的上下文有限。为妥善处理这一点:
- 跟踪当前会话中的实验次数。进行约 15 次实验后,上下文会变得臃肿。
- 主动保存状态——所有状态都保存在文件中(jsonl、md),因此新会话可以立即继续。
- 上下文即将耗尽时:更新
autoresearch.md,记录当前发现,提交状态文件,然后停止。下一会话会读取这些文件并继续。 - 恢复时:读取
autoresearch.md、autoresearch.jsonl和git log --oneline -20,了解当前进展。检查当前状态:
python3 autoresearch_helper.py status --jsonl autoresearch.jsonl
循环规则摘要
- 永远循环。 绝不要问“要继续吗?”
- 首要指标至上。 有所改进 -> 保留。变差或持平 -> 丢弃。
- 为每次运行添加 ASI 注释。 记录你的收获,而不仅仅是你做了什么。
- 关注置信度分数。 < 1.0x 表示结果处于噪声范围内——重新运行以确认。
- 越简单越好。 性能相同但代码减少 = 保留。
- 不要反复折腾。 如果反复撤销同一个想法?尝试结构上不同的方案。
- 崩溃: 如果修复很简单,就修复;否则记录下来并继续。
- 卡住时多思考。 重新阅读源文件,研究数据,推理实际发生的情况。最好的想法来自深入理解。
- 恢复时: 读取 autoresearch.md + git log,继续循环。
最终整理
实验循环结束时(达到终止条件、用户中断或上下文耗尽),将结果整理到清晰且易于审查的分支中。这是自动研究会话的最后阶段。
第 1 步:总结结果
python3 autoresearch_helper.py summary --jsonl autoresearch.jsonl
查看 git log,了解实际提交:
git log --oneline --stat $(git merge-base HEAD main)..HEAD
第 2 步:分组变更
将保留的实验归入逻辑变更集。每组应:
- 代表一项连贯的优化或变更
- 与其他组不共享修改过的文件(以便各分支可以独立合并)
- 清楚说明实现的效果和指标改进
向用户展示拟议的分组以供批准:
Group 1: "Reduce model depth from 8 to 6"
Files: train.py (DEPTH, HEAD_DIM, N_EMBED)
Metric improvement: val_bpb 1.15 -> 1.08 (-6.1%)
Experiments: #3, #7, #12
Group 2: "Switch to cosine LR schedule"
Files: train.py (lr_schedule, warmup_steps)
Metric improvement: val_bpb 1.08 -> 1.05 (-2.8%)
Experiments: #15, #18
等待用户确认后再继续。在任务工作者模式下,无需等待确认,直接采用最佳分组继续。
第 3 步:解决文件冲突
如果各组共享文件,请在创建分支前解决:
- 将相关的组并为一组(如果变更彼此相关)
- 更细致地拆分文件变更(如果它们确实是对不同部分的独立修改)
- 询问用户应优先处理哪一组
各组不得共享文件——每个分支都必须能够独立合并。如果所有变更都涉及同一个文件且无法拆分,则创建一个包含所有改进的最终分支。
第 4 步:创建干净的分支
对每组执行:
merge_base=$(git merge-base HEAD main)
git checkout -b autoresearch/finalize/<group-name> $merge_base
git checkout autoresearch/<session-branch> -- <file1> <file2> ...
git commit -m "<group description>
Autoresearch results:
- Metric: <name> improved from <baseline> to <best> (<delta>%)
- Confidence: <score>x noise floor
- Experiments: <count> total, <kept> kept"
第 5 步:验证并报告
对每个最终分支运行基准测试,确认改进仍然成立;如适用,运行相关检查,并确认其能与 main 干净地合并。
向用户提交摘要:
Created 2 clean branches from 20 experiments:
autoresearch/finalize/reduce-depth
val_bpb: 1.15 -> 1.08 (-6.1%)
Ready for review
autoresearch/finalize/cosine-schedule
val_bpb: 1.08 -> 1.05 (-2.8%)
Ready for review
Original experiment branch preserved: autoresearch/<session-branch>
原始实验分支始终会保留——最终整理会创建新分支。
任务工作者模式
作为任务工作者运行时,功能描述会指定优化目标、终止条件、涉及的文件和约束。请仔细阅读,遵循上述相同的循环流程,并遵守终止条件。达到条件后,执行最终整理,并在交接中报告结果。