GraphRAG 数据清洗:3 步把脏数据洗干净,变成可检索的知识图谱
2026/9/1 8:35:39 网站建设 项目流程

GraphRAG 数据清洗:3 步把脏数据洗干净,变成可检索的知识图谱

【免费下载链接】graphragA modular graph-based Retrieval-Augmented Generation (RAG) system项目地址: https://gitcode.com/GitHub_Trending/gr/graphrag

GraphRAG 是微软开源的模块化图结构检索增强生成系统,它先用 LLM 从文档中构建实体关系图谱,再基于图谱做检索。做知识图谱数据清洗时,翻车几乎都发生在数据进场环节:HTML 转义字符混进实体名、字段缺失、图里散落孤立节点。本文按一次真实索引任务走完整流程:配置怎么定、三步清洗按什么顺序做、效果怎么验证。

什么脏数据会让 GraphRAG 翻车

最常见的翻车点是实体名污染。LLM 的抽取结果靠分隔符逐条解析,源文档里若有 HTML 转义内容,实体名可能解析出Operation & Dulce这样的值。不还原的话,同一实体会以&&两种形态各存一条,图上凭空多出重复节点——实体提取失败排查,通常先从这一步查起。

第二类脏数据在图结构层面。主题不相干的文档抽取后会产生孤立节点和小型连通簇,社区检测(Leiden)在由多个不连通分量拼成的图上跑,得到的社区层级没有意义。再往细里说,字段缺失、权重解析成 NaN 的记录如果放过去,会直接污染度数统计和嵌入结果。

分块参数和校验字段怎么配

分块参数是清洗的预处理部分,都在项目配置里。max_tokens按模型上下文窗口定,overlap保证关键概念不被切在块边界上。顺手打开 graphml 快照,方便后面验证图结构。核心配置:

input: type: files chunking: strategy: token max_tokens: 1200 overlap: 100 snapshots: graphml: true

必填字段校验不能直接写在配置里,要在进管道前做:每份文档记录若缺少 id、text、source 等核心字段或类型不对,直接跳过该文档。项目里现成的函数在packages/graphrag/graphrag/index/utils/dicts.py,下面细说。

三步清洗流程

GraphRAG 文本标准化:clean_str 的三层处理

实现在 packages/graphrag/graphrag/index/utils/string.py,clean_str的逻辑很克制:非字符串直接原样返回;html.unescape还原&之类转义并去掉首尾空白;正则剔除\x00-\x1f\x7f-\x9f区间的控制字符。

调用时机在解析抽取结果时:packages/graphrag/graphrag/index/operations/extract_graph/graph_extractor.py里,每条实体名、类型、描述、关系两端点和边描述写入 DataFrame 前都会先过一遍clean_str。这一步等于在抽取出口把脏数据拦下,不让它进图。

字段校验与空值过滤:存在、类型、空值三段链

校验是一条链,顺序固定。先查存在性:dict_has_keys_with_types(data, [("title", str), ("type", str)])发现字段缺失立刻返回 False。再做类型验证:对每个字段尝试field_type(value)转换,TypeError 或 ValueError 即判无效;inplace=True时转换结果会被写回,顺手完成类型统一。最后做空值判断:packages/graphrag/graphrag/index/utils/is_null.pyis_null同时检查 None 和 float NaN,后者是value is None抓不住的,而 NaN 恰好藏在权重、度数这类数值字段里。管道里,记录级校验在抽取写入前跑,空值检查则用在文本嵌入等环节。

stable_lcc 连通分量去噪:它到底做了什么

代码在packages/graphrag/graphrag/graphs/stable_lcc.py(注意在 graphs/ 下而非 index/utils/),由graphrag/index/operations/cluster_graph.py在社区检测前调用。原理用三句话讲清:先把节点名归一化(HTML 反转义、转大写、去空白),让同名节点的大小写和转义变体合并;再求最大连通分量,把它之外的节点全部丢掉,孤立节点和小型簇都在这一步出局;最后按节点名排序边并去重反向对,保证同一输入永远得到同一输出,这就是 stable 的含义。

清洗效果怎么验证

别信"看起来变好了",看数字。三个指标就够。

实体规模:清洗前后对比输出目录里entities.parquetrelationships.parquet的行数,以及去重后的节点数变化,能说明清洗实际动过多少数据。

连通分量覆盖:把 relationships 过一遍stable_lcc,对比保留边数占比。占比很低说明图碎裂严重,要回源头数据找原因。

孤立节点占比:不属于最大连通分量的节点数除以总节点数。

拿节点集的小片段:

import pandas as pd rels = pd.read_parquet("output/relationships.parquet") nodes = set(rels.source) | set(rels.target)

图级别的直觉验证,把 graphml 快照导进 Gephi,在 Network Overview 面板看度数分布和分量布局,巨分量是否一家独大,一眼便知。

踩坑记录

清洗过度误删专有名词

  • 现象:AT&T 这类名字里的&被某层预处理写成&,或被自写过滤器当特殊字符剥掉。
  • 原因:clean_str只处理转义和控制字符,不会删合法标点,问题多半出在你额外加的一层归一化。
  • 处理:定稿前抽几百个实体名抽查,专有名词进白名单,额外的归一化步骤用"替换后再校验"而不是"先删掉"。

大规模数据清洗耗时

  • 现象:逐行清洗加全量索引,改一次配置重跑一遍不现实。
  • 原因:逐行clean_str、DataFrame 写入、graphml 导出都是串行 IO,规模一上来就放大。
  • 处理:用增量索引更新能力分批处理;必填字段校验和空值过滤前置到索引之前,别让脏数据消耗 LLM 调用。

特殊字符被错误过滤

  • 现象:权重字段出现 NaN,度数统计跟着错。
  • 原因:非数值权重解析失败时会回退 1.0,但 NaN 还可能来自 float 解析等其他来源,is None根本抓不到。
  • 处理:数值字段统一用is_null检查,写表前过滤,并记下被过滤行的来源文档,方便回溯。

想继续深入,方向有两个:参照packages/graphrag/graphrag/index/operations/的写法写自己的行级清洗处理器挂进管道;或者把dicts.py的校验扩展成配置驱动的字段白名单。第一轮练习建议拿仓库自带的官方 Operation Dulce 数据集(docs/data/operation_dulce/)跑一遍完整清洗流程,它恰好同时具备上面几类问题,清洗前后的实体数和连通分量差异可以直接对比。

【免费下载链接】graphragA modular graph-based Retrieval-Augmented Generation (RAG) system项目地址: https://gitcode.com/GitHub_Trending/gr/graphrag

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询