ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

OpenWiki 实战:用 Markdown 和 CLI 为 AI Agent 构建知识库

OpenWiki 实战:用 Markdown 和 CLI 为 AI Agent 构建知识库 1. 为什么大家都在聊 OpenWiki从一个真实痛点说起第一次听到 OpenWiki 这个名字是在一个做 AI Agent 开发的朋友群里。有人甩了张截图说他们团队把内部知识库从某个商业文档平台整体迁到了 OpenWiki 上迁移过程只花了两个晚上而且所有内容都是纯 Markdown 文件直接躺在 Git 仓库里。当时我的第一反应是又一个文档工具市面上 Notion、语雀、Confluence 已经够多了为什么还要折腾后来自己动手搭了一套又陆续帮两个团队做了迁移才慢慢理解这股风潮背后的逻辑。OpenWiki 本质上不是一个更好看的文档工具它解决的是一个更底层的问题当 AI Agent 开始大规模参与知识生产与消费时文档的存储格式、访问方式和版本管理方式都必须重新设计。传统文档平台的核心假设是人在浏览器里读写文档所以它们把内容锁在数据库里用富文本编辑器渲染靠 API 做集成。但现在的场景变了LangChain 写的 Agent 需要读取知识库做 RAG 检索Codex CLI、Claude CLI 这类命令行工具需要直接操作文件Markdown 作为大模型的母语格式被广泛使用Git 作为版本控制的事实标准不可替代。OpenWiki 恰好站在了这几个趋势的交汇点上——它把 Wiki 还原成一堆 Markdown 文件 一个轻量渲染层 一套 CLI 工具链让人类和 AI 都能用自己最舒服的方式访问同一份内容。这篇文章适合三类人看一是正在做 AI Agent 开发、需要给 Agent 配知识库的工程师二是团队里负责文档基建、被 Confluence 折磨过的技术负责人三是对 Markdown、CLI、LangChain 这些词眼熟但还没串起来的新手。我会从设计思路、核心细节、实操流程到踩坑经验把 OpenWiki 这套东西讲透让你看完能直接上手搭一套。2. OpenWiki 的整体设计与思路拆解2.1 它到底解决了什么问题从文档平台到文档即代码要理解 OpenWiki 为什么火得先理解传统 Wiki 的三大痛点。第一个痛点是格式锁定。你在 Notion 里写的文档导出成 Markdown 经常丢格式表格变乱码图片路径全断。你在 Confluence 里写的页面想批量迁移到别的地方得写一堆爬虫脚本。这些平台的富文本格式是私有的本质上是一种数据绑架。第二个痛点是AI 不友好。LangChain 的 Document Loader 读 Notion 要走 API读 Confluence 要走 API还要处理分页、限流、权限。而读一个本地 Markdown 文件夹一行代码DirectoryLoader(./docs, glob**/*.md)就搞定了。对于做 RAG 的人来说这个差距是数量级的。第三个痛点是版本管理缺失。文档平台自带的版本历史又慢又难用想 diff 两个版本、想回滚、想分支管理基本不可能。而 Git 天生就是干这个的。OpenWiki 的设计思路可以用一句话概括文档即代码Docs as Code。每一篇 Wiki 页面就是一个.md文件整个 Wiki 就是一个 Git 仓库渲染层只负责把 Markdown 转成网页。这个思路其实不新GitBook、Docusaurus、MkDocs 都走过这条路但 OpenWiki 的差异化在于它同时提供了面向人的 Web 界面和面向 AI 的 CLI 接口并且把两者统一在同一份文件上。提示判断一个文档工具是否AI 友好最简单的标准是——你能不能用一个cat命令读出它的全部内容。能就是友好的不能就得走 API。2.2 为什么是 Markdown大模型的母语格式Markdown 成为 OpenWiki 的默认格式不是偶然。这里有个很多人没意识到的点主流大模型的训练语料里Markdown 的占比极高。GitHub 上的 README、技术博客、Stack Overflow 的回答大量都是 Markdown。所以模型对 Markdown 的结构理解能力远强于对 HTML 或富文本 JSON 的理解。这带来一个实际好处当你把 Markdown 文档喂给 LangChain 做检索时模型能准确识别#标题层级、-列表、|表格、代码块这些结构从而更好地做分块chunking。相比之下如果你把 HTML 直接喂进去标签噪音会严重干扰检索质量。Markdown 的另一个优势是纯文本可 diff。两个版本的文档git diff一下改了什么一目了然。这对团队协作太重要了——你能看到同事到底改了哪句话而不是某某更新了此页面这种无意义提示。不过 Markdown 也有坑最典型的就是换行。标准 Markdown 里单个换行符不产生br需要行尾加两个空格或者空一行。很多新手写文档时发现我明明换行了渲染出来却连在一起就是这个原因。OpenWiki 这类工具通常会启用 GFMGitHub Flavored Markdown扩展让换行行为更符合直觉但你在写的时候还是要注意这个细节。2.3 为什么要有 CLIAgent 时代的操作入口OpenWiki 提供 CLI 工具这个设计在传统文档工具看来是倒退——都什么年代了还用命令行但如果你在做 AI Agent 开发就会明白 CLI 才是 Agent 最自然的操作界面。原因很简单Agent 通过工具调用tool calling执行操作而 CLI 命令是最容易被封装成工具的形式。你让 Agent 去创建一个新页面如果走 Web API需要处理认证、请求体格式、错误码如果走 CLI就是一句openwiki new 页面标题Agent 只要生成这行命令就行。这和 Codex CLI、Claude CLI 这类工具的流行是同一个逻辑。它们让 AI 能直接在终端里操作文件系统、执行命令、读写代码。OpenWiki 的 CLI 让 AI 能直接管理知识库这就把知识库维护这件事从人工操作变成了 Agent 可以自动完成的任务。我实测过一个场景让 Agent 每天定时扫描 Git 仓库的 commit把重要的代码变更自动整理成 Wiki 页面。整个流程就是 Agent 调用git log拿到变更调用 OpenWiki CLI 创建页面调用git commit提交。全程不需要人干预这在传统文档平台上根本做不到。2.4 和 LangChain、LangGraph 的关系知识库是 Agent 的记忆层热词里频繁出现 LangChain、LangGraph、AI Agent这不是巧合。OpenWiki 在 AI Agent 技术栈里的定位是记忆层Memory和知识层Knowledge的载体。一个完整的 Agent 系统通常包含几个部分LLM 负责推理工具Tools负责执行动作记忆Memory负责保存上下文知识库Knowledge Base负责提供领域知识。LangChain 提供了把这些组件串起来的框架LangGraph 则用图结构管理更复杂的状态流转。OpenWiki 扮演的是后两个角色。Agent 的长期记忆可以存成 Markdown 文件领域知识可以组织成 Wiki 页面检索时用 LangChain 的 VectorStore 做向量化用 Retriever 做召回。这套组合下来你就有了一个能记住事、能查资料的 Agent。这里要澄清一个常见困惑Agent、LLM、AI 模型有什么区别。LLM大语言模型是底层能力比如 DeepSeek、GPT 这些它们本质上是文字接龙的概率模型。AI 模型是更宽泛的概念包括图像模型、语音模型等。Agent 则是在 LLM 之上加了一层自主决策 工具调用的架构它能自己决定下一步做什么。OpenWiki 服务的是 Agent 这一层而不是 LLM 本身。3. 核心细节解析与实操要点3.1 目录结构设计让 Agent 和人都能找到东西OpenWiki 的目录结构设计直接决定了检索质量。我见过太多团队把文档一股脑塞进一个文件夹结果 Agent 检索时召回一堆无关内容。合理的结构应该按领域 - 主题 - 具体页面三层组织。一个我常用的结构模板是这样的wiki/ ├── index.md # 首页作为导航入口 ├── 01-产品/ │ ├── 01-需求文档/ │ │ ├── 用户登录.md │ │ └── 支付流程.md │ └── 02-设计稿/ ├── 02-技术/ │ ├── 01-架构/ │ │ └── 系统总览.md │ └── 02-API/ │ └── 接口规范.md └── 03-运维/ └── 01-部署/ └── 环境说明.md数字前缀的作用是控制排序让文件在文件管理器和侧边栏里都按预期顺序排列。这个细节看似小但对 Agent 很重要——当 Agent 按目录遍历时有序的结构能帮助它建立正确的上下文。注意目录名和文件名尽量用中文或英文避免特殊字符和空格。空格在 CLI 里需要转义会给 Agent 生成命令带来麻烦。3.2 Markdown 语法要点那些容易踩的坑写 OpenWiki 文档Markdown 语法是基本功但有几个坑几乎人人都会踩。换行问题。前面提过标准 Markdown 单换行不生效。解决办法有两个行尾加两个空格或者段落之间空一行。我推荐后者因为两个尾随空格在编辑器里看不见容易在格式化时被删掉。表格转换。Markdown 表格写起来爽但要转成 Excel 就麻烦了。热词里markdown表格转换excel搜索量很高说明这是普遍需求。我的做法是用pandoc一行命令搞定pandoc input.md -o output.xlsx反过来 Excel 转 Markdown 也行pandoc input.xlsx -o output.md。这个工具在文档格式转换上是万能的值得每个做文档的人装一个。图片路径。这是迁移时最容易出问题的地方。Markdown 里图片用![alt](path)引用path 可以是相对路径也可以是绝对路径。OpenWiki 里推荐用相对路径并且把图片放在和文档同级的assets文件夹里。这样整个仓库迁移时图片跟着走不会断链。方框和特殊符号。热词里markdown 方框指的是任务列表的复选框- [ ]和- [x]以及引用块。这些在 OpenWiki 里都能正常渲染但要注意 GFM 扩展是否开启。3.3 CLI 工具链把知识库操作变成命令OpenWiki 的 CLI 是它区别于其他 Wiki 的核心。我整理了几个高频命令这些也是 Agent 最常调用的命令作用Agent 使用场景openwiki new 标题创建新页面Agent 整理新知识时自动建页openwiki search 关键词全文检索Agent 查找已有内容避免重复openwiki serve启动本地预览开发时实时查看效果openwiki build生成静态站点部署到服务器openwiki export导出为其他格式交付给非技术同事这些命令的设计哲学是幂等和可组合。比如openwiki new如果页面已存在不会覆盖而是提示openwiki search的输出是纯文本方便管道传给其他命令。这种设计让 Agent 能安全地调用不用担心误操作。3.4 与 LangChain 集成构建本地知识库问答把 OpenWiki 接进 LangChain 做本地知识库问答是我用得最多的场景。核心代码其实很短from langchain_community.document_loaders import DirectoryLoader from langchain_text_splitters import MarkdownHeaderTextSplitter from langchain_community.vectorstores import FAISS from langchain_openai import OpenAIEmbeddings # 加载所有 Markdown 文件 loader DirectoryLoader(./wiki, glob**/*.md) docs loader.load() # 按标题层级切分保留结构信息 splitter MarkdownHeaderTextSplitter( headers_to_split_on[(#, h1), (##, h2), (###, h3)] ) chunks splitter.split_text(\n.join([d.page_content for d in docs])) # 向量化并存储 vectorstore FAISS.from_texts(chunks, OpenAIEmbeddings()) retriever vectorstore.as_retriever(search_kwargs{k: 5})这里的关键是MarkdownHeaderTextSplitter。它按标题层级切分而不是按固定字符数切分这样每个 chunk 都保留了完整的语义单元。实测下来检索准确率比朴素的RecursiveCharacterTextSplitter高不少。提示langchain和langgraph的区别经常被问。简单说LangChain 是组件库 链式编排适合线性流程LangGraph 是状态图编排适合有循环、分支、多 Agent 协作的复杂场景。做知识库问答用 LangChain 就够了做多 Agent 系统才需要 LangGraph。4. 实操过程与核心环节实现4.1 环境准备从零搭建一套 OpenWiki我以一台干净的 Linux 服务器为例走一遍完整流程。假设你已经装好了 Git 和 Node.jsOpenWiki 的渲染层通常基于 Node 生态。第一步克隆或初始化仓库mkdir my-wiki cd my-wiki git init第二步安装 OpenWiki CLI。具体安装方式取决于你用的发行版常见的是通过包管理器或直接下载二进制。装完后验证openwiki --version第三步初始化项目结构openwiki init这个命令会生成默认的目录结构和配置文件。配置文件里可以设置站点标题、主题、侧边栏顺序等。第四步启动本地预览openwiki serve --port 3000浏览器打开localhost:3000就能看到渲染后的 Wiki 了。改 Markdown 文件页面会自动刷新这个热重载体验和现代前端开发工具一致。4.2 内容迁移从旧平台搬家的实战记录迁移是最费劲的环节。我帮一个团队从 Confluence 迁移了大约 800 个页面过程分三步。第一步批量导出。Confluence 支持导出为 HTML 或 Markdown。导出后用pandoc批量转换for f in *.html; do pandoc $f -o ${f%.html}.md done第二步清洗格式。导出的 Markdown 通常很脏有大量冗余的空行、错误的标题层级、断掉的图片链接。我写了个 Python 脚本做批量清洗主要处理三件事统一标题层级、修复图片路径、删除空段落。第三步重建目录结构。导出的文件是扁平的需要按业务逻辑重新组织。这一步没法完全自动化得人工过一遍但可以用脚本先按文件名关键词做初步分类。整个迁移花了两个晚上其中清洗脚本占了一半时间。但迁移完成后团队反馈检索效率明显提升因为 Agent 能直接读文件了。4.3 接入 AI Agent让知识库自己长起来这是 OpenWiki 最有意思的玩法。我搭了一个 Agent每天做三件事自动归档。Agent 扫描团队聊天记录和邮件把有价值的技术讨论整理成 Wiki 页面。用的是 LangChain 的 Agent 框架配合 OpenWiki CLI。自动更新。Agent 监控代码仓库的 commit当某个模块的代码变更超过阈值时自动在对应的 Wiki 页面追加变更说明。自动巡检。Agent 定期检查所有 Wiki 页面找出超过 90 天未更新、或者引用了失效链接的页面生成待办清单。这套系统的核心是工具定义。给 Agent 定义的工具大概长这样from langchain.tools import tool import subprocess tool def create_wiki_page(title: str, content: str) - str: 创建一个新的 Wiki 页面 result subprocess.run( [openwiki, new, title, --content, content], capture_outputTrue, textTrue ) return result.stdout tool def search_wiki(keyword: str) - str: 在 Wiki 中搜索关键词 result subprocess.run( [openwiki, search, keyword], capture_outputTrue, textTrue ) return result.stdoutAgent 拿到这些工具后就能自主决定什么时候建页、什么时候搜索。实测下来一个中等规模的团队每周能自动产生 20-30 个有价值的 Wiki 页面人工只需要做审核。4.4 部署与协作Git 工作流怎么定OpenWiki 的协作完全依赖 Git所以工作流设计很重要。我推荐的是简化版 Git Flowmain分支稳定版本对应线上 Wikidraft分支草稿区Agent 自动生成的页面先提交到这里功能分支人工编辑大改动时用Agent 生成的页面先进draft人工审核后合并到main。这样既保证了自动化效率又有人工把关。部署方面openwiki build生成静态文件后扔到任意静态托管服务即可。因为全是静态文件CDN 加速、缓存策略都很简单访问速度比动态 Wiki 快得多。5. 常见问题与排查技巧实录5.1 检索不准Agent 找不到该找的内容这是最高频的问题。Agent 检索不到内容通常有三个原因。分块策略不对。如果你用固定字符数切分一个完整的知识点可能被切成两半检索时两边都召回不全。解决办法是用MarkdownHeaderTextSplitter按标题切分保证语义完整。关键词不匹配。用户问怎么登录文档里写的是用户认证流程字面不匹配但语义相关。这时候需要向量检索而不是关键词检索。LangChain 的VectorStoreRetriever能解决这个问题。文档太杂。一个文件夹里混了产品文档、技术文档、会议记录检索时噪音太大。解决办法是分库不同领域建不同的 VectorStore检索时按需选择。排查这类问题的技巧是先把 Agent 的检索结果打印出来看它到底召回了什么。如果召回的内容明显不相关就是分块或向量化的问题如果召回的内容相关但没被用上就是 Prompt 的问题。5.2 格式渲染异常Markdown 显示不对Markdown 渲染问题五花八门我整理了一个速查表现象原因解决换行不生效单换行符段落间空一行或行尾加两空格表格错位列数不匹配检查每行的 代码块不渲染反引号数量不对用三个反引号并标注语言图片不显示路径错误用相对路径确认文件存在列表嵌套乱缩进不一致统一用 2 或 4 空格缩进注意不同渲染器对 Markdown 的支持有差异。OpenWiki 通常支持 GFM但如果你用了某些扩展语法比如 Mermaid 图表需要确认渲染器是否开启了对应插件。热词里markdown preview mermaid support就是这个需求VS Code 里装对应插件就能预览。5.3 CLI 命令报错权限和路径问题CLI 报错最常见的是两类权限不足和路径错误。权限问题通常出现在 Agent 调用时。Agent 运行的用户可能没有仓库的写权限导致openwiki new失败。解决办法是给 Agent 单独建一个用户授予仓库目录的读写权限。路径问题多出现在相对路径上。CLI 命令如果在错误的目录下执行会找不到文件。我的习惯是在脚本开头先cd到仓库根目录或者用绝对路径。5.4 与 LangChain 集成的坑版本兼容和去重LangChain 迭代很快版本兼容是个大坑。我遇到过langchain和langchain-community版本不匹配导致导入失败的情况。建议用conda或venv建独立环境锁定版本。另一个坑是去重逻辑。热词里提到langchain 和 langchain4j 的默认 rrf 实现去重逻辑存在缺陷这是真实存在的问题。RRFReciprocal Rank Fusion是融合多路检索结果的算法默认实现可能把相似度高的重复内容都保留下来。解决办法是在检索后加一层去重按内容哈希或相似度阈值过滤。def deduplicate(docs, threshold0.9): seen [] result [] for doc in docs: if not any(similar(doc.page_content, s) threshold for s in seen): seen.append(doc.page_content) result.append(doc) return result这个函数虽然简单但能显著提升检索结果的质量。5.5 独家避坑经验那些文档里不会写的最后分享几个我踩过的坑。别把敏感信息写进 Wiki。因为 OpenWiki 是纯文本 Git一旦提交历史记录里就删不掉了。密钥、密码、内部地址这些要么用环境变量要么放在单独的私有仓库。Agent 生成的内容必须审核。我见过 Agent 把错误的代码片段写进 Wiki结果被其他同事当成正确示例用了。自动化可以提效但不能替代审核。定期做仓库瘦身。Git 仓库会随着时间膨胀尤其是频繁提交大文件时。定期用git gc清理或者用git filter-repo移除历史大文件。备份策略要独立。Git 仓库本身是分布式的但如果只存在一台服务器上还是有风险。我建议至少有一个异地备份用git clone --mirror定期同步。这套东西用下来最大的体会是OpenWiki 的价值不在于它本身多强大而在于它把知识库从封闭平台变成了开放文件。当你的知识库变成一堆 Markdown 文件AI Agent 能读、能写、能检索Git 能管版本CLI 能自动化整个知识管理的玩法就完全不一样了。我现在的习惯是任何值得记录的东西先写成 Markdown 扔进仓库剩下的交给 Agent 去整理。这种人负责创造机器负责组织的分工效率比传统方式高太多了。
返回列表