你有没有过这样的经历?
学了一堆技术,笔记散落在各处——有道云、飞书文档、VS Code的临时文件、浏览器的书签。想用的时候找不到,找到了又不记得上下文。
Karpathy(OpenAI联合创始人、前特斯拉AI总监)最近提出了一个优雅的解法:LLM Wiki——不用向量数据库,不用传统RAG,让LLM自己维护一个Markdown知识库。
今天这篇文章,带你从零搭建一个可闭环的个人Wiki RAG系统。用Ollama本地模型,完全离线,代码不到300行。
读完你会觉得:我行了,我也能搭。
Karpathy的LLM Wiki是什么?
一句话:让LLM帮你维护一个结构化的Markdown知识库。
传统做法是这样的:
文档 → 分块 → Embedding → 向量数据库 → 检索 → LLM回答
Karpathy的做法是这样的:
raw笔记 → LLM编译 → 结构化Wiki → 直接塞给LLM
核心区别:不需要向量数据库,不需要Embedding,不需要检索管线。 LLM读一个index.md全局索引,然后按需拉取具体的Wiki文章。
优点: 零基础设施,token效率高,人可读。
缺点: 知识量大了(超过100篇),一个context window装不下索引。
我的方案:混合架构
取两者之长:
raw/ → 原始知识素材(你的笔记) wiki/ → LLM编译后的结构化文章 向量索引 → 支持大规模精准检索
Wiki层保证知识可读、可维护。 RAG检索层保证知识量大了也能精准找到。
整个系统4个命令搞定:
wiki-rag compile # 编译raw → wiki wiki-rag query "你的问题" # 查询 wiki-rag add "主题" "内容" # 添加新知识 wiki-rag compile --force # 强制重新编译
环境准备
▪ 1. 安装Ollama
# macOS brew install ollama ollama serve
▪ 2. 拉取模型
ollama pull deepseek-r1:1.5b # LLM(编译+回答) ollama pull nomic-embed-text # Embedding模型
为什么选这两个?轻量、离线、够用。 1.5B模型在MacBook上秒回,nomic-embed-text是Ollama生态最常用的Embedding模型。
▪ 3. 创建项目
mkdir wiki-rag && cd wiki-rag
创建 pyproject.toml:
[project] name = "wiki-rag" version = "0.1.0" requires-python = ">=3.10" dependencies = [ "llama-index>=0.12.0", "numpy", ]
uv sync
三层架构设计
▪ 第一层:raw/(原始素材)
放你的笔记,随便写,Markdown格式:
raw/ ├── python-decorators.md ├── docker-network.md ├── git-rebase-merge.md ├── redis-data-structures.md └── http2-vs-http1.md
▪ 第二层:wiki/(LLM编译后的结构化文章)
LLM把你的乱七八糟笔记编译成结构化的Wiki文章:
COMPILE_PROMPT = """你是一个知识整理专家。请将以下原始笔记编译为一篇结构清晰的Wiki文章。 要求: 1. 保留所有核心技术要点 2. 使用清晰的标题层级 3. 关键术语加粗 4. 保留核心代码 5. 末尾添加「一句话总结」 6. 生成3-5个标签"""
智能跳过: 用MD5哈希检测文件变化,没改动的自动跳过。
▪ 第三层:向量索引(RAG检索)
把Wiki文章分块,生成Embedding,存到本地JSON:
# 分块 → Embedding → 存储 paragraphs = [p for p in content.split("\n\n") if p.strip()] for para in paragraphs: emb = client.embeddings(model="nomic-embed-text", prompt=para) chunks.append({"text": para, "embedding": emb["embedding"]})
查询时:问题Embedding → 余弦相似度 → 取Top3 → 拼接上下文 → LLM回答。
核心代码
整个系统就一个文件 src/wiki_rag.py,不到300行。
▪ 编译:raw → wiki
def compile_raw_to_wiki(raw_file, force=False): # 1. 检查是否需要重新编译(MD5哈希) if not force and file_hash_unchanged(raw_file): return None # 跳过 # 2. 调用LLM编译 content = raw_file.read_text() resp = client.chat(model="deepseek-r1:1.5b", messages=[ {"role": "user", "content": COMPILE_PROMPT.format(content=content)} ]) # 3. 写入wiki/ wiki_path = WIKI_DIR / raw_file.name wiki_path.write_text(resp["message"]["content"])
▪ 查询:向量检索 + LLM回答
def query(question): # 1. 问题的Embedding q_emb = client.embeddings(model="nomic-embed-text", prompt=question) # 2. 余弦相似度检索Top3 scored = [(cosine_sim(q_emb, chunk["embedding"]), chunk) for chunk in index_data["chunks"]] top3 = sorted(scored, reverse=True)[:3] # 3. 拼接上下文 → LLM回答 context = "\n\n".join(chunk["text"] for _, chunk in top3) resp = client.chat(model="deepseek-r1:1.5b", messages=[ {"role": "user", "content": f"基于以下内容回答:\n{context}\n\n问题:{question}"} ]) return resp["message"]["content"]
就这么简单。 没有向量数据库,没有FAISS,没有复杂的检索管线。
跑起来
# 编译 uv run python -m src.wiki_rag compile # 📝 编译: docker-network.md ... ✅ 完成 # 📝 编译: redis-data-structures.md ... ✅ 完成 # ... # 📊 编译完成: 5 篇新编译 # 📑 索引已更新: 5 篇文章 # ✅ 向量索引构建完成: 68 个chunk # 查询 uv run python -m src.wiki_rag query "Python装饰器是什么" # 💡 回答: Python装饰器是一种高阶函数...
踩坑记录
▪ 坑1:LlamaIndex的Ollama集成502
LlamaIndex的Ollama客户端在Mac上频繁502。
解决方案: 直接用 ollama Python SDK,绕过LlamaIndex的集成层。
▪ 坑2:Ollama并发限制
Embedding请求并发太高会502。
解决方案: 逐个请求,不批量。
▪ 坑3:模型选择
9B的Qwen模型编译5篇文章就要几分钟,还经常超时。
解决方案: 用1.5B的deepseek-r1,够快够用。
扩展方向
这个MVP能跑起来后,可以往这些方向扩展:
完整代码
GitHub仓库: https://github.com/helloworldtang/wiki-rag
clone下来,装好Ollama,uv sync + compile 就能跑。
13个单元测试全通过,端到端验证成功。

不是demo,是真能用的MVP。


一句话总结
Karpathy说:知识管理正在成为AI工作流的核心成本。用LLM Wiki + RAG,你可以在本地搭建一个真正可用的个人知识库——零API费用,完全离线,数据自己掌控。
试试看,你会发现:真没那么难。