varunyn/wiki-langGraph

GitHub: varunyn/wiki-langGraph

基于 LangGraph 的 markdown 知识库管道,将原始笔记增量编译为 Obsidian 风格的互链 wiki,支持 LLM 辅助编写、语义链接、问答检索与结构化 lint。

Stars: 3 | Forks: 1

# wiki-langgraph LangGraph pipeline **摄取**原始 markdown,**编译**Obsidian 风格的 vault(wikilinks、创作的 backlinks、语义 `See also`、`Index.md`),可选运行 **LLM 编写**,支持 **query → save → future context** 复合积累,在启用时刷新本地 **[QMD](https://github.com/tobi/qmd)** 索引,并对 vault 进行 **lint**。 ## 当前功能 - 将原始 markdown 编译为生成的 Obsidian wiki。 - 通过 `compiled_from:` frontmatter 保留出处。 - 将创作的 **Backlinks** 与语义 **See also** / **Related (semantic)** 建议分开。 - 生成包含笔记元数据和图谱计数的丰富 `Index.md`。 - 支持增量 LLM 编译,可选择对现有 wiki 笔记进行扩充。 - 为生成的 LLM 候选内容添加基于风险的审查队列。 - 允许您使用 `query` 对已编译的 wiki 提问。 - 允许您使用 `research` 合成更深度的研究简报。 - 允许您将有用的答案保存在原始 `Queries/` 下,然后在未来的运行中将其编译为查询上下文。 - 可选使用 QMD 进行语义相关笔记查找和 index/embed 刷新。 - 对未解析的 wikilinks、孤立笔记、过期输出和 index 偏移进行 lint。 - 当配置的生成 wiki 目录位于原始 vault 内时,在摄取时将其排除。 ## 背景:“LLM Wiki”模式 Andrej Karpathy [在 X 上发帖](https://x.com/karpathy/status/2039805659525644595)介绍了一种工作流,其中模型不仅在提问时检索数据块(经典 RAG),而且会在您和原始来源之间**增量构建并维护一个持久的、相互链接的 markdown wiki**——因此结构和综合分析会**不断积累**,而不是在每次查询时重新推导。他在一个复制粘贴的 **idea file**([gist](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f))中扩展了这个想法。 **wiki-langgraph** 是该模式某些部分的**具体实现**:可复现的编译 pipeline、vault 链接、可选的 LLM 处理、通过 QMD 实现的可选本地搜索/embedding 以及基于规则的 lint。该 gist 有意保持抽象;本仓库固定了目录布局、env vars 和 graph 行为——有关完整的节点图和模块映射,请参见 **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)**。 ## 前置条件 | 需求 | 何时需要 | | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Python 3.12+** | 始终需要 | | **[uv](https://docs.astral.sh/uv/)** | 始终需要(安装依赖并运行 CLI) | | **兼容 OpenAI 的 HTTP API** (`WIKI_OPENAI_API_BASE`) | `query`、`research`、`WIKI_LLM_COMPILE=true`,和/或带有 `WIKI_SEMANTIC_BACKEND=llm` 的 `WIKI_SEMANTIC_LINKS=true`(例如具有 OpenAI 兼容性的 [Ollama](https://ollama.com/)、llama.cpp server、vLLM 等) | | 位于 `PATH` 中的 **[QMD](https://github.com/tobi/qmd)** | `WIKI_SEMANTIC_BACKEND=qmd` 和/或 `WIKI_QMD_REFRESH=true`(混合搜索 + 编译后的可选 `qmd embed`) | | **Obsidian** | 可选;可用作生成 vault 的阅读器/UI,运行 pipeline 不需要它 | **最小化运行:**如果您接受 repo 下 `data/raw` → `data/wiki` 的默认设置,并且不启用 LLM 编译、语义 LLM 功能或 QMD 刷新,则不需要 `.env`。任何调用 chat API 的操作都需要可访问的 base URL 和 model id。对于此最小化路径,QMD 刷新默认处于关闭状态。 ## 设置 ``` uv sync cp .env.example .env # optional; set paths and features below ``` 设置从带有 **`WIKI_`** 前缀的环境变量(以及当前工作目录中可选的 **`.env`**)加载。**`cp .env.example .env`** 是通常的起点;只需根据您的实际使用情况调整即可。 ## 运行 ``` uv run wiki-langgraph run -v uv run wiki-langgraph query "How should I debug RAG failures?" uv run wiki-langgraph query "How should I debug RAG failures?" --save uv run wiki-langgraph research "Compare RAG failures and evaluation loops" --save uv run wiki-langgraph review list uv run wiki-langgraph lint uv run wiki-langgraph version ``` ### 命令参考 | 命令 | 用途 | | --- | --- | | `wiki-langgraph run -v` | 运行 摄取 → 编译 → 可选的 QMD 刷新 → lint。 | | `wiki-langgraph query "..."` | 使用检索到的已编译 wiki 笔记回答问题。 | | `wiki-langgraph query "..." --save` | 将答案作为原始笔记保存在 `Queries/` 下,以便未来的运行可以对其进行编译。 | | `wiki-langgraph research "..."` | 从更广泛的检索到的 wiki 上下文中合成结构化的研究简报。 | | `wiki-langgraph research "..." --save` | 将简报作为原始笔记保存在 `Research/` 下,以便未来的运行可以对其进行编译。 | | `wiki-langgraph review list/show/approve/reject` | 检查并解决排队的 LLM 编译候选内容。 | | `wiki-langgraph lint` | 检查原始/wiki 健康状况而不进行编译。 | | `wiki-langgraph lint --fix --dry-run` | 预览未解析的 wikilink 清理。 | | `wiki-langgraph version` | 打印 package 版本。 | ### Lint 可捕获未解析的链接、孤立笔记和过期的 wiki 输出 `wiki-langgraph lint` 会检查原始/wiki 对是否存在以下几个高信号问题: - 摄取的原始树中未解析的 `[[wikilinks]]` - **没有传出 `[[wikilinks]]`** 的 markdown 笔记(`W_ORPHAN_NOTE`),当源语料库不完整或分割不正确时,这些笔记通常是可疑的 - 比其编译后的 wiki 输出更新的原始笔记(`W_STALE_WIKI`) - `Index.md` 与已编译的笔记目录不一致 生成的 index 笔记不受孤立笔记警告的限制。要自动清理未解析的链接: ``` uv run wiki-langgraph lint --fix --dry-run # preview: fuzzy rewrites + strip the rest uv run wiki-langgraph lint --fix # edit raw .md under WIKI_DATA_RAW_DIR uv run wiki-langgraph lint --fix --fix-mode strip # plain text only (no fuzzy rename) uv run wiki-langgraph lint --fix --fix-mode rewrite # fuzzy only; leave what is still broken ``` **`--fix`** 会更新**原始**来源:它会尝试对目录笔记标签进行**单一明确的模糊匹配**(`difflib`,可通过 `--fuzzy-cutoff` 配置),然后将任何剩余的损坏链接转换为**纯文本**(将 `[[note|alias]]` 保留为 `alias`)。重新运行 **`wiki-langgraph run`** 以使 wiki 匹配。它**不会**为指向您语料库之外的链接虚构文件——除非模糊匹配找到了接近的 vault 内名称,否则这些链接将变为纯文本。 ### 查询和保存探索 针对已编译的 wiki 提出问题: ``` uv run wiki-langgraph query "How should I debug RAG failures?" ``` `query` 命令对已编译的 wiki 笔记使用本地词法检索器,将最相关的笔记发送到配置的 chat model,并打印答案和来源笔记。添加 `--save` 以将答案写回到 `Queries/` 下的原始 vault 中: ``` uv run wiki-langgraph query "How should I debug RAG failures?" --save uv run wiki-langgraph run -v ``` 保存的原始笔记包括原始问题、生成的答案以及指向检索到的来源笔记的 wikilinks。下一次编译运行会将其变成正常的 wiki 页面,因此未来的查询可以将其用作上下文。 保存的查询布局: ``` raw vault: Queries/How should I debug RAG failures.md compiled wiki: wiki/Queries/How should I debug RAG failures.md ``` 原始的 `Queries/` 笔记是事实来源。编译后的 `wiki/Queries/` 页面是生成的输出,并且像任何其他编译的笔记一样出现在 `Index.md` 中。 ### 研究简报 当您需要更广泛的综合分析而不是简短的回答时,请使用 `research`: ``` uv run wiki-langgraph research "Compare RAG failures and evaluation loops" uv run wiki-langgraph research "Compare RAG failures and evaluation loops" --save uv run wiki-langgraph run -v ``` 研究模式使用与 `query` 相同的已编译 wiki 检索路径,但默认使用更多的来源笔记,并要求 model 提供包含摘要、发现、来源笔记、相关概念、开放问题和后续步骤的结构化简报。使用 `--save` 时,原始笔记会写入 `Research/` 下,并在下次运行时编译到 `wiki/Research/` 中,因此这些调查也会成为未来的检索上下文。 ## 配置(环境变量) 所有名称都列在 **`.env.example`** 中。以下是重要内容以及何时设置它们。 ### 路径和项目布局 | 变量 | 用途 | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `WIKI_DATA_RAW_DIR` | 要**摄取**的根文件夹(递归)。默认值:`/data/raw`。 | | `WIKI_DATA_WIKI_DIR` | **编译后的 vault** 输出。默认值:`/data/wiki`。当您的 vault 位于更大的 Obsidian 树中时设置此项;有关避免重复 `wiki/wiki/` 路径段的信息,请参见 `.env.example`。 | 如果未设置,则路径派生自 package 位置(开发时为 repo 根目录)。如果 `WIKI_DATA_WIKI_DIR` 位于 `WIKI_DATA_RAW_DIR` 内,则生成的 wiki 文件夹将从摄取和 lint 源枚举中排除,这样生成的页面就不会作为原始输入反馈回去。 ### OpenAI 兼容的 LLM (chat HTTP) | 变量 | 用途 | | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | | `WIKI_OPENAI_API_BASE` | chat completions 的 Base URL,例如 `http://127.0.0.1:11434/v1` (Ollama)。对于 `query`、`research`、`WIKI_LLM_COMPILE` 或语义 LLM 后端是**必需的**。 | | `WIKI_OPENAI_API_KEY` | 作为 API key 发送;许多本地服务器会忽略它——配置中的默认值是一个占位符。 | | `WIKI_LLM_MODEL` | 传递给 API 的 model id(例如您的 Ollama model 名称)。 | | `WIKI_LLM_REQUEST_TIMEOUT_SEC` | 每次请求的 HTTP 超时;长时间的本地生成通常需要**数百秒**。 | ### LLM “编译”(原始 → wiki markdown) | 变量 | 用途 | | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | `WIKI_LLM_COMPILE` | 如果为 `true`,则在写入 wiki 之前,通过 chat model 重写每个更改过的原始 `.md`(面向 Obsidian 的 prompt)。需要 `WIKI_OPENAI_API_BASE`。 | | `WIKI_LLM_COMPILE_INCREMENTAL` | 如果为 `true`,则仅重新编写其**原始**内容已更改的文件(默认情况下位于 `data/.wiki-langgraph/` 下的 hash manifest)。 | | `WIKI_LLM_COMPILE_ENRICH` | 如果为 `true`,当笔记已存在时,将新的原始内容**合并到现有的** wiki 笔记中,而不是完全重写。 | | `WIKI_LLM_COMPILE_MAX_WORKERS` | 用于编写的 Thread pool 大小。**默认为 `1`**:本地服务器通常一次处理一个 completion;提高此值可能会导致超时。 | | `WIKI_LLM_COMPILE_REVIEW` | `off`(默认)、`risky` 或 `all`。`risky` 会自动应用低风险的生成笔记,并将高风险候选内容排入 `data/.wiki-langgraph/candidates/` 下。 | | `WIKI_MANIFEST_PATH` | 可选的增量 hash / semantic-cache JSON 文件覆盖。在以后的运行中,已删除的笔记将从存储的 hash 和 semantic 缓存中被清除。 | 审查队列命令: ``` uv run wiki-langgraph review list uv run wiki-langgraph review show uv run wiki-langgraph review approve uv run wiki-langgraph review reject ``` 批准会将排队的 markdown 写入配置的 wiki 路径,并在 manifest 中记录原始内容的 hash,以便以后的增量运行保留已批准的编写笔记。 高风险候选内容包括现有笔记覆盖、输出为空或非常短、缺少 `compiled_from`、大幅缩小以及 wikilink 流失率高。排队的候选内容在获得批准之前不会更新 manifest 中的原始 hash,因此它们会被重试或保持可见,而不是被静默视为已完成。 ### 语义“See also” / 相关笔记 | 变量 | 用途 | | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | | `WIKI_SEMANTIC_LINKS` | 如果为 `true`,编译会建议相关笔记(与创作的 `[[wikilinks]]` 分开)。 | | `WIKI_SEMANTIC_BACKEND` | `llm`(需要 API base)或 `qmd`(本地 CLI)。 | | `WIKI_QMD_BIN`, `WIKI_QMD_COLLECTION` | 用于 `qmd query` / 刷新的 QMD 可执行文件和 collection 名称。 | | `WIKI_QMD_MIN_SCORE`, `WIKI_QMD_TOP_N`, `WIKI_QMD_CANDIDATE_LIMIT` | 调整检索质量和候选广度。 | | `WIKI_QMD_NO_RERANK`, `WIKI_QMD_QUERY_TIMEOUT_SEC` | 跳过 rer 以实现更适合 CPU 的快速查询,并调整查询超时。 | | `WIKI_QMD_CHUNK_STRATEGY` | 用于 query/embed 的 QMD chunking 模式:`regex`(默认)或 `auto`。 | ### QMD 索引刷新(编译后) | 变量 | 用途 | | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `WIKI_QMD_REFRESH` | 如果为 `true`,在写入 wiki 文件后,对已配置的 collection 运行 `qmd update` 和 `qmd embed`。**默认为 `false`**,因此最小化运行不需要 QMD;在安装并需要本地 QMD 索引时启用它。 | | `WIKI_QMD_REFRESH_TIMEOUT_SEC` | 刷新的 Subprocess 超时。 | | `WIKI_QMD_EMBED_MAX_DOCS_PER_BATCH` | 每个 `qmd embed` batch 加载的文档的可选上限。 | | `WIKI_QMD_EMBED_MAX_BATCH_MB` | 每个 `qmd embed` batch 的可选 UTF-8 MB 上限。 | | `WIKI_QMD_CPU_ONLY` | 如果为 `true`,当 Metal/GPU 在 macOS 上失败时,强制基于 node-llama-cpp 的 query/embed 工作使用 CPU。 | ### Graph 运行时 | 变量 | 用途 | | -------- | ------- | | `WIKI_GRAPH_INGEST_TIMEOUT_SEC` | 摄取节点的 LangGraph 超时。 | | `WIKI_GRAPH_COMPILE_TIMEOUT_SEC` | 编译的 LangGraph 超时,包括可选的本地 LLM 编写。默认值有意设置得较高。 | | `WIKI_GRAPH_INDEX_TIMEOUT_SEC` | index 节点的 LangGraph 超时,包括可选的 QMD 刷新/embed。 | | `WIKI_GRAPH_LINT_TIMEOUT_SEC` | vault lint 的 LangGraph 超时。 | ### Lint、日志、skills | 变量 | 用途 | | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `WIKI_LINT_ON_RUN` | 如果为 `true`,在 index 步骤之后运行与 `wiki-langgraph lint` 相同的检查;任何问题都会导致 `run` 失败并返回退出状态 **1**。 | | `WIKI_LOG_FILE`, `WIKI_LOG_LEVEL` | 可选的文件日志记录;`DEBUG` 会添加详细的编译细节。 | | `WIKI_OBSIDIAN_MARKDOWN_SKILL_PATH` | OFM 系统文本的自定义 `SKILL.md` 的可选路径;否则使用捆绑的 package skill(或者如果您添加了一个,则为 repo 级别的 `skills/obsidian-markdown/SKILL.md`)。 | 有关编译步骤和出处的语义(`compiled_from:`、backlinks 与 semantic 页脚),请参见 **docs/ARCHITECTURE.md** 和 **AGENTS.md**。 ## 链接出处 生成的 wiki 有意将三个图谱概念分开: | 部分 | 含义 | | --- | --- | | `See also` | 从此笔记到相关笔记的出站语义建议。 | | `Backlinks` | 来自其他笔记正文的入站创作链接。生成的 `See also` 块不计算在内。 | | `Related (semantic)` | 来自其他笔记的入站语义建议。这些是推荐,而不是创作的引用。 | 这种分离可防止将机器建议的相关性误认为是人类/创作的证据。 ## Deep Agents `deep_agent.create_wiki_deep_agent` 可用于批处理编译之外的 agent 工作流。它使用配置的 chat model、以项目为根的 filesystem backend、位于 `/skills/` 下的捆绑/项目 skill、存在时的 `AGENTS.md` 记忆,以及拒绝访问 `.env`、`.git`、`.codegraph` 和内部 agent 产物路径的 filesystem 权限。 主要的 CLI 查询和研究路径目前使用直接的 LangChain 流程以提高可预测性。Deep Agents 最适合未来的多步 agentic 研究、候选审查辅助和概念页面的合成。 ## 布局 | 路径 | 角色 | | --------------------- | ------------------------------------------------ | | `data/raw/` | 要摄取的源文件(默认原始根目录) | | `data/wiki/` | 编译后的 vault 输出(默认 wiki 根目录) | | `Queries/` | 使用 `query --save` 时保存的原始查询笔记 | | `Research/` | 使用 `research --save` 时保存的原始研究简报 | | `src/wiki_langgraph/` | Package(graph、节点、链接、lint、LLM hooks) | | `AGENTS.md` | 面向 agent 的项目笔记 | ## 测试 ``` uv run pytest ``` ## 许可证 [MIT](LICENSE)
标签:DLL 劫持, LangGraph, Obsidian, RAG, 大语言模型, 知识管理, 逆向工具