- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
本文是一篇聚焦于 xberg(Rust 内核的多语言文档智能库)PHP 绑定的实战指南,核心主题是force_ocr配置项:当 PDF 已经携带原生文本层(native text layer)时,如何强制 xberg 仍然对每一页执行 OCR 识别。读完本文,你将掌握 PHP 侧构造ExtractInput、配置 OCR 后端与语言、解读ExtractionResult的完整方法,并理解force_ocr在 xberg 底层配置系统、OCR 流水线与契约测试中的真实行为,从而在扫描件、伪文本层 PDF 等场景下稳定获得预期的提取结果。
为什么需要 force_ocr:理解 xberg 的默认 OCR 策略
在讨论force_ocr之前,先弄清 xberg 默认的 OCR 触发逻辑,否则很难判断何时需要强制。
从配置模型看,xberg 的 PDF 提取默认采用OcrStrategy::Auto(crates/xberg/src/core/config/ocr.rs中定义):只有原生文本层未通过质量检查的页面才会被送入 OCR。换言之,一个带有完整可搜索文本层的 PDF,默认会直接走原生文本提取,根本不会调用 OCR 引擎——这是性能上的合理默认,因为原生文本又快又准。
但现实中的 PDF 并不总是"文本层即真相":
- 扫描仪侧车文本(OCR sidecar):扫描件常带有一层由扫描仪自动生成的"隐形"OCR 文本,其坐标错位、文字残缺,甚至与页面视觉内容完全不符。
Auto策略下,只要这层文本通过质量门禁,xberg 就会按原生文本处理,提取出的内容可能不可用; - 伪文本层:某些排版工具生成的 PDF 文本层与渲染结果不一致,或仅包含页眉、页脚、页码等零星文字;
- 统一流水线需求:团队希望无论 PDF 是否有文本层,都统一走同一套 OCR 流水线,以便获得一致的输出结构与置信度信息。
force_ocr正是为这些场景设计的开关。其字段定义位于 提取核心配置(crates/xberg/src/core/config/extraction/core.rs),注释言简意赅:"Force OCR even for searchable PDFs"(即使 PDF 可搜索也强制 OCR)。置为true后,OCR 的触发不再依赖页面文本质量判定,而是作用于 PDF 的每一页。
PHP 调用示例:一份可直接运行的完整代码
关联文档 ocr_force_all_pages.md 给出了 xberg PHP 绑定中最直接的force_ocr用法,这是由 alef 自动生成的跨语言契约测试片段(frontmatter 标注level: typecheck、side_effect: server),意味着它同时承担着语法校验与行为契约的双重职责。完整代码如下:
<?php declare(strict_types=1); require_once __DIR__ . '/vendor/autoload.php'; use Xberg\Xberg; use Xberg\ExtractInput; $input = \Xberg\ExtractInput::from_json(json_encode([ "kind" => "uri", "mimeType" => "application/pdf", "uri" => "https://example.com/pdf/fake_memo.pdf", ])); $result = Xberg::extract($input, [ "force_ocr" => true, "ocr" => [ "backend" => "tesseract", "enabled" => true, "language" => ["eng"], ], ]); var_dump($result->getResults()[0]->content);逐行拆解这段代码,它实际覆盖了 xberg PHP 绑定调用的完整链路:
- 输入构造:
\Xberg\ExtractInput::from_json()接收一段 JSON 字符串来构建提取输入。示例中kind为"uri",配合mimeType: "application/pdf"与uri指向远程 PDF。xberg 的输入模型支持多种kind(如uri、bytes等),from_json这种构造方式使 PHP 侧可以直接复用其他语言(Rust/Python/TypeScript)熟悉的 JSON 输入格式。 - 提取调用:
Xberg::extract($input, $config)是核心入口,第二个参数是配置数组。这里的配置包含了两个层次——顶层开关force_ocr,以及内嵌的ocr配置块。 - 结果读取:返回值提供
getResults()方法,返回结果数组;示例取第一个元素([0])的content属性,即该文档提取出的文本内容。契约测试对应的断言(见下文)要求results[0].content中出现指定的 OCR 词汇,验证了强制 OCR 确实产出了基于图像识别的文本。
配置参数详解:force_ocr 与 ocr 配置块
上述示例中的配置参数并非随意书写,每一个都与 xberg 的配置模型一一对应。结合源码可以给出更完整的参数语义:
顶层:force_ocr与相关开关
| 参数 | 类型 | 默认值 | 语义 |
|---|---|---|---|
force_ocr | boolean | false | 强制对 PDF 每一页执行 OCR,即使页面已有原生文本层 |
force_ocr_pages | number[] | 无 | 仅强制对指定页码(从 1 开始计)的页面 OCR,未列出的页面仍走原生文本提取;与force_ocr同时配置时被force_ocr覆盖 |
disable_ocr | boolean | false | 完全禁用 OCR;与force_ocr互斥,不可同时为true |
ocr_strategy | enum | Auto | 在force_ocr与force_ocr_pages均未生效时决定哪些页面需要 OCR |
这些开关均定义在 提取核心配置 中。特别值得注意两点:
force_ocr_pages的页码是1-indexed的(源码注释明确要求>= 1),并且重复页码会被自动去重。在 OCR 流水线实现 中,传入0会被直接忽略并输出一条force_ocr_pages contains 0; page numbers are 1-indexed, ignoring的告警日志,这是新手最容易踩的坑;disable_ocr与force_ocr的互斥约束在配置校验阶段就会被拦截(Cannot be true simultaneously with force_ocr),所以不要试图用"先禁用再强制"的方式绕过,直接报验证错误。
ocr配置块:后端与语言
示例中的ocr块包含三个字段:
| 字段 | 示例值 | 说明 |
|---|---|---|
backend | "tesseract" | OCR 后端引擎。xberg 是支持多 OCR 后端的(例如 tesseract、paddle 等),后端是否可用取决于编译特性与运行时注册 |
enabled | true | OCR 功能的显式开关,与force_ocr配合时通常显式置为true |
language | ["eng"] | 识别语言列表,数组形式支持多语言;示例指定英语 |
从源码模型看,ocr字段的类型是Option<OcrConfig>(提取核心配置)。当force_ocr为true而ocr块缺失时,xberg 会使用OcrConfig::default()的默认阈值与自动注册的后端继续工作(提取核心配置 中ocr_enabled = !disable_ocr && (ocr.is_some() || force_ocr)的逻辑表明force_ocr本身即可点亮 OCR 路径),因此示例中显式给出backend与language的目的是把行为钉死:明确的引擎、明确的语言,不依赖运行时环境猜测。
契约测试:如何证明 force_ocr 真的生效
文档片段背后对应着一个真实可运行的契约测试:fixtures/contract/ocr_force_all_pages.json。它属于 xberg 的契约测试体系(fixtures/contract/目录),用于跨语言验证 API 行为一致性。该 fixture 的关键内容:
- mock 服务:测试启动一个本地 mock HTTP 服务,
/pdf/fake_memo.pdf路径返回content-type: application/pdf,正文来自仓库内的fake_memo.pdf测试文档——这解释了 PHP 示例中 URI 为何指向https://example.com/pdf/fake_memo.pdf; - 配置:与 PHP 示例完全一致的
{"force_ocr": true, "ocr": {"enabled": true, "backend": "tesseract", "language": ["eng"]}}; - 断言(
assertions部分):results[0].mime_type等于"application/pdf"(提取结果保留了原文档 MIME 类型);results[0].content包含"bottles"、"blankets"、"laptops"三个词(contains_all)。
第二组断言正是"强制 OCR"行为的直接证据:只有当 tesseract 对 PDF 渲染出的每一页图像执行了识别,content才会包含这些来自页面图像的词汇;如果force_ocr未生效而走了原生文本层,这一断言便可能失败。这个 fixture 与文档片段一一对应,是文档示例"可运行、可验证"的最有力佐证。
底层实现:从配置合并到 OCR 流水线的调用链
理解了参数与测试,再看force_ocr在 Rust 内核中的落地路径,就能对它的行为边界有完整把握。
配置合并层:xberg 支持将 JSON 配置与基础配置合并。在 配置合并模块 的测试中可以看到,merge_config_json(&base, r#"{"force_ocr": true}"#)后merged.force_ocr为true,说明force_ocr是一个标准的、可被请求级 JSON 覆盖的顶层配置字段——这意味在 REST API、MCP 或各语言绑定中,你都可以用同样的 JSON 键名直接透传该配置,无需为 PHP 绑定单独记忆一套命名。
页面选择层:当force_ocr为true时,混合 OCR/原生文本提取路径(extract_mixed_ocr_native_with_layout_inputs,位于 OCR 流水线)会将全部页面标记为需要 OCR。值得留意的一个细节是AllPagesFailedPolicy:当通过force_ocr_pages显式指定页面时,若这些页面 OCR 全部失败,策略是返回错误(ReturnError);而普通force_ocr场景失败时则保留原生文本(PreserveNative)作为兜底。这说明 xberg 对"显式强制"比"全量强制"更严格,因为前者代表用户对特定页面的明确诉求。
分块决策层:force_ocr还会影响分块(chunking)决策。在 分块决策模块 中,ChunkingReason::OcrRequired携带force_ocr: bool字段,意味着强制 OCR 的大文件会被识别为"OCR 需求触发分块"的场景,从而进入分块计划以控制内存占用与处理时长。从源码结构可以推断,强制 OCR 会显著增加单文档的处理成本(逐页渲染 + 识别),分块正是 xberg 对这种成本的结构性应对。
与其他 OCR 策略的配合与边界
force_ocr并非唯一的选择。xberg 的 OCR 策略 提供了粒度不同的控制手段,你可以按场景组合:
OcrStrategy::ScannedPages { min_confidence }:不强制全部页面,而是只对"看起来像扫描件"的页面 OCR。判断依据包括栅格覆盖率、文本层是否隐形、图像编码与 PDF 生产方等;默认最小置信度为0.70(常量定义)。适合混合文档——部分页面是扫描件、部分是可编辑文本;force_ocr_pages: [n, ...]:只强制特定页,适合已知问题页的定向修复;force_ocr: true:全量强制,适合扫描件占绝对主体、或需要统一流水线输出的场景;- VLM 回退:xberg 的
OcrPipelineConfig还支持多后端质量门禁流水线(VlmFallbackPolicy),经典 OCR 结果质量不达标时回退到视觉语言模型。force_ocr改变的是"哪些页面进入 OCR",而质量回退改变的是"OCR 结果如何被评估与替换",两者正交,可以叠加使用。
实际选型建议:若文档是纯扫描件(无任何可用文本层),Auto策略本身就会触发 OCR,force_ocr更多是为了解决"有文本层但文本层不可信"的问题;若只是个别页面有问题,优先用force_ocr_pages以节省全量渲染成本;只有当你需要保证"每一页的输出都来自同一套 OCR 流水线"时,才应选择全量force_ocr。
小结
force_ocr是 xberg 提取配置中一个虽小但关键的开关:它把 OCR 的触发依据从"文本质量判定"切换为"用户显式指令",让开发者可以拿回对 PDF 提取路径的完全控制权。通过本文,你已经掌握了它在 PHP 绑定中的完整调用形态(ExtractInput::from_json→Xberg::extract→getResults()[0]->content)、配套ocr配置块的语义、与force_ocr_pages/disable_ocr的边界关系,以及它从配置合并、页面选择到分块决策的底层实现链路。配合fixtures/contract/ocr_force_all_pages.json契约测试,你可以在自己的环境中验证这一行为,并将其直接复用到实际项目的扫描件处理流水线中。
- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
相关推荐
Xberg 全页强制 OCR(force_ocr)实战:对含原生文本层的 PDF 逐页重识别
Xberg 全页强制 OCR(force_ocr)实战:对含原生文本层的 PDF 逐页重识别 本文围绕 Xberg 的 force_ocr 配置展开,讲解如何在
后端AI 应用NLPxberg 的 force_ocr 完全实战:让已含文本层的 PDF 逐页强制走 OCR
xberg 的 force_ocr 完全实战:让已含文本层的 PDF 逐页强制走 OCR 本篇聚焦 xberg 文档提取管线中的 force_ocr 配置项:当
后端AI 应用NLPxberg Java 实战:用 force_ocr 强制 OCR 已含文本层的 PDF 全页面
xberg Java 实战:用 force_ocr 强制 OCR 已含文本层的 PDF 全页面 本篇技术指南聚焦 xberg 文档抽取库 Java 绑定中的 f
后端AI 应用NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考