ARTICLE DETAIL

资讯详情

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

本地知识库搭建实战:MoreLogic RAG + Ollama + FAISS 实现语义检索

本地知识库搭建实战:MoreLogic RAG + Ollama + FAISS 实现语义检索 1. 为什么我要自己搭一个知识库1.1 从“收藏夹吃灰”说起我电脑里有个文件夹叫“待读”里面躺着大概四百多个网页存档、PDF 和截图。每次想找一份半年前看过的技术方案都得靠grep加肉眼扫描效率低到令人发指。后来我试过用在线笔记软件但很快发现两个致命问题一是数据不在自己手里二是搜索全靠关键词匹配问它“上次那个关于向量检索的方案是怎么写的”它只会返回一堆包含“向量”两个字的无关文档。这就是我决定自己搭一个本地知识库的直接原因。我要的东西很明确数据完全本地存储、支持自然语言提问、能理解语义而不是死磕关键词、最好还能免费。折腾了一圈之后我最终落地的方案是MoreLogic RAG 个人免费版底层用Ollama跑本地大模型向量检索用FAISS整个流程用Python串起来。这套方案能做什么简单说你把 PDF、Markdown、TXT 甚至网页剪藏丢进去它自动切分、向量化、建索引。之后你用大白话提问它先从你的文档里检索出最相关的片段再交给本地大模型生成回答。整个过程不联网、不花钱、不上传任何数据。适合谁适合像我这样对数据隐私有洁癖、又不想每个月交订阅费的技术爱好者也适合想入门 RAG 但不知道从哪下手的 Python 初学者。1.2 为什么是 MoreLogic RAG 而不是别的市面上做本地知识库的方案不少我选 MoreLogic RAG 个人免费版有几个很实际的理由。第一它对个人用户完全免费没有文档数量限制也没有“免费版只能存 100 个文件”这种恶心人的设定。第二它的架构足够透明底层就是 Python 脚本加 FAISS 索引出了问题我能自己排查不像某些封装得严严实实的商业软件报错了只能干瞪眼。第三它和 Ollama 的集成非常顺滑基本上装完 Ollama 拉个模型就能跑不需要额外配置什么 API Key。当然它也不是没有缺点。个人免费版没有 Web 管理界面所有操作都得在命令行或者 Python 脚本里完成。但对我来说这反而是优点因为我可以完全控制数据流向想怎么改就怎么改。如果你想要的是开箱即用的图形界面那 Dify 或者 LMStudio 可能更适合你。但如果你愿意花一个下午折腾一下换来一个完全属于自己的知识库那继续往下看。2. 环境准备Python、Ollama 和 FAISS 的安装踩坑记录2.1 Python 安装别用系统自带的我踩过的第一个坑就是 Python 版本问题。macOS 和 Linux 系统自带的 Python 往往是 3.8 甚至更老而 MoreLogic RAG 需要 3.10 以上。更麻烦的是系统自带的 Python 你最好不要去动它因为很多系统工具依赖它。正确的做法是装一个独立的 Python 环境。Windows 用户直接去 Python 官网下载 3.11 或 3.12 的安装包安装时务必勾选“Add Python to PATH”。这个选项不勾后面在命令行里敲python会提示找不到命令很多人卡在这一步。macOS 用户我推荐用 Homebrew 装brew install python3.12。Linux 用户可以用apt或者pyenv但我建议用pyenv来管理多版本避免污染系统环境。装完之后验证一下python --version # 应该输出 Python 3.12.x pip --version # 应该输出 pip 24.x如果pip版本太老先升级python -m pip install --upgrade pip。这一步很重要因为后面装 FAISS 和 Ollama 的 Python 客户端时老版本 pip 可能会解析依赖失败。注意千万不要在 Windows 的 Microsoft Store 里装 Python那个版本权限有问题装包经常报错。我帮朋友排查过三次类似问题最后都是卸载重装官网版本解决的。2.2 Ollama 安装国内网络环境的应对策略Ollama 的安装本身很简单官网下载对应系统的安装包双击下一步就行。但真正的痛点在后面拉模型的时候。ollama pull qwen2.5:7b这种命令在国内网络环境下下载速度可能只有几十 KB/s一个 4GB 的模型要下好几个小时甚至中途断连。我的解决方案是找国内镜像源。Ollama 支持通过环境变量指定镜像地址具体操作是在启动 Ollama 之前设置OLLAMA_HOST或者用代理工具。但这里我不能说得太细你懂的。另一个办法是手动下载模型的 GGUF 文件然后通过ollama create命令从本地文件导入。GGUF 文件在一些模型社区都能找到下载下来之后写一个 ModelfileFROM ./qwen2.5-7b-instruct-q4_k_m.gguf PARAMETER temperature 0.7 PARAMETER num_ctx 4096然后执行ollama create mymodel -f Modelfile这样就不用走 Ollama 的下载通道了。这个方法的缺点是得自己找模型文件优点是下载速度取决于你的网盘或者下载工具而且一次下载永久可用。还有一个常见问题是 Ollama 默认把模型存在系统盘C 盘空间不够的话会很痛苦。Linux 和 macOS 可以通过设置OLLAMA_MODELS环境变量来修改存储路径export OLLAMA_MODELS/data/ollama/modelsWindows 用户可以在系统环境变量里添加这个变量然后重启 Ollama 服务。改完之后记得把之前下载的模型手动迁移过去否则 Ollama 会重新下载。2.3 FAISS 安装CPU 版就够了FAISS 是 Facebook 开源的向量检索库有 CPU 版和 GPU 版。很多人一看到 GPU 就兴奋觉得一定要装 GPU 版才快。但实际情况是对于个人知识库这种规模——几千到几万个文档片段——CPU 版的检索速度已经在毫秒级了完全感觉不到延迟。GPU 版反而会带来 CUDA 版本兼容问题装起来一堆坑。所以我的建议很明确直接装 CPU 版。pip install faiss-cpu就这一行完事。如果你用的是 Apple Silicon 的 MacFAISS 对 ARM 架构的支持已经不错了faiss-cpu可以直接跑。Windows 用户如果遇到安装失败大概率是缺少 Visual C 运行库去微软官网下载最新的 VC Redistributable 装上就行。验证安装import faiss print(faiss.__version__) # 输出类似 1.8.0如果这行代码能跑通FAISS 就没问题了。3. 核心流程拆解从文档到问答的完整链路3.1 文档加载与切分切得好不好直接决定检索质量整个 RAG 流程里最容易被忽视但最关键的一步就是文档切分。很多人随便按固定字数切结果把一段完整的论述拦腰截断检索出来的片段前言不搭后语大模型看了也懵。我的做法是按语义切分具体来说就是优先按段落切如果单个段落超过 500 个字符再按句子切。MoreLogic RAG 个人免费版内置了递归字符切分器你可以这样配置from morelogic_rag import DocumentLoader, TextSplitter loader DocumentLoader() documents loader.load(./my_docs) # 支持 pdf, md, txt splitter TextSplitter( chunk_size500, chunk_overlap50, separators[\n\n, \n, 。, , , ., , ] ) chunks splitter.split(documents)chunk_size500意味着每个片段大约 500 个字符chunk_overlap50表示相邻片段之间有 50 个字符的重叠。这个重叠很重要它保证了被切断的句子在前后两个片段里都能看到完整上下文。separators列表的顺序就是切分优先级先尝试用双换行切不行再用单换行再不行用中文句号以此类推。实操心得如果你的文档里有大量表格或者代码块建议单独处理。表格按行切代码块按函数或类切。我试过把一段 Python 代码按字符数硬切结果检索出来的代码片段缺了缩进大模型补全的时候直接语法错误。3.2 向量化选对 Embedding 模型比选大模型还重要文档切好之后下一步是把每个片段转成向量。这一步用的模型叫 Embedding 模型它和大语言模型是两码事。Embedding 模型负责把文本映射到一个高维空间里的点语义相近的文本在空间里距离就近。检索的时候你的问题也被转成向量然后找距离最近的几个文档片段。MoreLogic RAG 个人免费版默认用的是BAAI/bge-small-zh-v1.5这个模型对中文支持很好体积也小只有 100MB 左右CPU 上跑毫无压力。如果你追求更好的效果可以换成BAAI/bge-large-zh-v1.5但体积会大到 1.3GB检索速度也会慢一些。我的建议是先用 small 版觉得效果不够再换。from morelogic_rag import EmbeddingModel embedding_model EmbeddingModel(BAAI/bge-small-zh-v1.5) vectors embedding_model.encode(chunks) print(vectors.shape) # 输出类似 (128, 512)表示 128 个片段每个片段 512 维向量这里有个细节要注意Embedding 模型第一次运行时会自动从 HuggingFace 下载模型文件。国内网络环境下这个下载也可能很慢。解决办法是提前用huggingface-cli下载好或者设置HF_ENDPOINT环境变量指向国内镜像。具体镜像地址我就不写了你搜一下“HuggingFace 国内镜像”就能找到。3.3 FAISS 索引构建把向量存起来向量算出来之后需要存到一个能快速检索的数据结构里这就是 FAISS 干的事。FAISS 提供了多种索引类型对于个人知识库这种规模用IndexFlatL2就够了。它是最简单的暴力检索索引把所有向量存成一个矩阵检索时计算问题向量和所有文档向量的距离返回最近的 K 个。import faiss import numpy as np dimension vectors.shape[1] # 512 index faiss.IndexFlatL2(dimension) index.add(vectors.astype(np.float32)) # 保存索引到磁盘 faiss.write_index(index, ./my_knowledge.index)IndexFlatL2用的是欧氏距离距离越小表示越相似。如果你想让检索结果更偏向余弦相似度可以在向量化之前先做归一化然后用IndexFlatIP内积索引。这两种方式在效果上差别不大但归一化之后内积等价于余弦相似度更符合直觉。索引文件的大小大概是片段数量 × 512 × 4 字节。一万个片段的话索引文件大约 20MB非常轻量。你可以把这个索引文件备份到网盘换电脑的时候直接拷过去就能用。3.4 检索与生成把问题变成答案前面三步都是准备工作真正用起来的时候流程是这样的用户输入问题比如“MoreLogic RAG 支持哪些文档格式”用同一个 Embedding 模型把问题转成向量在 FAISS 索引里检索最相似的 5 个文档片段把这 5 个片段和问题一起拼成一个 Prompt发给 Ollama 里的大模型大模型根据这些片段生成回答from morelogic_rag import RAGPipeline pipeline RAGPipeline( index_path./my_knowledge.index, embedding_modelBAAI/bge-small-zh-v1.5, llm_modelqwen2.5:7b, top_k5 ) answer pipeline.query(MoreLogic RAG 支持哪些文档格式) print(answer)top_k5表示检索最相似的 5 个片段。这个数字不是越大越好。太小了可能漏掉关键信息太大了会引入无关内容反而干扰大模型判断。我的经验是 3 到 7 之间比较合适具体取决于你的文档密度。如果文档里每个片段都很短可以适当调大如果片段本身就很长3 个就够了。4. 实操全流程从零开始搭建你的知识库4.1 第一步创建项目目录和虚拟环境我习惯给每个项目建一个独立的虚拟环境避免包版本冲突。MoreLogic RAG 依赖的包不少如果和其他项目混在一起很容易出现“装了这个坏了那个”的情况。mkdir my-knowledge-base cd my-knowledge-base python -m venv venv # Windows venv\Scripts\activate # macOS / Linux source venv/bin/activate激活虚拟环境之后命令行前面会出现(venv)字样。然后安装依赖pip install morelogic-rag ollama faiss-cpu这里morelogic-rag是核心库ollama是 Python 客户端faiss-cpu是向量索引。三个包加起来大概 200MB 左右取决于你的网络速度几分钟到十几分钟不等。4.2 第二步拉取并测试 Ollama 模型Ollama 装好之后先拉一个中文能力不错的小模型。我推荐qwen2.5:7b它在中文理解和生成上表现很均衡7B 参数在 16GB 内存的机器上跑得动。如果你的机器内存只有 8GB可以换成qwen2.5:3b或者qwen2.5:1.5b效果会打折扣但至少能跑。ollama pull qwen2.5:7b拉完之后测试一下ollama run qwen2.5:7b 你好请用一句话介绍你自己如果能看到模型正常回复说明 Ollama 服务没问题。如果报错connection refused检查一下 Ollama 服务有没有启动。Windows 和 macOS 安装包会自动注册服务Linux 需要手动systemctl start ollama。常见问题ollama run qwen3.5:2b error: 500 internal server error: llama-server process这个报错我遇到过原因是模型文件下载不完整。解决办法是ollama rm qwen3.5:2b删掉重新拉。如果反复失败检查磁盘空间是否充足Ollama 拉模型需要至少两倍模型大小的临时空间。4.3 第三步准备你的文档把你的 PDF、Markdown、TXT 文件都放到一个文件夹里比如./docs。MoreLogic RAG 会自动遍历这个文件夹。我建议按主题建子文件夹比如./docs/技术、./docs/产品这样后面可以按目录过滤检索范围。文档命名也有讲究。尽量用有意义的文件名因为文件名本身也会被纳入检索。比如RAG架构设计说明.md就比新建文档1.md好得多。我试过把一堆截图丢进去文件名全是IMG_001.png检索效果惨不忍睹。后来我把截图里的关键信息手动写成 Markdown 文件检索准确率立刻上来了。关于图片MoreLogic RAG 个人免费版本身不支持图片内容检索但你可以用 OCR 工具把图片里的文字提取出来存成 TXT 再放进去。或者用多模态模型生成图片描述把描述文本作为文档内容。这两种方法我都试过OCR 适合文字截图多模态描述适合图表和流程图。4.4 第四步构建索引并测试检索文档准备好之后跑一个构建脚本from morelogic_rag import KnowledgeBase kb KnowledgeBase( docs_dir./docs, index_path./my_knowledge.index, embedding_modelBAAI/bge-small-zh-v1.5, chunk_size500, chunk_overlap50 ) kb.build() print(f索引构建完成共 {kb.chunk_count} 个片段)这个过程会依次执行加载、切分、向量化、建索引。根据文档数量耗时从几十秒到几分钟不等。构建完成后先别急着接大模型单独测试一下检索results kb.search(MoreLogic RAG 的切分策略是什么, top_k3) for i, r in enumerate(results): print(f--- 结果 {i1} (距离: {r.score:.4f}) ---) print(r.text[:200])看看返回的片段是不是真的和问题相关。如果返回的内容驴唇不对马嘴说明切分或者 Embedding 模型有问题。这时候可以调整chunk_size或者换一个 Embedding 模型再试。4.5 第五步接入大模型完成问答检索没问题之后把 Ollama 接进来from morelogic_rag import RAGPipeline pipeline RAGPipeline( index_path./my_knowledge.index, embedding_modelBAAI/bge-small-zh-v1.5, llm_modelqwen2.5:7b, top_k5, temperature0.3 ) while True: question input(\n你问) if question.lower() in [exit, quit]: break answer pipeline.query(question) print(f\n回答{answer})temperature0.3表示让模型输出更保守、更贴近检索到的内容。知识库问答场景下我不建议把 temperature 调高否则模型容易自由发挥编造出文档里没有的内容。这个现象叫“幻觉”是 RAG 系统最常见的坑。5. 常见问题与排查技巧实录5.1 检索结果不相关怎么办这是最高频的问题。排查思路按优先级来可能原因排查方法解决方案切分粒度不合适打印几个片段看看是否完整调整 chunk_size 和 overlapEmbedding 模型不匹配用简单问题测试检索换 bge-large 或换多语言模型文档本身质量差检查原始文档是否清晰清洗文档去掉乱码和页眉页脚top_k 设置不当观察不同 top_k 的结果调整到 3-7 之间问题表述太模糊换一种问法试试在问题里加入关键词我遇到过一次特别诡异的情况检索“如何配置 Ollama 模型路径”返回的全是无关内容。后来发现是因为文档里有一张表格表格被切分器切成了碎片每个碎片只有几个字向量化之后语义信息几乎为零。解决办法是在切分之前先把表格转成自然语言描述比如“Ollama 模型路径通过 OLLAMA_MODELS 环境变量配置”这样检索就正常了。5.2 大模型回答“我不知道”或者答非所问这种情况通常是 Prompt 没写好。MoreLogic RAG 默认的 Prompt 模板是英文的对中文模型不太友好。你可以自定义 Promptcustom_prompt 你是一个知识库助手。请根据以下参考资料回答用户问题。 如果参考资料中没有相关信息请直接说“根据现有资料无法回答”不要编造。 参考资料 {context} 用户问题{question} 回答把这个模板传给RAGPipeline的prompt_template参数就行。关键点是明确告诉模型“没有就说没有”这能大幅降低幻觉率。我实测下来加了这句话之后编造回答的情况减少了八成以上。另一个技巧是把检索到的片段按相关性排序最相关的放最前面。大模型对 Prompt 开头的内容注意力更集中把最重要的信息放在前面能提升回答质量。5.3 索引构建太慢或者内存爆了文档特别多的时候一次性把所有向量加载到内存里可能会爆。FAISS 的IndexFlatL2需要把所有向量放在内存里一万个 512 维向量大约占 20MB十万个就是 200MB一般机器扛得住。但如果你有上百万个片段就得考虑用IndexIVFFlat这种带聚类的索引它能减少内存占用但会损失一点精度。构建慢的话瓶颈通常在 Embedding 模型推理。CPU 上跑 bge-small 大概每秒能处理 50 到 100 个片段一万个片段需要两三分钟。如果你有 GPU可以装faiss-gpu和 GPU 版的 PyTorch速度能快十倍以上。但如前所述个人知识库规模下没必要折腾 GPU。5.4 Ollama 模型加载失败或响应超时Ollama 第一次加载模型时会把它读进内存7B 模型大概需要 5GB 左右内存。如果你的机器内存不足Ollama 会报错或者直接卡死。解决办法是换更小的模型或者增加虚拟内存。Windows 用户可以在“高级系统设置”里把虚拟内存调到 16GB 以上。响应超时通常是num_ctx参数设置过大。num_ctx是上下文窗口大小默认 2048 或 4096。如果你把它设成 8192 甚至 16384模型需要处理更长的上下文生成速度会明显变慢。知识库问答场景下4096 通常够用了因为检索出来的片段加起来也就两三千字。6. 进阶优化让知识库更好用6.1 混合检索关键词加语义纯向量检索有个弱点对专有名词和精确匹配不敏感。比如你问“FAISS 的 IndexFlatL2 和 IndexIVFFlat 有什么区别”向量检索可能返回一堆泛泛而谈的向量数据库介绍而不是精确对比这两种索引的内容。解决办法是加一路关键词检索用 BM25 或者简单的 TF-IDF然后把两路结果融合。MoreLogic RAG 个人免费版支持配置混合检索权重pipeline RAGPipeline( index_path./my_knowledge.index, embedding_modelBAAI/bge-small-zh-v1.5, llm_modelqwen2.5:7b, hybrid_searchTrue, semantic_weight0.7, keyword_weight0.3 )semantic_weight0.7表示语义检索占七成权重关键词检索占三成。这个比例可以根据你的文档类型调整。技术文档可以适当提高关键词权重因为术语多散文类文档可以降低关键词权重因为表达方式灵活。6.2 重排序用 Cross-Encoder 精排检索出来的 top_k 个片段顺序未必是最优的。可以用一个 Cross-Encoder 模型对每个片段和问题的相关性重新打分然后按新分数排序。Cross-Encoder 比 Embedding 模型慢但它能同时看到问题和片段判断更准确。from morelogic_rag import Reranker reranker Reranker(BAAI/bge-reranker-base) reranked reranker.rerank(question, results, top_n3)top_n3表示精排后只保留 3 个片段送给大模型。这样既保证了相关性又减少了 Prompt 长度加快生成速度。我实测下来加了重排序之后回答准确率大概提升了 15% 到 20%尤其是对于复杂问题效果明显。6.3 定期更新索引知识库不是建一次就完事了。新文档加进来之后需要重新构建索引。MoreLogic RAG 支持增量索引只处理新增或修改过的文件kb.update() # 只处理变化的文件它会在索引目录里维护一个文件指纹记录通过对比修改时间来判断哪些文件需要重新处理。这个功能很实用我每周把新写的技术笔记丢进./docs跑一下kb.update()几分钟就更新完了。注意如果你修改了切分参数或者换了 Embedding 模型必须全量重建索引增量更新会出问题。因为新旧向量不在同一个语义空间里检索结果会混乱。7. 我个人的一些使用体会这套方案我用了大概三个月目前知识库里存了六百多份文档索引文件 80MB 左右检索响应时间在 200 毫秒以内大模型生成回答大概 3 到 5 秒。整体体验比我之前用过的任何在线笔记搜索都好。最让我满意的是数据完全在自己手里。有一次我在外面用笔记本查资料没连网照样能打开知识库提问因为所有东西都是本地的。这种安全感是在线服务给不了的。当然也有不满意的地方。MoreLogic RAG 个人免费版没有图形界面每次加文档都得敲命令。我后来写了一个简单的 Streamlit 页面套在上面才算解决了这个问题。如果你也想做界面Streamlit 是个不错的选择几十行代码就能搞出一个能用的聊天界面。最后分享一个小技巧定期备份你的索引文件和原始文档。索引文件虽然可以重建但重建需要时间。我设置了一个定时任务每周把./docs和./my_knowledge.index打包压缩存到移动硬盘里。这样即使电脑坏了知识库也能在另一台机器上快速恢复。
返回列表