用本地LLM构建知识图谱

我运行Graph RAG系统已经有一段时间了。它的理念很吸引人:与其将文本块塞进向量存储,希望语义相似性找到正确的上下文,你构建一个知识图谱——一个实体及其关系的结构化网络——然后在查询时在该图谱上检索。系统不仅知道哪些词彼此相邻出现,它还知道玛丽·居里巴黎大学工作,她发现了镭,镭一种元素。这种结构化理解对于需要跨多个文档连接信息的复杂问题来说确实有帮助。

但我们没有足够讨论的是:在查询知识图谱之前,你必须先构建一个。

这意味着从原始文本——文章、法律文件、医疗记录、技术文档——中提取结构化的实体-关系三元组。像(CRISPR-Cas9, developed_by, Jennifer Doudna)(Tesla, headquartered_in, Austin)这样的形式。大多数GraphRAG教程用GPT-4调用来一语带过。但我们处理的数据不能离开我们的基础设施,这意味着我们需要本地模型。而本地模型在结构化提取方面的表现比你预期的要差得多。

我们需要确切了解提取问题对于我们的流水线有多难,以及是否可以改进它。因此我们构建了一个全面的内部基准测试,测试了领先的开源权重模型,然后微调了一个。以下是我们学到的。

1、基准测试

我们想回答一个实际问题:如果我们将一段文本交给运行在GPU基础设施上的7-9亿参数模型,它从文本中提取知识图谱的可靠性如何?

在内部,我们构建了一个大型基准测试套件,涵盖我们的流水线实际处理的领域——数百个带有手工标注金标准实体和三元组的段落,涵盖多个复杂度级别和文档类型。对于本文,我们分享一个具有代表性的50样本子集的结果,专注于法律领域——合同、判例法、法规合规、公司治理、劳动法和国际法——以便发现可以在公开数据上复现。每个段落都有四个复杂度级别的金标准标签:简单(几个清晰的实体)、中等(多个相互关联的关系)、复杂(密集段落嵌套关系)和边缘情况(别名、缩写、空段落)。该子集包含约150个金标准实体和139个金标准三元组,我们在这里观察到的模式与在整个内部基准测试中看到的是一致的。

我们测试了四个模型,都在单个NVIDIA RTX 3090(24GB)上通过vLLM运行:

  模型                      参数量   家族          
 -------------------------- ------------ ---------------- 
  Qwen 2.5 7B Instruct       7B           Qwen (阿里巴巴)  
  Llama 3.1 8B Instruct      8B           Llama (Meta)    
  Mistral 7B Instruct v0.3   7B           Mistral         
  Gemma 2 9B IT              9B           Gemma (Google)

每个模型用三种提示策略测试:朴素指令("以JSON格式提取实体和关系")、提示中内嵌schema方法(相同的指令加上完整JSON schema)和少样本提示(两个展示预期输入输出格式的示例)。

1.1 我们如何衡量质量

评估提取质量几乎和执行提取本身一样困难。输出was_born_in而不是born_in的模型在语义上是正确的——在知识图谱中它们的意思相同。惩罚这种差异会让每个模型看起来比实际更差。

我们构建了一个具有三层模糊匹配的评估流水线。首先,实体匹配使用token排序比率,阈值为75,所以"Jennifer Doudna"匹配"Dr. Jennifer Doudna",容忍部分重叠。其次,谓词匹配通过同义词规范化层——约75组语义等效的关系名称,如{born_in, was_born_in, birthplace, place_of_birth}都映射到相同含义。第三,子串匹配处理模型在三元组中产生冗长实体名称的情况。

这些匹配改进将测量的三元组F1提高了15-34%,而无需更改任何模型输出。教训:如果你在构建Graph RAG评估流水线,在匹配逻辑上的投入要和提取提示一样多。

1.2 我们发现了什么

实体检测基本解决。关系提取还没有。 所有四个模型的实体F1在0.78到0.91之间——它们在文本中找东西相当不错。但三元组F1讲述了一个不同的故事。所有12个模型-策略组合中最好的结果是0.732(Llama 3.1配合少样本),大多数配置在0.52到0.60之间。模型可以发现句子中的"Marie Curie"和"Warsaw",但可靠地产生结构化三元组(Marie Curie, born_in, Warsaw)要困难得多。

没有最好的模型——只有权衡。 这对于我们的流水线是最重要的实际发现,在整个内部基准测试中都成立。当我们绘制schema符合度(模型是否产生有效的、可解析的输出?)与三元组F1(当它工作时,有多好?)的关系图时,右上角是空的。没有模型既高度可靠又高度准确。

  模型          策略           Schema符合度   三元组F1  
 -------------- ------------------ -------------------- ----------- 
  Llama 3.1 8B   少样本           20%                  0.732      
  Gemma 2 9B     少样本           65%                  0.653      
  Qwen 2.5 7B    少样本           80%                  0.579      
  Mistral 7B     少样本           100%                 0.564      
  Mistral 7B     提示中内嵌schema   100%                 0.549      
  Gemma 2 9B     提示中内嵌schema   95%                  0.571      
  Qwen 2.5 7B    提示中内嵌schema   100%                 0.563      
  Llama 3.1 8B   提示中内嵌schema   95%                  0.522

Llama 3.1配合少样本在工作时产生最好的提取——但它只在20%的时间产生有效输出。在生产流水线中,这意味着80%的文档要么被丢弃,要么需要昂贵的重试。Mistral配合提示中内嵌schema从不失败产生有效JSON,但提取质量平庸。Gemma 2处于中间位置,在9B参数下提供最佳平衡。

少样本帮助质量但损害可靠性。 在所有四个模型中,少样本提示始终实现最高的三元组F1。这些示例帮助模型理解预期输出结构和谓词的粒度。但代价是真实的:少样本提示长3-5倍,增加延迟并降低输出可靠性。更长的上下文似乎会混淆较小的模型,导致它们产生格式错误的JSON或部分提取。Mistral是唯一一个少样本严格优于其他选项的模型——即使使用更长的提示,它也保持了100%的schema符合度。

复杂度对三元组的影响大于实体。 当段落变得更难——更多实体、嵌套关系、时间限定词——实体检测保持相对稳定,但三元组提取急剧下降。模型难以将密集文本分解为原子三元组,常常产生复合对象而不是每个关系的单独三元组。对于处理密集法律和技术文本的流水线来说,这很重要:提取质量在我们实际文档上的下降比简单基准测试暗示的更多。

2、通过微调缩小差距

基准测试结果清楚地展示了可靠性-质量的权衡。在生产流水线中,你不能容忍80%的失败率,但也不能接受碰巧结构可靠但提取质量平庸的模型。我们需要缩小这个差距。

思路很直接。与其要求一个通用的指令遵循模型仅从提示执行结构化提取,我们用监督示例教它这个模式。微调后,模型应该从一个简短的系统提示可靠地产生带实体和三元组的有效JSON——不需要少样本示例,为更长的段落释放整个上下文窗口。

2.1 训练数据

对于微调数据,我们转向REBEL(Relation Extraction By End-to-end Language generation),这是Babelscape从与Wikidata三元组对齐的维基百科文本构建的银标数据集。REBEL包含数百万个文本段落及其提取的实体-关系三元组——正是我们需要的任务。

原始REBEL格式使用线性化token方案:<triplet> Subject <subj> Object <obj> Relation。我们编写了一个转换流水线,将其解析为我们的目标JSON格式(带有推断类型的实体,加上主语-谓词-宾语三元组),过滤质量(段落在100-1500字符之间,2-15个三元组,去重),并输出用于训练的chat格式JSONL。

除此之外,我们创建了100个手工制作的训练样本,涵盖30多个领域——物理、医学、考古、计算机科学、生态学、电信等——每个都有仔细标注的实体和三元组。将高质量策划示例与较大的银标数据集混合,给模型提供精度和覆盖面。

最终训练集:来自REBEL的3000个样本加上100个手工制作的样本,500个用于验证。

2.2 训练设置

训练在两个RTX 3090 GPU上使用QLoRA——4位量化基础权重,在注意力和前馈投影上使用LoRA适配器。这将每个GPU的内存占用控制在20GB以内,同时仍能有效微调80亿参数模型。

关键配置选择,参考前沿训练手册:

基础模型:Qwen3-8B。 它在我们的基准测试中表现最佳,使用标准密集Transformer架构,微调可预测。

QLoRA配置r=64,alpha=128。 比典型的r=16默认值更高——结构化提取是复杂任务,受益于更多适配器容量。alpha与rank的比率为2,保持学习率缩放合理。

学习率:3e-5配合余弦调度。 比预训练学习率低一个数量级,遵循手册对SFT的建议。对完整数据集进行三个epoch,前3%步骤进行预热。

用户轮次掩码。 训练损失仅在助手输出(JSON提取)上计算,不在系统提示或输入段落上。这将模型的学习完全集中在提取任务上。

序列打包。 多个短训练示例被打包成单个序列以最大化GPU利用率,因为大多数提取示例远低于2048 token限制。

2.3 结果

训练在2x RTX 3090 GPU上33分钟完成。最终训练损失:1.0,验证损失:0.67。模型平稳收敛——没有训练不稳定性或损失尖峰。

我们在相同的50样本法律子集上评估微调模型。以下是微调后的Qwen3-8B与最佳基础模型配置的比较:

  模型                 策略                  Schema符合度   实体F1   三元组F1  
 --------------------- ------------------------- -------------- ----------- ----------- 
  Qwen3-8B 微调        微调(朴素提示)        100%           0.847       0.211      
  Llama 3.1 8B         少样本                  20%            0.907       0.732      
  Gemma 2 9B           少样本                  65%            0.868       0.653      
  Qwen 2.5 7B          提示中内嵌schema        100%           0.814       0.563      
  Mistral 7B           提示中内嵌schema        100%           0.782       0.549

结果根据你关注的指标讲述两个非常不同的故事。

结构问题完全解决。 微调模型在所有50个样本上实现100% JSON有效性和100% schema符合度。每一个响应都是格式正确的JSON对象,具有正确的实体和三元组结构。没有解析失败,没有格式错误输出,不需要重试。对于我们的流水线,这是最重要的改进——每次解析失败意味着丢失数据或昂贵的重试逻辑,微调完全消除了这一点。

实体提取表现良好。 实体F1为0.847,与基础模型相比具有竞争力——略低于Llama配合少样本的0.907,但高于Qwen 2.5配合提示中内嵌schema的0.814。模型在文本中找到正确的东西。

但三元组F1令人失望——原因很有启发性。

微调模型在三元组F1上得分0.211,远低于每个基础模型配置。查看原始输出揭示了确切原因。以下是微调模型对关于专利诉讼的法律段落的示例提取:

{
  "entities": [
    {"name": "TechCorp Industries", "type": "Organization"},
    {"name": "DataFlow Systems", "type": "Organization"},
    {"name": "U.S. Patent No. 10,234,567", "type": "Patent"}
  ],
  "triples": [
    {"subject": "TechCorp Industries",
     "predicate": "filed a patent infringement lawsuit against",
     "object": "DataFlow Systems"},
    {"subject": "TechCorp Industries",
     "predicate": "holds",
     "object": "U.S. Patent No. 10,234,567"}
  ]
}

实体是正确的。三元组在语义上是正确的——它们准确描述了源文本中的关系。但谓词"filed a patent infringement lawsuit against"与基准测试的金标准谓词"filed_lawsuit_against"不匹配。模型产生冗长的自然语言谓词,而不是基准测试期望的简洁snake_case标识符。

这是领域迁移问题,不是提取质量问题。REBEL数据集——源自维基百科和Wikidata——使用百科全书式的、描述性的关系名称。模型学会了以那种风格提取关系。我们的法律基准测试使用简洁的、规范化的谓词。模糊评估流水线的75个同义词组有助于弥合部分差距,但它们无法覆盖百科全书式和领域特定谓词风格之间的全部词汇不匹配。

2.4 但是等等——领域内评估如何?

明显的下一个问题:如果法律子集由于领域不匹配而不公平,当我们在保留的REBEL数据上评估时会发生什么——模型训练时使用的同一领域?

我们正是这样做的,生成了195个新的REBEL样本(跳过前20,000行以避免与训练数据重叠),并在它们上评估微调模型。

  指标               法律子集   REBEL保留集  
 -------------------- -------------- ---------------- 
  样本数              50             195             
  JSON有效性          100%           100%            
  Schema符合度       100%           100%            
  实体F1            0.847          0.661           
  三元组F1           0.211          0.067

REBEL保留数据上的三元组F1比法律基准测试更差——0.067对比0.211。这确实令人惊讶。模型是在REBEL数据上训练的。它怎么能在更多相同数据上表现更差?

查看原始输出揭示了比词汇问题更深层的东西。以下是样本35,关于德国奥伯斯多夫花样滑冰比赛的段落:

REBEL金标准三元组是(Deutsche Eislauf-Union, country, Germany)(Oberstdorf, country, Germany)——Wikidata风格的将实体链接到其国家属性的事实。模型反而产生(Deutsche Eislauf-Union, organizes, competition)(competition, location, Oberstdorf)——句子实际内容的自然阅读。

两种提取都是正确的。但它们从同一文本中提取了不同的事实

REBEL的银标通过将Wikidata三元组与维基百科句子对齐派生。当一个句子提到Germany和Deutsche Eislauf-Union时,REBEL查询Wikidata并找到(Deutsche Eislauf-Union, country, Germany)——一个碰巧被句子支持的知识库事实,即使句子并不真正关于那个事实。同时,模型学会了提取文本实际描述的内容:谁组织什么,在哪里。

这是知识库补全(关于这些实体我们知道什么事实?)和文本接地关系提取(这段文字表达了什么关系?)之间的区别。REBEL在前者上训练;模型内化了后者。对于Graph RAG——其整个目的是构建反映文档实际内容的知识图谱——模型的行为可以说比REBEL的金标准更有用。

2.5 这实际上意味着什么

微调结果既是成功,又是比预期更深层的教训。

有效的部分: 通过监督微调教会模型可靠地产生结构化JSON输出非常有效。从简单系统提示实现100% schema符合度——无需少样本示例,无需提示中内嵌schema——是一个重大的实际胜利。在我们的流水线中,这消除了为每个提取步骤增加延迟和复杂性的重试逻辑和失败处理。

关于评估的教训: 没有哪个基准能公平衡量这个模型。法律子集惩罚谓词词汇不匹配。REBEL基准惩罚模型提取文本接地关系而不是知识库风格的事实。这突显了关系提取评估中的一个基本挑战:对于给定的段落,没有单一"正确"的三元组集合。正确的提取取决于你构建知识图谱的目的。

我们下一步做什么: 我们流水线的前进道路是领域特定的微调数据。即使是50-100个带有我们目标谓词词汇和提取理念的例子——向模型展示哪些关系对我们的用例重要——与通用REBEL基础混合,应该能够缩小差距。模型已经知道如何提取;它只需要学习提取什么对于我们的领域。

3、实际要点

无论你今天是否在运行Graph RAG流水线,还是评估是否要构建一个,以下是这项工作的建议。

从提示中内嵌schema开始。 在我们测试的每个模型中,在提示中提供JSON schema是最安全的默认选择。它提供最佳的可靠性-质量比,并且在提示长度方面几乎没有成本。将少样本留给你已经验证确实对你的特定模型和领域有帮助的情况。

为提取失败留出预算。 即使最可靠的基础模型配置(Mistral + 提示中内嵌schema,100%符合度)也为了可靠性牺牲了提取质量。构建你的流水线以优雅地处理失败——用不同策略重试,回退到更简单的提取,或标记供人工审查。

投资评估。 过于严格的字符串匹配会让模型看起来比实际差15-30%。从第一天起就在评估中构建同义词感知的谓词匹配和模糊实体比较。

微调完全解决可靠性问题。 如果你的流水线遭受解析失败和格式错误输出的困扰,在几千个示例上微调可以完全消除这些。消费级GPU上的QLoRA,不到一小时的训练——与花在重试逻辑和失败处理上的工程时间相比,成本微乎其微。

但要注意领域差距——它比词汇更深。 在REBEL等通用提取数据上微调教会了模型结构模式,但它可能学到与你需求不同的提取理念。REBEL的Wikidata对齐标签偏向知识库补全;生产Graph RAG流水线可能需要文本接地提取。即使是少量领域特定示例(50-100个样本),向模型展示哪些关系对你的用例重要,也很可能缩小这个差距。

评估比提取更难。 我们的REBEL实验揭示,对于给定的段落,没有单一"正确"的三元组集合。产生不同但同样有效的三元组的模型,在任何期望特定金标准标签的基准测试上都会得零分。如果你在评估提取质量,考虑人工评估精度(提取的三元组是否确实在文本中陈述?)以及自动召回指标。

本地模型已经可用于生产。 基础模型0.55-0.65的三元组F1意味着本地模型产生的知识图谱三元组超过一半是正确的且基于源文本。通过基于置信度的过滤和定期人工审查,这足以运行生产知识图谱,而无需将数据发送到外部API。

实体识别和关系提取之间的差距是本地Graph RAG的真正瓶颈。缩小它是一个可解决的工程问题——不是模型大小的根本限制。工具已经存在:像REBEL这样的开放数据集、QLoRA的高效训练,以及衡量进展的清晰评估方法。微调结果表明结构可靠性已经解决;剩余的挑战是教会模型你领域的提取理念,这需要的数据远少于从零开始教提取。

所有实验都在NVIDIA RTX 3090 GPU上运行,使用vLLM进行推理,使用TRL/PEFT进行微调。适配器训练流水线和REBEL转换脚本在GitHub上分享。


原文链接: Building Knowledge Graphs with Local LLMs: From Benchmarking to Fine-Tuning

汇智网翻译整理,转载请标明出处