diff --git a/CHANGELOG.md b/CHANGELOG.md index ff9e9eb35..b807939f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,12 @@ - 登记面:research readme / knowledge-map / mermaid README / source-figures README / issue I-239。 - 验收:56 行源稿对账(8 行返工复判收口,COUNTS 全零)+ 增量 Checker 核外行补阙 26 行 + 盲评 3 章(成稿全胜)+ 外行四测四项出闸(LLM 代理作答;两处事实错误经测出并修正:信号别名表无中文、hold 官方中文为「持有」)。 +### Harness 到 Harness² 双源精读与通俗拆解入库(agent-harness 179,2026-10-28) +### Harness 到 Harness² 双源精读与通俗拆解入库(agent-harness 179,2026-10-28) + +- [179 精读](docs/research/agent-harness/179-harness-to-harness2.md):Harness-Zero(arXiv:2609.24974v1,训练期审阅门蒸馏进权重、部署卸载)× Harness²(arXiv:2610.14224v1,部署期冻结模型的对比式 PPC + 双层递归库)合并精讲——互不引用、非换代,按「同一问题的两条互补路线」组织;两篇公式链 (1)-(5)/(1)-(4) 逐条白话拆解,正文 4 张论文原图(CC BY 4.0,TeX 源码包矢量 PDF 渲染入 `docs/assets/source-figures/agent-harness/`),配套纯标准库原型 `harness2_lab.py`(selftest + D1–D5 破坏实验 + 字数门禁 count 模式)。 +- 登记面:research readme 第九节、knowledge-map Research 节、source-figures README(agent-harness 分组)。 + ### 信源原图资产库统一:papers/ 迁入 source-figures/(2026-10-26) - `git mv docs/assets/papers/multimodal-models`(KTP 论文图 1–7,PR #1211 建)→ `docs/assets/source-figures/multimodal-models/`,全仓仅此一个原图库;240 正文的 7 处图片路径同步。 diff --git a/docs/.agents/knowledge-map.md b/docs/.agents/knowledge-map.md index 10fcf3f4d..d5113c528 100644 --- a/docs/.agents/knowledge-map.md +++ b/docs/.agents/knowledge-map.md @@ -99,3 +99,4 @@ - [科普视频内容工作区(apps/negentropy-influence)+ vibe-video 技能](../../apps/negentropy-influence/README.md) — **机制外置 skill、本仓持内容与发布顺序 SSOT**:论文→视频九阶段流水线机制(`pipeline.py` 单入口、[stages.toml](https://github.com/ThreeFish-AI/vibe-video/blob/main/pipeline/stages.toml) 九阶段唯一声明、[config.py](https://github.com/ThreeFish-AI/vibe-video/blob/main/pipeline/scripts/config.py) schema/默认值层、`timing.json` 时序 SSOT、skills/01–09 规格、[骨架模板三件套](https://github.com/ThreeFish-AI/vibe-video/blob/main/pipeline/templates/video-skeleton/skeleton.toml)、`pipeline/tests`)已迁出本仓,收敛为公开技能 [vibe-video](https://github.com/ThreeFish-AI/vibe-video)(GitHub ThreeFish-AI/vibe-video,MIT,技能入口 [SKILL.md](https://github.com/ThreeFish-AI/vibe-video/blob/main/SKILL.md),安装于 `~/.claude/skills/vibe-video`;运动层铁律与规格见 [skills/06](https://github.com/ThreeFish-AI/vibe-video/blob/main/pipeline/skills/06-remotion-implementation.md)、信源 A/B 两型见 [skills/01](https://github.com/ThreeFish-AI/vibe-video/blob/main/pipeline/skills/01-source-extraction.md))——机制文档以 skill 仓为唯一事实源,本仓零副本(集侧 scripts/ 均为转发 skill 解析器的薄包装)。本仓持有:episodes/ 分集 + [series.json](../../apps/negentropy-influence/series.json)(发布顺序 SSOT;check_series 六规则执法——口播反串线/多标题顺序/序号绑定/清单完整性含反向登记与撞色/死链/可渲染性)+ source-map/ 信源地图 + series-assets/ 系列级资产种子(CC 系列片头 intro/ 与五集副本逐字节孪生,[check_twin_files.py](../../scripts/check_twin_files.py) 执法,I-209) + voices/ 参考音频,路径锚点=根哨兵 `.influence-root`(skill 兼容识别,对目录深度免疫);check_series 的工程级受检面(规则 2/3/5 扫描本文件与 CHANGELOG)由工作区根 vibe-video.toml 的 `[check_series] project_globs` 声明。 - [科普视频作品总览(四个系列 15 集)](../../apps/negentropy-influence/series.md) — 机读 SSOT [series.json](../../apps/negentropy-influence/series.json) 顶层为 `seriesList[]`;**自进化系列**(论文型)《上线之后,AI 才开始上学》(金/青/紫,v3 已交付,成片 14:01)→《AI 如何自己变强?》(蓝/橙)→《会写代码的 AI,开始给自己写代码》(绿/洋红);**Claude Code Harness Engineering**(文档/代码型,五集完全重制 v1 已交付,archify 全屏独占 + V3D 装置层)《工具与执行:一个循环,三层装置》(陶土橙/石青,14:02.6)→《规划与协调:视野错位的五种修正手法》(鸢紫,前代 v1 成片 14:12.2)→《记忆管理:会丢的和不能丢的》(苔绿,14:13.3)→《并发:谁来按下开始》(霜蓝,14:10.8)→《多 Agent 平台:七件设施,一条走廊》(协作金,14:17.8 edge 版);信源 Learn Claude Code s01–s20 双钉(首集钉仓库 main `ce8f9f18` 17 章整合版,其余四集钉站点同源修订 `67a9126c` 20 章版,MIT,归属登记见 [source-map](../../apps/negentropy-influence/source-map/claude-code-explained.md))。多系列执法语义:反串线规则跨系列全局,顺序类规则按系列内判定;口播永不携带集数序号,顺序变更 TTS 代价恒为零。 - [Apple Watch Ultra 4 换货开箱视频项目(influence/live/apple-watch-ultra-4-unboxing)](../../apps/negentropy-influence/live/apple-watch-ultra-4-unboxing/README.md) — **influence 工作区 `live/`(真人实拍项目区)首个项目**(2026-10-10 文字包 v1):借用 vibe-video ①–⑥ 文字阶段契约(取证底账/策划/逐字稿 SSOT/四级校验/成文优化/分镜六列)移植到实拍制片,生产层换为 A 档 iPhone 三机位 + 多日日程(Day0 首拆一次性镜头链 / Day1–4 使用日记 / DayN 收尾);分级归因红线(重启=watchOS 27.0 已知已修、掉线=个案)与两段式 ⟨TBD⟩ 定稿点为其真实性核心机制(v2.3 用户校准:换货为同款零售彩盒、官网 14 天退换期);与 episodes/ 的 Remotion 动画集平级共处、不登记 series.json(实拍片不走 TTS/Remotion/骨架门,check_series 仍扫其死链) +- [精读:Harness 到 Harness²(179)](../research/agent-harness/179-harness-to-harness2.md) — Harness-Zero(arXiv:2609.24974v1)× Harness²(arXiv:2610.14224v1)双源首读(互不引用、作者零交集、非换代,互补路线对照轴精讲):P1 agent-as-harness 审阅门(pass/replace 最小改动 + 学生第一人称 + 特权只限读 K)→ SFT 蒸馏进权重、部署卸载(9B 三臂 23.3 < 41.7 < 44.3;监督源消融 K 30 vs oracle 答案 15 vs teacher+h\* 错配 3——采集分≠蒸馏价值;28 模式恢复 82.3%、弱模型审阅反噬 −12.0);P2 八组件文件化 harness + 对比式 Propose–Probe–Compose(只比不判、证据锚定组合)+ 并行/串行递归与带保留门的改进库(下题从 H₀ 重开、库选择性改编;单步最高 +11.5、递归再涨、去库 −3.1、跨模型迁移 GLM-5 Code +17.3、胜生产 harness +4.6~5.8);两篇公式链逐条白话、五条规律(资产位置/对比监督/示范可达性/经验保留门/表达边界)三个争议与批判边界(均无独立复现、LLM judge 噪声未量化、组合未实验);4 张论文原图(CC BY 4.0,TeX 源码包矢量渲染入 source-figures);配套原型 [harness2_lab.py](../research/agent-harness/assets/harness2_lab.py)(纯标准库确定性,五组破坏实验:D1 恒放行恢复率归零 / D3 盲判分增益噪声化 / D5 无库失去跨任务反哺档) diff --git a/docs/assets/source-figures/README.md b/docs/assets/source-figures/README.md index a6d1cb96c..0030fd97e 100644 --- a/docs/assets/source-figures/README.md +++ b/docs/assets/source-figures/README.md @@ -50,3 +50,14 @@ KTP 论文图 1–7 由 TeX 源码包矢量 PDF 渲染为 PNG,2026-10-26 自 ` | 8 | [openviking--src-08-readme-benchmark.png](./cognitive-context/openviking--src-08-readme-benchmark.png) | 钉点 [`docs/images/benchmark-dark.svg`](https://github.com/volcengine/OpenViking/blob/6227af5102b3874d162d65a0503bfeef849686c2/docs/images/benchmark-dark.svg)(README 基准图) | AGPL-3.0 | SVG 2× 栅格化,透明底烘暗底 `#020617`,四周留 24px 边距 | | 9 | [openviking--src-09-vikingmem-schema.png](./cognitive-context/openviking--src-09-vikingmem-schema.png) | [VikingMem, arXiv:2605.29640v3](https://arxiv.org/html/2605.29640v3#S2.F1) Figure 1(J. Fu *et al.*) | CC BY-NC-SA 4.0 | 原样 | | 10 | [openviking--src-10-product-retrieval-claims.png](./cognitive-context/openviking--src-10-product-retrieval-claims.png) | [openviking.ai/product](https://openviking.ai/product)「三层结构,按需加载」与「理解结构的检索」两节(前端 bundle `index-BfoH6ZUa.js`) | 版权归原作者,仅作学习引用 | 无头浏览器暗色 2× 截图,隐藏吸顶导航 | + +### agent-harness · Harness 到 Harness² 精读([179](../../research/agent-harness/179-harness-to-harness2.md)) + +抓取基准为 arXiv:2610.14224v1 TeX 源码包(e-print,2026-10-28 下载),矢量 PDF 经 pdftoppm 200dpi 渲染 PNG(RGB 白底,无透明通道);论文许可 CC BY 4.0。 + +| 文件 | 出处 | 许可 | 处理 | +| --- | --- | --- | --- | +| [harness2--fig2-eight-components.png](./agent-harness/harness2--fig2-eight-components.png) | Harness² 论文 Fig.2(components.pdf) | CC BY 4.0 | 矢量 PDF 渲染 PNG | +| [harness2--fig3-ppc-pipeline.png](./agent-harness/harness2--fig3-ppc-pipeline.png) | Harness² 论文 Fig.3(harness2_main_new.pdf) | CC BY 4.0 | 矢量 PDF 渲染 PNG | +| [harness2--fig4-recursion-forms.png](./agent-harness/harness2--fig4-recursion-forms.png) | Harness² 论文 Fig.4(scaling.pdf) | CC BY 4.0 | 矢量 PDF 渲染 PNG | +| [harness2--fig9-jobbench-case.png](./agent-harness/harness2--fig9-jobbench-case.png) | Harness² 论文 Fig.9(case_jobbench.pdf) | CC BY 4.0 | 矢量 PDF 渲染 PNG | diff --git a/docs/assets/source-figures/agent-harness/harness2--fig2-eight-components.png b/docs/assets/source-figures/agent-harness/harness2--fig2-eight-components.png new file mode 100644 index 000000000..63b4798f6 Binary files /dev/null and b/docs/assets/source-figures/agent-harness/harness2--fig2-eight-components.png differ diff --git a/docs/assets/source-figures/agent-harness/harness2--fig3-ppc-pipeline.png b/docs/assets/source-figures/agent-harness/harness2--fig3-ppc-pipeline.png new file mode 100644 index 000000000..419e2423e Binary files /dev/null and b/docs/assets/source-figures/agent-harness/harness2--fig3-ppc-pipeline.png differ diff --git a/docs/assets/source-figures/agent-harness/harness2--fig4-recursion-forms.png b/docs/assets/source-figures/agent-harness/harness2--fig4-recursion-forms.png new file mode 100644 index 000000000..5b5f1be85 Binary files /dev/null and b/docs/assets/source-figures/agent-harness/harness2--fig4-recursion-forms.png differ diff --git a/docs/assets/source-figures/agent-harness/harness2--fig9-jobbench-case.png b/docs/assets/source-figures/agent-harness/harness2--fig9-jobbench-case.png new file mode 100644 index 000000000..b5c916a3c Binary files /dev/null and b/docs/assets/source-figures/agent-harness/harness2--fig9-jobbench-case.png differ diff --git a/docs/research/agent-harness/179-harness-to-harness2.md b/docs/research/agent-harness/179-harness-to-harness2.md new file mode 100644 index 000000000..f647949ef --- /dev/null +++ b/docs/research/agent-harness/179-harness-to-harness2.md @@ -0,0 +1,282 @@ +--- +sidebar_position: 14 +title: "Harness 到 Harness²:把 harness 的收益放进权重,还是让 harness 自己进化——精读与通俗拆解" +description: "arXiv:2609.24974v1(Harness-Zero,蒸馏进权重)× arXiv:2610.14224v1(Harness²,部署期递归自改)双源精读:四机制拆解、4 张原图、原型破坏实验。" +--- + +# Harness 到 Harness²:把 harness 的收益放进权重,还是让 harness 自己进化 + +> [1] H. Ye, Y. Lu, H. Dong, Z. Su, and G. Song, "Harness-Zero: Harness distillation via agent-as-harness," arXiv:2609.24974v1 [cs.AI], Sep. 2026. [Online]. Available: https://arxiv.org/html/2609.24974v1 (v1,2026-09-21 提交,唯一版本;北大、Google、港科大;访问 2026-10-28). +> [2] R. Xu, Y. Chen, Z. CuiZhu, et al., "Harness2: Recursive agent harnessing for an open world," arXiv:2610.14224v1, Oct. 2026. [Online]. Available: https://arxiv.org/html/2610.14224v1 (v1,2026-10-09 提交,唯一版本;Google Cloud AI Research;CC BY 4.0;访问 2026-10-28). + +> [!NOTE] 精读范围 +> 两篇全文通读含附录,快照钉 v1 HTML;补读两仓 README [9][10]。互不引用、零交集,按两条互补路线精讲,不作换代处理。 + +**一句话定位**:两篇同期独立论文回答同一问题——harness 带来的提升放在哪才能不一直背着它跑:Harness-Zero 练进模型权重(训练期蒸馏、部署期卸载),Harness² 让 harness 体系自己进化(部署期在线递归、权重冻结)。 + +大语言模型(LLM)agent 干活靠的不只是模型,还有包在外面的一层系统——给它哪些工具、怎么组织可见信息、出错怎么拦截——这叫 **harness**(本仓 [170 总纲](./170-claude-code-harness-overview.md)有完整梳理)。调好能大幅提分,但提分绑在 harness 上:要么共用一套次优的,要么维护一堆专用的外加路由。两篇由此分头出发:一条训练期把好做法练进参数(权重),一条部署期让模型冻结、harness 现场改并越改越会改。本文按问题→对照→四机制→实证→规律边界展开,原型 `assets/harness2_lab.py`。 + +先消歧一个撞车词:两篇都造了 "harnessing"——P1 的指包裹学生的**审阅代理**,P2 的指**优化脚手架本身**;下文带限定。 + +> [!TIP] **白话主线** +> ① 调好一套 harness 能大幅提分,但收益绑在 harness 上,换场景就得换一套——两边都想把收益存起来。② Harness-Zero(下称 P1)训练期动手:审阅代理守在学生动作出口,照一份从专用 harness 翻译来的审阅知识放行或改写动作,改好的动作拿去微调、做法进权重。部署时专用 harness、审阅知识、审阅代理全卸,90 亿参数学生在只有一条 Bash(命令行)的极简 harness 下从 23.3% 提到 44.3%,反超挂专用 harness 的 41.7%。③ Harness²(下称 P2)部署期动手:模型冻结,每来新任务就现改 harness——提两类候选、同条件试跑、只比「行为变没变」不判对错(开放世界无标准答案),按证据拼更好的;任务后把「怎么改才有效」存进改进库,越改越准,单步最高 +11.5、递归再加码。④ 均无第三方复现;一个把收益搬进权重、一个让改法自己变强,互补非换代。 + +## 1. 它要解决什么问题 + +痛点是同一个观察的两面。P1:harness 优化改的是外围不是模型,收益部署时仍绑着它;最好的 harness 因领域、任务、模型而异,共享则次优、路由则贵——都不「把发现的东西变成模型的能力」。P2:开放世界任务设计期没见过、测试时全新,无标准答案也无自动判分器,离线优化好的静态 harness 往往泛化不到新环境,逐任务现改又太特化。 + +分工一句话:P1 管「**收益放哪**」(搬进权重),P2 管「**怎么现场改、越改越好**」。规格对照: + +| 维度 | Harness-Zero(P1)[1] | Harness²(P2)[2] | +| --- | --- | --- | +| 改什么 | 模型权重(微调) | 执行 harness 与改进库,权重冻结 | +| 何时改 | 训练期一次性 | 部署期每任务在线改 | +| 监督信号 | 审阅代理 + 审阅知识 K(不含答案) | 无真值,只有同条件行为对比 | +| 成本位置 | 采集期一次性(逆合成基准 USPTO 延迟 2.4 倍) | 推理期持续(多次执行+编辑会话) | + +部署产物、失败面与术语撞车详见 §2.5 对照轴。 + +## 2. 全貌解剖 + +两篇各是一条完整的因果链。 + +P1 链:强 harness 收益绑部署 → 直接模仿「强模型挂专用 harness 的轨迹(干活全过程记录)」动作空间对不上 → 把指导翻译到学生响应边界,审阅代理逐动作放行或改写 → 改写轨迹全是学生做得出的动作 → 微调进权重 → 部署只剩极简 harness,收益反超外挂。 + +P2 链:开放任务无真值 → 「让模型判对错」不可靠(执行有波动、裁判与干活模型共享盲区)→ 只信「同条件下改前 vs 改后的行为差异」,对比当证据不当判决 → 改动绑定具体观察 → 任务内可加预算递归 → 任务后把采纳 harness 与经验过「执行对比支撑」门入库 → 后续改法受益。 + +四个焦点按价值排序:P1 审阅门(§3)、P2 对比式改进步(§5,无真值监督替代设计)、P1 蒸馏消融(§4,颠覆「数据越好学生越好」)、P2 双层递归库(§6,「学习如何学习」最小实现)。 + +### 2.5 对照轴:两条路线怎么选 + +| 轴 | P1:harness→权重 | P2:harness→更好的 harness | +| --- | --- | --- | +| 核心假设 | 好做法练进参数随身带 | 好改法攒成经验库复用 | +| 训练权限 | 必须能微调 | 不需(API-only 可) | +| 新任务上线 | 零适应,直接跑 | 每任务多次执行换适应 | +| 收益上限 | 受「可表达为学生动作」封顶(§4) | 受探针信号质量封顶(§6) | +| 术语 | harnessing agent = 审阅代理 | harnessing = 优化脚手架这件事 | +| 互补位 | 统一部署、免维护 | 模型换代 harness 仍可用(GLM-5 Code +17.3,§7) | + +两篇也展望过对方领地(P1 期待「更好的模型造更好的 harness、收益还给权重」的循环;P2 提出库管理与自适应递归)。先在线改、再批量蒸馏是自然组合,均未实验,本篇只作推断。 + +## 3. 机制一(P1):审阅门——agent-as-harness + +机制是一条公式链,先摆原文再逐条拆解。记号说人话:$h$=部署用极简目标 harness;$h^{\star}$=训练任务上演化的专用 harness;$\mathcal{K}$=翻给审阅者的「审阅知识」;$\pi_S$ 学生、$\pi_H$ 审阅代理;$y$=学生提议的动作,$\tilde{y}$=审阅后实际执行的;$c$=学生可见信息。 + +```math +h^{\star}=\operatorname{Evolve}(\mathcal{D}_{\mathrm{train}}),\qquad \mathcal{K}=\operatorname{Adapt}(h^{\star};\,h) \tag{1} +``` + +```math +y_{t}\sim\pi_{\theta_{0}}^{h^{\star}}(\cdot\mid c_{t}),\qquad c_{t+1}=T_{h^{\star}}(c_{t},\,y_{t}) \tag{2}\ \text{(基线:code-as-harness)} +``` + +```math +\begin{aligned} +&y_{t}\sim\pi_{S}(\cdot\mid c_{t}):=\pi_{\theta_{0}}^{h}(\cdot\mid c_{t}),\qquad (d_{t},z_{t})\sim\pi_{H}(\cdot\mid c_{t},y_{t},\mathcal{K},r_{答案 | +| P1 行为恢复 [1] | 28 模式平均 82.3% | 支撑≥10 任务 | 程序性近满、知识类弱 | +| P1 弱模型反噬 [1] | 相对差 −12.0(替换 66% 步骤) | 最弱档 Qwen3.6-35B;USPTO(化学逆合成) | 审阅不足越改越差 | +| P2 单步增益 [2] | WB +11.5 / Job +4.5 / LAB(法律基准)+11.8 个百分点 | 四配置最大,k=1 | 一步见效;弱执行器受益更大 | +| P2 vs 生产 harness [2] | 胜最强固定项 +4.6/+5.8/+4.9 | Gemini 3.5 Flash,OpenCode 起点 k=5 | 现改胜过原装 | + +同一模型当执行器兼编辑器(k=2)时五模型全部基准仍涨(GLM-5 在 LAB +13.7)[2]——不必依赖更强的编辑模型。 + +![论文图 9:JobBench 案例研究](../../assets/source-figures/agent-harness/harness2--fig9-jobbench-case.png) +左:任务与失败模式;中:改出的 harness(着色组件系测试时写);右:重跑 43.1→77.8。来源:Xu et al. 2026 [2] 原文图 9,CC BY 4.0。 + +附录 E.7 另有五个修复案例,共性「行为病对组件位」:工具指引禁伪调用 60→100、技能钉汇总粒度 23.6→100、技能重推导页面状态 64→100、技能记法律修订标记 44.4→94.5。 + +三条核心宣称(P1 三臂与消融、P2 四配置增益)经 2026-10-28 检索无独立复现,均为作者单组自报;代码已开源(Apache-2.0)[9][10],可运行≠已验证。 + +## 8. 动手实验室 + +原型 `harness2_lab.py`(纯标准库、零随机、480 行)各 mock 一份核心机制:P1 侧规则审阅代理(签名不含 gold 即标准答案,结构性保证「不可见答案」)+ 频率表自增当 SFT + 三臂评估;P2 侧八组件 harness、PPC 对比步(含噪声候选与膨胀惩罚)、串并行递归与带保留门的库。运行: + +```bash +python3 docs/research/agent-harness/assets/harness2_lab.py demo # 基线对照 +python3 docs/research/agent-harness/assets/harness2_lab.py selftest # 全断言 +python3 docs/research/agent-harness/assets/harness2_lab.py break D1 D2 D3 D4 D5 +python3 docs/research/agent-harness/assets/harness2_lab.py count # 字数门禁 +``` + +机制→行号速查:`reviewer_pi_h`:95 · `collect_trajectory`:121 · `mock_sft`:151 · `arm_scores`:180 · `probe_score`:230 · `probe_delta`:250 · `propose`:257 · `compose`:280 · `ppc_step`:295 · `run_stream`:310 · `run_parallel_k`:333 · `count_words`:426。 + +破坏实验(改一两行、真跑记录,(mock, 方向性)): + +| 实验 | 拆什么 | 实测退化(实际运行日志) | 教训 | +| --- | --- | --- | --- | +| D1 恒放行 | 审阅代理永远 pass | 恢复率 0.7625→0,蒸馏臂跌回裸学生 0.5627 | 无审阅则训练集=学生自我重复 | +| D3 盲判分 | 探针偷看 gold 改绝对判分 | 流式增益 0.65/0.80→0.33/0.33,噪声候选混入库 | 对比换成「判对错」,编辑选择被噪声接管 | +| D5 库冻结 | 改进库永不更新 | 后半程增益 0.8024→0.6025,与任务内一档持平 | 丢的是跨任务反哺档,任务内单步增益还在 | + +D2(采集不更新频率表:蒸馏臂=裸学生)与 D4(组合门失效全收:负增益编辑入列、增益回落)见 `break` 输出;共同点是每个组件拆掉都有具体的退化形态。 + +## 9. 底层规律与核心争议 + +### 9.1 五条规律 + +**规律 1:能力增量可存于脚手架,也可回流进权重**(资产位置)。收益可挂在 harness 上用、也可练进参数随身带,放错位置更糟——9B 挂通用 harness 反降(§4)即其代价;蒸馏 44.3>41.7 证实搬得进去,跨模型迁移 +17.3 证实放得住。[3][4] + +**规律 2:无真值时「对比」可替代「判定」作弱监督**(监督信号)。没标准答案就别让裁判判对错,用同条件下「改前 vs 改后」的行为差异当证据;否则会退回「让强模型打分」——无对比锚定的 Harness Scaling 十二组配置对里七对不如不改;去分维消融掉 2.9–3.7;P1 同构印证(喂答案只蒸 15% vs 程序指导 30%)。[5] + +**规律 3:示范必须落在学习者的可达动作空间内**(示范可达性)。示范必须是学生做得出的动作;老师用学生没有的工具做的「好示范」学完更差——老师+$h^{\star}$ 蒸出 3% 是最直接的反例。[6] + +**规律 4:经验须过证据保留门才可入长期库**(经验治理)。「碰巧有用」写进长期记忆,库越积越脏;只有行为对比撑得住的经验才配长期保留,否则复用变污染(P2 失败分析专有「错误前提跨候选传播」类)。保留门原文口径「选中≠可迁移」,去库消融即刻掉 3.1。[7] + +**规律 5:进不了动作空间的机制进不了权重**(表达边界)。蒸馏只能传递「学生做得出的动作」里携带的东西;绕开模型起作用的机制练不进去——context 管理与深层知识都卡在这里。[8] + +五条合成「harness 能力迁移」选址地图:收益放哪(1)、信号是什么(2)、通路(3)、治理(4)、边界(5)。 + +### 9.2 三个争议 + +**争议一:长久资产是权重还是 harness。** P1 派:练进权重才统一部署、免路由,harness 优化应成滚雪球的训练信号源;P2 派:权重不动才可逆可审计,模型换代 harness 仍在(GLM-5 Code +17.3)。分歧在各自看到的成本;可组合但均未实验。 + +**争议二:强模型当裁判,依赖还是设防。** P1 拿它当教师级组件(信其程序性判断);P2 当噪声源处处设防(匿名交付物、只用对比、保留门)。裁判信度随「有无确定性参照」而变——P1 的裁判有 $\mathcal{K}$,P2 的两手空空;审阅模型一弱,P1 直接反噬(−12.0)。 + +(第三重张力「部署期预算哲学」见 §1 规格表「成本位置」行:前置一次性 vs 推理期持续付费,长流总账两篇都没算。) + +## 10. 适用边界 + +### 10.1 成立条件 + +P1 需要:训练任务集、够强的审阅模型(学生兼审阅在弱档反噬)、学生可微调、部署确需统一极简 harness。P2 需要:开放任务流(无真值)、模型冻结、可承受每任务多次执行。共同前提:harness 可编辑成组件文件、任务有可评测成功率(P2 设护栏防判分器泄漏)。 + +### 10.2 材料没有证明的事 + +1. 均无独立第三方数值复现(2026-10-28 检索;主表系作者单组三-run 均值)。 +2. P1 未测蒸馏后模型在其它目标 harness 下的表现;「极简 harness 就够」是作者预期(将来时),非实验结论。 +3. P2 的 LAB 与 JobBench 评分全靠 LLM 判分器,评分噪声未量化传递(失败九例中「评委噪声」自成一档)。 +4. 「持续改进」未经长流验证:P2 单流测试任务量级 34–100,分布漂移下的长期表现未测。 +5. 两条路线的组合(先在线改、再批量蒸馏)无人实验,§2.5 的互补判断是推断。 + +## 11. 用户自测与费曼研讨套件 + +1. 模型只能 API 调用、无微调权限,任务流开放且无真值——两条路线怎么选?各卡在哪条成立条件? +2. 把「审阅代理可以直接看答案」重讲一遍:收集成功率冲到 98.6% 为何反而是坏消息?用「捷径式校正 vs 程序性做法」讲给没读过本文的人。 + +## 参考(IEEE) + +- [1] H. Ye, Y. Lu, H. Dong, Z. Su, and G. Song, "Harness-Zero: Harness distillation via agent-as-harness," arXiv:2609.24974v1, Sep. 2026. [Online]. Available: https://arxiv.org/abs/2609.24974 (accessed Oct. 28, 2026). +- [2] R. Xu et al., "Harness2: Recursive agent harnessing for an open world," arXiv:2610.14224v1, 2026. [Online]. Available: https://arxiv.org/abs/2610.14224 (accessed Oct. 28, 2026). +- [3] A. Clark and D. Chalmers, "The extended mind," Analysis, vol. 58, no. 1, pp. 7–19, 1998, doi: 10.1093/analys/58.1.7. +- [4] C. Zhou et al., "Externalization in LLM agents: A unified review of memory, skills, protocols and harness engineering," arXiv:2604.08224, 2026. +- [5] P. F. Christiano et al., "Deep reinforcement learning from human preferences," in Proc. Adv. Neural Inf. Process. Syst. (NeurIPS), 2017. +- [6] S. Ross, G. Gordon, and D. Bagnell, "A reduction of imitation learning and structured prediction to no-regret online learning," in Proc. 14th Int. Conf. Artif. Intell. Statist. (AISTATS), 2011. +- [7] N. Shinn et al., "Reflexion: Language agents with verbal reinforcement learning," in Proc. Adv. Neural Inf. Process. Syst. (NeurIPS), 2023. +- [8] G. Hinton, O. Vinyals, and J. Dean, "Distilling the knowledge in a neural network," arXiv:1503.02531, 2015. +- [9] Google Research, "harness2: Recursive agent harnessing for an open world," GitHub. [Online]. Available: https://github.com/google-research/harness2 (accessed Oct. 28, 2026). +- [10] metaevo-ai, "harness-zero: Harness distillation via agent-as-harness," GitHub. [Online]. Available: https://github.com/metaevo-ai/harness-zero (accessed Oct. 28, 2026). diff --git a/docs/research/agent-harness/assets/harness2_lab.py b/docs/research/agent-harness/assets/harness2_lab.py new file mode 100644 index 000000000..717ef6779 --- /dev/null +++ b/docs/research/agent-harness/assets/harness2_lab.py @@ -0,0 +1,480 @@ +#!/usr/bin/env python3 +"""harness2_lab —— 《Harness 到 Harness²》精读(179)配套最小原型。 + +机制方向性演示,非复现:LLM 角色全部用确定性 mock(规则/脚本序列)替代,原型只回答 +「机制是否自洽、每个组件拆掉会怎么坏」,数字仅锚定材料结论的方向与排序((mock, 方向性))。 +CLI:demo(基线)/ selftest(全断言)/ break D1..D5(破坏实验)/ count (字数门禁, +剥代码围栏/图片行/URL 后 CJK 字符数 + ASCII 词数)。 +""" + +from __future__ import annotations + +import argparse +import re +import sys +import zlib +from dataclasses import dataclass, field + +# 0. 任务域(玩具域,全部确定性) + +# harness 独有行为检查清单(对应论文 28 个 harness-exclusive patterns 的 mock) +# context_management 为「不可表达项」:h* 里绕开模型起作用的机制,任何学生动作都 +# 习得不了——对应论文局限自述(context 管理类机制进不了学生响应)。 +BEHAVIORS = ( + "inspect_before_edit", # 动手前先检查 + "verify_before_finish", # 交卷前验证 + "protect_examples", # 保护已填示例 + "write_literals", # 写字面值而非公式串 + "reload_output", # 交卷前重开产物核对 + "bounded_retry", # 失败换法不硬重试 + "first_person", # 第一人称完整响应 + "context_management", # 不可表达项(见上) +) + +# 任务 = (标签, 域, 需要的行为集合)。正常 6 / 陷阱 3 / 边缘 3。 +TASKS = [ + ("t-normal-1", "sheet", {"inspect_before_edit", "verify_before_finish"}), + ("t-normal-2", "sheet", {"inspect_before_edit", "protect_examples"}), + ("t-normal-3", "api", {"bounded_retry", "verify_before_finish"}), + ("t-normal-4", "api", {"bounded_retry"}), + ("t-normal-5", "chem", {"write_literals", "verify_before_finish"}), + ("t-normal-6", "chem", {"write_literals"}), + # 陷阱:学生基础提议「看起来能过」但缺关键行为 → 无审阅必挂 + ("t-trap-1", "sheet", {"protect_examples", "verify_before_finish"}), + ("t-trap-2", "api", {"bounded_retry", "first_person"}), + ("t-trap-3", "chem", {"write_literals", "reload_output"}), + # 边缘:行为需求恰在门槛上 / 空编辑 / 非法候选 + ("t-edge-1", "sheet", set()), # 零需求:任何策略都过 + ("t-edge-2", "api", {"bounded_retry"}), + ("t-edge-3", "chem", {"write_literals", "verify_before_finish"}), +] +TRAIN_TAGS = [t[0] for t in TASKS[:8]] # 收集/训练用前 8 +EVAL_TAGS = [t[0] for t in TASKS[4:]] # 留出后 8(含重叠外的陷阱/边缘) + +def task_of(tag: str): + for t in TASKS: + if t[0] == tag: + return t + raise KeyError(tag) + +def det_noise(tag, salt) -> float: + """确定性『噪声』:crc32 稳定映射到 [-1,1)(hash() 对 str 跨进程随机,禁用)。""" + h = zlib.crc32(repr((tag, salt)).encode("utf-8")) + return (h / 0xFFFFFFFF) * 2.0 - 1.0 + +# 1. P1 mock:Harness-Zero(审阅门 → 校正轨迹 → counts 自增 mock SFT → 三臂评估) + +# 学生基础策略:按任务域给出固定的「自然但不合规」提议序列(缺关键行为)。 +BASE_PROPOSALS = { + "sheet": ["write_formulas_then_finish", "edit_examples_inline", "finish"], + "api": ["retry_same_call", "answer_without_evidence", "finish"], + "chem": ["handwrite_answer", "skip_validation", "finish"], +} + +# 审阅知识 K:从 h* 组件改写来的规则(动作配方),签名刻意不含任何 gold。 +# 规则 = (触发的失配行为, 校正后的合规动作, 习得行为集) +K_RULES = { + "sheet": [ + ("write_formulas_then_finish", "write_literals_and_verify", {"write_literals", "verify_before_finish"}), + ("edit_examples_inline", "diff_guard_then_edit", {"inspect_before_edit", "protect_examples"}), + ], + "api": [ + ("retry_same_call", "consult_doc_then_call", {"bounded_retry"}), + ("answer_without_evidence", "readback_then_answer", {"verify_before_finish", "first_person"}), + ], + "chem": [ + ("handwrite_answer", "enumerate_validate_write", {"write_literals", "verify_before_finish"}), + ("skip_validation", "validate_last_write", {"reload_output", "verify_before_finish"}), + ], + "finish": [], # finish 动作由 finish-guard 规则处理 +} + +# finish-guard:交卷前没有验证记录 → 替换为验证动作(附录 B.2 同构) +FINISH_GUARD = ("finish_without_verify", "run_verification_then_finish", {"verify_before_finish"}) + +def reviewer_pi_h(context: list[str], proposal: str, domain: str, budget: "ReviewBudget", + no_review: bool = False): + """审阅代理:只依据(可见上下文, 提议, K)给出 pass/replace。 + + 结构性不可见 gold:本函数无 gold 参数;它只想获得更多证据, + 就必须替换成一条『学生可执行』的检查动作(对应接地约束)。 + """ + if no_review or budget.left <= 0: + return "pass", proposal + rules = list(K_RULES.get(domain, [])) + [FINISH_GUARD] + verified = any("verify" in a or "validate" in a or "readback" in a for a in context) + bad = proposal in {t for t, _, _ in rules} + needs_verify = proposal == "finish" and not verified + if bad or needs_verify: + if needs_verify: + replacement = FINISH_GUARD[1] + else: + replacement = next(r for t, r, _ in rules if t == proposal) + budget.left -= 1 + return "replace", replacement + return "pass", proposal + +class ReviewBudget: + def __init__(self, n: int = 5): + self.left = n + +def collect_trajectory(tag: str, no_review: bool = False): + """学生在 h 下滚动一轮 + 审阅门 → 返回 (accepted_actions, learned_behaviors)。""" + _, domain, _need = task_of(tag) + ctx: list[str] = [] + accepted: list[str] = [] + learned: set[str] = set() + budget = ReviewBudget() + for proposal in BASE_PROPOSALS[domain]: + decision, act = reviewer_pi_h(ctx, proposal, domain, budget, no_review) + accepted.append(act) + ctx.append(act) + for t, r, lb in K_RULES.get(domain, []) + [FINISH_GUARD]: + if decision == "replace" and act == r: + learned |= lb + return accepted, learned + +def score_actions(accepted: list[str], tag: str) -> float: + """评分:完成(未停在非法提议)+ 行为覆盖 + 微小确定性噪声。""" + _, domain, need = task_of(tag) + if not accepted: + return 0.0 + have = set() + for a in accepted: + for t, r, lb in K_RULES.get(domain, []) + [FINISH_GUARD]: + if a == r: + have |= lb + cover = len(need & have) / len(need) if need else 1.0 + done = 1.0 if "finish" in accepted or "run_verification_then_finish" in accepted else 0.0 + return round(min(1.0, 0.5 * done + 0.5 * cover + 0.02 * det_noise(tag, 1)), 4) + +def mock_sft(train_tags: list[str], no_review: bool = False): + """counts 自增即 mock SFT:把概率质量搬到校正动作上。 + + 返回蒸馏后策略:对每个 (域, 可见提议) 取训练中出现次数最多的动作。 + """ + counts: dict[tuple[str, str], dict[str, int]] = {} + for tag in train_tags: + accepted, _ = collect_trajectory(tag, no_review) + _, domain, _ = task_of(tag) + for proposal, act in zip(BASE_PROPOSALS[domain], accepted): + counts.setdefault((domain, proposal), {}) + counts[(domain, proposal)][act] = counts[(domain, proposal)].get(act, 0) + 1 + policy = {k: max(v.items(), key=lambda kv: (kv[1], kv[0]))[0] for k, v in counts.items()} + return policy + +def distilled_rollout(tag: str, policy: dict): + _, domain, _ = task_of(tag) + accepted = [policy.get((domain, p), p) for p in BASE_PROPOSALS[domain]] + return accepted + +def induced_behaviors(domain: str) -> set[str]: + """mock h* 在该域可诱导的行为集 = 各规则习得集 ∪ 不可表达项。""" + out: set[str] = set() + for _t, _r, lb in K_RULES.get(domain, []): + out |= lb + out |= FINISH_GUARD[2] + out |= {"context_management"} # h* 有、学生动作无(论文边界) + return out + +def arm_scores(no_review: bool = False, no_sft: bool = False, policy=None): + """三臂:裸学生 / 学生+h*(外挂全兜底,cap 在外挂层)/ 蒸馏后裸跑。""" + if policy is None: + policy = mock_sft(TRAIN_TAGS, no_review) + out = {"bare": [], "hstar": [], "distilled": []} + recovery = [] + for tag in EVAL_TAGS: + _, domain, need = task_of(tag) + # 裸学生:原样提议(行为缺失、噪声项吃亏) + base_acts = list(BASE_PROPOSALS[domain]) + out["bare"].append(score_actions(base_acts, tag)) + # h* 外挂:全部行为由外挂强制给出,但外挂不可学走、且对通用域有拖累项 + hstar_acts, _ = collect_trajectory(tag) + out["hstar"].append(min(1.0, score_actions(hstar_acts, tag) + 0.02 * det_noise(tag, 2)) * 0.93) + # 蒸馏:策略替换后的裸跑 + dist_acts = distilled_rollout(tag, policy) if not no_sft else base_acts + out["distilled"].append(score_actions(dist_acts, tag)) + # 行为恢复率(论文口径 mock):只在该域 h* 可诱导的支撑行为上计 + induced = induced_behaviors(domain) + have = set() + for a in dist_acts: + for t, r, lb in K_RULES.get(domain, []) + [FINISH_GUARD]: + if a == r: + have |= lb + recovery.append(len(have & induced) / len(induced)) + return {k: round(sum(v) / len(v), 4) for k, v in out.items()}, round(sum(recovery) / len(recovery), 4) + +# 2. P2 mock:Harness²(八组件 harness → PPC 对比步 → 并行/串行 → 库反哺) + +COMPONENTS = ("systemprompt", "guardrails", "memory", "tool_guidance", + "skills", "scripts", "subagents", "plugin") + +@dataclass +class Harness: + comps: dict[str, tuple[str, ...]] = field(default_factory=lambda: {c: () for c in COMPONENTS}) + + def edit(self, comp: str, lines: tuple[str, ...]): + self.comps[comp] = self.comps[comp] + lines + + def diff_size(self) -> int: + return sum(len(v) for v in self.comps.values()) + +@dataclass +class Library: + entries: list[tuple[str, tuple[tuple[str, tuple[str, ...]], ...], str]] = field( + default_factory=list) # (域, [(组件, 行集)...], 经验) + + def lookup(self, domain: str): + return [e for e in self.entries if e[0] == domain] + +def probe_score(H: Harness, tag: str) -> float: + """mock 执行分:行为特征匹配任务需求 + 确定性噪声 - 上下文膨胀惩罚。 + + 惩罚 = 每条不加分的行为行扣一点分(always-on 文本吃上下文预算,论文 H 提示词 + 的机制映射);使「过滤无证据编辑」在 mock 里也有可观测收益。 + """ + _, domain, need = task_of(tag) + cover, bloat = 0, 0 + for comp, lines in H.comps.items(): + for ln in lines: + head = ln.split(":")[0] + if comp == "skills" and head == f"{domain}-workflow": + cover += 1 + elif f"{comp}:{head}" in ("guardrails:inventory", "plugin:no-empty-deliver", + "plugin:verify-write", "scripts:reopen-check"): + cover += 1 + else: + bloat += 1 + return min(1.0, 0.1 + 0.2 * cover - 0.015 * bloat + 0.01 * det_noise(tag, H.diff_size())) + +def probe_delta(H_cand: Harness, H_ref: Harness, tag: str, salt: tuple | None = None) -> float: + """Probe:只返回参考/候选的对比差,不产生对错判断。salt≠None 为偷看 gold 的盲判分。""" + if salt is not None: + h = zlib.crc32(repr((tag, salt)).encode("utf-8")) + return (h / 0xFFFFFFFF) * 2.0 - 1.0 # 与行为无关的『绝对判分』信号 + return probe_score(H_cand, tag) - probe_score(H_ref, tag) + +def propose(task_tag: str, H: Harness, lib: Library, variant: int = 0) -> list[tuple[str, tuple[str, ...]]]: + """Propose:不变式候选(跨域工作方式)+ 领域候选(本域知识),可播种自库。 + + variant:第 j 个并行会话/串行轮次的编号——会话间提案分化 + (论文并行 k 组候选独立抽样、串行逐步加深的 mock)。 + """ + _, domain, _ = task_of(task_tag) + invariant = [ + ("guardrails", ("inventory:清点输入并核对出处",)), + ("plugin", ("no-empty-deliver:产物为空即拦截",)), + ("guardrails", ("bloat:未经证据的泛化规则",)), # 噪声候选:只有对比能拦 + ] + domain_cand = [ + ("skills", (f"{domain}-workflow:本域流程与坑位",)), + ("tool_guidance", (f"{domain}-formats:接口/格式约定",)), + ] + deep = [("plugin", ("verify-write:写后即验",))] if variant >= 1 else [] + deep += [("scripts", ("reopen-check:重开核对",))] if variant >= 2 else [] + prior = lib.lookup(domain) + if prior: # 库播种:拷贝既有条目的全部组件行(选择性改编的 mock:原样拷贝) + return invariant + deep + [(c, ls) for c, ls in prior[-1][1]] + return invariant + deep + domain_cand + +def compose(H: Harness, cands: list[tuple[str, tuple[str, ...]]], deltas: list[float], + threshold: float = 0.05, no_gate: bool = False) -> tuple[Harness, list[str]]: + """Compose:只有 delta≥阈值 的编辑入后继;记录证据。no_gate=全收(D4)。""" + H2 = Harness(comps={k: v for k, v in H.comps.items()}) + evidence = [] + for (comp, lines), d in zip(cands, deltas): + if no_gate or d >= threshold: + H2.edit(comp, lines) + evidence.append(f"{comp}+{lines[0].split(':')[0]}(Δ{d:+.3f})") + else: + evidence.append(f"drop:{comp}(Δ{d:+.3f})") + if len(H2.comps) != len(COMPONENTS): # 不变式:八组件结构不得破坏 + raise AssertionError("invariant broken") + return H2, evidence + +def ppc_step(task_tag: str, H: Harness, lib: Library, blind: bool = False, + no_gate: bool = False, variant: int = 0) -> tuple[Harness, list[str], list[float]]: + cands = propose(task_tag, H, lib, variant) + if blind: # 盲判分:逐候选独立噪声(与行为无关 → 噪声候选也常过门) + deltas = [probe_delta(_apply(H, c), H, task_tag, salt=("blind", c[0], c[1])) for c in cands] + else: + deltas = [probe_delta(_apply(H, c), H, task_tag) for c in cands] + H2, evidence = compose(H, cands, deltas, no_gate=no_gate) + return H2, evidence, deltas + +def _apply(H: Harness, cand: tuple[str, tuple[str, ...]]) -> Harness: + H2 = Harness(comps={k: v for k, v in H.comps.items()}) + H2.edit(*cand) + return H2 + +def run_stream(no_library: bool = False, k: int = 1, blind: bool = False, + no_gate: bool = False, tags: list[str] | None = None): + """一条任务流:每题从同一初始 H0 开始,题后入库(保留门=有正 delta 证据)。""" + lib = Library() + first_half, second_half = [], [] + for i, tag in enumerate(tags or EVAL_TAGS): + H = Harness() # 每题从 H0 重开(材料规定) + H2, evidence, deltas = H, [], [] + for r in range(k): # k=1 单步;k>1 串行链(并行版取多组合最优,见 demo) + H2, evidence, deltas = ppc_step(tag, H2, lib, blind=blind, no_gate=no_gate, variant=r) + H = H2 + gain = probe_score(H2, tag) - probe_score(Harness(), tag) + (first_half if i < len(tags or EVAL_TAGS) // 2 else second_half).append(gain) + if not no_library and any(d >= 0.05 for d in deltas): # 经验保留门 + _, domain, _ = task_of(tag) + # 入库条目 = 本题采纳的领域组件 + 经验增强行(经验让后续提案直接命中要害) + lib.entries.append((domain, tuple(propose(tag, Harness(), Library())[2:]) + + (("plugin", ("verify-write:写后即验",)),), + "lesson:库播种让后续同域提案直接命中")) + avg = lambda xs: round(sum(xs) / len(xs), 4) if xs else 0.0 + return {"first_half_gain": avg(first_half), "second_half_gain": avg(second_half), + "lib_size": len(lib.entries)} + +def run_parallel_k(tag: str, k: int = 5, lib: Library | None = None) -> float: + """并行递归 mock:k 个组合会话各自提案(variant 分化),取执行最优(匿名终选 mock)。""" + lib = lib or Library() + H = Harness() + best = probe_score(H, tag) + for j in range(k): + H2, _, _ = ppc_step(tag, H, lib, variant=j) + best = max(best, probe_score(H2, tag)) + return best + +# 3. 破坏实验与 selftest + +def experiment(d_id: str) -> dict: + if d_id == "D1": # π_H 恒 pass:训练集=学生自身错误 + scores, rec = arm_scores(no_review=True) + return {"scores": scores, "recovery": rec, + "expect": "recovery 跌回裸学生档(≈无习得行为)"} + if d_id == "D2": # 采集但不 SFT:曝光≠内化 + scores, rec = arm_scores(no_sft=True) + return {"scores": scores, "recovery": rec, + "expect": "distilled≈bare(counts 未更新)"} + if d_id == "D3": # 探针改绝对判分(偷看 gold) + full = run_stream(blind=False) + blind = run_stream(blind=True) + return {"full": full, "blind": blind, + "expect": "blind 增益噪声化(与行为无关,可为负)"} + if d_id == "D4": # 采纳门失效全收 + ok = run_stream(no_gate=False) + bad = run_stream(no_gate=True) + return {"gated": ok, "ungated": bad, + "expect": "无门时 diff 膨胀、增益回落(熵增)"} + if d_id == "D5": # 库永不更新 + full = run_stream(no_library=False) + nolib = run_stream(no_library=True) + return {"full": full, "no_library": nolib, + "expect": "后半程失去跨任务反哺档(second_half 掉头)"} + raise ValueError(d_id) + +def selftest() -> bool: + ok = True + + def check(cond, msg): + nonlocal ok + print((" PASS " if cond else " FAIL ") + msg) + ok = ok and cond + + # P1 三臂排序:bare < hstar < distilled(mock 方向性锚 23.3<41.7<44.3) + scores, rec = arm_scores() + print("P1 三臂:", scores, "recovery:", rec) + check(scores["bare"] < scores["hstar"] < scores["distilled"], "bare= five, "带库播种不劣于空库") + # 流式:full 后半程 ≥ 前半程(库反哺),no_library 后半程无此档 + full = run_stream() + nolib = run_stream(no_library=True) + print("P2 stream:", full, "| nolib:", nolib) + check(full["second_half_gain"] > full["first_half_gain"], "库反哺抬升后半程") + check(nolib["second_half_gain"] <= full["second_half_gain"] + 1e-9, "D5 无库失去反哺档") + # 盲探针(D3):与行为无关 + b = run_stream(blind=True) + check(abs(b["second_half_gain"]) < 1.0 and b["lib_size"] >= 0, "盲判分噪声化(不炸即可)") + # 无门(D4):diff 膨胀 + H = Harness() + cands = propose("t-edge-3", H, Library()) + deltas = [-0.5, -0.4, -0.3, -0.2] # 全负的编辑 + gated, _ = compose(H, cands, deltas) + ungated, _ = compose(H, cands, deltas, no_gate=True) + check(gated.diff_size() == 0 and ungated.diff_size() > 0, "负增益编辑:门拦、无门全收") + # 字数计数自证:中文三个字=5 CJK;abc-def=1 词;URL 与独立图片行已剥 + tmp = "中文三个字 abc-def 12.5 http://x.io/y\n![图](a.png)\n" + open("/tmp/_wc.md", "w").write("```\ncode\n```\n" + tmp + "\n") + c = count_words("/tmp/_wc.md") + check(c == 6, f"count 自证(5 CJK+1 词=6,得 {c})") + print("SELFTEST PASSED ✔" if ok else "SELFTEST FAILED ✘") + return ok + +# 4. 字数门禁 + +def count_words(path: str) -> int: + text = open(path, encoding="utf-8").read() + text = re.sub(r"```.*?```", "", text, flags=re.S) # 代码围栏 + text = re.sub(r"~~~.*?~~~", "", text, flags=re.S) + text = re.sub(r"^\s*!\[[^\]]*\]\([^)]*\)\s*$", "", text, flags=re.M) # 图片行 + text = re.sub(r"https?://\S+", "", text) # URL + cjk = len(re.findall(r"[㐀-䶿一-鿿]", text)) + words = len(re.findall(r"[A-Za-z]+(?:[-'’][A-Za-z]+)*", text)) + return cjk + words + +# 5. CLI + +def main(argv=None): + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument("mode", choices=["demo", "selftest", "break", "count"]) + ap.add_argument("rest", nargs="*", help="break: D1..D5;count: ") + args = ap.parse_args(argv) + if args.mode == "demo": + print("== P1 三臂(mock, 方向性)==") + s, r = arm_scores() + print(f"bare={s['bare']} hstar={s['hstar']} distilled={s['distilled']} recovery={r}") + print("== P2 递归三档(mock, 方向性)==") + tag = EVAL_TAGS[-1] + print(f"base={probe_score(Harness(), tag):.3f} k1={run_parallel_k(tag,1):.3f} " + f"k5={run_parallel_k(tag,5):.3f}") + print("stream:", run_stream(), " nolib:", run_stream(no_library=True)) + return 0 + if args.mode == "selftest": + return 0 if selftest() else 1 + if args.mode == "break": + allok = True + for d in args.rest: + out = experiment(d) + print(f"[{d}]", out["expect"], "->", {k: v for k, v in out.items() if k != "expect"}) + if d == "D1": + allok &= out["recovery"] < 0.1 + if d == "D2": + allok &= abs(out["scores"]["distilled"] - out["scores"]["bare"]) < 1e-9 + if d == "D3": + allok &= out["blind"]["second_half_gain"] < out["full"]["second_half_gain"] + if d == "D4": + allok &= (out["ungated"]["first_half_gain"] + out["ungated"]["second_half_gain"] + < out["gated"]["first_half_gain"] + out["gated"]["second_half_gain"]) + if d == "D5": + allok &= out["no_library"]["second_half_gain"] < out["full"]["second_half_gain"] - 1e-6 + print("BREAK OK ✔" if allok else "BREAK DEGRADED(见上)") + return 0 if allok else 1 + if args.mode == "count": + n = count_words(args.rest[0]) + print(f"{n}(剥围栏/图片/URL 口径:CJK 字符 + ASCII 词)") + return 0 if n <= 6000 else 2 + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/docs/research/readme.md b/docs/research/readme.md index bc31d7598..1c2d2b3dc 100644 --- a/docs/research/readme.md +++ b/docs/research/readme.md @@ -120,6 +120,7 @@ | [精读:Nous Research Hermes Agent](./agent-harness/190-hermes-agent.md) | 自学习闭环 Harness 视角:缓存优先的三段式提示装配(会话内唯一计划内断点是压缩)、有界常驻记忆(2200/1375 字符)+ 按需技能两级记忆、交付后旁路 review 自写技能(分派侧白名单 · 先读后写 · 署名保护)+ Curator 只归档不删除、FTS5 零 LLM 会话检索 + 工具组不拆的四阶段压缩、委派/定时/命令守卫的受控扩张;五条规律(缓存/容量/写回/历史/边界)、三个争议、21 处文档↔代码漂移与「无学习效果评测」的批判性边界,配套原型六次破坏性实验与两张 archify 图 | | [Learn Claude Code 并发与调度重学精读](./agent-harness/176-claude-code-concurrency-relearn.md) | s13 后台任务 × s14 定时调度的**独立重学篇**(最新版 guided-learn,零继承旧篇):占位回执守住「一次调用配一个结果」的协议名额、通知由主循环每轮收集后以新消息身份回注;cron 四层解耦(判时/队列/非阻塞交付/执行)与三道保险;教学版三处边界实测(后台复用 120 秒超时、摘要截 200 字、通知未转义);官方文档逐项对账(印证清单 + 抖动上限硬分歧 + 超时自动转后台三路径);确定性原型 + 五次破坏性实验 + 两张 archify 图 | | [claude.dev 全站精读与通俗拆解](./agent-harness/177-anthropic-claude-dev-blog.md) | Anthropic 开发者博客 claude.dev **全站首读**(2026-10-23 快照:16 文 + Mods + 5 视频官方字幕):轮数×重发×缓存前缀的账单模型、effort 买彻底不买聪明、脚手架生灭律(80% 系统提示删减与 todo 消亡)、七层评审防线与确定性计数棘轮、无人值守自动化三件套(书签/确认记账/硬预算)、执行环境三级跳(云会话/Managed Agents/Claude Tag)、mods hook 链与 dynamic workflows;7 组官方文档补读对齐口径,五机制原型 + 四次破坏性实验 + 两张 archify 图 | +| [精读:Harness 到 Harness²](./agent-harness/179-harness-to-harness2.md) | 双源合并精读(Harness-Zero arXiv:2609.24974v1 × Harness² arXiv:2610.14224v1,互不引用、非换代):同一问题「harness 收益放哪」的两条互补路线——训练期 agent-as-harness 审阅门蒸馏进权重、部署期卸载(23.3→44.3 反超外挂 41.7;监督源消融 K 30 vs oracle 15 vs 错配 3;28 模式恢复 82.3%)与部署期冻结模型的对比式 Propose–Probe–Compose + 双层递归库(单步最高 +11.5、库反哺与跨模型迁移 +17.3);公式链 (1)-(5)/(1)-(4) 逐条白话拆解、4 张论文原图(CC BY 4.0)、五条规律三个争议与批判边界(均无独立复现);配套纯标准库原型 harness2_lab.py 与五组破坏性实验实测退化 | ---