
一、关于 LangExtract
1.1 需求痛点
很多时候,我们需要在一堆非标准的文本里面提取特定的字段(比如提取人名
、电话
、地址
等),形成结构化的数据,如保存到 Excel 。数据量不大的情况下,人工就能胜任。如果量很大,就得借助程序(使用规则匹配)来清洗,这种方式比人工高效,但出错率也高。因为程序是非常死板
的,只认设定好的规则
(不会变通),而人工可以在各种未预见的情况下,依然能找到正确的数据,程序则由于不理解自然语言与答案失之交臂😂。
1.2 LangExtract
LangExtract : A Python library for extracting structured information from unstructured text using LLMs with precise source grounding and interactive visualization.
一个 Python 库,用于使用具有精确源基础和交互式可视化的 LLM 从非结构化文本中提取结构化信息。
这个库是 Google 在 2025 年 7 月底发布,目前最新版本是 1.0.8(截至2025-08-22),具有以下特点:
- 精确的源头定位:能将每次提取的内容映射到源文本中的确切位置,可通过可视化突出显示进行追溯和验证。
- 可靠的结构化输出:基于少量示例强制执行一致的输出模式,利用Gemini等支持模型中的受控生成来保证强大的结构化结果,输出可直接接入数据库等下游流程。
- 针对长文档优化:通过优化文本分块、并行处理和多次传递的策略,克服大型文档提取中的困难,提高召回率,能处理完整的小说级别的文档。
- 交互式可视化:可即时生成一个独立的交互式HTML文件,以可视化和审查数千个提取的实体及其原始上下文,方便审核和错误分析。
- 灵活的LLM支持:支持用户偏好的模型,从Google Gemini系列等基于云的LLM到通过内置Ollama接口的本地开源模型都可使用。
- 适应任何领域:只需几个示例,即可为任何领域定义提取任务,无需进行模型微调就能适应用户需求。
LangExtract 在医疗、金融、法律、科研等领域都有广泛的应用前景,例如从临床记录中提取药物名称、剂量,从合同中提取责任条款、风险项等。
1.3 参考文章
二、小试牛刀
本文我们将使用豆包大模型进行实践😄。
2.1 安装依赖
shell
mkdir langextract
# 创建虚拟环境
python -m venv .env
source .env/bin/activate # On Windows: .env\Scripts\activate
# 安装依赖
pip install langextract openai
2.2 简单的人物信息抽取
python
import langextract as lx
# 定义示例
examples = [
lx.data.ExampleData(
text = "梁思成(1901年4月20日-1972年1月9日),籍贯广东新会,生于日本东京。毕生致力于中国古代建筑的研究和保护,是建筑历史学家、建筑教育家和建筑师,被誉为中国近代建筑之父。",
extractions=[
lx.data.Extraction(extraction_class="姓名", extraction_text="梁思成"),
lx.data.Extraction(extraction_class="出生日期", extraction_text="1901年4月20日"),
lx.data.Extraction(extraction_class="逝世日期", extraction_text="1972年1月9日"),
lx.data.Extraction(extraction_class="出生地", extraction_text="日本东京"),
lx.data.Extraction(extraction_class="职业", extraction_text="建筑历史学家、建筑教育家、建筑师"),
lx.data.Extraction("荣誉", "中国近代建筑之父")
]
),
lx.data.ExampleData(
text = "林徽因(1904年6月10日-1955年4月1日),原名"徽音",汉族,祖籍福建闽侯(今福建福州),出生于浙江杭州。为中国近现代建筑学家、文学家,清华大学建筑系教授。",
extractions=[
lx.data.Extraction(extraction_class="姓名", extraction_text="林徽因"),
lx.data.Extraction(extraction_class="出生日期", extraction_text="1904年6月10日"),
lx.data.Extraction(extraction_class="逝世日期", extraction_text="1955年4月1日"),
lx.data.Extraction(extraction_class="出生地", extraction_text="浙江杭州"),
lx.data.Extraction(extraction_class="职业", extraction_text="建筑学家、文学家"),
lx.data.Extraction("荣誉", "")
]
)
]
# 配置模型并调用解析程序
result = lx.extract(
text_or_documents="古龙(1938年6月7日一1985年9月21日),原名熊耀华,籍贯江西南昌,汉族。1938年6月7日出生于香港。武侠小说家,新派武侠小说泰斗,与金庸、梁羽生、温瑞安并称为中国武侠小说四大宗师。",
prompt_description="从人物简要介绍中提取姓名、出生日期、逝世日期(如有)、出生地、职业、荣耀/成就",
examples = examples,
config= lx.factory.ModelConfig(
model_id="doubao-seed-1-6-flash-250615",
provider="OpenAILanguageModel",
provider_kwargs={
"temperature" : 0.1,
"max_tokens" : 2048,
"base_url" : "https://ark.cn-beijing.volces.com/api/v3",
"api_key" : ""
}
)
)
for entity in result.extractions:
position_info = ""
if entity.char_interval:
start, end = entity.char_interval.start_pos, entity.char_interval.end_pos
position_info = f" (位置: {start}-{end})"
print(f"• {entity.extraction_class.capitalize()}: {entity.extraction_text}{position_info}")
我们执行python index.py
,大概 5 秒就能看到结果。
2.3 提取公共资源交易信息
我之前写过一篇Chrome插件 | 公共资源交易平台中标公示数据采集工具(仅作技术交流学习)的文章,里面就涉及结构化信息提取,当时用的是专家规则+正则表达式
从文本中匹配结果,现在让我们试下 langextract 是否能做的更好😄。
2.3.1 准备示例

2.3.2 运行结果
从上面的结果来看,提取的数据是准确的(耗时大概10秒),不过还多了一个结果(数据基本是空白),可以在程序中控制只要第一个结果即可😄。
三、JavaScript 版本
在 github 上有一个 typescript 版本的实现:kmbro/langextract-typescript。
A TypeScript translation of the original Python LangExtract library by Google LLC. This library provides structured information extraction from text using Large Language Models (LLMs) with full TypeScript support, comprehensive visualization tools, and a powerful CLI interface.
js
import { extract } from "langextract"
/**@type {Array<import("langextract").ExampleData>} */
const examples = [
{
text:"梁思成(1901年4月20日-1972年1月9日),籍贯广东新会,生于日本东京。毕生致力于中国古代建筑的研究和保护,是建筑历史学家、建筑教育家和建筑师,被誉为中国近代建筑之父。",
extractions:[
{ extractionClass:"姓名", extractionText:"梁思成"},
{ extractionClass:"出生日期", extractionText:"1901年4月20日"},
{ extractionClass:"逝世日期", extractionText:"1972年1月9日"},
{ extractionClass:"出生地", extractionText:"日本东京"},
{ extractionClass:"职业", extractionText:"建筑历史学家、建筑教育家、建筑师"},
{ extractionClass:"荣誉", extractionText:"中国近代建筑之父"}
]
},
{
text:"林徽因(1904年6月10日-1955年4月1日),原名"徽音",汉族,祖籍福建闽侯(今福建福州),出生于浙江杭州。为中国近现代建筑学家、文学家,清华大学建筑系教授。",
extractions:[
{ extractionClass:"姓名", extractionText:"林徽因" },
{ extractionClass:"出生日期", extractionText:"1904年6月10日"},
{ extractionClass:"逝世日期", extractionText:"1955年4月1日"},
{ extractionClass:"出生地", extractionText:"浙江杭州"},
{ extractionClass:"职业", extractionText:"建筑学家、文学家"},
{ extractionClass:"荣誉", extractionText:""}
]
}
]
extract(
"古龙(1938年6月7日一1985年9月21日),原名熊耀华,籍贯江西南昌,汉族。1938年6月7日出生于香港。武侠小说家,新派武侠小说泰斗,与金庸、梁羽生、温瑞安并称为中国武侠小说四大宗师。",
{
promptDescription :"从人物简要介绍中提取姓名、出生日期、逝世日期(如有)、出生地、职业、荣耀/成就",
examples,
modelType : 'openai',
modelId : 'doubao-seed-1-6-flash-250615',
baseURL : 'https://ark.cn-beijing.volces.com/api/v3',
apiKey : '',
temperature : 0.1,
debug : true
}
)
.then(result=>{
console.debug(`documentId=${result.documentId}`)
console.debug(result.extractions)
})
.catch(e=>console.debug(e))
很遗憾,这个代码执行后没有任何结果😔,感觉是对大模型的兼容性还不够高。

四、Rust 版本
目前我在 github 找到两个 Rust 的实现:modularflow/langextract-rust、daleione/langextract。
rust
use langextract_rust::{extract, ExtractConfig, data::{ExampleData, Extraction}, providers::ProviderConfig, LangExtractError};
#[tokio::main]
async fn main()->Result<(), LangExtractError> {
// 获取环境变量,不存在会返回 Err
let api_key = std::env::var("API_KEY").expect("请设置 API_KEY 环境变量");
println!(" API_KEY={}\n", api_key);
// 提取示例
let examples = vec![
ExampleData::new(
"梁思成(1901年4月20日-1972年1月9日),籍贯广东新会,生于日本东京。毕生致力于中国古代建筑的研究和保护,是建筑历史学家、建筑教育家和建筑师,被誉为中国近代建筑之父。".to_string(),
vec![
Extraction::new("姓名".to_string(), "梁思成".to_string()),
Extraction::new("出生日期".to_string(), "1901年4月20日".to_string()),
Extraction::new("逝世日期".to_string(), "1972年1月9日".to_string()),
Extraction::new("出生地".to_string(), "日本东京".to_string()),
Extraction::new("职业".to_string(), "建筑历史学家、建筑教育家、建筑师".to_string()),
Extraction::new("荣誉".to_string(), "中国近代建筑之父".to_string())
]
),
ExampleData::new(
"林徽因(1904年6月10日-1955年4月1日),原名"徽音",汉族,祖籍福建闽侯(今福建福州),出生于浙江杭州。为中国近现代建筑学家、文学家,清华大学建筑系教授。".to_string(),
vec![
Extraction::new("姓名".to_string(), "林徽因".to_string()),
Extraction::new("出生日期".to_string(), "1904年6月10日".to_string()),
Extraction::new("逝世日期".to_string(), "1955年4月1日".to_string()),
Extraction::new("出生地".to_string(), "浙江杭州".to_string()),
Extraction::new("职业".to_string(), "建筑学家、文学家".to_string()),
Extraction::new("荣誉".to_string(), "".to_string())
]
)
];
// 配置大模型
let custom_config = ProviderConfig::custom("https://ark.cn-beijing.volces.com/api/v3", "doubao-seed-1-6-flash-250615")
.with_api_key(api_key.clone());
println!(" Provider Type: {}", custom_config.provider_type);
println!(" Base URL: {}", custom_config.base_url);
println!(" Model: {}", custom_config.model);
println!(" Headers: {:?}", custom_config.headers);
let extract_config = ExtractConfig {
model_id: "doubao-seed-1-6-flash-250615".to_string(),
model_url: Some("https://ark.cn-beijing.volces.com/api/v3".to_string()),
api_key: Some(api_key.clone()),
..Default::default()
};
let result = extract(
"古龙(1938年6月7日一1985年9月21日),原名熊耀华,籍贯江西南昌,汉族。1938年6月7日出生于香港。武侠小说家,新派武侠小说泰斗,与金庸、梁羽生、温瑞安并称为中国武侠小说四大宗师。",
Some("从人物简要介绍中提取姓名、出生日期、逝世日期(如有)、出生地、职业、荣耀/成就"),
&examples,
extract_config
).await?;
println!("✅ Extracted {} items", result.extraction_count());
// Show extractions with character positions
if let Some(extractions) = &result.extractions {
for extraction in extractions {
println!("• [{}] '{}' at {:?}",
extraction.extraction_class,
extraction.extraction_text,
extraction.char_interval
);
}
}
Ok(())
}
上述代码使用的是 ,可惜没跑成功😂,报错ConfigurationError("Custom provider inference not yet implemented")
,我在 github 上提了 issue,希望能够得到解决。
Java 版本
目前我还没有找到 Java 实现的版本,是不是一个机会😄?