这项目名字看着简单,但背后其实挺有文章。llm_wiki,字面意思就是“面向大语言模型(Large Language Model)的个人知识库”,但如果你真把它当成一个普通的收藏夹或者笔记本来做,那大概率会在三个月后彻底吃灰。这年头大模型相关的论文、仓库、工具、框架更新速度堪比坐火箭,今天还在用LangChain,明天冒出个Dify,后天LlamaIndex 又发新版了。靠刷社交媒体和收藏网页来跟踪,不是在骗自己,就是在制造焦虑。
我当时决定搞这个知识库,目标很明确:不是做第二个搜索引擎,而是给“我的知识体系”盖一栋有结构的房子。我要的是翻出一条记录时,能顺藤摸瓜找出一整条知识链路。这篇文章就把整个项目的搭建思路、目录设计、内容沉淀方法以及踩过的坑全部摊开讲,希望能给也在搭同类知识库的人一点参考。
1. 项目整体设计思路:为什么不是博客、也不是手机备忘录
差不多每个接触LLM一段时间的人都会经历这么个阶段:收藏了上百个GitHub链接,微信里飘着几十个“文件传输助手”里的资料PDF,浏览器书签里躺着一堆“干货”。但真正要查某一个概念的时候,脑子完全抓瞎。尤其是大模型这行,很多东西你只在零散的碎片里听说过,比如LoRA到底怎么调参、KV Cache是干嘛的、vLLM和TGI有什么区别,如果不系统理一遍,上手项目时就是到处碰壁。
llm_wiki的定位就是解决这个信息碎片化问题。它更像是一套有目录、有索引、有交叉引用的个人技术百科,而不是时间线的博客,更不是随手记的备忘录。
1.1 需求清单:我在动手之前列的几条硬性要求
第一个要求是可检索。我脑子里常常只有一半的关键词,比如说“那个显存占用很低的量化方案叫什么来着”,我需要一个能通过“量化、显存、推理速度”这种模糊词快速定位到对应文档的机制。
第二个要求是可交叉跳转。大模型知识是个网络,不是树状目录。微调离不开模型架构,部署离不开量化,量化又依赖模型架构的知识。所以wiki里的每一条核心概念都要能和其他条目互相链接,像维基百科那样点来点去。
第三个要求是可版本化。模型知识变化太快,今天写的结论可能一个月后就过时了。我需要给每条笔记加状态标记,比如“已验证”“待验证”“已过时”,能追踪到哪些内容需要定期更新。
第四个要求是低调轻量。我不想要一个特别重型的在线文档系统,登录、权限、富文本编辑这些统统不需要。打开就能写,保存就走人,最好所有数据都在本地文件里,想备份就拷走,想迁移就打包。
1.2 方案选型:我为什么放弃了Notion、语雀和Confluence
做方案选型的时候,我先把市面上流行的笔记和wiki工具过了一遍。Notion确实是很多人的首选,块编辑器、数据库视图、多端同步都很漂亮,但我个人受不了两个点:一是所有内容都存在云端,虽然方便但总觉得不踏实,尤其项目里有不少实验记录和内部信息,能本地存就本地存;二是Notion的数据库功能其实挺笨重的,你要建一套好用的知识索引,得花不少心思去维护那张表。
语雀的情况类似,富文本体验好,但国内平台的商业化氛围越来越重,而且我并不需要那么强的在文档里画表格、搞视图的能力。Confluence更不用说了,那是给团队协作用的,功能强但对个人维护来讲太重了,启动一个服务就够麻烦的。
最后我选择了本地Markdown文件 + Git版本控制的组合。所有内容就是一个普通文件夹,里面是一堆.md纯文本文件,用 VS Code 写,用 Git 做版本管理,可以推到 GitHub 私有仓库做异地备份。如果你想更顺手一点,也可以用 Obsidian 或者思源笔记这些支持 Markdown 的本地笔记工具打开同一个文件夹,直接获得图谱视图和双链能力。我的选择是 Obsidian + Git,因为Obsidian对双链的支持不用等待计算,感知速度快,体验非常接近本地方案。
之所以咬死本地化的方案,核心原因就一个:知识库是给自己用的,不是给平台交租金的。纯文本文件是最后一道防线,无论未来哪个工具跑路或者不维护了,我手里的
.md文件依然是干干净净的知识资产,随时可以迁移到任何新工具里。
1.3 内容组织逻辑:让wiki像维基百科,而不是文件夹摆件
目录设计是整个llm_wiki最核心的一步。我第一版设计是纯按照技术方向分的,比如模型架构一个文件夹、微调一个文件夹、推理部署一个文件夹。用着用着发现一个大问题:LLM的知识很难严格划分边界。一篇讲RAG的文章可能同时涉及向量数据库、Embedding模型、Prompt工程和上下文窗口管理。如果只按单个主题归档,查找的时候总会漏掉那些“既算A又算B”的内容。
所以我在文件目录之上引入了一个标签系统。每篇文档的头部都有一小块YAML格式的元信息,记录这篇文档属于哪些主题、状态是什么、关联了哪些文档。
--- title: LoRA低秩适配微调实战 tags: [微调, 参数高效微调, LoRA, 显存优化] status: 已验证 date: 2024-05-12 related: - 大模型显存估算 - QLoRA量化微调 - PEFT参数高效微调 ---这种做法效果立竿见影,因为LLM的知识管理本来就不应该是树状的,而是网状的。树状目录负责“放东西”,标签和链接负责“找东西”。目录结构再合理,它也只是一个固定的视角,而标签系统允许我从多个维度切入同一篇内容。比如我想找“在消费级显卡上微调7B模型”的笔记,我既可以点进“微调”目录去翻,也可以直接搜标签“显存优化”,两条路都能到达正确的地方。
2. 目录结构与知识分类:从顶层设计到落地细节
目录设计不能拍脑袋,我花了一整个下午把当时脑子里所有和LLM相关的知识点列出来,然后又拿关键词做了一遍头脑风暴,最后合并、分组,得到了一个相对稳定的顶层结构。
llm_wiki/ ├── concepts/ # 基础概念:凡是理解任何话题前必须知道的东西 ├── models/ # 模型档案:用过的、想用的、需要对比的开源模型 ├── finetune/ # 微调与对齐:数据准备、训练参数、代码模板 ├── inference/ # 推理与部署:量化、服务化、显存调优 ├── frameworks/ # 应用框架与工具链 ├── prompts/ # Prompt工程与提示设计模式 ├── papers/ # 论文阅读笔记 ├── projects/ # 自己做的实验、踩坑的完整记录 ├── resources/ # 聚合类资源,比如数据集列表、代码仓库清单 └── templates/ # 各类文档的创建模板2.1 各目录的边界与核心定位
concepts是整棵树的根。像Token与分词、注意力机制、上下文窗口、RLHF、KV Cache、温度参数等等这种所有地方都会用到的基础语义,全放在这里。每篇文档要求写明白“一句话解释”和“快速理解的类比”,剩下的空间留给更深入的展开。比如KV Cache那一篇的“一句话解释”我写的是:“在自回归生成时把历史词元的键值向量缓存下来,避免每生成一个token就把整个历史的attention重新算一遍。”当你把这一句话记住,后面看任何跟推理加速相关的工具时都会觉得亲切。
models是模型档案库,每发布一个用过或研究过的新模型就新建一个文件,内容里写清楚参数量、上下文窗口、架构特点、适合的任务类型、许可证、显存占用实测、微调和推理时的表现。不写任何主观吹捧,只记录事实和我实际跑出来的数据。
finetune是记录我实际做过的微调实验和看过的微调教程笔记。什么时候用全参微调,什么时候用LoRA,数据清洗怎么做,learning rate大概设多少,训练loss不降怎么办,这些全都是拿真金白银的电费和显卡堆出来的经验,写下来一方面防止自己重复踩坑,另一方面也是给未来项目攒一份内部参考手册。
inference单独拉出来是因为我发现太多人卡在“模型训练好了,但根本装不进推理环境”这道坎上。这个目录专门记录从huggingface的transformers代码跑通到vLLM高并发部署之间的所有环节,包括量化工具选型、pytorch版本兼容性坑、显存估算公式,以及如何把一个7B模型从FP16压到INT4之后,在多轮对话场景下还能保持不掉链子。
frameworks覆盖的是LangChain、LlamaIndex、Dify、Ollama、FastAPI等应用层工具。我没有按工具官方文档的说明书往里面抄,而是用“我用它解决了一个什么问题”的视角来写。
papers是我克制了自己的收藏癖之后保留的论文阅读笔记。只记两类:一是经典里程碑,二是引起我强烈兴趣的前沿工作。每篇笔记不超过500字,重点回答三个问题:这篇论文解决什么问题?核心方法是什么?如果我要复现,最棘手的点在哪?
projects则是我自己动手的实验全流程记录,从目标、方案、遇到的具体报错、最后的结果,全部按时间线组织。经验告诉我们,能复现自己两年前的实验步骤比什么文档都有价值。
2.2 自定义模板:让每篇文档都长一个样
建库初期我就发现,如果没有模板,写着写着就会变成一坨自由的流水账,一篇20行一篇500行,侧重点完全不一致。后来我在templates文件夹里放了几套模板,每建新需求就从对应模板复制一份,这样保证了不同时间写的笔记从结构上保持统一。
比如模型档案模板大致长这样:
# 模型名称(发布时间) ## 一句话总结 在什么场景下选用这个模型 ## 基础信息 - 参数量: - 架构: - 上下文长度: - 训练数据规模: - 许可证: - 显存实测(加载/推理): ## 实测结论 推理速度、量化表现、输出质量,与同级别模型的对比 ## 适合场景与不适合场景 ## 参考资源链接这类模板最重要的是把“客观事实”和“个人结论”分成两个不同区块,客观事实部分方便快速比较,个人结论部分则是在真实项目中积累下来的隐形知识。
2.3 索引与导航:从Home页开始的一网打尽
顶层目录下面全是文件夹,直接打开只能看到一个一个的文件名,缺少一张能统领全库的“地图”。因此我在根目录维护一个HOME.md,里面不只是列目录,而是围绕“学习路径”组织了一套导航:
- 如果你是大模型新手,先看concepts下基础概念的前5篇,然后转prompts,最后再看inference。
- 如果你想做微调,走“concepts → finetune → projects/xx微调实验”这条链路。
- 如果你是来做Agent应用,直接进frameworks看LangChain和LlamaIndex两篇,再结合prompts里的结构化输出套路。
这张导航表不需要死板地维护,而是随着知识库内容的沉淀不断演进。但它有一项铁律:Home页上出现的每一个链接,都必须保证是当前最新版本的位置。否则新手一进来就点了个过时的文档,整个wiki的信任度瞬间归零。
3. 核心板块的内容沉淀:怎么让wiki真正值钱
一个wiki的价值不在目录有多精致,而在每一条记录本身够不够深、够不够实。前面说了,整个库的灵魂板块是models、finetune、inference这三个,下面分别讲讲我是怎么往这几个板块填内容的。
3.1 模型档案:用统一的档案模板沉淀实测数据
模型档案是llm_wiki里频率最高的板块。每有开源模型发布,我会第一时间申请权重或者从ModelScope把模型拉到本地,然后按模板跑完一轮“体检”,把数据填进档案。
实测下来,一份合格的模型档案至少应该包含以下维度:
| 维度 | 具体内容 | 对项目的价值 |
|---|---|---|
| 模型大小 | 参数量、FP16权重体积、量化后体积 | 判断部署方式 |
| 上下文窗口 | 原生支持长度、外推后的有效长度 | 决定任务输入长度设计 |
| 推理资源 | 实测峰值显存、单token延迟 | 预估部署成本 |
| 输出质量 | 中英文效果、代码能力、数学能力 | 任务选型比较 |
| 生态兼容 | transformers是否支持、vLLM是否支持 | 影响工程落地周期 |
| 许可证 | 商用限制、归属权 | 决定项目能否上线商用 |
举一个实际案例,比如我之前记录Qwen2.5-7B-Instruct的时候,填了这样一组数据:参数量7.6B,FP16权重约15GB,在24G显卡上FP16加载时峰值显存约16.1GB,如果做INT4 AWQ量化后压到约5.6GB,可以在16G显卡上流畅跑多轮对话。单token延迟在vLLM下约18ms/token(输入512长度,batch=8),在Ollama默认配置下约30ms/token。这些数据来自我自己跑的一次压测,虽然不一定对每个人每块卡都精确,但有同一标准的实测数据,至少在做模型选型时有了一份置信度高的内部参考资料。
3.2 微调笔记:把每次实验都变成可复用的工序
微调是整个LLM领域里“文档离实操最远”的部分。官方教程只会告诉你跑训练脚本,却不告诉你数据要处理成什么格式、LoRA的r和alpha到底怎么配、学习率从多少开始试。我的finetune目录就是为了打破这种信息差而存在的。
每篇微调笔记我都要求自己按这样的流程来写:先明确一个具体的业务问题,比如“给客服场景做一个意图分类模型,只有2000条标注数据”。然后写清楚我选了哪个基座模型、用LoRA还是QLoRA、挂载到哪些模块上(比如q_proj、v_proj)、训练参数是多少、跑了多少个epoch、loss曲线最后长什么样、在验证集上的指标表现。最重要的部分是“显存与参数”的计算记录。
比如用QLoRA微调7B模型,我记录的是这样的数据:基础模型加载使用NF4量化,大概占显存6-7GB;LoRA适配器本身很小,只占1-2GB;梯度checkpointing打开之后,序列长度2048时的batch size可以开到2,算上优化器状态和激活值,总共在14GB左右能跑起来。这套数字对我后期规划显卡资源极其关键,不用再靠猜。
记录loss曲线也特别重要。很多新手一看到loss不降就慌,有经验之后你会发现,正常LoRA训练的loss在大概前200步下降速度很快,然后进入一个平台期,如果加大学习率会出现剧烈震荡,说明已经过拟合或者数据质量有问题。把这些常态现象写进笔记里,以后再遇到类似情况只需要翻一下之前的记录就能快速定位。
3.3 推理部署记录:显存估算和量化选择的实证
推理部署的痛点永远是两个——显存不够用、吞吐上不去。inference目录里我的第一篇核心文档是“大模型推理显存估算方法”。
显存占用主要包括四块:模型权重、KV Cache、激活值、临时buffer。公式不复杂:模型权重显存大约等于参数量乘以精度字节数,7B模型FP16就是7×2=14GB,INT8就减半到7GB,INT4再减半到约3.5GB;KV Cache则与序列长度、层数、头数、batch size直接相关,公式为2 × 层数 × 注意力头数 × 每头维度 × 序列长度 × 批次大小 × 字节数。我一般直接使用一个粗略的经验值:7B模型,序列长度2048、batch=8时,KV Cache大概占2-4GB。把这些数据和vLLM、Ollama的实测结果放在同一篇笔记里,部署新项目时直接照着选方案就行。
量化工具的选型记录也是这块的重头戏。我试过GPTQ、AWQ、GGUF(主要通过llama.cpp和Ollama使用),也试过FP8。实测下来的结论是:如果追求吞吐量和并发,AWQ对vLLM的支持更顺滑;如果追求方便性和多端部署,GGUF更简单直接。但不管选哪种,都要在笔记里记录量化后的困惑度变化和下游任务表现,防止“为了量化而量化”。
4. 实操过程:从“采集”到“沉淀”的日常维护工作流
结构搭好了,内容也陆陆续续填了一些,接下来的大问题是怎么让这套系统持续运转。很多人搭个人知识库最大的失败原因不是没结构,而是缺乏一个持续的输入输出循环。我这里分享一套自己跑了半年多的工作流。
4.1 信息采集:把“刷到有用的”变成“流进待整理池”
我每天会在各种渠道刷到大模型相关的信息——公众号文章、推特上的论文解读、GitHub Trending仓库、微信群里的讨论。以前的做法是收藏、点星、转发保存,基本属于“存完就忘”。现在的做法是建立了一个统一的“待整理池”。
方法很朴素:在本地wiki文件夹的根目录下放一个inbox/目录,也叫收件箱。任何看到的信息,如果在30秒内判断为“值得沉淀”,就立刻在收件箱里新建一个卡片.md文件,只要几行字,不要多写,可以是一段链接、两三个关键句、甚至一个待完善大纲。
举例来说,我在逛某个技术社区时看到一篇关于“RAG的引文召回怎么解决上下文覆盖不全”的分析,当时没时间细读,就在inbox里记下一段:
# RAG覆盖不全问题(待整理) 来源:链接 核心:引文召回 vs 段落召回 覆盖差异;query改写可能造成上下文漂移 关联想法:对比一下长文档切片重叠度的经验值等到周末有整块时间了,再把inbox里攒的卡片拿出来,筛选、归类、扩写成正式的文档,放到对应的目录中。这套流程本质上是借鉴了GTD里的“收集箱”思想,用最轻量的方式先兜住信息,再统一消化。
4.2 写作沉淀:用“费曼式”口吻重写而不是搬运
在将inbox转正的时候,我最看重的一点是:绝对不能把原文粘贴过来就算完成。wiki的价值在于经过我大脑过滤之后的再表达,而不是原文的副本。
所谓费曼式重写,就是假装你要把这个概念讲给一个完全不懂的同事听。写“LoRA”的时候,我会先从“与其训练整个模型,不如训练一小部分增量矩阵”开始,再用铅笔和橡皮擦的类比解释低秩分解的本质。然后用一段代码示例帮助读者快速理解PEFT库的实际用法。写完检查一遍,如果发现自己也说不清楚某句话,就说明这个知识点还没真弄懂,那就去补课,直到能写明白为止。
这一步非常花时间,但它是wiki区别于普通收藏夹的根本分水岭。收藏夹存的是一堆别人的话,wiki存的是“你消化之后的话”。
4.3 版本管理与跨设备同步:像管代码一样管知识
因为wiki本质上是Markdown文件,版本管理交给Git几乎是顺理成章的事。我的同步方案是:本地文件夹作为工作区,Git仓库作为版本记录,远程GitHub私有仓库作为加密备份。
日常操作基本是三条命令:
git add . git commit -m "添加Qwen2.5微调实验记录,更新显存估算" # 推送远端备份 git push origin main跨设备同步的时候,我依然用Git。在公司电脑上拉取最新代码,在家里的机器上继续写。这套流程对纯文本文件来说非常丝滑,不会出现网盘同步冲突那种诡异的副本文件。
需要注意的两点:Git仓库要记得加
.gitignore忽略临时文件和一些大的二进制附件;另外如果wiki文件夹里有图片,建议用相对路径存放并且压缩大小,否则整个仓库体积会膨胀得很快。
4.4 定期回顾机制:让wiki跟上模型迭代速度
LLM领域的信息保质期极短,一篇半年前写的部署笔记很可能因为某个库的版本大改已经彻底失效。我给自己定了一些定期回顾的规则:
- 每周花20分钟清理inbox,保证待整理池不是垃圾池。
- 每月扫一遍models目录,检查是否有新版本发布、旧的结论是否还成立。
- 每次做新项目用到一个旧笔记时,顺手更新笔记里的时间戳和状态标记。
这种机制要求不高,但能保证知识库处于“活着”的状态。知识库一旦开始有内容过期,读者(也就是我自己)就会对它失去信任,然后就再也不翻了。这种信任感一旦消失,整个项目就废了。
5. 常见问题与排查技巧:我的避坑记录
搭llm_wiki的过程中我也踩过不少坑,有些是工具层面的,有些是方法论层面的。挑几个典型的记录一下,希望能帮你提前绕开。
5.1 问题:wiki的分析变成“垃圾桶”,文件夹越来越多
初期我犯过一个典型错误:每遇到一个新概念就新建一个文件夹,比如“注意力机制”“自注意力”“多头注意力”“GQA”“MQA”分别建了五个文件分散在不同地方。结果是名称冗余严重,检索反而更困难。
排查思路与解法:后来我做的第一件事是合并同类项,把“自注意力”“多头注意力”等全部归入concepts/attention.md一篇长文档,用二级标题区分不同变体。并在文件头部用标签#注意力统一挂载。本质上这意味着文档数量要尽量少,内容颗粒度要尽量适中。如果每个细碎知识点都单独一篇,wiki就成字典了,翻起来极其痛苦。最理想的状态是每篇文档都有独立的阅读价值,不是孤立的知识碎片。
5.2 问题:写了不更新,笔记很快过期
我的models目录里至今躺着几个已经完全不用的早期模型笔记,比如一些已经被行业淘汰的旧版基座模型。如果不加处理地全部留着,会干扰新模型的查阅。
排查思路与解法:我给文档元信息增加了status字段,标准值有“活跃”“临期”“归档”。凡是已经停止维护的模型,统一把状态从“活跃”改成“归档”,然后在顶部加一行提示:“此模型已停止更新,建议参考XXX。”这样既保留了历史记录,又不会误人子弟。
这个方法也适用于工具链。今天很火的框架可能三个月后就走下坡路,归档不删除,是对知识历史负责;状态分明,是给未来的自己省时间。
5.3 问题:过度追求“完美结构”导致无法动笔
还有一种很常见的心理,就是总觉得目录没设计好就不敢开始写。我第一版目录就设计了好几周,总担心分类不合理、以后返工,结果那几周产出的正文内容几乎为零。
经验教训:知识库的结构一定是在写作过程中长出来的,不是规划出来的。开始阶段只需要一个极简框架,比如就分“模型”“微调”“部署”“杂项”四种,先保证自己能写起来。等到东西多了、分类不够用了,再迭代调整。原有的内容即使挪动位置,成本也只是把文件移个目录而已,比想象中低得多。动手永远比完美重要。
5.4 问题:换电脑和备份时的文件冲突
因为用Git同步,偶尔也会遇到在两台电脑上同时编辑同一个文件然后提交冲突的情况。文本冲突解决起来虽然比二进制好处理,但依然麻烦。
排查思路与解法:我把工作流改成“单线程”模式:出门用手机或平板只看不改,回家在主力电脑上一次性处理完inbox和文档更新。如果确实需要在外修改,就避免同时修改同一篇文档。真遇到冲突时,git mergetool跑一下,或者直接读冲突标记手动合并,基本都能解决。
另外一个保险措施是给Git仓库加上pre-push钩子,push之前自动跑Markdown语法检查,防止表格语法损坏或者代码块没闭合。这类问题虽然不影响文件存在,但渲染出来很难看,影响阅读体验。
最后再说一点个人的体会
搭llm_wiki对我而言,最大的收获不是它在关键时刻帮我找到某篇笔记,而是它逼着我把“看过”变成“理解过”。LLM领域的信息太多、太杂,如果没有一个消化和重构的环节,看再多的文章也只是在给大脑缓存增加垃圾。现在每次写一条笔记,我都会先问自己:如果三个月后的我来看这篇东西,会不会还需要再搜一遍原始资料?如果答案是“需要”,那就说明笔记还没写到位。
这个项目到现在还在持续迭代,最近我在研究把llm_wiki里沉淀的问答记录做成一个自动标注的RAG评测集,让知识库里的内容能反过来帮助验证我做的Agent系统的效果。这大概就是知识库最理想的状态——不只是资历的证据,更是下一项工作的起点和燃料。无论你是做LLM相关开发还是研究,都推荐尽早建一个能让自己持续信任的私人wiki,哪怕从十篇文档开始呢。