# 批量提取 S3 钻孔资料中的编号和孔深

MOI 支持通过标准 S3 连接器批量导入对象存储中的工程文件，并使用信息提取工作流将 PDF、扫描件和图片中的关键字段转换为结构化结果。整个过程可以直接处理 S3 中的一批文件，无需逐份下载和整理。

本教程以钻孔柱状图为例，从 3 份 PDF 中提取钻孔编号和孔深，并将结果保存为 JSON。

完成后，MOI 会在 Catalog 中为每份完整文件生成一份 JSON：

```json
{
  "hole_id": "DEMO-ZK-001",
  "depth": "35.8m"
}
```

为了方便说明操作流程，本教程提供 3 份工程文档示例文件。实际使用时，可以直接处理自己 S3 文件夹中的工程文件。

整个操作预计约 30 分钟。文件解析时间会随文件数量变化。

## 你将完成什么

- 连接存放工程文件的 S3 文件夹；
- 将一批 PDF 导入 MOI Catalog；
- 创建信息提取工作流；
- 批量提取钻孔编号和孔深；
- 在结果数据卷中查看结构化 JSON。

## 开始前准备

- 准备一个 MOI 账号，可前往 [MOI 云端登录/注册](https://moi.matrixorigin.cn/)；
- 准备 S3 Endpoint、Bucket、文件路径、Access Key ID 和 Access Key Secret。

为了方便完成教程，我们提供了 [S3 工程文档示例包](../assets/downloads/moi-s3-engineering-demo.zip)。您可以使用样例文件跟随教程操作；实际使用时，直接选择自己 S3 文件夹中的工程文件。

示例文件包括：

| 文件 | 用途 |
| --- | --- |
| `demo-borehole-log-001.pdf` | 提取钻孔编号 `DEMO-ZK-001` 和孔深 `35.8m` |
| `demo-borehole-log-002.pdf` | 提取钻孔编号 `DEMO-ZK-002` 和孔深 `48.2m` |
| `demo-borehole-log-missing-depth.pdf` | 未填写孔深的钻孔记录示例 |

## 操作步骤

### 1. 连接 S3

1. 登录 MOI，在左侧导航的 **数据连接** 中选择 **连接器**。
2. 点击 **新建连接器**，将连接器名称填写为 `conn_s3`。
3. 类型选择 **对象存储 > 标准 S3**，用途选择 **导入**。
4. 填写以下连接信息：

   | 字段 | 填写内容 |
   | --- | --- |
   | Endpoint | S3 API 地址，包含协议和端口 |
   | AccessKey ID | 可读取测试文件夹的 Access Key |
   | AccessKey Secret | 与 AccessKey ID 对应的 Secret Key |
   | 文件路径 | `<bucket>/<测试文件夹>/`，不填写 `s3://` |
   | S3 地址风格 | MinIO 通常选择 **Path Style** |
   | 地区 | 表单要求时填写 S3 配置的 Region |

5. 点击 **测试连接**。连接成功后，点击 **确定**。

```{image} images/minio-standard-s3-connector-config.png
:alt: 创建标准 S3 连接器并测试连接
```

返回连接器列表，确认 `conn_s3` 的状态为 **已连接**。

```{image} images/minio-standard-s3-connector-connected.png
:alt: 标准 S3 连接器状态显示为已连接
```

### 2. 批量导入工程文件

1. 在左侧导航的 **数据连接** 中选择 **导入任务**。
2. 点击 **新建导入任务**，选择 **非结构化**。
3. 数据来源选择 **连接器源**，然后选择 `conn_s3`。
4. 将导入方式设置为 **一次性**。
5. 在目标位置中选择当前工作区的 Catalog，并将文件导入以下位置：

   ```text
   <当前工作区 Catalog> / tutorial_data / excel_analysis / incoming
   ```

   其中，`tutorial_data` 是目录，`excel_analysis` 是数据库，`incoming` 是保存原始文件的数据卷。如果尚未创建，可以在选择目标位置时依次新建。

6. 在导入文件列表中选择存放待处理工程文件的 S3 文件夹。
7. 保持其余配置为默认值，点击 **创建并开始导入**。

```{image} images/s3-import-task-config.png
:alt: 从 S3 连接器选择工程文件并配置导入任务
```

8. 等待导入任务状态变为 **已完成**。

```{image} images/s3-import-task-completed.png
:alt: S3 文件导入任务状态显示为已完成
```

导入完成后，可以在 **资源中心 > Catalog > tutorial_data > excel_analysis > incoming** 中看到本次导入的工程文件。

### 3. 创建信息提取工作流

先在 **资源中心 > Catalog > tutorial_data > excel_analysis** 下创建结果数据卷 `extracted`，用于保存提取结果。

结果位置为：

```text
<当前工作区 Catalog> / tutorial_data / excel_analysis / extracted
```

然后创建工作流：

1. 在左侧导航的 **数据处理** 中选择 **工作流**。
2. 点击 **创建工作流**。
3. 找到 **解析信息提取** 模板，点击 **使用模板**。

```{image} images/s3-workflow-select-information-extraction-template.png
:alt: 创建工作流时选择解析信息提取模板
```

4. 将工作流名称填写为 `engineering_document_extraction`。
5. 按下面的顺序完成运行配置。

#### 选择 Catalog 数据源

在运行配置的 **Catalog 数据源** 中进行以下设置：

- **计算资源**：保持 **跟随工作流默认**；
- **源文件**：选择导入后的数据卷：

```text
tutorial_data / excel_analysis / incoming
```

- **文件范围**：选择 **按文件**，然后选中本次需要处理的 3 份 PDF。

```{image} images/s3-workflow-catalog-source.png
:alt: 在解析信息提取模板中配置 Catalog 数据源并选择工程文件
```

#### 配置结构化抽取

在运行配置的 **结构化抽取** 中进行以下设置：

- **计算资源**：保持 **跟随工作流默认**；
- **多模态提取模型**：选择当前工作区可用的 VL 模型，例如 **Genesis / qwen-vl-max（系统默认）**；
- **提取字段定义**：选择 **JSON 配置**，将以下 JSON Schema 粘贴到输入框中：

```json
{
  "type": "object",
  "properties": {
    "hole_id": {
      "type": "string",
      "description": "钻孔编号。移除 OCR 产生的多余空格，但保留编号中的连字符。"
    },
    "depth": {
      "type": "string",
      "description": "终孔孔深，保留数值和单位 m，并移除数值与单位之间的空格。"
    }
  },
  "required": ["hole_id", "depth"]
}
```

```{image} images/s3-workflow-structured-extraction-schema.png
:alt: 选择 VL 多模态模型并配置钻孔编号和孔深的 JSON Schema
```

#### 保存至 Catalog

在运行配置的 **保存至 Catalog** 中进行以下设置：

- **计算资源**：保持 **跟随工作流默认**；
- **输出位置**：选择用于保存结构化提取结果的数据卷：

```text
tutorial_data / excel_analysis / extracted
```

```{image} images/s3-workflow-save-to-catalog.png
:alt: 在解析信息提取模板中配置结构化结果的 Catalog 输出位置
```

完成配置后，点击 **确认**。

### 4. 保存并运行工作流

1. 点击 **保存并启用**。
2. 在工作流页面点击 **运行**。
3. 确认输入位置为 `incoming`，输出位置为 `extracted`。
4. 开始运行后，在工作流页面右侧找到 **作业** 按钮并点击。
5. 在作业列表中找到本次运行记录，等待 3 个文件对应的作业状态均变为 **已完成**。

```{image} images/s3-workflow-run-completed.png
:alt: 作业列表中 engineering_document_extraction 的运行状态显示为已完成
```

### 5. 查看结构化结果

1. 打开 **资源中心 > Catalog > tutorial_data > excel_analysis > extracted**。
2. 确认列表中为每份源 PDF 生成了一个 ZIP 结果包。ZIP 文件名由源文件名和系统生成的标识组成。
3. 点击每个 ZIP 右侧的 **下载** 图标，将结果包下载到本地并解压。

```{image} images/s3-workflow-output-packages.png
:alt: Catalog 的 extracted 数据卷中显示三份源 PDF 对应的 ZIP 结果包和下载入口
```

每个 ZIP 结果包包含以下 3 个 JSON 文件。以 `demo-borehole-log-002.pdf` 的结果包为例：

| 文件 | 包含内容 | 用途 |
| --- | --- | --- |
| `demo-borehole-log-002.pdf_extract.json` | `extraction` 中的 `hole_id`、`depth` 以及源文件名 | 查看并使用最终结构化提取结果 |
| `demo-borehole-log-002.pdf_extracted_sources.json` | 每个字段的提取值，以及对应的文件、页码和解析块 | 查看字段在原文中的来源位置 |
| `demo-borehole-log-002.pdf_parse.json` | 文档类型、解析块数量以及各块的 OCR、图注和元数据 | 查看文档的块级解析内容 |

`_extract.json` 是主要结果文件，其中包含工作流按照 Schema 生成的结构化字段：

```{image} images/s3-workflow-output-extract.png
:alt: extract JSON 中包含 extraction 对象、孔深、钻孔编号和源文件名
```

`_extracted_sources.json` 为每个字段保存来源信息，包括提取值、源文件、页码和解析块编号：

```{image} images/s3-workflow-output-sources.png
:alt: extracted sources JSON 中记录孔深和钻孔编号各自对应的来源位置
```

`_parse.json` 保存文档解析产生的块级结果：

```{image} images/s3-workflow-output-parse.png
:alt: parse JSON 中包含源文件信息、解析块和块级元数据
```

查看结果时，先打开 `_extract.json` 查看 `hole_id` 和 `depth`；再打开 `_extracted_sources.json` 查看每个字段对应的源文件、页码和解析块；需要了解文档的块级解析内容时，打开 `_parse.json`。

## 教程完成

您已经完成了从 S3 工程文档到结构化结果的完整流程：工程文件已从 S3 批量导入 MOI，工作流完成了文档解析和字段提取，结果以 JSON 保存到 Catalog，可用于后续台账整理和资料核对。
