先说明一下我这篇要聊的东西是什么。knowledge-work-plugins,字面意思是“知识工作插件集”,说白了我过去两年大部分精力都投入在一个内部项目上:把知识工作者日常里那些琐碎、重复、容易漏的环节,拆成一个个可以独立运行的插件,再把它们挂到同一个宿主平台上协同工作。做这套东西的起因很实际——我自己每天有一大半时间不是在“生产”,而是在“搬运”信息:网页存进笔记、PDF摘出关键段、会议纪要里的待办转进任务列表、灵感碎片跟当前项目关联起来。这些动作分开看都小事一桩,但凑在一起,一天能吃掉我三四个小时。
这篇文章我会尽量把整套东西讲透:为什么要做插件化而不是搞一个大而全的工具、宿主平台和插件之间的边界怎么划、几个核心插件内部是怎么实现的、有哪些参数和细节是网上文档大概率不会写到的,以及我实际踩过的坑。适合的人群包括但不限于:在折腾知识库/笔记系统的人、想把个人工作流自动化但仍然希望保持灵活性的同学、做内部工具平台的技术负责人。无论你最终是打算直接上手类似方案,还是只想借鉴其中的设计思路,我觉得下文的内容都有参考价值。
1. 为什么会有这么一套插件集:知识工作场景的真实痛点
1.1 先拆解一下“知识工作”到底包含哪些环节
我观察自己以及身边几位经常要处理大量信息的人(研究员、产品经理、工程师都有),发现所谓的“知识工作”其实可以被拆成几个固定动作:采集、整理、关联、输出。采集是往本地或云端捞内容,网页、PDF、图片、聊天记录都算;整理是去重、分类、打标签、格式化;关联是找到不同信息之间的关系,比如一条结论出自哪篇论文、一个需求对应哪个任务;输出则是把前面沉淀的内容变成文档、报告、代码或者决策。
这四个环节的痛点很不一样。采集的问题是散,信息散落在浏览器、邮箱、网盘、IM里,想找的时候永远不知道在哪。整理的问题是累,手动打标签、改格式、搬文件,全是低认知密度的重复劳动。关联的问题是无序,看了几十篇资料,最后脑子里还是一团浆糊。输出的问题是断,写文档时要重新翻资料,提到的引用、来源、上下文都得重新找一遍。
市面上不是没有单点工具,剪藏软件、PDF阅读器、笔记软件各有各的强项,但它们之间基本不通气。我在一篇笔记里引用了某篇PDF的观点,笔记软件和PDF阅读器是两套体系,关联全靠人肉维护;任务清单在另一个工具里,跟笔记内容完全脱节。知识工作的效率损耗,很大一部分来自这种“工具之间的缝隙”,而不是某个工具本身不好用。
1.2 为什么选插件化,而不是直接定制一个大而全平台
这是我一开始纠结过的问题。既然工具之间缝隙大,那做一个一体化平台、把采集整理关联输出全包了不就行了?后来我没走那条路,理由有三条。
第一,知识工作的流程太个人化。同是研究员,有人习惯先读全文再细抠某页,有人只看摘要和结论;同是工程师,有人乐意用命令行走一切,有人只接受图形界面。大而全平台意味着替所有用户做了一整套默认假设,结果往往是每个人都要迁就它。插件化则允许不同的人组装不同的工作流,底层共享一套数据,但具体环节按需选装。
第二,单一平台的维护成本会爆炸。一体化意味着采集器、解析器、编辑器、图谱渲染全糊在一个代码库里,任何一块需求变化都可能波及其他模块。拆成插件之后,每个插件独立演进,坏了不影响宿主,升级也不用全量发布。我见过不少团队做内部知识工具,做得越大越不敢改,最后只能靠发布纪律硬撑,那个滋味不好受。
第三,插件化天然保留了一个“逃生通道”。工具选型是会变的,笔记软件可能更迭、浏览器可能换内核、文档格式可能升级。如果所有功能都耦合在一个封闭平台上,迁移成本极高;但插件之间如果有清晰的数据协议,换掉某一个插件的实现,其他插件照样能跑。
我当时给自己定的原则很简单:**核心的数据模型和插件协议是稳定的底座,其余都做成可替换的模块。**这套底座花了我不少时间设计,但后面每新增一个插件,都能感觉到当初这份投入是划算的,因为新插件不需要关心别人怎么存数据、怎么发通知,只需要按协议接入就行。
1.3 这套插件集能做什么、不能做什么
能力边界先讲清楚,免得大家抱有不切实际的期待。这套knowledge-work-plugins能做的事情包括:从网页和 PDF 里提取结构化内容、自动整理并生成摘要、把笔记条目和任务条目双向关联、在写作时快速引用知识库内容、以及定期把散落各处的信息汇总成“周报草稿”。这些都是我在实践中验证过的,稳定且实用。
它不能做什么?不能替你判断哪些信息重要,不能百分百保证抽取出来的内容永远格式正确,也没有办法替你做出决策。工具能把信息整理好、把关联呈现出来,但“看懂”这件事还是得你本人来。我见过有人指望插件自动生成一篇能直接用的分析报告,最后发现机器生成的永远只是素材汇编,结论还得自己下。这个预期管理如果一开始没做好,用起来会非常失望。
2. 插件集整体架构:宿主、协议与数据模型
2.1 宿主平台的选择与边界
做插件集第一步是定宿主。这个宿主未必非要自己从零开发,我当时考虑过两类选择:一类是直接寄生在成熟工具上,比如以某个笔记软件或编辑器的插件机制为底座;另一类是自己维护一个轻量宿主,只负责进程调度、数据存储和插件通信。最终我选了后者,原因很现实:成熟工具的插件 API 往往只覆盖它自己想让你扩展的功能,而我的插件集里有不少能力需要跨工具协作,比如同时操作浏览器书签、本地文件、任务清单,单纯的笔记插件 API 撑不住。
自己写宿主听起来工作量很大,其实边界控制住并不复杂。我的宿主只做四件事:维护一份全局知识索引、管理插件生命周期、提供统一的日志和配置入口、以及负责数据变更通知。真正干活的是各个插件。这也意味着宿主写得很薄,大概一两千行核心逻辑就够用,不至于成为新的维护负担。
选宿主的时候有一个关键原则:不要试图把宿主做成“平台”。凡是某个插件特有且不影响别人的功能,就不放进宿主里。比如网页正文提取,它只服务剪藏插件,那就做成插件内部的能力,宿主完全不用知道什么叫正文提取,只需要知道有一条“内容被保存了”的事件发生。边界清晰之后,插件的增删变得异常轻松。
2.2 插件通信协议与数据流
插件之间不是直接互相调用,而是通过宿主转发消息。我定义了一套轻量级的消息协议,消息分三类:指令消息(比如剪藏插件请求保存一个网页)、事件消息(比如保存成功后广播一条content.created事件)、查询消息(比如写作插件问知识库里有没有某主题的引用资料)。
这个设计的价值在于解耦。剪藏插件不需要知道摘要插件存不存在;如果用户没有装摘要插件,事件广播出去没人消费,数据照常入库,后面装了摘要插件,它可以从知识索引里回捞历史数据离线补齐摘要。这样插件之间的依赖关系从“运行时强依赖”变成了“消息级弱依赖”,也让我不用处理复杂的插件启动顺序问题。
查询消息走的是同步通道,但我在实现里加了一层超时保护,避免某个插件响应过慢阻塞主流程。具体做法是:所有查询消息可以带一个上下文 token,宿主把请求转发给目标插件后最多等待 3 秒,拿不到结果就返回空集合并记录一条 WARN 日志。这个细节在平时不太起眼,但真遇到某个插件偶发卡死时,它能防止整个知识库 UI 卡住,属于投入很小收益很大的防御式设计。
2.3 统一数据模型设计
如果每个插件都用自己的数据格式,那插件集就是个拼盘而不是一个产品。我用了一套“条目—块—链接”的三层数据模型,这也是整套系统的地基。
**条目(Entry)**代表一个知识对象,比如一篇文章、一张图片、一个任务或者一条笔记。每个条目有类型、标题、创建时间、来源 URI 这些元数据。**块(Block)**是条目内部的单元,代表一段文本、一个图片引用、一个表格片段,相当于把长文档切成了可寻址的小段。**链接(Link)**描述两个块之间的关系,关系类型可以是“引用”“相关”“包含”等等。
为什么要把条目再切到块这个粒度?因为知识工作里真正被反复引用的不是整篇文章,而是文章里的某几段话。我在写作时想引用一篇报告里的某个数据,如果我只能在“整篇报告”这个粒度上引用,那引用的价值就太粗了。切成块之后,链接的精度大幅提升,知识图谱也能画到句子级,而不是文件级。
数据模型定下来之后,另一个关键决定是存储引擎。我用的是 SQLite + 全文索引的组合,理由也很简单:这是一个本地优先、单用户为主的知识系统,不需要上分布式存储;SQLite 的事务能力够用,全文索引能满足大部分检索需求,而且备份迁移非常方便。整套知识库就是一个几百 MB 的本地文件,拷贝走就是全量备份,这个特性在数据主权这件事上给了我很大的安心感。
3. 核心插件逐个拆解:功能定位与实现要点
3.1 网页剪藏与正文提取插件
这是整套插件集里使用频率最高的一个。功能上很直观:在浏览器里选中某个网页,调用插件,它就把网页标题、正文内容、作者、发布时间、原始链接一并存入知识库。听起来简单,但真正做起来最花心思的是正文提取。
网页正文提取的本质是从一段充满标签、脚本、导航栏、广告的 HTML 里把真正的内容区域挑出来。我处理的时候分两层走。第一层是启发式规则:统计每个 DOM 节点的文本密度和链接密度,文本密度高而链接密度低的节点,大概率是正文容器,这是很多正文提取库的基本思路。第二层是对站点特征进行模板修正,比如某些网站的结构比较特殊,第一层会判断失误,我会在配置里针对这些域名做微调。
提取完正文之后,下一步是清洗。广告标记、追踪参数、无意义的空段落都要去掉;正文里的图片需要决定是存远程链接还是下载到本地,我默认选远程链接,但提供一个设置项,如果用户需要离线访问,可以改成“图片缓存到本地”。这里有个容易被忽视的问题:远程图片链接可能会失效,所以我在保存时还会记录图片的曾经地址和抓取时间,至少失效后能追溯。
这段实现我前前后后改了三版,最大的教训是不要试图在正文提取上做到 100% 完美。网页是千奇百怪的,花太多时间对抗个别网站的奇葩结构,边际收益很低。我的策略是:保证主流站点 90% 以上准确率,对剩下的长尾站点允许用户手动选择“正文模式”或“整页保存模式”,降低挫败感而不是硬碰硬。
3.2 PDF 标注与知识抽取插件
PDF 是知识工作里最难处理的格式,没有之一。原因在于 PDF 的视觉排版信息是给打印机看的,不是给阅读器用的,文字块、图表、页眉页脚在底层都是离散的对象。直接从 PDF 里抽文本,拿到的经常是顺序错乱、段落断裂的字符流。我处理 PDF 时没有强行做完整的版面还原,而是有限度地做了三件事。
第一是文本层提取。数字原生的 PDF 大多有文本层,直接用专业库提取即可。扫描件没有文本层,需要走 OCR,但 OCR 又慢又容易出错,我把它设计成可选功能,默认关闭。第二是“页级别块切分”,我不尝试把整个 PDF 还原成顺畅的文章流,而是把每一页作为一个独立的容器,提取页内的文本块并记录它们的坐标位置。第三是标注导出,用户在某一段文本上划高亮或加注释时,系统记录的是“(页码, 文本块 ID, 偏移量)”这样的三元组,而不是简单复制字符串。这样哪怕原文后来被重新排版,只要语义结构没变,标注依然可以定位到对应内容。
其中有意思的是标注定位。我在按坐标提取文本块时,会把块内的实际文字一起存储,建立索引。用户高亮某段文字时,通过对整页文本做模糊匹配定位到“块 ID + 起始偏移”,这比纯坐标定位更稳。因为 PDF 阅读器渲染时的字体度量差异可能导致坐标漂移,但文本内容不会变。
这个插件我踩过最深的坑是字体编码。有些 PDF 内嵌字体不是标准 Unicode 编码,提取出来的文本是乱码。解决思路一是换用另一种 PDF 解析引擎做交叉验证,二是允许用户把这一页标记为“图像页”强制走 OCR。一开始我想找一种万能解析方案,最后发现“多引擎+人工标记兜底”才是真正可靠的路径。
3.3 知识图谱与双向链接插件
知识库里的数据如果只是一堆条目和块,用起来跟网盘里塞一堆文件没有本质区别。真正让知识库“活”起来的,是条目和块之间的关系图谱。这个插件做的事情是:自动建立链接,并提供可视化的图谱界面让人跳转。
自动建立链接分为两条路径。一是规则路径:当某个块里出现了另一个块标题的完整字符串时,自动加一条“提及”关系;当我在看某条笔记时,系统会在侧边栏展示“本页被哪些其他条目提及”以及“本页引用了哪些条目”。二是语义路径:基于文本相似度计算,把相似度过高的两块作为“相关”候选,但默认不会直接写入图谱,而是推到“链接建议”列表里,由我人工确认。这个设计是为了避免噪音——如果自动把所有相似内容全部连起来,图谱会变成一团线球,没有辨识度。
图谱可视化我用的是力导向图,节点是条目,边是链接关系。刚开始做的时候觉得很酷,但实际用下来发现纯图谱浏览的实用价值有限,超过几百个节点之后,人很难从一团乱线里读到有效信息。所以我把图谱拆成两种视图:全局视图只统计数量、呈现聚类,用于宏观感知知识分布;局部视图则是以某个条目为中心,展开两层以内的邻居,用于实际跳转浏览。后者的使用频率远高于前者,这也是一个“看起来炫但实际没用”的教训。
双向链接做得早有个额外的好处:它让我对“哪些内容值得入库”有了新的理解。只有那些真正需要被反复引用、反复关联的内容才值得被保存;随手截图、纯粹收藏而不会再看的内容,存进来只是增加噪音。这个认知反过来指导了其他插件的设计,比如剪藏插件会在我保存内容时提示一下“这个页面可能不值得剪藏,因为它和已有条目关联极少”,算是一个轻量级的质量过滤器。
3.4 任务联动与写作出口插件
知识工作的最后一环是输出,而输出通常跟任务绑定。任务联动插件解决的是“知识库里的结论如何变成待办”的问题。我在阅读某篇 PDF 时高亮了一段文字,并批注“需要和团队确认数据口径”,这段批注需要变成一条任务,进入任务管理系统。插件做的就是这件事:把知识库里的“批注块”转换成“任务条目”,同时保留双向链接,任务完成后可以在知识库里看到“这个待办源自哪篇资料”的线索。
写作出口插件则是面向长文写作场景。它本身不替代编辑器,而是作为一个“引用侧边栏”存在。我在编辑器里写一段话时,插件会根据当前段落的关键词,实时搜索知识库,列出相关条目和引用块,我选择某一条后,它会插入一段结构化引用,比如[[引用:文章标题#块ID]]。写完后,可以一键生成参考文献列表,每一条都指向知识库里对应的原始出处。
这两个插件让知识库真正参与到了工作闭环中,而不只是“存东西的地方”。我现在的习惯是:所有输入最终都要有自己的输出出口,要么变成一段可复用的文字,要么变成一个明确的待办。如果一样东西看完之后既没有触发任何输出,也没有产生任何关联,那它大概率是被过度收集了。
4. 关键参数与工程化细节
4.1 内容清洗与文本分块的参数选择
知识库里的长文档不能直接拿去建索引和算相似度,必须先分块。分块粒度过粗,检索时命中结果太模糊;粒度过细,语义碎片化,召回效果变差。我在实践中把默认块大小设为300 到 500 个汉字,同时要求块之间保留 50 字左右的重叠。
这个数字不是拍脑袋定的。我做过一组对比实验,把同一批文档分别按 100/300/500/1000 字分块,然后模拟写作场景里的引用检索需求,统计 Top-5 命中块里有多少是真正对应当前段落主题的。结果显示 300-500 字这个区间综合表现最好:既保留了段落的上下文语义,又不会因为块太长导致一个块里混杂了多个主题。100 字分块的问题在于,很多关键信息被切成了两半,检索时只能命中一半。1000 字以上则容易让“检索到内容”变成“检索到整个文档”,精度下降。
清洗规则同样值得列一下。除了去掉 HTML 标签之外,我还会做这四步:一是压缩连续空白符,包括把多个连续换行统一成单换行;二是去掉无信息的导航文本(“点击查看” “阅读全文”这类);三是把全角标点统一为半角,方便后续 token 化;四是过滤纯数字/纯符号的行,因为这类行往往来自页眉页码或者图表坐标残留。清洗做完之后,文本会进入分块流程,分块本身是纯逻辑切割,不影响原文的永久存储。
4.2 全文检索与语义检索的配合
知识库的搜索是我花精力最多也最满意的一部分。我选择的是“全文检索与语义检索并行,结果混合排序”的策略,而不是单纯依赖某一种。
全文检索的优点是精确可控,我搜“Claude 长上下文能力”时,命中结果一定包含这几个词的组合,缺点是它不认识同义词,搜“LLM 窗口大小”时搜不到“大模型上下文长度”的说法。语义检索则相反,基于文本嵌入向量来做相似度匹配,懂同义但召回结果有时候奇奇怪怪,看似语义相似实则不相关。
我的做法是两路结果都取 Top-N,然后用一个轻量级重排模型对合并集合打分。重排的特征包括:全文命中命中词数、命中词在原文中的位置密度、语义相似度分数、还有创建时间和引用次数作为弱特征。权重我调过几版,最终发现命中词数权重应该高于语义相似度,因为写作引用场景里,用户更关心“原文真的提到了这个词”,而不是“这两段话读起来有点接近”。
嵌入模型我没有选择超大模型,因为知识库的检索请求频率很高,单次检索等待时间太长会影响使用体验。我最后用的是一个轻量级本地嵌入模型,单条查询延迟控制在 50 毫秒左右,精度损失换来了丝滑交互。这个取舍在单人知识库场景里非常合理,因为本地库的语料范围有限,轻量模型的召回效果已经足够。
4.3 插件热更新与数据兼容
插件集做大之后,更新和兼容性问题就躲不开了。插件之间可能有依赖关系,比如知识图谱插件读取剪藏插件生成的数据。如果图谱插件升级后读取旧格式数据失败,就会报错。解决这个问题的核心手段是给每一类数据加版本号,并在读取时做迁移。
具体落地时我用了一套基于数据模型版本的迁移机制。每当数据模型有破坏性变更,我会写一个从旧版本映射到新版本的迁移函数,并且在宿主的启动流程里自动执行。比如 v1 版本的“块”没有坐标字段,v2 版本加了坐标字段,迁移函数会给旧的块填充一个空坐标对象,而不是报错。好的迁移策略应该是“向前兼容”,即新代码能读旧数据,必要时当场补默认值,而不是要求用户先手动导出再重新导入。
插件热更新方面,我参考的是“插件是独立进程”的思路。每个插件跑在独立的子进程或 worker 里,宿主通过消息协议与它们通信。更新某个插件时,宿主向旧实例发送退出信号,拉起新实例,这期间其他插件不受影响。这个方案会引入一定的进程通信开销,但对于知识工作这种延迟不敏感的场景,换来的是极高的稳定性。我把通信消息体控制在可序列化的 JSON 范围,避免跨进程传递复杂对象带来的序列化坑。
这块还有一个容易踩的坑:插件版本升级后,配置项的默认值变化可能导致用户旧配置失效。我的做法是所有配置项都带一个since_version字段,旧的配置文件中缺失的字段,在加载时自动用当前版本的默认值补上。这样做虽然会让“新版本悄悄改变了行为”,但我会在升级日志里标注清楚,至少不会出现配置文件解析失败这种低级问题。
5. 实操中的问题与排查实录
5.1 插件之间的“状态拉拽”
实际用起来,插件集经常遇到一个现象:单独测每个插件都正常,组合起来就出问题。典型的例子是剪藏插件保存一篇很长的网页后,摘要插件自动对这一长文生成摘要,生成了很久;这段时间里,用户再发起一次知识库检索,宿主被摘要插件占用的计算资源拖慢,检索响应变得很慢。
排查过程让我认识到,插件之间虽然逻辑上解耦,但共享的是同一个宿主进程的计算资源,必须在资源层面做隔离。我最终把耗时计算(摘要生成、嵌入计算、OCR)全部放到独立工作进程里,并限制这类进程的并发数为 2。宿主自身的资源被保护起来,即时后台计算再忙,检索和 UI 交互也能保持流畅。如果你也遇到类似“一跑后台任务整个界面就卡”的情况,优先检查是不是所有插件的重活都堆在同一个主进程里干了。
另一个状态问题更隐蔽:某个插件的内部状态会影响消息处理。比如 PDF 插件在解析一份损坏的文件时进入了一个异常分支,没有正常返回错误码,宿主一直等待它的响应,导致依赖这个结果的后续插件超时。解决方式是给所有查询类消息的通知加上统一的超时和重试机制,超时返回空结果而不是报错中断,同时把异常分支里的状态清理写成defer式的确保执行,避免污染下一次调用。
5.2 数据格式漂移与外部依赖变更
知识库里的数据来源五花八门,格式漂移是防不住的。上午存的是 Markdown 格式的笔记,下午从某网站剪藏来的是 HTML 转纯文本,晚上又从 PDF 里提取了一段带坐标信息的块。所有数据虽然都是“块”,但内部结构可能完全不同,这在写入知识库时很容易产生无法预估的字段缺失。
我的处理方式是引入“块类型校验”。每个块在写入前必须经过格式校验器,校验不过的数据会被拒绝入库并进入“待修复队列”。同时,我对外部依赖(比如网页正文提取库、PDF 解析库)做了抽象层,不直接引用它们的数据结构和返回值类型,而是在插件内部先转换成自己的统一格式。这样外部库升级了、字段换了,只需要改插件内部的一个适配函数,不会影响知识库核心。
我做这套抽象层确实多花了一些时间,但它带来的收益是实实在在的:有两次我更换了底层 PDF 解析库,都只用改一个适配文件,其他插件完全不知道我换了引擎。如果你做长期维护的插件集,建议从一开始就把“适配层”和“业务层”分开,否则外部依赖一变,改动会像波浪一样扩散到所有相关插件。
5.3 性能瓶颈与缓存策略
知识库条数到几千、块数到几万之后,性能问题就开始浮现了。最明显的瓶颈不在存储,而在“每次界面操作都实时计算”。比如打开知识图谱的局部视图,如果是每次都现查数据库再计算关联边,几百毫秒到几秒的延迟是家常便饭;写作插件每次敲键盘都要触发一次语义检索,同样开销不小。
我给这套系统引入了两级缓存。一级是“查询结果缓存”,同一个查询请求(指纹化后的 key)在 60 秒内直接返回缓存结果,适合写作插件的高频检索场景。二级是“图结构缓存”,知识图谱的局部视图计算出来后,只要相关条目的数据没有变更,就直接复用缓存,只有数据变更事件触发时才会刷新。
缓存最大的敌人是失效不彻底。我应对的方式是让所有数据变更都经过同一条“变更事件”通道,图谱缓存订阅了这个通道,只要某个条目有更新,涉及它的局部视图缓存全部失效重算。实践下来,这个事件的粒度控制很重要:如果所有数据变化都触发全量缓存失效,那缓存基本就没用了。我按“条目 ID + 块 ID”的粒度来分发失效事件,只清掉真正受影响的那几个缓存项。
还有个小建议:不要过度缓存。知识工作场景里,用户经常手动修改内容,如果缓存时间太长,界面显示的数据和真实数据之间有明显滞后,会非常让人困惑。我最后把默认缓存时间调成了一个很保守的值,只挡住真正高频重复的查询,而不是试图用缓存包办所有读操作。
6. 关于这套插件集的一些真实体会
做到现在,我最大的感受是:插件化的核心价值不是“灵活”这个词本身,而是它逼着你把知识工作的边界想清楚。哪些是共识底座、哪些是个性化功能、哪些是会被替换的模块,这些原本模糊的问题,在划分插件边界时无可回避。这种约束反而让系统变得更简单了,因为每次添加新功能的时候,都要先问一句:它真的是独立的插件,还是应该长在某一个现有模块上?
如果让我给刚开始做类似事情的人一个建议,我会说:先别急着写代码,先花时间定义一个你信得过的数据模型。插件可以换,协议可以改,但数据模型一旦演化得很混乱,后续所有插件都会在一个不稳定的地基上盖楼。我的数据模型从最初设计到现在只调整了两次,每一次调整都意味着所有插件都要适配,代价不小。那些一开始觉得“先跑起来再说”的草率设计,后面基本都是重写,重写的同时还很容易带出数据迁移的隐藏故障。
给想从这套方案里抄作业的人最后一个提示:从“剪藏+检索”这两个插件起步,不要在第一天就把图谱、OCR、任务联动全部铺开。知识工作的工具需要跟着真实使用习惯长出来,而不是一次性规划出来的。我先用了半年剪藏和全文检索,才逐渐发现我需要图谱和任务联动,再顺着这个需求一个一个插件地补,这样每个插件都有明确的动机和真实使用场景。反过来,如果一开始就把所有功能都装满,你大概率会在维护和噪音里迷失方向,因为连你自己都搞不清哪个插件到底是拿来干什么的。
这套knowledge-work-plugins到现在还在迭代,最近在考虑的方向是插件生态的对外接口标准化,让新插件接入时不需要了解宿主的内部实现,只需要遵循消息协议和数据模型约定。这是把个人工具推向下一个阶段的关键,也是我觉得整个插件化思路最值得持续深耕的地方。