Google 悄悄开源了一个「数据提取神器」,3 行代码干掉你 500 行正则
你还在用正则表达式从 LLM 输出里抠 JSON 吗?Google 工程师受不了了,直接开源了 LangExtract——一行 lx.extract() 解决所有结构化提取的痛。
💢 痛点:LLM 时代最被低估的脏活
2026 年了,大模型的能力早已不是瓶颈。真正的瓶颈是什么?
是把大模型的输出变成你代码能用的数据。
想象一下这个场景:你让 GPT 帮你从一份 50 页的财报里提取关键财务数据。模型很聪明,回答得头头是道。但你要的不是一段话——你要的是一个干干净净的 JSON,能直接灌进数据库。
于是你开始写代码:
# 😭 你的日常
import re, json
response = llm.generate("从以下文本提取财务数据...")
# 哦不,模型输出了 ```json 包裹的内容
text = re.search(r'```json\s*(.*?)\s*```', response, re.DOTALL)
if text:
try:
data = json.loads(text.group(1))
except json.JSONDecodeError:
# 模型偶尔输出不合法 JSON,加个修复逻辑...
data = fix_json(text.group(1)) # 又是 100 行
else:
# 模型没用代码块包裹,试试直接解析...
try:
data = json.loads(response)
except:
# 算了,用正则硬扣吧... 😤
pass这还只是第一步。 如果文本超过模型的上下文窗口呢?你得自己分块。分块之后不同块的结果怎么合并?怎么去重?提取出来的内容怎么映射回原文位置?
这套"脏活",几乎每个用 LLM 做数据提取的开发者都在重复造轮子。
Google 的工程师终于忍不了了。

▲ 传统方式 vs LangExtract 对比:一边是无尽的调试深渊,一边是 3 行代码准时下班
🚀 LangExtract:Google 的答案
LangExtract 是 Google 在 2025 年底开源的一个 Python 库,目标很明确:
用最少的代码,从任意文本中提取结构化数据——自动分块、自动并发、自动对齐、自动去重。
项目地址:https://github.com/google/langextract

直接看核心 API,感受一下它的简洁度:
import langextract as lx
result = lx.extract(
"一大段非结构化文本...",
prompt_description="提取所有人物及其职位",
examples=[...], # Few-shot 示例
model_id="gemini-2.5-flash"# 支持 Gemini/GPT/Ollama
)
lx.visualize(result) # 一行可视化3 行代码,完事了。 没有正则,没有 JSON 修复,没有手动分块。

▲ LangExtract 核心工作流:从原始文本到结构化数据的全自动管线
🧠 它到底解决了什么?5 大核心痛点逐个击破
痛点 1:长文本分块是个噩梦
你有一份 10 万字的合同,模型上下文窗口只有 8K tokens。怎么办?
❌ 传统做法: 手动按字数切分,祈祷切分点不会把一句话劈成两半。
✅ LangExtract: 内置智能分块引擎,基于句子边界分块,支持跨块上下文窗口( context_window_chars ),让模型在处理当前块时能"看到"上一块的尾部内容,解决跨块指代问题(比如"她"指的是上一段提到的某个人)。
result = lx.extract(
超长文本,
context_window_chars=500, # 跨块上下文重叠 500 字符
max_char_buffer=2000, # 每块最大 2000 字符
...
)痛点 2:LLM 输出格式不可控
模型有时候输出 json ... ,有时候直接输出裸 JSON,有时候夹杂废话。传统方案需要你写一堆 Parser。
✅ LangExtract: 内置 Resolver 解析器,自动处理各种输出格式,支持 JSON 和 YAML,还有模糊对齐( fuzzy_alignment )功能——即使模型输出的文本和原文不完全一致,也能正确定位到原文中的位置。
痛点 3:提取结果无法溯源
你从一篇论文里提取了 20 个实体,但你不知道每个实体是从原文的哪个位置提取的。
✅ LangExtract: 返回的 AnnotatedDocument 对象包含完整的原文映射信息( char_interval ),精确到字符级别。配合 lx.visualize() ,直接在 Jupyter Notebook 里高亮显示提取结果在原文中的位置。
痛点 4:处理速度太慢
1000 条文本顺序调用 API,等到天荒地老。
✅ LangExtract: 内置批量并发处理,默认 10 个 worker 并行调用 LLM API。处理大批量数据时,还支持 Gemini Batch API 做离线批处理。
result = lx.extract(
documents,
batch_length=20, # 每批 20 个文本块
max_workers=10, # 10 路并发
...
)痛点 5:切换模型要重写代码
今天用 Gemini,明天想试试 GPT-4,后天又想跑个本地 Ollama。每个模型 API 不一样,代码改到吐。
✅ LangExtract: 统一的 Provider 抽象层,切换模型只需改一个参数:
# 用 Google Gemini
lx.extract(..., model_id="gemini-2.5-flash")
# 切换到 OpenAI
lx.extract(..., model_id="gpt-4o")
# 用本地 Ollama
lx.extract(..., model_id="llama3", model_url="http://localhost:11434")而且支持 插件机制 ——第三方可以通过 Python entry_points 注册自定义 Provider, pip install 后自动可用,零配置。

▲ 并发处理流程:自动分块 → 多路并发调 LLM → 解析合并 → 返回结果
🏗️ 架构设计:分层解耦的正确示范
LangExtract 的代码架构非常优雅,值得学习:
🎯 用户 API 层
├── lx.extract() ← 主入口
└── lx.visualize() ← 可视化
⚙️ 处理管线层
├── Chunking ← 智能分块
├── Prompting ← Few-shot 提示词构建
├── Annotation ← 标注引擎(并发调度)
└── Resolver ← 结果解析 + 模糊对齐
🔌 提供者层(可扩展)
├── Gemini ← Google AI
├── OpenAI ← GPT 系列
├── Ollama ← 本地推理
└── Plugin System ← 第三方扩展
🏗️ 核心层
├── BaseLanguageModel ← 模型接口
├── Data Types ← Schema + 数据类型
└── Tokenizer ← 分词器
▲ 分层架构图:严格的单向依赖,上层依赖下层,绝不反向
几个设计亮点:
- 严格的依赖方向:Core 层不依赖 Providers,Providers 不依赖 Annotation。通过 import-linter 在 CI 中强制执行。
- 注册表模式:模型 ID 通过正则匹配自动路由到对应 Provider,用户无需关心底层实现。
- PEP 562 懒加载:import langextract 时不会立即加载所有子模块,首次访问时才加载,启动快。
🔥 实战场景:它能干什么?
| 场景 | 传统做法 | LangExtract |
|---|---|---|
| 从新闻中提取人物和事件 | 写 NER + 关系抽取模型 | 3 行代码 |
| 解析简历提取教育经历和工作经验 | 正则 + 模板匹配 | 3 行代码 |
| 从合同中提取关键条款 | 法律 NLP 专用模型 | 3 行代码 |
| 医疗报告结构化 | 领域专用标注 + 训练 | 3 行代码 |
| 从论文中提取方法论和结果 | 手动整理 | 3 行代码 |
共同点:你只需要告诉模型"提取什么"、给几个示例,剩下的交给 LangExtract。
📝 快速上手
安装
pip install langextract
# 如果要用 OpenAI
pip install langextract[openai]
# 如果要用本地 Ollama
# 确保 Ollama 服务已运行完整示例
import langextract as lx
from langextract.core.data import ExampleData
# 定义示例(告诉模型你要什么格式)
examples = [
ExampleData(
text="张三是腾讯的高级工程师,在深圳工作。",
extractions=[{
"name": "张三",
"company": "腾讯",
"title": "高级工程师",
"location": "深圳"
}]
)
]
# 一行提取
result = lx.extract(
"李四于 2024 年加入阿里巴巴,担任算法专家,base 杭州。"
"王五是字节跳动的产品经理,常驻北京。",
prompt_description="从文本中提取人物的姓名、公司、职位和工作地点",
examples=examples,
model_id="gemini-2.5-flash"
)
# 可视化结果
lx.visualize(result)🤔 和 Instructor / LangChain 有什么区别?
你可能会问:这不是和 instructor 或 LangChain 的结构化输出差不多吗?
区别很大:
| 特性 | LangExtract | Instructor | LangChain |
|---|---|---|---|
| 长文本自动分块 | ✅ 内置 | ❌ 自己写 | ❌ 自己写 |
| 跨块上下文窗口 | ✅ 内置 | ❌ | ❌ |
| 提取结果溯源 | ✅ 字符级定位 | ❌ | ❌ |
| 结果可视化 | ✅ 内置 | ❌ | ❌ |
| 模糊文本对齐 | ✅ 内置 | ❌ | ❌ |
| 多轮提取去重 | ✅ extraction_passes | ❌ | ❌ |
| 批量并发 | ✅ 内置 | ❌ | 需额外配置 |
简单说: Instructor 解决的是"让 LLM 输出结构化数据"这一个点,LangExtract 解决的是从非结构化文本到结构化数据的完整管线。
💡 值得关注的技术细节
多轮提取(Multi-pass Extraction)
对于信息密度很高的文本,单次提取可能遗漏。LangExtract 支持多轮提取:
result = lx.extract(
dense_text,
extraction_passes=3, # 提取 3 轮,自动合并去重
...
)每轮独立提取,最后自动合并,先提取到的结果优先(first-pass wins),重叠部分自动去重。
URL 自动下载
# 直接传 URL,自动下载网页内容并提取
result = lx.extract(
"https://example.com/article",
...
)Prompt 验证
提供了 Few-shot 示例的自动验证机制,在提取之前就检查你的示例是否和文本对齐,提前发现问题:
result = lx.extract(
...,
prompt_validation_level="ERROR", # 示例不对齐直接报错
prompt_validation_strict=True,
)📊 项目数据
- GitHub Stars: 快速增长中 ⭐
- 版本: v1.1.1(活跃维护)
- 许可证: Apache 2.0(商用友好)
- Python: ≥ 3.10
- DOI: 10.5281/zenodo.17015089(可学术引用)
- 代码质量: 完整测试套件 + import-linter 依赖检查 + 类型注解
🎯 总结
LangExtract 不是又一个 LLM wrapper。它解决的是一个非常具体且普遍的痛点:
如何从大规模非结构化文本中,可靠地、可追溯地、高效地提取结构化数据。
在 LLM 时代,这个问题几乎每个做数据处理的团队都会遇到。Google 用一个设计优雅的开源工具给出了标准答案。
如果你的工作涉及到:
- 📄 文档解析(合同、财报、简历)
- 🏥 医疗 NLP(病历结构化、药品信息提取)
- 📰 信息抽取(新闻、社交媒体、研究论文)
- 🏗️ 数据管线(ETL 中的非结构化数据处理)
强烈建议收藏这个项目。