Files
GraphRAGAgent/backend/pipeline/entity_extractor.py
T
admin a46ceb94de
GraphRAG CI/CD / build-and-deploy (push) Successful in 6m15s
feat: 重构图谱抽取 — 支持建筑规范文档的 8 种实体类型
- 实体类型改为:构件/设备/设施/指标/场所/材料/措施/条款
- 中文 prompt + 建筑规范领域 Few-shot 示例
- 前端图谱颜色、筛选项同步更新
- QA agent 系统提示词适配建筑规范领域
2026-06-18 16:30:58 +08:00

98 lines
6.0 KiB
Python

"""
Entity Extractor — LangExtract + DeepSeek entity extraction.
Independent implementation for the GraphRAG Studio backend.
"""
from __future__ import annotations
import os
from pathlib import Path
from dotenv import load_dotenv
import langextract as lx
from langextract.providers.openai import OpenAILanguageModel
load_dotenv(Path(__file__).parent.parent / ".env", override=True)
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY", "")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com")
MODEL_ID = "deepseek-chat"
PROMPT_DESCRIPTION = (
"从建筑规范文本中按出现顺序提取命名实体。"
"实体类型:"
"构件 — 建筑构件和部位(防火墙、防火门、楼梯间、电梯井、管道井、变形缝、外墙、屋面、楼板、梁、柱、承重墙、隔墙、门窗、幕墙、雨篷、阳台、走廊、前室、竖井等);"
"设备 — 消防设备和系统(消火栓、灭火器、喷淋系统、报警系统、防烟排烟系统、应急照明、疏散指示、防火卷帘、消防电梯、消防水箱、消防水泵、气体灭火系统、火灾自动报警系统、电气火灾监控系统等);"
"设施 — 建筑设施和配套(停车场、锅炉房、变配电室、发电机房、储油间、空调机房、通风机房、电梯机房、消防控制室、水泵房等);"
"指标 — 技术参数和量化要求(耐火等级、防火间距、疏散宽度、最大面积、高度限值、距离要求、时间要求、容量要求、温度限值、压力要求等);"
"场所 — 建筑分类和空间类型(高层建筑、地下建筑、公共建筑、住宅建筑、工业建筑、商业建筑、医疗建筑、教育建筑、娱乐场所、仓库、厂房、中庭、避难层、避难走道、敞开楼梯间等);"
"材料 — 建筑材料和产品(不燃材料、难燃材料、可燃材料、防火涂料、防火玻璃、防火密封件、保温材料、装饰材料、钢结构防火保护材料等);"
"措施 — 防火措施和策略(防火分隔、防火封堵、自然排烟、机械加压送风、机械排烟、安全疏散、防火保护、消防供电、消防水源、灭火救援等);"
"条款 — 规范条文引用(强制性条文、推荐性条文、术语定义、一般规定、基本要求等)。"
)
EXAMPLES = [
lx.data.ExampleData(
text=(
"建筑高度大于100m的公共建筑应设置避难层。避难层应采用耐火极限不低于3.00h的防火墙和甲级防火门进行分隔。"
"建筑内的消防控制室应采用耐火极限不低于2.00h的防火隔墙与乙级防火门与其他部位分隔。"
"疏散走道两侧的隔墙应采用不燃材料,其耐火极限不应低于1.00h。"
),
extractions=[
lx.data.Extraction(extraction_class="场所", extraction_text="公共建筑"),
lx.data.Extraction(extraction_class="构件", extraction_text="避难层"),
lx.data.Extraction(extraction_class="指标", extraction_text="耐火极限不低于3.00h"),
lx.data.Extraction(extraction_class="构件", extraction_text="防火墙"),
lx.data.Extraction(extraction_class="构件", extraction_text="甲级防火门"),
lx.data.Extraction(extraction_class="设施", extraction_text="消防控制室"),
lx.data.Extraction(extraction_class="指标", extraction_text="耐火极限不低于2.00h"),
lx.data.Extraction(extraction_class="构件", extraction_text="防火隔墙"),
lx.data.Extraction(extraction_class="构件", extraction_text="乙级防火门"),
lx.data.Extraction(extraction_class="构件", extraction_text="疏散走道"),
lx.data.Extraction(extraction_class="构件", extraction_text="隔墙"),
lx.data.Extraction(extraction_class="材料", extraction_text="不燃材料"),
lx.data.Extraction(extraction_class="指标", extraction_text="耐火极限不应低于1.00h"),
],
),
lx.data.ExampleData(
text=(
"住宅建筑室内消火栓设计流量不应小于5L/s。高位消防水箱有效容积不应小于18m3,"
"且应设置在建筑最高部位。消防电梯前室应设置室内消火栓。"
"公共建筑内每个防火分区的安全出口不应少于2个。"
),
extractions=[
lx.data.Extraction(extraction_class="场所", extraction_text="住宅建筑"),
lx.data.Extraction(extraction_class="设备", extraction_text="室内消火栓"),
lx.data.Extraction(extraction_class="指标", extraction_text="不应小于5L/s"),
lx.data.Extraction(extraction_class="设备", extraction_text="高位消防水箱"),
lx.data.Extraction(extraction_class="指标", extraction_text="不应小于18m3"),
lx.data.Extraction(extraction_class="构件", extraction_text="消防电梯前室"),
lx.data.Extraction(extraction_class="设备", extraction_text="室内消火栓"),
lx.data.Extraction(extraction_class="场所", extraction_text="公共建筑"),
lx.data.Extraction(extraction_class="构件", extraction_text="防火分区"),
lx.data.Extraction(extraction_class="构件", extraction_text="安全出口"),
lx.data.Extraction(extraction_class="指标", extraction_text="不应少于2个"),
],
),
]
def create_model() -> OpenAILanguageModel:
if not DEEPSEEK_API_KEY:
raise ValueError("DEEPSEEK_API_KEY not set in backend/.env")
return OpenAILanguageModel(
model_id=MODEL_ID,
api_key=DEEPSEEK_API_KEY,
base_url=DEEPSEEK_BASE_URL,
)
def extract_entities(page_text: str, model: OpenAILanguageModel) -> lx.data.AnnotatedDocument:
return lx.extract(
text_or_documents=page_text,
prompt_description=PROMPT_DESCRIPTION,
examples=EXAMPLES,
model=model,
show_progress=False,
)