Files
GraphRAGAgent/docs/langextract_specification-v1.0.md
plf b02d3378fc GraphRAG Studio — initial commit: multimodal RAG system with KG visualization
Full-stack application for document-to-knowledge-graph pipeline:
- Backend: FastAPI + LangGraph ReAct agent + DeepSeek + MinerU parsing
- Frontend: React 19 + Vite + D3.js + shadcn/ui
- Pipeline: MinerU parsing → LangExtract entity extraction → KG building

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 17:30:04 +08:00

22 KiB
Raw Blame History

LangExtract Pipeline 规范文档 v1.0

基于 google/langextract 源码分析 + MVP 实测验证 版本基线2026-03-04 main 分支 本地源码路径:F:\GraphRAGAgent\langextract_src\ 测试脚本路径:F:\GraphRAGAgent\langextract_src\mvp_test_deepseek.py


目录


〇、虚拟环境

本组件使用独立的 Python 虚拟环境与项目其他组件MinerU MVP、GraphRAG Pipeline 等)完全隔离。

所有 Python 命令必须在子虚拟环境中运行,禁止使用全局 Python 或其他组件的 venv。

环境信息

  • 虚拟环境路径:F:\GraphRAGAgent\langextract_src\.venv\
  • Python 版本3.12
  • 创建工具uv
  • 安装方式:uv pip install -e ".[all]" (含 openai、google-genai 等 60 个包)

运行方式

方式一:直接使用 venv 内的 Python 解释器(推荐)

F:/GraphRAGAgent/langextract_src/.venv/Scripts/python.exe mvp_test_deepseek.py

方式二:先激活环境再运行

cd F:/GraphRAGAgent/langextract_src
source .venv/Scripts/activate
python mvp_test_deepseek.py

安装新依赖

uv pip install <package> --python F:/GraphRAGAgent/langextract_src/.venv/Scripts/python.exe

一、Pipeline 执行流程

1.1 完整执行链路

基于 MVP 实测验证的完整 Pipeline 分为 5 个阶段:

Step 0: 激活虚拟环境
  └── F:/GraphRAGAgent/langextract_src/.venv/Scripts/python.exe

Step 1: 准备输入
  ├── 构造纯文本字符串str
  ├── 或构造 Document 对象列表
  └── LangExtract 仅接受纯文本PDF/DOCX 等需前置解析

Step 2: 构造 Few-shot 示例
  ├── 创建 ExampleData 对象列表
  ├── 每个 ExampleData 包含text示例文本 + extractions标注实体列表
  └── extraction_text 必须是 text 的精确子串

Step 3: 配置模型并调用 extract()
  ├── 直接实例化 OpenAILanguageModelDeepSeek 场景)
  ├── 传入 model_id="deepseek-chat", base_url, api_key
  └── 调用 lx.extract(text_or_documents=..., examples=..., model=model)

Step 4: LangExtract 内部处理
  ├── 文本分块基于句子边界max_char_buffer=1000
  ├── 构造 Prompt含 prompt_description + examples
  ├── 调用 LLM 推理JSON 格式输出)
  ├── 解析 LLM JSON 响应为 Extraction 对象
  └── 字符级对齐char_interval + alignment_status

Step 5: 保存输出
  ├── lx.io.save_annotated_documents() → JSONL 文件
  └── 自定义 JSON 摘要(可选)

1.2 MVP 测试脚本

文件路径: F:\GraphRAGAgent\langextract_src\mvp_test_deepseek.py

执行命令:

F:/GraphRAGAgent/langextract_src/.venv/Scripts/python.exe mvp_test_deepseek.py

脚本核心流程:

from langextract.providers.openai import OpenAILanguageModel

# Step 1: 直接实例化 OpenAI Provider指向 DeepSeek
model = OpenAILanguageModel(
    model_id="deepseek-chat",
    api_key="sk-...",
    base_url="https://api.deepseek.com",
)

# Step 2: 构造示例数据
examples = [
    lx.data.ExampleData(
        text="LangChain is a framework created by Harrison Chase...",
        extractions=[
            lx.data.Extraction(extraction_class="TECHNOLOGY", extraction_text="LangChain"),
            lx.data.Extraction(extraction_class="ORGANIZATION", extraction_text="Harrison Chase"),
            ...
        ],
    )
]

# Step 3: 调用抽取
result = lx.extract(
    text_or_documents=input_text,
    prompt_description="Extract named entities...",
    examples=examples,
    model=model,
    show_progress=True,
)

# Step 4: 保存结果
lx.io.save_annotated_documents([result], output_name="graphrag_entities.jsonl", output_dir="mvp_output")

实测结果:

指标
输入文本长度 520 字符
模型 deepseek-chat
耗时 21.6 秒
提取实体数 17
实体类型分布 TECHNOLOGY: 9, CONCEPT: 7, ORGANIZATION: 1
精确匹配率 16/17 (94.1%) — 仅 1 个 match_fuzzy
输出文件 2 个JSONL + JSON 摘要)

1.3 输入规范

LangExtract 仅接受纯文本作为输入,支持以下 4 种传入方式:

输入方式 示例 说明
纯文本字符串 extract("这是一段文本...") 直接传入文本内容MVP 实测使用此方式)
URL extract("https://example.com/article.txt") 自动下载 URL 文本内容(fetch_urls=True
Document 对象 extract([Document(text="...", document_id="doc1")]) 传入 Document 可迭代集合
CSV 文件 通过 Dataset 类加载后传入 指定 text 列和 id 列

1.4 不支持的输入格式

以下格式 不被支持,需要在 LangExtract 之前通过外部工具预处理为纯文本:

格式 状态 预处理方案
PDF 不支持 使用 MinerU / PyMuPDF 先转文本
DOCX 不支持 使用 python-docx 先转文本
HTML 不支持 使用 BeautifulSoup 先提取文本
图片 不支持 使用 OCR 工具先识别文本
Markdown含媒体 不支持 需提取纯文本部分
Excel / JSON 不支持 需序列化为纯文本

二、模型接入规范

2.1 模型路由机制

文件路径:langextract/providers/patterns.py

LangExtract 通过 正则匹配 model_id 自动路由到对应的 Provider

Provider 匹配模式 优先级 示例模型
Gemini ^gemini 10 gemini-2.5-flash, gemini-1.5-pro
OpenAI ^gpt-4, ^gpt4., ^gpt-5, ^gpt5. 10 gpt-4o, gpt-4o-mini
Ollama gemma, llama, mistral, phi, qwen, deepseek 10 gemma2:2b, llama3.2:1b

2.2 DeepSeek 接入(实测验证)

重要发现: 规范文档 v0 中描述的 model_id="gpt-4o-mini" + language_model_params={"base_url": ...} 方式 实测不可用,因为 model_id 同时用于路由和 API 调用DeepSeek 不识别 gpt-4o-mini 模型名。

正确方式 — 直接实例化 OpenAI Provider

from langextract.providers.openai import OpenAILanguageModel

model = OpenAILanguageModel(
    model_id="deepseek-chat",           # DeepSeek 实际模型名
    api_key="sk-your-deepseek-key",
    base_url="https://api.deepseek.com",
)

result = lx.extract(
    text_or_documents="...",
    examples=[...],
    model=model,                         # 通过 model 参数传入,绕过路由
    show_progress=True,
)

实测验证状态: DeepSeek deepseek-chat 模型通过此方式成功完成实体抽取JSON 格式输出正常。

2.3 路由陷阱与规避方案

方案 能否工作 原因
model_id="gpt-4o-mini" + language_model_params={"base_url": "https://api.deepseek.com"} 不能 model_id 被同时用作 API 调用的 model 参数DeepSeek 返回 400 Model Not Exist
config=ModelConfig(model_id="deepseek-chat", provider="openai") 不能 _create_model_with_schema() 中使用 provider 时未先调用 load_builtins_once(),导致 No provider found 错误LangExtract 内部 bug
model=OpenAILanguageModel(model_id="deepseek-chat", ...) 可以 直接实例化绕过路由,model_id 正确传递给 DeepSeek API

2.4 OpenAI Provider 构造参数

文件路径:langextract/providers/openai.py

class OpenAILanguageModel(BaseLanguageModel):
    def __init__(
        self,
        model_id: str = 'gpt-4o-mini',
        api_key: str | None = None,
        base_url: str | None = None,
        organization: str | None = None,
        format_type: FormatType = FormatType.JSON,
        temperature: float | None = None,
        max_workers: int = 10,
        **kwargs,
    )
参数 默认值 说明
model_id gpt-4o-mini 模型标识(同时作为 API 调用的 model 参数)
api_key None 环境变量:OPENAI_API_KEYLANGEXTRACT_API_KEY
base_url None 自定义 API 端点DeepSeek 使用 https://api.deepseek.com
temperature None 采样温度
format_type JSON 输出格式JSON Mode

三、关键参数规范

3.1 extract() 核心参数

文件路径:langextract/extraction.py

def extract(
    text_or_documents: typing.Any,          # 必填:纯文本或 Document 列表
    prompt_description: str | None = None,  # 抽取提示词
    examples: typing.Sequence[Any] | None = None,  # 必填Few-shot 示例
    model_id: str = "gemini-2.5-flash",     # 模型标识(用于路由)
    api_key: str | None = None,             # API Key
    model: typing.Any = None,               # 预配置的模型实例(最高优先级)
    max_char_buffer: int = 1000,            # 分块最大字符数
    temperature: float | None = None,       # 采样温度
    batch_length: int = 10,                 # 每批分块数
    max_workers: int = 10,                  # 最大并行线程
    additional_context: str | None = None,  # 附加上下文
    resolver_params: dict | None = None,    # 对齐参数
    language_model_params: dict | None = None,  # Provider 构造参数
    extraction_passes: int = 1,             # 抽取轮次
    context_window_chars: int | None = None, # 上下文窗口
    config: typing.Any = None,              # ModelConfig 实例
    model_url: str | None = None,           # 自托管端点
    show_progress: bool = True,             # 显示进度条
    ...
) -> list[AnnotatedDocument] | AnnotatedDocument

MVP 实测使用的参数组合:

参数 实测值 说明
text_or_documents 520 字符纯文本 GraphRAG 领域相关文本
prompt_description "Extract named entities..." 指定 TECHNOLOGY/ORGANIZATION/CONCEPT 三类
examples 1 个 ExampleData含 6 个 Extraction Few-shot 示例
model OpenAILanguageModel 实例 直接实例化,指向 DeepSeek
show_progress True 显示进度
max_char_buffer 1000默认 文本未超过阈值,未触发分块

3.2 ExampleData 示例数据格式

文件路径:langextract/core/data.py

@dataclasses.dataclass
class ExampleData:
    text: str                                    # 示例文本(必填)
    extractions: list[Extraction]                # 标注的实体列表(必填)

MVP 实测示例:

lx.data.ExampleData(
    text="LangChain is a framework created by Harrison Chase for building "
         "LLM applications. It integrates with OpenAI models and Pinecone "
         "vector database for semantic search.",
    extractions=[
        lx.data.Extraction(extraction_class="TECHNOLOGY", extraction_text="LangChain"),
        lx.data.Extraction(extraction_class="ORGANIZATION", extraction_text="Harrison Chase"),
        lx.data.Extraction(extraction_class="CONCEPT", extraction_text="LLM applications"),
        lx.data.Extraction(extraction_class="TECHNOLOGY", extraction_text="OpenAI models"),
        lx.data.Extraction(extraction_class="TECHNOLOGY", extraction_text="Pinecone"),
        lx.data.Extraction(extraction_class="CONCEPT", extraction_text="semantic search"),
    ],
)

约束条件:

  • extraction_text 必须是 text 的精确子串(否则对齐失败)
  • extraction_class 为自定义字符串,无预定义枚举
  • examples 列表不能为空(否则抛出 ValueError
  • 每个 ExampleData 可包含多个不同 extraction_class 的条目

3.3 Extraction 示例条目格式

@dataclasses.dataclass(init=False)
class Extraction:
    extraction_class: str                     # 必填:实体类型
    extraction_text: str                      # 必填:实体文本(须为原文子串)
    attributes: dict[str, str | list[str]] | None = None  # 可选:附加属性
    description: str | None = None            # 可选:实体描述

在 examples 中创建时只需要 extraction_classextraction_text,其余字段由 LangExtract 在推理后自动填充。

3.4 分块参数

文件路径:langextract/chunking.py

LangExtract 使用基于 句子边界 的确定性分块策略:

参数 默认值 说明
max_char_buffer 1000 每个分块最大字符数
context_window_chars None 前一分块的上下文窗口(用于指代消解)
batch_length 10 每批处理的分块数

分块策略:

  1. 如果单个句子超过 max_char_buffer,按换行符拆分
  2. 如果单个 token 超过 max_char_buffer,该 token 独占一个分块
  3. 如果多个句子可以放入 max_char_buffer,合并为一个分块

MVP 实测: 输入文本 520 字符 < max_char_buffer1000整段文本作为单一分块处理未触发分块逻辑。

3.5 Resolver 对齐参数

通过 extract()resolver_params 字典传入:

参数 类型 默认值 说明
enable_fuzzy_alignment bool True 精确匹配失败后是否尝试模糊匹配
fuzzy_alignment_threshold float 0.75 模糊匹配最低 token 重叠比率
accept_match_lesser bool True 是否接受部分精确匹配
suppress_parse_errors bool False JSON 解析失败时是否继续

MVP 实测: 未传入 resolver_params使用全部默认值。17 个抽取中 16 个 match_exact1 个 match_fuzzy"Microsoft Research")。


四、输出数据格式规范

4.1 JSONL 输出文件(实际生成)

文件路径: mvp_output/graphrag_entities.jsonl 文件大小: 4,650 bytes 格式: JSONLJSON Lines每行一个完整的 JSON 对象

保存 API

lx.io.save_annotated_documents(
    [result],
    output_name="graphrag_entities.jsonl",
    output_dir="mvp_output"
)

4.2 AnnotatedDocument 顶层结构

实际 JSONL 输出的顶层字段(基于本地生成文件):

字段 类型 实测值 说明
text string 520 字符 原始输入文本(完整保留)
document_id string "doc_8498f2b6" 自动生成,格式 doc_{uuid_hex[:8]}
extractions array[Extraction] 17 个元素 抽取的实体列表

注意: JSONL 中字段顺序为 extractionstextdocument_id(与 dataclass 定义顺序不同,以实际输出为准)。

4.3 Extraction 字段规范(实测对比)

实际输出的单条 Extraction 完整结构(摘自本地 JSONL 文件):

{
  "extraction_class": "TECHNOLOGY",
  "extraction_text": "GraphRAG",
  "char_interval": {
    "start_pos": 0,
    "end_pos": 8
  },
  "alignment_status": "match_exact",
  "extraction_index": 1,
  "group_index": 0,
  "description": null,
  "attributes": {}
}

实测字段对比(官方 Schema vs 实际输出):

字段 官方 Schema 实际输出 差异说明
extraction_class string string 一致
extraction_text string string 一致
char_interval object | null object(始终存在) 实测 17 个全部有值
alignment_status string | null string(始终存在) 实测 17 个全部有值
extraction_index int | null int(从 1 开始) 实测从 1 开始,非 0
group_index int | null int(从 0 开始) 实测从 0 开始递增
description string | null null 未使用 description 提示时为 null
attributes dict | null {}(空对象) 实测为空对象 {},非 null
token_interval object | null 不存在 实际 JSONL 输出中无此字段

关键差异总结:

  1. extraction_index1 开始(非 0
  2. attributes 未使用时输出空对象 {}(非 null
  3. token_interval 字段 不在 JSONL 输出中(仅存在于内存对象)

4.4 CharInterval 字符锚点

{
  "start_pos": 0,
  "end_pos": 8
}
  • start_pos起始位置包含0-indexed
  • end_pos:结束位置(不包含)
  • 语义:source_text[start_pos:end_pos] 即为实体在原文中的精确位置

实测验证(以 "GraphRAG" 为例):

text = "GraphRAG is an advanced..."
text[0:8]  # → "GraphRAG"  ✓ 匹配

4.5 AlignmentStatus 对齐状态枚举

状态值 序列化值 含义 可信度 MVP 实测数量
MATCH_EXACT "match_exact" LLM 输出与原文完全匹配 最高 16
MATCH_GREATER "match_greater" LLM 输出短于匹配到的原文 0
MATCH_LESSER "match_lesser" LLM 输出长于匹配到的原文 0
MATCH_FUZZY "match_fuzzy" 模糊匹配 1
None null 未找到对齐 不可信 0

实测精确匹配率: 16/17 = 94.1%。唯一的 match_fuzzy 是 "Microsoft Research"。

4.6 extraction_summary.json自定义摘要

文件路径: mvp_output/extraction_summary.json 文件大小: 2,863 bytes

此文件由 MVP 测试脚本自行生成(非 LangExtract 原生输出),结构如下:

{
  "total_extractions": 17,
  "extraction_classes": {
    "TECHNOLOGY": 9,
    "ORGANIZATION": 1,
    "CONCEPT": 7
  },
  "extractions": [
    {
      "class": "TECHNOLOGY",
      "text": "GraphRAG",
      "char_start": 0,
      "char_end": 8,
      "alignment": "match_exact"
    }
  ]
}

五、本地生成文件清单

MVP 测试后本地实际生成的文件(共 2 个输出文件):

langextract_src/
├── .env                            # DeepSeek API Key 配置
├── .venv/                          # 独立虚拟环境Python 3.12
├── mvp_test_deepseek.py            # MVP 测试脚本
└── mvp_output/                     # 输出目录
    ├── graphrag_entities.jsonl     # LangExtract 原生 JSONL 输出4,650 bytes
    └── extraction_summary.json    # 自定义 JSON 摘要2,863 bytes
文件 大小 来源 说明
graphrag_entities.jsonl 4,650 bytes lx.io.save_annotated_documents() LangExtract 原生输出1 行 JSONL含 17 个 Extraction
extraction_summary.json 2,863 bytes MVP 脚本自定义 扁平化摘要,含类型分布统计

附录:环境变量与常量速查

环境变量

变量名 适用 Provider 说明
LANGEXTRACT_API_KEY 所有 通用 API Key 后备
GEMINI_API_KEY Gemini Gemini API Key
OPENAI_API_KEY OpenAI OpenAI / DeepSeek API Key
OLLAMA_BASE_URL Ollama Ollama 服务地址(默认 http://localhost:11434

.env 配置MVP 实测)

OPENAI_API_KEY=sk-55cb39b8a3284355bc80217c11c85d1f

模型优先级

model预配置的模型实例 > configModelConfig 实例) > model_id + api_key

MVP 实测使用 model 参数(最高优先级),直接传入 OpenAILanguageModel 实例。

结构化输出支持

Provider Schema 类型 结构化输出模式
Gemini GeminiSchema 严格结构化输出
OpenAI JSON Mode 通过 response_format 约束
Ollama FormatModeSchema JSON 模式(非严格)

17 个实测抽取实体完整列表

# extraction_class extraction_text char_interval alignment_status
1 TECHNOLOGY GraphRAG [0, 8] match_exact
2 ORGANIZATION Microsoft Research [75, 93] match_fuzzy
3 CONCEPT retrieval-augmented generation [24, 54] match_exact
4 CONCEPT knowledge graphs [107, 123] match_exact
5 TECHNOLOGY GPT-4 [156, 161] match_exact
6 CONCEPT multi-hop reasoning [172, 191] match_exact
7 CONCEPT community detection algorithms [209, 239] match_exact
8 TECHNOLOGY Leiden clustering [248, 265] match_exact
9 TECHNOLOGY MinerU [315, 321] match_exact
10 TECHNOLOGY LangExtract [344, 355] match_exact
11 TECHNOLOGY Neo4j [383, 388] match_exact
12 CONCEPT graph database [396, 410] match_exact
13 CONCEPT pipeline [424, 432] match_exact
14 TECHNOLOGY PDF documents [443, 456] match_exact
15 TECHNOLOGY OCR [465, 468] match_exact
16 TECHNOLOGY NLP [473, 476] match_exact
17 CONCEPT knowledge graph [504, 519] match_exact