内容
<p align="center">
<img src="assets/knoten.png" alt="knoten" width="360">
</p>
<p align="center">
<b>一个记住哪些方法不奏效的研究图表。</b>
</p>
每个想法都是一个markdown文件,存放在git中,标记为 **存活**、**死亡** 或 **撤回**。如果某个想法死亡,节点会记录死亡原因、可以使其复活的条件以及重现该结果的代码。
## 工作原理
图表是一个文件夹,节点是一个markdown文件:**机器的前置信息,人类的说明,重现结果的代码**。
````markdown
---
id: hyp-self-consistency
type: hypothesis
status: dead
links:
- {rel: kn:killedByGate, to: method-compute-matched-baseline}
repro:
script: experiments/self_consistency.py
model: Qwen3-8B-Instruct
data: GSM8K test, 1319 questions
cmd: python experiments/self_consistency.py --n 5 --temp 0.7
results:
acc_greedy: 0.741
acc_self_consistency: 0.792
acc_compute_matched_baseline: 0.788
tokens_per_question: 1420
n_independent: 1319
---
# 自我一致性(采样5次,多数投票)优于贪婪解码
## 判决:死亡
采样5次并取多数票得分为79.2%,而贪婪解码为74.1%。+5.1分。
看起来像是一个免费的胜利。
## 为什么它死了
它不是免费的。它消耗的**5倍令牌**,而在相同的预算下,更长的CoT基线达到**78.8%**。整个增益来自计算,而不是方法。
```python
# 重现死亡:
python experiments/self_consistency.py --n 5 --compare compute_matched
```
## 什么会使其复活
一个任务,其中多数投票聚合确实起作用,即增益在计算匹配的基线中幸存下来。适用于代码执行或定理证明。GSM8K不是这样的任务。
````
三个月后,当有人再次提出自我一致性时:
```
$ knoten query "self-consistency"
[✗ DEAD] hyp-self-consistency
killed by : method-compute-matched-baseline
reopen if : A task where the majority-vote aggregation does real work, i.e.
where the gain survives a compute-matched baseline…
```
## 使用方法
```bash
pip install -e . # 添加".[mcp]"以启用代理服务器
knoten init my-topic # 创建一个新的图表(它是一个文件夹)
knoten new hypothesis hyp-idea # 搭建一个节点,包含所有必需的信息
knoten query <term> # 这个方法是否已经被尝试过?
knoten show <node> # 查看节点、结果和附件
knoten attach <node> <file>... # 附加脚本、绘图或笔记本
knoten detach <node> <file>
knoten validate # 强制执行图表的规则
knoten path A B # 如何从A到B?
knoten hook # 使`git commit`拒绝损坏的图表
```
每个图表在`graph.yaml`中声明自己的规则。`knoten`不知道您的领域,它强制执行**您**指定的规则。示例图表要求每个声明报告`tokens_per_question`并至少基于30个独立问题;其他主题可能需要完全不同的规则。
```yaml
rules:
- id: underpowered
when_type: hypothesis
require_result_min: {n_independent: 30}
message: 少于30个独立问题的结果是噪音,而不是证据。
```
您的图表还声明了自己的词汇,并且也会强制执行这些词汇:
```yaml
node_types: [hypothesis, experiment, finding, method, source]
statuses: [open, alive, dead, retracted, superseded, active]
```
`type: hypthesis`是一个输入错误,而不是新类型。`status: ded`比错误更糟糕 - 它会悄悄地从每个查询中删除声明,这正是此工具旨在防止的悄悄腐烂。
规则键或配置键如果`knoten`不认识,则会**硬错误**,而不是忽略。强制执行无效的配置是装饰,而无效的规则比没有规则更糟糕,因为您认为自己已经有保障了。
`knoten new`读取这些规则并预填充它们要求的内容 - 除了`scaffold`之外的所有内容都是`knoten`的意见,而是您的图表的意见。值故意为`TODO`,因此`new` + `validate`是一个检查清单,而不是猜测游戏:
```
$ knoten new hypothesis hyp-my-idea --status dead
+ nodes/hyp-my-idea.md (hypothesis, dead)
预填充了本图表规则所需的内容:
## 为什么它死了,## 什么会使其复活,tokens_per_question, n_independent
```
此工具旨在防止的失败是由**摩擦**引起的,因此编写路径是最容易受到摩擦影响的地方。编写说明,而不是您必须被拒绝才能发现的冗余信息。
## 网关是一个git钩子
```bash
knoten hook # 在`git init`之后
```
`git commit`现在运行`knoten validate`并**拒绝违反图表规则的图表**:
```
$ git commit -m "self-consistency is a win"
✗ hyp-self-consistency
[live-claims-must-cite-their-gates] 未挑战的声明不是发现,而是希望。
1 violation(s) — commit REJECTED
```
只有在您记得询问时才会触发的规则是让上一次尝试失败的规则。请将其放在您无法走过的地方。(`git commit --no-verify`会绕过它 - 您应该有理由这样做。)
## 附加代码和绘图
节点不仅仅是一个声明。它包含您需要重新运行它所需的内容。
```bash
knoten attach hyp-self-consistency experiments/self_consistency.py accuracy_vs_budget.png
```
文件被复制到`attachments/<node-id>/`,在frontmatter中列出,图像**嵌入在节点正文中**,以便在GitHub上呈现:
```
attachments/hyp-self-consistency/
self_consistency.py 杀死它的脚本
accuracy_vs_budget.png 显示原因的绘图
```
然后,如果节点列出的附件不存在,`knoten validate`会失败。损坏的重现是损坏的节点。
```bash
knoten show hyp-self-consistency # 边缘,结果,附件
knoten detach hyp-self-consistency accuracy_vs_budget.png
```
## 两个读者,一个文件
**人类**浏览说明并获取故事:尝试了什么,什么杀死了它,什么仍然开放。无需数据库,无需UI,只需markdown,您可以在任何编辑器或GitHub上阅读。
**代理**遍历frontmatter:类型边缘(`kn:killedByGate`,`kn:survivedGate`),结构化`results`,带有确切脚本/模型/数据/命令的`repro`块,以及任何附加脚本和绘图的路径,它们可以直接读取和重运行。代理回答“这是否已经尝试过?”和“如何重现它?”无需阅读一个字。
同一个文件为两者服务。这就是整个设计。
## 面向编码代理(MCP)
将Claude Code或任何MCP客户端指向图表。然后,它**在会话之间累积关于某个主题的知识**,而不是每次都从头开始:
```bash
pip install -e ".[mcp]"
```
```jsonc
{"mcpServers": {"knoten": {
"command": "knoten-mcp",
"env": {"KNOTEN_GRAPH": "/path/to/llm-research"}
}}}
```
```
knoten_query("has anyone tried self-consistency?") ← 在它开始工作之前
knoten_get("hyp-self-consistency") ← 完整的节点,包括事后总结
knoten_commit(node) ← 在完成后,成功或失败
knoten_attach(node, [script, plot]) ← 以及证明它的代码
knoten_path(a, b) ← 如何从A到B?
knoten_validate() ← 运行图表自己的规则
```
代理在运行实验之前读取图表,并在完成后写入,包括实验失败时。带有死亡原因记录的死亡假设是最有价值的节点,否则会丢失。
它还写入证据,而不仅仅是说明:`knoten_attach`将运行的脚本和生成的绘图放入节点。无法重现的声明是不可信的声明——所以杀死假设的代理留下杀死它的东西,准备好让下一个代理运行。
`knoten_commit` **在写入之前进行验证,如果违反规则则拒绝** - 候选节点被解析并在内存中检查,因此无效节点永远不会到达您的文件系统。代理无法记录一个漂亮的结果,却没有它所通过的测试:
```json
{"status": "REJECTED",
"violations": [{"rule": "live-claims-must-cite-their-gates",
"message": "未挑战的声明不是发现,而是希望."}]}
```
## 为什么要这样做
**您不再会重复已经运行并忘记的实验。** 死亡的尽头会带着死亡原因和重现命令一起返回。
**而且您不容易自欺欺人:** 声明只有在引用它所通过的测试时,才能标记为**存活**,因此一个好看的结果如果从未被检查,就不能悄悄地成为发现。
**而且一个损坏的节点是一个响亮的失败,而不是悄悄的。** 不可读的前置信息,未知的边缘关系(`kn:killdByGate` - 漏掉一个字母),不存在的规则键:所有这些都是错误。悄悄地忽略无法解析的内容的图表报告自己是健康的,但它正在腐烂。
**而且有人后来说撤回的声明确实如此。** `query`从双方都显示撤回:
```
[✓ ALIVE] hyp-few-shot-format
survived : method-compute-matched-baseline
RETRACTED by : ret-oops
```
参见`examples/llm-research/`以获取一个完整的图表,并参见[SPEC.md](SPEC.md)以获取设计文档。
MIT。 一个依赖(PyYAML)。 整个项目只有几行代码,您可以一行一行地读懂。