xberg 语言检测实战:通过 C FFI 开启 Language Detection 并读取 ISO 639-3 结果

  • 后端
  • 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.

项目地址: https://gitcode.com/gh_mirrors/kr/xberg
点击查看 免费下载

在 xberg 的多格式文档智能管线中,语言检测是一个可选的后处理步骤:开启后,提取结果会附带文档语言的 ISO 639-3 代码以及每语言的置信度、占比与可靠性信息。本文以 C 语言绑定为主线,完整演示如何构造 language_detection 配置、调用提取 API 并读取返回的语言代码,并结合 Rust 核心源码深入讲解单语言/多语言两种检测模式的分块聚合算法、阈值语义与结果结构,帮助读者在 C 项目中可靠地接入文档语言识别能力。

语言检测在 xberg 中的定位

xberg 的核心提取流程(PDF、DOCX、HTML 等 106 种格式)产出纯文本内容后,语言检测作为后处理插件运行,对提取出的文本分析语言构成。它具备以下特征(均能从源码确认):

  • 以 PostProcessor 插件形式注册,插件名为 language-detection,运行在 Early 处理阶段,优先级为 40;
  • 只有当提取配置中显式提供了 language_detection 配置对象时才会执行(should_process 检查 config.language_detection.is_some());
  • 底层使用 whatlang 库完成实际的语言识别,输出 ISO 639-3 语言代码(如 eng、spa、cmn);
  • 结果写入 ExtractedDocument 的两个字段:detected_languages(代码列表)与 detected_language_confidences(结构化详情)。

插件实现见 processor.rs,核心检测算法见 mod.rs。

配置项详解:LanguageDetectionConfig

无论使用哪种语言绑定,配置对象的核心是同一份 LanguageDetectionConfig 结构体,定义于 extraction/types.rs。该结构体使用 #[serde(deny_unknown_fields)],即拼写错误的字段名会直接导致配置解析失败,这一点在跨语言绑定调试时尤其重要。

字段类型默认值取值范围说明
enabledbooltrue—是否启用语言检测。注意:即使设为 true,若整个 language_detection 配置对象缺省,检测也不会运行
min_confidencef640.80.0–1.0最低置信度阈值。单语言模式下低于该值的整文检测结果会被丢弃;多语言模式下低于该值的分块结果被过滤
detect_multipleboolfalse—false 为单语言模式(整文检测一个主语言);true 为多语言模式(分块统计多种语言及各自占比)

默认值定义在同文件的 Default 实现中(enabled: true、min_confidence: 0.8、detect_multiple: false),见 extraction/types.rs#L591-L599。对应的 JSON 形态即文档示例中的:

{"language_detection":{"detect_multiple":false,"enabled":true,"min_confidence":0.5}}

这里将 min_confidence 显式调低到 0.5,比默认值 0.8 更宽松,适合短文档或混合内容场景;仓库的契约测试夹具 language_detection_config.json 与 language_detection_multilingual.json 分别演示了单语言与多语言两种配置的完整请求形态。

C FFI 实战:开启语言检测并提取文档

以下示例来自 C 语言的端到端片段(fixture 标识 fixture_c_language_detection_config,级别为 typecheck,需要语言检测功能编译进 FFI 库)。它演示了完整的调用链:构造输入 → 构造含语言检测配置的配置 → 提取 → 释放句柄:

#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xberg.h"

int main(void) {
    XBERGAlefHandle input_handle = xberg_extract_input_from_json("{\"kind\":\"uri\",\"mime_type\":\"text/plain\",\"uri\":\"https://example.com/text/report.txt\"}");
    XBERGAlefHandle config_handle = xberg_extraction_config_from_json("{\"language_detection\":{\"detect_multiple\":false,\"enabled\":true,\"min_confidence\":0.5}}");
    XBERGAlefHandle result = xberg_extract(input_handle, config_handle);
    xberg_extract_input_free(input_handle);
    xberg_extraction_config_free(config_handle);
    xberg_extraction_result_free(result);
    return EXIT_SUCCESS;
}

四个关键 FFI 入口

示例中涉及的所有函数都在自动生成的 C 头文件 xberg.h 中声明,调用关系与资源管理约定如下:

函数声明位置作用
xberg_extract_input_from_jsonxberg.h#L10627从 JSON 构造提取输入句柄。示例使用 uri 类型输入({"kind":"uri","mime_type":"text/plain","uri":"..."}),同样支持 bytes 类型直接传入文档字节
xberg_extraction_config_from_jsonxberg.h#L11473从 JSON 构造提取配置句柄。language_detection 子对象的三个字段在此被解析为 LanguageDetectionConfig
xberg_extractxberg.h#L29787同步执行提取,返回结果句柄(不透明类型 XBERGAlefHandle)
xberg_extract_input_free / xberg_extraction_config_free / xberg_extraction_result_freexberg.h#L10642、xberg.h#L11488、xberg.h#L12390三种类句柄必须各自配对释放,头文件注释明确要求 "Returned handle must be freed with ..."

头文件顶部还以宏形式声明了本 FFI 构建启用的 Cargo 特性,其中 #define XBERG_FEATURE_LANGUAGE_DETECTION 1(见 xberg.h#L30)表明当前构建已编译语言检测能力——如果你的定制构建关闭了该 feature,配置中的 language_detection 字段将无效果。

需要说明:示例中的 https://example.com/text/report.txt 是用于演示 URI 输入形态的占位地址。提取成功后,result 句柄对应的 ExtractedDocument 中,detected_languages 字段即为 ISO 639-3 代码数组(例如 ["eng"]),detected_language_confidences 为对应的结构化详情数组;两者均带 skip_serializing_if = Option::is_none,未检测到时在 JSON 输出中不出现。

底层检测算法:单语言与多语言两种模式

配置只是入口,真正的行为差异在 mod.rs 中实现。入口函数 detect_language_details 依序判断:配置未启用、文本 trim 后为空、或没有任何语言达到 min_confidence 时返回 None;否则按 detect_multiple 分派到两种路径。

单语言模式(detect_multiple: false)

对整段文本调用一次 whatlang 的 detect。置信度达到 min_confidence 时返回单元素结果,其中 proportion 恒为 1.0,reliable 直接取 whatlang 自身的 Info::is_reliable()(其内部 0.9 阈值)。

多语言模式(detect_multiple: true)

这是算法上更复杂的一条路径(detect_multiple_languages_details):

  1. 分块:将文本按 200 个字符切块(常量 CHUNK_SIZE = 200,该常量同时被 PDF OCR 合理性检测复用,保证两处分块边界一致);
  2. 逐块检测:对每个块运行 whatlang,仅保留置信度 ≥ min_confidence 的检测结果,按语言聚合块数与置信度之和;
  3. 聚合排序:按"该语言命中块数占总块数的比例"降序排列,平局时按 ISO 639-3 代码字典序打破,保证结果跨运行确定;
  4. 回退:若所有块都未达到阈值,回退到对整文的单语言检测;
  5. 可靠性判定:多语言模式下 reliable 取"该语言块平均置信度 > 0.9"(AGGREGATE_RELIABLE_THRESHOLD),与 whatlang 单次检测的可靠性阈值对齐。

一个值得注意的历史细节:仓库中的回归测试 test_confidence_threshold_is_honored_and_monotonic 记录了问题 #1223 的修复——旧实现曾把阈值上限钳制在 0.35,导致调高 min_confidence 无效果;现在过滤器是严格单调的,提高阈值只会移除语言,永远不会新增语言。

whatlang 覆盖的语言范围

从 lang_to_iso639_3 的映射表可以确认,whatlang 识别出的 70 种语言会被映射到 ISO 639-3 代码,覆盖英语(eng)、中文(cmn)、日语(jpn)、韩语(kor)、阿拉伯语(ara)、俄语(rus)、法语(fra)、德语(deu)等主要语言,以及斯瓦希里语(sna)、祖鲁语(zul)等非洲语言。未命中映射表的其他语言在映射中不会产出有效代码。

输出结构:LanguageConfidence

除 detected_languages 代码列表外,结果还包含结构化的 LanguageConfidence 数组(自 1.1.0 起提供,见 extraction.rs#L143-L155),每个元素包含四个字段:

字段含义
languageISO 639-3 代码,与 detected_languages 对应位置一致
confidence[0.0, 1.0] 的置信度。单语言模式为整文置信度;多语言模式为该语言命中块的平均置信度
proportion文档中归类为该语言的块占比。单语言模式恒为 1.0;多语言模式下未达到任何语言阈值的块不计入分子但仍计入分母
scriptwhatlang 检测到的书写系统,如 "Latin"、"Cyrillic"
reliable该检测是否可靠(单语言模式取 whatlang 内部 0.9 阈值判断;多语言模式取块平均置信度 > 0.9)

两个字段在"检测禁用、空文本、无语言达到阈值"三种情况下同时为 None(JSON 中省略),调用方应将其视为"未检测出可靠语言"而非"检测失败"。

边界行为与测试证据

mod.rs 的内嵌测试(约 40 个用例)系统验证了检测器的边界行为,可以作为你在生产环境中的预期参考:

  • 纯数字、纯标点、纯空白输入:返回 None(test_numbers_only、test_punctuation_only、test_whitespace_only);
  • 阈值过滤:min_confidence: 0.99 下短文本 "ok yes no" 被过滤为 None(test_confidence_threshold_filters_low_confidence);
  • 确定性:同一文本多次检测结果完全一致,多语言并列排序跨运行稳定(test_detection_consistency、test_multiple_languages_deterministic_order);
  • 排序契约:英文块与西班牙文块 4:1 时,eng 必须排在列表首位(test_multiple_languages_ordered_by_descending_chunk_share);
  • CJK、阿拉伯文/波斯语、西里尔/拉丁混排等混合文档均有对应测试,验证 detect_multiple: true 能返回多种语言。

插件层的测试(processor.rs#L94-L202)则验证了:配置缺省时不处理且 detected_languages 保持 None;配置存在时英文文本正确产出 eng;处理阶段确为 Early。

实践建议

  1. 短文档调低阈值:默认 min_confidence: 0.8 对长文档稳健,但短句、标题类文本容易低于阈值而整体返回空。示例中将阈值设为 0.5 是合理的折中;
  2. 需要语言占比时开启多语言模式:仅要"文档是什么语言"时保持 detect_multiple: false(单次检测,开销最小);需要区分双语合同、多语言报告中的语言构成时开启,并读取 proportion 字段;
  3. 注意 JSON 字段的严格性:配置解析拒绝未知字段,enabled 之外不要再手写其他字段名;
  4. 配对释放 FFI 句柄:C 侧三个句柄必须各自 free,头文件注释与 typecheck 级别的端到端片段都以此为契约。

综上,xberg 的语言检测通过一个三字段配置对象即可开启,底层是 whatlang 驱动的单次/分块聚合双模式算法,结果以 ISO 639-3 代码加结构化置信度双重形式返回;C 项目按本文示例组织输入、配置与释放逻辑,即可在提取管线中稳定获取文档语言信息。

  • 后端
  • 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.

项目地址: https://gitcode.com/gh_mirrors/kr/xberg
点击查看 免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值