- 后端
- 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(强制 OCR)与disable_ocr(禁用 OCR)时,请求会被拒绝并抛出校验异常。读完本文,你将理解这两个配置项的语义边界、Rust 引擎层校验的实现位置与错误消息来源,并能用 PHP 代码复现、验证这一冲突场景。
场景:同时"强制 OCR"又"禁用 OCR"会发生什么?
在处理扫描版 PDF、图片等无文本层文档时,OCR 开关直接决定提取管线是否执行图像文字识别。Xberg 提供了一组正交但互相影响的 OCR 配置项,其中force_ocr与disable_ocr语义上互斥:
force_ocr: true表示无论文档本身是否含文本层,都强制执行 OCR;disable_ocr: true表示对所有文档类型跳过 OCR。
两者同时为真时,管线无法决定"到底要不要跑 OCR",因此 Xberg 在引擎入口直接做配置校验并返回Validation错误,而不是等到提取中途才失败。这正是 error_extract_input_conflicting_ocr 文档片段(alef 生成的 PHP 用例片段)所演示的行为:调用Xberg::extract()并同时传入disable_ocr与force_ocr,随后捕获并打印异常。
参数语义:与 OCR 相关的四个配置项
在 Rust 核心的提取配置结构体 crates/xberg/src/core/config/extraction/core.rs 中,OCR 相关的字段包括:
| 配置项 | 类型 | 默认值 | 语义 |
|---|---|---|---|
force_ocr | bool | false | 强制对文档执行 OCR,忽略自动检测结果 |
disable_ocr | bool | false | 对所有文档类型硬性关闭 OCR;源码注释明确"不能与force_ocr同时为true" |
ocr_strategy | OcrStrategy | — | 当既未force_ocr也未指定force_ocr_pages时,决定哪些页面参与 OCR(如ScannedPages只处理扫描页) |
force_ocr_pages | Option<Vec<u32>> | None | 仅对指定页面执行 OCR,未列出的页面走原生文本提取;force_ocr: true时该字段被忽略 |
这里有一个容易被忽略的细节:disable_ocr的生效判定并不是只读这一个布尔字段。核心层提供了effective_disable_ocr()方法(见 core.rs),其逻辑是:
pub(crate) fn effective_disable_ocr(&self) -> bool { self.disable_ocr || self.ocr.as_ref().is_some_and(|o| !o.enabled) }也就是说,顶层disable_ocr: true与OcrConfig.enabled = false两种写法都会被统一视为"禁用 OCR"。核心层为该方法专门编写了单元测试(test_effective_disable_ocr_from_top_level_flag、test_effective_disable_ocr_from_ocr_enabled_false等,见 core.rs),确认两种途径效果一致。这也意味着:force_ocr: true与ocr.enabled: false的组合同样会触发冲突错误。
引擎层校验:错误在哪里抛出?
冲突校验发生在提取管线的入口阶段,早于 MIME 解析和提取器分派,两条路径都有实现:
字节输入路径(bytes)
在 crates/xberg/src/core/extractor/bytes.rs 的run_byte_extraction中,首先执行两类校验:
if config.force_ocr && config.effective_disable_ocr() { return Err(crate::XbergError::Validation { message: "force_ocr and disable_ocr cannot both be true".to_string(), source: None, }); } if matches!( config.ocr_strategy, crate::core::config::OcrStrategy::ScannedPages { .. } ) && config.effective_disable_ocr() { return Err(crate::XbergError::Validation { message: "ocr_strategy selects scanned pages for OCR, but disable_ocr is true".to_string(), source: None, }); }文件输入路径(file)
在 crates/xberg/src/core/extractor/file.rs 的detect_file_mime_blocking中,通过checks.force_ocr_conflict与checks.scanned_pages_ocr_conflict两个检测位执行完全相同的校验,错误消息与 bytes 路径一致。
可以推断,这两处校验属于同一套输入校验逻辑的不同入口(字节与文件),确保无论输入方式是bytes还是uri,冲突配置都会被拦截。校验完成后才进入 MIME 探测与提取链,因此冲突错误属于确定性的、可预期的快速失败,不会消耗 OCR 资源或产生半成品结果。
用 PHP 复现冲突场景
文档片段给出的 PHP 复现代码如下(完整保留原文):
<?php declare(strict_types=1); require_once __DIR__ . '/vendor/autoload.php'; use Xberg\Xberg; use Xberg\ExtractInput; $input = \Xberg\ExtractInput::from_json(json_encode(["bytes" => "text/fake_text.txt", "config" => ["disableOcr" => true, "forceOcr" => true], "filename" => "fake_text.txt", "kind" => "bytes", "mimeType" => "text/plain"])); try { Xberg::extract($input, ["disable_ocr" => true, "force_ocr" => true]); } catch (Throwable $error) { echo $error::class . ': ' . $error->getMessage() . "\n"; }运行后预期输出类似:
Xberg\XbergException: force_ocr and disable_ocr cannot both be true代码中有两个值得注意的配置入口:
- 输入级 config:
ExtractInput::from_json()的 JSON 中,config字段使用camelCase(disableOcr、forceOcr),对应本用例中字节输入自带的一组合法配置; - 调用级 config:
Xberg::extract($input, [...])的第二个参数使用snake_case(disable_ocr、force_ocr),两者都指向同一组引擎配置字段。
无论配置从哪个入口传入,只要解析后force_ocr与disable_ocr(或等效的ocr.enabled = false)同时为真,引擎都会抛出相同的Validation错误。文档片段还使用了from_json构造输入,这要求 PHP 包暴露 JSON 序列化入口;另一种常规写法是\Xberg\ExtractInput::fromBytes(...)与\Xberg\ExtractInput::fromUri(...)(见 packages/php/README.md 的快速开始示例)。
运行与验证:e2e 测试与夹具
该场景在仓库中不是孤立示例,而是有一套完整的测试与夹具支撑:
- 夹具定义:fixtures/error/error_extract_input_conflicting_ocr.json 声明了
category: "error"、call: "extract",输入为text/plain字节(内容是 "This is a test document..." 的 ASCII 文本),config同时设置force_ocr: true与disable_ocr: true,断言类型为error——即期望提取失败。 - e2e 测试:e2e/php/tests/ErrorTest.php 中的
test_error_extract_input_conflicting_ocr使用expectException(\Exception::class)断言异常必然抛出,并通过ExtractionConfig::from_json(json_encode(["disableOcr" => true, "forceOcr" => true]))从 JSON 加载冲突配置后调用XbergApi::extract()。 - 文档生成机制:本用例的文档片段位于 docs-site/src/snippets-generated/php/error/error_extract_input_conflicting_ocr.md,由 alef 自动生成(文件头标注
auto-generated by alef — DO NOT EDIT),可通过alef e2e generate重新生成、alef verify校验新鲜度。requires: []表示该用例无额外依赖,side_effect: safe表示运行不会产生外部副作用,适合在 CI 中反复执行。
若要本地复现,安装 PHP 包后(composer require xberg-io/xberg,要求 PHP 8.2+,见 packages/php/README.md),将上述代码放入脚本执行即可;更严谨的方式是直接运行 e2e 测试套件。
同类冲突:ocr_strategy 与 disable_ocr 的互斥
除了force_ocr,ocr_strategy也有一条隐藏的互斥规则:当策略为ScannedPages(只对扫描页 OCR)而disable_ocr同时为真时,引擎同样抛出Validation错误——错误消息为"ocr_strategy selects scanned pages for OCR, but disable_ocr is true"(见 bytes.rs 与 file.rs)。
这背后的逻辑是:ScannedPages属于自动触发型配置,它只是让引擎在检测到扫描页时运行 OCR;而disable_ocr是显式关闭型配置,优先级更高(核心层注释明确disable_ocr"skipping OCR for all document types" 且必须压制自动触发,相关测试disable_ocr_suppresses_embedded_image_ocr_even_when_opted_in见 core.rs)。两者并存时语义矛盾,因此同样选择快速失败。
避免冲突的配置建议
- 默认状态:
force_ocr、disable_ocr默认均为false(见 core.rs),此时引擎按文档实际内容自动决定是否 OCR,这是绝大多数场景的推荐起点。 - 扫描文档:需要强制识别扫描件时,只设
force_ocr: true(配合OcrConfig指定后端与语言),不要再设disable_ocr。 - 纯文本优先:需要完全跳过 OCR(如只提取文本层、节省资源)时,只设
disable_ocr: true,或等价地设ocr.enabled = false。 - 精细控制:只想处理个别页面时,用
force_ocr_pages指定页号列表,而不是全局force_ocr。 - 配置校验意识:与冲突错误并列的还有无效/不支持的 MIME 等校验错误(仓库中
fixtures/error/目录集中管理这类用例),它们的共同特点是在提取前即可确定失败,因此上层代码建议对Validation类异常做统一捕获与友好提示。
延伸:OCR 后端的常规配置
冲突校验之外,PHP 绑定的常规 OCR 配置通过ExtractionConfig与OcrConfig完成(参考 packages/php/README.md):
use Xberg\ExtractionConfig; use Xberg\OcrConfig; $config = new ExtractionConfig( ocr: new OcrConfig( backend: 'tesseract', language: 'eng' ) ); $output = \Xberg\XbergApi::extract(\Xberg\ExtractInput::fromUri('scanned_document.pdf'), $config);backend支持 Tesseract、PaddleOCR、Sceptre 等,language支持eng、eng+fra+deu等多语言组合。注意:OcrConfig.enabled = false会通过effective_disable_ocr()等效于disable_ocr,因此若同时显式设置force_ocr: true,同样会命中互斥校验——这是配置时最容易被遗漏的"隐形冲突"。
综上,force_ocr与disable_ocr的互斥是 Xberg 输入校验体系中的一个典型用例:文档层面有 alef 生成的 PHP 片段、测试层面有 e2e/php/tests/ErrorTest.php、引擎层面有 bytes.rs 与 file.rs 的双路径实现。理解这条链路,你就能在任何绑定语言中准确预判 OCR 配置冲突的失败行为。
- 后端
- 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 Elixir 绑定中 OCR 配置冲突错误解析:force_ocr 与 disable_ocr 互斥校验的源码级剖析
Xberg Elixir 绑定中 OCR 配置冲突错误解析:force_ocr 与 disable_ocr 互斥校验的源码级剖析 本篇文章围绕 Xberg 在
后端AI 应用NLPxberg 的 force_ocr 与 disable_ocr 互斥配置:Dart 绑定下冲突校验的源码级剖析
xberg 的 force_ocr 与 disable_ocr 互斥配置:Dart 绑定下冲突校验的源码级剖析 导读 在 xberg 的提取配置体系中, for
后端AI 应用NLPxberg 中 force_ocr 与 disable_ocr 互斥校验:OCR 开关冲突的检测机制与 Java 调用实践
xberg 中 force_ocr 与 disable_ocr 互斥校验:OCR 开关冲突的检测机制与 Java 调用实践 xberg 提供了一套多层次的 OC
后端AI 应用NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考