- 后端
- 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 项目中自动生成的 Dart 摘要示例(summarization_abstractive_smoke.md)为主线,讲解如何在 Dart 应用中通过XbergBridge.extract开启基于 LLM 的抽象式(abstractive)文档摘要:包括完整可运行的 Dart 代码、SummarizationConfig与LlmConfig的每个配置字段、API Key 解析优先级、底层提示词模板与 token 语义,以及如何用仓库中的 fixture 与测试验证行为。读完本文,你将能在自己的 Dart 项目中直接复刻并调优抽象式摘要流水线。
摘要双后端:Extractive 与 Abstractive 的定位
xberg 的摘要能力由summarization后处理器提供,运行于流水线的 Middle 阶段,触发条件是ExtractionConfig.summarization为Some(见 summarization.rs)。官方指南 summarization.mdx 将策略划分为两类:
| 策略 | Cargo feature | 网络依赖 | 质量特征 | 延迟 |
|---|---|---|---|---|
extractive(默认) | summarization | 无,完全本地 | 从原文选择句子,确定性输出 | 典型 < 100 ms |
abstractive | summarization-llm | LLM provider | 生成全新行文,可跨句子归纳 | 取决于 provider |
从源码看,两种后端分别对应 textrank 模块(纯 Rust 的 TextRank:对句子构建 TF-IDF 余弦相似度图并运行 PageRank)与 llm 模块(通过共享的crate::llm::text_completion::complete_text调用 LLM)。summarizationfeature 随no-ort-target、wasm-target、android-target、full等 target 默认启用;抽象式后端需要显式启用summarization-llm。
本篇文章聚焦的正是abstractive分支——它是这篇 Dart snippet 的核心主题。
Dart 示例逐行解析:一次抽象式摘要的完整调用
关联文档给出了一个可直接运行的 Dart 程序,其完整逻辑如下:
import 'dart:io'; import 'package:xberg/xberg.dart'; import 'package:xberg/src/xberg_bridge_generated/frb_generated.dart' show RustLib; Future<void> main() async { await RustLib.init(); try { final input = await createExtractInputFromJson(json: '{"kind":"uri","uri":"https://example.com/text/book_war_and_peace_1p.txt"}'); final config = await createExtractionConfigFromJson(json: '{"summarization":{"llm":{"max_tokens":200,"model":"openai/gpt-4o-mini","temperature":0.0},"max_tokens":150,"strategy":"abstractive"}}'); final result = await XbergBridge.extract(input, config: config); stdout.writeln(result.results[0].summary); } finally { RustLib.dispose(); } }调用链拆解如下:
- 初始化 Rust 运行时:
await RustLib.init()加载 flutter_rust_bridge 生成的绑定(frb_generated.dart),这是所有 Dart 调用触达 Rust 核心的前提;程序结束后在finally中RustLib.dispose()释放资源。 - 构造提取输入:
createExtractInputFromJson传入 JSON 字符串,kind: "uri"表示从 URL 抓取文档,这里是https://example.com/text/book_war_and_peace_1p.txt(测试场景下由 mock server 提供《战争与和平》第一页纯文本,对应 fixture abstractive_smoke.json 中的../test_documents/text/book_war_and_peace_1p.txt)。 - 构造提取配置:
createExtractionConfigFromJson传入的 JSON 是本节的关键,其中summarization对象包含三个字段:strategy: "abstractive":切换摘要后端;max_tokens: 150:请求摘要的大致 token 预算(语义详见下文);llm: {model: "openai/gpt-4o-mini", temperature: 0.0, max_tokens: 200}:LLM 提供商与采样参数。
- 执行提取:
XbergBridge.extract(input, config: config)完成抓取、解析、摘要全流程,结果写入result.results[0].summary,直接stdout.writeln打印。
snippet 顶部的说明还强调了一个重要行为:当XBERG_LLM_API_KEY(或OPENAI_API_KEY)未设置时,该用例会被自动跳过——抽象式摘要属于运行时才确定能否执行的后端,fixture 的 skip 规则也印证了这一点(见 abstractive_smoke.json:要求liter-llmfeature 与XBERG_LLM_API_KEY,离线 CI 由确定性的 extractive 变体覆盖)。
配置详解:SummarizationConfig 与 LlmConfig 字段说明
摘要配置的 Rust 侧定义位于 summarization.rs,结构如下:
| 字段 | 类型 | 说明 |
|---|---|---|
strategy | SummaryStrategy | extractive(默认)/abstractive,snake_case 序列化 |
max_tokens | Option<u32> | 摘要目标长度(token);None时后端选用默认值 |
llm | Option<LlmConfig> | 抽象式后端专用;extractive下忽略,abstractive下必填 |
LlmConfig定义于 llm.rs,Dart JSON 中可用的字段包括:
model(必填):liter-llm 路由格式的提供商/模型串,如openai/gpt-4o-mini、anthropic/claude-sonnet-4-20250514、groq/llama-3.1-70b-versatile;api_key:显式 API Key;为None时回退到提供商标准环境变量;base_url:自定义端点 URL 覆盖;timeout_secs:请求超时(秒),默认 60s;max_retries:最大重试次数,默认 3;temperature:采样温度;max_tokens:单次请求允许生成的 token 上限。
需要注意参数取值边界(同样来自 llm.rs):top_p必须在0.0 ~ 1.0,presence_penalty与frequency_penalty必须在-2.0 ~ 2.0。此外LlmConfig启用了deny_unknown_fields且Debug为手写实现,api_key与请求头值在日志中一律以[redacted]脱敏输出。
抽象式摘要的底层实现:提示词模板与输入预算
抽象式后端由 llm.rs 中的summarize_with_llm实现,其内部逻辑对理解max_tokens语义至关重要:
- 输入截断:
MAX_PROMPT_INPUT_CHARS = 128 * 1024字符(约 32k tokens),超长文档在 UTF-8 字符边界上截断(truncate_input),避免大文档打爆 token 预算; - 默认目标长度:
DEFAULT_MAX_TOKENS = 256,即SummarizationConfig.max_tokens为None时使用的默认值; - 提示词模板(
build_prompt)要求模型“在约 N token 内用单段简洁散文总结,不使用列表、Markdown 格式或标题,保留命名实体、数字与原文语气”,并将文本包裹在<document>...</document>标签中,最后以Summary:收尾。
因此,指南 summarization.mdx 对max_tokens语义的界定是:
extractive:作为输出摘要的松散 whitespace-token 上限,TextRank 选择器在即将超过上限时停止追加句子;abstractive:只是提示词中的“约 N token”请求提示,不是 provider 的硬性上限;provider 侧的请求限制由SummarizationConfig.llm.max_tokens单独控制。
成功返回的摘要文本(连同捕获的 usage 记录)会写入ExtractedDocument.summary,token 计数由 TextRank 侧的token_count统计;usage 记录以source = "summarisation_abstractive"追加到ExtractedDocument.llm_usage(见 plugins/processor/builtin/summarization.rs)。若 LLM 调用失败,处理器不会静默吞掉异常,而是向processing_warnings推入summarization_abstractive来源的警告;若配置缺少llm字段或未启用summarization-llmfeature,则直接返回校验错误,提醒调用方配置不完整。
输出形状:DocumentSummary
摘要结果序列化为DocumentSummary(定义见 summary.rs),字段包括:
{ "summary": { "text": "The contract sets out a 3-year support agreement with quarterly billing and a fixed escalation cap of 4%.", "strategy": "extractive", "token_count": 19 } }text:摘要正文(纯散文);strategy:产生该摘要的策略(extractive/abstractive);token_count:摘要的近似 token 数(Option<u32>,未知时省略)。
Dart 侧通过result.results[0].summary访问即可,text、strategy、token_count一一对应。
环境变量与 API Key 优先级
抽象式摘要必须能访问 LLM provider。API Key 的解析优先级(来自指南 summarization.mdx):
SummarizationConfig.llm.api_key(配置内显式指定);XBERG_LLM_API_KEY环境变量;- 各 provider 的标准环境变量(如
OPENAI_API_KEY)。
指南还建议:多数文档场景下gpt-4o-mini、claude-3-5-haiku或google/gemini-2.0-flash能取得较好的性价比。在 Dart 测试环境中,注意 e2e 用例 summarization_test.dart 只保留了对 extractive 变体的断言(summary 非空且strategy.wireValue == "extractive"),abstractive 因依赖真实 LLM 服务而由运行时 skip 机制处理,因此本地离线验证时建议先用 extractive 打通链路,再切换 abstractive 观察 LLM 输出。
CLI 与配置文件中的等价写法
摘要配置不止适用于 Dart 绑定,在 CLI / server 场景下写入xberg.toml即可(见 summarization_toml.md):
[summarization] strategy = "extractive" max_tokens = 200抽象式配置则在[summarization]下追加[summarization.llm]子表,字段与 Dart JSON 一一对应:
[summarization] strategy = "abstractive" max_tokens = 150 [summarization.llm] model = "openai/gpt-4o-mini" temperature = 0.0 max_tokens = 200适用边界与使用建议
指南 summarization.mdx 明确了摘要功能的最佳使用场景:需要一段话的 TL;DR 用于索引、搜索 snippet 或快速浏览;需要确定性、无网络依赖的摘要时选 extractive;需要流畅的、供下游 LLM 消费的抽象式行文时选 abstractive。
同时有两类场景不适合直接使用本功能:
- 需要按节(per-section)摘要:先对文档做 chunking,再对每个 chunk 分别摘要;
- 需要跨文档摘要:逐文档摘要后,再用 LLM 后端对摘要做二次摘要。
综上,abstractive摘要是一条“配置即用”的链路:Dart 侧只需把strategy切换为abstractive并附带一份llm配置,底层 Rust 核心便负责提示词构造、输入预算控制、usage 记录与失败诊断。若要进一步深挖实现,可继续阅读 text/summarization/mod.rs、text/summarization/llm.rs 与 types/summary.rs;完整的可复现断言可查看 abstractive_smoke.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 C 绑定下的抽象式(Abstractive)文档摘要:基于 FFI 的 LLM 摘要配置与调用实战
xberg C 绑定下的抽象式(Abstractive)文档摘要:基于 FFI 的 LLM 摘要配置与调用实战 本文以 xberg 仓库中为 C 语言生成的摘要
后端AI 应用NLPXberg Dart 绑定 URI 提取实战:从 URL 与本地路径抽取文档内容
Xberg Dart 绑定 URI 提取实战:从 URL 与本地路径抽取文档内容 本篇技术指南聚焦 Xberg 项目中 Dart 语言绑定的 URI 提取 AP
后端AI 应用NLPxberg C FFI 实战:用 TextRank 抽取式摘要在纯 Rust 核心上生成确定性文档摘要
xberg C FFI 实战:用 TextRank 抽取式摘要在纯 Rust 核心上生成确定性文档摘要 本篇基于 xberg 的 C 语言绑定,讲解如何通过 F
后端AI 应用NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考