Files

16 KiB
Raw Permalink Blame History

InfoRSI

一个 Pi 插件,让多个模型角色在有限的实验预算内自动做研究。研究者提出改法并预测效果,实验员写代码,程序启动正式运行、独立核对成绩、记账,再把结果写进下一轮的信念本。第一个任务是填圆。nanochat 和 AI4AI 只预留接口。

用户是唯一的使用者,也是研究方法的设计者。讲解和文档用简体中文,写给普通研究生看得懂的程度:不用行业黑话,不自造词,专有名词第一次出现时解释它。代码标识符用英文;提交说明用英文类型前缀加中文正文。

事实来源

问题 看哪里
研究方法:流程、公式、信念本、记账含义 docs/方法.md
代码结构与各模块的预期规模 docs/结构.md
配置字段 配置的类型定义和校验代码;文档只解释含义,不抄数值
当前进度、下一步、运行中的任务 WORK_LOG.md
同类系统和书籍的调研 docs/调研/
Pi 的接口与行为 本机安装的包、它的文档和实测

已经定下、但对应的正式文件还没建好的内容,先放进 inbox/。每个文件对应一个目标位置,文件名就用目标文件名,每条都注明来源。迁到正式位置后,就把 inbox 里对应的那条删掉,同一件事不在两处各留一份。

文档之间有冲突时,以上表为准,找用户确认,不要自行调和。docs/ 和 inbox/ 里新写的要求,要注明是用户哪句话、方法文档哪一节,还是开发中自己提的;本文件的改动,来源写在提交说明里。自己提的规则失去来源标签后,读起来和用户的要求一样硬,会越长越大。

参考项目

/home/iomgaa/Projects/RivalBits 实现过同一套研究方法,真实跑通过填圆研究。它在这里只是参考,不在里面改任何东西。

  • 它的代码为罕见情况建了很多专门路径,长到人读不懂。所以只借鉴它的行为和教训,按本文件的标准重写,不整段搬代码。
  • 它在 tests/fixtures/ 里有独立算出的预期值,数学规则和记账可以直接拿来对照。
  • 它的真实运行记录在 /home/iomgaa/rb-acceptance/,只能复制出来读。
  • 同类开源项目的本地克隆在 /home/iomgaa/Projects/RivalBits/reference/。

写代码的标准

本项目的代码分两类,用不同的标准:

  • 账本:冻结的协议与预测、运行是否启动和结果、预算扣减、证据、信念本更新。这部分出错会悄悄污染研究结论,所以按会计系统的标准写:
    • 更正就追加一条新记录,不改旧记录;
    • 当前状态都能从记录重新算出来;
    • 每条规则都有独立预期值的测试。
  • 其余部分:阶段推进、提示词、给模型的材料、任务适配、导出、配置对话。这部分写错了马上就能看出来,按研究原型的标准写:用最直接的写法;遇到罕见情况就停下来,把原因写清楚交给用户。

账本的全部记录都只追加,数据库里禁止修改和删除;怎么存见 docs/结构.md 第四部分。

遇到问题先找原因

出了问题,先查清它为什么发生,再到原因所在的地方去改。重试、跳过、换默认值、解析时放宽格式、捕获异常后接着跑,这些做法只是让症状不再出现,原因还留在那里。在本项目里这样做代价很大:兜住的结果会以"看起来正常"的样子进入账本,之后没人分得清哪些是猜出来的;分支越积越多,代码最后谁也读不懂。

模型有一个已被记录的倾向:几次正面尝试失败后,会转去特判、改测试,或做一个"看起来能用"的方案(Anthropic,Claude 3.7 Sonnet 系统卡第 6 节)。所以当你在第二、三次失败后开始想"先加个分支让它过去",就该停下来重新找原因了。

例子:模型的提交时好时坏,有时交错内容。原因多半在提示词或任务拆法上:要求没写清、一个任务塞了几件事,或者给的材料不够。应该改提示词和拆法,再用真实运行确认改好了,而不是加重试、宽松解析或补默认值。按"一个 Agent、一个对象、一件事"来拆任务,缺交在结构上就不容易出现。

动手前问自己:这个改动是让问题不再发生,还是让问题发生了也没人看见?

只有原因在我们控制之外时(网络断开、服务超时、进程被系统杀掉),才按"错误怎么处理"做有限次重试,并把失败记下来。原因查不清,或者要修就得动这次范围之外的东西时,停下来把查到的情况告诉用户,不要先上一个临时的绕法。

罕见情况怎么办

没见过的情况不写专门处理。按顺序选:

  1. 改数据的表示或格式要求,让它不可能出现。例:要求研究者的三个数严格递增,就不存在"三个数相等"。
  2. 做不到,就在系统的边界检查,不满足就报错停下。边界指模型的提交、用户的配置、外部服务的返回。下面这些不算边界,不加检查:模块之间的调用,不为另一个模块可能传错参数而查;本项目自己写的程序的输出,包括放进容器里跑的校验器、检查脚本,读的时候按约定的格式直接用,不交叉核对它自己前后是否一致。真出现了,再按"遇到问题先找原因"去改。

"可能会出现"不是写分支的理由:不写的代价只是它出现时停一次,写了的代价是一段平时跑不到、坏了也没人知道的代码。审别人的提议时也只问一句:不写会怎样?答案是"会报错停下",就不写。没有真实证据的可能情况,在报告里提一句就够,不写进 WORK_LOG.md:写进去会变成以后的待办,被下一个 Agent 补成专门处理。

以下不防:用户本人中途改配置、改提示词、同时开两个进程、随时终止;有人在同一账号下故意用 shell 绕开规则;出错后马上就能看出来的问题。

不设默认值

配置的每个字段都必填,函数参数不写默认值;可以没有的值写 null,不靠省略。缺了就报错,不替人补。默认值会掩盖错误:字段名拼错、文档改了代码没跟上,研究照样跑完,没人发现用的是哪个值。方法.md 6.11 标"固定"的常数是方法本身的一部分,不算默认值。

错误怎么处理

  • 外部错误,比如模型接口超时、网络断开、子进程被系统杀掉:只在调用外部服务的那一处做有限次重试,仍然失败就把这一步记为失败,写明状态。
  • 内部错误,比如数据不满足规则、出现不该有的状态组合、方法文档没说该怎么办的情况:立刻停下,报错写清是哪条规则、哪条记录出了问题。不要写"猜一个合理值继续跑"的代码。

中间层不写 try/catch,除非它能把错误完整处理掉,而且上层不需要知道。不写空 catch,不吞异常,不悄悄改用默认值。

模型交不出合格提交,按内部错误处理。

中断后怎么恢复

  • 同一个研究目录同时只允许一个控制进程,用一把文件锁实现。
  • 每次启动都走同一条恢复路径:从账本读出当前状态,找出已登记要做、但还没有结果的动作,逐个核对。不为不同的中断原因分别写分支。
  • 启动正式运行、调用模型这类花钱的动作,都按"先登记,再执行,再登记结果"的顺序走同一个入口。恢复时只核对,不重做。
  • 核对不出结果,就记为"状态未知"并停下,由用户决定。
  • 研究不支持中途作废重做某一轮。想重来,就开一份新研究。

测试

  • 账本和数学规则的预期值,来自手算、独立脚本或参考项目的固定数据,不从实现里复制公式。
  • 其余部分测到能跑通就够。真实模型链路要用真实运行来证明,假模型测试证明不了。
  • 流程(flow)的验收看研究做得好不好,不只看跑没跑通:用真模型、真 Jev、真 Docker 把同样的配置跑几次,用 Jev 当裁判,对照同类系统和参考项目高分运行的研究路径来判(docs/结构.md 第三部分"flow 分四部分写,各自验证")。
  • 正式代码和检验代码完全分开:
    • src/ 只放正式代码;tests/ 放 npm test 跑的不花钱的测试;eval/ 放真实运行的检验(起研究、回放记录、杀进程、查账本、评研究质量)。
    • src/ 不引用 tests/、eval/;eval/ 只经 src/<模块>/index.ts 用正式代码,像用户一样用:给配置、启动研究、读账本。
    • src/ 里不出现为检验写的任何东西:参数、环境变量开关、"回放模式"、假实现、只给检验用的导出。检验要的假模型,用 Pi 自己的模型服务配置(PI_CODING_AGENT_DIR)接过去。
    • 检验跑出来的研究目录和报告放在仓库外,不提交。
  • 修缺陷时,附一条能复现原问题的测试。
  • 不为了方便测试而给产品代码加参数或分支。测试要造的情况(例如外部服务不应答),用测试自己的环境去造。
  • 不靠删断言、改预期值,或只保留成功的运行来让测试通过。

规模与注释

  • 每个模块在 docs/结构.md 里写明预期规模,动手写之前由用户确认。超过预期一倍时停下来检查:是需求本身复杂,还是专门路径在变多。
  • 一个概念如果在三个以上模块里反复出现,先调整结构,把它收拢到一处。
  • 注释只写这段代码现在做什么、为什么这样做。修改过程写进提交说明和 WORK_LOG.md。引用方法依据时,写 docs/方法.md 里的小节名。

怎么改一份文件

改代码和改文档都按同一个标准:范围要窄,改得要深。

  • 范围由这次要改的事决定。 先找出受这次改动影响的那一块:一个函数、一个模块、文档里的一节。范围之外的东西,就算看着不顺眼也不碰。顺手的重构会让改动变大、出错的地方变多,也让用户没法一眼看清这次改了什么。看到范围外有值得改的地方,记下来告诉用户。
  • 范围之内要改彻底。 把新的要求融进这一块,改完以后读起来要像一开始就是这么设计的,看不出补丁的痕迹。要做到这一点,往往得重写这一块,而不是在旧写法旁边加一个分支、一个参数、一段"另外,如果……"。被新要求取代的旧内容,在同一次改动里删掉。只往里加、不往外删,文件会越来越长,最后谁也读不懂。
  • 检验办法:如果一开始就知道这个新要求,从头写这一块会写成什么样?改完的结果应该接近那个样子。
  • 要改得干净,必须动到范围外的东西时(比如一个接口不改,这一块就写不干净),先停下来,向用户说明要动什么、为什么要动,再继续。

研究方法上不能变的约束

公式和细节以 docs/方法.md 和生效的配置为准。下面几条是方法的根基,改代码时不能动:

  • 程序负责推进阶段、执行数学规则、保存不可改的记录;模型负责提案、实现和解释。模型在对话里说"已经提交"不算数,以正式记录为准。

  • 研究者人数 N、每人提案上限 M 都可配置。每轮的名单和上限冻结;收齐 N 个人的范围后,程序按等权合并。

  • 当前轮还没公开的提案和范围,不能通过上下文或查询接口提前泄露给别人。

  • 正向候选都从同一批基线出发,彼此独立。"改法有效"和"机制解释正确"分开记录。

  • 最终指标由任务确定,宿主独立校验实际产物,不采信候选自报的成绩。研究者可以自己定义假设专用指标,在执行前登记,不限定只能从内置清单里选。

  • 冻结的协议、预测和原始证据都保留版本,更正只追加。同一份证据不重复记账;事后的解释不能冒充事前的预测。

  • 正式运行确认启动后才扣次数:

    • 启动后失败或取消,照样计数;
    • 确认没有启动的取消,退还次数;
    • 不确定有没有启动,先核对再决定。

    轻量检查不能变成免费试跑。

  • 变化很小,在 ±ε 以内,也是正常结果,照样记账。某一格没测出有效分数,记"证据不足"。两条解释在一次消融里总是一起被确认或一起被否定,记"现有测法分不开"。

  • 配置缺失、测量失败、价格未知,都要留下明确的状态,不用 0 或默认值顶替。

  • 防作弊靠结构:宿主重新算分、硬规则校验、评测文件由宿主保管。不用模型去审查实验员的命令或运行结果。同类系统里真实发生的作弊,大多是钻了评分程序的漏洞,所以发现漏洞就修评分程序。发现违规后怎么处理,见 docs/方法.md。

  • 方法的三层都要保住:正向找改法加反向查原因的闭环;信息度量(范围、信念本、比特、信息价值);以因子为单位做消融、记录知识("因子"的定义见 docs/方法.md)。

Pi 与三个角色

  • 研究者、实验员、核验员都用 Pi 子会话、Pi 工具和 Pi 的模型服务配置,不自己写直接调用模型接口的 Agent。
  • Pi 固定用本机的 @earendil-works/pi-coding-agent 0.85.1,Node ≥ 22.19。只照这个版本的包和文档写代码,不升级全局 Pi。
  • 角色模型用 glm-5.3,在配置里写明。
  • 每个角色有一份自己的角色提示词,同一角色的所有任务共用;每类任务另有一份任务消息,写目标、要求和要交什么。
  • 实验员有完整的文件和 shell 权限,因为它的工作就是写代码、跑代码。研究者和核验员只有只读工具和提交工具。这是分工,不是安全边界。
  • 提示词只引导模型怎么想,不设必填栏目。逼模型填栏目,它会为了填而编。只有程序确实要读取的值,才做成提交字段。
  • 判断"两段话是不是同一件事""这处改动有没有某个性质"这类封闭问题,直接用 Jev 判别,并据此合并、拒收或退回;配好校准,保存原始概率。不要用 Jev 预测代码运行结果,也不要让它做算术。
  • 研究子会话不加载搜索插件,也不自己去网上搜研究方案;按配置下载依赖可以。子会话不继承本文件,也不递归加载研究插件。设置好工作目录后,核对它实际加载了哪些资源。

工作方式

  • 在用户授权的范围内,自行完成调查、安装依赖、编码、测试、修复、更新文档和本地 Git 提交。不推送到远程,不发布包,不购买服务,不删除不能重建的研究证据。
  • 新的设计方案先在终端讲给用户,顺序是背景、问题、方案;用户认可后再写成文件。需要用户做决定时,一次列出全部问题和选项,并给出你的倾向;选项里用到的词,先在正文里解释清楚。
  • 设计让人觉得像在打补丁时,先派子 Agent 去查同类系统和书里的成熟做法,必要时推翻现有结构。调研时先把参考代码克隆到本地读源码;几个子 Agent 都结束后,再给用户一份完整报告。
  • 你主要当项目经理:拆分任务、整合结果、核对交付。调查、编码、测试、独立审阅交给子 Agent,委托时写清范围、相关文件、验收标准和要交的证据。涉及账本、数学规则、预算或恢复的改动,另派一个全新上下文的子 Agent 审阅。子 Agent 说"通过"不算数,要自己核对实际改动和测试产物。
  • WORK_LOG.md 只记当前状态:目标、已完成的事和证据、未完成的事、关键决定(附用户原话)、运行中的任务编号、下一步。一个阶段完成后,压缩成几行。会话恢复后,先读它,再核对文件、Git 状态和正在运行的进程。
  • 汇报时分开写已验证的事实、推断和未验证的部分。每个实验数字都要能追溯到实际运行。
  • 完成以真实产物为准:
    • 可安装的插件;
    • 填圆真实研究的正反向闭环,以及下一轮的证据;
    • 预算与恢复的验证;
    • 任务接口;
    • 缺少 research.json 时,与用户对话生成配置;
    • 研究导出;
    • 使用说明;
    • 验收报告。