后端AI 应用NLP【免费下载链接】xbergPolyglot 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.项目地址https://gitcode.com/gh_mirrors/kr/xberg点击查看免费下载Xberg以 Rust 核心引擎为底座为 Elixir 提供了一套通过 Rustler NIF 暴露的高层提取 API。本篇文章以仓库中自动生成的契约contract代码片段docs-site/src/snippets-generated/elixir/contract/api_extract_batch_uri_with_config.md为骨架完整讲解 Elixir 中如何使用extract_batch一次性批量提取多个远程 URI 文档并针对单个输入附加独立的提取配置per-input config。读完本文你将掌握extract_batch的调用签名、ExtractInput的字段语义、逐输入配置与批次全局配置的合并规则以及底层引擎的并发、缓存与错误隔离原理可直接在自己的 Elixir 项目中落地。一、示例片段解读一次带配置的批量 URI 提取原文档中的核心示例是一段完整的 Elixir 代码展示了契约测试contract test的调用形态result Xberg.extract_batch_async([%{config %{output_format markdown}, kind uri, uri https://example.com/pdf/fake_memo.pdf}]) Enum.each(result.results, fn result - IO.puts(result.content) end)这段代码包含三个关键信息输入列表extract_batch_async接收一个列表列表中每个元素是一个 map表示一个待提取文档。这里的输入声明了kind为uri、uri指向远程 PDF并在config中通过output_format markdown为该文档单独指定了输出格式。批量返回result.results是本次批量提取的结果数组与输入一一对应。结果消费用Enum.each遍历每个result直接输出其content字段——即该文档提取出的正文内容。注意片段中的extract_batch_async是 NIF 层的异步调用形态在应用代码中更常用的是高层封装Xberg.extract_batch/1。二者的关系见下文。二、Elixir 批处理入口Xberg.extract_batch/1与 NIF 层2.1 高层 API 封装在 packages/elixir/lib/xberg.ex 中Xberg模块提供了关键字列表风格的高层函数doc Extract content from multiple bytes or URI inputs. spec extract_batch(keyword()) :: {:ok, map()} | {:error, atom, String.t()} def extract_batch(opts \\ []) do Xberg.Native.extract_batch_async( case Keyword.get(opts, :inputs) do nil - nil v when is_binary(v) - v v - Jason.encode!(v) end, case Keyword.get(opts, :config) do nil - nil v when is_binary(v) - v v - Jason.encode!(v) end ) end它接受两个关键字参数参数含义说明:inputs输入列表每个元素为ExtractInput结构或 map%{kind ..., uri ..., bytes ..., config ...}:config批次级全局配置所有输入共享的默认ExtractionConfig可被单个输入内的config覆盖函数返回{:ok, result_map}或{:error, reason, message}三元组。inputs/config既可以直接传二进制JSON 字符串也可以传 Elixir 数据结构由封装层统一Jason.encode!/1序列化后送入 NIF。2.2 NIF 层与原生实现NIF 声明位于 packages/elixir/lib/xberg/native.exdef extract_batch_async(_inputs, _config), do: :erlang.nif_error(:nif_not_loaded)该模块基于RustlerPrecompiled加载xberg_nifcrate并针对aarch64-apple-darwin、aarch64-unknown-linux-gnu、x86_64-unknown-linux-gnu、x86_64-pc-windows-msvc四个目标平台提供预编译产物。也就是说Elixir 侧只是薄封装真正的提取逻辑全部在 Rust 核心引擎中完成。三、逐输入配置Per-Input Config的结构与字段3.1ExtractInput统一输入模型Rust 侧的ExtractInput定义在 crates/xberg/src/core/config/extraction/types.rspub struct ExtractInput { pub kind: ExtractInputKind, // bytes 或 uri pub bytes: OptionVecu8, // kind bytes 时使用 pub uri: OptionString, // 本地路径、file:// 或 HTTP(S) URL pub mime_type: OptionString, // MIME 提示 pub filename: OptionString, // 文件名提示用于 MIME 探测与元数据 pub config: OptionFileExtractionConfig, // 逐输入提取覆盖 }其中kind只有两种取值Bytes内存字节与Uri本地路径、file://URI 或 HTTP(S) URL。本文示例使用的是Uri形态。3.2FileExtractionConfig可在单个输入上覆盖的字段config字段的类型是FileExtractionConfig定义于 crates/xberg/src/core/config/extraction/file_config.rs。它是覆盖层每个字段都是Option只覆盖你显式指定的项未指定的项沿用批次全局配置。可用字段包括节选核心项字段作用output_format覆盖输出内容格式plain、markdown、djot、htmlresult_format覆盖结果形态unified默认或element_basedforce_ocr强制对该文档执行 OCRdisable_ocr对该文档禁用 OCRocr_strategy/force_ocr_pages覆盖 OCR 页选择策略与强制页号1 起始chunking覆盖分块配置images覆盖图片提取配置pages覆盖页范围提取language_detection覆盖语言检测keywords覆盖关键词提取需keywords-yake/keywords-rake特性postprocessor覆盖后处理器timeout_secs覆盖该文档的提取超时秒超时只影响该输入mime_detection_policy覆盖 MIME 推断策略enable_quality_processing覆盖质量后处理开关include_document_structure覆盖文档结构输出开关需要特别说明的是output_format在全局配置ExtractionConfig中它的默认值是Plain纯文本可选Markdown、Djot需 djot 特性、Html见 crates/xberg/src/core/config/extraction/core.rs。当设置为Markdown时渲染器默认会对正文中的 Markdown 敏感字符如行首-、#做反斜杠转义escape_markdown默认true保证文本通过 CommonMark 解析器往返一致。3.3 配置合并批次全局配置 逐输入覆盖逐输入配置与批次配置不是二选一而是叠加。引擎在 crates/xberg/src/engine/extract_impl.rs 的resolve_input_config中完成合并fn resolve_input_config(input: ExtractInput, base_config: ExtractionConfig) - ExtractionConfig { let mut resolved input .config .as_ref() .map(|overrides| base_config.with_file_overrides(overrides)) .unwrap_or_else(|| base_config.clone()); resolved.ensure_cancel_token(); resolved }with_file_overrides定义于 crates/xberg/src/core/config/extraction/core.rs逐字段检查覆盖层的Option凡是Some的字段就替换全局配置中的对应值None则保留全局值。因此批次全局配置负责公共默认值如所有文档都输出 Markdown单个输入的config负责特例如某份扫描件需要force_ocr某个 HTML 需要输出plain。在并发批量模式下引擎还提供了resolve_input_config_arc优化没有逐输入覆盖时直接Arc::clone共享全局配置避免不必要的深拷贝有覆盖时才构造新的ArcExtractionConfig。四、底层引擎批量提取的执行链路4.1 入口委托Rust 核心的公开入口在 crates/xberg/src/core/extract/mod.rspub async fn extract_batch(inputs: VecExtractInput, config: ExtractionConfig) - ResultExtractionResult { DEFAULT_ENGINE.extract_batch(inputs, config).await }DEFAULT_ENGINE是进程级懒加载的单例引擎extract_batch委托给它执行。4.2 引擎内部的五步流程引擎实现crates/xberg/src/engine/extract_impl.rs中extract_batch的执行大致分五步进度事件发送BATCH_PROGRESS_STAGE_START进度 0.0。配置校验调用config.validate()校验 OCR、DPI、分块参数、置信度区间等校验失败立即返回错误并发送BATCH_PROGRESS_STAGE_ERROR。缓存查找用batch_content_cache_key计算批量缓存键——它把每个输入的bytes或 URI 解析结果、mime_type、filename与合并后的配置 JSON一起喂给 blake3 哈希。因此逐输入配置的改变会改变缓存键同一文档不同配置不会错误地共享缓存。执行提取extract_batch_uncached根据运行时特性选择顺序执行extract_batch_sequential或并发执行extract_batch_concurrent基于 TokioJoinSet分发任务并把线程预算按批次均分给各文档 worker。结果缓存若所有输入都成功且无错误项将序列化结果写入缓存最后发送BATCH_PROGRESS_STAGE_COMPLETE进度 1.0。4.3 错误隔离与去重批量语义上有两个重要设计错误隔离单个输入失败不会拖垮整个批次。顺序模式中每个输入的错误被包装为ExtractionErrorItem包含index、code、error_type、source、message追加到output.errors其余输入继续处理。这对应了仓库中extract_batch_uri_partial_failure等契约测试覆盖的场景。URI 去重与递归initial_seen_urls收集输入中所有 HTTP(S) URI 作为已访问集合initial_seed_hosts记录种子域名批处理结束后通过follow_recursive_document_urls支持按配置递归跟进文档内链接受UrlExtractionConfig/CrawlConfig控制。五、契约与测试验证这段代码为什么能跑原文档是 alef 工具链自动生成的契约片段!-- This file is auto-generated by alef --它与仓库中的真实契约定义、e2e 测试一一对应。5.1 契约 JSON契约定义在 fixtures/contract/api_extract_batch_uri_with_config.json{ id: api_extract_batch_uri_with_config, call: extract_batch, input: { inputs: [ { kind: uri, uri: $mock_url/pdf/fake_memo.pdf, config: { output_format: markdown } } ], mock_responses: [ { path: /pdf/fake_memo.pdf, status_code: 200, headers: { content-type: application/octet-stream }, body_file: ../test_documents/pdf/fake_memo.pdf } ] }, assertions: [ { type: equals, field: results[0].mime_type, value: application/pdf }, { type: min_length, field: results[0].content, value: 10 }, { type: equals, field: results[0].metadata.output_format, value: markdown } ] }这份契约精确规定了该批次的验收标准远程 mock 服务器返回fake_memo.pdf仓库测试文档见 crates/xberg/test_documents/pdf提取结果中results[0].mime_type必须是application/pdf说明 URI 输入走 HTTP 拉取后正确识别 MIMEresults[0].content长度至少为 10说明确实提取出了正文results[0].metadata.output_format必须是markdown——这正是逐输入配置生效的直接证据。5.2 Elixir e2e 测试对应的 e2e 测试位于 e2e/elixir/test/contract_test.exsdescribe api_extract_batch_uri_with_config do test api_extract_batch_uri_with_config do inputs_json Jason.encode!([%{config %{output_format markdown}, kind uri, uri $mock_url/pdf/fake_memo.pdf}]) | String.replace($mock_url, inputs_mock_base_url) inputs_value Jason.decode!(inputs_json) {:ok, result} Xberg.extract_batch(inputs: inputs_value) assert Enum.at(result.results, 0).mime_type application/pdf assert (is_binary(Enum.at(result.results, 0).content) byte_size(Enum.at(result.results, 0).content) 10) || ... assert Enum.at(result.results, 0).metadata.output_format markdown end end测试把$mock_url替换为 mock 服务器地址后调用Xberg.extract_batch(inputs: ...)并断言了与契约完全一致的三条结果。这意味着只要你的环境能访问到文档 URI本地路径、file://或 HTTP(S)在本地复现这段代码即可获得可验证的输出。六、实战建议混合批次与输出格式选择6.1 混合输入批次批量接口的真正价值在于一个请求内混合不同类型、不同需求的文档。官方提取指南 docs-site/src/content/docs/guides/extraction.mdx 中的Per-Input Configuration一节给出了标准范式——批次全局配置设公共默认值单个输入覆盖特例# 批次全局配置所有文档默认输出 markdown # 单个输入扫描件强制 OCRHTML 页面改为纯文本 inputs [ %{kind uri, uri report.pdf}, %{kind uri, uri scan.tiff, config %{force_ocr true}}, %{kind uri, uri notes.html, config %{output_format plain}} ] {:ok, result} Xberg.extract_batch(inputs: inputs, config: %{output_format markdown})也可以混合bytes输入内存中的文件内容例如读取本地文件后以字节列表传入并给出filename提示引擎会依据文件名辅助 MIME 探测。6.2 结果字段速览result.results中每个元素ExtractionResult的单项通常包含字段含义content提取出的正文格式取决于output_formatmetadata文档元数据含output_format等本次生效的配置回显mime_type探测到的 MIME 类型summary/errors批次汇总信息与单项错误列表非致命6.3 使用前提提取远程 HTTP(S) URI 需要引擎编译时启用url-ingestion特性本地路径与file://URI 不需要网络。输出格式中的djot需要djot特性html需要相应渲染器特性未启用的格式会被拒绝或回退具体以你的构建配置为准。Elixir 包通过 RustlerPrecompiled 加载预编译 NIF也可设置XBERG_BUILD1或开发环境Mix.env() in [:dev]强制本地编译。七、小结以契约片段docs-site/src/snippets-generated/elixir/contract/api_extract_batch_uri_with_config.md为线索我们完整梳理了 Elixir 侧批量 URI 提取的调用链Xberg.extract_batch/1高层封装→Xberg.Native.extract_batch_async/2Rustler NIF→ Rust 核心extract_batch→ 引擎合并逐输入配置with_file_overrides→ 并发/顺序执行 → 缓存与错误隔离。核心要点是逐输入配置通过ExtractInput.configFileExtractionConfig实现字段级覆盖未指定的字段自动继承批次全局配置这让你可以用一次extract_batch调用处理来源、格式、OCR 需求各不相同的文档集合而契约与 e2e 测试fixtures/contract/api_extract_batch_uri_with_config.json、e2e/elixir/test/contract_test.exs为这段代码的正确行为提供了可重复验证的保证。赞分享后端AI 应用NLP【免费下载链接】xbergPolyglot 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.项目地址https://gitcode.com/gh_mirrors/kr/xberg点击查看免费下载相关推荐xberg C 绑定批量文档抽取实战xberg_extract_batch 与 per-input config 逐条配置xberg C 绑定批量文档抽取实战xberg_extract_batch 与 per input config 逐条配置 本篇技术指南聚焦 xberg 的后端AI 应用NLPXberg C 批量 URI 文档提取实战ExtractBatchAsync 与按输入粒度覆盖配置Per-Input Config深度解析Xberg C 批量 URI 文档提取实战ExtractBatchAsync 与按输入粒度覆盖配置Per Input Config深度解析 本指南聚焦 X后端AI 应用NLPxberg Dart 绑定批量 URI 提取实战基于 extract_batch 与 per-input 配置逐文件控制输出格式xberg Dart 绑定批量 URI 提取实战基于 extract_batch 与 per input 配置逐文件控制输出格式 本篇指南讲解如何在 xber后端AI 应用NLP上一篇OpenResume代码覆盖率工具集成Jest与Istanbul配置下一篇EdgeGPT终极指南3种对话风格模式对比与选择技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考