- name
- llm-wiki
- version
- 3.6.4
- author
- sdyckjq-lab
- license
- MIT
- description
- 个人知识库构建系统(基于 Karpathy llm-wiki 方法论)。让 AI 持续构建和维护你的知识库,
支持多种素材源(网页、推特、公众号、小红书、知乎、YouTube、PDF、本地文件),
自动整理为结构化的 wiki。
触发条件:用户明确提到"知识库"、"wiki"、"llm-wiki",或要求对已初始化的知识库执行
消化、查询、健康检查等操作。不要在用户只是要求"总结这篇文章"时触发——必须是明确的
知识库相关意图。
- metadata
- {"hermes":{"tags":["knowledge-base","wiki","research","note-taking"]}}
# llm-wiki — 个人知识库构建系统
> 把碎片化的信息变成持续积累、互相链接的知识库。你只需要提供素材,AI 做所有的整理工作。
## 这个 skill 做什么
llm-wiki 帮你构建一个**持续增长的个人知识库**。它不是传统的笔记软件,而是一个让 AI 帮你维护的 wiki 系统:
- 你给素材(链接、文件、文本),AI 提取核心知识并整理成互相链接的 wiki 页面
- 知识库随着每次使用变得越来越丰富,而不是每次重新开始
- 所有内容都是本地 markdown 文件,用 Obsidian 或任何编辑器都能查看
## 核心理念
传统方式(RAG/聊天记录)的问题:每次问问题,AI 都要从头阅读原始文件,没有积累。知识库的价值在于**知识被编译一次,然后持续维护**,而不是每次重新推导。
## 快速开始
告诉用户这两步就够了:
1. **初始化**:说"帮我初始化一个知识库"
2. **添加素材**:给一个链接或文件,说"帮我消化这篇"
---
## Script Directory
Scripts located in `scripts/` subdirectory.
**Path Resolution**:
1. `SKILL_DIR` = this SKILL.md's directory
2. Script path = `${SKILL_DIR}/scripts/<script-name>`
---
## 依赖检查
核心主线(本地文件、纯文本、已有知识库操作)默认不需要这些提取依赖。
只有当用户给的是 URL 类来源,并且明确要自动提取网页 / X / 微信公众号 / YouTube / 知乎内容时,才检查以下可选依赖。
如果缺失,提示用户运行:
```bash
bash ${SKILL_DIR}/install.sh --platform <当前平台> --with-optional-adapters
```
可选依赖 skill / 工具:
- `baoyu-url-to-markdown` — 普通网页、X/Twitter、部分知乎提取
- `wechat-article-to-markdown` — 微信公众号提取
- `youtube-transcript` — YouTube 字幕提取
即使这些依赖缺失,skill 仍可工作(用户可以直接提供本地文件、粘贴文本,或改走手动入口)。
## 外挂状态模型
外挂失败统一分成 `not_installed / env_unavailable / runtime_failed / unsupported / empty_result` 五类。
所有需要枚举来源、读取 `source_label`、`raw_dir`、`adapter_name`、`fallback_hint` 的地方,都先读来源总表:
```bash
bash ${SKILL_DIR}/scripts/source-registry.sh list
```
需要拿单个来源的定义时,用:
```bash
bash ${SKILL_DIR}/scripts/source-registry.sh get <source_id>
```
对 URL 类来源,先运行:
```bash
bash ${SKILL_DIR}/scripts/adapter-state.sh check <source_id>
```
`adapter-state.sh check` 返回 8 列:
```text
source_id source_label state state_label detail recovery_action install_hint fallback_hint
```
- `not_installed`:提示用户可补安装,同时允许改走手动入口
- `env_unavailable`:说明缺少的环境条件,同时允许改走手动入口
- `runtime_failed`:说明本次提取执行失败,允许重试一次,再改走手动入口
- `unsupported`:直接给出手动入口,不尝试自动提取
- `empty_result`:说明自动提取没拿到有效内容,请用户手动补全文本
当自动提取实际执行后,再运行:
```bash
bash ${SKILL_DIR}/scripts/adapter-state.sh classify-run <source_id> <exit_code> <output_path>
```
用返回的 `detail`、`recovery_action`、`install_hint`、`fallback_hint` 生成提示。核心主线不因外挂失败而中断。
---
## 工作流路由
根据用户的意图,路由到对应的工作流:
| 用户意图关键词 | 工作流 |
|---|---|
| "初始化知识库"、"新建 wiki"、"创建知识库" | → **init** |
| URL / 文件路径 / "添加素材"、"消化"、"整理" / 直接给链接 | → **ingest** |
| "批量消化"、"把这些都整理" / 给了文件夹路径 | → **batch-ingest** |
| "关于 XX"、"查询"、"XX 是什么"、"总结一下" | → **query** |
| "给我讲讲 XX"、"深度分析 XX"、"综述 XX"、"digest XX" | → **digest** |
| "对比一下 X 和 Y"、"比较 X 和 Y"、"整理一下时间线"、"按时间排列" | → **digest**(指定格式) |
| "检查知识库"、"健康检查"、"lint" | → **lint** |
| "知识库状态"、"现在有什么"、"有多少素材" | → **status** |
| "画个知识图谱"、"看看关联图"、"graph"、"知识库地图" | → **graph** |
| "删除素材"、"remove"、"delete source"、"移除" | → **delete** |
| "结晶化"、"crystallize"、"把这个记进知识库"、"总结这段对话" | → **crystallize** |
**重要**:如果用户直接给了一个 URL 或文件,但没有明确说要做什么,默认走 **ingest** 工作流。如果知识库还不存在,先自动走 **init** 再走 **ingest**。
---
## 通用前置检查
除 `init` 外,其他工作流默认先执行这段检查:
1. 先检查**当前工作目录**是否包含 `.wiki-schema.md`
- 如果包含 → 用当前目录作为知识库根路径
- 如果不包含 → 回退到读取 `~/.llm-wiki-path`
2. 如果两者都没有:
- `ingest` / `batch-ingest` → 先运行 `init`
- `query` / `lint` / `status` / `digest` / `graph` / `delete` → 提示用户先初始化知识库
3. 读取知识库根目录下的 `.wiki-schema.md`
4. 从 `.wiki-schema.md` 的"语言"字段判断 `WIKI_LANG`
- `语言:中文` → `WIKI_LANG=zh`
- `语言:English` → `WIKI_LANG=en`
- 字段缺失 → 默认 `WIKI_LANG=zh`
## 输出语言规则
所有面向用户的输出和新写入的 wiki 内容,都按 `WIKI_LANG` 生成:
- `WIKI_LANG=zh` → 使用下文中文示例
- `WIKI_LANG=en` → 保持与中文示例相同的结构、信息量和顺序,仅改为自然英文措辞
- 文件路径、wiki 链接、目录名保持现有约定,不因为语言切换而改动
**术语对照**:
- 素材 → Source
- 实体 → Entity
- 主题 → Topic
- 摘要 → Summary
- 综合 → Synthesis
- 消化 → Ingest
- 对比 → Comparison
- 深度报告 → Deep Dive Report
- 知识图谱 → Knowledge Graph
---
## 工作流 1:init(初始化知识库)
### 前置检查(含多知识库 CWD 检查)
1. 先检查**当前工作目录**是否包含 `.wiki-schema.md`
- 如果包含 → 当前目录已经是一个知识库,提示用户已存在并询问是否要重新初始化
2. 如果当前目录没有 → 读取 `~/.llm-wiki-path` 文件
- 如果存在 → 提示用户已有一个知识库(显示路径),询问是要新建还是切换到那个
3. 两个都没有 → 进入初始化流程
### 步骤
1. **询问知识库主题**(先向用户提问):
- "你的知识库要围绕什么主题?比如'AI 学习笔记'、'产品竞品分析'、'读书笔记'"
- 如果用户没想法,默认用"我的知识库"
2. **询问知识库语言**(先向用户提问):
- "知识库内容用什么语言?中文 / English(默认中文)"
- 选项:`zh`(中文)或 `en`(English)
- 如果用户没有明确说,默认 `zh`
- 将选择记录为 `WIKI_LANG`(`zh` 或 `en`)
3. **询问保存位置**(先向用户提问):
- 默认:`~/Documents/我的知识库/`(zh)或 `~/Documents/my-wiki/`(en)
- 用户可以自定义路径
4. **运行初始化脚本**:
```bash
bash ${SKILL_DIR}/scripts/init-wiki.sh "<路径>" "<主题>"
```
5. **补充初始化结果说明**:
- `init-wiki.sh` 会同时生成 `purpose.md` 和 `.wiki-cache.json`
- `purpose.md` 和 `.wiki-schema.md` 同级存放,用来记录研究目标、关键问题和研究范围
- 提醒用户优先填写核心目标和关键问题;这些内容写在 `purpose.md` 里,后续 ingest 会优先参考这里的方向
6. **写入语言配置并本地化种子文件**:
- 将 `.wiki-schema.md` 中的 `语言:{{LANGUAGE}}` 替换为:
- `zh` → `语言:中文`(种子文件保持中文,无需额外处理)
- `en` → `语言:English`,**同时**覆写以下种子文件为英文版:
- 如果 `WIKI_LANG=en`,读取 `${SKILL_DIR}/templates/index-en-template.md`、`${SKILL_DIR}/templates/overview-en-template.md`、`${SKILL_DIR}/templates/log-en-template.md`,将 `{{DATE}}` 和 `{{TOPIC}}` 替换为实际值后,分别写入 `index.md`、`wiki/overview.md`、`log.md`
7. **记录路径**到 `~/.llm-wiki-path`:
```bash
echo "<路径>" > ~/.llm-wiki-path
```
8. **输出引导**(根据 `WIKI_LANG` 切换语言):
**中文(zh)**:
```
知识库已创建!路径:<路径>
接下来你可以:
- 给我一个链接,我会自动提取并整理(网页、X/Twitter、公众号、知乎等)
- 小红书内容请直接粘贴文本给我(暂不支持自动提取)
- 给我一个本地文件路径(PDF、Markdown 等)
- 直接粘贴文本内容
- 批量消化:给我一个文件夹路径
推荐:用 Obsidian 打开这个文件夹,可以实时看到知识库的构建效果。
```
(英文版按「输出语言规则」生成,结构相同。)
---
## 工作流 2:ingest(消化素材)
这是最核心的工作流。用户给一个素材进来,AI 做所有的整理工作。
### 前置检查
执行**通用前置检查**(见上方定义)。
### 隐私自查提示(首次进入 ingest 必须执行)
在开始提取或分析任何内容之前,AI **必须**先对用户说下面这句话,然后等待确认:
> 在开始分析这份素材前,请先快速确认里面**不**包含这些敏感内容:
>
> - 手机号码(如 138xxxxxxxx)
> - 身份证号(18 位数字)
> - API 密钥(`sk-...`、`AIzaSy...`、`OPENAI_API_KEY=`、`ANTHROPIC_API_KEY=`、`Bearer ...`)
> - 明文密码(`password=`、`passwd=`)
> - 其他你不希望进入知识库的个人信息
>
> 如果素材里有上面任何一项,请先用文本编辑器删除或脱敏后再继续。
> llm-wiki **不会**自动过滤这些内容,处理后的内容会进入你的知识库。
>
> 确认无上述内容请回复 `y`,要中止请回复 `n`。
**流程规则**:
- 用户回复 `y`(或"可以"、"继续"、"没有"等明确肯定)→ 继续执行后续步骤
- 用户回复 `n`(或"停"、"取消"等明确否定)→ 终止本次 ingest,提示用户清理后再来
- 其他不明确的回复 → 再问一次,最多两次;两次都不是明确 y/n 则终止
- **绕过规则**:如果用户在当前对话里已经明确说过"素材里没有敏感信息,直接开始",
或者用户是在 `batch-ingest` 流程中(已经在顶层确认过一次),AI 可以跳过这一步
**为什么是自查清单而不是脚本**:
- 正则在非结构化文本(聊天记录、笔记)里误报率很高,错过真的敏感词,误报无害的普通词
- 把判断权还给用户,比让脚本决定更可靠
- 对新手更友好,不会遇到看不懂的脚本报错
### 素材提取路由
根据素材类型自动路由到最佳提取方式:
**外挂前置判断**:
- URL 先调用 `bash ${SKILL_DIR}/scripts/source-registry.sh match-url "<url>"`
- 本地文件先调用 `bash ${SKILL_DIR}/scripts/source-registry.sh match-file "<path>"`
- 纯文本粘贴直接调用 `bash ${SKILL_DIR}/scripts/source-registry.sh get plain_text`
- `source-registry.sh` 返回 10 列:`source_id`、`source_label`、`source_category`、`input_mode`、`match_rule`、`raw_dir`、`adapter_name`、`dependency_name`、`dependency_type`、`fallback_hint`
- 调用 `bash ${SKILL_DIR}/scripts/adapter-state.sh check <source_id>`
- 从 `adapter-state.sh check` 的 8 列结果里读取 `state`、`detail`、`recovery_action`、`install_hint`、`fallback_hint`
- 如果 `state=not_installed` / `env_unavailable` / `unsupported` → 不调用外挂,直接按 `detail`、`recovery_action`、`install_hint`、`fallback_hint` 告诉用户下一步
- 只有返回 `available` 时,才继续自动提取
**URL 类素材**(统一走来源总表,不手写域名表):
> **Chrome 提示**(仅当 `adapter_name=baoyu-url-to-markdown` 时):
> adapter-state.sh check 会把“提取器可用”与“是否存在 9222 可复用会话”分开表达。
> 如果 check 返回 `available`,正常调用外挂;即使 detail 提示未检测到 9222,也继续执行。baoyu-url-to-markdown 会自己处理 Chrome 启动,**继续执行,不要等待用户确认**。
> 只有在你想复用当前已登录的 Chrome 会话时,才需要手动开启 9222。
> 如果提取仍然失败(通常是页面需要登录态,如 X/Twitter、知乎等),可提示用户开启调试端口复用已登录会话:`open -na "Google Chrome" --args --remote-debugging-port=9222`
- 如果 `source_category=manual_only` → 不调用外挂,直接使用 `fallback_hint`
- 如果 `adapter_name=wechat-article-to-markdown` → 执行 `wechat-article-to-markdown "<URL>"`
- 如果 `adapter_name=youtube-transcript` → 调用 `youtube-transcript`
- 如果 `adapter_name=baoyu-url-to-markdown` → 调用 `baoyu-url-to-markdown`
**本地文件**:
- 统一走 `bash ${SKILL_DIR}/scripts/source-registry.sh match-file "<path>"`
- 命中后直接读取,不调用外挂
**纯文本粘贴**:
- 统一视为 `plain_text`
- 直接使用用户提供的文本
**统一回退规则**:
- 对自动提取结果,统一运行 `bash ${SKILL_DIR}/scripts/adapter-state.sh classify-run <source_id> <exit_code> <output_path>`
- 从 `classify-run` 返回的 8 列结果里读取 `state`、`detail`、`recovery_action`、`fallback_hint`
- 如果返回 `runtime_failed` → 按 `detail`、`recovery_action`、`fallback_hint` 告诉用户“这次自动提取失败,可以先重试一次;如果还不行,就改走手动入口”
- 如果返回 `empty_result` → 按 `detail`、`recovery_action`、`fallback_hint` 告诉用户“自动提取没有拿到有效正文,请手动补全文本后继续”
- 其他状态也使用同一份返回结果,不再手写第二套回退文案
### 内容分级处理
根据素材长度和信息密度自动选择处理级别:
**判断标准**:
- 素材内容 > 1000 字 → **完整处理**
- 素材内容 <= 1000 字(短推文、小红书笔记等)→ **简化处理**
### 完整处理流程(长素材 > 1000 字)
1. **提取素材内容**:按上面的路由获取素材文本
2. **保存原始素材**到 `raw/` 对应目录:
- 根据素材类型保存到对应目录(articles/、tweets/、wechat/、xiaohongshu/、zhihu/ 等)
- 文件名格式:`{日期}-{短标题}.md`
- 如果是 URL 类素材,在文件头部记录原始 URL
**图片检测与追踪**:保存素材后,扫描内容中是否包含图片引用(`![` 或 `<img` 或 `.png`/`.jpg`/`.gif`/`.svg` URL)。如果检测到图片:
- 告诉用户:"素材包含 {N} 张图片引用。图片链接可能失效,建议手动下载到 `raw/assets/`(Obsidian 用户可在设置中绑定快捷键一键下载附件)"
- 在后续 source 页面的 frontmatter 中:
- `images`:记录检测到的图片引用数量
- `image_paths`:如果用户已将图片下载到 `raw/assets/`,用 YAML block list 格式记录路径;如果尚未下载,保持为空数组 `[]`。示例:
```yaml
image_paths:
- raw/assets/2026-01-15-fig1.png
- raw/assets/2026-01-15-fig2.jpg
```
- 不阻塞 ingest 流程,仅做提醒
- 用户后续下载图片后,可以手动更新 source 页面的 `image_paths`,或在下次 lint 时由 AI 辅助补全
3. **读取上下文**:
- 优先顺序:`purpose.md` > `.wiki-schema.md` > `index.md`
- 如果 `purpose.md` 存在,先读取其中的核心目标、关键问题和研究范围
- 用 `purpose.md` 指导后续实体、主题、关联的取舍和权重
4. **缓存检查**:
- 在进入 LLM 处理前,先运行:
```bash
bash ${SKILL_DIR}/scripts/cache.sh check “<raw 文件路径>”
```
- 如果返回 `HIT` 或 `HIT(repaired)` → 跳过本次 LLM 调用,直接读取已有 wiki 页面,并告诉用户这是”无变化,直接复用已有结果”
- `HIT(repaired)` 表示缓存自愈修复成功(上次 update 被跳过但 source 页面存在且 source_path 匹配)
- 如果返回 `MISS:<reason>` → 继续执行下面的两步流程
- `MISS:no_entry` — 首次处理此素材(正常情况)
- `MISS:hash_changed` — 素材内容有变化,需要重新处理
- `MISS:no_source` — 有缓存记录但 source 页面被删除了
- `MISS:repaired_needs_verify` — 找到同名 source 页面但 source_path 不匹配,需要重新处理以确认关联正确
5. **Step 1:结构化分析**:
- 输入:原始内容 + `purpose.md` + 现有 wiki 结构(至少读取 `index.md` 概要)
- 输出:JSON 格式的分析结果,不持久化,只在当前 ingest 流程里临时传递
- JSON 至少包含 `entities`、`topics`、`connections`
- `confidence` 是必需字段,缺失就视为格式异常并触发单步回退
```json
{
"source_summary": "一句话概括",
"entities": [{"name": "xxx", "type": "concept", "relevance": "high", "confidence": "EXTRACTED", "evidence": "原文摘录或推理依据"}],
"topics": [{"name": "xxx", "importance": "high"}],
View on GitHub