从扫描件里取出人会读的那个顺序的文本
用 POST /ocr/text 提取阅读顺序纯文本,并按需获取仅含内容的 blocks、按 path 索引的原图坐标和明确的复核清单。
“只要把文字给我”听起来是最简单的 OCR 请求,却也最容易悄悄破坏搜索索引。视觉 OCR 可能找对了每个词,却按检测顺序返回:左栏第一行、右栏第一行、再回到左栏。系统没有报错,文档却不再是人能顺着读的文档。
POST /ocr/text 把这个问题与字段抽取、Markdown 转换分开处理。默认的 useLlm: true 会按人的阅读顺序重排区块,并重新连接因换行断开的内容。同时,文字和来源位置仍与 Vision 观测交叉核对,不会把语言模型的转写无条件当作真值。
控制请求的两个开关
useLlm 默认为 true。多栏排版、侧栏、倾斜扫描,或要交给人阅读的文字,都应保持开启。设为 false 时会跳过 LLM 步骤,按 raw OCR 顺序返回纯 Vision 转写;该路径仍会返回文档级校验对象。
includeBlocks 默认为 false。只要全文时读取 data.values.text 即可。需要自行分块、在原图高亮或制作复核界面时再开启。开启后会增加仅含内容的 data.values.blocks、形如 data.cells["blocks[0]"] 的元数据,以及 data.review.flagged 中的区块 path。
一次请求
下面开启 includeBlocks,以便把待复核文字追溯到原图。认证和全部参数见 API 文档。
curl -X POST https://api.space-ocr.com/ocr/text \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image": "https://example.com/page.jpg",
"imageType": "url",
"useLlm": true,
"includeBlocks": true
}'{
"status": "success",
"data": {
"values": {
"text": "樱花贸易有限公司\n发票\n合计 1,451元",
"blocks": [
{
"text": "樱花贸易有限公司"
},
{
"text": "发票\n合计 1,451元"
}
]
},
"cells": {
"blocks[0]": {
"box": {
"xmin": 60,
"ymin": 48,
"xmax": 470,
"ymax": 92
},
"quad": [
{
"x": 60,
"y": 48
},
{
"x": 470,
"y": 48
},
{
"x": 470,
"y": 92
},
{
"x": 60,
"y": 92
}
],
"verified": true,
"review": null,
"evidence": {
"text_match": true,
"source": "token_id"
}
},
"blocks[1]": {
"box": {
"xmin": 58,
"ymin": 190,
"xmax": 510,
"ymax": 274
},
"quad": [
{
"x": 58,
"y": 190
},
{
"x": 510,
"y": 190
},
{
"x": 510,
"y": 274
},
{
"x": 58,
"y": 274
}
],
"verified": false,
"review": {
"reasons": [
"text_mismatch"
]
},
"evidence": {
"text_match": false,
"source": "char_matcher_fallback"
}
}
},
"review": {
"unit": "block",
"total": 2,
"boxed": 2,
"verified": 1,
"flagged": [
{
"path": "blocks[1]",
"reasons": [
"text_mismatch"
]
}
],
"by_reason": {
"text_mismatch": 1
},
"coverage": {
"recovered_blocks": 0,
"vision_tokens": 8,
"tokens_claimed": 8,
"token_coverage": 1
}
},
"image": {
"width": 1654,
"height": 2339
},
"source": "llm"
}
}按职责读取响应
data.values.text是全文。开启 blocks 后,同样内容还会按{ text }单元放在data.values.blocks,内容中不混入坐标。data.cells[path]是原图证据的旁路数据。box与quad使用 0~1000 页面坐标,可结合data.image.width和height投影到处理后图像。verified表示区块与对应位置的 Vision 文字在规范化后是否一致,不是准确率百分比。data.review.flagged是实际复核清单。每个path都能直接查找data.cells[path],review.reasons给出建议检查的原因。data.source在阅读顺序路径中为llm,在 Vision 路径中为vision。
索引程序可以只消费 values.text,复核界面则消费 review 和 cells,无需从正文中拆坐标。
const { data } = await response.json();
indexDocument(data.values.text);
for (const flag of data.review.flagged) {
const cell = data.cells?.[flag.path];
queueForReview({
path: flag.path,
reasons: flag.reasons,
box: cell?.box,
quad: cell?.quad,
image: data.image,
});
}回退不会被隐藏。 LLM 阅读顺序步骤失败时,端点不会把它变成 OCR 错误,而会返回 Vision 转写。此时 data.source 为 "vision",原因写入 data.warning。未被任何区块认领的 Vision token 也可能作为 cells[path].evidence.source: "unclaimed_tokens" 的回收区块附加,从而暴露遗漏而不是悄悄丢弃。
选纯文本还是 Markdown
全文检索、向量化、差异比较、无障碍信息流等场景,如果不需要把标题和表格保留成独立类型,纯文本更合适。需要结构时改用 POST /ocr/markdown;图像转 Markdown 指南介绍了它的元素响应。坐标与复核元数据可继续阅读 OCR 原图坐标。
- 选择阅读顺序路径把图像发送到 POST /ocr/text。阅读顺序重要时保留默认 useLlm:true,只有 raw Vision 顺序可接受时才设为 false。
- 需要来源证据时请求 blocks设置 includeBlocks:true,获取 values.blocks、按 path 索引的 cells 和区块级 review;只需全文时保持默认值。
- 处理明确的复核清单遍历 data.review.flagged,用 data.cells[flag.path] 取出 box 或 quad,并绘制在 data.image 所描述的图像框架上。
- 记录实际转写路径把 data.source 与正文一起保存;自动回退为 vision 时向操作者显示 data.warning。