KRouter

KRouter 详细说明

main 的当前状态(最新发布版 v1.3.0,2026-11-09):测过什么,没测过什么。 一行安装拿到的是最新发布版; CHANGELOG.md 里「Unreleased」下的改动只在 main 上。给评估 agent 的全部事实和出处: docs/FOR-AGENTS.md。

首页没写的都在这里:安装选项、什么会离开本机、证据、版本、夜间写手怎么工作、四个挂载、和常见 agent 记忆的对比。回到首页。

导入你已经有的东西

安装 —— 一行,什么都不用懂

curl -fsSL https://raw.githubusercontent.com/398894496-arch/KRouter/main/scripts/bootstrap.sh | sh

Windows(PowerShell,不需要管理员):

irm https://raw.githubusercontent.com/398894496-arch/KRouter/main/scripts/bootstrap.ps1 | iex

它会下载最新发布版(tag,永远不是 main),先按 release 里的 SHA256SUMS 核对 SHA-256,再在 文稿/第二大脑 建一座库(系统语言是中文就用中文模板),装好路由器和 agent 规则,并在 Obsidian 里打开这座库。默认到此为止:只装查询,什么都不问,没有内容离开本机。加 --ask 才会问要不要导入最近的 agent 会话、要不要装夜间任务,并用一句话说清:会用哪个 CLI、以什么权限运行,每晚会发出多少页、多少 token——数字来自在新库上的一次预演。没有终端可问就当不要;--timer、--import 表示事先同意。升级时保留你以前同意过的。想固定在某个版本:… | KROUTER_TAG=v1.3.0 sh(Windows 先设 $env:KROUTER_TAG)。已有的库(… | sh -s -- --vault ~/MyVault)一个文件都不动,只补缺失的骨架文件。同一行再跑一次就是升级。唯一的前提是 Python 3(Windows 脚本缺 Python 时会用 winget 自动装)。最后一行会告诉你还剩哪一步:登录一个 AI 编程工具,或者贴一个 API key。之后不需要维护任何东西——锁名词只是可选的快捷方式,不是前提;召回自己就能按页面标题和正文答,答不了就直说,不硬猜。哪天晚上的活没干成,会弹桌面通知说明原因。数据去向、CLI 写入器能看到什么:SECURITY.md。

什么会离开本机,要花多少

备份你的库

库的 git 历史(如果有)能撤回一次改坏,但扛不住硬盘坏了、电脑丢了,或者勒索软件把整个文件夹加密。要防这些,得有一份放在别处的副本,而且是真的恢复过的副本。backup.py 就做这件事;不给它指定文件夹,它就不运行。

python3 ~/.agents/skills/krouter-obsidian/scripts/backup.py init --dir "<一个会同步到别处的文件夹>"
# 把 ~/.dsh-krouter-keys.env 里的 KROUTER_BACKUP_PASSPHRASE 复制进密码管理器,然后:
python3 ~/.agents/skills/krouter-obsidian/scripts/backup.py saved

之后夜间任务每晚写一个备份包,并且先把它重新打开验一遍,验过了才算数。连续三天没有一次恢复成功,或者密码还只存在这台电脑上,status 都会说出来,你的 agent 也就会告诉你。为什么这样设计:

证据一览

证明什么 结果 怎么读
锁按协议写的工作 模板上 25/25 个主题、39/39 个别名、0 冲突 穷举,clone 下来可复现(CI)
锁对比近邻检索 TF-IDF、MiniLM、BGE-M3 会硬凑隔壁页的地方,锁会拒 冻结回放,可复现(CI)
召回宁可拒答也不硬猜 英文模板:离题和半离题拒答 12/12。中文模板:6/6 和 5/6,正确页排第一 9/12——清空别名表也一样 公开基准,可复现(CI)
真实流量(作者的库) 92 个真实路由查询盲评:0.62 → 1.47(满分 2,≤0.5.1 → 0.9.0) 开发集——剩余的失败就是在这些查询上逐条分析的。留出合成集上自 0.6 起持平(88% / 75% → 88% / 71%)。新查询攒够 50 条后再盲评(不早于 2026-10-20)
问答卡 同一批 92 条消融:看不出收益(±0.05) 等新查询的实测结果再定,可能改为默认关闭

方法、细节和还没解决的:docs/VERIFY.md。

稳定性与版本

1.x 遵循语义化版本。下面这些是稳定的,只在大版本里改,而且附迁移办法:库的目录结构和区名文件、别名表格式、agent 读的回执字段(retrieval_status、canonical_match、canonical_source、recall:、how、host_action)、各个路由、MCP 工具 krouter_ask / krouter_status、KROUTER_* 环境变量,以及导入器写的页面标记(source: krouter-import、source: krouter-claude-mem)。小版本可以加步骤和选项,也可以调打分;每次调打分都要在公开基准上附改动前后的数字(CONTRIBUTING.md)。新功能的小版本最多一周一个,修复类的补丁版本修好就发。一行安装取的是最新发布版,从不取 main;要固定在某个版本,见上面的 KROUTER_TAG。CHANGELOG.md 写明改了什么、为什么改,包括外部评审发现了什么。

你的 Agent 会忘。这套系统把它写下来。

聊天不是记忆。人和人要记的东西不一样,所以没有任何第二大脑会在 clone 里装着别人的笔记——这套也不会。你下载的是操作系统:骨架、路由、每天自动蒸馏的写入器。你的名词、项目、纠错,用过之后才长出来。

自动记住 = 每天封账、蒸馏,写进库里。 不是上一句下一轮立刻灌回去。五道门过了,当天自动写成准经验(provisional),不问。正式经验(active)下次同类任务再问你。

检索先试一道可选的别名锁(一个短名词 → 那一页 + 双 SHA-256);大多数问题对不上它,由排序召回来答。别名表不用维护:自带一份样例,只有想把某个短名词固定到某一页时才值得加一行。排序召回会——规则页优先,附一句为这个问题预先算好的 answer (generated):;库里没有一页覆盖得了,就给 recall: none。没有向量库要养。打不中那一页,进化就没发生。

flowchart LR
  L1[L1 封当天] --> L2[L2 蒸馏]
  L2 --> L3[L3 两步晋升]
  L3 --> L4[L4 夜间整合]
  L4 --> L5[L5 打到那一页]
层 做什么 不许做什么
L1 日志 05 一天一篇 把流水账当成可复用方法
L2 蒸馏 蒸馏。摘要不能代替原文 自动写成 active
L3 晋升 五道门过了 → 当天自动 provisional。下次同类先问。采纳且该次验收 → active 自动写成 active。门过了还不写准经验
L4 整合 夜间:反复出现的主题 → 一页带出处的主题档案;每个规则页/主题页 3–5 张问答卡;从路由器自己没答好的问题里学触发词;体检页列出失效项 照抄权威页、页面改了还用旧卡、编造说法、改动来源页
L5 锁 + 召回 短名词 → 那一页 + 双 SHA。未命中 → 在可重建的 FTS5 缓存上排序召回,附 answer (generated):;覆盖不足 → recall: none。进程内约 30 ms,每次命令行调用约 110 ms(python3,只用标准库) 向量回退、引用隔壁、猜

完整规则:PROTOCOL.md · docs/ARCHITECTURE.md · docs/VERIFY.md

证据细节(四层,不要混)

拆开写。总账:docs/VERIFY.md。

1. 实现正确性 — 代码做了协议写的那件事

对本仓 template/ 别名表穷举:25/25 主题、39/39 别名、0 冲突。这是查完表,不是抽样,也不证明「算法聪明」。

别名锁这一层的改写不变量:整句改写 25/25 不会触发别名锁(设计如此,不会把整句当 AND);列出的短名词 25/25 打到金标页。没触发别名锁的改写会继续走排序召回:在 200 道留出题上,120 道可答题答对 102 道,大多数和页面用词不同。这是实现正确性。这不是五次新会话 LLM 盲测。 template/ 是干净的最小样例——下限,不是私库的实际难度。

python3 tests/fixtures/clone_25/run.py
python3 -m pytest -q tests/test_clone_25.py

tests/fixtures/clone_25/。verify_canonical_map.py 验的是你的库,复现不了作者历史上的 26/26 · 156/156。

2. 对照优势 — 锁 vs 词法 TF-IDF、MiniLM、BGE-M3

四句话拆开。N=36(正命中 16、取代 4、近邻 4、负查询 12)。MiniLM 和 BGE-M3 做过和 tfidf_map 同一套余弦地板扫描。matches_lock = 正命中全对 且 负查询全拒 且 假近邻 0。

现场重放(python3 + rg):clone_25 和词法/TF-IDF 行。向量两行:带指纹的 JSON,不是「陌生人自己再跑一遍编码器」。

python3 tests/fixtures/lock_vs_neighbor/run.py
python3 -m pytest -q tests/test_lock_vs_neighbor.py

tests/fixtures/lock_vs_neighbor/ · docs/LOCK_VS_NEIGHBOR.md。不是 LongMemEval。

3. 实战自陈 — 不在本仓

作者活库 2026-08-21:连续封账 72 天;30 条真实任务;LLM 25/25;26/26 主题、156/156 别名。本仓不含验证材料。 不是回执。要量你的表,跑 python3 scripts/verify_canonical_map.py --map … --vault …。要数你的封账天数和缺口,跑 python3 scripts/verify_sealed_days.py --vault …。那不验证作者的 72 天。

4. 真实流量 — 不在本仓

前三层用的都是有人为测试写的题。这一层用的是作者的 agent 真实发给路由器的问题:30 天 Codex / Claude Code / Cursor 会话里去重后的 92 条(全部调用里一半是重复提问)。每条分别过旧路由和新路由,两份输出随机打乱成 X / Y,由 LLM 评判各打 0(没用)/ 1(相关但还得翻)/ 2(直接答到)。同样的输出重评,均分会有约 ±0.05 的波动,差距小于 0.1 当作噪声。

版本 改了什么 均分(满分 2) 直接答到 没用
≤ 0.5.1 锁 + 整句字面 grep 0.62 14 49
0.9.0 + L1 召回、范围扩大、自学习触发词、主题档案、问答卡 1.47 55 12

同一轮、同样 92 条。各版本两两对比和合成独立题:docs/VERIFY.md。

十五分钟 — 在自带 template 上拿到回执

这段只证明锁能在本仓 template/ 上打到 Q01,不是在你已有的库上。不蒸馏昨天。不需要 GPU、Docker、嵌入进程。first_run.sh 故意不继承 OBSIDIAN_VAULT;要换一棵树,设 KROUTER_FIRST_RUN_VAULT。

git clone https://github.com/398894496-arch/KRouter.git
cd KRouter
python3 -m venv .venv && . .venv/bin/activate
python3 -m pip install -r requirements.txt
./scripts/first_run.sh

每次路由都给回执,调用方能分清「权威」和「猜的」:

retrieval_status: canonical-match
canonical_source: /YourVault/Agent第二大脑.md
canonical_id: Q01
source_verified_at: 2026-01-01
source_sha256: d8c1d5af…
canonical_map_sha256: c55b8715…
canonical_match: true

CI 每次 push 跑 pytest(含 clone_25、lock-vs-neighbor、召回基准、封账天数)、这支脚本、DSH 桥。查询时不联网;夜间步骤会把页面发给你的模型(见文末要告诉宿主的事)。

未命中就是未命中:canonical_match: false 加提示。suggest homz 只给提示,不是命中。换一个名词,或者往别名表加一行——就是你库里的 90 系统文件/canonical_sources.psv:

Q11|deploy;deployment;怎么发版|02 经验与方法/发布/发布流程.md|只从 main 发

打开每天的写入器

这就是产品。install.sh 会装上夜间任务(KROUTER_NO_TIMER=1 跳过);一行安装默认不装,--ask 时先问你。

把 template/ 拷到你的库,然后:

export OBSIDIAN_VAULT=/path/to/YourVault
./scripts/install.sh            # 以后升级:./scripts/install.sh --upgrade · 卸载:./scripts/uninstall.sh

别名表是你的,放在库里(90 系统文件/canonical_sources.psv),跟着库同步,升级不会动它;安装只在第一次放进十个样例名词,之后再也不碰。开始写自己的名词时,python3 ~/.agents/skills/krouter-obsidian/scripts/propose_aliases.py 会从你的库里起草候选,写到 90 系统文件/自动化/别名候选.md——勾上要的行,再加 --apply 运行。没勾的一行都不会进表。建议固定在某个发布 tag,不要直接跟 main。

先 API key: key 只存在 ~/.dsh-krouter-keys.env(权限 600),永不留在库里。贴在 90 系统文件/自动化/自进化钥匙.md 也行——下一次运行会把它挪进那个文件,页面上留一句说明——因为库里的东西 CLI 写入器读得到,库同步到哪儿它就跟到哪儿。写入器锁定该家旗舰模型,蒸馏并写准经验。

没有 key: 用已经登录的 CLI 做同一件事——grok、官方 Codex、claude、cursor-agent、opencode、kimi、pi、vibe、antigravity,夜间步骤认的是同一份名单。没有第二份 env。不要用 PATH 上的 agent。文件:extras/host-daily-evolution/。

装到 ~/.agents/skills/krouter-obsidian、~/.cursor/rules/krouter-obsidian.mdc、~/.cursor/rules/ask-product.mdc。Cursor 规则先跑 status,收据里有 host_action 必须告诉宿主。若 ~/.agents/skills/krouter-obsidian 已在,不带 --upgrade(与 --force 相同)会 exit 1;两者都只换代码,别名表、台账和软链原样保留。uninstall.sh 删掉定时器、Cursor 规则、hook 和 skill,别名表还没进库的先救进库,库本身不动(先用 --dry-run 看;--purge 另外清掉可重建的缓存和查询日志)。不会覆盖正在用的 obsidian-knowledge-router。定时器钉死本仓库的 krouter-obsidian。问的匹配器是 L3:一句最多一条准经验;record 不写 active;采纳且该次验收后 promote 才升正式。触发词是你自己的,写在准经验页或 ask-triggers.json。Codex / Claude 仍要贴 extras/codex/AGENTS.snippet.md。

本机已登录 CLI 时的订阅通道:grok 在内核沙箱 krouter 里运行(只碰知识库和路由器),claude 用 --permission-mode dontAsk 加白名单(知识库和路由器),Codex exec --sandbox workspace-write。见 SECURITY.md。

什么情况不该装

四个挂载,一座库

共享的是库——别名表就在库里——不是第二套协议。Windows 走 route_knowledge.py(同一套路由);DSH 在 win32 上优先用它。

挂载 仓库里有什么
Cursor install.sh → extras/cursor/krouter-obsidian.mdc
Codex extras/codex/AGENTS.snippet.md
Claude Code extras/claude-code/CLAUDE.snippet.md
DeepSeek Harness DSH 插座。克隆后:dsh plugin add /path/to/this/repo。目录:dsh plugin --profile web add github:398894496-arch/KRouter。只读工具,含 correction;memory 是库内路由,不是聊天记忆。卸插件不删库
node extras/dsh/test-bridge.mjs
dsh plugin --profile web add github:398894496-arch/KRouter

需要 python3、rg、PyYAML。测试:python3 -m pip install -r requirements-dev.txt && python3 -m pytest -q。

锁之后:召回、主题档案、问答卡、夜间维护

锁仍然单独裁决——只有 canonical_sources.psv 里的行能认领一页,来源被标成 superseded / retired / rejected 就失效。下面这些只负责排序、拒答,或写 provisional 的机器页。

日更封账后,自带定时器运行 nightly.py:compile_subconscious.py → reconsolidate.py → consolidate_topics.py → answer_cards.py → checkup.py。每步独立,都不改变封账本身的退出码;KROUTER_NIGHTLY=0 关掉。每一步的结果——跑了、跳过、部分失败还是失败,原因,走的哪条模型通道,调了几次、发出去多少字——写进 90 系统文件/自动化/夜间维护.md 和健康页;status 会读出来,步骤被跳过、失败或三天没跑时打印 host_action。需要模型的步骤和写入器走同一条通道:厂商表、旗舰锁、CLI 名单都只有一份,在 llm.py,写入器从这里导入。先 *_API_KEY,顺序与写入器相同(DeepSeek、OpenAI、Anthropic……Gemini),模型取 KROUTER_LEARN_MODEL,否则取厂商模型目录里的旗舰;再用写入器会选的那个 CLI;KROUTER_LEARN_CLI 是宿主特意指定的 CLI,排第一。checkup.py 还会列出过期、对不上原文、问题离页、未经核对、问题过宽的问答卡。测试:tests/test_recall_index.py、tests/test_api_lane.py、tests/test_install_nightly.py、tests/test_zones.py、tests/test_recall_bench.py。

不是 Mem0,不是笔记软件

clone 时是操作系统;两周后装着你封的日子、你的名词、你采纳的方法

  这套操作系统 常见 Agent 记忆
clone 里有什么 协议 + 骨架 + 路由 + 写入器 同样是空仓库
过完好的一天 蒸馏;五道门过了当天自动 provisional;下次先问 → 可能 active 把会话压缩了下次灌进提示词
过完一次纠错 改权威页。下次必须打开它 重新嵌入,盼着旧块自己烂掉
怎么找到那一页 按词排序召回,覆盖不足就拒答;可选的别名锁能把短名词固定到某一页 语义近邻
一个主题反复出现好几周 夜间整合成一页带出处的主题档案 碎片散在各个会话里
同一个问题又问一遍 确定地给同一页和它的 how;有合适的核对过的问答卡就附上 重新检索、重新读
你要养什么 你的名词和主题清单。没有向量库 索引、同步、注入、过期

想要把整段聊天自动灌进下一轮(装了 Claude Code 插件后,新会话会带上这个仓库最多 8 条记下的决定,不是聊天本身)、云记忆 API、或语义近邻,跳过。见 什么情况不该装。