- 教程
- 人工智能
- 大模型
- RAG
【免费下载链接】all-in-rag
🔍大模型应用开发实战一:RAG 技术全栈指南,在线阅读地址:https://datawhalechina.github.io/all-in-rag/
导读
本文以开源仓库 Datawhale all-in-rag 的 C8 章节食谱知识库中的 小炒肉.md 为分析样本,完整还原这道湘式家常菜从原料配比、腌制到出锅的 10 步做法,并以此为窗口,深入解析该菜谱文档在仓库 RAG(检索增强生成)系统中所扮演的数据角色:Markdown 结构感知分块、难度星级元数据解析、混合检索(向量 + BM25 + RRF)与分步骤回答生成的全链路机制。读完本文,你既能照着做出地道的小炒肉,也能理解一份食谱文档如何被「烹饪式」地加工成可检索、可回答的 RAG 知识库语料。
一、小炒肉食谱文档在项目中的定位
小炒肉食谱是 data/C8 食谱数据集下meat_dish(荤菜)分类的一篇标准 Markdown 菜谱。在仓库的目录设计中,每道菜都以独立 Markdown 文件存放,路径本身携带了分类信息:
- 分类依据:路径中的目录名
meat_dish会被映射为「荤菜」; - 菜品名称:文件名
小炒肉会被提取为dish_name元数据; - 难度等级:文档正文中的星级
★★★会被解析为「中等」。
这份文档是 code/C8 中「尝尝咸淡」食谱 RAG 系统的输入语料之一。整个系统围绕data/C8/cook下的全部菜谱构建索引,用户提问「小炒肉怎么做」「推荐几个荤菜」时,系统会先检索相关菜谱,再由大模型组织回答。
二、必备原料与工具清单
原文档完整罗列了制作小炒肉所需的原料与调料(摘自 小炒肉.md):
- 五花肉
- 朝天椒
- 小米椒
- 豆豉
- 豆瓣酱
- 老抽
- 淀粉
- 盐
- 葱
- 蒜
从配料结构看,这是一道典型的「干煸五花 + 双椒 + 豉香」风味菜:朝天椒提供干香,小米椒提供鲜辣,豆豉与豆瓣酱叠加发酵酱香,老抽上色、淀粉锁水,是湘式小炒中「煸香 + 酱香 + 辣香」三味合一的代表做法。
三、每份用量计算(原料配比表)
原文档按「每份」给出精确配比(摘自 小炒肉.md):
| 原料 | 用量(每份) | 备注 |
|---|---|---|
| 五花肉 | 500g | 主料,建议选肥瘦相间的三层五花 |
| 朝天椒 | 4 条 | 干香辣味 |
| 小米椒 | 4 颗 | 鲜辣味 |
| 豆豉 | 10g | 可根据个人口味 ±5g |
| 豆瓣酱 | 10g | 可根据个人口味 ±5g |
| 老抽 | 10ml | 上色 |
| 淀粉 | 10g | 腌制用,锁住肉汁 |
| 盐 | 1-2g | 腌制底味 |
| 葱 | 0.5-1 根 | 切段,出锅前增香 |
| 蒜 | 2 瓣 | 煸香 |
| 食用油 | 15ml | 煸炒用油 |
配比要点:豆豉与豆瓣酱均给出 ±5g 的浮动空间,说明这两味酱料是风味弹性最大的变量——喜重口可加到 15g,喜清淡可减至 5g;盐仅需 1-2g,因为豆瓣酱与豆豉本身含盐,腌制时注意不要过咸。
四、分步操作:10 步还原小炒肉
原文档的完整操作步骤(摘自 小炒肉.md):
- 切肉:五花肉切片。建议切成 2-3mm 的薄片,肥瘦相连,便于快速煸出油脂。
- 腌制:肉片放入器皿,加入淀粉、老抽、盐搅拌,腌制半小时。淀粉 + 老抽 + 盐的腌料组合既上色又保水,半小时的静置让肉片充分吸收底味。
- 备葱:葱切段。
- 备椒:小米椒、朝天椒斜刀切好。斜刀切法增大辣椒与热油的接触面积,更易释放辣味与香气。
- 热锅:热锅、倒油(15ml)。
- 煸肉:油热后加入五花肉煸炒,炒至变色后盛出。这一步目的是逼出五花肉部分油脂,使肉片边缘微焦、口感干香。
- 煸料头:锅中加蒜煸出香味,加入豆豉翻炒均匀。豆豉需经油温激发才会释放豉香。
- 下酱:加入豆瓣酱翻炒均匀。豆瓣酱需炒出红油,酱香才充分。
- 合炒:加入炒好的五花肉继续翻炒均匀,让肉片均匀裹上酱料。
- 收尾:加入小米椒、朝天椒、葱段翻炒 40 秒后出锅。辣椒与葱段不宜久炒,40 秒恰好断生并保持脆感。
五、从菜谱到语料:Markdown 结构感知分块
小炒肉这道菜谱之所以能被 RAG 系统有效检索,关键在于其规范的 Markdown 标题结构。仓库的数据准备模块 data_preparation.py 使用MarkdownHeaderTextSplitter按三级标题分块:
headers_to_split_on = [ ("#", "主标题"), # 菜品名称 ("##", "二级标题"), # 必备原料、计算、操作等 ("###", "三级标题") # 简易版本、复杂版本等 ] markdown_splitter = MarkdownHeaderTextSplitter( headers_to_split_on=headers_to_split_on, strip_headers=False # 保留标题,便于理解上下文 )对应到小炒肉文档,它会被切分为「主标题(小炒肉的做法)」「二级标题(必备原料和工具)」「二级标题(计算)」「二级标题(操作)」等独立 chunk。strip_headers=False意味着每个 chunk 都保留标题文本,使检索到的片段自带语义上下文——当用户问「小炒肉需要什么原料」时,系统能直接命中「必备原料和工具」这一块。
分块后,每个子块还会被打上chunk_id、parent_id、chunk_index等元数据,并维护parent_child_map父子映射(见 data_preparation.py),为后续「检索子块 → 回溯完整菜谱」的小块召回 / 父文档生成(Parent Document Retrieval)模式奠定基础。
六、元数据增强:星级如何变成「中等」
数据准备模块会对每篇菜谱自动增强元数据(见 data_preparation.py):
# 提取菜品分类:路径含 meat_dish → '荤菜' # 提取菜品名称:文件名 小炒肉 → '小炒肉' # 分析难度等级(使用正则精确匹配连续星号数量) 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, '未知')小炒肉文档开头的「预估烹饪难度:★★★」会被正则★+匹配到连续 3 颗星,从而映射为难度「中等」。这解释了菜谱文档为什么约定用连续星号而非「三颗星」之类的文字表述——星号长度可直接被正则计算,是机器友好的难度编码方式。
增强后的元数据(category=荤菜、dish_name=小炒肉、difficulty=中等)会随子块一并进入向量索引,并被检索阶段的元数据过滤和回答生成阶段的上下文格式化所复用。
七、检索与生成:小炒肉如何被「回答」出来
7.1 混合检索 + RRF 重排
索引构建模块 index_construction.py 使用BAAI/bge-small-zh-v1.5嵌入模型在 CPU 上完成向量化,并构建 FAISS 索引;检索优化模块 retrieval_optimization.py 则同时启用向量检索与 BM25 检索,再用 RRF(Reciprocal Rank Fusion)融合排序:
rrf_score = 1.0 / (k + rank + 1) # k 默认 60当用户问「小炒肉怎么做」时,向量检索负责语义匹配「做法 / 操作」类片段,BM25 则精确命中「小炒肉」这一关键词,两者经 RRF 融合后按 config.py 中的top_k=3返回 Top-3 子块。
7.2 查询路由与分步骤回答
主程序 main.py 在检索前先用大模型对问题路由:list(推荐列表)/detail(具体做法)/general(一般问题)。「小炒肉怎么做」会被路由为detail,随后触发generate_step_by_step_answer——生成集成模块 generation_integration.py 中的烹饪导师提示词会要求 LLM 按「菜品介绍 / 所需食材 / 制作步骤 / 制作技巧」组织回答,且明确「优先使用原文中的实用技巧,如果原文的附加内容与烹饪无关或为空,可以省略」——小炒肉文档的「附加内容」章节为空,模型将基于制作步骤总结要点。
检索到的子块会通过get_parent_documents回溯到完整菜谱(见 data_preparation.py),保证生成阶段拿到的是包含原料、用量、操作在内的整篇小炒肉文档,而非零散片段。
八、动手实践:运行与提问
在code/C8目录下按 requirements.txt 安装依赖,设置MOONSHOT_API_KEY环境变量后运行 main.py:
export MOONSHOT_API_KEY=your_key_here python main.py系统默认数据路径为../../data/C8/cook,可覆盖 config.py 中的data_path、embedding_model、llm_model、top_k、temperature等配置。可尝试的提问:
- 「小炒肉怎么做」→ 路由为 detail,返回分步骤制作指导;
- 「推荐几道荤菜」→ 路由为 list,返回去重后的菜品名列表;
- 「有没有中难度的菜」→ 触发元数据过滤,命中
difficulty=中等的菜谱。
九、小结
一份看似简单的小炒肉菜谱,在 Datawhale all-in-rag 的 C8 食谱 RAG 系统中完成了「文档加载 → 元数据增强(分类 / 菜名 / 难度)→ 结构感知分块 → 向量 + 关键词混合索引 → 路由 + 重写 + 检索 + 分步生成」的完整数据旅程。理解这份菜谱文档的格式约定(星号难度、标题层级、分类目录),也就掌握了为 RAG 知识库设计高质量结构化语料的核心要领——无论是菜谱,还是任何领域的技术文档,良好的结构本身就是最好的「可检索性设计」。
- 教程
- 人工智能
- 大模型
- RAG
【免费下载链接】all-in-rag
🔍大模型应用开发实战一:RAG 技术全栈指南,在线阅读地址:https://datawhalechina.github.io/all-in-rag/
相关推荐
Hindsight 中 AI Agent 的短期记忆与长期记忆:两层架构、retain/recall 实现与落地评估方法
Hindsight 中 AI Agent 的短期记忆与长期记忆:两层架构、retain/recall 实现与落地评估方法 理解"短期记忆 vs 长期记忆"这一主
教程人工智能大模型RAGRoo Code v2.2.29 发布解析:为自动写入增加可配置延迟,让诊断与 Linter 从容跟上
Roo Code v2.2.29 发布解析:为自动写入增加可配置延迟,让诊断与 Linter 从容跟上 Roo Code 2.2.29 引入了一项直接影响开发体
教程人工智能大模型RAG以「咖喱炒蟹」为例:all-in-rag 食谱 RAG 系统数据准备实战解析
以「咖喱炒蟹」为例:all in rag 食谱 RAG 系统数据准备实战解析 本篇以 all in rag 第 8 章「尝尝咸淡」食谱 RAG 系统知识库中的一
教程人工智能大模型RAG
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考