# EasyLink EasyDoc-Extract 文档信息抽取

## 概述

EasyDoc-Extract 是一个智能文档信息抽取模型。上传文档（PDF/图片）后，模型会自动从中抽取结构化信息，返回 JSON 格式的抽取结果，适用于合同要素提取、发票解析、表单数据录入等场景。

本接口为异步模式：提交任务后获得任务 ID，通过轮询接口查询结果。

更多细节请参考 [EasyLink 官方文档](https://docs.easylink-ai.com/docs/capabilities/extraction/universal)。

**请求地址**：`https://api.modelverse.cn/v1/easydoc/submit`

## 支持模型

- `easydoc-extract`
- `easydoc-extract-flash`

## 抽取模式说明

| 模式 | 触发条件 | 说明 |
| :--- | :--- | :--- |
| 封闭式 | `json_schema` 有效 JSON | 按指定 Schema 抽取字段，结果为结构化 JSON 对象 |
| 自定义 Prompt | `json_schema` 无效 + `prompt_cus` 非空 | 按自然语言描述抽取，结果为字符串 |
| 开放式 | 两者均为空 | 自动识别文档类型并抽取所有可识别字段（仅 `easydoc-extract` 支持） |

> 注：`easydoc-extract-flash` 仅支持封闭式抽取（`json_schema` 必填且非空）。

## 请求参数

### 提交任务

`POST /v1/easydoc/submit`，请求体为 `multipart/form-data` 格式，直接上传文件本身（不再需要公网 URL）。

| 字段 | 类型 | 是否必需 | 说明 |
| :--- | :--- | :--- | :--- |
| model | string | 是 | 模型名称：`easydoc-extract` 或 `easydoc-extract-flash` |
| files | file | 是 | 待抽取文件，支持 PDF / JPG / PNG / BMP / TIFF |
| json_schema | string | 否 | 封闭式模式：JSON Schema 格式字符串，指定需要抽取的字段 |
| prompt_cus | string | 否 | 自定义 Prompt 模式：自然语言描述抽取需求 |

`json_schema` 示例（封闭式模式，抽取合同关键字段）：

```json
{
  "type": "object",
  "properties": {
    "甲方名称": {"type": "string"},
    "乙方名称": {"type": "string"},
    "合同金额": {"type": "string"},
    "签订日期": {"type": "string"},
    "合同编号": {"type": "string"}
  }
}
```

### 查询任务状态

`GET /v1/tasks/status?task_id={task_id}`

| 字段 | 类型 | 是否必需 | 说明 |
| :--- | :--- | :--- | :--- |
| task_id | string | 是 | 提交任务时返回的任务 ID |

## 响应字段

### 提交响应

提交接口直接透传上游 EasyLink 的响应结构：

| 字段 | 类型 | 说明 |
| :--- | :--- | :--- |
| success | boolean | 请求是否成功 |
| data.task_id | string | 任务 ID，用于后续查询 |
| data.status | string | 任务初始状态，通常为 `PROCESSING` |
| err_code | string | 错误码（失败时返回） |
| err_message | string | 错误信息（失败时返回） |

> 注意：新接口的 task_id 在 `data.task_id` 字段，与老 URL 模式的 `output.task_id` 路径不同。

### 状态查询响应

| 字段 | 类型 | 说明 |
| :--- | :--- | :--- |
| output.task_status | string | 任务状态：`Pending` / `Running` / `Success` / `Failure` |
| output.result | array | 抽取结果列表（成功时返回），每个元素对应一个文件，见下方说明 |
| output.error_message | string | 错误信息（失败时返回） |
| usage.page_count | integer | 文件总页数，用于计费 |

`output.result` 每个元素的结构：

| 字段 | 类型 | 说明 |
| :--- | :--- | :--- |
| page_count | integer | 当前文件页数 |
| key_index | array | 抽取字段名列表（封闭式模式返回） |
| extracted_fields | object/string | 抽取结果：封闭式模式为 JSON 对象，自定义 Prompt 模式为字符串 |

## 示例

### Curl 示例

**提交任务（封闭式模式）：**

```bash
curl -X POST https://api.modelverse.cn/v1/easydoc/submit \
  -H "Authorization: Bearer {api_key}" \
  -F "model=easydoc-extract" \
  -F "files=@/path/to/contract.pdf" \
  -F 'json_schema={"type":"object","properties":{"甲方名称":{"type":"string"},"乙方名称":{"type":"string"},"合同金额":{"type":"string"},"签订日期":{"type":"string"}}}'
```

**提交任务（开放式模式）：**

```bash
curl -X POST https://api.modelverse.cn/v1/easydoc/submit \
  -H "Authorization: Bearer {api_key}" \
  -F "model=easydoc-extract" \
  -F "files=@/path/to/document.pdf"
```

**查询任务状态：**

```bash
curl "https://api.modelverse.cn/v1/tasks/status?task_id={task_id}" \
  -H "Authorization: Bearer {api_key}"
```

### Python 示例

```python
import json
import time
import requests

api_key = "******"  # 替换为你的 API Key
base_url = "https://api.modelverse.cn/v1"

headers = {
    "Authorization": f"Bearer {api_key}",
}

# 封闭式模式：构造 json_schema
schema = {
    "type": "object",
    "properties": {
        "甲方名称": {"type": "string"},
        "乙方名称": {"type": "string"},
        "合同金额": {"type": "string"},
        "签订日期": {"type": "string"},
    },
}

# 提交任务（multipart 本地上传）
with open("/path/to/contract.pdf", "rb") as f:
    files = {"files": ("contract.pdf", f, "application/pdf")}
    data = {
        "model": "easydoc-extract",
        "json_schema": json.dumps(schema, ensure_ascii=False),
    }
    resp = requests.post(f"{base_url}/easydoc/submit", headers=headers, files=files, data=data)

task_id = resp.json()["data"]["task_id"]
print(f"task_id: {task_id}")

# 轮询查询结果
while True:
    result = requests.get(
        f"{base_url}/tasks/status",
        headers=headers,
        params={"task_id": task_id},
    ).json()

    status = result["output"]["task_status"]
    print(f"status: {status}")

    if status == "Success":
        print("抽取结果:")
        for item in result["output"]["result"]:
            print(f"  页数: {item.get('page_count')}")
            print(f"  字段名: {item.get('key_index')}")
            print(f"  抽取内容: {item.get('extracted_fields')}")
        print(f"总页数: {result['usage']['page_count']}")
        break
    elif status == "Failure":
        print(f"失败: {result['output'].get('error_message')}")
        break

    time.sleep(5)
```

## 响应示例

**提交成功：**

```json
{
  "success": true,
  "data": {
    "task_id": "b_extract_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "status": "PROCESSING"
  }
}
```

**任务完成（封闭式模式）：**

```json
{
  "output": {
    "task_id": "b_extract_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "task_status": "Success",
    "result": [
      {
        "page_count": 5,
        "key_index": ["甲方名称", "乙方名称", "合同金额", "签订日期"],
        "extracted_fields": {
          "甲方名称": "北京示例科技有限公司",
          "乙方名称": "上海示例贸易有限公司",
          "合同金额": "人民币壹拾万元整",
          "签订日期": "2024年1月1日"
        }
      }
    ],
    "submit_time": 1700000000,
    "finish_time": 1700000060
  },
  "usage": {
    "page_count": 5
  },
  "request_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

## 使用说明

1. **文件格式**：支持 PDF、JPG、PNG、BMP、TIFF，通过 `files` 字段直接上传文件本身。
2. **抽取模式选择**：
   - 字段明确时推荐使用**封闭式模式**（传入 `json_schema`），结果最为准确。
   - 需要灵活描述抽取需求时使用**自定义 Prompt 模式**（传入 `prompt_cus`）。
   - 无特定需求时可使用**开放式模式**（两者均不传），自动识别并抽取文档中的所有可识别字段。
3. **json_schema 格式**：传入的是 JSON Schema 的**序列化字符串**（即对 JSON 对象调用 `json.dumps()` 后的结果），而非 JSON 对象本身。
4. **结果格式**：抽取结果通过 `output.result` 字段返回，为 JSON 数组，每个元素对应一个输入文件。
5. **计费**：按文件总页数计费，页数通过 `usage.page_count` 返回。

## 兼容：URL 模式（legacy）

旧版本接口仍可用，客户通过 `input.img_url` 传入文件的公网 URL，通过 `parameters.json_schema` / `parameters.prompt_cus` 传入抽取规则，mvs 帮忙下载后转发上游。新客户推荐使用上面的 V1 本地上传接口（对齐 EasyLink 官方调用方式）。

**请求地址**：`https://api.modelverse.cn/v1/tasks/submit`

```bash
curl -X POST https://api.modelverse.cn/v1/tasks/submit \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "easydoc-extract",
    "input": {
      "img_url": "https://example.com/contract.pdf"
    },
    "parameters": {
      "json_schema": "{\"type\":\"object\",\"properties\":{\"甲方名称\":{\"type\":\"string\"}}}"
    }
  }'
```

提交响应格式为 `{"output":{"task_id":"b_extract_xxx"},"request_id":"..."}`（task_id 在 `output.task_id`，注意与 V1 接口的 `data.task_id` 不同）。查询接口与 V1 一致，复用 `GET /v1/tasks/status`。
