RAG实战:用Notebook从零构建知识库问答系统
我先把话说在前头你要是想系统学 RAG检索增强生成光看概念、刷面试八股效率其实很低。真正让你“哦——原来是这样”的瞬间往往是亲手把一套代码从头到尾跑通的那一下。这篇博文就是想复刻那个“顿悟瞬间”。事情起因是我在 GitHub 上翻到一个基于 Notebook 的 RAG 实战项目当时心里想的是“不就是 load 文档、切分、embedding、向量检索、丢给 LLM 吗能有多难”。等到真在自己的 Jupyter Notebook 里一步步把每个 cell 跑起来把中间结果一行行打印出来看才意识到自己之前对 RAG 的理解有多么“悬浮”——很多细节概念里根本不会告诉你。这篇就按我的实操路线把 RAG 从“听说过”到“跑通了”再到“敢说自己懂了”的完整过程拆开讲包括踩坑、调参、评估以及我用 Notebook 做实验时的一些独门习惯。适合刚接触 RAG、被各种术语绕晕的初学者也适合已经跑过 demo 但总觉得差点意思的开发者。1. 动手之前的灵魂拷问RAG 到底在解决什么问题1.1 为什么“有 LLM”还不够在打开 Notebook 开始敲代码之前我觉得很有必要先把底层逻辑捋清楚。很多人对 RAG 的第一印象是“给大模型加个知识库”这个说法没错但太潦草了。RAG 本质上解决的是大模型“不会”和“乱编”这两个问题。“不会”好理解大模型的训练数据有截止日期没训过的东西它就是不知道你问它昨天新发布的某个产品参数它只能瞎猜。“乱编”其实就是幻觉哪怕它训练过相关内容一旦你的提问方式和训练语料的表达方式差得太远它就倾向于用“听起来顺嘴”的话来填坑。而 RAG 的思路非常直白我不逼你背知识点我直接把资料带进考场给你翻。里面有三个核心环节——检索Retrieval、增强Augmentation、生成Generation。通俗点说先从你的私有资料库里搜出和当前问题最相关的内容片段然后把原问题加上这些片段拼成一段完整的提示词交给大模型让它基于这些资料来回答。1.2 “本地知识库”这个说法最容易误导人你经常会看到“RAG 知识库”这样的说法好像做了一套系统就拥有一个能自动理解人类语言的知识库。实际上真正落地的时候你构建的是一个向量的仓库不是文本的仓库。你要先把原始文本切块切成小片段然后把这些片段丢给 embedding 模型转成向量一串一串的浮点数再存进支持向量检索的数据库里。等到用户提问时同样把问题转成向量在数据库里做相似度搜索。所以 RAG 里的“知识”在存储层面是一串串数学向量而不是你肉眼可读的文字。很多人在 Notebook 里跑完第一步看到数据库里那一堆 384 维或者 768 维的数组时才真正理解这一点。1.3 Notebook 为什么特别适合学 RAG说回工具层面。为什么我强烈建议用 Jupyter Notebook 来学习 RAG而不是直接去写一个完整的后端服务首先RAG 的链路是所有 AI 应用里最适合“分步观察”的。加载文档、切分、向量化、检索、拼接提示词、生成回答每一步的输入输出都非常清晰完全可以用代码块一步步拆开看。Notebook 的 cell 结构天然适合干这个你可以在每个 cell 后面加一个输出把向量、切分后的文本、检索出的相似度分数全打出来一步一步像解剖一样看。其次调试成本低。RAG 的失败点非常多参数设置不当、切分不合理、检索策略不对都可能让整个系统变得“像个智障回答机”。在脚本里调试每次都要从头跑一遍在 Notebook 里你可以只重新运行某几个 cell效率完全不是一个量级。我自己的习惯是用 Notebook 做原型验证跑通了再考虑封装成 API 服务。不管你是做知识库问答、企业私有化部署还是想给产品接入一个“文档理解助手”这个路径都适用。2. 环境搭建与工具选型别在不该纠结的地方浪费生命2.1 安装那点破事先别急着翻最新框架文档老老实实把基础环境搞干净。我用的是一台普通开发机Python 3.10。这里先给个忠告千万别在全局 Python 环境里乱装包用虚拟环境或者 Anaconda 单独建一个不然以后各种依赖冲突能让你怀疑人生。我在 Notebook 里跑了这么几行pip install langchain pip install langchain-community pip install langchain-openai pip install chromadb pip install jupyter为什么要装这些langchain帮你把“加载文档、切分、向量化、检索、调用 LLM”这一整套动作串成流水线。虽然很多核心组件你可以手写但框架提供的规范化接口和工具类能大大减少你初期的试错成本。langchain-community里面有很多现成的文档加载器PDF、Word、纯文本、Markdown 都有人帮你封装好了。langchain-openai用来对接 OpenAI 风格的大模型接口。实际上只要你之后用兼容 OpenAI API 的国产模型或者本地部署模型这个包也能用。chromadb一个轻量级向量数据库用起来非常简单适合原型开发和学习。比什么 ES、Milvus 上手成本低太多。jupyter这个是运行 Notebook 本身需要的。很多人会卡在类似“jupyter notebook error: subprocess-exited-with-error”这类问题。我遇到过基本都是版本不匹配导致的比如 Python 3.10 配了过旧版的依赖。解法也很粗暴把 pip 和关键包升级到最新pip install --upgrade pip setuptools wheel然后再安装。这个问题在 Windows 上尤其常见因为有些包需要编译 C 扩展环境里没有合适的构建工具就会报这个错。2.2 模型选型思路别一上来就追求“最好”RAG 链路里会用到两种模型一种是把文本转成向量的 embedding 模型另一种是最终负责组织答案的生成模型LLM。embedding 模型我强烈建议用 BGE北京智源研究院出的系列或者硅基流动、魔搭上托管的一些开源中文向量模型。为什么不用 OpenAI 的 text-embedding-3-small不是不好而是对于国内用户网络和成本都是现实问题。BGE 模型对中文的支持非常好在 HuggingFace 和 ModelScope 上都能直接下载用 sentence-transformers 库就能加载from sentence_transformers import SentenceTransformer model SentenceTransformer(BAAI/bge-small-zh-v1.5) embeddings model.encode([你好, 世界]) print(embeddings.shape)模型选小不选大这是学习阶段的原则。bge-small 版只有一百多兆跑得飞快消费级 CPU 都能跑效果对于学习场景完全够用。等你把整个链路跑通了再换更好的模型也不迟。生成模型考试环境下我用的是通义千问通过 DashScope 的 OpenAI 兼容接口调用也可以接 OpenAI 的 GPT 系列或者用 Ollama 拉一个本地模型。对于学习阶段我建议用 API 方式省去本地部署的麻烦。注册个账号拿到 API Key用 langchain-openai 的 ChatOpenAI 类就能接上。from langchain_openai import ChatOpenAI llm ChatOpenAI( modelqwen-plus, # 这里写你用的模型名 api_key你的key, base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1 )有一点特别重要别把 API Key 硬编码写死在代码里。Notebook 容易分享出去忘删 Key 等于直接把钱送人。第一节课就要养成习惯用环境变量或者单独的配置文件存。import os os.environ[OPENAI_API_KEY] 你在这里临时填一次在 Notebook 里临时设置是没问题的只要记得下线前清掉 cell 输出就行。2.3 关于“魔搭社区 Notebook 保活”这件事如果你是白嫖魔搭ModelScope提供的免费 Notebook 环境大概率会遇到一个恶心事长时间不操作环境就被回收了训练到一半的数据直接没。我的经验是把 RAG 实验拆成小模块每跑完一个阶段就把关键的中间结果保存下来。切分好并向量化好的数据直接存成向量数据库文件chromadb 支持本地持久化下次实验直接加载不需要重新 embedding。这比研究“保活”技巧实在多了。2.4 框架选型为什么最终选择了 LangChain现在市面上做 RAG 的框架很多LangChain、LlamaIndex、Haystack甚至 Spring AI 也来凑热闹。我最终在 Notebook 里用的是 LangChain理由有三个。第一资料多、社区大。遇到问题随手一搜全是答案对新手极其友好。第二抽象层次适中。LangChain 既能把整条 RAG 链路封装成极简接口也允许你单独拿每个组件出来手动控制。这非常适合教学场景。第三就业市场认可度高。现在面试题十有八九会问 LangChain 的组件机制用它练手等于顺便复习面试知识点。不过这里也得提一嘴LangChain 有个被万人吐槽的毛病——版本更新太快、API 经常变。你今天照着博客写的代码可能下个月就报 deprecated 警告。这时候最靠谱的文档还是官方 API 参考。我在后面给出的代码尽量用的是核心且稳定的那部分 API。3. 从零把 Notebook 跑通一个可复现的完整 RAG 实现3.1 准备测试文档做实验别拿太复杂的文档。我在 /data目录下放了几篇自己项目的 Markdown 说明文档和一份公司公开的产品介绍 PDF。这里给你一个建议先拿你自己熟悉内容的文档做测试。因为你熟悉原文才能准确判断 RAG 的检索结果好不好、生成回答时有没有“偷工减料”。加载文档这一步LangChain 提供了统一的接口from langchain_community.document_loaders import DirectoryLoader from langchain_community.document_loaders import TextLoader from langchain_community.document_loaders import PyPDFLoader # 加载 Markdown 文件 md_loader DirectoryLoader(./data/, glob**/*.md, loader_clsTextLoader) md_docs md_loader.load() # 加载 PDF 文件 pdf_loader DirectoryLoader(./data/, glob**/*.pdf, loader_clsPyPDFLoader) pdf_docs pdf_loader.load() all_docs md_docs pdf_docs print(f共加载了 {len(all_docs)} 个文档)这一步的本质是解析原始文件把它变成“一整个字符串”。3.2 文本切分的艺术这一步是整个 RAG 链路里最影响效果但最容易被忽略的环节。简单说你不能把一篇几万字的文档直接拿去向量化因为 embedding 模型有最大 token 限制而且太长的话语义会被稀释检索精度会很差。你需要把长文本切成一块一块的每一块就是一个“候选答案片段”。LangChain 里最常用的是 RecursiveCharacterTextSplitter。这个工具的特点是它会按优先级依次尝试用“\n\n”、“\n”、“。”、“ ”等分隔符去切保证切出来的块语义相对完整。from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap100, separators[\n\n, \n, 。, , , ., , ] ) split_docs text_splitter.split_documents(all_docs) print(f切分后共 {len(split_docs)} 个文档块)这里两个参数要重点解释chunk_size每块的目标长度单位是字符中文。我用 500是个比较平衡的值既能保证每个块包含足够的上下文信息又不至于让 embedding 时信息太分散。chunk_overlap相邻两块之间的重叠长度。为什么要重叠因为一个完整句子可能恰好被切分边界“腰斩”如果下一块完全没有前文的线索,模型回答时就会缺上下文。重叠的区间能有效缓解这个问题。说一下踩过的坑。我之前贪心觉得 chunk_size 越大信息越全直接填了 2000。结果检索的时候相关的那块内容里掺杂了大量无关信息导致生成的答案非常“飘”甚至把文档里本来就无关的两件事揉在一起回答。降到 500 之后答案精准度肉眼可见地提升了。另外一个技巧对于 Markdown 或者 HTML 这种带结构的文档可以优先用标题切分而不是纯按字符长度。LangChain 有 MarkdownHeaderTextSplitter按标题层级切出来每一块天然对应一个小节语义完整度极高。我后面实验里用它不是特别多因为测试文档本身结构不太规则但对有规律排版的技术文档这个工具是神器。3.3 向量化与存储接下来就是把每一块文本变成向量。前面装了 sentence-transformers这里结合 LangChain 的 HuggingFaceEmbeddings 使用from langchain_community.embeddings import HuggingFaceEmbeddings embeddings HuggingFaceEmbeddings( model_nameBAAI/bge-small-zh-v1.5, encode_kwargs{normalize_embeddings: True} )然后创建向量库。我这里用 Chroma因为它可以直接在本地持久化重启 Notebook 之后还能用from langchain_community.vectorstores import Chroma vectorstore Chroma.from_documents( documentssplit_docs, embeddingembeddings, persist_directory./chroma_db )等你跑完这一行可以打印一下存进去的向量维度感受一下print(vectorstore._collection.count()) # 看有多少条向量记录到这一步“知识库”就建好了。注意了这个过程里文本经过模型变成了数字向量向量之间距离的远近代表了语义的相似程度。距离越近意味着语义越接近。3.4 检索并生成回答完整链路里检索这一步是把用户的问题变成向量然后去库里查最相近的几块文本retriever vectorstore.as_retriever( search_typesimilarity, search_kwargs{k: 4} # 返回最相似的前4个文档块 ) query 告诉我这个项目的部署步骤是什么 retrieved_docs retriever.invoke(query) print(f检索到 {len(docs)} 个相关片段) for i, doc in enumerate(docs): print(f--- 片段 {i1} ---) print(doc.page_content[:200])强烈建议你这时候把检索出来的片段完整打印出来亲眼看看哪些内容被搜出来了哪些没被搜出来。这个“亲眼所见”比一百篇教程都管用你会立刻发现切分长度、重叠设置、embedding 模型选择到底是怎么影响结果的。最后一步把“原问题 检索到的资料”拼成提示词交给 LLMfrom langchain.prompts import ChatPromptTemplate from langchain.schema.runnables import RunnablePassthrough, RunnableLambda prompt ChatPromptTemplate.from_messages([ (system, 你是一个严谨的文档问答助手。请仅根据以下资料回答问题 如果资料中没有相关信息请回答「资料中没有找到答案」 不要编造内容。\n\n相关资料\n{context}), (human, 问题{question}) ]) def format_docs(docs): return \n\n.join([d.page_content for d in docs]) rag_chain ( {context: retriever | format_docs, question: RunnablePassthrough()} | prompt | llm ) response rag_chain.invoke(告诉我这个项目的部署步骤是什么) print(response.content)到这里一个最基本的 RAG 问答系统就已经能用了。你输入一个问题它会检索、拼接提示词、让模型基于资料回答。跑通的那一刻你应该能明显感觉到它跟直接问大模型有什么不一样——回答里会带着你文档里的原话而且不再胡编乱造。3.5 为什么检索是 RAG 的灵魂我这么说可能有点绝对但如果你想在简历上写“精通 RAG”你必须把检索这一环做到极致。为什么因为“生成”上面的模型和提示词技巧都已经很成熟了真正拉开差距的是你能不能从海量资料里精准找到那“一块”真正有用的信息。如果你的检索质量不行后面接 GPT-5 都救不回来。这就好比查资料写论文你查错了书写得再华丽也是跑题。在我的 Notebook 里检索策略是单独变成一个实验板块的。我会对比不同检索方式的效果比如similarity纯向量相似度最基础的方式。适合查“表述相近”的问题但容易忽略关键词的精确匹配。mmr最大边际相关性在保证相关性的同时尽量增加返回内容的多样性。适合处理那种需要从多个角度回答的问题避免返回的几块文本内容高度重复。相似度分数阈值过滤设定一个最低分低于阈值的直接不要防止把不相关的文本硬塞给模型。我用一个表格来对比这三种策略在测试集上的表现检索策略场景特点优点缺点向量相似度问题与答案表述接近简单快速语义匹配强可能忽略精确关键词返回结果单一MMR 多样性问题需要多角度信息结果覆盖广避免重复偶尔会带回相关性略低的内容分数阈值过滤问答有严格底线宁缺毋滥自动挡掉低质量片段阈值不好调调太高容易啥都搜不到4. 检索优化从“能跑”到“好用”的关键一跃能让开头那个代码跑起来你已经算是入门了。但离“真正搞懂”还差一步理解为什么有时候答案很蠢。4.1 为什么 Dense Vector Search 不是万能的Dense Vector Search稠密向量检索是目前最主流的检索方案它把文本编码成稠密向量用向量相似度来度量语义相似度。它的优势在于能“联想”比如你在文档里写的是“老王头”问的是“总经理”如果文档里交代了“总经理老王头”它也能找到。但它的毛病也很明显对精确匹配不敏感。比如你搜一串产品编号 “SKU-34567”只要文档里出现的是 “SKU 34567”embedding 可能就会觉得“这俩不太像”你再搜一个罕见的专有名词它的表现往往不如传统的 BM25 关键词检索。所以现在工业界普遍会做Hybrid Search混合检索把向量检索和 BM25 关键词检索的结果融合起来。LangChain 里可以用 EnsembleRetriever 做到from langchain.retrievers import BM25Retriever, EnsembleRetriever bm25_retriever BM25Retriever.from_documents(split_docs) bm25_retriever.k 4 vector_retriever vectorstore.as_retriever(search_kwargs{k: 4}) ensemble_retriever EnsembleRetriever( retrievers[bm25_retriever, vector_retriever], weights[0.3, 0.7] # 关键词检索占30%向量检索占70% )这个配置的直觉是大多数问题还是靠语义理解为主但偶尔那些“精确编码、代码、报错信息”类关键词靠 BM25 能兜住。4.2 元数据过滤只在小范围里搜另一个非常实用的优化是给每个文档块带上元数据来源、章节、日期、类型检索时先根据条件过滤数据范围再做语义搜索。比如我只想在这份“产品 A”的文档里找答案而不是在整个公司所有文档里捞那么可以先指定 metadata 条件retriever vectorstore.as_retriever( search_kwargs{k: 4, filter: {source: 产品A说明书.md}} )这个思路放到生产环境就是多租户隔离、权限控制的基础。不同用户只能搜索到自己权限范围内的数据。所以在构建向量库时千万不要把原始文件路径这种信息丢掉它后期就是你的过滤条件。4.3 “标题优先”或“摘要优先”的特殊策略针对结构化明显的文档一个高级一点的做法是让文档的切分、检索更智能。举个例子我处理一份几十万字的《公司规章制度汇编》如果用普通切分法检索出来的片段可能是一段没有上下文的条例正文。但如果在切分时把所属章节标题作为每条片段的前缀元数据预拼接进去检索时模型就能感知到这部分内容属于“考勤管理制度”这会让整个问答质量上升一个台阶。再比如有一种做法叫Parent Document Retriever父文档检索器检索的时候先检索小块比如 200 字的小段找到最相关的小段后再把这个小段所属的大块内容取出来一起喂给模型。小块负责“定位”大块负责“完整上下文”。当你的文档里有大段的背景信息单独一小块根本说不清楚时这个策略特别管用。4.4 从 RAG 到 Agentic RAG 和 GraphRAG如果你已经能做到前面的所有操作就可以开始了解两个进阶概念了。一个是Agentic RAG。普通 RAG 是“搜索一次就回答”Agentic RAG 是把大模型变成一个智能体它自己决定搜什么、什么时候搜、搜完要不要再搜一次。比如用户问“对比一下我们公司和 A 公司的季度营收变化”智能体可能会先把“我们公司 Q3 营收”和“A 公司 Q3 营收”拆成两次检索然后综合结果回答。另一个是GraphRAG。它用图结构来表示实体之间的关系在检索时不光找相关文本还要沿着图里的关系走一跳、两跳把相关内容全部捞出来。适合做“关系密集型”的知识问答比如多部文档里多个人员之间的关系、机构与项目之间的关系。如果你有兴趣后面我可以专门写一篇 Agentic RAG 的 Notebook 实践拆解一下 ReAct 模式和 Tool Calling 在检索中的应用。5. 如何科学地评估这套 RAG 系统5.1 别只看“回答得好不好”刚跑通的时候你问它几个问题发现回答得不错就觉得自己搞定了。但随着实验次数增加你会发现同一个问题换一种问法回答质量波动很大。这时候就暴露出一个关键问题我们用什么指标来衡量 RAG 系统的质量圈内常用的一套指标叫 RAGASRAG Assessment它把 RAG 拆成了几个维度忠实性Faithfulness回答是否严格基于检索到的上下文有没有瞎编。答案相关性Answer Relevance回答是不是切题的有没有答非所问。上下文相关性Context Relevance检索出来的资料到底跟问题相关不相关上文垃圾多不多。这三个指标叠加起来能帮你定位问题出在“检索”还是“生成”。5.2 用测评集说话我在 Notebook 里会建一个小型的测评集大概 30 到 50 条问答对。每条包含三部分问题、标准答案、所在的原文片段。问题要覆盖不同类型事实类、观点类、缺失信息类故意问文档里没有的内容看它会不会乱答、复合类需要融合多个片段。然后我用 langsmith 或者手动脚本跑评估。如果你不想装额外的工具可以直接调用 OpenAI 等模型做“裁判”让它对照标准答案给回答打分。虽然不完美但比人肉一个个看要高效得多。这里强调一个细节指标永远只是辅助还是要回到真实问法去做验证。我见过很多团队把 RAGAS 分数刷得特别好看一问实际业务场景的刁钻问题就露馅。因为测评集是你自己编的问法多少有点“顺着系统来”真实用户可不会这么好心。我自己的习惯是每次调完参数先跑一遍测评集看指标趋势再手动拿个 5-10 个刁钻问题“人肉验收”。两者一结合系统的可靠性才有保障。5.3 常见评估指标速查表指标考察点简单理解影响它的关键因素忠实性回答是否忠于上下文有没有一本正经地胡说八道提示词约束、模型能力、上下文的是否包含冲突信息答案相关性回答是否贴合问题有没有答非所问检索质量、模型理解能力上下文相关性检索到的资料是否相关喂进去的食材是不是做菜需要的切分策略、embedding 模型、检索策略召回率应该找的全找着了没需要的资料有没有漏掉向量库覆盖度、检索策略、k 值准确率找出来的里面有多少是对的捞上来的垃圾多不多embedding 模型、检索策略有了这套评估体系你再回头看前面那些看似“玄学”的参数调整chunk_size、overlap、k 值、检索策略一切都变得有方向了。6. 踩坑实录跑通 RAG 路上容易遇到的 7 个问题这部分是我最想分享的因为网上教程基本不会讲这些。全部是我在 Notebook 里撞出来的实战经验。6.1 加载 PDF 时中文乱码PyPDFLoader 对有些 PDF 解析效果很差尤其是扫描件或者排版复杂的文档提取出来全是乱码。这在大模型时代是个“很低级但很致命”的问题。解决方向先判断你的 PDF 是文字版还是扫描版。文字版的话换 PyMuPDF 或者 pdfplumber 这类解析库扫描版必须先过 OCR。国内很多公司内部文档都是扫描件所以你在做企业级 RAG 时这块的技能树必须点。6.2 切分后检索精度反而变差这就是典型“为了切分而切分”的坑。比如你把一整段互相强相关的文字硬切成了两块检索时虽然能搜到其中一块但缺少另一块的上下文生成答案时信息不完整。解法一是调大 chunk_overlap让两块有足够的重叠二是换用结构感知的切分器比如按标题切三是用上面前面提到的“父文档检索器”检索小块、返回大块。6.3 相似度分数没意义Chroma 默认返回的是距离distance不是相似度similarity而且数值大小跟你用的 embedding 模型强相关。我之前一度以为 0.8 是高分看到不少检索结果的分数都不到 0.5以为系统坏了。后来才搞清楚不同模型算出来的分数范围本来就不一样必须结合你自己的测试集去定相对阈值。别去背“低阈值大于 0.8 才靠谱”这种话没有任何意义。6.4 重复内容浪费 token向量库里如果存了重复的文档比如同一份说明在多个目录下各有一份检索时可能返回极其相似的结果白白浪费上下文窗口。解决方法是切分后做一次去重比如用哈希比对正文内容或者干脆在入库前让 LLM 跑一遍文本规范化。6.5 上下文长度超限当检索返回 4 个文档块每块 500 字再加对话历史很容易就把上下文窗口撑爆。做法有三个调小 k 值调小 chunk_size引入“对话摘要”把历史对话先压缩再拼接。多数情况下把 k 从 4 调成 3效果都不差。6.6 Token 费用暴涨做学术实验无所谓做生产环境就要精打细算。一条查询的背后embedding 费用 检索 LLM 生成费用看起来不多但 QPS 一上来就是不小的开销。我的习惯是在 vectorstore 层加一层缓存同一个问题如果在短时间内被反复问直接命中缓存不再重新检索和生成。6.7 Notebook 环境崩溃Notebook 跑着跑着挂了尤其是加载大 embedding 模型或者处理超大文本时内存占比飙升。我的经验是把文档加载和向量化拆到单独一个脚本执行结果存到磁盘再用 Notebook 去加载持久化后的向量库。这样 Notebook 只负责做实验和问答负载小很多也不容易崩溃。7. 个人实验心得与下一步扩展方向最后聊点题外的都是真实的项目体会。第一个感受是RAG 的学习路径本质上是“检索质量”的学习路径。模型生成这步你换谁家的 LLM 差距都不大但检索这一步你能从 60 分做到 80 分的空间非常大而且每一步都有清晰的验证方法。这算是 RAG 这个领域比较劝退也比较好玩的地方。第二个感受是Notebook 真的是最适合研究 RAG 的“实验台”。凡是那些需要反复调参、观察中间状态、可视化结果的活Notebook 都有天然优势。现在魔搭社区、Kaggle 这些平台也都提供了免费的 Notebook 环境上手实验的成本已经降到非常低了。你唯一需要的就是一个明确的问题、一份测试文档、一份好奇心。第三个建议是后面核心要做的事是“专精垂直场景”。通用领域的 RAG用 LangChain 默认配置就能搭个七七八八但真到特定领域就完全不是这么回事了。比如有人问“针对 3GPP 协议的 RAG 怎么做”那你就得考虑文档结构识别、专业术语的切分策略、面向协议的检索逻辑这些通用框架根本不替你操心。再比如银行场景的 RAG安全合规、审计追溯、权限隔离这些远比“怎么让回答更准确”要重要。我自己下一步的计划是把这套 Notebook 从本地搬到服务端用 FastAPI 包一层接口配合一个简单的 Web UI做成一个小型知识库问答产品。然后试试在那基础上做 Agentic RAG让模型自己决定要不要检索、检索几次看看能不能进一步提升体验。如果你也正在跑这套 Notebook卡在任何一个环境问题或者理解问题上欢迎在评论里提问。我保证在一个个小问题解决的过程中你会比我更快地理解 RAG 到底在做什么。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →