这些年的笔记,积得着实不少。倘要分类,大抵有三:
-
见着好的东西,便如获至宝,随手存下;
-
在公司做事时,零零碎碎记下的种种;
-
自己研发的一点心得,写着写着,竟成了如今的博客。
那些存下的与公司里的,如今大半蒙了灰,静静躺在角落,再没人去理会,颇像小时候攒下的糖纸和玻璃弹子——攒时爱如性命,转眼便忘在抽屉的最深处了。独有博客里的,倒还时常翻一翻,改一改,像常来常往的老友。同是资料文字,境遇竟这样不同,我起初也着实不解。
这些原是些零散的「机械知识」,各自为政,如一盘散沙,谁也不认得谁。我便动了个念头:何不寻个知识库,将它们好生收拢起来呢?于是下载了黑曜石(Obsidian)来试,摆弄了半日,终觉不甚趁手——与其低头去顺别人的规矩,不如自己动手造一个:拣些顶要紧、顶常用的功能来做,往后要怎样摆弄,便都由得我了。
说来也巧,恰有 Claude Code 这件利器在手。前后不过两个星期,居然也就成了;如今竟能日日用着,倒有些出乎我的意料。
文章内容让 AI 使用鲁迅语调润色了一下,看着还怪有意思的 ^_^!
1. 需求
这是当初画下的需求思维导图。彼时不过是纸上的一点空想,如今回头看,倒大半都落了地:文档的管理,知识的图谱,还有一个知识库的 AI 助手。

2. 特性
已做成的,大略有这几样,且容我一一道来:
- 富文本知识库:文档一开,便可直接落笔,写着写着自己就存了,并没有「编辑」「保存」一类的按钮在旁聒噪。主题内置了十来套,今日嫌它素净,明日换一副便是;界面的字,也可随心另换。
- 混合搜索:关键词与语义两路人马,并肩去寻,寻回再合。便是半途坏了一路,另一路也还带得几分结果回来,断不至教你两手空空。
- AI 聊天:聊天能联网,又有记性。答你的话之前,先自个儿去翻箱倒柜找料,翻过哪几篇,末了都一一列出,绝不含糊搪塞。文字与图分作两拨走,又按题目的难易,在便宜档与思考档之间掂量着挑拣——无非是替我省几个铜钱。寻常 OpenAI 那一路的接口,它大抵都认得。
- AI 改文档:可使它直接改动眼前的文档;改罢却不擅自动手,先捧个 diff 与你过目,你点了头,它才肯落笔。
- 知识图谱:将文档与知识点结成一张网,全在本地盘算,并不去劳动那尊贵的大模型,自然也不必花钱。
3. 技术栈
这物件造得极轻巧:拢共只一个二进制,不倚仗外头的什么服务,数据也都安分守己地躺在本地——无非是一堆 Markdown,外加一个 SQLite 罢了。
| 层 | 选型 |
|---|---|
| 语言 | Go |
| Web | Gin + Cobra |
| 存储 | Markdown 文件 + SQLite(GORM + glebarez 纯 Go 驱动,FTS5 全文索引) |
| 中文分词 | go-ego/gse(分词 + TextRank,内嵌词典) |
| 语义检索 | 嵌入向量存 SQLite,Go 暴力算余弦,没上向量库 |
| AI | go-openai,兼容 OpenAI 端点 |
| 前端 | 原生 JS + 手写 CSS;Vditor、marked、force-graph,全部自托管 |
4. 主要功能成果
4.1. 首页
布局是仿着 VS Code 的。不必说左边那条活动栏与资源管理器,也不必说中间宽宽绰绰的编辑之处,单是那一方首页,便颇可玩味:近来开过的文档、收藏,还有一小幅图谱的缩影,都齐齐聚在一处。人一进门,自己近来在忙些什么,便不消细想,一望而知了。

4.2. 资料内容
知识库说穿了,原不过是一堆 Markdown。开了便写,写着便存,与寻常用惯的笔记本子并没有两样。
暗地里却藏着「双存储」的巧思:一处落笔,两处皆同。
- Markdown 文件:这是内容的真身,独此一份,别无分店;
- SQLite:只记些元数据与全文的索引,专管搜寻一事。
如此这般,搜寻的本事是有了,那些文字却并不被数据库拘着——你随时另取别的编辑器来开得,或索性一股脑丢进 git 里去,都悉听尊便。

4.3. 知识图谱
知识图谱这东西,有人嫌它是鸡肋,食之无味;我却偏偏喜欢。将散落各处的知识点结成一张网,那可视之状,看着竟有几分惊心动魄。它不单可看,还可搜;鼠标一近某个节点,与它沾亲带故的一整条脉络,便都齐刷刷亮了起来,煞是好看。
这张图并不去惊动大模型:知识点是本地的 TextRank 一个个拣出来的,数据尽数出自 SQLite,算毕再以力导引徐徐铺陈开来。故而纵是断了网、不配 AI,它也照样能看。从前那一篇篇各自孤立、老死不相往来的「机械知识」,如今竟被牵着线,织成了一张网。

4.4. AI 助手(问答检索)
它这检索,是所谓「agentic」的:并不将一堆碎片一股脑塞给模型了事,倒像是打发一个伶俐的书童——由它自个儿在至多八个回合里拿主意:读哪几本,读到几时,都随它去;末了,还须把真正翻过的文档,一一列作「来源」呈上,不许它虚张声势。这书童手里,常备着三样家伙:
- list_docs:先取一份满库的书目清单,专对付「与我总结整个知识库」这一类的大题目;
- search_docs:混着法子搜,按你的题目寻那最相干的文档;
- read_doc:老老实实读原文。
个人的知识库,原是小而杂的一堆;让它自个儿拿捏该读到多深,倒比一股脑地召回来得准些。
那 search_docs 的底下,是两路分头去寻,再合于一处:
- 关键词路:先将中文分了词,走 SQLite 的 FTS5;倘正文里一时寻它不着,便退作加权的 LIKE,勉力兜着;
- 语义路:把问题化作一串向量,与文档的向量比一比余弦的远近;
- 融合精排:两路以 RRF 合了,若又配着 rerank,便再细细地排上一回。
便是坏了一路,这搜寻也不至于全盘皆输,至不济也还退得回关键词去。至于向量,我并不曾另请什么向量库来供着,只将它作 BLOB 塞进 SQLite,教 Go 硬着头皮算余弦罢了——个人库这点分量,弹指之间也就扫完,何苦再多养一张嘴。
另有两桩本事,是我格外中意的:
- 联网:库里遍寻不见、或那问题偏又带着时令的,它便自个儿出门去搜;
- 长期记忆:譬如「往后答话都用编号」这一类的脾性,它会牢牢记进一个固定的文件里,隔了三五回会话也还作数,省得你每回都从头交代一遍。

5. 后记
这些时日,Claude Code 这件利器,也被我使唤得几乎要冒出烟来。
倚仗着它,事情竟成得这样快,说来实在有些出乎意料。
功用大略是齐备了,然而要细细打磨的去处,却还多着呢:搜寻的准头,图谱的排布,还有 AI 的那几句提示词,无一不可再三推敲。也罢——就当它是一畦长养着的自留地,往后得了闲,便再慢慢地、一垄一垄地侍弄它去罢。

不得不吐槽一下 Fable 模型,好用是好用,但是 Token 耗费之速度也是出奇的快。