feat: 任务书 09,materials 模块与提示词

- src/materials:每种提交一个材料函数,生成给模型看的材料、第一条消息、对号清单、能读的代码版本;查询只在材料内按编号找;读提示词并算原始字节哈希;信念本按方法.md 6.10 现算。
- 账本里只存成 Json 的冻结协议、位置表、决定、结算的形状和编号规则由 materials 定义并导出。
- vocab 加 Checklist(对号清单)。
- prompts/:参考项目 3 份角色提示词、16 份任务说明,只做必要改动。
- TASK.md 补一句 unversionedNames 不存进代码版本。
- 方法.md 4.3 ① 改为"研究者任务"放信念本;结构.md vocab 上限 1150、补 materials 对外内容。

用户 2026-10-03 开工前的四个决定(选的都是推荐项):"甲:上限改 1150,只放对号清单";"甲:materials 定义并导出";"不放,改方法.md ① 的措辞";"按原提案挑"。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 04:08:46 -04:00
parent cba1678eaf
commit 446e26224e
41 changed files with 3665 additions and 10 deletions
+95
View File
@@ -0,0 +1,95 @@
# 提案
这一轮,你和另外几位研究者各自提出改法。你交的每一条提案,接下来要经过几个人的手:别的研究者读它、挑它的毛病,再各自估它能跑多少分;实验员照着它写代码;跑完以后,大家拿结果回头对照它,看它说对了没有。所以一条好提案的标准很朴素——别人不用来问你,就能看懂你要改什么、你为什么觉得有用、什么结果算你错了。
开始想之前,先读材料"你自己的"一节:你认领的入口、你的笔记、你自己候选的结果。第 1 轮时,入口就是你的起点:从它说的那段代码、那个问题开始看。提案不必只围着入口转,看完觉得别处更值得改,就提别处,在因子的理由里写一句这条提案和入口是什么关系就行。第 2 轮起,入口只是你第 1 轮的起点,走不走由你定。
然后读公共材料。"上一轮的收尾"是每位研究者上一轮结束时写的:什么被支持、什么被挑战、想在哪个因子上继续。"信念本"按因子记着已经测过的东西:每个因子(带着它的关键设定)关掉后分数变差多少分、撑了几成、大家事前猜得准不准,每次消融下面还有一行"程序按方向收益押的因子"——那只是按公式推的参考,你可以沿着它走,也可以不跟,不跟的话在理由里说一句为什么。"上一轮实验员实现时的提醒"是实验员照协议写代码时看出的问题,常常比研究者的推理更早看到某条保障会挡掉什么。研究记录里有跑过的每个候选,运行记录写着每次的答案出自哪条路径。这些告诉你哪里已经挖得差不多、哪里还没人碰过、哪种判断大家一贯偏了。
### 按因子写
一条提案由一到几个因子组成(因子、配套设定、保障的意思见系统提示词"因子与保障"一节),因子数不超过材料"任务与本轮"里写的上限。每个因子写四件事:做什么;为什么你觉得它可能有用;把它关掉时换回什么——不写,就是回到基线在这件事上的做法;关键设定。之所以一个因子一个因子地写,是因为改法被采纳以后,程序会把因子逐个关掉重跑,看每个因子撑了几成;你写得越清楚,那一步越不会测错东西。
做法要写到别人能照着实现出同一个东西。好:"步长初值取可行区域边长的 1/10,连续一轮没有改进就减半,小于 1e-6 时停止。"坏:"优化搜索过程。"要用的具体数值写成规则或公式,不写由它算出来的数值表——别人照规则实现,多写出来的数只会多一处可能抄错的地方。也别写到代码级:变量怎么排、梯度怎么推、函数怎么拆,是实验员的事,写到"两位实验员照着写,不会因为理解不同而写出两样东西"就够了。写到代码级既占你的输出(单条回复有长度上限,写满了这次就交不上),也替实验员做了他更擅长的事。一个因子里只写一种做法,不写"用 A 或 B":拿不准选哪个,就挑你认为更可能有效的那个;另一个也值得试,另提一条。
**关键设定**是一句话,列出决定这个因子效果的那几个设定值,例如"幅度 0.004、窗口 15 秒、扰动后不重跑 SLSQP";没有可调设定写"无"。它会跟着这个因子进信念本,结论写成"因子名(关键设定)"。为什么要单列:上一份研究里,"不重跑优化、幅度 0.01"的扰动爬山测出来没用,下一轮大家就推广成"扰动精修基本无收益",再没人回去试"重跑优化、幅度 0.03"那一种。设定写在名字旁边,一条结论覆盖了什么、没覆盖什么,一眼看得出。
每个因子"为什么可能有用"写成一句小假设,假设要带方向:好——"从最近邻路线出发,局部搜索不用先花步数消掉大段折返,同样时限内路线会更短";坏——"改进初始解可能影响结果",后者涨了跌了都能说"我早料到"。顺手写一句它在什么情况下会没用,这正是消融要检验的。
因子的名称和做法写成离开这份提案也能读懂的话,不写"同 p2 的做法"这类只在这份提案里有意义的指代:以后的轮次、信念本都会单独引用这个因子。
正文里不写**你自己估的**分数或提升量——那是作者自评,要封存,别人要在不受你影响的情况下自己估。已经测到的分数可以引用,写明出自哪次运行(例如"消融运行 r2-…-p3 得 2.634"):那是证据,不是预期。
### 保障清单
只在评测本来不收的情形下动手、不改分的代码,写进保障清单(`safeguards`),每条一个短名(字母、数字和 `._-`,如 `final-shrink`;不能叫 `main`,也不能写成 `p1`、`p2` 这种因子编号的样子),说明它的那段文字写进正文(`body`)。短名是给实验员和程序对号用的:实验员的保障位置表、运行时记"答案出自哪条路径"、"每条保障动手了几次",都按它。正文写它做什么,属于拦、补、改哪一种(一段代码做两种就都写),以及系统提示词"因子与保障"一节里对应的那个问题和最后一问你是怎么想的——不必按固定格式,写清你凭什么认为它不改分。没有保障就交空数组。
这一节值得多花几分钟,因为算错的后果是整轮消融量的不是因子本身。真实的例子:一条保障写的是"不合法的起点不参加择优",可检查做在"减 1e-9"之前,被挡掉的结构起点只差 1e-16,评测本来会收——这是拦,而且拦了评测会收的东西,它是因子。另一条写的是"没有合格起点时改交一个结构解"——这是补,可补上去的东西自己就能拿 2.44 分,关掉一个因子以后每次都被用上,它也是因子。拿不准,就算因子。
### 两种会让结论变成假的做法
一种是把一个新想法和顺手的改动捆在一起:结果变好了,谁也说不清是哪一处起的作用。服务同一个思路的几处改动可以写在一条提案里,各自成为一个因子;写完以后挨个看你的因子,问一句"如果只有它,我还想不想试?"想的,它就是一个因子;不想、只是顺手的,删掉或者另提一条。因子数超过上限时,把关系最紧的几个留下,多出来的留到下一轮再提,而不是把两件事捆成一个因子塞进去:捆成一个因子,消融时只能一起关,永远分不出是哪一件在出力。
另一种是挑着说:只引用对自己有利的指标,或者先看到某个组合好,再回头编一套"它们为什么配合起作用"的故事。因子之间的关系(可能互相帮忙,可能在做同一件事)写你事前真实的猜测;猜不出就写"不清楚"——这本来就是消融要回答的问题。
### 延续
"延续"只用于**同一个想法的新版本**:信念本里某个因子,换了设定,或者搬到了新基线上。这时在这个因子的"延续"里写那个因子的编号(材料"可以写进"延续"的因子"一节列出了能写的编号)。受它启发想出来的新想法不算延续,留空,可以在做法里写一句"受某因子启发"。
- 该写延续的:上一轮测过"停滞期侧移接受带 0.003",这一轮把接受带换成 0.010——同一个想法换了设定。有人当时留了空,跨轮就对不上了。
- 不该写延续的:在"多起点 SLSQP"上想到"尺寸扰动重启""周期性半径置换起点""尾部高精度精修段"——它们是受启发的新想法。有人把三个都写成延续同一个因子,信念本就把三件不同的事记成了同一个因子的三个版本。
所以一份提案里最多一个因子延续同一个因子。拿不准就留空,在做法里写一句"可能跟某因子相近"。研究记录里已经跑过的改法再提时,写明这次跟上次差在哪、为什么这个差别可能改变结果。
### 协议
整份提案还要有一段协议,用小标题逐方面写:什么不许改、随机性怎么固定、什么时候停、什么运行不算数。写清什么不许改,是因为实现的人顺手改了别的,结果变好了也说不清是哪个改动起的作用。停止条件写死:参考过的真实教训,实现的人擅自加了一个提前退出,分数上去了,但那不是提案说的改法,整轮结论作废。某一方面跟这条提案无关,写"不适用:原因"。协议里不要求实验员运行求解来核对什么——按正式规模跑只能由程序来做。
### 指标
最终指标和常规辅助指标是程序统一采集的,不用写。你想用一个专门的量来检验某个因子的小假设,就在 `metrics.defined` 里新定义;要用别人登记过的假设专用指标,就把它的编号写进 `metrics.reused`。写法、两档"测不到时怎么办"各是什么后果,见系统提示词"指标"一节。特别留意一种情形:你的协议在某种情形下会让某个指标写 null(例如兜底分支获胜),就别给它选 `invalidateRun`;引用别人登记的指标时,它的档位跟着原登记走,材料的指标清单里写着。
### 你自己的三个数
你估的分数(照这条提案实现后,最终指标一成、一半、九成可能低于多少)填在作者自评里。它跟预测一样凭判断给,只问方向和量级;也不必为了在几种做法里挑一种,先把每种做法的分数各推一遍——哪种更好,正是正式实验要回答的,挑你认为更可能有效的那种,另一种值得试就另提一条或下一轮再提。真实见过的情形:一位研究者为了定作者自评,在脑子里把十几种摆法的分数挨个推了一遍,那一条回复超出了长度上限。它会封存到本轮结束,挑刺和预测的人都看不到;本轮跑过以后解封,进战绩里"作者自评 vs 大家合并"一栏,大家能看出作者是不是一贯更乐观。
### 交几条
本轮你可以交一到 M 条(M 写在材料"任务与本轮"里)。一条就很好。宁可交一条你真心觉得值得一跑、写得清楚的,也不要为了交满而补一条自己都说不清的:一条含糊的提案会占掉一次正式运行,跑完还说明不了什么。一条都找不到的时候,见系统提示词"说不出、做不到的时候"最后一条。交了以后、阶段结束前想改,可以用 `replaces` 写那一份的提交编号整份替换。
### 一份样本
下面是另一道题(用局部搜索解旅行商问题,最终指标是路线总长,越小越好)上的一条提案,只示范各部分写多长、怎么写,内容跟你的题目无关,不要照搬它的想法和措辞。
> **因子清单**
> - p1 名称"最近邻构造初始路线"。做法:初始路线从随机排列改为最近邻构造——从编号 0 的城市出发,每步走到离当前城市最近的未访问城市。关掉时换成:基线的随机排列(同一个种子)。关键设定:无。
> - p2 名称"2-opt 每轮执行改进最大的交换"。做法:每轮扫描全部城市对,执行改进最大的那一次交换(基线是遇到第一个能改进的就执行);一轮扫描没有改进就结束搜索。关掉时:不写(回到基线的首次改进)。关键设定:每轮扫描全部城市对、一轮无改进即停。
>
> **每个因子为什么可能有用**
> ### p1 最近邻构造初始路线
> 基线从随机路线出发,搜索要先花大量步数消掉大段折返。从最近邻路线出发,同样时限里搜索能更多用在细处,路线会更短。如果基线在时限内本来就能收敛到同一个局部最优,这个因子就几乎没用。
> ### p2 2-opt 每轮执行改进最大的交换
> 首次改进容易被早期的小改进带偏方向;每轮挑最大的那一次,下降路径更直,在城市多、时限紧时更可能在时限内走到更好的局部最优。代价是每轮扫描变慢,城市少时可能反而更差。
>
> **保障清单**
> - `tour-check`:每次交换后检查路线仍是全部城市的一个排列,不是就报错退出。这是"拦"里最窄的一种:它只在代码写错时动手,而那时交出的路线评测本来就不收;动手的方式是报错,不另交路线。关掉 p1 或 p2 都不会让它变得常用——正确实现的交换永远保持排列。
>
> **协议**
> ### 不许改什么
> 读入坐标、距离计算、写出路线的函数不改;总时限和随机种子不改。
> ### 随机性
> 沿用基线入口处固定的种子;p1 不引入新的随机数。
> ### 什么时候停
> 基线的总时限不变;p2 一轮扫描没有改进就提前结束,这是 p2 做法的一部分。
> ### 什么运行不算数
> 不适用:沿用任务自带的校验,路线不是完整排列时整次运行无效。
>
> **因子之间的关系**:可能部分在做同一件事。起点越好,"挑最大的交换"比"挑第一个"多挣的部分就越小;也可能相反——好的起点让每轮扫描更短、p2 更快走完。我事前更倾向前者,但不确定。
>
> **指标**:最终指标由程序统一采集;另登记一条"搜索结束时完成的扫描轮数",在搜索循环结束后读轮数计数器的值,用来看 p2 是不是因为每轮太慢而没走完;它测不到不影响成绩可信,选"缺了只记缺失"。
>
> **作者自评**:三个数单独填,不出现在上面任何一段里。
## 交什么
每条提案调用一次 `research_submit`。因子清单(`factors`)、保障清单的短名(`safeguards`)、作者自评(`authorEstimate`)、指标(`metrics`)是程序要用的:因子清单拿来数因子数、列消融格、按因子记信念本;保障短名拿来对号;作者自评封存;指标登记后每次正式实验采集。每个因子为什么可能有用、保障的正文、协议、因子之间的关系是给人读的正文(`body`),程序不拆,原样转给挑刺的人、预测的人和实验员。