LLM Wiki
基于 Karpathy LLM Wiki 方法论,将任意来源的文章编译为持久、可查询的结构化知识库。
触发条件
使用场景:
- 用户给出一个或多个文章链接(微信公众号、博客、技术文档等),要求存入/编译进知识库
- 用户给出 GitHub 仓库链接(文档型仓库,如书籍、教程、知识库),要求整仓库摄入
- 用户给出本地文件路径,要求入库
- 用户要查询已有知识库的内容("知识库里有什么关于 X 的?")
- 用户要求对知识库做健康检查、刷新元信息、查看日志或概览
不使用场景:
- 仅下载微信文章而不编译入库 → 使用
wechat-article-down - 操作项目级
.omc/wiki/知识库 → 使用oh-my-claudecode:wiki - 普通的网页浏览或信息搜索 → 使用
web-access
调用路由
用户不需要显式指定技能名称。以下裸命令直接路由到本技能:
| 用户输入 | 路由到 | 说明 |
|---|---|---|
wiki init <路径> | llm-wiki | 指定知识库根目录,后续所有操作默认使用该路径 |
wiki ingest <URL或路径> | llm-wiki | 根据 URL 类型自动分派获取方式 |
wiki query "问题" | llm-wiki | 查询知识库 |
wiki lint | llm-wiki | 健康检查 |
wiki refresh | llm-wiki | 刷新 WIKI.md 元信息 |
wiki log | llm-wiki | 聚合操作日志 |
wiki list | llm-wiki | 精简知识概览 |
wiki evolve | llm-wiki | 更新所有已评估分类的进化档案 |
wiki evolve <分类名> | llm-wiki | 审计指定分类的覆盖度 |
wiki evolve --all | llm-wiki | 全量评估所有分类(含未评估的) |
wiki graph | llm-wiki | 部署知识图谱可视化 HTML 到知识库根目录 |
把这篇文章入库 + URL | llm-wiki | 自然语言触发 |
知识库里有什么关于X的 | llm-wiki | 自然语言查询 |
知识库评估 / 覆盖度审计 | llm-wiki | 自然语言触发 evolve |
与其他 wiki 技能的关系:
llm-wiki是统一入口,已合并wechat-wiki和article-wiki的全部能力wechat-wiki/article-wiki仍可通过/wechat-wiki或/article-wiki显式调用,但裸wiki命令统一走llm-wikioh-my-claudecode:wiki是完全不同的技能,用于项目级.omc/wiki/知识库,不会与本技能冲突
Ingest 内部路由(根据输入自动判断获取方式):
wiki ingest <来源>
│
├─ https://mp.weixin.qq.com/... → 调用 wechat-article-down 技能下载
├─ https://github.com/{owner}/{repo}... → GitHub MCP 扫描+批量读取(仅文档型仓库)
├─ https://... 或 http://...(其他) → 用 chrome-devtools 抓取网页正文
└─ 本地路径(/、~/、./) → 用 Read 工具读取文件
核心哲学
RAG 每次查询都从原文重新推导知识。LLM Wiki 不同——LLM 预先把文章读完、理解完、整合进结构化 wiki,查询时读的是已编译的笔记,不是原文。每篇新文章入库都让整个 wiki 更丰富;每个好答案存回 wiki 都成为新的知识节点。知识复利积累,不是每次重新推导。
分工:用户负责筛选文章来源、提问、判断方向;LLM 负责所有维护工作——摘要、交叉引用、归档、更新、检查矛盾。
支持的来源类型:
- 微信公众号文章(
https://mp.weixin.qq.com/...)→ 调用wechat-article-down技能下载 - GitHub 文档型仓库(
https://github.com/{owner}/{repo})→ GitHub MCP 扫描+批量读取,整仓库合并为一篇文章 - 非微信在线文章(其他
http(s)://...)→ 用 chrome-devtools 抓取 - 本地文件(
.md、.html、.txt等)→ 用 Read 工具读取
WIKI.md 的两种类型
WIKI.md 有两种 type,通过文件开头的 **类型**: 字段区分:
| 类型 | 含义 | 所在目录 |
|---|---|---|
wiki | 单个知识库的 schema | 知识库根目录(含 raw/、wiki/) |
collection | 多知识库注册表 | 包含多个知识库子目录的父目录 |
兼容旧格式:若 WIKI.md 中没有 **类型**: 字段,则通过目录结构推断——同级存在 raw/ 或 wiki/ 目录视为 type: wiki,否则检查是否有子目录含 WIKI.md 来判断是否为 collection。
Wiki-Root 定位规则(按优先级)
执行任何操作前,必须先确定 wiki-root。按以下顺序检测,命中即停:
- 用户显式指定:命令中给出了路径(如
wiki ingest ~/my-wiki ...)→ 使用该路径 - 持久化配置:检查本技能目录下的
config.json文件(即SKILL.md同级目录),若其中存在wikiRoot字段且该路径存在 → 使用该路径。此配置由wiki init设置/更新,持久保存知识库根目录 - 当前目录有 WIKI.md:读取并检查类型:
type: wiki→ 当前目录就是 wiki-root,直接使用type: collection→ 读取其中的子知识库列表:- 1 个子知识库 → 自动使用,告知用户
- 多个子知识库 → 列出让用户选择
- 用户也可选择「创建新知识库」→ 创建新子目录并注册到 collection
- 扫描子目录:当前目录无 WIKI.md,但在直接子目录中查找
*/WIKI.md:- 找到 1+ 个 → 自动创建 collection 类型的 WIKI.md 注册已有知识库(使用
references/collection-schema-template.md模板),然后按第 3 步的 collection 逻辑处理 - 找到 0 个 → 进入第 5 步
- 找到 1+ 个 → 自动创建 collection 类型的 WIKI.md 注册已有知识库(使用
- 均未命中:询问用户是要在当前目录创建新知识库(type: wiki),还是指定其他路径;确认后再初始化
关键:绝不跳过探测直接创建默认知识库。用户可能在知识库内、在 collection 目录中、或在包含知识库子目录的父目录中。
新建子知识库(在 collection 下)
在 collection 目录中创建新知识库时:
- 询问用户知识库名称和主题
- 创建子目录及
raw/、wiki/结构 - 用
references/wiki-schema-template.md生成子目录的 WIKI.md(type: wiki) - 更新父目录 WIKI.md(type: collection)的子知识库列表
目录结构
<wiki-root>/ # 按上述规则定位
├── raw/ # 原始文章(LLM 只读不写,除了初次存入)
│ └── <文章标题>/
│ ├── article.md
│ └── images/ # 文章中的图片(本地副本,仅在线文章需要)
├── wiki/ # LLM 编译生成的知识页面(LLM 全权维护)
│ ├── index.md # 内容目录:每页一行链接+摘要,查询时首先读此文件
│ ├── log.md # 操作日志:追加式,记录每次 ingest/query/lint/evolve
│ └── *.md # 各概念/主题/分析/查询存档页面
├── evolve/ # 知识进化追踪(LLM 维护)
│ ├── index.md # 总控面板:所有分类评分 + 下一步建议
│ └── <分类名>.md # 每个主题的进化档案(覆盖度评估 + 进化向量 + 日志)
├── knowledge-graph.html # 交互式知识图谱可视化(由 graph/init 命令部署)
└── WIKI.md # 知识库 schema:结构约定、工作流规则(与用户协同演化)
八种操作
Init(指定知识库目录)
将指定路径持久保存为知识库根目录,后续所有操作自动使用该路径,无需每次指定。
步骤:
- 用户提供路径(如
wiki init ~/my-wiki) - 路径验证:
- 路径不存在 → 询问用户是否创建目录结构(创建后继续)
- 路径存在但无 WIKI.md → 询问是否初始化为新知识库(按标准初始化流程创建)
- 路径存在且有 WIKI.md → 直接使用
- 写入持久化配置:将路径(绝对路径或
~开头的路径)写入本技能目录下的config.json文件(即SKILL.md同级目录),格式为{ "wikiRoot": "<路径>" } - 部署知识图谱:将本技能自带的
references/knowledge-graph.html复制到根目录(按「知识图谱部署位置规则」确定目标路径,若已存在则覆盖更新) - 输出确认:显示当前设置的知识库根目录路径、知识库基本信息(文章数、页面数等),提示用户可用浏览器打开
knowledge-graph.html查看知识图谱
后续效果:写入 config.json 后,Wiki-Root 定位规则的第 2 步会检测该文件。之后在任意目录执行 wiki ingest、wiki query 等操作时,都会自动使用该路径作为知识库根目录,无需重复指定。
Ingest(摄入编译)
用户提供文章来源(URL 或本地文件路径),获取并编译进知识库。建议逐篇摄入,保持参与感。
步骤:
-
定位 wiki-root:按「Wiki-Root 定位规则」确定路径。若已存在
WIKI.md,读取它确认结构,直接进入第 2 步;仅当确认为首次创建时才初始化——创建目录结构,读取本技能自带的references/wiki-schema-template.md,复制内容到<wiki-root>/WIKI.md,询问用户知识库主题后填入主题字段 -
获取文章内容:根据输入类型分支处理——
A. 微信公众号 URL(
https://mp.weixin.qq.com/开头):- 调用
wechat-article-down技能,指定--output <wiki-root>/raw/,使文章直接下载到raw/目录 - 已存在同名子目录则跳过
B. GitHub 仓库 URL(
https://github.com/{owner}/{repo}开头): 详见下方「GitHub 仓库 Ingest 流程」。整仓库合并为一个raw/<仓库标题>/article.md。C. 非微信在线 URL(其他
http://...或https://...,非 GitHub):- 使用
mcp__chrome-devtools__navigate_page打开页面 - 等待页面加载完成(使用
mcp__chrome-devtools__evaluate_script检查document.readyState) - 滚动页面触发懒加载(执行滚动脚本)
- 提取页面正文内容(执行提取脚本,见下方「通用网页提取脚本」)
- 从提取结果中获取标题和正文 Markdown
- 创建
raw/<标题>/article.md,写入内容(若已存在同名子目录则跳过) - 下载图片(见下方「图片下载流程」):提取正文中所有图片 URL,下载到
raw/<标题>/images/,并将 article.md 中的远程 URL 替换为本地相对路径
C. 本地文件(路径以
/、~/、./开头,或是已知存在的文件路径):- 用 Read 工具读取文件内容
- 判断格式:
.md文件:直接使用内容.html文件:提取正文文本,转为 Markdown.txt文件:直接使用内容- 其他文本格式(
.rst、.org等):转为 Markdown
- 从文件内容中提取或推断标题(优先用文件首行标题,其次用文件名)
- 创建
raw/<标题>/article.md,写入内容(若已存在同名子目录则跳过)
- 调用
-
编译知识:读取新文章
raw/*/article.md,对每篇:- 提取核心概念、观点、实体、要点
- 更新或新建
wiki/*.md页面(格式见本技能自带的references/page-format.md) - 发现矛盾用
> ⚠️ 矛盾:标注,不强行统一
-
更新 index.md:每个页面一行(链接 + 一句话摘要),按主题分组
-
追加 log.md:格式
## [YYYY-MM-DD] ingest | 文章标题,记录触及的页面列表
输入类型判断规则
| 模式 | 判定为 | 处理方式 |
|---|---|---|
https://mp.weixin.qq.com/... | 微信公众号 URL | 调用 wechat-article-down 下载 |
https://github.com/{owner}/{repo}... | GitHub 仓库 | GitHub MCP 扫描+批量读取(见下方详细流程) |
http://... 或 https://...(非微信、非 GitHub) | 通用在线 URL | 用 chrome-devtools 抓取 |
/、~/、./ 开头 | 本地文件路径 | 用 Read 工具读取 |
| 无前缀但文件存在 | 本地文件路径 | 用 Read 工具读取 |
article.md 写入格式
无论来源类型,写入 raw/<标题>/article.md 时统一格式:
---
title: 文章标题
source: 来源路径或 URL
type: wechat | web | github | local
repo: owner/repo # 仅 type: github 时填写
files: 25 # 仅 type: github 时填写,合并的文件数
ingested: YYYY-MM-DD
---
(正文 Markdown 内容)
通用网页提取脚本
在浏览器中执行以下脚本提取正文(通过 mcp__chrome-devtools__evaluate_script):
(() => {
const title = document.title || document.querySelector('h1')?.textContent || 'Untitled';
// 尝试常见正文容器
const selectors = [
'article', '[role="main"]', 'main',
'.post-content', '.article-content', '.entry-content',
'.content', '.post-body', '.article-body',
'#content', '#article', '#post-content'
];
let contentEl = null;
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el && el.textContent.trim().length > 200) {
contentEl = el;
break;
}
}
if (!contentEl) contentEl = document.body;
// 递归提取为 Markdown
function toMd(node, depth = 0) {
if (node.nodeType === 3) return node.textContent;
if (node.nodeType !== 1) return '';
const tag = node