Bundle
quick-research-campaign
DeepSeek Harness bundle: a bounded, de-confounded hyperparameter sweep ledger with a research-campaign playbook skill and paper-ready report tables
- Source
- wswbx
- License
- MIT
- Updated
- Updated yesterday
Readme
# quick-research-campaign
> 给 DeepSeek Harness 装一条科研流水线:**立靶 → 选仓库 → 对齐基线 → 最小改造 → 大规模调参 → 选优 → 配料表归因 → 出材料**。
它只管一件事:**你试了多少组、参数之间干不干净、为什么是这一组**。不建界面、不发请求、不跑实验。
---
## 装
```sh
dsh plugin --profile web add quick-research-campaign
```
重启该 profile 后生效。卸载:
```sh
dsh plugin --profile web remove quick-research-campaign
```
装好后每个会话都会得到三个工具和一个技能。
### 本机路径安装(未发布时)
```sh
dsh plugin --profile web add "file:C:/path/to/quick-research-campaign"
```
### 改配置
本包通过 `cordis.patch.yml` 插入一行,profile 自己的 `cordis.patch.yml` 可以按 id 覆盖它的整段 `config`:
```yaml
- id: tool-research-campaign
config:
maxTrialsPerCampaign: 64
```
| 字段 | 默认 | 含义 |
|---|---|---|
| `maxTrialsPerCampaign` | 必填(包内给 24) | 一次 campaign 可计划的 trial 上限;超过它的调用会被拒绝而不是截断 |
---
## 三个工具
### `research_sweep_plan`
开一本调参账本,把搜索空间展开成**有界、去混杂**的试验矩阵。
- 网格装得下预算就枚举完整笛卡尔积
- 装不下就**均匀采样**,而不是按固定步长截断
- 报告哪些参数取值一次都没被测到
- 报告哪些参数对被混杂(取值一一对应,贡献分不开)
```
space: { lr: {min:1e-5, max:1e-3, steps:4, log:true},
window: [4096, 8192, 32768],
gate_type: ["sigmoid","silu","none"] }
```
固定步长切割笛卡尔积是个陷阱:步长会和枚举顺序共振,让相邻维度产生系统性相关。实测中它让 `gate_type` 的某个取值一次没测,并且和 `rope_base` 完全绑定——消融表直接写不出来。均匀采样避开这一点。
### `research_sweep_record`
把一个 trial 记成 `ok` / `failed` / `pruned`,带指标和备注。**失败的、被剪枝的也记**——不知道搜索空间有多大,实验章节就撑不住。
`ok` 但没有任何指标会被拒绝:没产出数字的运行不能记成已完成的一次。
### `research_sweep_report`
按单个指标排名,并给出:
- 最优配置与最好的一组数字
- 相对**基线与 SOTA 靶子**的差距(靶子在 plan 时钉死:benchmark、split、指标、数值、来源)
- 相邻名次之间的差距 → 判断排名是否落在噪声里
- 每个参数的**边际效应** → 哪个组件在起作用,通常就是论文主角
- **混杂检查** → 哪些参数的贡献无法单独声称
- **论文材料清单** → 未勾选项就是方法/实验章节欠缺的内容
实测输出:
```
| # | trial | acc_32k | vs baseline | vs SOTA | gate_type | lr | window |
| 1 | t0011 | 72.7 | +4.6 WIN | +1.5 WIN | silu | 0.001 | 32768 |
- best over sota target: +1.5 (target beaten)
### gate_type
| value | mean acc_32k | trials |
| silu | 71.625 | 4 |
| sigmoid | 70.7333 | 3 |
| none | 68.9 | 3 |
```
`silu` 相对 `none` 平均 +2.7——这就是可写进消融表的数字。
---
## 技能 `research-campaign`
八阶段流水线手册,模型按需加载。核心是两条:
1. **一个组件一个 config 开关,默认关闭** —— 这是能写出「配料表」的前提:一个组件一个开关,才能一个一个加、一个一个测。
2. **先跑通 1 个 trial 再开大规模** —— 管线没通就并发,只会浪费算力。
---
## 边界(说清楚)
- **账本是进程状态**:按调用方会话索引,进程结束即消失。跨天的搜索请把每个 trial 的记录写进 `research/runs.jsonl`,账本丢了也能重建。持久化是刻意延期的——它需要一个拥有它的后端与迁移路径。
- **不执行实验**:工具只规划、记账、排名;跑训练的是模型 + shell。因此账本可以记录从未发生过的 trial。
- **报告检查完整性,不检查真实性**:边际效应与混杂由记录的数字重算得出,无法发现记错了运行来源的指标。
- **不做调度**:排队、重试、抢占属于 DSH 的 job / schedule 能力。
---
## 仓库结构
```
index 入口 lib/index.js 已构建,安装后直接可用,无需构建
类型声明 lib/types/**/*.d.ts
源码 src/{index,sweep,skill,types}.ts
冒烟测试 tests/smoke.test.mjs 直接驱动 lib/index.js,零依赖
引擎/组装测试 tests/*.spec.ts 需要 vitest
profile 补丁 cordis.patch.yml
```
### 已验证
`tests/smoke.test.mjs` 直接 import 发布产物 `lib/index.js`,在真实 Cordis Context 上挂载,跑完 plan → record → report 全流程,并验证销毁后工具与技能一起消失:
```sh
node --test # 4 passed, 0 failed
```
两个运行时依赖已对**已发布版本**分别验证:`@deepseek-ai/dsh-tools@0.0.1-rc.1` 的 `defineTool` 支持本包用到的 schema 写法(`json` / `integer` / `enum`),`@deepseek-ai/schemastery@3.18.2` 对缺失的必填字段按预期报错。
### 重新构建
`lib/` 随包发布,因此安装和使用都不需要构建。
要改代码:编辑 `src/*.ts`,然后
```sh
pnpm install # 需要网络:typescript、vitest 与 @deepseek-ai/* 依赖
pnpm run typecheck
pnpm exec vitest run
```
运行时的 `lib/index.js` 是一个自包含 bundle,外部只 import `@deepseek-ai/dsh-tools` 与 `@deepseek-ai/schemastery`。最省事的重建方式是在 DeepSeek Harness 源码检出里 `pnpm run build`,再把 `packages/research/tool-research-campaign/lib/` 覆盖过来——那样依赖版本必然一致。
---
## 设计取舍
**为什么不做成服务?** 所有消费者都在这一个包里。只有一个内部调用者的公开服务方法,正是 DSH 能力接缝规则反对的反模式。
**为什么不用会话日志持久化?** 插件新增的会话事件类型对不认识它的构建是「必读」的,降级后存储日志会被拒绝。这是真实第三方插件的踩坑记录。
**为什么账本按会话隔离?** preset 的常驻挂载是每个进程一份,若不按 agent 索引,两个会话会串账。
---
## License
MIT
Install
dsh plugin --profile web add github:wswbx/quick-research-campaign
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install quick-research-campaign from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.