
1. 项目从哪来为什么我会攒出这套“知识工作插件”做知识工作的人最大的成本往往不是“找答案”而是“让答案在需要的时候能自己出现”。我长期在文档、网页、代码片段、PDF之间来回切换最烦的不是资料少而是资料明明都看过、存过真到用的时候却怎么都搜不出来。这个叫 knowledge-work-plugins 的项目就是被这种反复出现的挫败感逼出来的。它本质上不是某一个插件而是一组互相配合的插件和脚本围绕一条主线工作把零散的信息先采集进来再拆成知识卡片最后统一沉淀到本地 Markdown 文件里。听起来好像很普通但真正做下来会发现里面每一个环节都有大量“看着不难、做起来磨人”的细节。这套思路适合谁如果你是每天要读大量网页、做调研、写方案、整理学习笔记的人或者你想给自己的笔记工作流加一点自动化但不想被云服务绑架这个项目的拆解过程应该能给你一个比较完整的参考。下文的代码和方案都是我在自己的笔记本上跑通的版本工具品牌不重要思路和坑才是重点。1.1 知识工作者的真实痛点信息散落、上下文断裂我复盘了一下自己过去半年的工作习惯发现最消耗精力的动作不是思考而是“上下文重建”。早上看到一篇好文章存进书签下午读到一个关键数据随手贴在某个文档里晚上又翻到一个不错的代码片段复制进本地文件。看起来每个动作都很便宜但等到周末想把这些东西串成方案时才知道麻烦在哪书签里没有正文文档里没有来源代码片段没有当时的场景说明。这也是我把项目命名为 knowledge-work-plugins 的原因。我要的不是“又一个收藏工具”而是一条能把采集、加工、存储、输出串起来的生产线。每个插件只解决一个环节但它们共享一套文件格式和标签规则合起来才能把碎片信息重新变成可复用的知识资产。1.2 设计目标降低采集成本提高复用效率立项时我给自己定了三条硬指标采集动作不超过两次点击否则不会坚持用。所有产出必须落到本地纯文本保证长期可迁移。每个知识卡片必须保留来源否则无法追溯。这三条看着简单实际决定了后面所有技术选型。比如为什么用本地 Markdown 而不是某个云笔记因为纯文本可以被检索、被脚本处理、被其他工具读取不绑定任何平台。为什么一定要保留来源因为知识卡片脱离了出处就只剩“感觉正确”没法验证。2. 整体设计四层结构而不是单个大而全的工具很多人的第一反应是找一个“全家桶”工具把剪藏、笔记、任务管理全包了。我试过类似方案最后都被两个问题卡住一是数据格式封闭想导出很痛苦二是功能越多学习成本越高最后连剪藏都懒得用。所以 knowledge-work-plugins 从一开始就按分层来设计。它不是一个大插件而是四个相对独立的模块组合。2.1 采集层网页剪藏与高亮批注采集层负责把网页以干净的 Markdown 或 HTML 快照保存下来同时保留 URL、标题、作者、发布时间等元信息。这里最大的坑是网页正文提取很多网页有大量导航、广告、推荐位粗暴抓取会把正文淹没。我的做法是优先使用“阅读模式”的解析结果拿不到再用自定义的抽取规则。具体来说我会先尝试从 DOM 里找 article / main 标签如果找不到再退回到常见的正文区块特征比如段落密度、标题层级。这一层不追求完美能拿到 80% 的干净正文就足够剩下的人工修一下成本也不高。2.2 加工层AI 摘要、标签与卡片化剪藏只是第一步真正的价值密度提升发生在加工层。我接入了一个通用大模型接口对保存的文章做两件事生成一段 100-150 字的中文摘要并提取 3-5 个关键词。摘要不需要“总结全文”只需要回答一个问题这篇文章和我的知识体系有什么关系关键词也不是随便给的。我会在 prompt 里明确要求标签必须来自预置标签库如果库里没有合适标签才允许提出新词。这样做的原因是标签一旦失控最后就会变成垃圾堆还不如不标。2.3 存储层统一收件箱 Markdown 卡片加工完之后内容会落到一个统一的“收件箱”目录然后按日期生成 Markdown 文件。每个文件包含 front matter标题、来源、时间、标签、摘要和正文。这里的核心原则是先统一收件不要急着分类。分类应该在周复盘或检索时做而不是在采集时做。因为人在采集时对内容的判断往往是最不准的。我见过太多人包括以前的我自己剪藏时觉得“这个以后肯定有用”然后精心放到某个二级分类里结果从此再也想不起来。把整理动作推迟到使用场景中做才是合理的顺序。2.4 输出层聚合周报、反向链接与一键检索最后是输出也是让整个系统“活起来”的关键。我写了一个脚本每周自动扫描收件箱按标签聚合成一份“本周输入清单”顺带列出那些几个月没被碰过的“死卡片”。输出层还做了反向链接卡片 A 引用了卡片 B就在 B 的文件里自动追加一条引用记录。这个设计是为了解决知识工作最隐蔽的问题大多数笔记系统只记录“存进去了”但不知道“用过没有”。加了反向链接和未访问时间统计之后我每周能看到哪些输入真正在影响我的输出哪些只是在角落里吃灰。3. 实操拆解每个模块怎么实现理论讲再多不如直接看实现。下面我把各模块的核心逻辑和一些关键代码/配置贴出来。注意这不是唯一正确的方案只是我踩过不少坑之后沉淀下来的版本。3.1 剪藏插件的核心实现manifest 配置与内容抽取我用的是基于标准浏览器扩展机制的方案核心入口就是 manifest.json。以下是一个最小可用配置{ manifest_version: 3, name: Knowledge Work Clipper, version: 1.0.0, permissions: [activeTab, scripting, storage], host_permissions: [all_urls], action: { default_popup: popup.html }, background: { service_worker: background.js } }关键权限只有三个。activeTab 允许我在用户点击扩展图标时读取当前页面scripting 允许我注入内容脚本以抽取正文storage 用来临时保存抽取结果。如果只是做剪藏不需要申请 unlimitedStorage 这种大权限权限越少上架审核和用户信任都会更顺利。正文抽取我封装了一个函数核心逻辑是“先找语意标签再退回到段落密度评分”function extractMainContent(doc) { let candidates doc.querySelectorAll(article, main [rolemain], .post-content, .article-content); if (candidates.length 0) { return candidates[0].cloneNode(true); } // 退回按段落密度评分 let paragraphs doc.querySelectorAll(p); let best null; let bestScore 0; paragraphs.forEach(p { let text p.innerText.trim(); if (text.length 80) return; let score text.length (p.closest(section, div) ? 10 : 0); if (score bestScore) { bestScore score; best p.parentElement; } }); return best; }这里最容易被忽略的是抽取后一定要把 script/style/noscript 节点全部去掉否则存下来的 Markdown 会被一堆 JS 文本污染。我最初没做这一步导致很多页面导出后出现大段乱码后来统一加了 cleanNode 逻辑才解决。3.2 高亮批注与本地缓存的同步机制剪藏之后我还会对文章里的关键段落做高亮。高亮不是存一个截图而是记录选中文本加上它所在的 CSS Selector。存储结构大概是这样{ articleId: 20250607-001, highlights: [ { text: 知识管理的核心不是收藏而是提取后再次连接, selector: body main p:nth-of-type(3), note: 这句话可以用于方案引言, createdAt: 2025-06-07T10:20:00Z } ] }有了 CSS Selector我就能在下次打开同一篇文章时重新定位高亮位置。不过 Selector 很容易因为网页改版而失效所以我在保存正文时同时存了一份文本快照失效时还能靠“文本匹配”兜底。同步机制上我没有用远程服务器而是借助浏览器本地存储加导出按钮。原因很简单知识数据属于我自己的资产不想为了云端同步引入额外风险。3.3 AI 摘要模块Prompt 模板与降噪设计摘要模块是整个项目里最“玄学”的部分因为模型输出不稳定。我的方案不是换更强模型而是用固定 prompt 模板和输出约束来降低不确定性。下面是我目前在用的模板你是一个知识管理助手。请用不超过150字的中文摘要回答 1. 这篇文章主要解决了什么问题 2. 它给出的关键方法或结论是什么 3. 它有什么值得注意的局限 要求 - 不要使用“本文”“作者”等空洞指代。 - 不要罗列章节结构。 - 输出为三行每行以 [问题]/[方法]/[局限] 开头。你会发现我刻意要求模型输出三行固定结构。这样做的直接好处是后续脚本可以按行解析直接写入 Markdown front matter不需要处理一堆自由文本。如果模型偶尔输出乱格式我就在解析前加一个“格式修正”的兜底函数比如按“ [问题] ”重新切分字符串。把模型当不稳定组件处理是知识工作自动化里很关键的心态。3.4 标签体系与本地文件组织方式标签是知识库的骨架。我的规则很简单由一个「标签表」文件集中管理所有合法标签格式如下# tags.yaml tags: - ai-basics - productivity - tool-review - frontend - reading-notes新增标签时先过一遍刚采集的文章是否能用已有标签覆盖实在覆盖不了再在 tags.yaml 里追加。这种“先查表、后新增”的顺序看起来多一个动作实际能避免标签失控。我在脚本里也加了一个校验如果 AI 返回的标签不在表里就把它放到 candidate 字段而不是直接写入正式标签。文件组织上我按“来源 日期”命名inbox/ 2025-06/ 2025-06-07-web-productivity-001.md 2025-06-07-web-productivity-002.md ...前端 front matter 长这样--- title: 如何设计一套可积累的知识工作流 url: https://example.com/article/123 source: web tags: [productivity, tool-review] summary: 这套流程把采集、卡片化、周复盘串成一条流水线关键在于延迟分类。 created: 2025-06-07T10:20:00Z aliases: [] ---这个结构的好处是任何支持 front matter 的工具都能直接读取不依赖我的插件。要迁移到别的笔记工具只需要把 Markdown 文件复制过去元数据不会丢。3.5 周报聚合与反向链接的实现思路周报聚合我写了一个 Python 脚本扫描收件箱并生成一个 README 文件。脚本的核心逻辑大致是def aggregate_weekly(inbox_path, output_path): notes load_markdown_files(inbox_path) by_tag defaultdict(list) for note in notes: for tag in note.tags: by_tag[tag].append(note) with open(output_path, w, encodingutf-8) as f: f.write(# 周度输入复盘\n\n) for tag, items in by_tag.items(): f.write(f## {tag}\n) for item in items: f.write(f- [{item.title}]({item.url}) — {item.summary}\n)反向链接更简单不需要图谱引擎只需要在写入卡片时扫描所有卡片正文找到“[[链接]]”或“引用卡片ID”然后在目标卡片末尾追加“被以下卡片引用”列表。将图谱下放成“引用列表”既有追踪能力又不会把系统搞复杂。4. 常见问题与排查实录任何自动化流程最后拼的都是稳定性。这里记录几个我真实踩过的坑。4.1 网页剪藏后 Markdown 正文乱码或混入导航文本这个问题大概率出在正文抽取阶段。优先检查抽取函数是不是把 script、style、noscript 标签保留下来了。另外有些网页是“懒加载”渲染正文在滚动后才出现这时 clipper 采集到的可能是空白。解决方法是在注入脚本里先尝试滚动页面到底部等待 1-2 秒再抽取。这个方法不算优雅但对大部分内容站有效。更稳妥的方案是用阅读模式内核或者直接解析 RSS/JSON-LD 元数据。4.2 AI 摘要不稳定内容被“创造性发挥”大模型有时候会给原文没有的结论这对知识库来说是致命的。我的对策有两个一是 prompt 里明确“只能基于原文不可联想”二是在摘要输出后做一次一致性校验把摘要里的数字、人名、专有名词和原文比对不一致就重新生成。校验函数不复杂但很有用def verify_facts(summary, original_text): key_phrases extract_named_entities(summary) missing [p for p in key_phrases if p not in original_text] return len(missing) 0当然这个校验是启发式的做不到百分百但能把“一本正经胡说八道”的概率降到一个可以接受的范围。4.3 Markdown 文件冲突与重复入库因为采集动作太顺手我很可能对同一篇文章剪藏两次。重复的坏处不只是占用空间还会让反向链接统计失真。我在入库前会算 URL 的哈希值作为 articleId重复 URL 直接跳过。如果正文相同但 URL 不同再用正文前 80 字的哈希做二次去重。冲突处理上我坚持“不自动覆盖”。如果检测到同一个 articleId会生成一个带时间戳的新文件并提示手工合并。这样做虽然多了一个动作但避免了自动化误删带来的更大麻烦。4.4 插件权限与隐私如何做到尽量克制在浏览器插件开发里权限越大越容易被平台审核盯上也越容易让用户警觉。我最后留的权限只有 activeTab、scripting、storage。所有数据处理都在本地完成唯一的外部请求是大模型接口而且我是通过一个本地代理脚本调用的扩展本身不直接持有 API Key。这个小决策很重要。很多插件把 key 硬编码在扩展包里用户一审查就崩了。放到本地脚本里至少能控制密钥的暴露面也方便在需要时切换服务商。5. 踩过几轮坑之后我的几点心得写到这里我想把自己最想说的几条经验放到最后不算总结就是真实使用后的体感。5.1 流程比工具重要采集成本永远是第一位知识管理工具不是越多越好而是“采集动作越少越好”。如果用一个新工具需要先想“该放到哪个文件夹”它注定会被放弃。我后来把所有入口都收敛到同一个小面板上点击即存体验才终于顺畅。任何自动化设计都要先问一句这个动作放在流程的哪个位置最不会被打断5.2 标签体系要设置“更新流程”而不是追求“初始完美规则”早期我把标签分类设计得很精细结果维护成本极高。后来改成“先粗放每周复盘时剪枝”系统反而稳定运行了大半年。标签是否合理不是设计出来的是用出来的。每周看一眼哪些标签没有新增内容、哪些标签长得太像及时合并或删除比一开始就规划好二十个分类更可持续。5.3 自动化不是替代判断而是把判断放到更重要的位置上知识自动化的价值不在于省掉所有人工操作而在于把人工操作放到更重要的判断上。AI 帮我生成摘要、归档、聚合周报但最终“这条信息要不要进入我的长期知识库”仍然是我自己来点确认。把判断权留给自己是知识工作自动化最容易被忽略的底线。如果你也在做类似的东西建议一开始别追求完整全家桶先把手里的“采集-存储-检索”这条最小闭环跑通再慢慢叠加 AI 摘要和反向链接。知识工作这件事从来都不是工具的问题而是流程的问题。工具只是把流程固化下来让你有更多精力去思考真正重要的部分。