十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

水煮鱼菜谱的 RAG 全链路实战:从 Markdown 结构化分块、元数据增强到混合检索与智能生成

水煮鱼菜谱的 RAG 全链路实战:从 Markdown 结构化分块、元数据增强到混合检索与智能生成 教程人工智能大模型RAG【免费下载链接】all-in-rag大模型应用开发实战一RAG 技术全栈指南在线阅读地址https://datawhalechina.github.io/all-in-rag/项目地址https://gitcode.com/datawhalechina/all-in-rag点击查看免费下载导读本文以all-in-rag开源仓库中「尝尝咸淡」食谱问答系统C8 章节项目的真实菜谱数据 —— 水煮鱼.md 为完整样本逐层拆解一份结构化菜谱文档从原始 Markdown 到 RAG 可检索知识块再到被 LLM 引用生成答案的完整处理链路。读者将掌握菜谱文档的标题层级结构与分块策略的关系、元数据增强的字段提取规则分类/难度/菜名、父子文本块小块检索、大块生成的设计动机以及向量检索与 BM25 混合检索 RRF 重排在具体文档上的作用原理并最终能在本地复现该系统对该文档的检索与问答效果。一、样本文档全貌水煮鱼菜谱的完整内容作为「尝尝咸淡」RAG 系统的输入数据data/C8/cook/dishes/aquatic/水煮鱼.md是一份结构高度规整的菜谱原文完整包含如下五大部分这也是后续一切分块、检索、生成操作的事实基础文档开头一级标题 简介 难度评级# 水煮鱼的做法 水煮鱼是一道做法中等难度的硬菜。巴沙鱼富含优质蛋白且脂肪含量低配合各种时令蔬菜十分营养健康。初学者一般需要 2 小时即可完成。 预估烹饪难度★★★★必备原料和工具二级标题巴沙鱼、蔬菜土豆片/豆芽/花菜/生菜等任意搭配红油豆瓣酱、藤椒油、菜籽油、白胡椒粉、蒜瓣、盐、糖量杯、厨房秤可选、大不锈钢碗计算二级标题按 3 至 5 人份量化食材/调料用量备注巴沙鱼500g核心主料蔬菜300g500g土豆片/豆芽/花菜/生菜等可自由搭配红油豆瓣酱40g不怕辣可多加 1020g豆豉10g可选藤椒油10ml麻味来源菜籽油25ml分次使用白胡椒粉3g去腥提味大蒜2 瓣切末盐5g腌制用 3g汆煮调味 2g糖2g提鲜操作二级标题完整 7 步准备冷冻巴沙鱼需室温自然解冻 5 小时后再切片切片撇成约 5cm 长、3cm 宽的薄片腌制将鱼片放入大不锈钢碗加入 30g 豆瓣酱、3g 盐、10ml 藤椒油、3g 白胡椒粉用手抓匀后加入 5ml 菜籽油收尾封味常温静置至少 30 分钟入味备菜大蒜切末以 300g 花菜、200g 生菜为例洗净备用焯水与炒菜花菜开水锅焯水备用生菜洗净晾干炒熟备用不用放油炒豆瓣酱热锅冷油菜籽油 20ml加入 10g 豆瓣酱、10g 豆豉可选和蒜末中火慢炒汆鱼片与盛盘加入 150ml 热水水开后放入腌制好的鱼片轻翻散开加入 2g 盐和 2g 糖调味再次沸腾即盛盘——先铺熟蔬菜垫底再盛鱼片最后浇上锅中剩余热汤。附加内容经验提示垫底蔬菜可自由发挥但需注意各自特性如改用土豆时必须先煮熟可用筷子戳一戳确认红油豆瓣酱辣度与盐量均可按口味调整切鱼片时可先垂直于鱼条方向剁成 5cm 鱼块再翻转 90 度斜撇成薄片腌制时注意不要用力抓以免破坏鱼片。原文档中「腌制」「焯水」两处引用了../../tips/learn/下的通用技巧文件该 tips 目录未随本仓库提供本文以纯文本概念呈现原文档末尾的参考资料区含一条外部视频链接为空或外部内容按仓库规范此处不做外部引用。这份文档的五个标准小标题正是 02_data_preparation.md 中所描述的数据特征结构高度规整、篇幅适中单菜谱约数百字无需过度清洗即可直接进入 RAG 流水线。二、菜谱文档的结构化特征为什么它天然适合 Markdown 结构分块在第 2 章 05_text_chunking.md 中介绍过基于文档结构标题层级的分块方法。水煮鱼这份文档就是该方法的理想样本# 水煮鱼的做法H1菜品名称 ├── ## 必备原料和工具H2 ├── ## 计算H2用量配比 ├── ## 操作H2制作步骤 └── ## 附加内容H2变化做法与技巧这种层级划分直接对应 data_preparation.py 中_markdown_header_split实现的分块器配置headers_to_split_on [ (#, 主标题), # 菜品名称 (##, 二级标题), # 必备原料、计算、操作等 (###, 三级标题) # 简易版本、复杂版本等 ] markdown_splitter MarkdownHeaderTextSplitter( headers_to_split_onheaders_to_split_on, strip_headersFalse # 保留标题便于理解上下文 )对水煮鱼文档执行该分块器后会产生 5 个子块子块 1 含 H1 标题 简介 难度评级子块 25 分别对应必备原料和工具计算操作附加内容。strip_headersFalse保证每个子块自带章节标题即使被单独检索到LLM 也能通过标题理解上下文。为什么不能简单把整个文档当一块文档 01_env_architecture.md 中给出了明确解释当用户问水煮鱼需要什么调料时若以整个文档为单位做向量检索该具体问题在全文中的占比很小可能检索不到或排名靠后而按必备原料和工具这一子块检索就能精确命中需求。这引出了系统的核心设计 —— 父子文本块架构。三、元数据增强从路径与内容中提取分类、难度与菜名在文档加载阶段data_preparation.py 的_enhance_metadata会为水煮鱼文档自动注入三条关键元数据这些字段是后续过滤检索和去重排序的依据1. 菜品分类category—— 从文件路径推断CATEGORY_MAPPING { meat_dish: 荤菜, vegetable_dish: 素菜, soup: 汤品, dessert: 甜品, breakfast: 早餐, staple: 主食, aquatic: 水产, condiment: 调料, drink: 饮品 }水煮鱼位于dishes/aquatic/目录下路径段中命中aquatic键因此被标记为水产。2. 菜品名称dish_name—— 从文件名提取file_path.stem直接取文件名主干得到水煮鱼。3. 难度等级difficulty—— 从内容星号提取star_match re.search(r★, content) if star_match: star_count len(star_match.group()) difficulty_map {5: 非常困难, 4: 困难, 3: 中等, 2: 简单, 1: 非常简单} doc.metadata[difficulty] difficulty_map.get(star_count, 未知)水煮鱼文档中的预估烹饪难度★★★★包含连续 4 颗星正则★匹配后得到star_count4映射结果为困难。这三条元数据同时被记录在父文档上并在分块时通过chunk.metadata.update(doc.metadata)复制到每个子块中见 data_preparation.py使得任意子块都携带完整的分类、难度、菜名信息为 main.py 中_extract_filters_from_query的元数据过滤检索提供支撑——例如用户问推荐一道水产系统会尝试以category水产过滤问做一道困难的水煮鱼可匹配difficulty困难。四、父子文本块小块检索、大块生成数据准备模块的另一个核心职责是维护父子映射关系。加载时每个父文档完整菜谱被分配唯一parent_id分块时每个子块获得独立chunk_id并通过self.parent_child_map[child_id] parent_id记录归属data_preparation.py。水煮鱼文档的父子关系示意父文档水煮鱼.mdparent_id md5(相对路径) ├── 子块1# 水煮鱼的做法 简介 难度评级 ├── 子块2## 必备原料和工具 食材清单 ├── 子块3## 计算 用量配比 ├── 子块4## 操作 详细制作步骤 └── 子块5## 附加内容 变化做法源码细节当前仓库实现中父文档 ID 并非随机 UUID而是hashlib.md5基于数据根目录相对路径计算出的确定性 IDdata_preparation.py保证同一文档多次加载 ID 稳定索引可复用。为什么小块检索、大块生成检索阶段用子块如操作章节做精确匹配命中后由get_parent_documentsdata_preparation.py根据子块携带的parent_id回溯完整父文档交给 LLM相关性统计统计每个父文档被命中的子块数量作为相关性指标去重合并同一道菜即使操作原料多个子块都被命中也只输出一次完整父文档避免重复信息排序输出命中子块越多的菜谱排名越靠前。例如用户问水煮鱼怎么做向量检索可能同时命中操作和计算两个子块去重后仅将完整的水煮鱼文档作为上下文传给生成模块既保证了步骤完整又避免了上下文冗余。这正是文档 01_env_architecture.md 中反复强调的用小块的精确性找到相关内容用大块的完整性保证回答质量。五、检索向量 BM25 双路混合与 RRF 重排在索引构建模块 index_construction.py 中所有子块包括水煮鱼分出的 5 个子块经 BGE-small-zh-v1.5 嵌入模型向量化后存入 FAISS同时子块原文提供给 BM25 检索器。检索阶段retrieval_optimization.py执行双路检索def hybrid_search(self, query: str, top_k: int 3) - List[Document]: vector_docs self.vector_retriever.get_relevant_documents(query) bm25_docs self.bm25_retriever.get_relevant_documents(query) reranked_docs self._rrf_rerank(vector_docs, bm25_docs) return reranked_docs[:top_k]两条检索路径对水煮鱼这类查询各有侧重向量检索语义理解意图与近义表达。例如想吃点鱼别太油腻这类口语化查询可以匹配到巴沙鱼低脂健康的水煮鱼简介子块BM25 检索关键词精确匹配菜名与食材词。水煮鱼巴沙鱼红油豆瓣酱等词能精准命中对应子块避免同义改写带来的漏检。RRFReciprocal Rank Fusion将两路排名融合核心代码为k 60 # RRF 参数 for rank, doc in enumerate(vector_results): rrf_scores[id(doc)] rrf_scores.get(id(doc), 0) 1 / (k rank 1) for rank, doc in enumerate(bm25_results): rrf_scores[id(doc)] rrf_scores.get(id(doc), 0) 1 / (k rank 1)1/(krank)机制使得两路结果中排名靠前的文档获得更高融合分同时避免单一路径排名垄断实现语义与关键词的优势互补。此外retrieval_optimization.py 还提供基于元数据的metadata_filtered_search可结合filter条件如category水产在向量检索阶段先行缩小范围与 main.py 中从用户问题自动提取过滤条件的逻辑配合实现对水产困难等约束的精确响应。六、生成查询路由与分步指导模式检索到水煮鱼相关子块并回溯父文档后generation_integration.py 通过查询路由决定回答方式查询路由query_routergeneration_integration.py将用户问题分为list推荐菜品、detail制作方法、general一般信息三类。如水煮鱼怎么做路由为detail查询重写query_rewrite对模糊查询如推荐个菜改写为简单家常菜推荐对包含具体菜名的查询保持原样回答生成detail类查询进入generate_step_by_step_answer分步指导模式其提示词要求 LLM 灵活组织菜品介绍 / 所需食材 / 制作步骤 / 制作技巧四个部分且强调优先使用原文中的实用技巧、不要强行填充无关内容——这正是水煮鱼文档附加内容中切鱼片技巧、蔬菜搭配经验被充分利用的环节。prompt ChatPromptTemplate.from_template( 你是一位专业的烹饪导师。请根据食谱信息为用户提供详细的分步骤指导。 ... ## 所需食材 ## ‍ 制作步骤 ## 制作技巧 )对于list类查询如推荐一道水产则调用generate_list_answer直接抽取dish_name元数据输出简洁的菜品名称列表无需 LLM 生成长文。七、本地复现与验证水煮鱼文档位于系统数据目录data/C8/cook/dishes/aquatic/下可直接作为「尝尝咸淡」RAG 系统的输入运行验证步骤如下环境准备按 docs/chapter8/01_env_architecture.md 创建 Python 3.12 环境并安装依赖conda create -n cook-rag-1 python3.12.7 conda activate cook-rag-1 cd code/C8 pip install -r requirements.txt配置 API Key在环境变量中设置MOONSHOT_API_KEY默认 LLM 为kimi-k2-0711-preview嵌入模型为BAAI/bge-small-zh-v1.5默认配置见 config.py运行交互式问答python main.py首次运行会遍历data/C8/cook下全部.md文件含水煮鱼执行加载、元数据增强、Markdown 结构分块、向量索引构建并将索引缓存到vector_index/之后启动直接加载缓存秒级就绪。交互阶段可输入水煮鱼怎么做水煮鱼需要什么调料推荐一道水产等问题观察 main.py 打印的路由类型、过滤条件、命中的文档块与最终回答即可完整验证本文所述各环节的实际效果。小结一份看似普通的水煮鱼菜谱在「尝尝咸淡」RAG 系统中经历了标题层级识别 → 元数据增强水产 / 困难 / 水煮鱼→ 父子分块 → 双路混合检索 → RRF 重排 → 智能路由生成的完整生命周期。通过本文对样本文档与 code/C8 源码的对照分析可以看出RAG 效果的上限取决于数据质量与结构利用方式而all-in-rag仓库中的菜谱数据与模块实现正是结构化数据 父子分块 混合检索这一套成熟方案的完整可运行范本。赞分享教程人工智能大模型RAG【免费下载链接】all-in-rag大模型应用开发实战一RAG 技术全栈指南在线阅读地址https://datawhalechina.github.io/all-in-rag/项目地址https://gitcode.com/datawhalechina/all-in-rag点击查看免费下载相关推荐从蒜蓉虾看食谱 RAG 数据准备Markdown 结构化分块与元数据增强实战从蒜蓉虾看食谱 RAG 数据准备Markdown 结构化分块与元数据增强实战 蒜蓉虾是一道广东省地方传统名菜以色香味俱全著称。在本仓库的食谱 RAG教程人工智能大模型RAGDatawhale all-in-rag 实战案例葱油桂鱼做法文档——从结构化菜谱到 RAG 知识库检索的完整链路Datawhale all in rag 实战案例葱油桂鱼做法文档——从结构化菜谱到 RAG 知识库检索的完整链路 葱油桂鱼是一道以清蒸为基底、以热油激香为核教程人工智能大模型RAG从菜谱到RAG知识库金枪鱼酱三明治的Markdown结构化解析与智能问答实战从菜谱到RAG知识库金枪鱼酱三明治的Markdown结构化解析与智能问答实战 这份文档是 Datawhale all in rag 项目实战章 docs/c教程人工智能大模型RAG上一篇Redux DevTools Extension与Marko集成高效模板引擎状态调试方案下一篇Chromebook Linux音频支持终极指南3步快速配置完整解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表