Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

Socrates

Tangyi QianTangyi Qian474 downloads

Highlight a passage in your notes and question it through a local sidecar. Desktop only.

Add to Obsidian
Socrates screenshot
Socrates screenshot
  • Overview
  • Scorecard
  • Updates35

紫色渐变卡片:左边是用 . : s A 3 G & @ 这套密度字符拼出的苏格拉底半身像,右边是 SOCRATES 字标、标语「苏格拉底学习法」和副题 Socrates-agent

演示:在笔记里划中一段,点 Use selection,苏格拉底侧栏开始追问。

苏格拉底学习法,深度学习任何一本教材

中文 · English


在 Obsidian 里划中一段,这个插件让你践行苏格拉底学习法。践行它意味着 下面两件事。

你可以不断追问。 你尽管问这本书。疑问会被当场解答,还可以写回你的笔记, 不会丢掉。只要你想,任何一个知识点都能吃透。

苏格拉底式提问。 它反过来不断问你,对着你刚划中的那段,把还没想清楚的 地方问出来,让你对这个知识点的理解再往下压一层。

目录

为什么需要它 · 它到底怎么用 · 核心功能逐个上例子 · 系统设计 · 装 · 用 · 隐私 · 开发与测试 · Future Works · 最近的版本


1 · 为什么需要它

苏格拉底是一个 Obsidian 插件。装上之后,你在笔记正文里划中一段,右边侧栏就以这一段为 话题跟你聊下去;聊出来的结论,它可以写回原文那一段。它只认真对待一件事:一个人啃一本 长手册,书很厚,作者不在场,读者只有你自己。收集灵感、润色文章这些它不做。

这件事的起点是一本 13083 行、626 KB 的技术手册,一个人写的,也只有一个人在读。 这种书跳着看没有意义:每一关都压在上一关的结论上,第 7 关里一句「所以这里必须先 read」, 理由埋在第 2 关某个决策的第三层里。真正折磨人的从来不是看不懂,而是卡住的那一刻 没人可问。

通用聊天机器人补不上这个位置。它没读过你这本书,你贴一段进去,它给的是一段四平八稳的 解释,正确,但和你手里这本书没有关系。它不知道这个概念在第 2 关是怎么铺垫的,不知道 作者在第 4 关的决策②里已经否掉过一个更朴素的做法,也不知道你三分钟前才刚问过一个 几乎一样的问题。

要把这个位置补上,这个插件跟的是苏格拉底学习法。苏格拉底几乎不讲课:他坐在 对方旁边,针对对方刚说的、刚读到的那一句追问,直到对方自己看见自己没想清楚的 地方。他不给答案,答案是被问出来的。你以为自己跟上了,一问就知道没有;你不必 先组织一整段讲解,只要接住那一个问题,问题本身已经圈定了该想哪一块。

更常被拿来自学的是费曼学习法。它的做法是:挑一个概念,用自己的话讲给一个 假想的外行听;讲不下去的地方就是没懂的地方,回去补,再讲一遍。它靠的是输出—— 你得自己开口讲。懂了八成之后拿它查漏,很管用。但它有一个入口:你已经能开始讲。

啃长手册最难受的时刻,恰恰卡在这个入口之前。材料刚铺到一半,上一关的结论还没在 脑子里站稳,你甚至不知道该拿哪一块去「讲给别人听」。空白纸不会先问你一句。费曼法 你自己就能做,一张纸就够;苏格拉底法一直缺的是那个坐在旁边的人。对一本关关相扣 的教材来说,你缺的不是讲台,是那个在你停下的地方问一句的人。这一点费曼法够不着: 卡住的那一刻就能用得上,不必等自己先变成老师。

所以它全部的设计都从一句话长出来:让一个真读过这本书、而且知道你读到哪儿了的人, 坐在你旁边。既然是坐在你旁边的人,默认动作就不该是把答案端上来。默认那枚芯片叫 socratic,职责是先别揭晓、反过来问你一个问题——一个默认反问的学习工具和一个默认给 答案的学习工具是两种东西,后者替你想完了,前者逼你自己先想一遍。

另外两件事它不靠提示词自觉,靠代码兜住。模型想改你笔记里的任何一段,必须在更早的 一轮里真的读过那个文件,这笔账由执行层记,声称读过不算数。会话、快照、深挖账本则全在 你自己机器上的本地目录里,仓库里没有任何埋点。出网的是发给你在设置里填的那个模型节点、 插件升级后重新拉起服务时取一份新 sidecar,以及模型调用 fetch 时向那个 URL 发的 GET (只接受公网 http/https)。前两条各自拦在哪一行,第 4 章有逐条的实现。

下面所有例子跑的都是另一本书:仓库 docs/demo/ 里那本 1405 行的 《从零手写 DQN · 强化学习通关手册》。它随仓公开,你可以导进自己的库把后面每一段对话 重跑一遍——这份 README 不打算让你只看着截图相信。


2 · 30 秒看明白它干什么

一次完整的用法是五步,全都发生在你那篇笔记和右边那条侧栏之间:不用离开 Obsidian,不用 开终端,也不用先把整本书喂给谁。前四步只是读和问,只有最后一步会碰你的磁盘,而且必须 你亲手点头它才碰。

  1. 在笔记里划中一段。
  2. 打开侧栏点「用当前选区」(命令面板里有同名命令),再点一枚芯片(先别揭晓 / 当我零基础 / 只举例子),或者直接打字问。
  3. 他先读你的笔记,再回答你,或者反过来问你一个问题。
  4. 与此同时,后台另起一条线(下面叫「深挖 ◆」)去读同一本书的别处,攒几个更深的问题 存进池子,每轮最多放一条出来抛给你。
  5. 想把解答留在笔记里,他会提议一处编辑;你点「允许」,磁盘上才会动。

Obsidian 窗口左右分屏:左边是《从零手写DQN》的正文,第二拍里有一段被划中并高亮;右边是苏格拉底侧栏,正在就那一段来回追问,底部挂着一条带 ◆ 的深挖问题。

这一节和下一节的界面图都是真跑出来的,没有摆拍。界面语言跟随 Obsidian,图里是中文界面。 状态行上那句「开发回退 DEEPSEEK_API_KEY」是从源码树跑才有的字样——你正常安装之后, 那里显示的是你在设置页填的那个节点。

它不是对任意笔记都一样好用。 主对话对任何 Markdown 都能跑;但后台深挖要在书里下锚, 需要教材按八拍体例写,每一关得有「第三拍 · 出身」「第七拍 · 实操代码」这样的小节。少了 那些小节,五条深挖轴会直接死掉一条,其余四条照常出题。 docs/demo/从零手写DQN.md 是一份可以照抄的样板,为什么非得是 这个体例,见 4.9 教材无关。


3 · 核心功能逐个上例子

场景:你在读《从零手写 DQN》的 Level 3,划中了第四拍的决策① 「为什么非要两个网络—— 一个冻着、一个在更新」(第 954–964 行)。这一段把答案拆成了三层:数学、动力学、工程。

以下所有回答都来自 deepseek/deepseek-v4-flash(经 OpenRouter 节点), 跑在一个隔离的 sidecar(插件在你本机拉起的那个 Python 小服务)上。 换任何一个 OpenAI 兼容的 Chat Completions 端点都能跑——但除这一个组合之外我没实测过。

这一章每一段输出都是真跑出来的:原始请求体和 SSE 事件流全存在 docs/demo/transcripts/ 里,每处引文下面都挂着对应的 JSON。 落盘之后只动过一件事——把采集环境的临时绝对路径换成 /Users/you/…,除此之外一个字符 没改(说明)。唯一没随仓公开的是 3.7 那两段,它们出自作者本机的旧会话,里面全是私人 vault 路径, 那一节的落款自己写着这件事。

3.1 · 先别揭晓 socratic

默认那一枚。 它读你划的那段,然后不回答——它去找那段话里你还没意识到的裂缝。

侧栏里点了「先别揭晓,问我一个问题」之后的回答:它把两个更新式并排摆出来,指出区别不在步长而在「记不记得旧账」,最后反过来问读者哪一个更接近它真正想要的。

你:(划中决策①,点「先别揭晓」,一个字没打)

苏格拉底:

好,你刚读完了决策①的三层拆法。那一块其实已经把“为什么冻住”讲透了——但有一个裂缝你可能注意到了,也可能没注意到。

手册说冻住目标之后,这就变回了一个“标准的监督回归问题”。好,那我问你:

监督回归里,标签得是 ground truth 吧?可 Q_target 还是自己估计出来的——它又不是上帝给的正确答案。那“变回标准监督回归”这个说法,是不是藏了一笔账没算?这笔账谁来还?

原文:03-chat-socratic.json 10.6 秒

手册里那句「变回标准监督回归」确实滑过了一件事:监督回归的标签是给定的, 而这里的标签是自己估的。

为什么默认是这一枚:一个学习工具,如果默认动作是「把答案给你」, 那它每被用一次,你就少想一次。默认动作是「问你一个问题」,成本完全不同。

3.2 · 当我零基础 explain_zero

同一段,换一枚芯片,形状完全变了:TL;DR → (a) 概念对比 → (b) 机制 → (c) 反例 → 两个能跑的例子。

展开真实回答(1423 字,30 秒)

TL;DR

冻住目标网络 = 把 RL 的移动靶子钉在墙上,让它变回普通回归。 在线网络每步更新,目标网络每 C 步才被同步一次。两次同步之间,损失函数里的目标是常数,半梯度变成了真梯度。

(a) 概念/对比:在动 vs 冻住

不冻(Level 2 的表格 / 函数逼近) 冻住(DQN)
目标里有 θ? 有,损失一更新目标也跟着变 没有,C 步之内目标不变
这是什么问题 非定常目标回归(半梯度) 标准监督回归(真梯度)
收敛风险 正反馈环路→发散 环路被切断,只每 C 步接通一瞬间

(c) 反例:C = 1 时就是白冻了

如果你让 C = 1(每更新一步就同步一次),那目标网络永远和在线网络一模一样——冻住了个寂寞。你退回到了 2013 年那版 DQN,震不减、环没断,烧着显卡和钱,跟没冻一样。

两个可运行例子

都在第七拍的 train() 函数里,用同一个函数体、不同参数跑:

例子 1:标准 DQN(C = 200)

# 第七拍里就是这样调的
returns = train(episodes=400, sync_every=200)

sync_every=200 就是 C。在线网络每更新 200 次,才把权重抄一份给 target_net。这 200 步里,目标是死的,梯度是准的。跑完能看到 return 曲线一路上扬。

例子 2:Double DQN(只改一个参数)

# 同一份代码,打开 double=True
returns = train(episodes=400, sync_every=200, double=True)

手册里 double 参数写死了——它只在计算 TD target 时多改了一行:选动作用在线网络,估值用目标网络。你可以对比这两条曲线,看看解耦 selection 和 evaluation 之后,是不是更稳了。

原文:04-chat-explain-zero.json

这里有一条约束值得单拿出来说。 explain_zero 的 prompt 里写着:例子的名字 必须对得上该 Level 第七拍里真出现过的东西,不许自己造。核对一下它给的四个名字:

它写的 教材里 位置
train() ✅ docs/demo/从零手写DQN.md:1223
sync_every=200 ✅ :1228 sync_every: int = 200, # ← 这就是 C
double=True ✅ :1230 double: bool = False, # 打开就是 Double DQN
if __name__ == "__main__" ✅ :1292

四个全中。这就是为什么工具要先读书,而不是先答题。

3.3 · 直接问 free

你自己打字。注意它仍然不肯直接把答案倒给你——socratic 不只是一枚芯片,是整个 prompt 的底色。

你:

我在学 DQN,不太理解为什么有一个 Q-network 要固定、另一个在更新。 凭什么这样算法就会收敛而不发散?这个 idea 最早是从哪来的、出自哪篇 paper?数学上怎么证明它不会发散?

苏格拉底:

好问题,三个问题串得很顺。我先不急着全倒给你——你把它们拆开想清楚,比听我念答案值钱得多。

先说你能自己翻到的部分:

手册第三拍「出身:这两个技巧分别是谁的」专门讲了 target network 和 replay buffer 各自从哪篇 paper 来的。你翻到那一段,看看它俩是不是同一篇论文提出来的——先搞清楚这个。

然后你回来看决策④。它已经写得很清楚了:没有人证明过 DQN 会收敛。 而且它把“能证明什么”和“不能证明什么”分得清清楚楚。你读完全段之后,可以试着用你自己的话回答我下面这个追问:

决策④说 DQN 和 FQI 之间隔着一层——DQN 每步只做一次梯度更新、目标每 C 步才同步。那如果 FQI 能证收敛,DQN 只是“靠近”它,这种靠近到底多近才算够近?你自己觉得,C 取多大,你才愿意说“嗯,这差不多就是 FQI 了”?

原文:05-chat-free-three-questions.json 11.0 秒

三个问题,它一个都没有直接回答,但三个都指到了书里的确切位置:出身在第三拍, 收敛性在决策④,而且它把决策④里最重要的那句话原样端了出来——「没有人证明过 DQN 会收敛。」

同一个问题用英文问一遍,它就肯给全了(14-chat-free-en.json):

第二个:哪个论文。

翻第三拍(924-943 行)。有个关键区分:2013 年的 workshop paper 没有 target network,2015 年的 Nature 加了。再往前,Riedmiller 2005 的 NFQ 是直接祖先——那篇的做法是「训完一整轮再换目标」,DQN 把它改成了每 C 步换一次。

第三个:有没有证明它不会发散。

结论是:没有人证明过 DQN 会收敛。但如果你把 C 推到极端——两次同步之间把回归训到底——它就变成了 Fitted Q Iteration,那个东西有一套误差界。

那些行号、那些年份、那句引文,全部来自它 read_file 读到的正文,不是它的记忆。

3.4 · 后台深挖 ◆

你那一轮对话结束的同一时刻,另起一条线程,去读同一本书的别处,攒出几个 「你现在还问不出来、但再往前走一步就会问」的问题存进池子。它跟你的对话完全并行, 你不用等;池子不会一次倒给你,每一轮最多放一条出来(pen/probe_store.py:42 的 MAX_RELEASE_PER_TURN = 1),侧栏上同时最多挂两条。

侧栏底部的芯片区:四枚固定芯片下面,一条带 ◆ 的深挖问题被高亮框起来——「γ 给未来打折,α 给旧账打折,两个折扣一起用,Q 值到底在追什么东西?」

真跑那一次池子里攒了三条,第三条是这样的:

◆ 深挖

你在 Level 2 学到三个东西凑齐就发散,DQN 砍掉了自举的实时性——那剩下的两样在这个结构下还会不会联手炸给你看?

axis: altitude · depth: 5 · 锚点跨两关:Level 2(740–747)+ Level 3(954–964)
(deadly triad:自举 + 离策略 + 函数逼近,三个凑齐就可能发散。)

它为什么抛这一条(why 字段,模型自己填的):

他刚读完决策①的三层拆法,手里正好捏着 Level 2 的 deadly triad。让他把两关的知识挂上钩——DQN 没有杀死发散,只是把那个环从每步都通改成每 C 步通一瞬。读者需要补上这个抽象跳跃。

原文:06b-deep-ledger.json 池子里 3 条,2 次调用,8043 in / 649 out token

读者划的是 Level 3 的一段,这个问题把它接回了 Level 2 的 deadly triad——七百行之前的内容。 它的判断是:DQN 没有消灭 deadly triad 的三个要素,只是把其中一个的接通频率 从每步降到了每 C 步。

闸门是真的会枪毙题的。 同一段正文,换成英文界面那一场:2 次调用、2002 个输出 token, 池子里一条都没留下——全被 depth < 4 这道闸挡了(pen/probe.py:1001)。 到第二轮才留下一条:

NFQ trains until convergence before updating the target, while DQN updates every C steps. Why doesn't DQN just adopt NFQ's approach for guaranteed convergence?

原文:13-deep-en.json

广度由代码封死,不由模型自律——这一条在 4.5 后台深挖是一条任务队列里会讲透。

3.5 · 写回原文,和那道审批闸

审批面板:标题「审批这次编辑」,下面是 edit_file 指向的那篇笔记,再下面是「--- 原文 ---」和「+++ 换成 +++」的逐行对照,最底下两个按钮「允许这次编辑」和「拒绝」。面板上写着「模型自己选要换的那一小段。点允许才会改这篇笔记。」

写回:两把工具,三道闸,一个快照栈

你说:「把你刚才讲的『为什么要两个网络』那三层,做成一个折叠块,补在决策① 后面。」

它先 read_file 读到带行号的原文,下一轮才单独提一次编辑。侧栏弹出审批面板, old_string / new_string 逐字对照。它提议的是:

- 这是本关最核心的一问,把它拆成三层:
+ 这是本关最核心的一问。下面从三个层面拆解,你可以按自己感兴趣的顺序读(点击展开):
+
+ <details>
+ <summary><b>数学层 · 动力学层 · 工程层 —— 三层拆解</b></summary>
  ...三层原文一字不动...
+
+ </details>

原文:07-chat-writeback.json

同一个文件,四个时刻的大小和 md5:

时刻 文件大小 md5
提案已发出、审批面板开着 96874 153a8982b0c7…
你点「拒绝」之后 96874 153a8982b0c7…
你点「允许」之后 97051 551363244889…
回滚之后 96874 153a8982b0c7…

提案挂着的时候,磁盘上一个字节都没动;拒绝之后还是没动;回滚之后逐字节还原成原文。

原文:08b-approve-deny.json(拒绝)· 08-approve-allow.json(允许)· 09-snapshots-rollback.json(回滚)

权限层是可以脱离模型单独验的,这也是它该有的样子:

调用 返回
decide("read_file") allow — 只读自动过
decide("fetch") allow — 取公网页面,自动过
decide("edit_file") ask — 每一次都问人
decide("bash") / decide("write_file") deny — 没登记的工具一律拒
read_first_block("edit_file", 教材, read_before=∅) ⛔ 挡下
read_first_block("edit_file", 教材, read_before={别的文件}) ⛔ 挡下
read_first_block("edit_file", 教材, read_before={教材}) ✅ 放行

原文:15-permission-gates.json 源码:pen/agent/permissions.py:15、:23

3.6 · 回滚 / 重做

写回之后侧栏上那两个箭头,走的是快照栈,不是编辑器的 undo。

侧栏顶部的回退箭头悬停时弹出提示「整篇笔记回到上一版(还能退 1 次)」;下方是完整的对话记录,中间可以看到「翻手册 成功」和「改原文 成功」两条状态行。

GET  /v1/handbooks/dqn-550d425c/snapshots
     → {"can_undo": true, "can_redo": false, "undo_n": 1, "redo_n": 0}

POST /v1/writeback/rollback
     → {"ok": true, "restored_from": ".../snapshots/20260822T015739533075Z-pre-edit.md"}

它按整篇还原,不是只撤你划的那一段。 因为模型提议的编辑可能同时动了好几处, 按选区回退会留下一个半新半旧的文件。

undo + redo 一共只留 20 版(pen/config.py:57 SNAPSHOT_KEEP = 20)—— 这不是一个无限的历史,是一个能兜住「刚才那下点错了」的深度。

3.7 · 两本书之间

书架上不止一本书的时候,苏格拉底会拿到一份其他教材的摘要 + 路径,于是他能翻到另一本。

这件事的价值,看一对同题对照最清楚。同一个问题——「另一本讲什么」——问了两次。

书架接上之前,他老实认账:

好问题,但我得先给你交个底:另一本《通关手册》我没读到,不能瞎编。

我能确认的是手上这本。它名字就写明了——writeback-fixture.md,fixture,测试夹具。 意思是:这本书的真正用途不是「内容」,是测试「写回」这条链路。

至于那本《通关手册》具体讲什么——你把它的路径给我,我去读一眼再回答你。 不读就猜,那是江湖骗子干的事。

书架接上之后,同一个问题,他先去读:

我先去翻一眼那本《通关手册》的开头,别凭标题瞎说。

read_file → 1 # 手搓 SWE Agent 通关手册 v2 · 教材级(全册:开篇 + Level 0~6 + Capstone) …

看完了,两本册子不是一套书,是两种东西。 《通关手册》是正课。 目标一句话:让你从零手搓出一个轻量 SWE Agent…… 整本一个比喻:你是师傅,Agent 是记性为零、胆子极大的实习生。

⚠️ 两段都出自作者本机的真实会话,没随仓公开(里面是私人 vault 路径), 所以这是全文唯一你没法自己核对的引文。其余每一处引文下面都挂着可点开的 JSON 原文。

注意「之前」那一版并不是失败。 他答「我没读到那本书」是对的——那本来就是实情。 这就是为什么书架那一整段在只有一本书的时候会整段不出现,而不是写一个「(无)」: 写「(无)」等于替模型确认过「没有别的书」,那是替它撒谎。

还有一条:给书名必须同时给路径。

光给书名,苏格拉底只会去猜文件名。

这句话现在是 pen/tests/test_tutor.py 里一条断言的失败提示。

3.8 · 账单

GET /v1/usage
{
  "spend": {
    "chat":  {"calls": 14, "in_tokens": 189275, "out_tokens": 9872,
              "cached_tokens": 125440, "reasoning_tokens": 4906},
    "probe": {"calls": 4,  "in_tokens": 15892,  "out_tokens": 6923,
              "cached_tokens": 3328,  "reasoning_tokens": 5674},
    "fold":  {"calls": 0,  "in_tokens": 0, "out_tokens": 0}
  },
  "total": 221962, "sessions": 2, "skipped": 0
}

设置页里的「花销」面板:一共 101,785 token,来自 2,694 场对话;下面分列主对话 59,806、深挖 41,979、写回 0,以及缓存命中 34,432。

原文:10-usage.json——上面 3.1 到 3.6 全部跑完之后的真实账单

三笔分开记:chat 是你正在聊的那条线,probe 是后台深挖,fold 是写回时的折叠生成。 分开记是为了能分开限——后台超支不该掐掉你正在读的那一轮。

它只数 token,不折算成钱。 因为汇率是你的:你填的是哪个节点、哪个模型、 有没有折扣、缓存命中算不算钱,只有你知道。

不过你大概想知道一个量级。上面那 22 万 token,按我跑这一轮时那个节点对 deepseek/deepseek-v4-flash 的挂牌价($0.077/M 入 + $0.154/M 出)算:

入 205167 × $0.077/M  +  出 16795 × $0.154/M  ≈  $0.018

不到两美分,而且这是上限——它把 12.9 万个缓存命中的 token 当全价算了。 换前沿模型会贵一到两个数量级。

这个累计数会往下掉,别以为是 bug——会话是有保质期的(见 4.8), 被清掉的那些,它们的账也跟着走了。

3.9 · 自己定一枚泡泡

上面那几枚芯片,底下其实都是同一件事:点一下,往 [意图] 段里塞一句话。 socratic 塞的是「别揭晓,先反问」,explain_zero 塞的是「当我零基础」。 就这么简单——所以没有理由只让作者写这句话。

设置页 → 自定义泡泡 → 从模板挑一个新建。三个起手模板分别是 「把这段出成一道题」「把解释折进原文」「补一段 LaTeX 风格伪代码」, 复制过来照你自己那本书的体例改:改小节名、改编号规则、改折叠块长什么样。 改完侧栏那排就多一枚按钮,虚线描边,和固定芯片分得开。

最常见的用法是按你自己的体例往笔记里插内容。比如让它把问题写进你的题目小节, 并且必须是 <details> 可展开格式——把这两句写进指令里就行,它照做:

就我划中的这一段,出一道自测题,写进这一关的题目小节。
题干独占一行,格式 **Qn. 一句话的问题?**,n 接着已有的最大编号往下排。

勾上「会改写原文」,它就知道这一轮要动笔记:先 read_file 读原文, 再提一次 edit_file,然后照常弹审批面板(见 3.5)—— 你不点允许,磁盘一个字节都不会动。撤销、快照、光标跳转全都照旧。

几件说在前面的事:

  • 这个开关不是磁盘的锁。 它管的是给模型的交代,不是工具的可见性—— 关掉的泡泡,模型仍可能提出一次 edit_file。真正拦住写盘的是审批闸,它一直都在。 这和 free 芯片的行为一模一样,3.3 那段已经说过一次。
  • 名字不翻译。 界面切英文,你的按钮还是你写的那几个字——那是你起的名字。
  • 泡泡住在你这个 vault 的 data.json 里,sidecar 一个字都不存, 指令随每次请求上行。换机器就跟着库走。
  • 名字留空就用指令的第一行当名字,不会变成一枚看不见的按钮。

格式校验(检查它产出的折叠块合不合你的体例)这一版还没接, pen/insert.py 里那个 lint_fold() 已经在等着了,下一个小版本上。


4 · 系统设计

4.1 · 三个进程,一条 loopback

三个进程,一条 loopback

Obsidian 插件(TypeScript)、本机 sidecar(Python / FastAPI)、你自己填的那个模型节点, 一共就这三个,中间那条线是 loopback。插件不打作者的服务器,仓库里没有任何 telemetry 端点;sidecar 只绑 127.0.0.1,你在设置里填一个非本机地址,parseListen 会直接抛 new Error("not-loopback")(src/sidecar.ts:53),而不是「尽力而为」地警告一句。

模型调用从你的电脑发出去,发到你填的那个节点,任何 OpenAI 兼容的 Chat Completions 端点都行。真正出本机的还有装和升级那两下:插件建 ~/.socrates-pen/venv 并从 GitHub 和 PyPI pip 安装 sidecar,之后就全在本地。升级那一下有个前提——插件每次启动先 ping 本机 服务,ping 通就直接接上、什么都不下载;只有 ping 不通、要重新拉起时才比对版本号,发现旧 了才照着新版本号再取一份。

4.2 · 工具箱里三把

工具箱里是 read_file、fetch 和 edit_file——没有 bash,没有 write_file,没有 shell。 权限也不是一个开关,是三值的:read_file 和 fetch 是 allow,自动过;edit_file 是 ask, 每一次都弹审批;其他任何名字一律 deny,不认识就拒。最后这一条是默认拒绝,不是默认放行, 模型幻觉出一个 run_command 来,撞的是墙。

fetch 给定一个 http 或 https 的 URL,GET 那一页,去掉标签,把正文交给模型。它不是搜索: 侧栏「查相关论文 / 算法出处」仍是灰的,没有 URL 就不会去网上翻。只接受公网地址,内网、 本机、file:// 一律拒;解析出 IP 之后按这个 IP 去连,Host / SNI 仍用原来的名字。

4.3 · read-first 是一道硬闸

要改哪一段,必须在更早一轮成功读过那个文件;同一批 tool_calls 里先 read 再 edit 也照样拦。这条容易被当成过度设计,其实不是——同一批里那两个调用的参数是同时生成的, 写 edit_file 的 old_string 时,read_file 的结果还没回来。那仍然是猜,只是猜得比较 像。被拦下来时模型收到的不是一句「拒绝」,是一段说明怎么做才对的话:

错误:edit_file 之前必须先成功 read_file 同一路径。请先 read_file 看准带行号的原文 (格式 N\t原文),下一轮再单独调用 edit_file(不要和 read_file 写在同一批 tool_calls 里)。 old_string 必须是去掉行号前缀后的纯原文。

pen/agent/permissions.py:7 READ_FIRST_MSG

4.4 · 沙箱有两套根,读和写不是一回事

写只允许改登记过的那一篇(assert_write_target:目标必须逐字等于登记时的原文路径)。 读可以放宽到白名单里的根。.git / .obsidian / .env* 一律拒,两边都拒。

这两套根宽窄差得很远,得说清楚。 从 Obsidian 里用,读根是整个库根 (外加 sidecar 自己那个根:read_roots() 返回的是 [REPO_ROOT, *extra_roots], REPO_ROOT 永远在里面——pip 装的时候它是 site-packages)—— 插件登记教材时把 vaultRoot(app) 一起发过去(src/views/PenView.ts:849 → pen/libraries.py 的 meta.allow_root → pen/tutor.py:69 的 read_roots() → pen/sandbox.py 的 assert_readable),不需要你手动放宽。实测:登记 book.md 之后 read_file("私人/日记/2026.md") 是放行的。

实际不会发生,是因为提示词只告诉了它当前这篇和书架那几本——那是行为,不是边界。 写那一侧才是真闸:连书架上的别本都改不了,只能改登记过的那一篇。

书架的可见性用的是读根,不是全局允许根。这条差别听起来很细,但方向很明确:

印一条苏格拉底读不到的路径,比不印更糟。

因为那会让他试着去读、失败、然后当着你的面编。

4.5 · 后台深挖是一条任务队列

后台深挖:一条任务队列

为什么要另起一层。 一开始追问是搭车产出的——让模型在回答的末尾顺手写两条 <!--pen:chips -->。问题是那两条永远纠缠在刚讲过的细节上(「echo 加不加引号」), 而读者真正想问的是架构层面的东西:搭车的追问,视野被那一轮的上下文锁死了。所以深挖 被拆成独立的一层,有自己的 prompt、自己的预算、自己的账本。

展开:这一层的六条设计约束(每条都有它要治的病)

① done 那一刻起一个 daemon 线程,刻意不用 ThreadPoolExecutor。 ThreadPoolExecutor 会注册一个 atexit 钩子去 join 所有 worker——一个卡在 网络 IO 上的 worker,能让你按 Ctrl-C 之后等 30 秒。daemon 线程不会。

② 永远不给它 tools。 定向读由 Python 执行,不是模型自己决定读多少:硬上限 2 段 × 80 行、最多 2 次。

广度由代码封死,不由模型自律。

一个能自己决定「我再多读几段」的后台任务,就是一张开着口的账单。

③ 故意不喂邻域。 不把读者划中那段的前后文喂给它。理由写在 pen/probe.py 的模块头上:

那 4000 字符里全是手册自带的入门题(「heredoc 里 <<'EOF' 的引号起什么作用」), 模型盯着它们必然产同构题——这才是「echo 加不加引号」的病根。

改喂苏格拉底刚讲的那段话,而且剥掉代码块。

④ 会话为键的收件箱 + 一个游标。 GET /v1/sessions/{sid}/deep?since=N。前端 3 秒一拍 (src/deeppoll.ts DEEP_POLL_MS = 3000),最多转 480 秒 (DEEP_POLL_BUDGET_MS),连失败 3 次放弃(DEEP_POLL_MAX_FAILS)。 正常情况下 running 一空就停,跑不满这个预算。

⑤ 成熟度闸门。 每条题自带 timing:now 这一轮就能放出来,later 留在池子里,每一轮重新过一次 闸——你读到那儿了,它才出来。放行之外还有一道节流:一轮最多放一条。

⑥ 质量靠强制填槽 + 确定性校验,不靠夸模型。 每条题必须填满 axis / depth / grounding / anchors / why, 五条轴是封闭集合:

轴 它要产什么
bridge 把两处挂上钩
tradeoff 这里选了 A 否了 B,代价是什么(必须填 alt)
vs_real 现实里是怎么做的(锚点必须落在「第三拍 · 出身」,白名单校验)
failure 什么条件下会炸(必须填 trigger)
altitude 往上抬一层

然后 Python 验槽,不验措辞:depth 自己打 1–5 分,depth < 4 的直接扔 (pen/probe.py:1001)。3.4 节里英文那一场,2 次调用 2002 个输出 token 被这道闸全部枪毙,就是它在干活。

4.6 · 配置每请求透传,不写全局槽

一台 sidecar 可能同时伺候两个 vault。设置写进全局槽,就是 A 库的模型串到 B 库去。 所以所有旋钮跟着每一个请求走。

一共 18 个旋钮(pen/config.py 的 LIMIT_RANGE)。前后端各有一张范围表, 而 scripts/check-limits.mjs 是一道 CI 闸,专门守着这两张表不许漂—— 前端夹到 30、后端夹到 60,那就是一个只在边界上出现的 bug。

4.7 · 成本闸门:分类不分总

闸门全景:钱一套闸,安全另一套

三个 token 上限分开记也分开限:主对话一个、后台深挖一个、跨书阅读一个。分开的理由 很实际——后台超支不该掐掉你正在读的那一轮。三条上限默认全是 0,0 就是不限,判据只有 一句 cap > 0 and (spent + max(0, headroom)) >= cap(pen/meter.py:167),「0 = 不限」 的全部实现就是 cap > 0 这一半。

超限不报错。它给模型追加一句让它收敛的话,不是抛异常,你看到的是一个短一点的回答, 不是一个红色感叹号。主对话那个不是硬上限:到线之后还会再出一次答案,因为那一轮 已经开跑了;设置页上就是这么写的,这里也照样写。

4.8 · 会话会过期,账也跟着走

类型 判据 留多久
空会话 len(messages) <= 1 1 天
聊过的 其余 7 天
挂着审批的 pending.id 非空且不是空会话 30 天

为什么需要这个:清理上线之前实测,会话目录攒到 3389 个文件 / 10.4 MB, 其中 3371 个是空的——每划一次词就建一场,绝大多数没等到第一句话就被下一次划词换掉了。

第三档那个「且不是空会话」是后来收紧的。第一版写成「有 pending 就永不删」, 那是一条无界豁免:任何带 pending 键的文件从此占着盘,清理再怎么跑都动不了它—— 那正是这次要治的病本身。

pen/retention.py,模块头有完整的实测记录

4.9 · 教材无关

它对任何 Markdown 教材都能用,书名从你那篇笔记的第 1 行 H1 注进去。这一句是 SYSTEM_PROMPT 的第一句话,也就是每一场会话 messages[0] 的全部内容,建场那一刻就 固化并落盘——书名要是写死在里面,模型一上来就被告知它在读一本它没在读的书。真跑那一次 落盘的 messages[0] 第一行是:

你是苏格拉底,坐在读者旁边,正在带人读一本叫《从零手写 DQN · 强化学习通关手册(全册:开篇 + Level 0~3 + Capstone)》的通关手册。

全文里 SWE 出现 0 次。

原文:02b-system-prompt.json

书名要注两次,因为提示词有两条路。后台深挖走的是另一份,它的 user packet 里给了位置、 原话、苏格拉底刚讲的、足迹、书架、已经问过的题,唯独不说这是哪本书——模型只能从关号、 拍名和材料往回推,于是照着提示词里那五个示范问题的名字走,而那五个例子取自别的书。 那一路现在也注书名,走的是和 messages[0] 同一套清洗:

[你在带读哪本书]
《从零手写 DQN · 强化学习通关手册(全册:开篇 + Level 0~3 + Capstone)》
(下面所有材料都出自这本书。它讲什么,看材料——别从别的书上推。)

pen/probe.py:build_user_message

但八拍体例留下了,而且是故意的。 「第三拍 · 出身」「第五拍 · Meta Question 门禁」这些 不是那本书的内容,是格式契约:vs_real 轴要求锚点落在「出身」那一拍,examples 要求例子名对得上「第七拍」。教材体例和深挖算法是咬合的,你的书按这个格式写,深挖才有 地方下锚,docs/demo/从零手写DQN.md 就是一份可以照抄的样板。

4.10 · 一轮对话,从划词到落字

一轮对话:从划词到落字
展开:给开发者的那一层

规模(截至 v0.15.11,全部实测)

部分 规模
Python(sidecar,不含测试) 32 个模块,9719 行
Python 测试 1101 passed
TypeScript(插件) 18 个文件,6137 行
HTTP 路由 23 条
配置旋钮 18 个

SSE 事件的种类在 JSON 载荷的 type 字段里,不在 SSE 的 event: 行上。 这是接这套 API 时第一个会踩的坑。八种:

type 是什么
status 阶段:writing / thinking / reading / tool
think 思考过程(模型支持时)
token 正文,一段一段吐
tool 工具跑完了,带 name / ok / detail
approval 要你点允许,带 pending_id / name / args
spend 这一轮花了多少 token
done 这一轮结束,带合并后的账
error 出事了,带本地化过的人话

测试闸门

前端 npm test 是十三道独立的闸,各守一件事。它们都打包真代码来跑, 不读源码找特征——插件这边没有测试框架,也不值得为这点事引一个:

闸 守什么
check-i18n.mjs 词表自检——语言解析在真实边界上的那几个坑
check-poll.mjs 深挖轮询的终止条件,跑的是编译出来的真代码。少一个终止条件,你关掉面板它还在后台敲 sidecar
check-api.mjs HTTP 错误的形状,跑的是 src/api.ts 编译出来的真代码
check-key.mjs 钥匙按主机落锁那套,换节点时不许把旧钥匙带到新主机上
check-fold.mjs 折叠块在聊天正文里要被剥干净,别让读者看到半截 HTML
check-css.mjs styles.css 的不变量,条条是真踩过的坑(跑一遍会打印当前条数)
check-limits.mjs 前后端那两张夹紧表必须逐项相等——同一道闸的两半
check-sidecar.mjs 版本比对、端口占用的解析,各家 lsof/netstat/ss 输出都喂一遍
check-chips.mjs 自定义泡泡的归一化和消毒(见 3.9),外加拿同一批语料把前后端那两份消毒逐字对跑一遍
check-preflight.mjs 体检结论到状态栏文案的映射,每一种码都要有一句人话
check-providers.mjs 前端厂商下拉表和 pen/providers.py 方言表逐项相等,含 base_url
check-locate.mjs 阅读视图划到的渲染文本对回原文行号:粗体、代码、表格、标题、折叠块都要对得上;对不上返回 null 而不是第 1 行
check-report.mjs 学习画像的雷达几何与书架合并:轴从 3 根长到 30 根,标签不出框、未评的点不画成 0 分、顺序不重排;同标题的两次登记并成一行

npm run build = tsc --noEmit && npm test && esbuild。三样全过才产 main.js。

后端 python -m pytest pen/tests -q → 1101 passed, 在任何一个干净 checkout 上都该是这个数(v0.15.1 之前不是,见 docs/v0.15.1-公开仓测试开箱45红.md)。

教材索引自检

python -m pen.index --check 你的笔记.md

它不调模型。同一份输入永远切出同一份索引——这条性质是所有定位、锚点、回读的地基。

$ python -m pen.index --check docs/demo/从零手写DQN.md
从零手写 DQN · 强化学习通关手册(全册:开篇 + Level 0~3 + Capstone)
path=/Users/you/socrates-pen/docs/demo/从零手写DQN.md
lines=1405 sections=87 qs=21 toc=45
CHECK OK

那五张架构图都是 .drawio.svg——GitHub 当图渲染,用 draw.io 打开还能直接改(mxGraph 模型存在根 <svg> 的 content 属性里)。


5 · 装 · 用 · 隐私

装

开工前确认三件事:

  • Obsidian 桌面版 1.5.0 或更高(手机版不行,它要在你机器上起一个 Python 进程)
  • 本机 Python 3.11 或更高(python.org)
  • 一个兼容 OpenAI Chat Completions 的 API Key

进了社区插件目录之后走设置 → 社区插件 → 浏览 → Socrates。在那之前手动装:从 GitHub Release 下载 main.js / manifest.json / styles.css 三个文件,拷进 <你的库>/.obsidian/plugins/socrates-pen/, 再回设置 → 社区插件里启用,Restricted mode 要关掉。

第一次启用会花大约一分钟:插件在 ~/.socrates-pen/venv 里建一个隔离环境,从本仓库 pip 安装 sidecar,这一步要访问 GitHub 和 PyPI。装完之后设置 → Socrates 最上面 那一行会显示本机服务在不在跑。全程不用开终端。

用

  1. 等设置页最上面显示本机服务运行中,没跑就点启动;然后在设置 → Socrates 填 API Key,需要的话再改 Base URL、模型、Thinking 档位。
  2. 打开一篇笔记划一段(实时预览或阅读模式都行),再打开苏格拉底侧栏用当前选区, 或者用命令面板做同样的事。
  3. 想把解答写进原文,就说清楚插哪 / 换哪,或者在有了真正解答之后点写回。模型 必须先读文件,再单独一轮提编辑;侧栏弹审批,点允许才写盘。
  4. 回到上一版 / 重做按快照栈整篇回退,不是只撤选区。

刚装好、还没填 Key 时的侧栏:顶上一行写着「sidecar 在,请到设置 → Socrates 填写 API Key」,中间是苏格拉底的字符画肖像和「苏格拉底学习法」字标,底下一排芯片——前三枚是亮的,「查相关论文 / 算法出处」和「把刚才的解答写进手册原文」两枚是灰的。

设置页:最上面是本机服务的启动/停止和运行状态,下面依次是语言、API Key(密码框)、Base URL、模型名、Thinking 档位、后台深挖开关,以及每小时深挖上限等旋钮。

隐私与网络

它不做什么。 不索引、不遍历、不上传,它不会扫你的库,也不会把笔记发到任何地方。 实际发生的读取只有两种:你划词的那一篇,和你放上书架的那几本。插件默认只访问 http://127.0.0.1:8765,不向作者汇报任何东西;会话、快照、深挖账本全在你自己机器上的 ~/.socrates-pen/ 下。

但那是行为,不是沙箱保证。 只读到那两种,是因为提示词里只告诉了它这些。沙箱真正的 读边界是整个库根(.git / .obsidian / .env* 除外),库根由插件在登记教材时一并 发过去(src/views/PenView.ts:849 把 vaultRoot(app) 发给 POST /handbooks/import), 不需要你手动放宽。你在对话里直接报出一个路径,它就能读到。写的边界严格得多,见 4.4 沙箱有两套根。

写盘那一侧才是真闸。 任何编辑都要你先批准,不批准就是一个字都不落盘,只问不写是 完全正常的用法。兜住这件事的是审批闸,不是「你没点那枚写回芯片」——在 free 里直说 「帮我在那段后面补一句」,模型同样会走到 edit_file(pen/session.py:64),侧栏照样 弹审批,3.5 那段拒绝演示用的正是 free 芯片 (08b-approve-deny.json)。真正的闸在 pen/agent/permissions.py:18-19:edit_file 恒为 ask,对每一枚芯片都成立。

剩下三件要你自己留意。 一,API Key 只存本机 sidecar 家目录的 ~/.socrates-pen/llm.json (权限 0600),不写进这个库——Sync / iCloud / git 带不走它;从旧版本升级时会把钥匙从 data.json 自动迁过去并抹掉。若这个库在旧版本时代被同步或提交过 git,历史里的那把钥匙 清不掉,请去服务商轮换一把。开发场景也可以不用设置页:给 sidecar 留 OPENAI_API_KEY 或 DEEPSEEK_API_KEY 环境变量(或源码树里的 .env)同样有效。二,网络有三处:装的时候从 GitHub 和 PyPI 拉 sidecar 和依赖到 ~/.socrates-pen,插件升级后重新拉起服务时会再取一 次;模型调用由这个本机进程发到你填的那个节点;模型调用 fetch 时会向那个 URL 发 GET (只接受公网 http/https,内网和本机一律拒绝)。三,禁用插件默认不会停掉 sidecar,那个 Python 进程还在跑,下次启用能立刻用,多个库也共用它;不想让它常驻的, 设置里有「退出后保持本机服务运行」,关掉之后退出 Obsidian 会停掉由本插件自己拉起的 那只(别人拉起的从不碰)。设置页那个「停止」会停掉配置端口上正在听的进程——包括 上次留下的、别的库共用的、旧版残留——并告诉你停的是哪一种。health 里带着 pen 版本, 和插件对齐才标「运行中」;旧服务占着端口时要先停再启动升级。

装不上 / 起不来

第一次启用要建 venv 再 pip 安装,这一步最容易出事。按顺序查:

  1. 设置页最上面那一行说什么。 显示「未运行」就先点启动,错误会直接印在那里。
  2. 本机 Python 够不够新。 终端里 python3 --version,要 3.11 或更高;macOS 自带的 可能还是 3.9,去 python.org 装一个。
  3. venv 建坏了就整个删掉重来。 rm -rf ~/.socrates-pen/venv,回设置页点启动它会重建; ~/.socrates-pen/ 下还存着你的会话和快照,别删整个目录。
  4. 端口被占。 默认 127.0.0.1:8765,lsof -nP -iTCP:8765 -sTCP:LISTEN 看是谁占着。
  5. 还是不行。 开 Obsidian 的开发者控制台(Ctrl/Cmd + Shift + I)看报错,连报错一起 提到 Issues。

6 · 开发 · 测试 · 许可

npm install
npm test        # 十三道闸,见「测试闸门」那张表
npm run build   # tsc --noEmit && npm test && esbuild

对着一个真库热更新:

export VAULT_PLUGIN_DIR=/path/to/vault/.obsidian/plugins/socrates-pen
npm run dev

没设 VAULT_PLUGIN_DIR 时 npm run dev 会直接退出——防止你把一份陈旧的 副本装进库里。

后端:

python -m pytest pen/tests -q       # 1101 passed
python -m pen.index --check 你的笔记.md

想自己复现 3 章里的所有例子:教材在 docs/demo/从零手写DQN.md, 每一步的原始请求体和 SSE 事件流在 docs/demo/transcripts/。

许可:MIT,见 LICENSE。


7 · Future Works

现在还做不到、或做得不好的几件事:

超长划选第一包不再带全文。 邻域 4000 字、目录 4500 字本来就有上限;划选超过 4000 字时,第一包只留开头和行号,其余按需 read_file。长会话可以把旧回合折进 带行号的滚动摘要(命令面板「把这场对话折进摘要」,或到了设置里那道窗口阈值 自动折)——侧栏旧气泡还在,下次请求不再带全文。

深挖更适合按固定体例写的教材。 后台追问会去「第三拍 · 出身」「第七拍 · 实操」这类小节 下锚。普通随笔、或没有这些小节的英文教材,主对话不受影响,跨章节的深挖会变弱。可以对照 docs/demo/从零手写DQN.md。

实测过的模型组合还很少。 这份文档里的例子都跑在 deepseek/deepseek-v4-flash 上。别的 OpenAI 兼容节点按协议能接,但没有逐家测过。


8 · 最近的版本

每个小版本都有一份设计说明在 docs/:读者看到了什么、病根在哪、改了什么、哪道闸守着。 这里只列 0.19 以来的大版本,补丁版顺带一句。

0.26.0 · 2026-09-03 · 窗口撞了退一批。 给小窗口模型(64k / 128k)的两道工具层保险。节点回「上下文太长」不再当普通拒绝报给读者:认出六家节点的溢出报文,把这一枪多少 token、模型上限多少连同「改成分段读」一起退回给模型,同一枪重打;退不了的换基座或折一次历史,一轮最多退三次。read_file 的截断改成按整行切并写明下一段的 offset,读到一半会说文件共几行,offset / limit 写错是工具错误不再炸掉整轮。设计说明

0.25.0 · 2026-09-03 · 学习画像。 侧栏第六枚按钮打开一个独立页签:一张随轴数增长的雷达、 十分制规则分与 BKT 掌握概率并列、每一分怎么来的逐条列出、这个库里每本书的书架。逐轮编码一律主模型, 第一次全量要读者点一下,之后打开面板增量补编,旧日志只进频率不进分。发版前用 Codex(gpt-5.6-sol) 审了一遍整段 diff,修了 16 条。0.25.1:只点芯片没打字的轮次是操作不是证据,不再硬归轴重试三次; 编码器每一枪的原始回复落日志。设计说明

0.24.0 · 2026-09-03 · 日志要够看。 画像的原料。轨迹补上本地时间、读者原话与导师回复全文、 真锚点(阅读视图下对不上行号不再假装在封面)、抛出的追问点没点、写回批准之后那半截、这一轮走的 快模型还是主模型。设计说明

0.23.0 · 2026-09-02 · 厂商方言表与真形状体检。 推理档 off / low / medium / high 按型号名自动 映射成各家的写法:DeepSeek、Google Gemini、OpenAI、GLM、Kimi、Meta,设置页多一个厂商选择兜底。 配置体检按主对话那一枪的真实形状打,不再猜。0.23.1:Gemini 3 的思考签名要带回去。 设计说明

0.22.0 · 2026-09-02 · Fast Mode。 顶栏一枚闪电开关:只读轮次走快模型,写回类轮次仍走基座。 快模型窗口小,压缩策略层按 stub → slim → fold 三档压,压完不污染会话,关掉开关就拿回完整上下文。 0.22.1–0.22.5:降级不再无声、配置体检、体检不许猜、思考正文带回去、Gemini 的推理档。 设计说明

0.21.0 · 2026-09-01 · 自定义泡泡。 底座那排芯片开放出来:每枚就是读者自己写的一段 prompt, 外加一个「会改写原文」开关;存在 vault 的 data.json 里随库同步,后端全程无状态。预置三个起手模板。 设计说明

0.20.0 · 2026-08-30 · 对话框可贴图。 设置里加「图像理解」开关,开了就能往对话框粘贴或拖入图片 (最多 4 张、每张 2MB),走 OpenAI 兼容的 image_url。落盘时丢掉像素,会话文件不会被撑爆。 设计说明

0.19.0 · 2026-08-25 · 主对话滚动摘要。 旧回合折成带行号锚点的抽取式摘要,不加第二次 LLM 调用; 划选超过 4000 字第一包只留开头。命令面板手动折,或到了 compact_chat_tokens 阈值自动折。 设计说明


MIT · xesws/socrates-pen

中文 · English

HealthExcellent
ReviewCaution
About
Highlight a passage and question it in a Socratic dialogue via the Socrates sidebar (desktop only). Run a local sidecar to host the tutor loop and tools, then optionally write approved answers back into the original note with user-approved edits and snapshot-based rollbacks.
AISidebarEditing
Details
Current version
0.26.0
Last updated
4 hours ago
Created
2 weeks ago
Updates
35 releases
Downloads
474
Compatible with
Obsidian 1.5.0+
Platforms
Desktop only
License
MIT
Report bugRequest featureReport plugin
Sponsor
PayPal
Author
Tangyi QianTangyi Qianxesws
GitHubxesws
  1. Community
  2. Plugins
  3. AI
  4. Socrates

Related plugins

Claude Sidebar

Run Claude Code in your sidebar.

Notebook Navigator

A better file browser and calendar inspired by Apple Notes, Bear, Evernote and Day One.

Claudian

Embeds Claude Code/Codex and other local Agents as AI collaborators in your vault.

LanguageTool Integration

Advanced grammar and spell checking, powered by LanguageTool.

Smart Connections

Find related notes and excerpts while writing. Your AI link building copilot displays relevant content in graph + list view. A local embedding model powers semantic search. Zero setup. No API key.

Meta Bind

Make your notes interactive with inline input fields, metadata displays, and buttons.

Tag Wrangler

Rename, merge, toggle, and search tags from the tag pane.

Copilot

Run AI agents such as Claude Code, Codex, and OpenCode inside your vault. Turn your second brain into a smart assistant that gets knowledge work done.

Fast Note Sync

Real-time sync of your vaults across server, mobile, and web; shareable with anyone; supports REST and MCP integrations to build your personal AI knowledge base.

Gemini Scribe

Allows you to interact with Gemini and use your notes as context.