# EasyLink EMR-Mask 病历脱敏

## 概述

EMR-Mask 是一个专业的病历文档智能脱敏模型。上传医疗文档（PDF/图片）后，模型会自动识别并遮蔽患者姓名、身份证号、联系电话等敏感信息，返回脱敏后的文件下载链接，保障医疗数据在共享、归档、训练等场景下的安全与合规性。

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

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

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

## 支持模型

- `easydoc-emr-mask`

## 请求参数

### 提交任务

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

| 字段 | 类型 | 是否必需 | 说明 |
| :--- | :--- | :--- | :--- |
| model | string | 是 | 模型名称，固定为 `easydoc-emr-mask` |
| files | file | 是 | 待脱敏文件，支持 PDF / JPG / PNG / BMP / TIFF |
| json_schema | string | 是 | 脱敏规则，JSON Schema 格式字符串，指定需要脱敏的字段 |

`json_schema` 示例（指定需要脱敏的字段）：

```json
{
  "type": "object",
  "properties": {
    "患者姓名": {"type": "string"},
    "患者性别": {"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.urls | array | 脱敏后的文件下载链接列表（1小时有效） |
| output.error_message | string | 错误信息（失败时返回） |
| usage.page_count | integer | 文件页数，用于计费 |

## 示例

### Curl 示例

**提交任务：**

```bash
curl -X POST https://api.modelverse.cn/v1/easydoc/submit \
  -H "Authorization: Bearer {api_key}" \
  -F "model=easydoc-emr-mask" \
  -F "files=@/path/to/medical_record.pdf" \
  -F 'json_schema={"type":"object","properties":{"患者姓名":{"type":"string"},"患者性别":{"type":"string"},"年龄":{"type":"string"}}}'
```

**查询任务状态：**

```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}",
}

# 脱敏规则
schema = {
    "type": "object",
    "properties": {
        "患者姓名": {"type": "string"},
        "患者性别": {"type": "string"},
        "年龄": {"type": "string"},
    },
}

# 提交任务（multipart 本地上传）
with open("/path/to/medical_record.pdf", "rb") as f:
    files = {"files": ("medical_record.pdf", f, "application/pdf")}
    data = {
        "model": "easydoc-emr-mask",
        "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 url in result["output"]["urls"]:
            print(url)
        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_mask_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "status": "PROCESSING"
  }
}
```

**任务完成：**

```json
{
  "output": {
    "task_id": "b_mask_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "task_status": "Success",
    "urls": [
      "https://oss.easylink-ai.com/easylink-easydoc-task/mask_merge/xxxxxxxx.pdf?..."
    ],
    "submit_time": 1700000000,
    "finish_time": 1700000060
  },
  "usage": {
    "page_count": 3
  },
  "request_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

## 使用说明

1. **文件格式**：支持 PDF、JPG、PNG、BMP、TIFF，通过 `files` 字段直接上传文件本身。
2. **脱敏规则**：通过 `json_schema` 字段传入 JSON Schema 字符串，指定需要脱敏的字段名。不传或传空会导致任务失败。
3. **结果链接有效期**：返回的脱敏文件 URL 有效期为 1 小时，请及时下载保存。
4. **计费**：按文件页数计费，页数通过 `usage.page_count` 返回。

## 兼容：URL 模式（legacy）

旧版本接口仍可用，客户通过 `input.img_url` 传入文件的公网 URL，通过 `input.prompt` 传入脱敏规则，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-emr-mask",
    "input": {
      "img_url": "https://example.com/medical_record.pdf",
      "prompt": "{\"type\":\"object\",\"properties\":{\"患者姓名\":{\"type\":\"string\"}}}"
    }
  }'
```

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