Label Studio Document AI 界面模板:用 ReactCode 构建 PDF 文档理解标注界面
【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio
Label Studio 的 Interfaces(可编程界面)体系允许你用 React 代码在标注平台内嵌入完全自定义的标注界面。本文基于仓库中的 Document AI 模板文档,完整讲解这个面向 PDF 与文档图片的“文档理解”界面:它如何组合区域框选、hOCR 词级文本选择、表格结构编辑、文档/页面级分类与字段抽取五大能力,以及其 React 代码中参数模式、颜色映射、项目配置和结果输出的定制要点,帮助你在企业版环境中快速搭建 layout、OCR 与字段抽取(field extraction)工作流。
这个界面解决什么问题
Document AI 模板创建一个文档理解标注界面,用于对 PDF 和文档图片进行如下标注:
- 对文档区域(标题、作者、摘要、图表、表格、引用等)画边界框并打区域标签;
- 基于 hOCR 词级坐标选择真实文本片段(text span),并捕获转录文本;
- 用可拖拽的行列分隔线标注表格结构,支持合并单元格、逐格标签与自动提取的单元格转录;
- 建立区域之间的关联(例如把图注链接到图、把引用链接到参考文献条目);
- 对整个文档或逐页做类型分类。
产出的是结构化程度很高的标注结果,直接服务于 Document AI 团队的 layout 分析、OCR 训练与字段抽取场景。
两点使用前须知(来自模板文档的明确约束):
- 仅限企业版:Interfaces 只能在 Label Studio Enterprise 和 Starter Cloud 中使用;
- 必须复制后再编辑:从Interfaces > Templates进入,点击目标模板旁边的溢出菜单(overflow menu),选择Duplicate生成可编辑副本,然后才能修改。
该模板在仓库中的位置与入口:模板文档位于 docs/source/templates/interfaces-document-ai.md,并收录于 Interfaces 模板画廊 docs/source/templates/gallery_interfaces.ejs 的 “Document AI” 卡片中(分类为 Interfaces / Document AI)。
界面 UI 结构
整个界面分为三栏:左侧的工具/实体栏(tool/entity rail)、中间的文档视口(document viewport)、右侧的选项卡式检查器面板(inspector panel)。
工具与实体栏
左侧纵向栏分为两个堆叠区:
- Tools(工具):Select(
V)、Pan(H)、Bounding box(B)、Text span(T)、Words(P)、Table(R)。当前激活的工具决定在视口中“点击并拖拽”触发的动作。 - Entity labels(实体标签):
entityTypes中每一项对应一个按钮,前九个条目自动获得热键1-9。选中某个实体后,接下来创建的标注就会应用该标签。
文档视口
中间的阅读主区域,行为按文档来源区分:
- PDF 场景:页面通过 PDF.js 渲染,支持连续滚动、当前页指示、缩放控件和跳页导航;
- 图片场景:单页视口渲染任务数据中的
image字段; - 提供了
hocr字段时:会叠加词级位置信息,使Text span和Words工具能够选中真实文本;在文本上直接画的边界框还会自动捕获一份transcription; - 已有标注渲染为彩色覆盖层,选中区域显示八个方向的缩放手柄;
- 表格以可拖拽的行列分隔线呈现,右键点击单元格打开逐格标签菜单,并暴露 merge(合并)操作。
检查器面板
右侧栏提供五个选项卡:
| 选项卡 | 作用 |
|---|---|
| Annotations | 列出所有区域:实体标签、页码范围、转录预览,以及每行的删除控件 |
| Transcription | 编辑所选区域的转录文本;当沙箱 bundle 提供documentAI.recognizeImage时显示 OCR 按钮 |
| Classifications | 可切换的 chip:Document type(取自documentTypes)与逐页Page type(取自pageTypes) |
| Links | 查看和创建区域间链接;每条链接以linkedTo: [targetId, ...]形式存储在源区域上 |
| Extraction | 可配置的抽取模式(schema),把实体类型绑定到命名字段(例如Authors→ 所有标为Author的区域),保存前可预览结构化对象 |
面板顶部还有一个搜索栏,可按转录文本或实体标签过滤区域。
React 代码:四个最值得定制的模块
完整Screen.jsx源码约 9,400 行,模板文档挑选了日常定制最可能涉及的四部分:任务数据参数、实体颜色表、内部PROJECT_CONFIG块(工具、特性、抽取模式)、以及写回 Label Studio 的结果结构。
界面参数 paramsSchema
在 Interface 配置中设置或重命名参数,可以指向不同的任务字段,或替换三套标签集(区域标签、文档类型、页面类型)。默认值与下文示例输入对应:
const paramsSchema = { type: "object", title: "Document AI Parameters", properties: { pdfField: { type: "dataField", default: "pdf", description: "Task data field containing the PDF URL", }, entityTypes: { type: "labels", description: "Labels available for annotating document regions", default: [ { name: "Title", color: "#10b981" }, { name: "Author", color: "#8b5cf6" }, { name: "Abstract", color: "#06b6d4" }, { name: "Section Header", color: "#f59e0b" }, { name: "Paragraph", color: "#64748b" }, { name: "Figure", color: "#10b981" }, { name: "Table", color: "#f97316" }, { name: "Citation", color: "#6366f1" }, // ... ], }, documentTypes: { type: "labels", description: "Document-level classification labels", default: [ { name: "Research Paper", color: "#3b82f6" }, { name: "Review Article", color: "#8b5cf6" }, { name: "Technical Report", color: "#10b981" }, // ... ], }, pageTypes: { type: "labels", description: "Page-level classification labels", default: [ { name: "Title Page", color: "#10b981" }, { name: "Abstract", color: "#06b6d4" }, { name: "Content", color: "#3b82f6" }, { name: "Tables", color: "#f97316" }, // ... ], }, }, };除了显式声明的pdfField,界面还会从输入 schema 中读取imageField与hocrField,默认值分别为image和hocr。任务数据中pdf或image二者必须至少提供一个。
实体颜色映射 ENTITY_COLORS
ENTITY_COLORS是模块级颜色表,被getEntityColor、toScreenRegionFromAnn以及视口覆盖层共同使用。如果重命名或新增标签,需要同步维护这张表——注意它使用实体的内部id(小写、snake_case),而不是面向用户的label:
const ENTITY_COLORS = { title: "#10b981", author: "#8b5cf6", affiliation: "#a855f7", abstract: "#06b6d4", section: "#f59e0b", paragraph: "#64748b", figure: "#10b981", figure_caption: "#34d399", table: "#f97316", table_caption: "#fb923c", equation: "#ec4899", citation: "#6366f1", reference: "#818cf8", list: "#14b8a6", footnote: "#78716c", header: "#9ca3af", footer: "#6b7280", page_number: "#525252", classifications: "#94a3b8", classificationMetadata: "#94a3b8", }; function getEntityColor(entityType) { return ENTITY_COLORS[entityType] || "#94a3b8"; }未命中的实体类型会回退到中性灰#94a3b8,这也是classifications/classificationMetadata两个元数据类实体使用的颜色。
PROJECT_CONFIG:工具、特性与抽取模式
在DocumentLabelingInterface内部,PROJECT_CONFIG是工具面板、特性开关和默认字段抽取模式的唯一事实来源(single source of truth)。Interface 设置中的params只覆盖entityTypes、documentTypes、pageTypes三项;其余内容(tools、features、fields)都需要在这个代码块里修改:
const PROJECT_CONFIG = { name: "Scientific Paper Labeling", contentType: "pdf", tools: { select: true, // Selection tool (V) pan: true, // Pan/hand tool (H) box: true, // Bounding box tool (B) span: true, // Text span selection (T) words: true, // Word selection tool (P) table: true, // Table annotation (R) }, features: { documentClassification: true, pageClassification: true, linking: true, transcription: true, tableEditing: true, search: true, extraction: true, }, // entityTypes, documentTypes, pageTypes are seeded here but // are overridden by params when the Interface is configured. fields: [ { id: "paper_title", label: "Paper Title", type: "string" }, { id: "authors", label: "Authors", type: "string" }, { id: "venue", label: "Venue/Journal", type: "string" }, { id: "year", label: "Year", type: "string" }, ], };features的七个开关与检查器面板的一一对应关系:documentClassification/pageClassification对应 Classifications 选项卡,linking对应 Links,transcription对应 Transcription,tableEditing对应表格分隔线编辑,search对应面板顶部搜索栏,extraction对应 Extraction 选项卡。要裁剪界面,直接关掉对应开关即可。
结果结构 getResults
getResults为每个区域输出一条 Label Studio result。所有 result 统一使用from_name: "documentai"和type: "documentai",完整标注负载(包括各类型专有字段)整体序列化进value,再由value内的type字段区分四种形态:
function getResults(regions, _relations) { return regions .filter(r => r._documentAI) .map(r => ({ id: r.id, from_name: "documentai", to_name: "document", type: "documentai", value: { ...r._documentAI }, origin: "manual", })); }value内的四种标注形态:
- Bounding box—
{ type: "boundingBox", entityType, x, y, w, h, page, startPage, endPage, transcription, linkedTo? } - Text span—
{ type: "textSpan", entityType, x, y, w, h, highlightRects, selectedText, transcription, spans, page, startPage, endPage } - Table—
{ type: "table", entityType: "table", x, y, w, h, tableData: { rows, cols, headerRows, headerCols, cellLabels, mergedCells, cellTranscriptions } } - Classification metadata—
{ type: "classificationMetadata", entityType: "classifications", documentClassification, pageClassifications }
坐标x、y、w、h均为页内相对百分比(0–100),不是像素值——这与 Label Studio 其他图像标注的归一化坐标约定一致,便于跨分辨率复用标注。
示例输入:任务数据格式
界面期望的data对象包含一个文档来源——pdf(PDF URL)或image(图片 URL)——以及可选的hocr字符串(为 text span 和单词拾取提供词级坐标)。字段名可通过pdfField、imageField、hocrField配置。
{ "data": { "pdf": "https://example.com/papers/2026-05-attention-is-all-you-still-need.pdf", "hocr": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n <body>\n <div class=\"ocr_page\" id=\"page_1\" title=\"bbox 0 0 800 1000\">\n <span class=\"ocrx_word\" title=\"bbox 80 140 480 188\">Attention</span>\n <span class=\"ocrx_word\" title=\"bbox 490 140 560 188\">Is</span>\n <span class=\"ocrx_word\" title=\"bbox 570 140 670 188\">All</span>\n <!-- ... more ocrx_word entries ... -->\n </div>\n </body>\n</html>" } }纯图片任务则用imageURL 替换pdf:
{ "data": { "image": "https://example.com/scans/invoice-2026-05-13.png", "hocr": "<?xml version=\"1.0\" encoding=\"UTF-8\"?> ... </html>" } }hOCR 采用标准ocr_page/ocrx_word结构:每个词是一个span,title属性携带bbox x1 y1 x2 y2(像素坐标,页内坐标系),界面据此把词级选择落到真实文本上。
示例输出:四种形态齐全的标注结果
保存后的标注中每个区域对应一条 result。下面的示例同时展示了全部四种形态:标题的 bounding box(带linkedTo引用)、摘要的 text span、第 3 页的表格,以及一条承载文档级与逐页级分类的 classification-metadata:
{ "result": [ { "id": "1747156800000", "from_name": "documentai", "to_name": "document", "type": "documentai", "value": { "id": 1747156800000, "type": "boundingBox", "entityType": "title", "x": 12.5, "y": 8.2, "w": 75.0, "h": 4.8, "page": 1, "startPage": 1, "endPage": 1, "transcription": "Attention Is All You Still Need", "linkedTo": [1747156800001] } }, { "id": "1747156800002", "from_name": "documentai", "to_name": "document", "type": "documentai", "value": { "id": 1747156800002, "type": "textSpan", "entityType": "abstract", "x": 12.4, "y": 18.6, "w": 75.3, "h": 11.2, "highlightRects": [ { "x": 12.4, "y": 18.6, "w": 75.3, "h": 1.6 }, { "x": 12.4, "y": 20.4, "w": 75.3, "h": 1.6 } ], "selectedText": "We revisit the original Transformer architecture and find that...", "transcription": "We revisit the original Transformer architecture and find that...", "spans": ["w_42", "w_43", "w_44", "w_45"], "page": 1, "startPage": 1, "endPage": 1 } }, { "id": "1747156800003", "from_name": "documentai", "to_name": "document", "type": "documentai", "value": { "id": 1747156800003, "type": "table", "entityType": "table", "x": 14.0, "y": 42.0, "w": 72.0, "h": 22.0, "page": 3, "startPage": 3, "endPage": 3, "tableData": { "rows": [0, 18, 36, 54, 72, 100], "cols": [0, 30, 55, 78, 100], "headerRows": [0], "headerCols": [0], "mergedCells": [], "cellLabels": { "0,0": "Model", "0,1": "Params", "0,2": "BLEU", "0,3": "Notes" }, "cellTranscriptions": { "1,0": "Baseline", "1,1": "65M", "1,2": "26.4", "2,0": "Ours", "2,1": "65M", "2,2": "27.9", "3,0": "Ours-Big", "3,1": "213M", "3,2": "29.1" } } } }, { "id": "1747156800004", "from_name": "documentai", "to_name": "document", "type": "documentai", "value": { "id": 1747156800004, "type": "classificationMetadata", "entityType": "classifications", "documentClassification": "research_paper", "pageClassifications": { "1": "title_page", "2": "abstract", "3": "tables", "4": "content", "5": "references" } } } ] }几个值得注意的细节:
tableData.rows/cols是边界百分比数组(示例中rows: [0, 18, 36, 54, 72, 100]表示 5 行),而不是行列计数;headerRows/headerCols指出哪些是表头行列;cellLabels与cellTranscriptions以"row,col"字符串为键;- text span 的
highlightRects是逐行高亮矩形数组,spans记录被选中词的 hOCR 词 id; pageClassifications以页码字符串为键,值是与pageTypes标签对应的 snake_case id(如title_page),与documentClassification的取值风格一致;- 跨页区域通过
startPage/endPage表达,多页 bounding box 也依赖这两个字段。
实现佐证:Interfaces 在 Label Studio 中的承载方式
结合仓库源码与文档结构,可以确认该模板的运行载体是<ReactCode>标签(旧名 ReactApp):
- 标签文档 docs/source/tags/reactcode.md 说明:
<ReactCode>把自定义标注 UI 嵌入 Label Studio,同时把输出保存为常规的 Label Studio regions/results,从而继续复用平台的标注管理、审核工作流与数据导出能力;该标签同样标注为仅企业版可用。 - 从源码结构看,web/libs/editor/src/tags/Custom.jsx 是标签的实际实现入口,文件头注释表明“标签已更名为 ReactCode,两个名称都受支持”。
- 本文的
getResults输出(from_name/to_name/value)正是ReactCode标签文档中“outputs 参数”约定下的结果序列化形式:from_name对应标签的name(documentai),to_name对应任务数据来源字段(document)。 - 更多 Interfaces 模板的总览见 docs/source/guide/interfaces.md,以及画廊文件 docs/source/templates/gallery_interfaces.ejs(与 Document AI 同列的还有 Doclang、LiDAR、Agent Evaluation 等模板)。
落地要点小结
- 前置条件:Label Studio Enterprise 或 Starter Cloud;从 Interfaces > Templates 中Duplicate出可编辑副本后再改代码。
- 数据接入:任务
data至少提供pdf或image;强烈建议同时提供hocr,否则 text span / Words 工具失去词级定位能力,边界框也不会自动捕获转录。字段名可用pdfField/imageField/hocrField覆盖默认值。 - 定制路径:改标签集走 Interface 配置(
paramsSchema);改工具、特性开关、抽取fields走代码中的PROJECT_CONFIG;改视口颜色必须同步ENTITY_COLORS且注意键是 snake_case 内部 id。 - 下游对接:导出的每条 result 都是
type: "documentai",需按value.type分派处理四种形态;坐标是 0–100 的页内百分比,换算像素时需结合该页渲染尺寸。
【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考