- 教程
- 人工智能
- 大模型
- RAG
【免费下载链接】all-in-rag
🔍大模型应用开发实战一:RAG 技术全栈指南,在线阅读地址:https://datawhalechina.github.io/all-in-rag/
本文以 Datawhale all-in-rag 仓库中 勾芡香菇汤.md 这份结构化的汤品菜谱为主体,完整讲解其原料配比、操作步骤与烹饪关键点;同时结合仓库第 8 章"尝尝咸淡 RAG 系统"(code/C8)的源码,剖析这份 Markdown 菜谱是如何被加载、打上元数据标签、按标题分块、索引并最终被检索与生成的。读完本文,你既能按图索骥做出一碗浓稠鲜香的勾芡香菇汤,也能理解一份普通菜谱在 RAG 全链路中的数据形态与处理逻辑。
一、菜品简介与难度评估
鲜香菇除了拿来和肉炒外,其实拿来做浓浓的勾芡汤也是非常可口的。香菇本身自带鲜味物质,切片后经短暂煎制再入汤,配合水淀粉勾芡,汤汁浓稠挂口,是一道成本低、操作快、极具家常感的快手汤品。
原文档给出了明确的难度评级:
预估烹饪难度:★★★
这个星级标记并非随意书写,在 RAG 系统的数据准备阶段会被自动解析成结构化的难度标签。见下文"元数据增强"一节。
二、必备原料和工具
制作勾芡香菇汤所需的原料非常精简,全部为常见食材与基础调味料:
| 类别 | 原料 | 说明 |
|---|---|---|
| 主料 | 香菇 | 推荐使用鲜香菇,风味与口感均优于干香菇 |
| 辅料 | 香葱 | 出锅前点缀提香 |
| 调味 | 食用油 | 煎香菇用,建议用无明显气味的植物油 |
| 调味 | 食用盐 | 浸泡去味与出锅调味两用 |
| 调味 | 鸡精 | 增鲜,用量按克计量 |
| 增稠 | 生粉 | 玉米淀粉、土豆淀粉等均可,用于勾芡 |
需要的工具包括:大碗(浸泡香菇用)、小碗(调制水淀粉用)、砧板与菜刀(切片)、炒锅/汤锅、锅铲。
三、用量计算(每份)
原文档给出了按"每份"计量的精确配比,这也是该菜谱可稳定复现的关键:
| 原料 | 用量(每份) |
|---|---|
| 鲜香菇 | 2 朵 |
| 香葱 | 0.5 根 |
| 鸡精 | 3 g |
| 食用油 | 10 ml |
| 食用盐 | 3 g |
| 开水 | 350 ml(其中 50 ml 用于调制水淀粉,300 ml 用于煮汤) |
| 生粉 | 10 g |
注意:操作环节中还会额外用到约 2 g 食用盐用于浸泡香菇,与出锅调味的 3 g 盐分开计量,避免混淆。若一次制作多份,可按上述配比等比例放大。
四、详细操作步骤
原文档的操作步骤紧凑,每一步都包含具体参数。这里按原文档骨架逐条展开,并补充关键点的说明:
香菇切片与盐水浸泡将香菇切成厚 0.5–1 cm 的片,放入大碗中,倒入 2 g 食用盐,浸泡 15 分钟。切片厚度可以自行把握:厚一点相对薄一点更有嚼劲,适合喜欢口感扎实的食客。
调制水淀粉将 10 g 生粉倒入小碗中,加入 50 ml 水,搅拌生粉直至完全融化、没有颗粒,即成水淀粉。这一步是勾芡成功的前提——若生粉未化开就下锅,汤汁中会出现粉疙瘩。
沥干香菇水分(可选)倒掉碗中的盐水,适当去掉香菇本身的水分,方便下一步煎制。此步骤为可选操作,但挤干水分能明显提升煎制效果。
小火煎香菇(可选)锅中小火倒入食用油,待油开始冒小泡(小火约 30 秒,具体视锅的功率而定),下入香菇片,每面煎 10 秒。煎制能激发香菇的焦香风味,是"浓浓的勾芡汤"风味层次的关键来源。
煮汤倒入开水 300 ml,调中火再煮 3–5 分钟,让香菇的鲜味充分融入汤中。
勾芡与调味倒入调制好的水淀粉,适当搅拌锅中汤汁,使其均匀浓稠;随后加入 3 g 盐、3 g 鸡精调味,最后撒上葱花即可出锅。
整个流程从备料到出锅约 25 分钟,其中浸泡 15 分钟是主要的时间开销,实际烹饪时间很短。
五、从菜谱到 RAG 知识库:数据形态与仓库定位
在 all-in-rag 仓库中,这份菜谱并不是孤立的烹饪笔记,它位于 data/C8/cook/dishes/soup/勾芡香菇汤/ 目录下,是第 8 章"尝尝咸淡 RAG 系统"(code/C8)的菜谱数据集成员。整个数据集采用与 HowToCook 社区项目一致的统一结构:每道菜一个目录,目录名即菜品名,内含同名.md菜谱文件(以及可选的过程/成品图片)。
这份数据集对应仓库第 8 章 01_env_architecture.md 中描述的"食谱 RAG 问答系统"——一个让用户用自然语言提问"今天吃什么""勾芡香菇汤怎么做"并得到结构化回答的系统。菜谱的目录层级与标题结构,正是后续数据准备模块元数据提取与分块的基础。
六、数据准备:加载、元数据增强与结构分块
data_preparation.py 是数据准备模块的实现,它对菜谱文档的处理可以分成三步:
6.1 递归加载 Markdown 文件
模块通过Path(data_path).rglob("*.md")递归扫描 data/C8/cook 目录下的全部菜谱文件,直接以 UTF-8 读取原文内容并保持 Markdown 格式,为每个文件分配一个基于相对路径的确定性parent_id(哈希值),同时标记doc_type = "parent"。勾芡香菇汤的菜谱文件正是在这一阶段被读入系统。
6.2 元数据增强:分类、菜品名与难度
_enhance_metadata方法从文件路径和内容中自动抽取三条核心元数据:
- 菜品分类:通过路径片段与
CATEGORY_MAPPING映射匹配。勾芡香菇汤位于soup/目录下,因此被标记为"汤品"。完整映射见源码中的CATEGORY_MAPPING(soup → 汤品、meat_dish → 荤菜、vegetable_dish → 素菜等)。 - 菜品名称:直接取文件名(
Path.stem),即"勾芡香菇汤"。 - 难度等级:使用正则
★+匹配内容中的连续星号数量,再映射到语义标签。预估烹饪难度:★★★会被解析为"中等"(映射表为{5: '非常困难', 4: '困难', 3: '中等', 2: '简单', 1: '非常简单'})。
这意味着当用户问"推荐一道简单的汤品"时,系统可以基于category与difficulty元数据直接过滤,而不必依赖语义猜测。
6.3 Markdown 结构感知分块
_markdown_header_split使用 LangChain 的MarkdownHeaderTextSplitter,按#、##、###三级标题对菜谱进行结构分块(strip_headers=False保留标题以便理解上下文)。以勾芡香菇汤为例,分块结果大致如下:
父文档:勾芡香菇汤.md(完整菜谱) ├── 子块1:# 勾芡香菇汤的做法 + 简介 + 难度评级 ├── 子块2:## 必备原料和工具 + 食材清单 ├── 子块3:## 计算 + 每份用量配比 ├── 子块4:## 操作 + 详细制作步骤 └── 子块5:## 附加内容每个子块都会继承父文档的元数据,并新增chunk_id、parent_id、doc_type = "child"、chunk_index等字段,同时建立parent_child_map父子映射。这正是第 8 章所强调的"小块检索,大块生成"架构:检索阶段用小的子块做精确匹配(例如"勾芡香菇汤需要什么原料"能精确命中"必备原料和工具"子块),生成阶段则通过get_parent_documents反查完整父文档,保证 LLM 拿到上下文完整的菜谱。
七、索引构建与检索优化:这道汤如何被找到
7.1 向量化与索引持久化
index_construction.py 使用HuggingFaceEmbeddings加载BAAI/bge-small-zh-v1.5中文嵌入模型(model_kwargs={'device': 'cpu'},normalize_embeddings=True),将分块后的子块向量化并构建 FAISS 索引,通过save_local持久化到 config.py 中index_save_path指定的./vector_index目录。首次构建后,后续启动直接load_local加载缓存索引,可显著缩短启动时间。
7.2 混合检索与 RRF 重排
retrieval_optimization.py 同时设置了两路检索器:
- 向量检索器(语义相似度):擅长理解查询意图,例如"想做一道浓稠鲜香的香菇汤"这类描述性问法;
- BM25 检索器(关键词匹配):擅长精确匹配,"勾芡香菇汤"这类完整菜名能稳定命中。
两路结果通过 RRF(Reciprocal Rank Fusion,_rrf_rerank)融合,对每个文档按1 / (k + rank + 1)(默认k = 60)累计得分后排序,最终按top_k(config.py 中默认为 3)返回。由于勾芡香菇汤的菜名与"香菇""汤"等关键词在标题和正文中高频出现,它在这两路检索中都能获得较高排名。
7.3 元数据过滤
metadata_filtered_search支持在混合检索结果之上按category、difficulty过滤。用户在 main.py 的_extract_filters_from_query中提问"来道汤品""推荐一道中等难度的菜"时,系统会从查询中抽取"汤品""中等"等关键词作为过滤条件,让"勾芡香菇汤"这类符合条件的目标文档脱颖而出。
八、生成阶段:当用户问"勾芡香菇汤怎么做"
generation_integration.py 负责最终的问答生成,其流程为:
- 查询路由:
query_router将用户问题分为list(推荐/列表)、detail(制作方法)、general(一般问题)三类。"勾芡香菇汤怎么做"会被路由为detail。 - 查询重写:
detail类查询通过query_rewrite判断是否需要改写(明确的菜名查询保持原样)。 - 检索:混合检索 + 元数据过滤,命中该菜谱的相关子块。
- 父子文档还原:
get_parent_documents将命中的子块映射回完整的父文档(去重并按相关性排序)。 - 分步指导生成:
generate_step_by_step_answer使用"菜品介绍 / 所需食材 / 制作步骤 / 制作技巧"的分步模板,结合检索到的完整菜谱生成结构化回答;generate_step_by_step_answer_stream则提供流式输出。也可以运行python main.py进入交互式问答,体验完整链路。
九、小结与延伸
勾芡香菇汤这份菜谱完整地体现了第 8 章 RAG 系统的数据设计思路:目录即分类、文件名即菜名、星级即难度、标题即分块边界。从 勾芡香菇汤.md 到可检索的向量索引,再到"怎么做"的分步回答,每一步都有 data_preparation.py、index_construction.py、retrieval_optimization.py、generation_integration.py 四个模块的源码支撑。
对开发者而言,可以以此为模板,参考 docs/chapter8 的文档与 code/C8 的代码,把任意同构的 Markdown 知识库(菜谱、文档、FAQ)接入这套"小块检索、大块生成"的 RAG 流水线;对读者而言,按照本文步骤备齐香菇、生粉、香葱等原料,约 25 分钟即可收获一碗浓稠鲜美的勾芡香菇汤。
- 教程
- 人工智能
- 大模型
- RAG
【免费下载链接】all-in-rag
🔍大模型应用开发实战一:RAG 技术全栈指南,在线阅读地址:https://datawhalechina.github.io/all-in-rag/
相关推荐
菌菇炖乳鸽做法详解:all-in-rag 食谱知识库中的汤品数据实战解析
菌菇炖乳鸽做法详解:all in rag 食谱知识库中的汤品数据实战解析 本文以仓库中的完整菜谱 菌菇炖乳鸽.md https://link.gitcode.c
教程人工智能大模型RAG朱雀汤(开水冲蛋花汤)食谱全解:从冲制工艺到 RAG 菜谱知识库的汤品数据实践
朱雀汤(开水冲蛋花汤)食谱全解:从冲制工艺到 RAG 菜谱知识库的汤品数据实践 导读 :本篇以 Datawhale「all in rag」仓库 C8 实战项目中
教程人工智能大模型RAGNocoDB 自部署教程:一条命令部署 + 4 个环境变量搞定生产环境
NocoDB 自部署教程:一条命令部署 + 4 个环境变量搞定生产环境 NocoDB 是一款免费、可自托管的 Airtable 替代方案:它不替换你的数据库,而
教程人工智能大模型RAG
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考