三贤人 · tri-Sages
同一件事问两遍,它给你两个答案——而且不会告诉你。
DSH(DeepSeek Harness)的多智能体判决插件。三台人格单元各自独立判断、互不可见、必须选边;投赞成必须写出「什么观测会推翻我」;再按规则计票,并把每一票的理由与少数派的异议逐字留痕。
中文 | English · MIT · 零运行时依赖
它回答什么问题
让大模型帮你做决定,有三种结构性失败,而且都发生在不可逆的场合:
| 失败 | 长什么样 |
|---|
| 和稀泥 | 一份滴水不漏的两面话。读完你还在原地——信息增加了,决定没有 |
| 许愿机 | 顺着提问者的偏好给结论。你听到的是自己想听的 |
| 无法自证 | 同一个问题问两遍可能得到两个答案,而它不会告诉你「我这次不一样了」 |
三贤人把纪律写进机制,而不是写进提示词的好意:
| 痛点 | 做法 |
|---|
| 和稀泥:读完仍站在原地 | 必须选边——判决只有赞成/反对,没有弃权;落在判断域之外也要给判断,把把握写进保留意见 |
| 许愿机:给提问者想听的答案 | 赞成负举证责任——投赞成必须写出「什么观测会推翻我」;写不出,这一票由系统记为反对 |
| 单模型判断无法自证 | 三票一致 + 引擎自证——重大事项任一反对即否决;每条记录带引擎版本与人格哈希 |
| 结论不可复核 | 异议逐字存档——少数派的理由原样落盘,不进摘要、不可覆盖 |
| 僵局卡死,无人负责 | 降档要签字——只有最年长的那一台能被再问一次,由她签字改成多数决;权力转移必须留名 |
| 人格是黑盒,改不动 | 人格与契约是外部 Markdown——每次表决现读,改完下一次即生效,无需重启 |
三台是什么
| 单元 | 她是哪一份自我 | 她只问一个问题 |
|---|
| 少女 · 黄金 | 还没做过 | 这件事可能成立吗 |
| 成女 · 乳香 | 正在做 | 这件事办得成吗,代价谁付 |
| 熟女 · 没药 | 已经做过太多 | 三十年后还剩什么 |
三样礼物里只有黄金是给活人的——所以替「现在还活着的人」说话的那一台,天生是少数派。
每台还带一条自查,能把她自己刚写下的赞成翻成反对。熟女那条:「把时间尺度缩到一代人之内,这个判断还成立吗?」
安装
前置:DSH(@deepseek-ai/dsh)0.2.0-rc.2(清单里以 peerDependencies 声明)+ Node.js ≥ 20。
方式 A:本地挂载(推荐)
把本目录放进 profile,在 profile 的 cordis.patch.yml 里加:
- insert:
- id: tri-sages
name: ./tri-sages/index.mjs
config:
llmMode: live
方式 B:装成包
dsh plugin --profile <名> add <本目录路径>
装好后两种入口:
| 输入 | 作用 |
|---|
/sages 要不要把旧表删掉 | 跑一次表决(档位自动判断,命中敏感词自动升到重大) |
/sages critical 要不要现在就动手 | 强制按重大判:三票一致才过,任一反对即否决 |
/sages normal 中午吃什么 | 强制按日常判:多数决 |
/sages history | 翻账本(最近 10 次) |
/sages ts-000001 | 取回某一次完整记录(含三台原话) |
/sages personas | 看当前生效的三份人格 |
/sages help | 用法 |
若 / 菜单里没列出它,手打完整字符串即可(和 /permission、/cache-report 一样,命令是注册好的)。
模型侧直接调工具:
| 工具 | 用途 |
|---|
sages_vote(question, context?, criticality?, label?) | 发起表决。返回票数、判决、三份原话与账本 id |
sages_history(limit?, key?) | 翻账本;key 可按 id(ts-000003)或 label 取回某一次 |
sages_personas(action?, unit?) | 看当前生效的人格(sha256/字数);action:"text" 取全文 |
判决只有三种:APPROVED / REJECTED / VETO。三台全都没回话时是 ERROR——不伪造判决。
⚠️ 代码改动要重启;人格与契约改完即生效。 加载器的热重载只重跑 apply,不热换 ESM 模块。所以每条账本记录都带 pluginVersion、每份报告都打印 引擎:tri-sages vX.Y.Z——用来确认跑起来的到底是哪一版。
示例输出
以下取自真实账本(ts-000001,中文原文;本仓库已对私人称呼与绝对路径脱敏)。
这一条早于引擎版本自证(v0.2.0 起才有),所以没有 引擎: 那一行。
$ /sages critical 从今以后,AI 助手在做不可逆的大改动之前(删文件、改 profile 配置、
装卸插件、批量改写),是否必须先跑一次三贤人表决?
三贤人 · ts-000001 · 2026-10-16 15:07:45
档位:重大(命中敏感词:不可逆)
结果:否決 VETO · 0:3(未获一致)
① 少女 · 黄金 反对 conf 0.72
理由:这条路我没见过走通。不可逆没有清单,谁能触发没写,卡住超时怎么办没写,
靠自觉的规矩会滑成两种:天天跑,或没人跑。否决权是单向的——一台模型的
犹豫就能停一次回滚;三台又是同一套模型,错会一起错,三份判断换不来三份证据。
可推翻:出现已定义的不可逆清单、超时默认放行机制,并有真实拦下一次误操作的记录,我就改判。
保留:我愿意相信流程能约束人,这是希望不是证据,按自查改为反对。
② 成女 · 乳香 反对 conf 0.68
理由:闸门的触发条件由被判断者自己认定……真正挡住不可逆损害的是备份、回收站、
回退路径,这些机器查得到,模型的自评查不到。
保留:把触发条件换成外部固定清单(无备份的删除、凭据与 profile 写入、装卸插件),
并强制动手前写下回退路径与备份点,我改判赞成。
③ 熟女 · 没药 反对 conf 0.63
理由:判断者与被判断者同源,这一票给不出新信息,只给出一份可以引用的合法性。
「写不出推翻条件就反对」这条纪律值得留,它不必以表决为形。
降档:最年长的那一台拒签 → 否决维持
她的原话:0 比 3 不是僵局,是一致。我签字改的是规则本身:今天为「让它走完」
降一次档,明天任何被否决的事都能再拿来问我一遍。那道闸门回不去。
模型:deepseek-v4.1-flash(会话默认)
用时:49.8s
这套系统第一次表决,否掉的是它自己。 而且三台的理由互不相同:少女说「这条路没人走通」,成女说「真正拦得住的是备份,不是再想一遍」,熟女说「同源判断不产生新信息,只产生引用凭据」。
怎么读它的判决
票数不是概率,一致不是正确。 最容易读错的地方:
| 陷阱 | 说明 |
|---|
| 单次读数不是结论 | 逐字相同的输入曾给出不同票面(同题两跑:一次 2:1、一次 3:0)。把一次结果当判断用之前,先复跑 |
| 3:0 不等于「必然对」 | 它只等于「三份自我在这三条轴上没有分歧」。三条轴都偏保守,所以一致通过也可能是集体盲区 |
| confidence 不是把握度 | 那是那一台自己报的数,没有校准过;同一台在同一题上会在 0.56–0.86 之间漂 |
| 看报告顶部的 ⚠ | 有台没回话时,它那一票是系统代投的反对,不是它的判断(账本保留该台的原始返回) |
| 降档要看谁签的字 | 僵局被改成多数决,是最年长那一台签的;她的理由往往比判决本身更值得读 |
三条实用规则
- 看异议,不看票数。 一致通过说明不了什么;少数派的理由才是这套系统真正产出的东西。
- 只有重大事项才用
critical。 它要求三票一致、任一反对即否决;日常事用它只会得到一堆 VETO。
- 读 caveats。 那里装着每一台自己都不太信的部分——
保留 字段通常比 理由 更接近真相。
数据来源与隐私
表决时发出去什么:三台各自的 system prompt(人格 + 公共契约)+ 同一份「议题 + 背景」。没有会话历史、没有工具定义、没有文件内容——ctx.llm.stream 是一次性调用。
三台没有手:它们不能读写文件、不能执行命令、不能调用任何工具。它们只能说话。
账本:本机 JSONL,<DSH_HOME>/tri-sages/ledger.jsonl,追加写、不覆盖。含议题、三台原话、异议、人格与契约的 sha256、引擎版本。
不发:不上传账本、不连第三方服务、不读你的会话日志。除了那次模型调用,它不联网。
⚠️ 议题会进入模型调用——别把密钥、凭据原文写进议题里。
工程结构
| 路径 | 内容 |
|---|
index.mjs / command.mjs | 插件入口(三个工具)与斜杠命令入口 |
lib/ | 计票、人格装载、提示词组装、模型桥、输出解析、账本、呈现、离线桩、模块解析 |
personas/ | 三份人格 + 公共输出契约(外部 Markdown,每次表决现读) |
test/ | 54 项测试,含用宿主真实工具定义机制的挂载测试 |
tools/ | 补丁校验、模型探测 |
refs/ | 实验材料:答案集、实测报告、脱敏账本 |
局限(诚实说明)
- 三台共用同一套权重。 「独立」是人格层面的独立,不是参数层面的。这是本项目最重要的局限,也是下一步要解决的事(为三份自我各训练一个适配器)。
- 单次读数不是结论。 逐字相同的输入曾给出不同的票面;把一次结果当判断用之前,先复跑。
- 仪器会漂移。 同一个
provider/model 名可能被换成不同的后端。实测中曾出现输出契约违规率从 2% 升到 33%、延迟从 46–92 秒塌到 17–22 秒,据此把整轮实验判为作废。跨时间的对照,先验证「模型还是不是原来那个」。
- 失败按保守默认处理。 某一台没回话时,它那一票会被记为反对(安全优先)。报告顶部会写明
⚠ 已表态:N/3 台。
- 它不是法律或医疗意见。 洞穴奇案在这里是测量工具,不是要它判对。
- 实测是小样本。 6 个议题 × 3 轮 + 同题复跑,不足以宣称任何统计意义上的稳定性。
卸载
dsh plugin --profile <名> remove tri-sages
本地挂载的话,删掉 profile 的 cordis.patch.yml 里那条 insert 条目即可。
账本不会自动删——位置见配置项 ledgerDir(默认 <DSH_HOME>/tri-sages/)。
开发
npm run test:offline # 46 项,不需要 DSH 宿主(CI 跑这个)
npm test # 54 项,多出的 8 项用宿主真实工具接口把插件挂载起来
node tools/probe-model.mjs # 受控探测:绕开插件直连 provider,验证模型是否还遵守输出契约
test/plugin.test.mjs 是第一道防线:它证明插件真能挂上去(含「从 DSH 安装目录解析 @deepseek-ai/dsh-tools」这一步——本地挂载最容易死在这里)。
改动见 CHANGELOG.md;实验材料见 refs/。
License
MIT