Skip to content

接口说明

OCR 文档智能服务

shell
POST https://api.scnet.cn/api/llm/v1/ocrdoc/submit

1.功能介绍

​ Scnet OCR 文档智能服务,支持多种文档类型的异步 OCR 识别任务提交与结果查询,适用于大批量文档处理场景。

​ 核心流程: ​ 【任务提交】通过 submit 接口提交待处理的文件 URL,获取任务 ID; ​ 【状态查询】通过 result 接口轮询任务状态,获取处理结果; ​ 【结果获取】任务成功后返回文件下载地址,可下载识别结果文件。


2.任务提交 API

2.1 端点信息

项目内容
URLPOST /api/llm/v1/ocrdoc/submit
Content-Typeapplication/json
认证Authorization: Bearer <token>

2.2 请求参数

Header 参数
名称类型必填示例值
Content-Typestringapplication/json
AuthorizationstringBearer <API Key>
Body 参数
名称类型必填描述
file_urlstring待处理文件的 公网可访问 下载地址 (获取文件上传地址,请参考
ocr_typestring识别类别(目前只有DOC_PARING)

2.3 请求体示例

json
{
    "file_url": "https://oss.ksai.scnet.cn:58043/ocr/doc/2135155845..."
}

2.4 响应参数

参数名称参数类型描述
codeString状态码
msgString结果描述
outputObject任务提交结果
    task_statusString任务状态(pending 待执行、running 执行中、succeeded 成功、failed 失败、unknown 任务不存在或未知状态)
    task_idString任务唯一标识,用于后续结果查询
request_idString请求唯一标识

2.5 响应示例

成功响应
json
{
  "code": "0",
  "msg": "",
  "data": {
    "output": {
      "task_status": "pending",
      "task_id": "0385dc79-5ff8-4d82-bcb6-xxxxxx"
    },
    "request_id": "4909100c-7b5a-9f92-bfe5-xxxxxx"
  }
}
失败响应
json
{
  "code": "10011",
  "msg": "Burst rate limit exceeded for model"
}

3.任务状态查询 API

3.1 端点信息

项目内容
URLPOST /api/llm/v1/ocrdoc/result
认证Authorization: Bearer <token>

3.2 请求参数

Header 参数
名称类型必填示例值
AuthorizationstringBearer <API Key>
Body 参数
名称类型必填描述
task_idsarray任务ID 列表

2.3 请求体示例

json
{
  "task_ids": [
    "2056706028668284929","2056703208598626305"
  ]
}

3.3 响应参数

参数名称参数类型描述
codeString状态码
msgString结果描述
requestIdString请求唯一标识
outputObject任务结果
     taskIdString任务唯一标识
     taskStatusString任务状态
     submitTimeString任务提交时间
     endTimeString任务结束时间(成功/失败时返回)
     resultsArray识别结果文件下载地址列表(成功时返回)
     error_codeString错误码(失败时返回)
     error_messageString错误信息(失败时返回)

3.4 响应示例

任务成功
json
{
  "code": "0",
  "msg": "success",
  "data": [
    {
      "output": {
        "results": [
          "https://minio.fanhualuomu.top:8088/long-document-parsing/longDocumentParsing/results/2026/05/19/2056703208598626305/013_result_2056703208598626305.json?response-content-disposition=attachment%3B%20filename%3D%22013_result_2056703208598626305.json%22%3B%20filename%2A%3DUTF-8%27%27013_result_2056703208598626305.json&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=peihaojie%2F20260519%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260519T114740Z&X-Amz-Expires=43200&X-Amz-SignedHeaders=host&X-Amz-Signature=d414e3ff2f9074b036dac1855dad18a67792f3dcb2d2930d9f3605a4c90b111f"
        ],
        "task_id": "2056703208598626305",
        "task_status": "succeeded",
        "submit_time": "2026-05-19 19:47:11",
        "end_time": "2026-05-19 19:47:40"
      },
      "usage": {
        "image_count": 1
      },
      "request_id": "5e726f4f7d518259"
    },
    {
      "output": {
        "results": [
          "https://minio.fanhualuomu.top:8088/long-document-parsing/longDocumentParsing/results/2026/05/19/2056706028668284929/014_result_2056706028668284929.json?response-content-disposition=attachment%3B%20filename%3D%22014_result_2056706028668284929.json%22%3B%20filename%2A%3DUTF-8%27%27014_result_2056706028668284929.json&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=peihaojie%2F20260519%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260519T115855Z&X-Amz-Expires=43200&X-Amz-SignedHeaders=host&X-Amz-Signature=89707d665c259c91d00bedc289e4d20922b3b8936548d793d8b0e20b4e38e751"
        ],
        "task_id": "2056706028668284929",
        "task_status": "succeeded",
        "submit_time": "2026-05-19 19:58:24",
        "end_time": "2026-05-19 19:58:55"
      },
      "usage": {
        "image_count": 1
      },
      "request_id": "5e726f4f7d518259"
    }
  ]
}
任务进行中
json

{
  "code": "0",
  "msg": "",
  "data": [
    {
      "request_id": "8ae698ba-df2d-966c-abcf-xxxxxx",
      "output": {
        "task_id": "e56d806f-76f9-4037-aefa-xxxxxx",
        "task_status": "running",
        "submit_time": "2026-04-20 19:33:50.425"
      }
    }
  ]
}
任务失败
json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "request_id": "c61fe158-c0de-40f0-b4d9-964625119ba4",
      "output": {
        "task_id": "86ecf553-d340-4e21-xxxxxxxxx",
        "task_status": "failed",
        "submit_time": "2025-11-11 11:46:28.116",
        "end_time": "2025-11-11 11:46:28.255",
        "error_code": "10011",
        "error_message": "Burst rate limit exceeded for model xxx"
      }
    }
  ]
}

4.请求示例

4.1 任务提交 cURL 请求示例

shell
curl --location 'https://api.scnet.cn/api/llm/v1/ocrdoc/submit' \
--header 'Authorization: Bearer <API Key>' \
--header 'Content-Type: application/json' \
--data '{
    "file_url": "https://oss.ksai.scnet.cn:58043/ocr/doc/xxxxxx"
}'

4.2 任务状态查询 cURL 请求示例

shell
curl --location 'https://api.scnet.cn/api/llm/v1/ocrdoc/result' \
--header 'Authorization: Bearer <API Key>' \
--header 'Content-Type: application/json' \
--data '{
    "task_ids": ["2056706028668284929","2056703208598626305"]
}'

4.3 Python 请求示例

python
import requests
import time

API_KEY = "<API Key>"
BASE_URL = "https://api.scnet.cn/api/llm/v1/ocrdoc"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

# 提交任务
submit_payload = {
    "fileUrl": "https://oss.ksai.scnet.cn:58043/ocr/doc/xxxxxx"
}
response = requests.post(f"{BASE_URL}/submit", json=submit_payload, headers=headers)
submit_result = response.json()
print("提交结果:", submit_result)

task_id = submit_result["output"]["taskId"]

# 轮询查询任务状态
while True:
    result_response = requests.get(
        f"{BASE_URL}/result",
        params={"taskId": task_id},
        headers=headers
    )
    result = result_response.json()
    task_status = result["output"]["taskStatus"]

    if task_status == "SUCCEEDED":
        print("任务成功:", result)
        break
    elif task_status == "FAILED":
        print("任务失败:", result)
        break
    else:
        estimated = result["output"].get("estimatedSeconds", 10)
        print(f"任务处理中,预计等待 {estimated} 秒...")
        time.sleep(min(estimated, 10))

4.4 Go 请求示例

go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

func main() {
	baseURL := "https://api.scnet.cn/api/llm/v1/ocrdoc"
	bearerToken := "<API Key>"

	// 提交任务
	submitBody := map[string]string{
		"fileUrl": "https://oss.ksai.scnet.cn:58043/ocr/doc/xxxxxx",
	}
	bodyBytes, _ := json.Marshal(submitBody)

	req, _ := http.NewRequest("POST", baseURL+"/submit", bytes.NewBuffer(bodyBytes))
	req.Header.Set("Authorization", "Bearer "+bearerToken)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, _ := client.Do(req)
	respBody, _ := io.ReadAll(resp.Body)
	resp.Body.Close()

	var submitResult map[string]interface{}
	json.Unmarshal(respBody, &submitResult)
	fmt.Printf("提交结果: %s\n", string(respBody))

	taskId := submitResult["output"].(map[string]interface{})["taskId"].(string)

	// 轮询查询任务状态
	for {
		req, _ = http.NewRequest("GET", baseURL+"/result?taskId="+taskId, nil)
		req.Header.Set("Authorization", "Bearer "+bearerToken)

		resp, _ = client.Do(req)
		respBody, _ = io.ReadAll(resp.Body)
		resp.Body.Close()

		var result map[string]interface{}
		json.Unmarshal(respBody, &result)
		output := result["output"].(map[string]interface{})
		taskStatus := output["taskStatus"].(string)

		if taskStatus == "SUCCEEDED" {
			fmt.Printf("任务成功: %s\n", string(respBody))
			break
		} else if taskStatus == "FAILED" {
			fmt.Printf("任务失败: %s\n", string(respBody))
			break
		} else {
			fmt.Println("任务处理中...")
			time.Sleep(10 * time.Second)
		}
	}
}

4.5 Node.js 请求示例

javascript
const API_KEY = '<API Key>';
const BASE_URL = 'https://api.scnet.cn/api/llm/v1/ocrdoc';

async function submitTask() {
    const response = await fetch(`${BASE_URL}/submit`, {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${API_KEY}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            fileUrl: 'https://oss.ksai.scnet.cn:58043/ocr/doc/xxxxxx'
        })
    });

    if (!response.ok) {
        throw new Error(`提交任务失败 [状态码: ${response.status}]:${await response.text()}`);
    }

    const submitResult = await response.json();
    console.log('提交结果:', submitResult);
    return submitResult.output.taskId;
}

async function pollResult(taskId) {
    while (true) {
        const response = await fetch(`${BASE_URL}/result?taskId=${taskId}`, {
            method: 'GET',
            headers: {
                'Authorization': `Bearer ${API_KEY}`
            }
        });

        if (!response.ok) {
            throw new Error(`查询任务失败 [状态码: ${response.status}]:${await response.text()}`);
        }

        const result = await response.json();
        const taskStatus = result.output.taskStatus;

        if (taskStatus === 'SUCCEEDED') {
            console.log('任务成功:', result);
            return result;
        } else if (taskStatus === 'FAILED') {
            console.log('任务失败:', result);
            return result;
        } else {
            const estimated = result.output.estimatedSeconds || 10;
            console.log(`任务处理中,预计等待 ${estimated} 秒...`);
            await new Promise(resolve => setTimeout(resolve, Math.min(estimated, 10) * 1000));
        }
    }
}

async function main() {
    try {
        const taskId = await submitTask();
        await pollResult(taskId);
    } catch (error) {
        console.error('OCR 文档智能服务调用失败:', error.message);
    }
}

main();

5.结果文件字段说明

5.1 整体数据结构

模型响应数据采用严谨的层级化结构组织,其基本演进线路为: 任务响应(Task Response) -> 文档级数组(Documents) -> 页面级数组(Datas) -> 版面块数组(Blocks) -> 细粒度元素(Lines/Cells/Sub-blocks)

在页面级别,系统同时并行输出两条主线:

  1. blocks (高精结构化版面块):提供完全解耦、带有精准空间坐标定位的版面元素,适合需要复杂渲染或二次加工的原子化场景。
  2. md (面向LLM的整页Markdown):提供已完成版面重建、序列化语序还原的纯文本 Markdown,可直接用于大模型训练、微调或 RAG 向量化检索。

5.2 响应参数字典

5.2.1 页面级参数 (datas 数组元素)
参数名称参数类型是否必填描述
rotate_angleint页面旋转角度。当开启文档方向矫正功能时有效,顺时针方向。默认为不启动,值为 0
heightint模型服务接收并处理的文档影像实际高度(单位:像素)。
widthint模型服务接收并处理的文档影像实际宽度(单位:像素)。
blocksarray[核心] 单页版面解析结果集合。包含该页面中切分出的所有逻辑及视觉实体块。
mdobject[附加] 整页的 Markdown 聚合内容及关联静态资源映射表。

5.2.2 版面块参数 (blocks 数组实体)

每个 Block 代表页面上的一个独立区域(如一个段落、一张图表、一个表格或一个公式)。

参数名称参数类型适用类型描述
idint所有 Block版面分析块的唯一标识 ID。
注:由于后处理流程中会对部分零散块进行合并与逻辑优化,此 ID 为递增但非连续。
bboxarray[int]所有 Block版面块的两点绝对坐标信息。格式为 [左上角X, 左上角Y, 右下角X, 右下角Y]
typestring所有 Block版面块的一级分类。可选值:text, chart, formula, footer, header, image, seal, table
sub_typestring所有 Block版面块的二级分类。定义了更为精细的语义属性(详见第四章分类体系)。
sub_imgstring视觉/特定块版面块的局部抠图。采用 Base64 编码串,图片格式为 JPG
仅在 algorithmchartfooter_imageheader_imageimage 等二级分类中返回。
linesarray文本相关块文字识别(OCR)内容。存在于 text(一级)、footer(二级)、footnote(二级)、header(二级)、formula_number(二级)等包含文本内容的版面块中。
latexstring公式块独立公式的标准 LaTeX 源码。仅存在于 display_formula(二级分类)块中
htmlstring表格块经过版面重建后的标准 HTML 格式表格代码。完美支持跨行、跨列及复杂嵌套结构渲染。仅存在于 table 块中
cellsarray表格块表格内部单元格的多维微观信息集合。仅存在于 table 块中
blocksarray印章块嵌套的印章元素集合。仅存在于 seal 块中

5.2.3 细粒度子元素参数明细

A. 文本行对象 (lines 内部元素)

参数名称参数类型描述
bboxarray[int]当前文本行的两点绝对包围盒坐标 [左上角X, 左上角Y, 右下角X, 右下角Y]
polygonarray[array[int]]文本行多边形顶点坐标序列。通过 [[x1,y1], [x2,y2], [x3,y3], [x4,y4]] 精准适配倾斜文本或弧形排版。
textstring经过 OCR 识别并校对后的纯文字内容。
scorefloat文字识别结果的整体置信度。取值范围:0.01.0

B. 单元格对象 (cells 内部元素)

参数名称参数类型描述
idint单元格在当前表格内的序号。
bboxarray单元格的两点包围盒坐标。
polygonarray单元格的多边形包围边界。
rowsarray[int]单元格所占据的水平行逻辑点位。如 [0, 0] 表示仅占第 0 行;[0, 1] 表示跨第 0 到 1 行(合并单元格)。
colsarray[int]单元格所占据的垂直列逻辑点位。如 [1, 3] 表示该单元格跨第 1 到 3 列。

C. 印章集合对象 (seal -> blocks 内部元素)

参数名称参数类型描述
idint当前印章实体的序号。
class_idint印章形状分类 ID。映射关系如下:
0: 圆形章 (circle_stamp)、1: 椭圆章 (oval_stamp)、2: 矩形章 (rectangle_stamp)、3: 其他 (other)、4: 个人私章 (personal_stamp)、5: 三角章 (triangele_stamp)、6: 菱形章 (rhombus_stamp)。
class_namestring印章形状分类的英文标准别名(如 circle_stamp, oval_stamp )。
bboxarray印章实体的包围盒坐标。
scorefloat该印章检测与分类的整体置信度得分。
is_rotatedbool标识印章是否处于旋转状态。
color_typestring印章颜色分类。可选值映射:"红色", "蓝色", "黑色", "其他"
sub_imgstring印章区域独立切图,Base64 编码,JPG 格式。
linesarray印章内部包含的文字识别结果列表(内部包含 text, score, polygon 属性)。

5.2.4 Markdown 聚合参数 (md 对象)
参数名称参数类型描述
markdown_contentstring整页重构后的完整 Markdown 格式文本。版面块中的视觉元素(如 algorithmchartimage 等)会在文本对应上下文中被转化为标准的图片标签(例:![](images/image_id_sid.jpg)) 进行自然占位。
imagesarray当前页面中被 Markdown 引用到的所有图片/视觉块清单字典。

images 数组元素明细:

  • id: int - 静态资源文件序列号。
  • block_index: int - 该图片在最外层 blocks 数组中对应的索引下标,通过该指标可联动溯源原图的绝对物理坐标。
  • seal_block_index: int - 如果该图片源自印章,则指示其在印章集合内部的下标。
  • format: string - 图片输出格式,固定为 JPG
  • path: string - Markdown 文本内映射的相对路径前缀,默认固定为 images/
  • name: string - 该图片在 Markdown 中映射的文件名(如 image_id_sid.jpg)。
  • type: string - 源版面块的一级分类。
  • sub_type: string - 源版面块的二级分类。

5.4 版面块分类体系 (Type & Sub_type)

服务内置了一套完整、细腻的二级分类模型,能够对文档元素赋予极高行业纵深的语义:

一级分类 (type)二级分类 (sub_type)行业语义与典型应用场景说明
text
(普通文本)
abstract论文、白皮书、专利的摘要区域。
content专门在大型、多级目录块中出现的导航引导文本。
doc_title文章的主标题。通常在全篇或单章起始页具有最大字号。
text最基础、最普遍的正文文本段落。
vertical_text古籍、特定公文、海报或亚洲部分排版风格中的竖排文本。
paragraph_title段落标题、小节标题(有别于 doc_title),用于标识结构层级。
reference参考文献的外围总框(List 外框)。
reference_content参考文献的每一条具体文献条目(List Item)。
aside_text侧边栏注文本。通常位于页面边缘,提供补充信息、导读或延伸阅读。
figure_title图片 (image)、图表 (chart) 或 表格 (table) 的标题/说明文本 (Caption)。
vision_footnote图片、图表或表格底部的专属小字注解或数据来源说明 (Footnote)。
number页码。
chart
(图表)
chart包含数据可视化元素的区块,如柱状图、折线图、饼图、散点图等。
formula
(公式)
display_formula独立占据一整行或多行的核心数学/物理/化学公式。具有专属的大号字体和独立居中对齐特征。
formula_number配合 display_formula 使用的右侧公式编号,便于正文索引(如 (1-1))。
inline_formula夹杂在普通正文行内部的短小公式或数学符号。
footer
(页脚)
footer页脚标准文本。通常包含版权声明、会议名称等。
footer_image位于页脚区域的图标或装饰性窄图。
footnote页面级别的学术/说明脚注。通常位于页面最下端,用于对正文特定名词做原页补充。
header
(页眉)
header页眉标准文本。如期刊名称、当前章节名。
header_image页眉区域的特殊 Logo、横线或机构徽标。
image
(图像)
image标准的实景照片、手绘图、结构图等插图。
algorithm特殊的算法逻辑伪代码块或流程图,具备代码块的排版架构。
table
(表格)
table标准的行列式数据表格,内部同时携带高精度的 OCR 文本和多维拓扑结构。
seal
(印章)
seal合同、发票、公文中的实体印章区域。包含完整的形状、颜色、旋转及内部文字识别能力。

6.任务状态说明

状态描述
pending任务已提交,等待处理
running任务处理中
succeeded任务处理成功
failed任务处理失败
unknown任务不存在或未知状态

7.错误码说明

错误码描述
10001Unknown error
10002Unsupported modal type xxx
10003Unsupported provider xxx
10004Unsupported model xxx
10005Model xxx not found
10006Task not found
10007Concurrency conflict for request, please try again later
10008Provider xxx process error
10009Model xxx route failed
10010Illegal content detected by content approval
10011Burst rate limit exceeded for model xxx
10012An system error has occurred, please try again later
10013Parameter illegal
10014Incorrect API key provided
10015Task timeout, please try again later