Skip to content

通过回调使用自定义 AI 模型

概述

从 SDK v4.1.0 开始,ComPDF Conversion SDK 暴露了基于回调的扩展点,允许您插入自己的 AI 推理引擎来进行 OCR、版面分析和表格识别。您可以不再依赖通过 CPDF_SetDocumentAIModel 加载的内置 DocumentAI 模型,而是使用任何模型或服务运行推理,并将结果以 JSON 字符串返回给 SDK。

CConvertCallback 上注册了相关回调对后,SDK 会跳过该能力的内置模型调用,转而使用您的 JSON 输出。如果回调对为 NULL,SDK 会回退到内置的 DocumentAI 模型(如果可用)。

回调对

每种 AI 能力使用两个回调:一个触发器回调(由 SDK 调用,传入临时目录中保存为 PNG 的页面图像路径)和一个结果获取器回调(紧接着由 SDK 调用以检索 JSON 字符串)。

能力触发器回调结果获取器回调触发条件
OCRocrget_ocr_resultenable_ocr = true
版面分析layoutget_layout_resultenable_ai_layout = trueenable_ocr = true
表格识别tableget_table_resultenable_ai_table_recognition = true 且版面分析检测到表格区域

规则:

  • 触发器接收 PNG 文件的 UTF-8 路径。推理成功返回 true,返回 false 则 SDK 忽略该页面结果。
  • 获取器必须返回 UTF-8 JSON C 字符串。指针必须在 SDK 完成解析之前保持有效,通常直到同一获取器的下一次调用。
  • 每种能力的两个回调必须同时设置。若只提供其中一个,SDK 将回退到内置路径。
  • JSON 中的坐标必须位于触发器接收到的图像的像素空间中,左上角为原点,X 向右,Y 向下。

示例

c
#include <stdbool.h>
#include <stddef.h>

#include "compdf_common_c.h"
#include "compdf_conversion_c.h"

static char g_ocr_json[4096];
static char g_layout_json[4096];
static char g_table_json[4096];

static bool MyOcrTrigger(const char* image_path)
{
    return RunMyOcrModel(image_path, g_ocr_json, sizeof(g_ocr_json));
}

static const char* MyOcrGetter(void)
{
    return g_ocr_json;
}

static bool MyLayoutTrigger(const char* image_path)
{
    return RunMyLayoutModel(image_path, g_layout_json, sizeof(g_layout_json));
}

static const char* MyLayoutGetter(void)
{
    return g_layout_json;
}

static bool MyTableTrigger(const char* image_path)
{
    return RunMyTableModel(image_path, g_table_json, sizeof(g_table_json));
}

static const char* MyTableGetter(void)
{
    return g_table_json;
}

int main(void)
{
    CPDF_LicenseVerify("LICENSE_KEY", "device_id", "app_id");
    CPDF_Initialize(CPDF_TEXT("resource"));

    CConvertCallback callback = {0};
    callback.ocr = MyOcrTrigger;
    callback.get_ocr_result = MyOcrGetter;
    callback.layout = MyLayoutTrigger;
    callback.get_layout_result = MyLayoutGetter;
    callback.table = MyTableTrigger;
    callback.get_table_result = MyTableGetter;

    COCRLanguage languages[] = {e_CENGLISH};

    CConvertOption option = CPDF_DefaultConvertOption();
    option.enable_ocr = true;
    option.enable_ai_layout = true;
    option.languages = languages;
    option.language_count = 1;

    CPDF_StartPDFToWord(CPDF_TEXT("input.pdf"), CPDF_TEXT(""), CPDF_TEXT("output.docx"), option, &callback);
    CPDF_Release();
    return 0;
}

您可以只注册想要覆盖的能力,其余保留 NULL 以保持内置行为。

线程安全与生命周期

  • 回调从 SDK 转换线程调用。如果模型引擎在多处共享,请以线程安全的方式实现。
  • 位于 image_path 的 PNG 图像存放在 SDK 临时目录中,触发器返回后可能会被很快删除。请在返回之前复制或处理它。
  • 获取器返回的 JSON 指针必须在同一获取器再次被调用或转换任务结束之前保持有效。

OCR 结果 JSON 模式

get_ocr_result 返回。SDK 会根据 words[](如果提供)或通过均匀分割 span 矩形来填充每个 text_spans[].chars[]

json
{
  "text_spans": [
    {
      "text": "Hello World",
      "confidence": 0.98,
      "rotation": 0.0,
      "rect": { "left": 120, "top": 80, "right": 320, "bottom": 110 },
      "style": {
        "font_size": 18.0,
        "font_color": { "r": 0, "g": 0, "b": 0 }
      },
      "words": [
        { "text": "Hello", "rect": { "left": 120, "top": 80, "right": 200, "bottom": 110 } },
        { "text": "World", "rect": { "left": 210, "top": 80, "right": 320, "bottom": 110 } }
      ]
    }
  ]
}
字段类型必需描述
text_spansarray页面上识别的文本跨度。
textstring跨度的 UTF-8 文本内容。
confidencenumber0.0 – 1.0。低于 0.1 的跨度将被丢弃。
rotationnumber文本旋转角度(度数)。默认 0。
rectobject图像像素中的边界框(left/top/right/bottom)。
style.font_sizenumber估计的字体大小(像素)。
style.font_colorobject{ r, g, b } 0 – 255。
wordsarray逐词边界框。若省略,SDK 将均匀分割 span 矩形。对于 CJK 与拉丁文混合行,强烈建议提供以正确排列字形间距。

版面分析结果 JSON 模式

get_layout_result 返回。置信度低于 0.45 的对象将被丢弃。

json
{
  "objects": [
    { "type": "title", "confidence": 0.95, "rect": { "left": 60, "top": 50, "right": 540, "bottom": 90 } },
    { "type": "paragraph", "confidence": 0.97, "rect": { "left": 60, "top": 100, "right": 540, "bottom": 220 } },
    { "type": "figure", "confidence": 0.92, "rect": { "left": 80, "top": 240, "right": 520, "bottom": 460 } },
    { "type": "table", "confidence": 0.93, "rect": { "left": 60, "top": 480, "right": 540, "bottom": 700 } }
  ]
}

支持的 type 值:

含义
paragraph正文段落
title标题
figure图像或图形
figure_title图形标题头
figure_caption图形标题文本
table表格区域。表格是否有边框由表格识别阶段决定,而非由版面标签决定。
table_title表格标题头
table_caption表格标题文本
ordered_list有序列表
unordered_list无序列表
catalogue目录
formula数学公式
code代码块
algorithm算法块
header页眉
footer页脚
page_number页码
reference参考文献或引用

未列出的 type 值对应的对象将被忽略。请使用此表中的值作为自定义输出中的规范版面标签。

表格识别结果 JSON 模式

get_table_result 返回,每个检测到的表格区域返回一次。多边形使用八个整数 [x0, y0, x1, y1, x2, y2, x3, y3],顺序为左上、右上、右下、左下。

json
{
  "type": "table_with_line",
  "position": [60, 480, 540, 480, 540, 700, 60, 700],
  "rows": 3,
  "cols": 2,
  "angle": 0.0,
  "height_of_rows": [40, 60, 60],
  "width_of_cols": [200, 280],
  "table_cells": [
    {
      "start_row": 0,
      "end_row": 0,
      "start_col": 0,
      "end_col": 0,
      "cell_background_color_r": 240,
      "cell_background_color_g": 240,
      "cell_background_color_b": 240,
      "position": [60, 480, 260, 480, 260, 520, 60, 520]
    }
  ]
}
字段类型描述
typestringtable_with_line 表示有边框的表格;其他值视为非标准(无边框)表格。
positionint[8]图像像素中的表格多边形。
rows / colsint行数 / 列数。
anglenumber倾斜角度(度数)。
height_of_rowsint[]每行像素高度(长度 = rows)。
width_of_colsint[]每列像素宽度(长度 = cols)。
table_cells[]array每个合并单元格一条记录。
start_row / end_rowint单元格的行跨度(含)。
start_col / end_colint单元格的列跨度(含)。
cell_background_color_*int单元格背景颜色分量(0 – 255)。
positionint[8]图像像素中的单元格多边形。

提示:验证 JSON

如果需要参考输出进行对比,可以先使用内置 DocumentAI 模型运行一次转换。SDK 内部使用相同的 JSON 结构,因此您的自定义输出应遵循相同的结构。