- 后端
- 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 开源仓库中的 Python 冒烟测试用例,完整讲解如何用官方 Python SDK 对 PNG 图片执行“不开启 OCR、仅提取元数据”的提取流程。你将掌握ExtractInput/ExtractInputKind/ExtractionConfig三个核心类型的使用方式、disable_ocr配置项的语义及其与 OCR 相关配置的协作关系,并了解该用例在仓库中的夹具定义、e2e 测试实现与底层 Rust 绑定调用链,可直接迁移到自己的图片管道场景中。
场景定位:为什么需要对 PNG 做“无 OCR”提取
在 xberg 的 smoke 测试体系中,smoke_image_png属于最基础的图片冒烟用例,其意图正如文档标题所述:PNG image (without OCR, metadata only)。它验证的是:当调用方明确关闭 OCR 时,提取管道仍能正确识别输入并返回基础元数据(核心是 MIME 类型image/png),而不必依赖任何 OCR 后端或模型资源。
这个场景在真实生产中有明确的适用价值:
- 管道自检:在 CI 中先用最轻量的图片用例验证 SDK 安装、绑定加载、URI 拉取与结果解析链路是否完好;
- 资源受限环境:无 GPU、无 OCR 模型缓存(如
candle_ocr、paddle_ocr、tesseract等后端)的容器中,仍需要对图片做类型识别与元数据提取; - 预分流:在进入 OCR 重管道之前,先用快速元数据层判断图片格式、尺寸等基础信息。
核心 API 一瞥:ExtractInput、ExtractInputKind 与 ExtractionConfig
该用例只涉及三个公开类型,全部由 Python 包xberg提供,底层桥接 Rust 原生绑定。
ExtractInput:统一的提取输入描述
ExtractInput是所有公开提取入口的“统一输入”类型,定义在 packages/python/xberg/options.py:
@dataclass(frozen=True, slots=True) class ExtractInput: kind: ExtractInputKind | str = "uri" # "bytes" 需要 bytes;"uri" 需要 uri bytes: bytes | None = None # kind = "bytes" 时的原始字节 uri: str | None = None # 本地路径、file:// URI 或 HTTP(S) URL mime_type: str | None = None # MIME 类型提示 filename: str | None = None # 用于 MIME 检测与元数据的文件名提示 config: FileExtractionConfig | None = None # 单输入级提取覆盖kind支持两种取值(见 packages/python/xberg/options.py 中ExtractInputKind的BYTES/URI常量):"bytes"直接携带原始字节流,"uri"则指向本地路径、file://URI 或 HTTP(S) URL。本例使用"uri",让提取器通过 URL 拉取远程 PNG。
ExtractionConfig:主提取配置
ExtractionConfig是提取的主配置(packages/python/xberg/options.py),包含 MIME 检测策略、OCR、chunking、语言检测、关键词、图片提取、PDF 选项等数十个字段。用例通过from_json以 JSON 字符串方式构建,这是所有配置类型的统一便捷入口:
config = ExtractionConfig.from_json("{\"disable_ocr\":true}")ExtractionConfig.from_json的实现直接桥接到原生绑定(packages/python/xberg/options.py):
@staticmethod def from_json(json_str: str) -> ExtractionConfig: """Build an ExtractionConfig from a JSON string, via the native binding.""" return _from_native_extraction_config(_xberg.ExtractionConfig.from_json(json_str))关键配置项 disable_ocr:语义与相关配置协作
disable_ocr
该字段定义于 packages/python/xberg/options.py,语义非常明确:
Disable OCR entirely, even for images.
即“即使面对图片也彻底禁用 OCR”。这正是本用例的核心开关:{"disable_ocr": true}意味着提取器不会为 PNG 调度任何 OCR 后端,只走图片元数据/内容解析路径。在 Python 绑定到 Rust 的转换层(packages/python/xberg/api.py 与 packages/python/xberg/api.py)中,disable_ocr会被原样透传给_rust.ExtractionConfig,从而控制原生管道行为。
与 OCR 相关配置的协作关系
为了准确理解disable_ocr在整个 OCR 配置族中的位置,下表列出与其直接相关的配置字段(同见于ExtractionConfig,packages/python/xberg/options.py):
| 字段 | 默认值 | 语义 |
|---|---|---|
ocr | None | OCR 配置对象(选择后端、语言等) |
force_ocr | False | 即使 PDF 已有文本层也强制 OCR |
ocr_strategy | "auto" | 在未设置force_ocr/force_ocr_pages时决定哪些页参与 OCR |
force_ocr_pages | None | 仅对指定页码(1 起)强制 OCR |
disable_ocr | False | 彻底禁用 OCR,包括图片(本用例) |
ocr_near_empty_fallback | None | 文本层为空/近空的 PDF 在Auto策略下是否回退 OCR |
ocr_embedded_images | None | 容器文档(DOCX、PPTX、ODT、HTML 等)内嵌图片是否送 OCR |
注意disable_ocr与force_ocr是互斥语义:e2e 错误用例 e2e/python/tests/test_error.py 专门验证了同时设置disable_ocr=True与force_ocr=True会被判定为冲突输入并报错,可见引擎对这两个开关做了显式的冲突校验。
图片提取子配置 ImageExtractionConfig
当disable_ocr未开启时,图片提取的细节由ImageExtractionConfig控制(packages/python/xberg/options.py)。理解它对区分“有 OCR 与无 OCR”两条路径至关重要:
extract_images(默认True):是否从文档提取图片对象;run_ocr_on_images(默认True):对提取出的图片运行 OCR 并将识别文本并入文档内容——注意默认开启,这正是本例必须显式disable_ocr: true的原因;ocr_text_only、append_ocr_text:控制 OCR 结果在 Markdown 输出中的呈现方式;target_dpi(默认 300)、max_image_dimension(默认 4096):图片归一化参数;include_data_base64(默认False):为 JSON-only 客户端填充 Base64 编码的图片字节。
也就是说,在默认配置下图片提取器默认会对图片做 OCR;而本用例通过disable_ocr从全局层面一刀切掉整个 OCR 阶段,使测试聚焦于元数据与 MIME 识别本身。
完整代码示例:继承并落地原文档用例
原文档(docs-site/src/snippets-generated/python/smoke/smoke_image_png.md)给出了完整可运行的脚本。这里原样继承并补充导入方式的说明:
import asyncio from xberg import extract, ExtractInput, ExtractInputKind from xberg._xberg import ExtractionConfig async def main() -> None: input = ExtractInput( kind=ExtractInputKind("uri"), uri="https://example.com/images/sample.png", ) config = ExtractionConfig.from_json("{\"disable_ocr\":true}") result = await extract(input, config) print(result.results[0].mime_type) asyncio.run(main())关于导入路径的一点说明:ExtractionConfig既可从原生绑定类型层xberg._xberg导入(如上,适用于类型检查场景,原文档的level: typecheck标记与此对应),也可从公共 API 层直接导入——packages/python/xberg/__init__.py已将其列入公开导出(packages/python/xberg/init.py),因此更常见的写法是:
from xberg import extract, ExtractInput, ExtractInputKind, ExtractionConfig两种写法等价,后者更贴近日常 SDK 用法。
关键 API 行为
extract是异步函数:定义于 packages/python/xberg/api.py,签名是async def extract(input: ExtractInput | None = None, config: ExtractionConfig | None = None) -> ExtractionResult。它先把 Python 侧的对象转换为 Rust 绑定类型(_to_rust_extract_input/_to_rust_extraction_config),再 await 原生实现,因此调用方必须处于异步上下文(脚本中用asyncio.run(main())包裹)。- 结果按列表组织:返回值
ExtractionResult的results是文档结果列表,单输入场景下取results[0];本用例只断言其mime_type。
夹具与 e2e 测试:用例如何在仓库中落地
夹具定义
该用例的完整语义记录在夹具 fixtures/smoke/image_png.json,它精确描述了冒烟测试的输入、mock 响应与断言:
{ "id": "smoke_image_png", "category": "smoke", "description": "Smoke test: PNG image (without OCR, metadata only)", "input": { "mock_responses": [ { "path": "/images/sample.png", "status_code": 200, "headers": {"content-type": "application/octet-stream"}, "body_file": "../test_documents/images/sample.png" } ], "extract_input": {"kind": "uri", "uri": "$mock_url/images/sample.png"} }, "assertions": [ {"type": "equals", "field": "results[0].mime_type", "value": "image/png"} ], "call": "extract", "config": {"disable_ocr": true} }从中可以看到三条重要工程信息:
- 通过 mock server 模拟远程 URI:
$mock_url指向本地 mock HTTP 服务,/images/sample.png返回application/octet-stream,正文来自 test_documents/images/sample.png(仓库根目录的test_documents目录)。即便响应头未明确声明image/png,提取器仍能靠内容嗅探正确判定 MIME——这正是mime_detection_policy(默认prefer_content)的价值。 - 断言聚焦元数据:唯一断言是
results[0].mime_type == "image/png",验证“关闭 OCR 后仍能识别图片类型”这条最小正确性底线。 - 配置文件驱动:
config: {"disable_ocr": true}与代码中的ExtractionConfig.from_json严格对应,保证文档、夹具与测试三方一致。
e2e 测试实现
Python 侧 e2e 测试位于 e2e/python/tests/test_smoke.py,与夹具一一对应:
@pytest.mark.asyncio async def test_smoke_image_png() -> None: """Smoke test: PNG image (without OCR, metadata only).""" input_mock_base_url = os.environ["MOCK_SERVER_URL"] + "/fixtures/smoke_image_png" input_json = '{"kind":"uri","uri":"$mock_url/images/sample.png"}'.replace("$mock_url", input_mock_base_url) input_data = json.loads(input_json) input = ExtractInput(kind=ExtractInputKind("uri"), uri=input_data["uri"]) config = ExtractionConfig.from_json('{"disable_ocr":true}') result = await extract(input, config) assert result.results[0].mime_type == "image/png"该测试由 alef 工具链生成并保持与夹具同步(生成文件头部的alef:hash注释用于校验新鲜度),运行前提是MOCK_SERVER_URL环境变量指向 e2e mock server,具体启动方式可参考 scripts/e2e/run-with-mock-server.sh。
与“开启 OCR”路径的对照:理解两条图片管道的差异
把无 OCR 用例与同文件中的 OCR 用例放在一起对照,可以更直观地理解disable_ocr的作用边界。同文件 e2e/python/tests/test_smoke.py 中的test_ocr_image_png走的是完全相反的路:
@pytest.mark.asyncio async def test_ocr_image_png() -> None: """OCR: PNG image extraction with OCR enabled. ...""" input = ExtractInput( bytes=Path("images/test_hello_world.png").read_bytes(), config=FileExtractionConfig(), filename="test_hello_world.png", kind=ExtractInputKind("bytes"), mime_type="image/png", ) config = ExtractionConfig.from_json("{}") # 不关 OCR result = await extract(input, config) assert result.results[0].mime_type == "image/png" assert len(result.results[0].content) >= 1 assert any(v in result.results[0].content for v in ["Hello", "World", "hello", "world"])两点值得注意:
- 输入方式不同:OCR 用例用
kind = "bytes"+ 本地文件字节(对应测试用图 fixtures/images/test_hello_world.png),而smoke_image_png用kind = "uri"+ 远程 URL,两者覆盖了ExtractInputKind的两条路径; - 断言强度不同:OCR 用例不仅校验 MIME,还断言
content中出现了从图片里识别出的"Hello"/"World"文本;而disable_ocr: true的用例则刻意不校验任何文本内容,只验证元数据层——这正体现了 smoke 测试“用最小代价验证链路可用”的设计意图。
小结
smoke_image_png虽是一则冒烟用例,但它浓缩了 xberg Python SDK 图片提取的三条核心经验:
- URI 输入 + 异步提取是远程文档提取的标准姿势,
extract会完成类型转换、网络拉取、内容嗅探与结果封装的全链路; disable_ocr是全局级 OCR 总开关,与force_ocr、ocr_strategy、ImageExtractionConfig.run_ocr_on_images构成完整的 OCR 控制矩阵,且与force_ocr存在显式冲突校验;- 以
mime_type为最小断言可以零依赖地验证图片管道的正确性,是 CI 冒烟与资源受限环境下的务实选择。
需要进一步探索时,建议阅读 packages/python/xberg/options.py 中完整的ExtractionConfig字段定义、packages/python/README.md 中更丰富的 Python 提取示例,以及 packages/python/xberg/api.py 的extract/extract_batch实现,从而把这一条最小用例扩展到批量化、多格式的真实管道。
- 后端
- 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 PHP 图像 PNG 冒烟测试:关闭 OCR 的纯元数据提取实战
Xberg PHP 图像 PNG 冒烟测试:关闭 OCR 的纯元数据提取实战 导读 本文围绕 Xberg 仓库中面向 PHP 绑定生成的 smoke_image
后端AI 应用NLPxberg C 冒烟测试实战:用 DisableOcr 快速提取 PNG 图片元数据
xberg C 冒烟测试实战:用 DisableOcr 快速提取 PNG 图片元数据 本文围绕 xberg 仓库中的 C 冒烟测试文档 smoke_image_
后端AI 应用NLPxberg C FFI 实战:PNG 图片元数据提取冒烟测试(smoke_image_png)全链路解析
xberg C FFI 实战:PNG 图片元数据提取冒烟测试(smoke_image_png)全链路解析 本篇基于 xberg 仓库中的 C 语言冒烟测试片段
后端AI 应用NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考