你是不是也有过这种经历公司有一堆 PDF 文档、Word 制度、产品手册每次想找点信息都得翻半天想让 AI 帮自己答疑但它一问三不知还经常一本正经地胡说八道这篇教程就来解决这两个痛点。我会带你用最少的概念、最少的环境依赖从零搭一个完全跑在自己电脑上的知识库问答系统。全程跟着做不需要懂向量数据库原理也不需要显卡。一、RAG 是什么先搞懂再动手RAG 是Retrieval-Augmented Generation的缩写中文叫检索增强生成。别被名字吓到用一句话说先去资料库里翻出相关的几页纸再把这几页纸交给 AI让它基于这些材料来回答问题。用一个生活化的比喻想象你是一个刚入职的员工被问到我们公司的年假怎么算“。你自己肯定答不上来。于是你先跑去档案室翻出《员工手册》里关于年假的那一章然后把这一章递给一个很会总结但记性不好的同事说你照着这页回答他”。这个同事读完后用大白话把答案讲了出来。在这个比喻里档案室 你的文档库翻出相关章节 检索Retrieval记性不好的同事 大语言模型LLM照着材料回答 生成Generation。传统的大模型有个天生缺陷它只知道自己训练时背过的内容对你的私有资料一无所知而且训练数据有截止日期。RAG 的核心思路就是——别让模型凭记忆瞎编给它一份开卷考试的参考资料。这样既能回答私有知识又能大幅减少幻觉胡说八道。一句话记住 RAG不开卷的 AI 在裸考加了 RAG 的 AI 拿着你的资料在开卷答题。二、整体架构一条流水线一个最基础的 RAG 系统其实是把建资料库和回答问题分成了两个阶段。我们画一条流水线【知识库构建阶段离线做一次就行】 文档 → 分块 → 向量化 → 存进向量库 .pdf/.txt 切小段 变成向量 (本地文件/数据库) 【问答阶段在线用户每次提问】 用户提问 → 向量化问题 → 检索最相关的几块 → 拼成 Prompt → 大模型生成答案逐段解释文档Document你的原始资料PDF、TXT、Word、网页都行。分块Chunking把长文档切成一段一段的小块。为什么要切因为大模型一次读不下整本手册而且检索时精准命中一小段比命中一大篇更有用。向量化Embedding用 embedding 模型把每一块文字变成一个长长的数字数组向量。语义相近的文字向量在数学空间里也离得近。这一步是 RAG 的魔法核心。向量库Vector Store把这些向量存起来方便后面快速比对。本地最简单的做法就是存成本地文件。检索Retrieval用户提问时同样把问题向量化然后在向量库里找离问题最近的几块资料。生成Generation把检索到的资料 用户问题拼成一个提示词Prompt丢给大模型让它基于资料作答。这六个环节里前四步是建库只在你新增/修改文档时跑一次后两步是问答每次提问都跑。这个区分很重要后面写代码时会对应上。三、环境准备3.1 你需要什么Python 3.10 或以上推荐 3.10/3.11兼容性最好。一台普通的电脑不需要独立显卡。我们用的 embedding 模型和生成模型都走本地轻量路线。网络第一次要下载模型后面离线也能用。3.2 安装 Ollama本地的模型运行器为了让整套系统完全本地、保护隐私、免 API 费用我们用 Ollama 来跑模型。它相当于一个本地模型管家一行命令就能下载并运行开源模型。去 ollama.com 下载安装一路下一步即可。打开终端拉取两个模型一个负责中文生成一个负责中文向量化# 中文生成模型7B 版本4G 内存勉强8G 更顺ollama pull qwen2.5:7b# 中文 embedding 模型bge-m3 对中文、中英混合都很强ollama pull bge-m3如果你的电脑内存比较小比如 8G 以下可以把qwen2.5:7b换成qwen2.5:3b牺牲一点质量换流畅度。3.3 安装 Python 依赖建议先建一个虚拟环境保持干净python-mvenv rag-env# Windows 激活rag-env\Scripts\activate# macOS / Linux 激活sourcerag-env/bin/activate pipinstallllama-index llama-index-llms-ollama llama-index-embeddings-ollamallama-index是今天的主角框架它把分块、向量化、检索、生成封装成了非常简单的 API另外两个是让它能调用本地 Ollama 模型的适配器。四、代码实战完整可运行的 RAG 流程下面这段代码是端到端、能直接跑的最小可用版本。我会一边贴代码一边讲。4.1 先造一份演示资料教程要能跟着做得有素材。我们在项目目录建一个data文件夹并写一份示例《员工手册》。你可以直接复制下面这段 Python 来生成importos os.makedirs(data,exist_okTrue)handbook 公司员工手册示例 一、年假规定 正式员工入职满一年后可享受年假。工作年限1-10年的每年5天10-20年的每年10天20年以上的每年15天。年假需提前3个工作日向直属主管申请当年未休完的可顺延至次年3月底。 二、加班与调休 工作日加班可申请调休调休需在加班发生起的2个月内使用。法定节假日加班按三倍工资结算不可折抵调休。 三、报销流程 员工因公产生的差旅、餐饮费用需在费用发生后30天内提交报销单并附发票原件。单笔超过2000元的支出须事前邮件报备。财务在收到合规单据后10个工作日内打款。 四、转正与试用期 试用期一般为3个月表现突出者可申请提前转正但不得低于法定最短试用期。转正需由部门负责人提交评估表。 withopen(data/员工手册.txt,w,encodingutf-8)asf:f.write(handbook)print(演示文档已生成data/员工手册.txt)4.2 主程序搭知识库 问答新建文件rag_demo.py内容如下fromllama_index.coreimport(VectorStoreIndex,SimpleDirectoryReader,Settings,)fromllama_index.llms.ollamaimportOllamafromllama_index.embeddings.ollamaimportOllamaEmbedding# ---------- 1. 配置本地模型 ----------# 生成模型负责读资料、写答案Settings.llmOllama(modelqwen2.5:7b,base_urlhttp://localhost:11434)# 向量化模型负责把文字变成向量Settings.embed_modelOllamaEmbedding(model_namebge-m3,base_urlhttp://localhost:11434)# 分块大小每块大约多少字符中文可按字符粗算Settings.chunk_size512Settings.chunk_overlap64# 块与块之间留点重叠避免一句话被切断# ---------- 2. 读取文档构建阶段 ----------documentsSimpleDirectoryReader(data).load_data()print(f已加载{len(documents)}个文档)# ---------- 3. 构建向量索引分块 向量化 入库一步到位 ----------indexVectorStoreIndex.from_documents(documents)print(知识库构建完成)# ---------- 4. 问答在线阶段 ----------query_engineindex.as_query_engine(similarity_top_k3)# 每次取最相关3块whileTrue:qinput(\n请输入你的问题输入 exit 退出)ifq.strip().lower()exit:breakresponsequery_engine.query(q)print(\n【答案】)print(response.response)4.3 跑起来看效果确保 Ollama 已经在后台运行任务栏有图标或终端跑ollama serve。然后python rag_demo.py试着问请输入你的问题年假最多能休几天你会看到模型基于《员工手册》回答“工作年限20年以上的员工每年可享受15天年假……” ——它确实读了你给的文件而不是凭空编的。这就是 RAG 的魔力。小提示第一次提问会稍微慢一点因为框架要懒加载索引。如果回答明显答非所问或我无法从资料中找到多半是下面常见问题里要讲的检索没调好先别慌往下看。五、常见问题三个最容易卡住新手的坑5.1 分块大小chunk_size怎么选核心矛盾块太大 → 一块里杂糅太多无关内容模型容易跑偏块太小 → 一句话被切成两半语义不完整检索命中了也拼不出完整答案。经验值参考场景建议 chunk_size说明中文手册 / 制度类300–600 字符中文信息密度高不用照搬英文的 512 token长论文 / 技术文档800–1200 字符段落完整更重要超短问答对FAQ整条当作一块一条 QA 不要拆还有个常被忽略的参数chunk_overlap重叠让相邻块共享一小段文字能防止答案正好卡在两块边界的尴尬。一般设为 chunk_size 的 10%–20%。调试方法直接改Settings.chunk_size重新构建索引看答案质量变化。别过度追求最优值80 分够用就行。5.2 embedding 模型选哪个embedding 模型决定了检索准不准是中文 RAG 里最值得花心思的一环。对比几个常用选择BAAI/bge 系列推荐bge-m3、bge-large-zh对中文支持极好HuggingFace 上下载量最高的中文向量模型之一。本教程用的bge-m3还能中英混搜。nomic-embed-textOllama 里开箱即用的轻量英文模型中文一般适合纯英文场景。OpenAI text-embedding-3-small效果稳定但要 API key、要联网、要花钱且数据出本地。智源 / 百度千帆 等国内方案中文友好但多一层账号和额度配置。给新手的建议先用本地的bge-m3把流程跑通确认架构没问题后再考虑换更强的 embedding 来提精度。5.3 检索效果怎么调如果模型找不到答案或找错资料按这个顺序排查调大similarity_top_k从 3 调到 5 或 8让它多翻几块资料宁可多给点上下文。改分块块太大就调小块太小就调大 加 overlap见 5.1。看检索到了啥打印中间结果确认召回的资料真的和问题相关retrieverindex.as_retriever(similarity_top_k5)nodesretriever.retrieve(年假怎么算)forninnodes:print(round(n.score,3),n.text[:80])# 看看分数和片段对不对得上换更强的 embeddingbge-m3还嫌不准可上bge-large-zh-v1.5需要走 HuggingFace 本地加载而不只是 Ollama。上 rerank见第六节在初步召回后再让一个精排模型把最相关的排到最前面。六、进阶提示让你的 RAG 更聪明当你把基础版跑顺了下面三招能显著提升效果而且都不复杂。6.1 Hybrid Search混合检索纯向量检索擅长语义相似但碰上专有名词、编号、精确匹配比如条款第 3.2 条“订单号 A2026”就容易翻车。混合检索 向量检索 关键词检索BM25双管齐下最后合并结果。LlamaIndex 里可以这样开启fromllama_index.core.retrieversimportQueryFusionRetrieverfromllama_index.retrievers.bm25importBM25Retriever# 向量检索器vector_retrieverindex.as_retriever(similarity_top_k5)# 关键词检索器bm25_retrieverBM25Retriever.from_defaults(docstoreindex.docstore,similarity_top_k5)# 融合两者fusionQueryFusionRetriever([vector_retriever,bm25_retriever],num_queries1,# 不做 query 扩展时设为 1modereciprocal_rerank,# 用 RRF 算法融合排序)nodesfusion.retrieve(报销单超过2000元要怎么办)6.2 Rerank重排序召回阶段为了快用的是粗排向量相似度rerank 阶段再用一个更聪明但更慢的模型对这 Top-N 个候选做精排把真正相关的顶上去。fromllama_index.core.query_engineimportRetrieverQueryEnginefromllama_index.core.postprocessorimportSentenceTransformerRerank rerankSentenceTransformerRerank(modelBAAI/bge-reranker-base,top_n3)engineRetrieverQueryEngine.from_args(retrievervector_retriever,node_postprocessors[rerank])rerank 是花小钱办大事的典型召回放宽多取点精排收紧只留最准的答案质量肉眼可见地变稳。6.3 Query Expansion查询扩展用户的问题往往太短、太口语比如只问年假。查询扩展就是让模型先把问题改写成几个更完整的问法分别去检索再把结果合并。相当于一个人不会只搜一个关键词而是换了几种说法都搜一遍。fromllama_index.core.indices.query.query_transformimport(DecomposeQueryTransform,)# 简单地让 LLM 生成 3 个相似问法各自检索再融合# 可配合 QueryFusionRetriever 的 num_queries 参数使用实际中把 6.1 里的num_queries设成 3~4框架就会自动用 LLM 生成多个变体查询并融合这正是 query expansion 的落地方式。一句话总结进阶三件套混合检索解决找不全rerank 解决排不准query expansion 解决问不清。七、作者经验总结我自己从零搭 RAG 时踩过不少坑最后沉淀成几条实在的建议送给同样在入门的你先跑通再优化。新手最容易犯的错误是一上来就纠结哪个 embedding 最强、要不要上向量数据库。别。先用bge-m3 Ollama 本地文件把整条流水线跑出第一个正确答案成就感有了后面的优化才有方向。中文场景分块和 embedding 是两个最影响体验的旋钮。英文教程里的 512 token 不能直接套到中文按字符数重新估embedding 优先选 bge 系列别拿英文模型硬凑中文。检索不好别急着怪模型。90% 的答非所问其实发生在检索阶段——资料根本没被召回模型再聪明也只能瞎编。养成先看检索到了什么的习惯可以省下大量调 prompt 的时间。本地方案值得坚持。用 Ollama 把生成和 embedding 都放在本地不仅免费、隐私可控更重要的是让你真正理解每一层在干嘛。等你需要更大规模、更强模型时再迁移到云端也不迟。RAG 不是银弹。它解决的是让模型基于你的资料回答但资料的准确性、分块是否合理、问题是否清晰依然决定上限。把它当成一个会查资料的助手而不是全知全能的 oracle。RAG 听起来高大上拆开看其实就是切文档 → 存向量 → 搜相关 → 交给模型四步。真正难的不是技术而是愿意动手把第一个 demo 跑起来。希望这篇教程能帮你跨过那道门槛——打开终端装好 Ollama复制代码按下回车你就已经有了一个属于自己的本地知识库问答系统。祝玩得开心也玩得明白。本文配套代码与示例文档均已给出可直接复制运行。如需扩展建议优先尝试第六节的三大进阶技巧。