commit 572283e101848fefe428735409d83b18d80544bb Author: lzaske Date: Tue May 12 09:41:56 2026 +0800 Initial commit diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..317067d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,77 @@ +name: "问题反馈:代码或文档问题" +description: "报告教程中的代码错误、文档错误、链接失效等问题" +labels: ["bug", "needs triage"] +title: "[问题反馈] 简要概述问题" +body: + - type: checkboxes + id: checklist + attributes: + label: 提交前检查 + description: 为了提升处理效率,请先确认以下事项 + options: + - label: 我已在 Issues 中搜索,未找到相同问题 + required: true + - label: 我已使用仓库最新版(或 `main` 分支)进行复现 + required: true + - type: dropdown + id: issue_type + attributes: + label: 问题类型 + options: + - 代码运行错误 + - 文档描述错误/不清晰 + - 链接失效/资源缺失 + - 依赖/环境问题 + - 其他 + validations: + required: true + - type: input + id: location + attributes: + label: 位置(章节/文件路径) + description: 如 `docs/chapter4/11_hybrid_search.md` 或 `code/C8/main.py` + placeholder: 请输入章节编号、文档路径或代码相对路径 + validations: + required: true + - type: textarea + id: description + attributes: + label: 问题描述 + description: 请清晰说明问题表现与期望行为 + placeholder: 实际结果 vs 期望结果 + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: 复现步骤 + description: 清晰的复现步骤有助于快速定位 + placeholder: | + 1. ... + 2. ... + 3. ... + - type: textarea + id: minimal_code + attributes: + label: 最小可复现代码/命令 + description: 请尽量提供最小复现片段,或给出命令行 + render: shell + placeholder: | + python code/C8/main.py --config ... + - type: textarea + id: env + attributes: + label: 环境信息 + description: 操作系统、Python/Node 版本、依赖版本等 + placeholder: | + OS: Windows 11 22631 + Python: 3.10.x + 依赖: langchain==..., llama-index==... + - type: textarea + id: logs + attributes: + label: 日志/报错信息与截图 + description: 可粘贴报错文本或上传截图 + render: bash + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..8bf1f4a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,3 @@ +blank_issues_enabled: false + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..127e36d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,54 @@ +name: "需求建议:希望新增教程内容" +description: "提出希望本仓库新增/扩展的教程主题或方向" +labels: ["enhancement", "discussion"] +title: "[需求建议] 简要概述主题/方向" +body: + - type: checkboxes + id: checklist + attributes: + label: 提交前检查 + options: + - label: 我已在 Issues 中搜索,未找到相同或高度相似的建议 + required: true + - type: input + id: topic + attributes: + label: 希望新增的教程主题/模块 + description: 尽量简洁、明确 + placeholder: 例如:Agentic RAG、企业级项目 + validations: + required: true + - type: textarea + id: context + attributes: + label: 背景与痛点 + description: 为什么需要这一模块?解决哪些实际问题? + placeholder: 场景背景、业务需求、目前的缺口 + validations: + required: true + - type: textarea + id: scope + attributes: + label: 建议覆盖的内容范围 + description: 可按章节/功能点列出 + placeholder: | + 1. 主题概述与系统架构 + 2. 环境与数据准备 + 3. 检索/索引/生成一体化示例 + 4. 评估与监控 + - type: textarea + id: audience + attributes: + label: 目标读者与预期效果 + description: 面向人群与学完后能做什么 + placeholder: 面向初学/进阶/生产落地;预期掌握的能力 + - type: textarea + id: references + attributes: + label: 相关资料/链接(选填) + description: 参考项目、论文、博客、Demo 等 + placeholder: | + - 论文/项目链接:... + - 竞品或类似教程:... + + diff --git a/.github/ISSUE_TEMPLATE/study_feedback.yml b/.github/ISSUE_TEMPLATE/study_feedback.yml new file mode 100644 index 0000000..1e39f3b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/study_feedback.yml @@ -0,0 +1,45 @@ +name: "学习反馈:学习体验与改进建议" +description: "分享你的学习体验、遇到的困惑,以及对教程改进的建议" +labels: ["feedback"] +title: "[学习反馈] 简要概述你的体验" +body: + - type: dropdown + id: experience + attributes: + label: 整体学习体验 + options: + - 非常好 + - 较好 + - 一般 + - 需要改进 + - 较差 + validations: + required: true + - type: textarea + id: what_helped + attributes: + label: 觉得教程哪些部分做得比较好? + placeholder: 例如:章节结构清晰、代码可运行、图示易懂... + - type: textarea + id: what_confusing + attributes: + label: 学习过程中遇到的困惑/不足 + description: 请指出具体章节或文件,便于改进 + placeholder: 例如:`docs/chapter3/06_vector_embedding.md` 的某段描述不清晰 + - type: textarea + id: improvement + attributes: + label: 你希望如何改进? + placeholder: 举例说明更好的呈现方式、补充案例、增加背景知识等 + - type: input + id: time_cost + attributes: + label: 学习用时(选填) + placeholder: 例如:总计约 6 小时 + - type: textarea + id: other + attributes: + label: 其他想说的话(选填) + placeholder: 欢迎分享你的收获或对作者的建议 + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4860020 --- /dev/null +++ b/.gitignore @@ -0,0 +1,73 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual Environment +venv/ +ENV/ + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# Environment variables +.env +.env.local + +# Logs +*.log +logs/ + +# Jupyter Notebook +.ipynb_checkpoints + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# python环境相关目录 +rag/ + +# Model files +*.h5 +*.pt +*.pth +*.ckpt +*.pkl +*.faiss + +# Cache +.cache/ +.cache/modelscope/ +.cargo + +# Models + +# LLM API keys +*.key +*.secret diff --git a/Extra-chapter/Neo4J-Simple-Application/images/1_4_2_1.png b/Extra-chapter/Neo4J-Simple-Application/images/1_4_2_1.png new file mode 100644 index 0000000..ff72b8a Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/1_4_2_1.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/1_4_3_1.png b/Extra-chapter/Neo4J-Simple-Application/images/1_4_3_1.png new file mode 100644 index 0000000..39eb55e Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/1_4_3_1.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/1_4_3_2.png b/Extra-chapter/Neo4J-Simple-Application/images/1_4_3_2.png new file mode 100644 index 0000000..7725c34 Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/1_4_3_2.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/1_4_3_3.png b/Extra-chapter/Neo4J-Simple-Application/images/1_4_3_3.png new file mode 100644 index 0000000..8f8eb88 Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/1_4_3_3.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/2_1_1.png b/Extra-chapter/Neo4J-Simple-Application/images/2_1_1.png new file mode 100644 index 0000000..a21f5cc Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/2_1_1.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/2_1_2.png b/Extra-chapter/Neo4J-Simple-Application/images/2_1_2.png new file mode 100644 index 0000000..d20fe75 Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/2_1_2.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/2_1_3.png b/Extra-chapter/Neo4J-Simple-Application/images/2_1_3.png new file mode 100644 index 0000000..7bc9506 Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/2_1_3.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/2_1_4.png b/Extra-chapter/Neo4J-Simple-Application/images/2_1_4.png new file mode 100644 index 0000000..0eaf936 Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/2_1_4.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/2_2_1_1.png b/Extra-chapter/Neo4J-Simple-Application/images/2_2_1_1.png new file mode 100644 index 0000000..c5541f6 Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/2_2_1_1.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/2_2_1_2.png b/Extra-chapter/Neo4J-Simple-Application/images/2_2_1_2.png new file mode 100644 index 0000000..15a5e1a Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/2_2_1_2.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/images/2_2_2_1.png b/Extra-chapter/Neo4J-Simple-Application/images/2_2_2_1.png new file mode 100644 index 0000000..e2b6d30 Binary files /dev/null and b/Extra-chapter/Neo4J-Simple-Application/images/2_2_2_1.png differ diff --git a/Extra-chapter/Neo4J-Simple-Application/readme.md b/Extra-chapter/Neo4J-Simple-Application/readme.md new file mode 100644 index 0000000..4e861da --- /dev/null +++ b/Extra-chapter/Neo4J-Simple-Application/readme.md @@ -0,0 +1,486 @@ +# Neo4J 简单应用 + +## 一、什么是知识图谱 + +**知识图谱(Knowledge Graph, KG)** 源于自然语言理解,其目标是用一种结构化的方式,来描述现实世界中的实体及其相互关系。它主要由两个核心要素构成: + +1. **节点(Nodes)**:代表现实世界中的“实体”(Entities),例如一个人、一部电影、一家公司或一个具体概念。 +2. **边(Edges)**:代表实体与实体之间的“关系”(Relations)。 + +这些元素共同构成了一个庞大的语义网络,其基本结构可以表示为 **(实体)- [关系] -> (实体)** 的三元组(Triples)。例如,“饺子”和“哪吒2”是两个实体,“导演”就是它们之间的关系,构成一个知识三元组:(饺子)- [导演] -> (哪吒2)。 + +## 二、知识图谱的应用 + +知识图谱并非一个孤立的学术概念,它在工业界有着广泛且深入的应用,尤其是在需要深度结合领域知识的场景中。 + +### 2.1 风险识别与网络分析 + +俗话说“近朱者赤,近墨者黑”,在许多领域,一个实体的风险或属性,往往与其关联的其他实体有很强的相关性。知识图谱正是挖掘这种关联性的利器。 + +- **犯罪网络侦查**:公安部门可以利用通话记录、社交关系、转账流水等信息构建犯罪嫌疑人网络。在这个网络中,如果某个节点与多个已知的犯罪分子有直接或间接的联系,那么他参与犯罪的可能性就大大增加。通过分析网络中的核心人物(连接数最多的节点)和资金流向,可以有效地打击整个犯罪团伙。 +- **信用卡反欺诈**:银行可以将申请人的信息(如电话、地址、公司)构建成一个庞大的关系网络。通过分析这张网络,可以识别出“欺诈团伙”——例如,多个申请人共享同一个联系电话或家庭住址,或者与已知的欺诈分子有紧密的社交关系。 + +### 2.2 智能诊断与运维 + +- **工业设备运维**:将设备的各种“故障现象”、“故障原因”、“解决方案”和“所需零件”构建成知识图谱。当设备出现问题时,系统可以根据上报的现象,在图谱中进行推理,快速定位可能的原因,并给出维修建议,甚至可以提示维修人员需要携带哪些工具和备件,从而提高维修效率。 +- **医疗辅助诊断**:医疗领域知识繁杂,可以通过构建“病症”、“疾病”、“检查项目”、“治疗方案”、“药品”之间的关系图谱。医生输入患者的症状后,系统可以辅助推荐需要进行的检查,并根据检查结果在图谱中推理,给出可能的诊断建议和治疗方案,帮助实现规范化诊疗。 + +### 2.3 特定领域聊天机器人 + +对于通用领域的开放式聊天,大语言模型(LLM)已展现出强大的能力。但在许多垂直领域,基于知识图谱的问答系统(KBQA)因其答案的准确性和可解释性,仍然具有不可替代的价值。其工作流程通常如下: + +1. **意图识别**:首先判断用户提问的意图。例如,“我想买一张明天上午的故宫门票”这个问题的意图是“票务预订”。 +2. **槽位填充 (实体抽取)**:从问题中抽取出关键信息,即“实体”。例如:`景点: 故宫`, `时间: 明天上午`, `数量: 一张`。 +3. **知识查询**:利用抽取出的实体,在知识图谱(或数据库)中进行精确查询。 +4. **回复生成**:将查询到的结果,通过预设的模板生成自然语言回复。 + +这种方式虽然不如 LLM 灵活,但在机票预订、酒店查询、银行客服等业务逻辑明确的场景中,能够提供更加可靠和可控的服务。 + +## 三、知识图谱的构建 + +如何从海量的、非结构化的文本(如新闻、财报、医疗记录)中,自动地构建出结构化的知识图谱,是整个技术流程的核心挑战。 + +### 3.1 经典构建流程 + +传统的知识图谱构建过程主要依赖于两项关键的 NLP 技术: + +1. **命名实体识别 (Named Entity Recognition, NER)**:从文本中识别并抽取出特定类别的实体。例如,在“英伟达发布了专为 AI 设计的 Blackwell 芯片”这句话中,识别出“英伟达”(公司)、“Blackwell”(产品)。这些被抽取的实体将成为知识图谱中的 **节点**。 +2. **关系抽取 (Relation Extraction, RE)**:在识别出实体的基础上,进一步判断实体与实体之间存在何种语义关系。在上面的例子中,模型需要判断“英伟达”和“Blackwell”之间的关系是“发布”。这个关系将成为连接两个节点的 **边**。 + +通过对大量文本进行这两步处理,我们就能源源不断地抽取出知识三元组,最终汇聚成一个庞大的知识图谱。 + +### 3.2 大模型带来的革新 + +随着大语言模型的兴起,传统的 NLP 任务流程正在被重塑。LLM 同样具备强大的实体识别和关系抽取能力,但这并不意味着对传统流程的简单替代,而是呈现出深度融合的趋势。 + +- **局限性与挑战**:完全依赖 LLM 会面临成本高昂、数据隐私(使用闭源 API 时)、以及“幻觉”问题,即模型可能会编造事实。 +- **融合方案**:为了结合知识图谱的准确性和大模型的推理能力,微软提出了 GraphRAG。原理是将知识图谱作为一个可靠、可随时更新的 **外部知识库**,并基于图结构进行“子图检索”(如社区发现、路径搜索等),而非检索孤立事实。当用户提问时: + 1. 利用模型从问题中识别出核心实体与约束。 + 2. 在图中检索与之高度相关的子图(社区/路径/邻域),获得准确且可解释的事实与关系。 + 3. 将该子图的结构化信息作为上下文,连同原始问题一起输入给大语言模型,生成基于证据的答案。 + +## 四、图数据库:Neo4j + +> [Neo4j 官方文档](https://neo4j.com/docs/) + +知识图谱需要专门的数据库进行存储和查询,这类数据库被称为 **图数据库 (Graph Database)**。其中,与传统的关系型数据库(如 MySQL)相比,图数据库的优势在于其对“关系”的查询性能。对于需要进行多层关系遍历的复杂查询(例如,查询“我朋友的朋友”),图数据库的效果远超关系型数据库。而 **Neo4j** 就是目前比较流行的一款开源图数据库。 + +### 4.1 核心概念 + +Neo4j 的数据模型主要包含以下几个概念: + +- **节点 (Node)**:节点是图中的基本数据单元,用于表示现实世界中的实体,例如一个人、一家公司、一本书或一个账户。在关系型数据库中,节点可以类比为表中的一行。 + +- **标签 (Label)**:用于为节点分类或打上“类型”标记。一个节点可以拥有一个或多个标签。例如,一个节点可以同时拥有 `:Person` 和 `:Author` 两个标签,表示这个人既是一个普通人,也是一位作者。 + +- **关系 (Relationship)**:这是图数据库的精髓所在,它以一种富有表现力的方式连接两个节点,并明确地定义了它们之间的联系。每个关系都具有以下特点: + - **有方向**:关系总是从一个“起始节点”指向一个“结束节点”。 + - **有类型**:每个关系都必须有一个类型(例如 `:FRIENDS_WITH`, `:PURCHASED`),用来描述连接的性质。 + - **可以拥有属性**:和节点一样,关系也可以存储属性,例如,一个 `:PURCHASED` 关系可以有一个 `date` 属性来记录购买日期。 + +- **属性 (Property)**:属性是以键值对(Key-Value)形式存储在节点和关系上的详细信息。键是字符串,值可以是各种基本数据类型(如字符串、数字、布尔值)或它们的数组。 + +这四个概念共同构成了一个灵活而强大的数据模型。 + +```mermaid +graph LR + A["Alice:Person {name: 'Alice'}"] + B["Bob:Person {name: 'Bob'}"] + A -- "KNOWS {since: 2020}" --> B +``` +> 在上图中,`Alice` 和 `Bob` 是 **节点**,`:Person` 是 **标签**,`{name: 'Alice'}` 是 **属性**,`KNOWS` 则是连接它们的 **关系** 类型,而 `{since: 2020}` 是这段关系上的 **属性**。 + +### 4.2 查询语言:Cypher + +Cypher 是 Neo4j 的声明式图形查询语言,它的语法灵感来源于 SQL,但针对图的特性进行了优化。通过 Cypher,我们可以用一种直观且高效的方式来查询和操作图数据。 + +例如,要查找在电影《黑客帝国》(The Matrix) 中出演过的所有演员,可以使用以下查询: + +```cypher +MATCH (actor:Person)-[:ACTED_IN]->(movie:Movie {title: 'The Matrix'}) +RETURN actor.name +``` + +官方的 Cypher 语法速查表([在线版本](https://neo4j.com/docs/cypher-refcard/4.4/))汇总了常用的命令、操作符和语法结构,可供读者快速查阅。 + +
+ Cypher 语法速查表 +

图 1.1: Cypher 语法速查表 (Cypher Refcard)

+
+ +### 4.3 安装与使用 + +对于初学者和开发者,推荐以下两种主流的安装方式。 + +1. **Neo4j Desktop (推荐用于本地学习)** + - **安装**: + 1. 访问 [Neo4j 官网](https://neo4j.com/download/),在 “Neo4j for Desktop” 板块点击 “Download” 按钮。 +
+ Neo4j Desktop 下载页面 +

图 1.2: 在官网点击下载

+
+ 2. 页面会跳转至一个注册表单。可以填写任意信息,然后点击 “Download Desktop” 按钮,浏览器将自动开始下载安装包。 +
+ 下载前填写表单 +

图 1.3: 填写注册表单

+
+ 3. 下载完成后,双击安装文件,程序会自动进行安装。 + 4. 安装完成后首次启动,会看到许可协议界面,点击 “Continue” 即可完成最后的设置。 +
+ 同意许可协议 +

图 1.4: 首次启动并同意许可协议

+
+ +2. **Docker (推荐用于服务器部署与跨平台开发)** + - **安装**: 只需一行命令即可完成拉取镜像和启动容器。 + ```bash + docker run \ + --name my-neo4j \ + -p 7474:7474 -p 7687:7687 \ + -d \ + -v $HOME/neo4j/data:/data \ + -v $HOME/neo4j/logs:/logs \ + --env NEO4J_AUTH=neo4j/password \ + neo4j:latest + ``` + - **参数说明**: + - `-p 7474:7474`: 将容器的 HTTP 端口映射到本机,用于浏览器访问。 + - `-p 7687:7687`: 将容器的 Bolt 驱动端口映射到本机,用于代码连接。 + - `-v $HOME/neo4j/data:/data`: 将数据目录挂载到本机,确保数据持久化。 + - `--env NEO4J_AUTH=neo4j/password`: 设置数据库的初始用户名和密码(此处为 `neo4j/password`)。 + - `neo4j:latest`: 使用最新的官方镜像。 + +安装好 Neo4j 后。我们就可以学习一些 Neo4j 的基本用法了。 + +## 五、创建并连接数据库 + +在使用 Neo4j 进行开发时,首先需要在 Neo4j Desktop 中创建一个本地数据库实例(Instance)。这个过程非常直观。 + +1. **创建实例**:打开 Neo4j Desktop,在 “Local instances” 页面点击 “Create instance” 按钮。 + +
+ 创建实例 +

图 2.1: 点击创建实例

+
+ +2. **配置实例**:在弹出的窗口中,为实例命名(例如 `base nlp`),选择所需的 Neo4j 版本,并为默认用户 `neo4j` 设置一个能记住的密码。完成后点击 “Create”。 + +
+ 配置实例 +

图 2.2: 配置实例信息

+
+ +3. **启动与连接**:实例创建后会自动启动,状态显示为 “RUNNING”。此时,可以通过浏览器直接访问 `http://127.0.0.1:7474` 来打开 Neo4j Browser。 + +
+ 启动实例 +

图 2.3: 实例创建成功并运行

+
+ + 在浏览器打开的连接界面中,使用刚刚设置的密码进行连接。 + +
+ 连接实例 +

图 2.4: 使用密码连接数据库

+
+ +## 六、增删查改 + +数据库操作的核心无外乎增删查改(CRUD),下面来使用 Cypher,围绕一个菜品信息图谱的场景,逐一介绍这些基本操作。 + +### 6.1 场景设定 + +为了方便演示,先设定好本次实践所需要用到的实体、属性和关系。 + +- **实体/标签 (Labels)**: + - `Ingredient`: 食材,拥有 `name`, `category`(类别), `origin`(产地), `tags`(标签,数组)等属性。 + - `Dish`: 菜品,拥有 `name`, `cuisine`(菜系)等属性。 +- **关系 (Relationships)**: + - `(Dish)-[:包含]->(Ingredient)`: 表示某菜品包含某种食材,关系上可以有 `用量` 属性。 + - `(Dish)-[:主要食材]->(Ingredient)`: 表示某菜品的主要食材是某种食材。 + - `(Dish)-[:调味]->(Ingredient)`: 表示某菜品使用某种食材进行调味。 + +### 6.2 创建 (CREATE) + +`CREATE` 语句用于在图中创建新的节点和关系。 + +#### 6.2.1 创建节点 + +创建节点的基本语法是 `CREATE (变量:标签 {属性: 值})`。 + +- **变量 (Variable)**: 如 `pork`,是一个临时名称,用于在同一条语句中引用该节点。如果后续不需要引用,可以省略。 +- **标签 (Label)**: 如 `Ingredient`,用于对节点进行分类。 +- **属性 (Properties)**: 一个包含键值对的 map/字典,用于描述节点的具体信息。 + +最基础的创建语句包含一个临时变量(`pork`)、一个标签(`Ingredient`)和一组属性。 + +```cypher +CREATE (pork:Ingredient {name:'猪肉', category:'肉类', origin:'杭州'}); +``` + +如果在创建后不需要立刻使用这个节点(例如,在同一查询中创建关系),可以省略临时变量名,这样语法更简洁。 + +```cypher +CREATE (:Ingredient {name:'土豆', category:'蔬菜', origin:'北京'}); +``` + +还可以在创建节点后,使用 `RETURN` 子句立即将其返回。这对于调试或确认节点是否按预期创建非常有用。`RETURN n` 会在结果面板中直接显示刚刚创建的 `鸡蛋` 节点的信息。 + +```cypher +CREATE (n:Ingredient {name:'鸡蛋'}) RETURN n; +``` + +执行上述三条命令后,数据库中就创建了三个 `Ingredient` 类型的节点。能够通过 Neo4j Browser 的可视化界面直观地看到这些新创建的数据。 + +
+ 创建节点后的数据库信息 +

图 2.5: 执行创建命令后,左侧面板显示已有 3 个 Ingredient 节点

+
+ +点击左侧面板中的 `Ingredient` 标签,Neo4j Browser 会自动执行 `MATCH (n:Ingredient) RETURN n LIMIT 25;` 查询,并在主窗口中展示所有食材节点。如图 2.6 所示,点击其中一个节点(如“土豆”),右侧会显示其详细属性。这里可以观察到: + +- **`` 字段**:这是 Neo4j 为每个节点自动生成的内部唯一标识符。 +- **Key-Value 结构**:右侧的 “Key” 和 “Value” 两列展示了节点属性是以键值对的形式存储的。 +- **自定义属性**:`name`、`category`、`origin` 三个字段的值与前面 `CREATE` 语句中设定的值完全一致。 + +
+ 查询并查看节点详情 +

图 2.6: 查询并查看新创建的节点及其属性

+
+ +#### 6.2.2 创建关系 + +关系的创建通常需要先指定关系两端的节点,然后用 `-[变量:类型 {属性}]->` 来定义关系。 + +- 关系必须有 **方向** 和 **类型 (Type)**。 +- 小括号 `()` 用于表示节点,中括号 `[]` 用于表示关系。 + +在实际应用中,常常需要一次性创建多个节点以及它们之间的关系。`CREATE` 语句支持通过逗号分隔,在一个查询中完成复杂图谱的构建。下面的例子将创建一个更复杂的菜品关系网络,以体现“多对多”的特性(一道菜包含多种食材,一种食材可用于多道菜)。 + +```cypher +CREATE + // 创建食材节点 + (rousi:Ingredient {name:'猪里脊'}), + (muer:Ingredient {name:'木耳'}), + (huluobo:Ingredient {name:'胡萝卜'}), + (qingjiao:Ingredient {name:'青椒'}), + // 创建菜品节点 + (d1:Dish {name:'鱼香肉丝', cuisine:'川菜'}), + (d2:Dish {name:'木须肉', cuisine:'鲁菜'}), + // 创建关系 + (d1)-[:包含 {amount:'250g'}]->(rousi), (d1)-[:包含]->(muer), (d1)-[:包含]->(huluobo), + (d2)-[:包含 {amount:'150g'}]->(rousi), (d2)-[:包含]->(muer), + // 创建双向关系 + (rousi)-[:被用于]->(d1), (muer)-[:被用于]->(d1), (huluobo)-[:被用于]->(d1), + (rousi)-[:被用于]->(d2), (muer)-[:被用于]->(d2); +``` +这个查询语句做了以下几件事: +1. **创建了 4 个 `Ingredient` 节点**:猪里脊、木耳、胡萝卜、青椒。 +2. **创建了 2 个 `Dish` 节点**:鱼香肉丝、木须肉。 +3. **创建了 5 条 `包含` 关系**:从菜品指向食材。 +4. **创建了 5 条 `被用于` 关系**:从食材指向菜品。这样既可以方便地查询“一道菜包含哪些食材”,也可以高效地反向查询“一种食材被用在了哪些菜里”。 + +执行 `MATCH p=()-[:包含]->() RETURN p LIMIT 25;` 查询可以可视化展示所有“包含”关系。点击关系(箭头),可以在右侧看到其详细信息,例如“鱼香肉丝”到“猪里脊”的关系上,就包含了在 `CREATE` 语句中定义的 `amount: '250g'` 这一属性。 + +
+ 同时创建节点和关系后的图谱 +

图 2.7: 创建关系后的图谱结构

+
+ +### 6.3 查询 (MATCH) + +`MATCH` 是 Cypher 中用于查询图数据的命令,它允许你描述你想要寻找的节点和关系的模式。 + +#### 6.3.1 基本查询 + +最简单的查询是匹配并返回图中的任意节点,可以使用 `LIMIT` 关键字限制返回数量,避免因数据量过大导致浏览器卡顿。 + +```cypher +// 匹配并返回图中的任意 25 个节点 +MATCH (n) +RETURN n +LIMIT 25; +``` + +也可以根据标签和属性进行精确匹配。 + +```cypher +// 匹配所有标签为 Ingredient,且名字为'猪里脊'的节点 +MATCH (n:Ingredient {name:'猪里脊'}) RETURN n; +``` + +#### 6.3.2 条件查询 (WHERE) + +`WHERE` 子句提供了更灵活的过滤能力,可以对节点的属性进行复杂的逻辑判断。 + +例如,查询名字是'猪里脊'或'鸡蛋'的 `Ingredient` 节点。 + +```cypher +MATCH (n:Ingredient) +WHERE n.name IN ['猪里脊','鸡蛋'] +RETURN n; +``` + +也可以使用 `AND`、`OR` 等关键字构建复合查询条件。 + +```cypher +// 复合条件:查询指定名称且类别为“肉类”的节点 +MATCH (n:Ingredient) +WHERE n.name IN ['猪肉', '猪里脊', '鸡蛋'] AND n.category = '肉类' +RETURN n; +``` + +#### 6.3.3 返回指定属性 + +默认情况下,`RETURN n` 会返回整个节点对象。也可以只返回节点的特定属性,并使用 `AS` 为返回的列起别名,使结果更具可读性。 + +```cypher +MATCH (n:Ingredient) +WHERE n.name IN ['猪里脊','鸡蛋'] +RETURN n.name AS 食材名称, n.category AS 类别; +``` + +#### 6.3.4 关联查询 + +图数据库最强大的地方在于对关系的查询。例如,可以一次性查询“鱼香肉丝”和“木须肉”分别包含了哪些食材。 + +```cypher +MATCH (d:Dish)-[:包含]->(i:Ingredient) +WHERE d.name IN ['鱼香肉丝', '木须肉'] +RETURN d.name AS 菜品, collect(i.name) AS 食材列表; +``` +> `collect()` 是一个聚合函数,可以将匹配到的多个同类结果(这里是食材名称 `i.name`)收集到一个列表中。 + +#### 6.3.5 查询并创建 (MATCH + CREATE) + +在实际应用中,一个常见的操作是先找到图中已经存在的节点,然后为它们添加新的关系。这可以通过组合使用 `MATCH` 和 `CREATE` 来实现。 + +例如,我们已经创建了“鱼香肉丝”和“猪里脊”,现在想为它们添加一条“主要食材”的关系。 + +```cypher +MATCH + (d:Dish {name:'鱼香肉丝'}), + (i:Ingredient {name:'猪里脊'}) +MERGE + (d)-[r:主要食材]->(i) +RETURN d, i, r; +``` +> 这个模式确保了是在已有的、正确的实体之间建立关联,并通过 `MERGE` 避免重复的关系。 + +#### 6.3.6 排序 (ORDER BY) + +可以使用 `ORDER BY` 子句对返回的结果进行排序。默认是升序 (`ASC`),也可以指定为降序 (`DESC`)。 + +```cypher +// 查询所有食材,并按名称升序排序 +MATCH (i:Ingredient) +RETURN i.name, i.category +ORDER BY i.name ASC; +``` + +### 6.4 更新 (SET & MERGE) + +#### 6.4.1 更新属性 (SET) + +`SET` 语句用于修改或添加节点/关系的属性。它必须和 `MATCH` 配合使用,先找到要更新的实体,再进行修改。 + +```cypher +MATCH (i:Ingredient {name:'猪肉'}) +SET + i.is_frozen = true, + i.origin = '金华' +RETURN i; +``` + +#### 6.4.2 插入或更新 (MERGE) + +在构建知识图谱时,经常遇到这样的场景:如果某个节点已存在,则更新其属性;如果不存在,则创建它。`MERGE` 语句就可以解决这个问题。 + +`MERGE` 会根据你提供的模式在图中查找,如果找到匹配项,则执行 `ON MATCH` 部分;如果未找到,则执行 `ON CREATE` 部分,从而避免了重复创建实体。 + +```cypher +// 查找名为'大蒜'的 Ingredient 节点 +MERGE (n:Ingredient {name: '大蒜'}) +// 如果不存在,则创建该节点,并设置创建时间和初始库存 +ON CREATE SET + n.created = timestamp(), + n.stock = 100 +// 如果已存在,则更新其库存、访问次数和访问时间 +ON MATCH SET + n.stock = coalesce(n.stock, 0) - 1, + n.counter = coalesce(n.counter, 0) + 1, + n.accessTime = timestamp() +RETURN n; +``` +> `coalesce(property, defaultValue)` 是一个非常有用的函数,它会检查属性 `property` 是否存在,如果存在则返回其值,否则返回 `defaultValue`。 + +### 6.5 删除 (DELETE & REMOVE) + +#### 6.5.1 删除属性 (REMOVE) + +`REMOVE` 用于移除节点或关系上的某个属性。在下面的例子中,先用 `MATCH` 找到名为“大蒜”的节点,然后移除由 `MERGE` 命令在创建它时添加的 `created` 属性。 + +```cypher +MATCH (i:Ingredient {name:'大蒜'}) +REMOVE i.created +RETURN i; +``` + +#### 6.5.2 删除节点和关系 (DELETE) + +`DELETE` 用于删除节点和关系。但需要 **特别注意**:Neo4j 不允许直接删除一个还存在关联关系的节点。你必须先删除关系,才能删除节点。 + +```cypher +// 错误示范:如果'大蒜'还有关系连着,这条语句会报错 +MATCH (i:Ingredient {name:'大蒜'}) +DELETE i; +``` + +正确的做法有两种。第一种是先手动删除与节点相关的所有关系,然后再删除节点本身。 + +```cypher +// 正确做法 1:先删除关系,再删除节点 +MATCH (i:Ingredient {name:'大蒜'})-[r]-() // 匹配与'大蒜'相连的任意关系 +DELETE r, i; // 先删除关系 r,再删除节点 i +``` + +第二种做法更简洁,也是官方推荐的方式:使用 `DETACH DELETE`。它会自动删除指定节点以及所有与它直接相连的关系。 + +```cypher +// 正确做法 2:使用 DETACH DELETE (推荐) +MATCH (i:Ingredient {name:'大蒜'}) +DETACH DELETE i; +``` + +此外,还可以通过节点的内部 ID 进行精确查找和删除。每个节点都有一个由 Neo4j 自动分配的唯一 ID,可以通过 `id()` 函数获取。 + +```cypher +// 假设我们通过查询得知“大蒜”的 ID 为 5 +MATCH (i:Ingredient) +WHERE id(i) = 5 +DETACH DELETE i; +``` + +#### 6.5.3 清空数据库 + +如果想删除数据库中的所有节点和关系,可以使用以下命令: + +```cypher +// 匹配所有节点 n +MATCH (n) +// 强制删除节点 n 及其所有关系 +DETACH DELETE n; +``` + +#### 6.5.4 软删除 + +在生产环境中,直接从数据库中物理删除(`DELETE`)数据是一种高风险操作。一种更安全、更常见的做法是“软删除”。软删除并非真的将数据移除,而是通过 `SET` 命令为其添加一个状态属性,将其标记为“已删除”或“不活跃”。 + +```cypher +// 将“木耳”标记为不活跃 +MATCH (i:Ingredient {name:'木耳'}) +SET i.is_active = false; +``` +这样,在后续的查询中,只需要增加一个 `WHERE i.is_active = true` 的过滤条件,就能只使用那些“活跃”的数据,而被软删除的数据依然保留在数据库中,以备审计或恢复。 + +> 删除操作是高风险行为,尤其是在生产环境中。执行前请务必确认操作对象和范围,并做好数据备份。 diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/code/.env.example b/Extra-chapter/PowerRAG-SDK-Text-QA/code/.env.example new file mode 100644 index 0000000..3cd2992 --- /dev/null +++ b/Extra-chapter/PowerRAG-SDK-Text-QA/code/.env.example @@ -0,0 +1,26 @@ +# PowerRAG (RAGFlow) SDK demo config + +# SDK endpoint (from your docker-compose env: SVR_HTTP_PORT=9380) +RAGFLOW_BASE_URL=http://127.0.0.1:9380 + +# SDK API key (format: ragflow-...; created via /v1/api/new_token) +RAGFLOW_API_KEY=ragflow-REPLACE_ME + +# Optional: override dataset name created by the demo +RAGFLOW_DATASET_NAME=powerrag_text_qa_demo + +# Optional: override embedding model for dataset creation (recommended to leave empty and use tenant default) +# Format: @ +# Example: +# RAGFLOW_EMBEDDING_MODEL=text-embedding-3-small@OpenAI +RAGFLOW_EMBEDDING_MODEL= + +# ----------------------------- +# Optional: embedding provider config (used by the README “API 配置 embedding” steps) +# ----------------------------- + +# Use the factory/model name shown by your PowerRAG UI/API. +EMB_FACTORY=REPLACE_ME +EMB_MODEL=REPLACE_ME +EMB_API_BASE=REPLACE_ME +EMB_API_KEY=REPLACE_ME diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/code/config.py b/Extra-chapter/PowerRAG-SDK-Text-QA/code/config.py new file mode 100644 index 0000000..5818a2f --- /dev/null +++ b/Extra-chapter/PowerRAG-SDK-Text-QA/code/config.py @@ -0,0 +1,46 @@ +""" +PowerRAG (RAGFlow) SDK Demo configuration. + +This module follows the `code/` directory convention: +- Provide a small config object +- Load `.env` automatically (if present) +""" + +from __future__ import annotations + +import os +from dataclasses import dataclass + +from dotenv import load_dotenv + +load_dotenv() + + +def _bool_env(name: str, default: bool = False) -> bool: + raw = os.getenv(name) + if raw is None: + return default + raw = raw.strip().lower() + if raw in {"1", "true", "yes", "y", "on"}: + return True + if raw in {"0", "false", "no", "n", "off"}: + return False + return default + + +@dataclass(frozen=True) +class PowerRAGDemoConfig: + base_url: str = os.getenv("RAGFLOW_BASE_URL", "http://127.0.0.1:9380").strip() + api_key: str = os.getenv("RAGFLOW_API_KEY", "").strip() + dataset_name: str = os.getenv("RAGFLOW_DATASET_NAME", "powerrag_text_qa_demo").strip() + embedding_model: str = os.getenv("RAGFLOW_EMBEDDING_MODEL", "").strip() + + top_k: int = int(os.getenv("RAGFLOW_TOP_K", "5")) + candidate_k: int = int(os.getenv("RAGFLOW_CANDIDATE_K", "1024")) + similarity_threshold: float = float(os.getenv("RAGFLOW_SIMILARITY_THRESHOLD", "0.2")) + vector_similarity_weight: float = float(os.getenv("RAGFLOW_VECTOR_SIMILARITY_WEIGHT", "0.3")) + keyword: bool = _bool_env("RAGFLOW_KEYWORD", False) + + +DEFAULT_CONFIG = PowerRAGDemoConfig() + diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/code/main.py b/Extra-chapter/PowerRAG-SDK-Text-QA/code/main.py new file mode 100644 index 0000000..0249a96 --- /dev/null +++ b/Extra-chapter/PowerRAG-SDK-Text-QA/code/main.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +import os +import sys +from pathlib import Path +from typing import Any + +from config import DEFAULT_CONFIG + + +def _env(name: str, default: str | None = None) -> str | None: + value = os.getenv(name) + if value is None or value.strip() == "": + return default + return value.strip() + + +def _require(value: str | None, hint: str) -> str: + if value is None or value.strip() == "": + raise SystemExit(hint) + return value.strip() + + +def _read_bytes(path: Path) -> bytes: + try: + return path.read_bytes() + except FileNotFoundError: + raise SystemExit(f"File not found: {path}") + + +def _safe_get(obj: Any, attr: str, default: Any = None) -> Any: + try: + return getattr(obj, attr) + except Exception: + return default + + +def main(argv: list[str]) -> int: + parser = argparse.ArgumentParser( + description="PowerRAG (RAGFlow) SDK demo: upload Markdown, parse, retrieve top-k chunks.", + ) + parser.add_argument("--file", type=Path, required=True, help="Markdown file path, e.g. ./data/sample.md") + parser.add_argument("--question", type=str, required=True, help="User question for retrieval") + parser.add_argument("--top-k", type=int, default=DEFAULT_CONFIG.top_k, help="How many chunks to return (mapped to page_size)") + parser.add_argument( + "--embedding-model", + type=str, + default=DEFAULT_CONFIG.embedding_model or _env("RAGFLOW_EMBEDDING_MODEL"), + help=( + "Embedding model string in '@' format. " + "If omitted, server tenant default is used." + ), + ) + parser.add_argument("--candidate-k", type=int, default=DEFAULT_CONFIG.candidate_k, help="RAGFlow.retrieve(top_k=...) candidate pool size") + parser.add_argument("--similarity-threshold", type=float, default=DEFAULT_CONFIG.similarity_threshold, help="Filter chunks below this similarity") + parser.add_argument("--vector-similarity-weight", type=float, default=DEFAULT_CONFIG.vector_similarity_weight, help="Weight of vector similarity in hybrid score") + parser.add_argument("--keyword", action="store_true", default=DEFAULT_CONFIG.keyword, help="Enable keyword matching (hybrid retrieval)") + parser.add_argument("--dataset-name", type=str, default=DEFAULT_CONFIG.dataset_name, help="Dataset name to create") + parser.add_argument( + "--base-url", + type=str, + default=DEFAULT_CONFIG.base_url or _env("RAGFLOW_BASE_URL") or _env("POWERRAG_BASE_URL") or _env("BASE_URL"), + help="RAGFlow/PowerRAG base_url (or env RAGFLOW_BASE_URL / POWERRAG_BASE_URL / BASE_URL)", + ) + parser.add_argument( + "--api-key", + type=str, + default=DEFAULT_CONFIG.api_key or _env("RAGFLOW_API_KEY") or _env("POWERRAG_API_KEY") or _env("API_KEY"), + help="RAGFlow/PowerRAG api_key (or env RAGFLOW_API_KEY / POWERRAG_API_KEY / API_KEY)", + ) + parser.add_argument("--cleanup", action="store_true", help="Delete created dataset after finishing") + + args = parser.parse_args(argv) + + base_url = _require(args.base_url, "Missing base_url. Use --base-url or set env RAGFLOW_BASE_URL.") + api_key = _require(args.api_key, "Missing api_key. Use --api-key or set env RAGFLOW_API_KEY.") + + if args.top_k <= 0: + raise SystemExit("--top-k must be > 0") + if args.candidate_k <= 0: + raise SystemExit("--candidate-k must be > 0") + + blob = _read_bytes(args.file) + display_name = args.file.name + if not display_name.lower().endswith(".md"): + display_name = f"{display_name}.md" + + try: + from ragflow_sdk import RAGFlow # type: ignore + except Exception as e: + raise SystemExit( + "Failed to import ragflow_sdk. Install dependencies first:\n" + " pip install -r requirements.txt\n" + f"Original error: {e}" + ) + + rag = RAGFlow(api_key=api_key, base_url=base_url) + + dataset_kwargs: dict[str, Any] = {"name": args.dataset_name} + if args.embedding_model: + dataset_kwargs["embedding_model"] = args.embedding_model + dataset = rag.create_dataset(**dataset_kwargs) + try: + docs = dataset.upload_documents([{"display_name": display_name, "blob": blob}]) + if not docs: + raise SystemExit("Upload succeeded but no document returned by SDK.") + doc = docs[0] + + parse_results = dataset.parse_documents([doc.id]) + # parse_results: list[tuple[doc_id, status, success_count, failure_count]] (per API ref) + print("Parse results:") + print(parse_results) + if parse_results and isinstance(parse_results, list): + statuses = {r[1] for r in parse_results if isinstance(r, (list, tuple)) and len(r) >= 2} + if statuses and statuses != {"DONE"}: + raise SystemExit( + "Document parsing failed (status not DONE). " + "Most common cause is missing/unauthorized embedding model.\n" + "Try:\n" + " - set tenant default embedding model in UI or via /v1/user/set_tenant_info, OR\n" + " - rerun with --embedding-model '@' (must be supported & configured for the tenant)\n" + "If it still fails, check PowerRAG logs inside the container (task executor) for the detailed error.\n" + ) + + chunks = rag.retrieve( + question=args.question, + dataset_ids=[dataset.id], + document_ids=[doc.id], + page=1, + page_size=args.top_k, + similarity_threshold=args.similarity_threshold, + vector_similarity_weight=args.vector_similarity_weight, + top_k=args.candidate_k, + keyword=args.keyword, + ) + + print("\nRetrieved chunks:") + if not chunks: + print("(empty)") + return 0 + + for i, c in enumerate(chunks, start=1): + similarity = _safe_get(c, "similarity") + vector_similarity = _safe_get(c, "vector_similarity") + term_similarity = _safe_get(c, "term_similarity") + content = _safe_get(c, "content", "") + content_preview = (content or "").strip().replace("\n", " ") + if len(content_preview) > 260: + content_preview = content_preview[:260] + "…" + print(f"{i:02d}. similarity={similarity} vector={vector_similarity} term={term_similarity}") + print(f" {content_preview}") + + return 0 + finally: + if args.cleanup: + try: + rag.delete_datasets(ids=[dataset.id]) + except Exception as e: + print(f"Warning: failed to cleanup dataset {dataset.id}: {e}", file=sys.stderr) + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:])) diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/code/requirements.txt b/Extra-chapter/PowerRAG-SDK-Text-QA/code/requirements.txt new file mode 100644 index 0000000..f701974 --- /dev/null +++ b/Extra-chapter/PowerRAG-SDK-Text-QA/code/requirements.txt @@ -0,0 +1,3 @@ +ragflow-sdk +python-dotenv + diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/data/questions.txt b/Extra-chapter/PowerRAG-SDK-Text-QA/data/questions.txt new file mode 100644 index 0000000..a920adc --- /dev/null +++ b/Extra-chapter/PowerRAG-SDK-Text-QA/data/questions.txt @@ -0,0 +1,5 @@ +1) 这个 demo 的验收标准是什么? +2) 餐厅排队系统里,如果顾客过号,通常怎么处理? +3) 已发货未签收的退款规则是什么? +4) 如何估算排队等待时间? + diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/data/sample.md b/Extra-chapter/PowerRAG-SDK-Text-QA/data/sample.md new file mode 100644 index 0000000..b789e2f --- /dev/null +++ b/Extra-chapter/PowerRAG-SDK-Text-QA/data/sample.md @@ -0,0 +1,40 @@ +# PowerRAG 文本问答 Demo · 示例文档 + +## 1. 项目背景 + +本示例用于演示:上传一份 Markdown 文档 → 服务端自动解析与分块 → 基于问题检索相关 chunks。 + +## 2. 关键概念 + +- **分块(Chunk)**:把长文切成多个小段,便于向量化与检索。 +- **向量检索(Vector Search)**:把文本映射到向量空间,通过相似度找到相关片段。 +- **Top-k**:返回最相关的 k 个片段。 + +## 3. 规则与约束 + +1) 只有当“检索到的 chunks 与问题语义相关”时,才算成功。 +2) 本 demo 不要求大模型生成最终回答(可选)。 + +## 4. 示例内容:餐厅排队系统 + +我们要做一个餐厅排队系统,核心流程如下: + +1. 顾客在前台取号,系统生成排队号(例如 A001)。 +2. 服务员在就餐区空位出现时叫号,顾客到号后入座。 +3. 如果顾客过号,可选择重新排队或延后若干位。 +4. 系统需要支持查询当前排队情况,以及某个号码前面还有多少人。 + +### 4.1 常见问题 + +- “过号后怎么处理?”:可以延后或重新取号,策略由门店决定。 +- “如何估算等待时间?”:可以用平均翻台时间 × 前方人数估算。 +- “如何处理多人同时取号?”:需要对取号操作加锁或用原子自增保证顺序。 + +## 5. 示例内容:退款规则 + +退款规则如下: + +- 未发货:可全额退款。 +- 已发货未签收:可申请退款,但需要承担退货运费。 +- 已签收:7 天内可退货退款;超过 7 天视情况处理。 + diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/images/10_1_1.webp b/Extra-chapter/PowerRAG-SDK-Text-QA/images/10_1_1.webp new file mode 100644 index 0000000..0d91f67 Binary files /dev/null and b/Extra-chapter/PowerRAG-SDK-Text-QA/images/10_1_1.webp differ diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/images/10_1_2.webp b/Extra-chapter/PowerRAG-SDK-Text-QA/images/10_1_2.webp new file mode 100644 index 0000000..127c7ea Binary files /dev/null and b/Extra-chapter/PowerRAG-SDK-Text-QA/images/10_1_2.webp differ diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/images/10_1_3.webp b/Extra-chapter/PowerRAG-SDK-Text-QA/images/10_1_3.webp new file mode 100644 index 0000000..8253d44 Binary files /dev/null and b/Extra-chapter/PowerRAG-SDK-Text-QA/images/10_1_3.webp differ diff --git a/Extra-chapter/PowerRAG-SDK-Text-QA/readme.md b/Extra-chapter/PowerRAG-SDK-Text-QA/readme.md new file mode 100644 index 0000000..2765b3c --- /dev/null +++ b/Extra-chapter/PowerRAG-SDK-Text-QA/readme.md @@ -0,0 +1,404 @@ +# PowerRAG SDK 文本问答检索 Demo + +## 一、这篇专题要解决什么问题? + +很多同学做 RAG 时会先把注意力放在“怎么让大模型回答得更像人”。但只要检索没找对上下文,生成再花哨也只是“把错讲得更顺”。 + +这个专题做一件更朴素、也更值得先掌握的事: + +> **只做检索,不做生成。** + +你会把一份 Markdown 文档交给服务端,让服务端完成解析、切分、向量化,然后用问题去做 Top‑K 检索,拿回最相关的原文片段(chunks)。 + +**验收标准也很直接**:Top‑K chunks 是否与问题语义相关(不要求最终答案)。 + +本专题目录结构: + +- `readme.md`:本文(教学文档) +- `images/`:配图 +- `code/`:可运行脚本与配置(`main.py`、`config.py`、`.env.example`、`requirements.txt`) +- `data/`:可复现样例数据(`sample.md` + `questions.txt`) + +--- + +## 二、技术方案:从 Markdown 到 Top‑K chunks(图文讲清楚) + +下面这张图展示了端到端链路,也基本对应 `code/main.py` 的执行顺序。 + +
+ 端到端流程图:上传→解析/切分→向量化→Top-K 检索 +

图 10.1: 端到端流程(本 demo 只验收检索结果,不要求生成最终回答)

+
+ +为了避免“看完图还是不知道自己要做什么”,这里把图 10.1 的关键节点按顺序讲清楚(你可以边对照图边往下读): + +**(1)本地输入:Markdown 文档** + +你可以直接用本专题提供的 `data/sample.md`。这份文件故意写得短:包含“排队规则”和“退款规则”,方便你用不同问题去验证检索是否命中。 + +**(2)Upload:上传到 dataset** + +上传不是“把文本发过去就结束”,它的意义在于:服务端要把这份文档纳入某个 **dataset**(容器)里,后续切分出来的 chunks、embedding、索引都挂在这个容器下面。 + +**(3)Parse/Chunk:解析 + 切分** + +这一步会把 Markdown 解析成可检索的文本结构,并按服务端策略切成多个 chunk。 + +> ⚠️ 图里标了一个常见失败点:如果你的 tenant 没有配置默认 embedding(`embd_id` 为空或未授权),解析任务可能直接 FAIL。 + +**(4)Embedding:向量化** + +每个 chunk 会被映射成向量(embedding)。这一步是向量检索的前提——没有向量,后面就谈不上“语义相似”。 + +**(5)写入向量库/索引** + +chunk + embedding 会写入向量索引(图里叫 Vector Store / Index)。 + +**(6)Retrieve Top‑K:检索并返回 chunks** + +输入一个问题(question),服务端从索引里找出最相关的 K 个 chunk,并把这些原文片段返回给你。本 demo 的验收就看这里:**返回的 chunks 是否包含你期望的规则段落**。 + +--- + +到这里,你应该已经能把这条链路从头到尾“顺着说一遍”了: + +> 文档上传 → 服务端解析/切分/向量化 → 写入索引 → 问题检索 → 返回 Top‑K chunks。 + +但很多初学者还有一个常见困惑:**这些名词到底对应什么对象?我拿到的结果到底是谁?** + +所以下面我们换一个视角:不再看“流程”,而是看“对象之间的关系”。 + +--- + +再看图 10.2(对象关系)。这张图的目的只有一个:把“你上传的文件”和“检索返回的结果”彻底区分开。 + +很多同学第一次用 RAG 平台 SDK,会把这些概念混在一起。你只要记住: + +- **dataset**:容器(装很多文档) +- **document**:你上传的那份文件 +- **chunk**:文档切分出来的文本片段(检索返回的就是它) + +
+ 对象关系图:dataset-document-chunk-embedding 与 Top-K 返回 +

图 10.2: 对象关系与返回结构(检索返回的核心对象是 chunk)

+
+ +图 10.2 里最容易忽略、但最关键的一点是:**检索返回的是 chunk,不是 document。** + +- document 是“你上传的整份文件” +- chunk 是“切分后的片段”,它才是检索、重排、压缩、最终拼上下文的基本单位 + +所以你在终端里看到的 Top‑K 结果,应该是一段段原文片段,而不是整篇 Markdown。 + +> 💡 小白自检:我怎么判断“这段 chunk 就是我想要的那段”? +> +> 很简单:用你自己的语言把问题再复述一遍,然后在返回的 chunk 里找“能直接支撑答案的原文句子”。 +> 例如你问“已发货未签收能不能退款”,chunk 里应当出现“已发货未签收:可申请退款,但需要承担退货运费”这一类关键句。 + +--- +## 三、实现思路:从零写一版“最小检索脚本”(带代码块) + +先给一个“最小骨架”(你可以把它当作伪代码,但它基本就是 `code/main.py` 的主干): + +```python +rag = RAGFlow(api_key=..., base_url=...) + +# 1) 创建 dataset(容器) +dataset = rag.create_dataset(name=...) + +# 2) 上传文档(拿到 doc.id) +doc = dataset.upload_documents([{...}])[0] + +# 3) 解析/切分/向量化(失败大多发生在这里) +parse_results = dataset.parse_documents([doc.id]) + +# 4) 检索 Top-K chunks(验收点) +chunks = rag.retrieve(question=..., dataset_ids=[dataset.id], document_ids=[doc.id], page_size=top_k) +``` + +下面把每一步展开讲清楚(并配上代码片段)。 + +### 3.1 参数与配置:先让脚本可复现 + +先从命令行参数入手,理解脚本“能调什么”。`code/main.py` 里最常用的是这几个: + +```python +parser.add_argument("--file", type=Path, required=True) +parser.add_argument("--question", type=str, required=True) +parser.add_argument("--top-k", type=int, default=DEFAULT_CONFIG.top_k) +parser.add_argument("--dataset-name", type=str, default=DEFAULT_CONFIG.dataset_name) +parser.add_argument("--base-url", type=str, default=DEFAULT_CONFIG.base_url) +parser.add_argument("--api-key", type=str, default=DEFAULT_CONFIG.api_key) +``` + +- `--file`:你要上传哪份 Markdown +- `--question`:你想验证的提问 +- `--top-k`:返回多少个 chunk +- `--dataset-name`:本次创建/使用的数据集名字 +- `--base-url/--api-key`:PowerRAG 服务端地址与 SDK token + +这几个参数足够让你完成“换文档、换问题、调 Top‑K、连不同服务端”这四类最常见实验。 + +> 💡 小白自检:为什么这里既支持命令行参数,又支持 `.env`? +> +> 因为这两种场景都很常见: +> +> - 你本地调试时,喜欢用 `.env` 固定住 base_url/api_key +> - 你改参数做实验时,喜欢命令行直接覆盖(不用反复改文件) + +### 3.2 初始化 SDK:先连上再说 + +```python +from ragflow_sdk import RAGFlow + +rag = RAGFlow(api_key=api_key, base_url=base_url) +``` + +这里没有花活:就是把请求的 base_url 和 token 配好。 + +### 3.3 创建 dataset:把文档放进“一个篮子里” + +```python +dataset_kwargs = {"name": args.dataset_name} +if args.embedding_model: + dataset_kwargs["embedding_model"] = args.embedding_model +dataset = rag.create_dataset(**dataset_kwargs) +``` + +为什么要先有 dataset?因为“上传/解析/检索”都需要一个边界。 +你不希望每次检索都在整个租户的所有文档里搜;你希望“只在这次实验的文档集合里搜”。 + +> 💡 小白自检:能不能不建 dataset,直接上传然后检索? +> +> 取决于平台能力。但在 PowerRAG/RAGFlow 这类系统里,dataset 是“组织边界”。 +> 没有边界,检索要么全库搜(不可控),要么压根没有地方挂索引。 + +### 3.4 上传 document:得到 doc.id,后面都靠它 + +```python +docs = dataset.upload_documents([ + {"display_name": display_name, "blob": blob} +]) +doc = docs[0] +``` + +上传成功后,SDK 会返回一个 document 对象(至少包含 `doc.id`)。 +后续的 parse 和 retrieve 都要用它来限定范围。 + +> 💡 小白自检:为什么要限定 `document_ids=[doc.id]`? +> +> 因为你这次实验只关心“这份文档”的检索效果。 +> 如果不限定,dataset 里有多份文档时,你可能会检索到别的文档的 chunk,导致结果看起来“跑偏”。 + +### 3.5 解析 / 切分 / 向量化:最容易踩坑的一步 + +```python +parse_results = dataset.parse_documents([doc.id]) +print("Parse results:") +print(parse_results) +``` + +脚本会把 parse 的状态打印出来,并且做了一个很直接的判断: + +```python +statuses = {r[1] for r in parse_results if isinstance(r, (list, tuple)) and len(r) >= 2} +if statuses and statuses != {"DONE"}: + raise SystemExit("Document parsing failed (status not DONE)...") +``` + +你可以把它理解为“验收关卡”: + +- **DONE**:说明服务端已经把文档切成 chunk,并完成(或至少开始完成)向量化与索引写入 +- **FAIL/其他状态**:先别着急改代码,优先排查 tenant 默认 embedding + +> 经验:`Model(@None) not authorized` 基本就是在提示“默认 embedding 没配/没权限”。 + +> 💡 小白自检:为什么 embedding 配置会影响“解析(parse)”? +> +> 因为这里的 parse 往往不是“纯语法解析 Markdown”,而是一条“解析 → 切分 → 向量化 → 写索引”的流水线任务。 +> embedding 不可用时,流水线中途失败,平台就会把整个任务标为 FAIL。 + +### 3.6 检索 Top‑K:你真正要验收的结果 + +```python +chunks = rag.retrieve( + question=args.question, + dataset_ids=[dataset.id], + document_ids=[doc.id], + page=1, + page_size=args.top_k, + similarity_threshold=args.similarity_threshold, + vector_similarity_weight=args.vector_similarity_weight, + top_k=args.candidate_k, + keyword=args.keyword, +) +``` + +这里有两个点值得你留意(也是很多人调参的入口): + +- `page_size=args.top_k`:你最终想看多少条 chunk +- `similarity_threshold`:太高会过滤掉结果导致空,太低会混进无关段落 + +最后脚本会把每条 chunk 的内容预览打印出来: + +```python +for i, c in enumerate(chunks, start=1): + content = _safe_get(c, "content", "") + print(f"{i:02d}. {content[:260]}") +``` + +你要做的“人工验收”也很简单:看看这几段文字是不是回答问题所需的那几段原文。 + +> 💡 小白自检:Top‑K 是不是越大越好? +> +> 不是。Top‑K 太大容易把无关 chunk 混进来;太小又可能漏掉关键段落。 +> 教学 demo 里一般用 3~8 都够用。 + +--- + +### 3.7 先跑通一次(最短路径) + +> ⚠️ 注意:解析/向量化依赖 embedding。如果你的 tenant 没有配置默认 embedding(`embd_id` 为空或未授权),解析阶段会 FAIL。不要先怀疑 Python。 + +```bash +# 1) 安装依赖 +cd Extra-chapter/PowerRAG-SDK-Text-QA/code +python -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt + +# 2) 配置 .env(在 code/ 目录下) +cp .env.example .env + +# 3) 回到专题根目录运行(data/ 路径更直观) +cd .. +python code/main.py \ + --file data/sample.md \ + --question "已发货未签收的退款规则是什么?" \ + --top-k 5 \ + --cleanup +``` + +你会看到两段关键输出: + +1. `Parse results`:解析/分块状态(期望 `DONE`) +2. `Retrieved chunks`:Top‑K chunks 的内容预览 + +--- + +--- + +## 四、经验总结与坑点(把时间花在对的地方) + +很多时候问题不在“你写的 Python”,而在“服务端是不是已经把 embedding 产出来了”。 + +
+ 简化时序图:上传→解析→写入索引→Top-K 检索→返回 chunks +

图 10.3: code/main.py 与服务端 API 的交互顺序(简化版)

+
+ +如果你只记一条顺序,就记这句: + +> **先上传 → 再解析(产出 chunk+embedding)→ 最后检索(返回 chunk)** + +很多“为什么检索不到”的问题,本质是解析还没成功,索引里根本没有向量。 + +--- + +### 4.1 Parse results 是 FAIL + +优先检查 tenant 的默认 embedding(`embd_id`)是否已配置且可用。典型错误: + +- `Model(@None) not authorized` +- `Parse results: ... FAIL ...` + +如果已经配置仍失败,直接看 task executor 日志最省时间: + +```bash +docker exec powerrag-powerrag-1 sh -lc 'tail -n 200 /ragflow/logs/task_executor_* | tail -n 200' +``` + +### 4.2 401/403:token 类型搞混 + +PowerRAG 常见会同时出现两类 token: + +- Web 层 `AUTH`(用于 `/v1/*`) +- SDK 的 `ragflow-...` token(用于 `/api/v1/*`,通常写在 `Authorization: Bearer `) + +如果你看到 401/403,先确认 token 类型和接口前缀是否匹配。 + +--- + +--- + +## 附录:用 API 配默认 embedding + 生成 ragflow token(重操作区) + +> 这部分是“环境/账号/服务端配置”,放到附录,避免主线被淹没。 + +### A1. 用 API 配好 embedding(通用) + +这一步需要一个 Web 层的 `AUTH`(`/v1/*` 使用),它和 SDK 的 `ragflow-...` key 不是一回事。 + +你可以把 embedding 配置写进 `.env`(见 `.env.example` 的 `EMB_*`),下面命令会读取 `EMB_FACTORY/EMB_MODEL/EMB_API_BASE/EMB_API_KEY`。 + +#### A1.1 获取 `AUTH`(注册并从响应头拿 Authorization) + +PowerRAG 的 `/v1/user/register` 要求 password 先用服务端的 RSA public key 加密。最省事的方式是在容器内调用它自带的加密函数: + +```bash +BASE_URL="http://127.0.0.1:9380" + +ENC_PW="$(docker exec powerrag-powerrag-1 sh -lc 'python - <<"PY"\nfrom api.utils.crypt import crypt\nprint(crypt("powerrag"))\nPY')" + +EMAIL="powerrag.demo.$(date +%s)@example.com" +AUTH="$(curl -sS -D - -o /dev/null -X POST "$BASE_URL/v1/user/register" \ + -H 'Content-Type: application/json' \ + -d "{\"nickname\":\"demo\",\"email\":\"$EMAIL\",\"password\":\"$ENC_PW\"}" \ +| awk 'BEGIN{IGNORECASE=1} /^authorization:/{print $2}' | tr -d '\r')" +``` + +#### A1.2 绑定 embedding 的外部 API + +> 注意:`max_tokens` 需要显式传,否则可能报数据库字段错误。 + +```bash +curl -sS -X POST "$BASE_URL/v1/llm/add_llm" \ + -H "Authorization: $AUTH" \ + -H 'Content-Type: application/json' \ + -d '{ + "llm_factory": "'"${EMB_FACTORY}"'", + "model_type": "embedding", + "llm_name": "'"${EMB_MODEL}"'", + "api_base": "'"${EMB_API_BASE}"'", + "api_key": "'"${EMB_API_KEY}"'", + "max_tokens": 8192 + }' +``` + +#### A1.3 设置 tenant 默认 `embd_id` + +```bash +TENANT_ID="$(curl -sS -H "Authorization: $AUTH" "$BASE_URL/v1/user/tenant_info" | python -c 'import sys,json; print(json.load(sys.stdin)["data"]["tenant_id"])')" + +curl -sS -X POST "$BASE_URL/v1/user/set_tenant_info" \ + -H "Authorization: $AUTH" \ + -H 'Content-Type: application/json' \ + -d "{\"tenant_id\":\"$TENANT_ID\",\"llm_id\":\"\",\"embd_id\":\"${EMB_MODEL}@${EMB_FACTORY}\",\"asr_id\":\"\",\"img2txt_id\":\"\"}" +``` + +### A2. 生成 SDK 的 `ragflow-...` api_key + +SDK 接口在 `/api/v1/*`,它不认 `AUTH`,需要 `ragflow-...` 这种 token(放在 header:`Authorization: Bearer `)。 + +用 `AUTH` 创建一个 SDK key: + +```bash +DIALOG_ID="$(python -c 'import uuid; print(uuid.uuid4().hex)')" +API_KEY="$(curl -sS -X POST "$BASE_URL/v1/api/new_token" \ + -H "Authorization: $AUTH" \ + -H 'Content-Type: application/json' \ + -d "{\"dialog_id\":\"$DIALOG_ID\"}" \ +| python -c 'import sys,json; print(json.load(sys.stdin)["data"]["token"])')" + +echo "$API_KEY" +``` diff --git a/Extra-chapter/README.md b/Extra-chapter/README.md new file mode 100644 index 0000000..c7314d5 --- /dev/null +++ b/Extra-chapter/README.md @@ -0,0 +1,149 @@ +
+ +

🚀 All-in-RAG · Extra Chapter

+ +

主教程之外的「知识拓展与社区实践」专区

+ +
+ +--- + +## 📖 Extra Chapter 是什么? + +`Extra-chapter` 目录用于存放 **不直接属于主线章节,但对 RAG / LLM 应用非常有价值的补充内容**。这些内容可以是你对某个相关技术(如 Neo4j、Milvus、GraphRAG 等)的系统整理,也可以是与你的研究/工作紧密相关的专题总结。 + +在主仓库的「知识拓展」部分,我们会以清单形式挂出这里的优秀专题,例如: + +- `Neo4J 简单应用`(本目录下的第一个示例专题) +- `PowerRAG SDK 文本检索 Demo`(上传 Markdown → 解析/切分/向量化 → Top‑K 检索) + +我们希望通过 Extra Chapter: + +- **补充主教程**:覆盖 RAG 周边的生态组件和工程化话题 +- **沉淀实践经验**:记录真实项目中的设计思路与解决方案 +- **鼓励多元视角**:允许不同风格的探索与实验性内容 +- **形成可引用的知识单元**:每个专题都可以被单独阅读和复用 + +--- + +## 📂 推荐目录结构 + +每一个新专题建议在 `Extra-chapter/` 下新建一个独立子目录,并至少包含一个 `readme.md` 作为主文档。参考结构如下(可按需要增减): + +```text +Extra-chapter/ +├── your-topic-name/ # 你的专题目录(必需) +│ ├── readme.md # 专题主文档(必需) +│ ├── images/ # 图片资源(建议有图片时使用) +│ │ ├── figure1.png +│ │ └── figure2.jpg +│ ├── code/ # 代码示例(如有代码建议单独放) +│ │ ├── demo.py +│ │ └── requirements.txt +│ └── data/ # 示例数据(如有) +│ └── sample_data.json +└── README.md # 本说明文件 +``` + +> 当前仓库中的 `Neo4J 简单应用` 专题位于 `Extra-chapter/Neo4J/readme.md`,你可以参考其组织方式,但不必完全照搬。 + +--- + +## 🧱 命名与排版建议 + +### 1. 目录与文件命名 + +- **专题目录名 (`your-topic-name/`)** + - 使用有语义的英文或中英文混合 + - 避免过长,尽量能一眼看出主题,例如: + - `Neo4J-Simple-Application` + - `graph-rag-practice` + +- **主文档** + - 固定为:`readme.md`(小写),便于 GitHub 直接展示 + +- **图片 / 代码 / 数据** + - 统一放在 `images/`、`code/`、`data/` 等子目录中 + - 文件名建议包含用途或内容关键信息,例如:`pipeline-overview.png`、`retriever_benchmark.ipynb` + +### 2. 内容组织与标题层级 + +推荐的章节骨架(可根据需要微调): + +- `# 专题标题` +- `## 背景与动机` +- `## 场景或问题描述` +- `## 技术方案 / 实现思路` +- `## 实践步骤 / 代码示例` +- `## 经验总结与坑点` + +标题层级请保持清晰,避免过多嵌套(一般不超过三级:`##` / `###` / `####`)。 + +--- + +## ✅ 内容质量与范围 + +为了让内容对读者真正有帮助,提交 PR 前请尽量满足以下要求: + +- **与 RAG / LLM 应用相关** + - 例如:图数据库在 RAG 中的用法、检索评估方案、多模态扩展、部署/监控经验等 + +- **技术与事实尽量准确** + - 如有推测或实验性的结论,请明确标注 + - 关键代码建议给出可运行环境说明(Python 版本、依赖库等) + +- **结构清晰、可独立阅读** + - 读者不看主教程,也能从该专题收获完整的一段知识 + +- **尊重版权与引用规范** + - 如引用论文、博客或开源项目,请在文末列出参考资料或链接 + +--- + +## 🔀 提交 PR 的具体步骤(建议) + +1. **Fork 仓库并创建分支** + - 从 `main` 或当前默认分支拉出个人分支,例如:`feat/extra-chapter-neo4j-practice` + +2. **在 `Extra-chapter/` 下创建你的专题目录** + - 遵循上文的目录组织方案 + - 如有需要,可在根目录 `README.md` 的「第六部分:知识拓展」列表中,添加指向你专题的链接(格式参考已有的 `Neo4J 简单应用`) + +3. **本地检查排版与图片路径** + - 确认 Markdown 渲染正常、图片路径相对位置正确 + +4. **编写有信息量的 Commit Message** + +推荐包含以下信息(可按实际场景调整): + +```text +Extra-chapter: <你的专题标题> + +- 新增专题目录:Extra-chapter/ +- 主要内容:简要说明该专题解决了什么问题 / 分享了哪些经验 +- 代码与数据:如有,说明放在哪些子目录,如何运行 +- 个人信息(可选但推荐):你的 GitHub 链接、研究 / 工作方向等 +``` + +5. **发起 PR** + - PR 标题中建议包含:`[Extra-chapter]` + 你的专题名 + - 在 PR 描述里可以: + - 说明该专题与 All-in-RAG 主线章节的关系 + - 标注阅读顺序建议(例如:适合在读完第 3 章之后再看) + +--- + +## 💬 沟通与反馈 + +如果你在撰写 Extra Chapter 的过程中: + +- 不确定选题是否合适 +- 想讨论目录设计或技术路线 +- 希望对草稿先做一次技术性 Review + +可以在仓库的 `Discussions` 或 `Issues` 中发起话题,标题中带上 `Extra-chapter` 关键字,方便维护者和其他贡献者一起参与讨论。 + +--- + +欢迎你把自己的实践经验沉淀在这里,让更多学习 RAG / LLM 应用的同学受益。 🎉 + diff --git a/README.md b/README.md new file mode 100644 index 0000000..d30d8c9 --- /dev/null +++ b/README.md @@ -0,0 +1,235 @@ +# All-in-RAG | 大模型应用开发实战一:RAG技术全栈指南 + +
+ All-in-RAG Logo +
+ +
+

🔍 检索增强生成 (RAG) 技术全栈指南

+

从理论到实践,从基础到进阶,构建你的RAG技术体系

+
+ +
+ GitHub stars + GitHub forks + Python + + zread + +
+ + + +
+
+ + + + + + + +
🎯 系统化学习
完整的RAG技术体系
🛠️ 动手实践
丰富的项目案例
🚀 生产就绪
工程化最佳实践
📊 多模态支持
文本+图像检索
+
+ +## 项目简介(中文 | [English](README_en.md)) + +本项目是一个面向大模型应用开发者的RAG(检索增强生成)技术全栈教程,旨在通过体系化的学习路径和动手实践项目,帮助开发者掌握基于大语言模型的RAG应用开发技能,构建生产级的智能问答和知识检索系统。 + +**主要内容包括:** + +1. **RAG技术基础**:深入浅出地介绍RAG的核心概念、技术原理和应用场景 +2. **数据处理全流程**:从数据加载、清洗到文本分块的完整数据准备流程 +3. **索引构建与优化**:向量嵌入、多模态嵌入、向量数据库构建及索引优化技术 +4. **检索技术进阶**:混合检索、查询构建、Text2SQL等高级检索技术 +5. **生成集成与评估**:格式化生成、系统评估与优化方法 +6. **项目实战**:从基础到进阶的完整RAG应用开发实践 + +## 项目意义 + +随着大语言模型的快速发展,RAG技术已成为构建智能问答系统、知识检索应用的核心技术。然而,现有的RAG教程往往零散且缺乏系统性,初学者难以形成完整的技术体系认知。 + +本项目从实践出发,结合最新的RAG技术发展趋势,构建了一套完整的RAG学习体系,帮助开发者: +- 系统掌握RAG技术的理论基础和实践技能 +- 理解RAG系统的完整架构和各组件的作用 +- 具备独立开发RAG应用的能力 +- 掌握RAG系统的评估和优化方法 + +## 项目受众 + +**本项目适合以下人群学习:** +- 具备Python编程基础,对RAG技术感兴趣的开发者 +- 希望系统学习RAG技术的AI工程师 +- 想要构建智能问答系统的产品开发者 +- 对检索增强生成技术有学习需求的研究人员 + +**前置要求:** +- 掌握Python基础语法和常用库的使用 +- 能够简单使用docker +- 了解基本的LLM概念(推荐但非必需) +- 具备基础的Linux命令行操作能力 + +## 项目亮点 + +1. **体系化学习路径**:从基础概念到高级应用,构建完整的RAG技术学习体系 +2. **理论与实践并重**:每个章节都包含理论讲解和代码实践,确保学以致用 +3. **多模态支持**:不仅涵盖文本RAG,还包括多模态嵌入和检索技术 +4. **工程化导向**:注重实际应用中的工程化问题,包括性能优化、系统评估等 +5. **丰富的实战项目**:提供从基础到进阶的多个实战项目,帮助巩固学习成果 + +## 内容大纲 + +### 第一部分:RAG基础入门 + +**第一章 解锁RAG** [📖 查看章节](./docs/chapter1) +- [x] [RAG简介](./docs/chapter1/01_RAG_intro.md) - RAG技术概述与应用场景 +- [x] [准备工作](./docs/chapter1/02_preparation.md) - 环境配置与准备 +- [x] [四步构建RAG](./docs/chapter1/03_get_start_rag.md) - 快速上手RAG开发 +- [x] [附:环境部署](./docs/chapter1/virtualenv.md) - Python虚拟环境部署方案补充 (贡献者: [@anarchysaiko](https://github.com/anarchysaiko)) + +**第二章 数据准备** [📖 查看章节](./docs/chapter2) +- [x] [数据加载](./docs/chapter2/04_data_load.md) - 多格式文档处理与加载 +- [x] [文本分块](./docs/chapter2/05_text_chunking.md) - 文本切分策略与优化 + +### 第二部分:索引构建与优化 + +**第三章 索引构建** [📖 查看章节](./docs/chapter3) +- [x] [向量嵌入](./docs/chapter3/06_vector_embedding.md) - 文本向量化技术详解 +- [x] [多模态嵌入](./docs/chapter3/07_multimodal_embedding.md) - 图文多模态向量化 +- [x] [向量数据库](./docs/chapter3/08_vector_db.md) - 向量存储与检索系统 +- [x] [Milvus实践](./docs/chapter3/09_milvus.md) - Milvus多模态检索实战 +- [x] [索引优化](./docs/chapter3/10_index_optimization.md) - 索引性能调优技巧 + +### 第三部分:检索技术进阶 + +**第四章 检索优化** [📖 查看章节](./docs/chapter4) +- [x] [混合检索](./docs/chapter4/11_hybrid_search.md) - 稠密+稀疏检索融合 +- [x] [查询构建](./docs/chapter4/12_query_construction.md) - 智能查询理解与构建 +- [x] [Text2SQL](./docs/chapter4/13_text2sql.md) - 自然语言转SQL查询 +- [x] [查询重构与分发](./docs/chapter4/14_query_rewriting.md) - 查询优化策略 +- [x] [检索进阶技术](./docs/chapter4/15_advanced_retrieval_techniques.md) - 高级检索算法 + +### 第四部分:生成与评估 + +**第五章 生成集成** [📖 查看章节](./docs/chapter5) +- [x] [格式化生成](./docs/chapter5/16_formatted_generation.md) - 结构化输出与格式控制 + +**第六章 RAG系统评估** [📖 查看章节](./docs/chapter6) +- [x] [评估介绍](./docs/chapter6/18_system_evaluation.md) - RAG系统评估方法论 +- [x] [评估工具](./docs/chapter6/19_common_tools.md) - 常用评估工具与指标 + +### 第五部分:高级应用与实战 + +**第七章 高级RAG架构(拓展部分)** [📖 查看章节](./docs/chapter7) + +- [x] [基于知识图谱的RAG](./docs/chapter7/20_kg_rag.md) + +**第八章 项目实战一** [📖 查看章节](./docs/chapter8) +- [x] [环境配置与项目架构](./docs/chapter8/01_env_architecture.md) +- [x] [数据准备模块实现](./docs/chapter8/02_data_preparation.md) +- [x] [索引构建与检索优化](./docs/chapter8/03_index_retrieval.md) +- [x] [生成集成与系统整合](./docs/chapter8/04_generation_sys.md) + +**第九章 项目实战一优化(选修篇)** [📖 查看章节](./docs/chapter9) + +[🍽️ 项目展示](https://github.com/FutureUnreal/What-to-eat-today) +- [x] [图RAG架构设计](./docs/chapter9/01_graph_rag_architecture.md) +- [x] [图数据建模与准备](./docs/chapter9/02_graph_data_modeling.md) +- [x] [Milvus索引构建](./docs/chapter9/03_index_construction.md) +- [x] [智能查询路由与检索策略](./docs/chapter9/04_intelligent_query_routing.md) + +**第十章 项目实战二(选修篇)** [📖 查看章节](./docs/chapter10) *规划中* + +### Extra-chapter + +- [Neo4J 简单应用](./Extra-chapter/Neo4J-Simple-Application/readme.md) (贡献者: [dalvqw](https://github.com/FutureUnreal)) + +> 如果你在使用 RAG / 向量数据库 / Agentic RAG 等相关技术时,也有值得分享的经验与专题内容,非常欢迎以独立章节的形式投稿到 [Extra Chapter](./Extra-chapter/) 中。提交前请先阅读 Extra Chapter 的[贡献与 PR 指南](./Extra-chapter/README.md),我们会根据内容的完整度、实践深度与参考价值综合评估是否合并,并视情况在主教程中进行引用或扩展说明。 + +## 目录结构说明 + +``` +all-in-rag/ +├── docs/ # 教程文档 +├── code/ # 代码示例 +├── data/ # 示例数据 +├── models/ # 预训练模型 +├── Extra-chapter/ # 扩展章节与社区实践内容 +└── README.md # 项目说明 +``` + +## 实战项目展示 + +### 第八章 项目一: + +![项目一](./project01.png) + +### 第九章 项目一(Graph RAG优化): + +![项目一(Graph RAG优化)](./project01_graph.png) + +### 第十章 项目二: + +## 致谢 + +**核心贡献者** +- [dalvqw-项目负责人](https://github.com/FutureUnreal)(项目发起人与主要贡献者) + +**额外章节贡献者** +- [孙超-内容创作者](https://github.com/anarchysaiko)(Datawhale成员-上海工程技术大学) + +### 特别感谢 +- 感谢 [@Sm1les](https://github.com/Sm1les) 对本项目的帮助与支持 +- 感谢所有为本项目做出贡献的开发者们 +- 感谢开源社区提供的优秀工具和框架支持 +- 特别感谢以下为教程做出贡献的开发者! + +[![Contributors](https://contrib.rocks/image?repo=datawhalechina/all-in-rag)](https://github.com/datawhalechina/all-in-rag/graphs/contributors) + +*Made with [contrib.rocks](https://contrib.rocks).* + +## 参与贡献 + +我们欢迎所有形式的贡献,包括但不限于: + +- 🚨 **Bug报告**:发现问题请提交 [Issue](https://github.com/datawhalechina/all-in-rag/issues) +- 💭 **教程建议**:有好的想法欢迎在 [Discussions](https://github.com/datawhalechina/all-in-rag/discussions) 中讨论 +- 📚 **文档改进**:帮助完善文档内容和示例代码(当前仅支持 Extra-chapter 优质内容pr) + +## Star History + +[![all-in-rag stats](https://datawhalechina.github.io/members-visualization/badges/all-in-rag.png)](https://datawhalechina.github.io/members-visualization/repo-badge?repo=all-in-rag) + +
+

如果这个项目对你有帮助,请给我们一个 ⭐️

+

让更多人发现这个项目(护食?发来!)

+
+ +![star](./emoji.png) + +## 关于 Datawhale + +
+ Datawhale +

扫描二维码关注 Datawhale 公众号,获取更多优质开源内容

+
+ +--- + +## 许可证 + +知识共享许可协议 + +本作品采用 [知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议](http://creativecommons.org/licenses/by-nc-sa/4.0/) 进行许可。 + +--- diff --git a/README_en.md b/README_en.md new file mode 100644 index 0000000..0986ea7 --- /dev/null +++ b/README_en.md @@ -0,0 +1,222 @@ +# All-in-RAG | Large Model Application Development Practice: RAG Technology Full-Stack Guide + +
+ All-in-RAG Logo +
+ +
+

🔍 Retrieval-Augmented Generation (RAG) Technology Full-Stack Guide

+

From theory to practice, from basics to advanced, build your RAG technology system

+
+ +
+ GitHub stars + GitHub forks + Python +
+ + + +
+
+ + + + + + + +
🎯 Systematic Learning
Complete RAG technology system
🛠️ Hands-on Practice
Rich project examples
🚀 Production Ready
Engineering best practices
📊 Multimodal Support
Text + Image retrieval
+
+ +## Project Introduction([中文](README.md) | English) + +This project is a comprehensive RAG (Retrieval-Augmented Generation) technology full-stack tutorial for large model application developers. It aims to help developers master RAG application development skills based on large language models through systematic learning paths and hands-on practice projects, building production-grade intelligent Q&A and knowledge retrieval systems. + +**Main content includes:** + +1. **RAG Technology Fundamentals**: In-depth introduction to RAG core concepts, technical principles, and application scenarios +2. **Complete Data Processing Pipeline**: From data loading, cleaning to text chunking - the complete data preparation process +3. **Index Construction and Optimization**: Vector embedding, multimodal embedding, vector database construction and index optimization techniques +4. **Advanced Retrieval Techniques**: Hybrid retrieval, query construction, Text2SQL and other advanced retrieval technologies +5. **Generation Integration and Evaluation**: Formatted generation, system evaluation and optimization methods +6. **Project Practice**: Complete RAG application development practice from basic to advanced + +## Project Significance + +With the rapid development of large language models, RAG technology has become the core technology for building intelligent Q&A systems and knowledge retrieval applications. However, existing RAG tutorials are often scattered and lack systematicity, making it difficult for beginners to form a complete understanding of the technical system. + +Starting from practice and combining the latest RAG technology development trends, this project builds a complete RAG learning system to help developers: +- Systematically master the theoretical foundation and practical skills of RAG technology +- Understand the complete architecture of RAG systems and the role of each component +- Develop the ability to independently develop RAG applications +- Master evaluation and optimization methods for RAG systems + +## Target Audience + +**This project is suitable for the following groups:** +- Developers with Python programming foundation who are interested in RAG technology +- AI engineers who want to systematically learn RAG technology +- Product developers who want to build intelligent Q&A systems +- Researchers with learning needs for retrieval-augmented generation technology + +**Prerequisites:** +- Master Python basic syntax and usage of common libraries +- Ability to use Docker simply +- Understanding of basic LLM concepts (recommended but not required) +- Basic Linux command line operation skills + +## Project Highlights + +1. **Systematic Learning Path**: From basic concepts to advanced applications, building a complete RAG technology learning system +2. **Theory and Practice Combined**: Each chapter includes theoretical explanation and code practice to ensure learning and application +3. **Multimodal Support**: Covers not only text RAG, but also multimodal embedding and retrieval technologies +4. **Engineering-Oriented**: Focus on engineering problems in practical applications, including performance optimization, system evaluation, etc. +5. **Rich Practical Projects**: Provides multiple practical projects from basic to advanced to help consolidate learning outcomes + +## Content Outline + +### Part I: RAG Fundamentals + +**Chapter 1 Unlocking RAG** [📖 View Chapter](./docs/en/chapter1) +1. [x] [RAG Introduction](./docs/en/chapter1/01_RAG_intro.md) - RAG technology overview and application scenarios +2. [x] [Preparation](./docs/en/chapter1/02_preparation.md) - Environment configuration and preparation +3. [x] [Four Steps to Build RAG](./docs/en/chapter1/03_get_start_rag.md) - Quick start with RAG development + +**Chapter 2 Data Preparation** [📖 View Chapter](./docs/en/chapter2) +1. [x] [Data Loading](./docs/en/chapter2/04_data_load.md) - Multi-format document processing and loading +2. [x] [Text Chunking](./docs/en/chapter2/05_text_chunking.md) - Text segmentation strategies and optimization + +### Part II: Index Construction and Optimization + +**Chapter 3 Index Construction** [📖 View Chapter](./docs/en/chapter3) +1. [x] [Vector Embedding](./docs/en/chapter3/06_vector_embedding.md) - Detailed explanation of text vectorization technology +2. [x] [Multimodal Embedding](./docs/en/chapter3/07_multimodal_embedding.md) - Image-text multimodal vectorization +3. [x] [Vector Database](./docs/en/chapter3/08_vector_db.md) - Vector storage and retrieval systems +4. [x] [Milvus Practice](./docs/en/chapter3/09_milvus.md) - Milvus multimodal retrieval practice +5. [x] [Index Optimization](./docs/en/chapter3/10_index_optimization.md) - Index performance tuning techniques + +### Part III: Advanced Retrieval Techniques + +**Chapter 4 Retrieval Optimization** [📖 View Chapter](./docs/en/chapter4) +1. [x] [Hybrid Search](./docs/en/chapter4/11_hybrid_search.md) - Dense + sparse retrieval fusion +2. [x] [Query Construction](./docs/en/chapter4/12_query_construction.md) - Intelligent query understanding and construction +3. [x] [Text2SQL](./docs/en/chapter4/13_text2sql.md) - Natural language to SQL query +4. [x] [Query Rewriting and Routing](./docs/en/chapter4/14_query_rewriting.md) - Query optimization strategies +5. [x] [Advanced Retrieval Techniques](./docs/en/chapter4/15_advanced_retrieval_techniques.md) - Advanced retrieval algorithms + +### Part IV: Generation and Evaluation + +**Chapter 5 Generation Integration** [📖 View Chapter](./docs/en/chapter5) +1. [x] [Formatted Generation](./docs/en/chapter5/16_formatted_generation.md) - Structured output and format control + +**Chapter 6 RAG System Evaluation** [📖 View Chapter](./docs/en/chapter6) +1. [x] [Evaluation Introduction](./docs/en/chapter6/18_system_evaluation.md) - RAG system evaluation methodology +2. [x] [Evaluation Tools](./docs/en/chapter6/19_common_tools.md) - Common evaluation tools and metrics + +### Part V: Advanced Applications and Practice + +**Chapter 7 Advanced RAG Architecture (Extended Elective)** [📖 View Chapter](./docs/en/chapter7) + +1. [x] [Knowledge Graph-based RAG](./docs/en/chapter7/20_kg_rag.md) + +**Chapter 8 Project Practice I (Basic)** [📖 View Chapter](./docs/en/chapter8) +1. [x] [Environment Configuration and Project Architecture](./docs/en/chapter8/01_env_architecture.md) +2. [x] [Data Preparation Module Implementation](./docs/en/chapter8/02_data_preparation.md) +3. [x] [Index Construction and Retrieval Optimization](./docs/en/chapter8/03_index_retrieval.md) +4. [x] [Generation Integration and System Integration](./docs/en/chapter8/04_generation_sys.md) + +**Chapter 9 Project Practice I Optimization (Elective)** [📖 View Chapter](./docs/en/chapter9) + +[🍽️ Project Demo](https://github.com/FutureUnreal/What-to-eat-today) +1. [x] [Graph RAG Architecture Design](./docs/en/chapter9/01_graph_rag_architecture.md) +2. [x] [Graph Data Modeling and Preparation](./docs/en/chapter9/02_graph_data_modeling.md) +3. [x] [Milvus Index Construction](./docs/en/chapter9/03_index_construction.md) +4. [x] [Intelligent Query Routing and Retrieval Strategy](./docs/en/chapter9/04_intelligent_query_routing.md) + +**Chapter 10 Project Practice II (Elective)** [📖 View Chapter](./docs/en/chapter10) *In Planning* + +## Directory Structure + +``` +all-in-rag/ +├── docs/ # Tutorial documentation +├── code/ # Code examples +├── data/ # Sample data +├── models/ # Pre-trained models +└── README.md # Project description +``` + +## Practical Project Showcase + +### Chapter 8 Project I: + +![Project I](./project01.png) + +### Chapter 9 Project I (Graph RAG Optimization): + +![Project I (Graph RAG Optimization)](./project01_graph.png) + +### Chapter 10 Project II: + +## Acknowledgments + +**Core Contributors** +- [Yin Dalv - Project Lead](https://github.com/FutureUnreal) (Project initiator and main contributor) + +### Special Thanks +- Thanks to [@Sm1les](https://github.com/Sm1les) for help and support on this project +- Thanks to all developers who contributed to this project +- Thanks to the open source community for providing excellent tools and framework support +- Special thanks to the following developers who contributed to the tutorial! + +[![Contributors](https://contrib.rocks/image?repo=datawhalechina/all-in-rag)](https://github.com/datawhalechina/all-in-rag/graphs/contributors) + +*Made with [contrib.rocks](https://contrib.rocks).* + +## Contributing + +We welcome all forms of contributions, including but not limited to: + +- 🚨 **Bug Reports**: Please submit [Issues](https://github.com/datawhalechina/all-in-rag/issues) if you find problems +- 💭 **Feature Suggestions**: Welcome to discuss good ideas in [Discussions](https://github.com/datawhalechina/all-in-rag/discussions) +- 📚 **Documentation Improvement**: Help improve documentation content and example code +- ⚡ **Code Contributions**: Submit [Pull Requests](https://github.com/datawhalechina/all-in-rag/pulls) to improve the project + +## Star History + +[![all-in-rag stats](https://datawhalechina.github.io/members-visualization/badges/all-in-rag.png)](https://datawhalechina.github.io/members-visualization/repo-badge?repo=all-in-rag) + +
+

If this project helps you, please give us a ⭐️

+

Let more people discover this project (Food protection? Bring it on!)

+
+ +![star](./emoji.png) + +## About Datawhale + +
+ Datawhale +

Scan the QR code to follow Datawhale WeChat Official Account for more quality open source content

+
+ +--- + +## License + +Creative Commons License + +This work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/). + +--- \ No newline at end of file diff --git a/code/C1/01_langchain_example.py b/code/C1/01_langchain_example.py new file mode 100644 index 0000000..33346e1 --- /dev/null +++ b/code/C1/01_langchain_example.py @@ -0,0 +1,75 @@ +import os +# hugging face镜像设置,如果国内环境无法使用启用该设置 +# os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com' +from dotenv import load_dotenv +from langchain_community.document_loaders import UnstructuredMarkdownLoader +from langchain_text_splitters import RecursiveCharacterTextSplitter +from langchain_huggingface import HuggingFaceEmbeddings +from langchain_core.vectorstores import InMemoryVectorStore +from langchain_core.prompts import ChatPromptTemplate +from langchain_openai import ChatOpenAI + +load_dotenv() + +markdown_path = "../../data/C1/markdown/easy-rl-chapter1.md" + +# 加载本地markdown文件 +loader = UnstructuredMarkdownLoader(markdown_path) +docs = loader.load() + +# 文本分块 +text_splitter = RecursiveCharacterTextSplitter() +chunks = text_splitter.split_documents(docs) + +# 中文嵌入模型 +embeddings = HuggingFaceEmbeddings( + model_name="BAAI/bge-small-zh-v1.5", + model_kwargs={'device': 'cpu'}, + encode_kwargs={'normalize_embeddings': True} +) + +# 构建向量存储 +vectorstore = InMemoryVectorStore(embeddings) +vectorstore.add_documents(chunks) + +# 提示词模板 +prompt = ChatPromptTemplate.from_template("""请根据下面提供的上下文信息来回答问题。 +请确保你的回答完全基于这些上下文。 +如果上下文中没有足够的信息来回答问题,请直接告知:“抱歉,我无法根据提供的上下文找到相关信息来回答此问题。” + +上下文: +{context} + +问题: {question} + +回答:""" + ) + +# 配置大语言模型 + +# 使用 AIHubmix +llm = ChatOpenAI( + model="glm-4.7-flash-free", + temperature=0.7, + max_tokens=4096, + api_key=os.getenv("DEEPSEEK_API_KEY"), + base_url="https://aihubmix.com/v1" +) + +# llm = ChatOpenAI( +# model="deepseek-chat", +# temperature=0.7, +# max_tokens=4096, +# api_key=os.getenv("DEEPSEEK_API_KEY"), +# base_url="https://api.deepseek.com" +# ) + +# 用户查询 +question = "文中举了哪些例子?" + +# 在向量存储中查询相关文档 +retrieved_docs = vectorstore.similarity_search(question, k=3) +docs_content = "\n\n".join(doc.page_content for doc in retrieved_docs) + +answer = llm.invoke(prompt.format(question=question, context=docs_content)) +print(answer) diff --git a/code/C1/02_llamaIndex_example.py b/code/C1/02_llamaIndex_example.py new file mode 100644 index 0000000..eed667d --- /dev/null +++ b/code/C1/02_llamaIndex_example.py @@ -0,0 +1,33 @@ +import os +# os.environ['HF_ENDPOINT']='https://hf-mirror.com' +from dotenv import load_dotenv +from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings +from llama_index.llms.openai_like import OpenAILike +from llama_index.embeddings.huggingface import HuggingFaceEmbedding + +load_dotenv() + +# 使用 AIHubmix +Settings.llm = OpenAILike( + model="glm-4.7-flash-free", + api_key=os.getenv("DEEPSEEK_API_KEY"), + api_base="https://aihubmix.com/v1", + is_chat_model=True +) + +# Settings.llm = OpenAI( +# model="deepseek-chat", +# api_key=os.getenv("DEEPSEEK_API_KEY"), +# api_base="https://api.deepseek.com" +# ) +Settings.embed_model = HuggingFaceEmbedding("BAAI/bge-small-zh-v1.5") + +docs = SimpleDirectoryReader(input_files=["../../data/C1/markdown/easy-rl-chapter1.md"]).load_data() + +index = VectorStoreIndex.from_documents(docs) + +query_engine = index.as_query_engine() + +print(query_engine.get_prompts()) + +print(query_engine.query("文中举了哪些例子?")) \ No newline at end of file diff --git a/code/C1/fix_nltk.py b/code/C1/fix_nltk.py new file mode 100644 index 0000000..3e3bd34 --- /dev/null +++ b/code/C1/fix_nltk.py @@ -0,0 +1,4 @@ +import nltk + +nltk.download('punkt', force=True) +nltk.download('averaged_perceptron_tagger', force=True) \ No newline at end of file diff --git a/code/C2/01_unstructured_example.py b/code/C2/01_unstructured_example.py new file mode 100644 index 0000000..fa0fa99 --- /dev/null +++ b/code/C2/01_unstructured_example.py @@ -0,0 +1,25 @@ +from unstructured.partition.auto import partition + +# PDF文件路径 +pdf_path = "../../data/C2/pdf/rag.pdf" + +# 使用Unstructured加载并解析PDF文档 +elements = partition( + filename=pdf_path, + content_type="application/pdf" +) + +# 打印解析结果 +print(f"解析完成: {len(elements)} 个元素, {sum(len(str(e)) for e in elements)} 字符") + +# 统计元素类型 +from collections import Counter +types = Counter(e.category for e in elements) +print(f"元素类型: {dict(types)}") + +# 显示所有元素 +print("\n所有元素:") +for i, element in enumerate(elements, 1): + print(f"Element {i} ({element.category}):") + print(element) + print("=" * 60) \ No newline at end of file diff --git a/code/C2/02_character_splitter.py b/code/C2/02_character_splitter.py new file mode 100644 index 0000000..485fe7d --- /dev/null +++ b/code/C2/02_character_splitter.py @@ -0,0 +1,23 @@ +from langchain.text_splitter import CharacterTextSplitter +from langchain_community.document_loaders import TextLoader + +# 1. 文档加载 +loader = TextLoader("../../data/C2/txt/蜂医.txt", encoding="utf-8") +docs = loader.load() + +# 2. 初始化固定大小分块器 +text_splitter = CharacterTextSplitter( + chunk_size=200, # 每个块的大小 + chunk_overlap=10 # 块之间的重叠大小 +) + +# 3. 执行分块 +chunks = text_splitter.split_documents(docs) + +# 4. 打印结果 +print(f"文本被切分为 {len(chunks)} 个块。\n") +print("--- 前5个块内容示例 ---") +for i, chunk in enumerate(chunks[:5]): + print("=" * 60) + # chunk 是一个 Document 对象,需要访问它的 .page_content 属性来获取文本 + print(f'块 {i+1} (长度: {len(chunk.page_content)}): "{chunk.page_content}"') diff --git a/code/C2/03_recursive_character_splitter.py b/code/C2/03_recursive_character_splitter.py new file mode 100644 index 0000000..82ee06a --- /dev/null +++ b/code/C2/03_recursive_character_splitter.py @@ -0,0 +1,20 @@ +from langchain.text_splitter import RecursiveCharacterTextSplitter +from langchain_community.document_loaders import TextLoader + +loader = TextLoader("../../data/C2/txt/蜂医.txt", encoding="utf-8") +docs = loader.load() + +text_splitter = RecursiveCharacterTextSplitter( + # 针对中英文混合文本,定义一个更全面的分隔符列表 + separators=["\n\n", "\n", "。", ",", " ", ""], # 按顺序尝试分割 + chunk_size=200, + chunk_overlap=10 +) + +chunks = text_splitter.split_documents(docs) + +print(f"文本被切分为 {len(chunks)} 个块。\n") +print("--- 前5个块内容示例 ---") +for i, chunk in enumerate(chunks[:5]): + print("=" * 60) + print(f'块 {i+1} (长度: {len(chunk.page_content)}): "{chunk.page_content}"') diff --git a/code/C2/04_semantic_chunker.py b/code/C2/04_semantic_chunker.py new file mode 100644 index 0000000..6fa9b94 --- /dev/null +++ b/code/C2/04_semantic_chunker.py @@ -0,0 +1,26 @@ +from langchain_experimental.text_splitter import SemanticChunker +from langchain_community.embeddings import HuggingFaceEmbeddings +from langchain_community.document_loaders import TextLoader + +embeddings = HuggingFaceEmbeddings( + model_name="BAAI/bge-small-zh-v1.5", + model_kwargs={'device': 'cpu'}, + encode_kwargs={'normalize_embeddings': True} +) + +# 初始化 SemanticChunker +text_splitter = SemanticChunker( + embeddings, + breakpoint_threshold_type="percentile" # 也可以是 "standard_deviation", "interquartile", "gradient" +) + +loader = TextLoader("../../data/C2/txt/蜂医.txt", encoding="utf-8") +documents = loader.load() + +docs = text_splitter.split_documents(documents) + +print(f"文本被切分为 {len(docs)} 个块。\n") +print("--- 前2个块内容示例 ---") +for i, chunk in enumerate(docs[:2]): + print("=" * 60) + print(f'块 {i+1} (长度: {len(chunk.page_content)}):\n"{chunk.page_content}"') diff --git a/code/C3/01_bge_visualized.py b/code/C3/01_bge_visualized.py new file mode 100644 index 0000000..6291911 --- /dev/null +++ b/code/C3/01_bge_visualized.py @@ -0,0 +1,32 @@ +import torch +from visual_bge.visual_bge.modeling import Visualized_BGE + +model = Visualized_BGE(model_name_bge="BAAI/bge-base-en-v1.5", + model_weight="../../models/bge/Visualized_base_en_v1.5.pth") +model.eval() + +with torch.no_grad(): + text_emb = model.encode(text="datawhale开源组织的logo") + img_emb_1 = model.encode(image="../../data/C3/imgs/datawhale01.png") + multi_emb_1 = model.encode(image="../../data/C3/imgs/datawhale01.png", text="datawhale开源组织的logo") + img_emb_2 = model.encode(image="../../data/C3/imgs/datawhale02.png") + multi_emb_2 = model.encode(image="../../data/C3/imgs/datawhale02.png", text="datawhale开源组织的logo") + +# 计算相似度 +sim_1 = img_emb_1 @ img_emb_2.T +sim_2 = img_emb_1 @ multi_emb_1.T +sim_3 = text_emb @ multi_emb_1.T +sim_4 = multi_emb_1 @ multi_emb_2.T + +print("=== 相似度计算结果 ===") +print(f"纯图像 vs 纯图像: {sim_1}") +print(f"图文结合1 vs 纯图像: {sim_2}") +print(f"图文结合1 vs 纯文本: {sim_3}") +print(f"图文结合1 vs 图文结合2: {sim_4}") + +# 向量信息分析 +print("\n=== 嵌入向量信息 ===") +print(f"多模态向量维度: {multi_emb_1.shape}") +print(f"图像向量维度: {img_emb_1.shape}") +print(f"多模态向量示例 (前10个元素): {multi_emb_1[0][:10]}") +print(f"图像向量示例 (前10个元素): {img_emb_1[0][:10]}") diff --git a/code/C3/02_langchain_faiss.py b/code/C3/02_langchain_faiss.py new file mode 100644 index 0000000..2cb8f2f --- /dev/null +++ b/code/C3/02_langchain_faiss.py @@ -0,0 +1,37 @@ +from langchain_community.vectorstores import FAISS +from langchain_community.embeddings import HuggingFaceEmbeddings +from langchain_core.documents import Document + +# 1. 示例文本和嵌入模型 +texts = [ + "张三是法外狂徒", + "FAISS是一个用于高效相似性搜索和密集向量聚类的库。", + "LangChain是一个用于开发由语言模型驱动的应用程序的框架。" +] +docs = [Document(page_content=t) for t in texts] +embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5") + +# 2. 创建向量存储并保存到本地 +vectorstore = FAISS.from_documents(docs, embeddings) + +local_faiss_path = "./faiss_index_store" +vectorstore.save_local(local_faiss_path) + +print(f"FAISS index has been saved to {local_faiss_path}") + +# 3. 加载索引并执行查询 +# 加载时需指定相同的嵌入模型,并允许反序列化 +loaded_vectorstore = FAISS.load_local( + local_faiss_path, + embeddings, + allow_dangerous_deserialization=True +) + +# 执行相似性搜索 +query = "FAISS是做什么的?" +results = loaded_vectorstore.similarity_search(query, k=1) + +print(f"\n查询: '{query}'") +print("相似度最高的文档:") +for doc in results: + print(f"- {doc.page_content}") \ No newline at end of file diff --git a/code/C3/03_llamaindex_vector.py b/code/C3/03_llamaindex_vector.py new file mode 100644 index 0000000..d9d0b3b --- /dev/null +++ b/code/C3/03_llamaindex_vector.py @@ -0,0 +1,19 @@ +from llama_index.core import VectorStoreIndex, Document, Settings +from llama_index.embeddings.huggingface import HuggingFaceEmbedding + +# 1. 配置全局嵌入模型 +Settings.embed_model = HuggingFaceEmbedding("BAAI/bge-small-zh-v1.5") + +# 2. 创建示例文档 +texts = [ + "张三是法外狂徒", + "LlamaIndex是一个用于构建和查询私有或领域特定数据的框架。", + "它提供了数据连接、索引和查询接口等工具。" +] +docs = [Document(text=t) for t in texts] + +# 3. 创建索引并持久化到本地 +index = VectorStoreIndex.from_documents(docs) +persist_path = "./llamaindex_index_store" +index.storage_context.persist(persist_dir=persist_path) +print(f"LlamaIndex 索引已保存至: {persist_path}") diff --git a/code/C3/04_multi_milvus.py b/code/C3/04_multi_milvus.py new file mode 100644 index 0000000..eddf02f --- /dev/null +++ b/code/C3/04_multi_milvus.py @@ -0,0 +1,160 @@ +import os +from tqdm import tqdm +from glob import glob +import torch +from visual_bge.visual_bge.modeling import Visualized_BGE +from pymilvus import MilvusClient, FieldSchema, CollectionSchema, DataType +import numpy as np +import cv2 +from PIL import Image + +# 1. 初始化设置 +MODEL_NAME = "BAAI/bge-base-en-v1.5" +MODEL_PATH = "../../models/bge/Visualized_base_en_v1.5.pth" +DATA_DIR = "../../data/C3" +COLLECTION_NAME = "multimodal_demo" +MILVUS_URI = "http://localhost:19530" + +# 2. 定义工具 (编码器和可视化函数) +class Encoder: + """编码器类,用于将图像和文本编码为向量。""" + def __init__(self, model_name: str, model_path: str): + self.model = Visualized_BGE(model_name_bge=model_name, model_weight=model_path) + self.model.eval() + + def encode_query(self, image_path: str, text: str) -> list[float]: + with torch.no_grad(): + query_emb = self.model.encode(image=image_path, text=text) + return query_emb.tolist()[0] + + def encode_image(self, image_path: str) -> list[float]: + with torch.no_grad(): + query_emb = self.model.encode(image=image_path) + return query_emb.tolist()[0] + +def visualize_results(query_image_path: str, retrieved_images: list, img_height: int = 300, img_width: int = 300, row_count: int = 3) -> np.ndarray: + """从检索到的图像列表创建一个全景图用于可视化。""" + panoramic_width = img_width * row_count + panoramic_height = img_height * row_count + panoramic_image = np.full((panoramic_height, panoramic_width, 3), 255, dtype=np.uint8) + query_display_area = np.full((panoramic_height, img_width, 3), 255, dtype=np.uint8) + + # 处理查询图像 + query_pil = Image.open(query_image_path).convert("RGB") + query_cv = np.array(query_pil)[:, :, ::-1] + resized_query = cv2.resize(query_cv, (img_width, img_height)) + bordered_query = cv2.copyMakeBorder(resized_query, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=(255, 0, 0)) + query_display_area[img_height * (row_count - 1):, :] = cv2.resize(bordered_query, (img_width, img_height)) + cv2.putText(query_display_area, "Query", (10, panoramic_height - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) + + # 处理检索到的图像 + for i, img_path in enumerate(retrieved_images): + row, col = i // row_count, i % row_count + start_row, start_col = row * img_height, col * img_width + + retrieved_pil = Image.open(img_path).convert("RGB") + retrieved_cv = np.array(retrieved_pil)[:, :, ::-1] + resized_retrieved = cv2.resize(retrieved_cv, (img_width - 4, img_height - 4)) + bordered_retrieved = cv2.copyMakeBorder(resized_retrieved, 2, 2, 2, 2, cv2.BORDER_CONSTANT, value=(0, 0, 0)) + panoramic_image[start_row:start_row + img_height, start_col:start_col + img_width] = bordered_retrieved + + # 添加索引号 + cv2.putText(panoramic_image, str(i), (start_col + 10, start_row + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) + + return np.hstack([query_display_area, panoramic_image]) + +# 3. 初始化客户端 +print("--> 正在初始化编码器和Milvus客户端...") +encoder = Encoder(MODEL_NAME, MODEL_PATH) +milvus_client = MilvusClient(uri=MILVUS_URI) + +# 4. 创建 Milvus Collection +print(f"\n--> 正在创建 Collection '{COLLECTION_NAME}'") +if milvus_client.has_collection(COLLECTION_NAME): + milvus_client.drop_collection(COLLECTION_NAME) + print(f"已删除已存在的 Collection: '{COLLECTION_NAME}'") + +image_list = glob(os.path.join(DATA_DIR, "dragon", "*.png")) +if not image_list: + raise FileNotFoundError(f"在 {DATA_DIR}/dragon/ 中未找到任何 .png 图像。") +dim = len(encoder.encode_image(image_list[0])) + +fields = [ + FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True), + FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=dim), + FieldSchema(name="image_path", dtype=DataType.VARCHAR, max_length=512), +] + +# 创建集合 Schema +schema = CollectionSchema(fields, description="多模态图文检索") +print("Schema 结构:") +print(schema) + +# 创建集合 +milvus_client.create_collection(collection_name=COLLECTION_NAME, schema=schema) +print(f"成功创建 Collection: '{COLLECTION_NAME}'") +print("Collection 结构:") +print(milvus_client.describe_collection(collection_name=COLLECTION_NAME)) + +# 5. 准备并插入数据 +print(f"\n--> 正在向 '{COLLECTION_NAME}' 插入数据") +data_to_insert = [] +for image_path in tqdm(image_list, desc="生成图像嵌入"): + vector = encoder.encode_image(image_path) + data_to_insert.append({"vector": vector, "image_path": image_path}) + +if data_to_insert: + result = milvus_client.insert(collection_name=COLLECTION_NAME, data=data_to_insert) + print(f"成功插入 {result['insert_count']} 条数据。") + +# 6. 创建索引 +print(f"\n--> 正在为 '{COLLECTION_NAME}' 创建索引") +index_params = milvus_client.prepare_index_params() +index_params.add_index( + field_name="vector", + index_type="HNSW", + metric_type="COSINE", + params={"M": 16, "efConstruction": 256} +) +milvus_client.create_index(collection_name=COLLECTION_NAME, index_params=index_params) +print("成功为向量字段创建 HNSW 索引。") +print("索引详情:") +print(milvus_client.describe_index(collection_name=COLLECTION_NAME, index_name="vector")) +milvus_client.load_collection(collection_name=COLLECTION_NAME) +print("已加载 Collection 到内存中。") + +# 7. 执行多模态检索 +print(f"\n--> 正在 '{COLLECTION_NAME}' 中执行检索") +query_image_path = os.path.join(DATA_DIR, "dragon", "query.png") +query_text = "一条龙" +query_vector = encoder.encode_query(image_path=query_image_path, text=query_text) + +search_results = milvus_client.search( + collection_name=COLLECTION_NAME, + data=[query_vector], + output_fields=["image_path"], + limit=5, + search_params={"metric_type": "COSINE", "params": {"ef": 128}} +)[0] + +retrieved_images = [] +print("检索结果:") +for i, hit in enumerate(search_results): + print(f" Top {i+1}: ID={hit['id']}, 距离={hit['distance']:.4f}, 路径='{hit['entity']['image_path']}'") + retrieved_images.append(hit['entity']['image_path']) + +# 8. 可视化与清理 +print(f"\n--> 正在可视化结果并清理资源") +if not retrieved_images: + print("没有检索到任何图像。") +else: + panoramic_image = visualize_results(query_image_path, retrieved_images) + combined_image_path = os.path.join(DATA_DIR, "search_result.png") + cv2.imwrite(combined_image_path, panoramic_image) + print(f"结果图像已保存到: {combined_image_path}") + Image.open(combined_image_path).show() + +milvus_client.release_collection(collection_name=COLLECTION_NAME) +print(f"已从内存中释放 Collection: '{COLLECTION_NAME}'") +milvus_client.drop_collection(COLLECTION_NAME) +print(f"已删除 Collection: '{COLLECTION_NAME}'") diff --git a/code/C3/05_sentence_window_retrieval.py b/code/C3/05_sentence_window_retrieval.py new file mode 100644 index 0000000..e7121da --- /dev/null +++ b/code/C3/05_sentence_window_retrieval.py @@ -0,0 +1,51 @@ +import os +from llama_index.core.node_parser import SentenceWindowNodeParser, SentenceSplitter +from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings +from llama_index.llms.deepseek import DeepSeek +from llama_index.embeddings.huggingface import HuggingFaceEmbedding +from llama_index.core.postprocessor import MetadataReplacementPostProcessor + +# 1. 配置模型 +Settings.llm = DeepSeek(model="deepseek-chat", temperature=0.1, api_key=os.getenv("DEEPSEEK_API_KEY")) +Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en") + +# 2. 加载文档 +documents = SimpleDirectoryReader( + input_files=["../../data/C3/pdf/IPCC_AR6_WGII_Chapter03.pdf"] +).load_data() + +# 3. 创建节点与构建索引 +# 3.1 句子窗口索引 +node_parser = SentenceWindowNodeParser.from_defaults( + window_size=3, + window_metadata_key="window", + original_text_metadata_key="original_text", +) +sentence_nodes = node_parser.get_nodes_from_documents(documents) +sentence_index = VectorStoreIndex(sentence_nodes) + +# 3.2 常规分块索引 (基准) +base_parser = SentenceSplitter(chunk_size=512) +base_nodes = base_parser.get_nodes_from_documents(documents) +base_index = VectorStoreIndex(base_nodes) + +# 4. 构建查询引擎 +sentence_query_engine = sentence_index.as_query_engine( + similarity_top_k=2, + node_postprocessors=[ + MetadataReplacementPostProcessor(target_metadata_key="window") + ], +) +base_query_engine = base_index.as_query_engine(similarity_top_k=2) + +# 5. 执行查询并对比结果 +query = "What are the concerns surrounding the AMOC?" +print(f"查询: {query}\n") + +print("--- 句子窗口检索结果 ---") +window_response = sentence_query_engine.query(query) +print(f"回答: {window_response}\n") + +print("--- 常规检索结果 ---") +base_response = base_query_engine.query(query) +print(f"回答: {base_response}\n") diff --git a/code/C3/06_recursive_retrieval.py b/code/C3/06_recursive_retrieval.py new file mode 100644 index 0000000..97f1a26 --- /dev/null +++ b/code/C3/06_recursive_retrieval.py @@ -0,0 +1,63 @@ +import os +import pandas as pd +from dotenv import load_dotenv +from llama_index.core import VectorStoreIndex +from llama_index.core.schema import IndexNode +from llama_index.experimental.query_engine import PandasQueryEngine +from llama_index.core.retrievers import RecursiveRetriever +from llama_index.core.query_engine import RetrieverQueryEngine +from llama_index.llms.deepseek import DeepSeek +from llama_index.embeddings.huggingface import HuggingFaceEmbedding +from llama_index.core import Settings + +load_dotenv() + +# 配置模型 +Settings.llm = DeepSeek(model="deepseek-chat", api_key=os.getenv("DEEPSEEK_API_KEY")) +Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-zh-v1.5") + +# 1.加载数据并为每个工作表创建查询引擎和摘要节点 +excel_file = '../../data/C3/excel/movie.xlsx' +xls = pd.ExcelFile(excel_file) + +df_query_engines = {} +all_nodes = [] + +for sheet_name in xls.sheet_names: + df = pd.read_excel(xls, sheet_name=sheet_name) + + # 为当前工作表(DataFrame)创建一个 PandasQueryEngine + query_engine = PandasQueryEngine(df=df, llm=Settings.llm, verbose=True) + + # 为当前工作表创建一个摘要节点(IndexNode) + year = sheet_name.replace('年份_', '') + summary = f"这个表格包含了年份为 {year} 的电影信息,可以用来回答关于这一年电影的具体问题。" + node = IndexNode(text=summary, index_id=sheet_name) + all_nodes.append(node) + + # 存储工作表名称到其查询引擎的映射 + df_query_engines[sheet_name] = query_engine + +# 2. 创建顶层索引(只包含摘要节点) +vector_index = VectorStoreIndex(all_nodes) + +# 3. 创建递归检索器 +# 3.1 创建顶层检索器,用于在摘要节点中检索 +vector_retriever = vector_index.as_retriever(similarity_top_k=1) + +# 3.2 创建递归检索器 +recursive_retriever = RecursiveRetriever( + "vector", + retriever_dict={"vector": vector_retriever}, + query_engine_dict=df_query_engines, + verbose=True, +) + +# 4. 创建查询引擎 +query_engine = RetrieverQueryEngine.from_args(recursive_retriever) + +# 5. 执行查询 +query = "1994年评分人数最少的电影是哪一部?" +print(f"查询: {query}") +response = query_engine.query(query) +print(f"回答: {response}") diff --git a/code/C3/07_recursive_retrieval_v2.py b/code/C3/07_recursive_retrieval_v2.py new file mode 100644 index 0000000..a874d67 --- /dev/null +++ b/code/C3/07_recursive_retrieval_v2.py @@ -0,0 +1,101 @@ +import os +import pandas as pd +from dotenv import load_dotenv +from llama_index.core import VectorStoreIndex, Document, Settings +from llama_index.core.retrievers import VectorIndexRetriever +from llama_index.core.query_engine import RetrieverQueryEngine +from llama_index.core.vector_stores import MetadataFilters, ExactMatchFilter +from llama_index.llms.deepseek import DeepSeek +from llama_index.embeddings.huggingface import HuggingFaceEmbedding + +load_dotenv() + +# 配置模型 +Settings.llm = DeepSeek(model="deepseek-chat", api_key=os.getenv("DEEPSEEK_API_KEY")) +Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-zh-v1.5") + +# 1. 加载和预处理数据 +excel_file = '../../data/C3/excel/movie.xlsx' +xls = pd.ExcelFile(excel_file) + +summary_docs = [] +content_docs = [] + +print("开始加载和处理Excel文件...") +for sheet_name in xls.sheet_names: + df = pd.read_excel(xls, sheet_name=sheet_name) + + # 数据清洗 + if '评分人数' in df.columns: + df['评分人数'] = df['评分人数'].astype(str).str.replace('人评价', '').str.strip() + df['评分人数'] = pd.to_numeric(df['评分人数'], errors='coerce').fillna(0).astype(int) + + # 创建摘要文档 (用于路由) + year = sheet_name.replace('年份_', '') + summary_text = f"这个表格包含了年份为 {year} 的电影信息,包括电影名称、导演、评分、评分人数等。" + summary_doc = Document( + text=summary_text, + metadata={"sheet_name": sheet_name} + ) + summary_docs.append(summary_doc) + + # 创建内容文档 (用于最终问答) + content_text = df.to_string(index=False) + content_doc = Document( + text=content_text, + metadata={"sheet_name": sheet_name} + ) + content_docs.append(content_doc) + +print("数据加载和处理完成。\n") + +# 2. 构建向量索引 +# 使用默认的内存SimpleVectorStore,它支持元数据过滤 + +# 2.1 为摘要创建索引 +summary_index = VectorStoreIndex(summary_docs) + +# 2.2 为内容创建索引 +content_index = VectorStoreIndex(content_docs) + +print("摘要索引和内容索引构建完成。\n") + +# 3. 定义两步式查询逻辑 +def query_safe_recursive(query_str): + print(f"--- 开始执行查询 ---") + print(f"查询: {query_str}") + + # 第一步:路由 - 在摘要索引中找到最相关的表格 + print("\n第一步:在摘要索引中进行路由...") + summary_retriever = VectorIndexRetriever(index=summary_index, similarity_top_k=1) + retrieved_nodes = summary_retriever.retrieve(query_str) + + if not retrieved_nodes: + return "抱歉,未能找到相关的电影年份信息。" + + # 获取匹配到的工作表名称 + matched_sheet_name = retrieved_nodes[0].node.metadata['sheet_name'] + print(f"路由结果:匹配到工作表 -> {matched_sheet_name}") + + # 第二步:检索 - 在内容索引中根据工作表名称过滤并检索具体内容 + print("\n第二步:在内容索引中检索具体信息...") + content_retriever = VectorIndexRetriever( + index=content_index, + similarity_top_k=1, # 通常只返回最匹配的整个表格即可 + filters=MetadataFilters( + filters=[ExactMatchFilter(key="sheet_name", value=matched_sheet_name)] + ) + ) + + # 创建查询引擎并执行查询 + query_engine = RetrieverQueryEngine.from_args(content_retriever) + response = query_engine.query(query_str) + + print("--- 查询执行结束 ---\n") + return response + +# 4. 执行查询 +query = "1994年评分人数最少的电影是哪一部?" +response = query_safe_recursive(query) + +print(f"最终回答: {response}") diff --git a/code/C3/download_model.py b/code/C3/download_model.py new file mode 100644 index 0000000..b703701 --- /dev/null +++ b/code/C3/download_model.py @@ -0,0 +1,68 @@ +import requests +from pathlib import Path + +def download_visualized_bge_model(): + """ + 下载 Visual BGE 模型权重文件 + 如果模型文件不存在,则从 Hugging Face 下载 + """ + # 定义模型路径和下载URL + model_dir = Path("../../models/bge") + model_file = model_dir / "Visualized_base_en_v1.5.pth" + download_url = "https://huggingface.co/BAAI/bge-visualized/resolve/main/Visualized_base_en_v1.5.pth?download=true" + + # 检查模型文件是否已存在 + if model_file.exists(): + print(f"模型文件已存在: {model_file}") + print(f"文件大小: {model_file.stat().st_size / (1024*1024):.1f} MB") + return str(model_file) + + # 创建目录 + model_dir.mkdir(parents=True, exist_ok=True) + print(f"创建模型目录: {model_dir}") + + # 下载模型 + print(f"开始下载模型...") + print(f"下载地址: {download_url}") + + try: + response = requests.get(download_url, stream=True) + response.raise_for_status() + + # 获取文件大小 + total_size = int(response.headers.get('content-length', 0)) + downloaded_size = 0 + + with open(model_file, 'wb') as f: + for chunk in response.iter_content(chunk_size=8192): + if chunk: + f.write(chunk) + downloaded_size += len(chunk) + + # 显示下载进度 + if total_size > 0: + progress = (downloaded_size / total_size) * 100 + print(f"\r下载进度: {progress:.1f}% ({downloaded_size/(1024*1024):.1f}/{total_size/(1024*1024):.1f} MB)", end='') + + print(f"\n模型下载完成: {model_file}") + print(f"文件大小: {model_file.stat().st_size / (1024*1024):.1f} MB") + return str(model_file) + + except requests.exceptions.RequestException as e: + print(f"下载失败: {e}") + # 如果下载失败,删除不完整的文件 + if model_file.exists(): + model_file.unlink() + return None + except Exception as e: + print(f"发生错误: {e}") + if model_file.exists(): + model_file.unlink() + return None + +if __name__ == "__main__": + model_path = download_visualized_bge_model() + if model_path: + print(f"✅ 模型准备就绪: {model_path}") + else: + print("❌ 模型下载失败") diff --git a/code/C3/visual_bge/__init__.py b/code/C3/visual_bge/__init__.py new file mode 100644 index 0000000..13dc4fd --- /dev/null +++ b/code/C3/visual_bge/__init__.py @@ -0,0 +1 @@ +from .visual_bge.modeling import Visualized_BGE \ No newline at end of file diff --git a/code/C3/visual_bge/imgs/SFT-CIRR.png b/code/C3/visual_bge/imgs/SFT-CIRR.png new file mode 100644 index 0000000..3dc313a Binary files /dev/null and b/code/C3/visual_bge/imgs/SFT-CIRR.png differ diff --git a/code/C3/visual_bge/imgs/SFT-ReMuQ.png b/code/C3/visual_bge/imgs/SFT-ReMuQ.png new file mode 100644 index 0000000..317ce28 Binary files /dev/null and b/code/C3/visual_bge/imgs/SFT-ReMuQ.png differ diff --git a/code/C3/visual_bge/imgs/SFT-WebQA.png b/code/C3/visual_bge/imgs/SFT-WebQA.png new file mode 100644 index 0000000..a69d594 Binary files /dev/null and b/code/C3/visual_bge/imgs/SFT-WebQA.png differ diff --git a/code/C3/visual_bge/imgs/cir_candi_1.png b/code/C3/visual_bge/imgs/cir_candi_1.png new file mode 100644 index 0000000..d44fabf Binary files /dev/null and b/code/C3/visual_bge/imgs/cir_candi_1.png differ diff --git a/code/C3/visual_bge/imgs/cir_candi_2.png b/code/C3/visual_bge/imgs/cir_candi_2.png new file mode 100644 index 0000000..143a39d Binary files /dev/null and b/code/C3/visual_bge/imgs/cir_candi_2.png differ diff --git a/code/C3/visual_bge/imgs/cir_query.png b/code/C3/visual_bge/imgs/cir_query.png new file mode 100644 index 0000000..4a28de6 Binary files /dev/null and b/code/C3/visual_bge/imgs/cir_query.png differ diff --git a/code/C3/visual_bge/imgs/wiki_candi_1.jpg b/code/C3/visual_bge/imgs/wiki_candi_1.jpg new file mode 100644 index 0000000..6ae321f Binary files /dev/null and b/code/C3/visual_bge/imgs/wiki_candi_1.jpg differ diff --git a/code/C3/visual_bge/imgs/wiki_candi_2.jpg b/code/C3/visual_bge/imgs/wiki_candi_2.jpg new file mode 100644 index 0000000..1cf5b1d Binary files /dev/null and b/code/C3/visual_bge/imgs/wiki_candi_2.jpg differ diff --git a/code/C3/visual_bge/imgs/zs-benchmark.png b/code/C3/visual_bge/imgs/zs-benchmark.png new file mode 100644 index 0000000..b25d858 Binary files /dev/null and b/code/C3/visual_bge/imgs/zs-benchmark.png differ diff --git a/code/C3/visual_bge/imgs/zs-performance.png b/code/C3/visual_bge/imgs/zs-performance.png new file mode 100644 index 0000000..1874dcc Binary files /dev/null and b/code/C3/visual_bge/imgs/zs-performance.png differ diff --git a/code/C3/visual_bge/setup.py b/code/C3/visual_bge/setup.py new file mode 100644 index 0000000..40a80f5 --- /dev/null +++ b/code/C3/visual_bge/setup.py @@ -0,0 +1,18 @@ +from setuptools import setup, find_packages + +setup( + name="visual_bge", + version="0.1.0", + description='visual_bge', + long_description="./README.md", + long_description_content_type="text/markdown", + url='https://github.com/FlagOpen/FlagEmbedding/tree/master/research/visual_bge', + packages=find_packages(), + install_requires=[ + 'torchvision', + 'timm', + 'einops', + 'ftfy' + ], + python_requires='>=3.6', +) diff --git a/code/C3/visual_bge/visual_bge/eva_clip/__init__.py b/code/C3/visual_bge/visual_bge/eva_clip/__init__.py new file mode 100644 index 0000000..43e75c0 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/__init__.py @@ -0,0 +1,11 @@ +from .constants import OPENAI_DATASET_MEAN, OPENAI_DATASET_STD +from .factory import create_model, create_model_and_transforms, create_model_from_pretrained, get_tokenizer, create_eva_vision_and_transforms +from .factory import list_models, add_model_config, get_model_config, load_checkpoint +from .loss import ClipLoss +from .model import CLIP, CustomCLIP, CLIPTextCfg, CLIPVisionCfg,\ + convert_weights_to_lp, convert_weights_to_fp16, trace_model, get_cast_dtype +from .openai import load_openai_model, list_openai_models +from .pretrained import list_pretrained, list_pretrained_models_by_tag, list_pretrained_tags_by_model,\ + get_pretrained_url, download_pretrained_from_url, is_pretrained_cfg, get_pretrained_cfg, download_pretrained +from .tokenizer import SimpleTokenizer, tokenize +from .transform import image_transform \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/bpe_simple_vocab_16e6.txt.gz b/code/C3/visual_bge/visual_bge/eva_clip/bpe_simple_vocab_16e6.txt.gz new file mode 100644 index 0000000..7b5088a Binary files /dev/null and b/code/C3/visual_bge/visual_bge/eva_clip/bpe_simple_vocab_16e6.txt.gz differ diff --git a/code/C3/visual_bge/visual_bge/eva_clip/constants.py b/code/C3/visual_bge/visual_bge/eva_clip/constants.py new file mode 100644 index 0000000..a670bb3 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/constants.py @@ -0,0 +1,2 @@ +OPENAI_DATASET_MEAN = (0.48145466, 0.4578275, 0.40821073) +OPENAI_DATASET_STD = (0.26862954, 0.26130258, 0.27577711) diff --git a/code/C3/visual_bge/visual_bge/eva_clip/eva_vit_model.py b/code/C3/visual_bge/visual_bge/eva_clip/eva_vit_model.py new file mode 100644 index 0000000..f556dcc --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/eva_vit_model.py @@ -0,0 +1,532 @@ +# -------------------------------------------------------- +# Adapted from https://github.com/microsoft/unilm/tree/master/beit +# -------------------------------------------------------- +import math +import os +from functools import partial +import torch +import torch.nn as nn +import torch.nn.functional as F +try: + from timm.models.layers import drop_path, to_2tuple, trunc_normal_ +except: + from timm.layers import drop_path, to_2tuple, trunc_normal_ + +from .transformer import PatchDropout +from .rope import VisionRotaryEmbedding, VisionRotaryEmbeddingFast + +if os.getenv('ENV_TYPE') == 'deepspeed': + try: + from deepspeed.runtime.activation_checkpointing.checkpointing import checkpoint + except: + from torch.utils.checkpoint import checkpoint +else: + from torch.utils.checkpoint import checkpoint + +try: + import xformers.ops as xops +except ImportError: + xops = None + # print("Please 'pip install xformers'") + + +class DropPath(nn.Module): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + """ + def __init__(self, drop_prob=None): + super(DropPath, self).__init__() + self.drop_prob = drop_prob + + def forward(self, x): + return drop_path(x, self.drop_prob, self.training) + + def extra_repr(self) -> str: + return 'p={}'.format(self.drop_prob) + + +class Mlp(nn.Module): + def __init__( + self, + in_features, + hidden_features=None, + out_features=None, + act_layer=nn.GELU, + norm_layer=nn.LayerNorm, + drop=0., + subln=False, + + ): + super().__init__() + out_features = out_features or in_features + hidden_features = hidden_features or in_features + self.fc1 = nn.Linear(in_features, hidden_features) + self.act = act_layer() + + self.ffn_ln = norm_layer(hidden_features) if subln else nn.Identity() + + self.fc2 = nn.Linear(hidden_features, out_features) + self.drop = nn.Dropout(drop) + + def forward(self, x): + x = self.fc1(x) + x = self.act(x) + # x = self.drop(x) + # commit this for the orignal BERT implement + x = self.ffn_ln(x) + + x = self.fc2(x) + x = self.drop(x) + return x + +class SwiGLU(nn.Module): + def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.SiLU, drop=0., + norm_layer=nn.LayerNorm, subln=False): + super().__init__() + out_features = out_features or in_features + hidden_features = hidden_features or in_features + + self.w1 = nn.Linear(in_features, hidden_features) + self.w2 = nn.Linear(in_features, hidden_features) + + self.act = act_layer() + self.ffn_ln = norm_layer(hidden_features) if subln else nn.Identity() + self.w3 = nn.Linear(hidden_features, out_features) + + self.drop = nn.Dropout(drop) + + def forward(self, x): + x1 = self.w1(x) + x2 = self.w2(x) + hidden = self.act(x1) * x2 + x = self.ffn_ln(hidden) + x = self.w3(x) + x = self.drop(x) + return x + +class Attention(nn.Module): + def __init__( + self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., + proj_drop=0., window_size=None, attn_head_dim=None, xattn=False, rope=None, subln=False, norm_layer=nn.LayerNorm): + super().__init__() + self.num_heads = num_heads + head_dim = dim // num_heads + if attn_head_dim is not None: + head_dim = attn_head_dim + all_head_dim = head_dim * self.num_heads + self.scale = qk_scale or head_dim ** -0.5 + + self.subln = subln + if self.subln: + self.q_proj = nn.Linear(dim, all_head_dim, bias=False) + self.k_proj = nn.Linear(dim, all_head_dim, bias=False) + self.v_proj = nn.Linear(dim, all_head_dim, bias=False) + else: + self.qkv = nn.Linear(dim, all_head_dim * 3, bias=False) + + if qkv_bias: + self.q_bias = nn.Parameter(torch.zeros(all_head_dim)) + self.v_bias = nn.Parameter(torch.zeros(all_head_dim)) + else: + self.q_bias = None + self.v_bias = None + + if window_size: + self.window_size = window_size + self.num_relative_distance = (2 * window_size[0] - 1) * (2 * window_size[1] - 1) + 3 + self.relative_position_bias_table = nn.Parameter( + torch.zeros(self.num_relative_distance, num_heads)) # 2*Wh-1 * 2*Ww-1, nH + # cls to token & token 2 cls & cls to cls + + # get pair-wise relative position index for each token inside the window + coords_h = torch.arange(window_size[0]) + coords_w = torch.arange(window_size[1]) + coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww + coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww + relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww + relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2 + relative_coords[:, :, 0] += window_size[0] - 1 # shift to start from 0 + relative_coords[:, :, 1] += window_size[1] - 1 + relative_coords[:, :, 0] *= 2 * window_size[1] - 1 + relative_position_index = \ + torch.zeros(size=(window_size[0] * window_size[1] + 1, ) * 2, dtype=relative_coords.dtype) + relative_position_index[1:, 1:] = relative_coords.sum(-1) # Wh*Ww, Wh*Ww + relative_position_index[0, 0:] = self.num_relative_distance - 3 + relative_position_index[0:, 0] = self.num_relative_distance - 2 + relative_position_index[0, 0] = self.num_relative_distance - 1 + + self.register_buffer("relative_position_index", relative_position_index) + else: + self.window_size = None + self.relative_position_bias_table = None + self.relative_position_index = None + + self.attn_drop = nn.Dropout(attn_drop) + self.inner_attn_ln = norm_layer(all_head_dim) if subln else nn.Identity() + # self.proj = nn.Linear(all_head_dim, all_head_dim) + self.proj = nn.Linear(all_head_dim, dim) + self.proj_drop = nn.Dropout(proj_drop) + self.xattn = xattn + self.xattn_drop = attn_drop + + self.rope = rope + + def forward(self, x, rel_pos_bias=None, attn_mask=None): + B, N, C = x.shape + if self.subln: + q = F.linear(input=x, weight=self.q_proj.weight, bias=self.q_bias) + k = F.linear(input=x, weight=self.k_proj.weight, bias=None) + v = F.linear(input=x, weight=self.v_proj.weight, bias=self.v_bias) + + q = q.reshape(B, N, self.num_heads, -1).permute(0, 2, 1, 3) # B, num_heads, N, C + k = k.reshape(B, N, self.num_heads, -1).permute(0, 2, 1, 3) + v = v.reshape(B, N, self.num_heads, -1).permute(0, 2, 1, 3) + else: + + qkv_bias = None + if self.q_bias is not None: + qkv_bias = torch.cat((self.q_bias, torch.zeros_like(self.v_bias, requires_grad=False), self.v_bias)) + + qkv = F.linear(input=x, weight=self.qkv.weight, bias=qkv_bias) + qkv = qkv.reshape(B, N, 3, self.num_heads, -1).permute(2, 0, 3, 1, 4) # 3, B, num_heads, N, C + q, k, v = qkv[0], qkv[1], qkv[2] + + if self.rope: + # slightly fast impl + q_t = q[:, :, 1:, :] + ro_q_t = self.rope(q_t) + q = torch.cat((q[:, :, :1, :], ro_q_t), -2).type_as(v) + + k_t = k[:, :, 1:, :] + ro_k_t = self.rope(k_t) + k = torch.cat((k[:, :, :1, :], ro_k_t), -2).type_as(v) + + if xops is not None: + q = q.permute(0, 2, 1, 3) # B, num_heads, N, C -> B, N, num_heads, C + k = k.permute(0, 2, 1, 3) + v = v.permute(0, 2, 1, 3) + + x = xops.memory_efficient_attention( + q, k, v, + p=self.xattn_drop, + scale=self.scale, + ) + x = x.reshape(B, N, -1) + x = self.inner_attn_ln(x) + x = self.proj(x) + x = self.proj_drop(x) + else: + q = q * self.scale + attn = (q @ k.transpose(-2, -1)) + + if self.relative_position_bias_table is not None: + relative_position_bias = \ + self.relative_position_bias_table[self.relative_position_index.view(-1)].view( + self.window_size[0] * self.window_size[1] + 1, + self.window_size[0] * self.window_size[1] + 1, -1) # Wh*Ww,Wh*Ww,nH + relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww + attn = attn + relative_position_bias.unsqueeze(0).type_as(attn) + + if rel_pos_bias is not None: + attn = attn + rel_pos_bias.type_as(attn) + + if attn_mask is not None: + attn_mask = attn_mask.bool() + attn = attn.masked_fill(~attn_mask[:, None, None, :], float("-inf")) + + attn = attn.softmax(dim=-1) + attn = self.attn_drop(attn) + + x = (attn @ v).transpose(1, 2).reshape(B, N, -1) + x = self.inner_attn_ln(x) + x = self.proj(x) + x = self.proj_drop(x) + return x + + +class Block(nn.Module): + + def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0., + drop_path=0., init_values=None, act_layer=nn.GELU, norm_layer=nn.LayerNorm, + window_size=None, attn_head_dim=None, xattn=False, rope=None, postnorm=False, + subln=False, naiveswiglu=False): + super().__init__() + self.norm1 = norm_layer(dim) + self.attn = Attention( + dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, + attn_drop=attn_drop, proj_drop=drop, window_size=window_size, attn_head_dim=attn_head_dim, + xattn=xattn, rope=rope, subln=subln, norm_layer=norm_layer) + # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here + self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity() + self.norm2 = norm_layer(dim) + mlp_hidden_dim = int(dim * mlp_ratio) + + if naiveswiglu: + self.mlp = SwiGLU( + in_features=dim, + hidden_features=mlp_hidden_dim, + subln=subln, + norm_layer=norm_layer, + ) + else: + self.mlp = Mlp( + in_features=dim, + hidden_features=mlp_hidden_dim, + act_layer=act_layer, + subln=subln, + drop=drop + ) + + if init_values is not None and init_values > 0: + self.gamma_1 = nn.Parameter(init_values * torch.ones((dim)),requires_grad=True) + self.gamma_2 = nn.Parameter(init_values * torch.ones((dim)),requires_grad=True) + else: + self.gamma_1, self.gamma_2 = None, None + + self.postnorm = postnorm + + def forward(self, x, rel_pos_bias=None, attn_mask=None): + if self.gamma_1 is None: + if self.postnorm: + x = x + self.drop_path(self.norm1(self.attn(x, rel_pos_bias=rel_pos_bias, attn_mask=attn_mask))) + x = x + self.drop_path(self.norm2(self.mlp(x))) + else: + x = x + self.drop_path(self.attn(self.norm1(x), rel_pos_bias=rel_pos_bias, attn_mask=attn_mask)) + x = x + self.drop_path(self.mlp(self.norm2(x))) + else: + if self.postnorm: + x = x + self.drop_path(self.gamma_1 * self.norm1(self.attn(x, rel_pos_bias=rel_pos_bias, attn_mask=attn_mask))) + x = x + self.drop_path(self.gamma_2 * self.norm2(self.mlp(x))) + else: + x = x + self.drop_path(self.gamma_1 * self.attn(self.norm1(x), rel_pos_bias=rel_pos_bias, attn_mask=attn_mask)) + x = x + self.drop_path(self.gamma_2 * self.mlp(self.norm2(x))) + return x + + +class PatchEmbed(nn.Module): + """ Image to Patch Embedding + """ + def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768): + super().__init__() + img_size = to_2tuple(img_size) + patch_size = to_2tuple(patch_size) + num_patches = (img_size[1] // patch_size[1]) * (img_size[0] // patch_size[0]) + self.patch_shape = (img_size[0] // patch_size[0], img_size[1] // patch_size[1]) + self.img_size = img_size + self.patch_size = patch_size + self.num_patches = num_patches + + self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size) + + def forward(self, x, **kwargs): + B, C, H, W = x.shape + # FIXME look at relaxing size constraints + assert H == self.img_size[0] and W == self.img_size[1], \ + f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})." + x = self.proj(x).flatten(2).transpose(1, 2) # [10, 3, 224, 224] -> [10, 196, 768] + return x + + +class RelativePositionBias(nn.Module): + + def __init__(self, window_size, num_heads): + super().__init__() + self.window_size = window_size + self.num_relative_distance = (2 * window_size[0] - 1) * (2 * window_size[1] - 1) + 3 + self.relative_position_bias_table = nn.Parameter( + torch.zeros(self.num_relative_distance, num_heads)) # 2*Wh-1 * 2*Ww-1, nH + # cls to token & token 2 cls & cls to cls + + # get pair-wise relative position index for each token inside the window + coords_h = torch.arange(window_size[0]) + coords_w = torch.arange(window_size[1]) + coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww + coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww + relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww + relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2 + relative_coords[:, :, 0] += window_size[0] - 1 # shift to start from 0 + relative_coords[:, :, 1] += window_size[1] - 1 + relative_coords[:, :, 0] *= 2 * window_size[1] - 1 + relative_position_index = \ + torch.zeros(size=(window_size[0] * window_size[1] + 1,) * 2, dtype=relative_coords.dtype) + relative_position_index[1:, 1:] = relative_coords.sum(-1) # Wh*Ww, Wh*Ww + relative_position_index[0, 0:] = self.num_relative_distance - 3 + relative_position_index[0:, 0] = self.num_relative_distance - 2 + relative_position_index[0, 0] = self.num_relative_distance - 1 + + self.register_buffer("relative_position_index", relative_position_index) + + def forward(self): + relative_position_bias = \ + self.relative_position_bias_table[self.relative_position_index.view(-1)].view( + self.window_size[0] * self.window_size[1] + 1, + self.window_size[0] * self.window_size[1] + 1, -1) # Wh*Ww,Wh*Ww,nH + return relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww + + +class EVAVisionTransformer(nn.Module): + """ Vision Transformer with support for patch or hybrid CNN input stage + """ + def __init__(self, img_size=224, patch_size=16, in_chans=3, num_classes=1000, embed_dim=768, depth=12, + num_heads=12, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop_rate=0., attn_drop_rate=0., + drop_path_rate=0., norm_layer=nn.LayerNorm, init_values=None, patch_dropout=0., + use_abs_pos_emb=True, use_rel_pos_bias=False, use_shared_rel_pos_bias=False, rope=False, + use_mean_pooling=True, init_scale=0.001, grad_checkpointing=False, xattn=False, postnorm=False, + pt_hw_seq_len=16, intp_freq=False, naiveswiglu=False, subln=False): + super().__init__() + self.image_size = img_size + self.num_classes = num_classes + self.num_features = self.embed_dim = embed_dim # num_features for consistency with other models + + self.patch_embed = PatchEmbed( + img_size=img_size, patch_size=patch_size, in_chans=in_chans, embed_dim=embed_dim) + num_patches = self.patch_embed.num_patches + + self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim)) + # self.mask_token = nn.Parameter(torch.zeros(1, 1, embed_dim)) + if use_abs_pos_emb: + self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, embed_dim)) + else: + self.pos_embed = None + self.pos_drop = nn.Dropout(p=drop_rate) + + if use_shared_rel_pos_bias: + self.rel_pos_bias = RelativePositionBias(window_size=self.patch_embed.patch_shape, num_heads=num_heads) + else: + self.rel_pos_bias = None + + if rope: + half_head_dim = embed_dim // num_heads // 2 + hw_seq_len = img_size // patch_size + self.rope = VisionRotaryEmbeddingFast( + dim=half_head_dim, + pt_seq_len=pt_hw_seq_len, + ft_seq_len=hw_seq_len if intp_freq else None, + # patch_dropout=patch_dropout + ) + else: + self.rope = None + + self.naiveswiglu = naiveswiglu + + dpr = [x.item() for x in torch.linspace(0, drop_path_rate, depth)] # stochastic depth decay rule + self.use_rel_pos_bias = use_rel_pos_bias + self.blocks = nn.ModuleList([ + Block( + dim=embed_dim, num_heads=num_heads, mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale, + drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i], norm_layer=norm_layer, + init_values=init_values, window_size=self.patch_embed.patch_shape if use_rel_pos_bias else None, + xattn=xattn, rope=self.rope, postnorm=postnorm, subln=subln, naiveswiglu=naiveswiglu) + for i in range(depth)]) + self.norm = nn.Identity() if use_mean_pooling else norm_layer(embed_dim) + self.fc_norm = norm_layer(embed_dim) if use_mean_pooling else None + self.head = nn.Linear(embed_dim, num_classes) if num_classes > 0 else nn.Identity() + + if self.pos_embed is not None: + trunc_normal_(self.pos_embed, std=.02) + + trunc_normal_(self.cls_token, std=.02) + # trunc_normal_(self.mask_token, std=.02) + + self.apply(self._init_weights) + self.fix_init_weight() + + if isinstance(self.head, nn.Linear): + trunc_normal_(self.head.weight, std=.02) + self.head.weight.data.mul_(init_scale) + self.head.bias.data.mul_(init_scale) + + # setting a patch_dropout of 0. would mean it is disabled and this function would be the identity fn + self.patch_dropout = PatchDropout(patch_dropout) if patch_dropout > 0. else nn.Identity() + + self.grad_checkpointing = grad_checkpointing + + def fix_init_weight(self): + def rescale(param, layer_id): + param.div_(math.sqrt(2.0 * layer_id)) + + for layer_id, layer in enumerate(self.blocks): + rescale(layer.attn.proj.weight.data, layer_id + 1) + if self.naiveswiglu: + rescale(layer.mlp.w3.weight.data, layer_id + 1) + else: + rescale(layer.mlp.fc2.weight.data, layer_id + 1) + + def get_cast_dtype(self) -> torch.dtype: + return self.blocks[0].mlp.fc2.weight.dtype + + def _init_weights(self, m): + if isinstance(m, nn.Linear): + trunc_normal_(m.weight, std=.02) + if m.bias is not None: + nn.init.constant_(m.bias, 0) + elif isinstance(m, nn.LayerNorm): + nn.init.constant_(m.bias, 0) + nn.init.constant_(m.weight, 1.0) + + def get_num_layers(self): + return len(self.blocks) + + def lock(self, unlocked_groups=0, freeze_bn_stats=False): + assert unlocked_groups == 0, 'partial locking not currently supported for this model' + for param in self.parameters(): + param.requires_grad = False + + @torch.jit.ignore + def set_grad_checkpointing(self, enable=True): + self.grad_checkpointing = enable + + @torch.jit.ignore + def no_weight_decay(self): + return {'pos_embed', 'cls_token'} + + def get_classifier(self): + return self.head + + def reset_classifier(self, num_classes, global_pool=''): + self.num_classes = num_classes + self.head = nn.Linear(self.embed_dim, num_classes) if num_classes > 0 else nn.Identity() + + def forward_features(self, x, return_all_features=False): + + x = self.patch_embed(x) + batch_size, seq_len, _ = x.size() + + cls_tokens = self.cls_token.expand(batch_size, -1, -1) # stole cls_tokens impl from Phil Wang, thanks + x = torch.cat((cls_tokens, x), dim=1) + if self.pos_embed is not None: + x = x + self.pos_embed + x = self.pos_drop(x) + + # a patch_dropout of 0. would mean it is disabled and this function would do nothing but return what was passed in + if os.getenv('RoPE') == '1': + if self.training and not isinstance(self.patch_dropout, nn.Identity): + x, patch_indices_keep = self.patch_dropout(x) + self.rope.forward = partial(self.rope.forward, patch_indices_keep=patch_indices_keep) + else: + self.rope.forward = partial(self.rope.forward, patch_indices_keep=None) + x = self.patch_dropout(x) + else: + x = self.patch_dropout(x) + + rel_pos_bias = self.rel_pos_bias() if self.rel_pos_bias is not None else None + for blk in self.blocks: + if self.grad_checkpointing: + # x = checkpoint(blk, x, (rel_pos_bias,)) + x = checkpoint(blk, x, rel_pos_bias) + else: + x = blk(x, rel_pos_bias=rel_pos_bias) + + if not return_all_features: + x = self.norm(x) + if self.fc_norm is not None: + return self.fc_norm(x.mean(1)) + else: + return x[:, 0] + return x + + def forward(self, x, return_all_features=True): + if return_all_features: + return self.forward_features(x, return_all_features) + x = self.forward_features(x) + x = self.head(x) + return x diff --git a/code/C3/visual_bge/visual_bge/eva_clip/factory.py b/code/C3/visual_bge/visual_bge/eva_clip/factory.py new file mode 100644 index 0000000..44b3f3b --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/factory.py @@ -0,0 +1,519 @@ +import json +import logging +import os +import pathlib +import re +from copy import deepcopy +from pathlib import Path +from typing import Optional, Tuple, Union, Dict, Any +import torch + +from .constants import OPENAI_DATASET_MEAN, OPENAI_DATASET_STD +from .model import CLIP, CustomCLIP, convert_weights_to_lp, convert_to_custom_text_state_dict,\ + get_cast_dtype +from .openai import load_openai_model +from .pretrained import is_pretrained_cfg, get_pretrained_cfg, download_pretrained, list_pretrained_tags_by_model +from .transform import image_transform +from .tokenizer import HFTokenizer, tokenize +from .utils import resize_clip_pos_embed, resize_evaclip_pos_embed, resize_visual_pos_embed, resize_eva_pos_embed + + +_MODEL_CONFIG_PATHS = [Path(__file__).parent / f"model_configs/"] +_MODEL_CONFIGS = {} # directory (model_name: config) of model architecture configs + + +def _natural_key(string_): + return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_.lower())] + + +def _rescan_model_configs(): + global _MODEL_CONFIGS + + config_ext = ('.json',) + config_files = [] + for config_path in _MODEL_CONFIG_PATHS: + if config_path.is_file() and config_path.suffix in config_ext: + config_files.append(config_path) + elif config_path.is_dir(): + for ext in config_ext: + config_files.extend(config_path.glob(f'*{ext}')) + + for cf in config_files: + with open(cf, "r", encoding="utf8") as f: + model_cfg = json.load(f) + if all(a in model_cfg for a in ('embed_dim', 'vision_cfg', 'text_cfg')): + _MODEL_CONFIGS[cf.stem] = model_cfg + + _MODEL_CONFIGS = dict(sorted(_MODEL_CONFIGS.items(), key=lambda x: _natural_key(x[0]))) + + +_rescan_model_configs() # initial populate of model config registry + + +def list_models(): + """ enumerate available model architectures based on config files """ + return list(_MODEL_CONFIGS.keys()) + + +def add_model_config(path): + """ add model config path or file and update registry """ + if not isinstance(path, Path): + path = Path(path) + _MODEL_CONFIG_PATHS.append(path) + _rescan_model_configs() + + +def get_model_config(model_name): + if model_name in _MODEL_CONFIGS: + return deepcopy(_MODEL_CONFIGS[model_name]) + else: + return None + + +def get_tokenizer(model_name): + config = get_model_config(model_name) + tokenizer = HFTokenizer(config['text_cfg']['hf_tokenizer_name']) if 'hf_tokenizer_name' in config['text_cfg'] else tokenize + return tokenizer + + +# loading openai CLIP weights when is_openai=True for training +def load_state_dict(checkpoint_path: str, map_location: str='cpu', model_key: str='model|module|state_dict', is_openai: bool=False, skip_list: list=[]): + if is_openai: + model = torch.jit.load(checkpoint_path, map_location="cpu").eval() + state_dict = model.state_dict() + for key in ["input_resolution", "context_length", "vocab_size"]: + state_dict.pop(key, None) + else: + checkpoint = torch.load(checkpoint_path, map_location=map_location) + for mk in model_key.split('|'): + if isinstance(checkpoint, dict) and mk in checkpoint: + state_dict = checkpoint[mk] + break + else: + state_dict = checkpoint + if next(iter(state_dict.items()))[0].startswith('module'): + state_dict = {k[7:]: v for k, v in state_dict.items()} + + for k in skip_list: + if k in list(state_dict.keys()): + logging.info(f"Removing key {k} from pretrained checkpoint") + del state_dict[k] + + if os.getenv('RoPE') == '1': + for k in list(state_dict.keys()): + if 'freqs_cos' in k or 'freqs_sin' in k: + del state_dict[k] + return state_dict + + + +def load_checkpoint(model, checkpoint_path, model_key="model|module|state_dict", strict=True): + state_dict = load_state_dict(checkpoint_path, model_key=model_key, is_openai=False) + # detect old format and make compatible with new format + if 'positional_embedding' in state_dict and not hasattr(model, 'positional_embedding'): + state_dict = convert_to_custom_text_state_dict(state_dict) + if 'text.logit_scale' in state_dict and hasattr(model, 'logit_scale'): + state_dict['logit_scale'] = state_dict['text.logit_scale'] + del state_dict['text.logit_scale'] + + # resize_clip_pos_embed for CLIP and open CLIP + if 'visual.positional_embedding' in state_dict: + resize_clip_pos_embed(state_dict, model) + # specified to eva_vit_model + elif 'visual.pos_embed' in state_dict: + resize_evaclip_pos_embed(state_dict, model) + + # resize_clip_pos_embed(state_dict, model) + incompatible_keys = model.load_state_dict(state_dict, strict=strict) + logging.info(f"incompatible_keys.missing_keys: {incompatible_keys.missing_keys}") + return incompatible_keys + +def load_clip_visual_state_dict(checkpoint_path: str, map_location: str='cpu', is_openai: bool=False, skip_list:list=[]): + state_dict = load_state_dict(checkpoint_path, map_location=map_location, is_openai=is_openai, skip_list=skip_list) + + for k in list(state_dict.keys()): + if not k.startswith('visual.'): + del state_dict[k] + for k in list(state_dict.keys()): + if k.startswith('visual.'): + new_k = k[7:] + state_dict[new_k] = state_dict[k] + del state_dict[k] + return state_dict + +def load_clip_text_state_dict(checkpoint_path: str, map_location: str='cpu', is_openai: bool=False, skip_list:list=[]): + state_dict = load_state_dict(checkpoint_path, map_location=map_location, is_openai=is_openai, skip_list=skip_list) + + for k in list(state_dict.keys()): + if k.startswith('visual.'): + del state_dict[k] + return state_dict + +def get_pretrained_tag(pretrained_model): + pretrained_model = pretrained_model.lower() + if "laion" in pretrained_model or "open_clip" in pretrained_model: + return "open_clip" + elif "openai" in pretrained_model: + return "clip" + elif "eva" in pretrained_model and "clip" in pretrained_model: + return "eva_clip" + else: + return "other" + +def load_pretrained_checkpoint( + model, + visual_checkpoint_path, + text_checkpoint_path, + strict=True, + visual_model=None, + text_model=None, + model_key="model|module|state_dict", + skip_list=[]): + visual_tag = get_pretrained_tag(visual_model) + text_tag = get_pretrained_tag(text_model) + + logging.info(f"num of model state_dict keys: {len(model.state_dict().keys())}") + visual_incompatible_keys, text_incompatible_keys = None, None + if visual_checkpoint_path: + if visual_tag == "eva_clip" or visual_tag == "open_clip": + visual_state_dict = load_clip_visual_state_dict(visual_checkpoint_path, is_openai=False, skip_list=skip_list) + elif visual_tag == "clip": + visual_state_dict = load_clip_visual_state_dict(visual_checkpoint_path, is_openai=True, skip_list=skip_list) + else: + visual_state_dict = load_state_dict(visual_checkpoint_path, model_key=model_key, is_openai=False, skip_list=skip_list) + + # resize_clip_pos_embed for CLIP and open CLIP + if 'positional_embedding' in visual_state_dict: + resize_visual_pos_embed(visual_state_dict, model) + # specified to EVA model + elif 'pos_embed' in visual_state_dict: + resize_eva_pos_embed(visual_state_dict, model) + + visual_incompatible_keys = model.visual.load_state_dict(visual_state_dict, strict=strict) + logging.info(f"num of loaded visual_state_dict keys: {len(visual_state_dict.keys())}") + logging.info(f"visual_incompatible_keys.missing_keys: {visual_incompatible_keys.missing_keys}") + + if text_checkpoint_path: + if text_tag == "eva_clip" or text_tag == "open_clip": + text_state_dict = load_clip_text_state_dict(text_checkpoint_path, is_openai=False, skip_list=skip_list) + elif text_tag == "clip": + text_state_dict = load_clip_text_state_dict(text_checkpoint_path, is_openai=True, skip_list=skip_list) + else: + text_state_dict = load_state_dict(visual_checkpoint_path, model_key=model_key, is_openai=False, skip_list=skip_list) + + text_incompatible_keys = model.text.load_state_dict(text_state_dict, strict=strict) + + logging.info(f"num of loaded text_state_dict keys: {len(text_state_dict.keys())}") + logging.info(f"text_incompatible_keys.missing_keys: {text_incompatible_keys.missing_keys}") + + return visual_incompatible_keys, text_incompatible_keys + +def create_model( + model_name: str, + pretrained: Optional[str] = None, + precision: str = 'fp32', + device: Union[str, torch.device] = 'cpu', + jit: bool = False, + force_quick_gelu: bool = False, + force_custom_clip: bool = False, + force_patch_dropout: Optional[float] = None, + pretrained_image: str = '', + pretrained_text: str = '', + pretrained_hf: bool = True, + pretrained_visual_model: str = None, + pretrained_text_model: str = None, + cache_dir: Optional[str] = None, + skip_list: list = [], + is_only_visual: bool = False, + is_only_text: bool = False, +): + model_name = model_name.replace('/', '-') # for callers using old naming with / in ViT names + if isinstance(device, str): + device = torch.device(device) + + if pretrained and pretrained.lower() == 'openai': + logging.info(f'Loading pretrained {model_name} from OpenAI.') + model = load_openai_model( + model_name, + precision=precision, + device=device, + jit=jit, + cache_dir=cache_dir, + ) + else: + model_cfg = get_model_config(model_name) + if model_cfg is not None: + logging.info(f'Loaded {model_name} model config.') + else: + logging.error(f'Model config for {model_name} not found; available models {list_models()}.') + raise RuntimeError(f'Model config for {model_name} not found.') + + if 'rope' in model_cfg.get('vision_cfg', {}): + if model_cfg['vision_cfg']['rope']: + os.environ['RoPE'] = "1" + else: + os.environ['RoPE'] = "0" + + if force_quick_gelu: + # override for use of QuickGELU on non-OpenAI transformer models + model_cfg["quick_gelu"] = True + + if force_patch_dropout is not None: + # override the default patch dropout value + model_cfg['vision_cfg']["patch_dropout"] = force_patch_dropout + + cast_dtype = get_cast_dtype(precision) + custom_clip = model_cfg.pop('custom_text', False) or force_custom_clip or ('hf_model_name' in model_cfg['text_cfg']) + + + if custom_clip: + if 'hf_model_name' in model_cfg.get('text_cfg', {}): + model_cfg['text_cfg']['hf_model_pretrained'] = pretrained_hf + model = CustomCLIP(**model_cfg, cast_dtype=cast_dtype, is_only_visual=is_only_visual, is_only_text=is_only_text) + else: + model = CLIP(**model_cfg, cast_dtype=cast_dtype) + print("Not CustomCLIP: If you have set building only visual or text tower, you may still get a complete CLIP model.") + + pretrained_cfg = {} + if pretrained: + checkpoint_path = '' + pretrained_cfg = get_pretrained_cfg(model_name, pretrained) + if pretrained_cfg: + checkpoint_path = download_pretrained(pretrained_cfg, cache_dir=cache_dir) + elif os.path.exists(pretrained): + checkpoint_path = pretrained + + if checkpoint_path: + logging.info(f'Loading pretrained {model_name} weights ({pretrained}).') + load_checkpoint(model, + checkpoint_path, + model_key="model|module|state_dict", + strict=False + ) + else: + error_str = ( + f'Pretrained weights ({pretrained}) not found for model {model_name}.' + f'Available pretrained tags ({list_pretrained_tags_by_model(model_name)}.') + logging.warning(error_str) + raise RuntimeError(error_str) + else: + visual_checkpoint_path = '' + text_checkpoint_path = '' + + if pretrained_image: + pretrained_visual_model = pretrained_visual_model.replace('/', '-') # for callers using old naming with / in ViT names + pretrained_image_cfg = get_pretrained_cfg(pretrained_visual_model, pretrained_image) + if 'timm_model_name' in model_cfg.get('vision_cfg', {}): + # pretrained weight loading for timm models set via vision_cfg + model_cfg['vision_cfg']['timm_model_pretrained'] = True + elif pretrained_image_cfg: + visual_checkpoint_path = download_pretrained(pretrained_image_cfg, cache_dir=cache_dir) + elif os.path.exists(pretrained_image): + visual_checkpoint_path = pretrained_image + else: + logging.warning(f'Pretrained weights ({visual_checkpoint_path}) not found for model {model_name}.visual.') + raise RuntimeError(f'Pretrained weights ({visual_checkpoint_path}) not found for model {model_name}.visual.') + + if pretrained_text: + pretrained_text_model = pretrained_text_model.replace('/', '-') # for callers using old naming with / in ViT names + pretrained_text_cfg = get_pretrained_cfg(pretrained_text_model, pretrained_text) + if pretrained_image_cfg: + text_checkpoint_path = download_pretrained(pretrained_text_cfg, cache_dir=cache_dir) + elif os.path.exists(pretrained_text): + text_checkpoint_path = pretrained_text + else: + logging.warning(f'Pretrained weights ({text_checkpoint_path}) not found for model {model_name}.text.') + raise RuntimeError(f'Pretrained weights ({text_checkpoint_path}) not found for model {model_name}.text.') + + if visual_checkpoint_path: + logging.info(f'Loading pretrained {model_name}.visual weights ({visual_checkpoint_path}).') + if text_checkpoint_path: + logging.info(f'Loading pretrained {model_name}.text weights ({text_checkpoint_path}).') + + if visual_checkpoint_path or text_checkpoint_path: + load_pretrained_checkpoint( + model, + visual_checkpoint_path, + text_checkpoint_path, + strict=False, + visual_model=pretrained_visual_model, + text_model=pretrained_text_model, + model_key="model|module|state_dict", + skip_list=skip_list + ) + + if "fp16" in precision or "bf16" in precision: + logging.info(f'convert precision to {precision}') + model = model.to(torch.bfloat16) if 'bf16' in precision else model.to(torch.float16) + + model.to(device=device) + + # set image / mean metadata from pretrained_cfg if available, or use default + if not is_only_text: + model.visual.image_mean = pretrained_cfg.get('mean', None) or OPENAI_DATASET_MEAN + model.visual.image_std = pretrained_cfg.get('std', None) or OPENAI_DATASET_STD + + if jit: + model = torch.jit.script(model) + + return model + + +def create_model_and_transforms( + model_name: str, + pretrained: Optional[str] = None, + precision: str = 'fp32', + device: Union[str, torch.device] = 'cpu', + jit: bool = False, + force_quick_gelu: bool = False, + force_custom_clip: bool = False, + force_patch_dropout: Optional[float] = None, + pretrained_image: str = '', + pretrained_text: str = '', + pretrained_hf: bool = True, + pretrained_visual_model: str = None, + pretrained_text_model: str = None, + image_mean: Optional[Tuple[float, ...]] = None, + image_std: Optional[Tuple[float, ...]] = None, + cache_dir: Optional[str] = None, + skip_list: list = [], +): + model = create_model( + model_name, + pretrained, + precision=precision, + device=device, + jit=jit, + force_quick_gelu=force_quick_gelu, + force_custom_clip=force_custom_clip, + force_patch_dropout=force_patch_dropout, + pretrained_image=pretrained_image, + pretrained_text=pretrained_text, + pretrained_hf=pretrained_hf, + pretrained_visual_model=pretrained_visual_model, + pretrained_text_model=pretrained_text_model, + cache_dir=cache_dir, + skip_list=skip_list, + ) + + image_mean = image_mean or getattr(model.visual, 'image_mean', None) + image_std = image_std or getattr(model.visual, 'image_std', None) + preprocess_train = image_transform( + model.visual.image_size, + is_train=True, + mean=image_mean, + std=image_std + ) + preprocess_val = image_transform( + model.visual.image_size, + is_train=False, + mean=image_mean, + std=image_std + ) + + return model, preprocess_train, preprocess_val + +def create_eva_vision_and_transforms( + model_name: str, + pretrained: Optional[str] = None, + precision: str = 'fp32', + device: Union[str, torch.device] = 'cpu', + jit: bool = False, + force_quick_gelu: bool = False, + force_custom_clip: bool = False, + force_patch_dropout: Optional[float] = None, + pretrained_image: str = '', + pretrained_text: str = '', + pretrained_hf: bool = True, + pretrained_visual_model: str = None, + pretrained_text_model: str = None, + image_mean: Optional[Tuple[float, ...]] = None, + image_std: Optional[Tuple[float, ...]] = None, + cache_dir: Optional[str] = None, + skip_list: list = [], +): + model = create_model( + model_name, + pretrained, + precision=precision, + device=device, + jit=jit, + force_quick_gelu=force_quick_gelu, + force_custom_clip=force_custom_clip, + force_patch_dropout=force_patch_dropout, + pretrained_image=pretrained_image, + pretrained_text=pretrained_text, + pretrained_hf=pretrained_hf, + pretrained_visual_model=pretrained_visual_model, + pretrained_text_model=pretrained_text_model, + cache_dir=cache_dir, + skip_list=skip_list, + is_only_visual=True, # only use visual tower + ) + + image_mean = image_mean or getattr(model.visual, 'image_mean', None) + image_std = image_std or getattr(model.visual, 'image_std', None) + preprocess_train = image_transform( + model.visual.image_size, + is_train=True, + mean=image_mean, + std=image_std + ) + preprocess_val = image_transform( + model.visual.image_size, + is_train=False, + mean=image_mean, + std=image_std + ) + + return model, preprocess_train, preprocess_val + +def create_model_from_pretrained( + model_name: str, + pretrained: str, + precision: str = 'fp32', + device: Union[str, torch.device] = 'cpu', + jit: bool = False, + force_quick_gelu: bool = False, + force_custom_clip: bool = False, + force_patch_dropout: Optional[float] = None, + return_transform: bool = True, + image_mean: Optional[Tuple[float, ...]] = None, + image_std: Optional[Tuple[float, ...]] = None, + cache_dir: Optional[str] = None, + is_frozen: bool = False, +): + if not is_pretrained_cfg(model_name, pretrained) and not os.path.exists(pretrained): + raise RuntimeError( + f'{pretrained} is not a valid pretrained cfg or checkpoint for {model_name}.' + f' Use open_clip.list_pretrained() to find one.') + + model = create_model( + model_name, + pretrained, + precision=precision, + device=device, + jit=jit, + force_quick_gelu=force_quick_gelu, + force_custom_clip=force_custom_clip, + force_patch_dropout=force_patch_dropout, + cache_dir=cache_dir, + ) + + if is_frozen: + for param in model.parameters(): + param.requires_grad = False + + if not return_transform: + return model + + image_mean = image_mean or getattr(model.visual, 'image_mean', None) + image_std = image_std or getattr(model.visual, 'image_std', None) + preprocess = image_transform( + model.visual.image_size, + is_train=False, + mean=image_mean, + std=image_std + ) + + return model, preprocess diff --git a/code/C3/visual_bge/visual_bge/eva_clip/hf_configs.py b/code/C3/visual_bge/visual_bge/eva_clip/hf_configs.py new file mode 100644 index 0000000..a8c9b70 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/hf_configs.py @@ -0,0 +1,57 @@ +# HF architecture dict: +arch_dict = { + # https://huggingface.co/docs/transformers/model_doc/roberta#roberta + "roberta": { + "config_names": { + "context_length": "max_position_embeddings", + "vocab_size": "vocab_size", + "width": "hidden_size", + "heads": "num_attention_heads", + "layers": "num_hidden_layers", + "layer_attr": "layer", + "token_embeddings_attr": "embeddings" + }, + "pooler": "mean_pooler", + }, + # https://huggingface.co/docs/transformers/model_doc/xlm-roberta#transformers.XLMRobertaConfig + "xlm-roberta": { + "config_names": { + "context_length": "max_position_embeddings", + "vocab_size": "vocab_size", + "width": "hidden_size", + "heads": "num_attention_heads", + "layers": "num_hidden_layers", + "layer_attr": "layer", + "token_embeddings_attr": "embeddings" + }, + "pooler": "mean_pooler", + }, + # https://huggingface.co/docs/transformers/model_doc/mt5#mt5 + "mt5": { + "config_names": { + # unlimited seqlen + # https://github.com/google-research/text-to-text-transfer-transformer/issues/273 + # https://github.com/huggingface/transformers/blob/v4.24.0/src/transformers/models/t5/modeling_t5.py#L374 + "context_length": "", + "vocab_size": "vocab_size", + "width": "d_model", + "heads": "num_heads", + "layers": "num_layers", + "layer_attr": "block", + "token_embeddings_attr": "embed_tokens" + }, + "pooler": "mean_pooler", + }, + "bert": { + "config_names": { + "context_length": "max_position_embeddings", + "vocab_size": "vocab_size", + "width": "hidden_size", + "heads": "num_attention_heads", + "layers": "num_hidden_layers", + "layer_attr": "layer", + "token_embeddings_attr": "embeddings" + }, + "pooler": "mean_pooler", + } +} diff --git a/code/C3/visual_bge/visual_bge/eva_clip/hf_model.py b/code/C3/visual_bge/visual_bge/eva_clip/hf_model.py new file mode 100644 index 0000000..c4b9fd8 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/hf_model.py @@ -0,0 +1,248 @@ +""" huggingface model adapter + +Wraps HuggingFace transformers (https://github.com/huggingface/transformers) models for use as a text tower in CLIP model. +""" + +import re + +import torch +import torch.nn as nn +from torch.nn import functional as F +from torch import TensorType +try: + import transformers + from transformers import AutoModel, AutoModelForMaskedLM, AutoTokenizer, AutoConfig, PretrainedConfig + from transformers.modeling_outputs import BaseModelOutput, BaseModelOutputWithPooling, \ + BaseModelOutputWithPoolingAndCrossAttentions +except ImportError as e: + transformers = None + + + class BaseModelOutput: + pass + + + class PretrainedConfig: + pass + +from .hf_configs import arch_dict + +# utils +def _camel2snake(s): + return re.sub(r'(? TensorType: + # image_atts = torch.ones(image_embeds.size()[:-1],dtype=torch.long).to(x.device) + # attn_mask = (x != self.config.pad_token_id).long() + # out = self.transformer( + # input_ids=x, + # attention_mask=attn_mask, + # encoder_hidden_states = image_embeds, + # encoder_attention_mask = image_atts, + # ) + # pooled_out = self.pooler(out, attn_mask) + + # return self.itm_proj(pooled_out) + + def mask(self, input_ids, vocab_size, device, targets=None, masked_indices=None, probability_matrix=None): + if masked_indices is None: + masked_indices = torch.bernoulli(probability_matrix).bool() + + masked_indices[input_ids == self.tokenizer.pad_token_id] = False + masked_indices[input_ids == self.tokenizer.cls_token_id] = False + + if targets is not None: + targets[~masked_indices] = -100 # We only compute loss on masked tokens + + # 80% of the time, we replace masked input tokens with tokenizer.mask_token ([MASK]) + indices_replaced = torch.bernoulli(torch.full(input_ids.shape, 0.8)).bool() & masked_indices + input_ids[indices_replaced] = self.tokenizer.mask_token_id + + # 10% of the time, we replace masked input tokens with random word + indices_random = torch.bernoulli(torch.full(input_ids.shape, 0.5)).bool() & masked_indices & ~indices_replaced + random_words = torch.randint(vocab_size, input_ids.shape, dtype=torch.long).to(device) + input_ids[indices_random] = random_words[indices_random] + # The rest of the time (10% of the time) we keep the masked input tokens unchanged + + if targets is not None: + return input_ids, targets + else: + return input_ids + + def forward_mlm(self, input_ids, image_embeds, mlm_probability=0.25): + labels = input_ids.clone() + attn_mask = (input_ids != self.config.pad_token_id).long() + image_atts = torch.ones(image_embeds.size()[:-1],dtype=torch.long).to(input_ids.device) + vocab_size = getattr(self.config, arch_dict[self.config.model_type]["config_names"]["vocab_size"]) + probability_matrix = torch.full(labels.shape, mlm_probability) + input_ids, labels = self.mask(input_ids, vocab_size, input_ids.device, targets=labels, + probability_matrix = probability_matrix) + mlm_output = self.transformer(input_ids, + attention_mask = attn_mask, + encoder_hidden_states = image_embeds, + encoder_attention_mask = image_atts, + return_dict = True, + labels = labels, + ) + return mlm_output.loss + # mlm_output = self.transformer(input_ids, + # attention_mask = attn_mask, + # encoder_hidden_states = image_embeds, + # encoder_attention_mask = image_atts, + # return_dict = True, + # ).last_hidden_state + # logits = self.mlm_proj(mlm_output) + + # # logits = logits[:, :-1, :].contiguous().view(-1, vocab_size) + # logits = logits[:, 1:, :].contiguous().view(-1, vocab_size) + # labels = labels[:, 1:].contiguous().view(-1) + + # mlm_loss = F.cross_entropy( + # logits, + # labels, + # # label_smoothing=0.1, + # ) + # return mlm_loss + + + def forward(self, x:TensorType) -> TensorType: + attn_mask = (x != self.config.pad_token_id).long() + out = self.transformer(input_ids=x, attention_mask=attn_mask) + pooled_out = self.pooler(out, attn_mask) + + return self.proj(pooled_out) + + def lock(self, unlocked_layers:int=0, freeze_layer_norm:bool=True): + if not unlocked_layers: # full freezing + for n, p in self.transformer.named_parameters(): + p.requires_grad = (not freeze_layer_norm) if "LayerNorm" in n.split(".") else False + return + + encoder = self.transformer.encoder if hasattr(self.transformer, 'encoder') else self.transformer + layer_list = getattr(encoder, arch_dict[self.config.model_type]["config_names"]["layer_attr"]) + print(f"Unlocking {unlocked_layers}/{len(layer_list) + 1} layers of hf model") + embeddings = getattr( + self.transformer, arch_dict[self.config.model_type]["config_names"]["token_embeddings_attr"]) + modules = [embeddings, *layer_list][:-unlocked_layers] + # freeze layers + for module in modules: + for n, p in module.named_parameters(): + p.requires_grad = (not freeze_layer_norm) if "LayerNorm" in n.split(".") else False + + + @torch.jit.ignore + def set_grad_checkpointing(self, enable=True): + self.transformer.gradient_checkpointing_enable() + + def get_num_layers(self): + encoder = self.transformer.encoder if hasattr(self.transformer, 'encoder') else self.transformer + layer_list = getattr(encoder, arch_dict[self.config.model_type]["config_names"]["layer_attr"]) + return len(layer_list) + + def init_parameters(self): + pass diff --git a/code/C3/visual_bge/visual_bge/eva_clip/loss.py b/code/C3/visual_bge/visual_bge/eva_clip/loss.py new file mode 100644 index 0000000..473f60d --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/loss.py @@ -0,0 +1,138 @@ +import math +import torch +import torch.nn as nn +from torch.nn import functional as F + +try: + import torch.distributed.nn + from torch import distributed as dist + has_distributed = True +except ImportError: + has_distributed = False + +try: + import horovod.torch as hvd +except ImportError: + hvd = None + +from timm.loss import LabelSmoothingCrossEntropy + + +def gather_features( + image_features, + text_features, + local_loss=False, + gather_with_grad=False, + rank=0, + world_size=1, + use_horovod=False +): + assert has_distributed, 'torch.distributed did not import correctly, please use a PyTorch version with support.' + if use_horovod: + assert hvd is not None, 'Please install horovod' + if gather_with_grad: + all_image_features = hvd.allgather(image_features) + all_text_features = hvd.allgather(text_features) + else: + with torch.no_grad(): + all_image_features = hvd.allgather(image_features) + all_text_features = hvd.allgather(text_features) + if not local_loss: + # ensure grads for local rank when all_* features don't have a gradient + gathered_image_features = list(all_image_features.chunk(world_size, dim=0)) + gathered_text_features = list(all_text_features.chunk(world_size, dim=0)) + gathered_image_features[rank] = image_features + gathered_text_features[rank] = text_features + all_image_features = torch.cat(gathered_image_features, dim=0) + all_text_features = torch.cat(gathered_text_features, dim=0) + else: + # We gather tensors from all gpus + if gather_with_grad: + all_image_features = torch.cat(torch.distributed.nn.all_gather(image_features), dim=0) + all_text_features = torch.cat(torch.distributed.nn.all_gather(text_features), dim=0) + # all_image_features = torch.cat(torch.distributed.nn.all_gather(image_features, async_op=True), dim=0) + # all_text_features = torch.cat(torch.distributed.nn.all_gather(text_features, async_op=True), dim=0) + else: + gathered_image_features = [torch.zeros_like(image_features) for _ in range(world_size)] + gathered_text_features = [torch.zeros_like(text_features) for _ in range(world_size)] + dist.all_gather(gathered_image_features, image_features) + dist.all_gather(gathered_text_features, text_features) + if not local_loss: + # ensure grads for local rank when all_* features don't have a gradient + gathered_image_features[rank] = image_features + gathered_text_features[rank] = text_features + all_image_features = torch.cat(gathered_image_features, dim=0) + all_text_features = torch.cat(gathered_text_features, dim=0) + + return all_image_features, all_text_features + + +class ClipLoss(nn.Module): + + def __init__( + self, + local_loss=False, + gather_with_grad=False, + cache_labels=False, + rank=0, + world_size=1, + use_horovod=False, + smoothing=0., + ): + super().__init__() + self.local_loss = local_loss + self.gather_with_grad = gather_with_grad + self.cache_labels = cache_labels + self.rank = rank + self.world_size = world_size + self.use_horovod = use_horovod + self.label_smoothing_cross_entropy = LabelSmoothingCrossEntropy(smoothing=smoothing) if smoothing > 0 else None + + # cache state + self.prev_num_logits = 0 + self.labels = {} + + def forward(self, image_features, text_features, logit_scale=1.): + device = image_features.device + if self.world_size > 1: + all_image_features, all_text_features = gather_features( + image_features, text_features, + self.local_loss, self.gather_with_grad, self.rank, self.world_size, self.use_horovod) + + if self.local_loss: + logits_per_image = logit_scale * image_features @ all_text_features.T + logits_per_text = logit_scale * text_features @ all_image_features.T + else: + logits_per_image = logit_scale * all_image_features @ all_text_features.T + logits_per_text = logits_per_image.T + else: + logits_per_image = logit_scale * image_features @ text_features.T + logits_per_text = logit_scale * text_features @ image_features.T + # calculated ground-truth and cache if enabled + num_logits = logits_per_image.shape[0] + if self.prev_num_logits != num_logits or device not in self.labels: + labels = torch.arange(num_logits, device=device, dtype=torch.long) + if self.world_size > 1 and self.local_loss: + labels = labels + num_logits * self.rank + if self.cache_labels: + self.labels[device] = labels + self.prev_num_logits = num_logits + else: + labels = self.labels[device] + + if self.label_smoothing_cross_entropy: + total_loss = ( + self.label_smoothing_cross_entropy(logits_per_image, labels) + + self.label_smoothing_cross_entropy(logits_per_text, labels) + ) / 2 + else: + total_loss = ( + F.cross_entropy(logits_per_image, labels) + + F.cross_entropy(logits_per_text, labels) + ) / 2 + + acc = None + i2t_acc = (logits_per_image.argmax(-1) == labels).sum() / len(logits_per_image) + t2i_acc = (logits_per_text.argmax(-1) == labels).sum() / len(logits_per_text) + acc = {"i2t": i2t_acc, "t2i": t2i_acc} + return total_loss, acc \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/model.py b/code/C3/visual_bge/visual_bge/eva_clip/model.py new file mode 100644 index 0000000..58fc048 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/model.py @@ -0,0 +1,452 @@ +""" CLIP Model + +Adapted from https://github.com/openai/CLIP. Originally MIT License, Copyright (c) 2021 OpenAI. +""" +import os +from dataclasses import dataclass +from typing import Optional, Tuple, Union +from functools import partial + +import numpy as np +import torch +import torch.nn.functional as F +from torch import nn + +try: + from .hf_model import HFTextEncoder +except: + HFTextEncoder = None +from .modified_resnet import ModifiedResNet +from .timm_model import TimmModel +from .eva_vit_model import EVAVisionTransformer +from .transformer import LayerNorm, QuickGELU, Attention, VisionTransformer, TextTransformer + +# try: +# from apex.normalization import FusedLayerNorm +# except: +FusedLayerNorm = LayerNorm + # print("Please 'pip install apex'") + +try: + import xformers.ops as xops +except ImportError: + xops = None + # print("Please 'pip install xformers'") + +@dataclass +class CLIPVisionCfg: + layers: Union[Tuple[int, int, int, int], int] = 12 + width: int = 768 + head_width: int = 64 + mlp_ratio: float = 4.0 + patch_size: int = 16 + image_size: Union[Tuple[int, int], int] = 224 + ls_init_value: Optional[float] = None # layer scale initial value + patch_dropout: float = 0. # what fraction of patches to dropout during training (0 would mean disabled and no patches dropped) - 0.5 to 0.75 recommended in the paper for optimal results + global_average_pool: bool = False # whether to global average pool the last embedding layer, instead of using CLS token (https://arxiv.org/abs/2205.01580) + drop_path_rate: Optional[float] = None # drop path rate + timm_model_name: str = None # a valid model name overrides layers, width, patch_size + timm_model_pretrained: bool = False # use (imagenet) pretrained weights for named model + timm_pool: str = 'avg' # feature pooling for timm model ('abs_attn', 'rot_attn', 'avg', '') + timm_proj: str = 'linear' # linear projection for timm model output ('linear', 'mlp', '') + timm_proj_bias: bool = False # enable bias final projection + eva_model_name: str = None # a valid eva model name overrides layers, width, patch_size + qkv_bias: bool = True + fusedLN: bool = False + xattn: bool = False + postnorm: bool = False + rope: bool = False + pt_hw_seq_len: int = 16 # 224/14 + intp_freq: bool = False + naiveswiglu: bool = False + subln: bool = False + + +@dataclass +class CLIPTextCfg: + context_length: int = 77 + vocab_size: int = 49408 + width: int = 512 + heads: int = 8 + layers: int = 12 + ls_init_value: Optional[float] = None # layer scale initial value + hf_model_name: str = None + hf_tokenizer_name: str = None + hf_model_pretrained: bool = True + proj: str = 'mlp' + pooler_type: str = 'mean_pooler' + masked_language_modeling: bool = False + fusedLN: bool = False + xattn: bool = False + attn_mask: bool = True + +def get_cast_dtype(precision: str): + cast_dtype = None + if precision == 'bf16': + cast_dtype = torch.bfloat16 + elif precision == 'fp16': + cast_dtype = torch.float16 + return cast_dtype + + +def _build_vision_tower( + embed_dim: int, + vision_cfg: CLIPVisionCfg, + quick_gelu: bool = False, + cast_dtype: Optional[torch.dtype] = None +): + if isinstance(vision_cfg, dict): + vision_cfg = CLIPVisionCfg(**vision_cfg) + + # OpenAI models are pretrained w/ QuickGELU but native nn.GELU is both faster and more + # memory efficient in recent PyTorch releases (>= 1.10). + # NOTE: timm models always use native GELU regardless of quick_gelu flag. + act_layer = QuickGELU if quick_gelu else nn.GELU + + if vision_cfg.eva_model_name: + vision_heads = vision_cfg.width // vision_cfg.head_width + norm_layer = LayerNorm + + visual = EVAVisionTransformer( + img_size=vision_cfg.image_size, + patch_size=vision_cfg.patch_size, + num_classes=embed_dim, + use_mean_pooling=vision_cfg.global_average_pool, #False + init_values=vision_cfg.ls_init_value, + patch_dropout=vision_cfg.patch_dropout, + embed_dim=vision_cfg.width, + depth=vision_cfg.layers, + num_heads=vision_heads, + mlp_ratio=vision_cfg.mlp_ratio, + qkv_bias=vision_cfg.qkv_bias, + drop_path_rate=vision_cfg.drop_path_rate, + norm_layer= partial(FusedLayerNorm, eps=1e-6) if vision_cfg.fusedLN else partial(norm_layer, eps=1e-6), + xattn=vision_cfg.xattn, + rope=vision_cfg.rope, + postnorm=vision_cfg.postnorm, + pt_hw_seq_len= vision_cfg.pt_hw_seq_len, # 224/14 + intp_freq= vision_cfg.intp_freq, + naiveswiglu= vision_cfg.naiveswiglu, + subln= vision_cfg.subln + ) + elif vision_cfg.timm_model_name: + visual = TimmModel( + vision_cfg.timm_model_name, + pretrained=vision_cfg.timm_model_pretrained, + pool=vision_cfg.timm_pool, + proj=vision_cfg.timm_proj, + proj_bias=vision_cfg.timm_proj_bias, + embed_dim=embed_dim, + image_size=vision_cfg.image_size + ) + act_layer = nn.GELU # so that text transformer doesn't use QuickGELU w/ timm models + elif isinstance(vision_cfg.layers, (tuple, list)): + vision_heads = vision_cfg.width * 32 // vision_cfg.head_width + visual = ModifiedResNet( + layers=vision_cfg.layers, + output_dim=embed_dim, + heads=vision_heads, + image_size=vision_cfg.image_size, + width=vision_cfg.width + ) + else: + vision_heads = vision_cfg.width // vision_cfg.head_width + norm_layer = LayerNormFp32 if cast_dtype in (torch.float16, torch.bfloat16) else LayerNorm + visual = VisionTransformer( + image_size=vision_cfg.image_size, + patch_size=vision_cfg.patch_size, + width=vision_cfg.width, + layers=vision_cfg.layers, + heads=vision_heads, + mlp_ratio=vision_cfg.mlp_ratio, + ls_init_value=vision_cfg.ls_init_value, + patch_dropout=vision_cfg.patch_dropout, + global_average_pool=vision_cfg.global_average_pool, + output_dim=embed_dim, + act_layer=act_layer, + norm_layer=norm_layer, + ) + + return visual + + +def _build_text_tower( + embed_dim: int, + text_cfg: CLIPTextCfg, + quick_gelu: bool = False, + cast_dtype: Optional[torch.dtype] = None, +): + if isinstance(text_cfg, dict): + text_cfg = CLIPTextCfg(**text_cfg) + + if text_cfg.hf_model_name: + text = HFTextEncoder( + text_cfg.hf_model_name, + output_dim=embed_dim, + tokenizer_name=text_cfg.hf_tokenizer_name, + proj=text_cfg.proj, + pooler_type=text_cfg.pooler_type, + masked_language_modeling=text_cfg.masked_language_modeling + ) + else: + act_layer = QuickGELU if quick_gelu else nn.GELU + norm_layer = LayerNorm + + text = TextTransformer( + context_length=text_cfg.context_length, + vocab_size=text_cfg.vocab_size, + width=text_cfg.width, + heads=text_cfg.heads, + layers=text_cfg.layers, + ls_init_value=text_cfg.ls_init_value, + output_dim=embed_dim, + act_layer=act_layer, + norm_layer= FusedLayerNorm if text_cfg.fusedLN else norm_layer, + xattn=text_cfg.xattn, + attn_mask=text_cfg.attn_mask, + ) + return text + +class CLIP(nn.Module): + def __init__( + self, + embed_dim: int, + vision_cfg: CLIPVisionCfg, + text_cfg: CLIPTextCfg, + quick_gelu: bool = False, + cast_dtype: Optional[torch.dtype] = None, + ): + super().__init__() + self.visual = _build_vision_tower(embed_dim, vision_cfg, quick_gelu, cast_dtype) + + text = _build_text_tower(embed_dim, text_cfg, quick_gelu, cast_dtype) + self.transformer = text.transformer + self.vocab_size = text.vocab_size + self.token_embedding = text.token_embedding + self.positional_embedding = text.positional_embedding + self.ln_final = text.ln_final + self.text_projection = text.text_projection + self.register_buffer('attn_mask', text.attn_mask, persistent=False) + + self.logit_scale = nn.Parameter(torch.ones([]) * np.log(1 / 0.07)) + + def lock_image_tower(self, unlocked_groups=0, freeze_bn_stats=False): + # lock image tower as per LiT - https://arxiv.org/abs/2111.07991 + self.visual.lock(unlocked_groups=unlocked_groups, freeze_bn_stats=freeze_bn_stats) + + @torch.jit.ignore + def set_grad_checkpointing(self, enable=True): + self.visual.set_grad_checkpointing(enable) + self.transformer.grad_checkpointing = enable + + @torch.jit.ignore + def no_weight_decay(self): + return {'logit_scale'} + + def encode_image(self, image, normalize: bool = False): + features = self.visual(image) + return F.normalize(features, dim=-1) if normalize else features + + def encode_text(self, text, normalize: bool = False): + cast_dtype = self.transformer.get_cast_dtype() + + x = self.token_embedding(text).to(cast_dtype) # [batch_size, n_ctx, d_model] + + x = x + self.positional_embedding.to(cast_dtype) + x = x.permute(1, 0, 2) # NLD -> LND + x = self.transformer(x, attn_mask=self.attn_mask) + x = x.permute(1, 0, 2) # LND -> NLD + x = self.ln_final(x) # [batch_size, n_ctx, transformer.width] + # take features from the eot embedding (eot_token is the highest number in each sequence) + x = x[torch.arange(x.shape[0]), text.argmax(dim=-1)] @ self.text_projection + return F.normalize(x, dim=-1) if normalize else x + + def forward(self, image, text): + image_features = self.encode_image(image, normalize=True) + text_features = self.encode_text(text, normalize=True) + return image_features, text_features, self.logit_scale.exp() + + +class CustomCLIP(nn.Module): + def __init__( + self, + embed_dim: int, + vision_cfg: CLIPVisionCfg, + text_cfg: CLIPTextCfg, + quick_gelu: bool = False, + cast_dtype: Optional[torch.dtype] = None, + itm_task: bool = False, + is_only_visual: bool = False, + is_only_text: bool = False, + ): + super().__init__() + self.visual = _build_vision_tower(embed_dim, vision_cfg, quick_gelu, cast_dtype) + self.text = _build_text_tower(embed_dim, text_cfg, quick_gelu, cast_dtype) + self.logit_scale = nn.Parameter(torch.ones([]) * np.log(1 / 0.07)) #可学习参数 + if is_only_visual: + self.text = None + if is_only_text: + self.visual = None + + def lock_image_tower(self, unlocked_groups=0, freeze_bn_stats=False): + # lock image tower as per LiT - https://arxiv.org/abs/2111.07991 + self.visual.lock(unlocked_groups=unlocked_groups, freeze_bn_stats=freeze_bn_stats) + + def lock_text_tower(self, unlocked_layers:int=0, freeze_layer_norm:bool=True): + self.text.lock(unlocked_layers, freeze_layer_norm) + + @torch.jit.ignore + def set_grad_checkpointing(self, enable=True): + self.visual.set_grad_checkpointing(enable) + if self.text is not None: + self.text.set_grad_checkpointing(enable) + + @torch.jit.ignore + def no_weight_decay(self): + return {'logit_scale'} + + def encode_image(self, image, normalize: bool = False): + features = self.visual(image) + return F.normalize(features, dim=-1) if normalize else features + + def encode_text(self, text, normalize: bool = False): + features = self.text(text) + return F.normalize(features, dim=-1) if normalize else features + + def forward(self, image, text): + if self.visual is not None: + image_features = self.encode_image(image, normalize=True) + else: + image_features = None + if self.text is not None: + text_features = self.encode_text(text, normalize=True) + else: + text_features = None + return image_features, text_features, self.logit_scale.exp() + + +def convert_weights_to_lp(model: nn.Module, dtype=torch.float16): + """Convert applicable model parameters to low-precision (bf16 or fp16)""" + + def _convert_weights(l): + + if isinstance(l, (nn.Conv1d, nn.Conv2d, nn.Linear)): + l.weight.data = l.weight.data.to(dtype) + if l.bias is not None: + l.bias.data = l.bias.data.to(dtype) + + if isinstance(l, (nn.MultiheadAttention, Attention)): + for attr in [*[f"{s}_proj_weight" for s in ["in", "q", "k", "v"]], "in_proj_bias", "bias_k", "bias_v"]: + tensor = getattr(l, attr, None) + if tensor is not None: + tensor.data = tensor.data.to(dtype) + + if isinstance(l, nn.Parameter): + l.data = l.data.to(dtype) + + for name in ["text_projection", "proj"]: + if hasattr(l, name) and isinstance(l, nn.Parameter): + attr = getattr(l, name, None) + if attr is not None: + attr.data = attr.data.to(dtype) + + model.apply(_convert_weights) + + +convert_weights_to_fp16 = convert_weights_to_lp # backwards compat + + +# used to maintain checkpoint compatibility +def convert_to_custom_text_state_dict(state_dict: dict): + if 'text_projection' in state_dict: + # old format state_dict, move text tower -> .text + new_state_dict = {} + for k, v in state_dict.items(): + if any(k.startswith(p) for p in ( + 'text_projection', + 'positional_embedding', + 'token_embedding', + 'transformer', + 'ln_final', + 'logit_scale' + )): + k = 'text.' + k + new_state_dict[k] = v + return new_state_dict + return state_dict + + +def build_model_from_openai_state_dict( + state_dict: dict, + quick_gelu=True, + cast_dtype=torch.float16, +): + vit = "visual.proj" in state_dict + + if vit: + vision_width = state_dict["visual.conv1.weight"].shape[0] + vision_layers = len( + [k for k in state_dict.keys() if k.startswith("visual.") and k.endswith(".attn.in_proj_weight")]) + vision_patch_size = state_dict["visual.conv1.weight"].shape[-1] + grid_size = round((state_dict["visual.positional_embedding"].shape[0] - 1) ** 0.5) + image_size = vision_patch_size * grid_size + else: + counts: list = [ + len(set(k.split(".")[2] for k in state_dict if k.startswith(f"visual.layer{b}"))) for b in [1, 2, 3, 4]] + vision_layers = tuple(counts) + vision_width = state_dict["visual.layer1.0.conv1.weight"].shape[0] + output_width = round((state_dict["visual.attnpool.positional_embedding"].shape[0] - 1) ** 0.5) + vision_patch_size = None + assert output_width ** 2 + 1 == state_dict["visual.attnpool.positional_embedding"].shape[0] + image_size = output_width * 32 + + embed_dim = state_dict["text_projection"].shape[1] + context_length = state_dict["positional_embedding"].shape[0] + vocab_size = state_dict["token_embedding.weight"].shape[0] + transformer_width = state_dict["ln_final.weight"].shape[0] + transformer_heads = transformer_width // 64 + transformer_layers = len(set(k.split(".")[2] for k in state_dict if k.startswith(f"transformer.resblocks"))) + + vision_cfg = CLIPVisionCfg( + layers=vision_layers, + width=vision_width, + patch_size=vision_patch_size, + image_size=image_size, + ) + text_cfg = CLIPTextCfg( + context_length=context_length, + vocab_size=vocab_size, + width=transformer_width, + heads=transformer_heads, + layers=transformer_layers + ) + model = CLIP( + embed_dim, + vision_cfg=vision_cfg, + text_cfg=text_cfg, + quick_gelu=quick_gelu, # OpenAI models were trained with QuickGELU + cast_dtype=cast_dtype, + ) + + for key in ["input_resolution", "context_length", "vocab_size"]: + state_dict.pop(key, None) + + convert_weights_to_fp16(model) # OpenAI state dicts are partially converted to float16 + model.load_state_dict(state_dict) + return model.eval() + + +def trace_model(model, batch_size=256, device=torch.device('cpu')): + model.eval() + image_size = model.visual.image_size + example_images = torch.ones((batch_size, 3, image_size, image_size), device=device) + example_text = torch.zeros((batch_size, model.context_length), dtype=torch.int, device=device) + model = torch.jit.trace_module( + model, + inputs=dict( + forward=(example_images, example_text), + encode_text=(example_text,), + encode_image=(example_images,) + )) + model.visual.image_size = image_size + return model diff --git a/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA01-CLIP-B-16.json b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA01-CLIP-B-16.json new file mode 100644 index 0000000..aad2058 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA01-CLIP-B-16.json @@ -0,0 +1,19 @@ +{ + "embed_dim": 512, + "vision_cfg": { + "image_size": 224, + "layers": 12, + "width": 768, + "patch_size": 16, + "eva_model_name": "eva-clip-b-16", + "ls_init_value": 0.1, + "drop_path_rate": 0.0 + }, + "text_cfg": { + "context_length": 77, + "vocab_size": 49408, + "width": 512, + "heads": 8, + "layers": 12 + } +} \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA01-CLIP-g-14-plus.json b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA01-CLIP-g-14-plus.json new file mode 100644 index 0000000..1002795 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA01-CLIP-g-14-plus.json @@ -0,0 +1,24 @@ +{ + "embed_dim": 1024, + "vision_cfg": { + "image_size": 224, + "layers": 40, + "width": 1408, + "head_width": 88, + "mlp_ratio": 4.3637, + "patch_size": 14, + "eva_model_name": "eva-clip-g-14-x", + "drop_path_rate": 0, + "xattn": true, + "fusedLN": true + }, + "text_cfg": { + "context_length": 77, + "vocab_size": 49408, + "width": 1024, + "heads": 16, + "layers": 24, + "xattn": false, + "fusedLN": true + } +} \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA01-CLIP-g-14.json b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA01-CLIP-g-14.json new file mode 100644 index 0000000..5d338b4 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA01-CLIP-g-14.json @@ -0,0 +1,24 @@ +{ + "embed_dim": 1024, + "vision_cfg": { + "image_size": 224, + "layers": 40, + "width": 1408, + "head_width": 88, + "mlp_ratio": 4.3637, + "patch_size": 14, + "eva_model_name": "eva-clip-g-14-x", + "drop_path_rate": 0.4, + "xattn": true, + "fusedLN": true + }, + "text_cfg": { + "context_length": 77, + "vocab_size": 49408, + "width": 768, + "heads": 12, + "layers": 12, + "xattn": false, + "fusedLN": true + } +} \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-B-16.json b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-B-16.json new file mode 100644 index 0000000..6580a3f --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-B-16.json @@ -0,0 +1,30 @@ +{ + "embed_dim": 512, + "vision_cfg": { + "image_size": 224, + "layers": 12, + "width": 768, + "head_width": 64, + "patch_size": 16, + "mlp_ratio": 2.6667, + "eva_model_name": "eva-clip-b-16-X", + "drop_path_rate": 0.0, + "xattn": true, + "fusedLN": true, + "rope": true, + "pt_hw_seq_len": 16, + "intp_freq": true, + "naiveswiglu": true, + "subln": true, + "patch_dropout": 0.5 + }, + "text_cfg": { + "context_length": 77, + "vocab_size": 49408, + "width": 512, + "heads": 8, + "layers": 12, + "xattn": true, + "fusedLN": true + } +} \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-L-14-336.json b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-L-14-336.json new file mode 100644 index 0000000..3e1d124 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-L-14-336.json @@ -0,0 +1,29 @@ +{ + "embed_dim": 768, + "vision_cfg": { + "image_size": 336, + "layers": 24, + "width": 1024, + "drop_path_rate": 0, + "head_width": 64, + "mlp_ratio": 2.6667, + "patch_size": 14, + "eva_model_name": "eva-clip-l-14-336", + "xattn": true, + "fusedLN": true, + "rope": true, + "pt_hw_seq_len": 16, + "intp_freq": true, + "naiveswiglu": true, + "subln": true + }, + "text_cfg": { + "context_length": 77, + "vocab_size": 49408, + "width": 768, + "heads": 12, + "layers": 12, + "xattn": false, + "fusedLN": true + } +} \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-L-14.json b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-L-14.json new file mode 100644 index 0000000..03b22ad --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-L-14.json @@ -0,0 +1,29 @@ +{ + "embed_dim": 768, + "vision_cfg": { + "image_size": 224, + "layers": 24, + "width": 1024, + "drop_path_rate": 0, + "head_width": 64, + "mlp_ratio": 2.6667, + "patch_size": 14, + "eva_model_name": "eva-clip-l-14", + "xattn": true, + "fusedLN": true, + "rope": true, + "pt_hw_seq_len": 16, + "intp_freq": true, + "naiveswiglu": true, + "subln": true + }, + "text_cfg": { + "context_length": 77, + "vocab_size": 49408, + "width": 768, + "heads": 12, + "layers": 12, + "xattn": false, + "fusedLN": true + } +} \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-bigE-14-plus.json b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-bigE-14-plus.json new file mode 100644 index 0000000..aa04e25 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-bigE-14-plus.json @@ -0,0 +1,25 @@ +{ + "embed_dim": 1024, + "vision_cfg": { + "image_size": 224, + "layers": 64, + "width": 1792, + "head_width": 112, + "mlp_ratio": 8.571428571428571, + "patch_size": 14, + "eva_model_name": "eva-clip-4b-14-x", + "drop_path_rate": 0, + "xattn": true, + "postnorm": true, + "fusedLN": true + }, + "text_cfg": { + "context_length": 77, + "vocab_size": 49408, + "width": 1280, + "heads": 20, + "layers": 32, + "xattn": false, + "fusedLN": true + } +} diff --git a/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-bigE-14.json b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-bigE-14.json new file mode 100644 index 0000000..747ffcc --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/model_configs/EVA02-CLIP-bigE-14.json @@ -0,0 +1,25 @@ +{ + "embed_dim": 1024, + "vision_cfg": { + "image_size": 224, + "layers": 64, + "width": 1792, + "head_width": 112, + "mlp_ratio": 8.571428571428571, + "patch_size": 14, + "eva_model_name": "eva-clip-4b-14-x", + "drop_path_rate": 0, + "xattn": true, + "postnorm": true, + "fusedLN": true + }, + "text_cfg": { + "context_length": 77, + "vocab_size": 49408, + "width": 1024, + "heads": 16, + "layers": 24, + "xattn": false, + "fusedLN": true + } +} \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/modified_resnet.py b/code/C3/visual_bge/visual_bge/eva_clip/modified_resnet.py new file mode 100644 index 0000000..6a8d3ae --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/modified_resnet.py @@ -0,0 +1,181 @@ +from collections import OrderedDict + +import torch +from torch import nn +from torch.nn import functional as F + +from .utils import freeze_batch_norm_2d + + +class Bottleneck(nn.Module): + expansion = 4 + + def __init__(self, inplanes, planes, stride=1): + super().__init__() + + # all conv layers have stride 1. an avgpool is performed after the second convolution when stride > 1 + self.conv1 = nn.Conv2d(inplanes, planes, 1, bias=False) + self.bn1 = nn.BatchNorm2d(planes) + self.act1 = nn.ReLU(inplace=True) + + self.conv2 = nn.Conv2d(planes, planes, 3, padding=1, bias=False) + self.bn2 = nn.BatchNorm2d(planes) + self.act2 = nn.ReLU(inplace=True) + + self.avgpool = nn.AvgPool2d(stride) if stride > 1 else nn.Identity() + + self.conv3 = nn.Conv2d(planes, planes * self.expansion, 1, bias=False) + self.bn3 = nn.BatchNorm2d(planes * self.expansion) + self.act3 = nn.ReLU(inplace=True) + + self.downsample = None + self.stride = stride + + if stride > 1 or inplanes != planes * Bottleneck.expansion: + # downsampling layer is prepended with an avgpool, and the subsequent convolution has stride 1 + self.downsample = nn.Sequential(OrderedDict([ + ("-1", nn.AvgPool2d(stride)), + ("0", nn.Conv2d(inplanes, planes * self.expansion, 1, stride=1, bias=False)), + ("1", nn.BatchNorm2d(planes * self.expansion)) + ])) + + def forward(self, x: torch.Tensor): + identity = x + + out = self.act1(self.bn1(self.conv1(x))) + out = self.act2(self.bn2(self.conv2(out))) + out = self.avgpool(out) + out = self.bn3(self.conv3(out)) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.act3(out) + return out + + +class AttentionPool2d(nn.Module): + def __init__(self, spacial_dim: int, embed_dim: int, num_heads: int, output_dim: int = None): + super().__init__() + self.positional_embedding = nn.Parameter(torch.randn(spacial_dim ** 2 + 1, embed_dim) / embed_dim ** 0.5) + self.k_proj = nn.Linear(embed_dim, embed_dim) + self.q_proj = nn.Linear(embed_dim, embed_dim) + self.v_proj = nn.Linear(embed_dim, embed_dim) + self.c_proj = nn.Linear(embed_dim, output_dim or embed_dim) + self.num_heads = num_heads + + def forward(self, x): + x = x.reshape(x.shape[0], x.shape[1], x.shape[2] * x.shape[3]).permute(2, 0, 1) # NCHW -> (HW)NC + x = torch.cat([x.mean(dim=0, keepdim=True), x], dim=0) # (HW+1)NC + x = x + self.positional_embedding[:, None, :].to(x.dtype) # (HW+1)NC + x, _ = F.multi_head_attention_forward( + query=x, key=x, value=x, + embed_dim_to_check=x.shape[-1], + num_heads=self.num_heads, + q_proj_weight=self.q_proj.weight, + k_proj_weight=self.k_proj.weight, + v_proj_weight=self.v_proj.weight, + in_proj_weight=None, + in_proj_bias=torch.cat([self.q_proj.bias, self.k_proj.bias, self.v_proj.bias]), + bias_k=None, + bias_v=None, + add_zero_attn=False, + dropout_p=0., + out_proj_weight=self.c_proj.weight, + out_proj_bias=self.c_proj.bias, + use_separate_proj_weight=True, + training=self.training, + need_weights=False + ) + + return x[0] + + +class ModifiedResNet(nn.Module): + """ + A ResNet class that is similar to torchvision's but contains the following changes: + - There are now 3 "stem" convolutions as opposed to 1, with an average pool instead of a max pool. + - Performs anti-aliasing strided convolutions, where an avgpool is prepended to convolutions with stride > 1 + - The final pooling layer is a QKV attention instead of an average pool + """ + + def __init__(self, layers, output_dim, heads, image_size=224, width=64): + super().__init__() + self.output_dim = output_dim + self.image_size = image_size + + # the 3-layer stem + self.conv1 = nn.Conv2d(3, width // 2, kernel_size=3, stride=2, padding=1, bias=False) + self.bn1 = nn.BatchNorm2d(width // 2) + self.act1 = nn.ReLU(inplace=True) + self.conv2 = nn.Conv2d(width // 2, width // 2, kernel_size=3, padding=1, bias=False) + self.bn2 = nn.BatchNorm2d(width // 2) + self.act2 = nn.ReLU(inplace=True) + self.conv3 = nn.Conv2d(width // 2, width, kernel_size=3, padding=1, bias=False) + self.bn3 = nn.BatchNorm2d(width) + self.act3 = nn.ReLU(inplace=True) + self.avgpool = nn.AvgPool2d(2) + + # residual layers + self._inplanes = width # this is a *mutable* variable used during construction + self.layer1 = self._make_layer(width, layers[0]) + self.layer2 = self._make_layer(width * 2, layers[1], stride=2) + self.layer3 = self._make_layer(width * 4, layers[2], stride=2) + self.layer4 = self._make_layer(width * 8, layers[3], stride=2) + + embed_dim = width * 32 # the ResNet feature dimension + self.attnpool = AttentionPool2d(image_size // 32, embed_dim, heads, output_dim) + + self.init_parameters() + + def _make_layer(self, planes, blocks, stride=1): + layers = [Bottleneck(self._inplanes, planes, stride)] + + self._inplanes = planes * Bottleneck.expansion + for _ in range(1, blocks): + layers.append(Bottleneck(self._inplanes, planes)) + + return nn.Sequential(*layers) + + def init_parameters(self): + if self.attnpool is not None: + std = self.attnpool.c_proj.in_features ** -0.5 + nn.init.normal_(self.attnpool.q_proj.weight, std=std) + nn.init.normal_(self.attnpool.k_proj.weight, std=std) + nn.init.normal_(self.attnpool.v_proj.weight, std=std) + nn.init.normal_(self.attnpool.c_proj.weight, std=std) + + for resnet_block in [self.layer1, self.layer2, self.layer3, self.layer4]: + for name, param in resnet_block.named_parameters(): + if name.endswith("bn3.weight"): + nn.init.zeros_(param) + + def lock(self, unlocked_groups=0, freeze_bn_stats=False): + assert unlocked_groups == 0, 'partial locking not currently supported for this model' + for param in self.parameters(): + param.requires_grad = False + if freeze_bn_stats: + freeze_batch_norm_2d(self) + + @torch.jit.ignore + def set_grad_checkpointing(self, enable=True): + # FIXME support for non-transformer + pass + + def stem(self, x): + x = self.act1(self.bn1(self.conv1(x))) + x = self.act2(self.bn2(self.conv2(x))) + x = self.act3(self.bn3(self.conv3(x))) + x = self.avgpool(x) + return x + + def forward(self, x): + x = self.stem(x) + x = self.layer1(x) + x = self.layer2(x) + x = self.layer3(x) + x = self.layer4(x) + x = self.attnpool(x) + + return x diff --git a/code/C3/visual_bge/visual_bge/eva_clip/openai.py b/code/C3/visual_bge/visual_bge/eva_clip/openai.py new file mode 100644 index 0000000..cc4e13e --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/openai.py @@ -0,0 +1,144 @@ +""" OpenAI pretrained model functions + +Adapted from https://github.com/openai/CLIP. Originally MIT License, Copyright (c) 2021 OpenAI. +""" + +import os +import warnings +from typing import List, Optional, Union + +import torch + +from .model import build_model_from_openai_state_dict, convert_weights_to_lp, get_cast_dtype +from .pretrained import get_pretrained_url, list_pretrained_models_by_tag, download_pretrained_from_url + +__all__ = ["list_openai_models", "load_openai_model"] + + +def list_openai_models() -> List[str]: + """Returns the names of available CLIP models""" + return list_pretrained_models_by_tag('openai') + + +def load_openai_model( + name: str, + precision: Optional[str] = None, + device: Optional[Union[str, torch.device]] = None, + jit: bool = True, + cache_dir: Optional[str] = None, +): + """Load a CLIP model + + Parameters + ---------- + name : str + A model name listed by `clip.available_models()`, or the path to a model checkpoint containing the state_dict + precision: str + Model precision, if None defaults to 'fp32' if device == 'cpu' else 'fp16'. + device : Union[str, torch.device] + The device to put the loaded model + jit : bool + Whether to load the optimized JIT model (default) or more hackable non-JIT model. + cache_dir : Optional[str] + The directory to cache the downloaded model weights + + Returns + ------- + model : torch.nn.Module + The CLIP model + preprocess : Callable[[PIL.Image], torch.Tensor] + A torchvision transform that converts a PIL image into a tensor that the returned model can take as its input + """ + if device is None: + device = "cuda" if torch.cuda.is_available() else "cpu" + if precision is None: + precision = 'fp32' if device == 'cpu' else 'fp16' + + if get_pretrained_url(name, 'openai'): + model_path = download_pretrained_from_url(get_pretrained_url(name, 'openai'), cache_dir=cache_dir) + elif os.path.isfile(name): + model_path = name + else: + raise RuntimeError(f"Model {name} not found; available models = {list_openai_models()}") + + try: + # loading JIT archive + model = torch.jit.load(model_path, map_location=device if jit else "cpu").eval() + state_dict = None + except RuntimeError: + # loading saved state dict + if jit: + warnings.warn(f"File {model_path} is not a JIT archive. Loading as a state dict instead") + jit = False + state_dict = torch.load(model_path, map_location="cpu") + + if not jit: + # Build a non-jit model from the OpenAI jitted model state dict + cast_dtype = get_cast_dtype(precision) + try: + model = build_model_from_openai_state_dict(state_dict or model.state_dict(), cast_dtype=cast_dtype) + except KeyError: + sd = {k[7:]: v for k, v in state_dict["state_dict"].items()} + model = build_model_from_openai_state_dict(sd, cast_dtype=cast_dtype) + + # model from OpenAI state dict is in manually cast fp16 mode, must be converted for AMP/fp32/bf16 use + model = model.to(device) + if precision.startswith('amp') or precision == 'fp32': + model.float() + elif precision == 'bf16': + convert_weights_to_lp(model, dtype=torch.bfloat16) + + return model + + # patch the device names + device_holder = torch.jit.trace(lambda: torch.ones([]).to(torch.device(device)), example_inputs=[]) + device_node = [n for n in device_holder.graph.findAllNodes("prim::Constant") if "Device" in repr(n)][-1] + + def patch_device(module): + try: + graphs = [module.graph] if hasattr(module, "graph") else [] + except RuntimeError: + graphs = [] + + if hasattr(module, "forward1"): + graphs.append(module.forward1.graph) + + for graph in graphs: + for node in graph.findAllNodes("prim::Constant"): + if "value" in node.attributeNames() and str(node["value"]).startswith("cuda"): + node.copyAttributes(device_node) + + model.apply(patch_device) + patch_device(model.encode_image) + patch_device(model.encode_text) + + # patch dtype to float32 (typically for CPU) + if precision == 'fp32': + float_holder = torch.jit.trace(lambda: torch.ones([]).float(), example_inputs=[]) + float_input = list(float_holder.graph.findNode("aten::to").inputs())[1] + float_node = float_input.node() + + def patch_float(module): + try: + graphs = [module.graph] if hasattr(module, "graph") else [] + except RuntimeError: + graphs = [] + + if hasattr(module, "forward1"): + graphs.append(module.forward1.graph) + + for graph in graphs: + for node in graph.findAllNodes("aten::to"): + inputs = list(node.inputs()) + for i in [1, 2]: # dtype can be the second or third argument to aten::to() + if inputs[i].node()["value"] == 5: + inputs[i].node().copyAttributes(float_node) + + model.apply(patch_float) + patch_float(model.encode_image) + patch_float(model.encode_text) + model.float() + + # ensure image_size attr available at consistent location for both jit and non-jit + model.visual.image_size = model.input_resolution.item() + return model diff --git a/code/C3/visual_bge/visual_bge/eva_clip/pretrained.py b/code/C3/visual_bge/visual_bge/eva_clip/pretrained.py new file mode 100644 index 0000000..a1e55dc --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/pretrained.py @@ -0,0 +1,332 @@ +import hashlib +import os +import urllib +import warnings +from functools import partial +from typing import Dict, Union + +from tqdm import tqdm + +try: + from huggingface_hub import hf_hub_download + _has_hf_hub = True +except ImportError: + hf_hub_download = None + _has_hf_hub = False + + +def _pcfg(url='', hf_hub='', filename='', mean=None, std=None): + return dict( + url=url, + hf_hub=hf_hub, + mean=mean, + std=std, + ) + +_VITB32 = dict( + openai=_pcfg( + "https://openaipublic.azureedge.net/clip/models/40d365715913c9da98579312b702a82c18be219cc2a73407c4526f58eba950af/ViT-B-32.pt"), + laion400m_e31=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_b_32-quickgelu-laion400m_e31-d867053b.pt"), + laion400m_e32=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_b_32-quickgelu-laion400m_e32-46683a32.pt"), + laion2b_e16=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_b_32-laion2b_e16-af8dbd0c.pth"), + laion2b_s34b_b79k=_pcfg(hf_hub='laion/CLIP-ViT-B-32-laion2B-s34B-b79K/') +) + +_VITB32_quickgelu = dict( + openai=_pcfg( + "https://openaipublic.azureedge.net/clip/models/40d365715913c9da98579312b702a82c18be219cc2a73407c4526f58eba950af/ViT-B-32.pt"), + laion400m_e31=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_b_32-quickgelu-laion400m_e31-d867053b.pt"), + laion400m_e32=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_b_32-quickgelu-laion400m_e32-46683a32.pt"), +) + +_VITB16 = dict( + openai=_pcfg( + "https://openaipublic.azureedge.net/clip/models/5806e77cd80f8b59890b7e101eabd078d9fb84e6937f9e85e4ecb61988df416f/ViT-B-16.pt"), + laion400m_e31=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_b_16-laion400m_e31-00efa78f.pt"), + laion400m_e32=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_b_16-laion400m_e32-55e67d44.pt"), + laion2b_s34b_b88k=_pcfg(hf_hub='laion/CLIP-ViT-B-16-laion2B-s34B-b88K/'), +) + +_EVAB16 = dict( + eva=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_B_psz14to16.pt'), + eva02=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_B_psz14to16.pt'), + eva_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_B_psz16_s8B.pt'), + eva02_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_B_psz16_s8B.pt'), +) + +_VITB16_PLUS_240 = dict( + laion400m_e31=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_b_16_plus_240-laion400m_e31-8fb26589.pt"), + laion400m_e32=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_b_16_plus_240-laion400m_e32-699c4b84.pt"), +) + +_VITL14 = dict( + openai=_pcfg( + "https://openaipublic.azureedge.net/clip/models/b8cca3fd41ae0c99ba7e8951adf17d267cdb84cd88be6f7c2e0eca1737a03836/ViT-L-14.pt"), + laion400m_e31=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_l_14-laion400m_e31-69988bb6.pt"), + laion400m_e32=_pcfg( + "https://github.com/mlfoundations/open_clip/releases/download/v0.2-weights/vit_l_14-laion400m_e32-3d133497.pt"), + laion2b_s32b_b82k=_pcfg( + hf_hub='laion/CLIP-ViT-L-14-laion2B-s32B-b82K/', + mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)), +) + +_EVAL14 = dict( + eva=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_L_psz14.pt'), + eva02=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_L_psz14.pt'), + eva_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_L_psz14_s4B.pt'), + eva02_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_L_psz14_s4B.pt'), +) + +_VITL14_336 = dict( + openai=_pcfg( + "https://openaipublic.azureedge.net/clip/models/3035c92b350959924f9f00213499208652fc7ea050643e8b385c2dac08641f02/ViT-L-14-336px.pt"), +) + +_EVAL14_336 = dict( + eva_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_L_336_psz14_s6B.pt'), + eva02_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_L_336_psz14_s6B.pt'), + eva_clip_224to336=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_L_psz14_224to336.pt'), + eva02_clip_224to336=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_L_psz14_224to336.pt'), +) + +_VITH14 = dict( + laion2b_s32b_b79k=_pcfg(hf_hub='laion/CLIP-ViT-H-14-laion2B-s32B-b79K/'), +) + +_VITg14 = dict( + laion2b_s12b_b42k=_pcfg(hf_hub='laion/CLIP-ViT-g-14-laion2B-s12B-b42K/'), + laion2b_s34b_b88k=_pcfg(hf_hub='laion/CLIP-ViT-g-14-laion2B-s34B-b88K/'), +) + +_EVAg14 = dict( + eva=_pcfg(hf_hub='QuanSun/EVA-CLIP/'), + eva01=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA01_g_psz14.pt'), + eva_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA01_CLIP_g_14_psz14_s11B.pt'), + eva01_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA01_CLIP_g_14_psz14_s11B.pt'), +) + +_EVAg14_PLUS = dict( + eva=_pcfg(hf_hub='QuanSun/EVA-CLIP/'), + eva01=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA01_g_psz14.pt'), + eva_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA01_CLIP_g_14_plus_psz14_s11B.pt'), + eva01_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA01_CLIP_g_14_plus_psz14_s11B.pt'), +) + +_VITbigG14 = dict( + laion2b_s39b_b160k=_pcfg(hf_hub='laion/CLIP-ViT-bigG-14-laion2B-39B-b160k/'), +) + +_EVAbigE14 = dict( + eva=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_E_psz14.pt'), + eva02=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_E_psz14.pt'), + eva_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_E_psz14_s4B.pt'), + eva02_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_E_psz14_s4B.pt'), +) + +_EVAbigE14_PLUS = dict( + eva=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_E_psz14.pt'), + eva02=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_E_psz14.pt'), + eva_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_E_psz14_plus_s9B.pt'), + eva02_clip=_pcfg(hf_hub='QuanSun/EVA-CLIP/EVA02_CLIP_E_psz14_plus_s9B.pt'), +) + + +_PRETRAINED = { + # "ViT-B-32": _VITB32, + "OpenaiCLIP-B-32": _VITB32, + "OpenCLIP-B-32": _VITB32, + + # "ViT-B-32-quickgelu": _VITB32_quickgelu, + "OpenaiCLIP-B-32-quickgelu": _VITB32_quickgelu, + "OpenCLIP-B-32-quickgelu": _VITB32_quickgelu, + + # "ViT-B-16": _VITB16, + "OpenaiCLIP-B-16": _VITB16, + "OpenCLIP-B-16": _VITB16, + + "EVA02-B-16": _EVAB16, + "EVA02-CLIP-B-16": _EVAB16, + + # "ViT-B-16-plus-240": _VITB16_PLUS_240, + "OpenCLIP-B-16-plus-240": _VITB16_PLUS_240, + + # "ViT-L-14": _VITL14, + "OpenaiCLIP-L-14": _VITL14, + "OpenCLIP-L-14": _VITL14, + + "EVA02-L-14": _EVAL14, + "EVA02-CLIP-L-14": _EVAL14, + + # "ViT-L-14-336": _VITL14_336, + "OpenaiCLIP-L-14-336": _VITL14_336, + + "EVA02-CLIP-L-14-336": _EVAL14_336, + + # "ViT-H-14": _VITH14, + # "ViT-g-14": _VITg14, + "OpenCLIP-H-14": _VITH14, + "OpenCLIP-g-14": _VITg14, + + "EVA01-CLIP-g-14": _EVAg14, + "EVA01-CLIP-g-14-plus": _EVAg14_PLUS, + + # "ViT-bigG-14": _VITbigG14, + "OpenCLIP-bigG-14": _VITbigG14, + + "EVA02-CLIP-bigE-14": _EVAbigE14, + "EVA02-CLIP-bigE-14-plus": _EVAbigE14_PLUS, +} + + +def _clean_tag(tag: str): + # normalize pretrained tags + return tag.lower().replace('-', '_') + + +def list_pretrained(as_str: bool = False): + """ returns list of pretrained models + Returns a tuple (model_name, pretrain_tag) by default or 'name:tag' if as_str == True + """ + return [':'.join([k, t]) if as_str else (k, t) for k in _PRETRAINED.keys() for t in _PRETRAINED[k].keys()] + + +def list_pretrained_models_by_tag(tag: str): + """ return all models having the specified pretrain tag """ + models = [] + tag = _clean_tag(tag) + for k in _PRETRAINED.keys(): + if tag in _PRETRAINED[k]: + models.append(k) + return models + + +def list_pretrained_tags_by_model(model: str): + """ return all pretrain tags for the specified model architecture """ + tags = [] + if model in _PRETRAINED: + tags.extend(_PRETRAINED[model].keys()) + return tags + + +def is_pretrained_cfg(model: str, tag: str): + if model not in _PRETRAINED: + return False + return _clean_tag(tag) in _PRETRAINED[model] + + +def get_pretrained_cfg(model: str, tag: str): + if model not in _PRETRAINED: + return {} + model_pretrained = _PRETRAINED[model] + return model_pretrained.get(_clean_tag(tag), {}) + + +def get_pretrained_url(model: str, tag: str): + cfg = get_pretrained_cfg(model, _clean_tag(tag)) + return cfg.get('url', '') + + +def download_pretrained_from_url( + url: str, + cache_dir: Union[str, None] = None, +): + if not cache_dir: + cache_dir = os.path.expanduser("~/.cache/clip") + os.makedirs(cache_dir, exist_ok=True) + filename = os.path.basename(url) + + if 'openaipublic' in url: + expected_sha256 = url.split("/")[-2] + elif 'mlfoundations' in url: + expected_sha256 = os.path.splitext(filename)[0].split("-")[-1] + else: + expected_sha256 = '' + + download_target = os.path.join(cache_dir, filename) + + if os.path.exists(download_target) and not os.path.isfile(download_target): + raise RuntimeError(f"{download_target} exists and is not a regular file") + + if os.path.isfile(download_target): + if expected_sha256: + if hashlib.sha256(open(download_target, "rb").read()).hexdigest().startswith(expected_sha256): + return download_target + else: + warnings.warn(f"{download_target} exists, but the SHA256 checksum does not match; re-downloading the file") + else: + return download_target + + with urllib.request.urlopen(url) as source, open(download_target, "wb") as output: + with tqdm(total=int(source.headers.get("Content-Length")), ncols=80, unit='iB', unit_scale=True) as loop: + while True: + buffer = source.read(8192) + if not buffer: + break + + output.write(buffer) + loop.update(len(buffer)) + + if expected_sha256 and not hashlib.sha256(open(download_target, "rb").read()).hexdigest().startswith(expected_sha256): + raise RuntimeError(f"Model has been downloaded but the SHA256 checksum does not not match") + + return download_target + + +def has_hf_hub(necessary=False): + if not _has_hf_hub and necessary: + # if no HF Hub module installed, and it is necessary to continue, raise error + raise RuntimeError( + 'Hugging Face hub model specified but package not installed. Run `pip install huggingface_hub`.') + return _has_hf_hub + + +def download_pretrained_from_hf( + model_id: str, + filename: str = 'open_clip_pytorch_model.bin', + revision=None, + cache_dir: Union[str, None] = None, +): + has_hf_hub(True) + cached_file = hf_hub_download(model_id, filename, revision=revision, cache_dir=cache_dir) + return cached_file + + +def download_pretrained( + cfg: Dict, + force_hf_hub: bool = False, + cache_dir: Union[str, None] = None, +): + target = '' + if not cfg: + return target + + download_url = cfg.get('url', '') + download_hf_hub = cfg.get('hf_hub', '') + if download_hf_hub and force_hf_hub: + # use HF hub even if url exists + download_url = '' + + if download_url: + target = download_pretrained_from_url(download_url, cache_dir=cache_dir) + elif download_hf_hub: + has_hf_hub(True) + # we assume the hf_hub entries in pretrained config combine model_id + filename in + # 'org/model_name/filename.pt' form. To specify just the model id w/o filename and + # use 'open_clip_pytorch_model.bin' default, there must be a trailing slash 'org/model_name/'. + model_id, filename = os.path.split(download_hf_hub) + if filename: + target = download_pretrained_from_hf(model_id, filename=filename, cache_dir=cache_dir) + else: + target = download_pretrained_from_hf(model_id, cache_dir=cache_dir) + + return target diff --git a/code/C3/visual_bge/visual_bge/eva_clip/rope.py b/code/C3/visual_bge/visual_bge/eva_clip/rope.py new file mode 100644 index 0000000..69030c3 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/rope.py @@ -0,0 +1,137 @@ +from math import pi +import torch +from torch import nn +from einops import rearrange, repeat +import logging + +def broadcat(tensors, dim = -1): + num_tensors = len(tensors) + shape_lens = set(list(map(lambda t: len(t.shape), tensors))) + assert len(shape_lens) == 1, 'tensors must all have the same number of dimensions' + shape_len = list(shape_lens)[0] + dim = (dim + shape_len) if dim < 0 else dim + dims = list(zip(*map(lambda t: list(t.shape), tensors))) + expandable_dims = [(i, val) for i, val in enumerate(dims) if i != dim] + assert all([*map(lambda t: len(set(t[1])) <= 2, expandable_dims)]), 'invalid dimensions for broadcastable concatentation' + max_dims = list(map(lambda t: (t[0], max(t[1])), expandable_dims)) + expanded_dims = list(map(lambda t: (t[0], (t[1],) * num_tensors), max_dims)) + expanded_dims.insert(dim, (dim, dims[dim])) + expandable_shapes = list(zip(*map(lambda t: t[1], expanded_dims))) + tensors = list(map(lambda t: t[0].expand(*t[1]), zip(tensors, expandable_shapes))) + return torch.cat(tensors, dim = dim) + +def rotate_half(x): + x = rearrange(x, '... (d r) -> ... d r', r = 2) + x1, x2 = x.unbind(dim = -1) + x = torch.stack((-x2, x1), dim = -1) + return rearrange(x, '... d r -> ... (d r)') + + +class VisionRotaryEmbedding(nn.Module): + def __init__( + self, + dim, + pt_seq_len, + ft_seq_len=None, + custom_freqs = None, + freqs_for = 'lang', + theta = 10000, + max_freq = 10, + num_freqs = 1, + ): + super().__init__() + if custom_freqs: + freqs = custom_freqs + elif freqs_for == 'lang': + freqs = 1. / (theta ** (torch.arange(0, dim, 2)[:(dim // 2)].float() / dim)) + elif freqs_for == 'pixel': + freqs = torch.linspace(1., max_freq / 2, dim // 2) * pi + elif freqs_for == 'constant': + freqs = torch.ones(num_freqs).float() + else: + raise ValueError(f'unknown modality {freqs_for}') + + if ft_seq_len is None: ft_seq_len = pt_seq_len + t = torch.arange(ft_seq_len) / ft_seq_len * pt_seq_len + + freqs_h = torch.einsum('..., f -> ... f', t, freqs) + freqs_h = repeat(freqs_h, '... n -> ... (n r)', r = 2) + + freqs_w = torch.einsum('..., f -> ... f', t, freqs) + freqs_w = repeat(freqs_w, '... n -> ... (n r)', r = 2) + + freqs = broadcat((freqs_h[:, None, :], freqs_w[None, :, :]), dim = -1) + + self.register_buffer("freqs_cos", freqs.cos()) + self.register_buffer("freqs_sin", freqs.sin()) + + logging.info(f'Shape of rope freq: {self.freqs_cos.shape}') + + def forward(self, t, start_index = 0): + rot_dim = self.freqs_cos.shape[-1] + end_index = start_index + rot_dim + assert rot_dim <= t.shape[-1], f'feature dimension {t.shape[-1]} is not of sufficient size to rotate in all the positions {rot_dim}' + t_left, t, t_right = t[..., :start_index], t[..., start_index:end_index], t[..., end_index:] + t = (t * self.freqs_cos) + (rotate_half(t) * self.freqs_sin) + + return torch.cat((t_left, t, t_right), dim = -1) + +class VisionRotaryEmbeddingFast(nn.Module): + def __init__( + self, + dim, + pt_seq_len, + ft_seq_len=None, + custom_freqs = None, + freqs_for = 'lang', + theta = 10000, + max_freq = 10, + num_freqs = 1, + patch_dropout = 0. + ): + super().__init__() + if custom_freqs: + freqs = custom_freqs + elif freqs_for == 'lang': + freqs = 1. / (theta ** (torch.arange(0, dim, 2)[:(dim // 2)].float() / dim)) + elif freqs_for == 'pixel': + freqs = torch.linspace(1., max_freq / 2, dim // 2) * pi + elif freqs_for == 'constant': + freqs = torch.ones(num_freqs).float() + else: + raise ValueError(f'unknown modality {freqs_for}') + + if ft_seq_len is None: ft_seq_len = pt_seq_len + t = torch.arange(ft_seq_len) / ft_seq_len * pt_seq_len + + freqs = torch.einsum('..., f -> ... f', t, freqs) + freqs = repeat(freqs, '... n -> ... (n r)', r = 2) + freqs = broadcat((freqs[:, None, :], freqs[None, :, :]), dim = -1) + + freqs_cos = freqs.cos().view(-1, freqs.shape[-1]) + freqs_sin = freqs.sin().view(-1, freqs.shape[-1]) + + self.patch_dropout = patch_dropout + + self.register_buffer("freqs_cos", freqs_cos) + self.register_buffer("freqs_sin", freqs_sin) + + logging.info(f'Shape of rope freq: {self.freqs_cos.shape}') + + def forward(self, t, patch_indices_keep=None): + if patch_indices_keep is not None: + batch = t.size()[0] + batch_indices = torch.arange(batch) + batch_indices = batch_indices[..., None] + + freqs_cos = repeat(self.freqs_cos, 'i j -> n i m j', n=t.shape[0], m=t.shape[1]) + freqs_sin = repeat(self.freqs_sin, 'i j -> n i m j', n=t.shape[0], m=t.shape[1]) + + freqs_cos = freqs_cos[batch_indices, patch_indices_keep] + freqs_cos = rearrange(freqs_cos, 'n i m j -> n m i j') + freqs_sin = freqs_sin[batch_indices, patch_indices_keep] + freqs_sin = rearrange(freqs_sin, 'n i m j -> n m i j') + + return t * freqs_cos + rotate_half(t) * freqs_sin + + return t * self.freqs_cos + rotate_half(t) * self.freqs_sin \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/eva_clip/timm_model.py b/code/C3/visual_bge/visual_bge/eva_clip/timm_model.py new file mode 100644 index 0000000..b58122c --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/timm_model.py @@ -0,0 +1,122 @@ +""" timm model adapter + +Wraps timm (https://github.com/rwightman/pytorch-image-models) models for use as a vision tower in CLIP model. +""" +import logging +from collections import OrderedDict + +import torch +import torch.nn as nn + +try: + import timm + from timm.models.layers import Mlp, to_2tuple + try: + # old timm imports < 0.8.1 + from timm.models.layers.attention_pool2d import RotAttentionPool2d + from timm.models.layers.attention_pool2d import AttentionPool2d as AbsAttentionPool2d + except ImportError: + # new timm imports >= 0.8.1 + from timm.layers import RotAttentionPool2d + from timm.layers import AttentionPool2d as AbsAttentionPool2d +except ImportError: + timm = None + +from .utils import freeze_batch_norm_2d + + +class TimmModel(nn.Module): + """ timm model adapter + # FIXME this adapter is a work in progress, may change in ways that break weight compat + """ + + def __init__( + self, + model_name, + embed_dim, + image_size=224, + pool='avg', + proj='linear', + proj_bias=False, + drop=0., + pretrained=False): + super().__init__() + if timm is None: + raise RuntimeError("Please `pip install timm` to use timm models.") + + self.image_size = to_2tuple(image_size) + self.trunk = timm.create_model(model_name, pretrained=pretrained) + feat_size = self.trunk.default_cfg.get('pool_size', None) + feature_ndim = 1 if not feat_size else 2 + if pool in ('abs_attn', 'rot_attn'): + assert feature_ndim == 2 + # if attn pooling used, remove both classifier and default pool + self.trunk.reset_classifier(0, global_pool='') + else: + # reset global pool if pool config set, otherwise leave as network default + reset_kwargs = dict(global_pool=pool) if pool else {} + self.trunk.reset_classifier(0, **reset_kwargs) + prev_chs = self.trunk.num_features + + head_layers = OrderedDict() + if pool == 'abs_attn': + head_layers['pool'] = AbsAttentionPool2d(prev_chs, feat_size=feat_size, out_features=embed_dim) + prev_chs = embed_dim + elif pool == 'rot_attn': + head_layers['pool'] = RotAttentionPool2d(prev_chs, out_features=embed_dim) + prev_chs = embed_dim + else: + assert proj, 'projection layer needed if non-attention pooling is used.' + + # NOTE attention pool ends with a projection layer, so proj should usually be set to '' if such pooling is used + if proj == 'linear': + head_layers['drop'] = nn.Dropout(drop) + head_layers['proj'] = nn.Linear(prev_chs, embed_dim, bias=proj_bias) + elif proj == 'mlp': + head_layers['mlp'] = Mlp(prev_chs, 2 * embed_dim, embed_dim, drop=drop, bias=(True, proj_bias)) + + self.head = nn.Sequential(head_layers) + + def lock(self, unlocked_groups=0, freeze_bn_stats=False): + """ lock modules + Args: + unlocked_groups (int): leave last n layer groups unlocked (default: 0) + """ + if not unlocked_groups: + # lock full model + for param in self.trunk.parameters(): + param.requires_grad = False + if freeze_bn_stats: + freeze_batch_norm_2d(self.trunk) + else: + # NOTE: partial freeze requires latest timm (master) branch and is subject to change + try: + # FIXME import here until API stable and in an official release + from timm.models.helpers import group_parameters, group_modules + except ImportError: + raise RuntimeError( + 'Please install latest timm `pip install git+https://github.com/rwightman/pytorch-image-models`') + matcher = self.trunk.group_matcher() + gparams = group_parameters(self.trunk, matcher) + max_layer_id = max(gparams.keys()) + max_layer_id = max_layer_id - unlocked_groups + for group_idx in range(max_layer_id + 1): + group = gparams[group_idx] + for param in group: + self.trunk.get_parameter(param).requires_grad = False + if freeze_bn_stats: + gmodules = group_modules(self.trunk, matcher, reverse=True) + gmodules = {k for k, v in gmodules.items() if v <= max_layer_id} + freeze_batch_norm_2d(self.trunk, gmodules) + + @torch.jit.ignore + def set_grad_checkpointing(self, enable=True): + try: + self.trunk.set_grad_checkpointing(enable) + except Exception as e: + logging.warning('grad checkpointing not supported for this timm image tower, continuing without...') + + def forward(self, x): + x = self.trunk(x) + x = self.head(x) + return x diff --git a/code/C3/visual_bge/visual_bge/eva_clip/tokenizer.py b/code/C3/visual_bge/visual_bge/eva_clip/tokenizer.py new file mode 100644 index 0000000..41482f8 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/tokenizer.py @@ -0,0 +1,201 @@ +""" CLIP tokenizer + +Copied from https://github.com/openai/CLIP. Originally MIT License, Copyright (c) 2021 OpenAI. +""" +import gzip +import html +import os +from functools import lru_cache +from typing import Union, List + +import ftfy +import regex as re +import torch + +# https://stackoverflow.com/q/62691279 +import os +os.environ["TOKENIZERS_PARALLELISM"] = "false" + + +@lru_cache() +def default_bpe(): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "bpe_simple_vocab_16e6.txt.gz") + + +@lru_cache() +def bytes_to_unicode(): + """ + Returns list of utf-8 byte and a corresponding list of unicode strings. + The reversible bpe codes work on unicode strings. + This means you need a large # of unicode characters in your vocab if you want to avoid UNKs. + When you're at something like a 10B token dataset you end up needing around 5K for decent coverage. + This is a signficant percentage of your normal, say, 32K bpe vocab. + To avoid that, we want lookup tables between utf-8 bytes and unicode strings. + And avoids mapping to whitespace/control characters the bpe code barfs on. + """ + bs = list(range(ord("!"), ord("~")+1))+list(range(ord("¡"), ord("¬")+1))+list(range(ord("®"), ord("ÿ")+1)) + cs = bs[:] + n = 0 + for b in range(2**8): + if b not in bs: + bs.append(b) + cs.append(2**8+n) + n += 1 + cs = [chr(n) for n in cs] + return dict(zip(bs, cs)) + + +def get_pairs(word): + """Return set of symbol pairs in a word. + Word is represented as tuple of symbols (symbols being variable-length strings). + """ + pairs = set() + prev_char = word[0] + for char in word[1:]: + pairs.add((prev_char, char)) + prev_char = char + return pairs + + +def basic_clean(text): + text = ftfy.fix_text(text) + text = html.unescape(html.unescape(text)) + return text.strip() + + +def whitespace_clean(text): + text = re.sub(r'\s+', ' ', text) + text = text.strip() + return text + + +class SimpleTokenizer(object): + def __init__(self, bpe_path: str = default_bpe(), special_tokens=None): + self.byte_encoder = bytes_to_unicode() + self.byte_decoder = {v: k for k, v in self.byte_encoder.items()} + merges = gzip.open(bpe_path).read().decode("utf-8").split('\n') + merges = merges[1:49152-256-2+1] + merges = [tuple(merge.split()) for merge in merges] + vocab = list(bytes_to_unicode().values()) + vocab = vocab + [v+'' for v in vocab] + for merge in merges: + vocab.append(''.join(merge)) + if not special_tokens: + special_tokens = ['', ''] + else: + special_tokens = ['', ''] + special_tokens + vocab.extend(special_tokens) + self.encoder = dict(zip(vocab, range(len(vocab)))) + self.decoder = {v: k for k, v in self.encoder.items()} + self.bpe_ranks = dict(zip(merges, range(len(merges)))) + self.cache = {t:t for t in special_tokens} + special = "|".join(special_tokens) + self.pat = re.compile(special + r"""|'s|'t|'re|'ve|'m|'ll|'d|[\p{L}]+|[\p{N}]|[^\s\p{L}\p{N}]+""", re.IGNORECASE) + + self.vocab_size = len(self.encoder) + self.all_special_ids = [self.encoder[t] for t in special_tokens] + + def bpe(self, token): + if token in self.cache: + return self.cache[token] + word = tuple(token[:-1]) + ( token[-1] + '',) + pairs = get_pairs(word) + + if not pairs: + return token+'' + + while True: + bigram = min(pairs, key = lambda pair: self.bpe_ranks.get(pair, float('inf'))) + if bigram not in self.bpe_ranks: + break + first, second = bigram + new_word = [] + i = 0 + while i < len(word): + try: + j = word.index(first, i) + new_word.extend(word[i:j]) + i = j + except: + new_word.extend(word[i:]) + break + + if word[i] == first and i < len(word)-1 and word[i+1] == second: + new_word.append(first+second) + i += 2 + else: + new_word.append(word[i]) + i += 1 + new_word = tuple(new_word) + word = new_word + if len(word) == 1: + break + else: + pairs = get_pairs(word) + word = ' '.join(word) + self.cache[token] = word + return word + + def encode(self, text): + bpe_tokens = [] + text = whitespace_clean(basic_clean(text)).lower() + for token in re.findall(self.pat, text): + token = ''.join(self.byte_encoder[b] for b in token.encode('utf-8')) + bpe_tokens.extend(self.encoder[bpe_token] for bpe_token in self.bpe(token).split(' ')) + return bpe_tokens + + def decode(self, tokens): + text = ''.join([self.decoder[token] for token in tokens]) + text = bytearray([self.byte_decoder[c] for c in text]).decode('utf-8', errors="replace").replace('', ' ') + return text + + +_tokenizer = SimpleTokenizer() + + +def tokenize(texts: Union[str, List[str]], context_length: int = 77) -> torch.LongTensor: + """ + Returns the tokenized representation of given input string(s) + + Parameters + ---------- + texts : Union[str, List[str]] + An input string or a list of input strings to tokenize + context_length : int + The context length to use; all CLIP models use 77 as the context length + + Returns + ------- + A two-dimensional tensor containing the resulting tokens, shape = [number of input strings, context_length] + """ + if isinstance(texts, str): + texts = [texts] + + sot_token = _tokenizer.encoder[""] + eot_token = _tokenizer.encoder[""] + all_tokens = [[sot_token] + _tokenizer.encode(text) + [eot_token] for text in texts] + result = torch.zeros(len(all_tokens), context_length, dtype=torch.long) + + for i, tokens in enumerate(all_tokens): + if len(tokens) > context_length: + tokens = tokens[:context_length] # Truncate + tokens[-1] = eot_token + result[i, :len(tokens)] = torch.tensor(tokens) + + return result + + +class HFTokenizer: + "HuggingFace tokenizer wrapper" + def __init__(self, tokenizer_name:str): + from transformers import AutoTokenizer + self.tokenizer = AutoTokenizer.from_pretrained(tokenizer_name) + + def __call__(self, texts:Union[str, List[str]], context_length:int=77) -> torch.Tensor: + # same cleaning as for default tokenizer, except lowercasing + # adding lower (for case-sensitive tokenizers) will make it more robust but less sensitive to nuance + if isinstance(texts, str): + texts = [texts] + texts = [whitespace_clean(basic_clean(text)) for text in texts] + input_ids = self.tokenizer(texts, return_tensors='pt', max_length=context_length, padding='max_length', truncation=True).input_ids + return input_ids diff --git a/code/C3/visual_bge/visual_bge/eva_clip/transform.py b/code/C3/visual_bge/visual_bge/eva_clip/transform.py new file mode 100644 index 0000000..39f3e4c --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/transform.py @@ -0,0 +1,103 @@ +from typing import Optional, Sequence, Tuple + +import torch +import torch.nn as nn +import torchvision.transforms.functional as F + +from torchvision.transforms import Normalize, Compose, RandomResizedCrop, InterpolationMode, ToTensor, Resize, \ + CenterCrop + +from .constants import OPENAI_DATASET_MEAN, OPENAI_DATASET_STD + + +class ResizeMaxSize(nn.Module): + + def __init__(self, max_size, interpolation=InterpolationMode.BICUBIC, fn='max', fill=0): + super().__init__() + if not isinstance(max_size, int): + raise TypeError(f"Size should be int. Got {type(max_size)}") + self.max_size = max_size + self.interpolation = interpolation + self.fn = min if fn == 'min' else min + self.fill = fill + + def forward(self, img): + if isinstance(img, torch.Tensor): + height, width = img.shape[:2] + else: + width, height = img.size + scale = self.max_size / float(max(height, width)) + if scale != 1.0: + new_size = tuple(round(dim * scale) for dim in (height, width)) + img = F.resize(img, new_size, self.interpolation) + pad_h = self.max_size - new_size[0] + pad_w = self.max_size - new_size[1] + img = F.pad(img, padding=[pad_w//2, pad_h//2, pad_w - pad_w//2, pad_h - pad_h//2], fill=self.fill) + return img + + +def _convert_to_rgb(image): + return image.convert('RGB') + + +# class CatGen(nn.Module): +# def __init__(self, num=4): +# self.num = num +# def mixgen_batch(image, text): +# batch_size = image.shape[0] +# index = np.random.permutation(batch_size) + +# cat_images = [] +# for i in range(batch_size): +# # image mixup +# image[i,:] = lam * image[i,:] + (1 - lam) * image[index[i],:] +# # text concat +# text[i] = tokenizer((str(text[i]) + " " + str(text[index[i]])))[0] +# text = torch.stack(text) +# return image, text + + +def image_transform( + image_size: int, + is_train: bool, + mean: Optional[Tuple[float, ...]] = None, + std: Optional[Tuple[float, ...]] = None, + resize_longest_max: bool = False, + fill_color: int = 0, +): + mean = mean or OPENAI_DATASET_MEAN + if not isinstance(mean, (list, tuple)): + mean = (mean,) * 3 + + std = std or OPENAI_DATASET_STD + if not isinstance(std, (list, tuple)): + std = (std,) * 3 + + if isinstance(image_size, (list, tuple)) and image_size[0] == image_size[1]: + # for square size, pass size as int so that Resize() uses aspect preserving shortest edge + image_size = image_size[0] + + normalize = Normalize(mean=mean, std=std) + if is_train: + return Compose([ + RandomResizedCrop(image_size, scale=(0.9, 1.0), interpolation=InterpolationMode.BICUBIC), + _convert_to_rgb, + ToTensor(), + normalize, + ]) + else: + if resize_longest_max: + transforms = [ + ResizeMaxSize(image_size, fill=fill_color) + ] + else: + transforms = [ + Resize(image_size, interpolation=InterpolationMode.BICUBIC), + CenterCrop(image_size), + ] + transforms.extend([ + _convert_to_rgb, + ToTensor(), + normalize, + ]) + return Compose(transforms) diff --git a/code/C3/visual_bge/visual_bge/eva_clip/transformer.py b/code/C3/visual_bge/visual_bge/eva_clip/transformer.py new file mode 100644 index 0000000..16fea47 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/transformer.py @@ -0,0 +1,737 @@ +import os +import logging +from collections import OrderedDict +import math +from typing import Callable, Optional, Sequence +import numpy as np +import torch +from torch import nn +from torch.nn import functional as F + +try: + from timm.models.layers import trunc_normal_ +except: + from timm.layers import trunc_normal_ + +from .rope import VisionRotaryEmbedding, VisionRotaryEmbeddingFast +from .utils import to_2tuple + +if os.getenv('ENV_TYPE') == 'deepspeed': + try: + import deepspeed + from deepspeed.runtime.activation_checkpointing.checkpointing import checkpoint + except: + print("Please 'pip install deepspeed'") + deepspeed = None + from torch.utils.checkpoint import checkpoint +else: + from torch.utils.checkpoint import checkpoint + +try: + import xformers.ops as xops +except ImportError: + xops = None + # print("Please 'pip install xformers'") + +class LayerNormFp32(nn.LayerNorm): + """Subclass torch's LayerNorm to handle fp16 (by casting to float32 and back).""" + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def forward(self, x: torch.Tensor): + output = F.layer_norm( + x.float(), + self.normalized_shape, + self.weight.float() if self.weight is not None else None, + self.bias.float() if self.bias is not None else None, + self.eps, + ) + return output.type_as(x) + + +class LayerNorm(nn.LayerNorm): + """Subclass torch's LayerNorm (with cast back to input dtype).""" + + def forward(self, x: torch.Tensor): + orig_type = x.dtype + x = F.layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps) + return x.to(orig_type) + +class QuickGELU(nn.Module): + # NOTE This is slower than nn.GELU or nn.SiLU and uses more GPU memory + def forward(self, x: torch.Tensor): + return x * torch.sigmoid(1.702 * x) + + +class LayerScale(nn.Module): + def __init__(self, dim, init_values=1e-5, inplace=False): + super().__init__() + self.inplace = inplace + self.gamma = nn.Parameter(init_values * torch.ones(dim)) + + def forward(self, x): + return x.mul_(self.gamma) if self.inplace else x * self.gamma + +class PatchDropout(nn.Module): + """ + https://arxiv.org/abs/2212.00794 + """ + + def __init__(self, prob, exclude_first_token=True): + super().__init__() + assert 0 <= prob < 1. + self.prob = prob + self.exclude_first_token = exclude_first_token # exclude CLS token + logging.info(f"os.getenv('RoPE')={os.getenv('RoPE')}") + + def forward(self, x): + if not self.training or self.prob == 0.: + return x + + if self.exclude_first_token: + cls_tokens, x = x[:, :1], x[:, 1:] + else: + cls_tokens = torch.jit.annotate(torch.Tensor, x[:, :1]) + + batch = x.size()[0] + num_tokens = x.size()[1] + + batch_indices = torch.arange(batch) + batch_indices = batch_indices[..., None] + + keep_prob = 1 - self.prob + num_patches_keep = max(1, int(num_tokens * keep_prob)) + + rand = torch.randn(batch, num_tokens) + patch_indices_keep = rand.topk(num_patches_keep, dim=-1).indices + + x = x[batch_indices, patch_indices_keep] + + if self.exclude_first_token: + x = torch.cat((cls_tokens, x), dim=1) + + if self.training and os.getenv('RoPE') == '1': + return x, patch_indices_keep + + return x + + +def _in_projection_packed( + q: torch.Tensor, + k: torch.Tensor, + v: torch.Tensor, + w: torch.Tensor, + b: Optional[torch.Tensor] = None, + ): + """ + https://github.com/pytorch/pytorch/blob/db2a237763eb8693a20788be94f8c192e762baa8/torch/nn/functional.py#L4726 + """ + E = q.size(-1) + if k is v: + if q is k: + # self-attention + return F.linear(q, w, b).chunk(3, dim=-1) + else: + # encoder-decoder attention + w_q, w_kv = w.split([E, E * 2]) + if b is None: + b_q = b_kv = None + else: + b_q, b_kv = b.split([E, E * 2]) + return (F.linear(q, w_q, b_q),) + F.linear(k, w_kv, b_kv).chunk(2, dim=-1) + else: + w_q, w_k, w_v = w.chunk(3) + if b is None: + b_q = b_k = b_v = None + else: + b_q, b_k, b_v = b.chunk(3) + return F.linear(q, w_q, b_q), F.linear(k, w_k, b_k), F.linear(v, w_v, b_v) + +class Attention(nn.Module): + def __init__( + self, + dim, + num_heads=8, + qkv_bias=True, + scaled_cosine=False, + scale_heads=False, + logit_scale_max=math.log(1. / 0.01), + attn_drop=0., + proj_drop=0., + xattn=False, + rope=False + ): + super().__init__() + self.scaled_cosine = scaled_cosine + self.scale_heads = scale_heads + assert dim % num_heads == 0, 'dim should be divisible by num_heads' + self.num_heads = num_heads + self.head_dim = dim // num_heads + self.scale = self.head_dim ** -0.5 + self.logit_scale_max = logit_scale_max + + # keeping in_proj in this form (instead of nn.Linear) to match weight scheme of original + self.in_proj_weight = nn.Parameter(torch.randn((dim * 3, dim)) * self.scale) + if qkv_bias: + self.in_proj_bias = nn.Parameter(torch.zeros(dim * 3)) + else: + self.in_proj_bias = None + + if self.scaled_cosine: + self.logit_scale = nn.Parameter(torch.log(10 * torch.ones((num_heads, 1, 1)))) + else: + self.logit_scale = None + self.attn_drop = nn.Dropout(attn_drop) + if self.scale_heads: + self.head_scale = nn.Parameter(torch.ones((num_heads, 1, 1))) + else: + self.head_scale = None + self.out_proj = nn.Linear(dim, dim) + self.out_drop = nn.Dropout(proj_drop) + self.xattn = xattn + self.xattn_drop = attn_drop + self.rope = rope + + def forward(self, x, attn_mask: Optional[torch.Tensor] = None): + L, N, C = x.shape + q, k, v = F.linear(x, self.in_proj_weight, self.in_proj_bias).chunk(3, dim=-1) + if self.xattn: + q = q.contiguous().view(L, N, self.num_heads, -1).transpose(0, 1) + k = k.contiguous().view(L, N, self.num_heads, -1).transpose(0, 1) + v = v.contiguous().view(L, N, self.num_heads, -1).transpose(0, 1) + + x = xops.memory_efficient_attention( + q, k, v, + p=self.xattn_drop, + scale=self.scale if self.logit_scale is None else None, + attn_bias=xops.LowerTriangularMask() if attn_mask is not None else None, + ) + else: + q = q.contiguous().view(L, N * self.num_heads, -1).transpose(0, 1) + k = k.contiguous().view(L, N * self.num_heads, -1).transpose(0, 1) + v = v.contiguous().view(L, N * self.num_heads, -1).transpose(0, 1) + + if self.logit_scale is not None: + attn = torch.bmm(F.normalize(q, dim=-1), F.normalize(k, dim=-1).transpose(-1, -2)) + logit_scale = torch.clamp(self.logit_scale, max=self.logit_scale_max).exp() + attn = attn.view(N, self.num_heads, L, L) * logit_scale + attn = attn.view(-1, L, L) + else: + q = q * self.scale + attn = torch.bmm(q, k.transpose(-1, -2)) + + if attn_mask is not None: + if attn_mask.dtype == torch.bool: + new_attn_mask = torch.zeros_like(attn_mask, dtype=q.dtype) + new_attn_mask.masked_fill_(attn_mask, float("-inf")) + attn_mask = new_attn_mask + attn += attn_mask + + attn = attn.softmax(dim=-1) + attn = self.attn_drop(attn) + + x = torch.bmm(attn, v) + + if self.head_scale is not None: + x = x.view(N, self.num_heads, L, C) * self.head_scale + x = x.view(-1, L, C) + x = x.transpose(0, 1).reshape(L, N, C) + x = self.out_proj(x) + x = self.out_drop(x) + return x + +class CustomAttention(nn.Module): + def __init__( + self, + dim, + num_heads=8, + qkv_bias=True, + scaled_cosine=True, + scale_heads=False, + logit_scale_max=math.log(1. / 0.01), + attn_drop=0., + proj_drop=0., + xattn=False + ): + super().__init__() + self.scaled_cosine = scaled_cosine + self.scale_heads = scale_heads + assert dim % num_heads == 0, 'dim should be divisible by num_heads' + self.num_heads = num_heads + self.head_dim = dim // num_heads + self.scale = self.head_dim ** -0.5 + self.logit_scale_max = logit_scale_max + + # keeping in_proj in this form (instead of nn.Linear) to match weight scheme of original + self.in_proj_weight = nn.Parameter(torch.randn((dim * 3, dim)) * self.scale) + if qkv_bias: + self.in_proj_bias = nn.Parameter(torch.zeros(dim * 3)) + else: + self.in_proj_bias = None + + if self.scaled_cosine: + self.logit_scale = nn.Parameter(torch.log(10 * torch.ones((num_heads, 1, 1)))) + else: + self.logit_scale = None + self.attn_drop = nn.Dropout(attn_drop) + if self.scale_heads: + self.head_scale = nn.Parameter(torch.ones((num_heads, 1, 1))) + else: + self.head_scale = None + self.out_proj = nn.Linear(dim, dim) + self.out_drop = nn.Dropout(proj_drop) + self.xattn = xattn + self.xattn_drop = attn_drop + + def forward(self, query: torch.Tensor, key: torch.Tensor, value: torch.Tensor, attn_mask: Optional[torch.Tensor] = None): + q, k, v = _in_projection_packed(query, key, value, self.in_proj_weight, self.in_proj_bias) + N_q, B_q, C_q = q.shape + N_k, B_k, C_k = k.shape + N_v, B_v, C_v = v.shape + if self.xattn: + # B, N, C -> B, N, num_heads, C + q = q.permute(1, 0, 2).reshape(B_q, N_q, self.num_heads, -1) + k = k.permute(1, 0, 2).reshape(B_k, N_k, self.num_heads, -1) + v = v.permute(1, 0, 2).reshape(B_v, N_v, self.num_heads, -1) + + x = xops.memory_efficient_attention( + q, k, v, + p=self.xattn_drop, + scale=self.scale if self.logit_scale is None else None, + attn_bias=xops.LowerTriangularMask() if attn_mask is not None else None + ) + else: + # B*H, L, C + q = q.contiguous().view(N_q, B_q * self.num_heads, -1).transpose(0, 1) + k = k.contiguous().view(N_k, B_k * self.num_heads, -1).transpose(0, 1) + v = v.contiguous().view(N_v, B_v * self.num_heads, -1).transpose(0, 1) + + if self.logit_scale is not None: + # B*H, N_q, N_k + attn = torch.bmm(F.normalize(q, dim=-1), F.normalize(k, dim=-1).transpose(-1, -2)) + logit_scale = torch.clamp(self.logit_scale, max=self.logit_scale_max).exp() + attn = attn.view(B_q, self.num_heads, N_q, N_k) * logit_scale + attn = attn.view(-1, N_q, N_k) + else: + q = q * self.scale + attn = torch.bmm(q, k.transpose(-1, -2)) + + if attn_mask is not None: + if attn_mask.dtype == torch.bool: + new_attn_mask = torch.zeros_like(attn_mask, dtype=q.dtype) + new_attn_mask.masked_fill_(attn_mask, float("-inf")) + attn_mask = new_attn_mask + attn += attn_mask + + attn = attn.softmax(dim=-1) + attn = self.attn_drop(attn) + + x = torch.bmm(attn, v) + + if self.head_scale is not None: + x = x.view(B_q, self.num_heads, N_q, C_q) * self.head_scale + x = x.view(-1, N_q, C_q) + x = x.transpose(0, 1).reshape(N_q, B_q, C_q) + x = self.out_proj(x) + x = self.out_drop(x) + return x + +class CustomResidualAttentionBlock(nn.Module): + def __init__( + self, + d_model: int, + n_head: int, + mlp_ratio: float = 4.0, + ls_init_value: float = None, + act_layer: Callable = nn.GELU, + norm_layer: Callable = LayerNorm, + scale_cosine_attn: bool = False, + scale_heads: bool = False, + scale_attn: bool = False, + scale_fc: bool = False, + cross_attn: bool = False, + xattn: bool = False, + ): + super().__init__() + + self.ln_1 = norm_layer(d_model) + self.ln_1_k = norm_layer(d_model) if cross_attn else self.ln_1 + self.ln_1_v = norm_layer(d_model) if cross_attn else self.ln_1 + self.attn = CustomAttention( + d_model, n_head, + qkv_bias=True, + attn_drop=0., + proj_drop=0., + scaled_cosine=scale_cosine_attn, + scale_heads=scale_heads, + xattn=xattn + ) + + self.ln_attn = norm_layer(d_model) if scale_attn else nn.Identity() + self.ls_1 = LayerScale(d_model, ls_init_value) if ls_init_value is not None else nn.Identity() + + self.ln_2 = norm_layer(d_model) + mlp_width = int(d_model * mlp_ratio) + self.mlp = nn.Sequential(OrderedDict([ + ("c_fc", nn.Linear(d_model, mlp_width)), + ('ln', norm_layer(mlp_width) if scale_fc else nn.Identity()), + ("gelu", act_layer()), + ("c_proj", nn.Linear(mlp_width, d_model)) + ])) + + self.ls_2 = LayerScale(d_model, ls_init_value) if ls_init_value is not None else nn.Identity() + + def forward(self, q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, attn_mask: Optional[torch.Tensor] = None): + q = q + self.ls_1(self.ln_attn(self.attn(self.ln_1(q), self.ln_1_k(k), self.ln_1_v(v), attn_mask=attn_mask))) + q = q + self.ls_2(self.mlp(self.ln_2(q))) + return q + +class CustomTransformer(nn.Module): + def __init__( + self, + width: int, + layers: int, + heads: int, + mlp_ratio: float = 4.0, + ls_init_value: float = None, + act_layer: Callable = nn.GELU, + norm_layer: Callable = LayerNorm, + scale_cosine_attn: bool = True, + scale_heads: bool = False, + scale_attn: bool = False, + scale_fc: bool = False, + cross_attn: bool = False, + xattn: bool = False, + ): + super().__init__() + self.width = width + self.layers = layers + self.grad_checkpointing = False + self.xattn = xattn + + self.resblocks = nn.ModuleList([ + CustomResidualAttentionBlock( + width, + heads, + mlp_ratio, + ls_init_value=ls_init_value, + act_layer=act_layer, + norm_layer=norm_layer, + scale_cosine_attn=scale_cosine_attn, + scale_heads=scale_heads, + scale_attn=scale_attn, + scale_fc=scale_fc, + cross_attn=cross_attn, + xattn=xattn) + for _ in range(layers) + ]) + + def get_cast_dtype(self) -> torch.dtype: + return self.resblocks[0].mlp.c_fc.weight.dtype + + def forward(self, q: torch.Tensor, k: torch.Tensor = None, v: torch.Tensor = None, attn_mask: Optional[torch.Tensor] = None): + if k is None and v is None: + k = v = q + for r in self.resblocks: + if self.grad_checkpointing and not torch.jit.is_scripting(): + q = checkpoint(r, q, k, v, attn_mask) + else: + q = r(q, k, v, attn_mask=attn_mask) + return q + + +class ResidualAttentionBlock(nn.Module): + def __init__( + self, + d_model: int, + n_head: int, + mlp_ratio: float = 4.0, + ls_init_value: float = None, + act_layer: Callable = nn.GELU, + norm_layer: Callable = LayerNorm, + xattn: bool = False, + ): + super().__init__() + + self.ln_1 = norm_layer(d_model) + if xattn: + self.attn = Attention(d_model, n_head, xattn=True) + else: + self.attn = nn.MultiheadAttention(d_model, n_head) + self.ls_1 = LayerScale(d_model, ls_init_value) if ls_init_value is not None else nn.Identity() + + self.ln_2 = norm_layer(d_model) + mlp_width = int(d_model * mlp_ratio) + self.mlp = nn.Sequential(OrderedDict([ + ("c_fc", nn.Linear(d_model, mlp_width)), + ("gelu", act_layer()), + ("c_proj", nn.Linear(mlp_width, d_model)) + ])) + + self.ls_2 = LayerScale(d_model, ls_init_value) if ls_init_value is not None else nn.Identity() + self.xattn = xattn + + def attention(self, x: torch.Tensor, attn_mask: Optional[torch.Tensor] = None): + attn_mask = attn_mask.to(x.dtype) if attn_mask is not None else None + if self.xattn: + return self.attn(x, attn_mask=attn_mask) + return self.attn(x, x, x, need_weights=False, attn_mask=attn_mask)[0] + + def forward(self, x: torch.Tensor, attn_mask: Optional[torch.Tensor] = None): + x = x + self.ls_1(self.attention(self.ln_1(x), attn_mask=attn_mask)) + x = x + self.ls_2(self.mlp(self.ln_2(x))) + return x + +class Transformer(nn.Module): + def __init__( + self, + width: int, + layers: int, + heads: int, + mlp_ratio: float = 4.0, + ls_init_value: float = None, + act_layer: Callable = nn.GELU, + norm_layer: Callable = LayerNorm, + xattn: bool = False, + ): + super().__init__() + self.width = width + self.layers = layers + self.grad_checkpointing = False + + self.resblocks = nn.ModuleList([ + ResidualAttentionBlock( + width, heads, mlp_ratio, ls_init_value=ls_init_value, act_layer=act_layer, norm_layer=norm_layer, xattn=xattn) + for _ in range(layers) + ]) + + def get_cast_dtype(self) -> torch.dtype: + return self.resblocks[0].mlp.c_fc.weight.dtype + + def forward(self, x: torch.Tensor, attn_mask: Optional[torch.Tensor] = None): + for r in self.resblocks: + if self.grad_checkpointing and not torch.jit.is_scripting(): + x = checkpoint(r, x, attn_mask) + else: + x = r(x, attn_mask=attn_mask) + return x + + +class VisionTransformer(nn.Module): + def __init__( + self, + image_size: int, + patch_size: int, + width: int, + layers: int, + heads: int, + mlp_ratio: float, + ls_init_value: float = None, + patch_dropout: float = 0., + global_average_pool: bool = False, + output_dim: int = 512, + act_layer: Callable = nn.GELU, + norm_layer: Callable = LayerNorm, + xattn: bool = False, + ): + super().__init__() + self.image_size = to_2tuple(image_size) + self.patch_size = to_2tuple(patch_size) + self.grid_size = (self.image_size[0] // self.patch_size[0], self.image_size[1] // self.patch_size[1]) + self.output_dim = output_dim + self.conv1 = nn.Conv2d(in_channels=3, out_channels=width, kernel_size=patch_size, stride=patch_size, bias=False) + + scale = width ** -0.5 + self.class_embedding = nn.Parameter(scale * torch.randn(width)) + self.positional_embedding = nn.Parameter(scale * torch.randn(self.grid_size[0] * self.grid_size[1] + 1, width)) + + # setting a patch_dropout of 0. would mean it is disabled and this function would be the identity fn + self.patch_dropout = PatchDropout(patch_dropout) if patch_dropout > 0. else nn.Identity() + self.ln_pre = norm_layer(width) + + self.transformer = Transformer( + width, + layers, + heads, + mlp_ratio, + ls_init_value=ls_init_value, + act_layer=act_layer, + norm_layer=norm_layer, + xattn=xattn + ) + + self.global_average_pool = global_average_pool + self.ln_post = norm_layer(width) + self.proj = nn.Parameter(scale * torch.randn(width, output_dim)) + + def lock(self, unlocked_groups=0, freeze_bn_stats=False): + for param in self.parameters(): + param.requires_grad = False + + if unlocked_groups != 0: + groups = [ + [ + self.conv1, + self.class_embedding, + self.positional_embedding, + self.ln_pre, + ], + *self.transformer.resblocks[:-1], + [ + self.transformer.resblocks[-1], + self.ln_post, + ], + self.proj, + ] + + def _unlock(x): + if isinstance(x, Sequence): + for g in x: + _unlock(g) + else: + if isinstance(x, torch.nn.Parameter): + x.requires_grad = True + else: + for p in x.parameters(): + p.requires_grad = True + + _unlock(groups[-unlocked_groups:]) + + def get_num_layers(self): + return self.transformer.layers + + @torch.jit.ignore + def set_grad_checkpointing(self, enable=True): + self.transformer.grad_checkpointing = enable + + @torch.jit.ignore + def no_weight_decay(self): + return {'positional_embedding', 'class_embedding'} + + def forward(self, x: torch.Tensor, return_all_features: bool=False): + x = self.conv1(x) # shape = [*, width, grid, grid] + x = x.reshape(x.shape[0], x.shape[1], -1) # shape = [*, width, grid ** 2] + x = x.permute(0, 2, 1) # shape = [*, grid ** 2, width] + x = torch.cat( + [self.class_embedding.to(x.dtype) + torch.zeros(x.shape[0], 1, x.shape[-1], dtype=x.dtype, device=x.device), + x], dim=1) # shape = [*, grid ** 2 + 1, width] + x = x + self.positional_embedding.to(x.dtype) + + # a patch_dropout of 0. would mean it is disabled and this function would do nothing but return what was passed in + x = self.patch_dropout(x) + x = self.ln_pre(x) + + x = x.permute(1, 0, 2) # NLD -> LND + x = self.transformer(x) + x = x.permute(1, 0, 2) # LND -> NLD + + if not return_all_features: + if self.global_average_pool: + x = x.mean(dim=1) #x = x[:,1:,:].mean(dim=1) + else: + x = x[:, 0] + + x = self.ln_post(x) + + if self.proj is not None: + x = x @ self.proj + + return x + + +class TextTransformer(nn.Module): + def __init__( + self, + context_length: int = 77, + vocab_size: int = 49408, + width: int = 512, + heads: int = 8, + layers: int = 12, + ls_init_value: float = None, + output_dim: int = 512, + act_layer: Callable = nn.GELU, + norm_layer: Callable = LayerNorm, + xattn: bool= False, + attn_mask: bool = True + ): + super().__init__() + self.context_length = context_length + self.vocab_size = vocab_size + self.width = width + self.output_dim = output_dim + + self.token_embedding = nn.Embedding(vocab_size, width) + self.positional_embedding = nn.Parameter(torch.empty(self.context_length, width)) + self.transformer = Transformer( + width=width, + layers=layers, + heads=heads, + ls_init_value=ls_init_value, + act_layer=act_layer, + norm_layer=norm_layer, + xattn=xattn + ) + + self.xattn = xattn + self.ln_final = norm_layer(width) + self.text_projection = nn.Parameter(torch.empty(width, output_dim)) + + if attn_mask: + self.register_buffer('attn_mask', self.build_attention_mask(), persistent=False) + else: + self.attn_mask = None + + self.init_parameters() + + def init_parameters(self): + nn.init.normal_(self.token_embedding.weight, std=0.02) + nn.init.normal_(self.positional_embedding, std=0.01) + + proj_std = (self.transformer.width ** -0.5) * ((2 * self.transformer.layers) ** -0.5) + attn_std = self.transformer.width ** -0.5 + fc_std = (2 * self.transformer.width) ** -0.5 + for block in self.transformer.resblocks: + nn.init.normal_(block.attn.in_proj_weight, std=attn_std) + nn.init.normal_(block.attn.out_proj.weight, std=proj_std) + nn.init.normal_(block.mlp.c_fc.weight, std=fc_std) + nn.init.normal_(block.mlp.c_proj.weight, std=proj_std) + + if self.text_projection is not None: + nn.init.normal_(self.text_projection, std=self.transformer.width ** -0.5) + + @torch.jit.ignore + def set_grad_checkpointing(self, enable=True): + self.transformer.grad_checkpointing = enable + + @torch.jit.ignore + def no_weight_decay(self): + # return {'positional_embedding', 'token_embedding'} + return {'positional_embedding'} + + def get_num_layers(self): + return self.transformer.layers + + def build_attention_mask(self): + # lazily create causal attention mask, with full attention between the vision tokens + # pytorch uses additive attention mask; fill with -inf + mask = torch.empty(self.context_length, self.context_length) + mask.fill_(float("-inf")) + mask.triu_(1) # zero out the lower diagonal + return mask + + def forward(self, text, return_all_features: bool=False): + cast_dtype = self.transformer.get_cast_dtype() + x = self.token_embedding(text).to(cast_dtype) # [batch_size, n_ctx, d_model] + + x = x + self.positional_embedding.to(cast_dtype) + x = x.permute(1, 0, 2) # NLD -> LND + x = self.transformer(x, attn_mask=self.attn_mask) + # x = self.transformer(x) # no attention mask is applied + x = x.permute(1, 0, 2) # LND -> NLD + x = self.ln_final(x) + + if not return_all_features: + # x.shape = [batch_size, n_ctx, transformer.width] + # take features from the eot embedding (eot_token is the highest number in each sequence) + x = x[torch.arange(x.shape[0]), text.argmax(dim=-1)] @ self.text_projection + return x diff --git a/code/C3/visual_bge/visual_bge/eva_clip/utils.py b/code/C3/visual_bge/visual_bge/eva_clip/utils.py new file mode 100644 index 0000000..bdc5a7a --- /dev/null +++ b/code/C3/visual_bge/visual_bge/eva_clip/utils.py @@ -0,0 +1,326 @@ +from itertools import repeat +import collections.abc +import logging +import math +import numpy as np + +import torch +from torch import nn as nn +from torchvision.ops.misc import FrozenBatchNorm2d +import torch.nn.functional as F + +# open CLIP +def resize_clip_pos_embed(state_dict, model, interpolation: str = 'bicubic', seq_dim=1): + # Rescale the grid of position embeddings when loading from state_dict + old_pos_embed = state_dict.get('visual.positional_embedding', None) + if old_pos_embed is None or not hasattr(model.visual, 'grid_size'): + return + grid_size = to_2tuple(model.visual.grid_size) + extra_tokens = 1 # FIXME detect different token configs (ie no class token, or more) + new_seq_len = grid_size[0] * grid_size[1] + extra_tokens + if new_seq_len == old_pos_embed.shape[0]: + return + + if extra_tokens: + pos_emb_tok, pos_emb_img = old_pos_embed[:extra_tokens], old_pos_embed[extra_tokens:] + else: + pos_emb_tok, pos_emb_img = None, old_pos_embed + old_grid_size = to_2tuple(int(math.sqrt(len(pos_emb_img)))) + + logging.info('Resizing position embedding grid-size from %s to %s', old_grid_size, grid_size) + pos_emb_img = pos_emb_img.reshape(1, old_grid_size[0], old_grid_size[1], -1).permute(0, 3, 1, 2) + pos_emb_img = F.interpolate( + pos_emb_img, + size=grid_size, + mode=interpolation, + align_corners=True, + ) + pos_emb_img = pos_emb_img.permute(0, 2, 3, 1).reshape(1, grid_size[0] * grid_size[1], -1)[0] + if pos_emb_tok is not None: + new_pos_embed = torch.cat([pos_emb_tok, pos_emb_img], dim=0) + else: + new_pos_embed = pos_emb_img + state_dict['visual.positional_embedding'] = new_pos_embed + + +def resize_visual_pos_embed(state_dict, model, interpolation: str = 'bicubic', seq_dim=1): + # Rescale the grid of position embeddings when loading from state_dict + old_pos_embed = state_dict.get('positional_embedding', None) + if old_pos_embed is None or not hasattr(model.visual, 'grid_size'): + return + grid_size = to_2tuple(model.visual.grid_size) + extra_tokens = 1 # FIXME detect different token configs (ie no class token, or more) + new_seq_len = grid_size[0] * grid_size[1] + extra_tokens + if new_seq_len == old_pos_embed.shape[0]: + return + + if extra_tokens: + pos_emb_tok, pos_emb_img = old_pos_embed[:extra_tokens], old_pos_embed[extra_tokens:] + else: + pos_emb_tok, pos_emb_img = None, old_pos_embed + old_grid_size = to_2tuple(int(math.sqrt(len(pos_emb_img)))) + + logging.info('Resizing position embedding grid-size from %s to %s', old_grid_size, grid_size) + pos_emb_img = pos_emb_img.reshape(1, old_grid_size[0], old_grid_size[1], -1).permute(0, 3, 1, 2) + pos_emb_img = F.interpolate( + pos_emb_img, + size=grid_size, + mode=interpolation, + align_corners=True, + ) + pos_emb_img = pos_emb_img.permute(0, 2, 3, 1).reshape(1, grid_size[0] * grid_size[1], -1)[0] + if pos_emb_tok is not None: + new_pos_embed = torch.cat([pos_emb_tok, pos_emb_img], dim=0) + else: + new_pos_embed = pos_emb_img + state_dict['positional_embedding'] = new_pos_embed + +def resize_evaclip_pos_embed(state_dict, model, interpolation: str = 'bicubic', seq_dim=1): + all_keys = list(state_dict.keys()) + # interpolate position embedding + if 'visual.pos_embed' in state_dict: + pos_embed_checkpoint = state_dict['visual.pos_embed'] + embedding_size = pos_embed_checkpoint.shape[-1] + num_patches = model.visual.patch_embed.num_patches + num_extra_tokens = model.visual.pos_embed.shape[-2] - num_patches + # height (== width) for the checkpoint position embedding + orig_size = int((pos_embed_checkpoint.shape[-2] - num_extra_tokens) ** 0.5) + # height (== width) for the new position embedding + new_size = int(num_patches ** 0.5) + # class_token and dist_token are kept unchanged + if orig_size != new_size: + print("Position interpolate from %dx%d to %dx%d" % (orig_size, orig_size, new_size, new_size)) + extra_tokens = pos_embed_checkpoint[:, :num_extra_tokens] + # only the position tokens are interpolated + pos_tokens = pos_embed_checkpoint[:, num_extra_tokens:] + pos_tokens = pos_tokens.reshape(-1, orig_size, orig_size, embedding_size).permute(0, 3, 1, 2) + pos_tokens = torch.nn.functional.interpolate( + pos_tokens, size=(new_size, new_size), mode='bicubic', align_corners=False) + pos_tokens = pos_tokens.permute(0, 2, 3, 1).flatten(1, 2) + new_pos_embed = torch.cat((extra_tokens, pos_tokens), dim=1) + state_dict['visual.pos_embed'] = new_pos_embed + + patch_embed_proj = state_dict['visual.patch_embed.proj.weight'] + patch_size = model.visual.patch_embed.patch_size + state_dict['visual.patch_embed.proj.weight'] = torch.nn.functional.interpolate( + patch_embed_proj.float(), size=patch_size, mode='bicubic', align_corners=False) + + +def resize_eva_pos_embed(state_dict, model, interpolation: str = 'bicubic', seq_dim=1): + all_keys = list(state_dict.keys()) + # interpolate position embedding + if 'pos_embed' in state_dict: + pos_embed_checkpoint = state_dict['pos_embed'] + embedding_size = pos_embed_checkpoint.shape[-1] + num_patches = model.visual.patch_embed.num_patches + num_extra_tokens = model.visual.pos_embed.shape[-2] - num_patches + # height (== width) for the checkpoint position embedding + orig_size = int((pos_embed_checkpoint.shape[-2] - num_extra_tokens) ** 0.5) + # height (== width) for the new position embedding + new_size = int(num_patches ** 0.5) + # class_token and dist_token are kept unchanged + if orig_size != new_size: + print("Position interpolate from %dx%d to %dx%d" % (orig_size, orig_size, new_size, new_size)) + extra_tokens = pos_embed_checkpoint[:, :num_extra_tokens] + # only the position tokens are interpolated + pos_tokens = pos_embed_checkpoint[:, num_extra_tokens:] + pos_tokens = pos_tokens.reshape(-1, orig_size, orig_size, embedding_size).permute(0, 3, 1, 2) + pos_tokens = torch.nn.functional.interpolate( + pos_tokens, size=(new_size, new_size), mode='bicubic', align_corners=False) + pos_tokens = pos_tokens.permute(0, 2, 3, 1).flatten(1, 2) + new_pos_embed = torch.cat((extra_tokens, pos_tokens), dim=1) + state_dict['pos_embed'] = new_pos_embed + + patch_embed_proj = state_dict['patch_embed.proj.weight'] + patch_size = model.visual.patch_embed.patch_size + state_dict['patch_embed.proj.weight'] = torch.nn.functional.interpolate( + patch_embed_proj.float(), size=patch_size, mode='bicubic', align_corners=False) + + +def resize_rel_pos_embed(state_dict, model, interpolation: str = 'bicubic', seq_dim=1): + all_keys = list(state_dict.keys()) + for key in all_keys: + if "relative_position_index" in key: + state_dict.pop(key) + + if "relative_position_bias_table" in key: + rel_pos_bias = state_dict[key] + src_num_pos, num_attn_heads = rel_pos_bias.size() + dst_num_pos, _ = model.visual.state_dict()[key].size() + dst_patch_shape = model.visual.patch_embed.patch_shape + if dst_patch_shape[0] != dst_patch_shape[1]: + raise NotImplementedError() + num_extra_tokens = dst_num_pos - (dst_patch_shape[0] * 2 - 1) * (dst_patch_shape[1] * 2 - 1) + src_size = int((src_num_pos - num_extra_tokens) ** 0.5) + dst_size = int((dst_num_pos - num_extra_tokens) ** 0.5) + if src_size != dst_size: + print("Position interpolate for %s from %dx%d to %dx%d" % ( + key, src_size, src_size, dst_size, dst_size)) + extra_tokens = rel_pos_bias[-num_extra_tokens:, :] + rel_pos_bias = rel_pos_bias[:-num_extra_tokens, :] + + def geometric_progression(a, r, n): + return a * (1.0 - r ** n) / (1.0 - r) + + left, right = 1.01, 1.5 + while right - left > 1e-6: + q = (left + right) / 2.0 + gp = geometric_progression(1, q, src_size // 2) + if gp > dst_size // 2: + right = q + else: + left = q + + # if q > 1.090307: + # q = 1.090307 + + dis = [] + cur = 1 + for i in range(src_size // 2): + dis.append(cur) + cur += q ** (i + 1) + + r_ids = [-_ for _ in reversed(dis)] + + x = r_ids + [0] + dis + y = r_ids + [0] + dis + + t = dst_size // 2.0 + dx = np.arange(-t, t + 0.1, 1.0) + dy = np.arange(-t, t + 0.1, 1.0) + + print("Original positions = %s" % str(x)) + print("Target positions = %s" % str(dx)) + + all_rel_pos_bias = [] + + for i in range(num_attn_heads): + z = rel_pos_bias[:, i].view(src_size, src_size).float().numpy() + f = F.interpolate.interp2d(x, y, z, kind='cubic') + all_rel_pos_bias.append( + torch.Tensor(f(dx, dy)).contiguous().view(-1, 1).to(rel_pos_bias.device)) + + rel_pos_bias = torch.cat(all_rel_pos_bias, dim=-1) + + new_rel_pos_bias = torch.cat((rel_pos_bias, extra_tokens), dim=0) + state_dict[key] = new_rel_pos_bias + + # interpolate position embedding + if 'pos_embed' in state_dict: + pos_embed_checkpoint = state_dict['pos_embed'] + embedding_size = pos_embed_checkpoint.shape[-1] + num_patches = model.visual.patch_embed.num_patches + num_extra_tokens = model.visual.pos_embed.shape[-2] - num_patches + # height (== width) for the checkpoint position embedding + orig_size = int((pos_embed_checkpoint.shape[-2] - num_extra_tokens) ** 0.5) + # height (== width) for the new position embedding + new_size = int(num_patches ** 0.5) + # class_token and dist_token are kept unchanged + if orig_size != new_size: + print("Position interpolate from %dx%d to %dx%d" % (orig_size, orig_size, new_size, new_size)) + extra_tokens = pos_embed_checkpoint[:, :num_extra_tokens] + # only the position tokens are interpolated + pos_tokens = pos_embed_checkpoint[:, num_extra_tokens:] + pos_tokens = pos_tokens.reshape(-1, orig_size, orig_size, embedding_size).permute(0, 3, 1, 2) + pos_tokens = torch.nn.functional.interpolate( + pos_tokens, size=(new_size, new_size), mode='bicubic', align_corners=False) + pos_tokens = pos_tokens.permute(0, 2, 3, 1).flatten(1, 2) + new_pos_embed = torch.cat((extra_tokens, pos_tokens), dim=1) + state_dict['pos_embed'] = new_pos_embed + + patch_embed_proj = state_dict['patch_embed.proj.weight'] + patch_size = model.visual.patch_embed.patch_size + state_dict['patch_embed.proj.weight'] = torch.nn.functional.interpolate( + patch_embed_proj.float(), size=patch_size, mode='bicubic', align_corners=False) + + +def freeze_batch_norm_2d(module, module_match={}, name=''): + """ + Converts all `BatchNorm2d` and `SyncBatchNorm` layers of provided module into `FrozenBatchNorm2d`. If `module` is + itself an instance of either `BatchNorm2d` or `SyncBatchNorm`, it is converted into `FrozenBatchNorm2d` and + returned. Otherwise, the module is walked recursively and submodules are converted in place. + + Args: + module (torch.nn.Module): Any PyTorch module. + module_match (dict): Dictionary of full module names to freeze (all if empty) + name (str): Full module name (prefix) + + Returns: + torch.nn.Module: Resulting module + + Inspired by https://github.com/pytorch/pytorch/blob/a5895f85be0f10212791145bfedc0261d364f103/torch/nn/modules/batchnorm.py#L762 + """ + res = module + is_match = True + if module_match: + is_match = name in module_match + if is_match and isinstance(module, (nn.modules.batchnorm.BatchNorm2d, nn.modules.batchnorm.SyncBatchNorm)): + res = FrozenBatchNorm2d(module.num_features) + res.num_features = module.num_features + res.affine = module.affine + if module.affine: + res.weight.data = module.weight.data.clone().detach() + res.bias.data = module.bias.data.clone().detach() + res.running_mean.data = module.running_mean.data + res.running_var.data = module.running_var.data + res.eps = module.eps + else: + for child_name, child in module.named_children(): + full_child_name = '.'.join([name, child_name]) if name else child_name + new_child = freeze_batch_norm_2d(child, module_match, full_child_name) + if new_child is not child: + res.add_module(child_name, new_child) + return res + + +# From PyTorch internals +def _ntuple(n): + def parse(x): + if isinstance(x, collections.abc.Iterable): + return x + return tuple(repeat(x, n)) + return parse + + +to_1tuple = _ntuple(1) +to_2tuple = _ntuple(2) +to_3tuple = _ntuple(3) +to_4tuple = _ntuple(4) +to_ntuple = lambda n, x: _ntuple(n)(x) + + +def is_logging(args): + def is_global_master(args): + return args.rank == 0 + + def is_local_master(args): + return args.local_rank == 0 + + def is_master(args, local=False): + return is_local_master(args) if local else is_global_master(args) + return is_master + + +class AllGather(torch.autograd.Function): + """An autograd function that performs allgather on a tensor. + Performs all_gather operation on the provided tensors. + *** Warning ***: torch.distributed.all_gather has no gradient. + """ + + @staticmethod + def forward(ctx, tensor, rank, world_size): + tensors_gather = [torch.empty_like(tensor) for _ in range(world_size)] + torch.distributed.all_gather(tensors_gather, tensor) + ctx.rank = rank + ctx.batch_size = tensor.shape[0] + return torch.cat(tensors_gather, 0) + + @staticmethod + def backward(ctx, grad_output): + return ( + grad_output[ctx.batch_size * ctx.rank: ctx.batch_size * (ctx.rank + 1)], + None, + None + ) + +allgather = AllGather.apply \ No newline at end of file diff --git a/code/C3/visual_bge/visual_bge/modeling.py b/code/C3/visual_bge/visual_bge/modeling.py new file mode 100644 index 0000000..639c350 --- /dev/null +++ b/code/C3/visual_bge/visual_bge/modeling.py @@ -0,0 +1,378 @@ +import os +import logging +from dataclasses import dataclass +from typing import Optional, Tuple +import torch +import torch.distributed as dist +from torch import nn, Tensor +from transformers import AutoModel, AutoTokenizer, AutoConfig +from transformers.file_utils import ModelOutput + + +from .eva_clip import create_eva_vision_and_transforms +from PIL import Image + +logger = logging.getLogger(__name__) + + +@dataclass +class EncoderOutput(ModelOutput): + q_reps: Optional[Tensor] = None + c_reps: Optional[Tensor] = None + loss: Optional[Tensor] = None + scores: Optional[Tensor] = None + + +class Visualized_BGE(nn.Module): + def __init__(self, + model_name_bge: str = None, + model_weight = None, # "/path/to/your/weight/file/" + normlized: bool = True, + sentence_pooling_method: str = 'cls', + negatives_cross_device: bool = False, + temperature: float = 0.02, # 1.0 + from_pretrained=None, # local config file and model + ): + super().__init__() + + assert 'bge' in model_name_bge + assert model_weight is not None + + self.model_name_bge = model_name_bge + + if 'bge-base-en-v1.5' in model_name_bge: + model_name_eva = "EVA02-CLIP-B-16" + self.hidden_dim = 768 + self.depth = 12 + elif 'bge-m3' in model_name_bge: + model_name_eva = "EVA02-CLIP-L-14" + self.hidden_dim = 1024 + self.depth = 24 + else: + raise Exception(f'Unavailable model_name {model_name_bge}') + + if not from_pretrained: + bge_config = AutoConfig.from_pretrained(model_name_bge) + bge = AutoModel.from_config(bge_config) + else: + print("Loading from local path.") + bge_config = AutoConfig.from_pretrained(from_pretrained, local_files_only=True) + bge = AutoModel.from_config(bge_config) + + self.bge_encoder = bge.encoder + self.bge_embeddings = bge.embeddings + self.bge_pooler = bge.pooler + + self.model_visual, self.preprocess_train, self.preprocess_val= create_eva_vision_and_transforms( + model_name_eva, + force_custom_clip=True) + + + self.visual_proj = nn.Linear(self.hidden_dim, self.hidden_dim) + + + self.cross_entropy = nn.CrossEntropyLoss(reduction='mean') + + self.normlized = normlized + self.sentence_pooling_method = sentence_pooling_method + self.temperature = temperature + if not normlized: + self.temperature = 1.0 + logger.info("reset temperature = 1.0 due to using inner product to compute similarity") + + self.negatives_cross_device = negatives_cross_device + if self.negatives_cross_device: + if not dist.is_initialized(): + raise ValueError('Distributed training has not been initialized for representation all gather.') + + self.process_rank = dist.get_rank() + self.world_size = dist.get_world_size() + + self.load_model(model_weight) + + if not from_pretrained: + self.tokenizer = AutoTokenizer.from_pretrained(model_name_bge, use_fast=False) + else: + self.tokenizer = AutoTokenizer.from_pretrained(from_pretrained, use_fast=False) + + if torch.cuda.is_available(): + self.device = torch.device('cuda') + self.to(self.device) + else: + self.device = torch.device('cpu') + self.dtype = next(bge.parameters()).dtype + + def load_model(self, model_weight): + self.load_state_dict(torch.load(model_weight, map_location='cpu')) + + def gradient_checkpointing_enable(self, **kwargs): + # self.bge_encoder.gradient_checkpointing_enable() + self.model_visual.set_grad_checkpointing(True) + + + + def encode(self, image=None, text=None): + # used for simple inference + if image is not None: + image = self.preprocess_val(Image.open(image)).unsqueeze(0) + + if text is not None: + text = self.tokenizer(text, return_tensors="pt", padding=True) + return self.encode_mm(image.to(self.device), text.to(self.device)) + else: + return self.encode_image(image.to(self.device)) + else: + if text is not None: + text = self.tokenizer(text, return_tensors="pt", padding=True) + return self.encode_text(text.to(self.device)) + else: + return None + + + def get_extended_attention_mask( + self, attention_mask: Tensor, input_shape: Tuple[int], device: torch.device = None, dtype: torch.float = torch.float16 + ) -> Tensor: + """ + Makes broadcastable attention and causal masks so that future and masked tokens are ignored. + + Arguments: + attention_mask (`torch.Tensor`): + Mask with ones indicating tokens to attend to, zeros for tokens to ignore. + input_shape (`Tuple[int]`): + The shape of the input to the model. + + Returns: + `torch.Tensor` The extended attention mask, with a the same dtype as `attention_mask.dtype`. + """ + + # We can provide a self-attention mask of dimensions [batch_size, from_seq_length, to_seq_length] + # ourselves in which case we just need to make it broadcastable to all heads. + if attention_mask.dim() == 3: + extended_attention_mask = attention_mask[:, None, :, :] + elif attention_mask.dim() == 2: + # Provided a padding mask of dimensions [batch_size, seq_length] + # - if the model is a decoder, apply a causal mask in addition to the padding mask + # - if the model is an encoder, make the mask broadcastable to [batch_size, num_heads, seq_length, seq_length] + + extended_attention_mask = attention_mask[:, None, None, :] + else: + raise ValueError( + f"Wrong shape for input_ids (shape {input_shape}) or attention_mask (shape {attention_mask.shape})" + ) + + # Since attention_mask is 1.0 for positions we want to attend and 0.0 for + # masked positions, this operation will create a tensor which is 0.0 for + # positions we want to attend and the dtype's smallest value for masked positions. + # Since we are adding it to the raw scores before the softmax, this is + # effectively the same as removing these entirely. + extended_attention_mask = extended_attention_mask.to(dtype=dtype) # fp16 compatibility + extended_attention_mask = (1.0 - extended_attention_mask) * torch.finfo(dtype).min + + return extended_attention_mask + + def sentence_embedding(self, hidden_state, mask): + if self.sentence_pooling_method == 'mean': + s = torch.sum(hidden_state * mask.unsqueeze(-1).float(), dim=1) + d = mask.sum(axis=1, keepdim=True).float() + return s / d + elif self.sentence_pooling_method == 'cls': + return hidden_state[:, 0] + + + def encode_text(self, texts): + ''' + encode text only + ''' + input_ids = texts['input_ids'] + attention_mask = texts['attention_mask'] + + input_shape = input_ids.size() + device = input_ids.device + + token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=device) + + head_mask = [None] * self.depth + extended_attention_mask: torch.Tensor = self.get_extended_attention_mask(attention_mask, input_shape).to(self.dtype) + + embedding_output = self.bge_embeddings( + input_ids=input_ids, + position_ids=None, + token_type_ids=token_type_ids, + inputs_embeds=None, + past_key_values_length=0, + ) + encoder_outputs = self.bge_encoder( + embedding_output, + attention_mask=extended_attention_mask, + head_mask=head_mask, + encoder_hidden_states=None, + encoder_attention_mask=None, + past_key_values=None, + use_cache=False, + output_attentions=False, + output_hidden_states=False, + return_dict=True, + ) + sequence_output = encoder_outputs[0] + # pooled_output = self.bge_pooler(sequence_output) if self.bge_pooler is not None else None + + t_reps = self.sentence_embedding(sequence_output, texts['attention_mask']) # tensor: reps with pooling + if self.normlized: + t_reps = torch.nn.functional.normalize(t_reps, dim=-1) + return t_reps.contiguous() + + def encode_mm(self, images:torch.Tensor, texts): + img_token_emb = self.img_token_embedding(images) #[B, Patch_num, C] + img_token_emb = img_token_emb[:,1:] # img_cls is not used here + img_token_emb = self.visual_proj(img_token_emb) + device = img_token_emb.device + + img_token_len = img_token_emb.size()[1] + + # image position embedding, default position: bge_cls + img tokens + texts + img_token_position_ids = torch.arange(1, 1 + img_token_len).to(device=device) + img_position_embeddings = self.bge_embeddings.position_embeddings(img_token_position_ids) + img_token_emb = img_token_emb + img_position_embeddings + + img_token_emb = self.bge_embeddings.LayerNorm(img_token_emb) + + ### deal with prompt/text + prompt_input_ids = texts['input_ids'] + prompt_attention_mask = texts['attention_mask'] + prom_input_shape = prompt_input_ids.size() + + # bert + batch_size = prom_input_shape[0] + prompt_len = prom_input_shape[1] + prompt_start = 1 + img_token_len + + + cls_id = torch.tensor([0]).to(device=device) + prompt_position_ids = torch.arange(prompt_start, prompt_start + prompt_len - 1).to(device=device) + prompt_position_ids = torch.cat([cls_id, prompt_position_ids]).to(device=device) + + prompt_token_type_ids = torch.zeros(prom_input_shape, dtype=torch.long, device=device) + prompt_embedding_output = self.bge_embeddings( + input_ids=prompt_input_ids, + position_ids=prompt_position_ids, + token_type_ids=prompt_token_type_ids, + inputs_embeds=None, + past_key_values_length=0, + ) # [B, T, C] + + + cls_token = prompt_embedding_output[:, 0:1, :] # bge_cls token + prompt_embedding_output = prompt_embedding_output[:, 1:] + + prompt_img_embedding = torch.cat([cls_token, img_token_emb, prompt_embedding_output], dim=1) + + img_attention_mask = torch.ones(batch_size, img_token_len, device=device) + prom_img_attention_mask = torch.cat([img_attention_mask, prompt_attention_mask], dim=1) + prom_img_input_shape = prompt_img_embedding.size() + + head_mask = [None] * self.depth + extended_attention_mask: torch.Tensor = self.get_extended_attention_mask(prom_img_attention_mask, prom_img_input_shape).to(self.dtype) + + + encoder_outputs = self.bge_encoder( + prompt_img_embedding, + attention_mask=extended_attention_mask, + head_mask=head_mask, + encoder_hidden_states=None, + encoder_attention_mask=None, + past_key_values=None, + use_cache=False, + output_attentions=False, + output_hidden_states=False, + return_dict=True, + ) + sequence_output = encoder_outputs[0] + + prompt_img_reps = self.sentence_embedding(sequence_output, prom_img_attention_mask) # tensor: reps with pooling + if self.normlized: + prompt_img_reps = torch.nn.functional.normalize(prompt_img_reps, dim=-1) + return prompt_img_reps + + def compute_similarity(self, q_reps, p_reps): + if len(p_reps.size()) == 2: + return torch.matmul(q_reps, p_reps.transpose(0, 1)) + return torch.matmul(q_reps, p_reps.transpose(-2, -1)) + + def img_token_embedding(self, images): + if images is None: + return None + img_token_emb = self.model_visual.encode_image(images, normalize=False) # return_all_features=True, [B, Patch_num, C] + + return img_token_emb.contiguous() + + def encode_image(self, images): + if images is None: + return None + + batch_size = images.shape[0] + prompts = [""] * batch_size + + prompts = self.tokenizer(prompts, return_tensors="pt", padding=True) + prompts = prompts.to(images.device) + img_reps = self.encode_mm(images, prompts) + return img_reps + + def forward(self, mm_it_query=None, image_candidate=None, text_candidate=None, text_query=None, mm_it_candidate=None, task_type=None): + ### for stage-2 training + if task_type == "edit_image": + mm_query_reps = self.encode_mm(mm_it_query[0], mm_it_query[1]) + image_candi_reps = self.encode_image(image_candidate) + query_reps = mm_query_reps + candi_reps = image_candi_reps + + elif task_type == "t2it": + text_query_reps = self.encode_text(text_query) + mmit_candi_reps = self.encode_mm(mm_it_candidate[0], mm_it_candidate[1]) + query_reps = text_query_reps + candi_reps = mmit_candi_reps + + + if self.training: + if self.negatives_cross_device: + query_reps = self._dist_gather_tensor(query_reps) + candi_reps = self._dist_gather_tensor(candi_reps) + + scores = self.compute_similarity(query_reps, candi_reps) + scores = scores / self.temperature + scores = scores.view(query_reps.size(0), -1) + + target = torch.arange(scores.size(0), device=scores.device, dtype=torch.long) + target = target * (candi_reps.size(0) // query_reps.size(0)) + + loss_edit = self.compute_loss(scores, target) + loss = loss_edit + + logging.info("task types: %s; loss: %s" %(task_type, str(loss_edit))) + else: + scores = self.compute_similarity(query_reps, candi_reps) + loss=None + return EncoderOutput( + loss=loss, + scores=scores, + q_reps=query_reps, + c_reps=candi_reps, + ) + + def compute_loss(self, scores, target): + return self.cross_entropy(scores, target) + + def _dist_gather_tensor(self, t: Optional[torch.Tensor]): + if t is None: + return None + t = t.contiguous() + + all_tensors = [torch.empty_like(t) for _ in range(self.world_size)] + dist.all_gather(all_tensors, t) + + all_tensors[self.process_rank] = t + all_tensors = torch.cat(all_tensors, dim=0) + + return all_tensors + + def save(self, output_dir: str): + torch.save(self.state_dict(), os.path.join(output_dir, 'Visualized_BGE.pth')) diff --git a/code/C3/work_hybrid_multimodal_search.py b/code/C3/work_hybrid_multimodal_search.py new file mode 100644 index 0000000..b93694a --- /dev/null +++ b/code/C3/work_hybrid_multimodal_search.py @@ -0,0 +1,403 @@ +import json +import os +from tqdm import tqdm +import torch +from visual_bge.visual_bge.modeling import Visualized_BGE +from pymilvus import connections, MilvusClient, FieldSchema, CollectionSchema, DataType, Collection, AnnSearchRequest, RRFRanker +from pymilvus.model.hybrid import BGEM3EmbeddingFunction +import numpy as np +import cv2 +from PIL import Image +from typing import List, Dict, Any +from dataclasses import dataclass + +@dataclass +class DragonImage: + """龙类图像数据类""" + img_id: str + path: str + title: str + description: str + category: str + location: str + environment: str + combat_details: Dict[str, Any] = None + scene_info: Dict[str, Any] = None + +class DragonDataset: + """龙类图像数据集管理类""" + def __init__(self, data_dir: str, metadata_path: str): + self.data_dir = data_dir + self.metadata_path = metadata_path + self.images: List[DragonImage] = [] + self._load_metadata() + + def _load_metadata(self): + """加载图像元数据""" + with open(self.metadata_path, 'r', encoding='utf-8') as f: + data = json.load(f) + for img_data in data: + # 确保图片路径是完整的 + if not img_data['path'].startswith(self.data_dir): + img_data['path'] = os.path.join(self.data_dir, img_data['path'].split('/')[-1]) + self.images.append(DragonImage(**img_data)) + + def get_text_content(self, img: DragonImage) -> str: + """获取图像的文本描述内容""" + parts = [ + img.title, img.description, + img.location, img.environment + ] + if img.combat_details: + parts.extend(img.combat_details.get('combat_style', [])) + parts.extend(img.combat_details.get('abilities_used', [])) + if img.scene_info: + parts.append(img.scene_info.get('time_of_day', '')) + return ' '.join(filter(None, parts)) + +class HybridMultimodalEncoder: + """混合多模态编码器类""" + def __init__(self, visual_model_name: str, visual_model_path: str): + # 初始化Visual-BGE模型(用于多模态) + self.visual_model = Visualized_BGE(model_name_bge=visual_model_name, model_weight=visual_model_path) + self.visual_model.eval() + + # 初始化BGE-M3模型(用于混合检索) + self.bge_m3 = BGEM3EmbeddingFunction(use_fp16=False, device="cpu") + print(f"BGE-M3 密集向量维度: {self.bge_m3.dim['dense']}") + + def encode_multimodal(self, image_path: str, text: str) -> list[float]: + """编码多模态内容(图像+文本)""" + with torch.no_grad(): + query_emb = self.visual_model.encode(image=image_path, text=text) + return query_emb.tolist()[0] + + def encode_text_hybrid(self, text: str) -> dict: + """使用BGE-M3编码文本,返回稀疏和密集向量""" + embeddings = self.bge_m3([text]) + return { + 'sparse': embeddings["sparse"], + 'dense': embeddings["dense"] + } + + def encode_query(self, image_path: str = None, text: str = None, mode: str = "multimodal") -> dict: + """编码查询,支持多种模式""" + result = {} + + if mode in ["multimodal", "all"] and image_path and text: + result['multimodal'] = self.encode_multimodal(image_path, text) + + if mode in ["hybrid", "dense", "sparse", "all"] and text: + text_embeddings = self.encode_text_hybrid(text) + result['dense'] = text_embeddings['dense'][0] + result['sparse'] = text_embeddings['sparse']._getrow(0) + + return result + +def visualize_results(query_image_path: str, retrieved_results: list, search_mode: str, + img_height: int = 300, img_width: int = 300, row_count: int = 3) -> np.ndarray: + """从检索到的结果创建一个全景图用于可视化""" + panoramic_width = img_width * row_count + panoramic_height = img_height * row_count + panoramic_image = np.full((panoramic_height, panoramic_width, 3), 255, dtype=np.uint8) + query_display_area = np.full((panoramic_height, img_width, 3), 255, dtype=np.uint8) + + # 处理查询图像 + if query_image_path and os.path.exists(query_image_path): + query_pil = Image.open(query_image_path).convert("RGB") + query_cv = np.array(query_pil)[:, :, ::-1] + resized_query = cv2.resize(query_cv, (img_width, img_height)) + bordered_query = cv2.copyMakeBorder(resized_query, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=(255, 0, 0)) + query_display_area[img_height * (row_count - 1):, :] = cv2.resize(bordered_query, (img_width, img_height)) + cv2.putText(query_display_area, "Query", (10, panoramic_height - 40), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 2) + cv2.putText(query_display_area, search_mode, (10, panoramic_height - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 100, 0), 2) + + # 处理检索到的图像 + for i, result in enumerate(retrieved_results): + row, col = i // row_count, i % row_count + start_row, start_col = row * img_height, col * img_width + + img_path = result['image_path'] + retrieved_pil = Image.open(img_path).convert("RGB") + retrieved_cv = np.array(retrieved_pil)[:, :, ::-1] + resized_retrieved = cv2.resize(retrieved_cv, (img_width - 4, img_height - 4)) + bordered_retrieved = cv2.copyMakeBorder(resized_retrieved, 2, 2, 2, 2, cv2.BORDER_CONSTANT, value=(0, 0, 0)) + panoramic_image[start_row:start_row + img_height, start_col:start_col + img_width] = bordered_retrieved + + # 添加索引号和相似度 + cv2.putText(panoramic_image, f"{i+1}", (start_col + 10, start_row + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) + cv2.putText(panoramic_image, f"{result['distance']:.3f}", (start_col + 10, start_row + img_height - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) + + return np.hstack([query_display_area, panoramic_image]) + +class HybridMultimodalSearcher: + """混合多模态搜索系统""" + def __init__(self, data_dir: str, metadata_path: str, collection_name: str, milvus_uri: str): + self.data_dir = data_dir + self.metadata_path = metadata_path + self.collection_name = collection_name + self.milvus_uri = milvus_uri + + # 初始化数据集和编码器 + print("--> 正在初始化数据集...") + self.dataset = DragonDataset(data_dir, metadata_path) + print(f"加载了 {len(self.dataset.images)} 张龙类图像") + + print("--> 正在初始化混合多模态编码器...") + self.encoder = HybridMultimodalEncoder( + visual_model_name="BAAI/bge-base-en-v1.5", + visual_model_path="../../models/bge/Visualized_base_en_v1.5.pth" + ) + + # 连接Milvus + print(f"--> 正在连接到 Milvus: {milvus_uri}") + connections.connect(uri=milvus_uri) + self.milvus_client = MilvusClient(uri=milvus_uri) + + self.collection = None + + def create_collection(self): + """创建Collection""" + print(f"--> 正在创建 Collection '{self.collection_name}'") + if self.milvus_client.has_collection(self.collection_name): + self.milvus_client.drop_collection(self.collection_name) + print(f"已删除已存在的 Collection: '{self.collection_name}'") + + # 获取向量维度 + sample_text = self.dataset.get_text_content(self.dataset.images[0]) + sample_path = self.dataset.images[0].path + multimodal_dim = len(self.encoder.encode_multimodal(sample_path, sample_text)) + dense_dim = self.encoder.bge_m3.dim["dense"] + + print(f"多模态向量维度: {multimodal_dim}") + print(f"密集向量维度: {dense_dim}") + + fields = [ + FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100), + FieldSchema(name="img_id", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="image_path", dtype=DataType.VARCHAR, max_length=512), + FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=256), + FieldSchema(name="description", dtype=DataType.VARCHAR, max_length=4096), + FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=64), + FieldSchema(name="location", dtype=DataType.VARCHAR, max_length=128), + FieldSchema(name="environment", dtype=DataType.VARCHAR, max_length=64), + # 三种向量类型 + FieldSchema(name="multimodal_vector", dtype=DataType.FLOAT_VECTOR, dim=multimodal_dim), + FieldSchema(name="text_sparse_vector", dtype=DataType.SPARSE_FLOAT_VECTOR), + FieldSchema(name="text_dense_vector", dtype=DataType.FLOAT_VECTOR, dim=dense_dim) + ] + + schema = CollectionSchema(fields, description="混合多模态龙类图像检索") + self.collection = Collection(name=self.collection_name, schema=schema, consistency_level="Strong") + print("--> Collection 创建成功") + + # 创建索引 + print("--> 正在创建索引...") + # 多模态向量索引 + multimodal_index = {"index_type": "HNSW", "metric_type": "COSINE", "params": {"M": 16, "efConstruction": 256}} + self.collection.create_index("multimodal_vector", multimodal_index) + print("多模态向量索引创建成功") + + # 稀疏向量索引 + sparse_index = {"index_type": "SPARSE_INVERTED_INDEX", "metric_type": "IP"} + self.collection.create_index("text_sparse_vector", sparse_index) + print("稀疏向量索引创建成功") + + # 密集向量索引 + dense_index = {"index_type": "AUTOINDEX", "metric_type": "IP"} + self.collection.create_index("text_dense_vector", dense_index) + print("密集向量索引创建成功") + + self.collection.load() + print(f"--> Collection '{self.collection_name}' 已加载到内存") + + def insert_data(self): + """插入数据""" + if self.collection.is_empty: + print("--> Collection 为空,开始插入数据...") + + # 准备批量数据 + img_ids, image_paths, titles, descriptions = [], [], [], [] + categories, locations, environments = [], [], [] + multimodal_vectors, text_sparse_vectors, text_dense_vectors = [], [], [] + + for img_data in tqdm(self.dataset.images, desc="生成向量嵌入"): + text_content = self.dataset.get_text_content(img_data) + + # 生成多模态向量(图像+文本) + multimodal_vector = self.encoder.encode_multimodal(img_data.path, text_content) + + # 生成文本的混合向量(稀疏+密集) + text_embeddings = self.encoder.encode_text_hybrid(text_content) + + # 收集数据 + img_ids.append(img_data.img_id) + image_paths.append(img_data.path) + titles.append(img_data.title) + descriptions.append(img_data.description) + categories.append(img_data.category) + locations.append(img_data.location) + environments.append(img_data.environment) + + multimodal_vectors.append(multimodal_vector) + text_sparse_vectors.append(text_embeddings['sparse']._getrow(0)) + text_dense_vectors.append(text_embeddings['dense'][0]) + + # 插入数据 + self.collection.insert([ + img_ids, image_paths, titles, descriptions, categories, locations, environments, + multimodal_vectors, text_sparse_vectors, text_dense_vectors + ]) + + self.collection.flush() + print(f"--> 数据插入完成,总数: {self.collection.num_entities}") + else: + print(f"--> Collection 中已有 {self.collection.num_entities} 条数据,跳过插入") + + def search(self, query_image_path: str, query_text: str, mode: str = "hybrid", top_k: int = 5) -> list: + """执行搜索""" + search_params = {"metric_type": "IP", "params": {}} + cosine_params = {"metric_type": "COSINE", "params": {"ef": 128}} + output_fields = ["img_id", "image_path", "title", "description", "category", "location", "environment"] + + if mode == "multimodal": + # 多模态检索 + query_vector = self.encoder.encode_multimodal(query_image_path, query_text) + results = self.collection.search( + [query_vector], "multimodal_vector", param=cosine_params, + limit=top_k, output_fields=output_fields + )[0] + + elif mode == "dense": + # 密集向量检索 + query_embeddings = self.encoder.encode_text_hybrid(query_text) + dense_vec = query_embeddings['dense'][0] + results = self.collection.search( + [dense_vec], "text_dense_vector", param=search_params, + limit=top_k, output_fields=output_fields + )[0] + + elif mode == "sparse": + # 稀疏向量检索 + query_embeddings = self.encoder.encode_text_hybrid(query_text) + sparse_vec = query_embeddings['sparse']._getrow(0) + results = self.collection.search( + [sparse_vec], "text_sparse_vector", param=search_params, + limit=top_k, output_fields=output_fields + )[0] + + elif mode == "hybrid": + # 混合检索(稀疏+密集) + query_embeddings = self.encoder.encode_text_hybrid(query_text) + dense_vec = query_embeddings['dense'][0] + sparse_vec = query_embeddings['sparse']._getrow(0) + + # 创建RRF融合器 + rerank = RRFRanker(k=60) + + # 创建搜索请求 + dense_req = AnnSearchRequest([dense_vec], "text_dense_vector", search_params, limit=top_k) + sparse_req = AnnSearchRequest([sparse_vec], "text_sparse_vector", search_params, limit=top_k) + + # 执行混合搜索 + results = self.collection.hybrid_search( + [sparse_req, dense_req], rerank=rerank, limit=top_k, output_fields=output_fields + )[0] + + return results + + def compare_search_modes(self, query_image_path: str, query_text: str, top_k: int = 5): + """对比不同搜索模式的效果""" + modes = ["multimodal", "dense", "sparse", "hybrid"] + results = {} + + print(f"\n{'='*50}") + print(f"查询图像: {query_image_path}") + print(f"查询文本: {query_text}") + print(f"{'='*50}") + + for mode in modes: + print(f"\n--- [{mode.upper()}] 搜索结果 ---") + search_results = self.search(query_image_path, query_text, mode, top_k) + + mode_results = [] + for i, hit in enumerate(search_results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('image_path')}") + print(f" 描述: {hit.entity.get('description')[:80]}...") + + mode_results.append({ + 'image_path': hit.entity.get('image_path'), + 'distance': hit.distance, + 'title': hit.entity.get('title') + }) + + results[mode] = mode_results + + return results + + def visualize_comparison(self, query_image_path: str, query_text: str, top_k: int = 3): + """可视化对比不同搜索模式""" + modes = ["multimodal", "dense", "sparse", "hybrid"] + + for mode in modes: + results = self.search(query_image_path, query_text, mode, top_k) + + retrieved_results = [] + for hit in results: + retrieved_results.append({ + 'image_path': hit.entity.get('image_path'), + 'distance': hit.distance + }) + + if retrieved_results: + panoramic_image = visualize_results(query_image_path, retrieved_results, mode.upper()) + output_path = f"../../data/C4/{mode}_search_result.png" + cv2.imwrite(output_path, panoramic_image) + print(f"{mode.upper()} 搜索结果已保存到: {output_path}") + + def cleanup(self): + """清理资源""" + if self.collection: + self.collection.release() + print(f"已从内存中释放 Collection: '{self.collection_name}'") + self.milvus_client.drop_collection(self.collection_name) + print(f"已删除 Collection: '{self.collection_name}'") + +# 主程序 +if __name__ == "__main__": + # 初始化设置 + DATA_DIR = "../../data/C3/dragon" + METADATA_PATH = "../../data/C4/metadata/dragon.json" + COLLECTION_NAME = "hybrid_multimodal_dragon_demo" + MILVUS_URI = "http://localhost:19530" + + # 创建混合多模态搜索系统 + searcher = HybridMultimodalSearcher(DATA_DIR, METADATA_PATH, COLLECTION_NAME, MILVUS_URI) + + try: + # 创建Collection并插入数据 + searcher.create_collection() + searcher.insert_data() + + # 执行搜索对比 + query_image_path = os.path.join(DATA_DIR, "query.png") + query_text = "悬崖上的巨龙" + + # 对比不同搜索模式 + results = searcher.compare_search_modes(query_image_path, query_text, top_k=3) + + # 可视化结果 + searcher.visualize_comparison(query_image_path, query_text, top_k=3) + + print(f"\n{'='*50}") + print("搜索模式分析:") + print("- MULTIMODAL: 结合图像和文本的多模态向量检索") + print("- DENSE: 基于语义的密集向量检索") + print("- SPARSE: 基于关键词的稀疏向量检索") + print("- HYBRID: 稀疏+密集向量RRF融合检索") + print(f"{'='*50}") + + finally: + # 清理资源 + searcher.cleanup() \ No newline at end of file diff --git a/code/C3/work_multimodal_dragon_search.py b/code/C3/work_multimodal_dragon_search.py new file mode 100644 index 0000000..2c6d528 --- /dev/null +++ b/code/C3/work_multimodal_dragon_search.py @@ -0,0 +1,301 @@ +import json +import os +from tqdm import tqdm +from glob import glob +import torch +from visual_bge.visual_bge.modeling import Visualized_BGE +from pymilvus import MilvusClient, FieldSchema, CollectionSchema, DataType +import numpy as np +import cv2 +from PIL import Image +from typing import List, Dict, Any +from dataclasses import dataclass + +@dataclass +class DragonImage: + """龙类图像数据类""" + img_id: str + path: str + title: str + description: str + category: str + location: str + environment: str + combat_details: Dict[str, Any] = None + scene_info: Dict[str, Any] = None + +class DragonDataset: + """龙类图像数据集管理类""" + def __init__(self, data_dir: str, metadata_path: str): + self.data_dir = data_dir + self.metadata_path = metadata_path + self.images: List[DragonImage] = [] + self._load_metadata() + + def _load_metadata(self): + """加载图像元数据""" + with open(self.metadata_path, 'r', encoding='utf-8') as f: + data = json.load(f) + for img_data in data: + # 确保图片路径是完整的 + if not img_data['path'].startswith(self.data_dir): + img_data['path'] = os.path.join(self.data_dir, img_data['path'].split('/')[-1]) + self.images.append(DragonImage(**img_data)) + + def get_image_paths(self) -> List[str]: + """获取所有图像路径""" + return [img.path for img in self.images] + + def get_metadata_by_path(self, path: str) -> DragonImage: + """根据路径获取元数据""" + for img in self.images: + if img.path == path: + return img + return None + + def get_text_content(self, img: DragonImage) -> str: + """获取图像的文本描述内容""" + parts = [ + img.title, img.description, + img.location, img.environment + ] + if img.combat_details: + parts.extend(img.combat_details.get('combat_style', [])) + parts.extend(img.combat_details.get('abilities_used', [])) + if img.scene_info: + parts.append(img.scene_info.get('time_of_day', '')) + return ' '.join(filter(None, parts)) + +class Encoder: + """编码器类,用于将图像和文本编码为向量""" + def __init__(self, model_name: str, model_path: str): + self.model = Visualized_BGE(model_name_bge=model_name, model_weight=model_path) + self.model.eval() + + def encode_query(self, image_path: str = None, text: str = None) -> list[float]: + """编码查询(支持图像+文本或仅文本)""" + with torch.no_grad(): + if image_path and text: + query_emb = self.model.encode(image=image_path, text=text) + elif image_path: + query_emb = self.model.encode(image=image_path) + elif text: + query_emb = self.model.encode(text=text) + else: + raise ValueError("必须提供图像路径或文本内容") + return query_emb.tolist()[0] + + def encode_multimodal(self, image_path: str, text: str) -> list[float]: + """编码多模态内容(图像+文本)""" + with torch.no_grad(): + query_emb = self.model.encode(image=image_path, text=text) + return query_emb.tolist()[0] + +def visualize_results(query_image_path: str, retrieved_results: list, img_height: int = 300, img_width: int = 300, row_count: int = 3) -> np.ndarray: + """从检索到的结果创建一个全景图用于可视化""" + panoramic_width = img_width * row_count + panoramic_height = img_height * row_count + panoramic_image = np.full((panoramic_height, panoramic_width, 3), 255, dtype=np.uint8) + query_display_area = np.full((panoramic_height, img_width, 3), 255, dtype=np.uint8) + + # 处理查询图像 + if query_image_path and os.path.exists(query_image_path): + query_pil = Image.open(query_image_path).convert("RGB") + query_cv = np.array(query_pil)[:, :, ::-1] + resized_query = cv2.resize(query_cv, (img_width, img_height)) + bordered_query = cv2.copyMakeBorder(resized_query, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=(255, 0, 0)) + query_display_area[img_height * (row_count - 1):, :] = cv2.resize(bordered_query, (img_width, img_height)) + cv2.putText(query_display_area, "Query", (10, panoramic_height - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) + + # 处理检索到的图像 + for i, result in enumerate(retrieved_results): + row, col = i // row_count, i % row_count + start_row, start_col = row * img_height, col * img_width + + img_path = result['image_path'] + retrieved_pil = Image.open(img_path).convert("RGB") + retrieved_cv = np.array(retrieved_pil)[:, :, ::-1] + resized_retrieved = cv2.resize(retrieved_cv, (img_width - 4, img_height - 4)) + bordered_retrieved = cv2.copyMakeBorder(resized_retrieved, 2, 2, 2, 2, cv2.BORDER_CONSTANT, value=(0, 0, 0)) + panoramic_image[start_row:start_row + img_height, start_col:start_col + img_width] = bordered_retrieved + + # 添加索引号和相似度 + cv2.putText(panoramic_image, f"{i+1}", (start_col + 10, start_row + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) + cv2.putText(panoramic_image, f"{result['distance']:.3f}", (start_col + 10, start_row + img_height - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) + + return np.hstack([query_display_area, panoramic_image]) + +# 1. 初始化设置 +MODEL_NAME = "BAAI/bge-base-en-v1.5" +MODEL_PATH = "../../models/bge/Visualized_base_en_v1.5.pth" +DATA_DIR = "../../data/C3/dragon" +METADATA_PATH = "../../data/C4/metadata/dragon.json" +COLLECTION_NAME = "multimodal_dragon_demo" +MILVUS_URI = "http://localhost:19530" + +# 2. 初始化数据集和编码器 +print("--> 正在初始化数据集...") +dataset = DragonDataset(DATA_DIR, METADATA_PATH) +print(f"加载了 {len(dataset.images)} 张龙类图像") + +print("--> 正在初始化编码器和Milvus客户端...") +encoder = Encoder(MODEL_NAME, MODEL_PATH) +milvus_client = MilvusClient(uri=MILVUS_URI) + +# 3. 创建 Milvus Collection +print(f"\n--> 正在创建 Collection '{COLLECTION_NAME}'") +if milvus_client.has_collection(COLLECTION_NAME): + milvus_client.drop_collection(COLLECTION_NAME) + print(f"已删除已存在的 Collection: '{COLLECTION_NAME}'") + +# 获取向量维度 +sample_text = dataset.get_text_content(dataset.images[0]) +sample_path = dataset.images[0].path +dim = len(encoder.encode_multimodal(sample_path, sample_text)) + +fields = [ + FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True), + FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=dim), + FieldSchema(name="img_id", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="image_path", dtype=DataType.VARCHAR, max_length=512), + FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=256), + FieldSchema(name="description", dtype=DataType.VARCHAR, max_length=4096), + FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=64), + FieldSchema(name="location", dtype=DataType.VARCHAR, max_length=128), + FieldSchema(name="environment", dtype=DataType.VARCHAR, max_length=64), +] + +schema = CollectionSchema(fields, description="多模态龙类图像检索") + +# 创建集合 +milvus_client.create_collection(collection_name=COLLECTION_NAME, schema=schema) +print(f"成功创建 Collection: '{COLLECTION_NAME}'") + +# 4. 准备并插入数据 +print(f"\n--> 正在向 '{COLLECTION_NAME}' 插入数据") +data_to_insert = [] +for img_data in tqdm(dataset.images, desc="生成多模态嵌入"): + # 结合图像和文本信息生成向量 + text_content = dataset.get_text_content(img_data) + vector = encoder.encode_multimodal(img_data.path, text_content) + + data_to_insert.append({ + "vector": vector, + "img_id": img_data.img_id, + "image_path": img_data.path, + "title": img_data.title, + "description": img_data.description, + "category": img_data.category, + "location": img_data.location, + "environment": img_data.environment + }) + +if data_to_insert: + result = milvus_client.insert(collection_name=COLLECTION_NAME, data=data_to_insert) + print(f"成功插入 {result['insert_count']} 条数据。") + +# 5. 创建索引 +print(f"\n--> 正在为 '{COLLECTION_NAME}' 创建索引") +index_params = milvus_client.prepare_index_params() +index_params.add_index( + field_name="vector", + index_type="HNSW", + metric_type="COSINE", + params={"M": 16, "efConstruction": 256} +) +milvus_client.create_index(collection_name=COLLECTION_NAME, index_params=index_params) +print("成功为向量字段创建 HNSW 索引。") +milvus_client.load_collection(collection_name=COLLECTION_NAME) +print("已加载 Collection 到内存中。") + +# 6. 执行多模态检索 +print(f"\n--> 正在 '{COLLECTION_NAME}' 中执行多模态检索") + +# 示例1:图像+文本查询 +query_image_path = os.path.join(DATA_DIR, "query.png") +query_text = "悬崖上的巨龙" +query_vector = encoder.encode_query(image_path=query_image_path, text=query_text) + +print(f"\n=== 多模态查询(图像+文本)===") +print(f"查询图像: {query_image_path}") +print(f"查询文本: {query_text}") + +search_results = milvus_client.search( + collection_name=COLLECTION_NAME, + data=[query_vector], + output_fields=["img_id", "image_path", "title", "description", "category", "location", "environment"], + limit=6, + search_params={"metric_type": "COSINE", "params": {"ef": 128}} +)[0] + +retrieved_results = [] +print("检索结果:") +for i, hit in enumerate(search_results): + print(f" Top {i+1}: ID={hit['id']}, 距离={hit['distance']:.4f}") + print(f" 标题: {hit['entity']['title']}") + print(f" 描述: {hit['entity']['description'][:100]}...") + print(f" 类别: {hit['entity']['category']}") + print(f" 路径: {hit['entity']['image_path']}") + print("-" * 50) + retrieved_results.append({ + 'image_path': hit['entity']['image_path'], + 'distance': hit['distance'] + }) + +# 示例2:纯文本查询 +print(f"\n=== 纯文本查询 ===") +text_query = "悬崖上的巨龙" +text_query_vector = encoder.encode_query(text=text_query) + +print(f"查询文本: {text_query}") + +text_search_results = milvus_client.search( + collection_name=COLLECTION_NAME, + data=[text_query_vector], + output_fields=["img_id", "image_path", "title", "description", "category", "location", "environment"], + limit=3, + search_params={"metric_type": "COSINE", "params": {"ef": 128}} +)[0] + +print("文本检索结果:") +for i, hit in enumerate(text_search_results): + print(f" Top {i+1}: {hit['entity']['title']} (距离: {hit['distance']:.4f})") + print(f" 描述: {hit['entity']['description'][:80]}...") + +# 示例3:纯图像查询 +print(f"\n=== 纯图像查询 ===") +image_query_path = os.path.join(DATA_DIR, "query.png") +image_query_vector = encoder.encode_query(image_path=image_query_path) + +print(f"查询图像: {image_query_path}") + +image_search_results = milvus_client.search( + collection_name=COLLECTION_NAME, + data=[image_query_vector], + output_fields=["img_id", "image_path", "title", "description", "category", "location", "environment"], + limit=3, + search_params={"metric_type": "COSINE", "params": {"ef": 128}} +)[0] + +print("图像检索结果:") +for i, hit in enumerate(image_search_results): + print(f" Top {i+1}: {hit['entity']['title']} (距离: {hit['distance']:.4f})") + print(f" 类别: {hit['entity']['category']}") + print(f" 描述: {hit['entity']['description'][:80]}...") + print(f" 路径: {hit['entity']['image_path']}") + print("-" * 30) + +# 7. 可视化与清理 +print(f"\n--> 正在可视化结果并清理资源") +if retrieved_results: + panoramic_image = visualize_results(query_image_path, retrieved_results) + combined_image_path = "../../data/C4/multimodal_search.png" + cv2.imwrite(combined_image_path, panoramic_image) + print(f"结果图像已保存到: {combined_image_path}") + # Image.open(combined_image_path).show() + +# 8. 清理资源 +milvus_client.release_collection(collection_name=COLLECTION_NAME) +print(f"已从内存中释放 Collection: '{COLLECTION_NAME}'") +milvus_client.drop_collection(COLLECTION_NAME) +print(f"已删除 Collection: '{COLLECTION_NAME}'") \ No newline at end of file diff --git a/code/C4/01_hybrid_search.py b/code/C4/01_hybrid_search.py new file mode 100644 index 0000000..69a3854 --- /dev/null +++ b/code/C4/01_hybrid_search.py @@ -0,0 +1,209 @@ +import json +import os +import numpy as np +from pymilvus import connections, MilvusClient, FieldSchema, CollectionSchema, DataType, Collection, AnnSearchRequest, RRFRanker +from pymilvus.model.hybrid import BGEM3EmbeddingFunction + +# 1. 初始化设置 +COLLECTION_NAME = "dragon_hybrid_demo" +MILVUS_URI = "http://localhost:19530" # 服务器模式 +DATA_PATH = "../../data/C4/metadata/dragon.json" # 相对路径 +BATCH_SIZE = 50 + +# 2. 连接 Milvus 并初始化嵌入模型 +print(f"--> 正在连接到 Milvus: {MILVUS_URI}") +connections.connect(uri=MILVUS_URI) + +print("--> 正在初始化 BGE-M3 嵌入模型...") +ef = BGEM3EmbeddingFunction(use_fp16=False, device="cpu") +print(f"--> 嵌入模型初始化完成。密集向量维度: {ef.dim['dense']}") + +# 3. 创建 Collection +milvus_client = MilvusClient(uri=MILVUS_URI) +if milvus_client.has_collection(COLLECTION_NAME): + print(f"--> 正在删除已存在的 Collection '{COLLECTION_NAME}'...") + milvus_client.drop_collection(COLLECTION_NAME) + +fields = [ + FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100), + FieldSchema(name="img_id", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="path", dtype=DataType.VARCHAR, max_length=256), + FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=256), + FieldSchema(name="description", dtype=DataType.VARCHAR, max_length=4096), + FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=64), + FieldSchema(name="location", dtype=DataType.VARCHAR, max_length=128), + FieldSchema(name="environment", dtype=DataType.VARCHAR, max_length=64), + FieldSchema(name="sparse_vector", dtype=DataType.SPARSE_FLOAT_VECTOR), + FieldSchema(name="dense_vector", dtype=DataType.FLOAT_VECTOR, dim=ef.dim["dense"]) +] + +# 如果集合不存在,则创建它及索引 +if not milvus_client.has_collection(COLLECTION_NAME): + print(f"--> 正在创建 Collection '{COLLECTION_NAME}'...") + schema = CollectionSchema(fields, description="关于龙的混合检索示例") + # 创建集合 + collection = Collection(name=COLLECTION_NAME, schema=schema, consistency_level="Strong") + print("--> Collection 创建成功。") + + # 4. 创建索引 + print("--> 正在为新集合创建索引...") + sparse_index = {"index_type": "SPARSE_INVERTED_INDEX", "metric_type": "IP"} + collection.create_index("sparse_vector", sparse_index) + print("稀疏向量索引创建成功。") + + dense_index = {"index_type": "AUTOINDEX", "metric_type": "IP"} + collection.create_index("dense_vector", dense_index) + print("密集向量索引创建成功。") + +collection = Collection(COLLECTION_NAME) + +# 5. 加载数据并插入 +collection.load() +print(f"--> Collection '{COLLECTION_NAME}' 已加载到内存。") + +if collection.is_empty: + print(f"--> Collection 为空,开始插入数据...") + if not os.path.exists(DATA_PATH): + raise FileNotFoundError(f"数据文件未找到: {DATA_PATH}") + with open(DATA_PATH, 'r', encoding='utf-8') as f: + dataset = json.load(f) + + docs, metadata = [], [] + for item in dataset: + parts = [ + item.get('title', ''), + item.get('description', ''), + item.get('location', ''), + item.get('environment', ''), + # *item.get('combat_details', {}).get('combat_style', []), + # *item.get('combat_details', {}).get('abilities_used', []), + # item.get('scene_info', {}).get('time_of_day', '') + ] + docs.append(' '.join(filter(None, parts))) + metadata.append(item) + print(f"--> 数据加载完成,共 {len(docs)} 条。") + + print("--> 正在生成向量嵌入...") + embeddings = ef(docs) + print("--> 向量生成完成。") + + print("--> 正在分批插入数据...") + # 为每个字段准备批量数据 + img_ids = [doc["img_id"] for doc in metadata] + paths = [doc["path"] for doc in metadata] + titles = [doc["title"] for doc in metadata] + descriptions = [doc["description"] for doc in metadata] + categories = [doc["category"] for doc in metadata] + locations = [doc["location"] for doc in metadata] + environments = [doc["environment"] for doc in metadata] + + # 获取向量 + sparse_vectors = embeddings["sparse"] + dense_vectors = embeddings["dense"] + + # 插入数据 + collection.insert([ + img_ids, + paths, + titles, + descriptions, + categories, + locations, + environments, + sparse_vectors, + dense_vectors + ]) + + collection.flush() + print(f"--> 数据插入完成,总数: {collection.num_entities}") +else: + print(f"--> Collection 中已有 {collection.num_entities} 条数据,跳过插入。") + +# 6. 执行搜索 +search_query = "悬崖上的巨龙" +search_filter = 'category in ["western_dragon", "chinese_dragon", "movie_character"]' +top_k = 5 + +print(f"\n{'='*20} 开始混合搜索 {'='*20}") +print(f"查询: '{search_query}'") +print(f"过滤器: '{search_filter}'") + +query_embeddings = ef([search_query]) +dense_vec = query_embeddings["dense"][0] +sparse_vec = query_embeddings["sparse"]._getrow(0) + +# 打印向量信息 +print("\n=== 向量信息 ===") +print(f"密集向量维度: {len(dense_vec)}") +print(f"密集向量前5个元素: {dense_vec[:5]}") +print(f"密集向量范数: {np.linalg.norm(dense_vec):.4f}") + +print(f"\n稀疏向量维度: {sparse_vec.shape[1]}") +print(f"稀疏向量非零元素数量: {sparse_vec.nnz}") +print("稀疏向量前5个非零元素:") +for i in range(min(5, sparse_vec.nnz)): + print(f" - 索引: {sparse_vec.indices[i]}, 值: {sparse_vec.data[i]:.4f}") +density = (sparse_vec.nnz / sparse_vec.shape[1] * 100) +print(f"\n稀疏向量密度: {density:.8f}%") + +# 定义搜索参数 +search_params = {"metric_type": "IP", "params": {}} + +# 先执行单独的搜索 +print("\n--- [单独] 密集向量搜索结果 ---") +dense_results = collection.search( + [dense_vec], + anns_field="dense_vector", + param=search_params, + limit=top_k, + expr=search_filter, + output_fields=["title", "path", "description", "category", "location", "environment"] +)[0] + +for i, hit in enumerate(dense_results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('path')}") + print(f" 描述: {hit.entity.get('description')[:100]}...") + +print("\n--- [单独] 稀疏向量搜索结果 ---") +sparse_results = collection.search( + [sparse_vec], + anns_field="sparse_vector", + param=search_params, + limit=top_k, + expr=search_filter, + output_fields=["title", "path", "description", "category", "location", "environment"] +)[0] + +for i, hit in enumerate(sparse_results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('path')}") + print(f" 描述: {hit.entity.get('description')[:100]}...") + +print("\n--- [混合] 稀疏+密集向量搜索结果 ---") +# 创建 RRF 融合器 +rerank = RRFRanker(k=60) + +# 创建搜索请求 +dense_req = AnnSearchRequest([dense_vec], "dense_vector", search_params, limit=top_k) +sparse_req = AnnSearchRequest([sparse_vec], "sparse_vector", search_params, limit=top_k) + +# 执行混合搜索 +results = collection.hybrid_search( + [sparse_req, dense_req], + rerank=rerank, + limit=top_k, + output_fields=["title", "path", "description", "category", "location", "environment"] +)[0] + +# 打印最终结果 +for i, hit in enumerate(results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('path')}") + print(f" 描述: {hit.entity.get('description')[:100]}...") + +# 7. 清理资源 +milvus_client.release_collection(collection_name=COLLECTION_NAME) +print(f"已从内存中释放 Collection: '{COLLECTION_NAME}'") +milvus_client.drop_collection(COLLECTION_NAME) +print(f"已删除 Collection: '{COLLECTION_NAME}'") diff --git a/code/C4/01_hybrid_search_v2.py b/code/C4/01_hybrid_search_v2.py new file mode 100644 index 0000000..4e5cbfd --- /dev/null +++ b/code/C4/01_hybrid_search_v2.py @@ -0,0 +1,329 @@ +import json +import os +import numpy as np +import torch +from transformers import AutoModel, AutoProcessor +from sklearn.feature_extraction.text import TfidfVectorizer +from scipy.sparse import csr_matrix +from pymilvus import connections, MilvusClient, FieldSchema, CollectionSchema, DataType, Collection, AnnSearchRequest, RRFRanker + +# 1. 初始化设置 +COLLECTION_NAME = "dragon_siglip_demo" +MILVUS_URI = "http://localhost:19530" # 服务器模式 +DATA_PATH = "../../data/C4/metadata/dragon.json" # 相对路径 +BATCH_SIZE = 50 + +# 2. 自定义SigLIP嵌入函数类 +class SigLIPEmbeddingFunction: + def __init__(self, model_name="google/siglip-base-patch16-256-multilingual", device="cpu"): + """ + 初始化SigLIP嵌入函数 + Args: + model_name: SigLIP模型名称 + device: 设备类型 ("cpu" 或 "cuda") + """ + self.model_name = model_name + self.device = device + + print(f"--> 正在加载 SigLIP 模型: {model_name}") + self.model = AutoModel.from_pretrained(model_name) + self.processor = AutoProcessor.from_pretrained(model_name) + self.model.to(device) + self.model.eval() + + # 初始化TF-IDF作为稀疏向量生成器 + self.tfidf_vectorizer = TfidfVectorizer( + max_features=10000, # 限制词汇表大小以节省空间 + stop_words='english', + ngram_range=(1, 2) + ) + self.tfidf_fitted = False + + # 获取文本编码器的输出维度 + with torch.no_grad(): + dummy_text = ["test"] + inputs = self.processor(text=dummy_text, padding="max_length", return_tensors="pt") + outputs = self.model.text_model(**{k: v.to(device) for k, v in inputs.items() if k != 'pixel_values'}) + self.dense_dim = outputs.pooler_output.shape[-1] + + print(f"--> SigLIP 模型加载完成。密集向量维度: {self.dense_dim}") + + @property + def dim(self): + """返回维度信息,兼容原BGE-M3接口""" + return { + "dense": self.dense_dim, + "sparse": self.tfidf_vectorizer.max_features if self.tfidf_fitted else 10000 + } + + def fit_sparse(self, docs): + """拟合稀疏向量模型(TF-IDF)""" + print("--> 正在拟合 TF-IDF 模型...") + self.tfidf_vectorizer.fit(docs) + self.tfidf_fitted = True + print(f"--> TF-IDF 模型拟合完成。词汇表大小: {len(self.tfidf_vectorizer.vocabulary_)}") + + def encode_text_dense(self, texts): + """使用SigLIP编码文本为密集向量""" + if isinstance(texts, str): + texts = [texts] + + dense_vectors = [] + batch_size = 8 # 减小批次大小以节省内存 + + with torch.no_grad(): + for i in range(0, len(texts), batch_size): + batch_texts = texts[i:i + batch_size] + inputs = self.processor(text=batch_texts, padding="max_length", truncation=True, return_tensors="pt") + inputs = {k: v.to(self.device) for k, v in inputs.items() if k != 'pixel_values'} + + outputs = self.model.text_model(**inputs) + embeddings = outputs.pooler_output + + # 归一化向量 + embeddings = torch.nn.functional.normalize(embeddings, p=2, dim=1) + dense_vectors.extend(embeddings.cpu().numpy()) + + return np.array(dense_vectors) + + def encode_text_sparse(self, texts): + """使用TF-IDF编码文本为稀疏向量""" + if not self.tfidf_fitted: + raise ValueError("请先调用 fit_sparse() 方法拟合TF-IDF模型") + + if isinstance(texts, str): + texts = [texts] + + sparse_matrix = self.tfidf_vectorizer.transform(texts) + return sparse_matrix + + def __call__(self, texts): + """主调用方法,返回密集和稀疏向量""" + if isinstance(texts, str): + texts = [texts] + + # 如果还没有拟合稀疏模型,先拟合 + if not self.tfidf_fitted: + self.fit_sparse(texts) + + dense_vectors = self.encode_text_dense(texts) + sparse_vectors = self.encode_text_sparse(texts) + + return { + "dense": dense_vectors, + "sparse": sparse_vectors + } + +# 3. 连接 Milvus 并初始化嵌入模型 +print(f"--> 正在连接到 Milvus: {MILVUS_URI}") +connections.connect(uri=MILVUS_URI) + +print("--> 正在初始化 SigLIP 嵌入模型...") +ef = SigLIPEmbeddingFunction(device="cpu") # 如果有GPU可以改为"cuda" + +# 4. 创建 Collection +milvus_client = MilvusClient(uri=MILVUS_URI) +if milvus_client.has_collection(COLLECTION_NAME): + print(f"--> 正在删除已存在的 Collection '{COLLECTION_NAME}'...") + milvus_client.drop_collection(COLLECTION_NAME) + +fields = [ + FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100), + FieldSchema(name="img_id", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="path", dtype=DataType.VARCHAR, max_length=256), + FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=256), + FieldSchema(name="description", dtype=DataType.VARCHAR, max_length=4096), + FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=64), + FieldSchema(name="location", dtype=DataType.VARCHAR, max_length=128), + FieldSchema(name="environment", dtype=DataType.VARCHAR, max_length=64), + FieldSchema(name="sparse_vector", dtype=DataType.SPARSE_FLOAT_VECTOR), + FieldSchema(name="dense_vector", dtype=DataType.FLOAT_VECTOR, dim=ef.dim["dense"]) +] + +# 如果集合不存在,则创建它及索引 +if not milvus_client.has_collection(COLLECTION_NAME): + print(f"--> 正在创建 Collection '{COLLECTION_NAME}'...") + schema = CollectionSchema(fields, description="使用SigLIP的龙混合检索示例") + # 创建集合 + collection = Collection(name=COLLECTION_NAME, schema=schema, consistency_level="Strong") + print("--> Collection 创建成功。") + + # 5. 创建索引 + print("--> 正在为新集合创建索引...") + sparse_index = {"index_type": "SPARSE_INVERTED_INDEX", "metric_type": "IP"} + collection.create_index("sparse_vector", sparse_index) + print("稀疏向量索引创建成功。") + + dense_index = {"index_type": "AUTOINDEX", "metric_type": "IP"} + collection.create_index("dense_vector", dense_index) + print("密集向量索引创建成功。") + +collection = Collection(COLLECTION_NAME) + +# 6. 加载数据并插入 +collection.load() +print(f"--> Collection '{COLLECTION_NAME}' 已加载到内存。") + +if collection.is_empty: + print(f"--> Collection 为空,开始插入数据...") + if not os.path.exists(DATA_PATH): + raise FileNotFoundError(f"数据文件未找到: {DATA_PATH}") + with open(DATA_PATH, 'r', encoding='utf-8') as f: + dataset = json.load(f) + + docs, metadata = [], [] + for item in dataset: + parts = [ + item.get('title', ''), + item.get('description', ''), + item.get('location', ''), + item.get('environment', ''), + # *item.get('combat_details', {}).get('combat_style', []), + # *item.get('combat_details', {}).get('abilities_used', []), + # item.get('scene_info', {}).get('time_of_day', '') + ] + docs.append(' '.join(filter(None, parts))) + metadata.append(item) + print(f"--> 数据加载完成,共 {len(docs)} 条。") + + print("--> 正在生成向量嵌入...") + embeddings = ef(docs) + print("--> 向量生成完成。") + + print("--> 正在分批插入数据...") + # 为每个字段准备批量数据 + img_ids = [doc["img_id"] for doc in metadata] + paths = [doc["path"] for doc in metadata] + titles = [doc["title"] for doc in metadata] + descriptions = [doc["description"] for doc in metadata] + categories = [doc["category"] for doc in metadata] + locations = [doc["location"] for doc in metadata] + environments = [doc["environment"] for doc in metadata] + + # 获取向量 - 注意SigLIP返回的格式与BGE-M3不同 + sparse_vectors = [] + dense_vectors = embeddings["dense"].tolist() + + # 将稀疏矩阵转换为Milvus可接受的格式 + sparse_matrix = embeddings["sparse"] + for i in range(sparse_matrix.shape[0]): + row = sparse_matrix.getrow(i) + # 创建稀疏向量字典格式 + sparse_dict = {} + for j in range(row.nnz): + sparse_dict[row.indices[j]] = float(row.data[j]) + sparse_vectors.append(sparse_dict) + + # 插入数据 + collection.insert([ + img_ids, + paths, + titles, + descriptions, + categories, + locations, + environments, + sparse_vectors, + dense_vectors + ]) + + collection.flush() + print(f"--> 数据插入完成,总数: {collection.num_entities}") +else: + print(f"--> Collection 中已有 {collection.num_entities} 条数据,跳过插入。") + +# 7. 执行搜索 +search_query = "悬崖上的巨龙" +search_filter = 'category in ["western_dragon", "chinese_dragon", "movie_character"]' +top_k = 5 + +print(f"\n{'='*20} 开始混合搜索 {'='*20}") +print(f"查询: '{search_query}'") +print(f"过滤器: '{search_filter}'") + +# 生成查询向量 +query_embeddings = ef([search_query]) +dense_vec = query_embeddings["dense"][0].tolist() + +# 处理稀疏向量 +sparse_matrix = query_embeddings["sparse"] +sparse_row = sparse_matrix.getrow(0) +sparse_dict = {} +for j in range(sparse_row.nnz): + sparse_dict[sparse_row.indices[j]] = float(sparse_row.data[j]) + +# 打印向量信息 +print("\n=== 向量信息 ===") +print(f"密集向量维度: {len(dense_vec)}") +print(f"密集向量前5个元素: {dense_vec[:5]}") +print(f"密集向量范数: {np.linalg.norm(dense_vec):.4f}") + +print(f"\n稀疏向量维度: {sparse_matrix.shape[1]}") +print(f"稀疏向量非零元素数量: {sparse_row.nnz}") +print("稀疏向量前5个非零元素:") +for i, (idx, val) in enumerate(list(sparse_dict.items())[:5]): + print(f" - 索引: {idx}, 值: {val:.4f}") +density = (sparse_row.nnz / sparse_matrix.shape[1] * 100) +print(f"\n稀疏向量密度: {density:.8f}%") + +# 定义搜索参数 +search_params = {"metric_type": "IP", "params": {}} + +# 先执行单独的搜索 +print("\n--- [单独] 密集向量搜索结果 ---") +dense_results = collection.search( + [dense_vec], + anns_field="dense_vector", + param=search_params, + limit=top_k, + expr=search_filter, + output_fields=["title", "path", "description", "category", "location", "environment"] +)[0] + +for i, hit in enumerate(dense_results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('path')}") + print(f" 描述: {hit.entity.get('description')[:100]}...") + +print("\n--- [单独] 稀疏向量搜索结果 ---") +sparse_results = collection.search( + [sparse_dict], + anns_field="sparse_vector", + param=search_params, + limit=top_k, + expr=search_filter, + output_fields=["title", "path", "description", "category", "location", "environment"] +)[0] + +for i, hit in enumerate(sparse_results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('path')}") + print(f" 描述: {hit.entity.get('description')[:100]}...") + +print("\n--- [混合] 稀疏+密集向量搜索结果 ---") +# 创建 RRF 融合器 +rerank = RRFRanker(k=60) + +# 创建搜索请求 +dense_req = AnnSearchRequest([dense_vec], "dense_vector", search_params, limit=top_k) +sparse_req = AnnSearchRequest([sparse_dict], "sparse_vector", search_params, limit=top_k) + +# 执行混合搜索 +results = collection.hybrid_search( + [sparse_req, dense_req], + rerank=rerank, + limit=top_k, + output_fields=["title", "path", "description", "category", "location", "environment"] +)[0] + +# 打印最终结果 +for i, hit in enumerate(results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('path')}") + print(f" 描述: {hit.entity.get('description')[:100]}...") + +# 8. 清理资源 +milvus_client.release_collection(collection_name=COLLECTION_NAME) +print(f"已从内存中释放 Collection: '{COLLECTION_NAME}'") +milvus_client.drop_collection(COLLECTION_NAME) +print(f"已删除 Collection: '{COLLECTION_NAME}'") \ No newline at end of file diff --git a/code/C4/02_text_to_metadata_filter.py b/code/C4/02_text_to_metadata_filter.py new file mode 100644 index 0000000..2ea2626 --- /dev/null +++ b/code/C4/02_text_to_metadata_filter.py @@ -0,0 +1,111 @@ +import os +from langchain_deepseek import ChatDeepSeek +from langchain_community.document_loaders import BiliBiliLoader +from langchain.chains.query_constructor.base import AttributeInfo +from langchain.retrievers.self_query.base import SelfQueryRetriever +from langchain_community.vectorstores import Chroma +from langchain_huggingface import HuggingFaceEmbeddings +import logging + +logging.basicConfig(level=logging.INFO) + +# 1. 初始化视频数据 +video_urls = [ + "https://www.bilibili.com/video/BV1Bo4y1A7FU", + "https://www.bilibili.com/video/BV1ug4y157xA", + "https://www.bilibili.com/video/BV1yh411V7ge", +] + +bili = [] +try: + loader = BiliBiliLoader(video_urls=video_urls) + docs = loader.load() + + for doc in docs: + original = doc.metadata + + # 提取基本元数据字段 + metadata = { + 'title': original.get('title', '未知标题'), + 'author': original.get('owner', {}).get('name', '未知作者'), + 'source': original.get('bvid', '未知ID'), + 'view_count': original.get('stat', {}).get('view', 0), + 'length': original.get('duration', 0), + } + + doc.metadata = metadata + bili.append(doc) + +except Exception as e: + print(f"加载BiliBili视频失败: {str(e)}") + +if not bili: + print("没有成功加载任何视频,程序退出") + exit() + +# 2. 创建向量存储 +embed_model = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5") +vectorstore = Chroma.from_documents(bili, embed_model) + +# 3. 配置元数据字段信息 +metadata_field_info = [ + AttributeInfo( + name="title", + description="视频标题(字符串)", + type="string", + ), + AttributeInfo( + name="author", + description="视频作者(字符串)", + type="string", + ), + AttributeInfo( + name="view_count", + description="视频观看次数(整数)", + type="integer", + ), + AttributeInfo( + name="length", + description="视频长度(整数)", + type="integer" + ) +] + +# 4. 创建自查询检索器 +llm = ChatDeepSeek( + model="deepseek-chat", + temperature=0, + api_key=os.getenv("DEEPSEEK_API_KEY") + ) + +retriever = SelfQueryRetriever.from_llm( + llm=llm, + vectorstore=vectorstore, + document_contents="记录视频标题、作者、观看次数等信息的视频元数据", + metadata_field_info=metadata_field_info, + enable_limit=True, + verbose=True +) + +# 5. 执行查询示例 +queries = [ + "时间最短的视频", + "时长大于600秒的视频" +] + +for query in queries: + print(f"\n--- 查询: '{query}' ---") + results = retriever.invoke(query) + if results: + for doc in results: + title = doc.metadata.get('title', '未知标题') + author = doc.metadata.get('author', '未知作者') + view_count = doc.metadata.get('view_count', '未知') + length = doc.metadata.get('length', '未知') + print(f"标题: {title}") + print(f"作者: {author}") + print(f"观看次数: {view_count}") + print(f"时长: {length}秒") + print("="*50) + else: + print("未找到匹配的视频") diff --git a/code/C4/03_text2sql_demo.py b/code/C4/03_text2sql_demo.py new file mode 100644 index 0000000..2677c40 --- /dev/null +++ b/code/C4/03_text2sql_demo.py @@ -0,0 +1,220 @@ +import os +import sys +import sqlite3 + +# 添加text2sql模块路径 +sys.path.append(os.path.join(os.path.dirname(__file__), 'text2sql')) + +from text2sql.text2sql_agent import SimpleText2SQLAgent + + +def setup_demo(): + """设置演示环境""" + print("=== Text2SQL框架演示 ===\n") + + # 检查API密钥 + api_key = os.getenv("DEEPSEEK_API_KEY") + if not api_key: + print("先设置DEEPSEEK_API_KEY环境变量") + return None + + # 创建演示数据库 + print("创建演示数据库...") + db_path = create_demo_database() + + # 初始化Text2SQL代理 + print("初始化Text2SQL代理...") + agent = SimpleText2SQLAgent(api_key=api_key) + + # 连接数据库 + print("连接数据库...") + if not agent.connect_database(db_path): + print("数据库连接失败!") + return None + + # 加载知识库 + print("加载知识库...") + try: + agent.load_knowledge_base() + print("知识库加载成功!") + except Exception as e: + print(f"知识库加载失败: {str(e)}") + return None + + return agent, db_path + + +def create_demo_database(): + """创建演示数据库""" + db_path = "text2sql_demo.db" + + if os.path.exists(db_path): + os.remove(db_path) + + conn = sqlite3.connect(db_path) + cursor = conn.cursor() + + # 创建用户表 + cursor.execute(""" + CREATE TABLE users ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + email TEXT UNIQUE, + age INTEGER, + city TEXT + ) + """) + + # 创建产品表 + cursor.execute(""" + CREATE TABLE products ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + category TEXT, + price REAL, + stock INTEGER + ) + """) + + # 创建订单表 + cursor.execute(""" + CREATE TABLE orders ( + id INTEGER PRIMARY KEY, + user_id INTEGER, + product_id INTEGER, + quantity INTEGER, + order_date TEXT, + total_price REAL, + FOREIGN KEY (user_id) REFERENCES users(id), + FOREIGN KEY (product_id) REFERENCES products(id) + ) + """) + + # 插入示例数据 + users_data = [ + (1, '张三', 'zhangsan@email.com', 25, '北京'), + (2, '李四', 'lisi@email.com', 32, '上海'), + (3, '王五', 'wangwu@email.com', 28, '广州'), + (4, '赵六', 'zhaoliu@email.com', 35, '深圳'), + (5, '陈七', 'chenqi@email.com', 29, '杭州'), + ] + + products_data = [ + (1, 'iPhone 15', '电子产品', 7999.0, 50), + (2, 'MacBook Pro', '电子产品', 12999.0, 20), + (3, 'Nike运动鞋', '服装', 599.0, 100), + (4, '办公椅', '家具', 899.0, 30), + (5, '台灯', '家具', 199.0, 80), + (6, 'iPad', '电子产品', 3999.0, 40), + (7, 'Adidas外套', '服装', 399.0, 60), + ] + + orders_data = [ + (1, 1, 1, 1, '2024-01-15', 7999.0), + (2, 2, 3, 2, '2024-01-16', 1198.0), + (3, 3, 5, 1, '2024-01-17', 199.0), + (4, 1, 2, 1, '2024-01-18', 12999.0), + (5, 4, 4, 1, '2024-01-19', 899.0), + (6, 5, 6, 1, '2024-01-20', 3999.0), + (7, 2, 7, 1, '2024-01-21', 399.0), + ] + + cursor.executemany("INSERT INTO users VALUES (?, ?, ?, ?, ?)", users_data) + cursor.executemany("INSERT INTO products VALUES (?, ?, ?, ?, ?)", products_data) + cursor.executemany("INSERT INTO orders VALUES (?, ?, ?, ?, ?, ?)", orders_data) + + conn.commit() + conn.close() + + print(f"演示数据库已创建: {db_path}") + return db_path + + +def run_demo_queries(agent): + """运行演示查询""" + demo_questions = [ + "查询所有用户的姓名和邮箱", + "年龄大于30的用户有哪些", + "哪些产品的库存少于50", + "查询来自北京的用户的所有订单", + "统计每个城市的用户数量", + "查询价格在500-8000之间的产品" + ] + + print("\n开始运行演示查询...\n") + + success_count = 0 + + for i, question in enumerate(demo_questions, 1): + print(f"问题 {i}: {question}") + print("-" * 60) + + try: + result = agent.query(question) + + if result["success"]: + print(f"成功! SQL: {result['sql']}") + + if isinstance(result["results"], dict) and "rows" in result["results"]: + count = result["results"]["count"] + print(f"返回 {count} 行数据") + + # 显示前2行数据 + if count > 0: + for j, row in enumerate(result["results"]["rows"][:2]): + row_str = " | ".join(f"{k}: {v}" for k, v in row.items()) + print(f" {j+1}. {row_str}") + + if count > 2: + print(f" ... 还有 {count - 2} 行") + else: + print(f"结果: {result['results']}") + + success_count += 1 + + else: + print(f"失败: {result['error']}") + print(f"SQL: {result['sql']}") + + except Exception as e: + print(f"执行错误: {str(e)}") + + print() + + # 输出统计 + total_count = len(demo_questions) + + +def cleanup(agent, db_path): + """清理资源""" + print("\n清理资源...") + + if agent: + agent.cleanup() + + if os.path.exists(db_path): + os.remove(db_path) + print(f"已删除演示数据库: {db_path}") + + +def main(): + """主函数""" + # 设置演示环境 + setup_result = setup_demo() + + if setup_result is None: + return + + agent, db_path = setup_result + + try: + # 运行演示查询 + run_demo_queries(agent) + + finally: + # 清理资源 + cleanup(agent, db_path) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/code/C4/03_text2sql_demo_v2.py b/code/C4/03_text2sql_demo_v2.py new file mode 100644 index 0000000..9e75844 --- /dev/null +++ b/code/C4/03_text2sql_demo_v2.py @@ -0,0 +1,377 @@ +import os +import json +import sqlite3 +import numpy as np +from typing import List, Dict, Any +from sentence_transformers import SentenceTransformer +from sklearn.feature_extraction.text import TfidfVectorizer +from sklearn.metrics.pairwise import cosine_similarity +from pymilvus import connections, MilvusClient, FieldSchema, CollectionSchema, DataType, Collection + + +class BGESmallEmbeddingFunction: + """BGE-Small中文嵌入函数,用于Text2SQL知识库向量化""" + + def __init__(self, model_name="BAAI/bge-small-zh-v1.5", device="cpu"): + self.model_name = model_name + self.device = device + self.model = SentenceTransformer(model_name, device=device) + self.dense_dim = self.model.get_sentence_embedding_dimension() + + def encode_text(self, texts): + """编码文本为密集向量""" + if isinstance(texts, str): + texts = [texts] + + embeddings = self.model.encode( + texts, + normalize_embeddings=True, + batch_size=16, + convert_to_numpy=True + ) + + return embeddings + + @property + def dim(self): + """返回向量维度""" + return self.dense_dim + + +class SimpleKnowledgeBase: + """简化的知识库,使用BGE-Small进行向量检索""" + + def __init__(self, milvus_uri: str = "http://localhost:19530"): + self.milvus_uri = milvus_uri + self.collection_name = "text2sql_knowledge_base" + self.milvus_client = None + self.collection = None + + self.embedding_function = BGESmallEmbeddingFunction( + model_name="BAAI/bge-small-zh-v1.5", + device="cpu" + ) + + self.sql_examples = [] + self.table_schemas = [] + self.data_loaded = False + + def connect_milvus(self): + """连接Milvus数据库""" + connections.connect(uri=self.milvus_uri) + self.milvus_client = MilvusClient(uri=self.milvus_uri) + return True + + def create_collection(self): + """创建Milvus集合""" + if not self.milvus_client: + self.connect_milvus() + + if self.milvus_client.has_collection(self.collection_name): + self.milvus_client.drop_collection(self.collection_name) + + fields = [ + FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100), + FieldSchema(name="content_type", dtype=DataType.VARCHAR, max_length=50), + FieldSchema(name="question", dtype=DataType.VARCHAR, max_length=1000), + FieldSchema(name="sql", dtype=DataType.VARCHAR, max_length=2000), + FieldSchema(name="description", dtype=DataType.VARCHAR, max_length=1000), + FieldSchema(name="table_name", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=self.embedding_function.dim) + ] + + schema = CollectionSchema(fields, description="Text2SQL知识库") + self.collection = Collection(name=self.collection_name, schema=schema, consistency_level="Strong") + + index_params = {"index_type": "AUTOINDEX", "metric_type": "IP", "params": {}} + self.collection.create_index("embedding", index_params) + + return True + + def load_data(self): + """加载知识库数据""" + data_dir = os.path.join(os.path.dirname(__file__), "data") + + self.load_sql_examples(data_dir) + self.load_table_schemas(data_dir) + self.vectorize_and_store() + + self.data_loaded = True + + def load_sql_examples(self, data_dir: str): + """加载SQL示例""" + sql_examples_path = os.path.join(data_dir, "qsql_examples.json") + + default_examples = [ + {"question": "查询所有用户信息", "sql": "SELECT * FROM users", "description": "获取用户记录", "database": "sqlite"}, + {"question": "年龄大于30的用户", "sql": "SELECT * FROM users WHERE age > 30", "description": "年龄筛选", "database": "sqlite"}, + {"question": "统计用户总数", "sql": "SELECT COUNT(*) as user_count FROM users", "description": "用户计数", "database": "sqlite"}, + {"question": "查询库存不足的产品", "sql": "SELECT * FROM products WHERE stock < 50", "description": "库存筛选", "database": "sqlite"}, + {"question": "查询用户订单信息", "sql": "SELECT u.name, p.name, o.quantity FROM orders o JOIN users u ON o.user_id = u.id JOIN products p ON o.product_id = p.id", "description": "订单详情", "database": "sqlite"}, + {"question": "按城市统计用户", "sql": "SELECT city, COUNT(*) as count FROM users GROUP BY city", "description": "城市分组", "database": "sqlite"} + ] + + if os.path.exists(sql_examples_path): + with open(sql_examples_path, 'r', encoding='utf-8') as f: + self.sql_examples = json.load(f) + else: + self.sql_examples = default_examples + os.makedirs(data_dir, exist_ok=True) + with open(sql_examples_path, 'w', encoding='utf-8') as f: + json.dump(self.sql_examples, f, ensure_ascii=False, indent=2) + + def load_table_schemas(self, data_dir: str): + """加载表结构信息""" + schema_path = os.path.join(data_dir, "table_schemas.json") + + default_schemas = [ + { + "table_name": "users", + "description": "用户信息表", + "columns": [ + {"name": "id", "type": "INTEGER", "description": "用户ID"}, + {"name": "name", "type": "VARCHAR", "description": "用户姓名"}, + {"name": "age", "type": "INTEGER", "description": "用户年龄"}, + {"name": "email", "type": "VARCHAR", "description": "邮箱地址"}, + {"name": "city", "type": "VARCHAR", "description": "所在城市"}, + {"name": "created_at", "type": "DATETIME", "description": "创建时间"} + ] + }, + { + "table_name": "products", + "description": "产品信息表", + "columns": [ + {"name": "id", "type": "INTEGER", "description": "产品ID"}, + {"name": "product_name", "type": "VARCHAR", "description": "产品名称"}, + {"name": "category", "type": "VARCHAR", "description": "产品类别"}, + {"name": "price", "type": "DECIMAL", "description": "产品价格"}, + {"name": "stock", "type": "INTEGER", "description": "库存数量"}, + {"name": "description", "type": "TEXT", "description": "产品描述"} + ] + }, + { + "table_name": "orders", + "description": "订单信息表", + "columns": [ + {"name": "id", "type": "INTEGER", "description": "订单ID"}, + {"name": "user_id", "type": "INTEGER", "description": "用户ID"}, + {"name": "product_id", "type": "INTEGER", "description": "产品ID"}, + {"name": "quantity", "type": "INTEGER", "description": "购买数量"}, + {"name": "total_price", "type": "DECIMAL", "description": "总价格"}, + {"name": "order_date", "type": "DATETIME", "description": "订单日期"} + ] + } + ] + + if os.path.exists(schema_path): + with open(schema_path, 'r', encoding='utf-8') as f: + self.table_schemas = json.load(f) + else: + self.table_schemas = default_schemas + os.makedirs(data_dir, exist_ok=True) + with open(schema_path, 'w', encoding='utf-8') as f: + json.dump(self.table_schemas, f, ensure_ascii=False, indent=2) + + def vectorize_and_store(self): + """向量化数据并存储到Milvus""" + self.create_collection() + + all_texts = [] + all_metadata = [] + + for example in self.sql_examples: + text = f"问题: {example['question']} SQL: {example['sql']} 描述: {example.get('description', '')}" + all_texts.append(text) + all_metadata.append({ + "content_type": "sql_example", + "question": example['question'], + "sql": example['sql'], + "description": example.get('description', ''), + "table_name": "" + }) + + for schema in self.table_schemas: + columns_desc = ", ".join([f"{col['name']} ({col['type']}): {col.get('description', '')}" + for col in schema['columns']]) + text = f"表 {schema['table_name']}: {schema['description']} 字段: {columns_desc}" + all_texts.append(text) + all_metadata.append({ + "content_type": "table_schema", + "question": "", + "sql": "", + "description": schema['description'], + "table_name": schema['table_name'] + }) + + embeddings = self.embedding_function.encode_text(all_texts) + + insert_data = [] + for i, (embedding, metadata) in enumerate(zip(embeddings, all_metadata)): + insert_data.append([ + metadata["content_type"], + metadata["question"], + metadata["sql"], + metadata["description"], + metadata["table_name"], + embedding.tolist() + ]) + + self.collection.insert(insert_data) + self.collection.flush() + self.collection.load() + + def search(self, query: str, top_k: int = 5) -> List[Dict[str, Any]]: + """搜索相关的知识库信息""" + if not self.data_loaded: + self.load_data() + + query_embedding = self.embedding_function.encode_text([query])[0] + + search_params = {"metric_type": "IP", "params": {}} + results = self.collection.search( + [query_embedding.tolist()], + anns_field="embedding", + param=search_params, + limit=top_k, + output_fields=["content_type", "question", "sql", "description", "table_name"] + )[0] + + formatted_results = [] + for hit in results: + result = { + "score": float(hit.distance), + "content_type": hit.entity.get("content_type"), + "question": hit.entity.get("question"), + "sql": hit.entity.get("sql"), + "description": hit.entity.get("description"), + "table_name": hit.entity.get("table_name") + } + formatted_results.append(result) + + return formatted_results + + def _fallback_search(self, query: str, top_k: int) -> List[Dict[str, Any]]: + """降级搜索方法(简单文本匹配)""" + results = [] + query_lower = query.lower() + + for example in self.sql_examples: + question_lower = example['question'].lower() + sql_lower = example['sql'].lower() + + score = 0 + for word in query_lower.split(): + if word in question_lower: + score += 2 + if word in sql_lower: + score += 1 + + if score > 0: + results.append({ + "score": score, + "content_type": "sql_example", + "question": example['question'], + "sql": example['sql'], + "description": example.get('description', ''), + "table_name": "" + }) + + results.sort(key=lambda x: x['score'], reverse=True) + return results[:top_k] + + def add_sql_example(self, question: str, sql: str, description: str = ""): + """添加新的SQL示例""" + new_example = { + "question": question, + "sql": sql, + "description": description, + "database": "sqlite" + } + self.sql_examples.append(new_example) + + data_dir = os.path.join(os.path.dirname(__file__), "data") + sql_examples_path = os.path.join(data_dir, "qsql_examples.json") + + with open(sql_examples_path, 'w', encoding='utf-8') as f: + json.dump(self.sql_examples, f, ensure_ascii=False, indent=2) + + if self.collection and self.data_loaded: + text = f"问题: {question} SQL: {sql} 描述: {description}" + embedding = self.embedding_function.encode_text([text])[0] + + insert_data = [[ + "sql_example", + question, + sql, + description, + "", + embedding.tolist() + ]] + + self.collection.insert(insert_data) + self.collection.flush() + + def cleanup(self): + """清理资源""" + if self.collection: + self.collection.release() + + if self.milvus_client and self.milvus_client.has_collection(self.collection_name): + self.milvus_client.drop_collection(self.collection_name) + + +def demo(): + """简单演示""" + # 模型测试 + embedding_function = BGESmallEmbeddingFunction() + test_texts = ["查询用户", "统计数据"] + embeddings = embedding_function.encode_text(test_texts) + print(f"向量维度: {embeddings.shape}") + + # 数据库查询演示 + db_path = "demo.db" + + if os.path.exists(db_path): + os.remove(db_path) + + conn = sqlite3.connect(db_path) + cursor = conn.cursor() + + cursor.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER, city TEXT)") + + users_data = [(1, '张三', 25, '北京'), (2, '李四', 32, '上海'), (3, '王五', 35, '深圳')] + cursor.executemany("INSERT INTO users VALUES (?, ?, ?, ?)", users_data) + + conn.commit() + + # 执行查询 + test_sqls = [ + ("查询所有用户", "SELECT * FROM users"), + ("年龄大于30的用户", "SELECT * FROM users WHERE age > 30"), + ("统计用户总数", "SELECT COUNT(*) FROM users") + ] + + for i, (question, sql) in enumerate(test_sqls, 1): + print(f"\n问题 {i}: {question}") + print("-" * 40) + print(f"SQL: {sql}") + + cursor.execute(sql) + rows = cursor.fetchall() + + if rows: + print(f"返回 {len(rows)} 行数据") + for j, row in enumerate(rows[:2], 1): + print(f" {j}. {row}") + + if len(rows) > 2: + print(f" ... 还有 {len(rows) - 2} 行") + else: + print("无数据返回") + + conn.close() + os.remove(db_path) + + +if __name__ == "__main__": + demo() \ No newline at end of file diff --git a/code/C4/04_text_to_metadata_filter_v2.py b/code/C4/04_text_to_metadata_filter_v2.py new file mode 100644 index 0000000..6746e8a --- /dev/null +++ b/code/C4/04_text_to_metadata_filter_v2.py @@ -0,0 +1,149 @@ +import os +from langchain_deepseek import ChatDeepSeek +from langchain_community.document_loaders import BiliBiliLoader +from langchain.chains.query_constructor.base import AttributeInfo +from openai import OpenAI +from langchain_community.vectorstores import Chroma +from langchain_huggingface import HuggingFaceEmbeddings +import logging + +logging.basicConfig(level=logging.INFO) + +# 1. 初始化视频数据 +video_urls = [ + "https://www.bilibili.com/video/BV1Bo4y1A7FU", + "https://www.bilibili.com/video/BV1ug4y157xA", + "https://www.bilibili.com/video/BV1yh411V7ge", +] + +bili = [] +try: + loader = BiliBiliLoader(video_urls=video_urls) + docs = loader.load() + + for doc in docs: + original = doc.metadata + + # 提取基本元数据字段 + metadata = { + 'title': original.get('title', '未知标题'), + 'author': original.get('owner', {}).get('name', '未知作者'), + 'source': original.get('bvid', '未知ID'), + 'view_count': original.get('stat', {}).get('view', 0), + 'length': original.get('duration', 0), + } + + doc.metadata = metadata + bili.append(doc) + +except Exception as e: + print(f"加载BiliBili视频失败: {str(e)}") + +if not bili: + print("没有成功加载任何视频,程序退出") + exit() + +# 2. 创建向量存储 +embed_model = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5") +vectorstore = Chroma.from_documents(bili, embed_model) + +# 3. 配置元数据字段信息 +metadata_field_info = [ + AttributeInfo( + name="title", + description="视频标题(字符串)", + type="string", + ), + AttributeInfo( + name="author", + description="视频作者(字符串)", + type="string", + ), + AttributeInfo( + name="view_count", + description="视频观看次数(整数)", + type="integer", + ), + AttributeInfo( + name="length", + description="视频长度(整数)", + type="integer" + ) +] + +# 4. 初始化LLM客户端 +client = OpenAI( + base_url="https://api.deepseek.com", + api_key=os.getenv("DEEPSEEK_API_KEY") +) + +# 5. 获取所有文档用于排序 +all_documents = vectorstore.similarity_search("", k=len(bili)) + +# 6. 执行查询示例 +queries = [ + "时间最短的视频", + "播放量最高的视频" +] + +for query in queries: + print(f"\n--- 原始查询: '{query}' ---") + + # 使用大模型将自然语言转换为排序指令 + prompt = f"""你是一个智能助手,请将用户的问题转换成一个用于排序视频的JSON指令。 + +你需要识别用户想要排序的字段和排序方向。 +- 排序字段必须是 'view_count' (观看次数) 或 'length' (时长) 之一。 +- 排序方向必须是 'asc' (升序) 或 'desc' (降序) 之一。 + +例如: +- '时间最短的视频' 或 '哪个视频时间最短' 应转换为 {{"sort_by": "length", "order": "asc"}} +- '播放量最高的视频' 或 '哪个视频最火' 应转换为 {{"sort_by": "view_count", "order": "desc"}} + +请根据以下问题生成JSON指令: +原始问题: "{query}" + +JSON指令:""" + + response = client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0, + response_format={"type": "json_object"} + ) + + try: + import json + instruction_str = response.choices[0].message.content + instruction = json.loads(instruction_str) + print(f"--- 生成的排序指令: {instruction} ---") + + sort_by = instruction.get('sort_by') + order = instruction.get('order') + + if sort_by in ['length', 'view_count'] and order in ['asc', 'desc']: + # 在代码中执行排序 + reverse_order = (order == 'desc') + sorted_docs = sorted(all_documents, key=lambda doc: doc.metadata.get(sort_by, 0), reverse=reverse_order) + + # 获取排序后的第一个结果 + if sorted_docs: + doc = sorted_docs[0] + title = doc.metadata.get('title', '未知标题') + author = doc.metadata.get('author', '未知作者') + view_count = doc.metadata.get('view_count', '未知') + length = doc.metadata.get('length', '未知') + print(f"标题: {title}") + print(f"作者: {author}") + print(f"观看次数: {view_count}") + print(f"时长: {length}秒") + print("="*50) + else: + print("没有找到任何视频") + else: + print("生成的指令无效,无法执行排序") + + except (json.JSONDecodeError, KeyError) as e: + print(f"解析或执行指令失败: {e}") diff --git a/code/C4/05_llm_based_routing.py b/code/C4/05_llm_based_routing.py new file mode 100644 index 0000000..72ecc85 --- /dev/null +++ b/code/C4/05_llm_based_routing.py @@ -0,0 +1,72 @@ +import os +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.output_parsers import StrOutputParser +from langchain_deepseek import ChatDeepSeek +from langchain_core.runnables import RunnableBranch + +llm = ChatDeepSeek( + model="deepseek-chat", + temperature=0, + api_key=os.getenv("DEEPSEEK_API_KEY") + ) + +# 1. 设置不同菜系的处理链 +sichuan_prompt = ChatPromptTemplate.from_template( + "你是一位川菜大厨。请用正宗的川菜做法,回答关于「{question}」的问题。" +) +sichuan_chain = sichuan_prompt | llm | StrOutputParser() + +cantonese_prompt = ChatPromptTemplate.from_template( + "你是一位粤菜大厨。请用经典的粤菜做法,回答关于「{question}」的问题。" +) +cantonese_chain = cantonese_prompt | llm | StrOutputParser() + +# 定义备用通用链 +general_prompt = ChatPromptTemplate.from_template( + "你是一个美食助手。请回答关于「{question}」的问题。" +) +general_chain = general_prompt | llm | StrOutputParser() + + +# 2. 创建路由链 +classifier_prompt = ChatPromptTemplate.from_template( + """根据用户问题中提到的菜品,将其分类为:['川菜', '粤菜', 或 '其他']。 + 不要解释你的理由,只返回一个单词的分类结果。 + 问题: {question}""" +) +classifier_chain = classifier_prompt | llm | StrOutputParser() + +# 定义路由分支 +router_branch = RunnableBranch( + (lambda x: "川菜" in x["topic"], sichuan_chain), + (lambda x: "粤菜" in x["topic"], cantonese_chain), + general_chain # 默认选项 +) + +# 组合成完整路由链 +full_router_chain = {"topic": classifier_chain, "question": lambda x: x["question"]} | router_branch +print("完整的路由链创建成功。\n") + + +# 3. 运行演示查询 +demo_questions = [ + {"question": "麻婆豆腐怎么做?"}, # 应该路由到川菜 + {"question": "白切鸡的正宗做法是什么?"}, # 应该路由到粤菜 + {"question": "番茄炒蛋需要放糖吗?"} # 应该路由到其他 +] + +for i, item in enumerate(demo_questions, 1): + question = item["question"] + print(f"\n--- 问题 {i}: {question} ---") + + try: + # 获取路由决策 + topic = classifier_chain.invoke({"question": question}) + print(f"路由决策: {topic}") + + # 执行完整链 + result = full_router_chain.invoke(item) + print(f"回答: {result}") + except Exception as e: + print(f"执行错误: {e}") + diff --git a/code/C4/06_embedding_based_routing.py b/code/C4/06_embedding_based_routing.py new file mode 100644 index 0000000..af4414f --- /dev/null +++ b/code/C4/06_embedding_based_routing.py @@ -0,0 +1,83 @@ +import os +from langchain_core.prompts import PromptTemplate +from langchain_core.output_parsers import StrOutputParser +from langchain_deepseek import ChatDeepSeek +from langchain_huggingface import HuggingFaceEmbeddings +from langchain_core.runnables import RunnableLambda, RunnablePassthrough, RunnablePassthrough +from langchain_community.utils.math import cosine_similarity +import numpy as np + +# 1. 定义路由描述 +sichuan_route_prompt = "你是一位处理川菜的专家。用户的问题是关于麻辣、辛香、重口味的菜肴,例如水煮鱼、麻婆豆腐、鱼香肉丝、宫保鸡丁、花椒、海椒等。" +cantonese_route_prompt = "你是一位处理粤菜的专家。用户的问题是关于清淡、鲜美、原汁原味的菜肴,例如白切鸡、老火靓汤、虾饺、云吞面等。" + +route_prompts = [sichuan_route_prompt, cantonese_route_prompt] +route_names = ["川菜", "粤菜"] + +# 初始化嵌入模型,并对路由描述进行向量化 +embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5") +route_prompt_embeddings = embeddings.embed_documents(route_prompts) +print(f"已定义 {len(route_names)} 个路由: {', '.join(route_names)}") + +# 2. 定义不同路由的目标链 +llm = ChatDeepSeek( + model="deepseek-chat", + temperature=0, + api_key=os.getenv("DEEPSEEK_API_KEY") + ) + +# 定义川菜和粤菜处理链 +sichuan_chain = ( + PromptTemplate.from_template("你是一位川菜大厨。请用正宗的川菜做法,回答关于「{query}」的问题。") + | llm + | StrOutputParser() +) +cantonese_chain = ( + PromptTemplate.from_template("你是一位粤菜大厨。请用经典的粤菜做法,回答关于「{query}」的问题。") + | llm + | StrOutputParser() +) + +route_map = { "川菜": sichuan_chain, "粤菜": cantonese_chain } +print("川菜和粤菜的处理链创建成功。\n") + +# 3. 创建路由函数 +def route(info): + # 对用户查询进行嵌入 + query_embedding = embeddings.embed_query(info["query"]) + + # 计算与各路由提示的余弦相似度 + similarity_scores = cosine_similarity([query_embedding], route_prompt_embeddings)[0] + + # 找到最相似的路由 + chosen_route_index = np.argmax(similarity_scores) + chosen_route_name = route_names[chosen_route_index] + + print(f"路由决策: 检测到问题与“{chosen_route_name}”最相似。") + + # 获取对应的处理链 + chosen_chain = route_map[chosen_route_name] + + # 直接调用选中的链并返回结果 + return chosen_chain.invoke(info) + +# 创建完整的路由链 +full_chain = RunnableLambda(route) + + +# 4. 运行演示查询 +demo_queries = [ + "水煮鱼怎么做才嫩?", # 应该路由到川菜 + "如何做一碗清淡的云吞面?", # 应该路由到粤菜 + "麻婆豆腐的核心调料是什么?", # 应该路由到川菜 +] + +for i, query in enumerate(demo_queries, 1): + print(f"\n--- 问题 {i}: {query} ---") + try: + # 传入字典,full_chain 会直接返回最终答案 + result = full_chain.invoke({"query": query}) + print(f"回答: {result}") + except Exception as e: + print(f"执行错误: {e}") + diff --git a/code/C4/07_rerank_and_refine.py b/code/C4/07_rerank_and_refine.py new file mode 100644 index 0000000..8a441fe --- /dev/null +++ b/code/C4/07_rerank_and_refine.py @@ -0,0 +1,186 @@ +import os +from langchain_community.vectorstores import FAISS +from langchain.retrievers import ContextualCompressionRetriever +from langchain.retrievers.document_compressors import LLMChainExtractor +from langchain_community.embeddings import HuggingFaceBgeEmbeddings +from langchain.text_splitter import RecursiveCharacterTextSplitter +from langchain_community.document_loaders import TextLoader +from langchain_deepseek import ChatDeepSeek + +# 导入ColBERT重排器需要的模块 +from langchain.retrievers.document_compressors.base import BaseDocumentCompressor +from langchain.retrievers.document_compressors import DocumentCompressorPipeline +from langchain_core.documents import Document +from typing import Sequence +import torch +from transformers import AutoTokenizer, AutoModel +import torch.nn.functional as F + +class ColBERTReranker(BaseDocumentCompressor): + """ColBERT重排器""" + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + model_name = "bert-base-uncased" + + # 加载模型和分词器 + object.__setattr__(self, 'tokenizer', AutoTokenizer.from_pretrained(model_name)) + object.__setattr__(self, 'model', AutoModel.from_pretrained(model_name)) + self.model.eval() + print(f"ColBERT模型加载完成") + + def encode_text(self, texts): + """ColBERT文本编码""" + inputs = self.tokenizer( + texts, + return_tensors="pt", + padding=True, + truncation=True, + max_length=128 + ) + + with torch.no_grad(): + outputs = self.model(**inputs) + + embeddings = outputs.last_hidden_state + embeddings = F.normalize(embeddings, p=2, dim=-1) + + return embeddings + + def calculate_colbert_similarity(self, query_emb, doc_embs, query_mask, doc_masks): + """ColBERT相似度计算(MaxSim操作)""" + scores = [] + + for i, doc_emb in enumerate(doc_embs): + doc_mask = doc_masks[i:i+1] + + # 计算相似度矩阵 + similarity_matrix = torch.matmul(query_emb, doc_emb.unsqueeze(0).transpose(-2, -1)) + + # 应用文档mask + doc_mask_expanded = doc_mask.unsqueeze(1) + similarity_matrix = similarity_matrix.masked_fill(~doc_mask_expanded.bool(), -1e9) + + # MaxSim操作 + max_sim_per_query_token = similarity_matrix.max(dim=-1)[0] + + # 应用查询mask + query_mask_expanded = query_mask.unsqueeze(0) + max_sim_per_query_token = max_sim_per_query_token.masked_fill(~query_mask_expanded.bool(), 0) + + # 求和得到最终分数 + colbert_score = max_sim_per_query_token.sum(dim=-1).item() + scores.append(colbert_score) + + return scores + + def compress_documents( + self, + documents: Sequence[Document], + query: str, + callbacks=None, + ) -> Sequence[Document]: + """对文档进行ColBERT重排序""" + if len(documents) == 0: + return documents + + # 编码查询 + query_inputs = self.tokenizer( + [query], + return_tensors="pt", + padding=True, + truncation=True, + max_length=128 + ) + + with torch.no_grad(): + query_outputs = self.model(**query_inputs) + query_embeddings = F.normalize(query_outputs.last_hidden_state, p=2, dim=-1) + + # 编码文档 + doc_texts = [doc.page_content for doc in documents] + doc_inputs = self.tokenizer( + doc_texts, + return_tensors="pt", + padding=True, + truncation=True, + max_length=128 + ) + + with torch.no_grad(): + doc_outputs = self.model(**doc_inputs) + doc_embeddings = F.normalize(doc_outputs.last_hidden_state, p=2, dim=-1) + + # 计算ColBERT相似度 + scores = self.calculate_colbert_similarity( + query_embeddings, + doc_embeddings, + query_inputs['attention_mask'], + doc_inputs['attention_mask'] + ) + + # 排序并返回前5个 + scored_docs = list(zip(documents, scores)) + scored_docs.sort(key=lambda x: x[1], reverse=True) + reranked_docs = [doc for doc, _ in scored_docs[:5]] + + return reranked_docs + + + +# 初始化配置 +hf_bge_embeddings = HuggingFaceBgeEmbeddings( + model_name="BAAI/bge-large-zh-v1.5" +) + +llm = ChatDeepSeek( + model="deepseek-chat", + temperature=0.1, + api_key=os.getenv("DEEPSEEK_API_KEY") +) + +# 1. 加载和处理文档 +loader = TextLoader("../../data/C4/txt/ai.txt", encoding="utf-8") +documents = loader.load() +text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100) +docs = text_splitter.split_documents(documents) + +# 2. 创建向量存储和基础检索器 +vectorstore = FAISS.from_documents(docs, hf_bge_embeddings) +base_retriever = vectorstore.as_retriever(search_kwargs={"k": 20}) + +# 3. 设置ColBERT重排序器 +reranker = ColBERTReranker() + +# 4. 设置LLM压缩器 +compressor = LLMChainExtractor.from_llm(llm) + +# 5. 使用DocumentCompressorPipeline组装压缩管道 +# 流程: ColBERT重排 -> LLM压缩 +pipeline_compressor = DocumentCompressorPipeline( + transformers=[reranker, compressor] +) + +# 6. 创建最终的压缩检索器 +final_retriever = ContextualCompressionRetriever( + base_compressor=pipeline_compressor, + base_retriever=base_retriever +) + +# 7. 执行查询并展示结果 +query = "AI还有哪些缺陷需要克服?" +print(f"\n{'='*20} 开始执行查询 {'='*20}") +print(f"查询: {query}\n") + +# 7.1 基础检索结果 +print(f"--- (1) 基础检索结果 (Top 20) ---") +base_results = base_retriever.get_relevant_documents(query) +for i, doc in enumerate(base_results): + print(f" [{i+1}] {doc.page_content[:100]}...\n") + +# 7.2 使用管道压缩器的最终结果 +print(f"\n--- (2) 管道压缩后结果 (ColBERT重排 + LLM压缩) ---") +final_results = final_retriever.get_relevant_documents(query) +for i, doc in enumerate(final_results): + print(f" [{i+1}] {doc.page_content}\n") diff --git a/code/C4/text2sql/__init__.py b/code/C4/text2sql/__init__.py new file mode 100644 index 0000000..9a16b9d --- /dev/null +++ b/code/C4/text2sql/__init__.py @@ -0,0 +1,17 @@ +""" +简化的Text2SQL框架 +基于RAGFlow方案实现的Text2SQL框架 +""" + +__version__ = "1.0.0" +__author__ = "RAG Team" + +from .knowledge_base import SimpleKnowledgeBase +from .sql_generator import SimpleSQLGenerator +from .text2sql_agent import SimpleText2SQLAgent + +__all__ = [ + "SimpleKnowledgeBase", + "SimpleSQLGenerator", + "SimpleText2SQLAgent" +] \ No newline at end of file diff --git a/code/C4/text2sql/data/db_descriptions.json b/code/C4/text2sql/data/db_descriptions.json new file mode 100644 index 0000000..d532164 --- /dev/null +++ b/code/C4/text2sql/data/db_descriptions.json @@ -0,0 +1,57 @@ +[ + { + "table_name": "users", + "table_description": "用户信息表,存储注册用户的基本信息", + "columns": [ + {"name": "id", "description": "用户唯一标识符,主键", "type": "INT"}, + {"name": "name", "description": "用户姓名,不能为空", "type": "VARCHAR(100)"}, + {"name": "email", "description": "用户邮箱地址,必须唯一", "type": "VARCHAR(150)"}, + {"name": "age", "description": "用户年龄", "type": "INT"}, + {"name": "created_at", "description": "用户注册时间", "type": "TIMESTAMP"} + ] + }, + { + "table_name": "orders", + "table_description": "订单表,记录用户的购买订单信息", + "columns": [ + {"name": "id", "description": "订单唯一标识符,主键", "type": "INT"}, + {"name": "user_id", "description": "下单用户的ID,外键关联users表", "type": "INT"}, + {"name": "product_name", "description": "购买的产品名称", "type": "VARCHAR(200)"}, + {"name": "quantity", "description": "购买数量", "type": "INT"}, + {"name": "price", "description": "订单总价格", "type": "DECIMAL(10,2)"}, + {"name": "order_date", "description": "下单时间", "type": "TIMESTAMP"} + ] + }, + { + "table_name": "products", + "table_description": "产品表,存储商城中所有产品的信息", + "columns": [ + {"name": "id", "description": "产品唯一标识符,主键", "type": "INT"}, + {"name": "name", "description": "产品名称", "type": "VARCHAR(200)"}, + {"name": "category", "description": "产品分类", "type": "VARCHAR(100)"}, + {"name": "price", "description": "产品单价", "type": "DECIMAL(10,2)"}, + {"name": "stock", "description": "库存数量", "type": "INT"}, + {"name": "description", "description": "产品详细描述", "type": "TEXT"} + ] + }, + { + "table_name": "categories", + "table_description": "产品分类表,定义产品的分类信息", + "columns": [ + {"name": "id", "description": "分类唯一标识符,主键", "type": "INT"}, + {"name": "name", "description": "分类名称,必须唯一", "type": "VARCHAR(100)"}, + {"name": "description", "description": "分类描述", "type": "TEXT"} + ] + }, + { + "table_name": "order_items", + "table_description": "订单明细表,存储订单中包含的具体商品信息", + "columns": [ + {"name": "id", "description": "订单明细唯一标识符,主键", "type": "INT"}, + {"name": "order_id", "description": "关联的订单ID,外键", "type": "INT"}, + {"name": "product_id", "description": "关联的产品ID,外键", "type": "INT"}, + {"name": "quantity", "description": "该商品在订单中的数量", "type": "INT"}, + {"name": "unit_price", "description": "该商品的单价(下单时的价格)", "type": "DECIMAL(10,2)"} + ] + } +] \ No newline at end of file diff --git a/code/C4/text2sql/data/ddl_examples.json b/code/C4/text2sql/data/ddl_examples.json new file mode 100644 index 0000000..6188223 --- /dev/null +++ b/code/C4/text2sql/data/ddl_examples.json @@ -0,0 +1,27 @@ +[ + { + "table_name": "users", + "ddl_statement": "CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, email VARCHAR(150) UNIQUE, age INT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)", + "description": "用户信息表,存储用户基本信息" + }, + { + "table_name": "orders", + "ddl_statement": "CREATE TABLE orders (id INT PRIMARY KEY AUTO_INCREMENT, user_id INT, product_name VARCHAR(200), quantity INT, price DECIMAL(10,2), order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id))", + "description": "订单表,存储用户订单信息" + }, + { + "table_name": "products", + "ddl_statement": "CREATE TABLE products (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(200) NOT NULL, category VARCHAR(100), price DECIMAL(10,2), stock INT DEFAULT 0, description TEXT)", + "description": "产品表,存储产品基本信息" + }, + { + "table_name": "categories", + "ddl_statement": "CREATE TABLE categories (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL UNIQUE, description TEXT)", + "description": "产品分类表" + }, + { + "table_name": "order_items", + "ddl_statement": "CREATE TABLE order_items (id INT PRIMARY KEY AUTO_INCREMENT, order_id INT, product_id INT, quantity INT, unit_price DECIMAL(10,2), FOREIGN KEY (order_id) REFERENCES orders(id), FOREIGN KEY (product_id) REFERENCES products(id))", + "description": "订单明细表,存储订单中的具体商品信息" + } +] \ No newline at end of file diff --git a/code/C4/text2sql/data/qsql_examples.json b/code/C4/text2sql/data/qsql_examples.json new file mode 100644 index 0000000..1ecb46a --- /dev/null +++ b/code/C4/text2sql/data/qsql_examples.json @@ -0,0 +1,62 @@ +[ + { + "question": "查询所有用户的姓名和邮箱", + "sql": "SELECT name, email FROM users", + "database": "ecommerce" + }, + { + "question": "查找年龄大于25岁的用户", + "sql": "SELECT * FROM users WHERE age > 25", + "database": "ecommerce" + }, + { + "question": "查询每个用户的订单数量", + "sql": "SELECT u.name, COUNT(o.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.name", + "database": "ecommerce" + }, + { + "question": "查找最近7天的订单", + "sql": "SELECT * FROM orders WHERE order_date >= DATE_SUB(NOW(), INTERVAL 7 DAY)", + "database": "ecommerce" + }, + { + "question": "查询总销售额最高的前5个产品", + "sql": "SELECT p.name, SUM(oi.quantity * oi.unit_price) as total_sales FROM products p JOIN order_items oi ON p.id = oi.product_id GROUP BY p.id, p.name ORDER BY total_sales DESC LIMIT 5", + "database": "ecommerce" + }, + { + "question": "查询某个用户的所有订单", + "sql": "SELECT o.*, u.name as user_name FROM orders o JOIN users u ON o.user_id = u.id WHERE u.name = '张三'", + "database": "ecommerce" + }, + { + "question": "查询价格在100到500之间的产品", + "sql": "SELECT * FROM products WHERE price BETWEEN 100 AND 500", + "database": "ecommerce" + }, + { + "question": "查询库存少于10的产品", + "sql": "SELECT * FROM products WHERE stock < 10", + "database": "ecommerce" + }, + { + "question": "查询每个分类的产品数量", + "sql": "SELECT category, COUNT(*) as product_count FROM products GROUP BY category", + "database": "ecommerce" + }, + { + "question": "查询订单总金额大于1000的订单", + "sql": "SELECT o.*, SUM(oi.quantity * oi.unit_price) as total_amount FROM orders o JOIN order_items oi ON o.id = oi.order_id GROUP BY o.id HAVING total_amount > 1000", + "database": "ecommerce" + }, + { + "question": "查询没有下过订单的用户", + "sql": "SELECT u.* FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE o.id IS NULL", + "database": "ecommerce" + }, + { + "question": "查询平均订单金额", + "sql": "SELECT AVG(total_amount) as avg_order_amount FROM (SELECT o.id, SUM(oi.quantity * oi.unit_price) as total_amount FROM orders o JOIN order_items oi ON o.id = oi.order_id GROUP BY o.id) as order_totals", + "database": "ecommerce" + } +] \ No newline at end of file diff --git a/code/C4/text2sql/knowledge_base.py b/code/C4/text2sql/knowledge_base.py new file mode 100644 index 0000000..454f125 --- /dev/null +++ b/code/C4/text2sql/knowledge_base.py @@ -0,0 +1,184 @@ +import json +import os +from typing import List, Dict, Any +from pymilvus import MilvusClient, FieldSchema, CollectionSchema, DataType +from pymilvus.model.hybrid import BGEM3EmbeddingFunction + + +class SimpleKnowledgeBase: + """知识库""" + + def __init__(self, milvus_uri: str = "http://localhost:19530"): + self.milvus_uri = milvus_uri + self.client = MilvusClient(uri=milvus_uri) + self.embedding_function = BGEM3EmbeddingFunction(use_fp16=False, device="cpu") + self.collection_name = "text2sql_kb" + self._setup_collection() + + def _setup_collection(self): + """设置集合""" + if self.client.has_collection(self.collection_name): + self.client.drop_collection(self.collection_name) + + # 定义字段 + fields = [ + FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100), + FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=4096), + FieldSchema(name="type", dtype=DataType.VARCHAR, max_length=32), # ddl, qsql, description + FieldSchema(name="dense_vector", dtype=DataType.FLOAT_VECTOR, dim=self.embedding_function.dim["dense"]) + ] + + schema = CollectionSchema(fields, description="Text2SQL知识库") + + # 创建集合 + self.client.create_collection( + collection_name=self.collection_name, + schema=schema, + consistency_level="Strong" + ) + + # 创建索引 + index_params = self.client.prepare_index_params() + index_params.add_index( + field_name="dense_vector", + index_type="AUTOINDEX", + metric_type="IP" + ) + + self.client.create_index( + collection_name=self.collection_name, + index_params=index_params + ) + + def load_data(self): + """加载所有知识库数据""" + data_dir = os.path.join(os.path.dirname(__file__), "data") + + # 加载DDL数据 + ddl_path = os.path.join(data_dir, "ddl_examples.json") + if os.path.exists(ddl_path): + with open(ddl_path, 'r', encoding='utf-8') as f: + ddl_data = json.load(f) + self._add_ddl_data(ddl_data) + + # 加载Q->SQL数据 + qsql_path = os.path.join(data_dir, "qsql_examples.json") + if os.path.exists(qsql_path): + with open(qsql_path, 'r', encoding='utf-8') as f: + qsql_data = json.load(f) + self._add_qsql_data(qsql_data) + + # 加载描述数据 + desc_path = os.path.join(data_dir, "db_descriptions.json") + if os.path.exists(desc_path): + with open(desc_path, 'r', encoding='utf-8') as f: + desc_data = json.load(f) + self._add_description_data(desc_data) + + # 加载集合到内存 + self.client.load_collection(collection_name=self.collection_name) + print("知识库数据加载完成") + + def _add_ddl_data(self, data: List[Dict]): + """添加DDL数据""" + contents = [] + types = [] + + for item in data: + content = f"表名: {item.get('table_name', '')}\n" + content += f"DDL: {item.get('ddl_statement', '')}\n" + content += f"描述: {item.get('description', '')}" + + contents.append(content) + types.append("ddl") + + self._insert_data(contents, types) + + def _add_qsql_data(self, data: List[Dict]): + """添加Q->SQL数据""" + contents = [] + types = [] + + for item in data: + content = f"问题: {item.get('question', '')}\n" + content += f"SQL: {item.get('sql', '')}" + + contents.append(content) + types.append("qsql") + + self._insert_data(contents, types) + + def _add_description_data(self, data: List[Dict]): + """添加描述数据""" + contents = [] + types = [] + + for item in data: + content = f"表名: {item.get('table_name', '')}\n" + content += f"表描述: {item.get('table_description', '')}\n" + + columns = item.get('columns', []) + if columns: + content += "字段信息:\n" + for col in columns: + content += f" - {col.get('name', '')}: {col.get('description', '')} ({col.get('type', '')})\n" + + contents.append(content) + types.append("description") + + self._insert_data(contents, types) + + def _insert_data(self, contents: List[str], types: List[str]): + """插入数据""" + if not contents: + return + + # 生成嵌入 + embeddings = self.embedding_function(contents) + + # 构建插入数据,每一行是一个字典 + data_to_insert = [] + for i in range(len(contents)): + data_to_insert.append({ + "content": contents[i], + "type": types[i], + "dense_vector": embeddings["dense"][i] + }) + + # 插入数据 + result = self.client.insert( + collection_name=self.collection_name, + data=data_to_insert + ) + + def search(self, query: str, top_k: int = 5) -> List[Dict[str, Any]]: + """搜索相关内容""" + self.client.load_collection(collection_name=self.collection_name) + + query_embeddings = self.embedding_function([query]) + + search_results = self.client.search( + collection_name=self.collection_name, + data=query_embeddings["dense"], + anns_field="dense_vector", + search_params={"metric_type": "IP"}, + limit=top_k, + output_fields=["content", "type"] + ) + + results = [] + for hit in search_results[0]: + results.append({ + "content": hit["entity"]["content"], + "type": hit["entity"]["type"], + "score": hit["distance"] + }) + + return results + + def cleanup(self): + """清理资源""" + try: + self.client.drop_collection(self.collection_name) + except: + pass \ No newline at end of file diff --git a/code/C4/text2sql/sql_generator.py b/code/C4/text2sql/sql_generator.py new file mode 100644 index 0000000..dfe8cd2 --- /dev/null +++ b/code/C4/text2sql/sql_generator.py @@ -0,0 +1,113 @@ +import os +from typing import List, Dict, Any +from langchain_deepseek import ChatDeepSeek +from langchain.schema import HumanMessage, SystemMessage + + +class SimpleSQLGenerator: + """简化的SQL生成器""" + + def __init__(self, api_key: str = None): + self.llm = ChatDeepSeek( + model="deepseek-chat", + temperature=0, + api_key=api_key or os.getenv("DEEPSEEK_API_KEY") + ) + + def generate_sql(self, user_query: str, knowledge_results: List[Dict[str, Any]]) -> str: + """生成SQL语句""" + # 构建上下文 + context = self._build_context(knowledge_results) + + # 构建提示 + prompt = f"""你是一个SQL专家。请根据以下信息将用户问题转换为SQL查询语句。 + +数据库信息: +{context} + +用户问题:{user_query} + +要求: +1. 只返回SQL语句,不要包含任何解释 +2. 确保SQL语法正确 +3. 使用上下文中提供的表名和字段名 +4. 如果需要JOIN,请根据表结构进行合理关联 + +SQL语句:""" + + messages = [HumanMessage(content=prompt)] + response = self.llm.invoke(messages) + + # 清理SQL语句 + sql = response.content.strip() + if sql.startswith("```sql"): + sql = sql[6:] + if sql.startswith("```"): + sql = sql[3:] + if sql.endswith("```"): + sql = sql[:-3] + + return sql.strip() + + def fix_sql(self, original_sql: str, error_message: str, knowledge_results: List[Dict[str, Any]]) -> str: + """修复SQL语句""" + context = self._build_context(knowledge_results) + + prompt = f"""请修复以下SQL语句的错误。 + +数据库信息: +{context} + +原始SQL: +{original_sql} + +错误信息: +{error_message} + +请返回修复后的SQL语句(只返回SQL,不要解释):""" + + messages = [HumanMessage(content=prompt)] + response = self.llm.invoke(messages) + + # 清理SQL语句 + fixed_sql = response.content.strip() + if fixed_sql.startswith("```sql"): + fixed_sql = fixed_sql[6:] + if fixed_sql.startswith("```"): + fixed_sql = fixed_sql[3:] + if fixed_sql.endswith("```"): + fixed_sql = fixed_sql[:-3] + + return fixed_sql.strip() + + def _build_context(self, knowledge_results: List[Dict[str, Any]]) -> str: + """构建上下文信息""" + context = "" + + # 按类型分组 + ddl_info = [] + qsql_examples = [] + descriptions = [] + + for result in knowledge_results: + if result["type"] == "ddl": + ddl_info.append(result["content"]) + elif result["type"] == "qsql": + qsql_examples.append(result["content"]) + elif result["type"] == "description": + descriptions.append(result["content"]) + + # 构建上下文 + if ddl_info: + context += "=== 表结构信息 ===\n" + context += "\n".join(ddl_info) + "\n\n" + + if descriptions: + context += "=== 表和字段描述 ===\n" + context += "\n".join(descriptions) + "\n\n" + + if qsql_examples: + context += "=== 查询示例 ===\n" + context += "\n".join(qsql_examples) + "\n\n" + + return context \ No newline at end of file diff --git a/code/C4/text2sql/text2sql_agent.py b/code/C4/text2sql/text2sql_agent.py new file mode 100644 index 0000000..fa671dd --- /dev/null +++ b/code/C4/text2sql/text2sql_agent.py @@ -0,0 +1,213 @@ +import sqlite3 +import os +from typing import Dict, Any, List, Tuple +from .knowledge_base import SimpleKnowledgeBase +from .sql_generator import SimpleSQLGenerator + + +class SimpleText2SQLAgent: + """Text2SQL代理""" + + def __init__(self, milvus_uri: str = "http://localhost:19530", api_key: str = None): + """初始化代理""" + self.knowledge_base = SimpleKnowledgeBase(milvus_uri) + self.sql_generator = SimpleSQLGenerator(api_key) + self.db_path = None + self.connection = None + + # 配置参数 + self.max_retry_count = 3 + self.top_k_retrieval = 5 + self.max_result_rows = 100 + + def connect_database(self, db_path: str) -> bool: + """连接SQLite数据库""" + try: + self.db_path = db_path + self.connection = sqlite3.connect(db_path) + print(f"成功连接到数据库: {db_path}") + return True + except Exception as e: + print(f"数据库连接失败: {str(e)}") + return False + + def load_knowledge_base(self): + """加载知识库""" + self.knowledge_base.load_data() + + def query(self, user_question: str) -> Dict[str, Any]: + """执行Text2SQL查询""" + if not self.connection: + return { + "success": False, + "error": "数据库未连接", + "sql": None, + "results": None + } + + print(f"\n=== 处理查询: {user_question} ===") + + # 1. 从知识库检索 + print("检索知识库...") + knowledge_results = self.knowledge_base.search(user_question, self.top_k_retrieval) + print(f"检索到 {len(knowledge_results)} 条相关信息") + + # 2. 生成SQL + print("生成SQL...") + sql = self.sql_generator.generate_sql(user_question, knowledge_results) + print(f"生成的SQL: {sql}") + + # 3. 执行SQL(带重试) + retry_count = 0 + while retry_count < self.max_retry_count: + print(f"执行SQL (尝试 {retry_count + 1}/{self.max_retry_count})...") + + success, result = self._execute_sql(sql) + + if success: + print("SQL执行成功!") + return { + "success": True, + "error": None, + "sql": sql, + "results": result, + "retry_count": retry_count + } + else: + print(f"SQL执行失败: {result}") + + if retry_count < self.max_retry_count - 1: + print("尝试修复SQL...") + sql = self.sql_generator.fix_sql(sql, result, knowledge_results) + print(f"修复后的SQL: {sql}") + + retry_count += 1 + + return { + "success": False, + "error": f"超过最大重试次数 ({self.max_retry_count})", + "sql": sql, + "results": None, + "retry_count": retry_count + } + + def _execute_sql(self, sql: str) -> Tuple[bool, Any]: + """执行SQL语句""" + try: + cursor = self.connection.cursor() + + # 添加LIMIT限制 + if sql.strip().upper().startswith('SELECT') and 'LIMIT' not in sql.upper(): + sql = f"{sql.rstrip(';')} LIMIT {self.max_result_rows}" + + cursor.execute(sql) + + if sql.strip().upper().startswith('SELECT'): + # 查询语句 + columns = [desc[0] for desc in cursor.description] + rows = cursor.fetchall() + + results = [] + for row in rows: + result_row = {} + for i, value in enumerate(row): + result_row[columns[i]] = value + results.append(result_row) + + cursor.close() + return True, { + "columns": columns, + "rows": results, + "count": len(results) + } + else: + # 非查询语句 + self.connection.commit() + cursor.close() + return True, "SQL执行成功" + + except Exception as e: + return False, str(e) + + def add_example(self, question: str, sql: str): + """添加新的Q->SQL示例""" + # 简化版本:直接保存到文件 + data_dir = os.path.join(os.path.dirname(__file__), "data") + qsql_path = os.path.join(data_dir, "qsql_examples.json") + + try: + import json + + # 读取现有数据 + if os.path.exists(qsql_path): + with open(qsql_path, 'r', encoding='utf-8') as f: + data = json.load(f) + else: + data = [] + + # 添加新示例 + data.append({ + "question": question, + "sql": sql, + "database": "sqlite" + }) + + # 保存 + with open(qsql_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + + print(f"已添加新示例: {question}") + + except Exception as e: + print(f"添加示例失败: {str(e)}") + + def get_table_info(self) -> List[Dict[str, Any]]: + """获取数据库表信息""" + if not self.connection: + return [] + + try: + cursor = self.connection.cursor() + + # 获取所有表名 + cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") + tables = cursor.fetchall() + + table_info = [] + for table in tables: + table_name = table[0] + + # 获取表结构 + cursor.execute(f"PRAGMA table_info({table_name})") + columns = cursor.fetchall() + + table_info.append({ + "table_name": table_name, + "columns": [ + { + "name": col[1], + "type": col[2], + "nullable": not col[3], + "default": col[4], + "primary_key": bool(col[5]) + } + for col in columns + ] + }) + + cursor.close() + return table_info + + except Exception as e: + print(f"获取表信息失败: {str(e)}") + return [] + + def cleanup(self): + """清理资源""" + if self.connection: + self.connection.close() + self.connection = None + print("数据库连接已关闭") + + self.knowledge_base.cleanup() + print("知识库已清理") \ No newline at end of file diff --git a/code/C4/work_rerank_and_refine.py b/code/C4/work_rerank_and_refine.py new file mode 100644 index 0000000..4c1d2cf --- /dev/null +++ b/code/C4/work_rerank_and_refine.py @@ -0,0 +1,193 @@ +import os +from langchain_community.vectorstores import FAISS +from langchain.retrievers import ContextualCompressionRetriever +from langchain.retrievers.document_compressors import LLMChainExtractor +from langchain_community.embeddings import HuggingFaceBgeEmbeddings +from langchain.text_splitter import RecursiveCharacterTextSplitter +from langchain_community.document_loaders import TextLoader +from langchain_deepseek import ChatDeepSeek + +# 导入ColBERT重排器需要的模块 +from langchain.retrievers.document_compressors.base import BaseDocumentCompressor +from langchain.retrievers.document_compressors import DocumentCompressorPipeline +from langchain_core.documents import Document +from typing import Sequence +import torch +from transformers import AutoTokenizer, AutoModel +import torch.nn.functional as F + +class ColBERTReranker(BaseDocumentCompressor): + """ColBERT重排器""" + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + model_name = "bert-base-uncased" + + # 加载模型和分词器 + object.__setattr__(self, 'tokenizer', AutoTokenizer.from_pretrained(model_name)) + object.__setattr__(self, 'model', AutoModel.from_pretrained(model_name)) + self.model.eval() + print(f"ColBERT模型加载完成") + + def encode_text(self, texts): + """ColBERT文本编码""" + inputs = self.tokenizer( + texts, + return_tensors="pt", + padding=True, + truncation=True, + max_length=128 + ) + + with torch.no_grad(): + outputs = self.model(**inputs) + + embeddings = outputs.last_hidden_state + embeddings = F.normalize(embeddings, p=2, dim=-1) + + return embeddings + + def calculate_colbert_similarity(self, query_emb, doc_embs, query_mask, doc_masks): + """ColBERT相似度计算(MaxSim操作)""" + scores = [] + + for i, doc_emb in enumerate(doc_embs): + doc_mask = doc_masks[i:i+1] + + # 计算相似度矩阵 + similarity_matrix = torch.matmul(query_emb, doc_emb.unsqueeze(0).transpose(-2, -1)) + + # 应用文档mask + doc_mask_expanded = doc_mask.unsqueeze(1) + similarity_matrix = similarity_matrix.masked_fill(~doc_mask_expanded.bool(), -1e9) + + # MaxSim操作 + max_sim_per_query_token = similarity_matrix.max(dim=-1)[0] + + # 应用查询mask + query_mask_expanded = query_mask.unsqueeze(0) + max_sim_per_query_token = max_sim_per_query_token.masked_fill(~query_mask_expanded.bool(), 0) + + # 求和得到最终分数 + colbert_score = max_sim_per_query_token.sum(dim=-1).item() + scores.append(colbert_score) + + return scores + + def compress_documents( + self, + documents: Sequence[Document], + query: str, + callbacks=None, + ) -> Sequence[Document]: + """对文档进行ColBERT重排序""" + if len(documents) == 0: + return documents + + # 编码查询 + query_inputs = self.tokenizer( + [query], + return_tensors="pt", + padding=True, + truncation=True, + max_length=128 + ) + + with torch.no_grad(): + query_outputs = self.model(**query_inputs) + query_embeddings = F.normalize(query_outputs.last_hidden_state, p=2, dim=-1) + + # 编码文档 + doc_texts = [doc.page_content for doc in documents] + doc_inputs = self.tokenizer( + doc_texts, + return_tensors="pt", + padding=True, + truncation=True, + max_length=128 + ) + + with torch.no_grad(): + doc_outputs = self.model(**doc_inputs) + doc_embeddings = F.normalize(doc_outputs.last_hidden_state, p=2, dim=-1) + + # 计算ColBERT相似度 + scores = self.calculate_colbert_similarity( + query_embeddings, + doc_embeddings, + query_inputs['attention_mask'], + doc_inputs['attention_mask'] + ) + + # 排序并返回前5个 + scored_docs = list(zip(documents, scores)) + scored_docs.sort(key=lambda x: x[1], reverse=True) + reranked_docs = [doc for doc, _ in scored_docs[:5]] + + return reranked_docs + + + +# 初始化配置 +hf_bge_embeddings = HuggingFaceBgeEmbeddings( + model_name="BAAI/bge-large-zh-v1.5" +) + +llm = ChatDeepSeek( + model="deepseek-chat", + temperature=0.1, + api_key=os.getenv("DEEPSEEK_API_KEY") +) + +# 1. 加载和处理文档 +loader = TextLoader("../../data/C4/txt/ai.txt", encoding="utf-8") +documents = loader.load() + +# 优化分块策略:减少重叠,使用中文友好的分隔符 +text_splitter = RecursiveCharacterTextSplitter( + separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""], + chunk_size=300, + chunk_overlap=20 +) + +docs = text_splitter.split_documents(documents) + +# 2. 创建向量存储和基础检索器 +vectorstore = FAISS.from_documents(docs, hf_bge_embeddings) +base_retriever = vectorstore.as_retriever(search_kwargs={"k": 20}) + +# 3. 设置ColBERT重排序器 +reranker = ColBERTReranker() + +# 4. 设置LLM压缩器 +compressor = LLMChainExtractor.from_llm(llm) + +# 5. 使用DocumentCompressorPipeline组装压缩管道 +# 流程: ColBERT重排 -> LLM压缩 +pipeline_compressor = DocumentCompressorPipeline( + transformers=[reranker, compressor] +) + +# 6. 创建最终的压缩检索器 +final_retriever = ContextualCompressionRetriever( + base_compressor=pipeline_compressor, + base_retriever=base_retriever +) + +# 7. 执行查询并展示结果 +query = "AI还有哪些缺陷需要克服?" +print(f"\n{'='*20} 开始执行查询 {'='*20}") +print(f"查询: {query}\n") + +# 7.1 基础检索结果 +print(f"--- (1) 基础检索结果 (Top 20) ---") +base_results = base_retriever.get_relevant_documents(query) +for i, doc in enumerate(base_results): + print(f" [{i+1}] {doc.page_content[:100]}...\n") + +# 7.2 使用管道压缩器的最终结果 +print(f"\n--- (2) 管道压缩后结果 (ColBERT重排 + LLM压缩) ---") +final_results = final_retriever.get_relevant_documents(query) +for i, doc in enumerate(final_results): + print(f" [{i+1}] {doc.page_content}\n") diff --git a/code/C5/01_pydantic.py b/code/C5/01_pydantic.py new file mode 100644 index 0000000..5e06620 --- /dev/null +++ b/code/C5/01_pydantic.py @@ -0,0 +1,50 @@ +from typing import List +import os +from langchain_core.prompts import PromptTemplate +from pydantic import BaseModel, Field +from langchain_core.output_parsers import PydanticOutputParser +from langchain_deepseek import ChatDeepSeek + +# 初始化 LLM +llm = ChatDeepSeek( + model="deepseek-chat", + api_key=os.getenv("DEEPSEEK_API_KEY") +) + +# 1. 定义数据结构 +class PersonInfo(BaseModel): + name: str = Field(description="人物姓名") + age: int = Field(description="人物年龄") + skills: List[str] = Field(description="技能列表") + +# 2. 创建解析器 +parser = PydanticOutputParser(pydantic_object=PersonInfo) + +# 3. 创建提示模板 +prompt = PromptTemplate( + template="请根据以下文本提取信息。\n{format_instructions}\n{text}\n", + input_variables=["text"], + partial_variables={"format_instructions": parser.get_format_instructions()}, +) + +# # 打印格式指令 +# print("\n--- Format Instructions ---") +# print(parser.get_format_instructions()) +# print("--------------------------\n") + +# 4. 创建处理链 +chain = prompt | llm | parser + +# 5. 定义输入文本并执行调用链 +text = "张三今年30岁,他擅长Python和Go语言。" +result = chain.invoke({"text": text}) + +# 6. 打印结果 +print("\n--- 解析结果 ---") +print(f"结果类型: {type(result)}") +print(result) +print("--------------------\n") + +print(f"姓名: {result.name}") +print(f"年龄: {result.age}") +print(f"技能: {result.skills}") diff --git a/code/C5/02_function_calling_example.py b/code/C5/02_function_calling_example.py new file mode 100644 index 0000000..6a0ae0d --- /dev/null +++ b/code/C5/02_function_calling_example.py @@ -0,0 +1,71 @@ +from openai import OpenAI +import os + +# 初始化 OpenAI 客户端 +client = OpenAI( + api_key=os.getenv("DEEPSEEK_API_KEY"), + base_url="https://api.deepseek.com", +) + +# 定义一个函数,用于发送消息并获取模型的响应 +def send_messages(messages, tools=None): + response = client.chat.completions.create( + model="deepseek-chat", + messages=messages, + tools=tools, + tool_choice="auto", # 让模型自主决定是否调用工具 + ) + return response.choices[0].message + +# 1. 定义工具(函数)的 Schema +tools = [ + { + "type": "function", + "function": { + "name": "get_weather", + "description": "获取指定地点的天气信息", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "城市和省份,例如:杭州市, 浙江省", + } + }, + "required": ["location"] + }, + } + }, +] + +# 1. 用户提问,模型决策调用工具 +messages = [{"role": "user", "content": "杭州今天天气怎么样?"}] +print(f"User> {messages[0]['content']}\n") +message = send_messages(messages, tools=tools) + +# 2. 执行工具,并将结果返回模型 +if message.tool_calls: + print("--- 模型发起了工具调用 ---") + tool_call = message.tool_calls[0] + function_info = tool_call.function + print(f"工具名称: {function_info.name}") + print(f"工具参数: {function_info.arguments}") + + # 将模型的回复(包含工具调用请求)添加到消息历史中 + messages.append(message) + + # 模拟执行工具 + tool_output = "24℃,晴朗" + print(f"--- 执行工具并返回结果 ---") + print(f"工具执行结果: {tool_output}\n") + + # 将工具的执行结果作为一个新的消息添加到历史中 + messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": tool_output}) + + # 3. 第二次调用:将工具结果返回给模型,获取最终回答 + print("--- 将工具结果返回给模型,获取最终答案 ---") + final_message = send_messages(messages, tools=tools) + print(f"Model> {final_message.content}") +else: + # 如果模型没有调用工具,直接打印其回答 + print(f"Model> {message.content}") diff --git a/code/C6/01_llamaindex_evaluation_example.py b/code/C6/01_llamaindex_evaluation_example.py new file mode 100644 index 0000000..c73ef5e --- /dev/null +++ b/code/C6/01_llamaindex_evaluation_example.py @@ -0,0 +1,125 @@ +import os +import asyncio +from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings +from llama_index.core.node_parser import SentenceWindowNodeParser, SentenceSplitter +from llama_index.llms.deepseek import DeepSeek +from llama_index.embeddings.huggingface import HuggingFaceEmbedding +from llama_index.core.postprocessor import MetadataReplacementPostProcessor +from llama_index.core.evaluation import ( + FaithfulnessEvaluator, + RelevancyEvaluator, + BatchEvalRunner, +) +from llama_index.core.evaluation.eval_utils import get_results_df +from llama_index.core.evaluation import DatasetGenerator, QueryResponseDataset + +Settings.llm = DeepSeek(model="deepseek-chat", temperature=0.1, api_key=os.getenv("DEEPSEEK_API_KEY")) +Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en") + +async def main(): + # 1. 加载文档 + reader = SimpleDirectoryReader(input_files=["../../data/C3/pdf/IPCC_AR6_WGII_Chapter03.pdf"]) + documents = reader.load_data() + + # 1.1 加载或生成响应评估数据集 + if os.path.exists("./c6_response_eval_dataset.json"): + print("加载响应评估数据集...") + response_eval_dataset = QueryResponseDataset.from_json("./c6_response_eval_dataset.json") + else: + print("生成响应评估数据集...") + dataset_generator = DatasetGenerator.from_documents(documents[:10]) # 减少文档数量 + response_eval_dataset = await dataset_generator.agenerate_dataset_from_nodes(num=15) # 减少问题数量 + response_eval_dataset.save_json("./c6_response_eval_dataset.json") + + + + # 2. 构建两种不同的RAG查询引擎和检索器进行对比 + # 2.1 句子窗口检索 + sentence_parser = SentenceWindowNodeParser.from_defaults( + window_size=3, + window_metadata_key="window", + original_text_metadata_key="original_text", + ) + sentence_nodes = sentence_parser.get_nodes_from_documents(documents) + sentence_index = VectorStoreIndex(sentence_nodes) + + sentence_query_engine = sentence_index.as_query_engine( + similarity_top_k=2, + node_postprocessors=[ + MetadataReplacementPostProcessor(target_metadata_key="window") + ], + ) + sentence_retriever = sentence_index.as_retriever(similarity_top_k=2) + + # 2.2 常规分块检索(基准) + base_parser = SentenceSplitter(chunk_size=512) + base_nodes = base_parser.get_nodes_from_documents(documents) + base_index = VectorStoreIndex(base_nodes) + + base_query_engine = base_index.as_query_engine(similarity_top_k=2) + base_retriever = base_index.as_retriever(similarity_top_k=2) + + # 3. 初始化响应评估器 + faithfulness_evaluator = FaithfulnessEvaluator(llm=Settings.llm) + relevancy_evaluator = RelevancyEvaluator(llm=Settings.llm) + + # 4. 执行响应评估对比 + print("开始执行响应评估对比...") + evaluators = {"faithfulness": faithfulness_evaluator, "relevancy": relevancy_evaluator} + queries = response_eval_dataset.queries + + # 句子窗口检索响应评估 + print("\n=== 评估句子窗口检索 ===") + sentence_runner = BatchEvalRunner(evaluators, workers=2, show_progress=True) + sentence_response_results = await sentence_runner.aevaluate_queries( + queries=queries, query_engine=sentence_query_engine + ) + + # 常规分块检索响应评估 + print("\n=== 评估常规分块检索 ===") + base_runner = BatchEvalRunner(evaluators, workers=2, show_progress=True) + base_response_results = await base_runner.aevaluate_queries( + queries=queries, query_engine=base_query_engine + ) + + # 5. 分析并打印对比结果 + print("\n" + "="*60) + print("响应评估结果对比") + print("="*60) + + def calc_response_score(results, metric): + if results and results.get(metric): + scores = results[metric] + return sum(r.passing for r in scores) / len(scores) + return 0 + + # 句子窗口检索结果 + sentence_faith = calc_response_score(sentence_response_results, "faithfulness") + sentence_rel = calc_response_score(sentence_response_results, "relevancy") + + # 常规分块检索结果 + base_faith = calc_response_score(base_response_results, "faithfulness") + base_rel = calc_response_score(base_response_results, "relevancy") + + print(f"\n句子窗口检索:") + print(f" 忠实度: {sentence_faith:.1%}") + print(f" 相关性: {sentence_rel:.1%}") + + print(f"\n常规分块检索:") + print(f" 忠实度: {base_faith:.1%}") + print(f" 相关性: {base_rel:.1%}") + + + + # 简单对比 + if sentence_faith > base_faith and sentence_rel > base_rel: + print(f"\n✅ 句子窗口检索在两个维度上都优于常规分块检索") + elif sentence_faith > base_faith or sentence_rel > base_rel: + print(f"\n⚖️ 句子窗口检索在某些维度上有优势") + else: + print(f"\n❌ 句子窗口检索未显示明显优势") + + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/code/C6/c6_response_eval_dataset.json b/code/C6/c6_response_eval_dataset.json new file mode 100644 index 0000000..56f7fb2 --- /dev/null +++ b/code/C6/c6_response_eval_dataset.json @@ -0,0 +1,36 @@ +{ + "queries": { + "005f4f96-be64-48ad-ab90-38066f27e553": "Here are 10 diverse questions based solely on the provided context information:", + "f522fc46-fd0f-462b-9307-d1628b4da112": "**Citation Question**: How should the chapter \"Oceans and Coastal Ecosystems and Their Services\" be cited according to the IPCC AR6 WGII report?", + "64581ee3-eca7-4e50-84a0-dfde6f69abda": "**Authorship Question**: Who are the Coordinating Lead Authors of Chapter 3 in the IPCC AR6 WGII report?", + "73298e8c-51a6-4424-8d5c-aa6c1ae5eb81": "**Geographical Representation Question**: Which countries are represented by the Lead Authors of this chapter?", + "47a221d0-a95e-49f0-a0f8-13bcb2094c13": "**Page Range Question**: What is the page range for Chapter 3 in the IPCC AR6 WGII report?", + "64ff4db4-cd98-4741-a35c-e5d3ac8b7cd2": "**DOI Question**: What is the DOI (Digital Object Identifier) for Chapter 3 of the IPCC AR6 WGII report?", + "df2772ec-fbb1-4bde-9fde-87ecbbe242ed": "**Contributing Authors Question**: Name three Contributing Authors from different countries listed in the chapter.", + "6e4ed553-7dc6-4db0-8c97-f5dfe8540ed3": "**Review Editors Question**: Who are the Review Editors for this chapter, and which countries do they represent?", + "30d8e598-4a92-41e8-bafa-f62f503e2417": "**Chapter Scientist Question**: Who is credited as the Chapter Scientist for this chapter, and what is their affiliation?", + "dc190ac2-6d6a-496c-a742-4c799cacf9b9": "**Publisher Question**: Which publishers are responsible for the IPCC AR6 WGII report, and where are they based?", + "90275ad3-39f0-44b4-ae1a-da47454f4fe8": "**File Metadata Question**: What is the file size and creation date of the PDF document containing Chapter 3?", + "2d2edcb3-3f47-4a73-94ff-459290b231c4": "These questions test different aspects of the provided context, including citation format, authorship details, metadata, and structural elements of the report.", + "43f7eea1-2b43-4a99-ab50-fba2dd3471db": "Here are 10 diverse quiz/examination questions based strictly on the provided context:", + "ea03ffc2-674d-413a-9954-e708c4b0527b": "**Multiple Choice**: According to Section 3.2.2, which of the following is NOT listed as a physical change in the global ocean due to climate change?", + "242acbb0-4f32-4732-8cc0-6344f4e0f17c": "a) Sea level rise" + }, + "responses": { + "005f4f96-be64-48ad-ab90-38066f27e553": "Here are 10 diverse questions based solely on the provided context information:\n\n1. **Authorship**: Who are the Coordinating Lead Authors of Chapter 3 in the IPCC AR6 WGII report? \n - *Answer*: Sarah R. Cooley (USA) and David S. Schoeman (Australia). \n\n2. **Chapter Title**: What is the full title of Chapter 3 in the IPCC AR6 WGII report? \n - *Answer*: \"Oceans and Coastal Ecosystems and Their Services.\" \n\n3. **Page Range**: On which pages does Chapter 3 appear in the report? \n - *Answer*: Pages 379\u2013550. \n\n4. **DOI**: What is the Digital Object Identifier (DOI) for Chapter 3? \n - *Answer*: doi:10.1017/9781009325844.005. \n\n5. **Contributing Authors**: Name one Contributing Author from Nigeria. \n - *Answer*: Ibidun Adelekan. \n\n6. **Institutional Affiliation**: Which country/institution is Shin-Ichi Ito affiliated with as a Lead Author? \n - *Answer*: Japan. \n\n7. **Chapter Scientist**: Who served as the Chapter Scientist for this chapter? \n - *Answer*: Jessica Bolin (Australia). \n\n8. **Review Editors**: Who were the Review Editors for Chapter 3? \n - *Answer*: Karim Hilmi (Morocco) and Lisa Levin (USA). \n\n9. **Publisher**: Which publishers released the IPCC AR6 WGII report? \n - *Answer*: Cambridge University Press, Cambridge, UK, and New York, NY, USA. \n\n10. **File Metadata**: What is the file size of the PDF document containing Chapter 3? \n - *Answer*: 21,752,444 bytes (or ~21.75 MB). \n\nThese questions are derived exclusively from the provided context, ensuring no external knowledge is used.", + "f522fc46-fd0f-462b-9307-d1628b4da112": "The chapter \"Oceans and Coastal Ecosystems and Their Services\" should be cited as follows: \n\n**Cooley, S., D. Schoeman, L. Bopp, P. Boyd, S. Donner, D.Y. Ghebrehiwet, S.-I. Ito, W. Kiessling, P. Martinetto, E. Ojea, M.-F. Racault, B. Rost, and M. Skern-Mauritzen, 2022: Oceans and Coastal Ecosystems and Their Services.** In: *Climate Change 2022: Impacts, Adaptation and Vulnerability. Contribution of Working Group II to the Sixth Assessment Report of the Intergovernmental Panel on Climate Change* [H.-O. P\u00f6rtner, D.C. Roberts, M. Tignor, E.S. Poloczanska, K. Mintenbeck, A. Alegr\u00eda, M. Craig, S. Langsdorf, S. L\u00f6schke, V. M\u00f6ller, A. Okem, B. Rama (eds.)]. Cambridge University Press, Cambridge, UK and New York, NY, USA, pp. 379\u2013550, doi:10.1017/9781009325844.005. \n\nThis citation includes the coordinating lead authors, lead authors, chapter title, report title, editors, publisher details, page range, and DOI.", + "64581ee3-eca7-4e50-84a0-dfde6f69abda": "The Coordinating Lead Authors of Chapter 3 (\"Oceans and Coastal Ecosystems and Their Services\") in the IPCC AR6 WGII report are **Sarah R. Cooley (USA)** and **David S. Schoeman (Australia)**. \n\nThis information is explicitly stated in the provided context under the \"Coordinating Lead Authors\" section.", + "73298e8c-51a6-4424-8d5c-aa6c1ae5eb81": "Based on the context information provided, the Lead Authors of the chapter \"Oceans and Coastal Ecosystems and Their Services\" represent the following countries: \n\n1. **USA** \u2013 Sarah R. Cooley \n2. **Australia** \u2013 David S. Schoeman \n3. **France** \u2013 Laurent Bopp \n4. **Australia/UK** \u2013 Philip Boyd \n5. **Canada** \u2013 Simon Donner \n6. **Japan** \u2013 Shin-Ichi Ito \n7. **Germany** \u2013 Wolfgang Kiessling \n8. **Argentina** \u2013 Paulina Martinetto \n9. **Spain** \u2013 Elena Ojea \n10. **UK/France** \u2013 Marie-Fanny Racault \n11. **Germany** \u2013 Bj\u00f6rn Rost \n12. **Norway** \u2013 Mette Skern-Mauritzen \n13. **South Africa/Eritrea** \u2013 Dawit Yemane Ghebrehiwet \n\nThus, the countries represented by the Lead Authors are: **USA, Australia, France, UK, Canada, Japan, Germany, Argentina, Spain, Norway, South Africa, and Eritrea**. Some authors have dual affiliations (e.g., Australia/UK, UK/France, South Africa/Eritrea).", + "47a221d0-a95e-49f0-a0f8-13bcb2094c13": "The page range for Chapter 3 (\"Oceans and Coastal Ecosystems and Their Services\") in the IPCC AR6 WGII report is **379\u2013550**, as indicated in the citation provided in the context information. \n\nAnswer: The page range for Chapter 3 is 379\u2013550.", + "64ff4db4-cd98-4741-a35c-e5d3ac8b7cd2": "The DOI for Chapter 3 of the IPCC AR6 WGII report is **10.1017/9781009325844.005**. \n\nThis is explicitly stated in the citation provided in the context information.", + "df2772ec-fbb1-4bde-9fde-87ecbbe242ed": "Here are three Contributing Authors from different countries listed in the chapter:\n\n1. **Johann D. Bell** (Australia) \n2. **William W. L. Cheung** (Canada) \n3. **Elisabeth Holland** (Fiji) \n\nThese authors represent three distinct countries: Australia, Canada, and Fiji.", + "6e4ed553-7dc6-4db0-8c97-f5dfe8540ed3": "The Review Editors for this chapter are **Karim Hilmi** (Morocco) and **Lisa Levin** (USA). They represent Morocco and the United States, respectively. \n\n(Answer derived directly from the provided context information.)", + "30d8e598-4a92-41e8-bafa-f62f503e2417": "The Chapter Scientist credited for this chapter is **Jessica Bolin**, and their affiliation is **Australia**. \n\n(Source: Context information provided, under the \"Chapter Scientist\" section.)", + "dc190ac2-6d6a-496c-a742-4c799cacf9b9": "The IPCC AR6 WGII report is published by two publishers: \n\n1. **Cambridge University Press** (based in Cambridge, UK) \n2. **Cambridge University Press** (based in New York, NY, USA) \n\nThis information is derived from the citation provided in the context: \n*\"Cambridge University Press, Cambridge, UK and New York, NY, USA, pp. 379\u2013550, doi:10.1017/9781009325844.005.\"* \n\n(Note: While the citation lists \"Cambridge University Press\" twice with different locations, it does not specify a separate publisher for the U.S. edition, implying the same publisher operates in both locations.)", + "90275ad3-39f0-44b4-ae1a-da47454f4fe8": "The file size of the PDF document containing Chapter 3 is **21,752,444 bytes**, and the creation date is **2025-07-15**. \n\n(Source: Context metadata provided.)", + "2d2edcb3-3f47-4a73-94ff-459290b231c4": "Here are the answers to different aspects of the provided context: \n\n1. **Citation Format**: \n The chapter should be cited as: \n *Cooley, S., D. Schoeman, L. Bopp, P. Boyd, S. Donner, D.Y. Ghebrehiwet, S.-I. Ito, W. Kiessling, P. Martinetto, E. Ojea, M.-F. Racault, B. Rost, and M. Skern-Mauritzen, 2022: Oceans and Coastal Ecosystems and Their Services. In: Climate Change 2022: Impacts, Adaptation and Vulnerability. Contribution of Working Group II to the Sixth Assessment Report of the Intergovernmental Panel on Climate Change [H.-O. P\u00f6rtner, D.C. Roberts, M. Tignor, E.S. Poloczanska, K. Mintenbeck, A. Alegr\u00eda, M. Craig, S. Langsdorf, S. L\u00f6schke, V. M\u00f6ller, A. Okem, B. Rama (eds.)]. Cambridge University Press, Cambridge, UK and New York, NY, USA, pp. 379\u2013550, doi:10.1017/9781009325844.005.* \n\n2. **Authorship Details**: \n - **Coordinating Lead Authors**: Sarah R. Cooley (USA), David S. Schoeman (Australia) \n - **Lead Authors**: Laurent Bopp (France), Philip Boyd (Australia/UK), Simon Donner (Canada), Shin-Ichi Ito (Japan), Wolfgang Kiessling (Germany), Paulina Martinetto (Argentina), Elena Ojea (Spain), Marie-Fanny Racault (UK/France), Bj\u00f6rn Rost (Germany), Mette Skern-Mauritzen (Norway), Dawit Yemane Ghebrehiwet (South Africa/Eritrea) \n - **Contributing Authors, Review Editors, and Chapter Scientist** are also listed in the context. \n\n3. **Metadata**: \n - **Page Label**: 379 \n - **File Name**: IPCC_AR6_WGII_Chapter03.pdf \n - **File Path**: ..\\..\\data\\C3\\pdf\\IPCC_AR6_WGII_Chapter03.pdf \n - **File Type**: application/pdf \n - **File Size**: 21,752,444 bytes (~21.7 MB) \n - **Creation Date**: 2025-07-15 \n - **Last Modified Date**: 2025-07-15 \n\n4. **Structural Elements**: \n - The chapter is part of **Working Group II (WGII)** of the **Sixth Assessment Report (AR6)** of the IPCC. \n - It covers **Oceans and Coastal Ecosystems and Their Services** (pages 379\u2013550). \n - The **DOI** for the chapter is **10.1017/9781009325844.005**. \n\nLet me know if you need further details!", + "43f7eea1-2b43-4a99-ab50-fba2dd3471db": "Here are 10 diverse quiz/examination questions based strictly on the provided context from Chapter 3 of the IPCC AR6 WGII report: \n\n1. **Multiple Choice**: Which section of Chapter 3 discusses the challenges of attributing changes in marine ecosystems specifically to climate change? \n a) 3.1 Point of Departure \n b) FAQ 3.1 \n c) 3.2.1 Introduction \n d) Box 3.1 \n\n2. **True/False**: According to the table of contents, the chapter includes a FAQ about marine heatwaves and their impacts on marine life and human communities. (True/False) \n\n3. **Short Answer**: Name two types of climate-induced drivers discussed in Section 3.2 (Observed Trends and Projections of Climatic Impact-Drivers in the Global Ocean). \n\n4. **Fill in the Blank**: Section 3.3.4 focuses on __________ and evolutionary adaptation in marine organisms in response to climate drivers. \n\n5. **Matching**: Match the following subsections to their primary focus: \n - 3.2.2 \n - 3.2.3 \n - 3.3.3 \n - 3.4.2 \n Options: \n a) Chemical changes in the ocean \n b) Coastal ecosystems and seas \n c) Physical changes in the ocean \n d) Responses to multiple drivers \n\n6. **Short Answer**: What is the title of Box 3.2, and what organisms does it focus on? \n\n7. **Multiple Choice**: Which FAQ addresses the concept of \"tipping points\" in the ocean? \n a) FAQ 3.1 \n b) FAQ 3.2 \n c) FAQ 3.3 \n d) None of the above \n\n8. **True/False**: Section 3.3.5 discusses ecological responses to single drivers only. (True/False) \n\n9. **Short Answer**: In which section would you find a discussion of acclimation and adaptation mechanisms in marine species? \n\n10. **Essay Prompt (Brief)**: Based on the table of contents, explain how Chapter 3 structures its analysis of climate impacts on oceans and coastal ecosystems (e.g., drivers, biological responses, observed/projected impacts). \n\nThese questions test comprehension of the chapter's structure, key themes, and specific details while adhering strictly to the provided context. Let me know if you'd like adjustments or additional question types!", + "ea03ffc2-674d-413a-9954-e708c4b0527b": "To answer this question, we need to refer to **Section 3.2.2 (Physical Changes)** in the provided context. However, the context does not explicitly list the specific physical changes discussed in that section. Since the detailed content of Section 3.2.2 is not included in the given context, we cannot definitively identify which option is **NOT** listed as a physical change.\n\nIf this were a real exam question, you would need to refer to the actual text of **Section 3.2.2** in the IPCC AR6 WGII Chapter 3 document to determine the correct answer. Without that specific information, we cannot provide an accurate response. \n\nWould you like me to infer possible physical changes based on general climate science knowledge? (Note: This would go beyond the given context.)", + "242acbb0-4f32-4732-8cc0-6344f4e0f17c": "The context information provided does not explicitly mention \"sea level rise\" in the listed sections or headings. However, given that the chapter focuses on \"Oceans and Coastal Ecosystems and Their Services,\" it is likely that sea level rise is discussed in sections such as **3.2.2 Physical Changes** (which may cover ocean warming, ice melt, and associated sea level changes) or **3.4.2 Coastal Ecosystems and Seas** (which may address impacts on coastal areas). \n\nFor a precise answer, you would need to refer to the content of these sections in the actual document (e.g., page 392 for physical changes or page 410 for coastal ecosystems). Would you like me to infer potential connections based on typical IPCC reporting?" + } +} \ No newline at end of file diff --git a/code/C8/config.py b/code/C8/config.py new file mode 100644 index 0000000..a4f3c13 --- /dev/null +++ b/code/C8/config.py @@ -0,0 +1,49 @@ +""" +RAG系统配置文件 +""" + +from dataclasses import dataclass +from typing import Dict, Any + +@dataclass +class RAGConfig: + """RAG系统配置类""" + + # 路径配置 + data_path: str = "../../data/C8/cook" + index_save_path: str = "./vector_index" + + # 模型配置 + embedding_model: str = "BAAI/bge-small-zh-v1.5" + llm_model: str = "kimi-k2-0711-preview" + + # 检索配置 + top_k: int = 3 + + # 生成配置 + temperature: float = 0.1 + max_tokens: int = 2048 + + def __post_init__(self): + """初始化后的处理""" + pass + + @classmethod + def from_dict(cls, config_dict: Dict[str, Any]) -> 'RAGConfig': + """从字典创建配置对象""" + return cls(**config_dict) + + def to_dict(self) -> Dict[str, Any]: + """转换为字典""" + return { + 'data_path': self.data_path, + 'index_save_path': self.index_save_path, + 'embedding_model': self.embedding_model, + 'llm_model': self.llm_model, + 'top_k': self.top_k, + 'temperature': self.temperature, + 'max_tokens': self.max_tokens + } + +# 默认配置实例 +DEFAULT_CONFIG = RAGConfig() diff --git a/code/C8/main.py b/code/C8/main.py new file mode 100644 index 0000000..68d2a87 --- /dev/null +++ b/code/C8/main.py @@ -0,0 +1,369 @@ +""" +RAG系统主程序 +""" + +import os +import sys +import logging +from pathlib import Path +from typing import List + +# 添加模块路径 +sys.path.append(str(Path(__file__).parent)) + +from dotenv import load_dotenv +from config import DEFAULT_CONFIG, RAGConfig +from rag_modules import ( + DataPreparationModule, + IndexConstructionModule, + RetrievalOptimizationModule, + GenerationIntegrationModule +) + +# 加载环境变量 +load_dotenv() + +# 配置日志 +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' +) +logger = logging.getLogger(__name__) + +class RecipeRAGSystem: + """食谱RAG系统主类""" + + def __init__(self, config: RAGConfig = None): + """ + 初始化RAG系统 + + Args: + config: RAG系统配置,默认使用DEFAULT_CONFIG + """ + self.config = config or DEFAULT_CONFIG + self.data_module = None + self.index_module = None + self.retrieval_module = None + self.generation_module = None + + # 检查数据路径 + if not Path(self.config.data_path).exists(): + raise FileNotFoundError(f"数据路径不存在: {self.config.data_path}") + + # 检查API密钥 + if not os.getenv("MOONSHOT_API_KEY"): + raise ValueError("请设置 MOONSHOT_API_KEY 环境变量") + + def initialize_system(self): + """初始化所有模块""" + print("🚀 正在初始化RAG系统...") + + # 1. 初始化数据准备模块 + print("初始化数据准备模块...") + self.data_module = DataPreparationModule(self.config.data_path) + + # 2. 初始化索引构建模块 + print("初始化索引构建模块...") + self.index_module = IndexConstructionModule( + model_name=self.config.embedding_model, + index_save_path=self.config.index_save_path + ) + + # 3. 初始化生成集成模块 + print("🤖 初始化生成集成模块...") + self.generation_module = GenerationIntegrationModule( + model_name=self.config.llm_model, + temperature=self.config.temperature, + max_tokens=self.config.max_tokens + ) + + print("✅ 系统初始化完成!") + + def build_knowledge_base(self): + """构建知识库""" + print("\n正在构建知识库...") + + # 1. 尝试加载已保存的索引 + vectorstore = self.index_module.load_index() + + if vectorstore is not None: + print("✅ 成功加载已保存的向量索引!") + # 仍需要加载文档和分块用于检索模块 + print("加载食谱文档...") + self.data_module.load_documents() + print("进行文本分块...") + chunks = self.data_module.chunk_documents() + else: + print("未找到已保存的索引,开始构建新索引...") + + # 2. 加载文档 + print("加载食谱文档...") + self.data_module.load_documents() + + # 3. 文本分块 + print("进行文本分块...") + chunks = self.data_module.chunk_documents() + + # 4. 构建向量索引 + print("构建向量索引...") + vectorstore = self.index_module.build_vector_index(chunks) + + # 5. 保存索引 + print("保存向量索引...") + self.index_module.save_index() + + # 6. 初始化检索优化模块 + print("初始化检索优化...") + self.retrieval_module = RetrievalOptimizationModule(vectorstore, chunks) + + # 7. 显示统计信息 + stats = self.data_module.get_statistics() + print(f"\n📊 知识库统计:") + print(f" 文档总数: {stats['total_documents']}") + print(f" 文本块数: {stats['total_chunks']}") + print(f" 菜品分类: {list(stats['categories'].keys())}") + print(f" 难度分布: {stats['difficulties']}") + + print("✅ 知识库构建完成!") + + def ask_question(self, question: str, stream: bool = False): + """ + 回答用户问题 + + Args: + question: 用户问题 + stream: 是否使用流式输出 + + Returns: + 生成的回答或生成器 + """ + if not all([self.retrieval_module, self.generation_module]): + raise ValueError("请先构建知识库") + + print(f"\n❓ 用户问题: {question}") + + # 1. 查询路由 + route_type = self.generation_module.query_router(question) + print(f"🎯 查询类型: {route_type}") + + # 2. 智能查询重写(根据路由类型) + if route_type == 'list': + # 列表查询保持原查询 + rewritten_query = question + print(f"📝 列表查询保持原样: {question}") + else: + # 详细查询和一般查询使用智能重写 + print("🤖 智能分析查询...") + rewritten_query = self.generation_module.query_rewrite(question) + + # 3. 检索相关子块(自动应用元数据过滤) + print("🔍 检索相关文档...") + filters = self._extract_filters_from_query(question) + if filters: + print(f"应用过滤条件: {filters}") + relevant_chunks = self.retrieval_module.metadata_filtered_search(rewritten_query, filters, top_k=self.config.top_k) + else: + relevant_chunks = self.retrieval_module.hybrid_search(rewritten_query, top_k=self.config.top_k) + + # 显示检索到的子块信息 + if relevant_chunks: + chunk_info = [] + for chunk in relevant_chunks: + dish_name = chunk.metadata.get('dish_name', '未知菜品') + # 尝试从内容中提取章节标题 + content_preview = chunk.page_content[:100].strip() + if content_preview.startswith('#'): + # 如果是标题开头,提取标题(仅取第一行) + title_end = content_preview.find('\n') if '\n' in content_preview else len(content_preview) + section_title = content_preview[:title_end].replace('#', '').strip() + chunk_info.append(f"{dish_name}({section_title})") + else: + chunk_info.append(f"{dish_name}(内容片段)") + + print(f"找到 {len(relevant_chunks)} 个相关文档块: {', '.join(chunk_info)}") + else: + print(f"找到 {len(relevant_chunks)} 个相关文档块") + + # 4. 检查是否找到相关内容 + if not relevant_chunks: + return "抱歉,没有找到相关的食谱信息。请尝试其他菜品名称或关键词。" + + # 5. 根据路由类型选择回答方式 + if route_type == 'list': + # 列表查询:直接返回菜品名称列表 + print("📋 生成菜品列表...") + relevant_docs = self.data_module.get_parent_documents(relevant_chunks) + + # 显示找到的文档名称 + doc_names = [] + for doc in relevant_docs: + dish_name = doc.metadata.get('dish_name', '未知菜品') + doc_names.append(dish_name) + + if doc_names: + print(f"找到文档: {', '.join(doc_names)}") + + return self.generation_module.generate_list_answer(question, relevant_docs) + else: + # 详细查询:获取完整文档并生成详细回答 + print("获取完整文档...") + relevant_docs = self.data_module.get_parent_documents(relevant_chunks) + + # 显示找到的文档名称 + doc_names = [] + for doc in relevant_docs: + dish_name = doc.metadata.get('dish_name', '未知菜品') + doc_names.append(dish_name) + + if doc_names: + print(f"找到文档: {', '.join(doc_names)}") + else: + print(f"对应 {len(relevant_docs)} 个完整文档") + + print("✍️ 生成详细回答...") + + # 根据路由类型自动选择回答模式 + if route_type == "detail": + # 详细查询使用分步指导模式 + if stream: + return self.generation_module.generate_step_by_step_answer_stream(question, relevant_docs) + else: + return self.generation_module.generate_step_by_step_answer(question, relevant_docs) + else: + # 一般查询使用基础回答模式 + if stream: + return self.generation_module.generate_basic_answer_stream(question, relevant_docs) + else: + return self.generation_module.generate_basic_answer(question, relevant_docs) + + def _extract_filters_from_query(self, query: str) -> dict: + """ + 从用户问题中提取元数据过滤条件 + """ + filters = {} + # 分类关键词 + category_keywords = DataPreparationModule.get_supported_categories() + for cat in category_keywords: + if cat in query: + filters['category'] = cat + break + + # 难度关键词 + difficulty_keywords = DataPreparationModule.get_supported_difficulties() + for diff in sorted(difficulty_keywords, key=len, reverse=True): + if diff in query: + filters['difficulty'] = diff + break + + return filters + + def search_by_category(self, category: str, query: str = "") -> List[str]: + """ + 按分类搜索菜品 + + Args: + category: 菜品分类 + query: 可选的额外查询条件 + + Returns: + 菜品名称列表 + """ + if not self.retrieval_module: + raise ValueError("请先构建知识库") + + # 使用元数据过滤搜索 + search_query = query if query else category + filters = {"category": category} + + docs = self.retrieval_module.metadata_filtered_search(search_query, filters, top_k=10) + + # 提取菜品名称 + dish_names = [] + for doc in docs: + dish_name = doc.metadata.get('dish_name', '未知菜品') + if dish_name not in dish_names: + dish_names.append(dish_name) + + return dish_names + + def get_ingredients_list(self, dish_name: str) -> str: + """ + 获取指定菜品的食材信息 + + Args: + dish_name: 菜品名称 + + Returns: + 食材信息 + """ + if not all([self.retrieval_module, self.generation_module]): + raise ValueError("请先构建知识库") + + # 搜索相关文档 + docs = self.retrieval_module.hybrid_search(dish_name, top_k=3) + + # 生成食材信息 + answer = self.generation_module.generate_basic_answer(f"{dish_name}需要什么食材?", docs) + + return answer + + def run_interactive(self): + """运行交互式问答""" + print("=" * 60) + print("🍽️ 尝尝咸淡RAG系统 - 交互式问答 🍽️") + print("=" * 60) + print("💡 解决您的选择困难症,告别'今天吃什么'的世纪难题!") + + # 初始化系统 + self.initialize_system() + + # 构建知识库 + self.build_knowledge_base() + + print("\n交互式问答 (输入'退出'结束):") + + while True: + try: + user_input = input("\n您的问题: ").strip() + if user_input.lower() in ['退出', 'quit', 'exit', '']: + break + + # 询问是否使用流式输出 + stream_choice = input("是否使用流式输出? (y/n, 默认y): ").strip().lower() + use_stream = stream_choice != 'n' + + print("\n回答:") + if use_stream: + # 流式输出 + for chunk in self.ask_question(user_input, stream=True): + print(chunk, end="", flush=True) + print("\n") + else: + # 普通输出 + answer = self.ask_question(user_input, stream=False) + print(f"{answer}\n") + + except KeyboardInterrupt: + break + except Exception as e: + print(f"处理问题时出错: {e}") + + print("\n感谢使用尝尝咸淡RAG系统!") + + + +def main(): + """主函数""" + try: + # 创建RAG系统 + rag_system = RecipeRAGSystem() + + # 运行交互式问答 + rag_system.run_interactive() + + except Exception as e: + logger.error(f"系统运行出错: {e}") + print(f"系统错误: {e}") + +if __name__ == "__main__": + main() diff --git a/code/C8/rag_modules/__init__.py b/code/C8/rag_modules/__init__.py new file mode 100644 index 0000000..38f9795 --- /dev/null +++ b/code/C8/rag_modules/__init__.py @@ -0,0 +1,13 @@ +from .data_preparation import DataPreparationModule +from .index_construction import IndexConstructionModule +from .retrieval_optimization import RetrievalOptimizationModule +from .generation_integration import GenerationIntegrationModule + +__all__ = [ + 'DataPreparationModule', + 'IndexConstructionModule', + 'RetrievalOptimizationModule', + 'GenerationIntegrationModule' +] + +__version__ = "1.0.0" diff --git a/code/C8/rag_modules/data_preparation.py b/code/C8/rag_modules/data_preparation.py new file mode 100644 index 0000000..37645e8 --- /dev/null +++ b/code/C8/rag_modules/data_preparation.py @@ -0,0 +1,363 @@ +""" +数据准备模块 +""" + +import logging +import hashlib +from pathlib import Path +from typing import List, Dict, Any + +from langchain_text_splitters import MarkdownHeaderTextSplitter +from langchain_core.documents import Document +from pathlib import Path +import uuid + +logger = logging.getLogger(__name__) + +class DataPreparationModule: + """数据准备模块 - 负责数据加载、清洗和预处理""" + # 统一维护的分类与难度配置,供外部复用,避免关键词重复定义 + CATEGORY_MAPPING = { + 'meat_dish': '荤菜', + 'vegetable_dish': '素菜', + 'soup': '汤品', + 'dessert': '甜品', + 'breakfast': '早餐', + 'staple': '主食', + 'aquatic': '水产', + 'condiment': '调料', + 'drink': '饮品' + } + CATEGORY_LABELS = list(set(CATEGORY_MAPPING.values())) + DIFFICULTY_LABELS = ['非常简单', '简单', '中等', '困难', '非常困难'] + + def __init__(self, data_path: str): + """ + 初始化数据准备模块 + + Args: + data_path: 数据文件夹路径 + """ + self.data_path = data_path + self.documents: List[Document] = [] # 父文档(完整食谱) + self.chunks: List[Document] = [] # 子文档(按标题分割的小块) + self.parent_child_map: Dict[str, str] = {} # 子块ID -> 父文档ID的映射 + + def load_documents(self) -> List[Document]: + """ + 加载文档数据 + + Returns: + 加载的文档列表 + """ + logger.info(f"正在从 {self.data_path} 加载文档...") + + # 直接读取Markdown文件以保持原始格式 + documents = [] + data_path_obj = Path(self.data_path) + + for md_file in data_path_obj.rglob("*.md"): + try: + # 直接读取文件内容,保持Markdown格式 + with open(md_file, 'r', encoding='utf-8') as f: + content = f.read() + + # 为每个父文档分配确定性的唯一ID(基于数据根目录的相对路径) + try: + data_root = Path(self.data_path).resolve() + relative_path = Path(md_file).resolve().relative_to(data_root).as_posix() + except Exception: + relative_path = Path(md_file).as_posix() + parent_id = hashlib.md5(relative_path.encode("utf-8")).hexdigest() + + # 创建Document对象 + doc = Document( + page_content=content, + metadata={ + "source": str(md_file), + "parent_id": parent_id, + "doc_type": "parent" # 标记为父文档 + } + ) + documents.append(doc) + + except Exception as e: + logger.warning(f"读取文件 {md_file} 失败: {e}") + + # 增强文档元数据 + for doc in documents: + self._enhance_metadata(doc) + + self.documents = documents + logger.info(f"成功加载 {len(documents)} 个文档") + return documents + + def _enhance_metadata(self, doc: Document): + """ + 增强文档元数据 + + Args: + doc: 需要增强元数据的文档 + """ + file_path = Path(doc.metadata.get('source', '')) + path_parts = file_path.parts + + # 提取菜品分类 + doc.metadata['category'] = '其他' + for key, value in self.CATEGORY_MAPPING.items(): + if key in path_parts: + doc.metadata['category'] = value + break + + # 提取菜品名称 + doc.metadata['dish_name'] = file_path.stem + + # 分析难度等级 + content = doc.page_content + if '★★★★★' in content: + doc.metadata['difficulty'] = '非常困难' + elif '★★★★' in content: + doc.metadata['difficulty'] = '困难' + elif '★★★' in content: + doc.metadata['difficulty'] = '中等' + elif '★★' in content: + doc.metadata['difficulty'] = '简单' + elif '★' in content: + doc.metadata['difficulty'] = '非常简单' + else: + doc.metadata['difficulty'] = '未知' + + @classmethod + def get_supported_categories(cls) -> List[str]: + """对外提供支持的分类标签列表""" + return cls.CATEGORY_LABELS + + @classmethod + def get_supported_difficulties(cls) -> List[str]: + """对外提供支持的难度标签列表""" + return cls.DIFFICULTY_LABELS + + def chunk_documents(self) -> List[Document]: + """ + Markdown结构感知分块 + + Returns: + 分块后的文档列表 + """ + logger.info("正在进行Markdown结构感知分块...") + + if not self.documents: + raise ValueError("请先加载文档") + + # 使用Markdown标题分割器 + chunks = self._markdown_header_split() + + # 为每个chunk添加基础元数据 + for i, chunk in enumerate(chunks): + if 'chunk_id' not in chunk.metadata: + # 如果没有chunk_id(比如分割失败的情况),则生成一个 + chunk.metadata['chunk_id'] = str(uuid.uuid4()) + chunk.metadata['batch_index'] = i # 在当前批次中的索引 + chunk.metadata['chunk_size'] = len(chunk.page_content) + + self.chunks = chunks + logger.info(f"Markdown分块完成,共生成 {len(chunks)} 个chunk") + return chunks + + def _markdown_header_split(self) -> List[Document]: + """ + 使用Markdown标题分割器进行结构化分割 + + Returns: + 按标题结构分割的文档列表 + """ + # 定义要分割的标题层级 + headers_to_split_on = [ + ("#", "主标题"), # 菜品名称 + ("##", "二级标题"), # 必备原料、计算、操作等 + ("###", "三级标题") # 简易版本、复杂版本等 + ] + + # 创建Markdown分割器 + markdown_splitter = MarkdownHeaderTextSplitter( + headers_to_split_on=headers_to_split_on, + strip_headers=False # 保留标题,便于理解上下文 + ) + + all_chunks = [] + + for doc in self.documents: + try: + # 检查文档内容是否包含Markdown标题 + content_preview = doc.page_content[:200] + has_headers = any(line.strip().startswith('#') for line in content_preview.split('\n')) + + if not has_headers: + logger.warning(f"文档 {doc.metadata.get('dish_name', '未知')} 内容中没有发现Markdown标题") + logger.debug(f"内容预览: {content_preview}") + + # 对每个文档进行Markdown分割 + md_chunks = markdown_splitter.split_text(doc.page_content) + + logger.debug(f"文档 {doc.metadata.get('dish_name', '未知')} 分割成 {len(md_chunks)} 个chunk") + + # 如果没有分割成功,说明文档可能没有标题结构 + if len(md_chunks) <= 1: + logger.warning(f"文档 {doc.metadata.get('dish_name', '未知')} 未能按标题分割,可能缺少标题结构") + + # 为每个子块建立与父文档的关系 + parent_id = doc.metadata["parent_id"] + + for i, chunk in enumerate(md_chunks): + # 为子块分配唯一ID + child_id = str(uuid.uuid4()) + + # 合并原文档元数据和新的标题元数据 + chunk.metadata.update(doc.metadata) + chunk.metadata.update({ + "chunk_id": child_id, + "parent_id": parent_id, + "doc_type": "child", # 标记为子文档 + "chunk_index": i # 在父文档中的位置 + }) + + # 建立父子映射关系 + self.parent_child_map[child_id] = parent_id + + all_chunks.extend(md_chunks) + + except Exception as e: + logger.warning(f"文档 {doc.metadata.get('source', '未知')} Markdown分割失败: {e}") + # 如果Markdown分割失败,将整个文档作为一个chunk + all_chunks.append(doc) + + logger.info(f"Markdown结构分割完成,生成 {len(all_chunks)} 个结构化块") + return all_chunks + + def filter_documents_by_category(self, category: str) -> List[Document]: + """ + 按分类过滤文档 + + Args: + category: 菜品分类 + + Returns: + 过滤后的文档列表 + """ + return [doc for doc in self.documents if doc.metadata.get('category') == category] + + def filter_documents_by_difficulty(self, difficulty: str) -> List[Document]: + """ + 按难度过滤文档 + + Args: + difficulty: 难度等级 + + Returns: + 过滤后的文档列表 + """ + return [doc for doc in self.documents if doc.metadata.get('difficulty') == difficulty] + + def get_statistics(self) -> Dict[str, Any]: + """ + 获取数据统计信息 + + Returns: + 统计信息字典 + """ + if not self.documents: + return {} + + categories = {} + difficulties = {} + + for doc in self.documents: + # 统计分类 + category = doc.metadata.get('category', '未知') + categories[category] = categories.get(category, 0) + 1 + + # 统计难度 + difficulty = doc.metadata.get('difficulty', '未知') + difficulties[difficulty] = difficulties.get(difficulty, 0) + 1 + + return { + 'total_documents': len(self.documents), + 'total_chunks': len(self.chunks), + 'categories': categories, + 'difficulties': difficulties, + 'avg_chunk_size': sum(chunk.metadata.get('chunk_size', 0) for chunk in self.chunks) / len(self.chunks) if self.chunks else 0 + } + + def export_metadata(self, output_path: str): + """ + 导出元数据到JSON文件 + + Args: + output_path: 输出文件路径 + """ + import json + + metadata_list = [] + for doc in self.documents: + metadata_list.append({ + 'source': doc.metadata.get('source'), + 'dish_name': doc.metadata.get('dish_name'), + 'category': doc.metadata.get('category'), + 'difficulty': doc.metadata.get('difficulty'), + 'content_length': len(doc.page_content) + }) + + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(metadata_list, f, ensure_ascii=False, indent=2) + + logger.info(f"元数据已导出到: {output_path}") + + def get_parent_documents(self, child_chunks: List[Document]) -> List[Document]: + """ + 根据子块获取对应的父文档(智能去重) + + Args: + child_chunks: 检索到的子块列表 + + Returns: + 对应的父文档列表(去重,按相关性排序) + """ + # 统计每个父文档被匹配的次数(相关性指标) + parent_relevance = {} + parent_docs_map = {} + + # 收集所有相关的父文档ID和相关性分数 + for chunk in child_chunks: + parent_id = chunk.metadata.get("parent_id") + if parent_id: + # 增加相关性计数 + parent_relevance[parent_id] = parent_relevance.get(parent_id, 0) + 1 + + # 缓存父文档(避免重复查找) + if parent_id not in parent_docs_map: + for doc in self.documents: + if doc.metadata.get("parent_id") == parent_id: + parent_docs_map[parent_id] = doc + break + + # 按相关性排序(匹配次数多的排在前面) + sorted_parent_ids = sorted(parent_relevance.keys(), + key=lambda x: parent_relevance[x], + reverse=True) + + # 构建去重后的父文档列表 + parent_docs = [] + for parent_id in sorted_parent_ids: + if parent_id in parent_docs_map: + parent_docs.append(parent_docs_map[parent_id]) + + # 收集父文档名称和相关性信息用于日志 + parent_info = [] + for doc in parent_docs: + dish_name = doc.metadata.get('dish_name', '未知菜品') + parent_id = doc.metadata.get('parent_id') + relevance_count = parent_relevance.get(parent_id, 0) + parent_info.append(f"{dish_name}({relevance_count}块)") + + logger.info(f"从 {len(child_chunks)} 个子块中找到 {len(parent_docs)} 个去重父文档: {', '.join(parent_info)}") + return parent_docs diff --git a/code/C8/rag_modules/generation_integration.py b/code/C8/rag_modules/generation_integration.py new file mode 100644 index 0000000..46feb5f --- /dev/null +++ b/code/C8/rag_modules/generation_integration.py @@ -0,0 +1,401 @@ +""" +生成集成模块 +""" + +import os +import logging +from typing import List + +from langchain_core.prompts import ChatPromptTemplate, PromptTemplate +from langchain_community.chat_models.moonshot import MoonshotChat +from langchain_core.documents import Document +from langchain_core.runnables import RunnablePassthrough +from langchain_core.output_parsers import StrOutputParser + +logger = logging.getLogger(__name__) + +class GenerationIntegrationModule: + """生成集成模块 - 负责LLM集成和回答生成""" + + def __init__(self, model_name: str = "kimi-k2-0711-preview", temperature: float = 0.1, max_tokens: int = 2048): + """ + 初始化生成集成模块 + + Args: + model_name: 模型名称 + temperature: 生成温度 + max_tokens: 最大token数 + """ + self.model_name = model_name + self.temperature = temperature + self.max_tokens = max_tokens + self.llm = None + self.setup_llm() + + def setup_llm(self): + """初始化大语言模型""" + logger.info(f"正在初始化LLM: {self.model_name}") + + api_key = os.getenv("MOONSHOT_API_KEY") + if not api_key: + raise ValueError("请设置 MOONSHOT_API_KEY 环境变量") + + self.llm = MoonshotChat( + model=self.model_name, + temperature=self.temperature, + max_tokens=self.max_tokens, + moonshot_api_key=api_key + ) + + logger.info("LLM初始化完成") + + def generate_basic_answer(self, query: str, context_docs: List[Document]) -> str: + """ + 生成基础回答 + + Args: + query: 用户查询 + context_docs: 上下文文档列表 + + Returns: + 生成的回答 + """ + context = self._build_context(context_docs) + + prompt = ChatPromptTemplate.from_template(""" +你是一位专业的烹饪助手。请根据以下食谱信息回答用户的问题。 + +用户问题: {question} + +相关食谱信息: +{context} + +请提供详细、实用的回答。如果信息不足,请诚实说明。 + +回答:""") + + # 使用LCEL构建链 + chain = ( + {"question": RunnablePassthrough(), "context": lambda _: context} + | prompt + | self.llm + | StrOutputParser() + ) + + response = chain.invoke(query) + return response + + def generate_step_by_step_answer(self, query: str, context_docs: List[Document]) -> str: + """ + 生成分步骤回答 + + Args: + query: 用户查询 + context_docs: 上下文文档列表 + + Returns: + 分步骤的详细回答 + """ + context = self._build_context(context_docs) + + prompt = ChatPromptTemplate.from_template(""" +你是一位专业的烹饪导师。请根据食谱信息,为用户提供详细的分步骤指导。 + +用户问题: {question} + +相关食谱信息: +{context} + +请灵活组织回答,建议包含以下部分(可根据实际内容调整): + +## 🥘 菜品介绍 +[简要介绍菜品特点和难度] + +## 🛒 所需食材 +[列出主要食材和用量] + +## 👨‍🍳 制作步骤 +[详细的分步骤说明,每步包含具体操作和大概所需时间] + +## 💡 制作技巧 +[仅在有实用技巧时包含。优先使用原文中的实用技巧,如果原文的"附加内容"与烹饪无关或为空,可以基于制作步骤总结关键要点,或者完全省略此部分] + +注意: +- 根据实际内容灵活调整结构 +- 不要强行填充无关内容或重复制作步骤中的信息 +- 重点突出实用性和可操作性 +- 如果没有额外的技巧要分享,可以省略制作技巧部分 + +回答:""") + + chain = ( + {"question": RunnablePassthrough(), "context": lambda _: context} + | prompt + | self.llm + | StrOutputParser() + ) + + response = chain.invoke(query) + return response + + def query_rewrite(self, query: str) -> str: + """ + 智能查询重写 - 让大模型判断是否需要重写查询 + + Args: + query: 原始查询 + + Returns: + 重写后的查询或原查询 + """ + prompt = PromptTemplate( + template=""" +你是一个智能查询分析助手。请分析用户的查询,判断是否需要重写以提高食谱搜索效果。 + +原始查询: {query} + +分析规则: +1. **具体明确的查询**(直接返回原查询): + - 包含具体菜品名称:如"宫保鸡丁怎么做"、"红烧肉的制作方法" + - 明确的制作询问:如"蛋炒饭需要什么食材"、"糖醋排骨的步骤" + - 具体的烹饪技巧:如"如何炒菜不粘锅"、"怎样调制糖醋汁" + +2. **模糊不清的查询**(需要重写): + - 过于宽泛:如"做菜"、"有什么好吃的"、"推荐个菜" + - 缺乏具体信息:如"川菜"、"素菜"、"简单的" + - 口语化表达:如"想吃点什么"、"有饮品推荐吗" + +重写原则: +- 保持原意不变 +- 增加相关烹饪术语 +- 优先推荐简单易做的 +- 保持简洁性 + +示例: +- "做菜" → "简单易做的家常菜谱" +- "有饮品推荐吗" → "简单饮品制作方法" +- "推荐个菜" → "简单家常菜推荐" +- "川菜" → "经典川菜菜谱" +- "宫保鸡丁怎么做" → "宫保鸡丁怎么做"(保持原查询) +- "红烧肉需要什么食材" → "红烧肉需要什么食材"(保持原查询) + +请输出最终查询(如果不需要重写就返回原查询):""", + input_variables=["query"] + ) + + chain = ( + {"query": RunnablePassthrough()} + | prompt + | self.llm + | StrOutputParser() + ) + + response = chain.invoke(query).strip() + + # 记录重写结果 + if response != query: + logger.info(f"查询已重写: '{query}' → '{response}'") + else: + logger.info(f"查询无需重写: '{query}'") + + return response + + + + def query_router(self, query: str) -> str: + """ + 查询路由 - 根据查询类型选择不同的处理方式 + + Args: + query: 用户查询 + + Returns: + 路由类型 ('list', 'detail', 'general') + """ + prompt = ChatPromptTemplate.from_template(""" +根据用户的问题,将其分类为以下三种类型之一: + +1. 'list' - 用户想要获取菜品列表或推荐,只需要菜名 + 例如:推荐几个素菜、有什么川菜、给我3个简单的菜 + +2. 'detail' - 用户想要具体的制作方法或详细信息 + 例如:宫保鸡丁怎么做、制作步骤、需要什么食材 + +3. 'general' - 其他一般性问题 + 例如:什么是川菜、制作技巧、营养价值 + +请只返回分类结果:list、detail 或 general + +用户问题: {query} + +分类结果:""") + + chain = ( + {"query": RunnablePassthrough()} + | prompt + | self.llm + | StrOutputParser() + ) + + result = chain.invoke(query).strip().lower() + + # 确保返回有效的路由类型 + if result in ['list', 'detail', 'general']: + return result + else: + return 'general' # 默认类型 + + def generate_list_answer(self, query: str, context_docs: List[Document]) -> str: + """ + 生成列表式回答 - 适用于推荐类查询 + + Args: + query: 用户查询 + context_docs: 上下文文档列表 + + Returns: + 列表式回答 + """ + if not context_docs: + return "抱歉,没有找到相关的菜品信息。" + + # 提取菜品名称 + dish_names = [] + for doc in context_docs: + dish_name = doc.metadata.get('dish_name', '未知菜品') + if dish_name not in dish_names: + dish_names.append(dish_name) + + # 构建简洁的列表回答 + if len(dish_names) == 1: + return f"为您推荐:{dish_names[0]}" + elif len(dish_names) <= 3: + return f"为您推荐以下菜品:\n" + "\n".join([f"{i+1}. {name}" for i, name in enumerate(dish_names)]) + else: + return f"为您推荐以下菜品:\n" + "\n".join([f"{i+1}. {name}" for i, name in enumerate(dish_names[:3])]) + f"\n\n还有其他 {len(dish_names)-3} 道菜品可供选择。" + + def generate_basic_answer_stream(self, query: str, context_docs: List[Document]): + """ + 生成基础回答 - 流式输出 + + Args: + query: 用户查询 + context_docs: 上下文文档列表 + + Yields: + 生成的回答片段 + """ + context = self._build_context(context_docs) + + prompt = ChatPromptTemplate.from_template(""" +你是一位专业的烹饪助手。请根据以下食谱信息回答用户的问题。 + +用户问题: {question} + +相关食谱信息: +{context} + +请提供详细、实用的回答。如果信息不足,请诚实说明。 + +回答:""") + + chain = ( + {"question": RunnablePassthrough(), "context": lambda _: context} + | prompt + | self.llm + | StrOutputParser() + ) + + for chunk in chain.stream(query): + yield chunk + + def generate_step_by_step_answer_stream(self, query: str, context_docs: List[Document]): + """ + 生成详细步骤回答 - 流式输出 + + Args: + query: 用户查询 + context_docs: 上下文文档列表 + + Yields: + 详细步骤回答片段 + """ + context = self._build_context(context_docs) + + prompt = ChatPromptTemplate.from_template(""" +你是一位专业的烹饪导师。请根据食谱信息,为用户提供详细的分步骤指导。 + +用户问题: {question} + +相关食谱信息: +{context} + +请灵活组织回答,建议包含以下部分(可根据实际内容调整): + +## 🥘 菜品介绍 +[简要介绍菜品特点和难度] + +## 🛒 所需食材 +[列出主要食材和用量] + +## 👨‍🍳 制作步骤 +[详细的分步骤说明,每步包含具体操作和大概所需时间] + +## 💡 制作技巧 +[仅在有实用技巧时包含。如果原文的"附加内容"与烹饪无关或为空,可以基于制作步骤总结关键要点,或者完全省略此部分] + +注意: +- 根据实际内容灵活调整结构 +- 不要强行填充无关内容 +- 重点突出实用性和可操作性 + +回答:""") + + chain = ( + {"question": RunnablePassthrough(), "context": lambda _: context} + | prompt + | self.llm + | StrOutputParser() + ) + + for chunk in chain.stream(query): + yield chunk + + def _build_context(self, docs: List[Document], max_length: int = 2000) -> str: + """ + 构建上下文字符串 + + Args: + docs: 文档列表 + max_length: 最大长度 + + Returns: + 格式化的上下文字符串 + """ + if not docs: + return "暂无相关食谱信息。" + + context_parts = [] + current_length = 0 + + for i, doc in enumerate(docs, 1): + # 添加元数据信息 + metadata_info = f"【食谱 {i}】" + if 'dish_name' in doc.metadata: + metadata_info += f" {doc.metadata['dish_name']}" + if 'category' in doc.metadata: + metadata_info += f" | 分类: {doc.metadata['category']}" + if 'difficulty' in doc.metadata: + metadata_info += f" | 难度: {doc.metadata['difficulty']}" + + # 构建文档文本 + doc_text = f"{metadata_info}\n{doc.page_content}\n" + + # 检查长度限制 + if current_length + len(doc_text) > max_length: + break + + context_parts.append(doc_text) + current_length += len(doc_text) + + return "\n" + "="*50 + "\n".join(context_parts) diff --git a/code/C8/rag_modules/index_construction.py b/code/C8/rag_modules/index_construction.py new file mode 100644 index 0000000..9eaac97 --- /dev/null +++ b/code/C8/rag_modules/index_construction.py @@ -0,0 +1,135 @@ +""" +索引构建模块 +""" + +import logging +from typing import List +from pathlib import Path + +from langchain_huggingface import HuggingFaceEmbeddings +from langchain_community.vectorstores import FAISS +from langchain_core.documents import Document + +logger = logging.getLogger(__name__) + +class IndexConstructionModule: + """索引构建模块 - 负责向量化和索引构建""" + + def __init__(self, model_name: str = "BAAI/bge-small-zh-v1.5", index_save_path: str = "./vector_index"): + """ + 初始化索引构建模块 + + Args: + model_name: 嵌入模型名称 + index_save_path: 索引保存路径 + """ + self.model_name = model_name + self.index_save_path = index_save_path + self.embeddings = None + self.vectorstore = None + self.setup_embeddings() + + def setup_embeddings(self): + """初始化嵌入模型""" + logger.info(f"正在初始化嵌入模型: {self.model_name}") + + self.embeddings = HuggingFaceEmbeddings( + model_name=self.model_name, + model_kwargs={'device': 'cpu'}, + encode_kwargs={'normalize_embeddings': True} + ) + + logger.info("嵌入模型初始化完成") + + def build_vector_index(self, chunks: List[Document]) -> FAISS: + """ + 构建向量索引 + + Args: + chunks: 文档块列表 + + Returns: + FAISS向量存储对象 + """ + logger.info("正在构建FAISS向量索引...") + + if not chunks: + raise ValueError("文档块列表不能为空") + + # 构建FAISS向量存储 + self.vectorstore = FAISS.from_documents( + documents=chunks, + embedding=self.embeddings + ) + + logger.info(f"向量索引构建完成,包含 {len(chunks)} 个向量") + return self.vectorstore + + def add_documents(self, new_chunks: List[Document]): + """ + 向现有索引添加新文档 + + Args: + new_chunks: 新的文档块列表 + """ + if not self.vectorstore: + raise ValueError("请先构建向量索引") + + logger.info(f"正在添加 {len(new_chunks)} 个新文档到索引...") + self.vectorstore.add_documents(new_chunks) + logger.info("新文档添加完成") + + def save_index(self): + """ + 保存向量索引到配置的路径 + """ + if not self.vectorstore: + raise ValueError("请先构建向量索引") + + # 确保保存目录存在 + Path(self.index_save_path).mkdir(parents=True, exist_ok=True) + + self.vectorstore.save_local(self.index_save_path) + logger.info(f"向量索引已保存到: {self.index_save_path}") + + def load_index(self): + """ + 从配置的路径加载向量索引 + + Returns: + 加载的向量存储对象,如果加载失败返回None + """ + if not self.embeddings: + self.setup_embeddings() + + if not Path(self.index_save_path).exists(): + logger.info(f"索引路径不存在: {self.index_save_path},将构建新索引") + return None + + try: + self.vectorstore = FAISS.load_local( + self.index_save_path, + self.embeddings, + allow_dangerous_deserialization=True + ) + logger.info(f"向量索引已从 {self.index_save_path} 加载") + return self.vectorstore + except Exception as e: + logger.warning(f"加载向量索引失败: {e},将构建新索引") + return None + + def similarity_search(self, query: str, k: int = 5) -> List[Document]: + """ + 相似度搜索 + + Args: + query: 查询文本 + k: 返回结果数量 + + Returns: + 相似文档列表 + """ + if not self.vectorstore: + raise ValueError("请先构建或加载向量索引") + + return self.vectorstore.similarity_search(query, k=k) diff --git a/code/C8/rag_modules/retrieval_optimization.py b/code/C8/rag_modules/retrieval_optimization.py new file mode 100644 index 0000000..fee2253 --- /dev/null +++ b/code/C8/rag_modules/retrieval_optimization.py @@ -0,0 +1,162 @@ +""" +检索优化模块 +""" + +import logging +from typing import List, Dict, Any + +from langchain_community.vectorstores import FAISS +from langchain_community.retrievers import BM25Retriever +from langchain_core.documents import Document + +logger = logging.getLogger(__name__) + +class RetrievalOptimizationModule: + """检索优化模块 - 负责混合检索和过滤""" + + def __init__(self, vectorstore: FAISS, chunks: List[Document]): + """ + 初始化检索优化模块 + + Args: + vectorstore: FAISS向量存储 + chunks: 文档块列表 + """ + self.vectorstore = vectorstore + self.chunks = chunks + self.setup_retrievers() + + def setup_retrievers(self): + """设置向量检索器和BM25检索器""" + logger.info("正在设置检索器...") + + # 向量检索器 + self.vector_retriever = self.vectorstore.as_retriever( + search_type="similarity", + search_kwargs={"k": 5} + ) + + # BM25检索器 + self.bm25_retriever = BM25Retriever.from_documents( + self.chunks, + k=5 + ) + + + + logger.info("检索器设置完成") + + def hybrid_search(self, query: str, top_k: int = 3) -> List[Document]: + """ + 混合检索 - 结合向量检索和BM25检索,使用RRF重排 + + Args: + query: 查询文本 + top_k: 返回结果数量 + + Returns: + 检索到的文档列表 + """ + # 分别获取向量检索和BM25检索结果 + vector_docs = self.vector_retriever.invoke(query) + bm25_docs = self.bm25_retriever.invoke(query) + + # 使用RRF重排 + reranked_docs = self._rrf_rerank(vector_docs, bm25_docs) + return reranked_docs[:top_k] + + def metadata_filtered_search(self, query: str, filters: Dict[str, Any], top_k: int = 5) -> List[Document]: + """ + 带元数据过滤的检索 + + Args: + query: 查询文本 + filters: 元数据过滤条件 + top_k: 返回结果数量 + + Returns: + 过滤后的文档列表 + """ + # 先进行混合检索,获取更多候选 + docs = self.hybrid_search(query, top_k * 3) + + # 应用元数据过滤 + filtered_docs = [] + for doc in docs: + match = True + for key, value in filters.items(): + if key in doc.metadata: + if isinstance(value, list): + if doc.metadata[key] not in value: + match = False + break + else: + if doc.metadata[key] != value: + match = False + break + else: + match = False + break + + if match: + filtered_docs.append(doc) + if len(filtered_docs) >= top_k: + break + + return filtered_docs + + def _rrf_rerank(self, vector_docs: List[Document], bm25_docs: List[Document], k: int = 60) -> List[Document]: + """ + 使用RRF (Reciprocal Rank Fusion) 算法重排文档 + + Args: + vector_docs: 向量检索结果 + bm25_docs: BM25检索结果 + k: RRF参数,用于平滑排名 + + Returns: + 重排后的文档列表 + """ + doc_scores = {} + doc_objects = {} + + # 计算向量检索结果的RRF分数 + for rank, doc in enumerate(vector_docs): + # 使用文档内容的哈希作为唯一标识 + doc_id = hash(doc.page_content) + doc_objects[doc_id] = doc + + # RRF公式: 1 / (k + rank) + rrf_score = 1.0 / (k + rank + 1) + doc_scores[doc_id] = doc_scores.get(doc_id, 0) + rrf_score + + logger.debug(f"向量检索 - 文档{rank+1}: RRF分数 = {rrf_score:.4f}") + + # 计算BM25检索结果的RRF分数 + for rank, doc in enumerate(bm25_docs): + doc_id = hash(doc.page_content) + doc_objects[doc_id] = doc + + rrf_score = 1.0 / (k + rank + 1) + doc_scores[doc_id] = doc_scores.get(doc_id, 0) + rrf_score + + logger.debug(f"BM25检索 - 文档{rank+1}: RRF分数 = {rrf_score:.4f}") + + # 按最终RRF分数排序 + sorted_docs = sorted(doc_scores.items(), key=lambda x: x[1], reverse=True) + + # 构建最终结果 + reranked_docs = [] + for doc_id, final_score in sorted_docs: + if doc_id in doc_objects: + doc = doc_objects[doc_id] + # 将RRF分数添加到文档元数据中 + doc.metadata['rrf_score'] = final_score + reranked_docs.append(doc) + logger.debug(f"最终排序 - 文档: {doc.page_content[:50]}... 最终RRF分数: {final_score:.4f}") + + logger.info(f"RRF重排完成: 向量检索{len(vector_docs)}个文档, BM25检索{len(bm25_docs)}个文档, 合并后{len(reranked_docs)}个文档") + + return reranked_docs + + diff --git a/code/C8/requirements.txt b/code/C8/requirements.txt new file mode 100644 index 0000000..194eec9 --- /dev/null +++ b/code/C8/requirements.txt @@ -0,0 +1,12 @@ +langchain==0.3.26 +langchain-huggingface==0.3.1 +langchain-text-splitters==0.3.8 +langchain-unstructured==0.1.6 +langchain-community==0.3.27 +faiss-cpu>=1.7.0 +unstructured==0.18.11 +Markdown==3.8.2 +sentence-transformers>=3.0.0 +lazy_loader==0.4 +rank_bm25==0.2.2 +openai>=1.86.0,<2.0.0 \ No newline at end of file diff --git a/code/C9/.env.example b/code/C9/.env.example new file mode 100644 index 0000000..18f9303 Binary files /dev/null and b/code/C9/.env.example differ diff --git a/code/C9/agent(代码系ai生成)/AI_AGENT_README.md b/code/C9/agent(代码系ai生成)/AI_AGENT_README.md new file mode 100644 index 0000000..6f72ca9 --- /dev/null +++ b/code/C9/agent(代码系ai生成)/AI_AGENT_README.md @@ -0,0 +1,438 @@ +# AI菜谱知识图谱生成器 +## 基于Kimi大模型的智能菜谱解析系统 + +### 🌟 新功能特性 + +- **🤖 AI智能解析**: 使用Kimi大模型准确提取菜谱信息 +- **📊 结构化输出**: 自动生成标准化的知识图谱数据 +- **🔄 批量处理**: 支持大规模菜谱目录的批量转换 +- **💾 多格式导出**: 支持Neo4j和CSV两种输出格式 +- **🎯 高精度**: AI模型确保食材分类、步骤解析的准确性 +- **📁 智能目录识别**: 自动扫描dishes/目录,根据子目录名推断分类 +- **⚡ 优化处理**: 减少AI分类工作,提高处理效率和准确性 + +### 🚀 快速开始 + +#### 1. 安装依赖 + +```bash +pip install -r requirements.txt +``` + +#### 2. 配置API密钥 + +方法一:设置环境变量 +```bash +export KIMI_API_KEY="your_api_key_here" +``` + +方法二:编辑config.json +```json +{ + "kimi": { + "api_key": "your_api_key_here" + } +} +``` + +#### 3. 测试AI解析功能 + +```bash +python run_ai_agent.py test +``` + +#### 4. 批量处理菜谱 + +```bash +# 处理HowToCook项目(会自动扫描dishes/目录) +python run_ai_agent.py /path/to/HowToCook-master + +# 处理其他菜谱目录 +python run_ai_agent.py /path/to/your/recipes +``` + +### 📁 项目结构 + +``` +cook-rag-example/ +├── recipe_ai_agent.py # AI解析核心引擎 +├── run_ai_agent.py # 简化运行脚本 +├── batch_manager.py # 批次管理工具 +├── amount_normalizer.py # 用量标准化工具 +├── config.json # 配置文件 +├── requirements.txt # 依赖列表 +└── ai_output/ # AI输出目录 + ├── nodes.csv # Neo4j节点数据 + ├── relationships.csv # Neo4j关系数据 + └── neo4j_import.cypher # Neo4j导入脚本 +``` + +### 📁 智能目录处理 + +#### 自动分类识别 + +系统会智能识别HowToCook项目的目录结构: + +- **专门扫描**: 只处理 `dishes/` 目录下的菜谱文件 +- **自动分类**: 根据子目录名自动推断菜谱分类 +- **排除无关文件**: 自动跳过 `template/`、`.github/` 等目录 + +#### 目录分类映射 + +``` +vegetable_dish/ → 素菜 +meat_dish/ → 荤菜 +aquatic/ → 水产 +breakfast/ → 早餐 +staple/ → 主食 +soup/ → 汤类 +dessert/ → 甜品 +drink/ → 饮料 +condiment/ → 调料 +semi-finished/ → 半成品 +``` + +#### 处理优化 + +- **减少AI工作量**: 分类信息直接从目录结构获取,无需AI推理 +- **提高准确性**: 避免AI分类错误,确保分类一致性 +- **加快处理速度**: 减少API调用复杂度和处理时间 + +### 🤖 AI解析能力 + +#### 智能信息提取 + +AI系统能够从Markdown菜谱中准确提取: + +1. **基本信息** + - 菜谱名称 + - 难度等级(1-5星) + - 菜谱分类(素菜/荤菜/水产等) + - 菜系归属(川菜/粤菜等) + +2. **食材信息** + - 食材名称和分类 + - 用量和单位 + - 主要食材识别 + +3. **烹饪步骤** + - 步骤描述和顺序 + - 使用的烹饪方法 + - 需要的工具 + - 时间估计 + +4. **额外信息** + - 准备时间/烹饪时间 + - 供应人数 + - 营养信息(当可用时) + - 相关标签 + +#### 示例:AI解析结果 + +输入菜谱: +```markdown +# 红烧茄子的做法 +预估烹饪难度:★★★★ +## 必备原料和工具 +- 青茄子 +- 大蒜 +- 酱油 +- 面粉 +``` + +AI解析输出: +```json +{ + "name": "红烧茄子", + "difficulty": 4, + "category": "素菜", + "ingredients": [ + { + "name": "青茄子", + "category": "蔬菜", + "is_main": true + }, + { + "name": "大蒜", + "category": "蔬菜", + "is_main": false + } + ] +} +``` + +### 📊 知识图谱结构 + +#### Neo4j数据模型 + +**节点类型**: +- `Recipe`: 菜谱 +- `Ingredient`: 食材 +- `CookingStep`: 烹饪步骤 + +**关系类型**: +- `has_ingredient`: 菜谱包含食材 +- `has_step`: 菜谱包含步骤 +- `belongs_to_category`: 属于分类 +- `has_difficulty`: 具有难度 + +#### 示例查询 + +```cypher +// 查找所有包含茄子的菜谱 +MATCH (recipe:Concept)-[:has_ingredient]->(ing:Concept) +WHERE ing.name CONTAINS "茄子" +RETURN recipe.name, recipe.difficulty + +// 查找四星难度的素菜 +MATCH (recipe:Concept)-[:belongs_to_category]->(cat:Concept) +WHERE cat.name = "素菜" AND recipe.difficulty = 4 +RETURN recipe.name + +// 推荐基于现有食材的菜谱 +MATCH (recipe:Concept)-[:has_ingredient]->(ing:Concept) +WHERE ing.name IN ["茄子", "大蒜", "酱油"] +WITH recipe, count(ing) as matches +WHERE matches >= 2 +RETURN recipe.name, matches +ORDER BY matches DESC +``` + +### ⚙️ 配置选项 + +#### config.json详细配置 + +```json +{ + "deepseek": { + "api_key": "your_api_key", + "base_url": "https://api.deepseek.com", + "model": "deepseek-chat", + "max_retries": 3, + "timeout": 30 + }, + "processing": { + "batch_size": 10, + "delay_between_requests": 1, + "max_concurrent_requests": 5 + }, + "output": { + "format": "neo4j", + "directory": "./ai_output", + "include_nutrition": true, + "include_tags": true + } +} +``` + +### �️ 辅助工具 + +#### 批次管理工具 (batch_manager.py) + +用于管理分批处理的进度和数据: + +```bash +# 查看处理状态 +python batch_manager.py status + +# 继续中断的处理 +python batch_manager.py continue /path/to/recipes + +# 合并批次数据 +python batch_manager.py merge + +# 清理进度文件 +python batch_manager.py clean-progress + +# 清理批次数据 +python batch_manager.py clean-batches + +# 显示批次详情 +python batch_manager.py details +``` + +#### 用量标准化工具 (amount_normalizer.py) + +提供食材用量的标准化处理: + +```python +from amount_normalizer import AmountNormalizer + +normalizer = AmountNormalizer() + +# 标准化用量 +normalized, estimated = normalizer.normalize_amount("适量", "毫升") +# 返回: ("适量", 10.0) + +# 获取可比较的数值 +comparable = normalizer.get_comparable_value("一把", "") +# 返回: 50.0 + +# 格式化显示 +display = normalizer.format_for_display("2-3个", "") +# 返回: "2-3个" +``` + +### �🔧 高级用法 + +#### 1. 自定义分类映射 + +```python +# 在recipe_ai_agent.py中修改 +category_mapping = { + "素菜": "710000000", + "荤菜": "720000000", + "自定义分类": "999000000" +} +``` + +#### 2. 扩展AI提示词 + +```python +# 修改extract_recipe_info方法中的prompt +prompt = f""" +请分析菜谱并按以下格式提取信息: +- 添加您的自定义要求 +- 特殊的分类规则 +- 额外的营养信息要求 +""" +``` + +#### 3. 批量处理优化 + +```python +# 调整处理参数 +builder = RecipeKnowledgeGraphBuilder(ai_agent) +builder.batch_size = 20 # 增加批次大小 +builder.delay = 0.5 # 减少请求间隔 +``` + +### 📈 性能优化 + +#### API调用优化 + +1. **合理的请求频率**: 默认每秒1次请求,避免API限制 +2. **错误重试机制**: 自动重试失败的请求 +3. **批量处理**: 分批处理大量菜谱文件 + +#### 内存优化 + +1. **流式处理**: 逐个处理菜谱文件,避免内存溢出 +2. **定期清理**: 处理完成后及时释放内存 +3. **进度监控**: 实时显示处理进度 + +### 🔍 故障排除 + +#### 常见问题 + +1. **API密钥错误** + ``` + 错误: API调用失败: 401 + 解决: 检查API密钥是否正确设置 + ``` + +2. **网络连接问题** + ``` + 错误: API调用超时 + 解决: 检查网络连接,或增加timeout设置 + ``` + +3. **JSON解析错误** + ``` + 错误: JSON解析错误 + 解决: AI响应格式异常,会自动使用备用解析方法 + ``` + +4. **菜谱格式问题** + ``` + 错误: 无法提取菜谱信息 + 解决: 检查Markdown格式是否符合要求 + ``` + +#### 调试模式 + +```bash +# 启用详细日志 +export DEBUG=true +python run_ai_agent.py /path/to/recipes + +# 测试单个菜谱 +python run_ai_agent.py test +``` + +### 📋 使用场景 + +#### 1. 菜谱网站构建 +- 自动分类和标签 +- 智能推荐系统 +- 营养分析 + +#### 2. 烹饪应用开发 +- 食材识别 +- 步骤指导 +- 工具推荐 + +#### 3. 营养研究 +- 食材营养分析 +- 膳食搭配研究 +- 健康饮食推荐 + +#### 4. 餐饮业务 +- 菜单优化 +- 成本分析 +- 客户偏好分析 + +### 🌐 扩展开发 + +#### 添加新的AI模型 + +```python +class CustomAIAgent(DeepSeekRecipeAgent): + def __init__(self, api_key, model_name="custom-model"): + super().__init__(api_key) + self.model_name = model_name + + def call_custom_api(self, messages): + # 实现您的自定义AI调用逻辑 + pass +``` + +#### 支持新的输出格式 + +```python +def export_to_custom_format(self, output_dir): + """导出为自定义格式""" + # 实现您的导出逻辑 + pass +``` + +### 📊 数据质量保证 + +#### AI解析准确性 + +- **多轮验证**: AI提取后进行格式验证 +- **备用解析**: AI失败时使用规则解析 +- **人工审核**: 提供数据审核接口 + +#### 数据一致性 + +- **标准化分类**: 统一的食材和菜谱分类 +- **关系验证**: 确保图谱关系的逻辑一致性 +- **重复检测**: 自动识别和处理重复数据 + +--- + +**享受AI驱动的菜谱知识图谱构建体验!** 🎉 + +现在你可以安全地进行批量处理了!使用以下命令处理整个HowToCook项目: + +```bash +python run_ai_agent.py HowToCook-master +``` + +系统会: +1. 🎯 专门扫描 `HowToCook-master/dishes/` 目录 +2. 📁 根据子目录自动识别分类 (vegetable_dish→素菜, meat_dish→荤菜等) +3. 🚫 自动排除template、.github等非菜谱目录 +4. 🤖 用AI智能解析每个菜谱的详细信息 +5. 📊 生成完整的知识图谱数据 \ No newline at end of file diff --git a/code/C9/agent(代码系ai生成)/amount_normalizer.py b/code/C9/agent(代码系ai生成)/amount_normalizer.py new file mode 100644 index 0000000..f7a688b --- /dev/null +++ b/code/C9/agent(代码系ai生成)/amount_normalizer.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +用量标准化工具 - 处理中文菜谱中的非数值用量表达 +""" + +import re +from typing import Tuple, Optional + +class AmountNormalizer: + """用量标准化器""" + + def __init__(self): + # 标准化映射表 + self.amount_mappings = { + # 适量类 + "适量": "适量", + "适当": "适量", + "酌量": "适量", + "随意": "适量", + "看个人喜好": "适量", + + # 少量类 + "少许": "少许", + "少量": "少许", + "一点点": "少许", + "微量": "少许", + "稍许": "少许", + "稍微": "少许", + + # 中等量类 + "中量": "中量", + "适中": "中量", + "正常": "中量", + + # 大量类 + "大量": "大量", + "足量": "大量", + "充足": "大量", + + # 数量词类 + "一把": "1把", + "小把": "小把", + "大把": "大把", + "一勺": "1勺", + "一小勺": "1小勺", + "一大勺": "1大勺", + "一茶匙": "1茶匙", + "一汤匙": "1汤匙", + "一撮": "1撮", + + # 滴类 + "几滴": "几滴", + "数滴": "几滴", + "2-3滴": "几滴", + + # 片/个/根类 + "几片": "几片", + "数片": "几片", + "几个": "几个", + "数个": "几个", + "几根": "几根", + "数根": "几根", + "几颗": "几颗", + "数颗": "几颗" + } + + # 估算数值映射(用于营养计算等) + self.estimated_values = { + "适量": None, # 无法估算 + "少许": 2, # 约2g/ml + "中量": 10, # 约10g/ml + "大量": 30, # 约30g/ml + "1把": 15, # 约15g + "小把": 10, # 约10g + "大把": 20, # 约20g + "1勺": 5, # 约5ml + "1小勺": 3, # 约3ml + "1大勺": 15, # 约15ml + "1茶匙": 5, # 约5ml + "1汤匙": 15, # 约15ml + "1撮": 1, # 约1g + "几滴": 1, # 约1ml + "几片": 3, # 约3片 + "几个": 3, # 约3个 + "几根": 3, # 约3根 + "几颗": 3 # 约3颗 + } + + def normalize_amount(self, amount: str, unit: str = "") -> Tuple[str, Optional[float]]: + """ + 标准化用量表达 + + Args: + amount: 原始用量 + unit: 单位 + + Returns: + Tuple[标准化后的用量, 估算数值] + """ + if not amount: + return "", None + + # 清理输入 + amount = amount.strip() + + # 尝试提取数字 + number_match = re.match(r'^(\d+(?:\.\d+)?)', amount) + if number_match: + # 如果是纯数字,直接返回 + try: + numeric_value = float(number_match.group(1)) + return amount, numeric_value + except ValueError: + pass + + # 标准化非数值表达 + normalized = self.amount_mappings.get(amount, amount) + estimated = self.estimated_values.get(normalized, None) + + return normalized, estimated + + def parse_amount_with_unit(self, amount_str: str) -> Tuple[str, str, Optional[float]]: + """ + 解析包含单位的用量字符串 + + Args: + amount_str: 如"300毫升"、"适量盐"等 + + Returns: + Tuple[数量, 单位, 估算数值] + """ + if not amount_str: + return "", "", None + + # 常见单位模式 + unit_patterns = [ + r'(\d+(?:\.\d+)?)\s*(克|千克|斤|两|钱)', # 重量 + r'(\d+(?:\.\d+)?)\s*(毫升|升|杯|勺|茶匙|汤匙)', # 体积 + r'(\d+(?:\.\d+)?)\s*(个|只|条|片|根|瓣|颗)', # 数量 + r'(\d+(?:\.\d+)?)\s*(把|撮|滴)', # 特殊 + ] + + # 尝试匹配数字+单位 + for pattern in unit_patterns: + match = re.search(pattern, amount_str) + if match: + amount = match.group(1) + unit = match.group(2) + try: + numeric_value = float(amount) + return amount, unit, numeric_value + except ValueError: + pass + + # 处理纯文字表达 + normalized, estimated = self.normalize_amount(amount_str) + return normalized, "", estimated + + def get_comparable_value(self, amount: str, unit: str = "") -> Optional[float]: + """ + 获取可比较的数值(用于排序、筛选等) + + Args: + amount: 用量 + unit: 单位 + + Returns: + 可比较的数值,None表示无法比较 + """ + # 尝试解析为数字 + try: + return float(amount) + except ValueError: + pass + + # 使用估算值 + normalized, estimated = self.normalize_amount(amount, unit) + return estimated + + def format_for_display(self, amount: str, unit: str = "") -> str: + """ + 格式化用于显示的用量字符串 + + Args: + amount: 用量 + unit: 单位 + + Returns: + 格式化后的字符串 + """ + normalized, _ = self.normalize_amount(amount, unit) + + if unit and normalized: + # 如果有单位且不是特殊表达(如"适量"已经很完整) + if normalized not in ["适量", "少许", "中量", "大量"]: + return f"{normalized} {unit}" + else: + return normalized + else: + return normalized or amount + +# 使用示例 +def demo_normalization(): + """演示标准化功能""" + normalizer = AmountNormalizer() + + test_cases = [ + ("适量", "毫升"), + ("少许", "克"), + ("一把", ""), + ("300", "毫升"), + ("几滴", ""), + ("酌量", ""), + ("2-3滴", ""), + ("一小勺", ""), + ] + + pass + +if __name__ == "__main__": + demo_normalization() \ No newline at end of file diff --git a/code/C9/agent(代码系ai生成)/batch_manager.py b/code/C9/agent(代码系ai生成)/batch_manager.py new file mode 100644 index 0000000..9416046 --- /dev/null +++ b/code/C9/agent(代码系ai生成)/batch_manager.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +分批处理管理器 - 管理菜谱处理的分批保存和断点续传功能 +""" + +import os +import json +import sys +import argparse +from datetime import datetime +from recipe_ai_agent import KimiRecipeAgent, RecipeKnowledgeGraphBuilder + +def load_config(): + """加载配置文件""" + config_file = "config.json" + if os.path.exists(config_file): + with open(config_file, 'r', encoding='utf-8') as f: + return json.load(f) + else: + print("❌ 未找到config.json配置文件") + sys.exit(1) + +def show_progress_status(output_dir: str): + """显示处理进度状态""" + progress_file = os.path.join(output_dir, "progress.json") + + if not os.path.exists(progress_file): + print("📋 未找到进度文件,没有正在进行的任务") + return + + try: + with open(progress_file, 'r', encoding='utf-8') as f: + progress_data = json.load(f) + + print("处理进度状态:") + print(f"总文件: {progress_data.get('total_files', 'N/A')}, 已处理: {progress_data.get('processed_count', 0)}") + + status = progress_data.get('current_file', 'N/A') + if status == 'COMPLETED': + print("状态: 已完成") + elif status == 'INTERRUPTED': + print("状态: 被中断") + else: + print("状态: 进行中") + + # 检查批次文件 + batch_dirs = [d for d in os.listdir(output_dir) + if d.startswith("batch_") and os.path.isdir(os.path.join(output_dir, d))] + + if batch_dirs: + print(f"已保存批次: {len(batch_dirs)} 个") + + except Exception as e: + print(f"❌ 读取进度文件失败: {str(e)}") + +def clean_progress(output_dir: str): + """清理进度文件,重新开始处理""" + progress_file = os.path.join(output_dir, "progress.json") + + if os.path.exists(progress_file): + confirm = input("⚠️ 确认要清理进度文件吗?这将删除所有处理进度 (y/N): ").strip().lower() + if confirm == 'y': + os.remove(progress_file) + print("✅ 进度文件已清理") + else: + print("取消操作") + else: + print("📋 未找到进度文件") + +def clean_batches(output_dir: str): + """清理所有批次数据""" + batch_dirs = [d for d in os.listdir(output_dir) + if d.startswith("batch_") and os.path.isdir(os.path.join(output_dir, d))] + + if not batch_dirs: + print("📁 未找到批次数据") + return + + print(f"找到 {len(batch_dirs)} 个批次目录:") + for batch_dir in sorted(batch_dirs): + print(f" - {batch_dir}") + + confirm = input("\n⚠️ 确认要删除所有批次数据吗? (y/N): ").strip().lower() + if confirm == 'y': + import shutil + for batch_dir in batch_dirs: + batch_path = os.path.join(output_dir, batch_dir) + shutil.rmtree(batch_path) + print(f"🗑️ 已删除: {batch_dir}") + print("✅ 所有批次数据已清理") + else: + print("取消操作") + +def merge_batches(output_dir: str): + """手动合并所有批次数据""" + config = load_config() + api_key = config["kimi"].get("api_key") + + if not api_key: + print("❌ 未找到API密钥配置") + return + + try: + ai_agent = KimiRecipeAgent(api_key) + builder = RecipeKnowledgeGraphBuilder(ai_agent, output_dir) + + print("合并批次数据...") + total_concepts, total_relationships = builder.merge_all_batches() + + if total_concepts > 0 or total_relationships > 0: + print(f"合并完成: {total_concepts} 概念, {total_relationships} 关系") + + # 生成Neo4j格式 + format_type = config["output"].get("format", "neo4j") + if format_type == "neo4j": + builder.export_to_neo4j_csv(output_dir, merge_batches=False) + else: + print("未找到有效的批次数据") + + except Exception as e: + print(f"❌ 合并失败: {str(e)}") + +def continue_processing(recipe_dir: str, output_dir: str): + """继续处理中断的任务""" + config = load_config() + api_key = config["kimi"].get("api_key") + + if not api_key: + print("❌ 未找到API密钥配置") + return + + try: + ai_agent = KimiRecipeAgent(api_key) + batch_size = config.get("processing", {}).get("batch_size", 20) + builder = RecipeKnowledgeGraphBuilder(ai_agent, output_dir, batch_size) + + print("继续处理中断的任务...") + processed, failed = builder.batch_process_recipes(recipe_dir, resume=True) + + print(f"处理完成: 总数 {processed}, 失败 {failed}") + + # 自动合并数据 + print("自动合并批次数据...") + merge_batches(output_dir) + + except Exception as e: + print(f"❌ 处理失败: {str(e)}") + +def show_batch_details(output_dir: str, batch_num: int = None): + """显示批次详细信息""" + batch_dirs = [d for d in os.listdir(output_dir) + if d.startswith("batch_") and os.path.isdir(os.path.join(output_dir, d))] + + if not batch_dirs: + print("📁 未找到批次数据") + return + + batch_dirs.sort() + + if batch_num is not None: + target_batch = f"batch_{batch_num:03d}" + if target_batch not in batch_dirs: + print(f"❌ 未找到批次 {batch_num}") + return + batch_dirs = [target_batch] + + import pandas as pd + + for batch_dir in batch_dirs: + print(f"\n📁 {batch_dir}:") + batch_path = os.path.join(output_dir, batch_dir) + + # 概念文件 + concepts_file = os.path.join(batch_path, "concepts.csv") + if os.path.exists(concepts_file): + df = pd.read_csv(concepts_file) + print(f" 概念数量: {len(df)}") + + # 按类型统计 + if 'concept_type' in df.columns: + type_counts = df['concept_type'].value_counts() + for concept_type, count in type_counts.items(): + print(f" - {concept_type}: {count}") + + # 关系文件 + relationships_file = os.path.join(batch_path, "relationships.csv") + if os.path.exists(relationships_file): + df = pd.read_csv(relationships_file) + print(f" 关系数量: {len(df)}") + + # 按类型统计 + if 'relationship_type' in df.columns: + type_counts = df['relationship_type'].value_counts() + for rel_type, count in type_counts.items(): + print(f" - {rel_type}: {count}") + +def main(): + """主函数""" + parser = argparse.ArgumentParser( + description='分批处理管理器 - 管理菜谱处理的分批保存和断点续传', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +使用示例: + python batch_manager.py status # 查看处理状态 + python batch_manager.py continue ./HowToCook-master # 继续中断的处理 + python batch_manager.py merge # 合并批次数据 + python batch_manager.py clean-progress # 清理进度文件 + python batch_manager.py clean-batches # 清理批次数据 + python batch_manager.py details # 显示所有批次详情 + python batch_manager.py details -b 1 # 显示指定批次详情 + """) + + subparsers = parser.add_subparsers(dest='command', help='可用命令') + + # status命令 + subparsers.add_parser('status', help='查看处理进度状态') + + # continue命令 + continue_parser = subparsers.add_parser('continue', help='继续中断的处理') + continue_parser.add_argument('recipe_dir', help='菜谱目录路径') + + # merge命令 + subparsers.add_parser('merge', help='合并所有批次数据') + + # clean命令 + subparsers.add_parser('clean-progress', help='清理进度文件') + subparsers.add_parser('clean-batches', help='清理所有批次数据') + + # details命令 + details_parser = subparsers.add_parser('details', help='显示批次详细信息') + details_parser.add_argument('-b', '--batch', type=int, help='指定批次编号') + + # 全局参数 + parser.add_argument('-o', '--output', default='./ai_output', help='输出目录路径') + + args = parser.parse_args() + + if not args.command: + parser.print_help() + return + + # 确保输出目录存在 + os.makedirs(args.output, exist_ok=True) + + print("🛠️ 分批处理管理器") + print("=" * 50) + + try: + if args.command == 'status': + show_progress_status(args.output) + elif args.command == 'continue': + continue_processing(args.recipe_dir, args.output) + elif args.command == 'merge': + merge_batches(args.output) + elif args.command == 'clean-progress': + clean_progress(args.output) + elif args.command == 'clean-batches': + clean_batches(args.output) + elif args.command == 'details': + show_batch_details(args.output, args.batch) + + except KeyboardInterrupt: + print(f"\n\n⏹️ 操作被用户中断") + except Exception as e: + print(f"\n❌ 操作失败: {str(e)}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/code/C9/agent(代码系ai生成)/config.json b/code/C9/agent(代码系ai生成)/config.json new file mode 100644 index 0000000..7eb5654 --- /dev/null +++ b/code/C9/agent(代码系ai生成)/config.json @@ -0,0 +1,39 @@ +{ + "kimi": { + "api_key": "sk-xxx", + "base_url": "https://api.moonshot.cn/v1", + "model": "kimi-k2-0711-preview", + "max_retries": 3, + "timeout": 30 + }, + "processing": { + "batch_size": 10, + "delay_between_requests": 1, + "max_concurrent_requests": 5 + }, + "output": { + "format": "neo4j", + "directory": "./ai_output", + "include_nutrition": true, + "include_tags": true, + "available_formats": ["csv", "neo4j", "rf2"] + }, + "categories": { + "素菜": "710000000", + "荤菜": "720000000", + "水产": "730000000", + "早餐": "740000000", + "主食": "750000000", + "汤类": "760000000", + "甜品": "770000000", + "饮料": "780000000", + "调料": "790000000" + }, + "difficulty_mapping": { + "1": "610000000", + "2": "620000000", + "3": "630000000", + "4": "640000000", + "5": "650000000" + } +} \ No newline at end of file diff --git a/code/C9/agent(代码系ai生成)/recipe_ai_agent.py b/code/C9/agent(代码系ai生成)/recipe_ai_agent.py new file mode 100644 index 0000000..f5aa665 --- /dev/null +++ b/code/C9/agent(代码系ai生成)/recipe_ai_agent.py @@ -0,0 +1,1347 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +基于Kimi API的智能菜谱解析AI Agent +""" + +import os +import json +import re +import time +from openai import OpenAI +from typing import Dict, List, Optional, Tuple +from dataclasses import dataclass, asdict +import pandas as pd +import csv +from datetime import datetime + +@dataclass +class IngredientInfo: + """食材信息""" + name: str + amount: str = "" + unit: str = "" + category: str = "" + is_main: bool = True # 是否主要食材 + +@dataclass +class CookingStep: + """烹饪步骤""" + step_number: int + description: str + methods: List[str] # 使用的烹饪方法 + tools: List[str] # 需要的工具 + time_estimate: str = "" # 时间估计 + +@dataclass +class RecipeInfo: + """菜谱信息""" + name: str + difficulty: int # 1-5星 + category: str + cuisine_type: str = "" # 菜系 + prep_time: str = "" + cook_time: str = "" + servings: str = "" + ingredients: List[IngredientInfo] = None + steps: List[CookingStep] = None + tags: List[str] = None + nutrition_info: Dict = None + + def __post_init__(self): + if self.ingredients is None: + self.ingredients = [] + if self.steps is None: + self.steps = [] + if self.tags is None: + self.tags = [] + if self.nutrition_info is None: + self.nutrition_info = {} + +class KimiRecipeAgent: + """Kimi菜谱解析AI Agent""" + + def __init__(self, api_key: str, base_url: str = "https://api.moonshot.cn/v1"): + self.api_key = api_key + self.base_url = base_url + self.client = OpenAI( + api_key=api_key, + base_url=base_url + ) + + # 目录名到分类的映射 + self.directory_category_mapping = { + "vegetable_dish": "素菜", + "meat_dish": "荤菜", + "aquatic": "水产", + "breakfast": "早餐", + "staple": "主食", + "soup": "汤类", + "dessert": "甜品", + "drink": "饮料", + "condiment": "调料", + "semi-finished": "半成品" + } + + # 排除的目录 + self.excluded_directories = ["template", ".github", "tips", "starsystem"] + + # 预定义的食材分类 + self.ingredient_categories = { + "蔬菜": ["茄子", "辣椒", "洋葱", "大葱", "西红柿", "土豆", "萝卜", "白菜", "豆腐"], + "调料": ["盐", "酱油", "醋", "糖", "料酒", "生抽", "老抽", "蚝油", "味精"], + "蛋白质": ["鸡蛋", "肉", "鱼", "虾", "鸡", "猪", "牛", "羊"], + "淀粉类": ["面粉", "淀粉", "米", "面条", "面包", "土豆"] + } + + # 预定义的烹饪方法 + self.cooking_methods = ["炒", "炸", "煮", "蒸", "烤", "炖", "焖", "煎", "红烧", "清炒", "爆炒"] + + # 预定义的工具 + self.cooking_tools = ["炒锅", "平底锅", "蒸锅", "刀", "案板", "筷子", "锅铲", "勺子"] + + def call_kimi_api(self, messages: List[Dict], max_retries: int = 3) -> str: + """调用Kimi API""" + for attempt in range(max_retries): + try: + response = self.client.chat.completions.create( + model="kimi-k2-0711-preview", + messages=messages, + temperature=0.3, + max_tokens=2048, + stream=False + ) + + return response.choices[0].message.content + + except Exception as e: + print(f"API调用错误 (尝试 {attempt + 1}): {str(e)}") + if attempt < max_retries - 1: + time.sleep(2 ** attempt) # 指数退避 + + raise Exception("Kimi API调用失败") + + def infer_category_from_path(self, file_path: str) -> str: + """根据文件路径推断菜谱分类""" + path_parts = file_path.replace('\\', '/').split('/') + + for part in path_parts: + if part in self.directory_category_mapping: + return self.directory_category_mapping[part] + + return "" # 如果无法推断,返回空字符串 + + def extract_recipe_info(self, markdown_content: str, file_path: str = "") -> RecipeInfo: + """使用AI提取菜谱信息""" + + # 根据路径推断分类 + inferred_category = self.infer_category_from_path(file_path) + + # 构建提示词 + category_hint = f",根据文件路径推断此菜谱属于【{inferred_category}】分类" if inferred_category else "" + + prompt = f""" +请分析以下标准化格式的菜谱Markdown文档,提取结构化信息并以JSON格式返回。 + +文件路径: {file_path} +菜谱内容: +{markdown_content} + +## 文档结构说明 +此菜谱遵循标准格式,包含以下固定二级标题: +- ## 必备原料和工具:列出所有食材和工具 +- ## 计算:包含份量计算和具体用量 +- ## 操作:详细的烹饪步骤 +- ## 附加内容:补充说明和技巧提示(需要过滤无关内容) + +## 提取规则 +1. **菜谱名称**:从一级标题(# XXX的做法)提取 +2. **难度等级**:从"预估烹饪难度:★★★"中统计★的数量 +3. **菜谱分类**:可以是多个分类,用逗号分隔(如"早餐,素菜"表示既是早餐又是素菜) +4. **食材信息**:从"必备原料和工具"和"计算"部分提取,合并用量信息 +5. **烹饪步骤**:从"操作"部分的有序列表提取 +6. **技巧补充**:从"附加内容"提取有用的烹饪技巧,忽略模板文字(如"如果您遵循本指南...Issue或Pull request"等) + +请返回标准JSON格式{category_hint}: +{{ + "name": "菜谱名称(去掉'的做法'后缀)", + "difficulty": 1-5的数字(根据★数量:★=1, ★★=2, ★★★=3, ★★★★=4, ★★★★★=5), + "category": "{inferred_category if inferred_category else '菜谱分类(素菜/荤菜/水产/早餐/主食/汤类/甜品/饮料/调料,支持多个分类用逗号分隔,如\"早餐,素菜\")'}", + "cuisine_type": "菜系(川菜/粤菜/鲁菜/苏菜/闽菜/浙菜/湘菜/徽菜/东北菜/西北菜/等,如果不明确则为空)", + "prep_time": "准备时间(从腌制、切菜等步骤推断)", + "cook_time": "烹饪时间(从炒制、炖煮等步骤推断)", + "servings": "份数/人数(从'计算'部分提取,如'2个人食用')", + "ingredients": [ + {{ + "name": "食材名称", + "amount": "用量数字(从计算部分提取具体数值)", + "unit": "单位(克、个、毫升、片等)", + "category": "食材类别(蔬菜/调料/蛋白质/淀粉类/其他)", + "is_main": true/false(主要食材为true,调料为false) + }} + ], + "steps": [ + {{ + "step_number": 1, + "description": "步骤详细描述", + "methods": ["使用的烹饪方法:炒、炸、煮、蒸、烤、炖、焖、煎、红烧、腌制、切等"], + "tools": ["需要的工具:炒锅、平底锅、蒸锅、刀、案板、筷子、锅铲、盆等"], + "time_estimate": "时间估计(如步骤中提到'15秒'、'30秒'、'10-15分钟'等)" + }} + ], + "tags": ["从附加内容中提取的有用技巧标签"], + "nutrition_info": {{ + "calories": "", + "protein": "", + "carbs": "", + "fat": "" + }} +}} + +## 重要提示: +1. 从"计算"部分精确提取食材用量和单位 +2. 从"操作"部分的有序列表逐步解析烹饪步骤 +3. 从"附加内容"中只提取烹饪技巧,忽略"Issue或Pull request"等模板文字 +4. 食材分类要准确:蔬菜(包括各种菜类)、调料(盐、酱油、糖等)、蛋白质(鱼、肉、蛋)、淀粉类(面粉、米等) +5. 菜谱分类支持多重分类:如早餐类的蔬菜粥可以分类为"早餐,素菜,主食"(逗号分隔) +6. 当遇到"适量"、"少许"等非具体数值时,不要忘记加引号,如"amount": "适量" +7. 只返回标准JSON格式,确保语法正确 +""" + + messages = [ + {"role": "system", "content": "你是一个专业的菜谱分析专家,擅长从中文菜谱中提取结构化信息。"}, + {"role": "user", "content": prompt} + ] + + try: + response = self.call_kimi_api(messages) + + # 清理响应,确保是有效的JSON + response = response.strip() + if response.startswith("```json"): + response = response[7:] + if response.endswith("```"): + response = response[:-3] + response = response.strip() + + # 解析JSON + recipe_data = json.loads(response) + + # 转换为RecipeInfo对象 + recipe_info = RecipeInfo( + name=recipe_data.get("name", ""), + difficulty=recipe_data.get("difficulty", 3), + category=recipe_data.get("category", ""), + cuisine_type=recipe_data.get("cuisine_type", ""), + prep_time=recipe_data.get("prep_time", ""), + cook_time=recipe_data.get("cook_time", ""), + servings=recipe_data.get("servings", ""), + nutrition_info=recipe_data.get("nutrition_info", {}) + ) + + # 转换食材信息 + for ing_data in recipe_data.get("ingredients", []): + ingredient = IngredientInfo( + name=ing_data.get("name", ""), + amount=ing_data.get("amount", ""), + unit=ing_data.get("unit", ""), + category=ing_data.get("category", ""), + is_main=ing_data.get("is_main", True) + ) + recipe_info.ingredients.append(ingredient) + + # 转换步骤信息 + for step_data in recipe_data.get("steps", []): + step = CookingStep( + step_number=step_data.get("step_number", 0), + description=step_data.get("description", ""), + methods=step_data.get("methods", []), + tools=step_data.get("tools", []), + time_estimate=step_data.get("time_estimate", "") + ) + recipe_info.steps.append(step) + + # 添加标签 + recipe_info.tags = recipe_data.get("tags", []) + + return recipe_info + + except json.JSONDecodeError as e: + print(f"JSON解析错误: {e}") + print(f"原始响应: {response}") + return self._fallback_parse(markdown_content) + except Exception as e: + print(f"AI解析错误: {e}") + return self._fallback_parse(markdown_content) + + def _fallback_parse(self, content: str) -> RecipeInfo: + """备用解析方法(基于规则)""" + lines = content.strip().split('\n') + + # 提取菜谱名称 + name = "" + for line in lines: + if line.startswith('# '): + name = line[2:].replace('的做法', '').strip() + break + + # 提取难度 + difficulty = 3 # 默认3星 + for line in lines: + if '★' in line: + stars = line.count('★') + difficulty = min(max(stars, 1), 5) + break + + # 简单分类判断 + category = "其他" + if any(keyword in name for keyword in ["蛋", "豆腐"]): + category = "素菜" + elif any(keyword in name for keyword in ["肉", "鸡", "鱼", "虾"]): + category = "荤菜" + + return RecipeInfo( + name=name or "未知菜谱", + difficulty=difficulty, + category=category + ) + +class RecipeKnowledgeGraphBuilder: + """菜谱知识图谱构建器 - 支持分批保存和断点续传""" + + def __init__(self, ai_agent: KimiRecipeAgent, output_dir: str = "./ai_output", batch_size: int = 20): + self.ai_agent = ai_agent + self.concepts = [] + self.relationships = [] + self.concept_id_counter = 201000000 + self.output_dir = output_dir + self.batch_size = batch_size + self.progress_file = os.path.join(output_dir, "progress.json") + self.processed_files = set() + self.current_batch = 0 + + # 确保输出目录存在 + os.makedirs(output_dir, exist_ok=True) + + # 初始化预定义概念和关系类型映射 + self._init_predefined_concepts() + self._init_relationship_mappings() + + def _init_relationship_mappings(self): + """初始化关系类型映射""" + self.relationship_type_mapping = { + "has_ingredient": "801000001", + "requires_tool": "801000002", + "has_step": "801000003", + "belongs_to_category": "801000004", + "has_difficulty": "801000005", + "uses_method": "801000006", + "has_amount": "801000007", + "step_follows": "801000008", + "serves_people": "801000009", + "cooking_time": "801000010", + "prep_time": "801000011" + } + + def _init_predefined_concepts(self): + """初始化预定义概念""" + self.predefined_concepts = [ + # 根概念 + { + "concept_id": "100000000", + "concept_type": "Root", + "name": "烹饪概念", + "fsn": "烹饪概念 (Culinary Concept)", + "preferred_term": "烹饪概念" + }, + + # 顶级概念 + { + "concept_id": "200000000", + "concept_type": "Recipe", + "name": "菜谱", + "fsn": "菜谱 (Recipe)", + "preferred_term": "菜谱" + }, + { + "concept_id": "300000000", + "concept_type": "Ingredient", + "name": "食材", + "fsn": "食材 (Ingredient)", + "preferred_term": "食材" + }, + { + "concept_id": "400000000", + "concept_type": "CookingMethod", + "name": "烹饪方法", + "fsn": "烹饪方法 (Cooking Method)", + "preferred_term": "烹饪方法" + }, + { + "concept_id": "500000000", + "concept_type": "CookingTool", + "name": "烹饪工具", + "fsn": "烹饪工具 (Cooking Tool)", + "preferred_term": "烹饪工具" + }, + + # 难度等级 + { + "concept_id": "610000000", + "concept_type": "DifficultyLevel", + "name": "一星", + "fsn": "一星 (One Star)", + "preferred_term": "一星" + }, + { + "concept_id": "620000000", + "concept_type": "DifficultyLevel", + "name": "二星", + "fsn": "二星 (Two Star)", + "preferred_term": "二星" + }, + { + "concept_id": "630000000", + "concept_type": "DifficultyLevel", + "name": "三星", + "fsn": "三星 (Three Star)", + "preferred_term": "三星" + }, + { + "concept_id": "640000000", + "concept_type": "DifficultyLevel", + "name": "四星", + "fsn": "四星 (Four Star)", + "preferred_term": "四星" + }, + { + "concept_id": "650000000", + "concept_type": "DifficultyLevel", + "name": "五星", + "fsn": "五星 (Five Star)", + "preferred_term": "五星" + }, + + # 菜谱分类 + { + "concept_id": "710000000", + "concept_type": "RecipeCategory", + "name": "素菜", + "fsn": "素菜 (Vegetarian Dish)", + "preferred_term": "素菜" + }, + { + "concept_id": "720000000", + "concept_type": "RecipeCategory", + "name": "荤菜", + "fsn": "荤菜 (Meat Dish)", + "preferred_term": "荤菜" + }, + { + "concept_id": "730000000", + "concept_type": "RecipeCategory", + "name": "水产", + "fsn": "水产 (Aquatic Product)", + "preferred_term": "水产" + }, + { + "concept_id": "740000000", + "concept_type": "RecipeCategory", + "name": "早餐", + "fsn": "早餐 (Breakfast)", + "preferred_term": "早餐" + }, + { + "concept_id": "750000000", + "concept_type": "RecipeCategory", + "name": "主食", + "fsn": "主食 (Staple Food)", + "preferred_term": "主食" + }, + { + "concept_id": "760000000", + "concept_type": "RecipeCategory", + "name": "汤类", + "fsn": "汤类 (Soup)", + "preferred_term": "汤类" + }, + { + "concept_id": "770000000", + "concept_type": "RecipeCategory", + "name": "甜品", + "fsn": "甜品 (Dessert)", + "preferred_term": "甜品" + }, + { + "concept_id": "780000000", + "concept_type": "RecipeCategory", + "name": "饮料", + "fsn": "饮料 (Beverage)", + "preferred_term": "饮料" + }, + { + "concept_id": "790000000", + "concept_type": "RecipeCategory", + "name": "调料", + "fsn": "调料 (Condiment)", + "preferred_term": "调料" + } + ] + + def save_progress(self, current_file: str = None, total_files: int = 0, processed_count: int = 0): + """保存处理进度""" + progress_data = { + "processed_files": list(self.processed_files), + "current_file": current_file, + "total_files": total_files, + "processed_count": processed_count, + "current_batch": self.current_batch, + "concept_id_counter": self.concept_id_counter, + "timestamp": datetime.now().isoformat(), + "concepts_count": len(self.concepts), + "relationships_count": len(self.relationships) + } + + with open(self.progress_file, 'w', encoding='utf-8') as f: + json.dump(progress_data, f, ensure_ascii=False, indent=2) + + def load_progress(self) -> Dict: + """加载处理进度""" + if os.path.exists(self.progress_file): + try: + with open(self.progress_file, 'r', encoding='utf-8') as f: + progress_data = json.load(f) + + self.processed_files = set(progress_data.get("processed_files", [])) + self.current_batch = progress_data.get("current_batch", 0) + self.concept_id_counter = progress_data.get("concept_id_counter", 201000000) + + return progress_data + except Exception as e: + print(f"警告: 加载进度文件失败 - {str(e)}") + return {} + return {} + + def save_batch_data(self, batch_num: int = None): + """保存当前批次数据""" + if batch_num is None: + batch_num = self.current_batch + + batch_output_dir = os.path.join(self.output_dir, f"batch_{batch_num:03d}") + os.makedirs(batch_output_dir, exist_ok=True) + + # 保存概念数据 + if self.concepts: + concepts_df = pd.DataFrame(self.concepts) + concepts_file = os.path.join(batch_output_dir, "concepts.csv") + concepts_df.to_csv(concepts_file, index=False, encoding='utf-8') + + # 保存关系数据 + if self.relationships: + relationships_df = pd.DataFrame(self.relationships) + relationships_file = os.path.join(batch_output_dir, "relationships.csv") + relationships_df.to_csv(relationships_file, index=False, encoding='utf-8') + + print(f"批次 {batch_num} 已保存") + + return batch_output_dir + + def merge_all_batches(self): + """合并所有批次数据到最终输出文件""" + print("合并批次数据...") + + all_concepts = [] + all_relationships = [] + + # 收集所有批次数据 + batch_dirs = [d for d in os.listdir(self.output_dir) + if d.startswith("batch_") and os.path.isdir(os.path.join(self.output_dir, d))] + batch_dirs.sort() + + for batch_dir in batch_dirs: + batch_path = os.path.join(self.output_dir, batch_dir) + + # 读取概念文件 + concepts_file = os.path.join(batch_path, "concepts.csv") + if os.path.exists(concepts_file): + batch_concepts = pd.read_csv(concepts_file) + all_concepts.append(batch_concepts) + + # 读取关系文件 + relationships_file = os.path.join(batch_path, "relationships.csv") + if os.path.exists(relationships_file): + batch_relationships = pd.read_csv(relationships_file) + all_relationships.append(batch_relationships) + + # 合并数据 + if all_concepts: + final_concepts = pd.concat(all_concepts, ignore_index=True) + final_concepts.to_csv(os.path.join(self.output_dir, "concepts.csv"), + index=False, encoding='utf-8') + print(f"合并概念: {len(final_concepts)} 个") + + if all_relationships: + final_relationships = pd.concat(all_relationships, ignore_index=True) + final_relationships.to_csv(os.path.join(self.output_dir, "relationships.csv"), + index=False, encoding='utf-8') + print(f"合并关系: {len(final_relationships)} 个") + + return len(final_concepts) if all_concepts else 0, len(final_relationships) if all_relationships else 0 + + def generate_concept_id(self) -> str: + """生成新的概念ID""" + self.concept_id_counter += 1 + return str(self.concept_id_counter) + + def process_recipe(self, markdown_content: str, file_path: str) -> Dict: + """处理单个菜谱""" + # 处理菜谱 + + # 使用AI提取菜谱信息 + recipe_info = self.ai_agent.extract_recipe_info(markdown_content, file_path) + + # 生成概念ID + recipe_id = self.generate_concept_id() + + # 创建菜谱概念 + recipe_concept = { + "concept_id": recipe_id, + "concept_type": "Recipe", + "name": recipe_info.name, + "fsn": f"{recipe_info.name} (Recipe)", + "preferred_term": recipe_info.name, + "synonyms": self._generate_recipe_synonyms(recipe_info.name, recipe_info.category), + "category": recipe_info.category, + "difficulty": recipe_info.difficulty, + "cuisine_type": recipe_info.cuisine_type, + "prep_time": recipe_info.prep_time, + "cook_time": recipe_info.cook_time, + "servings": recipe_info.servings, + "tags": ",".join(recipe_info.tags), + "file_path": file_path + } + + self.concepts.append(recipe_concept) + + # 处理食材 + for ingredient in recipe_info.ingredients: + ing_id = self.generate_concept_id() + ing_concept = { + "concept_id": ing_id, + "concept_type": "Ingredient", + "name": ingredient.name, + "fsn": f"{ingredient.name} (Ingredient)", + "preferred_term": ingredient.name, + "synonyms": self._generate_ingredient_synonyms(ingredient.name), + "category": ingredient.category, + "amount": ingredient.amount, + "unit": ingredient.unit, + "is_main": ingredient.is_main + } + self.concepts.append(ing_concept) + + # 添加关系:菜谱包含食材 + self.relationships.append({ + "relationship_id": f"R_{len(self.relationships) + 1:06d}", + "source_id": recipe_id, + "target_id": ing_id, + "relationship_type": self.relationship_type_mapping["has_ingredient"], + "amount": ingredient.amount, + "unit": ingredient.unit + }) + + # 处理步骤 + for step in recipe_info.steps: + step_id = self.generate_concept_id() + step_concept = { + "concept_id": step_id, + "concept_type": "CookingStep", + "name": f"步骤{step.step_number}", + "fsn": f"步骤{step.step_number} (Cooking Step)", + "preferred_term": f"步骤{step.step_number}", + "description": step.description, + "step_number": step.step_number, + "methods": ",".join(step.methods), + "tools": ",".join(step.tools), + "time_estimate": step.time_estimate + } + self.concepts.append(step_concept) + + # 添加关系:菜谱包含步骤 + self.relationships.append({ + "relationship_id": f"R_{len(self.relationships) + 1:06d}", + "source_id": recipe_id, + "target_id": step_id, + "relationship_type": self.relationship_type_mapping["has_step"], + "step_order": step.step_number + }) + + # 添加分类关系 - 支持多重分类 + category_mapping = { + "素菜": "710000000", + "荤菜": "720000000", + "水产": "730000000", + "早餐": "740000000", + "主食": "750000000", + "汤类": "760000000", + "甜品": "770000000", + "饮料": "780000000", + "调料": "790000000" + } + + # 处理多重分类(支持逗号分隔的多个分类) + categories = [cat.strip() for cat in recipe_info.category.split(',') if cat.strip()] + + for category in categories: + if category in category_mapping: + self.relationships.append({ + "relationship_id": f"R_{len(self.relationships) + 1:06d}", + "source_id": recipe_id, + "target_id": category_mapping[category], + "relationship_type": self.relationship_type_mapping["belongs_to_category"] + }) + + # 添加难度关系 + difficulty_mapping = { + 1: "610000000", # 一星 + 2: "620000000", # 二星 + 3: "630000000", # 三星 + 4: "640000000", # 四星 + 5: "650000000" # 五星 + } + + if recipe_info.difficulty in difficulty_mapping: + self.relationships.append({ + "relationship_id": f"R_{len(self.relationships) + 1:06d}", + "source_id": recipe_id, + "target_id": difficulty_mapping[recipe_info.difficulty], + "relationship_type": self.relationship_type_mapping["has_difficulty"] + }) + + return recipe_concept + + def _generate_recipe_synonyms(self, name: str, category: str) -> List[str]: + """生成菜谱的同义词列表""" + synonyms = [] + + # 基于菜谱名称生成变体 + if name.endswith("的做法"): + base_name = name.replace("的做法", "") + synonyms.extend([ + f"{base_name}制作方法", + f"{base_name}烹饪方法", + base_name + ]) + + # 基于烹饪方法生成别名(注意:只有真正的同义词才映射) + cooking_method_mappings = { + "红烧": ["braised"], # 红烧 = 英文braised + "糖醋": ["sweet and sour"], # 糖醋 = 英文sweet and sour + "清炒": ["炒制", "stir-fried"], # 清炒 = 炒制 = 英文stir-fried + "蒸": ["清蒸", "steamed"], # 蒸 = 清蒸 = 英文steamed + "炖": ["煲", "stewed"], # 炖 = 煲 = 英文stewed + "烤": ["烘烤", "roasted", "baked"], # 烤 = 烘烤 = 英文roasted/baked + "炸": ["油炸", "deep-fried"], # 炸 = 油炸 = 英文deep-fried + "焖": ["闷", "braised"], # 焖 = 闷 = 某种形式的braised + "煎": ["pan-fried"], # 煎 = 英文pan-fried + "爆炒": ["stir-fried"], # 爆炒 = stir-fried的一种 + "白切": ["boiled"], # 白切 = 水煮的一种 + "油焖": ["oil-braised"] # 油焖 = oil-braised + } + + for method, variants in cooking_method_mappings.items(): + if method in name: + for variant in variants: + if variant != method: # 避免重复 + synonym = name.replace(method, variant) + if synonym != name: + synonyms.append(synonym) + + # 基于食材生成别名(提取主要食材) + ingredient_aliases = { + "茄子": ["青茄子", "紫茄子", "eggplant"], + "土豆": ["马铃薯", "洋芋", "potato"], + "西红柿": ["番茄", "tomato"], + "青椒": ["彩椒", "甜椒", "bell pepper"], + "豆腐": ["嫩豆腐", "老豆腐", "tofu"], + "白菜": ["大白菜", "小白菜", "cabbage"], + "萝卜": ["白萝卜", "胡萝卜", "radish"] + } + + for ingredient, aliases in ingredient_aliases.items(): + if ingredient in name: + for alias in aliases: + if alias != ingredient: + synonym = name.replace(ingredient, alias) + if synonym != name: + synonyms.append(synonym) + + # 基于地域特色添加别名 + regional_mappings = { + "川味": ["四川风味", "川菜风格"], + "粤式": ["广东风味", "粤菜风格"], + "京味": ["北京风味", "京菜风格"], + "湘味": ["湖南风味", "湘菜风格"] + } + + for region, variants in regional_mappings.items(): + if region in name: + for variant in variants: + synonym = name.replace(region, variant) + if synonym != name: + synonyms.append(synonym) + + # 去重并返回,按语言分类 + unique_synonyms = list(set(synonyms)) + return self._categorize_synonyms_by_language(unique_synonyms) + + def _categorize_synonyms_by_language(self, synonyms: List[str]) -> List[dict]: + """按语言分类同义词""" + categorized = [] + + for synonym in synonyms: + # 检测语言 + if self._is_english(synonym): + categorized.append({ + "term": synonym, + "language": "en", + "language_code": "en-US" + }) + elif self._is_chinese(synonym): + categorized.append({ + "term": synonym, + "language": "zh", + "language_code": "zh-CN" + }) + else: + # 默认为中文 + categorized.append({ + "term": synonym, + "language": "zh", + "language_code": "zh-CN" + }) + + return categorized + + def _is_english(self, text: str) -> bool: + """检测是否为英文""" + import re + # 检查是否主要包含英文字母和空格 + english_chars = re.findall(r'[a-zA-Z\s\-]', text) + return len(english_chars) / len(text) > 0.7 if text else False + + def _is_chinese(self, text: str) -> bool: + """检测是否为中文""" + import re + # 检查是否包含中文字符 + chinese_chars = re.findall(r'[\u4e00-\u9fff]', text) + return len(chinese_chars) > 0 + + def _format_synonyms_for_neo4j(self, synonyms) -> str: + """格式化同义词用于Neo4j导出""" + import pandas as pd + import json + + # 处理NaN值和空值 + if pd.isna(synonyms) or not synonyms: + return "" + + # 如果是字符串,尝试解析为JSON + if isinstance(synonyms, str): + if synonyms.strip() == "[]" or synonyms.strip() == "": + return "" + try: + synonyms = json.loads(synonyms) + except (json.JSONDecodeError, ValueError): + # 如果不是JSON,当作单个同义词处理 + return synonyms.strip() + + # 如果不是列表,返回空字符串 + if not isinstance(synonyms, (list, tuple)): + return "" + + formatted_terms = [] + for synonym_data in synonyms: + if isinstance(synonym_data, dict): + # 新格式:包含语言信息 + term = synonym_data.get('term', '') + lang = synonym_data.get('language', 'zh') + if term: + formatted_terms.append(f"{term}({lang})") + else: + # 兼容旧格式:纯字符串 + if synonym_data and str(synonym_data).strip(): + formatted_terms.append(str(synonym_data).strip()) + + return "|".join(formatted_terms) + + def _generate_ingredient_synonyms(self, name: str) -> List[str]: + """生成食材的同义词列表""" + ingredient_synonym_dict = { + # 蔬菜类 + "青茄子": ["茄子", "紫茄子", "圆茄"], + "西红柿": ["番茄", "洋柿子"], + "土豆": ["马铃薯", "洋芋", "地蛋"], + "红薯": ["地瓜", "甘薯", "山芋"], + "玉米": ["苞米", "玉蜀黍"], + "青椒": ["柿子椒", "甜椒", "彩椒"], + "大葱": ["葱白", "韭葱"], + "小葱": ["香葱", "细葱"], + "香菜": ["芫荽", "胡荽"], + "菠菜": ["赤根菜", "波斯菜"], + + # 调料类 + "生抽": ["淡色酱油", "鲜味酱油"], + "老抽": ["深色酱油", "红烧酱油"], + "料酒": ["黄酒", "绍兴酒"], + "白糖": ["细砂糖", "绵白糖"], + "冰糖": ["冰片糖", "块糖"], + "八角": ["大料", "茴香"], + + # 蛋白质类 + "鸡蛋": ["鸡子", "土鸡蛋"], + "豆腐": ["水豆腐", "嫩豆腐"] + } + + synonyms = ingredient_synonym_dict.get(name, []) + return self._categorize_synonyms_by_language(synonyms) + + def batch_process_recipes(self, recipe_dir: str, resume: bool = True) -> Tuple[int, int]: + """批量处理菜谱目录 - 支持断点续传和分批保存""" + import glob + + # 检查是否要恢复之前的进度 + progress_data = {} + if resume: + progress_data = self.load_progress() + if progress_data: + processed_count = progress_data.get("processed_count", 0) + print(f"检测到未完成任务,已处理: {processed_count} 个菜谱") + + confirm = input("\n是否继续之前的处理? (Y/n): ").strip().lower() + if confirm == 'n': + print("重新开始处理...") + self.processed_files.clear() + self.current_batch = 0 + self.concept_id_counter = 201000000 + # 清理进度文件 + if os.path.exists(self.progress_file): + os.remove(self.progress_file) + else: + print("继续之前的处理...") + + # 专门扫描dishes目录 + dishes_dir = os.path.join(recipe_dir, "dishes") + if not os.path.exists(dishes_dir): + # 如果没有dishes目录,则扫描整个目录(向后兼容) + dishes_dir = recipe_dir + print(f"未找到dishes目录,扫描整个目录: {recipe_dir}") + else: + print(f"扫描菜谱目录: {dishes_dir}") + + recipe_files = glob.glob(os.path.join(dishes_dir, "**/*.md"), recursive=True) + + # 过滤排除的目录 + filtered_files = [] + for recipe_file in recipe_files: + relative_path = os.path.relpath(recipe_file, recipe_dir) + path_parts = relative_path.replace('\\', '/').split('/') + + # 检查是否包含排除的目录 + if any(excluded in path_parts for excluded in self.ai_agent.excluded_directories): + continue + + filtered_files.append(recipe_file) + + recipe_files = filtered_files + + # 过滤掉已处理的文件 + remaining_files = [] + for recipe_file in recipe_files: + relative_path = os.path.relpath(recipe_file, recipe_dir) + if relative_path not in self.processed_files: + remaining_files.append(recipe_file) + + total_files = len(recipe_files) + remaining_count = len(remaining_files) + already_processed = len(self.processed_files) + + print(f"📊 文件统计:") + print(f" - 总文件数: {total_files}") + print(f" - 已处理: {already_processed}") + print(f" - 待处理: {remaining_count}") + + if remaining_count == 0: + print("✅ 所有文件都已处理完成!") + return already_processed, 0 + + processed_count = already_processed + failed_count = 0 + current_batch_count = 0 + + try: + for i, recipe_file in enumerate(remaining_files): + try: + with open(recipe_file, 'r', encoding='utf-8') as f: + content = f.read() + + relative_path = os.path.relpath(recipe_file, recipe_dir) + + # 处理菜谱 + self.process_recipe(content, relative_path) + + # 标记为已处理 + self.processed_files.add(relative_path) + processed_count += 1 + current_batch_count += 1 + + # 简化进度显示 + if processed_count % 20 == 0: + progress = (processed_count / total_files) * 100 + print(f"进度: {processed_count}/{total_files} ({progress:.1f}%)") + + # 保存进度(每处理5个文件保存一次进度) + if processed_count % 5 == 0: + self.save_progress(relative_path, total_files, processed_count) + + # 检查是否需要保存批次 + if current_batch_count >= self.batch_size: + self.save_batch_data() + + # 重置当前批次 + self.concepts.clear() + self.relationships.clear() + self.current_batch += 1 + current_batch_count = 0 + + except Exception as e: + failed_count += 1 + print(f"❌ 处理失败: {recipe_file} - {str(e)}") + continue + + # 保存最后一个批次(如果有数据) + if current_batch_count > 0: + self.save_batch_data() + + # 最终保存进度 + self.save_progress("COMPLETED", total_files, processed_count) + + print(f"处理完成: 成功 {processed_count - already_processed} 个,失败 {failed_count} 个") + + except KeyboardInterrupt: + print(f"用户中断,已保存进度: {processed_count}/{total_files}") + + # 保存当前批次数据 + if current_batch_count > 0: + self.save_batch_data() + + # 保存进度 + self.save_progress("INTERRUPTED", total_files, processed_count) + + return processed_count, failed_count + + def export_to_csv(self, output_dir: str): + """导出为CSV格式""" + os.makedirs(output_dir, exist_ok=True) + + # 导出概念 + concepts_df = pd.DataFrame(self.concepts) + concepts_df.to_csv(os.path.join(output_dir, "concepts.csv"), + index=False, encoding='utf-8') + + # 导出关系 + relationships_df = pd.DataFrame(self.relationships) + relationships_df.to_csv(os.path.join(output_dir, "relationships.csv"), + index=False, encoding='utf-8') + + print(f"CSV文件已导出到: {output_dir}") + print(f"- 概念数量: {len(self.concepts)}") + print(f"- 关系数量: {len(self.relationships)}") + + def export_to_rf2_format(self, output_dir: str): + """导出为RF2标准格式""" + os.makedirs(output_dir, exist_ok=True) + + # 合并所有概念(包括预定义概念) + all_concepts = list(self.predefined_concepts) + self.concepts + + # 1. 导出概念文件 (rf2_concept.txt) + concept_headers = ["id", "effectiveTime", "active", "moduleId", "definitionStatusId"] + with open(os.path.join(output_dir, "rf2_concept.txt"), 'w', encoding='utf-8') as f: + f.write('\t'.join(concept_headers) + '\n') + for concept in all_concepts: + f.write(f"{concept['concept_id']}\t20241201\t1\t900000000\t900000000\n") + + # 2. 导出描述文件 (rf2_description.txt) - 包含别名 + desc_headers = ["id", "effectiveTime", "active", "moduleId", "conceptId", + "languageCode", "typeId", "term", "caseSignificanceId"] + + desc_id_counter = 1 + with open(os.path.join(output_dir, "rf2_description.txt"), 'w', encoding='utf-8') as f: + f.write('\t'.join(desc_headers) + '\n') + + for concept in all_concepts: + concept_id = concept['concept_id'] + + # 完全限定名 (FSN) + if 'fsn' in concept and concept['fsn']: + f.write(f"D{desc_id_counter:06d}\t20241201\t1\t900000000\t{concept_id}\t" + f"zh-CN\t900000003\t{concept['fsn']}\t900000000\n") + desc_id_counter += 1 + + # 首选术语 (PT) + if 'preferred_term' in concept and concept['preferred_term']: + f.write(f"D{desc_id_counter:06d}\t20241201\t1\t900000000\t{concept_id}\t" + f"zh-CN\t900000001\t{concept['preferred_term']}\t900000000\n") + desc_id_counter += 1 + + # 同义词 (Synonyms) - 支持多语言 + if 'synonyms' in concept and concept['synonyms']: + for synonym_data in concept['synonyms']: + if isinstance(synonym_data, dict): + # 新格式:包含语言信息 + term = synonym_data['term'] + lang_code = synonym_data['language_code'] + else: + # 兼容旧格式:纯字符串 + term = synonym_data + lang_code = "zh-CN" # 默认中文 + + f.write(f"D{desc_id_counter:06d}\t20241201\t1\t900000000\t{concept_id}\t" + f"{lang_code}\t900000002\t{term}\t900000000\n") + desc_id_counter += 1 + + # 3. 导出关系文件 (rf2_relationship.txt) + rel_headers = ["id", "effectiveTime", "active", "moduleId", "sourceId", + "destinationId", "relationshipGroup", "typeId", "characteristicTypeId", "modifierId"] + + with open(os.path.join(output_dir, "rf2_relationship.txt"), 'w', encoding='utf-8') as f: + f.write('\t'.join(rel_headers) + '\n') + + rel_id_counter = 1 + for relationship in self.relationships: + f.write(f"R{rel_id_counter:06d}\t20241201\t1\t900000000\t" + f"{relationship['source_id']}\t{relationship['target_id']}\t0\t" + f"{relationship['relationship_type']}\t900000000\t900000000\n") + rel_id_counter += 1 + + print(f"RF2格式文件已导出到: {output_dir}") + print(f"- rf2_concept.txt: {len(all_concepts)} 个概念") + print(f"- rf2_description.txt: 包含首选术语和同义词") + print(f"- rf2_relationship.txt: {len(self.relationships)} 个关系") + + def export_to_neo4j_csv(self, output_dir: str, merge_batches: bool = True): + """导出为Neo4j导入格式的CSV - 支持合并批次数据""" + os.makedirs(output_dir, exist_ok=True) + + # 如果需要合并批次数据 + final_concepts = [] + final_relationships = [] + + if merge_batches: + # 先尝试合并所有批次数据 + total_concepts, total_relationships = self.merge_all_batches() + + # 如果有合并的数据,使用合并后的数据 + if total_concepts > 0: + concepts_df = pd.read_csv(os.path.join(output_dir, "concepts.csv")) + final_concepts = concepts_df.to_dict('records') + else: + final_concepts = self.concepts + + if total_relationships > 0: + relationships_df = pd.read_csv(os.path.join(output_dir, "relationships.csv")) + final_relationships = relationships_df.to_dict('records') + else: + final_relationships = self.relationships + else: + # 使用当前内存中的数据 + final_concepts = self.concepts + final_relationships = self.relationships + + # 准备节点数据 + nodes_data = [] + + # 首先添加预定义概念 + for predefined_concept in self.predefined_concepts: + node = { + "nodeId": predefined_concept["concept_id"], + "labels": predefined_concept["concept_type"], + "name": predefined_concept["name"], + "preferredTerm": predefined_concept.get("preferred_term", ""), + "fsn": predefined_concept.get("fsn", ""), + "conceptType": predefined_concept["concept_type"], + "synonyms": self._format_synonyms_for_neo4j(predefined_concept.get("synonyms", [])) + } + nodes_data.append(node) + + # 然后添加动态生成的概念 + for concept in final_concepts: + node = { + "nodeId": concept["concept_id"], + "labels": concept["concept_type"], + "name": concept["name"], + "preferredTerm": concept.get("preferred_term", ""), + "category": concept.get("category", ""), + "conceptType": concept["concept_type"], + "synonyms": self._format_synonyms_for_neo4j(concept.get("synonyms", [])) + } + + # 添加特定类型的属性 + if concept["concept_type"] == "Recipe": + node.update({ + "difficulty": concept.get("difficulty", ""), + "cuisineType": concept.get("cuisine_type", ""), + "prepTime": concept.get("prep_time", ""), + "cookTime": concept.get("cook_time", ""), + "servings": concept.get("servings", ""), + "tags": concept.get("tags", ""), + "filePath": concept.get("file_path", "") + }) + elif concept["concept_type"] == "Ingredient": + node.update({ + "amount": concept.get("amount", ""), + "unit": concept.get("unit", ""), + "isMain": concept.get("is_main", "") + }) + elif concept["concept_type"] == "CookingStep": + node.update({ + "description": concept.get("description", ""), + "stepNumber": concept.get("step_number", ""), + "methods": concept.get("methods", ""), + "tools": concept.get("tools", ""), + "timeEstimate": concept.get("time_estimate", "") + }) + + nodes_data.append(node) + + # 导出节点 + nodes_df = pd.DataFrame(nodes_data) + nodes_df.to_csv(os.path.join(output_dir, "nodes.csv"), + index=False, encoding='utf-8') + + # 准备关系数据 + relationships_data = [] + for rel in final_relationships: + relationship = { + "startNodeId": rel["source_id"], + "endNodeId": rel["target_id"], + "relationshipType": rel["relationship_type"], + "relationshipId": rel["relationship_id"] + } + + # 添加额外属性 + for key, value in rel.items(): + if key not in ["source_id", "target_id", "relationship_type", "relationship_id"]: + relationship[key] = value + + relationships_data.append(relationship) + + # 导出关系 + relationships_df = pd.DataFrame(relationships_data) + relationships_df.to_csv(os.path.join(output_dir, "relationships.csv"), + index=False, encoding='utf-8') + + # 生成Neo4j导入脚本 + import_script = f""" +// Neo4j 数据导入脚本 + +// 导入节点 +LOAD CSV WITH HEADERS FROM 'file:///nodes.csv' AS row +CREATE (n:Concept) +SET n.nodeId = row.nodeId, + n.name = row.name, + n.preferredTerm = row.preferredTerm, + n.category = row.category, + n.conceptType = row.conceptType, + n.difficulty = toInteger(row.difficulty), + n.cuisineType = row.cuisineType, + n.prepTime = row.prepTime, + n.cookTime = row.cookTime, + n.servings = row.servings, + n.tags = row.tags, + n.filePath = row.filePath, + n.amount = row.amount, + n.unit = row.unit, + n.isMain = toBoolean(row.isMain), + n.description = row.description, + n.stepNumber = toInteger(row.stepNumber), + n.methods = row.methods, + n.tools = row.tools, + n.timeEstimate = row.timeEstimate; + +// 创建索引 +CREATE INDEX concept_id_index IF NOT EXISTS FOR (c:Concept) ON (c.nodeId); +CREATE INDEX concept_name_index IF NOT EXISTS FOR (c:Concept) ON (c.name); +CREATE INDEX concept_category_index IF NOT EXISTS FOR (c:Concept) ON (c.category); + +// 导入关系 +LOAD CSV WITH HEADERS FROM 'file:///relationships.csv' AS row +MATCH (start:Concept {{nodeId: row.startNodeId}}) +MATCH (end:Concept {{nodeId: row.endNodeId}}) +CALL apoc.create.relationship(start, row.relationshipType, {{ + relationshipId: row.relationshipId, + amount: row.amount, + unit: row.unit, + stepOrder: toInteger(row.step_order) +}}, end) YIELD rel +RETURN count(rel); +""" + + with open(os.path.join(output_dir, "neo4j_import.cypher"), 'w', encoding='utf-8') as f: + f.write(import_script) + + print(f"Neo4j CSV文件已导出到: {output_dir}") + print(f"- 节点数量: {len(nodes_data)}") + print(f"- 关系数量: {len(relationships_data)}") + +def main(): + """主函数""" + import argparse + + parser = argparse.ArgumentParser(description='使用AI智能解析菜谱生成知识图谱') + parser.add_argument('recipe_dir', help='菜谱目录路径') + parser.add_argument('-k', '--api-key', required=True, help='Kimi API密钥') + parser.add_argument('-o', '--output', default='./ai_output', help='输出目录路径') + parser.add_argument('--format', choices=['csv', 'neo4j'], default='neo4j', + help='输出格式 (csv 或 neo4j)') + parser.add_argument('--base-url', default='https://api.moonshot.cn/v1', + help='Kimi API基础URL') + + args = parser.parse_args() + + # 检查输入目录 + if not os.path.exists(args.recipe_dir): + print(f"错误: 菜谱目录不存在 - {args.recipe_dir}") + return + + # 创建AI agent + print("初始化Kimi AI Agent...") + ai_agent = KimiRecipeAgent(args.api_key, args.base_url) + + # 创建知识图谱构建器 + builder = RecipeKnowledgeGraphBuilder(ai_agent, args.output) + + # 批量处理菜谱 + print(f"开始处理菜谱目录: {args.recipe_dir}") + processed, failed = builder.batch_process_recipes(args.recipe_dir) + + print(f"\n处理完成:") + print(f"- 成功处理: {processed} 个菜谱") + print(f"- 处理失败: {failed} 个菜谱") + + # 导出数据 + if args.format == 'neo4j': + builder.export_to_neo4j_csv(args.output) + else: + builder.export_to_csv(args.output) + +if __name__ == "__main__": + # 测试用例 + if len(os.sys.argv) == 1: + print("AI菜谱解析器测试模式") + print("请提供Kimi API密钥和菜谱目录路径") + print("使用方法:") + print("python recipe_ai_agent.py /path/to/recipes -k YOUR_API_KEY") + else: + main() \ No newline at end of file diff --git a/code/C9/agent(代码系ai生成)/recipe_ontology_design.md b/code/C9/agent(代码系ai生成)/recipe_ontology_design.md new file mode 100644 index 0000000..95cf480 --- /dev/null +++ b/code/C9/agent(代码系ai生成)/recipe_ontology_design.md @@ -0,0 +1,304 @@ +# 菜谱知识图谱设计方案 +## 烹饪本体设计 + +### 概述 +本设计方案将菜谱数据结构化为本体图数据库,支持语义查询、推理和知识发现。 + +### 核心概念体系 (Concept Hierarchy) + +#### 1. 根概念 (Root Concept) +``` +100000000 | Culinary Concept | (烹饪概念) +``` + +#### 2. 顶级概念 (Top Level Concepts) +``` +200000000 | Recipe | (菜谱) +300000000 | Ingredient | (食材) +400000000 | Tool | (工具) +500000000 | Cooking Method | (烹饪方法) +600000000 | Difficulty Level | (难度等级) +700000000 | Recipe Category | (菜谱分类) +800000000 | Measurement Unit | (计量单位) +900000000 | Cooking Step | (烹饪步骤) +``` + +### 概念分类体系 + +#### 菜谱分类 (Recipe Categories) +``` +710000000 | Vegetable Dish | (素菜) +720000000 | Meat Dish | (荤菜) +730000000 | Aquatic Product | (水产) +740000000 | Breakfast | (早餐) +750000000 | Staple Food | (主食) +760000000 | Soup | (汤类) +770000000 | Dessert | (甜品) +780000000 | Beverage | (饮料) +790000000 | Condiment | (调料) +``` + +#### 食材分类 (Ingredient Categories) +``` +310000000 | Vegetable | (蔬菜) +320000000 | Seasoning | (调料) +330000000 | Protein | (蛋白质) +340000000 | Starch | (淀粉类) +350000000 | Dairy | (乳制品) +360000000 | Fruit | (水果) +370000000 | Herb | (香草香料) +380000000 | Oil Fat | (油脂类) +``` + +#### 难度等级 (Difficulty Levels) +``` +610000000 | One Star | (一星) ★ +620000000 | Two Star | (二星) ★★ +630000000 | Three Star | (三星) ★★★ +640000000 | Four Star | (四星) ★★★★ +650000000 | Five Star | (五星) ★★★★★ +``` + +#### 烹饪方法 (Cooking Methods) +``` +501000000 | Stir Fry | (炒) +502000000 | Deep Fry | (炸) +503000000 | Braise | (红烧) +504000000 | Steam | (蒸) +505000000 | Boil | (煮) +506000000 | Roast | (烤) +507000000 | Stew | (炖) +508000000 | Mix | (拌) +509000000 | Marinate | (腌) +510000000 | Blanch | (焯) +``` + +### 关系类型定义 (Relationship Types) + +#### 核心关系 (Core Relationships) +``` +116680003 | is_a | (是一个) - 层次分类关系 +``` + +#### 属性关系 (Attribute Relationships) +``` +801000001 | has_ingredient | (包含食材) +801000002 | requires_tool | (需要工具) +801000003 | has_step | (包含步骤) +801000004 | belongs_to_category | (属于分类) +801000005 | has_difficulty | (具有难度) +801000006 | uses_method | (使用方法) +801000007 | has_amount | (具有用量) +801000008 | step_follows | (步骤顺序) +801000009 | serves_people | (供应人数) +801000010 | cooking_time | (烹饪时间) +801000011 | prep_time | (准备时间) +801000012 | ingredient_substitute | (食材替代) +801000013 | recipe_variant | (菜谱变体) +801000014 | nutritional_info | (营养信息) +``` + +### 具体实例设计 + +#### 红烧茄子菜谱实例 +``` +概念ID: 201000001 +完全限定名: 201000001 | 红烧茄子 (Braised Eggplant) | +首选术语: 红烧茄子 +同义词: 茄子烧制, 红烧青茄子 + +属性关系: +- belongs_to_category = 710000000 | 素菜 +- has_difficulty = 640000000 | 四星 +- serves_people = 2人份 +- cooking_time = 30分钟 +- prep_time = 15分钟 + +食材关系: +- has_ingredient = 311000001 | 青茄子 | : has_amount = "0.7个/份" +- has_ingredient = 311000002 | 大蒜 | : has_amount = "3瓣" +- has_ingredient = 321000001 | 酱油 | : has_amount = "茄子数量*7克" +- has_ingredient = 331000001 | 鸡蛋 | : has_amount = "1个" +- has_ingredient = 341000001 | 面粉 | : has_amount = "青茄子数量*150克" + +工具关系: +- requires_tool = 401000001 | 炒锅 +- requires_tool = 401000002 | 菜刀 +- requires_tool = 401000003 | 筷子 + +方法关系: +- uses_method = 502000000 | 炸 +- uses_method = 503000000 | 红烧 +- uses_method = 501000000 | 炒 + +步骤关系: +- has_step = S001 | 清洗食材 +- has_step = S002 | 切配处理 +- has_step = S003 | 调制面糊 +- has_step = S004 | 油炸茄块 +- has_step = S005 | 炒制调味 +``` + +### 表达式系统 + +#### 预协调表达式 (Precoordinated) +``` +201000001 | 红烧茄子 | +``` + +#### 后协调表达式 (Postcoordinated) +``` +# 四星难度的素菜 +710000000 | 素菜 | : has_difficulty = 640000000 | 四星 | + +# 包含茄子的红烧菜谱 +200000000 | 菜谱 | : { + has_ingredient = 311000001 | 青茄子 |, + uses_method = 503000000 | 红烧 | +} + +# 30分钟内完成的四星菜谱 +200000000 | 菜谱 | : { + has_difficulty = 640000000 | 四星 |, + cooking_time <= 30分钟 +} +``` + +### 数据文件结构 + +#### 概念文件 (rf2_concept.txt) +``` +id effectiveTime active moduleId definitionStatusId +100000000 20241201 1 900000000 900000000 +200000000 20241201 1 900000000 900000000 +201000001 20241201 1 900000000 900000000 +``` + +#### 描述文件 (rf2_description.txt) +``` +id effectiveTime active moduleId conceptId languageCode typeId term caseSignificanceId +D001 20241201 1 900000000 201000001 zh-CN 900000001 红烧茄子 900000000 +D002 20241201 1 900000000 201000001 zh-CN 900000002 茄子烧制 900000000 +D003 20241201 1 900000000 201000001 en 900000001 Braised Eggplant 900000000 +``` + +#### 关系文件 (rf2_relationship.txt) +``` +id effectiveTime active moduleId sourceId destinationId relationshipGroup typeId characteristicTypeId modifierId +R001 20241201 1 900000000 201000001 710000000 0 801000004 900000000 900000000 +R002 20241201 1 900000000 201000001 640000000 0 801000005 900000000 900000000 +R003 20241201 1 900000000 201000001 311000001 1 801000001 900000000 900000000 +``` + +### 查询示例 + +#### 1. 基础查询 - 所有素菜 +```cypher +MATCH (recipe:Concept)-[:IS_A*]->(category:Concept {conceptId: "710000000"}) +RETURN recipe.preferredTerm +``` + +#### 2. 复杂查询 - 包含特定食材的四星菜谱 +```cypher +MATCH (recipe:Concept)-[:HAS_INGREDIENT]->(ingredient:Concept) +WHERE ingredient.conceptId = "311000001" +AND (recipe)-[:HAS_DIFFICULTY]->(:Concept {conceptId: "640000000"}) +RETURN recipe.preferredTerm, recipe.cookingTime +``` + +#### 3. 语义查询 - 所有炒制类菜谱 +```cypher +MATCH (recipe:Concept)-[:USES_METHOD]->(method:Concept) +WHERE (method)-[:IS_A*]->(:Concept {conceptId: "501000000"}) +RETURN DISTINCT recipe.preferredTerm +``` + +### 实现技术栈 + +#### 图数据库选择 +- **Neo4j**: 成熟的图数据库,适合复杂查询 +- **ArangoDB**: 多模型数据库,支持图和文档 +- **Amazon Neptune**: 云原生图数据库 + +#### API设计 +```python +class RecipeOntologyAPI: + def search_recipes_by_ingredient(self, ingredient_id: str) -> List[Recipe]: + """根据食材搜索菜谱""" + pass + + def get_recipe_variants(self, recipe_id: str) -> List[Recipe]: + """获取菜谱变体""" + pass + + def suggest_substitutes(self, ingredient_id: str) -> List[Ingredient]: + """建议食材替代""" + pass + + def analyze_nutrition(self, recipe_id: str) -> NutritionInfo: + """分析营养成分""" + pass +``` + +### 应用场景 + +#### 1. 智能菜谱推荐 +- 基于现有食材推荐菜谱 +- 根据难度等级筛选 +- 营养搭配建议 + +#### 2. 食材替代建议 +- 过敏原替代 +- 地域性食材替换 +- 营养等价替代 + +#### 3. 烹饪知识推理 +- 步骤优化建议 +- 工具使用指导 +- 时间管理优化 + +#### 4. 营养分析 +- 卡路里计算 +- 营养成分分析 +- 膳食搭配建议 + +### 扩展性设计 + +#### 多语言支持 +``` +zh-CN: 红烧茄子 +en-US: Braised Eggplant +ja-JP: 茄子の煮物 +ko-KR: 가지조림 +``` + +#### 地域化扩展 +``` +中式烹饪: 701000000 +法式烹饪: 702000000 +意式烹饪: 703000000 +日式烹饪: 704000000 +``` + +#### 个性化标签 +``` +vegetarian: 素食主义 +vegan: 纯素 +halal: 清真 +kosher: 犹太教食物 +gluten_free: 无麸质 +``` + +### 质量控制 + +#### 概念一致性检查 +- 循环依赖检测 +- 概念完整性验证 +- 关系合理性校验 + +#### 数据质量保证 +- 重复概念检测 +- 缺失关系补充 +- 术语标准化 + +这个设计方案提供了一个完整的菜谱知识图谱框架,可以支持复杂的语义查询、推理和知识发现功能。 \ No newline at end of file diff --git a/code/C9/agent(代码系ai生成)/requirements.txt b/code/C9/agent(代码系ai生成)/requirements.txt new file mode 100644 index 0000000..4f1ee2f --- /dev/null +++ b/code/C9/agent(代码系ai生成)/requirements.txt @@ -0,0 +1,6 @@ +pandas==2.3.1 +pathlib2==2.3.6 +neo4j==5.28.1 +requests==2.32.4 +dataclasses==0.6 +openai==1.97.0 \ No newline at end of file diff --git a/code/C9/agent(代码系ai生成)/run_ai_agent.py b/code/C9/agent(代码系ai生成)/run_ai_agent.py new file mode 100644 index 0000000..903ec12 --- /dev/null +++ b/code/C9/agent(代码系ai生成)/run_ai_agent.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +简化的AI菜谱解析运行脚本 +""" + +import os +import json +import sys +from recipe_ai_agent import KimiRecipeAgent, RecipeKnowledgeGraphBuilder + +def load_config(): + """加载配置文件""" + config_file = "config.json" + if os.path.exists(config_file): + with open(config_file, 'r', encoding='utf-8') as f: + return json.load(f) + else: + print("警告: 未找到config.json配置文件,将使用默认配置") + return { + "kimi": { + "api_key": "", + "base_url": "https://api.moonshot.cn/v1" + }, + "output": { + "format": "neo4j", + "directory": "./ai_output" + } + } + +def setup_api_key(): + """设置API密钥""" + api_key = os.getenv('KIMI_API_KEY') + if not api_key: + api_key = input("请输入Kimi API密钥: ").strip() + if not api_key: + print("错误: 必须提供API密钥") + sys.exit(1) + return api_key + +def get_recipe_directory(): + """获取菜谱目录""" + if len(sys.argv) > 1: + recipe_dir = sys.argv[1] + else: + recipe_dir = input("请输入菜谱目录路径: ").strip() + + if not os.path.exists(recipe_dir): + print(f"错误: 目录不存在 - {recipe_dir}") + sys.exit(1) + + return recipe_dir + +def test_single_recipe(): + """测试单个菜谱解析""" + test_recipe = """# 红烧茄子的做法 +预估烹饪难度:★★★★ + +## 必备原料和工具 +- 大蒜 +- 大葱 +- 青辣椒 +- 洋葱 +- 西红柿 +- 青茄子 +- 盐 +- 酱油 +- 鸡蛋 +- 面粉 +- 淀粉 + +## 计算 +每次制作前需要确定计划做几份。一份正好够 2 个人食用 + +## 操作 +1. 青茄子、青辣椒、西红柿、洋葱、大葱洗净。 +2. 大葱切 5 毫米宽的葱花,大蒜扒皮并拍碎,西红柿切 6 立方厘米的块。 +3. 茄子切菱形块。 +4. 将面粉倒入盆中,依次加入少量水,搅拌均匀,呈粘稠糊状。 +5. 热锅,放入茄块翻炒至金黄色。 +""" + + print("=== 测试单个菜谱解析 ===") + + # 加载配置 + config = load_config() + api_key = config["kimi"].get("api_key") + if not api_key or api_key == "YOUR_KIMI_API_KEY_HERE": + api_key = setup_api_key() + + try: + agent = KimiRecipeAgent(api_key) + recipe_info = agent.extract_recipe_info(test_recipe, "dishes/vegetable_dish/红烧茄子.md") + + print(f"测试成功: {recipe_info.name} ({len(recipe_info.ingredients)}个食材, {len(recipe_info.steps)}个步骤)") + return True + + except Exception as e: + print(f"❌ 测试失败: {str(e)}") + return False + +def main(): + """主函数""" + print("🍳 AI菜谱知识图谱生成器") + print("=" * 50) + + # 检查是否为测试模式 + if len(sys.argv) > 1 and sys.argv[1] == "test": + success = test_single_recipe() + sys.exit(0 if success else 1) + + # 加载配置 + config = load_config() + + # 设置API密钥 + api_key = config["kimi"].get("api_key") + if not api_key or api_key == "YOUR_KIMI_API_KEY_HERE": + api_key = setup_api_key() + + # 获取菜谱目录 + recipe_dir = get_recipe_directory() + + # 确认参数 + print(f"\n配置信息:") + print(f"- API密钥: {api_key[:8]}...") + print(f"- 菜谱目录: {recipe_dir}") + print(f"- 输出格式: {config['output'].get('format', 'neo4j')}") + print(f"- 输出目录: {config['output'].get('directory', './ai_output')}") + + confirm = input("\n确认开始处理? (y/N): ").strip().lower() + if confirm != 'y': + print("取消处理") + return + + try: + # 创建AI agent + print("\n🤖 初始化AI Agent...") + ai_agent = KimiRecipeAgent(api_key, config["kimi"].get("base_url")) + + # 创建知识图谱构建器 + output_dir = config["output"].get("directory", "./ai_output") + batch_size = config.get("processing", {}).get("batch_size", 20) # 默认批次大小为20 + builder = RecipeKnowledgeGraphBuilder(ai_agent, output_dir, batch_size) + + # 批量处理菜谱 + print(f"\n📚 开始处理菜谱目录...") + processed, failed = builder.batch_process_recipes(recipe_dir) + + print(f"处理结果: 成功 {processed} 个,失败 {failed} 个") + + # 导出数据 + output_dir = config["output"].get("directory", "./ai_output") + output_format = config["output"].get("format", "neo4j") + + print(f"导出数据 (格式: {output_format})...") + + if output_format == "neo4j": + builder.export_to_neo4j_csv(output_dir) + print(f"Neo4j文件已生成: {output_dir}") + elif output_format == "rf2": + builder.export_to_rf2_format(output_dir) + print(f"RF2文件已生成: {output_dir}") + else: + builder.export_to_csv(output_dir) + print(f"CSV文件已生成: {output_dir}") + + print("处理完成!") + + except KeyboardInterrupt: + print(f"\n\n⏹️ 用户中断处理") + except Exception as e: + print(f"\n❌ 处理过程中出现错误: {str(e)}") + print(f"请检查API密钥、网络连接和菜谱文件格式") + +def show_help(): + """显示帮助信息""" + help_text = """ +🍳 AI菜谱知识图谱生成器 - 使用指南 + +基本用法: + python run_ai_agent.py [菜谱目录路径] + +测试模式: + python run_ai_agent.py test + +环境变量: + KIMI_API_KEY - Kimi API密钥 + +配置文件: + config.json - 详细配置选项 + +示例: + python run_ai_agent.py ./HowToCook-master + python run_ai_agent.py test + +输出格式: + - neo4j: 生成Neo4j导入格式的CSV文件 + - csv: 生成标准CSV文件 + +更多信息请查看README.md +""" + print(help_text) + +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] in ["-h", "--help", "help"]: + show_help() + else: + main() \ No newline at end of file diff --git a/code/C9/config.py b/code/C9/config.py new file mode 100644 index 0000000..7fe96e8 --- /dev/null +++ b/code/C9/config.py @@ -0,0 +1,73 @@ +""" +基于图数据库的RAG系统配置文件 +""" + +from dataclasses import dataclass +from typing import Dict, Any + +@dataclass +class GraphRAGConfig: + """基于图数据库的RAG系统配置类""" + + # Neo4j数据库配置 + neo4j_uri: str = "bolt://localhost:7687" + neo4j_user: str = "neo4j" + neo4j_password: str = "all-in-rag" + neo4j_database: str = "neo4j" + + # Milvus配置 + milvus_host: str = "localhost" + milvus_port: int = 19530 + milvus_collection_name: str = "cooking_knowledge" + milvus_dimension: int = 512 # BGE-small-zh-v1.5的向量维度 + + # 模型配置 + embedding_model: str = "BAAI/bge-small-zh-v1.5" + llm_model: str = "kimi-k2-0711-preview" + + # 检索配置(LightRAG Round-robin策略) + top_k: int = 5 + + # 生成配置 + temperature: float = 0.1 + max_tokens: int = 2048 + + # 图数据处理配置 + chunk_size: int = 500 + chunk_overlap: int = 50 + max_graph_depth: int = 2 # 图遍历最大深度 + + def __post_init__(self): + """初始化后的处理""" + # LightRAG使用Round-robin策略,无需权重验证 + pass + + @classmethod + def from_dict(cls, config_dict: Dict[str, Any]) -> 'GraphRAGConfig': + """从字典创建配置对象""" + return cls(**config_dict) + + def to_dict(self) -> Dict[str, Any]: + """转换为字典""" + return { + 'neo4j_uri': self.neo4j_uri, + 'neo4j_user': self.neo4j_user, + 'neo4j_password': self.neo4j_password, + 'neo4j_database': self.neo4j_database, + 'milvus_host': self.milvus_host, + 'milvus_port': self.milvus_port, + 'milvus_collection_name': self.milvus_collection_name, + 'milvus_dimension': self.milvus_dimension, + 'embedding_model': self.embedding_model, + 'llm_model': self.llm_model, + 'top_k': self.top_k, + + 'temperature': self.temperature, + 'max_tokens': self.max_tokens, + 'chunk_size': self.chunk_size, + 'chunk_overlap': self.chunk_overlap, + 'max_graph_depth': self.max_graph_depth + } + +# 默认配置实例 +DEFAULT_CONFIG = GraphRAGConfig() \ No newline at end of file diff --git a/code/C9/main.py b/code/C9/main.py new file mode 100644 index 0000000..989c47b --- /dev/null +++ b/code/C9/main.py @@ -0,0 +1,441 @@ +""" +基于图RAG的智能烹饪助手 - 主程序 +整合传统检索和图RAG检索,实现真正的图数据优势 +""" + +import os +import sys +import time +import logging +from typing import List, Optional + +# 设置日志 +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + +# 添加当前目录到Python路径 +sys.path.append(os.path.dirname(os.path.abspath(__file__))) + +from dotenv import load_dotenv +from config import DEFAULT_CONFIG, GraphRAGConfig +from rag_modules import ( + GraphDataPreparationModule, + MilvusIndexConstructionModule, + GenerationIntegrationModule +) +from rag_modules.hybrid_retrieval import HybridRetrievalModule +from rag_modules.graph_rag_retrieval import GraphRAGRetrieval +from rag_modules.intelligent_query_router import IntelligentQueryRouter, QueryAnalysis + +# 加载环境变量 +load_dotenv() + +class AdvancedGraphRAGSystem: + """ + 图RAG系统 + + 核心特性: + 1. 智能路由:自动选择最适合的检索策略 + 2. 双引擎检索:传统混合检索 + 图RAG检索 + 3. 图结构推理:多跳遍历、子图提取、关系推理 + 4. 查询复杂度分析:深度理解用户意图 + 5. 自适应学习:基于反馈优化系统性能 + """ + + def __init__(self, config: Optional[GraphRAGConfig] = None): + self.config = config or DEFAULT_CONFIG + + # 核心模块 + self.data_module = None + self.index_module = None + self.generation_module = None + + # 检索引擎 + self.traditional_retrieval = None + self.graph_rag_retrieval = None + self.query_router = None + + # 系统状态 + self.system_ready = False + + def initialize_system(self): + """初始化高级图RAG系统""" + logger.info("启动高级图RAG系统...") + + try: + # 1. 数据准备模块 + print("初始化数据准备模块...") + self.data_module = GraphDataPreparationModule( + uri=self.config.neo4j_uri, + user=self.config.neo4j_user, + password=self.config.neo4j_password, + database=self.config.neo4j_database + ) + + # 2. 向量索引模块 + print("初始化Milvus向量索引...") + self.index_module = MilvusIndexConstructionModule( + host=self.config.milvus_host, + port=self.config.milvus_port, + collection_name=self.config.milvus_collection_name, + dimension=self.config.milvus_dimension, + model_name=self.config.embedding_model + ) + + # 3. 生成模块 + print("初始化生成模块...") + self.generation_module = GenerationIntegrationModule( + model_name=self.config.llm_model, + temperature=self.config.temperature, + max_tokens=self.config.max_tokens + ) + + # 4. 传统混合检索模块 + print("初始化传统混合检索...") + self.traditional_retrieval = HybridRetrievalModule( + config=self.config, + milvus_module=self.index_module, + data_module=self.data_module, + llm_client=self.generation_module.client + ) + + # 5. 图RAG检索模块 + print("初始化图RAG检索引擎...") + self.graph_rag_retrieval = GraphRAGRetrieval( + config=self.config, + llm_client=self.generation_module.client + ) + + # 6. 智能查询路由器 + print("初始化智能查询路由器...") + self.query_router = IntelligentQueryRouter( + traditional_retrieval=self.traditional_retrieval, + graph_rag_retrieval=self.graph_rag_retrieval, + llm_client=self.generation_module.client, + config=self.config + ) + + print("✅ 高级图RAG系统初始化完成!") + + except Exception as e: + logger.error(f"系统初始化失败: {e}") + raise + + def build_knowledge_base(self): + """构建知识库(如果需要)""" + print("\n检查知识库状态...") + + try: + # 检查Milvus集合是否存在 + if self.index_module.has_collection(): + print("✅ 发现已存在的知识库,尝试加载...") + if self.index_module.load_collection(): + print("知识库加载成功!") + + # 重要:即使从已存在的知识库加载,也需要加载图数据以支持图索引 + print("加载图数据以支持图检索...") + self.data_module.load_graph_data() + print("构建菜谱文档...") + self.data_module.build_recipe_documents() + print("进行文档分块...") + chunks = self.data_module.chunk_documents( + chunk_size=self.config.chunk_size, + chunk_overlap=self.config.chunk_overlap + ) + + self._initialize_retrievers(chunks) + return + else: + print("❌ 知识库加载失败,开始重建...") + + print("未找到已存在的集合,开始构建新的知识库...") + + # 从Neo4j加载图数据 + print("从Neo4j加载图数据...") + self.data_module.load_graph_data() + + # 构建菜谱文档 + print("构建菜谱文档...") + self.data_module.build_recipe_documents() + + # 进行文档分块 + print("进行文档分块...") + chunks = self.data_module.chunk_documents( + chunk_size=self.config.chunk_size, + chunk_overlap=self.config.chunk_overlap + ) + + # 构建Milvus向量索引 + print("构建Milvus向量索引...") + if not self.index_module.build_vector_index(chunks): + raise Exception("构建向量索引失败") + + # 初始化检索器 + self._initialize_retrievers(chunks) + + # 显示统计信息 + self._show_knowledge_base_stats() + + print("✅ 知识库构建完成!") + + except Exception as e: + logger.error(f"知识库构建失败: {e}") + raise + + def _initialize_retrievers(self, chunks: List = None): + """初始化检索器""" + print("初始化检索引擎...") + + # 如果没有chunks,从数据模块获取 + if chunks is None: + chunks = self.data_module.chunks or [] + + # 初始化传统检索器 + self.traditional_retrieval.initialize(chunks) + + # 初始化图RAG检索器 + self.graph_rag_retrieval.initialize() + + self.system_ready = True + print("✅ 检索引擎初始化完成!") + + def _show_knowledge_base_stats(self): + """显示知识库统计信息""" + print(f"\n知识库统计:") + + # 数据统计 + stats = self.data_module.get_statistics() + print(f" 菜谱数量: {stats.get('total_recipes', 0)}") + print(f" 食材数量: {stats.get('total_ingredients', 0)}") + print(f" 烹饪步骤: {stats.get('total_cooking_steps', 0)}") + print(f" 文档数量: {stats.get('total_documents', 0)}") + print(f" 文本块数: {stats.get('total_chunks', 0)}") + + # Milvus统计 + milvus_stats = self.index_module.get_collection_stats() + print(f" 向量索引: {milvus_stats.get('row_count', 0)} 条记录") + + # 图RAG统计 + route_stats = self.query_router.get_route_statistics() + print(f" 路由统计: 总查询 {route_stats.get('total_queries', 0)} 次") + + if stats.get('categories'): + categories = list(stats['categories'].keys())[:10] + print(f" 🏷️ 主要分类: {', '.join(categories)}") + + def ask_question_with_routing(self, question: str, stream: bool = False, explain_routing: bool = False): + """ + 智能问答:自动选择最佳检索策略 + """ + if not self.system_ready: + raise ValueError("系统未就绪,请先构建知识库") + + print(f"\n❓ 用户问题: {question}") + + # 显示路由决策解释(可选) + if explain_routing: + explanation = self.query_router.explain_routing_decision(question) + print(explanation) + + start_time = time.time() + + try: + # 1. 智能路由检索 + print("执行智能查询路由...") + relevant_docs, analysis = self.query_router.route_query(question, self.config.top_k) + + # 2. 显示路由信息 + strategy_icons = { + "hybrid_traditional": "🔍", + "graph_rag": "🕸️", + "combined": "🔄" + } + strategy_icon = strategy_icons.get(analysis.recommended_strategy.value, "❓") + print(f"{strategy_icon} 使用策略: {analysis.recommended_strategy.value}") + print(f"📊 复杂度: {analysis.query_complexity:.2f}, 关系密集度: {analysis.relationship_intensity:.2f}") + + # 3. 显示检索结果信息 + if relevant_docs: + doc_info = [] + for doc in relevant_docs: + recipe_name = doc.metadata.get('recipe_name', '未知内容') + search_type = doc.metadata.get('search_type', doc.metadata.get('route_strategy', 'unknown')) + score = doc.metadata.get('final_score', doc.metadata.get('relevance_score', 0)) + doc_info.append(f"{recipe_name}({search_type}, {score:.3f})") + + print(f"📋 找到 {len(relevant_docs)} 个相关文档: {', '.join(doc_info[:3])}") + if len(doc_info) > 3: + print(f" 等 {len(relevant_docs)} 个结果...") + else: + # 保持返回值签名一致:始终返回 (result, analysis) + return "抱歉,没有找到相关的烹饪信息。请尝试其他问题。", analysis + + # 4. 生成回答 + print("🎯 智能生成回答...") + + if stream: + try: + for chunk_text in self.generation_module.generate_adaptive_answer_stream(question, relevant_docs): + print(chunk_text, end="", flush=True) + print("\n") + result = "流式输出完成" + except Exception as stream_error: + logger.error(f"流式输出过程中出现错误: {stream_error}") + print(f"\n⚠️ 流式输出中断,切换到标准模式...") + # 使用非流式作为后备 + result = self.generation_module.generate_adaptive_answer(question, relevant_docs) + else: + result = self.generation_module.generate_adaptive_answer(question, relevant_docs) + + # 5. 性能统计 + end_time = time.time() + print(f"\n⏱️ 问答完成,耗时: {end_time - start_time:.2f}秒") + + return result, analysis + + except Exception as e: + logger.error(f"问答处理失败: {e}") + return f"抱歉,处理问题时出现错误:{str(e)}", None + + + + + + def run_interactive(self): + """运行交互式问答""" + if not self.system_ready: + print("❌ 系统未就绪,请先构建知识库") + return + + print("\n欢迎使用尝尝咸淡RAG烹饪助手!") + print("可用功能:") + print(" - 'stats' : 查看系统统计") + print(" - 'rebuild' : 重建知识库") + print(" - 'quit' : 退出系统") + print("\n" + "="*50) + + while True: + try: + user_input = input("\n您的问题: ").strip() + + if not user_input: + continue + + if user_input.lower() == 'quit': + break + elif user_input.lower() == 'stats': + self._show_system_stats() + continue + elif user_input.lower() == 'rebuild': + self._rebuild_knowledge_base() + continue + + # 普通问答 - 使用默认设置 + use_stream = True # 默认使用流式输出 + explain_routing = False # 默认不显示路由决策 + + print("\n回答:") + + result, analysis = self.ask_question_with_routing( + user_input, + stream=use_stream, + explain_routing=explain_routing + ) + + if not use_stream and result: + print(f"{result}\n") + + except KeyboardInterrupt: + break + except Exception as e: + print(f"处理问题时出错: {e}") + import traceback + traceback.print_exc() + + print("\n👋 感谢使用尝尝咸淡RAG烹饪助手!") + self._cleanup() + + def _show_system_stats(self): + """显示系统统计信息""" + print("\n系统运行统计") + print("=" * 40) + + # 路由统计 + route_stats = self.query_router.get_route_statistics() + total_queries = route_stats.get('total_queries', 0) + + if total_queries > 0: + print(f"总查询次数: {total_queries}") + print(f"传统检索: {route_stats.get('traditional_count', 0)} ({route_stats.get('traditional_ratio', 0):.1%})") + print(f"图RAG检索: {route_stats.get('graph_rag_count', 0)} ({route_stats.get('graph_rag_ratio', 0):.1%})") + print(f"组合策略: {route_stats.get('combined_count', 0)} ({route_stats.get('combined_ratio', 0):.1%})") + else: + print("暂无查询记录") + + # 知识库统计 + self._show_knowledge_base_stats() + + def _rebuild_knowledge_base(self): + """重建知识库""" + print("\n准备重建知识库...") + + # 确认操作 + confirm = input("⚠️ 这将删除现有的向量数据并重新构建,是否继续?(y/N): ").strip().lower() + if confirm != 'y': + print("❌ 重建操作已取消") + return + + try: + print("删除现有的Milvus集合...") + if self.index_module.delete_collection(): + print("✅ 现有集合已删除") + else: + print("删除集合时出现问题,继续重建...") + + # 重新构建知识库 + print("开始重建知识库...") + self.build_knowledge_base() + + print("✅ 知识库重建完成!") + + except Exception as e: + logger.error(f"重建知识库失败: {e}") + print(f"❌ 重建失败: {e}") + print("建议:请检查Milvus服务状态后重试") + + def _cleanup(self): + """清理资源""" + if self.data_module: + self.data_module.close() + if self.traditional_retrieval: + self.traditional_retrieval.close() + if self.graph_rag_retrieval: + self.graph_rag_retrieval.close() + if self.index_module: + self.index_module.close() + +def main(): + """主函数""" + try: + print("启动高级图RAG系统...") + + # 创建高级图RAG系统 + rag_system = AdvancedGraphRAGSystem() + + # 初始化系统 + rag_system.initialize_system() + + # 构建知识库 + rag_system.build_knowledge_base() + + # 运行交互式问答 + rag_system.run_interactive() + + except Exception as e: + logger.error(f"系统运行失败: {e}") + import traceback + traceback.print_exc() + print(f"\n❌ 系统错误: {e}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/code/C9/rag_modules/__init__.py b/code/C9/rag_modules/__init__.py new file mode 100644 index 0000000..7dcc5e6 --- /dev/null +++ b/code/C9/rag_modules/__init__.py @@ -0,0 +1,15 @@ +""" +基于图数据库的RAG模块包 +""" + +from .graph_data_preparation import GraphDataPreparationModule +from .milvus_index_construction import MilvusIndexConstructionModule +from .hybrid_retrieval import HybridRetrievalModule +from .generation_integration import GenerationIntegrationModule + +__all__ = [ + 'GraphDataPreparationModule', + 'MilvusIndexConstructionModule', + 'HybridRetrievalModule', + 'GenerationIntegrationModule' +] \ No newline at end of file diff --git a/code/C9/rag_modules/generation_integration.py b/code/C9/rag_modules/generation_integration.py new file mode 100644 index 0000000..89a62f6 --- /dev/null +++ b/code/C9/rag_modules/generation_integration.py @@ -0,0 +1,175 @@ +""" +生成集成模块 +""" + +import logging +import os +import time +from typing import List + +from openai import OpenAI +from langchain_core.documents import Document + +logger = logging.getLogger(__name__) + +class GenerationIntegrationModule: + """生成集成模块 - 负责答案生成""" + + def __init__(self, model_name: str = "kimi-k2-0711-preview", temperature: float = 0.1, max_tokens: int = 2048): + """ + 初始化生成集成模块 + """ + self.model_name = model_name + self.temperature = temperature + self.max_tokens = max_tokens + + # 初始化OpenAI客户端(使用Moonshot API) + api_key = os.getenv("MOONSHOT_API_KEY") + if not api_key: + raise ValueError("请设置 MOONSHOT_API_KEY 环境变量") + + self.client = OpenAI( + api_key=api_key, + base_url="https://api.moonshot.cn/v1" + ) + + logger.info(f"生成模块初始化完成,模型: {model_name}") + + def generate_adaptive_answer(self, question: str, documents: List[Document]) -> str: + """ + 智能统一答案生成 + 自动适应不同类型的查询,无需预先分类 + """ + # 构建上下文 + context_parts = [] + + for doc in documents: + content = doc.page_content.strip() + if content: + # 添加检索层级信息(如果有的话) + level = doc.metadata.get('retrieval_level', '') + if level: + context_parts.append(f"[{level.upper()}] {content}") + else: + context_parts.append(content) + + context = "\n\n".join(context_parts) + + # LightRAG风格的统一提示词 + prompt = f""" + 作为一位专业的烹饪助手,请基于以下信息回答用户的问题。 + + 检索到的相关信息: + {context} + + 用户问题:{question} + + 请提供准确、实用的回答。根据问题的性质: + - 如果是询问多个菜品,请提供清晰的列表 + - 如果是询问具体制作方法,请提供详细步骤 + - 如果是一般性咨询,请提供综合性回答 + + 回答: + """ + + try: + response = self.client.chat.completions.create( + model=self.model_name, + messages=[ + {"role": "user", "content": prompt} + ], + temperature=self.temperature, + max_tokens=self.max_tokens + ) + + return response.choices[0].message.content.strip() + + except Exception as e: + logger.error(f"LightRAG答案生成失败: {e}") + return f"抱歉,生成回答时出现错误:{str(e)}" + + def generate_adaptive_answer_stream(self, question: str, documents: List[Document], max_retries: int = 3): + """ + LightRAG风格的流式答案生成(带重试机制) + """ + # 构建上下文 + context_parts = [] + + for doc in documents: + content = doc.page_content.strip() + if content: + level = doc.metadata.get('retrieval_level', '') + if level: + context_parts.append(f"[{level.upper()}] {content}") + else: + context_parts.append(content) + + context = "\n\n".join(context_parts) + + # LightRAG风格的统一提示词 + prompt = f""" + 作为一位专业的烹饪助手,请基于以下信息回答用户的问题。 + + 检索到的相关信息: + {context} + + 用户问题:{question} + + 请提供准确、实用的回答。根据问题的性质: + - 如果是询问多个菜品,请提供清晰的列表 + - 如果是询问具体制作方法,请提供详细步骤 + - 如果是一般性咨询,请提供综合性回答 + + 回答: + """ + + for attempt in range(max_retries): + try: + response = self.client.chat.completions.create( + model=self.model_name, + messages=[ + {"role": "user", "content": prompt} + ], + temperature=self.temperature, + max_tokens=self.max_tokens, + stream=True, + timeout=60 # 增加超时设置 + ) + + if attempt == 0: + print("开始流式生成回答...\n") + else: + print(f"第{attempt + 1}次尝试流式生成...\n") + + full_response = "" + for chunk in response: + if chunk.choices[0].delta.content: + content = chunk.choices[0].delta.content + full_response += content + yield content # 使用yield返回流式内容 + + # 如果成功完成,退出重试循环 + return + + except Exception as e: + logger.warning(f"流式生成第{attempt + 1}次尝试失败: {e}") + + if attempt < max_retries - 1: + wait_time = (attempt + 1) * 2 # 递增等待时间 + print(f"⚠️ 连接中断,{wait_time}秒后重试...") + time.sleep(wait_time) + continue + else: + # 所有重试都失败,使用非流式作为后备 + logger.error(f"流式生成完全失败,尝试非流式后备方案") + print("⚠️ 流式生成失败,切换到标准模式...") + + try: + fallback_response = self.generate_adaptive_answer(question, documents) + yield fallback_response + return + except Exception as fallback_error: + logger.error(f"后备生成也失败: {fallback_error}") + error_msg = f"抱歉,生成回答时出现网络错误,请稍后重试。错误信息:{str(e)}" + yield error_msg + return \ No newline at end of file diff --git a/code/C9/rag_modules/graph_data_preparation.py b/code/C9/rag_modules/graph_data_preparation.py new file mode 100644 index 0000000..9deaf2f --- /dev/null +++ b/code/C9/rag_modules/graph_data_preparation.py @@ -0,0 +1,458 @@ +""" +图数据库数据准备模块 +""" + +import logging +import json +from typing import List, Dict, Any, Optional +from dataclasses import dataclass + +from neo4j import GraphDatabase +from langchain_core.documents import Document + +logger = logging.getLogger(__name__) + +@dataclass +class GraphNode: + """图节点数据结构""" + node_id: str + labels: List[str] + name: str + properties: Dict[str, Any] + +@dataclass +class GraphRelation: + """图关系数据结构""" + start_node_id: str + end_node_id: str + relation_type: str + properties: Dict[str, Any] + +class GraphDataPreparationModule: + """图数据库数据准备模块 - 从Neo4j读取数据并转换为文档""" + + def __init__(self, uri: str, user: str, password: str, database: str = "neo4j"): + """ + 初始化图数据库连接 + + Args: + uri: Neo4j连接URI + user: 用户名 + password: 密码 + database: 数据库名称 + """ + self.uri = uri + self.user = user + self.password = password + self.database = database + self.driver = None + self.documents: List[Document] = [] + self.chunks: List[Document] = [] + self.recipes: List[GraphNode] = [] + self.ingredients: List[GraphNode] = [] + self.cooking_steps: List[GraphNode] = [] + + self._connect() + + def _connect(self): + """建立Neo4j连接""" + try: + self.driver = GraphDatabase.driver( + self.uri, + auth=(self.user, self.password), + database=self.database + ) + logger.info(f"已连接到Neo4j数据库: {self.uri}") + + # 测试连接 + with self.driver.session() as session: + result = session.run("RETURN 1 as test") + test_result = result.single() + if test_result: + logger.info("Neo4j连接测试成功") + + except Exception as e: + logger.error(f"连接Neo4j失败: {e}") + raise + + def close(self): + """关闭数据库连接""" + if hasattr(self, 'driver') and self.driver: + self.driver.close() + logger.info("Neo4j连接已关闭") + + def load_graph_data(self) -> Dict[str, Any]: + """ + 从Neo4j加载图数据 + + Returns: + 包含节点和关系的数据字典 + """ + logger.info("正在从Neo4j加载图数据...") + + with self.driver.session() as session: + # 加载所有菜谱节点,从Category关系中读取分类信息 + recipes_query = """ + MATCH (r:Recipe) + WHERE r.nodeId >= '200000000' + OPTIONAL MATCH (r)-[:BELONGS_TO_CATEGORY]->(c:Category) + WITH r, collect(c.name) as categories + RETURN r.nodeId as nodeId, labels(r) as labels, r.name as name, + properties(r) as originalProperties, + CASE WHEN size(categories) > 0 + THEN categories[0] + ELSE COALESCE(r.category, '未知') END as mainCategory, + CASE WHEN size(categories) > 0 + THEN categories + ELSE [COALESCE(r.category, '未知')] END as allCategories + ORDER BY r.nodeId + """ + + result = session.run(recipes_query) + self.recipes = [] + for record in result: + # 合并原始属性和新的分类信息 + properties = dict(record["originalProperties"]) + properties["category"] = record["mainCategory"] + properties["all_categories"] = record["allCategories"] + + node = GraphNode( + node_id=record["nodeId"], + labels=record["labels"], + name=record["name"], + properties=properties + ) + self.recipes.append(node) + + logger.info(f"加载了 {len(self.recipes)} 个菜谱节点") + + # 加载所有食材节点 + ingredients_query = """ + MATCH (i:Ingredient) + WHERE i.nodeId >= '200000000' + RETURN i.nodeId as nodeId, labels(i) as labels, i.name as name, + properties(i) as properties + ORDER BY i.nodeId + """ + + result = session.run(ingredients_query) + self.ingredients = [] + for record in result: + node = GraphNode( + node_id=record["nodeId"], + labels=record["labels"], + name=record["name"], + properties=record["properties"] + ) + self.ingredients.append(node) + + logger.info(f"加载了 {len(self.ingredients)} 个食材节点") + + # 加载所有烹饪步骤节点 + steps_query = """ + MATCH (s:CookingStep) + WHERE s.nodeId >= '200000000' + RETURN s.nodeId as nodeId, labels(s) as labels, s.name as name, + properties(s) as properties + ORDER BY s.nodeId + """ + + result = session.run(steps_query) + self.cooking_steps = [] + for record in result: + node = GraphNode( + node_id=record["nodeId"], + labels=record["labels"], + name=record["name"], + properties=record["properties"] + ) + self.cooking_steps.append(node) + + logger.info(f"加载了 {len(self.cooking_steps)} 个烹饪步骤节点") + + return { + 'recipes': len(self.recipes), + 'ingredients': len(self.ingredients), + 'cooking_steps': len(self.cooking_steps) + } + + def build_recipe_documents(self) -> List[Document]: + """ + 构建菜谱文档,集成相关的食材和步骤信息 + + Returns: + 结构化的菜谱文档列表 + """ + logger.info("正在构建菜谱文档...") + + documents = [] + + with self.driver.session() as session: + for recipe in self.recipes: + try: + recipe_id = recipe.node_id + recipe_name = recipe.name + + # 获取菜谱的相关食材 + ingredients_query = """ + MATCH (r:Recipe {nodeId: $recipe_id})-[req:REQUIRES]->(i:Ingredient) + RETURN i.name as name, i.category as category, + req.amount as amount, req.unit as unit, + i.description as description + ORDER BY i.name + """ + + ingredients_result = session.run(ingredients_query, {"recipe_id": recipe_id}) + ingredients_info = [] + for ing_record in ingredients_result: + amount = ing_record.get("amount", "") + unit = ing_record.get("unit", "") + ingredient_text = f"{ing_record['name']}" + if amount and unit: + ingredient_text += f"({amount}{unit})" + if ing_record.get("description"): + ingredient_text += f" - {ing_record['description']}" + ingredients_info.append(ingredient_text) + + # 获取菜谱的烹饪步骤 + steps_query = """ + MATCH (r:Recipe {nodeId: $recipe_id})-[c:CONTAINS_STEP]->(s:CookingStep) + RETURN s.name as name, s.description as description, + s.stepNumber as stepNumber, s.methods as methods, + s.tools as tools, s.timeEstimate as timeEstimate, + c.stepOrder as stepOrder + ORDER BY COALESCE(c.stepOrder, s.stepNumber, 999) + """ + + steps_result = session.run(steps_query, {"recipe_id": recipe_id}) + steps_info = [] + for step_record in steps_result: + step_text = f"步骤: {step_record['name']}" + if step_record.get("description"): + step_text += f"\n描述: {step_record['description']}" + if step_record.get("methods"): + step_text += f"\n方法: {step_record['methods']}" + if step_record.get("tools"): + step_text += f"\n工具: {step_record['tools']}" + if step_record.get("timeEstimate"): + step_text += f"\n时间: {step_record['timeEstimate']}" + steps_info.append(step_text) + + # 构建完整的菜谱文档内容 + content_parts = [f"# {recipe_name}"] + + # 添加菜谱基本信息 + if recipe.properties.get("description"): + content_parts.append(f"\n## 菜品描述\n{recipe.properties['description']}") + + if recipe.properties.get("cuisineType"): + content_parts.append(f"\n菜系: {recipe.properties['cuisineType']}") + + if recipe.properties.get("difficulty"): + content_parts.append(f"难度: {recipe.properties['difficulty']}星") + + if recipe.properties.get("prepTime") or recipe.properties.get("cookTime"): + time_info = [] + if recipe.properties.get("prepTime"): + time_info.append(f"准备时间: {recipe.properties['prepTime']}") + if recipe.properties.get("cookTime"): + time_info.append(f"烹饪时间: {recipe.properties['cookTime']}") + content_parts.append(f"\n时间信息: {', '.join(time_info)}") + + if recipe.properties.get("servings"): + content_parts.append(f"份量: {recipe.properties['servings']}") + + # 添加食材信息 + if ingredients_info: + content_parts.append("\n## 所需食材") + for i, ingredient in enumerate(ingredients_info, 1): + content_parts.append(f"{i}. {ingredient}") + + # 添加步骤信息 + if steps_info: + content_parts.append("\n## 制作步骤") + for i, step in enumerate(steps_info, 1): + content_parts.append(f"\n### 第{i}步\n{step}") + + # 添加标签信息 + if recipe.properties.get("tags"): + content_parts.append(f"\n## 标签\n{recipe.properties['tags']}") + + # 组合成最终内容 + full_content = "\n".join(content_parts) + + # 创建文档对象 + doc = Document( + page_content=full_content, + metadata={ + "node_id": recipe_id, + "recipe_name": recipe_name, + "node_type": "Recipe", + "category": recipe.properties.get("category", "未知"), + "cuisine_type": recipe.properties.get("cuisineType", "未知"), + "difficulty": recipe.properties.get("difficulty", 0), + "prep_time": recipe.properties.get("prepTime", ""), + "cook_time": recipe.properties.get("cookTime", ""), + "servings": recipe.properties.get("servings", ""), + "ingredients_count": len(ingredients_info), + "steps_count": len(steps_info), + "doc_type": "recipe", + "content_length": len(full_content) + } + ) + + documents.append(doc) + + except Exception as e: + logger.warning(f"构建菜谱文档失败 {recipe_name} (ID: {recipe_id}): {e}") + continue + + self.documents = documents + logger.info(f"成功构建 {len(documents)} 个菜谱文档") + return documents + + def chunk_documents(self, chunk_size: int = 500, chunk_overlap: int = 50) -> List[Document]: + """ + 对文档进行分块处理 + + Args: + chunk_size: 分块大小 + chunk_overlap: 重叠大小 + + Returns: + 分块后的文档列表 + """ + logger.info(f"正在进行文档分块,块大小: {chunk_size}, 重叠: {chunk_overlap}") + + if not self.documents: + raise ValueError("请先构建文档") + + chunks = [] + chunk_id = 0 + + for doc in self.documents: + content = doc.page_content + + # 简单的按长度分块 + if len(content) <= chunk_size: + # 内容较短,不需要分块 + chunk = Document( + page_content=content, + metadata={ + **doc.metadata, + "chunk_id": f"{doc.metadata['node_id']}_chunk_{chunk_id}", + "parent_id": doc.metadata["node_id"], + "chunk_index": 0, + "total_chunks": 1, + "chunk_size": len(content), + "doc_type": "chunk" + } + ) + chunks.append(chunk) + chunk_id += 1 + else: + # 按章节分块(基于标题) + sections = content.split('\n## ') + if len(sections) <= 1: + # 没有二级标题,按长度强制分块 + total_chunks = (len(content) - 1) // (chunk_size - chunk_overlap) + 1 + + for i in range(total_chunks): + start = i * (chunk_size - chunk_overlap) + end = min(start + chunk_size, len(content)) + + chunk_content = content[start:end] + + chunk = Document( + page_content=chunk_content, + metadata={ + **doc.metadata, + "chunk_id": f"{doc.metadata['node_id']}_chunk_{chunk_id}", + "parent_id": doc.metadata["node_id"], + "chunk_index": i, + "total_chunks": total_chunks, + "chunk_size": len(chunk_content), + "doc_type": "chunk" + } + ) + chunks.append(chunk) + chunk_id += 1 + else: + # 按章节分块 + total_chunks = len(sections) + for i, section in enumerate(sections): + if i == 0: + # 第一个部分包含标题 + chunk_content = section + else: + # 其他部分添加章节标题 + chunk_content = f"## {section}" + + chunk = Document( + page_content=chunk_content, + metadata={ + **doc.metadata, + "chunk_id": f"{doc.metadata['node_id']}_chunk_{chunk_id}", + "parent_id": doc.metadata["node_id"], + "chunk_index": i, + "total_chunks": total_chunks, + "chunk_size": len(chunk_content), + "doc_type": "chunk", + "section_title": section.split('\n')[0] if i > 0 else "主标题" + } + ) + chunks.append(chunk) + chunk_id += 1 + + self.chunks = chunks + logger.info(f"文档分块完成,共生成 {len(chunks)} 个块") + return chunks + + + + def get_statistics(self) -> Dict[str, Any]: + """ + 获取数据统计信息 + + Returns: + 统计信息字典 + """ + stats = { + 'total_recipes': len(self.recipes), + 'total_ingredients': len(self.ingredients), + 'total_cooking_steps': len(self.cooking_steps), + 'total_documents': len(self.documents), + 'total_chunks': len(self.chunks) + } + + if self.documents: + # 分类统计 + categories = {} + cuisines = {} + difficulties = {} + + for doc in self.documents: + category = doc.metadata.get('category', '未知') + categories[category] = categories.get(category, 0) + 1 + + cuisine = doc.metadata.get('cuisine_type', '未知') + cuisines[cuisine] = cuisines.get(cuisine, 0) + 1 + + difficulty = doc.metadata.get('difficulty', 0) + difficulties[str(difficulty)] = difficulties.get(str(difficulty), 0) + 1 + + stats.update({ + 'categories': categories, + 'cuisines': cuisines, + 'difficulties': difficulties, + 'avg_content_length': sum(doc.metadata.get('content_length', 0) for doc in self.documents) / len(self.documents), + 'avg_chunk_size': sum(chunk.metadata.get('chunk_size', 0) for chunk in self.chunks) / len(self.chunks) if self.chunks else 0 + }) + + return stats + + + + def __del__(self): + """析构函数,确保关闭连接""" + self.close() \ No newline at end of file diff --git a/code/C9/rag_modules/graph_indexing.py b/code/C9/rag_modules/graph_indexing.py new file mode 100644 index 0000000..3203706 --- /dev/null +++ b/code/C9/rag_modules/graph_indexing.py @@ -0,0 +1,387 @@ +""" +图索引模块 +实现实体和关系的键值对结构 (K,V) +K: 索引键(简短词汇或短语) +V: 详细描述段落(包含相关文本片段) +""" + +import json +import logging +from typing import Dict, List, Tuple, Any, Optional +from dataclasses import dataclass +from collections import defaultdict + +from langchain_core.documents import Document + +logger = logging.getLogger(__name__) + +@dataclass +class EntityKeyValue: + """实体键值对""" + entity_name: str + index_keys: List[str] # 索引键列表 + value_content: str # 详细描述内容 + entity_type: str # 实体类型 (Recipe, Ingredient, CookingStep) + metadata: Dict[str, Any] + +@dataclass +class RelationKeyValue: + """关系键值对""" + relation_id: str + index_keys: List[str] # 多个索引键(可包含全局主题) + value_content: str # 关系描述内容 + relation_type: str # 关系类型 + source_entity: str # 源实体 + target_entity: str # 目标实体 + metadata: Dict[str, Any] + +class GraphIndexingModule: + """ + 图索引模块 + 核心功能: + 1. 为实体创建键值对(名称作为唯一索引键) + 2. 为关系创建键值对(多个索引键,包含全局主题) + 3. 去重和优化图操作 + 4. 支持增量更新 + """ + + def __init__(self, config, llm_client): + self.config = config + self.llm_client = llm_client + + # 键值对存储 + self.entity_kv_store: Dict[str, EntityKeyValue] = {} + self.relation_kv_store: Dict[str, RelationKeyValue] = {} + + # 索引映射:key -> entity/relation IDs + self.key_to_entities: Dict[str, List[str]] = defaultdict(list) + self.key_to_relations: Dict[str, List[str]] = defaultdict(list) + + def create_entity_key_values(self, recipes: List[Any], ingredients: List[Any], + cooking_steps: List[Any]) -> Dict[str, EntityKeyValue]: + """ + 为实体创建键值对结构 + 每个实体使用其名称作为唯一索引键 + """ + logger.info("开始创建实体键值对...") + + # 处理菜谱实体 + for recipe in recipes: + entity_id = recipe.node_id + entity_name = recipe.name or f"菜谱_{entity_id}" + + # 构建详细内容 + content_parts = [f"菜品名称: {entity_name}"] + + if hasattr(recipe, 'properties'): + props = recipe.properties + if props.get('description'): + content_parts.append(f"描述: {props['description']}") + if props.get('category'): + content_parts.append(f"分类: {props['category']}") + if props.get('cuisineType'): + content_parts.append(f"菜系: {props['cuisineType']}") + if props.get('difficulty'): + content_parts.append(f"难度: {props['difficulty']}") + if props.get('cookingTime'): + content_parts.append(f"制作时间: {props['cookingTime']}") + + # 创建键值对 + entity_kv = EntityKeyValue( + entity_name=entity_name, + index_keys=[entity_name], # 使用名称作为唯一索引键 + value_content='\n'.join(content_parts), + entity_type="Recipe", + metadata={ + "node_id": entity_id, + "properties": getattr(recipe, 'properties', {}) + } + ) + + self.entity_kv_store[entity_id] = entity_kv + self.key_to_entities[entity_name].append(entity_id) + + # 处理食材实体 + for ingredient in ingredients: + entity_id = ingredient.node_id + entity_name = ingredient.name or f"食材_{entity_id}" + + content_parts = [f"食材名称: {entity_name}"] + + if hasattr(ingredient, 'properties'): + props = ingredient.properties + if props.get('category'): + content_parts.append(f"类别: {props['category']}") + if props.get('nutrition'): + content_parts.append(f"营养信息: {props['nutrition']}") + if props.get('storage'): + content_parts.append(f"储存方式: {props['storage']}") + + entity_kv = EntityKeyValue( + entity_name=entity_name, + index_keys=[entity_name], + value_content='\n'.join(content_parts), + entity_type="Ingredient", + metadata={ + "node_id": entity_id, + "properties": getattr(ingredient, 'properties', {}) + } + ) + + self.entity_kv_store[entity_id] = entity_kv + self.key_to_entities[entity_name].append(entity_id) + + # 处理烹饪步骤实体 + for step in cooking_steps: + entity_id = step.node_id + entity_name = f"步骤_{entity_id}" + + content_parts = [f"烹饪步骤: {entity_name}"] + + if hasattr(step, 'properties'): + props = step.properties + if props.get('description'): + content_parts.append(f"步骤描述: {props['description']}") + if props.get('order'): + content_parts.append(f"步骤顺序: {props['order']}") + if props.get('technique'): + content_parts.append(f"技巧: {props['technique']}") + if props.get('time'): + content_parts.append(f"时间: {props['time']}") + + entity_kv = EntityKeyValue( + entity_name=entity_name, + index_keys=[entity_name], + value_content='\n'.join(content_parts), + entity_type="CookingStep", + metadata={ + "node_id": entity_id, + "properties": getattr(step, 'properties', {}) + } + ) + + self.entity_kv_store[entity_id] = entity_kv + self.key_to_entities[entity_name].append(entity_id) + + logger.info(f"实体键值对创建完成,共 {len(self.entity_kv_store)} 个实体") + return self.entity_kv_store + + def create_relation_key_values(self, relationships: List[Tuple[str, str, str]]) -> Dict[str, RelationKeyValue]: + """ + 为关系创建键值对结构 + 关系可能有多个索引键,包含从LLM增强的全局主题 + """ + logger.info("开始创建关系键值对...") + + for i, (source_id, relation_type, target_id) in enumerate(relationships): + relation_id = f"rel_{i}_{source_id}_{target_id}" + + # 获取源实体和目标实体信息 + source_entity = self.entity_kv_store.get(source_id) + target_entity = self.entity_kv_store.get(target_id) + + if not source_entity or not target_entity: + continue + + # 构建关系描述 + content_parts = [ + f"关系类型: {relation_type}", + f"源实体: {source_entity.entity_name} ({source_entity.entity_type})", + f"目标实体: {target_entity.entity_name} ({target_entity.entity_type})" + ] + + # 生成多个索引键(包含全局主题) + index_keys = self._generate_relation_index_keys( + source_entity, target_entity, relation_type + ) + + # 创建关系键值对 + relation_kv = RelationKeyValue( + relation_id=relation_id, + index_keys=index_keys, + value_content='\n'.join(content_parts), + relation_type=relation_type, + source_entity=source_id, + target_entity=target_id, + metadata={ + "source_name": source_entity.entity_name, + "target_name": target_entity.entity_name, + "created_from_graph": True + } + ) + + self.relation_kv_store[relation_id] = relation_kv + + # 为每个索引键建立映射 + for key in index_keys: + self.key_to_relations[key].append(relation_id) + + logger.info(f"关系键值对创建完成,共 {len(self.relation_kv_store)} 个关系") + return self.relation_kv_store + + def _generate_relation_index_keys(self, source_entity: EntityKeyValue, + target_entity: EntityKeyValue, + relation_type: str) -> List[str]: + """ + 为关系生成多个索引键,包含全局主题 + """ + keys = [relation_type] # 基础关系类型键 + + # 根据关系类型和实体类型生成主题键 + if relation_type == "REQUIRES": + # 菜谱-食材关系的主题键 + keys.extend([ + "食材搭配", + "烹饪原料", + f"{source_entity.entity_name}_食材", + target_entity.entity_name + ]) + elif relation_type == "HAS_STEP": + # 菜谱-步骤关系的主题键 + keys.extend([ + "制作步骤", + "烹饪过程", + f"{source_entity.entity_name}_步骤", + "制作方法" + ]) + elif relation_type == "BELONGS_TO_CATEGORY": + # 分类关系的主题键 + keys.extend([ + "菜品分类", + "美食类别", + target_entity.entity_name + ]) + + # 使用LLM增强关系索引键(可选) + if getattr(self.config, 'enable_llm_relation_keys', False): + enhanced_keys = self._llm_enhance_relation_keys(source_entity, target_entity, relation_type) + keys.extend(enhanced_keys) + + # 去重并返回 + return list(set(keys)) + + def _llm_enhance_relation_keys(self, source_entity: EntityKeyValue, + target_entity: EntityKeyValue, + relation_type: str) -> List[str]: + """ + 使用LLM增强关系索引键,生成全局主题 + """ + prompt = f""" + 分析以下实体关系,生成相关的主题关键词: + + 源实体: {source_entity.entity_name} ({source_entity.entity_type}) + 目标实体: {target_entity.entity_name} ({target_entity.entity_type}) + 关系类型: {relation_type} + + 请生成3-5个相关的主题关键词,用于索引和检索。 + 返回JSON格式:{{"keywords": ["关键词1", "关键词2", "关键词3"]}} + """ + + try: + response = self.llm_client.chat.completions.create( + model=self.config.llm_model, + messages=[{"role": "user", "content": prompt}], + temperature=0.1, + max_tokens=200 + ) + + result = json.loads(response.choices[0].message.content.strip()) + return result.get("keywords", []) + + except Exception as e: + logger.error(f"LLM增强关系索引键失败: {e}") + return [] + + def deduplicate_entities_and_relations(self): + """ + 去重相同的实体和关系,优化图操作 + """ + logger.info("开始去重实体和关系...") + + # 实体去重:基于名称 + name_to_entities = defaultdict(list) + for entity_id, entity_kv in self.entity_kv_store.items(): + name_to_entities[entity_kv.entity_name].append(entity_id) + + # 合并重复实体 + entities_to_remove = [] + for name, entity_ids in name_to_entities.items(): + if len(entity_ids) > 1: + # 保留第一个,合并其他的内容 + primary_id = entity_ids[0] + primary_entity = self.entity_kv_store[primary_id] + + for entity_id in entity_ids[1:]: + duplicate_entity = self.entity_kv_store[entity_id] + # 合并内容 + primary_entity.value_content += f"\n\n补充信息: {duplicate_entity.value_content}" + # 标记删除 + entities_to_remove.append(entity_id) + + # 删除重复实体 + for entity_id in entities_to_remove: + del self.entity_kv_store[entity_id] + + # 关系去重:基于源-目标-类型 + relation_signature_to_ids = defaultdict(list) + for relation_id, relation_kv in self.relation_kv_store.items(): + signature = f"{relation_kv.source_entity}_{relation_kv.target_entity}_{relation_kv.relation_type}" + relation_signature_to_ids[signature].append(relation_id) + + # 合并重复关系 + relations_to_remove = [] + for signature, relation_ids in relation_signature_to_ids.items(): + if len(relation_ids) > 1: + # 保留第一个,删除其他 + for relation_id in relation_ids[1:]: + relations_to_remove.append(relation_id) + + # 删除重复关系 + for relation_id in relations_to_remove: + del self.relation_kv_store[relation_id] + + # 重建索引映射 + self._rebuild_key_mappings() + + logger.info(f"去重完成 - 删除了 {len(entities_to_remove)} 个重复实体,{len(relations_to_remove)} 个重复关系") + + def _rebuild_key_mappings(self): + """重建键到实体/关系的映射""" + self.key_to_entities.clear() + self.key_to_relations.clear() + + # 重建实体映射 + for entity_id, entity_kv in self.entity_kv_store.items(): + for key in entity_kv.index_keys: + self.key_to_entities[key].append(entity_id) + + # 重建关系映射 + for relation_id, relation_kv in self.relation_kv_store.items(): + for key in relation_kv.index_keys: + self.key_to_relations[key].append(relation_id) + + def get_entities_by_key(self, key: str) -> List[EntityKeyValue]: + """根据索引键获取实体""" + entity_ids = self.key_to_entities.get(key, []) + return [self.entity_kv_store[eid] for eid in entity_ids if eid in self.entity_kv_store] + + def get_relations_by_key(self, key: str) -> List[RelationKeyValue]: + """根据索引键获取关系""" + relation_ids = self.key_to_relations.get(key, []) + return [self.relation_kv_store[rid] for rid in relation_ids if rid in self.relation_kv_store] + + + + def get_statistics(self) -> Dict[str, Any]: + """获取键值对存储统计信息""" + return { + "total_entities": len(self.entity_kv_store), + "total_relations": len(self.relation_kv_store), + "total_entity_keys": sum(len(kv.index_keys) for kv in self.entity_kv_store.values()), + "total_relation_keys": sum(len(kv.index_keys) for kv in self.relation_kv_store.values()), + "entity_types": { + "Recipe": len([kv for kv in self.entity_kv_store.values() if kv.entity_type == "Recipe"]), + "Ingredient": len([kv for kv in self.entity_kv_store.values() if kv.entity_type == "Ingredient"]), + "CookingStep": len([kv for kv in self.entity_kv_store.values() if kv.entity_type == "CookingStep"]) + } + } \ No newline at end of file diff --git a/code/C9/rag_modules/graph_rag_retrieval.py b/code/C9/rag_modules/graph_rag_retrieval.py new file mode 100644 index 0000000..3d66941 --- /dev/null +++ b/code/C9/rag_modules/graph_rag_retrieval.py @@ -0,0 +1,701 @@ +""" +真正的图RAG检索模块 +基于图结构的知识推理和检索,而非简单的关键词匹配 +""" + +import json +import logging +from collections import defaultdict, deque +from typing import List, Dict, Tuple, Any, Optional, Set +from dataclasses import dataclass +from enum import Enum + +from langchain_core.documents import Document +from neo4j import GraphDatabase + +logger = logging.getLogger(__name__) + +class QueryType(Enum): + """查询类型枚举""" + ENTITY_RELATION = "entity_relation" # 实体关系查询:A和B有什么关系? + MULTI_HOP = "multi_hop" # 多跳查询:A通过什么连接到C? + SUBGRAPH = "subgraph" # 子图查询:A相关的所有信息 + PATH_FINDING = "path_finding" # 路径查找:从A到B的最佳路径 + CLUSTERING = "clustering" # 聚类查询:和A相似的都有什么? + +@dataclass +class GraphQuery: + """图查询结构""" + query_type: QueryType + source_entities: List[str] + target_entities: List[str] = None + relation_types: List[str] = None + max_depth: int = 2 + max_nodes: int = 50 + constraints: Dict[str, Any] = None + +@dataclass +class GraphPath: + """图路径结构""" + nodes: List[Dict[str, Any]] + relationships: List[Dict[str, Any]] + path_length: int + relevance_score: float + path_type: str + +@dataclass +class KnowledgeSubgraph: + """知识子图结构""" + central_nodes: List[Dict[str, Any]] + connected_nodes: List[Dict[str, Any]] + relationships: List[Dict[str, Any]] + graph_metrics: Dict[str, float] + reasoning_chains: List[List[str]] + +class GraphRAGRetrieval: + """ + 真正的图RAG检索系统 + 核心特点: + 1. 查询意图理解:识别图查询模式 + 2. 多跳图遍历:深度关系探索 + 3. 子图提取:相关知识网络 + 4. 图结构推理:基于拓扑的推理 + 5. 动态查询规划:自适应遍历策略 + """ + + def __init__(self, config, llm_client): + self.config = config + self.llm_client = llm_client + self.driver = None + + # 图结构缓存 + self.entity_cache = {} + self.relation_cache = {} + self.subgraph_cache = {} + + def initialize(self): + """初始化图RAG检索系统""" + logger.info("初始化图RAG检索系统...") + + # 连接Neo4j + try: + self.driver = GraphDatabase.driver( + self.config.neo4j_uri, + auth=(self.config.neo4j_user, self.config.neo4j_password) + ) + # 测试连接 + with self.driver.session() as session: + session.run("RETURN 1") + logger.info("Neo4j连接成功") + except Exception as e: + logger.error(f"Neo4j连接失败: {e}") + return + + # 预热:构建实体和关系索引 + self._build_graph_index() + + def _build_graph_index(self): + """构建图索引以加速查询""" + logger.info("构建图结构索引...") + + try: + with self.driver.session() as session: + # 构建实体索引 - 修复Neo4j语法兼容性问题 + entity_query = """ + MATCH (n) + WHERE n.nodeId IS NOT NULL + WITH n, COUNT { (n)--() } as degree + RETURN labels(n) as node_labels, n.nodeId as node_id, + n.name as name, n.category as category, degree + ORDER BY degree DESC + LIMIT 1000 + """ + + result = session.run(entity_query) + for record in result: + node_id = record["node_id"] + self.entity_cache[node_id] = { + "labels": record["node_labels"], + "name": record["name"], + "category": record["category"], + "degree": record["degree"] + } + + # 构建关系类型索引 + relation_query = """ + MATCH ()-[r]->() + RETURN type(r) as rel_type, count(r) as frequency + ORDER BY frequency DESC + """ + + result = session.run(relation_query) + for record in result: + rel_type = record["rel_type"] + self.relation_cache[rel_type] = record["frequency"] + + logger.info(f"索引构建完成: {len(self.entity_cache)}个实体, {len(self.relation_cache)}个关系类型") + + except Exception as e: + logger.error(f"构建图索引失败: {e}") + + def understand_graph_query(self, query: str) -> GraphQuery: + """ + 理解查询的图结构意图 + 这是图RAG的核心:从自然语言到图查询的转换 + """ + prompt = f""" + 作为图数据库专家,分析以下查询的图结构意图,并将自然语言问题映射到**已有图结构**上。 + + 已知图中大致有以下节点和关系: + - 节点类型: + - Recipe:菜谱节点,包含 name、description、cuisineType(如"川菜")、category、tags、prepTime、cookTime 等属性 + - Ingredient:食材节点,包含 name、category(如"蔬菜"、"蛋白质" 等) + - Category:菜品分类(如"川菜"、"家常菜"、"素菜") + - CookingStep:烹饪步骤 + - 主要关系: + - (Recipe)-[:REQUIRES]->(Ingredient) + - (Recipe)-[:BELONGS_TO_CATEGORY]->(Category) + - (Recipe)-[:CONTAINS_STEP]->(CookingStep) + + 请根据上述图结构分析下面的查询: + + 查询:{query} + + 请识别: + 1. 查询类型: + - entity_relation: 询问实体间的直接关系(如:鸡肉和胡萝卜能一起做菜吗?) + - multi_hop: 需要多跳推理(如:鸡肉配什么蔬菜?需要:鸡肉→菜品→食材→蔬菜) + - subgraph: 需要完整子图(如:川菜有什么特色?需要川菜相关的完整知识网络) + - path_finding: 路径查找(如:从食材到成品菜的制作路径) + - clustering: 聚类相似性(如:和宫保鸡丁类似的菜有哪些?) + + 2. source_entities: + - 只包含在图中**很有可能有对应节点**的具体实体名称 + - 优先选择:菜系(如"川菜")、具体菜名(如"宫保鸡丁")、食材名(如"鸡肉"、"豆腐") + - 不要把抽象概念或约束(如"糖尿病饮食限制"、"具体川菜菜品"、"健康饮食"、"30分钟内")放进 source_entities + + 3. target_entities: + - 只在确实需要限制「路径终点」时填写 + - 同样只能使用可能出现在 Recipe / Ingredient / Category 节点上的名称(如"蔬菜"、"素菜"、具体菜名) + - 如果不确定目标实体怎么映射到图中,请返回空列表 [] + + 4. relation_types:本次推理中希望优先考虑的关系类型列表 + - 例如:["REQUIRES", "BELONGS_TO_CATEGORY"] + + 5. max_depth:建议的图遍历深度(1-3 之间的整数) + + 6. constraints:可选的**属性级约束**,用于表达图结构之外的过滤条件,例如: + - 健康/饮食限制(如"糖尿病"、"低糖") + - 时间限制(如"30分钟内") + - 口味偏好(如"清淡"、"少油") + 用一个字典描述,例如: + {{ + "health": ["糖尿病", "低糖"], + "time": {{"max_minutes": 30}}, + "style": ["川菜"] + }} + + 示例1: + 查询:"鸡肉配什么蔬菜好?" + 期望分析:这是 multi_hop 查询,需要通过"鸡肉→使用鸡肉的菜品→这些菜品使用的蔬菜"的路径推理。 + + 返回JSON示例: + {{ + "query_type": "multi_hop", + "source_entities": ["鸡肉"], + "target_entities": ["蔬菜"], + "relation_types": ["REQUIRES", "BELONGS_TO_CATEGORY"], + "max_depth": 3, + "constraints": {{}} + }} + + 示例2: + 查询:"适合糖尿病人吃的低糖川菜有哪些,并且制作时间不超过30分钟?" + 期望分析: + - 图中可以直接对应的实体:主要是菜系 "川菜" + - 糖尿病/低糖/30分钟 属于属性级约束,不能当作节点 + - 可以使用 subgraph 或 multi_hop,以 "川菜" 为核心实体,结合属性约束做后续过滤 + + 返回JSON示例: + {{ + "query_type": "subgraph", + "source_entities": ["川菜"], + "target_entities": [], + "relation_types": ["BELONGS_TO_CATEGORY", "REQUIRES"], + "max_depth": 2, + "constraints": {{ + "health": ["糖尿病", "低糖"], + "time": {{"max_minutes": 30}} + }} + }} + + 请严格返回一个合法的 JSON 对象,不要包含任何多余的说明文字。 + """ + + try: + response = self.llm_client.chat.completions.create( + model=self.config.llm_model, + messages=[{"role": "user", "content": prompt}], + temperature=0.1, + max_tokens=1000 + ) + + result = json.loads(response.choices[0].message.content.strip()) + + return GraphQuery( + query_type=QueryType(result.get("query_type", "subgraph")), + source_entities=result.get("source_entities", []), + target_entities=result.get("target_entities", []), + relation_types=result.get("relation_types", []), + max_depth=result.get("max_depth", 2), + max_nodes=50 + ) + + except Exception as e: + logger.error(f"查询意图理解失败: {e}") + # 降级方案:默认子图查询 + return GraphQuery( + query_type=QueryType.SUBGRAPH, + source_entities=[query], + max_depth=2 + ) + + def multi_hop_traversal(self, graph_query: GraphQuery) -> List[GraphPath]: + """ + 多跳图遍历:这是图RAG的核心优势 + 通过图结构发现隐含的知识关联 + """ + logger.info(f"执行多跳遍历: {graph_query.source_entities} -> {graph_query.target_entities}") + + paths = [] + + if not self.driver: + logger.error("Neo4j连接未建立") + return paths + + try: + with self.driver.session() as session: + # 构建多跳遍历查询 + source_entities = graph_query.source_entities + target_keywords = graph_query.target_entities or [] + max_depth = graph_query.max_depth + + # 根据查询类型选择不同的遍历策略 + if graph_query.query_type == QueryType.MULTI_HOP: + # 根据是否有目标关键词动态拼接过滤条件 + target_filter_clause = "" + if target_keywords: + target_filter_clause = """ + AND ANY(kw IN $target_keywords WHERE + (target.name IS NOT NULL AND (toString(target.name) CONTAINS kw OR kw CONTAINS toString(target.name))) OR + (target.category IS NOT NULL AND (toString(target.category) CONTAINS kw OR kw CONTAINS toString(target.category))) + )""" + + cypher_query = f""" + // 多跳推理查询 + UNWIND $source_entities as source_name + MATCH (source) + WHERE source.name CONTAINS source_name OR source.nodeId = source_name + + // 执行多跳遍历 + MATCH path = (source)-[*1..{max_depth}]-(target) + WHERE NOT source = target{target_filter_clause} + + // 计算路径相关性 + WITH path, source, target, + length(path) as path_len, + relationships(path) as rels, + nodes(path) as path_nodes + + // 路径评分:短路径 + 高度数节点 + 关系类型匹配 + WITH path, source, target, path_len, rels, path_nodes, + (1.0 / path_len) + + (REDUCE(s = 0.0, n IN path_nodes | s + COUNT {{ (n)--() }}) / 10.0 / size(path_nodes)) + + (CASE WHEN ANY(r IN rels WHERE type(r) IN $relation_types) THEN 0.3 ELSE 0.0 END) as relevance + + ORDER BY relevance DESC + LIMIT 20 + + RETURN path, source, target, path_len, rels, path_nodes, relevance + """ + + params = { + "source_entities": source_entities, + "relation_types": graph_query.relation_types or [] + } + if target_keywords: + params["target_keywords"] = target_keywords + + result = session.run(cypher_query, params) + + for record in result: + path_data = self._parse_neo4j_path(record) + if path_data: + paths.append(path_data) + + elif graph_query.query_type == QueryType.ENTITY_RELATION: + # 实体间关系查询 + paths.extend(self._find_entity_relations(graph_query, session)) + + elif graph_query.query_type == QueryType.PATH_FINDING: + # 最短路径查找 + paths.extend(self._find_shortest_paths(graph_query, session)) + + except Exception as e: + logger.error(f"多跳遍历失败: {e}") + + logger.info(f"多跳遍历完成,找到 {len(paths)} 条路径") + return paths + + def extract_knowledge_subgraph(self, graph_query: GraphQuery) -> KnowledgeSubgraph: + """ + 提取知识子图:获取实体相关的完整知识网络 + 这体现了图RAG的整体性思维 + """ + logger.info(f"提取知识子图: {graph_query.source_entities}") + + if not self.driver: + logger.error("Neo4j连接未建立") + return self._fallback_subgraph_extraction(graph_query) + + try: + with self.driver.session() as session: + # 简化的子图提取(不依赖APOC) + cypher_query = f""" + // 找到源实体 + UNWIND $source_entities as entity_name + MATCH (source) + WHERE source.name CONTAINS entity_name + OR source.nodeId = entity_name + + // 获取指定深度的邻居 + MATCH (source)-[r*1..{graph_query.max_depth}]-(neighbor) + WITH source, collect(DISTINCT neighbor) as neighbors, + collect(DISTINCT r) as relationships + WHERE size(neighbors) <= $max_nodes + + // 计算图指标 + WITH source, neighbors, relationships, + size(neighbors) as node_count, + size(relationships) as rel_count + + RETURN + source, + neighbors[0..{graph_query.max_nodes}] as nodes, + relationships[0..{graph_query.max_nodes}] as rels, + {{ + node_count: node_count, + relationship_count: rel_count, + density: CASE WHEN node_count > 1 THEN toFloat(rel_count) / (node_count * (node_count - 1) / 2) ELSE 0.0 END + }} as metrics + """ + + result = session.run(cypher_query, { + "source_entities": graph_query.source_entities, + "max_nodes": graph_query.max_nodes + }) + + record = result.single() + if record: + return self._build_knowledge_subgraph(record) + + except Exception as e: + logger.error(f"子图提取失败: {e}") + + # 降级方案:简单邻居查询 + return self._fallback_subgraph_extraction(graph_query) + + def graph_structure_reasoning(self, subgraph: KnowledgeSubgraph, query: str) -> List[str]: + """ + 基于图结构的推理:这是图RAG的智能之处 + 不仅检索信息,还能进行逻辑推理 + """ + reasoning_chains = [] + + try: + # 1. 识别推理模式 + reasoning_patterns = self._identify_reasoning_patterns(subgraph) + + # 2. 构建推理链 + for pattern in reasoning_patterns: + chain = self._build_reasoning_chain(pattern, subgraph) + if chain: + reasoning_chains.append(chain) + + # 3. 验证推理链的可信度 + validated_chains = self._validate_reasoning_chains(reasoning_chains, query) + + logger.info(f"图结构推理完成,生成 {len(validated_chains)} 条推理链") + return validated_chains + + except Exception as e: + logger.error(f"图结构推理失败: {e}") + return [] + + def adaptive_query_planning(self, query: str) -> List[GraphQuery]: + """ + 自适应查询规划:根据查询复杂度动态调整策略 + """ + # 分析查询复杂度 + complexity_score = self._analyze_query_complexity(query) + + query_plans = [] + + if complexity_score < 0.3: + # 简单查询:直接邻居查询 + plan = GraphQuery( + query_type=QueryType.ENTITY_RELATION, + source_entities=[query], + max_depth=1, + max_nodes=20 + ) + query_plans.append(plan) + + elif complexity_score < 0.7: + # 中等复杂度:多跳查询 + plan = GraphQuery( + query_type=QueryType.MULTI_HOP, + source_entities=[query], + max_depth=2, + max_nodes=50 + ) + query_plans.append(plan) + + else: + # 复杂查询:子图提取 + 推理 + plan1 = GraphQuery( + query_type=QueryType.SUBGRAPH, + source_entities=[query], + max_depth=3, + max_nodes=100 + ) + plan2 = GraphQuery( + query_type=QueryType.MULTI_HOP, + source_entities=[query], + max_depth=3, + max_nodes=50 + ) + query_plans.extend([plan1, plan2]) + + return query_plans + + def graph_rag_search(self, query: str, top_k: int = 5) -> List[Document]: + """ + 图RAG主搜索接口:整合所有图RAG能力 + """ + logger.info(f"开始图RAG检索: {query}") + + if not self.driver: + logger.warning("Neo4j连接未建立,返回空结果") + return [] + + # 1. 查询意图理解 + graph_query = self.understand_graph_query(query) + logger.info(f"查询类型: {graph_query.query_type.value}") + + results = [] + + try: + # 2. 根据查询类型执行不同策略 + if graph_query.query_type in [QueryType.MULTI_HOP, QueryType.PATH_FINDING]: + # 多跳遍历 / 路径查找 + paths = self.multi_hop_traversal(graph_query) + results.extend(self._paths_to_documents(paths, query)) + + elif graph_query.query_type in [QueryType.SUBGRAPH, QueryType.CLUSTERING]: + # 子图提取 / 聚类查询:都视为“围绕核心实体的局部知识网络” + subgraph = self.extract_knowledge_subgraph(graph_query) + + # 图结构推理 + reasoning_chains = self.graph_structure_reasoning(subgraph, query) + + results.extend(self._subgraph_to_documents(subgraph, reasoning_chains, query)) + + elif graph_query.query_type == QueryType.ENTITY_RELATION: + # 实体关系查询(可以视为一跳 / 少量跳的路径查询) + paths = self.multi_hop_traversal(graph_query) + results.extend(self._paths_to_documents(paths, query)) + + # 3. 图结构相关性排序 + results = self._rank_by_graph_relevance(results, query) + + logger.info(f"图RAG检索完成,返回 {len(results[:top_k])} 个结果") + return results[:top_k] + + except Exception as e: + logger.error(f"图RAG检索失败: {e}") + return [] + + # ========== 辅助方法 ========== + + def _parse_neo4j_path(self, record) -> Optional[GraphPath]: + """解析Neo4j路径记录""" + try: + path_nodes = [] + for node in record["path_nodes"]: + path_nodes.append({ + "id": node.get("nodeId", ""), + "name": node.get("name", ""), + "labels": list(node.labels), + "properties": dict(node) + }) + + relationships = [] + for rel in record["rels"]: + relationships.append({ + "type": type(rel).__name__, + "properties": dict(rel) + }) + + return GraphPath( + nodes=path_nodes, + relationships=relationships, + path_length=record["path_len"], + relevance_score=record["relevance"], + path_type="multi_hop" + ) + + except Exception as e: + logger.error(f"路径解析失败: {e}") + return None + + def _build_knowledge_subgraph(self, record) -> KnowledgeSubgraph: + """构建知识子图对象""" + try: + central_nodes = [dict(record["source"])] + connected_nodes = [dict(node) for node in record["nodes"]] + relationships = [dict(rel) for rel in record["rels"]] + + return KnowledgeSubgraph( + central_nodes=central_nodes, + connected_nodes=connected_nodes, + relationships=relationships, + graph_metrics=record["metrics"], + reasoning_chains=[] + ) + except Exception as e: + logger.error(f"构建知识子图失败: {e}") + return KnowledgeSubgraph( + central_nodes=[], + connected_nodes=[], + relationships=[], + graph_metrics={}, + reasoning_chains=[] + ) + + def _paths_to_documents(self, paths: List[GraphPath], query: str) -> List[Document]: + """将图路径转换为Document对象""" + documents = [] + + for i, path in enumerate(paths): + # 构建路径描述 + path_desc = self._build_path_description(path) + + doc = Document( + page_content=path_desc, + metadata={ + "search_type": "graph_path", + "path_length": path.path_length, + "relevance_score": path.relevance_score, + "path_type": path.path_type, + "node_count": len(path.nodes), + "relationship_count": len(path.relationships), + "recipe_name": path.nodes[0].get("name", "图结构结果") if path.nodes else "图结构结果" + } + ) + documents.append(doc) + + return documents + + def _subgraph_to_documents(self, subgraph: KnowledgeSubgraph, + reasoning_chains: List[str], query: str) -> List[Document]: + """将知识子图转换为Document对象""" + documents = [] + + # 子图整体描述 + subgraph_desc = self._build_subgraph_description(subgraph) + + doc = Document( + page_content=subgraph_desc, + metadata={ + "search_type": "knowledge_subgraph", + "node_count": len(subgraph.connected_nodes), + "relationship_count": len(subgraph.relationships), + "graph_density": subgraph.graph_metrics.get("density", 0.0), + "reasoning_chains": reasoning_chains, + "recipe_name": subgraph.central_nodes[0].get("name", "知识子图") if subgraph.central_nodes else "知识子图" + } + ) + documents.append(doc) + + return documents + + def _build_path_description(self, path: GraphPath) -> str: + """构建路径的自然语言描述""" + if not path.nodes: + return "空路径" + + desc_parts = [] + for i, node in enumerate(path.nodes): + desc_parts.append(node.get("name", f"节点{i}")) + if i < len(path.relationships): + rel_type = path.relationships[i].get("type", "相关") + desc_parts.append(f" --{rel_type}--> ") + + return "".join(desc_parts) + + def _build_subgraph_description(self, subgraph: KnowledgeSubgraph) -> str: + """构建子图的自然语言描述""" + central_names = [node.get("name", "未知") for node in subgraph.central_nodes] + node_count = len(subgraph.connected_nodes) + rel_count = len(subgraph.relationships) + + return f"关于 {', '.join(central_names)} 的知识网络,包含 {node_count} 个相关概念和 {rel_count} 个关系。" + + def _rank_by_graph_relevance(self, documents: List[Document], query: str) -> List[Document]: + """基于图结构相关性排序""" + return sorted(documents, + key=lambda x: x.metadata.get("relevance_score", 0.0), + reverse=True) + + def _analyze_query_complexity(self, query: str) -> float: + """分析查询复杂度""" + complexity_indicators = ["什么", "如何", "为什么", "哪些", "关系", "影响", "原因"] + score = sum(1 for indicator in complexity_indicators if indicator in query) + return min(score / len(complexity_indicators), 1.0) + + def _identify_reasoning_patterns(self, subgraph: KnowledgeSubgraph) -> List[str]: + """识别推理模式""" + return ["因果关系", "组成关系", "相似关系"] + + def _build_reasoning_chain(self, pattern: str, subgraph: KnowledgeSubgraph) -> Optional[str]: + """构建推理链""" + return f"基于{pattern}的推理链" + + def _validate_reasoning_chains(self, chains: List[str], query: str) -> List[str]: + """验证推理链""" + return chains[:3] + + def _find_entity_relations(self, graph_query: GraphQuery, session) -> List[GraphPath]: + """查找实体间关系""" + return [] + + def _find_shortest_paths(self, graph_query: GraphQuery, session) -> List[GraphPath]: + """查找最短路径""" + return [] + + def _fallback_subgraph_extraction(self, graph_query: GraphQuery) -> KnowledgeSubgraph: + """降级子图提取""" + return KnowledgeSubgraph( + central_nodes=[], + connected_nodes=[], + relationships=[], + graph_metrics={}, + reasoning_chains=[] + ) + + def close(self): + """关闭资源连接""" + if hasattr(self, 'driver') and self.driver: + self.driver.close() + logger.info("图RAG检索系统已关闭") \ No newline at end of file diff --git a/code/C9/rag_modules/hybrid_retrieval.py b/code/C9/rag_modules/hybrid_retrieval.py new file mode 100644 index 0000000..58d102c --- /dev/null +++ b/code/C9/rag_modules/hybrid_retrieval.py @@ -0,0 +1,750 @@ +""" +混合检索模块 +基于双层检索范式:实体级 + 主题级检索 +结合 BM25(jieba 分词)、向量检索与图键值索引,使用 RRF 融合 +""" + +import json +import logging +from typing import List, Dict, Tuple, Any, Optional +from dataclasses import dataclass + +import jieba +from rank_bm25 import BM25Okapi +from langchain_core.documents import Document +from neo4j import GraphDatabase +from .graph_indexing import GraphIndexingModule + +logger = logging.getLogger(__name__) + +# 中文停用词表:助词 / 连词 / 疑问词 / 人称 / 语气词 / 动词修饰 +# 不引第三方停用词包,按烹饪问答场景手挑(覆盖 testset 高频虚词) +_CHINESE_STOPWORDS = set(""" +的 了 和 是 在 我 有 就 不 也 都 还 这 那 一 个 与 及 等 上 下 中 为 以 于 从 把 被 让 使 又 而 但 或 +什么 怎么 如何 哪些 哪个 哪里 谁 多少 几 你 他 她 它 我们 他们 她们 它们 +请问 请 想 要 需要 能 可以 应该 会 啊 呢 吧 嘛 吗 哦 呀 哈 +之 其 此 该 即 各 每 些 种 类 时 后 前 里 外 内 间 已经 正在 一些 一下 +""".split()) + +# RRF 融合的常数 k:Cormack et al. 2009 默认值 +_RRF_K = 60 + +@dataclass +class RetrievalResult: + """检索结果数据结构""" + content: str + node_id: str + node_type: str + relevance_score: float + retrieval_level: str # 'low' or 'high' + metadata: Dict[str, Any] + +class HybridRetrievalModule: + """ + 混合检索模块 + 核心特点: + 1. 双层检索范式(实体级 + 主题级,基于图键值索引) + 2. BM25 关键词检索(jieba 分词 + 停用词过滤) + 3. 向量检索(Milvus)+ 一跳邻居扩展 + 4. RRF (Reciprocal Rank Fusion) 融合三路结果 + """ + + def __init__(self, config, milvus_module, data_module, llm_client): + self.config = config + self.milvus_module = milvus_module + self.data_module = data_module + self.llm_client = llm_client + self.driver = None + + # BM25 索引 + 原始文档(按索引位置对齐) + self.bm25: Optional[BM25Okapi] = None + self.bm25_corpus_docs: List[Document] = [] + + # 图索引模块 + self.graph_indexing = GraphIndexingModule(config, llm_client) + self.graph_indexed = False + + def initialize(self, chunks: List[Document]): + """初始化检索系统""" + logger.info("初始化混合检索模块...") + + # 连接Neo4j + self.driver = GraphDatabase.driver( + self.config.neo4j_uri, + auth=(self.config.neo4j_user, self.config.neo4j_password) + ) + + # 初始化 BM25(jieba 分词 + 中文停用词过滤) + if chunks: + self.bm25_corpus_docs = list(chunks) + tokenized_corpus = [self._tokenize_chinese(d.page_content) for d in chunks] + self.bm25 = BM25Okapi(tokenized_corpus) + avg_tokens = sum(len(t) for t in tokenized_corpus) / max(1, len(tokenized_corpus)) + logger.info( + f"BM25(jieba+stopwords) 索引构建完成,文档数: {len(chunks)}," + f"平均 token 数: {avg_tokens:.1f}" + ) + + # 初始化图索引 + self._build_graph_index() + + @staticmethod + def _tokenize_chinese(text: str) -> List[str]: + """jieba 精确分词 + 停用词 / 空白 / 单字符过滤""" + if not text: + return [] + tokens = jieba.lcut(text) + return [ + t for t in tokens + if t.strip() and t not in _CHINESE_STOPWORDS and not t.isspace() + ] + + def _build_graph_index(self): + """构建图索引""" + if self.graph_indexed: + return + + logger.info("开始构建图索引...") + + try: + # 获取图数据 + recipes = self.data_module.recipes + ingredients = self.data_module.ingredients + cooking_steps = self.data_module.cooking_steps + + # 创建实体键值对 + self.graph_indexing.create_entity_key_values(recipes, ingredients, cooking_steps) + + # 创建关系键值对(这里需要从Neo4j获取关系数据) + relationships = self._extract_relationships_from_graph() + self.graph_indexing.create_relation_key_values(relationships) + + # 去重优化 + self.graph_indexing.deduplicate_entities_and_relations() + + self.graph_indexed = True + stats = self.graph_indexing.get_statistics() + logger.info(f"图索引构建完成: {stats}") + + except Exception as e: + logger.error(f"构建图索引失败: {e}") + + def _extract_relationships_from_graph(self) -> List[Tuple[str, str, str]]: + """从Neo4j图中提取关系""" + relationships = [] + + try: + with self.driver.session() as session: + query = """ + MATCH (source)-[r]->(target) + WHERE source.nodeId >= '200000000' OR target.nodeId >= '200000000' + RETURN source.nodeId as source_id, type(r) as relation_type, target.nodeId as target_id + LIMIT 1000 + """ + result = session.run(query) + + for record in result: + relationships.append(( + record["source_id"], + record["relation_type"], + record["target_id"] + )) + + except Exception as e: + logger.error(f"提取图关系失败: {e}") + + return relationships + + def extract_query_keywords(self, query: str) -> Tuple[List[str], List[str]]: + """ + 提取查询关键词:实体级 + 主题级 + """ + prompt = f""" + 作为烹饪知识助手,请分析以下查询并提取关键词,分为两个层次: + + 查询:{query} + + 提取规则: + 1. 实体级关键词:具体的食材、菜品名称、工具、品牌等有形实体 + - 例如:鸡胸肉、西兰花、红烧肉、平底锅、老干妈 + - 对于抽象查询,推测相关的具体食材/菜品 + + 2. 主题级关键词:抽象概念、烹饪主题、饮食风格、营养特点等 + - 例如:减肥、低热量、川菜、素食、下饭菜、快手菜 + - 排除动作词:推荐、介绍、制作、怎么做等 + + 示例: + 查询:"推荐几个减肥菜" + {{ + "entity_keywords": ["鸡胸肉", "西兰花", "水煮蛋", "胡萝卜", "黄瓜"], + "topic_keywords": ["减肥", "低热量", "高蛋白", "低脂"] + }} + + 查询:"川菜有什么特色" + {{ + "entity_keywords": ["麻婆豆腐", "宫保鸡丁", "水煮鱼", "辣椒", "花椒"], + "topic_keywords": ["川菜", "麻辣", "香辣", "下饭菜"] + }} + + 请严格按照JSON格式返回,不要包含多余的文字: + {{ + "entity_keywords": ["实体1", "实体2", ...], + "topic_keywords": ["主题1", "主题2", ...] + }} + """ + + try: + response = self.llm_client.chat.completions.create( + model=self.config.llm_model, + messages=[{"role": "user", "content": prompt}], + temperature=0.1, + max_tokens=500 + ) + + result = json.loads(response.choices[0].message.content.strip()) + entity_keywords = result.get("entity_keywords", []) + topic_keywords = result.get("topic_keywords", []) + + logger.info(f"关键词提取完成 - 实体级: {entity_keywords}, 主题级: {topic_keywords}") + return entity_keywords, topic_keywords + + except Exception as e: + logger.error(f"关键词提取失败: {e}") + # 降级方案:简单的关键词分割 + keywords = query.split() + return keywords[:3], keywords[3:6] if len(keywords) > 3 else keywords + + def entity_level_retrieval(self, entity_keywords: List[str], top_k: int = 5) -> List[RetrievalResult]: + """ + 实体级检索:专注于具体实体和关系 + 使用图索引的键值对结构进行检索 + """ + results = [] + + # 1. 使用图索引进行实体检索 + for keyword in entity_keywords: + # 检索匹配的实体 + entities = self.graph_indexing.get_entities_by_key(keyword) + + for entity in entities: + # 获取邻居信息 + neighbors = self._get_node_neighbors(entity.metadata["node_id"], max_neighbors=2) + + # 构建增强内容 + enhanced_content = entity.value_content + if neighbors: + enhanced_content += f"\n相关信息: {', '.join(neighbors)}" + + results.append(RetrievalResult( + content=enhanced_content, + node_id=entity.metadata["node_id"], + node_type=entity.entity_type, + relevance_score=0.9, # 精确匹配得分较高 + retrieval_level="entity", + metadata={ + "entity_name": entity.entity_name, + "entity_type": entity.entity_type, + "index_keys": entity.index_keys, + "matched_keyword": keyword + } + )) + + # 2. 如果图索引结果不足,使用Neo4j进行补充检索 + if len(results) < top_k: + neo4j_results = self._neo4j_entity_level_search(entity_keywords, top_k - len(results)) + results.extend(neo4j_results) + + # 3. 按相关性排序并返回 + results.sort(key=lambda x: x.relevance_score, reverse=True) + + logger.info(f"实体级检索完成,返回 {len(results)} 个结果") + return results[:top_k] + + def _neo4j_entity_level_search(self, keywords: List[str], limit: int) -> List[RetrievalResult]: + """Neo4j补充检索""" + results = [] + + try: + with self.driver.session() as session: + cypher_query = """ + UNWIND $keywords as keyword + CALL db.index.fulltext.queryNodes('recipe_fulltext_index', keyword + '*') + YIELD node, score + WHERE node:Recipe + RETURN + node.nodeId as node_id, + node.name as name, + node.description as description, + labels(node) as labels, + score + ORDER BY score DESC + LIMIT $limit + """ + + result = session.run(cypher_query, { + "keywords": keywords, + "limit": limit + }) + + for record in result: + content_parts = [] + if record["name"]: + content_parts.append(f"菜品: {record['name']}") + if record["description"]: + content_parts.append(f"描述: {record['description']}") + + results.append(RetrievalResult( + content='\n'.join(content_parts), + node_id=record["node_id"], + node_type="Recipe", + relevance_score=float(record["score"]) * 0.7, # 补充检索得分较低 + retrieval_level="entity", + metadata={ + "name": record["name"], + "labels": record["labels"], + "source": "neo4j_fallback" + } + )) + + except Exception as e: + logger.error(f"Neo4j补充检索失败: {e}") + + return results + + def topic_level_retrieval(self, topic_keywords: List[str], top_k: int = 5) -> List[RetrievalResult]: + """ + 主题级检索:专注于广泛主题和概念 + 使用图索引的关系键值对结构进行主题检索 + """ + results = [] + + # 1. 使用图索引进行关系/主题检索 + for keyword in topic_keywords: + # 检索匹配的关系 + relations = self.graph_indexing.get_relations_by_key(keyword) + + for relation in relations: + # 获取相关实体信息 + source_entity = self.graph_indexing.entity_kv_store.get(relation.source_entity) + target_entity = self.graph_indexing.entity_kv_store.get(relation.target_entity) + + if source_entity and target_entity: + # 构建丰富的主题内容 + content_parts = [ + f"主题: {keyword}", + relation.value_content, + f"相关菜品: {source_entity.entity_name}", + f"相关信息: {target_entity.entity_name}" + ] + + # 添加源实体的详细信息 + if source_entity.entity_type == "Recipe": + newline = '\n' + content_parts.append(f"菜品详情: {source_entity.value_content.split(newline)[0]}") + + results.append(RetrievalResult( + content='\n'.join(content_parts), + node_id=relation.source_entity, # 以主要实体为ID + node_type=source_entity.entity_type, + relevance_score=0.95, # 主题匹配得分 + retrieval_level="topic", + metadata={ + "relation_id": relation.relation_id, + "relation_type": relation.relation_type, + "source_name": source_entity.entity_name, + "target_name": target_entity.entity_name, + "matched_keyword": keyword, + "index_keys": relation.index_keys + } + )) + + # 2. 使用实体的分类信息进行主题检索 + for keyword in topic_keywords: + entities = self.graph_indexing.get_entities_by_key(keyword) + for entity in entities: + if entity.entity_type == "Recipe": + # 构建分类主题内容 + content_parts = [ + f"主题分类: {keyword}", + entity.value_content + ] + + results.append(RetrievalResult( + content='\n'.join(content_parts), + node_id=entity.metadata["node_id"], + node_type=entity.entity_type, + relevance_score=0.85, # 分类匹配得分 + retrieval_level="topic", + metadata={ + "entity_name": entity.entity_name, + "entity_type": entity.entity_type, + "matched_keyword": keyword, + "source": "category_match" + } + )) + + # 3. 如果结果不足,使用Neo4j进行补充检索 + if len(results) < top_k: + neo4j_results = self._neo4j_topic_level_search(topic_keywords, top_k - len(results)) + results.extend(neo4j_results) + + # 4. 按相关性排序并返回 + results.sort(key=lambda x: x.relevance_score, reverse=True) + + logger.info(f"主题级检索完成,返回 {len(results)} 个结果") + return results[:top_k] + + def _neo4j_topic_level_search(self, keywords: List[str], limit: int) -> List[RetrievalResult]: + """Neo4j主题级检索补充""" + results = [] + + try: + with self.driver.session() as session: + cypher_query = """ + UNWIND $keywords as keyword + MATCH (r:Recipe) + WHERE r.category CONTAINS keyword + OR r.cuisineType CONTAINS keyword + OR r.tags CONTAINS keyword + WITH r, keyword + OPTIONAL MATCH (r)-[:REQUIRES]->(i:Ingredient) + WITH r, keyword, collect(i.name)[0..3] as ingredients + RETURN + r.nodeId as node_id, + r.name as name, + r.category as category, + r.cuisineType as cuisine_type, + r.difficulty as difficulty, + ingredients, + keyword as matched_keyword + ORDER BY r.difficulty ASC, r.name + LIMIT $limit + """ + + result = session.run(cypher_query, { + "keywords": keywords, + "limit": limit + }) + + for record in result: + content_parts = [] + content_parts.append(f"菜品: {record['name']}") + + if record["category"]: + content_parts.append(f"分类: {record['category']}") + if record["cuisine_type"]: + content_parts.append(f"菜系: {record['cuisine_type']}") + if record["difficulty"]: + content_parts.append(f"难度: {record['difficulty']}") + + if record["ingredients"]: + ingredients_str = ', '.join(record["ingredients"][:3]) + content_parts.append(f"主要食材: {ingredients_str}") + + results.append(RetrievalResult( + content='\n'.join(content_parts), + node_id=record["node_id"], + node_type="Recipe", + relevance_score=0.75, # 补充检索得分 + retrieval_level="topic", + metadata={ + "name": record["name"], + "category": record["category"], + "cuisine_type": record["cuisine_type"], + "difficulty": record["difficulty"], + "matched_keyword": record["matched_keyword"], + "source": "neo4j_fallback" + } + )) + + except Exception as e: + logger.error(f"Neo4j主题级检索失败: {e}") + + return results + + def dual_level_retrieval(self, query: str, top_k: int = 5) -> List[Document]: + """ + 双层检索:结合实体级和主题级检索 + """ + logger.info(f"开始双层检索: {query}") + + # 1. 提取关键词 + entity_keywords, topic_keywords = self.extract_query_keywords(query) + + # 2. 执行双层检索 + entity_results = self.entity_level_retrieval(entity_keywords, top_k) + topic_results = self.topic_level_retrieval(topic_keywords, top_k) + + # 3. 结果合并和排序 + all_results = entity_results + topic_results + + # 4. 去重和重排序 + seen_nodes = set() + unique_results = [] + + for result in sorted(all_results, key=lambda x: x.relevance_score, reverse=True): + if result.node_id not in seen_nodes: + seen_nodes.add(result.node_id) + unique_results.append(result) + + # 5. 转换为Document格式 + documents = [] + for result in unique_results[:top_k]: + # 确保recipe_name字段正确设置 + recipe_name = result.metadata.get("name") or result.metadata.get("entity_name", "未知菜品") + + doc = Document( + page_content=result.content, + metadata={ + "node_id": result.node_id, + "node_type": result.node_type, + "retrieval_level": result.retrieval_level, + "relevance_score": result.relevance_score, + "recipe_name": recipe_name, # 确保有recipe_name字段 + "search_type": "dual_level", # 设置搜索类型 + **result.metadata + } + ) + documents.append(doc) + + logger.info(f"双层检索完成,返回 {len(documents)} 个文档") + return documents + + def vector_search_enhanced(self, query: str, top_k: int = 5) -> List[Document]: + """ + 增强的向量检索:结合图信息 + """ + try: + # 使用Milvus进行向量检索 + vector_docs = self.milvus_module.similarity_search(query, k=top_k*2) + + # 用图信息增强结果并转换为Document对象 + enhanced_docs = [] + for result in vector_docs: + # 从Milvus结果创建Document对象 + content = result.get("text", "") + metadata = result.get("metadata", {}) + node_id = metadata.get("node_id") + + if node_id: + # 从图中获取邻居信息 + neighbors = self._get_node_neighbors(node_id) + if neighbors: + # 将邻居信息添加到内容中 + neighbor_info = f"\n相关信息: {', '.join(neighbors[:3])}" + content += neighbor_info + + # 确保recipe_name字段正确设置 + recipe_name = metadata.get("recipe_name", "未知菜品") + + # 调试:打印向量得分 + vector_score = result.get("score", 0.0) + logger.debug(f"向量检索得分: {recipe_name} = {vector_score}") + + # 创建Document对象 + doc = Document( + page_content=content, + metadata={ + **metadata, + "recipe_name": recipe_name, # 确保有recipe_name字段 + "score": vector_score, + "search_type": "vector_enhanced" + } + ) + enhanced_docs.append(doc) + + return enhanced_docs[:top_k] + + except Exception as e: + logger.error(f"增强向量检索失败: {e}") + return [] + + def _get_node_neighbors(self, node_id: str, max_neighbors: int = 3) -> List[str]: + """获取节点的邻居信息""" + try: + with self.driver.session() as session: + query = """ + MATCH (n {nodeId: $node_id})-[r]-(neighbor) + RETURN neighbor.name as name + LIMIT $limit + """ + result = session.run(query, {"node_id": node_id, "limit": max_neighbors}) + return [record["name"] for record in result if record["name"]] + except Exception as e: + logger.error(f"获取邻居节点失败: {e}") + return [] + + def bm25_search(self, query: str, top_k: int = 5) -> List[Document]: + """ + BM25 检索:jieba 分词后查 BM25Okapi 索引,按分数降序返回 top_k。 + 分数写入 metadata["bm25_score"],供调试与未来潜在的分数级融合使用。 + """ + if self.bm25 is None or not self.bm25_corpus_docs: + logger.warning("BM25 索引未初始化,bm25_search 返回空") + return [] + + tokenized_query = self._tokenize_chinese(query) + if not tokenized_query: + logger.debug(f"BM25 query 分词为空,跳过: {query}") + return [] + + scores = self.bm25.get_scores(tokenized_query) + # 按分数降序取 top_k 索引 + top_indices = sorted( + range(len(scores)), key=lambda i: scores[i], reverse=True + )[:top_k] + + docs: List[Document] = [] + for idx in top_indices: + score = float(scores[idx]) + if score <= 0: + # BM25 分数 ≤ 0 视为无关(IDF/TF 全无贡献),不进结果 + continue + src = self.bm25_corpus_docs[idx] + recipe_name = ( + src.metadata.get("recipe_name") + or src.metadata.get("name") + or "未知菜品" + ) + doc = Document( + page_content=src.page_content, + metadata={ + **src.metadata, + "recipe_name": recipe_name, + "search_method": "bm25", + "search_type": "bm25", + "bm25_score": score, + } + ) + docs.append(doc) + + logger.info(f"BM25 检索完成,返回 {len(docs)} 个文档(query tokens={tokenized_query})") + return docs + + @staticmethod + def _rrf_merge( + ranked_lists: List[Tuple[str, List[Document]]], + top_k: int, + k: int = _RRF_K, + ) -> List[Document]: + """ + Reciprocal Rank Fusion: score(d) = Σ_i 1 / (k + best_rank_i(d)) + + Args: + ranked_lists: 多路 (source_name, ranked_docs) — docs 按相关度降序 + top_k: 最终返回个数 + k: RRF 平滑常数,默认 60(Cormack et al. 2009) + + 去重 key:node_id 优先,page_content[:200] hash 兜底。 + + 同 source 内同 doc_id 多次命中(如一道菜的多个 chunk 共享 recipe.nodeId): + - 算分只取该 source 内最佳 rank(最小 rank)一次,避免重复加分 + - 命中 chunk 数另存到 rrf_chunk_hits,供后续分析 + + canonical doc(最终展示给 LLM 的 page_content): + 选全局最小 rank 那个 chunk;rank 相同时按 ranked_lists 顺序优先。 + + 返回的 Document 是新对象,不会 mutate 输入 list 里的 Document。 + """ + # doc_id -> source_name -> 该 source 内最小 rank(用于算分) + best_rank_per_source: Dict[str, Dict[str, int]] = {} + # doc_id -> source_name -> 该 source 内命中 chunk 次数(信息存档) + chunk_hits_per_source: Dict[str, Dict[str, int]] = {} + # doc_id -> (global_best_rank, source_priority, doc) — 选 canonical doc + best_doc_info: Dict[str, Tuple[int, int, Document]] = {} + + for source_priority, (source_name, ranked_docs) in enumerate(ranked_lists): + for rank, doc in enumerate(ranked_docs, start=1): + node_id = doc.metadata.get("node_id") + doc_id = ( + str(node_id) if node_id is not None + else f"hash::{hash(doc.page_content[:200])}" + ) + + if doc_id not in best_rank_per_source: + best_rank_per_source[doc_id] = {} + chunk_hits_per_source[doc_id] = {} + + curr_best = best_rank_per_source[doc_id].get(source_name) + # 如果是第一次出现或者当前rank比记录的更小,则更新 + if curr_best is None or rank < curr_best: + best_rank_per_source[doc_id][source_name] = rank + + chunk_hits_per_source[doc_id][source_name] = ( + chunk_hits_per_source[doc_id].get(source_name, 0) + 1 + ) + + new_key = (rank, source_priority) + if ( + doc_id not in best_doc_info + or new_key < (best_doc_info[doc_id][0], best_doc_info[doc_id][1]) + ): + best_doc_info[doc_id] = (rank, source_priority, doc) + + # 每个 source 只用 best rank 算一次贡献 + rrf_scores: Dict[str, float] = { + doc_id: sum(1.0 / (k + r) for r in source_ranks.values()) + for doc_id, source_ranks in best_rank_per_source.items() + } + + sorted_ids = sorted( + rrf_scores.keys(), key=lambda d: rrf_scores[d], reverse=True + ) + + merged: List[Document] = [] + for doc_id in sorted_ids[:top_k]: + _, _, source_doc = best_doc_info[doc_id] + # 浅 copy metadata,避免 mutate 上游 Document + new_metadata = dict(source_doc.metadata) + new_metadata["rrf_score"] = rrf_scores[doc_id] + new_metadata["rrf_sources"] = list(best_rank_per_source[doc_id].keys()) + new_metadata["rrf_ranks"] = dict(best_rank_per_source[doc_id]) + new_metadata["rrf_chunk_hits"] = dict(chunk_hits_per_source[doc_id]) + new_metadata["final_score"] = rrf_scores[doc_id] + merged.append(Document( + page_content=source_doc.page_content, + metadata=new_metadata, + )) + + return merged + + def hybrid_search(self, query: str, top_k: int = 5) -> List[Document]: + """ + 混合检索:三路召回(图键值双层 + 向量 + BM25)→ RRF 融合 + """ + logger.info(f"开始混合检索(dual + vector + bm25, RRF k={_RRF_K}): {query}") + + # 每路给 RRF 留够候选空间,否则三路各自前 top_k 容易没交集,融合退化 + candidate_k = max(top_k * 2, 10) + + dual_docs = self.dual_level_retrieval(query, candidate_k) + vector_docs = self.vector_search_enhanced(query, candidate_k) + bm25_docs = self.bm25_search(query, candidate_k) + + # 标记每路来源(dual_level 内部会写 search_type 但不一定写 search_method) + for d in dual_docs: + d.metadata.setdefault("search_method", "dual_level") + for d in vector_docs: + d.metadata["search_method"] = "vector" + # bm25_search 内部已写 search_method=bm25 + + final_docs = self._rrf_merge( + ranked_lists=[ + ("dual_level", dual_docs), + ("vector", vector_docs), + ("bm25", bm25_docs), + ], + top_k=top_k, + ) + + logger.info( + f"RRF 融合完成:dual={len(dual_docs)} vector={len(vector_docs)} " + f"bm25={len(bm25_docs)} → 最终 {len(final_docs)} 个文档" + ) + return final_docs + + def close(self): + """关闭资源连接""" + if self.driver: + self.driver.close() + logger.info("Neo4j连接已关闭") \ No newline at end of file diff --git a/code/C9/rag_modules/intelligent_query_router.py b/code/C9/rag_modules/intelligent_query_router.py new file mode 100644 index 0000000..c4a240d --- /dev/null +++ b/code/C9/rag_modules/intelligent_query_router.py @@ -0,0 +1,306 @@ +""" +智能查询路由器 +根据查询特点自动选择最适合的检索策略: +- 传统混合检索:适合简单的信息查找 +- 图RAG检索:适合复杂的关系推理和知识发现 +""" + +import json +import logging +from typing import List, Dict, Tuple, Any, Optional +from dataclasses import dataclass +from enum import Enum + +from langchain_core.documents import Document + +logger = logging.getLogger(__name__) + +class SearchStrategy(Enum): + """搜索策略枚举""" + HYBRID_TRADITIONAL = "hybrid_traditional" # 传统混合检索 + GRAPH_RAG = "graph_rag" # 图RAG检索 + COMBINED = "combined" # 组合策略 + +@dataclass +class QueryAnalysis: + """查询分析结果""" + query_complexity: float # 查询复杂度 (0-1) + relationship_intensity: float # 关系密集度 (0-1) + reasoning_required: bool # 是否需要推理 + entity_count: int # 实体数量 + recommended_strategy: SearchStrategy + confidence: float # 推荐置信度 + reasoning: str # 推荐理由 + +class IntelligentQueryRouter: + """ + 智能查询路由器 + + 核心能力: + 1. 查询复杂度分析:识别简单查找 vs 复杂推理 + 2. 关系密集度评估:判断是否需要图结构优势 + 3. 策略自动选择:路由到最适合的检索引擎 + 4. 结果质量监控:基于反馈优化路由决策 + """ + + def __init__(self, + traditional_retrieval, # 传统混合检索模块 + graph_rag_retrieval, # 图RAG检索模块 + llm_client, + config): + self.traditional_retrieval = traditional_retrieval + self.graph_rag_retrieval = graph_rag_retrieval + self.llm_client = llm_client + self.config = config + + # 路由统计 + self.route_stats = { + "traditional_count": 0, + "graph_rag_count": 0, + "combined_count": 0, + "total_queries": 0 + } + + def analyze_query(self, query: str) -> QueryAnalysis: + """ + 深度分析查询特征,决定最佳检索策略 + """ + logger.info(f"分析查询特征: {query}") + + # 使用LLM进行智能分析 + analysis_prompt = f""" + 作为RAG系统的查询分析专家,请深度分析以下查询的特征: + + 查询:{query} + + 请从以下维度分析: + + 1. 查询复杂度 (0-1): + - 0.0-0.3: 简单信息查找(如:红烧肉怎么做?) + - 0.4-0.7: 中等复杂度(如:川菜有哪些特色菜?) + - 0.8-1.0: 高复杂度推理(如:为什么川菜用花椒而不是胡椒?) + + 2. 关系密集度 (0-1): + - 0.0-0.3: 单一实体信息(如:西红柿的营养价值) + - 0.4-0.7: 实体间关系(如:鸡肉配什么蔬菜?) + - 0.8-1.0: 复杂关系网络(如:川菜的形成与地理、历史的关系) + + 3. 推理需求: + - 是否需要多跳推理? + - 是否需要因果分析? + - 是否需要对比分析? + + 4. 实体识别: + - 查询中包含多少个明确实体? + - 实体类型是什么? + + 基于分析推荐检索策略: + - hybrid_traditional: 适合简单直接的信息查找 + - graph_rag: 适合复杂关系推理和知识发现 + - combined: 需要两种策略结合 + + 返回JSON格式: + {{ + "query_complexity": 0.6, + "relationship_intensity": 0.8, + "reasoning_required": true, + "entity_count": 3, + "recommended_strategy": "graph_rag", + "confidence": 0.85, + "reasoning": "该查询涉及多个实体间的复杂关系,需要图结构推理" + }} + """ + + try: + response = self.llm_client.chat.completions.create( + model=self.config.llm_model, + messages=[{"role": "user", "content": analysis_prompt}], + temperature=0.1, + max_tokens=800 + ) + + result = json.loads(response.choices[0].message.content.strip()) + + analysis = QueryAnalysis( + query_complexity=result.get("query_complexity", 0.5), + relationship_intensity=result.get("relationship_intensity", 0.5), + reasoning_required=result.get("reasoning_required", False), + entity_count=result.get("entity_count", 1), + recommended_strategy=SearchStrategy(result.get("recommended_strategy", "hybrid_traditional")), + confidence=result.get("confidence", 0.5), + reasoning=result.get("reasoning", "默认分析") + ) + + logger.info(f"查询分析完成: {analysis.recommended_strategy.value} (置信度: {analysis.confidence:.2f})") + return analysis + + except Exception as e: + logger.error(f"查询分析失败: {e}") + # 降级方案:基于规则的简单分析 + return self._rule_based_analysis(query) + + def _rule_based_analysis(self, query: str) -> QueryAnalysis: + """基于规则的降级分析""" + # 简单的规则判断 + complexity_keywords = ["为什么", "如何", "关系", "影响", "原因", "比较", "区别"] + relation_keywords = ["配", "搭配", "组合", "相关", "联系", "连接"] + + complexity = sum(1 for kw in complexity_keywords if kw in query) / len(complexity_keywords) + relation_intensity = sum(1 for kw in relation_keywords if kw in query) / len(relation_keywords) + + if complexity > 0.3 or relation_intensity > 0.3: + strategy = SearchStrategy.GRAPH_RAG + else: + strategy = SearchStrategy.HYBRID_TRADITIONAL + + return QueryAnalysis( + query_complexity=complexity, + relationship_intensity=relation_intensity, + reasoning_required=complexity > 0.3, + entity_count=len(query.split()), + recommended_strategy=strategy, + confidence=0.6, + reasoning="基于规则的简单分析" + ) + + def route_query(self, query: str, top_k: int = 5) -> Tuple[List[Document], QueryAnalysis]: + """ + 智能路由查询到最适合的检索引擎 + """ + logger.info(f"开始智能路由: {query}") + + # 1. 分析查询特征 + analysis = self.analyze_query(query) + + # 2. 更新统计 + self._update_route_stats(analysis.recommended_strategy) + + # 3. 根据策略执行检索 + documents = [] + + try: + if analysis.recommended_strategy == SearchStrategy.HYBRID_TRADITIONAL: + logger.info("使用传统混合检索") + documents = self.traditional_retrieval.hybrid_search(query, top_k) + + elif analysis.recommended_strategy == SearchStrategy.GRAPH_RAG: + logger.info("🕸️ 使用图RAG检索") + documents = self.graph_rag_retrieval.graph_rag_search(query, top_k) + + elif analysis.recommended_strategy == SearchStrategy.COMBINED: + logger.info("🔄 使用组合检索策略") + documents = self._combined_search(query, top_k) + + # 4. 结果后处理 + documents = self._post_process_results(documents, analysis) + + logger.info(f"路由完成,返回 {len(documents)} 个结果") + return documents, analysis + + except Exception as e: + logger.error(f"查询路由失败: {e}") + # 降级到传统检索 + documents = self.traditional_retrieval.hybrid_search(query, top_k) + return documents, analysis + + def _combined_search(self, query: str, top_k: int) -> List[Document]: + """ + 组合搜索策略:结合传统检索和图RAG的优势 + """ + # 分配结果数量 + traditional_k = max(1, top_k // 2) + graph_k = top_k - traditional_k + + # 执行两种检索 + traditional_docs = self.traditional_retrieval.hybrid_search(query, traditional_k) + graph_docs = self.graph_rag_retrieval.graph_rag_search(query, graph_k) + + # 合并和去重 + combined_docs = [] + seen_contents = set() + + # 交替添加结果(Round-robin) + max_len = max(len(traditional_docs), len(graph_docs)) + for i in range(max_len): + # 先添加图RAG结果(通常质量更高) + if i < len(graph_docs): + doc = graph_docs[i] + content_hash = hash(doc.page_content[:100]) + if content_hash not in seen_contents: + seen_contents.add(content_hash) + doc.metadata["search_source"] = "graph_rag" + combined_docs.append(doc) + + # 再添加传统检索结果 + if i < len(traditional_docs): + doc = traditional_docs[i] + content_hash = hash(doc.page_content[:100]) + if content_hash not in seen_contents: + seen_contents.add(content_hash) + doc.metadata["search_source"] = "traditional" + combined_docs.append(doc) + + return combined_docs[:top_k] + + def _post_process_results(self, documents: List[Document], analysis: QueryAnalysis) -> List[Document]: + """ + 结果后处理:根据查询分析优化结果 + """ + for doc in documents: + # 添加路由信息到元数据 + doc.metadata.update({ + "route_strategy": analysis.recommended_strategy.value, + "query_complexity": analysis.query_complexity, + "route_confidence": analysis.confidence + }) + + return documents + + def _update_route_stats(self, strategy: SearchStrategy): + """更新路由统计""" + self.route_stats["total_queries"] += 1 + + if strategy == SearchStrategy.HYBRID_TRADITIONAL: + self.route_stats["traditional_count"] += 1 + elif strategy == SearchStrategy.GRAPH_RAG: + self.route_stats["graph_rag_count"] += 1 + elif strategy == SearchStrategy.COMBINED: + self.route_stats["combined_count"] += 1 + + def get_route_statistics(self) -> Dict[str, Any]: + """获取路由统计信息""" + total = self.route_stats["total_queries"] + if total == 0: + return self.route_stats + + return { + **self.route_stats, + "traditional_ratio": self.route_stats["traditional_count"] / total, + "graph_rag_ratio": self.route_stats["graph_rag_count"] / total, + "combined_ratio": self.route_stats["combined_count"] / total + } + + def explain_routing_decision(self, query: str) -> str: + """解释路由决策过程""" + analysis = self.analyze_query(query) + + explanation = f""" + 查询路由分析报告 + + 查询:{query} + + 特征分析: + - 复杂度:{analysis.query_complexity:.2f} ({'简单' if analysis.query_complexity < 0.4 else '中等' if analysis.query_complexity < 0.8 else '复杂'}) + - 关系密集度:{analysis.relationship_intensity:.2f} ({'单一实体' if analysis.relationship_intensity < 0.4 else '实体关系' if analysis.relationship_intensity < 0.8 else '复杂关系网络'}) + - 推理需求:{'是' if analysis.reasoning_required else '否'} + - 实体数量:{analysis.entity_count} + + 推荐策略:{analysis.recommended_strategy.value} + 置信度:{analysis.confidence:.2f} + + 决策理由:{analysis.reasoning} + """ + + return explanation + + \ No newline at end of file diff --git a/code/C9/rag_modules/milvus_index_construction.py b/code/C9/rag_modules/milvus_index_construction.py new file mode 100644 index 0000000..c38a527 --- /dev/null +++ b/code/C9/rag_modules/milvus_index_construction.py @@ -0,0 +1,503 @@ +""" +Milvus索引构建模块 +""" + +import logging +import time +from typing import List, Dict, Any, Optional + +from pymilvus import MilvusClient, DataType, CollectionSchema, FieldSchema +from langchain_huggingface import HuggingFaceEmbeddings +from langchain_core.documents import Document +import numpy as np + +logger = logging.getLogger(__name__) + +class MilvusIndexConstructionModule: + """Milvus索引构建模块 - 负责向量化和Milvus索引构建""" + + def __init__(self, + host: str = "localhost", + port: int = 19530, + collection_name: str = "cooking_knowledge", + dimension: int = 512, + model_name: str = "BAAI/bge-small-zh-v1.5"): + """ + 初始化Milvus索引构建模块 + + Args: + host: Milvus服务器地址 + port: Milvus服务器端口 + collection_name: 集合名称 + dimension: 向量维度 + model_name: 嵌入模型名称 + """ + self.host = host + self.port = port + self.collection_name = collection_name + self.dimension = dimension + self.model_name = model_name + + self.client = None + self.embeddings = None + self.collection_created = False + + self._setup_client() + self._setup_embeddings() + + def _safe_truncate(self, text: str, max_length: int) -> str: + """ + 安全截取字符串,处理None值 + + Args: + text: 输入文本 + max_length: 最大长度 + + Returns: + 截取后的字符串 + """ + if text is None: + return "" + return str(text)[:max_length] + + def _setup_client(self): + """初始化Milvus客户端""" + try: + self.client = MilvusClient( + uri=f"http://{self.host}:{self.port}" + ) + logger.info(f"已连接到Milvus服务器: {self.host}:{self.port}") + + # 测试连接 + collections = self.client.list_collections() + logger.info(f"连接成功,当前集合: {collections}") + + except Exception as e: + logger.error(f"连接Milvus失败: {e}") + raise + + def _setup_embeddings(self): + """初始化嵌入模型""" + logger.info(f"正在初始化嵌入模型: {self.model_name}") + + self.embeddings = HuggingFaceEmbeddings( + model_name=self.model_name, + model_kwargs={'device': 'cpu'}, + encode_kwargs={'normalize_embeddings': True} + ) + + logger.info("嵌入模型初始化完成") + + def _create_collection_schema(self) -> CollectionSchema: + """ + 创建集合模式 + + Returns: + 集合模式对象 + """ + # 定义字段 + fields = [ + FieldSchema(name="id", dtype=DataType.VARCHAR, max_length=150, is_primary=True), + FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=self.dimension), + FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=15000), + FieldSchema(name="node_id", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="recipe_name", dtype=DataType.VARCHAR, max_length=300), + FieldSchema(name="node_type", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="cuisine_type", dtype=DataType.VARCHAR, max_length=200), + FieldSchema(name="difficulty", dtype=DataType.INT64), + FieldSchema(name="doc_type", dtype=DataType.VARCHAR, max_length=50), + FieldSchema(name="chunk_id", dtype=DataType.VARCHAR, max_length=150), + FieldSchema(name="parent_id", dtype=DataType.VARCHAR, max_length=100) + ] + + # 创建集合模式 + schema = CollectionSchema( + fields=fields, + description="中式烹饪知识图谱向量集合" + ) + + return schema + + def create_collection(self, force_recreate: bool = False) -> bool: + """ + 创建Milvus集合 + + Args: + force_recreate: 是否强制重新创建集合 + + Returns: + 是否创建成功 + """ + try: + # 检查集合是否存在 + if self.client.has_collection(self.collection_name): + if force_recreate: + logger.info(f"删除已存在的集合: {self.collection_name}") + self.client.drop_collection(self.collection_name) + else: + logger.info(f"集合 {self.collection_name} 已存在") + self.collection_created = True + return True + + # 创建集合 + schema = self._create_collection_schema() + + self.client.create_collection( + collection_name=self.collection_name, + schema=schema, + metric_type="COSINE", # 使用余弦相似度 + consistency_level="Strong" + ) + + logger.info(f"成功创建集合: {self.collection_name}") + self.collection_created = True + + return True + + except Exception as e: + logger.error(f"创建集合失败: {e}") + return False + + def create_index(self) -> bool: + """ + 创建向量索引 + + Returns: + 是否创建成功 + """ + try: + if not self.collection_created: + raise ValueError("请先创建集合") + + # 使用prepare_index_params创建正确的IndexParams对象 + index_params = self.client.prepare_index_params() + + # 添加向量字段索引 + index_params.add_index( + field_name="vector", + index_type="HNSW", + metric_type="COSINE", + params={ + "M": 16, + "efConstruction": 200 + } + ) + + self.client.create_index( + collection_name=self.collection_name, + index_params=index_params + ) + + logger.info("向量索引创建成功") + return True + + except Exception as e: + logger.error(f"创建索引失败: {e}") + return False + + def build_vector_index(self, chunks: List[Document]) -> bool: + """ + 构建向量索引 + + Args: + chunks: 文档块列表 + + Returns: + 是否构建成功 + """ + logger.info(f"正在构建Milvus向量索引,文档数量: {len(chunks)}...") + + if not chunks: + raise ValueError("文档块列表不能为空") + + try: + # 1. 创建集合(如果schema不兼容则强制重新创建) + if not self.create_collection(force_recreate=True): + return False + + # 2. 准备数据 + logger.info("正在生成向量embeddings...") + texts = [chunk.page_content for chunk in chunks] + vectors = self.embeddings.embed_documents(texts) + + # 3. 准备插入数据 + entities = [] + for i, (chunk, vector) in enumerate(zip(chunks, vectors)): + entity = { + "id": self._safe_truncate(chunk.metadata.get("chunk_id", f"chunk_{i}"), 150), + "vector": vector, + "text": self._safe_truncate(chunk.page_content, 15000), + "node_id": self._safe_truncate(chunk.metadata.get("node_id", ""), 100), + "recipe_name": self._safe_truncate(chunk.metadata.get("recipe_name", ""), 300), + "node_type": self._safe_truncate(chunk.metadata.get("node_type", ""), 100), + "category": self._safe_truncate(chunk.metadata.get("category", ""), 100), + "cuisine_type": self._safe_truncate(chunk.metadata.get("cuisine_type", ""), 200), + "difficulty": int(chunk.metadata.get("difficulty", 0)), + "doc_type": self._safe_truncate(chunk.metadata.get("doc_type", ""), 50), + "chunk_id": self._safe_truncate(chunk.metadata.get("chunk_id", f"chunk_{i}"), 150), + "parent_id": self._safe_truncate(chunk.metadata.get("parent_id", ""), 100) + } + entities.append(entity) + + # 4. 批量插入数据 + logger.info("正在插入向量数据...") + batch_size = 100 + for i in range(0, len(entities), batch_size): + batch = entities[i:i + batch_size] + self.client.insert( + collection_name=self.collection_name, + data=batch + ) + logger.info(f"已插入 {min(i + batch_size, len(entities))}/{len(entities)} 条数据") + + # 5. 创建索引 + if not self.create_index(): + return False + + # 6. 加载集合到内存 + self.client.load_collection(self.collection_name) + logger.info("集合已加载到内存") + + # 7. 等待索引构建完成 + logger.info("等待索引构建完成...") + time.sleep(2) + + logger.info(f"向量索引构建完成,包含 {len(chunks)} 个向量") + return True + + except Exception as e: + logger.error(f"构建向量索引失败: {e}") + return False + + def add_documents(self, new_chunks: List[Document]) -> bool: + """ + 向现有索引添加新文档 + + Args: + new_chunks: 新的文档块列表 + + Returns: + 是否添加成功 + """ + if not self.collection_created: + raise ValueError("请先构建向量索引") + + logger.info(f"正在添加 {len(new_chunks)} 个新文档到索引...") + + try: + # 生成向量 + texts = [chunk.page_content for chunk in new_chunks] + vectors = self.embeddings.embed_documents(texts) + + # 准备插入数据 + entities = [] + for i, (chunk, vector) in enumerate(zip(new_chunks, vectors)): + entity = { + "id": self._safe_truncate(chunk.metadata.get("chunk_id", f"new_chunk_{i}_{int(time.time())}"), 150), + "vector": vector, + "text": self._safe_truncate(chunk.page_content, 15000), + "node_id": self._safe_truncate(chunk.metadata.get("node_id", ""), 100), + "recipe_name": self._safe_truncate(chunk.metadata.get("recipe_name", ""), 300), + "node_type": self._safe_truncate(chunk.metadata.get("node_type", ""), 100), + "category": self._safe_truncate(chunk.metadata.get("category", ""), 100), + "cuisine_type": self._safe_truncate(chunk.metadata.get("cuisine_type", ""), 200), + "difficulty": int(chunk.metadata.get("difficulty", 0)), + "doc_type": self._safe_truncate(chunk.metadata.get("doc_type", ""), 50), + "chunk_id": self._safe_truncate(chunk.metadata.get("chunk_id", f"new_chunk_{i}_{int(time.time())}"), 150), + "parent_id": self._safe_truncate(chunk.metadata.get("parent_id", ""), 100) + } + entities.append(entity) + + # 插入数据 + self.client.insert( + collection_name=self.collection_name, + data=entities + ) + + logger.info("新文档添加完成") + return True + + except Exception as e: + logger.error(f"添加新文档失败: {e}") + return False + + def similarity_search(self, query: str, k: int = 5, filters: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]: + """ + 相似度搜索 + + Args: + query: 查询文本 + k: 返回结果数量 + filters: 过滤条件 + + Returns: + 搜索结果列表 + """ + if not self.collection_created: + raise ValueError("请先构建或加载向量索引") + + try: + # 生成查询向量 + query_vector = self.embeddings.embed_query(query) + + # 构建过滤表达式 + filter_expr = "" + if filters: + filter_conditions = [] + for key, value in filters.items(): + if isinstance(value, str): + filter_conditions.append(f'{key} == "{value}"') + elif isinstance(value, (int, float)): + filter_conditions.append(f'{key} == {value}') + elif isinstance(value, list): + # 支持IN操作 + if all(isinstance(v, str) for v in value): + value_str = '", "'.join(value) + filter_conditions.append(f'{key} in ["{value_str}"]') + else: + value_str = ', '.join(map(str, value)) + filter_conditions.append(f'{key} in [{value_str}]') + + if filter_conditions: + filter_expr = " and ".join(filter_conditions) + + # 执行搜索 - 修复参数传递 + search_params = { + "metric_type": "COSINE", + "params": {"ef": 64} + } + + # 构建搜索参数,避免重复传递 + search_kwargs = { + "collection_name": self.collection_name, + "data": [query_vector], + "anns_field": "vector", + "limit": k, + "output_fields": ["text", "node_id", "recipe_name", "node_type", + "category", "cuisine_type", "difficulty", "doc_type", + "chunk_id", "parent_id"], + "search_params": search_params + } + + # 只在有过滤条件时添加filter参数 + if filter_expr: + search_kwargs["filter"] = filter_expr + + results = self.client.search(**search_kwargs) + + # 处理结果 + formatted_results = [] + if results and len(results) > 0: + for hit in results[0]: # results[0]因为我们只发送了一个查询向量 + result = { + "id": hit["id"], + "score": hit["distance"], # 注意:在COSINE距离中,值越大相似度越高 + "text": hit["entity"]["text"], + "metadata": { + "node_id": hit["entity"]["node_id"], + "recipe_name": hit["entity"]["recipe_name"], + "node_type": hit["entity"]["node_type"], + "category": hit["entity"]["category"], + "cuisine_type": hit["entity"]["cuisine_type"], + "difficulty": hit["entity"]["difficulty"], + "doc_type": hit["entity"]["doc_type"], + "chunk_id": hit["entity"]["chunk_id"], + "parent_id": hit["entity"]["parent_id"] + } + } + formatted_results.append(result) + + return formatted_results + + except Exception as e: + logger.error(f"相似度搜索失败: {e}") + return [] + + def get_collection_stats(self) -> Dict[str, Any]: + """ + 获取集合统计信息 + + Returns: + 统计信息字典 + """ + try: + if not self.collection_created: + return {"error": "集合未创建"} + + stats = self.client.get_collection_stats(self.collection_name) + return { + "collection_name": self.collection_name, + "row_count": stats.get("row_count", 0), + "index_building_progress": stats.get("index_building_progress", 0), + "stats": stats + } + + except Exception as e: + logger.error(f"获取集合统计信息失败: {e}") + return {"error": str(e)} + + def delete_collection(self) -> bool: + """ + 删除集合 + + Returns: + 是否删除成功 + """ + try: + if self.client.has_collection(self.collection_name): + self.client.drop_collection(self.collection_name) + logger.info(f"集合 {self.collection_name} 已删除") + self.collection_created = False + return True + else: + logger.info(f"集合 {self.collection_name} 不存在") + return True + + except Exception as e: + logger.error(f"删除集合失败: {e}") + return False + + def has_collection(self) -> bool: + """ + 检查集合是否存在 + + Returns: + 集合是否存在 + """ + try: + return self.client.has_collection(self.collection_name) + except Exception as e: + logger.error(f"检查集合存在性失败: {e}") + return False + + def load_collection(self) -> bool: + """ + 加载集合到内存 + + Returns: + 是否加载成功 + """ + try: + if not self.client.has_collection(self.collection_name): + logger.error(f"集合 {self.collection_name} 不存在") + return False + + self.client.load_collection(self.collection_name) + self.collection_created = True + logger.info(f"集合 {self.collection_name} 已加载到内存") + return True + + except Exception as e: + logger.error(f"加载集合失败: {e}") + return False + + def close(self): + """关闭连接""" + if hasattr(self, 'client') and self.client: + # Milvus客户端不需要显式关闭 + logger.info("Milvus连接已关闭") + + def __del__(self): + """析构函数""" + self.close() \ No newline at end of file diff --git a/code/C9/requirements.txt b/code/C9/requirements.txt new file mode 100644 index 0000000..cf9a2ee --- /dev/null +++ b/code/C9/requirements.txt @@ -0,0 +1,35 @@ +transformers>=4.40.0 +torch==2.6.0 +torchvision==0.21.0 +torchaudio==2.6.0 +sentence-transformers>=3.0.0 + +langchain-core==0.3.71 +langchain-community==0.3.27 +langchain-huggingface==0.3.1 +langchain-text-splitters==0.3.8 +unstructured-client==0.41.0 +neo4j>=5.0.0 + +pymilvus==2.5.11 +rank-bm25>=0.2.2 +jieba>=0.42.1 + +lazy_loader==0.4 +huggingface-hub>=0.33.4 +tokenizers>=0.19.0 +accelerate>=0.20.0 + +openai>=1.86.0,<2.0.0 + +tiktoken>=0.4.0 + +python-dotenv>=1.0.0 + +numpy>=1.24.0 +pandas>=2.0.0 +scikit-learn>=1.3.0 +scipy>=1.10.0 +tqdm>=4.64.0 +pydantic>=2.0.0 +requests>=2.28.0 \ No newline at end of file diff --git a/code/docker-compose.yml b/code/docker-compose.yml new file mode 100644 index 0000000..c972f5f --- /dev/null +++ b/code/docker-compose.yml @@ -0,0 +1,65 @@ +version: '3.5' + +services: + etcd: + container_name: milvus-etcd + image: quay.io/coreos/etcd:v3.5.16 + environment: + - ETCD_AUTO_COMPACTION_MODE=revision + - ETCD_AUTO_COMPACTION_RETENTION=1000 + - ETCD_QUOTA_BACKEND_BYTES=4294967296 + - ETCD_SNAPSHOT_COUNT=50000 + volumes: + - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd + command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd + healthcheck: + test: ["CMD", "etcdctl", "endpoint", "health"] + interval: 30s + timeout: 20s + retries: 3 + + minio: + container_name: milvus-minio + image: minio/minio:RELEASE.2023-03-20T20-16-18Z + environment: + MINIO_ACCESS_KEY: minioadmin + MINIO_SECRET_KEY: minioadmin + ports: + - "9001:9001" + - "9000:9000" + volumes: + - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data + command: minio server /minio_data --console-address ":9001" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 30s + timeout: 20s + retries: 3 + + standalone: + container_name: milvus-standalone + image: milvusdb/milvus:v2.5.14 + command: ["milvus", "run", "standalone"] + security_opt: + - seccomp:unconfined + environment: + ETCD_ENDPOINTS: etcd:2379 + MINIO_ADDRESS: minio:9000 + volumes: + - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"] + interval: 30s + start_period: 90s + timeout: 20s + retries: 3 + ports: + - "19530:19530" + - "9091:9091" + depends_on: + - "etcd" + - "minio" + +networks: + default: + name: milvus \ No newline at end of file diff --git a/code/requirements.txt b/code/requirements.txt new file mode 100644 index 0000000..64fce75 --- /dev/null +++ b/code/requirements.txt @@ -0,0 +1,52 @@ +torch==2.6.0 +torchvision==0.21.0 +torchaudio==2.6.0 +huggingface-hub>=0.33.4 +transformers>=4.40.0 +tokenizers>=0.19.0 +sentence-transformers>=3.0.0 +accelerate>=0.20.0 +datasets>=2.14.0 +numpy>=1.24.0 +pandas>=2.0.0 +scikit-learn>=1.3.0 +scipy>=1.10.0 +langchain==0.3.26 +langchain-core==0.3.71 +langchain-community==0.3.27 +langchain-huggingface==0.3.1 +langchain-openai==0.3.28 +langchain-text-splitters==0.3.8 +langchain-experimental==0.3.4 +llama-index==0.12.51 +llama-index-core==0.12.52 +llama-index-embeddings-huggingface==0.5.5 +llama-index-embeddings-openai==0.3.1 +llama-index-llms-openai==0.4.7 +chromadb>=0.4.0 +faiss-cpu>=1.7.0 +pypdf>=4.0.0 +python-dotenv>=1.0.0 +openai>=1.86.0,<2.0.0 +requests>=2.28.0 +tqdm>=4.64.0 +pydantic>=2.0.0 +pymilvus==2.5.11 +pymilvus.model==0.3.2 +langchain-deepseek==0.1.4 +unstructured==0.18.11 +Markdown==3.8.2 +llama-index-llms-deepseek==0.1.2 +unstructured-client==0.41.0 +unstructured-inference==1.0.5 +unstructured.pytesseract==0.3.15 +unstructured[pdf] +opencv-python-headless==4.12.0.88 +einops==0.8.1 +ftfy==6.3.1 +llama-index-experimental==0.5.6 +openpyxl==3.1.5 +bilibili-api-python==17.3.0 +lark==1.2.2 +lazy_loader==0.4 +pyarrow==20.0.0 \ No newline at end of file diff --git a/data/C1/markdown/easy-rl-chapter1.md b/data/C1/markdown/easy-rl-chapter1.md new file mode 100644 index 0000000..ed6dadd --- /dev/null +++ b/data/C1/markdown/easy-rl-chapter1.md @@ -0,0 +1,668 @@ +# 第1章 强化学习基础 + +## 1.1 强化学习概述 +**强化学习(reinforcement learning,RL)**讨论的问题是智能体(agent)怎么在复杂、不确定的环境(environment)中最大化它能获得的奖励。如图 1.1 所示,强化学习由两部分组成:智能体和环境。在强化学习过程中,智能体与环境一直在交互。智能体在环境中获取某个状态后,它会利用该状态输出一个动作 (action),这个动作也称为决策(decision)。然后这个动作会在环境中被执行,环境会根据智能体采取的动作,输出下一个状态以及当前这个动作带来的奖励。智能体的目的就是尽可能多地从环境中获取奖励。 + +
+ +
+
图 1.1 强化学习示意
+ +### 1.1.1 强化学习与监督学习 + +我们可以把强化学习与监督学习做一个对比。以图片分类为例,如图 1.2 所示,**监督学习(supervised learning)**假设我们有大量被标注的数据,比如汽车、飞机、椅子这些被标注的图片,这些图片都要满足独立同分布,即它们之间是没有关联关系的。假设我们训练一个分类器,比如神经网络。为了分辨输入的 图片中是汽车还是飞机,在训练过程中,需要把正确的标签信息传递给神经网络。 当神经网络做出错误的预测时,比如输入汽车的图片,它预测出来是飞机,我们就会直接告诉它,该预测是错误的,正确的标签应该是汽车。最后我们根据类似错误写出一个损失函数(loss function),通过反向传播(back propagation)来训练神经网络。 + +
+ +
+
图 1.2 监督学习
+ +所以在监督学习过程中,有两个假设: + * 输入的数据(标注的数据)都应是没有关联的。因为如果输入的数据有关联,学习器(learner)是不好学习的。 + * 需要告诉学习器正确的标签是什么,这样它可以通过正确的标签来修正自己的预测。 + +> 通常假设样本空间中全体样本服从一个未知分布,我们获得的每个样本都是独立地从这个分布上采样获得的,即独立同分布(independent and identically distributed,简称 i.i.d.)。 + +在强化学习中,监督学习的两个假设其实都不能得到满足。以雅达利(Atari) 游戏 Breakout 为例,如图 1.3 所示,这是一个打砖块的游戏,控制木板左右移动从而把球反弹到上面来消除砖块。在玩游戏的过程中,我们可以发现智能体得到的观测(observation)不是独立同分布的,上一帧与下一帧间其实有非常强的连续性。我们得到的数据是相关的时间序列数据,不满足独立同分布。另外,我们并没有立刻获得反馈,游戏没有告诉我们哪个动作是正确动作。比如现在把木板往右移,这只会使得球往上或者往左一点儿,我们并不会得到即时的反馈。因此,强化学习之所以困难,是因为智能体不能得到即时的反馈,然而我们依然希望智能体在这个环境中学习。 + +
+ +
+
图 1.3 雅达利游戏Breakout
+ +如图 1.4 所示,强化学习的训练数据就是一个玩游戏的过程。我们从第 1 步开始,采取一个动作,比如我们把木板往右移,接到球。第 2 步我们又做出动作,得到的训练数据是一个玩游戏的序列。比如现在是在第 3 步,我们把这个序列放进网络,希望网络可以输出一个动作,即在当前的状态应该输出往右移或 者往左移。这里有个问题,我们没有标签来说明现在这个动作是正确还是错误的,必须等到游戏结束才可能知道,这个游戏可能 10s 后才结束。现在这个动作到底对最后游戏是否能赢有无帮助,我们其实是不清楚的。这里我们就面临**延迟奖励(delayed reward)**的问题,延迟奖励使得训练网络非常困难。 + +
+ +
+
图 1.4 强化学习:玩Breakout
+ +强化学习和监督学习的区别如下。 + +(1)强化学习输入的样本是序列数据,而不像监督学习里面样本都是独立的。 + +(2)学习器并没有告诉我们每一步正确的动作应该是什么,学习器需要自己去发现哪些动作可以带来 最多的奖励,只能通过不停地尝试来发现最有利的动作。 + +(3)智能体获得自己能力的过程,其实是不断地试错探索(trial-and-error exploration)的过程。探索 (exploration)和利用(exploitation)是强化学习里面非常核心的问题。其中,探索指尝试一些新的动作, 这些新的动作有可能会使我们得到更多的奖励,也有可能使我们“一无所有”;利用指采取已知的可以获得最多奖励的动作,重复执行这个动作,因为我们知道这样做可以获得一定的奖励。因此,我们需要在探索和利用之间进行权衡,这也是在监督学习里面没有的情况。 + +(4)在强化学习过程中,没有非常强的监督者(supervisor),只有**奖励信号(reward signal**),并且奖励信号是延迟的,即环境会在很久以后告诉我们之前我们采取的动作到底是不是有效的。因为我们没有得 到即时反馈,所以智能体使用强化学习来学习就非常困难。当我们采取一个动作后,如果我们使用监督学习,我们就可以立刻获得一个指导,比如,我们现在采取了一个错误的动作,正确的动作应该是什么。而在强化学习里面,环境可能会告诉我们这个动作是错误的,但是它并没有告诉我们正确的动作是什么。而且更困难的是,它可能是在一两分钟过后告诉我们这个动作是错误的。所以这也是强化学习和监督学习不同的地方。 + +通过与监督学习的比较,我们可以总结出强化学习的一些特征。 + +(1)强化学习会试错探索,它通过探索环境来获取对环境的理解。 + +(2)强化学习智能体会从环境里面获得延迟的奖励。 + +(3)在强化学习的训练过程中,时间非常重要。因为我们得到的是有时间关联的数据(sequential data), 而不是独立同分布的数据。在机器学习中,如果观测数据有非常强的关联,会使得训练非常不稳定。这也是为什么在监督学习中,我们希望数据尽量满足独立同分布,这样就可以消除数据之间的相关性。 + +(4)智能体的动作会影响它随后得到的数据,这一点是非常重要的。在训练智能体的过程中,很多时 候我们也是通过正在学习的智能体与环境交互来得到数据的。所以如果在训练过程中,智能体不能保持稳定,就会使我们采集到的数据非常糟糕。我们通过数据来训练智能体,如果数据有问题,整个训练过程就会失败。所以在强化学习里面一个非常重要的问题就是,怎么让智能体的动作一直稳定地提升。 + +### 1.1.2 强化学习的例子 + +为什么我们关注强化学习,其中非常重要的一个原因就是强化学习得到的模型可以有超人类的表现。 监督学习获取的监督数据,其实是人来标注的,比如 ImageNet 的图片的标签都是人类标注的。因此我们 可以确定监督学习算法的上限(upper bound)就是人类的表现,标注结果决定了它的表现永远不可能超越人类。但是对于强化学习,它在环境里面自己探索,有非常大的潜力,它可以获得超越人类的能力的表现,比如 DeepMind 的 AlphaGo 这样一个强化学习的算法可以把人类顶尖的棋手打败。 + +这里给大家举一些在现实生活中强化学习的例子。 + +(1)在自然界中,羚羊其实也在做强化学习。它刚刚出生的时候,可能都不知道怎么站立,然后它通过试错,一段时间后就可以跑得很快,可以适应环境。 + +(2)我们也可以把股票交易看成强化学习的过程。我们可以不断地买卖股票,然后根据市场给出的反馈来学会怎么去买卖可以让我们的奖励最大化。 + +(3)玩雅达利游戏或者其他电脑游戏,也是一个强化学习的过程,我们可以通过不断试错来知道怎么 玩才可以通关。 + +图 1.5 所示为强化学习的一个经典例子,即雅达利的 Pong 游戏。游戏中右边的选手把球拍到左边, 然后左边的选手需要把球拍到右边。训练好的强化学习智能体和正常的选手有区别:强化学习的智能体会一直做无意义的振动,而正常的选手不会做出这样的动作。 + +
+ +
+
图 1.5 Pong游戏
+ +在 Pong 游戏里面,其实只有两个动作:往上或者往下。如图 1.6 所示,如果强化学习通过学习一个策略网络来进行分类,那么策略网络会输入当前帧的图片,输出所有决策的可能性,比如往上移动的概率。 + +
+ +
+
图 1.6 强化学习玩 Pong
+ +如图 1.7 所示,对于监督学习,我们可以直接告诉智能体正确动作的标签是什么。但在 Pong 游戏中, 我们并不知道它的正确动作的标签是什么。 + +
+ +
+
图 1.7 监督学习玩 Pong
+ +在强化学习里面,我们让智能体尝试玩 Pong 游戏,对动作进行采样,直到游戏结束,然后对每个动作进行惩罚。图 1.8 所示为预演(rollout)的一个过程。预演是指我们从当前帧对动作进行采样,生成很多局游戏。我们将当前的智能体与环境交互,会得到一系列观测。每一个观测可看成一个轨迹(trajectory)。 轨迹就是当前帧以及它采取的策略,即状态和动作的序列: +$$ +\tau=\left(s_{0}, a_{0}, s_{1}, a_{1}, \ldots\right) +$$ +最后结束时,我们会知道到底有没有把这个球拍到对方区域,对方有没有接住,我们是赢了还是输了。我们可以通过观测序列以及最终奖励(eventual reward)来训练智能体,使它尽可能地采取可以获得最终奖励的动作。一场游戏称为一个**回合(episode)**或者**试验(trial)**。 + +
+ +
+
图 1.8 可能的预演序列
+ +### 1.1.3 强化学习的历史 + +强化学习是有一定的历史的,早期的强化学习,我们称其为标准强化学习。最近业界把强化学习与深度学习结合起来,就形成了深度强化学习(deep reinforcement learning),因此,深度强化学习 = 深度学习 + 强化学习。我们可将标准强化学习和深度强化学习类比于传统的计算机视觉和深度计算机视觉。 + +如图 1.9a 所示,传统的计算机视觉由两个过程组成。 + +(1)给定一张图片,我们先要提取它的特征,使用一些设计好的特征,比如方向梯度直方图(histogram of oriental gradient,HOG)、可变现的组件模型(deformable part model,DPM)。 + +(2)提取这些特征后,我们再单独训练一个分类器。这个分类器可以是支持向量机(support vector machine,SVM)或 Boosting,然后就可以辨别这张图片是狗还是猫。 + + +
+ +
+
(a)传统的计算机视觉
+
+ +
+
(b)深度计算机视觉
+ +
图 1.9 传统的计算机视觉与深度计算机视觉的区别
+ +2012年,Krizhevsky等人提出了AlexNet,AlexNet在ImageNet分类比赛中取得冠军,迅速引起了人们对于卷积神经网络的广泛关注。 +大家就把特征提取以及分类两者合到一块儿去了,就是训练一个神经网络。这个神经网络既可以做特征提取,也可以做分类,它可以实现端到端训练,如图 1.9b 所示,它的参数可以在每一个阶段都得到极大的优化,这是一个非常重要的突破。 + +我们可以把神经网络放到强化学习里面。 + +* 标准强化学习:比如 TD-Gammon 玩 Backgammon 游戏的过程,其实就是设计特征,然后训练价值函数的过程,如图 1.10a 所示。标准强化学习先设计很多特征,这些特征可以描述现在整个状态。 得到这些特征后,我们就可以通过训练一个分类网络或者分别训练一个价值估计函数来采取动作。 + +* 深度强化学习:自从我们有了深度学习,有了神经网络,就可以把智能体玩游戏的过程改进成一个端到端训练(end-to-end training)的过程,如图 1.10b 所示。我们不需要设计特征,直接输入状态就可以输出动作。我们可以用一个神经网络来拟合价值函数或策略网络,省去特征工程(feature engineering)的过程。 + +
+ +
+
(a)标准强化学习
+
+ +
+
(b)深度强化学习
+
图 1.10 标准强化学习与深度强化学习的区别
+ +### 1.1.4 强化学习的应用 + +为什么强化学习在这几年有很多的应用,比如玩游戏以及机器人的一些应用,并且可以击败人类的顶尖棋手呢?这有如下几点原因。首先,我们有了更多的算力(computation power),有了更多的 GPU,可 以更快地做更多的试错尝试。其次,通过不同尝试,智能体在环境里面获得了很多信息,然后可以在环境里面取得很大的奖励。最后,我们通过端到端训练把特征提取和价值估计或者决策一起优化,这样就可以 得到一个更强的决策网络。 + +接下来介绍一些强化学习里面比较有意思的例子,如图 1.11 所示。 + +(1)[DeepMind 研发的走路的智能体](https://www.youtube.com/watch?v=gn4nRCC9TwQ)。这个智能体往前走一步,就会得到一个奖励。这个智能体有不同的形态,可以学到很多有意思的功能。比如,像人一样的智能体学习怎么在曲折的道路上往前走。结果 非常有意思,这个智能体会把手举得非常高,因为举手可以让它的身体保持平衡,它就可以更快地在环境里面往前走。而且我们也可以增加环境的难度,加入一些扰动,智能体就会变得更鲁棒。 + +(2)[机械臂抓取](https://ai.googleblog.com/2016/03/deep-learning-for-robots-learning-from.html)。因为我们把强化学习应用到机械臂自动抓取需要大量的预演,所以我们可以使用多个机械臂进行训练。分布式系统可以让机械臂尝试抓取不同的物体,盘子里面物体的形状是不同的,这样 就可以让机械臂学到一个统一的动作,然后针对不同的抓取物都可以使用最优的抓取算法。因为抓取的物 体形状的差别很大,所以使用一些传统的抓取算法不能把所有物体都抓起来。传统的抓取算法对每一个物 体都需要建模,这样是非常费时的。但通过强化学习,我们可以学到一个统一的抓取算法,其适用于不同 的物体。 + +(3)[OpenAI 的机械臂翻魔方](https://www.youtube.com/watch?v=jwSbzNHGflM)。OpenAI 在 2018 年的时候设计了一款带有“手指”的机械臂,它可以通过翻动手指使得手中的木块达到预期的设定。人的手指其实非常灵活,怎么使得机械臂的手指也具有这 样灵活的能力一直是个问题。OpenAI 先在一个虚拟环境里面使用强化学习对智能体进行训练,再把它应 用到真实的机械臂上。这在强化学习里面是一种比较常用的做法,即我们先在虚拟环境里面得到一个很好 的智能体,然后把它应用到真实的机器人中。这是因为真实的机械臂通常非常容易坏,而且非常贵,一般 情况下没办法大批量地购买。OpenAI 在 2019 年对其机械臂进行了进一步的改进,这个机械臂在改进后 可以玩魔方了。 + +(4)[穿衣服的智能体](https://www.youtube.com/watch?v=ixmE5nt2o88)。很多时候我们要在电影或者一些动画中实现人穿衣服的场景,通过手写执行命令让机器人穿衣服非常困难,穿衣服也是一种非常精细的操作。我们可以训练强化学习智能体来实现穿衣 服功能。我们还可以在里面加入一些扰动,智能体可以抵抗扰动。可能会有失败的情况(failure case)出 现,这样智能体就穿不进去衣服。 + +
+ +
+
图 1.11 强化学习例子
+ +## 1.2 序列决策 + +### 1.2.1 智能体与环境 + +接下来我们介绍**序列决策(sequential decision making)**过程。强化学习研究的问题是智能体与环境交互的问题,图 1.12 左边的智能体一直在与图 1.12 右边的环境进行交互。智能体把它的动作输出给环境,环境取得这个动作后会进行下一步,把下一步的观测与这个动作带来的奖励返还给智能体。这样的交互会产生很多观测,智能体的目的是从这些观测之中学到能最大化奖励的策略。 + +
+ +
+
图 1.12 智能体和环境
+ +### 1.2.2 奖励 + +奖励是由环境给的一种标量的反馈信号(scalar feedback signal),这种信号可显示智能体在某一步采取某个策略的表现如何。强化学习的目的就是最大化智能体可以获得的奖励,智能体在环境里面存在的目 的就是最大化它的期望的累积奖励(expected cumulative reward)。不同的环境中,奖励也是不同的。这里给大家举一些奖励的例子。 + +(1)比如一个象棋选手,他的目的是赢棋,在最后棋局结束的时候,他就会得到一个正奖励(赢)或者负奖励(输)。 + +(2)在股票管理里面,奖励由股票获取的奖励与损失决定。 + +(3)在玩雅达利游戏的时候,奖励就是增加或减少的游戏的分数,奖励本身的稀疏程度决定了游戏的难度。 + +### 1.2.3 序列决策 + +在一个强化学习环境里面,智能体的目的就是选取一系列的动作来最大化奖励,所以这些选取的动作 必须有长期的影响。但在这个过程里面,智能体的奖励其实是被延迟了的,就是我们现在选取的某一步动作,可能要等到很久后才知道这一步到底产生了什么样的影响。如图 1.13 所示,在玩雅达利的 Pong 游戏时,我们可能只有到最后游戏结束时,才知道球到底有没有被击打过去。过程中我们采取的上升(up)或 下降(down)动作,并不会直接产生奖励。强化学习里面一个重要的课题就是近期奖励和远期奖励的权衡 (trade-off),研究怎么让智能体取得更多的远期奖励。 + +在与环境的交互过程中,智能体会获得很多观测。针对每一个观测,智能体会采取一个动作,也会得到一个奖励。所以历史是观测、动作、奖励的序列: +$$ +H_{t}=o_{1}, a_{1}, r_{1}, \ldots, o_{t}, a_{t}, r_{t} +$$ + +智能体在采取当前动作的时候会依赖于它之前得到的历史,所以我们可以把整个游戏的状态看成关于这个历史的函数: + +$$ +S_{t}=f\left(H_{t}\right) +$$ + +
+ +
+
图 1.13 玩Pong游戏
+ + +Q:状态和观测有什么关系? + +A:**状态**是对世界的完整描述,不会隐藏世界的信息。**观测**是对状态的部分描述,可能会遗漏一些信息。在深度强化学习中,我们几乎总是用实值的向量、矩阵或者更高阶的张量来表示状态和观测。例如, 我们可以用 RGB 像素值的矩阵来表示一个视觉的观测,可以用机器人关节的角度和速度来表示一个机器 人的状态。 + +环境有自己的函数$s_{t}^{e}=f^{e}\left(H_{t}\right)$ 来更新状态,在智能体的内部也有一个函数$s_{t}^{a}=f^{a}\left(H_{t}\right)$来更新状 态。当智能体的状态与环境的状态等价的时候,即当智能体能够观察到环境的所有状态时,我们称这个环境是完全可观测的(fully observed)。在这种情况下面,强化学习通常被建模成一个马尔可夫决策过程 (Markov decision process,MDP)的问题。在马尔可夫决策过程中,$o_{t}=s_{t}^{e}=s_{t}^{a}$。 + +但是有一种情况是智能体得到的观测并不能包含环境运作的所有状态,因为在强化学习的设定里面, 环境的状态才是真正的所有状态。比如智能体在玩 black jack 游戏,它能看到的其实是牌面上的牌。或者在 玩雅达利游戏的时候,观测到的只是当前电视上面这一帧的信息,我们并没有得到游戏内部里面所有的运 作状态。也就是当智能体只能看到部分的观测,我们就称这个环境是部分可观测的(partially observed)。 在这种情况下,强化学习通常被建模成**部分可观测马尔可夫决策过程(partially observable Markov decision process, POMDP)**的问题。部分可观测马尔可夫决策过程是马尔可夫决策过程的一种泛化。 部分可观测马尔可夫决策过程依然具有马尔可夫性质,但是假设智能体无法感知环境的状态,只能知道 部分观测值。比如在自动驾驶中,智能体只能感知传感器采集的有限的环境信息。部分可观测马尔可夫决策过程可以用一个七元组描述:$(S,A,T,R,\Omega,O,\gamma)$。其中 $S$ 表示状态空间,为隐变量,$A$ 为动作空间,$T(s'|s,a)$ 为状态转移概率,$R$ 为奖励函数,$\Omega(o|s,a)$ 为观测概率,$O$ 为观测空间,$\gamma$ 为折扣系数。 + +## 1.3 动作空间 + +不同的环境允许不同种类的动作。在给定的环境中,有效动作的集合经常被称为动作空间(action space)。像雅达利游戏和围棋(Go)这样的环境有离散动作空间(discrete action space),在这个动作 空间里,智能体的动作数量是有限的。在其他环境,比如在物理世界中控制一个智能体,在这个环境中就有连续动作空间(continuous action space)。在连续动作空间中,动作是实值的向量。 + +例如,走迷宫机器人如果只有往东、往南、往西、往北这 4 种移动方式,则其动作空间为离散动作空 间;如果机器人可以向 360 度中的任意角度进行移动,则其动作空间为连续动作空间。 + +## 1.4 强化学习智能体的组成成分和类型 + +对于一个强化学习智能体,它可能有一个或多个如下的组成成分。 + +* **策略(policy)**。智能体会用策略来选取下一步的动作。 + +* **价值函数(value function)**。我们用价值函数来对当前状态进行评估。价值函数用于评估智能体进 入某个状态后,可以对后面的奖励带来多大的影响。价值函数值越大,说明智能体进入这个状态越有利。 + +* **模型(model)**。模型表示智能体对环境的状态进行理解,它决定了环境中世界的运行方式。 下面我们深入了解这 3 个组成部分的细节。 + +### 1.4.1 策略 +策略是智能体的动作模型,它决定了智能体的动作。它其实是一个函数,用于把输入的状态变成动作。策略可分为两种:随机性策略和确定性策略。 + +**随机性策略(stochastic policy)**就是 $\pi$ 函数,即$\pi(a | s)=p\left(a_{t}=a | s_{t}=s\right)$。输入一个状态 $s$,输出一个概率。 +这个概率是智能体所有动作的概率,然后对这个概率分布进行采样,可得到智能体将采取的动作。比如可能是有 0.7 的概率往左,0.3 的概率往右,那么通过采样就可以得到智能体将采取的动作。 + +**确定性策略(deterministic policy)**就是智能体直接采取最有可能的动作,即 $a^{*}=\underset{a}{\arg \max} \pi(a \mid s)$。 + + +如图 1.14 所示,从雅达利游戏来看,策略函数的输入就是游戏的一帧,它的输出决定智能体向左移动或者向右移动。 + +
+ +
+
图 1.14 策略函数
+ +通常情况下,强化学习一般使用随机性策略,随机性策略有很多优点。比如,在学习时可以通过引入一定的随机性来更好地探索环境; +随机性策略的动作具有多样性,这一点在多个智能体博弈时非常重要。采用确定性策略的智能体总是对同样的状态采取相同的动作,这会导致它的策略很容易被对手预测。 + +### 1.4.2 价值函数 +价值函数的值是对未来奖励的预测,我们用它来评估状态的好坏。 +价值函数里面有一个**折扣因子(discount factor)**,我们希望在尽可能短的时间里面得到尽可能多的奖励。比如现在给我们两个选择:10天后给我们100块钱或者现在给我们100块钱。我们肯定更希望现在就给我们 100 块钱,因为我们可以把这 100 块钱存在银行里面,这样就会有一些利息。因此,我们可以把折扣因子放到价值函数的定义里面,价值函数的定义为 + +$$ +V_{\pi}(s) \doteq \mathbb{E}_{\pi}\left[G_{t} \mid s_{t}=s\right]=\mathbb{E}_{\pi}\left[\sum_{k=0}^{\infty} \gamma^{k} r_{t+k+1} \mid s_{t}=s\right], \text{对于所有的} s \in S +$$ + +期望 $\mathbb{E}_{\pi}$ 的下标是 $\pi$ 函数,$\pi$ 函数的值可反映在我们使用策略 $\pi$ 的时候,到底可以得到多少奖励。 + +我们还有一种价值函数:Q 函数。Q 函数里面包含两个变量:状态和动作。其定义为 +$$ +Q_{\pi}(s, a) \doteq \mathbb{E}_{\pi}\left[G_{t} \mid s_{t}=s, a_{t}=a\right]=\mathbb{E}_{\pi}\left[\sum_{k=0}^{\infty} \gamma^{k} r_{t+k+1} \mid s_{t}=s, a_{t}=a\right] +$$ +所以我们未来可以获得奖励的期望取决于当前的状态和当前的动作。Q 函数是强化学习算法里面要学习的一个函数。因为当我们得到 Q 函数后,进入某个状态要采取的最优动作可以通过 Q 函数得到。 + +### 1.4.3 模型 +第3个组成部分是模型,模型决定了下一步的状态。下一步的状态取决于当前的状态以及当前采取的动作。它由状态转移概率和奖励函数两个部分组成。状态转移概率即 +$$ +p_{s s^{\prime}}^{a}=p\left(s_{t+1}=s^{\prime} \mid s_{t}=s, a_{t}=a\right) +$$ + +奖励函数是指我们在当前状态采取了某个动作,可以得到多大的奖励,即 +$$ +R(s,a)=\mathbb{E}\left[r_{t+1} \mid s_{t}=s, a_{t}=a\right] +$$ +当我们有了策略、价值函数和模型3个组成部分后,就形成了一个**马尔可夫决策过程(Markov decision process)**。如图 1.15 所示,这个决策过程可视化了状态之间的转移以及采取的动作。 + +
+ +
+
图 1.15 马尔可夫决策过程
+ +我们来看一个走迷宫的例子。如图 1.16 所示,要求智能体从起点(start)开始,然后到达终点(goal)的位置。每走一步,我们就会得到 $-$1 的奖励。我们可以采取的动作是往上、下、左、右走。我们用现在智能体所在的位置来描述当前状态。 + + +
+ +
+
图 1.16 走迷宫的例子
+ + +我们可以用不同的强化学习方法来解这个环境。 +如果我们采取基于策略的强化学习(policy-based RL)方法,当学习好了这个环境后,在每一个状态,我们都会得到一个最佳的动作。如图 1.17 所示,比如我们现在在起点位置,我们知道最佳动作是往右走;在第二格的时候,得到的最佳动作是往上走;第三格是往右走......通过最佳的策略,我们可以最快地到达终点。 + + +
+ +
+
图 1.17 使用基于策略的强化学习方法得到的结果
+ + +如果换成基于价值的强化学习(value-based RL)方法,利用价值函数作为导向,我们就会得到另外一种表征,每一个状态会返回一个价值。如图 1.18 所示,比如我们在起点位置的时候,价值是 $-$16,因为我们最快可以 16 步到达终点。因为每走一步会减1,所以这里的价值是 $-$16。 +当我们快接近终点的时候,这个数字变得越来越大。在拐角的时候,比如现在在第二格,价值是$-$15,智能体会看上、下两格,它看到上面格子的价值变大了,变成 $-$14 了,下面格子的价值是 $-$16,那么智能体就会采取一个往上走的动作。所以通过学习的价值的不同,我们可以抽取出现在最佳的策略。 + +
+ +
+
图 1.18 使用基于价值的强化学习方法得到的结果
+ + +### 1.4.4 强化学习智能体的类型 +#### 1.基于价值的智能体与基于策略的智能体 + +根据智能体学习的事物不同,我们可以把智能体进行归类。**基于价值的智能体(value-based agent)**显式地学习价值函数,隐式地学习它的策略。策略是其从学到的价值函数里面推算出来的。**基于策略的智能体(policy-based agent)**直接学习策略,我们给它一个状态,它就会输出对应动作的概率。基于策略的智能体并没有学习价值函数。把基于价值的智能体和基于策略的智能体结合起来就有了**演员-评论员智能体(actor-critic agent)**。这一类智能体把策略和价值函数都学习了,然后通过两者的交互得到最佳的动作。 + +Q: 基于策略和基于价值的强化学习方法有什么区别? + +A: 对于一个状态转移概率已知的马尔可夫决策过程,我们可以使用动态规划算法来求解。从决策方式来看,强化学习又可以划分为基于策略的方法和基于价值的方法。决策方式是智能体在给定状态下从动作集合中选择一个动作的依据,它是静态的,不随状态变化而变化。 +在基于策略的强化学习方法中,智能体会制定一套动作策略(确定在给定状态下需要采取何种动作),并根据这个策略进行操作。强化学习算法直接对策略进行优化,使制定的策略能够获得最大的奖励。 +而在基于价值的强化学习方法中,智能体不需要制定显式的策略,它维护一个价值表格或价值函数,并通过这个价值表格或价值函数来选取价值最大的动作。基于价值迭代的方法只能应用在不连续的、离散的环境下(如围棋或某些游戏领域),对于动作集合规模庞大、动作连续的场景(如机器人控制领域),其很难学习到较好的结果(此时基于策略迭代的方法能够根据设定的策略来选择连续的动作)。 +基于价值的强化学习算法有Q学习(Q-learning)、 Sarsa 等,而基于策略的强化学习算法有策略梯度(Policy Gradient,PG)算法等。此外,演员-评论员算法同时使用策略和价值评估来做出决策。其中,智能体会根据策略做出动作,而价值函数会对做出的动作给出价值,这样可以在原有的策略梯度算法的基础上加速学习过程,取得更好的效果。 + +#### 2.有模型强化学习智能体与免模型强化学习智能体 + + +另外,我们可以通过智能体到底有没有学习环境模型来对智能体进行分类。 +**有模型(model-based)**强化学习智能体通过学习状态的转移来采取动作。 +**免模型(model-free)**强化学习智能体没有去直接估计状态的转移,也没有得到环境的具体转移变量,它通过学习价值函数和策略函数进行决策。免模型强化学习智能体的模型里面没有环境转移的模型。 + +我们可以用马尔可夫决策过程来定义强化学习任务,并将其表示为四元组 $$,即状态集合、动作集合、状态转移函数和奖励函数。如果这个四元组中所有元素均已知,且状态集合和动作集合在有限步数内是有限集,则智能体可以对真实环境进行建模,构建一个虚拟世界来模拟真实环境中的状态和交互反应。 +具体来说,当智能体知道状态转移函数 $P(s_{t+1}|s_t,a_t)$ 和奖励函数 $R(s_t,a_t)$ 后,它就能知道在某一状态下执行某一动作后能带来的奖励和环境的下一状态,这样智能体就不需要在真实环境中采取动作,直接在虚拟世界中学习和规划策略即可。这种学习方法称为**有模型强化学习**。 +有模型强化学习的流程如图 1.19 所示。 + + +
+ +
+
图 1.19 有模型强化学习流程
+ +然而在实际应用中,智能体并不是那么容易就能知晓马尔可夫决策过程中的所有元素的。通常情况下,状态转移函数和奖励函数很难估计,甚至连环境中的状态都可能是未知的,这时就需要采用免模型强化学习。免模型强化学习没有对真实环境进行建模,智能体只能在真实环境中通过一定的策略来执行动作,等待奖励和状态迁移,然后根据这些反馈信息来更新动作策略,这样反复迭代直到学习到最优策略。 + +Q:有模型强化学习和免模型强化学习有什么区别? + +A:针对是否需要对真实环境建模,强化学习可以分为有模型强化学习和免模型强化学习。有模型强化学习是指根据环境中的经验,构建一个虚拟世界,同时在真实环境和虚拟世界中学习;免模型强化学习是指不对环境进行建模,直接与真实环境进行交互来学习到最优策略。 + +总之,有模型强化学习相比免模型强化学习仅仅多出一个步骤,即对真实环境进行建模。因此,一些有模型的强化学习方法,也可以在免模型的强化学习方法中使用。在实际应用中,如果不清楚该用有模型强化学习还是免模型强化学习,可以先思考在智能体执行动作前,是否能对下一步的状态和奖励进行预测,如果能,就能够对环境进行建模,从而采用有模型学习。 + +免模型强化学习通常属于数据驱动型方法,需要大量的采样来估计状态、动作及奖励函数,从而优化动作策略。例如,在雅达利平台上的《太空侵略者》游戏中,免模型的深度强化学习需要大约两亿帧游戏画面才能学到比较理想的效果。相比之下,有模型的深度强化学习可以在一定程度上缓解训练数据匮乏的问题,因为智能体可以在虚拟世界中进行训练。 +免模型学习的泛化性要优于有模型强化学习,原因是有模型强化学习算需要对真实环境进行建模,并且虚拟世界与真实环境之间可能还有差异,这限制了有模型强化学习算法的泛化性。 +有模型的强化学习方法可以对环境建模,使得该类方法具有独特魅力,即“想象能力”。在免模型强化学习中,智能体只能一步一步地采取策略,等待真实环境的反馈;有模型强化学习可以在虚拟世界中预测出将要发生的事,并采取对自己最有利的策略。 + +目前,大部分深度强化学习方法都采用了免模型强化学习,这是因为:免模型强化学习更为简单、直观且有丰富的开源资料,如 AlphaGo 系列都采用免模型强化学习;在目前的强化学习研究中,大部分情况下环境都是静态的、可描述的,智能体的状态是离散的、可观察的(如雅达利游戏平台),这种相对简单、确定的问题并不需要评估状态转移函数和奖励函数,可直接采用免模型强化学习,使用大量的样本进行训练就能获得较好的效果。 + +如图 1.20 所示,我们可以把几类模型放到同一个图里面。图 1.20 有3个组成成分:价值函数、策略和模型。按一个智能体具有三者中的三者、两者或一者的情况可以把它分成很多类。 + + +
+ +
+
图 1.20 强化学习智能体的类型
+ +## 1.5 学习与规划 + +学习(learning)和规划(planning)是序列决策的两个基本问题。 +如图 1.21 所示,在强化学习中,环境初始时是未知的,智能体不知道环境如何工作,它通过不断地与环境交互,逐渐改进策略。 + +
+ +
+
图 1.21 学习
+ + +如图 1.22 所示,在规划中,环境是已知的,智能体被告知了整个环境的运作规则的详细信息。智能体能够计算出一个完美的模型,并且在不需要与环境进行任何交互的时候进行计算。智能体不需要实时地与环境交互就能知道未来环境,只需要知道当前的状态,就能够开始思考,来寻找最优解。 + +在图 1.22 所示的游戏中,规则是确定的,我们知道选择左之后环境将会产生什么变化。我们完全可以通过已知的规则,来在内部模拟整个决策过程,无需与环境交互。 +一个常用的强化学习问题解决思路是,先学习环境如何工作,也就是了解环境工作的方式,即学习得到一个模型,然后利用这个模型进行规划。 + + +
+ +
+
图 1.22 规划
+ +## 1.6 探索和利用 + +在强化学习里面,探索和利用是两个很核心的问题。 +探索即我们去探索环境,通过尝试不同的动作来得到最佳的策略(带来最大奖励的策略)。 +利用即我们不去尝试新的动作,而是采取已知的可以带来很大奖励的动作。 +在刚开始的时候,强化学习智能体不知道它采取了某个动作后会发生什么,所以它只能通过试错去探索,所以探索就是通过试错来理解采取的动作到底可不可以带来好的奖励。利用是指我们直接采取已知的可以带来很好奖励的动作。所以这里就面临一个权衡问题,即怎么通过牺牲一些短期的奖励来理解动作,从而学习到更好的策略。 + +下面举一些探索和利用的例子。 +以选择餐馆为例,利用是指我们直接去我们最喜欢的餐馆,因为我们去过这个餐馆很多次了,所以我们知道这里面的菜都非常可口。 +探索是指我们用手机搜索一个新的餐馆,然后去尝试它的菜到底好不好吃。我们有可能对这个新的餐馆感到非常不满意,这样钱就浪费了。 +以做广告为例,利用是指我们直接采取最优的广告策略。探索是指我们换一种广告策略,看看这个新的广告策略可不可以得到更好的效果。 +以挖油为例,利用是指我们直接在已知的地方挖油,这样可以确保挖到油。 +探索是指我们在一个新的地方挖油,这样就有很大的概率可能不能发现油田,但也可能有比较小的概率可以发现一个非常大的油田。 +以玩游戏为例,利用是指我们总是采取某一种策略。比如,我们玩《街头霸王》游戏的时候,采取的策略可能是蹲在角落,然后一直出脚。这个策略很可能可以奏效,但可能遇到特定的对手就会失效。 +探索是指我们可能尝试一些新的招式,有可能我们会放出“大招”来,这样就可能“一招毙命”。 + +与监督学习任务不同,强化学习任务的最终奖励在多步动作之后才能观察到,这里我们不妨先考虑比较简单的情形:最大化单步奖励,即仅考虑一步动作。需注意的是,即便在这样的简单情形下,强化学习仍与监督学习有显著不同,因为智能体需通过试错来发现各个动作产生的结果,而没有训练数据告诉智能体应当采取哪个动作。 + +想要最大化单步奖励需考虑两个方面:一是需知道每个动作带来的奖励,二是要执行奖励最大的动作。若每个动作对应的奖励是一个确定值,那么尝试遍所有的动作便能找出奖励最大的动作。然而,更一般的情形是,一个动作的奖励值是来自一个概率分布,仅通过一次尝试并不能确切地获得平均奖励值。 + +实际上,单步强化学习任务对应于一个理论模型,即**$K$-臂赌博机($K$-armed bandit)**。 $K$-臂赌博机也被称为**多臂赌博机(multi-armed bandit)** 。如图 1.23 所示,$K$-臂赌博机有 $K$ 个摇臂,赌徒在投入一个硬币后可选择按下其中一个摇臂,每个摇臂以一定的概率吐出硬币,但这个概率赌徒并不知道。赌徒的目标是通过一定的策略最大化自己的奖励,即获得最多的硬币。 +若仅为获知每个摇臂的期望奖励,则可采用**仅探索(exploration-only)法**:将所有的尝试机会平均分配给每个摇臂(即轮流按下每个摇臂),最后以每个摇臂各自的平均吐币概率作为其奖励期望的近似估计。若仅为执行奖励最大的动作,则可采用**仅利用(exploitation-only)法**:按下目前最优的(即到目前为止平均奖励最大的)摇臂,若有多个摇臂同为最优,则从中随机选取一个。 + +显然,仅探索法能很好地估计每个摇臂的奖励,却会失去很多选择最优摇臂的机会;仅利用法则相反,它没有很好地估计摇臂期望奖励,很可能经常选不到最优摇臂。因此,这两种方法都难以使最终的累积奖励最大化。 + +事实上,探索(估计摇臂的优劣)和利用(选择当前最优摇臂)这两者是矛盾的,因为尝试次数(总投币数)有限,加强了一方则自然会削弱另一方,这就是强化学习所面临的**探索-利用窘境(exploration-exploitation dilemma)**。显然,想要累积奖励最大,则必须在探索与利用之间达成较好的折中。 + +
+ +
+
图 1.23 K-臂赌博机图示
+ +## 1.7 强化学习实验 +强化学习是一个理论与实践相结合的机器学习分支,我们不仅要理解它算法背后的一些数学原理,还要通过上机实践实现算法。在很多实验环境里面去探索算法能不能得到预期效果也是一个非常重要的过程。 + +我们可以使用 Python 和深度学习的一些包来实现强化学习算法。现在有很多深度学习的包可以使用,比如 PyTorch、TensorFlow、Keras,熟练使用其中的两三种,就可以实现非常多的功能。所以我们并不需要从头去“造轮子”。 +### 1.7.1 Gym +OpenAI是一家非营利性的人工智能研究公司,其公布了非常多的学习资源以及算法资源。其之所以叫作 OpenAI,他们把所有开发的算法都进行了开源。 +如图 1.24 所示,OpenAI 的 **Gym库**是一个环境仿真库,里面包含很多现有的环境。针对不同的场景,我们可以选择不同的环境。离散控制场景(输出的动作是可数的,比如Pong游戏中输出的向上或向下动作)一般使用雅达利环境评估;连续控制场景(输出的动作是不可数的,比如机器人走路时不仅有方向,还有角度,角度就是不可数的,是一个连续的量 )一般使用 MuJoCo 环境评估。**Gym Retro**是对 Gym 环境的进一步扩展,包含更多的游戏。 + + +
+ +
+
图 1.24 OpenAI 的 Gym 库
+ + +我们可以通过 pip 来安装 Gym 库,由于 Gym 库 0.26.0 及其之后的版本对之前的代码不兼容,所以我们安装 0.26.0 之前的 Gym,比如 0.25.2。 +```bash +pip install gym==0.25.2 +``` +此外,为了显示图形界面,我们还需要安装 pygame 库。 +```bash +pip install pygame +``` + +在 Python 环境中导入Gym库,如果不报错,就可以认为 Gym 库安装成功。 + + +```bash +$python +>>>import gym +``` + +比如我们现在安装了Gym库,就可以直接调入Taxi-v3的环境。初始化这个环境后,我们就可以进行交互了。智能体得到某个观测后,它就会输出一个动作。这个动作会被环境拿去执行某个步骤 ,然后环境就会往前走一步,返回新的观测、奖励以及一个 flag 变量 done,done 决定这个游戏是不是结束了。我们通过几行代码就可实现强化学习的框架: + +```python +import gym +env = gym.make("Taxi-v3") +observation = env.reset() +agent = load_agent() +for step in range(100): + action = agent(observation) + observation, reward, done, info = env.step(action) +``` + +>上面这段代码只是示例,其目的是让读者了解强化学习算法代码实现的框架,并非完整代码,load\_agent 函数并未定义,所以运行这段代码会报错。 + + +如图 1.25 所示,Gym 库里面有很多经典的控制类游戏。比如 Acrobot需要让一个双连杆机器人立起来;CartPole需要通过控制一辆小车,让杆立起来;MountainCar需要通过前后移动车,让它到达旗帜的位置。在刚开始测试强化学习的时候,我们可以选择这些简单环境,因为强化学习在这些环境中可以在一两分钟之内见到效果。 + +
+ +
+
图1.25 经典控制问题
+ + +大家可以点[这个链接](https://www.gymlibrary.dev/environments/classic_control/)看一看这些环境。在刚开始测试强化学习的时候,可以选择这些简单环境,因为这些环境可以在一两分钟之内见到一个效果。 + +如图 1.26 所示,CartPole-v0 环境有两个动作:将小车向左移动和将小车向右移动。我们还可以得到观测:小车当前的位置,小车当前往左、往右移的速度,杆的角度以及杆的最高点(顶端)的速度。 +观测越详细,我们就可以更好地描述当前所有的状态。这里有奖励的定义,如果能多走一步,我们就会得到一个奖励(奖励值为1),所以我们需要存活尽可能多的时间来得到更多的奖励。当杆的角度大于某一个角度(没能保持平衡),或者小车的中心到达图形界面窗口的边缘,或者累积步数大于200,游戏就结束了。所以智能体的目的是控制杆,让它尽可能地保持平衡以及尽可能保持在环境的中央。 + + +
+ +
+
图 1.26 CartPole-v0的例子
+ + + +```python +import gym # 导入 Gym 的 Python 接口环境包 +env = gym.make('CartPole-v0') # 构建实验环境 +env.reset() # 重置一个回合 +for _ in range(1000): + env.render() # 显示图形界面 + action = env.action_space.sample() # 从动作空间中随机选取一个动作 + env.step(action) # 用于提交动作,括号内是具体的动作 +env.close() # 关闭环境 +``` + +注意:如果绘制了实验的图形界面窗口,那么关闭该窗口的最佳方式是调用 env.close()。试图直接关闭图形界面窗口可能会导致内存不能释放,甚至会导致死机。 + +当我们执行这段代码时,机器人会驾驶着小车朝某个方向一直跑,直到我们看不见,这是因为我们还没开始训练机器人。 + +Gym 库中的大部分小游戏都可以用一个普通的实数或者向量来表示动作。输出env.action\_space.sample()的返回值,能看到输出为 1 或者 0。env.action\_space.sample()的含义是,在该游戏的所有动作空间里随机选择一个作为输出。在这个例子中,动作只有两个:0 和 1,一左一右。env.step()方法有4个返回值:observation、reward、done、info 。 + +observation 是状态信息,是在游戏中观测到的屏幕像素值或者盘面状态描述信息。reward 是奖励值,即动作提交以后能够获得的奖励值。这个奖励值因游戏的不同而不同,但总体原则是,对完成游戏有帮助的动作会获得比较高的奖励值。done 表示游戏是否已经完成,如果完成了,就需要重置游戏并开始一个新的回合。info 是一些比较原始的用于诊断和调试的信息,或许对训练有帮助。不过,OpenAI 在评价我们提交的机器人时,是不允许使用这些信息的。 + +在每个训练中都要使用的返回值有 observation、reward、done。但 observation 的结构会由于游戏的不同而发生变化。以 CartPole-v0 为例,我们对代码进行修改: + +```python +import gym +env = gym.make('CartPole-v0') +env.reset() +for _ in range(1000): + env.render() + action = env.action_space.sample() + observation, reward, done, info = env.step(action) + print(observation) +env.close() +``` + +输出: +``` +[ 0.01653398 0.19114579 0.02013859 -0.28050058] +[ 0.0203569 -0.00425755 0.01452858 0.01846535] +[ 0.02027175 -0.19958481 0.01489789 0.31569658] +...... +``` + +从输出可以看出这是一个四维的观测。在其他游戏中会有维度更多的情况出现。 + +env.step()完成了一个完整的 $S \to A \to R \to S'$ 过程。我们只要不断观测这样的过程,并让智能体在其中用相应的算法完成训练,就能得到一个高质量的强化学习模型。 + +Gym 库已注册的环境可以通过以下代码查看: +```python +from gym import envs +env_specs = envs.registry.all() +envs_ids = [env_spec.id for env_spec in env_specs] +print(envs_ids) +``` +Gym 库中的每个环境都定义了观测空间和动作空间。观测空间和动作空间可以是离散的(取值为有限个离散的值),也可以是连续的(取值为连续的值)。 + +### 1.7.2 MountainCar-v0 例子 + +接下来,我们通过一个例子来学习如何与 Gym 库进行交互。我们选取**小车上山(MountainCar-v0)**作为例子。 + +首先我们来看看这个任务的观测空间和动作空间: +```python +import gym +env = gym.make('MountainCar-v0') +print('观测空间 = {}'.format(env.observation_space)) +print('动作空间 = {}'.format(env.action_space)) +print('观测范围 = {} ~ {}'.format(env.observation_space.low, + env.observation_space.high)) +print('动作数 = {}'.format(env.action_space.n)) +``` + +输出: + +``` +观测空间 = Box([-1.2 -0.07], [0.6 0.07], (2,), float32) +动作空间 = Discrete(3) +观测范围 = [-1.2 -0.07] ~ [0.6 0.07] +动作数 = 3 +``` + +在 Gym 库中,环境的观测空间用 env.observation\_space 表示,动作空间用 env.action\_space 表示。离散空间 gym.spaces.Discrete 类表示,连续空间用 gym.spaces.Box 类表示。对于离散空间,Discrete (n) 表示可能取值的数量为 n;对于连续空间,Box类实例成员中的 low 和 high 表示每个浮点数的取值范围。MountainCar-v0 中的观测是长度为 2 的 numpy 数组,数组中值的类型为 float。MountainCar-v0 中的动作是整数,取值范围为 {0,1,2}。 + +接下来实现智能体来控制小车移动,对应代码如下。 + +```python +class SimpleAgent: + def __init__(self, env): + pass + + def decide(self, observation): # 决策 + position, velocity = observation + lb = min(-0.09 * (position + 0.25) ** 2 + 0.03, + 0.3 * (position + 0.9) ** 4 - 0.008) + ub = -0.07 * (position + 0.38) ** 2 + 0.07 + if lb < velocity < ub: + action = 2 + else: + action = 0 + return action # 返回动作 + + def learn(self, *args): # 学习 + pass + +agent = SimpleAgent(env) +``` + +SimpleAgent 类的 decide()方法用于决策,learn() 方法用于学习,该智能体不是强化学习智能体,不能学习,只能根据给定的数学表达式进行决策。 + +接下来我们试图让智能体与环境交互,代码如下。 + +```python +def play(env, agent, render=False, train=False): + episode_reward = 0. # 记录回合总奖励,初始值为0 + observation = env.reset() # 重置游戏环境,开始新回合 + while True: # 不断循环,直到回合结束 + if render: # 判断是否显示 + env.render() # 显示图形界面 + action = agent.decide(observation) + next_observation, reward, done, _ = env.step(action) # 执行动作 + episode_reward += reward # 收集回合奖励 + if train: # 判断是否训练智能体 + agent.learn(observation, action, reward, done) # 学习 + if done: # 回合结束,跳出循环 + break + observation = next_observation + return episode_reward # 返回回合总奖励 +``` + +上面代码中的 play 函数可以让智能体和环境交互一个回合,该函数有 4 个参数。env 是环境类。agent 是智能体类。render 是 bool 型变量,其用于判断是否需要图形化显示。如果 render 为 True,则在交互过程中会调用 env.render() 以显示图形界面,通过调用 env.close() 可关闭图形界面。train 是 bool 型变量,其用于判断是否训练智能体,在训练过程中设置为 True,让智能体学习;在测试过程中设置为 False,让智能体保持不变。该函数的返回值 episode\_reward 是 float 型的数值,其表示智能体与环境交互一个回合的回合总奖励。 + +接下来,我们使用下面的代码让智能体和环境交互一个回合,并显示图形界面。 + +```python +env.seed(3) # 设置随机种子,让结果可复现 +episode_reward = play(env, agent, render=True) +print('回合奖励 = {}'.format(episode_reward)) +env.close() # 关闭图形界面 +``` + +输出: +``` +回合奖励 = -105.0 +``` + +为了评估智能体的性能,需要计算出连续交互 100 回合的平均回合奖励,代码如下。 +```python +episode_rewards = [play(env, agent) for _ in range(100)] +print('平均回合奖励 = {}'.format(np.mean(episode_rewards))) +``` + +输出: +``` +平均回合奖励 = -106.63 +``` + +SimpleAgent 类对应策略的平均回合奖励在 $-$110 左右,而对于小车上山任务,只要连续 100 个回合的平均回合奖励大于 $-$110,就可以认为该任务被解决了。完整代码实现可参考[小车上山代码](https://github.com/datawhalechina/easy-rl/blob/master/docs/chapter1/RL_example.py)。 + +测试智能体在 Gym 库中某个任务的性能时,出于习惯使然,学术界一般最关心 100 个回合的平均回合奖励。对于有些任务,还会指定一个参考的回合奖励值,当连续 100 个回合的奖励大于指定的值时,则认为该任务被解决了。而对于没有指定值的任务,就无所谓任务被解决了或没有被解决。 + +我们对 Gym 库的用法进行总结:使用 env=gym.make(环境名)取出环境,使用 env.reset()初始化环境,使用 env.step(动作)执行一步环境,使用 env.render()显示环境,使用 env.close()关闭环境。Gym库 有对应的[官方文档](https://www.gymlibrary.dev/),读者可以阅读文档来学习 Gym库 。 + +## 参考文献 + +* [百面深度学习](https://book.douban.com/subject/35043939/) +* [强化学习:原理与Python实现](https://book.douban.com/subject/34478302/) + +* [强化学习基础 David Silver 笔记](https://zhuanlan.zhihu.com/c_135909947) +* [David Silver 强化学习公开课中文讲解及实践](https://zhuanlan.zhihu.com/reinforce) +* [UCL Course on RL(David Silver)](https://www.davidsilver.uk/teaching/) + +* [白话强化学习与PyTorch](https://book.douban.com/subject/34809676/) + +* [OpenAI Spinning Up ](https://spinningup.openai.com/en/latest/spinningup/rl_intro.html#) + +* [神经网络与深度学习](https://nndl.github.io/) + +* [机器学习](https://book.douban.com/subject/26708119//) + + + + + + + + + + + diff --git a/data/C2/pdf/rag.pdf b/data/C2/pdf/rag.pdf new file mode 100644 index 0000000..25c1f55 Binary files /dev/null and b/data/C2/pdf/rag.pdf differ diff --git a/data/C2/txt/蜂医.txt b/data/C2/txt/蜂医.txt new file mode 100644 index 0000000..4591690 --- /dev/null +++ b/data/C2/txt/蜂医.txt @@ -0,0 +1,118 @@ +# 蜂医 + +游戏《三角洲行动》中的支援型干员 + +蜂医是2024年琳琅天上发行的《三角洲行动》中的支援型干员之一,在早期版本是唯一一个支援型干员。 + +蜂医在游戏中能够使用战术装备“激素枪”:远程治疗队友或'自我治疗',还可以使用兵种道具“烟幕无人机”:释放长烟幕,和“蜂巢科技烟雾弹”:产生一团白色烟雾(使用激素枪对烟雾射击换变成绿色烟雾,可起到治疗作用),干员特长为“高效救援”:救援倒地队友时速度更快,在全面战场模式中约1.4秒就能救起队友,且被救起的队友能恢复更多生命值。在烽火地带中,还能够移除队友血量上限减少的负面效果。 \[1-2]**** + +* 中文名 + + 罗伊•斯米 + +* 外文名 + + Roy smee \[2]** + +* 别    名 + + 罗伊、蜂医 + +* 性    别 + + 男 + +- 登场作品 + + [三角洲行动](/item/%E4%B8%89%E8%A7%92%E6%B4%B2%E8%A1%8C%E5%8A%A8/63251542?fromModule=lemma_inlink) + +- 生    日 + + 2008年2月23日 \[3]** + +- 身    高 + + 176 cm \[3]** + +- 体    重 + + 75 kg \[3]** + +## 目录 + +1. 1[角色设定](#1) +2. 2[角色定位](#2) +3. 3[技能](#3) + +1) ▪[战术装备 - 激素枪](#3-1) +2) ▪[战术道具 - 烟幕无人机](#3-2) +3) ▪[战术道具 - 蜂巢科技烟雾弹](#3-3) + +1. ▪[干员特长 - 高效救援](#3-4) + +## 角色设定 + +三角洲行动:医疗角色蜂医!让你不再为血量担忧 + +蜂医是游戏中的一名战地医生,拥有丰富的参军履历。 + +蜂医在干员档案中标明他有一个妻子和女儿。 + +## 角色定位 + +-蜂医在团队中主要承担支援和治疗的职责,是团队生存能力的重要保障。他能在激烈的战斗中为队友提供及时的治疗,确保队友保持良好的战斗状态,还能利用烟幕技能为团队创造有利的战术环境,如掩护队友转移、推进或突袭等。 + +## 技能 + +### 战术装备 - 激素枪 + +-可发射多目标追踪子弹,能同时锁定并缓慢治疗多名友方干员,治疗期间还能抑制队友的疼痛感等异常状态。 + +-开镜时,仅会锁定一个目标。 + +-全面战场中,开镜瞄准敌人可以扣除敌人20滴血 + +-长按按键可以对自己进行治疗,在全面战场中,可以恢复自身血量。烽火地带模式中,可以消除自身如骨折的负面效果。 + +### 战术道具 - 烟幕无人机 + +-能控制手势感应无人机向前飞行并喷射烟幕,形成一条长15米的烟雾长廊 + +-无人机飞行时,长按开火键引导无人机转向,可改变烟幕走向,用来分割战场、掩护队友撤退或进攻。 + +### 战术道具 - 蜂巢科技烟雾弹 + +-投掷后会在区域内产生一团白色烟雾,可作常规烟雾掩护使用。 + +-用激素枪向其烟雾射击,能将其染色为绿色的治疗烟雾,使在烟雾中的队友获得缓慢回血效果。 + +### 干员特长 - 高效救援 + +-救援倒地队友时速度更快。 + +-在全面战场模式中大概1.4秒就能救起队友,且被救起的队友不会存在扣血效果,能够恢复至满血。 + +-在烽火地带中,还能够移除队友血量上限减少的负面效果。 + +参考资料 + +* 1 + + [](#sup-1) + + [《三角洲行动》PC/移动今日上线](/reference/65245483/533aYdO6cr3_z3kATKCLyvz3ZnmWYNWt7OfaWrBzzqIPmGapB4rjFJkjrtQw87hkBETK4sgwNIZMxr6sWxla).腾讯游戏 \[引用日期2025-01-20]** +* 2 + + [](#sup-2) + + [《三角洲行动》干员档案-罗伊·斯米——代号:蜂医](/reference/65245483/533aYdO6cr3_z3kATPGIza6jYXqSN9ul6LOGBuNzzqIPmGapB5nyTcYw6ds2_P5rHUXIv5Utdt8Rk-fleC1Eu50Uc-xtRdNUgnm8E26tkOqJqZtux9xHoIldUaQemfHvtlK6hkzJhvWX5WjulmPM4YewIHHGSYAdj4VcVsyHC6syegGFn0a7eVi3FOY).哔哩哔哩.2024-03-16 \[引用日期2025-01-30]** +* 3 + + [](#sup-3) + + [三角洲干员背景小细节,蜂医的女儿是谁?](/reference/65245483/533aYdO6cr3_z3kATKLdz_32YXnEZ9qsu-LUAeNzzqIPmGapB5nyTcYw6ds2_P5rHUXIv5Utdt8Rk-fleC1En6pmD7hvN9drgnm8E26tkOqJqZtux9xHoIldW64QmbKk5wavij7ZiPKBqGy_yHrOuty2czaCG-pe1ZQcAc-PDfpldFDVl0PqLgmyQLGbxP34imiXDI6z_zKMaYGUK5M).哔哩哔哩.2025-01-26 \[引用日期2025-01-30]** +* 4 + + [](#sup-4) + + [《三角洲行动》全新黑夜之子赛季4月17日正式上线](/reference/65245483/533aYdO6cr3_z3kATPSPmKqhNHmQNIivurSFV-ZzzqIPmGapB4rjFJkjrtQw87hkBETK4sgwNIZMxr6nWxIb8a5OJbh9XO1mwCo).腾讯游戏 \[引用日期2025-06-13]** diff --git a/data/C3/dragon/dragon02.png b/data/C3/dragon/dragon02.png new file mode 100644 index 0000000..ff01194 Binary files /dev/null and b/data/C3/dragon/dragon02.png differ diff --git a/data/C3/dragon/dragon03.png b/data/C3/dragon/dragon03.png new file mode 100644 index 0000000..2f18e4a Binary files /dev/null and b/data/C3/dragon/dragon03.png differ diff --git a/data/C3/dragon/dragon04.png b/data/C3/dragon/dragon04.png new file mode 100644 index 0000000..300c30d Binary files /dev/null and b/data/C3/dragon/dragon04.png differ diff --git a/data/C3/dragon/dragon05.png b/data/C3/dragon/dragon05.png new file mode 100644 index 0000000..55451f6 Binary files /dev/null and b/data/C3/dragon/dragon05.png differ diff --git a/data/C3/dragon/dragon06.png b/data/C3/dragon/dragon06.png new file mode 100644 index 0000000..604afb0 Binary files /dev/null and b/data/C3/dragon/dragon06.png differ diff --git a/data/C3/dragon/other01.png b/data/C3/dragon/other01.png new file mode 100644 index 0000000..b070748 Binary files /dev/null and b/data/C3/dragon/other01.png differ diff --git a/data/C3/dragon/query.png b/data/C3/dragon/query.png new file mode 100644 index 0000000..35f9fcb Binary files /dev/null and b/data/C3/dragon/query.png differ diff --git a/data/C3/excel/movie.xlsx b/data/C3/excel/movie.xlsx new file mode 100644 index 0000000..bf04d70 Binary files /dev/null and b/data/C3/excel/movie.xlsx differ diff --git a/data/C3/imgs/datawhale01.png b/data/C3/imgs/datawhale01.png new file mode 100644 index 0000000..1a7337f Binary files /dev/null and b/data/C3/imgs/datawhale01.png differ diff --git a/data/C3/imgs/datawhale02.png b/data/C3/imgs/datawhale02.png new file mode 100644 index 0000000..039d063 Binary files /dev/null and b/data/C3/imgs/datawhale02.png differ diff --git a/data/C3/pdf/IPCC_AR6_WGII_Chapter03.pdf b/data/C3/pdf/IPCC_AR6_WGII_Chapter03.pdf new file mode 100644 index 0000000..47adbd1 Binary files /dev/null and b/data/C3/pdf/IPCC_AR6_WGII_Chapter03.pdf differ diff --git a/data/C4/metadata/dragon.json b/data/C4/metadata/dragon.json new file mode 100644 index 0000000..b0cb1b8 --- /dev/null +++ b/data/C4/metadata/dragon.json @@ -0,0 +1,56 @@ +[ + { + "img_id": "dragon02", + "path": "../../data/C3/dragon/dragon02.png", + "title": "悬崖上的白龙", + "description": "一头雄伟的白色巨龙栖息在悬崖边缘,背景是金色的云霞和远方的海岸。它拥有巨大的翅膀和优雅的身姿,是典型的西方奇幻生物。", + "category": "western_dragon", + "location": "悬崖海岸", + "environment": "天空" + }, + { + "img_id": "dragon03", + "path": "../../data/C3/dragon/dragon03.png", + "title": "霸王龙的怒吼", + "description": "史前时代的霸王龙张开血盆大口,发出震天的怒吼。在它身后,几只翼龙在阴沉的天空中盘旋,展现了白垩纪的原始力量。", + "category": "dinosaur", + "location": "史前荒野", + "environment": "陆地" + }, + { + "img_id": "dragon04", + "path": "../../data/C3/dragon/dragon04.png", + "title": "奔跑的奶龙", + "description": "一只Q版的黄色小恐龙,有着大大的绿色眼睛和友善的微笑。是一部动画中的角色,非常可爱。", + "category": "cartoon_dinosaur", + "location": "动画世界", + "environment": "未知" + }, + { + "img_id": "dragon05", + "path": "../../data/C3/dragon/dragon05.png", + "title": "驯龙高手:无牙仔", + "description": "在电影《驯龙高手》中,主角小嗝嗝骑着他的龙伙伴无牙仔在高空飞翔。他们飞向灿烂的太阳,下方是岛屿和海洋,画面充满了冒险与友谊。", + "category": "movie_character", + "location": "博克岛上空", + "environment": "天空" + }, + { + "img_id": "dragon06", + "path": "../../data/C3/dragon/dragon06.png", + "title": "中华金龙", + "description": "一条金色的中华龙在祥云间盘旋,它身形矫健,龙须飘逸,展现了东方神话中龙的威严与神圣。", + "category": "chinese_dragon", + "location": "祥云之上", + "environment": "天空" + }, + { + "img_id": "other01", + "path": "../../data/C3/dragon/other01.png", + "title": "金丝猴", + "description": "一只珍稀的金丝猴坐靠在树干上,悠闲地吃着食物。它拥有金色的长毛和蓝色的脸庞,是中国的特有物种。", + "category": "animal", + "location": "森林", + "environment": "陆地" + } +] \ No newline at end of file diff --git a/data/C4/txt/ai.txt b/data/C4/txt/ai.txt new file mode 100644 index 0000000..ebba260 --- /dev/null +++ b/data/C4/txt/ai.txt @@ -0,0 +1,29 @@ + 5月,全球多家科技公司发布新的大模型,它们在语义理解、多模态等方面进一步提升,人工智能(AI)的能力边界在不断扩大。随着无人驾驶、机器人等技术借助AI快速进化并逐步投入市场,不少国家通过推进法规建设、开展国际合作等方式,为AI领域创新提供更好的土壤。 + + 大模型更趋实用化 + + 5月下旬,中国深度求索(DeepSeek)公司表示,DeepSeek R1模型已完成小版本升级,当前版本为DeepSeek-R1-0528,模型的思维深度与推理能力显著提升。更新后的R1模型针对议论文、小说、散文等文体进行了进一步优化,能够输出篇幅更长、结构内容更完整的长篇作品,同时呈现出更加贴近人类偏好的写作风格。 + + 同样在5月,美国Anthropic公司推出“克劳德4”系列两款新模型:“奥普斯4”(Opus 4)与“十四行诗4”(Sonnet 4),旨在为业界提供更高标准的编程、推理和智能体应用。Opus 4是行业领先的编程模型,能够高效完成复杂且持续时间长的任务;而Sonnet 4在此前的3.7版本基础上显著升级,具备更强的指令理解能力与推理、编程表现。 + + 行业巨头谷歌公司也没闲着。该公司在5月推出整体性能和智能推理能力均较以往版本大幅提升的多个“双子座2.5”系列模型,并发布了多个多模态模型,如图像生成模型Imagen 4和视频生成模型Veo 3,具备从文本等多种输入形式生成高质量视觉内容的能力。音乐生成模型Lyria 2为音乐人提供了多模态创作工具。AI电影制作工具Flow集成了先进的多模态技术,使用户通过自然语言描述就能生成高质量的视觉作品。 + + AI仍有不少缺陷需克服 + + 尽管当前AI应用已相当广泛,但不少缺陷还是会影响其实用性。研究人员正努力分析导致这些缺陷的原因并寻求新的解决方法,从而改善AI的性能。 + + 一个比较明显的问题是,AI生成内容虽然已非常流畅,但提供的信息很多时候还是不准确。5月,日本研究人员在德国《先进科学》杂志发表的一项研究成果中指出,这一问题与人类的语言障碍——失语症类似。 + + 据研究人员介绍,大模型在出现严重错误时仍表达流畅,这与感觉性失语症的症状有相似之处,即说话流利却总说不出什么意思。这并不意味着AI聊天机器人有“脑损伤”,但它们可能被锁定在一种僵化的内部模式中,限制其灵活运用所储存知识,就像患了感觉性失语症。未来研究人员可以针对相关问题,找到改善措施。 + + 业界也确实在努力从不同角度去寻求优化大模型的解决方案。中国科学院自动化研究所联合鹏城实验室提出了一种高效推理策略AutoThink,可让大模型实现自主切换思考模式,避免“过度思考”。 + + 据研究人员介绍,AutoThink提供了一种简单而有效的推理新范式——通过省略号提示配合三阶段强化学习,引导大模型不再“逢题必深思熟虑”,而是根据问题难度自主决定“是否思考”“思考多少”。在多个数学数据集上,AutoThink实现了准确率与效率平衡,既提升性能又节省算力,展示出较强的适应性和实用性。 + + 营造更合理的AI创新环境 + + 国际劳工组织5月20日发布一份有关生成式AI与就业的报告表示,全球四分之一的工作岗位可能受到生成式AI影响。不过报告也指出,在劳动领域,生成式AI本身并无好坏之分,其社会经济影响在很大程度上取决于对技术普及的管理方式。 + + 一些国家已在积极尝试通过优化政策、法规来营造更好的AI创新环境。日本参议院全体会议5月28日以多数赞成票通过该国首部专门针对AI的法律,旨在促进AI相关技术研发和应用并防止其滥用。依据这部《人工智能相关技术研究开发及应用推进法》,日本拟设立以日本首相为首、全体内阁成员参加的“AI战略本部”作为日本AI政策的“司令部”,并制定“AI基本计划”。 + + 国际合作同样重要。“2025中国—上海合作组织人工智能合作论坛”5月29日在天津召开。论坛发布《中国—上合组织国家人工智能应用合作中心建设方案》,邀请上合组织成员国共建人工智能应用合作中心,围绕夯实人工智能发展基础、提供开源开放服务、加强产业合作对接、促进人才培育等方面加强务实合作,共同促进人工智能技术普惠应用。 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/咖喱炒蟹.md b/data/C8/cook/dishes/aquatic/咖喱炒蟹.md new file mode 100644 index 0000000..adca969 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/咖喱炒蟹.md @@ -0,0 +1,47 @@ +# 咖喱炒蟹的做法 + +第一次吃咖喱炒蟹是在泰国的建兴酒家中餐厅,爆肉的螃蟹挂满有蟹黄味道的咖喱,味道真的绝,喜欢吃海鲜的程序员绝对不能错过。操作简单,对沿海的程序员非常友好。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 青蟹(别称:肉蟹) +- 咖喱块(推介乐惠蟹黄咖喱) +- 洋葱 +- 椰浆 +- 鸡蛋 +- 生粉(别称:淀粉) +- 大蒜 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +- 肉蟹 1 只(大约 300g) * 份数 +- 咖喱块 15g(一小块)*份数 +- 椰浆 100ml*份数 +- 鸡蛋 1 个 *份数 +- 洋葱 200g *份数 +- 大蒜 5 瓣 *份数 + +## 操作 + +- 肉蟹掀盖后对半砍开,蟹钳用刀背轻轻拍裂,切口和蟹钳蘸一下生粉,不要太多。撒 5g 生粉到蟹盖中,盖住蟹黄,备用 +- 洋葱切成洋葱碎,备用 +- 大蒜切碎,备用 +- 烧一壶开水,备用 +- 起锅烧油,倒入约 20ml 食用油,等待 10 秒让油温升高 +- 将螃蟹切口朝下,轻轻放入锅中,煎 20 秒,这一步主要是封住蟹黄,蟹肉。然后翻面,每面煎 10 秒。煎完将螃蟹取出备用 +- 将螃蟹盖放入锅中,使用勺子舀起锅中热油泼到蟹盖中,煎封住蟹盖中的蟹黄,煎 20 秒后取出备用 +- 不用刷锅,再倒入 10ml 食用油,大火让油温升高至轻微冒烟,将大蒜末,洋葱碎倒入,炒 10 秒钟 +- 将咖喱块放入锅中炒化(10 秒),放入煎好的螃蟹,翻炒均匀 +- 倒入开水 300ml,焖煮 3 分钟。 +- 焖煮完后,倒入椰浆和蛋清,关火,关火后不断翻炒,一直到酱汁变浓稠。 +- 出锅 + +## 附加内容 + +- 做法参考:[十几年澳门厨房佬教学挂汁的咖喱蟹怎么做](https://www.bilibili.com/video/BV1Nq4y1W7K9) \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/小龙虾/小龙虾.md b/data/C8/cook/dishes/aquatic/小龙虾/小龙虾.md new file mode 100644 index 0000000..daa595d --- /dev/null +++ b/data/C8/cook/dishes/aquatic/小龙虾/小龙虾.md @@ -0,0 +1,61 @@ +# 小龙虾的做法 + +![成品](./成品.jpg) + +在家里做的小龙虾,肉质细嫩,鲜嫩多汁,干净卫生。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 小龙虾 +- 油 +- 香叶 +- 八角 +- 桂皮 +- 青花椒 +- 花椒 +- 子弹头辣椒 +- 葱姜蒜 +- 郫县豆瓣 +- 黄豆酱 +- 啤酒 +- 生抽 +- 盐 + +## 计算 + +以下是两斤小龙虾的量,按比例调整就好。 + +- 小龙虾 = 2 斤 +- 油 = 70 毫升(这是平时炒菜 3 倍量) +- 香叶 = 两片 +- 八角 = 一个 +- 桂皮 = 3 克 +- 青花椒 = 10 克 +- 花椒 = 10 克 +- 子弹头辣椒 = 5 克 +- 葱 = 一根大葱 +- 姜 = 30 克 +- 蒜 = 7 瓣大蒜 +- 郫县豆瓣 = 30 克 +- 黄豆酱 = 30 克 +- 啤酒 = 500 毫升 +- 生抽 = 30 毫升 +- 盐 = 10 克 + +## 操作 + +- 小龙虾刷干净去虾线,葱切 2cm 葱段,姜蒜切末。 +- 烧油,油微热, 下香叶、八角、桂皮、青花椒、花椒、子弹头辣椒。 +- 香料出香气之后下锅葱姜蒜 +- 葱姜蒜爆香后,加入郫县豆瓣、黄豆酱,炒出红油。 +- 下小龙虾,翻炒至变色。 +- 加入啤酒,等啤酒烧开后加入生抽,盐。 +- 将小龙虾完全煮熟后出锅。 + +## 附加内容 + +饭店应该都是油炸一遍,家庭油炸的话,太浪费了,所以在这个菜谱里用油比炒菜油多一些煎一下,实测同样好吃。 + +去虾线后的虾肉比不去虾线的虾肉口感差一些,并且小龙虾去虾线对新手是一个挑战,能接受虾线的情况下不去虾线也可以。 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/小龙虾/成品.jpg b/data/C8/cook/dishes/aquatic/小龙虾/成品.jpg new file mode 100644 index 0000000..164c7eb --- /dev/null +++ b/data/C8/cook/dishes/aquatic/小龙虾/成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f925932ded89df54e77c3148c70e772e8902a498a3bb0208a7404d7fcdc4a4a1 +size 562566 diff --git a/data/C8/cook/dishes/aquatic/干煎阿根廷红虾/干煎阿根廷红虾.jpg b/data/C8/cook/dishes/aquatic/干煎阿根廷红虾/干煎阿根廷红虾.jpg new file mode 100644 index 0000000..c715fca --- /dev/null +++ b/data/C8/cook/dishes/aquatic/干煎阿根廷红虾/干煎阿根廷红虾.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11f5b7bdcd5941a2a56de1e011298d5ee4acb1ba7c3789ef653ab6fe994865ff +size 92655 diff --git a/data/C8/cook/dishes/aquatic/干煎阿根廷红虾/干煎阿根廷红虾.md b/data/C8/cook/dishes/aquatic/干煎阿根廷红虾/干煎阿根廷红虾.md new file mode 100644 index 0000000..d13cddb --- /dev/null +++ b/data/C8/cook/dishes/aquatic/干煎阿根廷红虾/干煎阿根廷红虾.md @@ -0,0 +1,57 @@ +# 干煎阿根廷红虾的做法 + +![示例菜成品](./干煎阿根廷红虾.jpg) + +平常所见到虾,只有赴“汤”蹈“火”后,才能红!阿根廷虾很任性,一红就红一辈子!跟它住在北极的亲戚,北极虾一样,天生红。 + +阿根廷红虾,之所以这么红,是因为它生活在深海中,使得它体内含有丰富的碘、磷及珍贵的虾青素等微量元素,能够增强人体免疫力,还对心脏活动具有重要调节作用,可以减少血液中的胆固醇含量。 + +阿根廷红虾,不仅个大肥美,虾肉白如凝脂,细腻腴滑,口感鲜嫩,味道甜香浓郁,是虾类料理界的宠儿,看着真让人垂(chao)涎(ji)欲(xiang)滴(chi),快享受这大快朵颐的欢愉吧! + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 阿根廷红虾(选用了速冻虾) +- 海盐(研磨装) +- 黑胡椒(研磨装) +- 白葡萄酒 +- 生抽 +- 香菜 +- 柠檬 +- 洋葱 +- 生姜 +- 大蒜 + +## 计算 + +- 阿根廷红虾 2-3 只 +- 海盐 5g +- 黑胡椒(研磨装) +- 白葡萄酒 20ml +- 生抽 1ml +- 香菜 3 片 +- 柠檬 1 片 +- 洋葱 10g +- 生姜 10g +- 大蒜 10g + +## 操作 + +- 阿根廷红虾解冻,最好是提前 1 天从速冻取出放到冷藏里自然解冻,能更好保持风味和口感。可买已经开背去虾线的,节省了不少时间 +- 解冻好的红虾洗净擦干备用,注意这里一定要沥干水分,赶时间可以用厨房用纸吸干水分 +- 生姜切片,洋葱切小方块,香菜洗干净后,叶茎分离,把香菜叶切碎,大蒜压碎切成小块碎末 +- 大火热锅,热锅后倒入两调羹橄榄油,等油温升高后,放入生姜片,洋葱块和香菜茎煸炒 +- 约 1 分钟后取出生姜,洋葱和香菜茎,弃用 +- 调中大火,放入红虾开始煎,注意所有虾需要单面都完整接触平底锅,煎约 2 分钟,同时给每只虾刷上一层油 +- 待底面虾壳有微微焦黄时翻面,并撒入大蒜碎末,轻微晃动平底锅使得受热均匀 +- 约 1 分钟后添加 20ml 白葡萄酒 +- 再煎 1 分钟后调中小火,均匀撒上一层盐和黑胡椒 +- 给每只虾滴上一滴生抽 +- 撒上香菜叶,装盘 +- 切好柠檬片,摆放到盘边即可 + +## 附加内容 + +- 柠檬可提升虾的口感,但偏酸,可以根据喜好添加,也可以不用 +- 趁热吃 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/微波葱姜黑鳕鱼.md b/data/C8/cook/dishes/aquatic/微波葱姜黑鳕鱼.md new file mode 100644 index 0000000..4996d2e --- /dev/null +++ b/data/C8/cook/dishes/aquatic/微波葱姜黑鳕鱼.md @@ -0,0 +1,64 @@ +# 微波葱姜黑鳕鱼的做法 + +这道菜改编自西雅图 Veil 餐厅主厨 Johnny Zhu 的母亲 Margaret Lu 的菜谱。卢女士原菜谱是使用罗非鱼来做这道菜,Johnny 改为鳕鱼,但也可以用大比目鱼鱼排,或者海鲈鱼、鳟鱼等。每种鱼的密度有差别,烹饪时间要做微调。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +原料: + +- 黑鳕鱼,带皮 + +调味料: + +- 青葱 +- 姜 +- 料酒 +- 酱油 +- 芝麻油 +- 花生油 + +工具: + +- 密封袋 + +## 计算 + +每 2 份: + +- 黑鳕鱼,带皮,2 片,450g(本菜谱主角,所有调料可根据鳕鱼的实际重量进行比例调整) +- 青葱,葱白,25g。 +- 青葱,葱绿,10g。 +- 姜,13g。 +- 料酒,5mL。 +- 酱油,25mL。 +- 芝麻油,2mL。 +- 花生油,50mL。 + +## 操作 + +- 鱼片分别放入密封袋,鱼皮向下放在盘子中。 +- 取葱白切丝 25g,姜去皮后切丝,10g,混合在一起后分成两半,分别放在袋内鱼片上。 +- 每个袋子倒入 2.5mL 料酒。 +- 封好密封袋,放入微波炉中,中火(800 瓦)微波至*不透明且容易散开*时(约 3.5-5 分钟),从袋中取出鱼片。 +- 去除青葱和姜。 +- 取酱油 25mL,芝麻油 2mL,混合均匀后平均淋在两片鱼片上。 +- 取葱绿切细丝 10g,姜去皮后切丝 3g,混合后分成两份撒在鱼片上。 +- 取花生油 50mL,在小锅中加热至 190℃。 +- 将热油淋到放油葱绿的鱼片上,立刻上桌。 + +## 附加内容 + +### 使用海鲈鱼、罗非鱼、大比目鱼或者龙脷鱼 + +| 鱼类 | 是否切片 | 重量 | 微波时间 | +|----------|----------|------|-----------| +| 海鲈鱼 | 整条 | 450g | 6.5 分钟 | +| 罗非鱼 | 整条 | 800g | 6 分钟 | +| 大比目鱼 | 切片 | 170g | 2.25 分钟 | +| 龙脷鱼 | 切片 | 170g | 1.5 分钟 | + +### 其他变化 + +- 如果想让香气更为浓郁,在微波前可将葱姜与料酒均匀涂抹在鱼片的两侧,再进行微波加热。 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/水煮鱼.md b/data/C8/cook/dishes/aquatic/水煮鱼.md new file mode 100644 index 0000000..9f3863e --- /dev/null +++ b/data/C8/cook/dishes/aquatic/水煮鱼.md @@ -0,0 +1,59 @@ +# 水煮鱼的做法 + +水煮鱼是一道做法中等难度的硬菜。巴沙鱼富含优质蛋白且脂肪含量低,配合各种时令蔬菜十分营养健康。初学者一般需要 2 小时即可完成。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 巴沙鱼 +- 蔬菜(比如土豆片/豆芽/花菜/生菜/……) +- 红油豆瓣酱 +- 藤椒油 +- 菜籽油 +- 白胡椒粉 +- 蒜瓣 +- 盐 +- 糖 +- 量杯 +- 厨房秤(可选) +- 大不锈钢碗 + +## 计算 + +以下用量适合 3 至 5 人食用。 + +- 巴沙鱼 500g +- 蔬菜(比如土豆片/豆芽/花菜/生菜/……) 可有不同搭配,推荐合计重量 300g 至 500g +- 红油豆瓣酱 40g (不怕辣想多加红油就多加 10 至 20g) +- 豆豉 10g (可选) +- 藤椒油 10ml +- 菜籽油 25ml +- 白胡椒粉 3g +- 大蒜 2 瓣 +- 盐 5g +- 糖 2g + +## 操作 + +- 准备:巴沙鱼若是从冷冻柜里取出,需要放室温自然解冻 5 小时再做切片处理。 +- 切片:巴沙鱼撇成薄片,约 5cm 长,3cm 宽。 +- [腌制](../../tips/learn/学习腌.md):将切好片的巴沙鱼放入大不锈钢碗中 +- 加入 30g 豆瓣酱,3g 盐,10ml 藤椒油,3g 白胡椒粉 +- 用手抓匀后加入 5ml 菜籽油收尾封住口味 +- 常温静置至少 30 分钟入味。 +- 备菜:大蒜切成蒜末。以 300g 花菜,200g 生菜为例,将花菜与生菜洗净。 +- 焯水与炒菜:花菜[开水锅焯水](../../tips/learn/学习焯水.md)备用;将生菜洗净晾干,炒熟备用(不用放油)。 +- 炒豆瓣酱:热锅冷油(菜籽油 20ml),加入 10g 豆瓣酱,10g 豆豉(可选),加入蒜末,**中火**慢炒。 +- 汆鱼片:加入 150ml 热水,水很快开后加入腌制好的鱼片,轻轻翻动让鱼片在水中散开,加入 2g 盐和 2g 糖调味(此时可根据个人口味调整盐的用量)。水再次沸腾后即可盛盘。 +- 盛盘:先将熟的蔬菜盛至大碗中,然后将热的鱼片盛在蔬菜上面,浇上锅中剩余热汤即可! + +## 附加内容 + +- 垫底的蔬菜组合及用量可自由发挥,但需要注意各种蔬菜的特点,比如改成土豆的时候,需要将土豆片/土豆块煮熟(可以用筷子戳一戳确认)。 +- 红油豆瓣酱(辣度)以及盐的用量可根据个人口味调整。 +- 注意切鱼片的时候可以垂直于鱼片长条的方向先剁成 5cm 的鱼块,然后翻转 90 度斜着撇成薄片。 +- [腌制](../../tips/learn/学习腌.md)的时候注意不要太用力抓。 +- [How to Fillet a Fish 怎样给鱼剔骨](https://www.youtube.com/watch?v=uXSgGtMkgro) + +### 参考资料 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/油焖大虾/油焖大虾.jpg b/data/C8/cook/dishes/aquatic/油焖大虾/油焖大虾.jpg new file mode 100644 index 0000000..d7f86ca --- /dev/null +++ b/data/C8/cook/dishes/aquatic/油焖大虾/油焖大虾.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fcab1b3841f8e0c7ef5940c613d5dc32fb63d8ebfb33ba8c341789e587cae7a0 +size 158684 diff --git a/data/C8/cook/dishes/aquatic/油焖大虾/油焖大虾.md b/data/C8/cook/dishes/aquatic/油焖大虾/油焖大虾.md new file mode 100644 index 0000000..a6ce5f4 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/油焖大虾/油焖大虾.md @@ -0,0 +1,45 @@ +# 油焖大虾的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 黑虎虾 or 明虾、 +- 葱、姜 +- 料酒、盐、冰糖、植物油 + +## 计算 + + 1 人食用的版本。 + +- 虾 10 只 +- 花椒 5g +- 葱 50g +- 姜 20g +- 黄酒 30g +- 盐 3g +- 冰糖 10g +- 植物油 + +## 操作 + +- 剪虾枪到根上,虾须虾爪都剪掉,沙包挑掉,开背虾线挑出来,洗净备用 +- 炸料油 + - 油温三成热放花椒,油热离火,放葱姜(不要让油变色最好)葱稍微变黄沥油 (葱油弄多了可以留着作为拌面使用)。 +- 下油,虾摆放整齐,两面变色后轻轻摁虾头 + - 放姜米(姜切成细颗粒) + - 黄酒 30g + - 水两小碗 + - 盐 3g + - 冰糖 10 克 +- 大火烧开转小火盖盖子闷(中途不能再加汤水,不要开盖) +- 皮亮虾弯就可以起锅,虾摆盘 +- 收汁(过滤后倒回锅里收浓,放葱油 ) 汤汁剩余 1/4 时。 +- 浇汁 +- 完成 +- ![成品](./油焖大虾.jpg) +- 开吃✅ + +## 附加内容 + +- 做法参考:B 站老饭骨视频[从小吃到大的油焖大虾居然是假的?泰斗级大师还原真·味道](https://www.bilibili.com/video/BV17f4y1W7z9) \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/混合烤鱼/烤鱼.jpg b/data/C8/cook/dishes/aquatic/混合烤鱼/烤鱼.jpg new file mode 100644 index 0000000..e0df7d8 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/混合烤鱼/烤鱼.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a5de1202b8d802706addcbac7459a7f373f66fdabd948686e0e4661d6836856 +size 187076 diff --git a/data/C8/cook/dishes/aquatic/混合烤鱼/烤鱼.md b/data/C8/cook/dishes/aquatic/混合烤鱼/烤鱼.md new file mode 100644 index 0000000..6f2a9b3 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/混合烤鱼/烤鱼.md @@ -0,0 +1,78 @@ +# 烤鱼的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 草鱼(农贸市场或者超市让店家杀掉,去除不要的器官) +- 大葱 +- 料酒 +- 白胡椒粉 +- 食用盐 +- 大蒜 +- 桂皮 +- 八角 +- 香叶 +- 青花椒 +- 干辣椒段 +- 灯笼椒 +- 火锅底料(随意) +- 千张 +- 绿豆芽 +- 洋葱 +- 豆瓣酱 +- 芹菜段 +- 熟花生米 +- 白芝麻 +- 香菜(放更好吃,根据个人口味可放可不放) + +## 计算 + +每份: + +- 草鱼 大约三斤 +- 大葱 半根 +- 食用油 20ml +- 料酒 10-15ml +- 食用盐 5-10g +- 白胡椒粉 5g-10g +- 桂皮 一小片 +- 八角 两个 +- 大蒜粒 八个 +- 香叶 两张 +- 青花椒 一小把 +- 干辣椒段 10 个 +- 灯笼椒 4 个 +- 芹菜段 两根 +- 洋葱 半个 +- 千张 一张 + +## 操作 + +- 草鱼(一般 3 斤 )从背部切开,两面沿着鱼的背部往下划几刀,不要划到鱼肚皮,不然不易定型 + - 可以用热水浇在鱼身上洗去粘液或者用刷子在流动水龙头下面不停的刷洗,直到摸着没有黏糊糊的手感。 +- 把鱼放到容器中,加入料酒,10g 白胡椒粉,5g 食盐抹匀腌制二十分钟入味。 +- 把半根大葱切成一块一块,大蒜粒中间切开,和八角香叶桂皮放在一个容器中 +- 干辣椒段中间一分为二切开并和灯笼椒装在一个容器中 +- 芹菜切小段 +- 豆芽焯水 +- 千张焯水切成丝 +- 洋葱切成丝。 +- 烤制鱼 + - 家里有烤箱的可以在烤盘刷上底油,鱼皮朝下,直到烤制两面金黄,然后撒上孜然粉 + - 如果没有烤箱,可以热锅热油,锅的两边撒上 2g 食盐,下入草鱼开始煎,刚下入的时候不要着急翻动,等一面定型后再翻面,煎制两面金黄,撒上孜然粉,出锅装在盘子里准备。 +- 锅中撒上 20ml 食用油,等到油热后,把大葱大蒜八角香叶倒入炒香 +- 加上一包火锅底料的一半和 15-20g 豆瓣酱,炒出红油 +- 加入 5g 白糖,10g 食盐,5ml 生抽调味,倒入和食材齐平的清水煮开 +- 依次下入芹菜段,豆芽,千张丝,不用煮熟,稍微烫一下后铺上洋葱丝,放上烤鱼 +- 加入干辣椒,灯笼椒,青花椒 +- 另一个锅烧油,油热后浇在刚加入的辣椒上面激发出香味 +- 最后撒上熟花生米,葱花,白芝麻,香菜 +- 煮 5-6 分钟,美味即成。 + +![示例菜成品](./烤鱼.jpg) + +## 附加内容 + +- 技术总结:上述 + - 这道菜的食盐,胡椒粉,孜然粉,食用油,生抽,白糖等的使用量,根据个人口味和食材比例做决定,并不需要严格按照上述分量来做。 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/清蒸生蚝.md b/data/C8/cook/dishes/aquatic/清蒸生蚝.md new file mode 100644 index 0000000..dbc0d13 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/清蒸生蚝.md @@ -0,0 +1,32 @@ +# 清蒸生蚝的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 生蚝 +* 葱 +* 蒜 +* 姜 +* 酱油 +* 刷子 + +## 计算 + +* 饮用水 1 升 +* 生蚝 6 个 +* 葱 3 颗 +* 蒜 6 瓣 +* 姜 1 小块 +* 酱油 每个生蚝 1 ml + +## 操作 + +* 将生蚝用刷子刷干净(没有刷子用牙刷)。 +* 蒸锅中放水,将蒸屉放上之后,将 6 个生蚝平铺在蒸屉,使用 50%功率,蒸 3 分钟。 +* 用右手拿着湿抹布掀开烫锅盖,将每个生蚝的外壳掀开一半去掉,生蚝的凸面向下,平面向上,每个放 1 根姜丝,10g 蒜末放到生蚝上。 +* 关上烫锅盖,100%功率蒸 3.5 分钟。 +* 停火,用右手拿着抹布掀开烫锅盖,每个放 5ml 酱油。 +* 盛盘。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/清蒸鲈鱼/摆盘.jpg b/data/C8/cook/dishes/aquatic/清蒸鲈鱼/摆盘.jpg new file mode 100644 index 0000000..0c00538 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/清蒸鲈鱼/摆盘.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2574533c049d4f12ba4f982ec77dc7699c1db974c213a5d5d5c09c2d0535c13a +size 340422 diff --git a/data/C8/cook/dishes/aquatic/清蒸鲈鱼/改刀.jpg b/data/C8/cook/dishes/aquatic/清蒸鲈鱼/改刀.jpg new file mode 100644 index 0000000..29420bb --- /dev/null +++ b/data/C8/cook/dishes/aquatic/清蒸鲈鱼/改刀.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:512c9ad772cdd6f01ca678bd2d5b95302cd67b214cd5a77eaeb68415395a2dc5 +size 359597 diff --git a/data/C8/cook/dishes/aquatic/清蒸鲈鱼/清蒸鲈鱼.jpg b/data/C8/cook/dishes/aquatic/清蒸鲈鱼/清蒸鲈鱼.jpg new file mode 100644 index 0000000..b10870e --- /dev/null +++ b/data/C8/cook/dishes/aquatic/清蒸鲈鱼/清蒸鲈鱼.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aed686cdab101e7d3178b885b0187f8bb72c1c093ca638034c40ba68fc98ecc7 +size 263862 diff --git a/data/C8/cook/dishes/aquatic/清蒸鲈鱼/清蒸鲈鱼.md b/data/C8/cook/dishes/aquatic/清蒸鲈鱼/清蒸鲈鱼.md new file mode 100644 index 0000000..b8f0ee1 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/清蒸鲈鱼/清蒸鲈鱼.md @@ -0,0 +1,50 @@ +# 清蒸鲈鱼的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鲈鱼(害怕杀鱼的同学可以让店家帮忙杀) +- 香葱 +- 姜 +- 食用油 +- 蒸鱼豉油 +- 料酒 +- 食用盐 + +## 计算 + +每份: + +- 鲈鱼 一条 +- 香葱 三根 +- 姜 一块 +- 食用油 10-15ml +- 蒸鱼豉油 10-15ml +- 料酒 10-15ml +- 食用盐 5-10g + +## 操作 + +- 姜切片切丝、香葱的葱白切段,葱绿切丝,切丝后放入冷水浸泡备用。 +- 鲈鱼处理好后洗净,用厨房纸擦干,两面分别划几刀,用盐洗掉鱼身的粘液,并用 10g 盐抹遍鱼身的内外,腌制 10 分钟以上。 +- 补充一个鲈鱼改刀和摆盘的方法,改刀后可以让鲈鱼立起来蒸,均匀受热,同时吃起来更加方便,无需翻面。 +- ![改刀](./改刀.jpg) +- ![摆盘](./摆盘.jpg) +- 鱼肚内塞上姜和葱白,鱼身也撒上姜和葱白,量为备用的一半。蒸鱼的碟子用筷子将鱼跟碟子隔开蒸 +- 水烧热感觉到水温后放进入鱼 +- 大火清蒸 10 分钟。 +- 蒸好的鱼,用干净的盘子装起来并去除身上姜蒜 +- 鱼身浇上 15ml 蒸鱼豉油 +- 鱼身重新撒上姜和葱丝,锅内加上 10ml 食用油并烧热,将食用油淋至鱼身即可出菜 + +![示例菜成品](./清蒸鲈鱼.jpg) + +## 附加内容 + +- 技术总结: + - 这道菜属于有手就行,关键点在于火候,鱼的大小跟火候都会相关,太久会导致鱼肉太老极度影响口感,太短会导致部分鱼肉没熟。所以大火蒸鱼一般是 10 分钟内较佳。 + - 切记蒸鱼需要用筷子隔开装鱼的盘子,这样做的好处有两点: + - 1、鱼在蒸的过程中会将水滴到盘子,如果鱼直接接触会导致鱼食用时会腥。 + - 2、能够将鱼均匀受热。 + - 这道菜难度系数简单,而且味道非常棒哦 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/白灼虾/白灼虾.md b/data/C8/cook/dishes/aquatic/白灼虾/白灼虾.md new file mode 100644 index 0000000..e121268 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/白灼虾/白灼虾.md @@ -0,0 +1,56 @@ +# 白灼虾的做法 + +白灼虾非常适合程序员在沿海地区做,类似于清蒸鱼:简单容错、有营养、有满足感,甚至很好看。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 活虾 +- 洋葱 +- 姜 +- 蒜 +- 葱 +- 食用油 +- 酱油 +- 料酒 +- 芝麻 +- 蚝油 +- 香醋 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +- 虾 250g * 份数(建议 1-2 人份) +- 葱 一根 +- 姜 一块 +- 洋葱 一头 +- 蒜 5-8 瓣 +- 食用油 10-15ml +- 料酒 20 ml +- 酱油 10-15ml +- 芝麻 一把 +- 香醋 10 ml +- 蚝油 10 ml + +## 操作 + +- 洋葱切小块,姜切片,平铺平底锅。 +- 活虾冲洗一下(去除虾线、剪刀减掉虾腿虾须子都是可选操作),控水,铺在平底锅的洋葱、姜片之上。 +- 锅内倒入料酒,盖上锅盖,中火 1 分钟,小火 5 分钟,关火 5 分钟。 +- 和上一步并行操作,制作蘸料: + - 葱切成葱花、蒜切碎、倒入酱油、芝麻、香醋,搅拌之。 + - 油烧热,淋入蘸料。 +- 虾出锅,用干净的盘子装好。 + +![白灼虾](./白灼虾.webp) + +## 附加内容 + +- 技术细节: + - 开始不能大火、防止糊底。 + - 如果锅盖有通气口、时间要相应调节一下(考虑增加 30 秒中火)。 + - 蘸料其实也是可选的、也可以是纯的醋,大自然馈赠的鲜虾在没有水带走冲淡鲜甜的情况下口感味道都非常棒的。 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/白灼虾/白灼虾.webp b/data/C8/cook/dishes/aquatic/白灼虾/白灼虾.webp new file mode 100644 index 0000000..9a0d155 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/白灼虾/白灼虾.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:95333f6dc71486bbd921a95fab2304fe47a6c1c94d93ca099730ff98b1006776 +size 164196 diff --git a/data/C8/cook/dishes/aquatic/糖醋鲤鱼/成品.jpg b/data/C8/cook/dishes/aquatic/糖醋鲤鱼/成品.jpg new file mode 100644 index 0000000..5f5d7a6 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/糖醋鲤鱼/成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f27e7bd12a4467c047813eafac25eb704b010f375bf388b518c2196f5e55cca0 +size 196602 diff --git a/data/C8/cook/dishes/aquatic/糖醋鲤鱼/糖醋鲤鱼.md b/data/C8/cook/dishes/aquatic/糖醋鲤鱼/糖醋鲤鱼.md new file mode 100644 index 0000000..421a067 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/糖醋鲤鱼/糖醋鲤鱼.md @@ -0,0 +1,67 @@ +# 糖醋鲤鱼的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 鲤鱼 +- 番茄酱 +- 白糖 +- 白醋 +- 淀粉 +- 盐 +- 葱 +- 姜 +- 料酒 +- 香菜一颗 +- 盆(两个) +- 菜刀一个 +- 笊篱一个、锅铲一个 + +## 计算 + +注意,该菜只有 3 人以上版本(过大或太小的鱼都是不合适的),所以不需要公式计算,特别适合家庭聚餐时食用,如年夜饭 + +- 鲤鱼 = 约 3 斤 +- 清水 = 50g +- 番茄酱 = 40g +- 白糖 = 20g +- 白醋 = 10g +- 淀粉 = 10g +- 盐 = 30g +- 大葱 = 30g(约半颗) +- 姜 = 30g +- 料酒 = 25g + +## 操作 + +- 将鱼清洗干净,确保无鱼鳞等异物 +- 将鱼头朝左,鱼肚朝下,右手持刀。刀竖直切下 1cm,按紧鱼身往左片 3-4cm,再将鱼片中间轻轻划一刀 +- 将鱼放进盆里,然后将大姜切片,大葱切段(随便切切就行了,主要是需要去腥味) +- 用吃奶的力气将大葱大姜里的汁水挤到盆中 +- 加入 20g 盐,25g 料酒,然后给鲤鱼搓个澡,涂抹均匀 +- ![腌制](./腌制.jpg) + + (腌鱼时间越长,鱼腥味就越小,推荐腌 30 分钟以上) + +- 找个干净的盆,加入 100g 面粉、200g 淀粉、180g 水、5g 盐,用手将其搅拌均匀,面糊此时粘稠呈可拉丝状态,然后打入一个鸡蛋,再次搅匀 +- 等待 30 分钟 +- 将鱼放在案板上,用干毛巾将鱼身上的水擦干(这样可以更好的挂糊) +- 将盆冲洗干净,用干毛巾擦干 +- 起锅烧油,加入约 1L 的油,将油温烧至 7 成热,约 200-240 度 +- 捏起鱼的尾巴,将鱼头沉入锅底,用勺子往鱼的身上淋热油,待面糊成型后,将鱼慢慢放入锅中,拿锅铲轻轻铲起鱼的头部,然后垫上笊篱。防止底部炸糊。 +- 准备一个盛鱼的盘子,放在锅的旁边。 +- 用锅铲从鱼身处轻轻铲入,两个工具配合鱼翻个身。再炸两分钟,还是同样的方式(笊篱托着鱼头,锅铲托着鱼身,将鱼盛入盘中) +- 将锅中的油倒入擦干的盆中,放置一边,然后将锅刷干净 +- 将 50g 清水、40g 番茄酱、20g 白糖、10g 白醋放入小碗中,搅拌均匀 +- 再准备一个小碗加入 10g 淀粉、10g 水,搅拌成水淀粉 +- 开大火将锅烧热,然后倒入之前准备的料汁,大火烧开,转小火 +- 加入调好的水淀粉,边倒边搅拌,然后 20 秒后关火 +- 将熬好的糖醋汁用勺子均匀地浇在鱼身上,可以加点香菜或葱花点缀,糖醋鲤鱼就做好了 +- ![成品](./成品.jpg) + + 这里的糖醋汁熬的有点稠了...... + +## 附加内容 + +这道菜难度系数算中等吧,对新手还是不太友好的...... \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/糖醋鲤鱼/腌制.jpg b/data/C8/cook/dishes/aquatic/糖醋鲤鱼/腌制.jpg new file mode 100644 index 0000000..279f6d9 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/糖醋鲤鱼/腌制.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:738cfdf74dd7f3540f40787f890500a7c2b01e6c6af12163599ba35140c94192 +size 177914 diff --git a/data/C8/cook/dishes/aquatic/红烧鱼.md b/data/C8/cook/dishes/aquatic/红烧鱼.md new file mode 100644 index 0000000..9aca93a --- /dev/null +++ b/data/C8/cook/dishes/aquatic/红烧鱼.md @@ -0,0 +1,63 @@ +# 红烧鱼的做法 + +- **WARNING** 如果没有使用过菜刀剁过肉类食物,那么并不推荐使用该菜单!!! +- 在操作中,锋利的菜刀可能会划伤手指,请一定要小心。 + +- 此做法代表通用红烧鱼做法,材料分为必备和可添加~ + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 姜、蒜瓣、干辣椒 +- 油、盐、料酒、醋、酱油、白砂糖 +- 鱼 + +### 可额外添加的材料 + +注意这些材料都是经验计算得出,除了香菜外其他多了并不是一件好事儿 + +- 蚝油 +- 葱 +- 香菜 +- 小米椒 +- 味精(鸡精) + +## 计算 + +* 鱼 建议新手以一条中等大小的鲫鱼上手,提前划好花刀,方便成熟(不然鱼背上容易夹生) +* 姜丝,以正常老姜切 2-3 片,然后片丝即可 +* 蒜瓣 3-4 个,拍碎或者切碎或者切片 +* 干辣椒(依照个人口味)2-3 个,切碎 +* 香菜按照个人口味 +* 盐 10g,如果辣椒辣度高,建议多一点 +* 醋 5ml +* 酱油 5ml +* 白砂糖 10g +* 葱 1-2 根,正常就撒葱花 +* 小米椒 1-2,不放也可以,过来人的经验,最多放 2 个,不然辣度过高要菊花残。 +* 味精,看个人口味,不要放多,5g 即可。 +* 蚝油,5g 即可,和味精一个道理 + +## 操作 + +### 原材料准备 + +* 姜蒜准备好,切碎 +* 干辣椒切碎,和姜蒜一起 + +### 最终步骤 + +* 加入 30-50ml 油,等待锅热... +* 放入**擦干水分的鱼**(不想被热油溅一身的话),然后晃动锅,用热油煎鱼,注意这过程一定要小火 +* 将鱼翻面,重复上面油煎过程 +* 放入姜蒜辣椒,翻炒出香味 +* 倒入料酒,稍微多一点,此过程注意安全,会起大量油烟 +* 倒入醋(喜欢醋可以多放一点) +* 然后放入白砂糖,酱油(老抽) +* 加入冷水,以刚好淹没鱼身为宜,然后调成中火,盖上锅盖,大概 1 分钟后将鱼翻身,继续盖上锅盖 +* 3-4 分钟后,加入盐、小米椒、蚝油(味精、鸡精等),然后继续盖上锅盖,后续继续要翻身 +* 当锅内汤汁收汁到鱼的脊背线上的鱼鳍下面一点点的时候(或者汤汁不多的时候),转小火,加入香菜,葱花,然后盖上锅盖 20 秒,关火 +* 起锅 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/红烧鱼头.md b/data/C8/cook/dishes/aquatic/红烧鱼头.md new file mode 100644 index 0000000..7d17a19 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/红烧鱼头.md @@ -0,0 +1,71 @@ +# 红烧鱼头的做法 + +- **WARNING** 如果没有使用过菜刀剁过肉类食物,那么并不推荐使用该菜单!!! +- 在操作中,锋利的菜刀可能会划伤手指,请一定要小心。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 注:如果有可能,尽量另准备一把菜刀,超市或市场上均有廉价且刀片更厚的菜刀,刀片厚度在 5-7mm 为最佳。 +- 大葱、姜、大蒜、香菜、美人椒 +- 油、盐、鸡精、生抽、老抽、陈醋、黑胡椒粉、料酒 +- 八角、干辣椒 +- 鱼头一个 +- 注:市场直接贩卖的鱼头一般分为两种:白鲢、花鲢。前者价格便宜,后者价格略贵,但口感也更佳! + +## 计算 + +注意,这道菜仅有足够 2 人食用的版本。 + +* 鱼头一个 +* 大葱 200g +* 姜 80g +* 蒜瓣 3-4 个 +* 美人椒 1/4 个 +* 香菜 4 棵 +* 八角两个,干辣椒五个 + +## 操作 + +### 原材料准备 + +* 葱、姜、蒜、香菜、美人椒分别清洗干净。 +* 干辣椒与八角稍微冲洗即可。 +* 大葱切两半。后半段大葱(葱白处)切段,每段长度约 4cm。前半段(葱叶处)先切段,再将每段劈为四瓣。 +* 姜切片,每片厚度约 3mm。 +* 大蒜拍碎。 +* 拿出两棵香菜去根,切为 1.5cm 香菜碎。 +* 将美人椒切为厚度为 3mm 的辣椒圈。 +* 干辣椒切四段。 + +### 腌制鱼头 + +* 注:下文所述的鱼身是购买鱼头时所附带的鱼肉。 +* 将鱼头去鳞,清洗鱼头处未被清理干净的内脏。 +* 剁去鱼鳍、清理鱼鳃。 +* 将鱼头下巴与鱼身连接的地方剁开,鱼身剁块,鱼头剁成四/六瓣。 + * 注:鱼的处理很难用文字完全表述,可以搜索鱼头处理相关视频。 +* 将剁好的鱼头进行清洗,最好洗掉鱼块上滞留的血水。 +* 将清洗好的鱼块放入盆中,加入 5g 盐、10g 生抽、10g 料酒。放入葱(前半段切碎的那个)、1/3 姜片。将其拌匀,静置 1-2 小时。 + +### 最终步骤 + +* 加入 30ml 油,等待锅热... +* 油热,将锅关至小火 + * 如果不明白为何要这样做,请查看[学习炒与煎](../../tips/learn/学习炒与煎.md)中的翻炒辅料。 +* 放入姜片,慢慢翻炒,以姜片中的大部分汁水被炒出,以金黄色为准。 +* 放入葱段,翻炒至葱段略显发白。 +* 放入蒜碎、八角、干辣椒,翻炒 5 秒。 +* 将腌制好的鱼头倒入锅中,翻炒 2-3 分钟。 +* 倒入 500ml 清水,加入 2g 盐、3g 鸡精、5g 生抽、3g 老抽、5g 料酒、2g 黑胡椒粉、3g 陈醋。 +* 将两棵香菜放入锅中,盖上锅盖。 +* 调至大火,将水烧开。 +* 调至中火,慢焖入味。 +* 当汤汁减少一半时,打开锅盖。 +* 调至大火收汁,汤汁剩余 1/3 时,关火盛至小盆中。 +* 注:将锅中的汤汁均匀淋到鱼头上,盛盘时可以将锅中煮的香菜放入小盆底部,这样能让成品菜好看又好吃。 +* 将香菜放至已经盛出的鱼头上,把切好的美人椒圈放在香菜之上。 +* 色香味俱全的红烧鱼头出炉! + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/红烧鲤鱼.md b/data/C8/cook/dishes/aquatic/红烧鲤鱼.md new file mode 100644 index 0000000..81c68ed --- /dev/null +++ b/data/C8/cook/dishes/aquatic/红烧鲤鱼.md @@ -0,0 +1,60 @@ +# 红烧鲤鱼的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 大葱、姜、大蒜、干辣椒 +- 油、盐、生抽、老抽、陈醋、蚝油、料酒、白糖 +- 鲤鱼、五花肉 + +## 计算 + + 2 人食用的版本。 + +- 鲤鱼 (大约 2 斤) +- 五花肉 100g +- 大葱 200g +- 姜 80g +- 蒜瓣 3-4 个 +- 干辣椒两个 +- 白糖 50g + +## 操作 + +注:下文所述的鱼是购买时卖家简易处理后的,已刮鱼鳞已去内脏。 + +- 葱、姜、蒜、干辣椒分别清洗干净。 +- 葱白处切段,每段长度约 4cm,再将每段劈为四瓣。 +- 姜切片,每片厚度约 3mm。 +- 一个大蒜拍碎切末,其余蒜切为二瓣。 +- 干辣椒切四段。 +- 五花肉切片,约 4cm*4cm。 +- 清洗鱼。 +- 鱼背肉厚处拉几道斜口,方便入味 +- 锅里多倒点油,烧至 7 成热(刚刚开始冒烟),下入鱼炸 1 分钟至鱼皮稍稍变硬捞出备用(注意不要一下锅就拨弄鱼,等炸一会再拨弄、翻面),炸鱼的油倒出,锅里留一点底油 +- 将锅里底油烧热,下入五花肉,煸出香味。 +- 放入干辣椒、葱、姜、蒜瓣,翻炒 1 分钟。 +- 将炸好的鱼倒入锅中。 +- 沿锅边倒入 + - 50ml 料酒 + - 50ml 陈醋 + - 50ml 味极鲜 + - 20ml 老抽调色 + - 5ml 蚝油提鲜 + - 5g 匙盐 + - 50g 白糖 + - 清水没过鱼面。 +- 调至中火,将水烧开。 +- 调至小火,慢焖入味。 +- 15 分钟 后,打开锅盖,挑出锅里的葱、姜、蒜、干辣椒。 +- 调至大火收汁,汤汁剩余 1/4 时,撒点蒜末,关火盛出。 +- 红烧鲤鱼出锅! + +## 附加内容 + +基于下列原因,需要在红烧鲤鱼中添加五花肉: + +- 五花肉煸炒的时候会出猪油,相比较于植物油,动物油脂更香。 +- 煸炒至金黄的五花肉炖煮过后吃起来也很香的,相当于配菜。 +- 鱼类本身脂肪含量少,所以香味欠缺,着重的是肉质的口感。所以一般做鱼类菜都建议用猪油,想要一锅奶白香醇的鱼汤。猪油是最好的选择~ \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/芥末黄油罗氏虾/芥末黄油罗氏虾.jpg b/data/C8/cook/dishes/aquatic/芥末黄油罗氏虾/芥末黄油罗氏虾.jpg new file mode 100644 index 0000000..816b045 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/芥末黄油罗氏虾/芥末黄油罗氏虾.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:816f7d7bd0c54cee52e8f1ddffebbca96e5f56b9c9e2234520132afc128627a1 +size 333658 diff --git a/data/C8/cook/dishes/aquatic/芥末黄油罗氏虾/芥末黄油罗氏虾.md b/data/C8/cook/dishes/aquatic/芥末黄油罗氏虾/芥末黄油罗氏虾.md new file mode 100644 index 0000000..f42a836 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/芥末黄油罗氏虾/芥末黄油罗氏虾.md @@ -0,0 +1,50 @@ +# 芥末黄油罗氏虾的做法 + +![芥末黄油罗氏虾](./芥末黄油罗氏虾.jpg) +这是一道做法简单,味道美味,具有新意的海鲜菜。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 罗氏虾 +* 黄油 +* 芥末 +* 白糖 +* 生抽 +* 蚝油 +* 盐 +* 料酒、朗姆酒或啤酒 +* 香菜 +* 蒜 + +## 计算 + +按照 1 盘的份量: + +* 罗氏虾 1 斤多 广东市场价大概 40~45 一斤 +* 黄油 约 20g +* 芥末 15g +* 白糖 3g +* 生抽 30g +* 蚝油 30g +* 盐 3g +* 料酒、朗姆酒或啤酒 15g 到 30g +* 香菜 5 条 切段 +* 蒜 5 颗 剁成蒜蓉 + +## 操作 + +* 将罗氏虾剪掉头尾尖刺、触须和脚,剪刀把虾身开背,去除虾线。 +* 提前搅拌好芥末酱汁:酱油、蚝油、芥末、盐、糖,搅拌均匀! +* 洗好香菜,切段备用。 +* 罗氏虾沥掉水,锅中加入油,直接放入罗氏虾,中火,外表煎至金黄,捞出。 +* 下入蒜蓉,大火,利用煎虾剩下的油继续煎炒蒜蓉,等到锅中白雾冒出,蒜蓉已经煎出香味,下虾和黄油,让虾充分吸收黄油香味 +* 下入调好的酱汁,继续大火煮沸,翻炒虾,至酱汁收汁,加入酒(料酒、啤酒可以放 30g,朗姆酒味道浓郁放 15g 即可。) +* 在等酱汁稍微收汁,加入香菜翻炒两下,即可出锅。 + +## 附加内容 + +* 酱汁提前调配好,黄油提前备好,防止中间备料耗时。 +* 蒜蓉切记要等虾煎好后捞出再下,防止煎炒过久变黑,发苦。 +* 如果不太能接受芥末就放少点,能接受就放多点,如果放多了,煮久一会儿,芥末味也会散去。 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/葱油桂鱼/10.jpg b/data/C8/cook/dishes/aquatic/葱油桂鱼/10.jpg new file mode 100644 index 0000000..c9eb72d --- /dev/null +++ b/data/C8/cook/dishes/aquatic/葱油桂鱼/10.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f93cc9ee9bf97317a47072c93af5ba902b0bdde2037740600a33353bcb076fd +size 274902 diff --git a/data/C8/cook/dishes/aquatic/葱油桂鱼/葱油桂鱼.jpg b/data/C8/cook/dishes/aquatic/葱油桂鱼/葱油桂鱼.jpg new file mode 100644 index 0000000..fce0a18 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/葱油桂鱼/葱油桂鱼.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e31d4df915d3718d4075b35a65eec97e9d92b0150388c9dc6f24c6dd802c1257 +size 467681 diff --git a/data/C8/cook/dishes/aquatic/葱油桂鱼/葱油桂鱼.md b/data/C8/cook/dishes/aquatic/葱油桂鱼/葱油桂鱼.md new file mode 100644 index 0000000..68560b9 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/葱油桂鱼/葱油桂鱼.md @@ -0,0 +1,65 @@ +# 葱油桂鱼的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 桂鱼 +- 小葱 +- 小米辣 +- 姜 +- 料酒 +- 植物油 +- 盐 +- 蒸鱼豉油 +- 蒸笼(含蒸锅) +- 清水 +- 砧板 +- 铁锅 +- 塑料盘或塑料盆(腌鱼用) +- 一次性手套 +- 厨房纸 +- 蒸鱼盘子(能平放下一条鱼即可) +- 菜刀 +- 削皮刀 +- 防烫盘夹(或者防烫手套) + +## 计算 + +这里以 2 份 为例进行编排。实际操作过程中,考虑到鱼肉本身的质感和鲜味会随着单条鱼的体积有所变化,建议大家在烹饪的时候尽量选择以 2 份 的量进行操作鲜味最佳 + +- 桂鱼 = 1 斤(500g) +- 小葱 = 1 根(长度为 30cm) +- 小米辣 = 2 个 +- 姜 = 50g +- 料酒 = 25g +- 植物油 = 15g +- 盐 = 8g +- 蒸鱼豉油 = 10g +- 清水 = 5L + +## 操作 + +- 去菜市场买已经处理好的鱼(自己处理的话最好不要内脏),将鱼身表面的所有鳞片刮干净 +- 用厨房用纸将鱼肚子里的贴骨血和黑膜擦干净(帖骨血会影响口感,黑膜是鱼腥味的来源) +- 用菜刀在鱼身表面来回刮几次,将鱼身的黏液刮掉,进一步去除腥味,然后用清水将鱼内外冲洗干净 +- 将鱼平放在砧板,使用厨房纸将鱼内外的水分擦干,然后鱼头朝左,尾朝右,从鱼鳃边开始,每隔 3cm 纵向划一刀,深度达到鱼的脊椎骨即可,另一面使用同样的处理方式 +- 将鱼平放在盆中,确保盘中没有多余水分 +- 取一块 50g 姜(鸡蛋大小),用削皮刀把表面的皮去除并洗干净,然后切成厚度为 3mm 的姜片 +- 将小米辣洗干净、去蒂,切成厚度为 2mm 的小圆片(或切成 1mm 宽度的丝状) +- 将小葱洗干净,去除根须,切成 3cm 的小段,稍微粗一点的小葱,可以沿着小葱生长的方向沿中间劈开 +- 加入 8g 盐,25g 料酒到盆中,带上一次性手套,然后对鱼进行全身按摩 1 分钟,确保鱼身每个部位都均匀涂抹了盐和料酒 +- 按摩好鱼后,在鱼身的每一个刀口中塞入一片姜片,鱼肚子中放入 3 片姜片,腌制 10 分钟(建议不要腌制太久,否则鱼的鲜度降低) +- 在鱼腌制期间,在蒸锅中加入 5L 清水,烧开后,在蒸锅上放上蒸笼 +- 鱼腌制好后,会析出水分,将多余水分和腌制用料酒、姜片倒掉,用清水冲洗干净鱼身和鱼肚,用厨房纸擦干鱼身和鱼肚 +- 将鱼平放在蒸鱼盘中,重新在鱼身、鱼肚刀口处塞入姜片 +- 然后将蒸鱼盘放入蒸笼中,盖上盖子,中火蒸 20 分钟 +- 期间水蒸气会附着整个鱼和盘子上,凝结后形成鱼汤,出锅后千万不要倒掉这个汤,这个汤汁是鲜味精华 +- 用防烫夹将蒸鱼盘夹出,在鱼身和鱼周围淋上 10g 蒸鱼豉油 +- 然后在鱼身和周围均匀撒上小葱段和小米辣 +- 在铁锅中倒入 15g 植物油,用中小火慢熬 5 分钟,不要用大火,否则油会挥发很快 +- 将出锅后的热油均匀地慢慢地淋在鱼身上,鲜掉眉毛的葱油桂鱼就出炉啦! + +## 附加内容 + +经过若干次测试,成功率 100%,这道菜容错性很高,无论是什么省份、什么口味的人都能兼容。另外,本套教程虽然叫葱油桂鱼的做法,但原料本身不仅限于桂鱼,可以用鲈鱼、多宝鱼等海鱼代替(淡水鱼本身寄生虫会比海鱼多一点,不建议使用淡水鱼,淡水鱼的做法请参考《红烧鱼》等教程),耦合性低、可扩展性强。 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/葱油桂鱼/葱油鲈鱼.jpg b/data/C8/cook/dishes/aquatic/葱油桂鱼/葱油鲈鱼.jpg new file mode 100644 index 0000000..2ce41f7 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/葱油桂鱼/葱油鲈鱼.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c19b1374345a4892af215e526b687e62ee5c75fad536ade857413d022ef387f +size 689071 diff --git a/data/C8/cook/dishes/aquatic/葱烧海参/海参.jpeg b/data/C8/cook/dishes/aquatic/葱烧海参/海参.jpeg new file mode 100644 index 0000000..7cc9d76 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/葱烧海参/海参.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52d4c8976ac7b3830cd7a42a46e9945108edb156208b5634d3b62663d4a60ec6 +size 182359 diff --git a/data/C8/cook/dishes/aquatic/葱烧海参/葱烧海参.jpeg b/data/C8/cook/dishes/aquatic/葱烧海参/葱烧海参.jpeg new file mode 100644 index 0000000..081c158 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/葱烧海参/葱烧海参.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8256763229fc0970307d4edb7e9027cbc4366a9140f327414f35f4ce4fdb5c0d +size 206611 diff --git a/data/C8/cook/dishes/aquatic/葱烧海参/葱烧海参.md b/data/C8/cook/dishes/aquatic/葱烧海参/葱烧海参.md new file mode 100644 index 0000000..36c35f6 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/葱烧海参/葱烧海参.md @@ -0,0 +1,43 @@ +# 葱烧海参的做法 + +![示例菜成品](./葱烧海参.jpeg) + +这道菜的做法并不难,就是海参泡发是需要时间的。疫情隔离在家,干海参是过年前存的年货,正好拿出来尝试一下。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 泡发好的海参![海参](./海参.jpeg) +- 大葱葱白 + +## 计算 + +每份: + +- 泡发好的海参(北极参) 4 个 +- 大葱葱白 1 根大葱的葱白即可 +- 食用油 20-25ml +- 蚝油 20g +- 生抽 5g +- 白糖 2g +- 淀粉 2g + +## 操作 + +- 葱白切成 1cm 的段,备用。 +- 海参切成 1cm 的段,备用。 +- 准备一个空碗,倒入 20g 蚝油, 10g 生抽, 2g 白糖,搅拌均匀。![料汁](./酱汁.jpeg) +- 另一个空碗倒入淀粉,水,制备水淀粉,勾芡用。 +- 热锅,锅内放入 20ml - 25ml 食用油。等待 10 秒让油温升高。 +- 放入葱白,调*小火*,注意不要让葱白变焦。大概煎 3-5 分钟即可。![葱白](./葱白.jpeg) +- 用筷子夹出葱白,放入盘中备用。 +- 倒入调好的料汁,炒香,**等待 1 - 2 分钟** 。 +- 放入切好的海参,翻炒 1 分钟 +- 加入 100 ml 的水, 中小火, **等待 5 分钟** +- 等待锅中汤汁快干的时候,加入水淀粉,加入前面取出的葱白 +- 在外观*呈粘稠状态*后关火,盛盘 ![成品](./葱烧海参.jpeg) + +## 附加内容 + +- 操作时,需要注意观察锅中的水量,如快见底的时候就直接接入水淀粉即可。 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/葱烧海参/葱白.jpeg b/data/C8/cook/dishes/aquatic/葱烧海参/葱白.jpeg new file mode 100644 index 0000000..cbeaef4 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/葱烧海参/葱白.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e07620a44f1c674930260924c0543e8e5c3a50a18a0e0f45546178fd4784ecda +size 219213 diff --git a/data/C8/cook/dishes/aquatic/葱烧海参/酱汁.jpeg b/data/C8/cook/dishes/aquatic/葱烧海参/酱汁.jpeg new file mode 100644 index 0000000..8baebb4 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/葱烧海参/酱汁.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:104a89c8700bcaffae40fe2c159237a8ffd2174c10254d42f4107e9d907da648 +size 86402 diff --git a/data/C8/cook/dishes/aquatic/蒜蓉虾/1.jpeg b/data/C8/cook/dishes/aquatic/蒜蓉虾/1.jpeg new file mode 100644 index 0000000..7282e24 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/蒜蓉虾/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a2c2bd7303179454e8df1bb082b236d7d3d3b8b316e78090f1e40b1d5fd0393 +size 184204 diff --git a/data/C8/cook/dishes/aquatic/蒜蓉虾/2.jpeg b/data/C8/cook/dishes/aquatic/蒜蓉虾/2.jpeg new file mode 100644 index 0000000..25cd1c5 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/蒜蓉虾/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fad64ea2c5e5d484ccd9f144831ac8ced3bf1428830a2b63cb4e974e107c828d +size 154644 diff --git a/data/C8/cook/dishes/aquatic/蒜蓉虾/蒜蓉虾.md b/data/C8/cook/dishes/aquatic/蒜蓉虾/蒜蓉虾.md new file mode 100644 index 0000000..0816414 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/蒜蓉虾/蒜蓉虾.md @@ -0,0 +1,33 @@ +# 蒜蓉虾的做法 + +蒜蓉虾是广东省地方传统名菜,色香味俱全。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 海虾 +* 蒜蓉酱 +* 食用油 +* 生抽 + +## 计算 + +每份: + +* 海虾 8 只 +* 蒜蓉酱 50 g +* 食用油 20 ml +* 生抽 5 ml + +## 操作 + +* 用刀从从虾头中间切开,切到距离虾尾 1 cm +* 将蒜蓉酱铺在虾身中间,放在盘子中 +* 锅中倒入热水,将盘子放入锅中,大火蒸 3 分钟 +* 烧热油,倒入虾盘中,倒入生抽 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/蒜香黄油虾/1.jpg b/data/C8/cook/dishes/aquatic/蒜香黄油虾/1.jpg new file mode 100644 index 0000000..b801b4d --- /dev/null +++ b/data/C8/cook/dishes/aquatic/蒜香黄油虾/1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b586a85222af25349f456faab6f9fa56f4fea9d33c7056f0b23de19324972beb +size 893586 diff --git a/data/C8/cook/dishes/aquatic/蒜香黄油虾/蒜香黄油虾.md b/data/C8/cook/dishes/aquatic/蒜香黄油虾/蒜香黄油虾.md new file mode 100644 index 0000000..78c9b9d --- /dev/null +++ b/data/C8/cook/dishes/aquatic/蒜香黄油虾/蒜香黄油虾.md @@ -0,0 +1,46 @@ +# 蒜香黄油虾的做法 + +蒜香黄油虾是一道经典的西式海鲜料理,以鲜虾为主料,配以蒜末和黄油烹制而成。口感鲜嫩,蒜香浓郁。制作简单,适合家庭日常烹饪。 + +![蒜香黄油虾](./1.jpg) + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 大虾(推荐黑虎虾或基围虾) +- 无盐黄油(推荐安佳) +- 大蒜 +- 白葡萄酒(可选) +- 柠檬 +- 平底煎锅 +- 厨房用夹 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1-2 人食用。 + +每份: + +- 大虾 8-10 只(约 200g) +- 无盐黄油 30g +- 大蒜 4 瓣(约 20g) +- 白葡萄酒 15ml(可选) +- 柠檬 1/4 个 +- 橄榄油 10ml + +## 操作 + +- 大虾去头去壳留尾,用牙签挑去虾线,洗净后用厨房纸吸干水分 +- 大蒜切成蒜末,备用 +- 中火加热平底锅,放入 10ml 橄榄油 +- 油热后放入大虾,每面煎 1-1.5 分钟至变色,取出备用 +- 同一锅中加入黄油,融化后放入蒜末,小火炒香(约 30 秒) +- 如使用白葡萄酒,此时加入并煮至酒精挥发(约 1 分钟) +- 将虾放回锅中,与蒜香黄油酱汁翻炒均匀(约 1 分钟) +- 挤入柠檬汁,翻炒均匀后立即关火 +- 装盘,淋上锅中剩余酱汁 + +## 附加内容 + +- 虾不宜过度烹饪,否则会变硬 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/蛏抱蛋/1.jpeg b/data/C8/cook/dishes/aquatic/蛏抱蛋/1.jpeg new file mode 100644 index 0000000..1e18711 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/蛏抱蛋/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:19ee70651712e392a1650628306b3f7a80d100c8b8d06e2c99e8576faee4a634 +size 155301 diff --git a/data/C8/cook/dishes/aquatic/蛏抱蛋/2.jpeg b/data/C8/cook/dishes/aquatic/蛏抱蛋/2.jpeg new file mode 100644 index 0000000..c378552 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/蛏抱蛋/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:570a523b2242606fb521bd0fd57cc28d6dfba8b7e06d2a754ce4e65eda673325 +size 160679 diff --git a/data/C8/cook/dishes/aquatic/蛏抱蛋/3.jpeg b/data/C8/cook/dishes/aquatic/蛏抱蛋/3.jpeg new file mode 100644 index 0000000..82f4ca6 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/蛏抱蛋/3.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21d01034bc0c7029bae724690bb5f03c6506a4ed372a6a16f5aeb7d494df3df5 +size 183338 diff --git a/data/C8/cook/dishes/aquatic/蛏抱蛋/蛏抱蛋.md b/data/C8/cook/dishes/aquatic/蛏抱蛋/蛏抱蛋.md new file mode 100644 index 0000000..327d2bb --- /dev/null +++ b/data/C8/cook/dishes/aquatic/蛏抱蛋/蛏抱蛋.md @@ -0,0 +1,46 @@ +# 蛏抱蛋的做法 + +蛏抱蛋,是流行于福建省福州地区的传统家常菜 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 蛏子 +* 鸡蛋 +* 食用油 +* 洋葱 +* 淀粉 +* 生抽 +* 鸡精 +* 料酒 + +## 计算 + +每份: + +* 蛏子 200 g +* 鸡蛋 2 个 +* 食用油 100 ml +* 洋葱 0.25 个 +* 淀粉 20 g +* 生抽 5 ml +* 鸡精 5 ml +* 料酒 5 ml + +## 操作 + +* 烧开水,将蛏子放入水中,水煮 2 分钟后,捞上来去壳,放入大碗 +* 往大碗中加入洋葱、生抽、料酒、鸡精、生粉后,充分搅拌 +* 往大碗中打入 2 个 鸡蛋,继续搅拌 +* 起锅烧油,倒入碗中蛏子,煎炸至单面金黄后,翻面继续煎炸 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) +![示例菜成品](./3.jpeg) + +## 附加内容 + +* 更多情况下,福州当地会选用马蹄(解腻)和马铃薯(洗油),因为疫情期间买不到,所以选用了凤梨 +* 闽菜以甜为主,如果吃不惯的可以放弃白糖 +* 可以通过勺子敲打瘦肉块,听到声响来判断是否炸透瘦肉 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/香煎翘嘴鱼/香煎翘嘴鱼.jpeg b/data/C8/cook/dishes/aquatic/香煎翘嘴鱼/香煎翘嘴鱼.jpeg new file mode 100644 index 0000000..0b59d66 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/香煎翘嘴鱼/香煎翘嘴鱼.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:721a6ad9b94524c16febebe147e923a10a8359700b270d48fd792fb78cb64c24 +size 50316 diff --git a/data/C8/cook/dishes/aquatic/香煎翘嘴鱼/香煎翘嘴鱼.md b/data/C8/cook/dishes/aquatic/香煎翘嘴鱼/香煎翘嘴鱼.md new file mode 100644 index 0000000..a7a33d7 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/香煎翘嘴鱼/香煎翘嘴鱼.md @@ -0,0 +1,60 @@ +# 香煎翘嘴鱼的做法 + +![香煎翘嘴鱼](./香煎翘嘴鱼.jpeg) + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 翘嘴鱼(肉食性鱼类,肉细腻,口感好) +- 姜 +- 葱 +- 蒜 +- 青椒 +- 香菜 +- 老抽 +- 白糖 +- 豆瓣酱 +- 料酒 +- 生抽 +- 盐 + +## 计算 + +注:这个量大概是 2-3 个人的量 + +每份: + +- 翘嘴鱼:2 斤最佳 +- 姜沫:20g +- 葱:半根(50 克) +- 蒜:4 个 +- 香菜:个人口味 +- 老抽:2ml(不太喜欢重口的可以不放) +- 白糖:10g +- 干辣椒:4-6 个(根据个人口味选择) +- 料酒:100ml +- 生抽:4ml +- 盐:约 50g 用于腌制鱼 +- 食用油:100ml + +## 操作 + +- 鱼开背杀好(让卖鱼的杀好,千万不要剖腹杀鱼,切记是开背),清洗干净 +- 鱼表面用盐涂抹均匀,倒入料酒约 80ml,姜末 20g,放入冰箱保鲜层进行腌制 1-2 天 +- 取出腌制好的鱼,用绳挂起晾晒至半干(约 1-2 天,具体时间需结合气温与阳光) +- 食用前请将鱼用清水清洗,沥干水分(防止水遇油飞溅) +- 开大火将锅烧热,迅速改小火,锅中放油,尽量保持整个锅表面有油,将鱼沿锅边划入锅内(先煎鱼背面) +- 鱼入锅后(和翻面后),不要着急移动鱼的位置(此时容易破皮),煎约 30 秒后,尝试晃动锅 +- 背面煎约 1 分钟后,翻面煎约 1-2 分钟,煎至两面金黄 +- 等两面都煎好时,把鱼推向锅边一点,留点空间放入豆瓣酱炒香味,放入姜蒜, +- 炒出佐料香味后,加入料酒,生抽,老抽,倒入热水,水量和鱼平齐或者少点 +- 此时改中大火,煮 5-10 分钟,后放入青椒断,白糖,鸡精,十三香,陈醋 +- 改小火 2-5 分钟,放入葱,香菜,即可出锅 + +## 附加内容 + +- 切记鱼是开背杀,腌制时,鱼表面涂抹均匀食盐即可,腌制时间,晾晒时间 1-2 天即可 +- 煎鱼全程小火,刚入锅时不要移动鱼,会破皮 +- 青椒断放入后注意观察熟透程度,里面的青椒很好吃,另外香菜最后放 +- 注意火候的切换,豆瓣酱,白糖的调鲜效果,与陈醋的增香效果 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/鲤鱼炖白菜/鲤鱼炖白菜.jpeg b/data/C8/cook/dishes/aquatic/鲤鱼炖白菜/鲤鱼炖白菜.jpeg new file mode 100644 index 0000000..fa6e963 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/鲤鱼炖白菜/鲤鱼炖白菜.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97f47e86075c50d9211d9ed27dd12ba91a623e661da6e13e25e38b33856fddc2 +size 238094 diff --git a/data/C8/cook/dishes/aquatic/鲤鱼炖白菜/鲤鱼炖白菜.md b/data/C8/cook/dishes/aquatic/鲤鱼炖白菜/鲤鱼炖白菜.md new file mode 100644 index 0000000..1138b9b --- /dev/null +++ b/data/C8/cook/dishes/aquatic/鲤鱼炖白菜/鲤鱼炖白菜.md @@ -0,0 +1,52 @@ +# 鲤鱼炖白菜的做法 + +![鲤鱼炖白菜](./鲤鱼炖白菜.jpeg) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 食用油 +- 姜 +- 蒜 +- 鲤鱼 +- 白菜心/娃娃菜 +- 盐 +- 老抽 +- 生抽 +- 桂皮 +- 八角 +- 郫县豆瓣酱 +- 干辣椒(不吃辣可以不放) + +## 计算 + +注:调料根据鱼的大小进行换算。 + +每份: + +- 食用油:10ml +- 姜:3 片 +- 蒜:3 瓣(切成块) +- 鲤鱼:1.2 斤(清理过的) +- 娃娃菜:13 片(可以多放一些,一顿就缩小了) +- 盐:5-8 克 +- 老抽:3ml +- 生抽:6ml +- 桂皮:1 块 +- 八角:3 个 +- 郫县豆瓣酱:20 克 +- 干辣椒:4-6 个(根据个人口味选择) + +## 操作 + +- 鲤鱼清洗干净,改刀(在鱼身上多划几个伤口,方便入味) +- 娃娃菜清洗干净放入盘中备用 +- 锅中加油,等油热放入“少盐” “姜” “蒜” “郫县豆瓣酱” “桂皮” “八角” 炒出香味 +- 把鱼放锅里煎(3 分钟)每(30 秒)需要翻面 +- 加入“水”(水量尽量和鱼平齐,可以少一点点) 放入 “生抽” “老抽” “娃娃菜” +- 大火炖 15-20 分钟,汤汁快干时添加 “盐” 即可出锅 + +## 附加内容 + +- 也可以放一些粉条,粉条先凉水/热水,需要泡软,可以和娃娃菜一起放入 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/鳊鱼炖豆腐/鳊鱼炖豆腐.jpg b/data/C8/cook/dishes/aquatic/鳊鱼炖豆腐/鳊鱼炖豆腐.jpg new file mode 100644 index 0000000..a4cfa97 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/鳊鱼炖豆腐/鳊鱼炖豆腐.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ece70cc98f12c33dd9e66fb0ffedd1e7b94ff9dccc3501addd027174ed2a885d +size 455162 diff --git a/data/C8/cook/dishes/aquatic/鳊鱼炖豆腐/鳊鱼炖豆腐.md b/data/C8/cook/dishes/aquatic/鳊鱼炖豆腐/鳊鱼炖豆腐.md new file mode 100644 index 0000000..d35b93f --- /dev/null +++ b/data/C8/cook/dishes/aquatic/鳊鱼炖豆腐/鳊鱼炖豆腐.md @@ -0,0 +1,62 @@ +# 鳊鱼炖豆腐的做法 + +![鳊鱼炖豆腐](./鳊鱼炖豆腐.jpg) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鳊鱼(鱼可以让摊主帮忙处理好) +- 老豆腐 +- 姜 +- 葱 +- 蒜 +- 老抽 +- 桂皮(可选) +- 冰糖 +- 干辣椒(不吃辣可以不放) +- 料酒 +- 生抽 +- 盐 +- 八角(可选) +- 香叶(可选) +- 热水 + +## 计算 + +注:这个量大概是 2-3 个人的量 + +每份: + +- 鳊鱼:550 克 +- 老豆腐:400 克 +- 姜:5 片 +- 葱:半根(50 克) +- 蒜:4 个 +- 老抽:2ml(不太喜欢重口的可以不放) +- 桂皮:1 块 +- 冰糖:5 块 +- 干辣椒:4-6 个(根据个人口味选择) +- 料酒:5ml +- 生抽:4ml +- 盐:5-8 克(根据个人口味选择) +- 八角:1 个 +- 香叶:1-3 片 +- 食用油:10ml +- 热水:400 克 + +## 操作 + +- 鳊鱼改刀,放上姜片和料酒腌制 5-10 分钟 +- 老豆腐切块后放入水中备用 +- 锅中加油,可以放点盐在锅里,防止煎鱼的时候粘锅,把腌制的鱼用厨房纸擦干水分,把鱼放到锅中,两面都煎一下 +- 等两面都煎好时,把鱼推向锅边一点,留点空间放入葱姜蒜,干辣椒,香叶,八角炒出味道 +- 炒出佐料香味后,加入料酒,生抽,老抽,冰糖,桂皮,倒入热水,水量和鱼平齐或者少点 +- 大火烧开后,放入老豆腐,豆腐贴在锅边,加入食盐,转小火 +- 小火烧 10-15 分钟,然后大火收点汁,即可出锅 + +## 附加内容 + +- 鱼的两面,各煎 2-4 分钟即可 +- 煎鱼的时候全程中小火 +- 最后出锅时,加入一些切碎的大蒜,味道会更好 \ No newline at end of file diff --git a/data/C8/cook/dishes/aquatic/黄油煎虾/黄油煎虾.jpg b/data/C8/cook/dishes/aquatic/黄油煎虾/黄油煎虾.jpg new file mode 100644 index 0000000..fff05a4 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/黄油煎虾/黄油煎虾.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3215cc4bd2a584da624aea7661b2ef98fe9fddb535027d2437309be9d2841c75 +size 811157 diff --git a/data/C8/cook/dishes/aquatic/黄油煎虾/黄油煎虾.md b/data/C8/cook/dishes/aquatic/黄油煎虾/黄油煎虾.md new file mode 100644 index 0000000..291ce43 --- /dev/null +++ b/data/C8/cook/dishes/aquatic/黄油煎虾/黄油煎虾.md @@ -0,0 +1,44 @@ +# 黄油煎虾的做法 + +![示例菜成品](./黄油煎虾.jpg) + +黄油煎虾是一道制作相对简单、风味极佳的菜式,主要耗时在于处理活虾,总耗时在一个小时内,适合初学者进行烹饪。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鲜虾(强推肉质紧实的九节虾,普通明虾也可以) +- 黄油(推荐安佳,一次用一小盒 7g) +- 黑胡椒粒(瓶磨的那种) +- 生抽 +- 盐 +- 白糖 +- 米酒 + +## 计算 + +每份: + +- 鲜虾 300g +- 黄油 7g +- 黑胡椒粒 大概 15ml +- 食用油 45ml +- 生抽 10ml +- 米酒 5ml +- 白糖 10ml +- 盐 2.5ml + +## 操作 + +- 鲜虾摘除头部,顺带扯出虾线(这步处理不好可在下一步开背时取出虾线),使用剪刀剪开或菜刀片开虾背,沥干水分备用 +- 调制酱汁:小碗放入上述量的全部生抽、米酒、白糖、盐搅匀备用 +- 中大火热锅,热锅内放入食用油,等待 10 秒让油温升高 +- 虾全部放入锅中,开始瓶磨黑胡椒,均匀地撒在虾上翻炒 +- 虾变色后加入黄油,黄油完全融化后倒入调制酱汁,继续翻炒 +- 大火翻炒 15 秒收汁即可装盘 + +## 附加内容 + +- 虾开背才更好入味,不过处理时切记切记小心用刀,新手容易伤到手 +- [冯小厨的菜谱](https://www.bilibili.com/video/BV1g541177cd) \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/吐司果酱.md b/data/C8/cook/dishes/breakfast/吐司果酱.md new file mode 100644 index 0000000..ed6e643 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/吐司果酱.md @@ -0,0 +1,30 @@ +# 吐司果酱的做法 + +饱腹感的懒人快速营养早餐,2 分钟 搞定 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 新鲜吐司 +- 果酱 +- 面包机 + +## 计算 + +- 吐司两片 +- 果酱足够涂满一面吐司的量 + +## 操作 + +- 将吐司放入面包机 +- 设置好档位,时间到了会自动弹出 +- 两分钟后吐司加热完成弹出 +- 先取出一片吐司,涂满果酱再盖上另一片吐司即可 +- 用餐巾纸包一下可以边走边吃也可以吃完再出门 + +两分钟快速搞定,操作很简单,味道十分美味,十分适合程序员。耗时短,不会产生额外垃圾,也不需要清洗工具什么的。 + +## 附加内容 + +面包机一般不会超过一百块,吐司去楼下超市或美团买菜送上门,一般一包十块钱八片,保质期比较短,很干净卫生。 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/太阳蛋.md b/data/C8/cook/dishes/breakfast/太阳蛋.md new file mode 100644 index 0000000..584221a --- /dev/null +++ b/data/C8/cook/dishes/breakfast/太阳蛋.md @@ -0,0 +1,47 @@ +# 太阳蛋的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 鸡蛋 +- 盐 +- 油 +- 分可控火候微波炉或不可控火候微波炉(定义和分辨方式请见附加内容) +- 筷子或牙签 + +## 计算 + +- 鸡蛋的用量为 1 个。 +- 盐的用量为 1 g 每个鸡蛋。 +- 油的用量为 5 mL 每个鸡蛋。 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 可控火候微波炉 + +- 准备一个小碗,倒入在上一步计算好的油,撒盐,搅拌均匀。倾斜碗使油沾在碗表面。 +- 取出一个鸡蛋,打入小碗。 +- 蛋黄表面戳孔。牙签戳 5 个或筷子戳 1 个。 +- 放入微波炉,中火 3 分钟。 + +### 不可控火候微波炉 + +- 准备一个小碗,倒入在上一步计算好的油,撒盐,搅拌均匀。倾斜碗使油沾在碗表面。 +- 取出一个鸡蛋,打入小碗。 +- 蛋黄表面戳孔。牙签戳 5 个或筷子戳 1 个。 +- 放入微波炉,1 分钟。 +- while(太阳蛋 否 大面积成固体状) 用微波炉打(30s); + +## 附加内容 + +while(太阳蛋的熟度 不符合 个人口味) 用微波炉打(1 分钟); + +- 不可控火候微波炉: + - 定义: 即无法控制火候仅能控制时长的微波炉。 + - 辨别方法: 若在微波炉操作面板上无法找到小火,中火, 大火等字样即为不可控火候微波炉 +- 可控火候微波炉: + - 定义:即能控制火候又能控制时长的微波炉, + - 辨别方法: 若在微波炉操作面板上能找到小火,中火,大火等字样即为可控火候微波炉 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/完美水煮蛋.md b/data/C8/cook/dishes/breakfast/完美水煮蛋.md new file mode 100644 index 0000000..d1e1a05 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/完美水煮蛋.md @@ -0,0 +1,43 @@ +# 完美水煮蛋的做法 + +![完美水煮蛋](https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1yBdnK.img?w=768&h=512&m=6) + +科学家研发的循环水煮法,可同时达到蛋黄绵密、蛋白均匀凝固且保留最多营养素的效果。需精准控制温度与时间,难度较高。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 新鲜鸡蛋(推荐 AA 级) +- 100°C 沸水锅(直径≥ 15cm) +- 30°C 温水锅(直径≥ 15cm) +- 定时器 +- 漏勺 + +## 计算 + +每份: + +- 鸡蛋 1 个(约 60g ) +- 100°C 沸水 1500ml +- 30°C 温水 1500ml + +## 操作 + +- 准备两锅水: A 锅维持 100°C 沸水, B 锅维持 30°C 温水 +- 用漏勺将鸡蛋放入 A 锅,启动定时器 +- 精准**每 2 分钟**将鸡蛋转移至另一锅水 +- 重复转移操作共 16 次(总时长 32 分钟) +- 最后一次转移后,在 B 锅静置 30 秒 +- 立即放入冰水( 0 摄氏度)终止加热(维持 30 秒) +- 剥壳时从钝端气室处开始,沿纵轴剥离蛋膜 + +## 附加内容 + +- 关键参数: + - 蛋黄中心温度:67±1°C + - 蛋白分层温度: + - 外层:100°C→87°C + - 中层:87°C→55°C + - 内层:55°C→30°C +- 营养优势:多酚含量比传统煮法高 23% \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/微波炉荷包蛋.md b/data/C8/cook/dishes/breakfast/微波炉荷包蛋.md new file mode 100644 index 0000000..8959d66 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/微波炉荷包蛋.md @@ -0,0 +1,35 @@ +# 微波炉荷包蛋的做法 + +微波炉荷包蛋是一道简单易做且富含蛋白质的菜。只需要微波炉 120 秒内就可以完成,适合通勤社畜早餐。 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 鸡蛋 +- 芝麻油 +- 盐 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人早饭佐餐。 + +每份: + +- 鸡蛋 2 个 +- 饮用水 35ml +- 芝麻油 3ml +- 盐 0.8g + +## 操作 + +- 将鸡蛋打入小碗中,用筷子在所有鸡蛋黄上扎 2 个洞,避免加热弄脏微波炉 +- 然后向碗内倒入常温饮用水 +- 再向碗内倒入食用盐 +- 最后加入芝麻油 +- 将放好材料的碗放入微波炉中,高火加热 80 秒 +- 到达设定时间后,使用抹布垫着手取出成品 + +## 附加内容 + +- 微波炉加热前,如果想进一步避免蛋黄和蛋白溅射,可以在碗上盖个盖子避免弄脏微波炉 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/微波炉蛋糕.md b/data/C8/cook/dishes/breakfast/微波炉蛋糕.md new file mode 100644 index 0000000..67b4234 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/微波炉蛋糕.md @@ -0,0 +1,57 @@ +# 微波炉蛋糕的做法 + +微波炉"叮"蛋糕,大约需要 2 分钟 就能搞定!初学者所需时间预计延长至 20 分钟。 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 微波炉 +- 能放进微波炉的容器 +- 黄油 +- 面粉 +- 泡打粉(不加吃着像饼) +- 鸡蛋 + +## 计算 + +- 鸡蛋🥚 1 个 +- 面粉🍚 15g +- 泡打粉🍚 2.5g +- 白(红)糖🍬 10g +- 盐🧂 1g + +(口味可选) + +- 咖啡粉☕ +- 巧克力🍫 +- 麦片🍿 +- 牛奶🥛 +- 坚果🥜 +- 饼干屑🍪 +- 香蕉🍌 +- 非黑暗料理🍆 + +## 操作 + +- 加入以下食材,注意不要超过容器的 3/4 + - 挖半个鸡蛋大的黄油放进容器, 在微波炉**加热 15 秒**至融化 + - 将**巧克力/香蕉** 融化/搅碎成 **颗粒/糊状** + - 打入一个鸡蛋并打散搅和 + - 15g 白(红)糖(甜党可以多加些) (见附 4) + - 加入 1g 盐 (**如果后续的口味食材含盐需自己斟酌**) + - 加入 2.5g 泡打粉 + - 加入 15g 面粉(筋度没太大影响) + - **加入任何喜欢的口味食材!**(坚果与饼干等干食材不是现在放) + - 搅和至看不见干粉的稠酸奶状 + - 加入可选的干燥食材(不包括冲泡粉)在顶端 +- 夸赞一下自己🥰 +- 微波炉(高火)加热 **1分钟** (至蓬松蛋糕形态) +- 取出杯子(烫手啊啊啊啊↑)并拍朋友圈就可以吃了 + +## 附加内容 + +- 在夸赞自己之前的操作可以重复多遍做出更大的蛋糕 +- 泡打粉用来让蛋糕更蓬松 大多不含铝 几块钱一包 可以买了在家备着 +- 在 **加入任何喜欢的口味食材!** 这一步骤中 若加入**液体**(如牛奶) 请务必确保下一步可以搅和成**稠酸奶状** 建议少量多次加入以防止水分过量而导致成品湿瘪 +- **食材不要超过容器的3/4!!** \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/手抓饼.md b/data/C8/cook/dishes/breakfast/手抓饼.md new file mode 100644 index 0000000..9502350 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/手抓饼.md @@ -0,0 +1,57 @@ +# 手抓饼的做法 + +预估烹饪难度:★★ + +--- + +## 必备原料和工具 + +- 普通面粉 +- 开水 +- 冷水 +- 食用油 +- 盐 +- 鸡蛋 +- 生菜 +- 火腿 +- 芝士片 + +--- + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1~2 人食用。 + +总量(按每份): + +- 面粉 200 克 +- 开水 100 毫升 +- 冷水 50 毫升 +- 食用油 15 毫升 +- 盐 3 克 +- 鸡蛋 1 个 +- 生菜 30 克 +- 火腿 30 克 +- 芝士片 1 片 + +--- + +## 操作 + +1. 面粉放入碗中,加入开水搅拌成絮状,再加入冷水揉成光滑面团,覆盖湿布静置 20 分钟。 +2. 面团分成每份约 100 克,搓圆,擀成薄片。 +3. 表面均匀涂抹食用油,撒上盐,卷成蜗牛状,松弛 10 分钟。 +4. 面团再次擀成薄饼,厚度均匀。 +5. 热锅中倒入油,小火煎至两面金黄起泡。 +6. 煎好的饼依次铺入煎蛋、生菜、火腿、芝士片等配料,卷起即可。 + +--- + +## 附加内容 + +- 使用开水与冷水混合和面,有助于提升饼皮柔韧度。 +- 面团醒发时间不宜少于 20 分钟,否则不易擀薄。 +- 可根据个人口味增减配料,建议配料总重控制在 100 克以内。 +- 剩余生饼皮可冷藏保存 24 小时,使用时回温擀平即可。 + +--- \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/桂圆红枣粥.md b/data/C8/cook/dishes/breakfast/桂圆红枣粥.md new file mode 100644 index 0000000..6f78ad8 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/桂圆红枣粥.md @@ -0,0 +1,31 @@ +# 桂圆红枣粥的做法 + +桂圆红枣粥,甜口。补血安神,健脑益智,补养心脾。制作时间需要 70 分钟。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 糯米(或大米) +- 红枣 +- 桂圆 + +## 计算 + +每份: + +- 糯米 100g +- 红枣 15 颗 +- 桂圆 15 颗 + +## 操作 + +- 将桂圆肉扒出,用清水洗两次,放入碗中浸泡 10 分钟 +- 红枣用清水洗两次,放入碗中浸泡 10 分钟 +- 糯米放入电饭锅中,清水淘米两次后,加入 2000ml 水 +- 将桂圆和红枣加入电饭锅 +- 打开电饭锅煮饭模式,1 小时后粥成 + +## 附加内容 + +对粥的稀稠程度有不同喜好的朋友可以酌情增加或减少水的用量,煮出来的粥是甜的,可以通过控制加入桂圆的数量控制甜度 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/水煮玉米.md b/data/C8/cook/dishes/breakfast/水煮玉米.md new file mode 100644 index 0000000..3d1b124 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/水煮玉米.md @@ -0,0 +1,29 @@ +# 水煮玉米的做法 + +大约 15 分钟可以完成制作。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 新鲜玉米 +- 放得下玉米的锅 +- 水 +- 盐 +- 糖(可选) + +## 计算 + +- 一个带皮玉米 +- 淹过玉米约半节指头的水 +- 煮玉米的时候,开始和淡盐水,差不多 2 克盐加 50ml 的水 +- 根据口味选择加或者不加糖(可选) + +## 操作 + +- 将新鲜玉米剥去外皮,剩部分玉米皮入锅 +- 加入淹过玉米约半节指头的水,加盐和糖 +- 水煮开之后转至小火,加盖继续煮 15-20 分钟,玉米煮久点没事。 +- 煮熟后沥干水分,冷却后食用。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/温泉蛋/温泉蛋.md b/data/C8/cook/dishes/breakfast/温泉蛋/温泉蛋.md new file mode 100644 index 0000000..74f9bd5 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/温泉蛋/温泉蛋.md @@ -0,0 +1,59 @@ +# 温泉蛋的做法 + +一种传统的日式小吃,可以用于各种佐餐,注意与溏心蛋区分,溏心蛋是蛋黄不熟蛋白熟了,温泉蛋是蛋白不熟蛋黄熟了 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +### 主食材 + +- 鸡蛋 + +### 必备工具 + +- 厨房用温度计(尽量选用带有夹子的温度计) +- 杯子(无特定要求,只要是杯子就行) + +### 副食材 + +额外用作点缀的食材,可选 + +- 昆布酱油(一种日式的少盐酱油,用于为温泉蛋调味) +- 香葱 + +## 计算 + +- 鸡蛋的用量为 1 个,按照您的食量和锅的大小计算。 + +## 操作 + +### 煮蛋 + +- 在锅中盛装一定量自来水,确保水面没过约鸡蛋 3cm,水中插入温度计 +- 开火或打开电磁炉,逐渐调整电磁炉功率或火苗大小,使得水温保持在 **70 摄氏度** +- 将鸡蛋放入锅中。鸡蛋不可互相堆叠,应皆在底部,并留有空间可以晃动 +- 保持当前温度 **25 分钟** +- 准备一杯冰水 +- 捞出鸡蛋,并立刻放入冰水中,**等待 3 分钟** +- 将鸡蛋打入小碗,完成制作 + +## 附加内容 + +### 流程图解 + +``` mermaid +graph TD + A[锅中加水,插入温度计] --> B[控制水温到70℃] + B --> C[放入鸡蛋,保持水温为70℃ 25分钟] + B --> D[准备冰水] + C --> E + D --> E[鸡蛋捞出放入冰水,等待3分钟] + E --> F[鸡蛋打入小碗] +``` + +### 备注说明 + +- 若使用机械式温度计(无需供电)则温度计探头需没入水中至少 6cm,若使用电子温度计则无特殊要求 +- 锅可以采用稍厚的锅,方便控制温度 +- 虽然 70 摄氏度 25 分钟已经完全可以杀死沙门氏菌,但还是要尽量少吃,或购买正规可生食鸡蛋制作 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/溏心蛋.md b/data/C8/cook/dishes/breakfast/溏心蛋.md new file mode 100644 index 0000000..e293854 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/溏心蛋.md @@ -0,0 +1,33 @@ +# 溏心蛋的做法 + +喜欢健身的小伙伴可以在每颗鸡蛋中获得 6 克蛋白质。大约 15 分钟可以完成制作。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡蛋 +- 电锅 +- 水 +- 秒表(可选) + +## 计算 + +- 鸡蛋 1 颗或更多(只要您的电锅装得下,不管有几颗鸡蛋都可以) +- 淹过鸡蛋约 2 公分的冷水 + +## 操作 + +- 将鸡蛋放入电锅中。鸡蛋不可互相堆叠,应皆在底部,并留有空间可以晃动 +- 倒入淹过鸡蛋约 2 公分的冷水 +- 开盖,使用最大功率加热至水滚起(大约 85 - 95 度,稍微滚动,不需完全沸腾) +- 关火,盖上盖子,让鸡蛋静置。 + - 想要中央有流动的蛋黄,需静置 6 分钟 + - 若想要完全煮熟的易碎蛋黄,需静置 10 分钟 +- 沥干水分,用冷水冲洗鸡蛋约 1 分钟,即可去壳食用。 + +## 附加内容 + +如果觉得鸡蛋不够熟的小伙伴可以依照自己的喜好添加更多的水。 + +**警告** 溏心蛋有沙门氏菌感染的风险。不建议静置 5 分钟以内。 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/煎饺.md b/data/C8/cook/dishes/breakfast/煎饺.md new file mode 100644 index 0000000..031bf75 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/煎饺.md @@ -0,0 +1,30 @@ +# 煎饺的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 饺子(速冻水饺) + +## 计算 + +每份: + +- 饺子一包 (根据个人食量选择, 约 10 - 15 个) + +## 操作 + +- 取出平底锅(不沾平底锅最佳) +- 加入 10ml - 15 ml 食用油 +- 开火,放入饺子(尽量平均铺开,不宜堆叠) +- 立刻加入清水,水线没过饺子平均高度的 1/2 +- 盖上锅盖(此时炉灶应该处于大火) +- 等待 8 - 10 分钟 +- 当锅中水分仅剩 2mm 时, 转中火开始煎制 +- 当水分全部蒸发后,摇晃平底锅使饺子受热均匀 +- 放入黑芝麻和葱花再焖 10s +- 1 - 2 分钟夹出一个饺子观察底部,若出现金黄色脆皮立即取出 + +## 附加内容 + +- 操作时,需时刻观察锅内情况,切记不可分神玩手机。 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/燕麦鸡蛋饼.md b/data/C8/cook/dishes/breakfast/燕麦鸡蛋饼.md new file mode 100644 index 0000000..f37fe47 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/燕麦鸡蛋饼.md @@ -0,0 +1,46 @@ +# 燕麦鸡蛋饼的做法 + +燕麦鸡蛋饼是极具营养、便于制作、适宜快速制作的早餐。尤其适宜热爱健身的上班族。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 鸡蛋 +- 燕麦 +- 牛奶 50-100g,能够将燕麦搅拌粘稠即可 +- 可根据口味选择增加 50g 蔬菜,如菠菜。 + +## 计算 + +- 鸡蛋两个,亦可选择两个蛋清,一个蛋黄。 +- 纯干燕麦片 50g (大约等同一个鸡蛋的量) +- 牛奶一盒 约 250ml +- 蔬菜碎叶一把 + +## 操作 + +- 将牛奶与干燕麦混合搅拌均匀至黏稠状。 +- 将鸡蛋搅拌均匀至颜色单一程度。 +- 将鸡蛋液倒入燕麦牛奶中继续搅拌至黏稠、均匀。 +- 平底锅中加入一层黄油并覆盖均匀。 +- 下入搅拌好的食材,并摊开至饼状。 +- 小火加热两到三分钟。如想要加入蔬菜,可以在加热过程中加入碎菜叶。 +- 翻面继续加热两分钟。 +- 出锅,搭配剩下的牛奶作为早餐。 + +## 附加内容 + +- 如果口味偏咸口,可以在搅拌鸡蛋液时加入盐,胡椒等调料。 +- 煎饼时使用小火,避免燕麦部分煎糊。 + +### 营养成分 + +一份上述早餐的预估营养价值(三大营养素)如下,供热爱健身人群参考*。 + +- 碳水化合物:39g +- 蛋白质:30g +- 脂肪:19g +- 总热量:450kcal + +*: 牛奶按照常见的 250ml 计算 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/牛奶燕麦.md b/data/C8/cook/dishes/breakfast/牛奶燕麦.md new file mode 100644 index 0000000..2642932 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/牛奶燕麦.md @@ -0,0 +1,50 @@ +# 牛奶燕麦的做法 + +高蛋白,粗谷物纤维,饱腹感的懒人快速营养早餐,3 分钟 搞定 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 牛奶(巴氏奶口感更好) +- 燕麦 +- 鸡蛋 + +## 计算 + +- 🥛 牛奶 280ml/per +- 🍳 鸡蛋 1 个/per +- 🍚 燕麦 40g/per + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 燕麦烹饪常规方法 + +- 将牛奶倒入早餐杯(冷的即可) +- 准备好 200ml 水,如果是直饮水直接加入燕麦,否则请烧开后加入燕麦 +- 水沸后 2 分钟,燕麦煮好 +- 煮好的燕麦捞出倒入牛奶中(尽量不要将煮燕麦的水也倒入牛奶,影响口感) + +### 燕麦烹饪快速方法 + +- 将燕麦替换为快煮燕麦 +- 将牛奶倒入装有快煮燕麦的容器中并搅拌 +- 将混合物放入微波炉中 +- 中等火力微波 4 分钟 + +### 煎蛋烹饪方法 + +- 热锅,锅内放一层底油,油热后煎鸡蛋,每面煎 20s,考虑调底味(3g 椒盐,可选) +- 关火,装盘 + +烹饪基本 3 分钟 搞定,做完菜品都是常温,极易入口,一般每次 2 分钟吃完。 + +> 🥑 水果蔬菜,苏打饼干搭配食用更佳 + +## 附加内容 + +- 由于不同微波炉火力不同,故微波炉火力无法精确表明 +- 不建议混合物超过容器容量 50%,否则加热过程中内容物极有可能溢出 +- 不建议使用玻璃杯进行烹饪,理由同上 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/空气炸锅面包片.md b/data/C8/cook/dishes/breakfast/空气炸锅面包片.md new file mode 100644 index 0000000..a6e0e10 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/空气炸锅面包片.md @@ -0,0 +1,33 @@ +# 空气炸锅面包片的做法 + +健康饱肚子,适宜正在减脂期的程序员食用 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 面包片 +- 空气炸锅 + +## 计算 + +每份: + +- 面包片(两片) + +## 操作 + +- 取出两片面包片(建议使用粗粮面包片) +- 将面包片**垂直**放入空气炸锅 +- 200°C 烘烤 5 分钟 +- 取出即可使用 + +## 附加内容 + +营养成分表(数据基于全麦面包片) + +- 热量 254 千卡 +- 蛋白质 12.3 克 +- 脂肪 3.5 克 +- 碳水化合物 43.1 克 +- 膳食纤维 6.0 克 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/美式炒蛋.md b/data/C8/cook/dishes/breakfast/美式炒蛋.md new file mode 100644 index 0000000..197f197 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/美式炒蛋.md @@ -0,0 +1,34 @@ +# 美式炒蛋的做法 + +美式炒蛋具有松软鲜嫩的口感,与平时的炒蛋不同,美式炒蛋中加入了少量牛奶,使得蛋花更加的细密均匀,并且营养丰富~ + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 鸡蛋 +- 全脂牛奶/奶油 +- 黄油 +- 盐 + +## 计算 + +每份: + +- 鸡蛋 3 个 +- 全脂牛奶/奶油 10g +- 黄油 5 克 +- 盐 1 克 + +## 操作 + +- 鸡蛋打入大碗中,加盐搅打至起泡,静置 15 分钟 +- 黄油切小块入锅,倒入蛋液,开小火不断搅拌 +- 黄油一融化,就快速翻动蛋液,将其打碎成细密状,在蛋液大体凝固前关火 +- 加入牛奶搅拌 15 秒,至炒蛋湿润绵密,装盘 + +## 附加内容 + +- 想吃的更丰富可以在最后一步那里加上炒好的番茄丁,洋葱丁,培根丁,切好的芝士小丁,等等。(总之不会再出水的东东) +- 使用平底锅(不粘锅)。 +- 考虑到很多人是一人食就炒一两个鸡蛋,口径比较小的锅或许更方便在锅中均匀搅拌。 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/苏格兰蛋/egg1.png b/data/C8/cook/dishes/breakfast/苏格兰蛋/egg1.png new file mode 100644 index 0000000..6f67843 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/苏格兰蛋/egg1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a27348092913ddefff869702dfb52baf8884ff03d0b03ff45630b2b69fb174d1 +size 243472 diff --git a/data/C8/cook/dishes/breakfast/苏格兰蛋/egg2.png b/data/C8/cook/dishes/breakfast/苏格兰蛋/egg2.png new file mode 100644 index 0000000..b04db5d --- /dev/null +++ b/data/C8/cook/dishes/breakfast/苏格兰蛋/egg2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:471a5f232b22f958bca6e863c66f4ba400abf1fc9e3adb7f9b197df11c406a74 +size 755549 diff --git a/data/C8/cook/dishes/breakfast/苏格兰蛋/egg3.png b/data/C8/cook/dishes/breakfast/苏格兰蛋/egg3.png new file mode 100644 index 0000000..6ec34d6 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/苏格兰蛋/egg3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:335516ab7b455cbe5571cde6e164f7a2fce4673195b19515ecc2c73a2e09ea47 +size 859558 diff --git a/data/C8/cook/dishes/breakfast/苏格兰蛋/苏格兰蛋.md b/data/C8/cook/dishes/breakfast/苏格兰蛋/苏格兰蛋.md new file mode 100644 index 0000000..0e66d75 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/苏格兰蛋/苏格兰蛋.md @@ -0,0 +1,53 @@ + + + + +# 苏格兰蛋的做法 + + + + + +![简易版苏格兰蛋](./egg1.png) + +苏格兰蛋是一种用新鲜肉糜裹住鸡蛋,放入油中炸至金黄制成,这个版本比较费事,所以在此就给大家带来简易版,苏格兰蛋复杂版大家就自行查找。 + +简易版苏格兰蛋是利用手抓饼皮包裹住芝士培根糖心蛋放入油中炸至金黄制成,大约耗时 20-30 分钟。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡蛋 +- 手抓饼皮 +- 芝士 +- 培根 +- 空气炸锅或者油锅 + +## 计算 + +> 一份量 + +- 鸡蛋 50g(约 1 颗) +- 手抓饼 1 份-2 份(看鸡蛋大小) +- 芝士片 1-2 片 +- 培根片 1-2 片 + +## 操作 + +- 用冷水下锅水开 3 分钟后捞出 +- 鸡蛋捞出,放入冰水中剥壳更快速也更完整 +- 用芝士片包裹鸡蛋 +- 培根片包裹鸡蛋 +- 手抓饼两端切除以矩形包裹鸡蛋 +- 油温 6 成下锅(油面波动,有青烟,筷子插入油中周围泛起气泡即是 6 成温度) 炸制金黄即可 +- 空气炸锅 160 度 15 分钟 +- 切开即可食用 + +## 附加内容 + +- 芝士片、培根片、手抓饼直接淘宝购买即可 + +![效果图](./egg2.png) + +![效果图](./egg3.png) \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/茶叶蛋.md b/data/C8/cook/dishes/breakfast/茶叶蛋.md new file mode 100644 index 0000000..a197369 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/茶叶蛋.md @@ -0,0 +1,50 @@ +# 茶叶蛋的做法 + +茶香浓郁,鲜香可口的高蛋白快速营养早餐,大约耗时 30 分钟。烹饪略微耗时,可以周末尝试,做一次大约够 2-3 个人吃。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡蛋 +- 八角 +- 香叶 +- 桂皮 +- 茴香 +- 冰糖 +- 红茶 +- 生抽 +- 老抽 +- 食盐 + +## 计算 + +- 鸡蛋 400g(约 8 颗) +- 八角 4g(约 2 颗) +- 香叶 0.5-1g(约 2 片) +- 桂皮 3g(1 小块) +- 茴香 5g +- 冰糖 15g +- 红茶 20g +- 生抽 15g +- 老抽 25g +- 食盐 3g + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +- 用冷水将鸡蛋煮熟,大火大约 8 分钟(根据自家厨具决定) +- 鸡蛋捞出,过冷水 +- 将鸡蛋互相碰撞,使每个鸡蛋产生裂缝 +- 将鸡蛋下锅,放入八角,香叶,桂皮,茴香,冰糖,红茶,生抽,老抽,食盐 +- 加水直至没过鸡蛋 +- 大火煮开之后,转中小火煮 15 分钟 + +> 中火煮15 分钟之后,捞出料渣,鸡蛋再浸泡一会口感更佳 + +## 附加内容 + +- 鸡蛋捞出过冷水是为了让鸡蛋和壳之间产生间隙 +- 食盐可根据个人口味选择不加 +- 八角,香叶,桂皮,茴香,冰糖,自己没有这么多食材可以买现成的卤料包 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/蒸水蛋.md b/data/C8/cook/dishes/breakfast/蒸水蛋.md new file mode 100644 index 0000000..a954add --- /dev/null +++ b/data/C8/cook/dishes/breakfast/蒸水蛋.md @@ -0,0 +1,30 @@ +# 蒸水蛋的做法 + +蒸水蛋(北方有些地区叫鸡蛋糕儿)都是饭店的好吃,如何自己做水滑嫩香的蒸水蛋,本教程包教包会! + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 新鲜鸡蛋 +- 热水 +- 锡纸或保鲜膜 + +## 计算 + +- 鸡蛋两只 +- 盐 2g +- 热水 260ml + +## 操作 + +- 鸡蛋打入碗中,打散 +- 取其他容器,倒入 1.5 倍(半个蛋壳为 0.5 倍水)于蛋液的温水(温度 20~30),将盐倒入水中化开 +- 将盐水倒入鸡蛋液中,顺时针或逆时针单方向搅拌均匀,气泡之类的可以用舀出丢弃,过筛则口感更加。 +- 使用锡纸包裹盛蛋液的碗(或用盘子盖住),置入提前带盖并加入大约 3cm 深度水的锅中 +- 中火烧至水开,转最小的火继续蒸 4 分钟 + +## 附加内容 + +- 一般出锅稍晾即可食用,保留鸡蛋原香的终极口感 +- 也可加入蒸鱼豉油,葱花香油作为佐料。 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/蒸花卷.md b/data/C8/cook/dishes/breakfast/蒸花卷.md new file mode 100644 index 0000000..37f1cea --- /dev/null +++ b/data/C8/cook/dishes/breakfast/蒸花卷.md @@ -0,0 +1,33 @@ +# 蒸花卷的做法 + +蒸花卷是一道简单易做的菜。能补充碳水化合物,膳食纤维。一般初学者只需要半小时即可完成。作为快手早餐,学会做之后,再也不会早上饿肚子了。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 冷冻花卷 +- 圆碟子 +- 蒸架 +- 水 400ml + +## 计算 + +- 冷冻花卷 5 个(女生分量 3 个即可)(可以在超市、各种买菜平台购买) +- 圆碟子,直径 28cm +- 蒸架,直径 20cm +- 水 400ml + +## 操作 + +- 从花卷的包装袋中取出 5 个花卷 +- 把花卷平铺在碟子上,尽量不用重叠 +- 往锅里倒入 400ml 水,把蒸架放里面,把装花卷的碟子放在蒸架上,盖上锅盖。 +- 开大火加热,直至水沸腾。 +- 转中火加热 15 分钟 +- 开盖用手感受花卷的表面温度,如果不够热,就继续盖上盖子加热,否则就可以关火出锅。 +- 碟子取出放凉至 50 度即可食用 + +## 附加内容 + +- 操作时,需要注意观察锅里的水不能少于 50ml。 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/蛋煎糍粑.md b/data/C8/cook/dishes/breakfast/蛋煎糍粑.md new file mode 100644 index 0000000..73ad72a --- /dev/null +++ b/data/C8/cook/dishes/breakfast/蛋煎糍粑.md @@ -0,0 +1,40 @@ +# 蛋煎糍粑的做法 + +蛋煎糍粑做法很简单,不需要太多的厨艺基础~ + +蛋煎糍粑热量高,美味+顶饿+便宜,只需十分钟就可以完成~ + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 鸡蛋 +- 糍粑 +- 白糖或红糖 + +## 计算 + +每份: + +- 糍粑 两块 +- 红糖 10g (建议 8g - 15g 之间) +- 鸡蛋 1 个 +- 食用油 10-15ml +- 食用盐 2g + +## 操作 + +- 把糍粑切成长方形小块,便于后面煎 +- 碗里打入一个鸡蛋并把鸡蛋搅碎,加入 2g 食用盐 +- 将切好的小糍粑依此放入搅碎的鸡蛋里面,涂抹完糍粑双面为止 +- 锅里倒入植物油 10ml ,把涂抹好的糍粑小块放进去小火慢慢煎软。 +- 将剩下的鸡蛋液慢慢倒在糍粑表面 +- 用筷子或者勺子为糍粑翻面,来回煎至金黄色后开吃 + +## 附加内容 + +- 放糍粑进去时候注意把糍粑间隔开来,防止粘在一起 +- 鸡蛋的量根据糍粑的量而定 +- 糖的量根据个人喜好 + +- [蛋煎糍粑教程](https://www.dachu.co/recipe/378826) \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/金枪鱼酱三明治.md b/data/C8/cook/dishes/breakfast/金枪鱼酱三明治.md new file mode 100644 index 0000000..1e31337 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/金枪鱼酱三明治.md @@ -0,0 +1,36 @@ +# 金枪鱼酱三明治的做法 + +饱腹感很强的懒人早餐,营养很丰富,高蛋白,大概 5 分钟搞定。可以配着牛奶、咖啡等饮品一起吃。 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 水浸金枪鱼罐头(不建议用油浸,会很腻) +- 方形吐司片 +- 蛋黄酱 +- 俄式酸黄瓜汁 +- 芝士片(可选) +- 火腿片(可选) +- 轻食机 + +## 计算 + +- 水浸金枪鱼 65g +- 方形吐司片 2 片 +- 蛋黄酱 50 mL +- 俄式酸黄瓜汁 10-15mL(可根据个人口味调整) + +## 操作 + +- 将金枪鱼、蛋黄酱、俄式酸黄瓜汁倒入碗中,用勺子搅拌,保证将金枪鱼块搅碎,酱整体呈糊状,并备用 +- 将 1 片吐司放在轻食机上 +- 将做好的金枪鱼酱涂抹到吐司上,建议 10-15ml +- 将另一片方形吐司片覆盖在上面,并按压轻食机,开机 +- 待轻食机自动停止加热,即可装盘使用 + +## 附加内容 + +- 金枪鱼酱可以在前一天晚上在冰箱冷藏 +- 金枪鱼酱建议冷藏时间不超过一周,切需要使用保鲜膜盖住 +- 注意在按压操作之前不要将轻食机电源接通,以免引发安全问题 \ No newline at end of file diff --git a/data/C8/cook/dishes/breakfast/鸡蛋三明治.md b/data/C8/cook/dishes/breakfast/鸡蛋三明治.md new file mode 100644 index 0000000..97992a9 --- /dev/null +++ b/data/C8/cook/dishes/breakfast/鸡蛋三明治.md @@ -0,0 +1,38 @@ +# 鸡蛋三明治的做法 + +10 分钟的简易鸡蛋三明治 🥪 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 鸡蛋 +- 吐司 +- 培根 +- 黄油 +- 蛋黄酱 +- 盐 +- 黑胡椒 + +## 计算 + +- 鸡蛋 1 个 +- 吐司 2 片 +- 培根 2 片 +- 黄油 10 g +- 蛋黄酱 20g +- 盐 1g +- 黑胡椒 2g + +## 操作 + +- 吐司切去四边,备用 +- 鸡蛋煮熟,捣碎 +- 混合鸡蛋、蛋黄酱、盐、黑胡椒 +- 锅中加入黄油,煎熟培根 +- 组装吐司,在两片吐司间加入制作好的鸡蛋酱及培根 +- 四边形吐司切成三角形装盘 + +## 附加内容 + +- 也可加入芝士、酸黄瓜等食材 \ No newline at end of file diff --git a/data/C8/cook/dishes/condiment/油泼辣子/口水鸡+油泼辣子.jpg b/data/C8/cook/dishes/condiment/油泼辣子/口水鸡+油泼辣子.jpg new file mode 100644 index 0000000..bfc97eb --- /dev/null +++ b/data/C8/cook/dishes/condiment/油泼辣子/口水鸡+油泼辣子.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc1b51a258dedd63599ac30e8ff0f861e603f0d8bdc4da9e5cc4cc07d2f63565 +size 328386 diff --git a/data/C8/cook/dishes/condiment/油泼辣子/油泼辣子.jpg b/data/C8/cook/dishes/condiment/油泼辣子/油泼辣子.jpg new file mode 100644 index 0000000..3d91fe0 --- /dev/null +++ b/data/C8/cook/dishes/condiment/油泼辣子/油泼辣子.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb408f21b672f58ddadf7f57b0998c8617538fcf95fe13a0b947f9847089ed61 +size 397052 diff --git a/data/C8/cook/dishes/condiment/油泼辣子/油泼辣子.md b/data/C8/cook/dishes/condiment/油泼辣子/油泼辣子.md new file mode 100644 index 0000000..fdf81b2 --- /dev/null +++ b/data/C8/cook/dishes/condiment/油泼辣子/油泼辣子.md @@ -0,0 +1,62 @@ +# 油泼辣子的做法 + +![image](./口水鸡+油泼辣子.jpg) +![image](./油泼辣子.jpg) + +制作耗时 10 分钟 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 蒜头 +- 干辣椒面 +- 盐 +- 熟白芝麻 +- 小米椒 +- 花生油(可用菜籽油替换) +- 家庭小陶瓷碗 +- 家庭铁勺子 +- 五香粉 (可选) +- 草寇(可选) +- 小葱 (可选) +- 八角 +- 花椒 +- 香叶 +- 白芷 +- 姜片(可选) +- 糖 +- 白醋 + +## 计算 + +- 蒜头 1 个 +- 干辣椒面 100 克 +- 盐 5 克 +- 熟白芝麻 15 克 +- 小米椒 1 个 +- 花生油 150 毫升 (可用菜籽油替换) +- 五香粉 10 克(可选) +- 草寇 1 个(可选) +- 小葱 3-5 根(可选) +- 其他配料:八角(1)、花椒(20-50 粒都可,看个人口味)、香叶(2-3 片)、白芷(2-3 片)、姜片(大拇指粗细的姜切片)(可选) +- 糖 30 克 +- 白醋 5 ml(大概就是小铁勺子的量) + +## 操作 + +- 拿出蒜头掰 2 个`小蒜头`去皮 +- 拿出砧板剁碎`小蒜头`、`小米椒` +- 拿出碗倒入`花生油` +- 油热放入`其他配料`和`小葱`,等到香料变焦,捞出扔掉 +- 拿出铁锅将碗内的油放入加热 2 分钟(菜籽油烧至冒烟) +- 此时是空碗 +- 往空碗加入`干辣椒面`、`白芝麻`、`蒜末`、`小米椒`、`盐`、`五香粉`、`草寇`作为"调料" +- 关火将油温冷却至 `210` 摄氏度 +- 将锅内热油倒入碗内并用勺子搅拌即可(可以在 `165` 摄氏度时加入同样"调料"的碗最后进行混合进行增辣) +- 倒入热油稍微搅拌后放入白醋,此时会重新沸腾。继续进行搅拌,白醋增香。 +- 油泼辣子冷却到温热放白糖和味精,白糖可以是辣味柔和,不会那么的呛口 + +## 附加内容 + +- 五香粉、草寇作为"调料"加入,可以增加香味,使油泼辣子更香 \ No newline at end of file diff --git a/data/C8/cook/dishes/condiment/油酥.md b/data/C8/cook/dishes/condiment/油酥.md new file mode 100644 index 0000000..cadd73c --- /dev/null +++ b/data/C8/cook/dishes/condiment/油酥.md @@ -0,0 +1,25 @@ +# 油酥的做法 + +油酥是由面粉与热油混合调制的,通常在烙饼时涂点油酥,可以使得饼子层层分明,外酥里软,口感更佳。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 面粉 +- 油 +- 盐 + +## 计算 + +- 油 = (要烙饼的张数 * 10ml) +- 盐 = (要烙饼的张数 / 2)g +- 面粉 = (要烙饼的张数 / 0.13)g + +## 操作 + +- 面粉盛小碗里,加入盐 +- 加入 200 度的热油 +- 用筷子将其搅拌成无固状物体的糊状。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/condiment/炸串酱料.md b/data/C8/cook/dishes/condiment/炸串酱料.md new file mode 100644 index 0000000..056ffc7 --- /dev/null +++ b/data/C8/cook/dishes/condiment/炸串酱料.md @@ -0,0 +1,42 @@ +# 炸串酱料的做法 + +炸串酱料,号称淋袜子都好吃,新手友好,预计用时 10 分钟。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 干辣椒面(粗细都准备) +- 孜然粉 +- 胡椒粉 +- 五香粉 +- 花椒粉 +- 十三香 +- 麻辣鲜 +- 白芝麻 + +## 计算 + +- 干辣椒面 60 克 +- 孜然粉 20 克 +- 胡椒粉 10 克 +- 五香粉 15 克 +- 食盐 20 克 +- 花椒粉 15 克 +- 鸡精 8 克 +- 十三香 5 克 +- 麻辣鲜 5 克 +- 白芝麻 30 克 + +## 操作 + +- 所有原料在容器内混合,搅拌均匀。 +- 锅里烧热油,油的用量以在容器内没过所有原材料为佳。 +- 分三次淋入热油,每次 1/3,同时搅拌。 +- 最后放入香油 10ml,生抽 10ml,花椒油 10ml,蚝油 10ml。 + +## 附加内容 + +- 最后一步的调味可按自己喜好添加。 +- 不得一次性倒入所有热油,必须分次倒入并搅拌。 +- 原料可按比例缩减。 \ No newline at end of file diff --git a/data/C8/cook/dishes/condiment/简易版炒糖色.md b/data/C8/cook/dishes/condiment/简易版炒糖色.md new file mode 100644 index 0000000..b6cec53 --- /dev/null +++ b/data/C8/cook/dishes/condiment/简易版炒糖色.md @@ -0,0 +1,35 @@ +# 简易版炒糖色的做法 + +这是简易的糖色的做法。对于更为进阶的技巧和糖色更为进阶的用法,请学习[糖色的炒制](../../tips/advanced/糖色的炒制.md)。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 糖(任选其一): + - 冰糖:炒出来的`糖色`色泽最为鲜艳,红亮,必须水油炒,不加水融化会很慢 + - 白砂糖:必须水油炒,不加水融化会很慢 + - 绵白糖:可以不加水 +- 炒糖色过程火不要太大!!!电磁炉温度不够,火候过了发苦,不够发甜 + +## 计算 + +- `油`:100ml +- `开水`:500ml +- `糖`(这里以冰糖为例) + +## 操作 + +- 开火,并向锅中倒入 100ml 开水 +- 再向锅中倒入 100ml 油,与第一步间隔越短越好,此时锅为大火中火都可以,着急的话可以大火 +- 放入冰糖(如果冰糖过于耦合,可以提前敲碎,做到耦合度越低越好) +- 调整火力为中火 +- 开始搅拌 + - 要一直一直一直搅拌,变成棕褐色,此时**转为小火** + - 再变稀,变红茶色,再变成酱红色后起小泡泡,准备好执行下面的`操作1`or`操作2` + - 小泡泡会逐渐消失,之后会出现大泡泡,大泡泡出现时糖色完成 + - 需要在此时快速进行下一步操作(无论哪种操作都一定要提前准备好并快速!否则火候过大糖色发苦),根据菜品派别以及个人口味作出选择 + - 操作 1:可以直接加 400ml 开水降温 + - 操作 2:也可以加入葱姜蒜花椒等调味品进行翻炒 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/condiment/糖醋汁.md b/data/C8/cook/dishes/condiment/糖醋汁.md new file mode 100644 index 0000000..8ae77cf --- /dev/null +++ b/data/C8/cook/dishes/condiment/糖醋汁.md @@ -0,0 +1,32 @@ +# 糖醋汁的做法 + +糖醋汁通常情况下由清水、白糖、白醋等制成,有些人喜欢放一些番茄酱来增添不一样的酸甜味或放一些淀粉来增加菜肴汤汁的粘性和浓度,糖醋汁可用于糖醋鱼、糖醋里脊、糖醋排骨等菜品的制作 + +可依据糖醋汁配制的经典比例 1:2:3:4:5 来调制糖醋汁 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 清水 +- 白糖 +- 白醋/米醋 +- 料酒 +- 生抽 + +## 计算 + +- 清水(50ml) +- 生抽(40ml) +- 白糖(30g) +- 白醋(20ml) +- 料酒(10ml) + +## 操作 + +- 按照比例将各调料在小碗中搅拌均匀 +- 按不同菜肴的方式处理完毕后,将配制好的糖醋汁倒入锅中 +- 根据各菜肴的不同,烹制 5-10 分钟 +- 大火收汁,可增加菜的浓度、香味和光泽 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/condiment/草莓酱/做好的草莓酱.png b/data/C8/cook/dishes/condiment/草莓酱/做好的草莓酱.png new file mode 100644 index 0000000..cc2e320 --- /dev/null +++ b/data/C8/cook/dishes/condiment/草莓酱/做好的草莓酱.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:730116bef3da5646cd3683549103d8159314dc9ec9c024882179dddf32c70606 +size 337949 diff --git a/data/C8/cook/dishes/condiment/草莓酱/洗好的草莓.jpeg b/data/C8/cook/dishes/condiment/草莓酱/洗好的草莓.jpeg new file mode 100644 index 0000000..279c21d --- /dev/null +++ b/data/C8/cook/dishes/condiment/草莓酱/洗好的草莓.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:59db4e4dfcb6f86d829128efc3d22fef0f2e224abe916b09a8603483ad49d08f +size 99676 diff --git a/data/C8/cook/dishes/condiment/草莓酱/混合好的草莓.jpeg b/data/C8/cook/dishes/condiment/草莓酱/混合好的草莓.jpeg new file mode 100644 index 0000000..381f759 --- /dev/null +++ b/data/C8/cook/dishes/condiment/草莓酱/混合好的草莓.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b513eede3b66140538ab0bcd787578a2f45c716db80c930a0ec15684c794c80f +size 68587 diff --git a/data/C8/cook/dishes/condiment/草莓酱/熬煮的草莓.jpeg b/data/C8/cook/dishes/condiment/草莓酱/熬煮的草莓.jpeg new file mode 100644 index 0000000..c99ce94 --- /dev/null +++ b/data/C8/cook/dishes/condiment/草莓酱/熬煮的草莓.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9497ff6ca7b83eac4373e5417f89a37dc6633d81ed3922d0d89f082f34043a4 +size 43124 diff --git a/data/C8/cook/dishes/condiment/草莓酱/草莓酱.md b/data/C8/cook/dishes/condiment/草莓酱/草莓酱.md new file mode 100644 index 0000000..e06082e --- /dev/null +++ b/data/C8/cook/dishes/condiment/草莓酱/草莓酱.md @@ -0,0 +1,35 @@ +# 草莓酱的做法 + +可以买那种一筐一筐卖的小草莓,主要是便宜。做成酱抹在面包上非常好吃。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 草莓 +- 白砂糖 +- 保鲜膜 + +## 计算 + +每份: + +- 草莓 1200 克 +- 白糖 400 克 (如需要低糖饮食,可以考虑降低到 200g) + +## 操作 + +- 草莓洗净去叶 +- 将草莓切碎放入合适的碗中 +- 将白糖倒入碗中与草莓搅拌均匀 +- 碗用保鲜膜覆盖静置 1 小时 +- 将静置的草莓和糖的混合物倒入不粘锅中开大火烧开 +- 烧开后转小火不断搅拌直至果酱呈粘稠状关火 +- 待草莓酱冷却后装入准备好的密封罐中 + +![洗好的草莓](./洗好的草莓.jpeg) +![混合好的草莓](./混合好的草莓.jpeg) +![熬煮的草莓](./熬煮的草莓.jpeg) +![做好的草莓](./做好的草莓酱.png) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/condiment/葱油.md b/data/C8/cook/dishes/condiment/葱油.md new file mode 100644 index 0000000..4509d7d --- /dev/null +++ b/data/C8/cook/dishes/condiment/葱油.md @@ -0,0 +1,37 @@ +# 葱油的做法 + +葱油是用热油萃取以葱为主的各类香辛料得到的产物,可以用来调制肉馅,做凉拌菜,在热炒菜中作为出锅明油使用。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 油 +- 葱(大葱小葱都可以) +- 姜 +- 洋葱 +- 料酒 +- 香菜(可选) +- 开洋(可选) + +## 计算 + +- 油 200g +- 葱 80g +- 姜 20g +- 料酒 10ml +- 洋葱 150g +- 开洋 50g + +## 操作 + +- 开洋泡入 50 度温水中,加入 10ml 料酒去腥,泡 10 分钟后取出沥干水分 +- 葱,香菜洗净,切成 5cm 长的段,擦干表面水份 +- 洋葱切成丝,在锅里用热水煮 5 分钟,取出沥干水份 +- 姜去皮,切成片 +- 锅里倒入全部油,放入上述预处理好的材料,开中小火炸 20 分钟 + +## 附加内容 + +- 渣后的开洋葱渣也可以食用,葱油可以滤掉这些料渣,也可以保留 +- 开洋可以极大提升葱油鲜香,并增加鲜甜风味 \ No newline at end of file diff --git a/data/C8/cook/dishes/condiment/蒜香酱油.md b/data/C8/cook/dishes/condiment/蒜香酱油.md new file mode 100644 index 0000000..cd16715 --- /dev/null +++ b/data/C8/cook/dishes/condiment/蒜香酱油.md @@ -0,0 +1,28 @@ +# 蒜香酱油的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 蒜头 +- 白芝麻 +- 花生油 +- 酱油 +- 蘸料碟 + +## 计算 + +- 蒜头 2 瓣 +- 白芝麻 5 克 +- 花生油 15 毫升 +- 酱油 30 毫升 +- 蘸料碟 1 个 + +## 操作 + +- 拍碎蒜头 +- 往蘸料碟中加入酱油 +- 起锅,加入花生油,等到油温滚烫后加入拍好的蒜头,炸半分钟 +- 半分钟后,关火,把热油倒入蘸料碟,用筷子搅拌即可 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/condiment/蔗糖糖浆/bottle.jpg b/data/C8/cook/dishes/condiment/蔗糖糖浆/bottle.jpg new file mode 100644 index 0000000..a9ac032 --- /dev/null +++ b/data/C8/cook/dishes/condiment/蔗糖糖浆/bottle.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5cc433c2ab1edf1bc0cd30eaa2424b0c471798d2051f4bb30e2daa6d550fc89 +size 54634 diff --git a/data/C8/cook/dishes/condiment/蔗糖糖浆/蔗糖糖浆.md b/data/C8/cook/dishes/condiment/蔗糖糖浆/蔗糖糖浆.md new file mode 100644 index 0000000..d10da17 --- /dev/null +++ b/data/C8/cook/dishes/condiment/蔗糖糖浆/蔗糖糖浆.md @@ -0,0 +1,36 @@ +# 蔗糖糖浆的做法 + +将糖事先溶解好便于在配制饮料(特别是冷饮)时给饮料增甜 + +预估烹饪难度:★ + +## 必备原料和工具 + +原料 + +- 白砂糖 +- 水 + +工具 + +- 可密封容器(建议使用高硼硅试剂瓶,便宜) + +![bottle](./bottle.jpg) + +## 计算 + +建议比例=>糖 : 水 = 1 : 1,这样方便进行糖量控制,比如想要 15 克糖,就量取 30 克的糖浆 + +- 水 100 克 +- 白砂糖 100 克 + +## 操作 + +1. 将称好的白砂糖的饮用水于容器混匀 +2. 容器封盖放冰箱冷藏 + +## 附加内容 + +水无论冷热都可,如果比较急用,可用热水溶解后再冷却糖浆。 + +配制好的糖浆不会轻易变质,在冷藏状态下保存一周通常是没问题的。 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/反沙芋头/反沙芋头.md b/data/C8/cook/dishes/dessert/反沙芋头/反沙芋头.md new file mode 100644 index 0000000..35545b2 --- /dev/null +++ b/data/C8/cook/dishes/dessert/反沙芋头/反沙芋头.md @@ -0,0 +1,35 @@ +# 反沙芋头的做法 + +![反沙芋头成品](./反沙芋头成品.jpg) + +反沙芋头是一道著名的潮汕小吃,下午茶,制作起来特别方便,~预计制作时间 20 分钟 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 荔浦芋头(电商平台购买即可,实惠新鲜) +- 白砂糖或冰糖 +- 水 +- 葱 + +## 计算 + +- 荔浦芋头 200g +- 白砂糖 30g +- 水 15g + +## 操作 + +- 芋头切长条(稍微大条一点,翻炒过程不容易烂) +- 加入可以没过芋头的油,等油温起来(插入筷子冒小泡即可) +- 放进芋头到油里,去炸到芋头浮起来,一般是微微泛黄并且可以用筷子很轻松戳洞 +- 炸芋头的油放起来别浪费,后面炒菜啥的都能用 +- 接下来关键的一步,把糖(30g)和水(15g)按照 2:1 比例,加热至不变色且冒小泡 +- 倒入葱花和芋头,关火翻炒,此时等温度下来,糖就会有反沙的效果 +- 装盘上桌! + +## 附加内容 + +- 刚做好的反沙芋头很烫,小心烫嘴哦 +- 再配上茶,啊~真惬意啊 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/反沙芋头/反沙芋头成品.jpg b/data/C8/cook/dishes/dessert/反沙芋头/反沙芋头成品.jpg new file mode 100644 index 0000000..4c6c155 --- /dev/null +++ b/data/C8/cook/dishes/dessert/反沙芋头/反沙芋头成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a386b599cd01dced634707f600cadc91526efc1f16f942fe6d078f3eba9d9972 +size 339621 diff --git a/data/C8/cook/dishes/dessert/咖啡椰奶冻/咖啡椰奶冻.md b/data/C8/cook/dishes/dessert/咖啡椰奶冻/咖啡椰奶冻.md new file mode 100644 index 0000000..6285e70 --- /dev/null +++ b/data/C8/cook/dishes/dessert/咖啡椰奶冻/咖啡椰奶冻.md @@ -0,0 +1,44 @@ +# 咖啡椰奶冻的做法 + +![咖啡椰奶冻](./咖啡椰奶冻.png) + +咖啡椰奶冻是一道简单易于制作的甜品 出品时间约 1 小时(不算冷藏) + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 125ml 淡奶油 +- 250ml 椰树牌椰汁 +- 35ml espresso 意式浓缩 +- 50ml 椰子水 +- 10g 吉利丁(gelatin) +- 过滤网(可选) +- (那个...有摆盘需求的话,可以来点蓝莓 and/or 咖啡粉) + +## 计算 + +3-4 人份: + +- 125ml 淡奶油(whipping cream, 35% M.E) +- 250ml 椰树牌椰汁 +- 35ml espresso 意式浓缩(个人不推荐用 fruity 的咖啡豆) +- 50ml 椰子水(推荐 vita coco coconut water,有条件可以敲一个椰子) +- 10g 吉利丁 +- 糖(可选) + +## 操作 + +- 将定量淡奶油,椰树牌椰汁,espresso,椰子水混合备用。 +- 将以上液体加热 1 分钟,温度达到 50-60 度即可。 +- (可选)如果格外嗜甜可以加额外的糖。 +- 倒入吉利丁,搅拌至融化,煮 1 分钟。 +- (可选)过筛 (这一步可以让椰奶冻口感更佳顺畅)。 +- 放入模具。 +- (可选)过滤掉表层的泡泡。这一步可以让椰奶冻口感更好,并且看着也会更棒。 +- 放入冰箱冷藏区,等待 3 小时。 + +## 附加内容 + +注意事项:请务必不要让液体煮沸!!!也不要冒泡泡!!! +关于厨具清洗:建议直接用洗碗机,如果没有的话可以用温水洗。(因为 gelatin 不好清洗,洗碗机会比较好) \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/咖啡椰奶冻/咖啡椰奶冻.png b/data/C8/cook/dishes/dessert/咖啡椰奶冻/咖啡椰奶冻.png new file mode 100644 index 0000000..6f74c50 --- /dev/null +++ b/data/C8/cook/dishes/dessert/咖啡椰奶冻/咖啡椰奶冻.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21e9e4fad057c5aa80df03fedff29f5dc2b88017568375883d41613f21427645 +size 497427 diff --git a/data/C8/cook/dishes/dessert/奥利奥冰淇淋/奥利奥冰淇淋.md b/data/C8/cook/dishes/dessert/奥利奥冰淇淋/奥利奥冰淇淋.md new file mode 100644 index 0000000..77f12d3 --- /dev/null +++ b/data/C8/cook/dishes/dessert/奥利奥冰淇淋/奥利奥冰淇淋.md @@ -0,0 +1,38 @@ +# 奥利奥冰淇淋的做法 + +奥利奥冰淇淋是简单但好吃的冰淇淋,纯动物奶油不腻口,预计制作时长半小时(主要消耗在搅打奶油和去除奥利奥夹心上)。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 淡奶油(推荐品牌 安佳动物淡奶油) +- 原味奥利奥 +- 电动打蛋器 +- 一个容量在 600 毫升以上且直径小(PS: 需要注意能放得下电动打蛋仪)深度深的容器(如准备了冰淇淋模具 容器需要有尖嘴方便转移) +- 小刀(或者可以去除夹心的工具) +- 冰淇淋模具(可选) + +## 计算 + +每份: + +- 奥利奥 6 块 +- 白砂糖 18 克 +- 淡奶油 250 毫升 + +## 操作 + +- 将奥利奥拧开后去除利利(夹心),备用 +- 用筷子将奥奥剁碎,需要有一半奥奥变成粉状,另一半的奥奥最大长度小于 0.5 厘米,备用(某宝可搜“奥利奥饼干碎”,节省时间精力^-^) +- 将奶油全部倒置于深容器中,并加入准备好的糖 +- 开始用电动打蛋器高速挡 搅打至 电动打蛋器提起后下方会出现**悬挂住**的奶油( 0.5 厘米 - 1 厘米),而不是**全部**像液体一样滴下(部分滴下是正常现象)。 +- 搅打完成后将奥奥放入奶油中,搅拌均匀直至底部有奥奥。 +- 可选:将混合物倒入冰淇淋模具中 +- 放置冰箱冷冻室( -18 度) 4 小时以上可取出 + +## 附加内容 + +- 剁碎奥利奥的容器注意不要使用易碎容器。 +- 去除奥利奥夹心时切忌注意割到手。 +- 参考资料:[5分钟搞定【奥利奥麦旋风】太解馋叭!](https://www.xiachufang.com/recipe/106178429/) \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08606.jpg b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08606.jpg new file mode 100644 index 0000000..6d30727 --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08606.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:22333d526a638bbea544d849db76ba1d1b28bd43f0a00d7dda6f954e124da7a4 +size 557110 diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08608.jpg b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08608.jpg new file mode 100644 index 0000000..4f30542 --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08608.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cda36e9a21b1bdba22efeed754aea51aa8f9948b7daf4f36fbc71f7b3f1d05a3 +size 585890 diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08612.jpg b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08612.jpg new file mode 100644 index 0000000..f4528b5 --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08612.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:563842e1d13112cb6c0454b21b365881190ff1787e3434938478a7a5adb8908e +size 528341 diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08618.jpg b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08618.jpg new file mode 100644 index 0000000..97ae8c5 --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08618.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1960739575bede57d093cbe6e3115225827775b9e44ed1d9251f4aa0a838265 +size 462716 diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08621.jpg b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08621.jpg new file mode 100644 index 0000000..6334ead --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08621.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93c0c882e5af8a7d4b277a6bde546a0e9b2758654683cc5b18509e3fc66f3164 +size 531964 diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08627.jpg b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08627.jpg new file mode 100644 index 0000000..2127b66 --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08627.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:faee74d2de4c0c8b54e0b740740163312ffe3aa6dbca083bd45ac73e9d993bc0 +size 546271 diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08716.jpg b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08716.jpg new file mode 100644 index 0000000..901020e --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/DSC08716.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ebcac791864242c24396608b959f92d6ce2f3e9291cebbda7a35a51fbaa8c82 +size 996109 diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/IMG_0269.jpg b/data/C8/cook/dishes/dessert/戚风蛋糕/IMG_0269.jpg new file mode 100644 index 0000000..c8cf738 --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/IMG_0269.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:649955d2391bda62b53cc001f2ac513c62a2bf6a1d56eb38670c6be9ad0b24b6 +size 163597 diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/IMG_1516.jpg b/data/C8/cook/dishes/dessert/戚风蛋糕/IMG_1516.jpg new file mode 100644 index 0000000..71177a9 --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/IMG_1516.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48becd18a37327684e00fe8448fda00be31201793a0686d19ab1c4d7c0b3089f +size 375856 diff --git a/data/C8/cook/dishes/dessert/戚风蛋糕/戚风蛋糕.md b/data/C8/cook/dishes/dessert/戚风蛋糕/戚风蛋糕.md new file mode 100644 index 0000000..988fc10 --- /dev/null +++ b/data/C8/cook/dishes/dessert/戚风蛋糕/戚风蛋糕.md @@ -0,0 +1,138 @@ +# 戚风蛋糕的做法 + +戚风蛋糕是一道烘焙入门菜品,有一定操作难度。但成功制作后,其口感细腻绵软,令人回味。加上烘烤时间,一般初学者需要 **1.5 - 2 小时**即可完成。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +### 工具 + +* 烤箱(电饭锅可替代,但大多情况下由于锅胆材质问题易失败) +* 打蛋器(电动最好,手动费力且有一定失败概率)或筷子(非常不推荐) +* 铝合金阳极模具(千万不能选不沾模具,常用尺寸为 6 寸或 8 寸) +* 刮刀(用于翻拌蛋糕糊) + +### 原料 + +- 鸡蛋 +- 白糖 +- 牛奶(或水) +- 食用油(或黄油,但需加热软化) +- 低筋面粉(推荐惠宜) +- [可选] 柠檬汁或白醋 + +## 计算 + +每份(12 个面积单位): + +- 1 个鸡蛋(正常中等大小,约 50g) +- 白糖 16g +- 食用油 8g +- 牛奶 10g +- 低筋面粉 17g + +具体来说,对于常见 6 寸及 8 寸蛋糕: + +* 6 寸:大小为 3 份(即三个鸡蛋)。面积 36 个单位。 + * 鸡蛋 3 个,白糖 50g,食用油 25g,牛奶 30g,低筋面粉 50g +* 8 寸:大小为 5 份(即五个鸡蛋)。面积 64 个单位。 + * 鸡蛋 5 个,白糖 80g,食用油 40g,牛奶 50g,低筋面粉 90g + +## 操作 + +### 前期分离操作 + +* 从冰箱中取出新鲜的鸡蛋 +* 准备两个容器并擦干,分别盛放蛋清与蛋黄 +* 对盛放蛋清的容器,可稍有水珠,但**不能有任何油**;盛放蛋黄的容器不能有水珠 +* 打蛋,手工或利用分蛋器,将蛋清与蛋黄分离到两个容器中。 +* 分离过程中蛋黄不能破碎,**蛋清中不能混有任何蛋黄**,否则会严重影响打发。(白色系带可进入蛋清,不影响) +* (注意,不使用厨房机的情况下,盛放蛋清的容器也是打蛋的容器,为避免溢出,加入全部蛋清后不要超过容器的 **1/8**) + +### 搅拌蛋黄液 + +* 准备一个新的空碗,加入全部食用油,然后放入低筋面粉搅拌 + * 油会直接阻断面筋的形成 +* 将蛋黄加入碗中,再加入牛奶以及 **1/4** 的白糖,用刮刀搅拌均匀 + * 此时加入的牛奶虽然含水,但是不应形成面筋了。 +* 准备好低筋面粉,一边慢慢撒入容器一边用刮刀“Z 字形搅拌”(之字形搅拌),即刮刀只能沿着刀刃的方向两侧或前后移动。**不可无序地逆时针或顺时针搅拌** +* 继续,加入全部面粉,仍使用上述搅拌方式,直到混合均匀、无干粉状态。(出现一些团块是正常现象,可继续搅拌使其分散) +* 静置,备用 + +### 打发蛋白 + +* 准备好剩余 **3/4** 的白糖。分为三份,每份为总量的 **1/4** +* 蛋清中加入柠檬汁或白醋(可选) +* 打蛋器中速,打发蛋白至有*粗大气泡的状态*,加入**第一份白糖** +* 打蛋器高速,打发蛋白至*气泡较细腻的状态*,加入**第二份白糖** +* 打蛋器高速,打发蛋白至*“湿性发泡”*的状态(此时提起打蛋器头,有长长的弯曲尖角),加入**第三份白糖** +* 打蛋器中低速,打发蛋白至“干性发泡”的状态(提起打蛋器头,有短小直立的尖角;倒扣容器,蛋白可粘住容器不掉下来) +* 此时蛋白打发程度已符合要求 + * 关于蛋白状态的判断可参考附件链接中的图片。) + * 打蛋器应尽量贴近容器底部,防止出现上面浮着的表层打发,底部仍然是液体的情况) + +### 混合搅拌 + +* 简单搅拌几下蛋黄液 +* 用刮刀取 **1/3** 的蛋白霜,加入到蛋黄糊中 +* 采用“翻拌”的手法,此手法是为了避免消泡 + * 翻拌手法是 + * 先用右手拿刮刀从搅拌盆中心插入面糊底部 + * 向 8 点钟方向刮去直到碰到盆壁,顺势舀起面糊提到空中,然后再移回盆中心将面糊放入盆内 + * 左手握住搅拌盆从 9 点钟方向转到 7 点钟方向,刚好旋转了 60 度,就完成了一次循环 + * 速度大约是 1 秒钟两下 + * 此方法出自《小岛老师的蛋糕教室》。用接地气的话说就是,像炒菜一样翻炒。 +* 将 **1/3** 的蛋白霜与蛋黄液的混合液倒入剩余 **2/3** 的蛋白霜中,继续翻拌均匀 +* 将蛋糕糊倒入模具,震荡几下避免大气泡 + +### 烘烤 + +* 烘烤总时间:6 寸蛋糕 **30-35** 分钟,8 寸蛋糕 **50** 分钟。根据自己烤箱特性灵活调整,一般不超过 $\pm 5$ 分钟。(最后几分钟时可在烤箱前观察) +* 以**上管 **150** 摄氏度,下管 **160** 摄氏度**预热烘烤,约 10 分钟可到达预定温度。 +* 预热完成后,将模具放入烤箱下层 +* 选择**变温烘烤**,分为两个阶段。 + * 第一阶段烤箱设定温度为:上管 **150** 摄氏度,下管 **160** 摄氏度; + * 烘烤总时长的前 **3/5** 为第一阶段烘烤 + * 第二阶段温度为:上管 **160** 摄氏度,下管 **170** 摄氏度; + * 烘烤总时长的后 **2/5** 为第二阶段烘烤。直接调整烤箱温度即可切换。 +* 烤好后,出炉 + * 此操作可能会**烫手**,注意用毛巾辅助 + +### 冷却与脱模 + +- (可选) 将模具从高处落下,震出其中的热气 +- 模具倒扣 10 分钟,使蛋糕冷却 + - 没有冷却的蛋糕立刻脱模会损伤蛋糕 + - 此操作可能会**烫手**,注意用毛巾辅助 +- 脱模,食用 + +## 附加内容 + +- 参考了以下教程,文中说明非常详细且有每一步骤的配图。同时,对于为什么做某一个操作、背后的原理也有阐释,以及出现某些问题的分析: +- [为了做好这个戚风蛋糕,用了一整箱鸡蛋,从此告别凹底和塌陷](https://zhuanlan.zhihu.com/p/86865919) +- 对戚风蛋糕而言,蛋清打发是次要问题,关键是**烤制时的温度和时间**。 +- 蛋清容器而言,可有水珠,蛋黄容器不能有。 + - 原因:油会影响蛋白的打发,蛋清 85%是水,稍有水珠并不影响打发。 + - 特别新鲜的鸡蛋蛋清会比较硬,应对硬蛋清 5 个鸡蛋配方的话加 15ml 水会帮助蛋清打发(1 个鸡蛋配方则是 3g 水) +- 蛋清打发途中加的糖,实际也是先融于蛋清中的水里,成为糖浆溶液包裹在气泡外,对打发的气泡起保护作用。 +- 温度对糖融于水的速率以及溶解度影响较大,刚从冰箱拿出的蛋清不易打发。但温度较低的鸡蛋容易分离蛋清蛋黄,建议分离后恢复室温再进行打发。 +- 一些参考图片 + + ![配方](./IMG_1516.jpg) + + ![筛子分离蛋黄](./DSC08606.jpg) + + ![手动分蛋黄](./DSC08608.jpg) + + ![蛋黄](./DSC08612.jpg) + + ![打发蛋白](./IMG_0269.jpg) + + ![倒入模具](./DSC08618.jpg) + + ![预热烤箱](./DSC08621.jpg) + + ![烤制](./DSC08627.jpg) + + ![成品](./DSC08716.jpg) \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/提拉米苏/提拉米苏.md b/data/C8/cook/dishes/dessert/提拉米苏/提拉米苏.md new file mode 100644 index 0000000..941a342 --- /dev/null +++ b/data/C8/cook/dishes/dessert/提拉米苏/提拉米苏.md @@ -0,0 +1,46 @@ +# 提拉米苏的做法 + +![自家提拉米苏成品](提拉米苏成品.jpg) + +提拉米苏,是意大利传统甜品。无需烤箱操作简便,烘焙新手也可以零失误获得一份美味的提拉米苏。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 马斯卡彭芝士 +- 手指饼干 +- 放凉浓缩咖啡 +- 无菌鸡蛋 +- 白砂糖 +- 可可粉 +- 朗姆酒(不喜欢酒的朋友可省略,可按照自己口味调节) +- 一个装成品的容器(这里用的是玻璃乐扣) +- 打蛋器(手劲儿大的朋友也可以锻炼臂力) + +## 计算 + +- 马斯卡彭芝士 450g +- 手指饼干 1 包 +- 放凉浓缩咖啡 350ml +- 无菌鸡蛋 4 个 +- 白砂糖 50g +- 可可粉 10g +- 朗姆酒 35ml + +## 操作 + +- 分离蛋黄蛋清 +- 盛有蛋白的碗中加 10g 白砂糖湿性打发 +- 盛有蛋黄的碗中将 40g 白砂糖分三次加入,搅拌至均匀 +- 蛋黄中分三次加入马斯卡彭芝士,搅拌至均匀 +- 蛋黄中最后加入朗姆酒,搅拌均匀 +- 将打发好的蛋白分三次加入蛋黄芝士液中 +- 手指饼干两面浸湿咖啡液,平铺入容器 +- 两层芝士液两层饼干交替放入容器(这一步按照大家意愿及容器高度酌情处理) +- 放入冰箱冷藏四个小时(心急的小伙伴可以提早拿出来) +- 取出后在表面筛上可可粉,即可享用啦 + +## 附加内容 + +- [下厨房蛋白打发具体教程](https://www.xiachufang.com/recipe/101779500/) \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/提拉米苏/提拉米苏成品.jpg b/data/C8/cook/dishes/dessert/提拉米苏/提拉米苏成品.jpg new file mode 100644 index 0000000..c2785e3 --- /dev/null +++ b/data/C8/cook/dishes/dessert/提拉米苏/提拉米苏成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f52ad99a57d6e9a364e36ae2193b0d8a0f3244e84254b35083232d5874e069a0 +size 469348 diff --git a/data/C8/cook/dishes/dessert/无厨师机蜂蜜面包/无厨师机蜂蜜面包.jpg b/data/C8/cook/dishes/dessert/无厨师机蜂蜜面包/无厨师机蜂蜜面包.jpg new file mode 100644 index 0000000..669ac96 --- /dev/null +++ b/data/C8/cook/dishes/dessert/无厨师机蜂蜜面包/无厨师机蜂蜜面包.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d08b1b805bceb9ece6c3adb2f6721171dfc1b1547a2b0a3b39aa876c0983ae3 +size 234668 diff --git a/data/C8/cook/dishes/dessert/无厨师机蜂蜜面包/无厨师机蜂蜜面包.md b/data/C8/cook/dishes/dessert/无厨师机蜂蜜面包/无厨师机蜂蜜面包.md new file mode 100644 index 0000000..dd051d9 --- /dev/null +++ b/data/C8/cook/dishes/dessert/无厨师机蜂蜜面包/无厨师机蜂蜜面包.md @@ -0,0 +1,56 @@ +# 无厨师机蜂蜜面包的做法 + +![自家成品](./无厨师机蜂蜜面包.jpg) + +这个菜谱不需要厨师机,只需要等待!可以晚上的时候准备好放入冰箱,第二天再烤。口感虽然不如使用厨师机的但是还行,冰箱保存要吃的时候微波炉叮一下更好。花费时间大多在发面。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +面包本体 + +- 高筋面粉:400g +- 牛奶: 200g +- 酵母:4g +- 鸡蛋:1 个 +- 白砂糖:70g +- 盐: 2g +- 黄油: 30g + +蜂蜜水(涂在顶部) + +- 蜂蜜:20g +- 水: 20g + +可选(洒在顶部) + +- 芝麻 + +## 计算 + +以下用料使用烤制时使用一个长方形烤盘(10 x 15 英寸(约 25 x 38 厘米)) + 一个正方形烤盘(9 × 9 英寸(约 23 × 23 厘米)) + 油纸。建议按照需求减少用量,每顿早餐吃大概可以吃两周(冰箱储存), 冰箱储存会变硬, 微波炉加热 10 - 20s 即可。 + +## 操作 + +- 制作面团:将面粉,牛奶(建议加热到 40°,本人使用微波炉 15 - 20s),酵母,鸡蛋,面粉,糖和盐混合起来。 +- 搅拌面团,将原料混合均匀成团。 +- 加入黄油混合。 +- 继续搅拌 + 手揉,均匀混合。 +- 开始发面,使用保鲜膜覆盖容器,普通气温(10 - 20°)放置 1 - 2 小时,稍长时间对效果影响不大。 +- 明显看到面团发酵变大(2 倍)即可开始切分面团, 此时面团应该不再十分黏手。 +- 切分面团:理想状态每一份 60g(美观),可根据喜好适当调整大小。 +- 将每一份小面团使用擀面杖擀成舌状后卷起, 再次醒面 10 分钟左右。 +- 再次使用擀面杖擀成舌状后卷起, 从中间切开(一个变成两个)。 +- 再次使用擀面杖擀成舌状后卷起, 从中间切开(两个变成四个)。(此步骤可以按照自己的时间多擀/卷几次, 把握一份的大小就行) +- 烤盘放入油纸并倒入花生油, (每份卷好的)底部蘸水 + 面粉后放入烤盘。 +- 再次醒发(盖上保鲜膜), 这一步可以放入冰箱, 第二天再烤。 +- 刷上蛋液。 +- 烤箱 180°(355°F), 18 - 20 分钟。 +- 出炉后, 刷上蜂蜜水, 撒上芝麻。 + +## 附加内容 + +- 发面时间并不固定, 每 1 小时左右看一下确认就可以, 明显发酵变大即可, 建议发酵 2 - 2.5 倍大。 +- 面团大小不会显著影响口感和烘烤效果,可根据喜好调整。 +- 参考资料:下厨房 - 脆底蜂蜜小面包 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/炸鲜奶/炸鲜奶.jpg b/data/C8/cook/dishes/dessert/炸鲜奶/炸鲜奶.jpg new file mode 100644 index 0000000..df3c7ba --- /dev/null +++ b/data/C8/cook/dishes/dessert/炸鲜奶/炸鲜奶.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37114c83b20be2f92fb1c68d90c591e8c9583d8ea895984ef001bf1d37690feb +size 167715 diff --git a/data/C8/cook/dishes/dessert/炸鲜奶/炸鲜奶.md b/data/C8/cook/dishes/dessert/炸鲜奶/炸鲜奶.md new file mode 100644 index 0000000..e64e365 --- /dev/null +++ b/data/C8/cook/dishes/dessert/炸鲜奶/炸鲜奶.md @@ -0,0 +1,51 @@ +# 炸鲜奶的做法 + +![炸鲜奶成品](./炸鲜奶.jpg) + +炸鲜奶是一种外脆里嫩的甜点,营养价值适中,制作难度中等,预计制作时长约为 20 分钟。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 牛奶 +- 玉米淀粉 +- 面包糠 +- 鸡蛋 +- 白糖 +- 面包模具(或浅盘子) + +## 计算 + +每次制作前需要确定计划做几份。一份约 12 个。 + +每份: + +- 牛奶 250g +- 玉米淀粉 30g +- 面包糠 100g +- 鸡蛋 2 个 +- 白糖 30g + +## 操作 + +- 将牛奶倒入碗中 +- 加入玉米淀粉和白糖,搅拌均匀 +- 将模具刷上食用油 +- 牛奶下锅,中火烧开 +- 烧开后转小火,边煮边搅拌 +- 牛奶*变粘稠*后出锅,倒入模具 +- 将模具放冰箱**冷却 1 小时** +- 拿出,切成大小均匀的条,随后放入碗中 +- 向碗中倒入一半的面包糠,奶糊裹上后取出,备用 +- 在一个新碗中打入鸡蛋,搅匀,备用 +- 将奶糊裹上蛋液和剩余的面包糠 +- 锅中倒入足以覆盖奶糊的油,下锅 +- 奶糊外观*呈金黄状态*后停火,摆盘 + +## 附加内容 + +- 煮牛奶时必须小火慢煮,才能均匀受热 +- 奶糊下锅时油温不能过高或过低,最好保持在 5 分热 + +- 参考资料:[王刚的教学视频](https://www.bilibili.com/video/BV1U7411E7LH/) \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/烤蛋挞/烤蛋挞.md b/data/C8/cook/dishes/dessert/烤蛋挞/烤蛋挞.md new file mode 100644 index 0000000..a651e5a --- /dev/null +++ b/data/C8/cook/dishes/dessert/烤蛋挞/烤蛋挞.md @@ -0,0 +1,52 @@ +# 烤蛋挞的做法 + +![烤蛋挞](./烤蛋挞.png) + +烤蛋挞是一道简单易于制作的甜品 且半成品可置于冰箱冷冻长时间保存 随吃随取 出品时间约 1 小时 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +该配方为整包蛋挞皮所需量 填充后可直接冷冻保存 + +- 蛋挞皮 品牌不限 +- 鸡蛋 +- 牛奶 +- 淡奶油 +- 白砂糖 +- 烤箱 大小不限 +- 克数称 +- 搅拌器 包含且不限于筷子 打蛋器等工具 +- 筛网 网孔约为 1 毫米 + +## 计算 + +每份: + +该配方为整包蛋挞皮所需量 填充后可直接冷冻保存 + +- 蛋挞皮 品牌不限 整包蛋挞皮约为 30 只 +- 鸡蛋 8 个 普通鸡蛋即可 +- 牛奶 200 毫升 普通袋装牛奶即可 +- 淡奶油 450 毫升 烘焙店或超市即有售 +- 白砂糖 80 克 普通砂糖即可 细砂糖更优 易于融化 + +## 操作 + +- 将碗置于克数称上 称量 450 克 淡奶油(淡奶油密度在此处记为 1 ) +- 加入 80 克白砂糖 (甜度中等 可按个人口味增减 建议范围 60-100 克) +- 加入 200 克牛奶 (牛奶密度在此处记为 1 ) +- 取 8 个蛋黄加入 蛋清可留作他用 +- 均匀搅拌所有材料直至白砂糖全部融化 +- 使用网筛对搅拌完成的食材进行过滤 滤除鸡蛋黏膜 鸡蛋壳 未融化的白砂糖 结块的淡奶油 +- 此时请将烤箱设置 220 摄氏度开始预热(约 10 分钟) 记得拿出烤盘 +- 将蛋挞皮以 0.5 厘米的间隔均匀放置于烤盘中 +- 将过滤完成的食材倒入蛋挞皮中 液面距离蛋挞皮上沿 0.5 厘米即可不宜过多 +- 截止此步骤 半成品蛋挞的制作已经完成 可直接放入冰箱速冻 12 小时以上保存 +- 将半成品蛋挞放入烤箱中进行烤制 温度为 200 摄氏度 时间为 25 分钟 +- 烤制结束后即可食用 + +## 附加内容 + +操作时 请务必小心烤箱高温 防止烫伤 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/烤蛋挞/烤蛋挞.png b/data/C8/cook/dishes/dessert/烤蛋挞/烤蛋挞.png new file mode 100644 index 0000000..951426b --- /dev/null +++ b/data/C8/cook/dishes/dessert/烤蛋挞/烤蛋挞.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5106e9c4a7660ffa9ee36d6ec57c1aa824e1f70ac45d60cccf63e5fe0290874 +size 300259 diff --git a/data/C8/cook/dishes/dessert/玛格丽特饼干/玛格丽特饼干.jpg b/data/C8/cook/dishes/dessert/玛格丽特饼干/玛格丽特饼干.jpg new file mode 100644 index 0000000..4687be9 --- /dev/null +++ b/data/C8/cook/dishes/dessert/玛格丽特饼干/玛格丽特饼干.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:860b4ddff46ef963776338f67911eb80fd3f86f22e8c922c452ad123325cd07b +size 798541 diff --git a/data/C8/cook/dishes/dessert/玛格丽特饼干/玛格丽特饼干.md b/data/C8/cook/dishes/dessert/玛格丽特饼干/玛格丽特饼干.md new file mode 100644 index 0000000..b94e296 --- /dev/null +++ b/data/C8/cook/dishes/dessert/玛格丽特饼干/玛格丽特饼干.md @@ -0,0 +1,48 @@ +# 玛格丽特饼干的做法 + +![玛格丽特成品](./玛格丽特饼干.jpg) + +玛格丽特饼干通常作为下午茶点心或伴随热饮享用,是一种经典而受欢迎的点心。它们的酥脆质地和丰富的黄油味道使它们成为许多人喜爱的饼干之一。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 熟蛋黄 +- 黄油 +- 白砂糖 +- 盐 +- 低筋面粉 +- 玉米淀粉 +- 烤箱 + +## 计算 + +鉴于这种小甜点的高热量,每次制作前需要确定计划做几份。一份正好够一个人食用。 + +每份: + +- 熟蛋黄 1 个 +- 黄油 50 克 +- 白砂糖 20 克 +- 盐 1 克 +- 低筋面粉 50 克 +- 玉米淀粉 50 克 + +## 操作 + +- 黄油隔热水融化、将蛋黄磨碎备用。 +- 在融化的黄油中添加糖、盐、以及碾碎的鸡蛋黄,搅拌均匀 +- 加入低筋面粉与玉米淀粉,揉成面团 +- 将面团均匀分割成大约 8 克重的小面团,然后将它们搓成球状。 +- 使用大拇指轻压在每个小面团上,以形成裂纹。 +- 预热烤箱至 150℃,将小面团放入烤箱中,烘烤 20 分钟。 +- 微微放凉即可食用 + +## 附加内容 + +- 可根据个人口味微调盐与糖的比例,如果喜欢其他风味可以把每份的 3 克玉米淀粉换成可可粉或抹茶粉。 +- 如果条件允许可以把蛋黄、低筋面粉等食材过筛,口感会更好。 +- 介于材料获取难度选择了白砂糖,如果条件允许可以换成糖粉 30 克。 +- 如果没有烤箱可使用微波炉、空气炸锅等,微波炉为高火 2-3 分钟,空气炸锅为 150℃20 分钟 +- 参考资料:[第一百种可邮寄的小饼干 酥酥糯糯入口即化~-哔哩哔哩](https://b23.tv/NZCsV0x) \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/红柚蛋糕/红柚蛋糕.md b/data/C8/cook/dishes/dessert/红柚蛋糕/红柚蛋糕.md new file mode 100644 index 0000000..7fd9591 --- /dev/null +++ b/data/C8/cook/dishes/dessert/红柚蛋糕/红柚蛋糕.md @@ -0,0 +1,49 @@ +# 红柚蛋糕的做法 + +红柚蛋糕是空气炸锅基础甜点,一份适合单人食用,食材处理需要 10 分钟,烹饪需要 25 分钟。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 空气炸锅 +- 鸡蛋 +- 红柚果肉 +- 面粉 +- 锡纸盘 +- 油 +- 糖 +- 水 + +## 计算 + +一份为一人餐,多人餐请等比例增加,本例中锡纸盘直径 18 厘米,若使用更大锡纸盘也请等比例增加材料用量。 + +一份: + +- 鸡蛋 2 个 +- 面粉 80g +- 红柚果肉 20g +- 油 15ml +- 水 80ml +- 糖 15g + +## 操作 + +- 锡纸盘里打入鸡蛋 2 个, 加入红柚果肉 20g +- 锡纸盘中倒入 15ml 油并摇晃锡纸盘时期均匀覆盖盘底 +- 锡纸盘中放入 10g 糖, 以及 40g 面粉和 40ml 水 +- 用筷子顺时针方向搅拌至淡黄色糊状 +- 锡纸盘中放入 5g 糖, 以及 40g 面粉和 40ml 水 +- 继续用筷子搅拌至淡黄色糊状 +- 锡纸盘放入空气炸锅的烤篮上,用 180 摄氏度烤 15 分钟 +- 打开空气炸锅,小心取出锡纸盘,用筷子或勺子将蛋糕翻面 +- 继续 180 摄氏度烤 8 分钟 +- 取出即可食用 + +## 附加内容 + +- 如果喜欢较甜的口感可以增加 10g 糖 +- 红柚果肉可以酌情添加,但每份最好不超过 40g 以免影响成品观感 +- 糊状指没有面粉疙瘩且整体颜色均匀 +- 刚出锅的锡纸盘比较烫,请用夹子夹取或使用湿抹布之类的隔热材料拿取 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/芋泥雪媚娘/芋泥雪媚娘.md b/data/C8/cook/dishes/dessert/芋泥雪媚娘/芋泥雪媚娘.md new file mode 100644 index 0000000..6ebc053 --- /dev/null +++ b/data/C8/cook/dishes/dessert/芋泥雪媚娘/芋泥雪媚娘.md @@ -0,0 +1,52 @@ +# 芋泥雪媚娘的做法 + +![芋泥雪媚娘成品](./芋泥雪媚娘成品.jpg) + +芋泥雪媚娘是一道甜品,很适合做给孩子吃,无需烤箱,手残党也可以做成功~预计制作时间 2 小时。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 荔浦芋头(电商平台购买即可,实惠新鲜) +- 紫薯粉 +- 牛奶 +- 糯米粉 +- 玉米淀粉 +- 黄油 +- 淡奶油 +- 白砂糖 +- 料理搅拌机(电动打蛋器也可以) +- 筛网 +- 保鲜膜 +- 白砂糖 + +## 计算 + +- 荔浦芋头 200g +- 紫薯粉 3g +- 牛奶 165g +- 糯米粉 a 50g +- 糯米粉 b 75g +- 玉米淀粉 22g +- 黄油 30g +- 淡奶油(推荐安佳) 145g +- 白砂糖 26g + +## 操作 + +- 芋头切块,大火煮熟至软(40 分钟即可),全部放入料理机 +- 向内加入 30g 牛奶,25g 淡奶油,将其打成泥状 +- 再向内加入 3g 紫薯粉,18g 白砂糖,继续搅拌打成细腻芋泥 +- 取出另一个碗,加入全部糯米粉 b,22g 玉米淀粉,135g 牛奶,50g 白砂糖,混匀并过筛一遍,保鲜膜盖上并扎小洞,中火蒸半个小时 +- 在蒸的过程中,将糯米粉 a 放入平底锅小火翻炒至微微发黄(即炒熟),作为手粉备用 +- 将中火蒸完半小时的糯米牛奶混合物(果冻状)趁热加入黄油 30g,将黄油揉至面团完全吸收,然后放冰箱冷藏一小时 +- 取出另一只碗,加入 120g 淡奶油,8g 白砂糖,打发至有纹路,装进裱花袋备用 +- 取出冷藏后的面团,搓揉 5 分钟,分成 30g 一个,均匀撒上 2g 手粉防粘,擀成圆形,先挤上 5g 裱花奶油,然后放上 30g 芋泥,最后将面饼像包包子一样包起来(可以减去多余的皮) +- 包好后再均匀撒 2g 手粉防粘 +- 重复以上两步直至原材料用光 + +## 附加内容 + +- 制作时最好佩戴不粘手套 +- 制作完即可食用,不用再加热 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/芋泥雪媚娘/芋泥雪媚娘成品.jpg b/data/C8/cook/dishes/dessert/芋泥雪媚娘/芋泥雪媚娘成品.jpg new file mode 100644 index 0000000..1d87680 --- /dev/null +++ b/data/C8/cook/dishes/dessert/芋泥雪媚娘/芋泥雪媚娘成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2858e1af2f3676e05508022cf0a4fa258826df3b21db56e9299efd8747894da5 +size 293906 diff --git a/data/C8/cook/dishes/dessert/英式司康/英式司康.md b/data/C8/cook/dishes/dessert/英式司康/英式司康.md new file mode 100644 index 0000000..8469ce0 --- /dev/null +++ b/data/C8/cook/dishes/dessert/英式司康/英式司康.md @@ -0,0 +1,47 @@ +# 英式司康的做法 + +![示例菜成品](./英式司康.png) + +英式司康是非常简单快手的下午茶甜品,可以搭配果酱、茶与咖啡。成品以蛋奶香气为主轴风味,糖量适中不会过于甜腻。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 无盐黄油(推荐品牌总统) +- 低筋面粉 +- 糖 +- 盐 +- 泡打粉 +- 鸡蛋 +- 淡奶油 +- 奶油奶酪(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 4-6 个人吃。 + +每份: + +- 无盐黄油 40g +- 低筋面粉 180g +- 糖 30g +- 盐 1g +- 泡打粉 5g +- 鸡蛋 1 个(约 50g) +- 淡奶油 45g +- 奶油奶酪 50g + +## 操作 + +- 鸡蛋打散,称量出 30g 蛋液放入干净容器中,放入全量淡奶油和奶油奶酪混合均匀。如果奶酪太硬可以水浴加热至大约 40 度再混合。 +- 将低筋面粉,盐,糖,泡打粉放入干净容器中混合均匀 +- 黄油切成小块,放入上一步的混合物中,用手将黄油捏入混合物中,呈粗玉米粉质地 +- 将第一步的蛋奶混合液倒入上一步得到的粉油混合物种,搅拌均接近。叠压成均匀面团 +- 面团放到案板上,擀成 1.5cm 厚的面片,用刀或者模具分切成合适的形状 +- 用刷子蘸取剩余的 20g 鸡蛋液,刷在司康表面 +- 烤箱预热 180 度,烤制 27 分钟 + +## 附加内容 + +- 最简单的分切方案是擀成圆形面皮,用刀切成 6 个扇形 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/英式司康/英式司康.png b/data/C8/cook/dishes/dessert/英式司康/英式司康.png new file mode 100644 index 0000000..6b069fa --- /dev/null +++ b/data/C8/cook/dishes/dessert/英式司康/英式司康.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99ebbc8b9ace433b0f2821a40203a09b2de396e4378378c0643e78a15ecd7ea0 +size 758411 diff --git a/data/C8/cook/dishes/dessert/草莓冰淇淋/草莓冰淇淋.md b/data/C8/cook/dishes/dessert/草莓冰淇淋/草莓冰淇淋.md new file mode 100644 index 0000000..56c38e9 --- /dev/null +++ b/data/C8/cook/dishes/dessert/草莓冰淇淋/草莓冰淇淋.md @@ -0,0 +1,42 @@ +# 草莓冰淇淋的做法 + +草莓冰淇淋是简单但好吃的冰淇淋,可以做很多不同的口味。这次将用当季的新鲜草莓制作美味,**不需要搅拌**的草莓冰淇淋。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 加糖炼乳 +- 草莓 +- 重奶油 +- 香草精 +- 冰淇淋模具(可选) + +## 计算 + +一份: + +- 草莓糖浆: +- 草莓 500 克 +- 白砂糖 45 克 +- 香草精 1 克 +- 食盐 1 克 +- 冰淇淋底料: +- 香草精 5 克 +- 食盐 1 克 +- 重奶油 6 克 +- 加糖炼乳 400 克 + +## 操作 + +- 先做草莓糖浆。把草莓洗干净,去掉顶部叶子。将草莓切成 **5mm** 的小块。保留一半切碎的草莓,稍后折叠成冰淇淋。 +- 将另一半切碎的草莓和糖一起放入酱汁锅中。用中火搅拌和烹饪,直到草莓释放液体并在锅中形成糖浆。 +- 让草莓在糖浆中加热,不时搅拌,直到它们分解并变形,糖浆稍微变稠。 +- 当糖浆保持分开 **3秒钟** 时,就已经准备好了。把糖浆从火上移开,加入香草和盐搅拌。将草莓糖浆放在一边冷却。 +- 当糖浆冷却时,准备冰淇淋基料。在碗中加入甜炼乳、浓奶油、香草精和盐。使用手动搅拌器搅打混合物,直到它变得轻盈蓬松,并形成柔软的尖峰。 +- 将保留的切碎的新鲜草莓折叠到冰淇淋底座中。将生过的冰淇淋底座转移到冷冻安全容器中。将冷却的草莓糖浆淋在冰淇淋上,然后轻轻地将其旋入混合物中。 +- 盖上冰淇淋并冷冻 **八小时** ,然后舀取和食用。 + +## 附加内容 + +- 制作过程中注意安全,避免割/烫到手。 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/酸奶意式奶冻/酸奶意式奶冻.md b/data/C8/cook/dishes/dessert/酸奶意式奶冻/酸奶意式奶冻.md new file mode 100644 index 0000000..34980c5 --- /dev/null +++ b/data/C8/cook/dishes/dessert/酸奶意式奶冻/酸奶意式奶冻.md @@ -0,0 +1,39 @@ +# 酸奶意式奶冻的做法 + +![示例菜成品](./酸奶意式奶冻.png) + +意式奶冻非常适合作为餐后甜品,可以搭配果酱、水果和香草。成品增加了原味酸奶,不会过于甜腻。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 淡奶油 +- 糖 +- 原味酸奶 +- 吉利丁片 +- 筛网 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 3-6 个人吃。 + +每份: + +- 淡奶油 200g +- 糖 40g +- 原味酸奶 250g +- 吉利丁片 6g + +## 操作 + +- 吉利丁片剪成小片,泡入冷水中 +- 淡奶油和糖放入锅中,加热至 60 度 +- 关火,吉利丁从水中取出,控干水份,加入热淡奶油中,搅拌均匀 +- 淡奶油降温至 40 度,加入原味酸奶,搅拌均匀 +- 将上述步骤得到的混合物过两遍筛网 +- 分装入合适的容器,放入冰箱冷藏 4 小时以上 + +## 附加内容 + +- 传统版本的意式奶冻只用淡奶油,且糖量更大,比较甜腻。此版本做了改良,吃起来负担更小。 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/酸奶意式奶冻/酸奶意式奶冻.png b/data/C8/cook/dishes/dessert/酸奶意式奶冻/酸奶意式奶冻.png new file mode 100644 index 0000000..5c27c60 --- /dev/null +++ b/data/C8/cook/dishes/dessert/酸奶意式奶冻/酸奶意式奶冻.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:679a966f7409cd39662d4905bfe33901f52e13e8431ff9eb66696a5f316468a3 +size 630728 diff --git a/data/C8/cook/dishes/dessert/雪花酥/雪花酥.md b/data/C8/cook/dishes/dessert/雪花酥/雪花酥.md new file mode 100644 index 0000000..d22a2c9 --- /dev/null +++ b/data/C8/cook/dishes/dessert/雪花酥/雪花酥.md @@ -0,0 +1,51 @@ +# 雪花酥的做法 + +![雪花酥成品](./雪花酥成品.jpg) + +雪花酥是一个快捷简便的甜点,适合装盒送礼,制作耗时 30 分钟。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +### 工具 + +- 不粘平底锅 +- 烘焙刮刀(可用锅铲代替,小心使用破坏不粘锅涂层) +- 一次性塑料手套 +- 雪花酥/牛轧糖模具 +- 擀面杖 + +### 原料 + +- 无盐黄油 +- 棉花糖 +- 全脂奶粉 +- 混合坚果(三只松鼠每日坚果) +- 饼干(非夹心型饼干,推荐小奇福或购买使用雪花酥烘焙专用小饼干) + +## 计算 + +每份: + +- 无盐黄油 20g +- 棉花糖 75g +- 全脂奶粉 40g +- 混合坚果 60g +- 饼干 75g + +## 操作 + +- 饼干超过一元硬币大小先切成小块 +- 无盐黄油加入锅中,小火加热至无盐黄油完全融化 +- 棉花糖加入锅中,使用刮刀搅拌,直至棉花糖融化并与无盐黄油均匀融合 +- 20g 奶粉加入锅中,使用刮刀搅拌,奶粉与黄油棉花糖混合物搅拌均匀后立即关火 +- 准备好的所有混合坚果与饼干趁热加入锅中,使用刮刀搅拌 +- 搅拌到温度下降到手可以接触的温度后,戴上一次塑料手套,在锅中搓揉或者双手拿起拉扯,让饼干混合坚果与棉花糖黄油奶粉混合物分散均匀。 +- 将上述步骤混合物压入模具中,边角压实,擀面杖擀平,未满的一边用手尽量压成直边 +- 室温放凉,完全冷却后脱模,按照模具纹路切块,或切成自己喜欢的大小,撒上剩余奶粉,尽量使雪花酥每面都沾上奶粉 + +## 附加内容 + +- 棉花糖加热时间越长,最后成品越硬 +- 参考资料:[【一口小锅 十分钟搞定的网红草莓“雪花酥”-哔哩哔哩】](https://b23.tv/P547ILO) \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/雪花酥/雪花酥成品.jpg b/data/C8/cook/dishes/dessert/雪花酥/雪花酥成品.jpg new file mode 100644 index 0000000..21c5164 --- /dev/null +++ b/data/C8/cook/dishes/dessert/雪花酥/雪花酥成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb9440cf532ca03584d3b54facc511c7bbaccc4be06dc8ec2c91bd2ffcd7dbf1 +size 844716 diff --git a/data/C8/cook/dishes/dessert/魔芋蛋糕/魔芋蛋糕.md b/data/C8/cook/dishes/dessert/魔芋蛋糕/魔芋蛋糕.md new file mode 100644 index 0000000..8e56266 --- /dev/null +++ b/data/C8/cook/dishes/dessert/魔芋蛋糕/魔芋蛋糕.md @@ -0,0 +1,90 @@ +# 魔芋蛋糕的做法 + +魔芋蛋糕是一款低热量的甜点。蛋糕本身无麸质,并使用无热量的甜味剂代替白砂糖,非常适合减脂人群。加上烘烤时间,一般需要 **0.5 小时**即可完成。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +### 工具 + +* 烤箱 +* 电动打蛋器 +* 金属蛋糕模具(形状任意) +* 烘焙纸 +* 餐刀(用于翻拌和抹平蛋糕糊) +* 隔热手套 +* [可选] 分蛋器 + +### 原料 + +* 鸡蛋 +* 赤藓糖醇 +* 可可粉 +* 魔芋粉 +* 塔塔粉 + +## 计算 + +每份(9.25 × 5 × 1 英寸): + +* 3 个鸡蛋 +* 赤藓糖醇 50g +* 可可粉 10g +* 魔芋粉 10g +* 塔塔粉 1g + +## 操作 + +### 预热烤箱 + +* 在准备蛋糕糊之前,可以开始预热烤箱至 350 ℉( 150 ℃)以节省时间 + +### 前期分离操作 + +* 从冰箱中取出新鲜的鸡蛋 +* 准备两个容器并擦干,分别盛放蛋清与蛋黄 +* 对盛放蛋清的容器,可稍有水珠,但**不能有任何油**;盛放蛋黄的容器不能有水珠 +* 打蛋,手工或利用分蛋器,将蛋清与蛋黄分离到两个容器中。 +* 分离过程中蛋黄不能破碎,**蛋清中不能混有任何蛋黄**,否则会严重影响打发。(白色系带可进入蛋清,不影响) +* (注意,不使用厨房机的情况下,盛放蛋清的容器也是打蛋的容器,为避免溢出,加入全部蛋清后不要超过容器的 **1/8**) + +### 打发蛋白 + +* 蛋清中加入 1g 塔塔粉 +* 打蛋器高速,打发蛋白至*粗大气泡的状态*,加入 50g 赤藓糖醇 +* 打蛋器中低速,打发蛋白至*干性发泡*的状态(提起打蛋器头,有短小直立的尖角;倒扣容器,蛋白可粘住容器不掉下来) +* 此时蛋白打发程度已符合要求 + * 打蛋器应尽量贴近容器底部,防止出现上面浮着的表层打发,底部仍然是液体的情况) + +### 混合其他原料 + +* 把分离的蛋黄加入打发的蛋清中,打蛋器中低速搅拌均匀 +* 蛋清中加入 **10g 可可粉**和 **10g 魔芋粉**,先用餐刀翻拌,这是由于如果直接用打蛋器搅拌会造成粉末飞溅 +* 翻拌手法是 + * 先用右手拿刮刀从搅拌盆中心插入面糊底部 + * 向 8 点钟方向刮去直到碰到盆壁,顺势舀起面糊提到空中,然后再移回盆中心将面糊放入盆内 + * 左手握住搅拌盆从 9 点钟方向转到 7 点钟方向,刚好旋转了 60 度,就完成了 1 次循环 + * 速度大约是 1 秒钟 2 下 + * 此方法出自《小岛老师的蛋糕教室》。用接地气的话说就是,像炒菜一样翻炒。 +* 翻拌结束后,打蛋器低速搅拌均匀 + +### 烘烤 + +* 模具铺好烘焙纸,贴合底部与内壁 +* 将蛋糕糊倒入模具,然后用餐刀抹平,再然后震荡几下避免大气泡 +* 烘烤 25 分钟 +* 烤好后,戴好隔热手套取出 + +### 冷却与脱模 + +* (可选) 将模具从高处落下,震出其中的热气 +* 模具倒扣 10 分钟,使蛋糕冷却 + * 没有冷却的蛋糕立刻脱模会损伤蛋糕 + * 此操作可能会**烫手**,注意戴好隔热手套 +* 脱模,餐刀切块食用 + +## 附加内容 + +* 本食谱主要参考视频[Keto Konjac Chocolate Cake|生酮蛋糕](https://youtu.be/gzXlOrGI54U) +* 打发蛋白等部分大幅借鉴[戚风蛋糕](../戚风蛋糕/戚风蛋糕.md)制作流程 \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/龟苓膏/龟苓膏.md b/data/C8/cook/dishes/dessert/龟苓膏/龟苓膏.md new file mode 100644 index 0000000..aba586e --- /dev/null +++ b/data/C8/cook/dishes/dessert/龟苓膏/龟苓膏.md @@ -0,0 +1,45 @@ +# 龟苓膏的做法 + +![龟苓膏成品](./龟苓膏成品.jpg) + +预估烹饪难度:★★ + +--- + +## 必备原料和工具 + +- 龟苓膏粉 25 克 +- 冷水 120 毫升 +- 开水 500 毫升 +- 白砂糖 100 克 +- 小锅 +- 搅拌工具 +- 模具或碗 + +--- + +## 计算 + +每次制作约可获得 3~4 小碗成品,适合 2~4 人食用。 + +--- + +## 操作 + +1. 在锅中倒入龟苓膏粉 25 克与冷水 120 毫升,充分搅拌至无颗粒感。 +2. 在另一个容器中加入白砂糖 100 克,倒入沸水 500 毫升,搅拌至糖完全溶解。 +3. 将糖水缓慢倒入龟苓膏粉液中,立即搅拌均匀,避免结块。 +4. 将混合液体放入锅中,加热时保持中小火,并持续搅拌以防粘锅。 +5. 加热至液体变粘稠并开始冒小泡,即可关火。 +6. 快速将液体倒入模具中,自然冷却凝固。建议冷藏 1~2 小时后食用,口感更佳。 + +--- + +## 附加内容 + +- 龟苓膏冷却过程中不可随意移动容器,否则可能影响成型。 +- 加热时应避免使用大火,防止结块或糊底。 +- 可根据个人口味添加蜂蜜、炼乳或水果食用。 +- 不同品牌龟苓膏粉浓度略有差异,建议参照包装说明调整配比。 + +--- \ No newline at end of file diff --git a/data/C8/cook/dishes/dessert/龟苓膏/龟苓膏成品.jpg b/data/C8/cook/dishes/dessert/龟苓膏/龟苓膏成品.jpg new file mode 100644 index 0000000..f3dbb9b --- /dev/null +++ b/data/C8/cook/dishes/dessert/龟苓膏/龟苓膏成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6512d541a8cda03b8294602aa3e642552926fa6d05c28030345170facff252a8 +size 11754 diff --git a/data/C8/cook/dishes/drink/B52轰炸机.md b/data/C8/cook/dishes/drink/B52轰炸机.md new file mode 100644 index 0000000..d9e8e4c --- /dev/null +++ b/data/C8/cook/dishes/drink/B52轰炸机.md @@ -0,0 +1,39 @@ +# B52轰炸机的做法 + +B-52 是鸡尾酒中喝法比较独特的一种,要配上短吸管,餐巾纸和打火机。 + +把酒点燃,用吸管一口气喝完,然后就能体验到先冷后热那种冰火两重天的感觉。那种感觉,只有试过才知道。 + +用吸管适用于女士,最刺激的喝法是一口喝下,喝的时候注意尽量避免碰到杯口引起烫伤,让火在嘴里灭掉,才能喝出最好的味道。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 甘露咖啡酒 +- 爱尔兰百利甜酒 +- 蓝天原味伏特加 +- 吧勺 +- 利口酒杯 +- 打火机 + +## 计算 + +每份: + +- 甘露咖啡酒 10ml +- 爱尔兰百利甜酒 10ml +- 蓝天原味伏特加 10ml + +## 操作 + +- 在利口酒杯的最底层倒入甘露咖啡酒到 1/3 处。(10ml) +- 顺着吧勺缓缓倒入爱尔兰百利甜酒,也是 1/3 处 (10ml)。注意要慢,保证层次分明。(太快甜酒会和咖啡混合) +- 最后在上层倒入蓝天原味伏特加 (10ml) +- 用打火机热一下杯口 +- 最后一步点火: 看到淡蓝色的小火苗了吗? + +## 附加内容 + +- 喝的时候,现在酒吧常用的方法是提供一个吸管,在火还燃烧的时候插入,然后快速全部吸入。 +- 由于吸管太细,其中氧气不足,所以火苗会灭掉,不必担心。这时候,会感到一股热辣顺着喉咙一直烈到胃,之后就是久久的咖啡奶油回甘。非常刺激又好喝。 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/Mojito莫吉托.md b/data/C8/cook/dishes/drink/Mojito莫吉托.md new file mode 100644 index 0000000..6d1984f --- /dev/null +++ b/data/C8/cook/dishes/drink/Mojito莫吉托.md @@ -0,0 +1,43 @@ +# Mojito莫吉托的做法 + +Mojito 是一种传统的古巴高球鸡尾酒。 + +这种调酒有着相对低的酒精含量(大约 10%)。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 打碎的冰块 +- 冰镇苏打水 +- 压汁器 +- 海波杯 +- 研杵 + +## 计算 + +每份: + +- 一块青柠(切成两个半块) +- 五珠薄荷叶 +- 糖浆 20ml +- 金色朗姆酒 45ml +- 蓝天原味伏特加 10ml + +## 操作 + +- 将切成半块的青柠之一切成小块,放入海波杯,随后用研杵将其捣出汁; +- 用 3-4 珠薄荷叶沿着杯口涂抹,随后将其放入杯中; +- 加入 糖浆 20ml; +- 加入 金色朗姆酒 45ml; +- 将剩下的半块青柠压出汁水放入杯中; +- 轻轻搅拌,使砂糖/糖浆处于半融合状态; +- 将打碎的冰块放入杯中,直到占杯中 3/4; +- 加入冰镇苏打水直到刚好淹没碎冰; +- 旋转搅拌半分钟; +- 使用碎冰将海波杯补满; +- 将剩下的一株薄荷叶拍醒,插入碎冰,作装饰。 + +## 附加内容 + +- 参考资料:[【哔哩哔哩】莫吉托(Mojito)世界上最著名的经典鸡尾酒之一。](https://www.bilibili.com/video/BV1jg4y187kB) \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/冬瓜茶.md b/data/C8/cook/dishes/drink/冬瓜茶.md new file mode 100644 index 0000000..c9833ac --- /dev/null +++ b/data/C8/cook/dishes/drink/冬瓜茶.md @@ -0,0 +1,36 @@ +# 冬瓜茶的做法 + +冬瓜茶是一种清爽的传统饮料,一般初学者需要 4~5 小时完成。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 冬瓜 +- 冰糖 +- 保鲜膜 +- 过滤网 +- 大锅 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 4-5 个人饮用。 + +每份: + +- 冬瓜 1000g +- 冰糖 300g + +## 操作 + +1. **准备冬瓜**:将冬瓜去皮,去籽,切成小块(每块不超过 4cm)。 +2. **加入冰糖**:冬瓜加入冰糖,搅拌均匀,盖上保鲜膜放冰箱冷藏 2 小时以上。 +3. **煮冬瓜**: 此时冬瓜出了很多水, 倒入锅中 大火煮开,然后转中小火慢慢熬制 1~2 个小时,中途多搅拌防止糊锅。 +4. **过滤冬瓜茶**:使用过滤网将煮好的冬瓜茶液过滤,取出冬瓜块,只保留茶液。 +5. **冷却**:将冬瓜茶液放凉后,倒入干净的容器中,放入冰箱冷藏即可。 +6. **享用**: 熬好的冬瓜茶液是浓缩汁,根据个人喜好添加水或其他饮品,冷热皆宜。 + +## 附加内容 + +- **口感调整**:冰糖的用量可以调整,以达到个人喜好的甜度。 +- **保存方法**:冷藏保存,建议 1 周内喝完。 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/冰粉/冰粉.md b/data/C8/cook/dishes/drink/冰粉/冰粉.md new file mode 100644 index 0000000..b325fcc --- /dev/null +++ b/data/C8/cook/dishes/drink/冰粉/冰粉.md @@ -0,0 +1,41 @@ +# 冰粉的做法 + +![石凉粉(冰粉)成品1](./石凉粉(冰粉)成品1.jpg) +![石凉粉(冰粉)成品2](./石凉粉(冰粉)成品2.jpg) + +石凉粉,在有些地区也叫作冰粉,是河南省信阳市浉河区的一种著名特色小吃,属于豫菜系。该菜品类似果冻,但因为是天然植物做出来的,所以比果冻更健康,配上薄荷汁、柠檬汁、红豆等调料,清凉解暑。该食物深当地人的喜爱,老少皆宜。 + +制作方法简单,只是有些耗时,预计制作时长 3 小时(其中包含 2.5 小时静置成型时间)。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 冰粉籽 200g +- 过滤豆浆渣的纱布一块 +- 凉白开 2000g +- 薄荷汁 10ml / 薄荷粉 10g +- 一次性透明塑料杯(可选) +- 遇水发光冰块(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份够 5 个人吃。 + +每份: + +- 冰粉籽 200g +- 凉白开 2000g +- 薄荷汁 10ml / 薄荷粉 10g + +## 操作 + +- 将凉白开倒入盆中; +- 将冰粉籽全部用纱布包起来,开口处打结 +- 将包好的冰粉籽放入凉白开中,在凉白开中用力揉搓 6 分钟 +- 然后将凉白开放置 2.5 小时,即可成型 +- 随后将石凉粉用勺子装进准备好的一次性透明塑料杯中,加入 10ml 薄荷汁或者 10g 薄荷粉(柠檬汁、山楂汁、桑椹汁也可),再放入遇水发光冰块,用勺子慢慢搅拌均匀 + +## 附加内容 + +- 操作时,需要注意观察凉白开的颜色和粘度变化,如颜色过浅或者水不黏,则说明冰粉籽量不足,或者是揉搓力度和时间没有到位。 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/冰粉/石凉粉(冰粉)成品1.jpg b/data/C8/cook/dishes/drink/冰粉/石凉粉(冰粉)成品1.jpg new file mode 100644 index 0000000..d2983b9 --- /dev/null +++ b/data/C8/cook/dishes/drink/冰粉/石凉粉(冰粉)成品1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9caf2438128303b0d8f969b390814507bc1873fb090071562323caf96a0a6c37 +size 94427 diff --git a/data/C8/cook/dishes/drink/冰粉/石凉粉(冰粉)成品2.jpg b/data/C8/cook/dishes/drink/冰粉/石凉粉(冰粉)成品2.jpg new file mode 100644 index 0000000..1df5cf5 --- /dev/null +++ b/data/C8/cook/dishes/drink/冰粉/石凉粉(冰粉)成品2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc5293d83c036652b505b509282b3a53fe2081c191a52be38be6e5df3b76591d +size 761836 diff --git a/data/C8/cook/dishes/drink/可乐桶.md b/data/C8/cook/dishes/drink/可乐桶.md new file mode 100644 index 0000000..e87d820 --- /dev/null +++ b/data/C8/cook/dishes/drink/可乐桶.md @@ -0,0 +1,47 @@ +# 可乐桶的做法 + +**饮酒有害健康,未成年人禁止饮酒** + +预估烹饪难度:★★ + +## 必备原料和工具 + +原料 + +- 波旁威士忌 +- 可口可乐 +- 冰块 +- 柠檬(可选,提升口感用) + +工具 + +- 手动压汁器 + +## 计算 + +一杯分量,约 900 毫升(含冰) + +- 威士忌 100 毫升 +- 可口可乐 500 毫升 +- 柠檬 1 个 +- 冰块 300 克 + +## 操作 + +柠檬的处理 + +1. 将柠檬对半切(**刀方向垂直于柠檬的头尾连线**),并从其中的一半中切取一片柠檬备用 +2. 再次将柠檬对半切,将得到的 4 角柠檬用压汁器压出柠檬汁置于容器中备用 +3. 将挤压过的柠檬置于容器中备用 + +正式调配 + +1. 选择一个杯子,建议使用容量在大约 1 升的大型玻璃杯或铁皮酒桶 +2. 将冰块和挤压过的柠檬入杯中(可根据个人喜好设计柠檬与冰块的摆放) +3. 倒入 15 毫升柠檬汁(如果喜酸可以加多点或全加) +4. 沿杯壁缓慢倒入可口可乐至距离杯口 3/4 处(控制可乐和威士忌的比例约在 5:1 ) +5. 倒入威士忌直至满杯 + +## 附加内容 + +可乐桶因冰块和可乐的口感掩盖了威士忌的酒味,因此不善酒力的人也容易在不知不觉中过量饮酒,请在保证个人与饮酒者的安全下调配。 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/奇异果菠菜特调/kiwi-example.jpg b/data/C8/cook/dishes/drink/奇异果菠菜特调/kiwi-example.jpg new file mode 100644 index 0000000..77c1d07 --- /dev/null +++ b/data/C8/cook/dishes/drink/奇异果菠菜特调/kiwi-example.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5de91d65ad3fd78eeec884161be09d7d1874f868800677afff7f63ab23fc4311 +size 600591 diff --git a/data/C8/cook/dishes/drink/奇异果菠菜特调/奇异果菠菜特调.md b/data/C8/cook/dishes/drink/奇异果菠菜特调/奇异果菠菜特调.md new file mode 100644 index 0000000..639dff6 --- /dev/null +++ b/data/C8/cook/dishes/drink/奇异果菠菜特调/奇异果菠菜特调.md @@ -0,0 +1,43 @@ +# 奇异果菠菜特调的做法 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 原料: + - 奇异果 + - 苹果 + - 菠菜叶( 2-5 片) + - 水 + - 白砂糖 +- 工具 + - 榨汁机 + +## 计算 + +- 饮用水 700ml +- 奇异果 2 个 +- 苹果 1/2 个 +- 菠菜叶 4 叶 +- 白砂糖 12 克 + +## 操作 + +- 将猕猴桃切成两半,每半再分四份小块 +- 将苹果切丁 +- 将菠菜叶去梗,只留叶子部分 +- 将菠菜切碎 +- 一起倒入榨汁机搅拌杯 +- 注水 +- 加入白砂糖 +- 启动搅拌机,搅拌约 4 个 15 秒(每 15 秒停下看状态) + +## 附加内容 + +- 关于白砂糖的量:全糖为 12g,可根据个人情况在 0-12g 中调整 +- 本品是仿照宜家的奇异果菠菜汁自己研制的,没有宜家的好喝,但也不错 +- 欢迎改进! + +### 成品 + +![奇异果菠菜特调](kiwi-example.jpg) \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/奶茶.md b/data/C8/cook/dishes/drink/奶茶.md new file mode 100644 index 0000000..637f93b --- /dev/null +++ b/data/C8/cook/dishes/drink/奶茶.md @@ -0,0 +1,31 @@ +# 奶茶的做法 + +奶茶是一种简单易做的饮料。一般初学者只需要 30 分钟即可完成。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 袋泡红茶(推荐立顿黄牌精选红茶) +- 全脂奶粉或淡奶 +- 杯子,例如带刻度的杯子,陶瓷杯或保温杯 + +## 计算 + +每份: + +- 袋泡红茶 2 包(约 4g) +- 奶粉 11-12g +- 砂糖 5-7g + +## 操作 + +- 取袋泡红茶 2 包放入杯中,加入 180-200mL **沸水**。 +- **等待 20 - 30 分钟**。 +- 称取 11-12g 奶粉和 5-7g 砂糖,分别加入前一步骤得到的液体中。 +- 搅拌均匀即可饮用。 + +## 附加内容 + +- 加入沸水后,尽量保持杯子内部温暖,例如使用开口较小的杯子或盖上盖子。如果气温较低时,使用量杯量取可能导致沸水在冲入红茶前冷却,则可以不使用量杯量取而直接估计其体积。 +- 等待时间结束后可提起或搅动茶包以使冲泡更加均匀。 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/杨枝甘露.md b/data/C8/cook/dishes/drink/杨枝甘露.md new file mode 100644 index 0000000..5d7b62f --- /dev/null +++ b/data/C8/cook/dishes/drink/杨枝甘露.md @@ -0,0 +1,39 @@ +# 杨枝甘露的做法 + +没用西谷米的原因是家里没有,但是有很多的奇亚籽就拿来代替。而且奇亚籽用泡不用煮,省了很多时间! + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 杯子 +- 水果刀 +- 牛奶 +- 冰块 +- 调理机/果汁机 + +## 计算 + +每份: + +- 奇亚籽 24g +- 牛奶 50ml +- 冰块 2 小块 +- 芒果 1 粒 +- 葡萄柚 1/2 粒 +- 椰奶 150ml + +点缀: + +- 切丝芒果干 (可选) +- 切丝柳橙干 (可选) + +## 操作 + +- 奇亚籽泡牛奶 10 分钟。 +- 泡籽之时,把半粒芒果、葡萄柚去皮切丁,放入杯中。 +- 半粒芒果切小块放入调理机加冰块、椰奶打成泥。 +- 倒入杯中,放上点缀材料(如有)。 +- 一边享用一边写代码!! + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/柠檬水/柠檬水.jpg b/data/C8/cook/dishes/drink/柠檬水/柠檬水.jpg new file mode 100644 index 0000000..b3c3a75 --- /dev/null +++ b/data/C8/cook/dishes/drink/柠檬水/柠檬水.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:12dd16d866a01e8a94280f0276534716ebcd5055205223e944491bef3db2b0f1 +size 317111 diff --git a/data/C8/cook/dishes/drink/柠檬水/柠檬水.md b/data/C8/cook/dishes/drink/柠檬水/柠檬水.md new file mode 100644 index 0000000..6d776de --- /dev/null +++ b/data/C8/cook/dishes/drink/柠檬水/柠檬水.md @@ -0,0 +1,35 @@ +# 柠檬水的做法 + +![柠檬水成品](./柠檬水.jpg) + +预估烹饪难度:★ + +## 必备原料和工具 + +- 原料 + - 柠檬 + - 果蜜 + - 冰(可选) +- 工具 + - 雪克杯 + +## 计算 + +一杯分量,约 500 毫升 + +- 柠檬 40~45 克 +- 果蜜 40~45 克 +- 冰几块(可选) + +## 操作 + +- 称 40~45 克柠檬,放入雪克杯中 +- 雪克杯盖盖子锤大约 10 次 +- 加入果蜜 40~45 克 +- 补水 +- 摇晃均匀 +- 最后根据喜好加冰 + +## 附加内容 + +- 参考资料:[柠檬水教程](https://v.douyin.com/TVNTcXDi46I) \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/泰国手标红茶/泰国手标红茶.jpg b/data/C8/cook/dishes/drink/泰国手标红茶/泰国手标红茶.jpg new file mode 100644 index 0000000..8cdfaa6 --- /dev/null +++ b/data/C8/cook/dishes/drink/泰国手标红茶/泰国手标红茶.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:313daa522a150313b0adb87e0cbc867c3ce1c610391f131e6cc8cc929d584f66 +size 74470 diff --git a/data/C8/cook/dishes/drink/泰国手标红茶/泰国手标红茶.md b/data/C8/cook/dishes/drink/泰国手标红茶/泰国手标红茶.md new file mode 100644 index 0000000..0650e04 --- /dev/null +++ b/data/C8/cook/dishes/drink/泰国手标红茶/泰国手标红茶.md @@ -0,0 +1,41 @@ +# 泰国手标红茶的做法 + +![泰国手标红茶成品](./泰国手标红茶.jpg) + +泰国手标红茶是泰国街头随处可见的奶茶,味道香纯,绵密。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 水 +- 茶粉 +- 炼乳 +- 白糖 +- 牛奶 +- 克称 +- 带刻度容器 +- 港式奶茶过滤袋 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人吃。 + +每份: + +- 水(600cc) +- 茶粉(20g) +- 白糖(24g) +- 牛奶(18ml) +- 炼乳(24g) + +## 操作 + +- 600cc 水大火烧开 +- 在过滤袋中装入 20g 茶粉,开水倒入过滤袋中,过滤 20 遍 +- 使用克称量取 24g 炼乳、24g 白糖和 18ml 牛奶放入 1000ml 以上的水壶中 +- 将过滤好的茶水倒入水壶中搅拌,直到白糖融化 +- 将水壶放到冰箱 4 小时以上 +- 喝前可以加 6-8 颗冰块 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/海边落日/海边落日.jpg b/data/C8/cook/dishes/drink/海边落日/海边落日.jpg new file mode 100644 index 0000000..0af0528 --- /dev/null +++ b/data/C8/cook/dishes/drink/海边落日/海边落日.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b86eb8a26fb569ffe0ba565119e8318cf1e63b26d63c0eb682d289301f19147 +size 100230 diff --git a/data/C8/cook/dishes/drink/海边落日/海边落日.md b/data/C8/cook/dishes/drink/海边落日/海边落日.md new file mode 100644 index 0000000..ddf9063 --- /dev/null +++ b/data/C8/cook/dishes/drink/海边落日/海边落日.md @@ -0,0 +1,64 @@ +# 海边落日的做法 + +**饮酒有害健康,未成年人禁止饮酒** + +预估烹饪难度:★★★ + +## 必备原料和工具 + +原料 + +- 红石榴糖浆 +- NFC 橙汁 +- 苏打水 +- 白朗姆 +- 蓝橙力娇酒 +- 柠檬汁 +- 冰块 +- 柠檬 + +工具 + +- 大号的玻璃杯 +- 搅拌棒 +- 量酒器 +- 调酒杯 +- 吸管 +- 水果刀 + +## 计算 + +一杯分量(含冰) + +- 红石榴糖浆 15ml +- 橙汁 35~50ml +- 苏打水 50ml +- 白朗姆 30ml +- 蓝橙力娇酒 15ml +- 柠檬汁 15ml +- 大冰块差不多就行 +- 柠檬 1 片 + +## 操作 + +柠檬的处理 + +1. 柠檬洗净切出一片 + +正式调配 + +1. 选择一个杯子,建议使用容量在 350~400 毫升的透明玻璃杯 +2. 放入大冰块,用搅拌棒搅拌冰杯 +3. 加入红石榴糖浆 +4. 让橙汁沿搅拌棒导入酒杯,到就被一半就行 +5. 轻轻搅拌半圈 +6. 倒入苏打水 +7. 拿出调酒杯,加入白朗姆 + 蓝橙力娇酒 + 柠檬汁 + 冰块。然后 shake,shake +8. 轻轻倒入酒杯中 +9. 插上柠檬和吸管 + +## 附加内容 + +### 成品 + +![海边落日](./海边落日.jpg) \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/百香果橙子特调/soda-version.jpg b/data/C8/cook/dishes/drink/百香果橙子特调/soda-version.jpg new file mode 100644 index 0000000..4478109 --- /dev/null +++ b/data/C8/cook/dishes/drink/百香果橙子特调/soda-version.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d65a1c4f9b0016298a5d4b661a19eebb2a74b4b49d01dd311a782496a9144cf2 +size 105993 diff --git a/data/C8/cook/dishes/drink/百香果橙子特调/tea-version.jpg b/data/C8/cook/dishes/drink/百香果橙子特调/tea-version.jpg new file mode 100644 index 0000000..e7ba2a9 --- /dev/null +++ b/data/C8/cook/dishes/drink/百香果橙子特调/tea-version.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9d04d453fa419fcf87b17fc37e77fb1405677770c46ef4c8004ef30d22833f1 +size 384028 diff --git a/data/C8/cook/dishes/drink/百香果橙子特调/百香果橙子特调.md b/data/C8/cook/dishes/drink/百香果橙子特调/百香果橙子特调.md new file mode 100644 index 0000000..9930250 --- /dev/null +++ b/data/C8/cook/dishes/drink/百香果橙子特调/百香果橙子特调.md @@ -0,0 +1,66 @@ +# 百香果橙子特调的做法 + +茉莉绿茶版本 + +![tea](./tea-version.jpg) + +苏打气泡水版本 + +![tea](./soda-version.jpg) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 原料: + - 百香果 + - 橙子 + - 茉莉绿茶茶叶/苏打气泡水二选一 + - 白砂糖 + - 冰块 + - 蜂蜜(可选) + - 薄荷叶或其他绿叶(可选,装饰使用) +- 工具 + - 手动压汁器 + +## 计算 + +- 基于茉莉绿茶版本准备,一杯分量,约 380 毫升 + - 橙子 1 个(约 200 克,拳头大小) + - 茉莉绿茶茶叶 3~6 克 + - 开水 150 毫升 + - 冰块 160 克以上 + +- 腌制百香果部分(因为量小不好配置,这里是两次的分量) + - 百香果 3 个 + - 白砂糖 30 克 + - 蜂蜜 10 克(如果没有可以用 5 克白砂糖代替) + +## 操作 + +- 百香果腌制(因为量小不好配置,这里是两次的分量) + - 将三个百香果的果肉取出来(里面的汁也不能放过),置于容器中 + - 称量 30 克白砂糖放入 + - 称量 10 克蜂蜜放入(如果没有可以用 5 克白砂糖代替) + - 搅拌均匀 + - 容器保鲜膜封口,放入冰箱中进行 12~24 小时的腌制 +- 茉莉绿茶调配(推荐比例=>茶 : 水 : 冰 = 1~2 : 50 : 30) + - 称量 3~6 克茶叶置于容器,加入 150 毫升开水,泡 6 分钟 + - 往泡好的绿茶中放入 90 克冰块冷却,可搅拌加速冷却 + - 待冰块消失后,将茶叶过滤得到茉莉绿茶茶水约 240 毫升 +- 橙子的处理(可在泡茶期间处理) + - 将橙子对半切(**刀方向垂直于橙子的头尾连线**),并从其中的一半中切取一片橙子备用 + - 再次将橙子对半切,将得到的 4 角橙子用压汁器压出橙汁置于容器中备用 +- 正式调配 + - 选择一个杯子,建议使用容量在 350~400 毫升的透明玻璃杯 + - 将 70 克冰块放置在杯底,并将所有橙汁倒入 + - 将之前准备的一片橙子贴杯内壁放置 + - 将一次分量的腌制百香果浇在冰上 + - 缓慢注入茉莉绿茶直至满杯,便于分层 + - 在液面放置好装饰用的绿叶(可选) + +搅拌均匀后享用 + +## 附加内容 + +如果缺少或不喜欢茉莉绿茶,可以使用苏打气泡水代替,免去茉莉绿茶的调配流程 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/砂糖椰子冰沙/砂糖椰子冰沙-1.jpg b/data/C8/cook/dishes/drink/砂糖椰子冰沙/砂糖椰子冰沙-1.jpg new file mode 100644 index 0000000..f83f3af --- /dev/null +++ b/data/C8/cook/dishes/drink/砂糖椰子冰沙/砂糖椰子冰沙-1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:301ba66260dde0e0a911c22c09c97686c352f41ccfd96dec8bb9c49da601bcee +size 307428 diff --git a/data/C8/cook/dishes/drink/砂糖椰子冰沙/砂糖椰子冰沙.md b/data/C8/cook/dishes/drink/砂糖椰子冰沙/砂糖椰子冰沙.md new file mode 100644 index 0000000..6797f3e --- /dev/null +++ b/data/C8/cook/dishes/drink/砂糖椰子冰沙/砂糖椰子冰沙.md @@ -0,0 +1,35 @@ +# 砂糖椰子冰沙的做法 + +![alt text](砂糖椰子冰沙-1.jpg) + +砂糖椰子冰沙是一种制作极其快速方便的饮料,若原料选择得当则口感丰富。然而制作时动静较大,适合白天在家制作以作为下午茶。 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 瓶装椰汁(瓶口较大为佳) +- 咖啡调糖(黄色粗粒) + +## 计算 + +冰沙最佳份量通常与融化速度有关,300g 在零下 18 度制成的冰沙在室温下通常可维持 30 分钟。 + +每份: + +- 瓶装椰子汁 500ml +- 咖啡调糖 10g(两包太古咖啡调糖) +- 坚果碎(可选) + +## 操作 + +- 500ml 瓶装椰汁倒掉 200ml,立刻拧紧瓶盖。 +- 将这瓶椰汁放入冰箱冷冻区并冷冻 10 小时以上。 +- 将这瓶椰汁取出,若确认瓶中椰汁已彻底冻结,则在墙角、椅背、桌角等坚硬表面上用力抽打。(请务必确认表面不会因此受到损伤) +- 当抽打到冻结椰汁变成冰沙状态,打开瓶盖倒出冰沙。 +- 在冰沙表面均匀撒上咖啡调糖或坚果碎。 +- 完成 + +## 附加内容 + +- 在以上步骤中,瓶装椰汁可以提前冰冻,但是不宜超过 7 天,否则有变质风险。 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/耙耙柑茶/citrus-tea.jpg b/data/C8/cook/dishes/drink/耙耙柑茶/citrus-tea.jpg new file mode 100644 index 0000000..9bbd974 --- /dev/null +++ b/data/C8/cook/dishes/drink/耙耙柑茶/citrus-tea.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69c20ab5d48b83e7106110c7a632c08fd4559c7cb2cf9f3125140448fa83987b +size 426359 diff --git a/data/C8/cook/dishes/drink/耙耙柑茶/耙耙柑茶.md b/data/C8/cook/dishes/drink/耙耙柑茶/耙耙柑茶.md new file mode 100644 index 0000000..3333dd7 --- /dev/null +++ b/data/C8/cook/dishes/drink/耙耙柑茶/耙耙柑茶.md @@ -0,0 +1,45 @@ +# 耙耙柑茶的做法 + +![citrus-tea](citrus-tea.jpg) + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 原料: + - 耙耙柑(替换物请看附加内容) + - 茉莉绿茶 + - 冰块 + - [蔗糖糖浆](../../condiment/蔗糖糖浆/蔗糖糖浆.md)(可选) +- 工具 + - 搅拌机 + +## 计算 + +一杯分量,约 300 毫升 + +- 耙耙柑 1~2 个(200 克以上) +- 茉莉绿茶 2~4 克 +- 冰块 60 克 +- 1 : 1 蔗糖糖浆 10 克(可选) + +## 操作 + +- 茉莉绿茶调配(推荐比例=>茶 : 水 : 冰 = 1~2 : 50 : 30) + - 称量 2~4 克茶叶置于容器,加入 100 毫升开水,泡 6 分钟 + - 往泡好的绿茶中放入 60 克冰块冷却,可搅拌加速冷却 + - 待冰块消失后,将茶叶过滤得到茉莉绿茶茶水约 160 毫升 +- 正式调配 + - 选择一个杯子,建议使用容量在大约 300 毫升的透明玻璃杯 + - 取出耙耙柑的肉瓣,并将外皮剥去,取得果肉 + - 取 130 克果肉和 130 毫升茉莉绿茶放入搅拌机中 + - 倒入 10 克蔗糖糖浆(可选,如果喜甜可放) + - 封盖启动搅拌机,搅拌 20 秒后将搅拌产物倒入杯中 + - 取一点果肉撕碎撒在液面上 + +开始享受 + +## 附加内容 + +- 耙耙柑可以用其他容易分离果肉的柑橘替代,比如丑橘 +- 果肉和茶水比例为 1 : 1,如果需要配置更大的分量,可按比例提升用量 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/菠萝咖啡特调/菠萝咖啡特调.md b/data/C8/cook/dishes/drink/菠萝咖啡特调/菠萝咖啡特调.md new file mode 100644 index 0000000..5ec2385 --- /dev/null +++ b/data/C8/cook/dishes/drink/菠萝咖啡特调/菠萝咖啡特调.md @@ -0,0 +1,48 @@ +# 菠萝咖啡特调的做法 + +![示例菜成品](./菠萝咖啡特调.png) + +菠萝咖啡特调是非常适合家庭出品的饮料,酸甜可口。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 咖啡液(推荐浓缩或者冷萃) +- 菠萝汁(鲜榨或者 nfc) +- 冰块 +- 苏打水 +- 奶油 +- 牛奶 +- 糖 +- 海盐(可选) +- 朗姆酒 (可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人吃。 + +每份: + +- 咖啡液 30ml +- 菠萝汁 60ml +- 冰块 50g +- 苏打水 30ml +- 奶油 30ml +- 牛奶 10ml +- 糖 8g +- 海盐 0.5g +- 朗姆酒 5ml + +## 操作 + +- 杯子里依次加入冰块,咖啡液,菠萝汁和苏打水 +- 奶油加糖打发至湿性发泡,加入朗姆酒和牛奶均匀只有流动性 +- 在第一部混合液上方倒入奶油 +- 奶油顶面撒上海盐 + +## 附加内容 + +- 咖啡液建议选用花果风味,浓缩可以用中烘豆,冷萃可以用普通水洗或者日晒 +- 倒入奶油时,高度尽量放低,让奶油能均匀漂浮在饮料表面形成奶盖 +- 用新鲜的咖啡液和菠萝汁能大大提升整体风味口感 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/菠萝咖啡特调/菠萝咖啡特调.png b/data/C8/cook/dishes/drink/菠萝咖啡特调/菠萝咖啡特调.png new file mode 100644 index 0000000..3104e39 --- /dev/null +++ b/data/C8/cook/dishes/drink/菠萝咖啡特调/菠萝咖啡特调.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ee44b9ed04db873e1575965fc357261be291c6f1853ed3ea93f5ab2aa584740 +size 479657 diff --git a/data/C8/cook/dishes/drink/酒酿醪糟/酒酿米糕.jpeg b/data/C8/cook/dishes/drink/酒酿醪糟/酒酿米糕.jpeg new file mode 100644 index 0000000..fa1429d --- /dev/null +++ b/data/C8/cook/dishes/drink/酒酿醪糟/酒酿米糕.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2856ed0fdeea707fe6bd0ed1ee3cc74c1632a94f5b196b9a7ca1f0747f8c3c4b +size 234830 diff --git a/data/C8/cook/dishes/drink/酒酿醪糟/酒酿醪糟.jpeg b/data/C8/cook/dishes/drink/酒酿醪糟/酒酿醪糟.jpeg new file mode 100644 index 0000000..b424d23 --- /dev/null +++ b/data/C8/cook/dishes/drink/酒酿醪糟/酒酿醪糟.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27367109197b4bc1772f449af6d04c2fa455f66be54dd8a057464fb5c624771d +size 249128 diff --git a/data/C8/cook/dishes/drink/酒酿醪糟/酒酿醪糟.md b/data/C8/cook/dishes/drink/酒酿醪糟/酒酿醪糟.md new file mode 100644 index 0000000..083b513 --- /dev/null +++ b/data/C8/cook/dishes/drink/酒酿醪糟/酒酿醪糟.md @@ -0,0 +1,53 @@ +# 酒酿(醪糟)的做法 + +![酒酿成品](./酒酿醪糟.jpeg) + +酒酿,也叫醪糟,是一道传统中式发酵甜品。成品清甜微醺,含少量酒精,具有健脾开胃、促进消化的功效。虽然制作需要一定发酵技巧,但过程简单有趣,是发酵入门好选择。预计制作时间为 2 天(不含等待时间操作仅需 1 小时左右)。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 糯米 800g(推荐使用圆糯米) +- 安琪甜酒曲一包 (8g)(虽然按比例为每 1000g 糯米用 3g,但多放酒曲能提高成功概率) +- 清水 720g + 600g(720 克用于蒸饭,后 500g 用于发酵) +- 蒸锅(电饭煲即可) +- 温度计(可选但推荐) +- 干净密封玻璃或陶瓷容器 1 个 + +## 计算 + +本菜谱为 1 份,可供 6~8 人食用。 + +## 操作 + +- 将 800g 糯米淘洗干净放入电饭煲,加入 720g 清水选择蒸饭模式 +- 蒸熟后将米饭倒出摊凉,使用干净的工具将其摊至 30°C 左右(用温度计测量为宜,体感温热但不烫手) +- 将 8g 安琪甜酒曲用 20ml 温水(约 30°C)化开,均匀撒在糯米饭中,同时翻拌均匀 +- 向糯米饭中加入 600g 清水帮助酒曲翻拌均匀。静置 2-3 分钟后发现糯米饭吸饱水分。这次加水可以让酒酿首次发酵便汤汁丰富 +- 用擀面杖在糯米饭中央挖一个小洞(便于出酒) +- 将混合好的米饭装入干净容器中,轻轻压平表面,盖上盖子或保鲜膜密封好 +- 放置于 28 ~ 32°C 环境下发酵 24 ~ 48 小时。发酵期间不可剧烈摇晃或移动 +- 发酵成功标准为:中间凹槽有透明酒液渗出,整体略带酒香,无异味、不酸败 +- 发酵结束后可立即冷藏保存(过程中可以加入桂花),每次食用用干净工具取出,可冷藏保存 7 ~ 10 天 + +- 可以继续二次发酵,加入适量清水增加酒酿产量(800g 水以内即可) +- 酒酿会一直持续发酵。如果想停止发酵,可以上锅蒸 10 分钟 + +## 进阶版本 1:提前泡米版本 + +- 将 800g 糯米淘洗干净,倒入清水中浸泡 6 ~ 8 小时(冬季建议泡 8 ~ 10 小时),泡至米粒饱满 +- 沥干糯米,放入蒸布中,隔水蒸 40 ~ 60 分钟。每 20 分钟打开锅盖翻动一次确保蒸熟均匀 +- 蒸熟后将米饭倒出摊凉,加入酒曲,后续步骤同上 + +## 进阶版本 2:混合米 + +- 当然,酒酿老手可以随意尝试不同米搭配。可以替换 20%的糯米为小米、燕麦、黄米、血糯米等 + +## 附加内容 + +- 发酵温度至关重要,低温会发酵缓慢或失败,高温会杀死酒曲 +- 发酵失败常见原因:温度过高、米饭太热时拌入酒曲、容器未清洁干净或进水进油 +- 可搭配汤圆、蛋花、枸杞等加热食用,但注意不要煮沸时间过长以免酒香散失 +- 酒酿汁可用于制作酒酿米糕、酒酿饼等,还可以用作调料为肥牛饭、照烧汁增添风味 +![酒酿米糕](./酒酿米糕.jpeg) \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/酸梅汤/imges/sour_plum_soup.jpg b/data/C8/cook/dishes/drink/酸梅汤/imges/sour_plum_soup.jpg new file mode 100644 index 0000000..fc4d9d0 --- /dev/null +++ b/data/C8/cook/dishes/drink/酸梅汤/imges/sour_plum_soup.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4ca85d7c167c5725d7d779f73dfaaaaedc4e22b91611b81889ff1933370e1be +size 416498 diff --git a/data/C8/cook/dishes/drink/酸梅汤/酸梅汤.md b/data/C8/cook/dishes/drink/酸梅汤/酸梅汤.md new file mode 100644 index 0000000..0bc549e --- /dev/null +++ b/data/C8/cook/dishes/drink/酸梅汤/酸梅汤.md @@ -0,0 +1,46 @@ +# 酸梅汤的做法 + +![酸梅汤](./imges/sour_plum_soup.jpg) + +视频演示: [链接](https://www.bilibili.com/video/BV1164y1F7hv/) + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 水 +- 乌枣 +- 乌梅 +- 山楂片(生) +- 黄冰糖 +- 甘草 +- 陈皮 +- 红豆蔻 +- 干桂花 + +## 计算 + +- 两升水 +- 乌枣 25 克 +- 乌梅 25g +- 黄冰糖 100 克 +- 山楂片 30 克 +- 甘草 2 克 +- 陈皮 4 克 +- 红豆蔻 1 克 +- 干桂花 3 克 + +上述所有用量可以等比例增加或减小。 + +## 操作 + +- 冲洗材料(干桂花和冰糖除外), 1.5 升水常温浸泡两小时以上(干桂花和冰糖除外) +- 开中大火煮沸,盖盖,转小火煮 40 分钟,为头煎 +- 将冰糖放入盆内,再将沥好用材的头汤趁热倒入,搅拌至冰糖融化。 +- 药材重新装回锅内再 600 毫升的水,开大火煮沸,盖盖,转中火,再煮 20 分钟为二煎 +- 最后将二煎和冰糖水趁热混合为成品。在成品 60-70℃加入干桂花(不要超过 80℃)加盖晾凉再放入冰箱冷藏 3 小时以上。 +- 饮用时记得将干桂花沥出。如饮茶般细啜,冰凉振齿,酸醒人、甜适度,滋味丰满而悠长 + +## 附加内容 + +放入冰箱冷藏后再饮用效果更佳。 \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/酸梅汤(半成品加工).md b/data/C8/cook/dishes/drink/酸梅汤(半成品加工).md new file mode 100644 index 0000000..a99a077 --- /dev/null +++ b/data/C8/cook/dishes/drink/酸梅汤(半成品加工).md @@ -0,0 +1,34 @@ +# 酸梅汤(半成品加工)的做法 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 酸梅晶固体饮料 +- 方糖(可选) +- 北京二锅头酒(可选) + +## 计算 + +- 饮用水 1177 克 +- 酸梅晶固体饮料 120 克 +- 方糖 9 克 +- 北京二锅头酒 48 克 + +上述所有用量可以等比例增加或减小。 + +## 操作 + +- 取饮用水 1177 克。 +- 放入酸梅晶固体饮料 60 克,使用汤匙顺时针搅拌 50 圈。 +- 再放入剩下 60 克酸梅晶固体饮料,再次使用汤匙顺时针搅拌 50 圈。 +- 放入 9 克的方糖,使用汤匙顺时针搅拌 100 圈。 +- 放入北京二锅头酒 48 克,用汤匙顺时针搅拌 30 圈。 + +## 附加内容 + +如果没有准备方糖或北京二锅头,可以省略操作中的第 4 步或第 5 步。 + +放入冰箱冷藏后再饮用效果更佳。 + +**饮酒请勿驾车。** \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/金汤力/gin-tonic.jpg b/data/C8/cook/dishes/drink/金汤力/gin-tonic.jpg new file mode 100644 index 0000000..4cfda93 --- /dev/null +++ b/data/C8/cook/dishes/drink/金汤力/gin-tonic.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b34e3f9fc02ecd45d7902bc27daedf7a28c0ed8d48233ffc9c2a3bdb03a14c47 +size 258312 diff --git a/data/C8/cook/dishes/drink/金汤力/金汤力.md b/data/C8/cook/dishes/drink/金汤力/金汤力.md new file mode 100644 index 0000000..b8b067c --- /dev/null +++ b/data/C8/cook/dishes/drink/金汤力/金汤力.md @@ -0,0 +1,53 @@ +# 金汤力的做法 + +**饮酒有害健康,未成年人禁止饮酒** + +预估烹饪难度:★★ + +## 必备原料和工具 + +原料 + +- 金酒 +- 汤力水气泡水 +- 柠檬 +- 冰块 +- 新鲜绿叶(可选,装饰用) + +工具 + +- 手动压汁器 + +## 计算 + +一杯分量,约 350 毫升(含冰) + +- 金酒 30~40 毫升 +- 汤力水气泡水 1 罐 +- 柠檬 1 个 +- 冰块 100 克 + +## 操作 + +柠檬的处理 + +1. 将柠檬对半切(**刀方向垂直于柠檬的头尾连线**),并从其中的一半中切取一片柠檬备用 +2. 再次将柠檬对半切,将得到的 4 角柠檬用压汁器压出柠檬汁置于容器中备用 + +正式调配 + +1. 选择一个杯子,建议使用容量在 350~400 毫升的透明玻璃杯 +2. 将 100 克冰块放置在杯底 +3. 倒入 30~40 毫升金酒 +4. 倒入 15 毫升柠檬汁(如果喜酸可以加多点或全加) +5. 用勺子搅拌均匀 +6. 将之前准备的一片柠檬放置好 +7. 缓慢沿杯壁注入汤力水直至满杯(不要倒在冰上,避免起泡流失) +8. 用勺子轻轻上下提拉将液体搅拌均匀(不要旋转搅拌,避免起泡流失) +9. 在液面放置好装饰用的绿叶(可选) + +## 附加内容 + +### 成品 + +![gin-tonic](./gin-tonic.jpg) \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/金菲士/gin-fizz.jpg b/data/C8/cook/dishes/drink/金菲士/gin-fizz.jpg new file mode 100644 index 0000000..b0059e7 --- /dev/null +++ b/data/C8/cook/dishes/drink/金菲士/gin-fizz.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ad967b4a482143651fb96789f246130677c7fcc129f50b324518ca2b3d27ad5 +size 250324 diff --git a/data/C8/cook/dishes/drink/金菲士/金菲士.md b/data/C8/cook/dishes/drink/金菲士/金菲士.md new file mode 100644 index 0000000..e8c1413 --- /dev/null +++ b/data/C8/cook/dishes/drink/金菲士/金菲士.md @@ -0,0 +1,62 @@ +# 金菲士的做法 + +**饮酒有害健康,未成年人禁止饮酒** + +预估烹饪难度:★★ + +## 必备原料和工具 + +原料 + +- 金酒 +- 苏打气泡水 +- 柠檬 +- [蔗糖糖浆](../../condiment/蔗糖糖浆/蔗糖糖浆.md) +- 冰块 +- 新鲜绿叶(可选,装饰用) + +工具 + +- 手动压汁器 +- 雪克瓶(可选) + +## 计算 + +一杯分量,约 350 毫升(含冰) + +- 金酒 30~40 毫升 +- 苏打气泡水 1 罐 +- 柠檬 1 个 +- 1 : 1 蔗糖糖浆 30~40 克 +- 冰块 100 克 + +## 操作 + +柠檬的处理 + +1. 将柠檬对半切(**刀方向垂直于柠檬的头尾连线**),并从其中的一半中切取一片柠檬备用 +2. 再次将柠檬对半切,将得到的 4 角柠檬用压汁器压出柠檬汁置于容器中备用 + +正式调配(无雪克瓶) + +1. 选择一个杯子,建议使用容量在 350~400 毫升的透明玻璃杯 +2. 将 100 克冰块放置在杯底 +3. 倒入 30~40 毫升金酒 +4. 倒入 20 毫升柠檬汁(如果喜酸可以加多点或全加) +5. 倒入 30~40 克蔗糖糖浆 +6. 用勺子搅拌均匀 +7. 将之前准备的一片柠檬放置好 +8. 缓慢沿杯壁注入苏打气泡水直至满杯(不要倒在冰上,避免起泡流失) +9. 用勺子轻轻上下提拉将液体搅拌均匀(不要旋转搅拌,避免起泡流失) +10. 在液面放置好装饰用的绿叶(可选) + +如果有雪克瓶,可以将以上步骤 2~6 替换为以下步骤 + +1. 将冰块、金酒、柠檬汁、蔗糖糖浆倒入雪克瓶,雪克均匀 +2. 将充分雪克的产物倒到杯子中(如果里面的冰太碎了,可以选择过滤其中的冰,重新往杯中补充冰块) + +## 附加内容 + +### 成品 + +![gin-fizz](./gin-fizz.jpg) \ No newline at end of file diff --git a/data/C8/cook/dishes/drink/长岛冰茶.md b/data/C8/cook/dishes/drink/长岛冰茶.md new file mode 100644 index 0000000..497dbf2 --- /dev/null +++ b/data/C8/cook/dishes/drink/长岛冰茶.md @@ -0,0 +1,55 @@ +# 长岛冰茶的做法 + +**饮酒有害健康,未成年人禁止饮酒** + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 金酒 +- 龙舌兰酒 +- 伏特加 +- 白朗姆酒 +- 橙味甜酒 +- 柠檬 +- 枫糖浆 +- 可乐 +- 冰块 +- 高球杯(容量 300ml) + +## 计算 + +一杯分量,约 300ml(含冰): + +- 金酒 15ml +- 龙舌兰酒 15ml +- 伏特加 15ml +- 白朗姆酒 15ml +- 橙味甜酒 15ml +- 柠檬汁 30ml +- 枫糖浆 20ml +- 可乐 75ml +- 柠檬 1 个 +- 冰块 100 克 + +## 操作 + +- 柠檬对半切,挤出 30ml 柠檬汁至杯中; +- 依次向杯中加入: + - 15ml 金酒, + - 15ml 龙舌兰酒, + - 15ml 伏特加, + - 15ml 白朗姆酒, + - 15ml 橙味甜酒; + +- 向杯中缓慢倒入 20ml 枫糖浆,边倒边搅拌; +- 向杯中加入 75ml 可乐; +- 向杯中加入冰块直至满杯; +- 轻轻搅拌 20 秒; +- 开始享用. + +## 附加内容 + +长岛冰茶,不含茶却有着冰茶的口感,是一种有着较高酒精度(约 15%),但口感柔和易于接受的鸡尾酒。 + +参考资料:[国际调酒师协会:长岛冰茶](https://iba-world.com/long-island-ice-tea/) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/乡村啤酒鸭.md b/data/C8/cook/dishes/meat_dish/乡村啤酒鸭.md new file mode 100644 index 0000000..1ed5185 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/乡村啤酒鸭.md @@ -0,0 +1,83 @@ +# 乡村啤酒鸭的做法 + +![乡村啤酒鸭](https://jphuang-image.oss-cn-beijing.aliyuncs.com/beer/duck/%E6%88%90%E5%93%812.jpg) + +将鸭肉与啤酒一同炖煮成菜,使滋补的鸭肉味道更加浓厚,鸭肉不仅入口鲜香,还带有一股啤酒清香。一般初学者只需要 1 小时即可完成。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 鸭肉 +- 啤酒 +- 32 厘米以上的炒锅一个(锅太小难炒 +- 青椒 +- 红椒 +- 大蒜 +- 生姜 +- 小米椒 +- 蒜苗 +- 大葱 +- 草果 +- 桂皮 +- 八角 +- 香叶 +- 干辣椒 + +## 计算 + +- 鸭肉(半只,1 kg,让市场老板剁成小块) +- 啤酒 1000 ml (可以买 500 ml 的罐装啤酒两瓶) +- 青椒 2 条,红椒 1 条 ( 长度 10 厘米到 15 厘米 之间都可以)(切段 或者切片都可以, 2 厘米一段) + +### 辅料 + +- 大蒜 4 颗 ,拍散备用 +- 生姜 3 厘米长,拍散备用 +- 小米辣 3 颗,切两段即可(不吃辣的可以不用 +- 蒜苗 2 根 切段备用 +- 大葱 2 根 1 根切段,1 根备用 + +### 香料 + +- 草果 两颗,拍散去仔备用 +- 桂皮 4 厘米一小片 +- 八角 3 颗 +- 香叶 3 片 +- 干辣椒 6 条 (不吃辣可以不用 + +![酱料](https://jphuang-image.oss-cn-beijing.aliyuncs.com/beer/duck/%E5%A4%87%E6%96%99.jpg) + +## 操作 + +### 鸭肉焯水以去腥去血水 + +- 鸭肉清洗一遍放进锅中 +- 加清水淹没鸭肉 +- 加 20 ml 料酒 +- 加备用的 1 根 大葱 +- 加生姜 ,拍散的 2 厘米 +- 开火烧滚 +- 捞出浮沫 +- 鸭肉捞出,清水洗干净备用 + +### 开始煮 + +- 锅清洗感觉烧热,加 60ml 的花生油 +- 油温到 60 度的时候,加一把花椒( 30 颗) +- 加鸭肉翻炒 4 分钟 + - 2 分钟后加入所有的香料 + - 3 分钟的时候加入所有的料头(生姜,大蒜,小米辣) +- 加入 1000 ml 的啤酒 +- 烧鸭肉 30 分钟 + - 10 分钟的时候加 盐 (3 克) 生抽( 10 ml ) 老抽( 5 ml) + - 20 分钟 加入所有的辅料 (青椒和红椒段) + - 29 分钟加入 蒜苗段 和 大葱段 + - 翻炒 1 分钟 +- 出锅 + +## 附加内容 + +- 操作时,需要注意观察沸腾的水位线,如发现低于 2/3 的食材应加热水或者加啤酒。 + +- [厨师长:用土灶烧“乡村啤酒鸭”,味道安逸得不摆了](https://www.bilibili.com/video/BV1R4411u7po?spm_id_from=333.999.0.0) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/农家一碗香/农家一碗香.md b/data/C8/cook/dishes/meat_dish/农家一碗香/农家一碗香.md new file mode 100644 index 0000000..4aac95c --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/农家一碗香/农家一碗香.md @@ -0,0 +1,48 @@ +# 农家一碗香的做法 + +![农家一碗香](./农家一碗香成品.jpg) + +农家一碗香,是一道地道的湖南菜,里面主要食材有青椒、鸡蛋和猪肉。味道咸香下饭,而且这道菜烹饪简单,不需要特别的处理。 + +农家一碗香是一道中等难度的菜品。预计备菜 7 分钟,烹饪 10 分钟,总计 17 分钟。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + ++ 猪肉(推荐五花肉) ++ 青椒 ++ 蒜片 ++ 豆瓣酱 ++ 酱油 ++ 小米椒 ++ 白糖 ++ 姜片 + +## 计算 + +每次制作前需要确定计划做几份。这里一份够 1~2 个人吃。 + ++ 猪肉 250g ++ 青椒 3 个 ++ 蒜片 2 片 ++ 豆瓣酱 10g ++ 小米椒 1 个 ++ 白糖 5mg ++ 酱油 15ml ++ 姜 2 片 + +## 操作 + ++ 备菜阶段:将猪肉切片,最好把肥瘦分开放。同时要把青椒和小米辣切成段,蒜片用刀背拍成末,姜切成丝。鸡蛋打到小碗中,用筷子打散。 ++ 备好菜,就可正式煮菜了。先将油倒入锅中,锅中开小火,油热后将蛋液倒入锅中,将鸡蛋炒散,炒至断生即可,放回小碗中备用。 ++ 将锅中继续加一点油,开小火,锅热后将之前切的肥猪肉倒入锅中逼出猪油。 ++ 肥肉出现金黄色的时候,加大火力到中火,将瘦肉一起放入锅中翻炒。 ++ 瘦肉全部炒至变色的时候加入备好的姜丝、蒜末和豆瓣酱翻炒均匀给猪肉上色。 ++ 放入青红椒、炒至断生的鸡蛋后加入酱油和白糖,继续将它们翻炒到青椒微微断生,保持青椒清脆口感。 ++ 出锅上菜! + +## 附加内容 + ++ 如果第一次炒鸡蛋的时候放的油太多,炒猪肉的时候可以视情况不加油。 ++ 参考资料[下厨房](https://www.xiachufang.com/recipe/106817581/) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/农家一碗香/农家一碗香成品.jpg b/data/C8/cook/dishes/meat_dish/农家一碗香/农家一碗香成品.jpg new file mode 100644 index 0000000..a2b4d00 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/农家一碗香/农家一碗香成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7c20610243b1eb253fc25bafd7f71749ea5aa3c3a809641e08f3bb0537ae847 +size 28597 diff --git a/data/C8/cook/dishes/meat_dish/冬瓜酿肉/冬瓜形状.jpg b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/冬瓜形状.jpg new file mode 100644 index 0000000..a6e7a4a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/冬瓜形状.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6eacfaba62c173359e3224d7ff13ba013b2ce3637af8bdeee446be21a40b5f16 +size 193484 diff --git a/data/C8/cook/dishes/meat_dish/冬瓜酿肉/冬瓜酿肉.md b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/冬瓜酿肉.md new file mode 100644 index 0000000..78c0d58 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/冬瓜酿肉.md @@ -0,0 +1,70 @@ +# 冬瓜酿肉的做法 + +![冬瓜酿肉成品](./冬瓜酿肉成品.jpg) + +荤素搭配,鲜嫩爽滑,做法简单。一般 30 分钟。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 冬瓜 +- 猪肉末 +- 鸡蛋 +- 葱 +- 葱姜末 +- 胡椒粉 +- 生抽 +- 淀粉 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 猪肉末 300g +- 鸡蛋 1 个(可选,不习惯的人可能会有点腥) +- 冬瓜 200g +- 葱花(一根,约 20g) +- 胡椒粉 5g +- 生抽 10ml +- 淀粉 5g +- 水淀粉 25g(淀粉 25g,水 50ml) +- 葱姜末(姜 3-4 片约 30g, 取上面一根葱花中的葱白部分即可) +- 盐 20g + +## 操作 + +- 冬瓜去皮,切成 25cm 长 3cm 厚的片 + +![冬瓜形状](./冬瓜形状.jpg) + +- 将切好的冬瓜放入碗中,放入 15g 盐,将冬瓜抹匀,放置 10 分钟 +- 放置冬瓜的同时,换个碗放入肉末,葱姜末, 5g 盐,淀粉 5g,胡椒粉,生抽,胡椒粉 +- 使用筷子在肉末中进行顺时针搅拌,搅拌到食材颜色没有明显对比(约 2 分钟) +- 将腌制好的冬瓜(会变软)使用清水洗三遍 + +![腌制好的冬瓜](./腌制好的冬瓜.jpg) + +- 拿出 1 片冬瓜片卷起来,并把肉塞进去 + +![卷肉](./卷肉.jpg) + +- 放入碟子中摆到碟子的边缘 + +![摆盘](./摆盘.jpg) + +- 打入 1 个鸡蛋到中间圆圈处 + +![打鸡蛋](./打鸡蛋.jpg) + +- 放入普通铁锅中水烧开后,蒸 15 分钟,盖上锅盖 +- 开盖,取出蒸好的冬瓜酿肉 +- 将冬瓜酿肉碟子的水倒入锅中,放入水淀粉,加入 50ml 清水倒入锅中烧开 +- 淋到冬瓜酿肉上 + +## 附加内容 + +- 操作时,拿出冬瓜酿肉时注意碟子很烫,小心操作。 +- 参考资料:[b站视频](https://www.bilibili.com/video/BV1oF411F7wD?spm_id_from=333.337.search-card.all.click&vd_source=9f568660d497311d3f945e5dce319705) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/冬瓜酿肉/冬瓜酿肉成品.jpg b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/冬瓜酿肉成品.jpg new file mode 100644 index 0000000..8f032f7 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/冬瓜酿肉成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98998c94843ec9361ca74802d8d49cfe9f167710fa99658f3e54e5fe7c9da6a9 +size 235266 diff --git a/data/C8/cook/dishes/meat_dish/冬瓜酿肉/卷肉.jpg b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/卷肉.jpg new file mode 100644 index 0000000..c1fe021 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/卷肉.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9eb79228c801bf0c41aab8efbd825ee9c6569bdc4f35f22402bf4bdc974380b2 +size 142445 diff --git a/data/C8/cook/dishes/meat_dish/冬瓜酿肉/打鸡蛋.jpg b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/打鸡蛋.jpg new file mode 100644 index 0000000..9dff9ff --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/打鸡蛋.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9a57eb6dc46e473f0316d20705b467ce7196c66839f2c8e216bf7f7ded204ad +size 191148 diff --git a/data/C8/cook/dishes/meat_dish/冬瓜酿肉/摆盘.jpg b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/摆盘.jpg new file mode 100644 index 0000000..707a779 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/摆盘.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad41e74797bde4043ee5fb5db1f16ac26864b9a47cfcb9ae0898f787155e5ef3 +size 169394 diff --git a/data/C8/cook/dishes/meat_dish/冬瓜酿肉/腌制好的冬瓜.jpg b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/腌制好的冬瓜.jpg new file mode 100644 index 0000000..ae937e7 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/冬瓜酿肉/腌制好的冬瓜.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b07539cbed9799a47b030ba8aefa6dd4a393e1e9f986e7444d9ab75b72375f74 +size 112631 diff --git a/data/C8/cook/dishes/meat_dish/冷吃兔.md b/data/C8/cook/dishes/meat_dish/冷吃兔.md new file mode 100644 index 0000000..eaf4530 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/冷吃兔.md @@ -0,0 +1,64 @@ +# 冷吃兔的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 兔肉 +- 盐 +- 味精 +- 蚝油 +- 料酒 +- 蒜 +- 姜 +- 小葱/大葱/洋葱 +- 干辣椒 +- 青花椒 +- 八角 +- 桂皮 +- 香叶 +- 山奈 +- 白蔻 +- 小茴香 +- 白芝麻 + +## 计算 + +- 盐量 = 兔肉斤数 * 2 克 +- 味精量 = 兔肉斤数 * 1 克 +- 蚝油量 = 兔肉斤数 * 5 克 +- 料酒量 = 兔肉斤数 * 10 克 +- 油量 = 兔肉斤数 * 0.9 ~ 1 升 +- 蒜量 = 兔肉斤数 * 二分之一头蒜 +- 姜量 = 蒜量 +- 小葱/大葱/洋葱总量 = 兔肉斤数 * 15 克 +- 干辣椒量 = 辣椒段的总体积等于兔肉的总体积 +- 青花椒量 = 3 斤兔肉对应吃饭用的小碗,一整碗花椒 +- 八角量 = 兔肉斤数 * 1 粒 +- 桂皮量 = 兔肉斤数 * 大拇指长短的一块 +- 香叶量 = 兔肉斤数 * 5 片 +- 山奈量 = 兔肉斤数 * 黄豆大小的一块 +- 白蔻量 = 兔肉斤数 * 2 颗 +- 小茴香量 = 兔肉斤数 * 15 克 +- 白芝麻量 = 兔肉斤数 * 25 克 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +1. 蒜、姜扒皮并剁碎备用,八角、桂皮、香叶、山奈、白蔻、小茴香洗净备用。 +2. 干辣椒剪成 2 厘米的小段,洗净备用。 +3. 小葱/大葱/洋葱洗净,洋葱切成小块。 +4. 兔肉剁成 2 厘米的小块,加入盐、料酒、味精调味,腌制 15 分钟。 +5. 锅中倒油,油温 4 成热下小葱/大葱/洋葱,中小火煸炒出香味,待到小葱/大葱/洋葱微焦,将其捞出。 +6. 开大火升高油温,油温 8 成热时下入兔肉,炸制过程转中小火,炸至兔肉微微焦黄时捞出兔肉。 +7. 升高油温,倒入干辣椒、青花椒、八角、桂皮、香叶、山奈、白蔻、小茴香;转小火将辣椒段炸脆。 +8. 重新倒入兔肉,加入蚝油、翻炒几分钟。 +9. 关火,加入蒜、姜、白芝麻,翻炒均匀。 +10. 放置一夜更加入味。 + +## 附加内容 + +在操作的第 6 步骤中要注意:油量应该淹没兔肉,若未淹没需要及时补充。 + +在操作的第 7 步骤中要注意:辣椒极容易炸糊,炸糊会变成黑色,这个过程非常快,所以一定要小火,基本等到没太多水气蒸发时,就可以下兔肉了。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝.jpg b/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝.jpg new file mode 100644 index 0000000..6fdce19 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7e8cd17b4aca9ec6fd475d5ba614c6f44713ea3e50423bd119e920debf17bff +size 222198 diff --git a/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝.md b/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝.md new file mode 100644 index 0000000..d255542 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝.md @@ -0,0 +1,57 @@ +# 凉拌鸡丝的做法 + +![凉拌鸡丝成品](./凉拌鸡丝.jpg) +隔离期间的一道快手菜,少油低卡,制作简单,预计制作时间 30 分钟 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡胸肉(常温冷冻均可) +- 麻油(花椒油) +- 生抽 +- 香醋 +- 白糖 +- 盐 +- 料酒 +- 姜 +- 凉白开水 + +## 计算 + +每份: + +- 鸡胸肉 200 克 +- 麻油 5 毫升 +- 生抽 4 毫升 +- 香醋 4 毫升 +- 白糖 3 克 +- 盐 2 克 +- 姜 20 克 + +## 操作 + +- 姜切片,备用 +- 锅中倒入 4 升水 +- 加入鸡胸肉、姜片 +- 倒入 20 毫升料酒 +- 开大火不盖盖将水烧开 +- 水开后转中火,用勺子将浮沫捞出 +- 继续煮 **5-7** 分钟,如果是非冷冻肉煮 5 分钟,冷冻肉煮 7 分钟 +- 鸡胸肉大小会影响成熟时间,用筷子插入鸡胸肉,如果能轻松插入,代表鸡肉熟了。如果不熟需延长煮制时间 + +![凉拌鸡丝焯水](./凉拌鸡丝_焯水.jpg) + +- 用凉白开水冲泡鸡胸肉,使鸡胸肉降至室温 +- 顺着鸡胸肉纹理将鸡胸肉撕成细丝 + +![凉拌鸡丝_细丝](./凉拌鸡丝_撕.jpg) + +- 准备一个碗 +- 碗中加入准备好的麻油、生抽、香醋、白糖、盐 +- 搅拌料汁,使糖和盐尽量溶化 +- 将料汁倒入鸡丝中,搅拌均匀 + +## 附加内容 + +- 这道菜是隔离期间用现有材料做的,有条件可以加入香菜、小葱等进行调味,喜欢吃辣的可以加入辣椒油 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝_撕.jpg b/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝_撕.jpg new file mode 100644 index 0000000..7e1d5c6 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝_撕.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d817f4cd1469d850392f89f9844535930fb7a07da03d3b69a38780cfa587c5a +size 215039 diff --git a/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝_焯水.jpg b/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝_焯水.jpg new file mode 100644 index 0000000..407d447 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/凉拌鸡丝/凉拌鸡丝_焯水.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0ecb73e8dd374afe1182ceb60ba563499d18bfd9167a7d585d3fd44057c5675 +size 191551 diff --git a/data/C8/cook/dishes/meat_dish/卤菜/卤水.jpeg b/data/C8/cook/dishes/meat_dish/卤菜/卤水.jpeg new file mode 100644 index 0000000..fa490bb --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/卤菜/卤水.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c6bb2c84276bd3f9c889360d7cbbcbe8bf74ac94372b69dfc415d44c05bc5b2 +size 771752 diff --git a/data/C8/cook/dishes/meat_dish/卤菜/卤牛肉.jpeg b/data/C8/cook/dishes/meat_dish/卤菜/卤牛肉.jpeg new file mode 100644 index 0000000..dd0f368 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/卤菜/卤牛肉.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:307470297cb0530ad2e55e597da2c027f4256f25ea69c7b34f985e225852d980 +size 571100 diff --git a/data/C8/cook/dishes/meat_dish/卤菜/卤菜.md b/data/C8/cook/dishes/meat_dish/卤菜/卤菜.md new file mode 100644 index 0000000..9a7b13d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/卤菜/卤菜.md @@ -0,0 +1,97 @@ +# 卤菜的做法 + +卤菜是一道经典的中式卤味料理,富含蛋白质和多种维生素。肉质鲜嫩多汁,香气四溢,入味程度可根据浸泡时间自行调整。这道菜适合作为凉菜、下酒菜或搭配主食食用,卤水还可多次使用,越陈越香。 +本教程以卤牛肉为例,其他肉类同理。 + +![卤牛肉](./卤牛肉.jpeg) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 卤料包(超市即可购买) +- 黄豆酱 +- 豆瓣酱 +- 蚝油 +- 南腐乳 +- 洋葱 +- 生姜 +- 大蒜 +- 干辣椒 +- 生抽 +- 老抽 +- 盐 +- 白糖(最好是黄冰糖,用于熬糖色) +- 啤酒 +- 牛腱子(或其他肉类) +- 高压锅 +- 滤网 + +## 计算 + +每次制作前需要确定计划做几份。一份约可供 2-3 人食用。 + +每份: + +- 卤料包 1 包(约 10g) +- 黄豆酱 15ml +- 豆瓣酱 15ml +- 蚝油 15ml +- 南腐乳 15ml +- 洋葱 半个(约 100g) +- 生姜 30g +- 大蒜 40g +- 干辣椒 10g +- 生抽 120ml +- 老抽 60ml +- 盐 10-15g +- 白糖 30g(用于熬糖色) +- 啤酒 1 罐(330ml) +- 牛腱子 500g +- 清水 足量(需要没过所有肉类) + +## 操作 + +建议在此之前查看炒[糖色](./../../condiment/糖色.md)教程 + +- 牛腱子提前浸泡在冷水中 3 小时以上,去除血水 + +### 准备卤水 + +- 准备糖色:锅中加入 30g 白糖,小火加热至糖完全融化并呈现棕褐色,加入 150ml 热水,搅拌均匀备用 +- 将洋葱切块,生姜和大蒜拍碎,干辣椒掰断备用 +- 在锅中加入足量的水,放入卤料包、洋葱、生姜、大蒜、干辣椒,大火烧开 +- 加入黄豆酱、豆瓣酱、蚝油和南腐乳各 15ml,搅拌均匀 +- 倒入准备好的糖色,混合均匀 +- 加入生抽 120ml 和老抽 60ml,搅拌均匀 +- 加入 10-15g 盐调味 +- 倒入 1 罐啤酒(330ml),再次烧开 + +### 卤制牛肉 + +- 牛腱子放入锅中焯水 2-3 分钟,捞出并用热水冲洗干净表面的浮沫 +- 将焯水后的牛腱子放入已烧开的卤水中,确保卤水没过所有肉类 +- 盖上高压锅盖,上汽后继续烹饪 25-30 分钟 +- 烹饪完成后,不要开盖保温,自然冷却并浸泡一晚上(这样会更入味) +- 将卤好的肉取出放入冰箱冷藏,使其成型 +- 食用前取出切片,可直接食用或凉拌 + +### 保存卤水 + +- 卤水重复使用方法:每次卤完肉后,将卤水过滤,去除所有固体内容物,重新烧开杀菌,冷却后可冷藏或冷冻保存。使用时按原配方比例重新添加调味料。(加水量根据卤水使用情况而定) +- 卤水保存得当可以使用很长时间,且越老越香。 +- **重要提示**:如卤制素菜,必须另取一部分卤水,单独使用,并且卤制完素菜的卤水不可重复使用。 + +### 凉拌调料 + +- 将蒜末、葱花、白芝麻、辣椒粉按 1:1:1:1 的比例混合,依个人口味加小米辣,热植物油中加入少量芝麻油或藤椒油,分次泼在调料上,再加入生抽、醋、蚝油各 10ml,5ml 糖,味精/鸡精,最后 15ml 卤汤混合均匀。 +- 凉拌时可搭配拍黄瓜、木耳、油炸花生米、香菜等配菜。 + +## 附加内容 + +- 卤水可另取一部分做牛肉面,作为白水面条的汤底,再加上自己喜欢的蔬菜,味道极佳。 + +![牛肉面](./牛肉面.jpeg) + +卤水: +![卤水](./卤水.jpeg) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/卤菜/牛肉面.jpeg b/data/C8/cook/dishes/meat_dish/卤菜/牛肉面.jpeg new file mode 100644 index 0000000..3fda58f --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/卤菜/牛肉面.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fca6d255f545c87957a4b7be503af35a3123f3656849f3eac18047603a25cf7 +size 721513 diff --git a/data/C8/cook/dishes/meat_dish/口水鸡/口水鸡.jpg b/data/C8/cook/dishes/meat_dish/口水鸡/口水鸡.jpg new file mode 100644 index 0000000..7ca90ff --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/口水鸡/口水鸡.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:020d49a9cc65c30953f7ea1f8ad6f278349be99cc83a7edc76275fbcb4eef130 +size 228793 diff --git a/data/C8/cook/dishes/meat_dish/口水鸡/口水鸡.md b/data/C8/cook/dishes/meat_dish/口水鸡/口水鸡.md new file mode 100644 index 0000000..14ad614 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/口水鸡/口水鸡.md @@ -0,0 +1,62 @@ +# 口水鸡的做法 + +![口水鸡](./口水鸡.jpg) + +口水鸡(凉菜),炎炎夏日里,热菜难以入口,但又嗜肉如命, +除了口水鸡,实在想不出更好的适合在夏天吃的肉菜了。 +被红油包裹的鸡肉,红艳鲜亮,冰爽 Q 弹,鲜美而不腻。夏日米饭杀手当之无愧! +(注:口水鸡做法多样,欢迎补充) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 半只鸡 +- 辣椒粉 +- 花椒 +- 花生 +- 葱姜蒜 +- 花椒 +- 白糖 +- 生抽 +- 醋 +- 味精 + +## 计算 + +每份: + +- 食用油 20ml +- 鸡 半只(500g) +- 辣椒粉 20g +- 花椒 30 颗(20g) +- 花生 10 颗(30g) +- 小葱 2 颗(50g) +- 姜 1 小块(20g) +- 蒜 2 个 (10g) +- 白糖 5g +- 生抽 5ml +- 醋 5ml +- 味精 5g +- 花椒粉 5g +- 香菜 5g + +## 操作 + +- 姜切片,1 颗小葱,15 颗花椒备用 +- 鸡肉洗干净,放入锅中,清水没过鸡肉,放入姜片、小葱和花椒,开大火烧开。 +- 大火烧开后,转中小火 20 分钟关火 +- 取出鸡肉,放入冰水中,直至冰凉 +- 取出鸡肉,切块摆盘子中,备用 +- 小火把锅烧热,导入花生,烘烤至表皮爆裂。(注意随时翻动,不要糊了) +- 一颗葱切成段,蒜拍成末,花椒 15 颗,花生去皮切碎。 +- 锅内导入油烧热后,放入葱段,花椒和一半蒜末,炒香 +- 炒至油温 8 成热,关火,滤出热油 +- 将热油倒入放辣椒粉的碗中,搅拌,并滤出红油 +- 红油中放入剩余蒜末、生抽、醋、盐、味精、糖、香油、花椒粉。拌匀放凉 +- 在鸡肉上撒上花生碎,把红油淋到切好的鸡肉上,撒上香菜。成盘 + +## 附加内容 + +- 口水鸡第二种做法待更 +- \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/可乐鸡翅.md b/data/C8/cook/dishes/meat_dish/可乐鸡翅.md new file mode 100644 index 0000000..2bafe96 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/可乐鸡翅.md @@ -0,0 +1,45 @@ +# 可乐鸡翅的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 鸡翅中 +* 可乐 +* 白糖 +* 生抽 +* 盐 +* 生姜 +* 料酒或啤酒 +* 小葱 + +## 计算 + +按照 1 盘的份量: + +* 鸡翅 10 ~ 12 只 +* 可乐 500ml +* 白糖 10 克 +* 生抽 15 克 +* 老抽 3 克 +* 盐 2 克 +* 生姜 2 片 +* 料酒 20 毫升 +* 小葱挽成结 + +## 操作 + +* 鸡翅入锅,倒入冷水淹没。放生姜 1 片和料酒 10 ~ 20 毫升。大火煮开( 大约 2 分钟 )后,撇去浮沫,沥出水分 + * 这一步针对冰鲜鸡翅,刚买来的鸡翅直接改刀用生抽进行腌制即可。 +* 捞出鸡翅,可用刀将两边各划上两口改刀。生抽约 10 克腌制鸡翅 10 分钟(生抽能完全包裹鸡翅表面入味就行) +* 锅重新小火起油,先将剩余姜片爆香,然后下入腌好的鸡翅。将鸡翅煎至金黄翻面(直到两面金黄),用炒菜勺子翻动一下鸡翅,与姜片一起翻炒 4~5 下(目的是防止鸡翅和姜片粘黏)。 +* 鸡翅金黄,倒入可乐没过鸡翅,开大火将锅中可乐煮沸,然后撇去漂浮的黑色浮沫(包含血水)。此时加入葱结。 +* 调味:加入食用盐 2 克,白糖 10 克,生抽 3 克调味(可以适当用老抽调底色,3 克)。 +* 等到葱结变黄,和姜片一起捞出,转中火继续慢煮可乐鸡翅。 +* 等到可乐呈现挂丝状态,关小火让汁牢牢挂在鸡翅上。出锅,装盘。 + +## 附加内容 + +* 加入生姜爆香的同时能防止鸡翅粘锅。 +* 最后收汁时勿开过大火,防止味道偏苦。 +* 本菜品偏甜。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/台式卤肉饭/1.jpg b/data/C8/cook/dishes/meat_dish/台式卤肉饭/1.jpg new file mode 100644 index 0000000..3cc1fa4 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/台式卤肉饭/1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3686f533a387a4c41611c6f67a5603cd45a211e0a65ee1dba76e9b492c25f1f0 +size 30221 diff --git a/data/C8/cook/dishes/meat_dish/台式卤肉饭/台式卤肉饭.md b/data/C8/cook/dishes/meat_dish/台式卤肉饭/台式卤肉饭.md new file mode 100644 index 0000000..797ed8e --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/台式卤肉饭/台式卤肉饭.md @@ -0,0 +1,73 @@ +# 台式卤肉饭的做法 + +糖和脂肪是人类快乐的源泉,富含这二者的台式卤肉饭每一口都能带来直击灵魂的满足感。 + +本文提供一种操作简单但风味不减的台式卤肉饭做法,预计制作时间 1.5 小时(0.5 小时操作,1 小时炖煮)。 + +厨房小白可上手。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 红葱头(火葱) +- 带皮五花肉 (可用猪绞肉代替) +- 鸡蛋(可选) +- 食用油 +- 生抽酱油 +- 米酒(可用料酒代替) +- 大蒜 +- 香叶 +- 八角 +- 冰糖 +- 白胡椒粉 +- 五香粉(可选) +- 米饭 + +## 计算 + +每次制作前需要确定计划做几份。以下约莫 2~3 人份。 + +- 红葱头 25 g +- 带皮五花肉 500g +- 鸡蛋 4 个(可任意修改鸡蛋个数) +- 食用油 15 ml +- 生抽酱油 75 ml +- 米酒 10 + 25 ml +- 大蒜 25 g +- 香叶 2 片 +- 八角 1 颗 +- 冰糖 20 g +- 白胡椒粉 6 g +- 五香粉 6 g +- 米饭 (根据个人食量决定) + +## 操作 + +- 带皮五花肉切成 $0.7cm(长)\times 0.7cm(宽) \times 2.5cm(高)$ 的细长条 + +![肉条示例](./1.jpg) + +- 红葱头、大蒜切末备用 +- 鸡蛋煮熟剥壳,并用刀划破蛋白(便于入味),备用。 +- **大火**热锅,锅内放入 15 ml 食用油,让油滑满锅底即可。 + - 放油的目的是防止五花肉刚下锅时粘锅。等待 5s 使油温稍微升高。 +- 放入五花肉条,翻炒至肉色稍微变白,沿锅边淋入米酒 10ml 。继续翻炒至五花肉不再出油。 +- 将切好的红葱头加入锅中,翻炒 1 分钟爆出油葱香味。 +- 将切好的红葱头加入锅中,翻炒 30 秒。 +- 把猪肉推到旁边,放入冰糖加热到融化冒泡变成焦糖,再把猪肉一起翻拌,让焦糖均匀附着。 +- 加入生抽炒出香气。 +- 呛入米酒 25 ml ,水加到淹过猪肉,加入白胡椒粉、五香粉、八角、香叶、水煮蛋,沸腾后转小火卤 1 小时。 + - 注意: 不同酱油的咸淡不一,卤的时候务必试味道,太甜加酱油,太咸加点糖或水调整。 + - 小火炖煮过程中,每隔 15 分钟 搅拌检查一次,防止粘锅。 + - 如发现过干,则可加入 100ml 清水继续炖煮。 +- 1 小时后,开大火收汁直到酱汁浓稠,呈现有光泽的琥珀色,即完成。 +- 炖煮结束后,乘一碗米饭,将软烂的卤肉浇在米饭上,并加上卤蛋,开始享用。 + +## 附加内容 + +- 对于五花肉切条步骤,定义:五花肉带皮面向上摆在桌上,此时肉皮所在平面为长宽形成的平面,垂直此平面的为高。肉条最终效果是肥瘦相间的细长条。(注意:此处肉条一定要细,即长宽较小。细肉条更易于炖煮软糯)。 +- 五花肉切条小技巧: + - 若五花肉是**未冷冻**的,可以放入冰箱**冷冻室 30 分钟** 再取出切条。 + - 若是**冷冻五花肉**,可以在**常温**下放置 **30 分钟** 后再切条。 + - 切条时可以较小的力度将刀刃与肉快速摩擦,如此更易于切割并保护五花肉肥瘦相间的结构。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/咕噜肉.md b/data/C8/cook/dishes/meat_dish/咕噜肉.md new file mode 100644 index 0000000..6f50ecd --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/咕噜肉.md @@ -0,0 +1,56 @@ +# 咕噜肉的做法 + +咕噜肉是非常下饭的菜肴,只需一道就可以吃得津津有味,大人小孩都爱吃。而这次做的是简易版菠萝咕噜肉,利用简单的材料就可以在家做出特有风味的咕噜肉 。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 梅头猪肉 +- 青椒 +- 罐头菠萝片 +- 盐 +- 茄汁 +- 白醋 +- 蒜蓉 +- 生抽 +- 生粉 +- 白砂糖 + +## 计算 + +每份: + +- 1 汤匙 = 15ml +- 1 茶匙 = 5ml + +- 梅头猪肉 100g +- 青椒 25g +- 罐头菠萝片 75g +- 盐 1/4 茶匙 +- 茄汁 4 汤匙 +- 白醋 2 茶匙 +- 蒜蓉 1 汤匙 +- 生抽 1/2 茶匙 +- 生粉 2 1/2 茶匙 +- 白砂糖 2 汤匙 +- 水 200 毫升 + +## 操作 + +- 将梅头猪肉(100 克)洗净,然后用厨房纸抹干水份,将猪肉切成比想要的成品小一圈的大小。 +- 用盐(1/2 茶匙)腌制梅头猪肉 20 分钟。 +- 将青椒(25 克)切碎。 +- 将菠萝片(75 克)切件。 +- 在碗中加入茄汁(4 汤匙)﹑白醋(2 茶匙)﹑蒜蓉(1 汤匙)﹑生抽(½ 茶匙)﹑生粉(2½ 茶匙)﹑白砂糖(2 汤匙)﹑盐(¼ 茶匙)和水(200 毫升),拌匀成酱汁。 +- 将梅头猪肉粒沾上生粉(6 汤匙)。 +- 加入油(500 毫升)中火加热。 +- 将梅头猪肉粒放至锅里中火炸 5 分钟,然后盛起。 +- 加入梅头猪肉粒,再大火翻炸 1 分钟。 +- 加入油(1 茶匙)和酱汁,中火加热 3 分钟。 +- 加入青椒和菠萝,大火加热 2 分钟。 +- 将已炸好的梅头猪肉粒与酱汁拌匀即可。 + +## 附加内容 + +- 想让肉更有层次可以在生粉中加鸡蛋,炸出来会更香脆 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/咖喱肥牛/咖喱肥牛.jpg b/data/C8/cook/dishes/meat_dish/咖喱肥牛/咖喱肥牛.jpg new file mode 100644 index 0000000..36128d6 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/咖喱肥牛/咖喱肥牛.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:831781cf825117cb5c93e1641e39bd9ad7e8e186a2d11f35f419a406f3b1422e +size 306536 diff --git a/data/C8/cook/dishes/meat_dish/咖喱肥牛/咖喱肥牛.md b/data/C8/cook/dishes/meat_dish/咖喱肥牛/咖喱肥牛.md new file mode 100644 index 0000000..c886834 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/咖喱肥牛/咖喱肥牛.md @@ -0,0 +1,51 @@ +# 咖喱肥牛的做法 + +![咖喱肥牛成品](./咖喱肥牛.jpg) + +咖喱肥牛美味营养并且下饭,吃多了炒炸菜后再吃个咖喱肥牛相当美滋滋。 + +适合在家吃或者做成便当带去公司吃(微波炉加热也不会有太大味道~)。 + +并且所需材料少,容易购买,新手一般 40 分钟即可出锅。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 香叶 +- 纯牛奶(推荐卫岗鲜奶) +- 洋葱 +- 胡萝卜 +- 土豆 +- 肥牛卷 +- 咖喱块 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 香叶 1 片 +- 纯牛奶 50ml +- 洋葱 100g +- 胡萝卜 150g +- 土豆 200g (挺饱腹的,酌情添加) +- 肥牛卷 300g (喜欢吃肉就多来点) +- 咖喱块 2 块 (大约 100g) + +## 操作 + +- 洋葱切成条状、胡萝卜以及土豆切成块状,备用 +- 烧一锅开水,水沸时将肥牛卷下锅,捞出血沫后放在一边沥水,备用 +- 热锅,锅内放入 10ml - 15ml 食用油,**等待 10 秒让油温升高** +- 放入洋葱,翻炒至洋葱变软变透明 +- 放入土豆以及胡萝卜**翻炒 2 分钟** +- 加入冷水至淹没所有食材即可 +- 将香叶、咖喱块投入锅中,盖上锅盖,**待水沸腾后将火调小然后等待直至土豆块以及胡萝卜块炖至软烂(可用筷子确认)** +- 加入肥牛卷以及牛奶,盖上锅盖再小火煮 2-3 分钟即可出锅(用勺子搅拌食材,注意力度,避免肥牛卷破碎) + +## 附加内容 + +- 咖喱块不用捣碎,直接整块投入即可。 +- 操作时,需要注意搅拌食材,避免食材调味料不均匀。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/商芝肉.md b/data/C8/cook/dishes/meat_dish/商芝肉.md new file mode 100644 index 0000000..0d0482b --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/商芝肉.md @@ -0,0 +1,55 @@ +# 商芝肉的做法 + +此菜色泽红润,质地软嫩,肥而不腻,有浓郁的商芝香味,是陕西省商县特有的风味菜。因商芝属于陕西特产,此菜原料获取难度较大,不易制作。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 带皮猪五花肉(去骨) +- 商芝(又名紫萁,属蕨类,嫩叶可食) +- 葱 +- 姜 +- 八角 +- 蜂蜜 +- 醋 +- 料酒 +- 味精 +- 酱油 +- 摊鸡蛋皮 +- 精盐 +- 鸡汤 +- 芝麻油 +- 熟猪油 + +## 计算 + +每份:两人量 + +- 带皮猪五花肉: 500 克 +- 商芝: 50 克 +- 葱: 10 克 +- 姜: 2 克 +- 八角: 3 个 +- 蜂蜜: 15 克 +- 醋: 5 克 +- 料酒: 15 克 +- 味精: 1.5 克 +- 酱油: 10 克 +- 摊鸡蛋皮:一张约 15 克 +- 精盐: 1 克 +- 鸡汤: 200 克 +- 芝麻油: 10 克 +- 熟猪油: 2000 克(消耗约 60 克) + +## 操作 + +- 将肉刮洗干净,入煮锅煮至六成熟(变色为白),捞出趁热用蜂蜜、醋涂抹肉皮。 +- 炒锅内放入熟猪油,用旺火烧至八成熟(约 200 度,油表有大量青烟,油状平静),将肉块皮朝下投入,炸至呈金红色时,捞入凉肉煮锅(之前煮完的煮锅)中泡软,放在案板上,切成三寸(10 cm)长、两分(0.6 cm)厚的片,仍然皮朝下,整齐装入蒸碗内。 +- 将 5 克大葱切成 2.4 cm 长的段,5 克切成 2.4 cm 长的斜形片。姜去皮洗净,1.5 克切成片,5 克切成末,摊的鸡蛋皮切成 2.4 cm 长的等腰三角形片。 +- 商芝入沸水锅中煮软捞出,去除老茎、杂质,淘洗干净,切成 3 cm 长的段,放入碗中,加酱油(5 克)、精盐(1 克)、熟猪油(10 克)拌匀,盖在肉片上,另将鸡汤(100 克)放入一小碗中,加酱油(5 克)、精盐(0.5 克)、料酒(15 克)搅匀,浇入蒸碗,再放入姜片、葱段、八角上笼用旺火蒸约半小时后,转用小火继续蒸约一小时三十分钟,熟烂后取出,拣去姜、葱、八角,倒、过滤原汁,将肉扣入汤盘。 +- 炒锅内,放入鸡汤(100 克),加入原汁,用旺火烧沸,下入姜末、葱片、味精后搅匀,投入摊鸡蛋皮,淋芝麻油,浇入汤盘即成。 + +## 附加内容 + +- 商芝属于小地方不特别有名的特产,至少本人在其他地方没有见到过,在制作时可换成其他蕨类蔬菜。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/啤酒鸭/啤酒鸭.jpg b/data/C8/cook/dishes/meat_dish/啤酒鸭/啤酒鸭.jpg new file mode 100644 index 0000000..cbe808b --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/啤酒鸭/啤酒鸭.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2696cfa7ce4efb1c045ed2b731eed670f4feca83a015bb309035d0701962f06 +size 513313 diff --git a/data/C8/cook/dishes/meat_dish/啤酒鸭/啤酒鸭.md b/data/C8/cook/dishes/meat_dish/啤酒鸭/啤酒鸭.md new file mode 100644 index 0000000..79521dc --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/啤酒鸭/啤酒鸭.md @@ -0,0 +1,58 @@ +# 啤酒鸭的做法 + +![啤酒鸭成品](./啤酒鸭.jpg) + +啤酒鸭不仅入口鲜香,还带有一股啤酒清香。肉久吃不腻,汤久涮而不淡。风味独特,具有热而不浮,香而不腻的独特口味让人赞口不绝。一般初学者需要 1 小时即可完成。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 鸭肉 +- 啤酒 +- 生抽酱油 +- 老抽酱油 +- 姜 +- 蒜 +- 冰糖 +- 干辣椒 +- 料酒 +- 盐 +- 鸡精 +- 丁香 +- 八角 +- 香叶 +- 豆瓣酱 + +## 计算 + +每份: + +- 鸭肉半只(约 1kg) +- 啤酒 800ml +- 生抽酱油 10-15ml +- 老抽酱油 5-10ml +- 姜 5 片 +- 蒜头 12 瓣 +- 冰糖 10g +- 干辣椒 5 个 +- 料酒 30ml +- 盐 8g +- 鸡精 5g +- 丁香 4 颗 +- 八角 3 个 +- 香叶 3 片 +- 豆瓣酱 20g + +## 操作 + +- 把鸭子切成 3 cm 小块,鸭肉冷水下锅,加姜片、料酒,焯一遍水,盛出沥干水分,备用。 +- 炒锅烧热,放入约 100ml 食用油,大火待油烧开,鸭肉入锅翻炒至上色。 +- 待鸭肉完全变色(肉眼可见泛白),将鸭肉拨到锅的一边,倒入豆瓣酱和糖,小火翻炒出香味和糖色。 +- 加入丁香、八角、香叶、干辣椒、生抽、老抽、蒜,翻炒出香味。 +- 倒入啤酒,没过鸭肉,加入盐、鸡精,然后中火将鸭子烧 30 分钟(牙口不好的话可以再多烧 5 分钟)。 +- 出锅盛盘,上桌食用。 + +## 附加内容 + +- 啤酒的量一定要足够把所有鸭肉没过,啤酒最好选择清香型的。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/回锅肉/1.jpeg b/data/C8/cook/dishes/meat_dish/回锅肉/1.jpeg new file mode 100644 index 0000000..11c5bfe --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/回锅肉/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1c83481ffa82bf0d22631984d1c75df5b4aadbace98933337cd6a938f3c0f69 +size 156595 diff --git a/data/C8/cook/dishes/meat_dish/回锅肉/2.jpeg b/data/C8/cook/dishes/meat_dish/回锅肉/2.jpeg new file mode 100644 index 0000000..47350b5 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/回锅肉/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:448c9b45675459262ac7f67cf93f207bcf922b4b284a38d2c6ea227fef417cf7 +size 172039 diff --git a/data/C8/cook/dishes/meat_dish/回锅肉/回锅肉.md b/data/C8/cook/dishes/meat_dish/回锅肉/回锅肉.md new file mode 100644 index 0000000..c952038 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/回锅肉/回锅肉.md @@ -0,0 +1,82 @@ +# 回锅肉的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 五花肉 +- 小葱 +- 生姜 +- 青红椒 +- 蒜苗 +- 料酒 +- 豆瓣酱 +- 生抽酱油 +- 味精 + +## 计算 + +- 五花肉的用量为 0.5 斤/男人 0.3 斤/女人 (正宗回锅肉使用二刀肉[俗称:臀尖]制作,肉质坚实,肥瘦合适) +- 小葱 2 棵 +- 生姜 10-40g +- 青红椒(根据受辣程度选择, 0-30g)*注:不建议使用肉厚的菜椒 +- 蒜苗 1 把 +- 料酒 5ml +- 豆瓣酱 10ml +- 味精 5g +- 生抽 5ml + +## 操作 + +### 五花肉一段处理 + +- 锅烧热,用手将五花肉紧紧压在锅上炙皮 + - 这一步是为了处理猪皮上的汗腺(或者买肉的时候让师傅烧一下皮,喜欢汗腺的可以无视) +- 用钢丝球把皮刷干净,至黑色部分碳化部分被完全去除,不刷干净会有苦味 +- 将五花肉放入锅中,放入能淹没五花肉的冷水,放入生姜片、料酒和小葱(取 2 棵小葱打结) +- 开大火煮,水开后撇去浮沫,继续煮 15 分钟,煮至瘦肉部分可以用筷子轻松刺穿 + +### 配菜处理 + +- 青红椒切圈 +- 蒜苗切段 +- 生姜切小薄片 +- 将 5ml 豆瓣酱和 5ml 生抽提前混合 + +### 五花肉二段处理 + +- 将煮熟的五花肉捞出放入冷水晾凉 +- 擦干五花肉的水,切成上肥下瘦的 2mm 的薄片(切厚了口感不好,而且很油) + +### 开始炒肉 + +注意,此步骤**操作要迅速,小心糊锅** + +1. 锅烧热,放入一层底油滑锅 +2. 放入五花肉煸炒至肥肉透明,肉片微卷(欲称起灯盏窝),二刀肉效果最佳。 +3. 倒入豆瓣生抽混合物,5g 味精翻炒 15 秒 +4. 放入青红椒圈和小姜片,放入另 5ml 豆瓣酱翻炒 30 秒 +5. 放入蒜苗翻炒 60 秒 +6. 出锅 + +### 简易版本 + +- 选用冰冻五花肉常量放置 0.5 小时 或者鲜五花肉放冰箱冷藏 1 个小时,切成 2-5 mm 薄片 +- 开中火,辣椒放过锅中干煸 30-45 秒后取出 +- 锅烧热,放入一层底油滑锅,放入姜片煸炒 15 秒 +- 倒入五花肉,间隔 10 S 翻炒一次,待五花肉出现焦黄色(翻炒时间越久五花肉口感越硬) +- 倒入之前干煸过的辣椒、10ml 豆瓣酱,生抽调味,继续翻炒 60 秒 +- 倒入切成段的蒜苗翻炒 10 秒 +- 出锅 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) + +## 附加内容 + +- 不喜欢蒜苗可以换成洋葱或者其他蔬菜,但是要注意蔬菜的易熟程度将蔬菜提前炒至,不然会出现蔬菜半生不熟的情况 +- 如果回锅肉比较大块可以切成 5 厘米见方的块,五花肉煮至筷子稍微用力即可插入猪皮即可 +- 回锅肉过冷水晾凉后肉质会更紧致 +- 回锅肉擦干水是为了避免炒至的时候爆油溅伤 +- 回锅肉切记不要切厚了,不然很腻 +- \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/土豆炖排骨/土豆炖排骨.md b/data/C8/cook/dishes/meat_dish/土豆炖排骨/土豆炖排骨.md new file mode 100644 index 0000000..93adf21 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/土豆炖排骨/土豆炖排骨.md @@ -0,0 +1,53 @@ +# 土豆炖排骨的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 肋排 +- 土豆 +- 姜 +- 小葱 +- 料酒 +- 白糖 +- 干辣椒 +- 八角 +- 花椒 +- 桂皮 +- 生抽 +- 老抽 +- 蚝油 +- 黄豆酱 + +## 计算 + +- 肋排 = 750g +- 土豆 = 300g +- 姜 = 30g +- 小葱 = 25g +- 料酒 = 25g +- 白糖 = 10g +- 干辣椒 = 5g +- 八角 = 5g +- 花椒 = 5g +- 桂皮 = 5g +- 生抽 = 10g +- 老抽 = 5g +- 蚝油 = 5g +- 黄豆酱 = 5g + +## 操作 + +- 土豆两个滚刀切片,姜片切片 +- 排骨 750g 冷水下锅,加入姜片、葱段、料酒焯水 2 分钟,焯干水后捞出清洗干净(一定要用热水,不能用冷水) +- 热锅凉油,将白糖倒入锅中,翻炒至融化为焦糖色 +- 加入排骨煎至两面金黄,让排骨裹满焦糖 +- 加入干辣椒、八角、花椒、桂皮、姜片(建议买超市的香料包)、10ml 生抽、5ml 老抽、5ml 料酒、5ml 蚝油、5ml 黄豆酱 +- 大火翻炒均匀后加入 700ml 开水,大火烧开后转小火焖煮 1 小时 +- 最后加入土豆煮 10 分钟就可以出锅啦(喜欢吃青红椒的也可以按自己喜好加入) +- ![成果展示](./排骨1.jpg) +- ![成果展示](./排骨2.jpg) + +## 附加内容 + +这道菜难度系数简单,对新手友好,超级下饭 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/土豆炖排骨/排骨1.jpg b/data/C8/cook/dishes/meat_dish/土豆炖排骨/排骨1.jpg new file mode 100644 index 0000000..d882ae8 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/土豆炖排骨/排骨1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b5e629ff56fb13f0795bc843fb786c943782cb64812fbd803bc3bfc4ac7f5ff +size 111677 diff --git a/data/C8/cook/dishes/meat_dish/土豆炖排骨/排骨2.jpg b/data/C8/cook/dishes/meat_dish/土豆炖排骨/排骨2.jpg new file mode 100644 index 0000000..843ea54 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/土豆炖排骨/排骨2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79b8de0a0a08f5ceb32b93a4523fe4407f1e0e9cb40c3f9ce903f913c3b7896a +size 107934 diff --git a/data/C8/cook/dishes/meat_dish/奶酪培根通心粉/onepot.png b/data/C8/cook/dishes/meat_dish/奶酪培根通心粉/onepot.png new file mode 100644 index 0000000..0a42fac --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/奶酪培根通心粉/onepot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afa27596d08feffb45f2c93c92c37f5e116b8fcddb0416d5e106868611dae2f2 +size 189250 diff --git a/data/C8/cook/dishes/meat_dish/奶酪培根通心粉/oven.jpg b/data/C8/cook/dishes/meat_dish/奶酪培根通心粉/oven.jpg new file mode 100644 index 0000000..da53fe5 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/奶酪培根通心粉/oven.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e17a7accfc97ccd3a5b58fa2d8d38583d0d4835e40b03b141714cf1f6f1e6232 +size 42358 diff --git a/data/C8/cook/dishes/meat_dish/奶酪培根通心粉/奶酪培根通心粉.md b/data/C8/cook/dishes/meat_dish/奶酪培根通心粉/奶酪培根通心粉.md new file mode 100644 index 0000000..25a195a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/奶酪培根通心粉/奶酪培根通心粉.md @@ -0,0 +1,58 @@ +# 奶酪培根通心粉的做法 + +![烘烤成品](./oven.jpg) +![非烘烤成品](./onepot.png) + +这是一道美味的奶酪培根通心粉(Mac and Cheese),适合四人享用。它结合了浓郁的奶酪和香脆的培根,简单易做,是一道受欢迎的美式家常菜。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 通心粉 +- 奶酪 +- 肉类 +- 洋葱 +- 黄油 +- 面粉 +- 牛奶 +- 大蒜 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +- 通心粉 100-125g +- 奶酪 40-55g,若要烘烤额外准备 25g, 条状 +- 培根或其他肉类 100-125g +- 洋葱 25g-40g 切成碎 +- 黄油 15g +- 面粉 10g +- 牛奶 125ml +- 大蒜半瓣,切碎 + +## 操作 + +- 奶酪要磨成碎末 +- 洋葱切成条状 +- 通心粉用微咸的水煮 6 分钟 +- **中火** +- 锅中放入黄油,等待融化 +- 加入洋葱 +- 洋葱软化后加入大蒜 +- 大蒜香味出来后,加入肉类,等待 5 秒 +- **小火** +- 分四次加入牛奶,每次搅拌 5 秒后再加下一次 +- 加入面粉并充分搅拌 +- 加入奶酪并搅拌均匀 +- 将通心粉和奶酪搅拌 +- 如果不打算烘烤,可以直接吃了 +- **烘烤:** +- 预热烤箱至 180°C +- 将额外的 50g 芝士铺在通心粉之上 +- 等待烤箱预热至 180°C 后,将通心粉放入 +- 烤至表面金黄,约 24 分钟 + +## 附加内容 + +本料理及其不健康,有大约 1300 大卡,80g 脂肪,不建议常吃。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/姜炒鸡/姜炒鸡.jpg b/data/C8/cook/dishes/meat_dish/姜炒鸡/姜炒鸡.jpg new file mode 100644 index 0000000..5fcc9c0 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/姜炒鸡/姜炒鸡.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:100bcfa2cf789ede4042b555889dbd20de1a748c2f55d8ec033b10a6ce57119d +size 70533 diff --git a/data/C8/cook/dishes/meat_dish/姜炒鸡/姜炒鸡.md b/data/C8/cook/dishes/meat_dish/姜炒鸡/姜炒鸡.md new file mode 100644 index 0000000..fd1383c --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/姜炒鸡/姜炒鸡.md @@ -0,0 +1,46 @@ +# 姜炒鸡的做法 + +![姜炒鸡](./姜炒鸡.jpg) + +姜炒鸡是一道湖南口味菜,下饭五颗星,食材平平无奇又十分容易烹制,一学就会。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡 +- 生姜 +- 啤酒 +- 生抽 +- 老抽 +- 盐 +- 小米椒 +- 美人辣 +- 泡椒 +- 大蒜 + +## 计算 + +- 鸡 = 半只(土鸡最好,预计 650g) +- 食用油 = 50ml(茶油最好,没有就用菜籽油) +- 生姜 = 半斤 (250g) +- 啤酒 = 半瓶 250ml +- 生抽 = 20ml +- 老抽 = 10ml +- 盐 = 3g +- 小米椒 = 0-5 个 (0-50g)(根据辣口味调整) +- 美人辣 = 0-5 个 (0-50g)(没有可以用小米椒代替) +- 泡椒 = 5 个 (50g) +- 大蒜 = 3 头 (50g) + +## 操作 + +- 鸡尽量剁成 1cm 的小块,洗净后滤干,再放生抽腌和料酒腌制 30 分钟 +- 大先热锅到微微冒烟,放入食用油,等 5 秒 +- 下入姜片后转中火炒 30 秒, +- 下入鸡块翻炒 3 分钟,炒干水分,炒出鸡油 +- 放入各种剁碎的辣椒和大蒜子,加盐和老抽继续翻炒 30 秒 +- 倒入啤酒,中小火焖 2 分钟 +- 大火收汁盛盘 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/姜葱捞鸡/姜葱捞鸡.md b/data/C8/cook/dishes/meat_dish/姜葱捞鸡/姜葱捞鸡.md new file mode 100644 index 0000000..75b7023 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/姜葱捞鸡/姜葱捞鸡.md @@ -0,0 +1,43 @@ +# 姜葱捞鸡的做法 + +嫩滑爆汁,白饭杀手,简单易做, + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡腿肉 +- 盐焗鸡粉 +- 葱,姜 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 鸡腿 4 个, 约 400g +- 盐焗鸡粉 5g +- 姜 50g +- 葱 1 根 +- 盐 5g +- 糖 5g +- 油 35ml + +## 操作 + +- 四个鸡腿清洗干净,放入碗中 +- 碗中加入盐焗鸡粉和 5ml 油,搅拌均匀 +- 让鸡腿静置腌制 15 分钟, 同时准备蒸锅并把水煮开 +- 鸡腿腌制完成后, 放入水开后的蒸锅中,蒸制 20 分钟 +- 将姜根据个人口味切成 1)姜蓉或 2)姜丝或 3)姜粒 +- 将葱切成 0.5cm 小段 +- 将葱姜放入蘸料碗,并加入盐和糖 +- 将剩余的油倒入另一个锅中加热至六至七层热 +- 将热油淋入葱姜碗中 +- 鸡腿蒸好后将其撕碎成鸡丝,不需要特别细,大概 1cm 粗就可以 +- 姜葱姜油淋在鸡丝上,搅拌均匀即可 + +## 附加内容 + +- 参考: [白饭杀手来啦 #姜葱捞鸡-哔哩哔哩](https://b23.tv/2trBdqJ) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/孜然牛肉.md b/data/C8/cook/dishes/meat_dish/孜然牛肉.md new file mode 100644 index 0000000..2ebffcc --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/孜然牛肉.md @@ -0,0 +1,43 @@ +# 孜然牛肉的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 牛柳或牛肩肉 +* 青椒 +* 孜然(颗粒>粉) +* 小米椒 +* 生抽酱油 +* 淀粉 +* 油 +* 盐 +* 葱 +* 捣药罐(可选) + +## 计算 + +* 牛肉用量为 250 g/人 +* 青椒用量为 2 颗/人, 每颗 100g +* 孜然用量为 20 g/人 +* 小米椒用量为 3 颗/人, 每颗 5g +* 生抽酱油用量为 20 ml/人 +* 淀粉用量为 10g/人 +* 油用量为 15ml/人 +* 盐量用量为 3 g/人 +* 葱用量为 1 根/人, 每颗 20g + +使用上述条件,计算出计划使用的原材料比例,依口味调整。 + +## 操作 + +* 首先将小米椒切碎,和孜然粒一起放入捣药罐捣碎成颗粒,这样更入味。如果时间紧张可跳过捣碎步骤 +* 青椒切头去籽(喜欢辣的可不去),切成丝。葱切段。 +* 牛肉提前解冻,过一边水洗干净,晾干或用厨用纸吸干,将牛肉顺着纹理切成片 +* 然后进行腌肉,加入生抽,淀粉,油,均匀搅拌,静止 30 分钟。腌肉方法也可参考[学习腌](../../tips/learn/学习腌.md) +* 热锅下油,放入葱,爆出香味后放入腌好的牛肉煸炒 +* 牛肉变色后均匀放入孜然辣椒颗粒并炒熟 +* 然后下入青椒丝,断生后放盐 +* 大🔥炒 1 分钟后关火再翻炒 30 秒保证受热均匀即可出锅 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/宫保鸡丁/宫保鸡丁.jpg b/data/C8/cook/dishes/meat_dish/宫保鸡丁/宫保鸡丁.jpg new file mode 100644 index 0000000..1b79c18 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/宫保鸡丁/宫保鸡丁.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:190140df874799a6ad894b20fe66c168f752491648621827b5cf6c3f7bc9d4d5 +size 273993 diff --git a/data/C8/cook/dishes/meat_dish/宫保鸡丁/宫保鸡丁.md b/data/C8/cook/dishes/meat_dish/宫保鸡丁/宫保鸡丁.md new file mode 100644 index 0000000..ab7aeee --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/宫保鸡丁/宫保鸡丁.md @@ -0,0 +1,95 @@ +# 宫保鸡丁的做法 + +老派川菜的简单做法分享 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 手枪腿(或者鸡胸脯肉) +- 大葱 +- 干辣椒(或者二荆条) +- 熟花生 +- 生抽酱油 +- 香醋 +- 白糖 +- 料酒 +- 盐 +- 鸡精 +- 淀粉 +- 植物油 +- 芝麻油 + +### 可选原料 + +- 油泼辣子 +- 莴笋 +- 生花生 +- 豆瓣酱 + +## 计算 + +注意,这道菜默认一人版本,两人也够吃,理论上多人只需简单加倍即可。 + +- 必须配料 + - 手枪腿(或者鸡胸脯肉) = 1 支(约 350g) + - 大葱 = 1 根(约 180g) + - 熟花生 = 150g + - 姜片 = 10g + - 干辣椒(或者二荆条) = 10g(若选择二荆条,则需要大约 4 支) + - 生抽酱油 = 10g + - 白糖 = 2g + - 盐 = 2g + - 植物油 = 20g + - 淀粉 = 15g + - 料酒 = 15g +- 进阶配料 + - 老抽酱油 = 5g + - 花椒 = 5g + - 香醋 = 5g + - 鸡精 = 2g + - 芝麻油 = 10g + - 淀粉(用以勾芡) = 10g + - 豆瓣酱 = 10g +- 可选配料 + - 莴笋 = 约 250g + - 油泼辣子 = 5g + +使用上述条件,计算出计划使用的原材料比例,依口味调整。 + +## 操作 + +### 简易版本 + +- 手枪腿用剪刀去骨,鸡肉面用刀背拍打一遍,切条后切至 1.5cm 见方肉丁;泡于清水 10 分钟,捞出控干备用(若是鸡胸脯肉,则可以直接进行切丁以及之后的动作) +- 取大葱葱绿与姜片 5g 于碗中,倒入 50g 开水备用;葱白切 1.5cm 圆粒备用;取花生放入微波炉高火 5 分钟焙干备用 +- 鸡丁中加入盐 2g,老抽酱油 5g,料酒 15g,淀粉 15g 搅拌均匀,至微微发干;缓慢加入部分葱姜水,搅拌鸡丁至粘手;保鲜膜密封,放入冰箱腌制 1 小时 +- 干辣椒切段;起锅,大火烧热转小火;放入干辣椒焙干至微微发糊,捞起备用;花椒焙干至有香味,捞起备用 +- 转大火,倒入 20g 植物油,7 成热(竹筷子起泡)下入鸡丁,煎至上面开始发白,用锅铲翻面,煎 30s 后翻炒均匀 +- 下入葱粒翻炒,加入余下葱姜水不够 100g 再加一点清水(务必是热水);盖上锅盖,转中小火焖 2 分钟; +- 转大火,下入熟花生,干辣椒和花椒;加入鸡精 2g,香醋 5g,白糖 2g,翻炒均匀; +- 淀粉 10g 加 50g 清水调成水淀粉,加入锅中,翻炒均匀,收汁到自己想要的浓度 +- 关火,淋入芝麻油 10g,即可出锅 + +### 稍加复杂但是更加令人垂涎欲滴的版本 + +相较于简单版本,这里更加推荐使用二荆条与生花生。并且加入了莴笋陪衬花生的香脆与鸡肉的松软 + +- 莴笋去皮切至 1cm 见方的小块,备用; +- 二荆条切成 1cm 长段; +- 手枪腿用剪刀去骨,鸡肉面用刀背拍打一遍,切条后切至 1.5cm 见方肉丁;泡于清水 10 分钟,捞出控干备用(若是鸡胸脯肉,则可以直接进行切丁以及之后的动作); +- 取大葱葱绿与姜片 5g 于碗中,倒入 50g 开水备用;葱白切 1.5cm 圆粒备用 +- 鸡丁中加入盐 2g,老抽酱油 5g,料酒 15g,淀粉 15g 搅拌均匀,至微微发干;缓慢加入部分葱姜水,搅拌鸡丁至粘手;保鲜膜密封,放入冰箱腌制 1 小时 +- 转中火,倒入 20g 植物油,放入生花生翻炒至其表面微微焦糊,捞起花生但是油留在锅内; +- 继续加热,7 成热(竹筷子起泡)下入鸡丁,放入豆瓣酱,翻炒大概 1 分钟; +- 加入备好的莴笋丁,继续翻炒 1 分钟; +- 下入葱粒翻炒,加入余下葱姜水不够 100g 再加一点清水(务必是热水);加入二荆条段;盖上锅盖,转中小火焖 2 分钟; +- 转大火,下入先前捞起来备用的花生,花椒;加入鸡精 2g,香醋 5g,白糖 2g,翻炒均匀; +- 淀粉 10g 加 50g 清水调成水淀粉,加入锅中,翻炒均匀,收汁到自己想要的浓度 +- 关火,淋入芝麻油 10g 与油泼辣子 5g 再翻炒 10s,即可出锅 + +![宫保鸡丁](./宫保鸡丁.jpg) + +## 附加内容 + +辣椒依据个人口味酌量添加,怕辣可去籽; \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/小炒肉.md b/data/C8/cook/dishes/meat_dish/小炒肉.md new file mode 100644 index 0000000..e0f135a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/小炒肉.md @@ -0,0 +1,48 @@ +# 小炒肉的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 五花肉 +- 朝天椒 +- 小米椒 +- 豆豉 +- 豆瓣酱 +- 老抽 +- 淀粉 +- 盐 +- 葱 +- 蒜 + +## 计算 + +每份: + +- 五花肉 500g +- 朝天椒 4 条 +- 小米椒 4 颗 +- 豆豉 10g,根据个人口味加减 ±5g +- 豆瓣酱 10g,根据个人口味加减 ±5g +- 老抽 10ml +- 淀粉 10g +- 盐 1-2g +- 葱 0.5-1 根 +- 蒜 2 瓣 +- 食用油 15ml + +## 操作 + +- 五花肉切片 +- 把肉放入器皿内,加入淀粉、老抽、盐搅拌腌制半小时 +- 葱切段 +- 小米椒、朝天椒斜刀切好 +- 热锅、倒油 +- 油热后加入五花肉煸炒。炒至变色后盛出来 +- 向锅中加蒜,煸出香味,加入豆豉,翻炒均匀 +- 加入豆瓣酱翻炒均匀 +- 加入炒好的五花肉继续的翻炒均匀 +- 加入小米椒、朝天椒、葱段翻炒 40 秒 +- 出锅。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/小炒鸡肝/小炒鸡肝.md b/data/C8/cook/dishes/meat_dish/小炒鸡肝/小炒鸡肝.md new file mode 100644 index 0000000..43748a7 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/小炒鸡肝/小炒鸡肝.md @@ -0,0 +1,71 @@ +# 小炒鸡肝的做法 + +![小炒鸡肝](./成品.jpg) + +一道稍微麻烦的菜。 + +适合喜欢吃肝的人,也可以用其他的动物的肝,但是鸡肝会更好吃。 + +需要初学者具有一定的焯水技巧。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 生鸡肝 +- 蒜苗(蒜苗指的是:大蒜幼苗发育到一定时期的青苗。有些地方叫做青蒜,特别说明一下。) +- 大葱、姜、料酒 +- 食用盐、鸡精(味精)、五香粉(十三香)、胡椒粉 +- 烧烤料或孜然粉(可选) +- 芝麻(可选) +- 食用油 + +## 计算 + +每次制作前需要确定计划做几份。 +一份正好够 2 个人吃。 + +每份: + +- 生鸡肝 5 个(约 800g) +- 蒜苗(约 200g,喜欢吃的可以多放) +- 大葱 150g(分成两份,一份切段 100g,一份切片 50g) +- 姜 120g(分成两份,一份切片 70g,一份切丁 50g) +- 料酒 30ml +- 食用盐 5g +- 鸡精 5g(也可以是味精) +- 五香粉 5g(十三香) +- 胡椒粉 5g +- 烧烤料或孜然粉 10g(可选) +- 芝麻 5g (可选) +- 食用油 30ml + +## 操作 + +- 鸡肝清洗,备用 +- 蒜苗清洗,切段,备用 +- 大葱清洗,取 100g 切段,取 50g 切片,备用 +- 姜清晰,取 70g 切片, 取 50g 切丁,备用 +- 第一步:焯水 + - 清洗后的鸡肝放入锅内,加入凉水淹没鸡肝,并放入 100g 切段的大葱、70g 切片的姜和 30ml 料酒 + - 开大火,待水沸腾调至中火并撇去浮沫后**等待5-10分钟** + - 关火,捞出过凉水并清洗干净 + - 清洗干净后切片,备用 +- 第二步:炒制 + - 开中火。锅内加入 30ml 食用油,等待 10 秒使油升温 + - 加入 50g 切片的大葱和 50g 切丁的姜,翻炒爆香 + - 爆香后加入切片的鸡肝,翻炒至微微发黄 + - 加入蒜苗,翻炒 30 秒,断生后调至为小火 + - 加入调味料 + - 食用盐 5g + - 鸡精(味精) 5g + - 五香粉(十三香) 5g + - 胡椒粉 5g + - 烧烤料或 10g (可选) + - 调至为大火,快速翻炒 30 秒防止糊锅,关火 + - 盛出盘内,可以撒入 5g 芝麻作为装饰,如果不喜欢或者没有则可以不用添加。 + +## 附加内容 + +- 焯水时,需要注意观察沸腾的水位线,不要让水溢出避免发生危险。 +- 焯完水的鸡肝建议用凉水冲洗,更推荐冰水,可以让口感更好。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/小炒鸡肝/成品.jpg b/data/C8/cook/dishes/meat_dish/小炒鸡肝/成品.jpg new file mode 100644 index 0000000..c9a3e00 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/小炒鸡肝/成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf70ef2b18c3656e35d477cbe1c822828ce6aef6a437b33faa9c502027552153 +size 879941 diff --git a/data/C8/cook/dishes/meat_dish/小炒黄牛肉/小炒黄牛肉.jpg b/data/C8/cook/dishes/meat_dish/小炒黄牛肉/小炒黄牛肉.jpg new file mode 100644 index 0000000..d062e88 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/小炒黄牛肉/小炒黄牛肉.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da984fa253aab4c819341c3fa6da2f49ac303b8b5f1e12a56c3c02c07da15925 +size 257180 diff --git a/data/C8/cook/dishes/meat_dish/小炒黄牛肉/小炒黄牛肉.md b/data/C8/cook/dishes/meat_dish/小炒黄牛肉/小炒黄牛肉.md new file mode 100644 index 0000000..c2fdacc --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/小炒黄牛肉/小炒黄牛肉.md @@ -0,0 +1,43 @@ +# 小炒黄牛肉的做法 + +![小炒黄牛肉成品](./小炒黄牛肉.jpg) + +小炒黄牛肉是一道简单易做的湘菜。口味十分劲爆爽口。一般初学者只需要 1 小时即可完成 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 牛里脊 +- 芹菜 +- 小米椒 +- 野山椒 +- 香菜 + +## 计算 + +每份: + +- 牛里脊 400g +- 芹菜 200g +- 小米椒 30g +- 野山椒 30g +- 香菜 30g +- 食用油 15ml +- 酱油 6ml + +## 操作 + +- 牛里脊切成不超过 3cm 宽,3mm 厚的薄片,倒入 6ml 酱油,用手抓匀备用 +- 芹菜切成不超过 5cm 的小段,备用 +- 小米椒切成丝状,备用 +- 野山椒切成颗粒,备用 +- 香菜切成成不超过 3cm 的小段,备用 +- 热锅,锅内放入 15ml 食用油,大火等待 30 秒让油温升高 +- 放入小米椒和野山椒爆香 +- 放入牛里脊和芹菜,然后**大火翻炒 1 分钟** +- 关火,撒上香菜,盛盘 + +## 附加内容 + +- 操作时,全程需要开大火 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/小米辣炒肉.md b/data/C8/cook/dishes/meat_dish/小米辣炒肉.md new file mode 100644 index 0000000..129a33d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/小米辣炒肉.md @@ -0,0 +1,45 @@ +# 小米辣炒肉的做法 + +⚠️注意:不建议清淡饮食的尝试。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 小米辣 +* 花生油 +* 五花肉/瘦肉 +* 盐 +* 生抽 +* 蚝油 +* 大蒜 +* 姜 +* 豆瓣酱 +* 鸡精 +* 白糖 + +## 计算 + +每份: + +- 小米椒 20 个,根据个人口味加减 +- 花生油 20ml +- 五花肉/瘦肉 200g +- 盐 1-2g +- 生抽 10ml +- 蚝油 10ml +- 姜蒜 50g +- 豆瓣酱 10g,根据个人口味加减 +- 鸡精 10g +- 白糖 5g + +## 操作 + +* 将小米辣洗净,斜刀切大一点 +* 肉的话,想切丝切丝,想切片切片,倒入调料(生抽、蚝油、盐)腌制 5 分钟 +* 热锅倒油,先把肉炒好盛起 +* 姜蒜爆香,倒入豆瓣酱翻炒,到入切好的小米辣,再倒入瘦肉,翻炒一下,放点生抽、鸡精、盐、糖翻炒 + +## 附加内容 + +**调料可以根据自己的喜好放,也可以加老抽,老抽更香!** \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/小酥肉.md b/data/C8/cook/dishes/meat_dish/小酥肉.md new file mode 100644 index 0000000..528dbff --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/小酥肉.md @@ -0,0 +1,92 @@ +# 小酥肉的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 去皮猪肉(根据喜好选择肥瘦) +- 植物油 +- 老姜 +- 小葱 +- 料酒 +- 盐 +- 十三香 +- 胡椒粉 +- 味精 +- 鸡精 +- 花椒碎 +- 花椒粒 +- 生抽 +- 鸡蛋 +- 面粉 +- 红薯淀粉 + +## 计算 + +### 主料 + +- 猪肉 500 克 + +### 辅料 + +- 鸡蛋 2 个 +- 面粉 30 克 +- 红薯淀粉 120 克 + +### 葱姜水 + +- 老姜 20 克 +- 小葱 15 克 +- 料酒 15 克 +- 清水 80 克 + +### 腌制调料 + +- 盐 4 克 +- 十三香 2 克 +- 胡椒粉 3 克 +- 味精 5 克 +- 鸡精 5 克 +- 花椒碎 3 克 +- 花椒粒 3 克 +- 生抽 8 克 + +## 操作 + +### 葱姜水制作 + +- 老姜切丝,小葱不用切。 +- 根据计算公式倒入料酒、清水。 +- 用手捏揉 5 分钟,使姜葱的味道充分溶解在水中。 + +### 猪肉处理 + +- 将猪肉去皮洗净 +- 切成长度 8~10 厘米,厚度 1.5 厘米的肉条。 +- 根据上面的计算公式加入盐,十三香、胡椒粉、味精、鸡精、花椒碎、花椒粒、生抽。 +- 倒入前面制作好的葱姜水 +- 抓匀并且充分揉制 10 分钟,直至肉吸收所有水分并且变得粘手。 +- 封上保鲜膜放冷藏室静置 30 分钟。 + +### 猪肉裹粉 + +- 将面粉、红薯粉倒入腌制好的肉中,加入鸡蛋清。 +- 充分揉制 15 分钟。 + +### 初炸定形状 + +- 锅中倒入植物油,根据锅大小控制油量,油面高度 3 厘米以上。 +- 大火将温加热至 150° 后,转小火保持温度。 +- 将裹好粉的肉条用筷子夹入油锅中,捋成自己喜欢的形状,炸 3~5 分钟定型。目测颜色微黄,用锅铲翻动感受倒略微有些硬了就可以。具体时间受肉块大小、油温、裹粉程度影响。 +- 捞出沥油。 + +tips: 如果对时间没把握可以稍微多炸一下,否则肉会带一点生味。 没有经验可以一条一条的下锅,防止粘连。 + +### 复炸出成品 + +- 将油温升至 180° 放入初炸好的肉条,炸至金黄色即可捞出。 + +## 附加内容 + +- 裹粉一定要把红薯粉揉散,不要有干的颗粒裹在里面,否则会炸!!! +- 如果肉太多吃不完,可以只炸一遍然后放冰箱。后面再吃的时候拿出来复炸,口感基本没影响。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/尖叫牛蛙/尖叫牛蛙.jpg b/data/C8/cook/dishes/meat_dish/尖叫牛蛙/尖叫牛蛙.jpg new file mode 100644 index 0000000..06a6341 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/尖叫牛蛙/尖叫牛蛙.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a58999998f3ba769f7ed696b8a41bbcfc34d0b131181301cc9148edfe85e96e +size 47888 diff --git a/data/C8/cook/dishes/meat_dish/尖叫牛蛙/尖叫牛蛙.md b/data/C8/cook/dishes/meat_dish/尖叫牛蛙/尖叫牛蛙.md new file mode 100644 index 0000000..311d7cd --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/尖叫牛蛙/尖叫牛蛙.md @@ -0,0 +1,66 @@ +# 尖叫牛蛙的做法 + +![示例菜成品](./尖叫牛蛙.jpg) + +尖叫牛蛙是一道容易完成的菜。一般初学者只需要 1-2 小时即可完成。该菜品味道鲜美之外,还具有开胃功效,非常适宜食欲不佳的时候做,老少皆宜。(能吃辣最好) + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 牛蛙肉 +- 泡姜 +- 泡椒 +- 野山椒(也可以用干红辣椒替代) +- 青红辣椒 +- 大蒜 +- 豆瓣酱(推荐郫县豆瓣) +- 盐巴 +- 胡椒粉 +- 生粉(干淀粉也可) +- 啤酒(推荐雪花) +- 料酒 +- 藤椒油(可选) +- 猪油(可选) +- 葱花 + +## 计算 + +1 份 + +每份: + +- 牛蛙肉块 800g (买 3 斤活蛙,建议挑小个头的,肉质鲜嫩) +- 泡姜 20-30 克 (看个人口味,喜欢重口一点可以多放) +- 泡椒 5-10 克 (看个人吃辣的承受能力,不能吃辣的建议减半为 2.5 克,微微辣) +- 野山椒 10 克 +- 青红辣椒 20 克 +- 大蒜 30-50 克 (可以根据口味偏好调整,最好不低于 30 克) +- 豆瓣酱 20-30 克 (重口选 30,想吃清淡点 20 克。PS 这菜不可能太清淡,哈哈) +- 盐巴 15 克 +- 胡椒粉 10 克 +- 啤酒 400-500ml +- 料酒 10ml +- 藤椒油 5-10ml +- 生粉 30 克 (干淀粉可以平替) +- 猪油 20ml(没有猪油也可,用食用油替代) +- 食用油 200ml +- 葱花 5 克 + +## 操作 + +- 牛蛙肉洗净后控干水分,加入 10 克以上的盐巴和 50ml 以上的啤酒,用手抓 5 分钟,去除牛蛙肉的腥味 +- 然后对着清水冲洗,直至不再流出血水和杂质,控干水分,放到合适的器皿中,准备腌制 +- 加入 5 克盐,30 克生粉,10ml 料酒,5 克胡椒粉,用手抓均匀,腌制 5-10 分钟 +- 将泡姜 泡椒 野山椒 切丝或者片(根据自己刀工选择),青红辣椒切成圈圈 大蒜拨开即可 +- 起锅烧热,加入 200ml 食用油(锅底比较平的可以再加 100ml),烧至 6 成油温(有小气泡出现),将腌制好的牛蛙倒入,快速过油炸制,10 秒钟后捞出(不能超时太多,否则会导致蛙肉老柴) +- 捞出蛙肉后,控油,并将锅中的热油倒出到碗中,保留 30ml,加入 20ml 猪油(如果没有,则在锅中保留总共 50ml 食用油) +- 待油温 6 成热,加入泡姜、泡椒、野山椒、大蒜,超出香味,加入豆瓣酱 20 克,中火翻炒至出红油(时间控制在 30 秒),倒入 400ml 啤酒, +- 然后倒入炸过的牛蛙肉,用勺子推着翻,不要用力搅拌,加入 5 克胡椒粉,加入 5ml 藤椒油,中火慢焖 3 分钟 +- 加大火力,大火收汁半分钟,加入青红辣椒圈,再煮 10 秒准备起锅 +- 盛到盆里,撒上葱花,可以开动了! + +## 附加内容 + +- 控干水分的时候可以选择漏勺按压 +- 生粉抓揉的时候要均匀覆盖蛙肉 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/尖椒炒牛肉.md b/data/C8/cook/dishes/meat_dish/尖椒炒牛肉.md new file mode 100644 index 0000000..a7f9b10 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/尖椒炒牛肉.md @@ -0,0 +1,52 @@ +# 尖椒炒牛肉的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 牛肉 +* 葱、姜、蒜 +* 尖椒 +* 酱油 +* 盐 +* 糖 + +## 计算 + +* 牛肉用量为 250 g/人 +* 葱的用量为 0.5 根/人 +* 姜的用量为 1 个/人 +* 盐的用量为 3 g/人 +* 糖的用量为 1.5 g/人 +* 酱油的用量为 9 ml/人 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 配菜处理 + +* 蒜剁成蒜泥 +* 葱切段 +* 姜切成姜片 +* 尖椒切成段 + +### 牛肉的预处理 + +* 牛肉放入碗中 +* 加姜、盐、酱油、糖进行腌制 30-40 分钟 +* 腌制完姜可以去掉 + +### 炒熟 + +* 冷油下锅,待油变热至偶有气泡 +* 加入蒜泥 +* 蒜泥变金黄后加入尖椒 +* 待尖椒表皮微皱,加入腌制好的牛肉翻炒 +* 翻炒变熟之前加入葱,继续翻炒 +* 翻炒至牛肉变熟,关火出锅 + +## 附加内容 + +* 腌制可以加入小苏打使牛肉变嫩,牛肉苏打比例为 500g:3g。 +* 腌制的时候姜片可用料酒代替,料酒的用量为 3 g/人 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/山西过油肉.md b/data/C8/cook/dishes/meat_dish/山西过油肉.md new file mode 100644 index 0000000..450b1ed --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/山西过油肉.md @@ -0,0 +1,53 @@ +# 山西过油肉的做法 + +过油肉是山西传统名菜,有很多年历史,基本家家都会做。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 猪里脊 +- 蒜苔 +- 盐 +- 酱油 +- 葱姜蒜 +- 鸡蛋 +- 淀粉 +- 食用油 +- 木耳 +- 葱头 +- 料酒 +- 陈醋 +- 花椒粉 +- 鸡精 + +## 计算 + +本人饭量较大,这是本人一人量 + +- 猪里脊 150 g +- 蒜苔 6 根 +- 食用油 300ml +- 葱姜蒜 50g +- 生抽 20ml +- 食盐 10g +- 鸡蛋 1 个 +- 淀粉 10g +- 木耳 20g +- 葱头 100g +- 其他调料 20g + +## 操作 + +- 木耳提前泡发好,如果着急可以用热水泡发。 +- 猪里脊切片放入碗中,加 20ml 生抽、料酒、花椒粉,打入一个鸡蛋,拿自己的小手搅拌均匀,加入淀粉(建议红薯淀粉)拌匀,倒入 300ml 食用油封浆,腌制 15 分钟。 +- 蒜苔切段大约 3cm,葱头切菱形块备用。 +- 起锅烧油油要多一点,油温五成热,下入腌制好的肉片,将肉片打散,捞出控油备用。 +- 将锅中多余油倒出,留 10ml 油炒菜,油温七成热 +- 下入葱姜蒜爆香,先下蒜苔炒至断生,再下入木耳葱头,加入生抽,花椒粉,翻炒几下将之前炸好的肉片下入翻炒 +- 加 10g 的盐,起锅前加 10ml 的醋和鸡精,起锅装盘。 + +## 附加内容 + +- 炸肉片时,表面微焦即可,注意控制火候。 +- 起锅前也可以打个薄薄的水淀粉,口感更佳。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/倒入番茄蓉.png b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/倒入番茄蓉.png new file mode 100644 index 0000000..2b7b0e5 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/倒入番茄蓉.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbdbc391c9fd912de49b4d86cf0c8bf8476b48f7db2b357b6136c488b7c95cd9 +size 288928 diff --git a/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/巴基斯坦牛肉咖喱.md b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/巴基斯坦牛肉咖喱.md new file mode 100644 index 0000000..e7a968d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/巴基斯坦牛肉咖喱.md @@ -0,0 +1,59 @@ +# 巴基斯坦牛肉咖喱的做法 + +![巴基斯坦牛肉咖喱成品](./巴基斯坦牛肉咖喱.png) + +Achar gosht(巴基斯坦牛肉咖喱)是一道来自巴基斯坦的特色咖喱菜品。这道菜融合了咖喱的香浓和牛肉的软糯口感,风味独特,偏辣口。它富含优质蛋白质和多种维生素,营养价值丰富。制作过程需要 2.5 小时,步骤并不复杂,是一道适合在周末慢慢烹饪的美味佳肴。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 普通的炒锅 +- 电饭煲/电炖锅 +- Masala 粉(品牌可选 Shan) +- 牛肉 +- 番茄 +- 螺丝椒 +- 原味酸奶 +- 蒜粉 +- 姜粉 + +## 计算 + +这里以 1kg 牛肉的所需要的配菜量作为标的,可以通过它计算出不同菜量。1kg 牛肉做出的咖喱大概够 5 个人吃。 + +1kg 牛肉所需要的配菜量: + +- 番茄🍅 4 个 +- 螺丝椒 2 个(大个的) +- 原味酸奶 1 盒 +- Masala 粉一包 50g +- 蒜粉 5g +- 姜粉 5g + +## 操作 + +- 全部螺丝椒切成段状,备用 +- 全部番茄打成番茄蓉,备用 +![番茄蓉](./番茄蓉.png) +- 牛肉切成 2cm 的小块,洗净备用 +![牛肉](./牛肉.png) +- 炒锅中倒入一层油(用来防止番茄蓉沸腾蒸发) +![油](./油.png) +- 倒入番茄蓉,持续搅拌 2-3 分钟,等待它越变越红 +![倒入番茄蓉](./倒入番茄蓉.png) +![红](./红.png) +- 加入 5g 蒜粉,5g 姜粉和 1 包 50g 的 Masala 粉,搅拌均匀 +- 加入牛肉和螺丝椒段,搅拌均匀 +- 加入 1 盒酸奶(为了让整个酱汁变得粘稠),搅拌均匀 +- 将整锅材料转移到电饭煲/电炖锅,并加入 250 ml 的水,开启炖肉/慢炖档,设定时间 2-3 个小时 +- 等待完成,开锅检查牛肉软糯,就可以吃了 +![巴基斯坦牛肉咖喱成品](./巴基斯坦牛肉咖喱.png) + +## 附加内容 + +这道菜是从一个巴基斯坦的朋友那里偷师而来,特地整理了笔记,绝对正宗。 + +通常配以 烙饼(roti)、馕(naan) 或 米饭 食用。 + +如果想做 Chicken karahi 流程几乎是一样的,除了是先用油和各种花椒胡椒煎鸡肉变黄。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/巴基斯坦牛肉咖喱.png b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/巴基斯坦牛肉咖喱.png new file mode 100644 index 0000000..8e320e0 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/巴基斯坦牛肉咖喱.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7fadd63cbf025ae3203dcfa080af288c14be04041908110381d94aaa86ef5373 +size 222895 diff --git a/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/油.png b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/油.png new file mode 100644 index 0000000..6ec6686 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/油.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f144d6f42924ad3db89e7b232d3b40a169f3958662b62cdd773921180535ba2 +size 337608 diff --git a/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/牛肉.png b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/牛肉.png new file mode 100644 index 0000000..f216c6b --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/牛肉.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2af6933f6b227b53c4d4137f981d3b00c1fed581b2748dc70850e95913795fc6 +size 210428 diff --git a/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/番茄蓉.png b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/番茄蓉.png new file mode 100644 index 0000000..4910eb3 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/番茄蓉.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:568746a99c13a3378edcc3aed47175fcfe62f49fa463dcf034448b425392fab6 +size 133202 diff --git a/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/红.png b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/红.png new file mode 100644 index 0000000..a7f86d4 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/巴基斯坦牛肉咖喱/红.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf339b2f4fc5283e08650e6b79d82e7836367eb5a4f8dd0270c1c1908778c48e +size 548188 diff --git a/data/C8/cook/dishes/meat_dish/带把肘子.md b/data/C8/cook/dishes/meat_dish/带把肘子.md new file mode 100644 index 0000000..13b4223 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/带把肘子.md @@ -0,0 +1,58 @@ +# 带把肘子的做法 + +肘肉酥烂不腻,肘皮胶粘,香醇味美,辅佐以葱段,甜面酱,别有一番风味,因脚爪形似把柄,故得其名,是陕西省大荔县名菜。营养价值丰富,但制作难度较高。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +### 原料 + +- 带脚、爪猪前肘 +- 红豆腐乳 +- 甜面酱 +- 精盐 +- 红酱油 +- 白酱油 +- 料酒 +- 蒜片 +- 姜末 +- 八角 +- 桂皮 +- 葱 + +### 工具 + +- 小斧头(砸断骨头用) +- 消毒纱布(能盖住肘子) + +## 计算 + +每份:三人量 + +- 带脚、爪猪前肘: 一个(大约二斤五两 = 1250 克) +- 红豆腐乳: 1 块 = 10 克 +- 甜面酱: 150 克 +- 精盐: 15 克 +- 红酱油: 35 克 +- 白酱油: 25 克 +- 料酒: 25 克 +- 蒜片: 50 克 +- 姜末: 10 克 +- 八角: 3 个 +- 桂皮: 5 克 +- 葱: 200 克 + +## 操作 + +- 将肘子刮洗干净,肘头朝外、肘把(脚爪)朝里、肘皮朝下放在案板上。 +- 用刀在正中由肘头向肘把沿着腿骨将皮剖开,剔去腿骨两边的肉(三面离肉),底部骨与肉相连,使骨头露出,然后将两节腿骨由中间用刀背(还是用斧头吧)砸断。 +- 肘子放入煮锅煮至七成熟捞出(外观正常,内部淡红色),用干净抹布擦干水,趁热用红酱油涂抹肉皮。 +- 取蒸锅一个,锅底放入八角、桂皮,先将肘把的关节处用手掰断,不伤外皮,再将肘皮朝下装进蒸锅内,装锅时根据肘子体型,将肘把贴住锅边窝着装进锅内,成为圆形。 +- 撒入精盐,用消过毒的干净纱布盖在肉上,再将甜面酱(50 克)、葱(75 克)、红豆腐乳、红酱油、白酱油、姜、蒜等在纱布上抹开,用旺火蒸大约三小时(以蒸烂为准)。 +- 蒸完取出,揭去纱布,扣入盘中,拣去八角,上桌时另带葱段和甜面酱小碟(或将甜面酱抹到肘面上,另带葱段小碟亦可)。 + +## 附加内容 + +- 肘子七成熟要根据实际情况判断,有条件可询问家中长辈。 +- 蒸锅下半放水,上半放肘子,蒸时及时加水防止蒸干。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/干煸仔鸡/干煸仔鸡.md b/data/C8/cook/dishes/meat_dish/干煸仔鸡/干煸仔鸡.md new file mode 100644 index 0000000..21ec25e --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/干煸仔鸡/干煸仔鸡.md @@ -0,0 +1,60 @@ +# 干煸仔鸡的做法 + +![干煸仔鸡成品](./干煸仔鸡成品.jpg) + +干煸仔鸡是一道甜辣口味的川菜,是北京大学食堂赵春月厨师长研发的美食,广受师生喜爱。赵厨师长已将菜谱公开,方便大家自己动手制作,疫情居家下饭必备! + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 鸡腿 +- 土豆 +- 青椒 +- 大蒜 +- 盐 +- 胡椒粉 +- 生抽 +- 老抽 +- 料酒 +- 淀粉 +- 郫县红油豆瓣酱(注意区分,不是那种棕黄色的豆瓣酱) +- 白糖 +- 花椒碎 + +## 计算 + +1-2 人份: + +- 鸡腿肉 400g +- 土豆 200g +- 青椒 60g +- 蒜瓣 10g +- 盐 3g +- 鸡精 3g (可选) +- 胡椒粉 2g +- 生抽 5g +- 老抽 2g +- 料酒 5g +- 淀粉 20g +- 郫县红油豆瓣酱 40g +- 白糖 30g +- 花椒碎 2g + +## 操作 + +- 鸡腿去骨(如使用鸡腿排可忽略此步骤),鸡腿肉用刀背砸一砸,切成 2cm 的块。 +- 鸡腿肉中加入盐、鸡精(可选)、胡椒粉、生抽、老抽、料酒,抓拌至粘手时加入淀粉拌匀,加入食用油防止粘连,腌制 30 分钟。 +- 土豆去皮,切成 2cm 的块,沸水煮 5 分钟后捞出,控干水分,防止油炸时爆锅。 +- 青椒去籽,切成 2cm 小片,放在笊篱中备用。 +- 锅中加入宽油(根据锅的形状,能没过食材即可),油温烧至 180℃ 时,下入土豆块炸 3 分钟后捞出。 +- 待油温再次升高到 180℃时,下入鸡块炸 2 分钟后捞出。 +- 待油温再次升高到 180℃时,下入鸡块复炸 1 分钟后捞出。 +- 待油温再次升高到 180℃时,下入土豆块复炸 1 分钟后,将锅中的油和土豆块经过笊篱过滤倒出,让笊篱上的青椒片断生。 +- 锅中加入 5ml 食用油,小火煸炒蒜瓣至发黄,下入红油豆瓣酱煸炒出香,下入白糖炒融化,下入花椒碎,加 40ml 清水,不停搅拌至酱汁粘稠。 +- 下入炸好的鸡块、土豆块、青椒片,搅拌均匀后出锅。 + +## 附加内容 + +- 不舍得使用宽油油炸的话,可改用更少的油煎鸡块和土豆块。会增长用时,部分影响口感,但不会影响总体味道。 +- 参考资料:[北大餐饮中心官方资讯](https://mp.weixin.qq.com/s/gd7F1bezTyd3OQsUVVur1w) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/干煸仔鸡/干煸仔鸡成品.jpg b/data/C8/cook/dishes/meat_dish/干煸仔鸡/干煸仔鸡成品.jpg new file mode 100644 index 0000000..274604f --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/干煸仔鸡/干煸仔鸡成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70bf5cffba89198124688d0065273ebe6e24023cb047662145c98d0bc53ff144 +size 803109 diff --git a/data/C8/cook/dishes/meat_dish/广式萝卜牛腩/广式萝卜牛腩.md b/data/C8/cook/dishes/meat_dish/广式萝卜牛腩/广式萝卜牛腩.md new file mode 100644 index 0000000..1927212 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/广式萝卜牛腩/广式萝卜牛腩.md @@ -0,0 +1,63 @@ +# 广式萝卜牛腩的做法 + +![广式萝卜牛腩](./广式萝卜牛腩.webp) + +广式萝卜牛腩营养丰富,味道鲜美,汤汁浓郁、孩子食欲好了,成绩也好了。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 牛腩 +- 白萝卜 +- 姜片 +- 蒜瓣 +- 葱 +- 八角 +- 桂皮 +- 干辣椒 +- 香叶 +- 南乳 +- 柱侯酱 +- 蚝油 +- 酱油 +- 冰糖 +- 盐 +- 老抽 + +## 计算 + +一份正好够 3-4 人吃。 + +- 牛腩 500g +- 白萝卜 1 根 +- 姜片 8 片 +- 蒜瓣 5 片 +- 葱结 一把 +- 八角 2 片 +- 桂皮 1 小块 +- 干辣椒 2 个 +- 香叶 2 片 +- 南乳 1 块 +- 柱侯酱 30g +- 蚝油 15g +- 酱油 15g +- 冰糖 10g +- 盐 5g +- 老抽 15g + +## 操作 + +### 开始制作 + +* 萝卜滚到切块备用 +* 牛腩整块焯水,加入 2 片姜和一把葱结,等水开之后煮 5-10 分钟,然后捞出切件 +* 将牛腩切块,切成自己喜欢的大小(牛腩焯过水,待会儿焖的时候基本不会缩水了,大块的会焖相对就一点的时间) +* 准备焖牛腩的酱料,将南乳、柱侯酱、酱油、蚝油、糖、盐按上面的量调和(冰糖刚刚没了换成了白糖) +* 热锅下油,将姜蒜爆香,放入牛腩,炒至干身,加入调好的酱料,炒香,如果喜欢色泽浓一点的可以加一点老抽润色一下 +* 调料充分混合之后倒入热水 +* 将牛腩换到汤锅中,放入桂皮、八角、香叶和干辣椒,焖大概 2 个小时 +* 牛腩焖到半软之后加入白萝卜继续焖 30 分钟 +* 等到萝卜焖软之后就完成,一锅浓香的萝卜牛腩就完成了 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/广式萝卜牛腩/广式萝卜牛腩.webp b/data/C8/cook/dishes/meat_dish/广式萝卜牛腩/广式萝卜牛腩.webp new file mode 100644 index 0000000..54602fa --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/广式萝卜牛腩/广式萝卜牛腩.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f81095211422c6fff1088cca236cc1330671ba4a2d5b91a2170bfb6801e3729 +size 35284 diff --git a/data/C8/cook/dishes/meat_dish/徽派红烧肉/1.jpeg b/data/C8/cook/dishes/meat_dish/徽派红烧肉/1.jpeg new file mode 100644 index 0000000..65bc9c5 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/徽派红烧肉/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd6e9ed84fab1e84241dcc994c555a700119ee936e9c39f424387dcce26f1011 +size 125686 diff --git a/data/C8/cook/dishes/meat_dish/徽派红烧肉/2.jpeg b/data/C8/cook/dishes/meat_dish/徽派红烧肉/2.jpeg new file mode 100644 index 0000000..9b62de9 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/徽派红烧肉/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa35b7062fc2fe44ec18471caf479a822ed0b6f6b30b9c6913cfeeb0f4312a19 +size 154580 diff --git a/data/C8/cook/dishes/meat_dish/徽派红烧肉/徽派红烧肉.md b/data/C8/cook/dishes/meat_dish/徽派红烧肉/徽派红烧肉.md new file mode 100644 index 0000000..404c09b --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/徽派红烧肉/徽派红烧肉.md @@ -0,0 +1,56 @@ +# 徽派红烧肉的做法 + +徽式红烧肉是一道由五花肉等食材制成的菜肴。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 五花肉 +* 白砂糖 +* 食用油 +* 生抽 +* 蚝油 +* 老抽 +* 姜片 +* 蒜头 +* 料酒 +* 葱 +* 五香粉 +* 盐 + +## 计算 + +每份: + +* 五花肉 300 g +* 白砂糖 100 g +* 食用油 200 g +* 生抽 10 ml +* 蚝油 5 ml +* 老抽 5 ml +* 姜片 2 片 +* 蒜头 3 颗 +* 料酒 100 ml +* 葱 1 根 +* 五香粉 10 g +* 盐 10 g + +## 操作 + +* 五花肉切块,每块 2-3 cm 大小 +* 锅中加入 150 ml 食用油,倒入五花肉,煎炸 2 分钟 后,加入盐,翻炒五花肉,2 分钟 后出锅 +* 锅中加入 50 ml 食用油,倒入白砂糖,翻炒到咖啡色 +* 倒入五花肉,翻炒 30 S ,加入姜片、蒜头后翻炒 30 S +* 加入料酒,五香粉、葱,加入水没过五花肉,盖上锅盖煮 10 分钟 +* 加入生抽、老抽、蚝油,中火煮 20 分钟 +* 开锅,大火烧汁,端盘 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) + +## 附加内容 + +* 葱是整根,不需要切碎 +* 步骤二加盐的目的是锁住五花肉的油脂 +* 制作过程,用部分五花肉做了水煮处理,跟未处理的一起做后续制作,发现未水煮的肉质更 Q 弹 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/意式烤鸡.md b/data/C8/cook/dishes/meat_dish/意式烤鸡.md new file mode 100644 index 0000000..4452df2 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/意式烤鸡.md @@ -0,0 +1,48 @@ +# 意式烤鸡的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡腿肉 +- 盐 +- 黑胡椒 +- 橄榄油 +- 蒜 +- 柠檬汁 +- 欧芹 + +## 计算 + +- 鸡腿肉用量通常来说为 1-2 个/人 +- 盐用量为 2 g/人 +- 黑胡椒用量为 0.5 g/人 +- 橄榄油用量为 5 ml/人 +- 蒜用量为 1 瓣/人 +- 柠檬汁用量为 5ml/人 +- 欧芹用量为 1 根/人 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 鸡肉的预处理 + +- 鸡腿肉涂上盐、黑胡椒、橄榄油和蒜末 +- 放入预热至 180 度的烤箱中,烤 30-40 分钟或至熟 + +### 佐料的准备 + +- 欧芹切成碎末备用 +- 柠檬挤出汁备用 + +### 烤制 + +- 烤好的鸡肉取出,淋上柠檬汁 +- 撒上欧芹碎即可 + +## 附加内容 + +- 烤制时可以将鸡肉淋上蜂蜜或其他烤肉酱提升口感 +- 烤箱预热至 180 度,烤制时间根据鸡肉的大小和厚度而定,需确保鸡肉熟透 +- 鸡肉必须全熟才能吃,吃未全熟的鸡肉可能会导致食物中毒和感染细菌,如沙门氏菌和福氏杆菌等。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/新疆大盘鸡/大盘鸡.jpeg b/data/C8/cook/dishes/meat_dish/新疆大盘鸡/大盘鸡.jpeg new file mode 100644 index 0000000..53a7318 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/新疆大盘鸡/大盘鸡.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a709121ec499b3f09fc24e7b7b5c21b35724657e88ac458780332d097bf33767 +size 190378 diff --git a/data/C8/cook/dishes/meat_dish/新疆大盘鸡/大盘鸡皮带面.jpeg b/data/C8/cook/dishes/meat_dish/新疆大盘鸡/大盘鸡皮带面.jpeg new file mode 100644 index 0000000..4f89bf2 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/新疆大盘鸡/大盘鸡皮带面.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1007f138f0293365394e64a1ee746a066fd58acc1bb1ee4f0f2549054ea31e49 +size 215170 diff --git a/data/C8/cook/dishes/meat_dish/新疆大盘鸡/新疆大盘鸡.md b/data/C8/cook/dishes/meat_dish/新疆大盘鸡/新疆大盘鸡.md new file mode 100644 index 0000000..cf21573 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/新疆大盘鸡/新疆大盘鸡.md @@ -0,0 +1,43 @@ +# 新疆大盘鸡的做法 + +![大盘鸡](./大盘鸡.jpeg) + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 花椒,香叶,香果,干线椒,大蒜,大葱 +- 油,盐,生抽,蚝油,料酒(可拿啤酒),白糖 +- 鸡肉(鸡腿肉最好),土豆,菜椒和甜椒(可以不用,加上配色好看) + +## 计算 + +2 人食用 + +- 两个火枪腿的鸡肉(这大约是 1kg ) +- 土豆 2 个适中大小:750g +- 大葱 100g +- 菜椒甜椒各一个,各 50g +- 白糖 20g +- 干线椒 5 个 +- 大蒜 4 瓣 +- 油 50g + +## 操作 + +- 肉先剁好,块状,用清水+盐浸泡 5 分钟,去除血水,去腥,然后空干水 +- 葱蒜辣椒土豆等洗干净,土豆削皮 +- 葱白切长段,长度 4cm 一段,菜椒和线椒切块状 +- 土豆切成滚刀土豆,即切一刀动滚动一下,一块土豆大概有 4cm*4cm 大小即可 +- 炒糖色:先将油加入锅中,然后将白砂糖放入,用锅铲来回搅拌,将糖炒化,然后炒出焦黄色,此时将空干水的鸡肉倒入锅中翻炒,进行上色 +- 放入花椒,香叶,香果,干线椒等进行翻炒 +- 放入 5g 盐,生抽 7ml,蚝油 10g ,料酒 100g,倒入 1 升清水,料酒可以用啤酒代替 +- 调至中火,将水烧开,调制中小火慢炖入味 +- 当水收至鸡肉即将露出时,将土豆放在锅表面:注意不要翻动土豆,就盖在表面,不然翻到下面容易粘锅,继续盖锅盖炖,炖一会后将大葱,菜椒和甜椒放入,继续炖。 +- 炖到汁收的差不多时可以进行翻面,将土豆与汤汁相吸,最后关火盛出。 + +**另:此做法可以吃面,买粗面剂子,将粗面剂子压扁,然后用手拉成宽面,一定要是宽面,下好后可以放入到大盘鸡中,与汤汁搅拌味道极佳!** + +![大盘鸡皮带面](./大盘鸡皮带面.jpeg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/无骨鸡爪/无骨鸡爪.jpg b/data/C8/cook/dishes/meat_dish/无骨鸡爪/无骨鸡爪.jpg new file mode 100644 index 0000000..1f9d061 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/无骨鸡爪/无骨鸡爪.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a2cf3160bfd77b9a5763f735e79e46fd6882d5fdb901c4627026fac6c3bff2a +size 86781 diff --git a/data/C8/cook/dishes/meat_dish/无骨鸡爪/无骨鸡爪.md b/data/C8/cook/dishes/meat_dish/无骨鸡爪/无骨鸡爪.md new file mode 100644 index 0000000..28f43b6 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/无骨鸡爪/无骨鸡爪.md @@ -0,0 +1,87 @@ +# 无骨鸡爪的做法 + +![无骨鸡爪成品](./无骨鸡爪.jpg) +**图片里的颜色比较浅,家里人爱吃酱油少的** + +这是一道做法简单但消耗体力和耐力的无骨鸡爪,酸辣开胃,Q 弹爽口,第一次做的话总耗时 8 个小时 15 分钟。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 鸡爪 +- 姜 +- 料酒 +- 大葱 +- 大蒜 +- 小米辣 +- 洋葱 +- 生抽 +- 蚝油 +- 黑醋(推荐陈醋) +- 白糖 +- 盐 +- 花椒油 +- 香菜 +- 柠檬 + +## 计算 + +一份正好够 2-3 个人吃。 + +- 鸡爪 1kg +- 姜 4 片 +- 料酒 65g +- 大葱 3 段(5cm 一段) +- 大蒜 10 瓣 +- 小米辣 4 个少辣,6 个中辣,12 个大辣(推荐大辣) +- 洋葱 (半个) +- 生抽 75g = 15g * 5 +- 蚝油 30g = 15g * 2 +- 黑醋(推荐陈醋) 50g +- 白糖 10g +- 盐 3g +- 花椒油 10ml +- 香菜 3 颗 +- 柠檬 2 颗(以 1 颗为单位来调整酸度) + +## 操作 + +### 鸡爪处理 + +- 用剪刀 / 刀 把鸡爪上的指甲的部分全部剪掉 **包括指甲下面的肉和骨头,让它一点指甲都不剩** +- 用水把他们洗干净,放一边 +- 把`鸡爪`放入大锅中,准备去腥味 +- `大葱`,`料酒`,`姜` 全放进去 +- 加水没过`鸡爪` +- 大火煮开 **中途可以把浮末捞起来** +- 水开**100度,沸腾**后等 10 分钟 +- 关火,捞出来,把水沥干,洗干净,放入盆里 + +### 去骨 + +这一步可以省略,此步骤大约花费 2 小时 + +- 放入冰箱,**冷冻层** 20 分钟 +- 把全部放入不是冷冻层的冰箱,然后分批**10个一批**拿出来去骨 +- 从手指(鸡爪的)最前端开始,每只手指都要用刀划开**划到它的手背部分** +- 再从手背部用刀分划开至整个手臂 +- 把每只手指关节处都掰一掰**按手指出声音时那种** +- 按着它的手指最前端,往里推,每只手指都一样,先推到中间手掌手背部分 +- 每只手指皮脱离后,从手掌开始往手臂部分推直到整个脱下来了 +- 放入碗中,备用 + +### 调配腌料 + +- `小米辣` 切均匀小颗 +- `大蒜`,`洋葱`,`香菜`切碎 +- `柠檬`对半切开,把柠檬汁挤入鸡爪的容器里 +- 把`全部`调料倒入装鸡爪的容器,`小米辣`,`大蒜`,`洋葱`和`香菜`也放进去 +- 抓拌均匀 +- 放入冰箱一个晚上(6 个小时) +- 调配好后全部放入准备好的鸡爪 + +## 附加内容 + +- 操作时,需要注意观察沸腾的水位线,如发现低于 3/4 的食材应加热水至没过食材。 +- 鸡爪去骨教程 :[bili_89324373958](https://www.bilibili.com/video/BV1t44y117D8?share_source=copy_web) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/杀猪菜.md b/data/C8/cook/dishes/meat_dish/杀猪菜.md new file mode 100644 index 0000000..50270a1 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/杀猪菜.md @@ -0,0 +1,54 @@ +# 杀猪菜的做法 + +杀猪菜的做法 (荤菜) + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 血肠 +- 酸菜 +- 排骨 +- 料酒 +- 辣椒 +- 香叶 +- 八角 +- 葱结 +- 香油 +- 菜籽油 +- 蒜 + +## 计算 + +这道菜适合 2-3 人一起吃。这道菜每份应该加入的材料有: + +- 血肠 200 克 +- 酸菜 500 克 +- 排骨 400 克 +- 料酒 10 克 +- 蒜瓣 5 个 +- 姜粉 5 克 +- 干辣椒 5 个 +- 香叶 2 片 +- 八角 1 个 +- 葱结 1 个 +- 香油 10 克 +- 菜籽油 10 克 +- 盐 5 克 +- 蘸料:辣椒油 5 克、生抽 10 克、蒜蓉 5 克、香油 2 克。 + +## 操作 + +- 血肠用牙签多扎一些小孔,然后放水中小火煮十分钟,不要让水烧开,保持 80 度,否则血肠非常容易爆开。 +- 煮好的血肠切块备用。 +- 排骨放料酒焯水,控干水分备用。 +- 锅内放入菜籽油,放蒜瓣,干辣椒,姜粉炒香。 +- 放入排骨翻炒至表面金黄。 +- 酸菜洗净拧干水分,放入锅中,加入香油翻炒,香油可以更好的去除酸味而且让酸菜更香,大火翻炒二分钟。 +- 加入 600 毫升热水。 +- 转入电压力锅,加香叶,八角,葱结,盐。 +- 浓香模式压 40 分钟。 +- 到时间后放气开盖。加入血肠和枸杞,盖上锅盖焖二分钟即可,血肠是熟的,不需再加热。 +- 倒入盆中,按照上表调制蘸料,即可开吃。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/枝竹羊腩煲/枝竹羊腩煲.md b/data/C8/cook/dishes/meat_dish/枝竹羊腩煲/枝竹羊腩煲.md new file mode 100644 index 0000000..19c6c24 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/枝竹羊腩煲/枝竹羊腩煲.md @@ -0,0 +1,76 @@ +# 枝竹羊腩煲的做法 + +枝竹羊腩煲是一份老少皆宜,适合冬季暖胃的美食。 此道菜肥而不腻,搭配米饭堪称一绝。一般初学者需 2 个半小时即可完成。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 羊腩 +- 腐竹 +- 柱侯酱 +- 腐乳 +- 南乳 +- 老抽 +- 料酒 +- 蚝油 +- 清水 +- 冰糖 +- 葱段 +- 姜片 +- 香菇 +- 洋葱或红葱头 +- 蒜瓣 +- 香叶 +- 八角 +- 桂皮 +- 其余配菜例如马蹄、土豆或者萝卜可依据个人喜好自行添加 + +## 计算 + +每份: + +- 羊腩 500g +- 炸腐竹 30g-50g +- 柱侯酱 30g +- 腐乳 40g +- 南乳 35g +- 老抽 5ml +- 辣椒油 5ml +- 清水 500ml +- 冰糖 20g +- 砂糖 10g +- 小葱 5 根 +- 姜片 6-8 片 +- 香菇 7-8 个 +- 洋葱 1 个或红葱头 4 - 5 个 +- 蒜瓣 7-8 瓣 +- 香叶 1 片 +- 八角 4-5 个 +- 桂皮 10g + +## 操作 + +- 准备工作: 香菇提前浸泡 2 - 3 小时至变软。腐竹提前浸泡 30 分钟至变软 +- 准备酱汁 1: 南乳、柱侯酱、20g 腐乳、老抽放入同个小碗中搅拌均匀 +- 准备酱汁 2: 20g 腐乳、砂糖、辣椒油放入同个小碗搅拌均匀 +- 泡好的香菇去除根部 +- 泡好的腐竹切成 5cm 的小段,挤干水分 +- 洋葱去皮切丝。也可以用去皮红葱头进行替代,口味更佳。 +- 小葱切成大约 5cm 的葱段 +- 羊腩冷水下锅,放入 2 - 3 片姜片,倒入凉水,大火煮至水滚后关火 +- 捞出羊腩,放入准备好的冷水盆中放凉,使其更有嚼劲 +- 锅烧热后放入冷油,放入 4 - 5 片姜片、洋葱/红葱头、葱白段、7 - 8 瓣蒜瓣进行爆香 +- 放入冷却好的羊腩,用筷子搅拌大约 2 - 5 分钟直至出现金黄色 +- 放入调好的酱汁 1 ,翻炒大约 2 分钟至颜色均匀 +- 倒入清水至刚好没过食材 +- 放入香菇、冰糖、香叶、八角、桂皮 +- 加盖转小火炖 90 分钟 +- 开盖加入腐竹,加盖转中火煮 20 分钟 +- 开盖加入酱汁 2 搅拌均匀 +- 关火,出锅前加入葱绿段或香菜 + +## 附加内容 + +- 此菜属于粤菜,正宗做法多会添加马蹄。考虑到萝卜青菜各有所爱,也可根据个人口味替换成土豆、萝卜等其他食材 +- 参考资料:[枝竹羊腩煲 Lamb Stew with Bean Curd Sheet [by 點Cook Guide]](https://www.youtube.com/watch?v=ThVDpVoToDQ) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/土豆切片.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/土豆切片.jpeg new file mode 100644 index 0000000..32a3ffc --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/土豆切片.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cab6a7a02236b08c28de93672dd78591112a21acffc9bf1c61e61d36dfe10f70 +size 598684 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/柱候牛腩.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/柱候牛腩.jpeg new file mode 100644 index 0000000..4dde3e1 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/柱候牛腩.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34868b064fc4fbba237ab8807c5c3ea0b15d9bd3f38dfb79e434621746635030 +size 819389 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/柱候牛腩.md b/data/C8/cook/dishes/meat_dish/柱候牛腩/柱候牛腩.md new file mode 100644 index 0000000..9dab690 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/柱候牛腩.md @@ -0,0 +1,94 @@ +# 柱候牛腩的做法 + +![柱候牛腩成品](./柱候牛腩.jpeg) +![柱候牛腩搭配米饭](./柱候牛腩配米饭.jpeg) + +肉香味美,色泽诱人,滋补强壮,口感甚佳,令人垂涎的广式菜肴。有高压锅只需 1 个小时,否则需要炖煮 3 个小时。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 炖煮锅,高压锅(可选,但极度推荐!) +- 牛腩(首选坑腩,带筋的部位) + ![牛腩部位](./牛腩部位.jpeg) +- 柱候酱(核心酱),郫县豆瓣酱,南腐乳,叉烧酱(可选),蚝油, 老抽,生抽 +- 花雕酒,白酒 +- 香叶, 花椒,八角,干辣椒,丁香,甘草,干辣椒,小米辣(可选),姜,蒜 + +## 计算 + +以下为一份两人食用的量: + +- 牛腩 500-600g +- 姜 30g +- 蒜半头 +- 小米辣 1 条(可根据口味调整用量) +- 香叶 2 片 +- 花椒 0.5g +- 八角 2 个 +- 干辣椒 3 个(可根据口味调整用量) +- 丁香 3 个 +- 甘草 2 片 +- 南腐乳 2 块 +- 郫县豆瓣酱 15g +- 冰糖 10g +- 花雕酒 10g +- 白酒 20g +- 柱候酱 50g +- 蚝油 20g +- 老抽 5g +- 生抽 60g +- 叉烧酱 20g + +## 操作 + +- 先把辅料备好: + + - 碗 1:姜切成 1.5cm\*1.5cm 的小块,半头蒜剥好皮,如果有小米辣切成 1cm 小段 + ![碗 1](./碗1.jpeg) + - 碗 2:放入 2 片香叶,0.5g 花椒,2 个八角,3 个干辣椒,3 个丁香, 2 片甘草 + ![碗 2](./碗2.jpeg) + - 碗 3: 放入 2 块南乳 + ![碗 3](./碗3.jpeg) + - 碗 4: 放入 15g 豆瓣酱 + ![碗 4](./碗4.jpeg) + - 碗 5: 放入 10g 冰糖 + ![碗 5](./碗5.jpeg) + - 碗 6:倒入花雕酒 10g 和白酒 10g + ![碗 6](./碗6.jpeg) + - 碗 7:加入 50g 柱候酱,20g 蚝油,20g 叉烧酱,5g 老抽,60g 生抽 + ![碗 7](./碗7.jpeg) + +- 牛肉不用切,直接冷水下锅,开大火焯水,水沸腾时将牛肉捞出 + ![牛腩焯水](./牛腩焯水.jpeg) +- 冲洗牛肉表面的杂质后,切成 4cm\*4cm\*4cm 的大块,控干水后放入碗中备用 + ![牛腩切块](./牛腩切块.jpeg) +- 大火,热锅下油,把碗 1(姜、蒜、小米辣)倒入锅中,炒香 +- 中小火,倒入碗 2(香料),翻炒均匀,大概 30 秒 +- 中小火,放入碗 3(南乳),用锅铲把南乳压碎 +- 中小火,放入碗 4(豆瓣酱),翻炒均匀,大概 30 秒 +- 中小火,放入碗 5(冰糖),炒至融化 +- 中小火,下入牛腩,炒至牛肉上色 +- 大火,沿锅边淋入碗 6(酒),快速翻炒,炒至牛肉表面略微焦褐 +- 倒入碗 7(酱料),快速翻炒,留意底层汁水,炒至不停冒小气泡,汤汁略微浓稠 + ![牛腩此时可开始炖煮](./牛腩此时可开始炖煮.jpeg) +- 将锅内全部食材转移至另一个炖煮锅或高压锅,加水淹过食材 + ![牛腩入锅](./牛腩入锅.jpeg) +- 根据使用的锅来选择炖肉的时间: + + - a. 普通炖煮锅:小火炖煮 3 个小时 + - b. 高压锅:压 40 分钟 + +- 时间到后开盖调味,如果不够咸加盐或生抽(少量加,不断尝味道,直到合适),不够甜则同理加糖 +- 调好味道后便可以把牛腩先捞出 +- 如果要吃萝卜土豆,则削皮切成 2cm 厚片倒入锅中煮 10 - 15 分钟(或煮至想要吃的口感),如果是高压锅则在加压煮 5 分钟 + ![土豆切片](./土豆切片.jpeg) +- 煮好后捞出萝卜土豆和牛腩放一起 +- 把汤汁过滤淋入碗中 + ![过滤汤汁](./过滤汤汁.jpeg) + +## 附加内容 + +- 参考: [柱候牛腩+茅根马蹄竹蔗水教程](https://www.bilibili.com/video/BV12C4y1W7ox) +- 操作高压锅要注意安全哦! \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/柱候牛腩配米饭.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/柱候牛腩配米饭.jpeg new file mode 100644 index 0000000..1cf3623 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/柱候牛腩配米饭.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d21e2cdde42c3e7db148f0cede8683608ac6791d7ba90dba67c1abd7894eced +size 867447 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩入锅.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩入锅.jpeg new file mode 100644 index 0000000..2997f4c --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩入锅.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef479f4239cc6b02e9374f29cd65c08d97b86c0e2d2d6c43dff47be6f48beeaf +size 727213 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩切块.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩切块.jpeg new file mode 100644 index 0000000..bf4e8ab --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩切块.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c06cc7a57e0946b6ed09fe6f095291d7820ef39f9e78b095d7a4ca5286aba88f +size 946279 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩此时可开始炖煮.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩此时可开始炖煮.jpeg new file mode 100644 index 0000000..ca4a970 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩此时可开始炖煮.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f3c34fb8ffc30af9a146241ce772a3fc790c94709187d1550d26a7d57d2fd25 +size 774375 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩焯水.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩焯水.jpeg new file mode 100644 index 0000000..3e75e17 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩焯水.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ede6fdc3bb3bffafacf7ae9745f4ba8c21ffc5f53b1f6e1cdbc1db8535bd94d1 +size 841970 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩部位.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩部位.jpeg new file mode 100644 index 0000000..f905264 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/牛腩部位.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d85f167bcd4388fe4fb68f093900b5c997165fb689c1bb4bf2d3f46e3f0913b5 +size 792433 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/碗1.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗1.jpeg new file mode 100644 index 0000000..ce067ad --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7344200f5936dba5d59fbde1f9a81c7dd59c1bacbf5dcc8e1dfd449b2a4ed91e +size 541801 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/碗2.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗2.jpeg new file mode 100644 index 0000000..917810f --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8440335c5027e6a8b2ae59c589d3fb82a1cd689abc4dc03190cdeebfc6c9340 +size 667246 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/碗3.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗3.jpeg new file mode 100644 index 0000000..a396d9d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗3.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18afc2def4740088e80b2d24bb53ee4373ba1a143a72a3e526620b05029bc1a9 +size 734562 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/碗4.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗4.jpeg new file mode 100644 index 0000000..9118e59 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗4.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e8a399a8d88aae3e07c16fe068446da46310d9e300ddbd72ee323d629731bdd +size 664006 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/碗5.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗5.jpeg new file mode 100644 index 0000000..757a455 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗5.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:faafdc050329ac205f30ba3717327bfe458f62ccc11ff6adac3b6dd65094e4ac +size 727384 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/碗6.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗6.jpeg new file mode 100644 index 0000000..ce0d63d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗6.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb49de8b622f0ab7b409bbb1969561d750aa70aa3b2bc10cadac686f02a02d5a +size 640764 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/碗7.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗7.jpeg new file mode 100644 index 0000000..ab27440 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/碗7.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1a977e389e61c91ead75263b304974c769f4073d540d8c70d69b5288e9d8eb5 +size 937419 diff --git a/data/C8/cook/dishes/meat_dish/柱候牛腩/过滤汤汁.jpeg b/data/C8/cook/dishes/meat_dish/柱候牛腩/过滤汤汁.jpeg new file mode 100644 index 0000000..0589ee5 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/柱候牛腩/过滤汤汁.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff5dade207f50ad2988533bbca47eeafa00e4f959507783087fcf02c48808cf0 +size 346329 diff --git a/data/C8/cook/dishes/meat_dish/梅菜扣肉/1.jpeg b/data/C8/cook/dishes/meat_dish/梅菜扣肉/1.jpeg new file mode 100644 index 0000000..4f4856c --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/梅菜扣肉/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0084309fc0a95ef3ff98d7a88467929cbae4f87e30ab7aa7863884a1dd8c5298 +size 112389 diff --git a/data/C8/cook/dishes/meat_dish/梅菜扣肉/2.jpeg b/data/C8/cook/dishes/meat_dish/梅菜扣肉/2.jpeg new file mode 100644 index 0000000..d9d38ee --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/梅菜扣肉/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4d4cea0a0d3d062aeae8dec9ffe7ea67642a0470addfb3f8ba08ecab29e64d9 +size 169442 diff --git a/data/C8/cook/dishes/meat_dish/梅菜扣肉/3.jpeg b/data/C8/cook/dishes/meat_dish/梅菜扣肉/3.jpeg new file mode 100644 index 0000000..d2a2ab3 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/梅菜扣肉/3.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b85ed9b6f9114b40ee073ad1d7f32bb7d635b52a27c1efeefa807788b50d3b2e +size 104466 diff --git a/data/C8/cook/dishes/meat_dish/梅菜扣肉/4.jpeg b/data/C8/cook/dishes/meat_dish/梅菜扣肉/4.jpeg new file mode 100644 index 0000000..ee73079 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/梅菜扣肉/4.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3ad59f93389da164a0fdbb8f78925643ac2660e82f72bed81a09eacabf410dc +size 150169 diff --git a/data/C8/cook/dishes/meat_dish/梅菜扣肉/梅菜扣肉.md b/data/C8/cook/dishes/meat_dish/梅菜扣肉/梅菜扣肉.md new file mode 100644 index 0000000..d118846 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/梅菜扣肉/梅菜扣肉.md @@ -0,0 +1,59 @@ +# 梅菜扣肉的做法 + +梅菜扣肉造型别致、大方得体,颜色酱红油亮,汤汁黏稠鲜美,扣肉肥而不腻,食之软烂醇香。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 五花肉 +* 梅菜 +* 五香粉 +* 食用油 +* 白砂糖 +* 老抽 +* 生抽 +* 小米椒 +* 蒜末 +* 食用盐 +* 鸡精 + +## 计算 + +每份: + +* 五花肉 200 g +* 梅菜 30 g +* 五香粉 2 g +* 食用油 300 ml +* 白砂糖 5 g +* 老抽 30 ml +* 生抽 20 ml +* 小米椒 1 个 +* 蒜末 10 g +* 食用盐 2 g +* 鸡精 2 g + +## 操作 + +* 梅菜放到清水中,浸泡 1 小时 +* 锅中倒入 50 ml 食用油,将整个五花肉猪皮朝下,放到锅中 1 分钟 ,取出挂掉猪皮 【可选】 +* 锅中加入开水,放入五花肉,大火煮 20 分钟 (筷子可以插进五花肉),取出五花肉 +* 在五花肉表面涂抹均匀老抽、五香粉、白砂糖,放置 15 分钟 +* 起锅烧油,加入五花肉,中火油炸直至两面金黄色(3-5 分钟) +* 起锅烧油,倒入梅菜,加上小米椒、蒜蓉、鸡精、食用盐后翻炒,直至炒干梅干菜水分 +* 五花肉切片(后端 0.5-1 cm),放在大碗中,散上梅干菜 +* 中火蒸 45 分钟 +* 拿个盘子倒盖在五花肉大碗中,将五花肉倒在盘子中 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) +![示例菜成品](./3.jpeg) +![示例菜成品](./4.jpeg) + +## 附加内容 + +* 制作过程中发现,脆皮五花肉真香 Orz~ +* 不喜欢吃甜的可以去掉白砂糖,不影响主流程 +* 倒数第二个步骤,可以根据个人喜好调整时间 +* 炒干梅干菜的作用是为了后续吸油(盲猜) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/椒盐排条.md b/data/C8/cook/dishes/meat_dish/椒盐排条.md new file mode 100644 index 0000000..c60c247 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/椒盐排条.md @@ -0,0 +1,50 @@ +# 椒盐排条的做法 + +椒盐排条是道非常经典的本帮菜,咸、香,也容易制作。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 大排 +- 鸡蛋 +- 盐 +- 椒盐粉 +- 葱姜水 +- 面粉 +- 淀粉 +- 吉士粉(增色增香,没有可以不放) +- 水 +- 油 + +## 计算 + +每次制作前需要确定计划做几份。一份够 1 - 2 个人吃。 + +- 大排 4 块(大约 360 克) +- 鸡蛋 1 个 50 g +- 盐 1 g +- 椒盐粉 10 g +- 葱姜水 100 ml +- 面粉 80 g +- 淀粉 80 g +- 吉士粉 2-3 g(增色增香,没有可以不放) +- 水 10 g +- 油 10 g + +## 操作 + +- 大排洗干净,剔骨,用刀面拍松,切成厚片,再改成粗条。 +- 加入椒盐粉,搅匀,待到出胶质了**分次**加入葱姜水,放入冰箱腌制 20 分钟。 +- 制作炸糊。放入 80 g 面粉,20 g 淀粉(注意是 20 g 淀粉,剩下 60 g 备用),2 - 3 g 吉士粉,盐 1 g。 +- 打入一个鸡蛋,搅拌,再分次加入水 100 g ,再加 10 g 油,反复搅拌。直到炸糊完全调开,略粘稠即可。 +- 取出剩余的 60 g 淀粉,取出排条,裹上一层淀粉,再裹上面糊。 +- 锅中加入油,能没过食材即可,加热到大约 150 ℃ - 160 ℃ 。下入排条炸成浅金黄色后捞出。刚下入排条时可能会有粘连,不要动。待排条定型后可用筷子翻动,即可分开。 +- 待油温再次升高到 150 ℃ - 160 ℃ 时,下入排条复炸至金黄色后捞出。 +- 撒上椒盐粉,搅拌均匀后出锅。 + +## 附加内容 + +- 也可以用面包糠代替炸糊,但口感差距很大。 +- 炸糊也可以用来炸鸡腿、炸鱼等。 +- 参考:[椒盐排条的做法](https://www.bilibili.com/video/BV14s4y1c76H) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr1.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr1.jpg new file mode 100644 index 0000000..f62ce00 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6a397011449c367d082321c21dd8ff0e0d935dc8c80dcd92f1e18a6896cc015 +size 66372 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr10.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr10.jpg new file mode 100644 index 0000000..f54f9a7 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr10.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cbbed8164bf1dfc795af754f9f5be2ba4d7d60f4b4beb4df70c76d28768dd66 +size 82222 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr11.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr11.jpg new file mode 100644 index 0000000..35e61c6 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr11.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43c3ac806b2afaf322f9eaceec9198c3cb210ef01ba5e3d1e878b837421b646b +size 41846 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr12.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr12.jpg new file mode 100644 index 0000000..e1677c8 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr12.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa7009c182ff60822ca7765ac9cfad97cfd4f5bd9b670e4ce9ec0de0246a02b8 +size 47311 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr2.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr2.jpg new file mode 100644 index 0000000..ce4565f --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:411dfd993ce84ff7feed2f5dae89cea931b14e990c7d3b81e46975d7057e8329 +size 72110 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr3.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr3.jpg new file mode 100644 index 0000000..6b4f880 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr3.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c066dc181ea818f12c5b15c6736ccc427556f8dced6c74d27fb1b0970b509939 +size 80597 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr4.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr4.jpg new file mode 100644 index 0000000..502b23c --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr4.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39fcb3764286c4801bd12ba4269f427b47bb8d203a209588ff91f51da4002e60 +size 70001 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr5.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr5.jpg new file mode 100644 index 0000000..f123c94 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr5.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82fef0cfe83ad2fd8bf29c9af5f92f8cf77d780da63653b482c69080f0e7d29b +size 64949 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr6.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr6.jpg new file mode 100644 index 0000000..2ee07e8 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr6.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c01e040dfe2e52738976b4914ce5e7446b89dd3dd085fa684a93cb491fc491d2 +size 99883 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr7.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr7.jpg new file mode 100644 index 0000000..cbc853c --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr7.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27fca738c99c779a131db82ed9312f6874f57cfcb3e9f111c46d980099c16522 +size 58302 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr8.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr8.jpg new file mode 100644 index 0000000..329f3bf --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr8.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cef983f92955dd4f450953b648f29aa7606acc976f28bb52f5995dde9eea0946 +size 75042 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr9.jpg b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr9.jpg new file mode 100644 index 0000000..8387d0e --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/sznr9.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3aa9bb1546d44236d71c7c3abd9458e5c797dc21266a846d02b4363a2ea01b65 +size 89704 diff --git a/data/C8/cook/dishes/meat_dish/水煮牛肉/水煮牛肉.md b/data/C8/cook/dishes/meat_dish/水煮牛肉/水煮牛肉.md new file mode 100644 index 0000000..76900ea --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮牛肉/水煮牛肉.md @@ -0,0 +1,91 @@ +# 水煮牛肉的做法 + +![shuizhuniurou](./sznr1.jpg) + +麻辣鲜香 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 牛肉 +- 豆芽 +- 鸡蛋 +- 香菜 +- 豆瓣酱 +- 料酒 +- 淀粉 +- 干辣椒粉 +- 姜 +- 蒜 +- 红辣椒 +- 蚝油 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +这是一份的量: + +- 牛肉 300g +- 豆芽 100g +- 鸡蛋 1 个 +- 香菜 5 根 +- 豆瓣酱 10g +- 料酒 10ml +- 淀粉 15g +- 干辣椒粉 5g +- 姜 20g +- 蒜 3 瓣 +- 红辣椒 1 根 +- 蚝油 8g + +## 操作 + +- 牛肉洗干净切片。 + +![shuizhuniurou](./sznr2.jpg) + +- 加入 15g 姜丝,1 个鸡蛋,15g 淀粉,8g 蚝油,10ml 料酒搅拌均匀,腌制 15 分钟。 + +![shuizhuniurou](./sznr3.jpg) + +- 香菜洗干净切好。 + +![shuizhuniurou](./sznr4.jpg) + +- 锅里倒油,加入豆瓣酱,5g 姜丝,蒜片。 + +![shuizhuniurou](./sznr5.jpg) + +- 倒入开水,煮成红汤。 + +![shuizhuniurou](./sznr6.jpg) + +- 豆芽洗干净去掉尾须,放进开水里焯熟。 + +![shuizhuniurou](./sznr7.jpg) + +- 将豆芽铺入碗底。 + +![shuizhuniurou](./sznr8.jpg) + +- 将牛肉片一片一片的放进红汤中,煮熟以后捞出。 + +![shuizhuniurou](./sznr9.jpg) + +- 将牛肉铺在豆芽上,撒上香菜梗。 + +![shuizhuniurou](./sznr10.jpg) + +- 撒上香菜叶,辣椒粉,辣椒圈。 + +![shuizhuniurou](./sznr11.jpg) + +- 另起锅烧热油,将热油淋在菜上面,就完成了。 + +![shuizhuniurou](./sznr12.jpg) + +## 附加内容 + +- 参考: [水煮牛肉的详细步骤](https://www.zhms.cn/recipe/blrqm.html?source=2) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/水煮肉片.md b/data/C8/cook/dishes/meat_dish/水煮肉片.md new file mode 100644 index 0000000..ea93475 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/水煮肉片.md @@ -0,0 +1,83 @@ +# 水煮肉片的做法 + +水煮肉片麻辣鲜香,适合干饭,但是做法稍微有点麻烦。难度主要在肉滑嫩,初学者一般需要 1 - 2 小时完成。干饭人,一切都值~ + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 猪里脊肉 +- 食用盐 +- 胡椒粉 +- 生抽酱油 +- 料酒 +- 鸡蛋清 +- 土豆淀粉 +- 植物油 +- 豆芽 +- 凤尾 +- 芹菜 +- 蒜苗 +- 大蒜 +- 生姜 +- 红泡椒 +- 青花椒 +- 干辣椒 +- 红油豆瓣 +- 鸡精 +- 白砂糖 +- 小葱 +- 菜籽油 + +## 计算 + +- 里脊肉的用量为 300g +- 小葱 2 根 +- 生姜 10g +- 大蒜 20g +- 红泡椒 20g(根据受辣程度选择 0-40 g) +- 蒜苗 2 根 +- 芹菜 3 根 +- 红油瓣酱 5ml +- 鸡精 1.5g +- 生抽酱油 5g +- 食用盐 5g +- 胡椒粉 2g +- 料酒 3g +- 鸡蛋清 1 个 +- 土豆淀粉 7g +- 植物油 280g(根据情况选择,想吃重油就多加 100g) +- 菜籽油 200g(根据情况选择,想吃重油就多加 100g) +- 绿豆芽 100g +- 凤尾 1 根 +- 白砂糖 1g +- 小米辣干辣椒 20g(根据受辣程度选择 0-40g) +- 青花椒 5g(根据情况选择,想吃麻就多 5g) + +## 操作 + +- 里脊肉改刀成小块,再切成 2 毫米薄片(可根据自己的口感改进),放入碗中,加入清水清洗两遍来去除血水和杂质,捞出挤干水分备用。 +- 碗中加入食用盐 1.5g,胡椒粉 1g,生抽酱油 5g,料酒 3g,然后朝着一个方向搅拌 2 分钟,使其入味。 +- 另外准备一个碗,加入一个鸡蛋清,加入 7g 土豆淀粉,一个方向搅拌均匀,倒入肉中 + - 再次一个方向搅拌均匀(肉表面就形成了润滑膜,这样会使肉更加鲜嫩) + - 最后再加入 30g 植物油轻轻搅拌(防止肉片粘连)。 +- 绿豆芽 100g,凤尾 1 根(改刀成小条),芹菜 3 根切成小段,蒜苗 2 根拍散切成小段。 +- 大蒜 20g 剁碎,生姜小块剁碎,红泡椒 20g 剁碎。 +- 小米辣干辣椒 15g,青花椒 3g,锅内加入油滑锅,油稍许热了将多余的倒出备用留 50g 底油,下入干辣椒、花椒,开小火炒香,切记不要炒糊(颜色要变黑即可),倒出在菜板上剁细。 +- 锅烧热,放入 100g 植物油烧至 6 成热,加入 2g 青花椒、干辣椒爆香,配菜下锅,加入 1g 食用盐,炒至断生,盛入碗中垫底备用。 +- 锅洗干净,加入 150g 植物油烧至 6 成热,加入制作好的姜蒜红泡椒,爆香后加入豆瓣 10g,开小火把豆瓣爆香炒出红油即可。 +- 加入 800 毫升清水(根据实际情况选择),大火烧开,转小火调味,加入食用盐 2.5g,鸡精 1.5g,1g 白砂糖提鲜,1g 胡椒粉,5g 水淀粉(根据实际情况选择)将汤汁收浓稠一点。 +- 汤汁开后,开小火将腌制好的肉片分开依次下锅,然后开中火将肉片烫熟,用锅铲轻轻推动一下避免粘连,待汤汁烧开,肉片熟后捞出放入碗中配菜上,再将原汤倒入(不超过菜品)。 +- 碗中均匀撒上刀口辣椒、蒜蓉和葱花。 +- 锅洗干净,加入 200g 菜籽油,烧至 7 成热,然后一次性均匀泼在碗中肉片上(注意安全),美味完成。 + +## 附加内容 + +- 垫底的蔬菜根据自己口味选择(蘑菇、白菜、油麦菜等)。 +- 刀口辣椒制作嫌麻烦也可以直接用干辣椒段和青花椒代替。 +- 特别注意肉的腌制(搅拌的时候朝着一个方向、血水处理干净),保证肉滑嫩(鸡蛋清、淀粉搅拌均匀)。 +- 水煮牛肉也可以按照这个做法。 + +### 参考资料 + +- [美食作家王刚R](https://www.bilibili.com/video/BV1ys411u7Z4) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/洋葱炒猪肉.md b/data/C8/cook/dishes/meat_dish/洋葱炒猪肉.md new file mode 100644 index 0000000..653bd1a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/洋葱炒猪肉.md @@ -0,0 +1,51 @@ +# 洋葱炒猪肉的做法 + +咸中带甜,简单上手,一不小心可能让人多吃一碗饭。一般只需 15 分钟即可完成。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 洋葱 +- 猪肉片 +- 蕃茄酱 +- 麻油 + +## 计算 + +每份: + +食材 + +- 洋葱 一颗 (是主角,喜欢吃洋葱可以多半颗~一颗) +- 猪肉 (250g) +- 蒜头 (3 瓣) + +调味料 + +- 食用油 (15ml) +- 黑胡椒 (1.25g) +- 酱油 (30ml) +- 糖 (15g) +- 麻油 (5ml) +- 番茄酱 (15ml) +- 料酒 (15ml) + +备注:可以考虑购买[茶匙,大匙](https://www.sohu.com/a/127293243_570657)来精准确定用料的量。 + +## 操作 + +- 洋葱切片,猪肉,蒜头拍碎,以及混合上述调味料备用 +- 炒锅内倒入 1 大匙食用油(等待 10 秒让油温升高),倒入猪肉 +- 炒至变色后下蒜头炒香盛起备用 +- 原锅下洋葱翻炒 3~4 分钟后加入调味料炒匀 +- 下刚盛起备用的猪肉翻炒至猪肉熟后 +- 待猪肉熟后再翻炒 1、2 分钟即可起锅 + +## 附加内容 + +- 猪肉可选猪肩肉片或是切好的肉丝看个人喜好 + +### 参考资料 + +- [爱料理](https://icook.tw/) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/清蒸鳜鱼/清蒸鳜鱼.md b/data/C8/cook/dishes/meat_dish/清蒸鳜鱼/清蒸鳜鱼.md new file mode 100644 index 0000000..227ec5a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/清蒸鳜鱼/清蒸鳜鱼.md @@ -0,0 +1,51 @@ +# 清蒸鳜鱼的做法 + +![清蒸鳜鱼成品图](./清蒸鳜鱼成品图.jpg) + +鳜鱼可以称的上淡水鱼之王,味道鲜美,所谓高端的食材只需要最简单的烹饪方式,清蒸最能体现鳜鱼的鲜美。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鳜鱼 +- 大葱 +- 小葱 +- 生抽 +- 红辣椒 +- 姜片 +- 食用油 + +## 计算 + +每份(约 2 人份): + +- 鳜鱼 500g +- 大葱 1 节 +- 小葱 2 根 +- 生抽 30g +- 红辣椒 1 颗 +- 姜片 3 片 +- 食用油 20ml + +## 操作 + +1. **食材处理**: + - 鳜鱼从腹部切开,去除鱼鳃和内脏,打去鱼鳞,用到在表皮上刮去粘液(这一步也可让热心摊主处理) + - 鳜鱼身上打上花刀,放姜片,有条件的可以放点猪油,装盘在下面垫一个筷子,便于蒸制时受热均匀 + - 大葱划开后去除中间的芯,只保留外面两层 + - 小葱划开备用 + - 红椒去除辣椒籽和里层辣椒肉备用 + - 将准备好的大葱、小葱、辣椒码在一起,切成丝泡在水里备用 + +2. **炒制过程**: + - 锅里加水,水量大一些,水热后放入鳜鱼,盖上锅盖,大火蒸制 8 - 10 分钟,蒸鱼四字窍门:汽大火足 + - 蒸鱼过程,另起一个过热油,油需要烧到冒烟 + - 蒸制结束后,倒掉蒸鱼的水,去除姜片,放上葱丝,浇上热油 + - 在倒入生抽或蒸鱼豉油即可上桌 + +## 附加内容 + +- **注意事项**: + 1. 鳜鱼背部鱼鳍容易伤人,处理时候需要注意,最好用剪刀剪掉 + 2. 蒸制时间需要根据鱼的大小调整,蒸鱼的关键在于水多汽大火足 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/清蒸鳜鱼/清蒸鳜鱼成品图.jpg b/data/C8/cook/dishes/meat_dish/清蒸鳜鱼/清蒸鳜鱼成品图.jpg new file mode 100644 index 0000000..309ed07 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/清蒸鳜鱼/清蒸鳜鱼成品图.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdf7dc591a39cec31aa9d63c174c12d4f6a8aa9857a7c5fb56291b60b5de878d +size 241354 diff --git a/data/C8/cook/dishes/meat_dish/湖南家常红烧肉/湖南家常红烧肉.jpeg b/data/C8/cook/dishes/meat_dish/湖南家常红烧肉/湖南家常红烧肉.jpeg new file mode 100644 index 0000000..150098b --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/湖南家常红烧肉/湖南家常红烧肉.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45909a0725c1a87a73d523e280c54ec05ffafb9dce2a2b0708d4e371cafe1ba8 +size 536072 diff --git a/data/C8/cook/dishes/meat_dish/湖南家常红烧肉/湖南家常红烧肉.md b/data/C8/cook/dishes/meat_dish/湖南家常红烧肉/湖南家常红烧肉.md new file mode 100644 index 0000000..c20f241 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/湖南家常红烧肉/湖南家常红烧肉.md @@ -0,0 +1,51 @@ +# 湖南家常红烧肉的做法 + +![湖南家常红烧肉](./湖南家常红烧肉.jpeg) + +湖南家常红烧肉,入口软糯,肥而不腻 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 带皮五花肉 +- 干小米椒🌶(根据个人情况而定) +- 姜 +- 生抽 +- 老抽 +- 香叶 +- 桂皮 +- 八角 +- 冰糖 +- 料酒 +- 盐 +- 冰糖(锁油上色) +- 食用油 +- 开水 + +## 计算 + +一份正好够 2 人吃。 + +- 五花肉:500g +- 食用油:10g +- 香叶 5 片 +- 姜 3 片 +- 桂皮 1 小块 +- 冰糖 6 颗 +- 料酒 20 克 +- 生抽 5 克 +- 老抽 2 克 +- 盐 2 克 +- 八角 3 颗 + +## 操作 + +* 带皮五花肉洗净冷水下锅,加入姜片 2~3 片去腥味,煮到沸腾捞出冷水冲净白沫 +* 五花肉切块,尺寸 1.5cm*1.5cm 块状大小 +* 热锅加入油,加入冰糖小火搅拌至焦糖色即可,加入切好的五花肉,中火翻炒上色 +* 加入备好的姜片、八角、桂皮、生抽、老抽、料酒、干小米椒、盐,小火翻炒 1 分钟,加开水没过肉 +* 加盖中火煮沸,转小火慢顿 30 分钟,慢炖期间,间隔 10 分钟搅拌一次防止粘锅 +* 小火慢炖汤汁剩三分之一的时,调成中火收汁出锅。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step①:准备米粉.jpg b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step①:准备米粉.jpg new file mode 100644 index 0000000..5f5e5e5 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step①:准备米粉.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:513b3c124035395f72c3559d0d00a65147bd6a69be7db5d18fb308a711a52453 +size 293632 diff --git a/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step②:煸炒鸭子.jpg b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step②:煸炒鸭子.jpg new file mode 100644 index 0000000..cce4ea9 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step②:煸炒鸭子.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:950fb26c8434b02bf6b7161d298adc697a74d9746194b48a3acc9a3360b6b63e +size 198874 diff --git a/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step③:米粉裹鸭.jpg b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step③:米粉裹鸭.jpg new file mode 100644 index 0000000..a41d86f --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step③:米粉裹鸭.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b13589247004aac650b70b2a9574183863eaa2731f931547d70b76ed2852e183 +size 284673 diff --git a/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step④:高压锅蒸煮.jpg b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step④:高压锅蒸煮.jpg new file mode 100644 index 0000000..b82d819 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/step④:高压锅蒸煮.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14af960589443729924daf22f022b82b375264025243cd653d37489ff0ef5c0f +size 210826 diff --git a/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/湘祁米夫鸭.jpg b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/湘祁米夫鸭.jpg new file mode 100644 index 0000000..9865180 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/湘祁米夫鸭.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0c65928f9958776d91747bceb1c5a7169b6973e1d76edacf5fdd1ffad0854a8 +size 455420 diff --git a/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/湘祁米夫鸭.md b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/湘祁米夫鸭.md new file mode 100644 index 0000000..eacc959 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/湘祁米夫鸭/湘祁米夫鸭.md @@ -0,0 +1,61 @@ +# 湘祁米夫鸭的做法 + +![湘祁米夫鸭](./湘祁米夫鸭.jpg) + +湖南两祁地区特色菜品,逢年过节家家桌上有。鸭肉被米粉子包裹,入口咸香回味悠长可解乡愁。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 鸭子(必须新鲜现杀的) +- 糯米粉 +- 粘米粉 +- 蒸肉粉 +- 细辣椒粉(吃辣则加) +- 白胡椒粉 +- 五花肉(可加可不加) +- 姜蒜 +- 盐 +- 食用油 +- 开水 + +## 计算 + +正常 3-4 人吃 + +- 鸭子:1000g +- 糯米粉:100g +- 粘米粉: 300g +- 蒸肉粉: 50g +- 细辣椒粉: 50g +- 白胡椒粉:5g +- 五花肉:50g +- 姜蒜:20g +- 盐:10g +- 食用油:10g +- 开水:100g + +## 操作 + +* 将糯米粉、粘米粉、蒸肉粉、细辣椒粉、5 克盐、白胡椒粉倒一起搅匀 +* 鸭子让热心摊主剁成蒸煮块,姜切片,蒜子剥皮,五花肉切片即可 +* 热锅凉油煸炒五花肉出油,再加食用油烧热,下入鸭子煸炒 +* 鸭子煸炒到表皮焦变色,下入姜蒜和盐继续煸炒香味 +* 关小火倒入米粉翻炒,鸭肉均匀裹满米粉子,加入开水,少量多次的加,边加边翻炒 +* 翻炒鸭肉和米粉有湿感,铲出入碗中,高压锅放水蒸 20-25 分钟 +* 出锅前撒点葱花即可享用了 + +## 附加内容 + +这是一道家乡菜。 +鸭子品种不限,这里买的是水鸭,价格 24。 +蒸 20 分钟,是老鸭的话,蒸一个小时以上。 +第一步中粘米粉是主要的粉子,糯米粉是加软糯口感,蒸肉粉是加五香味道,辣椒粉和胡椒粉是加复合香味。 + +下面贴出重要步骤以供参考: + +![step①:准备米粉.jpg](./step①:准备米粉.jpg) +![step②:煸炒鸭子.jpg](./step②:煸炒鸭子.jpg) +![step③:米粉裹鸭.jpg](./step③:米粉裹鸭.jpg) +![step④:高压锅蒸煮.jpg](./step④:高压锅蒸煮.jpg) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/烤鸡翅.md b/data/C8/cook/dishes/meat_dish/烤鸡翅.md new file mode 100644 index 0000000..99e5d4d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/烤鸡翅.md @@ -0,0 +1,41 @@ +# 烤鸡翅的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡翅中 +- 盐 +- 黑胡椒粉 +- 酱油 +- 料酒 +- 烤箱 + +## 计算 + +- 鸡翅用量为 3-4 个/人 +- 盐的用量为 2 g/人 +- 黑胡椒粉的用量为 1 g/人 +- 酱油的用量为 3 ml/人 +- 料酒的用量为 3 ml/人 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 鸡翅的预处理 + +- 鸡翅放入碗中 +- 加盐、黑胡椒粉、酱油、料酒进行腌制 30-40 分钟 + +### 烤制过程 + +- 将烤箱预热至 200℃ +- 将腌制好的鸡翅均匀地放在烤盘上 +- 将烤盘放入烤箱中层,烤 15-20 分钟 +- 取出烤盘,将鸡翅翻面,再烤 15-20 分钟,直到熟透 + +## 附加内容 + +- 可以在腌制鸡翅时加入蜂蜜、酱油、姜蒜粉、五香粉等作为调味料,提升口感和香气 +- 烤鸡翅时,建议将烤盘底部垫上一层锡纸,便于清洁烤盘 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/牛排/牛排.jpg b/data/C8/cook/dishes/meat_dish/牛排/牛排.jpg new file mode 100644 index 0000000..ac59f66 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/牛排/牛排.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14fff3f6abd2e95f28d8dee24727516e997208adb44affa2b9b1d30e9ee8fc32 +size 127330 diff --git a/data/C8/cook/dishes/meat_dish/牛排/牛排.md b/data/C8/cook/dishes/meat_dish/牛排/牛排.md new file mode 100644 index 0000000..173fa32 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/牛排/牛排.md @@ -0,0 +1,102 @@ +# 牛排的做法 + +![牛排成品](./牛排.jpg) + +牛排是一种广受欢迎的西式肉类料理,富含蛋白质、油脂和铁、锌等矿物质。牛排的烹饪过程通过灵活的烹饪手法(如煎、烤、慢煮、熟成)控制牛排的熟度,从三分熟(中心为粉红色)到全熟(完全熟透)可选。高温烹饪能形成焦香外壳,搭配盐、大蒜、黄油、香料可以得到丰富的风味。牛排烹饪的入门较为简单,但精通困难。本文主要介绍最简单的煎牛排,全部烹饪过程耗时 15-30 分钟。图示为 5 分熟的牛小排(short ribs)。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 平底锅(有条件的推荐铸铁平底锅) +- 锡箔纸(可选) +- 厨房纸(可选) +- 汤匙 +- 牛排,参见[如何选择不同种类的牛排](https://zhuanlan.zhihu.com/p/72352426) +- 橄榄油(推荐特级初榨橄榄油) +- 黄油 +- 盐(推荐大颗粒海盐) +- 黑胡椒粉(推荐粗颗粒现磨黑胡椒) +- 大蒜 +- 香料(可选,推荐迷迭香或者百里香,尽量使用新鲜的植物枝条而不是这些香料磨成的粉) +- 预制牛排酱汁(可选) +- 配菜( 可选,按喜好准备,这里推荐芦笋,口蘑,小番茄,小土豆,选其中的 1-2 种即可) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 牛排 450-500g(两片牛排) +- 黑胡椒粉 2g +- 盐 5g +- 大蒜 1 个(约 25-30g,实际用量约为 5-10g) +- 橄榄油 10-15ml +- 黄油 20-25g +- 口蘑 5-10 个 +- 小土豆 5-10 个(每个约 20g) +- 小番茄 5-10 个(每个约 15g) +- 百里香 2g(若使用新鲜百里香枝条,取 3-6 根,每根约 10cm 长即可) + +## 操作 + +### 备料 + +1. 从冰箱中取出牛排解冻。 + + - 如果牛排处于冰冻状态,需提前一晚转移至冷藏室,并在烹饪前半小时放置在常温中。 + - **请勿**将牛排**置于水中或加热解冻**。 + +2. 将小番茄,小土豆和口蘑洗净,对半切开备用。 +3. 将大蒜剥皮,留 5-8 个较大的蒜瓣,用刀背**压扁**备用。 +4. 牛排的预处理 + + - 对于肉眼牛排(见[如何选择不同种类的牛排](https://zhuanlan.zhihu.com/p/72352426)),使用厨房剪刀竖直插入到肉眼牛排中心的结缔组织,剪 1-2 刀。这是因为肉眼牛排的“肉眼”(即这块结缔组织)在高温下会剧烈收缩导致牛排变形,使得牛排无法均匀受热。 + - 对于西冷牛排,如果您不喜欢西冷牛排边上的油脂,可以用刀慢慢将其剔除。 + - 随后,使用厨房纸包裹牛排,将牛排上附着的水全部吸干,直至牛排放在案板上拿起后不留下明显水渍即可。 + +### 烹饪 + + 注:本过程适用于制作 2-3cm 厚、5-7 成熟的牛排。如果您喜欢不同的熟度,考虑将前半部分煎制时间在此基础上增加或缩短 20-30%。 + +1. 将炉灶打开高火(见附录对于火力大小的说明),同时锅中加入橄榄油,热锅 15-30 秒。 +2. 腌制牛排。将海盐和黑胡椒均匀的洒在牛排的全部表面并用手涂抹,揉搓,使得盐和胡椒颗粒尽量嵌入到肉中。注意,腌制完成后牛排**需要立即下锅,不推荐提前腌制牛排**。这是因为外表涂抹的盐会析出牛肉中的水分,影响烹饪的同时丧失风味。 +3. 热锅至油温 6-8 成(参见[油温判断技巧](./../../../tips/advanced/油温判断技巧.md)),将牛排由近及远的缓慢放入锅中。 +4. 如果您使用了土豆作为配菜,可以将土豆放入碗中,然后放进微波炉加热 10 分钟,或者放入开水煮 3-5 分钟。 +5. 单面煎制 1.5 分钟(这个时间适用于 2-3cm 厚大约的牛排。如果您的牛排更薄,考虑将这个时间缩短为 1 分钟。如果您的牛排更厚,考虑将这个时间增加至 2-2.5 分钟。) +6. 翻面,再煎制 1.5 分钟。 + + - 对于西冷牛排和菲力牛排,您需要使用筷子或者锅铲将牛排竖起来,煎它的侧面约 30 秒。 + +7. 将炉灶切换至中火,随后按顺序**快速加入**黄油、大蒜、百里香。用锅铲推动黄油在锅中快速涂抹直至完全融化。将大蒜压在牛排下以增加风味。 +8. 将平底锅**倾斜地放在灶上**,使得油全部流到锅的一侧。 +9. 将香料和大蒜放置在牛排上,用汤匙舀起锅中的油,不断地淋在牛排上。这个过程持续 30 秒,随后将牛排翻面,再重复这个过程 30 秒。 + + - 您可以通过观察油淋在牛排表面时的状态来判断当前的火候。如果油淋在牛排上时冒泡并且油的颜色没有变成深褐色,则油温合适。 + - 如果您的牛排没有擦干净或使用了不推荐的方式解冻,或者使用盐进行了提前腌制,这个时候锅中会出现大量水,导致牛排最后是被“煮熟”的,从而丧失风味。 + - 如果牛排表面出现大量的油泡并且油的颜色变成深褐色,则说明油温过高,您需要将锅移开灶台,稍等片刻再继续淋油。 + +10. 将牛排盛出放在案板上,用锡箔纸包裹,等待 5-10 分钟。这个过程(称为醒肉)的作用是利用牛排自身的温度继续加热,锁住水分。 +11. 将配菜(土豆,番茄,蘑菇)倒入锅中,开中火煎 5 分钟。 +12. 取出牛排,用刀切成宽度 1.5cm 宽度的肉条,此时您可以观察到牛肉的熟度。 +13. 取出配菜,装盘,淋上锅中剩余的油或者牛排酱汁(可选) + +## 附加内容 + +### 火候的控制 + +煎制牛排是控制火候的艺术。限于篇幅,这里简单给出一些定量评估火力的方法和本文中用到的与火候相关的术语。更多内容参见[油温判断技巧](./../../../tips/advanced/油温判断技巧.md)。 + +- 对于电磁炉: + - 高火:功率 1.8Kw - 2.2kw。 + - 中火:功率 800w - 1.4kw。 + - 小火:功率 200w - 600w。 +- 对于燃气灶: + - 高火:旋转气阀至最大出气速度的 70%-90%。 + - 中火:旋转气阀至最大出气速度的 40%-60%。 + - 小火:旋转气阀至最大出气速度的 10%-30%。 + +### 关于调味 + +牛排的调味不一定需要遵循本指南的规范。通常来说,大蒜、黑胡椒和黄油是必须的,但如果您不喜欢迷迭香或百里香等唇形科植物等味道,您可以自由尝试其他牛排调味料进行调味。市面上也有售卖的多种烤肉调味盐可供选择。笔者曾发现一种中西结合的做法,即将小米辣切开与蒜片加入橄榄油中煎,并作为调味在最后淋到牛排上,也独具风味。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/猪皮冻/猪皮冻.jpg b/data/C8/cook/dishes/meat_dish/猪皮冻/猪皮冻.jpg new file mode 100644 index 0000000..733d003 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/猪皮冻/猪皮冻.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b96888969caf02dba9eb5dba0d8a8d7211b529aadbb6b9d731cda50bd21c7776 +size 25083 diff --git a/data/C8/cook/dishes/meat_dish/猪皮冻/猪皮冻.md b/data/C8/cook/dishes/meat_dish/猪皮冻/猪皮冻.md new file mode 100644 index 0000000..2090944 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/猪皮冻/猪皮冻.md @@ -0,0 +1,38 @@ +# 猪皮冻的做法 + +![无骨鸡爪成品](./猪皮冻.jpg) + +猪皮冻是一道简单易做的菜。北方人年夜饭餐桌上的“常青树”,晶莹剔透的外表,滑嫩 Q 弹的口感,是不折不扣的超级下酒菜。 + +猪皮美容养颜,难度稍高,预计制作时长 24 小时。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + + + +- 猪皮 +- 大料、花椒、白芷、桂皮、丁香、香叶、小茴香 + +## 计算 + +每份: + +* 主料:猪皮 1kg、水 4kg +* 调料:盐 13g、味精 10g、鸡精 15g、生抽 50ml、老抽 20ml、葱 10g、葱 10g、姜片 20g +* 香料包:八角 10g、花椒 5g + +## 操作 + +- 将猪皮,剁成不超过 10cm 小块,用清水浸泡 12 小时,然后冷水下锅,加入姜 10g、料酒 50ml 后,汆烫 5-10 分钟,捞出放入冷水中 +- 将焯过水的猪皮,放到案板上,将里面的白肉部分全部剔除,然后再切成成不超过 3mm 的长条,放入盆中 +- 加入白醋 20g,盐 5g,用力搓洗 3 分钟,再用清水洗净,这时的猪皮已经基本没什么腥味 +- 锅内加入 4kg 水,放入猪皮,葱 10g,姜片 10g,八角 10g,花椒 5g,大火烧开后,小火煲煮 90 分钟至猪皮软烂 +- 再加入盐 8g、味精 10g、鸡精 15g、生抽 50ml、老抽 20ml 调味后,倒入盘中,将葱姜,八角拣出,晾凉至果冻状 +- 放冰箱冷藏即可,食用时,切成小块或者厚片 + +## 附加内容 + +- 操作时,需要注意,做猪皮冻,直接下锅煮就“废”了,也是最忌讳的,一定要用白醋和盐不断搓洗猪皮,这样保证煮好的猪皮晶莹剔透,而且还没腥味 +- 参考资料:[铭哥说美食](https://www.bilibili.com/video/BV1hh41117TL?spm_id_from=333.999.0.0) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/猪肉烩酸菜.md b/data/C8/cook/dishes/meat_dish/猪肉烩酸菜.md new file mode 100644 index 0000000..8890eb1 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/猪肉烩酸菜.md @@ -0,0 +1,55 @@ +# 猪肉烩酸菜的做法 + +猪肉烩酸菜是一道北方名菜,简单易做。富含蛋白质。一般初学者需要 3 小时完成。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +* 猪五花肉或猪肉排骨 +* 东北酸菜 +* 大葱 +* 姜 +* 蒜 +* 盐 +* 生抽酱油 +* 五香粉 +* 料酒 +* 大料 + +## 计算 + +按照 3-5 个人吃的量: + +* 猪排骨或者五花肉(总共) 1500 克 +* 东北酸菜 1000 克 +* 大葱 1 根 +* 姜 100 克 +* 蒜 4 瓣 +* 盐 10 克 +* 生抽酱油 15 克 +* 五香粉 10 克 +* 料酒 20 毫升 +* 大料 2 颗 + +## 操作 + +- 大葱切段;生姜 50 克切段, 50 克切末;大蒜切末,备用。 +- 全部酸菜切丝,用水冲洗 2 ~ 3 遍备用。 + -冲洗次数取决于个人口味,喜欢酸味,可以冲洗 2 遍。害怕酸味,可以冲洗 3 ~ 4 遍。不能不冲洗,否则会过酸。 +- 排骨和五花肉入锅,倒入冷水淹没。放入全部葱段, 50 克生姜段和料酒 20 毫升。大火煮开后,等待 5 分钟。关火,将排骨和五花肉捞出,冷水冲洗掉浮沫,备用 +- 煮好的五花肉切片或者切块,备用。 +- 将之前的锅洗干净,并且擦干(不然加入油会崩出来)。 +- 锅中加入油,开中火,放入姜蒜末爆香,放入五花肉和排骨。将五花肉和排骨煎至金黄,倒入 10 克五香粉和 15 克 生抽酱油,用铲子翻动 1 ~ 2 分钟。 +- 将冲洗好的酸菜丝加入锅中,翻炒 3 分钟。 +- 倒入纯净水至刚好没过食材,加入 2 颗大料,转大火,直到锅中水沸腾。转中火,盖锅盖焖煮。 +- 等待 1.5 ~ 2 小时,直至五花肉软烂 (可以用筷子轻松扎穿) +- 掀开锅盖,开大火收汤,翻动锅中食材直至锅中剩余水分只覆盖锅底,转小火,准备调味。 +- 调味:加入食用盐 10 克,搅拌均匀。 +- 关火,出锅。 + +## 附加内容 + +- 大火收汤时,注意不要糊锅,可以适当翻动来检查水位。 +- 调味的技巧,最后加盐时,可以一点一点加入,搅拌后品尝味道,直到可以接受的口味 +- 本菜品有酸菜的特殊风味 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/甜辣烤全翅.md b/data/C8/cook/dishes/meat_dish/甜辣烤全翅.md new file mode 100644 index 0000000..be00fb7 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/甜辣烤全翅.md @@ -0,0 +1,62 @@ +# 甜辣烤全翅的做法 + +本甜辣烤全翅使用空气炸锅烹饪并仅使用家中常见调料,低油脂并且不需要成品烧烤酱,一份适合单人食用,食材处理需要 15 分钟,腌制需要 120 分钟, 烹饪需要 50 分钟。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 空气炸锅 +- 鸡全翅 +- 生抽 +- 老抽 +- 蒜粉 +- 胡椒粉 +- 糖 +- 甜椒粉 +- 辣椒粉 +- 蚝油 +- 水 +- 油 +- 锡纸盘 +- 保鲜膜 + +## 计算 + +一份为一人餐,多人餐请等比例增加。 + +一份: + +- 鸡全翅 4 个 +- 生抽 45ml +- 老抽 15ml +- 蒜粉 10g +- 胡椒粉 5g +- 糖 10g +- 甜椒粉 10g +- 辣椒粉 5g +- 蚝油 15ml +- 水 20ml +- 油 10ml + +## 操作 + +- 将 4 个新鲜鸡全翅取出,在翅中两根骨头之间用刀划开表皮,正反面各一刀 +- 将 4 个鸡全翅放入碗中,加入生抽 45ml , 老抽 15ml , 蒜粉 10g , 胡椒粉 5g , 糖 10g , 甜椒粉 10g ,辣椒粉 5g , 蚝油 15ml , 水 20ml 以及油 10ml +- 用勺子将酱汁均匀的抹在鸡全翅上,尤其是翅中的刀口处,大约花费 3 分钟 +- 用保鲜膜盖住防油腌制中鸡全翅的碗,放入冰箱冷藏格静置 120 分钟 +- 取出鸡全翅,锡纸盘中放入鸡全翅 4 个,将碗中残余酱料均匀倒在鸡全翅上 +- 锡纸盘放入空气炸锅的烤篮上,用 200 摄氏度烤 25 分钟 +- 打开空气炸锅,小心取出锡纸盘,将鸡全翅翻面 +- 继续 200 摄氏度烤 25 分钟 +- 取出即可食用 + +## 附加内容 + +- 本例中鸡全翅口感为微辣,需增加辣度请增加辣椒粉用量,但不宜超过 30g +- 鸡全翅指包含翅尖,翅中和翅根的鸡翅 +- 本品效果微焦,如不喜欢焦褐色外观可 不向锡纸盘中倒入残余酱汁并 每面只烤制 20 分钟 +- 实际烤制效果请根据自己空气炸锅的功率判断 +- 甜椒粉起增加色泽和风味作用,本身不能作为辣味剂 +- 腌制时间可自由掌控,建议在 60 分钟到 180 分钟之间为宜 +- 刚出锅的锡纸盘比较烫,请用夹子夹取或使用湿抹布之类的隔热材料拿取 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/番茄红酱.md b/data/C8/cook/dishes/meat_dish/番茄红酱.md new file mode 100644 index 0000000..3c16a77 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/番茄红酱.md @@ -0,0 +1,50 @@ +# 番茄红酱的做法 + +番茄红酱香浓可口,营养丰富,咱很喜欢。可以作为薄饼、意面~~热干面~~等主食的百搭酱料。有些繁琐,适合有烹饪经验的人尝试。一次吃不完也没有关系,可以冷冻后随时拿出来加热哦。(但是千万要记得吃) + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 碎牛肉 +- 蒜瓣 +- 胡萝卜 +- 芹菜 +- 洋葱 +- 橄榄油 +- 糖 +- 食盐 +- 胡椒粉 +- 番茄酱 +- 牛奶 +- 干罗勒或百里香(可选) + +## 计算 + +每份: + +- 碎牛肉 500g +- 蒜瓣 2 个 +- 胡萝卜 半根 +- 芹菜 一根 +- 洋葱 半个 +- 橄榄油 +- 糖 2g +- 食盐 10g +- 黑胡椒粉 5g +- 番茄酱 300g +- 牛奶 300ml + +## 操作 + +- 将胡萝卜、芹菜、洋葱切碎,蒜瓣切片。 +- 加入 10ml 橄榄油,热油下锅蔬菜,大火翻炒开始略微变色后盛出。 +- 锅内加油 10ml,加蒜翻炒 10 秒,加入碎牛肉、糖、盐、胡椒粉和香料将牛肉炒脆(有颗粒感)。 +- 加入炒好的蔬菜们和番茄酱继续翻炒,搅拌均匀。 +- 分多次缓缓倒入牛奶,中小火煮 30 分钟,完成。 + +## 附加内容 + +- **考虑各个品牌的番茄酱内含盐量不同,建议在炒牛肉时少放盐,煮的时候尝一下再调味** +- **煮酱料期间请搅动,以免粘锅。如果酱料变粘稠就可以出锅啦!** +- 可根据个人口味,将碎牛肉替换成一半碎猪肉一半碎牛肉,牛奶替换成鸡汤或饮用水。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/瘦肉土豆片/瘦肉土豆片.jpg b/data/C8/cook/dishes/meat_dish/瘦肉土豆片/瘦肉土豆片.jpg new file mode 100644 index 0000000..2fb209a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/瘦肉土豆片/瘦肉土豆片.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da63bbe24e8dbd48c4885102a0fac62825ba5beb66404935920e3c12b28326b9 +size 254333 diff --git a/data/C8/cook/dishes/meat_dish/瘦肉土豆片/瘦肉土豆片.md b/data/C8/cook/dishes/meat_dish/瘦肉土豆片/瘦肉土豆片.md new file mode 100644 index 0000000..e752314 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/瘦肉土豆片/瘦肉土豆片.md @@ -0,0 +1,45 @@ +# 瘦肉土豆片的做法 + +![示例菜成品](./瘦肉土豆片.jpg) + +瘦肉土豆片是一道简单易做的菜。小炒家常菜,方便快速,适合上班族用于带饭必备小炒菜。一般初学者只需要 1 小时即可完成。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 纯瘦肉 +- 土豆 +- 蒜苗 +- 生粉(玉米淀粉或其他淀粉) +- 生抽 +- 老抽 +- 食用盐 + +## 计算 + +1 人食用版本 + +- 纯瘦肉 200g +- 土豆 200g +- 蒜苗 2 根(约 20 g) +- 生粉 5g +- 生抽 10g +- 老抽 3g +- 食用盐 2g + +## 操作 + +- 土豆去皮、对半切开,再切成约 2mm 的薄片,备用 +- 蒜苗洗净,切成约 1cm 的段,备用 +- 瘦肉洗净切成约 2mm 的薄片,放入碗中,加入 5g 生粉、5g 生抽、3g 老抽腌制十分钟,备用 +- 瘦肉腌制时,烧一锅开水,将土豆片放入锅中,焯水,约 5 分钟 +- 热锅,锅内放入 10ml - 15ml 食用油。等待 10 秒让油温升高 +- 放入瘦肉,翻炒至变色,倒入蒜苗一起炒,蒜苗炒约 20 秒 +- 放入土豆,保持翻炒,加入 2g 食用盐、5g 生抽, +- 炒约 3 分钟,盛盘 + +## 附加内容 + +- 土豆片焯水注意不宜太久,防止土豆片变软 +- 腌制瘦肉要搅拌均匀 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/白菜猪肉炖粉条.md b/data/C8/cook/dishes/meat_dish/白菜猪肉炖粉条.md new file mode 100644 index 0000000..75f3803 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/白菜猪肉炖粉条.md @@ -0,0 +1,48 @@ +# 白菜猪肉炖粉条的做法 + +白菜猪肉炖粉条是一道简单易做的菜。这是一道传统的东北家常菜,以做法简单、味道上乘的特点,在广大东北人民群众中备受喜爱。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 五花肉 +- 白菜 +- 土豆干粉条 +- 十三香 +- 鸡精 +- 食用盐 +- 老抽 +- 生抽 + +## 计算 + +每份: + +- 五花肉 300g +- 大白菜 500g +- 土豆干粉条 50g +- 十三香 10g +- 鸡精 5g +- 食用盐 15g +- 老抽 5ml +- 生抽 5ml + +## 操作 + +- 锅内烧水,水开后放入干粉条,煮 5 分钟后同水一起倒出容器中,盖上盖子继续浸泡泡 备用(第一步先做这个,期间可以进行以下步骤) +- 五花肉切 3mm 的肉片,备用 +- 大白菜嫩叶与白菜帮子分开切成 2 份菜片,备用 +- 热锅,锅内放入 10ml - 15ml 食用油。等待 10 秒让油温升高 +- 放入五花肉,保持翻炒至肉变色 +- 加入老抽,炒 **1 分钟**,给肉上色 +- 加入白菜帮子,加入食用盐、生抽,炒一分钟(如果粘锅,烹入 10ml 水) +- 加水没过所有食材,加入鸡精 ,十三香,沸腾后,将火调小然后**等待 20 分钟** +- 粉条滤水切成小段放入碗中 备用 +- 加入白菜嫩叶,炒匀后将粉条放在菜上方,加盖再煮 **5 分钟** +- 尝味、关火,收汁 + +## 附加内容 + +- 土豆干粉条煮制时间长,可以放在第一步,期间进行其他步骤 +- 最后一步尝味,如果发现有味道淡、未熟,继续加盖煮一段时间 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/粉蒸肉.md b/data/C8/cook/dishes/meat_dish/粉蒸肉.md new file mode 100644 index 0000000..e3a56cc --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/粉蒸肉.md @@ -0,0 +1,59 @@ +# 粉蒸肉的做法 + +粉蒸肉是一道经典的中式蒸菜,香味浓郁,口感软糯,营养丰富。适合家庭聚餐或节日宴客。此菜适合有一定烹饪经验的人士制作,预计从准备到完成约需 90 分钟。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 五花肉 500g(肥瘦相间) +- 蒸肉米粉 100g(推荐使用李锦记或自制) +- 生抽 15ml +- 老抽 10ml +- 料酒 15ml +- 郫县豆瓣酱 10g(可选) +- 姜末 10g +- 蒜末 10g +- 白砂糖 5g +- 土豆 300g(或南瓜 300g,作为垫底食材) +- 清水(蒸锅用)2000ml + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 3 个人吃。 + +每份: + +- 五花肉 250g +- 蒸肉米粉 50g +- 生抽 7.5ml +- 老抽 5ml +- 料酒 7.5ml +- 郫县豆瓣酱 5g(可选) +- 姜末 5g +- 蒜末 5g +- 白砂糖 2.5g +- 土豆或南瓜 150g +- 蒸锅用水 1000ml + +## 操作 + +- 将五花肉洗净,切成长约 5cm、宽约 3cm、厚度约 0.5cm 的肉片 +- 将姜、蒜切成颗粒直径不大于 1mm 的细末 +- 取一大碗,放入切好的五花肉、15ml 生抽、10ml 老抽、15ml 料酒、10g 郫县豆瓣酱、10g 姜末、10g 蒜末、5g 白砂糖 +- 用筷子搅拌均匀后,盖上保鲜膜,室温(20°C - 25°C)静置腌制 30 分钟 +- 腌制完成后,加入 100g 蒸肉米粉,继续翻拌 2 分钟,确保每片肉都均匀裹粉 +- 土豆去皮,切片厚度控制在 0.8cm,片面积约为 5cm x 5cm,重量控制在 300g +- 在直径 20cm 的深碗底部铺满土豆片,尽量无重叠 +- 将拌好粉的五花肉均匀铺在土豆片上,压实 +- 蒸锅中加入 2000ml 清水,开火加热至水面持续冒泡(100°C) +- 将装好食材的碗放入蒸锅内,盖好锅盖 +- 保持中火蒸 60 分钟(火力保持在可持续沸腾的程度,约 600W 热功率) +- 时间结束后,用筷子插入肉块中央,若能轻松穿透并无明显阻力,则表明蒸熟 +- 若未达到此状态,则继续加热 10 - 15 分钟,直至肉质软烂,油脂渗出 +- 取出盛盘,即可食用 + +## 附加内容 + +- 如需自制米粉,可将大米 150g 放入锅中,中小火炒至微黄色(约 8 分钟),再加入干辣椒 1g、花椒 1g、八角 0.5g,炒香后用料理机打碎,过筛备用 +- 蒸制期间如水量低于锅底高度 1cm,应立即补充 500ml 热水(90°C 以上),以维持蒸汽充足 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/糖醋排骨/1.jpeg b/data/C8/cook/dishes/meat_dish/糖醋排骨/1.jpeg new file mode 100644 index 0000000..66ee5e8 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/糖醋排骨/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0843779d34a3147dfb2cb3ea8a108dee74dfd64a2b1c6f4e70173b1041f581ab +size 88411 diff --git a/data/C8/cook/dishes/meat_dish/糖醋排骨/2.jpeg b/data/C8/cook/dishes/meat_dish/糖醋排骨/2.jpeg new file mode 100644 index 0000000..1bf6faf --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/糖醋排骨/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5dcb3b61dfa257da166037feccc2deef673cb788e9ca2e41b68fb5d146dd5c0f +size 202934 diff --git a/data/C8/cook/dishes/meat_dish/糖醋排骨/糖醋排骨.md b/data/C8/cook/dishes/meat_dish/糖醋排骨/糖醋排骨.md new file mode 100644 index 0000000..889cd8d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/糖醋排骨/糖醋排骨.md @@ -0,0 +1,57 @@ +# 糖醋排骨的做法 + +糖醋排骨是一道具有代表性的传统名菜,以其独特的酸甜口味深受大众喜爱。本菜谱在保留原有风味的基础上,对用料绑定、火候控制以及操作细节作了优化,旨在提高菜谱的可迁移性和可执行性。 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 排骨 +- 白砂糖 +- 食用油 +- 生抽 +- 蚝油 +- 老抽 +- 鸡精 +- 姜片 +- 芝麻 +- 番茄酱 +- 香醋 +- 五香粉 + +## 计算 + +每份: + +- 排骨 300 g +- 白砂糖 30 g +- 食用油 300–350 ml (油量需根据锅具大小调整,如用于深炸则以足以覆盖排骨 2/3 为准) +- 生抽 5 ml +- 蚝油 5 ml +- 老抽 5 ml +- 鸡精 2 g +- 姜片 2 片 +- 芝麻 2 g +- 番茄酱 10 g +- 香醋 5 ml +- 五香粉 2 g + +## 操作 + +- 排骨与姜片放入冷水中,大火加热至水沸腾、出现大量泡沫后转中火,待水持续沸腾时再转小火焯水 2–3 分钟,捞出备用。 +- 用开水反复清洗排骨 2–3 遍,确保彻底去除血沫。 +- 在锅中倒入足够量的食用油进行深炸(油量依据锅具大小而定,建议约 300 ml 供一般家庭使用),待油温升至约 170°C 后,下排骨炸制 3–5 分钟,直至表面略呈金黄色,捞出控油。 +- 另取干净锅,置于小火上加热 50 ml 热水,加入白砂糖 30 g,轻轻搅拌直至糖完全溶解,并略呈淡黄色。此步骤的重点在于观察糖溶解情况,无需过分依赖颜色变化。 +- 将炸好的排骨倒入炒制糖水的锅中,迅速翻炒 30 秒后,依次加入香醋 5 ml、生抽 5 ml、蚝油 5 ml、鸡精 2 g、番茄酱 10 g、五香粉 2 g,再次翻炒 30 秒,使调料均匀裹覆排骨,然后加入开水至刚好没过排骨。 +- 用大火将锅中液体煮沸后,加入老抽 5 ml 进行上色,并快速收汁;若排骨块较大,可转小火焖煮 5–10 分钟以便更好地入味,切勿采用中火长时间炖煮 20 分钟,以免损伤口感。 +- 起锅装盘,撒上芝麻 2 g,即可享用。 + +## 附加内容 + +- 炸排骨时可根据实际情况轻撒少量干淀粉于排骨表面,以提升酥脆口感。 +- 焯水时注意火力变化:冷水下锅后先用大火至水沸腾、泡沫丰富,再转中火,最后转小火焯水;焯水后应使用开水清洗,避免因温差过大导致肉质变柴。 +- 步骤四的关键在于确保白糖完全溶解,无须过分依赖颜色变化判断。 +- 收汁时应快速翻炒,使排骨均匀裹上调料,避免长时间煮炖造成口感损失。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/糖醋里脊.md b/data/C8/cook/dishes/meat_dish/糖醋里脊.md new file mode 100644 index 0000000..d6b4b2d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/糖醋里脊.md @@ -0,0 +1,51 @@ +# 糖醋里脊的做法 + +糖醋里脊是中国经典传统名菜之一,该菜品以猪里脊肉为主材,配以面粉、淀粉、醋等佐料,酸甜可口,让人食欲大开;该菜品在陕菜、豫菜、浙菜、鲁菜、川菜、淮扬菜、粤菜、闽菜里均有此菜。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 里脊肉 +- 醋 +- 白糖 +- 淀粉 +- 鸡蛋 +- 生抽 +- 料酒 +- 蚝油 +- 番茄酱 +- 白胡椒粉 +- 盐 + +## 计算 + +每份: + +- 里脊肉 500g +- 醋 10g +- 白糖 30g +- 淀粉 50g +- 鸡蛋 50g +- 生抽 10ml +- 料酒 20g +- 蚝油 10g +- 番茄酱 30ml +- 白胡椒粉 5g +- 食盐 10g + +## 操作 + +- 腌肉:将猪里脊肉先切厚片,用刀背拍一拍,把肉拍松一点。切成一个手指头粗的条,加料酒,生抽,蚝油,食盐,白胡椒粉,一个鸡蛋,将肉用手抓匀,腌制 20 分钟以上。 +- 调酱:番茄酱+10g 醋+30g 白糖+150ml 清水,搅拌至糖融化,备用。 +- 裹粉:先把粉全部裹好再来炸,这样在炸的时候就不会手忙脚乱。准备一个大碗,里面放淀粉,把每一根肉条都满满裹上淀粉。 +- 炸制:油温 160 摄氏度下里脊,可以拿一个干筷子放在油里面试一下,周围冒小泡就可以下锅。 +- 炸到表面微黄可以捞出,全程中火。然后等油温升高到 200 摄氏度,把里脊倒进去重新炸一次,只需 40 秒,表皮就会很脆,马上捞出。 +- 裹酱:另外拿一个锅,锅里放底油,把调好的酱汁倒进去,煮到冒泡,把炸好的里脊放进去,翻炒,让每一根都裹上酱汁。 +- 下炸好的里脊肉翻炒,关火盛出。 + +## 附加内容 + +- 里脊要多炸几遍,注意火候,否则达不到外焦里嫩的效果! +- [下厨房](https://www.xiachufang.com/recipe/104483435/) +- [百度百科](https://baike.baidu.com/item/%E7%B3%96%E9%86%8B%E9%87%8C%E8%84%8A/135832) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/红烧猪蹄/红烧猪蹄.jpg b/data/C8/cook/dishes/meat_dish/红烧猪蹄/红烧猪蹄.jpg new file mode 100644 index 0000000..5340a4d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/红烧猪蹄/红烧猪蹄.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:930dc1711d81fe6fde7eafe85e6ec65f8a5bb47e1aafa6595bbc78f0e77e4b5c +size 261696 diff --git a/data/C8/cook/dishes/meat_dish/红烧猪蹄/红烧猪蹄.md b/data/C8/cook/dishes/meat_dish/红烧猪蹄/红烧猪蹄.md new file mode 100644 index 0000000..aabe0d5 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/红烧猪蹄/红烧猪蹄.md @@ -0,0 +1,54 @@ +# 红烧猪蹄的做法 + +![红烧猪蹄](./红烧猪蹄.jpg) + +红烧猪蹄营养丰富,味道香,汤汁浓郁、下饭强。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 猪蹄 +- 香叶 +- 姜 +- 葱 +- 老抽 +- 桂皮 +- 冰糖 +- 料酒 +- 生抽 +- 盐 +- 八角 +- 食用油 + +## 计算 + +一份正好够 3-4 人吃。 + +- 猪蹄:2~3 根 +- 食用油:30ml +- 香叶 2 片 +- 姜 5 片 +- 葱半根 +- 桂皮 1 块 +- 冰糖 7-8 粒 +- 料酒 30 ml +- 生抽 20 ml +- 老抽 20 ml +- 盐 8 克 +- 八角 4 个 + +## 操作 + +### 开始制作 + +* 冷水锅中放入热心摊主剁好的猪蹄,加入 20 ml 料酒与葱姜,煮 15 分钟去掉血腥 +* 热锅冷油,倒入 30ml 食用油,放入 7-8 粒冰糖,开小火,熬成糖色,期间用锅铲把冰糖压碎,大概熬 2 分钟 +* 熬成糖色后,放入焯过水的猪蹄,继续小火,翻炒猪蹄,直至所有猪蹄两面微黄 +* 加入香叶 2 片、桂皮 1 块、八角 4 个、生抽 20 ml、老抽 20 ml、料酒 10 ml、姜 3 片、盐 8 克,转中火、继续翻炒 1 分钟 +* 加入开水或者冷水,水需要没过猪蹄,盖上锅盖,大火烧开,烧开之后关火 +* 把锅内的食材全部倒入高压锅中,高压锅中需要 15 分钟(如果同学没有高压锅,可放在锅中大火转小火熬制即可) +* 15 分钟之后,把高压锅的食材倒入炒锅中,开大火收汁,此时可用筷子尝下味道、淡的话可以加 2~3g 盐 +* 大火收汁时长根据锅中的水来算,一般 30 秒即可,多留点也无碍、红烧猪蹄汤也是很下饭的 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/红烧肉/000.jpg b/data/C8/cook/dishes/meat_dish/红烧肉/000.jpg new file mode 100644 index 0000000..0aec16d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/红烧肉/000.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a931db08a57c50e6b5718d357cda7e4bed78fc599fc8d99220f3a26c6c135a8 +size 366456 diff --git a/data/C8/cook/dishes/meat_dish/红烧肉/001.jpg b/data/C8/cook/dishes/meat_dish/红烧肉/001.jpg new file mode 100644 index 0000000..6b30d19 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/红烧肉/001.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f027789e9796f6a0413883ee5ff63b1995e9a3b3a3ec4e4771e0504b53adeea +size 272650 diff --git a/data/C8/cook/dishes/meat_dish/红烧肉/南派红烧肉.md b/data/C8/cook/dishes/meat_dish/红烧肉/南派红烧肉.md new file mode 100644 index 0000000..01b5758 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/红烧肉/南派红烧肉.md @@ -0,0 +1,52 @@ +# 南派红烧肉的做法 + +这份红烧肉教程是一道新手不败的菜谱。配着米饭好吃的停不下来,香糯无敌棒色泽诱人肥而不腻 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 注:如果有可能,请尽量把刀磨的锋利一些。 +* 工具:`锅`(砂锅为宜,铝锅其次,高压锅也可以,最好不要铁锅、铜锅) +* 主料:`五花肉` +* 辅料:`油`、`冰糖`、`老抽`、`料酒`、`香叶`、`八角`、`生姜`、`盐`、`葱`、`开水`、`凉水`、`蒜`、`花椒` + +## 计算 + +一份正好够 1-3 人吃。 + +- 猪五花肉:约 2 斤 +- 油:100-150ml,色拉油、猪油、花生油都可以 +- 姜: 6 片 +- 冰糖:约 15 块 +- 白砂糖:30g +- 老抽:15ml +- 料酒:20ml +- 凉水:没过食材的量即可,看锅大小准备 +- 开水:没过食材的量即可,看锅大小准备 +- 香叶:4 片 +- 八角:3 个 +- 盐:2-3g +- 花椒:10g + +## 操作 + +建议在此之前查看炒[糖色](./../../condiment/简易版炒糖色.md)教程 + +- `猪五花肉`切大块(约 4.5cm ) +- `生姜`切片(每片厚度约 3mm ) +- `开水`烧开 +- `凉水`自来水即可 +- `小葱`小葱白色的部分`葱白`切成小段(小葱最佳,大葱也可以) +- `蒜`中间切开,不要拍扁,否则难以捞出以至最后`收汁`时影响味道 +- 建议先拿出来一半葱姜,再将剩下的`生姜、葱白、蒜、花椒、八角、香叶`提前放入一个碗中备用 +- 凉水锅中放入切好的五花肉,加入料酒与 2/5 葱姜,煮 15 分钟去掉血腥,捞出来后洗干净; +- 炒[糖色](./../../condiment/简易版炒糖色.md),注意采用其中提到的操作 2 来制作糖色。 +- 将准备好的`生姜、葱白、蒜、花椒、八角、香叶`还有`五花肉`倒入锅中`大火`翻炒,期间加入至闻到香味,倒入开水至没过全部肉炖煮 50 分钟-60 分钟 + - 高压锅的话 40 分钟; +- 加入 10ml 料酒; +- 盖上锅盖煮至沸腾后,每隔 25 分钟打开盖子将浮在表面的油和沫捞出; +- 当水的高度减至肉最高的高度与锅底高度的 3/5 时,转中火,并捞出除肉和水以外的所有辅料,开始收汁; +- 打开锅盖,待汤汁快没有的时粘稠状出锅(切记不可收干); + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/红烧肉/简易红烧肉.md b/data/C8/cook/dishes/meat_dish/红烧肉/简易红烧肉.md new file mode 100644 index 0000000..bdeab26 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/红烧肉/简易红烧肉.md @@ -0,0 +1,66 @@ +# 简易红烧肉的做法 + +这份红烧肉教程是一道新手不败的菜谱。配着米饭好吃的停不下来,香糯无敌棒色泽诱人肥而不腻。建议搭配米饭食用。 + +![红烧肉成品](./000.jpg) + +![红烧肉成品](./001.jpg) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 注:如果有可能,请尽量把刀磨的锋利一些。 +- 主料:`大肉`、`鸡蛋`(可选)、`豆皮`(可选) +- 辅料:`生姜`、`冰糖`、`生抽`、`老抽`、`料酒`、`香叶`、`八角`、`盐`、`水`、`葱`(记得要开水) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2-3 个人吃。 + +如果只有 1 人食用,可以考虑食材减半。 + +- 猪五花肉:约 3~4 斤 +- 姜: 6 片 +- 冰糖:15 克(约 7 块) +- 生抽:10ml +- 老抽:15ml +- 料酒:5ml +- 开水:没过食材的量,需要 600ml-900ml +- 香叶:3 片 +- 八角:2 个 +- 鹌鹑蛋(可选,没有鹌鹑蛋,可以用同等重量的鸡蛋代替):0-2 个 +- 豆皮(可选):0-80g +- 盐:2-3g + +## 操作 + +### 原材料准备 + +- `猪五花肉`切大块(约 4.5cm ,冷冻半小时至一小时更好切) +- `豆皮`切 2cm 的宽度 +- `生姜`切片(每片厚度约 3mm ) +- `水`烧开 +- `鹌鹑蛋`煮熟并用`叉子`/`牙签`扎孔(尽量多些好入味) +- `大葱`大葱白色的部分`葱白` + +### 开始制作 + +- 冷水锅中放入切好的`猪五花肉`,加入料酒与葱姜,煮 15 分钟去掉血腥 +- 锅中放入两片`生姜`提味 +- 开中小火后直接加入`五花肉`,不需要放入食用油,每块`五花肉`六个面都煎一下,煎至出油即可 +- 将煎出的油倒出备用,并将`五花肉`推至一边,加入 15g `冰糖`,翻炒至`冰糖`融化; +- 融化后将五花肉与冰糖炒至融合上色,加入 + - `生抽` 10ml + - `老抽` 15ml + - `料酒` 5ml + - 翻炒至上色; +- 加入`烧好的开水`炖煮 40 分钟(刀工差的同学切的过大请自觉延长炖煮时间),并放入 + - `生姜` 2 片 + - `香叶` 3 片 + - `八角` 2 个 +- 盖上锅盖煮至沸腾后,加入煮好扎好孔的`鹌鹑蛋`和`豆皮`,开中小火,等待 40 分钟。(中途可适当翻搅防止粘锅); +- 打开锅盖,待汤汁快没有的时候开大火收汁(切记不可收干); +- 加入 2-3g `盐`,翻炒一下,就可以出锅了。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/羊排焖面/羊排焖面.jpg b/data/C8/cook/dishes/meat_dish/羊排焖面/羊排焖面.jpg new file mode 100644 index 0000000..494a2d0 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/羊排焖面/羊排焖面.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d5b6a4e37d5ba54623c406c470e42086bb211b1d049f3cf4074a96162c331c1 +size 550609 diff --git a/data/C8/cook/dishes/meat_dish/羊排焖面/羊排焖面.md b/data/C8/cook/dishes/meat_dish/羊排焖面/羊排焖面.md new file mode 100644 index 0000000..e9eb418 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/羊排焖面/羊排焖面.md @@ -0,0 +1,59 @@ +# 羊排焖面的做法 + +![羊排焖面](./羊排焖面.jpg) +羊排焖面是一道硬菜,适合聚会时候大展身手。缺点就是有点花时间,优点就是好吃,而且一道菜补齐人体所需的三大营养物质。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 带皮羊排肉 +- 青椒 +- 甜椒 +- 青椒 +- 大葱 +- 花椒 +- 干辣椒 +- 生姜 +- 白砂糖 +- 老抽 + +## 计算 + +1 人份 * 2 顿 = 2 人份 + +- 带皮羊排 500g +- 青椒,甜椒 各 2 个 + +## 操作 + +- 羊肉冷水下锅焯水,水开了之后把血沫撇掉,捞出羊肉。 +- 切好生姜( 4 片),放入干辣椒与花椒在碗里备用。 +- 在炒锅加入油。(多一点也没关系) +- 油热之后,放入白砂糖,给羊肉炒出焦糖色。 +- 羊肉水份炒干之后,放入盐、老抽,以及备好的调味料。 +- 加入清水没过羊肉,大火煮沸之后,让其继续煮 10 分钟,之后小火炖煮 30 分钟。 +- 在此期间,可以和面。和面的量以及操作方法在附加内容里讲解 *(注 1)。 +- 放入青椒,甜椒,大葱,以及面皮进行翻炒。 +- 翻炒均匀之后,即可出锅。 + +*注 1:可以用超市的面条代替,但是尽量选择宽面。 + +## 附加内容 + +(和面小指南 之 材料) + +- 中筋面粉 300 g +- 盐 3 g +- 水 180 ml + +(和面小指南 之 操作) + +- 先把材料混合均匀,加水边和边搅拌,然后把面团和到光滑 +- 醒面( 10 分钟) +- 再次和面到光滑 +- 醒面( 5 分钟) +- 把面团揉成条,切成 6 到 8 个小剂子 +- 抹上油,等待 5 分钟 +- 把面团剂子擀成面皮 +- 放入锅中焖煮 4 分钟(一片一片操作) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/老妈蹄花/result1.jpg b/data/C8/cook/dishes/meat_dish/老妈蹄花/result1.jpg new file mode 100644 index 0000000..215c388 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/老妈蹄花/result1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49302b6cd77697e1061e7dd6dc5a9dba4e2ea3551c0d2ce27aa413628798a81f +size 601320 diff --git a/data/C8/cook/dishes/meat_dish/老妈蹄花/result2.jpg b/data/C8/cook/dishes/meat_dish/老妈蹄花/result2.jpg new file mode 100644 index 0000000..01e6124 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/老妈蹄花/result2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1027277f806d2e2b483a7bd71d1e8db5055dc5d06ad8d6b035a43855e9c0333 +size 950451 diff --git a/data/C8/cook/dishes/meat_dish/老妈蹄花/result3.jpg b/data/C8/cook/dishes/meat_dish/老妈蹄花/result3.jpg new file mode 100644 index 0000000..fac0ad4 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/老妈蹄花/result3.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebf3b29cc7e217f90d9d107d5b8cda37f447f4fcb5decf38305588138f958053 +size 612599 diff --git a/data/C8/cook/dishes/meat_dish/老妈蹄花/老妈蹄花.md b/data/C8/cook/dishes/meat_dish/老妈蹄花/老妈蹄花.md new file mode 100644 index 0000000..0f3e087 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/老妈蹄花/老妈蹄花.md @@ -0,0 +1,58 @@ +# 老妈蹄花的做法 + +![result 3](./result3.jpg) + +红烧猪蹄营养丰富,口感细腻,软烂脱骨,配上酸辣汁简直太香! + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 猪蹄(尽量选择猪前蹄:肉多筋多骨头少) +- 葱 +- 姜 +- 料酒 +- 生抽 +- 白芷 +- 当归(可选) +- 鸡精 +- 盐 +- 蒜 +- 小米椒 +- 白胡椒粉 +- 生抽 +- 香醋 +- 花椒油 +- 油泼辣子(可选) +- 白芸豆(没有可用海带) + +## 计算 + +- 猪蹄:3 根 +- 白芸豆:200g +- 当归:2g +- 白胡椒粉:5g +- 姜片:30g +- 当归:2g +- 蒜末:8g +- 鸡精:2g +- 生抽:25g +- 葱花:10g + +## 操作 + +### 开始制作 + +- 200g 白芸豆提前一晚清水浸泡备用 +- 准备猪前蹄,买菜的时候让师傅从中间劈开,用喷火枪去除毛囊,拿回家清洗 +- 冷水锅中加入猪蹄、大葱段、姜片、料酒,焯水十分钟,撇去浮沫,捞出洗干净备用 +- 高压锅中放入猪蹄、当归、白芷、白胡椒粉、姜片,上汽后压三十分钟,放入白芸豆,再压十分钟,这个时候如果汤底是奶白色,那么恭喜是正确的(如果中途需要加水,只能加热水) + +![result1](./result1.jpg) + +- 揭盖后加入盐、鸡精、葱花调味 +- 调制灵魂汁子:放入葱、蒜、小米椒,白胡椒粉、生抽、香醋、油泼辣子、花椒油、猪蹄原汤 + ![result2](./result2.jpg) +- 灵魂汁子,浇给 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/老式锅包肉/老式锅包肉.md b/data/C8/cook/dishes/meat_dish/老式锅包肉/老式锅包肉.md new file mode 100644 index 0000000..0cea883 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/老式锅包肉/老式锅包肉.md @@ -0,0 +1,105 @@ +# 老式锅包肉的做法 + +锅包肉是东北名菜,创始于光绪年间哈尔滨道台府厨师郑兴文之手。老式锅包肉的酸味来源于白醋汁,口味酸甜酥脆。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 猪通脊肉 +- 大葱 +- 姜 +- 蒜 +- 胡萝卜(可无) +- 香菜 +- 白醋(建议使用 9 度的醋,这样才会有较为突出的老式锅包肉特有的醋香) +- 白糖 +- 料酒 +- 盐 +- 味精 +- 土豆淀粉 +- 中筋面粉 +- 小苏打 +- 白熟芝麻(可无) +- 食用油 + +## 计算 + +每份(约 2 人份): + +- 猪通脊肉 300g +- 大葱 50g +- 姜 30g +- 蒜 3-4 瓣 +- 胡萝卜 10g(可无) +- 香菜 10g +- 白熟芝麻 5g(可无) +- 白醋 40g +- 白糖 40g +- 料酒 20ml +- 盐 8g +- 味精 5g +- 米醋 5ml(可无) +- 土豆淀粉 210g +- 中筋面粉 70g +- 小苏打 5g +- 食用油 1000ml(用于炸制) + +## 操作 + +1. **处理猪肉**: + - 将猪通脊肉切成厚度 8mm 的均匀肉片,去除白色筋膜。 + - 用清水冲洗肉片,去除血水。 + - 加入小苏打 5g,抓匀,静置 5 分钟。 + - 用清水冲洗 1-2 次,去除多余小苏打。 + +2. **腌制肉片**: + - 在肉片中加入盐 4g、料酒 5ml,拌匀,腌制 15 分钟。 + +3. **准备挂浆**: + - **方法一**: + - 将土豆淀粉 100g 加入 200ml 清水,搅匀,静置 20 分钟。 + - 倒出上层 2/3 的清水,保留底部淀粉浆,搅匀至酸奶状。 + - **方法二(推荐)**: + - 将土豆淀粉 210g 和中筋面粉 70g 混合。 + - 少量多次加入清水,搅拌至酸奶状,提起可拉丝,浆糊能在盆中堆积。 + - 加入食用油 10ml,小苏打 1g,搅拌均匀。 + +4. **挂浆**: + - 将腌制好的肉片放入浆糊中,拌匀,使每片肉均匀裹上浆。 + +5. **调制糖醋汁**: + - 混合白糖 40g、白醋 40g、盐 4g、味精 5g、米醋 5ml(可无),搅拌均匀,备用。 + +6. **准备配菜**: + - 大葱、姜、胡萝卜切丝,香菜切段,蒜切片。 + +7. **炸制肉片**: + - **第一次炸制**: + - 锅中加入食用油,加热至 150℃(五成热)。 + - 将肉片逐片放入油中,炸至表面定型,颜色浅黄,约 30 秒,捞出备用。 + - **第二次炸制**: + - 油温升至 170℃(六成热)。 + - 将所有肉片放入油中,炸至外壳金黄酥脆,约 1 分钟,捞出备用。 + - **第三次炸制(可选)**: + - 油温升至 200℃(七成热)。 + - 将肉片快速复炸 10-20 秒,增强酥脆度,捞出沥油。 + +8. **炒制**: + - 锅中留 20ml 底油,加热后放入姜丝、蒜片,煸香 10 秒。 + - 倒入调好的糖醋汁,大火加热至沸腾,熬至汤汁粘稠,约 30-60 秒。 + - 放入炸好的肉片、葱丝、胡萝卜丝、香菜段,快速翻炒 3 次,使汤汁均匀裹在肉片上。 + +9. **出锅装盘**: + - 将锅包肉盛入盘中,撒上白熟芝麻(可无),即可上桌。 + +## 附加内容 + +- **注意事项**: + 1. 肉片厚度应为 8mm,过厚过薄都会影响口感。 + 2. 炸制时控制油温,避免外壳过深或不酥脆。 + 3. 熬糖醋汁时,注意熬至粘稠但不结块,避免变成糖浆。 + +- **参考资料**: + - [老饭骨版本](https://www.bilibili.com/video/BV19F411b7ME) + - [老东北美食版本](https://www.bilibili.com/video/BV1wa4y1C7Cd) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/肉饼炖蛋.md b/data/C8/cook/dishes/meat_dish/肉饼炖蛋.md new file mode 100644 index 0000000..779ab8f --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/肉饼炖蛋.md @@ -0,0 +1,33 @@ +# 肉饼炖蛋的做法 + +肉饼炖蛋是一道传统的中国家常菜,也是一道非常受欢迎的下饭菜。初学者只需要 20 分钟即可完成。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 猪肉末 +- 鸡蛋 +- 料酒 +- 生抽 +- 白胡椒粉 +- 芝麻香油 + +## 计算 + +- 猪肉末 300g +- 鸡蛋 2 个 +- 料酒 10ml +- 生抽 20ml +- 白胡椒粉 5g +- 芝麻香油 10-15ml + +## 操作 + +- 在碗中加入猪肉末、料酒、生抽、白胡椒粉、鸡蛋和芝麻香油,搅拌均匀。 +- 将调好味的猪肉末铺在盘子里,肉末中间用勺子挖一个洞,往洞中打入 1 个鸡蛋。 +- 锅中加水至 1/4 高度,水烧开后,将盘子放入锅中,盖上锅盖,蒸 15 分钟。 + +## 附加内容 + +- 在取出肉饼炖蛋时,注意盘子很烫,请小心操作。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/芥末罗氏虾/芥末罗氏虾.md b/data/C8/cook/dishes/meat_dish/芥末罗氏虾/芥末罗氏虾.md new file mode 100644 index 0000000..871640f --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/芥末罗氏虾/芥末罗氏虾.md @@ -0,0 +1,62 @@ +# 芥末罗氏虾的做法 + +![芥末罗氏虾成品](./芥末罗氏虾成品.jpg) + +本菜品可替换成任意虾种类,包括但不限于基围虾、花虾、黑虎虾等。鲜香入味、芥末风味十足、吃完吮指,且操作十分简单。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 罗氏虾 +- 蒜 +- 青芥末 +- 生抽 +- 生粉 +- 胡椒粉 +- 白糖 +- 蚝油 +- 盐 +- 小米辣(不吃辣可不放或替换成红菜椒) +- 黄油 +- 食用油 + +## 计算 + +每份(约 2 人份): + +- 罗氏虾 250g +- 蒜 1-2 个 +- 青芥末 20g,用于碗汁 +- 生粉 10g,用于碗汁 +- 生抽 30g,用于碗汁 +- 胡椒粉 5g,用于碗汁 +- 白糖 3g,用于碗汁 +- 蚝油 15g,用于碗汁 +- 盐 3g,用于碗汁 +- 小米辣 1-2 个 +- 黄油 20g +- 食用油 80ml + +## 操作 + +1. **处理虾**: + - 将虾从背部切开,去除虾线和沙袋,也可从腹部切开,炸出来会胀开,成菜比较漂亮 + - 用清水洗干净,控干水分后可拍上生粉,也可不拍 + +2. **蒜蓉及碗汁处理**: + - 将 2 颗大蒜切成蒜末 + - 准备碗汁,放入生抽、蚝油、白糖、胡椒粉、盐,依据个人口味挤入芥末,加清水稀释后加入生粉化开 + +3. **炒制过程**: + - 锅热倒入食用油,大概能覆盖锅底 + - 放入控干水分的罗氏虾,慢慢煎制 + - 虾油煎出来后(表现为锅中出现大量气泡),加入准备好的蒜蓉及小米辣 + - 闻到蒜蓉的香味后,加入黄油 + - 黄油融化后翻拌均匀,加入准备好的碗汁 + - 盖锅盖焖煮 2 分钟汤汁浓稠后出锅 + +## 附加内容 + +- **注意事项**: + 1. 黄油入锅后不宜炸制太久,融化翻拌均匀即可烹入碗汁 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/芥末罗氏虾/芥末罗氏虾成品.jpg b/data/C8/cook/dishes/meat_dish/芥末罗氏虾/芥末罗氏虾成品.jpg new file mode 100644 index 0000000..1c6e71a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/芥末罗氏虾/芥末罗氏虾成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a837145efd525dd1b9af6dcdb78759ef70b064ad82a36e0821a02ac94b13fe2 +size 436219 diff --git a/data/C8/cook/dishes/meat_dish/茭白炒肉/1.jpeg b/data/C8/cook/dishes/meat_dish/茭白炒肉/1.jpeg new file mode 100644 index 0000000..8a30441 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/茭白炒肉/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9879cdd27a10433c7f7ebb519dc938b7b06b936b9ecf8eb2b9fa713c800969f9 +size 167692 diff --git a/data/C8/cook/dishes/meat_dish/茭白炒肉/2.jpeg b/data/C8/cook/dishes/meat_dish/茭白炒肉/2.jpeg new file mode 100644 index 0000000..e035852 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/茭白炒肉/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec7e19057e45048f7c3158b795f93c42ae8e2d922dc0da22f95865cd69e8a139 +size 153234 diff --git a/data/C8/cook/dishes/meat_dish/茭白炒肉/茭白炒肉.md b/data/C8/cook/dishes/meat_dish/茭白炒肉/茭白炒肉.md new file mode 100644 index 0000000..70ce9e3 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/茭白炒肉/茭白炒肉.md @@ -0,0 +1,53 @@ +# 茭白炒肉的做法 + +茭白味道鲜美,有一定营养价值 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 茭白 +* 瘦肉 +* 淀粉 +* 食用油 +* 鸡精 +* 姜 +* 蒜 +* 料酒 +* 盐 + +## 计算 + +每份: + +* 茭白 2 根 +* 瘦肉 100 g +* 淀粉 15 g +* 食用油 30 ml +* 鸡精 5 g +* 姜 1 片 +* 蒜 1 个 +* 料酒 5 ml +* 盐 2 g + +## 操作 + +### 准备 + +* 茭白切片,每片厚度 0.5 cm +* 瘦肉切条,厚度 0.3-0.5 cm,加入料酒、生粉、盐、水搅拌 +* 姜切片、蒜头剁碎 + +### 制作 + +* 起锅水烧开,放入茭白,水煮 60-90 S 后取出沥干 +* 起锅,倒入 15 ml 油,倒入瘦肉,反复翻炒 60 S 取出 +* 起锅,倒入 15 ml 油,倒入姜、蒜翻炒 30S,加入茭白继续翻炒 30 S +* 继续加入瘦肉翻炒 60 S,加入 20 ml 水,加入盐、鸡精后翻炒 60S 出锅 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) + +## 附加内容 + +* 最后一个步骤,可以考虑加蚝油、生抽代替盐上色 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/荔枝肉/1.jpeg b/data/C8/cook/dishes/meat_dish/荔枝肉/1.jpeg new file mode 100644 index 0000000..35ae6e7 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荔枝肉/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d72a37a69f9d1faf6b1acd7c4cfbf19cad0c8ed4da59367ca6c4feef513c5737 +size 175852 diff --git a/data/C8/cook/dishes/meat_dish/荔枝肉/2.jpeg b/data/C8/cook/dishes/meat_dish/荔枝肉/2.jpeg new file mode 100644 index 0000000..e649275 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荔枝肉/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dee79059efdff92ad75aae894dbee9b509dffbfa3832854b5d4bd92684c07c6c +size 137791 diff --git a/data/C8/cook/dishes/meat_dish/荔枝肉/3.jpeg b/data/C8/cook/dishes/meat_dish/荔枝肉/3.jpeg new file mode 100644 index 0000000..bf8b863 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荔枝肉/3.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93c0f369919f5c3f6ba73b730cb09ebe16f658a399033f7a54fe9beb9ca30029 +size 184261 diff --git a/data/C8/cook/dishes/meat_dish/荔枝肉/4.jpeg b/data/C8/cook/dishes/meat_dish/荔枝肉/4.jpeg new file mode 100644 index 0000000..d5bfe4b --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荔枝肉/4.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44e8417d678358f92a4fa151df653ef07b43e3d30023478da08231a5c466f817 +size 175823 diff --git a/data/C8/cook/dishes/meat_dish/荔枝肉/5.jpeg b/data/C8/cook/dishes/meat_dish/荔枝肉/5.jpeg new file mode 100644 index 0000000..5703372 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荔枝肉/5.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:851aa648571fa6118357d6e5ee67feb506e21b7af6a59b5b80a4eaa107708f73 +size 146027 diff --git a/data/C8/cook/dishes/meat_dish/荔枝肉/6.jpeg b/data/C8/cook/dishes/meat_dish/荔枝肉/6.jpeg new file mode 100644 index 0000000..be1fc7c --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荔枝肉/6.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6605f422c3c89789f2a930fa76ca6d0a61dc9d1522f213ed2840d7e0632f1f99 +size 192385 diff --git a/data/C8/cook/dishes/meat_dish/荔枝肉/7.jpeg b/data/C8/cook/dishes/meat_dish/荔枝肉/7.jpeg new file mode 100644 index 0000000..0f2d0df --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荔枝肉/7.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da5f72c8a7e58c2264e737a6e32879ca93103b6ca2c9f48270fd345033fb3586 +size 181448 diff --git a/data/C8/cook/dishes/meat_dish/荔枝肉/荔枝肉.md b/data/C8/cook/dishes/meat_dish/荔枝肉/荔枝肉.md new file mode 100644 index 0000000..c2b2a13 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荔枝肉/荔枝肉.md @@ -0,0 +1,66 @@ +# 荔枝肉的做法 + +荔枝肉独具闽菜特点,味道酸甜可口。是福州地区比较常见的一道菜肴 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 瘦肉 +* 凤梨 +* 鸡蛋 +* 食用油 +* 白砂糖 +* 淀粉 +* 生抽 +* 鸡精 +* 姜末 +* 芝麻 +* 番茄酱 +* 香醋 + +## 计算 + +每份: + +* 鲜香菇 2 朵 +* 蟹味菇 30 g +* 瘦肉 150 g +* 凤梨 100 g +* 鸡蛋 1 个 +* 食用油 500 ml +* 白砂糖 5 g +* 淀粉 100 g +* 生抽 5 ml +* 鸡精 5 g +* 姜末 5 g +* 芝麻 2 g +* 番茄酱 20 g +* 香醋 2 ml + +## 操作 + +* 瘦肉切块(每块 2-3 cm ),放入大碗中,加入鸡蛋 1 个 、生粉 50 g 、生抽 3 ml 、鸡精 2 g +* 充分搅拌,直至生粉包裹住瘦肉块(太稀则继续加生粉,太干则加水),然后加入 5 ml 油,在充分搅拌后备用 +* 在准备一个碗,加入番茄酱、鸡精 3 g 、生抽 2 ml 、姜末、白砂糖、生粉 10 g \香醋、凉水 200 ml ,充分搅拌后备用 +* 切一个凤梨, 准备 6 个 (每个 1.5-2 cm)凤梨块 +* 起锅烧油,倒入 500 ml 油,一直烧油直到听到油炸声 +* 将瘦肉一个一个放入锅中(切记不可以整碗倒入),保证每个肉不要粘在一起 +* 全部放入瘦肉后,每 30 S 用勺子来回两面翻转瘦肉块,直至瘦肉块表面金黄 +* 取出瘦肉,一分钟后倒入油锅中继续炸,直至瘦肉块表面出现焦黄后,取出放入大碗备用 +* 起锅,倒入汤汁,30 S 后倒入瘦肉块、凤梨块,充分翻炒后 出锅 +* 摆上芝麻 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) +![示例菜成品](./3.jpeg) +![示例菜成品](./4.jpeg) +![示例菜成品](./5.jpeg) +![示例菜成品](./6.jpeg) +![示例菜成品](./7.jpeg) + +## 附加内容 + +* 更多情况下,福州当地会选用马蹄(解腻)和马铃薯(洗油),因为疫情期间买不到,所以选用了凤梨 +* 闽菜以甜为主,如果吃不惯的可以放弃白糖 +* 可以通过勺子敲打瘦肉块,听到声响来判断是否炸透瘦肉 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/荷兰豆炒腊肠/1.png b/data/C8/cook/dishes/meat_dish/荷兰豆炒腊肠/1.png new file mode 100644 index 0000000..af6fe2c --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荷兰豆炒腊肠/1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b8091a3fbba4e25330fccefd896a5b5a7feffbe60f18d0bebb7e91a5da5be00 +size 233062 diff --git a/data/C8/cook/dishes/meat_dish/荷兰豆炒腊肠/2.png b/data/C8/cook/dishes/meat_dish/荷兰豆炒腊肠/2.png new file mode 100644 index 0000000..961cbdf --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荷兰豆炒腊肠/2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8699a7dbe78ebac0709e38c095381f3a604b13fc3ce6bbc71a4eef97019c2d2c +size 246925 diff --git a/data/C8/cook/dishes/meat_dish/荷兰豆炒腊肠/荷兰豆炒腊肠.md b/data/C8/cook/dishes/meat_dish/荷兰豆炒腊肠/荷兰豆炒腊肠.md new file mode 100644 index 0000000..a41a976 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/荷兰豆炒腊肠/荷兰豆炒腊肠.md @@ -0,0 +1,46 @@ +# 荷兰豆炒腊肠的做法 + +![荷兰豆炒腊肠](./1.png) + +荷兰豆炒腊肠是一道营养丰富,口感清爽,有利于开胃助食,增进食欲的美味菜肴。荷兰豆中富含人体所需的各种营养物质,尤其是含有优质蛋白质,可以提高机体的抗病能力和康复能力。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 荷兰豆 +- 腊肠 +- 生抽 +- 食用油 + +## 计算 + +下面是一人份。 + +每份: + +- 荷兰豆大约 50 个 +- 腊肠约 100 g +- 食用油 10ml +- 生抽 10ml + +## 操作 + +- 把荷兰豆去掉蒂,有时间的也可以同时把尾部去掉 + +- 买腊肠之前可以问老板是生的还是熟的,如果是生的,需要提前蒸一下,如果是熟的可以直接使用 + +- 把荷兰豆清洗一下,然后焯一下水,大概 45s,荷兰豆焯至变色即可,捞出过凉水备用 + +- 热锅,锅内放入大约 10ml 食用油。等待 10 秒让油温升高 + +- 放入腊肠,保持翻炒至腊肠*微微卷边*,注意这里一定要**保持小火**,小到不能小的那种,不然容易糊 + +- 放入荷兰豆,转为中大火,翻炒 30s 放入生抽,接着再翻炒 20-30s 即可 + + ![荷兰豆炒腊肠](./2.png) + +## 附加内容 + +- 在制作过程中没有放盐,是因为腊肠本身会有一些味道,同时生抽也会有一些咸味。 +- 腊肠虽然味道不错,但属于不太健康的食物,建议少放。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/萝卜炖羊排.md b/data/C8/cook/dishes/meat_dish/萝卜炖羊排.md new file mode 100644 index 0000000..f77f72e --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/萝卜炖羊排.md @@ -0,0 +1,49 @@ +# 萝卜炖羊排的做法 + +萝卜炖羊排是一道常见家常菜,老少皆宜。一般初学者只需要最多 2 小时即可完成。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 羊排 +- 白萝卜 +- 大葱 +- 花椒 +- 白芷(可选) +- 姜 +- 料酒或者黄酒 +- 食用盐 +- 冰糖 +- 水 + +## 计算 + +每份: + +- 羊排 400g +- 白萝卜一根 +- 大葱一根 +- 花椒 10 粒 +- 姜 10g ,一般买一头姜,从中切大约 4 片即可 +- 料酒或者黄酒 30ml-40ml +- 食用盐 10g +- 冰糖 2-4 粒 +- 水:没过食材的量,需要 1000ml + +## 操作 + +- 萝卜去皮、滚刀切成 3-5cm 的大块,备用 +- 羊排在购买时可以让卖家切好,因为家用刀一般难以切动,备用 +- 羊肉冷水下锅,加入一半的料酒,一半的葱姜,煮 10 分钟去掉血腥,(可选)把焯的过程中出现的血沫子可以用勺子盛出来 +- 另起一锅冷水,放入切好的白萝卜,放入一半的冰糖,等水开后煮 5 分钟去掉白萝卜的辣味 +- 盛出来焯好的羊排,放入高压锅中,加水没过所有食材后再增加大约 300ml 的水 +- 将剩余的葱姜料酒,花椒,冰糖,白芷(可选),盐放入锅中,盖锅等待上汽后计时,中火炖大约 15 分钟。 + - 如没有高压锅,则放入普通锅中,炖大约 40 分钟到 1 小时。 +- 关火,等待高压锅放气完毕,开盖,加入之前焯好的萝卜,调味,加入 3-10g 的食盐或者水,品尝汤的咸淡, +- 再开火,中火,高压锅上汽再炖 10 分钟,普通锅盖盖再炖 20 分钟 +- 关火,盛盘 + +## 附加内容 + +- 操作时,需要注意观察沸腾的水位线,如发现低于 2/3 的食材应加热水至没过食材。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/蒜苔炒肉末.md b/data/C8/cook/dishes/meat_dish/蒜苔炒肉末.md new file mode 100644 index 0000000..0e5d2fd --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/蒜苔炒肉末.md @@ -0,0 +1,42 @@ +# 蒜苔炒肉末的做法 + +蒜苔炒肉末是一道简单易做的菜。这是一道北方家常菜,以做法简单、味道上乘的特点,在广大北方人民群众中备受喜爱。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 五花肉薄片 +- 蒜苔 +- 食用盐 +- 生抽 +- 食用油 +- 蒜瓣 + +## 计算 + +1 人食用版本 + +- 蒜苔 1 扎(每扎蒜苔约 190g) +- 五花肉薄片 4 片(约 20g) +- 食用油 10ml +- 蒜瓣 2 瓣 +- 生抽 15ml +- 食盐 2g + +## 操作 + +- 蒜苔切成 5cm 小段,备用 +- 五花肉切成 5mm * 5cm 丝状,备用 +- 蒜瓣拍碎切成末,备用 +- 热锅,锅内放入 10ml 食用油。等待 10 秒让油温升高 +- 放入蒜末,中火翻炒 **10 秒** 将蒜末炒出香味 +- 放入五花肉和 5ml 生抽,中火翻炒 **30 秒** 将肉炒熟并上色 +- 将蒜苔放入锅内并加入 10ml 生抽,翻炒 **30 秒** +- 锅内加入 20g 水,中火翻炒 **5 分钟** 将蒜苔炒至稍稍变软 +- 最后加入 2g 食盐,中火翻炒 **30 秒**,即可出锅装盘 + +## 附加内容 + +- 加入食盐前可尝一下咸淡,自行决定是否增减盐量 +- 选用五花肉薄片是因为切肉简单且不用腌制即可入味 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/虎皮肘子.md b/data/C8/cook/dishes/meat_dish/虎皮肘子.md new file mode 100644 index 0000000..0d1ce45 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/虎皮肘子.md @@ -0,0 +1,108 @@ +# 虎皮肘子的做法 + +虎皮肘子是一道传统名菜,以猪肘为主料,通过先烧再炸后炖三个步骤使肘子皮呈现出虎皮状。肘子皮软烂入味,肥而不腻,瘦肉松软可口。这道菜是逢年过节让老辈子闭嘴猛炫的不二之选,可谓是救命法宝。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 猪前肘 +- 食用植物油 +- 冰糖 +- 盐 +- 老抽 +- 生抽 +- 白醋 +- 香叶 +- 肉桂皮 +- 豆蔻 +- 花椒 +- 大料 +- 淀粉 +- 葱 +- 姜 +- 蒜 +- 水 +- 料酒 + +## 计算 + +- 1 汤匙 = 15ml +- 1 茶匙 = 5ml + +|原料|数量|单位| +|:---:|:---:|:---:| +|猪前肘|1|个| +|食用植物油|1|桶| +|冰糖|5|桶| +|盐|1-2|茶匙| +|老抽|1|茶匙| +|生抽|1|汤匙| +|白醋|1|汤匙| +|香叶|3|片| +|肉桂皮|2-3|克| +|豆蔻|3|个| +|花椒|8-12|个| +|大料|2-4|个| +|淀粉|1|汤匙| +|葱|2|棵| +|姜|6|克| +|蒜|6|粒| +|料酒|2|汤匙| + +## 操作 + +### 预处理 + +- 猪肘解冻后水泡 1 小时去除血水。 +- 如有火焰喷枪,则使用火焰喷枪灼烧**猪肘皮**表面至**棕黑色**以去除猪毛,破坏汗腺。注意不要长时间炙烤同一个位置以避免烧焦,当猪肘皮几乎完全呈现棕黑色时则停止灼烧。 +- 如无火焰喷枪,将铁锅烧至 200 以上,将猪肘直接放入锅内,用锅铲或筷子使猪肘皮充分接触铁锅表面,当猪肘皮与铁锅接触位置呈现出棕色时,更换位置继续烫猪肘皮,直到整个猪肘被充分烫过。注意再次过程中注意铁锅温度,不要使铁锅红热。 +- 使用清洁球在水中刷洗猪肘,将其表面烧焦的部分去除。刷洗结束后,猪肘再次呈现出未被灼烧前的状态。 +- 将猪肘置于铁锅中,加尽量多的冷水,具体视铁锅深度与猪肘大小而定,在保证可以拿得动铁锅及其内容物的情况下,能浸没猪肘 3/4 以上为最佳。 + +### 去腥 + +- 取 1 棵葱的葱白,分成 3 段,放入锅中。 +- 取 3 粒蒜,分别用刀身拍扁,放入锅中。 +- 取 3 克姜,放入锅中。 +- 将 2 汤匙料酒加入锅中。 +- 锅中水烧开后,等待五分钟,随后将猪肘取出,捡出锅中所有配料,更换容器保留所有肉汤备用。 + +### 油炸 + +- 向锅中加入冷油,以之前水量为参考,能浸没猪肘 3/5 以上为佳,开中火加热。 +- 当[油温](tips/advanced/油温判断技巧.md)达到五成时,转为小火,放入猪肘油炸。 +- 在油炸过程中烹饪者应注意人身安全。 +- 在油炸过程中,使用锅铲或其他耐高温厨具将锅中的油均匀淋到猪肘未被浸没的部分,如果条件允许应以 3 分钟的间隔翻转猪肘,使其油炸均匀。 +- 油炸过程持续大约 20 分钟,当观察到猪肘皮已经全部呈现出浅棕色,而瘦肉部分已经微焦,则可捞出备用。 +- 炸制完后的油可用于制作其他油炸类食物,但注意不要使用太多次。 + +### 炒糖色 + +- [炒糖色](../../tips/advanced/糖色的炒制.md)200ml 备用。 + +### 炖煮 + +- 将猪肘加入高压锅内,加入所有肉汤、糖色、香叶、肉桂皮、豆蔻、花椒、大料、老抽、生抽、白醋。如果喜欢甜口,可以再额外加入 2-3 克冰糖。 +- 取 1 棵葱的葱白,分成 3 段,放入锅中。 +- 取 3 粒蒜,分别用刀身拍扁,放入锅中。 +- 取 3 克姜,放入锅中。 +- 盖上锅盖,加压炖煮 40 分钟。 + +### 收汁 + +- 在炖煮期间调制水淀粉。取碗 1 个,加入 1 汤匙淀粉,100ml 水,搅拌使其成为白色悬浊液 +- 炖煮时间结束后,打开高压锅锅盖,捡出锅中所有的配料,只保留猪肘。 +- 将高压锅中剩余的肉汤转移至铁锅内,猪肘转移至盘子或盆内 +- 将铁锅置于灶台上,开大火。在收汁过程中可以用筷子头蘸取锅内汤汁判断咸淡,并根据口味添加盐。注意,汤汁多的时候味道会比汤汁少的时候味道更淡,加入盐时需要考虑这一点。 +- 当肉汤沸腾时,注意观察剩余肉汤余量 +- 当剩余肉汤少于原肉汤体积的 1/2 时,再次搅拌之前调制好的水淀粉,并加入一半 +- 等待肉汤沸腾,加入剩下的一半 +- 等待肉汤沸腾,沸腾后等待 1-2 分钟关火,此时锅内的肉汤呈红棕色粘稠状 +- 用汤匙舀起肉汤均匀地淋在猪肘上,尽量使猪肘的每一处都淋到汤汁。如果在猪肘被完全淋到前汤汁已经用完则可直接上桌,否则剩余汤汁不需要再淋,可直接上桌。 + +## 附加内容 + +- 参考资料:[Bilibili老饭骨的视频教程](https://www.bilibili.com/video/BV1P4421c7s5) + + \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/蚂蚁上树.md b/data/C8/cook/dishes/meat_dish/蚂蚁上树.md new file mode 100644 index 0000000..5623bb2 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/蚂蚁上树.md @@ -0,0 +1,51 @@ +# 蚂蚁上树的做法 + +蚂蚁上树是一道经典的川菜,主要材料为粉丝和肉末。它咸香微辣、入味透彻,粉丝软滑爽口,肉末细嫩鲜香。全程只需 20 分钟,是非常适合家庭操作的一道菜。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 红薯粉丝 +- 猪肉末(或牛肉末) +- 郫县豆瓣酱 +- 生抽 +- 老抽 +- 食用油 +- 蒜末、姜末 +- 小葱(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 红薯粉丝 80g(干重) +- 猪肉末 150g +- 郫县豆瓣酱 15g +- 生抽 10ml +- 老抽 5ml +- 食用油 10ml +- 蒜末 10g +- 姜末 5g +- 清水 300ml(用于煮粉丝) + +## 操作 + +- 红薯粉丝提前泡软,泡水时间为 20 分钟,备用 +- 将蒜、姜分别剁碎,备用 +- 锅烧热,加入 10ml 食用油,加入蒜末、姜末炒香 +- 加入猪肉末翻炒至**肉色发白且微微出油** +- 加入郫县豆瓣酱,炒至**红油析出** +- 加入生抽和老抽,翻炒均匀 +- 倒入 300ml 清水,煮沸 +- 放入泡软沥干的粉丝,用筷子轻轻拨动防止粘连 +- 中小火煮约 5 分钟,直至粉丝**完全吸收汤汁**、呈现微微收干状态 +- 依据口味可撒入小葱末,关火装盘 + +## 附加内容 + +- 粉丝不建议煮太久,易断且口感变差;若时间过长汤汁应适当减少 +- 郫县豆瓣酱含盐量较高,可根据口味酌情减少生抽用量 +- 可加入 0.5g 白胡椒粉调味,风味更佳 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/血浆鸭/血浆鸭(微辣).jpg b/data/C8/cook/dishes/meat_dish/血浆鸭/血浆鸭(微辣).jpg new file mode 100644 index 0000000..02d00b7 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/血浆鸭/血浆鸭(微辣).jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca83bd9a682db12c20260f4d0e158237f45144c182d50c1f11d37388070eeed0 +size 236142 diff --git a/data/C8/cook/dishes/meat_dish/血浆鸭/血浆鸭(特辣).jpg b/data/C8/cook/dishes/meat_dish/血浆鸭/血浆鸭(特辣).jpg new file mode 100644 index 0000000..7664201 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/血浆鸭/血浆鸭(特辣).jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78c19e37130ee424cdaf18cdc9284a6a5a1c7c3fdb122044c58b84eba4d052be +size 403802 diff --git a/data/C8/cook/dishes/meat_dish/血浆鸭/血浆鸭.md b/data/C8/cook/dishes/meat_dish/血浆鸭/血浆鸭.md new file mode 100644 index 0000000..9650d0d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/血浆鸭/血浆鸭.md @@ -0,0 +1,57 @@ +# 血浆鸭的做法 + +![血浆鸭(特辣)](./血浆鸭(特辣).jpg) + +![血浆鸭(微辣)](./血浆鸭(微辣).jpg) + +血浆鸭是湖南武冈特色传统名菜,香、脆可口,由于醋血的作用,不仅鸭骨酥而脆,就是姜和辣椒也变得不辣而甜净。一般初学者只需要 2 小时就可以完成。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 鲜仔鸭肉 +- 鲜鸭血(宰杀鸭子时加醋接鸭血,用筷子顺时针搅拌防凝固) +- 姜 +- 蒜仔 +- 葱 +- 辣椒 +- 酒(或者白酒、啤酒、米酒皆可) +- 生抽 +- 料酒 +- 盐 +- 鸡精 + +## 计算 + +每份(建议 2-4 人份): + +- 鲜仔鸭肉 2000g +- 鲜鸭血 250ml +- 姜 6 片 (根据个人吃辣喜好程度可多放 1-3 片姜) +- 蒜仔 6 瓣 +- 香葱 2 根,切好备用 +- 辣椒 1000g(根据个人吃辣喜好程度可选青椒,线椒,美人椒等,喜欢吃辣可增加 5-8 个小米辣或朝天椒,切好备用) +- 酒(任选其一): + - 高度白酒 50ml + 水 150ml + - 啤酒 200ml + - 米酒 200ml +- 生抽 10ml +- 料酒 30ml +- 盐 8g +- 鸡精 5g + +## 操作 + +- 鲜仔鸭肉切成约 3cm 小块,加料酒、姜片,去除血水。 +- 炒锅烧热,放入约 100ml 食用油,大火待油烧开,放入腌制好的鲜鸭肉,不断翻炒。 +- 待鸭肉完全变色(肉眼可见泛白),放入酒,再加入 200ml 开水,刚好淹没鸭肉即可,盖上锅盖中火煮 15 分钟。 +- 水开之后,打开锅盖放入姜蒜,翻炒一遍,盖上锅盖持续加热 10 分钟。 +- 打开锅盖放入辣椒,不断翻炒,待至肉眼可见辣椒炒软,放入鲜鸭血,此时需要不断翻炒,确保每块鸭肉和每片辣椒都有鸭血的浸润(此乃血浆鸭的精髓)。 +- 翻炒至肉眼可见鸭血均为黑色,加入盐,鸡精,香葱,(喜欢食用山胡椒油的朋友也可以在此时放入 3-6 滴山胡椒油)再次翻炒一到二次即可。 +- 出锅盛盘,上桌食用。 + +## 附加内容 + +- 操作时,需要注意观察水位线,调整炉火大小,以防水烧干粘锅。 +- 放入鲜鸭血时,需要不断翻炒搅拌,防止鸭血抱团凝固成块。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/西红柿土豆炖牛肉/abaaba_1.png b/data/C8/cook/dishes/meat_dish/西红柿土豆炖牛肉/abaaba_1.png new file mode 100644 index 0000000..d4f07b3 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/西红柿土豆炖牛肉/abaaba_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df5bd3d5d2d5708c53ccb5d111b1647fbccc644859717e738ccbf2e188ae2ebe +size 678484 diff --git a/data/C8/cook/dishes/meat_dish/西红柿土豆炖牛肉/西红柿土豆炖牛肉.md b/data/C8/cook/dishes/meat_dish/西红柿土豆炖牛肉/西红柿土豆炖牛肉.md new file mode 100644 index 0000000..a7ba3b9 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/西红柿土豆炖牛肉/西红柿土豆炖牛肉.md @@ -0,0 +1,78 @@ +# 西红柿土豆炖牛肉的做法 + +![效果图](./abaaba_1.png) + +西红柿土豆炖牛肉(腩)的特点就是还挺好吃,牛肉是优质蛋白,换成牛腩更好吃。 + +难度基本没有,90 岁老奶奶拄拐杖都能做。 + +预计制作总时常 1~1.5h。炖的时间:做的时间≈3:1 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 牛肉 +- 小料 +- 葱 +- 姜 +- 料酒 +- 花椒 +- 八角 +- 香叶 +- 白糖 or 冰糖 +- 酱油(可选) +- 老抽 +- 黑胡椒粉(或白胡椒粉) +- 土豆 +- 西红柿 +- 洋葱 + +## 计算 + +- 牛肉 500-700g +- 小料 + - 葱一根,姜四片,料酒 + - 花椒 3g + - 八角一个(半) + - 香叶两片 + - 油 15ml (若用牛腩可根据喜好减少为 10ml) +- 调味品 + - 白糖 or 冰糖 + - 酱油(千禾酿造生抽无添加),老抽 + - 黑胡椒粉(白的也行)2g +- 土豆两三个(看喜好,锅能盛了为准) +- 西红柿拳头大小中等个头两三个 +- 比拳头大一点的洋葱一个 + +## 操作 + +- 备菜: + - 土豆去皮、切成 5cm 大块,备用 + - 西红柿切十字花刀,开水烫后去皮,把中间的芯去掉,切 3cm 小块备用 + - 葱切 4g 的葱花出来,剩下的掰成 5-8cm 大段 + - 牛肉泡凉水半小时去血水,或凉水下锅煮至表面变白捞出,期间撇去浮末 + - 洋葱切 0.5-1cm 小粒 +- 制作 + - 全程中火 + - 凉水没过牛肉,放入高压锅,放入葱段,姜片,放入 20g 料酒,上汽压 20 分钟 + - 取出牛肉后,切 5cm 大块,挑出姜,汤盛到一个大碗里一会炖煮用 + - 倒油,油四到五成热以后下花椒八角香叶,出香味之后糊之前挑出不用 + - 下入牛肉,葱姜,炒香,炒多久都无所谓,看着有点要糊可以舀 10ml 汤,此下同理 + - 炒香后加入生抽 15ml,料酒 15ml,胡椒粉,5-10g 番茄膏番茄酱或一个番茄罐头,加入洋葱炒至透明 + - (可选)可以加一点点盐使洋葱出水不容易糊,不要加太多,后面再调味 + - 加入西红柿炒至西红柿化开软烂,倒入剩下的汤 +- 炖煮 + - 中火开锅后,全程小火 + - 出锅前 30-40 分钟 加土豆并调味 + - 依据个人口味边尝边加糖盐,合适为止 + - 筷子戳牛肉软烂后出锅! + +## 附加内容 + +- 炖煮时保证汤加入的时候是温热的 +- 炖煮时不要扣盖否则土豆会烂 +- 炖煮时时不时翻动避免糊底 +- 砂锅炖煮会更好吃,可以在炒锅里炒完倒到煮锅里炖,如果用砂锅开锅之前不要用大火避免裂开 +- 酱油总量不要太多,汤汁浓缩的时候会变咸,稀的时候稍微淡点没事,炖煮时候觉得不够也可以再加酱油 +- 不要用鸡精味精,会抢夺牛肉的鲜味 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/西红柿牛腩/西红柿牛腩.md b/data/C8/cook/dishes/meat_dish/西红柿牛腩/西红柿牛腩.md new file mode 100644 index 0000000..9847c1e --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/西红柿牛腩/西红柿牛腩.md @@ -0,0 +1,41 @@ +# 西红柿牛腩的做法 + +西红柿牛腩汤汁浓厚酸甜可口,牛肉软绵醇香,搭配米饭绝配。一般初学者需要 90 分钟完成。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +* 西红柿 +* 牛腩 +* 燃气灶(西红柿去皮用) +* 高压锅/砂锅/普通铝锅(铁锅) +* 2cm 两段葱段、两片姜片,葱花、姜各 10g +* 生抽、白胡椒粉,白糖,料/黄酒,八角三小片 +* 牛腩(挑选肥瘦相间的口感比较好) + +## 计算 + +每份: + +- 西红柿 3-4 个(每个约 200g) +- 牛腩 500g +- 食用油 20-30ml + +## 操作 + +- 牛腩切条、切块成长宽高均 2cm ,冷水下锅,开锅煮制 2 分钟去除血水,捞出冲洗干净 +- 另起锅 2L 水烧开,加入 2cm 两段葱段、两片姜片、八角、料/黄酒 5-10ml,放入焯好的牛肉,盖盖炖制(砂锅 1 小时,高压锅炖肉模式 45 分钟),筷子能轻松插透就证明炖好了 +- 西红柿去皮:西红柿头部滑十字至腰线,筷子/刀叉从果蒂捅入,煤气灶小火,一边转动一边烤,及时拿下来查看,起皮后撕下来,切块。越小越好 + - 撕皮小心烫,去皮后的西红柿特别滑,慢切注意安全 +- 起锅烧油,油温 7 成热,葱、姜各 10g,番茄下锅,炒透炒出番茄红色,加入煮好的牛腩和原汤,原汤刚刚没过牛肉即可 +- 根据个人口味放入盐、糖、生抽调味盖盖 +- 开锅后大火继续炒制 3-5 分钟 +- 待番茄汁呈中等粘稠程度后关火,散入葱花,盛盘 + +## 附加内容 + +- 用火注意安全、用火注意安全、用火注意安全 +- 用砂锅/铝锅炖肉时,水开后转中小火/小火,使用高压锅见[学习使用压力锅](./../../../tips/learn/高压力锅.md) +- 教程中的番茄去皮方式是目前为止本人实践最快的方式 +- 绝对不用番茄酱和少加佐料,尽可能还原食材的原味 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/豆豉鲮鱼油麦菜/豆豉鲮鱼油麦菜.md b/data/C8/cook/dishes/meat_dish/豆豉鲮鱼油麦菜/豆豉鲮鱼油麦菜.md new file mode 100644 index 0000000..1fce452 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/豆豉鲮鱼油麦菜/豆豉鲮鱼油麦菜.md @@ -0,0 +1,46 @@ +# 豆豉鲮鱼油麦菜的做法 + +![豆豉鲮鱼油麦菜](./豆豉鲮鱼油麦菜成品.jpg) + +豆豉鲮鱼油麦菜是一到十分常见的菜,材料简单,操作方便,鲮鱼咸香,非常下饭。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 油麦菜 +- 甘竹牌鲮鱼罐头 +- 蒜 +- 生抽 +- 白糖 +- 食用油 + +## 计算 + +每份(约 2 人份): + +- 油麦菜 500g +- 鲮鱼罐头 1 罐(250g 上下) +- 蒜 4 瓣 +- 生抽 20g +- 白糖 3g +- 食用油 15ml + +## 操作 + +1. **食材处理**: + - 油麦菜洗净后切段 + - 鲮鱼罐头打开后,把鲮鱼主刺去除,切成小段后备用 + - 大蒜切成末 + +2. **炒制过程**: + - 锅热倒入食用油,油热后加入洗净的油麦菜,炒到萎蔫出水后盛出备用,倒掉炒制出的水分 + - 重新热锅后,加入鲮鱼罐头中的油,放入蒜末煸香 + - 蒜末煸香后加入鲮鱼罐头中的豆豉,翻拌后加入切碎的鲮鱼块,再次翻拌 + - 翻拌均匀后加入油麦菜,加入生抽和糖调味 + - 调味加入后简单翻拌即可出锅装盘 + +## 附加内容 + +- **注意事项**: + 1. 鲮鱼罐头本身带味道,加入生抽后够味,无需下盐 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/豆豉鲮鱼油麦菜/豆豉鲮鱼油麦菜成品.jpg b/data/C8/cook/dishes/meat_dish/豆豉鲮鱼油麦菜/豆豉鲮鱼油麦菜成品.jpg new file mode 100644 index 0000000..b346006 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/豆豉鲮鱼油麦菜/豆豉鲮鱼油麦菜成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3391847f2aa1b6ed390ab0ee53ca2f85ed6ef64cf46faaf2ba4f70c607fed910 +size 482681 diff --git a/data/C8/cook/dishes/meat_dish/豉汁蒸白鱔/豉汁蒸白鱔.jpeg b/data/C8/cook/dishes/meat_dish/豉汁蒸白鱔/豉汁蒸白鱔.jpeg new file mode 100644 index 0000000..2036102 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/豉汁蒸白鱔/豉汁蒸白鱔.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb6248f7dcb2afd7290353238076851894806ea374c710545d923b665b877777 +size 63117 diff --git a/data/C8/cook/dishes/meat_dish/豉汁蒸白鱔/豉汁蒸白鱔食谱.md b/data/C8/cook/dishes/meat_dish/豉汁蒸白鱔/豉汁蒸白鱔食谱.md new file mode 100644 index 0000000..e811010 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/豉汁蒸白鱔/豉汁蒸白鱔食谱.md @@ -0,0 +1,82 @@ +# 豉汁蒸白鱔的做法 + +![豉汁蒸白鱔示例菜成品](./豉汁蒸白鱔.jpeg) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 白鱔(白鳝) +- 豆豉 +- 蒜头 +- 姜 +- 葱 +- 生抽 +- 老抽 +- 糖 +- 麻油 +- 生粉(可选) +- 红椒(可选,装饰用) + +### 工具 + +- 蒸锅或电蒸炉 +- 耐热盘(适合蒸的盘子) +- 刀和砧板 +- 小碗(调酱汁用) + +## 计算 + +一人份量 + +每份: + +- 白鱔 250g (约一条小白鱔,已去内脏并切成段) +- 豆豉 1 汤匙 +- 蒜头 2 瓣 (剁碎) +- 姜 3 片 (切丝) +- 葱 1 根 (切段或丝) +- 生抽 1.5 汤匙 +- 老抽 0.5 茶匙 +- 糖 0.5 茶匙 +- 麻油 0.5 茶匙 +- 生粉 1 茶匙 (可选,用于腌制) +- 水 1 汤匙 (调酱汁) +- 红椒 少许 (切丝,装饰用) + +## 操作 + +1. **检查与清洗白鱔**: + - 购买时已请鱼贩去内脏、刮去黏液并切成约 5 厘米长的段。 + - 回家后检查白鱔,冲洗干净,确保无残留黏液或杂质。 + - 可选:用少许盐和 1 茶匙生粉轻搓白鱔段,腌制 5 分钟后冲洗干净,去腥并增加嫩滑口感。 + +2. **准备酱汁**: + - 在小碗中混合 1 汤匙豆豉、2 瓣蒜末、1.5 汤匙生抽、0.5 茶匙老抽、0.5 茶匙糖、0.5 茶匙麻油和 1 汤匙水,搅拌均匀。 + - 若喜欢更浓郁的豉汁,可多加 0.5 汤匙豆豉。 + +3. **摆盘**: + - 将已切好的白鱔段平铺在耐热盘中,尽量不重叠。 + - 将姜丝均匀撒在白鱔上。 + - 将调好的豉汁均匀淋在白鱔上。 + +4. **蒸制**: + - 在蒸锅或电蒸炉中加入适量水,烧开至沸腾。 + - 将装有白鱔的盘子放入蒸锅,盖上锅盖。 + - 用中大火蒸约 8-10 分钟 (视白鱔段大小调整时间),至白鱔熟透但不过老 (肉质变白,无血水)。 + +5. **装饰与完成**: + - 蒸好后取出,撒上葱丝和红椒丝 (可选) 作装饰。 + - 可再淋少许热麻油提升香气。 + - 趁热上桌,搭配白饭享用。 + +## 附加内容 + +- **注意事项**: + - 确保白鱔新鲜,购买时选择活鱼,肉质更鲜嫩。 + - 鱼贩切段时可指定长度 (约 5 厘米为宜),方便蒸制和食用。 + - 蒸制时间不宜过长,以免白鱔肉质变韧。 + +- **变种做法**: + - 可加入少许辣椒或 XO 酱,增加辣味和层次感。 + - 若喜欢更软嫩的口感,可在腌制时加入少许米酒。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/贵州辣子鸡/贵州辣子鸡.jpg b/data/C8/cook/dishes/meat_dish/贵州辣子鸡/贵州辣子鸡.jpg new file mode 100644 index 0000000..eae6a09 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/贵州辣子鸡/贵州辣子鸡.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8e19f3f206fd2f1f8d99b032d9cfd951171012ffb78a787f49d3c1b2443d06b +size 192203 diff --git a/data/C8/cook/dishes/meat_dish/贵州辣子鸡/贵州辣子鸡.md b/data/C8/cook/dishes/meat_dish/贵州辣子鸡/贵州辣子鸡.md new file mode 100644 index 0000000..3b98564 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/贵州辣子鸡/贵州辣子鸡.md @@ -0,0 +1,61 @@ +# 贵州辣子鸡的做法 + +![贵州辣子鸡](./贵州辣子鸡.jpg) + +贵州人对吃鸡的执恋 + +* 过节日,吃鸡 +* 过生日,吃鸡 +* 生病,吃鸡 +* 有客人,吃鸡 +* 家人团聚,吃鸡 +* 不知道吃什么,那就吃鸡 + +贵州辣子鸡多种配菜,香辣可口,香糯软烂 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 农村玉米鸡 +- 土豆 +- 大蒜 +- 香叶 +- 姜 +- 老抽 +- 花椒 or 麻椒 +- 糍粑辣椒(花溪党武的辣椒,遵义的子弹头,条子椒,大方的皱椒混合之后打碎的辣椒) +- 豆瓣酱 +- 啤酒 +- 蒜苗 +- 酒糟 +- 食用油 + +## 计算 + +每份: + +- 鸡三到四个人的量是四斤,人多可以依次累加 +- 啤酒半瓶 +- 姜手指头大小两个 +- 糍粑辣椒 500g,会是拳头大小两坨 +- 蒜苗三根 +- 香叶 2 片 +- 大蒜两个 +- 土豆两个 +- 菜籽油两斤,开始炸鸡会用很多 +- 老抽 20 ml + +## 操作 + +- 在锅中加入和锅一半高度的油,将切成长条的土豆先炸至表面金黄然后捞出备用,等油温上至烤手时候将切好的鸡块放入锅中炸,并放入切好的生姜片和花椒 +- 刚开始炸鸡的时候,油是浑浊的,因为鸡块里面有水的原因,等到油炸至清澈,鸡块就炸好了,然后捞出备用 +- 现在锅里面的油可以捞三分之一出来,现在用不到这么多的油 +- 将锅中剩余的油加热,加入糍粑辣椒,豆瓣酱,生姜片,炒出红油状,将炸好的鸡块翻炒均匀 +- 等到鸡块都上色,加入老抽,倒入啤酒,啤酒一定要盖过鸡块,加上香叶盖上盖,闷十分钟,期间间隔翻炒 +- 然后加入土豆条,大蒜(不用切,一颗一颗的最好),然后再闷 20 分钟 +- 最后加入酒糟翻炒均匀再加入切好的蒜苗,就可以出锅了 + +## 附加内容 + +- 操作时,需要注意翻炒,因为糍粑辣椒会糊掉 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/辣椒炒肉.md b/data/C8/cook/dishes/meat_dish/辣椒炒肉.md new file mode 100644 index 0000000..0bb565e --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/辣椒炒肉.md @@ -0,0 +1,51 @@ +# 辣椒炒肉的做法 + +⚠️注意:本道菜需要一定料理基础,不推荐新手尝试。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 青椒(吃辣的话推荐用杭椒,螺丝椒,不吃辣的用尖椒,甜椒) +* 猪瘦肉 +* 盐 +* 生抽 +* 蚝油 +* 大蒜 +* 姜 +* 酱油(可选) +* 豆豉(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +* 青椒的数量 = 份数 * 3 个。 +* 肉量 = 份数 * 200g。 +* 盐量 = 份数 * 3g。 +* 生抽 = 份数 * 3ml。 +* 蚝油 = 份数 * 3ml。 +* 大蒜 = 份数 * 5g。 +* 生姜 = 份数 * 5g。 +* 酱油 = 份数 * 2ml。 +* 豆豉 = 份数 * 3g。 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +* 将`青椒`洗净,去除`青椒把`以及`青椒籽`,再用`滚刀手法`切好备用。 +* `大蒜`用刀拍一下,再横切成`蒜瓣`,`生姜`切碎成`姜末`。 +* 将`猪瘦肉`切成`肉片`(顺着猪肉的纹理切,即刀和肉的纹理呈水平线,出来的肉片,纹路呈“川”字)。 +* 将切好的`猪肉`洗净,放入空碗,再加入计算好的`生抽`、`蚝油`、`盐`搅拌均匀,腌制 10 分钟。 +* 热锅,不用倒油,把`切好的青椒`放入锅中,大火干煸至虎皮状后,再加 2g`盐`继续翻炒 1 分钟 后捞起。 +* 不用洗锅,大火热锅,加入份数 * 8ml`油`,等待 30s,加入`蒜瓣`、`姜末`翻炒 15s。 +* 加入腌制好的`猪肉`倒入锅内翻炒 2 分钟,再加入干煸过的`青椒`翻炒 1 分钟。 +* 根据个人口味喜好加入`豆豉`,最后加入`酱油`,继续翻炒 30s。 +* 出锅,盛盘。 + +## 附加内容 + +**辣椒只能选择青椒,螺丝椒为最优解,切勿选择其他品种辣椒!** \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/酱排骨/1.jpeg b/data/C8/cook/dishes/meat_dish/酱排骨/1.jpeg new file mode 100644 index 0000000..c4135ab --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/酱排骨/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed5945aab58373295bd593d2ccd20a3bd8f5a8b5dbdc36a8aa890e7955a8258b +size 155288 diff --git a/data/C8/cook/dishes/meat_dish/酱排骨/2.jpeg b/data/C8/cook/dishes/meat_dish/酱排骨/2.jpeg new file mode 100644 index 0000000..12c8dd2 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/酱排骨/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6195531e46d5e6c76e6f601267c999bbe1b24354a46960f736b9d5f476546ebb +size 130831 diff --git a/data/C8/cook/dishes/meat_dish/酱排骨/酱排骨.md b/data/C8/cook/dishes/meat_dish/酱排骨/酱排骨.md new file mode 100644 index 0000000..e65acad --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/酱排骨/酱排骨.md @@ -0,0 +1,53 @@ +# 酱排骨的做法 + +酱排骨其色泽酱红,肉质酥烂,骨香浓郁,汁浓味鲜,咸中带甜。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 排骨 +* 五香粉 +* 料酒 +* 食用油 +* 白砂糖 +* 老抽 +* 生抽 +* 蚝油 +* 小米椒 +* 蒜 +* 姜 + +## 计算 + +每份: + +* 排骨 300 g +* 五香粉 20 g +* 料酒 10 ml +* 食用油 30 ml +* 白砂糖 15 g +* 老抽 10 ml +* 生抽 10 ml +* 蚝油 5 ml +* 小米椒 1 个 +* 蒜 2 粒 +* 姜 2 片 + +## 操作 + +* 起锅烧热水,放入排骨、姜片、料酒,煮开后用勺子舀去白色油沫,2-3 分钟后出锅 +* 冷水清洗排骨,清洗 2-3 遍 +* 小火起锅,加入食用油,加入白砂糖 ,轻轻搅拌到糖水变成黄色 +* 倒入排骨翻炒 30 S 后,加入生抽、蚝油、五香粉、蒜、小米椒后翻炒 30 S 后,加入清水没过排骨 +* 大火煮 30 分钟,加入老抽上色,再煮 10 分钟 +* 起锅摆盘 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) + +## 附加内容 + +* 增加味道的可以考虑加入豆瓣酱、番茄酱等 +* 大火煮时间可以根据每个人情况做调整 +* 煮排骨期间,可以顺道放入 2-3 个 鸡蛋一起煮,做成简易版卤蛋 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/酱牛肉/酱牛肉.jpg b/data/C8/cook/dishes/meat_dish/酱牛肉/酱牛肉.jpg new file mode 100644 index 0000000..eb09fe3 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/酱牛肉/酱牛肉.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:569dce1406a1f2d994e7d9aea4917bba4a2e988f75cde14c236f7d8ebfaa26e9 +size 138909 diff --git a/data/C8/cook/dishes/meat_dish/酱牛肉/酱牛肉.md b/data/C8/cook/dishes/meat_dish/酱牛肉/酱牛肉.md new file mode 100644 index 0000000..2d9d69b --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/酱牛肉/酱牛肉.md @@ -0,0 +1,60 @@ +# 酱牛肉的做法 + +![酱牛肉](./酱牛肉.jpg) + +家常酱牛肉营养丰富,味道香,不论是当作主食还是佐餐都很棒。一般初学者只需要 3 小时即可完成。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 牛肉 +- 香叶 +- 姜 +- 葱 +- 老抽 +- 桂皮 +- 冰糖 +- 花椒 +- 料酒 +- 生抽 +- 盐 +- 八角 +- 黄豆酱 + +## 计算 + +每份: + +- 牛肉 2000 克 +- 香叶 1 片 +- 姜 3 片 +- 葱半根 +- 老抽 15ml +- 桂皮 1 块 +- 冰糖 7-8 粒 +- 花椒 15 粒 +- 料酒 30ml +- 生抽 15ml +- 盐 8 克 +- 八角 4 个 +- 黄豆酱 15ml + +## 操作 + +- 牛肉浸泡 4-6 小时,加料酒、姜片,去除血水 +- 牛肉切成 8cm,不超过 10cm 的肉块 +- 牛肉放入锅中,加入冷水至水面没过牛肉,开锅至水沸腾开始计时,3 分钟后停火,捞出牛肉,用温水洗净 +- 将洗净后的牛肉放入砂锅或炖锅,加水没过牛肉,开大火,放入除盐之外的其他配料。 +- 水开之后,大火转为小火,持续加热 90 分钟,加盐 +- 加盐后,继续小火 90 分钟(注:每 30 分钟确认水位线,要求至少达到牛肉面高度的 80%) +- 加热 180 分钟后,捞出牛肉,自然冷却,切片 +- 上桌食用,其他牛肉建议不切片冷藏。 + +## 附加内容 + +- 操作时,需要注意观察沸腾的水位线,如发现低于 2/3 的食材应加热水至没过食材(约每 30 分)。 + +### 参考资料 + +- [下厨房app中的食谱](http://www.xiachufang.com/recipe/106670199/) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/醉排骨/1.jpeg b/data/C8/cook/dishes/meat_dish/醉排骨/1.jpeg new file mode 100644 index 0000000..07a0d24 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/醉排骨/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afe62da18a7c0600544b8f060dbe9b81afa15e879033f197b3203398124f037c +size 203763 diff --git a/data/C8/cook/dishes/meat_dish/醉排骨/醉排骨.md b/data/C8/cook/dishes/meat_dish/醉排骨/醉排骨.md new file mode 100644 index 0000000..ce9e2b3 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/醉排骨/醉排骨.md @@ -0,0 +1,52 @@ +# 醉排骨的做法 + +醉排骨是福建省福州市特色传统名菜 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 排骨 +* 白砂糖 +* 食用油 +* 鱼露 +* 芝麻 +* 番茄酱 +* 香醋 +* 蒜头 +* 葱 +* 地瓜粉 +* 鸡蛋黄 + +## 计算 + +每份: + +* 排骨 200 g +* 白砂糖 10 g +* 食用油 500 ml +* 鱼露 5 ml +* 芝麻 5 g +* 番茄酱 5 g +* 香醋 5 ml +* 蒜头 2 粒 +* 葱 1 根 +* 地瓜粉 30 g +* 鸡蛋黄 1 个 + +## 操作 + +* 排骨中加入 5 g 地瓜粉和水进行搅拌,清洗 2-3 遍后放入大碗备用 +* 排骨中加入鱼露、地瓜粉、鸡蛋黄 充分搅拌 +* 将排骨一个一个放入锅中(切记不可以整碗倒入),保证每个不要粘在一起 +* 全部放入后,每 30 S 用勺子来回两面翻转瘦肉块,直至排骨表面金黄 +* 取出排骨,一分钟后倒入油锅中继续炸,直至瘦肉块表面出现焦黄后,取出放入大碗备用 +* 准备一个小碗,加入蒜末、香醋、白砂糖、鱼露、番茄酱、葱花、芝麻搅拌均匀,倒入 5 ml 热油 +* 将汤汁浇灌入排骨,在充分搅拌后倒入盘中 + +![示例菜成品](./1.jpeg) + +## 附加内容 + +* 鱼露,又称鱼酱油,是一种广东,福建等地常见的调味品。效果类似于生抽 +* 本次制作过程中,由于疫情原因没有雨露,只能用老抽代替,所以排骨颜色偏黑,正常是金黄色 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/青椒土豆炒肉/青椒土豆炒肉.jpg b/data/C8/cook/dishes/meat_dish/青椒土豆炒肉/青椒土豆炒肉.jpg new file mode 100644 index 0000000..0611624 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/青椒土豆炒肉/青椒土豆炒肉.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca72217c05b13cd4b2c59a57ca4bd4be9ae4d6e9538ed46ceba72f09b0e2d9e3 +size 851311 diff --git a/data/C8/cook/dishes/meat_dish/青椒土豆炒肉/青椒土豆炒肉.md b/data/C8/cook/dishes/meat_dish/青椒土豆炒肉/青椒土豆炒肉.md new file mode 100644 index 0000000..0b3ce8c --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/青椒土豆炒肉/青椒土豆炒肉.md @@ -0,0 +1,47 @@ +# 青椒土豆炒肉的做法 + +![青椒土豆炒肉](https://user-images.githubusercontent.com/49046468/205808925-b0ab8f98-0325-4136-8094-3f2ae8c547d5.jpg) + +青椒土豆炒肉是一道荤素搭配的简单炒菜。一般初学者只需要 1 小时即可完成。贼下饭~ + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 青椒 +- 土豆 +- 猪肉(五花肉) +- 葱 +- 姜 +- 蒜 +- 盐 +- 酱油 +- 土豆淀粉 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 青椒 2 个(共约 200g) +- 土豆 2 个(共约 300g) +- 猪肉 200g +- 葱 1 根(约 10g) +- 姜 1 块(约 5g) +- 蒜 3 瓣(约 12g) +- 盐 7g +- 酱油 6-10ml +- 食用油 10-15ml +- 土豆淀粉 5g +- 水 15g + +## 操作 + +- 青椒去除根蒂切小块,土豆去皮切 2mm 薄片,猪肉切 4mm 薄片,葱横纵切 3mm 小段,姜蒜去皮拍散剁碎末;土豆淀粉加入约 15g 水搅拌均匀至水淀粉。 +- 起锅烧油,加热至 7 成热放入猪肉片,缓缓翻滚炒至去肉红色,加入约 3ml 酱油,翻炒肉片均匀上色,放入约 2g 盐。 +- 转 5 成油温,加入葱姜蒜炒 5 秒,然后加入土豆片,转 7 成油温均匀翻炒,加入加入约 5ml 酱油和 2g 盐,炒至土豆断生,表面轻微焦黄。 +- 转 8 成油温加入青椒,大火煸炒出锅气(有白烟冒出),反复均匀翻炒 1 分钟上色,最后在锅周围倒入水淀粉转 4 成火勾芡。 +- 在外观*呈粘稠状态*后关火,盛盘 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/香干肉丝.md b/data/C8/cook/dishes/meat_dish/香干肉丝.md new file mode 100644 index 0000000..26c298a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香干肉丝.md @@ -0,0 +1,55 @@ +# 香干肉丝的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 猪里脊(可以买超市切好且称重好的肉丝) +* 香干 +* 盐 +* 生抽 +* 淀粉 +* 大蒜 +* 青椒 +* 鸡精 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +* 香干 = 份数 * 75g +* 青椒的数量 = 份数 * 5 个 +* 肉量 = 份数 * 100g +* 盐量 = 份数 * 3g +* 生抽 = 份数 * 5ml +* 淀粉 = 份数 * 5g +* 大蒜 = 份数 * 5g(大约 3 个蒜瓣) +* 鸡精 = 2g + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 准备工作 + +* `肉丝`(没有肉丝,自己切)用生抽(3ml),生粉混合均匀待用。 +* 将`青椒`洗净,再用`滚刀手法`切好备用。 +* `大蒜`横切成片,`香干`切丝。 +* `淀粉`与水(10ml)混合,搅拌均匀。 + +### 起锅 + +* 干净锅 15ml 油,不用等油热就倒入肉丝慢慢划散,肉丝熟了,立马捞出,留油到锅里。 +* 将蒜片和香干放入锅中,加入 2ml 生抽,翻炒均匀。 +* 2-3 分钟,看火大小,将青椒丝放入锅中混合,翻炒。 +* 1 分钟后,放入肉丝混合。 +* 倒入淀粉与水的混合物勾芡,加入盐 3g,鸡精 2g,翻炒 2-3 分钟出锅。 +* 成品。 + +注意,不同的锅具或者灶台,会影响翻炒的时间,建议,不确定是否熟了,可以试吃下。 + +## 附加内容 + +**辣椒选择青椒,螺丝椒为最优解,喜欢辣的可以加入小米椒切细碎,同青椒一起加入!** \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/香干芹菜炒肉/香干芹菜炒肉.jpg b/data/C8/cook/dishes/meat_dish/香干芹菜炒肉/香干芹菜炒肉.jpg new file mode 100644 index 0000000..5163d53 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香干芹菜炒肉/香干芹菜炒肉.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a122c3a49d2dc5dacce10711262a233180ac3a2ded76e2cee0860b23c0fd632d +size 643709 diff --git a/data/C8/cook/dishes/meat_dish/香干芹菜炒肉/香干芹菜炒肉.md b/data/C8/cook/dishes/meat_dish/香干芹菜炒肉/香干芹菜炒肉.md new file mode 100644 index 0000000..a421a95 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香干芹菜炒肉/香干芹菜炒肉.md @@ -0,0 +1,59 @@ +# 香干芹菜炒肉的做法 + +![香干芹菜炒肉](./香干芹菜炒肉.jpg) + +香干芹菜炒肉是一道非常简单的家常菜小炒,据说多吃芹菜对于高血压有很好的缓解作用,加上香干和猪肉一起翻炒,还是很美味的。一般初学者只需要 30 分钟(含配菜时间)即可完成。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 豆干 +- 香芹/芹菜 +- 猪肉 +- 大蒜 +- 辣椒:青椒或者红椒都可以 +- 花椒:可选 +- 盐 +- 鸡精:可选 +- 老抽 +- 蚝油 +- 食用油 + +## 计算 + +注意,此数值大约是 2 个人的量。 + +每份: + +- 豆干:150g +- 香芹:4 根 +- 猪肉:200g +- 蒜头:2 瓣 +- 辣椒:4 个 +- 花椒:6 粒(不喜欢可以不放,或者放花椒水) +- 盐:5g +- 鸡精:3g +- 老抽:8ml +- 蚝油:5ml +- 食用油:10-15ml + +## 操作 + +- 芹菜去叶切段、切成不超过 4cm 的条状,备用 +- 香干切条,宽约小拇指,备用 +- 蒜头切片或者剁成蒜泥都行,备用 +- 辣椒切圈或者斜切成条都行,备用 +- 热锅,锅内放入 10ml - 15ml 食用油。等待 10 秒让油温升高 +- 放入花椒、大蒜爆香(可以吃姜的也可以额外放入一些姜片/姜丝) +- 加入猪肉炒至变色,再加入 8ml 老抽上色翻炒均匀(有豆瓣酱的,可以放入 3ml 豆瓣酱一起翻炒) +- 加入香干翻炒均匀(大约 2 分钟) +- 加入辣椒翻炒均匀(大约 1-2 分钟) +- 加入芹菜,放入 5g 盐翻炒 1 分钟 +- 加入 3g 鸡精、5ml 蚝油翻炒均匀,即可出锅 + +## 附加内容 + +- 如果没有买到香芹,或者用的芹菜比较粗,可以考虑焯水,放入滚水中 1 分钟捞出,冷水冲洗(保持爽脆) +- 如果买到的豆干比较硬、紧实,也可以切条后再焯水 +- [香干芹菜炒肉教程](https://www.xiachufang.com/recipe/105987156/) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/香煎五花肉/香煎五花肉.jpg b/data/C8/cook/dishes/meat_dish/香煎五花肉/香煎五花肉.jpg new file mode 100644 index 0000000..e4cbab5 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香煎五花肉/香煎五花肉.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:278471f5f14ade38b95de697f772b810d398c3badbb0c70303bb1248e0f9c564 +size 191816 diff --git a/data/C8/cook/dishes/meat_dish/香煎五花肉/香煎五花肉.md b/data/C8/cook/dishes/meat_dish/香煎五花肉/香煎五花肉.md new file mode 100644 index 0000000..8431ec1 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香煎五花肉/香煎五花肉.md @@ -0,0 +1,36 @@ +# 香煎五花肉的做法 + +![香煎五花肉](./香煎五花肉.jpg) + +香煎五花肉一道简单易上手的菜。五花肉肥而不腻,生菜叶脆爽健康。稍微有下厨经验的人半小时便可制作完毕。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 五花肉条(推荐长宽高为 20cm\*6cm\*5cm) +- 生菜 +- 酱油,盐,味精,料酒,姜蒜,油,豆瓣酱 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人吃。 + +每份: + +- 五花肉条(推荐长宽高为 20cm\*6cm\*5cm) +- 生菜一朵 +- 食用油 5ml + +## 操作 + +- 将五花肉条沿长边切片,每片厚 1mm-1.5mm,备用 +- 将切好的五花肉放置碗中,依次加入 8g 酱油,1g 盐,1g 味精,10g 料酒,两片姜,两朵拍扁的大蒜腌制 10 分钟 +- 将生菜叶直接用手扒下来,洗干净,备用 +- 热锅,倒入 5ml 食用油。油轻微冒烟后下入五花肉。单面煎制焦黄色后翻面,另一边同理。 +- 五花肉出锅后,装盘。 +- 将豆瓣酱抹到菜叶上,卷着五花肉即可食用 + +## 附加内容 + +- 操作时,小心被溅出的油烫到 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/香菇滑鸡/香菇滑鸡.jpg b/data/C8/cook/dishes/meat_dish/香菇滑鸡/香菇滑鸡.jpg new file mode 100644 index 0000000..f9756cb --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香菇滑鸡/香菇滑鸡.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4aadf9ec374925ec34ecb5eb8d9504cd4158a4d2441a6aaffefa6069588f72bc +size 942353 diff --git a/data/C8/cook/dishes/meat_dish/香菇滑鸡/香菇滑鸡.md b/data/C8/cook/dishes/meat_dish/香菇滑鸡/香菇滑鸡.md new file mode 100644 index 0000000..34f7a41 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香菇滑鸡/香菇滑鸡.md @@ -0,0 +1,52 @@ +# 香菇滑鸡的做法 + +![香菇滑鸡](./香菇滑鸡.jpg) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 大鸡腿 +- 干香菇 +- 姜 +- 葱 +- 蒜 + +## 计算 + +每份: + +- 大鸡腿 2 个 +- 干香菇 5 粒 +- 姜 2 片 +- 葱 2 颗 +- 蒜 2 瓣 +- 温水(30-40 ℃) 150ml +- 料酒 15ml +- 生抽 30ml +- 盐 1.5g +- 老抽 15ml +- 糖 15ml +- 香油 5ml + +## 操作 + +- 温水泡发干香菇 +- 姜切小块,葱切段,蒜对半切小粒 +- 鸡腿去骨(不去骨也可,只是略影响程序员吃饭的效率而已),切成小块 +- 泡发的香菇一分为四,香菇水留着备用 +- 鸡腿肉焯水 1 分钟,去除血沫和杂质 +- 鸡腿肉中加料酒 15ml、生抽 15ml、盐 1.5g、老抽 15ml,抓匀 +- 油温 3 成,下入鸡腿肉煸炒,等鸡腿肉金黄后盛出备用 +- 锅留底油,下入葱、姜、蒜炒香,香菇入锅,大火翻匀 +- 等待 20 秒会有香菇香味从锅中飘出,此时下入煸炒过的鸡腿肉,下入香菇水(全部,**本程序员认为的灵魂操作**)、糖 15ml、生抽 30ml +- 转中火不盖盖,咕嘟 2 分钟收浓汤汁,淋入香油 5ml,撒上葱花后即可关火、装盘 + +## 附加内容 + +- 鸡腿去骨操作较复杂,本人经验可供参考: + - 鸡腿于案板摆正,**骨头正对程序员**,从头部划一刀至最底部,刀口要深,确保有碰到骨头 + - 用手扒拉肉到两边 + - 用刀尖隔开骨头上沾着的肉 + - 鸡腿翻面,刀紧贴骨头插入,挑断骨头与肉的连接点 + - 用刀尖切断最后的粘连即可 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/香辣鸡爪煲/result1.jpg b/data/C8/cook/dishes/meat_dish/香辣鸡爪煲/result1.jpg new file mode 100644 index 0000000..458ce3e --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香辣鸡爪煲/result1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d17f782e6b200db8a3097685223a72e768da3dade3c8f2342e9dd9a18594b289 +size 569564 diff --git a/data/C8/cook/dishes/meat_dish/香辣鸡爪煲/result2.jpg b/data/C8/cook/dishes/meat_dish/香辣鸡爪煲/result2.jpg new file mode 100644 index 0000000..5876028 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香辣鸡爪煲/result2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02ad71b6e40f05a703a7d2ebcd6189738246c742c440fb0d01f37e6741d406f0 +size 903208 diff --git a/data/C8/cook/dishes/meat_dish/香辣鸡爪煲/香辣鸡爪煲.md b/data/C8/cook/dishes/meat_dish/香辣鸡爪煲/香辣鸡爪煲.md new file mode 100644 index 0000000..55925ab --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/香辣鸡爪煲/香辣鸡爪煲.md @@ -0,0 +1,51 @@ +# 香辣鸡爪煲的做法 + +![香辣鸡爪煲](./result2.jpg) + +香辣鸡爪煲口感 Q 弹,香辣浓郁,回味无穷。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 鸡爪 +- 葱 +- 姜 +- 料酒 +- 香叶 +- 八角 +- 生抽 +- 老抽 +- 蒜 +- 小米椒 +- 辣椒面(可选) +- 蚝油 +- 五香粉 +- 盐 +- 鸡精 + +## 计算 + +- 一斤鸡爪 +- 香叶 3 片 +- 八角三个 +- 小米椒 6 个 +- 姜末 10g +- 蒜末 10g +- 小葱 2 根 +- 蚝油 3g + +## 操作 + +- 给鸡爪剪去指甲。如果买的鸡爪只有脚掌部分,对半切开即可。 如果是整只鸡爪,需要去骨。清水洗干净。 +- 鸡爪冷水下锅,葱姜料酒焯水,水开,撇去浮沫。 +- 加入香叶、八角、生抽、老抽,盖盖小火慢煮三十分钟。 + ![煮鸡爪](./result1.jpg) +- 捞出鸡爪,留一碗鸡汤备用。 +- 起锅烧油,用小火炒香姜末、蒜末、小米椒,能吃辣再放点辣椒面。加入生抽、老抽、蚝油、五香粉、盐,炒出酱香味。 +- 放入鸡爪,放一点盐调味,翻炒一两分钟,再倒入鸡汤,边炒边搅动。 +- 放入鸡精提鲜,撒入葱段搅拌均匀即可出锅。 + +注:如果需要加入配菜,请在放入鸡爪之前,底料炒香之后执行。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/鱼香肉丝.md b/data/C8/cook/dishes/meat_dish/鱼香肉丝.md new file mode 100644 index 0000000..d47b7e3 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/鱼香肉丝.md @@ -0,0 +1,65 @@ +# 鱼香肉丝的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 里脊肉 200g +* 胡萝卜 100g +* 青椒 100g +* 木耳(干) 5g +* 生抽 10ml +* 料酒 5ml +* 蛋清 1 个 +* 淀粉 10g +* 醋 15ml +* 白糖 10g +* 盐 5g +* 姜 20g +* 葱 20g +* 蒜 2 瓣 +* 豆瓣酱 15g + +## 计算 + +注意,这道菜仅有足够 1-2 人食用的版本。 + +## 操作 + +### 制作腌料和香碗汁 + +* 制作`腌料`:将下列原料混合: + * 生抽 5ml + * 料酒 5ml + * 淀粉 5g + * 水 20ml + * 蛋清 1 个 +* 制作`香汁`:将下列原料混合: + * 生抽 5ml + * 醋 15ml + * 白糖 10 克 + * 盐 1 克 + * 淀粉 5g + * 水 20ml + +### 处理原料 + +* 用`腌料`腌制里脊肉 15-30 分钟。注意将肉抓匀。 +* 干木耳泡 4 个小时,洗净,切成小块。 +* 青椒洗净,去蒂,切成丝。 +* 胡萝卜洗净,切成丝,将胡萝卜丝[焯水](../../tips/learn/学习焯水.md)。 +* 姜、蒜切沫。 +* 葱切成 5mm 的小段。 + +### 炒熟各种材料 + +* 将锅烧热,加入 15ml 油。 +* 向锅内倒入准备好的腌肉,快速滑散至变白,盛出备用。 +* 将锅烧热,加入 5ml 油。 +* 倒入全部`葱`、`姜`、`蒜`、`豆瓣酱`。 +* 倒入全部`胡萝卜`,翻炒 20s 后,放入青椒和木耳,翻炒 2 分钟。 +* 倒入`炒过的肉`。快速翻炒均匀。注意不要炒超过 20 秒。 +* 倒入`香汁`。快速翻炒均匀。注意不要炒超过 15 秒。 +* 关火,盛盘。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz1.jpg b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz1.jpg new file mode 100644 index 0000000..d6faf86 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe0a89d568510ab2740c7b48416610c05238c0f19c35e3ff30483e7751b124b3 +size 252183 diff --git a/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz2.jpg b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz2.jpg new file mode 100644 index 0000000..ffcc556 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9700691bd0ed3e3cf03cacbe5ae25ed0e0b163401b9261f0f3c78dd944aa901b +size 97239 diff --git a/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz3.jpg b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz3.jpg new file mode 100644 index 0000000..782cdcb --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz3.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d6d708414df8f6df582b03586796bac0fd1d601a760e5beee2dd8a6a44f2dfc5 +size 148496 diff --git a/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz4.jpg b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz4.jpg new file mode 100644 index 0000000..1ff51c0 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz4.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb5fc1b83e420b441206a7d9b3eb0869412c12d937fe95f6e9c22988ba01088e +size 119691 diff --git a/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz5.jpg b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz5.jpg new file mode 100644 index 0000000..afa48e1 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz5.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb29c75d0125c8f38c4a327b70f17c8434bd33be35ce5f1183fda2ec70617d65 +size 120291 diff --git a/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz6.jpg b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz6.jpg new file mode 100644 index 0000000..b7c3dc4 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz6.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:266dfcf79f86514ac97d7885a9504ea1839a07df478d2b49f102ce5f3c8a2d2f +size 168925 diff --git a/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz7.jpg b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz7.jpg new file mode 100644 index 0000000..c703b0a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/鱼香茄子/yxqz7.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39032de47f0918e64e4334ede9c450d86aa7284a3b918d0d30bea5a17f2b69e9 +size 169683 diff --git a/data/C8/cook/dishes/meat_dish/鱼香茄子/鱼香茄子.md b/data/C8/cook/dishes/meat_dish/鱼香茄子/鱼香茄子.md new file mode 100644 index 0000000..eb66142 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/鱼香茄子/鱼香茄子.md @@ -0,0 +1,68 @@ +# 鱼香茄子的做法 + +![yuxiangqiezi](./yxqz1.jpg) + +这个菜真的超级下饭,当个干饭王吧。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 茄子 +- 肉末 +- 盐 +- 糖 +- 味精 +- 生抽 +- 老抽 +- 醋 +- 水淀粉 +- 豆瓣酱 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够一个人吃。 + +- 茄子 2 根 +- 肉末 20g +- 盐 3-5g +- 糖 5-10g +- 味精 5g +- 生抽 10ml +- 老抽 5ml +- 醋 10ml +- 水淀粉 100ml +- 豆瓣酱 20-30g +- 小葱、姜、蒜、小米辣 (根据自己口味) + +## 操作 + +- 将茄子切成条。 + + ![bz1](./yxqz2.jpg) + +- 将肉切成肉沫,葱姜蒜切碎、小米椒切丁。 + + ![bz2](./yxqz3.jpg) + +- 调鱼香汁:碗中放入盐、味精、糖、生抽、老抽、醋、水淀粉搅拌均匀。 +- 锅中倒入 300ml 油,开小火(小火容易掌控),等油温七成热(小火大约 40 秒,有烟冒出)放入茄子炸两分钟,当茄子边缘微黄就捞出。多出的油可以盛出以后炒菜用。 + + ![bz4](./yxqz4.jpg) + +- 锅中留 15-30ml 油,倒入肉沫炒至颜色变白就盛出来。 + + ![bz5](./yxqz5.jpg) + +- 锅中倒入 15-30ml 油,放入豆瓣酱、葱白、姜、蒜炒香,然后倒入肉沫翻炒均匀。 + + ![bz6](./yxqz6.jpg) + +- 加入 80-150ml 清水(水面预计茄子八成高度为准),倒入茄子、倒入料汁,爆炒入味收汁。最后放入葱翻炒均匀,就可以起锅了。 + + ![bz7](./yxqz7.jpg) + +## 附加内容 + +- 茄子看个人喜好,可以去皮,肉沫也可以多放一点。 +- 参考: [鱼香茄子详细步骤](https://www.zhms.cn/recipe/kbbrl.html?source=2) \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/麻婆豆腐/1.jpeg b/data/C8/cook/dishes/meat_dish/麻婆豆腐/1.jpeg new file mode 100644 index 0000000..83d76ff --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/麻婆豆腐/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fea5a8356b2bd0309ba51d50369d06fb493675dc309d6d85aad2d0bc191b418e +size 177651 diff --git a/data/C8/cook/dishes/meat_dish/麻婆豆腐/麻婆豆腐.md b/data/C8/cook/dishes/meat_dish/麻婆豆腐/麻婆豆腐.md new file mode 100644 index 0000000..12e3618 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/麻婆豆腐/麻婆豆腐.md @@ -0,0 +1,54 @@ +# 麻婆豆腐的做法 + +![成品](./1.jpeg) + +这是参考麻婆豆腐创作的一道菜。富含有铁、钙、磷、镁等人体必需的多种微量元素,最重要的是非常下饭哦~ + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 内脂豆腐(推荐清美) +- 水果刀 +- 咸鸭蛋(推荐留夫鸭的,这个是灵魂) +- 五花肉(超市的肉糜也行) +- 大蒜 +- 生姜 +- 小米椒(不吃辣的可选) +- 香辣酱(推荐广乐的) +- 花椒 +- 食盐 +- 酱油(味极鲜酱油) + +## 计算 + +- 1 盒内脂豆腐 +- 1 枚咸鸭蛋 +- 20-30g 五花肉 +- 两瓣大蒜 +- 2 片生姜 +- 5 根小米辣 +- 5g 蒜蓉辣酱 +- 20 颗花椒 +- 3g 食盐 +- 10g 酱油 + +## 操作 + +- 大蒜和生姜切碎,备用 +- 小米辣切成辣椒圈,备用 +- 五花肉切成肉糜(本来就是买的肉糜的跳过) +- 肉糜中加入一半的食盐和味极鲜酱油,搅拌均匀,备用 +- 鸭蛋用菜刀竖着对半切开(注意安全),去除蛋黄(一定要去除,不然会腥),剩下的蛋白捣碎成大约 2 mm * 2 mm 大小,不用太碎,备用 +- 打开豆腐包装,用水果刀将在盒子中的豆腐划成大约 2.5 cm * 3 cm 大小,备用 +- 热锅,锅内放入 10ml - 15ml 食用油。等待 10 秒让油温升高 +- 调成小火,放入大蒜、生姜、辣椒圈、花椒、咸鸭蛋、蒜蓉辣酱翻炒 20 秒,炒出香味 +- 调成中火,放入肉糜,翻炒大约 1 分钟,肉炒变色 +- 调成小火,放入豆腐,将剩下的食盐、味极鲜酱油酱油均匀的洒在豆腐上 +- 从锅边倒入开水(不然豆腐容易破),没过豆腐即可 +- 开大火,水沸腾后立马转入中火,等待大约 10 分钟 +- 等到水只剩 1/5 并且豆腐表面已经入色,关火,盛盘 + +## 附加内容 + +- 期间一定要注意观察,防止糊锅 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/麻辣香锅.md b/data/C8/cook/dishes/meat_dish/麻辣香锅.md new file mode 100644 index 0000000..2cf8fc9 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/麻辣香锅.md @@ -0,0 +1,45 @@ +# 麻辣香锅的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 青菜(油菜、油麦菜、菠菜) +- 无骨肉(猪肉、牛肉、鸡肉、鱼丸、火腿肠) +- 干豆腐 +- 北京麻辣方便面 +- 干辣椒 + +## 计算 + +此数值大约是 3 个人的量。 + +- 青菜共需 455 克,其中油菜、油麦菜、菠菜的比例按自己喜好分配即可 +- 无骨肉共需 430 克,其中猪肉、牛肉、鸡肉、鱼丸、火腿肠的比例按自己喜好分配即可 +- 干豆腐 152 克 +- 北京麻辣方便面 1 袋 +- 干辣椒 5 克 +- 麻辣香锅调料 110 克 + +以上内容中,青菜、无骨肉、干豆腐、北京麻辣方便面的配比为推荐配比,如果有自己喜欢的食材,可以按喜好重新分配比例。 + +## 操作 + +1. 烧开一锅水(水量能没过第 2-4 步中的食材即可)。 +2. 在开水中放入青菜,焯 5 分钟后盛出备用。 +3. 在开水中放入无骨肉,焯 4 分钟后盛出备用。 +4. 在开水中放入北京麻辣方便面,煮 2 分钟后盛出备用。 +5. 倒出开水,擦干锅具,放入 105 克食用油,大火加热 30 秒。 +6. 放入麻辣香锅调料,翻炒 20 秒。 +7. 放入干辣椒,翻炒 10 秒。 +8. 放入焯过的青菜,改中火,翻炒 3 分钟。 +9. 放入焯过的无骨肉,翻炒 3 分钟。 +10. 放入煮过的北京麻辣方便面,用筷子翻动 1 分钟。 +11. 关火,出锅。 + +## 附加内容 + +关于火候的说明: + +- 大火通常温度在 240 摄氏度,以电磁炉为例,输入功率大约 2 千瓦。 +- 中火通常温度在 120 摄氏度,以电磁炉为例,输入功率大约 1.4 千瓦。 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/黄焖鸡.md b/data/C8/cook/dishes/meat_dish/黄焖鸡.md new file mode 100644 index 0000000..bba035a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/黄焖鸡.md @@ -0,0 +1,58 @@ +# 黄焖鸡的做法 + +黄焖鸡是一道十分下饭的美食,食材平平无奇又十分容易烹制,一学就会。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡腿 +- 香菇(干香菇最佳) +- 青椒 +- 生姜片 +- 干辣椒 +- 盐 +- 料酒 +- 白胡椒粉 +- 白糖 +- 酱油 +- 味精 +- 土豆(可选) + +## 计算 + +- 鸡腿 = 两只 +- 香菇(干香菇最佳)= 5 朵 +- 青椒 = 两个 +- 生姜片 = 两片 +- 干辣椒 = 5,6 个 +- 盐 = 10g +- 料酒 = 10ml +- 白胡椒粉 = 5g +- 白糖 = 5g +- 酱油 = 5ml +- 土豆 = 一个(可选,可使汤汁更粘稠) + +## 操作 + +### 备菜阶段 + +- 鸡腿洗净,剁成**4cm**大小的块 +- 生姜切片、干辣椒切成**小圈** +- 香菇切片,青椒切成细长的**马蹄状**,若为干香菇,洗净灰尘后泡一晚上并留香菇水备用 +- 若有土豆,切为与鸡肉大小类似的**滚刀块** + +### 炒制阶段 + +- 炒糖色:锅里倒入底油,冷油时放入白糖(**有一定难度,新手可跳至鸡肉炒制并使用老抽替代**) +- 小火慢慢加热,待油温逐渐升高,白糖开始融化并变成较深的棕色(期间要不断搅拌,防止糊锅) +- 迅速倒入鸡块,转大火,快速翻炒!烹入料酒,继续翻炒片刻 +- 将生姜片和干辣椒倒入 +- 放入酱油,炒匀 +- 倒入香菇水或清水,以能淹住鸡肉为准 +- 倒入香菇片,白胡椒粉,盐,土豆 +- 翻炒均匀后,盖上锅盖焖煮,转中小火**15——20分钟**,有条件可以转至砂锅 +- 待鸡肉软烂,汤汁浓稠后(汤汁不要收的太干),最后放入青椒 +- 放入味精,兜炒均匀后,关火!青椒基本断生即可,不要炒时间久了 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/黄瓜炒肉.md b/data/C8/cook/dishes/meat_dish/黄瓜炒肉.md new file mode 100644 index 0000000..43437c5 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/黄瓜炒肉.md @@ -0,0 +1,41 @@ +# 黄瓜炒肉的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 黄瓜 +* 猪瘦肉 +* 食用油 +* 生抽 +* 盐 +* 蒜 +* 小米辣 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +* 黄瓜 = 100 克 * 份数 +* 猪肉 = 50 克 * 份数 +* 油量 = 50 克 * 份数 +* 盐量 = 10 克 * 份数 +* 酱油 = 5 克 * 份数 +* 蒜瓣 = 2 瓣 * 份数 +* 小米辣 = 1 根 * 份数 + +## 操作 + +* 将猪瘦肉切片,放入碗中,倒入食用油 10 克,生抽,搅拌均匀,腌制 10 分钟 +* 将黄瓜切去 5 厘米的头尾,剩余部分斜着切成 0.5 厘米的薄片 +* 将黄瓜倒入碗中,撒上盐 8 克,搅拌均匀,腌制 5 分钟 +* 将蒜瓣去皮,压扁,切成蒜末备用 +* 将小米辣去丁切分成均匀 0.5 厘米的段状 +* 热锅,倒油 40 克,等油温到冒烟,放入蒜蓉小米辣翻炒 5 次 +* 放入腌制好的猪瘦肉,翻炒至肉熟变色 +* 放入黄瓜,加入盐 2 克,大火翻炒均匀半分钟,出锅 + * 如果无法保证大火,可能会有点生。可以考虑增加到 50 秒。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/黑椒牛柳/黑椒牛柳.jpg b/data/C8/cook/dishes/meat_dish/黑椒牛柳/黑椒牛柳.jpg new file mode 100644 index 0000000..42fb769 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/黑椒牛柳/黑椒牛柳.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74ca83027454c83aa390d13401ff4c366b551bb063a84cc1104570c1a32f8fce +size 89269 diff --git a/data/C8/cook/dishes/meat_dish/黑椒牛柳/黑椒牛柳.md b/data/C8/cook/dishes/meat_dish/黑椒牛柳/黑椒牛柳.md new file mode 100644 index 0000000..aac34f6 --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/黑椒牛柳/黑椒牛柳.md @@ -0,0 +1,53 @@ +# 黑椒牛柳的做法 + +![黑椒牛柳成品](./黑椒牛柳.jpg) + +黑椒牛柳是一道简单易做的菜。蔬菜与肉类均衡,富含蛋白质,口味适合大多数人。一般初学者只需要 1 小时以内即可完成。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 牛肉(可以用牛里脊肉或者牛排肉) +- 洋葱 +- 菜椒(红/黄椒) +- 淀粉 +- 黑胡椒(粉) +- 黑椒(腌料) +- 盐 +- 花生油 + +注:粉与腌料可相互替代,具体用量请参照您购买的食品包装上的说明。 + +建议使用不粘锅。 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2-3 个人食用 + +总量: + +- 牛肉量 = 份数 * 100 克 (视就餐者胃容量和锅容量酌情增减) +- 洋葱量 = 份数 * 1/12 个(即 3 人时约切 1/4 ) +- 菜椒量 = 份数 * 1/12 个(即 3 人时约切 1/4 ) +- 盐量 = 份数 * 1 克 +- 淀粉 = 份数 * 3 克 +- 黑椒腌料 = 参照所购商品的说明按比例腌制 +- 黑胡椒粉 = 份数 * 1 克(实际上是随便撒) +- 花生油 = 份数 * 10ml (实际上油量是依据菜量变动的,如对牛肉的量有增减请按对应比例变动) + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +- 将牛肉切条,长度最好控制在 8 厘米以下,厚度约 5-10 毫米,宽度约 1 厘米(要求不严格) +- 利用腌料腌制牛肉,混合均匀后静置,用量与时间请参照商品说明,可以延长不能缩短。 +- 如果使用液态腌料,可以在腌制结束前三分钟撒一层黑胡椒粉,然后再加入淀粉,再次混合均匀后静置 20 分钟。 +- 开火,热锅,加入花生油。 +- 当能看到锅里的油冒出一丝烟时,放入牛肉,翻炒。 +- 开中火偏大,翻炒 2 分钟至牛肉外表变色(即不出现明显血色,有血色部分说明翻炒不到位)(此处应小心油滴溅射)。 +- 放入洋葱和菜椒,翻炒 2 分钟。 +- 加入盐,再次撒一份黑胡椒粉,翻炒 30 秒,搅拌均匀。 +- 观察洋葱已经变软即可关火,出锅,盛盘。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/meat_dish/黔式腊肠娃娃菜/黔式腊肠娃娃菜.jpg b/data/C8/cook/dishes/meat_dish/黔式腊肠娃娃菜/黔式腊肠娃娃菜.jpg new file mode 100644 index 0000000..e26237d --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/黔式腊肠娃娃菜/黔式腊肠娃娃菜.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d6cd2bc0e00cbce19a31c978a32c2e8326a23f47837fc4f10a370ea49e5b3ba0 +size 327261 diff --git a/data/C8/cook/dishes/meat_dish/黔式腊肠娃娃菜/黔式腊肠娃娃菜.md b/data/C8/cook/dishes/meat_dish/黔式腊肠娃娃菜/黔式腊肠娃娃菜.md new file mode 100644 index 0000000..cb08c8a --- /dev/null +++ b/data/C8/cook/dishes/meat_dish/黔式腊肠娃娃菜/黔式腊肠娃娃菜.md @@ -0,0 +1,33 @@ +# 黔式腊肠娃娃菜的做法 + +![黔式腊肠娃娃菜](./黔式腊肠娃娃菜.jpg) + +黔式腊肠娃娃菜不需要掌握火候,也无需调料,非常适合懒癌的菜。制作时间 15 分钟,口味近似于川菜、湘菜,却是西南菜系中鲜见的不辣菜式,咸鲜可口、南北皆宜。 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 黔式腊肠 +- 娃娃菜 + +## 计算 + +按照 1 人的份量: + +- 黔式腊肠 200g +- 娃娃菜 300g +- 水 750ml + +## 操作 + +- 锅内放入 750ml 水,开火加热至沸腾 +- 放入腊肠,计时 13 分钟 +- 放入娃娃菜,计时 2 分钟 +- 关火,夹出腊肠及娃娃菜 +- 娃娃菜切段、腊肠切片,装盘 + +## 附加内容 + +- 根据锅的大小,建议以水量没过食材为宜,宁多勿少 +- 如果没有刀具,娃娃菜和腊肠不切也可以 \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/凉皮.md b/data/C8/cook/dishes/semi-finished/凉皮.md new file mode 100644 index 0000000..1c2d46d --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/凉皮.md @@ -0,0 +1,55 @@ +# 凉皮的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 凉皮、面筋 +* 盐、鸡精、蚝油、生抽、老抽、香油、香醋、芝麻酱(原味芝麻酱最佳) +* 黄瓜、大蒜、绿豆芽 +* 盆、碗、盘子、蒜臼 + +## 计算 + +* 凉皮用量为 300 g/人 向下取整。 +* 芝麻酱的用量为 30 g/人 向下取整。 +* 黄瓜 100g/人、绿豆芽 50g/人。 + +## 操作 + +### 准备工作 + +* 锅中加入 500ml 水。煮沸。 +* 将绿豆芽放入锅中,大火煮 60 秒。豆芽捞出,过凉水,放入盘中备用。 +* 黄瓜切丝放入盘中备用 +* 将 10g 蒜瓣剥皮、放入蒜臼中加入 1g 盐。锤成蒜泥,加入 10g 自来水。放置备用。 +* 注:超市购买来的凉皮表面一般会有食用油,可以使用自来水清洗。面筋同样。 +* 注:清洗面筋之后,请用手将面筋中的大量水分挤出(不需过于用力)。 + +### 盐水调配 + +* 准备小碗,加入 3g 盐、2g 鸡精、5g 生抽、1g 老抽、1g 香油、2g 蚝油、香醋 5g、(盐、香醋均可根据个人口味酌量添加,以上数据只是大众口味)。 +* 以上调料加入 25-35g 温水(据个人咸淡程度),使用筷子将其拌匀、溶解。静置一旁冷却。 + +### 芝麻酱调配 + +* 注:以下计量均为一人份,如果有 n 人,请自觉将计量乘以 n +* 拿出小碗,将准备好的芝麻酱放入其中。 +* 加入 4g 盐、3g 鸡精、5g 生抽、1g 老抽、3g 蚝油。 +* 使用筷子将其调料与芝麻酱拌匀。 +* 加入 10g 清水将其拌匀。 +* 上一步骤重复 2、3 次(次数根据个人对芝麻酱的浓稠程度而定)。 + +### 最终步骤 + +* 拿出之前准备好的小盆,加入之前准备好的凉皮。 +* 倒入盐水,使用筷子将其拌匀。随之盛入小碗(盐水一并倒入碗中)。 +* 豆芽放置凉皮上、面筋随后放上。 +* 将调配好的芝麻酱从面筋上方倒下。 +* 撒上黄瓜丝。 +* 如有喜爱可以加入辣椒油。 +* 色香味俱全的家常凉皮出炉! + +## 附加内容 + +个人口味根据地区、天气、时间均有不同,调料的具体使用量请据个人情况而定。 \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/半成品意面.md b/data/C8/cook/dishes/semi-finished/半成品意面.md new file mode 100644 index 0000000..fe636c3 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/半成品意面.md @@ -0,0 +1,43 @@ +# 半成品意面的做法 + +意大利面🍝和中国面条口感上的区别主要是因为它是由小麦品种中最硬质的杜兰(durum)磨粉制成的。 + +预估烹饪难度:★ + +## 必备原料和工具 + +* 1 袋 半成品意大利面(推荐品牌圃美多) +* 50 ml 清水 +* 平底锅 或 微波炉 + +> 不同类型的意面烧制时长有所不同,这里是意大利直面的标准。 + +## 计算 + +- 2 人 1 顿 520g(以半成品为准) + +> 使用上述条件,按需求(包括但不限于日常食量、心情和饭前运动情况)计算材料用量。 + +## 操作 + +### 方法一 - 平底锅 + +- 热锅 +- 将 50 ml 清水倒入平底锅 +- 将面条放入,炒 1 分钟 +- 将酱料倒入,翻炒 1 分钟 +- 装盘即可 + +### 方法二 - 微波炉 + +- 将面条放入「可用于微波炉加热」的盘子中 +- 将附带的酱料倒在面条上 +- 倒入 50 ml 清水 +- 700W 加热 2 分钟 +- 取出拌匀即可 + +## 附加内容 + +- 传统意大利面非常长。20 世纪下半叶开始流行短的意大利粉,典型长度 25–30 cm。 +- “Spaghettoni”是较厚的意大利粉。“Spaghettini”较细的意大利面。“capellini”是更细版的意大利面。 +- 一个不可见,且不可感知的“飞行着的意大利面条怪物”在“一次严重的酗酒后”,创造了整个宇宙。 \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/懒人蛋挞/懒人蛋挞.md b/data/C8/cook/dishes/semi-finished/懒人蛋挞/懒人蛋挞.md new file mode 100644 index 0000000..ca0c3d3 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/懒人蛋挞/懒人蛋挞.md @@ -0,0 +1,32 @@ +# 懒人蛋挞的做法 + +![蛋挞成品](./懒人蛋挞.png) + +蛋挞是一道常见的可口甜品,通常而言制作蛋挞是需要调和蛋挞液和制作蛋挞皮的,这个过程比较复杂和耗时,但是网购半成品恰恰解决解决以上的难题,初学者只需大约 40 分就可以完成。从今往后只要家里有烤箱,就可以化身烘焙达人,帮家人烤蛋挞! + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 需要烤箱 1 个(有上下火功能的最佳,也可以没有) +- 隔热手套 1 双 +- 网购蛋挞液 1 盒,蛋挞皮 1 盒(附近的大超市也可以,比如家乐福、沃尔玛等等) + +## 计算 + +每份: + +- 蛋挞皮 1 个 +- 蛋挞液约 10ml,到达挞皮的 4/5 最佳 + +## 操作 + +- 烤箱 200 度,预热 10 分钟 +- 在烤盘上放上蛋挞皮,蛋挞皮中倒入蛋挞液约 10ml,具体分量需要看蛋挞皮大小,通常倒入 4/5 即可 +- 将烤盘放入烤箱内,上下火 190 度,烤 10 - 20 分。如果想快速烤出蛋挞液上的焦褐斑点,需要上火更高一些,通常是 200 - 210 度 +- 蛋挞液烤出焦褐斑点,蛋挞皮完全蓬松冒油即可 + +## 附加内容 + +- 操作时,可以根据焦褐斑大小适当调整时间,如果需要 +- 可以在蛋挞中加 10g 碎芝士,就是一道芝士蛋挞啦~ \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/懒人蛋挞/懒人蛋挞.png b/data/C8/cook/dishes/semi-finished/懒人蛋挞/懒人蛋挞.png new file mode 100644 index 0000000..81a0655 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/懒人蛋挞/懒人蛋挞.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89544396fa70bcd76d6489c9d343e59d31ec0ec3405e840e23b14f774344f1a8 +size 659940 diff --git a/data/C8/cook/dishes/semi-finished/炸薯条/炸薯条.jpg b/data/C8/cook/dishes/semi-finished/炸薯条/炸薯条.jpg new file mode 100644 index 0000000..0b46a15 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/炸薯条/炸薯条.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f307f51d716674a1f22027277f8f66282233a431af3456582e9fcc978ee6f9b +size 391271 diff --git a/data/C8/cook/dishes/semi-finished/炸薯条/炸薯条.md b/data/C8/cook/dishes/semi-finished/炸薯条/炸薯条.md new file mode 100644 index 0000000..ac95569 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/炸薯条/炸薯条.md @@ -0,0 +1,51 @@ +# 炸薯条的做法 + +![炸薯条](./炸薯条.jpg) + +薯条🍟是一种土豆🥔\马铃薯🥔\洋芋🥔切成条状之后再油炸而成的快餐食物(在有的国家可能不算快餐),非常适合。相较于油炸,空气炸锅可能会更加易于避免崩溃和实现异步非阻塞。相较于自己动手切土豆再洗去淀粉并喷上油,使用半成品薯条可能会显著减少热量摄入前的热量消耗,四舍五入就是会显著减少热量摄入~~前的热量消耗~~。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 1 袋半成品薯条(推荐品牌麦肯) +- 1 个空气炸锅(喜欢脆的切忌小牌子) + +> 注意,使用的烹饪工具不同炸薯条可能有不同的做法,这里仅介绍使用「空气炸锅」的做法。 + +## 计算 + +- 作为主食,1 人 1 顿 400g(以半成品为准) +- 作为小食,1 人 1 顿 1/4 主食质量+-50g + +> 使用上述条件,按需求量(包括但不限于日常食量、心情和饭前运动情况)计算材料用量。 + +## 操作 + +### 开封薯条 + +- 开封大分量半成品薯条注意开口要小,可以有效减少长久储藏下薯条表面结霜。 + +### 预热空气炸锅 + +- 插电,200℃预热 5 分钟。 +- 预热的目的是为了确保放入食材的时候锅内温度已经处于烹饪所需温度。 +- 注意,预热完再拿出薯条,不应等薯条软化后再炸制。 + +### 炸薯条 + +- 取出薯条放入空气炸锅,200℃20 分钟。 +- 取出薯条的时候注意半成品薯条已经有油,所以要异步去做客户端内刀斯林的话需要使用夹持工具。 +- 5~10 分钟时可以拿出锅体晃动使薯条受热均匀也防止粘连。 + +### 脆化(可选项) + +- 10 分钟~15 分钟时,拿出锅体,往已经干了的薯条表面喷 1 层面积为薯条表面积 2/3 的油。 + +### 取出&装盘 + +- 喜欢脆薯条的,取出后拿着锅体跳舞让空气经过薯条表面后装盘;喜欢软薯条的直接装盘。配合蘸酱或浇上酱汁更佳。 + +## 附加内容 + +- 番茄酱、蛋黄酱、蜂蜜芥末酱、[蒜香酱油](../../condiment/蒜香酱油.md)……炸薯条的晋级之路在于对酱料及酱料组合的探究。 \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/牛油火锅底料.md b/data/C8/cook/dishes/semi-finished/牛油火锅底料.md new file mode 100644 index 0000000..81c0efe --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/牛油火锅底料.md @@ -0,0 +1,94 @@ +# 牛油火锅底料的做法 + +重庆火锅又称毛肚火锅或麻辣火锅,是中国传统饮食方式之一。 + +其起源于明末清初的重庆嘉陵江畔,该菜式也是朝天门等码头船工纤夫的粗放餐饮方式。 + +其主要原料是牛毛肚、猪黄喉、鸭肠、牛血旺等。 + +一般初学者只需要 1 小时即可完成。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +### 原料 + +- 牛油 4500 g +- (色拉油 或 菜籽油) 1000 ml +- 纯猪油 500 g +- 豆瓣(郫县) 1000 g +- 糍粑辣椒 3000 g +- 老姜(切片) 250 g +- 大葱(切段) 100 g +- 洋葱(切丝) 100 g +- 大蒜(切片) 200 g +- 豆鼓(剁碎)(永川) 10 g +- 豆母子 140 g +- 红花椒 150 g +- 老油 ? 颗粒香料 100 g : 整形香料 150 g +- 麦芽粉(肉香) 12.5 g +- 白酒(52%VOL) 150 ml +- 老油 ?? 干辣椒面 15 g + +### 香料 + +- 山奈 5 g +- 八角 10 g +- 草果 10 g +- 肉桂 10 g +- 丁香 5 g +- 小茴香 10 g +- 白芷 10 g +- 荜拨 5 g +- 香草 10 g +- 香果 10 g +- 山楂 10 g +- 陈皮 5 g +- 香茅 10 g +- 砂仁 10 g +- 白蔻 10 g +- 香叶 10 g + +#### 颗粒香料 + +以上配料放入粉碎机打碎至大约 4 mm 颗粒备用。 + +#### 整形香料 + +以上配料洗净备用。 + +### 工具 + +- 粉碎机 + +## 计算 + +- 每份原料可制作 7.5 kg 火锅底料/火锅老油 + +## 操作 + +- 锅置旺火(大火)放入牛油烧至 八成热(240±10°C) 时放入 `老姜、大葱、洋葱、大蒜 (各100g)`,炸干(吸尽异味(牛油腥味))后捞出扔掉。 +- 放入 `(色拉油 || 菜籽油)、纯猪油`,等待锅中油温下降到 五成热(150±10°C) 时放入 `糍粑辣椒` 持续翻炒 5-8 分钟。 +- 放入 `豆瓣` 炒散,转用 **中小火** 慢炒至料渣略发白翻砂(发出沙沙声)。 +- 油在外观呈现樱桃红时放入 `姜片(150g)、大蒜(100g)` 炒香,大约 15 秒。 +- 放入 `豆鼓、豆母子` 炒香,放入 `红花椒、小茴香` 炒香。 +- (老油) 此刻放入 颗粒香料 +- 放入 `麦芽粉` 炒散,放入 `白酒` 炒散。 + +### 作为底料 + +- 起锅装入容器中,静置于温度低的环境(10-20) 5 天后再使用效果最佳。 + +### 作为老油 + +- 起锅装入容器中放入 `干辣椒面` 搅匀置放 24 小时,等待制作 **老油**。 +- 将底料倒入锅中,加入 3/5 的开水用大火烧开 (底料:2/5 开水:3/5)。 +- 烧开后表面会出现泡沫,将泡沫撇净。 +- 转用 **中小火** 慢熬出味(约 25-30 分钟),过滤去渣。 +- 等待容器中 **油水分离** 后,将表面的 **油** 撇净(将油打出来) 装入另外的容器。 +- 将上一步所 **撇** 出来的 **油** 重新倒入 **净锅** 中,直至 **炼干** 油中水分起锅装入容器即为 **火锅老油**。 + +## 附加内容 + +- **警告:操作时请擦干手上水滴!以免水进入油锅中发生爆炸!造成严重烧伤!** \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/空气炸锅羊排/空气炸锅羊排.md b/data/C8/cook/dishes/semi-finished/空气炸锅羊排/空气炸锅羊排.md new file mode 100644 index 0000000..3f928b5 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/空气炸锅羊排/空气炸锅羊排.md @@ -0,0 +1,39 @@ +# 空气炸锅羊排的做法 + +![示例菜成品](./羊排.jpg) + +空气炸锅羊排超级懒人版,味道尚可,主要看羊排的品质。 + +- 烹饪总时长:40 分钟(准备 5 分钟+腌制 20 分钟+下锅 15 分钟) +- 实际操作时间:10 分钟 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 必备:羊排(推荐 JD 购买大庄园 新西兰进口 羔羊法式肩排,500g/袋共三片,JD 打折的话 42 元) +- 必备:黑椒混合牛排调味料(懒) +- 必备:蒜蓉酱(推荐川娃子的,同样是因为懒) +- 必备:厨房纸 +- 可选:黄油(JD 买小盒装的,一片一小盒) +- 可选:烧烤料 +- 可选:罗勒碎 +- 可选:空气炸锅烤架(用烤架油比较少,底下更容易熟,洗起来麻烦。不用的话比较入味。看个人选择啦) + +## 计算 + +- 羊排 1 片约 160g +- 黑椒混合牛排调味料 5g +- 蒜蓉酱 20g +- 黄油 1 小盒 10g 或 烧烤料 20g + +## 操作 + +- 羊排放入碗中清水洗净血水 +- 羊排用厨房纸吸干水分,双面抹上黑椒混合调味料、蒜蓉酱,静置腌制 20 分钟 +- 锡纸碗放上烤架,羊排放在烤架上,撒上罗勒碎,黄油或烧烤料放在羊排上,空气炸锅 180° 10 分钟 +- 羊排翻面,撒上罗勒碎,黄油(从锡纸碗里舀上来)或烧烤料放在羊排上,空气炸锅 180° 5 分钟(可以视个人喜好加一点时间,这里写的是不会焦的时间) + +## 附加内容 + +- 推荐购买温控比较好的空气炸锅,不然可能会糊 \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/空气炸锅羊排/羊排.jpg b/data/C8/cook/dishes/semi-finished/空气炸锅羊排/羊排.jpg new file mode 100644 index 0000000..73ca076 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/空气炸锅羊排/羊排.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d934589b30ef560f645accc5ecaca383713f00cf23b702bc52695e4424cdfca +size 568327 diff --git a/data/C8/cook/dishes/semi-finished/空气炸锅鸡翅中/空气炸锅鸡翅中.md b/data/C8/cook/dishes/semi-finished/空气炸锅鸡翅中/空气炸锅鸡翅中.md new file mode 100644 index 0000000..3f7121a --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/空气炸锅鸡翅中/空气炸锅鸡翅中.md @@ -0,0 +1,31 @@ +# 空气炸锅鸡翅中的做法 + +![鸡翅中](./鸡翅中_0.jpg) +![鸡翅中](./鸡翅中_1.jpg) + +空气炸锅做鸡翅中方便,这样自带油脂的食物味道很好,比 KFC 的好吃,吃完不**用洗碗洗锅**。 + +- 烹饪时长:40 分钟(准备 3 分钟+解冻 20 分钟+下锅 17 分钟) +- 实际操作时间:5 分钟 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 必备:鸡翅中(推荐买泰森的奥尔良鸡翅中,JD 打折的话 30 多一袋 454g 大概 12 个。上鲜和圣农的也买过,没这个方便。泰森的是腌好的,如果有时间的话可以买没腌的自己腌。) +- 可选:罗勒碎(撒上去纯粹为了好看) +- 可选:云南单山蘸水(代替烧烤料) + +## 计算 + +- 鸡翅中 6 个(泰森奥尔良鸡翅中,其他品牌例如圣农嘟嘟翅可能会大一些,请自行根据食量斟酌) + +## 操作 + +- 鸡翅从冰箱拿出来,鸡翼面朝下放入锡纸烤盘,撒上罗勒碎,盖上保鲜膜自然解冻 20 分钟 +- 撒上罗勒碎,空气炸锅 200°C,10 分钟 +- 翻面,撒上罗勒碎,空气炸锅 200°C,7 分钟 + +## 附加内容 + +- 推荐购买温控比较好的空气炸锅,不然可能会糊 \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/空气炸锅鸡翅中/鸡翅中_0.jpg b/data/C8/cook/dishes/semi-finished/空气炸锅鸡翅中/鸡翅中_0.jpg new file mode 100644 index 0000000..ea71123 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/空气炸锅鸡翅中/鸡翅中_0.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfb07d57f5ae71e8e8120064fe43da126ad053c7eba3f0b035be00ea1ef99d0e +size 545083 diff --git a/data/C8/cook/dishes/semi-finished/空气炸锅鸡翅中/鸡翅中_1.jpg b/data/C8/cook/dishes/semi-finished/空气炸锅鸡翅中/鸡翅中_1.jpg new file mode 100644 index 0000000..579a8df --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/空气炸锅鸡翅中/鸡翅中_1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:003fd38c64f6dbab93dcc21e6ce7a679222e4763d917175953c0a4c1e5da7867 +size 551315 diff --git a/data/C8/cook/dishes/semi-finished/速冻水饺.md b/data/C8/cook/dishes/semi-finished/速冻水饺.md new file mode 100644 index 0000000..54a00be --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/速冻水饺.md @@ -0,0 +1,43 @@ +# 速冻水饺的做法 + +饺子是一种源自中国的一种以面皮包馅、形如半月或元宝形的食物。饺子是在农历新年和冬至等节日的重要食品。通常由碎肉和蔬菜馅料包裹成一片薄生面团后包好密封。而饺子的缺点在于难以制作。不妨选择购买速冻水饺来快速在家里吃上热气腾腾的饺子。 + +预估烹饪难度:★ + +## 必备原料和工具 + +* 未过期的一袋速冻水饺 + +## 计算 + +* 一般一个人可以食用 7~10 个水饺 +* 一个水饺约需要本身体积两倍的水(饺子倒入锅内时,水的高度应一至两倍于饺子的高度,即饺子高度为 1,水高度则为 1~2) + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +* 中火,将水倒入锅中,静候水煮沸。 +* 将饺子倒入锅中。 +* 倒入锅前可以适当用水过一下。 +* 倒入饺子后,可以用炒菜勺子或铲子搅水,但要注意不要铲到饺子上,以避免粘锅上撕破皮或互相粘连造成粘连处夹生。 +* 频率不需要太高,平均每 `30` 秒摇 `3` 秒,饺子浮起后不需要再做此步。 +* 饺子浮起及水再次煮沸后,用炒菜勺子盛起一个饺子观察,如果面皮有夹生可用炒菜勺子舀入 80ml 凉水,将水降温,然后继续煮至沸腾,此间重复此观察、搅拌操作,最多加两次水就能全熟。 +* 所有饺子浮起后(下饺子后约 8 分钟)用铲子或漏勺把饺子铲入盘或碗中,装盘后即可食用。 +* 吃完饺子后,等锅内水温降低,将水倒掉并用洗洁精及时刷锅,不然过段时间锅内煮过的面粉会在锅壁形成黏糊糊的物质。 + +## 附加内容 + +这道菜存在一些补充做法,包括但不限于: + +额外添加下列材料: + +* 黑醋 10ml +* 姜 一小块 50 克 +* 香油 2 滴 +* 大蒜/蒜泥 3 瓣/人 + +* 考虑搭配黑醋食用。建议用量:10-20ml。 +* 考虑姜切丝,在小碗加入 20ml 的黑醋与姜丝搅拌当蘸料,味道更丰富。 +* 考虑搭配黑醋时加入 1~3 滴香油,搅拌当蘸料。 +* 考虑搭配黑醋时加入砸好的蒜泥,搅拌当蘸料。(口腔内会残留蒜味,若饭后需要与他人面对面谈话建议放弃或清洁口腔) \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/速冻汤圆/速冻汤圆.jpg b/data/C8/cook/dishes/semi-finished/速冻汤圆/速冻汤圆.jpg new file mode 100644 index 0000000..6887d06 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/速冻汤圆/速冻汤圆.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c873955d6f4782cdde126f1ab0b96d0870dce35a72ef9b7f71c0078634b221c0 +size 490819 diff --git a/data/C8/cook/dishes/semi-finished/速冻汤圆/速冻汤圆.md b/data/C8/cook/dishes/semi-finished/速冻汤圆/速冻汤圆.md new file mode 100644 index 0000000..abceb60 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/速冻汤圆/速冻汤圆.md @@ -0,0 +1,31 @@ +# 速冻汤圆的做法 + +![速冻汤圆](./速冻汤圆.jpg) + +速冻汤圆是一道简单易做的菜。一般初学者只需要 6 分钟即可完成。 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 速冻汤圆 +- 微波炉 + +## 计算 + +每份: + +- 速冻汤圆:11 个。数量取决于碗的大小。保证放入的汤圆最高不超过碗高度 - 5mm。 + +## 操作 + +- 取出速冻汤圆,放入碗中。 +- 倒入开水,直至浸没汤圆。 +- 微波炉高火 4 分钟。 +- 假如汤圆均已吸水膨胀,则已熟。 +- 如果没熟,再加热 1 分钟。 + +## 附加内容 + +- 注意先加汤圆再加热水,不要颠倒,不然汤圆倒入热水可能会溅出烫伤。以及无法控制水面高度可能溢出。 +- 假如微波炉里碗太烫无法取出,可以用毛巾,或者某些微波炉可以连托盘一起取出。 \ No newline at end of file diff --git a/data/C8/cook/dishes/semi-finished/速冻馄饨.md b/data/C8/cook/dishes/semi-finished/速冻馄饨.md new file mode 100644 index 0000000..c83d4b3 --- /dev/null +++ b/data/C8/cook/dishes/semi-finished/速冻馄饨.md @@ -0,0 +1,48 @@ +# 速冻馄饨的做法 + +馄饨是一种起源于中国的一种民间传统面食,[饺子](./速冻水饺.md)由其分化而出,有皮薄馅嫩、汤清味鲜的特点。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 未过期的一袋速冻馄饨(自带调味料包更佳) +* 电饭煲(推荐品牌小米智能电饭煲) +* 盐(速冻馄饨无调味料包时) +* 鸡精(速冻馄饨无调味料包时) +* 胡椒粉(速冻馄饨无调味料包时) +* 香油(速冻馄饨无调味料包时) +* 香菜 1 根(可选) + +> 注意,使用的烹饪工具不同速冻馄饨可能有不同的做法,这里仅介绍使用「电饭煲」的做法。 + +## 计算 + +* 一般一个人一顿可以食用 12~20 个馄饨 +* 当所有馄饨放入电饭煲中时,能刚好没过所有馄饨的水乘以 2~3 倍的水量(一人食用的馄饨约需要 600ml 水量) + +## 操作 + +### 烧开水 + +* 将水倒入电饭煲中,按炖或煮的模式运行 35 分钟,此时揭开电饭煲应看到水为沸腾状态。 + +### 下馄饨 + +* 将速冻馄饨小心放入水中,注意不要烫伤。 +* 放入电饭煲前可以适当用水过一下。 +* 如果馄饨有调料包,此时可一并加入水中。 + +### 煮馄饨 + +* 盖上电饭煲,按同样炖或煮的模式运行 20 分钟。 + +### 盛馄饨 + +* 将所有馄饨连同能没过所有馄饨的水一同盛入碗中。 +* 如果此前没有加入调料包,此时可按自身口味轻重加入盐、鸡精、胡椒粉、香油调味。 +* 也可撒上 5~8 片香菜叶佐味(仅适用于对香菜味道不敏感的人)。 + +## 附加内容 + +* 出锅后也可以加入水煮荷包蛋([太阳蛋](../../dishes/breakfast/太阳蛋.md))一起食用。 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/勾芡香菇汤/1.jpeg b/data/C8/cook/dishes/soup/勾芡香菇汤/1.jpeg new file mode 100644 index 0000000..be7bd6c --- /dev/null +++ b/data/C8/cook/dishes/soup/勾芡香菇汤/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64c6aa506d788f66034dd3322eba1af825cec9505956be1f6b41f2595083caa9 +size 111653 diff --git a/data/C8/cook/dishes/soup/勾芡香菇汤/2.jpeg b/data/C8/cook/dishes/soup/勾芡香菇汤/2.jpeg new file mode 100644 index 0000000..6321108 --- /dev/null +++ b/data/C8/cook/dishes/soup/勾芡香菇汤/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66e16cecb8cf8a329c36f78b7edcdcdcf8f5ab7f8c8c7fe1ba13ba3c06af9987 +size 93096 diff --git a/data/C8/cook/dishes/soup/勾芡香菇汤/3.jpeg b/data/C8/cook/dishes/soup/勾芡香菇汤/3.jpeg new file mode 100644 index 0000000..7c1f51a --- /dev/null +++ b/data/C8/cook/dishes/soup/勾芡香菇汤/3.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:244a9b12ed25f461cfc6661032538e50e8c76c8b6b9a50b12d72fcefb161dd8d +size 156342 diff --git a/data/C8/cook/dishes/soup/勾芡香菇汤/勾芡香菇汤.md b/data/C8/cook/dishes/soup/勾芡香菇汤/勾芡香菇汤.md new file mode 100644 index 0000000..ce5773a --- /dev/null +++ b/data/C8/cook/dishes/soup/勾芡香菇汤/勾芡香菇汤.md @@ -0,0 +1,43 @@ +# 勾芡香菇汤的做法 + +鲜香菇除了拿来和肉炒外,其实拿来做浓浓的勾芡汤也是非常可口的。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 香菇 +* 香葱 +* 食用油 +* 食用盐 +* 鸡精 +* 生粉 + +## 计算 + +每份: + +* 鲜香菇 2 朵 +* 香葱 0.5 根 +* 鸡精 3 g +* 食用油 10 ml +* 食用盐 3 g +* 开水 350 ml +* 生粉 10 g + +## 操作 + +* 香菇切片(每片厚度 0.5-1 cm,厚点相对薄点更有嚼劲),放入大碗中,倒入 2g 食用盐 浸泡 15 分钟 +* 生粉倒入小碗中,加入 50ml 水,搅拌生粉直至融化没有颗粒(即水淀粉) +* 倒掉碗中的盐水,适当去掉香菇本身的水分(方便下一步煎炸)【可选】 +* 小火,倒入油,待油开始冒小泡(小火 30s ,看每个锅的功率),倒入香菇,每面煎 10s 【可选】 +* 倒入开水 300ml ,调中火再煮 3-5 分钟 +* 倒入水淀粉,适当搅拌锅中汤汁后,加入 3g 盐、3 g ,最后撒上葱花出锅 + +![示例菜成品](./1.jpeg) + +![示例菜成品](./2.jpeg) + +![示例菜成品](./3.jpeg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/奶油蘑菇汤.md b/data/C8/cook/dishes/soup/奶油蘑菇汤.md new file mode 100644 index 0000000..478b48d --- /dev/null +++ b/data/C8/cook/dishes/soup/奶油蘑菇汤.md @@ -0,0 +1,58 @@ +# 奶油蘑菇汤的做法 + +预估烹饪难度:★ + +--- + +## 必备原料和工具 + +- 白蘑菇 +- 洋葱 +- 黄油 +- 面粉 +- 牛奶 +- 淡奶油 +- 黑胡椒碎 +- 盐 +- 清水 + +--- + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1~2 人食用。 + +总量(按每份): + +- 白蘑菇 200 克 +- 洋葱 50 克 +- 黄油 15 克 +- 面粉 10 克 +- 牛奶 200 毫升 +- 淡奶油 30 毫升 +- 清水 100 毫升 +- 盐 2 克 +- 黑胡椒碎 1 克 + +--- + +## 操作 + +1. 白蘑菇切片备用,洋葱切末备用。 +2. 平底锅中放入黄油,小火融化后加入洋葱炒至透明。 +3. 加入白蘑菇翻炒至出水变软,撒入面粉搅拌均匀。 +4. 加入牛奶和清水,搅拌均匀后小火煮沸,保持搅拌防止糊底。 +5. 转小火煮约 10 分钟,汤汁浓稠。 +6. 倒入淡奶油继续加热 1 分钟,加入盐和黑胡椒调味。 +7. 熄火后可用料理机打成细腻浓汤(可选)。 + +--- + +## 附加内容 + +- 可将部分蘑菇预留作为装饰,提前煎香再添加。 +- 使用鸡高汤代替清水风味更佳,建议控制总液体不超过 300 毫升/份。 +- 喜欢浓汤口感可适当增加面粉和淡奶油用量。 +- 建议现做现吃,不建议冷藏或冷冻保存。 + +--- \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/小米粥.md b/data/C8/cook/dishes/soup/小米粥.md new file mode 100644 index 0000000..9a354c4 --- /dev/null +++ b/data/C8/cook/dishes/soup/小米粥.md @@ -0,0 +1,36 @@ +# 小米粥的做法 + +小米含有多种维生素、氨基酸、脂肪和碳水化合物,营养价值较高,每 100 克小米含蛋白质 9.7 克、脂肪 3.5 克,都不低于稻、麦。 + +一般粮食中不含有的胡萝卜素,而小米每 100 克含量 0.12 毫克,维生素 B1 的含量位居所有粮食之首。 + +小米含糖也很高,每 100 克含糖 72.8 克,产热量比大米高许多。另外,小米也富含维生素 B1,B2 等 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 小米 +- 水(山泉水最佳) + +## 计算 + +- 小米 100 克 +- 水(山泉水最佳) 2000 克 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +* 小米 100 克,放入碗中,用水轻淘一遍(用手搅拌一下,将水倒掉,只是去掉外面的浮灰,不可搓洗!!!) +* 水烧开,务必烧开!!! +* 水烧开沸腾时,将小米倒入锅内。(很容易被忽视的一个很重要的环节) +* 搅拌使得小米不会粘连锅底,继续用大火熬 6-10 分钟,注意用中间穿插搅拌几次。 +* 改中火、文火熬 15-20 分钟,锅盖要错开一条缝,千万不能让小米油溜掉哟,中间继续搅拌几次,不要糊锅底 + +## 附加内容 + +* 这是普通锅熬制(只需 30-35 分钟即可出锅),味道最佳。高压锅和电饭锅省事,不过效果下降,水量要适当减少,一般 100 克小米+1800 克水 +* 小米只需用水去除浮灰,千万不可过分淘,会损失掉小米油的 +* 千万记住小米需要在水开的时候下锅 +* 不喜欢放碱,更喜欢原汁原味的小米香 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/排骨苦瓜汤/排骨苦瓜汤.md b/data/C8/cook/dishes/soup/排骨苦瓜汤/排骨苦瓜汤.md new file mode 100644 index 0000000..90deab6 --- /dev/null +++ b/data/C8/cook/dishes/soup/排骨苦瓜汤/排骨苦瓜汤.md @@ -0,0 +1,50 @@ +# 排骨苦瓜汤的做法 + +排骨苦瓜汤是一道味道鲜美且容易烹饪的汤。不过汤的烹饪时间都较长,一般来说最好提前 4 个小时开始进行准备。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +可选工具 + +- 电压力锅(可以极大简化烹饪过程和时间) +- 砂锅(相比于炒锅更适合炖汤) + +必须材料 + +- 排骨 +- 苦瓜 +- 虾皮 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 4 个人吃。 +每份: + +- 排骨 250g 到 500g +- 苦瓜 100g 到 200g +- 虾皮 5g 到 15g +- 生姜 5~10g(可选,用于焯水时去腥) + +## 操作 + +- 排骨洗净,切到约 4cm ±2cm * 3 ± 2cm 的小块(如没有剁排骨的工具,可以求助摊主) +- 炒锅倒入冷水 700ml 和排骨一起加热至煮沸,关火捞出排骨 +- 苦瓜中间切为两半,清除干净内部的种子和苦瓜瓤,切为 0.5 ± 0.3 cm 的苦瓜条,洗净 + + 使用汤锅进行烹饪 + + - 汤锅倒入水 1100ml 和排骨,大火 + - 等待水沸腾后将苦瓜和虾皮下锅转小火,放等待 120~240 分钟(在 120 分钟之后可以捞出一块肉进行品尝,若肉可以较为轻松的从骨头上分离即可关火) + - 出锅时加盐和白胡椒,推荐量为每 250ml 0.3 到 0.6g 盐,0.1 到 0.5g 白胡椒 + + 使用电压力锅进行烹饪 + + - 倒入 1000ml 水和排骨,虾皮和苦瓜 + - 选择炖汤功能,进行烹饪(一般为加压烹饪 45 分钟) + - 出锅,和汤锅一样进行加盐和胡椒 + +## 附加内容 + +- 可以使用其他带有鲜味的食材代替虾皮,如瑶柱 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/昂刺鱼豆腐汤.md b/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/昂刺鱼豆腐汤.md new file mode 100644 index 0000000..d905016 --- /dev/null +++ b/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/昂刺鱼豆腐汤.md @@ -0,0 +1,45 @@ +# 昂刺鱼豆腐汤的做法 + +- 昂刺鱼/沙光鱼 豆腐汤 刺少 肉嫩 营养丰盛、适合任何年龄的小伙伴 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 昂刺鱼或者沙光鱼 +* 豆腐 +* 香葱 +* 姜 +* 食用油 +* 料酒 +* 食用盐 +* 胡椒粉 + +## 计算 + +每份: + +* 昂刺鱼或者沙光鱼 一条 +* 豆腐 100 g +* 香葱 一根 +* 姜 一块 +* 胡椒粉 3-5 g +* 食用油 15 ml +* 食用盐 10-15 g +* 开水 1L + +## 操作 + +* 鱼处理好后洗净,(特别注意肚内的血丝、不洗干净会有腥味),放入大碗中,倒入料酒、10g 姜片、5g 盐,腌制 15 分钟 +* 豆腐切块,放入凉水浸泡 5 分钟,捞出备用 +* 煎鱼前,先用生姜片擦一下锅防止粘锅,倒入油(油量为 15ml * 鱼的条数 ),烧热后放入鱼煎 2~3 分钟,期间需要晃动一下鱼,防止粘底,且需要翻一次身 +* 待鱼全部煎好之后,倒入开水、5ml 料酒、姜片,小火转至大火,盖上锅盖、大火煮 10 分钟(水要稍微多一些,后面会蒸发掉一些) +* 见汤变白后倒入准备好的豆腐,调中火再煮 5 分钟,加入 10g 盐、3g 胡椒粉调味,最后撒上葱花出锅 + +![示例菜成品](./沙光鱼豆腐汤.jpg) + +![示例菜成品](./昂刺鱼豆腐汤01.jpg) + +![示例菜成品](./昂刺鱼豆腐汤02.jpg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/昂刺鱼豆腐汤01.jpg b/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/昂刺鱼豆腐汤01.jpg new file mode 100644 index 0000000..c60ddc2 --- /dev/null +++ b/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/昂刺鱼豆腐汤01.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0005e2cf5436c419e86098fbd44da20bf914eb998a0e3229cf33b622b624d2bc +size 282973 diff --git a/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/昂刺鱼豆腐汤02.jpg b/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/昂刺鱼豆腐汤02.jpg new file mode 100644 index 0000000..d9809db --- /dev/null +++ b/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/昂刺鱼豆腐汤02.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b862b61f45b5b74e6f98740fb12a7d6e42c8b83c8d0c59d2bce479404247b472 +size 258482 diff --git a/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/沙光鱼豆腐汤.jpg b/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/沙光鱼豆腐汤.jpg new file mode 100644 index 0000000..455605b --- /dev/null +++ b/data/C8/cook/dishes/soup/昂刺鱼豆腐汤/沙光鱼豆腐汤.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4fbd591613dcd80ca74bff2176b0b8a173bef7cd44f309b147dc18c04fe523c +size 176307 diff --git a/data/C8/cook/dishes/soup/朱雀汤/朱雀汤.jpg b/data/C8/cook/dishes/soup/朱雀汤/朱雀汤.jpg new file mode 100644 index 0000000..5e453b1 --- /dev/null +++ b/data/C8/cook/dishes/soup/朱雀汤/朱雀汤.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90606125701e0de752a20c9c9428d6988a3c5ba52be306b541978ae23fb408b3 +size 319626 diff --git a/data/C8/cook/dishes/soup/朱雀汤/朱雀汤.md b/data/C8/cook/dishes/soup/朱雀汤/朱雀汤.md new file mode 100644 index 0000000..565c36d --- /dev/null +++ b/data/C8/cook/dishes/soup/朱雀汤/朱雀汤.md @@ -0,0 +1,33 @@ +# 朱雀汤的做法 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 鸡蛋 +- 香油(芝麻油) +- 白糖 +- 水 + +## 计算 + +按照 1 人份的份量: + +- 一个鸡蛋 +- 500ml 水 +- 20 克白糖(根据个人口味调整) +- 2ml 香油 + +## 操作 + +- 鸡蛋在碗中打散,再倒入香油。 +- 水烧开后,在沸腾状态下快速倒入盛有鸡蛋的碗中。 +- 放入白糖。 + +![示例菜成品](./朱雀汤.jpg) + +## 附加内容 + +- 鸡蛋一定要打散,水一定要在沸腾冒泡状态倒入鸡蛋液中,否则汤可能会浑浊影响口感 +- 此为豫东地区做法,其他地区有不放白糖放盐的,口味不同,根据个人口味调整 +- 此汤乃去火神器! \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/玉米排骨汤/玉米排骨汤.jpeg b/data/C8/cook/dishes/soup/玉米排骨汤/玉米排骨汤.jpeg new file mode 100644 index 0000000..807a3b3 --- /dev/null +++ b/data/C8/cook/dishes/soup/玉米排骨汤/玉米排骨汤.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f24f389efebb87c0b2809a8b134f199405f3d87a75dbeb0a83caf07a5c2563f3 +size 316330 diff --git a/data/C8/cook/dishes/soup/玉米排骨汤/玉米排骨汤.md b/data/C8/cook/dishes/soup/玉米排骨汤/玉米排骨汤.md new file mode 100644 index 0000000..2d6a024 --- /dev/null +++ b/data/C8/cook/dishes/soup/玉米排骨汤/玉米排骨汤.md @@ -0,0 +1,59 @@ +# 玉米排骨汤的做法 + +新鲜的排骨除了拿来烧或者炖之外,还可以用来煲汤,搭配玉米和胡萝卜煲出来的汤非常鲜美。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 排骨 +* 玉米 +* 胡箩卜 +* 生姜 +* 大葱 +* 食用油 +* 醋 +* 料酒 +* 黑胡椒粉 +* 食用盐 +* 砂锅(没有的话,用铁锅也行) + +## 计算 + +每份: + +* 排骨 500-800g +* 玉米一根(喜欢吃玉米的可以多一根) +* 胡萝卜一根(喜欢吃胡箩卜的可以多一根) +* 大葱小半根 +* 香葱一根 +* 食用油 10 ml +* 黑胡椒粉 4g +* 料酒 10ml +* 醋 10ml +* 食用盐 10-15g(根据最后汤剩余的量而定) +* 开水 1000 ml + +## 操作 + +### 备菜 + +* 大葱切成 3-4cm 的大段,用刀背拍一下 +* 玉米剁成小块 +* 胡箩卜切成滚刀块 +* 生姜去皮切大片 +* 新鲜的排骨砍成小块 + +### 操作 + +* 排骨凉水下锅,放入大葱、生姜、料酒开始焯水,大火烧开,撇去浮沫,捞出排骨,沥干水分 +* 热锅凉油,切大片的生姜和排骨一起下锅煸炒,待排骨表面微微焦黄,放入醋(可加速肉质软烂),继续煸炒一分钟 +* 冲入开水,一次给足,之后就不要再加了,大火烧开 +* 先下入玉米,放入胡椒粉,盖盖小火炖二十分钟,然后放入胡萝卜,盖盖继续小火炖四十分钟 +* 调味很简单,出锅前三分钟,除了盐什么都不用放,最后撒上一把小葱花即可 + +![示例菜成品](./玉米排骨汤.jpeg) + +## 附加内容 + +这道菜制作起来并不难,而且食材简单,对新手友好,适合降温的时候来上一大碗。 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/生汆丸子汤.md b/data/C8/cook/dishes/soup/生汆丸子汤.md new file mode 100644 index 0000000..40f25e6 --- /dev/null +++ b/data/C8/cook/dishes/soup/生汆丸子汤.md @@ -0,0 +1,74 @@ +# 生汆丸子汤的做法 + +生汆丸子汤,吃的就是一个鲜、嫩、弹。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +### 丸子肉配料 + +* 前腿肉 +* 盐 +* 胡椒粉 +* 葱姜花椒水 +* 一个鸡蛋的鸡蛋清 +* 土豆淀粉 +* 熟豆油 + +### 丸子汤配料 + +* 木耳 +* 黄花 +* 小香葱 +* 泡好的粉丝(放碗底) +* 盐 +* 鸡粉 +* 胡椒粉 +* 香油 +* 香菜 + +## 计算 + +每份: + +* 盐量 = 猪肉斤数 * 6 克 +* 胡椒粉量 = 猪肉斤数 * 2 克 +* 土豆淀粉 = 多少人的用量 * 40 克,本教程以一人用量算 + +## 操作 + +### 剁肉 + +- 肉改刀切开,肥瘦三七分 +- 上刀剁一剁,用刀背砸一砸,把肉筋打开打松疏 +- 剁一剁,砸一砸,剁成肉末,要想好吃得自己剁,机器打的太黏糊了 + +### 调味 + +- 每斤肉,6 克盐,1 克胡椒粉 +- 上手抓匀 +- 葱姜花椒水分次加,边加边搅,用手揉匀,让肉吸饱水。每斤肉末 80 克葱姜花椒水 +- 放入鸡蛋清,继续顺着一个方向搅 +- 加入 40 克土豆淀粉,搅匀 +- 加入熟豆油,这是为了保持其嫩滑弹的状态 + +### 汆丸子 + +- 起锅烧水,烧开,改小火,似开非开的样子 +- 上手,挤丸子, +- 全部漂起来,用小火煮 1 分钟 + +### 制作丸子汤 + +- 粉丝放碗底 +- 加木耳,黄花,小香葱并用盐、胡椒粉、鸡粉打底调味 +- 连汤带丸子冲如碗中 +- 淋 3-5 滴香油 +- 加一小颗香菜 + +## 附加内容 + +参考来自:[生汆丸子汤,吃的就是一个鲜、嫩、弹,学会打丸子的这些技巧,这碗汤才地道](https://www.bilibili.com/video/BV1Ga411C7zg?spm_id_from=333.1007.top_right_bar_window_history.content.click) + +* 辣椒油可以根据口味放 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/番茄牛肉蛋花汤.md b/data/C8/cook/dishes/soup/番茄牛肉蛋花汤.md new file mode 100644 index 0000000..7621ad9 --- /dev/null +++ b/data/C8/cook/dishes/soup/番茄牛肉蛋花汤.md @@ -0,0 +1,51 @@ +# 番茄牛肉蛋花汤的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 牛肉 +- 番茄 +- 鸡蛋 +- 葱、姜、蒜 +- 盐 +- 胡椒粉 + +## 计算 + +- 牛肉用量为 150 g/人 +- 番茄用量为 1 个/人 +- 鸡蛋用量为 1 个/人 +- 盐用量为 2 g/人 +- 胡椒粉用量为 0.5 g/人 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 配菜处理 + +- 牛肉切成薄片 +- 番茄切成小块 +- 葱切成葱花 +- 姜切成姜片 +- 蒜剁成蒜泥 + +### 牛肉的预处理 + +- 牛肉放入碗中 +- 加盐、胡椒粉腌制 15-20 分钟 + +### 煮汤 + +- 加水煮开 +- 加入姜片和牛肉片,煮至牛肉变色 +- 加入番茄块,煮至番茄变软 +- 打散鸡蛋液,缓慢地倒入锅中,用筷子搅拌形成蛋花 +- 加入盐和胡椒粉调味 +- 最后加入葱花,即可出锅 + +## 附加内容 + +- 可以根据口味加入一定的醋或糖来调整口感 +- 如果喜欢辣味,可以加入一定的辣椒或辣椒酱来调味 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/皮蛋瘦肉粥.md b/data/C8/cook/dishes/soup/皮蛋瘦肉粥.md new file mode 100644 index 0000000..66d774a --- /dev/null +++ b/data/C8/cook/dishes/soup/皮蛋瘦肉粥.md @@ -0,0 +1,68 @@ +# 皮蛋瘦肉粥的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 饮用水 +* 皮蛋(松花蛋) +* 瘦肉 +* 大米 +* 小葱 +* 香菜 +* 生菜 +* 生姜 +* 酱油 +* 蚝油 +* 盐 +* 胡椒粉 +* 食用油 +* 电饭锅 +* 小碗若干 + +## 计算 + +计量和处理食材时有条件带上一次性手套,生蔬食材建议提前洗净放置一旁 + +* 饮用水 1 升 +* 皮蛋 2 颗 +* 瘦肉 100g +* 大米 150ml +* 小葱 1 棵 +* 香菜 1 棵 +* 生菜 4 叶 +* 生姜 1 拇指块 +* 酱油 5 ml +* 蚝油 5 ml +* 盐 2g +* 胡椒粉 1g +* 食用油 10ml + +## 操作 + +### 主料 + +* 大米 - 洗净 - 放入电饭锅内胆 - 加入 1 升 饮用水 +* 瘦肉 - 洗净 - 简易晾去水分 - 加入 10ml 食用油 - 揉搓均匀 - 放入电饭锅内胆 +* 皮蛋 - 去壳 - 洗净 - 对半切开 - 分离蛋白蛋黄 - 蛋白简单切碎块 - 蛋黄揉碎 - 放入电饭锅内胆 +* 生姜 - 洗净 - 削皮 - 去除枯黄枯黑无法食用部分 - 切丝 - 放入电饭锅内胆 + +### 配料 + +* 小葱 - 洗净 - 去除根部 - 去除枯黄枯黑无法食用部分 - 切碎 - 放入小碗备用 +* 香菜 - 洗净 - 去除根部 - 去除枯黄枯黑无法食用部分 - 切碎 - 放入小碗备用 +* 生菜 - 洗净 - 去除根部 - 去除枯黄枯黑无法食用部分 - 切碎 - 放入小碗备用 + +### 酱料 + +* 酱油 + 蚝油 + 盐 + 胡椒粉 - 搅拌均匀 - 放入小碗备用 + +### 烹饪过程 + +* 主料 - 使用电饭锅煮粥模式煮熟 +* 配料 - 待主料煮熟后,生菜单独过一次热水,并与其余配料一同开盖加入主料中搅拌均匀 +* 酱料 - 待主料煮熟后,与其余配料一同开盖加入主料中搅拌均匀 + +## 附加内容 + +* 作为早餐时可提前一夜准备好主料,保温模式到第二天早餐,再添加配料和酱料 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/米粥.md b/data/C8/cook/dishes/soup/米粥.md new file mode 100644 index 0000000..1f43ab0 --- /dev/null +++ b/data/C8/cook/dishes/soup/米粥.md @@ -0,0 +1,34 @@ +# 米粥的做法 + +大米粥是一道以大米和水作為主要原料經大火煮沸熬製而成的美食,老少皆宜,米粥具有補脾、和胃、清肺功效。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 米 +* 水 +* 植物油(可选) + +## 计算 + +* 一般一个人可以食用 60ml-110ml 的米。 +* 水的体积是米饭的体积的 9-12 倍。 +* 一碗容量是 500ml。 +* 中断大火加热的最晚时间 T1:1.5 分钟/500ml * 水体积 +* 米粥能够食用的最早时间 Tr:10 分钟/500ml * 水体积 +* 油的质量 Mo:生米体积 / 10 +* 冷藏时间 Tc = 生米体积 /10 ml/分钟。 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +* (可选)将 Mo ml 的油与洗净的米混合,*尽量确保完全混合,即每粒米上至少都沾上少量油* +* (可选)将 米-油混合物品冷藏保存,冷藏时间 Tc。 +* 将米和水加入锅中。 +* 开大火,加热到 T1。 +* 在 T1 之前将火关小。**如果忘记此步骤,水可能会漫出而熄灭火焰。非常危险!** +* 加热到 Tr。在 Tr 时关闭火源。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/紫菜蛋花汤.md b/data/C8/cook/dishes/soup/紫菜蛋花汤.md new file mode 100644 index 0000000..c88f93a --- /dev/null +++ b/data/C8/cook/dishes/soup/紫菜蛋花汤.md @@ -0,0 +1,34 @@ +# 紫菜蛋花汤的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 鸡蛋 +* 紫菜 +* 葱花 +* 水 +* 盐 +* 油 +* 虾仁(个人口味,可加可不加) + +## 计算 + +按照 1 人份的份量: + +* 10g 的干紫菜(喜欢紫菜的可以多放些) +* 两个鸡蛋 +* 盐 2 克 + +## 操作 + +* 干紫菜用清水泡 15 分钟,捞起沥干水份备用。 +* 热锅,倒入 1.5 升清水、5ml 油、2g 盐。待水开后放入紫菜。 +* 紫菜烧开后 3 分钟,将打好的蛋液徐徐倒入锅内,30 秒既可起锅。 +* 撒上葱花,转小火 20 秒。 +* 关火,出锅前放入几滴香油,也有的会放入一点虾皮,味道也不错。 + +## 附加内容 + +* 水开后,将火关小,将打好的蛋液围绕中间沸腾的水倒入。为了使蛋花比较嫩,锅盖盖上熄灭火等半分钟后再打开. +* 如果喜欢浓稠口感,可加入 2g 淀粉. \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/罗宋汤.md b/data/C8/cook/dishes/soup/罗宋汤.md new file mode 100644 index 0000000..f26c66c --- /dev/null +++ b/data/C8/cook/dishes/soup/罗宋汤.md @@ -0,0 +1,63 @@ +# 罗宋汤的做法 + +罗宋汤是一道源自俄罗斯甜菜汤的汤品,在传入上海后有了本土化的做法。其制作较为简单,初学者只需要 2-3 小时即可完成。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 蔬菜高汤(欧芹、胡萝卜、洋葱三件套) +- 牛肉高汤(可用〇汤宝代替) +- 牛肉(可选牛腩肉或牛尾肉) +- 番茄(番茄膏、番茄罐头) + +## 计算 + +每份: + +- 牛肉高汤 500 mL +- 牛肉 250 g (可选用牛腩肉或牛尾肉) +- 番茄罐头 2 罐 (可用番茄替代、但风味欠佳) +- 番茄膏 5 g (增加番茄风味) +- 马铃薯 400 g +- 洋葱 100 g +- 胡萝卜 100 g +- 欧芹 100 g +- 包菜 200 g +- 红肠 100 - 200 g +- 橄榄油 5 mL (橄榄油用于蔬菜的烹制,可以用植物油代替) +- 植物油 5 mL (植物油用于牛肉的烹制,不能用橄榄油代替) +- 盐 18 g +- 黑胡椒 3 g + +## 操作 + +### 切配准备 + +- 洋葱、胡萝卜、欧芹切 1cm 见方小丁 +- 红肠、马铃薯切 2cm 块 +- 包菜去梗后,手撕至 2cm 片 +- 牛肉撒盐 3 g 、黑胡椒 3 g 腌制 5 分钟 + +### 煎制过程 + +- 平底锅烧热,加入植物油 +- 煎制牛肉,直至表面**焦黄色**(可以带生,千万别糊了),取出备用。 + +### 烹制过程1(前一小时) + +- 汤锅烧热,加入橄榄油、洋葱丁、胡萝卜丁、欧芹丁 +- 炒至**洋葱透明**,加入番茄膏、番茄罐头 +- 加入牛肉、马铃薯丁,翻炒均匀 +- 加水没过食材,中火烹制 1 小时 + +### 烹制过程2(后半小时) + +- 开锅加入包菜丁、红肠丁,搅拌均匀 +- 中火烹制半小时 +- 开盖加入剩余 15 g 盐,混合均匀后盛盘 + +## 附加内容 + +- 番茄尽量不用新鲜番茄代替,番茄罐头+番茄膏的组合风味更足 +- 除了胡萝卜、洋葱、欧芹、牛肉是必备食材外,其余可自由搭配 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/羊肉汤/羊肉汤.jpg b/data/C8/cook/dishes/soup/羊肉汤/羊肉汤.jpg new file mode 100644 index 0000000..3fbb029 --- /dev/null +++ b/data/C8/cook/dishes/soup/羊肉汤/羊肉汤.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d313dfe5e7348082e71ff515e2fa95859bb459f1338e74caf6ea3fa708aaaa71 +size 180904 diff --git a/data/C8/cook/dishes/soup/羊肉汤/羊肉汤.md b/data/C8/cook/dishes/soup/羊肉汤/羊肉汤.md new file mode 100644 index 0000000..ded9a40 --- /dev/null +++ b/data/C8/cook/dishes/soup/羊肉汤/羊肉汤.md @@ -0,0 +1,47 @@ +# 羊肉汤的做法 + +![羊杂汤](./羊肉汤.jpg) + +羊肉汤/羊肉汤简单易,有抵御寒冷、温润养胃、开胃健脾的功效,富含钙、铁、蛋白质等营养物质。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 羊肉或羊杂 +- 食用油 +- 料酒 +- 大葱 +- 白胡椒粉 +- 食用盐 +- 孜然粉(可选) +- 香菜(可选) + +## 计算 + +每份: + +- 羊肉 300g +- 食用油 10ml +- 料酒 20ml +- 大葱 50g +- 开水 1000ml +- 白胡椒粉 1g +- 食用盐 5g +- 孜然粉 1g +- 香菜 20g + +## 操作 + +- 羊肉切成长 5cm 宽 0.5cm 的块 +- 大葱切成小段 +- 羊肉放入锅中,加入 1000ml 常温水,加入料酒、大葱 +- 煮沸 2 分钟后,捞出羊肉,使用常温水洗净,沥干水分 +- 热锅加入食用油,加入羊肉,翻炒 2 分钟至羊肉表面微黄 +- 加入开水,开到大火档位 +- 5 分钟后,加入白胡椒粉、盐,继续煮沸 5 分钟 +- 出锅之后,加入香菜、孜然粉,搅拌均匀 + +## 附加内容 + +- 加入开水时,注意要开大火,使油脂与汤汁更好的融合 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/腊八粥.md b/data/C8/cook/dishes/soup/腊八粥.md new file mode 100644 index 0000000..376b250 --- /dev/null +++ b/data/C8/cook/dishes/soup/腊八粥.md @@ -0,0 +1,78 @@ +# 腊八粥的做法 + +> 无论盛在哪里的腊八粥,自然会熬煮过去。一年的酸甜苦辣涩。—— 迷迭香《腊八粥》 + +腊八粥,又称七宝五味粥、佛粥、大家饭等,是一种由多样食材熬制而成的粥。主要富含碳水化合物、磷镁元素和各类维生素等,不仅可以补充日常的能量,其中的莲子还有养心安神的作用,适合工作压力大的人食用。除去食材准备时间,一般只需要 3 小时即可完成。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 饮用水 +- 大米 +- 糯米 +- 花生 +- 红豆 +- 红枣 +- 粥锅(普通锅容易糊底,有条件可选择高压锅) +- 中号玻璃碗(或其他中号不锈钢容器) +- 小碗若干 + +### 可选原料 + +由于腊八粥的配方多样,下面的食材原料可以根据自己的口味偏好自行选择。 + +- 薏米 +- 黑米 +- 小米 +- 莲子 +- 绿豆 +- 黄豆 +- 豌豆 +- 红腰豆 +- 桂圆(去种龙眼干) +- 栗子 +- 去壳核桃 +- 葡萄干 +- 冰糖(或白糖,调味用) + +## 计算 + +对于一人份(三小碗)的情况,一份的分量是: + +- 饮用水 1 L +- 大米 50 g +- 糯米 50 g +- 薏米 50 g +- 黑米 50 g +- 小米 50 g +- 莲子 25 g +- 绿豆 25 g +- 红豆 25 g +- 花生 25 g +- 黄豆 25 g +- 豌豆 25 g +- 红枣 25 g +- 桂圆 25 g +- 栗子 25 g +- 去壳核桃 25 g +- 葡萄干 25 g +- 红腰豆 25 g +- 冰糖 10~25 g + +以上原料分量可以按照自己的口味偏好适当调整,对于米类,不建议超过 150 g ,对于其他豆类,不建议超过 50 g 。 + +## 操作 + +- 提前洗净好绿豆、红豆、花生、黄豆、豌豆、红腰豆,并用干净的玻璃碗盛放好,注入 3/4 玻璃碗大小的饮用水,浸泡一夜(或最少 8 小时)。 +- 提前洗净好大米、糯米、薏米、黑米、小米、莲子,并用干净的玻璃碗盛放好,注入 3/4 玻璃碗大小的饮用水,浸泡 3 小时。 +- 将步骤 1 中准备好的盛有绿豆、红豆、花生、黄豆、豌豆、红腰豆的玻璃碗中的水分分离倒出,其余原料倒入粥锅中,加入 1 升饮用水(或漫过食材 1 拇指块),大火煮沸,煮沸后合上锅盖,小火煮 30 分钟。 +- 将步骤 2 中准备好的盛有大米、糯米、薏米、黑米、小米、莲子的玻璃碗中的水分分离倒出,其余原料继续倒入粥锅中,合上锅盖,小火煮 60 分钟。 +- 洗净好红枣、桂圆、栗子、核桃、葡萄干(其中红枣切成小片)、冰糖,倒入锅中,合上锅盖,小火煮 60 分钟。 +- 确认煮出的粥粘稠后即可关火、盛盘、食用。 + +## 附加内容 + +- 往粥锅加入食材时,应当进行搅拌,使食材原料均匀分布在各处,并注意观察水位线,如发现水位线低于米线及食材应立即补水。 +- 注意控制火候,不要过大,定时搅拌。如果使用普通锅,建议烧开水后再下原料,搅拌到再次烧开改小火,避免锅底烧糊。如果有条件,建议改用高压锅或粥锅。 +- 参考资料:[全网最正宗腊八粥做法,香甜软糯一次成功!\_哔哩哔哩\_bilibili](https://www.bilibili.com/video/BV1Mt411H7by/?spm_id_from=333.1391.0.0&vd_source=2a1baf3b15cd0eb7f9396b4ad2708e44) 、 [腊八粥(在腊八节用多种食材熬制的粥)_百度百科](https://baike.baidu.com/item/腊八粥/27200) \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/菌菇炖乳鸽/菌菇炖乳鸽.jpg b/data/C8/cook/dishes/soup/菌菇炖乳鸽/菌菇炖乳鸽.jpg new file mode 100644 index 0000000..e68e4ba --- /dev/null +++ b/data/C8/cook/dishes/soup/菌菇炖乳鸽/菌菇炖乳鸽.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:607a984755c2837a8f03d67327f5f280cf8038f3178466f71e1e06f20d677674 +size 170623 diff --git a/data/C8/cook/dishes/soup/菌菇炖乳鸽/菌菇炖乳鸽.md b/data/C8/cook/dishes/soup/菌菇炖乳鸽/菌菇炖乳鸽.md new file mode 100644 index 0000000..195188c --- /dev/null +++ b/data/C8/cook/dishes/soup/菌菇炖乳鸽/菌菇炖乳鸽.md @@ -0,0 +1,39 @@ +# 菌菇炖乳鸽的做法 + +- 菌菇炖乳鸽 汤鲜、肉嫩、营养丰富 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 乳鸽 +* 菌菇 +* 玉米 +* 姜 +* 料酒 +* 食用盐 +* 瓦罐或者高压锅 + +## 计算 + +2 人份: + +* 乳鸽 300 g +* 菌菇 100 g +* 玉米 200 g +* 姜 30 g +* 料酒 15 ml +* 食用盐 10 g + +## 操作 + +* 冷水洗干净热心摊主处理好的乳鸽 +* 冷水锅中放入洗干净的乳鸽,加入 15ml 料酒与姜,水煮开即可捞出乳鸽,要不然会丢失营养 +* 把乳鸽放到高压缩或者瓦罐中、倒入的水要没过乳鸽,放入生姜 20 g,玉米 200 g、菌菇 100 g + + 注意:高压锅 30 分钟,瓦罐需在水烧开后转小火慢炖 40-60 分钟 +* 时间到了,盛到碗中,加入 3~5g 盐 即可 + +![示例菜成品](./菌菇炖乳鸽.jpg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/西红柿鸡蛋汤.md b/data/C8/cook/dishes/soup/西红柿鸡蛋汤.md new file mode 100644 index 0000000..5bd3053 --- /dev/null +++ b/data/C8/cook/dishes/soup/西红柿鸡蛋汤.md @@ -0,0 +1,36 @@ +# 西红柿鸡蛋汤的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 西红柿 +- 鸡蛋 +- 香油 +- 味素 +- 盐 +- 葱、姜、蒜 + +## 计算 + +- 西红柿 1 个 +- 鸡蛋 1-2 个(依照自己的口味而定,喜欢吃鸡蛋就放 2 个,一般就放 1 个) +- 香油 2 滴 +- 味素 5 克(可选) +- 盐 15 克 +- 葱、姜、蒜共 15 克 + +## 操作 + +1. 将西红柿洗净,切块。 +2. 葱姜蒜切碎。 +3. 鸡蛋打到碗中,用筷子(或打蛋器)搅拌均匀。 +4. 热锅,并放入 15 毫升的油,待能从油中看到冒出一丝烟时,放入葱姜蒜翻炒 30 秒。 +5. 放入西红柿翻炒 1 分钟。 +6. 倒入水,水的高度大约为锅内菜品高度的 1.2 倍,并放入盐。 +7. 待开锅后,将鸡蛋液放入,并用筷子将鸡蛋打散,放入味素和香油。 +8. 等待 30 秒,关火出锅。 + +## 附加内容 + +味素可加可不加。 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/金针菇汤.md b/data/C8/cook/dishes/soup/金针菇汤.md new file mode 100644 index 0000000..c7c3a9e --- /dev/null +++ b/data/C8/cook/dishes/soup/金针菇汤.md @@ -0,0 +1,29 @@ +# 金针菇汤的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 金针菇 +- 鸡蛋(如需要) + +## 计算 + +每份: + +- 金针菇 400-500 克 (市场里面售卖的一袋即可) +- 食盐 15 克 +- 味精 5 克 + +## 操作 + +1. 金针菇徒手掰散,越散越好**不然容易藏牙**,洗净备用。 +2. 用菜刀或者水果刀将上述金针菇段段切,可依据个人喜好,但长度不宜超过 5 cm。 +3. 将金针菇放入锅中,加水没过约食材总高度 1.1 倍,沸腾后**等待 3 分钟**。 +4. 加入味精和食盐并搅拌。 +5. 继续加热约 30 秒,关火装盘。 + +## 附加内容 + +- 如果喜欢在汤里加入鸡蛋,可在步骤 3 中水沸腾之后将打散的鸡蛋液倒入锅中。 +- 出锅后可加入 3-4 滴香油(或者麻油)增香。 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/银耳莲子粥/银耳莲子粥.md b/data/C8/cook/dishes/soup/银耳莲子粥/银耳莲子粥.md new file mode 100644 index 0000000..f0b17f0 --- /dev/null +++ b/data/C8/cook/dishes/soup/银耳莲子粥/银耳莲子粥.md @@ -0,0 +1,39 @@ +# 银耳莲子粥的做法 + +![银耳莲子粥](./银耳莲子粥.png) + +银耳莲子粥是一道营养非常丰富的粥。口味偏甜,具有养心安神的功效。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 银耳 +- 去心莲子 +- 红枣 +- 枸杞(可选) +- 冰糖 + +## 计算 + +按照 1 人的份量: + +- 银耳 60g +- 去心莲子 20g +- 红枣 6g +- 枸杞 5-6g +- 冰糖 10-20g + +## 操作 + +- 把银耳、莲子用清水浸泡 2 个小时,红枣浸泡 10 - 20 分钟,枸杞洗净,备用 +- 在锅中倒入 600ml 水,烧开后依次放入银耳、莲子、红枣 +- 等待水再次烧开后,盖上锅盖,转至中火继续熬 +- 熬到大约 1 小时后,放入 5g - 10g 冰糖和 5g - 6g 枸杞,转至小火熬 +- 小火继续熬 30 分钟,此时银耳开始呈现粘稠状态 +- 再次放入 5g - 10g 冰糖,用勺子搅拌 5 - 10 分钟 +- 关火,用勺子盛出 + +## 附加内容 + +- 当银耳呈现粘稠状态时,需要用勺子及时搅拌,防止银耳糊在锅底 \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/银耳莲子粥/银耳莲子粥.png b/data/C8/cook/dishes/soup/银耳莲子粥/银耳莲子粥.png new file mode 100644 index 0000000..50ae837 --- /dev/null +++ b/data/C8/cook/dishes/soup/银耳莲子粥/银耳莲子粥.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ec7cfe938f4c2d588e82b7428704d768cdc9410ecb31814c40ed5c8edcf7ebc +size 50218 diff --git a/data/C8/cook/dishes/soup/陈皮排骨汤.md b/data/C8/cook/dishes/soup/陈皮排骨汤.md new file mode 100644 index 0000000..efe4538 --- /dev/null +++ b/data/C8/cook/dishes/soup/陈皮排骨汤.md @@ -0,0 +1,49 @@ +# 陈皮排骨汤的做法 + +新鲜的排骨除了拿来烧或者炖之外,还可以用来煲汤,搭配广东陈皮煲出来的汤非常养生,对脾胃、肺及咽喉都有一定的滋补功效,熬夜党必备。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 排骨 +* 陈皮 +* 西洋参 +* 石斛 +* 玉竹 +* 麦冬 +* 煲汤盅 +* 盐 + +## 计算 + +每份: + +* 排骨,用猪骨也替代也可,4-5 块 +* 陈皮(一般选用 8-20 年制),一般 1 块陈皮是 3 瓣,取 1 瓣即可 +* 西洋参(又名花旗参),9 片 +* 石斛, 6 颗 +* 玉竹, 5 片 +* 麦冬, 7 个 +* 煲汤盅,按 1 人份 +* 食盐 ,5g + +## 操作 + +### 备菜 + +* 排骨用热水过一边,去血水 +* 陈皮、麦冬、玉竹、石斛和西洋参,冲洗干净即可 +* 煲汤盅洗干净 + +### 操作 + +* 打开煲汤盅,先放入排骨在底部,然后依次放入陈皮、麦冬、玉竹、石斛和西洋参 +* 加入热水进煲汤盅,水不宜太满 +* 煲汤容器加入水,炖煮 1.5 小时即可 +* 加入食盐,趁热饮用 + +## 附加内容 + +煲汤盅很烫,拿的时候小心别烫到或者手滑摔破 +广东老火靓汤,讲究用料和火候,只要备好料和炖够一定时辰,就算大功告成! \ No newline at end of file diff --git a/data/C8/cook/dishes/soup/陈皮排骨汤/陈皮排骨汤.jpg b/data/C8/cook/dishes/soup/陈皮排骨汤/陈皮排骨汤.jpg new file mode 100644 index 0000000..71986a0 --- /dev/null +++ b/data/C8/cook/dishes/soup/陈皮排骨汤/陈皮排骨汤.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63a81eca9c15e9ed8ef8e01f6792f545959778e7dd2a40660557a96bab07d077 +size 257484 diff --git a/data/C8/cook/dishes/soup/陈皮排骨汤/陈皮排骨汤.md b/data/C8/cook/dishes/soup/陈皮排骨汤/陈皮排骨汤.md new file mode 100644 index 0000000..f1c6593 --- /dev/null +++ b/data/C8/cook/dishes/soup/陈皮排骨汤/陈皮排骨汤.md @@ -0,0 +1,51 @@ +# 陈皮排骨汤的做法 + +新鲜的排骨除了拿来烧或者炖之外,还可以用来煲汤,搭配广东陈皮煲出来的汤非常养生,对脾胃、肺及咽喉都有一定的滋补功效,熬夜党必备。 + +![陈皮排骨汤](./陈皮排骨汤.jpg) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 排骨 +* 陈皮 +* 西洋参 +* 石斛 +* 玉竹 +* 麦冬 +* 煲汤盅 +* 盐 + +## 计算 + +每份: + +* 排骨,用猪骨也替代也可,4-5 块 +* 陈皮(一般选用 8-20 年制),一般 1 块陈皮是 3 瓣,取 1 瓣即可 +* 西洋参(又名花旗参),9 片 +* 石斛, 6 颗 +* 玉竹, 5 片 +* 麦冬, 7 个 +* 煲汤盅,按 1 人份 +* 食盐 ,5g + +## 操作 + +### 备菜 + +* 排骨用热水过一边,去血水 +* 陈皮、麦冬、玉竹、石斛和西洋参,冲洗干净即可 +* 煲汤盅洗干净 + +### 操作 + +* 打开煲汤盅,先放入排骨在底部,然后依次放入陈皮、麦冬、玉竹、石斛和西洋参 +* 加入热水进煲汤盅,水不宜太满 +* 煲汤容器加入水,炖煮 1.5 小时即可 +* 加入食盐,趁热饮用 + +## 附加内容 + +煲汤盅很烫,拿的时候小心别烫到或者手滑摔破 +广东老火靓汤,讲究用料和火候,只要备好料和炖够一定时辰,就算大功告成! \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/中式馅饼/中式馅饼.md b/data/C8/cook/dishes/staple/中式馅饼/中式馅饼.md new file mode 100644 index 0000000..b6f3152 --- /dev/null +++ b/data/C8/cook/dishes/staple/中式馅饼/中式馅饼.md @@ -0,0 +1,69 @@ +# 中式馅饼的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 面粉(非自发粉) +* 肉沫 +* 油 +* 盐 +* 糖 +* 生粉 +* 酱油 +* 风味调料(如鸡粉、孜然、椒盐,可选) +* 蒜头 +* 大葱 +* 鸡蛋(可选) +* 胡萝卜(可选) +* 平底锅 +* 炒锅(可以使用同一个平底锅替代) + +## 计算 + +每一份含: + +* 面粉 200g +* 肉沫 50g +* 油 30ml +* 盐 3g +* 糖 5g +* 生粉 10g +* 酱油 5g +* 风味调料 3g +* 蒜头 2 瓣 +* 大葱 1/4 根(靠叶部分) +* 鸡蛋 (可选,1 个) + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 准备原料 + +* 取肉沫(解冻),加入 1/2 所有上述调料(油、盐、糖、酱油、风味调料)和全部的生粉,搅拌均匀,腌制 30 分钟。 +* 将面粉加入碗中,加入鸡蛋,加入剩下 1/2 所有上述调料,加入相当于面粉 1/2 的水(使得面粉相对粘稠但可以流动),搅拌均匀。 +* 蒜头切为蒜末。 +* 大葱切段。 +* 胡萝卜切末(作为馅料用,所以要求尽量细碎,可用乱刀) + +### 烹饪 + +* 热锅冷油,宽油起锅。 +* 待油烧热后,放入蒜末爆香。 +* 加入腌制的肉沫,翻炒,直至断生。 +* 将胡萝卜末加入肉沫中一同翻炒,直至油被染为金黄色(这是为了萃取胡萝卜的风味)。 +* 关火。冷却 2 分钟。 +* 将炒好的肉沫倒入生面糊中,搅匀。 +* 重新开火,平底锅铺底油。 +* 调至小火,将面糊倒入锅中均匀铺满。保证厚度不要过高。可以端起锅,让面糊流过锅底来完成这一操作。 +* 在饼的表面尚为液态时,撒上大葱段。 +* 保持小火,直到底面凝固。 +* 将饼翻面,继续小火煎烤,直至另一侧凝固。 +* 之后,每一面再额外煎 20 秒。 +* 关火出锅。 + +## 附加内容 + +- 将肉沫和胡萝卜末加入面糊后,应该尽量搅匀,保证味道扩散到饼内各处。 +- 肉沫和胡萝卜末即馅料可以使用各类熟馅料替代。 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/凉粉/lf1.jpg b/data/C8/cook/dishes/staple/凉粉/lf1.jpg new file mode 100644 index 0000000..8b11bc7 --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61893b5370ae37caaf92f3174023cc787ca113e8b2aa6724d90862d48c82f2c2 +size 129562 diff --git a/data/C8/cook/dishes/staple/凉粉/lf10.jpg b/data/C8/cook/dishes/staple/凉粉/lf10.jpg new file mode 100644 index 0000000..d25a5b1 --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf10.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eeb55ae76874ad3639b9f3894fe51dd8b82896869ec3e67457f320182cd190d0 +size 87453 diff --git a/data/C8/cook/dishes/staple/凉粉/lf11.jpg b/data/C8/cook/dishes/staple/凉粉/lf11.jpg new file mode 100644 index 0000000..c8603ca --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf11.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01ea2efbe5ca36dd8de751c44a070dcc7f044e7db3a0074270e28219a0ca2de4 +size 73272 diff --git a/data/C8/cook/dishes/staple/凉粉/lf2.jpg b/data/C8/cook/dishes/staple/凉粉/lf2.jpg new file mode 100644 index 0000000..07f9a2b --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67ac0debe0e318b67e13d6c00e70c9ba2299f5b041c89d19952e3e9324d1212c +size 69094 diff --git a/data/C8/cook/dishes/staple/凉粉/lf3.jpg b/data/C8/cook/dishes/staple/凉粉/lf3.jpg new file mode 100644 index 0000000..2c082cf --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf3.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2b699e6a40c742aadf8bbb9f354fd7c7ab62f35c6713551afef95130c2e8a18 +size 73385 diff --git a/data/C8/cook/dishes/staple/凉粉/lf4.jpg b/data/C8/cook/dishes/staple/凉粉/lf4.jpg new file mode 100644 index 0000000..1e95eba --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf4.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1f39b0767548b13cb7dc8982168f1007de952971f1eeefc917376983ea29aac +size 57536 diff --git a/data/C8/cook/dishes/staple/凉粉/lf5.jpg b/data/C8/cook/dishes/staple/凉粉/lf5.jpg new file mode 100644 index 0000000..0b5b186 --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf5.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47a212b467fc394bce99d5fa5b6005ef081f71027b2a1ab3b94eaa1b96553ac4 +size 65076 diff --git a/data/C8/cook/dishes/staple/凉粉/lf6.jpg b/data/C8/cook/dishes/staple/凉粉/lf6.jpg new file mode 100644 index 0000000..754bb1c --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf6.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5debe910fe1164534d19f47565fdadc54d539578a908ba42ef6ab18896f9f189 +size 64287 diff --git a/data/C8/cook/dishes/staple/凉粉/lf7.jpg b/data/C8/cook/dishes/staple/凉粉/lf7.jpg new file mode 100644 index 0000000..605b2a2 --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf7.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc5d3da9d1ff64b45c49cba4b41603bf980b4049f9f83be0ec9d639ba91044cd +size 49289 diff --git a/data/C8/cook/dishes/staple/凉粉/lf8.jpg b/data/C8/cook/dishes/staple/凉粉/lf8.jpg new file mode 100644 index 0000000..bcf52c5 --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf8.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b3dafbcad1296908e55e806af1c507f8521441a618b6c53523bb1044c3915a9 +size 60950 diff --git a/data/C8/cook/dishes/staple/凉粉/lf9.jpg b/data/C8/cook/dishes/staple/凉粉/lf9.jpg new file mode 100644 index 0000000..5f9cc63 --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/lf9.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6af61bda9c1d60cfadd36e0aa1b8ffc0e2c860d4524182300360e07ccba004b5 +size 89763 diff --git a/data/C8/cook/dishes/staple/凉粉/凉粉.md b/data/C8/cook/dishes/staple/凉粉/凉粉.md new file mode 100644 index 0000000..c45e459 --- /dev/null +++ b/data/C8/cook/dishes/staple/凉粉/凉粉.md @@ -0,0 +1,83 @@ +# 凉粉的做法 + +![liangfen](./lf1.jpg) + +伤心凉粉吃了不会让人伤心的哦! + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 豌豆淀粉 +- 大蒜 +- 小米辣 +- 辣椒粉 +- 酱油 +- 醋 +- 白糖 +- 鸡精 +- 盐 +- 花生碎 +- 香菜 + +## 计算 + +下述材料为一人份,每次制作前需要确定计划做几份。一份正好够一个人吃。 + +- 豌豆淀粉 100g +- 大蒜 3 瓣 +- 小米辣 3 颗 +- 辣椒粉 10g +- 酱油 10ml +- 醋 10ml +- 白糖 3ml +- 鸡精 3g +- 盐 3g +- 花生碎 5g +- 香菜 5g + +## 操作 + +- 准备食材。 + + ![1](./lf2.jpg) + +- 把豌豆淀粉和水各 100 克混合搅拌。 + + ![bz2](./lf3.jpg) + +- 往锅中倒入 600g 水,大火煮开后转为小火。 + + ![bz4](./lf4.jpg) + +- 倒入淀粉水,边倒边不断的搅拌,搅拌到浓稠且色泽均匀。 + + ![bz5](./lf5.jpg) + +- 找一个容器,在容器中刷一层薄薄的食用油。 + + ![bz6](./lf6.jpg) + +- 将煮好的淀粉倒入容器中冷藏 2-4 小时。 + + ![bz7](./lf7.jpg) + +- 冷藏后取出,脱模,切条。 + + ![bz7](./lf8.jpg) + +- 大蒜和小米辣剁成沫,放上 10g 辣椒粉,5g 花生碎,热油搅拌均匀。 + + ![bz7](./lf9.jpg) + +- 再加入 10ml 酱油,10ml 醋,5g 白糖,3g 鸡精,3g 盐搅拌均匀。 + + ![bz7](./lf10.jpg) + +- 将调味料倒在凉粉上,然后撒上香菜即可。 + + ![bz7](./lf11.jpg) + +## 附加内容 + +- 参考: [制作凉粉的详细步骤](https://www.zhms.cn/recipe/mzvyy.html?source=2) \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/1-1成品.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/1-1成品.jpg new file mode 100644 index 0000000..31ee660 --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/1-1成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4688133a489ecfcf8151e85c5bde949e5a81025a4ea72d3fe78fdeb3983e7fd +size 41865 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/2-1设备简介1.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/2-1设备简介1.jpg new file mode 100644 index 0000000..06d1ab4 --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/2-1设备简介1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad2286261c0539859053a0b418c611441aeeb9650718b07be994916483cc15b4 +size 372430 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/2-2设备简介2.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/2-2设备简介2.jpg new file mode 100644 index 0000000..02a25e7 --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/2-2设备简介2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd6c0a2d566317b225d08bf477b8176dd08539999c95e449ce646456846cc9fb +size 338124 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/4-1酵头1.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/4-1酵头1.jpg new file mode 100644 index 0000000..43c035e --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/4-1酵头1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16234b6b0950130a5c11748d601f5bbbc9bc4cd379038c1be7bb95a7802437b2 +size 25710 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/4-2酵头2.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/4-2酵头2.jpg new file mode 100644 index 0000000..508ae1d --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/4-2酵头2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:acf5a9003d6db7bd4c0d730f32917de0e00bd287d4b2ed42e00e3eba81483eba +size 81943 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/4-3酵头3.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/4-3酵头3.jpg new file mode 100644 index 0000000..b55200b --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/4-3酵头3.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34f1f2117451edea9f3379c65f1e10c89b1d2aa02fcc2787b2d09fc7be421c88 +size 40494 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/4-4此时的面团.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/4-4此时的面团.jpg new file mode 100644 index 0000000..0e21bfa --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/4-4此时的面团.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f28e7c4ba67b43e829af75036803dbc3d50eef7247357b2db55d44c84ff365b1 +size 40123 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/4-5转移到容器内.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/4-5转移到容器内.jpg new file mode 100644 index 0000000..01cc9cf --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/4-5转移到容器内.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad4126cb21f3093205985667bd1da83125505a40716cd5eebffa81e38f9efdcd +size 31905 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/4-6成品面包.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/4-6成品面包.jpg new file mode 100644 index 0000000..8ac52c4 --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/4-6成品面包.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45531359bb77762d2df3540d5c51e0aa83b3d0f2fa9947b03ddbaa2e8180ef10 +size 42794 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/5-1成品.jpg b/data/C8/cook/dishes/staple/基础牛奶面包/5-1成品.jpg new file mode 100644 index 0000000..a1875d0 --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/5-1成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe52d48e058bd5803c56bcb6499c26e78a7b3d25dcd74ee2144a6602e3d8f4f7 +size 33865 diff --git a/data/C8/cook/dishes/staple/基础牛奶面包/基础牛奶面包.md b/data/C8/cook/dishes/staple/基础牛奶面包/基础牛奶面包.md new file mode 100644 index 0000000..18addf4 --- /dev/null +++ b/data/C8/cook/dishes/staple/基础牛奶面包/基础牛奶面包.md @@ -0,0 +1,202 @@ +# 基础牛奶面包的做法 + +![牛奶面包成品](./1-1成品.jpg) + +面包是常见的主食。普通面包需要经过长时间的发酵及和面。但本食谱尽量简化了制作步骤,方便新手上手,并尽量保证其风味。当然,要求更高的也可以查阅其的面包食谱。 + +本食谱**需要的额外的工具较多**,会在后面的章节详细介绍。 + +本食谱面向**烘焙新手**,难度**中**,预计制作制作时长 **200 分钟**。 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +### 所需原料 + +- 高筋或中筋面粉 *(尽量使用高筋面粉,但**避免使用低筋面粉**。所有无特殊说明的“万能面粉”均为中筋面粉)* +- 鸡蛋 *(不过分要求大小及重量)* +- 糖 *(如有糖浆是最好的。)* +- 干酵母 +- 盐 +- 牛奶或淡奶油或炼乳或奶粉 *(最好使用**奶粉**,奶香味十足,但**不要使用任何复方奶粉**,如成人奶粉或婴儿奶粉,因为化学性质不稳定。同时可以两种奶制品混合使用。尽量**避免选用额外含糖**的原料,因为实际含糖量会多于本食谱建议加糖量)* +- 黄油或玉米油 *(如果**选用的奶制品含脂量极高可以不加**。黄油尽量选用动脂无盐的。豆油可能会有豆腥味,尽量不要使用。)* +- 谷朊粉(可选) +- 香草精(可选) + +### 所必要的工具 + +- 烤箱 *(**不要使用不带控温的烤箱**)* +- 量杯 +- 布 +- 擀面杖 +- 硅油纸或模具 + +### 可选材料、工具及材料、工具的介绍 + +>![用具1](./2-1设备简介1.jpg) +>![用具2](./2-2设备简介2.jpg) +>烘焙是独立的美食制作门类,因此与日常烹饪的工具有很大差别。下面介绍了常用的工具。 +> +>- ①量杯:量取原料。量杯一般会以 cup 为度量单位。量取时不要晃动,防止量取的原料偏少。 +>- ②刮刀:又名硅胶铲,用于搅拌和刮净附着在容器边缘的面糊等。 +>- ③布:覆盖在面团表面防止在制作过程中损失过多的水分。在制作过程中根据实际情况选择使用潮湿的或干燥的布。建议使用蒸笼的屉布(不是一次性屉布),也可以使用保鲜膜。 +>- ④烤箱:烘烤食材。烤箱分为小型的经济型烤箱和大型的专业烤箱。经济型烤箱因密闭性差,因此可能受热不均,这时可以降低温度延长烘焙时间。烤箱必须先预热。后面的章节会展开细说。 +>- ⑤刮板:刮去面板上的面和将面团切成适当的大小。也可以用干净的刀代替。 +>- ⑥擀面杖:压制面团。 +>- ⑦喷壶:使面团或容器表面均匀覆盖上水或油,用于烤制脆皮和防粘。 +>- ⑧筛子:使面粉均匀铺开或过滤面粉结块和杂质。 +>- ⑨面板或硅胶垫:在其上方进行和面操作,防止污染面团和其地方。 +>- ⑩刷子:用于给面团刷蛋液,使成品更加光鲜、亮丽、有光泽。 +>- 11.硅油纸:防止烤制时与其物品粘连,使烤制的成品难以脱模。硅油纸是耐高温的,没有安全问题。部分硅油纸是区分正反面的,使用时要注意。 +>- 12.模具:帮助面包烘烤时塑形。对于面包烤制的模具无过多要求,但对于蛋糕烤制的模具必须是阳极氧化铝的材质且最好喷油面混合物帮助蛋糕爬升。 +>- 谷朊粉:这是从小麦中提取出来的蛋白质,在吸水后会形成网格状结构。在日常中应用广泛,如面筋等。 +>- 香草精:香草精是从香草高度提纯的天然食用香精。常用来制作香草味食品外还会用作中和蛋腥味等异味。 + +## 计算 + +**注意:虽然给出了原料的具体用量,但室内温度、室内湿度甚至是空气中酵母菌的含量都会影响制作过程。本食谱会在制作过程中尽可能地给予调整建议。** + +cup 是常用的烘焙计量单位,因为可以在体积与重量之间轻松进行换算。 1 cup = 250 ml ,一般的, 1 cup 面粉 = 120 g 。更多的换算见附加内容。 + +在此,用量较大的用 cup ,较小的用 g 。 + +每份: + +- **酵头** + - 面粉 1 cup (盛一杯后用勺子挂掉多余的部分,不要晃动) + - 30 ℃ 温水(以不烫手为宜) 1 cup + - 酵母 2 g + - 盐 2 g +- **面团** + - 面粉 2½ cup + - 鸡蛋 1 个 + - 糖或糖浆 ⅛ cup + - 奶制品 混合后共 ¼ cup (奶粉需要和水混合。) + - 黄油或玉米油 ⅛ cup + - 谷朊粉 ¼ ~ ½ cup (可选) + - 香草精 3 g (可选) + +## 操作 + +### 酵头的制作 + +酵头是预发酵的产物,通过预发酵,不仅可以提升成功率,而且更长的发酵时间会让面包的风味更好。如果有条件,酵头应该发酵 4 天以达到最佳风味。但对新手来说, 30 分钟的发酵的酵头所呈现的成品就已经很可观了。接下来制作酵头。 + +![发酵前酵头的理想状态](./4-1酵头1.jpg) + +1. 首先,将酵母和 ***30℃ 的温水*** 用刮刀或厨具混合均匀,静置 5 分钟。之后与面粉混合,搅拌均匀。此时的酵头应该是**特别粘稠**的面糊。 + +![用布盖上酵头](./4-2酵头2.jpg) + +2. 用布盖上面糊,将面糊放置到**温暖的地方**进行发酵,时长为 45 ~ 60 分钟。 + +![酵头的最终形态](./4-3酵头3.jpg) + +3. 最终的面糊应该是表面有很多气泡的且体积明显增大。 + +**发酵失败了?看看这里:** + +>1. 确定酵母没有过期 +>2. 确定水温合适 +>3. 延长发酵时间,可以放在冷藏室内过夜 +>4. 可能温度不够,这时可以将烤箱预热至 60℃ ,停止加热后放到烤箱内进行发酵 +>5. 可以再加入等量的酵母搅拌均匀再次发酵并延长发酵时间 +>6. 可以尝试加入 3g 糖再次发酵 + +**如何制作“永久的”酵头?** + +>有了酵头,随时开烤面包就不是梦!“永久的”酵头可以按下面的方法制作: +> +>1. 按上述方法制作好酵头后,放到阴凉的地方(甚至是冷藏室!)每1-3天在上面撒上薄薄的一层面粉(只要看不见面糊的厚度就可以!)再次搅拌,然后继续盖上布发酵。如果发酵过快体积过大,可以扔掉一部分。 +>2. 等到开始制作面包时,只需留下发酵前体积的酵头继续发酵,剩下的用于面包的制作。 +>3. 久而久之,酵头就会产生独特的香味,这种香味对于面包来说是最好的“原料”! + +### 面团的制作 + +有了酵头,那就成功一半了! + +![此时的面团](./4-4此时的面团.jpg) + +1.将剩下的原料全部与酵头用刮刀混合、搅拌。在搅拌时一定要刮壁,使其充分混合。在形成面团且没有干粉时,用干净的干燥的一只手按压面团,另一只手扶住容器,使其形成一个大的面团,然后倒在面板或硅胶垫上操作 + +>此时地面团应该已经成型并且比较软。如果无法成型且很黏,那么说明面粉较少,可以加入 ¼ cup 面粉再次充分搅拌,直至成型。如果的面团成型了或者有很多的干粉,那么说明揉制时间不够。这时可以增加揉制时间。 +> +>按压面团时,用拳头推开面团,然后对折再次推开,如此往复,将容器壁的面粉全部揉进面团里。 + +2.用手掌下部推开面团,然后对折再次推开,直至表面没有干粉结块。这时的面团还不是很光滑。 + +>如果在此过程中使用面板,可能会有少部分的粘连,这时可以用刮板或者刀将其铲下。 +> +>如果的面团成型但却比较硬,那么说明水分过少。这时可以在表面用湿润的手或者喷壶在表面均匀覆盖上水并盖上湿布静置发酵 20 分钟,如此往复。 + +![转移到容器内](./4-5转移到容器内.jpg) + +3.使用喷壶将至少是当前面团三倍大的容器内喷上一层植物油(也可用手涂抹均匀),将面团放入并盖上布,发酵 1 小时。 + +>如发酵发生问题,请参阅酵头制作下对于发酵失败的解决方法。 +> +>发酵后的面团表面应当是有粘性的。如果没有,可在表面用湿润的手或者喷壶在表面均匀覆盖上水并再次发酵 20 分钟。 + +4.此时面团应该有原来的两倍大。在面板或硅胶垫上撒上薄薄的一层面粉(可以看见面板或硅胶垫的厚度即可),然后将面团拿出,用手压瘪面团排气。 +5.之后使用擀面杖,擀成 1 cm 的厚片。并紧实、不留空隙地从一边卷起来。 +6.然后旋转 90° ,重复步骤 4、步骤 5 。 +7.将面包整形,放到垫了硅油纸的烤盘或者涂抹油脂的模具内。注意接缝处朝下。 + +>可以在烤盘上用喷均匀喷洒一层油或用黄油涂抹薄薄一层再放上硅油纸。这样硅油纸就不会随意移动了。 + +8.在托盘或模具内,发酵 30 ~ 45 分钟 。 + +>如发酵发生问题,请参阅酵头制作下对于发酵失败的解决方法。 + +9.于此同时,预热烤箱。 + +>烤箱的预热:将烤箱调到最高温度下空烤至少 20 分钟。 + +10.在面包上用剪子或者刀划开几条缝作为面包的花纹。 +11.用刷子刷上蛋液。(可选) + +![成品](./4-6成品面包.jpg) + +11.放入烤箱,上下火 180℃ 烤制 30 分钟,然后调 165 ℃ 再烤 10 分钟。 + +>不同的烤箱的温度不一样。在烤制过程中,观察面包,如果 30 分钟后没有明显的变色,那么温度过低。这时提高 5 ~ 10 ℃ 或多烘烤 5 ~ 10 分钟 +>在烤制结束后,品尝面包,如果面包表面发苦(注意,只要不苦都不算烘焙过度),那么温度过高,尝试降低 5 ~ 10 ℃ 或减少 5 ~ 10 分钟的烤制时间; +>如果外部已经呈焦糖色但里面却没有熟,那么降低 5 ~ 15 ℃ 并延长 10 ~ 20 分钟的烤制时间。 +> +>如果面包表面很硬或者开裂很严重,可以用锡纸覆盖面包并在最后十分钟拿开锡纸或者倒扣另一个烤盘并安在最上方的位置,然后在最后 10 分钟拿开锡纸或烤盘。 + +12.放凉后装入食品袋内,可保存一个星期。冷冻可保存一个月。 + +>当装在食品袋内密闭一晚上后,面包会内部和表面会进一步回软。所以最好的品尝时机是第二天早上。 + +## 附加内容 + +1. 常见原料的换算(仅供参考) + +| 体积 /cup |原料 |质量 /g | +|:---------:|:----:|:-------:| +|1 |黄油 |227 | +|1 |面粉 |120 | +|1 |细砂糖|180 ~ 200| +|1 |粗砂糖|200 ~ 220| +|1 |糖粉 |130 | +|1 |碎干果|114 | +|1 |葡萄干|170 | +|1 |蜂蜜 |340 | + +2. 如何保存多余的面包 + + 可以把面包切片进行冷冻,在下次使用时可以放置到常温处等待回温,亦或是直接加热。但**千万不要放到冷藏区!** 在冷藏区面包的水分会迅速流失。 + +3. 推荐食用方式 + +![成品](./5-1成品.jpg) + +a. 取一大块面包,上下一分为二。放入锅中小火加热(一般不需要加油,但如果希望脆皮可在面包表面涂抹黄油后再煎烤) 1 ~ 2 分钟。 +b. 锅中用喷壶喷 3 ~ 4 泵油,大火烧至锅中微微冒烟,转最小火。 +c. 然后下入一枚鸡蛋,盖盖子。等待 2 ~ 3 分钟。然后翻面再加热 2 ~ 3 分钟。 +(这是流心蛋的做法,如需要全熟蛋,可在翻面前加入最多 1 ml 的水,转中小火,直至把水烧干。这样就得到了一个全熟蛋) +d. 将面包双面涂上喜欢的任何酱料,将鸡蛋夹在中间。 + +------------------------------------------ \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/微波炉腊肠煲仔饭/微波炉腊肠煲仔饭.md b/data/C8/cook/dishes/staple/微波炉腊肠煲仔饭/微波炉腊肠煲仔饭.md new file mode 100644 index 0000000..f18b9cc --- /dev/null +++ b/data/C8/cook/dishes/staple/微波炉腊肠煲仔饭/微波炉腊肠煲仔饭.md @@ -0,0 +1,50 @@ +# 微波炉腊肠煲仔饭的做法 + +![微波炉腊肠煲仔饭](微波炉腊肠煲仔饭.png) + +程序员以单身汉居多 🐶,做再多的菜也会有一个人吃不完的烦恼,因此一份简单的腊肠煲仔饭则刚刚好。 + +使用微波炉烹制仅需 `15 分钟` ,既营养又美味,这是一道简单且细腻的主食,给 TA 露上一手吧。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 工具 + - 微波炉 + - 2 个大碗(推荐微波炉专用碗) + - 1 个小碗 +- 原料 + - 米 200 ml + - 腊肠 1 根 + - 鸡蛋 1 个 + - 红萝卜 1 个 + - 盐 + - 油 15 ml + - 生抽 10 ml + - 香葱 1 颗 + +## 计算 + +1 人份。 + +## 操作 + +- 将米淘洗干净后倒入 `饭碗` 内,加入 400ml 的水,**盖上盖** +- 放入微波炉,高火,`6` 分钟,煮饭途中准备原料 + - 切好腊肠 + - 洗好青菜 + - 切好红萝卜片 + - 切好葱花 + - `青菜碗` 中放入青菜、红萝卜片,倒入 10 ml 油,放入 5 g 盐 + - `小碗` 中倒入 10 ml 生抽、5 ml 油 +- 6 分钟后,用毛巾或隔热手套取出碗,可以看见米饭已经八分熟 +- 在米饭上摆入切片的腊肠,继续高火 `2` 分钟 +- 取出腊肠饭,放入 `青菜碗`,高火 `4-5` 分钟 +- 在腊肠饭上摆好青菜,磕入鸡蛋,看个人喜好继续高火 `40-60` 秒 +- 取出腊肠饭,此时已经基本完成。 +- 将 `小碗` 放入,继续高火 `30` 秒 +- 在腊肠饭上淋上叮热的生抽,撒上葱花即可 +- 多余的青菜可以沾着酱油吃 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/微波炉腊肠煲仔饭/微波炉腊肠煲仔饭.png b/data/C8/cook/dishes/staple/微波炉腊肠煲仔饭/微波炉腊肠煲仔饭.png new file mode 100644 index 0000000..a8fe3fa --- /dev/null +++ b/data/C8/cook/dishes/staple/微波炉腊肠煲仔饭/微波炉腊肠煲仔饭.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf6a4b313a3eb6935bddd6e0c6af4c762e91139d4314beffa9365d729ea7ee4d +size 524335 diff --git a/data/C8/cook/dishes/staple/意式肉酱面/final.jpg b/data/C8/cook/dishes/staple/意式肉酱面/final.jpg new file mode 100644 index 0000000..c6451e2 --- /dev/null +++ b/data/C8/cook/dishes/staple/意式肉酱面/final.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4308dbfe8c650eaa64adfd1453267fa0fbef2576950f70413dc5cf049797bba +size 168916 diff --git a/data/C8/cook/dishes/staple/意式肉酱面/sauce.jpg b/data/C8/cook/dishes/staple/意式肉酱面/sauce.jpg new file mode 100644 index 0000000..5148527 --- /dev/null +++ b/data/C8/cook/dishes/staple/意式肉酱面/sauce.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1fd980ce8583f0e29743981d598f40bc4cfca7178ed79d9d4934aefbd1711968 +size 102009 diff --git a/data/C8/cook/dishes/staple/意式肉酱面/spaghetti.jpg b/data/C8/cook/dishes/staple/意式肉酱面/spaghetti.jpg new file mode 100644 index 0000000..5008e12 --- /dev/null +++ b/data/C8/cook/dishes/staple/意式肉酱面/spaghetti.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0beec4d401e3cc317cacba32b324f84eddbfae4f58baf741411f420b95b15a12 +size 169125 diff --git a/data/C8/cook/dishes/staple/意式肉酱面/意式肉酱面.md b/data/C8/cook/dishes/staple/意式肉酱面/意式肉酱面.md new file mode 100644 index 0000000..7de10e1 --- /dev/null +++ b/data/C8/cook/dishes/staple/意式肉酱面/意式肉酱面.md @@ -0,0 +1,45 @@ +# 意式肉酱面的做法 + +![示例菜成品](./final.jpg) + +意式肉酱面是一道非常容易做的菜,做得熟练的话,可以在 15 分钟内完成,从此告别方便面 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 意大利面 +- 意大利面酱 +- 肉沫 +- 白洋葱(紫洋葱也可以) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 意大利面 180 克(可以根据食量上下浮动) +- 肉沫 80 克(可以根据食量上下浮动) +- 洋葱大半个 (大约 150 克,通常是肉的两倍重) +- 意大利面酱 300 克(可以看情况上下浮动) +- 食用油 10-15ml + +## 操作 + +- 锅中加水,烧开后放入意面(等待 6 - 12 分钟) +- 在烧水的时候可以进行下面这些步骤,但请注意煮面的时间 +- 洋葱切成小丁 +- 空锅中倒油,中火下入洋葱碎 +- 时刻搅拌,注意不要让洋葱烧糊,直到洋葱变成半透明状 +- 下入肉沫,继续搅拌(搅散),直到肉末变成棕色 +- 加入意大利面酱,稍微搅拌一下即可 +- 把煮好的意大利面沥干水分并倒入肉酱中搅拌均匀即可(或者直接把做好的肉酱倒在意面上也行) + +## 附加内容 + +- 意大利面分为很多不同的粗细,煮面条之前请注意意面盒子上标注的时间 +- 意大利面酱并不是番茄酱,平常用的番茄酱准确是叫番茄沙司,而意大利面酱虽然和番茄沙司都是调味过的番茄酱,但加的调味料不同 + +![不同种类的意面](./spaghetti.jpg) +![意大利面酱](./sauce.jpg) \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/手工水饺.md b/data/C8/cook/dishes/staple/手工水饺.md new file mode 100644 index 0000000..f48ef4f --- /dev/null +++ b/data/C8/cook/dishes/staple/手工水饺.md @@ -0,0 +1,89 @@ +# 手工水饺的做法 + +饺子是一道非常好吃的主食之一。饱肚且易于根据自己口味进行调味,适合在 US 的同学吃不到水饺解馋。一般初学者需要 3 小时完成,难度较大 + +预估烹饪难度:★★★★★ + +## 必备原料和工具 + +- 擀面杖 +- 面粉 +- 冷水 +- 直径 30cm 以上的盆 +- 芝麻香油 + +## 计算 + +-单人,约 20 只 + +每份: + +- 面粉 200g +- 冷水 150ml +- 芝麻香油 2-3ml +- 瘦肉末 250g +- 肥肉末 20g #不喜可不加 +- 姜 3g +- 葱 15g +- 盐 3g +- 蚝油 2ml +- 香油 2ml +- 生抽 2ml +- 鸡蛋 1 个 + +## 操作 + +### 制作饺子皮 + +- 盆中加入所有面粉 +- 加入芝麻香油 +- 面粉中央挖小洞 +- 分 4-5 次加入水,并搅和,当出现碎末状的稍微干燥面团时 +- 取消加水,用手将面团压实 +- 面团压实至可把盆周围的面粉纳入即可,此步骤为面光盆光 +- 将面团置于桌上,盆倒扣于桌上,环境温度为 25 度,使面团醒发约 45 分钟 +- 醒发完成后,将面团搓成条状,合成一团,再次搓成条,重复 3 次 +- 擀成条状,切成 20 份均匀大小面团,并搓成直径约 3-3.5cm 的球状 +- 压扁面团,在手上,桌上,擀面杖上,及面团上撒上面粉,此步骤防止面团发粘 +- 用擀面杖将面团擀平,约 8cm 直径,厚约 2mm,中间略微比四周厚 1mm + +### 拌馅 + +- 猪肉去皮,保留部分肥肉,切成小块 +- 菜刀(建议两把)将猪肉剁成肉沫,放入碗中 +- 葱、姜切成末,放入肉碗中搅拌均匀 +- 韭菜洗净,切短至 3mm 以下长度 +- 韭菜和肉沫混合,加入蚝油、生抽、香油各 2ml,加入一个鸡蛋的蛋清,用手混合搅拌均匀 +- 放置 30 分钟即可开始包饺子 + +### 包饺子 + +- 左手上放面皮,放饺子馅一面尽量不要粘到面粉,防止无法合拢 +- 右手用筷子夹约面皮 1/2 直径的馅 +- 沿饺子皮圆周进行合拢,捏实,个人吃无需捏花,饺子皮不漏即可 + +### 煮饺子 + +- 使用可放下 20 只饺子的锅,或分批量煮 +- 烧水,水约 3/4 锅的高度 +- 大火烧开水后放入饺子,调至中火 +- 第一次放入饺子,且水冒泡后,锅边加入 50ml 冷水(重复此步骤两次) +- 第三次水开后加入冷水 50ml,水开后调至小火等 60s 即可出锅 + +## 附加内容 + +- 煮水饺不需要盖锅盖,加三次水就是为了不让饺子一直处于沸腾状态导致表皮破损变成面片。 + +这道菜存在一些补充做法,包括但不限于: + +额外添加下列材料: + +* 黑醋 10ml +* 姜 一小块 50 克 +* 香油 2 滴 +* 大蒜/蒜泥 3 瓣/人 + +* 考虑搭配黑醋食用。建议用量:10-20ml。 +* 考虑姜切丝,在小碗加入 20ml 的黑醋与姜丝搅拌当蘸料,味道更丰富。 +* 考虑搭配黑醋时加入 1~3 滴香油,搅拌当蘸料。 +* 考虑搭配黑醋时加入砸好的蒜泥,搅拌当蘸料。(口腔内会残留蒜味,若饭后需要与他人面对面谈话建议放弃或清洁口腔) \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/扬州炒饭/veg.png b/data/C8/cook/dishes/staple/扬州炒饭/veg.png new file mode 100644 index 0000000..69fdeb7 --- /dev/null +++ b/data/C8/cook/dishes/staple/扬州炒饭/veg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07298958f870952d90a73c331a97fbf62d6917b5d9b8f5332196b0071ab58d33 +size 567767 diff --git a/data/C8/cook/dishes/staple/扬州炒饭/扬州炒饭.md b/data/C8/cook/dishes/staple/扬州炒饭/扬州炒饭.md new file mode 100644 index 0000000..e9ca0da --- /dev/null +++ b/data/C8/cook/dishes/staple/扬州炒饭/扬州炒饭.md @@ -0,0 +1,63 @@ +# 扬州炒饭的做法 + +扬州炒饭是蛋炒饭的升级版,制作时间较长,但是制作步骤简单 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 冷饭(干一点的为佳) +- 鸡蛋 +- 冷冻去皮基围虾 +- 午餐肉罐头 +- 青豆 +- 胡萝卜 +- 玉米粒(可选) +- 葱 +- 油 +- 盐 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1-2 个人吃。 + +每份: + +- 冷饭 500g +- 鸡蛋 2-3 个 +- 冷冻去头去皮基围虾 10-15 只 +- 午餐肉罐头 150g(推荐上海梅林的火腿午餐肉罐头,340g 每罐,一次用半罐) +- 青豆 30g +- 胡萝卜 30g +- 玉米粒 30g +- 葱 1 根 +- 油 30-40ml +- 盐 12-15g + +## 操作 + +- 胡萝卜切丁 0.2cm*0.2cm*0.2cm,备用 +- 午餐肉切丁 0.2cm*0.2cm*0.2cm,备用 +- 葱分别取葱白和葱绿,各切成 0.25-0.5cm 的小段,分开备用 +- 在碗中打入鸡蛋液,均匀搅拌,备用 +- 将胡萝卜,青豆,玉米粒煮熟捞出,备用(水别倒) +- 将虾煮熟,捞出备用(水可以倒了) +- 热锅热油,可以参考[学习炒与煎](../../../tips/learn/学习炒与煎.md)中的热锅双油 + - 第二次倒油需使用 20-30ml 油,等到第二次凉油热了以后,缓慢倒入鸡蛋(控制碗到油直接的流注直径大约在 0.5cm)不要搅拌 +- 鸡蛋凝固后立刻捞出,备用 +- 将午餐肉,青豆,胡萝卜,玉米粒,虾倒入锅中翻炒 1-2 分钟,装盘备用 +- 水冲一下锅,将杂物冲干净,保证锅内干净(可以有油但是不能有杂质) +- 热锅热油(10ml),将葱白放入爆香 +- 调至小火(如果油温过高可以关火 1-2 分钟),放入米饭,用铲子快速砸击米饭并翻炒,保证米饭均匀沾到油且粒粒分明 +- 倒入鸡蛋,继续砸击,使鸡蛋碎开并与米饭充分混合 +- 转大火,倒入其他所有备用配料,快速翻炒 1-2 分钟 +- 撒入盐,并翻炒至充分混合 +- 撒入葱绿,翻炒 1 分钟 +- 关火,装盘 + +## 附加内容 + +- 如做完后胳膊酸痛为正常现象,需加强上肢锻炼 +- 超市有青豆,胡萝卜,玉米粒的混合冷冻包装,可以使用这个省去切丁的烦恼,推荐 Pams Mixed Veges 很便宜,或者类似的都可以用(如下图) + +![Pams Mixed Veges](./veg.png) \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/披萨饼皮/001.jpeg b/data/C8/cook/dishes/staple/披萨饼皮/001.jpeg new file mode 100644 index 0000000..9340c11 --- /dev/null +++ b/data/C8/cook/dishes/staple/披萨饼皮/001.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddf220a8f27d244060686f06833a9b08d843bb96ad5a8ea51e6bb76b26320623 +size 298265 diff --git a/data/C8/cook/dishes/staple/披萨饼皮/披萨饼皮.md b/data/C8/cook/dishes/staple/披萨饼皮/披萨饼皮.md new file mode 100644 index 0000000..c0862e9 --- /dev/null +++ b/data/C8/cook/dishes/staple/披萨饼皮/披萨饼皮.md @@ -0,0 +1,73 @@ +# 披萨饼皮的做法 + +![示例是青红椒火腿披萨](./001.jpeg) + +披萨制作总体来说比较简单,稍微有点麻烦也是争议最多的就是披萨饼皮,做好了披萨饼皮喜欢吃什么口味的披萨,直接把准备好的食材放上去烤熟就好,所以这里重点说一下披萨饼皮如何制作。 + +本教程中的饼皮是属于软面团低温隔夜发酵 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +**原料** + +- 中筋面粉 +- 水(温水) +- 安琪干酵母粉 +- 食用盐 +- 橄榄油 +- 白砂糖 + +**工具** + +- 烤箱 +- 烘焙油纸 +- 披萨石(有更好,没有普通烤盘也可以) +- 擀面杖(非必需) + +## 计算 + +一个 8 ~ 9 寸的披萨差不多需要 125g 面粉,差不多是一个人的量(成年男性将将够吃的样子) + +原材料的混合比例 + +```text +面粉 : 水 : 橄榄油 : 酵母粉 : 盐 : 糖 +100 : 70 : 7 : 1 : 0.6 : 0.6 +``` + +示例 + +如果要一次做 4 个饼皮,需要: + +- 面粉 125g x 4= 500g, +- 水 70 x 5 = 350g, +- 橄榄油 7 x 5 =35g, +- 酵母粉 1 x 5 = 5g, +- 盐 0.6 x 5 = 3g, +- 糖 0.6 x 5 = 3g + +## 操作 + +- 用准备好的温水把酵母粉化开,稍微搅拌小就好,备用 +- 取准备好的面粉,依次添加盐、橄榄油、白砂糖 +- 准备混合水和面粉,边加水边搅拌直至水全部加完 +- 搅拌至看不到干米粉为止 +- 用差不多三倍大面团的容器装好,密封,冰箱冷藏(4 度) **等待 8~12 小时,一般晚上做第二天就可以用** +- 观察面团醒发完毕 **差不多是原始大小大约两倍算醒发完毕** +- 取醒发好的面团,均匀分成四份,分别用保鲜膜盖好,备用 +- 案板撒稍微多一点的干面粉,准备开始揉面 +- 因为是比较湿的面团,所以粘上干面粉后才没那么粘手,不用揉太多次,面团表面稍微光滑一点就可以了 +- 用手拉扯,或者擀面杖擀平,也不一定非得擀圆,只要厚度均匀,烤箱放得进去就好 +- 铺好油纸,放上饼皮,依照个人口味,把准备好的食材放上去,撒上芝士碎 +- 水果烤箱上 180 度,下 220 度,16 分钟即可 +- 肉蔬菜烤箱上 200 度,下 230 度,18 分钟即可 +- 挤上沙拉酱或者其他自己喜欢的酱即可享用~ + +## 附加内容 + +- 一定要注意水的比例 +- 烤箱品质层次不齐,第一次做注意观察火候对披萨的影响 +- 一般不特别标注是低筋或高筋面粉,基本都是中筋面粉 +- 容易出水的水果不能作为食材,比如西瓜、橘子等 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/日式咖喱饭/成品.jpg b/data/C8/cook/dishes/staple/日式咖喱饭/成品.jpg new file mode 100644 index 0000000..004f462 --- /dev/null +++ b/data/C8/cook/dishes/staple/日式咖喱饭/成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5d98099674c671c010ded82351ad55ab896a989826cec48bc4ed4c55020393e +size 152896 diff --git a/data/C8/cook/dishes/staple/日式咖喱饭/日式咖喱饭.md b/data/C8/cook/dishes/staple/日式咖喱饭/日式咖喱饭.md new file mode 100644 index 0000000..689d559 --- /dev/null +++ b/data/C8/cook/dishes/staple/日式咖喱饭/日式咖喱饭.md @@ -0,0 +1,89 @@ +# 日式咖喱饭的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +### 主食材 + +- 咖喱块(推荐品牌好侍) +- 土豆 +- 胡萝卜 +- 洋葱 +- 肉(猪肉、鸡肉、牛肉均可) +- 蒜头 + +### 副食材 + +额外用作点缀的食材,可选 + +- 花椰菜(清水煮开) +- 培根(即食) +- 煎蛋或[太阳蛋](../../breakfast/太阳蛋.md) + +## 计算 + +食材用量与咖喱成正比,计算部分以 **半盒好侍咖喱块(115g)** 为例。半盒约六碗份,做好的咖喱在冰箱冷藏后风味更佳,不用担心一个人吃不完。 + +- 洋葱 2 个 +- 土豆 2 个 +- 胡萝卜 1 根 +- 蒜头 2~3 瓣 +- 肉 2 斤 + +## 操作 + +### 1. 食材准备 + +- 胡萝卜去头尾,去皮,滚刀切 +- 洋葱剥去外层去芯,切成月牙状 +- 土豆去皮、切大块 +- 肉切块状 +- 剥蒜拍平切碎 +- 咖喱块切碎,增加接触面积加速溶解 + +### 2. 烧煮过程 + +- 热油锅放入蒜和肉,**快速翻炒**至肉*表面变白* +- 加入胡萝卜,**快速翻炒**至均匀受热 +- 加入洋葱,**快速翻炒**至洋葱*变透明状* +- 加入土豆,保持翻炒至土豆*变软*(可以用筷子确认) +- 加水没过所有食材,沸腾后**等待 15 分钟** +- 关火,加咖喱并搅拌 +- 等待咖喱融化后再开火,缓慢**搅拌 10 分钟**,防止糊锅 +- 在外观*呈粘稠状态*关火结束制作 + +### 3.冷藏后加热 + +冷藏的咖喱每次取出需要吃的份量,加热后盖在[米饭](../米饭/电饭煲蒸米饭.md)上。 + +- 微波炉:单人份高火 2-3 分钟 +- 锅:需额外加 50ml 水,加热时保持搅拌 + +## 附加内容 + +### 备注说明 + +- 步骤 1-6 可以在 2-5 的等待过程进行,在这个过程也可以用清水锅煮些蔬菜,或做个煎蛋。 +- 2-5 到 2-6 之间,需要注意观察沸腾的水位线,如发现低于 2/3 的食材应加热水至没过食材。 + +### 流程图解 + +``` mermaid +graph TD + A[处理肉, 胡萝卜, 洋葱, 土豆] --> B(开油锅, 先后下锅炒熟) + B --> C[加水没过食材, 煮15分钟] + C --> D[咖喱切碎, 开水煮花椰菜等] + C --> E[加入咖喱搅拌 10 分钟] + D --> E +``` + +### 成品 + +![日式咖喱饭成品](./成品.jpg) + +### 参考资料 + +- [世界美食教程的微博视频](http://t.cn/EJ77yFy) + +--- \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/日式肥牛丼饭/成品.png b/data/C8/cook/dishes/staple/日式肥牛丼饭/成品.png new file mode 100644 index 0000000..8db9695 --- /dev/null +++ b/data/C8/cook/dishes/staple/日式肥牛丼饭/成品.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbfbec148ac10e7864524df3cd78e775ca7f17d2452e09781be3c375b217fc2e +size 768884 diff --git a/data/C8/cook/dishes/staple/日式肥牛丼饭/日式肥牛丼饭.md b/data/C8/cook/dishes/staple/日式肥牛丼饭/日式肥牛丼饭.md new file mode 100644 index 0000000..49469db --- /dev/null +++ b/data/C8/cook/dishes/staple/日式肥牛丼饭/日式肥牛丼饭.md @@ -0,0 +1,91 @@ +# 日式肥牛丼饭的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +### 主食材 + +- 洋葱(务必选用外皮为白黄色的洋葱,不要用紫色的洋葱) +- 肥牛(火锅肥牛即可,也可选用原切肥牛片) +- 葱(也可选用切好的葱段) +- 白芝麻 +- 味淋(一种常用日式调料,可在各大电商平台购买,也可用料酒代替) + +### 副食材 + +额外用作点缀的食材,可选 + +- [温泉蛋](../../breakfast/温泉蛋/温泉蛋.md) +- 出汁(使用柴鱼干和昆布熬制的汤汁,可以用于提鲜) + +## 计算 + +食材用量与米饭成正比,计算部分以 **一杯米(160ml)** 为例。约为二人食用分量,吃不完可以放冰箱冷藏,但可能会没那么好吃 + +- 洋葱 1 个 +- 肥牛 250 克 +- 葱 1~2 根 +- 白芝麻 5 克 + +## 操作 + +### 1. 食材准备 + +- 洋葱剥去外层去芯,切成月牙状 +- 葱洗净切成 0.5cm 的小段 +- 热锅直接放入白芝麻,**前后晃动锅体**使芝麻均匀受热至*略呈金黄色* +- 肥牛焯水 1 分钟后捞出 +- 将 40g `味淋`(或 30g `料酒`),30g `酱油`,20g `耗油`,5g `糖`,5g `老抽`(可选,用于调色),在碗中搅拌混合成`调料`(该步骤可直接将碗放在电子秤上进行) + +### 2. 烧煮过程 + +- 热油锅放入洋葱,**快速翻炒**至洋葱*变透明状* +- 关小火,加入 250g 水(或出汁),开回大火加热**等待 3 分钟** +- 加入牛肉和`调料` +- **不断翻动**所有食材 **10 分钟**,防止食材粘锅 +- 关火 +- 盛装肥牛丼至[米饭](../米饭/电饭煲蒸米饭.md)上(注意要把汁水淋一些在饭上) +- 撒上葱花和白芝麻,制作完成。 + +### 3.冷藏后加热 + +冷藏的牛丼每次取出需要吃的份量,加热后盖在[米饭](../米饭/电饭煲蒸米饭.md)上。 + +- 微波炉:单人份高火 2-3 分钟 +- 锅:需额外加 50ml 水,加热时需**不断翻动** + +## 附加内容 + +```shell +struct Staple{float 咸度;}; +struct Staple 牛丼 +牛丼.咸度 = 尝一口汤汁; +while(牛丼.咸度 < 预期) 加入(1 g)酱油; 牛丼.咸度 = 尝一口汤汁; +``` + +### 备注说明 + +- 如果用的是比较不错的牛肉,可以选择不焯水,能够更加保留牛肉的风味,因为加入了味淋所以不会很腥,无需担心牛肉不熟,加热 10 分钟肯定熟了 +- 如果有条件,选择加入 15g`清酒` + +### 流程图解 + +``` mermaid +graph TD + A[处理肉,洋葱,葱花,白芝麻] --> B[开油锅, 炒熟洋葱] + B --> C[加水, 煮3分钟] + C --> D[加入牛肉和调料, 边搅拌边煮10分钟] + D --> E[盛装至碗中,撒上葱花和白芝麻] +``` + +### 成品 + +![日式肥牛丼饭](./成品.png) + +### 参考资料 + +- [河水洋洋实验室 【牛丼|肥牛饭】吉野家牛肉饭的正宗做法](https://www.bilibili.com/video/BV1rK4y1d7Fk) +- [夏叔厨房 60秒搞定神仙配方,好吃又下饭的肥牛饭!](https://www.bilibili.com/video/BV1xu4y1676X) + +--- \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/汤面.md b/data/C8/cook/dishes/staple/汤面.md new file mode 100644 index 0000000..599bf4f --- /dev/null +++ b/data/C8/cook/dishes/staple/汤面.md @@ -0,0 +1,37 @@ +# 汤面的做法 + +汤面是许多人喜爱的基础主食,根据个人喜好加入任何自己喜欢的食材,营养全面,固液兼具,材料易得,做法简单,有手就行。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 面食材料:可以是手工面条、龙须面、面鱼,也可以是泡面面饼、各类规格粉丝,或者是其他任何自己所喜欢的面食形式。 +- 菜类材料:建议荤素搭配,选择自己喜欢的食材洗干净即可。例如: + - 牛羊鱼虾等肉类(生熟皆可) + - 鸡蛋鸭蛋鹅蛋鸵鸟蛋等蛋类 + - 豆块豆筋豆腐皮等豆制品类 + - 生菜菠菜油麦菜 + - 青椒番茄胡萝卜等蔬菜类。 + +## 计算 + +- 面类材料:单人一个方便面大小的量,可以在 70-230g 之间选择。 +- 冷水: 加入能浸没面的量,一般在 200 - 400 ml 之间选择 +- 菜类:体积大约和面类相当 + - 其中青菜体积可忽略 + +## 操作 + +- 先将菜类材料切成边长不超过 4cm 的块状,便于煮熟 +- 如有生肉,则先放入冷水中,盖上锅盖,煮沸腾,先捞出上层血沫,再关火,捞出半熟的肉备用 +- 先大火将水加热至沸腾,后调至中火 +- 将较难煮熟的食材放入锅中(比如半熟肉类、香菇类、等最先放入锅中)。为保证煮熟,可在沸腾后计时 10 分钟,特别难熟的大块食材可追加 5 分钟。 +- 将面食放入锅中,适当搅拌确保面和汤充分接触,使液面保持轻微沸腾,煮 5 分钟。加入面后液面易产生白色泡沫,可适当抬起锅盖通气或者撤下锅盖。 +- 将易于煮熟的食材如青菜类放入锅中,适当搅拌以充分浸没,煮 2-5 分钟 +- 关火,随后加入盐、胡椒粉、香油等自己喜欢的调味料,适当搅拌即可出锅食用 + +## 附加内容 + +- 操作流程可根据自己喜好更改,多多尝试会有惊喜 +- 如掌握不好加盐量,可采用少量多次添加的方法,以免过量 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/河南蒸面条/河南蒸面条.md b/data/C8/cook/dishes/staple/河南蒸面条/河南蒸面条.md new file mode 100644 index 0000000..de929a4 --- /dev/null +++ b/data/C8/cook/dishes/staple/河南蒸面条/河南蒸面条.md @@ -0,0 +1,85 @@ +# 河南蒸面条的做法 + +![示例菜成品](./河南蒸面条.png) + +河南蒸面条是一道在河南坊间流行的小吃,也可以用家里的挂面制作。 + +简单来讲,是先将挂面裹油放入蒸笼蒸熟,再加蔬菜配以调料炒,最后二次蒸制,以达到入味劲道的效果。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 挂面 (推荐圆的) +- 五花肉 +- 蒜薹 +- 葱 + 姜 + 蒜 + 料酒 +- 盐 + 鸡精 + 十三香 +- 生抽 + 老抽 + 蚝油 +- 麻油 +- 油 + 锅 + 菜刀 + 铲子 +- 蒸篦子 +- 额外的盆 + +## 计算 + +下面的量是仅仅 1 够一个人一餐的主食的量!请针对实际调整用料的量! + +每份: + +- 挂面 300g +- 五花肉 350g +- 蒜薹 150g +- 食用油 10-15ml +- 生抽 15ml +- 老抽 10ml +- 蚝油 5ml +- 盐 2g +- 鸡精 2g +- 十三香 1g +- 葱 10g +- 姜 5g +- 蒜 10g +- 料酒 5ml +- 麻油 5ml + +## 操作 + +### 第一次蒸 + +- 起锅加 7 成水,水开,上蒸篦子 +- 将挂面,均匀铺开放置,淋 5ml 油并抹匀,蒸 15 分钟 +- 将挂面和蒸篦子取出,放置一边,并倒掉锅中的水 + +### 切菜 + +- 五花肉,切成 2mm 厚度的肉片 +- 蒜薹,切成 3cm 段 +- 葱,切成 0.2cm 薄片 +- 姜,切成 1mm x 1mm x 3cm 的细丝 +- 蒜,放在砧板上拍碎,切成 1mm 的粒度 + +### 炒制 + +- 起锅,烧干水分,加 3ml 食用油 +- 手持锅柄,摇晃锅,使食用油充分挂满锅的 2/3 +- 中火,加入肉片,翻炒 1 分钟 +- 加入葱姜蒜,料酒,继续翻炒 1 分钟 +- 将蒜薹段,放入锅中,翻炒 1 分钟 +- 开始调味,加入老抽、生抽、蚝油、盐、鸡精、十三香,翻炒 1 分钟 +- 加入 500ML 水,没过蔬菜,炖煮 1 分钟 +- 将蒸好的挂面放入,不断搅拌 3 分钟,待挂面全部均匀上色,关火 +- 将搅拌好的挂面和菜,全部倒入额外的盆中 + +### 第二次蒸 + +- 起锅,加冷水 7 成,放上蒸篦子,将拌好的面条和菜,均匀的铺在上面 +- 水开后,大火烧 15 分钟,出锅 +- 淋上 10g 的麻油,即可食用 + +## 附加内容 + +挂面的粗细与口感: + +- 细的、圆的 (超市大部分都是这种,口感更加劲道) +- 宽的、扁的 (口感比较软) \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/河南蒸面条/河南蒸面条.png b/data/C8/cook/dishes/staple/河南蒸面条/河南蒸面条.png new file mode 100644 index 0000000..a451e25 --- /dev/null +++ b/data/C8/cook/dishes/staple/河南蒸面条/河南蒸面条.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0638228136e6496fdbb18cb7e54a2832132ae74f0d0eba7005900009b029283 +size 876711 diff --git a/data/C8/cook/dishes/staple/火腿饭团/火腿饭团.md b/data/C8/cook/dishes/staple/火腿饭团/火腿饭团.md new file mode 100644 index 0000000..73df8bb --- /dev/null +++ b/data/C8/cook/dishes/staple/火腿饭团/火腿饭团.md @@ -0,0 +1,46 @@ +# 火腿饭团的做法 + +![火腿饭团](./饭团.png) +好吃!富含碳水和蛋白质还有维生素。有手就行的制作难度,预计制作时间 1 h 。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 火腿 +- 米饭 +- 水 +- 冷冻青豆(可选) +- 冷冻玉米粒(可选) +- 海苔碎(可选) +- 喜欢的沙拉酱(推荐日式 mayo!) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 火腿(100g) +- 米饭(125g) +- 水(90ml) +- 冷冻青豆(30g) +- 冷冻玉米粒(30g) +- 海苔碎(10g) +- 喜欢的沙拉酱(20g) +- 食用油 10-15ml + +## 操作 + +- 将米饭和水放到电饭锅里,点击米饭模式,等待完成 +- 冷冻玉米粒和青豆放到锅里,加水没过所有食材,沸腾后静待 2 分钟后,捞出。 +- 火腿切成 1cm 的方块 +- 与此同时,加入 10ml 食用油,加入火腿翻炒至火腿上色 +- 将米饭,火腿,海苔碎,青豆,玉米粒,沙拉酱放入碗中,混合均匀即可 +- 装盘(如果有的话) + +## 附加内容 + +- 沙拉酱的程度可以根据个人口味酌情删减。 +- 可以尝试混合沙拉酱。 +- 参考资料:小红书 - 干饭选手又困了 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/火腿饭团/饭团.png b/data/C8/cook/dishes/staple/火腿饭团/饭团.png new file mode 100644 index 0000000..cb67987 --- /dev/null +++ b/data/C8/cook/dishes/staple/火腿饭团/饭团.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef35bd4e25a072054cbea8a2497d9ccbf2dd2c6f693c2c603c79906f0e0a39fd +size 672534 diff --git a/data/C8/cook/dishes/staple/炒凉粉/chaoliangfen.jpg b/data/C8/cook/dishes/staple/炒凉粉/chaoliangfen.jpg new file mode 100644 index 0000000..5c40f00 --- /dev/null +++ b/data/C8/cook/dishes/staple/炒凉粉/chaoliangfen.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4852c438189a41be847389d8e327b4e0abd270e7a1ea2c777fedd78788c13b10 +size 567744 diff --git a/data/C8/cook/dishes/staple/炒凉粉/炒凉粉.md b/data/C8/cook/dishes/staple/炒凉粉/炒凉粉.md new file mode 100644 index 0000000..7a1f893 --- /dev/null +++ b/data/C8/cook/dishes/staple/炒凉粉/炒凉粉.md @@ -0,0 +1,53 @@ +# 炒凉粉的做法 + +![炒凉粉成品](./chaoliangfen.jpg) + +炒凉粉是一道流行于山西、陕西地区的一道特色小吃,入口滑嫩,老少皆宜。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 凉粉 +- 玉米油 +- 大蒜 +- 香葱 +- 豆瓣酱 +- 生抽 +- 老抽 +- 食盐 +- 十三香 +- 中粗辣椒面 +- 矿泉水 + +## 计算 + +下述材料为一人份,每次制作前需要确定计划做几份。一份正好够一个人吃。 + +- 凉粉 500g +- 玉米油 10ml +- 蒜末 10g +- 香葱 15g +- 豆瓣酱 15g +- 生抽 20ml +- 老抽 10ml +- 食盐 5g +- 十三香 5g +- 中粗辣椒面 15g +- 矿泉水 20ml + +## 操作 + +- 凉粉改刀切麻将块大小 +- 开小火,起锅烧油,锅烧微热后,下入蒜末爆香后加入豆瓣酱炒出红油 +- 将凉粉块下入锅中,翻炒 10 秒 +- 加入生抽提味,老抽上色,翻炒均匀后加入辣椒面继续翻炒均匀 +- 加入食盐、十三香继续翻炒 10 秒 +- 加入准备好的矿泉水,再次翻炒 10 秒,待汤汁浓稠后,关火出锅装盘 +- 撒上葱花即可完成 + + ![炒凉粉成品](./chaoliangfen.jpg) + +## 附加内容 + +- 选择凉粉时最好选用豌豆淀粉制作成的凉粉,条件不允许的话红薯淀粉或其他也可 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/炒凉粉/炒凉粉成品.jpg b/data/C8/cook/dishes/staple/炒凉粉/炒凉粉成品.jpg new file mode 100644 index 0000000..5c40f00 --- /dev/null +++ b/data/C8/cook/dishes/staple/炒凉粉/炒凉粉成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4852c438189a41be847389d8e327b4e0abd270e7a1ea2c777fedd78788c13b10 +size 567744 diff --git a/data/C8/cook/dishes/staple/炒年糕.md b/data/C8/cook/dishes/staple/炒年糕.md new file mode 100644 index 0000000..9d226ab --- /dev/null +++ b/data/C8/cook/dishes/staple/炒年糕.md @@ -0,0 +1,42 @@ +# 炒年糕的做法 + +闽南风味的炒年糕是一道非常好吃的主食。它制作过程简单,原料获取方便,适合海外朋友满足口腹之欲。初学者需要 30 分钟完成,难度较小。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 年糕/白粿 (形状不限) +- 葱 +- 调味料: 酱油,盐 +- (可选):鸡蛋,青菜 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +- 年糕 250 g * 份数 +- 小葱 2 根 * 份数 +- 食用油 50 ml +- 酱油 15 ml +- 盐 1-2g * 份数,按口味喜好。 + +## 操作 + +- 锅中加水烧开,煮熟年糕,碗中加水确保年糕不会粘连,捞起年糕备用。 +- 小葱切葱花(将葱白和葱叶分开),青菜切小段备用。 +- (可选) 制作炒蛋,见[西红柿炒蛋](https://github.com/Anduin2017/HowToCook/blob/master/dishes/vegetable_dish/%E8%A5%BF%E7%BA%A2%E6%9F%BF%E7%82%92%E9%B8%A1%E8%9B%8B.md)。 +- 热锅,加入 30ml 食用油。 +- 将葱白倒入锅中,直至大部分葱白变成焦黄色且发出香味,倒出葱油备用。 +- 重新热锅,加入 20ml 食用油。 +- 加入所有辅料(鸡蛋,青菜等),翻炒均匀。 +- 将年糕的水倒掉,向锅中加入年糕。 +- 加入酱油和盐,翻炒均匀。 +- 关火,加入葱油,翻炒均匀,乘盘。 + +## 附加内容 + +- 辅料的选择可以根据个人选择酌情添加,如加入瘦肉等 +- 在煮年糕的时候注意搅拌,以免粘锅 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/炒意大利面/a.jpg b/data/C8/cook/dishes/staple/炒意大利面/a.jpg new file mode 100644 index 0000000..8939bc5 --- /dev/null +++ b/data/C8/cook/dishes/staple/炒意大利面/a.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ead34b3329208a7e058badc4cb271ba63f9f7e21a0660f00b753d096f9cd3728 +size 197054 diff --git a/data/C8/cook/dishes/staple/炒意大利面/炒意大利面.md b/data/C8/cook/dishes/staple/炒意大利面/炒意大利面.md new file mode 100644 index 0000000..15c836f --- /dev/null +++ b/data/C8/cook/dishes/staple/炒意大利面/炒意大利面.md @@ -0,0 +1,31 @@ +# 炒意大利面的做法 + +![意大利面](./a.jpg) + +这是一道软糯爽口的意大利面的做法,非常简单,用时大概 30 分钟。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 意大利面 +- 肥牛片 +- 番茄酱 / 黑胡椒酱(选其一即可) +- 菜籽油(其他植物油也可) + +## 计算 + +- 意大利面 50 克 / 人 +- 肥牛 5 片 / 人 +- 食用油 5ml / 50 克意面 + +## 操作 + +- 加入 250 克水 / 人 +- 待水烧开,下入面条,中火煮 15 - 20 分钟(这个面通常比较硬,捞起来之前最好尝一下,中心如果有一点硬,需要继续煮) +- 捞出面条,盛入盘中备用 +- 热锅倒入食用油,待油温中热,下入面条翻炒一分钟(如果太干,加入少量水) +- 放入 10 克番茄酱、肥牛、加入 2g 食盐,继续翻炒一分钟 +- 起锅 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/炒方便面.md b/data/C8/cook/dishes/staple/炒方便面.md new file mode 100644 index 0000000..7acdb59 --- /dev/null +++ b/data/C8/cook/dishes/staple/炒方便面.md @@ -0,0 +1,68 @@ +# 炒方便面的做法 + +这是在探究了传统煮方便面的改良方向之后,进行的一次最成功的尝试。它能够让方便面的美味程度提升很大程度,简单好做。开始炒吧! + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 方便面 +* 盐 +* 鸡蛋 +* 火腿肠(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +* 方便面用量为 1.2 包/人 向下取整。 +* 鸡蛋的用量为 1.4 个/人 向下取整。 +* 盐的用量为 鸡蛋的用量 * 2g。 +* 火腿肠的用量为 0.7 个/人 向上取整。 +* 食用油的用量为 10 - 18 ml / 人。 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 火腿肠预处理 + +* 将火腿肠撕开包装,切成宽度 1cm 的小块。 + +### 面的处理 + +* 向煮锅中加入 300 ml 水。煮沸。 +* 加入方便面面饼,煮 45 秒。煮的过程中将其挑动,把面条打散。 +* 面条打散后立刻关火。 +* 将面汤和面分离。用凉水冲一下面条。 + +### 酱料处理 + +* 准备一个小碗,将方便面的调料包挤进去。 + * 挤进去所有菜包 + * 挤进去所有酱包 + * 挤进去 50% - 80% 的粉包。(全部粉包都挤进去会很咸) +* 将上一步的面汤取出 80ml,加入小碗,搅匀,得到调料碗。 + +### 鸡蛋的预处理 + +* 取出计算好的数量的鸡蛋,打入一个小碗。 +* 每个鸡蛋加入 2g 盐。搅拌均匀。 +* 热锅 20s,加入份数 * 8ml 油。 +* 加入刚刚准备好的一碗鸡蛋。翻炒大约 20s 至鸡蛋形成固态即可。 +* 将煎鸡蛋取出暂存。 + +### 最终步骤 + +* 热锅 20s,增加锅内的油到份数 * 10ml。 +* 加入第一步处理的火腿肠。翻炒 10 秒。 +* 加入第二步的面。翻炒 30 秒。 +* 加入第三步的调料碗。翻炒 30 秒。 +* 加入第四步的煎鸡蛋。翻炒 30 秒。 +* 关火盛盘即可。 + +## 附加内容 + +在北京,可以考虑在盛盘后加入芝麻酱。如果芝麻酱太浓稠,可以 1:1 兑水稀释。 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/炒河粉.md b/data/C8/cook/dishes/staple/炒河粉.md new file mode 100644 index 0000000..12bd0de --- /dev/null +++ b/data/C8/cook/dishes/staple/炒河粉.md @@ -0,0 +1,57 @@ +# 炒河粉的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 炒河粉、猪肉/牛肉 +* 炒料:盐、味精、老抽、生抽、孜然粉(或直接用河粉料) +* 其他调味料:胡椒粉 +* 黄瓜、面筋块、绿豆芽、鸡蛋、蒜瓣、小葱、淀粉 +* 盆、盘子 + +> 建议购买方案:在某宝、某买菜等平台上购买袋装鲜河粉,一般是1斤起售,冷藏保质期可达到两周,而且送河粉炒料! + +## 计算 + +* 河粉用量为 250 g/人,如果需要更大食量,可再加 100g/人 向下取整。 +* 黄瓜丝 30g/人、面筋块 30g/人、绿豆芽 30g/人、打碎的鸡蛋 1 个/人。 +* 拍碎的蒜瓣 2 个/人、小葱 1 根/人 +* 河粉料可按 20g/人添加,若自行准备炒料可 10g 盐+2g 味精+3g 孜然粉。 +* 淀粉可准备每 100g 肉+5g 淀粉比例准备。 +* 老抽/生抽,分别为每 250g 河粉 10ml/15ml。 + +## 操作 + +### 准备工作 + +* 小葱切碎(葱白和葱叶分开)、蒜瓣拍碎,丢案板上备用。 +* 打碎鸡蛋,捞一点蛋清到一只碗中,剩下的丢入另一只碗中备用。 +* 将绿豆芽放入锅中,大火煮 60 秒。豆芽捞出,过凉水,放入盘中备用。 +* 黄瓜切丝放入盘中备用,可和豆芽丢一起。 +* 处理面筋,单独丢一个盘中。 +* 肉切细条状,加入淀粉与刚刚碗中的鸡蛋清、胡椒粉,顺时针拌匀。 +* 注:超市购买来的凉皮表面一般会有食用油,可以使用自来水清洗。面筋同样。 +* 注:清洗面筋之后,请用手将面筋中的大量水分挤出(不需过于用力)。 + +### 热锅炒肉 + +* 加入食用油,锅热倒出。 +* 倒入处理好的肉,翻炒均匀至变色,倒入碗中备用。 + +### 炒制河粉 + +* 趁锅热,加入 20g 食用油(高血压人群可降低用量),倒入葱白、蒜爆炒出香。 +* 加入河粉,淋入老抽提色,翻炒均匀后再加入河粉炒料,继续翻炒。 +* 河粉即将透明时,放入炒制好的肉丝与面筋,并加入生抽提鲜,简单翻炒两次。 +* 加入豆芽与黄瓜丝,翻炒至河粉完全透明。 +* 关火! + +### 最终步骤 + +* 撒入葱叶点缀,把锅端起。 +* 倒入盘中,开始干饭。 + +## 附加内容 + +个人口味根据地区、天气、时间均有不同,调料的具体使用量请据个人情况而定,喜欢辣椒的可以自行添加。 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/炒馍.md b/data/C8/cook/dishes/staple/炒馍.md new file mode 100644 index 0000000..6c42a46 --- /dev/null +++ b/data/C8/cook/dishes/staple/炒馍.md @@ -0,0 +1,46 @@ +# 炒馍的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 馒头(隔天略硬更好) +* 盐 +* 油 +* 孜然粉 +* 五香粉 +* 小葱 +* 鸡蛋(可选) + +## 计算 + +* 馒头 2 个(隔天略硬更好) +* 盐 3g +* 油 20ml(花生油或芝麻油更好) +* 孜然粉 3g +* 辣椒粉 3g +* 五香粉 3g +* 小葱 2 棵 +* 鸡蛋 (可选,2 个) + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +* 将馒头切成小块或小片。 +* 选有鸡蛋的话将鸡蛋打进碗里,打散(可加盐和五香粉各 1g 或不加,等炒的过程中加)。 +* 鸡蛋浇在馒头上,拌匀,鸡蛋不宜过多。 +* 大火热锅,倒入食用油(不锈钢锅怕伤锅的话可以先倒油,烧至油热也可也可) +* 将馍丁放进去翻炒,翻炒均匀。 +* 将火调小,炒至馍丁呈金黄色。 +* 放入盐,胡椒粉,五香粉。 +* 最后将葱花放入一起翻炒几下。 +* 关火出锅。 + +## 附加内容 + +- 炒的过程中要注意控制火候,以防炒糊 +- 火大补救措施将火调小,可沿锅边加油润锅或洒水,注意不要全倒在一个地方,最好分散开 +- 调味料可根据个人喜好放入其他香料(比如南德调味料) +- 如果喜欢吃脆的,可以将火开到最小,多翻炒一会,关火后趁锅热再放置一会再倒出,更香脆 +- 辅料也可根据个人口味方位蒜末,蒜苗等,可以单独爆香在混合 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/炸酱面.md b/data/C8/cook/dishes/staple/炸酱面.md new file mode 100644 index 0000000..ea99150 --- /dev/null +++ b/data/C8/cook/dishes/staple/炸酱面.md @@ -0,0 +1,45 @@ +# 炸酱面的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 肉丁/肉末 +* 面条(挂面或普通面条) +* 蒜 +* 菜码(根据个人喜好选择,通常 4-10 种,可选择黄瓜、白菜、萝卜等) +* 豆瓣酱 +* 甜面酱 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +每份: + +* 肉丁/肉末 150g +* 如果 *面条* 选择了*挂面*:150g + 如果 *面条* 选择了*普通面条*:250g +* 葱 15g +* 菜码 总量 35g +* 食用油 10g +* 豆瓣酱 20g +* 甜面酱 20g + +## 操作 + +1. 菜码切丝备用。 +2. 葱切碎。油锅烧热,下葱和肉,炒至肉完全熟透(无红色) +3. 下豆瓣酱和甜面酱,继续炒至**微微粘稠**。盛出,得到*炸酱*。 +4. 取大碗,加凉水备用。 +5. 煮面条至断生(无白芯),盛入第 4 步装有凉水的碗中。 +6. 立即控水捞出,盛入干净的碗中。 +7. 取第 3 步炸酱,倒入碗中,拌匀。然后取第 1 步菜码,倒入碗中,拌匀。 + +## 附加内容 + +* 肉推荐瘦肉丁,口感更好,推荐现买现用。 +* *面条*推荐使用*普通面条*。 +* 面条口感关键在于劲道。勿选龙须等细面。 +* 如有条件(另一个锅)且熟练后,第 2、3 步和 1、4、5、6 步可分时并行执行。 +* 甜咸口个人有爱好,两种酱的配比需要自己迭代优化。 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/烙饼/成品.jpg b/data/C8/cook/dishes/staple/烙饼/成品.jpg new file mode 100644 index 0000000..6152a82 --- /dev/null +++ b/data/C8/cook/dishes/staple/烙饼/成品.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9be1b87ddc634a8c8df47e1f3725a5a25e5426875943c11b4285dc484c4b4f3a +size 144872 diff --git a/data/C8/cook/dishes/staple/烙饼/烙饼.md b/data/C8/cook/dishes/staple/烙饼/烙饼.md new file mode 100644 index 0000000..42b7327 --- /dev/null +++ b/data/C8/cook/dishes/staple/烙饼/烙饼.md @@ -0,0 +1,33 @@ +# 烙饼的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +* 油 +* 面粉 +* 电饼铛 + +## 计算 + +注意:该主食不提供更少或更多的版本,这里选取了最适合新手的量: + +* 面粉 = 400g +* 热水 = 130ml(80 度) +* 冷水 = 130ml + +## 操作 + +* 将 400g 面粉倒入盆中,一半用凉水和面,一半用热水和面,搅拌成面絮,用手揉成团。用保鲜膜封起来,醒面 40 分钟 +* 离醒面完成时间还有 10 分钟时,请查看[小技巧](../../condiment/油酥.md)中的油酥做法(热油酥效果更好) +* 醒好的面不用揉,稍微摁一下,用一横刀一竖刀将其分成四份。 +* 搓圆,擀开,擀成与电饼铛大小差不多的饼,取 1/4 的油酥,将饼表面涂抹均匀 +* 沿饼的半径切开,从外圈将其卷成圆锥形,然后将圆锥尾部捏好,防止油酥外漏。 +* 按压面饼圆锥尖的地方,将其压扁,然后再次擀成与电饼铛大小差不多的面饼(厚度约为 3mm) +* 将电饼铛预热,涂上凉油(热锅凉油),将擀好的饼放入电饼铛中,将饼的上方也刷点油,涂抹均匀(锁住水分),盖上盖子 +* 大火烙一分钟,打开盖子,将饼翻个面再烙一分钟 +* 重复以上动作,完成饼的烙制 + +![成品](./成品.jpg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/烧饼/芝麻烧饼.jpg b/data/C8/cook/dishes/staple/烧饼/芝麻烧饼.jpg new file mode 100644 index 0000000..8885f25 --- /dev/null +++ b/data/C8/cook/dishes/staple/烧饼/芝麻烧饼.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:895d1be5cd871c5041d87ec45a442e4513665af69f7f44c1c57eb383b1b03f5f +size 105129 diff --git a/data/C8/cook/dishes/staple/烧饼/芝麻烧饼.md b/data/C8/cook/dishes/staple/烧饼/芝麻烧饼.md new file mode 100644 index 0000000..140b312 --- /dev/null +++ b/data/C8/cook/dishes/staple/烧饼/芝麻烧饼.md @@ -0,0 +1,31 @@ +# 芝麻烧饼的做法 + +![示例菜成品](./芝麻烧饼.jpg) +芝麻烧饼,外酥里软,简单易做。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 面粉 +- 酵母粉 +- 白糖 +- 十三香 +- 食用油 +- 温水( 40℃ ) + +## 计算 + +菜谱食材为 7 张饼的量 + +## 操作 + +- 面团:300 克面粉,3 克酵母粉,3 克白糖,180 克温水,20 克食用油,醒面 10 分钟 +- 油酥:小碗放 30 克面粉,2 克盐,4 克十三香,20 克食用油,拌匀后,静置 +- 做饼:面擀成长方形,抹上调好的油酥,从一头卷起,切成 7 个面剂子,对折,用虎口收拢即可,先沾水再沾白芝麻,擀成小圆饼 +- 烙饼:将电饼铛预热,倒入凉油(锅底铺满油),将擀好的饼放入电饼铛中,将饼的上方也刷点油,涂抹均匀盖上盖子,选大饼档,听到叮的一声出锅即可 + +## 附加内容 + +- 如果没有电饼铛,也可以用平底锅 +- 芝麻如果没有也可不用,一样好吃 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/热干面.md b/data/C8/cook/dishes/staple/热干面.md new file mode 100644 index 0000000..928431e --- /dev/null +++ b/data/C8/cook/dishes/staple/热干面.md @@ -0,0 +1,50 @@ +# 热干面的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 热干面特有的碱水面 +* 小葱 +* 酸豆角 +* 肉末 +* 蒜水 +* 肉汤汁 +* 萝卜干 +* 芝麻酱 +* 辣椒油 +* 胡椒粉 +* 酱油 +* 食盐 +* 鸡精 + +## 计算 + +每份: + +* 热干面特有的碱水面 (250g) +* 小葱 (10g) +* 酸豆角 (20g) +* 肉末 (30g) +* 蒜水 (30ml) +* 肉汤汁 (30ml) +* 萝卜干 (50g) +* 芝麻酱 (40ml) +* 辣椒油 (0-10ml) +* 胡椒粉(0-10g) +* 酱油(5ml) +* 食盐(3g) +* 鸡精(0-3g) + +## 操作 + +* 水煮沸,并加入碱水面,焯烫 25 秒钟捞起 +* 撒上食盐、鸡精和胡椒粉 +* 芝麻酱用 90ml 水稀释,搅匀,然后加入 +* 加入 5ml 酱油,加入 30ml 肉汤汁和蒜水 +* 加入萝卜干,肉末,酸豆角,葱花 +* 拌均匀后开吃 + +## 附加内容 + +* 辣椒油看个人口味添加 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/煮泡面加蛋.md b/data/C8/cook/dishes/staple/煮泡面加蛋.md new file mode 100644 index 0000000..c0b7c06 --- /dev/null +++ b/data/C8/cook/dishes/staple/煮泡面加蛋.md @@ -0,0 +1,37 @@ +# 煮泡面加蛋的做法 + +煮泡面加蛋是能满足于各种人群的生存基本需求的重要主食,其材料方便易得,做法简单易上手且制作周期极短。 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 泡面 +- 鸡蛋 +- 水 + +## 计算 + +- 单人,能支撑一个成年人不饥饿状态约 3 至 4 小时。 + +每份: + +- 泡面 1 包 +- 水 550ml-1000ml,根据锅的情况。以能完整将泡面浸入其中为准。 +- 鸡蛋 1 个 + +## 操作 + +- 先将水加热至沸腾(火候不做严格要求,使用热水会更快) +- 将取出的面饼放入锅中 +- 将泡面里附带的佐料放入锅中 +- 取出筷子轻微拨动泡面,使佐料充分溶解,面饼充分浸泡受热 +- 盖上锅盖等待约 1 分钟至锅内水再次沸腾 +- 去壳鸡蛋,加入锅中 +- 等待约 3 至 4 分钟,即可 + +## 附加内容 + +- 本指南中的鸡蛋包括但不仅限于:生鸡蛋,熟鸡蛋,卤蛋等 +- 原材料泡面可在楼下便利店购买 +- 可根据个人需要加入佐料,和其他食材包括但不仅限于:火腿肠,生菜,小肉丝,辣条,鱼干,虾仁,鸡腿 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/电饭煲三文鱼炊饭/电饭煲三文鱼炊饭.md b/data/C8/cook/dishes/staple/电饭煲三文鱼炊饭/电饭煲三文鱼炊饭.md new file mode 100644 index 0000000..5546c97 --- /dev/null +++ b/data/C8/cook/dishes/staple/电饭煲三文鱼炊饭/电饭煲三文鱼炊饭.md @@ -0,0 +1,37 @@ +# 电饭煲三文鱼炊饭的做法 + +![电饭煲三文鱼炊饭示例菜成品](./电饭煲三文鱼炊饭.webp) + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 有盐牛油 +- 三文鱼 +- 米 +- 粟米(可选) +- 金菇(可选) +- 冬菇(可选) + +### 工具 + +- 电饭煲 + +## 计算 + +- 米 1 杯 / 人 +- 三文鱼 300g / 人 +- 水 +- 牛油一汤匙 / 人 + +## 操作 + +- 三文鱼去鳞,去骨 +- 金菇、冬菇切碎 +- 洗米三次 +- 把三文鱼、米、牛油放入电饭煲 +- 想口感浓厚一点,可以加多一汤匙牛油 +- 根据电饭煲的刻度放水 +- 把电饭煲調較至煲飯模式,等待大約 30 - 45 分鐘 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/电饭煲三文鱼炊饭/电饭煲三文鱼炊饭.webp b/data/C8/cook/dishes/staple/电饭煲三文鱼炊饭/电饭煲三文鱼炊饭.webp new file mode 100644 index 0000000..30c1d30 --- /dev/null +++ b/data/C8/cook/dishes/staple/电饭煲三文鱼炊饭/电饭煲三文鱼炊饭.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9915bc185429d27e252c8847b89742088e556579490feb72da0eb17d7ea861b9 +size 81664 diff --git a/data/C8/cook/dishes/staple/空气炸锅照烧鸡饭/空气炸锅照烧鸡饭.jpg b/data/C8/cook/dishes/staple/空气炸锅照烧鸡饭/空气炸锅照烧鸡饭.jpg new file mode 100644 index 0000000..bef88c5 --- /dev/null +++ b/data/C8/cook/dishes/staple/空气炸锅照烧鸡饭/空气炸锅照烧鸡饭.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d76a62d253e145506d66bcb9f86f67c362839466146379d06b77568e5fa323e +size 451342 diff --git a/data/C8/cook/dishes/staple/空气炸锅照烧鸡饭/空气炸锅照烧鸡饭.md b/data/C8/cook/dishes/staple/空气炸锅照烧鸡饭/空气炸锅照烧鸡饭.md new file mode 100644 index 0000000..94151c6 --- /dev/null +++ b/data/C8/cook/dishes/staple/空气炸锅照烧鸡饭/空气炸锅照烧鸡饭.md @@ -0,0 +1,39 @@ +# 空气炸锅照烧鸡饭的做法 + +![空气炸锅照烧鸡饭成品](./空气炸锅照烧鸡饭.jpg) + +空气炸锅照烧鸡饭是一道简单易做的菜。是一道既便利又便宜的美食,而且在品尝美味的同时,新手也能完全掌握! + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 丽滋饼干(Ritz crackers) +- 酱油 +- 糖(白沙糖) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人吃。 + +每份: + +- 鸡肉 900g +- 酱油 100-125ml +- 糖 60-65g +- 白醋 30-35ml +- 丽滋饼干(咸味曲奇可替代) 16 个(48g) +- 鸡蛋 2 个 + +## 操作 + +- 将酱油、糖和醋混合在一起,搅匀料汁备用 +- 另一个碗中加入鸡肉、鸡蛋、1/2 料汁和压碎的丽滋饼干。搅拌均匀 +- 空气炸锅用箔纸碗铺底,加入肉饼混合物,将剩余的料汁均匀的倒在上面 +- **350°** 炸**40 分钟**。最好在米饭上食用 +- 在外观*呈金黄酥脆*后出锅,切块盛盘 + +## 附加内容 + +- 操作时,需要注意温度以免烫伤。 +- 参考资料:[库克美食教程](https://cookpad.com/) \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/米饭/rice_regularPot.jpeg b/data/C8/cook/dishes/staple/米饭/rice_regularPot.jpeg new file mode 100644 index 0000000..e0f7b62 --- /dev/null +++ b/data/C8/cook/dishes/staple/米饭/rice_regularPot.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00047100735aeec050c1ada5420e49fc00712e244f522ea04a045fbdb8a9ada1 +size 138421 diff --git a/data/C8/cook/dishes/staple/米饭/煮锅蒸米饭.md b/data/C8/cook/dishes/staple/米饭/煮锅蒸米饭.md new file mode 100644 index 0000000..17878dc --- /dev/null +++ b/data/C8/cook/dishes/staple/米饭/煮锅蒸米饭.md @@ -0,0 +1,30 @@ +# 煮锅蒸米饭的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 北方大米 +- 水 +- 厚底煮锅+严丝合缝的锅盖(制作过程中不会有大量蒸汽泄漏) + +## 计算 + +- 米:100ml-200ml/人 +- 水:米的体积的 2 倍 + +## 操作 + +- 清洗大米 +- 将米和水加入煮锅 +- 大火煮至水沸腾 +- **搅拌底部防止粘黏** +- 盖上锅盖,转**小火**加热 10-15 分钟(根据对软糯程度的喜好),中途切勿打开锅盖 +- 关火,静置 5 分钟 +- Enjoy :) + +![rice_regularPot](./rice_regularPot.jpeg) + +## 附加内容 + +[腐国人研究煮米饭,好想送他们个电饭煲!](https://www.bilibili.com/video/BV1RW411z7r9) \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/米饭/电饭煲蒸米饭.md b/data/C8/cook/dishes/staple/米饭/电饭煲蒸米饭.md new file mode 100644 index 0000000..75f26d8 --- /dev/null +++ b/data/C8/cook/dishes/staple/米饭/电饭煲蒸米饭.md @@ -0,0 +1,38 @@ +# 电饭煲蒸米饭的做法 + +预估烹饪难度:★ + +## 必备原料和工具 + +* 电饭煲 +* 江南米或北方大米 +* 水 + +## 计算 + +* 一般一个人可以食用 100ml-200ml 的米。 + +指尖量水法 (用于精准确定米水量的方法) + +* 江南米,米和水放在电饭煲的容器内,食指触及米时,水量能刚好没过食指的第一个指节又第二个指节 1/4 处(即大约 2.6 厘米)。 +* 北方大米,米和水放在电饭煲的容器内,食指触及米,水量能刚好没过食指的第一个指节(即大约 2 厘米处)。 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +* 清洗米 +* 将米和水一起加入电饭煲中。 +* 连接电饭煲电源,进入加热模式。等待大约 30 分钟。 +* 待电饭煲自动进入保温模式后。 +* 将米在电饭煲中闷 10-15 分钟。 +* 盛出米。 + +## 附加内容 + +- 技术总结 + - 不论什么容器,水的量都是可以使用“指尖量水法”煮出好米饭。 + - 水的多少是能够严重影响一碗好米饭的口感。 + - 南方一般食用江南米,北方一般食用北方大米,江南米会比较细长,而北方大米会比较短且圆。 + - 米饭不同品种的米,不同的水量会极度影响口感。 +- 更多信息请参考使用的电饭煲的说明书。 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/老友猪肉粉/老友猪肉粉.jpg b/data/C8/cook/dishes/staple/老友猪肉粉/老友猪肉粉.jpg new file mode 100644 index 0000000..05ba3be --- /dev/null +++ b/data/C8/cook/dishes/staple/老友猪肉粉/老友猪肉粉.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65993209bb99dcb7f10ba75c124433cda5617545400f7d4398e0e5750f4c9cbe +size 482340 diff --git a/data/C8/cook/dishes/staple/老友猪肉粉/老友猪肉粉.md b/data/C8/cook/dishes/staple/老友猪肉粉/老友猪肉粉.md new file mode 100644 index 0000000..75f9e4a --- /dev/null +++ b/data/C8/cook/dishes/staple/老友猪肉粉/老友猪肉粉.md @@ -0,0 +1,54 @@ +# 老友猪肉粉的做法 + +![示例菜成品](老友猪肉粉.jpg) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 米粉 +- 猪肉 +- 酸笋 +- 剁椒 +- 豆豉 +- 大蒜 +- 料酒 +- 生抽 +- 白糖 +- 米醋 +- 盐 +- 油 +- 生粉 +- 胡椒粉 + +## 计算 + +每份: + +- 米粉(250g 记得 50 度的温水泡半小时) +- 猪肉(50g) +- 酸笋(50g) +- 剁椒(15g 辣椒剁完后, 个人需求适当放。 ) +- 豆豉(30g) +- 大蒜(10g) +- 料酒(10-20ml) +- 生抽(15ml) +- 白糖(5g 如果不喜欢糖,可以考虑不放) +- 米醋(5ml) +- 盐(5ml) +- 油(15ml) +- 生粉(15ml) +- 胡椒粉(10ml) + +## 操作 + +- 全部猪肉用料酒、盐、生抽、生粉、胡椒粉倒在一个碗里调味,备用 +- 热锅不放油,下全部酸笋把水份炒干,炒干的酸笋中间留点空间 +- 放入 10ml - 15ml 食用油与全部大蒜、 剁椒、 豆豉到炒干的酸笋中间到炒干的酸笋中间,全部推到中间炒出香味 +- 放入全部调味好的猪肉,持续放入 10ml 生抽炒一分钟 +- 放入 5ml 米醋、 10ml 生抽、450ml 清水一起煮开 +- 水煮开后,放入温水泡好的米粉,继续煮 3 分钟就可以盛盘 + +## 附加内容 + +- 记得米粉必须是泡过的才好吃,没有泡过的话是很难吃的! \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/老干妈拌面.md b/data/C8/cook/dishes/staple/老干妈拌面.md new file mode 100644 index 0000000..4b34cbe --- /dev/null +++ b/data/C8/cook/dishes/staple/老干妈拌面.md @@ -0,0 +1,33 @@ +# 老干妈拌面的做法 + +预估烹饪难度:★ + +## 必备原料和工具 + +* 面 +* 老干妈 +* 酱油 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +* 水 1 升 +* 面量 120 克 * 份数 +* 老干妈 15ml * 份数 +* 酱油 5ml * 份数 + +## 操作 + +* 将水倒入锅中并煮沸 +* 将面均匀放入锅中 +* 在煮的过程注意搅拌,避免面粘成一坨 +* 当用筷子挑起一根面且该面能自然地从筷子上滑落时再等 30 秒关火 +* 将面夹入碗中 +* 按照上面的计量放入老干妈和酱油 +* 用筷子将碗里的面、老干妈、酱油拌均匀 +* 吃 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/肉蛋盖饭.md b/data/C8/cook/dishes/staple/肉蛋盖饭.md new file mode 100644 index 0000000..3ed2951 --- /dev/null +++ b/data/C8/cook/dishes/staple/肉蛋盖饭.md @@ -0,0 +1,51 @@ +# 肉蛋盖饭的做法 + +肉蛋盖饭适合于单人简易晚餐,烹饪大约需要十五分钟。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 米饭 +- 鸡蛋 +- 肉馅 +- 老抽 +- 生抽 +- 醋 +- 红葱油(可选) +- 葱 +- 油 +- 糖 + +## 计算 + +一份为一人餐,多人餐请等比例增加,但需要考虑锅的容量。 + +一份: + +- 米饭 240g +- 鸡蛋 4 个 +- 肉馅 300g +- 老抽 10ml +- 生抽 25ml +- 醋 20ml +- 红葱油可选 10g +- 葱 10g +- 油 30ml +- 糖 15g + +## 操作 + +- 煮好米饭,通常使用买米赠送的量杯,一杯米 240g +- 锅中放油 30ml +- 放入肉馅,调中火煎至两面微焦 +- 将鸡蛋打入锅中,不要打散,盖上锅盖 +- 调一个碗汁,碗中放入计算中的对应数量的老抽,生抽,醋,糖,红葱油,搅拌均匀 +- 打开锅盖,将碗汁倒入锅中,等待三分钟 +- 关火,将肉蛋盖到米饭上 +- 安全检查,开始食用盖饭 + +## 附加内容 + +- 如果喜欢甜口可以增加 10g 糖 +- 请务必保证做完饭后关掉燃气设备以免发生危险 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/茄子肉煎饼/1茄片肉片.jpg b/data/C8/cook/dishes/staple/茄子肉煎饼/1茄片肉片.jpg new file mode 100644 index 0000000..583ac9d --- /dev/null +++ b/data/C8/cook/dishes/staple/茄子肉煎饼/1茄片肉片.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:06e6cf3d717452739c56fef0853d940bf3fc208d86f385a50bb17f81e5025e26 +size 600178 diff --git a/data/C8/cook/dishes/staple/茄子肉煎饼/2米粉250g.jpg b/data/C8/cook/dishes/staple/茄子肉煎饼/2米粉250g.jpg new file mode 100644 index 0000000..646d76b --- /dev/null +++ b/data/C8/cook/dishes/staple/茄子肉煎饼/2米粉250g.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:342783f2ff0f04c8af99b17dcfd1dc40c2cdeb4b74a821a34ec554db6b23d100 +size 537767 diff --git a/data/C8/cook/dishes/staple/茄子肉煎饼/3米粉面粉鸡蛋.jpg b/data/C8/cook/dishes/staple/茄子肉煎饼/3米粉面粉鸡蛋.jpg new file mode 100644 index 0000000..0ecd95f --- /dev/null +++ b/data/C8/cook/dishes/staple/茄子肉煎饼/3米粉面粉鸡蛋.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ab28b3242958743e04b70e9acea13c13916d0e7347cd12daa3e4fef49817f24 +size 725103 diff --git a/data/C8/cook/dishes/staple/茄子肉煎饼/4混合.jpg b/data/C8/cook/dishes/staple/茄子肉煎饼/4混合.jpg new file mode 100644 index 0000000..34f8110 --- /dev/null +++ b/data/C8/cook/dishes/staple/茄子肉煎饼/4混合.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47871a0e4bd03efa5c68f4cb7364f0a72f10095ba4a8db6b679d47fe2348edd7 +size 577383 diff --git a/data/C8/cook/dishes/staple/茄子肉煎饼/5起锅烧油.jpg b/data/C8/cook/dishes/staple/茄子肉煎饼/5起锅烧油.jpg new file mode 100644 index 0000000..af9b7aa --- /dev/null +++ b/data/C8/cook/dishes/staple/茄子肉煎饼/5起锅烧油.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e234eda17cc4fcca67e09e5633020f68f7d137b3bc48570a9a9024f511ad0564 +size 776917 diff --git a/data/C8/cook/dishes/staple/茄子肉煎饼/6开始煎.jpg b/data/C8/cook/dishes/staple/茄子肉煎饼/6开始煎.jpg new file mode 100644 index 0000000..d90b1e0 --- /dev/null +++ b/data/C8/cook/dishes/staple/茄子肉煎饼/6开始煎.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13e2daff216e2e9b94d8fc6b4c84c70832c831f7fe6d5242a021b2e0e0e4fdcc +size 778712 diff --git a/data/C8/cook/dishes/staple/茄子肉煎饼/7撒盐准备起锅.jpg b/data/C8/cook/dishes/staple/茄子肉煎饼/7撒盐准备起锅.jpg new file mode 100644 index 0000000..3f25a3d --- /dev/null +++ b/data/C8/cook/dishes/staple/茄子肉煎饼/7撒盐准备起锅.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35604453c43d1574f8e40fda32e0580f3fffcf10cdb88275081f55a264e97a3e +size 842831 diff --git a/data/C8/cook/dishes/staple/茄子肉煎饼/茄子肉煎饼.jpg b/data/C8/cook/dishes/staple/茄子肉煎饼/茄子肉煎饼.jpg new file mode 100644 index 0000000..ce8ec3c --- /dev/null +++ b/data/C8/cook/dishes/staple/茄子肉煎饼/茄子肉煎饼.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:203b2885c4a8d6dd4d730c1b1688bc4b3d00abec9dc2cfc58ca5c57534451d68 +size 848999 diff --git a/data/C8/cook/dishes/staple/茄子肉煎饼/茄子肉煎饼.md b/data/C8/cook/dishes/staple/茄子肉煎饼/茄子肉煎饼.md new file mode 100644 index 0000000..42f41b5 --- /dev/null +++ b/data/C8/cook/dishes/staple/茄子肉煎饼/茄子肉煎饼.md @@ -0,0 +1,63 @@ +# 茄子肉煎饼的做法 + +![茄子肉煎饼成品](./茄子肉煎饼.jpg) + +茄子肉煎饼是一道简单易做的饼类主食。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 米粉(指用大米研磨成的粉) +* 小麦粉 +* 鸡蛋 +* 煮熟的腊肉 +* 茄子(买长条状的,越圆越好) +* 食用油 +* 食盐 + +## 计算 + +制作 1 份,1 份正好够 2 个人吃。 + +每份: + +* 米粉 250g +* 面粉 50g +* 鸡蛋 1 个 +* 煮熟的腊肉 100g +* 茄子 1 根(约 10-15cm 长) +* 食用油 10-15ml +* 食盐 1-2g + +## 操作 + +* 将茄子去皮后切成片,将腊肉切成片,备用 + +![茄片肉片](./1茄片肉片.jpg) + +* 依次向盆中加入 250g 米粉(大米研磨成的粉)、50g 面粉和 1 个鸡蛋 + +![米粉250g](./2米粉250g.jpg) + +![米粉面粉鸡蛋](./3米粉面粉鸡蛋.jpg) + +* 边用筷子搅拌,边加入清水(**清水用于调节粘稠度**),使米粉、面粉、鸡蛋混合成面糊,当面糊能够附着在茄片、肉片上而不掉落时停止加水,而后将所有茄片和肉片放入面糊中,用面糊充分包裹 + +![混合](./4混合.jpg) + +* 平底锅加入食用油**10-30ml**,开小火 + +![起锅烧油](./5起锅烧油.jpg) + +* 用筷子或勺子把裹了面糊的茄片、肉片放入锅中,先煎至两面金黄,再煎**3-6分钟**(**煎的过程中,食用油会变少,可再添加食用油**) + +![开始煎](./6开始煎.jpg) + +* 撒盐,翻炒均匀,起锅装盘 + +![撒盐准备起锅](./7撒盐准备起锅.jpg) + +## 附加内容 + +* 用小火煎 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/葱油拌面.md b/data/C8/cook/dishes/staple/葱油拌面.md new file mode 100644 index 0000000..4ed8b20 --- /dev/null +++ b/data/C8/cook/dishes/staple/葱油拌面.md @@ -0,0 +1,59 @@ +# 葱油拌面的做法 + +葱油拌面是一道经典的上海家常面点。做法简单,以其独特的葱油香味而闻名。富含碳水化合物和脂肪,能够快速补充能量。一般初学者只需要 20 分钟即可完成。是一道非常适合加班后的简单晚餐选择。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 干面条 +- 小葱 +- 生抽 +- 老抽 +- 白糖 + +## 计算 + +葱油酱汁可以一次制作多份的量,分次使用。以下提供制作葱油酱汁的基础量,以及每份面条所需的葱油酱汁量。 + +葱油酱汁基础量 (约够 3-4 份使用): + +- 小葱 100 g +- 食用油 100 ml +- 生抽 60 ml +- 老抽 20 ml +- 白糖 15 g + +每份面条: + +- 干面条 80 g (约相当于 150 g 湿面条) +- 葱油酱汁 15 ml + +## 操作 + +### 制作葱油酱汁 + +- 将 小葱 洗净,切成长段(约 5-7 cm)。葱白和葱绿可以分开。 +- 锅中加入 100 ml 食用油,中火烧热。先放入葱白段,煸炒至微黄。 +- 加入葱绿段,转小火,继续煸炒。 +- 保持小火,耐心煸炒约 **15-20 分钟**,直至葱段变得焦黄酥脆。 +- 将焦黄的葱段捞出(葱油保留在锅中)。 +- 在锅中的葱油中,加入 60 ml 生抽,20 ml 老抽,15 g 白糖。小火加热并搅拌,约 **1 分钟**,至糖溶解,酱汁混合均匀。立即关火。将制作好的葱油酱汁倒入容器中,放凉后密封保存。 + +### 煮面条 (按份操作) + +- 取 80 g 干面条。 +- 锅中加入 1000 ml 饮用水,大火烧开。 +- 放入 面条,根据面条包装说明,煮至熟透(通常 **3-8 分钟**,以包装说明为准)。 +- 将 煮好的 面条 捞出,沥干水分,放入碗中。 + +### 混合拌面 (按份操作) + +- 在装有 面条 的碗中,加入 15 ml 之前做好的 葱油酱汁。 +- 可以加入之前炸好的葱段(可选)。 +- 用 筷子 快速搅拌均匀,即可食用。 + +## 附加内容 + +- 炸葱油时,火一定要小,要有耐心,才能将葱的香味充分炸出。 +- 制作好的葱油酱汁可以冷藏保存一段时间,下次吃面时直接取用。 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/蒸卤面.md b/data/C8/cook/dishes/staple/蒸卤面.md new file mode 100644 index 0000000..0130133 --- /dev/null +++ b/data/C8/cook/dishes/staple/蒸卤面.md @@ -0,0 +1,74 @@ +# 蒸卤面的做法 + +蒸卤面是一道豫南的非常经典的家常菜,荤素搭档,简单易学。一般初学者只需要一个小时即可完成。 + +NOTE:本次标准为豫南口味,可能和其他地方不太一样,食无标准,兼容并包,好吃即可。 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 猪五花肉 +- 芹菜 +- 鲜面条(要求必须是**最细**的,如果附近菜市场没有,请参考制作[焖面](https://note.youdao.com/)) +- 葱,姜,蒜 +- 食用油(花生油最佳) +- 生抽,老抽,料酒,盐,五香粉 +- 蒸锅,需带笼屉 +- 炒锅 + +下列原料供有一定烹饪基础或者学有余力的同学选配 + +- 花椒 +- 干红椒 +- 青椒 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +- 芹菜 两根中等大小的芹菜 +- 五花肉 350g +- 面条 500g +- 大葱 10cm +- 大蒜 5 瓣 +- 姜片 20g +- 青椒 2 个 +- 干红椒 3 个 +- 花椒 20 粒 +- 盐 10g +- 五香粉 5g +- 生抽 15ml +- 老抽 10ml + +## 操作 + +### 备料 + +- 猪肉去皮,切成 `2 cm * 6 cm * 0.5 cm` 薄片备用 +- 芹菜去叶,去掉根部 2cm,然后从中对半切开,切成 2cm 段备用 +- 大蒜去皮切粒备用,葱切 0.2cm 薄片备用,姜切细丝备用 + +### 预制 + +- 炒锅烧热至冒烟后,倒入 3ml 食用油滑锅后倒出底油 +- 重新加入食用油,加入肉片,葱姜蒜,干红椒,炒 1 分钟,注意不停匀速翻炒 +- 加入料酒,生抽,老抽,再翻炒 1 分钟 +- 续入 500ml 热水。盖上锅盖炖煮 3 分钟 +- 将芹菜,青椒倒入锅中,加入盐,五香粉调味,盖上锅盖继续炖煮煮 3 分钟 后关火 +- 蒸锅加入 1000ml 水,烧开上汽后,将面条摊平在笼屉上放入锅中,蒸 15 分钟 +- 面条蒸熟后取出,用筷子和无情铁手扒拉散开在案板上,室温冷却 + +### 再加工 + +- 将面条放入菜锅中搅拌,搅拌方式为一手持筷,一手持锅铲将菜翻至面条上面,以面条以全部均匀上色为搅拌完成标准 +- 将搅拌后的面条再次放在整屉上,再次蒸 10 分钟 关火 + +## 附加内容 + +- 技术总结 + - 切割猪肉时,可以让菜市场摊贩帮忙,根据经验,请求时机把握在已切割后未付款之前成功率最高 + - 首次做饭时可以提前备好料防止手忙脚乱,后续熟练后可以并发执行 + - 两次蒸面条时,都要尽量的弄散开,可以避免蒸好后团在一起。面条太长时可以拽断,方便后续搅拌与盛取 + - 取出蒸好的面条时尽量动作轻一些,避免蒸屉翻到面条触水 + - 佐餐时啤酒更配呦! \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/蛋包饭.md b/data/C8/cook/dishes/staple/蛋包饭.md new file mode 100644 index 0000000..9136770 --- /dev/null +++ b/data/C8/cook/dishes/staple/蛋包饭.md @@ -0,0 +1,54 @@ +# 蛋包饭的做法 + +蛋包饭是一道日式经典家常菜,由炒饭和嫩滑鸡蛋组成,口感丰富,色香味俱全。富含蛋白质、碳水和维生素,是非常适合早餐或正餐的选择。预估制作时间为 25 分钟。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡蛋(建议使用土鸡蛋,口感更香) +- 洋葱 +- 胡萝卜 +- 玉米粒 +- 青豆(可选) +- 火腿肠或鸡胸肉 +- 米饭 +- 番茄酱 +- 食用油(建议使用植物油) +- 牛奶(可选,让蛋皮更嫩) + +## 计算 + +每次制作前需要确定计划做几份。一份适合 1 人食用。 + +每份: + +- 鸡蛋 2 个 +- 洋葱 30g +- 胡萝卜 30g +- 火腿肠或鸡胸肉 50g +- 玉米粒和青豆总共 30g +- 米饭 200g +- 番茄酱 20ml +- 食用油 15ml +- 牛奶 10ml(与鸡蛋混合) + +## 操作 + +- 洋葱、胡萝卜、火腿肠或鸡胸肉切成小丁,备用 +- 热锅,锅中倒入 10ml 食用油,等待 10 秒加热 +- 先放入洋葱丁翻炒 1 分钟,出香味后加入胡萝卜、玉米粒、青豆继续翻炒 2 分钟 +- 加入火腿肠或鸡胸肉丁,炒至变色 +- 加入米饭炒散后,加入番茄酱 20ml,翻炒均匀,炒饭完成,盛出备用 +- 鸡蛋打散,加入 10ml 牛奶搅匀 +- 锅中放入 5ml 食用油,倒入蛋液,轻晃锅底让蛋液均匀铺满锅面 +- 用小火加热,待蛋液表面半熟状态时,将炒饭放入蛋液中央 +- 用铲子将蛋皮折叠包住米饭,形成椭圆形状 +- 用锅铲轻轻推至盘中,整理外形,可在表面挤上少量番茄酱装饰 + +## 附加内容 + +- 炒饭用隔夜饭不易粘锅,口感更好。 +- 打蛋时加入牛奶可以让蛋皮更加嫩滑。 +- 操作蛋皮时火力需小,避免底部焦糊。 +- 如果不擅长包裹造型,也可以直接将炒饭铺盘后盖上蛋皮。 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/蛋炒饭.md b/data/C8/cook/dishes/staple/蛋炒饭.md new file mode 100644 index 0000000..50285b9 --- /dev/null +++ b/data/C8/cook/dishes/staple/蛋炒饭.md @@ -0,0 +1,60 @@ +# 蛋炒饭的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 冷饭 +* 鸡蛋 +* 火腿 +* 黄瓜 +* 胡萝卜 +* 油 +* 盐 +* 胡椒粉 +* 生抽 +* 香葱 +* 灯影牛肉丝/午餐肉/腊肠/卤肉...等熟肉(备选) + +准备时,米饭可以参考[米饭的做法](./米饭/电饭煲蒸米饭.md)。 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1-2 个人食用 + +总量: + +* 冷饭(份数*500ml) +* 鸡蛋 (份数*1.5 // 1 向下取整) +* 火腿(份数*2 个) +* 黄瓜(可选,份数*30g) +* 胡萝卜(可选,份数*30g) +* 油(份数*12ml) +* 盐(份数\*4g - 份数*6g) +* 胡椒粉(份数*8g) +* 香葱(份数*1 颗) +* 生抽(份数*10ml) + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +* 米饭提前用铲子铲成小块 +* 火腿肠、胡萝卜、黄瓜等根据需求切片或者块状 +* 如果家里有熟肉 准备好味道更佳 +* 将蛋白,蛋黄分开,分别打入一个大碗里,各自搅匀。注意,不要在这一步加盐。 +* 大火热锅,待锅里冒烟放入食用油,放入蛋白,待主体凝固后盛出备用。 +* 如果油够,则直接放入蛋黄,如果油不够则放入食用油并等其升温到大火热锅 +* 待主体凝固后,将火调至中小火,倒入火腿肠、熟肉,胡萝卜、黄瓜等备料、翻炒 10 秒钟(到爆香) +* 重新倒入蛋白,翻炒 5s 钟,迅速倒入米饭大火翻炒,为的就是每一粒饭都裹上鸡蛋。 +* 翻炒过程中将米饭的块状捣碎、这一步过程会比较长、待米饭全部捣碎再翻炒均匀即可 +* 调至小火、加盐、胡椒粉、生抽 +* 进一步翻炒均匀,能看到一些米饭在锅里有“跳起来”的时候其实就已经差不多了 +* 最后倒入香葱再翻炒 10s +* 关火、盛入碗中 + +## 附加内容 + +* 技术总结 + - 使用隔夜的冷饭炒饭最佳,没有冷饭的同学也可以现煮(可以使用冰箱立马给米饭降温),不过要做到“粒粒分明”的口感就需要炒更久。 + - 炒饭要做到“粒粒分明”其实就是要将饭炒干。为什么要用隔夜的冷饭是因为隔夜已经流失了一定的水分。 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/螺蛳粉.md b/data/C8/cook/dishes/staple/螺蛳粉.md new file mode 100644 index 0000000..8c582ae --- /dev/null +++ b/data/C8/cook/dishes/staple/螺蛳粉.md @@ -0,0 +1,48 @@ +# 螺蛳粉的做法 + +正宗的螺蛳粉是不臭的! + +预估烹饪难度:★ + +## 必备原料和工具 + +> 出于家常菜考虑,从螺蛳,酸笋等工序开始制作螺蛳粉并不现实,因此本食谱基于袋装螺蛳粉实现。 + +### 原料 + +- 袋装螺蛳粉一包,其中应该包含: + - 米粉 + - 螺蛳肉包(可能放在配料包中) + - 汤料包 + - 酸笋包、花生包、豆皮包、木耳包等配料包 + - 醋包、辣椒油等调味包 + +### 工具 + +- 煮锅 + +- 电磁炉/灶台 + +- 筷子一双 + +## 计算 + +- 根据个人经验,一包袋装螺蛳粉足够一人一餐食(虽然看着很大包) +- 水 1L + +## 操作 + +- 锅中加水,将水烧开 +- 下米粉,煮 3-5 分钟,期间用筷子搅拌,防止米粉粘在一起 +- 下汤料包,按个人口味添加 +- 下一部分配料包,如木耳,花生,螺蛳(这部分配料需要煮一会才入味) +- 下调味包,按个人口味添加 +- 搅拌后捞出,放入碗中 +- 下剩下的配料包,如酸笋,豆皮(这部分配料不适合被汤泡太久) +- 享用美食 + +## 附加内容 + +- 如果想要更有嚼劲的粉,可以缩短第二步煮粉的时间 +- 如果想在螺蛳粉中添加炸蛋,请参考炸蛋的教程 +- 配料的选择请依照个人口味 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/food.jpg b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/food.jpg new file mode 100644 index 0000000..6cef5b8 --- /dev/null +++ b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/food.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8bcb1cee7a8eca1582b55ef0a758a347e0204d844e90a2dd9e77c2d44c1b43f4 +size 139657 diff --git a/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/fryEgg.jpg b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/fryEgg.jpg new file mode 100644 index 0000000..0a0ca75 --- /dev/null +++ b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/fryEgg.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1beadffd0179aea6bc1271d24980cdfc688a785bdf86f2e1a67e9b2ccc460586 +size 26908 diff --git a/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/pretreatFood.jpg b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/pretreatFood.jpg new file mode 100644 index 0000000..c0b7724 --- /dev/null +++ b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/pretreatFood.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8227fa95c101f817007409f9357fa7adfe507a513df2426025399756a493b165 +size 189603 diff --git a/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/tomato.jpg b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/tomato.jpg new file mode 100644 index 0000000..ad1bceb --- /dev/null +++ b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/tomato.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddd37080a214ce4af9526a22ad4fd82726ff5fac610093e639876a8142475717 +size 151487 diff --git a/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/tomatoNoodle.jpg b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/tomatoNoodle.jpg new file mode 100644 index 0000000..59ddaf2 --- /dev/null +++ b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/tomatoNoodle.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d69ab5423a6bac61311f93f6b28648ef11935e376d20fa4dda98d0a6ef1854af +size 138030 diff --git a/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/西红柿鸡蛋挂面.md b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/西红柿鸡蛋挂面.md new file mode 100644 index 0000000..55be131 --- /dev/null +++ b/data/C8/cook/dishes/staple/西红柿鸡蛋挂面/西红柿鸡蛋挂面.md @@ -0,0 +1,88 @@ +# 西红柿鸡蛋挂面的做法 + +挂面太多怎么办?只煮个白水面味道难以下咽怎么办?简单的食材煮个美味的面条怎么操作? +西红柿鸡蛋挂面只需简单的食材,快速的操作,不多的厨具,解决**不想麻烦**、**挂面太多**、**食材简单**的所有烦恼 +此处更要鸣谢 my mother 的在线指导:v: +简单好做,开始吧! +制作时间:20 分钟 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 挂面或者鲜面条也行 +- 西红柿一个 +- 盐 +- 鸡蛋 +- 葱 +- 酱油、蚝油或者鸡精 +- 白砂糖(中和西红柿的酸味,西红柿如果不酸就不用加) +- 青椒(非线椒) +- 香油 + +![食材](./food.jpg) + +## 计算 + +每次制作前需要确定计划做几份。如下分量正好够 1 个人食用 + +总量: + +- 挂面 1 把(根据食量来)50-100g +- 西红柿 1 个大概 200g 吧。 +- 鸡蛋 1~2 个 +- 盐 5g +- 蚝油 5g 或鸡精 3g +- 白砂糖 2g +- 酱油 5-8g +- 食用油的用量为 20g +- 香油 5g + +## 操作 + +### 食材的预处理 + +食材预处理很重要,无论做什么菜提前进行处理,在菜肴制作过程中才不会慌乱,并且制作是个很舒心的过程,这……可能就是为什么后厨需要一个单独的打荷岗位吧 + +- 小葱洗净并切成葱花 +- 西红柿切块儿,如果不太会切建议先百度一下~ +- 青椒切成菱形块 +- 生鸡蛋打入一个小碗并打散,如果鸡蛋有点腥味可以加 2g 白醋去腥 + +![食材预处理](./pretreatFood.jpg) + +### 鸡蛋的预处理 + +- 起锅烧热,倒入 15~20g 食用油,鸡蛋炒嫩滑就得多一点油,同时为后面煸炒西红柿留一些底油 +- 待油温到七成热时(手掌隔大概 10cm,能感觉到热),倒入蛋液快速划散 +- 鸡蛋滑到凝固后,一点不会有蛋液了后倒入小碗备用,此处留一些底油 + +![炒熟的鸡蛋](./fryEgg.jpg) +> 鸡蛋没有拍照用网图来代替吧 + +### 制作西红柿鸡蛋臊子 + +- 锅中留底油后先加入葱白、蒜末炒香 +- 加入西红柿块、青椒,待西红柿炒出一点汁水 +- 此时速速加入 5g 酱油和 2g 白砂糖 +- 翻炒十几秒后加入一碗清水(刚刚好即将没过西红柿即可) +- 煮沸后加入炒好的鸡蛋,加入蚝油 5g 或者 2g 鸡精用于提鲜 +- 中小火收汁,期间要搅拌防止粘锅,收汁到下图后加一点葱花(剩下的葱绿部分)和香油(不加也可以),臊子制作完成 + +![西红柿鸡蛋臊子](./tomato.jpg) + +### 最后煮面条 + +- 可以不用洗锅,直接加清水 500ml +- 煮沸加入挂面,挂面煮软后加入 100ml 清水 +- 再次煮沸后,若面条飘起来了,再加入 100ml 清水 +- 煮沸后看面条两侧是否呈透明状,透明状则熟了 +- 捞面到臊子碗中,拌面即可啦~ + +![西红柿鸡蛋面](./tomatoNoodle.jpg) + +## 附加内容 + +- 鸡蛋蛋液中可以加入 2g 黑胡椒味道更好 +- 熬臊子过程中加入 2g 白胡椒粉提升香辛口味 +- 煮面条如果一次性煮熟也可以,多次加水是为了让面条口感劲道,面条不粘黏,技巧在于煮沸就加冷水,循环往复两三次即可 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/豆角焖面/豆角焖面.md b/data/C8/cook/dishes/staple/豆角焖面/豆角焖面.md new file mode 100644 index 0000000..5dd32e8 --- /dev/null +++ b/data/C8/cook/dishes/staple/豆角焖面/豆角焖面.md @@ -0,0 +1,88 @@ +# 豆角焖面的做法 + +豆角焖面是一道懒人美食,操作简单,方便美味。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 鲜面条(韭叶 or 二细<解释见最下方 关于面条粗细区别一栏) +* 肉(最好为五花肉) +* 盐 +* 豆角 +* 鸡精 +* 耗油 +* 味精 +* 十三香 +* 生抽 +* 老抽 +* 葱 +* 蒜头 +* 姜 +* 热水 +* 菜刀 + +## 计算 + +下面的量是仅仅 1 够一个人一餐的主食的量!请针对实际调整用料的量! + +* 鲜面条 300g。 +* 肉 100g。 +* 豆角 150g。 +* 盐的用量为:2g。 +* 食用油的用量为 10 - 18 ml。 +* 鸡精的用量为:2g。 +* 生抽的用量为:10ml。 +* 耗油的用量为:5g。 +* 十三香的用量为:1g。 +* 老抽的用量为:5ml。 +* 味精的用量为:1g。 +* 热水的用量为:150ml。 +* 葱 10g。 +* 姜 5g。 +* 蒜 10g。 + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +### 准备动作 + +* 将豆角切成 5cm - 6cm 的小段。 +* 将葱切成 1cm - 2cm 小段。 +* 将姜切成 1mm x 1mm x 3cm 的长条 +* 将蒜放在砧板上拍碎,切成 1mm 的粒度。 +* 将五花肉切成 2mm 厚度的肉片。 + +* 首先将锅烧热,烧去锅内全部水汽,手放过内距离锅底 10cm 处,感觉明显有些许烤手。 +* 加入上述定量的食用油,手持锅柄,离灶 5cm 处,摇晃锅,使食用油充分挂满锅的三分之二(自下而上)。 + +> ps:不粘锅请忽略上述操作,静待3-5秒油热即可。 + +* 放入全部的姜和全部的葱段,翻炒爆香 5 秒(注意!此时有油飞溅的危险,建议带上手套或做好防护措施)。 +* 放入全部的肉片,放入以后不着急饭锅,静置 5 秒后,再翻炒,使所有的肉都裹满食用油。 +* 不断翻炒肉片,待到全部肉片都已经变色,沿锅边均匀淋如准备好的生抽,翻炒均匀。 +* 依次加入准备好的盐、老抽、耗油、十三香、鸡精以及全部准备好的豆角,翻炒 2 分钟。 +* 加入准备好的热水。 +* 水开使用勺子舀出锅内 2 分之一菜汤(注意!不要将菜舀出)。 +* 将所有面条平铺在菜的上方。 +* 盖上锅盖,中火焖 5 分钟。 +* 打开锅盖,将舀出的菜汤使用勺子,以每次一勺的量,均匀撒在面条上。 +* 盖上锅盖,中火焖 3 分钟。 +* 打开锅盖,将所有的蒜、味精均匀撒入。 + +> ps:此时锅内可能还有水,如果想吃湿一点的请关火,否则不用关火。 + +* 使用筷子不断翻炒,将菜与肉均匀搅拌。 +* 关火 + +## 附加内容 + +### 面条的粗细区别 + +* 毛细(顾名思义,就像头发,其实就有点像细粉丝那样细) +* 细(这个比毛细粗点,跟香头一样) +* 二细(有点像一般的炒面条那样粗) +* 三细(比二细稍微粗点,吃起来像吃粗粉条,不过面如果拉的比较劲道的话,这个嚼起来感觉很有味) +* 韭叶(这鸡就像韭菜叶子一样宽) +* 大宽(就像吃麻辣烫的那个宽粉一样) \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/酱拌荞麦面/1.jpeg b/data/C8/cook/dishes/staple/酱拌荞麦面/1.jpeg new file mode 100644 index 0000000..39e3292 --- /dev/null +++ b/data/C8/cook/dishes/staple/酱拌荞麦面/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa57a2b64265cb28abaedb4e7fa2a96838d00725f24aea294f1d3efd1e250b17 +size 190513 diff --git a/data/C8/cook/dishes/staple/酱拌荞麦面/2.jpeg b/data/C8/cook/dishes/staple/酱拌荞麦面/2.jpeg new file mode 100644 index 0000000..0fdc816 --- /dev/null +++ b/data/C8/cook/dishes/staple/酱拌荞麦面/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0af0c775d12c9ffaeca16bd5e4c1b0ed9abf37e91f337a6f52c22422cde2fad +size 198901 diff --git a/data/C8/cook/dishes/staple/酱拌荞麦面/酱拌荞麦面.md b/data/C8/cook/dishes/staple/酱拌荞麦面/酱拌荞麦面.md new file mode 100644 index 0000000..d436e75 --- /dev/null +++ b/data/C8/cook/dishes/staple/酱拌荞麦面/酱拌荞麦面.md @@ -0,0 +1,37 @@ +# 酱拌荞麦面的做法 + +酱拌荞麦面营养健康、酸甜可口 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 荞麦面 +* 黄瓜 +* 红萝卜 +* 老干妈 + +## 计算 + +每份: + +* 荞麦面 100 g +* 黄瓜 0.5 根 +* 红萝卜 0.5 根 +* 老干妈 20 ml + +## 操作 + +* 荞麦面下冷水煮熟,8-10 分钟 后捞出沥干备用 +* 黄瓜、萝卜 切成小条 +* 将荞麦面、黄瓜、萝卜放入盘子,放上老干妈,搅拌 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) + +## 附加内容 + +* 荞麦面沥干后可以放冰箱冰镇后口感更佳 +* 配料可以根据个人喜好选择其他,例如虾仁、肉沫等 +* 酱料可以根据个人喜欢选择其他,例如花生酱、芝麻酱等 +* 荞麦面跟其他面条热量几乎一致,所以不适合作为减脂的主食 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/酸辣蕨根粉.md b/data/C8/cook/dishes/staple/酸辣蕨根粉.md new file mode 100644 index 0000000..d60ac17 --- /dev/null +++ b/data/C8/cook/dishes/staple/酸辣蕨根粉.md @@ -0,0 +1,58 @@ +# 酸辣蕨根粉的做法 + +酸辣蕨根粉是一道适合初学者的简单易做的凉菜,可做主食,以酸辣口为主,预计 10 分钟可做完。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 蕨根粉 +* 油泼辣子 +* 酱油 +* 香醋 +* 小米辣(可选) +* 蒜(可选) +* 葱(可选) +* 盐 +* 糖 +* 一口有点深度的锅 + +## 计算 + +每份: + +* 酱油 : 醋 : 油泼辣子 = 3 : 2 : 2 (酱料具体量根据蕨根粉多少决定,这个比例仅为保证口味的方向不出错) +* 如果觉得酱料较为清淡,可以加入 2 至 5 克盐 +* 如果想要酱料鲜一些,可以加入 2 克糖 + +## 操作 + +### 蕨根粉的煮制 + +* 锅中加入约为深度 3/5 的水,烧开 +* 水沸腾后加入蕨根粉,中小火煮 8 分钟 +* 出锅 + +### 酱料的调制 + +* 根据配比,加入酱油、醋、油泼辣子 +* 用筷子蘸取,尝一口 +* 如果觉得此时酱油味稍浓,加入准备好的盐 +* 如果觉得此时不够鲜,加入准备好的糖 +* 充分搅拌至大部分颗粒状调料溶解 + +### 装盘与完成步骤 + +* 取一个碗 +* 加入上一步调制的酱料 +* 将蕨根粉过冷水后放入酱料中 +* 充分搅拌 +* 将准备的葱、蒜、小米辣切碎后撒在粉上 +* 完成啦(。・∀・)ノ゙ + +## 附加内容 + +* 葱姜蒜为附加调料,加入可以增添风味,不加也并无大碍 +* 糖和盐根据个人口味,需要加入的具体量不同,请酌情加入 +* 建议使用碗作为最终装盘餐具,因为使用盘子会使吃粉变得困难一些 +* 整体口味偏辣,如果不能吃辣请减少油泼辣子的量并且不加入小米辣 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/醪糟小汤圆.md b/data/C8/cook/dishes/staple/醪糟小汤圆.md new file mode 100644 index 0000000..1914cbc --- /dev/null +++ b/data/C8/cook/dishes/staple/醪糟小汤圆.md @@ -0,0 +1,36 @@ +# 醪糟小汤圆的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 小汤圆 +* 醪糟 +* 白糖 +* 枸杞(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1-2 个人食用 + +总量: + +* 水 300 毫升 * 份数 +* 小汤圆 250 克 * 份数 +* 醪糟 50 克 * 份数 +* 枸杞 5 颗 * 份数 +* 白糖 + +## 操作 + +* 将水倒入锅中并煮沸 +* 放入小汤圆煮 8 分钟 +* 放入醪糟和枸杞再煮 2 分钟 +* 盛入碗中根据个人口味加入白糖并搅拌均匀 +* 吃 + +## 附加内容 + +* 白糖的用量根据个人口味更改 +* 若喜欢更浓的口感可以减少 100 毫升内的水 +* 若喜欢软点的枸杞口感,可以将枸杞和小汤圆同时煮 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/韩式拌饭/韩式拌饭.md b/data/C8/cook/dishes/staple/韩式拌饭/韩式拌饭.md new file mode 100644 index 0000000..61dad16 --- /dev/null +++ b/data/C8/cook/dishes/staple/韩式拌饭/韩式拌饭.md @@ -0,0 +1,53 @@ +# 韩式拌饭的做法 + +![韩式拌饭](./韩式拌饭.png) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 米饭 +- 鸡蛋 +- 火锅牛肉卷 +- 豆芽 +- 蘑菇 +- 胡萝卜 +- 西葫芦 +- 韩式辣酱 +- 雪碧 +- 芝麻 +- 芝麻油 + +## 计算 + +每份: + +- 米饭 1 碗 (400g) +- 鸡蛋 1 颗 +- 火锅牛肉卷 6 卷 60g +- 豆芽 1 把 80g +- 蘑菇 50g +- 胡萝卜 1/4 根 +- 西葫芦 50g +- 韩式辣酱 25ml +- 雪碧 2 瓶盖, 20ml +- 芝麻 10g +- 芝麻油 20ml +- 生抽 15ml + +## 操作 + +- 蔬菜清洗 切丝 放锅中翻炒 食材变软 便可称出 +- 煮水 等沸腾时 焯牛肉卷 只需煮熟 大概三分钟即可捞出 +- 煎[溏心蛋](../../breakfast/溏心蛋.md) +- 将[米饭](../../staple/米饭/电饭煲蒸米饭.md)放在一个碗里 然后倒扣在大碗 +- 将准备好的蔬菜和肉卷依次绕圈放在米饭上面 将煎蛋放中间 +- 备酱汁 + - 10ml 韩式辣酱(甜辣口)+ 5ml 生抽 + 两瓶盖雪碧(减肥的话 可以放无糖雪碧)+ 10g 芝麻 + 5ml 芝麻油 + - 搅拌上述酱汁,可以再加生抽和盐 +- 将备好的酱汁倒在摆好盘的碗中 + +## 附加内容 + +- 这是道非常简单的菜 过程会比较繁琐 但当将菜肉米饭酱汁搅拌起来吃会很满足 +- 如果对外观有一定要求 可以用砂锅代替普通碗 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/韩式拌饭/韩式拌饭.png b/data/C8/cook/dishes/staple/韩式拌饭/韩式拌饭.png new file mode 100644 index 0000000..af23b43 --- /dev/null +++ b/data/C8/cook/dishes/staple/韩式拌饭/韩式拌饭.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37f962c58c7c8165ae99abbbe8850a5e92d6e4d12da86de4ad5d66d4b0fdf454 +size 241981 diff --git a/data/C8/cook/dishes/staple/韭菜盒子.md b/data/C8/cook/dishes/staple/韭菜盒子.md new file mode 100644 index 0000000..4e86b53 --- /dev/null +++ b/data/C8/cook/dishes/staple/韭菜盒子.md @@ -0,0 +1,40 @@ +# 韭菜盒子的做法 + +韭菜盒子是一道美味的传统小吃,外皮酥脆,内馅鲜香,富含维生素和蛋白质。制作简单,适合午餐,预计制作时长约 2.5 小时。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 韭菜 +- 虾仁 +- 鸡蛋 +- 香油 +- 盐 +- 面粉 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 韭菜 500g +- 虾仁 100g +- 鸡蛋 3 枚 +- 香油 10ml +- 盐 5g +- 面粉 250g + +## 操作 + +- 将面粉放入大碗中,加入水,搅拌成光滑的面团,静置 30 分钟。 +- 韭菜洗净切碎,加入打散的鸡蛋、5g 盐,搅拌均匀。 +- 将面团分成小剂子,擀成薄圆饼,包入韭菜、虾仁、鸡蛋液。 +- 热锅,加入食用油,放入包好的韭菜盒子,煎至两面金黄,约 3-4 分钟。 +- 盛盘,稍凉后即可享用。 + +## 附加内容 + +- 制作时可根据个人口味添加豆腐干等配料。 +- 注意煎制时火候,避免外焦内生。 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/鲣鱼海苔玉米饭/米饭.jpg b/data/C8/cook/dishes/staple/鲣鱼海苔玉米饭/米饭.jpg new file mode 100644 index 0000000..c3f9395 --- /dev/null +++ b/data/C8/cook/dishes/staple/鲣鱼海苔玉米饭/米饭.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e5a586a8d7ba5f2a2c7b793b16f917426bcbd7a55289bb7bf82e009f93fb08b +size 419183 diff --git a/data/C8/cook/dishes/staple/鲣鱼海苔玉米饭/鲣鱼海苔玉米饭.md b/data/C8/cook/dishes/staple/鲣鱼海苔玉米饭/鲣鱼海苔玉米饭.md new file mode 100644 index 0000000..d7e0aae --- /dev/null +++ b/data/C8/cook/dishes/staple/鲣鱼海苔玉米饭/鲣鱼海苔玉米饭.md @@ -0,0 +1,30 @@ +# 鲣鱼海苔玉米饭的做法 + +![示例菜成品](./米饭.jpg) + +空气炸锅羊排超级懒人版,味道尚可,主要看羊排的品质。 + +- 烹饪总时长:40 分钟(准备 3 分钟+煮饭 40 分钟+拌饭 2 分钟) +- 实际操作时间:5 分钟 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 必备:东北米(金龙鱼 30 元 5kg 的就行,推荐使用米家 IH 电饭煲煮,教程用的是米家小饭煲,**不推荐使用高压锅煮饭**) +- 必备:鲣鱼海苔碎(JD 和淘宝都有,可以搜索:日式拌饭料) +- 必备:玉米粒(淘宝搜索:玉米粒 即食) + +## 计算 + +- 鲣鱼海苔碎 20g +- 玉米粒 80g/袋 + +## 操作 + +- 盛好米饭,放入玉米粒拌好 +- 放入鲣鱼海苔碎 + +## 附加内容 + +- 使用米家小饭煲煮东北米的话,水没过米 3 毫米就行,太多水煮出来不是一粒一粒的饭 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/麻油拌面.md b/data/C8/cook/dishes/staple/麻油拌面.md new file mode 100644 index 0000000..3cec873 --- /dev/null +++ b/data/C8/cook/dishes/staple/麻油拌面.md @@ -0,0 +1,40 @@ +# 麻油拌面的做法 + +省吃俭用懒人的菜:麻油拌面:想必大家都会有节约开销的时刻吧,附上个人耐吃又省钱的食谱。不需要太多的步骤简单的煮,捞,吃。 + +- 单身的朋友懒惰出门,又不想花钱,简简单单就一餐。 +- 非单身的朋友想存钱,让女友花钱,简简单单就一餐。 + +预估烹饪难度:★ + +## 必备原料和工具 + +* 风干快熟面/任何牌子的快熟面(不需要调味料) +* 麻油 +* 胡椒粉 +* 老抽 +* 盐 + +## 计算 + +每份: + +* 水 1 升 +* 快熟面 1 块 +* 麻油 15ml +* 老抽 10 克 +* 盐 30 克(可选,这 30g 盐不会被全部食用) +* 胡椒粉 10 克 +* 生抽 5 克(可选) + +## 操作 + +* 将水倒入锅中并煮沸 (喜欢吃 q 弹面的同学,可在水里加入 30 克盐,用盐水煮出来的面会比较 q 弹) +* 将快熟面放入锅中 3 分钟(也可参考当下品牌快熟面的烹饪时间) +* 当面开始散了可以开始搅拌,让面受热均匀 +* 将水滤干把面倒入碗中 +* 按照上面的计量放入麻油,老抽,胡椒粉,生抽(可选) +* 筷子搅拌均匀 +* 一道简单即省钱的懒人麻油拌面就完成啦 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/staple/麻辣减脂荞麦面.md b/data/C8/cook/dishes/staple/麻辣减脂荞麦面.md new file mode 100644 index 0000000..0a88169 --- /dev/null +++ b/data/C8/cook/dishes/staple/麻辣减脂荞麦面.md @@ -0,0 +1,50 @@ +# 麻辣减脂荞麦面的做法 + +麻辣减脂荞麦面做法非常简单,不需要任何厨艺基础。 +一份 298 千卡,美味+便宜+减脂,只需要 20 分钟就可以完成。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 调味料:火锅底料、花生酱、全脂牛奶、生抽、辣椒油、醋、花椒油 +* 原料:半干荞麦面、娃娃菜、生菜 +* 洗菜盆、直径 18cm 的小锅 + +> 建议购买方案: +> 荞麦面:pdd买食尚烩荞麦面,一包400g,价格4.9元,可以做4份 +> 火锅底料:某宝小龙坎传统清油火锅底料味道最佳,29.8元一包,可以做20份 +> 花生酱:pdd莺歌花生酱 24.8元两瓶,可以做68份 +> 花椒油:pdd五丰黎红花椒油400ml,32元两瓶,可以做80份 +> 其他:随便,不会影响到口味 + +## 计算 + +每份: + +- 半干荞麦面 100g +- 娃娃菜 8 片(共 150g) +- 生菜 6 片(共 80g) +- 火锅底料 25g +- 花生酱 15g +- 全脂牛奶 150ml +- 生抽 6ml +- 辣椒油 10ml +- 醋 20ml +- 花椒油 10ml +- 水 500ml + +## 操作 + +- 娃娃菜、生菜洗好,备用 +- 锅内倒入 500ml 水,开大火,将荞麦面和娃娃菜放进去,等待水沸腾 +- 水沸腾后,转小火,加入火锅底料、花生酱、牛奶、生抽、辣椒油,水开后煮 5 分钟 +- 加入生菜,再煮 2 分钟 +- 加入醋、花椒油,关火,直接端着小锅开吃。 + +## 附加内容 + +* 一定要选半干荞麦面,口感最好 +* 可以随意添加其他东西,比如火锅丸、蛋饺等 +* 火锅底料、花生酱、牛奶一定要加,口味三大巨头 +* 如果不能吃酸,可以不加醋 \ No newline at end of file diff --git a/data/C8/cook/dishes/template/示例菜/示例菜.jpg b/data/C8/cook/dishes/template/示例菜/示例菜.jpg new file mode 100644 index 0000000..004f462 --- /dev/null +++ b/data/C8/cook/dishes/template/示例菜/示例菜.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5d98099674c671c010ded82351ad55ab896a989826cec48bc4ed4c55020393e +size 152896 diff --git a/data/C8/cook/dishes/template/示例菜/示例菜.md b/data/C8/cook/dishes/template/示例菜/示例菜.md new file mode 100644 index 0000000..217d2ca --- /dev/null +++ b/data/C8/cook/dishes/template/示例菜/示例菜.md @@ -0,0 +1,83 @@ + + + + +# 示例菜的做法 + + + + + +![示例菜成品](./示例菜.jpg) + + +示例菜是一道简单易做的菜。富含 DHA 和蛋白质。一般初学者只需要 3 小时即可完成。还有美容效果哦~ + + + +预估烹饪难度:★★★★ + +## 必备原料和工具 + + + + + + + + +- 咖喱块(推荐品牌好侍) +- 土豆 +- 藤椒油(可选) + +## 计算 + + + + + + + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + + + + + +- 咖喱块 115g +- 土豆 2 个(每个土豆大约重 120g,共约 240g) +- 食用油 10-15ml + +## 操作 + + + + + +- 土豆去皮、切成不超过 4cm 的大块,备用 +- 咖喱块切碎,增加接触面积加速溶解,备用 +- 热锅,锅内放入 10ml - 15ml 食用油。等待 10 秒让油温升高 +- 放入土豆,保持翻炒至土豆*变软*(可以用筷子确认) +- 加水没过所有食材,沸腾后,将火调小然后**等待 15 - 20 分钟** +- 关火,加咖喱并搅拌,等待直至咖喱融化 +- 再开火,缓慢**搅拌 10 分钟**,防止糊锅 +- 在外观*呈粘稠状态*后关火,盛盘 + +## 附加内容 + + + +- 操作时,需要注意观察沸腾的水位线,如发现低于 2/3 的食材应加热水至没过食材。 +- 参考资料:[世界美食教程的微博视频](http://t.cn/EJ77yFy) + + + + \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/上汤娃娃菜/上汤娃娃菜.md b/data/C8/cook/dishes/vegetable_dish/上汤娃娃菜/上汤娃娃菜.md new file mode 100644 index 0000000..1722f45 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/上汤娃娃菜/上汤娃娃菜.md @@ -0,0 +1,44 @@ +# 上汤娃娃菜的做法 + +上汤娃娃菜的做法 (素菜、减肥餐) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 娃娃菜 +- 皮蛋 +- 午餐肉(火腿肠) +- 葱 +- 姜 +- 蒜 +- 盐 +- 糖 +- 淀粉 + +## 计算 + +注意,这道菜仅有足够 2-4 人食用的版本。 + +- 娃娃菜 700g +- 金针菇 10g(看个人喜好, 不喜欢 see you tomorrow 的就不放 😂) +- 皮蛋 一个(没有也可以不放) +- 午餐肉(火腿肠都可以替代) + +## 操作 + +- 娃娃菜洗净, 竖着切开切成段。 +- 葱 3g 切 小段。蒜 10g 切片。姜 10g 切小片。 +- 皮蛋切成丁, 火腿肠或者午餐肉切成丁(1cm 大小的丁) +- 金针菇洗净撕开 +- 烧热水娃娃菜放进去十秒钟出一下水捞出。 +- 热锅凉油, 加热锅倒入油过一遍就倒出来, 重新倒入一点油。 +- 调至小火加入葱姜蒜,煎炒出香味即可。 +- 加入适 300g 清水(水量没过娃娃菜即可), 放入娃娃菜, 金针菇, 午餐肉 +- 加入调味料蚝油、糖、盐、味精烧开。 +- 煮 3 分钟, 煮开后开始装盘, 盛出娃娃菜后皮蛋放在上面把汤汁浇上去就可以了 +- ![上汤娃娃菜](./上汤娃娃菜.png) + + 拍照技术有限, 味道还是很不错的 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/上汤娃娃菜/上汤娃娃菜.png b/data/C8/cook/dishes/vegetable_dish/上汤娃娃菜/上汤娃娃菜.png new file mode 100644 index 0000000..cb17b40 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/上汤娃娃菜/上汤娃娃菜.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8395e4f7497206589f16ce6b051e9af2b545cc7ce7bf9a94ee4f160075835b1c +size 130842 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/1.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/1.jpg new file mode 100644 index 0000000..520ce42 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00e409375303807716393a7bd834348abb75efe9f59249be8e9853af5c48b190 +size 205351 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/10.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/10.jpg new file mode 100644 index 0000000..4437fb6 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/10.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e03a194a6110042022f54e29c4def4a65f3531742ba8959ba64e550a7f7e3f6b +size 360952 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/2.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/2.jpg new file mode 100644 index 0000000..504d2e3 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8a1565a6a69c09173a645ad12d7f6fd7a0e64fdb5965f65eb44438b96ffd11d +size 306422 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/3.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/3.jpg new file mode 100644 index 0000000..cd817d3 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/3.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:558c51056edaf2c4a4896a55c21102c5c489e34444ef7a8f4177a6781cd5b5ce +size 285668 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/4.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/4.jpg new file mode 100644 index 0000000..2bfd93b --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/4.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f923ee021ae30dbff2f19a2eee87f462109a5eff4529e6537068311a6a42e74d +size 162922 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/5.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/5.jpg new file mode 100644 index 0000000..a9e4b51 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/5.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:717b54d6849dcb6c06c1cac1a2a70e3ac4c5de2bf10f22ca8c70f0f4a925ae8e +size 227149 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/6.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/6.jpg new file mode 100644 index 0000000..d2b1426 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/6.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b1f77fa43e31a5469a2c8901563e101464ca8970366f4983097cdef18863d78 +size 128349 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/7.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/7.jpg new file mode 100644 index 0000000..1a6e17c --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/7.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91392b3f685b97e0fdc715f38076d73b0d06247ec8c5cff21ffeaf598839d243 +size 171107 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/8.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/8.jpg new file mode 100644 index 0000000..51f29c8 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/8.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c03bd4942f327e3c6c5aa3af6b6f1e125ed3f4245628eb82b55b70af2c688779 +size 294458 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/9.jpg b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/9.jpg new file mode 100644 index 0000000..89d6c51 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/9.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3555c972dd6744cffe749ec0ce845a8b84cf98a6b9df0e861dc8c58ed63f338a +size 295821 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌木耳/凉拌木耳.md b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/凉拌木耳.md new file mode 100644 index 0000000..62290fd --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌木耳/凉拌木耳.md @@ -0,0 +1,56 @@ +# 凉拌木耳的做法 + +凉拌木耳,由于发放物资中有很多干货,木耳是较为健康的食物。且凉拌木耳的烹饪方式也相对简单。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 干木耳 (湿木耳也可,但不能太久之前泡发的,必须是新鲜的湿木耳) +* 蒜瓣 +* 白糖 +* 小米辣 +* 盐 +* 香油 +* 生抽 +* 醋 +* 芥末 (可以不用) + +## 计算 + +每份(1 人量): + +* 干木耳: 20g / 湿木耳: 120g +* 蒜瓣: 2-3 个 +* 小米辣: 2 个 +* 盐: 2 g +* 糖: 5-10g(依个人口味) +* 生抽: 15ml +* 醋: 15ml +* 香油: 5ml +* 芥末: (约 2cm) + +## 操作 + +* 泡发干木耳, 水量约为 400ml, 泡发约 45 分钟。 (湿木耳跳过此步骤) +* 将泡发好的木耳, 进行去根处理(如图 4, 5, 6), 并彻底洗净。 +* 起锅烧水,水开后放入木耳, 大火煮 1.5-2 分钟。 +* 将蒜瓣、小米辣切碎放入碗中 (可选取中大碗), 并依次加入盐、糖、生抽、醋、香油、芥末, 用量如上。 +* 木耳盛出后沥水, 放入上一步碗中。 +* 搅拌充分,端盘。 + +![干木耳](1.jpg) +![木耳](2.jpg) +![泡发后](3.jpg) +![木耳根](4.jpg) +![木耳根](5.jpg) +![剪去部分](6.jpg) +![水煮1.5-2分钟](7.jpg) +![蒜瓣和干辣椒](8.jpg) +![调料拌匀](9.jpg) +![成品](10.jpg) + +## 附加内容 + +* 调味品的数量可以根据个人口味进行调整, 如果不喜欢芥末, 可以不加入。 +* 等木耳冷却入味后口味更佳, 约 15 分钟。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌油麦菜.md b/data/C8/cook/dishes/vegetable_dish/凉拌油麦菜.md new file mode 100644 index 0000000..c5cca16 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌油麦菜.md @@ -0,0 +1,42 @@ +# 凉拌油麦菜的做法 + +预估烹饪难度:★ + +## 必备原料和工具 + +* 油麦菜 +* 芝麻酱 +* 酱油 +* 醋 +* 蚝油 +* 白糖 +* 香油 +* 蒜 +* 盐 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1-2 个人食用 + +总量: + +* 1 颗 油麦菜(约 200g) * 份数 +* 15ml 醋 * 份数 +* 5ml 酱油 * 份数 +* 10ml 芝麻酱 * 份数 +* 5ml 香油 * 份数 +* 5g 糖 * 份数 +* 10ml 蚝油 * 份数 +* 两**头**蒜 * 份数 + +## 操作 + +* 蒜拍碎切末 +* 醋,酱油,芝麻酱,香油,糖,蚝油,蒜末放到碗里搅拌均匀 +* 油麦菜切段,每段不超过 4cm +* 油麦菜放到一个大点的盆里,倒入上述碗中酱料,充分搅拌均匀. + +## 附加内容 + +* 芝麻酱可以用花生酱代替 +* 芝麻酱一定要和油麦菜混合均匀才更好吃. \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌莴笋/1.jpeg b/data/C8/cook/dishes/vegetable_dish/凉拌莴笋/1.jpeg new file mode 100644 index 0000000..2298807 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌莴笋/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0a4566cbfb2d6ea8eb73a0996dab208cceb733d3a17b41912c4adf0790524d7 +size 146717 diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌莴笋/凉拌莴笋.md b/data/C8/cook/dishes/vegetable_dish/凉拌莴笋/凉拌莴笋.md new file mode 100644 index 0000000..5faaa6e --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌莴笋/凉拌莴笋.md @@ -0,0 +1,44 @@ +# 凉拌莴笋的做法 + +凉拌莴笋,开胃小菜 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 莴笋 +* 萝卜 +* 小米辣 +* 姜 +* 蒜头 +* 盐 +* 食用油 + +## 计算 + +每份: + +* 莴笋 1 根 +* 萝卜 0.25 根 +* 小米辣 2 个 +* 姜 1 片 +* 蒜头 2 粒 +* 盐 5 g +* 食用油 25 ml + +## 操作 + +* 莴笋削皮,切小条。萝卜切条,一起放入大碗,加入盐搅拌,放置 10 分钟 +* 放置后的莴笋用水清洗 1-2 遍 +* 起锅烧水,放入莴笋,水煮 1 分钟 捞出,沥干水分,放入大碗 +* 起锅烧油,放入姜片、蒜粒、小米椒煸炒 30-45 S ,倒入莴笋中 +* 搅拌充分,端盘 + +![示例菜成品](./1.jpeg) + +## 附加内容 + +* 萝卜非必须,只是为了增加菜色 +* 端盘后,可以根据个人口味,额外增加生抽、白砂糖、香醋、芝麻等佐料 +* 莴笋条的大小看个人口感决定,但莴笋皮要尽量多削点,不然真的影响口感 +* 冰镇效果更加 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌豆腐.md b/data/C8/cook/dishes/vegetable_dish/凉拌豆腐.md new file mode 100644 index 0000000..6afe979 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌豆腐.md @@ -0,0 +1,53 @@ +# 凉拌豆腐的做法 + +凉拌豆腐是一道清爽可口的家常凉菜。富含植物蛋白和钙质,低脂健康,非常适合夏季食用或作为日常佐餐。制作过程简单快捷,一般初学者只需要 10 分钟即可完成。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 豆腐 (推荐选用北豆腐或老豆腐) +- 小葱 +- 大蒜 +- 生抽 +- 香油 +- 醋(可选) +- 白糖(可选) +- 辣椒油(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人吃。 + +每份: + +- 豆腐 250 g (约 1 块常见大小的豆腐) +- 小葱 10 g +- 大蒜 2-3 瓣 +- 生抽 15 ml +- 香油 5 ml +- 醋 5 ml(可选) +- 白糖 2 g(可选) +- 辣椒油 5 ml(可选) + +## 操作 + +- 将 豆腐 切成 2 cm 见方的小块,备用。 +- 锅中加入 500 ml 饮用水,大火烧开。 +- 放入 豆腐 块,煮 **1-2 分钟**,以去除豆腥味并使豆腐口感更紧实。 +- 将 煮好的 豆腐 块捞出,沥干水分,放入碗中,备用。 +- 将 小葱 洗净,切成葱花,备用。 +- 将 大蒜 去皮,切成蒜末,备用。 +- 在一个干净的小碗中,加入 15 ml 生抽,5 ml 香油,5 ml 醋(可选),2 g 白糖(可选)。 +- 加入切好的 大蒜末。 +- 搅拌均匀,使 白糖 充分溶解,酱汁混合均匀。 +- 将制作好的酱汁均匀淋在 豆腐 块上。 +- 撒上切好的 小葱花。 +- 根据个人喜好,淋上 5 ml 辣椒油(可选)。 +- 用 筷子 或勺子轻轻拌匀,即可食用。 + +## 附加内容 + +- 制作凉拌豆腐时,建议选用质地较硬的北豆腐或老豆腐,不易碎裂,口感更佳。 +- 如果喜欢更清淡的口感,可以省略醋和辣椒油。 +- 酱汁的比例可以根据个人口味进行调整。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌金针菇.md b/data/C8/cook/dishes/vegetable_dish/凉拌金针菇.md new file mode 100644 index 0000000..d469d55 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌金针菇.md @@ -0,0 +1,53 @@ +# 凉拌金针菇的做法 + +凉拌金针菇是一道简单快捷的开胃凉菜。口感脆嫩爽滑,富含膳食纤维和多种维生素。制作过程无需复杂的烹饪技巧,非常适合新手和忙碌时快速准备。一般初学者只需要 10 分钟即可完成。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 金针菇 +- 小葱 +- 大蒜 +- 生抽 +- 醋 +- 白糖(可选) +- 香油(可选) +- 辣椒油(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人吃。 + +每份: + +- 金针菇 150 g (约 1 小包) +- 小葱 5 g +- 大蒜 2 瓣 +- 生抽 15 ml +- 醋 10 ml +- 白糖 3 g(可选) +- 香油 5 ml(可选) +- 辣椒油 5 ml(可选) + +## 操作 + +- 将 金针菇 根部切除,用清水冲洗干净,备用。 +- 将 小葱 洗净,切成葱花,备用。 +- 将 大蒜 去皮,切成蒜末,备用。 +- 锅中加入 1000 ml 饮用水,大火烧开。 +- 放入 金针菇,煮 **1-2 分钟**,至金针菇变软。 +- 将 煮好的 金针菇 捞出,沥干水分,放入一个较大的碗中,备用。 +- 在另一个干净的小碗中,加入 15 ml 生抽,10 ml 醋,3 g 白糖(可选),5 ml 香油(可选)。 +- 加入切好的 大蒜末。 +- 搅拌均匀,使 白糖 充分溶解,酱汁混合均匀。 +- 将制作好的酱汁均匀淋在 金针菇 上。 +- 撒上切好的 小葱花。 +- 根据个人喜好,淋上 5 ml 辣椒油(可选)。 +- 用 筷子 轻轻拌匀,即可食用。 + +## 附加内容 + +- 金针菇焯水时间不宜过长,以免影响口感。 +- 酱汁的比例可以根据个人口味喜好进行调整。 +- 如果不喜欢吃辣,可以省略辣椒油。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/凉拌黄瓜.md b/data/C8/cook/dishes/vegetable_dish/凉拌黄瓜.md new file mode 100644 index 0000000..47ff502 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/凉拌黄瓜.md @@ -0,0 +1,39 @@ +# 凉拌黄瓜的做法 + +预估烹饪难度:★ + +## 必备原料和工具 + +* 黄瓜 +* 醋 +* 酱油 +* 蒜 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +* 黄瓜 200 克 * 份数 +* 醋 7.5 ml + 4 ml * 份数 +* 酱油 5 ml + 2.5 ml * 份数 +* 蒜 3 瓣 * 份数 +* 盐 0.4 克 + 0.2 克 * 份数 +* 香油 5 ml + 2 ml * 份数 +* 蚝油 5 ml + +## 操作 + +* 用菜刀将黄瓜拍扁,再剁成长 3 厘米的碎块 +* 将碎黄瓜装入碗中 +* 将蒜拍碎切成碎末 +* 将醋,酱油,盐,蚝油和蒜依次倒入碗中搅拌均匀并腌制 15 分钟 +* 将香油倒入碗中并均匀搅拌 + +## 附加内容 + +* 部分情况下黄瓜端头有苦味,请洗净切下后确认 +* 做好之后直接开吃,亦可先准备好后放入冰箱冷藏(并非冷冻)后食用 +* 若放入冰箱冷藏,则需使用保鲜膜包紧,并在 8 小时内食用完毕,否则黄瓜会因过度腌制失去清脆口感 +* 推荐黄瓜去皮,口感更好 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/包菜炒鸡蛋粉丝/1.jpg b/data/C8/cook/dishes/vegetable_dish/包菜炒鸡蛋粉丝/1.jpg new file mode 100644 index 0000000..d2f924b --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/包菜炒鸡蛋粉丝/1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f08d14fedaea7dfbb05553be50b7bc6da776e1b31c0fd573850ce68cdaa7b3fc +size 569608 diff --git a/data/C8/cook/dishes/vegetable_dish/包菜炒鸡蛋粉丝/包菜炒鸡蛋粉丝.md b/data/C8/cook/dishes/vegetable_dish/包菜炒鸡蛋粉丝/包菜炒鸡蛋粉丝.md new file mode 100644 index 0000000..7274758 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/包菜炒鸡蛋粉丝/包菜炒鸡蛋粉丝.md @@ -0,0 +1,45 @@ +# 包菜炒鸡蛋粉丝的做法 + +包菜炒鸡蛋粉丝,是中国的一道日常生活中所熟知的菜品 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 包菜 +* 鸡蛋 +* 粉丝 +* 胡萝卜 +* 菜籽油 +* 盐、生抽、老抽、蚝油 +* 葱、蒜、干辣椒 + +## 计算 + +每份: + +* 包菜 半 颗 +* 鸡蛋 2 个 +* 粉丝 1 把 +* 胡萝卜 半 根 +* 菜籽油 20 ml +* 盐 2 g、生抽 15 ml、老抽 10 ml、蚝油 10 ml +* 葱 半 根、蒜瓣 2 片、干辣椒 5 根 + +## 操作 + +* 胡萝卜、包菜切丝备用 +* 粉丝先用冷水浸泡 1 小时,然后将粉丝放入锅中,加入开水烧至粉丝烫软捞出备用 +* 鸡蛋打入碗中,加入盐后搅拌 15 秒 +* 葱、蒜、辣椒切成小粒备用 +* 起锅烧油,倒入鸡蛋,打散炒熟盛出 +* 再倒入油,放入葱、蒜、干辣椒翻炒 8 秒 +* 下胡萝卜、包菜丝儿翻炒 30 秒 +* 放入粉丝 +* 放调料,生抽 15 ml,老抽 10 ml,蚝油 10 ml,盐 2 克 +* 放入之前炒好的鸡蛋,翻炒约 15 秒 +* 出锅摆盘 + +![示例菜成品](./1.jpg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/地三鲜.md b/data/C8/cook/dishes/vegetable_dish/地三鲜.md new file mode 100644 index 0000000..4f38275 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/地三鲜.md @@ -0,0 +1,52 @@ +# 地三鲜的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 茄子 +- 土豆 +- 尖椒 +- 葱 +- 姜 +- 蒜 +- 豆瓣酱 +- 生抽 +- 盐 +- 糖 +- 淀粉 + +## 计算 + +注意,这道菜仅有足够 2-4 人食用的版本。 + +- 茄子 100g +- 土豆 150g +- 尖椒 3 - 4 个 +- 淀粉 20g + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +- 土豆洗净、去皮。茄子、尖椒洗净。 +- 葱 3g 切 0.5cm 小段。蒜 10g 剁碎。姜 10g 切沫。 +- 茄子、土豆、尖椒均切成 15g 的小块。 +- 热锅,加入 25ml 油。 +- 加入土豆,煎炸大约 3 分钟,待其到大约 8 分熟,以显示金黄色为准。 +- 捞出土豆,留下油。 +- 加入茄子,煎炸大约 40 秒,待其到大约 7 分熟,以显示金黄色为准。 +- 如果锅内已经没有流动的油,可以考虑补充 15ml 油。 +- 放入葱 3g。姜 10g。 +- 放入豆瓣酱 20ml。 +- 放入生抽 10ml。 +- 放入盐 8g。 +- 放入糖 10g。 +- 放入之前处理的土豆。 +- 放入尖椒。 +- 翻炒 1 分钟。 +- 放入蒜 10g +- 加入 200ml 水和 20g 淀粉。 +- 待水开后,汤减少一半时,关火盛盘。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/小炒藕丁/小炒藕丁.jpg b/data/C8/cook/dishes/vegetable_dish/小炒藕丁/小炒藕丁.jpg new file mode 100644 index 0000000..0e2357c --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/小炒藕丁/小炒藕丁.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:55b904affb22c52eaaafb50493222bc45f50ffb9221384e373cd7d5336cd9fc1 +size 142291 diff --git a/data/C8/cook/dishes/vegetable_dish/小炒藕丁/小炒藕丁.md b/data/C8/cook/dishes/vegetable_dish/小炒藕丁/小炒藕丁.md new file mode 100644 index 0000000..3890090 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/小炒藕丁/小炒藕丁.md @@ -0,0 +1,48 @@ +# 小炒藕丁的做法 + +![小炒藕丁成品](./小炒藕丁.jpg) + +小炒藕丁是一道简单易做的菜,莲藕营养丰富,非常适合素食。预计制作时长 20 分钟 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 大葱 +- 小米辣 +- 莲藕 +- 生抽 +- 老抽 +- 耗油 +- 油 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 大葱 1 段 +- 小米辣 1-2 根 (看个人吃辣程度) +- 莲藕 1 段 +- 生抽 30 ml +- 老抽 15 ml +- 耗油 15 ml +- 食用油 10-15ml + +## 操作 + +- 大葱、小米辣切小段,备用 +- 莲藕去皮,切成不超过 3cm 的小块,放入水中备用(防止氧化发黑) +- 取炒锅,锅内放入 500ml 凉水,煮沸 +- 将藕丁下入沸水中,焯水 2 分钟后,取出放入盘中备用 +- 将锅中水倒掉后,将锅加热干燥,加入 10-15 ml 食用油 +- 待油温升高后,下入葱花,小米辣爆香 +- 将处理好的藕丁下入锅中,大火翻炒 +- 加入生抽、老抽、耗油 +- 翻炒 2 分钟即可出锅 + +## 附加内容 + +- 食用莲藕要挑选外皮呈黄褐色、肉肥厚而白的。如果发黑,有异味,则不宜食用。 +- 请尽量不要使用铁器,会导致莲藕发黑 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/干锅花菜/干锅花菜.jpg b/data/C8/cook/dishes/vegetable_dish/干锅花菜/干锅花菜.jpg new file mode 100644 index 0000000..1588b25 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/干锅花菜/干锅花菜.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c597133db31a865c86a0b7eaed15f79de3c0c722a08f8160fb8d6aa08e51b0c +size 593802 diff --git a/data/C8/cook/dishes/vegetable_dish/干锅花菜/干锅花菜.md b/data/C8/cook/dishes/vegetable_dish/干锅花菜/干锅花菜.md new file mode 100644 index 0000000..bb4493b --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/干锅花菜/干锅花菜.md @@ -0,0 +1,45 @@ +# 干锅花菜的做法 + +![干锅花菜成品](./干锅花菜.jpg) + +干锅花菜是湘菜常见的一道菜。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 花菜 +- 五花肉 +- 辣椒 +- 生抽 +- 白糖 +- 蒜 +- 盐 +- 油 + +## 计算 + +每份: + +- 花菜 400 g +- 五花肉 100 g +- 辣椒 1-2 根 +- 生抽 10 ml +- 白糖 5g +- 蒜瓣 3-4 个 +- 盐 2 g +- 油 10 ml + +## 操作 + +- 花菜朵朝下,没入淡盐水中浸泡 20 分钟。然后洗净用小刀拆成小朵 +- 入开水锅中焯水 1 分钟,捞出立即用冷水冲淋至完全凉透,沥水备用 +- 五花肉切成薄片,大蒜白色切下用刀背拍扁,小红辣椒切成段 +- 锅烧热放油,油热下大葱白爆香 +- 下五花肉片入锅,用中火煸炒至表面全部变色,继续煸炒一会儿,把肥肉部分的油份逼出一部分 +- 倒入红辣椒段和花菜,翻炒几下 +- 加入 10 ml 生抽 +- 再加入 5 g 白糖,转大火不断翻炒 1 分钟 +- 把大蒜叶部分切成段,放入锅中,翻炒几下后,关火盖上盖子焖 1 分钟即可 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/手撕包菜/1.jpeg b/data/C8/cook/dishes/vegetable_dish/手撕包菜/1.jpeg new file mode 100644 index 0000000..6f8472a --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/手撕包菜/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed0c29ea65a7ac4cc6a17a778bb5098d980405146f68c73c1b32fb0d310f5eea +size 127488 diff --git a/data/C8/cook/dishes/vegetable_dish/手撕包菜/2.jpeg b/data/C8/cook/dishes/vegetable_dish/手撕包菜/2.jpeg new file mode 100644 index 0000000..e8e3fe2 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/手撕包菜/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:424caab717e05e6a823f61551a9f6976bafb2a0c2ccf47d2cb792617d284abaf +size 151293 diff --git a/data/C8/cook/dishes/vegetable_dish/手撕包菜/3.jpeg b/data/C8/cook/dishes/vegetable_dish/手撕包菜/3.jpeg new file mode 100644 index 0000000..da686ae --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/手撕包菜/3.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f15dcd8504fcbeeb95f1930c0b0ff226a9f7576a846af0af600e4d741ffa3e9 +size 111973 diff --git a/data/C8/cook/dishes/vegetable_dish/手撕包菜/4.jpeg b/data/C8/cook/dishes/vegetable_dish/手撕包菜/4.jpeg new file mode 100644 index 0000000..b5dd844 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/手撕包菜/4.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37f7c1c9880153b3a4d5733c55203814c8fabcc93bc82acdfccbb450dd3bbd1b +size 138914 diff --git a/data/C8/cook/dishes/vegetable_dish/手撕包菜/手撕包菜.md b/data/C8/cook/dishes/vegetable_dish/手撕包菜/手撕包菜.md new file mode 100644 index 0000000..1f1c179 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/手撕包菜/手撕包菜.md @@ -0,0 +1,59 @@ +# 手撕包菜的做法 + +手撕包菜是一道色香味俱全的汉族名菜,属于湘菜系 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 包菜 +* 五花肉 +* 小米辣 +* 食用油 +* 料酒 +* 生抽 +* 香醋 +* 鸡精 +* 姜 +* 蒜头 +* 蒜苗 +* 盐 + +## 计算 + +每份: + +* 包菜 1 颗 +* 五花肉 200 g +* 小米辣 2 根 +* 食用油 60 ml +* 料酒 5 ml +* 生抽 5 ml +* 香醋 5 ml +* 鸡精 2 g +* 姜 2 片 +* 蒜头 2 粒 +* 蒜苗 0.5 根 +* 盐 5 g + +## 操作 + +* 包菜对半切开,去掉中间白色部分【参见图一】 +* 手撕包菜,碗中放入 2 g 盐,清洗包菜并沥干备用【参见图二】 +* 姜片、蒜头、小米辣、蒜苗处理后备用【参见图三】 +* 五花肉切片,清水清洗后备用 +* 锅中加入 30 ml 食用油,倒入包菜翻炒,大火翻炒 1 分钟 后,加入 3 g 盐 ,继续翻炒 2 分钟 后取出备用 +* 锅中加入 30 ml 食用油,倒入五花肉,大火翻炒 1 分钟 +* 倒入姜片等材料,翻炒 1 分钟 +* 倒入包菜翻炒后,加入 香醋、料酒、鸡精、料酒,大火继续翻炒,2 分钟 后出锅 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) +![示例菜成品](./3.jpeg) +![示例菜成品](./4.jpeg) + +## 附加内容 + +* 步骤五中,翻炒时间需要实际情况做调整,一般是炒到包菜七分熟后即可。七分熟是指包菜已经出水质感变软 +* 步骤五中,加盐的作用是锁住包菜水分的同时,给包菜上一点味道 +* 最后一个步骤中,翻炒时间根据实际情况和个人口感做灵活调整 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/拔丝土豆/1.jpeg b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/1.jpeg new file mode 100644 index 0000000..46f4ea1 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbea5212f5cf5ecfe5ae51b0dea7efbdb18c2e3c2e0600828d3e4c7e397de751 +size 220129 diff --git a/data/C8/cook/dishes/vegetable_dish/拔丝土豆/2.jpeg b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/2.jpeg new file mode 100644 index 0000000..74c4010 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ee16eb43af07cd6da37c54b4294f73e4e7acf4b313dd2e626e570d20a612092 +size 187193 diff --git a/data/C8/cook/dishes/vegetable_dish/拔丝土豆/3.jpeg b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/3.jpeg new file mode 100644 index 0000000..1a9fd99 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/3.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:273ed1826853e2b10165c33c6b6e5ec33d62fc3ba46dd9f163434b4e23cf7b80 +size 356894 diff --git a/data/C8/cook/dishes/vegetable_dish/拔丝土豆/4.jpeg b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/4.jpeg new file mode 100644 index 0000000..ed87fd5 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/4.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1788ab5b8dbc3b33af2fea04004761c87a784ef17977f4801c6681b6f7922e9e +size 174170 diff --git a/data/C8/cook/dishes/vegetable_dish/拔丝土豆/拔丝土豆.md b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/拔丝土豆.md new file mode 100644 index 0000000..a6ecfb9 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/拔丝土豆/拔丝土豆.md @@ -0,0 +1,44 @@ +# 拔丝土豆的做法 + +拔丝土豆是一道色香味俱全的特色名菜,属于鲁菜系 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 土豆 +* 食用油 +* 淀粉 +* 白砂糖 +* 水 +* 芝麻 + +## 计算 + +每份: + +* 土豆 2 个 +* 食用油 300 ml (土豆能浮在油上面即可) +* 淀粉 30 g +* 白砂糖 120 g (要多放糖,这是为了在土豆上面裹上一层厚厚的糖浆,从而产生拔丝的效果) +* 水 100 ml +* 芝麻 5 g + +## 操作 + +* 土豆去皮,切均匀的小块。放入淀粉(不加水)搅拌,使得淀粉覆盖土豆表面 +* 起锅烧油,放入土豆块,缓缓翻滚煎炸 5-7 分钟 ,直至筷子可以插进土豆 +* 取出土豆,放入大碗备用 +* 锅中加入水、白砂糖,沿着一个方向慢慢搅动白砂糖,直到白砂糖颜色变成褐色 +* 重新倒入土豆,翻炒 30 S 后 出锅 +* 土豆盛盘,散上芝麻 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) +![示例菜成品](./3.jpeg) +![示例菜成品](./4.jpeg) + +## 附加内容 + +* 土豆煎炸不可太熟透,否则在拔丝端盘时不容易定型,影响美观 +* 对于使用剩余的食用油,可以考虑重新收集到油壶。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/松仁玉米.md b/data/C8/cook/dishes/vegetable_dish/松仁玉米.md new file mode 100644 index 0000000..99f3594 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/松仁玉米.md @@ -0,0 +1,44 @@ +# 松仁玉米的做法 + +松仁玉米是一道色香味俱全的家常菜,口感甜嫩清爽,松仁香脆,老少皆宜。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 玉米粒(建议使用甜玉米) +* 熟松子仁 +* 胡萝卜(可选,增加色彩) +* 食用油 +* 白砂糖 +* 盐 +* 淀粉 +* 水 + +## 计算 + +每份: + +* 玉米粒 200 g(可用罐头甜玉米,也可自备煮熟) +* 熟松子仁 30 g +* 胡萝卜 50 g(切小丁,可省略) +* 食用油 15 ml +* 白砂糖 10 g +* 盐 1 g +* 淀粉 5 g +* 水 20 ml(用于调淀粉水) + +## 操作 + +* 玉米粒和胡萝卜丁提前焯水 1 分钟,捞出沥干备用 +* 热锅凉油,放入胡萝卜丁略炒,再加入玉米粒翻炒 +* 加入白砂糖和盐,炒匀 +* 混合水与淀粉成水淀粉,倒入锅中快速翻炒使汤汁略稠 +* 加入熟松仁翻炒均匀 +* 出锅装盘 + +## 附加内容 + +* 松仁可以提前用小火干炒至微微金黄香脆,更加美味 +* 使用罐头玉米时应先沥干水分,避免炒制过程中出水过多 +* 炒制时火候不宜过大,以防糊锅或松仁焦糊 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/椒盐玉米/椒盐玉米.jpeg b/data/C8/cook/dishes/vegetable_dish/椒盐玉米/椒盐玉米.jpeg new file mode 100644 index 0000000..b29c532 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/椒盐玉米/椒盐玉米.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f771ec3fe8e2f1970ff8db9114f7065e12e8a6cde91839e8d3c339ed010add2d +size 173857 diff --git a/data/C8/cook/dishes/vegetable_dish/椒盐玉米/椒盐玉米.md b/data/C8/cook/dishes/vegetable_dish/椒盐玉米/椒盐玉米.md new file mode 100644 index 0000000..15b8d83 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/椒盐玉米/椒盐玉米.md @@ -0,0 +1,46 @@ +# 椒盐玉米的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 玉米粒 +- 椒盐 +- 芝麻粒 +- 油 +- 淀粉 +- 两个塑料簸箕 +- 若干吸油纸 + +## 计算 + +这道菜分量和在川菜馆点的标准分量一样 + +- 玉米粒(袋装) 350g +- 淀粉(在锅里完全能盖住玉米粒表面为准,在 40 - 70g) +- 椒盐粉 10g +- 芝麻粒 10g + +## 操作 + +- 玉米粒都是剥好的,直接解冻即可,温水泡 15 分钟或者灶上开水煮 5 分钟。 +- 拿出一个簸箕,将其假设为 BoxA,垫上吸油纸,倒进解冻好的玉米粒。 +- shaking shaking shaking! - 直到吸油纸全部变湿为止。 +- 拿出第二个簸箕 BoxB,垫上吸油纸,将 BoxA 的玉米粒全部倒入 BoxB 中。 +- shaking shaking shaking! - 直到吸油纸全部变湿为止。 +- 重复上述操作多次,直到玉米表面没有明显可见的水滴但保持湿润的状态。 +- 倒入大量淀粉,能够完全盖住玉米粒。 +- shaking shaking shaking! - 直到淀粉裹住了玉米粒 +- 开灶 - 放锅 - 倒入油 尽量铺满锅底 但不要太多。 +- 油热 8 成,倒入裹上了淀粉的玉米粒。 +- 中火先煎 30s,不要翻炒,不然淀粉会掉。 +- 轻微翻炒 3 分钟即可出锅。 +- 最重要的一步:撒上 3g 椒盐,撒上芝麻粒! +- 香喷喷的”椒盐玉米“就做好了 + +## 附加内容 + +玉米粒不要自己剥,费手的,可以直接外卖软件买菜”已经剥好的玉米粒“,30 分钟 送达后温水解冻。 +开水解冻慢就拿开水煮!( 千万别煮玉米本身,带着包装一起煮,撕掉一个口 + +![椒盐玉米](./椒盐玉米.jpeg) \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/榄菜肉末四季豆/榄菜肉末四季豆.JPG b/data/C8/cook/dishes/vegetable_dish/榄菜肉末四季豆/榄菜肉末四季豆.JPG new file mode 100644 index 0000000..8dec8c9 Binary files /dev/null and b/data/C8/cook/dishes/vegetable_dish/榄菜肉末四季豆/榄菜肉末四季豆.JPG differ diff --git a/data/C8/cook/dishes/vegetable_dish/榄菜肉末四季豆/榄菜肉末四季豆.md b/data/C8/cook/dishes/vegetable_dish/榄菜肉末四季豆/榄菜肉末四季豆.md new file mode 100644 index 0000000..7d0a40a --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/榄菜肉末四季豆/榄菜肉末四季豆.md @@ -0,0 +1,37 @@ +# 榄菜肉末四季豆的做法 + +![榄菜肉末四季豆成品](./榄菜肉末四季豆.JPG) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 四季豆 +* 五花肉 +* 橄榄菜 +* 大蒜 +* 小米辣(不吃辣可以不放) + +## 计算 + +* 四季豆 220g +* 五花肉 100g +* 橄榄菜 20g +* 大蒜 10g +* 小米辣 10g + +## 操作 + +* 将四季豆洗净,并把筋撕干净,然后切成大小均匀的颗粒备用。 +* 将大蒜拍碎剁成蒜末备用。 +* 将小米辣切成大小均匀的颗粒备用。 +* 将五花肉去皮,然后剁成肉末备用。 +* 将锅烧热,然后加入 20ml 油滑锅,锅滑好之后将热油倒出,然后加入 10ml 冷油,这就是传说中热锅冷油,这么做主要是防止肉末粘锅。 +* 如果家里没有晾油瓶的话,也可以不用滑锅,放入油之后,直接加入肉末开始煸炒,小火煸炒两分钟,炒出猪油。 +* 肉末炒香之后加入蒜末,橄榄菜和小米辣,炒出香味。 +* 加入四季豆开中火煸炒,四季豆至少要炒 5 分钟,一定要保证四季豆**熟透**,否则可能会食物中毒。 +* 四季豆炒熟后加入 2ml 酱油从锅边淋入,然后加入 2g 盐、1g 鸡精、1g 胡椒粉和 0.5g 糖。 +* 将调料翻炒均匀。 +* 出锅,装盘。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/水油焖蔬菜.md b/data/C8/cook/dishes/vegetable_dish/水油焖蔬菜.md new file mode 100644 index 0000000..c9bb4d3 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/水油焖蔬菜.md @@ -0,0 +1,34 @@ +# 水油焖蔬菜的做法 + +水油焖蔬菜中添加了油,这提升了口感,并且可提升脂溶性维生素的摄入。相比生吃蔬菜,好处更多。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 食用油 +* 盐 +* 蚝油(可选) +* 叶菜类蔬菜 + +## 计算 + +叶菜类蔬菜含水量较多,在准备时可能看起来体积很大。实际受热后体积会迅速减小。 + +* 叶菜类蔬菜:300g ~ 500g + +## 操作 + +* 洗净蔬菜 +* 锅中加入 150ml 水,并烧开。(水不需要能完全没过蔬菜) +* 加入 3g 盐 +* (可选)加入 3ml 蚝油 +* 加入 2ml 食用油 +* 下菜, 翻拌一下,然后盖上锅盖焖 1 分钟 +* 盛盘 + +## 附加内容 + +* 不确定咸淡的情况, 可以先少放盐, 在出锅前尝味, 考虑调整加盐 +* 可以用鸡汤、骨头汤等替代水, 更好吃 +* 焖的时间不可过长 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/油醋爆蛋.md b/data/C8/cook/dishes/vegetable_dish/油醋爆蛋.md new file mode 100644 index 0000000..d8157f0 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/油醋爆蛋.md @@ -0,0 +1,41 @@ +# 油醋爆蛋的做法 + +油醋爆蛋是十分简单但是色香味一绝的一道菜,属于湘菜。制作十分简单,大约十分钟左右。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 鸡蛋 +- 小米辣 +- 小葱 +- 蒜 +- 盐 +- 油 +- 香醋 +- 生抽 +- 蚝油 +- 白糖 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 咖喱块 115g +- 土豆 2 个(每个土豆大约重 120g,共约 240g) +- 食用油 10-15ml + +## 操作 + +- 鸡蛋不需打散,直接打入碗中备用 +- 香葱切 3cm 长小段即可 +- 蒜瓣和小米辣放入打蒜器,打成沫 +- 将香醋、生抽、蚝油、白糖、水加入小碗,搅拌均匀作为糖醋料汁 +- 油热倒入鸡蛋,等鸡蛋凝固之后铲成大块,倒入蒜沫、小米辣沫、倒入糖醋料汁 +- 大火收汁、快出锅时加入葱段即可 + +## 附加内容 + +- 亲测老恒和酿造香醋零添加口味最好,醋香是本菜灵魂所在。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/洋葱炒鸡蛋/1.jpeg b/data/C8/cook/dishes/vegetable_dish/洋葱炒鸡蛋/1.jpeg new file mode 100644 index 0000000..88f8784 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/洋葱炒鸡蛋/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83b6951ab77218784ee6ba898b01beca3997cdabc08b749dd5e818fd9c004c22 +size 144620 diff --git a/data/C8/cook/dishes/vegetable_dish/洋葱炒鸡蛋/洋葱炒鸡蛋.md b/data/C8/cook/dishes/vegetable_dish/洋葱炒鸡蛋/洋葱炒鸡蛋.md new file mode 100644 index 0000000..3c961fe --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/洋葱炒鸡蛋/洋葱炒鸡蛋.md @@ -0,0 +1,35 @@ +# 洋葱炒鸡蛋的做法 + +洋葱炒鸡蛋,是中国的一道日常生活中所熟知的菜品 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 鸡蛋 +* 洋葱 +* 食用油 +* 盐 +* 葱 +* 料酒 + +## 计算 + +每份: + +* 鸡蛋 2 个 +* 洋葱 50 g +* 食用油 50 ml +* 盐 2 g +* 葱 半 根 +* 料酒 2 ml + +## 操作 + +* 鸡蛋打入大碗中,加入洋葱片、盐后搅拌 60 S +* 起锅烧油,倒入鸡蛋,一面煎炸 30-45 S ,翻面继续翻炒,反复 2-3 分钟 后散上料酒出锅 +* 鸡蛋装盘,散上葱花 + +![示例菜成品](./1.jpeg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/清炒花菜.md b/data/C8/cook/dishes/vegetable_dish/清炒花菜.md new file mode 100644 index 0000000..ae7cdb4 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/清炒花菜.md @@ -0,0 +1,42 @@ +# 清炒花菜的做法 + +清炒花菜是一道常见的家常素菜。富含维生素 C 和膳食纤维,口感脆嫩。做法简单,是一道快速上手的炒菜。一般初学者只需要 15 分钟即可完成。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 花菜 +- 大蒜 +- 盐 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人食用(作为配菜)。 + +每份: + +- 花菜 约 300 g (约 1/2 中等大小的花菜) +- 大蒜 2-3 瓣 +- 盐 3 g +- 食用油 15 ml +- 饮用水 50 ml (用于炒制过程) + +## 操作 + +- 将 花菜 洗净,用刀或手掰成小朵,粗茎部分可以切片,备用。 +- 将 大蒜 去皮,切成蒜片,备用。 +- 锅中加入 1000 ml 饮用水,大火烧开。 +- 放入 花菜 朵,煮 **2-3 分钟**,至花菜颜色变浅,口感稍微软化。 +- 将 煮好的 花菜 捞出,沥干水分,备用。 +- 热锅,加入 15 ml 食用油,大火烧热。 +- 放入 蒜片,快速煸炒出香味。 +- 放入 焯好水的 花菜 朵,转中大火,快速翻炒约 **2 分钟**,使花菜均匀受热。 +- 加入 3 g 盐,继续翻炒均匀。 +- 沿锅边淋入 50 ml 饮用水,盖上锅盖,焖 **1 分钟**,帮助花菜完全熟透入味。 +- 开盖,快速翻炒均匀,即可出锅。 + +## 附加内容 + +- 提前将花菜焯水可以缩短炒制时间,并使花菜更容易熟透。 +- 炒制时间可以根据个人喜欢的花菜软硬程度调整。喜欢脆一些可以缩短时间。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/清蒸南瓜.md b/data/C8/cook/dishes/vegetable_dish/清蒸南瓜.md new file mode 100644 index 0000000..3b580d9 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/清蒸南瓜.md @@ -0,0 +1,35 @@ +# 清蒸南瓜的做法 + +清蒸南瓜是一道制作极其简单的家常甜点或主食。它最大程度地保留了南瓜本身的天然甜味和营养,口感软糯。是健康饮食的不错选择。一般初学者只需要 15-20 分钟即可完成(主要为蒸的时间)。 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 南瓜 +- 蒸锅 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1-2 个人吃。 + +每份: + +- 南瓜 300 g +- 饮用水 1000 ml (用于蒸锅) + +## 操作 + +- 将 南瓜 外皮洗净,去除瓜瓤和籽。 +- 将 南瓜 切成厚度大约 2 cm 的片,备用。 +- 在 蒸锅 的锅中加入 1000 ml 饮用水。 +- 将切好的 南瓜 片均匀摆放在盘中。 +- 待蒸锅中的水烧开后,将装有 南瓜 的盘子放入蒸锅中。 +- 盖上锅盖,保持大火蒸 **15-20 分钟**,直至南瓜变软,可以用筷子轻松穿透。 +- 关火,小心取出盘子。 + +## 附加内容 + +- 南瓜的品种不同,甜度和口感会有差异。老南瓜通常更甜更面。 +- 南瓜皮含有营养,如果喜欢也可以不去皮蒸,但需要彻底洗净。 +- 蒸的时间取决于南瓜块的大小和厚度,以及南瓜的品种。用筷子测试是判断是否蒸熟的好方法。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/炒滑蛋/炒滑蛋.jpg b/data/C8/cook/dishes/vegetable_dish/炒滑蛋/炒滑蛋.jpg new file mode 100644 index 0000000..70b390b --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/炒滑蛋/炒滑蛋.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eccfab321e696eeb125a545a06a29727f2608897f464a55ea8b89431a89b5ca4 +size 121836 diff --git a/data/C8/cook/dishes/vegetable_dish/炒滑蛋/炒滑蛋.md b/data/C8/cook/dishes/vegetable_dish/炒滑蛋/炒滑蛋.md new file mode 100644 index 0000000..cd493bc --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/炒滑蛋/炒滑蛋.md @@ -0,0 +1,36 @@ +# 炒滑蛋的做法 + +![炒滑蛋成品](./炒滑蛋.jpg) + +炒滑蛋是一道简单易做的菜。一般初学者只需要 5 分钟即可完成。 + +预估烹饪难度:★ + +## 必备原料和工具 + +- 鸡蛋(最好是无菌蛋) +- 牛奶 + +## 计算 + +每份: + +- 鸡蛋 4 颗 +- 牛奶 30ml +- 食用油 10ml + +## 操作 + +- 鸡蛋加入牛奶以及 5ml 食用油搅拌均匀,备用 +- 大火烧热平底锅约 30s, 加入 5ml 食用油 +- 烧 30s 转小火, 并且放入搅拌好的鸡蛋 +- 在锅中静置 5 秒后,用锅铲将蛋液从边缘缓慢推向中间 +- 翻炒至鸡蛋大致凝固后关火,装盘 + +## 附加内容 + +- 最后可根据个人口味撒些黑胡椒或者盐来调味。 + +参考资料 + +- [甜琛廚房](http://sweetheartkitchen.com/recipes/scrambled-egg/) \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/炒茄子.md b/data/C8/cook/dishes/vegetable_dish/炒茄子.md new file mode 100644 index 0000000..d26390c --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/炒茄子.md @@ -0,0 +1,49 @@ +# 炒茄子的做法 + +家常炒茄子,简单易学,原料不复杂,其中可选项有无皆可。(但是八角强烈推荐) + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 茄子 +- 八角(可选) +- 虾皮(可选) +- 香葱(可选) +- 酱油 +- 菜籽油或花生油 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1-2 个人食用 + +总量: + +- 茄子数量 = 份数 * 1.8 个 +- 八角 = 份数 * 1 个 +- 虾皮 = 份数 * 正常男子手抓半把 +- 香葱 = 份数 * 2 颗 +- 酱油 = 份数 * 40 ml + +> 注:油、酱油这俩种材料在操作中也有体现,大家可以交叉对比来确定添加材料的数量 + +## 操作 + +- 将茄子洗净,一刀分为两段(竖切)。每段的茄子切菱形块,将切好的茄子放入碗中待命。 +- 将香葱洗净,并切成葱花放到案板上待命。 +- 切好八角,放到案板上待命。 +- 开火热锅,直至锅内没有水。 +- 往锅内倒食用油,没过锅底的两倍(油可以多加,但不可少加)。 +- 热油约 6 成熟,放入八角、虾皮、香葱这三种可选性材料。 +- 如果没有八角等可选材料,热油至 9 成熟。 +- 待锅内的油到 9 成熟,将碗中的茄子倒入锅内用锅铲进行翻炒。 +- 翻炒约 40 秒,将锅铲悬空,与锅平行,把酱油倒入锅铲内。一人约 2.5 锅铲(酱油可以少加,但不可多加,会咸) +- 继续进行翻炒。 +- 等到锅内所有茄子变色且变软时捞出。 + +## 附加内容 + +- 因为酱油的缘故,所以本菜不必加盐。出锅之前可以尝一下,如果不咸可以加微量的盐,下次炒时酱油量要增加 +- 如果加了虾皮,可以将酱油量酌情减少。 +- 炒本菜时,一直大火即可。 +- 切忌!一定不可加水,会变成水煮茄子,口感差,所以油可多放,不可少放。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/炒青菜.md b/data/C8/cook/dishes/vegetable_dish/炒青菜.md new file mode 100644 index 0000000..a697205 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/炒青菜.md @@ -0,0 +1,34 @@ +# 炒青菜的做法 + +制作简单方便。预计 10 分钟即可完成。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 青菜 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +- 青菜 100g * 份数 +- 食用油 10-15ml(覆盖锅底即可) +- 食盐 2g * 份数 +- 饮用水 70ml * 份数 +- 白糖 5g * 份数 + +## 操作 + +- 青菜掰成小瓣,用清水洗净,备用。 +- 中火或大火热锅后,锅内放入 10-15ml 食用油。再等待 30 秒让油温升高。 +- 将准备好的青菜倒入锅中,翻炒至青菜变软(约 1 分钟)。 +- 倒入计算好的清水,水位应当完全浸润或即将没过青菜,加入食盐 (2g * 份数),继续翻炒约 1 分钟。 +- 最后加入白糖小火加热 2 分钟,加热时盖上锅盖。 +- 盛盘。 + +## 附加内容 + +加入白糖,会让青菜颜色更绿。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/烤茄子/烤茄子.jpg b/data/C8/cook/dishes/vegetable_dish/烤茄子/烤茄子.jpg new file mode 100644 index 0000000..f026db8 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/烤茄子/烤茄子.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbcd0f7e77233ea8965f977d18b266999db5ba96d1ecb230d16767eba51128c2 +size 812441 diff --git a/data/C8/cook/dishes/vegetable_dish/烤茄子/烤茄子.md b/data/C8/cook/dishes/vegetable_dish/烤茄子/烤茄子.md new file mode 100644 index 0000000..2fb28a8 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/烤茄子/烤茄子.md @@ -0,0 +1,53 @@ +# 烤茄子的做法 + +非常简单方便,而且香极了 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 茄子 +- 食用油 +- 酱油(生抽) +- 蒜蓉 +- 辣椒 +- 孜然 +- 食用盐 + +## 计算 + +按照两个人的份量: + +- 茄子 1 个 (大约 200g) +- 食用油 20-30 毫升 +- 酱油 4-6 克 +- 小米椒 1 个 (大约 20g) +- 蒜蓉 3-4 瓣 +- 孜然 1-3 克 +- 食用盐 0.5-2 克 + +## 操作 + +- 将酱油、孜然、食用盐、蒜蓉和切碎的小米椒置于碗中,均匀搅拌备用 +- 茄子洗净,用纸巾擦干表面的水分 +- 用叉子在茄子的一侧扎 4-8 下 +- 使用 15-25ml 的食用油涂满茄子表面 +- 将烤箱温度设置为 200℃ (打开烤箱风扇 大火),预热 2 分钟 +- 将茄子放入烤箱中层或者上层,烤制 12-15 分钟 (茄子表面有褶皱,且能按压 0.3-0.5cm 的深度即可) +- 取出茄子,用刀茄子上竖着划一个口子。口子居中,上下距 1-1.5cm +- 用小刀或者叉子伸入口子,竖着切割茄子内部 +- 将口子微微掰开,倒入第一步准备的酱料 +- 再次将茄子放入烤箱,将烤箱温度设置为 200℃ ,烤制 4-7 分钟 +- 取出,关闭烤箱电源 + +## 附加内容 + +最终成品和楼下烧烤摊的烤茄子差不多,太香了! + +**注意事项:** +茄子表面有水分、未涂满食用油或未使用叉子扎孔可能导致**茄子在烤制的过程中爆裂** + +**可以改进的环节:** +第一次用刀划口子的时候,可以直接将茄子竖直切成两半,然后切割出纹路后涂抹上酱料 + +![示例菜成品](./烤茄子.jpg) \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/白灼菜心/白灼菜心.jpg b/data/C8/cook/dishes/vegetable_dish/白灼菜心/白灼菜心.jpg new file mode 100644 index 0000000..a29b6c9 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/白灼菜心/白灼菜心.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0804b87406411d2e0e80ee184cc4a4441119659da8aed12f6e8e7e8eb9d29975 +size 36300 diff --git a/data/C8/cook/dishes/vegetable_dish/白灼菜心/白灼菜心.md b/data/C8/cook/dishes/vegetable_dish/白灼菜心/白灼菜心.md new file mode 100644 index 0000000..e25cb39 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/白灼菜心/白灼菜心.md @@ -0,0 +1,54 @@ +# 白灼菜心的做法 + + + +![白灼菜心](./白灼菜心.jpg) + +> 没有拍照,上图是网图,不过做出来都差不多啦 + +白灼菜心是经典粤菜,白灼是粤菜的一种烹饪技法,用煮沸的水或汤将生的食物烫熟,称为白灼。这种烹饪手法能保持原有的鲜味,粤菜常用此法烹制虾和蔬菜。 + +总之吧,减肥或者是**快速解决绿叶菜的绝佳方式**。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 新鲜菜心 +- 生抽、蚝油、盐 +- 大蒜、小米辣 +- 食用油 + +## 计算 + +如下的量两个人够吃,一个人吃直接搭配个米饭也可以的。 + +- 新鲜菜心 250g +- 食用油 10g +- 调一个灵魂料汁儿 + - 生抽 5g + - 蚝油 5g + - 盐、糖 5g +- 大蒜四五瓣、小米辣一两根 + +## 操作 + +1. 菜心洗净,**去除根部比较硬或老的地方**。此处还用刀刮了**刮菜心根茎部分**,刮掉外面那层比较硬的,菜心内部更可口,但要注意根茎白灼时长,时间太长的话根茎不脆了 + +2. 大蒜切成蒜末,有洋葱顺便加了点洋葱 + +3. 调制灵魂料汁:生抽 5g 吧、蚝油 5g,加 3g 糖和 100g 清水半碗成一碗汁儿 + >如果要是加淀粉,汤汁儿煮沸后更容易挂在菜心上,味道会更重一些,广东人可能吃不惯 + +4. 一锅 500ml 清水加 5g 盐和 10g 食用油烧开 + +5. 将菜心根茎在沸水中烫 1 分钟,直到根茎颜色变成深绿。再将整个菜心放到锅中烫熟 1 分钟,捞起来码入盘中 + +6. 开另一小锅将兑好的料汁倒入,小火烧开,放入一半的蒜末,一点点姜丝和小米椒碎。在制作时加了一点点洋葱碎和大蒜,先在锅底倒油,五成热后倒入蒜末、洋葱,稍稍爆香后再加入料汁,加入小米辣煮开 + +7. 料汁稍微收汁,煮沸后稍等十来秒吧,后直接浇在菜心上,不要特别多,但蒜末还是很给力的不要少蒜 + +## 附加内容 + +- 选择菜心一定要比较新鲜!新鲜! +- 锅内烧清水要加油和盐 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/糖拌西红柿/火山飘雪.jpg b/data/C8/cook/dishes/vegetable_dish/糖拌西红柿/火山飘雪.jpg new file mode 100644 index 0000000..c189b54 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/糖拌西红柿/火山飘雪.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2b44e97983bb12bfeff14ebc7ca9c4f0fe945f8bf1d88c134d4ea1ca1b2f8b68 +size 55379 diff --git a/data/C8/cook/dishes/vegetable_dish/糖拌西红柿/糖拌西红柿.md b/data/C8/cook/dishes/vegetable_dish/糖拌西红柿/糖拌西红柿.md new file mode 100644 index 0000000..416f552 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/糖拌西红柿/糖拌西红柿.md @@ -0,0 +1,37 @@ +# 糖拌西红柿的做法 + +![示例菜成品](./火山飘雪.jpg) + +新鲜可口,制作简便,营养价值高,适合夏季食用,家庭餐桌上的一道美味凉菜。西红柿含有大量的维生素 C, 做法简单 几分钟就可完成。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 西红柿 +- 白砂糖 +- 冰箱 + +## 计算 + +一份正好够 2 人吃。 + +每份: + +- 西红柿 2 个(每个西红柿约 100g,共 200g) +- 白砂糖 20g + +## 操作 + +- 用刀将西红柿皮米字型划开 +- 用筷子插入西红柿的菊花,在燃气上转动烤 10 秒(或用开水冲 30 秒),直到西红柿皮卷边 +- 把西红柿的衣服脱光 +- 再西红柿大卸八块(沿纹路切可以更多的留汁水),去掉头部根蒂部,备用 +- 全部切好后,将西红柿在盘子中均匀码一层 +- 撒上白糖,重复上面一步直到全部西红柿放完 +- 放入冰箱冷藏 10 分钟 +- 一盘糖拌西红柿就好了,营养美味,酸甜爽口,夏日解暑又解腻 + +## 附加内容 + +在制作过程中 请您小心使用刀具。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/素炒豆角.md b/data/C8/cook/dishes/vegetable_dish/素炒豆角.md new file mode 100644 index 0000000..4dce00d --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/素炒豆角.md @@ -0,0 +1,46 @@ +# 素炒豆角的做法 + +巨下饭的家常菜 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 豆角 +- 小米椒 +- 葱 +- 蒜 +- 生抽 +- 老抽 +- 耗油 +- 盐 + +## 计算 + +注意,受食材个体影响,本菜谱为 2 人份菜谱 + +- 豆角 250g +- 小米椒 2 个 +- 葱 3 圈 +- 蒜 2 颗 +- 生抽 6ml +- 老抽 2ml +- 耗油 6ml +- 盐 6g + +## 操作 + +- 葱切花,蒜切沫,备用。 +- 生抽、老抽、耗油、盐混合调料汁,备用。 +- 小米椒切圈,备用。 +- 豆角去筋,45° 斜切*4-10cm*小段,备用。 +- 起锅烧油(10ml - 15ml),冒烟后放入葱、小米椒,翻炒至闻到香味; +- 加入豆角,翻炒*30s*, +- 加入料汁,开大火翻炒*2分钟* +- 倒入 150ml 水 +- 转中小火,盖上锅盖焖制 8-10 分钟 +- 加入蒜切沫,出锅。 + +## 附加内容 + +- 切豆角需要一定的刀工,不会的可以使用剪刀 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/红烧冬瓜/1.jpeg b/data/C8/cook/dishes/vegetable_dish/红烧冬瓜/1.jpeg new file mode 100644 index 0000000..af9564a --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/红烧冬瓜/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c8e572ae96824daa8ad99f9eba684266304dc4d61a75cf35da61b384f6821b57 +size 86396 diff --git a/data/C8/cook/dishes/vegetable_dish/红烧冬瓜/2.jpeg b/data/C8/cook/dishes/vegetable_dish/红烧冬瓜/2.jpeg new file mode 100644 index 0000000..8d4499d --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/红烧冬瓜/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94a93b388d330a5db25aadefa6547c92199e47fa16f48f58c0e6a44bca02e494 +size 104810 diff --git a/data/C8/cook/dishes/vegetable_dish/红烧冬瓜/红烧冬瓜.md b/data/C8/cook/dishes/vegetable_dish/红烧冬瓜/红烧冬瓜.md new file mode 100644 index 0000000..80a09dd --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/红烧冬瓜/红烧冬瓜.md @@ -0,0 +1,49 @@ +# 红烧冬瓜的做法 + +红烧冬瓜是一道具有色泽红亮,香鲜味美、营养价值丰富的家常菜 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 冬瓜 +* 食用油 +* 料酒 +* 淀粉 +* 生抽 +* 老抽 +* 鸡精 +* 香葱 +* 姜末 +* 蚝油 + +## 计算 + +每份: + +* 冬瓜 300 g +* 食用油 50 ml +* 料酒 2 ml +* 淀粉 10 g +* 生抽 10 ml +* 老抽 15 ml +* 鸡精 3 g +* 香葱 0.5 根 +* 姜末 1 粒 +* 蚝油 15 ml + +## 操作 + +* 冬瓜去皮,切 边长不超过 2cm 小块 +* 起锅烧油,放入冬瓜,缓缓翻滚煎炸 2 分钟 ,直至冬瓜表面泛金黄色 +* 取出冬瓜,放入大碗备用 +* 利用锅中的剩余油,依次放入姜末、生抽、蚝油,翻炒 15 S +* 重新倒入冬瓜,翻炒 30 S 后,加入开水,水要没过冬瓜表面,大火煮 10 分钟 +* 加入老抽上色,继续煮,直至冬瓜软糯(筷子可以轻松插近冬瓜) +* 加入鸡精、料酒、香葱翻炒后 30 S, 取出冬瓜到大碗中 +* 锅中剩余汤汁保留,倒入水淀粉,煮开后汤汁浇灌在冬瓜表面 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/红烧茄子.md b/data/C8/cook/dishes/vegetable_dish/红烧茄子.md new file mode 100644 index 0000000..954b231 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/红烧茄子.md @@ -0,0 +1,54 @@ +# 红烧茄子的做法 + +预估烹饪难度:★★★★ + +## 必备原料和工具 + +- 大蒜 +- 大葱 +- 青辣椒 +- 洋葱 +- 西红柿 +- 青茄子 +- 盐 +- 酱油 +- 鸡蛋 +- 面粉 +- 淀粉 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人食用 + +总量: + +- 青茄子的数量 = 份数 * 0.7 个 +- 青辣椒 = 份数 * 0.5 个 +- 洋葱 = 份数 * 0.3 个 +- 西红柿 = 1 个 +- 大葱 = 半颗 +- 大蒜 = 3 瓣 +- 鸡蛋 = 1 个 +- 面粉 = 青茄子数量 * 150 克 +- 淀粉 = 面粉 / 4 克 +- 酱油 = 茄子数量 * 7 克(向上取整) + +## 操作 + +1. 青茄子、青辣椒、西红柿、洋葱、大葱洗净。 +1. 大葱切 5 毫米宽的葱花,大蒜扒皮并拍碎,西红柿切 6 立方厘米的块,青辣椒、洋葱切 5g 的块。 +1. 茄子切菱形块(先切 2 公分厚的片,然后再把片切成 2 公分的条,最后斜刀切块儿...)。 +1. 将面粉倒入盆中,依次加入少量水,搅拌均匀,呈粘稠糊状。 +1. 加入淀粉,加入 30 克水,搅拌均匀。 +1. 将鸡蛋打到盆中,加入(面粉 / 20)克的盐,搅拌均匀。 +1. 将茄块倒入面糊中,搅拌使茄块的每一面都能沾上面糊。 +1. 开大火,热锅,加入 500 毫升的油,当能看到锅里的油冒出一丝烟时,调至小火,将茄块用筷子夹入到油锅,待所有的茄块下锅之后,调至中火,直到茄块变金黄色时捞出,将油倒出。 +1. 加入(份数 * 5)g 的油,放入大蒜、葱花,翻炒 15 秒,放入青辣椒块翻炒 30 秒,放入西红柿翻炒 30 秒。 +1. 放入炸好的茄块,加水面高度为锅内食材的 0.8 倍。 +1. 放入酱油和(份数 * 3)g 的盐。 +1. 等待,直到汤汁呈粘稠状(水位大概为剩余食材高度的 0.2-0.3 倍),开盖,盛出菜,关火。 + +## 附加内容 + +在操作的第 4-6 步骤中要注意: +一定要顺序执行,否则会有灾难性错误...... \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/脆皮豆腐.md b/data/C8/cook/dishes/vegetable_dish/脆皮豆腐.md new file mode 100644 index 0000000..f477464 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/脆皮豆腐.md @@ -0,0 +1,41 @@ +# 脆皮豆腐的做法 + +浓郁的酱汁裹满豆腐,吃一口就停不下来,别提有多好吃。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 老豆腐 +- 鸡蛋 +- 生抽 +- 老抽 +- 蚝油 +- 白糖 +- 玉米淀粉 +- 平底锅 + +## 计算 + +每份: + +- 老豆腐 1 块 (市场买 1.25 格 * 人) +- 鸡蛋 2 只 * 老豆腐块数 +- 玉米淀粉 50 g * 老豆腐块数 +- 生抽 20 g +- 蚝油 10 g +- 老抽 5 g +- 白糖 10 g + +## 操作 + +- 鸡蛋搅拌形成蛋液放置备用 +- 配置酱料 (20 g 生抽+10 g 蚝油+5 g 老抽+10 g 白糖+10 g 玉米淀粉+200 ml 清水) +- 老豆腐切片 (个人建议,仅供参考 人 * 5 片,厚度 1.2 cm) +- 玉米淀粉倒入盘中,将老豆腐片粘上淀粉后,粘上蛋液,放置一旁 +- 热锅,锅内放入 18ml 食用油。等待 10 秒让油温升高 +- 将粘上蛋液的老豆腐片均匀放入锅中,铺好锅底,小火煎至金黄翻面 +- 待两面煎至金黄后,倒入酱料,让每块豆腐都沐浴在酱料中,大火 3 分钟至酱汁浓稠 +- 关火 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/芹菜拌茶树菇/芹菜拌茶树菇.jpg b/data/C8/cook/dishes/vegetable_dish/芹菜拌茶树菇/芹菜拌茶树菇.jpg new file mode 100644 index 0000000..c75f7c9 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/芹菜拌茶树菇/芹菜拌茶树菇.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa799bb252bae7476c1670a6b8be58247b305e8466776cb43abbf7252cabc5e1 +size 553839 diff --git a/data/C8/cook/dishes/vegetable_dish/芹菜拌茶树菇/芹菜拌茶树菇.md b/data/C8/cook/dishes/vegetable_dish/芹菜拌茶树菇/芹菜拌茶树菇.md new file mode 100644 index 0000000..1b74aed --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/芹菜拌茶树菇/芹菜拌茶树菇.md @@ -0,0 +1,48 @@ +# 芹菜拌茶树菇的做法 + +![芹菜拌茶树菇成品](./芹菜拌茶树菇.jpg) +![闽星茶树菇](./闽星茶树菇.jpg) + +芹菜拌茶树菇是一道简单易做的凉拌菜。富含多种人体所需的维生素和矿物质。一般初学者只需要 30 分钟即可完成。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 闽星茶树菇 +- 芹菜 +- 香油 +- 蚝油 +- 味极鲜 +- 食用盐 + +## 计算 + +每次制作前需要确定计划做几份。一份可够 1-2 人。 + +每份: + +- 闽星茶树菇 1 瓶 +- 芹菜 250-300g(推荐 30cm 高的芹菜苗,没有芹菜苗可以用山芹或芹菜代替但是需要稍微焯水断生) +- 香油 5ml +- 蚝油 大约 7ml +- 味极鲜 3ml +- 食用盐 大约 2g + +## 操作 + +- (如果是芹菜苗这一步略过)用热水壶烧一壶热水,备用 +- 新鲜的芹菜苗或者芹菜摘去黄叶清洗,备用 +- (如果是芹菜苗这一步略过)将芹菜摘去叶子单独放一个盆中,将芹菜茎用刀划成 2-3 毫米宽的芹菜条备用,这一步的目的是让芹菜断生的更快更均匀,吃起来更脆更爽口 +- 芹菜苗切成 4cm 的芹菜段,备用 +- (如果是芹菜苗这一步略过)起锅开火,将热水壶的开水倒入锅中待水起泡沸腾 +- (如果是芹菜苗这一步略过)将切好的芹菜条放入锅中焯水,大约 20 秒放入芹菜叶,5 秒后关火全部捞出过凉水,备用 +- 将盆中焯好的芹菜或者芹菜苗撒上准备好的食盐,香油,耗油和味极鲜搅拌均匀 +- 将茶树菇倒入盆中搅拌均匀 +- 装盘 +- 开吃 + +## 附加内容 + +- 焯水时的水位需要没过芹菜 +- 芹菜叶太老太硬的话可以不要 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/芹菜拌茶树菇/闽星茶树菇.jpg b/data/C8/cook/dishes/vegetable_dish/芹菜拌茶树菇/闽星茶树菇.jpg new file mode 100644 index 0000000..b9e865f --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/芹菜拌茶树菇/闽星茶树菇.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8a383a37a316eadb128398a233610cfde68b744d35b6fa177021f05d7d8726f +size 143519 diff --git a/data/C8/cook/dishes/vegetable_dish/茄子炖土豆.md b/data/C8/cook/dishes/vegetable_dish/茄子炖土豆.md new file mode 100644 index 0000000..04d5b7c --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/茄子炖土豆.md @@ -0,0 +1,46 @@ +# 茄子炖土豆的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 茄子 +- 土豆 +- 肉 +- 辣椒(是青辣椒,而**不是辣椒面或辣椒油**) +- 酱油 +- 盐 +- 蒜 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2-3 个人食用 + +总量: + +- 茄子的数量 = 份数 * 1 个 (每个茄子约 150g) +- 土豆数量 = 份数 * 1 个(每个土豆约 150g) +- 肉量 = 份数 * 180 克 +- 酱油量 = 份数 * 15 毫升 +- 盐量 = 份数 * 5 克 +- 辣椒量 = 50 克(调味,所以无论多少人都放这些。) +- 蒜量 = 3 瓣(调味,所以无论多少人都放这些。注意是里面的小瓣 3 瓣,而**不是3整头**) + +使用上述条件,计算出计划使用的原材料比例。 + +## 操作 + +1. 将茄子、土豆、辣椒洗净,蒜扒皮并拍碎。 +2. 将茄子、土豆切成约 6 立方厘米的块,辣椒切成 5 克的小块,肉切成 3 厘米的丝。 +3. 开火,热锅,加入份数 * 13 毫升的油。 +4. 当能看到锅里的油冒出一丝烟时,放入辣椒。 +5. 煸出辣椒香气后,立刻放入肉,用铲子翻炒 30 秒。 +6. 放入土豆,翻炒 30 秒。 +7. 放入茄子,翻炒 30 秒。 +8. 放入酱油和盐,继续翻炒 5 分钟。 +9. 加入水,水面高度为锅内食材高度的 0.9 倍,并盖上锅盖。 +10. 等待,直到锅内水的高度剩余食材高度的 0.1 倍时,开盖,放入蒜,搅拌均匀,关火。 + +## 附加内容 + +在操作的第 5-7 步骤中要注意:在此过程中注意锅底如果没有液体(油或水),则加 5 毫升的水再继续翻炒。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/1.jpeg b/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/1.jpeg new file mode 100644 index 0000000..e2437c0 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:911b1aa6deb8f8a4d840fa23f648c064a2365b3d6e578c328f8310db4043cbb5 +size 234352 diff --git a/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/2.jpeg b/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/2.jpeg new file mode 100644 index 0000000..23b7dd7 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48f8e719b85d347a47fa433293822c94bbffcfaf57a22372dbca74ebb1ece6e3 +size 281002 diff --git a/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/3.jpeg b/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/3.jpeg new file mode 100644 index 0000000..9ca64d8 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/3.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e1477bcb437812d0d8ed3ebe44961f88275f9f2eca4b4e38fb12652f5195f86 +size 217623 diff --git a/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/莴笋叶煎饼.md b/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/莴笋叶煎饼.md new file mode 100644 index 0000000..9d32a57 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/莴笋叶煎饼/莴笋叶煎饼.md @@ -0,0 +1,40 @@ +# 莴笋叶煎饼的做法 + +莴笋叶煎饼营养、好吃 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 莴笋叶 +* 鸡蛋 +* 食用油 +* 生抽 +* 淀粉 +* 鸡精 + +## 计算 + +每份: + +* 莴笋叶 50 g +* 鸡蛋 2 个 +* 食用油 30 ml +* 生抽 5 ml +* 淀粉 15 g +* 鸡精 2 g + +## 操作 + +* 莴笋叶剁碎,加入鸡蛋、生粉、生抽、鸡精搅拌均匀备用 +* 起锅烧油,倒入莴笋叶浆汁,均匀平铺在锅面上 +* 第一面炸 120 S 后,翻面再炸 60 S 后出锅 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) +![示例菜成品](./3.jpeg) + +## 附加内容 + +* 选择莴笋叶是某省市买到的蔬菜包基本都包含莴笋,可以换成韭菜等 +* 莴笋叶直接焯水后凉拌有苦味,所以选择做成煎饼的配菜 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/菠菜炒鸡蛋/菠菜炒鸡蛋.jpg b/data/C8/cook/dishes/vegetable_dish/菠菜炒鸡蛋/菠菜炒鸡蛋.jpg new file mode 100644 index 0000000..23206ec --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/菠菜炒鸡蛋/菠菜炒鸡蛋.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3639de4c3efd641ab6f1c1a9ccaf99ec3072243f4c068606f7c7e18046ff36d7 +size 355731 diff --git a/data/C8/cook/dishes/vegetable_dish/菠菜炒鸡蛋/菠菜炒鸡蛋.md b/data/C8/cook/dishes/vegetable_dish/菠菜炒鸡蛋/菠菜炒鸡蛋.md new file mode 100644 index 0000000..e990cb9 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/菠菜炒鸡蛋/菠菜炒鸡蛋.md @@ -0,0 +1,36 @@ +# 菠菜炒鸡蛋的做法 + +这道菜难度系数简单,营养丰富。 + +![示例菜成品](./菠菜炒鸡蛋.jpg) + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 菠菜 +- 鸡蛋 +- 食用油 +- 食用盐 + +## 计算 + +按照 1 人的份量: + +- 菠菜 350g +- 鸡蛋 2 个 +- 食用油 15ml +- 食用盐 5g + +## 操作 + +- 菠菜去根,洗净,放在篮子里,焯水 +- 将鸡蛋打入碗中,搅匀 +- 热锅,加入 10ml 油 +- 油热后,倒入鸡蛋液,中火翻炒 15 秒,先煎成蛋饼,然后再用锅铲切成小块 +- 关火,将鸡蛋块 盛到盘子中,不要洗锅 +- 重新开火,倒入 5ml 油,油热后,放入菠菜,大火 翻炒 15 秒后,倒入鸡蛋块,翻炒均匀 +- 加入 5g 盐、100ml 饮用水,大火 翻炒 10 秒 +- 关火,盛盘 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/葱煎豆腐.md b/data/C8/cook/dishes/vegetable_dish/葱煎豆腐.md new file mode 100644 index 0000000..fc61164 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/葱煎豆腐.md @@ -0,0 +1,40 @@ +# 葱煎豆腐的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 白豆腐 +- 葱 +- 青辣椒 +- 盐 +- 鸡精 +- 平底锅 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用。 + +总量: + +- 白豆腐的数量 = 份数 * 0.8 向上取整。 +- 辣椒的数量 = 1.5 只/三人。 +- 葱的数量 = 2 根/三人。 +- 盐量 = 份数 * 3g。 +- 鸡精量 = 份数 * 1.5g。 + +使用上述条件,计算出计划使用的原材料比例,依口味调整。 + +## 操作 + +* 豆腐洗净。切约 5 mm 厚度,置于碟中。 +* 葱洗净,除去根部,切成葱花,备用。 +* 辣椒洗净,切开,去籽,切成 1cm * 1cm 状,备用、 +* 热锅,加入份数 * 9ml 油。 +* 油入锅后,使其均匀布于锅底,均匀放入豆腐,小火煎至金黄翻面。 +* 待两面金黄,盛入碟中备用。 +* 补油至覆盖锅底,倒入辣椒大火翻炒,并铲碾 3 分钟。 +* 倒入豆腐,翻炒,加入盐与鸡精,中火翻炒 1 分钟后倒入 10 ML 水,大火收汁。 +* 出锅前撒上之前计算好的葱花,起锅盛盘。 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/蒜蓉空心菜/1.JPG b/data/C8/cook/dishes/vegetable_dish/蒜蓉空心菜/1.JPG new file mode 100644 index 0000000..2eaf5ab Binary files /dev/null and b/data/C8/cook/dishes/vegetable_dish/蒜蓉空心菜/1.JPG differ diff --git a/data/C8/cook/dishes/vegetable_dish/蒜蓉空心菜/蒜蓉空心菜.md b/data/C8/cook/dishes/vegetable_dish/蒜蓉空心菜/蒜蓉空心菜.md new file mode 100644 index 0000000..be7a30b --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/蒜蓉空心菜/蒜蓉空心菜.md @@ -0,0 +1,44 @@ +# 蒜蓉空心菜的做法 + +背景: + +曾经去学校附近的川菜馆吃过蒜蓉空心菜,之后就一直很喜欢吃。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 空心菜 +* 蒜末 +* 盐 +* 生抽 +* 筷子 +* 铲子 + +## 计算 + +每份: + +* 新鲜空心菜 250 g +* 大蒜半个,切碎为蒜末 +* 食用油 45 ml +* 盐 2 g +* 白糖 3 g +* 生抽 8 ml + +## 操作 + +* 空心菜洗净,去掉烂叶或者老梗,均匀切成 2 段或者 3 段(防止过长不好炒) +* 锅里先倒少量油,烧至微微冒烟,此时拿起锅将国内的热油向四周浸润,让油均匀覆盖锅底,然后再倒入剩余的油([热锅凉油法](https://cook.aiursoft.cn/tips/learn/%E5%AD%A6%E4%B9%A0%E7%82%92%E4%B8%8E%E7%85%8E/?h=%E7%83%AD%E9%94%85#_5))。 +* 放入蒜末,小火炒 10 到 15 秒煸香 +* 尽快均匀地放入空心菜,**开大火**,左手拿铲子,右手拿筷子,配合将空心菜不停翻动,**直至软化变绿**。 +* 接着不需使用筷子,而是使用铲子快速翻炒已软化的空心菜 15 - 20 秒,使之受热更均匀,撒入盐 2 g ,白糖 3 g,生抽 8 ml。 +* 继续大火翻炒 10 秒,即可出锅。 + +![示例菜成品](./1.JPG) + +## 附加内容 + +* 空心菜尽量选择新鲜,鲜嫩的,否则炒出来口感可能会比较老 +* 实际放入空心菜的量可以根据锅的大小决定,建议不超过一个锅,否则太多的话开始的翻动阶段和后续的翻炒,容易掉出少量空心菜到灶台 +* 炒空心菜时,一定要**开大火**,这样空心菜才能快速变软的同时保持脆嫩的口感,大火也有利于炒出生抽的香味。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/蒜蓉西兰花.md b/data/C8/cook/dishes/vegetable_dish/蒜蓉西兰花.md new file mode 100644 index 0000000..57a9a35 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/蒜蓉西兰花.md @@ -0,0 +1,40 @@ +# 蒜蓉西兰花的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 西兰花 1 个 +- 大蒜 3-4 瓣 +- 生抽 +- 蚝油 +- 白糖 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 2 个人吃。 + +每份: + +- 西兰花 约 200 g (约 1/2 中等大小的西兰花) +- 大蒜 3-4 瓣 +- 生抽 10 ml +- 蚝油 5 ml +- 白糖 2 g + +## 操作 + +- 将 西兰花 切成小朵,清洗干净。 +- 将 大蒜 去皮,切成蒜末,备用。 +- 锅中加入 1000 ml 饮用水,大火烧开。 +- 放入 西兰花,保持大火 **煮 2-3 分钟**,至 西兰花 颜色变翠绿,口感变软。 +- 将 煮好的 西兰花 捞出,沥干水分,摆入盘中,备用。 +- 热锅,加入 10 ml 食用油。油温升高后,放入 大蒜末,小火煸炒出香味。 +- 加入 10 ml 生抽,5 ml 蚝油,2 g 白糖,加入 30 ml 饮用水。 +- 将锅中汤汁烧开。 +- 将烧好的蒜蓉汁 均匀淋在盘中的 西兰花 上。 + +## 附加内容 + +- 焯水时间不宜超过推荐时长,以免影响西兰花的口感和营养。 +- 如果想保留西兰花更脆的口感,可以缩短焯水时间。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/蒲烧茄子.md b/data/C8/cook/dishes/vegetable_dish/蒲烧茄子.md new file mode 100644 index 0000000..f3df4bc --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/蒲烧茄子.md @@ -0,0 +1,49 @@ +# 蒲烧茄子的做法 + +众所皆知,茄子🍆和土豆🥔是两种荤菜。这一道蒲烧茄子,从外观上之于鳗鱼正如`土豆炖.*`中的生姜之于土豆。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 茄子 +- 蒲烧汁 +- 蜂蜜 +- 白糖 +- 生抽 +- 老抽 +- 料酒 +- 水 + +## 计算 + +- 根据锅的类型决策不同量的油 + - 不粘锅:油汇聚成滴后要散布在茄子的面积 + - 铁锅:摊开后油可以刚好覆盖锅底 +- 1 个长的上小下大的茄子(注意不要使用浙茄和圆茄) +- 1 份蒲烧汁 + - 20 ml 蜂蜜 + - 15 ml 白糖 + - 40 ml 生抽 + - 10 ml 老抽 + - 20 ml 料酒 + - 100 ml 水 + +## 操作 + +- 茄子削皮、横着切成两段 +- 蒸 5 分钟 +- 纵向切开,不要切断,在两边切面各划 2~3 刀至可以摊平 +- 煎至两面金黄 +- 往茄子上浇蒲烧汁至没过 1/2 茄子高度 +- 煎至背面上色,翻面 + - 同时收汁,若无法收汁可以加入水淀粉(生粉和水的比例在 1:4 到 1:10 根据收汁情况而定) +- 把剩下的蒲烧汁浇在茄子上 +- 出锅,一份茄子烧蒲烧汁就烧好了 + +## 附加内容 + +- 这个蒲焼き其实很中国,日式的蒲烧其实是烤的。 +- 灵魂其实在于蒲烧汁?也可以买现成的蒲烧汁。 +- 如果觉得腻可以在装盘后撒点切成 2~5 mm 的小葱,颜色搭配上也能不那么单调。 +- 炒茄子(鱼香茄子、酱爆茄子)墙裂推荐浙茄,细长所以切成滚刀块刚刚好,皮很嫩不像这里需要去皮,茄子的味道适中。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/虎皮青椒/虎皮青椒.jpg b/data/C8/cook/dishes/vegetable_dish/虎皮青椒/虎皮青椒.jpg new file mode 100644 index 0000000..2359029 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/虎皮青椒/虎皮青椒.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:095119290d7f953b46452ead44c738cb9c5707d7727a009599e1d916e4287be0 +size 1022689 diff --git a/data/C8/cook/dishes/vegetable_dish/虎皮青椒/虎皮青椒.md b/data/C8/cook/dishes/vegetable_dish/虎皮青椒/虎皮青椒.md new file mode 100644 index 0000000..f1409d2 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/虎皮青椒/虎皮青椒.md @@ -0,0 +1,41 @@ +# 虎皮青椒的做法 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 青椒 +- 大蒜 +- 白糖(灵魂) +- 醋 +- 生抽 +- 盐 +- 砵或者有一定深度的碗 + +## 计算 + +每份: + +- 青椒 5 个,长度在 10-15cm 的最为合适 +- 大蒜 2-3 瓣 +- 油 20ml +- 白糖 15g +- 生抽 15ml +- 香醋 15ml +- 盐 4g + +## 操作 + +- 去掉青椒蒂,用自来水冲洗干净。 +- 青椒切长片,平均一个青椒纵向切成 3-4 片即可。 +- 大蒜去皮,切成碎末,体积在 2mm x 2mm x 2mm 即可。 +- `调料 1`:拿一个小碗倒入 20ml 油,将大蒜末放入其中。 +- `调料 2`:白糖、生抽、醋、盐全部倒入砵(碗)等容器,搅拌。 +- 将 `调料 1` 倒入锅中,开火加热 5 成放入青椒,青椒片不要叠在一起,单独成片放置锅中。 +- 用锅铲不停的按压青椒,合适的时候翻面。 +- 翻炒约 2 分钟,待青椒表皮出现褶皱时,倒入 `调料 2`。 +- 加大火候继续翻炒 30s 后即可出锅盛入盘中。 + +## 附加内容 + +![虎皮青椒](./虎皮青椒.jpg) \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/蚝油三鲜菇/1.jpeg b/data/C8/cook/dishes/vegetable_dish/蚝油三鲜菇/1.jpeg new file mode 100644 index 0000000..877e695 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/蚝油三鲜菇/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d73160bd045a46fc1b5ddf11952d003d8da6139190d0e0497708e8097a7e47cf +size 148582 diff --git a/data/C8/cook/dishes/vegetable_dish/蚝油三鲜菇/2.jpeg b/data/C8/cook/dishes/vegetable_dish/蚝油三鲜菇/2.jpeg new file mode 100644 index 0000000..327d8dc --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/蚝油三鲜菇/2.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99b4ff67e643167cedf9fa102c14b938ebe80ffa0fa5ebbd7e621b0878bb566f +size 154747 diff --git a/data/C8/cook/dishes/vegetable_dish/蚝油三鲜菇/蚝油三鲜菇.md b/data/C8/cook/dishes/vegetable_dish/蚝油三鲜菇/蚝油三鲜菇.md new file mode 100644 index 0000000..8f2afbf --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/蚝油三鲜菇/蚝油三鲜菇.md @@ -0,0 +1,62 @@ +# 蚝油三鲜菇的做法 + +几分钟就能做出的蚝油蘑菇,滑嫩入味鲜美可口,别提多好吃了。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +* 香菇 +* 蟹味菇 +* 白玉菇 +* 小米辣 +* 菜椒 +* 食用油 +* 盐 +* 料酒 +* 淀粉 +* 生抽 +* 鸡精 +* 香葱 +* 姜末 +* 蚝油 +* 西蓝花 + +## 计算 + +每份: + +* 鲜香菇 2 朵 +* 蟹味菇 30 g +* 白玉菇 30 g +* 小米辣 1 根 +* 菜椒 0.5 颗 +* 食用油 10 ml +* 食用盐 5 g +* 料酒 2 ml +* 淀粉 10 g +* 生抽 10 ml +* 鸡精 3 g +* 香葱 0.5 根 +* 姜末 1 粒 +* 蚝油 5 ml +* 开水 350 ml +* 西蓝花 100 g + +## 操作 + +* 蟹味菇、白玉菇 去掉根部泥土,掰散菌朵 +* 香菇切片(每片厚度 0.5-1 cm,厚点相对薄点更有嚼劲) +* 生粉倒入小碗中,加入 50ml 水,搅拌生粉直至融化没有颗粒(即水淀粉)备用 +* 水开,放入西蓝花,清水煮 3 分钟,放入碗中备用 +* 洗锅烧开水,加入 5 g 食用盐,倒入蟹味菇、白玉菇、香菇,水煮 1 分钟 +* 1 分钟后,捞出沥干水分 +* 起锅烧油,待油开始冒小泡,放入姜末、小米辣、菜椒 煸炒 30 S +* 倒入三鲜菇,然后依次倒入生抽、蚝油、鸡精,翻炒均匀后,倒入水淀粉 +* 中火烧干汁,加入料酒、葱花 出锅 +* 摆上西蓝花 + +![示例菜成品](./1.jpeg) +![示例菜成品](./2.jpeg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/蚝油生菜.md b/data/C8/cook/dishes/vegetable_dish/蚝油生菜.md new file mode 100644 index 0000000..6087578 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/蚝油生菜.md @@ -0,0 +1,40 @@ +# 蚝油生菜的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 生菜 +- 蚝油 +- 大蒜 +- 生抽 +- 盐 +- 白糖 +- 食用油 + +## 计算 + +这道菜分量和在川菜馆点的标准分量一样 + +- 生菜 1 棵( 200 g ± 50 ) +- 蚝油 6-8 ml +- 大蒜 4-5 瓣(做成蒜泥或切碎) +- 生抽 6 ml +- 盐 0.5 g +- 白糖 1 g +- 食用油 5-8 ml + +## 操作 + +- 生菜洗净并去掉烂菜叶。 +- 热锅,先放 1 L 清水(凉),然后在锅内放入 2 ml - 3 ml 食用油和 0.5 g 盐,等待锅中的水煮沸。 +- 水沸后,放入生菜,将**每一片**生菜叶都焯水 10 s。 +- 捞出生菜,控干水份,摆盘 。 +- 调汁:将生抽 10 ml 、蚝油 6-8 ml 、盐 0.5 g 、 白糖 1 g 放入碗中调匀,并加入 10-15 ml 清水(凉)搅拌均匀。 +- 再开火,热锅,放入食用油 5-8 ml,油热放入蒜泥。 +- 等待有蒜香飘出,倒入调好的汁,煮沸即可,立马关火。 +- 将锅中的汤汁均匀地**浇**在生菜上。 + +## 附加内容 + +这道菜富含维生素,做法简单,尝起来爽口又不上火。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/西红柿炒鸡蛋.md b/data/C8/cook/dishes/vegetable_dish/西红柿炒鸡蛋.md new file mode 100644 index 0000000..546ea6c --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/西红柿炒鸡蛋.md @@ -0,0 +1,55 @@ +# 西红柿炒鸡蛋的做法 + +西红柿炒蛋是中国家常几乎最常见的一道菜肴。它的原材料易于搜集,制作步骤也较为简单,所以非常适合新厨师上手,是很多人学习做菜时做的第一道菜。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 西红柿 +* 鸡蛋 +* 食用油 +* 盐 +* 糖(可选) +* 葱花(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +* 西红柿 = 1 个(约 180g) * 份数 +* 鸡蛋 = 1.5 个 * 份数,向上取整 +* 食用油 = 4ml * 鸡蛋/个 +* 盐 = 1.5-2g * 份数 +* 糖 = 0-2g * 份数 +* 葱花 = 0-10g * 份数 + +## 操作 + +- 西红柿洗净 +- 可选:去掉西红柿的外表皮 + - 开水烫表皮,然后将西红柿放入冷水,剥去外皮 +- 西红柿去蒂,切成边长不超过 4cm 的小块,即为 `西红柿块` +- 将鸡蛋打入碗中,加入 `1g * 份数` 的盐,搅匀,即为 `鸡蛋液` + - 可以考虑向鸡蛋中加入 1ml 醋,这可以去除腥味,令鸡蛋更蓬松 +- 热锅,加入食用油 +- 油热后,倒入 `鸡蛋液`。翻炒至鸡蛋结为固体且颜色微微发黄,即为 `半熟鸡蛋` +- 关火。将 `半熟鸡蛋` 盛盘,重新开火 + - 注意:不要洗锅 +- 加入 `西红柿块`,锅铲拍打并翻炒 20 秒,或至西红柿软烂 +- 向锅中加入 `半熟鸡蛋`,翻炒均匀 + - 可以考虑加入 10ml 番茄酱和 50ml 清水,增加汤汁 + - 可以额外加入一些其它熟肉和材料 +- 加入剩余的盐、糖(可选,如果倾向于甜味版本)、葱花(可选),翻炒均匀 +- 关火,盛盘 + +## 附加内容 + +这道菜根据不同的口味偏好,存在诸多版本,包括且不限于: + +* 快速做法: + - 直接在有`半熟鸡蛋`的锅中加入 `西红柿块`,与鸡蛋一起翻炒直至西红柿软烂 + - 继续 第 10 步 +* 加入盐 改为 “加入两滴生抽” \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/西红柿豆腐汤羹/1.jpeg b/data/C8/cook/dishes/vegetable_dish/西红柿豆腐汤羹/1.jpeg new file mode 100644 index 0000000..c46e021 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/西红柿豆腐汤羹/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9657a000763f67d20ce7ddf8f80c5d5cdc947f2a9782c25cbd07a72427110e2f +size 105667 diff --git a/data/C8/cook/dishes/vegetable_dish/西红柿豆腐汤羹/西红柿豆腐汤羹.md b/data/C8/cook/dishes/vegetable_dish/西红柿豆腐汤羹/西红柿豆腐汤羹.md new file mode 100644 index 0000000..d60101c --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/西红柿豆腐汤羹/西红柿豆腐汤羹.md @@ -0,0 +1,45 @@ +# 西红柿豆腐汤羹的做法 + +西红柿豆腐汤羹是一道很清淡美味的汤羹 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 西红柿 +* 鸡蛋 +* 豆腐 +* 食用油 +* 盐 +* 淀粉 +* 鸡精 +* 香葱 +* 姜 +* 开水 + +## 计算 + +每份: + +* 西红柿 1 个 +* 鸡蛋 1 个 +* 豆腐 100 g +* 食用油 5 ml +* 盐 2 g +* 淀粉 5 g +* 鸡精 2 g +* 香葱 0.5 根 +* 姜 1 片 +* 开水 350 ml + +## 操作 + +* 西红柿切成小丁、鸡蛋打入碗中搅拌、豆腐切块备用 +* 起锅烧油,放入姜片 5 S 后倒入入西红柿翻炒 30 S +* 锅中加入开水,汤水烧开,60 S 后到入鸡蛋液、豆腐块 +* 汤水重新烧开后,加入水淀粉,沿一个方向搅拌 2 圈 +* 加入鸡精、盐、香葱,30 S 后起锅 + +![示例菜成品](./1.jpeg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/西葫芦炒鸡蛋/西葫芦炒鸡蛋.jpeg b/data/C8/cook/dishes/vegetable_dish/西葫芦炒鸡蛋/西葫芦炒鸡蛋.jpeg new file mode 100644 index 0000000..a687705 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/西葫芦炒鸡蛋/西葫芦炒鸡蛋.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad77e0934f5592d64e357d138f58679c4e92cf5aa907baaa52620c6759b81492 +size 46138 diff --git a/data/C8/cook/dishes/vegetable_dish/西葫芦炒鸡蛋/西葫芦炒鸡蛋.md b/data/C8/cook/dishes/vegetable_dish/西葫芦炒鸡蛋/西葫芦炒鸡蛋.md new file mode 100644 index 0000000..d76951b --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/西葫芦炒鸡蛋/西葫芦炒鸡蛋.md @@ -0,0 +1,39 @@ +# 西葫芦炒鸡蛋的做法 + +![西葫芦炒鸡蛋](./西葫芦炒鸡蛋.jpeg) + +西葫芦炒鸡蛋是一道简单易做的家常菜。简单易购的食材,好吃又下饭。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 西葫芦 +- 鸡蛋 +- 西红柿(可选) +- 食用盐 +- 食用油 + +## 计算 + +按照 2 人的份量: + +- 西葫芦 500g +- 西红柿 100g +- 鸡蛋 3 个 +- 食用油 10-20ml +- 食用盐 6g + +## 操作 + +- 西红柿洗净,切成小块,备用 +- 西葫芦洗净,切成边长约为 4cm 的菱形,备用 +- 打三个鸡蛋到碗里,打散搅匀,备用 +- 热锅,锅内放入 5ml - 10ml 食用油 +- 倒入鸡蛋,保持翻炒至鸡蛋成固体,用锅铲分成小块后盛到碗里,备用 +- 锅内放入 5ml - 10ml 食用油,倒入西红柿,炒至变软 +- 倒入西葫芦一起翻炒均匀,放入 6g 食用盐,将火调小然后**等待 4 - 5 分钟** +- 倒入备用的鸡蛋,中火翻炒 15 秒 +- 关火,盛盘 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/话梅煮毛豆/1.jpeg b/data/C8/cook/dishes/vegetable_dish/话梅煮毛豆/1.jpeg new file mode 100644 index 0000000..02b32d8 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/话梅煮毛豆/1.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:95e3bfffa094e22530e6bb4f29d312391156bc49b71a144fc0271382ab87d09a +size 154361 diff --git a/data/C8/cook/dishes/vegetable_dish/话梅煮毛豆/话梅煮毛豆.md b/data/C8/cook/dishes/vegetable_dish/话梅煮毛豆/话梅煮毛豆.md new file mode 100644 index 0000000..0e133f7 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/话梅煮毛豆/话梅煮毛豆.md @@ -0,0 +1,29 @@ +# 话梅煮毛豆的做法 + +酸甜可口、营养价值高的一种简易美食 + +预估烹饪难度:★★ + +## 必备原料和工具 + +* 毛豆 +* 话梅 +* 食用盐 + +## 计算 + +每份: + +* 毛豆 300 g +* 话梅 6 颗 +* 食用盐 2 g + +## 操作 + +* 清水加入食用盐,毛豆浸泡 15 分钟 +* 加入开水,倒入毛豆、话梅,水煮 20-30 分钟 +* 起锅开吃 + +![示例菜成品](./1.jpeg) + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/酸辣土豆丝.md b/data/C8/cook/dishes/vegetable_dish/酸辣土豆丝.md new file mode 100644 index 0000000..72cf6c9 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/酸辣土豆丝.md @@ -0,0 +1,46 @@ +# 酸辣土豆丝的做法 + +酸辣土豆丝是一道简单易做的菜。色泽光亮,酸辣可口。辅料辣椒富含维生素 C。该菜用料简单,好学易做 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 土豆 +- 大蒜 +- 青椒 +- 红椒 +- 干辣椒 +- 葱 +- 生抽 +- 陈醋 +- 盐 + +## 计算 + +每份: + +- 土豆 240g(越细越长更好) +- 大蒜 4 瓣 +- 青椒 0.5 个 +- 红椒 0.5 个 +- 干辣椒 3 个 +- 葱 1 根 +- 生抽 5ml +- 陈醋 10ml +- 盐 2g +- 食用油 10-15ml + +## 操作 + +- 土豆去皮、切丝(或用刨丝器)。 +- 切好的土豆丝用清水清洗,去除多余的淀粉,然后对土豆丝焯水 10 秒。沥干,备用。 +- 葱蒜干辣椒切小块,青红椒切丝。 +- 热锅,小火热油爆香蒜和干辣椒。 +- 加入青红椒翻炒几下,加入土豆丝翻炒至变色。 +- 加 5ml 生抽,10ml 陈醋,蒜末,最后加入盐翻炒均匀即可。 + +## 附加内容 + +- 清洗土豆丝淀粉一定要去干净,不然会全黏在一起 +- 加入蒜末、盐后应尽快出锅,保留蒜香以及避免破坏口感。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/金针菇日本豆腐煲.md b/data/C8/cook/dishes/vegetable_dish/金针菇日本豆腐煲.md new file mode 100644 index 0000000..2715884 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/金针菇日本豆腐煲.md @@ -0,0 +1,41 @@ +# 金针菇日本豆腐煲的做法 + +金针菇日本豆腐煲是一道容易上手的日常料理。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 金针菇 +- 日本豆腐(玉子豆腐) +- 小米椒 +- 生抽 +- 蚝油 +- 盐 +- 糖 +- 食用油 + +## 计算 + +每份: + +- 金针菇 1-2 把 +- 豆腐 2 袋 +- 小米椒 3-5 根,切碎 +- 蒜 2-3 瓣 +- 生抽 15ml +- 蚝油 5ml +- 老抽 3ml +- 糖 3g +- 食用油 10-15ml + +## 操作 + +- 豆腐切片,小火煎到两面金黄出锅备用。 +- 切蒜成蒜末;将生抽,蚝油,老抽,糖,100ml 水调汁备用。 +- 热锅放油,油热放小米椒、蒜末爆香,先放金针菇,炒软,把煎好的豆腐平铺在金针菇上,倒入#2 配好的料汁,焖 5 分钟,大火收汁。 + +## 附加内容 + +- 金针菇一定要先炒软 +- 豆腐尽量不要翻炒,容易碎 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/陕北熬豆角.md b/data/C8/cook/dishes/vegetable_dish/陕北熬豆角.md new file mode 100644 index 0000000..8748e67 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/陕北熬豆角.md @@ -0,0 +1,54 @@ +# 陕北熬豆角的做法 + +陕北熬豆角是一种对初学者极其友善的菜,因其制作方式使用`熬`的方式,食材可多可少,可有可无,几乎不存在失败的可能性。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 豆角 +- 土豆 +- 西红柿 +- 螺丝椒(可选) +- 盐 +- 生抽 +- 五香粉 +- 蚝油 +- 葱 +- 姜 +- 蒜 + +## 计算 + +注意,受食材个体影响,本菜谱为 2 人份菜谱 + +- 豆角 300g * 2 人 +- 土豆 1 个 * 2 人 +- 西红柿 1 个 * 2 人 +- 螺丝椒(可选)2 个 * 2 人 +- 盐 6g * 2 人 +- 生抽 6ml * 2 人 +- 五香粉 3g * 2 人 +- 蚝油 6ml * 2 人 +- 葱 3 圈 +- 姜 2g +- 蒜 2 颗 +- 香菜碎(可选)根据口味加 + +## 操作 + +- 葱切花,蒜切沫,姜切丝,备用。 +- 豆角去筋,切*2-10cm*小段,备用。 +- 土豆去皮,切*1cm³*小块,备用。 +- 西红柿去皮,切*1cm³*小块,备用。 +- 辣椒去仔,切*0.15cm 宽*条,备用。 +- 起锅烧油(10ml - 15ml),冒烟后放入葱姜蒜,翻炒至闻到葱姜蒜香味; +- 加入豆角,翻炒至变色(青绿色变为翠绿色); +- 加入土豆块,翻炒 30s; +- 加入热水(水面刚刚漫过菜),盖上锅盖熬至土豆*变软*(可以用筷子确认); +- 加入西红柿块,加入盐,生抽,蚝油,五香粉,辣椒,熬至西红柿成汁(注意搅拌,防止糊锅); +- 加入香菜碎,出锅。 + +## 附加内容 + +- 加入西红柿后开始继续熬制后,需要偶尔翻搅防止糊底 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/雷椒皮蛋.md b/data/C8/cook/dishes/vegetable_dish/雷椒皮蛋.md new file mode 100644 index 0000000..784c764 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/雷椒皮蛋.md @@ -0,0 +1,52 @@ +# 雷椒皮蛋的做法 + +雷椒皮蛋是一个非常简单的下饭凉菜,这道菜操作比较简单,且食材常见, 最终成品卖相不会很好看,但是是夏天下饭的神器之一 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 皮蛋 +- 长条青椒(有些叫线椒,后面介绍以“青椒”代替) +- 葱 +- 蒜 +- 小米辣(可选) +- 食用油 +- 生抽 +- 陈醋 +- 白糖 +- 香油 +- 深一点的小铁盆 + +## 计算 + +每份: + +- 皮蛋 2 个 +- 青椒 4 根 (长 10-15cm,宽 2-4cm) +- 葱 (大约 10cm 即可,葱绿最佳) +- 蒜 3-4 瓣 +- 食用油 10-20ml +- 生抽 15-20ml +- 陈醋 15-20ml +- 白糖 6-10g +- 香油 5-7ml +- 小米辣 3-4 颗 + +## 操作 + +- 青椒清洗,去除根部,侧面切开,去除内部的子后在案板压平,备用(一定要去除青椒子,否则会在锅里炸开) +- 葱切成半厘米小段,备用 +- 蒜去皮,切成碎末,备用 +- 皮蛋去皮,备用 +- 小米辣,切成 5-10mm 的小段,备用 +- 热锅,锅内放入 10ml - 20ml 食用油 +- 放入全部青椒,改小火保持锅子温度,煎至青椒变软(可以用筷子试一下,插入即透即可) +- 关火,将皮蛋和青椒放入小铁盆中 +- 方法 1: 有擀面杖且砸东西不会吵到邻居:用擀面杖的一头在小盆中砸击皮蛋和青椒,至皮蛋与青椒混合(选项) +- 方法 2:将青椒用手撕开,撕成大约半厘米的条状,用叉子将皮蛋压碎(选项) +- 小米辣 +- 倒入生抽,陈醋,白糖,香油,以及其他未使用的备用食材 +- 均匀搅拌 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/鸡蛋火腿炒黄瓜.md b/data/C8/cook/dishes/vegetable_dish/鸡蛋火腿炒黄瓜.md new file mode 100644 index 0000000..164a9c5 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/鸡蛋火腿炒黄瓜.md @@ -0,0 +1,42 @@ +# 鸡蛋火腿炒黄瓜的做法 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 黄瓜 +- 鸡蛋 +- 火腿肠 +- 盐 +- 生抽 +- 红尖椒(可选) + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人吃。 + +每份: + +- 黄瓜 1 根(约 200g) +- 鸡蛋 2 个 +- 火腿肠 1 根(约 40g) +- 红尖椒 1 个(可选) +- 食用油 10ml +- 生抽 3ml +- 盐 2g + +## 操作 + +- 黄瓜洗净,切半圆形片,备用 +- 火腿切半圆形片,备用 +- 红尖椒(可选)切碎,备用 +- 将鸡蛋打入碗中,搅匀,即为 `鸡蛋液` +- 热锅里倒 5ml 食用油 +- 油热后转小火,倒入打散的`鸡蛋液`,用筷子划散,翻炒至鸡蛋结为固体且颜色微微发黄,即为 `半熟鸡蛋`,盛出备用 +- **不用洗锅**,往锅内倒入 5ml 食用油,倒入黄瓜片大火**翻炒 1 分钟** +- 把 `半熟鸡蛋` 倒入锅中,调入 2g 盐、3ml 生抽,立刻倒入火腿片和辣椒碎(可选)翻炒均匀 +- 关火,盛盘 + +## 附加内容 + +- 火腿是咸的,要在调味后才加入,这样不会让火腿也沾上盐 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/微波炉鸡蛋羹.jpg b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/微波炉鸡蛋羹.jpg new file mode 100644 index 0000000..5ddc691 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/微波炉鸡蛋羹.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9474c75f2b71732259273656f2ac6d7e0689e045edc94d5b3c9d8621d057c2fe +size 326920 diff --git a/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/微波炉鸡蛋羹.md b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/微波炉鸡蛋羹.md new file mode 100644 index 0000000..ee62c6e --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/微波炉鸡蛋羹.md @@ -0,0 +1,49 @@ +# 微波炉鸡蛋羹的做法 + +![微波炉鸡蛋羹](./微波炉鸡蛋羹.jpg) +微波炉鸡蛋羹是一个简单易制作的菜。非常适合夜间突然饿了的时候充当夜宵,快捷简单。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +每次制作可以最多制作三份。超过 3 人需要的情况下,需要分多次制作。 + +- 鸡蛋 +- 水 + +## 计算 + +每次制作前需要确定计划做几份。一份正好够 1 个人食用 + +总量: + +- 鸡蛋 2 个 * 份数 +- 水 200ml * 份数 +- 虾皮 10 个 * 份数(可选) +- 葱 5g *份数(可选) +- 盐 3g * 份数 +- 酱油(可选) +- 芝麻油(香油) 1ml(可选) + +## 操作 + +- 将鸡蛋打入可使用微波炉加热的陶瓷碗中,使用筷子将其打散。 +- 加入水和盐,搅拌均匀。 +- 将虾皮放入碗中,搅拌均匀,保证所有虾皮不会堆积在一起。 +- 葱切碎至边长 0.6±3mm 状,放入碗中搅拌均匀。 +- 将此碗及内容物放入微波炉中,容器表面覆盖保鲜膜或以可微波瓷盘加盖(注意:不得密封,必须留有涨缩量)加热 2 分钟(500W)。 +- 小心地取下保鲜膜或其他覆盖物,然后继续加热 2 分钟。 +- 若微波炉不带旋转式加热盘,将碗缓慢的水平旋转 180 度,以确保内容物加热均匀。 +- 放入芝麻油。 +- 小心地从微波炉中拿出碗(真的很烫)。 +- 如果选择放入酱油,则确保酱油在鸡蛋羹表面流动后能以最薄的形式沾满鸡蛋羹表面即可。 +- 开心的享受鸡蛋羹 + +## 附加内容 + +- 鸡蛋 1 个约为 50±5g。若使用其他品种蛋品可按比例增减水量。 + +- 一定要确保将鸡蛋打散,否则可能会发生轻度鸡蛋爆炸。 + +- 鸡蛋和水不能超过碗容量的 2/3,否则可能发生溢出。 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/蒸箱鸡蛋羹.md b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/蒸箱鸡蛋羹.md new file mode 100644 index 0000000..fb4bcec --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/蒸箱鸡蛋羹.md @@ -0,0 +1,41 @@ +# 蒸箱鸡蛋羹的做法 + +蒸箱鸡蛋羹,是一道简单快捷易做的菜,制作时长约为 15 分钟。适用于有家庭蒸箱的厨师。 + +预估烹饪难度:★★★ + +## 必备原料和工具 + +- 鸡蛋 +- 食用盐 +- 食用油 +- 生抽(可选) +- 蒸箱 + +## 计算 + +按照 1 人的份量: + +- 鸡蛋 1 个 +- 食用盐 1g +- 食用油 5ml +- 生抽 / 味极鲜 6ml(可选调味) + +## 操作 + +- 一个鸡蛋放入碗中打散 +- 向碗中加入鸡蛋体积 1.0-1.5 倍 60 度纯净水,并且搅拌均匀 + - 正确范围内水越少弹,水越多越嫩 + - 注意:超出范围后,水越少会口感变得太弹,水越多会变得太稀 +- 加入食用盐 1g + - 盐起到了重要的增加底味和凝固作用 +- 加入食用油 5ml +- 过滤蛋液,去掉蛋液中的浮沫(可选,不过滤蒸出来的蛋会有气泡导致不好看) +- 确认蒸箱的水源已经补充至足够(若不确定,可把水槽补满) +- 将已经完全搅拌均匀的鸡蛋液碗放入蒸箱 +- 调节至**100摄氏度**蒸 **10 分钟** +- 打开蒸箱 (注意:蒸箱在开启时会有蒸气瞬间喷出,注意缓慢开启) +- 出锅(可加入生抽调味) +- 享用 + +## 附加内容 \ No newline at end of file diff --git a/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/鸡蛋羹.jpg b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/鸡蛋羹.jpg new file mode 100644 index 0000000..b230d64 --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/鸡蛋羹.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1a5035f6c0ce2339fca040cb298a4f312017b67be86728828e57320c7a174fd +size 218388 diff --git a/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/鸡蛋羹.md b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/鸡蛋羹.md new file mode 100644 index 0000000..baea28a --- /dev/null +++ b/data/C8/cook/dishes/vegetable_dish/鸡蛋羹/鸡蛋羹.md @@ -0,0 +1,52 @@ +# 鸡蛋羹的做法 + +![鸡蛋羹成品](./鸡蛋羹.jpg) + +鸡蛋羹,又称水蒸蛋,不需要准备复杂的食材,是一道简单快捷易做的菜,当早餐或是正餐都可,制作时长约为 15 分钟。 + +预估烹饪难度:★★ + +## 必备原料和工具 + +- 鸡蛋 +- 食用盐 +- 香油 +- 生抽 / 味极鲜 +- 白醋(可选) +- 藤椒油(可选) + +## 计算 + +按照 1 人的份量: + +- 鸡蛋 2 个 +- 食用盐 3g +- 香油(或芝麻油) 2-4ml +- 生抽 / 味极鲜 8ml +- 白醋(或料酒) 2ml(可选) + +## 操作 + +- 两个鸡蛋放入碗中打散 +- 加入食用盐 3g + - 盐起到了重要的增加底味和凝固作用 +- 加入 2ml 白醋,去除鸡蛋的腥味(可选) + - 加入米醋也行,但米醋的颜色会使鸡蛋微微发黑 + - 还可以加入料酒,同样具有去腥的作用,且没有醋的酸味 +- 向碗中加入鸡蛋体积 1-1.5 倍的 70 度纯净水,并且搅拌均匀 + - 1 倍的水鸡蛋更弹,1.5 倍的水鸡蛋更嫩 +- 过滤蛋液,去掉蛋液中的浮沫(可选,不过滤蒸出来的蛋会有气泡导致不好看) +- 向任意一口锅中加入 50ml 清水,水烧开后,放入盛有鸡蛋液的碗 + - 蒸碗要盖上一个盖子,倒扣一个有凹槽的铁碟子,或者使用保鲜膜来减少水汽进入,这是为了避免其变成蜂窝状 +- 蒸煮步骤(二选一) + 1. 开**中火**蒸**10 分钟**, 10 分钟之后关火再闷上**5 分钟**。 + 2. 开**大火**蒸**5 分钟**,要保持锅中水一直处于沸腾状态,否则要延长时间。每隔**2 分钟**开盖一次释放水蒸气,开盖过晚蛋羹容易变成蜂窝状;开盖太早/频繁蒸的时间需要久一些。 +- 如何判断已经熟了? + - 晃动碗,蛋羹不再处于液体状态,拥有类似果冻的 Q 弹状态即可出锅。 +- 出锅 +- 加入香油和生抽即可享用 + - 也可用藤椒油代替香油,增加麻爽口感 + +## 附加内容 + +上面介绍的是基础水蒸蛋做法,可以在此基础上派生,添加诸如火腿肠、肉馅、虾皮等材料,丰富鸡蛋羹的口感。 \ No newline at end of file diff --git a/data/C9/cypher/neo4j_import.cypher b/data/C9/cypher/neo4j_import.cypher new file mode 100644 index 0000000..e278f57 --- /dev/null +++ b/data/C9/cypher/neo4j_import.cypher @@ -0,0 +1,369 @@ +// ======================================================================================== +// 中式烹饪知识图谱构建脚本 +// ======================================================================================== + +// 删除已存在的约束 +DROP CONSTRAINT recipe_id_unique IF EXISTS; +DROP CONSTRAINT ingredient_id_unique IF EXISTS; +DROP CONSTRAINT cookingstep_id_unique IF EXISTS; +DROP CONSTRAINT cookingmethod_id_unique IF EXISTS; +DROP CONSTRAINT cookingtool_id_unique IF EXISTS; +DROP CONSTRAINT difficultylevel_id_unique IF EXISTS; + +// 创建核心约束 +CREATE CONSTRAINT recipe_id_unique IF NOT EXISTS FOR (r:Recipe) REQUIRE r.nodeId IS UNIQUE; +CREATE CONSTRAINT ingredient_id_unique IF NOT EXISTS FOR (i:Ingredient) REQUIRE i.nodeId IS UNIQUE; +CREATE CONSTRAINT cookingstep_id_unique IF NOT EXISTS FOR (s:CookingStep) REQUIRE s.nodeId IS UNIQUE; + +// 创建基础索引 +CREATE INDEX recipe_name_index IF NOT EXISTS FOR (r:Recipe) ON (r.name); +CREATE INDEX recipe_difficulty_index IF NOT EXISTS FOR (r:Recipe) ON (r.difficulty); +CREATE INDEX recipe_cuisine_index IF NOT EXISTS FOR (r:Recipe) ON (r.cuisineType); +CREATE INDEX ingredient_name_index IF NOT EXISTS FOR (i:Ingredient) ON (i.name); +CREATE INDEX ingredient_category_index IF NOT EXISTS FOR (i:Ingredient) ON (i.category); +CREATE INDEX cookingstep_number_index IF NOT EXISTS FOR (s:CookingStep) ON (s.stepNumber); + +// 创建全文搜索索引(包含更多字段) +CREATE FULLTEXT INDEX recipe_fulltext_index IF NOT EXISTS FOR (r:Recipe) ON EACH [r.name, r.description, r.preferredTerm, r.fsn, r.tags]; +CREATE FULLTEXT INDEX ingredient_fulltext_index IF NOT EXISTS FOR (i:Ingredient) ON EACH [i.name, i.description, i.preferredTerm, i.fsn]; +CREATE FULLTEXT INDEX cookingstep_fulltext_index IF NOT EXISTS FOR (s:CookingStep) ON EACH [s.name, s.description, s.methods, s.tools]; + +// 创建层次结构节点 +RETURN 'Creating hierarchy nodes from nodes.csv'; +LOAD CSV WITH HEADERS FROM 'file:///nodes.csv' AS row +WITH row +WHERE row.nodeId < '200000000' // 层次结构节点的ID范围 + AND row.nodeId IS NOT NULL + AND row.name IS NOT NULL +WITH row, row.labels as nodeType +CALL apoc.create.node([nodeType], { + nodeId: row.nodeId, + name: row.name, + preferredTerm: row.preferredTerm, + fsn: row.fsn, + conceptType: row.conceptType, + synonyms: row.synonyms, + category: row.category, + description: row.description, + originalLabels: row.labels, + isHierarchyNode: true +}) YIELD node +RETURN count(node); + +// 创建菜谱节点 +RETURN 'Creating Recipe nodes from nodes.csv'; +LOAD CSV WITH HEADERS FROM 'file:///nodes.csv' AS row +WITH row +WHERE row.labels = 'Recipe' + AND row.nodeId >= '200000000' // 只处理具体实例,不处理层次结构 + AND row.nodeId IS NOT NULL + AND row.name IS NOT NULL + + MERGE (r:Recipe {nodeId: row.nodeId}) + SET r.name = row.name, + r.preferredTerm = row.preferredTerm, + r.fsn = row.fsn, + r.description = row.description, + r.difficulty = CASE + WHEN row.difficulty IS NOT NULL THEN toFloat(row.difficulty) + ELSE null + END, + r.category = row.category, + r.conceptType = row.conceptType, + r.cuisineType = row.cuisineType, + r.prepTime = row.prepTime, + r.cookTime = row.cookTime, + r.servings = row.servings, + r.tags = row.tags, + r.filePath = row.filePath, + r.synonyms = row.synonyms, + r.textForEmbedding = row.name + ' ' + COALESCE(row.preferredTerm, '') + ' ' + + COALESCE(row.description, '') + ' ' + COALESCE(row.tags, ''), + r.originalLabels = row.labels; + +// 创建食材节点 +RETURN 'Creating Ingredient nodes'; +LOAD CSV WITH HEADERS FROM 'file:///nodes.csv' AS row +WITH row +WHERE row.labels = 'Ingredient' + AND row.nodeId >= '200000000' // 只处理具体实例 + AND row.nodeId IS NOT NULL + AND row.name IS NOT NULL + + MERGE (i:Ingredient {nodeId: row.nodeId}) + SET i.name = row.name, + i.preferredTerm = row.preferredTerm, + i.fsn = row.fsn, + i.description = row.description, + i.category = row.category, + i.conceptType = row.conceptType, + i.amount = row.amount, + i.unit = row.unit, + i.isMain = CASE + WHEN row.isMain IS NOT NULL THEN toBoolean(row.isMain) + ELSE null + END, + i.synonyms = row.synonyms, + i.originalLabels = row.labels; + +// 创建烹饪步骤节点 +RETURN 'Creating CookingStep nodes'; +LOAD CSV WITH HEADERS FROM 'file:///nodes.csv' AS row +WITH row +WHERE row.labels = 'CookingStep' + AND row.nodeId >= '200000000' // 只处理具体实例 + AND row.nodeId IS NOT NULL + AND row.name IS NOT NULL + + MERGE (s:CookingStep {nodeId: row.nodeId}) + SET s.name = row.name, + s.preferredTerm = row.preferredTerm, + s.fsn = row.fsn, + s.description = row.description, + s.category = row.category, + s.conceptType = row.conceptType, + s.stepNumber = CASE + WHEN row.stepNumber IS NOT NULL THEN toFloat(row.stepNumber) + ELSE null + END, + s.methods = row.methods, + s.tools = row.tools, + s.timeEstimate = row.timeEstimate, + s.synonyms = row.synonyms, + s.originalLabels = row.labels; + +// 创建其他类型节点 +RETURN 'Creating other node types'; +LOAD CSV WITH HEADERS FROM 'file:///nodes.csv' AS row +WITH row +WHERE NOT (row.labels IN ['Recipe', 'Ingredient', 'CookingStep']) + AND row.nodeId IS NOT NULL + AND row.name IS NOT NULL +WITH row, row.labels as nodeType +CALL apoc.create.node([nodeType], { + nodeId: row.nodeId, + name: row.name, + description: row.description, + category: row.category, + conceptType: row.conceptType, + originalLabels: row.labels +}) YIELD node +RETURN count(node); + +// 创建需要关系 (801000001) +RETURN 'Creating REQUIRES relationships'; +LOAD CSV WITH HEADERS FROM 'file:///relationships.csv' AS row +WITH row +WHERE row.relationshipType = '801000001' + AND row.startNodeId IS NOT NULL + AND row.endNodeId IS NOT NULL +MATCH (source:Recipe {nodeId: row.startNodeId}) +MATCH (target:Ingredient {nodeId: row.endNodeId}) +MERGE (source)-[r:REQUIRES]->(target) +SET r.relationshipId = row.relationshipId, + r.amount = row.amount, + r.unit = row.unit, + r.originalType = row.relationshipType; + +// 创建包含步骤关系 (801000003) +RETURN 'Creating CONTAINS relationships'; +LOAD CSV WITH HEADERS FROM 'file:///relationships.csv' AS row +WITH row +WHERE row.relationshipType = '801000003' + AND row.startNodeId IS NOT NULL + AND row.endNodeId IS NOT NULL +MATCH (source:Recipe {nodeId: row.startNodeId}) +MATCH (target:CookingStep {nodeId: row.endNodeId}) +MERGE (source)-[r:CONTAINS_STEP]->(target) +SET r.relationshipId = row.relationshipId, + r.stepOrder = CASE + WHEN row.step_order IS NOT NULL AND row.step_order <> '' + THEN toFloat(row.step_order) + ELSE null + END, + r.originalType = row.relationshipType; + +// 创建其他关系类型 +RETURN 'Creating other relationships'; +LOAD CSV WITH HEADERS FROM 'file:///relationships.csv' AS row +WITH row +WHERE NOT (row.relationshipType IN ['801000001', '801000003']) + AND row.relationshipType IS NOT NULL + AND row.startNodeId IS NOT NULL + AND row.endNodeId IS NOT NULL +MATCH (source {nodeId: row.startNodeId}) +MATCH (target {nodeId: row.endNodeId}) +WITH source, target, row, + CASE row.relationshipType + WHEN '801000004' THEN 'BELONGS_TO' + WHEN '801000005' THEN 'DIFFICULTY_LEVEL' + ELSE row.relationshipType + END as relType +CALL apoc.create.relationship(source, relType, { + relationshipId: row.relationshipId, + amount: row.amount, + unit: row.unit, + stepOrder: CASE + WHEN row.step_order IS NOT NULL AND row.step_order <> '' + THEN toFloat(row.step_order) + ELSE null + END, + originalType: row.relationshipType +}, target) YIELD rel +RETURN count(rel); + +// 基于数据创建分类节点(支持多重分类) +RETURN 'Creating category nodes from data'; + +// 处理多重分类:按逗号分割并创建分类节点 +MATCH (n) +WHERE n.category IS NOT NULL AND n.category <> '' +WITH n, split(n.category, ',') as categoryList +UNWIND categoryList as categoryName +WITH n, trim(categoryName) as cleanCategoryName +WHERE cleanCategoryName <> '' +MERGE (cat:Category {name: cleanCategoryName}) +MERGE (n)-[:BELONGS_TO_CATEGORY]->(cat); + +// 为每个唯一的conceptType创建概念类型节点 +MATCH (n) +WHERE n.conceptType IS NOT NULL AND n.conceptType <> '' +WITH DISTINCT n.conceptType as conceptTypeName +MERGE (ct:ConceptType {name: conceptTypeName}); + +// 连接实体到概念类型 +MATCH (n), (ct:ConceptType) +WHERE n.conceptType = ct.name +MERGE (n)-[:HAS_CONCEPT_TYPE]->(ct); + +// 创建基于数据的相似性关系(仅基于相同分类) +RETURN 'Creating data-driven similarity relationships'; +MATCH (n1), (n2) +WHERE n1.category = n2.category + AND n1.nodeId <> n2.nodeId + AND n1.category IS NOT NULL + AND labels(n1) = labels(n2) +WITH n1, n2, n1.category as sharedCategory +LIMIT 1000 +MERGE (n1)-[:SIMILAR { + basis: 'same_category', + category: sharedCategory, + confidence: 0.6 +}]->(n2); + +// 生成统计信息 +RETURN 'Generating statistics'; +MATCH (n) +WITH labels(n) as nodeTypes, count(n) as nodeCount +UNWIND nodeTypes as nodeType +WITH nodeType, sum(nodeCount) as totalCount +WHERE nodeType <> 'Category' AND nodeType <> 'ConceptType' +CREATE (stat:GraphStatistics { + nodeType: nodeType, + count: totalCount, + generatedAt: datetime() +}); + +MATCH ()-[r]->() +WITH type(r) as relType, count(r) as relCount +CREATE (stat:RelationshipStatistics { + relationshipType: relType, + count: relCount, + generatedAt: datetime() +}); + +// 处理同义词关系(如果数据中有同义词) +RETURN 'Creating synonym relationships'; +MATCH (n) +WHERE n.synonyms IS NOT NULL AND n.synonyms <> '' AND n.synonyms <> '[]' +WITH n, n.synonyms as synonymsJson +WHERE synonymsJson IS NOT NULL +// 这里可以根据实际的同义词格式进行解析 +// 目前先创建一个标记,表示该节点有同义词 +SET n.hasSynonyms = true; + +// 创建基于时间的步骤序列关系 +RETURN 'Creating step sequence relationships'; +MATCH (r:Recipe)-[:CONTAINS_STEP]->(s1:CookingStep) +MATCH (r)-[:CONTAINS_STEP]->(s2:CookingStep) +WHERE s1.stepNumber IS NOT NULL AND s2.stepNumber IS NOT NULL + AND s2.stepNumber = s1.stepNumber + 1 +MERGE (s1)-[:NEXT_STEP { + sequence: true, + timeDifference: s2.stepNumber - s1.stepNumber +}]->(s2); + +// 创建基于工具的关系 +RETURN 'Creating tool-based relationships'; +MATCH (s1:CookingStep), (s2:CookingStep) +WHERE s1.tools IS NOT NULL AND s2.tools IS NOT NULL + AND s1.tools = s2.tools + AND s1.nodeId <> s2.nodeId +WITH s1, s2, s1.tools as sharedTool +LIMIT 1000 +MERGE (s1)-[:USES_SAME_TOOL { + tool: sharedTool, + similarity: 0.5 +}]->(s2); + +// 创建基于烹饪方法的关系 +RETURN 'Creating method-based relationships'; +MATCH (s1:CookingStep), (s2:CookingStep) +WHERE s1.methods IS NOT NULL AND s2.methods IS NOT NULL + AND s1.methods = s2.methods + AND s1.nodeId <> s2.nodeId +WITH s1, s2, s1.methods as sharedMethod +LIMIT 1000 +MERGE (s1)-[:USES_SAME_METHOD { + method: sharedMethod, + similarity: 0.7 +}]->(s2); + +// 为难度等级创建特殊处理 +RETURN 'Processing difficulty levels'; +MATCH (d:DifficultyLevel) +SET d.level = CASE d.name + WHEN '一星' THEN 1 + WHEN '二星' THEN 2 + WHEN '三星' THEN 3 + WHEN '四星' THEN 4 + WHEN '五星' THEN 5 + ELSE 0 +END; + +// 创建菜谱到难度等级的直接关系(如果数据中有对应关系) +MATCH (r:Recipe) +WHERE r.difficulty IS NOT NULL +MATCH (d:DifficultyLevel) +WHERE d.level = toInteger(r.difficulty) +MERGE (r)-[:HAS_DIFFICULTY_LEVEL]->(d); + +// 优化:为高频查询创建计算属性 +RETURN 'Creating computed properties for optimization'; + +// 为菜谱计算总时间 +MATCH (r:Recipe) +WHERE r.prepTime IS NOT NULL AND r.cookTime IS NOT NULL +SET r.totalTime = CASE + WHEN r.prepTime =~ '.*分钟.*' AND r.cookTime =~ '.*分钟.*' THEN + toInteger(split(r.prepTime, '分钟')[0]) + toInteger(split(r.cookTime, '分钟')[0]) + ELSE null +END; + +// 为菜谱计算食材数量 +MATCH (r:Recipe) +OPTIONAL MATCH (r)-[:REQUIRES]->(i:Ingredient) +WITH r, count(i) as ingredientCount +SET r.ingredientCount = ingredientCount; + +// 为菜谱计算步骤数量 +MATCH (r:Recipe) +OPTIONAL MATCH (r)-[:CONTAINS_STEP]->(s:CookingStep) +WITH r, count(s) as stepCount +SET r.stepCount = stepCount; + +RETURN 'Knowledge graph construction completed!'; + +MATCH (n) +RETURN labels(n) as NodeType, count(n) as Count +ORDER BY Count DESC; \ No newline at end of file diff --git a/data/C9/cypher/nodes.csv b/data/C9/cypher/nodes.csv new file mode 100644 index 0000000..0934861 --- /dev/null +++ b/data/C9/cypher/nodes.csv @@ -0,0 +1,5761 @@ +nodeId,labels,name,preferredTerm,fsn,conceptType,synonyms,category,difficulty,cuisineType,prepTime,cookTime,servings,tags,filePath,amount,unit,isMain,description,stepNumber,methods,tools,timeEstimate +100000000,Root,烹饪概念,烹饪概念,烹饪概念 (Culinary Concept),Root,,,,,,,,,,,,,,,,, +200000000,Recipe,菜谱,菜谱,菜谱 (Recipe),Recipe,,,,,,,,,,,,,,,,, +300000000,Ingredient,食材,食材,食材 (Ingredient),Ingredient,,,,,,,,,,,,,,,,, +400000000,CookingMethod,烹饪方法,烹饪方法,烹饪方法 (Cooking Method),CookingMethod,,,,,,,,,,,,,,,,, +500000000,CookingTool,烹饪工具,烹饪工具,烹饪工具 (Cooking Tool),CookingTool,,,,,,,,,,,,,,,,, +610000000,DifficultyLevel,一星,一星,一星 (One Star),DifficultyLevel,,,,,,,,,,,,,,,,, +620000000,DifficultyLevel,二星,二星,二星 (Two Star),DifficultyLevel,,,,,,,,,,,,,,,,, +630000000,DifficultyLevel,三星,三星,三星 (Three Star),DifficultyLevel,,,,,,,,,,,,,,,,, +640000000,DifficultyLevel,四星,四星,四星 (Four Star),DifficultyLevel,,,,,,,,,,,,,,,,, +650000000,DifficultyLevel,五星,五星,五星 (Five Star),DifficultyLevel,,,,,,,,,,,,,,,,, +710000000,RecipeCategory,素菜,素菜,素菜 (Vegetarian Dish),RecipeCategory,,,,,,,,,,,,,,,,, +720000000,RecipeCategory,荤菜,荤菜,荤菜 (Meat Dish),RecipeCategory,,,,,,,,,,,,,,,,, +730000000,RecipeCategory,水产,水产,水产 (Aquatic Product),RecipeCategory,,,,,,,,,,,,,,,,, +740000000,RecipeCategory,早餐,早餐,早餐 (Breakfast),RecipeCategory,,,,,,,,,,,,,,,,, +750000000,RecipeCategory,主食,主食,主食 (Staple Food),RecipeCategory,,,,,,,,,,,,,,,,, +760000000,RecipeCategory,汤类,汤类,汤类 (Soup),RecipeCategory,,,,,,,,,,,,,,,,, +770000000,RecipeCategory,甜品,甜品,甜品 (Dessert),RecipeCategory,,,,,,,,,,,,,,,,, +780000000,RecipeCategory,饮料,饮料,饮料 (Beverage),RecipeCategory,,,,,,,,,,,,,,,,, +790000000,RecipeCategory,调料,调料,调料 (Condiment),RecipeCategory,,,,,,,,,,,,,,,,, +201000001,Recipe,咖喱炒蟹,咖喱炒蟹,,Recipe,,水产,4.0,泰国菜,10分钟,8分钟,1人/份,"泰国风味,咖喱蟹黄,海鲜,快手菜",dishes\aquatic\咖喱炒蟹.md,,,,,,,, +201000002,Ingredient,青蟹,青蟹,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201000003,Ingredient,咖喱块,咖喱块,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201000004,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,200,g,False,,,,, +201000005,Ingredient,椰浆,椰浆,,Ingredient,,调料,,,,,,,,100,ml,False,,,,, +201000006,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201000007,Ingredient,生粉,生粉,,Ingredient,,淀粉类,,,,,,,,5,g,False,,,,, +201000008,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,5,瓣,False,,,,, +201000009,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201000010,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,300,ml,False,,,,, +201000011,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,肉蟹掀盖后对半砍开,蟹钳用刀背轻轻拍裂,切口和蟹钳蘸一下生粉,不要太多。撒5g生粉到蟹盖中,盖住蟹黄,备用。,1.0,"切,拍,蘸,撒","刀,案板",2分钟 +201000012,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,洋葱切成洋葱碎,备用。,2.0,切,"刀,案板",1分钟 +201000013,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大蒜切碎,备用。,3.0,切,"刀,案板",30秒 +201000014,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,烧一壶开水,备用。,4.0,烧,水壶,2分钟 +201000015,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,起锅烧油,倒入约20ml食用油,等待10秒让油温升高。,5.0,"烧,倒",炒锅,10秒 +201000016,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将螃蟹切口朝下,轻轻放入锅中,煎20秒,这一步主要是封住蟹黄、蟹肉。然后翻面,每面煎10秒。煎完将螃蟹取出备用。,6.0,煎,"炒锅,锅铲",40秒 +201000017,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将螃蟹盖放入锅中,使用勺子舀起锅中热油泼到蟹盖中,煎封住蟹盖中的蟹黄,煎20秒后取出备用。,7.0,"煎,泼","炒锅,勺子",20秒 +201000018,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,不用刷锅,再倒入10ml食用油,大火让油温升高至轻微冒烟,将大蒜末、洋葱碎倒入,炒10秒钟。,8.0,"倒,炒","炒锅,锅铲",10秒 +201000019,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将咖喱块放入锅中炒化(10秒),放入煎好的螃蟹,翻炒均匀。,9.0,"炒,翻炒","炒锅,锅铲",10秒 +201000020,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,倒入开水300ml,焖煮3分钟。,10.0,"倒,焖煮",炒锅,3分钟 +201000021,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,焖煮完后,倒入椰浆和蛋清,关火,关火后不断翻炒,一直到酱汁变浓稠。,11.0,"倒,翻炒","炒锅,锅铲",1分钟 +201000022,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,出锅。,12.0,出锅,锅铲,5秒 +201000023,Recipe,微波葱姜黑鳕鱼,微波葱姜黑鳕鱼,,Recipe,,水产,3.0,,约5分钟,3.5-5分钟,2人份,"微波,葱姜,热油泼香,可替换鱼种,海鲈鱼6.5分钟,罗非鱼6分钟,大比目鱼2.25分钟,龙脷鱼1.5分钟,微波前可抹葱姜料酒增香",dishes\aquatic\微波葱姜黑鳕鱼.md,,,,,,,, +201000024,Ingredient,黑鳕鱼,黑鳕鱼,,Ingredient,,蛋白质,,,,,,,,450,g,True,,,,, +201000025,Ingredient,青葱(葱白),青葱(葱白),,Ingredient,,蔬菜,,,,,,,,25,g,False,,,,, +201000026,Ingredient,青葱(葱绿),青葱(葱绿),,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201000027,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,13,g,False,,,,, +201000028,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,mL,False,,,,, +201000029,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,25,mL,False,,,,, +201000030,Ingredient,芝麻油,芝麻油,,Ingredient,,调料,,,,,,,,2,mL,False,,,,, +201000031,Ingredient,花生油,花生油,,Ingredient,,调料,,,,,,,,50,mL,False,,,,, +201000032,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将黑鳕鱼片分别放入密封袋,鱼皮向下放在盘子中。,1.0,切,"密封袋,盘子", +201000033,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,取葱白25g切丝,姜13g去皮后切丝,混合后分成两半,分别放在袋内鱼片上。,2.0,切,"刀,案板", +201000034,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,每个袋子倒入2.5mL料酒。,3.0,倒,量勺, +201000035,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,封好密封袋,放入微波炉,中火(800瓦)微波至不透明且容易散开(约3.5-5分钟),取出鱼片。,4.0,微波,"微波炉,密封袋",3.5-5分钟 +201000036,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,去除青葱和姜。,5.0,去料,筷子, +201000037,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将酱油25mL与芝麻油2mL混合均匀,平均淋在两片鱼片上。,6.0,"混合,淋","小碗,勺子", +201000038,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,取葱绿10g切细丝,姜3g去皮后切丝,混合后分成两份撒在鱼片上。,7.0,"切,撒","刀,案板", +201000039,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,取花生油50mL在小锅中加热至190℃,将热油淋到放葱绿的鱼片上,立刻上桌。,8.0,"加热,淋","小锅,温度计,勺子", +201000040,Recipe,水煮鱼,水煮鱼,,Recipe,,水产,4.0,川菜,5小时30分钟,约20分钟,3至5人,"蔬菜组合可自由调整,土豆需先煮熟,红油豆瓣酱与盐量可按口味调整,切鱼块后90度斜切薄片,腌制时勿用力过猛",dishes\aquatic\水煮鱼.md,,,,,,,, +201000041,Ingredient,巴沙鱼,巴沙鱼,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201000042,Ingredient,蔬菜(土豆片/豆芽/花菜/生菜等),蔬菜(土豆片/豆芽/花菜/生菜等),,Ingredient,,蔬菜,,,,,,,,300-500,g,True,,,,, +201000043,Ingredient,红油豆瓣酱,红油豆瓣酱,,Ingredient,,调料,,,,,,,,40,g,False,,,,, +201000044,Ingredient,豆豉,豆豉,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201000045,Ingredient,藤椒油,藤椒油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201000046,Ingredient,菜籽油,菜籽油,,Ingredient,,调料,,,,,,,,25,ml,False,,,,, +201000047,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201000048,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,2,瓣,False,,,,, +201000049,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201000050,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201000051,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,巴沙鱼若从冷冻柜取出,放室温自然解冻5小时,再切片处理。,1.0,解冻,,5小时 +201000052,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将巴沙鱼撇成约5cm长、3cm宽的薄片。,2.0,切,刀, +201000053,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将鱼片放入大不锈钢碗中,加入30g豆瓣酱、3g盐、10ml藤椒油、3g白胡椒粉,用手抓匀后加入5ml菜籽油封味,常温静置至少30分钟入味。,3.0,腌制,大不锈钢碗,30分钟 +201000054,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,大蒜切成蒜末;以300g花菜、200g生菜为例,将蔬菜洗净。,4.0,"切,洗","刀,盆", +201000055,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,花菜开水锅焯水备用;生菜洗净晾干后炒熟备用(不用放油)。,5.0,"焯水,炒","锅,漏勺", +201000056,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,热锅冷油(菜籽油20ml),加入10g豆瓣酱、10g豆豉(可选)和蒜末,中火慢炒。,6.0,炒,"炒锅,锅铲", +201000057,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入150ml热水,水开后放入腌制好的鱼片,轻轻翻动使其散开,加入2g盐和2g糖调味,水再次沸腾即可盛盘。,7.0,煮,"锅,漏勺", +201000058,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,先将熟蔬菜盛至大碗中,再将热鱼片铺在蔬菜上,浇上锅中剩余热汤即可。,8.0,盛盘,大碗, +201000059,Recipe,清蒸生蚝,清蒸生蚝,,Recipe,"[{'term': '清清蒸生蚝', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '清steamed生蚝', 'language': 'zh', 'language_code': 'zh-CN'}]",水产,3.0,,5分钟,6.5分钟,1人,,dishes\aquatic\清蒸生蚝.md,,,,,,,, +201000060,Ingredient,生蚝,生蚝,,Ingredient,,蛋白质,,,,,,,,6,个,True,,,,, +201000061,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,1,升,False,,,,, +201000062,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,3,颗,False,,,,, +201000063,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,6,瓣,False,,,,, +201000064,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,1,小块,False,,,,, +201000065,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,6,毫升,False,,,,, +201000066,Ingredient,刷子,刷子,,Ingredient,,工具,,,,,,,,1,把,False,,,,, +201000067,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将生蚝用刷子刷干净(没有刷子用牙刷)。,1.0,清洗,刷子, +201000068,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,蒸锅中放水,将蒸屉放上之后,将6个生蚝平铺在蒸屉,使用50%功率,蒸3分钟。,2.0,蒸,"蒸锅,蒸屉",3分钟 +201000069,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,用右手拿着湿抹布掀开烫锅盖,将每个生蚝的外壳掀开一半去掉,生蚝的凸面向下,平面向上,每个放1根姜丝、10g蒜末放到生蚝上。,3.0,"掀盖,去壳,摆盘","湿抹布,蒸锅", +201000070,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,关上烫锅盖,100%功率蒸3.5分钟。,4.0,蒸,蒸锅,3.5分钟 +201000071,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,停火,用右手拿着抹布掀开烫锅盖,每个放5ml酱油。,5.0,"调味,掀盖","抹布,蒸锅", +201000072,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,盛盘。,6.0,装盘,, +201000073,Recipe,红烧鱼,红烧鱼,,Recipe,"[{'term': 'braised鱼', 'language': 'en', 'language_code': 'en-US'}]",水产,4.0,,约10分钟(切配姜蒜辣椒、处理鱼),约8-10分钟(煎鱼+炖煮+收汁),1条鱼(1-2人),"新手建议用鲫鱼,煎鱼前擦干水分防溅油,小火煎鱼防糊,收汁到鱼鳍下位置即可,小米椒最多2个防过辣",dishes\aquatic\红烧鱼.md,,,,,,,, +201000074,Ingredient,鲫鱼,鲫鱼,,Ingredient,,蛋白质,,,,,,,,1,条,True,,,,, +201000075,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,2,片,False,,,,, +201000076,Ingredient,蒜瓣,蒜瓣,,Ingredient,,蔬菜,,,,,,,,3.5,个,False,,,,, +201000077,Ingredient,干辣椒,干辣椒,,Ingredient,,蔬菜,,,,,,,,2.5,个,False,,,,, +201000078,Ingredient,油,油,,Ingredient,,调料,,,,,,,,40,毫升,False,,,,, +201000079,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000080,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201000081,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201000082,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201000083,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000084,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000085,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1.5,根,False,,,,, +201000086,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,适量,,False,,,,, +201000087,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,1.5,个,False,,,,, +201000088,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000089,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,姜蒜切碎,干辣椒切碎,与姜蒜一起备用。,1.0,切,"刀,案板",约3分钟 +201000090,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中加入30-50ml油,小火加热至锅热。,2.0,加热,炒锅,约30秒 +201000091,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将擦干水分的鱼放入锅中,小火煎至底部金黄,期间晃动锅防止粘锅。,3.0,煎,"炒锅,锅铲",约2-3分钟 +201000092,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,翻面,重复煎另一面至金黄。,4.0,煎,锅铲,约2-3分钟 +201000093,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入姜蒜辣椒碎,翻炒出香味。,5.0,炒,锅铲,约30秒 +201000094,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入适量料酒,迅速产生大量油烟,注意安全。,6.0,炝锅,锅铲,约15秒 +201000095,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入醋、白砂糖、酱油(老抽),翻炒均匀。,7.0,炒,锅铲,约15秒 +201000096,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入冷水,刚好淹没鱼身,转中火,盖锅盖1分钟后翻面,再盖锅盖继续炖煮3-4分钟。,8.0,炖,"炒锅,锅盖",约4-5分钟 +201000097,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入盐、小米椒、蚝油、味精,盖锅盖继续炖煮并适时翻面。,9.0,炖,"锅铲,锅盖",约2-3分钟 +201000098,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,汤汁收至鱼鳍下方位置时转小火,加入香菜和葱花,盖锅盖20秒后关火。,10.0,焖,锅盖,20秒 +201000099,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,起锅装盘。,11.0,装盘,锅铲,约10秒 +201000100,Recipe,红烧鱼头,红烧鱼头,,Recipe,"[{'term': 'braised鱼头', 'language': 'en', 'language_code': 'en-US'}]",水产,4.0,,1-2小时(腌制)+ 15分钟(切配),约30分钟(炒制+焖煮+收汁),2人,"使用厚菜刀更安全,花鲢鱼头口感更佳,腌制去腥,收汁提味",dishes\aquatic\红烧鱼头.md,,,,,,,, +201000101,Ingredient,鱼头,鱼头,,Ingredient,,蛋白质,,,,,,,,1,个,True,,,,, +201000102,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,200,g,False,,,,, +201000103,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,80,g,False,,,,, +201000104,Ingredient,蒜瓣,蒜瓣,,Ingredient,,蔬菜,,,,,,,,3.5,个,False,,,,, +201000105,Ingredient,美人椒,美人椒,,Ingredient,,蔬菜,,,,,,,,0.25,个,False,,,,, +201000106,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,4,棵,False,,,,, +201000107,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,个,False,,,,, +201000108,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,5,个,False,,,,, +201000109,Ingredient,油,油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201000110,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,7,g,False,,,,, +201000111,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201000112,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,g,False,,,,, +201000113,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,g,False,,,,, +201000114,Ingredient,陈醋,陈醋,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201000115,Ingredient,黑胡椒粉,黑胡椒粉,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201000116,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,g,False,,,,, +201000117,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,500,ml,False,,,,, +201000118,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,葱、姜、蒜、香菜、美人椒分别清洗干净;干辣椒与八角稍微冲洗。,1.0,清洗,"刀,案板,盆",5分钟 +201000119,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,大葱切两半:葱白切段约4 cm,葱叶切段后劈四瓣;姜切3 mm片;蒜拍碎;两棵香菜切1.5 cm碎;美人椒切3 mm圈;干辣椒切四段。,2.0,切,"刀,案板",10分钟 +201000120,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,鱼头去鳞、清理内脏、剁去鱼鳍、清理鱼鳃,将鱼头下巴与鱼身连接处剁开,鱼身切块,鱼头剁成4-6瓣,再次清洗血水。,3.0,"剁,清洗","菜刀,盆",10分钟 +201000121,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将鱼块放入盆中,加5 g盐、10 g生抽、10 g料酒、切碎的葱叶段、1/3姜片拌匀,静置腌制1-2小时。,4.0,腌制,盆,1-2小时 +201000122,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中加30 ml油,小火加热,放入姜片炒至金黄出汁。,5.0,炒,"炒锅,锅铲",1-2分钟 +201000123,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入葱白段翻炒至略发白,再加入蒜碎、八角、干辣椒翻炒5秒。,6.0,炒,"炒锅,锅铲",30秒 +201000124,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,倒入腌制好的鱼头翻炒2-3分钟。,7.0,炒,"炒锅,锅铲",2-3分钟 +201000125,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入500 ml清水,调入2 g盐、3 g鸡精、5 g生抽、3 g老抽、5 g料酒、2 g黑胡椒粉、3 g陈醋,放入两棵香菜,盖锅盖,大火烧开后转中火慢焖。,8.0,"煮,焖","炒锅,锅盖",15分钟 +201000126,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,汤汁减半时开盖,大火收汁至剩余1/3,关火。将汤汁均匀淋在鱼头上,香菜垫底装饰,再放上剩余香菜和美人椒圈。,9.0,"收汁,装盘","锅铲,小盆",5分钟 +201000127,Recipe,红烧鲤鱼,红烧鲤鱼,,Recipe,"[{'term': 'braised鲤鱼', 'language': 'en', 'language_code': 'en-US'}]",水产,4.0,鲁菜,约15分钟,约25分钟,2人,"五花肉煸炒出猪油更香,动物油脂提升鱼类香味,炖煮后五花肉可当配菜,鱼类脂肪含量低需猪油增香",dishes\aquatic\红烧鲤鱼.md,,,,,,,, +201000128,Ingredient,鲤鱼,鲤鱼,,Ingredient,,蛋白质,,,,,,,,1000,克,True,,,,, +201000129,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,100,克,False,,,,, +201000130,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,200,克,False,,,,, +201000131,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,80,克,False,,,,, +201000132,Ingredient,蒜瓣,蒜瓣,,Ingredient,,蔬菜,,,,,,,,3.5,个,False,,,,, +201000133,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,2,个,False,,,,, +201000134,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,50,克,False,,,,, +201000135,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,50,毫升,False,,,,, +201000136,Ingredient,陈醋,陈醋,,Ingredient,,调料,,,,,,,,50,毫升,False,,,,, +201000137,Ingredient,味极鲜,味极鲜,,Ingredient,,调料,,,,,,,,50,毫升,False,,,,, +201000138,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201000139,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201000140,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000141,Ingredient,油,油,,Ingredient,,调料,,,,,,,,适量,毫升,False,,,,, +201000142,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,没过鱼面,毫升,False,,,,, +201000143,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,葱、姜、蒜、干辣椒分别清洗干净。,1.0,清洗,盆, +201000144,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱白处切段,每段长度约4cm,再将每段劈为四瓣。,2.0,切,"刀,案板", +201000145,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,姜切片,每片厚度约3mm。,3.0,切,"刀,案板", +201000146,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,一个大蒜拍碎切末,其余蒜切为二瓣。,4.0,"拍,切","刀,案板", +201000147,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,干辣椒切四段。,5.0,切,"刀,案板", +201000148,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,五花肉切片,约4cm×4cm。,6.0,切,"刀,案板", +201000149,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,清洗鱼。,7.0,清洗,盆, +201000150,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,鱼背肉厚处拉几道斜口,方便入味。,8.0,切,"刀,案板", +201000151,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,锅里多倒点油,烧至7成热(刚刚开始冒烟),下入鱼炸1分钟至鱼皮稍稍变硬捞出备用,炸鱼的油倒出,锅里留一点底油。,9.0,炸,"炒锅,锅铲",1分钟 +201000152,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将锅里底油烧热,下入五花肉,煸出香味。,10.0,煸,"炒锅,锅铲", +201000153,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,放入干辣椒、葱、姜、蒜瓣,翻炒1分钟。,11.0,炒,"炒锅,锅铲",1分钟 +201000154,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,将炸好的鱼倒入锅中。,12.0,倒,锅铲, +201000155,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,沿锅边倒入料酒50ml、陈醋50ml、味极鲜50ml、老抽20ml、蚝油5ml、盐5g、白糖50g、清水没过鱼面。,13.0,倒,锅铲, +201000156,CookingStep,步骤14,步骤14,,CookingStep,,,,,,,,,,,,,调至中火,将水烧开。,14.0,烧,炒锅, +201000157,CookingStep,步骤15,步骤15,,CookingStep,,,,,,,,,,,,,调至小火,慢焖入味。,15.0,焖,"炒锅,锅盖", +201000158,CookingStep,步骤16,步骤16,,CookingStep,,,,,,,,,,,,,15分钟后,打开锅盖,挑出锅里的葱、姜、蒜、干辣椒。,16.0,挑,筷子,15分钟 +201000159,CookingStep,步骤17,步骤17,,CookingStep,,,,,,,,,,,,,调至大火收汁,汤汁剩余1/4时,撒点蒜末,关火盛出。,17.0,"收汁,撒,关火",锅铲, +201000160,Recipe,小龙虾,小龙虾,,Recipe,,水产,4.0,川菜,15-20分钟(刷洗、去虾线、切配料),25-30分钟(煎香料、炒酱、煮虾),2斤小龙虾(约2-3人份),"家庭版免油炸,可保留虾线,香辣口味,啤酒提鲜",dishes\aquatic\小龙虾\小龙虾.md,,,,,,,, +201000161,Ingredient,小龙虾,小龙虾,,Ingredient,,蛋白质,,,,,,,,2,斤,True,,,,, +201000162,Ingredient,油,油,,Ingredient,,调料,,,,,,,,70,毫升,False,,,,, +201000163,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201000164,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,个,False,,,,, +201000165,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201000166,Ingredient,青花椒,青花椒,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000167,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000168,Ingredient,子弹头辣椒,子弹头辣椒,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000169,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201000170,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,30,克,False,,,,, +201000171,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,7,瓣,False,,,,, +201000172,Ingredient,郫县豆瓣,郫县豆瓣,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201000173,Ingredient,黄豆酱,黄豆酱,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201000174,Ingredient,啤酒,啤酒,,Ingredient,,调料,,,,,,,,500,毫升,False,,,,, +201000175,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,毫升,False,,,,, +201000176,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000177,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,小龙虾刷干净去虾线,葱切2cm葱段,姜蒜切末。,1.0,"清洗,切","刷子,刀,案板",10-15分钟 +201000178,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,烧油,油微热,下香叶、八角、桂皮、青花椒、花椒、子弹头辣椒。,2.0,"煎,炒",炒锅,30-60秒 +201000179,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,香料出香气之后下锅葱姜蒜。,3.0,炒,炒锅,30秒 +201000180,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,葱姜蒜爆香后,加入郫县豆瓣、黄豆酱,炒出红油。,4.0,炒,炒锅,1-2分钟 +201000181,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,下小龙虾,翻炒至变色。,5.0,炒,炒锅,3-5分钟 +201000182,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入啤酒,等啤酒烧开后加入生抽、盐。,6.0,"煮,调味",炒锅,2-3分钟 +201000183,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将小龙虾完全煮熟后出锅。,7.0,煮,炒锅,8-10分钟 +201000184,Recipe,干煎阿根廷红虾,干煎阿根廷红虾,,Recipe,"[{'term': '干pan-fried阿根廷红虾', 'language': 'zh', 'language_code': 'zh-CN'}]",水产,3.0,,提前1天冷藏解冻+10分钟,约5分钟,1人,"趁热吃,柠檬可增酸提味,可按喜好增减",dishes\aquatic\干煎阿根廷红虾\干煎阿根廷红虾.md,,,,,,,, +201000185,Ingredient,阿根廷红虾,阿根廷红虾,,Ingredient,,蛋白质,,,,,,,,2-3,只,True,,,,, +201000186,Ingredient,海盐,海盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000187,Ingredient,黑胡椒,黑胡椒,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000188,Ingredient,白葡萄酒,白葡萄酒,,Ingredient,,调料,,,,,,,,20,毫升,False,,,,, +201000189,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,毫升,False,,,,, +201000190,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,3,片,False,,,,, +201000191,Ingredient,柠檬,柠檬,,Ingredient,,蔬菜,,,,,,,,1,片,False,,,,, +201000192,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,10,克,False,,,,, +201000193,Ingredient,生姜,生姜,,Ingredient,,蔬菜,,,,,,,,10,克,False,,,,, +201000194,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,10,克,False,,,,, +201000195,Ingredient,橄榄油,橄榄油,,Ingredient,,调料,,,,,,,,2调羹,,False,,,,, +201000196,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,阿根廷红虾提前1天从速冻取出放到冷藏里自然解冻,可买已开背去虾线的成品,1.0,解冻,冰箱,24小时 +201000197,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,解冻好的红虾洗净擦干,用厨房用纸吸干水分,2.0,"清洗,擦干",厨房用纸,2分钟 +201000198,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,生姜切片,洋葱切小方块,香菜洗净叶茎分离,香菜叶切碎,大蒜压碎切末,3.0,"切,压碎","刀,案板,压蒜器",3分钟 +201000199,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,大火热锅,倒入橄榄油,油温升高后放入生姜片、洋葱块和香菜茎煸炒,4.0,"热锅,煸炒","平底锅,锅铲",1分钟 +201000200,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,约1分钟后取出姜、洋葱和香菜茎,弃用,5.0,取出,锅铲,1分钟 +201000201,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,调中大火,放入红虾单面煎2分钟,同时给每只虾刷一层油,6.0,煎,"平底锅,刷子",2分钟 +201000202,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,待底面虾壳微焦黄时翻面,撒入大蒜碎末,轻晃锅使受热均匀,7.0,"翻面,撒料,晃动","锅铲,平底锅",1分钟 +201000203,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入20ml白葡萄酒继续煎1分钟,8.0,煎,平底锅,1分钟 +201000204,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,调中小火,均匀撒盐和黑胡椒,每只虾滴一滴生抽,9.0,调味,手,30秒 +201000205,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,撒上香菜叶装盘,切好柠檬片摆盘边即可,10.0,装盘,刀,30秒 +201000206,Recipe,油焖大虾,油焖大虾,,Recipe,"[{'term': '油闷大虾', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '油braised大虾', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'oil-braised大虾', 'language': 'en', 'language_code': 'en-US'}]",水产,4.0,鲁菜,约10分钟(剪虾枪、虾须、挑沙包、开背去虾线、洗净),约15-20分钟(炸料油、煎虾、焖煮、收汁),1人,"老饭骨,真·味道,葱油可拌面",dishes\aquatic\油焖大虾\油焖大虾.md,,,,,,,, +201000207,Ingredient,黑虎虾/明虾,黑虎虾/明虾,,Ingredient,,蛋白质,,,,,,,,10,只,True,,,,, +201000208,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000209,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,50,克,False,,,,, +201000210,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,20,克,False,,,,, +201000211,Ingredient,黄酒,黄酒,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201000212,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201000213,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,克,False,,,,, +201000214,Ingredient,植物油,植物油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000215,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,剪虾枪到根上,虾须虾爪都剪掉,沙包挑掉,开背虾线挑出来,洗净备用,1.0,切,"剪刀,刀,案板,盆",约5-8分钟 +201000216,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,炸料油:油温三成热放花椒,油热离火,放葱姜(不要让油变色最好),葱稍微变黄沥油,2.0,炸,"炒锅,锅铲,漏勺",约2-3分钟 +201000217,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,下油,虾摆放整齐,两面变色后轻轻摁虾头,3.0,煎,"炒锅,锅铲",约2-3分钟 +201000218,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,放姜米(姜切成细颗粒)、黄酒30g、水两小碗、盐3g、冰糖10克,4.0,炒,锅铲,约30秒 +201000219,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,大火烧开转小火盖盖子焖(中途不能再加汤水,不要开盖),5.0,焖,"炒锅,锅盖",约5-8分钟 +201000220,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,皮亮虾弯就可以起锅,虾摆盘,6.0,摆盘,"筷子,盘子",约30秒 +201000221,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,收汁:过滤后倒回锅里收浓,放葱油,汤汁剩余1/4时,7.0,收汁,"锅铲,漏勺",约2-3分钟 +201000222,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,浇汁,完成,8.0,浇汁,"锅铲,勺子",约30秒 +201000223,Recipe,烤鱼,烤鱼,,Recipe,"[{'term': 'baked鱼', 'language': 'en', 'language_code': 'en-US'}, {'term': '烘烤鱼', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'roasted鱼', 'language': 'en', 'language_code': 'en-US'}]",水产,4.0,川菜,20分钟(腌制)+ 10分钟(切配),25分钟(烤/煎+煮),1份,食盐、胡椒粉、孜然粉、食用油、生抽、白糖等可按个人口味调整,dishes\aquatic\混合烤鱼\烤鱼.md,,,,,,,, +201000224,Ingredient,草鱼,草鱼,,Ingredient,,蛋白质,,,,,,,,1500,克,True,,,,, +201000225,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,0.5,根,False,,,,, +201000226,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,20,毫升,False,,,,, +201000227,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,12.5,毫升,False,,,,, +201000228,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,7.5,克,False,,,,, +201000229,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,7.5,克,False,,,,, +201000230,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,1,小片,False,,,,, +201000231,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,个,False,,,,, +201000232,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,8,粒,False,,,,, +201000233,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201000234,Ingredient,青花椒,青花椒,,Ingredient,,调料,,,,,,,,1,小把,False,,,,, +201000235,Ingredient,干辣椒段,干辣椒段,,Ingredient,,调料,,,,,,,,10,个,False,,,,, +201000236,Ingredient,灯笼椒,灯笼椒,,Ingredient,,蔬菜,,,,,,,,4,个,False,,,,, +201000237,Ingredient,芹菜段,芹菜段,,Ingredient,,蔬菜,,,,,,,,2,根,False,,,,, +201000238,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,0.5,个,False,,,,, +201000239,Ingredient,千张,千张,,Ingredient,,蛋白质,,,,,,,,1,张,False,,,,, +201000240,Ingredient,绿豆芽,绿豆芽,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201000241,Ingredient,火锅底料,火锅底料,,Ingredient,,调料,,,,,,,,0.5,包,False,,,,, +201000242,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,17.5,克,False,,,,, +201000243,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,克,False,,,,, +201000244,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,毫升,False,,,,, +201000245,Ingredient,孜然粉,孜然粉,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000246,Ingredient,熟花生米,熟花生米,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201000247,Ingredient,白芝麻,白芝麻,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201000248,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,适量,,False,,,,, +201000249,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,草鱼从背部切开,两面沿背部划几刀,不要划破鱼肚;用热水或刷子洗净表面粘液。,1.0,"切,清洗","刀,刷子",5分钟 +201000250,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鱼放入容器,加料酒、白胡椒粉、食盐抹匀,腌制二十分钟入味。,2.0,腌制,容器,20分钟 +201000251,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大葱切块,大蒜粒对半切,与八角、香叶、桂皮放同一容器;干辣椒段、灯笼椒切段放另一容器;芹菜切段;豆芽、千张焯水,千张切丝;洋葱切丝。,3.0,"切,焯水","刀,案板,锅,漏勺",10分钟 +201000252,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,烤箱版:烤盘刷底油,鱼皮朝下烤至两面金黄,撒孜然粉。无烤箱版:热锅热油,锅边撒少量盐防粘,下鱼煎至两面金黄,撒孜然粉后出锅装盘。,4.0,"烤,煎","烤箱/平底锅,锅铲",10分钟 +201000253,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中倒20ml食用油,油热后下大葱、大蒜、八角、香叶炒香。,5.0,炒,"炒锅,锅铲",1分钟 +201000254,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入半包火锅底料和豆瓣酱炒出红油,放白糖、食盐、生抽调味,倒入与食材齐平的清水煮开。,6.0,"炒,煮","炒锅,锅铲",3分钟 +201000255,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,依次下芹菜段、豆芽、千张丝稍烫后铺洋葱丝,放上烤鱼,再铺干辣椒、灯笼椒、青花椒。,7.0,"煮,铺","炒锅,锅铲",2分钟 +201000256,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,另起锅烧热油,浇在辣椒上激香,最后撒熟花生米、葱花、白芝麻、香菜,再煮5-6分钟即可。,8.0,"浇油,煮","小锅,锅铲",5-6分钟 +201000257,Recipe,清蒸鲈鱼,清蒸鲈鱼,,Recipe,"[{'term': '清steamed鲈鱼', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '清清蒸鲈鱼', 'language': 'zh', 'language_code': 'zh-CN'}]",水产,3.0,粤菜,10分钟(腌制)+ 5分钟(处理与改刀),10分钟(蒸),1条鱼,"火候关键,大火蒸10分钟,筷子隔开蒸防腥,均匀受热,鱼肉不老",dishes\aquatic\清蒸鲈鱼\清蒸鲈鱼.md,,,,,,,, +201000258,Ingredient,鲈鱼,鲈鱼,,Ingredient,,蛋白质,,,,,,,,1,条,True,,,,, +201000259,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,3,根,False,,,,, +201000260,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,1,块,False,,,,, +201000261,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,毫升,False,,,,, +201000262,Ingredient,蒸鱼豉油,蒸鱼豉油,,Ingredient,,调料,,,,,,,,10-15,毫升,False,,,,, +201000263,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10-15,毫升,False,,,,, +201000264,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,5-10,克,False,,,,, +201000265,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,姜切片切丝、香葱的葱白切段,葱绿切丝,切丝后放入冷水浸泡备用。,1.0,切,"刀,案板,冷水碗",2分钟 +201000266,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鲈鱼处理好后洗净,用厨房纸擦干,两面分别划几刀,用盐洗掉鱼身的粘液,并用10g盐抹遍鱼身的内外,腌制10分钟以上。,2.0,"洗,腌制,切","厨房纸,刀,案板,盆",10分钟 +201000267,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,鱼肚内塞上姜和葱白,鱼身也撒上姜和葱白,量为备用的一半。蒸鱼的碟子用筷子将鱼跟碟子隔开蒸。,3.0,摆盘,"碟子,筷子",1分钟 +201000268,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,水烧热感觉到水温后放进入鱼,大火清蒸10分钟。,4.0,蒸,"蒸锅,大火",10分钟 +201000269,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,蒸好的鱼,用干净的盘子装起来并去除身上姜蒜。,5.0,装盘,"干净盘子,筷子",30秒 +201000270,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,鱼身浇上15ml蒸鱼豉油。,6.0,浇汁,量勺,15秒 +201000271,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,鱼身重新撒上姜和葱丝,锅内加上10ml食用油并烧热,将食用油淋至鱼身即可出菜。,7.0,淋油,"锅,量勺,锅铲",30秒 +201000272,Recipe,白灼虾,白灼虾,,Recipe,,水产,2.0,粤菜,5分钟,11分钟(中火1分钟+小火5分钟+关火焖5分钟),1人,"开始不能大火防止糊底,锅盖有通气口需增加30秒中火,蘸料可选纯醋,鲜虾无需蘸料也鲜甜",dishes\aquatic\白灼虾\白灼虾.md,,,,,,,, +201000273,Ingredient,虾,虾,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201000274,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201000275,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,1,块,False,,,,, +201000276,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,1,头,False,,,,, +201000277,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,5-8,瓣,False,,,,, +201000278,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201000279,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,ml,False,,,,, +201000280,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201000281,Ingredient,芝麻,芝麻,,Ingredient,,调料,,,,,,,,1,把,False,,,,, +201000282,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201000283,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201000284,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,洋葱切小块,姜切片,平铺平底锅。,1.0,切,"刀,案板,平底锅",2分钟 +201000285,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,活虾冲洗一下(去除虾线、剪刀减掉虾腿虾须子都是可选操作),控水,铺在平底锅的洋葱、姜片之上。,2.0,"冲洗,控水,铺","剪刀,盆",2分钟 +201000286,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅内倒入料酒,盖上锅盖,中火1分钟,小火5分钟,关火5分钟。,3.0,"煮,焖","平底锅,锅盖",11分钟 +201000287,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,制作蘸料:葱切成葱花、蒜切碎、倒入酱油、芝麻、香醋,搅拌之。,4.0,"切,搅拌","刀,案板,碗,筷子",2分钟 +201000288,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,油烧热,淋入蘸料。,5.0,"热油,淋","锅,勺子",30秒 +201000289,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,虾出锅,用干净的盘子装好。,6.0,装盘,盘子,30秒 +201000290,Recipe,糖醋鲤鱼,糖醋鲤鱼,,Recipe,"[{'term': 'sweet and sour鲤鱼', 'language': 'en', 'language_code': 'en-US'}]",水产,4.0,鲁菜,30分钟(腌制),约15分钟(炸鱼+熬汁),3人以上,"对新手不太友好,适合家庭聚餐,年夜饭",dishes\aquatic\糖醋鲤鱼\糖醋鲤鱼.md,,,,,,,, +201000291,Ingredient,鲤鱼,鲤鱼,,Ingredient,,蛋白质,,,,,,,,3,斤,True,,,,, +201000292,Ingredient,番茄酱,番茄酱,,Ingredient,,调料,,,,,,,,40,克,False,,,,, +201000293,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,克,False,,,,, +201000294,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000295,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,10,克,False,,,,, +201000296,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201000297,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,30,克,False,,,,, +201000298,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,30,克,False,,,,, +201000299,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,25,克,False,,,,, +201000300,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,颗,False,,,,, +201000301,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,100,克,False,,,,, +201000302,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201000303,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,50,克,False,,,,, +201000304,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将鱼清洗干净,确保无鱼鳞等异物,1.0,清洗,盆, +201000305,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将鱼头朝左,鱼肚朝下,右手持刀。刀竖直切下1cm,按紧鱼身往左片3-4cm,再将鱼片中间轻轻划一刀,2.0,切,"菜刀,案板", +201000306,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将鱼放进盆里,然后将大姜切片,大葱切段,用吃奶的力气将大葱大姜里的汁水挤到盆中,3.0,"切,挤汁","盆,菜刀", +201000307,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入20g盐、25g料酒,给鲤鱼搓澡,涂抹均匀,腌制30分钟以上,4.0,腌制,盆,30分钟 +201000308,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,在干净盆中加入100g面粉、200g淀粉、180g水、5g盐,搅拌均匀后加入一个鸡蛋,再次搅匀成可拉丝面糊,5.0,搅拌,盆, +201000309,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,等待30分钟,6.0,静置,,30分钟 +201000310,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将鱼放在案板上,用干毛巾擦干鱼身水分,盆冲洗干净并擦干,7.0,擦干,"干毛巾,盆", +201000311,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,起锅烧油,加入约1L油,油温烧至7成热(200-240℃),8.0,炸,"锅,锅铲,笊篱", +201000312,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,捏鱼尾,鱼头先入油锅,用勺子淋热油定型,面糊成型后整鱼入锅,用笊篱托鱼头防糊,9.0,炸,"锅,锅铲,笊篱", +201000313,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,用锅铲和笊篱配合给鱼翻身,再炸2分钟,出锅装盘,10.0,炸,"锅铲,笊篱,盘子",2分钟 +201000314,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将锅中油倒出,锅刷干净,11.0,"倒油,清洗",锅, +201000315,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,小碗混合50g清水、40g番茄酱、20g白糖、10g白醋,搅拌均匀,12.0,搅拌,小碗, +201000316,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,另取小碗,10g淀粉加10g水调成水淀粉,13.0,搅拌,小碗, +201000317,CookingStep,步骤14,步骤14,,CookingStep,,,,,,,,,,,,,大火烧热锅,倒入料汁,烧开后转小火,加入水淀粉边倒边搅,20秒后关火,14.0,"煮,搅拌","锅,勺子",20秒 +201000318,CookingStep,步骤15,步骤15,,CookingStep,,,,,,,,,,,,,将糖醋汁均匀浇在鱼身上,撒香菜或葱花点缀即可,15.0,浇汁,"勺子,盘子", +201000319,Recipe,芥末黄油罗氏虾,芥末黄油罗氏虾,,Recipe,,水产,3.0,,约10分钟,约15分钟,1盘,"酱汁提前调配,黄油提前备好,蒜蓉后放防焦苦,芥末量可调整",dishes\aquatic\芥末黄油罗氏虾\芥末黄油罗氏虾.md,,,,,,,, +201000320,Ingredient,罗氏虾,罗氏虾,,Ingredient,,蛋白质,,,,,,,,500,克,True,,,,, +201000321,Ingredient,黄油,黄油,,Ingredient,,其他,,,,,,,,20,克,False,,,,, +201000322,Ingredient,芥末,芥末,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201000323,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,克,False,,,,, +201000324,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,克,False,,,,, +201000325,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201000326,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201000327,Ingredient,料酒、朗姆酒或啤酒,料酒、朗姆酒或啤酒,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201000328,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,5,条,False,,,,, +201000329,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,5,颗,False,,,,, +201000330,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将罗氏虾剪掉头尾尖刺、触须和脚,剪刀把虾身开背,去除虾线。,1.0,切,剪刀,约5分钟 +201000331,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,提前搅拌好芥末酱汁:酱油、蚝油、芥末、盐、糖,搅拌均匀!,2.0,搅拌,"碗,筷子",约2分钟 +201000332,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,洗好香菜,切段备用。,3.0,切,"刀,案板",约1分钟 +201000333,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,罗氏虾沥掉水,锅中加入油,直接放入罗氏虾,中火,外表煎至金黄,捞出。,4.0,煎,"炒锅,锅铲",约3-4分钟 +201000334,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,下入蒜蓉,大火,利用煎虾剩下的油继续煎炒蒜蓉,等到锅中白雾冒出,蒜蓉已经煎出香味,下虾和黄油,让虾充分吸收黄油香味。,5.0,炒,"炒锅,锅铲",约2分钟 +201000335,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,下入调好的酱汁,继续大火煮沸,翻炒虾,至酱汁收汁,加入酒(料酒、啤酒可以放30g,朗姆酒味道浓郁放15g即可)。,6.0,"炒,煮","炒锅,锅铲",约3-4分钟 +201000336,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,在等酱汁稍微收汁,加入香菜翻炒两下,即可出锅。,7.0,炒,锅铲,约30秒 +201000337,Recipe,葱油桂鱼,葱油桂鱼,,Recipe,,水产,4.0,粤菜,20分钟(含腌制10分钟),25分钟(含蒸鱼20分钟+熬油5分钟),2份,"成功率高,容错性强,兼容各地口味,可替换鱼类:鲈鱼、多宝鱼等海鱼,不建议使用淡水鱼",dishes\aquatic\葱油桂鱼\葱油桂鱼.md,,,,,,,, +201000338,Ingredient,桂鱼,桂鱼,,Ingredient,,蛋白质,,,,,,,,500,克,True,,,,, +201000339,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,根,False,,,,, +201000340,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,2,个,False,,,,, +201000341,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,50,克,False,,,,, +201000342,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,25,克,False,,,,, +201000343,Ingredient,植物油,植物油,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201000344,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,8,克,False,,,,, +201000345,Ingredient,蒸鱼豉油,蒸鱼豉油,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000346,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,5000,毫升,False,,,,, +201000347,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,去菜市场买已经处理好的鱼(自己处理的话最好不要内脏),将鱼身表面的所有鳞片刮干净,1.0,处理,菜刀, +201000348,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用厨房用纸将鱼肚子里的贴骨血和黑膜擦干净(帖骨血会影响口感,黑膜是鱼腥味的来源),2.0,清理,厨房纸, +201000349,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,用菜刀在鱼身表面来回刮几次,将鱼身的黏液刮掉,进一步去除腥味,然后用清水将鱼内外冲洗干净,3.0,"清理,冲洗",菜刀, +201000350,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将鱼平放在砧板,使用厨房纸将鱼内外的水分擦干,然后鱼头朝左,尾朝右,从鱼鳃边开始,每隔3cm纵向划一刀,深度达到鱼的脊椎骨即可,另一面使用同样的处理方式,4.0,切,"砧板,厨房纸,菜刀", +201000351,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将鱼平放在盆中,确保盘中没有多余水分,5.0,摆放,塑料盆, +201000352,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,取一块50g姜,用削皮刀把表面的皮去除并洗干净,然后切成厚度为3mm的姜片,6.0,"去皮,切","削皮刀,菜刀", +201000353,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将小米辣洗干净、去蒂,切成厚度为2mm的小圆片(或切成1mm宽度的丝状),7.0,切,菜刀, +201000354,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将小葱洗干净,去除根须,切成3cm的小段,稍微粗一点的小葱,可以沿中间劈开,8.0,切,菜刀, +201000355,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入8g盐、25g料酒到盆中,带上一次性手套,对鱼进行全身按摩1分钟,确保鱼身每个部位都均匀涂抹了盐和料酒,9.0,"腌制,按摩","塑料盆,一次性手套",1分钟 +201000356,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,在鱼身的每一个刀口中塞入一片姜片,鱼肚子中放入3片姜片,腌制10分钟,10.0,腌制,塑料盆,10分钟 +201000357,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,在鱼腌制期间,在蒸锅中加入5L清水,烧开后,在蒸锅上放上蒸笼,11.0,烧水,"蒸锅,蒸笼", +201000358,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,鱼腌制好后,会析出水分,将多余水分和腌制用料酒、姜片倒掉,用清水冲洗干净鱼身和鱼肚,用厨房纸擦干,12.0,"冲洗,擦干",厨房纸, +201000359,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,将鱼平放在蒸鱼盘中,重新在鱼身、鱼肚刀口处塞入姜片,13.0,摆放,蒸鱼盘, +201000360,CookingStep,步骤14,步骤14,,CookingStep,,,,,,,,,,,,,将蒸鱼盘放入蒸笼中,盖上盖子,中火蒸20分钟,14.0,蒸,"蒸笼,防烫夹",20分钟 +201000361,CookingStep,步骤15,步骤15,,CookingStep,,,,,,,,,,,,,用防烫夹将蒸鱼盘夹出,在鱼身和鱼周围淋上10g蒸鱼豉油,15.0,淋汁,防烫夹, +201000362,CookingStep,步骤16,步骤16,,CookingStep,,,,,,,,,,,,,在鱼身和周围均匀撒上小葱段和小米辣,16.0,撒料,, +201000363,CookingStep,步骤17,步骤17,,CookingStep,,,,,,,,,,,,,在铁锅中倒入15g植物油,用中小火慢熬5分钟,不要用大火,否则油会挥发很快,17.0,熬油,铁锅,5分钟 +201000364,CookingStep,步骤18,步骤18,,CookingStep,,,,,,,,,,,,,将出锅后的热油均匀地慢慢地淋在鱼身上,鲜掉眉毛的葱油桂鱼就出炉啦!,18.0,淋油,铁锅, +201000365,Recipe,葱烧海参,葱烧海参,,Recipe,,水产,3.0,鲁菜,5分钟,约15分钟,1份,"注意水量,小火煎葱防焦,汤汁粘稠即关火",dishes\aquatic\葱烧海参\葱烧海参.md,,,,,,,, +201000366,Ingredient,泡发好的海参(北极参),泡发好的海参(北极参),,Ingredient,,蛋白质,,,,,,,,4,个,True,,,,, +201000367,Ingredient,大葱葱白,大葱葱白,,Ingredient,,蔬菜,,,,,,,,1,根,True,,,,, +201000368,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,20,毫升,False,,,,, +201000369,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201000370,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,克,False,,,,, +201000371,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,克,False,,,,, +201000372,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,2,克,False,,,,, +201000373,Ingredient,水,水,,Ingredient,,其他,,,,,,,,100,毫升,False,,,,, +201000374,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,葱白切成1cm的段,备用。,1.0,切,"刀,案板",1分钟 +201000375,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,海参切成1cm的段,备用。,2.0,切,"刀,案板",1分钟 +201000376,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,准备一个空碗,倒入20g蚝油、5g生抽、2g白糖,搅拌均匀成料汁。,3.0,搅拌,"碗,筷子",30秒 +201000377,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,另一个空碗倒入淀粉和少量水,制备水淀粉,用于勾芡。,4.0,混合,"碗,筷子",30秒 +201000378,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅,锅内放入20-25ml食用油,等待10秒让油温升高。,5.0,"热锅,倒油",炒锅,10秒 +201000379,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入葱白,调小火,煎至葱白微黄不焦,约3-5分钟。,6.0,煎,"炒锅,筷子",3-5分钟 +201000380,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,用筷子夹出葱白,放入盘中备用。,7.0,取出,"筷子,盘子",10秒 +201000381,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入调好的料汁,炒香,等待1-2分钟。,8.0,炒,锅铲,1-2分钟 +201000382,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,放入切好的海参,翻炒1分钟。,9.0,炒,锅铲,1分钟 +201000383,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入100ml水,转中小火,炖煮5分钟。,10.0,炖,锅铲,5分钟 +201000384,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,待锅中汤汁快干时,加入水淀粉和之前取出的葱白,翻炒至汤汁粘稠。,11.0,"勾芡,炒",锅铲,30秒 +201000385,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,汤汁呈粘稠状态后关火,盛盘。,12.0,盛盘,"锅铲,盘子",10秒 +201000386,Recipe,蒜蓉虾,蒜蓉虾,,Recipe,,水产,2.0,粤菜,5分钟,3分钟,1,,dishes\aquatic\蒜蓉虾\蒜蓉虾.md,,,,,,,, +201000387,Ingredient,海虾,海虾,,Ingredient,,蛋白质,,,,,,,,8,只,True,,,,, +201000388,Ingredient,蒜蓉酱,蒜蓉酱,,Ingredient,,调料,,,,,,,,50,g,False,,,,, +201000389,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201000390,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201000391,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,用刀从虾头中间切开,切到距离虾尾1 cm,1.0,切,刀,1-2分钟 +201000392,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将蒜蓉酱铺在虾身中间,放在盘子中,2.0,铺,盘子,30秒 +201000393,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中倒入热水,将盘子放入锅中,大火蒸3分钟,3.0,蒸,"蒸锅,盘子",3分钟 +201000394,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,烧热油,倒入虾盘中,倒入生抽,4.0,"烧热,倒","锅,盘子",30秒 +201000395,Recipe,蒜香黄油虾,蒜香黄油虾,,Recipe,,水产,2.0,,约5分钟,约4-5分钟,1-2人,虾不宜过度烹饪,否则会变硬,dishes\aquatic\蒜香黄油虾\蒜香黄油虾.md,,,,,,,, +201000396,Ingredient,大虾,大虾,,Ingredient,,蛋白质,,,,,,,,200,克,True,,,,, +201000397,Ingredient,无盐黄油,无盐黄油,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201000398,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,20,克,False,,,,, +201000399,Ingredient,白葡萄酒,白葡萄酒,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201000400,Ingredient,柠檬,柠檬,,Ingredient,,蔬菜,,,,,,,,0.25,个,False,,,,, +201000401,Ingredient,橄榄油,橄榄油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201000402,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,大虾去头去壳留尾,用牙签挑去虾线,洗净后用厨房纸吸干水分,1.0,"切,腌制","牙签,厨房纸",约2分钟 +201000403,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,大蒜切成蒜末,备用,2.0,切,"刀,案板",约1分钟 +201000404,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,中火加热平底锅,放入10ml橄榄油,3.0,加热,平底锅,约30秒 +201000405,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,油热后放入大虾,每面煎1-1.5分钟至变色,取出备用,4.0,煎,"平底锅,厨房用夹",2-3分钟 +201000406,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,同一锅中加入黄油,融化后放入蒜末,小火炒香(约30秒),5.0,"炒,融化",平底锅,30秒 +201000407,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,如使用白葡萄酒,此时加入并煮至酒精挥发(约1分钟),6.0,煮,平底锅,1分钟 +201000408,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将虾放回锅中,与蒜香黄油酱汁翻炒均匀(约1分钟),7.0,炒,"平底锅,锅铲",1分钟 +201000409,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,挤入柠檬汁,翻炒均匀后立即关火,8.0,炒,平底锅,10秒 +201000410,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,装盘,淋上锅中剩余酱汁,9.0,装盘,锅铲,10秒 +201000411,Recipe,蛏抱蛋,蛏抱蛋,,Recipe,,水产,3.0,闽菜,约5分钟(去壳、切洋葱、调腌料),约10分钟(焯水2分钟+煎炸约8分钟),1份,"福州传统家常菜,可加入马蹄或马铃薯解腻,闽菜偏甜可不加糖,听声辨炸透技巧",dishes\aquatic\蛏抱蛋\蛏抱蛋.md,,,,,,,, +201000412,Ingredient,蛏子,蛏子,,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201000413,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201000414,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,100,ml,False,,,,, +201000415,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,0.25,个,False,,,,, +201000416,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,20,g,False,,,,, +201000417,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201000418,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201000419,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201000420,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,烧开水,将蛏子放入水中,水煮2分钟后,捞上来去壳,放入大碗,1.0,煮,"锅,漏勺,大碗",2分钟 +201000421,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,往大碗中加入洋葱、生抽、料酒、鸡精、淀粉后,充分搅拌,2.0,拌,"大碗,筷子或勺子",约1分钟 +201000422,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,往大碗中打入2个鸡蛋,继续搅拌,3.0,拌,"大碗,筷子或勺子",约30秒 +201000423,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,起锅烧油,倒入碗中蛏子,煎炸至单面金黄后,翻面继续煎炸,4.0,煎炸,"炒锅,锅铲",约6-8分钟 +201000424,Recipe,香煎翘嘴鱼,香煎翘嘴鱼,,Recipe,"[{'term': '香pan-fried翘嘴鱼', 'language': 'zh', 'language_code': 'zh-CN'}]",水产,4.0,湘菜,腌制1-2天 + 晾晒1-2天,煎2-3分钟 + 煮5-10分钟 + 小火焖2-5分钟,2-3人,"开背杀鱼,腌制1-2天,晾晒至半干,煎鱼全程小火,刚入锅不要移动鱼防破皮,青椒最后放,豆瓣酱提鲜,白糖调鲜,陈醋增香",dishes\aquatic\香煎翘嘴鱼\香煎翘嘴鱼.md,,,,,,,, +201000425,Ingredient,翘嘴鱼,翘嘴鱼,,Ingredient,,蛋白质,,,,,,,,2,斤,True,,,,, +201000426,Ingredient,姜沫,姜沫,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201000427,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,50,克,False,,,,, +201000428,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,4,个,False,,,,, +201000429,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,适量,,False,,,,, +201000430,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,毫升,False,,,,, +201000431,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,克,False,,,,, +201000432,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000433,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,4-6,个,False,,,,, +201000434,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,100,毫升,False,,,,, +201000435,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,4,毫升,False,,,,, +201000436,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,50,克,False,,,,, +201000437,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,100,毫升,False,,,,, +201000438,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,适量,,False,,,,, +201000439,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000440,Ingredient,十三香,十三香,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000441,Ingredient,陈醋,陈醋,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000442,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鱼开背杀好(让卖鱼的杀好,千万不要剖腹杀鱼,切记是开背),清洗干净,1.0,切,刀, +201000443,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鱼表面用盐涂抹均匀,倒入料酒约80ml、姜末20g,放入冰箱保鲜层进行腌制1-2天,2.0,腌制,"盆,冰箱",1-2天 +201000444,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,取出腌制好的鱼,用绳挂起晾晒至半干(约1-2天,具体时间需结合气温与阳光),3.0,晾晒,绳,1-2天 +201000445,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,食用前请将鱼用清水清洗,沥干水分(防止水遇油飞溅),4.0,清洗,盆, +201000446,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,开大火将锅烧热,迅速改小火,锅中放油,尽量保持整个锅表面有油,将鱼沿锅边划入锅内(先煎鱼背面),5.0,煎,"炒锅,锅铲", +201000447,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,鱼入锅后(和翻面后),不要着急移动鱼的位置(此时容易破皮),煎约30秒后,尝试晃动锅,6.0,煎,炒锅,30秒 +201000448,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,背面煎约1分钟后,翻面煎约1-2分钟,煎至两面金黄,7.0,煎,锅铲,2-3分钟 +201000449,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,等两面都煎好时,把鱼推向锅边一点,留点空间放入豆瓣酱炒出香味,放入姜蒜,8.0,炒,锅铲, +201000450,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,炒出佐料香味后,加入料酒、生抽、老抽,倒入热水,水量和鱼平齐或者少点,9.0,"炒,煮",锅铲, +201000451,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,此时改中大火,煮5-10分钟,后放入青椒段、白糖、鸡精、十三香、陈醋,10.0,煮,锅铲,5-10分钟 +201000452,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,改小火2-5分钟,放入葱、香菜,即可出锅,11.0,焖,锅铲,2-5分钟 +201000453,Recipe,鲤鱼炖白菜,鲤鱼炖白菜,,Recipe,"[{'term': '鲤鱼煲白菜', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲤鱼炖cabbage', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲤鱼炖大白菜', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲤鱼炖小白菜', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲤鱼stewed白菜', 'language': 'zh', 'language_code': 'zh-CN'}]",水产,3.0,川菜,约10分钟,约20-25分钟,1人份,"可加粉条,不吃辣可不放干辣椒",dishes\aquatic\鲤鱼炖白菜\鲤鱼炖白菜.md,,,,,,,, +201000454,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201000455,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,3,片,False,,,,, +201000456,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,3,瓣,False,,,,, +201000457,Ingredient,鲤鱼,鲤鱼,,Ingredient,,蛋白质,,,,,,,,1.2,斤,True,,,,, +201000458,Ingredient,娃娃菜,娃娃菜,,Ingredient,,蔬菜,,,,,,,,13,片,True,,,,, +201000459,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5-8,克,False,,,,, +201000460,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,ml,False,,,,, +201000461,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,6,ml,False,,,,, +201000462,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,1,块,False,,,,, +201000463,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,个,False,,,,, +201000464,Ingredient,郫县豆瓣酱,郫县豆瓣酱,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201000465,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,4-6,个,False,,,,, +201000466,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鲤鱼清洗干净,改刀(在鱼身上多划几个伤口,方便入味),1.0,切,刀, +201000467,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,娃娃菜清洗干净放入盘中备用,2.0,清洗,盆, +201000468,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中加油,等油热放入“少盐”“姜”“蒜”“郫县豆瓣酱”“桂皮”“八角”炒出香味,3.0,炒,"锅,锅铲", +201000469,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,把鱼放锅里煎(3分钟)每30秒需要翻面,4.0,煎,"锅,锅铲",3分钟 +201000470,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入“水”(水量尽量和鱼平齐,可以少一点点)放入“生抽”“老抽”“娃娃菜”,5.0,煮,锅, +201000471,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,大火炖15-20分钟,汤汁快干时添加“盐”即可出锅,6.0,炖,锅,15-20分钟 +201000472,Recipe,鳊鱼炖豆腐,鳊鱼炖豆腐,,Recipe,"[{'term': '鳊鱼炖老豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鳊鱼炖tofu', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鳊鱼炖嫩豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鳊鱼煲豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鳊鱼stewed豆腐', 'language': 'zh', 'language_code': 'zh-CN'}]",水产,3.0,,5-10分钟,20-25分钟,2-3人,"煎鱼时中小火,每面煎2-4分钟,出锅前加蒜末更香",dishes\aquatic\鳊鱼炖豆腐\鳊鱼炖豆腐.md,,,,,,,, +201000473,Ingredient,鳊鱼,鳊鱼,,Ingredient,,蛋白质,,,,,,,,550,克,True,,,,, +201000474,Ingredient,老豆腐,老豆腐,,Ingredient,,蛋白质,,,,,,,,400,克,True,,,,, +201000475,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,5,片,False,,,,, +201000476,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,50,克,False,,,,, +201000477,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,4,个,False,,,,, +201000478,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,毫升,False,,,,, +201000479,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,1,块,False,,,,, +201000480,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,块,False,,,,, +201000481,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,4,个,False,,,,, +201000482,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,毫升,False,,,,, +201000483,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,4,毫升,False,,,,, +201000484,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000485,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,个,False,,,,, +201000486,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,1,片,False,,,,, +201000487,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201000488,Ingredient,热水,热水,,Ingredient,,其他,,,,,,,,400,克,False,,,,, +201000489,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鳊鱼改刀,放上姜片和料酒腌制5-10分钟,1.0,"切,腌制","刀,盆",5-10分钟 +201000490,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,老豆腐切块后放入水中备用,2.0,切,"刀,案板,盆", +201000491,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中加油,可以放点盐在锅里,防止煎鱼的时候粘锅,把腌制的鱼用厨房纸擦干水分,把鱼放到锅中,两面都煎一下,3.0,煎,"炒锅,锅铲,厨房纸",每面2-4分钟 +201000492,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,等两面都煎好时,把鱼推向锅边一点,留点空间放入葱姜蒜、干辣椒、香叶、八角炒出味道,4.0,炒,"炒锅,锅铲", +201000493,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,炒出佐料香味后,加入料酒、生抽、老抽、冰糖、桂皮,倒入热水,水量和鱼平齐或者少点,5.0,炖,炒锅, +201000494,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,大火烧开后,放入老豆腐,豆腐贴在锅边,加入食盐,转小火,6.0,炖,炒锅, +201000495,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,小火烧10-15分钟,然后大火收点汁,即可出锅,7.0,"炖,收汁",炒锅,10-15分钟 +201000496,Recipe,黄油煎虾,黄油煎虾,,Recipe,"[{'term': '黄油pan-fried虾', 'language': 'en', 'language_code': 'en-US'}]",水产,3.0,,约20分钟(处理活虾、开背、调汁),约5分钟(热锅、煎炒、收汁),1,"虾开背才更好入味,处理时切记小心用刀",dishes\aquatic\黄油煎虾\黄油煎虾.md,,,,,,,, +201000497,Ingredient,鲜虾,鲜虾,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201000498,Ingredient,黄油,黄油,,Ingredient,,调料,,,,,,,,7,g,False,,,,, +201000499,Ingredient,黑胡椒粒,黑胡椒粒,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201000500,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,45,ml,False,,,,, +201000501,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201000502,Ingredient,米酒,米酒,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201000503,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201000504,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2.5,ml,False,,,,, +201000505,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鲜虾摘除头部,顺带扯出虾线(这步处理不好可在下一步开背时取出虾线),使用剪刀剪开或菜刀片开虾背,沥干水分备用,1.0,切,"剪刀,菜刀,案板", +201000506,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,调制酱汁:小碗放入上述量的全部生抽、米酒、白糖、盐搅匀备用,2.0,搅拌,"小碗,筷子", +201000507,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,中大火热锅,热锅内放入食用油,等待10秒让油温升高,3.0,炒,炒锅,10秒 +201000508,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,虾全部放入锅中,开始瓶磨黑胡椒,均匀地撒在虾上翻炒,4.0,炒,"炒锅,锅铲", +201000509,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,虾变色后加入黄油,黄油完全融化后倒入调制酱汁,继续翻炒,5.0,炒,"炒锅,锅铲", +201000510,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,大火翻炒15秒收汁即可装盘,6.0,炒,"炒锅,锅铲",15秒 +201000511,Recipe,吐司果酱,吐司果酱,,Recipe,,早餐,1.0,,0分钟,2分钟,1人,"快速,懒人,无额外垃圾,免清洗,边走边吃",dishes\breakfast\吐司果酱.md,,,,,,,, +201000512,Ingredient,吐司,吐司,,Ingredient,,淀粉类,,,,,,,,2,片,True,,,,, +201000513,Ingredient,果酱,果酱,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000514,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将吐司放入面包机,1.0,烤,面包机, +201000515,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,"设置好档位,时间到了会自动弹出",2.0,烤,面包机, +201000516,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,两分钟后吐司加热完成弹出,3.0,烤,面包机,2分钟 +201000517,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,"先取出一片吐司,涂满果酱再盖上另一片吐司即可",4.0,涂抹,面包机, +201000518,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,用餐巾纸包一下可以边走边吃也可以吃完再出门,5.0,,餐巾纸, +201000519,Recipe,太阳蛋,太阳蛋,,Recipe,,早餐,2.0,,2分钟,3-5分钟,1人,"微波炉技巧,蛋黄戳孔防炸,火候控制",dishes\breakfast\太阳蛋.md,,,,,,,, +201000520,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201000521,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201000522,Ingredient,油,油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201000523,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,准备一个小碗,倒入计算好的油,撒盐,搅拌均匀。倾斜碗使油沾在碗表面。,1.0,搅拌,"小碗,筷子或牙签",30秒 +201000524,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,取出一个鸡蛋,打入小碗。,2.0,打蛋,小碗,10秒 +201000525,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,蛋黄表面戳孔。牙签戳5个或筷子戳1个。,3.0,戳孔,牙签或筷子,10秒 +201000526,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,放入微波炉,中火3分钟(可控火候微波炉)或1分钟后每30秒检查一次(不可控火候微波炉)。,4.0,微波,微波炉,3-5分钟 +201000527,Recipe,完美水煮蛋,完美水煮蛋,,Recipe,,早餐,5.0,,0分钟(无需额外准备),32分30秒,1人份,"蛋黄中心温度67±1°C,蛋白分层温度100°C→87°C→55°C→30°C,多酚含量比传统煮法高23%,循环水煮法",dishes\breakfast\完美水煮蛋.md,,,,,,,, +201000528,Ingredient,新鲜鸡蛋,新鲜鸡蛋,,Ingredient,,蛋白质,,,,,,,,1,个,True,,,,, +201000529,Ingredient,100°C沸水,100°C沸水,,Ingredient,,其他,,,,,,,,1500,毫升,False,,,,, +201000530,Ingredient,30°C温水,30°C温水,,Ingredient,,其他,,,,,,,,1500,毫升,False,,,,, +201000531,Ingredient,冰水,冰水,,Ingredient,,其他,,,,,,,,适量,毫升,False,,,,, +201000532,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,准备两锅水:A锅维持100°C沸水,B锅维持30°C温水,1.0,煮,锅, +201000533,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用漏勺将鸡蛋放入A锅,启动定时器,2.0,煮,"漏勺,锅,定时器", +201000534,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,精准每2分钟将鸡蛋转移至另一锅水,3.0,煮,"漏勺,锅",2分钟 +201000535,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,重复转移操作共16次(总时长32分钟),4.0,煮,"漏勺,锅",32分钟 +201000536,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,最后一次转移后,在B锅静置30秒,5.0,静置,锅,30秒 +201000537,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,立即放入冰水(0摄氏度)终止加热(维持30秒),6.0,冷却,冰水盆,30秒 +201000538,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,剥壳时从钝端气室处开始,沿纵轴剥离蛋膜,7.0,剥壳,, +201000539,Recipe,微波炉荷包蛋,微波炉荷包蛋,,Recipe,,早餐,1.0,,1分钟,80秒,1人,盖盖子防溅射,dishes\breakfast\微波炉荷包蛋.md,,,,,,,, +201000540,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201000541,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,35,毫升,False,,,,, +201000542,Ingredient,芝麻油,芝麻油,,Ingredient,,调料,,,,,,,,3,毫升,False,,,,, +201000543,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,0.8,克,False,,,,, +201000544,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将鸡蛋打入小碗中,用筷子在所有鸡蛋黄上扎2个洞,避免加热弄脏微波炉,1.0,切,"小碗,筷子",20秒 +201000545,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,然后向碗内倒入常温饮用水,2.0,倒,小碗,5秒 +201000546,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,再向碗内倒入食用盐,3.0,倒,小碗,5秒 +201000547,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,最后加入芝麻油,4.0,倒,小碗,5秒 +201000548,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将放好材料的碗放入微波炉中,高火加热80秒,5.0,微波,"微波炉,碗",80秒 +201000549,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,到达设定时间后,使用抹布垫着手取出成品,6.0,取,"抹布,碗",10秒 +201000550,Recipe,微波炉蛋糕,微波炉蛋糕,,Recipe,,早餐,1.0,,20分钟(初学者),2分钟,1人份,"泡打粉让蛋糕更蓬松,食材不超过容器3/4,液体需少量多次加入防止湿瘪,可重复操作做更大蛋糕",dishes\breakfast\微波炉蛋糕.md,,,,,,,, +201000551,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201000552,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,15,g,True,,,,, +201000553,Ingredient,泡打粉,泡打粉,,Ingredient,,调料,,,,,,,,2.5,g,False,,,,, +201000554,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201000555,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201000556,Ingredient,黄油,黄油,,Ingredient,,其他,,,,,,,,半个鸡蛋大,,True,,,,, +201000557,Ingredient,咖啡粉,咖啡粉,,Ingredient,,调料,,,,,,,,可选,,False,,,,, +201000558,Ingredient,巧克力,巧克力,,Ingredient,,其他,,,,,,,,可选,,False,,,,, +201000559,Ingredient,麦片,麦片,,Ingredient,,淀粉类,,,,,,,,可选,,False,,,,, +201000560,Ingredient,牛奶,牛奶,,Ingredient,,其他,,,,,,,,可选,,False,,,,, +201000561,Ingredient,坚果,坚果,,Ingredient,,其他,,,,,,,,可选,,False,,,,, +201000562,Ingredient,饼干屑,饼干屑,,Ingredient,,淀粉类,,,,,,,,可选,,False,,,,, +201000563,Ingredient,香蕉,香蕉,,Ingredient,,其他,,,,,,,,可选,,False,,,,, +201000564,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,挖半个鸡蛋大的黄油放进容器,在微波炉加热15秒至融化,1.0,加热,"微波炉,容器",15秒 +201000565,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将巧克力/香蕉融化/搅碎成颗粒/糊状,2.0,搅碎,容器, +201000566,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,打入一个鸡蛋并打散搅和,3.0,打散,容器, +201000567,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入15g白糖、1g盐、2.5g泡打粉、15g面粉,并加入任何喜欢的口味食材(坚果与饼干等干食材除外),搅和至看不见干粉的稠酸奶状,4.0,搅拌,容器, +201000568,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入可选的干燥食材在顶端,5.0,加入,容器, +201000569,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,微波炉高火加热1分钟至蓬松蛋糕形态,6.0,加热,微波炉,1分钟 +201000570,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,取出杯子并享用,7.0,取出,, +201000571,Recipe,手抓饼,手抓饼,,Recipe,,早餐,2.0,,30分钟(含醒面20分钟+松弛10分钟),约5分钟,1~2人,"开水与冷水混合和面提升饼皮柔韧度,面团醒发时间不少于20分钟,配料总重控制在100克以内,生饼皮可冷藏保存24小时",dishes\breakfast\手抓饼.md,,,,,,,, +201000572,Ingredient,普通面粉,普通面粉,,Ingredient,,淀粉类,,,,,,,,200,克,True,,,,, +201000573,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,100,毫升,False,,,,, +201000574,Ingredient,冷水,冷水,,Ingredient,,其他,,,,,,,,50,毫升,False,,,,, +201000575,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201000576,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201000577,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201000578,Ingredient,生菜,生菜,,Ingredient,,蔬菜,,,,,,,,30,克,True,,,,, +201000579,Ingredient,火腿,火腿,,Ingredient,,蛋白质,,,,,,,,30,克,True,,,,, +201000580,Ingredient,芝士片,芝士片,,Ingredient,,蛋白质,,,,,,,,1,片,True,,,,, +201000581,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,面粉放入碗中,加入开水搅拌成絮状,再加入冷水揉成光滑面团,覆盖湿布静置 20 分钟。,1.0,"搅拌,揉,静置","碗,湿布",20分钟 +201000582,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,面团分成每份约 100 克,搓圆,擀成薄片。,2.0,"分份,搓,擀","擀面杖,案板", +201000583,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,表面均匀涂抹食用油,撒上盐,卷成蜗牛状,松弛 10 分钟。,3.0,"涂抹,撒,卷,松弛",刷子或勺子,10分钟 +201000584,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,面团再次擀成薄饼,厚度均匀。,4.0,擀,"擀面杖,案板", +201000585,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅中倒入油,小火煎至两面金黄起泡。,5.0,煎,"平底锅,锅铲",约2-3分钟 +201000586,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,煎好的饼依次铺入煎蛋、生菜、火腿、芝士片等配料,卷起即可。,6.0,"煎,铺,卷","平底锅,锅铲",约1-2分钟 +201000587,Recipe,桂圆红枣粥,桂圆红枣粥,,Recipe,,早餐,2.0,,20分钟,60分钟,1,"可调整水量控制稀稠,甜度可通过桂圆数量调节",dishes\breakfast\桂圆红枣粥.md,,,,,,,, +201000588,Ingredient,糯米,糯米,,Ingredient,,淀粉类,,,,,,,,100,g,True,,,,, +201000589,Ingredient,红枣,红枣,,Ingredient,,蔬菜,,,,,,,,15,颗,True,,,,, +201000590,Ingredient,桂圆,桂圆,,Ingredient,,其他,,,,,,,,15,颗,True,,,,, +201000591,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将桂圆肉扒出,用清水洗两次,放入碗中浸泡10分钟,1.0,"洗,浸泡",碗,10分钟 +201000592,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,红枣用清水洗两次,放入碗中浸泡10分钟,2.0,"洗,浸泡",碗,10分钟 +201000593,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,糯米放入电饭锅中,清水淘米两次后,加入2000ml水,3.0,"淘洗,加水",电饭锅, +201000594,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将桂圆和红枣加入电饭锅,4.0,加入,电饭锅, +201000595,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,打开电饭锅煮饭模式,1小时后粥成,5.0,煮,电饭锅,60分钟 +201000596,Recipe,水煮玉米,水煮玉米,,Recipe,,早餐,2.0,,5分钟,15-20分钟,1人份,,dishes\breakfast\水煮玉米.md,,,,,,,, +201000597,Ingredient,新鲜玉米,新鲜玉米,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201000598,Ingredient,水,水,,Ingredient,,其他,,,,,,,,50,毫升,False,,,,, +201000599,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201000600,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000601,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将新鲜玉米剥去外皮,剩部分玉米皮入锅,1.0,切,刀, +201000602,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入淹过玉米约半节指头的水,加盐和糖,2.0,加,锅, +201000603,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,水煮开之后转至小火,加盖继续煮15-20分钟,玉米煮久点没事,3.0,煮,"锅,锅盖",15-20分钟 +201000604,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,煮熟后沥干水分,冷却后食用,4.0,"沥水,冷却",漏勺, +201000605,Recipe,溏心蛋,溏心蛋,,Recipe,,早餐,3.0,,1分钟,15分钟,1颗或更多,"溏心蛋有沙门氏菌感染风险,可依据喜好调整水量,不建议静置5分钟以内",dishes\breakfast\溏心蛋.md,,,,,,,, +201000606,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,颗,True,,,,, +201000607,Ingredient,水,水,,Ingredient,,其他,,,,,,,,2,公分,False,,,,, +201000608,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将鸡蛋放入电锅中。鸡蛋不可互相堆叠,应皆在底部,并留有空间可以晃动,1.0,放置,电锅, +201000609,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,倒入淹过鸡蛋约 2 公分的冷水,2.0,倒水,电锅, +201000610,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,开盖,使用最大功率加热至水滚起(大约 85 - 95 度,稍微滚动,不需完全沸腾),3.0,加热,电锅, +201000611,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,关火,盖上盖子,让鸡蛋静置。想要中央有流动的蛋黄,需静置 6 分钟;若想要完全煮熟的易碎蛋黄,需静置 10 分钟,4.0,焖,"电锅,盖子",6-10分钟 +201000612,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,沥干水分,用冷水冲洗鸡蛋约 1 分钟,即可去壳食用,5.0,"冲洗,去壳",冷水,1分钟 +201000613,Recipe,煎饺,煎饺,,Recipe,"[{'term': 'pan-fried饺', 'language': 'en', 'language_code': 'en-US'}]",早餐,2.0,,0分钟,10-12分钟,1人,需时刻观察锅内情况,不可分神玩手机,dishes\breakfast\煎饺.md,,,,,,,, +201000614,Ingredient,速冻水饺,速冻水饺,,Ingredient,,淀粉类,,,,,,,,10-15,个,True,,,,, +201000615,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,毫升,False,,,,, +201000616,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,没过饺子高度1/2,毫升,False,,,,, +201000617,Ingredient,黑芝麻,黑芝麻,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000618,Ingredient,葱花,葱花,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201000619,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,取出平底锅(不沾平底锅最佳),1.0,,平底锅, +201000620,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入10-15ml食用油,2.0,倒,平底锅, +201000621,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,开火,放入饺子(尽量平均铺开,不宜堆叠),3.0,放,平底锅, +201000622,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,立刻加入清水,水线没过饺子平均高度的1/2,4.0,倒,平底锅, +201000623,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,盖上锅盖(此时炉灶应该处于大火),5.0,焖,"平底锅,锅盖",8-10分钟 +201000624,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,当锅中水分仅剩2mm时,转中火开始煎制,6.0,煎,平底锅, +201000625,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,当水分全部蒸发后,摇晃平底锅使饺子受热均匀,7.0,煎,平底锅, +201000626,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入黑芝麻和葱花再焖10秒,8.0,焖,"平底锅,锅盖",10秒 +201000627,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,1-2分钟夹出一个饺子观察底部,若出现金黄色脆皮立即取出,9.0,煎,"平底锅,筷子",1-2分钟 +201000628,Recipe,燕麦鸡蛋饼,燕麦鸡蛋饼,,Recipe,,早餐,2.0,,5分钟,5分钟,1人份,"小火煎制,可加盐胡椒调味,避免燕麦煎糊",dishes\breakfast\燕麦鸡蛋饼.md,,,,,,,, +201000629,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201000630,Ingredient,纯干燕麦片,纯干燕麦片,,Ingredient,,淀粉类,,,,,,,,50,克,True,,,,, +201000631,Ingredient,牛奶,牛奶,,Ingredient,,其他,,,,,,,,50,毫升,True,,,,, +201000632,Ingredient,蔬菜(菠菜等),蔬菜(菠菜等),,Ingredient,,蔬菜,,,,,,,,50,克,False,,,,, +201000633,Ingredient,黄油,黄油,,Ingredient,,其他,,,,,,,,适量,克,False,,,,, +201000634,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,克,False,,,,, +201000635,Ingredient,胡椒,胡椒,,Ingredient,,调料,,,,,,,,适量,克,False,,,,, +201000636,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将牛奶与干燕麦混合搅拌均匀至黏稠状。,1.0,搅拌,"碗,筷子或勺子",1分钟 +201000637,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将鸡蛋搅拌均匀至颜色单一程度。,2.0,搅拌,"碗,筷子或打蛋器",30秒 +201000638,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将鸡蛋液倒入燕麦牛奶中继续搅拌至黏稠、均匀。,3.0,搅拌,"碗,筷子或勺子",30秒 +201000639,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,平底锅中加入一层黄油并覆盖均匀。,4.0,"加热,抹油","平底锅,锅铲或刷子",30秒 +201000640,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,下入搅拌好的食材,并摊开至饼状。,5.0,摊平,"平底锅,锅铲",30秒 +201000641,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,小火加热两到三分钟。如想要加入蔬菜,可以在加热过程中加入碎菜叶。,6.0,煎,"平底锅,锅铲",2-3分钟 +201000642,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,翻面继续加热两分钟。,7.0,煎,"平底锅,锅铲",2分钟 +201000643,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,出锅,搭配剩下的牛奶作为早餐。,8.0,装盘,盘子,30秒 +201000644,Recipe,牛奶燕麦,牛奶燕麦,,Recipe,,早餐,1.0,,1分钟,3分钟,1人份,"微波炉火力不同需自行调整,混合物不超过容器容量50%,不建议使用玻璃杯烹饪",dishes\breakfast\牛奶燕麦.md,,,,,,,, +201000645,Ingredient,牛奶,牛奶,,Ingredient,,蛋白质,,,,,,,,280,ml,True,,,,, +201000646,Ingredient,燕麦,燕麦,,Ingredient,,淀粉类,,,,,,,,40,g,True,,,,, +201000647,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201000648,Ingredient,椒盐,椒盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201000649,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将牛奶倒入早餐杯(冷的即可),1.0,倒,早餐杯,10秒 +201000650,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,准备好200ml水,如果是直饮水直接加入燕麦,否则请烧开后加入燕麦,2.0,煮,锅,1分钟 +201000651,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,水沸后2分钟,燕麦煮好,3.0,煮,锅,2分钟 +201000652,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,煮好的燕麦捞出倒入牛奶中(尽量不要将煮燕麦的水也倒入牛奶,影响口感),4.0,捞,"漏勺,早餐杯",10秒 +201000653,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅,锅内放一层底油,油热后煎鸡蛋,每面煎20秒,考虑调底味(3g椒盐,可选),5.0,煎,"平底锅,锅铲",40秒 +201000654,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,关火,装盘,6.0,装盘,盘子,5秒 +201000655,Recipe,空气炸锅面包片,空气炸锅面包片,,Recipe,"[{'term': '空气油炸锅面包片', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '空气deep-fried锅面包片', 'language': 'zh', 'language_code': 'zh-CN'}]",早餐,1.0,,0分钟,5分钟,1份,"减脂期,全麦面包,粗粮面包",dishes\breakfast\空气炸锅面包片.md,,,,,,,, +201000656,Ingredient,面包片,面包片,,Ingredient,,淀粉类,,,,,,,,2,片,True,,,,, +201000657,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,取出两片面包片(建议使用粗粮面包片),1.0,取,, +201000658,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将面包片垂直放入空气炸锅,2.0,放置,空气炸锅, +201000659,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,200°C 烘烤 5 分钟,3.0,烤,空气炸锅,5分钟 +201000660,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,取出即可使用,4.0,取,, +201000661,Recipe,美式炒蛋,美式炒蛋,,Recipe,,早餐,2.0,,15分钟,3-5分钟,1,"使用不粘锅,可加入番茄丁/洋葱丁/培根丁/芝士丁,一人食可用小锅",dishes\breakfast\美式炒蛋.md,,,,,,,, +201000662,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,3,个,True,,,,, +201000663,Ingredient,全脂牛奶/奶油,全脂牛奶/奶油,,Ingredient,,其他,,,,,,,,10,克,False,,,,, +201000664,Ingredient,黄油,黄油,,Ingredient,,其他,,,,,,,,5,克,False,,,,, +201000665,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201000666,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡蛋打入大碗中,加盐搅打至起泡,静置15分钟,1.0,"切,搅拌,腌制","大碗,筷子或打蛋器",15分钟 +201000667,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,黄油切小块入锅,倒入蛋液,开小火不断搅拌,2.0,"切,炒,搅拌","平底锅,锅铲",1-2分钟 +201000668,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,黄油一融化,就快速翻动蛋液,将其打碎成细密状,在蛋液大体凝固前关火,3.0,"炒,搅拌","平底锅,锅铲",30秒 +201000669,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入牛奶搅拌15秒,至炒蛋湿润绵密,装盘,4.0,搅拌,锅铲,15秒 +201000670,Recipe,茶叶蛋,茶叶蛋,,Recipe,,早餐,3.0,,5分钟,30分钟,2-3人,"过冷水使蛋壳易剥,食盐可省略,可用现成卤料包替代香料",dishes\breakfast\茶叶蛋.md,,,,,,,, +201000671,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,400,g,True,,,,, +201000672,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,4,g,False,,,,, +201000673,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,0.5,g,False,,,,, +201000674,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201000675,Ingredient,茴香,茴香,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201000676,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,g,False,,,,, +201000677,Ingredient,红茶,红茶,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201000678,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,g,False,,,,, +201000679,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,25,g,False,,,,, +201000680,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201000681,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,用冷水将鸡蛋煮熟,大火大约8分钟,1.0,煮,锅,8分钟 +201000682,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鸡蛋捞出,过冷水,2.0,冷却,冷水盆, +201000683,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将鸡蛋互相碰撞,使每个鸡蛋产生裂缝,3.0,敲裂,手, +201000684,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将鸡蛋下锅,放入八角、香叶、桂皮、茴香、冰糖、红茶、生抽、老抽、食盐,加水直至没过鸡蛋,4.0,"加料,加水",锅, +201000685,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,大火煮开之后,转中小火煮15分钟,5.0,煮,锅,15分钟 +201000686,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,捞出料渣,鸡蛋再浸泡一会口感更佳,6.0,浸泡,锅, +201000687,Recipe,蒸水蛋,蒸水蛋,,Recipe,"[{'term': '清蒸水蛋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'steamed水蛋', 'language': 'en', 'language_code': 'en-US'}]",早餐,2.0,,5分钟,约10分钟(含水开与蒸4分钟),1人,"出锅稍晾即可食用,可加入蒸鱼豉油、葱花、香油作为佐料",dishes\breakfast\蒸水蛋.md,,,,,,,, +201000688,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201000689,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201000690,Ingredient,热水,热水,,Ingredient,,其他,,,,,,,,260,毫升,False,,,,, +201000691,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡蛋打入碗中,打散,1.0,切,"碗,筷子", +201000692,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,取其他容器,倒入1.5倍于蛋液的温水(温度20~30℃),将盐倒入水中化开,2.0,"混合,溶解","容器,筷子", +201000693,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将盐水倒入鸡蛋液中,单方向搅拌均匀,气泡可用勺子舀出丢弃,过筛则口感更加,3.0,"搅拌,过筛","碗,勺子,筛网", +201000694,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,使用锡纸包裹盛蛋液的碗(或用盘子盖住),置入提前带盖并加入约3cm深度水的锅中,4.0,"包裹,摆放","锡纸,碗,锅,盘子", +201000695,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,中火烧至水开,转最小的火继续蒸4分钟,5.0,蒸,"锅,锅盖",4分钟 +201000696,Recipe,蒸花卷,蒸花卷,,Recipe,"[{'term': '清蒸花卷', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'steamed花卷', 'language': 'en', 'language_code': 'en-US'}]",早餐,2.0,,2分钟,15分钟,1人(女生3个,男生5个),观察锅里的水不能少于50ml,dishes\breakfast\蒸花卷.md,,,,,,,, +201000697,Ingredient,冷冻花卷,冷冻花卷,,Ingredient,,淀粉类,,,,,,,,5,个,True,,,,, +201000698,Ingredient,水,水,,Ingredient,,其他,,,,,,,,400,毫升,False,,,,, +201000699,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,从花卷的包装袋中取出5个花卷,1.0,取,, +201000700,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,把花卷平铺在碟子上,尽量不用重叠,2.0,铺,圆碟子, +201000701,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,往锅里倒入400ml水,把蒸架放里面,把装花卷的碟子放在蒸架上,盖上锅盖,3.0,"倒,放,盖","锅,蒸架,锅盖", +201000702,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,开大火加热,直至水沸腾,4.0,加热,锅, +201000703,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,转中火加热15分钟,5.0,蒸,锅,15分钟 +201000704,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,开盖用手感受花卷的表面温度,如果不够热,就继续盖上盖子加热,否则就可以关火出锅,6.0,"检查,加热,关火","锅,锅盖", +201000705,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,碟子取出放凉至50度即可食用,7.0,"取,放凉",圆碟子, +201000706,Recipe,蛋煎糍粑,蛋煎糍粑,,Recipe,"[{'term': '蛋pan-fried糍粑', 'language': 'en', 'language_code': 'en-US'}]",早餐,2.0,,2分钟,8分钟,1人份,"放糍粑时注意间隔防止粘连,鸡蛋量根据糍粑量调整,糖量按个人口味增减",dishes\breakfast\蛋煎糍粑.md,,,,,,,, +201000707,Ingredient,糍粑,糍粑,,Ingredient,,淀粉类,,,,,,,,2,块,True,,,,, +201000708,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201000709,Ingredient,红糖,红糖,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000710,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201000711,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201000712,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,把糍粑切成长方形小块,便于后面煎,1.0,切,"刀,案板",1分钟 +201000713,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,碗里打入一个鸡蛋并把鸡蛋搅碎,加入2g食用盐,2.0,"打蛋,搅拌","碗,筷子",30秒 +201000714,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将切好的小糍粑依次放入搅碎的鸡蛋里面,涂抹完糍粑双面为止,3.0,裹蛋液,"碗,筷子",30秒 +201000715,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅里倒入植物油10ml,把涂抹好的糍粑小块放进去小火慢慢煎软,4.0,煎,"平底锅,锅铲",3-4分钟 +201000716,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将剩下的鸡蛋液慢慢倒在糍粑表面,5.0,倒蛋液,"碗,筷子",15秒 +201000717,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,用筷子或者勺子为糍粑翻面,来回煎至金黄色后开吃,6.0,"煎,翻面","筷子,锅铲",2-3分钟 +201000718,Recipe,金枪鱼酱三明治,金枪鱼酱三明治,,Recipe,,早餐,1.0,,约2分钟,约3分钟,1人份,"金枪鱼酱可提前一晚冷藏,金枪鱼酱冷藏不超过一周,使用保鲜膜覆盖,轻食机按压前勿接通电源",dishes\breakfast\金枪鱼酱三明治.md,,,,,,,, +201000719,Ingredient,水浸金枪鱼,水浸金枪鱼,,Ingredient,,蛋白质,,,,,,,,65,g,True,,,,, +201000720,Ingredient,方形吐司片,方形吐司片,,Ingredient,,淀粉类,,,,,,,,2,片,True,,,,, +201000721,Ingredient,蛋黄酱,蛋黄酱,,Ingredient,,调料,,,,,,,,50,mL,False,,,,, +201000722,Ingredient,俄式酸黄瓜汁,俄式酸黄瓜汁,,Ingredient,,调料,,,,,,,,10-15,mL,False,,,,, +201000723,Ingredient,芝士片,芝士片,,Ingredient,,蛋白质,,,,,,,,1,片,False,,,,, +201000724,Ingredient,火腿片,火腿片,,Ingredient,,蛋白质,,,,,,,,1,片,False,,,,, +201000725,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将金枪鱼、蛋黄酱、俄式酸黄瓜汁倒入碗中,用勺子搅拌,保证将金枪鱼块搅碎,酱整体呈糊状,并备用,1.0,搅拌,"碗,勺子",约1分钟 +201000726,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将1片吐司放在轻食机上,2.0,放置,轻食机,约5秒 +201000727,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将做好的金枪鱼酱涂抹到吐司上,建议10-15mL,3.0,涂抹,勺子,约30秒 +201000728,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将另一片方形吐司片覆盖在上面,并按压轻食机,开机,4.0,"覆盖,按压",轻食机,约5秒 +201000729,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,待轻食机自动停止加热,即可装盘使用,5.0,加热,轻食机,约2-3分钟 +201000730,Recipe,鸡蛋三明治,鸡蛋三明治,,Recipe,,早餐,2.0,,5分钟,5分钟,1人份,"可加芝士,可加酸黄瓜",dishes\breakfast\鸡蛋三明治.md,,,,,,,, +201000731,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201000732,Ingredient,吐司,吐司,,Ingredient,,淀粉类,,,,,,,,2,片,True,,,,, +201000733,Ingredient,培根,培根,,Ingredient,,蛋白质,,,,,,,,2,片,True,,,,, +201000734,Ingredient,黄油,黄油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201000735,Ingredient,蛋黄酱,蛋黄酱,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201000736,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201000737,Ingredient,黑胡椒,黑胡椒,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201000738,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,吐司切去四边,备用,1.0,切,"刀,案板",30秒 +201000739,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鸡蛋煮熟,捣碎,2.0,"煮,捣碎","锅,筷子或勺子",3-4分钟 +201000740,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,混合鸡蛋、蛋黄酱、盐、黑胡椒,3.0,混合,"碗,勺子",30秒 +201000741,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅中加入黄油,煎熟培根,4.0,煎,"平底锅,锅铲",1-2分钟 +201000742,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,组装吐司,在两片吐司间加入制作好的鸡蛋酱及培根,5.0,组装,"刀,案板",30秒 +201000743,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,四边形吐司切成三角形装盘,6.0,切,"刀,案板",20秒 +201000744,Recipe,温泉蛋,温泉蛋,,Recipe,,早餐,3.0,日式,5分钟,28分钟,1人,"70℃精准控温,25分钟杀菌,冰水迅速降温,使用厚锅更易控温,建议选用可生食鸡蛋",dishes\breakfast\温泉蛋\温泉蛋.md,,,,,,,, +201000745,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201000746,Ingredient,昆布酱油,昆布酱油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000747,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201000748,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,在锅中盛装一定量自来水,确保水面没过约鸡蛋3cm,水中插入温度计,1.0,准备,"锅,厨房用温度计", +201000749,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,开火或打开电磁炉,逐渐调整功率或火苗大小,使水温保持在70摄氏度,2.0,加热,厨房用温度计, +201000750,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将鸡蛋放入锅中,鸡蛋不可互相堆叠,应皆在底部,并留有空间可以晃动,3.0,煮,锅, +201000751,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,保持当前温度25分钟,4.0,煮,厨房用温度计,25分钟 +201000752,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,准备一杯冰水,5.0,准备,杯子, +201000753,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,捞出鸡蛋,并立刻放入冰水中,等待3分钟,6.0,冷却,杯子,3分钟 +201000754,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将鸡蛋打入小碗,完成制作,7.0,装盘,小碗, +201000755,Recipe,苏格兰蛋,苏格兰蛋,,Recipe,,早餐,3.0,,约5分钟,15-20分钟,1人份,芝士片、培根片、手抓饼可直接淘宝购买,dishes\breakfast\苏格兰蛋\苏格兰蛋.md,,,,,,,, +201000756,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,50,克,True,,,,, +201000757,Ingredient,手抓饼,手抓饼,,Ingredient,,淀粉类,,,,,,,,1.5,份,True,,,,, +201000758,Ingredient,芝士片,芝士片,,Ingredient,,蛋白质,,,,,,,,1.5,片,True,,,,, +201000759,Ingredient,培根片,培根片,,Ingredient,,蛋白质,,,,,,,,1.5,片,True,,,,, +201000760,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,用冷水下锅,水开后煮3分钟,1.0,煮,锅,3分钟 +201000761,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鸡蛋捞出,放入冰水中剥壳更快速也更完整,2.0,"冷却,剥壳","冰水,碗",1-2分钟 +201000762,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,用芝士片包裹鸡蛋,3.0,包裹,,30秒 +201000763,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,培根片包裹鸡蛋,4.0,包裹,,30秒 +201000764,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,手抓饼两端切除以矩形包裹鸡蛋,5.0,"包裹,切",刀,1分钟 +201000765,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,油温6成下锅(油面波动,有青烟,筷子插入油中周围泛起气泡即是6成温度),炸至金黄即可,6.0,炸,"油锅,筷子",3-5分钟 +201000766,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,空气炸锅160度15分钟,7.0,烤,空气炸锅,15分钟 +201000767,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,切开即可食用,8.0,切,刀,30秒 +201000768,Recipe,油酥,油酥,,Recipe,,调料,2.0,,2分钟,1分钟,按烙饼张数计算,"烙饼增香,层次分明,外酥里软",dishes\condiment\油酥.md,,,,,,,, +201000769,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,烙饼张数/0.13,克,True,,,,, +201000770,Ingredient,油,油,,Ingredient,,调料,,,,,,,,烙饼张数*10,毫升,True,,,,, +201000771,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,烙饼张数/2,克,False,,,,, +201000772,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将面粉倒入小碗中,加入盐,1.0,混合,"小碗,筷子",30秒 +201000773,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将油加热至约200℃,2.0,加热,"锅,温度计",30秒 +201000774,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将热油倒入面粉中,用筷子快速搅拌至无固状颗粒的糊状,3.0,搅拌,筷子,30秒 +201000775,Recipe,炸串酱料,炸串酱料,,Recipe,"[{'term': 'deep-fried串酱料', 'language': 'en', 'language_code': 'en-US'}, {'term': '油炸串酱料', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,2.0,,5分钟,5分钟,约150克酱料,"分次淋热油,可按比例缩减,最后调味可自定义",dishes\condiment\炸串酱料.md,,,,,,,, +201000776,Ingredient,干辣椒面,干辣椒面,,Ingredient,,调料,,,,,,,,60,克,True,,,,, +201000777,Ingredient,孜然粉,孜然粉,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201000778,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000779,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201000780,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201000781,Ingredient,花椒粉,花椒粉,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201000782,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,8,克,False,,,,, +201000783,Ingredient,十三香,十三香,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000784,Ingredient,麻辣鲜,麻辣鲜,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000785,Ingredient,白芝麻,白芝麻,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201000786,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201000787,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,毫升,False,,,,, +201000788,Ingredient,花椒油,花椒油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201000789,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201000790,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,所有原料在容器内混合,搅拌均匀。,1.0,"混合,搅拌","容器,筷子或勺子",1分钟 +201000791,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅里烧热油,油的用量以在容器内没过所有原材料为佳。,2.0,加热,"锅,油",2分钟 +201000792,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,分三次淋入热油,每次1/3,同时搅拌。,3.0,"淋油,搅拌","锅,勺子",1分钟 +201000793,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,最后放入香油10ml、生抽10ml、花椒油10ml、蚝油10ml,搅拌均匀。,4.0,"加入,搅拌",勺子,1分钟 +201000794,Recipe,简易版炒糖色,简易版炒糖色,,Recipe,,调料,4.0,,5分钟(敲碎冰糖、量取油与水),8-10分钟(从开火到糖色完成),约500ml糖色(可用于多道菜品),"炒糖色,火候控制,水油炒法,电磁炉不适用,避免发苦",dishes\condiment\简易版炒糖色.md,,,,,,,, +201000795,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,100,克,True,,,,, +201000796,Ingredient,油,油,,Ingredient,,调料,,,,,,,,100,毫升,False,,,,, +201000797,Ingredient,开水,开水,,Ingredient,,调料,,,,,,,,500,毫升,False,,,,, +201000798,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,开火,向锅中倒入100ml开水,1.0,倒,炒锅,10秒 +201000799,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,立即倒入100ml油,与上一步间隔越短越好,火力可大火或中火,2.0,倒,炒锅,5秒 +201000800,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放入冰糖(若冰糖过大可提前敲碎),3.0,放,炒锅,5秒 +201000801,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,调整火力为中火,开始持续搅拌,4.0,搅拌,锅铲,2-3分钟 +201000802,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,糖液变成棕褐色后转为小火,继续搅拌至呈红茶色、酱红色并出现小泡泡,5.0,搅拌,锅铲,2-3分钟 +201000803,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,小泡泡消失后出现大泡泡,糖色完成,立即选择操作1或操作2,6.0,观察,锅铲,30秒 +201000804,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,操作1:迅速加入400ml开水降温;操作2:加入葱姜蒜花椒等调味品翻炒,7.0,"倒,翻炒",锅铲,5秒 +201000805,Recipe,糖醋汁,糖醋汁,,Recipe,"[{'term': 'sweet and sour汁', 'language': 'en', 'language_code': 'en-US'}]",调料,2.0,,2分钟,5-10分钟,1份,"经典比例1:2:3:4:5,可加入番茄酱增味,可加入淀粉增稠",dishes\condiment\糖醋汁.md,,,,,,,, +201000806,Ingredient,清水,清水,,Ingredient,,调料,,,,,,,,50,毫升,False,,,,, +201000807,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,40,毫升,False,,,,, +201000808,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,克,False,,,,, +201000809,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,20,毫升,False,,,,, +201000810,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,毫升,False,,,,, +201000811,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,按照比例将各调料在小碗中搅拌均匀,1.0,搅拌,"小碗,筷子",1分钟 +201000812,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,按不同菜肴的方式处理完毕后,将配制好的糖醋汁倒入锅中,2.0,倒,锅,1分钟 +201000813,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,根据各菜肴的不同,烹制5-10分钟,3.0,煮,锅,5-10分钟 +201000814,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,大火收汁,可增加菜的浓度、香味和光泽,4.0,收汁,锅,1-2分钟 +201000815,Recipe,葱油,葱油,,Recipe,,调料,3.0,,约20分钟,20分钟,,"开洋可提升鲜香与鲜甜风味,葱渣可食用,可滤渣或保留料渣",dishes\condiment\葱油.md,,,,,,,, +201000816,Ingredient,油,油,,Ingredient,,调料,,,,,,,,200,g,False,,,,, +201000817,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,80,g,True,,,,, +201000818,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,20,g,False,,,,, +201000819,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201000820,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,150,g,False,,,,, +201000821,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,适量,g,False,,,,, +201000822,Ingredient,开洋,开洋,,Ingredient,,蛋白质,,,,,,,,50,g,False,,,,, +201000823,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,开洋泡入50度温水中,加入10ml料酒去腥,泡10分钟后取出沥干水分,1.0,"泡,去腥",盆,10分钟 +201000824,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱、香菜洗净,切成5cm长的段,擦干表面水分,2.0,"洗,切,擦干","刀,案板,厨房纸", +201000825,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,洋葱切成丝,在锅里用热水煮5分钟,取出沥干水分,3.0,"切,煮","刀,案板,锅",5分钟 +201000826,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,姜去皮,切成片,4.0,"去皮,切","刀,案板", +201000827,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅里倒入全部油,放入上述预处理好的材料,开中小火炸20分钟,5.0,炸,锅,20分钟 +201000828,Recipe,蒜香酱油,蒜香酱油,,Recipe,,调料,2.0,,2分钟,30秒,1份,,dishes\condiment\蒜香酱油.md,,,,,,,, +201000829,Ingredient,蒜头,蒜头,,Ingredient,,蔬菜,,,,,,,,2,瓣,True,,,,, +201000830,Ingredient,白芝麻,白芝麻,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000831,Ingredient,花生油,花生油,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201000832,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,30,毫升,True,,,,, +201000833,Ingredient,蘸料碟,蘸料碟,,Ingredient,,其他,,,,,,,,1,个,False,,,,, +201000834,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,拍碎蒜头,1.0,切,刀,30秒 +201000835,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,往蘸料碟中加入酱油,2.0,倒,蘸料碟,10秒 +201000836,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,起锅,加入花生油,等到油温滚烫后加入拍好的蒜头,炸半分钟,3.0,炸,"锅,锅铲",30秒 +201000837,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,半分钟后,关火,把热油倒入蘸料碟,用筷子搅拌即可,4.0,"倒,搅拌","筷子,蘸料碟",10秒 +201000838,Recipe,油泼辣子,油泼辣子,,Recipe,,调料,3.0,川菜,5分钟,10分钟,约200克成品,"增香,增辣,柔和辣味,五香粉增香,草寇增香",dishes\condiment\油泼辣子\油泼辣子.md,,,,,,,, +201000839,Ingredient,干辣椒面,干辣椒面,,Ingredient,,调料,,,,,,,,100,克,True,,,,, +201000840,Ingredient,花生油,花生油,,Ingredient,,调料,,,,,,,,150,毫升,True,,,,, +201000841,Ingredient,熟白芝麻,熟白芝麻,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201000842,Ingredient,蒜头,蒜头,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201000843,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201000844,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201000845,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201000846,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201000847,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201000848,Ingredient,草寇,草寇,,Ingredient,,调料,,,,,,,,1,个,False,,,,, +201000849,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,3-5,根,False,,,,, +201000850,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,个,False,,,,, +201000851,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,20-50,粒,False,,,,, +201000852,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2-3,片,False,,,,, +201000853,Ingredient,白芷,白芷,,Ingredient,,调料,,,,,,,,2-3,片,False,,,,, +201000854,Ingredient,姜片,姜片,,Ingredient,,蔬菜,,,,,,,,大拇指粗细,片,False,,,,, +201000855,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,蒜头掰2个小蒜头去皮,1.0,切,刀,1分钟 +201000856,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,砧板上剁碎小蒜头和小米椒,2.0,切,"刀,砧板",1分钟 +201000857,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将花生油倒入小陶瓷碗备用,3.0,倒,小陶瓷碗,30秒 +201000858,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,冷油放入八角、花椒、香叶、白芷、姜片、小葱,小火炸至香料变焦后捞出丢弃,4.0,炸,"锅,勺子",3-4分钟 +201000859,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将碗内油倒入铁锅,继续加热2分钟至菜籽油冒烟,5.0,加热,铁锅,2分钟 +201000860,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,空碗中加入干辣椒面、白芝麻、蒜末、小米椒、盐、五香粉、草寇作为调料,6.0,混合,"碗,勺子",30秒 +201000861,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,关火,将油温冷却至210摄氏度,7.0,静置,温度计,1-2分钟 +201000862,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将热油倒入调料碗中并立即用勺子搅拌,8.0,"泼,搅拌",勺子,30秒 +201000863,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,油温降至165摄氏度时,可再次加入同样调料的碗混合增辣(可选),9.0,混合,勺子,30秒 +201000864,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,倒入白醋,继续搅拌至重新沸腾,增香,10.0,搅拌,勺子,30秒 +201000865,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,待油泼辣子冷却至温热,加入白糖和味精,搅拌均匀使辣味柔和,11.0,搅拌,勺子,1分钟 +201000866,Recipe,草莓酱,草莓酱,,Recipe,,调料,2.0,,1小时10分钟(含1小时静置),约20分钟,1份,低糖版本可将糖减至200g,dishes\condiment\草莓酱\草莓酱.md,,,,,,,, +201000867,Ingredient,草莓,草莓,,Ingredient,,蔬菜,,,,,,,,1200,克,True,,,,, +201000868,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,400,克,False,,,,, +201000869,Ingredient,保鲜膜,保鲜膜,,Ingredient,,其他,,,,,,,,1,张,False,,,,, +201000870,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,草莓洗净去叶,1.0,"洗,切","盆,刀",5分钟 +201000871,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将草莓切碎放入合适的碗中,2.0,切,"刀,碗",5分钟 +201000872,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将白糖倒入碗中与草莓搅拌均匀,3.0,搅拌,"碗,筷子或勺",2分钟 +201000873,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,碗用保鲜膜覆盖静置1小时,4.0,腌制,"保鲜膜,碗",1小时 +201000874,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将静置的草莓和糖的混合物倒入不粘锅中开大火烧开,5.0,煮,不粘锅,3-5分钟 +201000875,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,烧开后转小火不断搅拌直至果酱呈粘稠状关火,6.0,"煮,搅拌","不粘锅,锅铲",10-15分钟 +201000876,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,待草莓酱冷却后装入准备好的密封罐中,7.0,"冷却,装罐",密封罐,10分钟 +201000877,Recipe,蔗糖糖浆,蔗糖糖浆,,Recipe,,调料,1.0,,2分钟,0分钟,约200克糖浆,"冷饮增甜,冷藏保存一周,热水可加速溶解",dishes\condiment\蔗糖糖浆\蔗糖糖浆.md,,,,,,,, +201000878,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,100,克,True,,,,, +201000879,Ingredient,水,水,,Ingredient,,其他,,,,,,,,100,克,False,,,,, +201000880,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将称好的白砂糖与饮用水于容器混匀,1.0,混合,可密封容器,1分钟 +201000881,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,容器封盖放冰箱冷藏,2.0,冷藏,可密封容器,即刻可用,冷藏后更佳 +201000882,Recipe,反沙芋头,反沙芋头,,Recipe,,甜品,3.0,粤菜,5分钟,15分钟,1人份,"潮汕小吃,下午茶,小心烫嘴,配茶更惬意",dishes\dessert\反沙芋头\反沙芋头.md,,,,,,,, +201000883,Ingredient,荔浦芋头,荔浦芋头,,Ingredient,,淀粉类,,,,,,,,200,克,True,,,,, +201000884,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201000885,Ingredient,水,水,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201000886,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,适量,克,False,,,,, +201000887,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,芋头切成长条,稍微大条一点,翻炒过程不容易烂,1.0,切,"刀,案板",2分钟 +201000888,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入可以没过芋头的油,等油温起来(插入筷子冒小泡即可),2.0,炸,"锅,筷子",2分钟 +201000889,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放进芋头到油里,炸至芋头浮起来,微微泛黄且筷子能轻松戳洞,3.0,炸,"锅,筷子",5-8分钟 +201000890,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,炸芋头的油倒出备用,后续可炒菜使用,4.0,倒油,锅铲,30秒 +201000891,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将糖30g和水15g按2:1比例混合,加热至糖液不变色且冒小泡,5.0,煮,锅,2-3分钟 +201000892,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入葱花和炸好的芋头,关火翻炒,待温度下降糖反沙,6.0,翻炒,锅铲,1-2分钟 +201000893,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,装盘上桌,7.0,装盘,盘子,30秒 +201000894,Recipe,咖啡椰奶冻,咖啡椰奶冻,,Recipe,,甜品,4.0,,5分钟,1分钟,3-4人,"不要让液体煮沸,不要冒泡泡,使用洗碗机清洗",dishes\dessert\咖啡椰奶冻\咖啡椰奶冻.md,,,,,,,, +201000895,Ingredient,淡奶油,淡奶油,,Ingredient,,蛋白质,,,,,,,,125,ml,True,,,,, +201000896,Ingredient,椰树牌椰汁,椰树牌椰汁,,Ingredient,,其他,,,,,,,,250,ml,True,,,,, +201000897,Ingredient,espresso意式浓缩,espresso意式浓缩,,Ingredient,,调料,,,,,,,,35,ml,True,,,,, +201000898,Ingredient,椰子水,椰子水,,Ingredient,,其他,,,,,,,,50,ml,True,,,,, +201000899,Ingredient,吉利丁,吉利丁,,Ingredient,,其他,,,,,,,,10,g,True,,,,, +201000900,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,可选,,False,,,,, +201000901,Ingredient,蓝莓,蓝莓,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201000902,Ingredient,咖啡粉,咖啡粉,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000903,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将淡奶油、椰树牌椰汁、espresso、椰子水混合备用。,1.0,混合,容器, +201000904,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将以上液体加热1分钟,温度达到50-60℃即可。,2.0,加热,锅,1分钟 +201000905,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,(可选)如果格外嗜甜可以加额外的糖。,3.0,调味,勺子, +201000906,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入吉利丁,搅拌至融化,煮1分钟。,4.0,"搅拌,煮","勺子,锅",1分钟 +201000907,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,(可选)过筛,这一步可以让椰奶冻口感更佳顺畅。,5.0,过滤,过滤网, +201000908,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入模具。,6.0,倒入,模具, +201000909,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,(可选)过滤掉表层的泡泡,这一步可以让椰奶冻口感更好,并且看着也会更棒。,7.0,过滤,过滤网, +201000910,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入冰箱冷藏区,等待3小时。,8.0,冷藏,冰箱,3小时 +201000911,Recipe,奥利奥冰淇淋,奥利奥冰淇淋,,Recipe,,甜品,3.0,,30分钟,4小时以上(冷冻),1份,"剁碎奥利奥的容器注意不要使用易碎容器,去除奥利奥夹心时切忌注意割到手",dishes\dessert\奥利奥冰淇淋\奥利奥冰淇淋.md,,,,,,,, +201000912,Ingredient,奥利奥,奥利奥,,Ingredient,,其他,,,,,,,,6,块,True,,,,, +201000913,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,18,克,False,,,,, +201000914,Ingredient,淡奶油,淡奶油,,Ingredient,,其他,,,,,,,,250,毫升,True,,,,, +201000915,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将奥利奥拧开后去除夹心,备用,1.0,切,小刀, +201000916,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用筷子将奥奥剁碎,需要有一半奥奥变成粉状,另一半的奥奥最大长度小于0.5厘米,备用,2.0,切,筷子, +201000917,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将奶油全部倒置于深容器中,并加入准备好的糖,3.0,倒,深容器, +201000918,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,开始用电动打蛋器高速挡搅打至电动打蛋器提起后下方会出现悬挂住的奶油(0.5厘米-1厘米),而不是全部像液体一样滴下,4.0,搅打,"电动打蛋器,深容器", +201000919,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,搅打完成后将奥奥放入奶油中,搅拌均匀直至底部有奥奥,5.0,搅拌,深容器, +201000920,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,可选:将混合物倒入冰淇淋模具中,6.0,倒,冰淇淋模具, +201000921,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放置冰箱冷冻室(-18度)4小时以上可取出,7.0,冷冻,冰箱,4小时以上 +201000922,Recipe,戚风蛋糕,戚风蛋糕,,Recipe,,甜品,5.0,,约30分钟,30-50分钟,6寸(3人份)或8寸(5人份),"温度控制是关键,蛋白必须干性发泡,模具不能选不沾,蛋清容器可少量水珠但绝不可有油,低温鸡蛋易分蛋但需回温再打发",dishes\dessert\戚风蛋糕\戚风蛋糕.md,,,,,,,, +201000923,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,3,个,True,,,,, +201000924,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,50,g,False,,,,, +201000925,Ingredient,牛奶,牛奶,,Ingredient,,其他,,,,,,,,30,g,False,,,,, +201000926,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,25,g,False,,,,, +201000927,Ingredient,低筋面粉,低筋面粉,,Ingredient,,淀粉类,,,,,,,,50,g,True,,,,, +201000928,Ingredient,柠檬汁,柠檬汁,,Ingredient,,调料,,,,,,,,少许,,False,,,,, +201000929,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,前期分离:将蛋清与蛋黄分别放入两个干净无油无水的容器中,蛋清中不得混入蛋黄。,1.0,分离,"分蛋器,容器",5分钟 +201000930,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,搅拌蛋黄液:先混合食用油与低筋面粉,再加入蛋黄、牛奶及1/4白糖,用刮刀Z字形搅拌至无干粉。,2.0,搅拌,"刮刀,碗",5-7分钟 +201000931,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,打发蛋白:分三次加入剩余白糖,将蛋白打至干性发泡(短小直立尖角)。,3.0,打发,"电动打蛋器,容器",8-10分钟 +201000932,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,混合搅拌:先取1/3蛋白霜与蛋黄糊翻拌均匀,再倒回剩余蛋白霜中继续翻拌,倒入模具后轻震排气。,4.0,翻拌,"刮刀,模具",3-5分钟 +201000933,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,烘烤:烤箱预热后,6寸蛋糕先150/160℃烤18-21分钟,再160/170℃烤12-14分钟;8寸蛋糕时间相应延长。,5.0,烤,烤箱,30-50分钟 +201000934,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,冷却脱模:出炉后震模倒扣冷却10分钟,再脱模食用。,6.0,"冷却,脱模","毛巾,模具",10分钟 +201000935,Recipe,提拉米苏,提拉米苏,,Recipe,,甜品,4.0,意大利,约20分钟,冷藏4小时,1份(按容器大小),"无需烤箱,新手友好,蛋白打发技巧",dishes\dessert\提拉米苏\提拉米苏.md,,,,,,,, +201000936,Ingredient,马斯卡彭芝士,马斯卡彭芝士,,Ingredient,,蛋白质,,,,,,,,450,g,True,,,,, +201000937,Ingredient,手指饼干,手指饼干,,Ingredient,,淀粉类,,,,,,,,1,包,True,,,,, +201000938,Ingredient,放凉浓缩咖啡,放凉浓缩咖啡,,Ingredient,,其他,,,,,,,,350,ml,True,,,,, +201000939,Ingredient,无菌鸡蛋,无菌鸡蛋,,Ingredient,,蛋白质,,,,,,,,4,个,True,,,,, +201000940,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,50,g,False,,,,, +201000941,Ingredient,可可粉,可可粉,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201000942,Ingredient,朗姆酒,朗姆酒,,Ingredient,,调料,,,,,,,,35,ml,False,,,,, +201000943,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,分离蛋黄蛋清,1.0,切,刀, +201000944,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,盛有蛋白的碗中加10g白砂糖湿性打发,2.0,打发,"打蛋器,碗", +201000945,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,盛有蛋黄的碗中将40g白砂糖分三次加入,搅拌至均匀,3.0,搅拌,"碗,打蛋器", +201000946,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,蛋黄中分三次加入马斯卡彭芝士,搅拌至均匀,4.0,搅拌,"碗,打蛋器", +201000947,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,蛋黄中最后加入朗姆酒,搅拌均匀,5.0,搅拌,"碗,打蛋器", +201000948,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将打发好的蛋白分三次加入蛋黄芝士液中,6.0,搅拌,"碗,打蛋器", +201000949,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,手指饼干两面浸湿咖啡液,平铺入容器,7.0,浸渍,容器, +201000950,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,两层芝士液两层饼干交替放入容器(按容器高度酌情处理),8.0,铺层,容器, +201000951,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,放入冰箱冷藏四个小时,9.0,冷藏,冰箱,4小时 +201000952,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,取出后在表面筛上可可粉,即可享用,10.0,筛粉,筛网, +201000953,Recipe,无厨师机蜂蜜面包,无厨师机蜂蜜面包,,Recipe,,甜品,5.0,,约2小时(含两次发面),18-20分钟,约两周早餐量(按每次60g小面包计算,可吃14次左右),"无需厨师机,可冷藏过夜,微波炉回热,发面时间灵活,面团大小可调整",dishes\dessert\无厨师机蜂蜜面包\无厨师机蜂蜜面包.md,,,,,,,, +201000954,Ingredient,高筋面粉,高筋面粉,,Ingredient,,淀粉类,,,,,,,,400,g,True,,,,, +201000955,Ingredient,牛奶,牛奶,,Ingredient,,其他,,,,,,,,200,g,True,,,,, +201000956,Ingredient,酵母,酵母,,Ingredient,,调料,,,,,,,,4,g,False,,,,, +201000957,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201000958,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,70,g,False,,,,, +201000959,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201000960,Ingredient,黄油,黄油,,Ingredient,,其他,,,,,,,,30,g,True,,,,, +201000961,Ingredient,蜂蜜,蜂蜜,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201000962,Ingredient,水,水,,Ingredient,,其他,,,,,,,,20,g,False,,,,, +201000963,Ingredient,芝麻,芝麻,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000964,Ingredient,花生油,花生油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000965,Ingredient,蛋液,蛋液,,Ingredient,,蛋白质,,,,,,,,适量,,False,,,,, +201000966,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将高筋面粉、牛奶(加热至40℃)、酵母、鸡蛋、白砂糖和盐混合,开始制作面团。,1.0,混合,盆, +201000967,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,搅拌面团,使原料混合均匀成团。,2.0,搅拌,手或筷子, +201000968,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入软化的黄油,继续揉面至黄油完全吸收。,3.0,揉,手, +201000969,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,覆盖保鲜膜,室温(10-20℃)第一次发酵1-2小时,至体积膨胀2倍。,4.0,发酵,"保鲜膜,容器",1-2小时 +201000970,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将发酵好的面团分割成每份约60g的小面团。,5.0,切分,"刀,案板", +201000971,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将小面团擀成舌状后卷起,松弛醒面10分钟。,6.0,"擀,卷,醒面",擀面杖,10分钟 +201000972,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,再次擀成舌状卷起,从中间切开,一个变两个。,7.0,"擀,卷,切","擀面杖,刀", +201000973,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,可重复擀卷并切开步骤,直到达到理想大小。,8.0,"擀,卷,切","擀面杖,刀", +201000974,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,烤盘铺油纸并刷少量花生油,将卷好的面团底部蘸水再蘸面粉后摆入烤盘。,9.0,摆盘,"烤盘,油纸", +201000975,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,覆盖保鲜膜进行第二次醒发,可室温继续发酵或放入冰箱冷藏过夜。,10.0,发酵,保鲜膜,冷藏过夜或室温至明显膨胀 +201000976,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,表面刷蛋液。,11.0,刷,刷子, +201000977,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,烤箱预热180℃(355°F),烘烤18-20分钟。,12.0,烤,烤箱,18-20分钟 +201000978,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,出炉后立即刷蜂蜜水,并撒上芝麻即可。,13.0,"刷,撒",刷子, +201000979,Recipe,炸鲜奶,炸鲜奶,,Recipe,"[{'term': '油炸鲜奶', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'deep-fried鲜奶', 'language': 'en', 'language_code': 'en-US'}]",甜品,3.0,,1小时10分钟,10分钟,1份(约12个),"小火慢煮,油温5分热",dishes\dessert\炸鲜奶\炸鲜奶.md,,,,,,,, +201000980,Ingredient,牛奶,牛奶,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201000981,Ingredient,玉米淀粉,玉米淀粉,,Ingredient,,淀粉类,,,,,,,,30,g,True,,,,, +201000982,Ingredient,面包糠,面包糠,,Ingredient,,淀粉类,,,,,,,,100,g,True,,,,, +201000983,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201000984,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,g,False,,,,, +201000985,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201000986,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将牛奶倒入碗中,1.0,倒,碗, +201000987,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入玉米淀粉和白糖,搅拌均匀,2.0,搅拌,"碗,筷子或打蛋器", +201000988,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将模具刷上食用油,3.0,刷,"模具,刷子", +201000989,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,牛奶下锅,中火烧开,4.0,煮,锅, +201000990,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,烧开后转小火,边煮边搅拌,5.0,"煮,搅拌","锅,锅铲", +201000991,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,牛奶变粘稠后出锅,倒入模具,6.0,倒,模具, +201000992,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将模具放冰箱冷却1小时,7.0,冷藏,冰箱,1小时 +201000993,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,拿出,切成大小均匀的条,随后放入碗中,8.0,切,"刀,碗", +201000994,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,向碗中倒入一半的面包糠,奶糊裹上后取出,备用,9.0,裹,碗, +201000995,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,在一个新碗中打入鸡蛋,搅匀,备用,10.0,"打,搅拌","碗,筷子或打蛋器", +201000996,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将奶糊裹上蛋液和剩余的面包糠,11.0,裹,碗, +201000997,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,锅中倒入足以覆盖奶糊的油,下锅,12.0,炸,锅, +201000998,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,奶糊外观呈金黄状态后停火,摆盘,13.0,"炸,摆盘","锅,盘子", +201000999,Recipe,烤蛋挞,烤蛋挞,,Recipe,"[{'term': 'baked蛋挞', 'language': 'en', 'language_code': 'en-US'}, {'term': 'roasted蛋挞', 'language': 'en', 'language_code': 'en-US'}, {'term': '烘烤蛋挞', 'language': 'zh', 'language_code': 'zh-CN'}]",甜品,4.0,,10分钟,25分钟,30只,"小心烤箱高温,防止烫伤",dishes\dessert\烤蛋挞\烤蛋挞.md,,,,,,,, +201001000,Ingredient,蛋挞皮,蛋挞皮,,Ingredient,,淀粉类,,,,,,,,30,个,True,,,,, +201001001,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,8,个,True,,,,, +201001002,Ingredient,牛奶,牛奶,,Ingredient,,蛋白质,,,,,,,,200,毫升,True,,,,, +201001003,Ingredient,淡奶油,淡奶油,,Ingredient,,蛋白质,,,,,,,,450,毫升,True,,,,, +201001004,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,80,克,False,,,,, +201001005,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将碗置于克数称上称量450克淡奶油。,1.0,称量,"克数称,碗", +201001006,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入80克白砂糖。,2.0,加入,碗, +201001007,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入200克牛奶。,3.0,加入,碗, +201001008,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,取8个蛋黄加入,蛋清可留作他用。,4.0,"分离,加入",碗, +201001009,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,均匀搅拌所有材料直至白砂糖全部融化。,5.0,搅拌,搅拌器, +201001010,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,使用网筛对搅拌完成的食材进行过滤,滤除鸡蛋黏膜、鸡蛋壳、未融化的白砂糖、结块的淡奶油。,6.0,过滤,筛网, +201001011,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将烤箱设置220摄氏度开始预热,约10分钟,记得拿出烤盘。,7.0,预热,"烤箱,烤盘",10分钟 +201001012,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将蛋挞皮以0.5厘米的间隔均匀放置于烤盘中。,8.0,摆放,烤盘, +201001013,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将过滤完成的食材倒入蛋挞皮中,液面距离蛋挞皮上沿0.5厘米即可,不宜过多。,9.0,倒入,烤盘, +201001014,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,半成品蛋挞制作完成,可直接放入冰箱速冻12小时以上保存。,10.0,冷冻,冰箱,12小时 +201001015,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将半成品蛋挞放入烤箱中烤制,温度200摄氏度,时间25分钟。,11.0,烤,烤箱,25分钟 +201001016,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,烤制结束后即可食用。,12.0,取出,, +201001017,Recipe,玛格丽特饼干,玛格丽特饼干,,Recipe,,甜品,3.0,,10分钟,20分钟,1人份,"可替换玉米淀粉为可可粉或抹茶粉,食材过筛口感更佳,可用糖粉替代白砂糖,可用微波炉或空气炸锅代替烤箱",dishes\dessert\玛格丽特饼干\玛格丽特饼干.md,,,,,,,, +201001018,Ingredient,熟蛋黄,熟蛋黄,,Ingredient,,蛋白质,,,,,,,,1,个,True,,,,, +201001019,Ingredient,黄油,黄油,,Ingredient,,其他,,,,,,,,50,克,True,,,,, +201001020,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201001021,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201001022,Ingredient,低筋面粉,低筋面粉,,Ingredient,,淀粉类,,,,,,,,50,克,True,,,,, +201001023,Ingredient,玉米淀粉,玉米淀粉,,Ingredient,,淀粉类,,,,,,,,50,克,True,,,,, +201001024,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,黄油隔热水融化、将蛋黄磨碎备用。,1.0,融化,热水盆, +201001025,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,在融化的黄油中添加糖、盐、以及碾碎的鸡蛋黄,搅拌均匀。,2.0,搅拌,盆, +201001026,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入低筋面粉与玉米淀粉,揉成面团。,3.0,揉,盆, +201001027,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将面团均匀分割成大约8克重的小面团,然后将它们搓成球状。,4.0,"分割,搓圆",电子秤, +201001028,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,使用大拇指轻压在每个小面团上,以形成裂纹。,5.0,按压,手, +201001029,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,预热烤箱至150℃,将小面团放入烤箱中,烘烤20分钟。,6.0,"预热,烘烤",烤箱,20分钟 +201001030,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,微微放凉即可食用。,7.0,冷却,, +201001031,Recipe,红柚蛋糕,红柚蛋糕,,Recipe,,甜品,3.0,,10分钟,25分钟,1人,"喜欢更甜可多加10g糖,红柚果肉最多不超过40g,糊状需无面粉疙瘩且颜色均匀,出锅锡纸盘烫,需用夹子或湿抹布隔热",dishes\dessert\红柚蛋糕\红柚蛋糕.md,,,,,,,, +201001032,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201001033,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,80,克,True,,,,, +201001034,Ingredient,红柚果肉,红柚果肉,,Ingredient,,蔬菜,,,,,,,,20,克,True,,,,, +201001035,Ingredient,油,油,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201001036,Ingredient,水,水,,Ingredient,,其他,,,,,,,,80,毫升,False,,,,, +201001037,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201001038,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锡纸盘里打入鸡蛋2个,加入红柚果肉20g,1.0,混合,锡纸盘, +201001039,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锡纸盘中倒入15ml油并摇晃锡纸盘使其均匀覆盖盘底,2.0,"倒油,摇晃",锡纸盘, +201001040,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锡纸盘中放入10g糖,以及40g面粉和40ml水,3.0,加入,锡纸盘, +201001041,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,用筷子顺时针方向搅拌至淡黄色糊状,4.0,搅拌,筷子, +201001042,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锡纸盘中放入5g糖,以及40g面粉和40ml水,5.0,加入,锡纸盘, +201001043,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,继续用筷子搅拌至淡黄色糊状,6.0,搅拌,筷子, +201001044,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,锡纸盘放入空气炸锅的烤篮上,用180摄氏度烤15分钟,7.0,烤,"空气炸锅,锡纸盘",15分钟 +201001045,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,打开空气炸锅,小心取出锡纸盘,用筷子或勺子将蛋糕翻面,8.0,翻面,"筷子,勺子,锡纸盘", +201001046,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,继续180摄氏度烤8分钟,9.0,烤,空气炸锅,8分钟 +201001047,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,取出即可食用,10.0,取出,夹子, +201001048,Recipe,芋泥雪媚娘,芋泥雪媚娘,,Recipe,,甜品,5.0,,约30分钟(切芋头、称量、过筛、打发奶油等),约90分钟(煮芋头40分钟+蒸糯米团30分钟+冷藏1小时),约10个(按30g/个面团计算),"无需烤箱,手残党友好,适合孩子,制作时戴不粘手套,做好即食",dishes\dessert\芋泥雪媚娘\芋泥雪媚娘.md,,,,,,,, +201001049,Ingredient,荔浦芋头,荔浦芋头,,Ingredient,,蔬菜,,,,,,,,200,g,True,,,,, +201001050,Ingredient,紫薯粉,紫薯粉,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201001051,Ingredient,牛奶,牛奶,,Ingredient,,其他,,,,,,,,165,g,False,,,,, +201001052,Ingredient,糯米粉 a,糯米粉 a,,Ingredient,,淀粉类,,,,,,,,50,g,False,,,,, +201001053,Ingredient,糯米粉 b,糯米粉 b,,Ingredient,,淀粉类,,,,,,,,75,g,True,,,,, +201001054,Ingredient,玉米淀粉,玉米淀粉,,Ingredient,,淀粉类,,,,,,,,22,g,False,,,,, +201001055,Ingredient,黄油,黄油,,Ingredient,,其他,,,,,,,,30,g,False,,,,, +201001056,Ingredient,淡奶油,淡奶油,,Ingredient,,其他,,,,,,,,145,g,False,,,,, +201001057,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,26,g,False,,,,, +201001058,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,芋头切块,大火煮熟至软(40分钟即可),全部放入料理机,1.0,煮,"锅,料理机",40分钟 +201001059,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,向内加入30g牛奶、25g淡奶油,将其打成泥状,2.0,搅拌,料理机, +201001060,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,再向内加入3g紫薯粉、18g白砂糖,继续搅拌打成细腻芋泥,3.0,搅拌,料理机, +201001061,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,取出另一个碗,加入全部糯米粉b、22g玉米淀粉、135g牛奶、50g白砂糖,混匀并过筛一遍,保鲜膜盖上并扎小洞,中火蒸半个小时,4.0,"混合,过筛,蒸","碗,筛网,保鲜膜,蒸锅",30分钟 +201001062,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,在蒸的过程中,将糯米粉a放入平底锅小火翻炒至微微发黄(即炒熟),作为手粉备用,5.0,炒,平底锅, +201001063,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将中火蒸完半小时的糯米牛奶混合物(果冻状)趁热加入黄油30g,将黄油揉至面团完全吸收,然后放冰箱冷藏一小时,6.0,"揉,冷藏","碗,冰箱",1小时 +201001064,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,取出另一只碗,加入120g淡奶油、8g白砂糖,打发至有纹路,装进裱花袋备用,7.0,打发,"碗,电动打蛋器,裱花袋", +201001065,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,取出冷藏后的面团,搓揉5分钟,分成30g一个,均匀撒上2g手粉防粘,擀成圆形,8.0,"搓揉,分割,擀",擀面杖,5分钟 +201001066,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,先挤上5g裱花奶油,然后放上30g芋泥,最后将面饼像包包子一样包起来(可以减去多余的皮),9.0,包,裱花袋, +201001067,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,包好后再均匀撒2g手粉防粘,10.0,撒粉,, +201001068,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,重复以上两步直至原材料用光,11.0,重复,, +201001069,Recipe,英式司康,英式司康,,Recipe,,甜品,3.0,,约15分钟,27分钟,4-6人,"下午茶,快手甜品,分切方案:擀成圆形面皮后切成6个扇形",dishes\dessert\英式司康\英式司康.md,,,,,,,, +201001070,Ingredient,无盐黄油,无盐黄油,,Ingredient,,蛋白质,,,,,,,,40,g,True,,,,, +201001071,Ingredient,低筋面粉,低筋面粉,,Ingredient,,淀粉类,,,,,,,,180,g,True,,,,, +201001072,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201001073,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201001074,Ingredient,泡打粉,泡打粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201001075,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201001076,Ingredient,淡奶油,淡奶油,,Ingredient,,蛋白质,,,,,,,,45,g,True,,,,, +201001077,Ingredient,奶油奶酪,奶油奶酪,,Ingredient,,蛋白质,,,,,,,,50,g,False,,,,, +201001078,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡蛋打散,称量出30g蛋液放入干净容器中,放入全量淡奶油和奶油奶酪混合均匀。如果奶酪太硬可以水浴加热至大约40度再混合。,1.0,"混合,加热","容器,水浴", +201001079,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将低筋面粉,盐,糖,泡打粉放入干净容器中混合均匀。,2.0,混合,容器, +201001080,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,黄油切成小块,放入上一步的混合物中,用手将黄油捏入混合物中,呈粗玉米粉质地。,3.0,"切,捏合","刀,手", +201001081,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将第一步的蛋奶混合液倒入上一步得到的粉油混合物中,搅拌均匀后叠压成均匀面团。,4.0,"搅拌,叠压","容器,手", +201001082,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,面团放到案板上,擀成1.5cm厚的面片,用刀或者模具分切成合适的形状。,5.0,"擀,切","案板,擀面杖,刀,模具", +201001083,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,用刷子蘸取剩余的20g鸡蛋液,刷在司康表面。,6.0,刷,刷子, +201001084,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,烤箱预热180度,烤制27分钟。,7.0,烤,烤箱,27分钟 +201001085,Recipe,草莓冰淇淋,草莓冰淇淋,,Recipe,,甜品,2.0,,约20分钟(切草莓、煮糖浆、打发奶油),约10分钟(煮草莓糖浆),1份,"无需搅拌,当季草莓,冷冻甜品,注意安全避免割/烫手",dishes\dessert\草莓冰淇淋\草莓冰淇淋.md,,,,,,,, +201001086,Ingredient,草莓,草莓,,Ingredient,,蔬菜,,,,,,,,500,克,True,,,,, +201001087,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,45,克,False,,,,, +201001088,Ingredient,香草精,香草精,,Ingredient,,调料,,,,,,,,6,克,False,,,,, +201001089,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201001090,Ingredient,重奶油,重奶油,,Ingredient,,蛋白质,,,,,,,,6,克,True,,,,, +201001091,Ingredient,加糖炼乳,加糖炼乳,,Ingredient,,蛋白质,,,,,,,,400,克,True,,,,, +201001092,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将草莓洗净,去蒂后切成5 mm的小块,保留一半备用;另一半与45 g白砂糖一起放入酱汁锅中。,1.0,切,"刀,案板,酱汁锅",约5分钟 +201001093,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用中火加热酱汁锅,边搅拌边煮至草莓出汁并形成糖浆,继续加热至草莓完全分解、糖浆略稠,当糖浆能保持分离3秒即可离火。,2.0,"煮,搅拌","酱汁锅,锅铲",约5-7分钟 +201001094,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,离火后加入1 g香草精和1 g食盐搅拌均匀,将草莓糖浆放凉备用。,3.0,搅拌,锅铲,约3分钟 +201001095,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,在碗中加入400 g加糖炼乳、6 g重奶油、5 g香草精和1 g食盐,用手动搅拌器搅打至轻盈蓬松并形成柔软尖峰。,4.0,打发,"碗,手动搅拌器",约3-5分钟 +201001096,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将保留的切碎草莓折叠进冰淇淋基料,倒入冷冻安全容器,淋上冷却的草莓糖浆并轻轻旋入,盖上盖子冷冻8小时后即可享用。,5.0,"折叠,冷冻","冷冻安全容器,盖子",8小时 +201001097,Recipe,酸奶意式奶冻,酸奶意式奶冻,,Recipe,,甜品,4.0,,5分钟,10分钟,3-6人,"改良版意式奶冻,减糖,搭配果酱水果香草",dishes\dessert\酸奶意式奶冻\酸奶意式奶冻.md,,,,,,,, +201001098,Ingredient,淡奶油,淡奶油,,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201001099,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,40,g,False,,,,, +201001100,Ingredient,原味酸奶,原味酸奶,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201001101,Ingredient,吉利丁片,吉利丁片,,Ingredient,,其他,,,,,,,,6,g,False,,,,, +201001102,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,吉利丁片剪成小片,泡入冷水中,1.0,切,"刀,盆",2分钟 +201001103,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,淡奶油和糖放入锅中,加热至60度,2.0,加热,"锅,温度计",3分钟 +201001104,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,关火,吉利丁从水中取出,控干水份,加入热淡奶油中,搅拌均匀,3.0,搅拌,筷子或搅拌棒,1分钟 +201001105,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,淡奶油降温至40度,加入原味酸奶,搅拌均匀,4.0,搅拌,"温度计,筷子或搅拌棒",2分钟 +201001106,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将上述步骤得到的混合物过两遍筛网,5.0,过滤,筛网,2分钟 +201001107,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,分装入合适的容器,放入冰箱冷藏4小时以上,6.0,冷藏,"容器,冰箱",4小时以上 +201001108,Recipe,雪花酥,雪花酥,,Recipe,,甜品,3.0,,5分钟,25分钟,1份,棉花糖加热时间越长成品越硬,dishes\dessert\雪花酥\雪花酥.md,,,,,,,, +201001109,Ingredient,无盐黄油,无盐黄油,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201001110,Ingredient,棉花糖,棉花糖,,Ingredient,,其他,,,,,,,,75,g,True,,,,, +201001111,Ingredient,全脂奶粉,全脂奶粉,,Ingredient,,其他,,,,,,,,40,g,True,,,,, +201001112,Ingredient,混合坚果,混合坚果,,Ingredient,,其他,,,,,,,,60,g,True,,,,, +201001113,Ingredient,饼干,饼干,,Ingredient,,淀粉类,,,,,,,,75,g,True,,,,, +201001114,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,饼干超过一元硬币大小先切成小块,1.0,切,刀,2分钟 +201001115,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,无盐黄油加入锅中,小火加热至无盐黄油完全融化,2.0,加热,不粘平底锅,2-3分钟 +201001116,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,棉花糖加入锅中,使用刮刀搅拌,直至棉花糖融化并与无盐黄油均匀融合,3.0,搅拌,"不粘平底锅,烘焙刮刀",3-4分钟 +201001117,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,20g 奶粉加入锅中,使用刮刀搅拌,奶粉与黄油棉花糖混合物搅拌均匀后立即关火,4.0,搅拌,"不粘平底锅,烘焙刮刀",30秒 +201001118,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,准备好的所有混合坚果与饼干趁热加入锅中,使用刮刀搅拌,5.0,搅拌,"不粘平底锅,烘焙刮刀",1分钟 +201001119,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,搅拌到温度下降到手可以接触的温度后,戴上一次塑料手套,在锅中搓揉或者双手拿起拉扯,让饼干混合坚果与棉花糖黄油奶粉混合物分散均匀,6.0,"搓揉,拉扯",一次性塑料手套,2-3分钟 +201001120,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将上述步骤混合物压入模具中,边角压实,擀面杖擀平,未满的一边用手尽量压成直边,7.0,"压,擀","雪花酥模具,擀面杖",2-3分钟 +201001121,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,室温放凉,完全冷却后脱模,按照模具纹路切块,或切成自己喜欢的大小,撒上剩余奶粉,尽量使雪花酥每面都沾上奶粉,8.0,"冷却,切块,撒粉",刀,10-15分钟 +201001122,Recipe,魔芋蛋糕,魔芋蛋糕,,Recipe,,甜品,4.0,,约10分钟,25分钟,1份(9.25×5×1英寸),"低热量,无麸质,生酮友好,戚风手法,小岛翻拌法",dishes\dessert\魔芋蛋糕\魔芋蛋糕.md,,,,,,,, +201001123,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,3,个,True,,,,, +201001124,Ingredient,赤藓糖醇,赤藓糖醇,,Ingredient,,调料,,,,,,,,50,克,False,,,,, +201001125,Ingredient,可可粉,可可粉,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001126,Ingredient,魔芋粉,魔芋粉,,Ingredient,,淀粉类,,,,,,,,10,克,True,,,,, +201001127,Ingredient,塔塔粉,塔塔粉,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201001128,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,预热烤箱至350℉(150℃)。,1.0,预热,烤箱,5分钟 +201001129,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,从冰箱取出鸡蛋,准备两个干净容器,分别盛放蛋清与蛋黄;确保蛋清容器无油、蛋黄容器无水。,2.0,分离,"容器,分蛋器(可选)",2-3分钟 +201001130,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,蛋清中加入1g塔塔粉,用电动打蛋器高速打发至粗大气泡,加入50g赤藓糖醇;再转中低速打发至干性发泡(提起打蛋器呈短小直立尖角,倒扣容器不滑落)。,3.0,打发,"电动打蛋器,容器",3-5分钟 +201001131,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将蛋黄加入打发的蛋清中,用电动打蛋器中低速搅拌均匀。,4.0,搅拌,电动打蛋器,30秒 +201001132,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入10g可可粉和10g魔芋粉,先用餐刀翻拌(避免粉末飞溅),再低速搅拌均匀。,5.0,"翻拌,搅拌","餐刀,电动打蛋器",1分钟 +201001133,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,模具铺好烘焙纸,倒入蛋糕糊,用餐刀抹平表面,轻震模具排出大气泡。,6.0,"倒入,抹平,震模","金属蛋糕模具,烘焙纸,餐刀",1分钟 +201001134,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入预热好的烤箱,烘烤25分钟。,7.0,烘烤,"烤箱,隔热手套",25分钟 +201001135,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,烤好后戴隔热手套取出模具,可选从高处落下震出热气,倒扣冷却10分钟,再脱模切块食用。,8.0,"震模,倒扣,脱模,切块","隔热手套,餐刀",10分钟 +201001136,Recipe,龟苓膏,龟苓膏,,Recipe,,甜品,2.0,,5分钟,10分钟,2-4人,"冷却过程中不可随意移动容器,加热时避免使用大火,可添加蜂蜜、炼乳或水果,不同品牌龟苓膏粉需调整配比",dishes\dessert\龟苓膏\龟苓膏.md,,,,,,,, +201001137,Ingredient,龟苓膏粉,龟苓膏粉,,Ingredient,,淀粉类,,,,,,,,25,克,True,,,,, +201001138,Ingredient,冷水,冷水,,Ingredient,,其他,,,,,,,,120,毫升,False,,,,, +201001139,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,500,毫升,False,,,,, +201001140,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,100,克,False,,,,, +201001141,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,在锅中倒入龟苓膏粉25克与冷水120毫升,充分搅拌至无颗粒感。,1.0,搅拌,"锅,搅拌工具",2分钟 +201001142,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,在另一个容器中加入白砂糖100克,倒入沸水500毫升,搅拌至糖完全溶解。,2.0,搅拌,"容器,搅拌工具",1分钟 +201001143,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将糖水缓慢倒入龟苓膏粉液中,立即搅拌均匀,避免结块。,3.0,搅拌,搅拌工具,1分钟 +201001144,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将混合液体放入锅中,加热时保持中小火,并持续搅拌以防粘锅。,4.0,"加热,搅拌","锅,搅拌工具",5分钟 +201001145,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加热至液体变粘稠并开始冒小泡,即可关火。,5.0,加热,锅,1分钟 +201001146,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,快速将液体倒入模具中,自然冷却凝固。建议冷藏1~2小时后食用,口感更佳。,6.0,冷却,模具或碗,1~2小时 +201001147,Recipe,B52轰炸机,B52轰炸机,,Recipe,"[{'term': 'B52轰油炸机', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'B52轰deep-fried机', 'language': 'en', 'language_code': 'en-US'}]",饮料,3.0,,2分钟,1分钟,1杯,"点燃后饮用,使用短吸管,冰火两重天体验,女士可用吸管,男士可一口闷",dishes\drink\B52轰炸机.md,,,,,,,, +201001148,Ingredient,甘露咖啡酒,甘露咖啡酒,,Ingredient,,其他,,,,,,,,10,毫升,True,,,,, +201001149,Ingredient,爱尔兰百利甜酒,爱尔兰百利甜酒,,Ingredient,,其他,,,,,,,,10,毫升,True,,,,, +201001150,Ingredient,蓝天原味伏特加,蓝天原味伏特加,,Ingredient,,其他,,,,,,,,10,毫升,True,,,,, +201001151,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,在利口酒杯的最底层倒入甘露咖啡酒到 1/3 处。(10ml),1.0,倒,利口酒杯,10秒 +201001152,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,顺着吧勺缓缓倒入爱尔兰百利甜酒,也是 1/3 处 (10ml)。注意要慢,保证层次分明。(太快甜酒会和咖啡混合),2.0,倒,"吧勺,利口酒杯",15秒 +201001153,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,最后在上层倒入蓝天原味伏特加 (10ml),3.0,倒,利口酒杯,10秒 +201001154,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,用打火机热一下杯口,4.0,加热,"打火机,利口酒杯",5秒 +201001155,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,最后一步点火: 看到淡蓝色的小火苗了吗?,5.0,点燃,"打火机,利口酒杯",5秒 +201001156,Recipe,Mojito莫吉托,Mojito莫吉托,,Recipe,,饮料,3.0,,5分钟,2分钟,1杯,"经典鸡尾酒,古巴,低酒精度,薄荷清香",dishes\drink\Mojito莫吉托.md,,,,,,,, +201001157,Ingredient,青柠,青柠,,Ingredient,,蔬菜,,,,,,,,1,块,True,,,,, +201001158,Ingredient,薄荷叶,薄荷叶,,Ingredient,,蔬菜,,,,,,,,5,珠,True,,,,, +201001159,Ingredient,糖浆,糖浆,,Ingredient,,调料,,,,,,,,20,毫升,False,,,,, +201001160,Ingredient,金色朗姆酒,金色朗姆酒,,Ingredient,,其他,,,,,,,,45,毫升,True,,,,, +201001161,Ingredient,蓝天原味伏特加,蓝天原味伏特加,,Ingredient,,其他,,,,,,,,10,毫升,True,,,,, +201001162,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,1,杯,False,,,,, +201001163,Ingredient,苏打水,苏打水,,Ingredient,,其他,,,,,,,,1,杯,False,,,,, +201001164,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将切成半块的青柠之一切成小块,放入海波杯,随后用研杵将其捣出汁,1.0,"切,捣","研杵,海波杯",30秒 +201001165,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用3-4珠薄荷叶沿着杯口涂抹,随后将其放入杯中,2.0,涂抹,海波杯,15秒 +201001166,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入糖浆20ml,3.0,加,量杯,5秒 +201001167,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入金色朗姆酒45ml,4.0,加,量杯,5秒 +201001168,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将剩下的半块青柠压出汁水放入杯中,5.0,压汁,压汁器,10秒 +201001169,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,轻轻搅拌,使砂糖/糖浆处于半融合状态,6.0,搅拌,调酒棒,10秒 +201001170,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将打碎的冰块放入杯中,直到占杯中3/4,7.0,加冰,海波杯,10秒 +201001171,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入冰镇苏打水直到刚好淹没碎冰,8.0,加,海波杯,5秒 +201001172,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,旋转搅拌半分钟,9.0,搅拌,调酒棒,30秒 +201001173,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,使用碎冰将海波杯补满,10.0,加冰,海波杯,5秒 +201001174,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将剩下的一株薄荷叶拍醒,插入碎冰,作装饰,11.0,"拍醒,装饰",海波杯,10秒 +201001175,Recipe,冬瓜茶,冬瓜茶,,Recipe,,饮料,2.0,,2小时以上(冷藏腌制),1~2小时(熬制),4-5人,"口感调整:冰糖用量可调甜度,冷藏保存1周内喝完",dishes\drink\冬瓜茶.md,,,,,,,, +201001176,Ingredient,冬瓜,冬瓜,,Ingredient,,蔬菜,,,,,,,,1000,g,True,,,,, +201001177,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,300,g,False,,,,, +201001178,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将冬瓜去皮,去籽,切成小块(每块不超过 4cm)。,1.0,切,"刀,案板", +201001179,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,冬瓜加入冰糖,搅拌均匀,盖上保鲜膜放冰箱冷藏 2 小时以上。,2.0,"搅拌,腌制","盆,保鲜膜,冰箱",2小时以上 +201001180,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,此时冬瓜出了很多水,倒入锅中大火煮开,然后转中小火慢慢熬制 1~2 个小时,中途多搅拌防止糊锅。,3.0,"煮,熬制,搅拌","大锅,锅铲",1~2小时 +201001181,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,使用过滤网将煮好的冬瓜茶液过滤,取出冬瓜块,只保留茶液。,4.0,过滤,过滤网, +201001182,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将冬瓜茶液放凉后,倒入干净的容器中,放入冰箱冷藏即可。,5.0,冷却,"容器,冰箱", +201001183,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,熬好的冬瓜茶液是浓缩汁,根据个人喜好添加水或其他饮品,冷热皆宜。,6.0,稀释,, +201001184,Recipe,可乐桶,可乐桶,,Recipe,,饮料,2.0,,5分钟,0分钟,1杯(约900毫升),可乐桶因冰块和可乐的口感掩盖了威士忌的酒味,因此不善酒力的人也容易在不知不觉中过量饮酒,请在保证个人与饮酒者的安全下调配,dishes\drink\可乐桶.md,,,,,,,, +201001185,Ingredient,波旁威士忌,波旁威士忌,,Ingredient,,其他,,,,,,,,100,毫升,True,,,,, +201001186,Ingredient,可口可乐,可口可乐,,Ingredient,,其他,,,,,,,,500,毫升,True,,,,, +201001187,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,300,克,False,,,,, +201001188,Ingredient,柠檬,柠檬,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201001189,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将柠檬对半切(刀方向垂直于柠檬的头尾连线),并从其中的一半中切取一片柠檬备用,1.0,切,刀, +201001190,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,再次将柠檬对半切,将得到的4角柠檬用压汁器压出柠檬汁置于容器中备用,2.0,"切,压汁","刀,手动压汁器", +201001191,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将挤压过的柠檬置于容器中备用,3.0,,, +201001192,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,选择一个杯子,建议使用容量在大约1升的大型玻璃杯或铁皮酒桶,4.0,,大型玻璃杯或铁皮酒桶, +201001193,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将冰块和挤压过的柠檬入杯中(可根据个人喜好设计柠檬与冰块的摆放),5.0,,, +201001194,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入15毫升柠檬汁(如果喜酸可以加多点或全加),6.0,倒,, +201001195,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,沿杯壁缓慢倒入可口可乐至距离杯口3/4处(控制可乐和威士忌的比例约在5:1),7.0,倒,, +201001196,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入威士忌直至满杯,8.0,倒,, +201001197,Recipe,奶茶,奶茶,,Recipe,,饮料,2.0,,0分钟,20-30分钟,1份,"保温冲泡,茶包均匀冲泡",dishes\drink\奶茶.md,,,,,,,, +201001198,Ingredient,袋泡红茶,袋泡红茶,,Ingredient,,其他,,,,,,,,4,克,True,,,,, +201001199,Ingredient,全脂奶粉,全脂奶粉,,Ingredient,,其他,,,,,,,,11.5,克,True,,,,, +201001200,Ingredient,砂糖,砂糖,,Ingredient,,调料,,,,,,,,6,克,False,,,,, +201001201,Ingredient,沸水,沸水,,Ingredient,,其他,,,,,,,,190,毫升,False,,,,, +201001202,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,取袋泡红茶2包放入杯中,加入180-200mL沸水。,1.0,冲泡,杯子, +201001203,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,等待20-30分钟。,2.0,浸泡,杯子,20-30分钟 +201001204,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,称取11-12g奶粉和5-7g砂糖,分别加入前一步骤得到的液体中。,3.0,"称量,加入","电子秤,杯子", +201001205,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,搅拌均匀即可饮用。,4.0,搅拌,搅拌棒或勺子, +201001206,Recipe,杨枝甘露,杨枝甘露,,Recipe,,饮料,2.0,,10分钟,0分钟,1份,奇亚籽代替西谷米,免煮省时,dishes\drink\杨枝甘露.md,,,,,,,, +201001207,Ingredient,奇亚籽,奇亚籽,,Ingredient,,淀粉类,,,,,,,,24,g,True,,,,, +201001208,Ingredient,牛奶,牛奶,,Ingredient,,蛋白质,,,,,,,,50,ml,True,,,,, +201001209,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,2,小块,False,,,,, +201001210,Ingredient,芒果,芒果,,Ingredient,,蔬菜,,,,,,,,1,粒,True,,,,, +201001211,Ingredient,葡萄柚,葡萄柚,,Ingredient,,蔬菜,,,,,,,,0.5,粒,True,,,,, +201001212,Ingredient,椰奶,椰奶,,Ingredient,,蛋白质,,,,,,,,150,ml,True,,,,, +201001213,Ingredient,切丝芒果干,切丝芒果干,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201001214,Ingredient,切丝柳橙干,切丝柳橙干,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201001215,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,奇亚籽泡牛奶 10 分钟。,1.0,泡,杯子,10分钟 +201001216,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,泡籽之时,把半粒芒果、葡萄柚去皮切丁,放入杯中。,2.0,"去皮,切丁","水果刀,杯子", +201001217,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,半粒芒果切小块放入调理机加冰块、椰奶打成泥。,3.0,"切,打泥","水果刀,调理机/果汁机", +201001218,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入杯中,放上点缀材料(如有)。,4.0,"倒,放",杯子, +201001219,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,一边享用一边写代码!!,5.0,,, +201001220,Recipe,酸梅汤(半成品加工),酸梅汤(半成品加工),,Recipe,,饮料,1.0,,5分钟,5分钟,1份,"可冷藏后饮用,可省略方糖,可省略二锅头,饮酒勿驾车",dishes\drink\酸梅汤(半成品加工).md,,,,,,,, +201001221,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,1177,克,True,,,,, +201001222,Ingredient,酸梅晶固体饮料,酸梅晶固体饮料,,Ingredient,,调料,,,,,,,,120,克,True,,,,, +201001223,Ingredient,方糖,方糖,,Ingredient,,调料,,,,,,,,9,克,False,,,,, +201001224,Ingredient,北京二锅头酒,北京二锅头酒,,Ingredient,,调料,,,,,,,,48,克,False,,,,, +201001225,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,取饮用水 1177 克。,1.0,,量杯或电子秤,30秒 +201001226,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,放入酸梅晶固体饮料 60 克,使用汤匙顺时针搅拌 50 圈。,2.0,搅拌,汤匙,1分钟 +201001227,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,再放入剩下 60 克酸梅晶固体饮料,再次使用汤匙顺时针搅拌 50 圈。,3.0,搅拌,汤匙,1分钟 +201001228,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,放入 9 克的方糖,使用汤匙顺时针搅拌 100 圈。,4.0,搅拌,汤匙,1.5分钟 +201001229,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入北京二锅头酒 48 克,用汤匙顺时针搅拌 30 圈。,5.0,搅拌,汤匙,30秒 +201001230,Recipe,长岛冰茶,长岛冰茶,,Recipe,,饮料,2.0,,5分钟,0分钟,1杯,"不含茶却有冰茶口感,酒精度约15%,口感柔和易接受",dishes\drink\长岛冰茶.md,,,,,,,, +201001231,Ingredient,金酒,金酒,,Ingredient,,其他,,,,,,,,15,毫升,True,,,,, +201001232,Ingredient,龙舌兰酒,龙舌兰酒,,Ingredient,,其他,,,,,,,,15,毫升,True,,,,, +201001233,Ingredient,伏特加,伏特加,,Ingredient,,其他,,,,,,,,15,毫升,True,,,,, +201001234,Ingredient,白朗姆酒,白朗姆酒,,Ingredient,,其他,,,,,,,,15,毫升,True,,,,, +201001235,Ingredient,橙味甜酒,橙味甜酒,,Ingredient,,其他,,,,,,,,15,毫升,True,,,,, +201001236,Ingredient,柠檬,柠檬,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201001237,Ingredient,柠檬汁,柠檬汁,,Ingredient,,调料,,,,,,,,30,毫升,False,,,,, +201001238,Ingredient,枫糖浆,枫糖浆,,Ingredient,,调料,,,,,,,,20,毫升,False,,,,, +201001239,Ingredient,可乐,可乐,,Ingredient,,其他,,,,,,,,75,毫升,True,,,,, +201001240,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,100,克,False,,,,, +201001241,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,柠檬对半切,挤出30ml柠檬汁至杯中,1.0,"切,挤","刀,杯子",30秒 +201001242,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,依次向杯中加入15ml金酒、15ml龙舌兰酒、15ml伏特加、15ml白朗姆酒、15ml橙味甜酒,2.0,倒,"量杯,杯子",30秒 +201001243,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,向杯中缓慢倒入20ml枫糖浆,边倒边搅拌,3.0,"倒,搅拌","量杯,搅拌棒,杯子",20秒 +201001244,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,向杯中加入75ml可乐,4.0,倒,"量杯,杯子",10秒 +201001245,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,向杯中加入冰块直至满杯,5.0,加,杯子,10秒 +201001246,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,轻轻搅拌20秒,6.0,搅拌,"搅拌棒,杯子",20秒 +201001247,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,开始享用,7.0,,, +201001248,Recipe,冰粉,冰粉,,Recipe,,饮料,2.0,豫菜,30分钟,2.5小时静置成型,5人,"观察颜色和粘度变化,颜色过浅或水不黏需增加冰粉籽或延长揉搓时间",dishes\drink\冰粉\冰粉.md,,,,,,,, +201001249,Ingredient,冰粉籽,冰粉籽,,Ingredient,,淀粉类,,,,,,,,200,克,True,,,,, +201001250,Ingredient,凉白开,凉白开,,Ingredient,,其他,,,,,,,,2000,毫升,True,,,,, +201001251,Ingredient,薄荷汁,薄荷汁,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201001252,Ingredient,薄荷粉,薄荷粉,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001253,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将凉白开倒入盆中,1.0,,盆, +201001254,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将冰粉籽全部用纱布包起来,开口处打结,2.0,包,纱布, +201001255,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将包好的冰粉籽放入凉白开中,在凉白开中用力揉搓6分钟,3.0,揉搓,盆,6分钟 +201001256,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将凉白开放置2.5小时,即可成型,4.0,静置,盆,2.5小时 +201001257,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,用勺子将石凉粉装进一次性透明塑料杯中,加入10ml薄荷汁或10g薄荷粉,再放入遇水发光冰块,用勺子慢慢搅拌均匀,5.0,"装杯,搅拌","勺子,一次性透明塑料杯", +201001258,Recipe,奇异果菠菜特调,奇异果菠菜特调,,Recipe,,饮料,1.0,,5分钟,1分钟,1人份,"糖量可调,自制饮料,宜家仿制",dishes\drink\奇异果菠菜特调\奇异果菠菜特调.md,,,,,,,, +201001259,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,700,毫升,True,,,,, +201001260,Ingredient,奇异果,奇异果,,Ingredient,,其他,,,,,,,,2,个,True,,,,, +201001261,Ingredient,苹果,苹果,,Ingredient,,其他,,,,,,,,0.5,个,True,,,,, +201001262,Ingredient,菠菜叶,菠菜叶,,Ingredient,,蔬菜,,,,,,,,4,叶,True,,,,, +201001263,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,12,克,False,,,,, +201001264,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将猕猴桃切成两半,每半再分四份小块,1.0,切,刀,1分钟 +201001265,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将苹果切丁,2.0,切,刀,30秒 +201001266,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将菠菜叶去梗,只留叶子部分,3.0,去梗,手,30秒 +201001267,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将菠菜切碎,4.0,切,刀,30秒 +201001268,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,一起倒入榨汁机搅拌杯,5.0,倒入,榨汁机,10秒 +201001269,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,注水,6.0,加入,榨汁机,5秒 +201001270,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入白砂糖,7.0,加入,榨汁机,5秒 +201001271,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,启动搅拌机,搅拌约4个15秒(每15秒停下看状态),8.0,搅拌,榨汁机,1分钟 +201001272,Recipe,柠檬水,柠檬水,,Recipe,,饮料,1.0,,1分钟,1分钟,1杯(约500毫升),抖音教程,dishes\drink\柠檬水\柠檬水.md,,,,,,,, +201001273,Ingredient,柠檬,柠檬,,Ingredient,,蔬菜,,,,,,,,42.5,克,True,,,,, +201001274,Ingredient,果蜜,果蜜,,Ingredient,,调料,,,,,,,,42.5,克,False,,,,, +201001275,Ingredient,冰,冰,,Ingredient,,其他,,,,,,,,几块,,False,,,,, +201001276,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,称40~45克柠檬,放入雪克杯中,1.0,称量,雪克杯,10秒 +201001277,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,雪克杯盖盖子锤大约10次,2.0,锤,雪克杯,10秒 +201001278,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入果蜜40~45克,3.0,加入,雪克杯,5秒 +201001279,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,补水,4.0,加水,雪克杯,5秒 +201001280,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,摇晃均匀,5.0,摇晃,雪克杯,10秒 +201001281,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,最后根据喜好加冰,6.0,加冰,雪克杯,5秒 +201001282,Recipe,泰国手标红茶,泰国手标红茶,,Recipe,,饮料,3.0,泰国,5分钟,10分钟,1人,,dishes\drink\泰国手标红茶\泰国手标红茶.md,,,,,,,, +201001283,Ingredient,水,水,,Ingredient,,其他,,,,,,,,600,毫升,True,,,,, +201001284,Ingredient,茶粉,茶粉,,Ingredient,,其他,,,,,,,,20,克,True,,,,, +201001285,Ingredient,炼乳,炼乳,,Ingredient,,调料,,,,,,,,24,克,False,,,,, +201001286,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,24,克,False,,,,, +201001287,Ingredient,牛奶,牛奶,,Ingredient,,蛋白质,,,,,,,,18,毫升,False,,,,, +201001288,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,600毫升水大火烧开,1.0,煮,锅, +201001289,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,在港式奶茶过滤袋中装入20克茶粉,将开水倒入过滤袋中,过滤20遍,2.0,过滤,港式奶茶过滤袋, +201001290,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,使用克称量取24克炼乳、24克白糖和18毫升牛奶,放入1000毫升以上的水壶中,3.0,称量,"克称,水壶", +201001291,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将过滤好的茶水倒入水壶中搅拌,直到白糖融化,4.0,搅拌,水壶, +201001292,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将水壶放入冰箱冷藏4小时以上,5.0,冷藏,冰箱,4小时 +201001293,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,喝前可加入6-8颗冰块,6.0,,, +201001294,Recipe,海边落日,海边落日,,Recipe,,饮料,3.0,,5分钟,3分钟,1杯,"分层效果,透明玻璃杯,摇匀",dishes\drink\海边落日\海边落日.md,,,,,,,, +201001295,Ingredient,红石榴糖浆,红石榴糖浆,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201001296,Ingredient,NFC橙汁,NFC橙汁,,Ingredient,,其他,,,,,,,,35~50,ml,True,,,,, +201001297,Ingredient,苏打水,苏打水,,Ingredient,,其他,,,,,,,,50,ml,True,,,,, +201001298,Ingredient,白朗姆,白朗姆,,Ingredient,,其他,,,,,,,,30,ml,True,,,,, +201001299,Ingredient,蓝橙力娇酒,蓝橙力娇酒,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201001300,Ingredient,柠檬汁,柠檬汁,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201001301,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,适量,块,False,,,,, +201001302,Ingredient,柠檬,柠檬,,Ingredient,,蔬菜,,,,,,,,1,片,False,,,,, +201001303,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,柠檬洗净切出一片,1.0,切,水果刀,30秒 +201001304,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,选择一个容量在350~400毫升的透明玻璃杯,2.0,准备,玻璃杯,10秒 +201001305,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放入大冰块,用搅拌棒搅拌冰杯,3.0,搅拌,搅拌棒,15秒 +201001306,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入红石榴糖浆,4.0,倒入,量酒器,5秒 +201001307,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,让橙汁沿搅拌棒导入酒杯,到杯一半即可,5.0,倒入,搅拌棒,5秒 +201001308,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,轻轻搅拌半圈,6.0,搅拌,搅拌棒,5秒 +201001309,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,倒入苏打水,7.0,倒入,量酒器,5秒 +201001310,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,在调酒杯中加入白朗姆、蓝橙力娇酒、柠檬汁和冰块,然后摇匀,8.0,摇匀,"调酒杯,量酒器",20秒 +201001311,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将摇匀后的酒液轻轻倒入酒杯中,9.0,倒入,调酒杯,5秒 +201001312,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,插上柠檬片和吸管,10.0,装饰,吸管,5秒 +201001313,Recipe,百香果橙子特调,百香果橙子特调,,Recipe,,饮料,3.0,,12-24小时(百香果腌制),6分钟(泡茶),1杯(约380毫升),"茉莉绿茶可替换为苏打气泡水,分层效果,透明玻璃杯更佳",dishes\drink\百香果橙子特调\百香果橙子特调.md,,,,,,,, +201001314,Ingredient,百香果,百香果,,Ingredient,,其他,,,,,,,,3,个,True,,,,, +201001315,Ingredient,橙子,橙子,,Ingredient,,其他,,,,,,,,1,个,True,,,,, +201001316,Ingredient,茉莉绿茶茶叶,茉莉绿茶茶叶,,Ingredient,,其他,,,,,,,,3,克,True,,,,, +201001317,Ingredient,苏打气泡水,苏打气泡水,,Ingredient,,其他,,,,,,,,240,毫升,True,,,,, +201001318,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201001319,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,160,克,False,,,,, +201001320,Ingredient,蜂蜜,蜂蜜,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001321,Ingredient,薄荷叶,薄荷叶,,Ingredient,,蔬菜,,,,,,,,1,片,False,,,,, +201001322,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,150,毫升,False,,,,, +201001323,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将三个百香果的果肉取出来(里面的汁也不能放过),置于容器中,1.0,切,"刀,容器", +201001324,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,称量30克白砂糖、10克蜂蜜放入百香果中,搅拌均匀;若没有蜂蜜可用5克白砂糖代替,2.0,"称量,搅拌","电子秤,勺子", +201001325,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,容器用保鲜膜封口,放入冰箱腌制12~24小时,3.0,腌制,"保鲜膜,冰箱",12-24小时 +201001326,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,称量3~6克茉莉绿茶茶叶置于容器,加入150毫升开水,泡6分钟,4.0,"称量,泡","电子秤,容器",6分钟 +201001327,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,往泡好的绿茶中加入90克冰块冷却,可搅拌加速冷却;待冰块消失后过滤得约240毫升茶水,5.0,"冷却,过滤","冰块,过滤器", +201001328,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将橙子对半切(刀方向垂直于橙子的头尾连线),并从其中一半切取一片橙子备用,6.0,切,刀, +201001329,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,再次将橙子对半切,得到4角橙子,用压汁器压出橙汁备用,7.0,"切,压汁","刀,手动压汁器", +201001330,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,选350~400毫升透明玻璃杯,杯底放70克冰块,倒入全部橙汁,8.0,倒,玻璃杯, +201001331,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将一片橙子贴杯内壁放置,加入一次分量的腌制百香果,9.0,放,勺子, +201001332,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,缓慢注入茉莉绿茶直至满杯,便于分层;可选放装饰绿叶,搅拌均匀后享用,10.0,"倒,搅拌","玻璃杯,勺子", +201001333,Recipe,砂糖椰子冰沙,砂糖椰子冰沙,,Recipe,,饮料,1.0,,10小时以上冷冻,约2分钟(抽打与装盘),1人份,提前冷冻不宜超过7天,否则有变质风险,dishes\drink\砂糖椰子冰沙\砂糖椰子冰沙.md,,,,,,,, +201001334,Ingredient,瓶装椰汁,瓶装椰汁,,Ingredient,,其他,,,,,,,,500,ml,True,,,,, +201001335,Ingredient,咖啡调糖,咖啡调糖,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001336,Ingredient,坚果碎,坚果碎,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201001337,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,500ml瓶装椰汁倒掉200ml,立刻拧紧瓶盖。,1.0,倒,瓶装椰汁,30秒 +201001338,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将这瓶椰汁放入冰箱冷冻区并冷冻10小时以上。,2.0,冷冻,冰箱,10小时以上 +201001339,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将这瓶椰汁取出,若确认瓶中椰汁已彻底冻结,则在墙角、椅背、桌角等坚硬表面上用力抽打。(请务必确认表面不会因此受到损伤),3.0,抽打,墙角/椅背/桌角,1-2分钟 +201001340,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,当抽打到冻结椰汁变成冰沙状态,打开瓶盖倒出冰沙。,4.0,倒出,瓶装椰汁,30秒 +201001341,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,在冰沙表面均匀撒上咖啡调糖或坚果碎。,5.0,撒,,15秒 +201001342,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,完成,6.0,,, +201001343,Recipe,耙耙柑茶,耙耙柑茶,,Recipe,,饮料,2.0,,约8分钟,约20秒,1杯(约300毫升),"耙耙柑可用丑橘等易分离果肉的柑橘替代,果肉与茶水比例1:1,可按比例放大分量",dishes\drink\耙耙柑茶\耙耙柑茶.md,,,,,,,, +201001344,Ingredient,耙耙柑,耙耙柑,,Ingredient,,蔬菜,,,,,,,,200,克,True,,,,, +201001345,Ingredient,茉莉绿茶,茉莉绿茶,,Ingredient,,其他,,,,,,,,2,克,False,,,,, +201001346,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,60,克,False,,,,, +201001347,Ingredient,蔗糖糖浆,蔗糖糖浆,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001348,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,称量2~4克茉莉绿茶叶置于容器,加入100毫升开水,泡6分钟,1.0,泡,容器,6分钟 +201001349,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,往泡好的绿茶中放入60克冰块冷却,可搅拌加速冷却,2.0,搅拌,容器,约1分钟 +201001350,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,待冰块消失后,将茶叶过滤得到茉莉绿茶茶水约160毫升,3.0,过滤,滤网, +201001351,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,取出耙耙柑的肉瓣,并将外皮剥去,取得果肉,4.0,剥,手, +201001352,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,取130克果肉和130毫升茉莉绿茶放入搅拌机中,5.0,称量,搅拌机, +201001353,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入10克蔗糖糖浆(可选,如果喜甜可放),6.0,倒,搅拌机, +201001354,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,封盖启动搅拌机,搅拌20秒后将搅拌产物倒入杯中,7.0,搅拌,"搅拌机,杯子",20秒 +201001355,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,取一点果肉撕碎撒在液面上,8.0,撒,手, +201001356,Recipe,菠萝咖啡特调,菠萝咖啡特调,,Recipe,,饮料,3.0,,5分钟,5分钟,1人,"花果风味咖啡液更佳,浓缩可用中烘豆,冷萃可用水洗或日晒豆,奶油倒入时放低高度形成均匀奶盖,使用新鲜咖啡液和菠萝汁提升风味",dishes\drink\菠萝咖啡特调\菠萝咖啡特调.md,,,,,,,, +201001357,Ingredient,咖啡液,咖啡液,,Ingredient,,其他,,,,,,,,30,ml,True,,,,, +201001358,Ingredient,菠萝汁,菠萝汁,,Ingredient,,其他,,,,,,,,60,ml,True,,,,, +201001359,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,50,g,False,,,,, +201001360,Ingredient,苏打水,苏打水,,Ingredient,,其他,,,,,,,,30,ml,False,,,,, +201001361,Ingredient,奶油,奶油,,Ingredient,,其他,,,,,,,,30,ml,False,,,,, +201001362,Ingredient,牛奶,牛奶,,Ingredient,,其他,,,,,,,,10,ml,False,,,,, +201001363,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,8,g,False,,,,, +201001364,Ingredient,海盐,海盐,,Ingredient,,调料,,,,,,,,0.5,g,False,,,,, +201001365,Ingredient,朗姆酒,朗姆酒,,Ingredient,,其他,,,,,,,,5,ml,False,,,,, +201001366,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,杯子里依次加入冰块、咖啡液、菠萝汁和苏打水,1.0,混合,杯子,30秒 +201001367,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,奶油加糖打发至湿性发泡,加入朗姆酒和牛奶搅拌均匀,保持流动性,2.0,"打发,搅拌","打蛋器,盆",2-3分钟 +201001368,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,在第一步混合液上方倒入奶油,3.0,倒入,勺子,30秒 +201001369,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,奶油顶面撒上海盐,4.0,撒,小勺,10秒 +201001370,Recipe,酒酿(醪糟),酒酿(醪糟),,Recipe,,饮料,4.0,,1小时(不含等待),24-48小时发酵,6-8人,"发酵温度28-32°C,失败原因:温度过高、米饭过热、容器不洁,可搭配汤圆、蛋花、枸杞,酒酿汁可做米糕、饼、调料",dishes\drink\酒酿醪糟\酒酿醪糟.md,,,,,,,, +201001371,Ingredient,糯米,糯米,,Ingredient,,淀粉类,,,,,,,,800,克,True,,,,, +201001372,Ingredient,安琪甜酒曲,安琪甜酒曲,,Ingredient,,调料,,,,,,,,8,克,False,,,,, +201001373,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,1320,克,False,,,,, +201001374,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将800g糯米淘洗干净放入电饭煲,加入720g清水选择蒸饭模式,1.0,蒸,电饭煲, +201001375,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,蒸熟后将米饭倒出摊凉,使用干净的工具将其摊至30°C左右,2.0,摊凉,温度计, +201001376,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将8g安琪甜酒曲用20ml温水(约30°C)化开,均匀撒在糯米饭中,同时翻拌均匀,3.0,混合,干净工具, +201001377,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,向糯米饭中加入600g清水帮助酒曲翻拌均匀,静置2-3分钟,4.0,混合,,2-3分钟 +201001378,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,用擀面杖在糯米饭中央挖一个小洞便于出酒,5.0,挖洞,擀面杖, +201001379,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将混合好的米饭装入干净容器中,轻轻压平表面,盖上盖子或保鲜膜密封好,6.0,装罐,"干净密封玻璃或陶瓷容器,保鲜膜", +201001380,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放置于28~32°C环境下发酵24~48小时,期间不可剧烈摇晃或移动,7.0,发酵,,24-48小时 +201001381,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,发酵成功后冷藏保存,可冷藏7~10天,8.0,冷藏,, +201001382,Recipe,酸梅汤,酸梅汤,,Recipe,,饮料,4.0,,2小时以上(常温浸泡),60分钟(头煎40分钟+二煎20分钟),约2升,冷藏后饮用效果更佳,dishes\drink\酸梅汤\酸梅汤.md,,,,,,,, +201001383,Ingredient,水,水,,Ingredient,,其他,,,,,,,,2000,毫升,True,,,,, +201001384,Ingredient,乌枣,乌枣,,Ingredient,,其他,,,,,,,,25,克,True,,,,, +201001385,Ingredient,乌梅,乌梅,,Ingredient,,其他,,,,,,,,25,克,True,,,,, +201001386,Ingredient,山楂片(生),山楂片(生),,Ingredient,,其他,,,,,,,,30,克,True,,,,, +201001387,Ingredient,黄冰糖,黄冰糖,,Ingredient,,调料,,,,,,,,100,克,False,,,,, +201001388,Ingredient,甘草,甘草,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201001389,Ingredient,陈皮,陈皮,,Ingredient,,调料,,,,,,,,4,克,False,,,,, +201001390,Ingredient,红豆蔻,红豆蔻,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201001391,Ingredient,干桂花,干桂花,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201001392,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,冲洗材料(干桂花和冰糖除外),用1.5升水常温浸泡两小时以上,1.0,"冲洗,浸泡",盆,2小时以上 +201001393,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,开中大火煮沸,盖盖,转小火煮40分钟,为头煎,2.0,煮,锅,40分钟 +201001394,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将冰糖放入盆内,再将沥好用材的头汤趁热倒入,搅拌至冰糖融化,3.0,搅拌,盆,1-2分钟 +201001395,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,药材重新装回锅内再加600毫升水,开大火煮沸,盖盖,转中火,再煮20分钟为二煎,4.0,煮,锅,20分钟 +201001396,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将二煎和冰糖水趁热混合为成品,在60-70℃加入干桂花(不超过80℃),加盖晾凉,再放入冰箱冷藏3小时以上,5.0,"混合,冷藏","盆,冰箱",3小时以上 +201001397,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,饮用时沥出干桂花,如饮茶般细啜,冰凉振齿,酸醒人、甜适度,滋味丰满而悠长,6.0,"沥出,饮用",滤网或漏勺,1分钟 +201001398,Recipe,金汤力,金汤力,,Recipe,,饮料,2.0,,5分钟,2分钟,1杯,"避免起泡流失,沿杯壁注入,上下提拉搅拌",dishes\drink\金汤力\金汤力.md,,,,,,,, +201001399,Ingredient,金酒,金酒,,Ingredient,,其他,,,,,,,,30~40,毫升,True,,,,, +201001400,Ingredient,汤力水气泡水,汤力水气泡水,,Ingredient,,其他,,,,,,,,1,罐,True,,,,, +201001401,Ingredient,柠檬,柠檬,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201001402,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,100,克,False,,,,, +201001403,Ingredient,新鲜绿叶,新鲜绿叶,,Ingredient,,蔬菜,,,,,,,,1,片,False,,,,, +201001404,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将柠檬对半切(刀方向垂直于柠檬的头尾连线),并从其中的一半中切取一片柠檬备用,1.0,切,刀,30秒 +201001405,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,再次将柠檬对半切,将得到的4角柠檬用压汁器压出柠檬汁置于容器中备用,2.0,"切,压汁","刀,手动压汁器,容器",30秒 +201001406,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,选择一个杯子,建议使用容量在350~400毫升的透明玻璃杯,3.0,,透明玻璃杯,5秒 +201001407,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将100克冰块放置在杯底,4.0,,,5秒 +201001408,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,倒入30~40毫升金酒,5.0,倒,,5秒 +201001409,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入15毫升柠檬汁(如果喜酸可以加多点或全加),6.0,倒,,5秒 +201001410,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,用勺子搅拌均匀,7.0,搅拌,勺子,10秒 +201001411,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将之前准备的一片柠檬放置好,8.0,装饰,,5秒 +201001412,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,缓慢沿杯壁注入汤力水直至满杯(不要倒在冰上,避免起泡流失),9.0,倒,,15秒 +201001413,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,用勺子轻轻上下提拉将液体搅拌均匀(不要旋转搅拌,避免起泡流失),10.0,搅拌,勺子,10秒 +201001414,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,在液面放置好装饰用的绿叶(可选),11.0,装饰,,5秒 +201001415,Recipe,金菲士,金菲士,,Recipe,,饮料,2.0,,5分钟,2分钟,1杯(约350毫升),"使用雪克瓶可提升口感,沿杯壁注入苏打水减少起泡流失,提拉搅拌避免气泡流失",dishes\drink\金菲士\金菲士.md,,,,,,,, +201001416,Ingredient,金酒,金酒,,Ingredient,,其他,,,,,,,,35,毫升,True,,,,, +201001417,Ingredient,苏打气泡水,苏打气泡水,,Ingredient,,其他,,,,,,,,1,罐,True,,,,, +201001418,Ingredient,柠檬,柠檬,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201001419,Ingredient,蔗糖糖浆,蔗糖糖浆,,Ingredient,,调料,,,,,,,,35,克,False,,,,, +201001420,Ingredient,冰块,冰块,,Ingredient,,其他,,,,,,,,100,克,False,,,,, +201001421,Ingredient,新鲜绿叶,新鲜绿叶,,Ingredient,,蔬菜,,,,,,,,1,片,False,,,,, +201001422,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将柠檬对半切(刀方向垂直于柠檬的头尾连线),并从其中的一半中切取一片柠檬备用,1.0,切,刀, +201001423,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,再次将柠檬对半切,将得到的4角柠檬用压汁器压出柠檬汁置于容器中备用,2.0,"切,压汁","刀,手动压汁器", +201001424,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,选择一个容量在350~400毫升的透明玻璃杯,将100克冰块放置在杯底,3.0,放置,玻璃杯, +201001425,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入30~40毫升金酒、20毫升柠檬汁、30~40克蔗糖糖浆,用勺子搅拌均匀,4.0,"倒,搅拌",勺子, +201001426,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将之前准备的一片柠檬放置好,缓慢沿杯壁注入苏打气泡水直至满杯(不要倒在冰上,避免起泡流失),5.0,倒,勺子, +201001427,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,用勺子轻轻上下提拉将液体搅拌均匀(不要旋转搅拌,避免起泡流失),在液面放置好装饰用的绿叶(可选),6.0,"提拉搅拌,放置",勺子, +201001428,Recipe,乡村啤酒鸭,乡村啤酒鸭,,Recipe,,荤菜,4.0,,10分钟,1小时,2-3人,"观察水位线,低于2/3时加热水或啤酒",dishes\meat_dish\乡村啤酒鸭.md,,,,,,,, +201001429,Ingredient,鸭肉,鸭肉,,Ingredient,,蛋白质,,,,,,,,1000,克,True,,,,, +201001430,Ingredient,啤酒,啤酒,,Ingredient,,调料,,,,,,,,1000,毫升,False,,,,, +201001431,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,条,False,,,,, +201001432,Ingredient,红椒,红椒,,Ingredient,,蔬菜,,,,,,,,1,条,False,,,,, +201001433,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,4,颗,False,,,,, +201001434,Ingredient,生姜,生姜,,Ingredient,,调料,,,,,,,,3,厘米,False,,,,, +201001435,Ingredient,小米辣,小米辣,,Ingredient,,调料,,,,,,,,3,颗,False,,,,, +201001436,Ingredient,蒜苗,蒜苗,,Ingredient,,蔬菜,,,,,,,,2,根,False,,,,, +201001437,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,根,False,,,,, +201001438,Ingredient,草果,草果,,Ingredient,,调料,,,,,,,,2,颗,False,,,,, +201001439,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,4,厘米,False,,,,, +201001440,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,颗,False,,,,, +201001441,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,3,片,False,,,,, +201001442,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,6,条,False,,,,, +201001443,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201001444,Ingredient,花生油,花生油,,Ingredient,,调料,,,,,,,,60,毫升,False,,,,, +201001445,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,30,颗,False,,,,, +201001446,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201001447,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,毫升,False,,,,, +201001448,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,毫升,False,,,,, +201001449,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸭肉清洗一遍放进锅中,加清水淹没鸭肉,加入20 ml料酒、1根大葱、拍散的2厘米生姜,开火烧滚,捞出浮沫,鸭肉捞出用清水洗净备用。,1.0,"焯水,清洗","锅,漏勺",5分钟 +201001450,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅清洗后烧热,加入60 ml花生油,油温升至60℃时加入30颗花椒爆香。,2.0,"加热,爆香","炒锅,锅铲",1分钟 +201001451,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,倒入鸭肉翻炒4分钟:2分钟后加入所有香料(草果、桂皮、八角、香叶、干辣椒),3分钟时加入料头(生姜、大蒜、小米辣)。,3.0,炒,"炒锅,锅铲",4分钟 +201001452,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入1000 ml啤酒,大火烧开后转小火炖煮30分钟。,4.0,炖煮,"炒锅,锅盖",30分钟 +201001453,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,炖煮10分钟时加入盐3克、生抽10 ml、老抽5 ml;20分钟时加入青椒和红椒段;29分钟时加入蒜苗段和剩余大葱段,翻炒1分钟后出锅。,5.0,"调味,炖煮,炒",锅铲,1分钟 +201001454,Recipe,冷吃兔,冷吃兔,,Recipe,,荤菜,4.0,川菜,约25分钟(切配10分钟+腌制15分钟),约30分钟(炸制+炒制),按兔肉斤数计算,未给出具体人数,"油量需淹没兔肉,干辣椒极易炸糊需小火,放置一夜更入味",dishes\meat_dish\冷吃兔.md,,,,,,,, +201001455,Ingredient,兔肉,兔肉,,Ingredient,,蛋白质,,,,,,,,1,斤,True,,,,, +201001456,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克/斤兔肉,False,,,,, +201001457,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,1,克/斤兔肉,False,,,,, +201001458,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,克/斤兔肉,False,,,,, +201001459,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,克/斤兔肉,False,,,,, +201001460,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,0.9,升/斤兔肉,False,,,,, +201001461,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,0.5,头/斤兔肉,False,,,,, +201001462,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,0.5,头蒜量,False,,,,, +201001463,Ingredient,小葱/大葱/洋葱,小葱/大葱/洋葱,,Ingredient,,蔬菜,,,,,,,,15,克/斤兔肉,False,,,,, +201001464,Ingredient,干辣椒,干辣椒,,Ingredient,,蔬菜,,,,,,,,1,体积等于兔肉体积,False,,,,, +201001465,Ingredient,青花椒,青花椒,,Ingredient,,调料,,,,,,,,1,小碗/3斤兔肉,False,,,,, +201001466,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,粒/斤兔肉,False,,,,, +201001467,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,1,大拇指长/斤兔肉,False,,,,, +201001468,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,5,片/斤兔肉,False,,,,, +201001469,Ingredient,山奈,山奈,,Ingredient,,调料,,,,,,,,1,黄豆大小/斤兔肉,False,,,,, +201001470,Ingredient,白蔻,白蔻,,Ingredient,,调料,,,,,,,,2,颗/斤兔肉,False,,,,, +201001471,Ingredient,小茴香,小茴香,,Ingredient,,调料,,,,,,,,15,克/斤兔肉,False,,,,, +201001472,Ingredient,白芝麻,白芝麻,,Ingredient,,其他,,,,,,,,25,克/斤兔肉,False,,,,, +201001473,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,蒜、姜扒皮并剁碎备用,八角、桂皮、香叶、山奈、白蔻、小茴香洗净备用。,1.0,"切,洗","刀,案板,盆",约5分钟 +201001474,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,干辣椒剪成2厘米的小段,洗净备用。,2.0,"剪,洗","剪刀,盆",约3分钟 +201001475,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,小葱/大葱/洋葱洗净,洋葱切成小块。,3.0,"洗,切","刀,案板,盆",约2分钟 +201001476,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,兔肉剁成2厘米的小块,加入盐、料酒、味精调味,腌制15分钟。,4.0,"切,腌制","刀,案板,盆",15分钟 +201001477,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中倒油,油温4成热下小葱/大葱/洋葱,中小火煸炒出香味,待到小葱/大葱/洋葱微焦,将其捞出。,5.0,炒,"炒锅,锅铲",约3-5分钟 +201001478,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,开大火升高油温,油温8成热时下入兔肉,炸制过程转中小火,炸至兔肉微微焦黄时捞出兔肉。,6.0,炸,"炒锅,漏勺",约5-7分钟 +201001479,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,升高油温,倒入干辣椒、青花椒、八角、桂皮、香叶、山奈、白蔻、小茴香;转小火将辣椒段炸脆。,7.0,炸,"炒锅,锅铲",约2-3分钟 +201001480,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,重新倒入兔肉,加入蚝油、翻炒几分钟。,8.0,炒,"炒锅,锅铲",约3分钟 +201001481,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,关火,加入蒜、姜、白芝麻,翻炒均匀。,9.0,炒,"炒锅,锅铲",约30秒 +201001482,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,放置一夜更加入味。,10.0,静置,容器,过夜 +201001483,Recipe,可乐鸡翅,可乐鸡翅,,Recipe,,荤菜,3.0,,10分钟(腌制),约25分钟,1盘,"生姜爆香防粘锅,收汁勿开大火防苦,口味偏甜",dishes\meat_dish\可乐鸡翅.md,,,,,,,, +201001484,Ingredient,鸡翅中,鸡翅中,,Ingredient,,蛋白质,,,,,,,,10,只,True,,,,, +201001485,Ingredient,可乐,可乐,,Ingredient,,调料,,,,,,,,500,毫升,False,,,,, +201001486,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,克,False,,,,, +201001487,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,克,False,,,,, +201001488,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,克,False,,,,, +201001489,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201001490,Ingredient,生姜,生姜,,Ingredient,,蔬菜,,,,,,,,2,片,False,,,,, +201001491,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201001492,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,个,False,,,,, +201001493,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡翅入锅,倒入冷水淹没。放生姜1片和料酒10~20毫升。大火煮开(大约2分钟)后,撇去浮沫,沥出水分,1.0,"煮,焯水","锅,漏勺",约2分钟 +201001494,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,捞出鸡翅,用刀将两边各划上两口改刀。用生抽约10克腌制鸡翅10分钟,2.0,"切,腌制","刀,案板,碗",10分钟 +201001495,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅重新小火起油,先将剩余姜片爆香,然后下入腌好的鸡翅。将鸡翅煎至金黄翻面,直到两面金黄,与姜片一起翻炒4~5下,3.0,"煎,炒","炒锅,锅铲",约5分钟 +201001496,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入可乐没过鸡翅,开大火煮沸,撇去黑色浮沫,加入葱结,4.0,"煮,撇沫","锅,锅铲",约2分钟 +201001497,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入盐2克、白糖10克、生抽3克、老抽3克调味,5.0,调味,锅铲,约30秒 +201001498,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,待葱结变黄,捞出葱结和姜片,转中火继续慢煮,6.0,"煮,慢炖","锅,筷子",约8分钟 +201001499,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,可乐呈现挂丝状态后,关小火收汁,让汁牢牢挂在鸡翅上,出锅装盘,7.0,收汁,"锅,锅铲",约2分钟 +201001500,Recipe,咕噜肉,咕噜肉,,Recipe,,荤菜,4.0,粤菜,25分钟(含腌制20分钟、切配5分钟),11分钟(炸6分钟、炒5分钟),1人份,裹粉加鸡蛋更香脆,dishes\meat_dish\咕噜肉.md,,,,,,,, +201001501,Ingredient,梅头猪肉,梅头猪肉,,Ingredient,,蛋白质,,,,,,,,100,克,True,,,,, +201001502,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,25,克,False,,,,, +201001503,Ingredient,罐头菠萝片,罐头菠萝片,,Ingredient,,蔬菜,,,,,,,,75,克,False,,,,, +201001504,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,0.25,茶匙,False,,,,, +201001505,Ingredient,茄汁,茄汁,,Ingredient,,调料,,,,,,,,4,汤匙,False,,,,, +201001506,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,2,茶匙,False,,,,, +201001507,Ingredient,蒜蓉,蒜蓉,,Ingredient,,调料,,,,,,,,1,汤匙,False,,,,, +201001508,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,0.5,茶匙,False,,,,, +201001509,Ingredient,生粉,生粉,,Ingredient,,淀粉类,,,,,,,,2.5,茶匙,False,,,,, +201001510,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,2,汤匙,False,,,,, +201001511,Ingredient,水,水,,Ingredient,,其他,,,,,,,,200,毫升,False,,,,, +201001512,Ingredient,油,油,,Ingredient,,其他,,,,,,,,500,毫升,False,,,,, +201001513,Ingredient,生粉(裹粉用),生粉(裹粉用),,Ingredient,,淀粉类,,,,,,,,6,汤匙,False,,,,, +201001514,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将梅头猪肉(100 克)洗净,然后用厨房纸抹干水份,将猪肉切成比想要的成品小一圈的大小。,1.0,切,"刀,案板,厨房纸",2分钟 +201001515,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用盐(1/2 茶匙)腌制梅头猪肉 20 分钟。,2.0,腌制,盆,20分钟 +201001516,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将青椒(25 克)切碎。,3.0,切,"刀,案板",1分钟 +201001517,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将菠萝片(75 克)切件。,4.0,切,"刀,案板",1分钟 +201001518,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,在碗中加入茄汁(4 汤匙)、白醋(2 茶匙)、蒜蓉(1 汤匙)、生抽(½ 茶匙)、生粉(2½ 茶匙)、白砂糖(2 汤匙)、盐(¼ 茶匙)和水(200 毫升),拌匀成酱汁。,5.0,拌,"碗,筷子",1分钟 +201001519,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将梅头猪肉粒沾上生粉(6 汤匙)。,6.0,裹粉,盆,1分钟 +201001520,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入油(500 毫升)中火加热。,7.0,加热,锅,2分钟 +201001521,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将梅头猪肉粒放至锅里中火炸 5 分钟,然后盛起。,8.0,炸,"锅,漏勺",5分钟 +201001522,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入梅头猪肉粒,再大火翻炸 1 分钟。,9.0,炸,"锅,锅铲",1分钟 +201001523,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入油(1 茶匙)和酱汁,中火加热 3 分钟。,10.0,炒,"锅,锅铲",3分钟 +201001524,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,加入青椒和菠萝,大火加热 2 分钟。,11.0,炒,"锅,锅铲",2分钟 +201001525,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,将已炸好的梅头猪肉粒与酱汁拌匀即可。,12.0,拌,"锅,锅铲",30秒 +201001526,Recipe,商芝肉,商芝肉,,Recipe,,荤菜,5.0,西北菜,约30分钟(含煮肉、切配、处理商芝),约2小时(蒸制2小时,炸制与调味约10分钟),2人,商芝可替换为其他蕨类蔬菜,dishes\meat_dish\商芝肉.md,,,,,,,, +201001527,Ingredient,带皮猪五花肉,带皮猪五花肉,,Ingredient,,蛋白质,,,,,,,,500,克,True,,,,, +201001528,Ingredient,商芝,商芝,,Ingredient,,蔬菜,,,,,,,,50,克,True,,,,, +201001529,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,10,克,False,,,,, +201001530,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,2,克,False,,,,, +201001531,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,个,False,,,,, +201001532,Ingredient,蜂蜜,蜂蜜,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201001533,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001534,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,克,False,,,,, +201001535,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,1.5,克,False,,,,, +201001536,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001537,Ingredient,摊鸡蛋皮,摊鸡蛋皮,,Ingredient,,蛋白质,,,,,,,,15,克,False,,,,, +201001538,Ingredient,精盐,精盐,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201001539,Ingredient,鸡汤,鸡汤,,Ingredient,,其他,,,,,,,,200,克,False,,,,, +201001540,Ingredient,芝麻油,芝麻油,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001541,Ingredient,熟猪油,熟猪油,,Ingredient,,调料,,,,,,,,2000,克,False,,,,, +201001542,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将肉刮洗干净,入煮锅煮至六成熟(变色为白),捞出趁热用蜂蜜、醋涂抹肉皮。,1.0,"煮,涂抹","煮锅,刷子或勺子",约10分钟 +201001543,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,炒锅内放入熟猪油,用旺火烧至八成熟(约200度,油表有大量青烟,油状平静),将肉块皮朝下投入,炸至呈金红色时,捞入凉肉煮锅中泡软。,2.0,炸,"炒锅,漏勺",约2-3分钟 +201001544,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将肉放在案板上,切成10 cm长、0.6 cm厚的片,仍然皮朝下,整齐装入蒸碗内。,3.0,切,"刀,案板,蒸碗",约5分钟 +201001545,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将5克大葱切成2.4 cm长的段,5克切成2.4 cm长的斜形片;姜去皮洗净,1.5克切成片,5克切成末;摊的鸡蛋皮切成2.4 cm长的等腰三角形片。,4.0,切,"刀,案板",约5分钟 +201001546,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,商芝入沸水锅中煮软捞出,去除老茎、杂质,淘洗干净,切成3 cm长的段,放入碗中,加酱油5克、精盐1克、熟猪油10克拌匀,盖在肉片上。,5.0,"煮,拌","煮锅,碗,筷子",约5分钟 +201001547,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,另将鸡汤100克放入一小碗中,加酱油5克、精盐0.5克、料酒15克搅匀,浇入蒸碗,再放入姜片、葱段、八角,上笼用旺火蒸约半小时后,转用小火继续蒸约一小时三十分钟。,6.0,蒸,"蒸锅,小碗",2小时 +201001548,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,熟烂后取出,拣去姜、葱、八角,倒、过滤原汁,将肉扣入汤盘。,7.0,"过滤,扣盘","滤网,汤盘",约2分钟 +201001549,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,炒锅内放入鸡汤100克,加入原汁,用旺火烧沸,下入姜末、葱片、味精后搅匀,投入摊鸡蛋皮,淋芝麻油,浇入汤盘即成。,8.0,"烧,淋","炒锅,汤勺",约1分钟 +201001550,Recipe,孜然牛肉,孜然牛肉,,Recipe,,荤菜,3.0,西北菜,30分钟(含腌肉),约5分钟,1人,"孜然粒捣碎更入味,腌制牛肉30分钟,大火快炒",dishes\meat_dish\孜然牛肉.md,,,,,,,, +201001551,Ingredient,牛柳/牛肩肉,牛柳/牛肩肉,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201001552,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,颗,True,,,,, +201001553,Ingredient,孜然粒,孜然粒,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201001554,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,3,颗,False,,,,, +201001555,Ingredient,生抽酱油,生抽酱油,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201001556,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,10,g,False,,,,, +201001557,Ingredient,油,油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201001558,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201001559,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201001560,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将小米椒切碎,和孜然粒一起放入捣药罐捣碎成颗粒,更入味;时间紧张可跳过,1.0,"切,捣碎","刀,捣药罐", +201001561,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,青椒切头去籽(喜欢辣可保留),切成丝;葱切段,2.0,切,"刀,案板", +201001562,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,牛肉提前解冻,过水洗净,晾干或用厨房纸吸干,顺纹理切片,3.0,"切,清洗","刀,案板,厨房纸", +201001563,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,腌肉:加入生抽、淀粉、油,搅拌均匀,静置30分钟,4.0,"腌制,搅拌","盆,筷子",30分钟 +201001564,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅下油,放入葱段爆香,加入腌好的牛肉煸炒,5.0,炒,"炒锅,锅铲", +201001565,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,牛肉变色后均匀撒入孜然辣椒颗粒,继续炒熟,6.0,炒,锅铲, +201001566,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入青椒丝,断生后加盐调味,7.0,炒,锅铲, +201001567,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,大火炒1分钟后关火,再翻炒30秒保证受热均匀即可出锅,8.0,炒,锅铲,1分30秒 +201001568,Recipe,小炒肉,小炒肉,,Recipe,,荤菜,3.0,湘菜,30分钟(腌制)+ 10分钟(切配),5-7分钟,1人份,,dishes\meat_dish\小炒肉.md,,,,,,,, +201001569,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201001570,Ingredient,朝天椒,朝天椒,,Ingredient,,蔬菜,,,,,,,,4,条,False,,,,, +201001571,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,4,颗,False,,,,, +201001572,Ingredient,豆豉,豆豉,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001573,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001574,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201001575,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,10,g,False,,,,, +201001576,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1-2,g,False,,,,, +201001577,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,0.5-1,根,False,,,,, +201001578,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,2,瓣,False,,,,, +201001579,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201001580,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,五花肉切片,1.0,切,"刀,案板",约2分钟 +201001581,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,把肉放入器皿内,加入淀粉、老抽、盐搅拌腌制半小时,2.0,"腌制,搅拌","盆,筷子",30分钟 +201001582,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,葱切段,3.0,切,"刀,案板",约30秒 +201001583,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,小米椒、朝天椒斜刀切好,4.0,切,"刀,案板",约1分钟 +201001584,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅、倒油,5.0,"加热,倒","炒锅,锅铲",约30秒 +201001585,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,油热后加入五花肉煸炒,炒至变色后盛出来,6.0,炒,"炒锅,锅铲",约1-2分钟 +201001586,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,向锅中加蒜,煸出香味,加入豆豉,翻炒均匀,7.0,炒,"炒锅,锅铲",约30秒 +201001587,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入豆瓣酱翻炒均匀,8.0,炒,"炒锅,锅铲",约30秒 +201001588,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入炒好的五花肉继续翻炒均匀,9.0,炒,"炒锅,锅铲",约30秒 +201001589,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入小米椒、朝天椒、葱段翻炒40秒,10.0,炒,"炒锅,锅铲",40秒 +201001590,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,出锅,11.0,出锅,锅铲,约5秒 +201001591,Recipe,小米辣炒肉,小米辣炒肉,,Recipe,,荤菜,3.0,川菜,约10分钟,约5分钟,1人份,"可根据口味加减小米辣和豆瓣酱,可加老抽增香",dishes\meat_dish\小米辣炒肉.md,,,,,,,, +201001592,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,20,个,True,,,,, +201001593,Ingredient,花生油,花生油,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201001594,Ingredient,五花肉/瘦肉,五花肉/瘦肉,,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201001595,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1-2,g,False,,,,, +201001596,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201001597,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201001598,Ingredient,姜蒜,姜蒜,,Ingredient,,蔬菜,,,,,,,,50,g,False,,,,, +201001599,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001600,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001601,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201001602,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将小米辣洗净,斜刀切大一点,1.0,切,"刀,案板",约2分钟 +201001603,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,肉切丝或切片,倒入生抽、蚝油、盐腌制5分钟,2.0,"切,腌制","刀,案板,盆",5分钟 +201001604,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅倒油,先把肉炒好盛起,3.0,炒,"炒锅,锅铲",约1分钟 +201001605,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,姜蒜爆香,倒入豆瓣酱翻炒,加入切好的小米辣,再倒入瘦肉,翻炒后加生抽、鸡精、盐、糖炒匀,4.0,"爆香,炒,翻炒","炒锅,锅铲",约2分钟 +201001606,Recipe,小酥肉,小酥肉,,Recipe,,荤菜,3.0,川菜,腌制30分钟+静置30分钟,初炸3-5分钟+复炸2-3分钟,约3-4人份,"红薯淀粉需揉散避免炸锅,可一次初炸后冷藏保存,食用前复炸口感不变",dishes\meat_dish\小酥肉.md,,,,,,,, +201001607,Ingredient,去皮猪肉,去皮猪肉,,Ingredient,,蛋白质,,,,,,,,500,克,True,,,,, +201001608,Ingredient,植物油,植物油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201001609,Ingredient,老姜,老姜,,Ingredient,,蔬菜,,,,,,,,20,克,False,,,,, +201001610,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,15,克,False,,,,, +201001611,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,克,False,,,,, +201001612,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,4,克,False,,,,, +201001613,Ingredient,十三香,十三香,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201001614,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201001615,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001616,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001617,Ingredient,花椒碎,花椒碎,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201001618,Ingredient,花椒粒,花椒粒,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201001619,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,8,克,False,,,,, +201001620,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,False,,,,, +201001621,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,30,克,False,,,,, +201001622,Ingredient,红薯淀粉,红薯淀粉,,Ingredient,,淀粉类,,,,,,,,120,克,False,,,,, +201001623,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,80,克,False,,,,, +201001624,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,老姜切丝,小葱不用切,加入料酒和清水,用手捏揉5分钟制成葱姜水。,1.0,"切,揉","刀,盆",5分钟 +201001625,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,猪肉去皮洗净,切成长8-10厘米、厚1.5厘米的肉条。,2.0,切,"刀,案板",5分钟 +201001626,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,肉条中加入盐、十三香、胡椒粉、味精、鸡精、花椒碎、花椒粒、生抽和葱姜水,抓匀揉制10分钟至肉吸收水分并粘手,封保鲜膜冷藏静置30分钟。,3.0,"腌制,揉","盆,保鲜膜,冰箱",40分钟 +201001627,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将面粉、红薯淀粉和鸡蛋清加入腌好的肉中,揉制15分钟至均匀无干粉。,4.0,揉,盆,15分钟 +201001628,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中倒油,油面高度3厘米以上,大火加热至150°C后转小火,将肉条逐条下锅初炸3-5分钟至微黄定型,捞出沥油。,5.0,炸,"锅,筷子,锅铲,漏勺",3-5分钟 +201001629,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,油温升至180°C,放入初炸好的肉条复炸至金黄色,捞出沥油即可。,6.0,炸,"锅,漏勺",2-3分钟 +201001630,Recipe,尖椒炒牛肉,尖椒炒牛肉,,Recipe,,荤菜,3.0,,30-40分钟(腌制)+ 约10分钟(切配),约5分钟(炒制),1人,"腌制时加小苏打可使牛肉更嫩(500g牛肉:3g小苏打),姜片可用料酒代替(3g/人)",dishes\meat_dish\尖椒炒牛肉.md,,,,,,,, +201001631,Ingredient,牛肉,牛肉,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201001632,Ingredient,尖椒,尖椒,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201001633,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201001634,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201001635,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,1,瓣,False,,,,, +201001636,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,9,ml,False,,,,, +201001637,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201001638,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,1.5,g,False,,,,, +201001639,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,蒜剁成蒜泥,葱切段,姜切成姜片,尖椒切成段。,1.0,切,"刀,案板",约5分钟 +201001640,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,牛肉放入碗中,加姜、盐、酱油、糖进行腌制30-40分钟;腌制完姜可以去掉。,2.0,腌制,碗,30-40分钟 +201001641,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,冷油下锅,待油变热至偶有气泡,加入蒜泥。,3.0,炒,"炒锅,锅铲",约30秒 +201001642,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,蒜泥变金黄后加入尖椒,待尖椒表皮微皱。,4.0,炒,锅铲,约1分钟 +201001643,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入腌制好的牛肉翻炒,翻炒变熟之前加入葱,继续翻炒至牛肉变熟,关火出锅。,5.0,炒,锅铲,约2-3分钟 +201001644,Recipe,山西过油肉,山西过油肉,,Recipe,,荤菜,4.0,山西菜,20分钟(含15分钟腌制),10分钟,1人,"炸肉片表面微焦即可,起锅前可打薄水淀粉增口感",dishes\meat_dish\山西过油肉.md,,,,,,,, +201001645,Ingredient,猪里脊,猪里脊,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201001646,Ingredient,蒜苔,蒜苔,,Ingredient,,蔬菜,,,,,,,,6,根,True,,,,, +201001647,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,300,ml,False,,,,, +201001648,Ingredient,葱姜蒜,葱姜蒜,,Ingredient,,调料,,,,,,,,50,g,False,,,,, +201001649,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,ml,False,,,,, +201001650,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001651,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201001652,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,10,g,False,,,,, +201001653,Ingredient,木耳,木耳,,Ingredient,,蔬菜,,,,,,,,20,g,True,,,,, +201001654,Ingredient,葱头,葱头,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201001655,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201001656,Ingredient,陈醋,陈醋,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201001657,Ingredient,花椒粉,花椒粉,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201001658,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201001659,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,木耳提前泡发好,如果着急可以用热水泡发。,1.0,泡发,碗,10-15分钟 +201001660,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,猪里脊切片放入碗中,加20ml生抽、料酒、花椒粉,打入一个鸡蛋,搅拌均匀后加入淀粉拌匀,再倒入300ml食用油封浆,腌制15分钟。,2.0,"切,腌制,搅拌","刀,案板,碗,筷子",15分钟 +201001661,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,蒜苔切段约3cm,葱头切菱形块备用。,3.0,切,"刀,案板",2分钟 +201001662,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,起锅烧油,油量稍多,油温五成热时下入腌制好的肉片,将肉片打散,炸至表面微焦后捞出控油备用。,4.0,炸,"炒锅,锅铲,漏勺",2-3分钟 +201001663,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将锅中多余油倒出,留约10ml油炒菜,油温七成热。,5.0,"倒油,加热",炒锅,30秒 +201001664,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,下入葱姜蒜爆香,先下蒜苔炒至断生,再下入木耳和葱头,加入生抽、花椒粉翻炒几下,随后倒入炸好的肉片继续翻炒。,6.0,"炒,爆香","炒锅,锅铲",2-3分钟 +201001665,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入10g盐,起锅前淋入10ml陈醋和适量鸡精,快速翻炒均匀后起锅装盘。,7.0,"炒,调味",锅铲,30秒 +201001666,Recipe,带把肘子,带把肘子,,Recipe,,荤菜,5.0,西北菜,约15分钟(清洗、剔骨、砸骨、抹酱油等),约3.5小时(煮七成熟+蒸3小时),3人,"七成熟判断需经验,蒸时及时补水防干锅",dishes\meat_dish\带把肘子.md,,,,,,,, +201001667,Ingredient,带脚、爪猪前肘,带脚、爪猪前肘,,Ingredient,,蛋白质,,,,,,,,1250,克,True,,,,, +201001668,Ingredient,红豆腐乳,红豆腐乳,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001669,Ingredient,甜面酱,甜面酱,,Ingredient,,调料,,,,,,,,150,克,False,,,,, +201001670,Ingredient,精盐,精盐,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201001671,Ingredient,红酱油,红酱油,,Ingredient,,调料,,,,,,,,35,克,False,,,,, +201001672,Ingredient,白酱油,白酱油,,Ingredient,,调料,,,,,,,,25,克,False,,,,, +201001673,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,25,克,False,,,,, +201001674,Ingredient,蒜片,蒜片,,Ingredient,,蔬菜,,,,,,,,50,克,False,,,,, +201001675,Ingredient,姜末,姜末,,Ingredient,,蔬菜,,,,,,,,10,克,False,,,,, +201001676,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,个,False,,,,, +201001677,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001678,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,200,克,False,,,,, +201001679,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将肘子刮洗干净,肘头朝外、肘把(脚爪)朝里、肘皮朝下放在案板上。,1.0,清洗,案板, +201001680,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用刀在正中由肘头向肘把沿着腿骨将皮剖开,剔去腿骨两边的肉(三面离肉),底部骨与肉相连,使骨头露出,然后将两节腿骨由中间用刀背(还是用斧头吧)砸断。,2.0,"切,剔骨,砸骨","刀,小斧头,案板", +201001681,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,肘子放入煮锅煮至七成熟捞出(外观正常,内部淡红色),用干净抹布擦干水,趁热用红酱油涂抹肉皮。,3.0,"煮,涂抹","煮锅,抹布",约30分钟 +201001682,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,取蒸锅一个,锅底放入八角、桂皮,先将肘把的关节处用手掰断,不伤外皮,再将肘皮朝下装进蒸锅内,装锅时根据肘子体型,将肘把贴住锅边窝着装进锅内,成为圆形。,4.0,"掰断,装锅",蒸锅, +201001683,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,撒入精盐,用消过毒的干净纱布盖在肉上,再将甜面酱(50克)、葱(75克)、红豆腐乳、红酱油、白酱油、姜、蒜等在纱布上抹开,用旺火蒸大约三小时(以蒸烂为准)。,5.0,"撒,抹,蒸","蒸锅,纱布",3小时 +201001684,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,蒸完取出,揭去纱布,扣入盘中,拣去八角,上桌时另带葱段和甜面酱小碟(或将甜面酱抹到肘面上,另带葱段小碟亦可)。,6.0,"取出,装盘",盘, +201001685,Recipe,意式烤鸡,意式烤鸡,,Recipe,"[{'term': '意式baked鸡', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '意式烘烤鸡', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '意式roasted鸡', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,意大利菜,10分钟,30-40分钟,按人数计算,"可淋蜂蜜或烤肉酱增味,烤箱180℃预热,鸡肉必须全熟",dishes\meat_dish\意式烤鸡.md,,,,,,,, +201001686,Ingredient,鸡腿肉,鸡腿肉,,Ingredient,,蛋白质,,,,,,,,1.5,个/人,True,,,,, +201001687,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g/人,False,,,,, +201001688,Ingredient,黑胡椒,黑胡椒,,Ingredient,,调料,,,,,,,,0.5,g/人,False,,,,, +201001689,Ingredient,橄榄油,橄榄油,,Ingredient,,调料,,,,,,,,5,ml/人,False,,,,, +201001690,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,1,瓣/人,False,,,,, +201001691,Ingredient,柠檬汁,柠檬汁,,Ingredient,,调料,,,,,,,,5,ml/人,False,,,,, +201001692,Ingredient,欧芹,欧芹,,Ingredient,,蔬菜,,,,,,,,1,根/人,False,,,,, +201001693,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡腿肉涂上盐、黑胡椒、橄榄油和蒜末,1.0,腌制,盆,5分钟 +201001694,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,放入预热至180度的烤箱中,烤30-40分钟或至熟,2.0,烤,烤箱,30-40分钟 +201001695,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,欧芹切成碎末备用,3.0,切,"刀,案板",2分钟 +201001696,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,柠檬挤出汁备用,4.0,挤汁,手动榨汁器或手,1分钟 +201001697,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,烤好的鸡肉取出,淋上柠檬汁,撒上欧芹碎即可,5.0,"淋,撒",勺子,2分钟 +201001698,Recipe,杀猪菜,杀猪菜,,Recipe,,荤菜,4.0,东北菜,约15分钟(焯水、切配、扎孔等),约50分钟(焯水+炒香+高压40分钟+焖2分钟),2-3人,"血肠需低温慢煮防爆裂,酸菜先炒去酸增香,排骨先焯水去腥,蘸料可自定义",dishes\meat_dish\杀猪菜.md,,,,,,,, +201001699,Ingredient,血肠,血肠,,Ingredient,,蛋白质,,,,,,,,200,克,True,,,,, +201001700,Ingredient,酸菜,酸菜,,Ingredient,,蔬菜,,,,,,,,500,克,True,,,,, +201001701,Ingredient,排骨,排骨,,Ingredient,,蛋白质,,,,,,,,400,克,True,,,,, +201001702,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,克,False,,,,, +201001703,Ingredient,蒜瓣,蒜瓣,,Ingredient,,调料,,,,,,,,5,个,False,,,,, +201001704,Ingredient,姜粉,姜粉,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001705,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,5,个,False,,,,, +201001706,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201001707,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,个,False,,,,, +201001708,Ingredient,葱结,葱结,,Ingredient,,调料,,,,,,,,1,个,False,,,,, +201001709,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001710,Ingredient,菜籽油,菜籽油,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001711,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001712,Ingredient,辣椒油,辣椒油,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001713,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,克,False,,,,, +201001714,Ingredient,蒜蓉,蒜蓉,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001715,Ingredient,枸杞,枸杞,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201001716,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,血肠用牙签多扎一些小孔,然后放水中小火煮十分钟,不要让水烧开,保持80度,否则血肠非常容易爆开。,1.0,煮,"牙签,锅",10分钟 +201001717,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,煮好的血肠切块备用。,2.0,切,"刀,案板",约2分钟 +201001718,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,排骨放料酒焯水,控干水分备用。,3.0,焯水,"锅,漏勺",约5分钟 +201001719,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅内放入菜籽油,放蒜瓣、干辣椒、姜粉炒香。,4.0,炒,"炒锅,锅铲",约30秒 +201001720,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入排骨翻炒至表面金黄。,5.0,炒,"炒锅,锅铲",约3分钟 +201001721,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,酸菜洗净拧干水分,放入锅中,加入香油翻炒,香油可以更好地去除酸味而且让酸菜更香,大火翻炒二分钟。,6.0,炒,"炒锅,锅铲",2分钟 +201001722,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入600毫升热水。,7.0,加汤,量杯,约10秒 +201001723,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,转入电压力锅,加香叶、八角、葱结、盐。,8.0,"转移,调味",电压力锅,约30秒 +201001724,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,浓香模式压40分钟。,9.0,高压炖煮,电压力锅,40分钟 +201001725,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,到时间后放气开盖,加入血肠和枸杞,盖上锅盖焖二分钟即可,血肠是熟的,不需再加热。,10.0,焖,电压力锅,2分钟 +201001726,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,倒入盆中,按照上表调制蘸料,即可开吃。,11.0,"装盘,蘸食","盆,小碗",约1分钟 +201001727,Recipe,椒盐排条,椒盐排条,,Recipe,,荤菜,4.0,本帮菜,20分钟(腌制)+ 切配时间,约10分钟(两次炸制),1-2人,"可用面包糠替代炸糊但口感不同,炸糊可复用于鸡腿、鱼",dishes\meat_dish\椒盐排条.md,,,,,,,, +201001728,Ingredient,大排,大排,,Ingredient,,蛋白质,,,,,,,,360,克,True,,,,, +201001729,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201001730,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201001731,Ingredient,椒盐粉,椒盐粉,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001732,Ingredient,葱姜水,葱姜水,,Ingredient,,调料,,,,,,,,100,毫升,False,,,,, +201001733,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,80,克,False,,,,, +201001734,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,80,克,False,,,,, +201001735,Ingredient,吉士粉,吉士粉,,Ingredient,,调料,,,,,,,,2.5,克,False,,,,, +201001736,Ingredient,水,水,,Ingredient,,其他,,,,,,,,10,克,False,,,,, +201001737,Ingredient,油,油,,Ingredient,,其他,,,,,,,,10,克,False,,,,, +201001738,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,大排洗干净,剔骨,用刀面拍松,切成厚片,再改成粗条。,1.0,切,"刀,案板", +201001739,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入椒盐粉搅匀,待出胶质后分次加入葱姜水,放入冰箱腌制20分钟。,2.0,腌制,"盆,冰箱",20分钟 +201001740,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,制作炸糊:放入80 g面粉、20 g淀粉(剩余60 g淀粉备用)、2-3 g吉士粉、1 g盐。,3.0,混合,盆, +201001741,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,打入一个鸡蛋,搅拌后分次加入100 g水,再加10 g油,反复搅拌至炸糊略粘稠。,4.0,搅拌,"盆,筷子", +201001742,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,取出剩余60 g淀粉,将排条先裹一层淀粉,再裹上面糊。,5.0,裹粉,盆, +201001743,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锅中加油至没过食材,加热至150-160 ℃,下入排条炸至浅金黄后捞出。,6.0,炸,"锅,筷子", +201001744,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,待油温再次升至150-160 ℃,复炸至金黄色后捞出。,7.0,炸,"锅,筷子", +201001745,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,撒上椒盐粉,搅拌均匀后出锅。,8.0,拌,锅铲, +201001746,Recipe,水煮肉片,水煮肉片,,Recipe,,荤菜,5.0,川菜,20-30分钟,15-20分钟,2-3人,"肉片需先清洗去血水再腌制,肉片搅拌需朝一个方向,鸡蛋清+淀粉形成润滑膜保证滑嫩,刀口辣椒可简化用干辣椒段+青花椒,蔬菜底可替换为蘑菇、白菜、油麦菜,同样做法适用于水煮牛肉",dishes\meat_dish\水煮肉片.md,,,,,,,, +201001747,Ingredient,猪里脊肉,猪里脊肉,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201001748,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201001749,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201001750,Ingredient,生抽酱油,生抽酱油,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201001751,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,g,False,,,,, +201001752,Ingredient,鸡蛋清,鸡蛋清,,Ingredient,,蛋白质,,,,,,,,1,个,False,,,,, +201001753,Ingredient,土豆淀粉,土豆淀粉,,Ingredient,,淀粉类,,,,,,,,7,g,False,,,,, +201001754,Ingredient,植物油,植物油,,Ingredient,,其他,,,,,,,,280,g,False,,,,, +201001755,Ingredient,菜籽油,菜籽油,,Ingredient,,其他,,,,,,,,200,g,False,,,,, +201001756,Ingredient,绿豆芽,绿豆芽,,Ingredient,,蔬菜,,,,,,,,100,g,False,,,,, +201001757,Ingredient,凤尾,凤尾,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201001758,Ingredient,芹菜,芹菜,,Ingredient,,蔬菜,,,,,,,,3,根,False,,,,, +201001759,Ingredient,蒜苗,蒜苗,,Ingredient,,蔬菜,,,,,,,,2,根,False,,,,, +201001760,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,20,g,False,,,,, +201001761,Ingredient,生姜,生姜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201001762,Ingredient,红泡椒,红泡椒,,Ingredient,,蔬菜,,,,,,,,20,g,False,,,,, +201001763,Ingredient,青花椒,青花椒,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201001764,Ingredient,小米辣干辣椒,小米辣干辣椒,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201001765,Ingredient,红油豆瓣,红油豆瓣,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201001766,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,1.5,g,False,,,,, +201001767,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201001768,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,根,False,,,,, +201001769,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,里脊肉改刀成小块,再切成2毫米薄片,放入碗中,加入清水清洗两遍去除血水和杂质,捞出挤干水分备用。,1.0,"切,清洗","刀,案板,碗",5分钟 +201001770,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,碗中加入食用盐1.5g、胡椒粉1g、生抽酱油5g、料酒3g,朝一个方向搅拌2分钟使其入味。,2.0,"腌制,搅拌","碗,筷子",2分钟 +201001771,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,另取一碗加入鸡蛋清和土豆淀粉7g,一个方向搅拌均匀后倒入肉中,再次搅拌至肉表面形成润滑膜,最后加入30g植物油轻轻搅拌防止粘连。,3.0,"搅拌,腌制","碗,筷子",3分钟 +201001772,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,绿豆芽100g、凤尾1根改刀成小条、芹菜3根切段、蒜苗2根拍散切段备用。,4.0,切,"刀,案板",3分钟 +201001773,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,大蒜20g、生姜10g、红泡椒20g分别剁碎;小米辣干辣椒15g、青花椒3g入油锅小火炒香后倒出剁细成刀口辣椒。,5.0,"剁,炒","刀,案板,炒锅",3分钟 +201001774,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锅烧热,放入100g植物油烧至6成热,加入2g青花椒和干辣椒爆香,下配菜加盐1g炒至断生,盛入碗中垫底。,6.0,炒,"炒锅,锅铲",2分钟 +201001775,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,锅洗净,加入150g植物油烧至6成热,爆香姜蒜红泡椒,加入红油豆瓣10g小火炒出红油。,7.0,炒,"炒锅,锅铲",2分钟 +201001776,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入800ml清水大火烧开,转小火调味:盐2.5g、鸡精1.5g、白砂糖1g、胡椒粉1g、水淀粉5g收浓汤汁。,8.0,"煮,调味","炒锅,锅铲",3分钟 +201001777,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,汤汁开后转小火,将肉片依次下锅,再转中火烫熟,轻推避免粘连,熟后连汤倒入配菜碗中。,9.0,煮,锅铲,2分钟 +201001778,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,碗中均匀撒上刀口辣椒、蒜蓉和葱花。,10.0,撒,手,30秒 +201001779,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,锅洗净,加入200g菜籽油烧至7成热,一次性泼在碗中肉片上即可。,11.0,泼油,"炒锅,锅铲",1分钟 +201001780,Recipe,洋葱炒猪肉,洋葱炒猪肉,,Recipe,,荤菜,3.0,,5分钟,10分钟,1人份,猪肉可选猪肩肉片或肉丝,dishes\meat_dish\洋葱炒猪肉.md,,,,,,,, +201001781,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,1,颗,True,,,,, +201001782,Ingredient,猪肉,猪肉,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201001783,Ingredient,蒜头,蒜头,,Ingredient,,蔬菜,,,,,,,,3,瓣,False,,,,, +201001784,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201001785,Ingredient,黑胡椒,黑胡椒,,Ingredient,,调料,,,,,,,,1.25,g,False,,,,, +201001786,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201001787,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201001788,Ingredient,麻油,麻油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201001789,Ingredient,番茄酱,番茄酱,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201001790,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201001791,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,洋葱切片,猪肉,蒜头拍碎,以及混合上述调味料备用,1.0,"切,拍碎,混合","刀,案板,盆",2-3分钟 +201001792,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,炒锅内倒入1大匙食用油(等待10秒让油温升高),倒入猪肉,2.0,炒,"炒锅,锅铲",10秒预热,2分钟炒肉 +201001793,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,炒至变色后下蒜头炒香盛起备用,3.0,炒,锅铲,30秒 +201001794,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,原锅下洋葱翻炒3~4分钟后加入调味料炒匀,4.0,炒,锅铲,3-4分钟 +201001795,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,下刚盛起备用的猪肉翻炒至猪肉熟后,5.0,炒,锅铲,1-2分钟 +201001796,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,待猪肉熟后再翻炒1、2分钟即可起锅,6.0,炒,锅铲,1-2分钟 +201001797,Recipe,烤鸡翅,烤鸡翅,,Recipe,"[{'term': 'roasted鸡翅', 'language': 'en', 'language_code': 'en-US'}, {'term': '烘烤鸡翅', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'baked鸡翅', 'language': 'en', 'language_code': 'en-US'}]",荤菜,3.0,,30-40分钟,30-40分钟,1人,"腌制时可加蜂蜜、姜蒜粉、五香粉提味,烤盘垫锡纸便于清洁",dishes\meat_dish\烤鸡翅.md,,,,,,,, +201001798,Ingredient,鸡翅中,鸡翅中,,Ingredient,,蛋白质,,,,,,,,3-4,个,True,,,,, +201001799,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201001800,Ingredient,黑胡椒粉,黑胡椒粉,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201001801,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,3,ml,False,,,,, +201001802,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,ml,False,,,,, +201001803,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡翅放入碗中,加盐、黑胡椒粉、酱油、料酒进行腌制,1.0,腌制,碗,30-40分钟 +201001804,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将烤箱预热至200℃,2.0,预热,烤箱, +201001805,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将腌制好的鸡翅均匀地放在烤盘上,3.0,摆盘,烤盘, +201001806,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将烤盘放入烤箱中层,烤15-20分钟,4.0,烤,"烤箱,烤盘",15-20分钟 +201001807,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,取出烤盘,将鸡翅翻面,再烤15-20分钟,直到熟透,5.0,"翻面,烤","烤箱,烤盘",15-20分钟 +201001808,Recipe,猪肉烩酸菜,猪肉烩酸菜,,Recipe,,荤菜,5.0,东北菜,约30分钟,1.5-2小时,3-5人,"大火收汤时注意防糊锅,最后加盐可少量多次品尝调整,酸菜风味独特",dishes\meat_dish\猪肉烩酸菜.md,,,,,,,, +201001809,Ingredient,猪排骨或五花肉,猪排骨或五花肉,,Ingredient,,蛋白质,,,,,,,,1500,克,True,,,,, +201001810,Ingredient,东北酸菜,东北酸菜,,Ingredient,,蔬菜,,,,,,,,1000,克,True,,,,, +201001811,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,根,False,,,,, +201001812,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,100,克,False,,,,, +201001813,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,4,瓣,False,,,,, +201001814,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001815,Ingredient,生抽酱油,生抽酱油,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201001816,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201001817,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201001818,Ingredient,大料,大料,,Ingredient,,调料,,,,,,,,2,颗,False,,,,, +201001819,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,大葱切段;生姜50克切段、50克切末;大蒜切末,备用。,1.0,切,"刀,案板",约5分钟 +201001820,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,全部酸菜切丝,用水冲洗2~3遍备用。冲洗次数取决于个人口味,喜欢酸味可冲洗2遍,怕酸可冲洗3~4遍,不能不冲洗,否则会过酸。,2.0,"切,冲洗","刀,案板,盆",约5分钟 +201001821,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,排骨和五花肉入锅,倒入冷水淹没,放入全部葱段、50克生姜段和20毫升料酒。大火煮开后等待5分钟,关火捞出排骨和五花肉,用冷水冲洗掉浮沫,备用。,3.0,"焯水,冲洗","锅,漏勺",约10分钟 +201001822,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,煮好的五花肉切片或切块,备用。,4.0,切,"刀,案板",约2分钟 +201001823,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将之前的锅洗净并擦干,防止加油时油崩。,5.0,清洗,锅,约2分钟 +201001824,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锅中加油,开中火,放入姜蒜末爆香,加入五花肉和排骨煎至金黄,倒入10克五香粉和15克生抽酱油,用铲子翻动1~2分钟。,6.0,"煎,炒","锅,锅铲",约5分钟 +201001825,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将冲洗好的酸菜丝加入锅中,翻炒3分钟。,7.0,炒,"锅,锅铲",3分钟 +201001826,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入纯净水至刚好没过食材,加入2颗大料,转大火至水沸腾后转中火,盖锅盖焖煮。,8.0,焖煮,"锅,锅盖",1.5-2小时 +201001827,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,等待1.5~2小时,直至五花肉软烂(可用筷子轻松扎穿)。,9.0,焖煮,"锅,筷子",1.5-2小时 +201001828,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,掀开锅盖,开大火收汤,翻动锅中食材直至剩余水分仅覆盖锅底,转小火准备调味。,10.0,收汁,"锅,锅铲",约5分钟 +201001829,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,调味:加入10克食用盐,搅拌均匀。,11.0,调味,"锅,锅铲",约1分钟 +201001830,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,关火,出锅。,12.0,出锅,锅铲,约1分钟 +201001831,Recipe,甜辣烤全翅,甜辣烤全翅,,Recipe,"[{'term': '甜辣烘烤全翅', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜辣baked全翅', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜辣roasted全翅', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,,15分钟,50分钟,1人,"微辣口感,可增辣度,微焦外观,腌制时间60-180分钟,甜椒粉增色泽,锡纸盘防烫",dishes\meat_dish\甜辣烤全翅.md,,,,,,,, +201001832,Ingredient,鸡全翅,鸡全翅,,Ingredient,,蛋白质,,,,,,,,4,个,True,,,,, +201001833,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,45,ml,False,,,,, +201001834,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201001835,Ingredient,蒜粉,蒜粉,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001836,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201001837,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001838,Ingredient,甜椒粉,甜椒粉,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001839,Ingredient,辣椒粉,辣椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201001840,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201001841,Ingredient,水,水,,Ingredient,,其他,,,,,,,,20,ml,False,,,,, +201001842,Ingredient,油,油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201001843,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将4个新鲜鸡全翅取出,在翅中两根骨头之间用刀划开表皮,正反面各一刀,1.0,切,刀, +201001844,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将4个鸡全翅放入碗中,加入生抽45ml、老抽15ml、蒜粉10g、胡椒粉5g、糖10g、甜椒粉10g、辣椒粉5g、蚝油15ml、水20ml以及油10ml,2.0,腌制,碗, +201001845,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,用勺子将酱汁均匀地抹在鸡全翅上,尤其是翅中的刀口处,3.0,腌制,勺子,3分钟 +201001846,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,用保鲜膜盖住碗,放入冰箱冷藏格静置120分钟,4.0,腌制,保鲜膜,120分钟 +201001847,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,取出鸡全翅,锡纸盘中放入鸡全翅4个,将碗中残余酱料均匀倒在鸡全翅上,5.0,准备,锡纸盘, +201001848,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锡纸盘放入空气炸锅的烤篮上,用200摄氏度烤25分钟,6.0,烤,空气炸锅,25分钟 +201001849,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,打开空气炸锅,小心取出锡纸盘,将鸡全翅翻面,7.0,翻面,夹子, +201001850,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,继续200摄氏度烤25分钟,8.0,烤,空气炸锅,25分钟 +201001851,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,取出即可食用,9.0,取出,夹子, +201001852,Recipe,番茄红酱,番茄红酱,,Recipe,,荤菜,4.0,,约10分钟,约40分钟,1份,"考虑各个品牌的番茄酱内含盐量不同,建议在炒牛肉时少放盐,煮的时候尝一下再调味,煮酱料期间请搅动,以免粘锅。如果酱料变粘稠就可以出锅啦!,可将碎牛肉替换成一半碎猪肉一半碎牛肉,牛奶替换成鸡汤或饮用水",dishes\meat_dish\番茄红酱.md,,,,,,,, +201001853,Ingredient,碎牛肉,碎牛肉,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201001854,Ingredient,蒜瓣,蒜瓣,,Ingredient,,调料,,,,,,,,2,个,False,,,,, +201001855,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201001856,Ingredient,芹菜,芹菜,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201001857,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,0.5,个,False,,,,, +201001858,Ingredient,橄榄油,橄榄油,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201001859,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201001860,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001861,Ingredient,黑胡椒粉,黑胡椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201001862,Ingredient,番茄酱,番茄酱,,Ingredient,,调料,,,,,,,,300,g,True,,,,, +201001863,Ingredient,牛奶,牛奶,,Ingredient,,其他,,,,,,,,300,ml,False,,,,, +201001864,Ingredient,干罗勒或百里香,干罗勒或百里香,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201001865,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将胡萝卜、芹菜、洋葱切碎,蒜瓣切片。,1.0,切,"刀,案板",约5分钟 +201001866,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入10ml橄榄油,热油下锅蔬菜,大火翻炒开始略微变色后盛出。,2.0,炒,"炒锅,锅铲",约3分钟 +201001867,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅内加油10ml,加蒜翻炒10秒,加入碎牛肉、糖、盐、胡椒粉和香料将牛肉炒脆(有颗粒感)。,3.0,炒,"炒锅,锅铲",约5分钟 +201001868,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入炒好的蔬菜和番茄酱继续翻炒,搅拌均匀。,4.0,"炒,搅拌","炒锅,锅铲",约2分钟 +201001869,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,分多次缓缓倒入牛奶,中小火煮30分钟,完成。,5.0,煮,"炒锅,锅铲",30分钟 +201001870,Recipe,白菜猪肉炖粉条,白菜猪肉炖粉条,,Recipe,"[{'term': '小白菜猪肉炖粉条', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '白菜猪肉煲粉条', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '白菜猪肉stewed粉条', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '大白菜猪肉炖粉条', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'cabbage猪肉炖粉条', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,东北菜,约10分钟,约30分钟,1人份,"土豆干粉条煮制时间长,可提前处理,最后尝味,淡或未熟可继续加盖煮",dishes\meat_dish\白菜猪肉炖粉条.md,,,,,,,, +201001871,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201001872,Ingredient,大白菜,大白菜,,Ingredient,,蔬菜,,,,,,,,500,g,True,,,,, +201001873,Ingredient,土豆干粉条,土豆干粉条,,Ingredient,,淀粉类,,,,,,,,50,g,True,,,,, +201001874,Ingredient,十三香,十三香,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001875,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201001876,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201001877,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201001878,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201001879,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201001880,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅内烧水,水开后放入干粉条,煮5分钟后同水一起倒出容器中,盖上盖子继续浸泡备用,1.0,煮,"锅,容器",5分钟 +201001881,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,五花肉切3mm的肉片,备用,2.0,切,"刀,案板", +201001882,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大白菜嫩叶与白菜帮子分开切成2份菜片,备用,3.0,切,"刀,案板", +201001883,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,锅内放入10-15ml食用油,等待10秒让油温升高,4.0,加热,炒锅,10秒 +201001884,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入五花肉,保持翻炒至肉变色,5.0,炒,"炒锅,锅铲", +201001885,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入老抽,炒1分钟,给肉上色,6.0,炒,"炒锅,锅铲",1分钟 +201001886,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入白菜帮子,加入食用盐、生抽,炒一分钟(如果粘锅,烹入10ml水),7.0,炒,"炒锅,锅铲",1分钟 +201001887,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加水没过所有食材,加入鸡精、十三香,沸腾后将火调小然后等待20分钟,8.0,炖,"炒锅,锅盖",20分钟 +201001888,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,粉条滤水切成小段放入碗中备用,9.0,切,"刀,碗", +201001889,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入白菜嫩叶,炒匀后将粉条放在菜上方,加盖再煮5分钟,10.0,"炒,炖","炒锅,锅盖",5分钟 +201001890,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,尝味、关火,收汁,11.0,收汁,炒锅, +201001891,Recipe,粉蒸肉,粉蒸肉,,Recipe,"[{'term': '粉清蒸肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '粉steamed肉', 'language': 'en', 'language_code': 'en-US'}]",荤菜,4.0,川菜,30分钟,60-75分钟,3人,"自制米粉技巧,蒸制补水提示",dishes\meat_dish\粉蒸肉.md,,,,,,,, +201001892,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,250,克,True,,,,, +201001893,Ingredient,蒸肉米粉,蒸肉米粉,,Ingredient,,淀粉类,,,,,,,,50,克,False,,,,, +201001894,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,7.5,毫升,False,,,,, +201001895,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,毫升,False,,,,, +201001896,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,7.5,毫升,False,,,,, +201001897,Ingredient,郫县豆瓣酱,郫县豆瓣酱,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001898,Ingredient,姜末,姜末,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001899,Ingredient,蒜末,蒜末,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001900,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,2.5,克,False,,,,, +201001901,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,150,克,False,,,,, +201001902,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,1000,毫升,False,,,,, +201001903,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将五花肉洗净,切成长约5cm、宽约3cm、厚度约0.5cm的肉片,1.0,切,"刀,案板", +201001904,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将姜、蒜切成颗粒直径不大于1mm的细末,2.0,切,"刀,案板", +201001905,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,取一大碗,放入切好的五花肉、生抽、老抽、料酒、郫县豆瓣酱、姜末、蒜末、白砂糖,3.0,混合,碗, +201001906,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,用筷子搅拌均匀后,盖上保鲜膜,室温(20°C-25°C)静置腌制30分钟,4.0,"搅拌,腌制","筷子,保鲜膜,碗",30分钟 +201001907,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,腌制完成后,加入蒸肉米粉,继续翻拌2分钟,确保每片肉都均匀裹粉,5.0,搅拌,"筷子,碗",2分钟 +201001908,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,土豆去皮,切片厚度控制在0.8cm,片面积约为5cm×5cm,重量控制在150g,6.0,"去皮,切","刀,案板", +201001909,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,在直径20cm的深碗底部铺满土豆片,尽量无重叠,7.0,铺底,碗, +201001910,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将拌好粉的五花肉均匀铺在土豆片上,压实,8.0,"铺放,压实",碗, +201001911,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,蒸锅中加入1000ml清水,开火加热至水面持续冒泡(100°C),9.0,加热,蒸锅, +201001912,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将装好食材的碗放入蒸锅内,盖好锅盖,10.0,蒸,蒸锅, +201001913,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,保持中火蒸60分钟(火力保持在可持续沸腾的程度,约600W热功率),11.0,蒸,蒸锅,60分钟 +201001914,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,时间结束后,用筷子插入肉块中央,若能轻松穿透并无明显阻力,则表明蒸熟;若未达到此状态,则继续加热10-15分钟,直至肉质软烂,油脂渗出,12.0,"检查,蒸","筷子,蒸锅",10-15分钟 +201001915,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,取出盛盘,即可食用,13.0,装盘,碗, +201001916,Recipe,糖醋里脊,糖醋里脊,,Recipe,"[{'term': 'sweet and sour里脊', 'language': 'en', 'language_code': 'en-US'}]",荤菜,4.0,"陕菜,豫菜,浙菜,鲁菜,川菜,淮扬菜,粤菜,闽菜",20分钟(腌制),约15分钟(炸制+裹酱),1份,"外焦里嫩,多炸几遍,注意火候",dishes\meat_dish\糖醋里脊.md,,,,,,,, +201001917,Ingredient,里脊肉,里脊肉,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201001918,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001919,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,g,False,,,,, +201001920,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,50,g,False,,,,, +201001921,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,50,g,False,,,,, +201001922,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201001923,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,g,False,,,,, +201001924,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001925,Ingredient,番茄酱,番茄酱,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201001926,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201001927,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001928,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将猪里脊肉先切厚片,用刀背拍松后切成手指粗的条,加入料酒、生抽、蚝油、食盐、白胡椒粉和一个鸡蛋,用手抓匀腌制20分钟以上。,1.0,"切,拍,腌制","刀,案板,盆",20分钟 +201001929,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将番茄酱、10g醋、30g白糖和150ml清水混合,搅拌至糖融化,备用。,2.0,搅拌,"碗,筷子",1-2分钟 +201001930,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,准备一个大碗倒入淀粉,将每根肉条均匀裹满淀粉备用。,3.0,裹粉,碗,3-5分钟 +201001931,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将油温升至160℃,用干筷子测试冒小泡后,下里脊肉炸至表面微黄,全程中火,捞出备用。,4.0,炸,"锅,筷子",3-4分钟 +201001932,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将油温升至200℃,再次倒入里脊肉复炸40秒,使表皮更脆,立即捞出。,5.0,炸,"锅,漏勺",40秒 +201001933,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,另起锅加少量底油,倒入调好的酱汁煮至冒泡,放入炸好的里脊肉快速翻炒,使每根肉条均匀裹上酱汁后关火盛出。,6.0,炒,"锅,锅铲",1-2分钟 +201001934,Recipe,肉饼炖蛋,肉饼炖蛋,,Recipe,"[{'term': '肉饼stewed蛋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '肉饼煲蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,,5分钟,15分钟,2人,小心烫手,dishes\meat_dish\肉饼炖蛋.md,,,,,,,, +201001935,Ingredient,猪肉末,猪肉末,,Ingredient,,蛋白质,,,,,,,,300,克,True,,,,, +201001936,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201001937,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,毫升,False,,,,, +201001938,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201001939,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201001940,Ingredient,芝麻香油,芝麻香油,,Ingredient,,调料,,,,,,,,10-15,毫升,False,,,,, +201001941,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,在碗中加入猪肉末、料酒、生抽、白胡椒粉、鸡蛋和芝麻香油,搅拌均匀。,1.0,搅拌,"碗,筷子或勺子",2分钟 +201001942,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将调好味的猪肉末铺在盘子里,肉末中间用勺子挖一个洞,往洞中打入1个鸡蛋。,2.0,"铺平,挖洞,打入","盘子,勺子",2分钟 +201001943,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中加水至1/4高度,水烧开后,将盘子放入锅中,盖上锅盖,蒸15分钟。,3.0,蒸,"锅,盘子,锅盖",15分钟 +201001944,Recipe,萝卜炖羊排,萝卜炖羊排,,Recipe,"[{'term': 'radish炖羊排', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡萝卜炖羊排', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '萝卜煲羊排', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '萝卜stewed羊排', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '白萝卜炖羊排', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,4.0,西北菜,约20分钟(切萝卜、处理羊排、焯水),高压锅版约35分钟;普通锅版约80-90分钟,1份,"观察水位线,水位低于2/3食材时加热水至没过食材",dishes\meat_dish\萝卜炖羊排.md,,,,,,,, +201001945,Ingredient,羊排,羊排,,Ingredient,,蛋白质,,,,,,,,400,g,True,,,,, +201001946,Ingredient,白萝卜,白萝卜,,Ingredient,,蔬菜,,,,,,,,1,根,True,,,,, +201001947,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,根,False,,,,, +201001948,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,10,粒,False,,,,, +201001949,Ingredient,白芷,白芷,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201001950,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201001951,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30-40,ml,False,,,,, +201001952,Ingredient,黄酒,黄酒,,Ingredient,,调料,,,,,,,,30-40,ml,False,,,,, +201001953,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201001954,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2-4,粒,False,,,,, +201001955,Ingredient,水,水,,Ingredient,,其他,,,,,,,,1000,ml,False,,,,, +201001956,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,萝卜去皮、滚刀切成 3-5cm 的大块,备用,1.0,切,"刀,案板",约5分钟 +201001957,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,羊排在购买时可以让卖家切好,因为家用刀一般难以切动,备用,2.0,切,, +201001958,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,羊肉冷水下锅,加入一半的料酒,一半的葱姜,煮 10 分钟去掉血腥,(可选)把焯的过程中出现的血沫子可以用勺子盛出来,3.0,"焯水,煮","锅,勺子",10分钟 +201001959,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,另起一锅冷水,放入切好的白萝卜,放入一半的冰糖,等水开后煮 5 分钟去掉白萝卜的辣味,4.0,"焯水,煮",锅,5分钟 +201001960,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,盛出来焯好的羊排,放入高压锅中,加水没过所有食材后再增加大约 300ml 的水,5.0,"盛,加",高压锅, +201001961,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将剩余的葱姜料酒,花椒,冰糖,白芷(可选),盐放入锅中,盖锅等待上汽后计时,中火炖大约 15 分钟。如没有高压锅,则放入普通锅中,炖大约 40 分钟到 1 小时,6.0,炖,"高压锅,普通锅",高压锅15分钟;普通锅40-60分钟 +201001962,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,关火,等待高压锅放气完毕,开盖,加入之前焯好的萝卜,调味,加入 3-10g 的食盐或者水,品尝汤的咸淡,7.0,"放气,开盖,调味",高压锅,约5分钟 +201001963,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,再开火,中火,高压锅上汽再炖 10 分钟,普通锅盖盖再炖 20 分钟,8.0,炖,"高压锅,普通锅",高压锅10分钟;普通锅20分钟 +201001964,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,关火,盛盘,9.0,盛盘,, +201001965,Recipe,蒜苔炒肉末,蒜苔炒肉末,,Recipe,,荤菜,2.0,东北菜,约5分钟,约6分钟,1人,"加入食盐前可尝一下咸淡,自行增减盐量,选用五花肉薄片无需腌制即可入味",dishes\meat_dish\蒜苔炒肉末.md,,,,,,,, +201001966,Ingredient,蒜苔,蒜苔,,Ingredient,,蔬菜,,,,,,,,190,g,True,,,,, +201001967,Ingredient,五花肉薄片,五花肉薄片,,Ingredient,,蛋白质,,,,,,,,20,g,True,,,,, +201001968,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201001969,Ingredient,蒜瓣,蒜瓣,,Ingredient,,调料,,,,,,,,2,瓣,False,,,,, +201001970,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201001971,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201001972,Ingredient,水,水,,Ingredient,,其他,,,,,,,,20,g,False,,,,, +201001973,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,蒜苔切成5cm小段,备用,1.0,切,"刀,案板", +201001974,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,五花肉切成5mm×5cm丝状,备用,2.0,切,"刀,案板", +201001975,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,蒜瓣拍碎切成末,备用,3.0,"拍,切","刀,案板", +201001976,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,锅内放入10ml食用油,等待10秒让油温升高,4.0,加热,炒锅,10秒 +201001977,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入蒜末,中火翻炒10秒将蒜末炒出香味,5.0,炒,"炒锅,锅铲",10秒 +201001978,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入五花肉和5ml生抽,中火翻炒30秒将肉炒熟并上色,6.0,炒,"炒锅,锅铲",30秒 +201001979,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将蒜苔放入锅内并加入10ml生抽,翻炒30秒,7.0,炒,"炒锅,锅铲",30秒 +201001980,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,锅内加入20g水,中火翻炒5分钟将蒜苔炒至稍稍变软,8.0,炒,"炒锅,锅铲",5分钟 +201001981,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,最后加入2g食盐,中火翻炒30秒,即可出锅装盘,9.0,炒,"炒锅,锅铲",30秒 +201001982,Recipe,虎皮肘子,虎皮肘子,,Recipe,,荤菜,5.0,东北菜,约1小时(解冻、泡水、灼烧、刷洗),约1小时40分钟(焯水5分钟+油炸20分钟+高压炖煮40分钟+收汁15-20分钟),1个肘子(约3-4人份),"传统名菜,先烧再炸后炖,虎皮状表皮,肥而不腻,老饭骨教程",dishes\meat_dish\虎皮肘子.md,,,,,,,, +201001983,Ingredient,猪前肘,猪前肘,,Ingredient,,蛋白质,,,,,,,,1,个,True,,,,, +201001984,Ingredient,食用植物油,食用植物油,,Ingredient,,调料,,,,,,,,1,桶,False,,,,, +201001985,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,桶,False,,,,, +201001986,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1-2,茶匙,False,,,,, +201001987,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,茶匙,False,,,,, +201001988,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,汤匙,False,,,,, +201001989,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,1,汤匙,False,,,,, +201001990,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,3,片,False,,,,, +201001991,Ingredient,肉桂皮,肉桂皮,,Ingredient,,调料,,,,,,,,2-3,克,False,,,,, +201001992,Ingredient,豆蔻,豆蔻,,Ingredient,,调料,,,,,,,,3,个,False,,,,, +201001993,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,8-12,个,False,,,,, +201001994,Ingredient,大料,大料,,Ingredient,,调料,,,,,,,,2-4,个,False,,,,, +201001995,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,1,汤匙,False,,,,, +201001996,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,2,棵,False,,,,, +201001997,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,6,克,False,,,,, +201001998,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,6,粒,False,,,,, +201001999,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,汤匙,False,,,,, +201002000,Ingredient,水,水,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201002001,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,猪肘解冻后水泡1小时去除血水。,1.0,浸泡,盆,1小时 +201002002,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,使用火焰喷枪或烧热的铁锅将猪肘皮灼烧至棕黑色,去除猪毛和汗腺。,2.0,灼烧,"火焰喷枪,铁锅,锅铲,筷子",约5-8分钟 +201002003,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,用清洁球刷洗猪肘,去除烧焦部分,恢复干净表面。,3.0,刷洗,清洁球,约3-5分钟 +201002004,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将猪肘放入铁锅,加冷水浸没3/4以上,加入葱白、蒜、姜、料酒,烧开后焯水5分钟。,4.0,焯水,"铁锅,刀",5分钟 +201002005,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,捞出猪肘,保留肉汤备用,去除配料。,5.0,"捞出,过滤","漏勺,容器",约2分钟 +201002006,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锅中加入冷油,油量浸没猪肘3/5以上,中火加热至五成热后转小火,放入猪肘油炸20分钟,期间每3分钟翻面一次。,6.0,油炸,"锅,锅铲",20分钟 +201002007,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,捞出炸好的猪肘备用,炸油可留作他用。,7.0,捞出,漏勺,约1分钟 +201002008,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,炒糖色200ml备用。,8.0,炒糖色,锅,约5分钟 +201002009,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将猪肘、肉汤、糖色及所有香料、调味料加入高压锅,再加葱白、蒜、姜,加压炖煮40分钟。,9.0,炖煮,高压锅,40分钟 +201002010,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,炖煮期间调制水淀粉:1汤匙淀粉+100ml水搅匀备用。,10.0,调制水淀粉,"碗,筷子",约2分钟 +201002011,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,高压锅泄压后开盖,取出配料,将猪肘移至盘中,肉汤倒入铁锅。,11.0,"取出,转移","筷子,铁锅",约3分钟 +201002012,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,大火收汁,汤汁剩一半时分两次加入水淀粉,每次沸腾后再加下一次,最后淋在猪肘上即可。,12.0,"收汁,勾芡,淋汁","锅,汤匙",15-20分钟 +201002013,Recipe,蚂蚁上树,蚂蚁上树,,Recipe,,荤菜,3.0,川菜,20分钟(粉丝泡软+切配),约10分钟(炒制+煮制),2人,"粉丝不宜久煮,郫县豆瓣酱含盐高可减生抽,可加白胡椒粉提味",dishes\meat_dish\蚂蚁上树.md,,,,,,,, +201002014,Ingredient,红薯粉丝,红薯粉丝,,Ingredient,,淀粉类,,,,,,,,80,g,True,,,,, +201002015,Ingredient,猪肉末,猪肉末,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201002016,Ingredient,郫县豆瓣酱,郫县豆瓣酱,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201002017,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201002018,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201002019,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201002020,Ingredient,蒜末,蒜末,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002021,Ingredient,姜末,姜末,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002022,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,300,ml,False,,,,, +201002023,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,适量,,False,,,,, +201002024,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,0.5,g,False,,,,, +201002025,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,红薯粉丝提前泡软,泡水时间为20分钟,备用,1.0,泡,盆,20分钟 +201002026,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将蒜、姜分别剁碎,备用,2.0,切,"刀,案板", +201002027,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅烧热,加入10ml食用油,加入蒜末、姜末炒香,3.0,炒,"炒锅,锅铲", +201002028,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入猪肉末翻炒至肉色发白且微微出油,4.0,炒,锅铲, +201002029,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入郫县豆瓣酱,炒至红油析出,5.0,炒,锅铲, +201002030,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入生抽和老抽,翻炒均匀,6.0,炒,锅铲, +201002031,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,倒入300ml清水,煮沸,7.0,煮,锅铲, +201002032,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入泡软沥干的粉丝,用筷子轻轻拨动防止粘连,8.0,煮,筷子, +201002033,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,中小火煮约5分钟,直至粉丝完全吸收汤汁、呈现微微收干状态,9.0,煮,锅铲,5分钟 +201002034,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,依据口味可撒入小葱末,关火装盘,10.0,装盘,锅铲, +201002035,Recipe,辣椒炒肉,辣椒炒肉,,Recipe,,荤菜,3.0,湘菜,15分钟,8分钟,1人,"辣椒选择:螺丝椒最优,肉片顺纹切呈川字,先干煸青椒出虎皮",dishes\meat_dish\辣椒炒肉.md,,,,,,,, +201002036,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,3,个,True,,,,, +201002037,Ingredient,猪瘦肉,猪瘦肉,,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201002038,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002039,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,ml,False,,,,, +201002040,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,3,ml,False,,,,, +201002041,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002042,Ingredient,生姜,生姜,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002043,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,2,ml,False,,,,, +201002044,Ingredient,豆豉,豆豉,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201002045,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,8,ml,False,,,,, +201002046,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将青椒洗净,去除青椒把以及青椒籽,再用滚刀手法切好备用。,1.0,切,"刀,案板",2分钟 +201002047,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,大蒜用刀拍一下,再横切成蒜瓣,生姜切碎成姜末。,2.0,"拍,切","刀,案板",1分钟 +201002048,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将猪瘦肉切成肉片(顺着猪肉的纹理切,即刀和肉的纹理呈水平线,出来的肉片,纹路呈“川”字)。,3.0,切,"刀,案板",2分钟 +201002049,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将切好的猪肉洗净,放入空碗,再加入计算好的生抽、蚝油、盐搅拌均匀,腌制10分钟。,4.0,腌制,"碗,筷子",10分钟 +201002050,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅,不用倒油,把切好的青椒放入锅中,大火干煸至虎皮状后,再加2g盐继续翻炒1分钟后捞起。,5.0,"干煸,炒","炒锅,锅铲",3分钟 +201002051,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,不用洗锅,大火热锅,加入8ml油,等待30秒,加入蒜瓣、姜末翻炒15秒。,6.0,炒,"炒锅,锅铲",45秒 +201002052,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入腌制好的猪肉倒入锅内翻炒2分钟,再加入干煸过的青椒翻炒1分钟。,7.0,炒,"炒锅,锅铲",3分钟 +201002053,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,根据个人口味喜好加入豆豉,最后加入酱油,继续翻炒30秒。,8.0,炒,"炒锅,锅铲",30秒 +201002054,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,出锅,盛盘。,9.0,装盘,"锅铲,盘子",10秒 +201002055,Recipe,香干肉丝,香干肉丝,,Recipe,,荤菜,3.0,,约10分钟,约8-10分钟,1人/份,"螺丝椒为最优青椒选择,可加小米椒增辣",dishes\meat_dish\香干肉丝.md,,,,,,,, +201002056,Ingredient,猪里脊,猪里脊,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201002057,Ingredient,香干,香干,,Ingredient,,蛋白质,,,,,,,,75,g,True,,,,, +201002058,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,5,个,True,,,,, +201002059,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201002060,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201002061,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,5,g,False,,,,, +201002062,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,5,g,False,,,,, +201002063,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002064,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,肉丝用3ml生抽与生粉混合均匀,腌制待用。,1.0,腌制,盆,约2分钟 +201002065,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,青椒洗净,用滚刀手法切好备用。,2.0,切,"刀,案板",约2分钟 +201002066,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大蒜横切成片,香干切丝。,3.0,切,"刀,案板",约2分钟 +201002067,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,淀粉与10ml水混合,搅拌均匀成芡汁备用。,4.0,混合,"碗,筷子",约1分钟 +201002068,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,干净锅倒入15ml油,不用等油热即倒入肉丝,慢慢划散至肉丝变色熟透,立即捞出,留油在锅中。,5.0,炒,"炒锅,锅铲",约2-3分钟 +201002069,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将蒜片和香干放入锅中,加入2ml生抽,翻炒均匀。,6.0,炒,"炒锅,锅铲",约1分钟 +201002070,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,2-3分钟后,根据火力大小,将青椒丝放入锅中混合翻炒。,7.0,炒,"炒锅,锅铲",约2-3分钟 +201002071,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,1分钟后放入肉丝混合。,8.0,炒,"炒锅,锅铲",约1分钟 +201002072,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,倒入淀粉芡汁勾芡,加入3g盐和2g鸡精,翻炒2-3分钟后出锅。,9.0,"勾芡,炒","炒锅,锅铲",约2-3分钟 +201002073,Recipe,鱼香肉丝,鱼香肉丝,,Recipe,,荤菜,4.0,川菜,15-30分钟(腌制)+ 4小时(木耳泡发)+ 10分钟(切配),约5分钟(炒制),1-2人,,dishes\meat_dish\鱼香肉丝.md,,,,,,,, +201002074,Ingredient,里脊肉,里脊肉,,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201002075,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201002076,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,100,g,True,,,,, +201002077,Ingredient,木耳(干),木耳(干),,Ingredient,,蔬菜,,,,,,,,5,g,True,,,,, +201002078,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201002079,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201002080,Ingredient,蛋清,蛋清,,Ingredient,,蛋白质,,,,,,,,1,个,False,,,,, +201002081,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,10,g,False,,,,, +201002082,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201002083,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201002084,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002085,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002086,Ingredient,葱,葱,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002087,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,2,瓣,False,,,,, +201002088,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201002089,Ingredient,水,水,,Ingredient,,其他,,,,,,,,40,ml,False,,,,, +201002090,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,20,ml,False,,,,, +201002091,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,制作腌料:将生抽5ml、料酒5ml、淀粉5g、水20ml、蛋清1个混合成腌料。,1.0,混合,碗,1分钟 +201002092,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,制作香汁:将生抽5ml、醋15ml、白糖10g、盐1g、淀粉5g、水20ml混合成香汁备用。,2.0,混合,碗,1分钟 +201002093,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,用腌料腌制里脊肉15-30分钟,并抓匀。,3.0,腌制,碗,15-30分钟 +201002094,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,干木耳泡发4小时,洗净,切成小块。,4.0,"泡发,切","刀,案板",4小时 +201002095,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,青椒洗净去蒂切丝;胡萝卜洗净切丝并焯水。,5.0,"洗,切,焯水","刀,案板,锅",5分钟 +201002096,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,姜、蒜切末;葱切成5mm小段。,6.0,切,"刀,案板",2分钟 +201002097,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,锅烧热后加15ml油,倒入腌好的里脊肉快速滑散至变白,盛出备用。,7.0,炒,"炒锅,锅铲",30秒 +201002098,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,锅再次烧热加5ml油,倒入葱、姜、蒜、豆瓣酱炒香。,8.0,炒,"炒锅,锅铲",20秒 +201002099,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,倒入胡萝卜丝翻炒20秒,加入青椒丝和木耳块继续翻炒2分钟。,9.0,炒,"炒锅,锅铲",2分20秒 +201002100,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,倒入炒过的里脊肉,快速翻炒均匀,不超过20秒。,10.0,炒,"炒锅,锅铲",20秒 +201002101,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,倒入香汁,快速翻炒均匀,不超过15秒后关火。,11.0,炒,"炒锅,锅铲",15秒 +201002102,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,盛盘即可。,12.0,装盘,锅铲,10秒 +201002103,Recipe,麻辣香锅,麻辣香锅,,Recipe,,荤菜,3.0,川菜,约5分钟(洗菜、切配),约18分钟(焯水+炒制),3人,"大火240℃/2kW,中火120℃/1.4kW",dishes\meat_dish\麻辣香锅.md,,,,,,,, +201002104,Ingredient,青菜(油菜、油麦菜、菠菜),青菜(油菜、油麦菜、菠菜),,Ingredient,,蔬菜,,,,,,,,455,克,True,,,,, +201002105,Ingredient,无骨肉(猪肉、牛肉、鸡肉、鱼丸、火腿肠),无骨肉(猪肉、牛肉、鸡肉、鱼丸、火腿肠),,Ingredient,,蛋白质,,,,,,,,430,克,True,,,,, +201002106,Ingredient,干豆腐,干豆腐,,Ingredient,,蛋白质,,,,,,,,152,克,True,,,,, +201002107,Ingredient,北京麻辣方便面,北京麻辣方便面,,Ingredient,,淀粉类,,,,,,,,1,袋,True,,,,, +201002108,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002109,Ingredient,麻辣香锅调料,麻辣香锅调料,,Ingredient,,调料,,,,,,,,110,克,False,,,,, +201002110,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,105,克,False,,,,, +201002111,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,烧开一锅水(水量能没过第 2-4 步中的食材即可)。,1.0,煮,锅,约2分钟 +201002112,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,在开水中放入青菜,焯 5 分钟后盛出备用。,2.0,焯水,"锅,漏勺",5分钟 +201002113,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,在开水中放入无骨肉,焯 4 分钟后盛出备用。,3.0,焯水,"锅,漏勺",4分钟 +201002114,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,在开水中放入北京麻辣方便面,煮 2 分钟后盛出备用。,4.0,煮,"锅,漏勺",2分钟 +201002115,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,倒出开水,擦干锅具,放入 105 克食用油,大火加热 30 秒。,5.0,加热,锅,30秒 +201002116,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入麻辣香锅调料,翻炒 20 秒。,6.0,炒,"锅,锅铲",20秒 +201002117,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入干辣椒,翻炒 10 秒。,7.0,炒,"锅,锅铲",10秒 +201002118,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入焯过的青菜,改中火,翻炒 3 分钟。,8.0,炒,"锅,锅铲",3分钟 +201002119,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,放入焯过的无骨肉,翻炒 3 分钟。,9.0,炒,"锅,锅铲",3分钟 +201002120,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,放入煮过的北京麻辣方便面,用筷子翻动 1 分钟。,10.0,炒,"锅,筷子",1分钟 +201002121,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,关火,出锅。,11.0,出锅,锅铲,约10秒 +201002122,Recipe,黄焖鸡,黄焖鸡,,Recipe,"[{'term': '黄闷鸡', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '黄braised鸡', 'language': 'en', 'language_code': 'en-US'}]",荤菜,3.0,,约20分钟(含泡干香菇、切配),15-20分钟,2人,"炒糖色技巧,砂锅焖煮更香,汤汁浓稠不过干,青椒最后放保持脆嫩",dishes\meat_dish\黄焖鸡.md,,,,,,,, +201002123,Ingredient,鸡腿,鸡腿,,Ingredient,,蛋白质,,,,,,,,2,只,True,,,,, +201002124,Ingredient,香菇,香菇,,Ingredient,,蔬菜,,,,,,,,5,朵,True,,,,, +201002125,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,个,True,,,,, +201002126,Ingredient,生姜片,生姜片,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002127,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,5.5,个,False,,,,, +201002128,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002129,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201002130,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002131,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201002132,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201002133,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201002134,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",淀粉类,,,,,,,,1,个,False,,,,, +201002135,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡腿洗净,剁成4cm大小的块,1.0,切,"刀,案板", +201002136,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,生姜切片、干辣椒切成小圈,2.0,切,"刀,案板", +201002137,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,香菇切片,青椒切成细长的马蹄状;若为干香菇,洗净灰尘后泡一晚上并留香菇水备用,3.0,"切,泡发","刀,案板,盆", +201002138,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,若有土豆,切为与鸡肉大小类似的滚刀块,4.0,切,"刀,案板", +201002139,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,炒糖色:锅里倒入底油,冷油时放入白糖;小火慢慢加热,待糖融化并变成较深的棕色,期间不断搅拌,5.0,炒,"炒锅,锅铲",约2-3分钟 +201002140,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,迅速倒入鸡块,转大火快速翻炒,烹入料酒继续翻炒片刻,6.0,炒,"炒锅,锅铲",约1分钟 +201002141,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入生姜片和干辣椒炒匀,7.0,炒,锅铲,约30秒 +201002142,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入酱油炒匀,8.0,炒,锅铲,约30秒 +201002143,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,倒入香菇水或清水,以能淹住鸡肉为准,9.0,倒,锅铲, +201002144,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入香菇片、白胡椒粉、盐、土豆,翻炒均匀后盖上锅盖焖煮,转中小火15-20分钟,可转至砂锅,10.0,"炒,焖","炒锅/砂锅,锅盖",15-20分钟 +201002145,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,鸡肉软烂、汤汁浓稠后放入青椒,加入味精兜炒均匀,青椒断生即可关火,11.0,炒,锅铲,约30秒 +201002146,Recipe,黄瓜炒肉,黄瓜炒肉,,Recipe,,荤菜,3.0,,15分钟,约1分钟,1人/份,"大火快炒,若火力不足可适当延长炒制时间",dishes\meat_dish\黄瓜炒肉.md,,,,,,,, +201002147,Ingredient,黄瓜,黄瓜,,Ingredient,,蔬菜,,,,,,,,100,克,True,,,,, +201002148,Ingredient,猪瘦肉,猪瘦肉,,Ingredient,,蛋白质,,,,,,,,50,克,True,,,,, +201002149,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,50,克,False,,,,, +201002150,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,克,False,,,,, +201002151,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201002152,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,2,瓣,False,,,,, +201002153,Ingredient,小米辣,小米辣,,Ingredient,,调料,,,,,,,,1,根,False,,,,, +201002154,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将猪瘦肉切片,放入碗中,倒入食用油10克、生抽,搅拌均匀,腌制10分钟,1.0,"切,腌制","刀,碗,筷子",10分钟 +201002155,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将黄瓜切去5厘米的头尾,剩余部分斜着切成0.5厘米的薄片,2.0,切,"刀,案板", +201002156,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将黄瓜倒入碗中,撒上盐8克,搅拌均匀,腌制5分钟,3.0,腌制,"碗,筷子",5分钟 +201002157,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将蒜瓣去皮,压扁,切成蒜末备用,4.0,切,"刀,案板", +201002158,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将小米辣去蒂切分成均匀0.5厘米的段状,5.0,切,"刀,案板", +201002159,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,热锅,倒油40克,等油温到冒烟,放入蒜蓉、小米辣翻炒5次,6.0,炒,"炒锅,锅铲",约10秒 +201002160,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入腌制好的猪瘦肉,翻炒至肉熟变色,7.0,炒,"炒锅,锅铲",约20秒 +201002161,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入黄瓜,加入盐2克,大火翻炒均匀半分钟,出锅;若无法保证大火,可延长至50秒,8.0,炒,"炒锅,锅铲",30-50秒 +201002162,Recipe,农家一碗香,农家一碗香,,Recipe,,荤菜,3.0,湘菜,7分钟,10分钟,1~2人,第一次炒鸡蛋油多时,后续炒肉可酌情不加油,dishes\meat_dish\农家一碗香\农家一碗香.md,,,,,,,, +201002163,Ingredient,猪肉(五花肉),猪肉(五花肉),,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201002164,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,3,个,True,,,,, +201002165,Ingredient,蒜片,蒜片,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002166,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002167,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201002168,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201002169,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,mg,False,,,,, +201002170,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002171,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,适量,个,True,,,,, +201002172,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将猪肉切片,最好把肥瘦分开放;青椒和小米辣切成段;蒜片用刀背拍成末;姜切成丝;鸡蛋打到小碗中,用筷子打散。,1.0,"切,拍,打散","刀,案板,碗,筷子", +201002173,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中倒油,开小火,油热后倒入蛋液,炒散至断生,盛出备用。,2.0,炒,"炒锅,锅铲,碗", +201002174,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中再加少许油,小火将肥猪肉下锅逼出猪油。,3.0,"煎,煸","炒锅,锅铲", +201002175,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,肥肉呈金黄色时转中火,加入瘦肉翻炒至变色。,4.0,炒,"炒锅,锅铲", +201002176,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入姜丝、蒜末和豆瓣酱,翻炒均匀给猪肉上色。,5.0,炒,"炒锅,锅铲", +201002177,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入青红椒和炒好的鸡蛋,加入酱油和白糖,翻炒至青椒微微断生,保持清脆口感。,6.0,炒,"炒锅,锅铲", +201002178,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,出锅装盘即可。,7.0,装盘,锅铲, +201002179,Recipe,冬瓜酿肉,冬瓜酿肉,,Recipe,,荤菜,4.0,,25分钟,15分钟,2人,操作时注意碟子很烫,小心操作,dishes\meat_dish\冬瓜酿肉\冬瓜酿肉.md,,,,,,,, +201002180,Ingredient,猪肉末,猪肉末,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201002181,Ingredient,冬瓜,冬瓜,,Ingredient,,蔬菜,,,,,,,,200,g,True,,,,, +201002182,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201002183,Ingredient,葱花,葱花,,Ingredient,,蔬菜,,,,,,,,20,g,False,,,,, +201002184,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002185,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201002186,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,5,g,False,,,,, +201002187,Ingredient,水淀粉,水淀粉,,Ingredient,,淀粉类,,,,,,,,25,g,False,,,,, +201002188,Ingredient,水,水,,Ingredient,,其他,,,,,,,,50,ml,False,,,,, +201002189,Ingredient,葱姜末,葱姜末,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201002190,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002191,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,冬瓜去皮,切成25cm长3cm厚的片,1.0,切,"刀,案板", +201002192,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将切好的冬瓜放入碗中,放入15g盐,将冬瓜抹匀,放置10分钟,2.0,腌制,碗,10分钟 +201002193,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放置冬瓜的同时,换个碗放入肉末、葱姜末、5g盐、淀粉5g、胡椒粉、生抽、胡椒粉,3.0,混合,"碗,筷子", +201002194,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,使用筷子在肉末中进行顺时针搅拌,搅拌到食材颜色没有明显对比(约2分钟),4.0,搅拌,筷子,2分钟 +201002195,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将腌制好的冬瓜(会变软)使用清水洗三遍,5.0,清洗,水盆, +201002196,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,拿出1片冬瓜片卷起来,并把肉塞进去,6.0,"卷,塞",手, +201002197,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入碟子中摆到碟子的边缘,7.0,摆盘,碟子, +201002198,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,打入1个鸡蛋到中间圆圈处,8.0,打蛋,碟子, +201002199,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,放入普通铁锅中水烧开后,蒸15分钟,盖上锅盖,9.0,蒸,"铁锅,锅盖",15分钟 +201002200,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,开盖,取出蒸好的冬瓜酿肉,10.0,取,防烫手套, +201002201,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将冬瓜酿肉碟子的水倒入锅中,放入水淀粉,加入50ml清水倒入锅中烧开,11.0,"倒,煮",锅, +201002202,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,淋到冬瓜酿肉上,12.0,淋,勺子, +201002203,Recipe,凉拌鸡丝,凉拌鸡丝,,Recipe,,荤菜,3.0,,10分钟,5-7分钟,1人份,"少油低卡,快手菜,可加入香菜,可加入小葱,可加辣椒油",dishes\meat_dish\凉拌鸡丝\凉拌鸡丝.md,,,,,,,, +201002204,Ingredient,鸡胸肉,鸡胸肉,,Ingredient,,蛋白质,,,,,,,,200,克,True,,,,, +201002205,Ingredient,麻油,麻油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201002206,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,4,毫升,False,,,,, +201002207,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,4,毫升,False,,,,, +201002208,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,克,False,,,,, +201002209,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201002210,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201002211,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,20,克,False,,,,, +201002212,Ingredient,凉白开水,凉白开水,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201002213,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,姜切片,备用,1.0,切,刀, +201002214,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中倒入4升水,2.0,,锅, +201002215,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入鸡胸肉、姜片,3.0,加,锅, +201002216,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入20毫升料酒,4.0,加,锅, +201002217,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,开大火不盖盖将水烧开,5.0,煮,锅, +201002218,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,水开后转中火,用勺子将浮沫捞出,6.0,"煮,捞","锅,勺子", +201002219,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,继续煮5-7分钟,如果是非冷冻肉煮5分钟,冷冻肉煮7分钟;用筷子插入鸡胸肉,如果能轻松插入,代表鸡肉熟了,否则延长煮制时间,7.0,煮,"锅,筷子",5-7分钟 +201002220,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,用凉白开水冲泡鸡胸肉,使鸡胸肉降至室温,8.0,冲,盆, +201002221,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,顺着鸡胸肉纹理将鸡胸肉撕成细丝,9.0,撕,手, +201002222,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,准备一个碗,碗中加入准备好的麻油、生抽、香醋、白糖、盐,搅拌料汁,使糖和盐尽量溶化,10.0,搅拌,"碗,筷子", +201002223,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将料汁倒入鸡丝中,搅拌均匀,11.0,拌,"碗,筷子", +201002224,Recipe,卤菜,卤菜,,Recipe,,荤菜,3.0,,3小时以上(牛腱子浸泡),25-30分钟(高压锅卤制)+ 浸泡过夜,2-3人,"卤水可重复使用,越老越香,卤素菜需单独取卤水,可做牛肉面汤底",dishes\meat_dish\卤菜\卤菜.md,,,,,,,, +201002225,Ingredient,卤料包,卤料包,,Ingredient,,调料,,,,,,,,1,包,False,,,,, +201002226,Ingredient,黄豆酱,黄豆酱,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201002227,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201002228,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201002229,Ingredient,南腐乳,南腐乳,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201002230,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,100,g,False,,,,, +201002231,Ingredient,生姜,生姜,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201002232,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,40,g,False,,,,, +201002233,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002234,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,120,ml,False,,,,, +201002235,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,60,ml,False,,,,, +201002236,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10-15,g,False,,,,, +201002237,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,g,False,,,,, +201002238,Ingredient,啤酒,啤酒,,Ingredient,,调料,,,,,,,,330,ml,False,,,,, +201002239,Ingredient,牛腱子,牛腱子,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201002240,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,足量,ml,False,,,,, +201002241,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,牛腱子提前浸泡在冷水中3小时以上,去除血水,1.0,浸泡,盆,3小时以上 +201002242,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中加入30g白糖,小火加热至糖完全融化并呈现棕褐色,加入150ml热水,搅拌均匀备用,制成糖色,2.0,炒,锅, +201002243,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将洋葱切块,生姜和大蒜拍碎,干辣椒掰断备用,3.0,"切,拍,掰","刀,案板", +201002244,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,在锅中加入足量的水,放入卤料包、洋葱、生姜、大蒜、干辣椒,大火烧开,4.0,煮,锅, +201002245,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入黄豆酱、豆瓣酱、蚝油和南腐乳各15ml,搅拌均匀,5.0,搅拌,"锅,勺", +201002246,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入准备好的糖色,混合均匀,6.0,搅拌,"锅,勺", +201002247,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入生抽120ml和老抽60ml,搅拌均匀,7.0,搅拌,"锅,勺", +201002248,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入10-15g盐调味,倒入1罐啤酒(330ml),再次烧开,8.0,"搅拌,煮",锅, +201002249,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,牛腱子放入锅中焯水2-3分钟,捞出并用热水冲洗干净表面的浮沫,9.0,"焯水,冲洗","锅,滤网",2-3分钟 +201002250,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将焯水后的牛腱子放入已烧开的卤水中,确保卤水没过所有肉类,10.0,煮,锅, +201002251,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,盖上高压锅盖,上汽后继续烹饪25-30分钟,11.0,高压煮,高压锅,25-30分钟 +201002252,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,烹饪完成后,不要开盖保温,自然冷却并浸泡一晚上,12.0,焖,高压锅,过夜 +201002253,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,将卤好的肉取出放入冰箱冷藏,使其成型,13.0,冷藏,冰箱, +201002254,CookingStep,步骤14,步骤14,,CookingStep,,,,,,,,,,,,,食用前取出切片,可直接食用或凉拌,14.0,切,刀, +201002255,Recipe,口水鸡,口水鸡,,Recipe,,荤菜,3.0,川菜,约15分钟(切配、花生烘烤、红油调制),约30分钟(煮鸡20分钟+冰水冷却),1份,"夏日凉菜,米饭杀手,冰爽Q弹,红油香辣",dishes\meat_dish\口水鸡\口水鸡.md,,,,,,,, +201002256,Ingredient,鸡,鸡,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201002257,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201002258,Ingredient,辣椒粉,辣椒粉,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002259,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002260,Ingredient,花生,花生,,Ingredient,,蛋白质,,,,,,,,30,g,False,,,,, +201002261,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,50,g,False,,,,, +201002262,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,20,g,False,,,,, +201002263,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201002264,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201002265,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201002266,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201002267,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002268,Ingredient,花椒粉,花椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002269,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,5,g,False,,,,, +201002270,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,姜切片,1颗小葱切段,15颗花椒备用,1.0,切,"刀,案板",2分钟 +201002271,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鸡肉洗净,放入锅中,加清水没过鸡肉,放入姜片、葱段和花椒,大火烧开,2.0,煮,锅,5分钟 +201002272,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,水开后转中小火煮20分钟,关火,3.0,煮,锅,20分钟 +201002273,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,取出鸡肉,放入冰水中迅速冷却至冰凉,4.0,冷却,"盆,冰水",5分钟 +201002274,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,取出鸡肉,切块摆盘备用,5.0,切,"刀,案板,盘子",3分钟 +201002275,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,小火将锅烧热,倒入花生,烘烤至表皮爆裂,注意翻动防糊,6.0,"炒,烘烤","锅,锅铲",3-4分钟 +201002276,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,一颗葱切段,蒜拍末,花椒15颗,花生去皮后切碎,7.0,"切,拍","刀,案板",2分钟 +201002277,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,锅内倒油烧热,放入葱段、花椒和一半蒜末炒香,8.0,炒,"锅,锅铲",1分钟 +201002278,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,油温升至8成热后关火,滤出热油,9.0,"炸,过滤","锅,滤网,碗",30秒 +201002279,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将热油倒入盛辣椒粉的碗中,搅拌并滤出红油,10.0,"炸,搅拌,过滤","碗,筷子,滤网",1分钟 +201002280,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,在红油中加入剩余蒜末、生抽、醋、盐、味精、糖、香油、花椒粉,拌匀放凉,11.0,搅拌,"碗,筷子",2分钟 +201002281,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,鸡肉上撒花生碎,淋红油,撒香菜即成,12.0,"淋,撒","勺子,盘子",1分钟 +201002282,Recipe,台式卤肉饭,台式卤肉饭,,Recipe,,荤菜,5.0,台湾菜,30分钟,1小时,2~3人,"五花肉冷冻30分钟更易切条,冷冻五花肉常温回温30分钟再切,切条时刀刃与肉快速摩擦保护肥瘦结构,肉条要细(0.7 cm×0.7 cm)更易炖煮软糯",dishes\meat_dish\台式卤肉饭\台式卤肉饭.md,,,,,,,, +201002283,Ingredient,红葱头,红葱头,,Ingredient,,蔬菜,,,,,,,,25,g,False,,,,, +201002284,Ingredient,带皮五花肉,带皮五花肉,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201002285,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,4,个,False,,,,, +201002286,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201002287,Ingredient,生抽酱油,生抽酱油,,Ingredient,,调料,,,,,,,,75,ml,False,,,,, +201002288,Ingredient,米酒,米酒,,Ingredient,,调料,,,,,,,,35,ml,False,,,,, +201002289,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,25,g,False,,,,, +201002290,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002291,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,颗,False,,,,, +201002292,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,g,False,,,,, +201002293,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,6,g,False,,,,, +201002294,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,6,g,False,,,,, +201002295,Ingredient,米饭,米饭,,Ingredient,,淀粉类,,,,,,,,根据个人食量决定,,True,,,,, +201002296,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,带皮五花肉切成0.7 cm × 0.7 cm × 2.5 cm的细长条,1.0,切,"刀,案板", +201002297,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,红葱头、大蒜切末备用,2.0,切,"刀,案板", +201002298,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,鸡蛋煮熟剥壳,并用刀划破蛋白便于入味,备用,3.0,"煮,切","锅,刀", +201002299,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,大火热锅,倒入15 ml食用油,让油滑满锅底,等待5秒使油温升高,4.0,炒,"炒锅,锅铲",5秒 +201002300,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入五花肉条,翻炒至肉色稍微变白,沿锅边淋入米酒10 ml,继续翻炒至五花肉不再出油,5.0,炒,"炒锅,锅铲", +201002301,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入红葱头末,翻炒1分钟爆出油葱香味,6.0,炒,"炒锅,锅铲",1分钟 +201002302,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,再次加入大蒜末,翻炒30秒,7.0,炒,"炒锅,锅铲",30秒 +201002303,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,把猪肉推到锅边,放入冰糖加热至融化冒泡变成焦糖,再把猪肉翻拌均匀让焦糖附着,8.0,"炒,炒糖色","炒锅,锅铲", +201002304,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入生抽炒出香气,9.0,炒,"炒锅,锅铲", +201002305,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,呛入米酒25 ml,加水至刚好没过猪肉,加入白胡椒粉、五香粉、八角、香叶、水煮蛋,沸腾后转小火卤1小时,10.0,炖,"炒锅,锅铲",1小时 +201002306,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,炖煮过程中每隔15分钟搅拌检查一次,防止粘锅;如过干可加入100 ml清水继续炖煮,11.0,"炖,搅拌",锅铲,每15分钟 +201002307,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,1小时后开大火收汁至酱汁浓稠、呈有光泽的琥珀色,12.0,收汁,"炒锅,锅铲", +201002308,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,盛一碗米饭,将软烂的卤肉浇在米饭上,加上卤蛋即可享用,13.0,装盘,"碗,勺子", +201002309,Recipe,咖喱肥牛,咖喱肥牛,,Recipe,,荤菜,4.0,,约10分钟(切菜、焯水),约30分钟(炖煮+收汁),2人,"咖喱块不用捣碎直接整块投入,注意搅拌避免调味料不均匀",dishes\meat_dish\咖喱肥牛\咖喱肥牛.md,,,,,,,, +201002310,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,1,片,False,,,,, +201002311,Ingredient,纯牛奶,纯牛奶,,Ingredient,,其他,,,,,,,,50,ml,False,,,,, +201002312,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,100,g,False,,,,, +201002313,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,150,g,False,,,,, +201002314,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,200,g,False,,,,, +201002315,Ingredient,肥牛卷,肥牛卷,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201002316,Ingredient,咖喱块,咖喱块,,Ingredient,,调料,,,,,,,,100,g,False,,,,, +201002317,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201002318,Ingredient,冷水,冷水,,Ingredient,,其他,,,,,,,,适量,ml,False,,,,, +201002319,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,洋葱切成条状、胡萝卜以及土豆切成块状,备用,1.0,切,"刀,案板",约5分钟 +201002320,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,烧一锅开水,水沸时将肥牛卷下锅,捞出血沫后放在一边沥水,备用,2.0,"煮,焯水","锅,漏勺",约2-3分钟 +201002321,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅,锅内放入10ml-15ml食用油,等待10秒让油温升高,3.0,加热,炒锅,10秒 +201002322,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,放入洋葱,翻炒至洋葱变软变透明,4.0,炒,锅铲,约2分钟 +201002323,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入土豆以及胡萝卜翻炒2分钟,5.0,炒,锅铲,2分钟 +201002324,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入冷水至淹没所有食材即可,6.0,加水,锅, +201002325,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将香叶、咖喱块投入锅中,盖上锅盖,待水沸腾后将火调小然后等待直至土豆块以及胡萝卜块炖至软烂(可用筷子确认),7.0,炖,"锅,筷子",约15-20分钟 +201002326,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入肥牛卷以及牛奶,盖上锅盖再小火煮2-3分钟即可出锅(用勺子搅拌食材,注意力度,避免肥牛卷破碎),8.0,"煮,搅拌","锅,勺子",2-3分钟 +201002327,Recipe,啤酒鸭,啤酒鸭,,Recipe,,荤菜,4.0,川菜,15分钟,45分钟,1份,"啤酒需没过鸭肉,选择清香型啤酒",dishes\meat_dish\啤酒鸭\啤酒鸭.md,,,,,,,, +201002328,Ingredient,鸭肉,鸭肉,,Ingredient,,蛋白质,,,,,,,,1000,克,True,,,,, +201002329,Ingredient,啤酒,啤酒,,Ingredient,,其他,,,,,,,,800,毫升,True,,,,, +201002330,Ingredient,生抽酱油,生抽酱油,,Ingredient,,调料,,,,,,,,10-15,毫升,False,,,,, +201002331,Ingredient,老抽酱油,老抽酱油,,Ingredient,,调料,,,,,,,,5-10,毫升,False,,,,, +201002332,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,5,片,False,,,,, +201002333,Ingredient,蒜头,蒜头,,Ingredient,,蔬菜,,,,,,,,12,瓣,False,,,,, +201002334,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,克,False,,,,, +201002335,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,5,个,False,,,,, +201002336,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,毫升,False,,,,, +201002337,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,8,克,False,,,,, +201002338,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002339,Ingredient,丁香,丁香,,Ingredient,,调料,,,,,,,,4,颗,False,,,,, +201002340,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,个,False,,,,, +201002341,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,3,片,False,,,,, +201002342,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201002343,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,100,毫升,False,,,,, +201002344,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,把鸭子切成3 cm小块,鸭肉冷水下锅,加姜片、料酒,焯一遍水,盛出沥干水分,备用。,1.0,"切,焯水","刀,案板,锅",5分钟 +201002345,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,炒锅烧热,放入约100ml食用油,大火待油烧开,鸭肉入锅翻炒至上色。,2.0,炒,"炒锅,锅铲",3-5分钟 +201002346,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,待鸭肉完全变色(肉眼可见泛白),将鸭肉拨到锅的一边,倒入豆瓣酱和糖,小火翻炒出香味和糖色。,3.0,炒,"炒锅,锅铲",2分钟 +201002347,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入丁香、八角、香叶、干辣椒、生抽、老抽、蒜,翻炒出香味。,4.0,炒,"炒锅,锅铲",1-2分钟 +201002348,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,倒入啤酒,没过鸭肉,加入盐、鸡精,然后中火将鸭子烧30分钟(牙口不好的话可以再多烧5分钟)。,5.0,炖,炒锅,30-35分钟 +201002349,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,出锅盛盘,上桌食用。,6.0,盛盘,"锅铲,盘子",1分钟 +201002350,Recipe,回锅肉,回锅肉,,Recipe,,荤菜,4.0,川菜,20-25分钟(煮肉+切配菜),约5分钟(炒制),1人(按0.5斤/男人或0.3斤/女人计算),"五花肉需擦干水分防溅油,肉片厚度2mm最佳,过厚易腻,煮后过冷水使肉质更紧致,蒜苗可替换为洋葱等易熟蔬菜,正宗做法可用二刀肉(臀尖)",dishes\meat_dish\回锅肉\回锅肉.md,,,,,,,, +201002351,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,250,克,True,,,,, +201002352,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,棵,False,,,,, +201002353,Ingredient,生姜,生姜,,Ingredient,,蔬菜,,,,,,,,25,克,False,,,,, +201002354,Ingredient,青红椒,青红椒,,Ingredient,,蔬菜,,,,,,,,15,克,False,,,,, +201002355,Ingredient,蒜苗,蒜苗,,Ingredient,,蔬菜,,,,,,,,1,把,False,,,,, +201002356,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,毫升,False,,,,, +201002357,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201002358,Ingredient,生抽酱油,生抽酱油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201002359,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002360,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅烧热,将五花肉皮朝下压紧锅底炙皮,去除汗腺和异味,1.0,炙皮,炒锅,约30秒 +201002361,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用钢丝球刷净猪皮,去除黑色碳化部分,避免苦味,2.0,刷洗,钢丝球,1-2分钟 +201002362,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,五花肉冷水下锅,加姜片、料酒、打结的小葱,大火煮沸后撇沫,继续煮15分钟至筷子可轻松插入瘦肉,3.0,"焯水,煮","锅,筷子",15分钟 +201002363,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,青红椒切圈,蒜苗切段,生姜切薄片;将5ml豆瓣酱与5ml生抽提前混合备用,4.0,切,"刀,案板",3-5分钟 +201002364,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将煮熟的五花肉捞出过冷水后擦干,切成2mm厚的上肥下瘦薄片,5.0,"冷却,切片","刀,案板",2-3分钟 +201002365,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锅烧热后加少量底油滑锅,放入五花肉片煸炒至肥肉透明、肉片微卷呈灯盏窝状,6.0,煸炒,"炒锅,锅铲",1-2分钟 +201002366,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,倒入豆瓣生抽混合物和5g味精,快速翻炒15秒,7.0,炒,锅铲,15秒 +201002367,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入青红椒圈、小姜片及剩余5ml豆瓣酱,翻炒30秒,8.0,炒,锅铲,30秒 +201002368,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,最后加入蒜苗段翻炒60秒后出锅,9.0,炒,锅铲,60秒 +201002369,Recipe,土豆炖排骨,土豆炖排骨,,Recipe,"[{'term': 'potato炖排骨', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋炖排骨', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土豆stewed排骨', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '马铃薯炖排骨', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土豆煲排骨', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,,约15分钟(切配、焯水),约70分钟(煎糖色+炖煮1小时+土豆10分钟),2-3人,"简单,新手友好,下饭",dishes\meat_dish\土豆炖排骨\土豆炖排骨.md,,,,,,,, +201002370,Ingredient,肋排,肋排,,Ingredient,,蛋白质,,,,,,,,750,g,True,,,,, +201002371,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,300,g,True,,,,, +201002372,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201002373,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,25,g,False,,,,, +201002374,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,25,g,False,,,,, +201002375,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201002376,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002377,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201002378,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002379,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002380,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201002381,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201002382,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002383,Ingredient,黄豆酱,黄豆酱,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002384,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,土豆两个滚刀切片,姜片切片,1.0,切,"刀,案板",约5分钟 +201002385,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,排骨 750g 冷水下锅,加入姜片、葱段、料酒焯水 2 分钟,焯干水后捞出清洗干净(一定要用热水,不能用冷水),2.0,"焯水,清洗","锅,漏勺,盆",约5分钟 +201002386,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅凉油,将白糖倒入锅中,翻炒至融化为焦糖色,3.0,炒,"炒锅,锅铲",约1-2分钟 +201002387,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入排骨煎至两面金黄,让排骨裹满焦糖,4.0,煎,"炒锅,锅铲",约3-4分钟 +201002388,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入干辣椒、八角、花椒、桂皮、姜片、10ml 生抽、5ml 老抽、5ml 料酒、5ml 蚝油、5ml 黄豆酱,大火翻炒均匀,5.0,炒,"炒锅,锅铲",约1分钟 +201002389,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,大火翻炒均匀后加入 700ml 开水,大火烧开后转小火焖煮 1 小时,6.0,"炖,焖","炒锅,锅盖",1小时 +201002390,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,最后加入土豆煮 10 分钟就可以出锅啦(喜欢吃青红椒的也可以按自己喜好加入),7.0,煮,"炒锅,锅铲",10分钟 +201002391,Recipe,奶酪培根通心粉,奶酪培根通心粉,,Recipe,,荤菜,3.0,美式,约10分钟(切洋葱、大蒜、培根,磨奶酪),30-34分钟(煮面6分钟+炒酱约5分钟+烘烤24分钟),2人份(1份),"高热量,高脂肪,美式家常菜,简易烤箱菜",dishes\meat_dish\奶酪培根通心粉\奶酪培根通心粉.md,,,,,,,, +201002392,Ingredient,通心粉,通心粉,,Ingredient,,淀粉类,,,,,,,,100-125,g,True,,,,, +201002393,Ingredient,奶酪,奶酪,,Ingredient,,蛋白质,,,,,,,,40-55,g,True,,,,, +201002394,Ingredient,奶酪(烘烤用),奶酪(烘烤用),,Ingredient,,蛋白质,,,,,,,,25,g,False,,,,, +201002395,Ingredient,培根,培根,,Ingredient,,蛋白质,,,,,,,,100-125,g,True,,,,, +201002396,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,25-40,g,False,,,,, +201002397,Ingredient,黄油,黄油,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201002398,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,10,g,False,,,,, +201002399,Ingredient,牛奶,牛奶,,Ingredient,,其他,,,,,,,,125,ml,False,,,,, +201002400,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,0.5,瓣,False,,,,, +201002401,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将奶酪磨成碎末备用,1.0,切,刨丝器,2分钟 +201002402,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,洋葱切成条状,大蒜切碎,2.0,切,"刀,案板",3分钟 +201002403,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,通心粉用微咸的水煮6分钟,3.0,煮,锅,6分钟 +201002404,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,中火加热锅,放入黄油等待融化,4.0,炒,"锅,锅铲",30秒 +201002405,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入洋葱炒至软化,5.0,炒,锅铲,1-2分钟 +201002406,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,洋葱软化后加入大蒜,炒香,6.0,炒,锅铲,30秒 +201002407,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,大蒜香味出来后加入培根,等待5秒,7.0,炒,锅铲,5秒 +201002408,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,转小火,分四次加入牛奶,每次搅拌5秒后再加下一次,8.0,搅拌,锅铲,20秒 +201002409,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入面粉并充分搅拌至无干粉,9.0,搅拌,锅铲,30秒 +201002410,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入奶酪并搅拌均匀成奶酪酱,10.0,搅拌,锅铲,1分钟 +201002411,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将煮好的通心粉倒入奶酪酱中拌匀,11.0,搅拌,锅铲,30秒 +201002412,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,若不烘烤可直接食用;若烘烤则预热烤箱至180°C,12.0,烤,烤箱,5分钟预热 +201002413,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,将额外的25g奶酪铺在通心粉表面,13.0,撒,手,30秒 +201002414,CookingStep,步骤14,步骤14,,CookingStep,,,,,,,,,,,,,放入预热好的烤箱,烤至表面金黄,约24分钟,14.0,烤,烤箱,24分钟 +201002415,Recipe,姜炒鸡,姜炒鸡,,Recipe,,荤菜,3.0,湘菜,30分钟(腌制)+ 切配时间,约7分钟(炒3分钟+焖2分钟+收汁2分钟),2-3人,"下饭,湖南口味,快手菜",dishes\meat_dish\姜炒鸡\姜炒鸡.md,,,,,,,, +201002416,Ingredient,鸡,鸡,,Ingredient,,蛋白质,,,,,,,,650,g,True,,,,, +201002417,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,50,ml,False,,,,, +201002418,Ingredient,生姜,生姜,,Ingredient,,蔬菜,,,,,,,,250,g,True,,,,, +201002419,Ingredient,啤酒,啤酒,,Ingredient,,调料,,,,,,,,250,ml,False,,,,, +201002420,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,ml,False,,,,, +201002421,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201002422,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201002423,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,0-50,g,False,,,,, +201002424,Ingredient,美人辣,美人辣,,Ingredient,,蔬菜,,,,,,,,0-50,g,False,,,,, +201002425,Ingredient,泡椒,泡椒,,Ingredient,,蔬菜,,,,,,,,50,g,False,,,,, +201002426,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,50,g,False,,,,, +201002427,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡尽量剁成1cm的小块,洗净后滤干,再用生抽和料酒腌制30分钟。,1.0,"切,腌制","刀,案板,盆",30分钟 +201002428,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,大火将锅烧至微微冒烟,倒入食用油,等待5秒。,2.0,炒,炒锅,5秒 +201002429,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,下入姜片后转中火炒30秒。,3.0,炒,锅铲,30秒 +201002430,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,下入鸡块翻炒3分钟,炒干水分并炒出鸡油。,4.0,炒,锅铲,3分钟 +201002431,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入剁碎的辣椒和大蒜子,加盐和老抽继续翻炒30秒。,5.0,炒,锅铲,30秒 +201002432,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入啤酒,中小火焖2分钟。,6.0,焖,炒锅,2分钟 +201002433,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,大火收汁后盛盘。,7.0,炒,锅铲,1-2分钟 +201002434,Recipe,姜葱捞鸡,姜葱捞鸡,,Recipe,,荤菜,3.0,粤菜,15分钟,20分钟,2人,"嫩滑爆汁,白饭杀手,简单易做",dishes\meat_dish\姜葱捞鸡\姜葱捞鸡.md,,,,,,,, +201002435,Ingredient,鸡腿,鸡腿,,Ingredient,,蛋白质,,,,,,,,4,个,True,,,,, +201002436,Ingredient,鸡腿,鸡腿,,Ingredient,,蛋白质,,,,,,,,400,克,True,,,,, +201002437,Ingredient,盐焗鸡粉,盐焗鸡粉,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002438,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,50,克,False,,,,, +201002439,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201002440,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002441,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002442,Ingredient,油,油,,Ingredient,,调料,,,,,,,,35,毫升,False,,,,, +201002443,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,四个鸡腿清洗干净,放入碗中,1.0,清洗,碗, +201002444,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,碗中加入盐焗鸡粉和5ml油,搅拌均匀,2.0,搅拌,"碗,筷子或勺子", +201002445,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,让鸡腿静置腌制15分钟,同时准备蒸锅并把水煮开,3.0,腌制,蒸锅,15分钟 +201002446,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,鸡腿腌制完成后,放入水开后的蒸锅中,蒸制20分钟,4.0,蒸,蒸锅,20分钟 +201002447,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将姜根据个人口味切成1)姜蓉或2)姜丝或3)姜粒,5.0,切,"刀,案板", +201002448,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将葱切成0.5cm小段,6.0,切,"刀,案板", +201002449,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将葱姜放入蘸料碗,并加入盐和糖,7.0,混合,碗, +201002450,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将剩余的油倒入另一个锅中加热至六至七层热,8.0,加热,锅, +201002451,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将热油淋入葱姜碗中,9.0,淋油,"锅,碗", +201002452,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,鸡腿蒸好后将其撕碎成鸡丝,不需要特别细,大概1cm粗就可以,10.0,撕,筷子或手, +201002453,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将葱姜油淋在鸡丝上,搅拌均匀即可,11.0,搅拌,"碗,筷子或勺子", +201002454,Recipe,宫保鸡丁,宫保鸡丁,,Recipe,,荤菜,4.0,川菜,1小时10分钟(含腌制1小时),约15分钟,1-2人,"辣椒可去籽减辣,花生微波焙干更脆,葱姜水分次加入更嫩滑",dishes\meat_dish\宫保鸡丁\宫保鸡丁.md,,,,,,,, +201002455,Ingredient,手枪腿,手枪腿,,Ingredient,,蛋白质,,,,,,,,350,g,True,,,,, +201002456,Ingredient,鸡胸脯肉,鸡胸脯肉,,Ingredient,,蛋白质,,,,,,,,350,g,True,,,,, +201002457,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,180,g,True,,,,, +201002458,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002459,Ingredient,二荆条,二荆条,,Ingredient,,蔬菜,,,,,,,,4,支,False,,,,, +201002460,Ingredient,熟花生,熟花生,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201002461,Ingredient,生花生,生花生,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201002462,Ingredient,莴笋,莴笋,,Ingredient,,蔬菜,,,,,,,,250,g,False,,,,, +201002463,Ingredient,姜片,姜片,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201002464,Ingredient,生抽酱油,生抽酱油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002465,Ingredient,老抽酱油,老抽酱油,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002466,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002467,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,g,False,,,,, +201002468,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,g,False,,,,, +201002469,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002470,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002471,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,25,g,False,,,,, +201002472,Ingredient,植物油,植物油,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002473,Ingredient,芝麻油,芝麻油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002474,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002475,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002476,Ingredient,油泼辣子,油泼辣子,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002477,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,手枪腿去骨,用刀背拍松后切成1.5cm见方肉丁,清水浸泡10分钟,捞出控干备用,1.0,"切,腌制","剪刀,刀,碗",10分钟 +201002478,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,大葱绿与5g姜片加50g开水泡成葱姜水;葱白切1.5cm圆粒;花生微波高火5分钟焙干,2.0,"切,加热","刀,微波炉",5分钟 +201002479,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,鸡丁加盐2g、老抽5g、料酒15g、淀粉15g拌匀至发干,再分次加入葱姜水搅至粘手,盖膜冷藏腌1小时,3.0,腌制,"碗,保鲜膜,冰箱",1小时 +201002480,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,干辣椒切段;小火焙干辣椒至微糊,再焙香花椒,分别捞出备用,4.0,"炒,焙","炒锅,锅铲",2-3分钟 +201002481,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,大火热锅倒20g油,7成热下鸡丁煎至表面发白,翻面再煎30秒后翻炒均匀,5.0,"煎,炒","炒锅,锅铲",1-2分钟 +201002482,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入葱粒翻炒,倒入剩余葱姜水(不足100g补热水),盖盖中小火焖2分钟,6.0,"炒,焖","炒锅,锅盖",2分钟 +201002483,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,开盖转大火,加入熟花生、干辣椒、花椒,调入鸡精2g、香醋5g、白糖2g翻炒均匀,7.0,炒,锅铲,30秒 +201002484,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,10g淀粉加50g水调成水淀粉,倒入锅中快速翻炒收汁至理想浓度,8.0,勾芡,锅铲,30秒 +201002485,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,关火淋入芝麻油10g,翻匀即可出锅,9.0,淋油,锅铲,10秒 +201002486,Recipe,小炒鸡肝,小炒鸡肝,,Recipe,,荤菜,3.0,,约15分钟(清洗、切配、焯水准备),约15分钟(焯水5-10分钟+炒制5分钟),2人,"焯水技巧,冰水过冷提升口感,注意水位防溢出",dishes\meat_dish\小炒鸡肝\小炒鸡肝.md,,,,,,,, +201002487,Ingredient,生鸡肝,生鸡肝,,Ingredient,,蛋白质,,,,,,,,800,g,True,,,,, +201002488,Ingredient,蒜苗,蒜苗,,Ingredient,,蔬菜,,,,,,,,200,g,True,,,,, +201002489,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,150,g,False,,,,, +201002490,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,120,g,False,,,,, +201002491,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,ml,False,,,,, +201002492,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002493,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002494,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002495,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002496,Ingredient,烧烤料或孜然粉,烧烤料或孜然粉,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002497,Ingredient,芝麻,芝麻,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002498,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201002499,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡肝清洗,备用,1.0,清洗,盆, +201002500,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,蒜苗清洗,切段,备用,2.0,"清洗,切","刀,案板", +201002501,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大葱清洗,取100g切段,取50g切片,备用,3.0,"清洗,切","刀,案板", +201002502,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,姜清洗,取70g切片,取50g切丁,备用,4.0,"清洗,切","刀,案板", +201002503,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,焯水:清洗后的鸡肝放入锅内,加入凉水淹没鸡肝,并放入100g切段的大葱、70g切片的姜和30ml料酒;开大火,待水沸腾调至中火并撇去浮沫后等待5-10分钟;关火,捞出过凉水并清洗干净;清洗干净后切片,备用,5.0,"焯水,撇沫,过冷水,切","锅,漏勺,刀,案板",5-10分钟 +201002504,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,开中火,锅内加入30ml食用油,等待10秒使油升温,6.0,炒,"锅,锅铲",10秒 +201002505,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入50g切片的大葱和50g切丁的姜,翻炒爆香,7.0,炒,"锅,锅铲", +201002506,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,爆香后加入切片的鸡肝,翻炒至微微发黄,8.0,炒,"锅,锅铲", +201002507,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入蒜苗,翻炒30秒,断生后调至小火,9.0,炒,"锅,锅铲",30秒 +201002508,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入调味料:食用盐5g、鸡精5g、五香粉5g、胡椒粉5g、烧烤料或孜然粉10g(可选),10.0,调味,锅铲, +201002509,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,调至大火,快速翻炒30秒防止糊锅,关火,11.0,炒,"锅,锅铲",30秒 +201002510,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,盛出盘内,可以撒入5g芝麻作为装饰,如果不喜欢或者没有则可以不用添加,12.0,装盘,盘子, +201002511,Recipe,小炒黄牛肉,小炒黄牛肉,,Recipe,,荤菜,4.0,湘菜,约30分钟(切配、腌制),约3分钟(爆香+炒制),1份,"全程大火,爆炒,湘菜,香辣",dishes\meat_dish\小炒黄牛肉\小炒黄牛肉.md,,,,,,,, +201002512,Ingredient,牛里脊,牛里脊,,Ingredient,,蛋白质,,,,,,,,400,g,True,,,,, +201002513,Ingredient,芹菜,芹菜,,Ingredient,,蔬菜,,,,,,,,200,g,True,,,,, +201002514,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201002515,Ingredient,野山椒,野山椒,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201002516,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,30,g,False,,,,, +201002517,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201002518,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,6,ml,False,,,,, +201002519,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,牛里脊切成不超过3cm宽、3mm厚的薄片,倒入6ml酱油,用手抓匀备用,1.0,"切,腌制","刀,案板,盆",约10分钟 +201002520,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,芹菜切成不超过5cm的小段,备用,2.0,切,"刀,案板",约5分钟 +201002521,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,小米椒切成丝状,备用,3.0,切,"刀,案板",约2分钟 +201002522,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,野山椒切成颗粒,备用,4.0,切,"刀,案板",约2分钟 +201002523,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,香菜切成不超过3cm的小段,备用,5.0,切,"刀,案板",约2分钟 +201002524,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,热锅,锅内放入15ml食用油,大火等待30秒让油温升高,6.0,"热锅,加热",炒锅,30秒 +201002525,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入小米椒和野山椒爆香,7.0,"爆香,炒",锅铲,约30秒 +201002526,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入牛里脊和芹菜,然后大火翻炒1分钟,8.0,炒,锅铲,1分钟 +201002527,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,关火,撒上香菜,盛盘,9.0,装盘,锅铲,约10秒 +201002528,Recipe,尖叫牛蛙,尖叫牛蛙,,Recipe,,荤菜,4.0,川菜,20-25分钟(含清洗、腌制、切配),8-10分钟(含过油、炒制、焖煮、收汁),1份,"控干水分可用漏勺按压,生粉需均匀覆盖蛙肉",dishes\meat_dish\尖叫牛蛙\尖叫牛蛙.md,,,,,,,, +201002529,Ingredient,牛蛙肉块,牛蛙肉块,,Ingredient,,蛋白质,,,,,,,,800,克,True,,,,, +201002530,Ingredient,泡姜,泡姜,,Ingredient,,蔬菜,,,,,,,,25,克,False,,,,, +201002531,Ingredient,泡椒,泡椒,,Ingredient,,蔬菜,,,,,,,,7.5,克,False,,,,, +201002532,Ingredient,野山椒,野山椒,,Ingredient,,蔬菜,,,,,,,,10,克,False,,,,, +201002533,Ingredient,青红辣椒,青红辣椒,,Ingredient,,蔬菜,,,,,,,,20,克,False,,,,, +201002534,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,40,克,False,,,,, +201002535,Ingredient,郫县豆瓣酱,郫县豆瓣酱,,Ingredient,,调料,,,,,,,,25,克,False,,,,, +201002536,Ingredient,盐巴,盐巴,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201002537,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201002538,Ingredient,生粉,生粉,,Ingredient,,淀粉类,,,,,,,,30,克,False,,,,, +201002539,Ingredient,啤酒,啤酒,,Ingredient,,调料,,,,,,,,450,毫升,False,,,,, +201002540,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,毫升,False,,,,, +201002541,Ingredient,藤椒油,藤椒油,,Ingredient,,调料,,,,,,,,7.5,毫升,False,,,,, +201002542,Ingredient,猪油,猪油,,Ingredient,,其他,,,,,,,,20,毫升,False,,,,, +201002543,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,200,毫升,False,,,,, +201002544,Ingredient,葱花,葱花,,Ingredient,,蔬菜,,,,,,,,5,克,False,,,,, +201002545,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,牛蛙肉洗净控干水分,加入10克以上盐巴和50毫升以上啤酒,用手抓5分钟去腥,1.0,"清洗,腌制",盆,5分钟 +201002546,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用清水冲洗至无血水杂质,再次控干水分备用,2.0,清洗,漏勺,2-3分钟 +201002547,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入5克盐、30克生粉、10毫升料酒、5克胡椒粉,抓匀腌制5-10分钟,3.0,腌制,盆,5-10分钟 +201002548,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,泡姜、泡椒、野山椒切丝或片,青红辣椒切圈,大蒜剥皮,4.0,切,"刀,案板",5分钟 +201002549,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中倒入200毫升食用油,烧至6成热,下牛蛙快速过油炸10秒后捞出控油,5.0,炸,"炒锅,漏勺",10秒 +201002550,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒出多余热油,锅中留30毫升底油,加入20毫升猪油(或再补20毫升食用油),6.0,倒油,炒锅,30秒 +201002551,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,油温6成热,下泡姜、泡椒、野山椒、大蒜炒香,加20克豆瓣酱炒出红油约30秒,7.0,炒,锅铲,30秒 +201002552,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入400毫升啤酒,加入炸好的牛蛙,轻推翻匀,加5克胡椒粉、5毫升藤椒油,中火焖3分钟,8.0,焖,锅铲,3分钟 +201002553,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,大火收汁30秒,加入青红辣椒圈再煮10秒,9.0,"炒,收汁",锅铲,40秒 +201002554,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,出锅装盘,撒上葱花即可,10.0,装盘,盆,10秒 +201002555,Recipe,巴基斯坦牛肉咖喱,巴基斯坦牛肉咖喱,,Recipe,,荤菜,5.0,巴基斯坦菜,约15分钟,2-3小时,5人,"巴基斯坦风味,偏辣,慢炖,配烙饼/馕/米饭,正宗做法",dishes\meat_dish\巴基斯坦牛肉咖喱\巴基斯坦牛肉咖喱.md,,,,,,,, +201002556,Ingredient,牛肉,牛肉,,Ingredient,,蛋白质,,,,,,,,1000,克,True,,,,, +201002557,Ingredient,番茄,番茄,,Ingredient,,蔬菜,,,,,,,,4,个,False,,,,, +201002558,Ingredient,螺丝椒,螺丝椒,,Ingredient,,蔬菜,,,,,,,,2,个,False,,,,, +201002559,Ingredient,原味酸奶,原味酸奶,,Ingredient,,蛋白质,,,,,,,,1,盒,False,,,,, +201002560,Ingredient,Masala粉,Masala粉,,Ingredient,,调料,,,,,,,,50,克,False,,,,, +201002561,Ingredient,蒜粉,蒜粉,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002562,Ingredient,姜粉,姜粉,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002563,Ingredient,水,水,,Ingredient,,其他,,,,,,,,250,毫升,False,,,,, +201002564,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,适量,毫升,False,,,,, +201002565,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,全部螺丝椒切成段状,备用,1.0,切,"刀,案板",约2分钟 +201002566,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,全部番茄打成番茄蓉,备用,2.0,"切,搅拌","刀,案板,搅拌机",约3分钟 +201002567,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,牛肉切成2cm的小块,洗净备用,3.0,"切,洗","刀,案板,盆",约5分钟 +201002568,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,炒锅中倒入一层油(用来防止番茄蓉沸腾蒸发),4.0,倒油,炒锅,约30秒 +201002569,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,倒入番茄蓉,持续搅拌2-3分钟,等待它越变越红,5.0,"炒,搅拌","炒锅,锅铲",2-3分钟 +201002570,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入5g蒜粉、5g姜粉和1包50g的Masala粉,搅拌均匀,6.0,"炒,搅拌","炒锅,锅铲",约1分钟 +201002571,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入牛肉和螺丝椒段,搅拌均匀,7.0,"炒,搅拌","炒锅,锅铲",约1分钟 +201002572,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入1盒酸奶(为了让整个酱汁变得粘稠),搅拌均匀,8.0,搅拌,"炒锅,锅铲",约30秒 +201002573,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将整锅材料转移到电饭煲/电炖锅,并加入250 ml的水,开启炖肉/慢炖档,设定时间2-3个小时,9.0,"炖,转移","电饭煲,电炖锅",2-3小时 +201002574,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,等待完成,开锅检查牛肉软糯,就可以吃了,10.0,"检查,装盘","电饭煲,筷子",约1分钟 +201002575,Recipe,干煸仔鸡,干煸仔鸡,,Recipe,,荤菜,4.0,川菜,30分钟(腌制)+ 切配时间,约15分钟(油炸+炒制),1-2人,"可改用少量油煎鸡块和土豆块,甜辣口味,疫情居家下饭必备",dishes\meat_dish\干煸仔鸡\干煸仔鸡.md,,,,,,,, +201002576,Ingredient,鸡腿肉,鸡腿肉,,Ingredient,,蛋白质,,,,,,,,400,g,True,,,,, +201002577,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,200,g,True,,,,, +201002578,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,60,g,True,,,,, +201002579,Ingredient,蒜瓣,蒜瓣,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201002580,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201002581,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201002582,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002583,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201002584,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,g,False,,,,, +201002585,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201002586,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,20,g,False,,,,, +201002587,Ingredient,郫县红油豆瓣酱,郫县红油豆瓣酱,,Ingredient,,调料,,,,,,,,40,g,False,,,,, +201002588,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,g,False,,,,, +201002589,Ingredient,花椒碎,花椒碎,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002590,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,宽油,ml,False,,,,, +201002591,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡腿去骨(如使用鸡腿排可忽略此步骤),鸡腿肉用刀背砸一砸,切成 2cm 的块。,1.0,"切,去骨","刀,案板", +201002592,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鸡腿肉中加入盐、鸡精(可选)、胡椒粉、生抽、老抽、料酒,抓拌至粘手时加入淀粉拌匀,加入食用油防止粘连,腌制 30 分钟。,2.0,"腌制,抓拌","盆,筷子",30分钟 +201002593,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,土豆去皮,切成 2cm 的块,沸水煮 5 分钟后捞出,控干水分,防止油炸时爆锅。,3.0,"切,煮","刀,案板,锅,笊篱",5分钟 +201002594,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,青椒去籽,切成 2cm 小片,放在笊篱中备用。,4.0,"切,去籽","刀,案板,笊篱", +201002595,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中加入宽油(根据锅的形状,能没过食材即可),油温烧至 180℃ 时,下入土豆块炸 3 分钟后捞出。,5.0,炸,"锅,笊篱",3分钟 +201002596,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,待油温再次升高到 180℃时,下入鸡块炸 2 分钟后捞出。,6.0,炸,"锅,笊篱",2分钟 +201002597,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,待油温再次升高到 180℃时,下入鸡块复炸 1 分钟后捞出。,7.0,炸,"锅,笊篱",1分钟 +201002598,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,待油温再次升高到 180℃时,下入土豆块复炸 1 分钟后,将锅中的油和土豆块经过笊篱过滤倒出,让笊篱上的青椒片断生。,8.0,"炸,过滤","锅,笊篱",1分钟 +201002599,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,锅中加入 5ml 食用油,小火煸炒蒜瓣至发黄,下入红油豆瓣酱煸炒出香,下入白糖炒融化,下入花椒碎,加 40ml 清水,不停搅拌至酱汁粘稠。,9.0,"炒,煸炒,搅拌","锅,锅铲", +201002600,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,下入炸好的鸡块、土豆块、青椒片,搅拌均匀后出锅。,10.0,"炒,搅拌","锅,锅铲", +201002601,Recipe,广式萝卜牛腩,广式萝卜牛腩,,Recipe,"[{'term': '广式radish牛腩', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '广式胡萝卜牛腩', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '广式白萝卜牛腩', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,4.0,粤菜,约15分钟,约2.5小时,3-4人,"汤汁浓郁,营养丰富,增食欲",dishes\meat_dish\广式萝卜牛腩\广式萝卜牛腩.md,,,,,,,, +201002602,Ingredient,牛腩,牛腩,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201002603,Ingredient,白萝卜,白萝卜,,Ingredient,,蔬菜,,,,,,,,1,根,True,,,,, +201002604,Ingredient,姜片,姜片,,Ingredient,,蔬菜,,,,,,,,8,片,False,,,,, +201002605,Ingredient,蒜瓣,蒜瓣,,Ingredient,,蔬菜,,,,,,,,5,片,False,,,,, +201002606,Ingredient,葱结,葱结,,Ingredient,,蔬菜,,,,,,,,1,把,False,,,,, +201002607,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,片,False,,,,, +201002608,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,1,小块,False,,,,, +201002609,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,2,个,False,,,,, +201002610,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002611,Ingredient,南乳,南乳,,Ingredient,,调料,,,,,,,,1,块,False,,,,, +201002612,Ingredient,柱侯酱,柱侯酱,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201002613,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201002614,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201002615,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201002616,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002617,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,g,False,,,,, +201002618,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,萝卜滚刀切块备用,1.0,切,"刀,案板",约3分钟 +201002619,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,牛腩整块焯水,加入2片姜和一把葱结,等水开之后煮5-10分钟,然后捞出切件,2.0,"焯水,煮","锅,刀,案板",5-10分钟 +201002620,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将牛腩切块,切成自己喜欢的大小,3.0,切,"刀,案板",约2分钟 +201002621,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,准备焖牛腩的酱料,将南乳、柱侯酱、酱油、蚝油、糖、盐按上面的量调和,4.0,"混合,调酱","碗,勺子",约2分钟 +201002622,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅下油,将姜蒜爆香,放入牛腩,炒至干身,加入调好的酱料,炒香,如果喜欢色泽浓一点的可以加一点老抽润色,5.0,"炒,爆香","炒锅,锅铲",约5分钟 +201002623,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,调料充分混合之后倒入热水,6.0,加汤,锅,约30秒 +201002624,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将牛腩换到汤锅中,放入桂皮、八角、香叶和干辣椒,焖大概2个小时,7.0,"焖,炖",汤锅,约2小时 +201002625,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,牛腩焖到半软之后加入白萝卜继续焖30分钟,8.0,焖,汤锅,30分钟 +201002626,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,等到萝卜焖软之后就完成,一锅浓香的萝卜牛腩就完成了,9.0,焖,汤锅,约5分钟 +201002627,Recipe,徽派红烧肉,徽派红烧肉,,Recipe,"[{'term': '徽派braised肉', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,4.0,徽菜,约5分钟(切肉、备料),约35分钟,1份,"葱整根不切碎,步骤二加盐可锁住油脂,未水煮的五花肉更Q弹",dishes\meat_dish\徽派红烧肉\徽派红烧肉.md,,,,,,,, +201002628,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201002629,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,100,g,False,,,,, +201002630,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,200,g,False,,,,, +201002631,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201002632,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201002633,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201002634,Ingredient,姜片,姜片,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002635,Ingredient,蒜头,蒜头,,Ingredient,,调料,,,,,,,,3,颗,False,,,,, +201002636,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,100,ml,False,,,,, +201002637,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201002638,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002639,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002640,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,五花肉切块,每块2-3 cm大小,1.0,切,"刀,案板",约2分钟 +201002641,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中加入150 ml食用油,倒入五花肉,煎炸2分钟后,加入盐,翻炒五花肉,2分钟后出锅,2.0,"炸,炒","炒锅,锅铲",4分钟 +201002642,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中加入50 ml食用油,倒入白砂糖,翻炒到咖啡色,3.0,炒,"炒锅,锅铲",约2分钟 +201002643,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入五花肉,翻炒30秒后,加入姜片、蒜头后翻炒30秒,4.0,炒,"炒锅,锅铲",1分钟 +201002644,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入料酒、五香粉、葱,加入水没过五花肉,盖上锅盖煮10分钟,5.0,煮,"炒锅,锅盖",10分钟 +201002645,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入生抽、老抽、蚝油,中火煮20分钟,6.0,煮,炒锅,20分钟 +201002646,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,开锅,大火烧汁,端盘,7.0,烧汁,炒锅,约2分钟 +201002647,Recipe,新疆大盘鸡,新疆大盘鸡,,Recipe,,荤菜,4.0,西北菜,约15分钟(浸泡、切配),约40-50分钟(炒糖色、炖煮、收汁),2人,"可配皮带面,西北风味,炒糖色,慢炖入味",dishes\meat_dish\新疆大盘鸡\新疆大盘鸡.md,,,,,,,, +201002648,Ingredient,鸡腿肉,鸡腿肉,,Ingredient,,蛋白质,,,,,,,,1000,g,True,,,,, +201002649,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,750,g,True,,,,, +201002650,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,100,g,False,,,,, +201002651,Ingredient,菜椒,菜椒,,Ingredient,,蔬菜,,,,,,,,50,g,False,,,,, +201002652,Ingredient,甜椒,甜椒,,Ingredient,,蔬菜,,,,,,,,50,g,False,,,,, +201002653,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002654,Ingredient,干线椒,干线椒,,Ingredient,,调料,,,,,,,,5,个,False,,,,, +201002655,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,4,瓣,False,,,,, +201002656,Ingredient,油,油,,Ingredient,,调料,,,,,,,,50,g,False,,,,, +201002657,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002658,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,7,ml,False,,,,, +201002659,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002660,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,100,g,False,,,,, +201002661,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,1000,ml,False,,,,, +201002662,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201002663,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,适量,片,False,,,,, +201002664,Ingredient,香果,香果,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201002665,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将鸡腿肉剁成块状,用清水加盐浸泡5分钟去除血水与腥味,然后沥干备用。,1.0,"切,浸泡","刀,盆",5分钟 +201002666,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱、蒜、干线椒、土豆等洗净;土豆削皮。,2.0,"清洗,削皮","刀,案板",3-5分钟 +201002667,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,葱白切成长约4cm的段;菜椒、甜椒切块;土豆切成4cm×4cm滚刀块。,3.0,切,"刀,案板",5分钟 +201002668,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅中倒入油,加入白砂糖,小火炒糖色至焦黄色,立即倒入沥干鸡肉翻炒上色。,4.0,炒,"炒锅,锅铲",2-3分钟 +201002669,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入花椒、香叶、香果、干线椒等香料继续翻炒出香味。,5.0,炒,锅铲,1分钟 +201002670,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入5g盐、7ml生抽、10g蚝油、100g料酒(或啤酒)和1升清水,中火煮沸后转小火慢炖。,6.0,炖,锅铲,20分钟 +201002671,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,汤汁收至鸡肉即将露出时,将土豆块铺在表面,不翻动,盖盖继续炖。,7.0,炖,锅盖,10分钟 +201002672,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入大葱段、菜椒和甜椒块,继续炖至汤汁浓稠,最后翻面让土豆吸汁,关火盛出。,8.0,"炖,收汁",锅铲,5-10分钟 +201002673,Recipe,无骨鸡爪,无骨鸡爪,,Recipe,,荤菜,5.0,,约2小时(去骨)+ 6小时(腌制),10分钟(焯水),2-3人,"酸辣开胃,Q弹爽口,去骨技巧,冷藏腌制,注意水位线",dishes\meat_dish\无骨鸡爪\无骨鸡爪.md,,,,,,,, +201002674,Ingredient,鸡爪,鸡爪,,Ingredient,,蛋白质,,,,,,,,1000,g,True,,,,, +201002675,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,4,片,False,,,,, +201002676,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,65,g,False,,,,, +201002677,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,3,段,False,,,,, +201002678,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,10,瓣,False,,,,, +201002679,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,12,个,False,,,,, +201002680,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,0.5,个,False,,,,, +201002681,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,75,g,False,,,,, +201002682,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201002683,Ingredient,黑醋,黑醋,,Ingredient,,调料,,,,,,,,50,g,False,,,,, +201002684,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201002685,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201002686,Ingredient,花椒油,花椒油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201002687,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,3,颗,False,,,,, +201002688,Ingredient,柠檬,柠檬,,Ingredient,,蔬菜,,,,,,,,2,颗,False,,,,, +201002689,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,用剪刀或刀剪掉鸡爪指甲及下方骨肉,确保无指甲残留,然后洗净备用。,1.0,切,"剪刀,刀", +201002690,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将鸡爪、大葱、料酒、姜放入锅中,加水没过鸡爪,大火煮开并捞去浮沫。,2.0,煮,"锅,筷子",水开后煮10分钟 +201002691,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,关火后捞出鸡爪,沥干水分并洗净,放入盆中备用。,3.0,"捞,沥水","漏勺,盆", +201002692,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将鸡爪放入冷冻层冷冻20分钟,再分批(每批10个)取出去骨。,4.0,冷冻,"冰箱,刀",约2小时 +201002693,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,从鸡爪手指前端划开至手背,再从手背划开至手臂,掰动关节后推挤脱骨,完成所有鸡爪。,5.0,"切,掰",刀, +201002694,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,小米辣切小粒,大蒜、洋葱、香菜切碎,柠檬对半挤汁。,6.0,"切,挤汁","刀,案板", +201002695,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将鸡爪、全部调料、小米辣、大蒜、洋葱、香菜、柠檬汁一起放入容器,抓拌均匀。,7.0,"拌,腌制",盆, +201002696,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将拌好的鸡爪放入冰箱冷藏腌制一晚(6小时)即可食用。,8.0,腌制,冰箱,6小时 +201002697,Recipe,枝竹羊腩煲,枝竹羊腩煲,,Recipe,,荤菜,5.0,粤菜,约3小时(含香菇、腐竹浸泡),约2小时10分钟,1份,"冬季暖胃,肥而不腻,可替换配菜,正宗做法可加马蹄",dishes\meat_dish\枝竹羊腩煲\枝竹羊腩煲.md,,,,,,,, +201002698,Ingredient,羊腩,羊腩,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201002699,Ingredient,炸腐竹,炸腐竹,,Ingredient,,蛋白质,,,,,,,,30,g,True,,,,, +201002700,Ingredient,柱侯酱,柱侯酱,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201002701,Ingredient,腐乳,腐乳,,Ingredient,,调料,,,,,,,,40,g,False,,,,, +201002702,Ingredient,南乳,南乳,,Ingredient,,调料,,,,,,,,35,g,False,,,,, +201002703,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201002704,Ingredient,辣椒油,辣椒油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201002705,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,500,ml,False,,,,, +201002706,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,g,False,,,,, +201002707,Ingredient,砂糖,砂糖,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002708,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,5,根,False,,,,, +201002709,Ingredient,姜片,姜片,,Ingredient,,蔬菜,,,,,,,,7,片,False,,,,, +201002710,Ingredient,香菇,香菇,,Ingredient,,蔬菜,,,,,,,,7.5,个,False,,,,, +201002711,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201002712,Ingredient,蒜瓣,蒜瓣,,Ingredient,,蔬菜,,,,,,,,7.5,瓣,False,,,,, +201002713,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,1,片,False,,,,, +201002714,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,4.5,个,False,,,,, +201002715,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002716,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,香菇提前浸泡2-3小时至变软,1.0,浸泡,盆,2-3小时 +201002717,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,腐竹提前浸泡30分钟至变软,2.0,浸泡,盆,30分钟 +201002718,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将南乳、柱侯酱、20g腐乳、老抽放入小碗搅拌均匀制成酱汁1,3.0,搅拌,"小碗,筷子",1分钟 +201002719,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将20g腐乳、砂糖、辣椒油放入小碗搅拌均匀制成酱汁2,4.0,搅拌,"小碗,筷子",1分钟 +201002720,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,泡好的香菇去除根部,5.0,切,"刀,案板",2分钟 +201002721,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,泡好的腐竹切成5cm小段并挤干水分,6.0,"切,挤干","刀,案板",3分钟 +201002722,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,洋葱去皮切丝;小葱切成5cm葱段,7.0,切,"刀,案板",3分钟 +201002723,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,羊腩冷水下锅,加入2-3片姜片,大火煮至水滚后关火,8.0,焯水,"锅,筷子",5分钟 +201002724,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,捞出羊腩放入冷水盆中放凉,使其更有嚼劲,9.0,冷却,盆,2分钟 +201002725,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,锅烧热后倒冷油,爆香姜片、洋葱、葱白段、蒜瓣,10.0,"炒,爆香","锅,锅铲",1分钟 +201002726,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,放入冷却好的羊腩,用筷子翻炒2-5分钟至表面金黄,11.0,炒,"锅,筷子",2-5分钟 +201002727,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,加入酱汁1,翻炒约2分钟至颜色均匀,12.0,炒,锅铲,2分钟 +201002728,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,倒入清水至刚好没过食材,13.0,加汤,锅,10秒 +201002729,CookingStep,步骤14,步骤14,,CookingStep,,,,,,,,,,,,,加入香菇、冰糖、香叶、八角、桂皮,加盖转小火炖90分钟,14.0,炖,锅,90分钟 +201002730,CookingStep,步骤15,步骤15,,CookingStep,,,,,,,,,,,,,开盖加入腐竹,加盖转中火煮20分钟,15.0,煮,锅,20分钟 +201002731,CookingStep,步骤16,步骤16,,CookingStep,,,,,,,,,,,,,开盖加入酱汁2搅拌均匀,16.0,搅拌,锅铲,30秒 +201002732,CookingStep,步骤17,步骤17,,CookingStep,,,,,,,,,,,,,关火,出锅前加入葱绿段或香菜,17.0,出锅,锅铲,10秒 +201002733,Recipe,柱候牛腩,柱候牛腩,,Recipe,,荤菜,4.0,粤菜,20分钟,高压锅40分钟或普通锅3小时,2人,"高压锅可缩短时间,注意安全操作高压锅,可搭配萝卜土豆",dishes\meat_dish\柱候牛腩\柱候牛腩.md,,,,,,,, +201002734,Ingredient,牛腩,牛腩,,Ingredient,,蛋白质,,,,,,,,550,g,True,,,,, +201002735,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201002736,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,0.5,头,False,,,,, +201002737,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,1,条,False,,,,, +201002738,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002739,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,0.5,g,False,,,,, +201002740,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,个,False,,,,, +201002741,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,3,个,False,,,,, +201002742,Ingredient,丁香,丁香,,Ingredient,,调料,,,,,,,,3,个,False,,,,, +201002743,Ingredient,甘草,甘草,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002744,Ingredient,南腐乳,南腐乳,,Ingredient,,调料,,,,,,,,2,块,False,,,,, +201002745,Ingredient,郫县豆瓣酱,郫县豆瓣酱,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201002746,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201002747,Ingredient,花雕酒,花雕酒,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002748,Ingredient,白酒,白酒,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002749,Ingredient,柱候酱,柱候酱,,Ingredient,,调料,,,,,,,,50,g,False,,,,, +201002750,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002751,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201002752,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,60,g,False,,,,, +201002753,Ingredient,叉烧酱,叉烧酱,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002754,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将姜切成1.5cm×1.5cm小块,蒜剥皮,小米辣切1cm小段,分装碗1。,1.0,切,"刀,案板,碗",5分钟 +201002755,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将香叶、花椒、八角、干辣椒、丁香、甘草放入碗2。,2.0,分装,碗,1分钟 +201002756,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将南腐乳放入碗3。,3.0,分装,碗,30秒 +201002757,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将郫县豆瓣酱放入碗4。,4.0,分装,碗,30秒 +201002758,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将冰糖放入碗5。,5.0,分装,碗,30秒 +201002759,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将花雕酒10g和白酒10g倒入碗6。,6.0,分装,碗,30秒 +201002760,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将柱候酱、蚝油、叉烧酱、老抽、生抽混合入碗7。,7.0,混合,碗,1分钟 +201002761,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,牛腩整块冷水下锅,大火焯水,水沸后捞出。,8.0,焯水,锅,3-5分钟 +201002762,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,冲洗牛腩表面杂质,切成4cm×4cm×4cm大块,控干备用。,9.0,切,"刀,案板,盆",5分钟 +201002763,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,大火热锅下油,倒入碗1(姜蒜小米辣)炒香。,10.0,炒,"炒锅,锅铲",30秒 +201002764,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,中小火倒入碗2香料,翻炒约30秒。,11.0,炒,"炒锅,锅铲",30秒 +201002765,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,中小火加入碗3南乳,用锅铲压碎炒匀。,12.0,"炒,压碎","炒锅,锅铲",30秒 +201002766,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,中小火加入碗4豆瓣酱,翻炒约30秒。,13.0,炒,"炒锅,锅铲",30秒 +201002767,CookingStep,步骤14,步骤14,,CookingStep,,,,,,,,,,,,,中小火加入碗5冰糖,炒至融化。,14.0,炒,"炒锅,锅铲",1分钟 +201002768,CookingStep,步骤15,步骤15,,CookingStep,,,,,,,,,,,,,中小火加入牛腩,炒至牛肉上色。,15.0,炒,"炒锅,锅铲",2-3分钟 +201002769,CookingStep,步骤16,步骤16,,CookingStep,,,,,,,,,,,,,大火沿锅边淋入碗6的酒,快速翻炒至牛肉表面略焦褐。,16.0,"炒,淋酒","炒锅,锅铲",1分钟 +201002770,CookingStep,步骤17,步骤17,,CookingStep,,,,,,,,,,,,,倒入碗7酱料,快速翻炒至冒小泡、汤汁略浓稠。,17.0,炒,"炒锅,锅铲",1-2分钟 +201002771,CookingStep,步骤18,步骤18,,CookingStep,,,,,,,,,,,,,将锅内食材转移至炖煮锅或高压锅,加水没过食材。,18.0,"转移,加水",炖煮锅/高压锅,1分钟 +201002772,CookingStep,步骤19,步骤19,,CookingStep,,,,,,,,,,,,,普通锅小火炖3小时,或高压锅压40分钟。,19.0,"炖,压",炖煮锅/高压锅,40分钟-3小时 +201002773,CookingStep,步骤20,步骤20,,CookingStep,,,,,,,,,,,,,开盖后尝味,根据需要加盐或糖调味。,20.0,调味,勺,2分钟 +201002774,CookingStep,步骤21,步骤21,,CookingStep,,,,,,,,,,,,,捞出牛腩;如需加萝卜或土豆,削皮切2cm厚片煮10-15分钟(高压锅再压5分钟)。,21.0,煮,锅,10-15分钟 +201002775,CookingStep,步骤22,步骤22,,CookingStep,,,,,,,,,,,,,将汤汁过滤后淋入碗中,与牛腩、配菜一起上桌。,22.0,过滤,"滤网,碗",2分钟 +201002776,Recipe,梅菜扣肉,梅菜扣肉,,Recipe,,荤菜,4.0,粤菜,1小时15分钟(含梅菜浸泡1小时、腌制15分钟),约1小时10分钟(煮20分钟+炸3-5分钟+炒梅菜+蒸45分钟),1人份,"可去糖减甜,梅菜需炒干吸油,蒸制时间可按喜好调整",dishes\meat_dish\梅菜扣肉\梅菜扣肉.md,,,,,,,, +201002777,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201002778,Ingredient,梅菜,梅菜,,Ingredient,,蔬菜,,,,,,,,30,g,True,,,,, +201002779,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002780,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,300,ml,False,,,,, +201002781,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002782,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,ml,False,,,,, +201002783,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,ml,False,,,,, +201002784,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201002785,Ingredient,蒜末,蒜末,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201002786,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002787,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002788,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,梅菜放到清水中,浸泡1小时,1.0,浸泡,碗,1小时 +201002789,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中倒入50 ml食用油,将整个五花肉猪皮朝下,放到锅中1分钟,取出刮掉猪皮(可选),2.0,煎,炒锅,1分钟 +201002790,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中加入开水,放入五花肉,大火煮20分钟(筷子可以插进五花肉),取出五花肉,3.0,煮,锅,20分钟 +201002791,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,在五花肉表面涂抹均匀老抽、五香粉、白砂糖,放置15分钟,4.0,腌制,碗,15分钟 +201002792,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,起锅烧油,加入五花肉,中火油炸直至两面金黄色(3-5分钟),5.0,炸,炒锅,3-5分钟 +201002793,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,起锅烧油,倒入梅菜,加上小米椒、蒜蓉、鸡精、食用盐后翻炒,直至炒干梅干菜水分,6.0,炒,"炒锅,锅铲",约5分钟 +201002794,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,五花肉切片(厚度0.5-1 cm),放在大碗中,撒上梅干菜,7.0,切,"刀,案板,碗",2分钟 +201002795,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,中火蒸45分钟,8.0,蒸,蒸锅,45分钟 +201002796,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,拿个盘子倒盖在五花肉大碗中,将五花肉倒在盘子中,9.0,倒扣,"盘子,碗",1分钟 +201002797,Recipe,水煮牛肉,水煮牛肉,,Recipe,,荤菜,3.0,川菜,20分钟(含15分钟腌制),10分钟,2人,"麻辣鲜香,川菜经典",dishes\meat_dish\水煮牛肉\水煮牛肉.md,,,,,,,, +201002798,Ingredient,牛肉,牛肉,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201002799,Ingredient,豆芽,豆芽,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201002800,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201002801,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,5,根,False,,,,, +201002802,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002803,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201002804,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,15,g,False,,,,, +201002805,Ingredient,干辣椒粉,干辣椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002806,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002807,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,3,瓣,False,,,,, +201002808,Ingredient,红辣椒,红辣椒,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201002809,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,8,g,False,,,,, +201002810,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,牛肉洗干净切片,1.0,切,"刀,案板",约2分钟 +201002811,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入15g姜丝、1个鸡蛋、15g淀粉、8g蚝油、10ml料酒搅拌均匀,腌制15分钟,2.0,"腌制,搅拌","盆,筷子",15分钟 +201002812,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,香菜洗干净切好,3.0,切,"刀,案板",约1分钟 +201002813,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅里倒油,加入豆瓣酱、5g姜丝、蒜片炒香,4.0,炒,"炒锅,锅铲",约1分钟 +201002814,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,倒入开水,煮成红汤,5.0,煮,炒锅,约2分钟 +201002815,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,豆芽洗干净去掉尾须,放进开水里焯熟,6.0,焯,"锅,漏勺",约1分钟 +201002816,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将豆芽铺入碗底,7.0,摆盘,碗,约30秒 +201002817,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将牛肉片一片一片放进红汤中,煮熟后捞出,8.0,煮,"锅,筷子",约2-3分钟 +201002818,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将牛肉铺在豆芽上,撒上香菜梗,9.0,摆盘,碗,约30秒 +201002819,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,撒上香菜叶、辣椒粉、辣椒圈,10.0,摆盘,碗,约30秒 +201002820,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,另起锅烧热油,将热油淋在菜上面,完成,11.0,淋油,"锅,勺",约30秒 +201002821,Recipe,清蒸鳜鱼,清蒸鳜鱼,,Recipe,"[{'term': '清清蒸鳜鱼', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '清steamed鳜鱼', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,,约15分钟,8-10分钟,2人份,"鳜鱼背部鱼鳍易伤人,处理时需小心,建议剪掉,蒸制时间需根据鱼大小调整,水多汽大火足是关键",dishes\meat_dish\清蒸鳜鱼\清蒸鳜鱼.md,,,,,,,, +201002822,Ingredient,鳜鱼,鳜鱼,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201002823,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,节,False,,,,, +201002824,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,根,False,,,,, +201002825,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,g,False,,,,, +201002826,Ingredient,红辣椒,红辣椒,,Ingredient,,蔬菜,,,,,,,,1,颗,False,,,,, +201002827,Ingredient,姜片,姜片,,Ingredient,,调料,,,,,,,,3,片,False,,,,, +201002828,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201002829,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鳜鱼从腹部切开,去除鱼鳃和内脏,打去鱼鳞,用刀在表皮上刮去粘液(可让摊主代劳),1.0,"切,清理",刀, +201002830,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鳜鱼身上打上花刀,放姜片,可放少许猪油,装盘并在下面垫筷子以便受热均匀,2.0,"切,摆盘","刀,筷子", +201002831,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大葱划开后去除中间的芯,只保留外面两层;小葱划开备用;红椒去籽去肉备用,3.0,切,刀, +201002832,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将大葱、小葱、辣椒码在一起切成丝,泡在水里备用,4.0,切,刀, +201002833,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中加大量水,水热后放入鳜鱼,盖上锅盖,大火蒸8-10分钟,5.0,蒸,"蒸锅,锅盖",8-10分钟 +201002834,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,蒸鱼期间另起一锅烧热油至冒烟,6.0,加热,锅, +201002835,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,蒸好后倒掉蒸鱼的水,去除姜片,放上葱丝,浇上热油,7.0,"倒,淋","锅,筷子", +201002836,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入生抽或蒸鱼豉油即可上桌,8.0,淋,, +201002837,Recipe,湖南家常红烧肉,湖南家常红烧肉,,Recipe,"[{'term': '湖南家常braised肉', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,湘菜,约10分钟,约45分钟,2人,"肥而不腻,入口软糯,锁油上色",dishes\meat_dish\湖南家常红烧肉\湖南家常红烧肉.md,,,,,,,, +201002838,Ingredient,带皮五花肉,带皮五花肉,,Ingredient,,蛋白质,,,,,,,,500,g,True,,,,, +201002839,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002840,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,5,片,False,,,,, +201002841,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,3,片,False,,,,, +201002842,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,1,小块,False,,,,, +201002843,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,6,颗,False,,,,, +201002844,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,g,False,,,,, +201002845,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201002846,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,g,False,,,,, +201002847,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002848,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,颗,False,,,,, +201002849,Ingredient,干小米椒,干小米椒,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201002850,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,没过肉,,False,,,,, +201002851,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,带皮五花肉洗净冷水下锅,加入姜片2~3片去腥味,煮到沸腾捞出冷水冲净白沫,1.0,煮,"锅,刀",至沸腾 +201002852,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,五花肉切块,尺寸1.5cm×1.5cm块状大小,2.0,切,"刀,案板",约3分钟 +201002853,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅加入油,加入冰糖小火搅拌至焦糖色即可,加入切好的五花肉,中火翻炒上色,3.0,"炒,炒糖色","炒锅,锅铲",约3-5分钟 +201002854,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入备好的姜片、八角、桂皮、生抽、老抽、料酒、干小米椒、盐,小火翻炒1分钟,加开水没过肉,4.0,"炒,加汤",锅铲,1分钟 +201002855,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加盖中火煮沸,转小火慢炖30分钟,慢炖期间,间隔10分钟搅拌一次防止粘锅,5.0,炖,"锅,锅铲",30分钟 +201002856,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,小火慢炖汤汁剩三分之一时,调成中火收汁出锅,6.0,收汁,锅铲,约5分钟 +201002857,Recipe,湘祁米夫鸭,湘祁米夫鸭,,Recipe,,荤菜,4.0,湘菜,约10分钟(切鸭、配料准备),高压锅蒸20-25分钟(老鸭需60分钟以上),3-4人,"湖南两祁地区特色菜,鸭肉品种不限,水鸭即可,粘米粉为主粉,糯米粉增软糯,蒸肉粉增五香,辣椒粉和胡椒粉提供复合香味,高压锅蒸20分钟(老鸭需1小时以上)",dishes\meat_dish\湘祁米夫鸭\湘祁米夫鸭.md,,,,,,,, +201002858,Ingredient,鸭子,鸭子,,Ingredient,,蛋白质,,,,,,,,1000,克,True,,,,, +201002859,Ingredient,糯米粉,糯米粉,,Ingredient,,淀粉类,,,,,,,,100,克,False,,,,, +201002860,Ingredient,粘米粉,粘米粉,,Ingredient,,淀粉类,,,,,,,,300,克,False,,,,, +201002861,Ingredient,蒸肉粉,蒸肉粉,,Ingredient,,淀粉类,,,,,,,,50,克,False,,,,, +201002862,Ingredient,细辣椒粉,细辣椒粉,,Ingredient,,调料,,,,,,,,50,克,False,,,,, +201002863,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002864,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,50,克,False,,,,, +201002865,Ingredient,姜蒜,姜蒜,,Ingredient,,蔬菜,,,,,,,,20,克,False,,,,, +201002866,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201002867,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201002868,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,100,克,False,,,,, +201002869,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将糯米粉、粘米粉、蒸肉粉、细辣椒粉、5克盐、白胡椒粉倒在一起搅匀,制成米粉混合物备用。,1.0,混合,盆,约2分钟 +201002870,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鸭子请摊主剁成适合蒸煮的块;姜切片,蒜剥皮;五花肉切片备用。,2.0,切,"刀,案板",约5分钟 +201002871,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅凉油,先煸炒五花肉出油,再加适量食用油烧热,放入鸭块煸炒。,3.0,炒,"炒锅,锅铲",约3-5分钟 +201002872,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,鸭肉煸炒至表皮焦黄变色,加入姜片、蒜瓣和剩余盐,继续炒出香味。,4.0,炒,"炒锅,锅铲",约2分钟 +201002873,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,关小火,倒入米粉混合物翻炒,使鸭肉均匀裹满米粉;少量多次加入开水,边加边翻炒,保持湿润。,5.0,炒,"炒锅,锅铲",约3分钟 +201002874,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将裹好米粉的鸭肉装入碗中,放入高压锅,加水蒸20-25分钟(老鸭需60分钟以上)。,6.0,蒸,"高压锅,碗",20-25分钟 +201002875,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,出锅前撒葱花即可享用。,7.0,装饰,筷子,约10秒 +201002876,Recipe,牛排,牛排,,Recipe,,荤菜,4.0,西餐,30分钟(含解冻、预处理),15-30分钟,2人,"火候控制,醒肉技巧,油温判断,电磁炉火力参考,燃气灶火力参考,调味自由搭配",dishes\meat_dish\牛排\牛排.md,,,,,,,, +201002877,Ingredient,牛排,牛排,,Ingredient,,蛋白质,,,,,,,,475,克,True,,,,, +201002878,Ingredient,橄榄油,橄榄油,,Ingredient,,调料,,,,,,,,12.5,毫升,False,,,,, +201002879,Ingredient,黄油,黄油,,Ingredient,,调料,,,,,,,,22.5,克,False,,,,, +201002880,Ingredient,海盐,海盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201002881,Ingredient,黑胡椒,黑胡椒,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201002882,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,7.5,克,False,,,,, +201002883,Ingredient,百里香,百里香,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201002884,Ingredient,口蘑,口蘑,,Ingredient,,蔬菜,,,,,,,,7.5,个,False,,,,, +201002885,Ingredient,小土豆,小土豆,,Ingredient,,蔬菜,,,,,,,,7.5,个,False,,,,, +201002886,Ingredient,小番茄,小番茄,,Ingredient,,蔬菜,,,,,,,,7.5,个,False,,,,, +201002887,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,提前一晚将冰冻牛排移至冷藏室,烹饪前半小时置于常温解冻,1.0,解冻,冰箱,30分钟 +201002888,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,小番茄、小土豆、口蘑洗净对半切开备用,2.0,切,"刀,案板",5分钟 +201002889,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大蒜剥皮后压扁备用,3.0,压,刀,2分钟 +201002890,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,肉眼牛排剪断中心结缔组织;西冷牛排可剔除边缘脂肪;用厨房纸吸干表面水分,4.0,"剪,吸干","厨房剪刀,厨房纸",3分钟 +201002891,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,高火预热平底锅15-30秒,倒入橄榄油,5.0,热锅,平底锅,20秒 +201002892,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,牛排两面均匀撒上海盐和黑胡椒并立即下锅,6.0,"腌制,煎",平底锅,1分钟 +201002893,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,单面煎1.5分钟后翻面再煎1.5分钟;西冷/菲力需立起煎侧面30秒,7.0,煎,"平底锅,锅铲",3.5分钟 +201002894,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,转中火,加入黄油、大蒜、百里香,用锅铲推动黄油融化并将蒜瓣压在牛排下,8.0,"煎,淋油","平底锅,锅铲",1分钟 +201002895,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,倾斜锅身,用汤匙不断将热油淋在牛排上各30秒,9.0,淋油,汤匙,1分钟 +201002896,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,牛排出锅后用锡箔纸包裹静置5-10分钟醒肉,10.0,静置,锡箔纸,7.5分钟 +201002897,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将配菜倒入锅中中火煎5分钟,11.0,煎,平底锅,5分钟 +201002898,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,牛排切成1.5cm宽肉条,与配菜一起装盘,可淋上锅中余油或牛排酱汁,12.0,"切,装盘","刀,盘子",2分钟 +201002899,Recipe,猪皮冻,猪皮冻,,Recipe,,"荤菜,凉菜,下酒菜",5.0,东北菜,12小时(浸泡)+ 20分钟(处理),90分钟(炖煮)+ 12小时(冷藏凝固),每份,"晶莹剔透,去腥关键:白醋+盐搓洗,Q弹口感,下酒菜,年夜饭必备",dishes\meat_dish\猪皮冻\猪皮冻.md,,,,,,,, +201002900,Ingredient,猪皮,猪皮,,Ingredient,,蛋白质,,,,,,,,1000,g,True,,,,, +201002901,Ingredient,水,水,,Ingredient,,其他,,,,,,,,4000,g,False,,,,, +201002902,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,13,g,False,,,,, +201002903,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002904,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201002905,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,50,ml,False,,,,, +201002906,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,ml,False,,,,, +201002907,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,20,g,False,,,,, +201002908,Ingredient,姜片,姜片,,Ingredient,,蔬菜,,,,,,,,20,g,False,,,,, +201002909,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201002910,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201002911,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,50,ml,False,,,,, +201002912,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201002913,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将猪皮剁成不超过10cm的小块,用清水浸泡12小时。,1.0,"切,浸泡","刀,盆",12小时 +201002914,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,冷水下锅,加入10g姜片、50ml料酒,汆烫5-10分钟后捞出放入冷水中。,2.0,焯水,"锅,漏勺",5-10分钟 +201002915,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将焯过水的猪皮放在案板上,剔除白肉部分,再切成不超过3mm的长条。,3.0,"切,去脂","刀,案板",10分钟 +201002916,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入20g白醋、5g盐,用力搓洗3分钟,再用清水洗净。,4.0,搓洗,盆,3分钟 +201002917,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅内加入4kg水,放入猪皮、10g葱、10g姜片、10g八角、5g花椒,大火烧开后小火煲煮90分钟至猪皮软烂。,5.0,"煮,炖",锅,90分钟 +201002918,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入盐8g、味精10g、鸡精15g、生抽50ml、老抽20ml调味,倒入盘中,拣出葱姜八角,晾凉至果冻状。,6.0,"调味,冷却","锅,盘",30分钟 +201002919,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放冰箱冷藏,食用时切成小块或厚片。,7.0,"冷藏,切","冰箱,刀",12小时 +201002920,Recipe,瘦肉土豆片,瘦肉土豆片,,Recipe,"[{'term': '瘦肉洋芋片', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '瘦肉马铃薯片', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '瘦肉potato片', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,,约20分钟(切菜+腌制10分钟),约8-10分钟(焯水5分钟+炒制3分钟+其他),1人,"土豆片焯水不宜太久,防止变软,腌制瘦肉需搅拌均匀",dishes\meat_dish\瘦肉土豆片\瘦肉土豆片.md,,,,,,,, +201002921,Ingredient,纯瘦肉,纯瘦肉,,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201002922,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,200,g,True,,,,, +201002923,Ingredient,蒜苗,蒜苗,,Ingredient,,蔬菜,,,,,,,,2,根,False,,,,, +201002924,Ingredient,生粉,生粉,,Ingredient,,淀粉类,,,,,,,,5,g,False,,,,, +201002925,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,g,False,,,,, +201002926,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,g,False,,,,, +201002927,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002928,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201002929,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,土豆去皮、对半切开,再切成约2mm的薄片,备用,1.0,切,"刀,案板", +201002930,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,蒜苗洗净,切成约1cm的段,备用,2.0,"切,洗","刀,案板", +201002931,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,瘦肉洗净切成约2mm的薄片,放入碗中,加入5g生粉、5g生抽、3g老抽腌制十分钟,备用,3.0,"切,腌制","刀,案板,碗",10分钟 +201002932,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,烧一锅开水,将土豆片放入锅中,焯水,约5分钟,4.0,"煮,焯水",锅,5分钟 +201002933,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅,锅内放入10-15ml食用油,等待10秒让油温升高,5.0,炒,炒锅,10秒 +201002934,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入瘦肉,翻炒至变色,倒入蒜苗一起炒,蒜苗炒约20秒,6.0,炒,锅铲,20秒 +201002935,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入土豆,保持翻炒,加入2g食用盐、5g生抽,7.0,炒,锅铲, +201002936,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,炒约3分钟,盛盘,8.0,炒,锅铲,3分钟 +201002937,Recipe,糖醋排骨,糖醋排骨,,Recipe,"[{'term': 'sweet and sour排骨', 'language': 'en', 'language_code': 'en-US'}]",荤菜,4.0,苏菜,5分钟,25-30分钟,1人份,"炸排骨前可轻撒干淀粉提升酥脆口感,焯水火力需先大火后中火再转小火,焯水后需用开水清洗避免肉质变柴,糖溶解即可无需过度依赖颜色变化,收汁需快速翻炒避免长时间炖煮",dishes\meat_dish\糖醋排骨\糖醋排骨.md,,,,,,,, +201002938,Ingredient,排骨,排骨,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201002939,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201002940,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,300,ml,False,,,,, +201002941,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201002942,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201002943,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201002944,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002945,Ingredient,姜片,姜片,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002946,Ingredient,芝麻,芝麻,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002947,Ingredient,番茄酱,番茄酱,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201002948,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201002949,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201002950,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,排骨与姜片放入冷水中,大火加热至水沸腾、出现大量泡沫后转中火,待水持续沸腾时再转小火焯水2–3分钟,捞出备用。,1.0,"焯水,煮",锅,2-3分钟 +201002951,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用开水反复清洗排骨2–3遍,确保彻底去除血沫。,2.0,清洗,盆,1-2分钟 +201002952,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,在锅中倒入足够量的食用油进行深炸(油量依据锅具大小而定,建议约300 ml供一般家庭使用),待油温升至约170°C后,下排骨炸制3–5分钟,直至表面略呈金黄色,捞出控油。,3.0,炸,"锅,漏勺",3-5分钟 +201002953,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,另取干净锅,置于小火上加热50 ml热水,加入白砂糖30 g,轻轻搅拌直至糖完全溶解,并略呈淡黄色。此步骤的重点在于观察糖溶解情况,无需过分依赖颜色变化。,4.0,炒糖色,"锅,锅铲",2-3分钟 +201002954,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将炸好的排骨倒入炒制糖水的锅中,迅速翻炒30秒后,依次加入香醋5 ml、生抽5 ml、蚝油5 ml、鸡精2 g、番茄酱10 g、五香粉2 g,再次翻炒30秒,使调料均匀裹覆排骨,然后加入开水至刚好没过排骨。,5.0,"炒,调味","锅,锅铲",1分钟 +201002955,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,用大火将锅中液体煮沸后,加入老抽5 ml进行上色,并快速收汁;若排骨块较大,可转小火焖煮5–10分钟以便更好地入味,切勿采用中火长时间炖煮20分钟,以免损伤口感。,6.0,"煮,焖,收汁","锅,锅铲",5-10分钟 +201002956,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,起锅装盘,撒上芝麻2 g,即可享用。,7.0,装盘,盘子,30秒 +201002957,Recipe,红烧猪蹄,红烧猪蹄,,Recipe,"[{'term': 'braised猪蹄', 'language': 'en', 'language_code': 'en-US'}]",荤菜,4.0,,约15分钟(焯水去腥),约35分钟(炒糖色2分钟+翻炒1分钟+高压锅15分钟+收汁30秒),3-4人,"汤汁浓郁,下饭,高压锅可替代",dishes\meat_dish\红烧猪蹄\红烧猪蹄.md,,,,,,,, +201002958,Ingredient,猪蹄,猪蹄,,Ingredient,,蛋白质,,,,,,,,2~3,根,True,,,,, +201002959,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,30,毫升,False,,,,, +201002960,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201002961,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,5,片,False,,,,, +201002962,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201002963,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,1,块,False,,,,, +201002964,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,7-8,粒,False,,,,, +201002965,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,毫升,False,,,,, +201002966,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201002967,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201002968,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,8,克,False,,,,, +201002969,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,4,个,False,,,,, +201002970,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,冷水锅中放入剁好的猪蹄,加入20ml料酒与葱姜,煮15分钟去掉血腥。,1.0,煮,锅,15分钟 +201002971,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,热锅冷油,倒入30ml食用油,放入7-8粒冰糖,开小火熬成糖色,期间用锅铲把冰糖压碎,大概熬2分钟。,2.0,"炒,熬","炒锅,锅铲",2分钟 +201002972,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,熬成糖色后,放入焯过水的猪蹄,继续小火翻炒至所有猪蹄两面微黄。,3.0,炒,"炒锅,锅铲", +201002973,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入香叶2片、桂皮1块、八角4个、生抽20ml、老抽20ml、料酒10ml、姜3片、盐8克,转中火继续翻炒1分钟。,4.0,炒,"炒锅,锅铲",1分钟 +201002974,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入开水或冷水,水需没过猪蹄,盖上锅盖大火烧开,烧开后关火。,5.0,煮,"锅,锅盖", +201002975,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,把锅内食材全部倒入高压锅中,高压锅压15分钟(若无高压锅,可锅中大火转小火熬制)。,6.0,炖,高压锅,15分钟 +201002976,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,15分钟后,把高压锅食材倒回炒锅,开大火收汁,此时可尝味,淡则加2-3g盐。,7.0,收汁,"炒锅,筷子", +201002977,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,大火收汁时长根据锅中水量,一般30秒即可,多留汤汁也无碍,红烧猪蹄汤也很下饭。,8.0,收汁,炒锅,30秒 +201002978,Recipe,南派红烧肉,南派红烧肉,,Recipe,"[{'term': '南派braised肉', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,4.0,,约20分钟(切肉、切配料、焯水准备),约90-110分钟(焯水15分钟+炒糖色与炖煮50-60分钟+收汁10-15分钟),1-3人,"新手不败,肥而不腻,色泽诱人,香糯无敌,配米饭绝佳",dishes\meat_dish\红烧肉\南派红烧肉.md,,,,,,,, +201002979,Ingredient,猪五花肉,猪五花肉,,Ingredient,,蛋白质,,,,,,,,1000,克,True,,,,, +201002980,Ingredient,油,油,,Ingredient,,调料,,,,,,,,100-150,毫升,False,,,,, +201002981,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,6,片,False,,,,, +201002982,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,块,False,,,,, +201002983,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201002984,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201002985,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201002986,Ingredient,凉水,凉水,,Ingredient,,其他,,,,,,,,没过食材,适量,False,,,,, +201002987,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,没过食材,适量,False,,,,, +201002988,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,4,片,False,,,,, +201002989,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,个,False,,,,, +201002990,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2-3,克,False,,,,, +201002991,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201002992,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,适量,根,False,,,,, +201002993,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,适量,瓣,False,,,,, +201002994,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将猪五花肉切成约4.5厘米的大块;生姜切成约3毫米厚的片;小葱白色部分切段;蒜中间切开备用。,1.0,切,"刀,案板",约5-10分钟 +201002995,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将一半葱姜取出,剩余生姜、葱白、蒜、花椒、八角、香叶放入碗中备用。,2.0,备料,碗,约2分钟 +201002996,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,凉水中放入切好的五花肉、料酒和2/5的葱姜,煮15分钟去腥,捞出洗净。,3.0,"焯水,煮",锅,15分钟 +201002997,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,按简易版炒糖色教程,采用操作2炒糖色。,4.0,炒,"锅,锅铲",约5分钟 +201002998,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将五花肉及碗中的生姜、葱白、蒜、花椒、八角、香叶倒入糖色锅中,大火翻炒至香味四溢,加入开水没过全部肉,炖煮50-60分钟(高压锅40分钟)。,5.0,"炒,炖","锅,锅铲",50-60分钟 +201002999,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入10毫升料酒,盖上锅盖煮沸后,每隔25分钟打开盖子撇去浮沫和浮油。,6.0,"炖,撇沫","锅,勺子",约50分钟 +201003000,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,当水位降至肉高度的3/5时转中火,捞出除肉和水外的所有辅料,开始收汁。,7.0,收汁,"锅,筷子",10-15分钟 +201003001,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,打开锅盖,待汤汁浓稠但不可收干时出锅。,8.0,收汁,锅,约5分钟 +201003002,Recipe,简易红烧肉,简易红烧肉,,Recipe,"[{'term': '简易braised肉', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,,约20分钟(切肉、焯水、准备配料),约95分钟(焯水15分钟+煎肉+炖煮80分钟),2-3人,"新手不败,肥而不腻,色泽诱人,香糯下饭",dishes\meat_dish\红烧肉\简易红烧肉.md,,,,,,,, +201003003,Ingredient,猪五花肉,猪五花肉,,Ingredient,,蛋白质,,,,,,,,3.5,斤,True,,,,, +201003004,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,6,片,False,,,,, +201003005,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,克,False,,,,, +201003006,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,毫升,False,,,,, +201003007,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201003008,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,毫升,False,,,,, +201003009,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,750,毫升,False,,,,, +201003010,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,3,片,False,,,,, +201003011,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,个,False,,,,, +201003012,Ingredient,鹌鹑蛋,鹌鹑蛋,,Ingredient,,蛋白质,,,,,,,,1,个,False,,,,, +201003013,Ingredient,豆皮,豆皮,,Ingredient,,蛋白质,,,,,,,,40,克,False,,,,, +201003014,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2.5,克,False,,,,, +201003015,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201003016,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将猪五花肉切成约4.5cm的大块,冷冻半小时至一小时更好切。,1.0,切,刀,10分钟 +201003017,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,豆皮切成2cm宽条;生姜切成约3mm厚片;大葱取葱白部分;鹌鹑蛋煮熟后用叉子或牙签扎孔备用。,2.0,"切,煮","刀,锅,叉子/牙签",10分钟 +201003018,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,冷水锅中放入五花肉、料酒和葱姜,煮15分钟去腥。,3.0,煮,锅,15分钟 +201003019,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅中放两片生姜提味,开中小火,将五花肉六面煎至出油。,4.0,煎,炒锅,5分钟 +201003020,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,倒出多余油脂,将五花肉拨至一边,加入冰糖炒至融化,再与五花肉一起翻炒上色。,5.0,炒,锅铲,3分钟 +201003021,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入生抽、老抽、料酒,继续翻炒至上色均匀。,6.0,炒,锅铲,2分钟 +201003022,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,倒入烧好的开水,没过食材,加入生姜、香叶、八角,盖上锅盖炖煮40分钟。,7.0,炖,"锅,锅盖",40分钟 +201003023,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入鹌鹑蛋和豆皮,继续中小火炖煮40分钟,中途适当翻搅防粘。,8.0,炖,锅铲,40分钟 +201003024,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,开大火收汁,汤汁快干时关火,加入2-3g盐翻炒均匀即可。,9.0,"炒,收汁",锅铲,2分钟 +201003025,Recipe,羊排焖面,羊排焖面,,Recipe,"[{'term': '羊排braised面', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '羊排闷面', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,4.0,西北菜,约20分钟(切配、焯水、和面),约50分钟(炖煮30分钟+焖面4分钟+其他炒制),2人份,"宽面口感更佳,可替换超市宽面条,聚会硬菜,三大营养物质齐全",dishes\meat_dish\羊排焖面\羊排焖面.md,,,,,,,, +201003026,Ingredient,带皮羊排,带皮羊排,,Ingredient,,蛋白质,,,,,,,,500,克,True,,,,, +201003027,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,个,False,,,,, +201003028,Ingredient,甜椒,甜椒,,Ingredient,,蔬菜,,,,,,,,2,个,False,,,,, +201003029,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,适量,,False,,,,, +201003030,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003031,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003032,Ingredient,生姜,生姜,,Ingredient,,调料,,,,,,,,4,片,False,,,,, +201003033,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003034,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201003035,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003036,Ingredient,中筋面粉,中筋面粉,,Ingredient,,淀粉类,,,,,,,,300,克,True,,,,, +201003037,Ingredient,盐(和面用),盐(和面用),,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201003038,Ingredient,水,水,,Ingredient,,其他,,,,,,,,180,毫升,False,,,,, +201003039,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,羊肉冷水下锅焯水,水开后撇去血沫,捞出羊肉备用。,1.0,焯水,锅,约5分钟 +201003040,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,切4片生姜,与干辣椒、花椒一起放入碗中备用。,2.0,切,"刀,碗",约2分钟 +201003041,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,炒锅加油,油热后放入白砂糖炒出焦糖色。,3.0,炒,炒锅,约2分钟 +201003042,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,放入羊肉翻炒至水分炒干,加盐、老抽及备好的调味料继续翻炒。,4.0,炒,"炒锅,锅铲",约3分钟 +201003043,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入清水没过羊肉,大火煮沸后转中小火炖煮30分钟。,5.0,"煮,炖",炒锅,40分钟(10分钟煮沸+30分钟炖煮) +201003044,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,和面:中筋面粉300g加盐3g,加水180ml和成光滑面团,醒面10分钟后再揉光滑,再醒5分钟。,6.0,"和面,醒面","盆,擀面杖",20分钟 +201003045,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将面团分成6-8个小剂子,抹油静置5分钟后擀成宽面皮。,7.0,"切,擀","刀,擀面杖",约5分钟 +201003046,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将青椒、甜椒、大葱切段,与擀好的面皮一起放入炖好的羊排中翻炒均匀。,8.0,"炒,焖","炒锅,锅铲",约4分钟 +201003047,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,翻炒均匀后出锅装盘。,9.0,炒,锅铲,约1分钟 +201003048,Recipe,老妈蹄花,老妈蹄花,,Recipe,,荤菜,4.0,川菜,前一晚浸泡白芸豆,约10分钟处理猪蹄,焯水10分钟 + 高压锅40分钟 ≈ 50分钟,3根猪蹄(约3-4人份),"高压锅省时,汤底奶白色判断标准,中途加热水防汤浑,灵魂酸辣汁",dishes\meat_dish\老妈蹄花\老妈蹄花.md,,,,,,,, +201003049,Ingredient,猪蹄,猪蹄,,Ingredient,,蛋白质,,,,,,,,3,根,True,,,,, +201003050,Ingredient,白芸豆,白芸豆,,Ingredient,,淀粉类,,,,,,,,200,g,False,,,,, +201003051,Ingredient,当归,当归,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201003052,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003053,Ingredient,姜片,姜片,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201003054,Ingredient,蒜末,蒜末,,Ingredient,,蔬菜,,,,,,,,8,g,False,,,,, +201003055,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201003056,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,25,g,False,,,,, +201003057,Ingredient,葱花,葱花,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201003058,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003059,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003060,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201003061,Ingredient,白芷,白芷,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003062,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003063,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003064,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003065,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003066,Ingredient,花椒油,花椒油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003067,Ingredient,油泼辣子,油泼辣子,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003068,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,200g白芸豆提前一晚用清水浸泡备用,1.0,浸泡,盆,前一晚 +201003069,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,准备猪前蹄,让摊主从中间劈开,用喷火枪去除毛囊,回家清洗干净,2.0,处理,喷火枪,约5分钟 +201003070,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,冷水锅中加入猪蹄、大葱段、姜片、料酒,焯水十分钟,撇去浮沫后捞出洗净备用,3.0,"焯水,撇沫,清洗",锅,10分钟 +201003071,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,高压锅中放入猪蹄、当归、白芷、白胡椒粉、姜片,上汽后压三十分钟,4.0,高压炖煮,高压锅,30分钟 +201003072,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入白芸豆,再压十分钟;若汤底呈奶白色则正确(中途如需加水只能加热水),5.0,高压炖煮,高压锅,10分钟 +201003073,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,揭盖后加入盐、鸡精、葱花调味,6.0,调味,勺子,1分钟 +201003074,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,调制灵魂汁子:放入葱、蒜、小米椒、白胡椒粉、生抽、香醋、油泼辣子、花椒油、猪蹄原汤,搅拌均匀,7.0,"调制,搅拌","碗,勺子",2分钟 +201003075,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将灵魂汁子浇在猪蹄上即可享用,8.0,浇汁,勺子,30秒 +201003076,Recipe,老式锅包肉,老式锅包肉,,Recipe,,荤菜,4.0,东北菜,约40分钟(含腌制15分钟、淀粉静置20分钟),约10分钟(炸制+炒制),2人份,"肉片厚度8mm,控制油温避免过深,糖醋汁熬至粘稠不结块",dishes\meat_dish\老式锅包肉\老式锅包肉.md,,,,,,,, +201003077,Ingredient,猪通脊肉,猪通脊肉,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201003078,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,50,g,False,,,,, +201003079,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201003080,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,3.5,瓣,False,,,,, +201003081,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201003082,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,10,g,False,,,,, +201003083,Ingredient,白熟芝麻,白熟芝麻,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003084,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,40,g,False,,,,, +201003085,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,40,g,False,,,,, +201003086,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,ml,False,,,,, +201003087,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,8,g,False,,,,, +201003088,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003089,Ingredient,米醋,米醋,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201003090,Ingredient,土豆淀粉,土豆淀粉,,Ingredient,,淀粉类,,,,,,,,210,g,False,,,,, +201003091,Ingredient,中筋面粉,中筋面粉,,Ingredient,,淀粉类,,,,,,,,70,g,False,,,,, +201003092,Ingredient,小苏打,小苏打,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003093,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,1000,ml,False,,,,, +201003094,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将猪通脊肉切成厚度8mm的均匀肉片,去除白色筋膜;用清水冲洗肉片去血水;加入小苏打5g抓匀静置5分钟;再冲洗1-2次去除多余小苏打。,1.0,"切,冲洗,腌制","刀,案板,盆",约10分钟 +201003095,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,在肉片中加入盐4g、料酒5ml拌匀,腌制15分钟。,2.0,腌制,盆,15分钟 +201003096,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将土豆淀粉210g与中筋面粉70g混合,少量多次加水搅拌至酸奶状,可拉丝并在盆中堆积;加入食用油10ml、小苏打1g搅匀成挂浆。,3.0,搅拌,"盆,筷子",约5分钟 +201003097,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将腌制好的肉片放入浆糊中拌匀,使每片肉均匀裹上浆。,4.0,裹浆,"盆,筷子",约2分钟 +201003098,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,混合白糖40g、白醋40g、盐4g、味精5g、米醋5ml搅匀成糖醋汁备用。,5.0,搅拌,"碗,筷子",约1分钟 +201003099,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,大葱、姜、胡萝卜切丝,香菜切段,蒜切片备用。,6.0,切,"刀,案板",约3分钟 +201003100,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,第一次炸制:锅中加油至150℃,逐片放入肉片炸至浅黄定型约30秒后捞出;第二次炸制:油温升至170℃,全部复炸至金黄酥脆约1分钟;第三次可选:油温200℃快速复炸10-20秒增强酥脆,捞出沥油。,7.0,炸,"锅,漏勺",约3分钟 +201003101,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,锅中留20ml底油,煸香姜丝蒜片10秒;倒入糖醋汁大火熬至粘稠30-60秒;加入炸好的肉片、葱丝、胡萝卜丝、香菜段快速翻炒3次裹汁。,8.0,"炒,熬汁","锅,锅铲",约2分钟 +201003102,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将锅包肉盛入盘中,撒上白熟芝麻即可上桌。,9.0,装盘,盘子,约30秒 +201003103,Recipe,芥末罗氏虾,芥末罗氏虾,,Recipe,,荤菜,3.0,,约10分钟,约10分钟,2人份,黄油入锅后不宜炸制太久,融化翻拌均匀即可烹入碗汁,dishes\meat_dish\芥末罗氏虾\芥末罗氏虾.md,,,,,,,, +201003104,Ingredient,罗氏虾,罗氏虾,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201003105,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,2,个,False,,,,, +201003106,Ingredient,青芥末,青芥末,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201003107,Ingredient,生粉,生粉,,Ingredient,,淀粉类,,,,,,,,10,g,False,,,,, +201003108,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,g,False,,,,, +201003109,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003110,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,g,False,,,,, +201003111,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201003112,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201003113,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,2,个,False,,,,, +201003114,Ingredient,黄油,黄油,,Ingredient,,其他,,,,,,,,20,g,False,,,,, +201003115,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,80,ml,False,,,,, +201003116,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将虾从背部切开,去除虾线和沙袋,也可从腹部切开,炸出来会胀开,成菜比较漂亮;用清水洗干净,控干水分后可拍上生粉,也可不拍。,1.0,"切,清洗,拍粉","刀,案板,盆",约5分钟 +201003117,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将2颗大蒜切成蒜末;准备碗汁,放入生抽、蚝油、白糖、胡椒粉、盐,依据个人口味挤入芥末,加清水稀释后加入生粉化开。,2.0,"切,调制","刀,案板,碗,筷子",约3分钟 +201003118,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅热倒入食用油,大概能覆盖锅底;放入控干水分的罗氏虾,慢慢煎制。,3.0,煎,"炒锅,锅铲",约3分钟 +201003119,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,虾油煎出来后(表现为锅中出现大量气泡),加入准备好的蒜蓉及小米辣;闻到蒜蓉的香味后,加入黄油。,4.0,炒,锅铲,约1分钟 +201003120,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,黄油融化后翻拌均匀,加入准备好的碗汁;盖锅盖焖煮2分钟汤汁浓稠后出锅。,5.0,焖煮,"锅铲,锅盖",2分钟 +201003121,Recipe,茭白炒肉,茭白炒肉,,Recipe,,荤菜,3.0,,约10分钟,约5分钟,1份,可加蚝油、生抽代替盐上色,dishes\meat_dish\茭白炒肉\茭白炒肉.md,,,,,,,, +201003122,Ingredient,茭白,茭白,,Ingredient,,蔬菜,,,,,,,,2,根,True,,,,, +201003123,Ingredient,瘦肉,瘦肉,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201003124,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,15,g,False,,,,, +201003125,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201003126,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003127,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,1,片,False,,,,, +201003128,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,1,个,False,,,,, +201003129,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201003130,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201003131,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,茭白切片,每片厚度0.5 cm,1.0,切,"刀,案板",约2分钟 +201003132,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,瘦肉切条,厚度0.3-0.5 cm,加入料酒、生粉、盐、水搅拌腌制,2.0,"切,腌制","刀,案板,盆,筷子",约3分钟 +201003133,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,姜切片、蒜头剁碎,3.0,"切,剁","刀,案板",约1分钟 +201003134,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,起锅水烧开,放入茭白,水煮60-90秒后取出沥干,4.0,煮,"锅,漏勺",60-90秒 +201003135,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,起锅,倒入15 ml油,倒入瘦肉,反复翻炒60秒后取出,5.0,炒,"炒锅,锅铲",60秒 +201003136,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,起锅,倒入15 ml油,倒入姜、蒜翻炒30秒,加入茭白继续翻炒30秒,6.0,炒,"炒锅,锅铲",60秒 +201003137,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,继续加入瘦肉翻炒60秒,加入20 ml水,加入盐、鸡精后翻炒60秒出锅,7.0,炒,"炒锅,锅铲",120秒 +201003138,Recipe,荔枝肉,荔枝肉,,Recipe,,荤菜,4.0,闽菜,约15分钟(切肉、腌肉、调汁、切凤梨),约10分钟(两次油炸+炒制),1人份,"福州特色,酸甜口味,二次油炸更酥脆,可用马蹄或马铃薯替代凤梨,闽菜偏甜可减糖,听声辨炸透",dishes\meat_dish\荔枝肉\荔枝肉.md,,,,,,,, +201003139,Ingredient,瘦肉,瘦肉,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201003140,Ingredient,凤梨,凤梨,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201003141,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201003142,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,500,ml,False,,,,, +201003143,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003144,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,100,g,False,,,,, +201003145,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201003146,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003147,Ingredient,姜末,姜末,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003148,Ingredient,芝麻,芝麻,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201003149,Ingredient,番茄酱,番茄酱,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201003150,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,2,ml,False,,,,, +201003151,Ingredient,鲜香菇,鲜香菇,,Ingredient,,蔬菜,,,,,,,,2,朵,False,,,,, +201003152,Ingredient,蟹味菇,蟹味菇,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201003153,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,瘦肉切块(每块2-3 cm),放入大碗中,加入鸡蛋1个、生粉50 g、生抽3 ml、鸡精2 g,1.0,"切,腌制","刀,案板,大碗",3分钟 +201003154,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,充分搅拌直至生粉包裹住瘦肉块(太稀则继续加生粉,太干则加水),然后加入5 ml油,充分搅拌后备用,2.0,"搅拌,腌制","筷子,大碗",2分钟 +201003155,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,准备碗,加入番茄酱、鸡精3 g、生抽2 ml、姜末、白砂糖、生粉10 g、香醋、凉水200 ml,充分搅拌后备用,3.0,搅拌,"碗,筷子",2分钟 +201003156,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,切凤梨,准备6个(每个1.5-2 cm)凤梨块,4.0,切,"刀,案板",2分钟 +201003157,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,起锅烧油,倒入500 ml油,一直烧油直到听到油炸声,5.0,炸,"炒锅,锅铲",2分钟 +201003158,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将瘦肉一个一个放入锅中(切记不可以整碗倒入),保证每个肉不要粘在一起,6.0,炸,"炒锅,锅铲",1分钟 +201003159,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,全部放入瘦肉后,每30秒用勺子来回两面翻转瘦肉块,直至瘦肉块表面金黄,7.0,炸,"炒锅,勺子",3分钟 +201003160,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,取出瘦肉,一分钟后倒入油锅中继续炸,直至瘦肉块表面出现焦黄后,取出放入大碗备用,8.0,炸,"炒锅,漏勺,大碗",2分钟 +201003161,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,起锅,倒入汤汁,30秒后倒入瘦肉块、凤梨块,充分翻炒后出锅,9.0,炒,"炒锅,锅铲",1分钟 +201003162,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,摆上芝麻,10.0,装饰,手,10秒 +201003163,Recipe,荷兰豆炒腊肠,荷兰豆炒腊肠,,Recipe,,荤菜,2.0,,5分钟,3分钟,1人份,"无需额外加盐,腊肠本身有咸味,生抽提供咸味,腊肠需小火慢炒防糊,腊肠属高盐食品建议适量",dishes\meat_dish\荷兰豆炒腊肠\荷兰豆炒腊肠.md,,,,,,,, +201003164,Ingredient,荷兰豆,荷兰豆,,Ingredient,,蔬菜,,,,,,,,50,个,True,,,,, +201003165,Ingredient,腊肠,腊肠,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201003166,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201003167,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201003168,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,把荷兰豆去掉蒂,有时间的也可以同时把尾部去掉,1.0,切,刀, +201003169,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,买腊肠之前可以问老板是生的还是熟的,如果是生的,需要提前蒸一下,如果是熟的可以直接使用,2.0,蒸,蒸锅, +201003170,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,把荷兰豆清洗一下,然后焯一下水,大概45秒,荷兰豆焯至变色即可,捞出过凉水备用,3.0,煮,"锅,盆",45秒 +201003171,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,锅内放入大约10ml食用油。等待10秒让油温升高,4.0,炒,炒锅,10秒 +201003172,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入腊肠,保持翻炒至腊肠微微卷边,注意这里一定要保持小火,小到不能小的那种,不然容易糊,5.0,炒,锅铲, +201003173,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入荷兰豆,转为中大火,翻炒30秒放入生抽,接着再翻炒20-30秒即可,6.0,炒,锅铲,50-60秒 +201003174,Recipe,血浆鸭,血浆鸭,,Recipe,,荤菜,5.0,湘菜,约20分钟(切鸭、处理鸭血、切配料),约40分钟(炒、煮、焖、收汁),2-4人,"观察水位线防烧干,加鸭血后持续翻炒防凝固",dishes\meat_dish\血浆鸭\血浆鸭.md,,,,,,,, +201003175,Ingredient,鲜仔鸭肉,鲜仔鸭肉,,Ingredient,,蛋白质,,,,,,,,2000,g,True,,,,, +201003176,Ingredient,鲜鸭血,鲜鸭血,,Ingredient,,蛋白质,,,,,,,,250,ml,True,,,,, +201003177,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,6,片,False,,,,, +201003178,Ingredient,蒜仔,蒜仔,,Ingredient,,蔬菜,,,,,,,,6,瓣,False,,,,, +201003179,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,2,根,False,,,,, +201003180,Ingredient,辣椒,辣椒,,Ingredient,,蔬菜,,,,,,,,1000,g,False,,,,, +201003181,Ingredient,高度白酒,高度白酒,,Ingredient,,调料,,,,,,,,50,ml,False,,,,, +201003182,Ingredient,水,水,,Ingredient,,其他,,,,,,,,150,ml,False,,,,, +201003183,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201003184,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,ml,False,,,,, +201003185,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,8,g,False,,,,, +201003186,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003187,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,100,ml,False,,,,, +201003188,Ingredient,山胡椒油,山胡椒油,,Ingredient,,调料,,,,,,,,3-6,滴,False,,,,, +201003189,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鲜仔鸭肉切成约3cm小块,加料酒、姜片,去除血水。,1.0,"切,腌制","刀,案板,盆",约10分钟 +201003190,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,炒锅烧热,放入约100ml食用油,大火待油烧开,放入腌制好的鲜鸭肉,不断翻炒。,2.0,炒,"炒锅,锅铲",约5分钟 +201003191,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,待鸭肉完全变色(肉眼可见泛白),放入酒,再加入200ml开水,刚好淹没鸭肉即可,盖上锅盖中火煮15分钟。,3.0,"煮,焖","炒锅,锅盖",15分钟 +201003192,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,水开之后,打开锅盖放入姜蒜,翻炒一遍,盖上锅盖持续加热10分钟。,4.0,"炒,焖","炒锅,锅盖,锅铲",10分钟 +201003193,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,打开锅盖放入辣椒,不断翻炒,待至肉眼可见辣椒炒软,放入鲜鸭血,此时需要不断翻炒,确保每块鸭肉和每片辣椒都有鸭血的浸润。,5.0,炒,"炒锅,锅铲",约5分钟 +201003194,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,翻炒至肉眼可见鸭血均为黑色,加入盐、鸡精、香葱,(喜欢食用山胡椒油的朋友也可以在此时放入3-6滴山胡椒油)再次翻炒一到二次即可。,6.0,炒,"炒锅,锅铲",约2分钟 +201003195,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,出锅盛盘,上桌食用。,7.0,装盘,盘子,约1分钟 +201003196,Recipe,西红柿土豆炖牛肉,西红柿土豆炖牛肉,,Recipe,"[{'term': '西红柿马铃薯炖牛肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '西红柿土豆煲牛肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '西红柿土豆stewed牛肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'tomato土豆炖牛肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '西红柿洋芋炖牛肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '西红柿potato炖牛肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '番茄土豆炖牛肉', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,4.0,,约20分钟,60-90分钟,3-4人,"砂锅更佳,炖煮不扣盖,汤需温热加入,避免糊底需翻动,酱油宁少勿多,不用鸡精味精",dishes\meat_dish\西红柿土豆炖牛肉\西红柿土豆炖牛肉.md,,,,,,,, +201003197,Ingredient,牛肉,牛肉,,Ingredient,,蛋白质,,,,,,,,600,克,True,,,,, +201003198,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201003199,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,4,片,False,,,,, +201003200,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,35,毫升,False,,,,, +201003201,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201003202,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,0.5,个,False,,,,, +201003203,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201003204,Ingredient,油,油,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201003205,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201003206,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201003207,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201003208,Ingredient,黑胡椒粉,黑胡椒粉,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201003209,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,3,个,True,,,,, +201003210,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,3,个,True,,,,, +201003211,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201003212,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,土豆去皮、切成5cm大块,备用,1.0,切,"刀,案板",3-5分钟 +201003213,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,西红柿切十字花刀,开水烫后去皮,去芯,切3cm小块备用,2.0,"切,烫","刀,案板,盆",5分钟 +201003214,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,葱切4g葱花,其余掰成5-8cm大段;洋葱切0.5-1cm小粒,3.0,切,"刀,案板",3分钟 +201003215,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,牛肉泡凉水半小时去血水,或凉水下锅煮至表面变白捞出,期间撇去浮沫,4.0,焯水,"锅,漏勺",10分钟 +201003216,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,凉水没过牛肉,放入高压锅,加葱段、姜片、20g料酒,上汽压20分钟,5.0,炖,高压锅,20分钟 +201003217,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,取出牛肉切5cm大块,挑出姜片,汤盛碗备用,6.0,切,"刀,案板,碗",2分钟 +201003218,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,锅中倒油,油4-5成热下花椒、八角、香叶,出香味后捞出不用,7.0,炒,"炒锅,锅铲",30秒 +201003219,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,下牛肉、葱姜炒香,必要时加少量牛肉汤防糊,8.0,炒,"炒锅,锅铲",2-3分钟 +201003220,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加生抽15ml、料酒15ml、胡椒粉、5-10g番茄酱或番茄罐头,加洋葱炒至透明,9.0,炒,"炒锅,锅铲",2-3分钟 +201003221,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入西红柿炒至软烂,倒入剩余牛肉汤,10.0,"炒,炖","炒锅,锅铲",3-5分钟 +201003222,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,中火开锅后转小火,出锅前30-40分钟加入土豆并调味,边尝边加糖盐,11.0,"炖,调味","锅,筷子",30-40分钟 +201003223,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,筷子能轻松戳透牛肉时即可关火出锅,12.0,检查,筷子,1分钟 +201003224,Recipe,西红柿牛腩,西红柿牛腩,,Recipe,"[{'term': 'tomato牛腩', 'language': 'en', 'language_code': 'en-US'}, {'term': '番茄牛腩', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,5.0,,20分钟,90分钟,1份,"用火注意安全,砂锅/铝锅炖肉时水开后转中小火/小火,番茄去皮方法:十字刀+小火旋转烤,不用番茄酱,少加佐料,还原食材原味",dishes\meat_dish\西红柿牛腩\西红柿牛腩.md,,,,,,,, +201003225,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,3.5,个,True,,,,, +201003226,Ingredient,牛腩,牛腩,,Ingredient,,蛋白质,,,,,,,,500,克,True,,,,, +201003227,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,25,毫升,False,,,,, +201003228,Ingredient,葱段,葱段,,Ingredient,,调料,,,,,,,,2,段,False,,,,, +201003229,Ingredient,姜片,姜片,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201003230,Ingredient,葱花,葱花,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201003231,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201003232,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201003233,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003234,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201003235,Ingredient,料酒/黄酒,料酒/黄酒,,Ingredient,,调料,,,,,,,,7.5,毫升,False,,,,, +201003236,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,小片,False,,,,, +201003237,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003238,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,牛腩切条、切块成长宽高均2cm,冷水下锅,开锅煮制2分钟去除血水,捞出冲洗干净,1.0,"切,煮","刀,案板,锅",2分钟 +201003239,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,另起锅2L水烧开,加入2cm两段葱段、两片姜片、八角、料酒5-10ml,放入焯好的牛肉,盖盖炖制(砂锅1小时,高压锅炖肉模式45分钟),筷子能轻松插透就证明炖好了,2.0,炖,"砂锅/高压锅/铝锅,筷子",45-60分钟 +201003240,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,西红柿去皮:西红柿头部滑十字至腰线,筷子/刀叉从果蒂捅入,煤气灶小火,一边转动一边烤,及时拿下来查看,起皮后撕下来,切块。越小越好,3.0,"烤,切","刀,筷子/刀叉,煤气灶",5分钟 +201003241,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,起锅烧油,油温7成热,葱、姜各10g,番茄下锅,炒透炒出番茄红色,加入煮好的牛腩和原汤,原汤刚刚没过牛肉即可,4.0,炒,"炒锅,锅铲",5分钟 +201003242,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,根据个人口味放入盐、糖、生抽调味盖盖,5.0,调味,锅铲,1分钟 +201003243,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,开锅后大火继续炒制3-5分钟,6.0,炒,锅铲,3-5分钟 +201003244,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,待番茄汁呈中等粘稠程度后关火,散入葱花,盛盘,7.0,"收汁,装盘",锅铲,1分钟 +201003245,Recipe,豆豉鲮鱼油麦菜,豆豉鲮鱼油麦菜,,Recipe,,荤菜,2.0,粤菜,5分钟,5分钟,2人份,鲮鱼罐头本身带味道,加入生抽后够味,无需下盐,dishes\meat_dish\豆豉鲮鱼油麦菜\豆豉鲮鱼油麦菜.md,,,,,,,, +201003246,Ingredient,油麦菜,油麦菜,,Ingredient,,蔬菜,,,,,,,,500,g,True,,,,, +201003247,Ingredient,甘竹牌鲮鱼罐头,甘竹牌鲮鱼罐头,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201003248,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,4,瓣,False,,,,, +201003249,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,g,False,,,,, +201003250,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,g,False,,,,, +201003251,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201003252,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,油麦菜洗净后切段;鲮鱼罐头打开后,把鲮鱼主刺去除,切成小段后备用;大蒜切成末。,1.0,切,"刀,案板",3分钟 +201003253,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅热倒入食用油,油热后加入洗净的油麦菜,炒到萎蔫出水后盛出备用,倒掉炒制出的水分。,2.0,炒,"炒锅,锅铲",1分钟 +201003254,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,重新热锅后,加入鲮鱼罐头中的油,放入蒜末煸香。,3.0,煸,"炒锅,锅铲",30秒 +201003255,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,蒜末煸香后加入鲮鱼罐头中的豆豉,翻拌后加入切碎的鲮鱼块,再次翻拌。,4.0,翻拌,锅铲,30秒 +201003256,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,翻拌均匀后加入油麦菜,加入生抽和糖调味,简单翻拌即可出锅装盘。,5.0,翻拌,锅铲,30秒 +201003257,Recipe,豉汁蒸白鱔,豉汁蒸白鱔,,Recipe,"[{'term': '豉汁清蒸白鱔', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '豉汁steamed白鱔', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,粤菜,约10分钟,8-10分钟,1人份,"确保白鱔新鲜,蒸制时间不宜过长,可加少许米酒增嫩,可加入辣椒或XO酱变味",dishes\meat_dish\豉汁蒸白鱔\豉汁蒸白鱔食谱.md,,,,,,,, +201003258,Ingredient,白鱔,白鱔,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201003259,Ingredient,豆豉,豆豉,,Ingredient,,调料,,,,,,,,1,汤匙,False,,,,, +201003260,Ingredient,蒜头,蒜头,,Ingredient,,调料,,,,,,,,2,瓣,False,,,,, +201003261,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,3,片,False,,,,, +201003262,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201003263,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1.5,汤匙,False,,,,, +201003264,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,0.5,茶匙,False,,,,, +201003265,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,0.5,茶匙,False,,,,, +201003266,Ingredient,麻油,麻油,,Ingredient,,调料,,,,,,,,0.5,茶匙,False,,,,, +201003267,Ingredient,生粉,生粉,,Ingredient,,淀粉类,,,,,,,,1,茶匙,False,,,,, +201003268,Ingredient,水,水,,Ingredient,,其他,,,,,,,,1,汤匙,False,,,,, +201003269,Ingredient,红椒,红椒,,Ingredient,,蔬菜,,,,,,,,少许,,False,,,,, +201003270,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,检查与清洗白鱔:购买时已请鱼贩去内脏、刮去黏液并切成约5厘米长的段;回家后检查白鱔,冲洗干净,确保无残留黏液或杂质;可选:用少许盐和1茶匙生粉轻搓白鱔段,腌制5分钟后冲洗干净,去腥并增加嫩滑口感。,1.0,"腌制,清洗","刀,砧板,盆",5分钟 +201003271,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,准备酱汁:在小碗中混合1汤匙豆豉、2瓣蒜末、1.5汤匙生抽、0.5茶匙老抽、0.5茶匙糖、0.5茶匙麻油和1汤匙水,搅拌均匀;若喜欢更浓郁的豉汁,可多加0.5汤匙豆豉。,2.0,"混合,搅拌","小碗,汤匙,茶匙",2分钟 +201003272,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,摆盘:将已切好的白鱔段平铺在耐热盘中,尽量不重叠;将姜丝均匀撒在白鱔上;将调好的豉汁均匀淋在白鱔上。,3.0,摆盘,耐热盘,2分钟 +201003273,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,蒸制:在蒸锅或电蒸炉中加入适量水,烧开至沸腾;将装有白鱔的盘子放入蒸锅,盖上锅盖;用中大火蒸约8-10分钟(视白鱔段大小调整时间),至白鱔熟透但不过老(肉质变白,无血水)。,4.0,蒸,蒸锅或电蒸炉,8-10分钟 +201003274,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,装饰与完成:蒸好后取出,撒上葱丝和红椒丝(可选)作装饰;可再淋少许热麻油提升香气;趁热上桌,搭配白饭享用。,5.0,"装饰,淋油","蒸锅,汤匙",1分钟 +201003275,Recipe,贵州辣子鸡,贵州辣子鸡,,Recipe,,荤菜,4.0,黔菜,约20分钟(切鸡、土豆、姜蒜、蒜苗等),约40分钟(炸土豆、炸鸡、炒料、焖煮),3-4人,糍粑辣椒易糊需勤翻炒,dishes\meat_dish\贵州辣子鸡\贵州辣子鸡.md,,,,,,,, +201003276,Ingredient,农村玉米鸡,农村玉米鸡,,Ingredient,,蛋白质,,,,,,,,4,斤,True,,,,, +201003277,Ingredient,啤酒,啤酒,,Ingredient,,调料,,,,,,,,0.5,瓶,False,,,,, +201003278,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,2,个,False,,,,, +201003279,Ingredient,糍粑辣椒,糍粑辣椒,,Ingredient,,调料,,,,,,,,500,克,False,,,,, +201003280,Ingredient,蒜苗,蒜苗,,Ingredient,,蔬菜,,,,,,,,3,根,False,,,,, +201003281,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201003282,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,2,个,False,,,,, +201003283,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",淀粉类,,,,,,,,2,个,False,,,,, +201003284,Ingredient,菜籽油,菜籽油,,Ingredient,,调料,,,,,,,,2,斤,False,,,,, +201003285,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201003286,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003287,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003288,Ingredient,酒糟,酒糟,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003289,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅中倒入约锅一半高度的菜籽油,将切成长条的土豆炸至表面金黄后捞出备用。,1.0,炸,"锅,筷子或漏勺",约3-5分钟 +201003290,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,油温升至烤手程度,放入切好的鸡块、生姜片、花椒,炸至油变清澈后捞出鸡块备用。,2.0,炸,"锅,筷子或漏勺",约8-10分钟 +201003291,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将锅内约三分之一的油盛出备用。,3.0,捞油,"锅铲,容器",约30秒 +201003292,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅中留余油,加入糍粑辣椒、豆瓣酱、生姜片,炒出红油后倒入炸好的鸡块翻炒均匀。,4.0,炒,"锅,锅铲",约2-3分钟 +201003293,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,鸡块上色后加入老抽,倒入啤酒没过鸡块,放入香叶,加盖焖10分钟,期间间隔翻炒。,5.0,"焖,翻炒","锅,锅盖,锅铲",10分钟 +201003294,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入土豆条和整颗大蒜,再焖20分钟。,6.0,焖,"锅,锅盖",20分钟 +201003295,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,最后加入酒糟翻炒均匀,放入切好的蒜苗,即可出锅。,7.0,炒,"锅,锅铲",约1分钟 +201003296,Recipe,酱排骨,酱排骨,,Recipe,,荤菜,4.0,,约5分钟,约45分钟,1人份,"可加豆瓣酱、番茄酱增味,煮排骨时间可调整,可加入鸡蛋做卤蛋",dishes\meat_dish\酱排骨\酱排骨.md,,,,,,,, +201003297,Ingredient,排骨,排骨,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201003298,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201003299,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201003300,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201003301,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201003302,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201003303,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201003304,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201003305,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201003306,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,2,粒,False,,,,, +201003307,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,2,片,False,,,,, +201003308,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,起锅烧热水,放入排骨、姜片、料酒,煮开后用勺子舀去白色油沫,2-3 分钟后出锅,1.0,煮,"锅,勺子",2-3分钟 +201003309,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,冷水清洗排骨,清洗 2-3 遍,2.0,清洗,盆, +201003310,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,小火起锅,加入食用油,加入白砂糖,轻轻搅拌到糖水变成黄色,3.0,炒糖色,"锅,锅铲", +201003311,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入排骨翻炒30秒后,加入生抽、蚝油、五香粉、蒜、小米椒后翻炒30秒后,加入清水没过排骨,4.0,炒,"锅,锅铲",约1分钟 +201003312,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,大火煮30分钟,加入老抽上色,再煮10分钟,5.0,煮,锅,40分钟 +201003313,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,起锅摆盘,6.0,装盘,盘, +201003314,Recipe,酱牛肉,酱牛肉,,Recipe,,荤菜,5.0,,4-6小时(浸泡去血水),3小时(焯水3分钟+小火炖煮180分钟),每份,"观察水位线,每30分钟加水至没过食材",dishes\meat_dish\酱牛肉\酱牛肉.md,,,,,,,, +201003315,Ingredient,牛肉,牛肉,,Ingredient,,蛋白质,,,,,,,,2000,克,True,,,,, +201003316,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,1,片,False,,,,, +201003317,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,3,片,False,,,,, +201003318,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201003319,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201003320,Ingredient,桂皮,桂皮,,Ingredient,,调料,,,,,,,,1,块,False,,,,, +201003321,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,7,粒,False,,,,, +201003322,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,15,粒,False,,,,, +201003323,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,毫升,False,,,,, +201003324,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201003325,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,8,克,False,,,,, +201003326,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,4,个,False,,,,, +201003327,Ingredient,黄豆酱,黄豆酱,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201003328,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,牛肉浸泡 4-6 小时,加料酒、姜片,去除血水,1.0,腌制,盆,4-6小时 +201003329,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,牛肉切成 8cm,不超过 10cm 的肉块,2.0,切,"刀,案板", +201003330,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,牛肉放入锅中,加入冷水至水面没过牛肉,开锅至水沸腾开始计时,3 分钟后停火,捞出牛肉,用温水洗净,3.0,"焯水,煮",锅,3分钟 +201003331,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将洗净后的牛肉放入砂锅或炖锅,加水没过牛肉,开大火,放入除盐之外的其他配料,4.0,炖,"砂锅,炖锅", +201003332,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,水开之后,大火转为小火,持续加热 90 分钟,加盐,5.0,炖,"砂锅,炖锅",90分钟 +201003333,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加盐后,继续小火 90 分钟(注:每 30 分钟确认水位线,要求至少达到牛肉面高度的 80%),6.0,炖,"砂锅,炖锅",90分钟 +201003334,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加热 180 分钟后,捞出牛肉,自然冷却,切片,7.0,"冷却,切","刀,案板", +201003335,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,上桌食用,其他牛肉建议不切片冷藏,8.0,冷藏,, +201003336,Recipe,醉排骨,醉排骨,,Recipe,,荤菜,4.0,闽菜,约10分钟(清洗、腌制),约5分钟(两次油炸),1人份,"鱼露可用生抽代替,正常成品应为金黄色,福建传统名菜",dishes\meat_dish\醉排骨\醉排骨.md,,,,,,,, +201003337,Ingredient,排骨,排骨,,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201003338,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003339,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,500,ml,False,,,,, +201003340,Ingredient,鱼露,鱼露,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201003341,Ingredient,芝麻,芝麻,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003342,Ingredient,番茄酱,番茄酱,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003343,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201003344,Ingredient,蒜头,蒜头,,Ingredient,,蔬菜,,,,,,,,2,粒,False,,,,, +201003345,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201003346,Ingredient,地瓜粉,地瓜粉,,Ingredient,,淀粉类,,,,,,,,30,g,False,,,,, +201003347,Ingredient,鸡蛋黄,鸡蛋黄,,Ingredient,,蛋白质,,,,,,,,1,个,False,,,,, +201003348,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,排骨中加入5 g地瓜粉和水进行搅拌,清洗2-3遍后放入大碗备用,1.0,"清洗,搅拌",大碗,约2分钟 +201003349,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,排骨中加入鱼露、地瓜粉、鸡蛋黄充分搅拌,2.0,"搅拌,腌制",大碗,约2分钟 +201003350,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将排骨一个一个放入锅中(切记不可以整碗倒入),保证每个不要粘在一起,3.0,炸,"锅,勺子",约30秒 +201003351,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,全部放入后,每30秒用勺子来回两面翻转瘦肉块,直至排骨表面金黄,4.0,"炸,翻转","锅,勺子",约2-3分钟 +201003352,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,取出排骨,一分钟后倒入油锅中继续炸,直至瘦肉块表面出现焦黄后,取出放入大碗备用,5.0,复炸,"锅,大碗",约1分钟 +201003353,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,准备一个小碗,加入蒜末、香醋、白砂糖、鱼露、番茄酱、葱花、芝麻搅拌均匀,倒入5 ml热油,6.0,"搅拌,淋油","小碗,锅",约30秒 +201003354,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将汤汁浇灌入排骨,在充分搅拌后倒入盘中,7.0,"搅拌,装盘","大碗,盘子",约30秒 +201003355,Recipe,青椒土豆炒肉,青椒土豆炒肉,,Recipe,"[{'term': '青椒potato炒肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒土豆炒肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '青椒洋芋炒肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒土豆炒肉', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'bell pepper土豆炒肉', 'language': 'en', 'language_code': 'en-US'}, {'term': '青椒马铃薯炒肉', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,,约20分钟,约10分钟,2个人,,dishes\meat_dish\青椒土豆炒肉\青椒土豆炒肉.md,,,,,,,, +201003356,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,200,g,True,,,,, +201003357,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,300,g,True,,,,, +201003358,Ingredient,猪肉(五花肉),猪肉(五花肉),,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201003359,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201003360,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,5,g,False,,,,, +201003361,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,12,g,False,,,,, +201003362,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,7,g,False,,,,, +201003363,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,6-10,ml,False,,,,, +201003364,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201003365,Ingredient,土豆淀粉,土豆淀粉,,Ingredient,,淀粉类,,,,,,,,5,g,False,,,,, +201003366,Ingredient,水,水,,Ingredient,,其他,,,,,,,,15,g,False,,,,, +201003367,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,青椒去除根蒂切小块,土豆去皮切2mm薄片,猪肉切4mm薄片,葱横纵切3mm小段,姜蒜去皮拍散剁碎末;土豆淀粉加入约15g水搅拌均匀至水淀粉。,1.0,切,"刀,案板,盆",约15分钟 +201003368,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,起锅烧油,加热至7成热放入猪肉片,缓缓翻滚炒至去肉红色,加入约3ml酱油,翻炒肉片均匀上色,放入约2g盐。,2.0,炒,"炒锅,锅铲",约2分钟 +201003369,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,转5成油温,加入葱姜蒜炒5秒,然后加入土豆片,转7成油温均匀翻炒,加入约5ml酱油和2g盐,炒至土豆断生,表面轻微焦黄。,3.0,炒,"炒锅,锅铲",约3分钟 +201003370,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,转8成油温加入青椒,大火煸炒出锅气(有白烟冒出),反复均匀翻炒1分钟上色,最后在锅周围倒入水淀粉转4成火勾芡。,4.0,"炒,勾芡","炒锅,锅铲",约1分钟 +201003371,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,在外观呈粘稠状态后关火,盛盘。,5.0,"关火,盛盘","锅铲,盘子",约10秒 +201003372,Recipe,香干芹菜炒肉,香干芹菜炒肉,,Recipe,,荤菜,3.0,,约10分钟(切配、腌制),约8-10分钟(炒制),2人,"芹菜焯水保持爽脆,豆干较硬可焯水,可放花椒水或豆瓣酱增香",dishes\meat_dish\香干芹菜炒肉\香干芹菜炒肉.md,,,,,,,, +201003373,Ingredient,豆干,豆干,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201003374,Ingredient,香芹,香芹,,Ingredient,,蔬菜,,,,,,,,4,根,True,,,,, +201003375,Ingredient,猪肉,猪肉,,Ingredient,,蛋白质,,,,,,,,200,g,True,,,,, +201003376,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,2,瓣,False,,,,, +201003377,Ingredient,辣椒,辣椒,,Ingredient,,蔬菜,,,,,,,,4,个,False,,,,, +201003378,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,6,粒,False,,,,, +201003379,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003380,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201003381,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,8,ml,False,,,,, +201003382,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201003383,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201003384,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,芹菜去叶切段、切成不超过4cm的条状,备用,1.0,切,"刀,案板",约2分钟 +201003385,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,香干切条,宽约小拇指,备用,2.0,切,"刀,案板",约1分钟 +201003386,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,蒜头切片或者剁成蒜泥都行,备用,3.0,切,"刀,案板",约30秒 +201003387,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,辣椒切圈或者斜切成条都行,备用,4.0,切,"刀,案板",约30秒 +201003388,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅,锅内放入10-15ml食用油,等待10秒让油温升高,5.0,炒,炒锅,10秒 +201003389,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入花椒、大蒜爆香(可以吃姜的也可以额外放入一些姜片/姜丝),6.0,爆香,"炒锅,锅铲",约30秒 +201003390,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入猪肉炒至变色,再加入8ml老抽上色翻炒均匀(有豆瓣酱的,可以放入3ml豆瓣酱一起翻炒),7.0,炒,"炒锅,锅铲",约2分钟 +201003391,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入香干翻炒均匀(大约2分钟),8.0,炒,"炒锅,锅铲",约2分钟 +201003392,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入辣椒翻炒均匀(大约1-2分钟),9.0,炒,"炒锅,锅铲",1-2分钟 +201003393,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入芹菜,放入5g盐翻炒1分钟,10.0,炒,"炒锅,锅铲",1分钟 +201003394,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,加入3g鸡精、5ml蚝油翻炒均匀,即可出锅,11.0,炒,"炒锅,锅铲",约30秒 +201003395,Recipe,香煎五花肉,香煎五花肉,,Recipe,"[{'term': '香pan-fried五花肉', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,,15分钟,10分钟,1人,小心被溅出的油烫到,dishes\meat_dish\香煎五花肉\香煎五花肉.md,,,,,,,, +201003396,Ingredient,五花肉条,五花肉条,,Ingredient,,蛋白质,,,,,,,,1,条,True,,,,, +201003397,Ingredient,生菜,生菜,,Ingredient,,蔬菜,,,,,,,,1,朵,True,,,,, +201003398,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201003399,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,8,克,False,,,,, +201003400,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201003401,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201003402,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,克,False,,,,, +201003403,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201003404,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,2,朵,False,,,,, +201003405,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003406,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将五花肉条沿长边切片,每片厚1mm-1.5mm,备用,1.0,切,"刀,案板",5分钟 +201003407,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将切好的五花肉放置碗中,依次加入8g酱油、1g盐、1g味精、10g料酒、两片姜、两朵拍扁的大蒜腌制10分钟,2.0,腌制,碗,10分钟 +201003408,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将生菜叶直接用手扒下来,洗干净,备用,3.0,清洗,手,2分钟 +201003409,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,倒入5ml食用油。油轻微冒烟后下入五花肉。单面煎制焦黄色后翻面,另一边同理,4.0,煎,"平底锅,锅铲",5分钟 +201003410,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,五花肉出锅后,装盘,5.0,装盘,盘子,1分钟 +201003411,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将豆瓣酱抹到菜叶上,卷着五花肉即可食用,6.0,卷,手,1分钟 +201003412,Recipe,香菇滑鸡,香菇滑鸡,,Recipe,,荤菜,3.0,,约15分钟(泡发香菇、切配、去骨、腌制),约8分钟(焯水1分钟+炒鸡3分钟+炖煮2分钟+收汁2分钟),1人份,"鸡腿去骨技巧,香菇水提鲜,程序员效率",dishes\meat_dish\香菇滑鸡\香菇滑鸡.md,,,,,,,, +201003413,Ingredient,大鸡腿,大鸡腿,,Ingredient,,蛋白质,,,,,,,,2,个,True,,,,, +201003414,Ingredient,干香菇,干香菇,,Ingredient,,蔬菜,,,,,,,,5,粒,True,,,,, +201003415,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,2,片,False,,,,, +201003416,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,2,颗,False,,,,, +201003417,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,2,瓣,False,,,,, +201003418,Ingredient,温水,温水,,Ingredient,,其他,,,,,,,,150,毫升,False,,,,, +201003419,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201003420,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,45,毫升,False,,,,, +201003421,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1.5,克,False,,,,, +201003422,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201003423,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201003424,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201003425,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,用温水(30-40℃)泡发干香菇,1.0,泡发,碗,约10分钟 +201003426,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,姜切小块,葱切段,蒜对半切小粒,2.0,切,"刀,案板",2分钟 +201003427,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,鸡腿去骨(可不去骨),切成小块,3.0,"去骨,切","刀,案板",3分钟 +201003428,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,泡发的香菇一分为四,保留泡发香菇的水备用,4.0,切,"刀,案板",1分钟 +201003429,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,鸡腿肉焯水1分钟,去除血沫和杂质,5.0,焯水,"锅,漏勺",1分钟 +201003430,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,鸡腿肉中加入料酒15ml、生抽15ml、盐1.5g、老抽15ml,抓匀腌制,6.0,腌制,盆,2分钟 +201003431,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,锅中油温三成,下入鸡腿肉煸炒至金黄后盛出备用,7.0,炒,"炒锅,锅铲",3分钟 +201003432,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,锅留底油,下入葱、姜、蒜炒香,再加入香菇大火翻匀,8.0,炒,"炒锅,锅铲",20秒 +201003433,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,香菇香味飘出后,加入煸炒过的鸡腿肉,倒入全部香菇水、糖15ml、生抽30ml,9.0,"炒,炖煮","炒锅,锅铲",10秒 +201003434,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,转中火不盖盖炖煮2分钟收浓汤汁,淋入香油5ml,撒上葱花后关火装盘,10.0,"炖煮,收汁","炒锅,锅铲",2分钟 +201003435,Recipe,香辣鸡爪煲,香辣鸡爪煲,,Recipe,,荤菜,4.0,川菜,约10分钟(剪指甲、清洗、切配料),约40分钟(焯水+炖煮30分钟+炒制10分钟),1斤鸡爪(约2-3人份),"可加配菜,Q弹口感,香辣浓郁",dishes\meat_dish\香辣鸡爪煲\香辣鸡爪煲.md,,,,,,,, +201003436,Ingredient,鸡爪,鸡爪,,Ingredient,,蛋白质,,,,,,,,500,克,True,,,,, +201003437,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,3,片,False,,,,, +201003438,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,个,False,,,,, +201003439,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,6,个,False,,,,, +201003440,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,10,克,False,,,,, +201003441,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,10,克,False,,,,, +201003442,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,2,根,False,,,,, +201003443,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201003444,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201003445,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201003446,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201003447,Ingredient,辣椒面,辣椒面,,Ingredient,,调料,,,,,,,,可选,,False,,,,, +201003448,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003449,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003450,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003451,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,给鸡爪剪去指甲;如为整只鸡爪需去骨,再用清水洗净。,1.0,切,"剪刀,刀,案板,盆",5分钟 +201003452,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,鸡爪冷水下锅,加入葱、姜、料酒焯水,水开后撇去浮沫。,2.0,焯水,"锅,漏勺",3-5分钟 +201003453,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入香叶、八角、生抽、老抽,盖盖小火慢煮三十分钟。,3.0,炖,"锅,锅盖",30分钟 +201003454,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,捞出鸡爪,留一碗鸡汤备用。,4.0,捞,"漏勺,碗",1分钟 +201003455,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,起锅烧油,小火炒香姜末、蒜末、小米椒,能吃辣可再加辣椒面。,5.0,炒,"炒锅,锅铲",1-2分钟 +201003456,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入生抽、老抽、蚝油、五香粉、盐,炒出酱香味。,6.0,炒,锅铲,30秒 +201003457,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入鸡爪,加少许盐调味,翻炒1-2分钟,再倒入预留鸡汤,边炒边搅动。,7.0,炒,锅铲,2-3分钟 +201003458,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入鸡精提鲜,撒葱段搅拌均匀即可出锅。,8.0,炒,锅铲,30秒 +201003459,Recipe,鱼香茄子,鱼香茄子,,Recipe,"[{'term': '鱼香eggplant', 'language': 'en', 'language_code': 'en-US'}, {'term': '鱼香紫茄子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鱼香青茄子', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,川菜,10分钟,15分钟,1人,"茄子可去皮,肉沫可增量,超级下饭",dishes\meat_dish\鱼香茄子\鱼香茄子.md,,,,,,,, +201003460,Ingredient,茄子,茄子,,Ingredient,,蔬菜,,,,,,,,2,根,True,,,,, +201003461,Ingredient,肉末,肉末,,Ingredient,,蛋白质,,,,,,,,20,克,True,,,,, +201003462,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3-5,克,False,,,,, +201003463,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,5-10,克,False,,,,, +201003464,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201003465,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,毫升,False,,,,, +201003466,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,毫升,False,,,,, +201003467,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201003468,Ingredient,水淀粉,水淀粉,,Ingredient,,淀粉类,,,,,,,,100,毫升,False,,,,, +201003469,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,20-30,克,False,,,,, +201003470,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,适量,,False,,,,, +201003471,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003472,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003473,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003474,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将茄子切成条。,1.0,切,"刀,案板",2分钟 +201003475,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将肉切成肉沫,葱姜蒜切碎、小米椒切丁。,2.0,切,"刀,案板",3分钟 +201003476,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,调鱼香汁:碗中放入盐、味精、糖、生抽、老抽、醋、水淀粉搅拌均匀。,3.0,搅拌,"碗,筷子",1分钟 +201003477,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅中倒入300毫升油,开小火,等油温七成热(小火约40秒,有烟冒出)放入茄子炸两分钟,当茄子边缘微黄就捞出。,4.0,炸,"炒锅,漏勺",2-3分钟 +201003478,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中留15-30毫升油,倒入肉沫炒至颜色变白就盛出来。,5.0,炒,"炒锅,锅铲",1分钟 +201003479,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锅中再倒入15-30毫升油,放入豆瓣酱、葱白、姜、蒜炒香,然后倒入肉沫翻炒均匀。,6.0,炒,"炒锅,锅铲",1分钟 +201003480,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入80-150毫升清水(水面预计茄子八成高度为准),倒入茄子、倒入料汁,爆炒入味收汁。最后放入葱翻炒均匀,就可以起锅了。,7.0,"爆炒,收汁","炒锅,锅铲",3-4分钟 +201003481,Recipe,麻婆豆腐,麻婆豆腐,,Recipe,"[{'term': '麻婆tofu', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '麻婆老豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '麻婆嫩豆腐', 'language': 'zh', 'language_code': 'zh-CN'}]",荤菜,3.0,川菜,约10分钟,约12分钟,1人份,防止糊锅,dishes\meat_dish\麻婆豆腐\麻婆豆腐.md,,,,,,,, +201003482,Ingredient,内脂豆腐,内脂豆腐,,Ingredient,,蛋白质,,,,,,,,1,盒,True,,,,, +201003483,Ingredient,咸鸭蛋,咸鸭蛋,,Ingredient,,蛋白质,,,,,,,,1,枚,True,,,,, +201003484,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,20,g,True,,,,, +201003485,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,2,瓣,False,,,,, +201003486,Ingredient,生姜,生姜,,Ingredient,,蔬菜,,,,,,,,2,片,False,,,,, +201003487,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,5,根,False,,,,, +201003488,Ingredient,香辣酱,香辣酱,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003489,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,20,颗,False,,,,, +201003490,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201003491,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003492,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,10,ml,False,,,,, +201003493,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,适量,ml,False,,,,, +201003494,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,大蒜和生姜切碎,备用,1.0,切,刀, +201003495,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,小米辣切成辣椒圈,备用,2.0,切,刀, +201003496,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,五花肉切成肉糜(本来就是买的肉糜的跳过),3.0,切,刀, +201003497,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,肉糜中加入一半的食盐和味极鲜酱油,搅拌均匀,备用,4.0,"腌制,搅拌","盆,筷子", +201003498,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,鸭蛋用菜刀竖着对半切开(注意安全),去除蛋黄(一定要去除,不然会腥),剩下的蛋白捣碎成大约 2 mm * 2 mm 大小,不用太碎,备用,5.0,"切,捣碎","刀,案板", +201003499,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,打开豆腐包装,用水果刀将在盒子中的豆腐划成大约 2.5 cm * 3 cm 大小,备用,6.0,切,水果刀, +201003500,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,热锅,锅内放入 10ml - 15ml 食用油。等待 10 秒让油温升高,7.0,加热,炒锅,10秒 +201003501,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,调成小火,放入大蒜、生姜、辣椒圈、花椒、咸鸭蛋、蒜蓉辣酱翻炒 20 秒,炒出香味,8.0,炒,"炒锅,锅铲",20秒 +201003502,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,调成中火,放入肉糜,翻炒大约 1 分钟,肉炒变色,9.0,炒,"炒锅,锅铲",1分钟 +201003503,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,调成小火,放入豆腐,将剩下的食盐、味极鲜酱油酱油均匀的洒在豆腐上,10.0,调味,锅铲, +201003504,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,从锅边倒入开水(不然豆腐容易破),没过豆腐即可,11.0,煮,锅铲, +201003505,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,开大火,水沸腾后立马转入中火,等待大约 10 分钟,12.0,"煮,炖",炒锅,10分钟 +201003506,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,等到水只剩 1/5 并且豆腐表面已经入色,关火,盛盘,13.0,"收汁,装盘",锅铲, +201003507,Recipe,黑椒牛柳,黑椒牛柳,,Recipe,,荤菜,4.0,,腌制时间(按商品说明)+ 20分钟静置,约5分钟,2-3人,"蔬菜与肉类均衡,富含蛋白质,适合初学者,建议使用不粘锅",dishes\meat_dish\黑椒牛柳\黑椒牛柳.md,,,,,,,, +201003508,Ingredient,牛肉,牛肉,,Ingredient,,蛋白质,,,,,,,,100,克,True,,,,, +201003509,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,1/12,个,False,,,,, +201003510,Ingredient,菜椒,菜椒,,Ingredient,,蔬菜,,,,,,,,1/12,个,False,,,,, +201003511,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,3,克,False,,,,, +201003512,Ingredient,黑胡椒(粉),黑胡椒(粉),,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201003513,Ingredient,黑椒腌料,黑椒腌料,,Ingredient,,调料,,,,,,,,按商品说明,,False,,,,, +201003514,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201003515,Ingredient,花生油,花生油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201003516,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将牛肉切条,长度最好控制在8厘米以下,厚度约5-10毫米,宽度约1厘米(要求不严格),1.0,切,"刀,案板", +201003517,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,利用腌料腌制牛肉,混合均匀后静置,用量与时间请参照商品说明,可以延长不能缩短,2.0,腌制,盆,按商品说明 +201003518,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,如果使用液态腌料,可以在腌制结束前三分钟撒一层黑胡椒粉,然后再加入淀粉,再次混合均匀后静置20分钟,3.0,"腌制,撒,混合",盆,20分钟 +201003519,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,开火,热锅,加入花生油,4.0,加热,不粘锅, +201003520,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,当能看到锅里的油冒出一丝烟时,放入牛肉,翻炒,5.0,炒,"不粘锅,锅铲", +201003521,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,开中火偏大,翻炒2分钟至牛肉外表变色(即不出现明显血色,有血色部分说明翻炒不到位)(此处应小心油滴溅射),6.0,炒,"不粘锅,锅铲",2分钟 +201003522,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入洋葱和菜椒,翻炒2分钟,7.0,炒,"不粘锅,锅铲",2分钟 +201003523,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入盐,再次撒一份黑胡椒粉,翻炒30秒,搅拌均匀,8.0,"撒,炒","不粘锅,锅铲",30秒 +201003524,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,观察洋葱已经变软即可关火,出锅,盛盘,9.0,"关火,盛盘","不粘锅,锅铲,盘子", +201003525,Recipe,黔式腊肠娃娃菜,黔式腊肠娃娃菜,,Recipe,,荤菜,1.0,西南菜,0分钟,15分钟,1人,"水量宁多勿少,可不切直接食用",dishes\meat_dish\黔式腊肠娃娃菜\黔式腊肠娃娃菜.md,,,,,,,, +201003526,Ingredient,黔式腊肠,黔式腊肠,,Ingredient,,蛋白质,,,,,,,,200,克,True,,,,, +201003527,Ingredient,娃娃菜,娃娃菜,,Ingredient,,蔬菜,,,,,,,,300,克,True,,,,, +201003528,Ingredient,水,水,,Ingredient,,其他,,,,,,,,750,毫升,False,,,,, +201003529,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅内放入750ml水,开火加热至沸腾,1.0,煮,锅, +201003530,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,放入腊肠,计时13分钟,2.0,煮,锅,13分钟 +201003531,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放入娃娃菜,计时2分钟,3.0,煮,锅,2分钟 +201003532,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,关火,夹出腊肠及娃娃菜,4.0,夹取,筷子, +201003533,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,娃娃菜切段、腊肠切片,装盘,5.0,切,"刀,案板", +201003534,Recipe,凉皮,凉皮,,Recipe,,半成品,3.0,西北菜,约10分钟,约2分钟,1人,"个人口味可调,夏季凉菜,快手,可增辣",dishes\semi-finished\凉皮.md,,,,,,,, +201003535,Ingredient,凉皮,凉皮,,Ingredient,,淀粉类,,,,,,,,300,g,True,,,,, +201003536,Ingredient,面筋,面筋,,Ingredient,,蛋白质,,,,,,,,,适量,True,,,,, +201003537,Ingredient,芝麻酱,芝麻酱,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201003538,Ingredient,黄瓜,黄瓜,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201003539,Ingredient,绿豆芽,绿豆芽,,Ingredient,,蔬菜,,,,,,,,50,g,True,,,,, +201003540,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003541,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,,适量,False,,,,, +201003542,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,,适量,False,,,,, +201003543,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,,适量,False,,,,, +201003544,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,,适量,False,,,,, +201003545,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,,适量,False,,,,, +201003546,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,,适量,False,,,,, +201003547,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,,适量,False,,,,, +201003548,Ingredient,辣椒油,辣椒油,,Ingredient,,调料,,,,,,,,,可选,False,,,,, +201003549,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅中加入500ml水,煮沸。,1.0,煮,锅,约2分钟 +201003550,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将绿豆芽放入锅中,大火煮60秒,捞出过凉水备用。,2.0,"煮,焯水,冷却","锅,漏勺,冷水盆",60秒 +201003551,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,黄瓜切丝备用。,3.0,切,"刀,案板",约1分钟 +201003552,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将10g蒜瓣剥皮,加入1g盐捣成蒜泥,加入10g自来水调匀备用。,4.0,"捣,调","蒜臼,小碗",约1分钟 +201003553,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,清洗凉皮与面筋,挤干面筋水分。,5.0,"洗,挤水","自来水,手",约1分钟 +201003554,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,在小碗中混合3g盐、2g鸡精、5g生抽、1g老抽、1g香油、2g蚝油、5g香醋,加入25-35g温水调匀成盐水。,6.0,调,"小碗,筷子",约1分钟 +201003555,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,在小碗中放入30g芝麻酱,加入4g盐、3g鸡精、5g生抽、1g老抽、3g蚝油拌匀,分次加入10g清水调至顺滑。,7.0,调,"小碗,筷子",约2分钟 +201003556,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将凉皮放入小盆,倒入盐水拌匀后盛入小碗。,8.0,拌,"小盆,小碗,筷子",约30秒 +201003557,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,在凉皮上依次摆放绿豆芽、面筋,淋上芝麻酱,撒上黄瓜丝,可按喜好加辣椒油。,9.0,摆盘,"小碗,筷子",约30秒 +201003558,Recipe,半成品意面,半成品意面,,Recipe,,半成品,1.0,意大利,0分钟,2分钟,2人,"意大利面,杜兰小麦,快速,微波,平底锅",dishes\semi-finished\半成品意面.md,,,,,,,, +201003559,Ingredient,半成品意大利面,半成品意大利面,,Ingredient,,淀粉类,,,,,,,,520,g,True,,,,, +201003560,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,50,ml,False,,,,, +201003561,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,热锅,1.0,加热,平底锅,约10秒 +201003562,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将50 ml清水倒入平底锅,2.0,倒,平底锅,约5秒 +201003563,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将面条放入,炒1分钟,3.0,炒,"平底锅,锅铲",1分钟 +201003564,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将酱料倒入,翻炒1分钟,4.0,炒,"平底锅,锅铲",1分钟 +201003565,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,装盘即可,5.0,装盘,盘子,约5秒 +201003566,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将面条放入可用于微波炉加热的盘子中,1.0,放,微波炉专用盘,约5秒 +201003567,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将附带的酱料倒在面条上,2.0,倒,微波炉专用盘,约5秒 +201003568,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,倒入50 ml清水,3.0,倒,微波炉专用盘,约5秒 +201003569,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,700W加热2分钟,4.0,微波加热,微波炉,2分钟 +201003570,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,取出拌匀即可,5.0,搅拌,筷子或叉子,约10秒 +201003571,Recipe,牛油火锅底料,牛油火锅底料,,Recipe,,半成品,5.0,川菜,约30分钟(香料处理、切配),约1小时(炒制+静置),7.5 kg,"操作时擦干手上水滴,防止水入油锅爆炸,静置5天后风味更佳,老油需二次炼干水分",dishes\semi-finished\牛油火锅底料.md,,,,,,,, +201003572,Ingredient,牛油,牛油,,Ingredient,,脂肪,,,,,,,,4500,g,True,,,,, +201003573,Ingredient,色拉油,色拉油,,Ingredient,,脂肪,,,,,,,,1000,ml,False,,,,, +201003574,Ingredient,菜籽油,菜籽油,,Ingredient,,脂肪,,,,,,,,1000,ml,False,,,,, +201003575,Ingredient,纯猪油,纯猪油,,Ingredient,,脂肪,,,,,,,,500,g,False,,,,, +201003576,Ingredient,郫县豆瓣,郫县豆瓣,,Ingredient,,调料,,,,,,,,1000,g,False,,,,, +201003577,Ingredient,糍粑辣椒,糍粑辣椒,,Ingredient,,调料,,,,,,,,3000,g,False,,,,, +201003578,Ingredient,老姜,老姜,,Ingredient,,蔬菜,,,,,,,,400,g,False,,,,, +201003579,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,100,g,False,,,,, +201003580,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,100,g,False,,,,, +201003581,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,300,g,False,,,,, +201003582,Ingredient,永川豆鼓,永川豆鼓,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003583,Ingredient,豆母子,豆母子,,Ingredient,,调料,,,,,,,,140,g,False,,,,, +201003584,Ingredient,红花椒,红花椒,,Ingredient,,调料,,,,,,,,150,g,False,,,,, +201003585,Ingredient,颗粒香料,颗粒香料,,Ingredient,,调料,,,,,,,,100,g,False,,,,, +201003586,Ingredient,整形香料,整形香料,,Ingredient,,调料,,,,,,,,150,g,False,,,,, +201003587,Ingredient,麦芽粉,麦芽粉,,Ingredient,,调料,,,,,,,,12.5,g,False,,,,, +201003588,Ingredient,52%VOL白酒,52%VOL白酒,,Ingredient,,调料,,,,,,,,150,ml,False,,,,, +201003589,Ingredient,干辣椒面,干辣椒面,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201003590,Ingredient,山奈,山奈,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003591,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201003592,Ingredient,草果,草果,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003593,Ingredient,肉桂,肉桂,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003594,Ingredient,丁香,丁香,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003595,Ingredient,小茴香,小茴香,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003596,Ingredient,白芷,白芷,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003597,Ingredient,荜拨,荜拨,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003598,Ingredient,香草,香草,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003599,Ingredient,香果,香果,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003600,Ingredient,山楂,山楂,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003601,Ingredient,陈皮,陈皮,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003602,Ingredient,香茅,香茅,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003603,Ingredient,砂仁,砂仁,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003604,Ingredient,白蔻,白蔻,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003605,Ingredient,香叶,香叶,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003606,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅置旺火,放入牛油烧至八成热(240±10°C),加入老姜100g、大葱100g、洋葱100g、大蒜100g炸干吸尽牛油腥味后捞出扔掉。,1.0,炸,锅,约2-3分钟 +201003607,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入色拉油或菜籽油1000ml、纯猪油500g,待油温降至五成热(150±10°C)时放入糍粑辣椒3000g,持续翻炒5-8分钟。,2.0,炒,锅,5-8分钟 +201003608,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入郫县豆瓣1000g炒散,转中小火慢炒至料渣略发白翻砂并发出沙沙声。,3.0,炒,锅,约10-15分钟 +201003609,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,当油呈樱桃红色时,加入姜片150g、大蒜100g炒香约15秒。,4.0,炒,锅,15秒 +201003610,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入剁碎的永川豆鼓10g、豆母子140g炒香,再加入红花椒150g、小茴香10g炒香。,5.0,炒,锅,约1-2分钟 +201003611,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入颗粒香料100g(已打碎至4mm颗粒)继续炒香。,6.0,炒,锅,约1分钟 +201003612,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入麦芽粉12.5g炒散,再沿锅边淋入52%VOL白酒150ml炒散。,7.0,炒,锅,约30秒 +201003613,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,作为底料:起锅装入容器,置于10-20°C环境静置5天后使用风味最佳。,8.0,静置,容器,5天 +201003614,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,作为老油:起锅后趁热加入干辣椒面15g搅匀,静置24小时。,9.0,静置,容器,24小时 +201003615,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将底料倒入锅中,加入3/5开水(底料:开水=2:3),大火烧开并撇去浮沫。,10.0,煮,锅,约5分钟 +201003616,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,转中小火慢熬25-30分钟出味后过滤去渣。,11.0,"熬,过滤","锅,滤网",25-30分钟 +201003617,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,静置待油水分离,将表面油脂撇出,重新倒入净锅炼干水分,起锅装容器即为火锅老油。,12.0,"撇油,炼干","锅,容器",约10分钟 +201003618,Recipe,速冻水饺,速冻水饺,,Recipe,,半成品,1.0,,0分钟,约8分钟,1人,"蘸料搭配,黑醋,姜丝,香油,蒜泥,防粘锅技巧,加凉水防夹生",dishes\semi-finished\速冻水饺.md,,,,,,,, +201003619,Ingredient,速冻水饺,速冻水饺,,Ingredient,,其他,,,,,,,,7,个,True,,,,, +201003620,Ingredient,水,水,,Ingredient,,其他,,,,,,,,14,个体积,False,,,,, +201003621,Ingredient,黑醋,黑醋,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201003622,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,50,克,False,,,,, +201003623,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,2,滴,False,,,,, +201003624,Ingredient,大蒜/蒜泥,大蒜/蒜泥,,Ingredient,,蔬菜,,,,,,,,3,瓣,False,,,,, +201003625,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,中火,将水倒入锅中,静候水煮沸。,1.0,煮,锅, +201003626,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将饺子倒入锅中。倒入锅前可以适当用水过一下。,2.0,煮,锅, +201003627,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,倒入饺子后,用炒菜勺子或铲子搅水,注意不要铲到饺子上,避免粘锅或互相粘连。频率为平均每30秒摇3秒,饺子浮起后停止。,3.0,"煮,搅拌","炒菜勺子,铲子",30秒摇3秒 +201003628,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,饺子浮起及水再次煮沸后,盛起一个饺子观察,若面皮夹生则舀入80ml凉水降温,继续煮至沸腾,最多加两次水即可全熟。,4.0,"煮,观察",炒菜勺子, +201003629,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,所有饺子浮起后(约8分钟),用铲子或漏勺将饺子铲入盘或碗中,装盘后即可食用。,5.0,装盘,"铲子,漏勺,盘或碗",约8分钟 +201003630,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,吃完饺子后,等锅内水温降低,将水倒掉并用洗洁精及时刷锅,防止面粉在锅壁形成黏糊物质。,6.0,清洗,"洗洁精,锅", +201003631,Recipe,速冻馄饨,速冻馄饨,,Recipe,,半成品,2.0,,0分钟,55分钟,1人,可搭配太阳蛋,dishes\semi-finished\速冻馄饨.md,,,,,,,, +201003632,Ingredient,速冻馄饨,速冻馄饨,,Ingredient,,淀粉类,,,,,,,,16,个,True,,,,, +201003633,Ingredient,水,水,,Ingredient,,其他,,,,,,,,600,毫升,False,,,,, +201003634,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003635,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003636,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003637,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003638,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,根,False,,,,, +201003639,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将水倒入电饭煲中,按炖或煮的模式运行35分钟,直至水沸腾。,1.0,煮,电饭煲,35分钟 +201003640,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将速冻馄饨小心放入沸水中,可提前用水冲一下;若有调料包,此时一并加入。,2.0,煮,电饭煲, +201003641,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,盖上电饭煲,继续按炖或煮模式运行20分钟。,3.0,煮,电饭煲,20分钟 +201003642,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将馄饨连同汤汁盛入碗中,按需加入盐、鸡精、胡椒粉、香油调味,可撒香菜叶增香。,4.0,盛,碗, +201003643,Recipe,懒人蛋挞,懒人蛋挞,,Recipe,,半成品,3.0,,5分钟,20-30分钟,1份,"可加入碎芝士做芝士蛋挞,根据焦褐斑大小调整时间",dishes\semi-finished\懒人蛋挞\懒人蛋挞.md,,,,,,,, +201003644,Ingredient,蛋挞皮,蛋挞皮,,Ingredient,,淀粉类,,,,,,,,1,个,True,,,,, +201003645,Ingredient,蛋挞液,蛋挞液,,Ingredient,,其他,,,,,,,,10,毫升,True,,,,, +201003646,Ingredient,碎芝士,碎芝士,,Ingredient,,蛋白质,,,,,,,,10,克,False,,,,, +201003647,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,烤箱预热至200度,预热10分钟,1.0,预热,烤箱,10分钟 +201003648,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,在烤盘上摆放蛋挞皮,倒入蛋挞液约10ml至挞皮4/5高度,2.0,倒,烤盘,2分钟 +201003649,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将烤盘放入烤箱,上下火190度烤10-20分钟;若想快速出现焦褐斑点,上火调至200-210度,3.0,烤,烤箱,10-20分钟 +201003650,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,观察蛋挞液出现焦褐斑点且蛋挞皮完全蓬松冒油即可出炉,4.0,观察,烤箱,1分钟 +201003651,Recipe,炸薯条,炸薯条,,Recipe,"[{'term': '油炸薯条', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'deep-fried薯条', 'language': 'en', 'language_code': 'en-US'}]",半成品,2.0,,5分钟(预热+开封),20分钟,1人,"空气炸锅,脆化技巧,酱料搭配,减少热量消耗",dishes\semi-finished\炸薯条\炸薯条.md,,,,,,,, +201003652,Ingredient,半成品薯条,半成品薯条,,Ingredient,,淀粉类,,,,,,,,400,克,True,,,,, +201003653,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,开封大分量半成品薯条,注意开口要小,减少结霜。,1.0,开封,剪刀或刀具,1分钟 +201003654,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,空气炸锅插电,200℃预热5分钟。,2.0,预热,空气炸锅,5分钟 +201003655,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,取出薯条放入空气炸锅,200℃炸20分钟;5~10分钟时取出锅体晃动使受热均匀。,3.0,炸,"空气炸锅,夹持工具",20分钟 +201003656,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,可选:10~15分钟时取出锅体,向薯条表面喷一层油(覆盖2/3表面积)以增加脆度。,4.0,喷油,喷油壶,1分钟 +201003657,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,取出薯条并装盘;喜欢脆的可摇晃锅体让空气经过薯条表面。,5.0,装盘,"锅体,盘子",1分钟 +201003658,Recipe,空气炸锅羊排,空气炸锅羊排,,Recipe,"[{'term': '空气deep-fried锅羊排', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '空气油炸锅羊排', 'language': 'zh', 'language_code': 'zh-CN'}]",半成品,3.0,西北菜,25分钟,15分钟,1人,"温控好的空气炸锅,懒人版,看羊排品质",dishes\semi-finished\空气炸锅羊排\空气炸锅羊排.md,,,,,,,, +201003659,Ingredient,羊排,羊排,,Ingredient,,蛋白质,,,,,,,,160,克,True,,,,, +201003660,Ingredient,黑椒混合牛排调味料,黑椒混合牛排调味料,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201003661,Ingredient,蒜蓉酱,蒜蓉酱,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201003662,Ingredient,黄油,黄油,,Ingredient,,其他,,,,,,,,10,克,False,,,,, +201003663,Ingredient,烧烤料,烧烤料,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201003664,Ingredient,罗勒碎,罗勒碎,,Ingredient,,调料,,,,,,,,适量,克,False,,,,, +201003665,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,羊排放入碗中清水洗净血水,1.0,洗,碗,2分钟 +201003666,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,羊排用厨房纸吸干水分,双面抹上黑椒混合调味料、蒜蓉酱,静置腌制20分钟,2.0,"吸干,抹,腌制","厨房纸,碗",20分钟 +201003667,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锡纸碗放上烤架,羊排放在烤架上,撒上罗勒碎,黄油或烧烤料放在羊排上,空气炸锅180°烤10分钟,3.0,"撒,烤","锡纸碗,烤架,空气炸锅",10分钟 +201003668,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,羊排翻面,撒上罗勒碎,黄油(从锡纸碗里舀上来)或烧烤料放在羊排上,空气炸锅180°再烤5分钟,4.0,"翻面,撒,烤",空气炸锅,5分钟 +201003669,Recipe,空气炸锅鸡翅中,空气炸锅鸡翅中,,Recipe,"[{'term': '空气油炸锅鸡翅中', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '空气deep-fried锅鸡翅中', 'language': 'zh', 'language_code': 'zh-CN'}]",半成品,2.0,,20分钟(解冻),17分钟,1人,推荐购买温控好的空气炸锅,避免烤糊,dishes\semi-finished\空气炸锅鸡翅中\空气炸锅鸡翅中.md,,,,,,,, +201003670,Ingredient,鸡翅中,鸡翅中,,Ingredient,,蛋白质,,,,,,,,6,个,True,,,,, +201003671,Ingredient,罗勒碎,罗勒碎,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003672,Ingredient,云南单山蘸水,云南单山蘸水,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003673,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡翅从冰箱取出,鸡翼面朝下放入锡纸烤盘,撒上罗勒碎,盖上保鲜膜自然解冻20分钟,1.0,解冻,"锡纸烤盘,保鲜膜",20分钟 +201003674,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,撒上罗勒碎,空气炸锅200°C,烤10分钟,2.0,烤,空气炸锅,10分钟 +201003675,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,翻面,再撒罗勒碎,空气炸锅200°C,继续烤7分钟,3.0,烤,空气炸锅,7分钟 +201003676,Recipe,速冻汤圆,速冻汤圆,,Recipe,,半成品,1.0,,1分钟,4-5分钟,1人份,"先加汤圆再加热水,避免烫伤,碗过热可用毛巾或托盘取出",dishes\semi-finished\速冻汤圆\速冻汤圆.md,,,,,,,, +201003677,Ingredient,速冻汤圆,速冻汤圆,,Ingredient,,淀粉类,,,,,,,,11,个,True,,,,, +201003678,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,浸没汤圆,毫升,False,,,,, +201003679,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,取出速冻汤圆,放入碗中。,1.0,"取,放",碗,30秒 +201003680,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,倒入开水,直至浸没汤圆。,2.0,倒,碗,30秒 +201003681,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,微波炉高火 4 分钟。,3.0,微波加热,微波炉,4分钟 +201003682,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,假如汤圆均已吸水膨胀,则已熟。如果没熟,再加热 1 分钟。,4.0,"观察,微波加热",微波炉,1分钟 +201003683,Recipe,奶油蘑菇汤,奶油蘑菇汤,,Recipe,,汤类,1.0,,10分钟,15分钟,1-2人,"预留蘑菇煎香装饰,鸡高汤替代清水,增加面粉和淡奶油可更浓稠,现做现吃",dishes\soup\奶油蘑菇汤.md,,,,,,,, +201003684,Ingredient,白蘑菇,白蘑菇,,Ingredient,,蔬菜,,,,,,,,200,克,True,,,,, +201003685,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,50,克,True,,,,, +201003686,Ingredient,黄油,黄油,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201003687,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,10,克,False,,,,, +201003688,Ingredient,牛奶,牛奶,,Ingredient,,其他,,,,,,,,200,毫升,True,,,,, +201003689,Ingredient,淡奶油,淡奶油,,Ingredient,,其他,,,,,,,,30,毫升,False,,,,, +201003690,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,100,毫升,False,,,,, +201003691,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201003692,Ingredient,黑胡椒碎,黑胡椒碎,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201003693,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,白蘑菇切片备用,洋葱切末备用。,1.0,切,"刀,案板",5分钟 +201003694,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,平底锅中放入黄油,小火融化后加入洋葱炒至透明。,2.0,炒,"平底锅,锅铲",2-3分钟 +201003695,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入白蘑菇翻炒至出水变软,撒入面粉搅拌均匀。,3.0,"炒,搅拌",锅铲,3-4分钟 +201003696,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入牛奶和清水,搅拌均匀后小火煮沸,保持搅拌防止糊底。,4.0,"煮,搅拌",锅铲,2-3分钟 +201003697,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,转小火煮约10分钟,汤汁浓稠。,5.0,煮,锅铲,10分钟 +201003698,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入淡奶油继续加热1分钟,加入盐和黑胡椒调味。,6.0,"加热,调味",锅铲,1分钟 +201003699,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,熄火后可用料理机打成细腻浓汤(可选)。,7.0,搅拌,料理机,30秒 +201003700,Recipe,小米粥,小米粥,,Recipe,,汤类,2.0,,2分钟,30-35分钟,2-3人,"水开后下锅,不可过度淘洗,锅盖留缝保小米油,普通锅最佳,高压锅/电饭锅水量减至1800克",dishes\soup\小米粥.md,,,,,,,, +201003701,Ingredient,小米,小米,,Ingredient,,淀粉类,,,,,,,,100,克,True,,,,, +201003702,Ingredient,水,水,,Ingredient,,其他,,,,,,,,2000,克,False,,,,, +201003703,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,小米 100 克放入碗中,用水轻淘一遍(用手搅拌一下,将水倒掉,只是去掉外面的浮灰,不可搓洗),1.0,淘洗,碗,1分钟 +201003704,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,水烧开,务必烧开,2.0,煮,锅,3-5分钟 +201003705,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,水沸腾时将小米倒入锅内,搅拌使小米不粘连锅底,继续用大火熬6-10分钟,期间穿插搅拌几次,3.0,"煮,搅拌","锅,勺子",6-10分钟 +201003706,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,改中火、文火熬15-20分钟,锅盖错开一条缝,期间继续搅拌几次,防止糊锅底,4.0,"煮,搅拌","锅,勺子",15-20分钟 +201003707,Recipe,生汆丸子汤,生汆丸子汤,,Recipe,,汤类,4.0,,约20分钟(剁肉、调味、配菜准备),约5分钟(汆丸子+冲汤),1人,"鲜嫩弹,手工剁肉,葱姜花椒水去腥,熟豆油锁嫩,辣椒油可选",dishes\soup\生汆丸子汤.md,,,,,,,, +201003708,Ingredient,前腿肉,前腿肉,,Ingredient,,蛋白质,,,,,,,,500,克,True,,,,, +201003709,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201003710,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201003711,Ingredient,葱姜花椒水,葱姜花椒水,,Ingredient,,调料,,,,,,,,400,克,False,,,,, +201003712,Ingredient,鸡蛋清,鸡蛋清,,Ingredient,,蛋白质,,,,,,,,1,个,False,,,,, +201003713,Ingredient,土豆淀粉,土豆淀粉,,Ingredient,,淀粉类,,,,,,,,40,克,False,,,,, +201003714,Ingredient,熟豆油,熟豆油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003715,Ingredient,木耳,木耳,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003716,Ingredient,黄花,黄花,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003717,Ingredient,小香葱,小香葱,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003718,Ingredient,粉丝,粉丝,,Ingredient,,淀粉类,,,,,,,,适量,,False,,,,, +201003719,Ingredient,鸡粉,鸡粉,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201003720,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,3,滴,False,,,,, +201003721,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,小颗,False,,,,, +201003722,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,肉改刀切开,肥瘦三七分,上刀剁一剁,用刀背砸一砸,把肉筋打开打松疏,继续剁成肉末。,1.0,"切,剁,砸","刀,案板",约10分钟 +201003723,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,每斤肉加6克盐、1克胡椒粉,上手抓匀;葱姜花椒水分次加入,边加边搅,让肉吸饱水(每斤肉末80克葱姜花椒水);加入鸡蛋清顺一个方向搅;再加入40克土豆淀粉搅匀;最后加熟豆油保持嫩滑弹。,2.0,"抓,搅拌,揉","盆,手",约5分钟 +201003724,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,起锅烧水,烧开后改小火至似开非开状态,用手挤丸子下锅,待全部漂起后用小火再煮1分钟。,3.0,"煮,汆","锅,手",约3分钟 +201003725,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,粉丝放碗底,加入木耳、黄花、小香葱,并用盐、胡椒粉、鸡粉打底调味;将连汤带丸子冲入碗中,淋3-5滴香油,最后加一小颗香菜即可。,4.0,"冲汤,调味","碗,勺",约1分钟 +201003726,Recipe,番茄牛肉蛋花汤,番茄牛肉蛋花汤,,Recipe,,汤类,3.0,,20-25分钟(含腌制15-20分钟),约10分钟,按人数计算,"可调酸度,可调辣度,可加醋,可加糖,可加辣椒",dishes\soup\番茄牛肉蛋花汤.md,,,,,,,, +201003727,Ingredient,牛肉,牛肉,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201003728,Ingredient,番茄,番茄,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201003729,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201003730,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,适量,根,False,,,,, +201003731,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,适量,片,False,,,,, +201003732,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,适量,瓣,False,,,,, +201003733,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201003734,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,0.5,g,False,,,,, +201003735,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,牛肉切成薄片,1.0,切,"刀,案板",2-3分钟 +201003736,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,番茄切成小块,2.0,切,"刀,案板",1-2分钟 +201003737,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,葱切成葱花,姜切成姜片,蒜剁成蒜泥,3.0,"切,剁","刀,案板",2-3分钟 +201003738,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将牛肉片放入碗中,加盐和胡椒粉腌制15-20分钟,4.0,腌制,碗,15-20分钟 +201003739,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中加水煮开,5.0,煮,锅,2-3分钟 +201003740,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入姜片和牛肉片,煮至牛肉变色,6.0,煮,"锅,筷子",2-3分钟 +201003741,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入番茄块,煮至番茄变软,7.0,煮,锅,2-3分钟 +201003742,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,打散鸡蛋液,缓慢地倒入锅中,用筷子搅拌形成蛋花,8.0,"倒,搅拌","碗,筷子,锅",30秒 +201003743,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入盐和胡椒粉调味,9.0,调味,"锅,勺子",10秒 +201003744,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,最后加入葱花,即可出锅,10.0,"撒,出锅","锅,勺子",10秒 +201003745,Recipe,皮蛋瘦肉粥,皮蛋瘦肉粥,,Recipe,,"汤类,早餐,主食",3.0,,约15分钟,电饭锅煮粥模式(约30-40分钟),2-3人,"可提前一夜准备主料并保温,早餐优选,简单快手",dishes\soup\皮蛋瘦肉粥.md,,,,,,,, +201003746,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,1,升,True,,,,, +201003747,Ingredient,皮蛋,皮蛋,,Ingredient,,蛋白质,,,,,,,,2,颗,True,,,,, +201003748,Ingredient,瘦肉,瘦肉,,Ingredient,,蛋白质,,,,,,,,100,克,True,,,,, +201003749,Ingredient,大米,大米,,Ingredient,,淀粉类,,,,,,,,150,毫升,True,,,,, +201003750,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,棵,False,,,,, +201003751,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,棵,False,,,,, +201003752,Ingredient,生菜,生菜,,Ingredient,,蔬菜,,,,,,,,4,叶,False,,,,, +201003753,Ingredient,生姜,生姜,,Ingredient,,蔬菜,,,,,,,,1,拇指块,False,,,,, +201003754,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201003755,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201003756,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201003757,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201003758,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201003759,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,大米洗净,放入电饭锅内胆,加入1升饮用水。,1.0,"洗,加入",电饭锅内胆,2分钟 +201003760,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,瘦肉洗净,简易晾去水分,加入10ml食用油揉搓均匀,放入电饭锅内胆。,2.0,"洗,晾,加入,揉搓",小碗,3分钟 +201003761,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,皮蛋去壳、洗净,对半切开,分离蛋白与蛋黄,蛋白切小块,蛋黄揉碎,放入电饭锅内胆。,3.0,"去壳,洗,切,揉碎,加入","刀,小碗",3分钟 +201003762,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,生姜洗净、削皮、去枯黄部分后切丝,放入电饭锅内胆。,4.0,"洗,削皮,切,加入",刀,2分钟 +201003763,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,启动电饭锅煮粥模式,将主料煮熟。,5.0,煮,电饭锅,30-40分钟 +201003764,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,小葱、香菜、生菜分别洗净、去根、去枯黄部分后切碎,放入小碗备用;生菜单独过一次热水。,6.0,"洗,切,焯水","刀,小碗,热水",5分钟 +201003765,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将酱油、蚝油、盐、胡椒粉搅拌均匀成酱料,放入小碗备用。,7.0,搅拌,"小碗,筷子",1分钟 +201003766,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,主料煮熟后开盖,加入配料(生菜、葱、香菜)和酱料,搅拌均匀即可。,8.0,"加入,搅拌",筷子,2分钟 +201003767,Recipe,米粥,米粥,,Recipe,,汤类,2.0,,冷藏时间 Tc = 生米体积 /10 ml/分钟(可选),Tr = 10 分钟/500ml * 水体积,1人,"老少皆宜,补脾和胃,清肺功效",dishes\soup\米粥.md,,,,,,,, +201003768,Ingredient,米,米,,Ingredient,,淀粉类,,,,,,,,60-110,ml,True,,,,, +201003769,Ingredient,水,水,,Ingredient,,其他,,,,,,,,540-1320,ml,True,,,,, +201003770,Ingredient,植物油,植物油,,Ingredient,,调料,,,,,,,,生米体积 / 10,ml,False,,,,, +201003771,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,(可选)将植物油与生米混合,确保每粒米都沾上少量油,1.0,混合,盆, +201003772,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,(可选)将米-油混合物冷藏保存,冷藏时间 Tc,2.0,冷藏,冰箱,Tc = 生米体积 /10 ml/分钟 +201003773,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将米和水加入锅中,3.0,加料,锅, +201003774,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,开大火加热到 T1(T1 = 1.5 分钟/500ml * 水体积),4.0,大火加热,锅,T1 +201003775,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,在 T1 之前将火关小,防止水漫出熄灭火焰,5.0,调小火,锅, +201003776,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,继续加热到 Tr(Tr = 10 分钟/500ml * 水体积),然后关火,6.0,小火炖煮,锅,Tr +201003777,Recipe,紫菜蛋花汤,紫菜蛋花汤,,Recipe,,汤类,2.0,,15分钟(紫菜泡发),约5分钟,1人份,"蛋花嫩滑技巧,可加入淀粉增稠,可选虾仁或虾皮提鲜",dishes\soup\紫菜蛋花汤.md,,,,,,,, +201003778,Ingredient,干紫菜,干紫菜,,Ingredient,,蔬菜,,,,,,,,10,克,True,,,,, +201003779,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201003780,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201003781,Ingredient,水,水,,Ingredient,,其他,,,,,,,,1.5,升,False,,,,, +201003782,Ingredient,油,油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201003783,Ingredient,葱花,葱花,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201003784,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,几滴,,False,,,,, +201003785,Ingredient,虾仁,虾仁,,Ingredient,,蛋白质,,,,,,,,可选,,False,,,,, +201003786,Ingredient,虾皮,虾皮,,Ingredient,,蛋白质,,,,,,,,可选,,False,,,,, +201003787,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,2,克,False,,,,, +201003788,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,干紫菜用清水泡15分钟,捞起沥干水分备用。,1.0,泡发,碗,15分钟 +201003789,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,热锅,倒入1.5升清水、5ml油、2g盐。待水开后放入紫菜。,2.0,煮,锅,约2分钟 +201003790,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,紫菜烧开后3分钟,将打好的蛋液徐徐倒入锅内,30秒即可起锅。,3.0,煮,锅,3分30秒 +201003791,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,撒上葱花,转小火20秒。,4.0,煮,锅,20秒 +201003792,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,关火,出锅前放入几滴香油,也可加入一点虾皮提味。,5.0,调味,锅, +201003793,Recipe,罗宋汤,罗宋汤,,Recipe,,汤类,4.0,,20分钟,1小时30分钟,1人份,"番茄罐头+番茄膏风味更佳,胡萝卜洋葱欧芹牛肉为必备,其余食材可自由搭配",dishes\soup\罗宋汤.md,,,,,,,, +201003794,Ingredient,牛肉高汤,牛肉高汤,,Ingredient,,调料,,,,,,,,500,mL,False,,,,, +201003795,Ingredient,牛肉,牛肉,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201003796,Ingredient,番茄罐头,番茄罐头,,Ingredient,,蔬菜,,,,,,,,2,罐,True,,,,, +201003797,Ingredient,番茄膏,番茄膏,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201003798,Ingredient,马铃薯,马铃薯,,Ingredient,,淀粉类,,,,,,,,400,g,True,,,,, +201003799,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201003800,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201003801,Ingredient,欧芹,欧芹,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201003802,Ingredient,包菜,包菜,,Ingredient,,蔬菜,,,,,,,,200,g,True,,,,, +201003803,Ingredient,红肠,红肠,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201003804,Ingredient,橄榄油,橄榄油,,Ingredient,,调料,,,,,,,,5,mL,False,,,,, +201003805,Ingredient,植物油,植物油,,Ingredient,,调料,,,,,,,,5,mL,False,,,,, +201003806,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,18,g,False,,,,, +201003807,Ingredient,黑胡椒,黑胡椒,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201003808,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,洋葱、胡萝卜、欧芹切1cm见方小丁,1.0,切,"刀,案板",5分钟 +201003809,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,红肠、马铃薯切2cm块,2.0,切,"刀,案板",5分钟 +201003810,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,包菜去梗后,手撕至2cm片,3.0,撕,手,3分钟 +201003811,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,牛肉撒盐3g、黑胡椒3g腌制5分钟,4.0,腌制,盆,5分钟 +201003812,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,平底锅烧热,加入植物油,煎制牛肉至表面焦黄色,取出备用,5.0,煎,平底锅,5分钟 +201003813,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,汤锅烧热,加入橄榄油、洋葱丁、胡萝卜丁、欧芹丁,炒至洋葱透明,6.0,炒,"汤锅,锅铲",5分钟 +201003814,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入番茄膏、番茄罐头,翻炒均匀,7.0,炒,"汤锅,锅铲",2分钟 +201003815,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入牛肉、马铃薯丁,翻炒均匀后加水没过食材,中火烹制1小时,8.0,"炒,炖",汤锅,1小时 +201003816,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,开锅加入包菜丁、红肠丁,搅拌均匀,中火烹制半小时,9.0,炖,汤锅,30分钟 +201003817,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,开盖加入剩余15g盐,混合均匀后盛盘,10.0,搅拌,"汤锅,锅铲",1分钟 +201003818,Recipe,腊八粥,腊八粥,,Recipe,,汤类,4.0,,浸泡一夜(8小时)+ 3小时,2.5小时(30分钟+60分钟+60分钟),1人份(三小碗),"加料时需搅拌使食材均匀分布,注意水位线,低于米线立即补水,控制火候,定时搅拌防糊底,普通锅建议水开后再下原料并改小火,有条件可使用高压锅或粥锅",dishes\soup\腊八粥.md,,,,,,,, +201003819,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,1000,毫升,True,,,,, +201003820,Ingredient,大米,大米,,Ingredient,,淀粉类,,,,,,,,50,克,True,,,,, +201003821,Ingredient,糯米,糯米,,Ingredient,,淀粉类,,,,,,,,50,克,True,,,,, +201003822,Ingredient,花生,花生,,Ingredient,,蛋白质,,,,,,,,25,克,True,,,,, +201003823,Ingredient,红豆,红豆,,Ingredient,,淀粉类,,,,,,,,25,克,True,,,,, +201003824,Ingredient,红枣,红枣,,Ingredient,,蔬菜,,,,,,,,25,克,True,,,,, +201003825,Ingredient,薏米,薏米,,Ingredient,,淀粉类,,,,,,,,50,克,True,,,,, +201003826,Ingredient,黑米,黑米,,Ingredient,,淀粉类,,,,,,,,50,克,True,,,,, +201003827,Ingredient,小米,小米,,Ingredient,,淀粉类,,,,,,,,50,克,True,,,,, +201003828,Ingredient,莲子,莲子,,Ingredient,,蔬菜,,,,,,,,25,克,True,,,,, +201003829,Ingredient,绿豆,绿豆,,Ingredient,,蔬菜,,,,,,,,25,克,True,,,,, +201003830,Ingredient,黄豆,黄豆,,Ingredient,,蛋白质,,,,,,,,25,克,True,,,,, +201003831,Ingredient,豌豆,豌豆,,Ingredient,,蔬菜,,,,,,,,25,克,True,,,,, +201003832,Ingredient,红腰豆,红腰豆,,Ingredient,,蛋白质,,,,,,,,25,克,True,,,,, +201003833,Ingredient,桂圆,桂圆,,Ingredient,,蔬菜,,,,,,,,25,克,True,,,,, +201003834,Ingredient,栗子,栗子,,Ingredient,,蔬菜,,,,,,,,25,克,True,,,,, +201003835,Ingredient,去壳核桃,去壳核桃,,Ingredient,,蛋白质,,,,,,,,25,克,True,,,,, +201003836,Ingredient,葡萄干,葡萄干,,Ingredient,,蔬菜,,,,,,,,25,克,True,,,,, +201003837,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10~25,克,False,,,,, +201003838,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,提前洗净绿豆、红豆、花生、黄豆、豌豆、红腰豆,放入玻璃碗,加饮用水至3/4碗高,浸泡一夜(或最少8小时)。,1.0,浸泡,玻璃碗,8小时 +201003839,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,提前洗净大米、糯米、薏米、黑米、小米、莲子,放入玻璃碗,加饮用水至3/4碗高,浸泡3小时。,2.0,浸泡,玻璃碗,3小时 +201003840,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将步骤1中浸泡好的豆类沥干水分,倒入粥锅,加入1升饮用水(或漫过食材1拇指高),大火煮沸后合盖,小火煮30分钟。,3.0,煮,粥锅,30分钟 +201003841,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将步骤2中浸泡好的米类及莲子沥干水分,倒入粥锅,合盖,小火继续煮60分钟。,4.0,煮,粥锅,60分钟 +201003842,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,洗净红枣、桂圆、栗子、核桃、葡萄干(红枣切片),与冰糖一起倒入锅中,合盖,小火再煮60分钟。,5.0,煮,粥锅,60分钟 +201003843,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,确认粥已粘稠后关火,盛盘即可食用。,6.0,盛盘,碗, +201003844,Recipe,西红柿鸡蛋汤,西红柿鸡蛋汤,,Recipe,"[{'term': 'tomato鸡蛋汤', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '番茄鸡蛋汤', 'language': 'zh', 'language_code': 'zh-CN'}]",汤类,2.0,,约5分钟,约5分钟,1人份,味素可加可不加,dishes\soup\西红柿鸡蛋汤.md,,,,,,,, +201003845,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,个,True,,,,, +201003846,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1-2,个,True,,,,, +201003847,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,2,滴,False,,,,, +201003848,Ingredient,味素,味素,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201003849,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201003850,Ingredient,葱,葱,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201003851,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201003852,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201003853,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201003854,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将西红柿洗净,切块。,1.0,切,"刀,案板",约1分钟 +201003855,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱姜蒜切碎。,2.0,切,"刀,案板",约1分钟 +201003856,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,鸡蛋打到碗中,用筷子(或打蛋器)搅拌均匀。,3.0,搅拌,"碗,筷子或打蛋器",约30秒 +201003857,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,并放入15毫升的油,待能从油中看到冒出一丝烟时,放入葱姜蒜翻炒30秒。,4.0,炒,"炒锅,锅铲",约30秒 +201003858,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入西红柿翻炒1分钟。,5.0,炒,"炒锅,锅铲",1分钟 +201003859,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入水,水的高度大约为锅内菜品高度的1.2倍,并放入盐。,6.0,煮,炒锅,约30秒 +201003860,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,待开锅后,将鸡蛋液放入,并用筷子将鸡蛋打散,放入味素和香油。,7.0,"煮,搅拌",筷子,约30秒 +201003861,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,等待30秒,关火出锅。,8.0,煮,炒锅,30秒 +201003862,Recipe,金针菇汤,金针菇汤,,Recipe,,汤类,2.0,,约5分钟,约4分钟,1人份,"可加入鸡蛋增香,出锅后滴香油或麻油提味",dishes\soup\金针菇汤.md,,,,,,,, +201003863,Ingredient,金针菇,金针菇,,Ingredient,,蔬菜,,,,,,,,400-500,克,True,,,,, +201003864,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201003865,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201003866,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201003867,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,3-4,滴,False,,,,, +201003868,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,金针菇徒手掰散,越散越好,洗净备用,1.0,切,手,约2分钟 +201003869,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用菜刀或者水果刀将上述金针菇切段,长度不宜超过5 cm,2.0,切,"菜刀,水果刀",约1分钟 +201003870,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将金针菇放入锅中,加水没过约食材总高度1.1倍,沸腾后等待3分钟,3.0,煮,锅,约3分钟 +201003871,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入味精和食盐并搅拌,4.0,搅拌,锅铲,约10秒 +201003872,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,继续加热约30秒,关火装盘,5.0,煮,锅,30秒 +201003873,Recipe,陈皮排骨汤,陈皮排骨汤,,Recipe,,汤类,4.0,粤菜,5分钟,1.5小时,1人份,"广东老火靓汤,熬夜党必备,注意防烫",dishes\soup\陈皮排骨汤.md,,,,,,,, +201003874,Ingredient,排骨,排骨,,Ingredient,,蛋白质,,,,,,,,4-5,块,True,,,,, +201003875,Ingredient,陈皮,陈皮,,Ingredient,,调料,,,,,,,,1,瓣,False,,,,, +201003876,Ingredient,西洋参,西洋参,,Ingredient,,其他,,,,,,,,9,片,False,,,,, +201003877,Ingredient,石斛,石斛,,Ingredient,,其他,,,,,,,,6,颗,False,,,,, +201003878,Ingredient,玉竹,玉竹,,Ingredient,,其他,,,,,,,,5,片,False,,,,, +201003879,Ingredient,麦冬,麦冬,,Ingredient,,其他,,,,,,,,7,个,False,,,,, +201003880,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201003881,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,排骨用热水过一遍,去血水,1.0,焯水,锅, +201003882,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,陈皮、麦冬、玉竹、石斛和西洋参冲洗干净,2.0,冲洗,盆, +201003883,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,煲汤盅洗干净,3.0,清洗,煲汤盅, +201003884,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,打开煲汤盅,先放入排骨在底部,然后依次放入陈皮、麦冬、玉竹、石斛和西洋参,4.0,摆放,煲汤盅, +201003885,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入热水进煲汤盅,水不宜太满,5.0,加水,煲汤盅, +201003886,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,煲汤容器加入水,炖煮1.5小时,6.0,炖,煲汤容器,1.5小时 +201003887,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入食盐,趁热饮用,7.0,调味,汤勺, +201003888,Recipe,勾芡香菇汤,勾芡香菇汤,,Recipe,,汤类,3.0,,15分钟(香菇腌制),约8分钟(煎香菇+煮制+勾芡),1人份,,dishes\soup\勾芡香菇汤\勾芡香菇汤.md,,,,,,,, +201003889,Ingredient,鲜香菇,鲜香菇,,Ingredient,,蔬菜,,,,,,,,2,朵,True,,,,, +201003890,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201003891,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201003892,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201003893,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201003894,Ingredient,生粉,生粉,,Ingredient,,淀粉类,,,,,,,,10,克,False,,,,, +201003895,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,350,毫升,False,,,,, +201003896,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,香菇切片(每片厚度0.5-1 cm),放入大碗中,倒入2 g食用盐浸泡15分钟,1.0,"切,腌制","刀,案板,大碗",15分钟 +201003897,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,生粉倒入小碗中,加入50 ml水,搅拌至无颗粒(即水淀粉),2.0,搅拌,"小碗,筷子",约1分钟 +201003898,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,倒掉碗中的盐水,适当去掉香菇本身的水分(方便下一步煎炸)【可选】,3.0,沥水,筛网或手,约30秒 +201003899,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,小火热锅,倒入油,待油开始冒小泡(小火30 s),倒入香菇,每面煎10 s【可选】,4.0,煎,"炒锅,锅铲",约50秒 +201003900,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,倒入开水300 ml,调中火再煮3-5分钟,5.0,煮,炒锅,3-5分钟 +201003901,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入水淀粉,适当搅拌锅中汤汁后,加入3 g盐、3 g鸡精,最后撒上葱花出锅,6.0,"勾芡,搅拌,撒",锅铲,约30秒 +201003902,Recipe,排骨苦瓜汤,排骨苦瓜汤,,Recipe,,汤类,4.0,,约30分钟(切排骨、处理苦瓜、焯水等),汤锅120-240分钟;电压力锅45分钟,4人,可用瑶柱代替虾皮增鲜,dishes\soup\排骨苦瓜汤\排骨苦瓜汤.md,,,,,,,, +201003903,Ingredient,排骨,排骨,,Ingredient,,蛋白质,,,,,,,,375,克,True,,,,, +201003904,Ingredient,苦瓜,苦瓜,,Ingredient,,蔬菜,,,,,,,,150,克,True,,,,, +201003905,Ingredient,虾皮,虾皮,,Ingredient,,蛋白质,,,,,,,,10,克,False,,,,, +201003906,Ingredient,生姜,生姜,,Ingredient,,调料,,,,,,,,7.5,克,False,,,,, +201003907,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,0.45,克,False,,,,, +201003908,Ingredient,白胡椒,白胡椒,,Ingredient,,调料,,,,,,,,0.3,克,False,,,,, +201003909,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,排骨洗净,切成约4cm×3cm的小块(如无剁骨工具可请摊主代劳),1.0,切,刀,约10分钟 +201003910,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,炒锅中倒入700ml冷水与排骨一起加热至沸腾,关火后捞出排骨,2.0,焯水,炒锅,约10分钟 +201003911,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,苦瓜对半切开,去籽去瓤后切成0.5cm厚的苦瓜条,洗净备用,3.0,"切,清洗","刀,盆",约5分钟 +201003912,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,汤锅倒入1100ml水与焯好的排骨,大火煮沸,4.0,煮,汤锅,约5分钟 +201003913,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,水沸后加入苦瓜条和虾皮,转小火炖煮120-240分钟;120分钟后可试尝,排骨能轻松脱骨即可关火,5.0,炖,汤锅,120-240分钟 +201003914,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,出锅前按每250ml汤加入0.3-0.6g盐、0.1-0.5g白胡椒调味,6.0,调味,汤勺,约1分钟 +201003915,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,(电压力锅法)将1000ml水、排骨、虾皮、苦瓜一起放入电压力锅,选择炖汤功能加压烹饪45分钟,出锅后按步骤6调味,7.0,炖,电压力锅,45分钟 +201003916,Recipe,昂刺鱼豆腐汤,昂刺鱼豆腐汤,,Recipe,"[{'term': '昂刺鱼tofu汤', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '昂刺鱼老豆腐汤', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '昂刺鱼嫩豆腐汤', 'language': 'zh', 'language_code': 'zh-CN'}]",汤类,3.0,,20分钟(腌制15分钟+豆腐浸泡5分钟),17分钟(煎鱼2-3分钟+大火煮10分钟+中火煮5分钟),1人份,"刺少,肉嫩,营养丰盛,适合任何年龄",dishes\soup\昂刺鱼豆腐汤\昂刺鱼豆腐汤.md,,,,,,,, +201003917,Ingredient,昂刺鱼或沙光鱼,昂刺鱼或沙光鱼,,Ingredient,,蛋白质,,,,,,,,1,条,True,,,,, +201003918,Ingredient,豆腐,豆腐,,Ingredient,"[{'term': '水豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '嫩豆腐', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,100,g,True,,,,, +201003919,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201003920,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,1,块,False,,,,, +201003921,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201003922,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201003923,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201003924,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201003925,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,1000,ml,False,,,,, +201003926,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鱼处理好后洗净,特别注意肚内的血丝,不洗干净会有腥味。放入大碗中,倒入料酒、10g姜片、5g盐,腌制15分钟。,1.0,腌制,碗,15分钟 +201003927,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,豆腐切块,放入凉水浸泡5分钟,捞出备用。,2.0,"切,浸泡","刀,案板,盆",5分钟 +201003928,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,煎鱼前,先用生姜片擦一下锅防止粘锅,倒入油(油量为15ml×鱼的条数),烧热后放入鱼煎2-3分钟,期间需要晃动一下鱼防止粘底,且需要翻一次身。,3.0,煎,"炒锅,锅铲",2-3分钟 +201003929,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,待鱼全部煎好后,倒入开水、5ml料酒、姜片,小火转至大火,盖上锅盖大火煮10分钟(水要稍微多一些,后面会蒸发掉一些)。,4.0,煮,"炒锅,锅盖",10分钟 +201003930,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,见汤变白后倒入准备好的豆腐,调中火再煮5分钟,加入10g盐、3g胡椒粉调味,最后撒上葱花出锅。,5.0,"煮,调味",锅铲,5分钟 +201003931,Recipe,朱雀汤,朱雀汤,,Recipe,,汤类,1.0,豫东菜,2分钟,2分钟,1人份,"去火,豫东特色,快速汤,鸡蛋汤,可盐可甜",dishes\soup\朱雀汤\朱雀汤.md,,,,,,,, +201003932,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201003933,Ingredient,水,水,,Ingredient,,其他,,,,,,,,500,毫升,True,,,,, +201003934,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,克,False,,,,, +201003935,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,2,毫升,False,,,,, +201003936,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡蛋在碗中打散,再倒入香油。,1.0,"打散,倒","碗,筷子",30秒 +201003937,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,水烧开后,在沸腾状态下快速倒入盛有鸡蛋的碗中。,2.0,"煮,倒","锅,碗",30秒 +201003938,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放入白糖。,3.0,放,碗,5秒 +201003939,Recipe,玉米排骨汤,玉米排骨汤,,Recipe,,汤类,3.0,,约15分钟,约70分钟,1份,"食材简单,新手友好,适合降温时食用",dishes\soup\玉米排骨汤\玉米排骨汤.md,,,,,,,, +201003940,Ingredient,排骨,排骨,,Ingredient,,蛋白质,,,,,,,,500-800,g,True,,,,, +201003941,Ingredient,玉米,玉米,,Ingredient,"[{'term': '苞米', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '玉蜀黍', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,根,True,,,,, +201003942,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,1,根,True,,,,, +201003943,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,小半根,根,False,,,,, +201003944,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201003945,Ingredient,生姜,生姜,,Ingredient,,蔬菜,,,,,,,,若干,片,False,,,,, +201003946,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201003947,Ingredient,黑胡椒粉,黑胡椒粉,,Ingredient,,调料,,,,,,,,4,g,False,,,,, +201003948,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201003949,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201003950,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,10-15,g,False,,,,, +201003951,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,1000,ml,False,,,,, +201003952,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,大葱切成3-4cm的大段,用刀背拍一下;玉米剁成小块;胡萝卜切成滚刀块;生姜去皮切大片;排骨砍成小块。,1.0,"切,剁","刀,案板",约10分钟 +201003953,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,排骨凉水下锅,加入大葱、生姜、料酒焯水,大火烧开,撇去浮沫,捞出排骨并沥干水分。,2.0,"焯水,煮","锅,漏勺",约5分钟 +201003954,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅凉油,放入生姜片和排骨煸炒,至排骨表面微微焦黄,加入醋继续煸炒1分钟。,3.0,"炒,煸炒","炒锅,锅铲",约3分钟 +201003955,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,冲入1000ml开水,大火烧开。,4.0,煮,锅,约1分钟 +201003956,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,先下入玉米,加入黑胡椒粉,盖盖小火炖20分钟。,5.0,炖,"锅,锅盖",20分钟 +201003957,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入胡萝卜,盖盖继续小火炖40分钟。,6.0,炖,"锅,锅盖",40分钟 +201003958,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,出锅前3分钟加盐调味,最后撒入香葱末即可。,7.0,调味,"锅,勺子",3分钟 +201003959,Recipe,羊肉汤,羊肉汤,,Recipe,,汤类,3.0,西北菜,10分钟,15分钟,1人份,开大火使油脂与汤汁更好融合,dishes\soup\羊肉汤\羊肉汤.md,,,,,,,, +201003960,Ingredient,羊肉,羊肉,,Ingredient,,蛋白质,,,,,,,,300,克,True,,,,, +201003961,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201003962,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201003963,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,50,克,False,,,,, +201003964,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,1000,毫升,False,,,,, +201003965,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201003966,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201003967,Ingredient,孜然粉,孜然粉,,Ingredient,,调料,,,,,,,,1,克,False,,,,, +201003968,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,20,克,False,,,,, +201003969,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,羊肉切成长5cm宽0.5cm的块,1.0,切,"刀,案板",2-3分钟 +201003970,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,大葱切成小段,2.0,切,"刀,案板",30秒 +201003971,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,羊肉放入锅中,加入1000ml常温水,加入料酒、大葱,3.0,煮,锅,1分钟 +201003972,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,煮沸2分钟后,捞出羊肉,使用常温水洗净,沥干水分,4.0,"煮,焯水,冲洗","锅,漏勺,盆",2分钟 +201003973,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅加入食用油,加入羊肉,翻炒2分钟至羊肉表面微黄,5.0,炒,"炒锅,锅铲",2分钟 +201003974,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入开水,开到大火档位,6.0,煮,炒锅,30秒 +201003975,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,5分钟后,加入白胡椒粉、盐,继续煮沸5分钟,7.0,煮,炒锅,10分钟 +201003976,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,出锅之后,加入香菜、孜然粉,搅拌均匀,8.0,搅拌,锅铲,30秒 +201003977,Recipe,菌菇炖乳鸽,菌菇炖乳鸽,,Recipe,"[{'term': '菌菇煲乳鸽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '菌菇stewed乳鸽', 'language': 'zh', 'language_code': 'zh-CN'}]",汤类,4.0,,5分钟,高压锅30分钟 / 瓦罐40-60分钟,2人份,,dishes\soup\菌菇炖乳鸽\菌菇炖乳鸽.md,,,,,,,, +201003978,Ingredient,乳鸽,乳鸽,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201003979,Ingredient,菌菇,菌菇,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201003980,Ingredient,玉米,玉米,,Ingredient,"[{'term': '苞米', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '玉蜀黍', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,200,g,False,,,,, +201003981,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201003982,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201003983,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201003984,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,冷水洗干净热心摊主处理好的乳鸽,1.0,清洗,盆, +201003985,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,冷水锅中放入洗干净的乳鸽,加入15ml料酒与姜,水煮开即可捞出乳鸽,要不然会丢失营养,2.0,焯水,锅,水开后立即捞出 +201003986,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,把乳鸽放到高压锅或者瓦罐中,倒入的水要没过乳鸽,放入生姜20g、玉米200g、菌菇100g,3.0,炖,"高压锅,瓦罐", +201003987,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,高压锅30分钟;瓦罐需在水烧开后转小火慢炖40-60分钟,4.0,炖,"高压锅,瓦罐",高压锅30分钟 / 瓦罐40-60分钟 +201003988,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,时间到了,盛到碗中,加入3~5g盐即可,5.0,调味,碗, +201003989,Recipe,银耳莲子粥,银耳莲子粥,,Recipe,,汤类,4.0,,2小时10分钟,1小时30分钟,1人,当银耳呈现粘稠状态时,需要用勺子及时搅拌,防止银耳糊在锅底,dishes\soup\银耳莲子粥\银耳莲子粥.md,,,,,,,, +201003990,Ingredient,银耳,银耳,,Ingredient,,蔬菜,,,,,,,,60,g,True,,,,, +201003991,Ingredient,去心莲子,去心莲子,,Ingredient,,蔬菜,,,,,,,,20,g,True,,,,, +201003992,Ingredient,红枣,红枣,,Ingredient,,蔬菜,,,,,,,,6,g,True,,,,, +201003993,Ingredient,枸杞,枸杞,,Ingredient,,蔬菜,,,,,,,,5-6,g,False,,,,, +201003994,Ingredient,冰糖,冰糖,,Ingredient,"[{'term': '冰片糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '块糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10-20,g,False,,,,, +201003995,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,把银耳、莲子用清水浸泡2个小时,红枣浸泡10-20分钟,枸杞洗净,备用,1.0,浸泡,盆,2小时 +201003996,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,在锅中倒入600ml水,烧开后依次放入银耳、莲子、红枣,2.0,煮,锅, +201003997,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,等待水再次烧开后,盖上锅盖,转至中火继续熬,3.0,煮,锅, +201003998,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,熬到大约1小时后,放入5g-10g冰糖和5g-6g枸杞,转至小火熬,4.0,煮,锅,1小时 +201003999,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,小火继续熬30分钟,此时银耳开始呈现粘稠状态,5.0,煮,锅,30分钟 +201004000,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,再次放入5g-10g冰糖,用勺子搅拌5-10分钟,6.0,搅拌,"锅,勺子",5-10分钟 +201004001,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,关火,用勺子盛出,7.0,盛出,勺子, +201004002,Recipe,陈皮排骨汤,陈皮排骨汤,,Recipe,,汤类,3.0,粤菜,10分钟,1.5小时,1人份,"广东老火靓汤,熬夜党必备,养生,注意防烫",dishes\soup\陈皮排骨汤\陈皮排骨汤.md,,,,,,,, +201004003,Ingredient,排骨,排骨,,Ingredient,,蛋白质,,,,,,,,4,块,True,,,,, +201004004,Ingredient,陈皮,陈皮,,Ingredient,,调料,,,,,,,,1,瓣,False,,,,, +201004005,Ingredient,西洋参,西洋参,,Ingredient,,其他,,,,,,,,9,片,False,,,,, +201004006,Ingredient,石斛,石斛,,Ingredient,,其他,,,,,,,,6,颗,False,,,,, +201004007,Ingredient,玉竹,玉竹,,Ingredient,,其他,,,,,,,,5,片,False,,,,, +201004008,Ingredient,麦冬,麦冬,,Ingredient,,其他,,,,,,,,7,个,False,,,,, +201004009,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201004010,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,排骨用热水过一遍,去血水,1.0,焯水,锅,约2分钟 +201004011,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,陈皮、麦冬、玉竹、石斛和西洋参冲洗干净,2.0,冲洗,盆,约3分钟 +201004012,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,煲汤盅洗干净,3.0,清洗,煲汤盅,约1分钟 +201004013,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,打开煲汤盅,先放入排骨在底部,然后依次放入陈皮、麦冬、玉竹、石斛和西洋参,4.0,摆放,煲汤盅,约2分钟 +201004014,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入热水进煲汤盅,水不宜太满,5.0,加水,煲汤盅,约1分钟 +201004015,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,煲汤容器加入水,炖煮1.5小时,6.0,炖,煲汤盅,1.5小时 +201004016,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入食盐,趁热饮用,7.0,调味,汤匙,约1分钟 +201004017,Recipe,手工水饺,手工水饺,,Recipe,,主食,5.0,,2小时30分钟,30分钟,1人,"煮饺子不盖锅盖,加三次冷水防破皮,可配黑醋姜丝蘸料,可配蒜泥香油蘸料",dishes\staple\手工水饺.md,,,,,,,, +201004018,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,200,g,True,,,,, +201004019,Ingredient,冷水,冷水,,Ingredient,,其他,,,,,,,,150,ml,True,,,,, +201004020,Ingredient,芝麻香油,芝麻香油,,Ingredient,,调料,,,,,,,,2-3,ml,False,,,,, +201004021,Ingredient,瘦肉末,瘦肉末,,Ingredient,,蛋白质,,,,,,,,250,g,True,,,,, +201004022,Ingredient,肥肉末,肥肉末,,Ingredient,,蛋白质,,,,,,,,20,g,False,,,,, +201004023,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004024,Ingredient,葱,葱,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201004025,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004026,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,2,ml,False,,,,, +201004027,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,2,ml,False,,,,, +201004028,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,ml,False,,,,, +201004029,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201004030,Ingredient,韭菜,韭菜,,Ingredient,,蔬菜,,,,,,,,适量,,True,,,,, +201004031,Ingredient,黑醋,黑醋,,Ingredient,,调料,,,,,,,,10-20,ml,False,,,,, +201004032,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,3,瓣,False,,,,, +201004033,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,盆中加入所有面粉,加入芝麻香油,面粉中央挖小洞,分4-5次加入水并搅和,出现碎末状稍干面团后停止加水,用手压实面团至面光盆光。,1.0,"搅拌,压实",盆, +201004034,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将面团置于桌上,盆倒扣,环境温度25度醒发45分钟。,2.0,醒发,盆,45分钟 +201004035,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,醒发完成后,将面团搓条、合团、再搓条,重复3次后擀条,切成20份均匀面团并搓成直径3-3.5cm球状。,3.0,"搓,擀,切","擀面杖,刀", +201004036,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,压扁面团,撒面粉防粘,用擀面杖擀成直径约8cm、厚约2mm、中间略厚1mm的饺子皮。,4.0,擀,擀面杖, +201004037,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,猪肉去皮切块,用两把菜刀剁成肉末放入碗中;葱姜切末加入肉末搅拌均匀;韭菜洗净切3mm以下长度;韭菜与肉末混合,加入蚝油、生抽、香油各2ml及蛋清,用手搅拌均匀,静置30分钟。,5.0,"剁,切,搅拌,腌制","刀,碗",30分钟 +201004038,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,左手托皮,右手夹馅,沿饺子皮圆周合拢捏实,无需捏花,确保不漏即可。,6.0,包,筷子, +201004039,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,锅中加水至3/4高度,大火烧开,放入饺子后转中火,水冒泡后加50ml冷水,重复两次;第三次水开后加50ml冷水,再开后小火60秒即可出锅。,7.0,煮,锅,约15分钟 +201004040,Recipe,汤面,汤面,,Recipe,,主食,2.0,,5-10分钟(切菜、处理肉类),15-20分钟,1人,"少量多次加盐,灵活调整食材,固液兼具,做法简单",dishes\staple\汤面.md,,,,,,,, +201004041,Ingredient,面食,面食,,Ingredient,,淀粉类,,,,,,,,70-230,g,True,,,,, +201004042,Ingredient,冷水,冷水,,Ingredient,,其他,,,,,,,,200-400,ml,False,,,,, +201004043,Ingredient,肉类(牛羊鱼虾等),肉类(牛羊鱼虾等),,Ingredient,,蛋白质,,,,,,,,适量,g,True,,,,, +201004044,Ingredient,蛋类(鸡蛋鸭蛋等),蛋类(鸡蛋鸭蛋等),,Ingredient,,蛋白质,,,,,,,,适量,个,True,,,,, +201004045,Ingredient,豆制品(豆腐皮等),豆制品(豆腐皮等),,Ingredient,,蛋白质,,,,,,,,适量,g,True,,,,, +201004046,Ingredient,青菜(生菜菠菜等),青菜(生菜菠菜等),,Ingredient,,蔬菜,,,,,,,,适量,g,True,,,,, +201004047,Ingredient,其他蔬菜(青椒番茄胡萝卜等),其他蔬菜(青椒番茄胡萝卜等),,Ingredient,,蔬菜,,,,,,,,适量,g,True,,,,, +201004048,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,g,False,,,,, +201004049,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,适量,g,False,,,,, +201004050,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,适量,ml,False,,,,, +201004051,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将菜类材料切成边长不超过4cm的块状,便于煮熟,1.0,切,"刀,案板",3-5分钟 +201004052,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,如有生肉,则先放入冷水中,盖上锅盖,煮沸腾,先捞出上层血沫,再关火,捞出半熟的肉备用,2.0,煮,"锅,锅盖,漏勺",5-7分钟 +201004053,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,先大火将水加热至沸腾,后调至中火,3.0,煮,锅,2-3分钟 +201004054,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将较难煮熟的食材放入锅中(比如半熟肉类、香菇类、等最先放入锅中)。为保证煮熟,可在沸腾后计时10分钟,特别难熟的大块食材可追加5分钟,4.0,煮,"锅,计时器",10-15分钟 +201004055,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将面食放入锅中,适当搅拌确保面和汤充分接触,使液面保持轻微沸腾,煮5分钟。加入面后液面易产生白色泡沫,可适当抬起锅盖通气或者撤下锅盖,5.0,"煮,搅拌","锅,筷子或锅铲",5分钟 +201004056,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将易于煮熟的食材如青菜类放入锅中,适当搅拌以充分浸没,煮2-5分钟,6.0,"煮,搅拌","锅,筷子或锅铲",2-5分钟 +201004057,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,关火,随后加入盐、胡椒粉、香油等自己喜欢的调味料,适当搅拌即可出锅食用,7.0,搅拌,"锅,筷子或锅铲",1分钟 +201004058,Recipe,炒年糕,炒年糕,,Recipe,,主食,3.0,闽菜,10分钟,20分钟,1人/份,"辅料可酌情添加,煮年糕需搅拌防粘锅",dishes\staple\炒年糕.md,,,,,,,, +201004059,Ingredient,年糕,年糕,,Ingredient,,淀粉类,,,,,,,,250,g,True,,,,, +201004060,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,根,False,,,,, +201004061,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,50,ml,False,,,,, +201004062,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201004063,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1-2,g,False,,,,, +201004064,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201004065,Ingredient,青菜,青菜,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201004066,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅中加水烧开,煮熟年糕,碗中加水确保年糕不会粘连,捞起年糕备用。,1.0,煮,"锅,碗",5-7分钟 +201004067,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,小葱切葱花(将葱白和葱叶分开),青菜切小段备用。,2.0,切,"刀,案板",3分钟 +201004068,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,(可选)制作炒蛋,见西红柿炒蛋菜谱。,3.0,炒,炒锅,3分钟 +201004069,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,加入30ml食用油。,4.0,加热,炒锅,30秒 +201004070,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将葱白倒入锅中,直至大部分葱白变成焦黄色且发出香味,倒出葱油备用。,5.0,炒,炒锅,1-2分钟 +201004071,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,重新热锅,加入20ml食用油。,6.0,加热,炒锅,30秒 +201004072,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入所有辅料(鸡蛋,青菜等),翻炒均匀。,7.0,炒,"炒锅,锅铲",1-2分钟 +201004073,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将年糕的水倒掉,向锅中加入年糕。,8.0,倒,"碗,锅铲",30秒 +201004074,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入酱油和盐,翻炒均匀。,9.0,炒,锅铲,1-2分钟 +201004075,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,关火,加入葱油,翻炒均匀,乘盘。,10.0,炒,锅铲,30秒 +201004076,Recipe,炒方便面,炒方便面,,Recipe,,主食,2.0,,约5分钟,约5分钟,1人/份,"可加入芝麻酱,芝麻酱1:1兑水稀释",dishes\staple\炒方便面.md,,,,,,,, +201004077,Ingredient,方便面,方便面,,Ingredient,,淀粉类,,,,,,,,1.2,包,True,,,,, +201004078,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1.4,个,True,,,,, +201004079,Ingredient,火腿肠,火腿肠,,Ingredient,,蛋白质,,,,,,,,0.7,个,False,,,,, +201004080,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2.8,克,False,,,,, +201004081,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201004082,Ingredient,方便面调料包,方便面调料包,,Ingredient,,调料,,,,,,,,1,套,False,,,,, +201004083,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将火腿肠撕开包装,切成宽度1cm的小块。,1.0,切,"刀,案板",约30秒 +201004084,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,向煮锅中加入300ml水,煮沸后加入方便面面饼,煮45秒并挑散面条,关火后立即将面汤与面分离,并用凉水冲一下面条。,2.0,"煮,挑散,冲洗","煮锅,筷子",约1分钟 +201004085,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将方便面调料包(菜包、酱包全部,粉包50%-80%)挤入小碗中,加入80ml面汤搅匀,制成调料碗。,3.0,搅拌,"小碗,筷子",约30秒 +201004086,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将鸡蛋打入小碗,每蛋加2g盐搅匀;热锅20秒后倒入8ml油,倒入蛋液炒20秒至固态,盛出备用。,4.0,"打蛋,炒","小碗,炒锅,锅铲",约1分钟 +201004087,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅20秒后加油至10ml,倒入火腿肠翻炒10秒,加入面条翻炒30秒,倒入调料碗再炒30秒,最后加入煎好的鸡蛋翻炒30秒,关火盛盘。,5.0,炒,"炒锅,锅铲",约2分钟 +201004088,Recipe,炒河粉,炒河粉,,Recipe,,主食,4.0,,15分钟,10分钟,1人,"可网购袋装鲜河粉,冷藏保质期两周,调料用量可按个人口味调整,喜欢辣可自加辣椒",dishes\staple\炒河粉.md,,,,,,,, +201004089,Ingredient,河粉,河粉,,Ingredient,,淀粉类,,,,,,,,250,g,True,,,,, +201004090,Ingredient,猪肉/牛肉,猪肉/牛肉,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201004091,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201004092,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201004093,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201004094,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201004095,Ingredient,孜然粉,孜然粉,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004096,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201004097,Ingredient,黄瓜,黄瓜,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201004098,Ingredient,面筋块,面筋块,,Ingredient,,蛋白质,,,,,,,,30,g,False,,,,, +201004099,Ingredient,绿豆芽,绿豆芽,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201004100,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201004101,Ingredient,蒜瓣,蒜瓣,,Ingredient,,调料,,,,,,,,2,个,False,,,,, +201004102,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,根,False,,,,, +201004103,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,5,g,False,,,,, +201004104,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201004105,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,小葱切碎(葱白和葱叶分开)、蒜瓣拍碎,丢案板上备用。,1.0,"切,拍","刀,案板",2分钟 +201004106,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,打碎鸡蛋,捞一点蛋清到一只碗中,剩下的丢入另一只碗中备用。,2.0,打,碗,1分钟 +201004107,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将绿豆芽放入锅中,大火煮60秒。豆芽捞出,过凉水,放入盘中备用。,3.0,"煮,过水","锅,漏勺,盘",2分钟 +201004108,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,黄瓜切丝放入盘中备用,可和豆芽丢一起。,4.0,切,"刀,盘",2分钟 +201004109,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,处理面筋,单独丢一个盘中。,5.0,"清洗,挤水",盘,2分钟 +201004110,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,肉切细条状,加入淀粉与刚刚碗中的鸡蛋清、胡椒粉,顺时针拌匀。,6.0,"切,拌,腌制","刀,碗,筷子",3分钟 +201004111,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入食用油,锅热倒出。倒入处理好的肉,翻炒均匀至变色,倒入碗中备用。,7.0,炒,"炒锅,锅铲,碗",2分钟 +201004112,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,趁锅热,加入20g食用油,倒入葱白、蒜爆炒出香。,8.0,炒,"炒锅,锅铲",30秒 +201004113,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入河粉,淋入老抽提色,翻炒均匀后再加入河粉炒料,继续翻炒。,9.0,炒,"炒锅,锅铲",2分钟 +201004114,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,河粉即将透明时,放入炒制好的肉丝与面筋,并加入生抽提鲜,简单翻炒两次。,10.0,炒,"炒锅,锅铲",1分钟 +201004115,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,加入豆芽与黄瓜丝,翻炒至河粉完全透明。关火!,11.0,炒,"炒锅,锅铲",1分钟 +201004116,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,撒入葱叶点缀,把锅端起。倒入盘中,开始干饭。,12.0,装盘,盘,30秒 +201004117,Recipe,炒馍,炒馍,,Recipe,,主食,3.0,西北菜,5分钟,8-10分钟,2人份,"控制火候防糊,火大补救:调小火、沿锅边加油或洒水,可增香:南德调味料,更脆技巧:小火多炒、关火后余热焖,可加蒜末蒜苗爆香",dishes\staple\炒馍.md,,,,,,,, +201004118,Ingredient,馒头,馒头,,Ingredient,,淀粉类,,,,,,,,2,个,True,,,,, +201004119,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004120,Ingredient,油,油,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201004121,Ingredient,孜然粉,孜然粉,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004122,Ingredient,辣椒粉,辣椒粉,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004123,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004124,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,棵,False,,,,, +201004125,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,False,,,,, +201004126,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将馒头切成小块或小片。,1.0,切,"刀,案板",2分钟 +201004127,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,如果使用鸡蛋,将鸡蛋打进碗里,打散(可加盐和五香粉各1g或不加)。,2.0,打散,"碗,筷子",30秒 +201004128,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将鸡蛋液浇在馒头上,拌匀,鸡蛋不宜过多。,3.0,拌,"盆,筷子",30秒 +201004129,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,大火热锅,倒入食用油。,4.0,"热锅,倒油",炒锅,30秒 +201004130,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将馍丁放入锅中翻炒,翻炒均匀。,5.0,炒,锅铲,2分钟 +201004131,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将火调小,炒至馍丁呈金黄色。,6.0,炒,锅铲,3-4分钟 +201004132,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入盐、辣椒粉、五香粉,翻炒均匀。,7.0,炒,锅铲,30秒 +201004133,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,最后将葱花放入一起翻炒几下。,8.0,炒,锅铲,15秒 +201004134,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,关火出锅。,9.0,关火,,5秒 +201004135,Recipe,炸酱面,炸酱面,,Recipe,"[{'term': '油炸酱面', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'deep-fried酱面', 'language': 'en', 'language_code': 'en-US'}]",主食,3.0,鲁菜,10分钟,15分钟,1人,"肉推荐瘦肉丁现买现用,面条推荐普通面条,面条口感关键在于劲道,勿选龙须等细面,甜咸口可自行调整酱配比",dishes\staple\炸酱面.md,,,,,,,, +201004136,Ingredient,肉丁/肉末,肉丁/肉末,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201004137,Ingredient,挂面,挂面,,Ingredient,,淀粉类,,,,,,,,150,g,True,,,,, +201004138,Ingredient,普通面条,普通面条,,Ingredient,,淀粉类,,,,,,,,250,g,True,,,,, +201004139,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,15,g,False,,,,, +201004140,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,适量,g,False,,,,, +201004141,Ingredient,菜码(黄瓜、白菜、萝卜等),菜码(黄瓜、白菜、萝卜等),,Ingredient,,蔬菜,,,,,,,,35,g,False,,,,, +201004142,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201004143,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201004144,Ingredient,甜面酱,甜面酱,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201004145,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,菜码切丝备用。,1.0,切,"刀,案板",3分钟 +201004146,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱切碎。油锅烧热,下葱和肉,炒至肉完全熟透(无红色)。,2.0,"切,炒","刀,案板,炒锅,锅铲",5分钟 +201004147,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,下豆瓣酱和甜面酱,继续炒至微微粘稠。盛出,得到炸酱。,3.0,炒,锅铲,2分钟 +201004148,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,取大碗,加凉水备用。,4.0,,大碗,30秒 +201004149,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,煮面条至断生(无白芯),盛入第4步装有凉水的碗中。,5.0,煮,"锅,筷子",3-4分钟 +201004150,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,立即控水捞出,盛入干净的碗中。,6.0,捞,"筷子,漏勺",30秒 +201004151,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,取第3步炸酱,倒入碗中,拌匀。然后取第1步菜码,倒入碗中,拌匀。,7.0,拌,筷子,1分钟 +201004152,Recipe,热干面,热干面,,Recipe,,主食,3.0,湖北菜,约5分钟,约1分钟,1人份,辣椒油看个人口味添加,dishes\staple\热干面.md,,,,,,,, +201004153,Ingredient,碱水面,碱水面,,Ingredient,,淀粉类,,,,,,,,250,g,True,,,,, +201004154,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,10,g,False,,,,, +201004155,Ingredient,酸豆角,酸豆角,,Ingredient,,蔬菜,,,,,,,,20,g,False,,,,, +201004156,Ingredient,肉末,肉末,,Ingredient,,蛋白质,,,,,,,,30,g,False,,,,, +201004157,Ingredient,蒜水,蒜水,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201004158,Ingredient,肉汤汁,肉汤汁,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201004159,Ingredient,萝卜干,萝卜干,,Ingredient,,蔬菜,,,,,,,,50,g,False,,,,, +201004160,Ingredient,芝麻酱,芝麻酱,,Ingredient,,调料,,,,,,,,40,ml,False,,,,, +201004161,Ingredient,辣椒油,辣椒油,,Ingredient,,调料,,,,,,,,0-10,ml,False,,,,, +201004162,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,0-10,g,False,,,,, +201004163,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004164,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004165,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,0-3,g,False,,,,, +201004166,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,水煮沸,并加入碱水面,焯烫25秒钟捞起,1.0,煮,锅,25秒 +201004167,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,撒上食盐、鸡精和胡椒粉,2.0,调味,,约5秒 +201004168,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,芝麻酱用90ml水稀释,搅匀,然后加入,3.0,调汁,"碗,筷子",约15秒 +201004169,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入5ml酱油,加入30ml肉汤汁和蒜水,4.0,调味,,约5秒 +201004170,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入萝卜干、肉末、酸豆角、葱花,5.0,拌,筷子,约5秒 +201004171,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,拌均匀后开吃,6.0,拌,筷子,约10秒 +201004172,Recipe,煮泡面加蛋,煮泡面加蛋,,Recipe,,主食,1.0,,0分钟,4-5分钟,1人,"可加入火腿肠、生菜、小肉丝、辣条、鱼干、虾仁、鸡腿等配料,鸡蛋可用生鸡蛋、熟鸡蛋、卤蛋等",dishes\staple\煮泡面加蛋.md,,,,,,,, +201004173,Ingredient,泡面,泡面,,Ingredient,,淀粉类,,,,,,,,1,包,True,,,,, +201004174,Ingredient,水,水,,Ingredient,,其他,,,,,,,,550-1000,毫升,False,,,,, +201004175,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201004176,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,先将水加热至沸腾(火候不做严格要求,使用热水会更快),1.0,煮,锅,视初始水温而定 +201004177,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将取出的面饼放入锅中,2.0,放,锅, +201004178,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将泡面里附带的佐料放入锅中,3.0,放,锅, +201004179,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,取出筷子轻微拨动泡面,使佐料充分溶解,面饼充分浸泡受热,4.0,搅拌,筷子, +201004180,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,盖上锅盖等待约1分钟至锅内水再次沸腾,5.0,煮,"锅,锅盖",约1分钟 +201004181,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,去壳鸡蛋,加入锅中,6.0,放,锅, +201004182,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,等待约3至4分钟,即可,7.0,煮,锅,3-4分钟 +201004183,Recipe,老干妈拌面,老干妈拌面,,Recipe,,主食,1.0,,0分钟,约5-7分钟,1人/份,,dishes\staple\老干妈拌面.md,,,,,,,, +201004184,Ingredient,水,水,,Ingredient,,其他,,,,,,,,1,升,False,,,,, +201004185,Ingredient,面,面,,Ingredient,,淀粉类,,,,,,,,120,克,True,,,,, +201004186,Ingredient,老干妈,老干妈,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201004187,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201004188,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将水倒入锅中并煮沸,1.0,煮,锅,约2-3分钟 +201004189,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将面均匀放入锅中,2.0,煮,锅, +201004190,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,在煮的过程注意搅拌,避免面粘成一坨,3.0,搅拌,筷子, +201004191,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,当用筷子挑起一根面且该面能自然地从筷子上滑落时再等30秒关火,4.0,煮,"筷子,锅",30秒 +201004192,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将面夹入碗中,5.0,夹取,"筷子,碗", +201004193,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,按照上面的计量放入老干妈和酱油,6.0,调味,碗, +201004194,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,用筷子将碗里的面、老干妈、酱油拌均匀,7.0,搅拌,"筷子,碗", +201004195,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,吃,8.0,,, +201004196,Recipe,肉蛋盖饭,肉蛋盖饭,,Recipe,,主食,3.0,,5分钟,10分钟,1人,"甜口可调,关火后检查燃气",dishes\staple\肉蛋盖饭.md,,,,,,,, +201004197,Ingredient,米饭,米饭,,Ingredient,,淀粉类,,,,,,,,240,g,True,,,,, +201004198,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,4,个,True,,,,, +201004199,Ingredient,肉馅,肉馅,,Ingredient,,蛋白质,,,,,,,,300,g,True,,,,, +201004200,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201004201,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,25,ml,False,,,,, +201004202,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201004203,Ingredient,红葱油,红葱油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201004204,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201004205,Ingredient,油,油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201004206,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201004207,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,煮好米饭,通常使用买米赠送的量杯,一杯米240g,1.0,煮,电饭煲, +201004208,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中放油30ml,2.0,倒油,锅, +201004209,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放入肉馅,调中火煎至两面微焦,3.0,煎,锅, +201004210,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将鸡蛋打入锅中,不要打散,盖上锅盖,4.0,煎,"锅,锅盖", +201004211,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,调一个碗汁,碗中放入计算中的对应数量的老抽、生抽、醋、糖、红葱油,搅拌均匀,5.0,搅拌,"碗,筷子", +201004212,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,打开锅盖,将碗汁倒入锅中,等待三分钟,6.0,焖,锅,3分钟 +201004213,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,关火,将肉蛋盖到米饭上,7.0,装盘,锅铲, +201004214,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,安全检查,开始食用盖饭,8.0,,, +201004215,Recipe,葱油拌面,葱油拌面,,Recipe,,主食,2.0,沪菜,5分钟,20分钟,3-4,"小火慢炸,葱香浓郁,可冷藏保存,快速晚餐",dishes\staple\葱油拌面.md,,,,,,,, +201004216,Ingredient,干面条,干面条,,Ingredient,,淀粉类,,,,,,,,80,g,True,,,,, +201004217,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,100,g,True,,,,, +201004218,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,100,ml,False,,,,, +201004219,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,60,ml,False,,,,, +201004220,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,ml,False,,,,, +201004221,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,g,False,,,,, +201004222,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将小葱洗净,切成长段(约5-7 cm),葱白和葱绿分开。,1.0,切,"刀,案板",2分钟 +201004223,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中加入100 ml食用油,中火烧热,先放入葱白段煸炒至微黄。,2.0,炒,"锅,锅铲",2-3分钟 +201004224,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入葱绿段,转小火继续煸炒15-20分钟,至葱段焦黄酥脆。,3.0,炒,"锅,锅铲",15-20分钟 +201004225,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将焦黄的葱段捞出,葱油保留在锅中。,4.0,捞,锅铲,30秒 +201004226,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,在葱油中加入生抽、老抽、白糖,小火加热并搅拌约1分钟至糖溶解,酱汁混合均匀后关火。,5.0,"加热,搅拌","锅,锅铲",1分钟 +201004227,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将制作好的葱油酱汁倒入容器中,放凉后密封保存。,6.0,倒,容器,2分钟 +201004228,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,锅中加入1000 ml饮用水,大火烧开。,7.0,煮,锅,2分钟 +201004229,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入80 g干面条,根据包装说明煮至熟透(通常3-8分钟)。,8.0,煮,"锅,筷子",3-8分钟 +201004230,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将煮好的面条捞出,沥干水分,放入碗中。,9.0,"捞,沥","漏勺,碗",30秒 +201004231,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,在面条中加入15 ml葱油酱汁,可选加入炸好的葱段,用筷子快速搅拌均匀即可食用。,10.0,拌,"筷子,碗",30秒 +201004232,Recipe,蒸卤面,蒸卤面,,Recipe,"[{'term': 'steamed卤面', 'language': 'en', 'language_code': 'en-US'}, {'term': '清蒸卤面', 'language': 'zh', 'language_code': 'zh-CN'}]",主食,4.0,豫菜,20分钟,40分钟,2人,"切割猪肉时可让摊贩代劳,提前备料防止手忙脚乱,两次蒸面都要尽量散开避免结团,面条太长可拽断方便搅拌,取出蒸面时动作要轻避免触水",dishes\staple\蒸卤面.md,,,,,,,, +201004233,Ingredient,猪五花肉,猪五花肉,,Ingredient,,蛋白质,,,,,,,,350,g,True,,,,, +201004234,Ingredient,芹菜,芹菜,,Ingredient,,蔬菜,,,,,,,,2,根,True,,,,, +201004235,Ingredient,鲜面条,鲜面条,,Ingredient,,淀粉类,,,,,,,,500,g,True,,,,, +201004236,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,10,cm,False,,,,, +201004237,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,5,瓣,False,,,,, +201004238,Ingredient,姜片,姜片,,Ingredient,,蔬菜,,,,,,,,20,g,False,,,,, +201004239,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,个,False,,,,, +201004240,Ingredient,干红椒,干红椒,,Ingredient,,蔬菜,,,,,,,,3,个,False,,,,, +201004241,Ingredient,花椒,花椒,,Ingredient,,调料,,,,,,,,20,粒,False,,,,, +201004242,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201004243,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201004244,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201004245,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201004246,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201004247,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201004248,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,猪肉去皮,切成2 cm * 6 cm * 0.5 cm薄片备用,1.0,切,刀,5分钟 +201004249,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,芹菜去叶,去掉根部2 cm,然后从中对半切开,切成2 cm段备用,2.0,切,刀,3分钟 +201004250,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大蒜去皮切粒备用,葱切0.2 cm薄片备用,姜切细丝备用,3.0,切,刀,2分钟 +201004251,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,炒锅烧热至冒烟后,倒入3 ml食用油滑锅后倒出底油,4.0,炒,炒锅,1分钟 +201004252,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,重新加入食用油,加入肉片、葱姜蒜、干红椒,炒1分钟,注意不停匀速翻炒,5.0,炒,"炒锅,锅铲",1分钟 +201004253,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入料酒、生抽、老抽,再翻炒1分钟,6.0,炒,"炒锅,锅铲",1分钟 +201004254,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,续入500 ml热水,盖上锅盖炖煮3分钟,7.0,炖,"炒锅,锅盖",3分钟 +201004255,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将芹菜、青椒倒入锅中,加入盐、五香粉调味,盖上锅盖继续炖煮3分钟后关火,8.0,炖,"炒锅,锅盖",3分钟 +201004256,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,蒸锅加入1000 ml水,烧开上汽后,将面条摊平在笼屉上放入锅中,蒸15分钟,9.0,蒸,"蒸锅,笼屉",15分钟 +201004257,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,面条蒸熟后取出,用筷子和无情铁手扒拉散开在案板上,室温冷却,10.0,"蒸,冷却","筷子,案板",5分钟 +201004258,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,将面条放入菜锅中搅拌,搅拌方式为一手持筷,一手持锅铲将菜翻至面条上面,以面条全部均匀上色为搅拌完成标准,11.0,搅拌,"筷子,锅铲",3分钟 +201004259,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,将搅拌后的面条再次放在笼屉上,再次蒸10分钟关火,12.0,蒸,"蒸锅,笼屉",10分钟 +201004260,Recipe,蛋包饭,蛋包饭,,Recipe,,主食,3.0,日式,10分钟,15分钟,1人,"隔夜饭不易粘锅,加牛奶蛋皮更嫩滑,小火煎蛋皮防焦糊,可直接盖蛋皮简化造型",dishes\staple\蛋包饭.md,,,,,,,, +201004261,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201004262,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,30,g,True,,,,, +201004263,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,30,g,True,,,,, +201004264,Ingredient,火腿肠,火腿肠,,Ingredient,,蛋白质,,,,,,,,50,g,True,,,,, +201004265,Ingredient,鸡胸肉,鸡胸肉,,Ingredient,,蛋白质,,,,,,,,50,g,True,,,,, +201004266,Ingredient,玉米粒,玉米粒,,Ingredient,,蔬菜,,,,,,,,30,g,True,,,,, +201004267,Ingredient,青豆,青豆,,Ingredient,,蔬菜,,,,,,,,30,g,True,,,,, +201004268,Ingredient,米饭,米饭,,Ingredient,,淀粉类,,,,,,,,200,g,True,,,,, +201004269,Ingredient,番茄酱,番茄酱,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201004270,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201004271,Ingredient,牛奶,牛奶,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201004272,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,洋葱、胡萝卜、火腿肠或鸡胸肉切成小丁,备用,1.0,切,"刀,案板",3分钟 +201004273,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,热锅,锅中倒入10ml食用油,等待10秒加热,2.0,加热,炒锅,10秒 +201004274,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,先放入洋葱丁翻炒1分钟,出香味后加入胡萝卜、玉米粒、青豆继续翻炒2分钟,3.0,炒,锅铲,3分钟 +201004275,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入火腿肠或鸡胸肉丁,炒至变色,4.0,炒,锅铲,2分钟 +201004276,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入米饭炒散后,加入番茄酱20ml,翻炒均匀,炒饭完成,盛出备用,5.0,炒,锅铲,3分钟 +201004277,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,鸡蛋打散,加入10ml牛奶搅匀,6.0,搅拌,"盆,筷子",1分钟 +201004278,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,锅中放入5ml食用油,倒入蛋液,轻晃锅底让蛋液均匀铺满锅面,7.0,煎,"平底锅,锅铲",1分钟 +201004279,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,用小火加热,待蛋液表面半熟状态时,将炒饭放入蛋液中央,8.0,煎,锅铲,2分钟 +201004280,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,用铲子将蛋皮折叠包住米饭,形成椭圆形状,9.0,折叠,锅铲,1分钟 +201004281,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,用锅铲轻轻推至盘中,整理外形,可在表面挤上少量番茄酱装饰,10.0,装盘,"锅铲,盘子",1分钟 +201004282,Recipe,蛋炒饭,蛋炒饭,,Recipe,,主食,3.0,,10分钟,10分钟,1-2人,"隔夜冷饭最佳,粒粒分明需炒干,现煮米饭需冰箱快速降温",dishes\staple\蛋炒饭.md,,,,,,,, +201004283,Ingredient,冷饭,冷饭,,Ingredient,,淀粉类,,,,,,,,500,ml,True,,,,, +201004284,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1.5,个,True,,,,, +201004285,Ingredient,火腿,火腿,,Ingredient,,蛋白质,,,,,,,,2,个,True,,,,, +201004286,Ingredient,黄瓜,黄瓜,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201004287,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201004288,Ingredient,油,油,,Ingredient,,调料,,,,,,,,12,ml,False,,,,, +201004289,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,4,g,False,,,,, +201004290,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,8,g,False,,,,, +201004291,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,1,颗,False,,,,, +201004292,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201004293,Ingredient,灯影牛肉丝/午餐肉/腊肠/卤肉,灯影牛肉丝/午餐肉/腊肠/卤肉,,Ingredient,,蛋白质,,,,,,,,适量,,False,,,,, +201004294,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,米饭提前用铲子铲成小块,1.0,切,铲子,1分钟 +201004295,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,火腿肠、胡萝卜、黄瓜等根据需求切片或者块状,2.0,切,"刀,案板",3分钟 +201004296,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,如果家里有熟肉,准备好味道更佳,3.0,准备,,1分钟 +201004297,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将蛋白、蛋黄分开,分别打入一个大碗里,各自搅匀。注意,不要在这一步加盐,4.0,"分离,搅拌","碗,筷子",2分钟 +201004298,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,大火热锅,待锅里冒烟放入食用油,放入蛋白,待主体凝固后盛出备用,5.0,炒,"炒锅,锅铲",1分钟 +201004299,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,如果油够,则直接放入蛋黄;如果油不够则放入食用油并等其升温到大火热锅,6.0,炒,"炒锅,锅铲",30秒 +201004300,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,待蛋黄主体凝固后,将火调至中小火,倒入火腿肠、熟肉、胡萝卜、黄瓜等备料,翻炒10秒钟到爆香,7.0,炒,"炒锅,锅铲",10秒 +201004301,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,重新倒入蛋白,翻炒5秒,迅速倒入米饭大火翻炒,使每一粒饭都裹上鸡蛋,8.0,炒,"炒锅,锅铲",2分钟 +201004302,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,翻炒过程中将米饭的块状捣碎,待米饭全部捣碎并翻炒均匀,9.0,"炒,捣碎",锅铲,3分钟 +201004303,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,调至小火,加盐、胡椒粉、生抽,进一步翻炒均匀,能看到一些米饭在锅里有“跳起来”的时候即可,10.0,炒,锅铲,1分钟 +201004304,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,最后倒入香葱再翻炒10秒,11.0,炒,锅铲,10秒 +201004305,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,关火,盛入碗中,12.0,盛盘,碗,30秒 +201004306,Recipe,螺蛳粉,螺蛳粉,,Recipe,,主食,1.0,,0分钟(袋装即食,无需额外准备),约8-10分钟,1人,"缩短煮粉时间可增加嚼劲,可添加炸蛋,配料按个人口味调整",dishes\staple\螺蛳粉.md,,,,,,,, +201004307,Ingredient,袋装螺蛳粉,袋装螺蛳粉,,Ingredient,,淀粉类,,,,,,,,1,包,True,,,,, +201004308,Ingredient,水,水,,Ingredient,,其他,,,,,,,,1000,毫升,False,,,,, +201004309,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅中加水,将水烧开,1.0,煮,"煮锅,电磁炉/灶台", +201004310,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,下米粉,煮3-5分钟,期间用筷子搅拌,防止米粉粘在一起,2.0,煮,"煮锅,筷子",3-5分钟 +201004311,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,下汤料包,按个人口味添加,3.0,煮,煮锅, +201004312,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,下一部分配料包,如木耳、花生、螺蛳(这部分配料需要煮一会才入味),4.0,煮,煮锅, +201004313,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,下调味包,按个人口味添加,5.0,煮,煮锅, +201004314,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,搅拌后捞出,放入碗中,6.0,捞取,"筷子,碗", +201004315,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,下剩下的配料包,如酸笋、豆皮(这部分配料不适合被汤泡太久),7.0,拌,筷子, +201004316,Recipe,酸辣蕨根粉,酸辣蕨根粉,,Recipe,,"主食,凉菜",2.0,川菜,5分钟,10分钟,1人份,"酸辣口味,初学者友好,10分钟快手菜,可调整辣度,建议用碗盛装",dishes\staple\酸辣蕨根粉.md,,,,,,,, +201004317,Ingredient,蕨根粉,蕨根粉,,Ingredient,,淀粉类,,,,,,,,适量,克,True,,,,, +201004318,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,3,份,False,,,,, +201004319,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,2,份,False,,,,, +201004320,Ingredient,油泼辣子,油泼辣子,,Ingredient,,调料,,,,,,,,2,份,False,,,,, +201004321,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2-5,克,False,,,,, +201004322,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201004323,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,适量,个,False,,,,, +201004324,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,适量,瓣,False,,,,, +201004325,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,适量,根,False,,,,, +201004326,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅中加入约为深度3/5的水,烧开,1.0,煮,锅,2分钟 +201004327,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,水沸腾后加入蕨根粉,中小火煮8分钟,2.0,煮,锅,8分钟 +201004328,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,按3:2:2比例加入酱油、香醋、油泼辣子,尝味后酌情加盐、糖,充分搅拌至颗粒溶解,3.0,搅拌,筷子,2分钟 +201004329,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,蕨根粉过冷水后放入碗中,倒入酱料拌匀,撒上葱、蒜、小米辣碎即可,4.0,"过冷水,搅拌,撒料","碗,筷子,刀",1分钟 +201004330,Recipe,醪糟小汤圆,醪糟小汤圆,,Recipe,,主食,2.0,,0 分钟(无需额外准备),10 分钟,1-2 人,"白糖用量可调整,减少100毫升水可增浓口感,枸杞提前煮可更软",dishes\staple\醪糟小汤圆.md,,,,,,,, +201004331,Ingredient,水,水,,Ingredient,,其他,,,,,,,,300,毫升,False,,,,, +201004332,Ingredient,小汤圆,小汤圆,,Ingredient,,淀粉类,,,,,,,,250,克,True,,,,, +201004333,Ingredient,醪糟,醪糟,,Ingredient,,其他,,,,,,,,50,克,True,,,,, +201004334,Ingredient,枸杞,枸杞,,Ingredient,,蔬菜,,,,,,,,5,颗,False,,,,, +201004335,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,适量,,False,,,,, +201004336,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将水倒入锅中并煮沸,1.0,煮,锅, +201004337,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,放入小汤圆煮 8 分钟,2.0,煮,锅,8 分钟 +201004338,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放入醪糟和枸杞再煮 2 分钟,3.0,煮,锅,2 分钟 +201004339,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,盛入碗中根据个人口味加入白糖并搅拌均匀,4.0,搅拌,"碗,筷子", +201004340,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,吃,5.0,,, +201004341,Recipe,韭菜盒子,韭菜盒子,,Recipe,,主食,3.0,,30分钟(面团静置),3-4分钟(煎制),2人,"可根据个人口味添加豆腐干等配料,注意煎制时火候,避免外焦内生",dishes\staple\韭菜盒子.md,,,,,,,, +201004342,Ingredient,韭菜,韭菜,,Ingredient,,蔬菜,,,,,,,,500,g,True,,,,, +201004343,Ingredient,虾仁,虾仁,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201004344,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,3,枚,True,,,,, +201004345,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201004346,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201004347,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,250,g,True,,,,, +201004348,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将面粉放入大碗中,加入水,搅拌成光滑的面团,静置30分钟。,1.0,"搅拌,静置",大碗,30分钟 +201004349,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,韭菜洗净切碎,加入打散的鸡蛋、5g盐,搅拌均匀。,2.0,"洗,切碎,搅拌","刀,案板,盆", +201004350,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将面团分成小剂子,擀成薄圆饼,包入韭菜、虾仁、鸡蛋液。,3.0,"分剂,擀,包","擀面杖,案板", +201004351,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,加入食用油,放入包好的韭菜盒子,煎至两面金黄,约3-4分钟。,4.0,"热锅,煎","平底锅,锅铲",3-4分钟 +201004352,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,盛盘,稍凉后即可享用。,5.0,装盘,盘子, +201004353,Recipe,麻油拌面,麻油拌面,,Recipe,,主食,1.0,,0分钟,3分钟,1人份,"省钱,懒人,简单,Q弹面技巧:加盐煮面",dishes\staple\麻油拌面.md,,,,,,,, +201004354,Ingredient,水,水,,Ingredient,,其他,,,,,,,,1,升,False,,,,, +201004355,Ingredient,快熟面,快熟面,,Ingredient,,淀粉类,,,,,,,,1,块,True,,,,, +201004356,Ingredient,麻油,麻油,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201004357,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,克,False,,,,, +201004358,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201004359,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201004360,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,克,False,,,,, +201004361,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将水倒入锅中并煮沸(喜欢吃Q弹面的同学,可在水里加入30克盐,用盐水煮出来的面会比较Q弹),1.0,煮,锅,至水沸腾 +201004362,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将快熟面放入锅中煮3分钟(也可参考当下品牌快熟面的烹饪时间),2.0,煮,锅,3分钟 +201004363,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,当面开始散了可以开始搅拌,让面受热均匀,3.0,搅拌,筷子或锅铲,约30秒 +201004364,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将水滤干把面倒入碗中,4.0,沥水,"滤网或漏勺,碗",约10秒 +201004365,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,按照上面的计量放入麻油、老抽、胡椒粉、生抽(可选),5.0,拌,碗,约5秒 +201004366,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,筷子搅拌均匀,6.0,拌,筷子,约15秒 +201004367,Recipe,麻辣减脂荞麦面,麻辣减脂荞麦面,,Recipe,,主食,2.0,川菜,5分钟,15分钟,1人份,"半干荞麦面口感最佳,火锅底料+花生酱+牛奶为口味三大巨头,可随意加火锅丸、蛋饺,不吃酸可省醋",dishes\staple\麻辣减脂荞麦面.md,,,,,,,, +201004368,Ingredient,半干荞麦面,半干荞麦面,,Ingredient,,淀粉类,,,,,,,,100,g,True,,,,, +201004369,Ingredient,娃娃菜,娃娃菜,,Ingredient,,蔬菜,,,,,,,,150,g,True,,,,, +201004370,Ingredient,生菜,生菜,,Ingredient,,蔬菜,,,,,,,,80,g,True,,,,, +201004371,Ingredient,火锅底料,火锅底料,,Ingredient,,调料,,,,,,,,25,g,False,,,,, +201004372,Ingredient,花生酱,花生酱,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201004373,Ingredient,全脂牛奶,全脂牛奶,,Ingredient,,蛋白质,,,,,,,,150,ml,False,,,,, +201004374,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,6,ml,False,,,,, +201004375,Ingredient,辣椒油,辣椒油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201004376,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201004377,Ingredient,花椒油,花椒油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201004378,Ingredient,水,水,,Ingredient,,其他,,,,,,,,500,ml,False,,,,, +201004379,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,娃娃菜、生菜洗好,备用,1.0,洗,洗菜盆,2分钟 +201004380,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅内倒入500ml水,开大火,将荞麦面和娃娃菜放进去,等待水沸腾,2.0,煮,直径18cm的小锅,3-4分钟 +201004381,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,水沸腾后,转小火,加入火锅底料、花生酱、牛奶、生抽、辣椒油,水开后煮5分钟,3.0,煮,直径18cm的小锅,5分钟 +201004382,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入生菜,再煮2分钟,4.0,煮,直径18cm的小锅,2分钟 +201004383,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入醋、花椒油,关火,直接端着小锅开吃,5.0,关火,直径18cm的小锅,1分钟 +201004384,Recipe,中式馅饼,中式馅饼,,Recipe,,主食,4.0,,约35分钟(30分钟腌制+5分钟切配),约10分钟,1份,"搅匀馅料与面糊保证味道均匀,馅料可替换为其他熟馅料",dishes\staple\中式馅饼\中式馅饼.md,,,,,,,, +201004385,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,200,g,True,,,,, +201004386,Ingredient,肉沫,肉沫,,Ingredient,,蛋白质,,,,,,,,50,g,True,,,,, +201004387,Ingredient,油,油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201004388,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004389,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201004390,Ingredient,生粉,生粉,,Ingredient,,淀粉类,,,,,,,,10,g,False,,,,, +201004391,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201004392,Ingredient,风味调料,风味调料,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004393,Ingredient,蒜头,蒜头,,Ingredient,,蔬菜,,,,,,,,2,瓣,False,,,,, +201004394,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,0.25,根,False,,,,, +201004395,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201004396,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201004397,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,取肉沫(解冻),加入1/2所有调料(油、盐、糖、酱油、风味调料)和全部生粉,搅拌均匀,腌制30分钟。,1.0,腌制,盆,30分钟 +201004398,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将面粉加入碗中,加入鸡蛋、剩下1/2调料,再加入相当于面粉1/2的水,搅拌均匀成粘稠可流动的面糊。,2.0,搅拌,碗,2分钟 +201004399,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,蒜头切为蒜末,大葱切段,胡萝卜切末。,3.0,切,"刀,案板",3分钟 +201004400,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅冷油,宽油起锅,待油烧热后放入蒜末爆香。,4.0,炒,"炒锅,锅铲",15秒 +201004401,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入腌制的肉沫翻炒至断生,再加入胡萝卜末继续翻炒至油呈金黄色。,5.0,炒,"炒锅,锅铲",2-3分钟 +201004402,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,关火冷却2分钟,将炒好的肉沫倒入生面糊中搅匀。,6.0,搅拌,盆,1分钟 +201004403,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,重新开火,平底锅铺底油,调至小火,将面糊倒入锅中均匀铺满,厚度适中。,7.0,煎,平底锅,30秒 +201004404,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,在饼表面尚为液态时撒上大葱段,保持小火直到底面凝固。,8.0,煎,平底锅,2-3分钟 +201004405,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将饼翻面,继续小火煎烤至另一侧凝固,再每面额外煎20秒。,9.0,煎,"平底锅,锅铲",1分钟 +201004406,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,关火出锅。,10.0,,,5秒 +201004407,Recipe,凉粉,凉粉,,Recipe,,主食,3.0,川菜,5分钟,10分钟,1人份,"冷藏定型,川味小吃,凉拌",dishes\staple\凉粉\凉粉.md,,,,,,,, +201004408,Ingredient,豌豆淀粉,豌豆淀粉,,Ingredient,,淀粉类,,,,,,,,100,g,True,,,,, +201004409,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,3,瓣,False,,,,, +201004410,Ingredient,小米辣,小米辣,,Ingredient,,调料,,,,,,,,3,颗,False,,,,, +201004411,Ingredient,辣椒粉,辣椒粉,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201004412,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201004413,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201004414,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,ml,False,,,,, +201004415,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004416,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004417,Ingredient,花生碎,花生碎,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201004418,Ingredient,香菜,香菜,,Ingredient,"[{'term': '芫荽', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '胡荽', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,5,g,False,,,,, +201004419,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,准备食材。,1.0,准备,"案板,刀",2分钟 +201004420,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,把豌豆淀粉和水各100克混合搅拌。,2.0,搅拌,"碗,筷子",1分钟 +201004421,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,往锅中倒入600g水,大火煮开后转为小火。,3.0,煮,锅,3分钟 +201004422,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入淀粉水,边倒边不断搅拌,搅拌到浓稠且色泽均匀。,4.0,"搅拌,煮","锅,锅铲",3分钟 +201004423,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,找一个容器,在容器中刷一层薄薄的食用油。,5.0,刷油,"容器,刷子",30秒 +201004424,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将煮好的淀粉倒入容器中冷藏2-4小时。,6.0,冷藏,"容器,冰箱",2-4小时 +201004425,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,冷藏后取出,脱模,切条。,7.0,切,"刀,案板",1分钟 +201004426,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,大蒜和小米辣剁成沫,放上10g辣椒粉、5g花生碎,热油搅拌均匀。,8.0,"剁,搅拌","刀,案板,碗,热油锅",2分钟 +201004427,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,再加入10ml酱油、10ml醋、5g白糖、3g鸡精、3g盐搅拌均匀。,9.0,搅拌,"碗,筷子",30秒 +201004428,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将调味料倒在凉粉上,然后撒上香菜即可。,10.0,"淋,撒","碗,筷子",30秒 +201004429,Recipe,基础牛奶面包,基础牛奶面包,,Recipe,,主食,5.0,,约30分钟(含酵头静置5分钟+混合面团),200分钟(含发酵145-165分钟+烘烤40分钟+冷却),1条,"面包回软技巧:密封一晚后口感最佳,冷冻保存:切片冷冻,回温或加热食用,避免冷藏:冷藏会导致水分流失,烤箱温度调整:根据上色情况±5-10℃或±5-10分钟,单位换算:1 cup面粉=120g,1 cup黄油=227g",dishes\staple\基础牛奶面包\基础牛奶面包.md,,,,,,,, +201004430,Ingredient,高筋面粉,高筋面粉,,Ingredient,,淀粉类,,,,,,,,3.5,cup,True,,,,, +201004431,Ingredient,温水,温水,,Ingredient,,其他,,,,,,,,1,cup,False,,,,, +201004432,Ingredient,干酵母,干酵母,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201004433,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201004434,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201004435,Ingredient,糖或糖浆,糖或糖浆,,Ingredient,,调料,,,,,,,,0.125,cup,False,,,,, +201004436,Ingredient,奶制品,奶制品,,Ingredient,,蛋白质,,,,,,,,0.25,cup,True,,,,, +201004437,Ingredient,黄油或玉米油,黄油或玉米油,,Ingredient,,其他,,,,,,,,0.125,cup,False,,,,, +201004438,Ingredient,谷朊粉,谷朊粉,,Ingredient,,其他,,,,,,,,0.25-0.5,cup,False,,,,, +201004439,Ingredient,香草精,香草精,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004440,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将酵母与30℃温水混合,静置5分钟后加入1杯面粉和2g盐,搅拌均匀成粘稠面糊,盖布发酵45-60分钟至表面多泡体积增大。,1.0,"混合,静置,发酵","刮刀,布,容器",5分钟静置+45-60分钟发酵 +201004441,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将剩余面粉、鸡蛋、糖、奶制品、黄油、谷朊粉、香草精与酵头混合,刮壁搅拌至无干粉,倒在面板按压成团。,2.0,"混合,搅拌,按压","刮刀,面板或硅胶垫,手",10分钟 +201004442,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,反复推开对折面团至表面光滑,喷油的容器内放入面团,盖布发酵1小时至两倍大。,3.0,"揉面,发酵","面板,喷壶,布,容器",1小时 +201004443,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,取出面团排气,擀成1cm厚片后卷起,旋转90°再次擀卷,整形接缝朝下放入铺硅油纸的烤盘,二次发酵30-45分钟。,4.0,"排气,擀压,整形,发酵","擀面杖,硅油纸,烤盘,布",30-45分钟 +201004444,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,烤箱最高温空烤预热20分钟,面包表面划口,刷蛋液,180℃上下火烤30分钟后调165℃再烤10分钟。,5.0,"预热,划口,刷蛋液,烘烤","烤箱,剪刀或刀,刷子",50分钟(含预热20分钟+烘烤40分钟) +201004445,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,出炉后放凉,装入食品袋常温保存一周或冷冻保存一个月。,6.0,"冷却,保存",食品袋,自然冷却 +201004446,Recipe,微波炉腊肠煲仔饭,微波炉腊肠煲仔饭,,Recipe,,主食,2.0,,6分钟(切配腊肠、青菜、红萝卜、葱花),15分钟,1人份,"微波炉,单身汉,简单快捷,一人食",dishes\staple\微波炉腊肠煲仔饭\微波炉腊肠煲仔饭.md,,,,,,,, +201004447,Ingredient,米,米,,Ingredient,,淀粉类,,,,,,,,200,ml,True,,,,, +201004448,Ingredient,腊肠,腊肠,,Ingredient,,蛋白质,,,,,,,,1,根,True,,,,, +201004449,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201004450,Ingredient,红萝卜,红萝卜,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201004451,Ingredient,青菜,青菜,,Ingredient,,蔬菜,,,,,,,,适量,,True,,,,, +201004452,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201004453,Ingredient,油,油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201004454,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201004455,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,1,颗,False,,,,, +201004456,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将米淘洗干净后倒入饭碗内,加入400ml的水,盖上盖,1.0,"淘洗,加水","饭碗,微波炉专用盖", +201004457,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,放入微波炉,高火6分钟,煮饭途中准备原料,2.0,微波,微波炉,6分钟 +201004458,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,切好腊肠、洗好青菜、切好红萝卜片、切好葱花,3.0,"切,洗","刀,案板", +201004459,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,青菜碗中放入青菜、红萝卜片,倒入10ml油,放入5g盐,4.0,混合,青菜碗, +201004460,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,小碗中倒入10ml生抽、5ml油,5.0,混合,小碗, +201004461,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,6分钟后取出饭碗,可见米饭八分熟,在米饭上摆入腊肠片,继续高火2分钟,6.0,微波,"微波炉,隔热手套",2分钟 +201004462,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,取出腊肠饭,放入青菜碗,高火4-5分钟,7.0,微波,微波炉,4-5分钟 +201004463,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,在腊肠饭上摆好青菜,磕入鸡蛋,继续高火40-60秒,8.0,微波,微波炉,40-60秒 +201004464,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,取出腊肠饭,将小碗放入微波炉,高火30秒,9.0,微波,微波炉,30秒 +201004465,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将叮热的生抽淋在腊肠饭上,撒上葱花即可,10.0,"淋,撒",小碗, +201004466,Recipe,意式肉酱面,意式肉酱面,,Recipe,,主食,1.0,意大利,约5分钟,15分钟,2人,"意面粗细不同需按包装时间煮,意大利面酱≠番茄沙司,调味料不同",dishes\staple\意式肉酱面\意式肉酱面.md,,,,,,,, +201004467,Ingredient,意大利面,意大利面,,Ingredient,,淀粉类,,,,,,,,180,克,True,,,,, +201004468,Ingredient,肉沫,肉沫,,Ingredient,,蛋白质,,,,,,,,80,克,True,,,,, +201004469,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,150,克,True,,,,, +201004470,Ingredient,意大利面酱,意大利面酱,,Ingredient,,调料,,,,,,,,300,克,False,,,,, +201004471,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,毫升,False,,,,, +201004472,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,锅中加水,烧开后放入意面,按包装时间煮 6-12 分钟,1.0,煮,锅,6-12分钟 +201004473,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,洋葱切成小丁,2.0,切,"刀,案板",约2分钟 +201004474,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,空锅中倒油,中火下入洋葱碎,持续搅拌至洋葱半透明,3.0,"炒,搅拌","锅,锅铲",约3分钟 +201004475,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,下入肉沫,继续搅拌搅散,炒至肉末变棕色,4.0,"炒,搅拌","锅,锅铲",约3分钟 +201004476,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入意大利面酱,稍微搅拌均匀,5.0,搅拌,"锅,锅铲",约1分钟 +201004477,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将煮好的意面沥干水分,倒入肉酱中搅拌均匀即可,6.0,搅拌,"漏勺,锅,锅铲",约1分钟 +201004478,Recipe,扬州炒饭,扬州炒饭,,Recipe,,主食,4.0,苏菜,约15分钟(切丁、打蛋、焯水),约10分钟(炒制),1-2人,"冷冻蔬菜混合包可替代切丁,炒饭需快速砸击使米粒分明,做完胳膊酸痛属正常需加强上肢锻炼",dishes\staple\扬州炒饭\扬州炒饭.md,,,,,,,, +201004479,Ingredient,冷饭,冷饭,,Ingredient,,淀粉类,,,,,,,,500,g,True,,,,, +201004480,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2.5,个,True,,,,, +201004481,Ingredient,冷冻去皮基围虾,冷冻去皮基围虾,,Ingredient,,蛋白质,,,,,,,,12.5,只,True,,,,, +201004482,Ingredient,午餐肉罐头,午餐肉罐头,,Ingredient,,蛋白质,,,,,,,,150,g,True,,,,, +201004483,Ingredient,青豆,青豆,,Ingredient,,蔬菜,,,,,,,,30,g,True,,,,, +201004484,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,30,g,True,,,,, +201004485,Ingredient,玉米粒,玉米粒,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201004486,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201004487,Ingredient,油,油,,Ingredient,,调料,,,,,,,,35,ml,False,,,,, +201004488,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,13.5,g,False,,,,, +201004489,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,胡萝卜切丁 0.2cm×0.2cm×0.2cm,备用,1.0,切,"刀,案板",2分钟 +201004490,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,午餐肉切丁 0.2cm×0.2cm×0.2cm,备用,2.0,切,"刀,案板",1分钟 +201004491,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,葱分别取葱白和葱绿,各切成 0.25-0.5cm 的小段,分开备用,3.0,切,"刀,案板",1分钟 +201004492,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,在碗中打入鸡蛋液,均匀搅拌,备用,4.0,搅拌,"碗,筷子",30秒 +201004493,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将胡萝卜、青豆、玉米粒煮熟捞出,备用(水别倒),5.0,煮,"锅,漏勺",3-4分钟 +201004494,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将虾煮熟,捞出备用(水可以倒了),6.0,煮,"锅,漏勺",2分钟 +201004495,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,热锅热油(第二次倒油 20-30ml),油温后缓慢倒入鸡蛋液,不搅拌,7.0,"炒,煎","炒锅,锅铲",30秒 +201004496,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,鸡蛋凝固后立刻捞出,备用,8.0,炒,锅铲,10秒 +201004497,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将午餐肉、青豆、胡萝卜、玉米粒、虾倒入锅中翻炒 1-2 分钟,装盘备用,9.0,炒,"炒锅,锅铲",1-2分钟 +201004498,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,水冲一下锅,将杂物冲干净,保证锅内干净(可以有油但无杂质),10.0,清洗,水,30秒 +201004499,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,热锅热油(10ml),将葱白放入爆香,11.0,炒,"炒锅,锅铲",20秒 +201004500,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,调至小火,放入米饭,用铲子快速砸击米饭并翻炒,使米饭粒粒分明,12.0,炒,锅铲,2分钟 +201004501,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,倒入鸡蛋,继续砸击,使鸡蛋碎开并与米饭充分混合,13.0,炒,锅铲,1分钟 +201004502,CookingStep,步骤14,步骤14,,CookingStep,,,,,,,,,,,,,转大火,倒入所有备用配料,快速翻炒 1-2 分钟,14.0,炒,锅铲,1-2分钟 +201004503,CookingStep,步骤15,步骤15,,CookingStep,,,,,,,,,,,,,撒入盐,并翻炒至充分混合,15.0,炒,锅铲,30秒 +201004504,CookingStep,步骤16,步骤16,,CookingStep,,,,,,,,,,,,,撒入葱绿,翻炒 1 分钟,16.0,炒,锅铲,1分钟 +201004505,CookingStep,步骤17,步骤17,,CookingStep,,,,,,,,,,,,,关火,装盘,17.0,装盘,"锅铲,盘子",10秒 +201004506,Recipe,披萨饼皮,披萨饼皮,,Recipe,,主食,4.0,,8~12小时(低温隔夜发酵),16~18分钟(根据配料不同),4个8~9寸披萨(约4人份),"低温隔夜发酵,软面团,注意水量比例,第一次做需观察火候,中筋面粉,避免使用易出水水果",dishes\staple\披萨饼皮\披萨饼皮.md,,,,,,,, +201004507,Ingredient,中筋面粉,中筋面粉,,Ingredient,,淀粉类,,,,,,,,500,克,True,,,,, +201004508,Ingredient,温水,温水,,Ingredient,,其他,,,,,,,,350,克,False,,,,, +201004509,Ingredient,安琪干酵母粉,安琪干酵母粉,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201004510,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201004511,Ingredient,橄榄油,橄榄油,,Ingredient,,调料,,,,,,,,35,克,False,,,,, +201004512,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201004513,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,用准备好的温水把酵母粉化开,稍微搅拌即可,备用,1.0,搅拌,盆, +201004514,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,取准备好的面粉,依次添加盐、橄榄油、白砂糖,2.0,混合,盆, +201004515,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,边加水边搅拌直至水全部加完,搅拌至看不到干面粉为止,3.0,搅拌,盆, +201004516,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将面团放入约三倍大的容器,密封后冰箱冷藏(4℃)发酵8~12小时,4.0,冷藏发酵,容器,8~12小时 +201004517,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,观察面团醒发至原始大小约两倍即可,5.0,观察,, +201004518,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将醒发好的面团均匀分成四份,分别用保鲜膜盖好备用,6.0,分割,保鲜膜, +201004519,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,案板撒适量干面粉,将面团揉至表面稍微光滑即可,7.0,揉面,"案板,擀面杖(可选)", +201004520,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,用手拉扯或擀面杖擀平,厚度均匀即可,不一定非得圆形,8.0,"擀,拉扯",擀面杖(可选), +201004521,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,铺好油纸,放上饼皮,按个人口味添加食材并撒上芝士碎,9.0,"铺放,撒",烘焙油纸, +201004522,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,水果类披萨:烤箱上火180℃,下火220℃,烤16分钟,10.0,烤,烤箱,16分钟 +201004523,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,肉类蔬菜披萨:烤箱上火200℃,下火230℃,烤18分钟,11.0,烤,烤箱,18分钟 +201004524,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,出炉后挤上沙拉酱或其他喜欢的酱料即可享用,12.0,挤酱,, +201004525,Recipe,日式咖喱饭,日式咖喱饭,,Recipe,,主食,4.0,日料,约15分钟,约40分钟(15分钟炖煮+10分钟收汁),6碗,"冷藏后风味更佳,可提前批量制作,注意水位线不低于食材2/3,咖喱块切碎易融化,可搭配太阳蛋或花椰菜",dishes\staple\日式咖喱饭\日式咖喱饭.md,,,,,,,, +201004526,Ingredient,咖喱块,咖喱块,,Ingredient,,调料,,,,,,,,115,g,True,,,,, +201004527,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,2,个,True,,,,, +201004528,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,个,True,,,,, +201004529,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,1,根,True,,,,, +201004530,Ingredient,蒜头,蒜头,,Ingredient,,调料,,,,,,,,2.5,瓣,True,,,,, +201004531,Ingredient,肉,肉,,Ingredient,,蛋白质,,,,,,,,2,斤,True,,,,, +201004532,Ingredient,花椰菜,花椰菜,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201004533,Ingredient,培根,培根,,Ingredient,,蛋白质,,,,,,,,适量,,False,,,,, +201004534,Ingredient,煎蛋,煎蛋,,Ingredient,,蛋白质,,,,,,,,适量,,False,,,,, +201004535,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,胡萝卜去头尾、去皮,滚刀切块;洋葱剥去外层去芯,切成月牙状;土豆去皮切大块;肉切块;蒜头拍碎切末;咖喱块切碎备用。,1.0,"切,去皮,拍碎","刀,案板",约10分钟 +201004536,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,热油锅,放入蒜末和肉块,快速翻炒至肉表面变白。,2.0,炒,"炒锅,锅铲",2-3分钟 +201004537,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入胡萝卜块,快速翻炒至均匀受热。,3.0,炒,锅铲,1-2分钟 +201004538,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入洋葱,快速翻炒至洋葱变透明。,4.0,炒,锅铲,2-3分钟 +201004539,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入土豆块,继续翻炒至土豆变软(可用筷子确认)。,5.0,炒,"锅铲,筷子",3-4分钟 +201004540,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加水没过所有食材,沸腾后保持中火炖煮15分钟。,6.0,"煮,炖","锅,锅盖",15分钟 +201004541,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,关火,加入切碎的咖喱块并搅拌至完全融化。,7.0,搅拌,锅铲,1-2分钟 +201004542,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,再次开火,小火慢炖并持续搅拌10分钟,防止糊锅,直至咖喱呈粘稠状态后关火。,8.0,"炖,搅拌",锅铲,10分钟 +201004543,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,冷藏保存的咖喱每次取所需份量,微波炉高火2-3分钟或锅中加50ml水加热并搅拌后盖在米饭上即可。,9.0,"加热,搅拌","微波炉,锅,锅铲",2-3分钟 +201004544,Recipe,日式肥牛丼饭,日式肥牛丼饭,,Recipe,,主食,4.0,日式,约10分钟,约15分钟,2人,"优质牛肉可不焯水以保留风味,味淋去腥,可额外加清酒增香,冷藏后微波或锅加热,锅加热需额外加水并不断翻动",dishes\staple\日式肥牛丼饭\日式肥牛丼饭.md,,,,,,,, +201004545,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201004546,Ingredient,肥牛,肥牛,,Ingredient,,蛋白质,,,,,,,,250,克,True,,,,, +201004547,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1.5,根,True,,,,, +201004548,Ingredient,白芝麻,白芝麻,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201004549,Ingredient,味淋,味淋,,Ingredient,,调料,,,,,,,,40,克,False,,,,, +201004550,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,30,克,False,,,,, +201004551,Ingredient,耗油,耗油,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201004552,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201004553,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,克,False,,,,, +201004554,Ingredient,水,水,,Ingredient,,其他,,,,,,,,250,毫升,False,,,,, +201004555,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,克,False,,,,, +201004556,Ingredient,清酒,清酒,,Ingredient,,调料,,,,,,,,15,克,False,,,,, +201004557,Ingredient,出汁,出汁,,Ingredient,,调料,,,,,,,,适量,毫升,False,,,,, +201004558,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,洋葱剥去外层去芯,切成月牙状,1.0,切,刀, +201004559,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱洗净切成0.5cm的小段,2.0,切,刀, +201004560,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅直接放入白芝麻,前后晃动锅体使芝麻均匀受热至略呈金黄色,3.0,炒,锅, +201004561,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,肥牛焯水1分钟后捞出,4.0,焯水,锅,1分钟 +201004562,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将味淋、酱油、耗油、糖、老抽在碗中搅拌混合成调料,5.0,混合,碗, +201004563,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,热油锅放入洋葱,快速翻炒至洋葱变透明状,6.0,炒,锅, +201004564,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,关小火,加入250g水或出汁,开回大火加热等待3分钟,7.0,煮,锅,3分钟 +201004565,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入牛肉和调料,不断翻动所有食材10分钟,防止食材粘锅,8.0,煮,锅,10分钟 +201004566,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,关火,盛装肥牛丼至米饭上,把汁水淋一些在饭上,9.0,盛装,锅铲, +201004567,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,撒上葱花和白芝麻,制作完成,10.0,撒,手, +201004568,Recipe,河南蒸面条,河南蒸面条,,Recipe,"[{'term': '河南steamed面条', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '河南清蒸面条', 'language': 'zh', 'language_code': 'zh-CN'}]",主食,4.0,豫菜,约20分钟(切菜+第一次蒸面),约35分钟(第一次蒸15分钟+炒制5分钟+第二次蒸15分钟),1人,挂面粗细影响口感:细圆挂面更劲道,宽扁挂面更软,dishes\staple\河南蒸面条\河南蒸面条.md,,,,,,,, +201004569,Ingredient,挂面,挂面,,Ingredient,,淀粉类,,,,,,,,300,g,True,,,,, +201004570,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,350,g,True,,,,, +201004571,Ingredient,蒜薹,蒜薹,,Ingredient,,蔬菜,,,,,,,,150,g,True,,,,, +201004572,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201004573,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201004574,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201004575,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004576,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201004577,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201004578,Ingredient,十三香,十三香,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201004579,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201004580,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,5,g,False,,,,, +201004581,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201004582,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201004583,Ingredient,麻油,麻油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004584,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,起锅加7成水,水开后上蒸篦子,将挂面均匀铺开放置,淋5ml油并抹匀,蒸15分钟;蒸好后取出挂面和蒸篦子,倒掉锅中水。,1.0,蒸,"锅,蒸篦子",15分钟 +201004585,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,五花肉切成2mm厚度的肉片;蒜薹切成3cm段;葱切成0.2cm薄片;姜切成1mm×1mm×3cm细丝;蒜拍碎后切成1mm粒度。,2.0,切,"刀,砧板",约5分钟 +201004586,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,起锅烧干水分,加3ml食用油并摇晃锅使油挂满锅的2/3;中火下肉片翻炒1分钟,加入葱姜蒜和料酒再炒1分钟;加入蒜薹段炒1分钟;调入老抽、生抽、蚝油、盐、鸡精、十三香再炒1分钟;加500ml水没过蔬菜,炖煮1分钟;倒入蒸好的挂面,不断搅拌3分钟至均匀上色后关火,将面条和菜倒入盆中。,3.0,"炒,炖,搅拌","锅,铲子,盆",约8分钟 +201004587,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,起锅加冷水7成,放上蒸篦子,将拌好的面条和菜均匀铺在上面;水开后大火蒸15分钟;出锅后淋上10g麻油即可食用。,4.0,蒸,"锅,蒸篦子",15分钟 +201004588,Recipe,火腿饭团,火腿饭团,,Recipe,,主食,4.0,,10分钟,50分钟,2人,"沙拉酱用量可调整,可混合不同沙拉酱",dishes\staple\火腿饭团\火腿饭团.md,,,,,,,, +201004589,Ingredient,火腿,火腿,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201004590,Ingredient,米饭,米饭,,Ingredient,,淀粉类,,,,,,,,125,g,True,,,,, +201004591,Ingredient,水,水,,Ingredient,,其他,,,,,,,,90,ml,False,,,,, +201004592,Ingredient,冷冻青豆,冷冻青豆,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201004593,Ingredient,冷冻玉米粒,冷冻玉米粒,,Ingredient,,蔬菜,,,,,,,,30,g,False,,,,, +201004594,Ingredient,海苔碎,海苔碎,,Ingredient,,其他,,,,,,,,10,g,False,,,,, +201004595,Ingredient,沙拉酱,沙拉酱,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201004596,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201004597,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将米饭和水放到电饭锅里,点击米饭模式,等待完成,1.0,煮,电饭锅,约40分钟 +201004598,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,冷冻玉米粒和青豆放到锅里,加水没过所有食材,沸腾后静待2分钟后,捞出,2.0,煮,锅,5分钟 +201004599,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,火腿切成1cm的方块,3.0,切,"刀,案板",2分钟 +201004600,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入10ml食用油,加入火腿翻炒至火腿上色,4.0,炒,"炒锅,锅铲",3分钟 +201004601,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将米饭、火腿、海苔碎、青豆、玉米粒、沙拉酱放入碗中,混合均匀即可,5.0,混合,"碗,筷子",2分钟 +201004602,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,装盘(如果有的话),6.0,装盘,盘子,1分钟 +201004603,Recipe,炒凉粉,炒凉粉,,Recipe,,主食,3.0,西北菜,5分钟,约1分钟,1人份,"豌豆淀粉凉粉最佳,红薯淀粉可替代",dishes\staple\炒凉粉\炒凉粉.md,,,,,,,, +201004604,Ingredient,凉粉,凉粉,,Ingredient,,淀粉类,,,,,,,,500,g,True,,,,, +201004605,Ingredient,玉米油,玉米油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201004606,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201004607,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,15,g,False,,,,, +201004608,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201004609,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,ml,False,,,,, +201004610,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201004611,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201004612,Ingredient,十三香,十三香,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201004613,Ingredient,中粗辣椒面,中粗辣椒面,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201004614,Ingredient,矿泉水,矿泉水,,Ingredient,,其他,,,,,,,,20,ml,False,,,,, +201004615,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,凉粉改刀切麻将块大小,1.0,切,"刀,案板",2分钟 +201004616,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,开小火,起锅烧油,锅烧微热后,下入蒜末爆香后加入豆瓣酱炒出红油,2.0,"炒,爆香","炒锅,锅铲",20秒 +201004617,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将凉粉块下入锅中,翻炒10秒,3.0,炒,锅铲,10秒 +201004618,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入生抽提味,老抽上色,翻炒均匀后加入辣椒面继续翻炒均匀,4.0,炒,锅铲,10秒 +201004619,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入食盐、十三香继续翻炒10秒,5.0,炒,锅铲,10秒 +201004620,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入准备好的矿泉水,再次翻炒10秒,待汤汁浓稠后,关火出锅装盘,6.0,炒,锅铲,10秒 +201004621,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,撒上葱花即可完成,7.0,撒,筷子,5秒 +201004622,Recipe,炒意大利面,炒意大利面,,Recipe,,主食,3.0,,约5分钟,30分钟,1人,,dishes\staple\炒意大利面\炒意大利面.md,,,,,,,, +201004623,Ingredient,意大利面,意大利面,,Ingredient,,淀粉类,,,,,,,,50,克,True,,,,, +201004624,Ingredient,肥牛片,肥牛片,,Ingredient,,蛋白质,,,,,,,,5,片,True,,,,, +201004625,Ingredient,番茄酱,番茄酱,,Ingredient,,调料,,,,,,,,10,克,False,,,,, +201004626,Ingredient,黑胡椒酱,黑胡椒酱,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201004627,Ingredient,菜籽油,菜籽油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201004628,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201004629,Ingredient,水,水,,Ingredient,,其他,,,,,,,,250,克,False,,,,, +201004630,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,加入250克水,待水烧开,1.0,煮,锅, +201004631,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,下入意大利面,中火煮15-20分钟(面条中心略硬需继续煮),2.0,煮,锅,15-20分钟 +201004632,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,捞出面条,盛入盘中备用,3.0,捞,漏勺, +201004633,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅倒入食用油,待油温中热,下入面条翻炒一分钟(如太干可少量加水),4.0,炒,"炒锅,锅铲",1分钟 +201004634,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入番茄酱、肥牛片、食盐,继续翻炒一分钟,5.0,炒,锅铲,1分钟 +201004635,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,起锅,6.0,,, +201004636,Recipe,烙饼,烙饼,,Recipe,,主食,4.0,,40分钟(醒面),约6-8分钟(每面各烙3-4次,每次1分钟),4份,"热油酥效果更好,热锅凉油防粘,刷油锁水",dishes\staple\烙饼\烙饼.md,,,,,,,, +201004637,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,400,g,True,,,,, +201004638,Ingredient,热水,热水,,Ingredient,,其他,,,,,,,,130,ml,False,,,,, +201004639,Ingredient,冷水,冷水,,Ingredient,,其他,,,,,,,,130,ml,False,,,,, +201004640,Ingredient,油,油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201004641,Ingredient,油酥,油酥,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201004642,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将400g面粉倒入盆中,一半用凉水和面,一半用热水和面,搅拌成面絮,用手揉成团。用保鲜膜封起来,醒面40分钟。,1.0,"和面,揉面,醒面","盆,保鲜膜",40分钟 +201004643,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,离醒面完成时间还有10分钟时,查看油酥做法并准备热油酥。,2.0,准备,,10分钟 +201004644,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,醒好的面不用揉,稍微摁一下,用一横刀一竖刀将其分成四份。,3.0,切分,刀, +201004645,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,搓圆,擀开,擀成与电饼铛大小差不多的饼,取1/4的油酥,将饼表面涂抹均匀。,4.0,"搓圆,擀,涂抹","擀面杖,刷子", +201004646,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,沿饼的半径切开,从外圈将其卷成圆锥形,然后将圆锥尾部捏好,防止油酥外漏。,5.0,"切,卷,捏合",刀, +201004647,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,按压面饼圆锥尖的地方,将其压扁,然后再次擀成与电饼铛大小差不多的面饼(厚度约为3mm)。,6.0,"按压,擀",擀面杖, +201004648,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将电饼铛预热,涂上凉油(热锅凉油),将擀好的饼放入电饼铛中,将饼的上方也刷点油,涂抹均匀(锁住水分),盖上盖子。,7.0,"预热,刷油,烙","电饼铛,刷子", +201004649,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,大火烙一分钟,打开盖子,将饼翻个面再烙一分钟。,8.0,"烙,翻面","电饼铛,锅铲",1分钟 +201004650,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,重复以上动作,完成饼的烙制。,9.0,"烙,翻面",电饼铛,约4-6分钟 +201004651,Recipe,芝麻烧饼,芝麻烧饼,,Recipe,,主食,3.0,,10分钟(醒面),电饼铛大饼档时间(约5-8分钟),7张饼,"无电饼铛可用平底锅,芝麻可省略",dishes\staple\烧饼\芝麻烧饼.md,,,,,,,, +201004652,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,300,克,True,,,,, +201004653,Ingredient,酵母粉,酵母粉,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201004654,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,克,False,,,,, +201004655,Ingredient,十三香,十三香,,Ingredient,,调料,,,,,,,,4,克,False,,,,, +201004656,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,40,克,False,,,,, +201004657,Ingredient,温水,温水,,Ingredient,,其他,,,,,,,,180,克,False,,,,, +201004658,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201004659,Ingredient,白芝麻,白芝麻,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201004660,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,面团:将300克面粉、3克酵母粉、3克白糖、180克40℃温水和20克食用油混合,揉成面团后醒面10分钟。,1.0,"混合,揉,醒面",盆,10分钟 +201004661,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,油酥:在小碗中放入30克面粉、2克盐、4克十三香和20克食用油,拌匀后静置备用。,2.0,"拌,静置",小碗, +201004662,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,做饼:将醒好的面团擀成长方形,均匀抹上调好的油酥,从一端卷起,切成7个面剂子,对折后用虎口收拢成圆团,先沾水再沾白芝麻,最后擀成小圆饼。,3.0,"擀,抹,卷,切,对折,收拢,沾,擀","擀面杖,刀,案板", +201004663,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,烙饼:电饼铛预热后倒入凉油铺满锅底,放入擀好的饼,在饼表面再刷一层油,盖盖选择大饼档,听到提示音即可出锅。,4.0,"预热,倒油,烙,刷油,盖盖","电饼铛,刷子",电饼铛大饼档时间 +201004664,Recipe,电饭煲三文鱼炊饭,电饭煲三文鱼炊饭,,Recipe,,主食,2.0,,10分钟,30-45分钟,1人,想口感浓厚一点,可以加多一汤匙牛油,dishes\staple\电饭煲三文鱼炊饭\电饭煲三文鱼炊饭.md,,,,,,,, +201004665,Ingredient,米,米,,Ingredient,,淀粉类,,,,,,,,1,杯,True,,,,, +201004666,Ingredient,三文鱼,三文鱼,,Ingredient,,蛋白质,,,,,,,,300,克,True,,,,, +201004667,Ingredient,有盐牛油,有盐牛油,,Ingredient,,调料,,,,,,,,1,汤匙,False,,,,, +201004668,Ingredient,水,水,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201004669,Ingredient,粟米,粟米,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201004670,Ingredient,金菇,金菇,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201004671,Ingredient,冬菇,冬菇,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201004672,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,三文鱼去鳞,去骨,1.0,切,刀, +201004673,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,金菇、冬菇切碎,2.0,切,刀, +201004674,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,洗米三次,3.0,洗,盆, +201004675,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,把三文鱼、米、牛油放入电饭煲,4.0,放,电饭煲, +201004676,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,根据电饭煲的刻度放水,5.0,加水,电饭煲, +201004677,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,把电饭煲調較至煲飯模式,等待大約30-45分钟,6.0,煮,电饭煲,30-45分钟 +201004678,Recipe,空气炸锅照烧鸡饭,空气炸锅照烧鸡饭,,Recipe,"[{'term': '空气deep-fried锅照烧鸡饭', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '空气油炸锅照烧鸡饭', 'language': 'zh', 'language_code': 'zh-CN'}]",主食,4.0,,约10分钟,40分钟,1人,操作时注意温度以免烫伤,dishes\staple\空气炸锅照烧鸡饭\空气炸锅照烧鸡饭.md,,,,,,,, +201004679,Ingredient,鸡肉,鸡肉,,Ingredient,,蛋白质,,,,,,,,900,g,True,,,,, +201004680,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,100-125,ml,False,,,,, +201004681,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,60-65,g,False,,,,, +201004682,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,30-35,ml,False,,,,, +201004683,Ingredient,丽滋饼干,丽滋饼干,,Ingredient,,淀粉类,,,,,,,,48,g,False,,,,, +201004684,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,False,,,,, +201004685,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将酱油、糖和醋混合在一起,搅匀料汁备用,1.0,混合,碗, +201004686,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,另一个碗中加入鸡肉、鸡蛋、1/2料汁和压碎的丽滋饼干,搅拌均匀,2.0,搅拌,碗, +201004687,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,空气炸锅用箔纸碗铺底,加入肉饼混合物,将剩余的料汁均匀倒在上面,3.0,"铺底,倒入","空气炸锅,箔纸碗", +201004688,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,350°F炸40分钟,最好在米饭上食用,4.0,炸,空气炸锅,40分钟 +201004689,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,外观呈金黄酥脆后出锅,切块盛盘,5.0,"出锅,切块","刀,盘", +201004690,Recipe,煮锅蒸米饭,煮锅蒸米饭,,Recipe,"[{'term': '煮锅清蒸米饭', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '煮锅steamed米饭', 'language': 'zh', 'language_code': 'zh-CN'}]",主食,2.0,,2分钟,15-20分钟,1人,"厚底煮锅,严丝合缝锅盖,小火焖饭,中途勿开盖",dishes\staple\米饭\煮锅蒸米饭.md,,,,,,,, +201004691,Ingredient,北方大米,北方大米,,Ingredient,,淀粉类,,,,,,,,100,毫升,True,,,,, +201004692,Ingredient,水,水,,Ingredient,,其他,,,,,,,,200,毫升,False,,,,, +201004693,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,清洗大米,1.0,洗,盆, +201004694,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将米和水加入煮锅,2.0,加,煮锅, +201004695,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大火煮至水沸腾,3.0,煮,煮锅, +201004696,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,搅拌底部防止粘黏,4.0,搅拌,锅铲, +201004697,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,盖上锅盖,转小火加热10-15分钟(根据对软糯程度的喜好),中途切勿打开锅盖,5.0,焖,"煮锅,锅盖",10-15分钟 +201004698,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,关火,静置5分钟,6.0,静置,煮锅,5分钟 +201004699,Recipe,电饭煲蒸米饭,电饭煲蒸米饭,,Recipe,"[{'term': '电饭煲steamed米饭', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '电饭煲清蒸米饭', 'language': 'zh', 'language_code': 'zh-CN'}]",主食,1.0,,5分钟,30-40分钟,1人,"指尖量水法,江南米水量约2.6厘米,北方大米水量约2厘米,南方多用江南米,北方多用北方大米,水量决定口感",dishes\staple\米饭\电饭煲蒸米饭.md,,,,,,,, +201004700,Ingredient,江南米,江南米,,Ingredient,,淀粉类,,,,,,,,100-200,毫升,True,,,,, +201004701,Ingredient,北方大米,北方大米,,Ingredient,,淀粉类,,,,,,,,100-200,毫升,True,,,,, +201004702,Ingredient,水,水,,Ingredient,,其他,,,,,,,,指尖量水法,,False,,,,, +201004703,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,清洗米,1.0,清洗,盆, +201004704,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将米和水一起加入电饭煲中,2.0,加,电饭煲, +201004705,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,连接电饭煲电源,进入加热模式。等待大约30分钟,3.0,加热,电饭煲,30分钟 +201004706,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,待电饭煲自动进入保温模式后,4.0,保温,电饭煲, +201004707,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将米在电饭煲中闷10-15分钟,5.0,焖,电饭煲,10-15分钟 +201004708,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,盛出米,6.0,盛出,电饭煲, +201004709,Recipe,老友猪肉粉,老友猪肉粉,,Recipe,,主食,3.0,广西菜,30分钟(米粉温水泡发),约10分钟,1人份,"米粉需提前用温水泡发30分钟,酸笋先炒干去水味",dishes\staple\老友猪肉粉\老友猪肉粉.md,,,,,,,, +201004710,Ingredient,米粉,米粉,,Ingredient,,淀粉类,,,,,,,,250,g,True,,,,, +201004711,Ingredient,猪肉,猪肉,,Ingredient,,蛋白质,,,,,,,,50,g,True,,,,, +201004712,Ingredient,酸笋,酸笋,,Ingredient,,蔬菜,,,,,,,,50,g,True,,,,, +201004713,Ingredient,剁椒,剁椒,,Ingredient,,调料,,,,,,,,15,g,False,,,,, +201004714,Ingredient,豆豉,豆豉,,Ingredient,,调料,,,,,,,,30,g,False,,,,, +201004715,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201004716,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201004717,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,25,ml,False,,,,, +201004718,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201004719,Ingredient,米醋,米醋,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004720,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004721,Ingredient,油,油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201004722,Ingredient,生粉,生粉,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201004723,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201004724,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,450,ml,False,,,,, +201004725,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将猪肉用料酒、盐、生抽、生粉、胡椒粉放入碗中拌匀,腌制备用。,1.0,腌制,碗,约2分钟 +201004726,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,热锅不放油,倒入酸笋炒干水分,中间留出空位。,2.0,炒干,炒锅,约2分钟 +201004727,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,在酸笋中间倒入食用油,加入大蒜、剁椒、豆豉炒香,再与酸笋混合。,3.0,炒,"炒锅,锅铲",约1分钟 +201004728,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,放入腌制好的猪肉,加入10ml生抽,翻炒1分钟。,4.0,炒,"炒锅,锅铲",1分钟 +201004729,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入米醋、生抽和清水,煮开。,5.0,煮,炒锅,约2分钟 +201004730,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,水开后加入泡好的米粉,继续煮3分钟即可出锅。,6.0,煮,炒锅,3分钟 +201004731,Recipe,茄子肉煎饼,茄子肉煎饼,,Recipe,"[{'term': '紫茄子肉煎饼', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '青茄子肉煎饼', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'eggplant肉煎饼', 'language': 'en', 'language_code': 'en-US'}, {'term': '茄子肉pan-fried饼', 'language': 'zh', 'language_code': 'zh-CN'}]",主食,3.0,,约10分钟(切茄子、腊肉、调面糊),约6-9分钟(煎制),2人,小火煎,dishes\staple\茄子肉煎饼\茄子肉煎饼.md,,,,,,,, +201004732,Ingredient,米粉,米粉,,Ingredient,,淀粉类,,,,,,,,250,g,True,,,,, +201004733,Ingredient,小麦粉,小麦粉,,Ingredient,,淀粉类,,,,,,,,50,g,True,,,,, +201004734,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201004735,Ingredient,煮熟的腊肉,煮熟的腊肉,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201004736,Ingredient,茄子,茄子,,Ingredient,,蔬菜,,,,,,,,1,根,True,,,,, +201004737,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-30,ml,False,,,,, +201004738,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,1-2,g,False,,,,, +201004739,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201004740,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将茄子去皮后切成片,将腊肉切成片,备用,1.0,切,"刀,案板", +201004741,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,依次向盆中加入250g米粉、50g面粉和1个鸡蛋,2.0,混合,盆, +201004742,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,边用筷子搅拌,边加入清水,使米粉、面粉、鸡蛋混合成面糊;当面糊能够附着在茄片、肉片上而不掉落时停止加水,而后将所有茄片和肉片放入面糊中,用面糊充分包裹,3.0,"搅拌,混合,包裹","盆,筷子", +201004743,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,平底锅加入食用油10-30ml,开小火,4.0,加热,平底锅, +201004744,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,用筷子或勺子把裹了面糊的茄片、肉片放入锅中,先煎至两面金黄,再煎3-6分钟(煎的过程中,食用油会变少,可再添加食用油),5.0,煎,"平底锅,筷子,勺子",3-6分钟 +201004745,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,撒盐,翻炒均匀,起锅装盘,6.0,"撒,翻炒,装盘",锅铲, +201004746,Recipe,西红柿鸡蛋挂面,西红柿鸡蛋挂面,,Recipe,"[{'term': 'tomato鸡蛋挂面', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '番茄鸡蛋挂面', 'language': 'zh', 'language_code': 'zh-CN'}]",主食,2.0,,5分钟,15分钟,1人,"多次加水煮面更劲道,蛋液加黑胡椒增香,熬臊子加白胡椒粉提味",dishes\staple\西红柿鸡蛋挂面\西红柿鸡蛋挂面.md,,,,,,,, +201004747,Ingredient,挂面,挂面,,Ingredient,,淀粉类,,,,,,,,75,克,True,,,,, +201004748,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,200,克,True,,,,, +201004749,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1.5,个,True,,,,, +201004750,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,个,False,,,,, +201004751,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,根,False,,,,, +201004752,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201004753,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,6.5,克,False,,,,, +201004754,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201004755,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201004756,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201004757,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201004758,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201004759,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201004760,Ingredient,黑胡椒,黑胡椒,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201004761,Ingredient,白胡椒粉,白胡椒粉,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201004762,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,小葱洗净并切成葱花;西红柿切块;青椒切成菱形块;鸡蛋打入碗中打散,如腥味重可加2g白醋去腥。,1.0,切,"刀,案板,碗",3分钟 +201004763,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,起锅烧热,倒入15-20g食用油,油温七成热时倒入蛋液快速划散,炒至凝固后盛出备用,留底油。,2.0,炒,"炒锅,锅铲",2分钟 +201004764,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中留底油,下葱白、蒜末炒香,加入西红柿块和青椒翻炒出汁,加入酱油5g、白砂糖2g,翻炒十几秒后加一碗清水,煮沸后加入炒好的鸡蛋、蚝油5g(或鸡精2g)提鲜,中小火收汁,期间搅拌防粘,收汁完成后撒葱花、淋香油,制成西红柿鸡蛋臊子。,3.0,"炒,煮,收汁","炒锅,锅铲",7分钟 +201004765,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅中加清水500ml煮沸,下挂面,煮软后加入100ml清水,再次煮沸后再加100ml清水,重复2-3次,面条两侧呈透明状即熟,捞出放入臊子碗中拌匀即可。,4.0,煮,"锅,筷子",6分钟 +201004766,Recipe,豆角焖面,豆角焖面,,Recipe,"[{'term': '豆角闷面', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '豆角braised面', 'language': 'zh', 'language_code': 'zh-CN'}]",主食,3.0,,约10分钟,约15分钟,1人,"懒人美食,操作简单,面条粗细可选:毛细/细/二细/三细/韭叶/大宽",dishes\staple\豆角焖面\豆角焖面.md,,,,,,,, +201004767,Ingredient,鲜面条,鲜面条,,Ingredient,,淀粉类,,,,,,,,300,g,True,,,,, +201004768,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201004769,Ingredient,豆角,豆角,,Ingredient,,蔬菜,,,,,,,,150,g,True,,,,, +201004770,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201004771,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-18,ml,False,,,,, +201004772,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201004773,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201004774,Ingredient,耗油,耗油,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201004775,Ingredient,十三香,十三香,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201004776,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201004777,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201004778,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201004779,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,5,g,False,,,,, +201004780,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201004781,Ingredient,热水,热水,,Ingredient,,其他,,,,,,,,150,ml,False,,,,, +201004782,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将豆角切成5-6 cm的小段。,1.0,切,"菜刀,砧板", +201004783,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将葱切成1-2 cm小段;姜切成1 mm×1 mm×3 cm长条;蒜拍碎后切成1 mm粒度;五花肉切成2 mm厚片。,2.0,切,"菜刀,砧板", +201004784,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅烧热至手放锅上方10 cm处明显烤手,倒入10-18 ml食用油,摇晃锅使油挂满锅底三分之二。,3.0,"加热,倒油",炒锅, +201004785,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,放入全部姜和葱段,爆香5秒。,4.0,炒,"炒锅,锅铲",5秒 +201004786,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入全部肉片,静置5秒后翻炒,使肉片均匀裹油。,5.0,炒,"炒锅,锅铲",5秒+ +201004787,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,肉片全部变色后,沿锅边淋入生抽,翻炒均匀。,6.0,"炒,淋","炒锅,锅铲", +201004788,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,依次加入盐、老抽、耗油、十三香、鸡精及全部豆角,翻炒2分钟。,7.0,炒,"炒锅,锅铲",2分钟 +201004789,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入150 ml热水,水开后舀出一半菜汤备用。,8.0,煮,"炒锅,勺子", +201004790,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将面条平铺在菜上,盖盖中火焖5分钟。,9.0,焖,"炒锅,锅盖",5分钟 +201004791,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,打开锅盖,将之前舀出的菜汤每次一勺均匀撒在面条上,再盖盖中火焖3分钟。,10.0,焖,"炒锅,锅盖,勺子",3分钟 +201004792,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,开盖后撒入全部蒜和味精,用筷子翻炒均匀即可关火。,11.0,炒,"炒锅,筷子", +201004793,Recipe,酱拌荞麦面,酱拌荞麦面,,Recipe,,主食,2.0,,5分钟,8-10分钟,1人份,"冰镇口感更佳,可替换配料虾仁肉沫,可替换酱料花生酱芝麻酱,热量与普通面条相近",dishes\staple\酱拌荞麦面\酱拌荞麦面.md,,,,,,,, +201004794,Ingredient,荞麦面,荞麦面,,Ingredient,,淀粉类,,,,,,,,100,g,True,,,,, +201004795,Ingredient,黄瓜,黄瓜,,Ingredient,,蔬菜,,,,,,,,0.5,根,True,,,,, +201004796,Ingredient,红萝卜,红萝卜,,Ingredient,,蔬菜,,,,,,,,0.5,根,True,,,,, +201004797,Ingredient,老干妈,老干妈,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201004798,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,荞麦面下冷水煮熟,8-10分钟后捞出沥干备用,1.0,煮,锅,8-10分钟 +201004799,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,黄瓜、萝卜切成小条,2.0,切,"刀,案板",约2分钟 +201004800,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将荞麦面、黄瓜、萝卜放入盘子,放上老干妈,搅拌,3.0,搅拌,"盘子,筷子",约1分钟 +201004801,Recipe,韩式拌饭,韩式拌饭,,Recipe,,主食,3.0,韩餐,15分钟,10分钟,1人份,"简单快手,外观可升级,砂锅替代,甜辣口味,减肥可用无糖雪碧",dishes\staple\韩式拌饭\韩式拌饭.md,,,,,,,, +201004802,Ingredient,米饭,米饭,,Ingredient,,淀粉类,,,,,,,,400,g,True,,,,, +201004803,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201004804,Ingredient,火锅牛肉卷,火锅牛肉卷,,Ingredient,,蛋白质,,,,,,,,60,g,True,,,,, +201004805,Ingredient,豆芽,豆芽,,Ingredient,,蔬菜,,,,,,,,80,g,True,,,,, +201004806,Ingredient,蘑菇,蘑菇,,Ingredient,,蔬菜,,,,,,,,50,g,True,,,,, +201004807,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,0.25,根,True,,,,, +201004808,Ingredient,西葫芦,西葫芦,,Ingredient,,蔬菜,,,,,,,,50,g,True,,,,, +201004809,Ingredient,韩式辣酱,韩式辣酱,,Ingredient,,调料,,,,,,,,25,ml,False,,,,, +201004810,Ingredient,雪碧,雪碧,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201004811,Ingredient,芝麻,芝麻,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201004812,Ingredient,芝麻油,芝麻油,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201004813,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201004814,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,蔬菜清洗、切丝,放锅中翻炒至食材变软后盛出备用。,1.0,"清洗,切,炒","刀,案板,炒锅,锅铲",5分钟 +201004815,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中加水,水沸腾后焯牛肉卷,煮熟约3分钟捞出。,2.0,煮,"锅,筷子",3分钟 +201004816,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,煎溏心蛋备用。,3.0,煎,"平底锅,锅铲",2分钟 +201004817,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将米饭放在碗中,倒扣在大碗中央。,4.0,摆盘,碗,1分钟 +201004818,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将炒好的蔬菜和牛肉卷依次绕圈摆放在米饭上,把煎蛋放在中央。,5.0,摆盘,"碗,筷子",2分钟 +201004819,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,调制酱汁:10ml韩式辣酱 + 5ml生抽 + 20ml雪碧 + 10g芝麻 + 5ml芝麻油,搅拌均匀,可按口味再加生抽和盐。,6.0,搅拌,"小碗,勺子",1分钟 +201004820,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将调好的酱汁均匀淋在摆好盘的食材上即可。,7.0,淋,勺子,30秒 +201004821,Recipe,鲣鱼海苔玉米饭,鲣鱼海苔玉米饭,,Recipe,,主食,2.0,日式,3 分钟,40 分钟,1 人份,"米家小饭煲,东北米水没过米 3 毫米,不推荐使用高压锅",dishes\staple\鲣鱼海苔玉米饭\鲣鱼海苔玉米饭.md,,,,,,,, +201004822,Ingredient,东北米,东北米,,Ingredient,,淀粉类,,,,,,,,1 人份,杯,True,,,,, +201004823,Ingredient,鲣鱼海苔碎,鲣鱼海苔碎,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201004824,Ingredient,玉米粒,玉米粒,,Ingredient,,蔬菜,,,,,,,,80,克,True,,,,, +201004825,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,盛好米饭,放入玉米粒拌好,1.0,拌,"碗,筷子",1 分钟 +201004826,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,放入鲣鱼海苔碎,2.0,拌,"碗,筷子",1 分钟 +201004827,Recipe,凉拌油麦菜,凉拌油麦菜,,Recipe,,素菜,1.0,,5分钟,2分钟,1-2人,"芝麻酱可用花生酱代替,芝麻酱需与油麦菜混合均匀更美味",dishes\vegetable_dish\凉拌油麦菜.md,,,,,,,, +201004828,Ingredient,油麦菜,油麦菜,,Ingredient,,蔬菜,,,,,,,,200,克,True,,,,, +201004829,Ingredient,芝麻酱,芝麻酱,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201004830,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201004831,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201004832,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201004833,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,克,False,,,,, +201004834,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201004835,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,2,头,False,,,,, +201004836,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201004837,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,蒜拍碎切末,1.0,切,"刀,案板",1分钟 +201004838,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,醋、酱油、芝麻酱、香油、糖、蚝油、蒜末放到碗里搅拌均匀,2.0,搅拌,"碗,筷子",1分钟 +201004839,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,油麦菜切段,每段不超过4cm,3.0,切,"刀,案板",2分钟 +201004840,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,油麦菜放到一个大点的盆里,倒入上述碗中酱料,充分搅拌均匀,4.0,搅拌,"盆,筷子",1分钟 +201004841,Recipe,凉拌豆腐,凉拌豆腐,,Recipe,"[{'term': '凉拌tofu', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '凉拌老豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '凉拌嫩豆腐', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,2.0,,5分钟,2分钟,1人,"选用北豆腐或老豆腐口感更佳,可省略醋和辣椒油以清淡口味,酱汁比例可调",dishes\vegetable_dish\凉拌豆腐.md,,,,,,,, +201004842,Ingredient,豆腐,豆腐,,Ingredient,"[{'term': '水豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '嫩豆腐', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,250,g,True,,,,, +201004843,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,10,g,False,,,,, +201004844,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,2,瓣,False,,,,, +201004845,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201004846,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004847,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004848,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,g,False,,,,, +201004849,Ingredient,辣椒油,辣椒油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004850,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将豆腐切成2 cm见方的小块,备用。,1.0,切,"刀,案板", +201004851,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中加入500 ml饮用水,大火烧开。,2.0,煮,锅, +201004852,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放入豆腐块,煮1-2分钟,以去除豆腥味并使豆腐口感更紧实。,3.0,煮,锅,1-2分钟 +201004853,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将煮好的豆腐块捞出,沥干水分,放入碗中,备用。,4.0,"捞,沥","漏勺,碗", +201004854,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将小葱洗净,切成葱花,备用。,5.0,"洗,切","刀,案板", +201004855,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将大蒜去皮,切成蒜末,备用。,6.0,"去皮,切","刀,案板", +201004856,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,在一个干净的小碗中,加入15 ml生抽,5 ml香油,5 ml醋(可选),2 g白糖(可选)。,7.0,混合,小碗, +201004857,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入切好的大蒜末。,8.0,混合,小碗, +201004858,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,搅拌均匀,使白糖充分溶解,酱汁混合均匀。,9.0,搅拌,"筷子,小碗", +201004859,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将制作好的酱汁均匀淋在豆腐块上。,10.0,淋,碗, +201004860,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,撒上切好的小葱花。,11.0,撒,碗, +201004861,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,根据个人喜好,淋上5 ml辣椒油(可选)。,12.0,淋,碗, +201004862,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,用筷子或勺子轻轻拌匀,即可食用。,13.0,拌,"筷子,勺子,碗", +201004863,Recipe,凉拌金针菇,凉拌金针菇,,Recipe,,素菜,2.0,,5分钟,1-2分钟,1人,"焯水时间不宜过长,酱汁比例可调,可省略辣椒油",dishes\vegetable_dish\凉拌金针菇.md,,,,,,,, +201004864,Ingredient,金针菇,金针菇,,Ingredient,,蔬菜,,,,,,,,150,g,True,,,,, +201004865,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,5,g,False,,,,, +201004866,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,2,瓣,False,,,,, +201004867,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201004868,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201004869,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,g,False,,,,, +201004870,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004871,Ingredient,辣椒油,辣椒油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201004872,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将金针菇根部切除,用清水冲洗干净,备用。,1.0,"切,洗",刀, +201004873,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将小葱洗净,切成葱花,备用。,2.0,"洗,切",刀, +201004874,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将大蒜去皮,切成蒜末,备用。,3.0,切,刀, +201004875,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅中加入1000 ml饮用水,大火烧开。,4.0,煮,锅, +201004876,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,放入金针菇,煮1-2分钟,至金针菇变软。,5.0,煮,锅,1-2分钟 +201004877,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将煮好的金针菇捞出,沥干水分,放入一个较大的碗中,备用。,6.0,"捞,沥","漏勺,碗", +201004878,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,在另一个干净的小碗中,加入15 ml生抽、10 ml醋、3 g白糖(可选)、5 ml香油(可选)。,7.0,混合,碗, +201004879,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入切好的大蒜末。,8.0,混合,碗, +201004880,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,搅拌均匀,使白糖充分溶解,酱汁混合均匀。,9.0,搅拌,筷子, +201004881,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将制作好的酱汁均匀淋在金针菇上。,10.0,淋,碗, +201004882,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,撒上切好的小葱花。,11.0,撒,碗, +201004883,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,根据个人喜好,淋上5 ml辣椒油(可选)。,12.0,淋,碗, +201004884,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,用筷子轻轻拌匀,即可食用。,13.0,拌,筷子, +201004885,Recipe,凉拌黄瓜,凉拌黄瓜,,Recipe,,素菜,1.0,,15分钟(腌制),5分钟(处理+拌制),1人/份,"黄瓜去皮口感更好,冷藏后食用需保鲜膜包紧并在8小时内吃完,黄瓜端头苦味需切除确认",dishes\vegetable_dish\凉拌黄瓜.md,,,,,,,, +201004886,Ingredient,黄瓜,黄瓜,,Ingredient,,蔬菜,,,,,,,,200,克,True,,,,, +201004887,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,11.5,毫升,False,,,,, +201004888,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,7.5,毫升,False,,,,, +201004889,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,3,瓣,False,,,,, +201004890,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,0.6,克,False,,,,, +201004891,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,7,毫升,False,,,,, +201004892,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201004893,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,用菜刀将黄瓜拍扁,再剁成长3厘米的碎块,1.0,切,菜刀, +201004894,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将碎黄瓜装入碗中,2.0,,碗, +201004895,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将蒜拍碎切成碎末,3.0,切,菜刀, +201004896,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将醋、酱油、盐、蚝油和蒜依次倒入碗中搅拌均匀并腌制15分钟,4.0,"搅拌,腌制","碗,筷子",15分钟 +201004897,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将香油倒入碗中并均匀搅拌,5.0,搅拌,"碗,筷子", +201004898,Recipe,地三鲜,地三鲜,,Recipe,,素菜,3.0,东北菜,约10分钟,约8分钟,2-4人,,dishes\vegetable_dish\地三鲜.md,,,,,,,, +201004899,Ingredient,茄子,茄子,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201004900,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,150,g,True,,,,, +201004901,Ingredient,尖椒,尖椒,,Ingredient,,蔬菜,,,,,,,,3.5,个,True,,,,, +201004902,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,3,g,False,,,,, +201004903,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201004904,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201004905,Ingredient,豆瓣酱,豆瓣酱,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201004906,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201004907,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,8,g,False,,,,, +201004908,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201004909,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,20,g,False,,,,, +201004910,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,40,ml,False,,,,, +201004911,Ingredient,水,水,,Ingredient,,其他,,,,,,,,200,ml,False,,,,, +201004912,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,土豆洗净、去皮。茄子、尖椒洗净。,1.0,"洗,去皮","刀,案板", +201004913,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱3g切0.5cm小段。蒜10g剁碎。姜10g切沫。,2.0,切,"刀,案板", +201004914,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,茄子、土豆、尖椒均切成15g的小块。,3.0,切,"刀,案板", +201004915,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,加入25ml油。,4.0,加热,炒锅, +201004916,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入土豆,煎炸大约3分钟,待其到大约8分熟,以显示金黄色为准。,5.0,"炸,煎","炒锅,锅铲",3分钟 +201004917,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,捞出土豆,留下油。,6.0,捞,锅铲, +201004918,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入茄子,煎炸大约40秒,待其到大约7分熟,以显示金黄色为准。,7.0,"炸,煎","炒锅,锅铲",40秒 +201004919,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,如果锅内已经没有流动的油,可以考虑补充15ml油。,8.0,加,炒锅, +201004920,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,放入葱3g、姜10g。,9.0,炒,锅铲, +201004921,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,放入豆瓣酱20ml。,10.0,炒,锅铲, +201004922,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,放入生抽10ml、盐8g、糖10g。,11.0,炒,锅铲, +201004923,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,放入之前处理的土豆和尖椒。,12.0,炒,锅铲, +201004924,CookingStep,步骤13,步骤13,,CookingStep,,,,,,,,,,,,,翻炒1分钟。,13.0,炒,锅铲,1分钟 +201004925,CookingStep,步骤14,步骤14,,CookingStep,,,,,,,,,,,,,放入蒜10g。,14.0,炒,锅铲, +201004926,CookingStep,步骤15,步骤15,,CookingStep,,,,,,,,,,,,,加入200ml水和20g淀粉。,15.0,"加,勾芡",锅铲, +201004927,CookingStep,步骤16,步骤16,,CookingStep,,,,,,,,,,,,,待水开后,汤减少一半时,关火盛盘。,16.0,煮,锅铲,约2分钟 +201004928,Recipe,松仁玉米,松仁玉米,,Recipe,,素菜,2.0,,5分钟(切胡萝卜丁、焯水准备),5分钟(炒制全过程),1人份,"松仁可提前小火干炒至微金黄更香脆,罐头玉米需先沥干水分避免出水过多,炒制火候不宜过大防糊锅",dishes\vegetable_dish\松仁玉米.md,,,,,,,, +201004929,Ingredient,玉米粒,玉米粒,,Ingredient,,蔬菜,,,,,,,,200,g,True,,,,, +201004930,Ingredient,熟松子仁,熟松子仁,,Ingredient,,其他,,,,,,,,30,g,True,,,,, +201004931,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,50,g,False,,,,, +201004932,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201004933,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201004934,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201004935,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,5,g,False,,,,, +201004936,Ingredient,水,水,,Ingredient,,其他,,,,,,,,20,ml,False,,,,, +201004937,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,玉米粒和胡萝卜丁提前焯水1分钟,捞出沥干备用,1.0,焯水,"锅,漏勺",1分钟 +201004938,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,热锅凉油,放入胡萝卜丁略炒,再加入玉米粒翻炒,2.0,炒,"炒锅,锅铲",30秒 +201004939,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入白砂糖和盐,炒匀,3.0,炒,锅铲,20秒 +201004940,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,混合水与淀粉成水淀粉,倒入锅中快速翻炒使汤汁略稠,4.0,炒,"锅铲,小碗",20秒 +201004941,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入熟松仁翻炒均匀,5.0,炒,锅铲,15秒 +201004942,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,出锅装盘,6.0,装盘,盘子,5秒 +201004943,Recipe,水油焖蔬菜,水油焖蔬菜,,Recipe,"[{'term': '水oil-braised蔬菜', 'language': 'en', 'language_code': 'en-US'}, {'term': '水油braised蔬菜', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '水油闷蔬菜', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,2.0,,5分钟,约3分钟,1-2人,"先少放盐出锅前尝味,可用鸡汤骨头汤替代水,焖制时间不宜过长",dishes\vegetable_dish\水油焖蔬菜.md,,,,,,,, +201004944,Ingredient,叶菜类蔬菜,叶菜类蔬菜,,Ingredient,,蔬菜,,,,,,,,300-500,g,True,,,,, +201004945,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,2,ml,False,,,,, +201004946,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004947,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,3,ml,False,,,,, +201004948,Ingredient,水,水,,Ingredient,,其他,,,,,,,,150,ml,False,,,,, +201004949,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,洗净蔬菜,1.0,洗,盆,2分钟 +201004950,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅中加入150ml水,并烧开,2.0,煮,锅,1分钟 +201004951,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入3g盐,3.0,调味,锅,5秒 +201004952,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,(可选)加入3ml蚝油,4.0,调味,锅,5秒 +201004953,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入2ml食用油,5.0,调味,锅,5秒 +201004954,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,下菜,翻拌一下,然后盖上锅盖焖1分钟,6.0,"焖,翻拌","锅,锅铲",1分钟 +201004955,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,盛盘,7.0,装盘,锅铲,10秒 +201004956,Recipe,油醋爆蛋,油醋爆蛋,,Recipe,,素菜,2.0,湘菜,5分钟,5分钟,2人,"老恒和酿造香醋零添加口味最佳,醋香是灵魂",dishes\vegetable_dish\油醋爆蛋.md,,,,,,,, +201004957,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,4,个,True,,,,, +201004958,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,2,个,False,,,,, +201004959,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,根,False,,,,, +201004960,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,3,瓣,False,,,,, +201004961,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201004962,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201004963,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201004964,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,毫升,False,,,,, +201004965,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201004966,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,克,False,,,,, +201004967,Ingredient,水,水,,Ingredient,,其他,,,,,,,,20,毫升,False,,,,, +201004968,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡蛋不需打散,直接打入碗中备用,1.0,准备,碗,30秒 +201004969,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,香葱切3cm长小段即可,2.0,切,"刀,案板",30秒 +201004970,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,蒜瓣和小米辣放入打蒜器,打成沫,3.0,打碎,打蒜器,30秒 +201004971,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将香醋、生抽、蚝油、白糖、水加入小碗,搅拌均匀作为糖醋料汁,4.0,搅拌,"小碗,筷子",30秒 +201004972,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,油热倒入鸡蛋,等鸡蛋凝固之后铲成大块,倒入蒜沫、小米辣沫、倒入糖醋料汁,5.0,"煎,炒","炒锅,锅铲",2-3分钟 +201004973,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,大火收汁、快出锅时加入葱段即可,6.0,炒,锅铲,30秒 +201004974,Recipe,清炒花菜,清炒花菜,,Recipe,"[{'term': '炒制花菜', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'stir-fried花菜', 'language': 'en', 'language_code': 'en-US'}]",素菜,2.0,,5分钟,10分钟,2人,"焯水缩短炒制时间,炒制时间可调软硬",dishes\vegetable_dish\清炒花菜.md,,,,,,,, +201004975,Ingredient,花菜,花菜,,Ingredient,,蔬菜,,,,,,,,300,g,True,,,,, +201004976,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,2.5,瓣,False,,,,, +201004977,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201004978,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201004979,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,50,ml,False,,,,, +201004980,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将花菜洗净,用刀或手掰成小朵,粗茎部分可以切片,备用。,1.0,切,"刀,案板", +201004981,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将大蒜去皮,切成蒜片,备用。,2.0,切,"刀,案板", +201004982,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中加入1000 ml饮用水,大火烧开。,3.0,煮,锅, +201004983,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,放入花菜朵,煮2-3分钟,至花菜颜色变浅,口感稍微软化。,4.0,煮,锅,2-3分钟 +201004984,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将煮好的花菜捞出,沥干水分,备用。,5.0,沥水,漏勺, +201004985,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,热锅,加入15 ml食用油,大火烧热。,6.0,炒,炒锅, +201004986,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入蒜片,快速煸炒出香味。,7.0,炒,"炒锅,锅铲", +201004987,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入焯好水的花菜朵,转中大火,快速翻炒约2分钟,使花菜均匀受热。,8.0,炒,"炒锅,锅铲",2分钟 +201004988,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入3 g盐,继续翻炒均匀。,9.0,炒,锅铲, +201004989,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,沿锅边淋入50 ml饮用水,盖上锅盖,焖1分钟,帮助花菜完全熟透入味。,10.0,焖,"炒锅,锅盖",1分钟 +201004990,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,开盖,快速翻炒均匀,即可出锅。,11.0,炒,锅铲, +201004991,Recipe,清蒸南瓜,清蒸南瓜,,Recipe,"[{'term': '清清蒸南瓜', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '清steamed南瓜', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,1.0,,5分钟,15-20分钟,1-2人,"老南瓜更甜更面,南瓜皮可保留增加营养,蒸制时间视南瓜厚度与品种调整,用筷子测试是否熟透",dishes\vegetable_dish\清蒸南瓜.md,,,,,,,, +201004992,Ingredient,南瓜,南瓜,,Ingredient,,蔬菜,,,,,,,,300,克,True,,,,, +201004993,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,1000,毫升,False,,,,, +201004994,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将南瓜外皮洗净,去除瓜瓤和籽。,1.0,切,刀, +201004995,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将南瓜切成厚度大约2 cm的片,备用。,2.0,切,"刀,案板", +201004996,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,在蒸锅的锅中加入1000 ml饮用水。,3.0,加水,蒸锅, +201004997,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将切好的南瓜片均匀摆放在盘中。,4.0,摆盘,盘, +201004998,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,待蒸锅中的水烧开后,将装有南瓜的盘子放入蒸锅中。,5.0,蒸,"蒸锅,盘", +201004999,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,盖上锅盖,保持大火蒸15-20分钟,直至南瓜变软,可以用筷子轻松穿透。,6.0,蒸,"蒸锅,锅盖,筷子",15-20分钟 +201005000,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,关火,小心取出盘子。,7.0,关火,"蒸锅,盘", +201005001,Recipe,炒茄子,炒茄子,,Recipe,"[{'term': '炒eggplant', 'language': 'en', 'language_code': 'en-US'}, {'term': '炒紫茄子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '炒青茄子', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,3.0,,约5分钟,约3分钟,1-2人,"全程大火,不可加水,酱油自带咸味无需加盐,油宁多勿少,可酌情减少酱油用量(若加虾皮)",dishes\vegetable_dish\炒茄子.md,,,,,,,, +201005002,Ingredient,茄子,茄子,,Ingredient,,蔬菜,,,,,,,,1.8,个,True,,,,, +201005003,Ingredient,八角,八角,,Ingredient,"[{'term': '大料', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茴香', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,个,False,,,,, +201005004,Ingredient,虾皮,虾皮,,Ingredient,,蛋白质,,,,,,,,正常男子手抓半把,,False,,,,, +201005005,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,2,颗,False,,,,, +201005006,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,40,ml,False,,,,, +201005007,Ingredient,菜籽油或花生油,菜籽油或花生油,,Ingredient,,调料,,,,,,,,没过锅底的两倍,,False,,,,, +201005008,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将茄子洗净,一刀分为两段(竖切)。每段的茄子切菱形块,将切好的茄子放入碗中待命。,1.0,切,"刀,案板,碗", +201005009,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将香葱洗净,并切成葱花放到案板上待命。,2.0,切,"刀,案板", +201005010,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,切好八角,放到案板上待命。,3.0,切,"刀,案板", +201005011,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,开火热锅,直至锅内没有水。,4.0,加热,炒锅, +201005012,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,往锅内倒食用油,没过锅底的两倍(油可以多加,但不可少加)。,5.0,倒油,炒锅, +201005013,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,热油约6成熟,放入八角、虾皮、香葱这三种可选性材料。,6.0,炸香,"炒锅,锅铲", +201005014,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,如果没有八角等可选材料,热油至9成熟。,7.0,加热,炒锅, +201005015,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,待锅内的油到9成熟,将碗中的茄子倒入锅内用锅铲进行翻炒。,8.0,炒,"炒锅,锅铲", +201005016,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,翻炒约40秒,将锅铲悬空,与锅平行,把酱油倒入锅铲内。一人约2.5锅铲(酱油可以少加,但不可多加,会咸)。,9.0,"炒,调味",锅铲,40秒 +201005017,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,继续进行翻炒。,10.0,炒,锅铲, +201005018,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,等到锅内所有茄子变色且变软时捞出。,11.0,炒,锅铲, +201005019,Recipe,炒青菜,炒青菜,,Recipe,,素菜,2.0,,约2分钟,约4分钟,1人,加入白糖让青菜颜色更绿,dishes\vegetable_dish\炒青菜.md,,,,,,,, +201005020,Ingredient,青菜,青菜,,Ingredient,,蔬菜,,,,,,,,100,g,True,,,,, +201005021,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201005022,Ingredient,食盐,食盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005023,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,70,ml,False,,,,, +201005024,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201005025,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,青菜掰成小瓣,用清水洗净,备用。,1.0,"切,洗","刀,盆",约1分钟 +201005026,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,中火或大火热锅后,锅内放入10-15ml食用油,再等待30秒让油温升高。,2.0,炒,炒锅,30秒 +201005027,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将准备好的青菜倒入锅中,翻炒至青菜变软(约1分钟)。,3.0,炒,锅铲,1分钟 +201005028,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入计算好的清水,水位应当完全浸润或即将没过青菜,加入食盐,继续翻炒约1分钟。,4.0,炒,锅铲,1分钟 +201005029,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,最后加入白糖小火加热2分钟,加热时盖上锅盖。,5.0,"焖,炒","炒锅,锅盖",2分钟 +201005030,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,盛盘。,6.0,,, +201005031,Recipe,素炒豆角,素炒豆角,,Recipe,,素菜,2.0,,约10分钟,约11-12分钟,2人份,切豆角需要一定刀工,不会的可用剪刀,dishes\vegetable_dish\素炒豆角.md,,,,,,,, +201005032,Ingredient,豆角,豆角,,Ingredient,,蔬菜,,,,,,,,250,g,True,,,,, +201005033,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,2,个,False,,,,, +201005034,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,3,圈,False,,,,, +201005035,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,2,颗,False,,,,, +201005036,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,6,ml,False,,,,, +201005037,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,ml,False,,,,, +201005038,Ingredient,耗油,耗油,,Ingredient,,调料,,,,,,,,6,ml,False,,,,, +201005039,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,6,g,False,,,,, +201005040,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,葱切花,蒜切沫,备用。,1.0,切,"刀,案板", +201005041,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,生抽、老抽、耗油、盐混合调料汁,备用。,2.0,混合,碗或盆, +201005042,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,小米椒切圈,备用。,3.0,切,"刀,案板", +201005043,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,豆角去筋,45°斜切4-10cm小段,备用。,4.0,切,"刀,案板", +201005044,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,起锅烧油(10ml-15ml),冒烟后放入葱、小米椒,翻炒至闻到香味。,5.0,炒,"炒锅,锅铲", +201005045,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入豆角,翻炒30秒。,6.0,炒,锅铲,30秒 +201005046,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入料汁,开大火翻炒2分钟。,7.0,炒,锅铲,2分钟 +201005047,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入150ml水,转中小火,盖上锅盖焖制8-10分钟。,8.0,焖,"炒锅,锅盖",8-10分钟 +201005048,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入蒜切沫,出锅。,9.0,炒,锅铲, +201005049,Recipe,红烧茄子,红烧茄子,,Recipe,"[{'term': '红烧紫茄子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧青茄子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧eggplant', 'language': 'en', 'language_code': 'en-US'}, {'term': 'braised茄子', 'language': 'en', 'language_code': 'en-US'}]",素菜,4.0,,约15分钟,约20分钟,2人份,"面糊顺序不可乱,炸茄子油温控制,收汁至粘稠",dishes\vegetable_dish\红烧茄子.md,,,,,,,, +201005050,Ingredient,青茄子,青茄子,,Ingredient,"[{'term': '茄子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '紫茄子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '圆茄', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,0.7,个,True,,,,, +201005051,Ingredient,青辣椒,青辣椒,,Ingredient,,蔬菜,,,,,,,,0.5,个,False,,,,, +201005052,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,0.3,个,False,,,,, +201005053,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,个,False,,,,, +201005054,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,0.5,颗,False,,,,, +201005055,Ingredient,大蒜,大蒜,,Ingredient,,蔬菜,,,,,,,,3,瓣,False,,,,, +201005056,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,False,,,,, +201005057,Ingredient,面粉,面粉,,Ingredient,,淀粉类,,,,,,,,105,克,False,,,,, +201005058,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,26.25,克,False,,,,, +201005059,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5.25,克,False,,,,, +201005060,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201005061,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,505,毫升,False,,,,, +201005062,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,青茄子、青辣椒、西红柿、洋葱、大葱洗净。,1.0,清洗,水盆,2-3分钟 +201005063,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,大葱切5毫米宽的葱花,大蒜扒皮并拍碎,西红柿切6立方厘米的块,青辣椒、洋葱切5g的块。,2.0,切,"刀,案板",5分钟 +201005064,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,茄子切菱形块:先切2公分厚的片,再切成2公分的条,最后斜刀切块。,3.0,切,"刀,案板",3-4分钟 +201005065,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将面粉倒入盆中,依次加入少量水,搅拌均匀,呈粘稠糊状。,4.0,搅拌,"盆,筷子或打蛋器",1分钟 +201005066,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入淀粉,加入30克水,搅拌均匀。,5.0,搅拌,"盆,筷子或打蛋器",30秒 +201005067,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将鸡蛋打到盆中,加入5.25克盐,搅拌均匀。,6.0,搅拌,"盆,筷子或打蛋器",30秒 +201005068,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将茄块倒入面糊中,搅拌使茄块的每一面都能沾上面糊。,7.0,裹浆,"盆,筷子",1分钟 +201005069,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,开大火,热锅,加入500毫升的油,当能看到锅里的油冒出一丝烟时,调至小火,将茄块用筷子夹入到油锅,待所有的茄块下锅之后,调至中火,直到茄块变金黄色时捞出,将油倒出。,8.0,炸,"炒锅,筷子,漏勺",5-7分钟 +201005070,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入5毫升油,放入大蒜、葱花,翻炒15秒,放入青辣椒块翻炒30秒,放入西红柿翻炒30秒。,9.0,炒,"炒锅,锅铲",1分15秒 +201005071,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,放入炸好的茄块,加水面高度为锅内食材的0.8倍。,10.0,"加水,混合","炒锅,锅铲",30秒 +201005072,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,放入酱油和3克盐。,11.0,调味,锅铲,10秒 +201005073,CookingStep,步骤12,步骤12,,CookingStep,,,,,,,,,,,,,等待,直到汤汁呈粘稠状(水位大概为剩余食材高度的0.2-0.3倍),开盖,盛出菜,关火。,12.0,"收汁,出锅","锅铲,盘子",3-5分钟 +201005074,Recipe,脆皮豆腐,脆皮豆腐,,Recipe,"[{'term': '脆皮老豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '脆皮嫩豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '脆皮tofu', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,3.0,,约10分钟,约10分钟,1人,,dishes\vegetable_dish\脆皮豆腐.md,,,,,,,, +201005075,Ingredient,老豆腐,老豆腐,,Ingredient,,蛋白质,,,,,,,,1,块,True,,,,, +201005076,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201005077,Ingredient,玉米淀粉,玉米淀粉,,Ingredient,,淀粉类,,,,,,,,50,g,False,,,,, +201005078,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,g,False,,,,, +201005079,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201005080,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201005081,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,g,False,,,,, +201005082,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,200,ml,False,,,,, +201005083,Ingredient,食用油,食用油,,Ingredient,,其他,,,,,,,,18,ml,False,,,,, +201005084,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡蛋搅拌形成蛋液放置备用,1.0,搅拌,"碗,筷子",1分钟 +201005085,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,配置酱料:20 g 生抽+10 g 蚝油+5 g 老抽+10 g 白糖+10 g 玉米淀粉+200 ml 清水,搅拌均匀,2.0,搅拌,"碗,筷子",1分钟 +201005086,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,老豆腐切片,每块豆腐切5片,厚度约1.2 cm,3.0,切,"刀,案板",2分钟 +201005087,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,玉米淀粉倒入盘中,将老豆腐片先粘上淀粉,再粘上蛋液,放置一旁备用,4.0,裹粉,"盘,筷子",3分钟 +201005088,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅,倒入18 ml食用油,等待10秒让油温升高,5.0,热锅,平底锅,10秒 +201005089,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将裹好蛋液的老豆腐片均匀放入锅中,小火煎至一面金黄后翻面,6.0,煎,"平底锅,锅铲",3-4分钟 +201005090,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,待两面均煎至金黄后,倒入调好的酱料,让每块豆腐都裹满酱汁,大火煮3分钟至酱汁浓稠,7.0,"煮,收汁","平底锅,锅铲",3分钟 +201005091,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,关火,出锅装盘,8.0,关火,锅铲,10秒 +201005092,Recipe,茄子炖土豆,茄子炖土豆,,Recipe,"[{'term': '茄子炖洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茄子炖马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茄子stewed土豆', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茄子煲土豆', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '紫茄子炖土豆', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'eggplant炖土豆', 'language': 'en', 'language_code': 'en-US'}, {'term': '青茄子炖土豆', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '茄子炖potato', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,3.0,东北菜,约10分钟(洗菜、切菜、拍蒜),约15-20分钟(含翻炒、炖煮),2-3人,"注意锅底干锅时补5毫升水,辣椒需用青辣椒而非辣椒面,蒜最后放提香",dishes\vegetable_dish\茄子炖土豆.md,,,,,,,, +201005093,Ingredient,茄子,茄子,,Ingredient,,蔬菜,,,,,,,,150,克,True,,,,, +201005094,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,150,克,True,,,,, +201005095,Ingredient,肉,肉,,Ingredient,,蛋白质,,,,,,,,180,克,True,,,,, +201005096,Ingredient,青辣椒,青辣椒,,Ingredient,,蔬菜,,,,,,,,50,克,False,,,,, +201005097,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201005098,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201005099,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,3,瓣,False,,,,, +201005100,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,13,毫升,False,,,,, +201005101,Ingredient,水,水,,Ingredient,,其他,,,,,,,,适量,毫升,False,,,,, +201005102,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将茄子、土豆、辣椒洗净,蒜扒皮并拍碎。,1.0,"洗,扒皮,拍碎","刀,案板",2-3分钟 +201005103,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将茄子、土豆切成约6立方厘米的块,辣椒切成5克的小块,肉切成3厘米的丝。,2.0,切,"刀,案板",5-7分钟 +201005104,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,开火,热锅,加入份数*13毫升的油。,3.0,"热锅,倒油","炒锅,量勺",30秒 +201005105,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,当能看到锅里的油冒出一丝烟时,放入辣椒。,4.0,煸炒,锅铲,10-15秒 +201005106,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,煸出辣椒香气后,立刻放入肉,用铲子翻炒30秒。,5.0,炒,锅铲,30秒 +201005107,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,放入土豆,翻炒30秒。,6.0,炒,锅铲,30秒 +201005108,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入茄子,翻炒30秒。,7.0,炒,锅铲,30秒 +201005109,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入酱油和盐,继续翻炒5分钟。,8.0,炒,锅铲,5分钟 +201005110,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入水,水面高度为锅内食材高度的0.9倍,并盖上锅盖。,9.0,"加水,炖煮","锅盖,锅铲",5-7分钟 +201005111,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,等待,直到锅内水的高度剩余食材高度的0.1倍时,开盖,放入蒜,搅拌均匀,关火。,10.0,"炖,搅拌",锅铲,2-3分钟 +201005112,Recipe,葱煎豆腐,葱煎豆腐,,Recipe,"[{'term': '葱煎tofu', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '葱煎嫩豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '葱煎老豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '葱pan-fried豆腐', 'language': 'en', 'language_code': 'en-US'}]",素菜,3.0,,约10分钟,约10分钟,1人/份,,dishes\vegetable_dish\葱煎豆腐.md,,,,,,,, +201005113,Ingredient,白豆腐,白豆腐,,Ingredient,,蛋白质,,,,,,,,0.8,块,True,,,,, +201005114,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,0.67,根,True,,,,, +201005115,Ingredient,青辣椒,青辣椒,,Ingredient,,蔬菜,,,,,,,,0.5,只,True,,,,, +201005116,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201005117,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,1.5,克,False,,,,, +201005118,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,9,毫升,False,,,,, +201005119,Ingredient,水,水,,Ingredient,,其他,,,,,,,,10,毫升,False,,,,, +201005120,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,豆腐洗净,切成约5 mm厚片,置于碟中备用。,1.0,切,"刀,碟子",2-3分钟 +201005121,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱洗净,去根后切成葱花备用。,2.0,切,"刀,案板",1分钟 +201005122,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,青辣椒洗净,切开去籽后切成1 cm×1 cm小块备用。,3.0,切,"刀,案板",1-2分钟 +201005123,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,平底锅加热,倒入9 ml食用油,使油均匀铺满锅底。,4.0,加热,平底锅,30秒 +201005124,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,均匀放入豆腐片,小火煎至一面金黄后翻面继续煎至两面金黄。,5.0,煎,"平底锅,锅铲",3-4分钟 +201005125,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将煎好的豆腐盛出备用。,6.0,盛出,"锅铲,碟子",10秒 +201005126,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,补油至覆盖锅底,倒入辣椒块,大火翻炒并用锅铲碾压3分钟。,7.0,"炒,碾压","锅铲,平底锅",3分钟 +201005127,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入煎好的豆腐,加入盐与鸡精,中火翻炒1分钟后加入10 ml水,大火收汁。,8.0,"炒,收汁","锅铲,平底锅",2分钟 +201005128,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,出锅前撒上葱花,起锅盛盘即可。,9.0,"撒,盛盘","锅铲,盘子",20秒 +201005129,Recipe,蒜蓉西兰花,蒜蓉西兰花,,Recipe,,素菜,2.0,,5分钟,5-6分钟,2人,"焯水时间不宜过长,缩短焯水时间可保留更脆口感",dishes\vegetable_dish\蒜蓉西兰花.md,,,,,,,, +201005130,Ingredient,西兰花,西兰花,,Ingredient,,蔬菜,,,,,,,,200,g,True,,,,, +201005131,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,3,瓣,False,,,,, +201005132,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201005133,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201005134,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,g,False,,,,, +201005135,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201005136,Ingredient,饮用水,饮用水,,Ingredient,,其他,,,,,,,,1030,ml,False,,,,, +201005137,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将西兰花切成小朵,清洗干净。,1.0,"切,清洗","刀,案板,盆",2分钟 +201005138,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将大蒜去皮,切成蒜末,备用。,2.0,切,"刀,案板",1分钟 +201005139,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中加入1000 ml饮用水,大火烧开。,3.0,煮,锅,1分钟 +201005140,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,放入西兰花,保持大火煮2-3分钟,至西兰花颜色变翠绿,口感变软。,4.0,煮,"锅,筷子",2-3分钟 +201005141,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将煮好的西兰花捞出,沥干水分,摆入盘中,备用。,5.0,"沥水,摆盘","漏勺,盘子",30秒 +201005142,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,热锅,加入10 ml食用油。油温升高后,放入大蒜末,小火煸炒出香味。,6.0,炒,"炒锅,锅铲",30秒 +201005143,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入10 ml生抽、5 ml蚝油、2 g白糖,加入30 ml饮用水。,7.0,调味,锅铲,10秒 +201005144,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将锅中汤汁烧开。,8.0,煮,锅铲,20秒 +201005145,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将烧好的蒜蓉汁均匀淋在盘中的西兰花上。,9.0,淋汁,锅铲,10秒 +201005146,Recipe,蒲烧茄子,蒲烧茄子,,Recipe,"[{'term': '蒲烧紫茄子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '蒲烧eggplant', 'language': 'en', 'language_code': 'en-US'}, {'term': '蒲烧青茄子', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,3.0,,约10分钟,约15分钟,1人份,"蒲烧汁可买现成,装盘后撒小葱解腻,日式蒲烧为烤制,本做法更中式,推荐用长茄而非浙茄圆茄",dishes\vegetable_dish\蒲烧茄子.md,,,,,,,, +201005147,Ingredient,茄子,茄子,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201005148,Ingredient,蜂蜜,蜂蜜,,Ingredient,,调料,,,,,,,,20,毫升,False,,,,, +201005149,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201005150,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,40,毫升,False,,,,, +201005151,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,毫升,False,,,,, +201005152,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,20,毫升,False,,,,, +201005153,Ingredient,水,水,,Ingredient,,其他,,,,,,,,100,毫升,False,,,,, +201005154,Ingredient,水淀粉,水淀粉,,Ingredient,,其他,,,,,,,,适量,,False,,,,, +201005155,Ingredient,小葱,小葱,,Ingredient,"[{'term': '香葱', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '细葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,适量,,False,,,,, +201005156,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,茄子削皮、横着切成两段,1.0,切,"刀,案板", +201005157,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,蒸5分钟,2.0,蒸,蒸锅,5分钟 +201005158,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,纵向切开,不要切断,在两边切面各划2~3刀至可以摊平,3.0,切,"刀,案板", +201005159,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,煎至两面金黄,4.0,煎,"平底锅,锅铲", +201005160,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,往茄子上浇蒲烧汁至没过1/2茄子高度,5.0,浇汁,锅铲, +201005161,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,煎至背面上色,翻面,同时收汁,若无法收汁可以加入水淀粉(生粉和水的比例在1:4到1:10根据收汁情况而定),6.0,"煎,收汁",锅铲, +201005162,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,把剩下的蒲烧汁浇在茄子上,7.0,浇汁,锅铲, +201005163,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,出锅,一份茄子烧蒲烧汁就烧好了,8.0,出锅,锅铲, +201005164,Recipe,蚝油生菜,蚝油生菜,,Recipe,,素菜,2.0,粤菜,5分钟,5分钟,1人份,"富含维生素,做法简单,爽口,不上火",dishes\vegetable_dish\蚝油生菜.md,,,,,,,, +201005165,Ingredient,生菜,生菜,,Ingredient,,蔬菜,,,,,,,,200,g,True,,,,, +201005166,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,7,ml,False,,,,, +201005167,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,4.5,瓣,False,,,,, +201005168,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,6,ml,False,,,,, +201005169,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,0.5,g,False,,,,, +201005170,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,1,g,False,,,,, +201005171,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,6.5,ml,False,,,,, +201005172,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,1015,ml,False,,,,, +201005173,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,生菜洗净并去掉烂菜叶。,1.0,"洗,切","盆,刀",2分钟 +201005174,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,热锅,先放1 L清水(凉),然后在锅内放入2-3 ml食用油和0.5 g盐,等待锅中的水煮沸。,2.0,煮,锅,2分钟 +201005175,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,水沸后,放入生菜,将每一片生菜叶都焯水10 s。,3.0,焯水,"锅,漏勺",10秒 +201005176,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,捞出生菜,控干水份,摆盘。,4.0,"沥水,摆盘","漏勺,盘子",30秒 +201005177,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,调汁:将生抽10 ml、蚝油6-8 ml、盐0.5 g、白糖1 g放入碗中调匀,并加入10-15 ml清水(凉)搅拌均匀。,5.0,调汁,"碗,筷子",30秒 +201005178,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,再开火,热锅,放入食用油5-8 ml,油热放入蒜泥。,6.0,炒,"锅,锅铲",30秒 +201005179,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,等待有蒜香飘出,倒入调好的汁,煮沸即可,立马关火。,7.0,"炒,煮","锅,锅铲",20秒 +201005180,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将锅中的汤汁均匀地浇在生菜上。,8.0,浇汁,"锅,锅铲",10秒 +201005181,Recipe,西红柿炒鸡蛋,西红柿炒鸡蛋,,Recipe,"[{'term': '番茄炒鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'tomato炒鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,2.0,,5分钟,5分钟,1人/份,"快速做法:鸡蛋与西红柿同炒,可用生抽替代部分盐,可选加番茄酱增汤汁,可选加熟肉",dishes\vegetable_dish\西红柿炒鸡蛋.md,,,,,,,, +201005182,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,个,True,,,,, +201005183,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1.5,个,True,,,,, +201005184,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,6,ml,False,,,,, +201005185,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,1.5,g,False,,,,, +201005186,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,0,g,False,,,,, +201005187,Ingredient,葱花,葱花,,Ingredient,,蔬菜,,,,,,,,0,g,False,,,,, +201005188,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,西红柿洗净,可选:用开水烫表皮后放入冷水剥去外皮,去蒂后切成边长不超过4cm的小块,1.0,"切,烫,剥","刀,案板,锅",2分钟 +201005189,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将鸡蛋打入碗中,加入1g盐搅匀,可选加1ml醋去腥增蓬松,制成鸡蛋液,2.0,搅拌,"碗,筷子",30秒 +201005190,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅,倒入食用油,油热后倒入鸡蛋液,翻炒至鸡蛋结为固体且微微发黄,制成半熟鸡蛋,3.0,炒,"炒锅,锅铲",1分钟 +201005191,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,关火,将半熟鸡蛋盛盘,重新开火(不洗锅),4.0,盛盘,"锅铲,盘子",10秒 +201005192,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入西红柿块,锅铲拍打并翻炒20秒或至西红柿软烂,5.0,炒,锅铲,20秒 +201005193,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入半熟鸡蛋,翻炒均匀;可选加入10ml番茄酱和50ml清水增加汤汁,也可加入其他熟肉,6.0,炒,锅铲,30秒 +201005194,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入剩余盐、可选的糖和葱花,翻炒均匀后关火盛盘,7.0,"炒,盛盘","锅铲,盘子",30秒 +201005195,Recipe,酸辣土豆丝,酸辣土豆丝,,Recipe,"[{'term': '酸辣马铃薯丝', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '酸辣potato丝', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '酸辣洋芋丝', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,2.0,川菜,10分钟,5分钟,1人份,"去淀粉,保持蒜香,快速出锅",dishes\vegetable_dish\酸辣土豆丝.md,,,,,,,, +201005196,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,240,g,True,,,,, +201005197,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,4,瓣,False,,,,, +201005198,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,0.5,个,False,,,,, +201005199,Ingredient,红椒,红椒,,Ingredient,,蔬菜,,,,,,,,0.5,个,False,,,,, +201005200,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,3,个,False,,,,, +201005201,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201005202,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201005203,Ingredient,陈醋,陈醋,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201005204,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005205,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201005206,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,土豆去皮、切丝(或用刨丝器)。,1.0,切,"刀,案板,刨丝器",3分钟 +201005207,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,切好的土豆丝用清水清洗,去除多余的淀粉,然后对土豆丝焯水10秒。沥干,备用。,2.0,"清洗,焯水","盆,锅,漏勺",10秒 +201005208,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,葱蒜干辣椒切小块,青红椒切丝。,3.0,切,"刀,案板",2分钟 +201005209,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,小火热油爆香蒜和干辣椒。,4.0,"炒,爆香","炒锅,锅铲",30秒 +201005210,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入青红椒翻炒几下,加入土豆丝翻炒至变色。,5.0,炒,"炒锅,锅铲",1-2分钟 +201005211,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加5ml生抽,10ml陈醋,蒜末,最后加入盐翻炒均匀即可。,6.0,炒,锅铲,30秒 +201005212,Recipe,金针菇日本豆腐煲,金针菇日本豆腐煲,,Recipe,"[{'term': '金针菇日本tofu煲', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '金针菇日本嫩豆腐煲', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '金针菇日本老豆腐煲', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,2.0,,5-10分钟,10-15分钟,1人份,"金针菇一定要先炒软,豆腐尽量不要翻炒,容易碎",dishes\vegetable_dish\金针菇日本豆腐煲.md,,,,,,,, +201005213,Ingredient,金针菇,金针菇,,Ingredient,,蔬菜,,,,,,,,1-2,把,True,,,,, +201005214,Ingredient,日本豆腐,日本豆腐,,Ingredient,,蛋白质,,,,,,,,2,袋,True,,,,, +201005215,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,3-5,根,False,,,,, +201005216,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,2-3,瓣,False,,,,, +201005217,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201005218,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,毫升,False,,,,, +201005219,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,毫升,False,,,,, +201005220,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,3,克,False,,,,, +201005221,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,毫升,False,,,,, +201005222,Ingredient,水,水,,Ingredient,,其他,,,,,,,,100,毫升,False,,,,, +201005223,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,豆腐切片,小火煎到两面金黄出锅备用。,1.0,"切,煎","刀,平底锅,锅铲",3-5分钟 +201005224,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,切蒜成蒜末;将生抽、蚝油、老抽、糖、100ml水调汁备用。,2.0,"切,调汁","刀,案板,小碗",2分钟 +201005225,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅放油,油热放小米椒、蒜末爆香,先放金针菇,炒软,把煎好的豆腐平铺在金针菇上,倒入步骤2配好的料汁,焖5分钟,大火收汁。,3.0,"炒,焖,收汁","炒锅,锅铲",8-10分钟 +201005226,Recipe,陕北熬豆角,陕北熬豆角,,Recipe,,素菜,2.0,西北菜,约10分钟,约20-25分钟,2人份,偶尔翻搅防止糊底,dishes\vegetable_dish\陕北熬豆角.md,,,,,,,, +201005227,Ingredient,豆角,豆角,,Ingredient,,蔬菜,,,,,,,,600,g,True,,,,, +201005228,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,个,True,,,,, +201005229,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,个,True,,,,, +201005230,Ingredient,螺丝椒,螺丝椒,,Ingredient,,蔬菜,,,,,,,,4,个,False,,,,, +201005231,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,12,g,False,,,,, +201005232,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,12,ml,False,,,,, +201005233,Ingredient,五香粉,五香粉,,Ingredient,,调料,,,,,,,,6,g,False,,,,, +201005234,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,12,ml,False,,,,, +201005235,Ingredient,葱,葱,,Ingredient,,调料,,,,,,,,3,圈,False,,,,, +201005236,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005237,Ingredient,蒜,蒜,,Ingredient,,调料,,,,,,,,2,颗,False,,,,, +201005238,Ingredient,香菜碎,香菜碎,,Ingredient,,蔬菜,,,,,,,,适量,,False,,,,, +201005239,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,ml,False,,,,, +201005240,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,葱切花,蒜切沫,姜切丝,备用。,1.0,切,"刀,案板",约2分钟 +201005241,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,豆角去筋,切2-10cm小段,备用。,2.0,切,"刀,案板",约3分钟 +201005242,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,土豆去皮,切1cm³小块,备用。,3.0,切,"刀,案板",约2分钟 +201005243,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,西红柿去皮,切1cm³小块,备用。,4.0,切,"刀,案板",约2分钟 +201005244,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,辣椒去仔,切0.15cm宽条,备用。,5.0,切,"刀,案板",约1分钟 +201005245,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,起锅烧油(10ml-15ml),冒烟后放入葱姜蒜,翻炒至闻到葱姜蒜香味。,6.0,炒,"炒锅,锅铲",约30秒 +201005246,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入豆角,翻炒至变色(青绿色变为翠绿色)。,7.0,炒,锅铲,约2分钟 +201005247,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入土豆块,翻炒30秒。,8.0,炒,锅铲,30秒 +201005248,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入热水(水面刚刚漫过菜),盖上锅盖熬至土豆变软(可以用筷子确认)。,9.0,"熬,煮","炒锅,锅盖,筷子",约10-12分钟 +201005249,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入西红柿块,加入盐、生抽、蚝油、五香粉、辣椒,熬至西红柿成汁(注意搅拌,防止糊锅)。,10.0,"熬,搅拌",锅铲,约3-5分钟 +201005250,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,加入香菜碎,出锅。,11.0,装盘,锅铲,约10秒 +201005251,Recipe,雷椒皮蛋,雷椒皮蛋,,Recipe,,素菜,2.0,湘菜,10分钟,5分钟,1人份,"夏天下饭神器,去青椒子防炸,两种压碎方式可选",dishes\vegetable_dish\雷椒皮蛋.md,,,,,,,, +201005252,Ingredient,皮蛋,皮蛋,,Ingredient,,蛋白质,,,,,,,,2,个,True,,,,, +201005253,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,4,根,True,,,,, +201005254,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,10,cm,False,,,,, +201005255,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,3.5,瓣,False,,,,, +201005256,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,3.5,颗,False,,,,, +201005257,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201005258,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,17.5,ml,False,,,,, +201005259,Ingredient,陈醋,陈醋,,Ingredient,,调料,,,,,,,,17.5,ml,False,,,,, +201005260,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,8,g,False,,,,, +201005261,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,6,ml,False,,,,, +201005262,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,青椒清洗,去除根部,侧面切开,去除内部的子后在案板压平,备用,1.0,切,"刀,案板",2分钟 +201005263,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱切成半厘米小段,备用,2.0,切,"刀,案板",30秒 +201005264,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,蒜去皮,切成碎末,备用,3.0,切,"刀,案板",30秒 +201005265,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,皮蛋去皮,备用,4.0,剥,手,30秒 +201005266,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,小米辣切成5-10mm的小段,备用,5.0,切,"刀,案板",30秒 +201005267,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,热锅,锅内放入10-20ml食用油,6.0,加热,锅,30秒 +201005268,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入全部青椒,改小火保持锅子温度,煎至青椒变软,7.0,煎,"锅,筷子",3分钟 +201005269,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,关火,将皮蛋和青椒放入小铁盆中,8.0,转移,小铁盆,15秒 +201005270,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,用擀面杖或叉子将皮蛋与青椒混合压碎,9.0,压碎,"擀面杖,叉子,小铁盆",1分钟 +201005271,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,加入小米辣、生抽、陈醋、白糖、香油及其他备用食材,均匀搅拌,10.0,拌,筷子,30秒 +201005272,Recipe,鸡蛋火腿炒黄瓜,鸡蛋火腿炒黄瓜,,Recipe,,素菜,2.0,,约5分钟,约3分钟,1人份,火腿是咸的,要在调味后才加入,这样不会让火腿也沾上盐,dishes\vegetable_dish\鸡蛋火腿炒黄瓜.md,,,,,,,, +201005273,Ingredient,黄瓜,黄瓜,,Ingredient,,蔬菜,,,,,,,,200,g,True,,,,, +201005274,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201005275,Ingredient,火腿肠,火腿肠,,Ingredient,,蛋白质,,,,,,,,40,g,True,,,,, +201005276,Ingredient,红尖椒,红尖椒,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201005277,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201005278,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,ml,False,,,,, +201005279,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005280,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,黄瓜洗净,切半圆形片,备用,1.0,切,"刀,案板", +201005281,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,火腿切半圆形片,备用,2.0,切,"刀,案板", +201005282,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,红尖椒(可选)切碎,备用,3.0,切,"刀,案板", +201005283,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将鸡蛋打入碗中,搅匀,即为鸡蛋液,4.0,搅拌,"碗,筷子", +201005284,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,热锅里倒5ml食用油,5.0,加热,炒锅, +201005285,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,油热后转小火,倒入打散的鸡蛋液,用筷子划散,翻炒至鸡蛋结为固体且颜色微微发黄,即为半熟鸡蛋,盛出备用,6.0,炒,"炒锅,筷子",约1分钟 +201005286,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,不用洗锅,往锅内倒入5ml食用油,倒入黄瓜片大火翻炒1分钟,7.0,炒,"炒锅,锅铲",1分钟 +201005287,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,把半熟鸡蛋倒入锅中,调入2g盐、3ml生抽,立刻倒入火腿片和辣椒碎(可选)翻炒均匀,8.0,炒,"炒锅,锅铲",约30秒 +201005288,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,关火,盛盘,9.0,装盘,锅铲, +201005289,Recipe,上汤娃娃菜,上汤娃娃菜,,Recipe,,"素菜,减肥餐",3.0,,10分钟,5分钟,2-4人,,dishes\vegetable_dish\上汤娃娃菜\上汤娃娃菜.md,,,,,,,, +201005290,Ingredient,娃娃菜,娃娃菜,,Ingredient,,蔬菜,,,,,,,,700,g,True,,,,, +201005291,Ingredient,皮蛋,皮蛋,,Ingredient,,蛋白质,,,,,,,,1,个,True,,,,, +201005292,Ingredient,午餐肉,午餐肉,,Ingredient,,蛋白质,,,,,,,,适量,,True,,,,, +201005293,Ingredient,金针菇,金针菇,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201005294,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,3,g,False,,,,, +201005295,Ingredient,姜,姜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201005296,Ingredient,蒜,蒜,,Ingredient,,蔬菜,,,,,,,,10,g,False,,,,, +201005297,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201005298,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201005299,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,适量,,False,,,,, +201005300,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201005301,Ingredient,味精,味精,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201005302,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,娃娃菜洗净,竖着切开切成段。,1.0,切,"刀,案板",2分钟 +201005303,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,葱3g切小段,蒜10g切片,姜10g切小片。,2.0,切,"刀,案板",2分钟 +201005304,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,皮蛋切成丁,火腿肠或午餐肉切成1cm大小的丁。,3.0,切,"刀,案板",2分钟 +201005305,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,金针菇洗净撕开。,4.0,洗,盆,1分钟 +201005306,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,烧热水,娃娃菜放进去十秒钟焯水后捞出。,5.0,焯水,"锅,漏勺",30秒 +201005307,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,热锅凉油,加热锅倒入油过一遍就倒出来,重新倒入一点油。,6.0,"热锅,倒油","炒锅,锅铲",30秒 +201005308,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,调至小火,加入葱姜蒜,煎炒出香味即可。,7.0,煎炒,"炒锅,锅铲",30秒 +201005309,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入约300g清水(水量没过娃娃菜即可),放入娃娃菜、金针菇、午餐肉。,8.0,"加汤,煮",炒锅,1分钟 +201005310,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加入调味料蚝油、糖、盐、味精烧开。,9.0,"调味,烧开",锅铲,1分钟 +201005311,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,煮3分钟,煮开后开始装盘,盛出娃娃菜后皮蛋放在上面,把汤汁浇上去即可。,10.0,"煮,装盘","锅铲,盘子",3分钟 +201005312,Recipe,凉拌木耳,凉拌木耳,,Recipe,,素菜,2.0,,45分钟(泡发)+ 5分钟(处理),2分钟,1人,"调味可随个人口味调整,可省略芥末,冷却15分钟更入味",dishes\vegetable_dish\凉拌木耳\凉拌木耳.md,,,,,,,, +201005313,Ingredient,干木耳,干木耳,,Ingredient,,蔬菜,,,,,,,,20,g,True,,,,, +201005314,Ingredient,湿木耳,湿木耳,,Ingredient,,蔬菜,,,,,,,,120,g,True,,,,, +201005315,Ingredient,蒜瓣,蒜瓣,,Ingredient,,调料,,,,,,,,2,个,False,,,,, +201005316,Ingredient,小米辣,小米辣,,Ingredient,,调料,,,,,,,,2,个,False,,,,, +201005317,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005318,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,7.5,g,False,,,,, +201005319,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201005320,Ingredient,醋,醋,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201005321,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201005322,Ingredient,芥末,芥末,,Ingredient,,调料,,,,,,,,2,cm,False,,,,, +201005323,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,泡发干木耳,水量约为400ml,泡发约45分钟。(湿木耳跳过此步骤),1.0,泡发,碗,45分钟 +201005324,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将泡发好的木耳进行去根处理,并彻底洗净。,2.0,切,"刀,盆",5分钟 +201005325,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,起锅烧水,水开后放入木耳,大火煮1.5-2分钟。,3.0,煮,锅,2分钟 +201005326,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将蒜瓣、小米辣切碎放入碗中,并依次加入盐、糖、生抽、醋、香油、芥末,用量如上。,4.0,"切,混合","刀,碗",2分钟 +201005327,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,木耳盛出后沥水,放入上一步碗中。,5.0,沥水,"漏勺,碗",1分钟 +201005328,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,搅拌充分,端盘。,6.0,搅拌,筷子,1分钟 +201005329,Recipe,凉拌莴笋,凉拌莴笋,,Recipe,,素菜,2.0,,约10分钟(切菜+腌制),约2分钟(焯水+炒料),1人份,"萝卜可省略,冰镇口感更佳,莴笋皮需多削,可额外加生抽、白砂糖、香醋、芝麻",dishes\vegetable_dish\凉拌莴笋\凉拌莴笋.md,,,,,,,, +201005330,Ingredient,莴笋,莴笋,,Ingredient,,蔬菜,,,,,,,,1,根,True,,,,, +201005331,Ingredient,萝卜,萝卜,,Ingredient,,蔬菜,,,,,,,,0.25,根,False,,,,, +201005332,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,2,个,False,,,,, +201005333,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,1,片,False,,,,, +201005334,Ingredient,蒜头,蒜头,,Ingredient,,调料,,,,,,,,2,粒,False,,,,, +201005335,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201005336,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,25,ml,False,,,,, +201005337,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,莴笋削皮,切小条。萝卜切条,一起放入大碗,加入盐搅拌,放置10分钟,1.0,"切,腌制","刀,案板,大碗",10分钟 +201005338,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,放置后的莴笋用水清洗1-2遍,2.0,清洗,盆,约1分钟 +201005339,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,起锅烧水,放入莴笋,水煮1分钟捞出,沥干水分,放入大碗,3.0,煮,"锅,漏勺,大碗",1分钟 +201005340,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,起锅烧油,放入姜片、蒜粒、小米椒煸炒30-45秒,倒入莴笋中,4.0,炒,"锅,锅铲",30-45秒 +201005341,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,搅拌充分,端盘,5.0,搅拌,筷子,约30秒 +201005342,Recipe,包菜炒鸡蛋粉丝,包菜炒鸡蛋粉丝,,Recipe,,素菜,3.0,,约1小时10分钟(粉丝冷水浸泡1小时+切配10分钟),约3分钟,1份,,dishes\vegetable_dish\包菜炒鸡蛋粉丝\包菜炒鸡蛋粉丝.md,,,,,,,, +201005343,Ingredient,包菜,包菜,,Ingredient,,蔬菜,,,,,,,,0.5,颗,True,,,,, +201005344,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201005345,Ingredient,粉丝,粉丝,,Ingredient,,淀粉类,,,,,,,,1,把,True,,,,, +201005346,Ingredient,胡萝卜,胡萝卜,,Ingredient,,蔬菜,,,,,,,,0.5,根,True,,,,, +201005347,Ingredient,菜籽油,菜籽油,,Ingredient,,调料,,,,,,,,20,ml,False,,,,, +201005348,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005349,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201005350,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201005351,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201005352,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201005353,Ingredient,蒜瓣,蒜瓣,,Ingredient,,蔬菜,,,,,,,,2,片,False,,,,, +201005354,Ingredient,干辣椒,干辣椒,,Ingredient,,调料,,,,,,,,5,根,False,,,,, +201005355,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,胡萝卜、包菜切丝备用,1.0,切,"刀,案板",约5分钟 +201005356,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,粉丝先用冷水浸泡1小时,然后将粉丝放入锅中,加入开水烧至粉丝烫软捞出备用,2.0,"浸泡,煮","锅,漏勺",1小时+2分钟 +201005357,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,鸡蛋打入碗中,加入盐后搅拌15秒,3.0,搅拌,"碗,筷子",15秒 +201005358,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,葱、蒜、辣椒切成小粒备用,4.0,切,"刀,案板",约2分钟 +201005359,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,起锅烧油,倒入鸡蛋,打散炒熟盛出,5.0,炒,"炒锅,锅铲",约30秒 +201005360,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,再倒入油,放入葱、蒜、干辣椒翻炒8秒,6.0,炒,"炒锅,锅铲",8秒 +201005361,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,下胡萝卜、包菜丝儿翻炒30秒,7.0,炒,"炒锅,锅铲",30秒 +201005362,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入粉丝,8.0,混合,锅铲,约5秒 +201005363,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,放调料:生抽15 ml,老抽10 ml,蚝油10 ml,盐2克,9.0,调味,锅铲,约10秒 +201005364,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,放入之前炒好的鸡蛋,翻炒约15秒,10.0,炒,锅铲,15秒 +201005365,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,出锅摆盘,11.0,装盘,"锅铲,盘子",约5秒 +201005366,Recipe,小炒藕丁,小炒藕丁,,Recipe,,素菜,3.0,,约5分钟,约15分钟,2人,"挑选莲藕外皮黄褐色、肉肥厚而白,避免使用铁器防止莲藕发黑",dishes\vegetable_dish\小炒藕丁\小炒藕丁.md,,,,,,,, +201005367,Ingredient,大葱,大葱,,Ingredient,"[{'term': '葱白', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '韭葱', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,段,True,,,,, +201005368,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,1-2,根,True,,,,, +201005369,Ingredient,莲藕,莲藕,,Ingredient,,蔬菜,,,,,,,,1,段,True,,,,, +201005370,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,30,毫升,False,,,,, +201005371,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201005372,Ingredient,耗油,耗油,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201005373,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-15,毫升,False,,,,, +201005374,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,大葱、小米辣切小段,备用,1.0,切,"刀,案板", +201005375,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,莲藕去皮,切成不超过3cm的小块,放入水中备用(防止氧化发黑),2.0,"去皮,切","刀,案板,盆", +201005376,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,取炒锅,锅内放入500ml凉水,煮沸,3.0,煮,炒锅, +201005377,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将藕丁下入沸水中,焯水2分钟后,取出放入盘中备用,4.0,焯水,"炒锅,漏勺,盘",2分钟 +201005378,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将锅中水倒掉后,将锅加热干燥,加入10-15ml食用油,5.0,"加热,倒",炒锅, +201005379,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,待油温升高后,下入葱花,小米辣爆香,6.0,"爆香,炒","炒锅,锅铲", +201005380,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将处理好的藕丁下入锅中,大火翻炒,7.0,炒,"炒锅,锅铲", +201005381,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入生抽、老抽、耗油,8.0,加调料,锅铲, +201005382,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,翻炒2分钟即可出锅,9.0,炒,锅铲,2分钟 +201005383,Recipe,干锅花菜,干锅花菜,,Recipe,,素菜,3.0,湘菜,25分钟,10分钟,1人份,,dishes\vegetable_dish\干锅花菜\干锅花菜.md,,,,,,,, +201005384,Ingredient,花菜,花菜,,Ingredient,,蔬菜,,,,,,,,400,g,True,,,,, +201005385,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201005386,Ingredient,辣椒,辣椒,,Ingredient,,蔬菜,,,,,,,,1.5,根,False,,,,, +201005387,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201005388,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201005389,Ingredient,蒜瓣,蒜瓣,,Ingredient,,蔬菜,,,,,,,,3.5,个,False,,,,, +201005390,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005391,Ingredient,油,油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201005392,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,花菜朵朝下,没入淡盐水中浸泡 20 分钟。然后洗净用小刀拆成小朵,1.0,"腌制,切","盆,小刀",20分钟 +201005393,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,入开水锅中焯水 1 分钟,捞出立即用冷水冲淋至完全凉透,沥水备用,2.0,"煮,冲淋","锅,漏勺",1分钟 +201005394,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,五花肉切成薄片,大蒜白色切下用刀背拍扁,小红辣椒切成段,3.0,"切,拍","刀,案板",3分钟 +201005395,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅烧热放油,油热下大葱白爆香,4.0,炒,"炒锅,锅铲",30秒 +201005396,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,下五花肉片入锅,用中火煸炒至表面全部变色,继续煸炒一会儿,把肥肉部分的油份逼出一部分,5.0,"炒,煸","炒锅,锅铲",2分钟 +201005397,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入红辣椒段和花菜,翻炒几下,6.0,炒,锅铲,30秒 +201005398,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入 10 ml 生抽,7.0,调味,锅铲,5秒 +201005399,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,再加入 5 g 白糖,转大火不断翻炒 1 分钟,8.0,炒,锅铲,1分钟 +201005400,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,把大蒜叶部分切成段,放入锅中,翻炒几下后,关火盖上盖子焖 1 分钟即可,9.0,"炒,焖","锅铲,锅盖",1分钟 +201005401,Recipe,手撕包菜,手撕包菜,,Recipe,,素菜,3.0,湘菜,约10分钟,约6分钟,1人份,"包菜七分熟口感最佳,加盐可锁住水分并提味,最后翻炒时间可灵活调整",dishes\vegetable_dish\手撕包菜\手撕包菜.md,,,,,,,, +201005402,Ingredient,包菜,包菜,,Ingredient,,蔬菜,,,,,,,,1,颗,True,,,,, +201005403,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,200,g,False,,,,, +201005404,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,2,根,False,,,,, +201005405,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,60,ml,False,,,,, +201005406,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201005407,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201005408,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201005409,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005410,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,2,片,False,,,,, +201005411,Ingredient,蒜头,蒜头,,Ingredient,,调料,,,,,,,,2,粒,False,,,,, +201005412,Ingredient,蒜苗,蒜苗,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201005413,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201005414,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,包菜对半切开,去掉中间白色部分,1.0,切,"刀,案板", +201005415,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,手撕包菜,碗中放入2 g盐,清洗包菜并沥干备用,2.0,"撕,洗","碗,盆", +201005416,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,姜片、蒜头、小米辣、蒜苗处理后备用,3.0,切,"刀,案板", +201005417,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,五花肉切片,清水清洗后备用,4.0,"切,洗","刀,案板,盆", +201005418,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中加入30 ml食用油,倒入包菜翻炒,大火翻炒1分钟后加入3 g盐,继续翻炒2分钟后取出备用,5.0,炒,"炒锅,锅铲",3分钟 +201005419,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锅中加入30 ml食用油,倒入五花肉,大火翻炒1分钟,6.0,炒,"炒锅,锅铲",1分钟 +201005420,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,倒入姜片等材料,翻炒1分钟,7.0,炒,"炒锅,锅铲",1分钟 +201005421,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入包菜翻炒后,加入香醋、料酒、鸡精、料酒,大火继续翻炒,2分钟后出锅,8.0,炒,"炒锅,锅铲",2分钟 +201005422,Recipe,拔丝土豆,拔丝土豆,,Recipe,"[{'term': '拔丝洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '拔丝potato', 'language': 'en', 'language_code': 'en-US'}, {'term': '拔丝马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,3.0,鲁菜,约10分钟,约10分钟,1份,"土豆煎炸不可太熟透,否则在拔丝端盘时不容易定型,剩余食用油可收集再利用",dishes\vegetable_dish\拔丝土豆\拔丝土豆.md,,,,,,,, +201005423,Ingredient,土豆,土豆,,Ingredient,"[{'term': '马铃薯', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋芋', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '地蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,2,个,True,,,,, +201005424,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,300,毫升,False,,,,, +201005425,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,30,克,False,,,,, +201005426,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,120,克,False,,,,, +201005427,Ingredient,水,水,,Ingredient,,调料,,,,,,,,100,毫升,False,,,,, +201005428,Ingredient,芝麻,芝麻,,Ingredient,,调料,,,,,,,,5,克,False,,,,, +201005429,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,土豆去皮,切均匀的小块。放入淀粉(不加水)搅拌,使得淀粉覆盖土豆表面,1.0,"切,搅拌","刀,案板,盆",约3分钟 +201005430,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,起锅烧油,放入土豆块,缓缓翻滚煎炸5-7分钟,直至筷子可以插进土豆,2.0,炸,"炒锅,锅铲,筷子",5-7分钟 +201005431,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,取出土豆,放入大碗备用,3.0,沥油,"漏勺,大碗",约30秒 +201005432,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅中加入水、白砂糖,沿着一个方向慢慢搅动白砂糖,直到白砂糖颜色变成褐色,4.0,炒糖色,"炒锅,锅铲",约2-3分钟 +201005433,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,重新倒入土豆,翻炒30秒后出锅,5.0,翻炒,锅铲,30秒 +201005434,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,土豆盛盘,撒上芝麻,6.0,装盘,盘子,约15秒 +201005435,Recipe,椒盐玉米,椒盐玉米,,Recipe,,素菜,3.0,川菜,15-20分钟,4-5分钟,1份(川菜馆标准分量),"使用外卖剥好玉米粒省时,裹淀粉后先煎30秒防掉粉,解冻时带包装煮避免煮玉米本身",dishes\vegetable_dish\椒盐玉米\椒盐玉米.md,,,,,,,, +201005436,Ingredient,玉米粒,玉米粒,,Ingredient,,蔬菜,,,,,,,,350,g,True,,,,, +201005437,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,40-70,g,False,,,,, +201005438,Ingredient,椒盐粉,椒盐粉,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201005439,Ingredient,芝麻粒,芝麻粒,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201005440,Ingredient,油,油,,Ingredient,,调料,,,,,,,,铺满锅底,适量,False,,,,, +201005441,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,玉米粒解冻:温水泡15分钟或开水煮5分钟(带包装煮),1.0,解冻,"盆,锅",15分钟 +201005442,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将解冻好的玉米粒倒入垫有吸油纸的簸箕BoxA,摇晃至吸油纸全湿,2.0,沥水,"塑料簸箕,吸油纸", +201005443,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将玉米粒转入第二个垫有吸油纸的簸箕BoxB,再次摇晃至吸油纸全湿,重复多次直至玉米表面无明显水滴但仍湿润,3.0,沥水,"塑料簸箕,吸油纸", +201005444,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,倒入大量淀粉,摇晃簸箕使淀粉均匀裹住玉米粒,4.0,裹粉,塑料簸箕, +201005445,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,锅中倒入适量油,加热至八成热,5.0,"热锅,热油",锅, +201005446,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,倒入裹好淀粉的玉米粒,中火先煎30秒不翻动,6.0,煎,"锅,锅铲",30秒 +201005447,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,轻微翻炒3分钟后出锅,7.0,炒,锅铲,3分钟 +201005448,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,出锅后撒上椒盐3g和芝麻粒10g即可,8.0,调味,, +201005449,Recipe,榄菜肉末四季豆,榄菜肉末四季豆,,Recipe,,素菜,3.0,粤菜,10分钟,10分钟,2人份,"热锅冷油防粘,四季豆必须炒熟,可免辣",dishes\vegetable_dish\榄菜肉末四季豆\榄菜肉末四季豆.md,,,,,,,, +201005450,Ingredient,四季豆,四季豆,,Ingredient,,蔬菜,,,,,,,,220,g,True,,,,, +201005451,Ingredient,五花肉,五花肉,,Ingredient,,蛋白质,,,,,,,,100,g,True,,,,, +201005452,Ingredient,橄榄菜,橄榄菜,,Ingredient,,调料,,,,,,,,20,g,False,,,,, +201005453,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201005454,Ingredient,小米辣,小米辣,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201005455,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201005456,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,2,ml,False,,,,, +201005457,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005458,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201005459,Ingredient,胡椒粉,胡椒粉,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201005460,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,0.5,g,False,,,,, +201005461,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将四季豆洗净,并把筋撕干净,然后切成大小均匀的颗粒备用。,1.0,切,"刀,案板",3分钟 +201005462,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将大蒜拍碎剁成蒜末备用。,2.0,"拍,剁","刀,案板",1分钟 +201005463,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将小米辣切成大小均匀的颗粒备用。,3.0,切,"刀,案板",1分钟 +201005464,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,将五花肉去皮,然后剁成肉末备用。,4.0,剁,"刀,案板",2分钟 +201005465,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将锅烧热,然后加入20ml油滑锅,锅滑好之后将热油倒出,再加入10ml冷油,形成热锅冷油,防止肉末粘锅。,5.0,"滑锅,倒油",炒锅,30秒 +201005466,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,小火煸炒肉末两分钟,炒出猪油。,6.0,炒,"炒锅,锅铲",2分钟 +201005467,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,肉末炒香后加入蒜末、橄榄菜和小米辣,炒出香味。,7.0,炒,锅铲,30秒 +201005468,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,加入四季豆开中火煸炒至少5分钟,确保四季豆熟透,避免食物中毒。,8.0,炒,锅铲,5分钟 +201005469,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,四季豆炒熟后加入2ml酱油从锅边淋入,再加入2g盐、1g鸡精、1g胡椒粉和0.5g糖。,9.0,调味,锅铲,30秒 +201005470,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,将调料翻炒均匀后出锅装盘。,10.0,炒,锅铲,30秒 +201005471,Recipe,洋葱炒鸡蛋,洋葱炒鸡蛋,,Recipe,,素菜,2.0,,约2分钟,约3-4分钟,1份,,dishes\vegetable_dish\洋葱炒鸡蛋\洋葱炒鸡蛋.md,,,,,,,, +201005472,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201005473,Ingredient,洋葱,洋葱,,Ingredient,,蔬菜,,,,,,,,50,g,True,,,,, +201005474,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,50,ml,False,,,,, +201005475,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005476,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201005477,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,ml,False,,,,, +201005478,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡蛋打入大碗中,加入洋葱片、盐后搅拌60秒,1.0,"切,搅拌","大碗,筷子或打蛋器",60秒 +201005479,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,起锅烧油,倒入鸡蛋,一面煎炸30-45秒,翻面继续翻炒,反复2-3分钟后撒上料酒出锅,2.0,"煎,炒","炒锅,锅铲",2-3分钟 +201005480,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,鸡蛋装盘,撒上葱花,3.0,装盘,盘子,5秒 +201005481,Recipe,炒滑蛋,炒滑蛋,,Recipe,,素菜,1.0,,约1分钟,约2分钟,1人份,可根据个人口味撒黑胡椒或盐调味,dishes\vegetable_dish\炒滑蛋\炒滑蛋.md,,,,,,,, +201005482,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,4,个,True,,,,, +201005483,Ingredient,牛奶,牛奶,,Ingredient,,蛋白质,,,,,,,,30,毫升,False,,,,, +201005484,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,毫升,False,,,,, +201005485,Ingredient,黑胡椒,黑胡椒,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201005486,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201005487,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,鸡蛋加入牛奶以及5ml食用油搅拌均匀,备用,1.0,搅拌,"盆,筷子或打蛋器",约30秒 +201005488,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,大火烧热平底锅约30秒,加入5ml食用油,2.0,加热,平底锅,30秒 +201005489,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,烧30秒后转小火,并且放入搅拌好的鸡蛋,3.0,"加热,倒蛋液",平底锅,30秒 +201005490,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,在锅中静置5秒后,用锅铲将蛋液从边缘缓慢推向中间,4.0,"静置,推炒",锅铲,5秒 +201005491,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,翻炒至鸡蛋大致凝固后关火,装盘,5.0,"翻炒,关火",锅铲,约30秒 +201005492,Recipe,烤茄子,烤茄子,,Recipe,"[{'term': '烘烤茄子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '烤青茄子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '烤eggplant', 'language': 'en', 'language_code': 'en-US'}, {'term': 'baked茄子', 'language': 'en', 'language_code': 'en-US'}, {'term': 'roasted茄子', 'language': 'en', 'language_code': 'en-US'}, {'term': '烤紫茄子', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,3.0,,约5分钟,16-22分钟,2人,"茄子表面有水分、未涂满食用油或未使用叉子扎孔可能导致茄子在烤制的过程中爆裂,第一次用刀划口子的时候,可以直接将茄子竖直切成两半,然后切割出纹路后涂抹上酱料",dishes\vegetable_dish\烤茄子\烤茄子.md,,,,,,,, +201005493,Ingredient,茄子,茄子,,Ingredient,,蔬菜,,,,,,,,1,个,True,,,,, +201005494,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,20-30,毫升,False,,,,, +201005495,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,4-6,克,False,,,,, +201005496,Ingredient,小米椒,小米椒,,Ingredient,,蔬菜,,,,,,,,1,个,False,,,,, +201005497,Ingredient,蒜蓉,蒜蓉,,Ingredient,,调料,,,,,,,,3-4,瓣,False,,,,, +201005498,Ingredient,孜然,孜然,,Ingredient,,调料,,,,,,,,1-3,克,False,,,,, +201005499,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,0.5-2,克,False,,,,, +201005500,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将酱油、孜然、食用盐、蒜蓉和切碎的小米椒置于碗中,均匀搅拌备用,1.0,搅拌,碗, +201005501,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,茄子洗净,用纸巾擦干表面的水分,2.0,"清洗,擦干",纸巾, +201005502,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,用叉子在茄子的一侧扎4-8下,3.0,扎孔,叉子, +201005503,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,使用15-25ml的食用油涂满茄子表面,4.0,涂抹,刷子或手, +201005504,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将烤箱温度设置为200℃(打开烤箱风扇 大火),预热2分钟,5.0,预热,烤箱,2分钟 +201005505,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将茄子放入烤箱中层或者上层,烤制12-15分钟(茄子表面有褶皱,且能按压0.3-0.5cm的深度即可),6.0,烤,烤箱,12-15分钟 +201005506,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,取出茄子,用刀在茄子上竖着划一个口子。口子居中,上下距1-1.5cm,7.0,切割,刀, +201005507,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,用小刀或者叉子伸入口子,竖着切割茄子内部,8.0,切割,小刀或叉子, +201005508,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,将口子微微掰开,倒入第一步准备的酱料,9.0,倒入,刀或叉子, +201005509,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,再次将茄子放入烤箱,将烤箱温度设置为200℃,烤制4-7分钟,10.0,烤,烤箱,4-7分钟 +201005510,CookingStep,步骤11,步骤11,,CookingStep,,,,,,,,,,,,,取出,关闭烤箱电源,11.0,取出,烤箱, +201005511,Recipe,白灼菜心,白灼菜心,,Recipe,,素菜,2.0,粤菜,约5分钟,约3分钟,2人,"保持菜心新鲜,白灼前水中加盐和油,蒜末爆香提味,根茎先烫后整菜烫",dishes\vegetable_dish\白灼菜心\白灼菜心.md,,,,,,,, +201005512,Ingredient,新鲜菜心,新鲜菜心,,Ingredient,,蔬菜,,,,,,,,250,g,True,,,,, +201005513,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,g,False,,,,, +201005514,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,g,False,,,,, +201005515,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201005516,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201005517,Ingredient,糖,糖,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201005518,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,4,瓣,False,,,,, +201005519,Ingredient,小米辣,小米辣,,Ingredient,,调料,,,,,,,,2,根,False,,,,, +201005520,Ingredient,清水,清水,,Ingredient,,其他,,,,,,,,500,ml,False,,,,, +201005521,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,菜心洗净,去除根部比较硬或老的地方,用刀刮掉根茎部分较硬的外层,使内部更可口。,1.0,"切,刮","刀,案板",约2分钟 +201005522,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,大蒜切成蒜末,如有洋葱可适量加入洋葱碎。,2.0,切,"刀,案板",约1分钟 +201005523,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,调制料汁:将生抽5g、蚝油5g、糖3g与100g清水混合成一碗汁。,3.0,混合,"碗,勺子",约1分钟 +201005524,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,锅中加入500ml清水、5g盐和10g食用油,烧开。,4.0,煮,锅,约1分钟 +201005525,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,先将菜心根茎在沸水中烫1分钟至颜色变深绿,再将整个菜心放入锅中烫熟1分钟,捞出码入盘中。,5.0,煮,"锅,筷子",2分钟 +201005526,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,另起小锅,倒入调好的料汁,小火烧开,加入一半蒜末、姜丝、小米椒碎及洋葱碎。先在锅底倒油,五成热后爆香蒜末和洋葱,再加入料汁和小米辣煮开。,6.0,"炒,煮","小锅,锅铲",约1分钟 +201005527,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,料汁煮沸后稍等10秒,收至略浓,直接浇在菜心上,蒜末不可少。,7.0,浇,勺子,约10秒 +201005528,Recipe,糖拌西红柿,糖拌西红柿,,Recipe,"[{'term': '糖拌番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '糖拌tomato', 'language': 'en', 'language_code': 'en-US'}]",素菜,2.0,,5分钟,0分钟,2人,小心使用刀具,dishes\vegetable_dish\糖拌西红柿\糖拌西红柿.md,,,,,,,, +201005529,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,200,克,True,,,,, +201005530,Ingredient,白砂糖,白砂糖,,Ingredient,,调料,,,,,,,,20,克,False,,,,, +201005531,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,用刀将西红柿皮米字型划开,1.0,切,刀, +201005532,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,用筷子插入西红柿的菊花,在燃气上转动烤 10 秒(或用开水冲 30 秒),直到西红柿皮卷边,2.0,"烤,烫","筷子,燃气,开水",10-30秒 +201005533,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,把西红柿的衣服脱光,3.0,去皮,手, +201005534,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,再西红柿大卸八块(沿纹路切可以更多的留汁水),去掉头部根蒂部,备用,4.0,切,刀, +201005535,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,全部切好后,将西红柿在盘子中均匀码一层,5.0,摆盘,盘子, +201005536,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,撒上白糖,重复上面一步直到全部西红柿放完,6.0,撒,盘子, +201005537,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,放入冰箱冷藏 10 分钟,7.0,冷藏,冰箱,10分钟 +201005538,Recipe,红烧冬瓜,红烧冬瓜,,Recipe,"[{'term': 'braised冬瓜', 'language': 'en', 'language_code': 'en-US'}]",素菜,3.0,,约5分钟,约15分钟,1人份,,dishes\vegetable_dish\红烧冬瓜\红烧冬瓜.md,,,,,,,, +201005539,Ingredient,冬瓜,冬瓜,,Ingredient,,蔬菜,,,,,,,,300,g,True,,,,, +201005540,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,50,ml,False,,,,, +201005541,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,ml,False,,,,, +201005542,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,10,g,False,,,,, +201005543,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201005544,Ingredient,老抽,老抽,,Ingredient,"[{'term': '深色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '红烧酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,ml,False,,,,, +201005545,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201005546,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201005547,Ingredient,姜末,姜末,,Ingredient,,调料,,,,,,,,1,粒,False,,,,, +201005548,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201005549,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,冬瓜去皮,切边长不超过2cm的小块,1.0,切,"刀,案板",约2分钟 +201005550,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,起锅烧油,放入冬瓜,缓缓翻滚煎炸2分钟,直至冬瓜表面泛金黄色,2.0,煎炸,"炒锅,锅铲",2分钟 +201005551,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,取出冬瓜,放入大碗备用,3.0,取出,"锅铲,大碗",约10秒 +201005552,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,利用锅中的剩余油,依次放入姜末、生抽、蚝油,翻炒15秒,4.0,炒,"炒锅,锅铲",15秒 +201005553,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,重新倒入冬瓜,翻炒30秒后,加入开水,水要没过冬瓜表面,大火煮10分钟,5.0,"炒,煮","炒锅,锅铲",10分30秒 +201005554,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,加入老抽上色,继续煮,直至冬瓜软糯(筷子可以轻松插进冬瓜),6.0,煮,"炒锅,筷子",约3-5分钟 +201005555,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入鸡精、料酒、香葱翻炒后30秒,取出冬瓜到大碗中,7.0,炒,"炒锅,锅铲,大碗",30秒 +201005556,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,锅中剩余汤汁保留,倒入水淀粉,煮开后汤汁浇灌在冬瓜表面,8.0,"煮,浇汁","炒锅,锅铲,大碗",约30秒 +201005557,Recipe,芹菜拌茶树菇,芹菜拌茶树菇,,Recipe,,素菜,2.0,,约10分钟,约20秒焯水,1-2人,"焯水水位需没过芹菜,芹菜叶太老可去除",dishes\vegetable_dish\芹菜拌茶树菇\芹菜拌茶树菇.md,,,,,,,, +201005558,Ingredient,闽星茶树菇,闽星茶树菇,,Ingredient,,蔬菜,,,,,,,,1,瓶,True,,,,, +201005559,Ingredient,芹菜,芹菜,,Ingredient,,蔬菜,,,,,,,,250-300,g,True,,,,, +201005560,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201005561,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,7,ml,False,,,,, +201005562,Ingredient,味极鲜,味极鲜,,Ingredient,,调料,,,,,,,,3,ml,False,,,,, +201005563,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005564,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,如果是芹菜(非芹菜苗),先用热水壶烧一壶热水备用。,1.0,烧水,热水壶, +201005565,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,新鲜芹菜苗或芹菜摘去黄叶并清洗干净备用。,2.0,清洗,盆, +201005566,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,如果是芹菜(非芹菜苗),将芹菜摘去叶子单独放一盆中,芹菜茎用刀划成2-3毫米宽的芹菜条备用,以便焯水更均匀。,3.0,切,"刀,案板,盆", +201005567,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,芹菜苗切成约4厘米的芹菜段备用。,4.0,切,"刀,案板", +201005568,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,如果是芹菜(非芹菜苗),起锅开火,将热水壶的开水倒入锅中待水沸腾起泡。,5.0,煮,锅, +201005569,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,如果是芹菜(非芹菜苗),将切好的芹菜条放入锅中焯水约20秒,再放入芹菜叶焯5秒后关火,全部捞出过凉水备用。,6.0,"焯水,冷却","锅,漏勺,凉水盆",25秒 +201005570,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将焯好的芹菜或芹菜苗放入盆中,加入食盐、香油、蚝油和味极鲜搅拌均匀。,7.0,拌,"盆,筷子", +201005571,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,将茶树菇倒入盆中,与芹菜搅拌均匀。,8.0,拌,"盆,筷子", +201005572,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,装盘即可开吃。,9.0,装盘,盘子, +201005573,Recipe,莴笋叶煎饼,莴笋叶煎饼,,Recipe,"[{'term': '莴笋叶pan-fried饼', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,2.0,,约5分钟,180秒,1份,"莴笋叶可替换为韭菜,莴笋叶焯水凉拌会苦,适合煎饼",dishes\vegetable_dish\莴笋叶煎饼\莴笋叶煎饼.md,,,,,,,, +201005574,Ingredient,莴笋叶,莴笋叶,,Ingredient,,蔬菜,,,,,,,,50,g,True,,,,, +201005575,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201005576,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,30,ml,False,,,,, +201005577,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,5,ml,False,,,,, +201005578,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,15,g,False,,,,, +201005579,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005580,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,莴笋叶剁碎,加入鸡蛋、生粉、生抽、鸡精搅拌均匀备用,1.0,"切,搅拌","刀,案板,盆",约2分钟 +201005581,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,起锅烧油,倒入莴笋叶浆汁,均匀平铺在锅面上,2.0,煎,"平底锅,锅铲",约30秒 +201005582,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,第一面炸120秒后,翻面再炸60秒后出锅,3.0,煎,"平底锅,锅铲",180秒 +201005583,Recipe,菠菜炒鸡蛋,菠菜炒鸡蛋,,Recipe,,素菜,2.0,,约5分钟(焯水、打蛋、切菜),约1分钟(炒制),1人,,dishes\vegetable_dish\菠菜炒鸡蛋\菠菜炒鸡蛋.md,,,,,,,, +201005584,Ingredient,菠菜,菠菜,,Ingredient,"[{'term': '赤根菜', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '波斯菜', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,350,g,True,,,,, +201005585,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201005586,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,15,ml,False,,,,, +201005587,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201005588,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,菠菜去根,洗净,放在篮子里,焯水,1.0,"切,焯水","刀,篮子,锅", +201005589,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,将鸡蛋打入碗中,搅匀,2.0,"打,搅拌","碗,筷子", +201005590,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,热锅,加入10ml油,3.0,加热,炒锅, +201005591,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,油热后,倒入鸡蛋液,中火翻炒15秒,先煎成蛋饼,然后再用锅铲切成小块,4.0,"煎,炒",锅铲,15秒 +201005592,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,关火,将鸡蛋块盛到盘子中,不要洗锅,5.0,盛,盘子, +201005593,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,重新开火,倒入5ml油,油热后,放入菠菜,大火翻炒15秒后,倒入鸡蛋块,翻炒均匀,6.0,炒,"炒锅,锅铲",15秒 +201005594,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,加入5g盐、100ml饮用水,大火翻炒10秒,7.0,炒,锅铲,10秒 +201005595,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,关火,盛盘,8.0,盛,盘子, +201005596,Recipe,蒜蓉空心菜,蒜蓉空心菜,,Recipe,,素菜,2.0,川菜,5分钟,约1分钟,1人份,"大火快炒,保持脆嫩,热锅凉油法,空心菜选新鲜嫩叶",dishes\vegetable_dish\蒜蓉空心菜\蒜蓉空心菜.md,,,,,,,, +201005597,Ingredient,空心菜,空心菜,,Ingredient,,蔬菜,,,,,,,,250,克,True,,,,, +201005598,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,0.5,个,False,,,,, +201005599,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,45,毫升,False,,,,, +201005600,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,克,False,,,,, +201005601,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,3,克,False,,,,, +201005602,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,8,毫升,False,,,,, +201005603,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,空心菜洗净,去掉烂叶或老梗,均匀切成2-3段,防止过长不好炒,1.0,切,"刀,案板",约2分钟 +201005604,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,锅里先倒少量油,烧至微微冒烟后,用热锅凉油法让油均匀覆盖锅底,再倒入剩余的油,2.0,炒,"炒锅,铲子",约10秒 +201005605,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,放入蒜末,小火炒10-15秒煸香,3.0,炒,铲子,10-15秒 +201005606,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,尽快均匀放入空心菜,开大火,左手拿铲子右手拿筷子不停翻动,直至软化变绿,4.0,炒,"铲子,筷子",约20秒 +201005607,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,改用铲子快速翻炒已软化的空心菜15-20秒,撒入盐、白糖、生抽,5.0,炒,铲子,15-20秒 +201005608,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,继续大火翻炒10秒后即可出锅,6.0,炒,铲子,10秒 +201005609,Recipe,虎皮青椒,虎皮青椒,,Recipe,"[{'term': '虎皮彩椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '虎皮甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '虎皮bell pepper', 'language': 'en', 'language_code': 'en-US'}]",素菜,3.0,川菜,5分钟,2分30秒,1份,,dishes\vegetable_dish\虎皮青椒\虎皮青椒.md,,,,,,,, +201005610,Ingredient,青椒,青椒,,Ingredient,"[{'term': '柿子椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '甜椒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '彩椒', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,5,个,True,,,,, +201005611,Ingredient,大蒜,大蒜,,Ingredient,,调料,,,,,,,,2.5,瓣,False,,,,, +201005612,Ingredient,油,油,,Ingredient,,调料,,,,,,,,20,毫升,False,,,,, +201005613,Ingredient,白糖,白糖,,Ingredient,"[{'term': '细砂糖', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绵白糖', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,克,False,,,,, +201005614,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,15,毫升,False,,,,, +201005615,Ingredient,香醋,香醋,,Ingredient,,调料,,,,,,,,15,毫升,False,,,,, +201005616,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,4,克,False,,,,, +201005617,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,去掉青椒蒂,用自来水冲洗干净。,1.0,清洗,自来水, +201005618,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,青椒切长片,平均一个青椒纵向切成3-4片即可。,2.0,切,刀, +201005619,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,大蒜去皮,切成碎末,体积在2mm x 2mm x 2mm即可。,3.0,切,刀, +201005620,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,拿一个小碗倒入20ml油,将大蒜末放入其中,制成调料1。,4.0,混合,小碗, +201005621,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将白糖、生抽、醋、盐全部倒入砵(碗)等容器,搅拌,制成调料2。,5.0,混合,砵或碗, +201005622,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,将调料1倒入锅中,开火加热至5成油温,放入青椒,青椒片不要叠在一起,单独成片放置锅中。,6.0,炒,"锅,锅铲", +201005623,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,用锅铲不停按压青椒,合适的时候翻面。,7.0,"炒,按压",锅铲, +201005624,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,翻炒约2分钟,待青椒表皮出现褶皱时,倒入调料2。,8.0,炒,锅铲,2分钟 +201005625,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,加大火候继续翻炒30秒后即可出锅盛入盘中。,9.0,炒,锅铲,30秒 +201005626,Recipe,蚝油三鲜菇,蚝油三鲜菇,,Recipe,,素菜,3.0,,10分钟,10分钟,1人份,,dishes\vegetable_dish\蚝油三鲜菇\蚝油三鲜菇.md,,,,,,,, +201005627,Ingredient,鲜香菇,鲜香菇,,Ingredient,,蔬菜,,,,,,,,2,朵,True,,,,, +201005628,Ingredient,蟹味菇,蟹味菇,,Ingredient,,蔬菜,,,,,,,,30,g,True,,,,, +201005629,Ingredient,白玉菇,白玉菇,,Ingredient,,蔬菜,,,,,,,,30,g,True,,,,, +201005630,Ingredient,小米辣,小米辣,,Ingredient,,蔬菜,,,,,,,,1,根,False,,,,, +201005631,Ingredient,菜椒,菜椒,,Ingredient,,蔬菜,,,,,,,,0.5,颗,False,,,,, +201005632,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10,ml,False,,,,, +201005633,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,5,g,False,,,,, +201005634,Ingredient,料酒,料酒,,Ingredient,"[{'term': '黄酒', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '绍兴酒', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,2,ml,False,,,,, +201005635,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,10,g,False,,,,, +201005636,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,10,ml,False,,,,, +201005637,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201005638,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201005639,Ingredient,姜末,姜末,,Ingredient,,调料,,,,,,,,1,粒,False,,,,, +201005640,Ingredient,蚝油,蚝油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201005641,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,350,ml,False,,,,, +201005642,Ingredient,西蓝花,西蓝花,,Ingredient,,蔬菜,,,,,,,,100,g,False,,,,, +201005643,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,蟹味菇、白玉菇去掉根部泥土,掰散菌朵,1.0,"清洗,切","刀,盆",2分钟 +201005644,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,香菇切片,每片厚度0.5-1 cm,厚点更有嚼劲,2.0,切,"刀,案板",2分钟 +201005645,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,生粉倒入小碗中,加入50ml水,搅拌至无颗粒,制成水淀粉备用,3.0,搅拌,"碗,筷子",1分钟 +201005646,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,水开后放入西蓝花,清水煮3分钟,捞出放入碗中备用,4.0,煮,"锅,漏勺",3分钟 +201005647,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,洗锅后重新烧开水,加入5g食用盐,倒入蟹味菇、白玉菇、香菇,水煮1分钟,5.0,焯水,"锅,漏勺",1分钟 +201005648,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,1分钟后捞出沥干水分,6.0,沥水,漏勺,30秒 +201005649,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,起锅烧油,待油开始冒小泡,放入姜末、小米辣、菜椒煸炒30秒,7.0,炒,"炒锅,锅铲",30秒 +201005650,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入三鲜菇,依次加入生抽、蚝油、鸡精,翻炒均匀后倒入水淀粉,8.0,"炒,勾芡","炒锅,锅铲",1分钟 +201005651,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,中火烧干汁,加入料酒、葱花,出锅,9.0,炒,"炒锅,锅铲",30秒 +201005652,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,摆上西蓝花装饰,10.0,摆盘,筷子,30秒 +201005653,Recipe,西红柿豆腐汤羹,西红柿豆腐汤羹,,Recipe,"[{'term': '西红柿嫩豆腐汤羹', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '西红柿tofu汤羹', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '西红柿老豆腐汤羹', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': 'tomato豆腐汤羹', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '番茄豆腐汤羹', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,2.0,,5分钟,3分钟,1人份,,dishes\vegetable_dish\西红柿豆腐汤羹\西红柿豆腐汤羹.md,,,,,,,, +201005654,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,1,个,True,,,,, +201005655,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201005656,Ingredient,豆腐,豆腐,,Ingredient,"[{'term': '水豆腐', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '嫩豆腐', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,100,g,True,,,,, +201005657,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201005658,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005659,Ingredient,淀粉,淀粉,,Ingredient,,淀粉类,,,,,,,,5,g,False,,,,, +201005660,Ingredient,鸡精,鸡精,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005661,Ingredient,香葱,香葱,,Ingredient,,蔬菜,,,,,,,,0.5,根,False,,,,, +201005662,Ingredient,姜,姜,,Ingredient,,调料,,,,,,,,1,片,False,,,,, +201005663,Ingredient,开水,开水,,Ingredient,,其他,,,,,,,,350,ml,False,,,,, +201005664,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,西红柿切成小丁、鸡蛋打入碗中搅拌、豆腐切块备用,1.0,"切,搅拌","刀,案板,碗",2分钟 +201005665,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,起锅烧油,放入姜片5秒后倒入西红柿翻炒30秒,2.0,炒,"炒锅,锅铲",35秒 +201005666,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,锅中加入开水,汤水烧开,60秒后倒入鸡蛋液、豆腐块,3.0,煮,炒锅,60秒 +201005667,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,汤水重新烧开后,加入水淀粉,沿一个方向搅拌2圈,4.0,"煮,搅拌",锅铲,10秒 +201005668,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,加入鸡精、盐、香葱,30秒后起锅,5.0,煮,锅铲,30秒 +201005669,Recipe,西葫芦炒鸡蛋,西葫芦炒鸡蛋,,Recipe,,素菜,2.0,,约5分钟,约8-9分钟,2人,,dishes\vegetable_dish\西葫芦炒鸡蛋\西葫芦炒鸡蛋.md,,,,,,,, +201005670,Ingredient,西葫芦,西葫芦,,Ingredient,,蔬菜,,,,,,,,500,g,True,,,,, +201005671,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,3,个,True,,,,, +201005672,Ingredient,西红柿,西红柿,,Ingredient,"[{'term': '番茄', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '洋柿子', 'language': 'zh', 'language_code': 'zh-CN'}]",蔬菜,,,,,,,,100,g,False,,,,, +201005673,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,10-20,ml,False,,,,, +201005674,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,6,g,False,,,,, +201005675,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,西红柿洗净,切成小块,备用,1.0,切,"刀,案板", +201005676,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,西葫芦洗净,切成边长约为4cm的菱形,备用,2.0,切,"刀,案板", +201005677,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,打三个鸡蛋到碗里,打散搅匀,备用,3.0,打散,"碗,筷子", +201005678,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,热锅,锅内放入5-10ml食用油,4.0,热锅,炒锅, +201005679,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,倒入鸡蛋,保持翻炒至鸡蛋成固体,用锅铲分成小块后盛到碗里,备用,5.0,炒,"炒锅,锅铲,碗", +201005680,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锅内放入5-10ml食用油,倒入西红柿,炒至变软,6.0,炒,"炒锅,锅铲", +201005681,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,倒入西葫芦一起翻炒均匀,放入6g食用盐,将火调小然后等待4-5分钟,7.0,"炒,焖","炒锅,锅铲",4-5分钟 +201005682,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,倒入备用的鸡蛋,中火翻炒15秒,8.0,炒,"炒锅,锅铲",15秒 +201005683,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,关火,盛盘,9.0,盛盘,锅铲, +201005684,Recipe,话梅煮毛豆,话梅煮毛豆,,Recipe,,素菜,2.0,,15分钟,20-30分钟,1份,,dishes\vegetable_dish\话梅煮毛豆\话梅煮毛豆.md,,,,,,,, +201005685,Ingredient,毛豆,毛豆,,Ingredient,,蔬菜,,,,,,,,300,g,True,,,,, +201005686,Ingredient,话梅,话梅,,Ingredient,,调料,,,,,,,,6,颗,False,,,,, +201005687,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,2,g,False,,,,, +201005688,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,清水加入食用盐,毛豆浸泡15分钟,1.0,腌制,盆,15分钟 +201005689,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入开水,倒入毛豆、话梅,水煮20-30分钟,2.0,煮,锅,20-30分钟 +201005690,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,起锅开吃,3.0,,, +201005691,Recipe,微波炉鸡蛋羹,微波炉鸡蛋羹,,Recipe,,素菜,2.0,,3分钟,4分钟,1人/份,"鸡蛋和水不能超过碗容量的2/3,一定要将鸡蛋打散避免爆炸,适合夜宵,快捷简单",dishes\vegetable_dish\鸡蛋羹\微波炉鸡蛋羹.md,,,,,,,, +201005692,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201005693,Ingredient,水,水,,Ingredient,,其他,,,,,,,,200,ml,True,,,,, +201005694,Ingredient,虾皮,虾皮,,Ingredient,,蛋白质,,,,,,,,10,个,False,,,,, +201005695,Ingredient,葱,葱,,Ingredient,,蔬菜,,,,,,,,5,g,False,,,,, +201005696,Ingredient,盐,盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201005697,Ingredient,酱油,酱油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201005698,Ingredient,芝麻油,芝麻油,,Ingredient,,调料,,,,,,,,1,ml,False,,,,, +201005699,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,将鸡蛋打入可使用微波炉加热的陶瓷碗中,使用筷子将其打散。,1.0,切,"陶瓷碗,筷子", +201005700,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入水和盐,搅拌均匀。,2.0,搅拌,筷子, +201005701,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,将虾皮放入碗中,搅拌均匀,保证所有虾皮不会堆积在一起。,3.0,搅拌,筷子, +201005702,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,葱切碎至边长0.6±3mm状,放入碗中搅拌均匀。,4.0,"切,搅拌","刀,筷子", +201005703,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,将此碗及内容物放入微波炉中,容器表面覆盖保鲜膜或以可微波瓷盘加盖(注意:不得密封,必须留有涨缩量)加热2分钟(500W)。,5.0,微波,"微波炉,保鲜膜,瓷盘",2分钟 +201005704,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,小心地取下保鲜膜或其他覆盖物,然后继续加热2分钟。,6.0,微波,微波炉,2分钟 +201005705,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,若微波炉不带旋转式加热盘,将碗缓慢的水平旋转180度,以确保内容物加热均匀。,7.0,旋转,微波炉, +201005706,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,放入芝麻油。,8.0,调味,, +201005707,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,小心地从微波炉中拿出碗(真的很烫)。,9.0,取出,微波炉, +201005708,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,如果选择放入酱油,则确保酱油在鸡蛋羹表面流动后能以最薄的形式沾满鸡蛋羹表面即可。,10.0,调味,, +201005709,Recipe,蒸箱鸡蛋羹,蒸箱鸡蛋羹,,Recipe,"[{'term': 'steamed箱鸡蛋羹', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '清蒸箱鸡蛋羹', 'language': 'zh', 'language_code': 'zh-CN'}]",素菜,3.0,,5分钟,10分钟,1人,"过滤蛋液可去气泡,水量控制影响口感,蒸箱使用注意安全",dishes\vegetable_dish\鸡蛋羹\蒸箱鸡蛋羹.md,,,,,,,, +201005710,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,1,个,True,,,,, +201005711,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,1,g,False,,,,, +201005712,Ingredient,食用油,食用油,,Ingredient,,调料,,,,,,,,5,ml,False,,,,, +201005713,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,6,ml,False,,,,, +201005714,Ingredient,纯净水,纯净水,,Ingredient,,其他,,,,,,,,1.0-1.5倍鸡蛋体积,ml,False,,,,, +201005715,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,一个鸡蛋放入碗中打散,1.0,切,碗, +201005716,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,向碗中加入鸡蛋体积1.0-1.5倍60度纯净水,并且搅拌均匀,2.0,搅拌,碗, +201005717,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入食用盐1g,3.0,调味,碗, +201005718,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入食用油5ml,4.0,调味,碗, +201005719,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,过滤蛋液,去掉蛋液中的浮沫(可选,不过滤蒸出来的蛋会有气泡导致不好看),5.0,过滤,筛网, +201005720,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,确认蒸箱的水源已经补充至足够(若不确定,可把水槽补满),6.0,检查,蒸箱, +201005721,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,将已经完全搅拌均匀的鸡蛋液碗放入蒸箱,7.0,放置,"蒸箱,碗", +201005722,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,调节至100摄氏度蒸10分钟,8.0,蒸,蒸箱,10分钟 +201005723,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,打开蒸箱(注意:蒸箱在开启时会有蒸气瞬间喷出,注意缓慢开启),9.0,开盖,蒸箱, +201005724,CookingStep,步骤10,步骤10,,CookingStep,,,,,,,,,,,,,出锅(可加入生抽调味),10.0,调味,碗, +201005725,Recipe,鸡蛋羹,鸡蛋羹,,Recipe,,素菜,2.0,,5分钟,10-15分钟,1人,"可添加火腿肠、肉馅、虾皮丰富口感,过滤蛋液可减少气泡,蒸碗加盖防蜂窝状",dishes\vegetable_dish\鸡蛋羹\鸡蛋羹.md,,,,,,,, +201005726,Ingredient,鸡蛋,鸡蛋,,Ingredient,"[{'term': '鸡子', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '土鸡蛋', 'language': 'zh', 'language_code': 'zh-CN'}]",蛋白质,,,,,,,,2,个,True,,,,, +201005727,Ingredient,食用盐,食用盐,,Ingredient,,调料,,,,,,,,3,g,False,,,,, +201005728,Ingredient,香油,香油,,Ingredient,,调料,,,,,,,,2-4,ml,False,,,,, +201005729,Ingredient,生抽,生抽,,Ingredient,"[{'term': '淡色酱油', 'language': 'zh', 'language_code': 'zh-CN'}, {'term': '鲜味酱油', 'language': 'zh', 'language_code': 'zh-CN'}]",调料,,,,,,,,8,ml,False,,,,, +201005730,Ingredient,白醋,白醋,,Ingredient,,调料,,,,,,,,2,ml,False,,,,, +201005731,Ingredient,藤椒油,藤椒油,,Ingredient,,调料,,,,,,,,适量,,False,,,,, +201005732,Ingredient,纯净水,纯净水,,Ingredient,,其他,,,,,,,,1-1.5,倍鸡蛋体积,False,,,,, +201005733,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,两个鸡蛋放入碗中打散,1.0,切,"碗,筷子", +201005734,CookingStep,步骤2,步骤2,,CookingStep,,,,,,,,,,,,,加入食用盐3g,搅拌均匀,2.0,搅拌,筷子, +201005735,CookingStep,步骤3,步骤3,,CookingStep,,,,,,,,,,,,,加入2ml白醋去腥(可选),3.0,搅拌,筷子, +201005736,CookingStep,步骤4,步骤4,,CookingStep,,,,,,,,,,,,,加入鸡蛋体积1-1.5倍的70度纯净水,搅拌均匀,4.0,搅拌,筷子, +201005737,CookingStep,步骤5,步骤5,,CookingStep,,,,,,,,,,,,,过滤蛋液,去掉浮沫(可选),5.0,过滤,筛网, +201005738,CookingStep,步骤6,步骤6,,CookingStep,,,,,,,,,,,,,锅中加入50ml清水,烧开后放入盛有蛋液的碗,加盖或保鲜膜,6.0,蒸,"锅,碗,盖子或保鲜膜", +201005739,CookingStep,步骤7,步骤7,,CookingStep,,,,,,,,,,,,,中火蒸10分钟后关火再焖5分钟,或大火蒸5分钟并每隔2分钟开盖一次,7.0,蒸,"锅,计时器",10-15分钟 +201005740,CookingStep,步骤8,步骤8,,CookingStep,,,,,,,,,,,,,晃动碗检查蛋羹已凝固呈果冻状即可,8.0,检查,碗, +201005741,CookingStep,步骤9,步骤9,,CookingStep,,,,,,,,,,,,,出锅后加入香油和生抽即可享用,9.0,调味,勺子, diff --git a/data/C9/cypher/relationships.csv b/data/C9/cypher/relationships.csv new file mode 100644 index 0000000..243a00b --- /dev/null +++ b/data/C9/cypher/relationships.csv @@ -0,0 +1,6056 @@ +startNodeId,endNodeId,relationshipType,relationshipId,amount,unit,step_order +201000001,201000002,801000001,R_000001,300,g, +201000001,201000003,801000001,R_000002,15,g, +201000001,201000004,801000001,R_000003,200,g, +201000001,201000005,801000001,R_000004,100,ml, +201000001,201000006,801000001,R_000005,1,个, +201000001,201000007,801000001,R_000006,5,g, +201000001,201000008,801000001,R_000007,5,瓣, +201000001,201000009,801000001,R_000008,30,ml, +201000001,201000010,801000001,R_000009,300,ml, +201000001,201000011,801000003,R_000010,,,1.0 +201000001,201000012,801000003,R_000011,,,2.0 +201000001,201000013,801000003,R_000012,,,3.0 +201000001,201000014,801000003,R_000013,,,4.0 +201000001,201000015,801000003,R_000014,,,5.0 +201000001,201000016,801000003,R_000015,,,6.0 +201000001,201000017,801000003,R_000016,,,7.0 +201000001,201000018,801000003,R_000017,,,8.0 +201000001,201000019,801000003,R_000018,,,9.0 +201000001,201000020,801000003,R_000019,,,10.0 +201000001,201000021,801000003,R_000020,,,11.0 +201000001,201000022,801000003,R_000021,,,12.0 +201000001,730000000,801000004,R_000022,,, +201000001,640000000,801000005,R_000023,,, +201000023,201000024,801000001,R_000024,450,g, +201000023,201000025,801000001,R_000025,25,g, +201000023,201000026,801000001,R_000026,10,g, +201000023,201000027,801000001,R_000027,13,g, +201000023,201000028,801000001,R_000028,5,mL, +201000023,201000029,801000001,R_000029,25,mL, +201000023,201000030,801000001,R_000030,2,mL, +201000023,201000031,801000001,R_000031,50,mL, +201000023,201000032,801000003,R_000032,,,1.0 +201000023,201000033,801000003,R_000033,,,2.0 +201000023,201000034,801000003,R_000034,,,3.0 +201000023,201000035,801000003,R_000035,,,4.0 +201000023,201000036,801000003,R_000036,,,5.0 +201000023,201000037,801000003,R_000037,,,6.0 +201000023,201000038,801000003,R_000038,,,7.0 +201000023,201000039,801000003,R_000039,,,8.0 +201000023,730000000,801000004,R_000040,,, +201000023,630000000,801000005,R_000041,,, +201000040,201000041,801000001,R_000042,500,g, +201000040,201000042,801000001,R_000043,300-500,g, +201000040,201000043,801000001,R_000044,40,g, +201000040,201000044,801000001,R_000045,10,g, +201000040,201000045,801000001,R_000046,10,ml, +201000040,201000046,801000001,R_000047,25,ml, +201000040,201000047,801000001,R_000048,3,g, +201000040,201000048,801000001,R_000049,2,瓣, +201000040,201000049,801000001,R_000050,5,g, +201000040,201000050,801000001,R_000051,2,g, +201000040,201000051,801000003,R_000052,,,1.0 +201000040,201000052,801000003,R_000053,,,2.0 +201000040,201000053,801000003,R_000054,,,3.0 +201000040,201000054,801000003,R_000055,,,4.0 +201000040,201000055,801000003,R_000056,,,5.0 +201000040,201000056,801000003,R_000057,,,6.0 +201000040,201000057,801000003,R_000058,,,7.0 +201000040,201000058,801000003,R_000059,,,8.0 +201000040,730000000,801000004,R_000060,,, +201000040,640000000,801000005,R_000061,,, +201000059,201000060,801000001,R_000062,6,个, +201000059,201000061,801000001,R_000063,1,升, +201000059,201000062,801000001,R_000064,3,颗, +201000059,201000063,801000001,R_000065,6,瓣, +201000059,201000064,801000001,R_000066,1,小块, +201000059,201000065,801000001,R_000067,6,毫升, +201000059,201000066,801000001,R_000068,1,把, +201000059,201000067,801000003,R_000069,,,1.0 +201000059,201000068,801000003,R_000070,,,2.0 +201000059,201000069,801000003,R_000071,,,3.0 +201000059,201000070,801000003,R_000072,,,4.0 +201000059,201000071,801000003,R_000073,,,5.0 +201000059,201000072,801000003,R_000074,,,6.0 +201000059,730000000,801000004,R_000075,,, +201000059,630000000,801000005,R_000076,,, +201000073,201000074,801000001,R_000077,1,条, +201000073,201000075,801000001,R_000078,2,片, +201000073,201000076,801000001,R_000079,3.5,个, +201000073,201000077,801000001,R_000080,2.5,个, +201000073,201000078,801000001,R_000081,40,毫升, +201000073,201000079,801000001,R_000082,10,克, +201000073,201000080,801000001,R_000083,适量,, +201000073,201000081,801000001,R_000084,5,毫升, +201000073,201000082,801000001,R_000085,5,毫升, +201000073,201000083,801000001,R_000086,10,克, +201000073,201000084,801000001,R_000087,5,克, +201000073,201000085,801000001,R_000088,1.5,根, +201000073,201000086,801000001,R_000089,适量,, +201000073,201000087,801000001,R_000090,1.5,个, +201000073,201000088,801000001,R_000091,5,克, +201000073,201000089,801000003,R_000092,,,1.0 +201000073,201000090,801000003,R_000093,,,2.0 +201000073,201000091,801000003,R_000094,,,3.0 +201000073,201000092,801000003,R_000095,,,4.0 +201000073,201000093,801000003,R_000096,,,5.0 +201000073,201000094,801000003,R_000097,,,6.0 +201000073,201000095,801000003,R_000098,,,7.0 +201000073,201000096,801000003,R_000099,,,8.0 +201000073,201000097,801000003,R_000100,,,9.0 +201000073,201000098,801000003,R_000101,,,10.0 +201000073,201000099,801000003,R_000102,,,11.0 +201000073,730000000,801000004,R_000103,,, +201000073,640000000,801000005,R_000104,,, +201000100,201000101,801000001,R_000105,1,个, +201000100,201000102,801000001,R_000106,200,g, +201000100,201000103,801000001,R_000107,80,g, +201000100,201000104,801000001,R_000108,3.5,个, +201000100,201000105,801000001,R_000109,0.25,个, +201000100,201000106,801000001,R_000110,4,棵, +201000100,201000107,801000001,R_000111,2,个, +201000100,201000108,801000001,R_000112,5,个, +201000100,201000109,801000001,R_000113,30,ml, +201000100,201000110,801000001,R_000114,7,g, +201000100,201000111,801000001,R_000115,3,g, +201000100,201000112,801000001,R_000116,15,g, +201000100,201000113,801000001,R_000117,3,g, +201000100,201000114,801000001,R_000118,3,g, +201000100,201000115,801000001,R_000119,2,g, +201000100,201000116,801000001,R_000120,15,g, +201000100,201000117,801000001,R_000121,500,ml, +201000100,201000118,801000003,R_000122,,,1.0 +201000100,201000119,801000003,R_000123,,,2.0 +201000100,201000120,801000003,R_000124,,,3.0 +201000100,201000121,801000003,R_000125,,,4.0 +201000100,201000122,801000003,R_000126,,,5.0 +201000100,201000123,801000003,R_000127,,,6.0 +201000100,201000124,801000003,R_000128,,,7.0 +201000100,201000125,801000003,R_000129,,,8.0 +201000100,201000126,801000003,R_000130,,,9.0 +201000100,730000000,801000004,R_000131,,, +201000100,640000000,801000005,R_000132,,, +201000127,201000128,801000001,R_000133,1000,克, +201000127,201000129,801000001,R_000134,100,克, +201000127,201000130,801000001,R_000135,200,克, +201000127,201000131,801000001,R_000136,80,克, +201000127,201000132,801000001,R_000137,3.5,个, +201000127,201000133,801000001,R_000138,2,个, +201000127,201000134,801000001,R_000139,50,克, +201000127,201000135,801000001,R_000140,50,毫升, +201000127,201000136,801000001,R_000141,50,毫升, +201000127,201000137,801000001,R_000142,50,毫升, +201000127,201000138,801000001,R_000143,20,毫升, +201000127,201000139,801000001,R_000144,5,毫升, +201000127,201000140,801000001,R_000145,5,克, +201000127,201000141,801000001,R_000146,适量,毫升, +201000127,201000142,801000001,R_000147,没过鱼面,毫升, +201000127,201000143,801000003,R_000148,,,1.0 +201000127,201000144,801000003,R_000149,,,2.0 +201000127,201000145,801000003,R_000150,,,3.0 +201000127,201000146,801000003,R_000151,,,4.0 +201000127,201000147,801000003,R_000152,,,5.0 +201000127,201000148,801000003,R_000153,,,6.0 +201000127,201000149,801000003,R_000154,,,7.0 +201000127,201000150,801000003,R_000155,,,8.0 +201000127,201000151,801000003,R_000156,,,9.0 +201000127,201000152,801000003,R_000157,,,10.0 +201000127,201000153,801000003,R_000158,,,11.0 +201000127,201000154,801000003,R_000159,,,12.0 +201000127,201000155,801000003,R_000160,,,13.0 +201000127,201000156,801000003,R_000161,,,14.0 +201000127,201000157,801000003,R_000162,,,15.0 +201000127,201000158,801000003,R_000163,,,16.0 +201000127,201000159,801000003,R_000164,,,17.0 +201000127,730000000,801000004,R_000165,,, +201000127,640000000,801000005,R_000166,,, +201000160,201000161,801000001,R_000167,2,斤, +201000160,201000162,801000001,R_000168,70,毫升, +201000160,201000163,801000001,R_000169,2,片, +201000160,201000164,801000001,R_000170,1,个, +201000160,201000165,801000001,R_000171,3,克, +201000160,201000166,801000001,R_000172,10,克, +201000160,201000167,801000001,R_000173,10,克, +201000160,201000168,801000001,R_000174,5,克, +201000160,201000169,801000001,R_000175,1,根, +201000160,201000170,801000001,R_000176,30,克, +201000160,201000171,801000001,R_000177,7,瓣, +201000160,201000172,801000001,R_000178,30,克, +201000160,201000173,801000001,R_000179,30,克, +201000160,201000174,801000001,R_000180,500,毫升, +201000160,201000175,801000001,R_000181,30,毫升, +201000160,201000176,801000001,R_000182,10,克, +201000160,201000177,801000003,R_000183,,,1.0 +201000160,201000178,801000003,R_000184,,,2.0 +201000160,201000179,801000003,R_000185,,,3.0 +201000160,201000180,801000003,R_000186,,,4.0 +201000160,201000181,801000003,R_000187,,,5.0 +201000160,201000182,801000003,R_000188,,,6.0 +201000160,201000183,801000003,R_000189,,,7.0 +201000160,730000000,801000004,R_000190,,, +201000160,640000000,801000005,R_000191,,, +201000184,201000185,801000001,R_000192,2-3,只, +201000184,201000186,801000001,R_000193,5,克, +201000184,201000187,801000001,R_000194,适量,, +201000184,201000188,801000001,R_000195,20,毫升, +201000184,201000189,801000001,R_000196,1,毫升, +201000184,201000190,801000001,R_000197,3,片, +201000184,201000191,801000001,R_000198,1,片, +201000184,201000192,801000001,R_000199,10,克, +201000184,201000193,801000001,R_000200,10,克, +201000184,201000194,801000001,R_000201,10,克, +201000184,201000195,801000001,R_000202,2调羹,, +201000184,201000196,801000003,R_000203,,,1.0 +201000184,201000197,801000003,R_000204,,,2.0 +201000184,201000198,801000003,R_000205,,,3.0 +201000184,201000199,801000003,R_000206,,,4.0 +201000184,201000200,801000003,R_000207,,,5.0 +201000184,201000201,801000003,R_000208,,,6.0 +201000184,201000202,801000003,R_000209,,,7.0 +201000184,201000203,801000003,R_000210,,,8.0 +201000184,201000204,801000003,R_000211,,,9.0 +201000184,201000205,801000003,R_000212,,,10.0 +201000184,730000000,801000004,R_000213,,, +201000184,630000000,801000005,R_000214,,, +201000206,201000207,801000001,R_000215,10,只, +201000206,201000208,801000001,R_000216,5,克, +201000206,201000209,801000001,R_000217,50,克, +201000206,201000210,801000001,R_000218,20,克, +201000206,201000211,801000001,R_000219,30,克, +201000206,201000212,801000001,R_000220,3,克, +201000206,201000213,801000001,R_000221,10,克, +201000206,201000214,801000001,R_000222,适量,, +201000206,201000215,801000003,R_000223,,,1.0 +201000206,201000216,801000003,R_000224,,,2.0 +201000206,201000217,801000003,R_000225,,,3.0 +201000206,201000218,801000003,R_000226,,,4.0 +201000206,201000219,801000003,R_000227,,,5.0 +201000206,201000220,801000003,R_000228,,,6.0 +201000206,201000221,801000003,R_000229,,,7.0 +201000206,201000222,801000003,R_000230,,,8.0 +201000206,730000000,801000004,R_000231,,, +201000206,640000000,801000005,R_000232,,, +201000223,201000224,801000001,R_000001,1500,克, +201000223,201000225,801000001,R_000002,0.5,根, +201000223,201000226,801000001,R_000003,20,毫升, +201000223,201000227,801000001,R_000004,12.5,毫升, +201000223,201000228,801000001,R_000005,7.5,克, +201000223,201000229,801000001,R_000006,7.5,克, +201000223,201000230,801000001,R_000007,1,小片, +201000223,201000231,801000001,R_000008,2,个, +201000223,201000232,801000001,R_000009,8,粒, +201000223,201000233,801000001,R_000010,2,片, +201000223,201000234,801000001,R_000011,1,小把, +201000223,201000235,801000001,R_000012,10,个, +201000223,201000236,801000001,R_000013,4,个, +201000223,201000237,801000001,R_000014,2,根, +201000223,201000238,801000001,R_000015,0.5,个, +201000223,201000239,801000001,R_000016,1,张, +201000223,201000240,801000001,R_000017,适量,, +201000223,201000241,801000001,R_000018,0.5,包, +201000223,201000242,801000001,R_000019,17.5,克, +201000223,201000243,801000001,R_000020,5,克, +201000223,201000244,801000001,R_000021,5,毫升, +201000223,201000245,801000001,R_000022,适量,, +201000223,201000246,801000001,R_000023,适量,, +201000223,201000247,801000001,R_000024,适量,, +201000223,201000248,801000001,R_000025,适量,, +201000223,201000249,801000003,R_000026,,,1.0 +201000223,201000250,801000003,R_000027,,,2.0 +201000223,201000251,801000003,R_000028,,,3.0 +201000223,201000252,801000003,R_000029,,,4.0 +201000223,201000253,801000003,R_000030,,,5.0 +201000223,201000254,801000003,R_000031,,,6.0 +201000223,201000255,801000003,R_000032,,,7.0 +201000223,201000256,801000003,R_000033,,,8.0 +201000223,730000000,801000004,R_000034,,, +201000223,640000000,801000005,R_000035,,, +201000257,201000258,801000001,R_000036,1,条, +201000257,201000259,801000001,R_000037,3,根, +201000257,201000260,801000001,R_000038,1,块, +201000257,201000261,801000001,R_000039,10-15,毫升, +201000257,201000262,801000001,R_000040,10-15,毫升, +201000257,201000263,801000001,R_000041,10-15,毫升, +201000257,201000264,801000001,R_000042,5-10,克, +201000257,201000265,801000003,R_000043,,,1.0 +201000257,201000266,801000003,R_000044,,,2.0 +201000257,201000267,801000003,R_000045,,,3.0 +201000257,201000268,801000003,R_000046,,,4.0 +201000257,201000269,801000003,R_000047,,,5.0 +201000257,201000270,801000003,R_000048,,,6.0 +201000257,201000271,801000003,R_000049,,,7.0 +201000257,730000000,801000004,R_000050,,, +201000257,630000000,801000005,R_000051,,, +201000272,201000273,801000001,R_000052,250,g, +201000272,201000274,801000001,R_000053,1,根, +201000272,201000275,801000001,R_000054,1,块, +201000272,201000276,801000001,R_000055,1,头, +201000272,201000277,801000001,R_000056,5-8,瓣, +201000272,201000278,801000001,R_000057,10-15,ml, +201000272,201000279,801000001,R_000058,20,ml, +201000272,201000280,801000001,R_000059,10-15,ml, +201000272,201000281,801000001,R_000060,1,把, +201000272,201000282,801000001,R_000061,10,ml, +201000272,201000283,801000001,R_000062,10,ml, +201000272,201000284,801000003,R_000063,,,1.0 +201000272,201000285,801000003,R_000064,,,2.0 +201000272,201000286,801000003,R_000065,,,3.0 +201000272,201000287,801000003,R_000066,,,4.0 +201000272,201000288,801000003,R_000067,,,5.0 +201000272,201000289,801000003,R_000068,,,6.0 +201000272,730000000,801000004,R_000069,,, +201000272,620000000,801000005,R_000070,,, +201000290,201000291,801000001,R_000071,3,斤, +201000290,201000292,801000001,R_000072,40,克, +201000290,201000293,801000001,R_000073,20,克, +201000290,201000294,801000001,R_000074,10,克, +201000290,201000295,801000001,R_000075,10,克, +201000290,201000296,801000001,R_000076,30,克, +201000290,201000297,801000001,R_000077,30,克, +201000290,201000298,801000001,R_000078,30,克, +201000290,201000299,801000001,R_000079,25,克, +201000290,201000300,801000001,R_000080,1,颗, +201000290,201000301,801000001,R_000081,100,克, +201000290,201000302,801000001,R_000082,1,个, +201000290,201000303,801000001,R_000083,50,克, +201000290,201000304,801000003,R_000084,,,1.0 +201000290,201000305,801000003,R_000085,,,2.0 +201000290,201000306,801000003,R_000086,,,3.0 +201000290,201000307,801000003,R_000087,,,4.0 +201000290,201000308,801000003,R_000088,,,5.0 +201000290,201000309,801000003,R_000089,,,6.0 +201000290,201000310,801000003,R_000090,,,7.0 +201000290,201000311,801000003,R_000091,,,8.0 +201000290,201000312,801000003,R_000092,,,9.0 +201000290,201000313,801000003,R_000093,,,10.0 +201000290,201000314,801000003,R_000094,,,11.0 +201000290,201000315,801000003,R_000095,,,12.0 +201000290,201000316,801000003,R_000096,,,13.0 +201000290,201000317,801000003,R_000097,,,14.0 +201000290,201000318,801000003,R_000098,,,15.0 +201000290,730000000,801000004,R_000099,,, +201000290,640000000,801000005,R_000100,,, +201000319,201000320,801000001,R_000101,500,克, +201000319,201000321,801000001,R_000102,20,克, +201000319,201000322,801000001,R_000103,15,克, +201000319,201000323,801000001,R_000104,3,克, +201000319,201000324,801000001,R_000105,30,克, +201000319,201000325,801000001,R_000106,30,克, +201000319,201000326,801000001,R_000107,3,克, +201000319,201000327,801000001,R_000108,15,克, +201000319,201000328,801000001,R_000109,5,条, +201000319,201000329,801000001,R_000110,5,颗, +201000319,201000330,801000003,R_000111,,,1.0 +201000319,201000331,801000003,R_000112,,,2.0 +201000319,201000332,801000003,R_000113,,,3.0 +201000319,201000333,801000003,R_000114,,,4.0 +201000319,201000334,801000003,R_000115,,,5.0 +201000319,201000335,801000003,R_000116,,,6.0 +201000319,201000336,801000003,R_000117,,,7.0 +201000319,730000000,801000004,R_000118,,, +201000319,630000000,801000005,R_000119,,, +201000337,201000338,801000001,R_000120,500,克, +201000337,201000339,801000001,R_000121,1,根, +201000337,201000340,801000001,R_000122,2,个, +201000337,201000341,801000001,R_000123,50,克, +201000337,201000342,801000001,R_000124,25,克, +201000337,201000343,801000001,R_000125,15,克, +201000337,201000344,801000001,R_000126,8,克, +201000337,201000345,801000001,R_000127,10,克, +201000337,201000346,801000001,R_000128,5000,毫升, +201000337,201000347,801000003,R_000129,,,1.0 +201000337,201000348,801000003,R_000130,,,2.0 +201000337,201000349,801000003,R_000131,,,3.0 +201000337,201000350,801000003,R_000132,,,4.0 +201000337,201000351,801000003,R_000133,,,5.0 +201000337,201000352,801000003,R_000134,,,6.0 +201000337,201000353,801000003,R_000135,,,7.0 +201000337,201000354,801000003,R_000136,,,8.0 +201000337,201000355,801000003,R_000137,,,9.0 +201000337,201000356,801000003,R_000138,,,10.0 +201000337,201000357,801000003,R_000139,,,11.0 +201000337,201000358,801000003,R_000140,,,12.0 +201000337,201000359,801000003,R_000141,,,13.0 +201000337,201000360,801000003,R_000142,,,14.0 +201000337,201000361,801000003,R_000143,,,15.0 +201000337,201000362,801000003,R_000144,,,16.0 +201000337,201000363,801000003,R_000145,,,17.0 +201000337,201000364,801000003,R_000146,,,18.0 +201000337,730000000,801000004,R_000147,,, +201000337,640000000,801000005,R_000148,,, +201000365,201000366,801000001,R_000149,4,个, +201000365,201000367,801000001,R_000150,1,根, +201000365,201000368,801000001,R_000151,20,毫升, +201000365,201000369,801000001,R_000152,20,克, +201000365,201000370,801000001,R_000153,5,克, +201000365,201000371,801000001,R_000154,2,克, +201000365,201000372,801000001,R_000155,2,克, +201000365,201000373,801000001,R_000156,100,毫升, +201000365,201000374,801000003,R_000157,,,1.0 +201000365,201000375,801000003,R_000158,,,2.0 +201000365,201000376,801000003,R_000159,,,3.0 +201000365,201000377,801000003,R_000160,,,4.0 +201000365,201000378,801000003,R_000161,,,5.0 +201000365,201000379,801000003,R_000162,,,6.0 +201000365,201000380,801000003,R_000163,,,7.0 +201000365,201000381,801000003,R_000164,,,8.0 +201000365,201000382,801000003,R_000165,,,9.0 +201000365,201000383,801000003,R_000166,,,10.0 +201000365,201000384,801000003,R_000167,,,11.0 +201000365,201000385,801000003,R_000168,,,12.0 +201000365,730000000,801000004,R_000169,,, +201000365,630000000,801000005,R_000170,,, +201000386,201000387,801000001,R_000171,8,只, +201000386,201000388,801000001,R_000172,50,g, +201000386,201000389,801000001,R_000173,20,ml, +201000386,201000390,801000001,R_000174,5,ml, +201000386,201000391,801000003,R_000175,,,1.0 +201000386,201000392,801000003,R_000176,,,2.0 +201000386,201000393,801000003,R_000177,,,3.0 +201000386,201000394,801000003,R_000178,,,4.0 +201000386,730000000,801000004,R_000179,,, +201000386,620000000,801000005,R_000180,,, +201000395,201000396,801000001,R_000181,200,克, +201000395,201000397,801000001,R_000182,30,克, +201000395,201000398,801000001,R_000183,20,克, +201000395,201000399,801000001,R_000184,15,毫升, +201000395,201000400,801000001,R_000185,0.25,个, +201000395,201000401,801000001,R_000186,10,毫升, +201000395,201000402,801000003,R_000187,,,1.0 +201000395,201000403,801000003,R_000188,,,2.0 +201000395,201000404,801000003,R_000189,,,3.0 +201000395,201000405,801000003,R_000190,,,4.0 +201000395,201000406,801000003,R_000191,,,5.0 +201000395,201000407,801000003,R_000192,,,6.0 +201000395,201000408,801000003,R_000193,,,7.0 +201000395,201000409,801000003,R_000194,,,8.0 +201000395,201000410,801000003,R_000195,,,9.0 +201000395,730000000,801000004,R_000196,,, +201000395,620000000,801000005,R_000197,,, +201000411,201000412,801000001,R_000198,200,g, +201000411,201000413,801000001,R_000199,2,个, +201000411,201000414,801000001,R_000200,100,ml, +201000411,201000415,801000001,R_000201,0.25,个, +201000411,201000416,801000001,R_000202,20,g, +201000411,201000417,801000001,R_000203,5,ml, +201000411,201000418,801000001,R_000204,5,ml, +201000411,201000419,801000001,R_000205,5,ml, +201000411,201000420,801000003,R_000206,,,1.0 +201000411,201000421,801000003,R_000207,,,2.0 +201000411,201000422,801000003,R_000208,,,3.0 +201000411,201000423,801000003,R_000209,,,4.0 +201000411,730000000,801000004,R_000210,,, +201000411,630000000,801000005,R_000211,,, +201000424,201000425,801000001,R_000001,2,斤, +201000424,201000426,801000001,R_000002,20,克, +201000424,201000427,801000001,R_000003,50,克, +201000424,201000428,801000001,R_000004,4,个, +201000424,201000429,801000001,R_000005,适量,, +201000424,201000430,801000001,R_000006,2,毫升, +201000424,201000431,801000001,R_000007,10,克, +201000424,201000432,801000001,R_000008,适量,, +201000424,201000433,801000001,R_000009,4-6,个, +201000424,201000434,801000001,R_000010,100,毫升, +201000424,201000435,801000001,R_000011,4,毫升, +201000424,201000436,801000001,R_000012,50,克, +201000424,201000437,801000001,R_000013,100,毫升, +201000424,201000438,801000001,R_000014,适量,, +201000424,201000439,801000001,R_000015,适量,, +201000424,201000440,801000001,R_000016,适量,, +201000424,201000441,801000001,R_000017,适量,, +201000424,201000442,801000003,R_000018,,,1.0 +201000424,201000443,801000003,R_000019,,,2.0 +201000424,201000444,801000003,R_000020,,,3.0 +201000424,201000445,801000003,R_000021,,,4.0 +201000424,201000446,801000003,R_000022,,,5.0 +201000424,201000447,801000003,R_000023,,,6.0 +201000424,201000448,801000003,R_000024,,,7.0 +201000424,201000449,801000003,R_000025,,,8.0 +201000424,201000450,801000003,R_000026,,,9.0 +201000424,201000451,801000003,R_000027,,,10.0 +201000424,201000452,801000003,R_000028,,,11.0 +201000424,730000000,801000004,R_000029,,, +201000424,640000000,801000005,R_000030,,, +201000453,201000454,801000001,R_000031,10,ml, +201000453,201000455,801000001,R_000032,3,片, +201000453,201000456,801000001,R_000033,3,瓣, +201000453,201000457,801000001,R_000034,1.2,斤, +201000453,201000458,801000001,R_000035,13,片, +201000453,201000459,801000001,R_000036,5-8,克, +201000453,201000460,801000001,R_000037,3,ml, +201000453,201000461,801000001,R_000038,6,ml, +201000453,201000462,801000001,R_000039,1,块, +201000453,201000463,801000001,R_000040,3,个, +201000453,201000464,801000001,R_000041,20,克, +201000453,201000465,801000001,R_000042,4-6,个, +201000453,201000466,801000003,R_000043,,,1.0 +201000453,201000467,801000003,R_000044,,,2.0 +201000453,201000468,801000003,R_000045,,,3.0 +201000453,201000469,801000003,R_000046,,,4.0 +201000453,201000470,801000003,R_000047,,,5.0 +201000453,201000471,801000003,R_000048,,,6.0 +201000453,730000000,801000004,R_000049,,, +201000453,630000000,801000005,R_000050,,, +201000472,201000473,801000001,R_000051,550,克, +201000472,201000474,801000001,R_000052,400,克, +201000472,201000475,801000001,R_000053,5,片, +201000472,201000476,801000001,R_000054,50,克, +201000472,201000477,801000001,R_000055,4,个, +201000472,201000478,801000001,R_000056,2,毫升, +201000472,201000479,801000001,R_000057,1,块, +201000472,201000480,801000001,R_000058,5,块, +201000472,201000481,801000001,R_000059,4,个, +201000472,201000482,801000001,R_000060,5,毫升, +201000472,201000483,801000001,R_000061,4,毫升, +201000472,201000484,801000001,R_000062,5,克, +201000472,201000485,801000001,R_000063,1,个, +201000472,201000486,801000001,R_000064,1,片, +201000472,201000487,801000001,R_000065,10,毫升, +201000472,201000488,801000001,R_000066,400,克, +201000472,201000489,801000003,R_000067,,,1.0 +201000472,201000490,801000003,R_000068,,,2.0 +201000472,201000491,801000003,R_000069,,,3.0 +201000472,201000492,801000003,R_000070,,,4.0 +201000472,201000493,801000003,R_000071,,,5.0 +201000472,201000494,801000003,R_000072,,,6.0 +201000472,201000495,801000003,R_000073,,,7.0 +201000472,730000000,801000004,R_000074,,, +201000472,630000000,801000005,R_000075,,, +201000496,201000497,801000001,R_000076,300,g, +201000496,201000498,801000001,R_000077,7,g, +201000496,201000499,801000001,R_000078,15,ml, +201000496,201000500,801000001,R_000079,45,ml, +201000496,201000501,801000001,R_000080,10,ml, +201000496,201000502,801000001,R_000081,5,ml, +201000496,201000503,801000001,R_000082,10,ml, +201000496,201000504,801000001,R_000083,2.5,ml, +201000496,201000505,801000003,R_000084,,,1.0 +201000496,201000506,801000003,R_000085,,,2.0 +201000496,201000507,801000003,R_000086,,,3.0 +201000496,201000508,801000003,R_000087,,,4.0 +201000496,201000509,801000003,R_000088,,,5.0 +201000496,201000510,801000003,R_000089,,,6.0 +201000496,730000000,801000004,R_000090,,, +201000496,630000000,801000005,R_000091,,, +201000511,201000512,801000001,R_000092,2,片, +201000511,201000513,801000001,R_000093,适量,, +201000511,201000514,801000003,R_000094,,,1.0 +201000511,201000515,801000003,R_000095,,,2.0 +201000511,201000516,801000003,R_000096,,,3.0 +201000511,201000517,801000003,R_000097,,,4.0 +201000511,201000518,801000003,R_000098,,,5.0 +201000511,740000000,801000004,R_000099,,, +201000511,610000000,801000005,R_000100,,, +201000519,201000520,801000001,R_000101,1,个, +201000519,201000521,801000001,R_000102,1,克, +201000519,201000522,801000001,R_000103,5,毫升, +201000519,201000523,801000003,R_000104,,,1.0 +201000519,201000524,801000003,R_000105,,,2.0 +201000519,201000525,801000003,R_000106,,,3.0 +201000519,201000526,801000003,R_000107,,,4.0 +201000519,740000000,801000004,R_000108,,, +201000519,620000000,801000005,R_000109,,, +201000527,201000528,801000001,R_000110,1,个, +201000527,201000529,801000001,R_000111,1500,毫升, +201000527,201000530,801000001,R_000112,1500,毫升, +201000527,201000531,801000001,R_000113,适量,毫升, +201000527,201000532,801000003,R_000114,,,1.0 +201000527,201000533,801000003,R_000115,,,2.0 +201000527,201000534,801000003,R_000116,,,3.0 +201000527,201000535,801000003,R_000117,,,4.0 +201000527,201000536,801000003,R_000118,,,5.0 +201000527,201000537,801000003,R_000119,,,6.0 +201000527,201000538,801000003,R_000120,,,7.0 +201000527,740000000,801000004,R_000121,,, +201000527,650000000,801000005,R_000122,,, +201000539,201000540,801000001,R_000123,2,个, +201000539,201000541,801000001,R_000124,35,毫升, +201000539,201000542,801000001,R_000125,3,毫升, +201000539,201000543,801000001,R_000126,0.8,克, +201000539,201000544,801000003,R_000127,,,1.0 +201000539,201000545,801000003,R_000128,,,2.0 +201000539,201000546,801000003,R_000129,,,3.0 +201000539,201000547,801000003,R_000130,,,4.0 +201000539,201000548,801000003,R_000131,,,5.0 +201000539,201000549,801000003,R_000132,,,6.0 +201000539,740000000,801000004,R_000133,,, +201000539,610000000,801000005,R_000134,,, +201000550,201000551,801000001,R_000135,1,个, +201000550,201000552,801000001,R_000136,15,g, +201000550,201000553,801000001,R_000137,2.5,g, +201000550,201000554,801000001,R_000138,10,g, +201000550,201000555,801000001,R_000139,1,g, +201000550,201000556,801000001,R_000140,半个鸡蛋大,, +201000550,201000557,801000001,R_000141,可选,, +201000550,201000558,801000001,R_000142,可选,, +201000550,201000559,801000001,R_000143,可选,, +201000550,201000560,801000001,R_000144,可选,, +201000550,201000561,801000001,R_000145,可选,, +201000550,201000562,801000001,R_000146,可选,, +201000550,201000563,801000001,R_000147,可选,, +201000550,201000564,801000003,R_000148,,,1.0 +201000550,201000565,801000003,R_000149,,,2.0 +201000550,201000566,801000003,R_000150,,,3.0 +201000550,201000567,801000003,R_000151,,,4.0 +201000550,201000568,801000003,R_000152,,,5.0 +201000550,201000569,801000003,R_000153,,,6.0 +201000550,201000570,801000003,R_000154,,,7.0 +201000550,740000000,801000004,R_000155,,, +201000550,610000000,801000005,R_000156,,, +201000571,201000572,801000001,R_000157,200,克, +201000571,201000573,801000001,R_000158,100,毫升, +201000571,201000574,801000001,R_000159,50,毫升, +201000571,201000575,801000001,R_000160,15,毫升, +201000571,201000576,801000001,R_000161,3,克, +201000571,201000577,801000001,R_000162,1,个, +201000571,201000578,801000001,R_000163,30,克, +201000571,201000579,801000001,R_000164,30,克, +201000571,201000580,801000001,R_000165,1,片, +201000571,201000581,801000003,R_000166,,,1.0 +201000571,201000582,801000003,R_000167,,,2.0 +201000571,201000583,801000003,R_000168,,,3.0 +201000571,201000584,801000003,R_000169,,,4.0 +201000571,201000585,801000003,R_000170,,,5.0 +201000571,201000586,801000003,R_000171,,,6.0 +201000571,740000000,801000004,R_000172,,, +201000571,620000000,801000005,R_000173,,, +201000587,201000588,801000001,R_000001,100,g, +201000587,201000589,801000001,R_000002,15,颗, +201000587,201000590,801000001,R_000003,15,颗, +201000587,201000591,801000003,R_000004,,,1.0 +201000587,201000592,801000003,R_000005,,,2.0 +201000587,201000593,801000003,R_000006,,,3.0 +201000587,201000594,801000003,R_000007,,,4.0 +201000587,201000595,801000003,R_000008,,,5.0 +201000587,740000000,801000004,R_000009,,, +201000587,620000000,801000005,R_000010,,, +201000596,201000597,801000001,R_000011,1,个, +201000596,201000598,801000001,R_000012,50,毫升, +201000596,201000599,801000001,R_000013,2,克, +201000596,201000600,801000001,R_000014,适量,, +201000596,201000601,801000003,R_000015,,,1.0 +201000596,201000602,801000003,R_000016,,,2.0 +201000596,201000603,801000003,R_000017,,,3.0 +201000596,201000604,801000003,R_000018,,,4.0 +201000596,740000000,801000004,R_000019,,, +201000596,620000000,801000005,R_000020,,, +201000605,201000606,801000001,R_000021,1,颗, +201000605,201000607,801000001,R_000022,2,公分, +201000605,201000608,801000003,R_000023,,,1.0 +201000605,201000609,801000003,R_000024,,,2.0 +201000605,201000610,801000003,R_000025,,,3.0 +201000605,201000611,801000003,R_000026,,,4.0 +201000605,201000612,801000003,R_000027,,,5.0 +201000605,740000000,801000004,R_000028,,, +201000605,630000000,801000005,R_000029,,, +201000613,201000614,801000001,R_000030,10-15,个, +201000613,201000615,801000001,R_000031,10-15,毫升, +201000613,201000616,801000001,R_000032,没过饺子高度1/2,毫升, +201000613,201000617,801000001,R_000033,适量,, +201000613,201000618,801000001,R_000034,适量,, +201000613,201000619,801000003,R_000035,,,1.0 +201000613,201000620,801000003,R_000036,,,2.0 +201000613,201000621,801000003,R_000037,,,3.0 +201000613,201000622,801000003,R_000038,,,4.0 +201000613,201000623,801000003,R_000039,,,5.0 +201000613,201000624,801000003,R_000040,,,6.0 +201000613,201000625,801000003,R_000041,,,7.0 +201000613,201000626,801000003,R_000042,,,8.0 +201000613,201000627,801000003,R_000043,,,9.0 +201000613,740000000,801000004,R_000044,,, +201000613,620000000,801000005,R_000045,,, +201000628,201000629,801000001,R_000046,2,个, +201000628,201000630,801000001,R_000047,50,克, +201000628,201000631,801000001,R_000048,50,毫升, +201000628,201000632,801000001,R_000049,50,克, +201000628,201000633,801000001,R_000050,适量,克, +201000628,201000634,801000001,R_000051,适量,克, +201000628,201000635,801000001,R_000052,适量,克, +201000628,201000636,801000003,R_000053,,,1.0 +201000628,201000637,801000003,R_000054,,,2.0 +201000628,201000638,801000003,R_000055,,,3.0 +201000628,201000639,801000003,R_000056,,,4.0 +201000628,201000640,801000003,R_000057,,,5.0 +201000628,201000641,801000003,R_000058,,,6.0 +201000628,201000642,801000003,R_000059,,,7.0 +201000628,201000643,801000003,R_000060,,,8.0 +201000628,740000000,801000004,R_000061,,, +201000628,620000000,801000005,R_000062,,, +201000644,201000645,801000001,R_000063,280,ml, +201000644,201000646,801000001,R_000064,40,g, +201000644,201000647,801000001,R_000065,1,个, +201000644,201000648,801000001,R_000066,3,g, +201000644,201000649,801000003,R_000067,,,1.0 +201000644,201000650,801000003,R_000068,,,2.0 +201000644,201000651,801000003,R_000069,,,3.0 +201000644,201000652,801000003,R_000070,,,4.0 +201000644,201000653,801000003,R_000071,,,5.0 +201000644,201000654,801000003,R_000072,,,6.0 +201000644,740000000,801000004,R_000073,,, +201000644,610000000,801000005,R_000074,,, +201000655,201000656,801000001,R_000075,2,片, +201000655,201000657,801000003,R_000076,,,1.0 +201000655,201000658,801000003,R_000077,,,2.0 +201000655,201000659,801000003,R_000078,,,3.0 +201000655,201000660,801000003,R_000079,,,4.0 +201000655,740000000,801000004,R_000080,,, +201000655,610000000,801000005,R_000081,,, +201000661,201000662,801000001,R_000082,3,个, +201000661,201000663,801000001,R_000083,10,克, +201000661,201000664,801000001,R_000084,5,克, +201000661,201000665,801000001,R_000085,1,克, +201000661,201000666,801000003,R_000086,,,1.0 +201000661,201000667,801000003,R_000087,,,2.0 +201000661,201000668,801000003,R_000088,,,3.0 +201000661,201000669,801000003,R_000089,,,4.0 +201000661,740000000,801000004,R_000090,,, +201000661,620000000,801000005,R_000091,,, +201000670,201000671,801000001,R_000092,400,g, +201000670,201000672,801000001,R_000093,4,g, +201000670,201000673,801000001,R_000094,0.5,g, +201000670,201000674,801000001,R_000095,3,g, +201000670,201000675,801000001,R_000096,5,g, +201000670,201000676,801000001,R_000097,15,g, +201000670,201000677,801000001,R_000098,20,g, +201000670,201000678,801000001,R_000099,15,g, +201000670,201000679,801000001,R_000100,25,g, +201000670,201000680,801000001,R_000101,3,g, +201000670,201000681,801000003,R_000102,,,1.0 +201000670,201000682,801000003,R_000103,,,2.0 +201000670,201000683,801000003,R_000104,,,3.0 +201000670,201000684,801000003,R_000105,,,4.0 +201000670,201000685,801000003,R_000106,,,5.0 +201000670,201000686,801000003,R_000107,,,6.0 +201000670,740000000,801000004,R_000108,,, +201000670,630000000,801000005,R_000109,,, +201000687,201000688,801000001,R_000110,2,个, +201000687,201000689,801000001,R_000111,2,克, +201000687,201000690,801000001,R_000112,260,毫升, +201000687,201000691,801000003,R_000113,,,1.0 +201000687,201000692,801000003,R_000114,,,2.0 +201000687,201000693,801000003,R_000115,,,3.0 +201000687,201000694,801000003,R_000116,,,4.0 +201000687,201000695,801000003,R_000117,,,5.0 +201000687,740000000,801000004,R_000118,,, +201000687,620000000,801000005,R_000119,,, +201000696,201000697,801000001,R_000001,5,个, +201000696,201000698,801000001,R_000002,400,毫升, +201000696,201000699,801000003,R_000003,,,1.0 +201000696,201000700,801000003,R_000004,,,2.0 +201000696,201000701,801000003,R_000005,,,3.0 +201000696,201000702,801000003,R_000006,,,4.0 +201000696,201000703,801000003,R_000007,,,5.0 +201000696,201000704,801000003,R_000008,,,6.0 +201000696,201000705,801000003,R_000009,,,7.0 +201000696,740000000,801000004,R_000010,,, +201000696,620000000,801000005,R_000011,,, +201000706,201000707,801000001,R_000012,2,块, +201000706,201000708,801000001,R_000013,1,个, +201000706,201000709,801000001,R_000014,10,克, +201000706,201000710,801000001,R_000015,10,毫升, +201000706,201000711,801000001,R_000016,2,克, +201000706,201000712,801000003,R_000017,,,1.0 +201000706,201000713,801000003,R_000018,,,2.0 +201000706,201000714,801000003,R_000019,,,3.0 +201000706,201000715,801000003,R_000020,,,4.0 +201000706,201000716,801000003,R_000021,,,5.0 +201000706,201000717,801000003,R_000022,,,6.0 +201000706,740000000,801000004,R_000023,,, +201000706,620000000,801000005,R_000024,,, +201000718,201000719,801000001,R_000025,65,g, +201000718,201000720,801000001,R_000026,2,片, +201000718,201000721,801000001,R_000027,50,mL, +201000718,201000722,801000001,R_000028,10-15,mL, +201000718,201000723,801000001,R_000029,1,片, +201000718,201000724,801000001,R_000030,1,片, +201000718,201000725,801000003,R_000031,,,1.0 +201000718,201000726,801000003,R_000032,,,2.0 +201000718,201000727,801000003,R_000033,,,3.0 +201000718,201000728,801000003,R_000034,,,4.0 +201000718,201000729,801000003,R_000035,,,5.0 +201000718,740000000,801000004,R_000036,,, +201000718,610000000,801000005,R_000037,,, +201000730,201000731,801000001,R_000038,1,个, +201000730,201000732,801000001,R_000039,2,片, +201000730,201000733,801000001,R_000040,2,片, +201000730,201000734,801000001,R_000041,10,g, +201000730,201000735,801000001,R_000042,20,g, +201000730,201000736,801000001,R_000043,1,g, +201000730,201000737,801000001,R_000044,2,g, +201000730,201000738,801000003,R_000045,,,1.0 +201000730,201000739,801000003,R_000046,,,2.0 +201000730,201000740,801000003,R_000047,,,3.0 +201000730,201000741,801000003,R_000048,,,4.0 +201000730,201000742,801000003,R_000049,,,5.0 +201000730,201000743,801000003,R_000050,,,6.0 +201000730,740000000,801000004,R_000051,,, +201000730,620000000,801000005,R_000052,,, +201000744,201000745,801000001,R_000053,1,个, +201000744,201000746,801000001,R_000054,适量,, +201000744,201000747,801000001,R_000055,适量,, +201000744,201000748,801000003,R_000056,,,1.0 +201000744,201000749,801000003,R_000057,,,2.0 +201000744,201000750,801000003,R_000058,,,3.0 +201000744,201000751,801000003,R_000059,,,4.0 +201000744,201000752,801000003,R_000060,,,5.0 +201000744,201000753,801000003,R_000061,,,6.0 +201000744,201000754,801000003,R_000062,,,7.0 +201000744,740000000,801000004,R_000063,,, +201000744,630000000,801000005,R_000064,,, +201000755,201000756,801000001,R_000065,50,克, +201000755,201000757,801000001,R_000066,1.5,份, +201000755,201000758,801000001,R_000067,1.5,片, +201000755,201000759,801000001,R_000068,1.5,片, +201000755,201000760,801000003,R_000069,,,1.0 +201000755,201000761,801000003,R_000070,,,2.0 +201000755,201000762,801000003,R_000071,,,3.0 +201000755,201000763,801000003,R_000072,,,4.0 +201000755,201000764,801000003,R_000073,,,5.0 +201000755,201000765,801000003,R_000074,,,6.0 +201000755,201000766,801000003,R_000075,,,7.0 +201000755,201000767,801000003,R_000076,,,8.0 +201000755,740000000,801000004,R_000077,,, +201000755,630000000,801000005,R_000078,,, +201000768,201000769,801000001,R_000079,烙饼张数/0.13,克, +201000768,201000770,801000001,R_000080,烙饼张数*10,毫升, +201000768,201000771,801000001,R_000081,烙饼张数/2,克, +201000768,201000772,801000003,R_000082,,,1.0 +201000768,201000773,801000003,R_000083,,,2.0 +201000768,201000774,801000003,R_000084,,,3.0 +201000768,790000000,801000004,R_000085,,, +201000768,620000000,801000005,R_000086,,, +201000775,201000776,801000001,R_000087,60,克, +201000775,201000777,801000001,R_000088,20,克, +201000775,201000778,801000001,R_000089,10,克, +201000775,201000779,801000001,R_000090,15,克, +201000775,201000780,801000001,R_000091,20,克, +201000775,201000781,801000001,R_000092,15,克, +201000775,201000782,801000001,R_000093,8,克, +201000775,201000783,801000001,R_000094,5,克, +201000775,201000784,801000001,R_000095,5,克, +201000775,201000785,801000001,R_000096,30,克, +201000775,201000786,801000001,R_000097,10,毫升, +201000775,201000787,801000001,R_000098,10,毫升, +201000775,201000788,801000001,R_000099,10,毫升, +201000775,201000789,801000001,R_000100,10,毫升, +201000775,201000790,801000003,R_000101,,,1.0 +201000775,201000791,801000003,R_000102,,,2.0 +201000775,201000792,801000003,R_000103,,,3.0 +201000775,201000793,801000003,R_000104,,,4.0 +201000775,790000000,801000004,R_000105,,, +201000775,620000000,801000005,R_000106,,, +201000794,201000795,801000001,R_000107,100,克, +201000794,201000796,801000001,R_000108,100,毫升, +201000794,201000797,801000001,R_000109,500,毫升, +201000794,201000798,801000003,R_000110,,,1.0 +201000794,201000799,801000003,R_000111,,,2.0 +201000794,201000800,801000003,R_000112,,,3.0 +201000794,201000801,801000003,R_000113,,,4.0 +201000794,201000802,801000003,R_000114,,,5.0 +201000794,201000803,801000003,R_000115,,,6.0 +201000794,201000804,801000003,R_000116,,,7.0 +201000794,790000000,801000004,R_000117,,, +201000794,640000000,801000005,R_000118,,, +201000805,201000806,801000001,R_000119,50,毫升, +201000805,201000807,801000001,R_000120,40,毫升, +201000805,201000808,801000001,R_000121,30,克, +201000805,201000809,801000001,R_000122,20,毫升, +201000805,201000810,801000001,R_000123,10,毫升, +201000805,201000811,801000003,R_000124,,,1.0 +201000805,201000812,801000003,R_000125,,,2.0 +201000805,201000813,801000003,R_000126,,,3.0 +201000805,201000814,801000003,R_000127,,,4.0 +201000805,790000000,801000004,R_000128,,, +201000805,620000000,801000005,R_000129,,, +201000815,201000816,801000001,R_000001,200,g, +201000815,201000817,801000001,R_000002,80,g, +201000815,201000818,801000001,R_000003,20,g, +201000815,201000819,801000001,R_000004,10,ml, +201000815,201000820,801000001,R_000005,150,g, +201000815,201000821,801000001,R_000006,适量,g, +201000815,201000822,801000001,R_000007,50,g, +201000815,201000823,801000003,R_000008,,,1.0 +201000815,201000824,801000003,R_000009,,,2.0 +201000815,201000825,801000003,R_000010,,,3.0 +201000815,201000826,801000003,R_000011,,,4.0 +201000815,201000827,801000003,R_000012,,,5.0 +201000815,790000000,801000004,R_000013,,, +201000815,630000000,801000005,R_000014,,, +201000828,201000829,801000001,R_000015,2,瓣, +201000828,201000830,801000001,R_000016,5,克, +201000828,201000831,801000001,R_000017,15,毫升, +201000828,201000832,801000001,R_000018,30,毫升, +201000828,201000833,801000001,R_000019,1,个, +201000828,201000834,801000003,R_000020,,,1.0 +201000828,201000835,801000003,R_000021,,,2.0 +201000828,201000836,801000003,R_000022,,,3.0 +201000828,201000837,801000003,R_000023,,,4.0 +201000828,790000000,801000004,R_000024,,, +201000828,620000000,801000005,R_000025,,, +201000838,201000839,801000001,R_000026,100,克, +201000838,201000840,801000001,R_000027,150,毫升, +201000838,201000841,801000001,R_000028,15,克, +201000838,201000842,801000001,R_000029,1,个, +201000838,201000843,801000001,R_000030,1,个, +201000838,201000844,801000001,R_000031,5,克, +201000838,201000845,801000001,R_000032,30,克, +201000838,201000846,801000001,R_000033,5,毫升, +201000838,201000847,801000001,R_000034,10,克, +201000838,201000848,801000001,R_000035,1,个, +201000838,201000849,801000001,R_000036,3-5,根, +201000838,201000850,801000001,R_000037,1,个, +201000838,201000851,801000001,R_000038,20-50,粒, +201000838,201000852,801000001,R_000039,2-3,片, +201000838,201000853,801000001,R_000040,2-3,片, +201000838,201000854,801000001,R_000041,大拇指粗细,片, +201000838,201000855,801000003,R_000042,,,1.0 +201000838,201000856,801000003,R_000043,,,2.0 +201000838,201000857,801000003,R_000044,,,3.0 +201000838,201000858,801000003,R_000045,,,4.0 +201000838,201000859,801000003,R_000046,,,5.0 +201000838,201000860,801000003,R_000047,,,6.0 +201000838,201000861,801000003,R_000048,,,7.0 +201000838,201000862,801000003,R_000049,,,8.0 +201000838,201000863,801000003,R_000050,,,9.0 +201000838,201000864,801000003,R_000051,,,10.0 +201000838,201000865,801000003,R_000052,,,11.0 +201000838,790000000,801000004,R_000053,,, +201000838,630000000,801000005,R_000054,,, +201000866,201000867,801000001,R_000055,1200,克, +201000866,201000868,801000001,R_000056,400,克, +201000866,201000869,801000001,R_000057,1,张, +201000866,201000870,801000003,R_000058,,,1.0 +201000866,201000871,801000003,R_000059,,,2.0 +201000866,201000872,801000003,R_000060,,,3.0 +201000866,201000873,801000003,R_000061,,,4.0 +201000866,201000874,801000003,R_000062,,,5.0 +201000866,201000875,801000003,R_000063,,,6.0 +201000866,201000876,801000003,R_000064,,,7.0 +201000866,790000000,801000004,R_000065,,, +201000866,620000000,801000005,R_000066,,, +201000877,201000878,801000001,R_000067,100,克, +201000877,201000879,801000001,R_000068,100,克, +201000877,201000880,801000003,R_000069,,,1.0 +201000877,201000881,801000003,R_000070,,,2.0 +201000877,790000000,801000004,R_000071,,, +201000877,610000000,801000005,R_000072,,, +201000882,201000883,801000001,R_000073,200,克, +201000882,201000884,801000001,R_000074,30,克, +201000882,201000885,801000001,R_000075,15,克, +201000882,201000886,801000001,R_000076,适量,克, +201000882,201000887,801000003,R_000077,,,1.0 +201000882,201000888,801000003,R_000078,,,2.0 +201000882,201000889,801000003,R_000079,,,3.0 +201000882,201000890,801000003,R_000080,,,4.0 +201000882,201000891,801000003,R_000081,,,5.0 +201000882,201000892,801000003,R_000082,,,6.0 +201000882,201000893,801000003,R_000083,,,7.0 +201000882,770000000,801000004,R_000084,,, +201000882,630000000,801000005,R_000085,,, +201000894,201000895,801000001,R_000086,125,ml, +201000894,201000896,801000001,R_000087,250,ml, +201000894,201000897,801000001,R_000088,35,ml, +201000894,201000898,801000001,R_000089,50,ml, +201000894,201000899,801000001,R_000090,10,g, +201000894,201000900,801000001,R_000091,可选,, +201000894,201000901,801000001,R_000092,适量,, +201000894,201000902,801000001,R_000093,适量,, +201000894,201000903,801000003,R_000094,,,1.0 +201000894,201000904,801000003,R_000095,,,2.0 +201000894,201000905,801000003,R_000096,,,3.0 +201000894,201000906,801000003,R_000097,,,4.0 +201000894,201000907,801000003,R_000098,,,5.0 +201000894,201000908,801000003,R_000099,,,6.0 +201000894,201000909,801000003,R_000100,,,7.0 +201000894,201000910,801000003,R_000101,,,8.0 +201000894,770000000,801000004,R_000102,,, +201000894,640000000,801000005,R_000103,,, +201000911,201000912,801000001,R_000104,6,块, +201000911,201000913,801000001,R_000105,18,克, +201000911,201000914,801000001,R_000106,250,毫升, +201000911,201000915,801000003,R_000107,,,1.0 +201000911,201000916,801000003,R_000108,,,2.0 +201000911,201000917,801000003,R_000109,,,3.0 +201000911,201000918,801000003,R_000110,,,4.0 +201000911,201000919,801000003,R_000111,,,5.0 +201000911,201000920,801000003,R_000112,,,6.0 +201000911,201000921,801000003,R_000113,,,7.0 +201000911,770000000,801000004,R_000114,,, +201000911,630000000,801000005,R_000115,,, +201000922,201000923,801000001,R_000116,3,个, +201000922,201000924,801000001,R_000117,50,g, +201000922,201000925,801000001,R_000118,30,g, +201000922,201000926,801000001,R_000119,25,g, +201000922,201000927,801000001,R_000120,50,g, +201000922,201000928,801000001,R_000121,少许,, +201000922,201000929,801000003,R_000122,,,1.0 +201000922,201000930,801000003,R_000123,,,2.0 +201000922,201000931,801000003,R_000124,,,3.0 +201000922,201000932,801000003,R_000125,,,4.0 +201000922,201000933,801000003,R_000126,,,5.0 +201000922,201000934,801000003,R_000127,,,6.0 +201000922,770000000,801000004,R_000128,,, +201000922,650000000,801000005,R_000129,,, +201000935,201000936,801000001,R_000130,450,g, +201000935,201000937,801000001,R_000131,1,包, +201000935,201000938,801000001,R_000132,350,ml, +201000935,201000939,801000001,R_000133,4,个, +201000935,201000940,801000001,R_000134,50,g, +201000935,201000941,801000001,R_000135,10,g, +201000935,201000942,801000001,R_000136,35,ml, +201000935,201000943,801000003,R_000137,,,1.0 +201000935,201000944,801000003,R_000138,,,2.0 +201000935,201000945,801000003,R_000139,,,3.0 +201000935,201000946,801000003,R_000140,,,4.0 +201000935,201000947,801000003,R_000141,,,5.0 +201000935,201000948,801000003,R_000142,,,6.0 +201000935,201000949,801000003,R_000143,,,7.0 +201000935,201000950,801000003,R_000144,,,8.0 +201000935,201000951,801000003,R_000145,,,9.0 +201000935,201000952,801000003,R_000146,,,10.0 +201000935,770000000,801000004,R_000147,,, +201000935,640000000,801000005,R_000148,,, +201000953,201000954,801000001,R_000001,400,g, +201000953,201000955,801000001,R_000002,200,g, +201000953,201000956,801000001,R_000003,4,g, +201000953,201000957,801000001,R_000004,1,个, +201000953,201000958,801000001,R_000005,70,g, +201000953,201000959,801000001,R_000006,2,g, +201000953,201000960,801000001,R_000007,30,g, +201000953,201000961,801000001,R_000008,20,g, +201000953,201000962,801000001,R_000009,20,g, +201000953,201000963,801000001,R_000010,适量,, +201000953,201000964,801000001,R_000011,适量,, +201000953,201000965,801000001,R_000012,适量,, +201000953,201000966,801000003,R_000013,,,1.0 +201000953,201000967,801000003,R_000014,,,2.0 +201000953,201000968,801000003,R_000015,,,3.0 +201000953,201000969,801000003,R_000016,,,4.0 +201000953,201000970,801000003,R_000017,,,5.0 +201000953,201000971,801000003,R_000018,,,6.0 +201000953,201000972,801000003,R_000019,,,7.0 +201000953,201000973,801000003,R_000020,,,8.0 +201000953,201000974,801000003,R_000021,,,9.0 +201000953,201000975,801000003,R_000022,,,10.0 +201000953,201000976,801000003,R_000023,,,11.0 +201000953,201000977,801000003,R_000024,,,12.0 +201000953,201000978,801000003,R_000025,,,13.0 +201000953,770000000,801000004,R_000026,,, +201000953,650000000,801000005,R_000027,,, +201000979,201000980,801000001,R_000028,250,g, +201000979,201000981,801000001,R_000029,30,g, +201000979,201000982,801000001,R_000030,100,g, +201000979,201000983,801000001,R_000031,2,个, +201000979,201000984,801000001,R_000032,30,g, +201000979,201000985,801000001,R_000033,适量,, +201000979,201000986,801000003,R_000034,,,1.0 +201000979,201000987,801000003,R_000035,,,2.0 +201000979,201000988,801000003,R_000036,,,3.0 +201000979,201000989,801000003,R_000037,,,4.0 +201000979,201000990,801000003,R_000038,,,5.0 +201000979,201000991,801000003,R_000039,,,6.0 +201000979,201000992,801000003,R_000040,,,7.0 +201000979,201000993,801000003,R_000041,,,8.0 +201000979,201000994,801000003,R_000042,,,9.0 +201000979,201000995,801000003,R_000043,,,10.0 +201000979,201000996,801000003,R_000044,,,11.0 +201000979,201000997,801000003,R_000045,,,12.0 +201000979,201000998,801000003,R_000046,,,13.0 +201000979,770000000,801000004,R_000047,,, +201000979,630000000,801000005,R_000048,,, +201000999,201001000,801000001,R_000049,30,个, +201000999,201001001,801000001,R_000050,8,个, +201000999,201001002,801000001,R_000051,200,毫升, +201000999,201001003,801000001,R_000052,450,毫升, +201000999,201001004,801000001,R_000053,80,克, +201000999,201001005,801000003,R_000054,,,1.0 +201000999,201001006,801000003,R_000055,,,2.0 +201000999,201001007,801000003,R_000056,,,3.0 +201000999,201001008,801000003,R_000057,,,4.0 +201000999,201001009,801000003,R_000058,,,5.0 +201000999,201001010,801000003,R_000059,,,6.0 +201000999,201001011,801000003,R_000060,,,7.0 +201000999,201001012,801000003,R_000061,,,8.0 +201000999,201001013,801000003,R_000062,,,9.0 +201000999,201001014,801000003,R_000063,,,10.0 +201000999,201001015,801000003,R_000064,,,11.0 +201000999,201001016,801000003,R_000065,,,12.0 +201000999,770000000,801000004,R_000066,,, +201000999,640000000,801000005,R_000067,,, +201001017,201001018,801000001,R_000068,1,个, +201001017,201001019,801000001,R_000069,50,克, +201001017,201001020,801000001,R_000070,20,克, +201001017,201001021,801000001,R_000071,1,克, +201001017,201001022,801000001,R_000072,50,克, +201001017,201001023,801000001,R_000073,50,克, +201001017,201001024,801000003,R_000074,,,1.0 +201001017,201001025,801000003,R_000075,,,2.0 +201001017,201001026,801000003,R_000076,,,3.0 +201001017,201001027,801000003,R_000077,,,4.0 +201001017,201001028,801000003,R_000078,,,5.0 +201001017,201001029,801000003,R_000079,,,6.0 +201001017,201001030,801000003,R_000080,,,7.0 +201001017,770000000,801000004,R_000081,,, +201001017,630000000,801000005,R_000082,,, +201001031,201001032,801000001,R_000083,2,个, +201001031,201001033,801000001,R_000084,80,克, +201001031,201001034,801000001,R_000085,20,克, +201001031,201001035,801000001,R_000086,15,毫升, +201001031,201001036,801000001,R_000087,80,毫升, +201001031,201001037,801000001,R_000088,15,克, +201001031,201001038,801000003,R_000089,,,1.0 +201001031,201001039,801000003,R_000090,,,2.0 +201001031,201001040,801000003,R_000091,,,3.0 +201001031,201001041,801000003,R_000092,,,4.0 +201001031,201001042,801000003,R_000093,,,5.0 +201001031,201001043,801000003,R_000094,,,6.0 +201001031,201001044,801000003,R_000095,,,7.0 +201001031,201001045,801000003,R_000096,,,8.0 +201001031,201001046,801000003,R_000097,,,9.0 +201001031,201001047,801000003,R_000098,,,10.0 +201001031,770000000,801000004,R_000099,,, +201001031,630000000,801000005,R_000100,,, +201001048,201001049,801000001,R_000101,200,g, +201001048,201001050,801000001,R_000102,3,g, +201001048,201001051,801000001,R_000103,165,g, +201001048,201001052,801000001,R_000104,50,g, +201001048,201001053,801000001,R_000105,75,g, +201001048,201001054,801000001,R_000106,22,g, +201001048,201001055,801000001,R_000107,30,g, +201001048,201001056,801000001,R_000108,145,g, +201001048,201001057,801000001,R_000109,26,g, +201001048,201001058,801000003,R_000110,,,1.0 +201001048,201001059,801000003,R_000111,,,2.0 +201001048,201001060,801000003,R_000112,,,3.0 +201001048,201001061,801000003,R_000113,,,4.0 +201001048,201001062,801000003,R_000114,,,5.0 +201001048,201001063,801000003,R_000115,,,6.0 +201001048,201001064,801000003,R_000116,,,7.0 +201001048,201001065,801000003,R_000117,,,8.0 +201001048,201001066,801000003,R_000118,,,9.0 +201001048,201001067,801000003,R_000119,,,10.0 +201001048,201001068,801000003,R_000120,,,11.0 +201001048,770000000,801000004,R_000121,,, +201001048,650000000,801000005,R_000122,,, +201001069,201001070,801000001,R_000123,40,g, +201001069,201001071,801000001,R_000124,180,g, +201001069,201001072,801000001,R_000125,30,g, +201001069,201001073,801000001,R_000126,1,g, +201001069,201001074,801000001,R_000127,5,g, +201001069,201001075,801000001,R_000128,1,个, +201001069,201001076,801000001,R_000129,45,g, +201001069,201001077,801000001,R_000130,50,g, +201001069,201001078,801000003,R_000131,,,1.0 +201001069,201001079,801000003,R_000132,,,2.0 +201001069,201001080,801000003,R_000133,,,3.0 +201001069,201001081,801000003,R_000134,,,4.0 +201001069,201001082,801000003,R_000135,,,5.0 +201001069,201001083,801000003,R_000136,,,6.0 +201001069,201001084,801000003,R_000137,,,7.0 +201001069,770000000,801000004,R_000138,,, +201001069,630000000,801000005,R_000139,,, +201001085,201001086,801000001,R_000140,500,克, +201001085,201001087,801000001,R_000141,45,克, +201001085,201001088,801000001,R_000142,6,克, +201001085,201001089,801000001,R_000143,2,克, +201001085,201001090,801000001,R_000144,6,克, +201001085,201001091,801000001,R_000145,400,克, +201001085,201001092,801000003,R_000146,,,1.0 +201001085,201001093,801000003,R_000147,,,2.0 +201001085,201001094,801000003,R_000148,,,3.0 +201001085,201001095,801000003,R_000149,,,4.0 +201001085,201001096,801000003,R_000150,,,5.0 +201001085,770000000,801000004,R_000151,,, +201001085,620000000,801000005,R_000152,,, +201001097,201001098,801000001,R_000153,200,g, +201001097,201001099,801000001,R_000154,40,g, +201001097,201001100,801000001,R_000155,250,g, +201001097,201001101,801000001,R_000156,6,g, +201001097,201001102,801000003,R_000157,,,1.0 +201001097,201001103,801000003,R_000158,,,2.0 +201001097,201001104,801000003,R_000159,,,3.0 +201001097,201001105,801000003,R_000160,,,4.0 +201001097,201001106,801000003,R_000161,,,5.0 +201001097,201001107,801000003,R_000162,,,6.0 +201001097,770000000,801000004,R_000163,,, +201001097,640000000,801000005,R_000164,,, +201001108,201001109,801000001,R_000165,20,g, +201001108,201001110,801000001,R_000166,75,g, +201001108,201001111,801000001,R_000167,40,g, +201001108,201001112,801000001,R_000168,60,g, +201001108,201001113,801000001,R_000169,75,g, +201001108,201001114,801000003,R_000170,,,1.0 +201001108,201001115,801000003,R_000171,,,2.0 +201001108,201001116,801000003,R_000172,,,3.0 +201001108,201001117,801000003,R_000173,,,4.0 +201001108,201001118,801000003,R_000174,,,5.0 +201001108,201001119,801000003,R_000175,,,6.0 +201001108,201001120,801000003,R_000176,,,7.0 +201001108,201001121,801000003,R_000177,,,8.0 +201001108,770000000,801000004,R_000178,,, +201001108,630000000,801000005,R_000179,,, +201001122,201001123,801000001,R_000001,3,个, +201001122,201001124,801000001,R_000002,50,克, +201001122,201001125,801000001,R_000003,10,克, +201001122,201001126,801000001,R_000004,10,克, +201001122,201001127,801000001,R_000005,1,克, +201001122,201001128,801000003,R_000006,,,1.0 +201001122,201001129,801000003,R_000007,,,2.0 +201001122,201001130,801000003,R_000008,,,3.0 +201001122,201001131,801000003,R_000009,,,4.0 +201001122,201001132,801000003,R_000010,,,5.0 +201001122,201001133,801000003,R_000011,,,6.0 +201001122,201001134,801000003,R_000012,,,7.0 +201001122,201001135,801000003,R_000013,,,8.0 +201001122,770000000,801000004,R_000014,,, +201001122,640000000,801000005,R_000015,,, +201001136,201001137,801000001,R_000016,25,克, +201001136,201001138,801000001,R_000017,120,毫升, +201001136,201001139,801000001,R_000018,500,毫升, +201001136,201001140,801000001,R_000019,100,克, +201001136,201001141,801000003,R_000020,,,1.0 +201001136,201001142,801000003,R_000021,,,2.0 +201001136,201001143,801000003,R_000022,,,3.0 +201001136,201001144,801000003,R_000023,,,4.0 +201001136,201001145,801000003,R_000024,,,5.0 +201001136,201001146,801000003,R_000025,,,6.0 +201001136,770000000,801000004,R_000026,,, +201001136,620000000,801000005,R_000027,,, +201001147,201001148,801000001,R_000028,10,毫升, +201001147,201001149,801000001,R_000029,10,毫升, +201001147,201001150,801000001,R_000030,10,毫升, +201001147,201001151,801000003,R_000031,,,1.0 +201001147,201001152,801000003,R_000032,,,2.0 +201001147,201001153,801000003,R_000033,,,3.0 +201001147,201001154,801000003,R_000034,,,4.0 +201001147,201001155,801000003,R_000035,,,5.0 +201001147,780000000,801000004,R_000036,,, +201001147,630000000,801000005,R_000037,,, +201001156,201001157,801000001,R_000038,1,块, +201001156,201001158,801000001,R_000039,5,珠, +201001156,201001159,801000001,R_000040,20,毫升, +201001156,201001160,801000001,R_000041,45,毫升, +201001156,201001161,801000001,R_000042,10,毫升, +201001156,201001162,801000001,R_000043,1,杯, +201001156,201001163,801000001,R_000044,1,杯, +201001156,201001164,801000003,R_000045,,,1.0 +201001156,201001165,801000003,R_000046,,,2.0 +201001156,201001166,801000003,R_000047,,,3.0 +201001156,201001167,801000003,R_000048,,,4.0 +201001156,201001168,801000003,R_000049,,,5.0 +201001156,201001169,801000003,R_000050,,,6.0 +201001156,201001170,801000003,R_000051,,,7.0 +201001156,201001171,801000003,R_000052,,,8.0 +201001156,201001172,801000003,R_000053,,,9.0 +201001156,201001173,801000003,R_000054,,,10.0 +201001156,201001174,801000003,R_000055,,,11.0 +201001156,780000000,801000004,R_000056,,, +201001156,630000000,801000005,R_000057,,, +201001175,201001176,801000001,R_000058,1000,g, +201001175,201001177,801000001,R_000059,300,g, +201001175,201001178,801000003,R_000060,,,1.0 +201001175,201001179,801000003,R_000061,,,2.0 +201001175,201001180,801000003,R_000062,,,3.0 +201001175,201001181,801000003,R_000063,,,4.0 +201001175,201001182,801000003,R_000064,,,5.0 +201001175,201001183,801000003,R_000065,,,6.0 +201001175,780000000,801000004,R_000066,,, +201001175,620000000,801000005,R_000067,,, +201001184,201001185,801000001,R_000068,100,毫升, +201001184,201001186,801000001,R_000069,500,毫升, +201001184,201001187,801000001,R_000070,300,克, +201001184,201001188,801000001,R_000071,1,个, +201001184,201001189,801000003,R_000072,,,1.0 +201001184,201001190,801000003,R_000073,,,2.0 +201001184,201001191,801000003,R_000074,,,3.0 +201001184,201001192,801000003,R_000075,,,4.0 +201001184,201001193,801000003,R_000076,,,5.0 +201001184,201001194,801000003,R_000077,,,6.0 +201001184,201001195,801000003,R_000078,,,7.0 +201001184,201001196,801000003,R_000079,,,8.0 +201001184,780000000,801000004,R_000080,,, +201001184,620000000,801000005,R_000081,,, +201001197,201001198,801000001,R_000082,4,克, +201001197,201001199,801000001,R_000083,11.5,克, +201001197,201001200,801000001,R_000084,6,克, +201001197,201001201,801000001,R_000085,190,毫升, +201001197,201001202,801000003,R_000086,,,1.0 +201001197,201001203,801000003,R_000087,,,2.0 +201001197,201001204,801000003,R_000088,,,3.0 +201001197,201001205,801000003,R_000089,,,4.0 +201001197,780000000,801000004,R_000090,,, +201001197,620000000,801000005,R_000091,,, +201001206,201001207,801000001,R_000092,24,g, +201001206,201001208,801000001,R_000093,50,ml, +201001206,201001209,801000001,R_000094,2,小块, +201001206,201001210,801000001,R_000095,1,粒, +201001206,201001211,801000001,R_000096,0.5,粒, +201001206,201001212,801000001,R_000097,150,ml, +201001206,201001213,801000001,R_000098,适量,, +201001206,201001214,801000001,R_000099,适量,, +201001206,201001215,801000003,R_000100,,,1.0 +201001206,201001216,801000003,R_000101,,,2.0 +201001206,201001217,801000003,R_000102,,,3.0 +201001206,201001218,801000003,R_000103,,,4.0 +201001206,201001219,801000003,R_000104,,,5.0 +201001206,780000000,801000004,R_000105,,, +201001206,620000000,801000005,R_000106,,, +201001220,201001221,801000001,R_000107,1177,克, +201001220,201001222,801000001,R_000108,120,克, +201001220,201001223,801000001,R_000109,9,克, +201001220,201001224,801000001,R_000110,48,克, +201001220,201001225,801000003,R_000111,,,1.0 +201001220,201001226,801000003,R_000112,,,2.0 +201001220,201001227,801000003,R_000113,,,3.0 +201001220,201001228,801000003,R_000114,,,4.0 +201001220,201001229,801000003,R_000115,,,5.0 +201001220,780000000,801000004,R_000116,,, +201001220,610000000,801000005,R_000117,,, +201001230,201001231,801000001,R_000118,15,毫升, +201001230,201001232,801000001,R_000119,15,毫升, +201001230,201001233,801000001,R_000120,15,毫升, +201001230,201001234,801000001,R_000121,15,毫升, +201001230,201001235,801000001,R_000122,15,毫升, +201001230,201001236,801000001,R_000123,1,个, +201001230,201001237,801000001,R_000124,30,毫升, +201001230,201001238,801000001,R_000125,20,毫升, +201001230,201001239,801000001,R_000126,75,毫升, +201001230,201001240,801000001,R_000127,100,克, +201001230,201001241,801000003,R_000128,,,1.0 +201001230,201001242,801000003,R_000129,,,2.0 +201001230,201001243,801000003,R_000130,,,3.0 +201001230,201001244,801000003,R_000131,,,4.0 +201001230,201001245,801000003,R_000132,,,5.0 +201001230,201001246,801000003,R_000133,,,6.0 +201001230,201001247,801000003,R_000134,,,7.0 +201001230,780000000,801000004,R_000135,,, +201001230,620000000,801000005,R_000136,,, +201001248,201001249,801000001,R_000001,200,克, +201001248,201001250,801000001,R_000002,2000,毫升, +201001248,201001251,801000001,R_000003,10,毫升, +201001248,201001252,801000001,R_000004,10,克, +201001248,201001253,801000003,R_000005,,,1.0 +201001248,201001254,801000003,R_000006,,,2.0 +201001248,201001255,801000003,R_000007,,,3.0 +201001248,201001256,801000003,R_000008,,,4.0 +201001248,201001257,801000003,R_000009,,,5.0 +201001248,780000000,801000004,R_000010,,, +201001248,620000000,801000005,R_000011,,, +201001258,201001259,801000001,R_000012,700,毫升, +201001258,201001260,801000001,R_000013,2,个, +201001258,201001261,801000001,R_000014,0.5,个, +201001258,201001262,801000001,R_000015,4,叶, +201001258,201001263,801000001,R_000016,12,克, +201001258,201001264,801000003,R_000017,,,1.0 +201001258,201001265,801000003,R_000018,,,2.0 +201001258,201001266,801000003,R_000019,,,3.0 +201001258,201001267,801000003,R_000020,,,4.0 +201001258,201001268,801000003,R_000021,,,5.0 +201001258,201001269,801000003,R_000022,,,6.0 +201001258,201001270,801000003,R_000023,,,7.0 +201001258,201001271,801000003,R_000024,,,8.0 +201001258,780000000,801000004,R_000025,,, +201001258,610000000,801000005,R_000026,,, +201001272,201001273,801000001,R_000027,42.5,克, +201001272,201001274,801000001,R_000028,42.5,克, +201001272,201001275,801000001,R_000029,几块,, +201001272,201001276,801000003,R_000030,,,1.0 +201001272,201001277,801000003,R_000031,,,2.0 +201001272,201001278,801000003,R_000032,,,3.0 +201001272,201001279,801000003,R_000033,,,4.0 +201001272,201001280,801000003,R_000034,,,5.0 +201001272,201001281,801000003,R_000035,,,6.0 +201001272,780000000,801000004,R_000036,,, +201001272,610000000,801000005,R_000037,,, +201001282,201001283,801000001,R_000038,600,毫升, +201001282,201001284,801000001,R_000039,20,克, +201001282,201001285,801000001,R_000040,24,克, +201001282,201001286,801000001,R_000041,24,克, +201001282,201001287,801000001,R_000042,18,毫升, +201001282,201001288,801000003,R_000043,,,1.0 +201001282,201001289,801000003,R_000044,,,2.0 +201001282,201001290,801000003,R_000045,,,3.0 +201001282,201001291,801000003,R_000046,,,4.0 +201001282,201001292,801000003,R_000047,,,5.0 +201001282,201001293,801000003,R_000048,,,6.0 +201001282,780000000,801000004,R_000049,,, +201001282,630000000,801000005,R_000050,,, +201001294,201001295,801000001,R_000051,15,ml, +201001294,201001296,801000001,R_000052,35~50,ml, +201001294,201001297,801000001,R_000053,50,ml, +201001294,201001298,801000001,R_000054,30,ml, +201001294,201001299,801000001,R_000055,15,ml, +201001294,201001300,801000001,R_000056,15,ml, +201001294,201001301,801000001,R_000057,适量,块, +201001294,201001302,801000001,R_000058,1,片, +201001294,201001303,801000003,R_000059,,,1.0 +201001294,201001304,801000003,R_000060,,,2.0 +201001294,201001305,801000003,R_000061,,,3.0 +201001294,201001306,801000003,R_000062,,,4.0 +201001294,201001307,801000003,R_000063,,,5.0 +201001294,201001308,801000003,R_000064,,,6.0 +201001294,201001309,801000003,R_000065,,,7.0 +201001294,201001310,801000003,R_000066,,,8.0 +201001294,201001311,801000003,R_000067,,,9.0 +201001294,201001312,801000003,R_000068,,,10.0 +201001294,780000000,801000004,R_000069,,, +201001294,630000000,801000005,R_000070,,, +201001313,201001314,801000001,R_000071,3,个, +201001313,201001315,801000001,R_000072,1,个, +201001313,201001316,801000001,R_000073,3,克, +201001313,201001317,801000001,R_000074,240,毫升, +201001313,201001318,801000001,R_000075,30,克, +201001313,201001319,801000001,R_000076,160,克, +201001313,201001320,801000001,R_000077,10,克, +201001313,201001321,801000001,R_000078,1,片, +201001313,201001322,801000001,R_000079,150,毫升, +201001313,201001323,801000003,R_000080,,,1.0 +201001313,201001324,801000003,R_000081,,,2.0 +201001313,201001325,801000003,R_000082,,,3.0 +201001313,201001326,801000003,R_000083,,,4.0 +201001313,201001327,801000003,R_000084,,,5.0 +201001313,201001328,801000003,R_000085,,,6.0 +201001313,201001329,801000003,R_000086,,,7.0 +201001313,201001330,801000003,R_000087,,,8.0 +201001313,201001331,801000003,R_000088,,,9.0 +201001313,201001332,801000003,R_000089,,,10.0 +201001313,780000000,801000004,R_000090,,, +201001313,630000000,801000005,R_000091,,, +201001333,201001334,801000001,R_000092,500,ml, +201001333,201001335,801000001,R_000093,10,g, +201001333,201001336,801000001,R_000094,适量,, +201001333,201001337,801000003,R_000095,,,1.0 +201001333,201001338,801000003,R_000096,,,2.0 +201001333,201001339,801000003,R_000097,,,3.0 +201001333,201001340,801000003,R_000098,,,4.0 +201001333,201001341,801000003,R_000099,,,5.0 +201001333,201001342,801000003,R_000100,,,6.0 +201001333,780000000,801000004,R_000101,,, +201001333,610000000,801000005,R_000102,,, +201001343,201001344,801000001,R_000103,200,克, +201001343,201001345,801000001,R_000104,2,克, +201001343,201001346,801000001,R_000105,60,克, +201001343,201001347,801000001,R_000106,10,克, +201001343,201001348,801000003,R_000107,,,1.0 +201001343,201001349,801000003,R_000108,,,2.0 +201001343,201001350,801000003,R_000109,,,3.0 +201001343,201001351,801000003,R_000110,,,4.0 +201001343,201001352,801000003,R_000111,,,5.0 +201001343,201001353,801000003,R_000112,,,6.0 +201001343,201001354,801000003,R_000113,,,7.0 +201001343,201001355,801000003,R_000114,,,8.0 +201001343,780000000,801000004,R_000115,,, +201001343,620000000,801000005,R_000116,,, +201001356,201001357,801000001,R_000117,30,ml, +201001356,201001358,801000001,R_000118,60,ml, +201001356,201001359,801000001,R_000119,50,g, +201001356,201001360,801000001,R_000120,30,ml, +201001356,201001361,801000001,R_000121,30,ml, +201001356,201001362,801000001,R_000122,10,ml, +201001356,201001363,801000001,R_000123,8,g, +201001356,201001364,801000001,R_000124,0.5,g, +201001356,201001365,801000001,R_000125,5,ml, +201001356,201001366,801000003,R_000126,,,1.0 +201001356,201001367,801000003,R_000127,,,2.0 +201001356,201001368,801000003,R_000128,,,3.0 +201001356,201001369,801000003,R_000129,,,4.0 +201001356,780000000,801000004,R_000130,,, +201001356,630000000,801000005,R_000131,,, +201001370,201001371,801000001,R_000132,800,克, +201001370,201001372,801000001,R_000133,8,克, +201001370,201001373,801000001,R_000134,1320,克, +201001370,201001374,801000003,R_000135,,,1.0 +201001370,201001375,801000003,R_000136,,,2.0 +201001370,201001376,801000003,R_000137,,,3.0 +201001370,201001377,801000003,R_000138,,,4.0 +201001370,201001378,801000003,R_000139,,,5.0 +201001370,201001379,801000003,R_000140,,,6.0 +201001370,201001380,801000003,R_000141,,,7.0 +201001370,201001381,801000003,R_000142,,,8.0 +201001370,780000000,801000004,R_000143,,, +201001370,640000000,801000005,R_000144,,, +201001382,201001383,801000001,R_000001,2000,毫升, +201001382,201001384,801000001,R_000002,25,克, +201001382,201001385,801000001,R_000003,25,克, +201001382,201001386,801000001,R_000004,30,克, +201001382,201001387,801000001,R_000005,100,克, +201001382,201001388,801000001,R_000006,2,克, +201001382,201001389,801000001,R_000007,4,克, +201001382,201001390,801000001,R_000008,1,克, +201001382,201001391,801000001,R_000009,3,克, +201001382,201001392,801000003,R_000010,,,1.0 +201001382,201001393,801000003,R_000011,,,2.0 +201001382,201001394,801000003,R_000012,,,3.0 +201001382,201001395,801000003,R_000013,,,4.0 +201001382,201001396,801000003,R_000014,,,5.0 +201001382,201001397,801000003,R_000015,,,6.0 +201001382,780000000,801000004,R_000016,,, +201001382,640000000,801000005,R_000017,,, +201001398,201001399,801000001,R_000018,30~40,毫升, +201001398,201001400,801000001,R_000019,1,罐, +201001398,201001401,801000001,R_000020,1,个, +201001398,201001402,801000001,R_000021,100,克, +201001398,201001403,801000001,R_000022,1,片, +201001398,201001404,801000003,R_000023,,,1.0 +201001398,201001405,801000003,R_000024,,,2.0 +201001398,201001406,801000003,R_000025,,,3.0 +201001398,201001407,801000003,R_000026,,,4.0 +201001398,201001408,801000003,R_000027,,,5.0 +201001398,201001409,801000003,R_000028,,,6.0 +201001398,201001410,801000003,R_000029,,,7.0 +201001398,201001411,801000003,R_000030,,,8.0 +201001398,201001412,801000003,R_000031,,,9.0 +201001398,201001413,801000003,R_000032,,,10.0 +201001398,201001414,801000003,R_000033,,,11.0 +201001398,780000000,801000004,R_000034,,, +201001398,620000000,801000005,R_000035,,, +201001415,201001416,801000001,R_000036,35,毫升, +201001415,201001417,801000001,R_000037,1,罐, +201001415,201001418,801000001,R_000038,1,个, +201001415,201001419,801000001,R_000039,35,克, +201001415,201001420,801000001,R_000040,100,克, +201001415,201001421,801000001,R_000041,1,片, +201001415,201001422,801000003,R_000042,,,1.0 +201001415,201001423,801000003,R_000043,,,2.0 +201001415,201001424,801000003,R_000044,,,3.0 +201001415,201001425,801000003,R_000045,,,4.0 +201001415,201001426,801000003,R_000046,,,5.0 +201001415,201001427,801000003,R_000047,,,6.0 +201001415,780000000,801000004,R_000048,,, +201001415,620000000,801000005,R_000049,,, +201001428,201001429,801000001,R_000050,1000,克, +201001428,201001430,801000001,R_000051,1000,毫升, +201001428,201001431,801000001,R_000052,2,条, +201001428,201001432,801000001,R_000053,1,条, +201001428,201001433,801000001,R_000054,4,颗, +201001428,201001434,801000001,R_000055,3,厘米, +201001428,201001435,801000001,R_000056,3,颗, +201001428,201001436,801000001,R_000057,2,根, +201001428,201001437,801000001,R_000058,2,根, +201001428,201001438,801000001,R_000059,2,颗, +201001428,201001439,801000001,R_000060,4,厘米, +201001428,201001440,801000001,R_000061,3,颗, +201001428,201001441,801000001,R_000062,3,片, +201001428,201001442,801000001,R_000063,6,条, +201001428,201001443,801000001,R_000064,20,毫升, +201001428,201001444,801000001,R_000065,60,毫升, +201001428,201001445,801000001,R_000066,30,颗, +201001428,201001446,801000001,R_000067,3,克, +201001428,201001447,801000001,R_000068,10,毫升, +201001428,201001448,801000001,R_000069,5,毫升, +201001428,201001449,801000003,R_000070,,,1.0 +201001428,201001450,801000003,R_000071,,,2.0 +201001428,201001451,801000003,R_000072,,,3.0 +201001428,201001452,801000003,R_000073,,,4.0 +201001428,201001453,801000003,R_000074,,,5.0 +201001428,720000000,801000004,R_000075,,, +201001428,640000000,801000005,R_000076,,, +201001454,201001455,801000001,R_000077,1,斤, +201001454,201001456,801000001,R_000078,2,克/斤兔肉, +201001454,201001457,801000001,R_000079,1,克/斤兔肉, +201001454,201001458,801000001,R_000080,5,克/斤兔肉, +201001454,201001459,801000001,R_000081,10,克/斤兔肉, +201001454,201001460,801000001,R_000082,0.9,升/斤兔肉, +201001454,201001461,801000001,R_000083,0.5,头/斤兔肉, +201001454,201001462,801000001,R_000084,0.5,头蒜量, +201001454,201001463,801000001,R_000085,15,克/斤兔肉, +201001454,201001464,801000001,R_000086,1,体积等于兔肉体积, +201001454,201001465,801000001,R_000087,1,小碗/3斤兔肉, +201001454,201001466,801000001,R_000088,1,粒/斤兔肉, +201001454,201001467,801000001,R_000089,1,大拇指长/斤兔肉, +201001454,201001468,801000001,R_000090,5,片/斤兔肉, +201001454,201001469,801000001,R_000091,1,黄豆大小/斤兔肉, +201001454,201001470,801000001,R_000092,2,颗/斤兔肉, +201001454,201001471,801000001,R_000093,15,克/斤兔肉, +201001454,201001472,801000001,R_000094,25,克/斤兔肉, +201001454,201001473,801000003,R_000095,,,1.0 +201001454,201001474,801000003,R_000096,,,2.0 +201001454,201001475,801000003,R_000097,,,3.0 +201001454,201001476,801000003,R_000098,,,4.0 +201001454,201001477,801000003,R_000099,,,5.0 +201001454,201001478,801000003,R_000100,,,6.0 +201001454,201001479,801000003,R_000101,,,7.0 +201001454,201001480,801000003,R_000102,,,8.0 +201001454,201001481,801000003,R_000103,,,9.0 +201001454,201001482,801000003,R_000104,,,10.0 +201001454,720000000,801000004,R_000105,,, +201001454,640000000,801000005,R_000106,,, +201001483,201001484,801000001,R_000107,10,只, +201001483,201001485,801000001,R_000108,500,毫升, +201001483,201001486,801000001,R_000109,10,克, +201001483,201001487,801000001,R_000110,15,克, +201001483,201001488,801000001,R_000111,3,克, +201001483,201001489,801000001,R_000112,2,克, +201001483,201001490,801000001,R_000113,2,片, +201001483,201001491,801000001,R_000114,20,毫升, +201001483,201001492,801000001,R_000115,1,个, +201001483,201001493,801000003,R_000116,,,1.0 +201001483,201001494,801000003,R_000117,,,2.0 +201001483,201001495,801000003,R_000118,,,3.0 +201001483,201001496,801000003,R_000119,,,4.0 +201001483,201001497,801000003,R_000120,,,5.0 +201001483,201001498,801000003,R_000121,,,6.0 +201001483,201001499,801000003,R_000122,,,7.0 +201001483,720000000,801000004,R_000123,,, +201001483,630000000,801000005,R_000124,,, +201001500,201001501,801000001,R_000125,100,克, +201001500,201001502,801000001,R_000126,25,克, +201001500,201001503,801000001,R_000127,75,克, +201001500,201001504,801000001,R_000128,0.25,茶匙, +201001500,201001505,801000001,R_000129,4,汤匙, +201001500,201001506,801000001,R_000130,2,茶匙, +201001500,201001507,801000001,R_000131,1,汤匙, +201001500,201001508,801000001,R_000132,0.5,茶匙, +201001500,201001509,801000001,R_000133,2.5,茶匙, +201001500,201001510,801000001,R_000134,2,汤匙, +201001500,201001511,801000001,R_000135,200,毫升, +201001500,201001512,801000001,R_000136,500,毫升, +201001500,201001513,801000001,R_000137,6,汤匙, +201001500,201001514,801000003,R_000138,,,1.0 +201001500,201001515,801000003,R_000139,,,2.0 +201001500,201001516,801000003,R_000140,,,3.0 +201001500,201001517,801000003,R_000141,,,4.0 +201001500,201001518,801000003,R_000142,,,5.0 +201001500,201001519,801000003,R_000143,,,6.0 +201001500,201001520,801000003,R_000144,,,7.0 +201001500,201001521,801000003,R_000145,,,8.0 +201001500,201001522,801000003,R_000146,,,9.0 +201001500,201001523,801000003,R_000147,,,10.0 +201001500,201001524,801000003,R_000148,,,11.0 +201001500,201001525,801000003,R_000149,,,12.0 +201001500,720000000,801000004,R_000150,,, +201001500,640000000,801000005,R_000151,,, +201001526,201001527,801000001,R_000152,500,克, +201001526,201001528,801000001,R_000153,50,克, +201001526,201001529,801000001,R_000154,10,克, +201001526,201001530,801000001,R_000155,2,克, +201001526,201001531,801000001,R_000156,3,个, +201001526,201001532,801000001,R_000157,15,克, +201001526,201001533,801000001,R_000158,5,克, +201001526,201001534,801000001,R_000159,15,克, +201001526,201001535,801000001,R_000160,1.5,克, +201001526,201001536,801000001,R_000161,10,克, +201001526,201001537,801000001,R_000162,15,克, +201001526,201001538,801000001,R_000163,1,克, +201001526,201001539,801000001,R_000164,200,克, +201001526,201001540,801000001,R_000165,10,克, +201001526,201001541,801000001,R_000166,2000,克, +201001526,201001542,801000003,R_000167,,,1.0 +201001526,201001543,801000003,R_000168,,,2.0 +201001526,201001544,801000003,R_000169,,,3.0 +201001526,201001545,801000003,R_000170,,,4.0 +201001526,201001546,801000003,R_000171,,,5.0 +201001526,201001547,801000003,R_000172,,,6.0 +201001526,201001548,801000003,R_000173,,,7.0 +201001526,201001549,801000003,R_000174,,,8.0 +201001526,720000000,801000004,R_000175,,, +201001526,650000000,801000005,R_000176,,, +201001550,201001551,801000001,R_000177,250,g, +201001550,201001552,801000001,R_000178,2,颗, +201001550,201001553,801000001,R_000179,20,g, +201001550,201001554,801000001,R_000180,3,颗, +201001550,201001555,801000001,R_000181,20,ml, +201001550,201001556,801000001,R_000182,10,g, +201001550,201001557,801000001,R_000183,15,ml, +201001550,201001558,801000001,R_000184,3,g, +201001550,201001559,801000001,R_000185,1,根, +201001550,201001560,801000003,R_000186,,,1.0 +201001550,201001561,801000003,R_000187,,,2.0 +201001550,201001562,801000003,R_000188,,,3.0 +201001550,201001563,801000003,R_000189,,,4.0 +201001550,201001564,801000003,R_000190,,,5.0 +201001550,201001565,801000003,R_000191,,,6.0 +201001550,201001566,801000003,R_000192,,,7.0 +201001550,201001567,801000003,R_000193,,,8.0 +201001550,720000000,801000004,R_000194,,, +201001550,630000000,801000005,R_000195,,, +201001568,201001569,801000001,R_000196,500,g, +201001568,201001570,801000001,R_000197,4,条, +201001568,201001571,801000001,R_000198,4,颗, +201001568,201001572,801000001,R_000199,10,g, +201001568,201001573,801000001,R_000200,10,g, +201001568,201001574,801000001,R_000201,10,ml, +201001568,201001575,801000001,R_000202,10,g, +201001568,201001576,801000001,R_000203,1-2,g, +201001568,201001577,801000001,R_000204,0.5-1,根, +201001568,201001578,801000001,R_000205,2,瓣, +201001568,201001579,801000001,R_000206,15,ml, +201001568,201001580,801000003,R_000207,,,1.0 +201001568,201001581,801000003,R_000208,,,2.0 +201001568,201001582,801000003,R_000209,,,3.0 +201001568,201001583,801000003,R_000210,,,4.0 +201001568,201001584,801000003,R_000211,,,5.0 +201001568,201001585,801000003,R_000212,,,6.0 +201001568,201001586,801000003,R_000213,,,7.0 +201001568,201001587,801000003,R_000214,,,8.0 +201001568,201001588,801000003,R_000215,,,9.0 +201001568,201001589,801000003,R_000216,,,10.0 +201001568,201001590,801000003,R_000217,,,11.0 +201001568,720000000,801000004,R_000218,,, +201001568,630000000,801000005,R_000219,,, +201001591,201001592,801000001,R_000001,20,个, +201001591,201001593,801000001,R_000002,20,ml, +201001591,201001594,801000001,R_000003,200,g, +201001591,201001595,801000001,R_000004,1-2,g, +201001591,201001596,801000001,R_000005,10,ml, +201001591,201001597,801000001,R_000006,10,ml, +201001591,201001598,801000001,R_000007,50,g, +201001591,201001599,801000001,R_000008,10,g, +201001591,201001600,801000001,R_000009,10,g, +201001591,201001601,801000001,R_000010,5,g, +201001591,201001602,801000003,R_000011,,,1.0 +201001591,201001603,801000003,R_000012,,,2.0 +201001591,201001604,801000003,R_000013,,,3.0 +201001591,201001605,801000003,R_000014,,,4.0 +201001591,720000000,801000004,R_000015,,, +201001591,630000000,801000005,R_000016,,, +201001606,201001607,801000001,R_000017,500,克, +201001606,201001608,801000001,R_000018,适量,, +201001606,201001609,801000001,R_000019,20,克, +201001606,201001610,801000001,R_000020,15,克, +201001606,201001611,801000001,R_000021,15,克, +201001606,201001612,801000001,R_000022,4,克, +201001606,201001613,801000001,R_000023,2,克, +201001606,201001614,801000001,R_000024,3,克, +201001606,201001615,801000001,R_000025,5,克, +201001606,201001616,801000001,R_000026,5,克, +201001606,201001617,801000001,R_000027,3,克, +201001606,201001618,801000001,R_000028,3,克, +201001606,201001619,801000001,R_000029,8,克, +201001606,201001620,801000001,R_000030,2,个, +201001606,201001621,801000001,R_000031,30,克, +201001606,201001622,801000001,R_000032,120,克, +201001606,201001623,801000001,R_000033,80,克, +201001606,201001624,801000003,R_000034,,,1.0 +201001606,201001625,801000003,R_000035,,,2.0 +201001606,201001626,801000003,R_000036,,,3.0 +201001606,201001627,801000003,R_000037,,,4.0 +201001606,201001628,801000003,R_000038,,,5.0 +201001606,201001629,801000003,R_000039,,,6.0 +201001606,720000000,801000004,R_000040,,, +201001606,630000000,801000005,R_000041,,, +201001630,201001631,801000001,R_000042,250,g, +201001630,201001632,801000001,R_000043,1,个, +201001630,201001633,801000001,R_000044,0.5,根, +201001630,201001634,801000001,R_000045,1,个, +201001630,201001635,801000001,R_000046,1,瓣, +201001630,201001636,801000001,R_000047,9,ml, +201001630,201001637,801000001,R_000048,3,g, +201001630,201001638,801000001,R_000049,1.5,g, +201001630,201001639,801000003,R_000050,,,1.0 +201001630,201001640,801000003,R_000051,,,2.0 +201001630,201001641,801000003,R_000052,,,3.0 +201001630,201001642,801000003,R_000053,,,4.0 +201001630,201001643,801000003,R_000054,,,5.0 +201001630,720000000,801000004,R_000055,,, +201001630,630000000,801000005,R_000056,,, +201001644,201001645,801000001,R_000057,150,g, +201001644,201001646,801000001,R_000058,6,根, +201001644,201001647,801000001,R_000059,300,ml, +201001644,201001648,801000001,R_000060,50,g, +201001644,201001649,801000001,R_000061,20,ml, +201001644,201001650,801000001,R_000062,10,g, +201001644,201001651,801000001,R_000063,1,个, +201001644,201001652,801000001,R_000064,10,g, +201001644,201001653,801000001,R_000065,20,g, +201001644,201001654,801000001,R_000066,100,g, +201001644,201001655,801000001,R_000067,适量,, +201001644,201001656,801000001,R_000068,10,ml, +201001644,201001657,801000001,R_000069,适量,, +201001644,201001658,801000001,R_000070,适量,, +201001644,201001659,801000003,R_000071,,,1.0 +201001644,201001660,801000003,R_000072,,,2.0 +201001644,201001661,801000003,R_000073,,,3.0 +201001644,201001662,801000003,R_000074,,,4.0 +201001644,201001663,801000003,R_000075,,,5.0 +201001644,201001664,801000003,R_000076,,,6.0 +201001644,201001665,801000003,R_000077,,,7.0 +201001644,720000000,801000004,R_000078,,, +201001644,640000000,801000005,R_000079,,, +201001666,201001667,801000001,R_000080,1250,克, +201001666,201001668,801000001,R_000081,10,克, +201001666,201001669,801000001,R_000082,150,克, +201001666,201001670,801000001,R_000083,15,克, +201001666,201001671,801000001,R_000084,35,克, +201001666,201001672,801000001,R_000085,25,克, +201001666,201001673,801000001,R_000086,25,克, +201001666,201001674,801000001,R_000087,50,克, +201001666,201001675,801000001,R_000088,10,克, +201001666,201001676,801000001,R_000089,3,个, +201001666,201001677,801000001,R_000090,5,克, +201001666,201001678,801000001,R_000091,200,克, +201001666,201001679,801000003,R_000092,,,1.0 +201001666,201001680,801000003,R_000093,,,2.0 +201001666,201001681,801000003,R_000094,,,3.0 +201001666,201001682,801000003,R_000095,,,4.0 +201001666,201001683,801000003,R_000096,,,5.0 +201001666,201001684,801000003,R_000097,,,6.0 +201001666,720000000,801000004,R_000098,,, +201001666,650000000,801000005,R_000099,,, +201001685,201001686,801000001,R_000100,1.5,个/人, +201001685,201001687,801000001,R_000101,2,g/人, +201001685,201001688,801000001,R_000102,0.5,g/人, +201001685,201001689,801000001,R_000103,5,ml/人, +201001685,201001690,801000001,R_000104,1,瓣/人, +201001685,201001691,801000001,R_000105,5,ml/人, +201001685,201001692,801000001,R_000106,1,根/人, +201001685,201001693,801000003,R_000107,,,1.0 +201001685,201001694,801000003,R_000108,,,2.0 +201001685,201001695,801000003,R_000109,,,3.0 +201001685,201001696,801000003,R_000110,,,4.0 +201001685,201001697,801000003,R_000111,,,5.0 +201001685,720000000,801000004,R_000112,,, +201001685,630000000,801000005,R_000113,,, +201001698,201001699,801000001,R_000114,200,克, +201001698,201001700,801000001,R_000115,500,克, +201001698,201001701,801000001,R_000116,400,克, +201001698,201001702,801000001,R_000117,10,克, +201001698,201001703,801000001,R_000118,5,个, +201001698,201001704,801000001,R_000119,5,克, +201001698,201001705,801000001,R_000120,5,个, +201001698,201001706,801000001,R_000121,2,片, +201001698,201001707,801000001,R_000122,1,个, +201001698,201001708,801000001,R_000123,1,个, +201001698,201001709,801000001,R_000124,10,克, +201001698,201001710,801000001,R_000125,10,克, +201001698,201001711,801000001,R_000126,5,克, +201001698,201001712,801000001,R_000127,5,克, +201001698,201001713,801000001,R_000128,10,克, +201001698,201001714,801000001,R_000129,5,克, +201001698,201001715,801000001,R_000130,适量,, +201001698,201001716,801000003,R_000131,,,1.0 +201001698,201001717,801000003,R_000132,,,2.0 +201001698,201001718,801000003,R_000133,,,3.0 +201001698,201001719,801000003,R_000134,,,4.0 +201001698,201001720,801000003,R_000135,,,5.0 +201001698,201001721,801000003,R_000136,,,6.0 +201001698,201001722,801000003,R_000137,,,7.0 +201001698,201001723,801000003,R_000138,,,8.0 +201001698,201001724,801000003,R_000139,,,9.0 +201001698,201001725,801000003,R_000140,,,10.0 +201001698,201001726,801000003,R_000141,,,11.0 +201001698,720000000,801000004,R_000142,,, +201001698,640000000,801000005,R_000143,,, +201001727,201001728,801000001,R_000144,360,克, +201001727,201001729,801000001,R_000145,1,个, +201001727,201001730,801000001,R_000146,1,克, +201001727,201001731,801000001,R_000147,10,克, +201001727,201001732,801000001,R_000148,100,毫升, +201001727,201001733,801000001,R_000149,80,克, +201001727,201001734,801000001,R_000150,80,克, +201001727,201001735,801000001,R_000151,2.5,克, +201001727,201001736,801000001,R_000152,10,克, +201001727,201001737,801000001,R_000153,10,克, +201001727,201001738,801000003,R_000154,,,1.0 +201001727,201001739,801000003,R_000155,,,2.0 +201001727,201001740,801000003,R_000156,,,3.0 +201001727,201001741,801000003,R_000157,,,4.0 +201001727,201001742,801000003,R_000158,,,5.0 +201001727,201001743,801000003,R_000159,,,6.0 +201001727,201001744,801000003,R_000160,,,7.0 +201001727,201001745,801000003,R_000161,,,8.0 +201001727,720000000,801000004,R_000162,,, +201001727,640000000,801000005,R_000163,,, +201001746,201001747,801000001,R_000164,300,g, +201001746,201001748,801000001,R_000165,5,g, +201001746,201001749,801000001,R_000166,2,g, +201001746,201001750,801000001,R_000167,5,g, +201001746,201001751,801000001,R_000168,3,g, +201001746,201001752,801000001,R_000169,1,个, +201001746,201001753,801000001,R_000170,7,g, +201001746,201001754,801000001,R_000171,280,g, +201001746,201001755,801000001,R_000172,200,g, +201001746,201001756,801000001,R_000173,100,g, +201001746,201001757,801000001,R_000174,1,根, +201001746,201001758,801000001,R_000175,3,根, +201001746,201001759,801000001,R_000176,2,根, +201001746,201001760,801000001,R_000177,20,g, +201001746,201001761,801000001,R_000178,10,g, +201001746,201001762,801000001,R_000179,20,g, +201001746,201001763,801000001,R_000180,5,g, +201001746,201001764,801000001,R_000181,20,g, +201001746,201001765,801000001,R_000182,5,ml, +201001746,201001766,801000001,R_000183,1.5,g, +201001746,201001767,801000001,R_000184,1,g, +201001746,201001768,801000001,R_000185,2,根, +201001746,201001769,801000003,R_000186,,,1.0 +201001746,201001770,801000003,R_000187,,,2.0 +201001746,201001771,801000003,R_000188,,,3.0 +201001746,201001772,801000003,R_000189,,,4.0 +201001746,201001773,801000003,R_000190,,,5.0 +201001746,201001774,801000003,R_000191,,,6.0 +201001746,201001775,801000003,R_000192,,,7.0 +201001746,201001776,801000003,R_000193,,,8.0 +201001746,201001777,801000003,R_000194,,,9.0 +201001746,201001778,801000003,R_000195,,,10.0 +201001746,201001779,801000003,R_000196,,,11.0 +201001746,720000000,801000004,R_000197,,, +201001746,650000000,801000005,R_000198,,, +201001780,201001781,801000001,R_000199,1,颗, +201001780,201001782,801000001,R_000200,250,g, +201001780,201001783,801000001,R_000201,3,瓣, +201001780,201001784,801000001,R_000202,15,ml, +201001780,201001785,801000001,R_000203,1.25,g, +201001780,201001786,801000001,R_000204,30,ml, +201001780,201001787,801000001,R_000205,15,g, +201001780,201001788,801000001,R_000206,5,ml, +201001780,201001789,801000001,R_000207,15,ml, +201001780,201001790,801000001,R_000208,15,ml, +201001780,201001791,801000003,R_000209,,,1.0 +201001780,201001792,801000003,R_000210,,,2.0 +201001780,201001793,801000003,R_000211,,,3.0 +201001780,201001794,801000003,R_000212,,,4.0 +201001780,201001795,801000003,R_000213,,,5.0 +201001780,201001796,801000003,R_000214,,,6.0 +201001780,720000000,801000004,R_000215,,, +201001780,630000000,801000005,R_000216,,, +201001797,201001798,801000001,R_000001,3-4,个, +201001797,201001799,801000001,R_000002,2,g, +201001797,201001800,801000001,R_000003,1,g, +201001797,201001801,801000001,R_000004,3,ml, +201001797,201001802,801000001,R_000005,3,ml, +201001797,201001803,801000003,R_000006,,,1.0 +201001797,201001804,801000003,R_000007,,,2.0 +201001797,201001805,801000003,R_000008,,,3.0 +201001797,201001806,801000003,R_000009,,,4.0 +201001797,201001807,801000003,R_000010,,,5.0 +201001797,720000000,801000004,R_000011,,, +201001797,630000000,801000005,R_000012,,, +201001808,201001809,801000001,R_000013,1500,克, +201001808,201001810,801000001,R_000014,1000,克, +201001808,201001811,801000001,R_000015,1,根, +201001808,201001812,801000001,R_000016,100,克, +201001808,201001813,801000001,R_000017,4,瓣, +201001808,201001814,801000001,R_000018,10,克, +201001808,201001815,801000001,R_000019,15,克, +201001808,201001816,801000001,R_000020,10,克, +201001808,201001817,801000001,R_000021,20,毫升, +201001808,201001818,801000001,R_000022,2,颗, +201001808,201001819,801000003,R_000023,,,1.0 +201001808,201001820,801000003,R_000024,,,2.0 +201001808,201001821,801000003,R_000025,,,3.0 +201001808,201001822,801000003,R_000026,,,4.0 +201001808,201001823,801000003,R_000027,,,5.0 +201001808,201001824,801000003,R_000028,,,6.0 +201001808,201001825,801000003,R_000029,,,7.0 +201001808,201001826,801000003,R_000030,,,8.0 +201001808,201001827,801000003,R_000031,,,9.0 +201001808,201001828,801000003,R_000032,,,10.0 +201001808,201001829,801000003,R_000033,,,11.0 +201001808,201001830,801000003,R_000034,,,12.0 +201001808,720000000,801000004,R_000035,,, +201001808,650000000,801000005,R_000036,,, +201001831,201001832,801000001,R_000037,4,个, +201001831,201001833,801000001,R_000038,45,ml, +201001831,201001834,801000001,R_000039,15,ml, +201001831,201001835,801000001,R_000040,10,g, +201001831,201001836,801000001,R_000041,5,g, +201001831,201001837,801000001,R_000042,10,g, +201001831,201001838,801000001,R_000043,10,g, +201001831,201001839,801000001,R_000044,5,g, +201001831,201001840,801000001,R_000045,15,ml, +201001831,201001841,801000001,R_000046,20,ml, +201001831,201001842,801000001,R_000047,10,ml, +201001831,201001843,801000003,R_000048,,,1.0 +201001831,201001844,801000003,R_000049,,,2.0 +201001831,201001845,801000003,R_000050,,,3.0 +201001831,201001846,801000003,R_000051,,,4.0 +201001831,201001847,801000003,R_000052,,,5.0 +201001831,201001848,801000003,R_000053,,,6.0 +201001831,201001849,801000003,R_000054,,,7.0 +201001831,201001850,801000003,R_000055,,,8.0 +201001831,201001851,801000003,R_000056,,,9.0 +201001831,720000000,801000004,R_000057,,, +201001831,630000000,801000005,R_000058,,, +201001852,201001853,801000001,R_000059,500,g, +201001852,201001854,801000001,R_000060,2,个, +201001852,201001855,801000001,R_000061,0.5,根, +201001852,201001856,801000001,R_000062,1,根, +201001852,201001857,801000001,R_000063,0.5,个, +201001852,201001858,801000001,R_000064,20,ml, +201001852,201001859,801000001,R_000065,2,g, +201001852,201001860,801000001,R_000066,10,g, +201001852,201001861,801000001,R_000067,5,g, +201001852,201001862,801000001,R_000068,300,g, +201001852,201001863,801000001,R_000069,300,ml, +201001852,201001864,801000001,R_000070,适量,, +201001852,201001865,801000003,R_000071,,,1.0 +201001852,201001866,801000003,R_000072,,,2.0 +201001852,201001867,801000003,R_000073,,,3.0 +201001852,201001868,801000003,R_000074,,,4.0 +201001852,201001869,801000003,R_000075,,,5.0 +201001852,720000000,801000004,R_000076,,, +201001852,640000000,801000005,R_000077,,, +201001870,201001871,801000001,R_000078,300,g, +201001870,201001872,801000001,R_000079,500,g, +201001870,201001873,801000001,R_000080,50,g, +201001870,201001874,801000001,R_000081,10,g, +201001870,201001875,801000001,R_000082,5,g, +201001870,201001876,801000001,R_000083,15,g, +201001870,201001877,801000001,R_000084,5,ml, +201001870,201001878,801000001,R_000085,5,ml, +201001870,201001879,801000001,R_000086,10-15,ml, +201001870,201001880,801000003,R_000087,,,1.0 +201001870,201001881,801000003,R_000088,,,2.0 +201001870,201001882,801000003,R_000089,,,3.0 +201001870,201001883,801000003,R_000090,,,4.0 +201001870,201001884,801000003,R_000091,,,5.0 +201001870,201001885,801000003,R_000092,,,6.0 +201001870,201001886,801000003,R_000093,,,7.0 +201001870,201001887,801000003,R_000094,,,8.0 +201001870,201001888,801000003,R_000095,,,9.0 +201001870,201001889,801000003,R_000096,,,10.0 +201001870,201001890,801000003,R_000097,,,11.0 +201001870,720000000,801000004,R_000098,,, +201001870,630000000,801000005,R_000099,,, +201001891,201001892,801000001,R_000100,250,克, +201001891,201001893,801000001,R_000101,50,克, +201001891,201001894,801000001,R_000102,7.5,毫升, +201001891,201001895,801000001,R_000103,5,毫升, +201001891,201001896,801000001,R_000104,7.5,毫升, +201001891,201001897,801000001,R_000105,5,克, +201001891,201001898,801000001,R_000106,5,克, +201001891,201001899,801000001,R_000107,5,克, +201001891,201001900,801000001,R_000108,2.5,克, +201001891,201001901,801000001,R_000109,150,克, +201001891,201001902,801000001,R_000110,1000,毫升, +201001891,201001903,801000003,R_000111,,,1.0 +201001891,201001904,801000003,R_000112,,,2.0 +201001891,201001905,801000003,R_000113,,,3.0 +201001891,201001906,801000003,R_000114,,,4.0 +201001891,201001907,801000003,R_000115,,,5.0 +201001891,201001908,801000003,R_000116,,,6.0 +201001891,201001909,801000003,R_000117,,,7.0 +201001891,201001910,801000003,R_000118,,,8.0 +201001891,201001911,801000003,R_000119,,,9.0 +201001891,201001912,801000003,R_000120,,,10.0 +201001891,201001913,801000003,R_000121,,,11.0 +201001891,201001914,801000003,R_000122,,,12.0 +201001891,201001915,801000003,R_000123,,,13.0 +201001891,720000000,801000004,R_000124,,, +201001891,640000000,801000005,R_000125,,, +201001916,201001917,801000001,R_000126,500,g, +201001916,201001918,801000001,R_000127,10,g, +201001916,201001919,801000001,R_000128,30,g, +201001916,201001920,801000001,R_000129,50,g, +201001916,201001921,801000001,R_000130,50,g, +201001916,201001922,801000001,R_000131,10,ml, +201001916,201001923,801000001,R_000132,20,g, +201001916,201001924,801000001,R_000133,10,g, +201001916,201001925,801000001,R_000134,30,ml, +201001916,201001926,801000001,R_000135,5,g, +201001916,201001927,801000001,R_000136,10,g, +201001916,201001928,801000003,R_000137,,,1.0 +201001916,201001929,801000003,R_000138,,,2.0 +201001916,201001930,801000003,R_000139,,,3.0 +201001916,201001931,801000003,R_000140,,,4.0 +201001916,201001932,801000003,R_000141,,,5.0 +201001916,201001933,801000003,R_000142,,,6.0 +201001916,720000000,801000004,R_000143,,, +201001916,640000000,801000005,R_000144,,, +201001934,201001935,801000001,R_000145,300,克, +201001934,201001936,801000001,R_000146,2,个, +201001934,201001937,801000001,R_000147,10,毫升, +201001934,201001938,801000001,R_000148,20,毫升, +201001934,201001939,801000001,R_000149,5,克, +201001934,201001940,801000001,R_000150,10-15,毫升, +201001934,201001941,801000003,R_000151,,,1.0 +201001934,201001942,801000003,R_000152,,,2.0 +201001934,201001943,801000003,R_000153,,,3.0 +201001934,720000000,801000004,R_000154,,, +201001934,630000000,801000005,R_000155,,, +201001944,201001945,801000001,R_000156,400,g, +201001944,201001946,801000001,R_000157,1,根, +201001944,201001947,801000001,R_000158,1,根, +201001944,201001948,801000001,R_000159,10,粒, +201001944,201001949,801000001,R_000160,适量,, +201001944,201001950,801000001,R_000161,10,g, +201001944,201001951,801000001,R_000162,30-40,ml, +201001944,201001952,801000001,R_000163,30-40,ml, +201001944,201001953,801000001,R_000164,10,g, +201001944,201001954,801000001,R_000165,2-4,粒, +201001944,201001955,801000001,R_000166,1000,ml, +201001944,201001956,801000003,R_000167,,,1.0 +201001944,201001957,801000003,R_000168,,,2.0 +201001944,201001958,801000003,R_000169,,,3.0 +201001944,201001959,801000003,R_000170,,,4.0 +201001944,201001960,801000003,R_000171,,,5.0 +201001944,201001961,801000003,R_000172,,,6.0 +201001944,201001962,801000003,R_000173,,,7.0 +201001944,201001963,801000003,R_000174,,,8.0 +201001944,201001964,801000003,R_000175,,,9.0 +201001944,720000000,801000004,R_000176,,, +201001944,640000000,801000005,R_000177,,, +201001965,201001966,801000001,R_000178,190,g, +201001965,201001967,801000001,R_000179,20,g, +201001965,201001968,801000001,R_000180,10,ml, +201001965,201001969,801000001,R_000181,2,瓣, +201001965,201001970,801000001,R_000182,15,ml, +201001965,201001971,801000001,R_000183,2,g, +201001965,201001972,801000001,R_000184,20,g, +201001965,201001973,801000003,R_000185,,,1.0 +201001965,201001974,801000003,R_000186,,,2.0 +201001965,201001975,801000003,R_000187,,,3.0 +201001965,201001976,801000003,R_000188,,,4.0 +201001965,201001977,801000003,R_000189,,,5.0 +201001965,201001978,801000003,R_000190,,,6.0 +201001965,201001979,801000003,R_000191,,,7.0 +201001965,201001980,801000003,R_000192,,,8.0 +201001965,201001981,801000003,R_000193,,,9.0 +201001965,720000000,801000004,R_000194,,, +201001965,620000000,801000005,R_000195,,, +201001982,201001983,801000001,R_000001,1,个, +201001982,201001984,801000001,R_000002,1,桶, +201001982,201001985,801000001,R_000003,5,桶, +201001982,201001986,801000001,R_000004,1-2,茶匙, +201001982,201001987,801000001,R_000005,1,茶匙, +201001982,201001988,801000001,R_000006,1,汤匙, +201001982,201001989,801000001,R_000007,1,汤匙, +201001982,201001990,801000001,R_000008,3,片, +201001982,201001991,801000001,R_000009,2-3,克, +201001982,201001992,801000001,R_000010,3,个, +201001982,201001993,801000001,R_000011,8-12,个, +201001982,201001994,801000001,R_000012,2-4,个, +201001982,201001995,801000001,R_000013,1,汤匙, +201001982,201001996,801000001,R_000014,2,棵, +201001982,201001997,801000001,R_000015,6,克, +201001982,201001998,801000001,R_000016,6,粒, +201001982,201001999,801000001,R_000017,2,汤匙, +201001982,201002000,801000001,R_000018,适量,, +201001982,201002001,801000003,R_000019,,,1.0 +201001982,201002002,801000003,R_000020,,,2.0 +201001982,201002003,801000003,R_000021,,,3.0 +201001982,201002004,801000003,R_000022,,,4.0 +201001982,201002005,801000003,R_000023,,,5.0 +201001982,201002006,801000003,R_000024,,,6.0 +201001982,201002007,801000003,R_000025,,,7.0 +201001982,201002008,801000003,R_000026,,,8.0 +201001982,201002009,801000003,R_000027,,,9.0 +201001982,201002010,801000003,R_000028,,,10.0 +201001982,201002011,801000003,R_000029,,,11.0 +201001982,201002012,801000003,R_000030,,,12.0 +201001982,720000000,801000004,R_000031,,, +201001982,650000000,801000005,R_000032,,, +201002013,201002014,801000001,R_000033,80,g, +201002013,201002015,801000001,R_000034,150,g, +201002013,201002016,801000001,R_000035,15,g, +201002013,201002017,801000001,R_000036,10,ml, +201002013,201002018,801000001,R_000037,5,ml, +201002013,201002019,801000001,R_000038,10,ml, +201002013,201002020,801000001,R_000039,10,g, +201002013,201002021,801000001,R_000040,5,g, +201002013,201002022,801000001,R_000041,300,ml, +201002013,201002023,801000001,R_000042,适量,, +201002013,201002024,801000001,R_000043,0.5,g, +201002013,201002025,801000003,R_000044,,,1.0 +201002013,201002026,801000003,R_000045,,,2.0 +201002013,201002027,801000003,R_000046,,,3.0 +201002013,201002028,801000003,R_000047,,,4.0 +201002013,201002029,801000003,R_000048,,,5.0 +201002013,201002030,801000003,R_000049,,,6.0 +201002013,201002031,801000003,R_000050,,,7.0 +201002013,201002032,801000003,R_000051,,,8.0 +201002013,201002033,801000003,R_000052,,,9.0 +201002013,201002034,801000003,R_000053,,,10.0 +201002013,720000000,801000004,R_000054,,, +201002013,630000000,801000005,R_000055,,, +201002035,201002036,801000001,R_000056,3,个, +201002035,201002037,801000001,R_000057,200,g, +201002035,201002038,801000001,R_000058,5,g, +201002035,201002039,801000001,R_000059,3,ml, +201002035,201002040,801000001,R_000060,3,ml, +201002035,201002041,801000001,R_000061,5,g, +201002035,201002042,801000001,R_000062,5,g, +201002035,201002043,801000001,R_000063,2,ml, +201002035,201002044,801000001,R_000064,3,g, +201002035,201002045,801000001,R_000065,8,ml, +201002035,201002046,801000003,R_000066,,,1.0 +201002035,201002047,801000003,R_000067,,,2.0 +201002035,201002048,801000003,R_000068,,,3.0 +201002035,201002049,801000003,R_000069,,,4.0 +201002035,201002050,801000003,R_000070,,,5.0 +201002035,201002051,801000003,R_000071,,,6.0 +201002035,201002052,801000003,R_000072,,,7.0 +201002035,201002053,801000003,R_000073,,,8.0 +201002035,201002054,801000003,R_000074,,,9.0 +201002035,720000000,801000004,R_000075,,, +201002035,630000000,801000005,R_000076,,, +201002055,201002056,801000001,R_000077,100,g, +201002055,201002057,801000001,R_000078,75,g, +201002055,201002058,801000001,R_000079,5,个, +201002055,201002059,801000001,R_000080,3,g, +201002055,201002060,801000001,R_000081,5,ml, +201002055,201002061,801000001,R_000082,5,g, +201002055,201002062,801000001,R_000083,5,g, +201002055,201002063,801000001,R_000084,2,g, +201002055,201002064,801000003,R_000085,,,1.0 +201002055,201002065,801000003,R_000086,,,2.0 +201002055,201002066,801000003,R_000087,,,3.0 +201002055,201002067,801000003,R_000088,,,4.0 +201002055,201002068,801000003,R_000089,,,5.0 +201002055,201002069,801000003,R_000090,,,6.0 +201002055,201002070,801000003,R_000091,,,7.0 +201002055,201002071,801000003,R_000092,,,8.0 +201002055,201002072,801000003,R_000093,,,9.0 +201002055,720000000,801000004,R_000094,,, +201002055,630000000,801000005,R_000095,,, +201002073,201002074,801000001,R_000096,200,g, +201002073,201002075,801000001,R_000097,100,g, +201002073,201002076,801000001,R_000098,100,g, +201002073,201002077,801000001,R_000099,5,g, +201002073,201002078,801000001,R_000100,10,ml, +201002073,201002079,801000001,R_000101,5,ml, +201002073,201002080,801000001,R_000102,1,个, +201002073,201002081,801000001,R_000103,10,g, +201002073,201002082,801000001,R_000104,15,ml, +201002073,201002083,801000001,R_000105,10,g, +201002073,201002084,801000001,R_000106,5,g, +201002073,201002085,801000001,R_000107,20,g, +201002073,201002086,801000001,R_000108,20,g, +201002073,201002087,801000001,R_000109,2,瓣, +201002073,201002088,801000001,R_000110,15,g, +201002073,201002089,801000001,R_000111,40,ml, +201002073,201002090,801000001,R_000112,20,ml, +201002073,201002091,801000003,R_000113,,,1.0 +201002073,201002092,801000003,R_000114,,,2.0 +201002073,201002093,801000003,R_000115,,,3.0 +201002073,201002094,801000003,R_000116,,,4.0 +201002073,201002095,801000003,R_000117,,,5.0 +201002073,201002096,801000003,R_000118,,,6.0 +201002073,201002097,801000003,R_000119,,,7.0 +201002073,201002098,801000003,R_000120,,,8.0 +201002073,201002099,801000003,R_000121,,,9.0 +201002073,201002100,801000003,R_000122,,,10.0 +201002073,201002101,801000003,R_000123,,,11.0 +201002073,201002102,801000003,R_000124,,,12.0 +201002073,720000000,801000004,R_000125,,, +201002073,640000000,801000005,R_000126,,, +201002103,201002104,801000001,R_000127,455,克, +201002103,201002105,801000001,R_000128,430,克, +201002103,201002106,801000001,R_000129,152,克, +201002103,201002107,801000001,R_000130,1,袋, +201002103,201002108,801000001,R_000131,5,克, +201002103,201002109,801000001,R_000132,110,克, +201002103,201002110,801000001,R_000133,105,克, +201002103,201002111,801000003,R_000134,,,1.0 +201002103,201002112,801000003,R_000135,,,2.0 +201002103,201002113,801000003,R_000136,,,3.0 +201002103,201002114,801000003,R_000137,,,4.0 +201002103,201002115,801000003,R_000138,,,5.0 +201002103,201002116,801000003,R_000139,,,6.0 +201002103,201002117,801000003,R_000140,,,7.0 +201002103,201002118,801000003,R_000141,,,8.0 +201002103,201002119,801000003,R_000142,,,9.0 +201002103,201002120,801000003,R_000143,,,10.0 +201002103,201002121,801000003,R_000144,,,11.0 +201002103,720000000,801000004,R_000145,,, +201002103,630000000,801000005,R_000146,,, +201002122,201002123,801000001,R_000147,2,只, +201002122,201002124,801000001,R_000148,5,朵, +201002122,201002125,801000001,R_000149,2,个, +201002122,201002126,801000001,R_000150,2,片, +201002122,201002127,801000001,R_000151,5.5,个, +201002122,201002128,801000001,R_000152,10,g, +201002122,201002129,801000001,R_000153,10,ml, +201002122,201002130,801000001,R_000154,5,g, +201002122,201002131,801000001,R_000155,5,g, +201002122,201002132,801000001,R_000156,5,ml, +201002122,201002133,801000001,R_000157,适量,, +201002122,201002134,801000001,R_000158,1,个, +201002122,201002135,801000003,R_000159,,,1.0 +201002122,201002136,801000003,R_000160,,,2.0 +201002122,201002137,801000003,R_000161,,,3.0 +201002122,201002138,801000003,R_000162,,,4.0 +201002122,201002139,801000003,R_000163,,,5.0 +201002122,201002140,801000003,R_000164,,,6.0 +201002122,201002141,801000003,R_000165,,,7.0 +201002122,201002142,801000003,R_000166,,,8.0 +201002122,201002143,801000003,R_000167,,,9.0 +201002122,201002144,801000003,R_000168,,,10.0 +201002122,201002145,801000003,R_000169,,,11.0 +201002122,720000000,801000004,R_000170,,, +201002122,630000000,801000005,R_000171,,, +201002146,201002147,801000001,R_000172,100,克, +201002146,201002148,801000001,R_000173,50,克, +201002146,201002149,801000001,R_000174,50,克, +201002146,201002150,801000001,R_000175,5,克, +201002146,201002151,801000001,R_000176,10,克, +201002146,201002152,801000001,R_000177,2,瓣, +201002146,201002153,801000001,R_000178,1,根, +201002146,201002154,801000003,R_000179,,,1.0 +201002146,201002155,801000003,R_000180,,,2.0 +201002146,201002156,801000003,R_000181,,,3.0 +201002146,201002157,801000003,R_000182,,,4.0 +201002146,201002158,801000003,R_000183,,,5.0 +201002146,201002159,801000003,R_000184,,,6.0 +201002146,201002160,801000003,R_000185,,,7.0 +201002146,201002161,801000003,R_000186,,,8.0 +201002146,720000000,801000004,R_000187,,, +201002146,630000000,801000005,R_000188,,, +201002162,201002163,801000001,R_000189,250,g, +201002162,201002164,801000001,R_000190,3,个, +201002162,201002165,801000001,R_000191,2,片, +201002162,201002166,801000001,R_000192,10,g, +201002162,201002167,801000001,R_000193,15,ml, +201002162,201002168,801000001,R_000194,1,个, +201002162,201002169,801000001,R_000195,5,mg, +201002162,201002170,801000001,R_000196,2,片, +201002162,201002171,801000001,R_000197,适量,个, +201002162,201002172,801000003,R_000198,,,1.0 +201002162,201002173,801000003,R_000199,,,2.0 +201002162,201002174,801000003,R_000200,,,3.0 +201002162,201002175,801000003,R_000201,,,4.0 +201002162,201002176,801000003,R_000202,,,5.0 +201002162,201002177,801000003,R_000203,,,6.0 +201002162,201002178,801000003,R_000204,,,7.0 +201002162,720000000,801000004,R_000205,,, +201002162,630000000,801000005,R_000206,,, +201002179,201002180,801000001,R_000207,300,g, +201002179,201002181,801000001,R_000208,200,g, +201002179,201002182,801000001,R_000209,1,个, +201002179,201002183,801000001,R_000210,20,g, +201002179,201002184,801000001,R_000211,5,g, +201002179,201002185,801000001,R_000212,10,ml, +201002179,201002186,801000001,R_000213,5,g, +201002179,201002187,801000001,R_000214,25,g, +201002179,201002188,801000001,R_000215,50,ml, +201002179,201002189,801000001,R_000216,30,g, +201002179,201002190,801000001,R_000217,20,g, +201002179,201002191,801000003,R_000218,,,1.0 +201002179,201002192,801000003,R_000219,,,2.0 +201002179,201002193,801000003,R_000220,,,3.0 +201002179,201002194,801000003,R_000221,,,4.0 +201002179,201002195,801000003,R_000222,,,5.0 +201002179,201002196,801000003,R_000223,,,6.0 +201002179,201002197,801000003,R_000224,,,7.0 +201002179,201002198,801000003,R_000225,,,8.0 +201002179,201002199,801000003,R_000226,,,9.0 +201002179,201002200,801000003,R_000227,,,10.0 +201002179,201002201,801000003,R_000228,,,11.0 +201002179,201002202,801000003,R_000229,,,12.0 +201002179,720000000,801000004,R_000230,,, +201002179,640000000,801000005,R_000231,,, +201002203,201002204,801000001,R_000001,200,克, +201002203,201002205,801000001,R_000002,5,毫升, +201002203,201002206,801000001,R_000003,4,毫升, +201002203,201002207,801000001,R_000004,4,毫升, +201002203,201002208,801000001,R_000005,3,克, +201002203,201002209,801000001,R_000006,2,克, +201002203,201002210,801000001,R_000007,20,毫升, +201002203,201002211,801000001,R_000008,20,克, +201002203,201002212,801000001,R_000009,适量,, +201002203,201002213,801000003,R_000010,,,1.0 +201002203,201002214,801000003,R_000011,,,2.0 +201002203,201002215,801000003,R_000012,,,3.0 +201002203,201002216,801000003,R_000013,,,4.0 +201002203,201002217,801000003,R_000014,,,5.0 +201002203,201002218,801000003,R_000015,,,6.0 +201002203,201002219,801000003,R_000016,,,7.0 +201002203,201002220,801000003,R_000017,,,8.0 +201002203,201002221,801000003,R_000018,,,9.0 +201002203,201002222,801000003,R_000019,,,10.0 +201002203,201002223,801000003,R_000020,,,11.0 +201002203,720000000,801000004,R_000021,,, +201002203,630000000,801000005,R_000022,,, +201002224,201002225,801000001,R_000023,1,包, +201002224,201002226,801000001,R_000024,15,ml, +201002224,201002227,801000001,R_000025,15,ml, +201002224,201002228,801000001,R_000026,15,ml, +201002224,201002229,801000001,R_000027,15,ml, +201002224,201002230,801000001,R_000028,100,g, +201002224,201002231,801000001,R_000029,30,g, +201002224,201002232,801000001,R_000030,40,g, +201002224,201002233,801000001,R_000031,10,g, +201002224,201002234,801000001,R_000032,120,ml, +201002224,201002235,801000001,R_000033,60,ml, +201002224,201002236,801000001,R_000034,10-15,g, +201002224,201002237,801000001,R_000035,30,g, +201002224,201002238,801000001,R_000036,330,ml, +201002224,201002239,801000001,R_000037,500,g, +201002224,201002240,801000001,R_000038,足量,ml, +201002224,201002241,801000003,R_000039,,,1.0 +201002224,201002242,801000003,R_000040,,,2.0 +201002224,201002243,801000003,R_000041,,,3.0 +201002224,201002244,801000003,R_000042,,,4.0 +201002224,201002245,801000003,R_000043,,,5.0 +201002224,201002246,801000003,R_000044,,,6.0 +201002224,201002247,801000003,R_000045,,,7.0 +201002224,201002248,801000003,R_000046,,,8.0 +201002224,201002249,801000003,R_000047,,,9.0 +201002224,201002250,801000003,R_000048,,,10.0 +201002224,201002251,801000003,R_000049,,,11.0 +201002224,201002252,801000003,R_000050,,,12.0 +201002224,201002253,801000003,R_000051,,,13.0 +201002224,201002254,801000003,R_000052,,,14.0 +201002224,720000000,801000004,R_000053,,, +201002224,630000000,801000005,R_000054,,, +201002255,201002256,801000001,R_000055,500,g, +201002255,201002257,801000001,R_000056,20,ml, +201002255,201002258,801000001,R_000057,20,g, +201002255,201002259,801000001,R_000058,20,g, +201002255,201002260,801000001,R_000059,30,g, +201002255,201002261,801000001,R_000060,50,g, +201002255,201002262,801000001,R_000061,20,g, +201002255,201002263,801000001,R_000062,10,g, +201002255,201002264,801000001,R_000063,5,g, +201002255,201002265,801000001,R_000064,5,ml, +201002255,201002266,801000001,R_000065,5,ml, +201002255,201002267,801000001,R_000066,5,g, +201002255,201002268,801000001,R_000067,5,g, +201002255,201002269,801000001,R_000068,5,g, +201002255,201002270,801000003,R_000069,,,1.0 +201002255,201002271,801000003,R_000070,,,2.0 +201002255,201002272,801000003,R_000071,,,3.0 +201002255,201002273,801000003,R_000072,,,4.0 +201002255,201002274,801000003,R_000073,,,5.0 +201002255,201002275,801000003,R_000074,,,6.0 +201002255,201002276,801000003,R_000075,,,7.0 +201002255,201002277,801000003,R_000076,,,8.0 +201002255,201002278,801000003,R_000077,,,9.0 +201002255,201002279,801000003,R_000078,,,10.0 +201002255,201002280,801000003,R_000079,,,11.0 +201002255,201002281,801000003,R_000080,,,12.0 +201002255,720000000,801000004,R_000081,,, +201002255,630000000,801000005,R_000082,,, +201002282,201002283,801000001,R_000083,25,g, +201002282,201002284,801000001,R_000084,500,g, +201002282,201002285,801000001,R_000085,4,个, +201002282,201002286,801000001,R_000086,15,ml, +201002282,201002287,801000001,R_000087,75,ml, +201002282,201002288,801000001,R_000088,35,ml, +201002282,201002289,801000001,R_000089,25,g, +201002282,201002290,801000001,R_000090,2,片, +201002282,201002291,801000001,R_000091,1,颗, +201002282,201002292,801000001,R_000092,20,g, +201002282,201002293,801000001,R_000093,6,g, +201002282,201002294,801000001,R_000094,6,g, +201002282,201002295,801000001,R_000095,根据个人食量决定,, +201002282,201002296,801000003,R_000096,,,1.0 +201002282,201002297,801000003,R_000097,,,2.0 +201002282,201002298,801000003,R_000098,,,3.0 +201002282,201002299,801000003,R_000099,,,4.0 +201002282,201002300,801000003,R_000100,,,5.0 +201002282,201002301,801000003,R_000101,,,6.0 +201002282,201002302,801000003,R_000102,,,7.0 +201002282,201002303,801000003,R_000103,,,8.0 +201002282,201002304,801000003,R_000104,,,9.0 +201002282,201002305,801000003,R_000105,,,10.0 +201002282,201002306,801000003,R_000106,,,11.0 +201002282,201002307,801000003,R_000107,,,12.0 +201002282,201002308,801000003,R_000108,,,13.0 +201002282,720000000,801000004,R_000109,,, +201002282,650000000,801000005,R_000110,,, +201002309,201002310,801000001,R_000111,1,片, +201002309,201002311,801000001,R_000112,50,ml, +201002309,201002312,801000001,R_000113,100,g, +201002309,201002313,801000001,R_000114,150,g, +201002309,201002314,801000001,R_000115,200,g, +201002309,201002315,801000001,R_000116,300,g, +201002309,201002316,801000001,R_000117,100,g, +201002309,201002317,801000001,R_000118,10-15,ml, +201002309,201002318,801000001,R_000119,适量,ml, +201002309,201002319,801000003,R_000120,,,1.0 +201002309,201002320,801000003,R_000121,,,2.0 +201002309,201002321,801000003,R_000122,,,3.0 +201002309,201002322,801000003,R_000123,,,4.0 +201002309,201002323,801000003,R_000124,,,5.0 +201002309,201002324,801000003,R_000125,,,6.0 +201002309,201002325,801000003,R_000126,,,7.0 +201002309,201002326,801000003,R_000127,,,8.0 +201002309,720000000,801000004,R_000128,,, +201002309,640000000,801000005,R_000129,,, +201002327,201002328,801000001,R_000130,1000,克, +201002327,201002329,801000001,R_000131,800,毫升, +201002327,201002330,801000001,R_000132,10-15,毫升, +201002327,201002331,801000001,R_000133,5-10,毫升, +201002327,201002332,801000001,R_000134,5,片, +201002327,201002333,801000001,R_000135,12,瓣, +201002327,201002334,801000001,R_000136,10,克, +201002327,201002335,801000001,R_000137,5,个, +201002327,201002336,801000001,R_000138,30,毫升, +201002327,201002337,801000001,R_000139,8,克, +201002327,201002338,801000001,R_000140,5,克, +201002327,201002339,801000001,R_000141,4,颗, +201002327,201002340,801000001,R_000142,3,个, +201002327,201002341,801000001,R_000143,3,片, +201002327,201002342,801000001,R_000144,20,克, +201002327,201002343,801000001,R_000145,100,毫升, +201002327,201002344,801000003,R_000146,,,1.0 +201002327,201002345,801000003,R_000147,,,2.0 +201002327,201002346,801000003,R_000148,,,3.0 +201002327,201002347,801000003,R_000149,,,4.0 +201002327,201002348,801000003,R_000150,,,5.0 +201002327,201002349,801000003,R_000151,,,6.0 +201002327,720000000,801000004,R_000152,,, +201002327,640000000,801000005,R_000153,,, +201002350,201002351,801000001,R_000154,250,克, +201002350,201002352,801000001,R_000155,2,棵, +201002350,201002353,801000001,R_000156,25,克, +201002350,201002354,801000001,R_000157,15,克, +201002350,201002355,801000001,R_000158,1,把, +201002350,201002356,801000001,R_000159,5,毫升, +201002350,201002357,801000001,R_000160,15,毫升, +201002350,201002358,801000001,R_000161,5,毫升, +201002350,201002359,801000001,R_000162,5,克, +201002350,201002360,801000003,R_000163,,,1.0 +201002350,201002361,801000003,R_000164,,,2.0 +201002350,201002362,801000003,R_000165,,,3.0 +201002350,201002363,801000003,R_000166,,,4.0 +201002350,201002364,801000003,R_000167,,,5.0 +201002350,201002365,801000003,R_000168,,,6.0 +201002350,201002366,801000003,R_000169,,,7.0 +201002350,201002367,801000003,R_000170,,,8.0 +201002350,201002368,801000003,R_000171,,,9.0 +201002350,720000000,801000004,R_000172,,, +201002350,640000000,801000005,R_000173,,, +201002369,201002370,801000001,R_000174,750,g, +201002369,201002371,801000001,R_000175,300,g, +201002369,201002372,801000001,R_000176,30,g, +201002369,201002373,801000001,R_000177,25,g, +201002369,201002374,801000001,R_000178,25,g, +201002369,201002375,801000001,R_000179,10,g, +201002369,201002376,801000001,R_000180,5,g, +201002369,201002377,801000001,R_000181,5,g, +201002369,201002378,801000001,R_000182,5,g, +201002369,201002379,801000001,R_000183,5,g, +201002369,201002380,801000001,R_000184,10,g, +201002369,201002381,801000001,R_000185,5,g, +201002369,201002382,801000001,R_000186,5,g, +201002369,201002383,801000001,R_000187,5,g, +201002369,201002384,801000003,R_000188,,,1.0 +201002369,201002385,801000003,R_000189,,,2.0 +201002369,201002386,801000003,R_000190,,,3.0 +201002369,201002387,801000003,R_000191,,,4.0 +201002369,201002388,801000003,R_000192,,,5.0 +201002369,201002389,801000003,R_000193,,,6.0 +201002369,201002390,801000003,R_000194,,,7.0 +201002369,720000000,801000004,R_000195,,, +201002369,630000000,801000005,R_000196,,, +201002391,201002392,801000001,R_000197,100-125,g, +201002391,201002393,801000001,R_000198,40-55,g, +201002391,201002394,801000001,R_000199,25,g, +201002391,201002395,801000001,R_000200,100-125,g, +201002391,201002396,801000001,R_000201,25-40,g, +201002391,201002397,801000001,R_000202,15,g, +201002391,201002398,801000001,R_000203,10,g, +201002391,201002399,801000001,R_000204,125,ml, +201002391,201002400,801000001,R_000205,0.5,瓣, +201002391,201002401,801000003,R_000206,,,1.0 +201002391,201002402,801000003,R_000207,,,2.0 +201002391,201002403,801000003,R_000208,,,3.0 +201002391,201002404,801000003,R_000209,,,4.0 +201002391,201002405,801000003,R_000210,,,5.0 +201002391,201002406,801000003,R_000211,,,6.0 +201002391,201002407,801000003,R_000212,,,7.0 +201002391,201002408,801000003,R_000213,,,8.0 +201002391,201002409,801000003,R_000214,,,9.0 +201002391,201002410,801000003,R_000215,,,10.0 +201002391,201002411,801000003,R_000216,,,11.0 +201002391,201002412,801000003,R_000217,,,12.0 +201002391,201002413,801000003,R_000218,,,13.0 +201002391,201002414,801000003,R_000219,,,14.0 +201002391,720000000,801000004,R_000220,,, +201002391,630000000,801000005,R_000221,,, +201002415,201002416,801000001,R_000222,650,g, +201002415,201002417,801000001,R_000223,50,ml, +201002415,201002418,801000001,R_000224,250,g, +201002415,201002419,801000001,R_000225,250,ml, +201002415,201002420,801000001,R_000226,20,ml, +201002415,201002421,801000001,R_000227,10,ml, +201002415,201002422,801000001,R_000228,3,g, +201002415,201002423,801000001,R_000229,0-50,g, +201002415,201002424,801000001,R_000230,0-50,g, +201002415,201002425,801000001,R_000231,50,g, +201002415,201002426,801000001,R_000232,50,g, +201002415,201002427,801000003,R_000233,,,1.0 +201002415,201002428,801000003,R_000234,,,2.0 +201002415,201002429,801000003,R_000235,,,3.0 +201002415,201002430,801000003,R_000236,,,4.0 +201002415,201002431,801000003,R_000237,,,5.0 +201002415,201002432,801000003,R_000238,,,6.0 +201002415,201002433,801000003,R_000239,,,7.0 +201002415,720000000,801000004,R_000240,,, +201002415,630000000,801000005,R_000241,,, +201002434,201002435,801000001,R_000001,4,个, +201002434,201002436,801000001,R_000002,400,克, +201002434,201002437,801000001,R_000003,5,克, +201002434,201002438,801000001,R_000004,50,克, +201002434,201002439,801000001,R_000005,1,根, +201002434,201002440,801000001,R_000006,5,克, +201002434,201002441,801000001,R_000007,5,克, +201002434,201002442,801000001,R_000008,35,毫升, +201002434,201002443,801000003,R_000009,,,1.0 +201002434,201002444,801000003,R_000010,,,2.0 +201002434,201002445,801000003,R_000011,,,3.0 +201002434,201002446,801000003,R_000012,,,4.0 +201002434,201002447,801000003,R_000013,,,5.0 +201002434,201002448,801000003,R_000014,,,6.0 +201002434,201002449,801000003,R_000015,,,7.0 +201002434,201002450,801000003,R_000016,,,8.0 +201002434,201002451,801000003,R_000017,,,9.0 +201002434,201002452,801000003,R_000018,,,10.0 +201002434,201002453,801000003,R_000019,,,11.0 +201002434,720000000,801000004,R_000020,,, +201002434,630000000,801000005,R_000021,,, +201002454,201002455,801000001,R_000022,350,g, +201002454,201002456,801000001,R_000023,350,g, +201002454,201002457,801000001,R_000024,180,g, +201002454,201002458,801000001,R_000025,10,g, +201002454,201002459,801000001,R_000026,4,支, +201002454,201002460,801000001,R_000027,150,g, +201002454,201002461,801000001,R_000028,150,g, +201002454,201002462,801000001,R_000029,250,g, +201002454,201002463,801000001,R_000030,10,g, +201002454,201002464,801000001,R_000031,10,g, +201002454,201002465,801000001,R_000032,5,g, +201002454,201002466,801000001,R_000033,5,g, +201002454,201002467,801000001,R_000034,2,g, +201002454,201002468,801000001,R_000035,15,g, +201002454,201002469,801000001,R_000036,2,g, +201002454,201002470,801000001,R_000037,2,g, +201002454,201002471,801000001,R_000038,25,g, +201002454,201002472,801000001,R_000039,20,g, +201002454,201002473,801000001,R_000040,10,g, +201002454,201002474,801000001,R_000041,5,g, +201002454,201002475,801000001,R_000042,10,g, +201002454,201002476,801000001,R_000043,5,g, +201002454,201002477,801000003,R_000044,,,1.0 +201002454,201002478,801000003,R_000045,,,2.0 +201002454,201002479,801000003,R_000046,,,3.0 +201002454,201002480,801000003,R_000047,,,4.0 +201002454,201002481,801000003,R_000048,,,5.0 +201002454,201002482,801000003,R_000049,,,6.0 +201002454,201002483,801000003,R_000050,,,7.0 +201002454,201002484,801000003,R_000051,,,8.0 +201002454,201002485,801000003,R_000052,,,9.0 +201002454,720000000,801000004,R_000053,,, +201002454,640000000,801000005,R_000054,,, +201002486,201002487,801000001,R_000055,800,g, +201002486,201002488,801000001,R_000056,200,g, +201002486,201002489,801000001,R_000057,150,g, +201002486,201002490,801000001,R_000058,120,g, +201002486,201002491,801000001,R_000059,30,ml, +201002486,201002492,801000001,R_000060,5,g, +201002486,201002493,801000001,R_000061,5,g, +201002486,201002494,801000001,R_000062,5,g, +201002486,201002495,801000001,R_000063,5,g, +201002486,201002496,801000001,R_000064,10,g, +201002486,201002497,801000001,R_000065,5,g, +201002486,201002498,801000001,R_000066,30,ml, +201002486,201002499,801000003,R_000067,,,1.0 +201002486,201002500,801000003,R_000068,,,2.0 +201002486,201002501,801000003,R_000069,,,3.0 +201002486,201002502,801000003,R_000070,,,4.0 +201002486,201002503,801000003,R_000071,,,5.0 +201002486,201002504,801000003,R_000072,,,6.0 +201002486,201002505,801000003,R_000073,,,7.0 +201002486,201002506,801000003,R_000074,,,8.0 +201002486,201002507,801000003,R_000075,,,9.0 +201002486,201002508,801000003,R_000076,,,10.0 +201002486,201002509,801000003,R_000077,,,11.0 +201002486,201002510,801000003,R_000078,,,12.0 +201002486,720000000,801000004,R_000079,,, +201002486,630000000,801000005,R_000080,,, +201002511,201002512,801000001,R_000081,400,g, +201002511,201002513,801000001,R_000082,200,g, +201002511,201002514,801000001,R_000083,30,g, +201002511,201002515,801000001,R_000084,30,g, +201002511,201002516,801000001,R_000085,30,g, +201002511,201002517,801000001,R_000086,15,ml, +201002511,201002518,801000001,R_000087,6,ml, +201002511,201002519,801000003,R_000088,,,1.0 +201002511,201002520,801000003,R_000089,,,2.0 +201002511,201002521,801000003,R_000090,,,3.0 +201002511,201002522,801000003,R_000091,,,4.0 +201002511,201002523,801000003,R_000092,,,5.0 +201002511,201002524,801000003,R_000093,,,6.0 +201002511,201002525,801000003,R_000094,,,7.0 +201002511,201002526,801000003,R_000095,,,8.0 +201002511,201002527,801000003,R_000096,,,9.0 +201002511,720000000,801000004,R_000097,,, +201002511,640000000,801000005,R_000098,,, +201002528,201002529,801000001,R_000099,800,克, +201002528,201002530,801000001,R_000100,25,克, +201002528,201002531,801000001,R_000101,7.5,克, +201002528,201002532,801000001,R_000102,10,克, +201002528,201002533,801000001,R_000103,20,克, +201002528,201002534,801000001,R_000104,40,克, +201002528,201002535,801000001,R_000105,25,克, +201002528,201002536,801000001,R_000106,15,克, +201002528,201002537,801000001,R_000107,10,克, +201002528,201002538,801000001,R_000108,30,克, +201002528,201002539,801000001,R_000109,450,毫升, +201002528,201002540,801000001,R_000110,10,毫升, +201002528,201002541,801000001,R_000111,7.5,毫升, +201002528,201002542,801000001,R_000112,20,毫升, +201002528,201002543,801000001,R_000113,200,毫升, +201002528,201002544,801000001,R_000114,5,克, +201002528,201002545,801000003,R_000115,,,1.0 +201002528,201002546,801000003,R_000116,,,2.0 +201002528,201002547,801000003,R_000117,,,3.0 +201002528,201002548,801000003,R_000118,,,4.0 +201002528,201002549,801000003,R_000119,,,5.0 +201002528,201002550,801000003,R_000120,,,6.0 +201002528,201002551,801000003,R_000121,,,7.0 +201002528,201002552,801000003,R_000122,,,8.0 +201002528,201002553,801000003,R_000123,,,9.0 +201002528,201002554,801000003,R_000124,,,10.0 +201002528,720000000,801000004,R_000125,,, +201002528,640000000,801000005,R_000126,,, +201002555,201002556,801000001,R_000127,1000,克, +201002555,201002557,801000001,R_000128,4,个, +201002555,201002558,801000001,R_000129,2,个, +201002555,201002559,801000001,R_000130,1,盒, +201002555,201002560,801000001,R_000131,50,克, +201002555,201002561,801000001,R_000132,5,克, +201002555,201002562,801000001,R_000133,5,克, +201002555,201002563,801000001,R_000134,250,毫升, +201002555,201002564,801000001,R_000135,适量,毫升, +201002555,201002565,801000003,R_000136,,,1.0 +201002555,201002566,801000003,R_000137,,,2.0 +201002555,201002567,801000003,R_000138,,,3.0 +201002555,201002568,801000003,R_000139,,,4.0 +201002555,201002569,801000003,R_000140,,,5.0 +201002555,201002570,801000003,R_000141,,,6.0 +201002555,201002571,801000003,R_000142,,,7.0 +201002555,201002572,801000003,R_000143,,,8.0 +201002555,201002573,801000003,R_000144,,,9.0 +201002555,201002574,801000003,R_000145,,,10.0 +201002555,720000000,801000004,R_000146,,, +201002555,650000000,801000005,R_000147,,, +201002575,201002576,801000001,R_000148,400,g, +201002575,201002577,801000001,R_000149,200,g, +201002575,201002578,801000001,R_000150,60,g, +201002575,201002579,801000001,R_000151,10,g, +201002575,201002580,801000001,R_000152,3,g, +201002575,201002581,801000001,R_000153,3,g, +201002575,201002582,801000001,R_000154,2,g, +201002575,201002583,801000001,R_000155,5,g, +201002575,201002584,801000001,R_000156,2,g, +201002575,201002585,801000001,R_000157,5,g, +201002575,201002586,801000001,R_000158,20,g, +201002575,201002587,801000001,R_000159,40,g, +201002575,201002588,801000001,R_000160,30,g, +201002575,201002589,801000001,R_000161,2,g, +201002575,201002590,801000001,R_000162,宽油,ml, +201002575,201002591,801000003,R_000163,,,1.0 +201002575,201002592,801000003,R_000164,,,2.0 +201002575,201002593,801000003,R_000165,,,3.0 +201002575,201002594,801000003,R_000166,,,4.0 +201002575,201002595,801000003,R_000167,,,5.0 +201002575,201002596,801000003,R_000168,,,6.0 +201002575,201002597,801000003,R_000169,,,7.0 +201002575,201002598,801000003,R_000170,,,8.0 +201002575,201002599,801000003,R_000171,,,9.0 +201002575,201002600,801000003,R_000172,,,10.0 +201002575,720000000,801000004,R_000173,,, +201002575,640000000,801000005,R_000174,,, +201002601,201002602,801000001,R_000175,500,g, +201002601,201002603,801000001,R_000176,1,根, +201002601,201002604,801000001,R_000177,8,片, +201002601,201002605,801000001,R_000178,5,片, +201002601,201002606,801000001,R_000179,1,把, +201002601,201002607,801000001,R_000180,2,片, +201002601,201002608,801000001,R_000181,1,小块, +201002601,201002609,801000001,R_000182,2,个, +201002601,201002610,801000001,R_000183,2,片, +201002601,201002611,801000001,R_000184,1,块, +201002601,201002612,801000001,R_000185,30,g, +201002601,201002613,801000001,R_000186,15,g, +201002601,201002614,801000001,R_000187,15,g, +201002601,201002615,801000001,R_000188,10,g, +201002601,201002616,801000001,R_000189,5,g, +201002601,201002617,801000001,R_000190,15,g, +201002601,201002618,801000003,R_000191,,,1.0 +201002601,201002619,801000003,R_000192,,,2.0 +201002601,201002620,801000003,R_000193,,,3.0 +201002601,201002621,801000003,R_000194,,,4.0 +201002601,201002622,801000003,R_000195,,,5.0 +201002601,201002623,801000003,R_000196,,,6.0 +201002601,201002624,801000003,R_000197,,,7.0 +201002601,201002625,801000003,R_000198,,,8.0 +201002601,201002626,801000003,R_000199,,,9.0 +201002601,720000000,801000004,R_000200,,, +201002601,640000000,801000005,R_000201,,, +201002627,201002628,801000001,R_000202,300,g, +201002627,201002629,801000001,R_000203,100,g, +201002627,201002630,801000001,R_000204,200,g, +201002627,201002631,801000001,R_000205,10,ml, +201002627,201002632,801000001,R_000206,5,ml, +201002627,201002633,801000001,R_000207,5,ml, +201002627,201002634,801000001,R_000208,2,片, +201002627,201002635,801000001,R_000209,3,颗, +201002627,201002636,801000001,R_000210,100,ml, +201002627,201002637,801000001,R_000211,1,根, +201002627,201002638,801000001,R_000212,10,g, +201002627,201002639,801000001,R_000213,10,g, +201002627,201002640,801000003,R_000214,,,1.0 +201002627,201002641,801000003,R_000215,,,2.0 +201002627,201002642,801000003,R_000216,,,3.0 +201002627,201002643,801000003,R_000217,,,4.0 +201002627,201002644,801000003,R_000218,,,5.0 +201002627,201002645,801000003,R_000219,,,6.0 +201002627,201002646,801000003,R_000220,,,7.0 +201002627,720000000,801000004,R_000221,,, +201002627,640000000,801000005,R_000222,,, +201002647,201002648,801000001,R_000223,1000,g, +201002647,201002649,801000001,R_000224,750,g, +201002647,201002650,801000001,R_000225,100,g, +201002647,201002651,801000001,R_000226,50,g, +201002647,201002652,801000001,R_000227,50,g, +201002647,201002653,801000001,R_000228,20,g, +201002647,201002654,801000001,R_000229,5,个, +201002647,201002655,801000001,R_000230,4,瓣, +201002647,201002656,801000001,R_000231,50,g, +201002647,201002657,801000001,R_000232,5,g, +201002647,201002658,801000001,R_000233,7,ml, +201002647,201002659,801000001,R_000234,10,g, +201002647,201002660,801000001,R_000235,100,g, +201002647,201002661,801000001,R_000236,1000,ml, +201002647,201002662,801000001,R_000237,适量,, +201002647,201002663,801000001,R_000238,适量,片, +201002647,201002664,801000001,R_000239,适量,, +201002647,201002665,801000003,R_000240,,,1.0 +201002647,201002666,801000003,R_000241,,,2.0 +201002647,201002667,801000003,R_000242,,,3.0 +201002647,201002668,801000003,R_000243,,,4.0 +201002647,201002669,801000003,R_000244,,,5.0 +201002647,201002670,801000003,R_000245,,,6.0 +201002647,201002671,801000003,R_000246,,,7.0 +201002647,201002672,801000003,R_000247,,,8.0 +201002647,720000000,801000004,R_000248,,, +201002647,640000000,801000005,R_000249,,, +201002673,201002674,801000001,R_000001,1000,g, +201002673,201002675,801000001,R_000002,4,片, +201002673,201002676,801000001,R_000003,65,g, +201002673,201002677,801000001,R_000004,3,段, +201002673,201002678,801000001,R_000005,10,瓣, +201002673,201002679,801000001,R_000006,12,个, +201002673,201002680,801000001,R_000007,0.5,个, +201002673,201002681,801000001,R_000008,75,g, +201002673,201002682,801000001,R_000009,30,g, +201002673,201002683,801000001,R_000010,50,g, +201002673,201002684,801000001,R_000011,10,g, +201002673,201002685,801000001,R_000012,3,g, +201002673,201002686,801000001,R_000013,10,ml, +201002673,201002687,801000001,R_000014,3,颗, +201002673,201002688,801000001,R_000015,2,颗, +201002673,201002689,801000003,R_000016,,,1.0 +201002673,201002690,801000003,R_000017,,,2.0 +201002673,201002691,801000003,R_000018,,,3.0 +201002673,201002692,801000003,R_000019,,,4.0 +201002673,201002693,801000003,R_000020,,,5.0 +201002673,201002694,801000003,R_000021,,,6.0 +201002673,201002695,801000003,R_000022,,,7.0 +201002673,201002696,801000003,R_000023,,,8.0 +201002673,720000000,801000004,R_000024,,, +201002673,650000000,801000005,R_000025,,, +201002697,201002698,801000001,R_000026,500,g, +201002697,201002699,801000001,R_000027,30,g, +201002697,201002700,801000001,R_000028,30,g, +201002697,201002701,801000001,R_000029,40,g, +201002697,201002702,801000001,R_000030,35,g, +201002697,201002703,801000001,R_000031,5,ml, +201002697,201002704,801000001,R_000032,5,ml, +201002697,201002705,801000001,R_000033,500,ml, +201002697,201002706,801000001,R_000034,20,g, +201002697,201002707,801000001,R_000035,10,g, +201002697,201002708,801000001,R_000036,5,根, +201002697,201002709,801000001,R_000037,7,片, +201002697,201002710,801000001,R_000038,7.5,个, +201002697,201002711,801000001,R_000039,1,个, +201002697,201002712,801000001,R_000040,7.5,瓣, +201002697,201002713,801000001,R_000041,1,片, +201002697,201002714,801000001,R_000042,4.5,个, +201002697,201002715,801000001,R_000043,10,g, +201002697,201002716,801000003,R_000044,,,1.0 +201002697,201002717,801000003,R_000045,,,2.0 +201002697,201002718,801000003,R_000046,,,3.0 +201002697,201002719,801000003,R_000047,,,4.0 +201002697,201002720,801000003,R_000048,,,5.0 +201002697,201002721,801000003,R_000049,,,6.0 +201002697,201002722,801000003,R_000050,,,7.0 +201002697,201002723,801000003,R_000051,,,8.0 +201002697,201002724,801000003,R_000052,,,9.0 +201002697,201002725,801000003,R_000053,,,10.0 +201002697,201002726,801000003,R_000054,,,11.0 +201002697,201002727,801000003,R_000055,,,12.0 +201002697,201002728,801000003,R_000056,,,13.0 +201002697,201002729,801000003,R_000057,,,14.0 +201002697,201002730,801000003,R_000058,,,15.0 +201002697,201002731,801000003,R_000059,,,16.0 +201002697,201002732,801000003,R_000060,,,17.0 +201002697,720000000,801000004,R_000061,,, +201002697,650000000,801000005,R_000062,,, +201002733,201002734,801000001,R_000063,550,g, +201002733,201002735,801000001,R_000064,30,g, +201002733,201002736,801000001,R_000065,0.5,头, +201002733,201002737,801000001,R_000066,1,条, +201002733,201002738,801000001,R_000067,2,片, +201002733,201002739,801000001,R_000068,0.5,g, +201002733,201002740,801000001,R_000069,2,个, +201002733,201002741,801000001,R_000070,3,个, +201002733,201002742,801000001,R_000071,3,个, +201002733,201002743,801000001,R_000072,2,片, +201002733,201002744,801000001,R_000073,2,块, +201002733,201002745,801000001,R_000074,15,g, +201002733,201002746,801000001,R_000075,10,g, +201002733,201002747,801000001,R_000076,10,g, +201002733,201002748,801000001,R_000077,20,g, +201002733,201002749,801000001,R_000078,50,g, +201002733,201002750,801000001,R_000079,20,g, +201002733,201002751,801000001,R_000080,5,g, +201002733,201002752,801000001,R_000081,60,g, +201002733,201002753,801000001,R_000082,20,g, +201002733,201002754,801000003,R_000083,,,1.0 +201002733,201002755,801000003,R_000084,,,2.0 +201002733,201002756,801000003,R_000085,,,3.0 +201002733,201002757,801000003,R_000086,,,4.0 +201002733,201002758,801000003,R_000087,,,5.0 +201002733,201002759,801000003,R_000088,,,6.0 +201002733,201002760,801000003,R_000089,,,7.0 +201002733,201002761,801000003,R_000090,,,8.0 +201002733,201002762,801000003,R_000091,,,9.0 +201002733,201002763,801000003,R_000092,,,10.0 +201002733,201002764,801000003,R_000093,,,11.0 +201002733,201002765,801000003,R_000094,,,12.0 +201002733,201002766,801000003,R_000095,,,13.0 +201002733,201002767,801000003,R_000096,,,14.0 +201002733,201002768,801000003,R_000097,,,15.0 +201002733,201002769,801000003,R_000098,,,16.0 +201002733,201002770,801000003,R_000099,,,17.0 +201002733,201002771,801000003,R_000100,,,18.0 +201002733,201002772,801000003,R_000101,,,19.0 +201002733,201002773,801000003,R_000102,,,20.0 +201002733,201002774,801000003,R_000103,,,21.0 +201002733,201002775,801000003,R_000104,,,22.0 +201002733,720000000,801000004,R_000105,,, +201002733,640000000,801000005,R_000106,,, +201002776,201002777,801000001,R_000107,200,g, +201002776,201002778,801000001,R_000108,30,g, +201002776,201002779,801000001,R_000109,2,g, +201002776,201002780,801000001,R_000110,300,ml, +201002776,201002781,801000001,R_000111,5,g, +201002776,201002782,801000001,R_000112,30,ml, +201002776,201002783,801000001,R_000113,20,ml, +201002776,201002784,801000001,R_000114,1,个, +201002776,201002785,801000001,R_000115,10,g, +201002776,201002786,801000001,R_000116,2,g, +201002776,201002787,801000001,R_000117,2,g, +201002776,201002788,801000003,R_000118,,,1.0 +201002776,201002789,801000003,R_000119,,,2.0 +201002776,201002790,801000003,R_000120,,,3.0 +201002776,201002791,801000003,R_000121,,,4.0 +201002776,201002792,801000003,R_000122,,,5.0 +201002776,201002793,801000003,R_000123,,,6.0 +201002776,201002794,801000003,R_000124,,,7.0 +201002776,201002795,801000003,R_000125,,,8.0 +201002776,201002796,801000003,R_000126,,,9.0 +201002776,720000000,801000004,R_000127,,, +201002776,640000000,801000005,R_000128,,, +201002797,201002798,801000001,R_000129,300,g, +201002797,201002799,801000001,R_000130,100,g, +201002797,201002800,801000001,R_000131,1,个, +201002797,201002801,801000001,R_000132,5,根, +201002797,201002802,801000001,R_000133,10,g, +201002797,201002803,801000001,R_000134,10,ml, +201002797,201002804,801000001,R_000135,15,g, +201002797,201002805,801000001,R_000136,5,g, +201002797,201002806,801000001,R_000137,20,g, +201002797,201002807,801000001,R_000138,3,瓣, +201002797,201002808,801000001,R_000139,1,根, +201002797,201002809,801000001,R_000140,8,g, +201002797,201002810,801000003,R_000141,,,1.0 +201002797,201002811,801000003,R_000142,,,2.0 +201002797,201002812,801000003,R_000143,,,3.0 +201002797,201002813,801000003,R_000144,,,4.0 +201002797,201002814,801000003,R_000145,,,5.0 +201002797,201002815,801000003,R_000146,,,6.0 +201002797,201002816,801000003,R_000147,,,7.0 +201002797,201002817,801000003,R_000148,,,8.0 +201002797,201002818,801000003,R_000149,,,9.0 +201002797,201002819,801000003,R_000150,,,10.0 +201002797,201002820,801000003,R_000151,,,11.0 +201002797,720000000,801000004,R_000152,,, +201002797,630000000,801000005,R_000153,,, +201002821,201002822,801000001,R_000154,500,g, +201002821,201002823,801000001,R_000155,1,节, +201002821,201002824,801000001,R_000156,2,根, +201002821,201002825,801000001,R_000157,30,g, +201002821,201002826,801000001,R_000158,1,颗, +201002821,201002827,801000001,R_000159,3,片, +201002821,201002828,801000001,R_000160,20,ml, +201002821,201002829,801000003,R_000161,,,1.0 +201002821,201002830,801000003,R_000162,,,2.0 +201002821,201002831,801000003,R_000163,,,3.0 +201002821,201002832,801000003,R_000164,,,4.0 +201002821,201002833,801000003,R_000165,,,5.0 +201002821,201002834,801000003,R_000166,,,6.0 +201002821,201002835,801000003,R_000167,,,7.0 +201002821,201002836,801000003,R_000168,,,8.0 +201002821,720000000,801000004,R_000169,,, +201002821,630000000,801000005,R_000170,,, +201002837,201002838,801000001,R_000171,500,g, +201002837,201002839,801000001,R_000172,10,g, +201002837,201002840,801000001,R_000173,5,片, +201002837,201002841,801000001,R_000174,3,片, +201002837,201002842,801000001,R_000175,1,小块, +201002837,201002843,801000001,R_000176,6,颗, +201002837,201002844,801000001,R_000177,20,g, +201002837,201002845,801000001,R_000178,5,g, +201002837,201002846,801000001,R_000179,2,g, +201002837,201002847,801000001,R_000180,2,g, +201002837,201002848,801000001,R_000181,3,颗, +201002837,201002849,801000001,R_000182,适量,, +201002837,201002850,801000001,R_000183,没过肉,, +201002837,201002851,801000003,R_000184,,,1.0 +201002837,201002852,801000003,R_000185,,,2.0 +201002837,201002853,801000003,R_000186,,,3.0 +201002837,201002854,801000003,R_000187,,,4.0 +201002837,201002855,801000003,R_000188,,,5.0 +201002837,201002856,801000003,R_000189,,,6.0 +201002837,720000000,801000004,R_000190,,, +201002837,630000000,801000005,R_000191,,, +201002857,201002858,801000001,R_000192,1000,克, +201002857,201002859,801000001,R_000193,100,克, +201002857,201002860,801000001,R_000194,300,克, +201002857,201002861,801000001,R_000195,50,克, +201002857,201002862,801000001,R_000196,50,克, +201002857,201002863,801000001,R_000197,5,克, +201002857,201002864,801000001,R_000198,50,克, +201002857,201002865,801000001,R_000199,20,克, +201002857,201002866,801000001,R_000200,10,克, +201002857,201002867,801000001,R_000201,10,克, +201002857,201002868,801000001,R_000202,100,克, +201002857,201002869,801000003,R_000203,,,1.0 +201002857,201002870,801000003,R_000204,,,2.0 +201002857,201002871,801000003,R_000205,,,3.0 +201002857,201002872,801000003,R_000206,,,4.0 +201002857,201002873,801000003,R_000207,,,5.0 +201002857,201002874,801000003,R_000208,,,6.0 +201002857,201002875,801000003,R_000209,,,7.0 +201002857,720000000,801000004,R_000210,,, +201002857,640000000,801000005,R_000211,,, +201002876,201002877,801000001,R_000212,475,克, +201002876,201002878,801000001,R_000213,12.5,毫升, +201002876,201002879,801000001,R_000214,22.5,克, +201002876,201002880,801000001,R_000215,5,克, +201002876,201002881,801000001,R_000216,2,克, +201002876,201002882,801000001,R_000217,7.5,克, +201002876,201002883,801000001,R_000218,2,克, +201002876,201002884,801000001,R_000219,7.5,个, +201002876,201002885,801000001,R_000220,7.5,个, +201002876,201002886,801000001,R_000221,7.5,个, +201002876,201002887,801000003,R_000222,,,1.0 +201002876,201002888,801000003,R_000223,,,2.0 +201002876,201002889,801000003,R_000224,,,3.0 +201002876,201002890,801000003,R_000225,,,4.0 +201002876,201002891,801000003,R_000226,,,5.0 +201002876,201002892,801000003,R_000227,,,6.0 +201002876,201002893,801000003,R_000228,,,7.0 +201002876,201002894,801000003,R_000229,,,8.0 +201002876,201002895,801000003,R_000230,,,9.0 +201002876,201002896,801000003,R_000231,,,10.0 +201002876,201002897,801000003,R_000232,,,11.0 +201002876,201002898,801000003,R_000233,,,12.0 +201002876,720000000,801000004,R_000234,,, +201002876,640000000,801000005,R_000235,,, +201002899,201002900,801000001,R_000236,1000,g, +201002899,201002901,801000001,R_000237,4000,g, +201002899,201002902,801000001,R_000238,13,g, +201002899,201002903,801000001,R_000239,10,g, +201002899,201002904,801000001,R_000240,15,g, +201002899,201002905,801000001,R_000241,50,ml, +201002899,201002906,801000001,R_000242,20,ml, +201002899,201002907,801000001,R_000243,20,g, +201002899,201002908,801000001,R_000244,20,g, +201002899,201002909,801000001,R_000245,10,g, +201002899,201002910,801000001,R_000246,5,g, +201002899,201002911,801000001,R_000247,50,ml, +201002899,201002912,801000001,R_000248,20,g, +201002899,201002913,801000003,R_000249,,,1.0 +201002899,201002914,801000003,R_000250,,,2.0 +201002899,201002915,801000003,R_000251,,,3.0 +201002899,201002916,801000003,R_000252,,,4.0 +201002899,201002917,801000003,R_000253,,,5.0 +201002899,201002918,801000003,R_000254,,,6.0 +201002899,201002919,801000003,R_000255,,,7.0 +201002899,720000000,801000004,R_000256,,, +201002899,650000000,801000005,R_000257,,, +201002920,201002921,801000001,R_000001,200,g, +201002920,201002922,801000001,R_000002,200,g, +201002920,201002923,801000001,R_000003,2,根, +201002920,201002924,801000001,R_000004,5,g, +201002920,201002925,801000001,R_000005,15,g, +201002920,201002926,801000001,R_000006,3,g, +201002920,201002927,801000001,R_000007,2,g, +201002920,201002928,801000001,R_000008,10,ml, +201002920,201002929,801000003,R_000009,,,1.0 +201002920,201002930,801000003,R_000010,,,2.0 +201002920,201002931,801000003,R_000011,,,3.0 +201002920,201002932,801000003,R_000012,,,4.0 +201002920,201002933,801000003,R_000013,,,5.0 +201002920,201002934,801000003,R_000014,,,6.0 +201002920,201002935,801000003,R_000015,,,7.0 +201002920,201002936,801000003,R_000016,,,8.0 +201002920,720000000,801000004,R_000017,,, +201002920,630000000,801000005,R_000018,,, +201002937,201002938,801000001,R_000019,300,g, +201002937,201002939,801000001,R_000020,30,g, +201002937,201002940,801000001,R_000021,300,ml, +201002937,201002941,801000001,R_000022,5,ml, +201002937,201002942,801000001,R_000023,5,ml, +201002937,201002943,801000001,R_000024,5,ml, +201002937,201002944,801000001,R_000025,2,g, +201002937,201002945,801000001,R_000026,2,片, +201002937,201002946,801000001,R_000027,2,g, +201002937,201002947,801000001,R_000028,10,g, +201002937,201002948,801000001,R_000029,5,ml, +201002937,201002949,801000001,R_000030,2,g, +201002937,201002950,801000003,R_000031,,,1.0 +201002937,201002951,801000003,R_000032,,,2.0 +201002937,201002952,801000003,R_000033,,,3.0 +201002937,201002953,801000003,R_000034,,,4.0 +201002937,201002954,801000003,R_000035,,,5.0 +201002937,201002955,801000003,R_000036,,,6.0 +201002937,201002956,801000003,R_000037,,,7.0 +201002937,720000000,801000004,R_000038,,, +201002937,640000000,801000005,R_000039,,, +201002957,201002958,801000001,R_000040,2~3,根, +201002957,201002959,801000001,R_000041,30,毫升, +201002957,201002960,801000001,R_000042,2,片, +201002957,201002961,801000001,R_000043,5,片, +201002957,201002962,801000001,R_000044,0.5,根, +201002957,201002963,801000001,R_000045,1,块, +201002957,201002964,801000001,R_000046,7-8,粒, +201002957,201002965,801000001,R_000047,30,毫升, +201002957,201002966,801000001,R_000048,20,毫升, +201002957,201002967,801000001,R_000049,20,毫升, +201002957,201002968,801000001,R_000050,8,克, +201002957,201002969,801000001,R_000051,4,个, +201002957,201002970,801000003,R_000052,,,1.0 +201002957,201002971,801000003,R_000053,,,2.0 +201002957,201002972,801000003,R_000054,,,3.0 +201002957,201002973,801000003,R_000055,,,4.0 +201002957,201002974,801000003,R_000056,,,5.0 +201002957,201002975,801000003,R_000057,,,6.0 +201002957,201002976,801000003,R_000058,,,7.0 +201002957,201002977,801000003,R_000059,,,8.0 +201002957,720000000,801000004,R_000060,,, +201002957,640000000,801000005,R_000061,,, +201002978,201002979,801000001,R_000062,1000,克, +201002978,201002980,801000001,R_000063,100-150,毫升, +201002978,201002981,801000001,R_000064,6,片, +201002978,201002982,801000001,R_000065,15,块, +201002978,201002983,801000001,R_000066,30,克, +201002978,201002984,801000001,R_000067,15,毫升, +201002978,201002985,801000001,R_000068,20,毫升, +201002978,201002986,801000001,R_000069,没过食材,适量, +201002978,201002987,801000001,R_000070,没过食材,适量, +201002978,201002988,801000001,R_000071,4,片, +201002978,201002989,801000001,R_000072,3,个, +201002978,201002990,801000001,R_000073,2-3,克, +201002978,201002991,801000001,R_000074,10,克, +201002978,201002992,801000001,R_000075,适量,根, +201002978,201002993,801000001,R_000076,适量,瓣, +201002978,201002994,801000003,R_000077,,,1.0 +201002978,201002995,801000003,R_000078,,,2.0 +201002978,201002996,801000003,R_000079,,,3.0 +201002978,201002997,801000003,R_000080,,,4.0 +201002978,201002998,801000003,R_000081,,,5.0 +201002978,201002999,801000003,R_000082,,,6.0 +201002978,201003000,801000003,R_000083,,,7.0 +201002978,201003001,801000003,R_000084,,,8.0 +201002978,720000000,801000004,R_000085,,, +201002978,640000000,801000005,R_000086,,, +201003002,201003003,801000001,R_000087,3.5,斤, +201003002,201003004,801000001,R_000088,6,片, +201003002,201003005,801000001,R_000089,15,克, +201003002,201003006,801000001,R_000090,10,毫升, +201003002,201003007,801000001,R_000091,15,毫升, +201003002,201003008,801000001,R_000092,5,毫升, +201003002,201003009,801000001,R_000093,750,毫升, +201003002,201003010,801000001,R_000094,3,片, +201003002,201003011,801000001,R_000095,2,个, +201003002,201003012,801000001,R_000096,1,个, +201003002,201003013,801000001,R_000097,40,克, +201003002,201003014,801000001,R_000098,2.5,克, +201003002,201003015,801000001,R_000099,1,根, +201003002,201003016,801000003,R_000100,,,1.0 +201003002,201003017,801000003,R_000101,,,2.0 +201003002,201003018,801000003,R_000102,,,3.0 +201003002,201003019,801000003,R_000103,,,4.0 +201003002,201003020,801000003,R_000104,,,5.0 +201003002,201003021,801000003,R_000105,,,6.0 +201003002,201003022,801000003,R_000106,,,7.0 +201003002,201003023,801000003,R_000107,,,8.0 +201003002,201003024,801000003,R_000108,,,9.0 +201003002,720000000,801000004,R_000109,,, +201003002,630000000,801000005,R_000110,,, +201003025,201003026,801000001,R_000111,500,克, +201003025,201003027,801000001,R_000112,2,个, +201003025,201003028,801000001,R_000113,2,个, +201003025,201003029,801000001,R_000114,适量,, +201003025,201003030,801000001,R_000115,适量,, +201003025,201003031,801000001,R_000116,适量,, +201003025,201003032,801000001,R_000117,4,片, +201003025,201003033,801000001,R_000118,适量,, +201003025,201003034,801000001,R_000119,适量,, +201003025,201003035,801000001,R_000120,适量,, +201003025,201003036,801000001,R_000121,300,克, +201003025,201003037,801000001,R_000122,3,克, +201003025,201003038,801000001,R_000123,180,毫升, +201003025,201003039,801000003,R_000124,,,1.0 +201003025,201003040,801000003,R_000125,,,2.0 +201003025,201003041,801000003,R_000126,,,3.0 +201003025,201003042,801000003,R_000127,,,4.0 +201003025,201003043,801000003,R_000128,,,5.0 +201003025,201003044,801000003,R_000129,,,6.0 +201003025,201003045,801000003,R_000130,,,7.0 +201003025,201003046,801000003,R_000131,,,8.0 +201003025,201003047,801000003,R_000132,,,9.0 +201003025,720000000,801000004,R_000133,,, +201003025,640000000,801000005,R_000134,,, +201003048,201003049,801000001,R_000135,3,根, +201003048,201003050,801000001,R_000136,200,g, +201003048,201003051,801000001,R_000137,2,g, +201003048,201003052,801000001,R_000138,5,g, +201003048,201003053,801000001,R_000139,30,g, +201003048,201003054,801000001,R_000140,8,g, +201003048,201003055,801000001,R_000141,2,g, +201003048,201003056,801000001,R_000142,25,g, +201003048,201003057,801000001,R_000143,10,g, +201003048,201003058,801000001,R_000144,适量,, +201003048,201003059,801000001,R_000145,适量,, +201003048,201003060,801000001,R_000146,适量,, +201003048,201003061,801000001,R_000147,适量,, +201003048,201003062,801000001,R_000148,适量,, +201003048,201003063,801000001,R_000149,适量,, +201003048,201003064,801000001,R_000150,适量,, +201003048,201003065,801000001,R_000151,适量,, +201003048,201003066,801000001,R_000152,适量,, +201003048,201003067,801000001,R_000153,适量,, +201003048,201003068,801000003,R_000154,,,1.0 +201003048,201003069,801000003,R_000155,,,2.0 +201003048,201003070,801000003,R_000156,,,3.0 +201003048,201003071,801000003,R_000157,,,4.0 +201003048,201003072,801000003,R_000158,,,5.0 +201003048,201003073,801000003,R_000159,,,6.0 +201003048,201003074,801000003,R_000160,,,7.0 +201003048,201003075,801000003,R_000161,,,8.0 +201003048,720000000,801000004,R_000162,,, +201003048,640000000,801000005,R_000163,,, +201003076,201003077,801000001,R_000164,300,g, +201003076,201003078,801000001,R_000165,50,g, +201003076,201003079,801000001,R_000166,30,g, +201003076,201003080,801000001,R_000167,3.5,瓣, +201003076,201003081,801000001,R_000168,10,g, +201003076,201003082,801000001,R_000169,10,g, +201003076,201003083,801000001,R_000170,5,g, +201003076,201003084,801000001,R_000171,40,g, +201003076,201003085,801000001,R_000172,40,g, +201003076,201003086,801000001,R_000173,20,ml, +201003076,201003087,801000001,R_000174,8,g, +201003076,201003088,801000001,R_000175,5,g, +201003076,201003089,801000001,R_000176,5,ml, +201003076,201003090,801000001,R_000177,210,g, +201003076,201003091,801000001,R_000178,70,g, +201003076,201003092,801000001,R_000179,5,g, +201003076,201003093,801000001,R_000180,1000,ml, +201003076,201003094,801000003,R_000181,,,1.0 +201003076,201003095,801000003,R_000182,,,2.0 +201003076,201003096,801000003,R_000183,,,3.0 +201003076,201003097,801000003,R_000184,,,4.0 +201003076,201003098,801000003,R_000185,,,5.0 +201003076,201003099,801000003,R_000186,,,6.0 +201003076,201003100,801000003,R_000187,,,7.0 +201003076,201003101,801000003,R_000188,,,8.0 +201003076,201003102,801000003,R_000189,,,9.0 +201003076,720000000,801000004,R_000190,,, +201003076,640000000,801000005,R_000191,,, +201003103,201003104,801000001,R_000192,250,g, +201003103,201003105,801000001,R_000193,2,个, +201003103,201003106,801000001,R_000194,20,g, +201003103,201003107,801000001,R_000195,10,g, +201003103,201003108,801000001,R_000196,30,g, +201003103,201003109,801000001,R_000197,5,g, +201003103,201003110,801000001,R_000198,3,g, +201003103,201003111,801000001,R_000199,15,g, +201003103,201003112,801000001,R_000200,3,g, +201003103,201003113,801000001,R_000201,2,个, +201003103,201003114,801000001,R_000202,20,g, +201003103,201003115,801000001,R_000203,80,ml, +201003103,201003116,801000003,R_000204,,,1.0 +201003103,201003117,801000003,R_000205,,,2.0 +201003103,201003118,801000003,R_000206,,,3.0 +201003103,201003119,801000003,R_000207,,,4.0 +201003103,201003120,801000003,R_000208,,,5.0 +201003103,720000000,801000004,R_000209,,, +201003103,630000000,801000005,R_000210,,, +201003121,201003122,801000001,R_000211,2,根, +201003121,201003123,801000001,R_000212,100,g, +201003121,201003124,801000001,R_000213,15,g, +201003121,201003125,801000001,R_000214,30,ml, +201003121,201003126,801000001,R_000215,5,g, +201003121,201003127,801000001,R_000216,1,片, +201003121,201003128,801000001,R_000217,1,个, +201003121,201003129,801000001,R_000218,5,ml, +201003121,201003130,801000001,R_000219,2,g, +201003121,201003131,801000003,R_000220,,,1.0 +201003121,201003132,801000003,R_000221,,,2.0 +201003121,201003133,801000003,R_000222,,,3.0 +201003121,201003134,801000003,R_000223,,,4.0 +201003121,201003135,801000003,R_000224,,,5.0 +201003121,201003136,801000003,R_000225,,,6.0 +201003121,201003137,801000003,R_000226,,,7.0 +201003121,720000000,801000004,R_000227,,, +201003121,630000000,801000005,R_000228,,, +201003138,201003139,801000001,R_000001,150,g, +201003138,201003140,801000001,R_000002,100,g, +201003138,201003141,801000001,R_000003,1,个, +201003138,201003142,801000001,R_000004,500,ml, +201003138,201003143,801000001,R_000005,5,g, +201003138,201003144,801000001,R_000006,100,g, +201003138,201003145,801000001,R_000007,5,ml, +201003138,201003146,801000001,R_000008,5,g, +201003138,201003147,801000001,R_000009,5,g, +201003138,201003148,801000001,R_000010,2,g, +201003138,201003149,801000001,R_000011,20,g, +201003138,201003150,801000001,R_000012,2,ml, +201003138,201003151,801000001,R_000013,2,朵, +201003138,201003152,801000001,R_000014,30,g, +201003138,201003153,801000003,R_000015,,,1.0 +201003138,201003154,801000003,R_000016,,,2.0 +201003138,201003155,801000003,R_000017,,,3.0 +201003138,201003156,801000003,R_000018,,,4.0 +201003138,201003157,801000003,R_000019,,,5.0 +201003138,201003158,801000003,R_000020,,,6.0 +201003138,201003159,801000003,R_000021,,,7.0 +201003138,201003160,801000003,R_000022,,,8.0 +201003138,201003161,801000003,R_000023,,,9.0 +201003138,201003162,801000003,R_000024,,,10.0 +201003138,720000000,801000004,R_000025,,, +201003138,640000000,801000005,R_000026,,, +201003163,201003164,801000001,R_000027,50,个, +201003163,201003165,801000001,R_000028,100,g, +201003163,201003166,801000001,R_000029,10,ml, +201003163,201003167,801000001,R_000030,10,ml, +201003163,201003168,801000003,R_000031,,,1.0 +201003163,201003169,801000003,R_000032,,,2.0 +201003163,201003170,801000003,R_000033,,,3.0 +201003163,201003171,801000003,R_000034,,,4.0 +201003163,201003172,801000003,R_000035,,,5.0 +201003163,201003173,801000003,R_000036,,,6.0 +201003163,720000000,801000004,R_000037,,, +201003163,620000000,801000005,R_000038,,, +201003174,201003175,801000001,R_000039,2000,g, +201003174,201003176,801000001,R_000040,250,ml, +201003174,201003177,801000001,R_000041,6,片, +201003174,201003178,801000001,R_000042,6,瓣, +201003174,201003179,801000001,R_000043,2,根, +201003174,201003180,801000001,R_000044,1000,g, +201003174,201003181,801000001,R_000045,50,ml, +201003174,201003182,801000001,R_000046,150,ml, +201003174,201003183,801000001,R_000047,10,ml, +201003174,201003184,801000001,R_000048,30,ml, +201003174,201003185,801000001,R_000049,8,g, +201003174,201003186,801000001,R_000050,5,g, +201003174,201003187,801000001,R_000051,100,ml, +201003174,201003188,801000001,R_000052,3-6,滴, +201003174,201003189,801000003,R_000053,,,1.0 +201003174,201003190,801000003,R_000054,,,2.0 +201003174,201003191,801000003,R_000055,,,3.0 +201003174,201003192,801000003,R_000056,,,4.0 +201003174,201003193,801000003,R_000057,,,5.0 +201003174,201003194,801000003,R_000058,,,6.0 +201003174,201003195,801000003,R_000059,,,7.0 +201003174,720000000,801000004,R_000060,,, +201003174,650000000,801000005,R_000061,,, +201003196,201003197,801000001,R_000062,600,克, +201003196,201003198,801000001,R_000063,1,根, +201003196,201003199,801000001,R_000064,4,片, +201003196,201003200,801000001,R_000065,35,毫升, +201003196,201003201,801000001,R_000066,3,克, +201003196,201003202,801000001,R_000067,0.5,个, +201003196,201003203,801000001,R_000068,2,片, +201003196,201003204,801000001,R_000069,15,毫升, +201003196,201003205,801000001,R_000070,适量,, +201003196,201003206,801000001,R_000071,15,毫升, +201003196,201003207,801000001,R_000072,适量,, +201003196,201003208,801000001,R_000073,2,克, +201003196,201003209,801000001,R_000074,3,个, +201003196,201003210,801000001,R_000075,3,个, +201003196,201003211,801000001,R_000076,1,个, +201003196,201003212,801000003,R_000077,,,1.0 +201003196,201003213,801000003,R_000078,,,2.0 +201003196,201003214,801000003,R_000079,,,3.0 +201003196,201003215,801000003,R_000080,,,4.0 +201003196,201003216,801000003,R_000081,,,5.0 +201003196,201003217,801000003,R_000082,,,6.0 +201003196,201003218,801000003,R_000083,,,7.0 +201003196,201003219,801000003,R_000084,,,8.0 +201003196,201003220,801000003,R_000085,,,9.0 +201003196,201003221,801000003,R_000086,,,10.0 +201003196,201003222,801000003,R_000087,,,11.0 +201003196,201003223,801000003,R_000088,,,12.0 +201003196,720000000,801000004,R_000089,,, +201003196,640000000,801000005,R_000090,,, +201003224,201003225,801000001,R_000091,3.5,个, +201003224,201003226,801000001,R_000092,500,克, +201003224,201003227,801000001,R_000093,25,毫升, +201003224,201003228,801000001,R_000094,2,段, +201003224,201003229,801000001,R_000095,2,片, +201003224,201003230,801000001,R_000096,10,克, +201003224,201003231,801000001,R_000097,10,克, +201003224,201003232,801000001,R_000098,适量,, +201003224,201003233,801000001,R_000099,适量,, +201003224,201003234,801000001,R_000100,适量,, +201003224,201003235,801000001,R_000101,7.5,毫升, +201003224,201003236,801000001,R_000102,3,小片, +201003224,201003237,801000001,R_000103,适量,, +201003224,201003238,801000003,R_000104,,,1.0 +201003224,201003239,801000003,R_000105,,,2.0 +201003224,201003240,801000003,R_000106,,,3.0 +201003224,201003241,801000003,R_000107,,,4.0 +201003224,201003242,801000003,R_000108,,,5.0 +201003224,201003243,801000003,R_000109,,,6.0 +201003224,201003244,801000003,R_000110,,,7.0 +201003224,720000000,801000004,R_000111,,, +201003224,650000000,801000005,R_000112,,, +201003245,201003246,801000001,R_000113,500,g, +201003245,201003247,801000001,R_000114,250,g, +201003245,201003248,801000001,R_000115,4,瓣, +201003245,201003249,801000001,R_000116,20,g, +201003245,201003250,801000001,R_000117,3,g, +201003245,201003251,801000001,R_000118,15,ml, +201003245,201003252,801000003,R_000119,,,1.0 +201003245,201003253,801000003,R_000120,,,2.0 +201003245,201003254,801000003,R_000121,,,3.0 +201003245,201003255,801000003,R_000122,,,4.0 +201003245,201003256,801000003,R_000123,,,5.0 +201003245,720000000,801000004,R_000124,,, +201003245,620000000,801000005,R_000125,,, +201003257,201003258,801000001,R_000126,250,g, +201003257,201003259,801000001,R_000127,1,汤匙, +201003257,201003260,801000001,R_000128,2,瓣, +201003257,201003261,801000001,R_000129,3,片, +201003257,201003262,801000001,R_000130,1,根, +201003257,201003263,801000001,R_000131,1.5,汤匙, +201003257,201003264,801000001,R_000132,0.5,茶匙, +201003257,201003265,801000001,R_000133,0.5,茶匙, +201003257,201003266,801000001,R_000134,0.5,茶匙, +201003257,201003267,801000001,R_000135,1,茶匙, +201003257,201003268,801000001,R_000136,1,汤匙, +201003257,201003269,801000001,R_000137,少许,, +201003257,201003270,801000003,R_000138,,,1.0 +201003257,201003271,801000003,R_000139,,,2.0 +201003257,201003272,801000003,R_000140,,,3.0 +201003257,201003273,801000003,R_000141,,,4.0 +201003257,201003274,801000003,R_000142,,,5.0 +201003257,720000000,801000004,R_000143,,, +201003257,630000000,801000005,R_000144,,, +201003275,201003276,801000001,R_000145,4,斤, +201003275,201003277,801000001,R_000146,0.5,瓶, +201003275,201003278,801000001,R_000147,2,个, +201003275,201003279,801000001,R_000148,500,克, +201003275,201003280,801000001,R_000149,3,根, +201003275,201003281,801000001,R_000150,2,片, +201003275,201003282,801000001,R_000151,2,个, +201003275,201003283,801000001,R_000152,2,个, +201003275,201003284,801000001,R_000153,2,斤, +201003275,201003285,801000001,R_000154,20,毫升, +201003275,201003286,801000001,R_000155,适量,, +201003275,201003287,801000001,R_000156,适量,, +201003275,201003288,801000001,R_000157,适量,, +201003275,201003289,801000003,R_000158,,,1.0 +201003275,201003290,801000003,R_000159,,,2.0 +201003275,201003291,801000003,R_000160,,,3.0 +201003275,201003292,801000003,R_000161,,,4.0 +201003275,201003293,801000003,R_000162,,,5.0 +201003275,201003294,801000003,R_000163,,,6.0 +201003275,201003295,801000003,R_000164,,,7.0 +201003275,720000000,801000004,R_000165,,, +201003275,640000000,801000005,R_000166,,, +201003296,201003297,801000001,R_000167,300,g, +201003296,201003298,801000001,R_000168,20,g, +201003296,201003299,801000001,R_000169,10,ml, +201003296,201003300,801000001,R_000170,30,ml, +201003296,201003301,801000001,R_000171,15,g, +201003296,201003302,801000001,R_000172,10,ml, +201003296,201003303,801000001,R_000173,10,ml, +201003296,201003304,801000001,R_000174,5,ml, +201003296,201003305,801000001,R_000175,1,个, +201003296,201003306,801000001,R_000176,2,粒, +201003296,201003307,801000001,R_000177,2,片, +201003296,201003308,801000003,R_000178,,,1.0 +201003296,201003309,801000003,R_000179,,,2.0 +201003296,201003310,801000003,R_000180,,,3.0 +201003296,201003311,801000003,R_000181,,,4.0 +201003296,201003312,801000003,R_000182,,,5.0 +201003296,201003313,801000003,R_000183,,,6.0 +201003296,720000000,801000004,R_000184,,, +201003296,640000000,801000005,R_000185,,, +201003314,201003315,801000001,R_000186,2000,克, +201003314,201003316,801000001,R_000187,1,片, +201003314,201003317,801000001,R_000188,3,片, +201003314,201003318,801000001,R_000189,0.5,根, +201003314,201003319,801000001,R_000190,15,毫升, +201003314,201003320,801000001,R_000191,1,块, +201003314,201003321,801000001,R_000192,7,粒, +201003314,201003322,801000001,R_000193,15,粒, +201003314,201003323,801000001,R_000194,30,毫升, +201003314,201003324,801000001,R_000195,15,毫升, +201003314,201003325,801000001,R_000196,8,克, +201003314,201003326,801000001,R_000197,4,个, +201003314,201003327,801000001,R_000198,15,毫升, +201003314,201003328,801000003,R_000199,,,1.0 +201003314,201003329,801000003,R_000200,,,2.0 +201003314,201003330,801000003,R_000201,,,3.0 +201003314,201003331,801000003,R_000202,,,4.0 +201003314,201003332,801000003,R_000203,,,5.0 +201003314,201003333,801000003,R_000204,,,6.0 +201003314,201003334,801000003,R_000205,,,7.0 +201003314,201003335,801000003,R_000206,,,8.0 +201003314,720000000,801000004,R_000207,,, +201003314,650000000,801000005,R_000208,,, +201003336,201003337,801000001,R_000001,200,g, +201003336,201003338,801000001,R_000002,10,g, +201003336,201003339,801000001,R_000003,500,ml, +201003336,201003340,801000001,R_000004,5,ml, +201003336,201003341,801000001,R_000005,5,g, +201003336,201003342,801000001,R_000006,5,g, +201003336,201003343,801000001,R_000007,5,ml, +201003336,201003344,801000001,R_000008,2,粒, +201003336,201003345,801000001,R_000009,1,根, +201003336,201003346,801000001,R_000010,30,g, +201003336,201003347,801000001,R_000011,1,个, +201003336,201003348,801000003,R_000012,,,1.0 +201003336,201003349,801000003,R_000013,,,2.0 +201003336,201003350,801000003,R_000014,,,3.0 +201003336,201003351,801000003,R_000015,,,4.0 +201003336,201003352,801000003,R_000016,,,5.0 +201003336,201003353,801000003,R_000017,,,6.0 +201003336,201003354,801000003,R_000018,,,7.0 +201003336,720000000,801000004,R_000019,,, +201003336,640000000,801000005,R_000020,,, +201003355,201003356,801000001,R_000021,200,g, +201003355,201003357,801000001,R_000022,300,g, +201003355,201003358,801000001,R_000023,200,g, +201003355,201003359,801000001,R_000024,10,g, +201003355,201003360,801000001,R_000025,5,g, +201003355,201003361,801000001,R_000026,12,g, +201003355,201003362,801000001,R_000027,7,g, +201003355,201003363,801000001,R_000028,6-10,ml, +201003355,201003364,801000001,R_000029,10-15,ml, +201003355,201003365,801000001,R_000030,5,g, +201003355,201003366,801000001,R_000031,15,g, +201003355,201003367,801000003,R_000032,,,1.0 +201003355,201003368,801000003,R_000033,,,2.0 +201003355,201003369,801000003,R_000034,,,3.0 +201003355,201003370,801000003,R_000035,,,4.0 +201003355,201003371,801000003,R_000036,,,5.0 +201003355,720000000,801000004,R_000037,,, +201003355,630000000,801000005,R_000038,,, +201003372,201003373,801000001,R_000039,150,g, +201003372,201003374,801000001,R_000040,4,根, +201003372,201003375,801000001,R_000041,200,g, +201003372,201003376,801000001,R_000042,2,瓣, +201003372,201003377,801000001,R_000043,4,个, +201003372,201003378,801000001,R_000044,6,粒, +201003372,201003379,801000001,R_000045,5,g, +201003372,201003380,801000001,R_000046,3,g, +201003372,201003381,801000001,R_000047,8,ml, +201003372,201003382,801000001,R_000048,5,ml, +201003372,201003383,801000001,R_000049,10-15,ml, +201003372,201003384,801000003,R_000050,,,1.0 +201003372,201003385,801000003,R_000051,,,2.0 +201003372,201003386,801000003,R_000052,,,3.0 +201003372,201003387,801000003,R_000053,,,4.0 +201003372,201003388,801000003,R_000054,,,5.0 +201003372,201003389,801000003,R_000055,,,6.0 +201003372,201003390,801000003,R_000056,,,7.0 +201003372,201003391,801000003,R_000057,,,8.0 +201003372,201003392,801000003,R_000058,,,9.0 +201003372,201003393,801000003,R_000059,,,10.0 +201003372,201003394,801000003,R_000060,,,11.0 +201003372,720000000,801000004,R_000061,,, +201003372,630000000,801000005,R_000062,,, +201003395,201003396,801000001,R_000063,1,条, +201003395,201003397,801000001,R_000064,1,朵, +201003395,201003398,801000001,R_000065,5,毫升, +201003395,201003399,801000001,R_000066,8,克, +201003395,201003400,801000001,R_000067,1,克, +201003395,201003401,801000001,R_000068,1,克, +201003395,201003402,801000001,R_000069,10,克, +201003395,201003403,801000001,R_000070,2,片, +201003395,201003404,801000001,R_000071,2,朵, +201003395,201003405,801000001,R_000072,适量,, +201003395,201003406,801000003,R_000073,,,1.0 +201003395,201003407,801000003,R_000074,,,2.0 +201003395,201003408,801000003,R_000075,,,3.0 +201003395,201003409,801000003,R_000076,,,4.0 +201003395,201003410,801000003,R_000077,,,5.0 +201003395,201003411,801000003,R_000078,,,6.0 +201003395,720000000,801000004,R_000079,,, +201003395,630000000,801000005,R_000080,,, +201003412,201003413,801000001,R_000081,2,个, +201003412,201003414,801000001,R_000082,5,粒, +201003412,201003415,801000001,R_000083,2,片, +201003412,201003416,801000001,R_000084,2,颗, +201003412,201003417,801000001,R_000085,2,瓣, +201003412,201003418,801000001,R_000086,150,毫升, +201003412,201003419,801000001,R_000087,15,毫升, +201003412,201003420,801000001,R_000088,45,毫升, +201003412,201003421,801000001,R_000089,1.5,克, +201003412,201003422,801000001,R_000090,15,毫升, +201003412,201003423,801000001,R_000091,15,毫升, +201003412,201003424,801000001,R_000092,5,毫升, +201003412,201003425,801000003,R_000093,,,1.0 +201003412,201003426,801000003,R_000094,,,2.0 +201003412,201003427,801000003,R_000095,,,3.0 +201003412,201003428,801000003,R_000096,,,4.0 +201003412,201003429,801000003,R_000097,,,5.0 +201003412,201003430,801000003,R_000098,,,6.0 +201003412,201003431,801000003,R_000099,,,7.0 +201003412,201003432,801000003,R_000100,,,8.0 +201003412,201003433,801000003,R_000101,,,9.0 +201003412,201003434,801000003,R_000102,,,10.0 +201003412,720000000,801000004,R_000103,,, +201003412,630000000,801000005,R_000104,,, +201003435,201003436,801000001,R_000105,500,克, +201003435,201003437,801000001,R_000106,3,片, +201003435,201003438,801000001,R_000107,3,个, +201003435,201003439,801000001,R_000108,6,个, +201003435,201003440,801000001,R_000109,10,克, +201003435,201003441,801000001,R_000110,10,克, +201003435,201003442,801000001,R_000111,2,根, +201003435,201003443,801000001,R_000112,3,克, +201003435,201003444,801000001,R_000113,适量,, +201003435,201003445,801000001,R_000114,适量,, +201003435,201003446,801000001,R_000115,适量,, +201003435,201003447,801000001,R_000116,可选,, +201003435,201003448,801000001,R_000117,适量,, +201003435,201003449,801000001,R_000118,适量,, +201003435,201003450,801000001,R_000119,适量,, +201003435,201003451,801000003,R_000120,,,1.0 +201003435,201003452,801000003,R_000121,,,2.0 +201003435,201003453,801000003,R_000122,,,3.0 +201003435,201003454,801000003,R_000123,,,4.0 +201003435,201003455,801000003,R_000124,,,5.0 +201003435,201003456,801000003,R_000125,,,6.0 +201003435,201003457,801000003,R_000126,,,7.0 +201003435,201003458,801000003,R_000127,,,8.0 +201003435,720000000,801000004,R_000128,,, +201003435,640000000,801000005,R_000129,,, +201003459,201003460,801000001,R_000130,2,根, +201003459,201003461,801000001,R_000131,20,克, +201003459,201003462,801000001,R_000132,3-5,克, +201003459,201003463,801000001,R_000133,5-10,克, +201003459,201003464,801000001,R_000134,5,克, +201003459,201003465,801000001,R_000135,10,毫升, +201003459,201003466,801000001,R_000136,5,毫升, +201003459,201003467,801000001,R_000137,10,毫升, +201003459,201003468,801000001,R_000138,100,毫升, +201003459,201003469,801000001,R_000139,20-30,克, +201003459,201003470,801000001,R_000140,适量,, +201003459,201003471,801000001,R_000141,适量,, +201003459,201003472,801000001,R_000142,适量,, +201003459,201003473,801000001,R_000143,适量,, +201003459,201003474,801000003,R_000144,,,1.0 +201003459,201003475,801000003,R_000145,,,2.0 +201003459,201003476,801000003,R_000146,,,3.0 +201003459,201003477,801000003,R_000147,,,4.0 +201003459,201003478,801000003,R_000148,,,5.0 +201003459,201003479,801000003,R_000149,,,6.0 +201003459,201003480,801000003,R_000150,,,7.0 +201003459,720000000,801000004,R_000151,,, +201003459,630000000,801000005,R_000152,,, +201003481,201003482,801000001,R_000153,1,盒, +201003481,201003483,801000001,R_000154,1,枚, +201003481,201003484,801000001,R_000155,20,g, +201003481,201003485,801000001,R_000156,2,瓣, +201003481,201003486,801000001,R_000157,2,片, +201003481,201003487,801000001,R_000158,5,根, +201003481,201003488,801000001,R_000159,5,g, +201003481,201003489,801000001,R_000160,20,颗, +201003481,201003490,801000001,R_000161,3,g, +201003481,201003491,801000001,R_000162,10,g, +201003481,201003492,801000001,R_000163,10,ml, +201003481,201003493,801000001,R_000164,适量,ml, +201003481,201003494,801000003,R_000165,,,1.0 +201003481,201003495,801000003,R_000166,,,2.0 +201003481,201003496,801000003,R_000167,,,3.0 +201003481,201003497,801000003,R_000168,,,4.0 +201003481,201003498,801000003,R_000169,,,5.0 +201003481,201003499,801000003,R_000170,,,6.0 +201003481,201003500,801000003,R_000171,,,7.0 +201003481,201003501,801000003,R_000172,,,8.0 +201003481,201003502,801000003,R_000173,,,9.0 +201003481,201003503,801000003,R_000174,,,10.0 +201003481,201003504,801000003,R_000175,,,11.0 +201003481,201003505,801000003,R_000176,,,12.0 +201003481,201003506,801000003,R_000177,,,13.0 +201003481,720000000,801000004,R_000178,,, +201003481,630000000,801000005,R_000179,,, +201003507,201003508,801000001,R_000180,100,克, +201003507,201003509,801000001,R_000181,1/12,个, +201003507,201003510,801000001,R_000182,1/12,个, +201003507,201003511,801000001,R_000183,3,克, +201003507,201003512,801000001,R_000184,1,克, +201003507,201003513,801000001,R_000185,按商品说明,, +201003507,201003514,801000001,R_000186,1,克, +201003507,201003515,801000001,R_000187,10,毫升, +201003507,201003516,801000003,R_000188,,,1.0 +201003507,201003517,801000003,R_000189,,,2.0 +201003507,201003518,801000003,R_000190,,,3.0 +201003507,201003519,801000003,R_000191,,,4.0 +201003507,201003520,801000003,R_000192,,,5.0 +201003507,201003521,801000003,R_000193,,,6.0 +201003507,201003522,801000003,R_000194,,,7.0 +201003507,201003523,801000003,R_000195,,,8.0 +201003507,201003524,801000003,R_000196,,,9.0 +201003507,720000000,801000004,R_000197,,, +201003507,640000000,801000005,R_000198,,, +201003525,201003526,801000001,R_000199,200,克, +201003525,201003527,801000001,R_000200,300,克, +201003525,201003528,801000001,R_000201,750,毫升, +201003525,201003529,801000003,R_000202,,,1.0 +201003525,201003530,801000003,R_000203,,,2.0 +201003525,201003531,801000003,R_000204,,,3.0 +201003525,201003532,801000003,R_000205,,,4.0 +201003525,201003533,801000003,R_000206,,,5.0 +201003525,720000000,801000004,R_000207,,, +201003525,610000000,801000005,R_000208,,, +201003534,201003535,801000001,R_000001,300,g, +201003534,201003536,801000001,R_000002,,适量, +201003534,201003537,801000001,R_000003,30,g, +201003534,201003538,801000001,R_000004,100,g, +201003534,201003539,801000001,R_000005,50,g, +201003534,201003540,801000001,R_000006,10,g, +201003534,201003541,801000001,R_000007,,适量, +201003534,201003542,801000001,R_000008,,适量, +201003534,201003543,801000001,R_000009,,适量, +201003534,201003544,801000001,R_000010,,适量, +201003534,201003545,801000001,R_000011,,适量, +201003534,201003546,801000001,R_000012,,适量, +201003534,201003547,801000001,R_000013,,适量, +201003534,201003548,801000001,R_000014,,可选, +201003534,201003549,801000003,R_000015,,,1.0 +201003534,201003550,801000003,R_000016,,,2.0 +201003534,201003551,801000003,R_000017,,,3.0 +201003534,201003552,801000003,R_000018,,,4.0 +201003534,201003553,801000003,R_000019,,,5.0 +201003534,201003554,801000003,R_000020,,,6.0 +201003534,201003555,801000003,R_000021,,,7.0 +201003534,201003556,801000003,R_000022,,,8.0 +201003534,201003557,801000003,R_000023,,,9.0 +201003534,630000000,801000005,R_000024,,, +201003558,201003559,801000001,R_000025,520,g, +201003558,201003560,801000001,R_000026,50,ml, +201003558,201003561,801000003,R_000027,,,1.0 +201003558,201003562,801000003,R_000028,,,2.0 +201003558,201003563,801000003,R_000029,,,3.0 +201003558,201003564,801000003,R_000030,,,4.0 +201003558,201003565,801000003,R_000031,,,5.0 +201003558,201003566,801000003,R_000032,,,1.0 +201003558,201003567,801000003,R_000033,,,2.0 +201003558,201003568,801000003,R_000034,,,3.0 +201003558,201003569,801000003,R_000035,,,4.0 +201003558,201003570,801000003,R_000036,,,5.0 +201003558,610000000,801000005,R_000037,,, +201003571,201003572,801000001,R_000038,4500,g, +201003571,201003573,801000001,R_000039,1000,ml, +201003571,201003574,801000001,R_000040,1000,ml, +201003571,201003575,801000001,R_000041,500,g, +201003571,201003576,801000001,R_000042,1000,g, +201003571,201003577,801000001,R_000043,3000,g, +201003571,201003578,801000001,R_000044,400,g, +201003571,201003579,801000001,R_000045,100,g, +201003571,201003580,801000001,R_000046,100,g, +201003571,201003581,801000001,R_000047,300,g, +201003571,201003582,801000001,R_000048,10,g, +201003571,201003583,801000001,R_000049,140,g, +201003571,201003584,801000001,R_000050,150,g, +201003571,201003585,801000001,R_000051,100,g, +201003571,201003586,801000001,R_000052,150,g, +201003571,201003587,801000001,R_000053,12.5,g, +201003571,201003588,801000001,R_000054,150,ml, +201003571,201003589,801000001,R_000055,15,g, +201003571,201003590,801000001,R_000056,5,g, +201003571,201003591,801000001,R_000057,10,g, +201003571,201003592,801000001,R_000058,10,g, +201003571,201003593,801000001,R_000059,10,g, +201003571,201003594,801000001,R_000060,5,g, +201003571,201003595,801000001,R_000061,10,g, +201003571,201003596,801000001,R_000062,10,g, +201003571,201003597,801000001,R_000063,5,g, +201003571,201003598,801000001,R_000064,10,g, +201003571,201003599,801000001,R_000065,10,g, +201003571,201003600,801000001,R_000066,10,g, +201003571,201003601,801000001,R_000067,5,g, +201003571,201003602,801000001,R_000068,10,g, +201003571,201003603,801000001,R_000069,10,g, +201003571,201003604,801000001,R_000070,10,g, +201003571,201003605,801000001,R_000071,10,g, +201003571,201003606,801000003,R_000072,,,1.0 +201003571,201003607,801000003,R_000073,,,2.0 +201003571,201003608,801000003,R_000074,,,3.0 +201003571,201003609,801000003,R_000075,,,4.0 +201003571,201003610,801000003,R_000076,,,5.0 +201003571,201003611,801000003,R_000077,,,6.0 +201003571,201003612,801000003,R_000078,,,7.0 +201003571,201003613,801000003,R_000079,,,8.0 +201003571,201003614,801000003,R_000080,,,9.0 +201003571,201003615,801000003,R_000081,,,10.0 +201003571,201003616,801000003,R_000082,,,11.0 +201003571,201003617,801000003,R_000083,,,12.0 +201003571,650000000,801000005,R_000084,,, +201003618,201003619,801000001,R_000085,7,个, +201003618,201003620,801000001,R_000086,14,个体积, +201003618,201003621,801000001,R_000087,10,毫升, +201003618,201003622,801000001,R_000088,50,克, +201003618,201003623,801000001,R_000089,2,滴, +201003618,201003624,801000001,R_000090,3,瓣, +201003618,201003625,801000003,R_000091,,,1.0 +201003618,201003626,801000003,R_000092,,,2.0 +201003618,201003627,801000003,R_000093,,,3.0 +201003618,201003628,801000003,R_000094,,,4.0 +201003618,201003629,801000003,R_000095,,,5.0 +201003618,201003630,801000003,R_000096,,,6.0 +201003618,610000000,801000005,R_000097,,, +201003631,201003632,801000001,R_000098,16,个, +201003631,201003633,801000001,R_000099,600,毫升, +201003631,201003634,801000001,R_000100,适量,, +201003631,201003635,801000001,R_000101,适量,, +201003631,201003636,801000001,R_000102,适量,, +201003631,201003637,801000001,R_000103,适量,, +201003631,201003638,801000001,R_000104,1,根, +201003631,201003639,801000003,R_000105,,,1.0 +201003631,201003640,801000003,R_000106,,,2.0 +201003631,201003641,801000003,R_000107,,,3.0 +201003631,201003642,801000003,R_000108,,,4.0 +201003631,620000000,801000005,R_000109,,, +201003643,201003644,801000001,R_000110,1,个, +201003643,201003645,801000001,R_000111,10,毫升, +201003643,201003646,801000001,R_000112,10,克, +201003643,201003647,801000003,R_000113,,,1.0 +201003643,201003648,801000003,R_000114,,,2.0 +201003643,201003649,801000003,R_000115,,,3.0 +201003643,201003650,801000003,R_000116,,,4.0 +201003643,630000000,801000005,R_000117,,, +201003651,201003652,801000001,R_000118,400,克, +201003651,201003653,801000003,R_000119,,,1.0 +201003651,201003654,801000003,R_000120,,,2.0 +201003651,201003655,801000003,R_000121,,,3.0 +201003651,201003656,801000003,R_000122,,,4.0 +201003651,201003657,801000003,R_000123,,,5.0 +201003651,620000000,801000005,R_000124,,, +201003658,201003659,801000001,R_000125,160,克, +201003658,201003660,801000001,R_000126,5,克, +201003658,201003661,801000001,R_000127,20,克, +201003658,201003662,801000001,R_000128,10,克, +201003658,201003663,801000001,R_000129,20,克, +201003658,201003664,801000001,R_000130,适量,克, +201003658,201003665,801000003,R_000131,,,1.0 +201003658,201003666,801000003,R_000132,,,2.0 +201003658,201003667,801000003,R_000133,,,3.0 +201003658,201003668,801000003,R_000134,,,4.0 +201003658,630000000,801000005,R_000135,,, +201003669,201003670,801000001,R_000136,6,个, +201003669,201003671,801000001,R_000137,适量,, +201003669,201003672,801000001,R_000138,适量,, +201003669,201003673,801000003,R_000139,,,1.0 +201003669,201003674,801000003,R_000140,,,2.0 +201003669,201003675,801000003,R_000141,,,3.0 +201003669,620000000,801000005,R_000142,,, +201003676,201003677,801000001,R_000143,11,个, +201003676,201003678,801000001,R_000144,浸没汤圆,毫升, +201003676,201003679,801000003,R_000145,,,1.0 +201003676,201003680,801000003,R_000146,,,2.0 +201003676,201003681,801000003,R_000147,,,3.0 +201003676,201003682,801000003,R_000148,,,4.0 +201003676,610000000,801000005,R_000149,,, +201003683,201003684,801000001,R_000001,200,克, +201003683,201003685,801000001,R_000002,50,克, +201003683,201003686,801000001,R_000003,15,克, +201003683,201003687,801000001,R_000004,10,克, +201003683,201003688,801000001,R_000005,200,毫升, +201003683,201003689,801000001,R_000006,30,毫升, +201003683,201003690,801000001,R_000007,100,毫升, +201003683,201003691,801000001,R_000008,2,克, +201003683,201003692,801000001,R_000009,1,克, +201003683,201003693,801000003,R_000010,,,1.0 +201003683,201003694,801000003,R_000011,,,2.0 +201003683,201003695,801000003,R_000012,,,3.0 +201003683,201003696,801000003,R_000013,,,4.0 +201003683,201003697,801000003,R_000014,,,5.0 +201003683,201003698,801000003,R_000015,,,6.0 +201003683,201003699,801000003,R_000016,,,7.0 +201003683,760000000,801000004,R_000017,,, +201003683,610000000,801000005,R_000018,,, +201003700,201003701,801000001,R_000019,100,克, +201003700,201003702,801000001,R_000020,2000,克, +201003700,201003703,801000003,R_000021,,,1.0 +201003700,201003704,801000003,R_000022,,,2.0 +201003700,201003705,801000003,R_000023,,,3.0 +201003700,201003706,801000003,R_000024,,,4.0 +201003700,760000000,801000004,R_000025,,, +201003700,620000000,801000005,R_000026,,, +201003707,201003708,801000001,R_000027,500,克, +201003707,201003709,801000001,R_000028,30,克, +201003707,201003710,801000001,R_000029,10,克, +201003707,201003711,801000001,R_000030,400,克, +201003707,201003712,801000001,R_000031,1,个, +201003707,201003713,801000001,R_000032,40,克, +201003707,201003714,801000001,R_000033,适量,, +201003707,201003715,801000001,R_000034,适量,, +201003707,201003716,801000001,R_000035,适量,, +201003707,201003717,801000001,R_000036,适量,, +201003707,201003718,801000001,R_000037,适量,, +201003707,201003719,801000001,R_000038,适量,, +201003707,201003720,801000001,R_000039,3,滴, +201003707,201003721,801000001,R_000040,1,小颗, +201003707,201003722,801000003,R_000041,,,1.0 +201003707,201003723,801000003,R_000042,,,2.0 +201003707,201003724,801000003,R_000043,,,3.0 +201003707,201003725,801000003,R_000044,,,4.0 +201003707,760000000,801000004,R_000045,,, +201003707,640000000,801000005,R_000046,,, +201003726,201003727,801000001,R_000047,150,g, +201003726,201003728,801000001,R_000048,1,个, +201003726,201003729,801000001,R_000049,1,个, +201003726,201003730,801000001,R_000050,适量,根, +201003726,201003731,801000001,R_000051,适量,片, +201003726,201003732,801000001,R_000052,适量,瓣, +201003726,201003733,801000001,R_000053,2,g, +201003726,201003734,801000001,R_000054,0.5,g, +201003726,201003735,801000003,R_000055,,,1.0 +201003726,201003736,801000003,R_000056,,,2.0 +201003726,201003737,801000003,R_000057,,,3.0 +201003726,201003738,801000003,R_000058,,,4.0 +201003726,201003739,801000003,R_000059,,,5.0 +201003726,201003740,801000003,R_000060,,,6.0 +201003726,201003741,801000003,R_000061,,,7.0 +201003726,201003742,801000003,R_000062,,,8.0 +201003726,201003743,801000003,R_000063,,,9.0 +201003726,201003744,801000003,R_000064,,,10.0 +201003726,760000000,801000004,R_000065,,, +201003726,630000000,801000005,R_000066,,, +201003745,201003746,801000001,R_000067,1,升, +201003745,201003747,801000001,R_000068,2,颗, +201003745,201003748,801000001,R_000069,100,克, +201003745,201003749,801000001,R_000070,150,毫升, +201003745,201003750,801000001,R_000071,1,棵, +201003745,201003751,801000001,R_000072,1,棵, +201003745,201003752,801000001,R_000073,4,叶, +201003745,201003753,801000001,R_000074,1,拇指块, +201003745,201003754,801000001,R_000075,5,毫升, +201003745,201003755,801000001,R_000076,5,毫升, +201003745,201003756,801000001,R_000077,2,克, +201003745,201003757,801000001,R_000078,1,克, +201003745,201003758,801000001,R_000079,10,毫升, +201003745,201003759,801000003,R_000080,,,1.0 +201003745,201003760,801000003,R_000081,,,2.0 +201003745,201003761,801000003,R_000082,,,3.0 +201003745,201003762,801000003,R_000083,,,4.0 +201003745,201003763,801000003,R_000084,,,5.0 +201003745,201003764,801000003,R_000085,,,6.0 +201003745,201003765,801000003,R_000086,,,7.0 +201003745,201003766,801000003,R_000087,,,8.0 +201003745,760000000,801000004,R_000088,,, +201003745,740000000,801000004,R_000089,,, +201003745,750000000,801000004,R_000090,,, +201003745,630000000,801000005,R_000091,,, +201003767,201003768,801000001,R_000092,60-110,ml, +201003767,201003769,801000001,R_000093,540-1320,ml, +201003767,201003770,801000001,R_000094,生米体积 / 10,ml, +201003767,201003771,801000003,R_000095,,,1.0 +201003767,201003772,801000003,R_000096,,,2.0 +201003767,201003773,801000003,R_000097,,,3.0 +201003767,201003774,801000003,R_000098,,,4.0 +201003767,201003775,801000003,R_000099,,,5.0 +201003767,201003776,801000003,R_000100,,,6.0 +201003767,760000000,801000004,R_000101,,, +201003767,620000000,801000005,R_000102,,, +201003777,201003778,801000001,R_000103,10,克, +201003777,201003779,801000001,R_000104,2,个, +201003777,201003780,801000001,R_000105,2,克, +201003777,201003781,801000001,R_000106,1.5,升, +201003777,201003782,801000001,R_000107,5,毫升, +201003777,201003783,801000001,R_000108,适量,, +201003777,201003784,801000001,R_000109,几滴,, +201003777,201003785,801000001,R_000110,可选,, +201003777,201003786,801000001,R_000111,可选,, +201003777,201003787,801000001,R_000112,2,克, +201003777,201003788,801000003,R_000113,,,1.0 +201003777,201003789,801000003,R_000114,,,2.0 +201003777,201003790,801000003,R_000115,,,3.0 +201003777,201003791,801000003,R_000116,,,4.0 +201003777,201003792,801000003,R_000117,,,5.0 +201003777,760000000,801000004,R_000118,,, +201003777,620000000,801000005,R_000119,,, +201003793,201003794,801000001,R_000120,500,mL, +201003793,201003795,801000001,R_000121,250,g, +201003793,201003796,801000001,R_000122,2,罐, +201003793,201003797,801000001,R_000123,5,g, +201003793,201003798,801000001,R_000124,400,g, +201003793,201003799,801000001,R_000125,100,g, +201003793,201003800,801000001,R_000126,100,g, +201003793,201003801,801000001,R_000127,100,g, +201003793,201003802,801000001,R_000128,200,g, +201003793,201003803,801000001,R_000129,150,g, +201003793,201003804,801000001,R_000130,5,mL, +201003793,201003805,801000001,R_000131,5,mL, +201003793,201003806,801000001,R_000132,18,g, +201003793,201003807,801000001,R_000133,3,g, +201003793,201003808,801000003,R_000134,,,1.0 +201003793,201003809,801000003,R_000135,,,2.0 +201003793,201003810,801000003,R_000136,,,3.0 +201003793,201003811,801000003,R_000137,,,4.0 +201003793,201003812,801000003,R_000138,,,5.0 +201003793,201003813,801000003,R_000139,,,6.0 +201003793,201003814,801000003,R_000140,,,7.0 +201003793,201003815,801000003,R_000141,,,8.0 +201003793,201003816,801000003,R_000142,,,9.0 +201003793,201003817,801000003,R_000143,,,10.0 +201003793,760000000,801000004,R_000144,,, +201003793,640000000,801000005,R_000145,,, +201003818,201003819,801000001,R_000146,1000,毫升, +201003818,201003820,801000001,R_000147,50,克, +201003818,201003821,801000001,R_000148,50,克, +201003818,201003822,801000001,R_000149,25,克, +201003818,201003823,801000001,R_000150,25,克, +201003818,201003824,801000001,R_000151,25,克, +201003818,201003825,801000001,R_000152,50,克, +201003818,201003826,801000001,R_000153,50,克, +201003818,201003827,801000001,R_000154,50,克, +201003818,201003828,801000001,R_000155,25,克, +201003818,201003829,801000001,R_000156,25,克, +201003818,201003830,801000001,R_000157,25,克, +201003818,201003831,801000001,R_000158,25,克, +201003818,201003832,801000001,R_000159,25,克, +201003818,201003833,801000001,R_000160,25,克, +201003818,201003834,801000001,R_000161,25,克, +201003818,201003835,801000001,R_000162,25,克, +201003818,201003836,801000001,R_000163,25,克, +201003818,201003837,801000001,R_000164,10~25,克, +201003818,201003838,801000003,R_000165,,,1.0 +201003818,201003839,801000003,R_000166,,,2.0 +201003818,201003840,801000003,R_000167,,,3.0 +201003818,201003841,801000003,R_000168,,,4.0 +201003818,201003842,801000003,R_000169,,,5.0 +201003818,201003843,801000003,R_000170,,,6.0 +201003818,760000000,801000004,R_000171,,, +201003818,640000000,801000005,R_000172,,, +201003844,201003845,801000001,R_000173,1,个, +201003844,201003846,801000001,R_000174,1-2,个, +201003844,201003847,801000001,R_000175,2,滴, +201003844,201003848,801000001,R_000176,5,克, +201003844,201003849,801000001,R_000177,15,克, +201003844,201003850,801000001,R_000178,5,克, +201003844,201003851,801000001,R_000179,5,克, +201003844,201003852,801000001,R_000180,5,克, +201003844,201003853,801000001,R_000181,15,毫升, +201003844,201003854,801000003,R_000182,,,1.0 +201003844,201003855,801000003,R_000183,,,2.0 +201003844,201003856,801000003,R_000184,,,3.0 +201003844,201003857,801000003,R_000185,,,4.0 +201003844,201003858,801000003,R_000186,,,5.0 +201003844,201003859,801000003,R_000187,,,6.0 +201003844,201003860,801000003,R_000188,,,7.0 +201003844,201003861,801000003,R_000189,,,8.0 +201003844,760000000,801000004,R_000190,,, +201003844,620000000,801000005,R_000191,,, +201003862,201003863,801000001,R_000001,400-500,克, +201003862,201003864,801000001,R_000002,1,个, +201003862,201003865,801000001,R_000003,15,克, +201003862,201003866,801000001,R_000004,5,克, +201003862,201003867,801000001,R_000005,3-4,滴, +201003862,201003868,801000003,R_000006,,,1.0 +201003862,201003869,801000003,R_000007,,,2.0 +201003862,201003870,801000003,R_000008,,,3.0 +201003862,201003871,801000003,R_000009,,,4.0 +201003862,201003872,801000003,R_000010,,,5.0 +201003862,760000000,801000004,R_000011,,, +201003862,620000000,801000005,R_000012,,, +201003873,201003874,801000001,R_000013,4-5,块, +201003873,201003875,801000001,R_000014,1,瓣, +201003873,201003876,801000001,R_000015,9,片, +201003873,201003877,801000001,R_000016,6,颗, +201003873,201003878,801000001,R_000017,5,片, +201003873,201003879,801000001,R_000018,7,个, +201003873,201003880,801000001,R_000019,5,克, +201003873,201003881,801000003,R_000020,,,1.0 +201003873,201003882,801000003,R_000021,,,2.0 +201003873,201003883,801000003,R_000022,,,3.0 +201003873,201003884,801000003,R_000023,,,4.0 +201003873,201003885,801000003,R_000024,,,5.0 +201003873,201003886,801000003,R_000025,,,6.0 +201003873,201003887,801000003,R_000026,,,7.0 +201003873,760000000,801000004,R_000027,,, +201003873,640000000,801000005,R_000028,,, +201003888,201003889,801000001,R_000029,2,朵, +201003888,201003890,801000001,R_000030,0.5,根, +201003888,201003891,801000001,R_000031,10,毫升, +201003888,201003892,801000001,R_000032,3,克, +201003888,201003893,801000001,R_000033,3,克, +201003888,201003894,801000001,R_000034,10,克, +201003888,201003895,801000001,R_000035,350,毫升, +201003888,201003896,801000003,R_000036,,,1.0 +201003888,201003897,801000003,R_000037,,,2.0 +201003888,201003898,801000003,R_000038,,,3.0 +201003888,201003899,801000003,R_000039,,,4.0 +201003888,201003900,801000003,R_000040,,,5.0 +201003888,201003901,801000003,R_000041,,,6.0 +201003888,760000000,801000004,R_000042,,, +201003888,630000000,801000005,R_000043,,, +201003902,201003903,801000001,R_000044,375,克, +201003902,201003904,801000001,R_000045,150,克, +201003902,201003905,801000001,R_000046,10,克, +201003902,201003906,801000001,R_000047,7.5,克, +201003902,201003907,801000001,R_000048,0.45,克, +201003902,201003908,801000001,R_000049,0.3,克, +201003902,201003909,801000003,R_000050,,,1.0 +201003902,201003910,801000003,R_000051,,,2.0 +201003902,201003911,801000003,R_000052,,,3.0 +201003902,201003912,801000003,R_000053,,,4.0 +201003902,201003913,801000003,R_000054,,,5.0 +201003902,201003914,801000003,R_000055,,,6.0 +201003902,201003915,801000003,R_000056,,,7.0 +201003902,760000000,801000004,R_000057,,, +201003902,640000000,801000005,R_000058,,, +201003916,201003917,801000001,R_000059,1,条, +201003916,201003918,801000001,R_000060,100,g, +201003916,201003919,801000001,R_000061,1,根, +201003916,201003920,801000001,R_000062,1,块, +201003916,201003921,801000001,R_000063,15,ml, +201003916,201003922,801000001,R_000064,5,ml, +201003916,201003923,801000001,R_000065,15,g, +201003916,201003924,801000001,R_000066,3,g, +201003916,201003925,801000001,R_000067,1000,ml, +201003916,201003926,801000003,R_000068,,,1.0 +201003916,201003927,801000003,R_000069,,,2.0 +201003916,201003928,801000003,R_000070,,,3.0 +201003916,201003929,801000003,R_000071,,,4.0 +201003916,201003930,801000003,R_000072,,,5.0 +201003916,760000000,801000004,R_000073,,, +201003916,630000000,801000005,R_000074,,, +201003931,201003932,801000001,R_000075,1,个, +201003931,201003933,801000001,R_000076,500,毫升, +201003931,201003934,801000001,R_000077,20,克, +201003931,201003935,801000001,R_000078,2,毫升, +201003931,201003936,801000003,R_000079,,,1.0 +201003931,201003937,801000003,R_000080,,,2.0 +201003931,201003938,801000003,R_000081,,,3.0 +201003931,760000000,801000004,R_000082,,, +201003931,610000000,801000005,R_000083,,, +201003939,201003940,801000001,R_000084,500-800,g, +201003939,201003941,801000001,R_000085,1,根, +201003939,201003942,801000001,R_000086,1,根, +201003939,201003943,801000001,R_000087,小半根,根, +201003939,201003944,801000001,R_000088,1,根, +201003939,201003945,801000001,R_000089,若干,片, +201003939,201003946,801000001,R_000090,10,ml, +201003939,201003947,801000001,R_000091,4,g, +201003939,201003948,801000001,R_000092,10,ml, +201003939,201003949,801000001,R_000093,10,ml, +201003939,201003950,801000001,R_000094,10-15,g, +201003939,201003951,801000001,R_000095,1000,ml, +201003939,201003952,801000003,R_000096,,,1.0 +201003939,201003953,801000003,R_000097,,,2.0 +201003939,201003954,801000003,R_000098,,,3.0 +201003939,201003955,801000003,R_000099,,,4.0 +201003939,201003956,801000003,R_000100,,,5.0 +201003939,201003957,801000003,R_000101,,,6.0 +201003939,201003958,801000003,R_000102,,,7.0 +201003939,760000000,801000004,R_000103,,, +201003939,630000000,801000005,R_000104,,, +201003959,201003960,801000001,R_000105,300,克, +201003959,201003961,801000001,R_000106,10,毫升, +201003959,201003962,801000001,R_000107,20,毫升, +201003959,201003963,801000001,R_000108,50,克, +201003959,201003964,801000001,R_000109,1000,毫升, +201003959,201003965,801000001,R_000110,1,克, +201003959,201003966,801000001,R_000111,5,克, +201003959,201003967,801000001,R_000112,1,克, +201003959,201003968,801000001,R_000113,20,克, +201003959,201003969,801000003,R_000114,,,1.0 +201003959,201003970,801000003,R_000115,,,2.0 +201003959,201003971,801000003,R_000116,,,3.0 +201003959,201003972,801000003,R_000117,,,4.0 +201003959,201003973,801000003,R_000118,,,5.0 +201003959,201003974,801000003,R_000119,,,6.0 +201003959,201003975,801000003,R_000120,,,7.0 +201003959,201003976,801000003,R_000121,,,8.0 +201003959,760000000,801000004,R_000122,,, +201003959,630000000,801000005,R_000123,,, +201003977,201003978,801000001,R_000124,300,g, +201003977,201003979,801000001,R_000125,100,g, +201003977,201003980,801000001,R_000126,200,g, +201003977,201003981,801000001,R_000127,30,g, +201003977,201003982,801000001,R_000128,15,ml, +201003977,201003983,801000001,R_000129,10,g, +201003977,201003984,801000003,R_000130,,,1.0 +201003977,201003985,801000003,R_000131,,,2.0 +201003977,201003986,801000003,R_000132,,,3.0 +201003977,201003987,801000003,R_000133,,,4.0 +201003977,201003988,801000003,R_000134,,,5.0 +201003977,760000000,801000004,R_000135,,, +201003977,640000000,801000005,R_000136,,, +201003989,201003990,801000001,R_000137,60,g, +201003989,201003991,801000001,R_000138,20,g, +201003989,201003992,801000001,R_000139,6,g, +201003989,201003993,801000001,R_000140,5-6,g, +201003989,201003994,801000001,R_000141,10-20,g, +201003989,201003995,801000003,R_000142,,,1.0 +201003989,201003996,801000003,R_000143,,,2.0 +201003989,201003997,801000003,R_000144,,,3.0 +201003989,201003998,801000003,R_000145,,,4.0 +201003989,201003999,801000003,R_000146,,,5.0 +201003989,201004000,801000003,R_000147,,,6.0 +201003989,201004001,801000003,R_000148,,,7.0 +201003989,760000000,801000004,R_000149,,, +201003989,640000000,801000005,R_000150,,, +201004002,201004003,801000001,R_000001,4,块, +201004002,201004004,801000001,R_000002,1,瓣, +201004002,201004005,801000001,R_000003,9,片, +201004002,201004006,801000001,R_000004,6,颗, +201004002,201004007,801000001,R_000005,5,片, +201004002,201004008,801000001,R_000006,7,个, +201004002,201004009,801000001,R_000007,5,克, +201004002,201004010,801000003,R_000008,,,1.0 +201004002,201004011,801000003,R_000009,,,2.0 +201004002,201004012,801000003,R_000010,,,3.0 +201004002,201004013,801000003,R_000011,,,4.0 +201004002,201004014,801000003,R_000012,,,5.0 +201004002,201004015,801000003,R_000013,,,6.0 +201004002,201004016,801000003,R_000014,,,7.0 +201004002,760000000,801000004,R_000015,,, +201004002,630000000,801000005,R_000016,,, +201004017,201004018,801000001,R_000017,200,g, +201004017,201004019,801000001,R_000018,150,ml, +201004017,201004020,801000001,R_000019,2-3,ml, +201004017,201004021,801000001,R_000020,250,g, +201004017,201004022,801000001,R_000021,20,g, +201004017,201004023,801000001,R_000022,3,g, +201004017,201004024,801000001,R_000023,15,g, +201004017,201004025,801000001,R_000024,3,g, +201004017,201004026,801000001,R_000025,2,ml, +201004017,201004027,801000001,R_000026,2,ml, +201004017,201004028,801000001,R_000027,2,ml, +201004017,201004029,801000001,R_000028,1,个, +201004017,201004030,801000001,R_000029,适量,, +201004017,201004031,801000001,R_000030,10-20,ml, +201004017,201004032,801000001,R_000031,3,瓣, +201004017,201004033,801000003,R_000032,,,1.0 +201004017,201004034,801000003,R_000033,,,2.0 +201004017,201004035,801000003,R_000034,,,3.0 +201004017,201004036,801000003,R_000035,,,4.0 +201004017,201004037,801000003,R_000036,,,5.0 +201004017,201004038,801000003,R_000037,,,6.0 +201004017,201004039,801000003,R_000038,,,7.0 +201004017,750000000,801000004,R_000039,,, +201004017,650000000,801000005,R_000040,,, +201004040,201004041,801000001,R_000041,70-230,g, +201004040,201004042,801000001,R_000042,200-400,ml, +201004040,201004043,801000001,R_000043,适量,g, +201004040,201004044,801000001,R_000044,适量,个, +201004040,201004045,801000001,R_000045,适量,g, +201004040,201004046,801000001,R_000046,适量,g, +201004040,201004047,801000001,R_000047,适量,g, +201004040,201004048,801000001,R_000048,适量,g, +201004040,201004049,801000001,R_000049,适量,g, +201004040,201004050,801000001,R_000050,适量,ml, +201004040,201004051,801000003,R_000051,,,1.0 +201004040,201004052,801000003,R_000052,,,2.0 +201004040,201004053,801000003,R_000053,,,3.0 +201004040,201004054,801000003,R_000054,,,4.0 +201004040,201004055,801000003,R_000055,,,5.0 +201004040,201004056,801000003,R_000056,,,6.0 +201004040,201004057,801000003,R_000057,,,7.0 +201004040,750000000,801000004,R_000058,,, +201004040,620000000,801000005,R_000059,,, +201004058,201004059,801000001,R_000060,250,g, +201004058,201004060,801000001,R_000061,2,根, +201004058,201004061,801000001,R_000062,50,ml, +201004058,201004062,801000001,R_000063,15,ml, +201004058,201004063,801000001,R_000064,1-2,g, +201004058,201004064,801000001,R_000065,1,个, +201004058,201004065,801000001,R_000066,适量,, +201004058,201004066,801000003,R_000067,,,1.0 +201004058,201004067,801000003,R_000068,,,2.0 +201004058,201004068,801000003,R_000069,,,3.0 +201004058,201004069,801000003,R_000070,,,4.0 +201004058,201004070,801000003,R_000071,,,5.0 +201004058,201004071,801000003,R_000072,,,6.0 +201004058,201004072,801000003,R_000073,,,7.0 +201004058,201004073,801000003,R_000074,,,8.0 +201004058,201004074,801000003,R_000075,,,9.0 +201004058,201004075,801000003,R_000076,,,10.0 +201004058,750000000,801000004,R_000077,,, +201004058,630000000,801000005,R_000078,,, +201004076,201004077,801000001,R_000079,1.2,包, +201004076,201004078,801000001,R_000080,1.4,个, +201004076,201004079,801000001,R_000081,0.7,个, +201004076,201004080,801000001,R_000082,2.8,克, +201004076,201004081,801000001,R_000083,10,毫升, +201004076,201004082,801000001,R_000084,1,套, +201004076,201004083,801000003,R_000085,,,1.0 +201004076,201004084,801000003,R_000086,,,2.0 +201004076,201004085,801000003,R_000087,,,3.0 +201004076,201004086,801000003,R_000088,,,4.0 +201004076,201004087,801000003,R_000089,,,5.0 +201004076,750000000,801000004,R_000090,,, +201004076,620000000,801000005,R_000091,,, +201004088,201004089,801000001,R_000092,250,g, +201004088,201004090,801000001,R_000093,100,g, +201004088,201004091,801000001,R_000094,10,g, +201004088,201004092,801000001,R_000095,2,g, +201004088,201004093,801000001,R_000096,10,ml, +201004088,201004094,801000001,R_000097,15,ml, +201004088,201004095,801000001,R_000098,3,g, +201004088,201004096,801000001,R_000099,适量,, +201004088,201004097,801000001,R_000100,30,g, +201004088,201004098,801000001,R_000101,30,g, +201004088,201004099,801000001,R_000102,30,g, +201004088,201004100,801000001,R_000103,1,个, +201004088,201004101,801000001,R_000104,2,个, +201004088,201004102,801000001,R_000105,1,根, +201004088,201004103,801000001,R_000106,5,g, +201004088,201004104,801000001,R_000107,20,g, +201004088,201004105,801000003,R_000108,,,1.0 +201004088,201004106,801000003,R_000109,,,2.0 +201004088,201004107,801000003,R_000110,,,3.0 +201004088,201004108,801000003,R_000111,,,4.0 +201004088,201004109,801000003,R_000112,,,5.0 +201004088,201004110,801000003,R_000113,,,6.0 +201004088,201004111,801000003,R_000114,,,7.0 +201004088,201004112,801000003,R_000115,,,8.0 +201004088,201004113,801000003,R_000116,,,9.0 +201004088,201004114,801000003,R_000117,,,10.0 +201004088,201004115,801000003,R_000118,,,11.0 +201004088,201004116,801000003,R_000119,,,12.0 +201004088,750000000,801000004,R_000120,,, +201004088,640000000,801000005,R_000121,,, +201004117,201004118,801000001,R_000122,2,个, +201004117,201004119,801000001,R_000123,3,g, +201004117,201004120,801000001,R_000124,20,ml, +201004117,201004121,801000001,R_000125,3,g, +201004117,201004122,801000001,R_000126,3,g, +201004117,201004123,801000001,R_000127,3,g, +201004117,201004124,801000001,R_000128,2,棵, +201004117,201004125,801000001,R_000129,2,个, +201004117,201004126,801000003,R_000130,,,1.0 +201004117,201004127,801000003,R_000131,,,2.0 +201004117,201004128,801000003,R_000132,,,3.0 +201004117,201004129,801000003,R_000133,,,4.0 +201004117,201004130,801000003,R_000134,,,5.0 +201004117,201004131,801000003,R_000135,,,6.0 +201004117,201004132,801000003,R_000136,,,7.0 +201004117,201004133,801000003,R_000137,,,8.0 +201004117,201004134,801000003,R_000138,,,9.0 +201004117,750000000,801000004,R_000139,,, +201004117,630000000,801000005,R_000140,,, +201004135,201004136,801000001,R_000141,150,g, +201004135,201004137,801000001,R_000142,150,g, +201004135,201004138,801000001,R_000143,250,g, +201004135,201004139,801000001,R_000144,15,g, +201004135,201004140,801000001,R_000145,适量,g, +201004135,201004141,801000001,R_000146,35,g, +201004135,201004142,801000001,R_000147,10,g, +201004135,201004143,801000001,R_000148,20,g, +201004135,201004144,801000001,R_000149,20,g, +201004135,201004145,801000003,R_000150,,,1.0 +201004135,201004146,801000003,R_000151,,,2.0 +201004135,201004147,801000003,R_000152,,,3.0 +201004135,201004148,801000003,R_000153,,,4.0 +201004135,201004149,801000003,R_000154,,,5.0 +201004135,201004150,801000003,R_000155,,,6.0 +201004135,201004151,801000003,R_000156,,,7.0 +201004135,750000000,801000004,R_000157,,, +201004135,630000000,801000005,R_000158,,, +201004152,201004153,801000001,R_000159,250,g, +201004152,201004154,801000001,R_000160,10,g, +201004152,201004155,801000001,R_000161,20,g, +201004152,201004156,801000001,R_000162,30,g, +201004152,201004157,801000001,R_000163,30,ml, +201004152,201004158,801000001,R_000164,30,ml, +201004152,201004159,801000001,R_000165,50,g, +201004152,201004160,801000001,R_000166,40,ml, +201004152,201004161,801000001,R_000167,0-10,ml, +201004152,201004162,801000001,R_000168,0-10,g, +201004152,201004163,801000001,R_000169,5,ml, +201004152,201004164,801000001,R_000170,3,g, +201004152,201004165,801000001,R_000171,0-3,g, +201004152,201004166,801000003,R_000172,,,1.0 +201004152,201004167,801000003,R_000173,,,2.0 +201004152,201004168,801000003,R_000174,,,3.0 +201004152,201004169,801000003,R_000175,,,4.0 +201004152,201004170,801000003,R_000176,,,5.0 +201004152,201004171,801000003,R_000177,,,6.0 +201004152,750000000,801000004,R_000178,,, +201004152,630000000,801000005,R_000179,,, +201004172,201004173,801000001,R_000180,1,包, +201004172,201004174,801000001,R_000181,550-1000,毫升, +201004172,201004175,801000001,R_000182,1,个, +201004172,201004176,801000003,R_000183,,,1.0 +201004172,201004177,801000003,R_000184,,,2.0 +201004172,201004178,801000003,R_000185,,,3.0 +201004172,201004179,801000003,R_000186,,,4.0 +201004172,201004180,801000003,R_000187,,,5.0 +201004172,201004181,801000003,R_000188,,,6.0 +201004172,201004182,801000003,R_000189,,,7.0 +201004172,750000000,801000004,R_000190,,, +201004172,610000000,801000005,R_000191,,, +201004183,201004184,801000001,R_000001,1,升, +201004183,201004185,801000001,R_000002,120,克, +201004183,201004186,801000001,R_000003,15,毫升, +201004183,201004187,801000001,R_000004,5,毫升, +201004183,201004188,801000003,R_000005,,,1.0 +201004183,201004189,801000003,R_000006,,,2.0 +201004183,201004190,801000003,R_000007,,,3.0 +201004183,201004191,801000003,R_000008,,,4.0 +201004183,201004192,801000003,R_000009,,,5.0 +201004183,201004193,801000003,R_000010,,,6.0 +201004183,201004194,801000003,R_000011,,,7.0 +201004183,201004195,801000003,R_000012,,,8.0 +201004183,750000000,801000004,R_000013,,, +201004183,610000000,801000005,R_000014,,, +201004196,201004197,801000001,R_000015,240,g, +201004196,201004198,801000001,R_000016,4,个, +201004196,201004199,801000001,R_000017,300,g, +201004196,201004200,801000001,R_000018,10,ml, +201004196,201004201,801000001,R_000019,25,ml, +201004196,201004202,801000001,R_000020,20,ml, +201004196,201004203,801000001,R_000021,10,g, +201004196,201004204,801000001,R_000022,10,g, +201004196,201004205,801000001,R_000023,30,ml, +201004196,201004206,801000001,R_000024,15,g, +201004196,201004207,801000003,R_000025,,,1.0 +201004196,201004208,801000003,R_000026,,,2.0 +201004196,201004209,801000003,R_000027,,,3.0 +201004196,201004210,801000003,R_000028,,,4.0 +201004196,201004211,801000003,R_000029,,,5.0 +201004196,201004212,801000003,R_000030,,,6.0 +201004196,201004213,801000003,R_000031,,,7.0 +201004196,201004214,801000003,R_000032,,,8.0 +201004196,750000000,801000004,R_000033,,, +201004196,630000000,801000005,R_000034,,, +201004215,201004216,801000001,R_000035,80,g, +201004215,201004217,801000001,R_000036,100,g, +201004215,201004218,801000001,R_000037,100,ml, +201004215,201004219,801000001,R_000038,60,ml, +201004215,201004220,801000001,R_000039,20,ml, +201004215,201004221,801000001,R_000040,15,g, +201004215,201004222,801000003,R_000041,,,1.0 +201004215,201004223,801000003,R_000042,,,2.0 +201004215,201004224,801000003,R_000043,,,3.0 +201004215,201004225,801000003,R_000044,,,4.0 +201004215,201004226,801000003,R_000045,,,5.0 +201004215,201004227,801000003,R_000046,,,6.0 +201004215,201004228,801000003,R_000047,,,7.0 +201004215,201004229,801000003,R_000048,,,8.0 +201004215,201004230,801000003,R_000049,,,9.0 +201004215,201004231,801000003,R_000050,,,10.0 +201004215,750000000,801000004,R_000051,,, +201004215,620000000,801000005,R_000052,,, +201004232,201004233,801000001,R_000053,350,g, +201004232,201004234,801000001,R_000054,2,根, +201004232,201004235,801000001,R_000055,500,g, +201004232,201004236,801000001,R_000056,10,cm, +201004232,201004237,801000001,R_000057,5,瓣, +201004232,201004238,801000001,R_000058,20,g, +201004232,201004239,801000001,R_000059,2,个, +201004232,201004240,801000001,R_000060,3,个, +201004232,201004241,801000001,R_000061,20,粒, +201004232,201004242,801000001,R_000062,10,g, +201004232,201004243,801000001,R_000063,5,g, +201004232,201004244,801000001,R_000064,15,ml, +201004232,201004245,801000001,R_000065,10,ml, +201004232,201004246,801000001,R_000066,适量,, +201004232,201004247,801000001,R_000067,适量,, +201004232,201004248,801000003,R_000068,,,1.0 +201004232,201004249,801000003,R_000069,,,2.0 +201004232,201004250,801000003,R_000070,,,3.0 +201004232,201004251,801000003,R_000071,,,4.0 +201004232,201004252,801000003,R_000072,,,5.0 +201004232,201004253,801000003,R_000073,,,6.0 +201004232,201004254,801000003,R_000074,,,7.0 +201004232,201004255,801000003,R_000075,,,8.0 +201004232,201004256,801000003,R_000076,,,9.0 +201004232,201004257,801000003,R_000077,,,10.0 +201004232,201004258,801000003,R_000078,,,11.0 +201004232,201004259,801000003,R_000079,,,12.0 +201004232,750000000,801000004,R_000080,,, +201004232,640000000,801000005,R_000081,,, +201004260,201004261,801000001,R_000082,2,个, +201004260,201004262,801000001,R_000083,30,g, +201004260,201004263,801000001,R_000084,30,g, +201004260,201004264,801000001,R_000085,50,g, +201004260,201004265,801000001,R_000086,50,g, +201004260,201004266,801000001,R_000087,30,g, +201004260,201004267,801000001,R_000088,30,g, +201004260,201004268,801000001,R_000089,200,g, +201004260,201004269,801000001,R_000090,20,ml, +201004260,201004270,801000001,R_000091,15,ml, +201004260,201004271,801000001,R_000092,10,ml, +201004260,201004272,801000003,R_000093,,,1.0 +201004260,201004273,801000003,R_000094,,,2.0 +201004260,201004274,801000003,R_000095,,,3.0 +201004260,201004275,801000003,R_000096,,,4.0 +201004260,201004276,801000003,R_000097,,,5.0 +201004260,201004277,801000003,R_000098,,,6.0 +201004260,201004278,801000003,R_000099,,,7.0 +201004260,201004279,801000003,R_000100,,,8.0 +201004260,201004280,801000003,R_000101,,,9.0 +201004260,201004281,801000003,R_000102,,,10.0 +201004260,750000000,801000004,R_000103,,, +201004260,630000000,801000005,R_000104,,, +201004282,201004283,801000001,R_000105,500,ml, +201004282,201004284,801000001,R_000106,1.5,个, +201004282,201004285,801000001,R_000107,2,个, +201004282,201004286,801000001,R_000108,30,g, +201004282,201004287,801000001,R_000109,30,g, +201004282,201004288,801000001,R_000110,12,ml, +201004282,201004289,801000001,R_000111,4,g, +201004282,201004290,801000001,R_000112,8,g, +201004282,201004291,801000001,R_000113,1,颗, +201004282,201004292,801000001,R_000114,10,ml, +201004282,201004293,801000001,R_000115,适量,, +201004282,201004294,801000003,R_000116,,,1.0 +201004282,201004295,801000003,R_000117,,,2.0 +201004282,201004296,801000003,R_000118,,,3.0 +201004282,201004297,801000003,R_000119,,,4.0 +201004282,201004298,801000003,R_000120,,,5.0 +201004282,201004299,801000003,R_000121,,,6.0 +201004282,201004300,801000003,R_000122,,,7.0 +201004282,201004301,801000003,R_000123,,,8.0 +201004282,201004302,801000003,R_000124,,,9.0 +201004282,201004303,801000003,R_000125,,,10.0 +201004282,201004304,801000003,R_000126,,,11.0 +201004282,201004305,801000003,R_000127,,,12.0 +201004282,750000000,801000004,R_000128,,, +201004282,630000000,801000005,R_000129,,, +201004306,201004307,801000001,R_000130,1,包, +201004306,201004308,801000001,R_000131,1000,毫升, +201004306,201004309,801000003,R_000132,,,1.0 +201004306,201004310,801000003,R_000133,,,2.0 +201004306,201004311,801000003,R_000134,,,3.0 +201004306,201004312,801000003,R_000135,,,4.0 +201004306,201004313,801000003,R_000136,,,5.0 +201004306,201004314,801000003,R_000137,,,6.0 +201004306,201004315,801000003,R_000138,,,7.0 +201004306,750000000,801000004,R_000139,,, +201004306,610000000,801000005,R_000140,,, +201004316,201004317,801000001,R_000141,适量,克, +201004316,201004318,801000001,R_000142,3,份, +201004316,201004319,801000001,R_000143,2,份, +201004316,201004320,801000001,R_000144,2,份, +201004316,201004321,801000001,R_000145,2-5,克, +201004316,201004322,801000001,R_000146,2,克, +201004316,201004323,801000001,R_000147,适量,个, +201004316,201004324,801000001,R_000148,适量,瓣, +201004316,201004325,801000001,R_000149,适量,根, +201004316,201004326,801000003,R_000150,,,1.0 +201004316,201004327,801000003,R_000151,,,2.0 +201004316,201004328,801000003,R_000152,,,3.0 +201004316,201004329,801000003,R_000153,,,4.0 +201004316,750000000,801000004,R_000154,,, +201004316,620000000,801000005,R_000155,,, +201004330,201004331,801000001,R_000156,300,毫升, +201004330,201004332,801000001,R_000157,250,克, +201004330,201004333,801000001,R_000158,50,克, +201004330,201004334,801000001,R_000159,5,颗, +201004330,201004335,801000001,R_000160,适量,, +201004330,201004336,801000003,R_000161,,,1.0 +201004330,201004337,801000003,R_000162,,,2.0 +201004330,201004338,801000003,R_000163,,,3.0 +201004330,201004339,801000003,R_000164,,,4.0 +201004330,201004340,801000003,R_000165,,,5.0 +201004330,750000000,801000004,R_000166,,, +201004330,620000000,801000005,R_000167,,, +201004341,201004342,801000001,R_000168,500,g, +201004341,201004343,801000001,R_000169,100,g, +201004341,201004344,801000001,R_000170,3,枚, +201004341,201004345,801000001,R_000171,10,ml, +201004341,201004346,801000001,R_000172,5,g, +201004341,201004347,801000001,R_000173,250,g, +201004341,201004348,801000003,R_000174,,,1.0 +201004341,201004349,801000003,R_000175,,,2.0 +201004341,201004350,801000003,R_000176,,,3.0 +201004341,201004351,801000003,R_000177,,,4.0 +201004341,201004352,801000003,R_000178,,,5.0 +201004341,750000000,801000004,R_000179,,, +201004341,630000000,801000005,R_000180,,, +201004353,201004354,801000001,R_000001,1,升, +201004353,201004355,801000001,R_000002,1,块, +201004353,201004356,801000001,R_000003,15,毫升, +201004353,201004357,801000001,R_000004,10,克, +201004353,201004358,801000001,R_000005,30,克, +201004353,201004359,801000001,R_000006,10,克, +201004353,201004360,801000001,R_000007,5,克, +201004353,201004361,801000003,R_000008,,,1.0 +201004353,201004362,801000003,R_000009,,,2.0 +201004353,201004363,801000003,R_000010,,,3.0 +201004353,201004364,801000003,R_000011,,,4.0 +201004353,201004365,801000003,R_000012,,,5.0 +201004353,201004366,801000003,R_000013,,,6.0 +201004353,750000000,801000004,R_000014,,, +201004353,610000000,801000005,R_000015,,, +201004367,201004368,801000001,R_000016,100,g, +201004367,201004369,801000001,R_000017,150,g, +201004367,201004370,801000001,R_000018,80,g, +201004367,201004371,801000001,R_000019,25,g, +201004367,201004372,801000001,R_000020,15,g, +201004367,201004373,801000001,R_000021,150,ml, +201004367,201004374,801000001,R_000022,6,ml, +201004367,201004375,801000001,R_000023,10,ml, +201004367,201004376,801000001,R_000024,20,ml, +201004367,201004377,801000001,R_000025,10,ml, +201004367,201004378,801000001,R_000026,500,ml, +201004367,201004379,801000003,R_000027,,,1.0 +201004367,201004380,801000003,R_000028,,,2.0 +201004367,201004381,801000003,R_000029,,,3.0 +201004367,201004382,801000003,R_000030,,,4.0 +201004367,201004383,801000003,R_000031,,,5.0 +201004367,750000000,801000004,R_000032,,, +201004367,620000000,801000005,R_000033,,, +201004384,201004385,801000001,R_000034,200,g, +201004384,201004386,801000001,R_000035,50,g, +201004384,201004387,801000001,R_000036,30,ml, +201004384,201004388,801000001,R_000037,3,g, +201004384,201004389,801000001,R_000038,5,g, +201004384,201004390,801000001,R_000039,10,g, +201004384,201004391,801000001,R_000040,5,g, +201004384,201004392,801000001,R_000041,3,g, +201004384,201004393,801000001,R_000042,2,瓣, +201004384,201004394,801000001,R_000043,0.25,根, +201004384,201004395,801000001,R_000044,1,个, +201004384,201004396,801000001,R_000045,适量,, +201004384,201004397,801000003,R_000046,,,1.0 +201004384,201004398,801000003,R_000047,,,2.0 +201004384,201004399,801000003,R_000048,,,3.0 +201004384,201004400,801000003,R_000049,,,4.0 +201004384,201004401,801000003,R_000050,,,5.0 +201004384,201004402,801000003,R_000051,,,6.0 +201004384,201004403,801000003,R_000052,,,7.0 +201004384,201004404,801000003,R_000053,,,8.0 +201004384,201004405,801000003,R_000054,,,9.0 +201004384,201004406,801000003,R_000055,,,10.0 +201004384,750000000,801000004,R_000056,,, +201004384,640000000,801000005,R_000057,,, +201004407,201004408,801000001,R_000058,100,g, +201004407,201004409,801000001,R_000059,3,瓣, +201004407,201004410,801000001,R_000060,3,颗, +201004407,201004411,801000001,R_000061,10,g, +201004407,201004412,801000001,R_000062,10,ml, +201004407,201004413,801000001,R_000063,10,ml, +201004407,201004414,801000001,R_000064,3,ml, +201004407,201004415,801000001,R_000065,3,g, +201004407,201004416,801000001,R_000066,3,g, +201004407,201004417,801000001,R_000067,5,g, +201004407,201004418,801000001,R_000068,5,g, +201004407,201004419,801000003,R_000069,,,1.0 +201004407,201004420,801000003,R_000070,,,2.0 +201004407,201004421,801000003,R_000071,,,3.0 +201004407,201004422,801000003,R_000072,,,4.0 +201004407,201004423,801000003,R_000073,,,5.0 +201004407,201004424,801000003,R_000074,,,6.0 +201004407,201004425,801000003,R_000075,,,7.0 +201004407,201004426,801000003,R_000076,,,8.0 +201004407,201004427,801000003,R_000077,,,9.0 +201004407,201004428,801000003,R_000078,,,10.0 +201004407,750000000,801000004,R_000079,,, +201004407,630000000,801000005,R_000080,,, +201004429,201004430,801000001,R_000081,3.5,cup, +201004429,201004431,801000001,R_000082,1,cup, +201004429,201004432,801000001,R_000083,2,g, +201004429,201004433,801000001,R_000084,2,g, +201004429,201004434,801000001,R_000085,1,个, +201004429,201004435,801000001,R_000086,0.125,cup, +201004429,201004436,801000001,R_000087,0.25,cup, +201004429,201004437,801000001,R_000088,0.125,cup, +201004429,201004438,801000001,R_000089,0.25-0.5,cup, +201004429,201004439,801000001,R_000090,3,g, +201004429,201004440,801000003,R_000091,,,1.0 +201004429,201004441,801000003,R_000092,,,2.0 +201004429,201004442,801000003,R_000093,,,3.0 +201004429,201004443,801000003,R_000094,,,4.0 +201004429,201004444,801000003,R_000095,,,5.0 +201004429,201004445,801000003,R_000096,,,6.0 +201004429,750000000,801000004,R_000097,,, +201004429,650000000,801000005,R_000098,,, +201004446,201004447,801000001,R_000099,200,ml, +201004446,201004448,801000001,R_000100,1,根, +201004446,201004449,801000001,R_000101,1,个, +201004446,201004450,801000001,R_000102,1,个, +201004446,201004451,801000001,R_000103,适量,, +201004446,201004452,801000001,R_000104,5,g, +201004446,201004453,801000001,R_000105,15,ml, +201004446,201004454,801000001,R_000106,10,ml, +201004446,201004455,801000001,R_000107,1,颗, +201004446,201004456,801000003,R_000108,,,1.0 +201004446,201004457,801000003,R_000109,,,2.0 +201004446,201004458,801000003,R_000110,,,3.0 +201004446,201004459,801000003,R_000111,,,4.0 +201004446,201004460,801000003,R_000112,,,5.0 +201004446,201004461,801000003,R_000113,,,6.0 +201004446,201004462,801000003,R_000114,,,7.0 +201004446,201004463,801000003,R_000115,,,8.0 +201004446,201004464,801000003,R_000116,,,9.0 +201004446,201004465,801000003,R_000117,,,10.0 +201004446,750000000,801000004,R_000118,,, +201004446,620000000,801000005,R_000119,,, +201004466,201004467,801000001,R_000120,180,克, +201004466,201004468,801000001,R_000121,80,克, +201004466,201004469,801000001,R_000122,150,克, +201004466,201004470,801000001,R_000123,300,克, +201004466,201004471,801000001,R_000124,10-15,毫升, +201004466,201004472,801000003,R_000125,,,1.0 +201004466,201004473,801000003,R_000126,,,2.0 +201004466,201004474,801000003,R_000127,,,3.0 +201004466,201004475,801000003,R_000128,,,4.0 +201004466,201004476,801000003,R_000129,,,5.0 +201004466,201004477,801000003,R_000130,,,6.0 +201004466,750000000,801000004,R_000131,,, +201004466,610000000,801000005,R_000132,,, +201004478,201004479,801000001,R_000133,500,g, +201004478,201004480,801000001,R_000134,2.5,个, +201004478,201004481,801000001,R_000135,12.5,只, +201004478,201004482,801000001,R_000136,150,g, +201004478,201004483,801000001,R_000137,30,g, +201004478,201004484,801000001,R_000138,30,g, +201004478,201004485,801000001,R_000139,30,g, +201004478,201004486,801000001,R_000140,1,根, +201004478,201004487,801000001,R_000141,35,ml, +201004478,201004488,801000001,R_000142,13.5,g, +201004478,201004489,801000003,R_000143,,,1.0 +201004478,201004490,801000003,R_000144,,,2.0 +201004478,201004491,801000003,R_000145,,,3.0 +201004478,201004492,801000003,R_000146,,,4.0 +201004478,201004493,801000003,R_000147,,,5.0 +201004478,201004494,801000003,R_000148,,,6.0 +201004478,201004495,801000003,R_000149,,,7.0 +201004478,201004496,801000003,R_000150,,,8.0 +201004478,201004497,801000003,R_000151,,,9.0 +201004478,201004498,801000003,R_000152,,,10.0 +201004478,201004499,801000003,R_000153,,,11.0 +201004478,201004500,801000003,R_000154,,,12.0 +201004478,201004501,801000003,R_000155,,,13.0 +201004478,201004502,801000003,R_000156,,,14.0 +201004478,201004503,801000003,R_000157,,,15.0 +201004478,201004504,801000003,R_000158,,,16.0 +201004478,201004505,801000003,R_000159,,,17.0 +201004478,750000000,801000004,R_000160,,, +201004478,640000000,801000005,R_000161,,, +201004506,201004507,801000001,R_000162,500,克, +201004506,201004508,801000001,R_000163,350,克, +201004506,201004509,801000001,R_000164,5,克, +201004506,201004510,801000001,R_000165,3,克, +201004506,201004511,801000001,R_000166,35,克, +201004506,201004512,801000001,R_000167,3,克, +201004506,201004513,801000003,R_000168,,,1.0 +201004506,201004514,801000003,R_000169,,,2.0 +201004506,201004515,801000003,R_000170,,,3.0 +201004506,201004516,801000003,R_000171,,,4.0 +201004506,201004517,801000003,R_000172,,,5.0 +201004506,201004518,801000003,R_000173,,,6.0 +201004506,201004519,801000003,R_000174,,,7.0 +201004506,201004520,801000003,R_000175,,,8.0 +201004506,201004521,801000003,R_000176,,,9.0 +201004506,201004522,801000003,R_000177,,,10.0 +201004506,201004523,801000003,R_000178,,,11.0 +201004506,201004524,801000003,R_000179,,,12.0 +201004506,750000000,801000004,R_000180,,, +201004506,640000000,801000005,R_000181,,, +201004525,201004526,801000001,R_000182,115,g, +201004525,201004527,801000001,R_000183,2,个, +201004525,201004528,801000001,R_000184,2,个, +201004525,201004529,801000001,R_000185,1,根, +201004525,201004530,801000001,R_000186,2.5,瓣, +201004525,201004531,801000001,R_000187,2,斤, +201004525,201004532,801000001,R_000188,适量,, +201004525,201004533,801000001,R_000189,适量,, +201004525,201004534,801000001,R_000190,适量,, +201004525,201004535,801000003,R_000191,,,1.0 +201004525,201004536,801000003,R_000192,,,2.0 +201004525,201004537,801000003,R_000193,,,3.0 +201004525,201004538,801000003,R_000194,,,4.0 +201004525,201004539,801000003,R_000195,,,5.0 +201004525,201004540,801000003,R_000196,,,6.0 +201004525,201004541,801000003,R_000197,,,7.0 +201004525,201004542,801000003,R_000198,,,8.0 +201004525,201004543,801000003,R_000199,,,9.0 +201004525,750000000,801000004,R_000200,,, +201004525,640000000,801000005,R_000201,,, +201004544,201004545,801000001,R_000001,1,个, +201004544,201004546,801000001,R_000002,250,克, +201004544,201004547,801000001,R_000003,1.5,根, +201004544,201004548,801000001,R_000004,5,克, +201004544,201004549,801000001,R_000005,40,克, +201004544,201004550,801000001,R_000006,30,克, +201004544,201004551,801000001,R_000007,20,克, +201004544,201004552,801000001,R_000008,5,克, +201004544,201004553,801000001,R_000009,5,克, +201004544,201004554,801000001,R_000010,250,毫升, +201004544,201004555,801000001,R_000011,30,克, +201004544,201004556,801000001,R_000012,15,克, +201004544,201004557,801000001,R_000013,适量,毫升, +201004544,201004558,801000003,R_000014,,,1.0 +201004544,201004559,801000003,R_000015,,,2.0 +201004544,201004560,801000003,R_000016,,,3.0 +201004544,201004561,801000003,R_000017,,,4.0 +201004544,201004562,801000003,R_000018,,,5.0 +201004544,201004563,801000003,R_000019,,,6.0 +201004544,201004564,801000003,R_000020,,,7.0 +201004544,201004565,801000003,R_000021,,,8.0 +201004544,201004566,801000003,R_000022,,,9.0 +201004544,201004567,801000003,R_000023,,,10.0 +201004544,750000000,801000004,R_000024,,, +201004544,640000000,801000005,R_000025,,, +201004568,201004569,801000001,R_000026,300,g, +201004568,201004570,801000001,R_000027,350,g, +201004568,201004571,801000001,R_000028,150,g, +201004568,201004572,801000001,R_000029,10-15,ml, +201004568,201004573,801000001,R_000030,15,ml, +201004568,201004574,801000001,R_000031,10,ml, +201004568,201004575,801000001,R_000032,5,ml, +201004568,201004576,801000001,R_000033,2,g, +201004568,201004577,801000001,R_000034,2,g, +201004568,201004578,801000001,R_000035,1,g, +201004568,201004579,801000001,R_000036,10,g, +201004568,201004580,801000001,R_000037,5,g, +201004568,201004581,801000001,R_000038,10,g, +201004568,201004582,801000001,R_000039,5,ml, +201004568,201004583,801000001,R_000040,5,ml, +201004568,201004584,801000003,R_000041,,,1.0 +201004568,201004585,801000003,R_000042,,,2.0 +201004568,201004586,801000003,R_000043,,,3.0 +201004568,201004587,801000003,R_000044,,,4.0 +201004568,750000000,801000004,R_000045,,, +201004568,640000000,801000005,R_000046,,, +201004588,201004589,801000001,R_000047,100,g, +201004588,201004590,801000001,R_000048,125,g, +201004588,201004591,801000001,R_000049,90,ml, +201004588,201004592,801000001,R_000050,30,g, +201004588,201004593,801000001,R_000051,30,g, +201004588,201004594,801000001,R_000052,10,g, +201004588,201004595,801000001,R_000053,20,g, +201004588,201004596,801000001,R_000054,10-15,ml, +201004588,201004597,801000003,R_000055,,,1.0 +201004588,201004598,801000003,R_000056,,,2.0 +201004588,201004599,801000003,R_000057,,,3.0 +201004588,201004600,801000003,R_000058,,,4.0 +201004588,201004601,801000003,R_000059,,,5.0 +201004588,201004602,801000003,R_000060,,,6.0 +201004588,750000000,801000004,R_000061,,, +201004588,640000000,801000005,R_000062,,, +201004603,201004604,801000001,R_000063,500,g, +201004603,201004605,801000001,R_000064,10,ml, +201004603,201004606,801000001,R_000065,10,g, +201004603,201004607,801000001,R_000066,15,g, +201004603,201004608,801000001,R_000067,15,g, +201004603,201004609,801000001,R_000068,20,ml, +201004603,201004610,801000001,R_000069,10,ml, +201004603,201004611,801000001,R_000070,5,g, +201004603,201004612,801000001,R_000071,5,g, +201004603,201004613,801000001,R_000072,15,g, +201004603,201004614,801000001,R_000073,20,ml, +201004603,201004615,801000003,R_000074,,,1.0 +201004603,201004616,801000003,R_000075,,,2.0 +201004603,201004617,801000003,R_000076,,,3.0 +201004603,201004618,801000003,R_000077,,,4.0 +201004603,201004619,801000003,R_000078,,,5.0 +201004603,201004620,801000003,R_000079,,,6.0 +201004603,201004621,801000003,R_000080,,,7.0 +201004603,750000000,801000004,R_000081,,, +201004603,630000000,801000005,R_000082,,, +201004622,201004623,801000001,R_000083,50,克, +201004622,201004624,801000001,R_000084,5,片, +201004622,201004625,801000001,R_000085,10,克, +201004622,201004626,801000001,R_000086,适量,, +201004622,201004627,801000001,R_000087,5,毫升, +201004622,201004628,801000001,R_000088,2,克, +201004622,201004629,801000001,R_000089,250,克, +201004622,201004630,801000003,R_000090,,,1.0 +201004622,201004631,801000003,R_000091,,,2.0 +201004622,201004632,801000003,R_000092,,,3.0 +201004622,201004633,801000003,R_000093,,,4.0 +201004622,201004634,801000003,R_000094,,,5.0 +201004622,201004635,801000003,R_000095,,,6.0 +201004622,750000000,801000004,R_000096,,, +201004622,630000000,801000005,R_000097,,, +201004636,201004637,801000001,R_000098,400,g, +201004636,201004638,801000001,R_000099,130,ml, +201004636,201004639,801000001,R_000100,130,ml, +201004636,201004640,801000001,R_000101,适量,, +201004636,201004641,801000001,R_000102,适量,, +201004636,201004642,801000003,R_000103,,,1.0 +201004636,201004643,801000003,R_000104,,,2.0 +201004636,201004644,801000003,R_000105,,,3.0 +201004636,201004645,801000003,R_000106,,,4.0 +201004636,201004646,801000003,R_000107,,,5.0 +201004636,201004647,801000003,R_000108,,,6.0 +201004636,201004648,801000003,R_000109,,,7.0 +201004636,201004649,801000003,R_000110,,,8.0 +201004636,201004650,801000003,R_000111,,,9.0 +201004636,750000000,801000004,R_000112,,, +201004636,640000000,801000005,R_000113,,, +201004651,201004652,801000001,R_000114,300,克, +201004651,201004653,801000001,R_000115,3,克, +201004651,201004654,801000001,R_000116,3,克, +201004651,201004655,801000001,R_000117,4,克, +201004651,201004656,801000001,R_000118,40,克, +201004651,201004657,801000001,R_000119,180,克, +201004651,201004658,801000001,R_000120,2,克, +201004651,201004659,801000001,R_000121,适量,, +201004651,201004660,801000003,R_000122,,,1.0 +201004651,201004661,801000003,R_000123,,,2.0 +201004651,201004662,801000003,R_000124,,,3.0 +201004651,201004663,801000003,R_000125,,,4.0 +201004651,750000000,801000004,R_000126,,, +201004651,630000000,801000005,R_000127,,, +201004664,201004665,801000001,R_000128,1,杯, +201004664,201004666,801000001,R_000129,300,克, +201004664,201004667,801000001,R_000130,1,汤匙, +201004664,201004668,801000001,R_000131,适量,, +201004664,201004669,801000001,R_000132,适量,, +201004664,201004670,801000001,R_000133,适量,, +201004664,201004671,801000001,R_000134,适量,, +201004664,201004672,801000003,R_000135,,,1.0 +201004664,201004673,801000003,R_000136,,,2.0 +201004664,201004674,801000003,R_000137,,,3.0 +201004664,201004675,801000003,R_000138,,,4.0 +201004664,201004676,801000003,R_000139,,,5.0 +201004664,201004677,801000003,R_000140,,,6.0 +201004664,750000000,801000004,R_000141,,, +201004664,620000000,801000005,R_000142,,, +201004678,201004679,801000001,R_000143,900,g, +201004678,201004680,801000001,R_000144,100-125,ml, +201004678,201004681,801000001,R_000145,60-65,g, +201004678,201004682,801000001,R_000146,30-35,ml, +201004678,201004683,801000001,R_000147,48,g, +201004678,201004684,801000001,R_000148,2,个, +201004678,201004685,801000003,R_000149,,,1.0 +201004678,201004686,801000003,R_000150,,,2.0 +201004678,201004687,801000003,R_000151,,,3.0 +201004678,201004688,801000003,R_000152,,,4.0 +201004678,201004689,801000003,R_000153,,,5.0 +201004678,750000000,801000004,R_000154,,, +201004678,640000000,801000005,R_000155,,, +201004690,201004691,801000001,R_000156,100,毫升, +201004690,201004692,801000001,R_000157,200,毫升, +201004690,201004693,801000003,R_000158,,,1.0 +201004690,201004694,801000003,R_000159,,,2.0 +201004690,201004695,801000003,R_000160,,,3.0 +201004690,201004696,801000003,R_000161,,,4.0 +201004690,201004697,801000003,R_000162,,,5.0 +201004690,201004698,801000003,R_000163,,,6.0 +201004690,750000000,801000004,R_000164,,, +201004690,620000000,801000005,R_000165,,, +201004699,201004700,801000001,R_000001,100-200,毫升, +201004699,201004701,801000001,R_000002,100-200,毫升, +201004699,201004702,801000001,R_000003,指尖量水法,, +201004699,201004703,801000003,R_000004,,,1.0 +201004699,201004704,801000003,R_000005,,,2.0 +201004699,201004705,801000003,R_000006,,,3.0 +201004699,201004706,801000003,R_000007,,,4.0 +201004699,201004707,801000003,R_000008,,,5.0 +201004699,201004708,801000003,R_000009,,,6.0 +201004699,750000000,801000004,R_000010,,, +201004699,610000000,801000005,R_000011,,, +201004709,201004710,801000001,R_000012,250,g, +201004709,201004711,801000001,R_000013,50,g, +201004709,201004712,801000001,R_000014,50,g, +201004709,201004713,801000001,R_000015,15,g, +201004709,201004714,801000001,R_000016,30,g, +201004709,201004715,801000001,R_000017,10,g, +201004709,201004716,801000001,R_000018,15,ml, +201004709,201004717,801000001,R_000019,25,ml, +201004709,201004718,801000001,R_000020,5,g, +201004709,201004719,801000001,R_000021,5,ml, +201004709,201004720,801000001,R_000022,5,ml, +201004709,201004721,801000001,R_000023,15,ml, +201004709,201004722,801000001,R_000024,15,ml, +201004709,201004723,801000001,R_000025,10,ml, +201004709,201004724,801000001,R_000026,450,ml, +201004709,201004725,801000003,R_000027,,,1.0 +201004709,201004726,801000003,R_000028,,,2.0 +201004709,201004727,801000003,R_000029,,,3.0 +201004709,201004728,801000003,R_000030,,,4.0 +201004709,201004729,801000003,R_000031,,,5.0 +201004709,201004730,801000003,R_000032,,,6.0 +201004709,750000000,801000004,R_000033,,, +201004709,630000000,801000005,R_000034,,, +201004731,201004732,801000001,R_000035,250,g, +201004731,201004733,801000001,R_000036,50,g, +201004731,201004734,801000001,R_000037,1,个, +201004731,201004735,801000001,R_000038,100,g, +201004731,201004736,801000001,R_000039,1,根, +201004731,201004737,801000001,R_000040,10-30,ml, +201004731,201004738,801000001,R_000041,1-2,g, +201004731,201004739,801000001,R_000042,适量,, +201004731,201004740,801000003,R_000043,,,1.0 +201004731,201004741,801000003,R_000044,,,2.0 +201004731,201004742,801000003,R_000045,,,3.0 +201004731,201004743,801000003,R_000046,,,4.0 +201004731,201004744,801000003,R_000047,,,5.0 +201004731,201004745,801000003,R_000048,,,6.0 +201004731,750000000,801000004,R_000049,,, +201004731,630000000,801000005,R_000050,,, +201004746,201004747,801000001,R_000051,75,克, +201004746,201004748,801000001,R_000052,200,克, +201004746,201004749,801000001,R_000053,1.5,个, +201004746,201004750,801000001,R_000054,1,个, +201004746,201004751,801000001,R_000055,1,根, +201004746,201004752,801000001,R_000056,5,克, +201004746,201004753,801000001,R_000057,6.5,克, +201004746,201004754,801000001,R_000058,5,克, +201004746,201004755,801000001,R_000059,3,克, +201004746,201004756,801000001,R_000060,2,克, +201004746,201004757,801000001,R_000061,20,克, +201004746,201004758,801000001,R_000062,5,克, +201004746,201004759,801000001,R_000063,2,克, +201004746,201004760,801000001,R_000064,2,克, +201004746,201004761,801000001,R_000065,2,克, +201004746,201004762,801000003,R_000066,,,1.0 +201004746,201004763,801000003,R_000067,,,2.0 +201004746,201004764,801000003,R_000068,,,3.0 +201004746,201004765,801000003,R_000069,,,4.0 +201004746,750000000,801000004,R_000070,,, +201004746,620000000,801000005,R_000071,,, +201004766,201004767,801000001,R_000072,300,g, +201004766,201004768,801000001,R_000073,100,g, +201004766,201004769,801000001,R_000074,150,g, +201004766,201004770,801000001,R_000075,2,g, +201004766,201004771,801000001,R_000076,10-18,ml, +201004766,201004772,801000001,R_000077,2,g, +201004766,201004773,801000001,R_000078,10,ml, +201004766,201004774,801000001,R_000079,5,g, +201004766,201004775,801000001,R_000080,1,g, +201004766,201004776,801000001,R_000081,5,ml, +201004766,201004777,801000001,R_000082,1,g, +201004766,201004778,801000001,R_000083,10,g, +201004766,201004779,801000001,R_000084,5,g, +201004766,201004780,801000001,R_000085,10,g, +201004766,201004781,801000001,R_000086,150,ml, +201004766,201004782,801000003,R_000087,,,1.0 +201004766,201004783,801000003,R_000088,,,2.0 +201004766,201004784,801000003,R_000089,,,3.0 +201004766,201004785,801000003,R_000090,,,4.0 +201004766,201004786,801000003,R_000091,,,5.0 +201004766,201004787,801000003,R_000092,,,6.0 +201004766,201004788,801000003,R_000093,,,7.0 +201004766,201004789,801000003,R_000094,,,8.0 +201004766,201004790,801000003,R_000095,,,9.0 +201004766,201004791,801000003,R_000096,,,10.0 +201004766,201004792,801000003,R_000097,,,11.0 +201004766,750000000,801000004,R_000098,,, +201004766,630000000,801000005,R_000099,,, +201004793,201004794,801000001,R_000100,100,g, +201004793,201004795,801000001,R_000101,0.5,根, +201004793,201004796,801000001,R_000102,0.5,根, +201004793,201004797,801000001,R_000103,20,ml, +201004793,201004798,801000003,R_000104,,,1.0 +201004793,201004799,801000003,R_000105,,,2.0 +201004793,201004800,801000003,R_000106,,,3.0 +201004793,750000000,801000004,R_000107,,, +201004793,620000000,801000005,R_000108,,, +201004801,201004802,801000001,R_000109,400,g, +201004801,201004803,801000001,R_000110,1,个, +201004801,201004804,801000001,R_000111,60,g, +201004801,201004805,801000001,R_000112,80,g, +201004801,201004806,801000001,R_000113,50,g, +201004801,201004807,801000001,R_000114,0.25,根, +201004801,201004808,801000001,R_000115,50,g, +201004801,201004809,801000001,R_000116,25,ml, +201004801,201004810,801000001,R_000117,20,ml, +201004801,201004811,801000001,R_000118,10,g, +201004801,201004812,801000001,R_000119,20,ml, +201004801,201004813,801000001,R_000120,15,ml, +201004801,201004814,801000003,R_000121,,,1.0 +201004801,201004815,801000003,R_000122,,,2.0 +201004801,201004816,801000003,R_000123,,,3.0 +201004801,201004817,801000003,R_000124,,,4.0 +201004801,201004818,801000003,R_000125,,,5.0 +201004801,201004819,801000003,R_000126,,,6.0 +201004801,201004820,801000003,R_000127,,,7.0 +201004801,750000000,801000004,R_000128,,, +201004801,630000000,801000005,R_000129,,, +201004821,201004822,801000001,R_000130,1 人份,杯, +201004821,201004823,801000001,R_000131,20,克, +201004821,201004824,801000001,R_000132,80,克, +201004821,201004825,801000003,R_000133,,,1.0 +201004821,201004826,801000003,R_000134,,,2.0 +201004821,750000000,801000004,R_000135,,, +201004821,620000000,801000005,R_000136,,, +201004827,201004828,801000001,R_000137,200,克, +201004827,201004829,801000001,R_000138,10,毫升, +201004827,201004830,801000001,R_000139,5,毫升, +201004827,201004831,801000001,R_000140,15,毫升, +201004827,201004832,801000001,R_000141,10,毫升, +201004827,201004833,801000001,R_000142,5,克, +201004827,201004834,801000001,R_000143,5,毫升, +201004827,201004835,801000001,R_000144,2,头, +201004827,201004836,801000001,R_000145,适量,, +201004827,201004837,801000003,R_000146,,,1.0 +201004827,201004838,801000003,R_000147,,,2.0 +201004827,201004839,801000003,R_000148,,,3.0 +201004827,201004840,801000003,R_000149,,,4.0 +201004827,710000000,801000004,R_000150,,, +201004827,610000000,801000005,R_000151,,, +201004841,201004842,801000001,R_000152,250,g, +201004841,201004843,801000001,R_000153,10,g, +201004841,201004844,801000001,R_000154,2,瓣, +201004841,201004845,801000001,R_000155,15,ml, +201004841,201004846,801000001,R_000156,5,ml, +201004841,201004847,801000001,R_000157,5,ml, +201004841,201004848,801000001,R_000158,2,g, +201004841,201004849,801000001,R_000159,5,ml, +201004841,201004850,801000003,R_000160,,,1.0 +201004841,201004851,801000003,R_000161,,,2.0 +201004841,201004852,801000003,R_000162,,,3.0 +201004841,201004853,801000003,R_000163,,,4.0 +201004841,201004854,801000003,R_000164,,,5.0 +201004841,201004855,801000003,R_000165,,,6.0 +201004841,201004856,801000003,R_000166,,,7.0 +201004841,201004857,801000003,R_000167,,,8.0 +201004841,201004858,801000003,R_000168,,,9.0 +201004841,201004859,801000003,R_000169,,,10.0 +201004841,201004860,801000003,R_000170,,,11.0 +201004841,201004861,801000003,R_000171,,,12.0 +201004841,201004862,801000003,R_000172,,,13.0 +201004841,710000000,801000004,R_000173,,, +201004841,620000000,801000005,R_000174,,, +201004863,201004864,801000001,R_000001,150,g, +201004863,201004865,801000001,R_000002,5,g, +201004863,201004866,801000001,R_000003,2,瓣, +201004863,201004867,801000001,R_000004,15,ml, +201004863,201004868,801000001,R_000005,10,ml, +201004863,201004869,801000001,R_000006,3,g, +201004863,201004870,801000001,R_000007,5,ml, +201004863,201004871,801000001,R_000008,5,ml, +201004863,201004872,801000003,R_000009,,,1.0 +201004863,201004873,801000003,R_000010,,,2.0 +201004863,201004874,801000003,R_000011,,,3.0 +201004863,201004875,801000003,R_000012,,,4.0 +201004863,201004876,801000003,R_000013,,,5.0 +201004863,201004877,801000003,R_000014,,,6.0 +201004863,201004878,801000003,R_000015,,,7.0 +201004863,201004879,801000003,R_000016,,,8.0 +201004863,201004880,801000003,R_000017,,,9.0 +201004863,201004881,801000003,R_000018,,,10.0 +201004863,201004882,801000003,R_000019,,,11.0 +201004863,201004883,801000003,R_000020,,,12.0 +201004863,201004884,801000003,R_000021,,,13.0 +201004863,710000000,801000004,R_000022,,, +201004863,620000000,801000005,R_000023,,, +201004885,201004886,801000001,R_000024,200,克, +201004885,201004887,801000001,R_000025,11.5,毫升, +201004885,201004888,801000001,R_000026,7.5,毫升, +201004885,201004889,801000001,R_000027,3,瓣, +201004885,201004890,801000001,R_000028,0.6,克, +201004885,201004891,801000001,R_000029,7,毫升, +201004885,201004892,801000001,R_000030,5,毫升, +201004885,201004893,801000003,R_000031,,,1.0 +201004885,201004894,801000003,R_000032,,,2.0 +201004885,201004895,801000003,R_000033,,,3.0 +201004885,201004896,801000003,R_000034,,,4.0 +201004885,201004897,801000003,R_000035,,,5.0 +201004885,710000000,801000004,R_000036,,, +201004885,610000000,801000005,R_000037,,, +201004898,201004899,801000001,R_000038,100,g, +201004898,201004900,801000001,R_000039,150,g, +201004898,201004901,801000001,R_000040,3.5,个, +201004898,201004902,801000001,R_000041,3,g, +201004898,201004903,801000001,R_000042,10,g, +201004898,201004904,801000001,R_000043,10,g, +201004898,201004905,801000001,R_000044,20,ml, +201004898,201004906,801000001,R_000045,10,ml, +201004898,201004907,801000001,R_000046,8,g, +201004898,201004908,801000001,R_000047,10,g, +201004898,201004909,801000001,R_000048,20,g, +201004898,201004910,801000001,R_000049,40,ml, +201004898,201004911,801000001,R_000050,200,ml, +201004898,201004912,801000003,R_000051,,,1.0 +201004898,201004913,801000003,R_000052,,,2.0 +201004898,201004914,801000003,R_000053,,,3.0 +201004898,201004915,801000003,R_000054,,,4.0 +201004898,201004916,801000003,R_000055,,,5.0 +201004898,201004917,801000003,R_000056,,,6.0 +201004898,201004918,801000003,R_000057,,,7.0 +201004898,201004919,801000003,R_000058,,,8.0 +201004898,201004920,801000003,R_000059,,,9.0 +201004898,201004921,801000003,R_000060,,,10.0 +201004898,201004922,801000003,R_000061,,,11.0 +201004898,201004923,801000003,R_000062,,,12.0 +201004898,201004924,801000003,R_000063,,,13.0 +201004898,201004925,801000003,R_000064,,,14.0 +201004898,201004926,801000003,R_000065,,,15.0 +201004898,201004927,801000003,R_000066,,,16.0 +201004898,710000000,801000004,R_000067,,, +201004898,630000000,801000005,R_000068,,, +201004928,201004929,801000001,R_000069,200,g, +201004928,201004930,801000001,R_000070,30,g, +201004928,201004931,801000001,R_000071,50,g, +201004928,201004932,801000001,R_000072,15,ml, +201004928,201004933,801000001,R_000073,10,g, +201004928,201004934,801000001,R_000074,1,g, +201004928,201004935,801000001,R_000075,5,g, +201004928,201004936,801000001,R_000076,20,ml, +201004928,201004937,801000003,R_000077,,,1.0 +201004928,201004938,801000003,R_000078,,,2.0 +201004928,201004939,801000003,R_000079,,,3.0 +201004928,201004940,801000003,R_000080,,,4.0 +201004928,201004941,801000003,R_000081,,,5.0 +201004928,201004942,801000003,R_000082,,,6.0 +201004928,710000000,801000004,R_000083,,, +201004928,620000000,801000005,R_000084,,, +201004943,201004944,801000001,R_000085,300-500,g, +201004943,201004945,801000001,R_000086,2,ml, +201004943,201004946,801000001,R_000087,3,g, +201004943,201004947,801000001,R_000088,3,ml, +201004943,201004948,801000001,R_000089,150,ml, +201004943,201004949,801000003,R_000090,,,1.0 +201004943,201004950,801000003,R_000091,,,2.0 +201004943,201004951,801000003,R_000092,,,3.0 +201004943,201004952,801000003,R_000093,,,4.0 +201004943,201004953,801000003,R_000094,,,5.0 +201004943,201004954,801000003,R_000095,,,6.0 +201004943,201004955,801000003,R_000096,,,7.0 +201004943,710000000,801000004,R_000097,,, +201004943,620000000,801000005,R_000098,,, +201004956,201004957,801000001,R_000099,4,个, +201004956,201004958,801000001,R_000100,2,个, +201004956,201004959,801000001,R_000101,2,根, +201004956,201004960,801000001,R_000102,3,瓣, +201004956,201004961,801000001,R_000103,适量,, +201004956,201004962,801000001,R_000104,10,毫升, +201004956,201004963,801000001,R_000105,15,毫升, +201004956,201004964,801000001,R_000106,10,毫升, +201004956,201004965,801000001,R_000107,5,毫升, +201004956,201004966,801000001,R_000108,3,克, +201004956,201004967,801000001,R_000109,20,毫升, +201004956,201004968,801000003,R_000110,,,1.0 +201004956,201004969,801000003,R_000111,,,2.0 +201004956,201004970,801000003,R_000112,,,3.0 +201004956,201004971,801000003,R_000113,,,4.0 +201004956,201004972,801000003,R_000114,,,5.0 +201004956,201004973,801000003,R_000115,,,6.0 +201004956,710000000,801000004,R_000116,,, +201004956,620000000,801000005,R_000117,,, +201004974,201004975,801000001,R_000118,300,g, +201004974,201004976,801000001,R_000119,2.5,瓣, +201004974,201004977,801000001,R_000120,3,g, +201004974,201004978,801000001,R_000121,15,ml, +201004974,201004979,801000001,R_000122,50,ml, +201004974,201004980,801000003,R_000123,,,1.0 +201004974,201004981,801000003,R_000124,,,2.0 +201004974,201004982,801000003,R_000125,,,3.0 +201004974,201004983,801000003,R_000126,,,4.0 +201004974,201004984,801000003,R_000127,,,5.0 +201004974,201004985,801000003,R_000128,,,6.0 +201004974,201004986,801000003,R_000129,,,7.0 +201004974,201004987,801000003,R_000130,,,8.0 +201004974,201004988,801000003,R_000131,,,9.0 +201004974,201004989,801000003,R_000132,,,10.0 +201004974,201004990,801000003,R_000133,,,11.0 +201004974,710000000,801000004,R_000134,,, +201004974,620000000,801000005,R_000135,,, +201004991,201004992,801000001,R_000136,300,克, +201004991,201004993,801000001,R_000137,1000,毫升, +201004991,201004994,801000003,R_000138,,,1.0 +201004991,201004995,801000003,R_000139,,,2.0 +201004991,201004996,801000003,R_000140,,,3.0 +201004991,201004997,801000003,R_000141,,,4.0 +201004991,201004998,801000003,R_000142,,,5.0 +201004991,201004999,801000003,R_000143,,,6.0 +201004991,201005000,801000003,R_000144,,,7.0 +201004991,710000000,801000004,R_000145,,, +201004991,610000000,801000005,R_000146,,, +201005001,201005002,801000001,R_000147,1.8,个, +201005001,201005003,801000001,R_000148,1,个, +201005001,201005004,801000001,R_000149,正常男子手抓半把,, +201005001,201005005,801000001,R_000150,2,颗, +201005001,201005006,801000001,R_000151,40,ml, +201005001,201005007,801000001,R_000152,没过锅底的两倍,, +201005001,201005008,801000003,R_000153,,,1.0 +201005001,201005009,801000003,R_000154,,,2.0 +201005001,201005010,801000003,R_000155,,,3.0 +201005001,201005011,801000003,R_000156,,,4.0 +201005001,201005012,801000003,R_000157,,,5.0 +201005001,201005013,801000003,R_000158,,,6.0 +201005001,201005014,801000003,R_000159,,,7.0 +201005001,201005015,801000003,R_000160,,,8.0 +201005001,201005016,801000003,R_000161,,,9.0 +201005001,201005017,801000003,R_000162,,,10.0 +201005001,201005018,801000003,R_000163,,,11.0 +201005001,710000000,801000004,R_000164,,, +201005001,630000000,801000005,R_000165,,, +201005019,201005020,801000001,R_000166,100,g, +201005019,201005021,801000001,R_000167,10-15,ml, +201005019,201005022,801000001,R_000168,2,g, +201005019,201005023,801000001,R_000169,70,ml, +201005019,201005024,801000001,R_000170,5,g, +201005019,201005025,801000003,R_000171,,,1.0 +201005019,201005026,801000003,R_000172,,,2.0 +201005019,201005027,801000003,R_000173,,,3.0 +201005019,201005028,801000003,R_000174,,,4.0 +201005019,201005029,801000003,R_000175,,,5.0 +201005019,201005030,801000003,R_000176,,,6.0 +201005019,710000000,801000004,R_000177,,, +201005019,620000000,801000005,R_000178,,, +201005031,201005032,801000001,R_000001,250,g, +201005031,201005033,801000001,R_000002,2,个, +201005031,201005034,801000001,R_000003,3,圈, +201005031,201005035,801000001,R_000004,2,颗, +201005031,201005036,801000001,R_000005,6,ml, +201005031,201005037,801000001,R_000006,2,ml, +201005031,201005038,801000001,R_000007,6,ml, +201005031,201005039,801000001,R_000008,6,g, +201005031,201005040,801000003,R_000009,,,1.0 +201005031,201005041,801000003,R_000010,,,2.0 +201005031,201005042,801000003,R_000011,,,3.0 +201005031,201005043,801000003,R_000012,,,4.0 +201005031,201005044,801000003,R_000013,,,5.0 +201005031,201005045,801000003,R_000014,,,6.0 +201005031,201005046,801000003,R_000015,,,7.0 +201005031,201005047,801000003,R_000016,,,8.0 +201005031,201005048,801000003,R_000017,,,9.0 +201005031,710000000,801000004,R_000018,,, +201005031,620000000,801000005,R_000019,,, +201005049,201005050,801000001,R_000020,0.7,个, +201005049,201005051,801000001,R_000021,0.5,个, +201005049,201005052,801000001,R_000022,0.3,个, +201005049,201005053,801000001,R_000023,1,个, +201005049,201005054,801000001,R_000024,0.5,颗, +201005049,201005055,801000001,R_000025,3,瓣, +201005049,201005056,801000001,R_000026,1,个, +201005049,201005057,801000001,R_000027,105,克, +201005049,201005058,801000001,R_000028,26.25,克, +201005049,201005059,801000001,R_000029,5.25,克, +201005049,201005060,801000001,R_000030,5,克, +201005049,201005061,801000001,R_000031,505,毫升, +201005049,201005062,801000003,R_000032,,,1.0 +201005049,201005063,801000003,R_000033,,,2.0 +201005049,201005064,801000003,R_000034,,,3.0 +201005049,201005065,801000003,R_000035,,,4.0 +201005049,201005066,801000003,R_000036,,,5.0 +201005049,201005067,801000003,R_000037,,,6.0 +201005049,201005068,801000003,R_000038,,,7.0 +201005049,201005069,801000003,R_000039,,,8.0 +201005049,201005070,801000003,R_000040,,,9.0 +201005049,201005071,801000003,R_000041,,,10.0 +201005049,201005072,801000003,R_000042,,,11.0 +201005049,201005073,801000003,R_000043,,,12.0 +201005049,710000000,801000004,R_000044,,, +201005049,640000000,801000005,R_000045,,, +201005074,201005075,801000001,R_000046,1,块, +201005074,201005076,801000001,R_000047,2,个, +201005074,201005077,801000001,R_000048,50,g, +201005074,201005078,801000001,R_000049,20,g, +201005074,201005079,801000001,R_000050,10,g, +201005074,201005080,801000001,R_000051,5,g, +201005074,201005081,801000001,R_000052,10,g, +201005074,201005082,801000001,R_000053,200,ml, +201005074,201005083,801000001,R_000054,18,ml, +201005074,201005084,801000003,R_000055,,,1.0 +201005074,201005085,801000003,R_000056,,,2.0 +201005074,201005086,801000003,R_000057,,,3.0 +201005074,201005087,801000003,R_000058,,,4.0 +201005074,201005088,801000003,R_000059,,,5.0 +201005074,201005089,801000003,R_000060,,,6.0 +201005074,201005090,801000003,R_000061,,,7.0 +201005074,201005091,801000003,R_000062,,,8.0 +201005074,710000000,801000004,R_000063,,, +201005074,630000000,801000005,R_000064,,, +201005092,201005093,801000001,R_000065,150,克, +201005092,201005094,801000001,R_000066,150,克, +201005092,201005095,801000001,R_000067,180,克, +201005092,201005096,801000001,R_000068,50,克, +201005092,201005097,801000001,R_000069,15,毫升, +201005092,201005098,801000001,R_000070,5,克, +201005092,201005099,801000001,R_000071,3,瓣, +201005092,201005100,801000001,R_000072,13,毫升, +201005092,201005101,801000001,R_000073,适量,毫升, +201005092,201005102,801000003,R_000074,,,1.0 +201005092,201005103,801000003,R_000075,,,2.0 +201005092,201005104,801000003,R_000076,,,3.0 +201005092,201005105,801000003,R_000077,,,4.0 +201005092,201005106,801000003,R_000078,,,5.0 +201005092,201005107,801000003,R_000079,,,6.0 +201005092,201005108,801000003,R_000080,,,7.0 +201005092,201005109,801000003,R_000081,,,8.0 +201005092,201005110,801000003,R_000082,,,9.0 +201005092,201005111,801000003,R_000083,,,10.0 +201005092,710000000,801000004,R_000084,,, +201005092,630000000,801000005,R_000085,,, +201005112,201005113,801000001,R_000086,0.8,块, +201005112,201005114,801000001,R_000087,0.67,根, +201005112,201005115,801000001,R_000088,0.5,只, +201005112,201005116,801000001,R_000089,3,克, +201005112,201005117,801000001,R_000090,1.5,克, +201005112,201005118,801000001,R_000091,9,毫升, +201005112,201005119,801000001,R_000092,10,毫升, +201005112,201005120,801000003,R_000093,,,1.0 +201005112,201005121,801000003,R_000094,,,2.0 +201005112,201005122,801000003,R_000095,,,3.0 +201005112,201005123,801000003,R_000096,,,4.0 +201005112,201005124,801000003,R_000097,,,5.0 +201005112,201005125,801000003,R_000098,,,6.0 +201005112,201005126,801000003,R_000099,,,7.0 +201005112,201005127,801000003,R_000100,,,8.0 +201005112,201005128,801000003,R_000101,,,9.0 +201005112,710000000,801000004,R_000102,,, +201005112,630000000,801000005,R_000103,,, +201005129,201005130,801000001,R_000104,200,g, +201005129,201005131,801000001,R_000105,3,瓣, +201005129,201005132,801000001,R_000106,10,ml, +201005129,201005133,801000001,R_000107,5,ml, +201005129,201005134,801000001,R_000108,2,g, +201005129,201005135,801000001,R_000109,10,ml, +201005129,201005136,801000001,R_000110,1030,ml, +201005129,201005137,801000003,R_000111,,,1.0 +201005129,201005138,801000003,R_000112,,,2.0 +201005129,201005139,801000003,R_000113,,,3.0 +201005129,201005140,801000003,R_000114,,,4.0 +201005129,201005141,801000003,R_000115,,,5.0 +201005129,201005142,801000003,R_000116,,,6.0 +201005129,201005143,801000003,R_000117,,,7.0 +201005129,201005144,801000003,R_000118,,,8.0 +201005129,201005145,801000003,R_000119,,,9.0 +201005129,710000000,801000004,R_000120,,, +201005129,620000000,801000005,R_000121,,, +201005146,201005147,801000001,R_000122,1,个, +201005146,201005148,801000001,R_000123,20,毫升, +201005146,201005149,801000001,R_000124,15,毫升, +201005146,201005150,801000001,R_000125,40,毫升, +201005146,201005151,801000001,R_000126,10,毫升, +201005146,201005152,801000001,R_000127,20,毫升, +201005146,201005153,801000001,R_000128,100,毫升, +201005146,201005154,801000001,R_000129,适量,, +201005146,201005155,801000001,R_000130,适量,, +201005146,201005156,801000003,R_000131,,,1.0 +201005146,201005157,801000003,R_000132,,,2.0 +201005146,201005158,801000003,R_000133,,,3.0 +201005146,201005159,801000003,R_000134,,,4.0 +201005146,201005160,801000003,R_000135,,,5.0 +201005146,201005161,801000003,R_000136,,,6.0 +201005146,201005162,801000003,R_000137,,,7.0 +201005146,201005163,801000003,R_000138,,,8.0 +201005146,710000000,801000004,R_000139,,, +201005146,630000000,801000005,R_000140,,, +201005164,201005165,801000001,R_000141,200,g, +201005164,201005166,801000001,R_000142,7,ml, +201005164,201005167,801000001,R_000143,4.5,瓣, +201005164,201005168,801000001,R_000144,6,ml, +201005164,201005169,801000001,R_000145,0.5,g, +201005164,201005170,801000001,R_000146,1,g, +201005164,201005171,801000001,R_000147,6.5,ml, +201005164,201005172,801000001,R_000148,1015,ml, +201005164,201005173,801000003,R_000149,,,1.0 +201005164,201005174,801000003,R_000150,,,2.0 +201005164,201005175,801000003,R_000151,,,3.0 +201005164,201005176,801000003,R_000152,,,4.0 +201005164,201005177,801000003,R_000153,,,5.0 +201005164,201005178,801000003,R_000154,,,6.0 +201005164,201005179,801000003,R_000155,,,7.0 +201005164,201005180,801000003,R_000156,,,8.0 +201005164,710000000,801000004,R_000157,,, +201005164,620000000,801000005,R_000158,,, +201005181,201005182,801000001,R_000159,1,个, +201005181,201005183,801000001,R_000160,1.5,个, +201005181,201005184,801000001,R_000161,6,ml, +201005181,201005185,801000001,R_000162,1.5,g, +201005181,201005186,801000001,R_000163,0,g, +201005181,201005187,801000001,R_000164,0,g, +201005181,201005188,801000003,R_000165,,,1.0 +201005181,201005189,801000003,R_000166,,,2.0 +201005181,201005190,801000003,R_000167,,,3.0 +201005181,201005191,801000003,R_000168,,,4.0 +201005181,201005192,801000003,R_000169,,,5.0 +201005181,201005193,801000003,R_000170,,,6.0 +201005181,201005194,801000003,R_000171,,,7.0 +201005181,710000000,801000004,R_000172,,, +201005181,620000000,801000005,R_000173,,, +201005195,201005196,801000001,R_000174,240,g, +201005195,201005197,801000001,R_000175,4,瓣, +201005195,201005198,801000001,R_000176,0.5,个, +201005195,201005199,801000001,R_000177,0.5,个, +201005195,201005200,801000001,R_000178,3,个, +201005195,201005201,801000001,R_000179,1,根, +201005195,201005202,801000001,R_000180,5,ml, +201005195,201005203,801000001,R_000181,10,ml, +201005195,201005204,801000001,R_000182,2,g, +201005195,201005205,801000001,R_000183,10-15,ml, +201005195,201005206,801000003,R_000184,,,1.0 +201005195,201005207,801000003,R_000185,,,2.0 +201005195,201005208,801000003,R_000186,,,3.0 +201005195,201005209,801000003,R_000187,,,4.0 +201005195,201005210,801000003,R_000188,,,5.0 +201005195,201005211,801000003,R_000189,,,6.0 +201005195,710000000,801000004,R_000190,,, +201005195,620000000,801000005,R_000191,,, +201005212,201005213,801000001,R_000001,1-2,把, +201005212,201005214,801000001,R_000002,2,袋, +201005212,201005215,801000001,R_000003,3-5,根, +201005212,201005216,801000001,R_000004,2-3,瓣, +201005212,201005217,801000001,R_000005,15,毫升, +201005212,201005218,801000001,R_000006,5,毫升, +201005212,201005219,801000001,R_000007,3,毫升, +201005212,201005220,801000001,R_000008,3,克, +201005212,201005221,801000001,R_000009,10-15,毫升, +201005212,201005222,801000001,R_000010,100,毫升, +201005212,201005223,801000003,R_000011,,,1.0 +201005212,201005224,801000003,R_000012,,,2.0 +201005212,201005225,801000003,R_000013,,,3.0 +201005212,710000000,801000004,R_000014,,, +201005212,620000000,801000005,R_000015,,, +201005226,201005227,801000001,R_000016,600,g, +201005226,201005228,801000001,R_000017,2,个, +201005226,201005229,801000001,R_000018,2,个, +201005226,201005230,801000001,R_000019,4,个, +201005226,201005231,801000001,R_000020,12,g, +201005226,201005232,801000001,R_000021,12,ml, +201005226,201005233,801000001,R_000022,6,g, +201005226,201005234,801000001,R_000023,12,ml, +201005226,201005235,801000001,R_000024,3,圈, +201005226,201005236,801000001,R_000025,2,g, +201005226,201005237,801000001,R_000026,2,颗, +201005226,201005238,801000001,R_000027,适量,, +201005226,201005239,801000001,R_000028,10-15,ml, +201005226,201005240,801000003,R_000029,,,1.0 +201005226,201005241,801000003,R_000030,,,2.0 +201005226,201005242,801000003,R_000031,,,3.0 +201005226,201005243,801000003,R_000032,,,4.0 +201005226,201005244,801000003,R_000033,,,5.0 +201005226,201005245,801000003,R_000034,,,6.0 +201005226,201005246,801000003,R_000035,,,7.0 +201005226,201005247,801000003,R_000036,,,8.0 +201005226,201005248,801000003,R_000037,,,9.0 +201005226,201005249,801000003,R_000038,,,10.0 +201005226,201005250,801000003,R_000039,,,11.0 +201005226,710000000,801000004,R_000040,,, +201005226,620000000,801000005,R_000041,,, +201005251,201005252,801000001,R_000042,2,个, +201005251,201005253,801000001,R_000043,4,根, +201005251,201005254,801000001,R_000044,10,cm, +201005251,201005255,801000001,R_000045,3.5,瓣, +201005251,201005256,801000001,R_000046,3.5,颗, +201005251,201005257,801000001,R_000047,15,ml, +201005251,201005258,801000001,R_000048,17.5,ml, +201005251,201005259,801000001,R_000049,17.5,ml, +201005251,201005260,801000001,R_000050,8,g, +201005251,201005261,801000001,R_000051,6,ml, +201005251,201005262,801000003,R_000052,,,1.0 +201005251,201005263,801000003,R_000053,,,2.0 +201005251,201005264,801000003,R_000054,,,3.0 +201005251,201005265,801000003,R_000055,,,4.0 +201005251,201005266,801000003,R_000056,,,5.0 +201005251,201005267,801000003,R_000057,,,6.0 +201005251,201005268,801000003,R_000058,,,7.0 +201005251,201005269,801000003,R_000059,,,8.0 +201005251,201005270,801000003,R_000060,,,9.0 +201005251,201005271,801000003,R_000061,,,10.0 +201005251,710000000,801000004,R_000062,,, +201005251,620000000,801000005,R_000063,,, +201005272,201005273,801000001,R_000064,200,g, +201005272,201005274,801000001,R_000065,2,个, +201005272,201005275,801000001,R_000066,40,g, +201005272,201005276,801000001,R_000067,1,个, +201005272,201005277,801000001,R_000068,10,ml, +201005272,201005278,801000001,R_000069,3,ml, +201005272,201005279,801000001,R_000070,2,g, +201005272,201005280,801000003,R_000071,,,1.0 +201005272,201005281,801000003,R_000072,,,2.0 +201005272,201005282,801000003,R_000073,,,3.0 +201005272,201005283,801000003,R_000074,,,4.0 +201005272,201005284,801000003,R_000075,,,5.0 +201005272,201005285,801000003,R_000076,,,6.0 +201005272,201005286,801000003,R_000077,,,7.0 +201005272,201005287,801000003,R_000078,,,8.0 +201005272,201005288,801000003,R_000079,,,9.0 +201005272,710000000,801000004,R_000080,,, +201005272,620000000,801000005,R_000081,,, +201005289,201005290,801000001,R_000082,700,g, +201005289,201005291,801000001,R_000083,1,个, +201005289,201005292,801000001,R_000084,适量,, +201005289,201005293,801000001,R_000085,10,g, +201005289,201005294,801000001,R_000086,3,g, +201005289,201005295,801000001,R_000087,10,g, +201005289,201005296,801000001,R_000088,10,g, +201005289,201005297,801000001,R_000089,适量,, +201005289,201005298,801000001,R_000090,适量,, +201005289,201005299,801000001,R_000091,适量,, +201005289,201005300,801000001,R_000092,适量,, +201005289,201005301,801000001,R_000093,适量,, +201005289,201005302,801000003,R_000094,,,1.0 +201005289,201005303,801000003,R_000095,,,2.0 +201005289,201005304,801000003,R_000096,,,3.0 +201005289,201005305,801000003,R_000097,,,4.0 +201005289,201005306,801000003,R_000098,,,5.0 +201005289,201005307,801000003,R_000099,,,6.0 +201005289,201005308,801000003,R_000100,,,7.0 +201005289,201005309,801000003,R_000101,,,8.0 +201005289,201005310,801000003,R_000102,,,9.0 +201005289,201005311,801000003,R_000103,,,10.0 +201005289,710000000,801000004,R_000104,,, +201005289,630000000,801000005,R_000105,,, +201005312,201005313,801000001,R_000106,20,g, +201005312,201005314,801000001,R_000107,120,g, +201005312,201005315,801000001,R_000108,2,个, +201005312,201005316,801000001,R_000109,2,个, +201005312,201005317,801000001,R_000110,2,g, +201005312,201005318,801000001,R_000111,7.5,g, +201005312,201005319,801000001,R_000112,15,ml, +201005312,201005320,801000001,R_000113,15,ml, +201005312,201005321,801000001,R_000114,5,ml, +201005312,201005322,801000001,R_000115,2,cm, +201005312,201005323,801000003,R_000116,,,1.0 +201005312,201005324,801000003,R_000117,,,2.0 +201005312,201005325,801000003,R_000118,,,3.0 +201005312,201005326,801000003,R_000119,,,4.0 +201005312,201005327,801000003,R_000120,,,5.0 +201005312,201005328,801000003,R_000121,,,6.0 +201005312,710000000,801000004,R_000122,,, +201005312,620000000,801000005,R_000123,,, +201005329,201005330,801000001,R_000124,1,根, +201005329,201005331,801000001,R_000125,0.25,根, +201005329,201005332,801000001,R_000126,2,个, +201005329,201005333,801000001,R_000127,1,片, +201005329,201005334,801000001,R_000128,2,粒, +201005329,201005335,801000001,R_000129,5,g, +201005329,201005336,801000001,R_000130,25,ml, +201005329,201005337,801000003,R_000131,,,1.0 +201005329,201005338,801000003,R_000132,,,2.0 +201005329,201005339,801000003,R_000133,,,3.0 +201005329,201005340,801000003,R_000134,,,4.0 +201005329,201005341,801000003,R_000135,,,5.0 +201005329,710000000,801000004,R_000136,,, +201005329,620000000,801000005,R_000137,,, +201005342,201005343,801000001,R_000138,0.5,颗, +201005342,201005344,801000001,R_000139,2,个, +201005342,201005345,801000001,R_000140,1,把, +201005342,201005346,801000001,R_000141,0.5,根, +201005342,201005347,801000001,R_000142,20,ml, +201005342,201005348,801000001,R_000143,2,g, +201005342,201005349,801000001,R_000144,15,ml, +201005342,201005350,801000001,R_000145,10,ml, +201005342,201005351,801000001,R_000146,10,ml, +201005342,201005352,801000001,R_000147,0.5,根, +201005342,201005353,801000001,R_000148,2,片, +201005342,201005354,801000001,R_000149,5,根, +201005342,201005355,801000003,R_000150,,,1.0 +201005342,201005356,801000003,R_000151,,,2.0 +201005342,201005357,801000003,R_000152,,,3.0 +201005342,201005358,801000003,R_000153,,,4.0 +201005342,201005359,801000003,R_000154,,,5.0 +201005342,201005360,801000003,R_000155,,,6.0 +201005342,201005361,801000003,R_000156,,,7.0 +201005342,201005362,801000003,R_000157,,,8.0 +201005342,201005363,801000003,R_000158,,,9.0 +201005342,201005364,801000003,R_000159,,,10.0 +201005342,201005365,801000003,R_000160,,,11.0 +201005342,710000000,801000004,R_000161,,, +201005342,630000000,801000005,R_000162,,, +201005366,201005367,801000001,R_000163,1,段, +201005366,201005368,801000001,R_000164,1-2,根, +201005366,201005369,801000001,R_000165,1,段, +201005366,201005370,801000001,R_000166,30,毫升, +201005366,201005371,801000001,R_000167,15,毫升, +201005366,201005372,801000001,R_000168,15,毫升, +201005366,201005373,801000001,R_000169,10-15,毫升, +201005366,201005374,801000003,R_000170,,,1.0 +201005366,201005375,801000003,R_000171,,,2.0 +201005366,201005376,801000003,R_000172,,,3.0 +201005366,201005377,801000003,R_000173,,,4.0 +201005366,201005378,801000003,R_000174,,,5.0 +201005366,201005379,801000003,R_000175,,,6.0 +201005366,201005380,801000003,R_000176,,,7.0 +201005366,201005381,801000003,R_000177,,,8.0 +201005366,201005382,801000003,R_000178,,,9.0 +201005366,710000000,801000004,R_000179,,, +201005366,630000000,801000005,R_000180,,, +201005383,201005384,801000001,R_000181,400,g, +201005383,201005385,801000001,R_000182,100,g, +201005383,201005386,801000001,R_000183,1.5,根, +201005383,201005387,801000001,R_000184,10,ml, +201005383,201005388,801000001,R_000185,5,g, +201005383,201005389,801000001,R_000186,3.5,个, +201005383,201005390,801000001,R_000187,2,g, +201005383,201005391,801000001,R_000188,10,ml, +201005383,201005392,801000003,R_000189,,,1.0 +201005383,201005393,801000003,R_000190,,,2.0 +201005383,201005394,801000003,R_000191,,,3.0 +201005383,201005395,801000003,R_000192,,,4.0 +201005383,201005396,801000003,R_000193,,,5.0 +201005383,201005397,801000003,R_000194,,,6.0 +201005383,201005398,801000003,R_000195,,,7.0 +201005383,201005399,801000003,R_000196,,,8.0 +201005383,201005400,801000003,R_000197,,,9.0 +201005383,710000000,801000004,R_000198,,, +201005383,630000000,801000005,R_000199,,, +201005401,201005402,801000001,R_000001,1,颗, +201005401,201005403,801000001,R_000002,200,g, +201005401,201005404,801000001,R_000003,2,根, +201005401,201005405,801000001,R_000004,60,ml, +201005401,201005406,801000001,R_000005,5,ml, +201005401,201005407,801000001,R_000006,5,ml, +201005401,201005408,801000001,R_000007,5,ml, +201005401,201005409,801000001,R_000008,2,g, +201005401,201005410,801000001,R_000009,2,片, +201005401,201005411,801000001,R_000010,2,粒, +201005401,201005412,801000001,R_000011,0.5,根, +201005401,201005413,801000001,R_000012,5,g, +201005401,201005414,801000003,R_000013,,,1.0 +201005401,201005415,801000003,R_000014,,,2.0 +201005401,201005416,801000003,R_000015,,,3.0 +201005401,201005417,801000003,R_000016,,,4.0 +201005401,201005418,801000003,R_000017,,,5.0 +201005401,201005419,801000003,R_000018,,,6.0 +201005401,201005420,801000003,R_000019,,,7.0 +201005401,201005421,801000003,R_000020,,,8.0 +201005401,710000000,801000004,R_000021,,, +201005401,630000000,801000005,R_000022,,, +201005422,201005423,801000001,R_000023,2,个, +201005422,201005424,801000001,R_000024,300,毫升, +201005422,201005425,801000001,R_000025,30,克, +201005422,201005426,801000001,R_000026,120,克, +201005422,201005427,801000001,R_000027,100,毫升, +201005422,201005428,801000001,R_000028,5,克, +201005422,201005429,801000003,R_000029,,,1.0 +201005422,201005430,801000003,R_000030,,,2.0 +201005422,201005431,801000003,R_000031,,,3.0 +201005422,201005432,801000003,R_000032,,,4.0 +201005422,201005433,801000003,R_000033,,,5.0 +201005422,201005434,801000003,R_000034,,,6.0 +201005422,710000000,801000004,R_000035,,, +201005422,630000000,801000005,R_000036,,, +201005435,201005436,801000001,R_000037,350,g, +201005435,201005437,801000001,R_000038,40-70,g, +201005435,201005438,801000001,R_000039,10,g, +201005435,201005439,801000001,R_000040,10,g, +201005435,201005440,801000001,R_000041,铺满锅底,适量, +201005435,201005441,801000003,R_000042,,,1.0 +201005435,201005442,801000003,R_000043,,,2.0 +201005435,201005443,801000003,R_000044,,,3.0 +201005435,201005444,801000003,R_000045,,,4.0 +201005435,201005445,801000003,R_000046,,,5.0 +201005435,201005446,801000003,R_000047,,,6.0 +201005435,201005447,801000003,R_000048,,,7.0 +201005435,201005448,801000003,R_000049,,,8.0 +201005435,710000000,801000004,R_000050,,, +201005435,630000000,801000005,R_000051,,, +201005449,201005450,801000001,R_000052,220,g, +201005449,201005451,801000001,R_000053,100,g, +201005449,201005452,801000001,R_000054,20,g, +201005449,201005453,801000001,R_000055,10,g, +201005449,201005454,801000001,R_000056,10,g, +201005449,201005455,801000001,R_000057,30,ml, +201005449,201005456,801000001,R_000058,2,ml, +201005449,201005457,801000001,R_000059,2,g, +201005449,201005458,801000001,R_000060,1,g, +201005449,201005459,801000001,R_000061,1,g, +201005449,201005460,801000001,R_000062,0.5,g, +201005449,201005461,801000003,R_000063,,,1.0 +201005449,201005462,801000003,R_000064,,,2.0 +201005449,201005463,801000003,R_000065,,,3.0 +201005449,201005464,801000003,R_000066,,,4.0 +201005449,201005465,801000003,R_000067,,,5.0 +201005449,201005466,801000003,R_000068,,,6.0 +201005449,201005467,801000003,R_000069,,,7.0 +201005449,201005468,801000003,R_000070,,,8.0 +201005449,201005469,801000003,R_000071,,,9.0 +201005449,201005470,801000003,R_000072,,,10.0 +201005449,710000000,801000004,R_000073,,, +201005449,630000000,801000005,R_000074,,, +201005471,201005472,801000001,R_000075,2,个, +201005471,201005473,801000001,R_000076,50,g, +201005471,201005474,801000001,R_000077,50,ml, +201005471,201005475,801000001,R_000078,2,g, +201005471,201005476,801000001,R_000079,0.5,根, +201005471,201005477,801000001,R_000080,2,ml, +201005471,201005478,801000003,R_000081,,,1.0 +201005471,201005479,801000003,R_000082,,,2.0 +201005471,201005480,801000003,R_000083,,,3.0 +201005471,710000000,801000004,R_000084,,, +201005471,620000000,801000005,R_000085,,, +201005481,201005482,801000001,R_000086,4,个, +201005481,201005483,801000001,R_000087,30,毫升, +201005481,201005484,801000001,R_000088,10,毫升, +201005481,201005485,801000001,R_000089,适量,, +201005481,201005486,801000001,R_000090,适量,, +201005481,201005487,801000003,R_000091,,,1.0 +201005481,201005488,801000003,R_000092,,,2.0 +201005481,201005489,801000003,R_000093,,,3.0 +201005481,201005490,801000003,R_000094,,,4.0 +201005481,201005491,801000003,R_000095,,,5.0 +201005481,710000000,801000004,R_000096,,, +201005481,610000000,801000005,R_000097,,, +201005492,201005493,801000001,R_000098,1,个, +201005492,201005494,801000001,R_000099,20-30,毫升, +201005492,201005495,801000001,R_000100,4-6,克, +201005492,201005496,801000001,R_000101,1,个, +201005492,201005497,801000001,R_000102,3-4,瓣, +201005492,201005498,801000001,R_000103,1-3,克, +201005492,201005499,801000001,R_000104,0.5-2,克, +201005492,201005500,801000003,R_000105,,,1.0 +201005492,201005501,801000003,R_000106,,,2.0 +201005492,201005502,801000003,R_000107,,,3.0 +201005492,201005503,801000003,R_000108,,,4.0 +201005492,201005504,801000003,R_000109,,,5.0 +201005492,201005505,801000003,R_000110,,,6.0 +201005492,201005506,801000003,R_000111,,,7.0 +201005492,201005507,801000003,R_000112,,,8.0 +201005492,201005508,801000003,R_000113,,,9.0 +201005492,201005509,801000003,R_000114,,,10.0 +201005492,201005510,801000003,R_000115,,,11.0 +201005492,710000000,801000004,R_000116,,, +201005492,630000000,801000005,R_000117,,, +201005511,201005512,801000001,R_000118,250,g, +201005511,201005513,801000001,R_000119,10,g, +201005511,201005514,801000001,R_000120,5,g, +201005511,201005515,801000001,R_000121,5,g, +201005511,201005516,801000001,R_000122,5,g, +201005511,201005517,801000001,R_000123,5,g, +201005511,201005518,801000001,R_000124,4,瓣, +201005511,201005519,801000001,R_000125,2,根, +201005511,201005520,801000001,R_000126,500,ml, +201005511,201005521,801000003,R_000127,,,1.0 +201005511,201005522,801000003,R_000128,,,2.0 +201005511,201005523,801000003,R_000129,,,3.0 +201005511,201005524,801000003,R_000130,,,4.0 +201005511,201005525,801000003,R_000131,,,5.0 +201005511,201005526,801000003,R_000132,,,6.0 +201005511,201005527,801000003,R_000133,,,7.0 +201005511,710000000,801000004,R_000134,,, +201005511,620000000,801000005,R_000135,,, +201005528,201005529,801000001,R_000136,200,克, +201005528,201005530,801000001,R_000137,20,克, +201005528,201005531,801000003,R_000138,,,1.0 +201005528,201005532,801000003,R_000139,,,2.0 +201005528,201005533,801000003,R_000140,,,3.0 +201005528,201005534,801000003,R_000141,,,4.0 +201005528,201005535,801000003,R_000142,,,5.0 +201005528,201005536,801000003,R_000143,,,6.0 +201005528,201005537,801000003,R_000144,,,7.0 +201005528,710000000,801000004,R_000145,,, +201005528,620000000,801000005,R_000146,,, +201005538,201005539,801000001,R_000147,300,g, +201005538,201005540,801000001,R_000148,50,ml, +201005538,201005541,801000001,R_000149,2,ml, +201005538,201005542,801000001,R_000150,10,g, +201005538,201005543,801000001,R_000151,10,ml, +201005538,201005544,801000001,R_000152,15,ml, +201005538,201005545,801000001,R_000153,3,g, +201005538,201005546,801000001,R_000154,0.5,根, +201005538,201005547,801000001,R_000155,1,粒, +201005538,201005548,801000001,R_000156,15,ml, +201005538,201005549,801000003,R_000157,,,1.0 +201005538,201005550,801000003,R_000158,,,2.0 +201005538,201005551,801000003,R_000159,,,3.0 +201005538,201005552,801000003,R_000160,,,4.0 +201005538,201005553,801000003,R_000161,,,5.0 +201005538,201005554,801000003,R_000162,,,6.0 +201005538,201005555,801000003,R_000163,,,7.0 +201005538,201005556,801000003,R_000164,,,8.0 +201005538,710000000,801000004,R_000165,,, +201005538,630000000,801000005,R_000166,,, +201005557,201005558,801000001,R_000001,1,瓶, +201005557,201005559,801000001,R_000002,250-300,g, +201005557,201005560,801000001,R_000003,5,ml, +201005557,201005561,801000001,R_000004,7,ml, +201005557,201005562,801000001,R_000005,3,ml, +201005557,201005563,801000001,R_000006,2,g, +201005557,201005564,801000003,R_000007,,,1.0 +201005557,201005565,801000003,R_000008,,,2.0 +201005557,201005566,801000003,R_000009,,,3.0 +201005557,201005567,801000003,R_000010,,,4.0 +201005557,201005568,801000003,R_000011,,,5.0 +201005557,201005569,801000003,R_000012,,,6.0 +201005557,201005570,801000003,R_000013,,,7.0 +201005557,201005571,801000003,R_000014,,,8.0 +201005557,201005572,801000003,R_000015,,,9.0 +201005557,710000000,801000004,R_000016,,, +201005557,620000000,801000005,R_000017,,, +201005573,201005574,801000001,R_000018,50,g, +201005573,201005575,801000001,R_000019,2,个, +201005573,201005576,801000001,R_000020,30,ml, +201005573,201005577,801000001,R_000021,5,ml, +201005573,201005578,801000001,R_000022,15,g, +201005573,201005579,801000001,R_000023,2,g, +201005573,201005580,801000003,R_000024,,,1.0 +201005573,201005581,801000003,R_000025,,,2.0 +201005573,201005582,801000003,R_000026,,,3.0 +201005573,710000000,801000004,R_000027,,, +201005573,620000000,801000005,R_000028,,, +201005583,201005584,801000001,R_000029,350,g, +201005583,201005585,801000001,R_000030,2,个, +201005583,201005586,801000001,R_000031,15,ml, +201005583,201005587,801000001,R_000032,5,g, +201005583,201005588,801000003,R_000033,,,1.0 +201005583,201005589,801000003,R_000034,,,2.0 +201005583,201005590,801000003,R_000035,,,3.0 +201005583,201005591,801000003,R_000036,,,4.0 +201005583,201005592,801000003,R_000037,,,5.0 +201005583,201005593,801000003,R_000038,,,6.0 +201005583,201005594,801000003,R_000039,,,7.0 +201005583,201005595,801000003,R_000040,,,8.0 +201005583,710000000,801000004,R_000041,,, +201005583,620000000,801000005,R_000042,,, +201005596,201005597,801000001,R_000043,250,克, +201005596,201005598,801000001,R_000044,0.5,个, +201005596,201005599,801000001,R_000045,45,毫升, +201005596,201005600,801000001,R_000046,2,克, +201005596,201005601,801000001,R_000047,3,克, +201005596,201005602,801000001,R_000048,8,毫升, +201005596,201005603,801000003,R_000049,,,1.0 +201005596,201005604,801000003,R_000050,,,2.0 +201005596,201005605,801000003,R_000051,,,3.0 +201005596,201005606,801000003,R_000052,,,4.0 +201005596,201005607,801000003,R_000053,,,5.0 +201005596,201005608,801000003,R_000054,,,6.0 +201005596,710000000,801000004,R_000055,,, +201005596,620000000,801000005,R_000056,,, +201005609,201005610,801000001,R_000057,5,个, +201005609,201005611,801000001,R_000058,2.5,瓣, +201005609,201005612,801000001,R_000059,20,毫升, +201005609,201005613,801000001,R_000060,15,克, +201005609,201005614,801000001,R_000061,15,毫升, +201005609,201005615,801000001,R_000062,15,毫升, +201005609,201005616,801000001,R_000063,4,克, +201005609,201005617,801000003,R_000064,,,1.0 +201005609,201005618,801000003,R_000065,,,2.0 +201005609,201005619,801000003,R_000066,,,3.0 +201005609,201005620,801000003,R_000067,,,4.0 +201005609,201005621,801000003,R_000068,,,5.0 +201005609,201005622,801000003,R_000069,,,6.0 +201005609,201005623,801000003,R_000070,,,7.0 +201005609,201005624,801000003,R_000071,,,8.0 +201005609,201005625,801000003,R_000072,,,9.0 +201005609,710000000,801000004,R_000073,,, +201005609,630000000,801000005,R_000074,,, +201005626,201005627,801000001,R_000075,2,朵, +201005626,201005628,801000001,R_000076,30,g, +201005626,201005629,801000001,R_000077,30,g, +201005626,201005630,801000001,R_000078,1,根, +201005626,201005631,801000001,R_000079,0.5,颗, +201005626,201005632,801000001,R_000080,10,ml, +201005626,201005633,801000001,R_000081,5,g, +201005626,201005634,801000001,R_000082,2,ml, +201005626,201005635,801000001,R_000083,10,g, +201005626,201005636,801000001,R_000084,10,ml, +201005626,201005637,801000001,R_000085,3,g, +201005626,201005638,801000001,R_000086,0.5,根, +201005626,201005639,801000001,R_000087,1,粒, +201005626,201005640,801000001,R_000088,5,ml, +201005626,201005641,801000001,R_000089,350,ml, +201005626,201005642,801000001,R_000090,100,g, +201005626,201005643,801000003,R_000091,,,1.0 +201005626,201005644,801000003,R_000092,,,2.0 +201005626,201005645,801000003,R_000093,,,3.0 +201005626,201005646,801000003,R_000094,,,4.0 +201005626,201005647,801000003,R_000095,,,5.0 +201005626,201005648,801000003,R_000096,,,6.0 +201005626,201005649,801000003,R_000097,,,7.0 +201005626,201005650,801000003,R_000098,,,8.0 +201005626,201005651,801000003,R_000099,,,9.0 +201005626,201005652,801000003,R_000100,,,10.0 +201005626,710000000,801000004,R_000101,,, +201005626,630000000,801000005,R_000102,,, +201005653,201005654,801000001,R_000103,1,个, +201005653,201005655,801000001,R_000104,1,个, +201005653,201005656,801000001,R_000105,100,g, +201005653,201005657,801000001,R_000106,5,ml, +201005653,201005658,801000001,R_000107,2,g, +201005653,201005659,801000001,R_000108,5,g, +201005653,201005660,801000001,R_000109,2,g, +201005653,201005661,801000001,R_000110,0.5,根, +201005653,201005662,801000001,R_000111,1,片, +201005653,201005663,801000001,R_000112,350,ml, +201005653,201005664,801000003,R_000113,,,1.0 +201005653,201005665,801000003,R_000114,,,2.0 +201005653,201005666,801000003,R_000115,,,3.0 +201005653,201005667,801000003,R_000116,,,4.0 +201005653,201005668,801000003,R_000117,,,5.0 +201005653,710000000,801000004,R_000118,,, +201005653,620000000,801000005,R_000119,,, +201005669,201005670,801000001,R_000120,500,g, +201005669,201005671,801000001,R_000121,3,个, +201005669,201005672,801000001,R_000122,100,g, +201005669,201005673,801000001,R_000123,10-20,ml, +201005669,201005674,801000001,R_000124,6,g, +201005669,201005675,801000003,R_000125,,,1.0 +201005669,201005676,801000003,R_000126,,,2.0 +201005669,201005677,801000003,R_000127,,,3.0 +201005669,201005678,801000003,R_000128,,,4.0 +201005669,201005679,801000003,R_000129,,,5.0 +201005669,201005680,801000003,R_000130,,,6.0 +201005669,201005681,801000003,R_000131,,,7.0 +201005669,201005682,801000003,R_000132,,,8.0 +201005669,201005683,801000003,R_000133,,,9.0 +201005669,710000000,801000004,R_000134,,, +201005669,620000000,801000005,R_000135,,, +201005684,201005685,801000001,R_000136,300,g, +201005684,201005686,801000001,R_000137,6,颗, +201005684,201005687,801000001,R_000138,2,g, +201005684,201005688,801000003,R_000139,,,1.0 +201005684,201005689,801000003,R_000140,,,2.0 +201005684,201005690,801000003,R_000141,,,3.0 +201005684,710000000,801000004,R_000142,,, +201005684,620000000,801000005,R_000143,,, +201005691,201005692,801000001,R_000144,2,个, +201005691,201005693,801000001,R_000145,200,ml, +201005691,201005694,801000001,R_000146,10,个, +201005691,201005695,801000001,R_000147,5,g, +201005691,201005696,801000001,R_000148,3,g, +201005691,201005697,801000001,R_000149,适量,, +201005691,201005698,801000001,R_000150,1,ml, +201005691,201005699,801000003,R_000151,,,1.0 +201005691,201005700,801000003,R_000152,,,2.0 +201005691,201005701,801000003,R_000153,,,3.0 +201005691,201005702,801000003,R_000154,,,4.0 +201005691,201005703,801000003,R_000155,,,5.0 +201005691,201005704,801000003,R_000156,,,6.0 +201005691,201005705,801000003,R_000157,,,7.0 +201005691,201005706,801000003,R_000158,,,8.0 +201005691,201005707,801000003,R_000159,,,9.0 +201005691,201005708,801000003,R_000160,,,10.0 +201005691,710000000,801000004,R_000161,,, +201005691,620000000,801000005,R_000162,,, +201005709,201005710,801000001,R_000001,1,个, +201005709,201005711,801000001,R_000002,1,g, +201005709,201005712,801000001,R_000003,5,ml, +201005709,201005713,801000001,R_000004,6,ml, +201005709,201005714,801000001,R_000005,1.0-1.5倍鸡蛋体积,ml, +201005709,201005715,801000003,R_000006,,,1.0 +201005709,201005716,801000003,R_000007,,,2.0 +201005709,201005717,801000003,R_000008,,,3.0 +201005709,201005718,801000003,R_000009,,,4.0 +201005709,201005719,801000003,R_000010,,,5.0 +201005709,201005720,801000003,R_000011,,,6.0 +201005709,201005721,801000003,R_000012,,,7.0 +201005709,201005722,801000003,R_000013,,,8.0 +201005709,201005723,801000003,R_000014,,,9.0 +201005709,201005724,801000003,R_000015,,,10.0 +201005709,710000000,801000004,R_000016,,, +201005709,630000000,801000005,R_000017,,, +201005725,201005726,801000001,R_000018,2,个, +201005725,201005727,801000001,R_000019,3,g, +201005725,201005728,801000001,R_000020,2-4,ml, +201005725,201005729,801000001,R_000021,8,ml, +201005725,201005730,801000001,R_000022,2,ml, +201005725,201005731,801000001,R_000023,适量,, +201005725,201005732,801000001,R_000024,1-1.5,倍鸡蛋体积, +201005725,201005733,801000003,R_000025,,,1.0 +201005725,201005734,801000003,R_000026,,,2.0 +201005725,201005735,801000003,R_000027,,,3.0 +201005725,201005736,801000003,R_000028,,,4.0 +201005725,201005737,801000003,R_000029,,,5.0 +201005725,201005738,801000003,R_000030,,,6.0 +201005725,201005739,801000003,R_000031,,,7.0 +201005725,201005740,801000003,R_000032,,,8.0 +201005725,201005741,801000003,R_000033,,,9.0 +201005725,710000000,801000004,R_000034,,, +201005725,620000000,801000005,R_000035,,, diff --git a/data/C9/docker-compose.yml b/data/C9/docker-compose.yml new file mode 100644 index 0000000..9f9aebf --- /dev/null +++ b/data/C9/docker-compose.yml @@ -0,0 +1,61 @@ +version: '3.8' + +services: + neo4j: + image: neo4j:5.18 + container_name: neo4j-db + ports: + - 7474:7474 # HTTP Web UI + - 7687:7687 # Bolt 协议端口 + environment: + NEO4J_AUTH: neo4j/all-in-rag + NEO4J_dbms_connector_bolt_advertised__address: localhost:7687 + # 允许从文件URL导入CSV + NEO4J_dbms_security_allow__csv__import__from__file__urls: "true" + # 设置导入目录 + NEO4J_dbms_directories_import: "/import" + # 启用 APOC 插件 + NEO4J_PLUGINS: '["apoc"]' + # APOC 配置 + NEO4J_apoc_export_file_enabled: "true" + NEO4J_apoc_import_file_enabled: "true" + NEO4J_apoc_import_file_use__neo4j__config: "true" + volumes: + - neo4j_data:/data + - neo4j_logs:/logs + - neo4j_plugins:/plugins + # 将cypher文件夹映射到容器的import目录(CSV文件在这里) + - ./cypher:/import + # 映射脚本目录 + - ./cypher:/scripts + restart: unless-stopped + # 添加健康检查 + healthcheck: + test: ["CMD", "cypher-shell", "-u", "neo4j", "-p", "all-in-rag", "RETURN 1"] + interval: 30s + timeout: 10s + retries: 5 + + # 添加脚本执行服务 + neo4j-init: + image: neo4j:5.18 + container_name: neo4j-init + depends_on: + neo4j: + condition: service_healthy + volumes: + - ./cypher:/scripts + command: > + sh -c " + echo 'Waiting for Neo4j to be ready...' && + sleep 10 && + echo 'Executing import script...' && + cypher-shell -a bolt://neo4j:7687 -u neo4j -p all-in-rag -f /scripts/neo4j_import.cypher && + echo 'Import completed!' + " + restart: "no" + +volumes: + neo4j_data: + neo4j_logs: + neo4j_plugins: diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/docs/.nojekyll @@ -0,0 +1 @@ + diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..1311943 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,234 @@ +# All-in-RAG | 大模型应用开发实战一:RAG技术全栈指南 + +
+ All-in-RAG Logo +
+ +
+

🔍 检索增强生成 (RAG) 技术全栈指南

+

从理论到实践,从基础到进阶,构建你的RAG技术体系

+
+ +
+ GitHub stars + GitHub forks + Python + + zread + +
+ + + +
+
+ + + + + + + +
🎯 系统化学习
完整的RAG技术体系
🛠️ 动手实践
丰富的项目案例
🚀 生产就绪
工程化最佳实践
📊 多模态支持
文本+图像检索
+
+ +## 项目简介(中文 | [English](en/)) + +本项目是一个面向大模型应用开发者的RAG(检索增强生成)技术全栈教程,旨在通过体系化的学习路径和动手实践项目,帮助开发者掌握基于大语言模型的RAG应用开发技能,构建生产级的智能问答和知识检索系统。 + +**主要内容包括:** + +1. **RAG技术基础**:深入浅出地介绍RAG的核心概念、技术原理和应用场景 +2. **数据处理全流程**:从数据加载、清洗到文本分块的完整数据准备流程 +3. **索引构建与优化**:向量嵌入、多模态嵌入、向量数据库构建及索引优化技术 +4. **检索技术进阶**:混合检索、查询构建、Text2SQL等高级检索技术 +5. **生成集成与评估**:格式化生成、系统评估与优化方法 +6. **项目实战**:从基础到进阶的完整RAG应用开发实践 + +## 项目意义 + +随着大语言模型的快速发展,RAG技术已成为构建智能问答系统、知识检索应用的核心技术。然而,现有的RAG教程往往零散且缺乏系统性,初学者难以形成完整的技术体系认知。 + +本项目从实践出发,结合最新的RAG技术发展趋势,构建了一套完整的RAG学习体系,帮助开发者: +- 系统掌握RAG技术的理论基础和实践技能 +- 理解RAG系统的完整架构和各组件的作用 +- 具备独立开发RAG应用的能力 +- 掌握RAG系统的评估和优化方法 + +## 项目受众 + +**本项目适合以下人群学习:** +- 具备Python编程基础,对RAG技术感兴趣的开发者 +- 希望系统学习RAG技术的AI工程师 +- 想要构建智能问答系统的产品开发者 +- 对检索增强生成技术有学习需求的研究人员 + +**前置要求:** +- 掌握Python基础语法和常用库的使用 +- 能够简单使用docker +- 了解基本的LLM概念(推荐但非必需) +- 具备基础的Linux命令行操作能力 + +## 项目亮点 + +1. **体系化学习路径**:从基础概念到高级应用,构建完整的RAG技术学习体系 +2. **理论与实践并重**:每个章节都包含理论讲解和代码实践,确保学以致用 +3. **多模态支持**:不仅涵盖文本RAG,还包括多模态嵌入和检索技术 +4. **工程化导向**:注重实际应用中的工程化问题,包括性能优化、系统评估等 +5. **丰富的实战项目**:提供从基础到进阶的多个实战项目,帮助巩固学习成果 + +## 内容大纲 + +### 第一部分:RAG基础入门 + +**第一章 解锁RAG** [📖 查看章节](chapter1) +1. [x] [RAG简介](chapter1/01_RAG_intro.md) - RAG技术概述与应用场景 +2. [x] [准备工作](chapter1/02_preparation.md) - 环境配置与工具准备 +3. [x] [四步构建RAG](chapter1/03_get_start_rag.md) - 快速上手RAG开发 +4. [x] [附:环境部署](chapter1/virtualenv.md) - Python虚拟环境部署方案补充 (贡献者: [@anarchysaiko](https://github.com/anarchysaiko)) + +**第二章 数据准备** [📖 查看章节](chapter2) +1. [x] [数据加载](chapter2/04_data_load.md) - 多格式文档处理与加载 +2. [x] [文本分块](chapter2/05_text_chunking.md) - 文本切分策略与优化 + +### 第二部分:索引构建与优化 + +**第三章 索引构建** [📖 查看章节](chapter3) +1. [x] [向量嵌入](chapter3/06_vector_embedding.md) - 文本向量化技术详解 +2. [x] [多模态嵌入](chapter3/07_multimodal_embedding.md) - 图文多模态向量化 +3. [x] [向量数据库](chapter3/08_vector_db.md) - 向量存储与检索系统 +4. [x] [Milvus实践](chapter3/09_milvus.md) - Milvus多模态检索实战 +5. [x] [索引优化](chapter3/10_index_optimization.md) - 索引性能调优技巧 + +### 第三部分:检索技术进阶 + +**第四章 检索优化** [📖 查看章节](chapter4) +1. [x] [混合检索](chapter4/11_hybrid_search.md) - 稠密+稀疏检索融合 +2. [x] [查询构建](chapter4/12_query_construction.md) - 智能查询理解与构建 +3. [x] [Text2SQL](chapter4/13_text2sql.md) - 自然语言转SQL查询 +4. [x] [查询重构与分发](chapter4/14_query_rewriting.md) - 查询优化策略 +5. [x] [检索进阶技术](chapter4/15_advanced_retrieval_techniques.md) - 高级检索算法 + +### 第四部分:生成与评估 + +**第五章 生成集成** [📖 查看章节](chapter5) +1. [x] [格式化生成](chapter5/16_formatted_generation.md) - 结构化输出与格式控制 + +**第六章 RAG系统评估** [📖 查看章节](chapter6) +1. [x] [评估介绍](chapter6/18_system_evaluation.md) - RAG系统评估方法论 +2. [x] [评估工具](chapter6/19_common_tools.md) - 常用评估工具与指标 + +### 第五部分:高级应用与实战 + +**第七章 高级RAG架构(拓展部分)** [📖 查看章节](chapter7) + +1. [x] [基于知识图谱的RAG](chapter7/20_kg_rag.md) + +**第八章 项目实战一** [📖 查看章节](chapter8) +1. [x] [环境配置与项目架构](chapter8/01_env_architecture.md) +2. [x] [数据准备模块实现](chapter8/02_data_preparation.md) +3. [x] [索引构建与检索优化](chapter8/03_index_retrieval.md) +4. [x] [生成集成与系统整合](chapter8/04_generation_sys.md) + +**第九章 项目实战一优化(选修篇)** [📖 查看章节](chapter9) + +[🍽️ 项目展示](https://github.com/FutureUnreal/What-to-eat-today) +1. [x] [图RAG架构设计](chapter9/01_graph_rag_architecture.md) +2. [x] [图数据建模与准备](chapter9/02_graph_data_modeling.md) +3. [x] [Milvus索引构建](chapter9/03_index_construction.md) +4. [x] [智能查询路由与检索策略](chapter9/04_intelligent_query_routing.md) + +**第十章 项目实战二(选修篇)** [📖 查看章节](chapter10) *规划中* + +### 第六部分:知识拓展 + +**第十一章 Neo4J 简单应用** [📖 查看章节](chapter11) +1. [x] [知识图谱与 Neo4j 安装](chapter11/01_knowledge_graph.md) +2. [x] [Neo4j 基本使用](chapter11/02_neo4j.md) + +## 目录结构说明 + +``` +all-in-rag/ +├── docs/ # 教程文档 +├── code/ # 代码示例 +├── data/ # 示例数据 +├── models/ # 预训练模型 +└── README.md # 项目说明 +``` + +## 实战项目展示 + +### 第八章 项目一: + +![项目一](./project01.png) + +### 第九章 项目一(Graph RAG优化): + +![项目一(Graph RAG优化)](./project01_graph.png) + +### 第十章 项目二: + +## 致谢 + +**核心贡献者** +- [dalvqw-项目负责人](https://github.com/FutureUnreal)(项目发起人与主要贡献者) + +**额外章节贡献者** +- [孙超-内容创作者](https://github.com/anarchysaiko)(Datawhale成员-上海工程技术大学) + +### 特别感谢 +- 感谢 [@Sm1les](https://github.com/Sm1les) 对本项目的帮助与支持 +- 感谢所有为本项目做出贡献的开发者们 +- 感谢开源社区提供的优秀工具和框架支持 +- 特别感谢以下为教程做出贡献的开发者! + +[![Contributors](https://contrib.rocks/image?repo=datawhalechina/all-in-rag)](https://github.com/datawhalechina/all-in-rag/graphs/contributors) + +*Made with [contrib.rocks](https://contrib.rocks).* + +## 参与贡献 + +我们欢迎所有形式的贡献,包括但不限于: + +- 🚨 **Bug报告**:发现问题请提交 [Issue](https://github.com/datawhalechina/all-in-rag/issues) +- 💭 **教程建议**:有好的想法欢迎在 [Discussions](https://github.com/datawhalechina/all-in-rag/discussions) 中讨论 +- 📚 **文档改进**:帮助完善文档内容和示例代码(当前仅支持 Extra-chapter 优质内容pr) + +## Star History + +[![all-in-rag stats](https://datawhalechina.github.io/members-visualization/badges/all-in-rag.png)](https://datawhalechina.github.io/members-visualization/repo-badge?repo=all-in-rag) + +
+

如果这个项目对你有帮助,请给我们一个 ⭐️

+

让更多人发现这个项目(护食?发来!)

+
+ +![star](./emoji.png) + +## 关于 Datawhale + +
+ Datawhale +

扫描二维码关注 Datawhale 公众号,获取更多优质开源内容

+
+ +--- + +## 许可证 + +知识共享许可协议 + +本作品采用 [知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议](http://creativecommons.org/licenses/by-nc-sa/4.0/) 进行许可。 + +--- diff --git a/docs/_sidebar.md b/docs/_sidebar.md new file mode 100644 index 0000000..50be035 --- /dev/null +++ b/docs/_sidebar.md @@ -0,0 +1,40 @@ +- 目录 + - 第一章 解锁RAG + - [第一节 RAG简介](chapter1/01_RAG_intro.md) + - [第二节 准备工作](chapter1/02_preparation.md) + - [第三节 四步构建RAG](chapter1/03_get_start_rag.md) + - [附:Python虚拟环境部署方案补充](chapter1/virtualenv.md) + - 第二章 数据准备 + - [第一节 数据加载](chapter2/04_data_load.md) + - [第二节 文本分块](chapter2/05_text_chunking.md) + - 第三章 索引构建 + - [第一节 向量嵌入](chapter3/06_vector_embedding.md) + - [第二节 多模态嵌入](chapter3/07_multimodal_embedding.md) + - [第三节 向量数据库](chapter3/08_vector_db.md) + - [第四节 Milvus实践](chapter3/09_milvus.md) + - [第五节 索引优化](chapter3/10_index_optimization.md) + - 第四章 检索优化 + - [第一节 混合检索](chapter4/11_hybrid_search.md) + - [第二节 查询构建](chapter4/12_query_construction.md) + - [第三节 Text2SQL](chapter4/13_text2sql.md) + - [第四节 查询重构与分发](chapter4/14_query_rewriting.md) + - [第五节 检索进阶技术](chapter4/15_advanced_retrieval_techniques.md) + - 第五章 生成集成 + - [第一节 格式化生成](chapter5/16_formatted_generation.md) + - 第六章 RAG系统评估 + - [第一节 评估介绍](chapter6/18_system_evaluation.md) + - [第二节 评估工具](chapter6/19_common_tools.md) + - 第七章 高级RAG架构(拓展选修篇) + - [第一节 基于知识图谱的RAG](chapter7/20_kg_rag.md) + - 第八章 项目实战一(基础篇) + - [环境配置与项目架构](chapter8/01_env_architecture.md) + - [数据准备模块实现](chapter8/02_data_preparation.md) + - [索引构建与检索优化](chapter8/03_index_retrieval.md) + - [生成集成与系统整合](chapter8/04_generation_sys.md) + - 第九章 项目实战一优化(选修篇) + - [图RAG架构设计](chapter9/01_graph_rag_architecture.md) + - [图数据建模与准备](chapter9/02_graph_data_modeling.md) + - [Milvus索引构建](chapter9/03_index_construction.md) + - [智能查询路由与检索策略](chapter9/04_intelligent_query_routing.md) + - 第十章 项目实战二(选修篇) + - [规划中...](chapter10/) \ No newline at end of file diff --git a/docs/chapter1/01_RAG_intro.md b/docs/chapter1/01_RAG_intro.md new file mode 100644 index 0000000..d607125 --- /dev/null +++ b/docs/chapter1/01_RAG_intro.md @@ -0,0 +1,232 @@ +# 第一节 RAG 简介 + +## 一、什么是 RAG? + +### 1.1 核心定义 + +从本质上讲,RAG(Retrieval-Augmented Generation)是一种旨在解决大语言模型(LLM)“知其然不知其所以然”问题的技术范式。它的核心是将模型内部学到的“**参数化知识**”(模型权重中固化的、模糊的“记忆”),与来自外部知识库的“**非参数化知识**”(精准、可随时更新的外部数据)相结合。其运作逻辑就是在 LLM 生成文本前,先通过检索机制从外部知识库中动态获取相关信息,并将这些“参考资料”融入生成过程,从而提升输出的准确性和时效性 [^1] [^2] [^3]。 + +> 💡 **一句话总结**:RAG 就是让 LLM 学会了“开卷考试”,它既能利用自己学到的知识,也能随时查阅外部资料。 + +### 1.2 技术原理 + +那么,RAG 系统是如何实现“参数化知识”与“非参数化知识”的结合呢?如图 1-1 所示,其架构主要通过两个阶段来完成这一过程: + +(1)**检索阶段:寻找“非参数化知识”** +- **知识向量化**:**嵌入模型(Embedding Model)** 充当了“连接器”的角色。它将外部知识库编码为向量索引(Index),存入**向量数据库**。 +- **语义召回**:当用户发起查询时,检索模块利用同样的嵌入模型将问题向量化,并通过**相似度搜索(Similarity Search)**,从海量数据中精准锁定与问题最相关的文档片段。 + +(2)**生成阶段:融合两种知识** +- **上下文整合**:**生成模块**接收检索阶段送来的相关文档片段以及用户的原始问题。 +- **指令引导生成**:该模块会遵循预设的 **Prompt** 指令,将上下文与问题有效整合,并引导 LLM(如 DeepSeek)进行可控的、有理有据的文本生成。 + +
+ RAG 双阶段架构示意图 +

图 1-1 RAG 双阶段架构示意图

+
+ +### 1.3 技术演进分类 + +RAG 的技术架构经历了从简单到复杂的演进,如图 1-2 大致可分为三个阶段 [^4]。 + +
+ RAG 技术演进分类 +

图 1-2 RAG 技术演进分类

+
+ +这三个阶段的具体对比如表 1-1 所示。 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
初级 RAG(Naive RAG)高级 RAG(Advanced RAG)模块化 RAG(Modular RAG)
流程离线: 索引
在线: 检索 → 生成
离线: 索引
在线: ...→ 检索前 → ... → 检索后 → ...
积木式可编排流程
特点基础线性流程增加检索前后的优化步骤模块化、可组合、可动态调整
关键技术基础向量检索查询重写(Query Rewrite)
结果重排(Rerank)
动态路由(Routing)
查询转换(Query Transformation)
多路融合(Fusion)
局限性效果不稳定,难以优化流程相对固定,优化点有限系统复杂性高
+

表 1-1 RAG 技术演进分类对比

+
+ +> “离线”指提前完成的数据预处理工作(如索引构建);“在线”指用户发起请求后的实时处理流程。 + +## 二、为什么要使用 RAG? + +### 2.1 技术选型:RAG vs. 微调 + +在选择具体的技术路径时,一个重要的考量是成本与效益的平衡。通常,我们应优先选择对模型改动最小、成本最低的方案,所以技术选型路径往往遵循的顺序是**提示词工程(Prompt Engineering) -> 检索增强生成 -> 微调(Fine-tuning)**。 + +我们可以从两个维度来理解这些技术的区别。如图 1-3 所示,**横轴代表“LLM 优化”**,即对模型本身进行多大程度的修改。从左到右,优化的程度越来越深,其中提示工程和 RAG 完全不改变模型权重,而微调则直接修改模型参数。**纵轴代表“上下文优化”**,是对输入给模型的信息进行多大程度的增强。从下到上,增强的程度越来越高,其中提示工程只是优化提问方式,而 RAG 则通过引入外部知识库,极大地丰富了上下文信息。 + +
+ 技术选型路径 +

图 1-3 选型路径图

+
+ +基于此,我们的选择路径就清晰了: +- **先尝试提示工程**:通过精心设计提示词来引导模型,适用于任务简单、模型已有相关知识的场景。 +- **再选择 RAG**:如果模型缺乏特定或实时知识而无法回答,则使用 RAG,通过外挂知识库为其提供上下文信息。 +- **最后考虑微调**:当目标是改变模型“如何做”(行为/风格/格式)而不是“知道什么”(知识)时,微调是最终且最合适的选择。例如,让模型学会严格遵循某种独特的输出格式、模仿特定人物的对话风格,或者将极其复杂的指令“蒸馏”进模型权重中。 + +RAG 的出现填补了通用模型与专业领域之间的鸿沟,它在解决如表 1-2 所示 LLM 局限时尤其有效: + +
+ + + + + + + + + + + + + + + + + + + + + +
问题RAG的解决方案
静态知识局限实时检索外部知识库,支持动态更新
幻觉(Hallucination)基于检索内容生成,错误率降低
领域专业性不足引入领域特定知识库(如医疗/法律)
数据隐私风险本地化部署知识库,避免敏感数据泄露
+

表 1-2 RAG 对 LLM 局限的解决方案

+
+ +### 2.2 关键优势 + +(1)**准确性与可信度的双重提升** + +RAG 最核心的价值在于突破了模型预训练知识的限制。它不仅能**补充专业领域的知识盲区**,还能通过提供具体的参考材料,有效**抑制“一本正经胡说八道”的幻觉现象**。论文研究还表明,RAG 生成的内容在**具体性**和**多样性**上也显著优于纯 LLM。更重要的是,RAG 具备**可溯源性**——每一条回答都能找到对应的原始文档出处,这种“有据可查”的特性极大提高了内容在法律、医疗等严肃场景下的可信度。 + +(2)**时效性保障** + +在知识更新方面,RAG 解决了 LLM 固有的**知识时滞问题**(即模型不知道训练截止日期之后发生的事)。RAG 允许知识库独立于模型进行**动态更新**——新政策或新数据一旦入库,立刻就能被检索到。这种能力在论文中被称为**“索引热拔插”(Index Hot-swapping)**——就像给机器人换一张存储卡一样,瞬间切换其世界知识库,而无需重新训练模型,实现了知识的实时在线。 + +(3)**显著的综合成本效益** + +从经济角度看,RAG 是一种高性价比的方案。首先,它**避免了高频微调**带来的巨额算力成本;其次,由于有了外部知识的强力辅助,我们在处理特定领域问题时,往往可以使用**参数量更小的基础模型**来达到类似的效果,从而直接降低了推理成本。这种架构也减少了试图将海量知识强行“塞入”模型权重中所需的计算资源消耗。 + +(4)**灵活的模块化可扩展性** + +RAG 的架构具备极强的包容性,支持**多源集成**,无论是 PDF、Word 还是网页数据,都能统一构建进知识库中。同时,其**模块化设计**实现了检索与生成的解耦,这意味着我们可以独立优化检索组件(比如更换更好的 Embedding 模型),而不会影响到生成组件的稳定性,便于系统的长期迭代。 + +### 2.3 适用场景风险分级 + +表 1-3 展示了 RAG 技术在不同风险等级场景中的适用性。 + +
+ + + + + + + + + + + + + + + + + + + + + +
风险等级案例RAG适用性
低风险翻译/语法检查高可靠性
中风险合同起草/法律咨询需结合人工审核
高风险证据分析/签证决策需严格质量控制机制
+

表 1-3 RAG 适用场景风险分级

+
+ +## 三、如何上手 RAG? + +### 3.1 基础工具链选择 + +构建 RAG 系统通常涉及几个关键环节的选型。在**开发模式**上,我们可以利用 **LangChain** 或 **LlamaIndex** 等成熟框架快速集成,**也可以选择不依赖框架的原生开发**,以获得对系统流程更精细的控制力(在 AI 编程辅助下这并非难事)。而在**记忆载体**(向量数据库)方面,既有 **Milvus**、**Pinecone** 等适合大规模数据的方案,也有 **FAISS**、**Chroma** 等轻量级或本地化的选择,需根据具体业务规模灵活决定。后期为了量化效果,还可以引入 **RAGAS** 或 **TruLens** 等自动化**评估工具**。 + +### 3.2 四步构建最小可行系统(MVP) + +(1)**数据准备与清洗**:这是系统的地基。我们需要将 PDF、Word 等多源异构数据标准化,并采用合理的**分块策略**(如按语义段落切分而非固定字符数),避免信息在切割中支离破碎。 + +(2)**索引构建**:将切分好的文本通过**嵌入模型**转化为向量,并存入数据库。可以在此阶段关联**元数据**(如来源、页码),这对后续的精确引用很有帮助。 + +(3)**检索策略优化**:不要依赖单一的向量搜索。可以采用**混合检索**(向量+关键词)等方式来提升召回率,并引入**重排序**模型对检索结果进行二次精选,确保 LLM 看到的都是精华。 + +(4)**生成与提示工程**:最后,设计一套清晰的 **Prompt 模板**,引导 LLM 基于检索到的上下文回答用户问题,并明确要求模型“不知道就说不知道”,防止幻觉。 + +### 3.3 新手友好方案 + +如果希望快速验证想法而非深耕代码,可以尝试 **FastGPT** 或 **Dify** 这样的可视化知识库平台,它们封装了复杂的 RAG 流程,仅需上传文档即可使用。对于开发者,利用 **LangChain4j Easy RAG** 或 GitHub 上的 **TinyRAG** [^6]等开源模板,也是高效的起手方式。 + +### 3.4 进阶与挑战 + +当基础的 RAG 系统搭建完成后,下一步的进阶之路便聚焦于如何评估、诊断并突破其固有的瓶颈。 + +(1)**评估维度与挑战** + +一套 RAG 系统的好坏,并不能仅凭感觉。业界通常会从几个维度进行量化评估,首先是**检索相关性**(找到的内容是否包含答案),其次是**生成质量**,这又可以细分为**语义准确性**(回答的意思是否正确)和**词汇匹配度**(专业术语是否使用得当)。 + +这些评估维度也直接对应了 RAG 当前面临的主要挑战。比如,**检索依赖性**问题——如果检索系统召回了错误信息,再强的 LLM 也会“一本正经地胡说八道”。此外,对于需要跨多个文档进行综合分析的**多跳推理**问题,常见的 RAG 架构也普遍感到吃力。 + +(2)**优化方向与架构演进** + +针对上述挑战,社区探索出了多种优化路径。在**性能层面**,可以通过**索引分层**(对高频数据启用缓存)和**多模态扩展**(支持图像/表格检索)来提升效率和能力边界。而在**架构层面**,简单的线性流程正在被更复杂的**设计模式**所取代。例如,系统可以通过**分支模式**并行处理多路检索,或通过**循环模式**进行自我修正,这些灵活的架构是通往更智能 RAG 的必由之路。 + +## 四、RAG 已死? + +随着大模型长上下文窗口能力的提升,社区中开始出现“RAG 已死”的声音。这一论调主要来自两个方面,一是认为长上下文已经能暴力“消化”海量文本,不再需要复杂的检索系统;二是批评 RAG 这个术语本身就过于宽泛,模糊了太多技术细节,反而阻碍了理解与优化。 + +这些观点忽略了一个技术概念在演进过程中的普遍规律。正如我们可以轻易地为现代复杂的 RAG 系统起一个更精确、更唬人的名字,比如 **“大模型知识管理专家系统”(Large Language Model Knowledge Management Expert System,LKE)**。因为它早已超出了最初“检索-增强-生成”的简单范畴。但这种“换名游戏”,恰恰说明了“RAG 已死”论的表面化——这无异于在用一个新瓶子去装 RAG 这个不断陈化的老酒。 + +> 笔者在此并非要创造一个新词,不过为什么要起 LKE 这个名字?它代表了三个核心要素: +> - **L(Large Language Model)**:强调系统的驱动力是大语言模型。 +> - **K(Knowledge Management)**:寓意着系统就像一个知识管理员,精准地为我们找到(**检索**)所需要的知识,辅助我们后续利用大模型进行更高阶应用。 +> - **E(Expert)**:说明系统能像专家一样,通过路由、分析、融合、修正等一系列步骤,最终给出答案(**生成**)、解决问题。 + +可以类比 **Transformer**。今天无论是以 GPT 为代表的 Decoder-only 还是以 BERT 为代表的 Encoder-only,我们都习惯称之为“基于 Transformer 架构”,尽管它们与最初论文中的完整形态差异巨大。但是 Transformer 这个标签抓住了一次技术范式的核心飞跃,并成为了一个技术时代的象征。同理,**RAG 的核心在于“将 LLM 的内在参数化知识与外部非参数化知识相结合”**。只要这个思想或需求不变,无论我们为其增加多少模块——查询转换、多路召回或者自我修正等等,它本质上依然是在这个框架下的演进。 + +所以,“RAG 已死”是一个伪命题。相反,**RAG 作为一个概念活得很好**,它正在像 Transformer 一样,成为一个不断吸收新技术、不断进化的基础架构范式。它的生命力,正在于它的“面目全非”和“包罗万象”。而**本教程的目标,就是绘制出这张描绘 RAG 全貌的清晰地图,当我们可以解构它的每一个模块、理解它的每一种可能性时,RAG 也好,LKE 也罢,这些都无关紧要**。我们要做的就是通过 RAG 这道经典例题来学习和拓展(将 LLM 的内在参数化知识与外部非参数化知识相结合)这类题型的解题思路。 + +> RAG 技术仍在快速发展中,可以持续关注学术和工业界的最新进展! + +## 参考文献 + +[^1]: [Genesis, J. (2025). *Retrieval-Augmented Text Generation: Methods, Challenges, and Applications*](https://www.researchgate.net/publication/391141346_Retrieval-Augmented_Generation_Methods_Applications_and_Challenges). + +[^2]: [Gao et al. (2023). *Retrieval-Augmented Generation for Large Language Models: A Survey*](https://arxiv.org/abs/2312.10997). + +[^3]: [Lewis et al. (2020). *Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks*](https://arxiv.org/abs/2005.11401). + +[^4]: [Gao et al. (2024). *Modular RAG: Transforming RAG Systems into LEGO-like Reconfigurable Frameworks*](https://arxiv.org/abs/2407.21059). + +[^6]: [*TinyRAG: GitHub项目*](https://github.com/KMnO4-zx/TinyRAG). \ No newline at end of file diff --git a/docs/chapter1/02_preparation.md b/docs/chapter1/02_preparation.md new file mode 100644 index 0000000..15255cf --- /dev/null +++ b/docs/chapter1/02_preparation.md @@ -0,0 +1,487 @@ +# 第二节 准备工作 + +> 本节环境配置方面主推两种基于浏览器的集成开发环境。不管是手机、平板还是电脑,随时都可以上号运行代码。虽然手机平板可能体验不佳,但胜在能用。 + +## 一、大模型 API 配置 + +### 1.1 AIHubmix API 申请 + +AIHubmix 是一个美国平台,公司注册在美国的特拉华州,一站式聚合了全球主流的 AI 模型,最新的模型通常能在发布当天最晚不超过 1 周就会支持。完全对接相关模型的云厂商(OpenAI 对接的是 Azure 云,Gemini 对接的 Google 官方,Claude 对接的是 AWS,其他开源等模型是对接到各大知名云厂商或者推理公司)。AIHubmix 的服务器是在美国谷歌云上采用集群部署,同时因为完全对接云厂商,所以稳定性非常好,有多端点路由机制,可以达到比直连官方更稳定的效果。 + +> AIHubmix 提供的免费模型足够我们完成项目的学习。 + +1. **访问 AIHubmix 平台** + + 打开浏览器,访问 [AIHubmix](https://aihubmix.com/?aff=anNj)。 + + ![AIHubmix](./images/1.png) + +2. **登录或注册账号** + + 如果已有账号,可以直接登录。如果没有,请点击页面右上角的注册按钮,使用邮箱或手机号完成注册。 + +3. **模型筛选** + + 注册完成后,来到[模型页面](https://aihubmix.com/models)。标签选择`免费`,可以看到官方提供了一定数量的免费模型。而且 AIHubmix 还提供了很多嵌入和重排序的国内外模型选择,这些在 RAG 领域都很常用。 + + ![模型页面](./images/2.png) + +4. **管理 API 密钥** + + 接着进入[密钥管理页面](https://console.aihubmix.com/token),如下图所示,默认已经有了一个密钥可以直接复制使用。当然也可以点击 `创建 Key` 填写名称后重新创建一个。 + + ![密钥管理](./images/3.png) + +### 1.2 DeepSeek API 申请 + +要使用 Deepseek 提供的大语言模型服务,你首先需要一个 API Key。下面是申请步骤: + +1. **访问 Deepseek 开放平台** + + 打开浏览器,访问 [Deepseek 开放平台](https://platform.deepseek.com/)。 + + ![Deepseek 平台首页](./images/1_2_1.webp) + +2. **登录或注册账号** + + 如果你已有账号,请直接登录。如果没有,请点击页面上的注册按钮,使用邮箱或手机号完成注册。 + +3. **创建新的 API 密钥** + + 登录成功后,在页面左侧的导航栏中找到并点击 `API Keys`。在 API 管理页面,点击 `创建 API key` 按钮。输入一个跟其他api key不重复的名称后点击创建。 + + ![创建新密钥按钮](./images/1_2_2.webp) + +4. **保存 API Key** + + 系统会为你生成一个新的 API 密钥。请**立即复制**并将其保存在一个安全的地方。 + + > 注意:出于安全原因,这个密钥只会完整显示一次,关闭弹窗后就没法再看到了。 + + ![复制并保存密钥](./images/1_2_3.webp) + +## 二、GitHub Codespaces 环境配置(推荐) + +> 首先确定是否具有可以流畅访问 GitHub 的网络环境,若无法流畅访问请使用下面的Cloud Studio + +GitHub Codespaces 是 GitHub 提供的一项服务,允许开发者在云端创建、编辑和运行代码。它提供了一个预配置的开发环境,包括代码编辑器、终端、调试工具等,可以直接在浏览器中使用。 + +### 2.1 创建Codespaces + +1. **访问项目地址** + + 打开浏览器,访问 [all-in-rag](https://github.com/datawhalechina/all-in-rag) + +2. **创建新分支** + 在项目页面的右上角,点击 `Fork` 按钮,创建一个新的分支。稍等一会儿即可创建成功。 + + ![创建新分支1](./images/1_2_4.webp) + + ![创建新分支2](./images/1_2_5.webp) + +3. **创建Codespaces** + 在项目页面的右上角,点击 `Code` 按钮,然后选择 `Codespaces` 选项卡。点击 `New codespace` 按钮,等待新的 Codespaces 环境创建成功。 + + ![创建Codespaces](./images/1_2_6.webp) + +4. **再次进入Codespaces** + 网页关闭后,找到刚才新建的存储库,点击红框框选内容即可重新进入 codespace 环境。 + + ![再次进入Codespaces](./images/1_2_7.webp) + +5. **额度设置** + 找到 GitHub 的账户设置中的 codespace 设置,挂起时间建议根据自己情况调整(时间过长会浪费额度,免费账号提供了单核120小时的额度) + + ![额度设置](./images/1_2_8.webp) + +### 2.2 python环境配置 + +进入 IDE 后先选择下方终端 + +![进入终端](./images/1_2_9.webp) + +1. **更新系统软件包** + + 在终端输入下面指令: + + ```bash + sudo apt update + sudo apt upgrade -y + ``` + +2. **安装Miniconda** + + ```bash + wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh + bash ~/miniconda.sh + ``` + + - 按 Enter 阅读许可协议 + - 输入 `yes` 同意协议 + - 安装路径提示时直接按 Enter(使用默认路径 /home/ubuntu/miniconda3) + - 是否初始化Miniconda:输入 `yes` 将Miniconda添加到您的PATH环境变量中。 + + ```bash + source ~/.bashrc + conda --version + ``` + + 如果显示版本号,说明安装成功。 + +### 2.3 API配置 + +1. 使用 `vim` 编辑器打开你的 shell 配置文件。 + + ```bash + vim ~/.bashrc + ``` + +2. 输入 `i` 进入编辑模式,在文件末尾添加以下行,将 `[你的大模型 API 密钥]` 替换为你自己的密钥: + + ```bash + export DEEPSEEK_API_KEY=[你的大模型 API 密钥] + ``` + + 如果选择的是 `AIHubmix` 平台,为了增加辨识度也可以使用: + + ```bash + export AIHUBMIX_API_KEY=[你的大模型 API 密钥] + ``` + + > 不要带 `[]` + +3. 保存并退出 在 vim 中,按 Esc 键进入命令模式,然后输入 `:wq` 并按 Enter 键保存文件并退出。 + +4. 使配置生效 执行以下命令来立即加载更新后的配置,让环境变量生效: + + ```bash + source ~/.bashrc + ``` + +### 2.4 创建并激活虚拟环境 + +1. **创建虚拟环境** + + ```bash + conda create --name all-in-rag python=3.12.7 + ``` + + 出现选项直接回车即可。 + +2. **激活虚拟环境** + + 使用以下命令激活虚拟环境: + + ```bash + conda activate all-in-rag + ``` + +3. **依赖安装** + 如果严格安装上述流程当前应该在项目根目录,进入code目录安装依赖库 + + ```bash + cd code + pip install -r requirements.txt + ``` + + > 如果出现关于grpcio的版本错误无需在意。 + +## 三、Cloud Studio 环境配置(国内环境推荐) + +Cloud Studio 是腾讯云推出的一款基于浏览器的集成开发环境(IDE)。支持CPU与GPU的访问。 + +> 听说一个月是50个小时的免费额度🤔 + +### 3.1 应用创建 + +1. **访问 Cloud Studio** + 打开浏览器,访问 [Cloud Studio](https://cloudstudio.net/)。 + +2. **登录或注册账号** + 点击页面右上角的 `注册登录` 按钮,使用微信等方式完成登录。 + +3. **创建应用** + 在页面上方的导航栏中找到并点击 `创建应用`。选择 `从 Git 仓库导入` ,在项目地址栏输入 `https://github.com/datawhalechina/all-in-rag.git` 后回车,将会自动为你创建标题和描述。 + + ![创建应用](./images/1_2_10.webp) + + > 注意描述中不要包含网址 + +4. **再次进入** + 后续在[应用管理页面](https://cloudstudio.net/my-app)找到之前创建的应用,点击后选择右上角编写代码即可再次进入。 + + ![再次进入应用](./images/1_2_11.webp) + +### 3.2 python环境配置 + +进入 IDE 后先选择右侧终端 + +![进入终端](./images/1_2_12.webp) + +1. **更新系统软件包** + + 在终端输入下面指令: + + ```bash + sudo apt update + sudo apt upgrade -y + ``` + +2. **切换普通用户** + + ```bash + su ubuntu + ``` + +3. **安装Miniconda** + + ```bash + wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh + bash ~/miniconda.sh + ``` + + - 按 Enter 阅读许可协议 + - 输入 `yes` 同意协议 + - 安装路径提示时直接按 Enter(使用默认路径 /home/ubuntu/miniconda3) + - 是否初始化Miniconda:输入 `yes` 将Miniconda添加到您的PATH环境变量中。 + + ```bash + source ~/.bashrc + conda --version + ``` + + 如果显示版本号,说明安装成功。 + +### 3.3 API配置 + +1. 使用 `vim` 编辑器打开你的 shell 配置文件。 + + ```bash + vim ~/.bashrc + ``` + +2. 输入 `i` 进入编辑模式,在文件末尾添加以下行,将 `[你的大模型 API 密钥]` 替换为你自己的密钥: + + ```bash + export DEEPSEEK_API_KEY=[你的大模型 API 密钥] + ``` + + 如果选择的是 `AIHubmix` 平台,为了增加辨识度也可以使用: + + ```bash + export AIHUBMIX_API_KEY=[你的大模型 API 密钥] + ``` + + > 不要带 `[]` + +3. 保存并退出 在 vim 中,按 Esc 键进入命令模式,然后输入 `:wq` 并按 Enter 键保存文件并退出。 + +4. 使配置生效 执行以下命令来立即加载更新后的配置,让环境变量生效: + + ```bash + source ~/.bashrc + ``` + +### 3.4 创建并激活虚拟环境 + +1. **创建虚拟环境** + + ```bash + conda create --name all-in-rag python=3.12.7 + ``` + + 出现选项直接回车即可。 + +2. **配置文件权限** + + ```bash + sudo chown -R ubuntu:ubuntu code models + ``` + +3. **激活虚拟环境** + + 使用以下命令激活虚拟环境: + + ```bash + conda activate all-in-rag + ``` + +4. **依赖安装** + 如果严格安装上述流程当前应该在项目根目录,进入code目录安装依赖库 + + ```bash + cd code + pip install -r requirements.txt + ``` + + > 如果出现关于grpcio的版本错误无需在意。 + +## 四、windows环境配置(使用Cloud Studio 或 Codespaces 可跳过此步骤) + +### 4.1 API配置 + +1. 右键点击 “计算机” 或 “此电脑”,然后点击 “属性”。 + +2. 在左侧菜单中,点击 “高级系统设置”。 + +3. 在 “系统属性” 对话框中,点击 “高级” 选项卡,然后点击下方的 “环境变量” 按钮。 + + ![高级系统设置](./images/1_2_13.webp) + +4. 在 “环境变量” 对话框中,点击 “新建”(在 “用户变量” 部分下),然后输入以下信息: + - 变量名:DEEPSEEK_API_KEY + - 变量值:[你的 Deepseek API 密钥] + + ![高级系统设置](./images/1_2_14.webp) + +### 4.2 安装Miniconda + +1. **下载安装程序** + + 优先推荐访问[清华大学开源软件镜像站](https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/),以获得更快的下载速度。根据你的系统选择最新的 `.exe` 版本下载。 + + ![选择Miniconda版本](images/1_2_15.webp) + + 你也可以从 [Miniconda 官方网站](https://docs.conda.io/en/latest/miniconda.html)下载。 + +2. **运行安装向导** + + 下载完成后,双击 `.exe` 文件启动安装。按照向导提示操作: + + * **Welcome**: 点击 `Next`。 + + ![Welcome](./images/1_2_16.webp) + + * **License Agreement**: 点击 `I Agree`。 + + ![License Agreement](./images/1_2_17.webp) + + * **Installation Type**: 选择 `Just Me`,点击 `Next`。 + + ![Installation Type](./images/1_2_18.webp) + + * **Choose Install Location**: 建议保持默认路径,或选择一个不含中文和空格的路径。点击 `Next`。 + + ![Install Location](./images/1_2_19.webp) + + * **Advanced Installation Options**: **请不要勾选** “Add Miniconda3 to my PATH environment variable”。我们将稍后手动配置环境变量。点击 `Install`。 + + ![Advanced Options](./images/1_2_20.webp) + + * **Installation Complete**: 安装完成后,点击 `Next`,然后取消勾选 “Learn more” 并点击 `Finish` 完成安装。 + +3. **手动配置环境变量** + + 为了能在任意终端窗口使用 `conda` 命令,需要手动配置环境变量。 + + * 在Windows搜索栏中搜索“编辑系统环境变量”并打开。 + + ![编辑系统环境变量](./images/1_2_21.webp) + + * 在“系统属性”窗口中,点击“环境变量”。 + + ![环境变量按钮](./images/1_2_22.webp) + + * 在“环境变量”窗口中,找到“系统变量”下的 `Path` 变量,选中并点击“编辑”。 + + ![编辑Path变量](./images/1_2_23.webp) + + * 在“编辑环境变量”窗口中,新建三个路径,将它们指向你 Miniconda 的安装目录下的相应文件夹。如果你的安装路径是 `D:\Miniconda3`,则需要添加: + ``` + D:\Miniconda3 + D:\Miniconda3\Scripts + D:\Miniconda3\Library\bin + ``` + ![添加路径](./images/1_2_24.webp) + + * 完成后,一路点击“确定”保存更改。 + +### 4.3 配置 Conda 镜像源 + +为了加快后续使用 `conda` 安装包的速度,强烈建议配置国内镜像源。打开一个新的终端或 Anaconda Prompt,运行以下命令: + +```bash +conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ +conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ +conda config --set show_channel_urls yes +``` + +配置完成后,可以通过 `conda config --show channels` 命令查看已添加的源。 + +## 五、项目代码拉取(使用Cloud Studio 或 Codespaces 可跳过此步骤) + +### 5.1 安装 Git + +如果你尚未安装 Git,请按照以下步骤安装。 + +* **Windows 系统**:访问[Git 官方网站](https://git-scm.com/download/win),下载并运行安装程序,按照默认设置完成安装。 +* **macOS 系统**:打开终端,输入以下命令安装 Git: + + ```bash + brew install git + ``` +* **Linux 系统(以 Ubuntu 为例)**:打开终端,输入以下命令安装 Git: + + ```bash + sudo apt-get update + sudo apt-get install git + ``` + +安装完成后,验证 Git 是否安装成功,输入以下命令: + +```bash +git --version +``` + +如果成功,会显示 Git 的版本号。 + +### 5.2 克隆项目代码 + +1. **选择存放项目的目录** + 打开终端(或 Windows 中的 Git Bash),导航到你想存放项目的目录: + + ```bash + cd [你希望存放项目的路径] + ``` + +2. **克隆仓库** + 使用以下命令拉取 `all-in-rag` 仓库: + + ```bash + git clone https://github.com/datawhalechina/all-in-rag.git + ``` + + 等待下载完成,项目代码将存放在当前目录下的 `all-in-rag` 文件夹中。 + +3. **进入项目目录** + 拉取代码后,进入项目目录: + + ```bash + cd all-in-rag + ``` + +### 5.3 创建并激活虚拟环境 + +在项目目录下,推荐使用前面配置好的 Miniconda 来创建 Python 虚拟环境。 + +1. **创建虚拟环境** + + ```bash + conda create --name all-in-rag python=3.12.7 + ``` + +2. **激活虚拟环境** + + 所有系统统一使用以下命令激活虚拟环境: + + ```bash + conda activate all-in-rag + ``` + +3. **依赖安装** + 如果严格安装上述流程当前应该在项目根目录,进入code目录安装依赖库 + + ```bash + cd code + pip install -r requirements.txt + ``` diff --git a/docs/chapter1/03_get_start_rag.md b/docs/chapter1/03_get_start_rag.md new file mode 100644 index 0000000..3c97ddd --- /dev/null +++ b/docs/chapter1/03_get_start_rag.md @@ -0,0 +1,250 @@ +# 第三节 四步构建RAG + +通过第一节的学习,我们对RAG已经有了基本认识,并且也准备好了虚拟环境和api_key,接下来将尝试使用[**LangChain**](https://python.langchain.com/docs/introduction/)和[**LlamaIndex**](https://docs.llamaindex.ai/en/stable/)框架完成第一个RAG应用的实现与运行。通过一个示例,演示如何加载本地Markdown文档,利用嵌入模型处理文本,并结合大型语言模型(LLM)来回答与文档内容相关的问题。 + +## 一、启动虚拟环境 + +### 1.1 激活虚拟环境 + +假设已经按照前一章节的指导,创建了名为 `all-in-rag` 的 Conda 虚拟环境。在运行脚本前,先激活虚拟环境: + +> 如果使用是Cloud Studio,需要确认当前是否是用户环境,如果不是请运行 `su ubuntu` 切换到用户环境。 + +```bash +conda activate all-in-rag +``` + +### 1.2 切换到项目目录 + +```bash +# 假设当前在 all-in-rag 项目的根目录下 +cd code/C1 +``` + +每章内容中的代码文件都存放在 `code/Cx` 目录下,其中 `x` 表示章节编号。 + +## 二、运行RAG示例代码 + +完成上述所有设置后,就可以运行RAG示例了。 + +打开终端,确保虚拟环境已激活,然后执行以下命令: + +```bash +python 01_langchain_example.py +``` + +> 若出现nltk相关报错,尝试运行代码路径下[fix_nltk.py](https://github.com/datawhalechina/all-in-rag/blob/main/code/C1/fix_nltk.py) + +代码运行后,可以看到类似下面的输出(格式化后): + +```bash +Downloading Model from https://www.modelscope.cn to directory: Path\to\all-in-rag\models\bge-small-zh-v1.5 +2025-06-08 02:36:19,318 - modelscope - INFO - Target directory already exists, skipping creation. +content=' +文中举了以下例子: + +1. **自然界中的羚羊**:刚出生的羚羊通过试错学习站立和奔跑,适应环境。 +2. **股票交易**:通过买卖股票并根据市场反馈调整策略,最大化奖励。 +3. **雅达利游戏(如Breakout和Pong)**:通过不断试错学习如何通关或赢得游戏。 +4. **选择餐馆**:利用(去已知喜欢的餐馆)与探索(尝试新餐馆)的权衡。 +5. **做广告**:利用(采取已知最优广告策略)与探索(尝试新广告策略)。 +6. **挖油**:利用(在已知地点挖油)与探索(在新地点挖油,可能发现大油田)。 +7. **玩游戏(如《街头霸王》)**:利用(固定策略如蹲角落出脚)与探索(尝试新招式如“大招”)。 + +这些例子用于说明强化学习中的核心概念(如探索与利用、延迟奖励等)及其在实际场景中的应用。 +' +additional_kwargs={'refusal': None} +response_metadata={ + 'token_usage': { + 'completion_tokens': 209, + 'prompt_tokens': 5576, + 'total_tokens': 5785, + 'completion_tokens_details': None, + 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 5568}, + 'prompt_cache_hit_tokens': 5568, + 'prompt_cache_miss_tokens': 8 + }, + 'model_name': 'deepseek-chat', + 'system_fingerprint': 'fp_8802369eaa_prod0425fp8', + 'id': '67a0580d-78b1-44d6-bccf-f654ae0e9bba', + 'service_tier': None, + 'finish_reason': 'stop', + 'logprobs': None +} +id='run--919cedcd-771e-4aed-8dfd-cf436795792e-0' +usage_metadata={ + 'input_tokens': 5576, + 'output_tokens': 209, + 'total_tokens': 5785, + 'input_token_details': {'cache_read': 5568}, + 'output_token_details': {} +} +``` + +> 首次运行时,脚本会下载`BAAI/bge-small-zh-v1.5`嵌入模型。 + +输出参数解析: +- **`content`**: 这是最核心的部分,即大型语言模型(LLM)根据你的问题和提供的上下文生成的具体回答。 +- **`additional_kwargs`**: 包含一些额外的参数,在这个例子中是 `{'refusal': None}`,表示模型没有拒绝回答。 +- **`response_metadata`**: 包含了关于LLM响应的元数据。 + - `token_usage`: 显示了本次调用消耗的token数量,包括完成(completion_tokens)、提示(prompt_tokens)和总量(total_tokens)。 + - `model_name`: 使用的LLM模型名称,当前是 `deepseek-chat`。 + - `system_fingerprint`, `id`, `service_tier`, `finish_reason`, `logprobs`: 这些是更详细的API响应信息,例如 `finish_reason: 'stop'` 表示模型正常完成了生成。 +- **`id`**: 本次运行的唯一标识符。 +- **`usage_metadata`**: 与 `response_metadata` 中的 `token_usage` 类似,提供了输入和输出token的统计。 + +## 三、基于 LangChain 框架的 RAG 实现 + +在第一节中,我们提到四步构建最小可行系统分别是数据准备、索引构建、检索优化和生成集成。下面将围绕这四个方面来实现一个基于 LangChain 框架的 RAG 应用。 + +> [本节完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C1/01_langchain_example.py) + +### 3.1 初始化设置 + +首先进行基础配置,包括导入必要的库、加载环境变量以及下载嵌入模型。 + +```python +import os +# os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com' +from dotenv import load_dotenv +from langchain_community.document_loaders import TextLoader +from langchain_text_splitters import RecursiveCharacterTextSplitter +from langchain_huggingface import HuggingFaceEmbeddings +from langchain_core.vectorstores import InMemoryVectorStore +from langchain_core.prompts import ChatPromptTemplate +from langchain_deepseek import ChatOpenAI + +# 加载环境变量 +load_dotenv() +``` + +### 3.2 数据准备 + +- **加载原始文档**: 先定义Markdown文件的路径,然后使用`TextLoader`加载该文件作为知识源。 + ```python + markdown_path = "../../data/C1/markdown/easy-rl-chapter1.md" + loader = TextLoader(markdown_path) + docs = loader.load() + ``` +- **文本分块 (Chunking)**: 为了便于后续的嵌入和检索,长文档被分割成较小的、可管理的文本块(chunks)。这里采用了递归字符分割策略,使用其默认参数进行分块。当不指定参数初始化 `RecursiveCharacterTextSplitter()` 时,其默认行为旨在最大程度保留文本的语义结构: + - **默认分隔符与语义保留**: 按顺序尝试使用一系列预设的分隔符 `["\n\n" (段落), "\n" (行), " " (空格), "" (字符)]` 来递归分割文本。这种策略的目的是尽可能保持段落、句子和单词的完整性,因为它们通常是语义上最相关的文本单元,直到文本块达到目标大小。 + - **保留分隔符**: 默认情况下 (`keep_separator=True`),分隔符本身会被保留在分割后的文本块中。 + - **默认块大小与重叠**: 使用其基类 `TextSplitter` 中定义的默认参数 `chunk_size=4000`(块大小)和 `chunk_overlap=200`(块重叠)。这些参数确保文本块符合预定的大小限制,并通过重叠来减少上下文信息的丢失。 + ```python + text_splitter = RecursiveCharacterTextSplitter() + texts = text_splitter.split_documents(docs) + ``` + +### 3.3 索引构建 + +数据准备完成后,接下来构建向量索引: + +- **初始化中文嵌入模型**: 使用`HuggingFaceEmbeddings`加载之前在初始化设置中下载的中文嵌入模型。配置模型在CPU上运行,并启用嵌入归一化 (`normalize_embeddings: True`)。 + ```python + embeddings = HuggingFaceEmbeddings( + model_name="BAAI/bge-small-zh-v1.5", + model_kwargs={'device': 'cpu'}, + encode_kwargs={'normalize_embeddings': True} + ) + ``` +- **构建向量存储**: 将分割后的文本块 (`texts`) 通过初始化好的嵌入模型转换为向量表示,然后使用`InMemoryVectorStore`将这些向量及其对应的原始文本内容添加进去,从而在内存中构建出一个向量索引。 + ```python + vectorstore = InMemoryVectorStore(embeddings) + vectorstore.add_documents(texts) + ``` + 这个过程完成后,便构建了一个可供查询的知识索引。 + +### 3.4 查询与检索 + +索引构建完毕后,便可以针对用户问题进行查询与检索: + +- **定义用户查询**: 设置一个具体的用户问题字符串。 + ```python + question = "文中举了哪些例子?" + ``` +- **在向量存储中查询相关文档**: 使用向量存储的`similarity_search`方法,根据用户问题在索引中查找最相关的 `k` (此处示例中 `k=3`) 个文本块。 + ```python + retrieved_docs = vectorstore.similarity_search(question, k=3) + ``` +- **准备上下文**: 将检索到的多个文本块的页面内容 (`doc.page_content`) 合并成一个单一的字符串,并使用双换行符 (`"\n\n"`) 分隔各个块,形成最终的上下文信息 (`docs_content`) 供大语言模型参考。 + ```python + docs_content = "\n\n".join(doc.page_content for doc in retrieved_docs) + ``` + > 使用 `"\n\n"` (双换行符) 而不是 `"\n"` (单换行符) 来连接不同的检索文档块,主要是为了在传递给大型语言模型(LLM)时,能够更清晰地在语义上区分这些独立的文本片段。双换行符通常代表段落的结束和新段落的开始,这种格式有助于LLM将每个块视为一个独立的上下文来源,从而更好地理解和利用这些信息来生成回答。 + +### 3.5 生成集成 + +最后一步是将检索到的上下文与用户问题结合,利用大语言模型(LLM)生成答案: + +- **构建提示词模板**: 使用`ChatPromptTemplate.from_template`创建一个结构化的提示模板。此模板指导LLM根据提供的上下文 (`context`) 回答用户的问题 (`question`),并明确指出在信息不足时应如何回应。 + ```python + prompt = ChatPromptTemplate.from_template("""请根据下面提供的上下文信息来回答问题。 + 请确保你的回答完全基于这些上下文。 + 如果上下文中没有足够的信息来回答问题,请直接告知:“抱歉,我无法根据提供的上下文找到相关信息来回答此问题。” + + 上下文: + {context} + + 问题: {question} + + 回答:""" + ) + ``` +- **配置大语言模型**: 初始化 `ChatOpenAI` 客户端,配置所用模型(`glm-4.7-flash-free`)、生成答案的温度参数(`temperature=0.7`)、最大Token数 (`max_tokens=2048`) 以及API密钥(从环境变量加载)和 url。 + ```python + llm = ChatOpenAI( + model="glm-4.7-flash-free", + temperature=0.7, + max_tokens=2048, + api_key=os.getenv("DEEPSEEK_API_KEY") + base_url="https://aihubmix.com/v1" + ) + ``` +- **调用LLM生成答案并输出**: 将用户问题 (`question`) 和先前准备好的上下文 (`docs_content`) 格式化到提示模板中,然后调用ChatDeepSeek的`invoke`方法获取生成的答案。 + ```python + answer = llm.invoke(prompt.format(question=question, context=docs_content)) + print(answer) + ``` + +> 老湿老湿,Langchain 很强大但还是太吃操作了,有没有更加简单又好用的框架推荐呢? + +> 有的兄弟,有的!像这样好用的框架还有LlamaIndex😉 + +## 四、低代码(基于LlamaIndex) + +在 RAG 方面,LlamaIndex 提供了更多封装好的 API 接口,这无疑降低了上手门槛,下面是一个简单实现: + +```python +import os +# os.environ['HF_ENDPOINT']='https://hf-mirror.com' +from dotenv import load_dotenv +from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings +from llama_index.llms.openai_like import OpenAILike +from llama_index.embeddings.huggingface import HuggingFaceEmbedding + +load_dotenv() + +Settings.llm = OpenAILike( + model="glm-4.7-flash-free", + api_key=os.getenv("DEEPSEEK_API_KEY"), + api_base="https://aihubmix.com/v1", + is_chat_model=True +) +Settings.embed_model = HuggingFaceEmbedding("BAAI/bge-small-zh-v1.5") + +documents = SimpleDirectoryReader(input_files=["../../data/C1/markdown/easy-rl-chapter1.md"]).load_data() + +index = VectorStoreIndex.from_documents(documents) + +query_engine = index.as_query_engine() + +print(query_engine.get_prompts()) + +print(query_engine.query("文中举了哪些例子?")) +``` + +## 练习(可利用大模型辅助完成) + +- LangChain代码最终得到的输出携带了各种参数,查询相关资料尝试把这些参数过滤掉得到`content`里的具体回答。 +- 修改Langchain代码中`RecursiveCharacterTextSplitter()`的参数`chunk_size`和`chunk_overlap`,观察输出结果有什么变化。 +- 给LlamaIndex代码添加代码注释。 \ No newline at end of file diff --git a/docs/chapter1/images/1.png b/docs/chapter1/images/1.png new file mode 100644 index 0000000..d31dbbc Binary files /dev/null and b/docs/chapter1/images/1.png differ diff --git a/docs/chapter1/images/1_1_1.svg b/docs/chapter1/images/1_1_1.svg new file mode 100644 index 0000000..78a9954 --- /dev/null +++ b/docs/chapter1/images/1_1_1.svg @@ -0,0 +1,3 @@ + + +
RAG
检索阶段
生成阶段
用户查询
检索模块
相关文档/片段
生成模块
Embedding
model



Encoding
外部知识库
Encoding
Vector
database
Prompt
LLM响应
author: dalvqw
Index
Similarity
Search
\ No newline at end of file diff --git a/docs/chapter1/images/1_1_2.png b/docs/chapter1/images/1_1_2.png new file mode 100644 index 0000000..6dba4a7 Binary files /dev/null and b/docs/chapter1/images/1_1_2.png differ diff --git a/docs/chapter1/images/1_1_3.svg b/docs/chapter1/images/1_1_3.svg new file mode 100644 index 0000000..f8aa2b7 --- /dev/null +++ b/docs/chapter1/images/1_1_3.svg @@ -0,0 +1,3 @@ + + +
RAG
Prompt Engineering
Fine-tuning
Hybrid
(RAG + Fine-tuning)
Context
optimization
LLM Optimization
Prompting vs RAG vs Fine-Tuning
\ No newline at end of file diff --git a/docs/chapter1/images/1_2_1.webp b/docs/chapter1/images/1_2_1.webp new file mode 100644 index 0000000..e543fd4 Binary files /dev/null and b/docs/chapter1/images/1_2_1.webp differ diff --git a/docs/chapter1/images/1_2_10.webp b/docs/chapter1/images/1_2_10.webp new file mode 100644 index 0000000..111d7dd Binary files /dev/null and b/docs/chapter1/images/1_2_10.webp differ diff --git a/docs/chapter1/images/1_2_11.webp b/docs/chapter1/images/1_2_11.webp new file mode 100644 index 0000000..3416aa9 Binary files /dev/null and b/docs/chapter1/images/1_2_11.webp differ diff --git a/docs/chapter1/images/1_2_12.webp b/docs/chapter1/images/1_2_12.webp new file mode 100644 index 0000000..2787ef7 Binary files /dev/null and b/docs/chapter1/images/1_2_12.webp differ diff --git a/docs/chapter1/images/1_2_13.webp b/docs/chapter1/images/1_2_13.webp new file mode 100644 index 0000000..8c6fc11 Binary files /dev/null and b/docs/chapter1/images/1_2_13.webp differ diff --git a/docs/chapter1/images/1_2_14.webp b/docs/chapter1/images/1_2_14.webp new file mode 100644 index 0000000..308e98c Binary files /dev/null and b/docs/chapter1/images/1_2_14.webp differ diff --git a/docs/chapter1/images/1_2_15.webp b/docs/chapter1/images/1_2_15.webp new file mode 100644 index 0000000..751ee9c Binary files /dev/null and b/docs/chapter1/images/1_2_15.webp differ diff --git a/docs/chapter1/images/1_2_16.webp b/docs/chapter1/images/1_2_16.webp new file mode 100644 index 0000000..fb50e8f Binary files /dev/null and b/docs/chapter1/images/1_2_16.webp differ diff --git a/docs/chapter1/images/1_2_17.webp b/docs/chapter1/images/1_2_17.webp new file mode 100644 index 0000000..acd77c9 Binary files /dev/null and b/docs/chapter1/images/1_2_17.webp differ diff --git a/docs/chapter1/images/1_2_18.webp b/docs/chapter1/images/1_2_18.webp new file mode 100644 index 0000000..4602e49 Binary files /dev/null and b/docs/chapter1/images/1_2_18.webp differ diff --git a/docs/chapter1/images/1_2_19.webp b/docs/chapter1/images/1_2_19.webp new file mode 100644 index 0000000..fa1c5c7 Binary files /dev/null and b/docs/chapter1/images/1_2_19.webp differ diff --git a/docs/chapter1/images/1_2_2.webp b/docs/chapter1/images/1_2_2.webp new file mode 100644 index 0000000..f22d8e7 Binary files /dev/null and b/docs/chapter1/images/1_2_2.webp differ diff --git a/docs/chapter1/images/1_2_20.webp b/docs/chapter1/images/1_2_20.webp new file mode 100644 index 0000000..bb6ee73 Binary files /dev/null and b/docs/chapter1/images/1_2_20.webp differ diff --git a/docs/chapter1/images/1_2_21.webp b/docs/chapter1/images/1_2_21.webp new file mode 100644 index 0000000..c5e7b6b Binary files /dev/null and b/docs/chapter1/images/1_2_21.webp differ diff --git a/docs/chapter1/images/1_2_22.webp b/docs/chapter1/images/1_2_22.webp new file mode 100644 index 0000000..de5cedd Binary files /dev/null and b/docs/chapter1/images/1_2_22.webp differ diff --git a/docs/chapter1/images/1_2_23.webp b/docs/chapter1/images/1_2_23.webp new file mode 100644 index 0000000..7de5172 Binary files /dev/null and b/docs/chapter1/images/1_2_23.webp differ diff --git a/docs/chapter1/images/1_2_24.webp b/docs/chapter1/images/1_2_24.webp new file mode 100644 index 0000000..11f30ee Binary files /dev/null and b/docs/chapter1/images/1_2_24.webp differ diff --git a/docs/chapter1/images/1_2_3.webp b/docs/chapter1/images/1_2_3.webp new file mode 100644 index 0000000..6f7f5db Binary files /dev/null and b/docs/chapter1/images/1_2_3.webp differ diff --git a/docs/chapter1/images/1_2_4.webp b/docs/chapter1/images/1_2_4.webp new file mode 100644 index 0000000..8c389f6 Binary files /dev/null and b/docs/chapter1/images/1_2_4.webp differ diff --git a/docs/chapter1/images/1_2_5.webp b/docs/chapter1/images/1_2_5.webp new file mode 100644 index 0000000..8404023 Binary files /dev/null and b/docs/chapter1/images/1_2_5.webp differ diff --git a/docs/chapter1/images/1_2_6.webp b/docs/chapter1/images/1_2_6.webp new file mode 100644 index 0000000..915d279 Binary files /dev/null and b/docs/chapter1/images/1_2_6.webp differ diff --git a/docs/chapter1/images/1_2_7.webp b/docs/chapter1/images/1_2_7.webp new file mode 100644 index 0000000..6473e20 Binary files /dev/null and b/docs/chapter1/images/1_2_7.webp differ diff --git a/docs/chapter1/images/1_2_8.webp b/docs/chapter1/images/1_2_8.webp new file mode 100644 index 0000000..d4248e8 Binary files /dev/null and b/docs/chapter1/images/1_2_8.webp differ diff --git a/docs/chapter1/images/1_2_9.webp b/docs/chapter1/images/1_2_9.webp new file mode 100644 index 0000000..72a1ed3 Binary files /dev/null and b/docs/chapter1/images/1_2_9.webp differ diff --git a/docs/chapter1/images/1_4_1.webp b/docs/chapter1/images/1_4_1.webp new file mode 100644 index 0000000..8be5c3c Binary files /dev/null and b/docs/chapter1/images/1_4_1.webp differ diff --git a/docs/chapter1/images/1_4_2.webp b/docs/chapter1/images/1_4_2.webp new file mode 100644 index 0000000..f407add Binary files /dev/null and b/docs/chapter1/images/1_4_2.webp differ diff --git a/docs/chapter1/images/1_4_3.webp b/docs/chapter1/images/1_4_3.webp new file mode 100644 index 0000000..3871c72 Binary files /dev/null and b/docs/chapter1/images/1_4_3.webp differ diff --git a/docs/chapter1/images/2.png b/docs/chapter1/images/2.png new file mode 100644 index 0000000..1a724d6 Binary files /dev/null and b/docs/chapter1/images/2.png differ diff --git a/docs/chapter1/images/3.png b/docs/chapter1/images/3.png new file mode 100644 index 0000000..5148eab Binary files /dev/null and b/docs/chapter1/images/3.png differ diff --git a/docs/chapter1/virtualenv.md b/docs/chapter1/virtualenv.md new file mode 100644 index 0000000..44832b5 --- /dev/null +++ b/docs/chapter1/virtualenv.md @@ -0,0 +1,91 @@ +# 附:Python虚拟环境部署方案补充 + +本项目由于涉及到的包过多,并且**依赖问题**自始至终都是Python的老大难问题,这就造成了 Python 工程化方面生态非常割裂。 + +对于这种问题,uv提供了统一的虚拟环境管理入口,同时吸收了 Rust 语言先进的包管理经验,使用它可以减少我们在 Python 工程方面折腾的时间,下面我们使用uv来安装项目的虚拟环境。 + +## 1.1 uv 环境管理 + +### 1.1.1 Windows 系统 + +**使用powershell 安装 uv** + +```bash +powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" +``` + +**安装成功后,按照提示输入以下命令添加环境变量**。这里注意,**不同的人的安装路径不同**,请按照提示自行复制粘贴命令。 + + +```bash +$env:Path = "C:\Users\michaelbradley\.local\bin;$env:Path" +``` + +![安装成功的提示](./images/1_4_1.webp) + + +**输入 uv 命令,如果出现以下提示,说明安装成功** + +![成功安装uv](./images/1_4_2.webp) + +### 1.1.2 Linux / MacOS 系统 + +**使用 curl 安装 uv** + +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +如果无法使用 curl 命令,**使用 wget 命令**安装 uv + +```bash +wget -qO- https://astral.sh/uv/install.sh | sh +``` + +**输入 uv 命令,如果出现以下提示,说明安装成功** + +![成功安装uv](./images/1_4_3.webp) + + +## 1.2 创建并激活虚拟环境 + +### 1.2.1 **创建虚拟环境** + +```bash +uv venv rag --python 3.12.7 +``` + +代码创建的虚拟环境名称为 rag ,使用Python版本为 3.12.7 + +Windows 系统创建成功后显示如下信息: + +```bash +PS C:\Users\parallel> uv venv rag --python 3.12.7 +Using CPython 3.12.7 +Creating virtual environment at: rag +Activate with: rag\Scripts\activate +``` + +Linux / MacOS 系统创建成功后显示如下信息: + +```bash +┌──(parallel㉿pacman)-[~/桌面] +└─$ uv venv rag -p 3.12.7 +Using CPython 3.12.7 +Creating virtual environment at: rag +Activate with: source rag/bin/activate +``` + +### 1.2.2 **激活虚拟环境** + +Windows 系统激活虚拟环境命令为: + +```bash +rag\Scripts\activate +``` + +Linux / MacOS 系统激活虚拟环境命令为: + +```bash +source rag/bin/activate +``` \ No newline at end of file diff --git a/docs/chapter2/04_data_load.md b/docs/chapter2/04_data_load.md new file mode 100644 index 0000000..1684ed2 --- /dev/null +++ b/docs/chapter2/04_data_load.md @@ -0,0 +1,234 @@ +# 第一节 数据加载 + +虽然本节内容在实际应用中非常重要,但是由于各种文档加载器的迭代更新,以及各类 AI 应用的不同需求,具体选择需要根据实际情况。本节仅作简单引入,但请务必**重视数据加载**环节,**“垃圾进,垃圾出 (Garbage In, Garbage Out)”** ——高质量输入是高质量输出的前提。 + +## 一、文档加载器 + +### 1.1 主要功能 + +RAG 系统中,**数据加载**是整个流水线的第一步,也是不可或缺的一步。文档加载器负责将各种格式的非结构化文档(如PDF、Word、Markdown、HTML等)转换为程序可以处理的结构化数据。数据加载的质量会直接影响后续的索引构建、检索效果和最终的生成质量。 + +文档加载器在 RAG 的数据管道中一般需要完成三个核心任务,一是解析不同格式的原始文档,将 PDF、Word、Markdown 等内容提取为可处理的纯文本,二是在解析过程中同时抽取文档来源、页码、作者等关键信息作为元数据,三是把文本和元数据整理成统一的数据结构,方便后续进行切分、向量化和入库,其整体流程与传统数据工程中的抽取、转换、加载相似,目标都是把杂乱的原始文档清洗并对齐为适合检索和建模的标准化语料。 + +### 1.2 当前主流RAG文档加载器 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
工具名称特点适用场景性能表现
PyMuPDF4LLMPDF→Markdown转换,OCR+表格识别科研文献、技术手册开源免费,GPU加速
TextLoader基础文本文件加载纯文本处理轻量高效
DirectoryLoader批量目录文件处理混合格式文档库支持多格式扩展
Unstructured多格式文档解析PDF、Word、HTML等统一接口,智能解析
FireCrawlLoader网页内容抓取在线文档、新闻实时内容获取
LlamaParse深度PDF结构解析法律合同、学术论文解析精度高,商业API
Docling模块化企业级解析企业合同、报告IBM生态兼容
MarkerPDF→Markdown,GPU加速科研文献、书籍专注PDF转换
MinerU多模态集成解析学术文献、财务报表集成LayoutLMv3+YOLOv8
+

表 2-1 当前主流 RAG 文档加载器

+
+ +## 二、Unstructured文档处理库 + +### 2.1 Unstructured 的核心优势 + +**Unstructured** [^1]是一个专业的文档处理库,专门设计用于RAG和AI微调场景的非结构化数据预处理。提供了统一的接口来处理多种文档格式,是目前应用较广泛的文档加载解决方案之一。Unstructured 在格式支持和内容解析方面具有明显优势,它一方面支持 PDF、Word、Excel、HTML、Markdown 等多种文档格式,并通过统一的 API 接口避免为不同格式分别编写代码,另一方面可以自动识别标题、段落、表格、列表等文档结构,同时保留相应的元数据信息。 + +
+ Unstructured 官网界面 +

图 2-1 Unstructured 官网界面

+
+ +### 2.2 支持的文档元素类型 + +Unstructured 能够识别和分类以下文档元素 [^2]: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
元素类型描述
Title文档标题
NarrativeText由多个完整句子组成的正文文本,不包括标题、页眉、页脚和说明文字
ListItem列表项,属于列表的正文文本元素
Table表格
Image图像元数据
Formula公式
Address物理地址
EmailAddress邮箱地址
FigureCaption图片标题/说明文字
Header文档页眉
Footer文档页脚
CodeSnippet代码片段
PageBreak页面分隔符
PageNumber页码
UncategorizedText未分类的自由文本
CompositeElement分块处理时产生的复合元素*
+

表 2-2 Unstructured 支持的文档元素类型

+
+ +> `CompositeElement` 是通过分块处理产生的特殊元素类型,由一个或多个连续的文本元素组合而成。例如,多个列表项可能会被组合成一个单独的块。 + +## 三、从 LangChain 封装到原始 Unstructured + +在第一章的示例中,我们使用了LangChain的`UnstructuredMarkdownLoader`,它是 LangChain 对 Unstructured 库的封装。接下来展示如何直接使用 Unstructured 库,这样可以获得更大的灵活性和控制力。 + +> [本节完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C2/01_unstructured_example.py) + +### 3.1 代码示例 + +创建一个简单的示例,尝试使用 Unstructured 库加载并解析一个PDF文件。 + +```python +from unstructured.partition.auto import partition + +# PDF文件路径 +pdf_path = "../../data/C2/pdf/rag.pdf" + +# 使用Unstructured加载并解析PDF文档 +elements = partition( + filename=pdf_path, + content_type="application/pdf" +) + +# 打印解析结果 +print(f"解析完成: {len(elements)} 个元素, {sum(len(str(e)) for e in elements)} 字符") + +# 统计元素类型 +from collections import Counter +types = Counter(e.category for e in elements) +print(f"元素类型: {dict(types)}") + +# 显示所有元素 +print("\n所有元素:") +for i, element in enumerate(elements, 1): + print(f"Element {i} ({element.category}):") + print(element) + print("=" * 60) +``` + +> 若代码运行出现报错 `ImportError: libgl.so.1 cannot open shared object file no such file or directory`, 执行 `sudo apt-get install python3-opencv` 安装依赖库。 + +**partition 函数参数解析:** + +- `filename`: 文档文件路径,支持本地文件路径; +- `content_type`: 可选参数,指定MIME类型(如"application/pdf"),可绕过自动文件类型检测; +- `file`: 可选参数,文件对象,与 filename 二选一使用; +- `url`: 可选参数,远程文档 URL,支持直接处理网络文档; +- `include_page_breaks`: 布尔值,是否在输出中包含页面分隔符; +- `strategy`: 处理策略,可选 "auto"、"fast"、"hi_res" 等; +- `encoding`: 文本编码格式,默认自动检测。 + +`partition`函数使用自动文件类型检测,内部会根据文件类型路由到对应的专用函数(如PDF文件会调用`partition_pdf`)。如果需要更专业的PDF处理,可以直接使用`from unstructured.partition.pdf import partition_pdf`,它提供更多PDF特有的参数选项,如OCR语言设置、图像提取、表格结构推理等高级功能,同时性能更优。 + +> 在实际应用中,针对 pdf 的处理,目前更多选用的是 PaddleOCR、MinerU 等模型或工具。 + +## 练习 + +- 使用`partition_pdf`替换当前`partition`函数并分别尝试用`hi_res`和`ocr_only`进行解析,观察输出结果有何变化。 + +## 参考文献 + +[^1]: [*Unstructured Open-Source Documentation*](https://docs.unstructured.io/open-source/) + +[^2]: [*Unstructured Open-Source: Document Elements*](https://docs.unstructured.io/open-source/concepts/document-elements) diff --git a/docs/chapter2/05_text_chunking.md b/docs/chapter2/05_text_chunking.md new file mode 100644 index 0000000..59f513a --- /dev/null +++ b/docs/chapter2/05_text_chunking.md @@ -0,0 +1,298 @@ +# 第二节 文本分块 + +## 一、理解文本分块 + +文本分块(Text Chunking)是构建 RAG 流程的关键步骤。它的原理是将加载后的长篇文档,切分成更小、更易于处理的单元。这些被切分出的文本块,是后续向量检索和模型处理的**基本单位**。 + +![文本分块示意图](./images/2_2_1.webp) + +## 二、文本分块重要性 + +### 2.1 满足模型上下文限制 + +将文本分块的首要原因,是为了适应 RAG 系统中两个核心组件的硬性限制: + +- **嵌入模型 (Embedding Model)**: 负责将文本块转换为向量。这类模型有严格的输入长度上限。例如,许多常用的嵌入模型(如 `bge-base-zh-v1.5`)的上下文窗口为512个token。任何超出此限制的文本块在输入时都会被截断,导致信息丢失,生成的向量也无法完整代表原文的语义。因此,文本块的大小**必须**小于等于嵌入模型的上下文窗口。 + +- **大语言模型 (LLM)**: 负责根据检索到的上下文生成答案。LLM同样有上下文窗口限制(尽管通常比嵌入模型大得多,从几千到上百万token不等)。检索到的所有文本块,连同用户问题和提示词,都必须能被放入这个窗口中。如果单个块过大,可能会导致只能容纳少数几个相关的块,限制了LLM回答问题时可参考的信息广度。 + +因此,分块是确保文本能够被两个模型完整、有效处理的基础。 + +### 2.2 为何“块”不是越大越好 + +假设嵌入模型最多能处理 8192 个 token,是否应该把块切得尽可能大(比如8000个token)呢?答案是否定的。**块的大小并非越大越好**,过大的块会严重影响RAG系统的性能。 + +#### 2.2.1 嵌入过程中的信息损失 + +大多数嵌入模型都基于 Transformer 编码器。其工作流程大致如下: + +- **分词 (Tokenization)**: 将输入的文本块分解成一个个 token。 +- **向量化 (Vectorization)**: Transformer 为**每个 token** 生成一个高维向量表示。 +- **池化 (Pooling)**: 通过某种方法(如取 `[CLS]` 位的向量、对所有token向量求平均 `mean pooling` 等),将所有 token 的向量**压缩**成一个**单一的向量**,这个向量代表了整个文本块的语义。 + +> `[CLS]` 是BERT等Transformer模型在输入文本开头添加的特殊标记,它通过自注意力机制动态聚合整个序列的上下文信息,其最终向量被训练用作代表全局语义的嵌入。 + +在这个`压缩`过程中,信息损失是不可避免的。一个768维的向量需要概括整个文本块的所有信息。**文本块越长,包含的语义点越多,这个单一向量所承载的信息就越稀释**,导致其表示变得笼统,关键细节被模糊化,从而降低了检索的精度。 + +#### 2.2.2 生成过程的“大海捞针” (Lost in the Middle) + +即使将检索到的多个大块文本都塞进LLM的长上下文窗口中,也会出现关键信息被“淹没”在大量无关内容里的问题。有研究表明 [^1],当LLM处理非常长的、充满大量信息的上下文时,它倾向于更好地记住开头和结尾的信息,而忽略中间部分的内容。 + +如果提供给LLM的上下文块又大又杂,充满了与问题无关的噪音,模型就很难从中提取出最关键的信息来形成答案,从而导致回答质量下降或产生幻觉。 + +#### 2.2.3 主题稀释导致检索失败 + +一个好的文本块应该聚焦于一个明确、单一的主题。如果一个块包含太多不相关的主题,它的语义就会被稀释,导致在检索时无法被精确匹配。 + +**举个栗子🌰:** + +假设有一个关于《王者荣耀》英雄鲁班七号的攻略文档。 + +- **糟糕的分块策略**:将“技能介绍”、“推荐出装”和“背景故事”这三个完全不同主题的内容,全部放在一个巨大的文本块里。 + - 当玩家查询“鲁班七号怎么出装?”时,这个大块虽然包含了出装信息,但由于被技能说明和英雄故事等无关主题严重稀释,其整体的检索相关性得分可能会很低,导致无法被召回。 + +- **优秀的分块策略**:将“技能”、“出装”和“故事”分别切分为三个独立的、主题聚焦的块。 + - 当玩家再次查询时,“推荐出装”这个块会因为与查询高度相关而获得极高的分数,从而被精准地检索出来。 + +通过合理分块,可以有效提升检索的信噪比,确保了后续生成环节能得到最优质、最相关的上下文。 + +## 三、基础分块策略 + +LangChain 提供了丰富且易于使用的文本分割器(Text Splitters),下面将介绍几种最核心的策略。 + +### 3.1 固定大小分块 + +这是最简单直接的分块方法。根据LangChain源码,这种方法的工作原理分为两个主要阶段: + +(1)**按段落分割**:`CharacterTextSplitter` 采用默认分隔符 `"\n\n"`,使用正则表达式将文本按段落进行分割,通过 `_split_text_with_regex` 函数处理。 + +(2)**智能合并**:调用继承自父类的 `_merge_splits` 方法,将分割后的段落依次合并。该方法会监控累积长度,当超过 `chunk_size` 时形成新块,并通过重叠机制(`chunk_overlap`)保持上下文连续性,同时在必要时发出超长块的警告。 + +需要注意,`CharacterTextSplitter` 实际实现的并非严格的固定大小分块。根据 `_merge_splits` 源码逻辑,这种方法会: + +- **优先保持段落完整性**:只有当添加新段落会导致总长度超过 `chunk_size` 时,才会结束当前块 +- **处理超长段落**:如果单个段落超过 `chunk_size`,系统会发出警告但仍将其作为完整块保留 +- **应用重叠机制**:通过 `chunk_overlap` 参数在块之间保持内容重叠,确保上下文连续性 + +所以,LangChain 的实现更准确地应该称为"段落感知的自适应分块",块大小会根据段落边界动态调整。 + +下面的代码展示了如何配置一个固定大小分块器: + +```python +from langchain.text_splitter import CharacterTextSplitter +from langchain_community.document_loaders import TextLoader + +loader = TextLoader("../../data/C2/txt/蜂医.txt") +docs = loader.load() + +text_splitter = CharacterTextSplitter( + chunk_size=200, # 每个块的目标大小为100个字符 + chunk_overlap=10 # 每个块之间重叠10个字符,以缓解语义割裂 +) + +chunks = text_splitter.split_documents(docs) + +print(f"文本被切分为 {len(chunks)} 个块。\n") +print("--- 前5个块内容示例 ---") +for i, chunk in enumerate(chunks[:5]): + print("=" * 60) + # chunk 是一个 Document 对象,需要访问它的 .page_content 属性来获取文本 + print(f'块 {i+1} (长度: {len(chunk.page_content)}): "{chunk.page_content}"') +``` + +这种方法的主要优势在于实现简单、处理速度快且计算开销小。劣势在于可能会在语义边界处切断文本,影响内容的完整性和连贯性。实际的固定大小分块实现(如LangChain的 `CharacterTextSplitter`)通常会结合分隔符来减少这种问题,在段落边界处优先切分,只有在必要时才会强制按大小切断。因此,这种方法在日志分析、数据预处理等场景中仍有其应用价值。 + +### 3.2 递归字符分块 + +在前面的章节中,已经尝试了使用 `RecursiveCharacterTextSplitter` 的默认配置来处理文档分块。现在让我们深入了解 `RecursiveCharacterTextSplitter` 的实现。这种分块器通过分隔符层级递归处理,相对与固定大小分块,改善了超长文本的处理效果。 + +**算法流程**: +(1)**寻找有效分隔符**: 从分隔符列表中从前到后遍历,找到第一个在当前文本中**存在**的分隔符。如果都不存在,使用最后一个分隔符(通常是空字符串 `""`)。 + +(2)**切分与分类处理**: 使用选定的分隔符切分文本,然后遍历所有片段: +- **如果片段不超过块大小**: 暂存到 `_good_splits` 中,准备合并 +- **如果片段超过块大小**: + - 首先,将暂存的合格片段通过 `_merge_splits` 合并成块 + - 然后,检查是否还有剩余分隔符: + - **有剩余分隔符**: 递归调用 `_split_text` 继续分割 + - **无剩余分隔符**: 直接保留为超长块 + +(3)**最终处理**: 将剩余的暂存片段合并成最后的块 + +**实现细节**: +- **批处理机制**: 先收集所有合格片段(`_good_splits`),遇到超长片段时才触发合并操作。 +- **递归终止条件**: 关键在于 `if not new_separators` 判断。当分隔符用尽时(`new_separators` 为空),停止递归,直接保留超长片段。确保算法不会无限递归。 + +**与固定大小分块的关键差异**: +- 固定大小分块遇到超长段落时只能发出警告并保留。 +- 递归分块会继续使用更细粒度的分隔符(句子→单词→字符)直到满足大小要求。 + +具体示例如下: + +```python +from langchain.text_splitter import RecursiveCharacterTextSplitter +from langchain_community.document_loaders import TextLoader + +loader = TextLoader("../../data/C2/txt/蜂医.txt") +docs = loader.load() + +text_splitter = RecursiveCharacterTextSplitter( + separators=["\n\n", "\n", "。", ",", " ", ""], # 分隔符优先级 + chunk_size=200, + chunk_overlap=10, +) + +chunks = text_splitter.split_text(docs) +``` + +**分隔符配置**: +- **默认分隔符**:`["\n\n", "\n", " ", ""]` +- **多语言支持**:对于无词边界语言(中文、日文、泰文),可添加: + ```python + separators=[ + "\n\n", "\n", " ", + ".", ",", "\u200b", # 零宽空格(泰文、日文) + "\uff0c", "\u3001", # 全角逗号、表意逗号 + "\uff0e", "\u3002", # 全角句号、表意句号 + "" + ] + ``` + +**编程语言特化支持**: + +`RecursiveCharacterTextSplitter` 能够针对特定的编程语言(如Python, Java等)使用预设的、更符合代码结构的分隔符。它们通常包含语言的顶级语法结构(如类、函数定义)和次级结构(如控制流语句),以实现更符合代码逻辑的分割。 + +```python +# 针对代码文档的优化分隔符 +splitter = RecursiveCharacterTextSplitter.from_language( + language=Language.PYTHON, # 支持Python、Java、C++等 + chunk_size=500, + chunk_overlap=50 +) +``` + +递归字符分块的原理是采用一组有层次结构的分隔符(如段落、句子、单词)进行递归分割,旨在有效平衡语义完整性与块大小控制。在 `RecursiveCharacterTextSplitter` 的实现中,该分块器首先尝试使用最高优先级的分隔符(如段落标记)来切分文本。如果切分后的块仍然过大,会继续对这个大块应用下一优先级分隔符(如句号),如此循环往复,直到块满足大小限制。这种分层处理的机制,能够在尽可能保持高级语义结构完整性的同时,有效控制块大小。 + +### 3.3 语义分块 + +语义分块(Semantic Chunking)是一种更智能的方法,这种方法不依赖于固定的字符数或预设的分隔符,而是尝试根据文本的语义内涵来切分。其核心是:**在语义主题发生显著变化的地方进行切分**。这使得每个分块都具有高度的内部语义一致性。LangChain 提供了 `langchain_experimental.text_splitter.SemanticChunker` 来实现这一功能。 + +**实现原理** + +`SemanticChunker` 的工作流程可以概括为以下几个步骤: + +(1)**句子分割 (Sentence Splitting)**:首先,使用标准的句子分割规则(例如,基于句号、问号、感叹号)将输入文本拆分成一个句子列表。 + +(2)**上下文感知嵌入 (Context-Aware Embedding)**:这是 `SemanticChunker` 的一个关键设计。该分块器不是对每个句子独立进行嵌入,而是通过 `buffer_size` 参数(默认为1)来捕捉上下文信息。对于列表中的每一个句子,这种方法会将其与前后各 `buffer_size` 个句子组合起来,然后对这个临时的、更长的组合文本进行嵌入。这样,每个句子最终得到的嵌入向量就融入了其上下文的语义。 + +(3)**计算语义距离 (Distance Calculation)**:计算每对**相邻**句子的嵌入向量之间的余弦距离。这个距离值量化了两个句子之间的语义差异——距离越大,表示语义关联越弱,跳跃越明显。 + +(4)**识别断点 (Breakpoint Identification)**:`SemanticChunker` 会分析所有计算出的距离值,并根据一个统计方法(默认为 `percentile`)来确定一个动态阈值。例如,它可能会将所有距离中第95百分位的值作为切分阈值。所有距离大于此阈值的点,都被识别为语义上的“断点”。 + +(5)**合并成块 (Merging into Chunks)**:最后,根据识别出的所有断点位置,将原始的句子序列进行切分,并将每个切分后的部分内的所有句子合并起来,形成一个最终的、语义连贯的文本块。 + +**断点识别方法 (`breakpoint_threshold_type`)** + +如何定义“显著的语义跳跃”是语义分块的关键。`SemanticChunker` 提供了几种基于统计的方法来识别断点: + +- `percentile` (百分位法 - **默认方法**): + - **逻辑**: 计算所有相邻句子的语义差异值,并将这些差异值进行排序。当一个差异值超过某个百分位阈值时,就认为该差异值是一个断点。 + - **参数**: `breakpoint_threshold_amount` (默认为 `95`),表示使用第95个百分位作为阈值。这意味着,只有最显著的5%的语义差异点会被选为切分点。 + +- `standard_deviation` (标准差法): + - **逻辑**: 计算所有差异值的平均值和标准差。当一个差异值超过“平均值 + N * 标准差”时,被视为异常高的跳跃,即断点。 + - **参数**: `breakpoint_threshold_amount` (默认为 `3`),表示使用3倍标准差作为阈值。 + +- `interquartile` (四分位距法): + - **逻辑**: 使用统计学中的四分位距(IQR)来识别异常值。当一个差异值超过 `Q3 + N * IQR` 时,被视为断点。 + - **参数**: `breakpoint_threshold_amount` (默认为 `1.5`),表示使用1.5倍的IQR。 + +- `gradient` (梯度法): + - **逻辑**: 这是一种更复杂的方法。它首先计算差异值的变化率(梯度),然后对梯度应用百分位法。对于那些句子间语义联系紧密、差异值普遍较低的文本(如法律、医疗文档)特别有效,因为这种方法能更好地捕捉到语义变化的“拐点”。 + - **参数**: `breakpoint_threshold_amount` (默认为 `95`)。 + +**具体示例如下** + +```python +import os +## os.environ["HF_ENDPOINT"] = "https://hf-mirror.com" +from langchain_experimental.text_splitter import SemanticChunker +from langchain_community.embeddings import HuggingFaceEmbeddings +from langchain_community.document_loaders import TextLoader + +embeddings = HuggingFaceEmbeddings( + model_name="BAAI/bge-small-zh-v1.5", + model_kwargs={'device': 'cpu'}, + encode_kwargs={'normalize_embeddings': True} +) + +# 初始化 SemanticChunker +text_splitter = SemanticChunker( + embeddings, + breakpoint_threshold_type="percentile" # 断点识别方法 +) + +loader = TextLoader("../../data/C2/txt/蜂医.txt") +documents = loader.load() + +docs = text_splitter.split_documents(documents) +``` + +### 3.4 基于文档结构的分块 + +对于具有明确结构标记的文档格式(如Markdown、HTML、LaTex),可以利用这些标记来实现更智能、更符合逻辑的分割。 + +#### 以 Markdown 结构分块为例 + +针对结构清晰的 Markdown 文档,利用其标题层级进行分块是一种高效且保留了丰富语义的方法。LangChain 提供了 `MarkdownHeaderTextSplitter` 来处理。 + +- **实现原理**: 该分块器的主要逻辑是“先按标题分组,再按需细分”。 + 1. **定义分割规则**: 用户首先需要提供一个标题层级的映射关系,例如 `[ ("#", "Header 1"), ("##", "Header 2") ]`,告诉分块器 `#` 是一级标题,`##` 是二级标题。 + 2. **内容聚合**: 分块器会遍历整个文档,将每个标题下的所有内容(直到下一个同级或更高级别的标题出现前)聚合在一起。每个聚合后的内容块都会被赋予一个包含其完整标题路径的元数据。 + +- **元数据注入的优势**: 这是此方法的主要特点。例如,对于一篇关于机器学习的文章,某个段落可能位于“第三章:模型评估”下的“3.2节:评估指标”中。经过分割后,这个段落形成的文本块,其元数据就会是 `{"Header 1": "第三章:模型评估", "Header 2": "3.2节:评估指标"}`。这种元数据为每个块提供了精确的“地址”,极大地增强了上下文的准确性,让大模型能更好地理解信息片段的来源和背景。 + +- **局限性与组合使用**: 单纯按标题分割可能会导致一个问题:某个章节下的内容可能非常长,远超模型能处理的上下文窗口。为了解决这个问题,`MarkdownHeaderTextSplitter` 可以与其它分块器(如 `RecursiveCharacterTextSplitter`)**组合使用**。具体流程是: + - 第一步,使用 `MarkdownHeaderTextSplitter` 将文档按标题分割成若干个大的、带有元数据的逻辑块。 + - 第二步,对这些逻辑块再应用 `RecursiveCharacterTextSplitter`,将其进一步切分为符合 `chunk_size` 要求的小块。由于这个过程是在第一步之后进行的,所有最终生成的小块都会**继承**来自第一步的标题元数据。 + +- **RAG应用优势**: 这种两阶段的分块方法,既保留了文档的宏观逻辑结构(通过元数据),又确保了每个块的大小适中,是处理结构化文档进行RAG的理想方案。 + +## 四、其他开源框架中的分块策略 + +### 4.1 Unstructured:基于文档元素的智能分块 + +`Unstructured`是一个强大的文档处理工具,同样提供了实用的[分块功能](https://docs.unstructured.io/open-source/core-functionality/chunking)。 + +(1)**分区 (Partitioning)**: 这是一个重要功能,负责将原始文档(如PDF、HTML)解析成一系列结构化的“元素”(Elements)。每个元素都带有语义标签,如 `Title` (标题)、`NarrativeText` (叙述文本)、`ListItem` (列表项) 等。这个过程本身就完成了对文档的深度理解和结构化。 + +(2)**分块 (Chunking)**: 该功能建立在**分区**的结果之上。分块功能不是对纯文本进行操作,而是将分区产生的“元素”列表作为输入,进行智能组合。Unstructured 提供了两种主要的分块方法: +- **`basic`**: 这是默认方法。这种方法会连续地组合文档元素(如段落、列表项),直到达到 `max_characters` 上限,尽可能地填满每个块。如果单个元素超过上限,则会对其进行文本分割。 +- **`by_title`**: 该方法在 `basic` 方法的基础上,增加了对“章节”的感知。该方法将 `Title` 元素视为一个新章节的开始,并强制在此处开始一个新的块,确保同一个块内不会包含来自不同章节的内容。这在处理报告、书籍等结构化文档时非常有用,效果类似于 LangChain 的 `MarkdownHeaderTextSplitter`,但适用范围更广。 + +Unstructured 允许将分块作为分区的一个参数在单次调用中完成,也支持在分区之后作为一个独立的步骤来执行分块。这种“先理解、后分割”的策略,使得 Unstructured 能在最大程度上保留文档的原始语义结构,特别是在处理版式复杂的文档时,优势尤为明显。 + +### 4.2 LlamaIndex:面向节点的解析与转换 + +[LlamaIndex](https://docs.llamaindex.ai/en/stable/module_guides/loading/node_parsers/modules/) 将数据处理流程抽象为对“**节点(Node)**”的操作。文档被加载后,首先会被解析成一系列的“节点”,分块只是节点转换(Transformation)中的一环。 + +LlamaIndex 的分块体系有以下特点: + +(1)**丰富的节点解析器 (Node Parser)**: LlamaIndex 提供了大量针对特定数据格式和方法的节点解析器,可以大致分为几类: +- **结构感知型**: 如 `MarkdownNodeParser`, `JSONNodeParser`, `CodeSplitter` 等,能理解并根据源文件的结构(如Markdown标题、代码函数)进行切分。 +- **语义感知型**: + - `SemanticSplitterNodeParser`: 与 LangChain 的 `SemanticChunker` 类似,这种解析器使用嵌入模型来检测句子之间的语义“断点”,在语义连续性明显减弱的地方切开,从而让每个 chunk 内部尽量连贯。 + - `SentenceWindowNodeParser`: 这是一种巧妙的方法。该方法将文档切分成单个的句子,但在每个句子节点(Node)的元数据中,会存储其前后相邻的N个句子(即“窗口”)。这使得在检索时,可以先用单个句子的嵌入进行精确匹配,然后将包含上下文“窗口”的完整文本送给LLM,极大地提升了上下文的质量。 +- **常规型**: 如 `TokenTextSplitter`, `SentenceSplitter` 等,提供基于Token数量或句子边界的常规切分方法。 + +(2)**灵活的转换流水线**: 用户可以构建一个灵活的流水线,例如先用 `MarkdownNodeParser` 按章节切分文档,再对每个章节节点应用 `SentenceSplitter` 进行更细粒度的句子级切分。每个节点都携带丰富的元数据,记录着其来源和上下文关系。 + +(3)**良好的互操作性**: LlamaIndex 提供了 `LangchainNodeParser`,可以方便地将任何 LangChain 的 `TextSplitter` 封装成 LlamaIndex 的节点解析器,无缝集成到其处理流程中。 + +### 4.3 ChunkViz:简易的可视化分块工具 + +在本文开头部分展示的分块图就是通过 [**ChunkViz**](https://chunkviz.up.railway.app/) 生成的。可以将你的文档、分块配置作为输入,用不同的颜色块展示每个 chunk 的边界和重叠部分,方便快速理解分块逻辑。 + +## 参考文献 + +[^1]: [Nelson F. Liu, et al. (2023). *Lost in the Middle: How Language Models Use Long Contexts*](https://arxiv.org/abs/2307.03172). diff --git a/docs/chapter2/images/2_1_1.png b/docs/chapter2/images/2_1_1.png new file mode 100644 index 0000000..54c34a4 Binary files /dev/null and b/docs/chapter2/images/2_1_1.png differ diff --git a/docs/chapter2/images/2_2_1.webp b/docs/chapter2/images/2_2_1.webp new file mode 100644 index 0000000..301a473 Binary files /dev/null and b/docs/chapter2/images/2_2_1.webp differ diff --git a/docs/chapter3/06_vector_embedding.md b/docs/chapter3/06_vector_embedding.md new file mode 100644 index 0000000..8691f63 --- /dev/null +++ b/docs/chapter3/06_vector_embedding.md @@ -0,0 +1,163 @@ +# 第一节 向量嵌入 + +## 一、向量嵌入基础 + +### 1.1 基础概念 + +#### 1.1.1 什么是 Embedding + +向量嵌入(Embedding)是一种将真实世界中复杂、高维的数据对象(如文本、图像、音频、视频等)转换为数学上易于处理的、低维、稠密的连续数值向量的技术。 + +想象一下,我们将每一个词、每一段话、每一张图片都放在一个巨大的多维空间里,并给它一个独一无二的坐标。这个坐标就是一个向量,它“嵌入”了原始数据的所有关键信息。这个过程,就是 Embedding。 + +- **数据对象**:任何信息,如文本“你好世界”,或一张猫的图片。 +- **Embedding 模型**:一个深度学习模型,负责接收数据对象并进行转换。 +- **输出向量**:一个固定长度的一维数组,例如 `[0.16, 0.29, -0.88, ...]`。这个向量的维度(长度)通常在几百到几千之间。 + +![Embedding 过程示意图](./images/3_1_1.webp) + +#### 1.1.2 向量空间的语义表示 + +Embedding 的真正意义在于,它产生的向量不是随机数值的堆砌,而是对数据**语义**的数学编码。 + +- **核心原则**:在 Embedding 构建的向量空间中,语义上相似的对象,其对应的向量在空间中的距离会更近;而语义上不相关的对象,它们的向量距离会更远。 +- **关键度量**:我们通常使用以下数学方法来衡量向量间的“距离”或“相似度”: + - **余弦相似度 (Cosine Similarity)** :计算两个向量夹角的余弦值。值越接近 1,代表方向越一致,语义越相似。这是最常用的度量方式。 + - **点积 (Dot Product)** :计算两个向量的乘积和。在向量归一化后,点积等价于余弦相似度。 + - **欧氏距离 (Euclidean Distance)** :计算两个向量在空间中的直线距离。距离越小,语义越相似。 + +### 1.2 Embedding 在 RAG 中的作用 + +在RAG流程中,Embedding 扮演着无可替代的重要角色。 + +#### 1.2.1 语义检索的基础 + +RAG 的“检索”环节通常以基于 Embedding 的语义搜索为核心。通用流程如下: +(1)**离线索引构建**:将知识库内文档切分后,使用 Embedding 模型将每个文档块(Chunk)转换为向量,存入专门的向量数据库中。 + +(2)**在线查询检索**:当用户提出问题时,使用**同一个** Embedding 模型将用户的问题也转换为一个向量。 + +(3)**相似度计算**:在向量数据库中,计算“问题向量”与所有“文档块向量”的相似度。 + +(4)**召回上下文**:选取相似度最高的 Top-K 个文档块,作为补充的上下文信息,与原始问题一同送给大语言模型(LLM)生成最终答案。 + +#### 1.2.2 决定检索质量的关键 + +Embedding 的质量直接决定了 RAG 检索召回内容的准确性与相关性。一个优秀的 Embedding 模型能够精准捕捉问题和文档之间的深层语义联系,即使用户的提问和原文的表述不完全一致。反之,一个劣质的 Embedding 模型可能会因为无法理解语义而召回不相关或错误的信息,从而“污染”提供给 LLM 的上下文,导致最终生成的答案质量低下。 + +## 二、Embedding 技术发展 + +Embedding 技术的发展与自然语言处理(NLP)的进步紧密相连,尤其是在 RAG 框架出现后,对嵌入技术提出了新的要求。其演进路径大致可分为以下几个关键阶段。 + +### 2.1 静态词嵌入:上下文无关的表示 + +- **代表模型**:Word2Vec (2013), GloVe (2014) +- **主要原理**:为词汇表中的每个单词生成一个固定的、与上下文无关的向量。例如,`Word2Vec` 通过 Skip-gram 和 CBOW 架构,利用局部上下文窗口学习词向量,并验证了向量运算的语义能力(如 `国王 - 男人 + 女人 ≈ 王后`)。`GloVe` 则融合了全局词-词共现矩阵的统计信息。 +- **局限性**:无法处理一词多义问题。在“苹果公司发布了新手机”和“我吃了一个苹果”中,“苹果”的词向量是完全相同的,这限制了其在复杂语境下的语义表达能力。 + +### 2.2 动态上下文嵌入 + +2017年,`Transformer` 架构的诞生带来了自注意力机制(Self-Attention),它允许模型在生成一个词的向量时,动态地考虑句子中所有其他词的影响。基于此,2018年 `BERT` 模型利用 `Transformer` 的编码器,通过掩码语言模型(MLM)等自监督任务进行预训练,生成了深度上下文相关的嵌入。同一个词在不同语境中会生成不同的向量,这有效解决了静态嵌入的一词多义难题。 + +### 2.3 RAG 对嵌入技术的新要求 + +在开篇我们就提到了 RAG 框架的提出[^1],是为了解决大型语言模型 **知识固化**(内部知识难以更新)和 **幻觉**(生成的内容可能不符合事实且无法溯源)的问题。它通过“检索-生成”范式,动态地为 LLM 注入外部知识。这一过程的核心是 **语义检索**,很大程度上依赖于高质量的向量嵌入。 + +后续 RAG 的兴起对嵌入技术提出了更高、更具体的要求: + +- **领域自适应能力**:通用的嵌入模型在专业领域(如法律、医疗)往往表现不佳,这就要求嵌入模型具备领域自适应的能力,能够通过微调或使用指令(如 INSTRUCTOR 模型)来适应特定领域的术语和语义。 +- **多粒度与多模态支持**:RAG 系统需要处理的不仅仅是短句,还可能包括长文档、代码,甚至是图像和表格。这就要求嵌入模型能够处理不同长度和类型的输入数据。 +- **检索效率与混合检索**:嵌入向量的维度和模型大小直接影响存储成本和检索速度。同时,为了结合语义相似性(密集检索)和关键词匹配(稀疏检索)的优点,支持混合检索的嵌入模型(如 BGE-M3)应运而生,在某些任务中成为提升召回率的关键。 + +## 三、嵌入模型训练原理 + +了解了嵌入模型的发展,我们来简单探究一下当前主流的嵌入模型(通常是基于 `BERT` 的变体)是如何通过训练获得强大的语义理解能力的。 + +现代嵌入模型的核心通常是 Transformer 的编码器(Encoder)部分,`BERT` 就是其中的典型代表。它通过堆叠多个 `Transformer Encoder` 层来构建一个深度的双向表示学习网络。 + +### 3.1 主要训练任务 + +BERT 的成功很大程度上归功于 **自监督学习** 策略,它允许模型从海量的、无标注的文本数据中学习知识。 + +#### 任务一:掩码语言模型 (Masked Language Model, MLM) + +- **过程**: + - 随机地将输入句子中 15% 的词元(Token)替换为一个特殊的 `[MASK]` 标记。 + - 让模型去预测这些被遮盖住的原始词元是什么。 +- **目标**:通过这个任务,模型被迫学习每个词元与其上下文之间的关系,从而掌握深层次的语境语义。 + +#### 任务二:下一句预测 (Next Sentence Prediction, NSP) + +- **过程**: + - 构造训练样本,每个样本包含两个句子 A 和 B。 + - 其中 50% 的样本,B 是 A 的真实下一句(IsNext);另外 50% 的样本,B 是从语料库中随机抽取的句子(NotNext)。 + - 让模型判断 B 是否是 A 的下一句。 +- **目标**:这个任务让模型学习句子与句子之间的逻辑关系、连贯性和主题相关性。 +- **重要说明**:后续的研究(如 RoBERTa)发现[^2],NSP 任务可能过于简单,甚至会损害模型性能。因此,许多现代的预训练模型(如 RoBERTa、SBERT)在预训练阶段移除了 NSP。 + +> 更多细节可查看 [BERT 架构及应用](https://github.com/datawhalechina/base-nlp/blob/main/docs/chapter5/13_Bert.md) + +### 3.2 效果增强策略 + +虽然 MLM 和 NSP 赋予了模型强大的基础语义理解能力,但为了在检索任务中表现更佳,现代嵌入模型通常会引入更具针对性的训练策略。 + +- **度量学习 (Metric Learning)** : + - **思想**:直接以“相似度”作为优化目标。 + - **方法**:收集大量相关的文本对(例如,(问题,答案)、(新闻标题,正文))。训练的目标是优化向量空间中的**相对距离**:让“正例对”的向量表示在空间中被“拉近”,而“负例对”的向量表示被“推远”。关键在于优化排序关系,而非追求绝对的相似度值(如 1 或 0),因为过度追求极端值可能导致模型过拟合。 + +- **对比学习 (Contrastive Learning)** : + - **思想**:在向量空间中,将相似的样本“拉近”,将不相似的样本“推远”。 + - **方法**:构建一个三元组(Anchor, Positive, Negative)。其中,Anchor 和 Positive 是相关的(例如,同一个问题的两种不同问法),Anchor 和 Negative 是不相关的。训练的目标是让 `distance(Anchor, Positive)` 尽可能小,同时让 `distance(Anchor, Negative)` 尽可能大。 + +## 四、嵌入模型选型指南 + +理论已经了解,那么该如何选择最适合你项目的嵌入模型? + +### 4.1 从 MTEB 排行榜开始 + +[**MTEB (Massive Text Embedding Benchmark)**](https://huggingface.co/spaces/mteb/leaderboard) 是一个由 Hugging Face 维护的、全面的文本嵌入模型评测基准。它涵盖了分类、聚类、检索、排序等多种任务,并提供了公开的排行榜,为评估和选择嵌入模型提供了重要的参考依据。 + +![MTEB 排行榜](./images/3_1_2.webp) + +下面这张图是网站中的模型评估图像,直观地展示了在选择开源嵌入模型时需要权衡的四个核心维度: + +- **横轴 - 模型参数量 (Number of Parameters)** :代表了模型的大小。通常,参数量越大的模型(越靠右),其潜在能力越强,但对计算资源的要求也越高。 +- **纵轴 - 平均任务得分 (Mean Task Score)** :代表了模型的综合性能。这个分数是模型在分类、聚类、检索等一系列标准 NLP 任务上的平均表现。分数越高(越靠上),说明模型的通用语义理解能力越强。 +- **气泡大小 - 嵌入维度 (Embedding Size)** :代表了模型输出向量的维度。气泡越大,维度越高,理论上能编码更丰富的语义细节,但同时也会占用更多的存储和计算资源。 +- **气泡颜色 - 最大处理长度 (Max Tokens)** :代表了模型能处理的文本长度上限。颜色越深,表示模型能处理的 Token 数量越多,对长文本的适应性越好。 + +![MTEB 排行榜多维度评估示意图](./images/3_1_3.webp) + +MTEB 榜单可以帮助我们快速筛选掉大量不合适的模型。但需要注意,榜单上的得分是在通用数据集上评测的,可能无法完全反映模型在你特定业务场景下的表现。 + +### 4.2 关键评估维度 + +在查看榜单时,除了分数,还需要关注以下几个关键维度: + +- **任务 (Task)** :对于 RAG 应用,需要重点关注模型在 `Retrieval` (检索) 任务下的排名。 +- **语言 (Language)** :模型是否支持你的业务数据所使用的语言?对于中文 RAG,应选择明确支持中文或多语言的模型。 +- **模型大小 (Size)** :模型越大,通常性能越好,但对硬件(显存)的要求也越高,推理速度也越慢。需要根据你的部署环境和性能要求来权衡。 +- **维度 (Dimensions)** :向量维度越高,能编码的信息越丰富,但也会占用更多的存储空间和计算资源。 +- **最大 Token 数 (Max Tokens)** :这决定了模型能处理的文本长度上限。这个参数是你设计文本分块(Chunking)策略时必须考虑的重要依据,块大小不应超过此限制。 +- **得分与机构 (Score & Publisher)** :结合模型的得分排名和其发布机构的声誉进行初步筛选。知名机构发布的模型通常质量更有保障。 +- **成本 (Cost)** :如果是使用 API 服务的模型,需要考虑其调用成本;如果是自部署开源模型,则需要评估其对硬件资源的消耗(如显存、内存)以及带来的运维成本。 + +### 4.3 迭代测试与优化 + +> 不要只依赖公开榜单做最终决定。 + +(1)**确定基线 (Baseline)** :根据上述维度,选择几个符合要求的模型作为你的初始基准模型。 + +(2)**构建私有评测集** :根据真实业务数据,手动创建一批高质量的评测样本,每个样本包含一个典型用户问题和它对应的标准答案(或最相关的文档块)。 + +(3)**迭代优化** : + - 使用基线模型在你的私有评测集上运行,评估其召回的准确率和相关性。 + - 如果效果不理想,可以尝试更换模型,或者调整 RAG 流程的其他环节(如文本分块策略)。 + - 通过几轮的对比测试和迭代优化,最终选出在你的特定场景下表现最佳的那个“心仪”模型。 + + +## 参考文献 + +[^1]: [Lewis et al. (2020). *Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks*](https://arxiv.org/abs/2005.11401) + +[^2]: [*RoBERTa: A Modified BERT Model for NLP*](https://www.comet.com/site/blog/roberta-a-modified-bert-model-for-nlp/) diff --git a/docs/chapter3/07_multimodal_embedding.md b/docs/chapter3/07_multimodal_embedding.md new file mode 100644 index 0000000..7c24f47 --- /dev/null +++ b/docs/chapter3/07_multimodal_embedding.md @@ -0,0 +1,124 @@ +# 第二节 多模态嵌入 + +现代 AI 的一项重要突破,是将简单的词向量发展成了能统一理解图文、音视频的复杂系统。这一发展建立在**注意力机制、Transformer 架构和对比学习**等关键技术之上,它们解决了在共享向量空间中对齐不同数据模态的核心挑战。其发展环环相扣:Word2Vec 为 BERT 的上下文理解铺路,而 BERT 又为 CLIP 等模型的跨模态能力奠定了基础。 + +## 一、为什么需要多模态嵌入? + +前面的章节介绍了如何为文本创建向量嵌入。然而,仅有文本的世界是不完整的。现实世界的信息是多模态的,包含图像、音频、视频等。传统的文本嵌入无法理解“那张有红色汽车的图片”这样的查询,因为文本向量和图像向量处于相互隔离的空间,存在一堵“模态墙”。 + +**多模态嵌入 (Multimodal Embedding)** 的目标正是为了打破这堵墙。其目的是将不同类型的数据(如图像和文本)映射到**同一个共享的向量空间**。在这个统一的空间里,一段描述“一只奔跑的狗”的文字,其向量会非常接近一张真实小狗奔跑的图片向量。 + +实现这一目标的关键,在于解决 **跨模态对齐 (Cross-modal Alignment)** 的挑战。以对比学习、视觉 Transformer (ViT) 等技术为代表的突破,让模型能够学习到不同模态数据之间的语义关联,最终催生了像 CLIP 这样的模型。 + +## 二、CLIP 模型浅析 + +在图文多模态领域,OpenAI 的 **CLIP (Contrastive Language-Image Pre-training)** 是一个很有影响力的模型,它为多模态嵌入定义了一个有效的范式。 + +CLIP 的架构清晰简洁。它采用**双编码器架构 (Dual-Encoder Architecture)**,包含一个图像编码器和一个文本编码器,分别将图像和文本映射到同一个共享的向量空间中。 + +![CLIP Architecture](./images/3_2_1.webp) +*图:CLIP 的工作流程。(1) 通过对比学习训练双编码器,对齐图文向量空间。(2)和(3) 展示了如何利用该空间,通过图文相似度匹配实现零样本预测。* + +为了让这两个编码器学会“对齐”不同模态的语义,CLIP 在训练时采用了**对比学习 (Contrastive Learning)** 策略。在处理一批图文数据时,模型的目标是:最大化正确图文对的向量相似度,同时最小化所有错误配对的相似度。通过这种“拉近正例,推远负例”的方式,模型从海量数据中学会了将语义相关的图像和文本在向量空间中拉近。 + +这种大规模的对比学习赋予了 CLIP 有效的**零样本(Zero-shot)识别能力**。它能将一个传统的分类任务,转化为一个“图文检索”问题——例如,要判断一张图片是不是猫,只需计算图片向量与“a photo of a cat”文本向量的相似度即可。这使得 CLIP 无需针对特定任务进行微调,就能实现对视觉概念的泛化理解。 + +## 三、常用多模态嵌入模型(以bge-visualized-m3为例) + +虽然 CLIP 为图文预训练提供了重要基础,但多模态领域的研究迅速发展,涌现了许多针对不同目标和场景进行优化的模型。例如,BLIP 系列专注于提升细粒度的图文理解与生成能力,而 ALIGN 则证明了利用海量噪声数据进行大规模训练的有效性。 + +在众多优秀的模型中,由北京智源人工智能研究院(BAAI)开发的 **bge-visualized-m3(Visualized-BGE 的 M3 版本)** 是一个很有代表性的现代多模态嵌入模型。它是在 **BGE-M3**(文本嵌入底座)的基础上引入图像能力而来,体现了当前技术向“更统一、更全面”发展的趋势。 + +bge-visualized-m3 的核心特性也可以概括为“M3”(主要继承自其文本底座 BGE-M3): +- **多语言性 (Multi-Linguality)**:支持超过 100 种语言的文本表示,可用于跨语言的图文检索(文本侧)。 +- **多功能性 (Multi-Functionality)**:在文本检索场景下,可按需求使用密集检索(Dense Retrieval)、多向量检索(Multi-Vector Retrieval)等不同范式。 +- **多粒度性 (Multi-Granularity)**:文本侧可处理从短句到长达 8192 个 token 的长文档,覆盖更广泛的应用需求。 + +在技术架构上,bge-visualized-m3 会先用视觉编码器提取图像的 **patch token**,再将其映射到与文本同维度的“图像 token”,与文本 token 一起送入 BGE 的 Transformer 编码器进行联合建模,最终得到可用于图文检索的统一向量表示。 + +## 四、代码示例 + +### 4.1 环境准备 + +**步骤1:安装 visual_bge 模块** + +```bash +# 进入 visual_bge 目录 +cd code/C3/visual_bge + +# 安装 visual_bge 模块及其依赖 +pip install -e . + +# 返回上级目录 +cd .. +``` + +**步骤2:下载模型权重** + +```bash +# 运行模型下载脚本 +python download_model.py +``` + +模型下载脚本会自动检查 `../../models/bge/` 目录下是否存在模型文件,如果不存在则从 Hugging Face 镜像站下载。 + +### 4.2 基础示例 + +```python +import os +os.environ["HF_ENDPOINT"] = "https://hf-mirror.com" +import torch +from visual_bge.visual_bge.modeling import Visualized_BGE + +model = Visualized_BGE(model_name_bge="BAAI/bge-base-en-v1.5", + model_weight="../../models/bge/Visualized_base_en_v1.5.pth") +model.eval() + +with torch.no_grad(): + text_emb = model.encode(text="datawhale开源组织的logo") + img_emb_1 = model.encode(image="../../data/C3/imgs/datawhale01.png") + multi_emb_1 = model.encode(image="../../data/C3/imgs/datawhale01.png", text="datawhale开源组织的logo") + img_emb_2 = model.encode(image="../../data/C3/imgs/datawhale02.png") + multi_emb_2 = model.encode(image="../../data/C3/imgs/datawhale02.png", text="datawhale开源组织的logo") + +# 计算相似度 +sim_1 = img_emb_1 @ img_emb_2.T +sim_2 = img_emb_1 @ multi_emb_1.T +sim_3 = text_emb @ multi_emb_1.T +sim_4 = multi_emb_1 @ multi_emb_2.T + +print("=== 相似度计算结果 ===") +print(f"纯图像 vs 纯图像: {sim_1}") +print(f"图文结合1 vs 纯图像: {sim_2}") +print(f"图文结合1 vs 纯文本: {sim_3}") +print(f"图文结合1 vs 图文结合2: {sim_4}") +``` + +**代码解读:** + +- **模型架构**: `Visualized_BGE` 是通过将图像token嵌入集成到BGE文本嵌入框架中构建的通用多模态嵌入模型,具备处理超越纯文本的多模态数据的灵活性。 +- **模型参数**: + - `model_name_bge`: 指定底层BGE文本嵌入模型,继承其强大的文本表示能力。 + - `model_weight`: Visual BGE的预训练权重文件,包含视觉编码器参数。 +- **多模态编码能力**: Visual BGE提供了编码多模态数据的多样性,支持纯文本、纯图像或图文组合的格式: + - **纯文本编码**: 保持原始BGE模型的强大文本嵌入能力。 + - **纯图像编码**: 使用基于EVA-CLIP的视觉编码器处理图像。 + - **图文联合编码**: 将图像和文本特征融合到统一的向量空间。 +- **应用场景**: 主要用于混合模态检索任务,包括多模态知识检索、组合图像检索、多模态查询的知识检索等。 +- **相似度计算**: 使用矩阵乘法计算余弦相似度,所有嵌入向量都被标准化到单位长度,确保相似度值在合理范围内。 + +**运行结果:** + +```bash +=== 相似度计算结果 === +纯图像 vs 纯图像: tensor([[0.8318]]) +图文结合1 vs 纯图像: tensor([[0.8291]]) +图文结合1 vs 纯文本: tensor([[0.7627]]) +图文结合1 vs 图文结合2: tensor([[0.9058]]) +``` + +> [完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C3/01_bge_visualized.py) + +## 练习 + +尝试把代码中的部分文本替换一下,比如将`datawhale开源组织的logo`替换为`blue whale`看看结果有什么不同。 \ No newline at end of file diff --git a/docs/chapter3/08_vector_db.md b/docs/chapter3/08_vector_db.md new file mode 100644 index 0000000..3059feb --- /dev/null +++ b/docs/chapter3/08_vector_db.md @@ -0,0 +1,162 @@ +# 第三节 向量数据库 + +## 一、向量数据库的作用 + +在前面我们学习了如何使用嵌入模型将文本、图像等非结构化数据转换为高维向量。这些向量是 RAG 系统能够进行语义理解的基础。然而,当向量数量从几百个增长到数百万甚至数十亿时,一个核心问题随之而来:**如何快速、准确地从海量向量中找到与用户查询最相似的那几个?** + +### 1.1 向量数据库主要功能 + +向量数据库的核心价值在于其高效处理海量高维向量的能力。其主要功能可以概括为以下几点: + +- **高效的相似性搜索**:这是向量数据库最重要的功能。它利用专门的索引技术(如 HNSW, IVF),能够在数十亿级别的向量中实现毫秒级的近似最近邻(ANN)查询,快速找到与给定查询最相似的数据。 + +- **高维数据存储与管理**:专门为存储高维向量(通常维度成百上千)而优化,支持对向量数据进行增、删、改、查等基本操作。 + +- **丰富的查询能力**:除了基本的相似性搜索,还支持按标量字段过滤查询(例如,在搜索相似图片的同时,指定`年份 > 2023`)、范围查询和聚类分析等,满足复杂业务需求。 + +- **可扩展与高可用**:现代向量数据库通常采用分布式架构,具备良好的水平扩展能力和容错性,能够通过增加节点来应对数据量的增长,并确保服务的稳定可靠。 + +- **数据与模型生态集成**:与主流的 AI 框架(如 LangChain, LlamaIndex)和机器学习工作流无缝集成,简化了从模型训练到向量检索的应用开发流程。 + +### 1.2 向量数据库 vs 传统数据库 + +传统的数据库(如 MySQL)擅长处理结构化数据的精确匹配查询(例如,`WHERE age = 25`),但它们并非为处理高维向量的相似性搜索而设计的。在庞大的向量集合中进行暴力、线性的相似度计算,其计算成本和时间延迟无法接受。**向量数据库 (Vector Database)** 很好的解决了这一问题,它是一种专门设计用于高效存储、管理和查询高维向量的数据库系统。在 RAG 流程中,它扮演着“知识库”的角色,是连接数据与大语言模型的关键桥梁。 + +向量数据库与传统数据库的主要差异如下: + +| **维度** | **向量数据库** | **传统数据库 (RDBMS)** | +| :--- | :--- | :--- | +| **核心数据类型** | 高维向量 (Embeddings) | 结构化数据 (文本、数字、日期) | +| **查询方式** | **相似性搜索** (ANN) | **精确匹配** | +| **索引机制** | HNSW, IVF, LSH 等 ANN 索引 | B-Tree, Hash Index | +| **主要应用场景** | AI 应用、RAG、推荐系统、图像/语音识别 | 业务系统 (ERP, CRM)、金融交易、数据报表 | +| **数据规模** | 轻松应对千亿级向量 | 通常在千万到亿级行数据,更大规模需复杂分库分表 | +| **性能特点** | 高维数据检索性能极高,计算密集型 | 结构化数据查询快,高维数据查询性能呈指数级下降 | +| **一致性** | 通常为最终一致性 | 强一致性 (ACID 事务) | + +向量数据库和传统数据库并非相互替代的关系,而是**互补关系**。在构建现代 AI 应用时,通常会将两者结合使用:利用传统数据库存储业务元数据和结构化信息,而向量数据库则专门负责处理和检索由 AI 模型产生的海量向量数据。 + +## 二、工作原理 + +向量数据库的核心是高效处理高维向量的相似性搜索。向量是一组有序的数值,可以表示文本、图像、音频等复杂数据的特征或属性。在 RAG 系统中,向量一般通过嵌入模型将原始数据转换为高维向量表示,比如上一节的图文示例。向量数据库通常采用四层架构,通过存储层、索引层、查询层和服务层的协同工作来实现高效相似性搜索,其中存储层负责存储向量数据和元数据,优化存储效率并支持分布式存储;索引层维护索引算法(HNSW、LSH、PQ等),负责索引的创建与优化,并支持索引调整;查询层处理查询请求,支持混合查询并实现查询优化;服务层管理客户端连接,提供监控和日志能力,并实现安全管理。 + +主要技术手段包括: +- **基于树的方法**:如 Annoy 使用的随机投影树,通过树形结构实现对数复杂度的搜索 +- **基于哈希的方法**:如 LSH(局部敏感哈希),通过哈希函数将相似向量映射到同一“桶” +- **基于图的方法**:如 HNSW(分层可导航小世界图),通过多层邻近图结构实现快速搜索 +- **基于量化的方法**:如 Faiss 的 IVF 和 PQ,通过聚类和量化压缩向量 + +## 三、主流向量数据库介绍 + +![向量数据库分类图](./images/3_3_1.webp) + +当前主流的向量数据库产品包括: + +[ **Pinecone** ](https://www.pinecone.io/)是一款完全托管的向量数据库服务,采用Serverless架构设计。它提供存储计算分离、自动扩展和负载均衡等企业级特性,并保证99.95%的SLA。Pinecone支持多种语言SDK,提供极高可用性和低延迟搜索(<100ms),特别适合企业级生产环境、高并发场景和大规模部署。 + +[ **Milvus** ](https://github.com/milvus-io/milvus)是一款开源的分布式向量数据库,采用分布式架构设计,支持GPU加速和多种索引算法。它能够处理亿级向量检索,提供高性能GPU加速和完善的生态系统。Milvus特别适合大规模部署、高性能要求的场景,以及需要自定义开发的开源项目。 + +[ **Qdrant** ](https://github.com/qdrant/qdrant)是一款高性能的开源向量数据库,采用Rust开发,支持二进制量化技术。它提供多种索引策略和向量混合搜索功能,能够实现极高的性能(RPS>4000)和低延迟搜索。Qdrant特别适合性能敏感应用、高并发场景以及中小规模部署。 + +[ **Weaviate** ](https://github.com/weaviate/weaviate)是一款支持GraphQL的AI集成向量数据库,提供20+AI模块和多模态支持。它采用GraphQL API设计,支持RAG优化,特别适合AI开发、多模态处理和快速开发场景。Weaviate具有活跃的社区支持和易于集成的特点。 + +[ **Chroma** ](https://github.com/chroma-core/chroma)是一款轻量级的开源向量数据库,采用本地优先设计,无依赖。它提供零配置安装、本地运行和低资源消耗等特性,特别适合原型开发、教育培训和小规模应用。Chroma的部署简单,适合快速原型开发。 + +**选择建议**: +- **新手入门/小型项目**:从 `ChromaDB` 或 `FAISS` 开始是最佳选择。它们与 LangChain/LlamaIndex 紧密集成,几行代码就能运行,且能满足基本的存储和检索需求。 +- **生产环境/大规模应用**:当数据量超过百万级,或需要高并发、实时更新、复杂元数据过滤时,应考虑更专业的解决方案,如 `Milvus`、`Weaviate` 或云服务 `Pinecone`。 + +## 四、本地向量存储:以 FAISS 为例 + +FAISS (Facebook AI Similarity Search) 是一个由 Facebook AI Research 开发的高性能库,专门用于高效的相似性搜索和密集向量聚类。当与 LangChain 结合使用时,它可以作为一个强大的本地向量存储方案,非常适合快速原型设计和中小型应用。 + +与 ChromaDB 等数据库不同,FAISS 本质上是一个算法库,它将索引直接保存为本地文件(一个 `.faiss` 索引文件和一个 `.pkl` 映射文件),而非运行一个数据库服务。这种方式轻量且高效。 + +### 4.1 环境准备 + +在开始之前,请确保已安装所有必需的库: + +> 当前requirements.txt安装的 `faiss-cpu` 是 CPU 版本。如果你的机器有 GPU,可以安装 `faiss-gpu` 以获得更好的性能。 + +### 4.2 基础示例(FAISS) + +下面的代码演示了使用 LangChain 和 FAISS 完成一个完整的“创建 -> 保存 -> 加载 -> 查询”流程。 + +```python +from langchain_community.vectorstores import FAISS +from langchain_community.embeddings import HuggingFaceEmbeddings +from langchain_core.documents import Document + +# 1. 示例文本和嵌入模型 +texts = [ + "张三是法外狂徒", + "FAISS是一个用于高效相似性搜索和密集向量聚类的库。", + "LangChain是一个用于开发由语言模型驱动的应用程序的框架。" +] +docs = [Document(page_content=t) for t in texts] +embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5") + +# 2. 创建向量存储并保存到本地 +vectorstore = FAISS.from_documents(docs, embeddings) + +local_faiss_path = "./faiss_index_store" +vectorstore.save_local(local_faiss_path) + +print(f"FAISS index has been saved to {local_faiss_path}") + +# 3. 加载索引并执行查询 +# 加载时需指定相同的嵌入模型,并允许反序列化 +loaded_vectorstore = FAISS.load_local( + local_faiss_path, + embeddings, + allow_dangerous_deserialization=True +) + +# 相似性搜索 +query = "FAISS是做什么的?" +results = loaded_vectorstore.similarity_search(query, k=1) + +print(f"\n查询: '{query}'") +print("相似度最高的文档:") +for doc in results: + print(f"- {doc.page_content}") +``` +**运行结果与解读**: + +当你运行上述脚本时,会看到类似以下的输出: +```bash +FAISS index has been saved to ./faiss_index_store + +查询: 'FAISS是做什么的?' +相似度最高的文档: +- FAISS是一个用于高效相似性搜索和密集向量聚类的库。 +``` + +**索引创建实现细节**: +通过深入 LangChain 源码,可以发现索引创建是一个分层、解耦的过程,主要涉及以下几个方法的嵌套调用: + +1. **`from_documents` (封装层)**: + * 这是我们直接调用的方法。它的职责很简单:从输入的 `Document` 对象列表中提取出纯文本内容 (`page_content`) 和元数据 (`metadata`)。 + * 然后,它将这些提取出的信息传递给核心的 `from_texts` 方法。 + +2. **`from_texts` (向量化入口)**: + * 这个方法是面向用户的入口。它接收文本列表,并执行关键的第一步:调用 `embedding.embed_documents(texts)`,将所有文本批量转换为向量。 + * 完成向量化后,它并不直接处理索引构建,而是将生成的向量和其他所有信息(文本、元数据等)传递给一个内部的辅助方法 `__from`。 + +3. **`__from` (构建索引框架)**: + * 一个内部方法,负责搭建 FAISS 向量存储的“空框架”。 + * 它会根据指定的距离策略(默认为 L2 欧氏距离)初始化一个空的 FAISS 索引结构(如 `faiss.IndexFlatL2`)。 + * 同时,它也准备好了用于存储文档原文的 `docstore` 和用于连接 FAISS 索引与文档的 `index_to_docstore_id` 映射。 + * 最后,它调用另一个内部方法 `__add` 来完成数据的填充。 + +4. **`__add` (填充数据)**: + * 真正执行数据添加操作的核心。它接收到向量、文本和元数据后,执行以下关键操作: + * **添加向量**: 将向量列表转换为 FAISS 需要的 `numpy` 数组,并调用 `self.index.add(vector)` 将其批量添加到 FAISS 索引中。 + * **存储文档**: 将文本和元数据打包成 `Document` 对象,存入 `docstore`。 + * **建立映射**: 更新 `index_to_docstore_id` 字典,建立起 FAISS 内部的整数 ID(如 0, 1, 2...)到我们文档唯一 ID 的映射关系。 + + +## 练习 + +1. LlamaIndex默认会将数据存储为透明可读的JSON格式,运行[03_llamaindex_vector.py](https://github.com/datawhalechina/all-in-rag/blob/main/code/C3/03_llamaindex_vector.py)文件,查看保存的json文件内容。 +2. 新建一个代码文件实现对LlamaIndex存储数据的加载和相似性搜索。 \ No newline at end of file diff --git a/docs/chapter3/09_milvus.md b/docs/chapter3/09_milvus.md new file mode 100644 index 0000000..91570b0 --- /dev/null +++ b/docs/chapter3/09_milvus.md @@ -0,0 +1,511 @@ +# 第四节 Milvus介绍及多模态检索实践 + +## 一、简介 + +Milvus 是一个开源的、专为大规模向量相似性搜索和分析而设计的向量数据库。它诞生于 Zilliz 公司,并已成为 LF AI & Data 基金会的顶级项目,在AI领域拥有广泛的应用。 + +与 FAISS、ChromaDB 等轻量级本地存储方案不同,Milvus 从设计之初就瞄准了**生产环境**。其采用云原生架构,具备高可用、高性能、易扩展的特性,能够处理十亿、百亿甚至更大规模的向量数据。 + +**官网地址**: [https://milvus.io/](https://milvus.io/) + +**GitHub**: [https://github.com/milvus-io/milvus](https://github.com/milvus-io/milvus) + +## 二、 部署安装 + +Milvus 提供了多种部署方式,这里以 **Milvus Standalone (单机版)** 为例。 + +### 1. 环境准备 + +- **安装 Docker 与 Docker Compose**: 确保系统中已安装并正在运行 Docker 和 Docker Compose。如果你对 Docker 不熟悉,可以参考这篇详细的教程:[Docker 万字教程:从入门到掌握](https://mp.weixin.qq.com/s/u2es87JU5FNlGo3qDLY_ng)。 + +> codespace 环境自带Docker Compose无需安装 + +### 2. 下载并启动 Milvus + +在你选定的工作目录下,打开终端(Terminal)或命令行工具(PowerShell),执行以下步骤: + +**第一步:下载配置文件** + +使用以下命令下载官方的 `docker-compose.yml` 文件。这个文件定义了 Milvus Standalone 及其运行所需的两个核心依赖服务:`etcd` 用于存储元数据,`MinIO` 用于对象存储(更多架构细节请参考[官方文档](https://milvus.io/docs/architecture_overview.md))。 + +```bash +# macOS / Linux (使用 wget) +wget https://github.com/milvus-io/milvus/releases/download/v2.5.14/milvus-standalone-docker-compose.yml -O docker-compose.yml +``` + +```powershell +# Windows (使用 PowerShell) +Invoke-WebRequest -Uri "https://github.com/milvus-io/milvus/releases/download/v2.5.14/milvus-standalone-docker-compose.yml" -OutFile "docker-compose.yml" +``` + +**第二步:启动 Milvus 服务** + +在 `docker-compose.yml` 文件所在的目录中,运行以下命令以后台模式启动 Milvus: + +```bash +docker compose up -d +``` + +Docker 将会自动拉取所需的镜像并启动三个容器:`milvus-standalone`, `milvus-minio`, 和 `milvus-etcd`。这个过程可能需要几分钟,具体取决于你的网络状况。 + +### 3. 验证安装 + +可以通过以下方式验证 Milvus 是否成功启动: + +- **查看 Docker 容器**: 打开 Docker Desktop 的仪表盘 (Windows/macOS) 或在终端运行 `docker ps` 命令 (Linux),确认三个 Milvus 相关容器(`milvus-standalone`, `milvus-minio`, `milvus-etcd`)都处于 `running` 或 `up` 状态。 +- **检查服务端口**: Milvus Standalone 默认通过 `19530` 端口提供服务,这是后续代码连接时需要用到的地址。 + +### 4. 常用管理命令 + +- **停止服务**: + ```bash + docker compose down + ``` + 此命令会停止并移除容器,但保留存储的数据卷。 + +- **彻底清理 (停止并删除数据)**: + 如果想彻底删除所有数据(包括向量、元数据等),可以执行以下命令: + ```bash + docker compose down -v + ``` + +## 三、核心组件 + +### 3.1 Collection (集合) + +可以用一个图书馆的比喻来理解 Collection: + +- **Collection (集合)**: 相当于一个**图书馆**,是所有数据的顶层容器。一个 Collection 可以包含多个 Partition,每个 Partition 可以包含多个 Entity。 +- **Partition (分区)**: 相当于图书馆里的**不同区域**(如“小说区”、“科技区”),将数据物理隔离,让检索更高效。 +- **Schema (模式)**: 相当于图书馆的**图书卡片规则**,定义了每本书(数据)必须登记哪些信息(字段)。 +- **Entity (实体)**: 相当于**一本具体的书**,是数据本身。 +- **Alias (别名)**: 相当于一个**动态的推荐书单**(如“本周精选”),它可以指向某个具体的 Collection,方便应用层调用,实现数据更新时的无缝切换。 + +**Collection** 是 Milvus 中最基本的数据组织单位,类似于关系型数据库中的一张**表 (Table)**。是我们存储、管理和查询向量及相关元数据的容器。所有的数据操作,如插入、删除、查询等,都是围绕 Collection 展开的。 + +一个 Collection 由其 **Schema** 定义,并包含以下重要的子概念和特性: + +#### 3.1.1 Schema + +在创建 Collection 之前,必须先定义它的 **Schema**。 `Schema` 规定了 Collection 的数据结构,定义了其中包含的所有**字段 (Field)** 及其属性。一个设计良好的 Schema 是能够保证数据一致性并提升查询性能。 + +Schema 通常包含以下几类字段: + +- **主键字段 (Primary Key Field)**: 每个 Collection 必须有且仅有一个主键字段,用于唯一标识每一条数据(实体)。它的值必须是唯一的,通常是整数或字符串类型。 +- **向量字段 (Vector Field)**: 用于存储核心的向量数据。一个 Collection 可以有一个或多个向量字段,以满足多模态等复杂场景的需求。 +- **标量字段 (Scalar Field)**: 用于存储除向量之外的元数据,如字符串、数字、布尔值、JSON 等。这些字段可以用于过滤查询,实现更精确的检索。 + +![Schema 设计剖析](./images/3_4_1.webp) + +上图以一篇新闻文章为例,展示了一个典型的多模态、混合向量 Schema 设计。它将一篇文章拆解为:唯一的 `Article (ID)`、文本元数据(如 `Title`、`Author Info`)、图像信息(`Image URL`),并为图像和摘要内容分别生成了密集向量(`Image Embedding`, `Summary Embedding`)和稀疏向量(`Summary Sparse Embedding`)。 + +#### 3.1.2 Partition (分区) + +**Partition** 是 Collection 内部的一个逻辑划分。每个 Collection 在创建时都会有一个名为 `_default` 的默认分区。我们可以根据业务需求创建更多的分区,将数据按特定规则(如类别、日期等)存入不同分区。 + +**为什么使用分区?** + +- **提升查询性能**: 在查询时,可以指定只在一个或几个分区内进行搜索,从而大幅减少需要扫描的数据量,显著提升检索速度。 +- **数据管理**: 便于对部分数据进行批量操作,如加载/卸载特定分区到内存,或者删除整个分区的数据。 + +一个 Collection 最多可以有 1024 个分区。合理利用分区是 Milvus 性能优化的重要手段之一。 + +#### 3.1.3 Alias (别名) + +**Alias** (别名) 是为 Collection 提供的一个“昵称”。通过为一个 Collection 设置别名,我们可以在应用程序中使用这个别名来执行所有操作,而不是直接使用真实的 Collection 名称。 + +**为什么使用别名?** + +- **安全地更新数据**:想象一下,你需要对一个在线服务的 Collection 进行大规模的数据更新或重建索引。直接在原 Collection 上操作风险很高。正确的做法是: + 1. 创建一个新的 Collection (`collection_v2`) 并导入、索引好所有新数据。 + 2. 将指向旧 Collection (`collection_v1`) 的别名(例如 `my_app_collection`)原子性地切换到新 Collection (`collection_v2`) 上。 +- **代码解耦**:整个切换过程对上层应用完全透明,无需修改任何代码或重启服务,实现了数据的平滑无缝升级。 + +### 3.2 索引 (Index) + +如果说 Collection 是 Milvus 的骨架,那么**索引 (Index)** 就是其加速检索的神经系统。从宏观上看,索引本身就是一种**为了加速查询而设计的复杂数据结构**。对向量数据创建索引后,Milvus 可以极大地提升向量相似性搜索的速度,代价是会占用额外的存储和内存资源。 + +![Milvus 索引结构与工作原理](./images/3_4_2.webp) + +上图清晰地展示了 Milvus 向量索引的内部组件及其工作流程: +- **数据结构**:这是索引的骨架,定义了向量的组织方式(如 HNSW 中的图结构)。 +- **量化**(可选):数据压缩技术,通过降低向量精度来减少内存占用和加速计算。 +- **结果精炼**(可选):在找到初步候选集后,进行更精确的计算以优化最终结果。 + +Milvus 支持对标量字段和向量字段分别创建索引。 + +- **标量字段索引**:主要用于加速元数据过滤,常用的有 `INVERTED`、`BITMAP` 等。通常使用推荐的索引类型即可。 +- **向量字段索引**:这是 Milvus 的核心。选择合适的向量索引是在查询性能、召回率和内存占用之间做出权衡的艺术。 + +#### 3.2.1 主要向量索引类型 + +Milvus 提供了多种向量索引算法,以适应不同的应用场景。以下是几种最核心的类型: + +- **FLAT (精确查找)** + - **原理**:暴力搜索(Brute-force Search)。它会计算查询向量与集合中所有向量之间的实际距离,返回最精确的结果。 + - **优点**:100% 的召回率,结果最准确。 + - **缺点**:速度慢,内存占用大,不适合海量数据。 + - **适用场景**:对精度要求极高,且数据规模较小(百万级以内)的场景。 + +- **IVF 系列 (倒排文件索引)** + - **原理**:类似于书籍的目录。它首先通过聚类将所有向量分成多个“桶”(`nlist`),查询时,先找到最相似的几个“桶”,然后只在这几个桶内进行精确搜索。`IVF_FLAT`、`IVF_SQ8`、`IVF_PQ` 是其不同变体,主要区别在于是否对桶内向量进行了压缩(量化)。 + - **优点**:通过缩小搜索范围,极大地提升了检索速度,是性能和效果之间很好的平衡。 + - **缺点**:召回率不是100%,因为相关向量可能被分到了未被搜索的桶中。 + - **适用场景**:通用场景,尤其适合需要高吞吐量的大规模数据集。 + +- **HNSW (基于图的索引)** + - **原理**:构建一个多层的邻近图。查询时从最上层的稀疏图开始,快速定位到目标区域,然后在下层的密集图中进行精确搜索。 + - **优点**:检索速度极快,召回率高,尤其擅长处理高维数据和低延迟查询。 + - **缺点**:内存占用非常大,构建索引的时间也较长。 + - **适用场景**:对查询延迟有严格要求(如实时推荐、在线搜索)的场景。 + +- **DiskANN (基于磁盘的索引)** + - **原理**:一种为在 SSD 等高速磁盘上运行而优化的图索引。 + - **优点**:支持远超内存容量的海量数据集(十亿级甚至更多),同时保持较低的查询延迟。 + - **缺点**:相比纯内存索引,延迟稍高。 + - **适用场景**:数据规模巨大,无法全部加载到内存的场景。 + +#### 3.2.2 如何选择索引? + +选择索引没有唯一的“最佳答案”,需要根据业务场景在**数据规模、内存限制、查询性能和召回率**之间进行权衡。 + +| 场景 | 推荐索引 | 备注 | +| :--- | :--- | :--- | +| 数据可完全载入内存,追求低延迟 | **HNSW** | 内存占用较大,但查询性能和召回率都很优秀。 | +| 数据可完全载入内存,追求高吞吐 | **IVF_FLAT / IVF_SQ8** | 性能和资源消耗的平衡之选。 | +| 数据量巨大,无法载入内存 | **DiskANN** | 在 SSD 上性能优异,专为海量数据设计。 | +| 追求 100% 准确率,数据量不大 | **FLAT** | 暴力搜索,确保结果最精确。 | + +在实际应用中,通常需要通过测试来找到最适合自己数据和查询模式的索引类型及其参数。 + +### 3.3 检索 + +#### 3.3.1 基础向量检索 (ANN Search) + +拥有了数据容器 (Collection) 和检索引擎 (Index) 后,最后一步就是从海量数据中高效地检索信息。这是 Milvus 的核心功能之一,**近似最近邻 (Approximate Nearest Neighbor, ANN) 检索**。与需要计算全部数据的暴力检索(Brute-force Search)不同,ANN 检索利用预先构建好的索引,能够极速地从海量数据中找到与查询向量最相似的 Top-K 个结果。这是一种在速度和精度之间取得极致平衡的策略。 + +- **主要参数**: + - `anns_field`: 指定要在哪个向量字段上进行检索。 + - `data`: 传入一个或多个查询向量。 + - `limit` (或 `top_k`): 指定需要返回的最相似结果的数量。 + - `search_params`: 指定检索时使用的参数,例如距离计算方式 (`metric_type`) 和索引相关的查询参数。 + +#### 3.3.2 增强检索 + +在基础的 ANN 检索之上,Milvus 提供了多种增强检索功能,以满足更复杂的业务需求。 + +**过滤检索 (Filtered Search)** + +在实际应用中,我们很少只进行单纯的向量检索。更常见的需求是“在满足特定条件的向量中,查找最相似的结果”,这就是过滤检索。它将**向量相似性检索**与**标量字段过滤**结合在一起。 + +- **工作原理**:先根据提供的过滤表达式 (`filter`) 筛选出符合条件的实体,然后仅在这个子集内执行 ANN 检索。这极大地提高了查询的精准度。 +- **应用示例**: + - **电商**:"检索与这件红色连衣裙最相似的商品,但只看价格低于500元且有库存的。" + - **知识库**:"查找与‘人工智能’相关的文档,但只从‘技术’分类下、且发布于2023年之后的文章中寻找。" + +**范围检索 (Range Search)** + +有时我们关心的不是最相似的 Top-K 个结果,而是“所有与查询向量的相似度在特定范围内的结果”。 + +- **工作原理**:范围检索允许定义一个距离(或相似度)的阈值范围。Milvus 会返回所有与查询向量的距离落在这个范围内的实体。 +- **应用示例**: + - **人脸识别**:"查找所有与目标人脸相似度超过 0.9 的人脸",用于身份验证。 + - **异常检测**:"查找所有与正常样本向量距离过大的数据点",用于发现异常。 + +**多向量混合检索 (Hybrid Search)** + +这是 Milvus 提供的一种极其强大的高级检索模式,它允许在一个请求中同时检索**多个向量字段**,并将结果智能地融合在一起。 + +- **工作原理**: + 1. **并行检索**:应用针对不同的向量字段(如一个用于文本语义的密集向量,一个用于关键词匹配的稀疏向量,一个用于图像内容的多模态向量)分别发起 ANN 检索请求。 + 2. **结果融合 (Rerank)**:Milvus 使用一个重排策略(Reranker)将来自不同检索流的结果合并成一个统一的、更高质量的排序列表。常用的策略有 `RRFRanker`(平衡各方结果)和 `WeightedRanker`(可为特定字段结果加权)。 + +- **应用示例**: + - **多模态商品检索**:用户输入文本“安静舒适的白色耳机”,系统可以同时检索商品的**文本描述向量**和**图片内容向量**,返回最匹配的商品。 + - **增强型 RAG**: 结合**密集向量**(捕捉语义)和**稀疏向量**(精确匹配关键词),实现比单一向量更精准的文档检索效果。 + +**分组检索 (Grouping Search)** + +分组检索解决了一个常见的痛点:检索结果多样性不足。想象一下,你检索“机器学习”,返回的前10篇文章都来自同一本教科书不同章节。这显然不是理想的结果。 + +- **工作原理**:分组检索允许指定一个字段(如 `document_id`)对结果进行分组。Milvus 会在检索后,确保返回的结果中每个组(每个 `document_id`)只出现一次(或指定的次数),且返回的是该组内与查询最相似的那个实体。 +- **应用示例**: + - **视频检索**:检索“可爱的猫咪”,确保返回的视频来自不同的博主。 + - **文档检索**:检索“数据库索引”,确保返回的结果来自不同的书籍或来源。 + +通过这些灵活的检索功能组合,开发者可以构建出满足各种复杂业务需求的向量检索应用。 + +## 四、milvus多模态实践 + +在本节中,我们将通过一个完整的示例,演示如何使用 Milvus 和 Visualized-BGE 模型构建一个端到端的图文多模态检索引擎。 + +### 4.1 初始化与工具定义 + +首先导入所有必需的库,定义好模型路径、数据目录等常量。为了代码的整洁和复用,将 Visualized-BGE 模型的加载和编码逻辑封装在一个 `Encoder` 类中,并定义了一个 `visualize_results` 函数用于后续的结果可视化。 + +```python +import os +from tqdm import tqdm +from glob import glob +import torch +from visual_bge.visual_bge.modeling import Visualized_BGE +from pymilvus import MilvusClient, FieldSchema, CollectionSchema, DataType +import numpy as np +import cv2 +from PIL import Image + +# 1. 初始化设置 +MODEL_NAME = "BAAI/bge-base-en-v1.5" +MODEL_PATH = "../../models/bge/Visualized_base_en_v1.5.pth" +DATA_DIR = "../../data/C3" +COLLECTION_NAME = "multimodal_demo" +MILVUS_URI = "http://localhost:19530" + +# 2. 定义工具 (编码器和可视化函数) +class Encoder: + """编码器类,用于将图像和文本编码为向量。""" + def __init__(self, model_name: str, model_path: str): + self.model = Visualized_BGE(model_name_bge=model_name, model_weight=model_path) + self.model.eval() + + def encode_query(self, image_path: str, text: str) -> list[float]: + with torch.no_grad(): + query_emb = self.model.encode(image=image_path, text=text) + return query_emb.tolist()[0] + + def encode_image(self, image_path: str) -> list[float]: + with torch.no_grad(): + query_emb = self.model.encode(image=image_path) + return query_emb.tolist()[0] + +def visualize_results(query_image_path: str, retrieved_images: list, img_height: int = 300, img_width: int = 300, row_count: int = 3) -> np.ndarray: + """从检索到的图像列表创建一个全景图用于可视化。""" + panoramic_width = img_width * row_count + panoramic_height = img_height * row_count + panoramic_image = np.full((panoramic_height, panoramic_width, 3), 255, dtype=np.uint8) + query_display_area = np.full((panoramic_height, img_width, 3), 255, dtype=np.uint8) + + # 处理查询图像 + query_pil = Image.open(query_image_path).convert("RGB") + query_cv = np.array(query_pil)[:, :, ::-1] + resized_query = cv2.resize(query_cv, (img_width, img_height)) + bordered_query = cv2.copyMakeBorder(resized_query, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=(255, 0, 0)) + query_display_area[img_height * (row_count - 1):, :] = cv2.resize(bordered_query, (img_width, img_height)) + cv2.putText(query_display_area, "Query", (10, panoramic_height - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) + + # 处理检索到的图像 + for i, img_path in enumerate(retrieved_images): + row, col = i // row_count, i % row_count + start_row, start_col = row * img_height, col * img_width + + retrieved_pil = Image.open(img_path).convert("RGB") + retrieved_cv = np.array(retrieved_pil)[:, :, ::-1] + resized_retrieved = cv2.resize(retrieved_cv, (img_width - 4, img_height - 4)) + bordered_retrieved = cv2.copyMakeBorder(resized_retrieved, 2, 2, 2, 2, cv2.BORDER_CONSTANT, value=(0, 0, 0)) + panoramic_image[start_row:start_row + img_height, start_col:start_col + img_width] = bordered_retrieved + + # 添加索引号 + cv2.putText(panoramic_image, str(i), (start_col + 10, start_row + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) + + return np.hstack([query_display_area, panoramic_image]) +``` + +### 4.2 创建 Collection + +这是与 Milvus 交互的开始。首先初始化 Milvus 客户端,然后定义 Collection 的 Schema,它规定了集合的数据结构。 + +```python +# 3. 初始化客户端 +print("--> 正在初始化编码器和Milvus客户端...") +encoder = Encoder(MODEL_NAME, MODEL_PATH) +milvus_client = MilvusClient(uri=MILVUS_URI) + +# 4. 创建 Milvus Collection +print(f"\n--> 正在创建 Collection '{COLLECTION_NAME}'") +if milvus_client.has_collection(COLLECTION_NAME): + milvus_client.drop_collection(COLLECTION_NAME) + print(f"已删除已存在的 Collection: '{COLLECTION_NAME}'") + +image_list = glob(os.path.join(DATA_DIR, "dragon", "*.png")) +if not image_list: + raise FileNotFoundError(f"在 {DATA_DIR}/dragon/ 中未找到任何 .png 图像。") +dim = len(encoder.encode_image(image_list[0])) + +fields = [ + FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True), + FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=dim), + FieldSchema(name="image_path", dtype=DataType.VARCHAR, max_length=512), +] + +# 创建集合 Schema +schema = CollectionSchema(fields, description="多模态图文检索") +print("Schema 结构:") +print(schema) + +# 创建集合 +milvus_client.create_collection(collection_name=COLLECTION_NAME, schema=schema) +print(f"成功创建 Collection: '{COLLECTION_NAME}'") +print("Collection 结构:") +print(milvus_client.describe_collection(collection_name=COLLECTION_NAME)) +``` + +**输出结果:** +```bash +--> 正在创建 Collection 'multimodal_demo' + +Schema 结构: +{ + 'auto_id': True, + 'description': '多模态图文检索', + 'fields': [ + {'name': 'id', 'description': '', 'type': , 'is_primary': True, 'auto_id': True}, + {'name': 'vector', 'description': '', 'type': , 'params': {'dim': 768}}, + {'name': 'image_path', 'description': '', 'type': , 'params': {'max_length': 512}} + ], + 'enable_dynamic_field': False +} + +成功创建 Collection: 'multimodal_demo' + +Collection 结构: +{ + 'collection_name': 'multimodal_demo', + 'auto_id': True, + 'num_shards': 1, + 'description': '多模态图文检索', + 'fields': [ + {'field_id': 100, 'name': 'id', 'description': '', 'type': , 'params': {}, 'auto_id': True, 'is_primary': True}, + {'field_id': 101, 'name': 'vector', 'description': '', 'type': , 'params': {'dim': 768}}, + {'field_id': 102, 'name': 'image_path', 'description': '', 'type': , 'params': {'max_length': 512}} + ], + 'functions': [], + 'aliases': [], + 'collection_id': 459243798405253751, + 'consistency_level': 2, + 'properties': {}, + 'num_partitions': 1, + 'enable_dynamic_field': False, + 'created_timestamp': 459249546649403396, + 'update_timestamp': 459249546649403396 +} +``` + +上面的输出详细展示了刚刚创建的 `multimodal_demo` Collection 的完整结构。其 **Schema** 包含了三个核心字段(**Field**):一个自增的 `id` 作为**主键**,一个 768 维的 `vector` **向量字段**用于存储图像嵌入,以及一个 `image_path` **标量字段**来记录原始图片路径。 + +### 4.3 准备并插入数据 + +创建好 Collection 后,需要将数据填充进去。通过遍历指定目录下的所有图片,将它们逐一编码成向量,然后与图片路径一起组织成符合 Schema 结构的格式,最后批量插入到 Collection 中。 + +```python +# 5. 准备并插入数据 +print(f"\n--> 正在向 '{COLLECTION_NAME}' 插入数据") +data_to_insert = [] +for image_path in tqdm(image_list, desc="生成图像嵌入"): + vector = encoder.encode_image(image_path) + data_to_insert.append({"vector": vector, "image_path": image_path}) + +if data_to_insert: + result = milvus_client.insert(collection_name=COLLECTION_NAME, data=data_to_insert) + print(f"成功插入 {result['insert_count']} 条数据。") +``` + +### 4.4 创建索引 + +为了实现快速检索,需要为向量字段创建索引。这里选择 `HNSW` 索引,它在召回率和查询性能之间有着很好的平衡。创建索引后,必须调用 `load_collection` 将集合加载到内存中才能进行搜索。 + +```python +# 6. 创建索引 +print(f"\n--> 正在为 '{COLLECTION_NAME}' 创建索引") +index_params = milvus_client.prepare_index_params() +index_params.add_index( + field_name="vector", + index_type="HNSW", + metric_type="COSINE", + params={"M": 16, "efConstruction": 256} +) +milvus_client.create_index(collection_name=COLLECTION_NAME, index_params=index_params) +print("成功为向量字段创建 HNSW 索引。") +print("索引详情:") +print(milvus_client.describe_index(collection_name=COLLECTION_NAME, index_name="vector")) +milvus_client.load_collection(collection_name=COLLECTION_NAME) +print("已加载 Collection 到内存中。") +``` + +**输出结果:** +```bash +--> 正在为 'multimodal_demo' 创建索引 +成功为向量字段创建 HNSW 索引。 +索引详情: +{'M': '16', 'efConstruction': '256', 'metric_type': 'COSINE', 'index_type': 'HNSW', 'field_name': 'vector', 'index_name': 'vector', 'total_rows': 0, 'indexed_rows': 0, 'pending_index_rows': 0, 'state': 'Finished'} +已加载 Collection 到内存中。 +``` + +可以看出,索引创建成功,在 `vector` 字段上成功创建了 `HNSW` 索引,并使用 `COSINE` 作为距离度量。`M: '16'` 和 `efConstruction: '256'` 是 HNSW 索引的两个关键参数,分别控制着图中每个节点的最大连接数和索引构建时的搜索范围,这些参数直接影响检索的性能和准确性。`state: 'Finished'` 状态表明索引已成功构建。 + +### 4.5 执行多模态检索 + +这里通过定义一个包含图片和文本的组合查询,将其编码为查询向量,然后调用 `search` 方法在 Milvus 中执行近似最近邻搜索。 + +```python +# 7. 执行多模态检索 +print(f"\n--> 正在 '{COLLECTION_NAME}' 中执行检索") +query_image_path = os.path.join(DATA_DIR, "dragon", "query.png") +query_text = "一条龙" +query_vector = encoder.encode_query(image_path=query_image_path, text=query_text) + +search_results = milvus_client.search( + collection_name=COLLECTION_NAME, + data=[query_vector], + output_fields=["image_path"], + limit=5, + search_params={"metric_type": "COSINE", "params": {"ef": 128}} +)[0] + +retrieved_images = [] +print("检索结果:") +for i, hit in enumerate(search_results): + print(f" Top {i+1}: ID={hit['id']}, 距离={hit['distance']:.4f}, 路径='{hit['entity']['image_path']}'") + retrieved_images.append(hit['entity']['image_path']) +``` + +**输出结果:** + +```bash +--> 正在 'multimodal_demo' 中执行检索 +检索结果: + Top 1: ID=459243798403756667, 距离=0.9411, 路径='../../data/C3\dragon\dragon01.png' + Top 2: ID=459243798403756668, 距离=0.5818, 路径='../../data/C3\dragon\dragon02.png' + Top 3: ID=459243798403756671, 距离=0.5731, 路径='../../data/C3\dragon\dragon05.png' + Top 4: ID=459243798403756670, 距离=0.4894, 路径='../../data/C3\dragon\dragon04.png' + Top 5: ID=459243798403756669, 距离=0.4100, 路径='../../data/C3\dragon\dragon03.png' +``` + +这段输出展示了与图文组合查询最相似的5个**实体 (Entity)**。`distance` 字段代表了**余弦相似度**,值越接近 1 表示越相似。可以看到,`Top 1` 结果正是查询图片本身,其相似度得分最高(0.9411),这说明了检索的有效性。其余结果也都是龙的图片,并按相似度从高到低精确排列。 + +### 4.6 可视化与清理 + +最后,将检索到的图片路径用于可视化,生成一张直观的结果对比图。在完成所有操作后,应该释放 Milvus 中的资源,包括从内存中卸载 Collection 和删除整个 Collection。 + +```python +# 8. 可视化与清理 +print(f"\n--> 正在可视化结果并清理资源") +if not retrieved_images: + print("没有检索到任何图像。") +else: + panoramic_image = visualize_results(query_image_path, retrieved_images) + combined_image_path = os.path.join(DATA_DIR, "search_result.png") + cv2.imwrite(combined_image_path, panoramic_image) + print(f"结果图像已保存到: {combined_image_path}") + Image.open(combined_image_path).show() + +milvus_client.release_collection(collection_name=COLLECTION_NAME) +print(f"已从内存中释放 Collection: '{COLLECTION_NAME}'") +milvus_client.drop_collection(COLLECTION_NAME) +print(f"已删除 Collection: '{COLLECTION_NAME}'") +``` + +![检索结果可视化](./images/3_4_3.png) + +通过上图可以看出,这个多模态检索引擎成功地理解了“一条龙”这个图文组合查询的意图,并从图库中找到了最相关的几张图片并进行排序。 + +> [本节完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C3/04_multi_milvus.py) diff --git a/docs/chapter3/10_index_optimization.md b/docs/chapter3/10_index_optimization.md new file mode 100644 index 0000000..c9e8c0a --- /dev/null +++ b/docs/chapter3/10_index_optimization.md @@ -0,0 +1,277 @@ +# 第五节 索引优化 + +在上一章的文本分块部分,已经简单介绍了一些索引优化的策略。本节将基于LlamaIndex的高性能生产级RAG构建方案[^1],对索引优化进行更深入的探讨。 + +## 一、上下文扩展 + +在RAG系统中,常常面临一个权衡问题:使用小块文本进行检索可以获得更高的精确度,但小块文本缺乏足够的上下文,可能导致大语言模型(LLM)无法生成高质量的答案;而使用大块文本虽然上下文丰富,却容易引入噪音,降低检索的相关性。为了解决这一矛盾,LlamaIndex 提出了一种实用的索引策略——**句子窗口检索(Sentence Window Retrieval)**[^2]。该技术巧妙地结合了两种方法的优点:它在检索时聚焦于高度精确的单个句子,在送入LLM生成答案前,又智能地将上下文扩展回一个更宽的“窗口”,从而同时保证检索的准确性和生成的质量。 + +### 1.1 主要思路 + +句子窗口检索的思想可以概括为:**为检索精确性而索引小块,为上下文丰富性而检索大块**。 + +其工作流程如下: + +(1)**索引阶段**:在构建索引时,文档被分割成**单个句子**。每个句子都作为一个独立的“节点(Node)”存入向量数据库。同时,每个句子节点都会在元数据(metadata)中存储其**上下文窗口**,即该句子原文中的前N个和后N个句子。这个窗口内的文本不会被索引,仅仅是作为元数据存储。 + +(2)**检索阶段**:当用户发起查询时,系统会在所有**单一句子节点**上执行相似度搜索。因为句子是表达完整语义的最小单位,所以这种方式可以非常精确地定位到与用户问题最相关的核心信息。 + +(3)**后处理阶段**:在检索到最相关的句子节点后,系统会使用一个名为 `MetadataReplacementPostProcessor` 的后处理模块。该模块会读取到检索到的句子节点的元数据,并用元数据中存储的**完整上下文窗口**来替换节点中原来的单一句子内容。 + +(4)**生成阶段**:最后,这些被替换了内容的、包含丰富上下文的节点被传递给LLM,用于生成最终的答案。 + +### 1.2 代码实现 + +下面通过 LlamaIndex 官网的示例,来演示如何实现句子窗口检索,并与常规的检索方法进行对比。该示例将加载一份PDF格式的IPCC气候报告,并就其中的专业问题进行提问。 + +核心代码如下: + +```python +# 假设 Settings.llm 和 Settings.embed_model 已经预先配置好 + +# 1. 加载文档 +documents = SimpleDirectoryReader( + input_files=["../../data/C3/pdf/IPCC_AR6_WGII_Chapter03.pdf"] +).load_data() + +# 2. 创建节点与构建索引 +# 2.1 句子窗口索引 +node_parser = SentenceWindowNodeParser.from_defaults( + window_size=3, + window_metadata_key="window", + original_text_metadata_key="original_text", +) +sentence_nodes = node_parser.get_nodes_from_documents(documents) +sentence_index = VectorStoreIndex(sentence_nodes) +``` + +根据 LlamaIndex 的底层源码,`SentenceWindowNodeParser` 的核心逻辑位于 `build_window_nodes_from_documents` 方法中。其实现过程可以分解为以下几个关键步骤: + +(1)**句子切分 (`sentence_splitter`)** :解析器首先接收一个文档(`Document`),然后调用 `self.sentence_splitter(doc.text)` 方法。这个 `sentence_splitter` 是一个可配置的函数,默认为 `split_by_sentence_tokenizer`,它负责将文档的全部文本精确地切分成一个句子列表(`text_splits`)。 + +(2)**创建基础节点 (`build_nodes_from_splits`)** :切分出的 `text_splits` 列表被传递给 `build_nodes_from_splits` 工具函数。这个函数会为列表中的**每一个句子**都创建一个独立的 `TextNode`。此时,每个 `TextNode` 的 `text` 属性就是这个句子的内容。 + +(3)**构建窗口并填充元数据 (主要循环)** :接下来,解析器会遍历所有新创建的 `TextNode`。对于位于第 `i` 个位置的节点,它会执行以下操作: + +* **定位窗口**:通过列表切片 `nodes[max(0, i - self.window_size) : min(i + self.window_size + 1, len(nodes))]` 来获取一个包含中心句子及其前后 `window_size`(默认为3)个邻近节点的列表(`window_nodes`)。这个切片操作很巧妙地处理了文档开头和结尾的边界情况。 +* **组合窗口文本**:将 `window_nodes` 列表中所有节点的 `text`(即所有在窗口内的句子)用空格拼接成一个长字符串。 +* **填充元数据**:将上一步生成的长字符串(完整的上下文窗口)存入当前节点(第`i`个节点)的元数据中,键为 `self.window_metadata_key`(默认为 `"window"`)。同时,也会将节点自身的文本(原始句子)存入元数据,键为 `self.original_text_metadata_key`(默认为 `"original_text"`)。 + +4. **设置元数据排除项**:这是一个非常关键的细节。在填充完元数据后,代码会执行 `node.excluded_embed_metadata_keys.extend(...)` 和 `node.excluded_llm_metadata_keys.extend(...)`。这行代码的作用是告诉后续的嵌入模型和LLM,在处理这个节点时,**应当忽略** `"window"` 和 `"original_text"` 这两个元数据字段。这确保了只有单个句子的纯净文本被用于生成向量嵌入,从而保证了检索的高精度。而 `"window"` 字段仅供后续的 `MetadataReplacementPostProcessor` 使用。 + +通过以上步骤,`SentenceWindowNodeParser` 最终返回一个 `TextNode` 列表。列表中的每个节点都代表一个独立的句子,其 `text` 属性用于精确检索,而其 `metadata` 中则“隐藏”了用于生成答案的丰富上下文窗口。 + +```python +# 2.2 常规分块索引 (基准) +base_parser = SentenceSplitter(chunk_size=512) +base_nodes = base_parser.get_nodes_from_documents(documents) +base_index = VectorStoreIndex(base_nodes) + +# 3. 构建查询引擎 +sentence_query_engine = sentence_index.as_query_engine( + similarity_top_k=2, + node_postprocessors=[ + MetadataReplacementPostProcessor(target_metadata_key="window") + ], +) +base_query_engine = base_index.as_query_engine(similarity_top_k=2) + +# 4. 执行查询并对比结果 +query = "What are the concerns surrounding the AMOC?" +print(f"查询: {query}\n") + +print("--- 句子窗口检索结果 ---") +window_response = sentence_query_engine.query(query) +print(f"回答: {window_response}\n") + +print("--- 常规检索结果 ---") +base_response = base_query_engine.query(query) +print(f"回答: {base_response}\n") +``` + +(1)**构建句子窗口索引**:这一步利用了 `SentenceWindowNodeParser`。它将文档解析为以单个句子为单位的 `Node`,同时将包含上下文的“窗口”文本(默认为前后各3个句子)存储在每个 `Node` 的元数据中。这一步是实现“为检索精确性而索引小块”思想的关键。 + +(2)**构建查询引擎与后处理**:查询引擎的构建是实现“为生成质量而扩展上下文”的关键。 + +* 在创建 `sentence_query_engine` 时,配置中加入了一个重要的后处理器 `MetadataReplacementPostProcessor`。 +* 它的作用是:当检索器根据用户查询找到最相关的节点(也就是单个句子)后,这个后处理器会立即介入。 +* 它会从该节点的元数据中读取出预先存储的完整“窗口”文本,并用它**替换**掉节点中原来的单个句子内容。 +* 这样,最终传递给大语言模型的就不再是孤立的句子,而是包含丰富上下文的完整文本段落,从而确保了生成答案的质量和连贯性。 + +我们向两个引擎提出的问题是:“关于大西洋经向翻转环流(AMOC),人们主要担忧什么?” (What are the concerns surrounding the AMOC?)。 + +**代码输出如下:** +```bash +查询: What are the concerns surrounding the AMOC? + +--- 句子窗口检索结果 --- +回答: The Atlantic Meridional Overturning Circulation (AMOC) is projected to decline over the 21st century with high confidence, though there is low confidence in quantitative projections of this decline. Observational records since the mid-2000s are too short to determine the relative contributions of internal variability, natural forcing, and anthropogenic forcing to AMOC changes. Additionally, there is low confidence in reconstructed and modeled AMOC changes for the 20th century due to limited agreement in quantitative trends. While an abrupt collapse before 2100 is not expected, the decline could have significant implications for global climate patterns. + +--- 常规检索结果 --- +回答: The concerns surrounding the Atlantic Meridional Overturning Circulation (AMOC) primarily involve its projected decline over the 21st century across all Shared Socioeconomic Pathway (SSP) scenarios. While an abrupt collapse before 2100 is not expected, there is high confidence in this decline, though quantitative projections remain uncertain. Observational records since the mid-2000s are too short to clearly distinguish the contributions of internal variability, natural forcing, and anthropogenic forcing to these changes. This uncertainty highlights the need for further research to better understand and predict AMOC behavior and its broader climate impacts. +``` + +从输出结果中可以观察到: + +* **两个答案都抓住了核心**:两个引擎都正确地识别出,对AMOC的主要担忧是其在21世纪预计的衰退。 +* **句子窗口检索的答案更详尽、更连贯**:句子窗口检索的回答不仅指出了衰退的趋势,还补充了关于“定量预测的置信度低”、“观测记录时间过短”、“20世纪重建和模拟的变化置信度低”等多个维度的细节。这使得答案的信息量更大,上下文更完整,更像一个综述。 +* **常规检索的答案相对宽泛**:常规检索的回答虽然正确,但内容相对概括,最后以“需要进一步研究”这样较为笼同的结论收尾。 + +这种差异正是句子窗口检索策略优势的体现。它通过“精确检索小文本块(单个句子),再扩展上下文(句子窗口)”的方式,为大语言模型提供了高度相关且信息丰富的上下文,从而生成了质量更高的答案。 + +> [完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C3/05_sentence_window_retrieval.py) + +## 二、结构化索引 + +随着知识库的规模不断扩大(例如,包含数百个PDF文件),传统的RAG方法(即对所有文本块进行top-k相似度搜索)会遇到瓶颈。当一个查询可能只与其中一两个文档相关时,在整个文档库中进行无差别的向量搜索,不仅效率低下,还容易被不相关的文本块干扰,导致检索结果不精确。 + +为了解决这个问题,一个有效的方法是利用**结构化索引**。其原理是在索引文本块的同时,为其附加结构化的**元数据(Metadata)**。这些元数据可以是任何有助于筛选和定位信息的标签,例如: + +* 文件名 +* 文档创建日期 +* 章节标题 +* 作者 +* 任何自定义的分类标签 + +![结构化索引](./images/3_5_1.webp) + +实际上,在第二章“文本分块”中介绍的**基于文档结构的分块**方法,就是实现结构化索引的一种前置步骤。例如,在使用 `MarkdownHeaderTextSplitter` 时,分块器会自动将Markdown文档的各级标题(如 `Header 1`, `Header 2` 等)提取并存入每个文本块的元数据中。这些标题信息就是非常有价值的结构化数据,可以直接用于后续的元数据过滤。 + +通过这种方式,可以在检索时实现“元数据过滤”和“向量搜索”的结合。例如,当用户查询“请总结一下2023年第二季度财报中关于AI的论述”时,系统可以: + +(1)**元数据预过滤**:首先通过元数据筛选,只在 `document_type == '财报'`、`year == 2023` 且 `quarter == 'Q2'` 的文档子集中进行搜索。 + +(2)**向量搜索**:然后,在经过滤的、范围更小的文本块集合中,执行针对查询“关于AI的论述”的向量相似度搜索。 + +这种“先过滤,再搜索”的策略,能够极大地缩小检索范围,显著提升大规模知识库场景下RAG应用的检索效率和准确性。LlamaIndex 提供了包括“自动检索”(Auto-Retrieval)在内的多种工具来支持这种结构化的检索范式。 + +### 2.1 代码实现:基于多表格的递归检索 + +在更复杂的场景中,结构化数据可能分布在多个来源中,例如一个包含多个工作表(Sheet)的 Excel 文件,每个工作表都代表一个独立的表格。在这种情况下,需要一种更强大的策略:**递归检索**[^3]。它能实现“路由”功能,先将查询引导至正确的知识来源(正确的表格),然后再在该来源内部执行精确查询。 + +下面使用一个包含多个工作表的电影数据 Excel 文件(`movie.xlsx`)来演示,其中每个工作表(如 `年份_1994`, `年份_2002` 等)都存储了对应年份的电影信息。 + +```python +# 1. 为每个工作表创建查询引擎和摘要节点 +excel_file = '../../data/C3/excel/movie.xlsx' +xls = pd.ExcelFile(excel_file) + +df_query_engines = {} +all_nodes = [] + +for sheet_name in xls.sheet_names: + df = pd.read_excel(xls, sheet_name=sheet_name) + # 为当前工作表创建一个 PandasQueryEngine + query_engine = PandasQueryEngine(df=df, llm=Settings.llm, verbose=True) + # 为当前工作表创建一个摘要节点(IndexNode) + year = sheet_name.replace('年份_', '') + summary = f"这个表格包含了年份为 {year} 的电影信息,可以用来回答关于这一年电影的具体问题。" + node = IndexNode(text=summary, index_id=sheet_name) + all_nodes.append(node) + # 存储工作表名称到其查询引擎的映射 + df_query_engines[sheet_name] = query_engine + +# 2. 创建顶层索引(只包含摘要节点) +vector_index = VectorStoreIndex(all_nodes) + +# 3. 创建递归检索器 +vector_retriever = vector_index.as_retriever(similarity_top_k=1) +recursive_retriever = RecursiveRetriever( + "vector", + retriever_dict={"vector": vector_retriever}, + query_engine_dict=df_query_engines, + verbose=True, +) + +# 4. 创建查询引擎 +query_engine = RetrieverQueryEngine.from_args(recursive_retriever) + +# 5. 执行查询 +query = "1994年评分人数最多的电影是哪一部?" +print(f"查询: {query}") +response = query_engine.query(query) +print(f"回答: {response}") +``` + +1. **创建 PandasQueryEngine** :遍历 Excel 中的每个工作表,为每个工作表(即一个独立的 DataFrame)都实例化一个 `PandasQueryEngine`。其强大之处在于,它能将关于表格的自然语言问题(如“评分人数最多的是哪个”)转换成实际的 Pandas 代码(如 `df.sort_values('评分人数').iloc[-1]`)来执行。 +2. **创建摘要节点 (`IndexNode`)** :对每个工作表,都创建一个 `IndexNode`,其内容是关于这个表格的一段摘要文本。这个节点将作为顶层检索的“指针”。 +3. **构建顶层索引** :使用所有创建的 `IndexNode` 构建一个 `VectorStoreIndex`。这个索引不包含任何表格的详细数据,只包含指向各个表格的“指针”信息。 +4. **创建 `RecursiveRetriever`** :这是实现递归检索的核心。将其配置为: + * `retriever_dict`: 指定顶层的检索器,即在摘要节点中进行检索的 `vector_retriever`。 + * `query_engine_dict`: 提供一个从节点 ID(即工作表名称)到其对应查询引擎的映射。当顶层检索器匹配到某个摘要节点后,递归检索器就知道该调用哪个 `PandasQueryEngine` 来处理后续查询。 + +**运行结果:** + +```bash +查询: 1994年评分人数最少的电影是哪一部? +> Retrieving with query id None: 1994年评分人数最少的电影是哪一部? +> Retrieved node with id, entering: 年份_1994 +> Retrieving with query id 年份_1994: 1994年评分人数最少的电影是哪一部? +> Pandas Instructions: +``` +df[df['年份'] == 1994].nsmallest(1, '评分人数')['电影名称'].iloc[0] +``` +> Pandas Output: 燃情岁月 +回答: 燃情岁月 +``` + +从输出中可以清晰地看到递归检索的完整流程: + +(1)**顶层路由**:`Retrieving with query id None`,系统首先在顶层的摘要索引中检索,根据问题“1994年...”匹配到了摘要节点 `年份_1994`。 + +(2)**进入子层**:`Retrieved node with id, entering: 年份_1994`,系统决定进入与“年份_1994”这个工作表关联的查询引擎。 + +(3)**子层查询**:`Retrieving with query id 年份_1994`,`PandasQueryEngine` 接管查询,并将问题发送给 LLM,让其生成 Pandas 代码。 + +(4)**代码生成与执行**:LLM 生成了 `df[df['年份'] == 1994].nsmallest(1, '评分人数')['电影名称'].iloc[0]`,引擎执行后得到输出 `燃情岁月`。 + +> [完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C3/06_recursive_retrieval.py) + +> ⚠️ **重要安全警告**:实际上在 LlamaIndex 的官网有提到,`PandasQueryEngine` 是一个实验性功能,具有潜在的安全风险。它的工作原理是让 LLM 生成 Python 代码,然后使用 `eval()` 函数在本地执行。这意味着,在没有严格沙箱隔离的环境下,理论上可能执行任意代码。**因此,强烈不建议在生产环境中使用此工具**。 + +### 2.2 另一种实现方式 + +鉴于 `PandasQueryEngine` 的安全风险,还可以采用一种更安全的方式来实现类似的多表格查询,思路是**将路由和检索彻底分离**。 + +这种改进方法的具体步骤如下: + +(1)**创建两个独立的向量索引**: + +* **摘要索引(用于路由)**:为每个Excel工作表(例如,“1994年电影数据”)创建一个非常简短的摘要性`Document`,例如:“此文档包含1994年的电影信息”。然后,用所有这些摘要文档构建一个轻量级的向量索引。这个索引的唯一目的就是充当“路由器”。 +* **内容索引(用于问答)**:将每个工作表的实际数据(例如,整个表格)转换为一个大的文本`Document`,并为其附加一个关键的元数据标签,如 `{"sheet_name": "年份_1994"}`。然后,用所有这些包含真实内容的文档构建一个向量索引。 + +(2)**执行两步查询**: + +* **第一步:路由**。当用户提问(例如,“1994年评分人数最少的电影是哪一部?”)时,首先在“摘要索引”中进行检索。由于问题中的“1994年”与“此文档包含1994年的电影信息”这个摘要高度相关,检索器会快速返回其对应的元数据,告诉系统目标是 `年份_1994` 这个工作表。 +* **第二步:检索**。拿到 `年份_1994` 这个目标后,系统会在“内容索引”中进行检索,但这次会附加一个**元数据过滤器**(`MetadataFilter`),强制要求只在 `sheet_name == "年份_1994"` 的文档中进行搜索。这样,LLM就能在正确的、经过筛选的数据范围内找到问题的答案。 + +通过这种“先路由,后用元数据过滤检索”的方式,既实现了跨多个数据源的查询能力,又避免了执行代码的安全隐患。LlamaIndex 官方也提供了类似的结构化分层检索[^4]可以参考。 + +> [完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C3/07_recursive_retrieval_v2.py) + +## 题外话:关于框架 + +> **有些人可能疑惑,为什么本教程不专注于一个框架(如 LlamaIndex 或 LangChain),而是混合使用,甚至造轮子?** + +框架是加速开发的强大工具,是帮助我们快速跨越技术鸿沟的“桥梁”。但任何桥梁都有其设计边界和局限性。我们的目标不是成为一个熟练的“过桥者”,而是成为一个懂得如何设计和建造桥梁的“工程师”。 + +因此,本教程选择的路径是: + +(1)**以原理为主**:我们优先关心的是“它是如何工作的?”而不是“我该调用哪个函数?”。新框架在诞生,老框架在迭代(当然不是笔者偷懒没更新 langchain🤫),但只要理解了底层的思想,我们将能更快地掌握任何现有或未来的框架。 + +(2)**拥抱灵活性**:真实世界的业务需求往往比框架预设的场景更复杂。当框架无法满足需求,或者像本节使用的 `PandasQueryEngine` 那样存在安全隐患时,懂得原理的话,就有能力去修改它,或者像本节的示例一样,用更底层的模块组合出更安全、合适的解决方案。 + +(3)**培养解决问题的能力**:只学习使用框架,好比是照着菜谱做菜,虽然能快速复刻出指定的菜肴,但一旦缺少某个食材或遇到意外情况,就可能束手无策。而理解原理,则像是学会了烹饪的精髓。这让你不仅能轻松地做出各种美食,还能创造新菜式。 + +如果你希望深入某个框架的细节,它的官方文档永远是最好、最权威的学习资料。而本教程的使命,是帮助你建立起关于 RAG 的坚实知识体系,让你无论面对何种工具,都能游刃有余。 + + +## 参考文献 + +[^1]: [*Building Performant RAG Applications for Production*](https://docs.llamaindex.ai/en/stable/optimizing/production_rag/) + +[^2]: [*LlamaIndex - Sentence Window Retrieval*](https://docs.llamaindex.ai/en/stable/examples/node_postprocessor/MetadataReplacementDemo/#metadata-replacement-node-sentence-window) + +[^3]: [*Recursive Retriever + Query Engine Demo*](https://docs.llamaindex.ai/en/stable/examples/query_engine/pdf_tables/recursive_retriever) + +[^4]: [*Structured Hierarchical Retrieval*](https://docs.llamaindex.ai/en/stable/examples/query_engine/multi_doc_auto_retrieval/multi_doc_auto_retrieval/) \ No newline at end of file diff --git a/docs/chapter3/images/3_1_1.webp b/docs/chapter3/images/3_1_1.webp new file mode 100644 index 0000000..66aec34 Binary files /dev/null and b/docs/chapter3/images/3_1_1.webp differ diff --git a/docs/chapter3/images/3_1_2.webp b/docs/chapter3/images/3_1_2.webp new file mode 100644 index 0000000..f21ac69 Binary files /dev/null and b/docs/chapter3/images/3_1_2.webp differ diff --git a/docs/chapter3/images/3_1_3.webp b/docs/chapter3/images/3_1_3.webp new file mode 100644 index 0000000..ee73069 Binary files /dev/null and b/docs/chapter3/images/3_1_3.webp differ diff --git a/docs/chapter3/images/3_2_1.webp b/docs/chapter3/images/3_2_1.webp new file mode 100644 index 0000000..47fefe9 Binary files /dev/null and b/docs/chapter3/images/3_2_1.webp differ diff --git a/docs/chapter3/images/3_3_1.webp b/docs/chapter3/images/3_3_1.webp new file mode 100644 index 0000000..0b30435 Binary files /dev/null and b/docs/chapter3/images/3_3_1.webp differ diff --git a/docs/chapter3/images/3_4_1.webp b/docs/chapter3/images/3_4_1.webp new file mode 100644 index 0000000..d66d5bf Binary files /dev/null and b/docs/chapter3/images/3_4_1.webp differ diff --git a/docs/chapter3/images/3_4_2.webp b/docs/chapter3/images/3_4_2.webp new file mode 100644 index 0000000..e9f9f6b Binary files /dev/null and b/docs/chapter3/images/3_4_2.webp differ diff --git a/docs/chapter3/images/3_4_3.png b/docs/chapter3/images/3_4_3.png new file mode 100644 index 0000000..0e768f1 Binary files /dev/null and b/docs/chapter3/images/3_4_3.png differ diff --git a/docs/chapter3/images/3_5_1.webp b/docs/chapter3/images/3_5_1.webp new file mode 100644 index 0000000..6c7878a Binary files /dev/null and b/docs/chapter3/images/3_5_1.webp differ diff --git a/docs/chapter4/11_hybrid_search.md b/docs/chapter4/11_hybrid_search.md new file mode 100644 index 0000000..ad6ee88 --- /dev/null +++ b/docs/chapter4/11_hybrid_search.md @@ -0,0 +1,419 @@ +# 第一节 混合检索 + +混合检索(Hybrid Search)是一种结合了 **稀疏向量(Sparse Vectors)** 和 **密集向量(Dense Vectors)** 优势的先进搜索技术。旨在同时利用稀疏向量的关键词精确匹配能力和密集向量的语义理解能力,以克服单一向量检索的局限性,从而在各种搜索场景下提供更准确、更鲁棒的检索结果。 + +在本节中,我们将首先分析这两种核心向量的特性,然后讨论它们如何融合,最后通过milvus实现混合检索。 + +## 一、稀疏向量 vs 密集向量 + +为了更好地理解混合检索,首先需要厘清两种向量的本质区别。 + +### 1.1 稀疏向量 + +稀疏向量,也常被称为“词法向量”,是基于词频统计的传统信息检索方法的数学表示。它通常是一个维度极高(与词汇表大小相当)但绝大多数元素为零的向量。它采用精准的“词袋”匹配模型,将文档视为一堆词的集合,不考虑其顺序和语法,其中向量的每一个维度都直接对应一个具体的词,非零值则代表该词在文档中的重要性(权重)。这类向量的经典权重计算方法是 TF-IDF。在信息检索领域,BM25 则是基于这种稀疏表示的成功且应用广泛的排序算法之一,其核心公式如下: + + $$ Score(Q, D) = \sum_{i=1}^{n} IDF(q_i) \cdot \frac{f(q_i, D) \cdot (k_1 + 1)}{f(q_i, D) + k_1 \cdot (1 - b + b \cdot \frac{|D|}{avgdl})} $$ + + 其中: + - $IDF(q_i)$: 查询词 $q_i$ 的逆文档频率,用于衡量一个词的普遍程度。越常见的词,IDF值越低。 + - $f(q_i, D)$: 查询词 $q_i$ 在文档 $D$ 中的词频。 + - $|D|$: 文档 $D$ 的长度。 + - $avgdl$: 集合中所有文档的平均长度。 + - $k_1, b$: 可调节的超参数。 $k_1$ 用于控制词频饱和度(一个词在文档中出现10次和100次,其重要性增长并非线性), $b$ 用于控制文档长度归一化的程度。 + +这种方法的优点是可解释性极强(每个维度都代表一个确切的词),无需训练,能够实现关键词的精确匹配,对于专业术语和特定名词的检索效果好。主要缺点是无法理解语义,例如它无法识别“汽车”和“轿车”是同义词,存在“词汇鸿沟”。 + +### 1.2 密集向量 + +密集向量,也常被称为“语义向量”,是通过深度学习模型学习到的数据(如文本、图像)的低维、稠密的浮点数表示。这些向量旨在将原始数据映射到一个连续的、充满意义的“语义空间”中来捕捉“语义”或“概念”。在理想的语义空间中,向量之间的距离和方向代表了它们所表示概念之间的关系。一个经典的例子是 `vector('国王') - vector('男人') + vector('女人')` 的计算结果在向量空间中非常接近 `vector('女王')`,这表明模型学会了“性别”和“皇室”这两个维度的抽象概念。它的代表包括 Word2Vec、GloVe、以及所有基于 Transformer 的模型(如 BERT、GPT)生成的嵌入(Embeddings)。 + +其主要优点是能够理解同义词、近义词和上下文关系,泛化能力强,在语义搜索任务中表现卓越。但缺点也同样明显:可解释性差(向量中的每个维度通常没有具体的物理意义),需要大量数据和算力进行模型训练,且对于未登录词(OOV)[^1]的处理相对困难。 + +> **OOV(Out-of-Vocabulary)未登录词**:指在模型训练时没有出现在词汇表中,但在实际使用时遇到的新词汇。例如,如果模型训练时词汇表中没有"ChatGPT"这个词,那么在实际应用中遇到它时就是OOV。传统的稀疏向量方法(如BM25)对OOV词汇会完全忽略,而现代的密集向量方法通过子词分割(如BPE、WordPiece)可以更好地处理OOV问题。 + +### 1.3 实例对比 + +**稀疏向量表示:** + +稀疏向量的核心思想是只存储非零值。例如,一个8维的向量 `[0, 0, 0, 5, 0, 0, 0, 9]`,其大部分元素都是零。用稀疏格式表示,可以极大地节约空间。常见的稀疏表示法有两种: + +1. **字典 / 键值对 (Dictionary / Key-Value):** + 这种方式将非零元素的 `索引` (0-based) 作为键,`值` 作为值。上面的向量可以表示为: + ```json + // {索引: 值} + { + "3": 5, + "7": 9 + } + ``` + +2. **坐标列表 (Coordinate list - COO):** + 这种方式通常用一个元组 `(维度, [索引列表], [值列表])` 来表示。上面的向量可以表示为: + ``` + (8, [3, 7], [5, 9]) + ``` + 这种格式在 `SciPy` 等科学计算库中非常常见。 + +假设在一个包含5万个词的词汇表中,“西红柿”在第88位,“炒”在第666位,“蛋”在第999位,它们的BM25权重分别是1.2、0.8、1.5。那么它的稀疏表示(采用字典格式)就是: +```json +// {索引: 权重} +{ + "88": 1.2, + "666": 0.8, + "999": 1.5 +} +``` +如果采用坐标列表(COO)格式,它会是这样: +``` +(50000, [88, 666, 999], [1.2, 0.8, 1.5]) +``` +这两种格式都清晰地记录了文档的关键信息,但它们的局限性也很明显:如果我们搜索“番茄炒鸡蛋”,由于“番茄”和“西红柿”是不同的词条(索引不同),模型将无法理解它们的语义相似性。 + +**密集向量表示:** + +与稀疏向量不同,密集向量的所有维度都有值,因此使用**数组 `[]`** 来表示是最直接的方式。一个预训练好的语义模型在读取“西红柿炒蛋”后,会输出一个低维的密集向量: + +```json +// 这是一个低维(比如1024维)的浮点数向量 +// 向量的每个维度没有直接的、可解释的含义 +[0.89, -0.12, 0.77, ..., -0.45] +``` + +这个向量本身难以解读,但它在语义空间中的位置可能与“番茄鸡蛋面”、“洋葱炒鸡蛋”等菜肴的向量非常接近,因为模型理解了它们共享“鸡蛋类菜肴”、“家常菜”、“酸甜口味”等核心概念。因此,当我们搜索“蛋白质丰富的家常菜”时,即使查询中没有出现任何原文关键词,密集向量也很有可能成功匹配到这份菜谱。 + +## 二、混合检索 + +通过上文可以看出稀疏向量和密集向量各有千秋,那么将它们结合起来,实现优势互补,就成了一个不错的选择。混合检索便是基于这个思路,通过结合多种搜索算法(最常见的是稀疏与密集检索)来提升搜索结果相关性和召回率。 + +- **主要目标**:解决单一检索技术的局限性。例如,关键词检索无法理解语义,而向量检索则可能忽略掉必须精确匹配的关键词(如产品型号、函数名等)。混合检索旨在同时利用稀疏向量的**精确性**和密集向量的**泛化性**,以应对复杂多变的搜索需求。 + +### 2.1 技术原理与融合方法 + +混合检索通常并行执行两种检索算法,然后将两组异构的结果集融合成一个统一的排序列表。以下是两种主流的融合策略: + +#### 2.1.1 倒数排序融合 (Reciprocal Rank Fusion, RRF) + +RRF 不关心不同检索系统的原始得分,只关心每个文档在各自结果集中的**排名**。其思想是:一个文档在不同检索系统中的排名越靠前,它的最终得分就越高。 + +其计分公式为: + +$$ RRF_{score}(d) = \sum_{i=1}^{k} \frac{1}{rank_i(d) + c} $$ + +其中: +- $d$ 是待评分的文档。 +- $k$ 是检索系统的数量(这里是2,即稀疏和密集)。 +- $rank_i(d)$ 是文档 $d$ 在第 $i$ 个检索系统中的排名。 +- $c$ 是一个常数(通常设为60),用于降低排名靠前文档的相对权重,实现更稳健的排名融合。 + +#### 2.1.2 加权线性组合 + +这种方法需要先将不同检索系统的得分进行归一化(例如,统一到 0-1 区间),然后通过一个权重参数 `α` 来进行线性组合。 + +$$ Hybrid_{score} = \alpha \cdot Dense_{score} + (1 - \alpha) \cdot Sparse_{score} $$ + +通过调整 `α` 的值,可以灵活地控制语义相似性与关键词匹配在最终排序中的贡献比例。例如,在电商搜索中,可以调高关键词的权重;而在智能问答中,则可以侧重于语义。 + +### 2.2 优势与局限 + +| 优势 | 局限 | +| :--- | :--- | +| **召回率与准确率高**:能同时捕获关键词和语义,显著优于单一检索。 | **计算资源消耗大**:需要同时维护和查询两套索引。 | +| **灵活性强**:可通过融合策略和权重调整,适应不同业务场景。 | **参数调试复杂**:融合权重等超参数需要反复实验调优。 | +| **容错性好**:关键词检索可部分弥补向量模型对拼写错误或罕见词的敏感性。 | **可解释性仍是挑战**:融合后的结果排序理由难以直观分析。 | + +## 三、代码实践:通过 Milvus 实现混合检索 + +接下来使用 Milvus 来实现一个完整的混合检索流程,从定义 Schema、插入数据,到执行查询。 + +### 3.1 步骤一:定义 Collection + +在上一章中我们实现了多模态图文检索,现在还是同样的步骤先创建一个 Collection。 + +```python +import json +import os +os.environ["HF_ENDPOINT"] = "https://hf-mirror.com" +import numpy as np +from pymilvus import connections, MilvusClient, FieldSchema, CollectionSchema, DataType, Collection, AnnSearchRequest, RRFRanker +from pymilvus.model.hybrid import BGEM3EmbeddingFunction + +# 1. 初始化设置 +COLLECTION_NAME = "dragon_hybrid_demo" +MILVUS_URI = "http://localhost:19530" # 服务器模式 +DATA_PATH = "../../data/C4/metadata/dragon.json" # 相对路径 +BATCH_SIZE = 50 + +# 2. 连接 Milvus 并初始化嵌入模型 +print(f"--> 正在连接到 Milvus: {MILVUS_URI}") +connections.connect(uri=MILVUS_URI) + +print("--> 正在初始化 BGE-M3 嵌入模型...") +ef = BGEM3EmbeddingFunction(use_fp16=False, device="cpu") +print(f"--> 嵌入模型初始化完成。密集向量维度: {ef.dim['dense']}") + +# 3. 创建 Collection +milvus_client = MilvusClient(uri=MILVUS_URI) +if milvus_client.has_collection(COLLECTION_NAME): + print(f"--> 正在删除已存在的 Collection '{COLLECTION_NAME}'...") + milvus_client.drop_collection(COLLECTION_NAME) + +fields = [ + FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100), + FieldSchema(name="img_id", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="path", dtype=DataType.VARCHAR, max_length=256), + FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=256), + FieldSchema(name="description", dtype=DataType.VARCHAR, max_length=4096), + FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=64), + FieldSchema(name="location", dtype=DataType.VARCHAR, max_length=128), + FieldSchema(name="environment", dtype=DataType.VARCHAR, max_length=64), + FieldSchema(name="sparse_vector", dtype=DataType.SPARSE_FLOAT_VECTOR), + FieldSchema(name="dense_vector", dtype=DataType.FLOAT_VECTOR, dim=ef.dim["dense"]) +] + +# 如果集合不存在,则创建它及索引 +if not milvus_client.has_collection(COLLECTION_NAME): + print(f"--> 正在创建 Collection '{COLLECTION_NAME}'...") + schema = CollectionSchema(fields, description="关于龙的混合检索示例") + # 创建集合 + collection = Collection(name=COLLECTION_NAME, schema=schema, consistency_level="Strong") + print("--> Collection 创建成功。") + + # 创建索引 + print("--> 正在为新集合创建索引...") + sparse_index = {"index_type": "SPARSE_INVERTED_INDEX", "metric_type": "IP"} + collection.create_index("sparse_vector", sparse_index) + print("稀疏向量索引创建成功。") + + dense_index = {"index_type": "AUTOINDEX", "metric_type": "IP"} + collection.create_index("dense_vector", dense_index) + print("密集向量索引创建成功。") + +collection = Collection(COLLECTION_NAME) +collection.load() +print(f"--> Collection '{COLLECTION_NAME}' 已加载到内存。") +``` + +**fields字段类型分析:** + +- **pk**: 主键设计,`auto_id=True` 让 Milvus 自动生成唯一标识,避免主键冲突 +- **标量字段**: 7个VARCHAR字段用于存储元数据,`max_length` 根据实际数据分布优化存储 +- **稀疏向量**: `SPARSE_FLOAT_VECTOR` 类型,存储关键词权重 +- **密集向量**: `FLOAT_VECTOR` 类型,固定1024维,存储语义特征 + + +### 3.2 步骤二:BGE-M3 双向量生成 + +这里使用 BGE-M3 作为向量生成器,它能够同时生成稀疏向量和密集向量。 + +#### 3.2.1 数据加载与预处理 + +```python +if collection.is_empty: + print(f"--> Collection 为空,开始插入数据...") + with open(DATA_PATH, 'r', encoding='utf-8') as f: + dataset = json.load(f) + + docs, metadata = [], [] + for item in dataset: + parts = [ + item.get('title', ''), + item.get('description', ''), + item.get('location', ''), + item.get('environment', ''), + ] + docs.append(' '.join(filter(None, parts))) + metadata.append(item) +``` + +Collection 此时已加载到内存但为空状态。通过 `is_empty` 检查避免重复插入。多字段文本合并中每个实体对应一个完整的数据记录。 + +#### 3.2.2 向量生成 + +```python +print("--> 正在生成向量嵌入...") +embeddings = ef(docs) +print("--> 向量生成完成。") + +# 获取两种向量 +sparse_vectors = embeddings["sparse"] # 稀疏向量:词频统计 +dense_vectors = embeddings["dense"] # 密集向量:语义编码 +``` + +#### 3.2.3 Collection 批量数据插入 + +```python +# 为每个字段准备批量数据 +img_ids = [doc["img_id"] for doc in metadata] +paths = [doc["path"] for doc in metadata] +titles = [doc["title"] for doc in metadata] +descriptions = [doc["description"] for doc in metadata] +categories = [doc["category"] for doc in metadata] +locations = [doc["location"] for doc in metadata] +environments = [doc["environment"] for doc in metadata] + +# 插入数据 +collection.insert([ + img_ids, paths, titles, descriptions, categories, locations, environments, + sparse_vectors, dense_vectors +]) +collection.flush() +``` + +- **字段映射**: 严格按照 Schema 定义的字段顺序插入,9个字段(7个标量+2个向量) +- **`flush()` 作用**: 强制将内存缓冲区数据写入磁盘,使数据立即可搜索 +- **最终状态**: Collection 包含6个Entity,索引层使用稀疏向量的 `SPARSE_INVERTED_INDEX` 和密集向量的 `AUTOINDEX` + +### 3.3 步骤三:实现混合检索 + +最后使用 milvus 中封装好的 RRF 排序算法来完成混合检索: + +#### 3.3.1 查询向量生成 + +```python +# 6. 执行搜索 +search_query = "悬崖上的巨龙" +search_filter = 'category in ["western_dragon", "chinese_dragon", "movie_character"]' +top_k = 5 + +print(f"\n{'='*20} 开始混合搜索 {'='*20}") +print(f"查询: '{search_query}'") +print(f"过滤器: '{search_filter}'") + +# 生成查询向量 +query_embeddings = ef([search_query]) +dense_vec = query_embeddings["dense"][0] +sparse_vec = query_embeddings["sparse"]._getrow(0) +``` + +尝试打印向量信息可以看到如下输出: + +```bash +=== 向量信息 === +密集向量维度: 1024 +密集向量前5个元素: [-0.0035305 0.02043397 -0.04192593 -0.03036701 -0.02098157] +密集向量范数: 1.0000 + +稀疏向量维度: 250002 +稀疏向量非零元素数量: 6 +稀疏向量前5个非零元素: + - 索引: 6, 值: 0.0659 + - 索引: 7977, 值: 0.1459 + - 索引: 14732, 值: 0.2959 + - 索引: 31433, 值: 0.1463 + - 索引: 141121, 值: 0.1587 + +稀疏向量密度: 0.00239998% +``` + +#### 3.3.2 混合检索执行 + +使用 RRF 算法进行混合检索,通过 milvus 封装的 RRFRanker 实现。RRFRanker 的核心参数是 `k` 值(默认60),用于控制 RRF 算法中的排序平滑程度。 + +其中 `k` 值越大,排序结果越平滑;越小则高排名结果的权重越突出 + +```python +# 定义搜索参数 +search_params = {"metric_type": "IP", "params": {}} + +# 先执行单独的搜索 +print("\n--- [单独] 密集向量搜索结果 ---") +dense_results = collection.search( + [dense_vec], + anns_field="dense_vector", + param=search_params, + limit=top_k, + expr=search_filter, + output_fields=["title", "path", "description", "category", "location", "environment"] +)[0] + +for i, hit in enumerate(dense_results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('path')}") + print(f" 描述: {hit.entity.get('description')[:100]}...") + +print("\n--- [单独] 稀疏向量搜索结果 ---") +sparse_results = collection.search( + [sparse_vec], + anns_field="sparse_vector", + param=search_params, + limit=top_k, + expr=search_filter, + output_fields=["title", "path", "description", "category", "location", "environment"] +)[0] + +for i, hit in enumerate(sparse_results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('path')}") + print(f" 描述: {hit.entity.get('description')[:100]}...") + +print("\n--- [混合] 稀疏+密集向量搜索结果 ---") +# 创建 RRF 融合器 +rerank = RRFRanker(k=60) + +# 创建搜索请求 +dense_req = AnnSearchRequest([dense_vec], "dense_vector", search_params, limit=top_k) +sparse_req = AnnSearchRequest([sparse_vec], "sparse_vector", search_params, limit=top_k) + +# 执行混合搜索 +results = collection.hybrid_search( + [sparse_req, dense_req], + rerank=rerank, + limit=top_k, + output_fields=["title", "path", "description", "category", "location", "environment"] +)[0] + +# 打印最终结果 +for i, hit in enumerate(results): + print(f"{i+1}. {hit.entity.get('title')} (Score: {hit.distance:.4f})") + print(f" 路径: {hit.entity.get('path')}") + print(f" 描述: {hit.entity.get('description')[:100]}...") +``` + +最终输出如下: +```bash +--- [单独] 密集向量搜索结果 --- +1. 悬崖上的白龙 (Score: 0.7219) + 路径: ../../data/C3/dragon/dragon02.png + 描述: 一头雄伟的白色巨龙栖息在悬崖边缘,背景是金色的云霞和远方的海岸。它拥有巨大的翅膀和优雅的身姿,是典型的西方奇幻生物。... +2. 中华金龙 (Score: 0.5131) + 路径: ../../data/C3/dragon/dragon06.png + 描述: 一条金色的中华龙在祥云间盘旋,它身形矫健,龙须飘逸,展现了东方神话中龙的威严与神圣。... +3. 驯龙高手:无牙仔 (Score: 0.5119) + 路径: ../../data/C3/dragon/dragon05.png + 描述: 在电影《驯龙高手》中,主角小嗝嗝骑着他的龙伙伴无牙仔在高空飞翔。他们飞向灿烂的太阳,下方是岛屿和海洋,画面充满了冒险与友谊。... + +--- [单独] 稀疏向量搜索结果 --- +1. 悬崖上的白龙 (Score: 0.2319) + 路径: ../../data/C3/dragon/dragon02.png + 描述: 一头雄伟的白色巨龙栖息在悬崖边缘,背景是金色的云霞和远方的海岸。它拥有巨大的翅膀和优雅的身姿,是典型的西方奇幻生物。... +2. 中华金龙 (Score: 0.0923) + 路径: ../../data/C3/dragon/dragon06.png + 描述: 一条金色的中华龙在祥云间盘旋,它身形矫健,龙须飘逸,展现了东方神话中龙的威严与神圣。... +3. 驯龙高手:无牙仔 (Score: 0.0691) + 路径: ../../data/C3/dragon/dragon05.png + 描述: 在电影《驯龙高手》中,主角小嗝嗝骑着他的龙伙伴无牙仔在高空飞翔。他们飞向灿烂的太阳,下方是岛屿和海洋,画面充满了冒险与友谊。... + +--- [混合] 稀疏+密集向量搜索结果 --- +1. 悬崖上的白龙 (Score: 0.0328) + 路径: ../../data/C3/dragon/dragon02.png + 描述: 一头雄伟的白色巨龙栖息在悬崖边缘,背景是金色的云霞和远方的海岸。它拥有巨大的翅膀和优雅的身姿,是典型的西方奇幻生物。... +2. 中华金龙 (Score: 0.0320) + 路径: ../../data/C3/dragon/dragon06.png + 描述: 一条金色的中华龙在祥云间盘旋,它身形矫健,龙须飘逸,展现了东方神话中龙的威严与神圣。... +3. 霸王龙的怒吼 (Score: 0.0318) + 路径: ../../data/C3/dragon/dragon03.png + 描述: 史前时代的霸王龙张开血盆大口,发出震天的怒吼。在它身后,几只翼龙在阴沉的天空中盘旋,展现了白垩纪的原始力量。... +4. 奔跑的奶龙 (Score: 0.0313) + 路径: ../../data/C3/dragon/dragon04.png + 描述: 一只Q版的黄色小恐龙,有着大大的绿色眼睛和友善的微笑。是一部动画中的角色,非常可爱。... +5. 驯龙高手:无牙仔 (Score: 0.0310) + 路径: ../../data/C3/dragon/dragon05.png + 描述: 在电影《驯龙高手》中,主角小嗝嗝骑着他的龙伙伴无牙仔在高空飞翔。他们飞向灿烂的太阳,下方是岛屿和海洋,画面充满了冒险与友谊。... +``` + +> [本节完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C4/01_hybrid_search.py) + +## 练习 + +- 分析代码为什么在密集向量检索和稀疏向量检索中,排名第三的驯龙高手在混合检索中反而排在了第五? +- 基于上一节的多模态检索代码 `04_multi_milvus.py` ,结合本节的检索代码加入多模态信息融合的功能并尝试使用混合检索。([参考代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C3/work_multimodal_dragon_search.py)) diff --git a/docs/chapter4/12_query_construction.md b/docs/chapter4/12_query_construction.md new file mode 100644 index 0000000..4f29c71 --- /dev/null +++ b/docs/chapter4/12_query_construction.md @@ -0,0 +1,212 @@ +# 第二节 查询构建 + +在前面的章节中,我们探讨了如何通过向量嵌入和相似度搜索来从非结构化数据中检索信息。然而,在实际应用中,我们常常需要处理更加复杂和多样化的数据,包括结构化数据(如SQL数据库)、半结构化数据(如带有元数据的文档)以及图数据。用户的查询也可能不仅仅是简单的语义匹配,而是包含复杂的过滤条件、聚合操作或关系查询。 + +**查询构建(Query Construction)**[^1] 正是应对这一挑战的关键技术。它利用大语言模型(LLM)的强大理解能力,将用户的自然语言查询“翻译”成针对特定数据源的结构化查询语言或带有过滤条件的请求。这使得RAG系统能够无缝地连接和利用各种类型的数据,从而极大地扩展了其应用场景和能力。 + +下图展示了查询构建在一个高级RAG流程中所处的位置: + +![Advanced RAG Pipeline](./images/4_2_1.webp) + +## 一、文本到元数据过滤器 + +在构建向量索引时,常常会为文档块(Chunks)附加元数据(Metadata),例如文档来源、发布日期、作者、章节、类别等。这些元数据为我们提供了在语义搜索之外进行精确过滤的可能。 + +**自查询检索器(Self-Query Retriever)** 是LangChain中实现这一功能的核心组件。它的工作流程如下: + +1. **定义元数据结构**:首先,需要向LLM清晰地描述文档内容和每个元数据字段的含义及类型。 +2. **查询解析**:当用户输入一个自然语言查询时,自查询检索器会调用LLM,将查询分解为两部分: + * **查询字符串(Query String)**:用于进行语义搜索的部分。 + * **元数据过滤器(Metadata Filter)**:从查询中提取出的结构化过滤条件。 +3. **执行查询**:检索器将解析出的查询字符串和元数据过滤器发送给向量数据库,执行一次同时包含语义搜索和元数据过滤的查询。 + +例如,对于查询“关于2022年发布的机器学习的论文”,自查询检索器会将其解析为: +* **查询字符串**: "机器学习的论文" +* **元数据过滤器**: `year == 2022` + +### 代码示例 + +接下来以B站视频为例来看看如何使用`SelfQueryRetriever`。 + +```python +import os +from langchain_deepseek import ChatDeepSeek +from langchain_community.document_loaders import BiliBiliLoader +from langchain.chains.query_constructor.base import AttributeInfo +from langchain.retrievers.self_query.base import SelfQueryRetriever +from langchain_community.vectorstores import Chroma +from langchain_huggingface import HuggingFaceEmbeddings +import logging + +logging.basicConfig(level=logging.INFO) + +# 1. 初始化视频数据 +video_urls = [ + "https://www.bilibili.com/video/BV1Bo4y1A7FU", + "https://www.bilibili.com/video/BV1ug4y157xA", + "https://www.bilibili.com/video/BV1yh411V7ge", +] + +bili = [] +try: + loader = BiliBiliLoader(video_urls=video_urls) + docs = loader.load() + + for doc in docs: + original = doc.metadata + + # 提取基本元数据字段 + metadata = { + 'title': original.get('title', '未知标题'), + 'author': original.get('owner', {}).get('name', '未知作者'), + 'source': original.get('bvid', '未知ID'), + 'view_count': original.get('stat', {}).get('view', 0), + 'length': original.get('duration', 0), + } + + doc.metadata = metadata + bili.append(doc) + +except Exception as e: + print(f"加载BiliBili视频失败: {str(e)}") + +if not bili: + print("没有成功加载任何视频,程序退出") + exit() + +# 2. 创建向量存储 +embed_model = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5") +vectorstore = Chroma.from_documents(bili, embed_model) +``` + +在上面的代码中,首先使用 `BiliBiliLoader` 加载了几个B站视频的文档和元数据。需要注意的是,由于 `BiliBiliLoader` 返回的原始元数据结构较为复杂(例如,作者和观看数信息嵌套在其他字典中),所以进行了一些预处理工作:遍历每个文档,手动提取需要的字段(如`title`, `author`, `view_count`, `length`),并构建一个干净、扁平化的新 `metadata` 字典。这个过程确保了后续的自查询检索器能够直接、可靠地访问这些字段。最后,将处理好的文档和元数据存入 `Chroma` 向量数据库中,为下一步的查询构建做好准备。 + +```python +# 3. 配置元数据字段信息 +metadata_field_info = [ + AttributeInfo( + name="title", + description="视频标题(字符串)", + type="string", + ), + AttributeInfo( + name="author", + description="视频作者(字符串)", + type="string", + ), + AttributeInfo( + name="view_count", + description="视频观看次数(整数)", + type="integer", + ), + AttributeInfo( + name="length", + description="视频长度,以秒为单位的整数", + type="integer" + ) +] + +# 4. 创建自查询检索器 +llm = ChatDeepSeek( + model="deepseek-chat", + temperature=0, + api_key=os.getenv("DEEPSEEK_API_KEY") + ) + +retriever = SelfQueryRetriever.from_llm( + llm=llm, + vectorstore=vectorstore, + document_contents="记录视频标题、作者、观看次数等信息的视频元数据", + metadata_field_info=metadata_field_info, + enable_limit=True, + verbose=True +) + +# 5. 执行查询示例 +queries = [ + "时间最短的视频", + "时长大于600秒的视频" +] + +for query in queries: + print(f"\n--- 查询: '{query}' ---") + results = retriever.invoke(query) + if results: + for doc in results: + title = doc.metadata.get('title', '未知标题') + author = doc.metadata.get('author', '未知作者') + view_count = doc.metadata.get('view_count', '未知') + length = doc.metadata.get('length', '未知') + print(f"标题: {title}") + print(f"作者: {author}") + print(f"观看次数: {view_count}") + print(f"时长: {length}秒") + print("="*50) + else: + print("未找到匹配的视频") +``` + +这部分代码是实现自查询检索的核心。主要分为三个步骤: + +1. **配置元数据字段 (`metadata_field_info`)** :这是与LLM沟通的蓝图。通过 `AttributeInfo` 为每个元数据字段定义名称、类型和一份清晰的自然语言 `description`。LLM 将依赖这份描述来理解如何处理用户的查询,例如,它会根据“视频长度(整数)”的描述来解析关于“时长”的过滤和排序请求。因此,一份准确、无歧义的描述很重要。 + +2. **创建自查询检索器 (`SelfQueryRetriever.from_llm`)** :`from_llm` 方法在底层执行了两个核心操作: + * **加载查询构造器**:利用传入的 `llm`、`document_contents` 和 `metadata_field_info`,创建一个专门的“查询构造链”。这个链的核心职责是将用户的自然语言查询(如“时长大于600秒的视频”)转换为一个通用的、结构化的查询对象。 + * **获取内置翻译器**:接着,检查使用的向量数据库(这里是 `Chroma`),并为其匹配一个内置的“翻译器”。这个翻译器负责将上一步生成的通用查询对象,翻译成 `Chroma` 数据库能够原生理解和执行的过滤语法。 + +3. **执行查询 (`retriever.invoke`)** :最后,用自然语言发起调用。检索器内部会依次执行“构造”和“翻译”两个步骤,最终向 `Chroma` 发起一个同时包含语义搜索和精确元数据过滤的复合查询,从而返回最相关的结果。 + +> **提示**:在代码中可以看到 `temperature` 参数被设置为 `0`。这个值是用于控制模型输出的随机性。值越高(如 0.8),输出越随机、越有创意;值越低,输出越确定、越集中。设置为 `0` 可以让模型的输出变得完全确定,即对于相同的输入,总是生成完全相同的输出。在自查询这种需要精确地将自然语言转换为结构化查询的场景下,可以确保转换结果的稳定和可复现。 + +**输出结果:** + +```bash +--- 查询: '时间最短的视频' --- +INFO:httpx:HTTP Request: POST https://api.deepseek.com/v1/chat/completions "HTTP/1.1 200 OK" +INFO:langchain.retrievers.self_query.base:Generated Query: query=' ' filter=None limit=1 +标题: 《吴恩达 x OpenAI Prompt课程》【专业翻译,配套代码笔记】02.Prompt 的构建原则 +作者: 二次元的Datawhale +观看次数: 18788 +时长: 1063秒 +================================================== + +--- 查询: '时长大于600秒的视频' --- +INFO:httpx:HTTP Request: POST https://api.deepseek.com/v1/chat/completions "HTTP/1.1 200 OK" +INFO:langchain.retrievers.self_query.base:Generated Query: query=' ' filter=Comparison(comparator=, attribute='length', value=600) limit=None +WARNING:chromadb.segment.impl.vector.local_hnsw:Number of requested results 4 is greater than number of elements in index 3, updating n_results = 3 +标题: 《吴恩达 x OpenAI Prompt课程》【专业翻译,配套代码笔记】03.Prompt如何迭代优化 +作者: 二次元的Datawhale +观看次数: 7090 +时长: 806秒 +================================================== +标题: 《吴恩达 x OpenAI Prompt课程》【专业翻译,配套代码笔记】02.Prompt 的构建原则 +作者: 二次元的Datawhale +观看次数: 18788 +时长: 1063秒 +``` + +## 二、文本到Cypher + +除了处理扁平化的元数据,查询构建技术还能应用于更复杂的数据结构,如图数据库。 + +### 2.1 什么是 Cypher? + +Cypher 是图数据库(如 Neo4j)中最常用的查询语言,其地位类似于 SQL 之于关系数据库。它采用一种直观的方式来匹配图中的模式和关系,例如 `(:Person {name:"Tomaz"})-[:LIVES_IN]->(:Country {name:"Slovenia"})` 描述了一个人和一个国家以及他们之间的“居住在”关系。 + +### 2.2 “文本到Cypher”的原理 + +与“文本到元数据过滤器”类似,“文本到Cypher”技术利用大语言模型(LLM)将用户的自然语言问题直接翻译成一句精准的 Cypher 查询语句。LangChain 提供了相应的工具链(如 `GraphCypherQAChain`),其工作流程通常是: +1. 接收用户的自然语言问题。 +2. LLM 根据预先提供的图谱模式(Schema),将问题转换为 Cypher 查询。 +3. 在图数据库上执行该查询,获取精确的结构化数据。 +4. (可选)将查询结果再次交由 LLM,生成通顺的自然语言答案。 + +由于生成有效的 Cypher 查询是一项复杂的任务,通常使用性能较强的 LLM 来确保转换的准确性。通过这种方式,用户可以用最自然的方式与高度结构化的图数据进行交互,极大地降低了数据查询的门槛。 + +## 思考 + +- 为什么本节的代码中查询“时间最短的视频”时,得到的结果是错误的? + +## 参考文献 + +[^1]: [*LangChain Blog: Query Construction*](https://blog.langchain.ac.cn/query-construction/) diff --git a/docs/chapter4/13_text2sql.md b/docs/chapter4/13_text2sql.md new file mode 100644 index 0000000..bbd3ba1 --- /dev/null +++ b/docs/chapter4/13_text2sql.md @@ -0,0 +1,404 @@ +# 第三节 文本到SQL + +继上一节探讨了如何为元数据和图数据构建查询后,本节将聚焦于结构化数据领域中一个常见的应用。在数据世界中,除了向量数据库能够处理的非结构化数据,关系型数据库(如 MySQL, PostgreSQL, SQLite)同样是存储和管理结构化数据的重点。**文本到SQL(Text-to-SQL)**[^1] 正是为了打破人与结构化数据之间的语言障碍而生。它利用大语言模型(LLM)将用户的自然语言问题,直接翻译成可以在数据库上执行的SQL查询语句。 + +![](./images/4_3_1.webp) + +## 一、业务挑战 + +- **“幻觉”问题**:LLM 可能会“想象”出数据库中不存在的表或字段,导致生成的SQL语句无效。 +- **对数据库结构理解不足**:LLM 需要准确理解表的结构、字段的含义以及表与表之间的关联关系,才能生成正确的 `JOIN` 和 `WHERE` 子句。 +- **处理用户输入的模糊性**:用户的提问可能存在拼写错误或不规范的表达(例如,“上个月的销售冠军是谁?”),模型需要具备一定的容错和推理能力。 + +## 二、优化策略 + +1. **提供精确的数据库模式**:这是最基础也是最关键的一步。我们需要向LLM提供数据库中相关表的 `CREATE TABLE` 语句。这就像是给了LLM一张地图,让它了解数据库的结构,包括表名、列名、数据类型和外键关系。 + +2. **提供少量高质量的示例**:在提示(Prompt)中加入一些“问题-SQL”的示例对,可以极大地提升LLM生成查询的准确性。这相当于给了LLM几个范例,让它学习如何根据相似的问题构建查询。 + +3. **利用RAG增强上下文**:这是更进一步的策略。我们可以像RAGFlow一样,为数据库构建一个专门的“知识库”[^2],其中不仅包含表的DDL(数据定义语言),还可以包含: + * **表和字段的详细描述**:用自然语言解释每个表是做什么的,每个字段代表什么业务含义。 + * **同义词和业务术语**:例如,将用户的“花费”映射到数据库的 `cost` 字段。 + * **复杂的查询示例**:提供一些包含 `JOIN`、`GROUP BY` 或子查询的复杂问答对。 + 当用户提问时,系统首先从这个知识库中检索最相关的信息(如相关的表结构、字段描述、相似的Q&A),然后将这些信息和用户的问题一起组合成一个内容更丰富的提示,交给LLM生成最终的SQL查询。这种方式极大地降低了“幻觉”的风险,提高了查询的准确度。 + +4. **错误修正与反思 (Error Correction and Reflection)**:在生成SQL后,系统会尝试执行它。如果数据库返回错误,可以将错误信息反馈给LLM,让它“反思”并修正SQL语句,然后重试。这个迭代过程可以显著提高查询的成功率。 + +## 三、实现一个简单的Text2SQL框架 + +本节基于RAGFlow方案实现了一个简单的Text2SQL框架。该框架使用Milvus向量数据库作为知识库,BGE-M3模型进行语义检索,DeepSeek作为大语言模型,专门针对SQLite数据库进行了优化。 + +![Text2SQL框架工作流程](./images/4_3_2.webp) + +### 3.1 知识库模块 (`knowledge_base.py`) + +知识库模块是整个框架的核心,负责存储和检索SQL相关的知识信息。 + +```python +class SimpleKnowledgeBase: + """知识库""" + + def __init__(self, milvus_uri: str = "http://localhost:19530"): + self.milvus_uri = milvus_uri + self.client = MilvusClient(uri=milvus_uri) + self.embedding_function = BGEM3EmbeddingFunction(use_fp16=False, device="cpu") + self.collection_name = "text2sql_kb" + self._setup_collection() +``` + +**设计思想:** + +1. **统一知识管理**:将DDL定义、Q-SQL示例和表描述三种类型的知识统一存储在一个Milvus集合中,通过 `type` 字段区分。 + +2. **语义检索能力**:使用BGE-M3模型进行向量化,支持中英文混合的语义相似度搜索。 + +```python +def _setup_collection(self): + """设置集合""" + # 定义字段 + fields = [ + FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100), + FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=4096), + FieldSchema(name="type", dtype=DataType.VARCHAR, max_length=32), # ddl, qsql, description + FieldSchema(name="dense_vector", dtype=DataType.FLOAT_VECTOR, dim=self.embedding_function.dim["dense"]) + ] +``` + +**数据加载策略:** + +```python +def load_data(self): + """加载所有知识库数据""" + # 加载DDL数据 - 表结构定义 + # 加载Q->SQL数据 - 问答示例 + # 加载描述数据 - 表和字段的业务描述 +``` + +框架支持三种类型的知识: +- **DDL知识**[^3]:表的结构定义,包括字段类型、约束等 +- **Q-SQL知识**[^4]:历史问答对,为新问题提供参考模式 +- **描述知识**[^5]:表和字段的业务含义,帮助理解数据语义 + +**检索机制:** + +```python +def search(self, query: str, top_k: int = 5) -> List[Dict[str, Any]]: + """搜索相关内容""" + query_embeddings = self.embedding_function([query]) + + search_results = self.client.search( + collection_name=self.collection_name, + data=query_embeddings["dense"], + anns_field="dense_vector", + search_params={"metric_type": "IP"}, # 内积相似度 + limit=top_k, + output_fields=["content", "type"] + ) +``` + + + +### 3.2 SQL生成模块 (`sql_generator.py`) + +SQL生成模块负责将自然语言问题转换为SQL查询语句,并具备错误修复能力。 + +```python +class SimpleSQLGenerator: + """简化的SQL生成器""" + + def __init__(self, api_key: str = None): + self.llm = ChatDeepSeek( + model="deepseek-chat", + temperature=0, # 确保结果的确定性 + api_key=api_key or os.getenv("DEEPSEEK_API_KEY") + ) +``` + +**SQL生成策略:** + +```python +def generate_sql(self, user_query: str, knowledge_results: List[Dict[str, Any]]) -> str: + """生成SQL语句""" + # 构建上下文 + context = self._build_context(knowledge_results) + + # 构建提示 + prompt = f"""你是一个SQL专家。请根据以下信息将用户问题转换为SQL查询语句。 + +数据库信息: +{context} + +用户问题:{user_query} + +要求: +1. 只返回SQL语句,不要包含任何解释 +2. 确保SQL语法正确 +3. 使用上下文中提供的表名和字段名 +4. 如果需要JOIN,请根据表结构进行合理关联 + +SQL语句:""" +``` + +**关键设计原则:** + +1. **上下文驱动**:通过知识库检索结果构建丰富的上下文信息 +2. **结构化提示**:明确的任务要求和格式约束 +3. **确定性输出**:设置temperature=0确保相同输入产生相同输出 + +**错误修复机制:** + +```python +def fix_sql(self, original_sql: str, error_message: str, knowledge_results: List[Dict[str, Any]]) -> str: + """修复SQL语句""" + context = self._build_context(knowledge_results) + + prompt = f"""请修复以下SQL语句的错误。 + +数据库信息: +{context} + +原始SQL: +{original_sql} + +错误信息: +{error_message} + +请返回修复后的SQL语句(只返回SQL,不要解释):""" +``` + +**上下文构建策略:** + +```python +def _build_context(self, knowledge_results: List[Dict[str, Any]]) -> str: + """构建上下文信息""" + # 按类型分组 + ddl_info = [] # 表结构信息 + qsql_examples = [] # 查询示例 + descriptions = [] # 表描述信息 + + # 分层次组织信息:结构 → 描述 → 示例 + if ddl_info: + context += "=== 表结构信息 ===\n" + if descriptions: + context += "=== 表和字段描述 ===\n" + if qsql_examples: + context += "=== 查询示例 ===\n" +``` + + + +### 3.3 代理模块 (`text2sql_agent.py`) + +代理模块是整个框架的控制中心,协调知识库检索、SQL生成和执行的完整流程。 + +```python +class SimpleText2SQLAgent: + """Text2SQL代理""" + + def __init__(self, milvus_uri: str = "http://localhost:19530", api_key: str = None): + self.knowledge_base = SimpleKnowledgeBase(milvus_uri) + self.sql_generator = SimpleSQLGenerator(api_key) + + # 配置参数 + self.max_retry_count = 3 # 最大重试次数 + self.top_k_retrieval = 5 # 检索数量 + self.max_result_rows = 100 # 结果行数限制 +``` + +**主要查询流程:** + +```python +def query(self, user_question: str) -> Dict[str, Any]: + """执行Text2SQL查询""" + # 1. 从知识库检索相关信息 + knowledge_results = self.knowledge_base.search(user_question, self.top_k_retrieval) + + # 2. 生成SQL语句 + sql = self.sql_generator.generate_sql(user_question, knowledge_results) + + # 3. 执行SQL(带重试机制) + retry_count = 0 + while retry_count < self.max_retry_count: + success, result = self._execute_sql(sql) + + if success: + return {"success": True, "sql": sql, "results": result} + else: + # 尝试修复SQL + sql = self.sql_generator.fix_sql(sql, result, knowledge_results) + retry_count += 1 +``` + +**安全执行策略:** + +```python +def _execute_sql(self, sql: str) -> Tuple[bool, Any]: + """执行SQL语句""" + # 添加LIMIT限制,防止大量数据返回 + if sql.strip().upper().startswith('SELECT') and 'LIMIT' not in sql.upper(): + sql = f"{sql.rstrip(';')} LIMIT {self.max_result_rows}" + + # 结构化结果返回 + if sql.strip().upper().startswith('SELECT'): + columns = [desc[0] for desc in cursor.description] + rows = cursor.fetchall() + + results = [] + for row in rows: + result_row = {} + for i, value in enumerate(row): + result_row[columns[i]] = value + results.append(result_row) + + return True, {"columns": columns, "rows": results, "count": len(results)} +``` + +### 3.4 完整流程模拟 + +以查询"年龄大于30的用户有哪些"为例,演示框架三个核心模块的完整协作过程: + +#### 3.4.1 模拟数据 + +假设数据库中的users表包含以下用户数据: + +| ID | 姓名 | 邮箱 | 年龄 | 城市 | +|----|------|------|------|------| +| 1 | 张三 | zhangsan@email.com | 25 | 北京 | +| 2 | 李四 | lisi@email.com | 32 | 上海 | +| 3 | 王五 | wangwu@email.com | 28 | 广州 | +| 4 | 赵六 | zhaoliu@email.com | 35 | 深圳 | +| 5 | 陈七 | chenqi@email.com | 29 | 杭州 | + +#### 3.4.2 Step 1: 知识库检索 + +**用户输入**:"年龄大于30的用户有哪些" + +**检索过程**: +1. BGE-M3模型将查询文本转换为768维向量 +2. Milvus在知识库中进行语义相似度搜索 +3. 返回最相关的5条知识,按相似度排序 + +**检索结果**: + +**DDL知识** (相似度: 0.85) +- 表名:users +- 结构:包含id、name、email、age、city字段 +- 约束:id为主键,email唯一 + +**Q-SQL示例** (相似度: 0.82) +- 问题:"查询年龄超过25岁的用户" +- SQL:`SELECT * FROM users WHERE age > 25` +> 这是检索到的相似示例,最终SQL会基于用户实际问题调整为age > 30 + +**表描述** (相似度: 0.78) +- age字段:用户年龄,整数类型 +- name字段:用户姓名,文本类型 + +#### 3.4.3 Step 2: SQL生成 + +**上下文构建**: +系统将检索到的知识整理成结构化的上下文信息: + +**表结构信息** +- 表名:users +- DDL定义:完整的CREATE TABLE语句 +- 字段约束:主键、唯一性等 + +**表和字段描述** +- age字段:用户年龄,INTEGER类型 +- name字段:用户姓名,TEXT类型 + +**查询示例** +- 相似问题:查询年龄超过25岁的用户 +- 参考SQL:`SELECT * FROM users WHERE age > 25` + +**SQL生成过程**: +1. DeepSeek分析用户问题的意图:查询满足年龄条件的用户 +2. 识别关键信息:年龄字段(age)、比较操作(大于)、阈值(**30**) +3. 参考示例模式:从`WHERE age > 25`学习到`WHERE age > 数值`的模式 +4. 模式应用:将用户的实际数值30替换示例中的25 +5. 生成目标SQL:`SELECT * FROM users WHERE age > 30` + +#### 3.4.4 Step 3: SQL执行与结果处理 + +**安全处理**: +- 原始SQL:`SELECT * FROM users WHERE age > 30` +- 自动添加限制:`SELECT * FROM users WHERE age > 30 LIMIT 100` + +**数据库执行**: +SQLite引擎逐行检查users表中的数据: + +| 用户 | 年龄检查 | 结果 | +|------|----------|------| +| 张三 | 25 > 30? | ❌ 不符合 | +| 李四 | 32 > 30? | ✅ 符合 | +| 王五 | 28 > 30? | ❌ 不符合 | +| 赵六 | 35 > 30? | ✅ 符合 | +| 陈七 | 29 > 30? | ❌ 不符合 | + +**结果处理**: +- 筛选出2条符合条件的记录 +- 转换为结构化JSON格式 +- 包含字段名称和数据类型信息 + +**最终输出**: +```json +{ + "success": true, + "error": null, + "sql": "SELECT * FROM users WHERE age > 30 LIMIT 100", + "results": { + "columns": ["id", "name", "email", "age", "city"], + "rows": [ + {"id": 2, "name": "李四", "email": "lisi@email.com", "age": 32, "city": "上海"}, + {"id": 4, "name": "赵六", "email": "zhaoliu@email.com", "age": 35, "city": "深圳"} + ], + "count": 2 + }, + "retry_count": 0 +} +``` + +通过这个**语义理解 → 结构化查询 → 数据过滤 → 结果输出**的完整流程,框架成功将用户的自然语言问题转换为精确的数据库查询结果。 + +### 3.5 代码运行 + +如果你想测试这个Text2SQL框架,可以通过以下方式进行: + +**快速体验**:运行演示程序 +```bash +python code/C4/03_text2sql_demo.py +``` +> 完整演示代码:[03_text2sql_demo.py](https://github.com/datawhalechina/all-in-rag/blob/main/code/C4/03_text2sql_demo.py) + +**核心代码获取**:三个核心模块的完整实现 +- `knowledge_base.py` - 知识库模块 +- `sql_generator.py` - SQL生成模块 +- `text2sql_agent.py` - 代理协调模块 + +> 源码地址:[code/C4/text2sql/](https://github.com/datawhalechina/all-in-rag/tree/main/code/C4/text2sql) + +**数据资源**:框架使用的JSON知识数据 +- `ddl_examples.json` - DDL结构示例 +- `qsql_examples.json` - 问题-SQL对示例 +- `db_descriptions.json` - 表和字段描述 + +> 数据文件:[code/C4/text2sql/data/](https://github.com/datawhalechina/all-in-rag/tree/main/code/C4/text2sql/data) + +### 3.6 为什么不直接使用封装好的框架? + +> 因为淋过雨,所以想为你撑把伞🤪 + +市面上确实有很多成熟的Text2SQL框架,但这些高度封装的工具往往存在**黑盒问题**——当查询结果不符合预期时,很难定位是检索环节、SQL生成环节还是执行环节出了问题。正如上一节LangChain示例中遇到的查询异常,我们很难深入到框架内部进行精确调试和优化。这一点在索引优化那节中也提到过。 + +## 参考文献 + +[^1]: [*LangChain Docs: Text to SQL*](https://python.langchain.com/docs/tutorials/sql_qa/) + +[^2]: [*RAGFlow Blog: Implementing Text2SQL with RAGFlow*](https://ragflow.io/blog/implementing-text2sql-with-ragflow) + +[^3]: DDL(Data Definition Language)是数据定义语言,用于定义数据库结构,如CREATE TABLE语句。 + +[^4]: Q-SQL示例是指"问题-SQL"对,即自然语言问题与对应SQL查询的配对示例,用于少样本学习。 + +[^5]: 表描述是对数据库表和字段的业务语义说明,帮助模型理解数据的实际含义和用途。 diff --git a/docs/chapter4/14_query_rewriting.md b/docs/chapter4/14_query_rewriting.md new file mode 100644 index 0000000..967d96f --- /dev/null +++ b/docs/chapter4/14_query_rewriting.md @@ -0,0 +1,315 @@ +# 第四节 查询重构与分发 + +此前已经学习了如何从不同类型的数据源(如向量数据库、关系型数据库)中构建查询。然而,用户的原始问题往往不是最优的检索输入。它可能过于复杂、包含歧义,或者与文档的实际措辞存在偏差。为了解决这些问题,我们需要在检索之前对用户的查询进行“预处理”,这就是本节要探讨的**查询重构与分发**。 + +这个阶段主要包含两个关键技术: + +1. **查询翻译(Query Translation)**:将用户的原始问题转换成一个或多个更适合检索的形式。 +2. **查询路由(Query Routing)**:根据问题的性质,将其智能地分发到最合适的数据源或检索器。 + +本节将重点介绍几种主流的查询翻译技术,并简要讨论查询路由的概念。 + +## 一、查询翻译 + +查询翻译的目标是弥合用户自然语言提问与文档库中存储信息之间的“语义鸿沟”。通过重写、分解或扩展查询,我们可以显著提升检索的准确率。 + +### 1.1 提示工程 + +这是最直接的查询重构方法。通过精心设计的提示词(Prompt),可以引导 LLM 将用户的原始查询改写得更清晰、更具体,或者转换成一种更利于检索的叙述风格。 + +在第二节查询构建的代码示例中,我们发现 `SelfQueryRetriever` 无法正确处理“时间最短的视频”这类需要排序或进行比较的查询。 + +为了解决这个问题,可以采用一种更高级的提示工程技巧:**让 LLM 直接构建出查询指令**。 + +这种方法的思路是,要求 LLM 直接分析用户的意图,并生成一个结构化(例如 JSON 格式)的指令,告诉我们的代码应该如何操作。对于“时间最短的视频”这个问题,我们期望 LLM 能直接告诉我们:“请按‘时长’字段进行升序排序,并返回第一条结果”。 + +下面,来看看如何修改代码来实现这一思路。我们不再使用 `SelfQueryRetriever`,而是直接与 LLM 交互,并根据其返回的指令在代码中执行排序逻辑。 + +关键的修改主要有两部分: + +(1)**设计一个新的提示词(Prompt),要求 LLM 输出 JSON 格式的排序指令。** + +```python +# 使用大模型将自然语言转换为排序指令 +prompt = f"""你是一个智能助手,请将用户的问题转换成一个用于排序视频的JSON指令。 + +你需要识别用户想要排序的字段和排序方向。 +- 排序字段必须是 'view_count' (观看次数) 或 'length' (时长) 之一。 +- 排序方向必须是 'asc' (升序) 或 'desc' (降序) 之一。 + +例如: +- '时间最短的视频' 或 '哪个视频时间最短' 应转换为 {{"sort_by": "length", "order": "asc"}} +- '播放量最高的视频' 或 '哪个视频最火' 应转换为 {{"sort_by": "view_count", "order": "desc"}} + +请根据以下问题生成JSON指令: +原始问题: "{query}" + +JSON指令:""" +``` + +(2)**在代码中调用 LLM,解析其返回的 JSON 指令,并执行相应的排序操作。** + +```python +# ... (前略,初始化LLM客户端) + +# 请求LLM生成指令,并指定返回JSON格式 +response = client.chat.completions.create( + model="deepseek-chat", + messages=[ + {"role": "user", "content": prompt} + ], + temperature=0, + response_format={"type": "json_object"} +) + +# 解析指令并执行排序 +try: + import json + instruction_str = response.choices[0].message.content + instruction = json.loads(instruction_str) + print(f"--- 生成的排序指令: {instruction} ---") + + sort_by = instruction.get('sort_by') + order = instruction.get('order') + + if sort_by in ['length', 'view_count'] and order in ['asc', 'desc']: + # 在代码中执行排序 + reverse_order = (order == 'desc') + sorted_docs = sorted(all_documents, key=lambda doc: doc.metadata.get(sort_by, 0), reverse=reverse_order) + # 获取排序后的第一个结果并打印 + if sorted_docs: + doc = sorted_docs[0] + # ... (打印结果的代码) + +except (json.JSONDecodeError, KeyError) as e: + print(f"解析或执行指令失败: {e}") +``` + +通过这种方式,成功地将 LLM 从一个简单的“文本改写员”提升为了一个能够理解复杂意图并生成可执行计划的“智能代理”,从而优雅地解决了“最值”查询的难题。 + +> [完整代码](https://github.com/datawhalechina/all-in-rag/tree/main/code/C4/04_text_to_metadata_filter_v2.py) + +### 1.2 多查询分解 (Multi-query) + +当用户提出一个复杂的问题时,直接用整个问题去检索可能效果不佳,因为它可能包含多个子主题或意图。分解技术的核心思想是将这个复杂问题拆分成多个更简单、更具体的子问题。然后,系统分别对每个子问题进行检索,最后将所有检索到的结果合并、去重,形成一个更全面的上下文,再交给 LLM 生成最终答案。 + +**示例**: +- **原始问题**:“在《流浪地球》中,刘慈欣对人工智能和未来社会结构有何看法?” +- **分解后的子问题**: + - “《流浪地球》中描述的人工智能技术有哪些?” + - “《流浪地球》中描绘的未来社会是怎样的?” + - “刘慈欣关于人工智能的观点是什么?” + +LangChain 提供了 `MultiQueryRetriever` 来完成这一过程[^1]。它在内部利用 LLM 将原始问题从不同角度分解成多个子问题,然后并行为每个子问题检索相关文档。最后,它将所有检索到的文档合并并去重,形成一个更全面的上下文,再传递给语言模型生成最终答案。通过这种策略,极大地丰富了检索结果,在有些应用中可以有效提升后续生成环节的质量。 + +### 1.3 退步提示(Step-Back Prompting) + +退步提示是由 Google DeepMind 团队提出的一种旨在提升大语言模型推理能力的提示工程技巧[^2]。当面对一个细节繁多或过于具体的问题时,模型直接作答(即便是使用思维链)也容易出错。退步提示通过引导模型“退后一步”来解决这个问题。 + +其核心流程分为两步: + +(1)**抽象化**:首先,引导 LLM 从用户的原始具体问题中,生成一个更高层次、更概括的“退步问题”(Step-back Question)。这个退步问题旨在探寻原始问题背后的通用原理或核心概念。 + +(2)**推理**:接着,系统会先获取“退步问题”的答案(例如,一个物理定律、一段历史背景等),然后将这个通用原理作为上下文,再结合原始的具体问题,进行推理并生成最终答案。 + +![“退步提示”与“思维链”对比图](./images/4_4_1.webp) + +**示例**: +- **原始问题**:“如果理想气体的温度增加2倍,体积增加8倍,其压力会如何变化?” +- **退步问题**:“这个问题背后的物理原理是什么?” +- **推理过程**:首先回答退步问题,得到“理想气体定律 PV=nRT”。然后基于这个定律,代入具体数值进行计算,最终得出压力变为原来的1/4。 + +通过先检索或生成高层知识,再进行具体推理,退步提示能够帮助模型构建一个更坚实的逻辑基础,从而提高在复杂问答场景下的准确性。 + +### 1.4 假设性文档嵌入 (HyDE) + +假设性文档嵌入(Hypothetical Document Embeddings, HyDE)是一种无需微调即可显著提升向量检索质量的查询改写技术,由 Luyu Gao 等人在其论文中首次提出[^3]。其核心是解决一个普遍存在于检索任务中的难题:用户的查询(Query)通常简短、关键词有限,而数据库中存储的文档则内容详实、上下文丰富,两者在语义向量空间中可能存在“鸿沟”,导致直接用查询向量进行搜索效果不佳。Zilliz 的一篇技术博客[^4]也对该技术进行了深入浅出的解读。 + +![HyDE](./images/4_4_2.webp) + +HyDE 通过一种巧妙的方式来“绕过”这个问题:它不直接使用用户的原始查询,而是先利用一个生成式大语言模型(LLM)来生成一个“假设性”的、能够完美回答该查询的文档。然后,HyDE 将这个内容详实的假设性文档进行向量化,用其生成的向量去数据库中寻找与之最相似的真实文档。HyDE 的工作流程可以分为三个步骤: + +(1)**生成**:当接收到用户查询时,首先调用一个生成式 LLM(例如,GPT-3.5)。提示该模型根据查询生成一个详细的、可能是理想答案的文档。这个文档不必完全符合事实,但它必须在语义上与一个好的答案高度相关。 + +(2)**编码**:将上一步生成的假设性文档输入到一个对比编码器(如 Contriever)中,将其转换为一个高维向量嵌入。这个向量在语义上代表了一个“理想答案”的位置。 + +(3)**检索**:使用这个假设性文档的向量,在向量数据库中执行相似性搜索,找出与这个“理想答案”最接近的真实文档。这些被检索出的文档将作为最终的上下文信息。 + +通过这种方式,HyDE 将困难的“查询到文档”的匹配问题,转化为了一个相对容易的“文档到文档”的匹配问题,从而提升检索的准确率。 + +## 二、查询路由 + +**查询路由(Query Routing)** 是用于优化复杂 RAG 系统的一项关键技术。当系统接入了多个不同的数据源或具备多种处理能力时,就需要一个“智能调度中心”来分析用户的查询,并动态选择最合适的处理路径。其本质是替代硬编码规则,通过语义理解将查询分发至最匹配的数据源、处理组件或提示模板,从而提升系统的效率与答案的准确性。 + +### 2.1 应用场景 + +查询路由的应用场景十分广泛。 + +1. **数据源路由**:这是最常见的场景。根据查询意图,将其路由到不同的知识库。例如: + * 查询“最新的 iPhone 有什么功能?” -> 路由到**产品文档向量数据库**。 + * 查询“我上次订购了什么?” -> 路由到**用户历史SQL数据库**(执行Text-to-SQL)。 + * 查询“A公司和B公司的投资关系是怎样的?” -> 路由到**企业知识图谱数据库**。 + +2. **组件路由**:根据问题的复杂性,将其分配给不同的处理组件,以平衡成本和效果。 + * 简单FAQ → 直接进行向量检索,速度快、成本低。 + * 复杂操作或需要与外部API交互 → 调用 Agent 来执行任务。 + +3. **提示模板路由**:为不同类型的任务动态选择最优的提示词模板,以优化生成效果。 + * 数学问题 → 选用包含分步思考(Step-by-Step)逻辑的提示模板。 + * 代码生成 → 选用专门为代码优化过的提示模板。 + +### 2.2 实现方法 + +实现查询路由主要有两种主流方法[^5]: + +#### 2.2.1 基于LLM的意图识别 + +这是最灵活的方法。通过设计一个包含路由选项的提示词,让大语言模型(LLM)直接对用户的查询进行分类,并输出一个代表路由选择的标签。 + +![逻辑路由](./images/4_4_3.webp) + +* **实现流程**: + 1. 定义清晰的路由选项(例如,数据源名称、功能分类)。 + 2. LLM 分析查询并输出决策标签。 + 3. 代码根据标签调用相应的检索器或工具。 + +该方法的核心在于构建一个“分类-分发”的流水线。这里以一个菜谱问答为例,系统需要根据用户提问的菜系(川菜、粤菜或其他)调用不同的专家模型。 + +> 接下来的代码示例广泛使用了 **LCEL**[^6],它是 LangChain 中用于构建链(Chain)的声明式方法。其核心是 `|` (管道)符号,可以将不同的组件(如提示、模型、解析器)串联起来,形成一个处理流水线。例如,`prompt | llm | parser` 就清晰地定义了一个“提示->模型->解析器”的调用顺序。这种方式不仅代码可读性强,而且 LangChain 会在底层自动进行并行、异步和流式等优化。 + +**第一步:定义分类器** + +首先创建一个 `classifier_chain`,它的任务是读取用户问题,并利用 LLM 的理解能力给问题打上分类标签(例如 '川菜', '粤菜', '其他')。 + +```python +# 假设 llm 已经定义 +classifier_prompt = ChatPromptTemplate.from_template( + """根据用户问题中提到的菜品,将其分类为:['川菜', '粤菜', 或 '其他']。 + 不要解释你的理由,只返回一个单词的分类结果。 + 问题: {question}""" +) +classifier_chain = classifier_prompt | llm | StrOutputParser() +``` + +**第二步:定义路由分支** + +接着,使用 `RunnableBranch` 来定义路由规则。它就像一个 `if-elif-else` 语句,根据输入的 `topic` 字段来选择执行哪一个处理链(`sichuan_chain`, `cantonese_chain` 或 `general_chain`)。 +```python +# 假设 sichuan_chain, cantonese_chain, general_chain 已定义 +router_branch = RunnableBranch( + (lambda x: "川菜" in x["topic"], sichuan_chain), + (lambda x: "粤菜" in x["topic"], cantonese_chain), + general_chain # 默认选项 +) +``` + +**第三步:组合完整路由链** + +最后,将分类器和路由分支组合起来。这个 `full_router_chain` 首先会并行执行两个操作:用 `classifier_chain` 为问题生成 `topic`,同时保留原始的 `question`。然后,它将这个包含 `topic` 和 `question` 的字典传递给 `router_branch`,由后者根据 `topic` 做出最终的路由决策。 + +```python +full_router_chain = {"topic": classifier_chain, "question": lambda x: x["question"]} | router_branch + +# 调用示例 +# result = full_router_chain.invoke({"question": "麻婆豆腐怎么做?"}) +``` + +> [完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C4/05_llm_based_routing.py) + +#### 2.2.2 嵌入相似性路由 + +这种方法不依赖 LLM 进行分类,延迟更低。它通过计算用户查询与预设的“路由示例语句”之间的向量嵌入相似度来做出决策。 + +![语义路由](./images/4_4_4.webp) + +**第一步:定义路由描述并向量化** + +为每个路由创建一个详细的文本描述,并使用嵌入模型将其转换为向量,供后续相似度计算使用。 + +```python +# 假设 embeddings 模型已经初始化 +sichuan_route_prompt = "你是一位处理川菜的专家。用户的问题是关于麻辣、辛香、重口味的菜肴,例如水煮鱼、麻婆豆腐、鱼香肉丝、宫保鸡丁、花椒、海椒等。" +cantonese_route_prompt = "你是一位处理粤菜的专家。用户的问题是关于清淡、鲜美、原汁原味的菜肴,例如白切鸡、老火靓汤、虾饺、云吞面等。" + +route_prompts = [sichuan_route_prompt, cantonese_route_prompt] +route_names = ["川菜", "粤菜"] +route_prompt_embeddings = embeddings.embed_documents(route_prompts) +``` + +**第二步:定义目标链** + +创建路由最终要分发到的目标处理链,并用一个字典 `route_map` 将路由名称和链对应起来。 + +```python +# 假设 llm 已经定义 +sichuan_chain = ( + PromptTemplate.from_template("你是一位川菜大厨。请用正宗的川菜做法,回答关于「{query}」的问题。") + | llm + | StrOutputParser() +) +cantonese_chain = ( + PromptTemplate.from_template("你是一位粤菜大厨。请用经典的粤菜做法,回答关于「{query}」的问题。") + | llm + | StrOutputParser() +) + +route_map = { "川菜": sichuan_chain, "粤菜": cantonese_chain } +``` + +**第三步:定义路由函数** + +定义一个 `route` 函数,接收用户问题,计算与各路由描述的相似度,选择最相似的路由并调用相应的处理链。 + +```python +def route(info): + # 1. 对用户查询进行嵌入 + query_embedding = embeddings.embed_query(info["query"]) + + # 2. 计算与各路由提示的余弦相似度 + similarity_scores = cosine_similarity([query_embedding], route_prompt_embeddings)[0] + + # 3. 找到最相似的路由名称 + chosen_route_index = np.argmax(similarity_scores) + chosen_route_name = route_names[chosen_route_index] + + # 4. 获取并调用对应的处理链,返回结果 + chosen_chain = route_map[chosen_route_name] + return chosen_chain.invoke(info) +``` + +**第四步:组合并调用** + +最后,将 `route` 函数包装成一个 `RunnableLambda`,形成一个完整的、可执行的路由链。 + +```python +full_chain = RunnableLambda(route) + +# 调用示例 +# result = full_chain.invoke({"question": "如何做一碗清淡的云吞面?"}) +``` + +> [完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C4/06_embedding_based_routing.py) + +### 2.3 LlamaIndex 拓展 + +与 LangChain 类似,LlamaIndex 也提供了强大的查询路由功能[^7],其思路是将不同的数据源或查询策略包装为“工具(Tool)”,然后通过一个“路由器(Router)”来为用户查询动态选择最合适的工具。实现方式与 LangChain 有异曲同工之处: + +* **基于LLM的意图识别**:这是 LlamaIndex 的主要实现方式。通过 `RouterQueryEngine` 来管理一组 `QueryEngineTool`。每个 `Tool` 都包含一个查询引擎和一段描述其功能的文本。路由器会利用一个 `Selector`(如 `LLMSingleSelector` 或更稳定的 `PydanticSingleSelector`)来让 LLM 根据工具的描述文本和用户问题进行语义匹配,从而选择一个或多个最合适的工具来执行。 + +* **嵌入相似性路由**:LlamaIndex 没有提供直接基于向量相似度计算的独立路由组件。它的“语义路由”是融合在基于 LLM 的意图识别中的——即让 LLM 理解每个 `Tool` 描述的 *语义*,并据此做出决策。这种方式更灵活,能够处理更复杂的路由逻辑,而不仅仅是文本相似度匹配。 + +## 参考文献 + +[^1]: [*How to use the MultiQueryRetriever*](https://python.langchain.com/docs/how_to/MultiQueryRetriever/) + +[^2]: [Zheng, H. S. et al. (2023). *Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models*](https://arxiv.org/abs/2310.06117). + +[^3]: [Gao, L. et al. (2022). *Precise Zero-Shot Dense Retrieval without Relevance Labels*](https://arxiv.org/abs/2212.10496). + +[^4]: [*使用假设性文档嵌入(HyDE)改进信息检索和 RAG*](https://zilliz.com.cn/blog/improve-rag-and-information-retrieval-with-hyde-hypothetical-document-embeddings). + +[^5]: [*How to route between sub-chains*](https://python.langchain.com/docs/how_to/routing/). + +[^6]: [*LangChain Expression Language*](https://python.langchain.com/docs/concepts/lcel/). + +[^7]: [*LlamaIndex Routing*](https://docs.llamaindex.ai/en/stable/module_guides/querying/router/). \ No newline at end of file diff --git a/docs/chapter4/15_advanced_retrieval_techniques.md b/docs/chapter4/15_advanced_retrieval_techniques.md new file mode 100644 index 0000000..d2254a8 --- /dev/null +++ b/docs/chapter4/15_advanced_retrieval_techniques.md @@ -0,0 +1,354 @@ +# 第五节 检索进阶 + +在基础的 RAG 流程中,依赖向量相似度从知识库中检索信息。不过,这种方法存在一些固有的局限性,例如最相关的文档不总是在检索结果的顶端,以及语义理解的偏差等。为了构建更强大、更精准的生产级 RAG 应用,需要引入更高级的检索技术。 + +![retrieval](images/4_5_1.webp) + +## 一、重排序 (Re-ranking) + +### 1.1 RRF (Reciprocal Rank Fusion) + +我们在 [**混合检索章节**](./11_hybrid_search.md) 中已经接触过 RRF。它是一种简单而有效的**零样本**重排方法,不依赖于任何模型训练,而是纯粹基于文档在多个不同检索器(例如,一个稀疏检索器和一个密集检索器)结果列表中的**排名**来计算最终分数。 + +一个文档如果在多个检索结果中都排名靠前,那么它很可能更重要。RRF 通过计算排名的倒数来为文档打分,有效融合了不同检索策略的优势。但是如果只考虑排名信息,会忽略原始的相似度分数,可能丢失部分有用信息。 + +### 1.2 RankLLM / LLM-based Reranker + +![rankllm](images/4_5_2.webp) + +RankLLM 代表了一类直接利用大型语言模型本身来进行重排的方法[^1]。其基本逻辑非常直观:既然 LLM 最终要负责根据上下文来生成答案,那么为什么不直接让它来判断哪些上下文最相关呢? + +这种方法通过一个精心设计的提示词来实现。该提示词会包含用户的查询和一系列候选文档(通常是文档的摘要或关键部分),然后要求 LLM 以特定格式(如 JSON)输出一个排序后的文档列表,并给出每个文档的相关性分数。 + +一个提示词示例如下: + +```text +以下是一个文档列表,每个文档都有一个编号和摘要。同时提供一个问题。请根据问题,按相关性顺序列出您认为需要查阅的文档编号,并给出相关性分数(1-10分)。请不要包含与问题无关的文档。 + +示例格式: +文档 1: <文档1的摘要> +文档 2: <文档2的摘要> +... +文档 10: <文档10的摘要> + +问题: <用户的问题> + +回答: +Doc: 9, Relevance: 7 +Doc: 3, Relevance: 4 +Doc: 7, Relevance: 3 +``` + +### 1.3 Cross-Encoder 重排 + +Cross-Encoder(交叉编码器)能提供出色的重排精度[^2]。它的工作原理是将查询(Query)和每个候选文档(Document)**拼接**成一个单一的输入(例如,`[CLS] query [SEP] document [SEP]`),然后将这个整体输入到一个预训练的 Transformer 模型(如 BERT)中,模型最终会输出一个单一的分数(通常在 0 到 1 之间),这个分数直接代表了文档与查询的**相关性**。 + +> 注:**[SEP]** 是在 BERT 这类基于 Transformer 架构的模型中,用于分隔不同文本片段(如查询和文档)的特殊标记。 + +
+cross-encoder +
+ +上图清晰地展示了 Cross-Encoder 的工作流程: +1. **初步检索**:搜索引擎首先从知识库中召回一个初始的文档列表(例如,前 50 篇)。 +2. **逐一评分**:对于列表中的**每一篇**文档,系统都将其与原始查询**配对**,然后发送给 Cross-Encoder 模型。 +3. **独立推理**:模型对每个“查询-文档”对进行一次完整的、独立的推理计算,得出一个精确的相关性分数。 +4. **返回重排结果**:系统根据这些新的分数对文档列表进行重新排序,并将最终结果返回给用户。 + +这个流程凸显了其高精度的来源(同时分析查询和文档),也解释了其高延迟的原因(需要N次独立的模型推理)。 + +常见的 Cross-Encoder 模型包括 `ms-marco-MiniLM-L-12-v2`、`ms-marco-TinyBERT-L-2-v2` 等。 + +### 1.4 ColBERT 重排 + +ColBERT(Contextualized Late Interaction over BERT)是一种创新的重排模型,它在 Cross-Encoder 的高精度和双编码器(Bi-Encoder)的高效率之间取得了平衡[^3]。采用了一种“**后期交互**”机制。 + +其工作流程如下: + +1. **独立编码**:ColBERT 分别为查询(Query)和文档(Document)中的每个 Token 生成上下文相关的嵌入向量。这一步是独立完成的,可以预先计算并存储文档的向量,从而加快查询速度。 +2. **后期交互**:在查询时,模型会计算查询中每个 Token 的向量与文档中每个 Token 向量之间的最大相似度(MaxSim)。 +3. **分数聚合**:最后,将查询中所有 Token 得到的最大相似度分数相加,得到最终的相关性总分。 + +通过这种方式,ColBERT 避免了将查询和文档拼接在一起进行昂贵的联合编码,同时又比单纯比较单个 `[CLS]` 向量的双编码器模型捕捉了更细粒度的词汇级交互信息。 + +### 1.5 重排方法对比 + +为了更直观地理解不同重排方法的特点和适用场景,下表对讨论过的几种主流方法进行了总结: + +| 特性 | RRF | RankLLM | Cross-Encoder | ColBERT | +| :--- | :--- | :--- | :--- | :--- | +| **核心机制** | 融合多个排名 | LLM 推理,生成排序列表 | 联合编码查询与文档,计算单一相关分 | 独立编码,后期交互 | +| **计算成本** | 低(简单数学计算) | 中 (API 费用与延迟) | 高(N次模型推理) | 中(向量点积计算) | +| **交互粒度** | 无(仅排名) | 概念/语义级 | 句子级(Query-Doc Pair) | Token 级 | +| **适用场景** | 多路召回结果融合 | 高价值语义理解场景 | Top-K 精排 | Top-K 重排 | + +## 二、压缩 (Compression) + +“压缩”技术旨在解决一个常见问题:初步检索到的文档块(Chunks)虽然整体上与查询相关,但可能包含大量无关的“噪音”文本。将这些未经处理的、冗长的上下文直接提供给 LLM,不仅会增加 API 调用的成本和延迟,还可能因为信息过载而降低最终生成答案的质量。 + +压缩的目标就是对检索到的内容进行“压缩”和“提炼”,只保留与用户查询最直接相关的信息。这可以通过两种主要方式实现: +1. **内容提取**:从文档中只抽出与查询相关的句子或段落。 +2. **文档过滤**:完全丢弃那些虽然被初步召回,但经过更精细判断后认为不相关的整个文档。 + +### 2.1 LangChain 的 ContextualCompressionRetriever + +LangChain 提供了一个强大的组件 `ContextualCompressionRetriever` 来实现上下文压缩[^4]。它像一个包装器,包裹在基础的检索器(如 `FAISS.as_retriever()`)之上。当基础检索器返回文档后,`ContextualCompressionRetriever` 会使用一个指定的 `DocumentCompressor` 对这些文档进行处理,然后再返回给调用者。 + +LangChain 内置了多种 `DocumentCompressor`: + +* `LLMChainExtractor`: 这是最直接的压缩方式。它会遍历每个文档,并利用一个 LLM Chain 来判断并提取出其中与查询相关的部分。这是一种“内容提取”。 +* `LLMChainFilter`: 这种压缩器同样使用 LLM,但它做的是“文档过滤”。它会判断整个文档是否与查询相关,如果相关,则保留整个文档;如果不相关,则直接丢弃。 +* `EmbeddingsFilter`: 这是一种更快速、成本更低的过滤方法。它会计算查询和每个文档的嵌入向量之间的相似度,只保留那些相似度超过预设阈值的文档。 + +### 2.2 自定义重排器与压缩管道 + +在前面我们就提到根据实际应用,需要自己进行一些功能的实现。这里以 ColBERT 为例,展示如何集成未被官方支持的功能。 + +整个探索和实现过程如下: + +1. **从官方文档出发**:首先,通过 LangChain 官方文档,了解到可以通过 `DocumentCompressorPipeline` 来组合多个压缩器和文档转换器。 +2. **需求缺口**:希望使用 ColBERT 模型进行重排,但发现 LangChain 并没有内置的 `ColBERT` 重排器。 +3. **分析示例与源码**:回头分析 `ContextualCompressionRetriever` 的用法和源码。我们发现,其处理逻辑分为两步:首先使用 `base_retriever` 获取原始文档,然后将这些文档交给 `base_compressor` 进行压缩或重排。这说明,实现自定义后处理(如重排)功能的关键在于 `base_compressor`。 +4. **定位核心基类**:通过f12查看源码,确定 `base_compressor` 参数接收的是 `BaseDocumentCompressor` 类型的对象。这就是实现自定义功能的核心切入点。 +5. **参考与实现**:最后,参考 LangChain 中其他重排器的实现方式,通过继承 `BaseDocumentCompressor` 基类并实现其关键方法,创建自己的 `ColBERTReranker` 类。 + +> PS:如果代码基础薄弱,想借助大模型帮你完成 `ColBERTReranker` ,需要提供给大模型的关键信息:`BaseDocumentCompressor` 的源码和 `ContextualCompressionRetriever` 的源码及其使用示例、你的明确目标(实现 ColBERT 重排逻辑)、以及 LangChain 中其他重排器的代码作为参考。信息越充分,模型生成的代码越准确。 + +#### 代码示例 + +自定义 `ColBERTReranker` 的代码实现: + +```python +class ColBERTReranker(BaseDocumentCompressor): + """ColBERT重排器""" + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + model_name = "bert-base-uncased" + + # 加载模型和分词器 + object.__setattr__(self, 'tokenizer', AutoTokenizer.from_pretrained(model_name)) + object.__setattr__(self, 'model', AutoModel.from_pretrained(model_name)) + self.model.eval() + print(f"ColBERT模型加载完成") + + def encode_text(self, texts): + """ColBERT文本编码""" + inputs = self.tokenizer( + texts, + return_tensors="pt", + padding=True, + truncation=True, + max_length=128 + ) + + with torch.no_grad(): + outputs = self.model(**inputs) + + embeddings = outputs.last_hidden_state + embeddings = F.normalize(embeddings, p=2, dim=-1) + + return embeddings + + def calculate_colbert_similarity(self, query_emb, doc_embs, query_mask, doc_masks): + """ColBERT相似度计算(MaxSim操作)""" + scores = [] + + for i, doc_emb in enumerate(doc_embs): + doc_mask = doc_masks[i:i+1] + + # 计算相似度矩阵 + similarity_matrix = torch.matmul(query_emb, doc_emb.unsqueeze(0).transpose(-2, -1)) + + # 应用文档mask + doc_mask_expanded = doc_mask.unsqueeze(1) + similarity_matrix = similarity_matrix.masked_fill(~doc_mask_expanded.bool(), -1e9) + + # MaxSim操作 + max_sim_per_query_token = similarity_matrix.max(dim=-1)[0] + + # 应用查询mask + query_mask_expanded = query_mask.unsqueeze(0) + max_sim_per_query_token = max_sim_per_query_token.masked_fill(~query_mask_expanded.bool(), 0) + + # 求和得到最终分数 + colbert_score = max_sim_per_query_token.sum(dim=-1).item() + scores.append(colbert_score) + + return scores + + def compress_documents( + self, + documents: Sequence[Document], + query: str, + callbacks=None, + ) -> Sequence[Document]: + """对文档进行ColBERT重排序""" + if len(documents) == 0: + return documents + + # 编码查询 + query_inputs = self.tokenizer( + [query], + return_tensors="pt", + padding=True, + truncation=True, + max_length=128 + ) + + with torch.no_grad(): + query_outputs = self.model(**query_inputs) + query_embeddings = F.normalize(query_outputs.last_hidden_state, p=2, dim=-1) + + # 编码文档 + doc_texts = [doc.page_content for doc in documents] + doc_inputs = self.tokenizer( + doc_texts, + return_tensors="pt", + padding=True, + truncation=True, + max_length=128 + ) + + with torch.no_grad(): + doc_outputs = self.model(**doc_inputs) + doc_embeddings = F.normalize(doc_outputs.last_hidden_state, p=2, dim=-1) + + # 计算ColBERT相似度 + scores = self.calculate_colbert_similarity( + query_embeddings, + doc_embeddings, + query_inputs['attention_mask'], + doc_inputs['attention_mask'] + ) + + # 排序并返回前5个 + scored_docs = list(zip(documents, scores)) + scored_docs.sort(key=lambda x: x[1], reverse=True) + reranked_docs = [doc for doc, _ in scored_docs[:5]] + + return reranked_docs +``` + +1. **继承与实现**:`ColBERTReranker` 类继承自 `BaseDocumentCompressor`,并实现了其核心的抽象方法 `compress_documents`。这个方法接收基础检索器返回的文档列表 `documents` 和原始查询 `query` 作为输入。 + +2. **实现ColBERT逻辑**:`compress_documents` 方法的内部逻辑遵循了在 “1.4 ColBERT 重排” 中描述的“后期交互”原理。 + * **独立编码**:在 `_colbert_score` 辅助函数中,查询和文档分别被独立编码,通过 `self.model` 得到各自所有 Token 的嵌入向量(`query_embeddings` 和 `doc_embeddings`)。 + * **后期交互**:代码 `similarity_matrix.max(dim=1).values` 实现了最大相似度(MaxSim)计算。为查询中的每一个 Token 向量,都从文档的所有 Token 向量中寻找一个最相似的,并记录下这个最大相似度值。 + * **分数聚合**:最后的 `.sum()` 操作将查询中所有 Token 算出的最大相似度值相加,得到该文档与查询的最终相关性总分。 + +3. **排序与返回**:`compress_documents` 方法遍历所有文档、计算出各自的分数后,根据分数从高到低对文档进行重新排序,并返回排序后的文档列表。 + +接下来,将这个自定义的 `ColBERTReranker` 与 LangChain 的其他组件(如 `LLMChainExtractor`)组合成一个强大的“重排+压缩”管道,并应用在实际的检索任务中。 + +```python +# 初始化配置...(略) + +# 1. 加载和处理文档 +loader = TextLoader("../../data/C4/txt/ai.txt", encoding="utf-8") +documents = loader.load() +text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100) +docs = text_splitter.split_documents(documents) + +# 2. 创建向量存储和基础检索器 +vectorstore = FAISS.from_documents(docs, hf_bge_embeddings) +base_retriever = vectorstore.as_retriever(search_kwargs={"k": 20}) + +# 3. 设置ColBERT重排序器 +reranker = ColBERTReranker() + +# 4. 设置LLM压缩器 +compressor = LLMChainExtractor.from_llm(llm) + +# 5. 使用DocumentCompressorPipeline组装压缩管道 +# 流程: ColBERT重排 -> LLM压缩 +pipeline_compressor = DocumentCompressorPipeline( + transformers=[reranker, compressor] +) + +# 6. 创建最终的压缩检索器 +final_retriever = ContextualCompressionRetriever( + base_compressor=pipeline_compressor, + base_retriever=base_retriever +) + +# 7. 执行查询并展示结果 +query = "AI还有哪些缺陷需要克服?" +print(f"\n{'='*20} 开始执行查询 {'='*20}") +print(f"查询: {query}\n") + +# 7.1 基础检索结果 +print(f"--- (1) 基础检索结果 (Top 20) ---") +base_results = base_retriever.get_relevant_documents(query) +for i, doc in enumerate(base_results): + print(f" [{i+1}] {doc.page_content[:100]}...\n") + +# 7.2 使用管道压缩器的最终结果 +print(f"\n--- (2) 管道压缩后结果 (ColBERT重排 + LLM压缩) ---") +final_results = final_retriever.get_relevant_documents(query) +for i, doc in enumerate(final_results): + print(f" [{i+1}] {doc.page_content}\n") +``` + +这段代码展示了如何将各个组件串联起来,形成一个完整的检索流程: + +1. **创建基础组件**:首先创建一个标准的 `FAISS` 向量存储和一个基础检索器 `base_retriever`,负责从向量库中初步召回20个可能相关的文档。 +2. **准备处理单元**:实例化两个关键的处理单元: + * `reranker`: 自定义的 `ColBERTReranker` 实例。 + * `compressor`: LangChain 内置的 `LLMChainExtractor`,用于从文档中提取与查询相关的句子。 +3. **构建处理管道 (`DocumentCompressorPipeline`)**:这是整个流程的核心。创建一个 `DocumentCompressorPipeline` 实例,并将 `reranker` 和 `compressor` 按顺序放入 `transformers` 列表中。根据 `DocumentCompressorPipeline` 的源码,它会依次调用列表中的每个处理器。因此,文档会先经过 `ColBERTReranker` 重排,重排后的结果再被送入 `LLMChainExtractor` 进行压缩。 +4. **组装最终检索器**:最后,用 `ContextualCompressionRetriever` 将 `base_retriever` 和我们创建的 `pipeline_compressor` 包装在一起。当调用 `final_retriever` 时,它会自动执行“基础检索 -> 管道处理(重排 -> 压缩)”的完整流程。 + +> [完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C4/07_rerank_and_refine.py) + +### 2.3 LlamaIndex 中的检索压缩 + +LlamaIndex 同样提供了封装好的压缩功能,其代表是 `SentenceEmbeddingOptimizer`[^5]。它也是一个后处理器(Node Postprocessor),工作在检索之后。 + +它的工作原理是,对于每个检索到的文档,将其分解成句子。然后计算每个句子与用户查询的嵌入相似度,最后只保留那些相似度最高的句子,从而“优化”文档,去除无关信息。 + +## 三、校正 (Correcting) + +传统的 RAG 流程有一个隐含的假设:检索到的文档总是与问题相关且包含正确答案。然而在现实世界中,检索系统可能会失败,返回不相关、过时或甚至完全错误的文档。如果将这些“有毒”的上下文直接喂给 LLM,就可能导致幻觉(Hallucination)或产生错误的回答。 + +**校正检索(Corrective-RAG, C-RAG)** 正是为解决这一问题而提出的一种策略[^6]。思路是引入一个“自我反思”或“自我修正”的循环,在生成答案之前,对检索到的文档质量进行评估,并根据评估结果采取不同的行动。 + +C-RAG 的工作流程可以概括为 **“检索-评估-行动”** 三个阶段: + +![C-RAG](images/4_5_4.webp) + +1. **检索 (Retrieve)** :与标准 RAG 一样,首先根据用户查询从知识库中检索一组文档。 + +2. **评估 (Assess)** :这是 C-RAG 的关键步骤。如图所示,一个“检索评估器 (Retrieval Evaluator)”会判断每个文档与查询的相关性,并给出“正确 (Correct)”、“不正确 (Incorrect)”或“模糊 (Ambiguous)”的标签。 + +3. **行动 (Act)** :根据评估结果,系统会进入不同的知识修正与获取流程: + * **如果评估为“正确”**:系统会进入“知识精炼 (Knowledge Refinement)”环节。如图,它会将原始文档分解成更小的知识片段 (strips),过滤掉无关部分,然后重新组合成更精准、更聚焦的上下文,再送给大模型生成答案。 + * **如果评估为“不正确”**:系统认为内部知识库无法回答问题,此时会触发“知识搜索 (Knowledge Searching)”。它会先对原始查询进行“查询重写 (Query Rewriting)”,生成一个更适合搜索引擎的查询,然后进行 Web 搜索,用外部信息来回答问题。 + * **如果评估为“模糊”**:同样会触发“知识搜索”,但通常会直接使用原始查询进行 Web 搜索,以获取额外信息来辅助生成答案。 + +通过这种方式,C-RAG 极大地增强了 RAG 系统的鲁棒性。不再盲目信任检索结果,而是增加了一个“事实核查”层,能够在检索失败时主动寻求外部帮助,从而有效减少幻觉,提升答案的准确性和可靠性。 + +在 LangChain 的 `langgraph` 库中,可以利用其图结构来灵活地构建这种带有条件判断和循环的复杂 RAG 流程[^7]。 + +## 练习 + +- 本节“自定义重排器与压缩管道”部分的代码运行后的输出会出现重复的情况,思考为什么会出现这个问题并尝试修改代码解决。([参考代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C4/work_rerank_and_refine.py)) + +## 参考文献 + +[^1]: [*Using LLM’s for Retrieval and Reranking*](https://www.llamaindex.ai/blog/using-llms-for-retrieval-and-reranking-23cf2d3a14b6). + +[^2]: [Nogueira, R., & Cho, K. (2019). *Passage Re-ranking with BERT*](https://arxiv.org/abs/1901.04085). + +[^3]: [*Advanced RAG: ColBERT Reranker*](https://www.pondhouse-data.com/blog/advanced-rag-colbert-reranker). + +[^4]: [*How to do retrieval with contextual compression*](https://python.langchain.com/docs/how_to/contextual_compression/). + +[^5]: [*Sentence Embedding Optimizer*](https://docs.llamaindex.ai/en/stable/examples/node_postprocessor/OptimizerDemo/). + +[^6]: [Jiang, Z. et al. (2024). *Corrective Retrieval Augmented Generation*](https://arxiv.org/pdf/2401.15884.pdf). + +[^7]: [*Corrective-RAG (CRAG)*](https://langchain-ai.github.io/langgraph/tutorials/rag/langgraph_crag/). + + diff --git a/docs/chapter4/images/4_2_1.webp b/docs/chapter4/images/4_2_1.webp new file mode 100644 index 0000000..7cb6d0c Binary files /dev/null and b/docs/chapter4/images/4_2_1.webp differ diff --git a/docs/chapter4/images/4_3_1.webp b/docs/chapter4/images/4_3_1.webp new file mode 100644 index 0000000..3b10919 Binary files /dev/null and b/docs/chapter4/images/4_3_1.webp differ diff --git a/docs/chapter4/images/4_3_2.webp b/docs/chapter4/images/4_3_2.webp new file mode 100644 index 0000000..30b8260 Binary files /dev/null and b/docs/chapter4/images/4_3_2.webp differ diff --git a/docs/chapter4/images/4_4_1.webp b/docs/chapter4/images/4_4_1.webp new file mode 100644 index 0000000..d137775 Binary files /dev/null and b/docs/chapter4/images/4_4_1.webp differ diff --git a/docs/chapter4/images/4_4_2.webp b/docs/chapter4/images/4_4_2.webp new file mode 100644 index 0000000..92ff41a Binary files /dev/null and b/docs/chapter4/images/4_4_2.webp differ diff --git a/docs/chapter4/images/4_4_3.webp b/docs/chapter4/images/4_4_3.webp new file mode 100644 index 0000000..26e465b Binary files /dev/null and b/docs/chapter4/images/4_4_3.webp differ diff --git a/docs/chapter4/images/4_4_4.webp b/docs/chapter4/images/4_4_4.webp new file mode 100644 index 0000000..ef09d28 Binary files /dev/null and b/docs/chapter4/images/4_4_4.webp differ diff --git a/docs/chapter4/images/4_5_1.webp b/docs/chapter4/images/4_5_1.webp new file mode 100644 index 0000000..9388cb2 Binary files /dev/null and b/docs/chapter4/images/4_5_1.webp differ diff --git a/docs/chapter4/images/4_5_2.webp b/docs/chapter4/images/4_5_2.webp new file mode 100644 index 0000000..81bc050 Binary files /dev/null and b/docs/chapter4/images/4_5_2.webp differ diff --git a/docs/chapter4/images/4_5_3.svg b/docs/chapter4/images/4_5_3.svg new file mode 100644 index 0000000..014b72d --- /dev/null +++ b/docs/chapter4/images/4_5_3.svg @@ -0,0 +1,3 @@ + + +
Cross-Encoder Rerank Sequence Diagram
User
Search System
Cross-Encoder
Model
Submit Query
Initial Retrieval (e.g.,
top 50 docs)
Query + Doc 1
Relevance Score 1
Query + Doc 2
Relevance Score 2
...
Query + Doc N
Relevance Score N
Return Re-Ranked
Results
Cross-Encoder
Model
User
Search System
Process each
document
\ No newline at end of file diff --git a/docs/chapter4/images/4_5_4.webp b/docs/chapter4/images/4_5_4.webp new file mode 100644 index 0000000..93b2da6 Binary files /dev/null and b/docs/chapter4/images/4_5_4.webp differ diff --git a/docs/chapter5/16_formatted_generation.md b/docs/chapter5/16_formatted_generation.md new file mode 100644 index 0000000..1ccb5ac --- /dev/null +++ b/docs/chapter5/16_formatted_generation.md @@ -0,0 +1,173 @@ +# 第一节 格式化生成 + +从大语言模型(LLM)那里获得一段非结构化的文本在应用中常常不满足实际需求。为了实现更复杂的逻辑、与外部工具交互或以用户友好的方式展示数据,需要模型能够输出具有特定结构的数据,例如 JSON 或 XML。 + +本节将讨论实现格式化生成的几种主流方法,包括 LangChain、LlamaIndex 等框架内置的解决方案,不依赖框架的实现思路,以及一种更强大的技术——Function Calling。 + +> 在生成阶段,提示词工程也是一个重要的部分。但是因为在前面几个章节中已经有了比较多的介绍,所以本章就不再赘述了。 + +## 一、为什么需要格式化生成? + +先来看几个具体的应用场景: + +- **RAG 驱动的电商客服**:当用户询问“推荐几款适合程序员的键盘”时,我们希望 LLM 返回一个包含产品名称、价格、特性和购买链接的 JSON 列表,而不是一段描述性文字,以便前端直接渲染成商品卡片。 +- **自然语言转 API 调用**:用户说“帮我查一下明天从上海到北京的航班”,系统需要将这句话解析成一个结构化的 API 请求,如 `{"departure": "上海", "destination": "北京", "date": "2025-07-18"}`。 +- **数据自动提取**:从一篇新闻文章中,自动抽取出事件、时间、地点、涉及人物等关键信息,并以结构化形式存入数据库。 + +在这些场景中,格式化生成是连接 LLM 的自然语言理解能力和下游应用程序的程序化逻辑之间的关键。 + +## 二、格式化生成的实现方法 + +> [完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C5/01_pydantic.py) + +### 2.1 Output Parsers + +LangChain 提供了一个强大的组件——`OutputParsers`(输出解析器),专门用于处理 LLM 的输出,其主要思想是在发送给 LLM 的提示(Prompt)中自动注入一段关于如何格式化输出的指令,并在得到结果后将 LLM 返回的纯文本字符串解析成预期的结构化数据(如 Python 对象)。 + +LangChain 提供了多种开箱即用的解析器,例如: + +- **StrOutputParser**:最基础的输出解析器,它简单地将 LLM 的输出作为字符串返回。 +- **JsonOutputParser**:可以解析包含嵌套结构和列表的复杂 JSON 字符串。 +- **PydanticOutputParser**:通过与 Pydantic 模型结合,可以实现对输出格式最严格的定义和验证。 + +接下来通过一个具体的代码示例,重点分析 `PydanticOutputParser` 的工作原理。它通过将用户定义的 Pydantic 数据模型转换为详细的格式指令,并注入到提示词中,来引导 LLM 生成严格符合该数据结构的 JSON 输出。最后再将模型返回的 JSON 字符串安全地解析为 Pydantic 对象实例。 + +```python +# (此处省略了导入和 LLM 初始化代码) + +# 1. 定义期望的数据结构 +class PersonInfo(BaseModel): + """用于存储个人信息的数据结构。""" + name: str = Field(description="人物姓名") + age: int = Field(description="人物年龄") + skills: List[str] = Field(description="技能列表") + +# 2. 基于 Pydantic 模型,创建解析器 +parser = PydanticOutputParser(pydantic_object=PersonInfo) + +# 3. 创建提示模板,注入格式指令 +prompt = PromptTemplate( + template="请根据以下文本提取信息。\n{format_instructions}\n{text}\n", + input_variables=["text"], + partial_variables={"format_instructions": parser.get_format_instructions()}, +) + +# 4. 创建处理链 (假定 llm 已被初始化) +chain = prompt | llm | parser + +# 5. 执行调用 +text = "张三今年30岁,他擅长Python和Go语言。" +result = chain.invoke({"text": text}) + +# 6. 打印结果 +print(result) +# name='张三' age=30 skills=['Python', 'Go语言'] +``` + +(1)**定义数据模型**:使用 Pydantic 的 `BaseModel` 定义 `PersonInfo` 类,这不仅是一个 Python 对象,更是一个清晰的数据结构规范(Schema)。`Field` 中的 `description` 描述文本将直接作为指令提供给大模型,因此其表述需要清晰准确。 + +(2)**生成格式指令**:当 `PydanticOutputParser` 实例化后,其 `get_format_instructions()` 方法会执行以下操作: +- 调用 Pydantic 模型的 `.model_json_schema()` 方法,提取出该数据结构的 JSON Schema 定义。 +- 对该 Schema 进行简化,并将其嵌入到一个预设的、指导性的提示模板中。这个模板明确要求 LLM 输出一个符合该 Schema 的 JSON 对象。 + +(3)**构建并执行调用链**:通过 LangChain 表达式语言(LCEL),将 `prompt`、`llm` 和 `parser` 链接起来。当调用链被触发时: +- `prompt` 会将用户输入(`text`)和上一步生成的格式指令(`format_instructions`)组合成最终的提示,发送给 `llm`。 +- `llm` 根据这个包含严格格式要求的提示,生成一个 JSON 格式的字符串。 + +(4)**解析与验证**:`PydanticOutputParser` 接收到 LLM 返回的字符串后,会执行一个两步解析过程: +- 首先,它继承自 `JsonOutputParser`,会将 LLM 输出的文本字符串解析成一个 Python 字典。 +- 然后,最关键的一步,它会使用 `PersonInfo.model_validate()` 方法,用定义的数据模型来验证这个字典。如果字典的键和值类型都符合 `PersonInfo` 的定义,解析器就会返回一个 `PersonInfo` 的实例对象;如果验证失败,则会抛出一个 `OutputParserException` 异常。 + +### 2.2 LlamaIndex 的输出解析 + +LlamaIndex 的输出解析与生成过程紧密结合,主要体现在两大核心组件中,分别是响应合成(Response Synthesis)和结构化输出(Structured Output)。 + +在 RAG 流程中,检索器召回一系列相关的文本块(Nodes)后,并不是简单地将它们拼接起来。响应合成器(Response Synthesizer)负责接收这些文本块和原始查询,并以一种更智能的方式将它们呈现给 LLM 以生成最终答案。例如,它可以逐块处理信息并迭代地优化答案(`refine` 模式),或者将尽可能多的文本块压缩进单次 LLM 调用中(`compact` 模式)。这个阶段的默认目标是生成一段高质量的**文本**回答。 + +当需要 LLM 返回结构化数据(如 JSON)而非纯文本时,LlamaIndex 主要使用 **Pydantic 程序(Pydantic Programs)**。这与 LangChain 的 `PydanticOutputParser` 思想一致: + +- **定义 Schema**:开发者首先定义一个 Pydantic 模型,明确所需输出的数据结构、字段和类型。 +- **引导生成**:LlamaIndex 会将这个 Pydantic 模型转换成 LLM 能理解的格式指令。如果底层的 LLM 支持 Function Calling,LlamaIndex 会优先使用该功能以获得更可靠的结构化输出。如果不支持,它会回退到将 JSON Schema 注入到提示词中的方法。 +- **解析验证**:最后,LLM 返回的输出会被自动解析并用 Pydantic 模型进行验证,确保其类型和结构完全正确,最终返回一个 Pydantic 对象实例。 + +### 2.3 不依赖框架的简单实现思路 + +如果不想依赖特定的框架,也可以通过提示工程的技巧来实现格式化生成。 + +主要思路是在提示中给出清晰、明确的指令和示例。以下是一些实用技巧: + +- **明确要求 JSON 格式**:在提示中直接、强硬地要求模型“必须返回一个 JSON 对象”、“不要包含任何解释性文字,只返回 JSON”。 +- **提供 JSON Schema**:在提示中给出你想要的 JSON 对象的模式(Schema),描述每个键的含义和数据类型。 +- **提供 few-shot 示例**:给出 1-2 个“用户输入 -> 期望的 JSON 输出”的完整示例,让模型学习输出的格式和风格。 +- **使用语法约束**:对于一些本地部署的开源模型(如通过 `llama.cpp` 运行的模型),可以使用 GBNF (GGML BNF) 等语法文件来强制约束模型的输出,确保其生成的每一个 token 都严格符合预定义的 JSON 语法。这是最严格也是最可靠的非 Function Calling 方法。 + +## 三、Function Calling + +Function Calling(或称 Tool Calling)是近年来 LLM 领域的一个重要进展,提升了模型与外部世界交互和生成结构化数据的能力。 + +> [本节完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C5/02_function_calling_example.py) + +### 3.1 概念与工作流程 + +Function Calling 的本质是一个多轮对话流程,让模型、代码和外部工具(如 API)协同工作。其核心工作流如下: + +(1)**定义工具**:首先,在代码中以特定格式(通常是 JSON Schema)定义好可用的工具,包括工具的名称、功能描述、以及需要的参数。 + +(2)**用户提问**:用户发起一个需要调用工具才能回答的请求。 + +(3)**模型决策**:模型接收到请求后,分析用户的意图,并匹配最合适的工具。它不会直接回答,而是返回一个包含 `tool_calls` 的特殊响应。这个响应相当于一个指令:“请调用某某工具,并使用这些参数”。 + +(4)**代码执行**:应用接收到这个指令,解析出工具名称和参数,然后**在代码层面实际执行**这个工具(例如,调用一个真实的天气 API)。 + +(5)**结果反馈**:将工具的执行结果(例如,从 API 获取的真实天气数据)包装成一个 `role` 为 `tool` 的消息,再次发送给模型。 + +(6)**最终生成**:模型接收到工具的执行结果后,结合原始问题和工具返回的信息,生成最终的、自然的语言回答。 + +### 3.2 Function Calling 实践 + +接下来,直接使用 `openai` 的例子,来展示上述流程。 + + +```python +# 1. 定义工具 +tools = [...] + +# 2. 用户提问 +messages = [{"role": "user", "content": "杭州今天天气怎么样?"}] +message = send_messages(messages, tools=tools) + +# 3. 代码执行:模拟调用天气API,并将结果添加到消息历史 +if message.tool_calls: + tool_call = message.tool_calls[0] + messages.append(message) # 添加模型的回复 + tool_output = "24℃,晴朗" # 模拟API结果 + messages.append({ + "role": "tool", + "tool_call_id": tool_call.id, + "content": tool_output + }) # 添加工具执行结果 + + # 4. 第二次调用 (`Tool -> Model`):将工具结果返回给模型,获取最终回答 + final_message = send_messages(messages, tools=tools) + print(final_message.content) +``` + +关键步骤: + +(1)**定义 `tools`**:用一个列表包含了所有可用的函数定义。每个定义都是一个 JSON 对象,严格描述了函数的名称 (`name`)、功能 (`description`) 和参数 (`parameters`)。这个描述的质量直接决定了模型能否正确选择和使用工具。 + +(2)**第一次调用 (`User -> Model`)**:将用户的原始问题(`"role": "user"`)和 `tools` 列表一同发送给模型。 + +(3)**处理 `tool_calls`**:检查模型的响应中是否包含 `tool_calls`。如果包含,就说明模型决定使用工具。解析出函数名和参数,并**模拟执行**(在真实场景中,这里会是真实的 API 调用)。 + +(4)**第二次调用 (`Tool -> Model`)**:将原始的用户问题、模型的工具调用响应,以及模拟执行后得到的工具结果(`"role": "tool"`),一同打包成新的对话历史,再次发送给模型。 + +(5)**获取最终答案**:模型在看到工具的执行结果后,就能用自然语言回答用户最初的问题了。 + +### 3.3 Function Calling 的优势 + +相比于单纯通过提示工程“请求”模型输出 JSON,Function Calling 的优势在于: + +- **可靠性更高**:这是模型原生支持的能力,相比于解析可能格式不稳定的纯文本输出,这种方式得到的结构化数据更稳定、精确。 +- **意图识别**:它不仅仅是格式化输出,更包含了“意图到函数的映射”。模型能根据用户问题主动选择最合适的工具。 +- **与外部世界交互**:它是构建能执行实际任务的 AI 代理(Agent)的核心基础,让 LLM 可以查询数据库、调用 API、控制智能家居等。 \ No newline at end of file diff --git a/docs/chapter6/18_system_evaluation.md b/docs/chapter6/18_system_evaluation.md new file mode 100644 index 0000000..d48fd08 --- /dev/null +++ b/docs/chapter6/18_system_evaluation.md @@ -0,0 +1,137 @@ +# 第一节 评估介绍 + +> 构建RAG系统后,下一个关键问题是:如何科学地评估其表现? + +评估之所以关键,是因为它回答了RAG开发与应用中的一系列核心问题: + +- **对于开发者:** 如何量化地追踪、迭代并提升RAG应用的性能?当系统出现“幻觉”或答非所问时,如何快速定位问题根源? +- **对于用户或决策者:** 面对两个不同的RAG应用,如何客观地评判孰优孰劣? + + +本节将探讨RAG评估的理念与方法,并围绕 **“RAG三元组(RAG Triad)”** 展开。 + +![RAG Triad](./images/6_1_1.webp) + +## 一、RAG评估三元组 + +该架构包含以下三个维度,并在 **TruLens** [^1]等工具中有深入的应用: + +(1)**上下文相关性 (Context Relevance)** +- **评估目标:** 检索器(Retriever)的性能。 +- **核心问题:** 检索到的上下文内容,是否与用户的查询(Query)高度相关? +- **重要性:** 检索是RAG应用在响应用户查询时的第一步。如果检索回来的上下文充满了噪声或无关信息,那么无论后续的生成模型多么强大,都没法做出正确答案。 + +(2)**忠实度 / 可信度 (Faithfulness / Groundedness)** +- **评估目标:** 生成器的可靠性。 +- **核心问题:** 生成的答案是否完全基于所提供的上下文信息? +- **重要性:** 这个维度主要在于量化LLM的“幻觉”程度。一个高忠实度的回答意味着模型严格遵守了上下文,没有捏造或歪曲事实。如果忠实度得分低,说明LLM在回答时“自由发挥”过度,引入了外部知识或不实信息。 + +(3)**答案相关性 (Answer Relevance)** +- **评估目标:** 系统的端到端(End-to-End)表现。 +- **核心问题:** 最终生成的答案是否直接、完整且有效地回答了用户的原始问题? +- **重要性:** 这是用户最直观的感受。一个答案可能完全基于上下文(高忠实度),但如果它答非所问,或者只回答了问题的一部分,那么这个答案的相关性就很低。例如,当用户问“法国在哪里,首都是哪里?”,如果答案只是“法国在西欧”,那么虽然忠实度高,但答案相关性很低。 + +> 你可能觉得忠实度和答案相关性很相似,但它们的侧重点是不同的。忠实度更关注模型是否严格遵循了上下文,而答案相关性则更关注模型是否直接、完整且有效地回答了问题。 + +通过对这三个维度进行评估,可以对RAG系统的表现有一个全面而细致的了解,并能准确定位问题所在:是检索出了问题,还是生成环节有待改进。 + +## 二、评估工作流 + +虽然上面把评估分成了三个部分,但实际上可以把评估过程拆解为两个主要环节:**检索评估**和**响应评估**。 + +### 2.1 检索评估 + +检索评估聚焦于RAG三元组中的 **上下文相关性 (Context Relevance)**,本质上是一次**白盒测试** [^2]。此阶段的评估需要一个标注数据集,其中包含一系列查询以及每个查询对应的真实相关文档。 + +这项评估借鉴了信息检索领域的多个经典指标: +- **上下文精确率 (Context Precision):** 衡量检索结果的准确性。计算在检索到的前 **k** 个文档中相关文档所占的比例,其中 **k** 是一个预设的数字(例如,k=3或k=5),代表评估的范围。高精确率意味着检索结果的噪声较少。 + + $$\text{Precision}@k = \frac{\text{检索到的}k\text{个结果中的相关文档数}}{k}$$ + +- **上下文召回率 (Context Recall):** 衡量检索结果的完整性。计算在检索到的前 **k** 个文档中,找到的相关文档占所有真实相关文档总数的比例。高召回率意味着系统能够成功找回大部分关键信息。 + + $$\text{Recall}@k = \frac{\text{检索到的}k\text{个结果中的相关文档数}}{\text{数据集中所有相关的文档总数}}$$ + +- **F1分数 (F1-Score):** F1分数是精确率和召回率的调和平均数,它同时兼顾了这两个指标,在它们之间寻求平衡。当精确率和召回率都高时,F1分数也高。 + + $$F_1 = 2 \cdot \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}$$ + +- **平均倒数排名 (MRR - Mean Reciprocal Rank):** 评估系统将第一个相关文档排在靠前位置的能力。对于一个查询,倒数排名是第一个相关文档排名的倒数。MRR是所有查询的倒数排名的平均值。该指标适用于用户通常只关心第一个正确答案的场景。 + + $$\text{MRR} = \frac{1}{|Q|} \sum_{q=1}^{|Q|} \frac{1}{\text{rank}_q}$$ + + 其中 `|Q|` 是查询总数,`rank_q` 是第 `q` 个查询的第一个相关文档的排名。 + +- **平均准确率均值 (MAP - Mean Average Precision):** MAP是一个综合性指标,同时评估了检索结果的精确率和相关文档的排名。它先计算每个查询的平均精确率(AP),然后对所有查询的AP取平均值。AP本身是基于每个相关文档被检索到时的精确率计算的。 + + $$\text{MAP} = \frac{1}{|Q|} \sum_{q=1}^{|Q|} \text{AP}(q)$$ + + 其中 `|Q|` 是查询总数,`AP(q)` 是第 `q` 个查询的平均精确率(Average Precision)。 + +要计算上述所有指标,前提是拥有一个高质量的标注数据集,其中包含了查询和每个查询对应的“真实”相关文档。 + +### 2.2 响应评估 + +响应评估覆盖了RAG三元组中的 **忠实度** 和 **答案相关性**。此环节通常采用 **端到端** 的评估范式,因为它直接衡量用户感知的最终输出质量。无论采用何种评估方法,都主要围绕以下两个核心维度展开。 + +#### 2.2.1 评估维度 + +(1)**忠实度 / 可信度**:衡量生成的答案在多大程度上可以由给定的上下文所证实。一个完全忠实的答案,其所有内容都必须能在上下文中找到依据,以此避免模型产生“幻觉”。 + +(2)**答案相关性**:衡量生成的答案与用户原始查询的对齐程度。一个高相关性的答案必须是直接的、切题的,并且不包含与问题无关的冗余信息。 + +#### 2.2.2 主要评估方法 + +针对上述维度,目前主要有两类评估方法: + +(1)**基于大语言模型的评估** + +这是一种强大的评估方法,能够提供更深度的语义评估,正逐渐成为主流选择。利用一个高性能、中立的llm作为“评估者”,对上述维度进行深度的语义理解和打分。 + +- **忠实度评估:** 首先,将生成的答案分解为一系列独立的声明或断言(Claims)。然后,对于每一个断言,在提供的上下文中进行验证,判断其真伪。最终的忠实度分数是所有被上下文证实的断言所占的比例。 +- **答案相关性评估:** 评估者需要同时分析用户查询和生成的答案。评分时会惩罚那些答非所问、信息不完整或包含过多无关细节的答案。 + +(2)**基于词汇重叠的经典指标** + +这类指标需要在数据集中包含一个或多个“标准答案”。它们通过计算生成答案与标准答案之间 n-gram(连续的n个词)的重叠程度来评估质量。 + +- **ROUGE (Recall-Oriented Understudy for Gisting Evaluation):** ROUGE关注的重点是 **召回率**,即标准答案中的词语有多少被生成答案所覆盖,因此常用于评估内容的 **完整性**。其常用变体包括计算n-gram的 `ROUGE-N` 和计算最长公共子序列的 `ROUGE-L`。 + + $$\text{ROUGE-N} = \frac{\text{匹配的 } n\text{-gram 数量}}{\text{参考答案中 } n\text{-gram 的总数}}$$ + +- **BLEU (Bilingual Evalu ation Understudy):** BLEU侧重于评估 **精确率**,衡量生成的答案中有多少词是有效的(即在标准答案中出现过)。它还引入了长度惩罚机制,避免模型生成过短的句子,因此更适合评估答案的 **流畅度和准确性**。 + + $$\text{BLEU} = \text{BP} \times \exp\left(\sum_{n=1}^{N} w_n \log p_n\right)$$ + + 其中,`BP` 是长度惩罚因子,`p_n` 是修正后的n-gram精确率。 + +- **METEOR (Metric for Evaluation of Translation with Explicit ORdering):** 作为BLEU的改进版,METEOR同时考量 **精确率和召回率** 的调和平均,并通过词干和同义词匹配(如将'boat'和'ship'视为相关)来更好地捕捉语义相似性。其评估结果通常被认为与人类判断的相关性更高。 + + $$F_{\text{mean}} = \frac{P \times R}{\alpha P + (1-\alpha)R}$$ + + $$\text{METEOR} = F_{\text{mean}} \times (1 - \text{Penalty})$$ + + 其中 `P` 是精确率,`R` 是召回率,`Penalty` 是基于语序的惩罚项。 + +> 为了更直观地理解三者的区别,来看一个简单的例子。 +> +> **假设:** +> - **参考答案:** `狗 在 床 上面` (共5个词) +> - **生成答案:** `狗 在 床 上` (共4个词) +> +> **评估分析:** +> - **ROUGE (召回率导向):** 从召回率的角度出发:“参考答案里的5个词,生成答案覆盖了多少?”——覆盖了4个。因此,它的召回率很高(ROUGE-1 为 4/5),得分会不错。ROUGE更关心“说全了没”。 +> +> - **BLEU (精确率导向):** 从精确率的角度进行评判:“生成答案里的4个词,有多少是有效的(在参考答案里)?”——全部有效,精确率很高。但它会发现生成答案比参考答案短,于是通过 **长度惩罚(Brevity Penalty)** 进行扣分。BLEU更关心“说对了没,以及长度是否合适”。 +> +> - **METEOR (综合平衡):** 同时计算精确率和召回率,并取一个调和平均。在这个例子里,词序是完全正确的,惩罚项为0。METEOR会在“说全”和“说对”之间找到一个最佳平衡点。 + +#### 2.2.3 方法对比和总结 + +基于LLM的评估更注重**语义和逻辑**,评估质量高,但成本也更高且存在评估者偏见。基于词汇重叠的指标**客观、计算快、成本低**,但无法理解语义,可能误判同义词或释义。在实践中,可以将两者结合,使用经典指标进行快速、大规模的初步筛选,再利用LLM进行更精细的评估。 + +## 参考文献 + +[^1]: [*The RAG Triad of Metrics*](https://www.trulens.org/getting_started/core_concepts/rag_triad/). + +[^2]:[*如何评估 RAG 应用?*](https://zilliz.com.cn/blog/how-to-evaluate-rag-zilliz) diff --git a/docs/chapter6/19_common_tools.md b/docs/chapter6/19_common_tools.md new file mode 100644 index 0000000..c4c153a --- /dev/null +++ b/docs/chapter6/19_common_tools.md @@ -0,0 +1,154 @@ +# 第二节 评估常用工具 + +了解了评估的基本原理之后,来介绍几个RAG评估工具,它们各自代表了不同的设计哲学和应用场景。 + +## 一、LlamaIndex Evaluation + +`LlamaIndex Evaluation` 是**深度集成于LlamaIndex框架内的评估模块**,专为使用该框架构建的RAG应用提供无缝的评估能力。作为RAG开发框架的原生组件,其核心定位是**为开发者在开发、调试和迭代周期中提供快速、灵活的嵌入式评估解决方案**。它强调与开发流程的紧密结合,允许开发者在构建过程中即时验证和对比不同RAG策略的性能[^1]。 + +> **适用场景**:对于深度使用 `LlamaIndex` 框架构建RAG应用的开发者而言,其内置评估模块是无缝集成的首选,提供了一站式的开发与评估体验。 + +### 1.1 核心理念与工作流 + +`LlamaIndex` 的评估理念是利用LLM作为“裁判”,以自动化的方式对RAG系统的各个环节进行打分。这种方法在很多场景下无需预先准备“标准答案”,大大降低了评估门槛。其典型工作流如下: + +1. **准备评估数据集**:通过 `DatasetGenerator` 从文档中自动生成问题-答案对(`QueryResponseDataset`),或加载一个已有的数据集。为了效率,通常会将生成的数据集保存到本地,避免重复生成。 +2. **构建查询引擎**:搭建一个或多个需要被评估的RAG查询引擎(`QueryEngine`)。这是进行对比实验的基础。 +3. **初始化评估器**:根据评估维度,选择并初始化一个或多个评估器,如 `FaithfulnessEvaluator`(忠实度)和 `RelevancyEvaluator`(相关性)。 +4. **执行批量评估**:使用 `BatchEvalRunner` 来管理整个评估过程。它能够高效地(可并行)将查询引擎应用于数据集中的所有问题,并调用所有评估器进行打分。 +5. **分析结果**:从评估运行器返回的结果中,计算各项指标的平均分,从而量化地对比不同RAG策略的优劣。 + +### 1.2 应用实例:对比不同检索策略 + +下面示例基于我们在第三章学习的“句子窗口检索”技术,通过评估,对比它与“常规分块检索”在响应质量上的差异。 + +**代码示例:** + + +```python +# ... (省略数据加载、文档解析、查询引擎构建等步骤) + +# 1. 初始化评估器 +# 定义需要评估的指标:忠实度和相关性 +faithfulness_evaluator = FaithfulnessEvaluator(llm=Settings.llm) +relevancy_evaluator = RelevancyEvaluator(llm=Settings.llm) +evaluators = {"faithfulness": faithfulness_evaluator, "relevancy": relevancy_evaluator} + +# 2. 使用BatchEvalRunner执行批量评估 +# 从数据集中获取查询列表 +queries = response_eval_dataset.queries + +# 评估“句子窗口检索”引擎 +print("\n=== 评估句子窗口检索 ===") +sentence_runner = BatchEvalRunner(evaluators, workers=2, show_progress=True) +sentence_response_results = await sentence_runner.aevaluate_queries( + queries=queries, query_engine=sentence_query_engine +) + +# 评估“常规分块检索”引擎 +print("\n=== 评估常规分块检索 ===") +base_runner = BatchEvalRunner(evaluators, workers=2, show_progress=True) +base_response_results = await base_runner.aevaluate_queries( + queries=queries, query_engine=base_query_engine +) + +# 3. 分析并打印结果 +# ... (省略结果计算与打印的辅助函数) +print(f"句子窗口检索: 忠实度={sentence_faith:.1%}, 相关性={sentence_rel:.1%}") +print(f"常规分块检索: 忠实度={base_faith:.1%}, 相关性={base_rel:.1%}") +``` + +**输出如下:** + +```bash +============================================================ +响应评估结果对比 +============================================================ + +句子窗口检索: + 忠实度: 53.3% + 相关性: 66.7% + +常规分块检索: + 忠实度: 0.0% + 相关性: 6.7% +``` + +通过这个结果可以看出,在本次实验中“句子窗口检索”的忠实度和相关性上均显著优于“常规分块检索”。 + +### 1.3 核心评估维度 + +LlamaIndex提供了丰富的评估器,覆盖了从检索到响应的各个环节。上述示例中主要使用了**响应评估**维度: + +- `Faithfulness` (忠实度): 评估生成的答案是否完全基于检索到的上下文,是检测“幻觉”现象的关键指标。分数越高,说明答案越可靠。 +- `Relevancy` (相关性): 评估生成的答案与用户提出的原始问题是否直接相关,确保答案切题。 + +此外,它还支持专门的**检索评估**维度,如: + +- `Hit Rate` (命中率): 评估检索到的上下文中是否包含了正确的答案。 +- `MRR` (平均倒数排名): 衡量找到正确答案的效率,排名越靠前得分越高。 + +## 二、RAGAS + +RAGAS(RAG Assessment)是一个**独立的、专注于RAG的开源评估框架**。提供了一套全面的指标来量化RAG管道的检索和生成两大核心环节的性能。其最显著的特色是支持**无参考评估**,即在许多场景下无需人工标注的“标准答案”即可进行评估,极大地降低了评估成本。现对RAG管道的持续监控和改进。如果你需要一个轻量级、与具体RAG实现解耦、能够快速对核心指标进行量化评估的工具时,`RAGAS` 是一个理想的选择。 + +### 2.1 设计理念 + +`RAGAS` 的核心思想是通过分析问题(`question`)、生成的答案(`answer`)和检索到的上下文(`context`)三者之间的关系,来综合评估RAG系统的性能。它将复杂的评估问题分解为几个简单、可量化的维度。 + +### 2.2 工作流程与核心指标 + +RAGAS的评估流程非常简洁,通常遵循以下步骤: + +(1)**准备数据集**:根据官方文档,一个标准的评估数据集应包含 `question`(问题)、`answer`(RAG系统生成的答案)、`contexts`(检索到的上下文)以及 `ground_truth`(标准参考答案)这四列。不过,`ground_truth` 对于计算 `context_recall` 等指标是必需的,但对于 `faithfulness` 等指标则是可选的。 + +(2)**运行评估**:调用 `ragas.evaluate()` 函数,传入准备好的数据集和需要评估的指标列表。 + +(3)**分析结果**:获取一个包含各项指标量化分数的评估报告。 + +其核心评估指标包括: + +- `faithfulness`: 衡量生成的答案中有多少比例的信息是可以由检索到的上下文所支持的。 +- `context_recall`: 衡量检索到的上下文与标准答案(`ground_truth`)的对齐程度,即标准答案中的信息是否被上下文完全“召回”。 +- `context_precision`: 衡量检索到的上下文中,信噪比如何,即有多少是真正与回答问题相关的。 +- `answer_relevancy`: 评估答案与问题的相关程度。此指标不评估事实准确性,只关注答案是否切题。 + +## 三、Phoenix (Arize Phoenix) + +Phoenix (现由Arize维护) 是一个**开源的LLM可观测性与评估平台**。在RAG评估生态中,它主要扮演**生产环境中的可视化分析与故障诊断引擎**的角色。它通过捕获LLM应用的轨迹(Traces),提供强大的可视化、切片和聚类分析能力,帮助开发者理解线上真实数据的表现。Phoenix 的核心价值在于**从海量生产数据中发现问题、监控性能漂移并进行深度诊断**,是连接线下评估与线上运维的关键桥梁。它不仅提供评估指标,更强调对LLM应用进行追踪(Tracing)和可视化分析,从而快速定位问题[^3]。 + +![phoenix](./images/6_2_1.webp) + +### 3.1 核心理念 + +`Phoenix` 的核心是“AI可观测性”,它通过追踪RAG系统内部的每一步调用(如检索、生成等),将整个流程可视化。这使得开发者可以直观地看到每个环节的输入、输出和耗时,并在此基础上进行深入的评估和调试。 + +### 3.2 工作原理 + +`Phoenix` 的工作流程是先通过基于开放标准 **OpenTelemetry** 的**代码插桩(`Instrumentation`)**,在 RAG 应用中集成追踪功能,自动捕获 LLM 调用、函数执行等事件;随后在应用运行过程中持续生成**追踪数据(`Traces`)**,记录完整的执行链路;接着在本地启动 `Phoenix` 的 Web 界面,加载并可视化这些追踪数据;最后在 UI 中对失败案例或表现不佳的查询进行筛选、钻取,并借助内置的**评估器(`Evals`)**完成深入的评估与调试。 + +特色功能: + +- **可视化追踪**: 将RAG的执行流程、数据和评估结果进行可视化展示,极大地方便了问题定位。 +- **根本原因分析**: 通过可视化的界面,可以轻松地对表现不佳的查询进行切片和钻取。 +- **安全护栏 (`Guardrails`)**: 允许为应用添加保护层,防止恶意或错误的输入输出,保障生产环境安全。 +- **数据探索与标注**: 提供数据探索、清洗和标注工具,帮助开发者利用生产数据反哺模型和系统优化。 +- **与Arize平台集成**: `Phoenix` 可以与Arize的商业平台无缝对接,实现生产环境中对RAG系统的持续监控。 + +## 四、对比建议 + +| **工具** | **核心机制** | **独特技术** | **典型应用场景** | +| ---------- | -------- | ----------------------- | --- | +| RAGAS | LLM驱动评估 | 合成数据生成、无参考评估架构 | 对比不同RAG策略、版本迭代后的性能回归测试 | +| LlamaIndex | 嵌入式评估 | 异步评估引擎、模块化BaseEvaluator | 开发过程中快速验证单个组件或完整管道的效果 | +| Phoenix | 追踪分析型 | 分布式追踪、向量聚类分析算法 | 生产环境监控、Bad Case分析、数据漂移检测 | + +> 在实践中,这些工具并非互斥,可以结合使用,以获得对RAG系统更全面、多维度的洞察。 + +## 参考文献 + +[^1]: [*LlamaIndex Evaluating*](https://docs.llamaindex.ai/en/stable/module_guides/evaluating/) + +[^2]: [*Ragas Docs*](https://docs.ragas.io/en/stable/) + +[^3]: [*Arize AI Phoenix*](https://arize.com/docs/phoenix) diff --git a/docs/chapter6/images/6_1_1.webp b/docs/chapter6/images/6_1_1.webp new file mode 100644 index 0000000..db7863c Binary files /dev/null and b/docs/chapter6/images/6_1_1.webp differ diff --git a/docs/chapter6/images/6_2_1.webp b/docs/chapter6/images/6_2_1.webp new file mode 100644 index 0000000..a5e8d7a Binary files /dev/null and b/docs/chapter6/images/6_2_1.webp differ diff --git a/docs/chapter7/20_kg_rag.md b/docs/chapter7/20_kg_rag.md new file mode 100644 index 0000000..980306d --- /dev/null +++ b/docs/chapter7/20_kg_rag.md @@ -0,0 +1,211 @@ +# 第一节 基于知识图谱的RAG + +传统RAG框架虽然有效缓解了大型语言模型的知识陈旧和幻觉问题,但在处理复杂查询时仍存在明显局限。依赖非结构化文本向量检索的方式,往往难以捕捉实体间的深层关系,导致上下文检索不精确、信息碎片化,甚至诱发模型产生"幻觉"。为了突破这些瓶颈,将结构化知识图谱融入 RAG 流程的新范式——GraphRAG 诞生。通过利用知识图谱的显式语义关系和图结构优势,GraphRAG能够提供更精准的上下文检索和更强的推理能力,在多跳查询和事实性要求较高的场景中表现尤为出色。 + +## 一、从传统RAG到知识图谱增强RAG的演进 + +
+ GraphRAG +
+ +### 1.1 传统RAG框架的固有局限性 + +尽管传统 RAG 通过"检索-生成"两阶段流程在一定程度上解决了LLM的知识更新问题,但其基于非结构化文本向量检索的核心机制仍存在几个关键局限。 + +**关系理解的缺失**:基于向量的检索主要关注语义相似性,难以捕捉和利用实体之间复杂的、隐含的关系。当查询涉及多实体关联或因果推理时,检索到的文本块之间可能缺乏逻辑联系,导致LLM难以进行有效的综合与推理。 + +**上下文的碎片化**:文本被切分成独立的块进行索引,这破坏了原文的结构和上下文连续性。对于需要跨越多个文档或长距离文本进行信息整合的问题,传统RAG往往力不从心。 + +**检索噪声与幻觉风险**:检索过程可能返回不相关或仅部分相关的噪声信息,这会干扰LLM的判断,甚至诱发其产生与事实不符的"幻觉"内容。知识图谱的引入被证实能有效减轻模型幻觉,提供更高质量的上下文。 + +**推理能力有限**:传统 RAG 的推理能力受限于检索到的线性文本内容,难以支持需要结构化知识进行导航的多跳推理。 + +**跨文档联结能力弱**:即便采用较大的切块与滑窗重叠,跨文档/跨章节的实体共现与隐式引用仍难以被显式建模,导致需要“连边”才能回答的问题(如沿因果、时间或供应链关系追踪)召回不足。 + +**实体歧义与别名问题**:仅依赖向量相似度很难稳定地区分同名实体(如不同城市/公司/人名),或统一别名、缩写与多语言变体,易造成错误对齐与语义漂移。 + +**时效性与版本一致性不足**:文本块往往缺少可计算的时间属性与有效期边界,导致时序敏感问题(如“某公司在某年是否仍为子公司”)难以得到一致答案。 + +一个典型示例: + +- 问题:“2019年收购A公司的企业,其母公司在2021年的主要投资对象是谁?” +- 传统做法需要检索多段文本并在生成阶段自行拼接与推理;若任一段缺失或存在歧义,整体推理链即会断裂。 + +### 1.2 知识图谱赋能 RAG 的核心优势 + +知识图谱通过节点(实体)和边(关系)的网络结构,将离散的知识显式地组织成一个相互连接的语义网络,为克服传统RAG的局限性提供了强有力的解决方案。 + +**结构化语义表达**:知识图谱以图的形式直接编码实体间的显式语义关系(如"公司A-收购-公司B"),避免了LLM从文本中进行隐式、可能存在偏差的推断,为复杂查询提供了清晰的导航路径。 + +**增强推理能力**:图的结构天然支持多跳推理,系统可以沿着图中的路径遍历,发现间接但关键的知识关联,从而回答需要多步逻辑推导的复杂问题。 + +**事实性与可解释性**:基于知识图谱检索的答案可以追溯其在图中的推理路径,这为答案提供了事实依据,极大地增强了系统的可解释性和可信度,有效抑制了幻觉。 + +**异构数据集成**:知识图谱能够无缝集成来自不同来源的结构化(如数据库)和非结构化(如文本)数据,形成一个全面、统一的知识视图,这在金融、医疗等需要整合海量异构信息的领域尤为重要。 + +进一步地: + +- **语义模式与本体支撑**:通过模式(Schema)与本体(Ontology)明确实体类型、关系约束与属性域值,约束推理空间,降低歧义。 +- **溯源与置信度管理**:边与节点可携带来源、时间戳与置信度,便于在生成时进行来源归因与冲突消解。 +- **时间与版本建模**:支持时间态边与版本化节点,允许对“历史状态”与“有效区间”进行查询(Time-travel Query)。 + +### 1.3 GraphRAG:一种范式革新 + +GraphRAG将检索的目标从独立的文本片段转变为在知识图谱中寻找相关的实体、关系、路径或子图。这一转变从根本上提升了RAG系统的能力。已有研究与实践报告显示,GraphRAG 在上下文召回、多跳问答准确率、事实一致性与可解释性等关键指标上较传统RAG具有显著优势。这标志着RAG技术从“信息检索”向“知识利用”的范式演进。 + +## 二、GraphRAG框架的核心架构与工作流程 + +大多数GraphRAG框架遵循一个通用的三阶段流程:知识图谱构建、图谱检索与增强生成。 + +### 2.1 通用架构三阶段 + +**知识图谱构建** 是 GraphRAG 的基础。该阶段的目标是从原始数据中构建一个高质量的知识图谱: + +- 知识抽取:利用 LLM 或 IE 管线从非/半结构化文本中抽取实体、关系与属性,包含指代消解、别名归一(Normalization)与术语标准化。 +- 质量控制:对三元组进行置信度评估、人机协同抽检与冲突消解;必要时通过规则与本体约束做一致性校验。 +- 图谱融合:进行实体对齐与去重(Entity Resolution),合并跨来源知识并保留来源/时间戳等溯源信息。 +- 存储与索引:落地到图数据库(如Neo4j/NebulaGraph/TigerGraph/Neptune等)并建立必要的属性与关系索引,便于后续高效检索与遍历。 + +**图谱检索** 阶段,当用户提出查询时,系统不再是简单地进行向量相似度搜索,而是执行更复杂的图谱检索操作。混合检索策略是主流趋势: + +- 实体定位:先用实体链接(Entity Linking)或向量检索在图中锁定核心实体节点。 +- 子图探索:从命中节点出发,利用图查询语言(如Cypher)或遍历算法进行邻域扩展、路径发现与约束过滤(例如限定关系类型、跳数、时间区间与置信度阈值)。 +- 结构化证据抽取:将路径与关键节点属性序列化为可读证据片段,或生成子图的文本摘要。 +- 高级检索:如GraphRAG采用社区检测(如Leiden)生成多层次摘要,实现“全局-局部”联合检索。 + +示例(Cypher):查询公司A两跳内的收购路径及目标行业。 + +```cypher +MATCH (a:Company {name: "A"})-[:ACQUIRED]->(b:Company)-[:IN_INDUSTRY]->(i:Industry) +RETURN a.name AS acquirer, b.name AS target, i.name AS industry +UNION +MATCH (a:Company {name: "A"})-[:ACQUIRED]->(:Company)-[:ACQUIRED]->(b2:Company)-[:IN_INDUSTRY]->(i2:Industry) +RETURN a.name AS acquirer, b2.name AS target, i2.name AS industry; +``` + +**增强生成** 是最后一步,将检索到的结构化知识(如相关实体的属性、实体间的关系路径、描述子图的文本摘要等)与原始查询一同注入到 LLM 提示(Prompt)中。实践要点: + +- 提示设计:明确要求模型引用“图证据”,并在回答中给出来源与路径(可作为可选的引用附录)。 +- 证据融合:将“结构化三元组/路径”与“原文片段”联合提供,兼顾事实性与文本细节。 +- 约束回答:对敏感领域(财务/医疗)可采用模板化输出与字段校验,减少幻觉。 + +### 2.2 方法论分类 + +根据综述性研究,现有的 GraphRAG 方法大致可以归为三类,反映了知识图谱与 RAG 结合深度的不同。 + +**知识驱动型:** 检索过程主要或完全依赖于知识图谱。这类方法直接在图上进行查询与推理(如文本转 Cypher/Gremlin),适用于需要强逻辑约束与可解释性的任务。 + +**索引驱动型:** 将知识图谱的结构信息融入到文本索引。例如用邻居实体/关系充当元数据特征、或将子图摘要拼接到文本后再向量化,以提升召回与重排效果。 + +**混合型:** 同时使用图检索与文本检索,并对结果统一重排与融合: + +- 简单事实问答可优先图检索;叙事性/描述性问题可补充文本证据。 +- 对复杂查询,可先图上定位路径,再以路径节点为“导航枢纽”做针对性文档检索。 + +优劣对比(概览): + +- 知识驱动:高精度/高可解释,但覆盖与容错受限于图谱完备性。 +- 索引驱动:集成成本低,但显式推理弱、可解释性一般。 +- 混合型:综合表现更稳健,但系统复杂度与工程成本较高。 + +## 三、前沿GraphRAG框架介绍(截至2025年) + +近年来,学术界和工业界涌现出一批具有代表性的GraphRAG框架,它们在架构设计和应用场景上各有侧重。 + +### 3.1 GraphRAG (Microsoft) + +GraphRAG是一个重量级的框架,其核心思想是“先构建全局知识,再按需检索”[^1][^2]。典型流程: + +- 文本→三元组/子图构建→图谱(属性图); +- 采用社区检测(如Leiden)进行图划分,按层级生成全局/社区/局部摘要; +- 查询时先匹配全局/社区摘要,再下钻到局部子图与原文证据; +- 根据需要返回“全局观”与“证据路径”并行的双视角答案。 + +该方法的优势是提供强全局感知与良好可解释性,适合探索性分析、全景总结与多跳问答;但前期构建与分层摘要成本较高,对数据持续变更的场景需设计批处理/增量更新与缓存策略。 + +### 3.2 LightRAG + +针对 GraphRAG 的“重量”问题,LightRAG 旨在实现轻量、高效、易扩展[^3][^4]: + +- 核心思路常见为“双层检索”与“图增强索引”,以较低构建成本获得全局-局部兼顾的检索能力; +- 更强调将结构信号嵌入到文本索引与重排中,弱化复杂的社区发现流程; +- 适用于资源受限、快速迭代与在线更新场景。 + +### 3.3 FRAG (Flexible RAG) + +FRAG强调“灵活性”与“模块化”,以自适应不同复杂度的查询[^5]: + +- 查询分流:通过分类器或规则将请求判定为简单/复杂; +- 简单查询:直接实体链接+属性查找,低延迟返回; +- 复杂查询:激活路径检索/多跳推理模块,再融合文本证据; +- 易扩展:模块化设计与预训练LLM能力复用,迁移成本低。 + +### 3.4 GraphIRAG (Iterative Knowledge Retrieval) + +GraphIRAG 引入“迭代检索”思想,认为单次检索不足以解决复杂问题[^6]: + +- 由控制器在生成中多轮触发图查询,逐步补齐证据链; +- 以“新信息增益”为准则决定是否继续迭代与何时停止; +- 对时间敏感与多跳推理任务更具鲁棒性。 + +## 四、性能评估与基准测试 + +### 4.1 核心评估指标 + +GraphRAG 的评估体系是多维度的,主要涵盖三个方面。 + +**检索质量**: + +- 传统:精确率(Precision)、召回率(Recall)、F1、命中率(Hit Rate@K)。 +- RAG特有: + - 上下文精确率(Context Precision)= 检索到的上下文中“真正相关”的比例; + - 上下文召回率(Context Recall)= 所有应当支持答案的“金标准证据”被检回的比例; + - 引用/归因准确率(Citation/Attribution)= 生成答案中的关键断言是否被检索证据正确支撑。 + +**生成质量**: + +- 问答:精确匹配(EM)、F1; +- 摘要:ROUGE; +- 事实一致性/忠实度(Faithfulness):断言与证据的一致性,可配合“逐句打标+归因检查”。 + +**系统性能**: + +推理延迟(Latency)是从接收查询到返回最终答案所需的总时间,是衡量系统响应速度的核心指标。吞吐量(Throughput)指系统在单位时间内能处理的查询数量(QPS)。成本(Cost)包括API调用次数、计算资源(GPU/CPU)和内存消耗等。 + +### 4.2 常用基准数据集 + +学术界已经建立了一系列基准数据集来评测GraphRAG在不同任务上的能力。 + +**多跳问答** 数据集要求模型在多个知识源之间进行推理,是检验GraphRAG核心能力的试金石。代表性数据集包括 HotpotQA、2WikiMultihopQA 和 MuSiQue。 + +**复杂问答** 数据集包含结构复杂的查询,代表性数据集包括 WebQSP 和 ComplexWebQuestions (CWQ)。 + +**知识图谱驱动的QA** 是专门为评估知识图谱问答能力设计的数据集,如 KGQAgen-10k。 + +不过,一些研究指出,部分现有基准(如WebQSP)存在数据质量问题或评估方法过于僵化(如严格的EM),可能导致对模型性能的低估。因此,构建更高质量、更科学的基准是未来的一个重要方向。 + +## 五、生产环境部署实践与挑战 + +将GraphRAG框架从实验室推向生产环境,面临着一系列独特的工程和技术挑战。 + +- **知识图谱的构建与动态维护**:高质量知识图谱的构建本身就是一项耗时耗力的知识工程。在生产环境中,知识需要持续保持最新状态,如何设计高效、准确、低成本的动态更新机制是核心难点。 + +- **系统性能与可扩展性**:随着知识库规模和用户查询量的增长,系统的响应延迟、吞吐量和资源消耗成为主要瓶颈。生产部署需要应对向量化速度慢、内存溢出、API 失败等具体问题。 + +- **安全与隐私保护**:RAG 系统引入外部数据源,带来了新的安全风险,包括数据隐私泄露、模型被注入恶意数据(模型中毒)、以及针对检索模块的攻击等。 + +- **成本控制**:大规模部署 GraphRAG 系统需要大量的计算和存储资源,如何优化系统架构以降低运营成本是一个重要的商业考量。 + +## 参考文献 + +[^1]: [Edge et al. (2024). *From Local to Global: A Graph RAG Approach to Query-Focused Summarization*](https://arxiv.org/abs/2404.16130) + +[^2]: [Microsoft GraphRAG Documentation](https://microsoft.github.io/graphrag/) + +[^3]: [Guo et al. (2024). *LightRAG: Simple and Fast Retrieval-Augmented Generation*](https://arxiv.org/abs/2410.05779) + +[^4]: [HKUDS LightRAG Repository](https://github.com/HKUDS/LightRAG) + +[^5]: [Zhang et al. (2025). *FRAG: A Flexible Modular Framework for Retrieval-Augmented Generation based on Knowledge Graphs*](https://arxiv.org/abs/2501.09957) + +[^6]: [Chen et al. (2025). *GraphIRAG: A Knowledge Graph-Based Iterative Retrieval-Augmented Generation Framework for Temporal Reasoning*](https://arxiv.org/abs/2503.14234) diff --git a/docs/chapter7/images/7_1_1.svg b/docs/chapter7/images/7_1_1.svg new file mode 100644 index 0000000..22586bf --- /dev/null +++ b/docs/chapter7/images/7_1_1.svg @@ -0,0 +1,3 @@ + + +
GraphRAG
检索阶段
生成阶段
用户查询
检索模块
相关文档/片段
生成模块
Embedding
model



Encoding
外部知识库
Encoding
Vector
Database
Prompt
LLM响应
Index
Similarity
Search
Graph
Generator



Graph
Database
Request
Extraction
Graph Traversal
author: dalvqw
\ No newline at end of file diff --git a/docs/chapter8/01_env_architecture.md b/docs/chapter8/01_env_architecture.md new file mode 100644 index 0000000..97a5d62 --- /dev/null +++ b/docs/chapter8/01_env_architecture.md @@ -0,0 +1,246 @@ +# 第一节 环境配置与项目架构 + +> 经过前面十几天的鏖战也是终于来到了项目实战环节。接下来,通过一个完整的实战项目来把前面学到的知识串联起来,构建一个真正可用的RAG系统。 + +## 一、项目背景 + +这个项目的灵感来自于笔者前段时间刷视频时,偶然看到了一个有趣的开源项目介绍——[程序员做饭指南](https://github.com/Anduin2017/HowToCook)。这是一个菜谱项目,用Markdown格式记录了各种菜品的制作方法,从简单的家常菜到复杂的宴客菜,应有尽有。更完美的是,这个项目中每道菜的Markdown文件都严格使用统一的小标题。 + +看到这个项目,笔者立刻想到:能不能构建一个智能问答系统来解决我的选择困难症?每天面对"今天吃什么"这个世纪难题,如果有个AI助手能根据我的需求推荐菜品、告诉我怎么做,那该多好!于是就有了搭建这个**尝尝咸淡RAG系统**的想法。 + +## 二、环境配置 + +### 2.1 创建虚拟环境 + +```bash +# 使用conda创建环境 +conda create -n cook-rag-1 python=3.12.7 +conda activate cook-rag-1 +``` + +### 2.2 安装核心依赖 + +老规矩,进入本章对应项目目录安装依赖包 + +```bash +cd code/C8 +pip install -r requirements.txt +``` + +如果 API Key 已经配置好了,可以直接使用下面命令运行项目 + +```bash +python main.py +``` + +### 2.3 申请Kimi API Key + +Kimi2 发布第八天来尝尝咸淡,申请地址:[Kimi API官网](https://platform.moonshot.cn/console/api-keys)。目前注册会送15元的额度,绰绰有余了。 + +### 2.4 API配置 + +参考前面章节 [**环境准备**](../chapter1/02_preparation.md) 中关于api_key的配置方法。在windows下,配置完成后应该如下图所示: + +![API配置](./images/8_1_1.webp) + +## 三、项目架构 + +### 3.1 项目目标 + +我们将基于HowToCook项目的菜谱数据,构建一个智能的食谱问答系统。用户可以: + +- 询问具体菜品的制作方法:"宫保鸡丁怎么做?" +- 寻求菜品推荐:"推荐几个简单的素菜" +- 获取食材信息:"红烧肉需要什么食材?" + +### 3.2 数据分析 + +#### 3.2.1 文档分析 + +HowToCook项目包含了大约300多个Markdown格式的菜谱文件。这些菜谱有两个关键特点:一是结构高度规整,每个文件都严格按照统一的格式来组织内容;二是内容篇幅较短,单个菜谱通常在700字左右。 + +打开任意一个菜谱文件,可以发现它们都遵循着相似的结构模式。通常以菜品做法作为一级标题,开头会有一段简介和难度评级,然后分为"必备原料和工具"、"计算"、"操作"、"附加内容"等几个主要部分。比如西红柿炒鸡蛋这道菜: + +```markdown +# 西红柿炒鸡蛋的做法 + +西红柿炒蛋是中国家常几乎最常见的一道菜肴... +预估烹饪难度:★★ + +## 必备原料和工具 +* 西红柿 +* 鸡蛋 +* 食用油... + +## 计算 +每次制作前需要确定计划做几份... +* 西红柿 = 1 个(约 180g) * 份数 +* 鸡蛋 = 1.5 个 * 份数,向上取整... + +## 操作 +- 西红柿洗净 +- 可选:去掉西红柿的外表皮... + +## 附加内容 +这道菜根据不同的口味偏好,存在诸多版本... +``` + +从数据上来看,这种高度结构化的数据不需要过多处理就可以直接用于RAG系统构建。还记得我们在第2章学过的[**Markdown结构分块**](../chapter2/05_text_chunking.md#34-基于文档结构的分块)吗?这个数据完全契合那种按标题层级分块的思路。更重要的是,每个菜谱文件的内容都不算太长,单个章节的内容通常在几百字左右,这意味着可以直接按照标题进行分块,而不用担心第2章提到的那个问题——某个章节内容过长超出模型上下文窗口,需要与常规分块方法(如`RecursiveCharacterTextSplitter`)组合使用。 + +#### 3.2.2 结构分块局限 + +虽然Markdown结构分块看起来很理想,但在实际使用中可能会遇到一个问题:按照标题严格分块会把内容切得太细,导致上下文信息不完整。比如用户问"宫保鸡丁怎么做",如果严格按标题分块,可能只检索到"操作"这一个章节,但缺少了"必备原料和工具"的信息,LLM就无法给出完整的制作指导。甚至有时候检索到的是"附加内容"中的某个变化做法,没有基础制作步骤,回答就会显得莫名其妙。如果你尝试直接把整个菜谱文档作为一个块,可以发现效果反而比结构分块要好,因为上下文信息是完整的。 + +为了解决这个矛盾,可以采用父子文本块的策略:用小的子块进行精确检索,但在生成时传递完整的父文档给LLM。这种方法在第3章的索引优化中虽然没有专门介绍,但本质上也属于上下文拓展的一种应用。通过这种方式,我们既保证了检索的精确性,又确保了生成时上下文的完整性。 + +> 反正都是把整个文档传给LLM,我为什么不直接用整个文档分块呢? + +这个问题问得很好!关键在于当用户问"宫保鸡丁需要什么调料"时,如果直接用整个文档做向量检索,这个具体问题在整个文档中的占比很小,很可能检索不到或者排名很靠后。但如果用小块检索,"必备原料和工具"这个章节就能精确匹配用户的需求。 + +简单来说,这种设计是"小块检索,大块生成"——用小块的精确性找到相关内容,用大块的完整性保证回答质量。如果直接用整个文档分块,就失去了检索的精确性优势。 + +### 3.3 整体架构 + +数据处理好之后,剩余的部分就是四个主要流程的组合,每个流程对工具进行筛选和优化后就可以构建出一个简单的rag系统。当前项目的架构如下图所示: + +```mermaid +flowchart TD + %% 系统初始化 + START[🚀 系统启动] --> CONFIG[⚙️ 加载配置
RAGConfig] + CONFIG --> INIT[🔧 初始化模块] + + %% 索引加载/构建 + INIT --> INDEX_CHECK{📂 检查索引缓存} + INDEX_CHECK -->|存在| LOAD_INDEX[⚡ 加载已保存索引
秒级启动] + INDEX_CHECK -->|不存在| BUILD_NEW[🔨 构建新索引] + + %% 构建新索引的顺序流程 + BUILD_NEW --> DataPrep + DataPrep --> IndexBuild + IndexBuild --> SAVE_INDEX[💾 保存索引到配置路径] + + %% 加载已有索引也需要数据准备(用于检索模块) + LOAD_INDEX --> DataPrepForRetrieval[📚 加载文档和分块
用于检索模块] + DataPrepForRetrieval --> READY[✅ 系统就绪] + SAVE_INDEX --> READY + + %% 用户交互开始 + READY --> A[👤 用户输入问题] + A --> B{🎯 查询路由} + + %% 查询路由分支 + B -->|list| C[📋 推荐查询] + B -->|detail| D[📖 详细查询] + B -->|general| E[ℹ️ 一般查询] + + %% 查询重写逻辑 - 合并相同处理 + C --> KEEP[📝 保持原查询] + D --> KEEP + E --> REWRITE[🔄 查询重写] + + %% 所有查询都进入统一的检索流程 + KEEP --> F[🔍 混合检索
top_k=config.top_k] + REWRITE --> F + + %% 检索阶段 + F --> G[📊 向量检索
config.embedding_model] + F --> H[🔤 BM25检索
关键词匹配] + + %% RRF重排 + G --> I[⚡ RRF重排融合] + H --> I + I --> J[📖 检索到子块] + + %% 父子文档处理 + J --> K[🧠 智能去重
按相关性排序] + K --> L[📚 获取父文档] + + %% 生成阶段 - 根据路由类型选择不同模式 + L --> M{🎨 生成模式路由} + M -->|list查询| N[📋 生成菜品列表
简洁输出] + M -->|detail查询| O[📝 分步指导模式
config.llm_model
详细步骤] + M -->|general查询| P[💬 基础回答模式
config.temperature
一般信息] + + %% 输出结果 + N --> Q[✨ 返回结果] + O --> Q + P --> Q + + %% 数据准备子流程 + subgraph DataPrep [📚 数据准备模块] + R[📁 加载Markdown文件
config.data_path] --> S[🔧 元数据增强] + S --> T[✂️ 按标题分块] + T --> U[🏷️ 父子关系建立] + U --> CHUNKS[📦 输出文本块chunks] + end + + %% 索引构建子流程 + subgraph IndexBuild [🔍 索引构建模块] + CHUNKS --> V[🤖 BGE嵌入模型
config.embedding_model] + V --> W[📊 FAISS向量索引] + W --> X[💾 索引持久化
config.index_save_path] + end + + %% 配置管理子流程 + subgraph ConfigMgmt [⚙️ 配置管理] + CFG1[🎛️ 默认配置
DEFAULT_CONFIG] + CFG2[🔧 自定义配置
RAGConfig] + CFG3[🌐 环境变量
HF_ENDPOINT] + end + + %% 连接配置到各模块 + ConfigMgmt --> DataPrep + ConfigMgmt --> IndexBuild + ConfigMgmt --> F + ConfigMgmt --> O + ConfigMgmt --> P + + %% 样式定义 + classDef startup fill:#e3f2fd,stroke:#0277bd,stroke-width:2px + classDef config fill:#f1f8e9,stroke:#388e3c,stroke-width:2px + classDef userInput fill:#e1f5fe,stroke:#01579b,stroke-width:2px + classDef routing fill:#f3e5f5,stroke:#4a148c,stroke-width:2px + classDef rewrite fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px + classDef retrieval fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px + classDef generation fill:#fff3e0,stroke:#e65100,stroke-width:2px + classDef output fill:#fce4ec,stroke:#880e4f,stroke-width:2px + classDef module fill:#f1f8e9,stroke:#33691e,stroke-width:2px + classDef cache fill:#fff8e1,stroke:#f57c00,stroke-width:2px + classDef dataflow fill:#e1f5fe,stroke:#0277bd,stroke-width:2px + + %% 应用样式 + class START,INIT startup + class CONFIG,ConfigMgmt,CFG1,CFG2,CFG3 config + class INDEX_CHECK,LOAD_INDEX,SAVE_INDEX cache + class A userInput + class B,C,D,E,M routing + class KEEP,REWRITE rewrite + class F,G,H,I,J,K,L retrieval + class N,O,P generation + class Q output + class DataPrep,IndexBuild module + class BUILD_NEW,READY,DataPrepForRetrieval startup + class CHUNKS dataflow +``` + +### 3.4 项目结构 + +基于上面的架构,可以构建出如下项目结构: + +```text +code/C8/ +├── config.py # 配置管理 +├── main.py # 主程序入口 +├── requirements.txt # 依赖列表 +├── rag_modules/ # 核心模块 +│ ├── __init__.py +│ ├── data_preparation.py # 数据准备模块 +│ ├── index_construction.py # 索引构建模块 +│ ├── retrieval_optimization.py # 检索优化模块 +│ └── generation_integration.py # 生成集成模块 +└── vector_index/ # 向量索引缓存(自动生成) +``` + +## 小结 + +本节从项目背景出发,完成了RAG系统的环境配置和整体架构设计。从下一节开始,我们将深入学习各个模块的具体实现,看看如何将这些设计思路转化为可运行的代码。 diff --git a/docs/chapter8/02_data_preparation.md b/docs/chapter8/02_data_preparation.md new file mode 100644 index 0000000..2542a21 --- /dev/null +++ b/docs/chapter8/02_data_preparation.md @@ -0,0 +1,315 @@ +# 第二节 数据准备模块实现 + +RAG系统的效果很大程度上取决于数据准备的质量。在上一节中,我们明确了"小块检索,大块生成"的父子文本块策略。接下来学习如何将数据准备部分的架构思想转化为可运行的代码。 + +```mermaid +flowchart LR + %% 数据准备模块流程 + START[📁 加载Markdown文件] --> ENHANCE[🔧 元数据增强] + ENHANCE --> SPLIT[✂️ 按标题分块] + SPLIT --> RELATION[🏷️ 父子关系建立] + RELATION --> DEDUP[🧠 智能去重机制] + DEDUP --> OUTPUT[📦 输出文本块chunks] + + %% 子流程详细说明 + subgraph LoadProcess [文档加载过程] + L1[📂 递归查找md文件] + L2[📄 读取文件内容] + L3[🆔 分配父文档ID] + L1 --> L2 --> L3 + end + + subgraph EnhanceProcess [元数据增强过程] + E1[🏷️ 提取菜品分类] + E2[📝 提取菜品名称] + E3[⭐ 分析难度等级] + E1 --> E2 --> E3 + end + + subgraph SplitProcess [结构分块过程] + S1[一级标题分割] + S2[二级标题分割] + S3[三级标题分割] + S1 --> S2 --> S3 + end + + %% 连接子流程 + START -.-> LoadProcess + ENHANCE -.-> EnhanceProcess + SPLIT -.-> SplitProcess + + %% 样式定义 + classDef process fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px + classDef subprocess fill:#f1f8e9,stroke:#33691e,stroke-width:2px + classDef output fill:#e1f5fe,stroke:#0277bd,stroke-width:2px + + %% 应用样式 + class START,ENHANCE,SPLIT,RELATION,DEDUP process + class LoadProcess,EnhanceProcess,SplitProcess subprocess + class OUTPUT output +``` + +## 一、核心设计 + +数据准备模块的核心是实现"小块检索,大块生成"的父子文本块架构。 + +**父子文本块映射关系**: +``` +父文档(完整菜谱) +├── 子块1:菜品介绍 + 难度评级 +├── 子块2:必备原料和工具 +├── 子块3:计算(用量配比) +├── 子块4:操作(制作步骤) +└── 子块5:附加内容(变化做法) +``` + +**基本流程**: +- **检索阶段**:使用小的子块进行精确匹配,提高检索准确性 +- **生成阶段**:传递完整的父文档给LLM,确保上下文完整性 +- **智能去重**:当检索到同一道菜的多个子块时,合并为一个完整菜谱 + +**元数据增强**: +- **菜品分类**:从文件路径推断(荤菜、素菜、汤品等) +- **难度等级**:从内容中的星级标记提取 +- **菜品名称**:从文件名提取 +- **文档关系**:建立父子文档的ID映射关系 + +## 二、模块实现详解 + +> [data_preparation.py完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C8/rag_modules/data_preparation.py) + +### 2.1 类结构设计 + +```python +class DataPreparationModule: + """数据准备模块 - 负责数据加载、清洗和预处理""" + + def __init__(self, data_path: str): + self.data_path = data_path + self.documents: List[Document] = [] # 父文档(完整食谱) + self.chunks: List[Document] = [] # 子文档(按标题分割的小块) + self.parent_child_map: Dict[str, str] = {} # 子块ID -> 父文档ID的映射 +``` + +- `documents`: 存储完整的菜谱文档(父文档) +- `chunks`: 存储按标题分割的小块(子文档) +- `parent_child_map`: 维护父子关系映射 + +### 2.2 文档加载实现 + +#### 2.2.1 批量加载Markdown文件 + +```python +def load_documents(self) -> List[Document]: + """加载文档数据""" + documents = [] + data_path_obj = Path(self.data_path) + + for md_file in data_path_obj.rglob("*.md"): + # 读取文件内容,保持Markdown格式 + with open(md_file, 'r', encoding='utf-8') as f: + content = f.read() + + # 为每个父文档分配唯一ID + parent_id = str(uuid.uuid4()) + + # 创建Document对象 + doc = Document( + page_content=content, + metadata={ + "source": str(md_file), + "parent_id": parent_id, + "doc_type": "parent" # 标记为父文档 + } + ) + documents.append(doc) + + # 增强文档元数据 + for doc in documents: + self._enhance_metadata(doc) + + self.documents = documents + return documents +``` + +- `rglob("*.md")`: 递归查找所有Markdown文件 +- `parent_id`: 为每个父文档分配唯一ID,建立父子关系的关键 +- `doc_type`: 标记为"parent",便于区分父子文档 + +#### 2.2.2 元数据增强 + +```python +def _enhance_metadata(self, doc: Document): + """增强文档元数据""" + file_path = Path(doc.metadata.get('source', '')) + path_parts = file_path.parts + + # 提取菜品分类 + category_mapping = { + 'meat_dish': '荤菜', 'vegetable_dish': '素菜', 'soup': '汤品', + 'dessert': '甜品', 'breakfast': '早餐', 'staple': '主食', + 'aquatic': '水产', 'condiment': '调料', 'drink': '饮品' + } + + # 从文件路径推断分类 + doc.metadata['category'] = '其他' + for key, value in category_mapping.items(): + if key in file_path.parts: + doc.metadata['category'] = value + break + + # 提取菜品名称 + doc.metadata['dish_name'] = file_path.stem + + # 分析难度等级 + content = doc.page_content + if '★★★★★' in content: + doc.metadata['difficulty'] = '非常困难' + elif '★★★★' in content: + doc.metadata['difficulty'] = '困难' + # ... (其他难度等级判断) + +``` + +- **分类推断**: 从HowToCook项目的目录结构推断菜品分类 +- **难度提取**: 从内容中的星级标记自动提取难度等级 +- **名称提取**: 直接使用文件名作为菜品名称 + +### 2.3 Markdown结构分块 + +将完整的菜谱文档按照Markdown标题结构进行分块,实现父子文本块架构。 + +#### 2.3.1 分块策略 + +```python +def chunk_documents(self) -> List[Document]: + """Markdown结构感知分块""" + if not self.documents: + raise ValueError("请先加载文档") + + # 使用Markdown标题分割器 + chunks = self._markdown_header_split() + + # 为每个chunk添加基础元数据 + for i, chunk in enumerate(chunks): + if 'chunk_id' not in chunk.metadata: + # 如果没有chunk_id(比如分割失败的情况),则生成一个 + chunk.metadata['chunk_id'] = str(uuid.uuid4()) + chunk.metadata['batch_index'] = i # 在当前批次中的索引 + chunk.metadata['chunk_size'] = len(chunk.page_content) + + self.chunks = chunks + return chunks +``` + +#### 2.3.2 Markdown标题分割器 + +```python +def _markdown_header_split(self) -> List[Document]: + """使用Markdown标题分割器进行结构化分割""" + # 定义要分割的标题层级 + headers_to_split_on = [ + ("#", "主标题"), # 菜品名称 + ("##", "二级标题"), # 必备原料、计算、操作等 + ("###", "三级标题") # 简易版本、复杂版本等 + ] + + # 创建Markdown分割器 + markdown_splitter = MarkdownHeaderTextSplitter( + headers_to_split_on=headers_to_split_on, + strip_headers=False # 保留标题,便于理解上下文 + ) + + all_chunks = [] + for doc in self.documents: + # 对每个文档进行Markdown分割 + md_chunks = markdown_splitter.split_text(doc.page_content) + + # 为每个子块建立与父文档的关系 + parent_id = doc.metadata["parent_id"] + + for i, chunk in enumerate(md_chunks): + # 为子块分配唯一ID并建立父子关系 + child_id = str(uuid.uuid4()) + chunk.metadata.update(doc.metadata) + chunk.metadata.update({ + "chunk_id": child_id, + "parent_id": parent_id, + "doc_type": "child", # 标记为子文档 + "chunk_index": i # 在父文档中的位置 + }) + + # 建立父子映射关系 + self.parent_child_map[child_id] = parent_id + + all_chunks.extend(md_chunks) + + return all_chunks +``` + +- **三级标题分割**: 按照`#`、`##`、`###`进行层级分割 +- **保留标题**: 设置`strip_headers=False`,保留标题信息便于理解上下文 +- **父子关系**: 每个子块都记录其父文档的`parent_id` +- **唯一标识**: 每个子块都有独立的`child_id` + +#### 2.3.3 分块效果示例 + +以"西红柿炒鸡蛋"为例,分块后的效果: + +``` +原文档:西红柿炒鸡蛋的做法.md (父文档) +├── 子块1:# 西红柿炒鸡蛋的做法 + 简介 + 难度评级 +├── 子块2:## 必备原料和工具 + 食材清单 +├── 子块3:## 计算 + 用量配比公式 +├── 子块4:## 操作 + 详细制作步骤 +└── 子块5:## 附加内容 +``` + +**分块逻辑**: +- **子块1**: 包含一级标题及其下的所有内容(简介、难度评级),直到遇到下一个二级标题 +- **子块2-5**: 每个二级标题及其下的内容形成一个独立子块 +- **精确检索**: 用户问"需要什么食材"时,能精确匹配到子块2 +- **上下文完整**: 生成时传递完整的父文档,包含所有必要信息 + +### 2.4 智能去重 + +当用户询问"宫保鸡丁怎么做"时,可能会检索到同一道菜的多个子块。我们需要智能去重,避免重复信息。 + +```python +def get_parent_documents(self, child_chunks: List[Document]) -> List[Document]: + """根据子块获取对应的父文档(智能去重)""" + # 统计每个父文档被匹配的次数(相关性指标) + parent_relevance = {} + parent_docs_map = {} + + # 收集所有相关的父文档ID和相关性分数 + for chunk in child_chunks: + parent_id = chunk.metadata.get("parent_id") + if parent_id: + # 增加相关性计数 + parent_relevance[parent_id] = parent_relevance.get(parent_id, 0) + 1 + + # 缓存父文档(避免重复查找) + if parent_id not in parent_docs_map: + for doc in self.documents: + if doc.metadata.get("parent_id") == parent_id: + parent_docs_map[parent_id] = doc + break + + # 按相关性排序并构建去重后的父文档列表 + sorted_parent_ids = sorted(parent_relevance.keys(), + key=lambda x: parent_relevance[x], reverse=True) + + # 构建去重后的父文档列表 + parent_docs = [] + for parent_id in sorted_parent_ids: + if parent_id in parent_docs_map: + parent_docs.append(parent_docs_map[parent_id]) + + return parent_docs +``` + +**去重逻辑**: +1. **统计相关性**: 计算每个父文档被匹配的子块数量 +2. **按相关性排序**: 匹配子块越多的菜谱排名越靠前 +3. **去重输出**: 每个菜谱只输出一次完整文档 \ No newline at end of file diff --git a/docs/chapter8/03_index_retrieval.md b/docs/chapter8/03_index_retrieval.md new file mode 100644 index 0000000..3e2409b --- /dev/null +++ b/docs/chapter8/03_index_retrieval.md @@ -0,0 +1,281 @@ +# 第三节 索引构建与检索优化 + +```mermaid +flowchart LR + %% 索引构建与检索优化流程 + INPUT[📦 接收文本块chunks] --> INDEX_CHECK{📂 检查索引缓存} + INDEX_CHECK -->|存在| LOAD_INDEX[⚡ 加载已保存索引] + INDEX_CHECK -->|不存在| BUILD_INDEX[🔨 构建新索引] + + BUILD_INDEX --> EMBED[🤖 BGE嵌入模型] + EMBED --> FAISS[📊 FAISS向量索引] + FAISS --> SAVE[💾 保存索引] + + LOAD_INDEX --> SETUP[🔧 设置检索器] + SAVE --> SETUP + + SETUP --> QUERY[❓ 用户查询] + QUERY --> HYBRID[🔍 RRF混合检索] + + %% 混合检索详细流程 + subgraph HybridProcess [RRF混合检索过程] + H1[📊 向量检索语义相似度] + H2[🔤 BM25检索关键词匹配] + H3[⚡ RRF重排融合] + H1 --> H3 + H2 --> H3 + end + + %% 索引构建详细流程 + subgraph IndexProcess [索引构建过程] + I1[📝 文本向量化] + I2[🗂️ 构建FAISS索引] + I3[💾 索引持久化] + I1 --> I2 --> I3 + end + + %% 检索器设置流程 + subgraph SetupProcess [检索器设置过程] + S1[🔍 向量检索器设置] + S2[📋 BM25检索器设置] + S1 --> S2 + end + + HYBRID --> RESULT[📖 检索结果] + + %% 连接子流程 + BUILD_INDEX -.-> IndexProcess + HYBRID -.-> HybridProcess + SETUP -.-> SetupProcess + + %% 样式定义 + classDef index fill:#fff3e0,stroke:#e65100,stroke-width:2px + classDef retrieval fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px + classDef cache fill:#fff8e1,stroke:#f57c00,stroke-width:2px + classDef subprocess fill:#f1f8e9,stroke:#33691e,stroke-width:2px + classDef output fill:#e1f5fe,stroke:#0277bd,stroke-width:2px + + %% 应用样式 + class BUILD_INDEX,EMBED,FAISS,SAVE index + class SETUP,QUERY,HYBRID retrieval + class INDEX_CHECK,LOAD_INDEX cache + class IndexProcess,HybridProcess,SetupProcess subprocess + class INPUT,RESULT output +``` + +## 一、核心设计 + +### 1.1 索引构建 + +索引构建模块的核心任务是将文本块转换为向量表示,并构建高效的检索索引。这里选择之前一直使用的BGE-small-zh-v1.5作为嵌入模型,并使用FAISS作为向量数据库来存储和检索向量。为了提升系统启动速度,实现索引缓存机制。首次构建后会将FAISS索引保存到本地,后续启动时直接加载已有索引,可以将启动时间从几分钟缩短到几秒钟。 + +### 1.2 混合检索 + +检索优化模块实现了多种检索策略的组合。采用双路检索的方式:向量检索基于语义相似度,擅长理解查询意图;BM25检索基于关键词匹配,擅长精确匹配。为了综合两种检索方式的优势,我们使用RRF(Reciprocal Rank Fusion)算法来融合检索结果。这个算法会综合考虑两种检索结果的排名信息,避免过度依赖单一检索方式。 + +> RRF 可能并不是效果最好的重排方式,但是够用🫠。如果想使用 ColBERT、RankLLM 等更先进的重排方法可以自行尝试。 + +此外,系统还支持基于元数据的智能过滤,可以按菜品分类、难度等级等条件进行筛选检索。 + +## 二、索引构建模块 + +> [index_construction.py完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C8/rag_modules/index_construction.py) + +### 2.1 类结构设计 + +```python +class IndexConstructionModule: + """索引构建模块 - 负责向量化和索引构建""" + + def __init__(self, model_name: str = "BAAI/bge-small-zh-v1.5", + index_save_path: str = "./vector_index"): + self.model_name = model_name + self.index_save_path = index_save_path + self.embeddings = None + self.vectorstore = None + self.setup_embeddings() +``` + +- `index_save_path`: 索引保存路径 +- `embeddings`: HuggingFace嵌入模型实例 +- `vectorstore`: FAISS向量存储实例 + + + +### 2.2 嵌入模型初始化 + +```python +def setup_embeddings(self): + """初始化嵌入模型""" + self.embeddings = HuggingFaceEmbeddings( + model_name=self.model_name, + model_kwargs={'device': 'cpu'}, + encode_kwargs={'normalize_embeddings': True} + ) +``` + +### 2.3 向量索引构建 + +```python +def build_vector_index(self, chunks: List[Document]) -> FAISS: + """构建向量索引""" + if not chunks: + raise ValueError("文档块列表不能为空") + + # 提取文本内容 + texts = [chunk.page_content for chunk in chunks] + metadatas = [chunk.metadata for chunk in chunks] + + # 构建FAISS向量索引 + self.vectorstore = FAISS.from_texts( + texts=texts, + embedding=self.embeddings, + metadatas=metadatas + ) + + return self.vectorstore +``` + +使用FAISS作为向量数据库,它的检索速度很快,同时保存了文本内容和元数据信息,支持大规模向量的高效检索。 + +### 2.4 索引缓存机制 + +```python +def save_index(self): + """保存向量索引到配置的路径""" + if not self.vectorstore: + raise ValueError("请先构建向量索引") + + # 确保保存目录存在 + Path(self.index_save_path).mkdir(parents=True, exist_ok=True) + + self.vectorstore.save_local(self.index_save_path) + +def load_index(self): + """从配置的路径加载向量索引""" + if not self.embeddings: + self.setup_embeddings() + + if not Path(self.index_save_path).exists(): + return None + + self.vectorstore = FAISS.load_local( + self.index_save_path, + self.embeddings, + allow_dangerous_deserialization=True + ) + return self.vectorstore +``` + +索引缓存的效果很明显:首次运行时构建索引需要几分钟,但后续运行时加载索引只需几秒钟。索引文件通常只有几十MB,存储效率很高。 + +## 三、检索优化模块 + +> [retrieval_optimization.py完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C8/rag_modules/retrieval_optimization.py) + +### 3.1 类结构设计 + +```python +class RetrievalOptimizationModule: + """检索优化模块 - 负责混合检索和过滤""" + + def __init__(self, vectorstore: FAISS, chunks: List[Document]): + self.vectorstore = vectorstore + self.chunks = chunks + self.setup_retrievers() +``` + +- `vectorstore`: FAISS向量存储实例 +- `chunks`: 文档块列表,用于BM25检索 + +### 3.2 检索器设置 + +```python +def setup_retrievers(self): + """设置向量检索器和BM25检索器""" + # 向量检索器 + self.vector_retriever = self.vectorstore.as_retriever( + search_type="similarity", + search_kwargs={"k": 5} + ) + + # BM25检索器 + self.bm25_retriever = BM25Retriever.from_documents( + self.chunks, + k=5 + ) +``` + +### 3.3 RRF混合检索 + +```python +def hybrid_search(self, query: str, top_k: int = 3) -> List[Document]: + """混合检索 - 结合向量检索和BM25检索,使用RRF重排""" + # 分别获取向量检索和BM25检索结果 + vector_docs = self.vector_retriever.get_relevant_documents(query) + bm25_docs = self.bm25_retriever.get_relevant_documents(query) + + # 使用RRF重排 + reranked_docs = self._rrf_rerank(vector_docs, bm25_docs) + return reranked_docs[:top_k] + +def _rrf_rerank(self, vector_results: List[Document], bm25_results: List[Document]) -> List[Document]: + """RRF (Reciprocal Rank Fusion) 重排""" + + # RRF融合算法 + rrf_scores = {} + k = 60 # RRF参数 + + # 计算向量检索的RRF分数 + for rank, doc in enumerate(vector_results): + doc_id = id(doc) + rrf_scores[doc_id] = rrf_scores.get(doc_id, 0) + 1 / (k + rank + 1) + + # 计算BM25检索的RRF分数 + for rank, doc in enumerate(bm25_results): + doc_id = id(doc) + rrf_scores[doc_id] = rrf_scores.get(doc_id, 0) + 1 / (k + rank + 1) + + # 合并所有文档并按RRF分数排序 + all_docs = {id(doc): doc for doc in vector_results + bm25_results} + sorted_docs = sorted(all_docs.items(), + key=lambda x: rrf_scores.get(x[0], 0), + reverse=True) + + return [doc for _, doc in sorted_docs] +``` + +在当前系统中,两种检索方式各有优势: + +**向量检索的优势**: +- 理解语义相似性,如"简单易做的菜"能匹配到标记为"简单"的菜谱 +- 处理同义词和近义词,如"制作方法"和"做法"、"烹饪步骤" +- 理解用户意图,如"适合新手"能找到难度较低的菜谱 + +**BM25检索的优势**: +- 精确匹配菜名,如"宫保鸡丁"能准确找到对应菜谱 +- 匹配具体食材,如"土豆丝"、"西红柿"等关键词 +- 处理专业术语,如"爆炒"、"红烧"等烹饪手法 + +RRF算法能综合两种检索方式的排名信息,既保证了语义理解的准确性,又确保了关键词匹配的精确性。当然还可以用路由的方式,根据查询类型智能选择使用向量检索还是BM25检索。这种方法针对性强,能为不同类型的查询选择最优的检索方式;不足是路由规则的设计和维护比较复杂,边界情况难以处理,而且通常需要调用LLM来判断查询类型,会增加延迟和成本。 + +### 3.4 元数据过滤检索 + +```python +def metadata_filtered_search(self, query: str, filters: Dict[str, Any], + top_k: int = 5) -> List[Document]: + """基于元数据过滤的检索""" + # 先进行向量检索 + vector_retriever = self.vectorstore.as_retriever( + search_type="similarity", + search_kwargs={"k": top_k * 3, "filter": filters} # 扩大检索范围 + ) + + results = vector_retriever.invoke(query) + return results[:top_k] +``` + +**过滤检索应用场景**: +- 用户询问"推荐几道素菜"时,可以按菜品分类过滤,只检索素菜相关的内容 +- 新手用户问"有什么简单的菜谱"时,可以按难度等级过滤,只返回标记为"简单"的菜谱 +- 想做汤品时询问"今天喝什么汤",可以按分类过滤出所有汤品菜谱 diff --git a/docs/chapter8/04_generation_sys.md b/docs/chapter8/04_generation_sys.md new file mode 100644 index 0000000..1a3d649 --- /dev/null +++ b/docs/chapter8/04_generation_sys.md @@ -0,0 +1,414 @@ +# 第四节 生成集成与系统整合 + +Boss要打完喽!在最后一节来学习一下如何实现智能的生成集成模块,以及将所有模块整合成一个完整的RAG系统。 + +```mermaid +flowchart LR + %% 生成集成与系统整合流程 + INPUT[📖 检索结果] --> ROUTE{🎯 查询路由} + + %% 查询路由分支 + ROUTE -->|list| LIST_QUERY[📋 列表查询] + ROUTE -->|detail| DETAIL_QUERY[📖 详细查询] + ROUTE -->|general| GENERAL_QUERY[ℹ️ 一般查询] + + %% 查询重写处理 + LIST_QUERY --> KEEP[📝 保持原查询] + DETAIL_QUERY --> KEEP + GENERAL_QUERY --> REWRITE[🔄 查询重写] + + %% 父子文档处理 + KEEP --> PARENT[📚 获取父文档] + REWRITE --> PARENT + PARENT --> DEDUP[🧠 智能去重排序] + + %% 生成模式路由 + DEDUP --> GEN_ROUTE{🎨 生成模式路由} + GEN_ROUTE -->|list| LIST_GEN[📋 列表生成模式] + GEN_ROUTE -->|detail| DETAIL_GEN[📝 分步指导模式] + GEN_ROUTE -->|general| BASIC_GEN[💬 基础回答模式] + + %% 最终输出 + LIST_GEN --> OUTPUT[✨ 返回结果] + DETAIL_GEN --> OUTPUT + BASIC_GEN --> OUTPUT + + %% 查询路由详细流程 + subgraph RouteProcess [查询路由过程] + R1[🔍 分析查询类型] + R2[📊 判断用户意图] + R3[🎯 选择处理策略] + R1 --> R2 --> R3 + end + + %% 查询重写详细流程 + subgraph RewriteProcess [查询重写过程] + W1[📝 分析查询模糊度] + W2[🔧 优化查询表达] + W3[✅ 输出重写结果] + W1 --> W2 --> W3 + end + + %% 生成模式详细流程 + subgraph GenerationProcess [多模式生成过程] + G1[📋 简洁列表输出] + G2[📝 结构化详细指导] + G3[💬 基础信息回答] + G1 --> G2 --> G3 + end + + %% 系统整合流程 + subgraph SystemProcess [系统整合过程] + SYS1[🔧 模块初始化] + SYS2[📚 知识库构建] + SYS3[🔄 交互式问答] + SYS1 --> SYS2 --> SYS3 + end + + %% 连接子流程 + ROUTE -.-> RouteProcess + REWRITE -.-> RewriteProcess + GEN_ROUTE -.-> GenerationProcess + OUTPUT -.-> SystemProcess + + %% 样式定义 + classDef routing fill:#f3e5f5,stroke:#4a148c,stroke-width:2px + classDef rewrite fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px + classDef generation fill:#fff3e0,stroke:#e65100,stroke-width:2px + classDef system fill:#e3f2fd,stroke:#0277bd,stroke-width:2px + classDef subprocess fill:#f1f8e9,stroke:#33691e,stroke-width:2px + classDef output fill:#fce4ec,stroke:#880e4f,stroke-width:2px + + %% 应用样式 + class ROUTE,LIST_QUERY,DETAIL_QUERY,GENERAL_QUERY,GEN_ROUTE routing + class KEEP,REWRITE rewrite + class LIST_GEN,DETAIL_GEN,BASIC_GEN generation + class PARENT,DEDUP system + class RouteProcess,RewriteProcess,GenerationProcess,SystemProcess subprocess + class INPUT,OUTPUT output +``` + +## 一、生成集成模块 + +生成集成模块是整个RAG系统的"大脑",负责理解用户意图、路由查询类型,并生成高质量的回答。 + +> [generation_integration.py完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C8/rag_modules/generation_integration.py) + +### 1.1 设计思路 + +**智能查询路由**:根据用户查询自动判断是列表查询、详细查询还是一般查询,选择最适合的生成策略。 + +**查询重写优化**:对模糊不清的查询进行智能重写,提升检索效果。比如将"做菜"重写为"简单易做的家常菜谱"。 + +**多模式生成**: +- **列表模式**:适用于推荐类查询,返回简洁的菜品列表 +- **详细模式**:适用于制作类查询,提供分步骤的详细指导 +- **基础模式**:适用于一般性问题,提供常规回答 + +> 上面说到的两种主要方法可以回顾 [**查询重构与分发**](https://github.com/datawhalechina/all-in-rag/blob/main/docs/chapter4/14_query_rewriting.md) + +### 1.2 类结构设计 + +```python +class GenerationIntegrationModule: + """生成集成模块 - 负责LLM集成和回答生成""" + + def __init__(self, model_name: str = "kimi-k2-0711-preview", + temperature: float = 0.1, max_tokens: int = 2048): + self.model_name = model_name + self.temperature = temperature + self.max_tokens = max_tokens + self.llm = None + self.setup_llm() +``` + +- `temperature`: 生成温度,控制回答的创造性 +- `max_tokens`: 最大生成长度 +- `llm`: Moonshot Chat模型实例 + +### 1.3 查询路由实现 + +```python +def query_router(self, query: str) -> str: + """查询路由 - 根据查询类型选择不同的处理方式""" + prompt = ChatPromptTemplate.from_template(""" +根据用户的问题,将其分类为以下三种类型之一: + +1. 'list' - 用户想要获取菜品列表或推荐,只需要菜名 + 例如:推荐几个素菜、有什么川菜、给我3个简单的菜 + +2. 'detail' - 用户想要具体的制作方法或详细信息 + 例如:宫保鸡丁怎么做、制作步骤、需要什么食材 + +3. 'general' - 其他一般性问题 + 例如:什么是川菜、制作技巧、营养价值 + +请只返回分类结果:list、detail 或 general + +用户问题: {query} + +分类结果:""") + + # ... (LCEL链式调用) + return result +``` + +查询路由是整个系统的关键,决定了后续的处理流程。通过LLM自动判断查询意图,比简单的关键词匹配更准确。 + +### 1.4 查询重写优化 + +```python +def query_rewrite(self, query: str) -> str: + """智能查询重写 - 让大模型判断是否需要重写查询""" + # 使用LLM分析查询是否需要重写 + # 具体明确的查询(如"宫保鸡丁怎么做")保持原样 + # 模糊查询(如"做菜"、"推荐个菜")进行重写优化 + + # ... (提示词设计和LCEL链式调用) + return response +``` + +查询重写能够将模糊的用户输入转换为更适合检索的查询,显著提升系统的实用性。重写规则包括:保持原意不变、增加相关烹饪术语、优先推荐简单易做的菜品。 + +### 1.5 多模式生成 + +**列表模式生成**: +```python +def generate_list_answer(self, query: str, context_docs: List[Document]) -> str: + """生成列表式回答 - 适用于推荐类查询""" + # 提取菜品名称 + dish_names = [] + for doc in context_docs: + dish_name = doc.metadata.get('dish_name', '未知菜品') + if dish_name not in dish_names: + dish_names.append(dish_name) + + # 构建简洁的列表回答 + if len(dish_names) <= 3: + return f"为您推荐以下菜品:\n" + "\n".join([f"{i+1}. {name}" for i, name in enumerate(dish_names)]) + # ... (其他情况处理) +``` + +**详细模式生成**: +```python +def generate_step_by_step_answer(self, query: str, context_docs: List[Document]) -> str: + """生成分步骤回答""" + # 使用结构化提示词,包含: + # - 🥘 菜品介绍 + # - 🛒 所需食材 + # - 👨‍🍳 制作步骤 + # - 💡 制作技巧 + + # ... (提示词设计和LCEL链式调用) + return response +``` + +详细模式使用结构化的提示词设计,让LLM能够生成格式规范、内容丰富的分步骤指导,重点突出实用性和可操作性。 + +## 二、系统整合 + +主程序负责协调各个模块,实现完整的RAG流程:数据准备 → 索引构建 → 检索优化 → 生成集成。同时提供了索引缓存、交互式问答等实用功能。 + +> [main.py完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C8/main.py) + +### 2.1 主系统类设计 + +```python +class RecipeRAGSystem: + """食谱RAG系统主类""" + + def __init__(self, config: RAGConfig = None): + self.config = config or DEFAULT_CONFIG + self.data_module = None + self.index_module = None + self.retrieval_module = None + self.generation_module = None + + # 检查数据路径和API密钥 + if not Path(self.config.data_path).exists(): + raise FileNotFoundError(f"数据路径不存在: {self.config.data_path}") + if not os.getenv("MOONSHOT_API_KEY"): + raise ValueError("请设置 MOONSHOT_API_KEY 环境变量") +``` + +主系统类负责协调所有模块,确保系统的完整性和一致性。 + +### 2.2 系统初始化流程 + +```python +def initialize_system(self): + """初始化所有模块""" + # 1. 初始化数据准备模块 + self.data_module = DataPreparationModule(self.config.data_path) + + # 2. 初始化索引构建模块 + self.index_module = IndexConstructionModule( + model_name=self.config.embedding_model, + index_save_path=self.config.index_save_path + ) + + # 3. 初始化生成集成模块 + self.generation_module = GenerationIntegrationModule( + model_name=self.config.llm_model, + temperature=self.config.temperature, + max_tokens=self.config.max_tokens + ) +``` + +初始化过程按照依赖关系有序进行,保证每个模块都能正确设置。 + +### 2.3 知识库构建流程 + +```python +def build_knowledge_base(self): + """构建知识库""" + # 1. 尝试加载已保存的索引 + vectorstore = self.index_module.load_index() + + if vectorstore is not None: + # 加载已有索引,但仍需要文档和分块用于检索模块 + self.data_module.load_documents() + chunks = self.data_module.chunk_documents() + else: + # 构建新索引的完整流程 + self.data_module.load_documents() + chunks = self.data_module.chunk_documents() + vectorstore = self.index_module.build_vector_index(chunks) + self.index_module.save_index() + + # 初始化检索优化模块 + self.retrieval_module = RetrievalOptimizationModule(vectorstore, chunks) +``` + +这个流程运用了之前设计的索引缓存机制,能够大幅提升系统启动速度。 + +### 2.4 智能问答流程 + +```python +def ask_question(self, question: str, stream: bool = False): + """回答用户问题""" + # 1. 查询路由 + route_type = self.generation_module.query_router(question) + + # 2. 智能查询重写(根据路由类型) + if route_type == 'list': + rewritten_query = question # 列表查询保持原样 + else: + rewritten_query = self.generation_module.query_rewrite(question) + + # 3. 检索相关子块 + relevant_chunks = self.retrieval_module.hybrid_search(rewritten_query, top_k=self.config.top_k) + + # 4. 根据路由类型选择回答方式 + if route_type == 'list': + # 列表查询:返回菜品名称列表 + relevant_docs = self.data_module.get_parent_documents(relevant_chunks) + return self.generation_module.generate_list_answer(question, relevant_docs) + else: + # 详细查询:获取完整文档并生成详细回答 + relevant_docs = self.data_module.get_parent_documents(relevant_chunks) + + if route_type == "detail": + # 详细查询使用分步指导模式 + return self.generation_module.generate_step_by_step_answer(question, relevant_docs) + else: + # 一般查询使用基础回答模式 + return self.generation_module.generate_basic_answer(question, relevant_docs) +``` + +这部分展示了程序执行流程:智能路由 → 查询优化 → 混合检索 → 父子文档处理 → 多模式生成。 + +### 2.5 实际使用示例 + +#### 2.5.1 不同查询类型的效果 + +**列表查询示例**: +``` +用户问题: "推荐几道简单的素菜" +查询类型: list +生成结果: +为您推荐以下菜品: +1. 西红柿炒鸡蛋 +2. 土豆丝 +3. 青椒炒豆腐 +``` + +**详细查询示例**: +``` +用户问题: "宫保鸡丁怎么做?" +查询类型: detail +生成结果: +## 🥘 菜品介绍 +宫保鸡丁是一道经典川菜,口感麻辣鲜香... + +## 🛒 所需食材 +- 鸡胸肉 300g +- 花生米 100g +- 干辣椒 10个 +... + +## 👨‍🍳 制作步骤 +1. 鸡肉切丁,用料酒和生抽腌制15分钟 +2. 热锅下油,爆炒花生米至微黄盛起 +... +``` + +#### 2.5.2 交互式问答 + +系统提供了完整的命令行交互界面,启动时会显示"尝尝咸淡RAG系统"的欢迎信息: + +```python +def run_interactive(self): + """运行交互式问答""" + print("=" * 60) + print("🍽️ 尝尝咸淡RAG系统 - 交互式问答 🍽️") + print("=" * 60) + print("💡 解决您的选择困难症,告别'今天吃什么'的世纪难题!") + + # 初始化系统和构建知识库 + self.initialize_system() + self.build_knowledge_base() + + while True: + user_input = input("\n您的问题: ").strip() + if user_input.lower() in ['退出', 'quit', 'exit']: + break + + # 询问是否使用流式输出 + stream_choice = input("是否使用流式输出? (y/n, 默认y): ").strip().lower() + use_stream = stream_choice != 'n' + + if use_stream: + # 流式输出,实时显示生成过程 + for chunk in self.ask_question(user_input, stream=True): + print(chunk, end="", flush=True) + else: + # 普通输出 + answer = self.ask_question(user_input, stream=False) + print(answer) +``` + +**运行效果示例**: +``` +============================================================ +🍽️ 尝尝咸淡RAG系统 - 交互式问答 🍽️ +============================================================ +💡 解决您的选择困难症,告别'今天吃什么'的世纪难题! + +✅ 成功加载已保存的向量索引! +✅ 系统初始化完成! + +您的问题: 推荐几道简单的素菜 +是否使用流式输出? (y/n, 默认y): y + +为您推荐以下素菜: +1. 西红柿炒鸡蛋 - 经典家常菜,简单易做 +2. 土豆丝 - 爽脆可口,适合新手 +3. 青椒炒豆腐 - 营养丰富,制作简单 +``` + +流式输出的实现通过LangChain的`chain.stream()`方法,它会返回一个生成器,每次yield一个文本片段。在交互式界面中,通过`print(chunk, end="", flush=True)`实时输出每个片段,`end=""`避免换行,`flush=True`确保立即显示,从而实现逐字逐句的流式效果。 + +## 三、优化方向 + +虽然当前系统已经具备了完整的RAG功能,但仍有许多优化空间。未来的优化可以聚焦于几个关键方向的融合与深化:可以通过 **集成图数据库** 将食谱数据构建为知识图谱,来揭示食材、菜品与烹饪方法间的复杂关联,进而支持复杂关系查询(如“和鸡肉搭配的食材有哪些”)、发掘潜在的食材组合并实现基于图的智能推荐。还可以 **融合多模态数据**,结合菜品图片等视觉信息,利用多模态模型进行图文联合检索,不仅能支持“这是什么菜”的视觉搜索,还可以通过图像识别食材来推荐相关菜谱。或者通过 **增强专业知识**,集成营养成分数据库、烹饪技巧知识图谱以及食材替换规则库等外部知识源,系统将能提供精准的营养分析、专业的烹饪指导,并灵活适应用户的饮食过敏或个人偏好。 \ No newline at end of file diff --git a/docs/chapter8/images/8_1_1.webp b/docs/chapter8/images/8_1_1.webp new file mode 100644 index 0000000..16a5002 Binary files /dev/null and b/docs/chapter8/images/8_1_1.webp differ diff --git a/docs/chapter9/01_graph_rag_architecture.md b/docs/chapter9/01_graph_rag_architecture.md new file mode 100644 index 0000000..148c1d2 --- /dev/null +++ b/docs/chapter9/01_graph_rag_architecture.md @@ -0,0 +1,426 @@ +# 第一节 图RAG系统架构与环境配置 + +> 在前面章节的基础上,接下来构建一个更先进的图RAG系统。通过引入Neo4j图数据库和智能查询路由机制,实现真正的知识图谱增强检索,解决传统RAG在复杂查询和关系推理方面的局限性。 + +![neo4j](images/9_1_1.svg) + +## 一、项目背景与目标 + +### 1.1 从传统RAG到图RAG的演进 + +上一章中,我们构建了基于向量检索的传统RAG系统,采用了父子文本块的分块策略,能够有效回答简单的菜谱查询。但在处理复杂的关系推理和多跳查询时仍存在明显局限: + +- **关系理解缺失**:虽然父子分块保持了文档结构,但无法显式建模食材、菜谱、烹饪方法之间的语义关系 +- **跨文档关联困难**:难以发现不同菜谱之间的相似性、替代关系等隐含联系 +- **推理能力有限**:缺乏基于知识图谱的多跳推理能力,难以回答需要复杂逻辑推理的问题 + +### 1.2 图RAG系统的核心优势 + +通过引入知识图谱,我们的新系统将具备: + +- **结构化知识表达**:以图的形式显式编码实体间的语义关系 +- **增强推理能力**:支持多跳推理和复杂关系查询 +- **智能查询路由**:根据查询复杂度自动选择最适合的检索策略 +- **事实性与可解释性**:基于图结构的推理路径提供可追溯的答案 + +## 二、环境配置 + +> 若需要进行外部访问,需更换本地或服务器环境 + +### 2.1 创建虚拟环境 + +```bash +# 使用conda创建环境 +conda create -n graph-rag python=3.12.7 +conda activate graph-rag +``` + +### 2.2 安装核心依赖 + +```bash +cd code/C9 +pip install -r requirements.txt +``` + +### 2.3 Neo4j数据库配置 + +使用Docker Compose方式安装Neo4j,配置文件位于 [`data/C9/docker-compose.yml`](https://github.com/datawhalechina/all-in-rag/blob/main/data/C9/docker-compose.yml): + +#### 2.3.1 启动Neo4j服务 + +```bash +# 进入docker-compose.yml所在目录 +cd data/C9 + +# 启动Neo4j服务 +docker-compose up -d + +# 检查服务状态 +docker-compose ps +``` + +#### 2.3.2 访问Neo4j Web界面 + +启动成功后,可以通过以下方式访问: +- **Web界面**:http://localhost:7474 +- **用户名**:neo4j +- **密码**:all-in-rag + +> 当前网址为本地访问,如果你是部署在远程服务器上,需要将 `localhost` 修改为你的服务器IP地址。 + +#### 2.3.3 数据导入 + +Docker Compose配置中包含了自动数据导入功能。启动服务时会自动执行以下步骤: + +1. **等待Neo4j服务就绪**:通过健康检查确保数据库可用 +2. **执行导入脚本**:自动运行 `data/C9/cypher/neo4j_import.cypher` +3. **导入菜谱数据**:包括菜谱、食材、烹饪步骤等节点和关系 + +导入的数据包括: +- **菜谱节点**:包含菜名、难度、烹饪时间、菜系等信息 +- **食材节点**:包含食材名称、分类、营养信息等 +- **烹饪步骤节点**:包含步骤描述、烹饪方法、所需工具等 +- **关系网络**:菜谱与食材、步骤之间的复杂关系 + +如果需要手动重新导入数据: + +```bash +# 进入容器执行导入脚本 +docker exec -it neo4j-db cypher-shell -u neo4j -p all-in-rag -f /import/cypher/neo4j_import.cypher +``` + +### 2.4 Milvus向量数据库配置 + +#### 2.4.1 使用Docker安装Milvus + +> 如果前面已经安装过了可以跳过此步,通过 `docker-compose ps` 确认Milvus服务正在运行即可。 + +```bash +# 下载Milvus standalone配置文件 +wget https://github.com/milvus-io/milvus/releases/download/v2.5.11/milvus-standalone-docker-compose.yml -O docker-compose.yml + +# 启动Milvus +docker-compose up -d +``` + +#### 2.4.2 验证安装 + +```bash +# 检查Milvus服务状态 +docker-compose ps +``` + +### 2.5 配置连接参数 + +在项目根目录创建 `.env` 文件: + +```env +# Neo4j配置 +NEO4J_URI=bolt://localhost:7687 +NEO4J_USER=neo4j +NEO4J_PASSWORD=all-in-rag +NEO4J_DATABASE=neo4j + +# Milvus配置 +MILVUS_HOST=localhost +MILVUS_PORT=19530 + +# LLM API配置 +MOONSHOT_API_KEY=your_api_key_here +``` + +## 三、系统架构设计 + +### 3.1 整体架构 + +我们的图RAG系统采用模块化设计,包含以下核心组件: + +```mermaid +flowchart TD + %% 系统启动和初始化 + START["🚀 启动高级图RAG系统"] --> CONFIG["⚙️ 加载配置
GraphRAGConfig"] + CONFIG --> INIT_CHECK{"🔍 检查系统依赖"} + + %% 依赖检查 + INIT_CHECK -->|Neo4j连接失败| NEO4J_ERROR["❌ Neo4j连接错误
检查图数据库状态"] + INIT_CHECK -->|Milvus连接失败| MILVUS_ERROR["❌ Milvus连接错误
检查向量数据库"] + INIT_CHECK -->|LLM API失败| LLM_ERROR["❌ LLM API错误
检查API密钥"] + INIT_CHECK -->|依赖正常| INIT_MODULES["✅ 初始化核心模块"] + + %% 知识库状态检查 + INIT_MODULES --> KB_CHECK{"📚 检查知识库状态"} + KB_CHECK -->|Milvus集合存在| LOAD_KB["⚡ 加载已存在知识库"] + KB_CHECK -->|集合不存在| BUILD_KB["🔨 构建新知识库"] + + %% 加载已有知识库 + LOAD_KB --> LOAD_SUCCESS{"加载成功?"} + LOAD_SUCCESS -->|成功| SYSTEM_READY["✅ 系统就绪
显示统计信息"] + LOAD_SUCCESS -->|失败| REBUILD_KB["🔄 重建知识库"] + + %% 构建新知识库流程 + BUILD_KB --> NEO4J_LOAD["🔗 从Neo4j加载图数据
菜谱、食材、烹饪步骤节点"] + REBUILD_KB --> NEO4J_LOAD + NEO4J_LOAD --> BUILD_DOCS["📝 构建结构化菜谱文档
组合图数据为完整文档"] + BUILD_DOCS --> CHUNK_DOCS["✂️ 智能文档分块
按章节或长度分块"] + CHUNK_DOCS --> BUILD_VECTOR["🎯 构建Milvus向量索引"] + BUILD_VECTOR --> SYSTEM_READY + + %% 用户交互循环 + SYSTEM_READY --> USER_INPUT["👤 用户输入查询"] + USER_INPUT --> SPECIAL_CMD{"🔍 特殊命令检查"} + + %% 特殊命令处理 + SPECIAL_CMD -->|stats| STATS["📊 显示系统统计
路由统计、知识库状态"] + SPECIAL_CMD -->|rebuild| REBUILD_CMD["🔄 重建知识库命令"] + SPECIAL_CMD -->|quit| EXIT["👋 退出系统"] + + %% 普通查询处理 - 智能路由核心 + SPECIAL_CMD -->|普通查询| QUERY_ANALYSIS["🧠 深度查询分析"] + + %% 查询分析的四个维度 + QUERY_ANALYSIS --> COMPLEXITY_ANALYSIS["📊 复杂度分析
0.0-0.3: 简单查找
0.4-0.7: 中等复杂
0.8-1.0: 高复杂推理"] + QUERY_ANALYSIS --> RELATION_ANALYSIS["🔗 关系密集度分析
0.0-0.3: 单一实体
0.4-0.7: 实体关系
0.8-1.0: 复杂关系网络"] + QUERY_ANALYSIS --> REASONING_ANALYSIS["🤔 推理需求判断
多跳推理?因果分析?
对比分析?"] + QUERY_ANALYSIS --> ENTITY_ANALYSIS["🏷️ 实体识别统计
实体数量和类型"] + + %% LLM智能分析 + COMPLEXITY_ANALYSIS --> LLM_ANALYSIS["🤖 LLM智能分析
综合评估查询特征"] + RELATION_ANALYSIS --> LLM_ANALYSIS + REASONING_ANALYSIS --> LLM_ANALYSIS + ENTITY_ANALYSIS --> LLM_ANALYSIS + + %% 分析结果和降级处理 + LLM_ANALYSIS --> ANALYSIS_SUCCESS{"分析成功?"} + ANALYSIS_SUCCESS -->|成功| ROUTE_DECISION["🎯 智能路由决策"] + ANALYSIS_SUCCESS -->|失败| RULE_FALLBACK["📋 降级到规则分析
基于关键词匹配"] + RULE_FALLBACK --> ROUTE_DECISION + + %% 三种检索策略路由 + ROUTE_DECISION -->|简单查询
复杂度<0.4| HYBRID_SEARCH["🔍 传统混合检索
保底策略"] + ROUTE_DECISION -->|复杂推理
关系密集>0.7| GRAPH_RAG_SEARCH["🕸️ 图RAG检索
高级复杂策略"] + ROUTE_DECISION -->|中等复杂
需要组合| COMBINED_SEARCH["🔄 组合检索策略
融合两种方法"] + + %% 检索执行和错误处理 + HYBRID_SEARCH --> HYBRID_SUCCESS{"检索成功?"} + GRAPH_RAG_SEARCH --> GRAPH_SUCCESS{"检索成功?"} + COMBINED_SEARCH --> COMBINED_SUCCESS{"检索成功?"} + + %% 高级策略失败时降级到传统混合检索 + GRAPH_SUCCESS -->|失败| FALLBACK_TO_HYBRID["⬇️ 降级到传统混合检索
保底方案"] + COMBINED_SUCCESS -->|失败| FALLBACK_TO_HYBRID + + %% 传统混合检索失败时直接异常 + HYBRID_SUCCESS -->|失败| SYSTEM_ERROR["❌ 系统检索异常
传统混合检索失败
无更低级降级"] + FALLBACK_TO_HYBRID --> FALLBACK_SUCCESS{"降级检索成功?"} + FALLBACK_SUCCESS -->|失败| SYSTEM_ERROR + + %% 成功路径 + HYBRID_SUCCESS -->|成功| GENERATE["🎨 生成回答"] + GRAPH_SUCCESS -->|成功| GENERATE + COMBINED_SUCCESS -->|成功| GENERATE + FALLBACK_SUCCESS -->|成功| GENERATE + + %% 固定的流式输出 + GENERATE --> STREAM_OUTPUT["📺 流式输出回答
use_stream = True
逐字符实时显示"] + + %% 统计更新和循环 + STREAM_OUTPUT --> UPDATE_STATS["📈 更新路由统计"] + UPDATE_STATS --> USER_INPUT + + %% 特殊命令返回循环 + STATS --> USER_INPUT + REBUILD_CMD --> BUILD_KB + + %% 错误处理返回 + NEO4J_ERROR --> EXIT + MILVUS_ERROR --> EXIT + LLM_ERROR --> EXIT + SYSTEM_ERROR --> USER_INPUT + + %% 详细子流程 + subgraph DataFlow ["📊 图数据处理流程"] + NEO4J_DB["🗄️ Neo4j图数据库
存储菜谱、食材、烹饪步骤
以及它们之间的关系网络"] + RECIPE_BUILD["📝 结构化菜谱文档构建
菜谱名称 + 分类 + 难度
+ 食材列表 + 制作步骤
+ 时间信息 + 标签"] + DOC_CHUNK["✂️ 智能文档分块
按章节分块:## 所需食材、## 制作步骤
或按长度分块:chunk_size=500
重叠处理:chunk_overlap=50"] + MILVUS_INDEX["🎯 Milvus向量索引
BGE-small-zh-v1.5
512维向量空间"] + + NEO4J_DB --> RECIPE_BUILD + RECIPE_BUILD --> DOC_CHUNK + DOC_CHUNK --> MILVUS_INDEX + end + + subgraph HybridFlow ["🔍 传统混合检索流程(保底)"] + DUAL_RETRIEVAL["🎯 双层检索
实体级+主题级"] + VECTOR_SEARCH["📊 增强向量检索
语义相似度匹配"] + RRF_MERGE["⚖️ RRF轮询融合
公平合并不同结果"] + INTERNAL_FALLBACK["🔧 内部降级机制
关键词提取失败→简单分词
图索引不足→Neo4j补充
Neo4j失败→静默失败"] + + DUAL_RETRIEVAL --> RRF_MERGE + VECTOR_SEARCH --> RRF_MERGE + INTERNAL_FALLBACK --> RRF_MERGE + end + + subgraph GraphRAGFlow ["🕸️ 图RAG检索流程(高级复杂)"] + GRAPH_UNDERSTAND["🧠 图查询理解
entity_relation/multi_hop
subgraph/path_finding"] + MULTI_HOP["🔄 多跳图遍历
最大深度3跳
发现隐含关联"] + SUBGRAPH_EXTRACT["🕸️ 知识子图提取
完整知识网络
最大100节点"] + GRAPH_REASONING["🤔 图结构推理
推理链构建
可信度验证"] + + GRAPH_UNDERSTAND --> MULTI_HOP + GRAPH_UNDERSTAND --> SUBGRAPH_EXTRACT + MULTI_HOP --> GRAPH_REASONING + SUBGRAPH_EXTRACT --> GRAPH_REASONING + end + + subgraph CombinedFlow ["🔄 组合检索流程"] + SPLIT_QUOTA["📊 分配检索配额
traditional_k = top_k // 2
graph_k = top_k - traditional_k"] + PARALLEL_SEARCH["⚡ 并行执行检索
传统检索 + 图RAG检索"] + ROUND_ROBIN["🔄 Round-robin合并
交替添加结果
图RAG优先"] + DEDUP["🧹 去重和排序
基于内容哈希"] + + SPLIT_QUOTA --> PARALLEL_SEARCH + PARALLEL_SEARCH --> ROUND_ROBIN + ROUND_ROBIN --> DEDUP + end + + subgraph FallbackStrategy ["⬇️ 降级策略(有限降级)"] + LEVEL3["🕸️ 图RAG检索
最高级:多跳推理+子图提取"] + LEVEL2["🔄 组合检索
中级:融合两种方法"] + LEVEL1["🔍 传统混合检索
保底:无更低级降级"] + ERROR_LEVEL["❌ 系统异常
传统混合检索失败"] + + LEVEL3 -->|失败| LEVEL1 + LEVEL2 -->|失败| LEVEL1 + LEVEL1 -->|失败| ERROR_LEVEL + end + + %% 样式定义 + classDef startup fill:#e3f2fd,stroke:#0277bd,stroke-width:2px + classDef config fill:#f1f8e9,stroke:#388e3c,stroke-width:2px + classDef basic fill:#fff3e0,stroke:#f57c00,stroke-width:2px + classDef advanced fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px + classDef knowledge fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px + classDef analysis fill:#f3e5f5,stroke:#4a148c,stroke-width:2px + classDef routing fill:#e1f5fe,stroke:#01579b,stroke-width:2px + classDef generation fill:#fce4ec,stroke:#880e4f,stroke-width:2px + classDef userflow fill:#fff8e1,stroke:#f57c00,stroke-width:2px + classDef error fill:#ffebee,stroke:#c62828,stroke-width:2px + classDef success fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px + classDef fallback fill:#fff3e0,stroke:#ff6f00,stroke-width:2px + classDef stream fill:#e1f5fe,stroke:#0288d1,stroke-width:2px + classDef combined fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px + classDef graphdata fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px + + %% 应用样式 + class START,INIT_MODULES,SYSTEM_READY startup + class CONFIG config + class HYBRID_SEARCH,HybridFlow,LEVEL1 basic + class GRAPH_RAG_SEARCH,GraphRAGFlow,LEVEL3 advanced + class KB_CHECK,LOAD_KB,BUILD_KB,NEO4J_LOAD,BUILD_DOCS,CHUNK_DOCS,BUILD_VECTOR knowledge + class QUERY_ANALYSIS,COMPLEXITY_ANALYSIS,RELATION_ANALYSIS,REASONING_ANALYSIS,ENTITY_ANALYSIS,LLM_ANALYSIS analysis + class ROUTE_DECISION,ANALYSIS_SUCCESS,RULE_FALLBACK routing + class GENERATE generation + class USER_INPUT,SPECIAL_CMD,STATS,REBUILD_CMD,EXIT userflow + class NEO4J_ERROR,MILVUS_ERROR,LLM_ERROR,SYSTEM_ERROR,ERROR_LEVEL error + class LOAD_SUCCESS,INIT_CHECK,HYBRID_SUCCESS,GRAPH_SUCCESS,COMBINED_SUCCESS,FALLBACK_SUCCESS success + class FALLBACK_TO_HYBRID,FallbackStrategy fallback + class STREAM_OUTPUT,UPDATE_STATS stream + class COMBINED_SEARCH,CombinedFlow,LEVEL2 combined + class DataFlow,NEO4J_DB graphdata +``` + +### 3.2 核心模块说明 + +#### 图数据准备模块 (GraphDataPreparationModule) +- **功能**:连接Neo4j数据库,加载图数据,构建结构化菜谱文档 +- **特点**:支持图数据到文档的智能转换,保持知识结构完整性 + +#### 向量索引模块 (MilvusIndexConstructionModule) +- **功能**:构建和管理Milvus向量索引,支持语义相似度检索 +- **特点**:使用BGE-small-zh-v1.5模型,512维向量空间 + +#### 混合检索模块 (HybridRetrievalModule) +- **功能**:传统的混合检索策略,结合向量检索和图扩展 +- **特点**:双层检索(实体级+主题级),RRF轮询融合 + +#### 图RAG检索模块 (GraphRAGRetrieval) +- **功能**:基于图结构的高级检索,支持多跳推理和子图提取 +- **特点**:图查询理解、多跳遍历、知识子图提取 + +#### 智能查询路由 (IntelligentQueryRouter) +- **功能**:分析查询特征,自动选择最适合的检索策略 +- **特点**:LLM驱动的查询分析,动态策略选择 + +#### 生成集成模块 (GenerationIntegrationModule) +- **功能**:基于检索结果生成最终答案,支持流式输出 +- **特点**:自适应生成策略,错误处理与重试机制 + +### 3.3 数据流程 + +1. **数据准备阶段**: + - 从Neo4j加载图数据(菜谱、食材、步骤节点及其关系) + - 构建结构化菜谱文档,保持知识完整性 + - 进行智能文档分块,支持章节和长度双重分块策略 + - 构建Milvus向量索引,支持语义检索 + +2. **查询处理阶段**: + - 用户输入查询 + - 智能查询路由器分析查询特征(复杂度、关系密集度、推理需求) + - 根据分析结果选择检索策略: + - 简单查询 → 传统混合检索 + - 复杂推理 → 图RAG检索 + - 中等复杂 → 组合检索策略 + - 执行相应的检索操作 + - 生成模块基于检索结果生成答案 + +3. **错误处理与降级**: + - 高级策略失败时自动降级到传统混合检索 + - 传统混合检索失败时返回系统异常 + - 支持流式输出中断时的自动重试机制 + +## 四、项目文件结构 + +``` +code/C9/ +├── main.py # 主程序入口 +├── config.py # 配置文件 +├── requirements.txt # 依赖包列表 +└── rag_modules/ # RAG模块包 + ├── __init__.py + ├── graph_data_preparation.py # 图数据准备模块 + ├── milvus_index_construction.py # Milvus索引构建模块 + ├── hybrid_retrieval.py # 混合检索模块 + ├── graph_rag_retrieval.py # 图RAG检索模块 + ├── intelligent_query_router.py # 智能查询路由器 + └── generation_integration.py # 生成集成模块 +``` + +## 五、快速开始 + +### 5.1 启动系统 + +```bash +# 确保Neo4j和Milvus服务已启动 +python main.py +``` + +### 5.2 系统初始化 + +首次运行时,系统会自动: +1. 检查并连接Neo4j和Milvus数据库 +2. 加载图数据并构建菜谱文档 +3. 创建向量索引 +4. 初始化各个检索模块 +5. 显示系统统计信息 + +### 5.3 交互式问答 + +系统启动后,可以进行交互式问答: + +``` +您的问题: 川菜有哪些特色菜? +您的问题: 如何制作宫保鸡丁? +您的问题: 减肥期间适合吃什么菜? +您的问题: stats # 查看系统统计 +您的问题: quit # 退出系统 +``` diff --git a/docs/chapter9/02_graph_data_modeling.md b/docs/chapter9/02_graph_data_modeling.md new file mode 100644 index 0000000..f0ce30a --- /dev/null +++ b/docs/chapter9/02_graph_data_modeling.md @@ -0,0 +1,445 @@ +# 第二节 图数据建模与Neo4j集成 + +> [本节完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C9/rag_modules/graph_data_preparation.py) + +## 一、数据来源与转换 + +### 1.1 从Markdown到图数据的转换 + +本章的图数据来源于第八章中使用的Markdown格式菜谱数据。为了构建知识图谱,笔者用AI开发了一个简单的[Agent](https://github.com/datawhalechina/all-in-rag/tree/main/code/C9/agent(%E4%BB%A3%E7%A0%81%E7%B3%BBai%E7%94%9F%E6%88%90)),通过LLM将结构化的Markdown菜谱数据转换为CSV格式的图数据。 + +**转换流程**: +1. **读取Markdown菜谱**:从第八章的数据源加载菜谱文件 +2. **LLM解析提取**:使用大语言模型识别和提取实体及关系 +3. **结构化输出**:生成nodes.csv和relationships.csv文件 +4. **图数据导入**:通过Cypher脚本导入Neo4j数据库 + +### 1.2 图数据文件结构 + +转换后的图数据包含两个核心文件: + +``` +data/C9/cypher/ +├── nodes.csv # 节点数据(菜谱、食材、步骤等) +├── relationships.csv # 关系数据(菜谱-食材、菜谱-步骤等) +└── neo4j_import.cypher # 数据导入脚本 +``` + +## 二、图数据模型设计 + +### 2.1 实际数据结构分析 + +基于LLM转换后的实际图数据,知识图谱包含以下核心实体类型。如果你有游戏逆向经验,可以把这些实体类型想象成虚幻引擎烹饪游戏中的对象类,节点间的关系就像对象间的指针引用: + +**核心实体类型**: +- **Recipe (菜谱)**:具体的菜品,包含难度、菜系、时间等属性 +- **Ingredient (食材)**:制作菜品所需的原料,包含分类、用量、单位等 +- **CookingStep (烹饪步骤)**:详细的制作步骤,包含方法、工具、时间估计 +- **CookingMethod (烹饪方法)**:如炒、煮、蒸、炸等烹饪技法 +- **CookingTool (烹饪工具)**:如炒锅、蒸锅、刀具等 +- **DifficultyLevel (难度等级)**:一星到五星的难度分级 +- **RecipeCategory (菜谱分类)**:素菜、荤菜、水产、早餐等分类 + +**实际数据特点**: +- **统一编码体系**:使用nodeId进行唯一标识(如201000001) +- **多语言支持**:包含preferredTerm、fsn等多语言字段 +- **丰富属性**:每个实体包含详细的属性信息 +- **层次化结构**:从抽象概念到具体实例的层次化组织 + +### 2.2 实际节点模型 + +基于实际数据的图数据模型: + +```mermaid +graph TB + %% 定义节点样式 + classDef recipeNode fill:#e1f5fe,stroke:#01579b,stroke-width:2px + classDef ingredientNode fill:#f3e5f5,stroke:#4a148c,stroke-width:2px + classDef stepNode fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px + classDef categoryNode fill:#fff3e0,stroke:#e65100,stroke-width:2px + classDef difficultyNode fill:#fce4ec,stroke:#880e4f,stroke-width:2px + + %% 菜谱节点 + Recipe["🍽️ Recipe
菜谱节点
---
nodeId: String
name: String
preferredTerm: String
fsn: String
conceptType: String
synonyms: String
category: String
difficulty: Float
cuisineType: String
prepTime: String
cookTime: String
servings: String
tags: String
filePath: String"] + + %% 食材节点 + Ingredient["🥬 Ingredient
食材节点
---
nodeId: String
name: String
preferredTerm: String
category: String
amount: String
unit: String
isMain: Boolean
synonyms: String"] + + %% 烹饪步骤节点 + CookingStep["👨‍🍳 CookingStep
烹饪步骤节点
---
nodeId: String
name: String
description: String
stepNumber: Float
methods: String
tools: String
timeEstimate: String"] + + %% 菜谱分类节点 + RecipeCategory["📂 RecipeCategory
菜谱分类节点
---
nodeId: String
name: String
preferredTerm: String
fsn: String"] + + %% 难度等级节点 + DifficultyLevel["⭐ DifficultyLevel
难度等级节点
---
nodeId: String
name: String
preferredTerm: String
fsn: String"] + + %% 关系连接 + Recipe -->|REQUIRES
需要食材
amount, unit| Ingredient + Recipe -->|CONTAINS_STEP
包含步骤
step_order| CookingStep + Recipe -->|BELONGS_TO_CATEGORY
属于分类| RecipeCategory + Recipe -->|HAS_DIFFICULTY_LEVEL
具有难度| DifficultyLevel + + %% 应用样式 + class Recipe recipeNode + class Ingredient ingredientNode + class CookingStep stepNode + class RecipeCategory categoryNode + class DifficultyLevel difficultyNode +``` + +**节点类型说明**: + +- **🍽️ Recipe (菜谱节点)**: 核心实体,包含菜谱的完整信息 +- **🥬 Ingredient (食材节点)**: 制作菜谱所需的食材信息 +- **👨‍🍳 CookingStep (烹饪步骤节点)**: 详细的制作步骤和方法 +- **📂 RecipeCategory (菜谱分类节点)**: 菜品分类(素菜、荤菜、水产等) +- **⭐ DifficultyLevel (难度等级节点)**: 制作难度分级(一星到五星) + +### 2.3 实际关系模型 + +基于实际数据的关系结构: + +```mermaid +graph LR + %% 定义节点样式 + classDef recipeNode fill:#e1f5fe,stroke:#01579b,stroke-width:3px + classDef ingredientNode fill:#f3e5f5,stroke:#4a148c,stroke-width:2px + classDef stepNode fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px + classDef categoryNode fill:#fff3e0,stroke:#e65100,stroke-width:2px + classDef difficultyNode fill:#fce4ec,stroke:#880e4f,stroke-width:2px + classDef rootNode fill:#f5f5f5,stroke:#424242,stroke-width:2px + classDef methodNode fill:#e3f2fd,stroke:#0277bd,stroke-width:2px + classDef toolNode fill:#f1f8e9,stroke:#33691e,stroke-width:2px + + %% 核心节点 + Recipe["🍽️ Recipe
菜谱"] + Ingredient["🥬 Ingredient
食材"] + CookingStep["👨‍🍳 CookingStep
烹饪步骤"] + RecipeCategory["📂 RecipeCategory
菜谱分类"] + DifficultyLevel["⭐ DifficultyLevel
难度等级"] + + %% 层次化节点 + Root["🌳 Root
根节点"] + CookingMethod["🔥 CookingMethod
烹饪方法"] + CookingTool["🔧 CookingTool
烹饪工具"] + + %% 主要关系 - 带属性标注 + Recipe -.->|"REQUIRES
relationshipId: String
amount: String
unit: String

示例: 300g, 2个"| Ingredient + Recipe -.->|"CONTAINS_STEP
relationshipId: String
step_order: Float

示例: 1.0, 2.0"| CookingStep + Recipe -->|"BELONGS_TO_CATEGORY
菜谱分类关系"| RecipeCategory + Recipe -->|"HAS_DIFFICULTY_LEVEL
难度等级关系"| DifficultyLevel + + %% 层次化关系 + Root -->|"IS_A
概念层次"| Recipe + Root -->|"IS_A
概念层次"| Ingredient + Root -->|"IS_A
概念层次"| CookingMethod + Root -->|"IS_A
概念层次"| CookingTool + + %% 应用样式 + class Recipe recipeNode + class Ingredient ingredientNode + class CookingStep stepNode + class RecipeCategory categoryNode + class DifficultyLevel difficultyNode + class Root rootNode + class CookingMethod methodNode + class CookingTool toolNode +``` + +**关系类型说明**: + +| 关系编码 | 关系类型 | 说明 | 属性 | +|---------|---------|------|------| +| **801000001** | REQUIRES | 菜谱-食材关系 | relationshipId, amount, unit | +| **801000003** | CONTAINS_STEP | 菜谱-步骤关系 | relationshipId, step_order | +| **801000004** | HAS_DIFFICULTY_LEVEL | 菜谱-难度关系 | relationshipId | +| **801000005** | BELONGS_TO_CATEGORY | 菜谱-分类关系 | relationshipId | + +**关系特点**: +- **虚线箭头**:表示带有丰富属性的关系(如REQUIRES、CONTAINS_STEP) +- **实线箭头**:表示简单的分类关系 +- **层次化结构**:Root节点作为概念层次的顶层节点 + +## 三、Neo4j数据导入 + +### 3.1 数据准备脚本 + +系统通过 `GraphDataPreparationModule` 来处理图数据的加载和管理: + +```python +class GraphDataPreparationModule: + def __init__(self, neo4j_config: dict): + """ + 初始化图数据准备模块 + + Args: + neo4j_config: Neo4j连接配置 + """ + self.driver = GraphDatabase.driver( + neo4j_config['uri'], + auth=(neo4j_config['user'], neo4j_config['password']) + ) + + def load_graph_data(self) -> List[Dict]: + """ + 从Neo4j加载图数据 + + Returns: + 包含菜谱信息的字典列表 + """ + query = """ + MATCH (r:Recipe) + OPTIONAL MATCH (r)-[:REQUIRES]->(i:Ingredient) + OPTIONAL MATCH (r)-[:HAS_STEP]->(s:Step) + OPTIONAL MATCH (r)-[:BELONGS_TO]->(c:Category) + RETURN r, collect(DISTINCT i) as ingredients, + collect(DISTINCT s) as steps, + collect(DISTINCT c) as categories + ORDER BY r.name + """ + + with self.driver.session() as session: + result = session.run(query) + return [record for record in result] +``` + +### 3.2 实际CSV数据格式 + +转换后的CSV文件格式(基于实际数据): + +**nodes.csv结构**: +```csv +nodeId,labels,name,preferredTerm,fsn,conceptType,synonyms,category,difficulty,cuisineType,prepTime,cookTime,servings,tags,filePath,amount,unit,isMain,description,stepNumber,methods,tools,timeEstimate +``` + +**实际数据示例**: +```csv +201000184,Recipe,干煎阿根廷红虾,干煎阿根廷红虾,,Recipe,"[{'term': '干pan-fried阿根廷红虾', 'language': 'zh'}]",水产,3.0,,提前1天冷藏解冻+10分钟,约5分钟,1人,"趁热吃,柠檬可增酸提味",dishes\aquatic\干煎阿根廷红虾\干煎阿根廷红虾.md,,,,,,,, +201000185,Ingredient,阿根廷红虾,阿根廷红虾,,Ingredient,,蛋白质,,,,,,,,2-3,只,True,,,,, +201000196,CookingStep,步骤1,步骤1,,CookingStep,,,,,,,,,,,,,阿根廷红虾提前1天从速冻取出放到冷藏里自然解冻,1.0,解冻,冰箱,24小时 +``` + +**relationships.csv结构**: +```csv +startNodeId,endNodeId,relationshipType,relationshipId,amount,unit,step_order +``` + +**实际关系示例**: +```csv +201000184,201000185,801000001,R_000001,2-3,只, +201000184,201000196,801000003,R_000010,,,1.0 +201000184,720000000,801000002,R_000020,,, +``` + +## 四、图数据查询与检索 + +### 4.1 基础查询模式 + +#### 简单实体查询 +```cypher +// 查找所有水产类菜谱 +MATCH (r:Recipe) +WHERE r.category = "水产" +RETURN r.name, r.difficulty, r.prepTime, r.cookTime + +// 查找包含特定食材的菜谱 +MATCH (r:Recipe)-[:REQUIRES]->(i:Ingredient) +WHERE i.name CONTAINS "虾" +RETURN r.name, r.difficulty, i.name, i.amount, i.unit + +// 使用全文搜索查找菜谱 +CALL db.index.fulltext.queryNodes("recipe_fulltext_index", "川菜 OR 辣椒") +YIELD node, score +RETURN node.name, node.category, score +ORDER BY score DESC +``` + +#### 多跳关系查询 +```cypher +// 查找某个难度等级的所有菜谱(基于属性查询) +MATCH (r:Recipe) +WHERE r.difficulty = 3.0 +RETURN r.name, r.category, r.prepTime, r.cookTime, r.difficulty + +// 查找菜谱的完整制作流程 +MATCH (r:Recipe {name: "干煎阿根廷红虾"})-[:CONTAINS_STEP]->(s:CookingStep) +RETURN r.name, s.stepNumber, s.description, s.methods, s.tools +ORDER BY s.stepNumber +``` + +### 4.2 复杂推理查询 + +#### 基于约束的菜谱推荐 +```cypher +// 查找适合新手的简单菜谱(低难度、步骤少) +MATCH (r:Recipe) +WHERE r.difficulty <= 2.0 + AND r.stepCount <= 5 +RETURN r.name, r.difficulty, r.stepCount, r.category +ORDER BY r.difficulty, r.stepCount + +// 查找制作时间短的菜谱 +MATCH (r:Recipe) +WHERE r.prepTime IS NOT NULL AND r.cookTime IS NOT NULL + AND r.prepTime CONTAINS "分钟" AND r.cookTime CONTAINS "分钟" +RETURN r.name, r.prepTime, r.cookTime, r.category +ORDER BY r.name +``` + +#### 菜谱组合推荐 +```cypher +// 查找同一分类下的不同菜谱 +MATCH (r1:Recipe), (r2:Recipe) +WHERE r1.category = r2.category + AND r1.category = "水产" + AND r1.nodeId <> r2.nodeId +RETURN r1.name, r2.name, r1.category +LIMIT 5 + +// 查找包含相同食材的不同菜谱 +MATCH (r1:Recipe)-[:REQUIRES]->(i:Ingredient)<-[:REQUIRES]-(r2:Recipe) +WHERE r1.nodeId <> r2.nodeId + AND i.name = "阿根廷红虾" +RETURN r1.name, r2.name, i.name +``` + +## 五、图数据到文档的转换 + +### 5.1 结构化文档构建 + +```python +def build_recipe_documents(self, graph_data: List[Dict]) -> List[Document]: + """将图数据转换为结构化文档""" + + documents = [] + for record in graph_data: + recipe = record['r'] + ingredients = record['ingredients'] + steps = record['steps'] + categories = record['categories'] + + # 构建结构化文档内容 + content_parts = [ + f"# {recipe['name']}", + f"分类: {', '.join([c['name'] for c in categories])}", + f"难度: {recipe['difficulty']}星", + # ... 时间、份量等基本信息 + "", + "## 所需食材" + ] + + # 添加食材列表 + for i, ingredient in enumerate(ingredients, 1): + content_parts.append(f"{i}. {ingredient['name']}") + + content_parts.extend(["", "## 制作步骤"]) + + # 添加制作步骤(按顺序排序) + sorted_steps = sorted(steps, key=lambda x: x.get('order', 0)) + for step in sorted_steps: + content_parts.extend([ + f"### 第{step['order']}步", + step['description'], + "" + ]) + + # 创建Document对象 + document = Document( + page_content="\n".join(content_parts), + metadata={ + 'recipe_name': recipe['name'], + 'node_id': recipe.get('nodeId'), # 关键:保持与图节点的关联 + 'difficulty': recipe.get('difficulty', 0), + 'categories': [c['name'] for c in categories], + 'ingredients': [i['name'] for i in ingredients] + # ... 其他元数据 + } + ) + documents.append(document) + + return documents +``` + +> **为什么不直接读取原始Markdown文件?** +> +> 虽然第八章中HowToCook项目的Markdown格式是统一的,但图RAG的价值在于提供更丰富的信息: +> +> **原始Markdown的特点**: +> - **格式统一**:HowToCook项目有良好的Markdown结构(`#`、`##`、`###`层级) +> - **信息完整**:包含菜品名称、原料、制作步骤等基本信息 +> - **元数据推断**:可以从文件路径推断分类,从`★★★★★`符号推断难度 +> +> **图数据构建文档的额外价值**: +> 1. **关系信息丰富**:包含食材间的替代关系、菜谱间的相似性等图关系 +> 2. **结构化查询**:可以通过图关系快速获取相关信息(如"包含鸡肉的所有菜谱") +> 3. **动态内容生成**:根据图关系动态生成推荐内容(如"相似菜谱"、"替代食材") +> 4. **语义增强**:图数据库可以存储更丰富的语义信息和计算结果 +> 5. **查询优化**:图查询在复杂关系检索上比文本搜索更高效 + +### 5.2 图RAG中的分块策略 + +在图RAG系统中,分块策略与上个项目有所不同,主要体现在**数据来源和上下文获取方式**的差异: + +**图RAG vs 传统RAG的分块对比**: + +| 特性 | 第八章 传统RAG | 第九章 图RAG | +|------|-----------------|----------------| +| **数据来源** | 直接读取Markdown文件 | 从图数据库构建文档 | +| **上下文获取** | 父子文档映射 | 图关系遍历 | +| **关系信息** | 有限(仅父子关系) | 丰富(多种图关系) | +| **分块策略** | 按Markdown标题分块 | 按语义+长度智能分块 | +| **元数据来源** | 文件路径+内容推断 | 图节点结构化数据 | + +**图RAG分块的特点**: +1. **保持图关联**:每个chunk通过`parent_id`与图节点关联 +2. **语义优先分块**:优先按章节分块,保持语义完整性 +3. **丰富的元数据**:直接从图节点获取结构化信息 +4. **双重上下文**:既有文本块关系,又有图关系信息 + +### 5.3 实际分块实现 + +在图RAG系统中,采用的实际分块策略: + +```python +def chunk_documents(self, chunk_size: int = 500, chunk_overlap: int = 50) -> List[Document]: + """图RAG文档分块:结合图结构优势的智能分块策略""" + + chunks = [] + for doc in self.documents: + content = doc.page_content + + if len(content) <= chunk_size: + # 短文档:保持完整,避免破坏语义 + chunk = Document( + page_content=content, + metadata={ + **doc.metadata, + "parent_id": doc.metadata["node_id"], # 关键:保持与图节点的关联 + "chunk_index": 0, + "doc_type": "chunk" + } + ) + chunks.append(chunk) + else: + # 长文档:智能分块策略 + sections = content.split('\n## ') + + if len(sections) <= 1: + # 无章节结构:按长度分块(带重叠) + total_chunks = (len(content) - 1) // (chunk_size - chunk_overlap) + 1 + for i in range(total_chunks): + start = i * (chunk_size - chunk_overlap) + end = min(start + chunk_size, len(content)) + # ... 创建chunk,保持parent_id关联 + else: + # 有章节结构:按语义分块(推荐) + for i, section in enumerate(sections): + chunk_content = section if i == 0 else f"## {section}" + # ... 创建chunk,包含section_title信息 + + return chunks +``` + +图RAG的分块策略在保持语义完整性的基础上,充分利用图数据库的结构化优势。与第八章直接读取Markdown文件不同,这里从图数据库构建标准化文档,每个chunk通过`parent_id`与原始Recipe节点保持关联,既继承了传统的父子文档映射关系,又能通过图关系遍历获取更丰富的上下文信息。在具体实现上,采用智能分块策略:短文档保持完整避免破坏语义,长文档优先按`##`标题进行章节分块,必要时才进行长度分块,同时为每个chunk提供丰富的元数据(如chunk_id、chunk_index、total_chunks等),确保后续处理的灵活性和可追溯性。 + diff --git a/docs/chapter9/03_index_construction.md b/docs/chapter9/03_index_construction.md new file mode 100644 index 0000000..bce908b --- /dev/null +++ b/docs/chapter9/03_index_construction.md @@ -0,0 +1,299 @@ +# 第三节 Milvus索引构建 + +在图RAG系统中,索引构建是连接图数据和向量检索的关键环节。本节介绍如何将图数据转换为可检索的向量索引。 + +在第三章中,我们已经详细介绍了Milvus的基本概念、部署方式和基础操作。本节将在此基础上,专门针对图RAG场景进行深度应用。如果你对Milvus还不熟悉,建议先阅读[Milvus介绍及多模态检索实践](https://github.com/datawhalechina/all-in-rag/blob/main/docs/chapter3/09_milvus.md)。 + +> [本节完整代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C9/rag_modules/milvus_index_construction.py) + +## 一、索引构建概述 + +### 1.1 索引构建流程 + +图RAG的索引构建需要将从图数据库构建的结构化文档转换为向量表示,并存储到向量数据库中: + +```mermaid +flowchart LR + A[图数据库] --> B[文档构建] + B --> C[文档分块] + C --> D[向量化] + D --> E[Milvus索引] + + style A fill:#e1f5fe + style E fill:#e8f5e8 +``` + +### 1.2 核心组件 + +- **文档构建器**:从图数据构建结构化文档 +- **分块处理器**:智能分块策略 +- **向量化模型**:文本转向量 +- **Milvus索引**:高性能向量存储和检索 + +## 二、Milvus索引构建实现 + +### 2.1 索引构建器核心架构 + +```python +class MilvusIndexConstructionModule: + """Milvus索引构建模块 - 负责向量化和Milvus索引构建""" + + def __init__(self, + host: str = "localhost", + port: int = 19530, + collection_name: str = "cooking_knowledge", + dimension: int = 512, + model_name: str = "BAAI/bge-small-zh-v1.5"): + self.host = host + self.port = port + self.collection_name = collection_name + self.dimension = dimension + self.model_name = model_name + + self.client = None + self.embeddings = None + self.collection_created = False + + self._setup_client() + self._setup_embeddings() +``` + +**代码解读**: +- **模块化设计**:将Milvus操作封装为独立模块,便于复用和维护 +- **配置灵活性**:支持自定义Milvus连接参数和嵌入模型 +- **中文优化**:默认使用`BAAI/bge-small-zh-v1.5`,专门针对中文文本优化 +- **延迟初始化**:在构造函数中设置连接,避免启动时的阻塞 + +### 2.2 向量化处理 + +```python +def _vectorize_documents(self, documents: List[Document]) -> Tuple[List[List[float]], List[Dict]]: + """文档向量化处理""" + vectors = [] + metadatas = [] + + for i, doc in enumerate(documents): + try: + # 向量化文档内容 + vector = self.embedding_model.embed_query(doc.page_content) + vectors.append(vector) + + # 准备元数据 + metadata = { + "id": i, + "content": doc.page_content, + "source": doc.metadata.get("source", ""), + "chunk_id": doc.metadata.get("chunk_id", ""), + "parent_id": doc.metadata.get("parent_id", ""), + # ... 其他元数据 + } + metadatas.append(metadata) + + except Exception as e: + logger.error(f"文档 {i} 向量化失败: {e}") + continue + + return vectors, metadatas +``` + +### 2.3 图RAG专用集合Schema设计 + +```python +def _create_collection_schema(self): + """创建集合schema""" + fields = [ + FieldSchema(name="id", dtype=DataType.VARCHAR, max_length=150, is_primary=True), + FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=self.dimension), + FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=15000), + FieldSchema(name="node_id", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="recipe_name", dtype=DataType.VARCHAR, max_length=300), + FieldSchema(name="node_type", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=100), + FieldSchema(name="cuisine_type", dtype=DataType.VARCHAR, max_length=200), + FieldSchema(name="difficulty", dtype=DataType.INT64), + FieldSchema(name="doc_type", dtype=DataType.VARCHAR, max_length=50), + FieldSchema(name="chunk_id", dtype=DataType.VARCHAR, max_length=150), + FieldSchema(name="parent_id", dtype=DataType.VARCHAR, max_length=100) + ] + + schema = CollectionSchema( + fields=fields, + description="中式烹饪知识图谱向量集合" + ) + return schema +``` + +**Schema设计亮点**: +- **图数据特化**:专门为烹饪知识图谱设计的字段结构 +- **丰富元数据**:包含菜谱名称、节点类型、菜系、难度等图谱特有信息 +- **长度优化**:根据实际数据特点设置合理的字段长度限制 +- **检索友好**:所有关键字段都可用于过滤和检索条件 + +## 三、索引优化策略 + +### 3.1 批量插入优化 + +```python +def _batch_insert(self, vectors: List[List[float]], metadatas: List[Dict]): + """批量插入优化""" + batch_size = self.config.batch_size + collection_name = self.config.milvus_collection_name + + for i in range(0, len(vectors), batch_size): + batch_vectors = vectors[i:i + batch_size] + batch_metadatas = metadatas[i:i + batch_size] + + # 准备插入数据 + insert_data = [ + [meta["id"] for meta in batch_metadatas], # id + batch_vectors, # vector + [meta["content"] for meta in batch_metadatas], # content + [meta["source"] for meta in batch_metadatas], # source + [meta["chunk_id"] for meta in batch_metadatas], # chunk_id + [meta["parent_id"] for meta in batch_metadatas], # parent_id + ] + + # 执行插入 + self.milvus_client.insert(collection_name, insert_data) + logger.info(f"批次 {i//batch_size + 1} 插入完成,数量: {len(batch_vectors)}") +``` + +### 3.2 索引创建 + +```python +def _create_index(self): + """创建向量索引""" + collection_name = self.config.milvus_collection_name + + # 索引参数 + index_params = { + "metric_type": "COSINE", # 余弦相似度 + "index_type": "IVF_FLAT", # 索引类型 + "params": {"nlist": 1024} # 索引参数 + } + + # 创建索引 + self.milvus_client.create_index( + collection_name=collection_name, + field_name="vector", + index_params=index_params + ) + + # 加载集合到内存 + self.milvus_client.load_collection(collection_name) + + logger.info("向量索引创建完成") +``` + +## 四、索引构建流程 + +### 4.1 核心向量构建流程 + +```python +def build_vector_index(self, chunks: List[Document]) -> bool: + """构建向量索引""" + logger.info(f"正在构建Milvus向量索引,文档数量: {len(chunks)}...") + + try: + # 1. 创建集合(如果schema不兼容则强制重新创建) + if not self.create_collection(force_recreate=True): + return False + + # 2. 准备数据 + logger.info("正在生成向量embeddings...") + texts = [chunk.page_content for chunk in chunks] + vectors = self.embeddings.embed_documents(texts) + + # 3. 准备插入数据 + entities = [] + for i, (chunk, vector) in enumerate(zip(chunks, vectors)): + entity = { + "id": self._safe_truncate(chunk.metadata.get("chunk_id", f"chunk_{i}"), 150), + "vector": vector, + "text": self._safe_truncate(chunk.page_content, 15000), + "node_id": self._safe_truncate(chunk.metadata.get("node_id", ""), 100), + "recipe_name": self._safe_truncate(chunk.metadata.get("recipe_name", ""), 300), + # ... 更多字段 + } + entities.append(entity) + + # 4. 批量插入数据 + batch_size = 100 + for i in range(0, len(entities), batch_size): + batch = entities[i:i + batch_size] + self.client.insert(collection_name=self.collection_name, data=batch) +``` + +**关键技术点解读**: + +1. **强制重建策略**:`force_recreate=True`确保Schema一致性,避免字段不匹配错误 + +2. **批量向量化**:一次性处理所有文档的向量化,提高效率 + ```python + texts = [chunk.page_content for chunk in chunks] + vectors = self.embeddings.embed_documents(texts) # 批量处理 + ``` + +3. **安全截断机制**:`_safe_truncate`方法防止字段长度超限 + ```python + def _safe_truncate(self, text: str, max_length: int) -> str: + if text is None: + return "" + return str(text)[:max_length] + ``` + +4. **图数据元数据保留**:完整保留图谱中的结构化信息,支持后续的复合检索 + +### 4.2 索引验证 + +```python +def verify_index(self) -> bool: + """验证索引构建结果""" + try: + collection_name = self.config.milvus_collection_name + + # 检查集合状态 + collection_info = self.milvus_client.describe_collection(collection_name) + logger.info(f"集合信息: {collection_info}") + + # 检查数据量 + count = self.milvus_client.query( + collection_name=collection_name, + expr="", + output_fields=["count(*)"] + ) + logger.info(f"索引中文档数量: {count}") + + # 简单检索测试 + test_results = self.milvus_client.search( + collection_name=collection_name, + data=[[0.1] * self.config.embedding_dim], # 测试向量 + anns_field="vector", + param={"metric_type": "COSINE", "params": {"nprobe": 10}}, + limit=1 + ) + + logger.info("索引验证通过") + return True + + except Exception as e: + logger.error(f"索引验证失败: {e}") + return False +``` + +## 五、为什么从FAISS切换到Milvus? + +在第八章中,使用的是FAISS作为向量存储方案。虽然FAISS在研究和原型开发中表现出色,但在生产环境和复杂应用场景下,Milvus提供了更多优势: + +**FAISS的局限性**: +- **纯库模式**:FAISS是一个向量搜索库,缺乏数据库的完整功能 +- **无持久化**:需要手动管理数据持久化和备份 +- **单机限制**:难以实现分布式部署和水平扩展 +- **元数据支持有限**:无法高效存储和查询复杂的结构化元数据 +- **并发性能**:在高并发场景下性能受限 + +**Milvus的优势**: +- **完整数据库功能**:提供CRUD操作、事务支持、数据一致性保证 +- **云原生架构**:支持分布式部署、自动扩缩容、高可用性 +- **丰富的元数据支持**:支持复杂Schema设计,适合图RAG的多维度数据 +- **生产级特性**:监控、日志、备份恢复等企业级功能 diff --git a/docs/chapter9/04_intelligent_query_routing.md b/docs/chapter9/04_intelligent_query_routing.md new file mode 100644 index 0000000..87187f5 --- /dev/null +++ b/docs/chapter9/04_intelligent_query_routing.md @@ -0,0 +1,437 @@ +# 第四节 智能查询路由与检索策略 + +> 不同类型的查询需要不同的检索策略。本节将详细介绍如何构建智能查询路由器,实现查询复杂度分析和检索策略的自动选择,以及三种核心检索策略的设计与实现。 + +## 一、智能查询路由器设计 + +### 1.1 查询路由的必要性 + +在图RAG系统中,可以实现更多样化的查询类型: + +**简单查询**: +- "川菜有哪些?" +- "宫保鸡丁怎么做?" +- "减肥菜推荐" + +**复杂推理查询**: +- "适合糖尿病人吃的低糖川菜有哪些,并且制作时间不超过30分钟?" +- "如果我只有鸡肉和蔬菜,能做什么菜,最好是不同菜系的?" +- "哪些菜可以用豆腐替代肉类,并且保持相似的口感?" + +**中等复杂查询**: +- "家常菜中哪些适合新手制作?" +- "有什么菜可以用剩余的土豆和胡萝卜?" + +不同复杂度的查询需要不同的检索策略来获得最佳效果。 + +### 1.2 查询分析框架 + +智能查询路由器通过四个维度分析查询特征: + +```python +class IntelligentQueryRouter: + def __init__(self, traditional_retrieval, graph_rag_retrieval, llm_client, config): + self.traditional_retrieval = traditional_retrieval + self.graph_rag_retrieval = graph_rag_retrieval + self.llm_client = llm_client + self.config = config + + # 路由统计 + self.route_stats = { + "traditional_count": 0, + "graph_rag_count": 0, + "combined_count": 0, + "total_queries": 0 + } + + def analyze_query(self, query: str) -> QueryAnalysis: + """深度分析查询特征,决定最佳检索策略""" + + analysis_prompt = f""" + 作为RAG系统的查询分析专家,请深度分析以下查询的特征: + + 查询:{query} + + 请从以下维度分析: + + 1. 查询复杂度 (0-1): + - 0.0-0.3: 简单信息查找(如:红烧肉怎么做?) + - 0.4-0.7: 中等复杂度(如:川菜有哪些特色菜?) + - 0.8-1.0: 高复杂度推理(如:为什么川菜用花椒而不是胡椒?) + + 2. 关系密集度 (0-1): + - 0.0-0.3: 单一实体信息(如:西红柿的营养价值) + - 0.4-0.7: 实体间关系(如:鸡肉配什么蔬菜?) + - 0.8-1.0: 复杂关系网络(如:川菜的形成与地理、历史的关系) + + 3. 推理需求:是否需要多跳推理、因果分析、对比分析? + 4. 实体识别:查询中包含多少个明确实体? + + 基于分析推荐检索策略: + - hybrid_traditional: 适合简单直接的信息查找 + - graph_rag: 适合复杂关系推理和知识发现 + - combined: 需要两种策略结合 + + 返回JSON格式: + {{ + "query_complexity": 0.6, + "relationship_intensity": 0.8, + "reasoning_required": true, + "entity_count": 3, + "recommended_strategy": "graph_rag", + "confidence": 0.85, + "reasoning": "该查询涉及多个实体间的复杂关系,需要图结构推理" + }} + """ + + try: + response = self.llm_client.chat.completions.create( + model=self.config.llm_model, + messages=[{"role": "user", "content": analysis_prompt}], + temperature=0.1, + max_tokens=800 + ) + + result = json.loads(response.choices[0].message.content.strip()) + + # 构建QueryAnalysis对象 + analysis = QueryAnalysis( + query_complexity=result.get("query_complexity", 0.5), + relationship_intensity=result.get("relationship_intensity", 0.5), + reasoning_required=result.get("reasoning_required", False), + entity_count=result.get("entity_count", 1), + recommended_strategy=SearchStrategy(result.get("recommended_strategy", "hybrid_traditional")), + confidence=result.get("confidence", 0.5), + reasoning=result.get("reasoning", "默认分析") + ) + + return analysis + + except Exception as e: + logger.error(f"查询分析失败: {e}") + # 降级方案:基于规则的简单分析 + return self._rule_based_analysis(query) +``` + +### 1.3 规则基础的降级分析 + +当LLM分析失败时,使用基于规则的降级分析: + +```python +def _rule_based_analysis(self, query: str) -> QueryAnalysis: + """基于规则的降级分析""" + # 简单的规则判断 + complexity_keywords = ["为什么", "如何", "关系", "影响", "原因", "比较", "区别"] + relation_keywords = ["配", "搭配", "组合", "相关", "联系", "连接"] + + complexity = sum(1 for kw in complexity_keywords if kw in query) / len(complexity_keywords) + relation_intensity = sum(1 for kw in relation_keywords if kw in query) / len(relation_keywords) + + # 策略选择 + if complexity > 0.3 or relation_intensity > 0.3: + strategy = SearchStrategy.GRAPH_RAG + else: + strategy = SearchStrategy.HYBRID_TRADITIONAL + + return QueryAnalysis( + query_complexity=complexity, + relationship_intensity=relation_intensity, + reasoning_required=complexity > 0.3, + entity_count=len(query.split()), # 简单估算 + recommended_strategy=strategy, + confidence=0.6, + reasoning="基于规则的简单分析" + ) +``` + +### 1.4 智能路由执行 + +基于分析结果,路由到最适合的检索策略: + +```python +def route_query(self, query: str, top_k: int = 5) -> Tuple[List[Document], QueryAnalysis]: + """智能路由查询到最适合的检索引擎""" + logger.info(f"开始智能路由: {query}") + + # 1. 分析查询特征 + analysis = self.analyze_query(query) + + # 2. 更新统计 + self._update_route_stats(analysis.recommended_strategy) + + # 3. 根据策略执行检索 + try: + if analysis.recommended_strategy == SearchStrategy.HYBRID_TRADITIONAL: + logger.info("使用传统混合检索") + documents = self.traditional_retrieval.hybrid_search(query, top_k) + + elif analysis.recommended_strategy == SearchStrategy.GRAPH_RAG: + logger.info("🕸️ 使用图RAG检索") + documents = self.graph_rag_retrieval.graph_rag_search(query, top_k) + + elif analysis.recommended_strategy == SearchStrategy.COMBINED: + logger.info("🔄 使用组合检索策略") + documents = self._combined_search(query, top_k) + + # 4. 结果后处理 + documents = self._post_process_results(documents, analysis) + + return documents, analysis + + except Exception as e: + logger.error(f"查询路由失败: {e}") + # 降级到传统检索 + documents = self.traditional_retrieval.hybrid_search(query, top_k) + return documents, analysis + +def _combined_search(self, query: str, top_k: int) -> List[Document]: + """组合搜索策略:结合传统检索和图RAG的优势""" + # 分配结果数量 + traditional_k = max(1, top_k // 2) + graph_k = top_k - traditional_k + + # 执行两种检索 + traditional_docs = self.traditional_retrieval.hybrid_search(query, traditional_k) + graph_docs = self.graph_rag_retrieval.graph_rag_search(query, graph_k) + + # 合并和去重(简化实现) + # ... 具体的合并逻辑 + + return combined_docs +``` + +## 二、三种检索策略详解 + +### 2.1 传统混合检索策略 + +> [混合检索模块代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C9/rag_modules/hybrid_retrieval.py) + +适用于简单查询,结合双层检索和向量检索: + +```python +class HybridRetrievalModule: + def hybrid_search(self, query: str, top_k: int = 5) -> List[Document]: + """ + 混合检索:使用Round-robin轮询合并策略 + 公平轮询合并不同检索结果,不使用权重配置 + """ + logger.info(f"开始混合检索: {query}") + + # 1. 双层检索(实体+主题检索) + dual_docs = self.dual_level_retrieval(query, top_k) + + # 2. 增强向量检索 + vector_docs = self.vector_search_enhanced(query, top_k) + + # 3. Round-robin轮询合并 + merged_docs = [] + seen_doc_ids = set() + max_len = max(len(dual_docs), len(vector_docs)) + + # Round-robin策略:交替从两个结果列表中取文档 + # 这种方法确保了不同检索方法的结果都能得到公平的展示机会 + for i in range(max_len): + # 先添加双层检索结果 + if i < len(dual_docs): + doc = dual_docs[i] + doc_id = doc.metadata.get("node_id", hash(doc.page_content)) + if doc_id not in seen_doc_ids: + seen_doc_ids.add(doc_id) + doc.metadata["search_method"] = "dual_level" + doc.metadata["final_score"] = doc.metadata.get("relevance_score", 0.0) + merged_docs.append(doc) + + # 再添加向量检索结果 + if i < len(vector_docs): + doc = vector_docs[i] + doc_id = doc.metadata.get("node_id", hash(doc.page_content)) + if doc_id not in seen_doc_ids: + seen_doc_ids.add(doc_id) + doc.metadata["search_method"] = "vector" + doc.metadata["final_score"] = doc.metadata.get("relevance_score", 0.0) + merged_docs.append(doc) + + return merged_docs[:top_k] +``` + +**Round-robin轮询合并原理**:Round-robin(轮询)是一种公平调度算法,在RAG系统中用于融合多个检索结果。其核心是按顺序轮流从不同的结果列表中选择文档,而不是基于分数权重进行合并。这种方法确保了每种检索策略的结果都能得到公平的展示机会,避免了某种方法因排序靠前而被过度选择的问题。相比复杂的加权融合,Round-robin实现简单且稳定,无需调优权重参数,自然保持了结果的多样性。 + +### 2.2 图RAG检索策略 + +> [图RAG检索模块代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C9/rag_modules/graph_rag_retrieval.py) + +适用于复杂推理查询,基于图结构进行多跳推理: + +```python +class GraphRAGRetrieval: + def graph_rag_search(self, query: str, top_k: int = 5) -> List[Document]: + """ + 图RAG主搜索接口:整合所有图RAG能力 + """ + logger.info(f"开始图RAG检索: {query}") + + # 1. 查询意图理解 + graph_query = self.understand_graph_query(query) + logger.info(f"查询类型: {graph_query.query_type.value}") + + results = [] + + try: + # 2. 根据查询类型执行不同策略 + if graph_query.query_type in [QueryType.MULTI_HOP, QueryType.PATH_FINDING]: + # 多跳遍历 + paths = self.multi_hop_traversal(graph_query) + results.extend(self._paths_to_documents(paths, query)) + + elif graph_query.query_type == QueryType.SUBGRAPH: + # 子图提取 + subgraph = self.extract_knowledge_subgraph(graph_query) + + # 图结构推理 + reasoning_chains = self.graph_structure_reasoning(subgraph, query) + + results.extend(self._subgraph_to_documents(subgraph, reasoning_chains, query)) + + elif graph_query.query_type == QueryType.ENTITY_RELATION: + # 实体关系查询 + paths = self.multi_hop_traversal(graph_query) + results.extend(self._paths_to_documents(paths, query)) + + # 3. 图结构相关性排序 + results = self._rank_by_graph_relevance(results, query) + + return results[:top_k] + + except Exception as e: + logger.error(f"图RAG检索失败: {e}") + return [] +``` + +**图RAG检索流程**: + +```mermaid +flowchart TD + A[用户查询] --> B[查询意图理解] + B --> C{查询类型判断} + + C -->|简单关系| D1[实体关系查询] + C -->|复杂推理| D2[多跳推理查询] + C -->|知识网络| D3[子图提取查询] + + D1 --> E1[直接关系检索] + D2 --> E2[多跳图遍历] + D3 --> E3[知识子图提取] + + E1 --> F[结果转换与排序] + E2 --> F + E3 --> F + + F --> G[返回Top-K结果] + + style A fill:#e1f5fe + style C fill:#fff3e0 + style F fill:#f3e5f5 + style G fill:#e8f5e8 +``` + +**多跳推理**: + +多跳推理是指通过图中的多个节点和关系进行间接推理,这是图RAG相比传统RAG的核心优势。传统检索只能找到直接匹配的信息,而多跳推理能够发现数据中的隐含关联。 + +- **工作原理**: + 1. **路径发现**:在知识图谱中寻找连接起始实体和目标实体的路径 + 2. **关系传递**:通过中间节点传递语义关系 + 3. **隐含推理**:发现原始数据中没有明确表达的知识关联 + +- **具体示例**:用户问"鸡肉配什么蔬菜好?" + + ``` + 传统检索:只能找到直接提到"鸡肉+蔬菜"的文档(可能很少) + + 多跳推理: + 1跳:鸡肉 → 宫保鸡丁、口水鸡、白切鸡... + 2跳:宫保鸡丁 → 胡萝卜、青椒、花生米... + 3跳:胡萝卜 → 蔬菜类别 + + 推理结果:鸡肉经常与胡萝卜、青椒等蔬菜搭配 + ``` + +- **多跳推理的价值**: + - **知识发现**:挖掘数据中的隐含关系 + - **推荐增强**:提供更丰富的搭配建议 + - **语义理解**:模拟人类的联想思维过程 + - **数据利用**:充分利用图结构的关系信息 + +通过这种多跳遍历,系统能发现"鸡肉"和"胡萝卜"之间的隐含关系:它们经常在同一道菜中出现,即使在原始数据中没有直接的"鸡肉-胡萝卜"关系。 + +### 2.3 组合检索策略 + +> [智能查询路由器代码](https://github.com/datawhalechina/all-in-rag/blob/main/code/C9/rag_modules/intelligent_query_router.py) + +适用于中等复杂查询,结合传统检索和图RAG的优势: + +```python +def _combined_search(self, query: str, top_k: int) -> List[Document]: + """组合搜索策略:结合传统检索和图RAG的优势""" + # 分配结果数量 + traditional_k = max(1, top_k // 2) + graph_k = top_k - traditional_k + + # 执行两种检索 + traditional_docs = self.traditional_retrieval.hybrid_search(query, traditional_k) + graph_docs = self.graph_rag_retrieval.graph_rag_search(query, graph_k) + + # Round-robin轮询合并(参考LightRAG的融合策略) + combined_docs = [] + seen_contents = set() + + # 交替添加结果,保持多样性(Round-robin策略) + max_len = max(len(traditional_docs), len(graph_docs)) + for i in range(max_len): + # 添加传统检索结果 + if i < len(traditional_docs): + doc = traditional_docs[i] + if doc.page_content not in seen_contents: + seen_contents.add(doc.page_content) + doc.metadata["search_strategy"] = "traditional" + combined_docs.append(doc) + + # 添加图RAG结果 + if i < len(graph_docs): + doc = graph_docs[i] + if doc.page_content not in seen_contents: + seen_contents.add(doc.page_content) + doc.metadata["search_strategy"] = "graph_rag" + combined_docs.append(doc) + + return combined_docs[:top_k] +``` + +**Round-robin轮询合并机制**:在组合检索中,Round-robin算法按照固定的轮转顺序从传统检索和图RAG检索的结果中交替选择文档。具体过程是:第1个位置选择传统检索的第1个结果,第2个位置选择图RAG的第1个结果,第3个位置选择传统检索的第2个结果,以此类推。这种机制避免了复杂的分数融合计算,通过位置轮转自然实现了不同检索策略结果的均衡分布,是一种简单而有效的多源信息融合方法。 + +## 三、路由决策逻辑 + +智能查询路由器通过分析查询特征,自动选择最适合的检索策略: + +**决策规则**: +- **简单查询**(复杂度 < 0.4)→ 传统混合检索 +- **复杂推理查询**(复杂度 > 0.7 或关系密集度 > 0.7)→ 图RAG检索 +- **中等复杂查询**(0.4 ≤ 复杂度 ≤ 0.7)→ 组合检索策略 + +**路由统计与优化**: + +```python +def _update_route_stats(self, strategy: SearchStrategy): + """更新路由统计信息""" + self.route_stats["total_queries"] += 1 + if strategy == SearchStrategy.HYBRID_TRADITIONAL: + self.route_stats["traditional_count"] += 1 + elif strategy == SearchStrategy.GRAPH_RAG: + self.route_stats["graph_rag_count"] += 1 + elif strategy == SearchStrategy.COMBINED: + self.route_stats["combined_count"] += 1 +``` + +> 最后的生成部分就不过多赘述了,和第八章类似,可以自行查阅代码。本章项目并不完善,仅作为对 GraphRAG 流程和架构的理解。可根据前面所学内容自行优化。 +> +> [What-to-eat-today 给当前项目加个前端并做了点优化,可以参考](https://github.com/FutureUnreal/What-to-eat-today) diff --git a/docs/chapter9/images/9_1_1.svg b/docs/chapter9/images/9_1_1.svg new file mode 100644 index 0000000..df08031 --- /dev/null +++ b/docs/chapter9/images/9_1_1.svg @@ -0,0 +1 @@ +Neo4j Graph VisualizationCreated using Neo4j (http://www.neo4j.com/)SIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMI…SIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMI…SIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARSIMILARREQUIRESREQUIRESCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPDIFFICULTY_LEVELBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TODIFFIC…BELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEBELON…BELON…DIFFICULTY_LEVELBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELON…HAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEBELONGS_TOBELON…HAS_CONCEPT_TYPEBELONGS_TOBELONGS_TO_CATEGORYHAS_CONCEPT_TYPEHAS_CONCEPT_TYPEBELONGS_TO_CATEGORYBELONGS_TOHAS_CONCEPT_TYPEHAS_CONCEPT_TYPENEXT_STEPNEXT_STEPNEXT_S…NEXT_STEPREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPDIFFICULTY_LEVELBELONGS_TOBELONGS…NEXT_STEPNEXT_STEPNEXT_STEPDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LE…DIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELBELONGS_TOBELONGS_TO_CATEGORYBELONGS…BELONG…BELONGS_TO_CATEG…BELONGS_T…BELONGS_TO_CATEGORYBELONGS_TO_CATEGORYBELONGS_TO_CATEGORYBELONGS_TO_CATEGORYBELONGS_TO_CATEGORYBELONGS_TO_CATEGORYBELONGS_TO_CATEGORYBELONGS_TO_CATEGORYBELON…BELON…BELONGS_TO_CATEGORYREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESREQUIRESCONTAINS_STEPCONTAINS_STEPCONTAI…CONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPDIFFICULTY_LEVELBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYBELON…DIFFIC…BELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYBELONGS_TODIFFICULTY_LEVELBELO…BELON…BELON…BELONGS_TOBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TODIFFICULTY_LEVELBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYBELONGS_TOBELONGS_TO_CATEGORYNEXT_STEPNEXT_STEPNEXT_STEPNEXT_STEPNEXT_…NEXT_STEPNEXT_STEPNEXT_STEPNEXT_STEPNEXT_STEPNEXT_STEPNEXT_STEPNEXT_STEPNEXT_…REQUIRESREQUIRESCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPCONTAINS_STEPDIFFICULTY_LEVELNEXT_STEPNEXT_STEPNEXT_STEPNEXT_STEPDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVELDIFFICULTY_LEVEL 菜谱 咖喱炒蟹 微波葱… 水煮鱼 清蒸生蚝 红烧鱼 红烧鱼头 红烧鲤鱼 小龙虾 干煎阿… 油焖大虾 烤鱼 清蒸鲈鱼 白灼虾 糖醋鲤鱼 芥末黄… 葱油桂鱼 葱烧海参 蒜蓉虾 蒜香黄… 蛏抱蛋 香煎翘… 鲤鱼炖… 鳊鱼炖… 黄油煎虾 吐司果酱 太阳蛋 完美水… 微波炉… 微波炉… 手抓饼 桂圆红… 水煮玉米 溏心蛋 煎饺 燕麦鸡… 牛奶燕麦 空气炸… 美式炒蛋 茶叶蛋 蒸水蛋 蒸花卷 蛋煎糍粑 金枪鱼… 鸡蛋三… 温泉蛋 苏格兰蛋 油酥 炸串酱料 吐司 果酱 一星 早餐 早餐 Recipe 干辣椒面 孜然粉 胡椒粉 五香粉 食盐 花椒粉 鸡精 十三香 麻辣鲜 白芝麻 香油 生抽 花椒油 蚝油 二星 调料 调料 鲤鱼 番茄酱 白糖 白醋 淀粉 大葱 料酒 香菜 面粉 鸡蛋 清水 四星 水产 水产 鸡蛋 三星 步骤1 步骤2 步骤2 步骤2 步骤7 步骤3 步骤5 步骤6 步骤4 步骤5 步骤4 步骤11 步骤8 步骤4 步骤1 步骤5 步骤1 步骤14 步骤3 步骤12 步骤3 步骤9 步骤1 步骤4 步骤13 步骤10 步骤3 步骤15 步骤2 \ No newline at end of file diff --git a/docs/emoji.png b/docs/emoji.png new file mode 100644 index 0000000..48665be Binary files /dev/null and b/docs/emoji.png differ diff --git a/docs/en/README.md b/docs/en/README.md new file mode 100644 index 0000000..c51f1cc --- /dev/null +++ b/docs/en/README.md @@ -0,0 +1,189 @@ +# All-in-RAG | Large Model Application Development Practice: RAG Technology Full-Stack Guide + +
+ All-in-RAG Logo +
+ +## Project Introduction [![Stars](https://img.shields.io/github/stars/datawhalechina/all-in-rag?style=social)](https://github.com/datawhalechina/all-in-rag/stargazers) ![GitHub forks](https://img.shields.io/github/forks/datawhalechina/all-in-rag) [![Python](https://img.shields.io/badge/Python-3.12.7-blue)](https://www.python.org/) [![Online Reading](https://img.shields.io/badge/Online%20Reading-Click%20Here-blue)](https://datawhalechina.github.io/) + +[中文](/) | English + +This project is a comprehensive RAG (Retrieval-Augmented Generation) technology full-stack tutorial for large model application developers. It aims to help developers master RAG application development skills based on large language models through systematic learning paths and hands-on practice projects, building production-grade intelligent Q&A and knowledge retrieval systems. + +**Main content includes:** + +1. **RAG Technology Fundamentals**: In-depth introduction to RAG core concepts, technical principles, and application scenarios +2. **Complete Data Processing Pipeline**: From data loading, cleaning to text chunking - the complete data preparation process +3. **Index Construction and Optimization**: Vector embedding, multimodal embedding, vector database construction and index optimization techniques +4. **Advanced Retrieval Techniques**: Hybrid retrieval, query construction, Text2SQL and other advanced retrieval technologies +5. **Generation Integration and Evaluation**: Formatted generation, system evaluation and optimization methods +6. **Project Practice**: Complete RAG application development practice from basic to advanced + +## Project Significance + +With the rapid development of large language models, RAG technology has become the core technology for building intelligent Q&A systems and knowledge retrieval applications. However, existing RAG tutorials are often scattered and lack systematicity, making it difficult for beginners to form a complete understanding of the technical system. + +Starting from practice and combining the latest RAG technology development trends, this project builds a complete RAG learning system to help developers: +- Systematically master the theoretical foundation and practical skills of RAG technology +- Understand the complete architecture of RAG systems and the role of each component +- Develop the ability to independently develop RAG applications +- Master evaluation and optimization methods for RAG systems + +## Target Audience + +**This project is suitable for the following groups:** +- Developers with Python programming foundation who are interested in RAG technology +- AI engineers who want to systematically learn RAG technology +- Product developers who want to build intelligent Q&A systems +- Researchers with learning needs for retrieval-augmented generation technology + +**Prerequisites:** +- Master Python basic syntax and usage of common libraries +- Ability to use Docker simply +- Understanding of basic LLM concepts (recommended but not required) +- Basic Linux command line operation skills + +## Project Highlights + +1. **Systematic Learning Path**: From basic concepts to advanced applications, building a complete RAG technology learning system +2. **Theory and Practice Combined**: Each chapter includes theoretical explanation and code practice to ensure learning and application +3. **Multimodal Support**: Covers not only text RAG, but also multimodal embedding and retrieval technologies +4. **Engineering-Oriented**: Focus on engineering problems in practical applications, including performance optimization, system evaluation, etc. +5. **Rich Practical Projects**: Provides multiple practical projects from basic to advanced to help consolidate learning outcomes + +## Content Outline + +### Part I: RAG Fundamentals + +**Chapter 1 Unlocking RAG** [📖 View Chapter](en/chapter1) +1. [x] [RAG Introduction](en/chapter1/01_RAG_intro.md) - RAG technology overview and application scenarios +2. [x] [Preparation](en/chapter1/02_preparation.md) - Environment configuration and tool preparation +3. [x] [Four Steps to Build RAG](en/chapter1/03_get_start_rag.md) - Quick start with RAG development + +**Chapter 2 Data Preparation** [📖 View Chapter](en/chapter2) +1. [x] [Data Loading](en/chapter2/04_data_load.md) - Multi-format document processing and loading +2. [x] [Text Chunking](en/chapter2/05_text_chunking.md) - Text segmentation strategies and optimization + +### Part II: Index Construction and Optimization + +**Chapter 3 Index Construction** [📖 View Chapter](en/chapter3) +1. [x] [Vector Embedding](en/chapter3/06_vector_embedding.md) - Detailed explanation of text vectorization technology +2. [x] [Multimodal Embedding](en/chapter3/07_multimodal_embedding.md) - Image-text multimodal vectorization +3. [x] [Vector Database](en/chapter3/08_vector_db.md) - Vector storage and retrieval systems +4. [x] [Milvus Practice](en/chapter3/09_milvus.md) - Milvus multimodal retrieval practice +5. [x] [Index Optimization](en/chapter3/10_index_optimization.md) - Index performance tuning techniques + +### Part III: Advanced Retrieval Techniques + +**Chapter 4 Retrieval Optimization** [📖 View Chapter](en/chapter4) +1. [x] [Hybrid Search](en/chapter4/11_hybrid_search.md) - Dense + sparse retrieval fusion +2. [x] [Query Construction](en/chapter4/12_query_construction.md) - Intelligent query understanding and construction +3. [x] [Text2SQL](en/chapter4/13_text2sql.md) - Natural language to SQL query +4. [x] [Query Rewriting and Routing](en/chapter4/14_query_rewriting.md) - Query optimization strategies +5. [x] [Advanced Retrieval Techniques](en/chapter4/15_advanced_retrieval_techniques.md) - Advanced retrieval algorithms + +### Part IV: Generation and Evaluation + +**Chapter 5 Generation Integration** [📖 View Chapter](en/chapter5) +1. [x] [Formatted Generation](en/chapter5/16_formatted_generation.md) - Structured output and format control + +**Chapter 6 RAG System Evaluation** [📖 View Chapter](en/chapter6) +1. [x] [Evaluation Introduction](en/chapter6/18_system_evaluation.md) - RAG system evaluation methodology +2. [x] [Evaluation Tools](en/chapter6/19_common_tools.md) - Common evaluation tools and metrics + +### Part V: Advanced Applications and Practice + +**Chapter 7 Advanced RAG Architecture (Extended Elective)** [📖 View Chapter](en/chapter7) + +1. [x] [Knowledge Graph-based RAG](en/chapter7/20_kg_rag.md) + +**Chapter 8 Project Practice I (Basic)** [📖 View Chapter](en/chapter8) +1. [x] [Environment Configuration and Project Architecture](en/chapter8/01_env_architecture.md) +2. [x] [Data Preparation Module Implementation](en/chapter8/02_data_preparation.md) +3. [x] [Index Construction and Retrieval Optimization](en/chapter8/03_index_retrieval.md) +4. [x] [Generation Integration and System Integration](en/chapter8/04_generation_sys.md) + +**Chapter 9 Project Practice I Optimization (Elective)** [📖 View Chapter](en/chapter9) + +[🍽️ Project Demo](https://github.com/FutureUnreal/What-to-eat-today) +1. [x] [Graph RAG Architecture Design](en/chapter9/01_graph_rag_architecture.md) +2. [x] [Graph Data Modeling and Preparation](en/chapter9/02_graph_data_modeling.md) +3. [x] [Milvus Index Construction](en/chapter9/03_index_construction.md) +4. [x] [Intelligent Query Routing and Retrieval Strategy](en/chapter9/04_intelligent_query_routing.md) + +**Chapter 10 Project Practice II (Elective)** [📖 View Chapter](en/chapter10) *In Planning* + +## Directory Structure + +``` +all-in-rag/ +├── docs/ # Tutorial documentation +├── code/ # Code examples +├── data/ # Sample data +├── models/ # Pre-trained models +└── README.md # Project description +``` + +## Practical Project Showcase + +### Chapter 8 Project I: + +![Project I](../project01.png) + +### Chapter 9 Project I (Graph RAG Optimization): + +![Project I (Graph RAG Optimization)](../project01_graph.png) + +### Chapter 10 Project II: + +## Acknowledgments + +**Core Contributors** +- [Yin Dalv - Project Lead](https://github.com/FutureUnreal) (Project initiator and main contributor) + +### Special Thanks +- Thanks to [@Sm1les](https://github.com/Sm1les) for help and support on this project +- Thanks to all developers who contributed to this project +- Thanks to the open source community for providing excellent tools and framework support +- Special thanks to the following developers who contributed to the tutorial! + +[![Contributors](https://contrib.rocks/image?repo=datawhalechina/all-in-rag)](https://github.com/datawhalechina/all-in-rag/graphs/contributors) + +*Made with [contrib.rocks](https://contrib.rocks).* + +## Contributing + +We welcome all forms of contributions, including but not limited to: + +- 🚨 **Bug Reports**: Please submit [Issues](https://github.com/datawhalechina/all-in-rag/issues) if you find problems +- 💭 **Feature Suggestions**: Welcome to discuss good ideas in [Discussions](https://github.com/datawhalechina/all-in-rag/discussions) +- 📚 **Documentation Improvement**: Help improve documentation content and example code +- ⚡ **Code Contributions**: Submit [Pull Requests](https://github.com/datawhalechina/all-in-rag/pulls) to improve the project + +## Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=datawhalechina/all-in-rag&type=Date)](https://star-history.com/#datawhalechina/all-in-rag&Date) + +
+

If this project helps you, please give us a ⭐️

+

Let more people discover this project (Food protection? Bring it on!)

+
+ +![star](../emoji.png) + +## About Datawhale + +
+ Datawhale +

Scan the QR code to follow Datawhale WeChat Official Account for more quality open source content

+
+ +--- + +## License + +Creative Commons License + +This work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/). + +--- diff --git a/docs/en/_sidebar.md b/docs/en/_sidebar.md new file mode 100644 index 0000000..8a48a77 --- /dev/null +++ b/docs/en/_sidebar.md @@ -0,0 +1,39 @@ +- Table of Contents + - Chapter 1: Unlocking RAG + - [Section 1: RAG Introduction](en/chapter1/01_RAG_intro.md) + - [Section 2: Preparation](en/chapter1/02_preparation.md) + - [Section 3: Four Steps to Build RAG](en/chapter1/03_get_start_rag.md) + - [Appendix: Python Virtual Environment Deployment](en/chapter1/04_virtualenv.md) + - Chapter 2: Data Preparation + - [Section 1: Data Loading](en/chapter2/04_data_load.md) + - [Section 2: Text Chunking](en/chapter2/05_text_chunking.md) + - Chapter 3: Index Construction + - [Section 1: Vector Embedding](en/chapter3/06_vector_embedding.md) + - [Section 2: Multimodal Embedding](en/chapter3/07_multimodal_embedding.md) + - [Section 3: Vector Database](en/chapter3/08_vector_db.md) + - [Section 4: Milvus Practice](en/chapter3/09_milvus.md) + - [Section 5: Index Optimization](en/chapter3/10_index_optimization.md) + - Chapter 4: Retrieval Optimization + - [Section 1: Hybrid Search](en/chapter4/11_hybrid_search.md) + - [Section 2: Query Construction](en/chapter4/12_query_construction.md) + - [Section 3: Text2SQL](en/chapter4/13_text2sql.md) + - [Section 4: Query Rewriting and Routing](en/chapter4/14_query_rewriting.md) + - [Section 5: Advanced Retrieval Techniques](en/chapter4/15_advanced_retrieval_techniques.md) + - Chapter 5: Generation Integration + - [Section 1: Formatted Generation](en/chapter5/16_formatted_generation.md) + - Chapter 6: RAG System Evaluation + - [Section 1: Evaluation Introduction](en/chapter6/18_system_evaluation.md) + - [Section 2: Evaluation Tools](en/chapter6/19_common_tools.md) + - Chapter 7: Advanced RAG Architecture (Extended Elective) + - [Section 1: Knowledge Graph-based RAG](en/chapter7/20_kg_rag.md) + - Chapter 8: Practical Project I (Basic) + - [Environment Configuration and Project Architecture](en/chapter8/01_env_architecture.md) + - [Data Preparation Module Implementation](en/chapter8/02_data_preparation.md) + - [Index Construction and Retrieval Optimization](en/chapter8/03_index_retrieval.md) + - [Generation Integration and System Integration](en/chapter8/04_generation_sys.md) + - Chapter 9: Practical Project I Optimization (Elective) + - [Graph RAG Architecture Design](en/chapter9/01_graph_rag_architecture.md) + - [Graph Data Modeling and Preparation](en/chapter9/02_graph_data_modeling.md) + - [Milvus Index Construction](en/chapter9/03_index_construction.md) + - [Intelligent Query Routing and Retrieval Strategies](en/chapter9/04_intelligent_query_routing.md) + - Chapter 10: Practical Project II (Elective) diff --git a/docs/en/chapter1/01_RAG_intro.md b/docs/en/chapter1/01_RAG_intro.md new file mode 100644 index 0000000..3fbd2b6 --- /dev/null +++ b/docs/en/chapter1/01_RAG_intro.md @@ -0,0 +1,170 @@ +# Chapter 1: Introduction to RAG + +## 1. What is RAG? + +### 1.1 Core Definition + +In essence, RAG (Retrieval-Augmented Generation) is a technical paradigm designed to solve the problem of large language models (LLMs) "knowing things without knowing why." Its core idea is to combine the **"Parametric Knowledge"** learned internally by the model (i.e., the solidified, fuzzy "memory" in its weights) with **"Non-parametric Knowledge"** from external knowledge bases (i.e., precise, externally updatable data). + +In plain terms, its operational logic is to dynamically retrieve relevant information from an external knowledge base before the LLM generates text, and integrate these "reference materials" into the generation process, thereby improving the output's accuracy and timeliness [^1] [^2] [^3]. + +> 💡 **In one sentence**: RAG teaches an LLM to perform an "open-book exam," allowing it to use both what it has learned and what it can look up. + +### 1.2 Technical Principles + +So, how does a RAG system achieve this combination of "parametric" and "non-parametric" knowledge? As shown in Figure 1-1, its core architecture accomplishes this process through two main phases: + +1. **Retrieval Phase: Finding "Non-parametric Knowledge"** + - **Knowledge Vectorization**: The **Embedding Model** acts as a "connector." It first encodes the external knowledge base into a vector index and stores it in a **Vector Database**. + - **Semantic Recall**: When a user makes a query, the retrieval module uses the same embedding model to vectorize the question and, through **Similarity Search**, precisely locates and recalls the most relevant document chunks from the vast data. + +2. **Generation Phase: Fusing the Two Types of Knowledge** + - **Context Integration**: The generation module receives the relevant document chunks from the retrieval phase and the user's original query. + - **Instructed Generation**: This module follows a preset **Prompt** to effectively integrate the context with the query and guides an LLM (like DeepSeek) to perform controlled, well-reasoned text generation. + +
+ RAG Two-Stage Architecture Diagram +

Figure 1-1 RAG Two-Stage Architecture Diagram

+
+ +### 1.3 Technical Evolution Classification + +The technical architecture of RAG has evolved from simple to complex, which can be broadly divided into three stages as shown in Figure 1-2 [^4]. + +
+ RAG Technical Evolution Classification +

Figure 1-2 RAG Technical Evolution Classification

+
+ +| | **Naive RAG** | **Advanced RAG** | **Modular RAG** | +|:---:|:---:|:---:|:---:| +| **Flow** | **Offline:** `Index`
**Online:** `Retrieve → Generate` | **Offline:** `Index`
**Online:** `...→ Pre-retrieve → ... → Post-retrieve → ...` | "LEGO-like" orchestrable flow | +| **Core Feature** | Basic linear flow | Adds optimization steps **before/after retrieval** | Modular, composable, dynamically adjustable | +| **Key Tech** | Basic vector retrieval | **Query Rewrite**
**Rerank** | **Routing**
**Query Transformation**
**Fusion** | +| **Limitations**| Unstable performance, hard to optimize | Relatively fixed flow, limited optimization points | High system complexity | + +> "Offline" refers to pre-processing work done in advance (like index construction); "Online" refers to the real-time processing flow after a user request. + +## 2. Why Use RAG? + +### 2.1 Technical Selection: RAG vs. Fine-tuning + +When choosing a technical path, a key consideration is the balance between cost and benefit. Typically, we should prioritize the solution with the least modification to the model and the lowest cost, so the technical selection path often follows this order: + +**Prompt Engineering -> Retrieval-Augmented Generation -> Fine-tuning**. + +We can understand the differences between these techniques from two dimensions. As shown in Figure 1-3, the **horizontal axis represents "LLM Optimization"**—the degree to which the model itself is modified. From left to right, the level of optimization deepens; Prompt Engineering and RAG do not change model weights at all, while Fine-tuning directly modifies model parameters. The **vertical axis represents "Context Optimization"**—the degree to which the information provided to the model is enhanced. From bottom to top, the level of enhancement increases; Prompt Engineering only optimizes the way questions are asked, while RAG vastly enriches the context by introducing an external knowledge base. + +
+ Technical Selection Path +

Figure 1-3 RAG, Fine-tuning, and Prompt Engineering Technical Selection Path

+
+ +Based on this framework, our selection path becomes clear: +- **First, try Prompt Engineering**: Guide the model by carefully designing prompts, suitable for simple tasks where the model already has relevant knowledge. +- **Then, choose RAG**: If the model cannot answer due to a lack of specific or real-time knowledge, use RAG to provide contextual information through an external knowledge base. +- **Finally, consider Fine-tuning**: When the goal is to change "how" the model does something (behavior/style/format) rather than "what" it knows (knowledge), Fine-tuning is the ultimate and most appropriate choice. For example, teaching the model to strictly follow a unique output format, mimic a specific character's dialogue style, or "distill" extremely complex instructions into the model weights. + +RAG bridges the gap between general-purpose models and specialized domains, and it is particularly effective at addressing the following core limitations of LLMs: + +| Problem | RAG Solution | +|---------------------|----------------------------------| +| **Static Knowledge Limitation** | Real-time retrieval from external knowledge bases, supporting dynamic updates | +| **Hallucination** | Generation based on retrieved content, reducing error rates | +| **Lack of Domain Expertise** | Introduction of domain-specific knowledge bases (e.g., medical/legal) | +| **Data Privacy Risks** | Local deployment of knowledge bases, avoiding sensitive data leakage | + +### 2.2 Key Advantages + +**1. Dual Improvement in Accuracy and Trustworthiness** + +The core value of RAG lies in breaking through the limitations of the model's pre-trained knowledge. It not only **fills knowledge gaps in specialized domains** but also effectively **suppresses the "hallucination" phenomenon** by providing concrete reference materials. Research also shows that RAG-generated content is significantly superior in **Specificity** and **Diversity** compared to pure LLMs. More importantly, RAG provides **traceability**—every answer can be traced back to its original source document, which greatly enhances the credibility of the content in serious contexts like law and medicine. + +**2. Timeliness Guarantee** + +In terms of knowledge updates, RAG solves the inherent **knowledge cutoff problem** of LLMs (i.e., the model is unaware of events after its training date). RAG allows the knowledge base to be **dynamically updated** independently of the model. This capability is referred to in papers as **"Index Hot-swapping"**—like swapping a memory card in a robot, it instantly switches the world knowledge base without retraining the model, enabling real-time knowledge. + +**3. Significant Overall Cost-Effectiveness** + +From an economic perspective, RAG is a highly cost-effective solution. First, it **avoids the huge computational costs of frequent fine-tuning**. Second, with the powerful assistance of external knowledge, we can often use **smaller base models** to achieve similar results on specific domain problems, directly reducing inference costs. This architecture also reduces the resources needed to forcibly "stuff" massive amounts of knowledge into model weights. + +**4. Flexible and Modular Scalability** + +The RAG architecture is highly inclusive, supporting **multi-source integration** from data like PDFs, Word documents, or web pages into a unified knowledge base. At the same time, its **modular design** decouples retrieval and generation, meaning we can independently optimize the retrieval component (e.g., by swapping in a better embedding model) without affecting the stability of the generation component, facilitating long-term system iteration. + +### 2.3 Risk-Graded Application Scenarios + +> The following shows the applicability of RAG technology in scenarios with different risk levels + +| Risk Level | Examples | RAG Applicability | +|:--------:|:------------------------------|:--------------------------:| +| **Low Risk** | Translation/Grammar checking | High reliability | +| **Medium Risk** | Contract drafting/Legal consultation | Requires human review | +| **High Risk** | Evidence analysis/Visa decisions | Requires strict quality control mechanisms | + +## 3. How to Get Started with RAG? + +### 3.1 Basic Toolchain Selection + +Building a RAG system typically involves selecting key components. For the **development mode**, you can use established frameworks like **LangChain** or **LlamaIndex** for rapid integration, **or you can opt for native development without a framework** to gain finer control over the system flow (which is not difficult with AI programming assistance). For the **memory carrier** (vector database), choices range from solutions suitable for large-scale data like **Milvus** and **Pinecone** to lightweight or local options like **FAISS** and **Chroma**, depending on the specific business scale. Finally, to quantify performance, you can also introduce automated **evaluation tools** like **RAGAS** or **TruLens**. + +### 3.2 Four Steps to Build a Minimum Viable Product (MVP) + +1. **Data Preparation and Cleaning** + This is the foundation of the system. You need to standardize heterogeneous data from sources like PDFs and Word documents and adopt a reasonable **chunking strategy** (e.g., splitting by semantic paragraphs rather than fixed character counts) to avoid information fragmentation. + +2. **Index Construction** + Convert the chunked text into vectors using an **embedding model** and store them in the database. It is helpful at this stage to associate **metadata** (like source and page number), which is crucial for precise citations later. + +3. **Retrieval Strategy Optimization** + Do not rely on a single vector search. Consider using **hybrid retrieval** (vector + keyword) to improve recall, and introduce a **reranking** model to further refine the search results, ensuring the LLM receives high-quality context. + +4. **Generation and Prompt Engineering** + Finally, design a clear **Prompt template** to guide the LLM to answer user questions based on the retrieved context, and explicitly require the model to state "I don't know" when it is unsure, to prevent hallucinations. + +### 3.3 Beginner-Friendly Solutions + +If you want to quickly validate ideas rather than dive deep into code, you can try visual knowledge base platforms like **FastGPT** or **Dify**, which encapsulate complex RAG workflows and allow you to get started just by uploading documents. For developers, using open-source templates like **LangChain4j Easy RAG** or **TinyRAG** [^5] on GitHub is also a highly efficient starting point. + +### 3.4 Advanced Topics and Challenges + +Once a basic RAG system is built, the next step is to focus on how to evaluate, diagnose, and overcome its inherent bottlenecks. + +**1. Evaluation Dimensions & Challenges** + +The quality of a RAG system cannot be judged by feeling alone. The industry typically uses several dimensions for quantitative evaluation: first is **retrieval relevance** (does the retrieved content contain the answer?), followed by **generation quality**, which can be subdivided into **semantic faithfulness** (is the meaning of the answer correct?) and **lexical appropriateness** (are technical terms used correctly?). + +These evaluation dimensions also directly correspond to the main challenges RAG currently faces. For example, the **retrieval dependency** problem—if the retrieval system recalls incorrect information, even the most powerful LLM will confidently spout nonsense. Additionally, current RAG architectures generally struggle with **multi-hop reasoning** problems that require synthesizing information across multiple documents. + +**2. Optimization Directions & Architectural Evolution** + +In response to these challenges, the community has explored various optimization paths. At the **performance level**, efficiency and capabilities can be enhanced through **layered indexing** (enabling caching for high-frequency data) and **multimodal extension** (supporting image/table retrieval). At the **architecture level**, simple linear flows are being replaced by more complex **design patterns**. For example, a system can use a **branching pattern** to handle multi-route retrieval in parallel or a **looping pattern** for self-correction. These flexible architectures are the path toward more intelligent RAG systems. + +## 4. Is RAG Dead? + +With the rise of long context window capabilities in large models, a voice has emerged in the community: "RAG is dead." The core arguments come from two aspects: first, that long context can already "digest" massive texts by brute force, making complex retrieval systems unnecessary; second, a criticism that the term RAG itself is too broad, blurring too many technical details and thus hindering clear understanding and optimization. + +These views, however, overlook a common pattern in the evolution of technical concepts. Just as we could easily coin a more precise, impressive name for a modern, complex RAG system—like the **"Large Language Model Knowledge Management Expert System" (LKE)**. It has already far surpassed the simple "retrieve-augment-generate" scope. But this "renaming game" merely illustrates the superficiality of the "RAG is dead" argument—it is tantamount to putting old wine in a new bottle. + +> The author does not intend to create a new term here, but why call it LKE? It represents three core elements: +> - **L (Large Language Model)**: Emphasizes that the system's driving force is the large language model. +> - **K (Knowledge Management)**: Signifies that the system acts like a knowledge administrator, precisely **finding** (retrieving) the knowledge we need to assist us in higher-level applications using the large model. +> - **E (Expert)**: Implies that the system can act like an expert, accurately providing answers (generation) and solving problems through a series of steps like routing, analysis, fusion, and correction. + +A more fitting analogy is the **Transformer**. Today, whether it's the Decoder-only architecture represented by GPT or the Encoder-only of BERT, we are accustomed to calling them "based on the Transformer architecture," despite their vast differences from the original paper's complete form. The Transformer label captured the core leap of a technical paradigm and became a cultural symbol of an era. By the same token, **the core of RAG lies in "combining the LLM's internal parametric knowledge with external non-parametric knowledge."** As long as this idea holds, no matter how many modules we add—query transformation, multi-route retrieval, or self-correction—it is still an evolution within this framework. + +Therefore, "RAG is dead" is a false proposition. On the contrary, **RAG as a concept is very much alive**; like the Transformer, it is becoming a foundational architectural paradigm that continuously absorbs new technologies and evolves. Its vitality lies precisely in its "unrecognizability" and "all-encompassing" nature. And **the goal of this tutorial is to draw a clear map of this RAG landscape. When we can deconstruct its every module and understand its every possibility, the debate over whether "RAG is dead" resolves itself.** + +> RAG technology is still rapidly developing, so keep following the latest advances in academia and industry! + +## References + +[^1]: [Genesis, J. (2025). *Retrieval-Augmented Text Generation: Methods, Challenges, and Applications*](https://www.researchgate.net/publication/391141346_Retrieval-Augmented_Generation_Methods_Applications_and_Challenges). + +[^2]: [Gao et al. (2023). *Retrieval-Augmented Generation for Large Language Models: A Survey*](https://arxiv.org/abs/2312.10997). + +[^3]: [Lewis et al. (2020). *Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks*](https://arxiv.org/abs/2005.11401). + +[^4]: [Gao et al. (2024). *Modular RAG: Transforming RAG Systems into LEGO-like Reconfigurable Frameworks*](https://arxiv.org/abs/2407.21059). + +[^5]: [*TinyRAG: GitHub Project*](https://github.com/KMnO4-zx/TinyRAG). \ No newline at end of file diff --git a/docs/en/chapter1/02_preparation.md b/docs/en/chapter1/02_preparation.md new file mode 100644 index 0000000..292fa86 --- /dev/null +++ b/docs/en/chapter1/02_preparation.md @@ -0,0 +1,421 @@ +# Chapter 2: Preparation + +> This section primarily recommends two browser-based integrated development environments for environment configuration. Whether you're using a phone, tablet, or computer, you can log in and run code anytime. Although the experience on phones and tablets might not be ideal, they are still usable. + +## 1. Deepseek API Configuration (You can also choose other LLM APIs) + +### 1.1 API Application + +To use the large language model services provided by Deepseek, you first need an API Key. Here are the application steps: + +1. **Visit Deepseek Open Platform** + Open your browser and visit [Deepseek Open Platform](https://platform.deepseek.com/). + + ![Deepseek Platform Homepage](../images/1_2_1.webp) + +2. **Login or Register Account** + If you already have an account, please log in directly. If not, click the register button on the page and complete registration using your email or phone number. + +3. **Create New API Key** + After successful login, find and click `API Keys` in the left navigation bar. On the API management page, click the `Create API key` button. Enter a name that doesn't duplicate other API keys and click create. + + ![Create New Key Button](../images/1_2_2.webp) + +4. **Save API Key** + The system will generate a new API key for you. Please **copy immediately** and save it in a secure place. + + > Note: For security reasons, this key will only be displayed in full once. You won't be able to see it again after closing the popup. + + ![Copy and Save Key](../images/1_2_3.webp) + +## 2. GitHub Codespaces Environment Configuration (Recommended) + +> First, ensure you have a network environment that can smoothly access GitHub. If you cannot access it smoothly, please use Cloud Studio below. + +GitHub Codespaces is a service provided by GitHub that allows developers to create, edit, and run code in the cloud. It provides a pre-configured development environment including code editor, terminal, debugging tools, etc., which can be used directly in the browser. + +### 2.1 Creating Codespaces + +1. **Visit Project Address** + + Open your browser and visit [all-in-rag](https://github.com/datawhalechina/all-in-rag) + +2. **Create New Fork** + In the upper right corner of the project page, click the `Fork` button to create a new fork. Wait a moment for successful creation. + + ![Create New Fork 1](../images/1_2_4.webp) + + ![Create New Fork 2](../images/1_2_5.webp) + +3. **Create Codespaces** + In the upper right corner of the project page, click the `Code` button, then select the `Codespaces` tab. Click the `New codespace` button and wait for the new Codespaces environment to be created successfully. + + ![Create Codespaces](../images/1_2_6.webp) + +4. **Re-enter Codespaces** + After closing the webpage, find the newly created repository and click the content in the red box to re-enter the codespace environment. + + ![Re-enter Codespaces](../images/1_2_7.webp) + +5. **Quota Settings** + Find the codespace settings in GitHub's account settings. It's recommended to adjust the suspend time according to your situation (too long will waste quota, free accounts provide 120 hours of single-core quota). + + ![Quota Settings](../images/1_2_8.webp) + +### 2.2 Python Environment Configuration + +After entering the IDE, first select the terminal below. + +![Enter Terminal](../images/1_2_9.webp) + +1. **Update System Packages** + + Enter the following command in the terminal: + + ```bash + sudo apt update + sudo apt upgrade -y + ``` + +2. **Install Miniconda** + + ```bash + wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh + bash ~/miniconda.sh + ``` + + - Press Enter to read the license agreement + - Enter `yes` to agree to the agreement + - Press Enter directly when prompted for installation path (use default path /home/ubuntu/miniconda3) + - Whether to initialize Miniconda: Enter `yes` to add Miniconda to your PATH environment variable. + + ```bash + source ~/.bashrc + conda --version + ``` + + If the version number is displayed, the installation is successful. + +### 2.3 API Configuration + +1. Use the `vim` editor to open your shell configuration file. + + ```bash + vim ~/.bashrc + ``` + +2. Enter `i` to enter edit mode, add the following line at the end of the file, replacing `[Your Deepseek API Key]` with your own key: + + ```bash + export DEEPSEEK_API_KEY=[Your Deepseek API Key] + ``` + +3. Save and exit. In vim, press Esc to enter command mode, then type `:wq` and press Enter to save the file and exit. + +4. Make configuration effective. Execute the following command to immediately load the updated configuration and make the environment variable effective: + + ```bash + source ~/.bashrc + ``` + +### 2.4 Create and Activate Virtual Environment + +1. **Create Virtual Environment** + + ```bash + conda create --name all-in-rag python=3.12.7 + ``` + + Press Enter directly when options appear. + +2. **Activate Virtual Environment** + + Use the following command to activate the virtual environment: + + ```bash + conda activate all-in-rag + ``` + +3. **Dependency Installation** + If you strictly follow the above process, you should currently be in the project root directory. Enter the code directory to install dependency libraries. + + ```bash + cd code + pip install -r requirements.txt + ``` + + > If there are version errors about grpcio, you can ignore them. + +## 3. Cloud Studio Environment Configuration (Recommended for Domestic Environment) + +Cloud Studio is a browser-based integrated development environment (IDE) launched by Tencent Cloud. It supports access to both CPU and GPU. + +> I heard there's a free quota of 50 hours per month 🤔 + +### 3.1 Application Creation + +1. **Visit Cloud Studio** + Open your browser and visit [Cloud Studio](https://cloudstudio.net/). + +2. **Login or Register Account** + Click the `Register/Login` button in the upper right corner of the page and complete login using WeChat or other methods. + +3. **Create Application** + Find and click `Create Application` in the navigation bar at the top of the page. Select `Import from Git Repository`, enter `https://github.com/datawhalechina/all-in-rag.git` in the project address bar and press Enter. It will automatically create a title and description for you. + + ![Create Application](../images/1_2_10.webp) + +4. **Re-enter** + Later, find the previously created application on the [Application Management Page](https://cloudstudio.net/my-app), click on it and select "Write Code" in the upper right corner to re-enter. + + ![Re-enter Application](../images/1_2_11.webp) + +### 3.2 Python Environment Configuration + +After entering the IDE, first select the terminal on the right. + +![Enter Terminal](../images/1_2_12.webp) + +1. **Update System Packages** + + Enter the following command in the terminal: + + ```bash + sudo apt update + sudo apt upgrade -y + ``` + +2. **Switch to Regular User** + + ```bash + su ubuntu + ``` + +3. **Install Miniconda** + + ```bash + wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh + bash ~/miniconda.sh + ``` + + - Press Enter to read the license agreement + - Enter `yes` to agree to the agreement + - Press Enter directly when prompted for installation path (use default path /home/ubuntu/miniconda3) + - Whether to initialize Miniconda: Enter `yes` to add Miniconda to your PATH environment variable. + + ```bash + source ~/.bashrc + conda --version + ``` + + If the version number is displayed, the installation is successful. + +### 3.3 API Configuration + +1. Use the `vim` editor to open your shell configuration file. + + ```bash + vim ~/.bashrc + ``` + +2. Enter `i` to enter edit mode, add the following line at the end of the file, replacing `[Your Deepseek API Key]` with your own key: + + ```bash + export DEEPSEEK_API_KEY=[Your Deepseek API Key] + ``` + +3. Save and exit. In vim, press Esc to enter command mode, then type `:wq` and press Enter to save the file and exit. + +4. Make configuration effective. Execute the following command to immediately load the updated configuration and make the environment variable effective: + + ```bash + source ~/.bashrc + ``` + +### 3.4 Create and Activate Virtual Environment + +1. **Create Virtual Environment** + + ```bash + conda create --name all-in-rag python=3.12.7 + ``` + + Press Enter directly when options appear. + +2. **Configure File Permissions** + + ```bash + sudo chown -R ubuntu:ubuntu code models + ``` + +3. **Activate Virtual Environment** + + Use the following command to activate the virtual environment: + + ```bash + conda activate all-in-rag + ``` + +4. **Dependency Installation** + If you strictly follow the above process, you should currently be in the project root directory. Enter the code directory to install dependency libraries. + + ```bash + cd code + pip install -r requirements.txt + ``` + + > If there are version errors about grpcio, you can ignore them. + +## 4. Windows Environment Configuration (Skip this step if using Cloud Studio or Codespaces) + +### 4.1 API Configuration + +1. Right-click "Computer" or "This PC", then click "Properties". + +2. In the left menu, click "Advanced system settings". + +3. In the "System Properties" dialog box, click the "Advanced" tab, then click the "Environment Variables" button below. + + ![Advanced System Settings](../images/1_2_13.webp) + +4. In the "Environment Variables" dialog box, click "New" (under the "User variables" section), then enter the following information: + - Variable name: DEEPSEEK_API_KEY + - Variable value: [Your Deepseek API Key] + + ![Advanced System Settings](../images/1_2_14.webp) + +### 4.2 Install Miniconda + +1. **Download Installer** + + It's recommended to visit [Tsinghua University Open Source Software Mirror](https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/) for faster download speeds. Choose the latest `Windows-x86_64.exe` version according to your system. + + ![Select Miniconda Version](images/ch1/miniconda-select-version.png) + + You can also download from the [Miniconda Official Website](https://docs.conda.io/en/latest/miniconda.html). + +2. **Run Installation Wizard** + + After downloading, double-click the `.exe` file to start installation. Follow the wizard prompts: + + * **Welcome**: Click `Next`. + ![Welcome](../images/) + * **License Agreement**: Click `I Agree`. + ![License Agreement](../images/) + * **Installation Type**: Select `Just Me`, click `Next`. + ![Installation Type](../images/) + * **Choose Install Location**: It's recommended to keep the default path, or choose a path without Chinese characters and spaces. Click `Next`. + ![Install Location](../images/) + * **Advanced Installation Options**: **Do not check** "Add Miniconda3 to my PATH environment variable". We will manually configure environment variables later. Click `Install`. + ![Advanced Options](../images/) + * **Installation Complete**: After installation is complete, click `Next`, then uncheck "Learn more" and click `Finish` to complete installation. + ![Installation Complete](../images/) + +3. **Manually Configure Environment Variables** + + To use the `conda` command in any terminal window, you need to manually configure environment variables. + + * Search for "Edit the system environment variables" in the Windows search bar and open it. + ![Edit System Environment Variables](../images/) + * In the "System Properties" window, click "Environment Variables". + ![Environment Variables Button](../images/) + * In the "Environment Variables" window, find the `Path` variable under "System variables", select it and click "Edit". + ![Edit Path Variable](../images/) + * In the "Edit Environment Variable" window, create three new paths pointing to the corresponding folders under your Miniconda installation directory. If your installation path is `D:\Miniconda3`, you need to add: + ``` + D:\Miniconda3 + D:\Miniconda3\Scripts + D:\Miniconda3\Library\bin + ``` + ![Add Paths](../images/) + * After completion, click "OK" all the way to save changes. + +### 4.3 Configure Conda Mirror Sources + +To speed up subsequent package installations using `conda`, it's strongly recommended to configure domestic mirror sources. Open a new terminal or Anaconda Prompt and run the following commands: + +```bash +conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ +conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ +conda config --set show_channel_urls yes +``` + +After configuration, you can view the added sources using the `conda config --show channels` command. + +## 5. Project Code Pulling (Skip this step if using Cloud Studio or Codespaces) + +### 5.1 Install Git + +If you haven't installed Git yet, please follow these steps to install it. + +* **Windows System**: Visit the [Git Official Website](https://git-scm.com/download/win), download and run the installer, complete installation with default settings. +* **macOS System**: Open terminal and enter the following command to install Git: + + ```bash + brew install git + ``` +* **Linux System (Ubuntu example)**: Open terminal and enter the following commands to install Git: + + ```bash + sudo apt-get update + sudo apt-get install git + ``` + +After installation, verify that Git is installed successfully by entering the following command: + +```bash +git --version +``` + +If successful, it will display Git's version number. + +### 5.2 Clone Project Code + +1. **Choose Directory for Project** + Open terminal (or Git Bash in Windows), navigate to the directory where you want to store the project: + + ```bash + cd [path where you want to store the project] + ``` + +2. **Clone Repository** + Use the following command to pull the `all-in-rag` repository: + + ```bash + git clone https://github.com/datawhalechina/all-in-rag.git + ``` + + Wait for the download to complete. The project code will be stored in the `all-in-rag` folder in the current directory. + +3. **Enter Project Directory** + After pulling the code, enter the project directory: + + ```bash + cd all-in-rag + ``` + +### 5.3 Create and Activate Virtual Environment + +In the project directory, it's recommended to use the previously configured Miniconda to create a Python virtual environment. + +1. **Create Virtual Environment** + + ```bash + conda create --name all-in-rag python=3.12.7 + ``` + +2. **Activate Virtual Environment** + + All systems use the following command to activate the virtual environment: + + ```bash + conda activate all-in-rag + ``` + +3. **Dependency Installation** + If you strictly follow the above process, you should currently be in the project root directory. Enter the code directory to install dependency libraries. + + ```bash + cd code + pip install -r requirements.txt + ``` \ No newline at end of file diff --git a/docs/en/chapter1/03_get_start_rag.md b/docs/en/chapter1/03_get_start_rag.md new file mode 100644 index 0000000..5bcd759 --- /dev/null +++ b/docs/en/chapter1/03_get_start_rag.md @@ -0,0 +1,243 @@ +# Chapter 3: Four Steps to Build RAG + +Through the learning in Chapter 1, we have gained a basic understanding of RAG and have prepared the virtual environment and API key. Next, we will try to use the [**LangChain**](https://python.langchain.com/docs/introduction/) and [**LlamaIndex**](https://docs.llamaindex.ai/en/stable/) frameworks to implement and run our first RAG application. Through an example, we will demonstrate how to load local Markdown documents, process text using embedding models, and combine with large language models (LLM) to answer questions related to document content. + +## 1. Start Virtual Environment + +### 1.1 Activate Virtual Environment + +Assuming you have created a Conda virtual environment named `all-in-rag` following the guidance in the previous chapter. Before running the script, first activate the virtual environment: + +> If using Cloud Studio, you need to confirm whether you are currently in the user environment. If not, please run `su ubuntu` to switch to the user environment. + +```bash +conda activate all-in-rag +``` + +### 1.2 Switch to Project Directory + +```bash +# Assuming currently in the root directory of the all-in-rag project +cd code/C1 +``` + +The code files for each chapter are stored in the `code/Cx` directory, where `x` represents the chapter number. + +## 2. Run RAG Example Code + +After completing all the above settings, you can run the RAG example. + +Open the terminal, ensure the virtual environment is activated, then execute the following command: + +```bash +python 01_langchain_example.py +``` + +> If you encounter nltk-related errors, try running [fix_nltk.py](https://github.com/datawhalechina/all-in-rag/blob/main/code/C1/fix_nltk.py) in the code path. + +After the code runs, you can see output similar to the following (formatted): + +```bash +Downloading Model from https://www.modelscope.cn to directory: Path\to\all-in-rag\models\bge-small-zh-v1.5 +2025-06-08 02:36:19,318 - modelscope - INFO - Target directory already exists, skipping creation. +content=' +文中举了以下例子: + +1. **自然界中的羚羊**:刚出生的羚羊通过试错学习站立和奔跑,适应环境。 +2. **股票交易**:通过买卖股票并根据市场反馈调整策略,最大化奖励。 +3. **雅达利游戏(如Breakout和Pong)**:通过不断试错学习如何通关或赢得游戏。 +4. **选择餐馆**:利用(去已知喜欢的餐馆)与探索(尝试新餐馆)的权衡。 +5. **做广告**:利用(采取已知最优广告策略)与探索(尝试新广告策略)。 +6. **挖油**:利用(在已知地点挖油)与探索(在新地点挖油,可能发现大油田)。 +7. **玩游戏(如《街头霸王》)**:利用(固定策略如蹲角落出脚)与探索(尝试新招式如"大招")。 + +这些例子用于说明强化学习中的核心概念(如探索与利用、延迟奖励等)及其在实际场景中的应用。 +' +additional_kwargs={'refusal': None} +response_metadata={ + 'token_usage': { + 'completion_tokens': 209, + 'prompt_tokens': 5576, + 'total_tokens': 5785, + 'completion_tokens_details': None, + 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 5568}, + 'prompt_cache_hit_tokens': 5568, + 'prompt_cache_miss_tokens': 8 + }, + 'model_name': 'deepseek-chat', + 'system_fingerprint': 'fp_8802369eaa_prod0425fp8', + 'id': '67a0580d-78b1-44d6-bccf-f654ae0e9bba', + 'service_tier': None, + 'finish_reason': 'stop', + 'logprobs': None +} +id='run--919cedcd-771e-4aed-8dfd-cf436795792e-0' +usage_metadata={ + 'input_tokens': 5576, + 'output_tokens': 209, + 'total_tokens': 5785, + 'input_token_details': {'cache_read': 5568}, + 'output_token_details': {} +} +``` + +> When running for the first time, the script will download the `BAAI/bge-small-zh-v1.5` embedding model. + +Output parameter explanation: +- **`content`**: This is the core part, which is the specific answer generated by the large language model (LLM) based on your question and the provided context. +- **`additional_kwargs`**: Contains some additional parameters. In this example, it's `{'refusal': None}`, indicating that the model did not refuse to answer. +- **`response_metadata`**: Contains metadata about the LLM response. + - `token_usage`: Shows the number of tokens consumed in this call, including completion_tokens, prompt_tokens, and total_tokens. + - `model_name`: The name of the LLM model used, currently `deepseek-chat`. + - `system_fingerprint`, `id`, `service_tier`, `finish_reason`, `logprobs`: These are more detailed API response information. For example, `finish_reason: 'stop'` indicates that the model completed generation normally. +- **`id`**: The unique identifier for this run. +- **`usage_metadata`**: Similar to `token_usage` in `response_metadata`, providing statistics on input and output tokens. + +## 3. RAG Implementation Based on LangChain Framework + +> In Chapter 1, we mentioned that the four steps to build a minimum viable system are data preparation, index construction, retrieval optimization, and generation integration. Next, we will implement a RAG application based on the LangChain framework around these four aspects. + +### 3.1 Initial Setup + +First, perform basic configuration, including importing necessary libraries, loading environment variables, and downloading embedding models. + +```python +import os +# os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com' +from dotenv import load_dotenv +from langchain_community.document_loaders import TextLoader +from langchain_text_splitters import RecursiveCharacterTextSplitter +from langchain_huggingface import HuggingFaceEmbeddings +from langchain_core.vectorstores import InMemoryVectorStore +from langchain_core.prompts import ChatPromptTemplate +from langchain_deepseek import ChatDeepSeek + +# Load environment variables +load_dotenv() +``` + +### 3.2 Data Preparation + +- **Load raw documents**: First define the path to the Markdown file, then use `TextLoader` to load the file as a knowledge source. + ```python + markdown_path = "../../data/C1/markdown/easy-rl-chapter1.md" + loader = TextLoader(markdown_path) + docs = loader.load() + ``` +- **Text Chunking**: To facilitate subsequent embedding and retrieval, long documents are split into smaller, manageable text chunks. Here we use a recursive character splitting strategy with its default parameters for chunking. When initializing `RecursiveCharacterTextSplitter()` without specifying parameters, its default behavior aims to preserve the semantic structure of the text to the maximum extent: + - **Default separators and semantic preservation**: Try to use a series of preset separators `["\n\n" (paragraphs), "\n" (lines), " " (spaces), "" (characters)]` in order to recursively split the text. The purpose of this strategy is to maintain the integrity of paragraphs, sentences, and words as much as possible, as they are usually the most semantically relevant text units, until the text chunks reach the target size. + - **Preserve separators**: By default (`keep_separator=True`), the separators themselves are preserved in the split text chunks. + - **Default chunk size and overlap**: Use the default parameters `chunk_size=4000` (chunk size) and `chunk_overlap=200` (chunk overlap) defined in its base class `TextSplitter`. These parameters ensure that text chunks meet predetermined size limits and reduce the loss of contextual information through overlap. + ```python + text_splitter = RecursiveCharacterTextSplitter() + texts = text_splitter.split_documents(docs) + ``` + +### 3.3 Index Construction + +After data preparation is complete, next build the vector index: + +- **Initialize Chinese embedding model**: Use `HuggingFaceEmbeddings` to load the Chinese embedding model downloaded in the initial setup. Configure the model to run on CPU and enable embedding normalization (`normalize_embeddings: True`). + ```python + embeddings = HuggingFaceEmbeddings( + model_name="BAAI/bge-small-zh-v1.5", + model_kwargs={'device': 'cpu'}, + encode_kwargs={'normalize_embeddings': True} + ) + ``` +- **Build vector storage**: Convert the split text chunks (`texts`) into vector representations through the initialized embedding model, then use `InMemoryVectorStore` to add these vectors and their corresponding original text content, thereby building a vector index in memory. + ```python + vectorstore = InMemoryVectorStore(embeddings) + vectorstore.add_documents(texts) + ``` + After this process is completed, a queryable knowledge index is built. + +### 3.4 Query and Retrieval + +After the index is built, you can query and retrieve based on user questions: + +- **Define user query**: Set a specific user question string. + ```python + question = "What examples are mentioned in the text?" + ``` +- **Query relevant documents in vector storage**: Use the `similarity_search` method of vector storage to find the most relevant `k` (in this example `k=3`) text chunks in the index based on user questions. + ```python + retrieved_docs = vectorstore.similarity_search(question, k=3) + ``` +- **Prepare context**: Merge the page content (`doc.page_content`) of multiple retrieved text chunks into a single string, separated by double newlines (`"\n\n"`), forming the final context information (`docs_content`) for the large language model to reference. + ```python + docs_content = "\n\n".join(doc.page_content for doc in retrieved_docs) + ``` + > Using `"\n\n"` (double newlines) instead of `"\n"` (single newlines) to connect different retrieved document chunks is mainly to more clearly distinguish these independent text fragments semantically when passing to large language models (LLM). Double newlines usually represent the end of a paragraph and the beginning of a new paragraph. This format helps LLM treat each chunk as an independent context source, thereby better understanding and utilizing this information to generate answers. + +### 3.5 Generation Integration + +The final step is to combine the retrieved context with user questions and use large language models (LLM) to generate answers: + +- **Build prompt template**: Use `ChatPromptTemplate.from_template` to create a structured prompt template. This template guides the LLM to answer user questions based on the provided context (`context`) and clearly indicates how to respond when information is insufficient. + ```python + prompt = ChatPromptTemplate.from_template("""Please answer the question based on the context information provided below. + Please ensure your answer is completely based on this context. + If there is not enough information in the context to answer the question, please directly inform: "Sorry, I cannot find relevant information in the provided context to answer this question." + + Context: + {context} + + Question: {question} + + Answer:""" + ) + ``` +- **Configure large language model**: Initialize the `ChatDeepSeek` client, configure the model used (`deepseek-chat`), temperature parameter for generating answers (`temperature=0.7`), maximum number of tokens (`max_tokens=2048`), and API key (loaded from environment variables). + ```python + llm = ChatDeepSeek( + model="deepseek-chat", + temperature=0.7, + max_tokens=2048, + api_key=os.getenv("DEEPSEEK_API_KEY") + ) + ``` +- **Call LLM to generate answer and output**: Format the user question (`question`) and previously prepared context (`docs_content`) into the prompt template, then call ChatDeepSeek's `invoke` method to get the generated answer. + ```python + answer = llm.invoke(prompt.format(question=question, context=docs_content)) + print(answer) + ``` +[Complete Code](https://github.com/datawhalechina/all-in-rag/blob/main/code/C1/01_langchain_example.py) + +> Teacher, teacher, LangChain is powerful but still requires too much operation. Do you have any simpler and more user-friendly framework recommendations? + +> Yes, brother, yes! There are other user-friendly frameworks like LlamaIndex😉 + +## 4. Low-Code (Based on LlamaIndex) + +In terms of RAG, LlamaIndex provides more encapsulated API interfaces, which undoubtedly lowers the barrier to entry. Here's a simple implementation: + +```python +import os +# os.environ['HF_ENDPOINT']='https://hf-mirror.com' +from dotenv import load_dotenv +from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings +from llama_index.llms.deepseek import DeepSeek +from llama_index.embeddings.huggingface import HuggingFaceEmbedding + +load_dotenv() + +Settings.llm = DeepSeek(model="deepseek-chat", api_key=os.getenv("DEEPSEEK_API_KEY")) +Settings.embed_model = HuggingFaceEmbedding("BAAI/bge-small-zh-v1.5") + +documents = SimpleDirectoryReader(input_files=["../../data/C1/markdown/easy-rl-chapter1.md"]).load_data() + +index = VectorStoreIndex.from_documents(documents) + +query_engine = index.as_query_engine() + +print(query_engine.get_prompts()) + +print(query_engine.query("What examples are mentioned in the text?")) +``` + +## Exercises (You can use large models to assist completion) + +- Modify the parameters `chunk_size` and `chunk_overlap` of `RecursiveCharacterTextSplitter()` in the LangChain code and observe what changes occur in the output results. +- The final output obtained from LangChain code carries various parameters. Look up relevant materials and try to filter out these parameters to get the specific answer in `content`. +- Add code comments to the LlamaIndex code. diff --git a/docs/en/chapter1/images/1_1_1.svg b/docs/en/chapter1/images/1_1_1.svg new file mode 100644 index 0000000..78a9954 --- /dev/null +++ b/docs/en/chapter1/images/1_1_1.svg @@ -0,0 +1,3 @@ + + +
RAG
检索阶段
生成阶段
用户查询
检索模块
相关文档/片段
生成模块
Embedding
model



Encoding
外部知识库
Encoding
Vector
database
Prompt
LLM响应
author: dalvqw
Index
Similarity
Search
\ No newline at end of file diff --git a/docs/en/chapter1/images/1_1_2.png b/docs/en/chapter1/images/1_1_2.png new file mode 100644 index 0000000..6dba4a7 Binary files /dev/null and b/docs/en/chapter1/images/1_1_2.png differ diff --git a/docs/en/chapter1/images/1_1_3.svg b/docs/en/chapter1/images/1_1_3.svg new file mode 100644 index 0000000..f8aa2b7 --- /dev/null +++ b/docs/en/chapter1/images/1_1_3.svg @@ -0,0 +1,3 @@ + + +
RAG
Prompt Engineering
Fine-tuning
Hybrid
(RAG + Fine-tuning)
Context
optimization
LLM Optimization
Prompting vs RAG vs Fine-Tuning
\ No newline at end of file diff --git a/docs/en/chapter1/images/1_2_1.webp b/docs/en/chapter1/images/1_2_1.webp new file mode 100644 index 0000000..e543fd4 Binary files /dev/null and b/docs/en/chapter1/images/1_2_1.webp differ diff --git a/docs/en/chapter1/images/1_2_10.webp b/docs/en/chapter1/images/1_2_10.webp new file mode 100644 index 0000000..111d7dd Binary files /dev/null and b/docs/en/chapter1/images/1_2_10.webp differ diff --git a/docs/en/chapter1/images/1_2_11.webp b/docs/en/chapter1/images/1_2_11.webp new file mode 100644 index 0000000..3416aa9 Binary files /dev/null and b/docs/en/chapter1/images/1_2_11.webp differ diff --git a/docs/en/chapter1/images/1_2_12.webp b/docs/en/chapter1/images/1_2_12.webp new file mode 100644 index 0000000..2787ef7 Binary files /dev/null and b/docs/en/chapter1/images/1_2_12.webp differ diff --git a/docs/en/chapter1/images/1_2_13.webp b/docs/en/chapter1/images/1_2_13.webp new file mode 100644 index 0000000..8c6fc11 Binary files /dev/null and b/docs/en/chapter1/images/1_2_13.webp differ diff --git a/docs/en/chapter1/images/1_2_14.webp b/docs/en/chapter1/images/1_2_14.webp new file mode 100644 index 0000000..308e98c Binary files /dev/null and b/docs/en/chapter1/images/1_2_14.webp differ diff --git a/docs/en/chapter1/images/1_2_2.webp b/docs/en/chapter1/images/1_2_2.webp new file mode 100644 index 0000000..f22d8e7 Binary files /dev/null and b/docs/en/chapter1/images/1_2_2.webp differ diff --git a/docs/en/chapter1/images/1_2_3.webp b/docs/en/chapter1/images/1_2_3.webp new file mode 100644 index 0000000..6f7f5db Binary files /dev/null and b/docs/en/chapter1/images/1_2_3.webp differ diff --git a/docs/en/chapter1/images/1_2_4.webp b/docs/en/chapter1/images/1_2_4.webp new file mode 100644 index 0000000..8c389f6 Binary files /dev/null and b/docs/en/chapter1/images/1_2_4.webp differ diff --git a/docs/en/chapter1/images/1_2_5.webp b/docs/en/chapter1/images/1_2_5.webp new file mode 100644 index 0000000..8404023 Binary files /dev/null and b/docs/en/chapter1/images/1_2_5.webp differ diff --git a/docs/en/chapter1/images/1_2_6.webp b/docs/en/chapter1/images/1_2_6.webp new file mode 100644 index 0000000..915d279 Binary files /dev/null and b/docs/en/chapter1/images/1_2_6.webp differ diff --git a/docs/en/chapter1/images/1_2_7.webp b/docs/en/chapter1/images/1_2_7.webp new file mode 100644 index 0000000..6473e20 Binary files /dev/null and b/docs/en/chapter1/images/1_2_7.webp differ diff --git a/docs/en/chapter1/images/1_2_8.webp b/docs/en/chapter1/images/1_2_8.webp new file mode 100644 index 0000000..d4248e8 Binary files /dev/null and b/docs/en/chapter1/images/1_2_8.webp differ diff --git a/docs/en/chapter1/images/1_2_9.webp b/docs/en/chapter1/images/1_2_9.webp new file mode 100644 index 0000000..72a1ed3 Binary files /dev/null and b/docs/en/chapter1/images/1_2_9.webp differ diff --git a/docs/en/chapter1/images/1_4_1.png b/docs/en/chapter1/images/1_4_1.png new file mode 100644 index 0000000..6afe0d7 Binary files /dev/null and b/docs/en/chapter1/images/1_4_1.png differ diff --git a/docs/en/chapter1/images/1_4_2.png b/docs/en/chapter1/images/1_4_2.png new file mode 100644 index 0000000..84a33db Binary files /dev/null and b/docs/en/chapter1/images/1_4_2.png differ diff --git a/docs/en/chapter1/images/1_4_3.png b/docs/en/chapter1/images/1_4_3.png new file mode 100644 index 0000000..515007e Binary files /dev/null and b/docs/en/chapter1/images/1_4_3.png differ diff --git a/docs/en/logo.svg b/docs/en/logo.svg new file mode 100644 index 0000000..a043544 --- /dev/null +++ b/docs/en/logo.svg @@ -0,0 +1,24550 @@ + + + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..d02ed4d --- /dev/null +++ b/docs/index.html @@ -0,0 +1,483 @@ + + + + + + All-in-RAG | 大模型应用开发实战:RAG技术全栈指南 + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/logo.svg b/docs/logo.svg new file mode 100644 index 0000000..a043544 --- /dev/null +++ b/docs/logo.svg @@ -0,0 +1,24550 @@ + + + + diff --git a/docs/project01.png b/docs/project01.png new file mode 100644 index 0000000..d90e3da Binary files /dev/null and b/docs/project01.png differ diff --git a/docs/project01_graph.png b/docs/project01_graph.png new file mode 100644 index 0000000..a0753d7 Binary files /dev/null and b/docs/project01_graph.png differ diff --git a/emoji.png b/emoji.png new file mode 100644 index 0000000..48665be Binary files /dev/null and b/emoji.png differ diff --git a/logo.svg b/logo.svg new file mode 100644 index 0000000..a043544 --- /dev/null +++ b/logo.svg @@ -0,0 +1,24550 @@ + + + + diff --git a/models/main.txt b/models/main.txt new file mode 100644 index 0000000..e69de29 diff --git a/project01.png b/project01.png new file mode 100644 index 0000000..d90e3da Binary files /dev/null and b/project01.png differ diff --git a/project01_graph.png b/project01_graph.png new file mode 100644 index 0000000..a0753d7 Binary files /dev/null and b/project01_graph.png differ diff --git a/内测群二维码.png b/内测群二维码.png new file mode 100644 index 0000000..a91ae19 Binary files /dev/null and b/内测群二维码.png differ