欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > LLM Graph Rag(基于LLM的事件图谱RAG)

LLM Graph Rag(基于LLM的事件图谱RAG)

2025/4/26 7:22:48 来源:https://blog.csdn.net/qq_41359817/article/details/147516383  浏览:    关键词:LLM Graph Rag(基于LLM的事件图谱RAG)

1.背景

经过几天对各类帖子和技术文章的深入研究,我发现目前行业内利用大语言模型(LLM)构建知识图谱(Graph)并实现检索问答系统时,普遍存在一定的局限性。去年,我曾实际体验过微软的 graphRAG,在使用过程中,构建出的知识图谱与我的预期存在差距。近期,我又对 langchainNeo4j、RagFlow、nebulaGraph 等工具进行了测试,这些工具虽然都采用抽取实体与关系的方式构建图谱,但在构建过程中,图谱构建的侧重点往往难以精准把控,无法完全满足个性化需求。

基于上述痛点,我决定从数据抽取的源头开始,亲自搭建一套完整的知识图谱检索问答(RAG)系统,力求打造出符合自身需求的解决方案。
在这里插入图片描述

在这里插入图片描述

2.大模型调用

2.1 框架选择

使用openai的方法调用各家厂商的大模型,使用方法如下
(1)导入包

pip install openai

(2)运行代码

import base64
import json
import requests
from openai import OpenAIclass LLMClass:clientOllama = OpenAI(base_url='http://192.168.1.86:11435/v1',api_key='*****',)def llmFunction(self, messages, model_name, stream=True, temperature=0.7, top_p=0.6):completion = self.clientOllama.chat.completions.create(model=model_name,messages=messages,stream=stream,temperature=temperature,top_p=top_p)if stream:content = ''for item in completion:chunk = item.choices[0].delta.contentif stream:print(chunk, end='')# yield chunkcontent += chunkelse:content = completion.choices[0].message.contentreturn contentdef llmApi(self, messages, model_name, stream=True, temperature=0.7, top_p=0.6):completion = self.clientOllama.chat.completions.create(model=model_name,messages=messages,stream=stream,temperature=temperature,top_p=top_p)if stream:content = ''for item in completion:chunk = item.choices[0].delta.contentif chunk:content += chunkif stream:print(chunk, end='')yield chunkelse:content = completion.choices[0].message.contentyield content

对 OpenAI 所采用的相关方法进行了针对性的封装处理,在此基础上创建的 LLMClass 类,成功实现了既能在终端以流式方式输出内容,又能在浏览器端实现流式输出的功能。

2.2 模型选择

大家若想在本地启动模型,可以选择使用 vllm 和 ollama 这两个工具。要是本地缺乏相应的运行环境,还能考虑使用阿里的百炼平台。值得一提的是,百炼平台为每个模型都提供了 100 万免费的 token 供大家使用。博主本人采用的就是本地的 ollama,以及阿里百炼平台来进行相关操作的。

3.数据需求

3.1 数据源

在本次研究中,数据源聚焦于军事新闻报道领域,特别是军舰军事相关内容。具体涵盖以下类别:

  • 官方渠道:中华人民共和国国防部官网发布的权威军事动态,其中包含军舰重大演习、部署等官方信息;中国军网对海军军舰的列装、训练等实时报道,是了解我国海军军舰发展的核心渠道。
  • 主流新闻媒体:国内如人民网军事、新华网军事等平台,会对国内外军舰军事行动、装备更新进行深度报道;国际上,BBC News、CNN 等媒体,能提供全球视角下军舰在军事冲突、联合军演等场景中的动态。
  • 专业军事平台:像 Jane’s Defence(简氏防务)这类专业数据库,拥有军舰型号参数、全球海军力量部署等详细数据;Defense News(国防新闻)则聚焦军事防务产业,对军舰建造、技术升级等方面有深入分析。

3.2 功能要求

通过对各类来源广泛且主题多样的军事新闻报道进行深入分析与处理,利用专业的技术手段构建出精确且全面的军事知识图谱。借助这一精心构建的军事图谱,能够实现对军舰航行轨迹的精准还原,对军舰所涉事件的深度剖析,以及对军舰实时动态的高效监测与分析,进而为军事领域的研究、决策制定等工作提供有力的数据支撑和有价值的参考依据。

4.图谱涉及

4.1 图谱scheme

基于实际业务需求,本次将图谱 Scheme 设计为 事件图谱 架构。该图谱以 事件 作为核心枢纽,将涉及的军舰型号、军队编制、战斗机机型等关键实体,通过事件触发、参与、关联等多元关系进行深度串联,形成逻辑紧密、层次分明的知识网络。这种设计能够高效聚合分散在不同新闻源中的军事信息,便于从事件维度挖掘各军事要素间的潜在联系,为后续的军事动态分析与决策提供结构化数据支撑 。
在这里插入图片描述

军舰
事件

后期会将地点location属性单独拎出作为一类标签,可以实现更复杂的查询。

5.数据抽取

5.1数据样例

什么情况?辽宁舰高调绕台一周 航母战力大跃升 此前曾绕行菲律宾
在这里插入图片描述

text = '''什么情况?辽宁舰高调绕台一周 航母战力大跃升 此前曾绕行菲律宾
军评陈光文 2024-10-23 18:25 山东
在过去1个月时间里,中国首艘航母辽宁舰活动频繁。
10月23日晨,台媒发布通报称,解放军航母辽宁舰10月22日晚间在东沙群岛附近海域航行,随后北上通过台湾海峡。
这就意味着,辽宁舰在9月18日里从台湾东部进入西太平洋,在台岛以东海空域参加训练演习。
然后,该舰进入南海海域,监视了美日菲的军演。
现在,辽宁舰再次从台湾西部的台湾海峡北上,实现了“绕台”。
而在此前9月18日辽宁舰通过与那国岛进入西太平洋,随后在10月初从菲律宾方向返回南海的基地,实现了绕行菲律宾一圈的战术目标。
辽宁舰经过近一年的升级后,已从一艘训练型航母转变成为一艘战斗型航母。
据日本自卫队监测称,在13号到15号的“联合利剑-2024B”演习期间,辽宁舰共起降舰载战斗机90架次,舰载直升机50架次,舰载机日均起降架次达到了破纪录的70架次。
这是自日本方面观测到辽宁舰以来,该舰起降次数首次达到70次,甚至已超过山东舰。
如此规模的舰载机起降次数,几乎迫近美国海军的水平,因此意味着辽宁舰的战斗力获得大幅提升,“战斗航母”之名实至名归。
在9月的训练演习期间,结束西太平洋地区演训的辽宁舰编队,包括3艘052D型驱逐舰——淮南舰、成都舰、乌鲁木齐舰,于2024年10月2日着菲律宾以东海域向西南方向航行。
10月1日国庆节这一天,辽宁舰战斗群从菲律宾棉兰老岛南部进入苏拉威西海,这是中国航母编队首次驶入这片海域,意义重大。
之后,辽宁舰编队穿过苏禄海,经由巴拉克拉海峡,最终抵达南海。
据说,辽宁舰这次是逼近从中东返回本土休整的罗斯福号航母,并用近乎战斗姿态的舰载机起降来表达“中国已不怕美国航母”的信号。
辽宁舰用一次绕行菲律宾本土,发出的警告意义重大,同时展示了中国航母的的新质战斗力。
10月8日,美商业卫星拍摄到辽宁舰和航母山东舰并排停泊在三亚某码头。
经过短暂休整后,10月13日以后,辽宁舰从巴士海峡前往西太平洋,参加了“联合利剑-2024B”演习。
10月15号,辽宁舰与055型导弹驱逐舰103号鞍山舰、052D型导弹驱逐舰118号乌鲁木齐舰通过巴林塘海峡返回南海。
谁也没想到,上次通过台湾海峡的辽宁舰走的是贴近海岸的航线——因为那是前往大连升级,这次该舰走的是所谓的“海峡中线”——显然是一次高调战斗训练。
分析认为,近一段时间以来,美加军舰航经台湾海峡并进行恶意炒作,美日针对中国的军演近期又要上演,朝鲜半岛剑拔弩张,美菲宣布要把“堤丰”导弹系统无限期部署菲律宾,台湾某些势力上窜下跳……
种种针对中国大陆的不利局面频繁上演,中国不得不公开表明自己的立场。
在绕行菲律宾一圈之后,中国航母又绕行台湾一周,把这两个热点地区巡视了一遍,由此传达出了中国的坚定意志。
下一步,山东舰该上场了,福建舰的第五次海试也该进行了,中国将用航母行动来向这个世界诉说自己的意志!
(军评陈光文于2024.10.23)
'''

5.2 抽取指令

依据设计的图谱 scheme,能够较为轻松地撰写出相应的抽取指令,具体内容如下:

def getMessages(text):p1 = "请从这篇关于近期国际军事行动的新闻报道中,梳理出精确到日期的各国军舰在不同海域的航行轨迹变动情况,以及涉及到的军事演习、对峙等具体军事事件的详细信息(包含参与主体、地点、主题等),军舰主体(需去重唯一)以及事件不能有遗漏"p2 = '''# 输出格式
## 输出格式为json,格式如下:
/```json
[{"event": "事件详细内容","time": "事件时间","location": "事件地点","subjects": ["事件涉及的主体1","事件涉及的主体2","事件涉及的主体3",]}
]
/```'''messages = [{"role": "assistant","content": p1},{"role": "assistant","content": p2},{"role": "user","content": "新闻报道:%s" % text}]return messages

本次操作总共涵盖2条指令。其中,指令 p1 是对出去任务的整体描述。指令 p2 的作用在于对输出格式进行详细说明。
抽取结果示例:

data = [{"event": "辽宁舰从台湾东部进入西太平洋,在台岛以东海空域参加训练演习","time": "2024年9月18日","location": "台岛以东海域","subjects": ["中国人民解放军辽宁舰"]},{"event": "辽宁舰监视美日菲在南海的军演","time": "2024年9月18日后","location": "南海海域","subjects": ["中国人民解放军辽宁舰", "美国海军", "日本自卫队", "菲律宾海军"]},{"event": "辽宁舰绕行菲律宾一圈,从与那国岛进入西太平洋,并在10月初返回南海","time": "2024年9月18日 - 10月初","location": "西太平洋、菲律宾附近海域、南海","subjects": ["中国人民解放军辽宁舰"]},{"event": "辽宁舰编队包括3艘052D型驱逐舰(淮南舰、成都舰、乌鲁木齐舰)从菲律宾以东海域向西南方向航行","time": "2024年10月2日","location": "菲律宾以东海域","subjects": ["中国人民解放军辽宁舰", "淮南舰", "成都舰", "乌鲁木齐舰"]},{"event": "辽宁舰战斗群从菲律宾棉兰老岛南部进入苏拉威西海","time": "2024年10月1日","location": "苏拉威西海","subjects": ["中国人民解放军辽宁舰", "055型导弹驱逐舰103号鞍山舰", "052D型导弹驱逐舰118号乌鲁木齐舰"]},{"event": "辽宁舰编队穿过苏禄海,经由巴拉克拉海峡抵达南海","time": "2024年10月","location": "苏禄海、巴拉克拉海峡、南海","subjects": ["中国人民解放军辽宁舰", "055型导弹驱逐舰103号鞍山舰", "052D型导弹驱逐舰118号乌鲁木齐舰"]},{"event": "辽宁舰和山东舰并排停泊在三亚某码头","time": "2024年10月8日","location": "三亚某码头","subjects": ["中国人民解放军辽宁舰", "中国人民解放军山东舰"]},{"event": "辽宁舰前往巴士海峡参加'联合利剑-2024B'演习","time": "2024年10月13日","location": "巴士海峡","subjects": ["中国人民解放军辽宁舰", "日本自卫队"]},{"event": "辽宁舰与鞍山舰和乌鲁木齐舰通过巴林塘海峡返回南海","time": "2024年10月15日","location": "巴林塘海峡、南海","subjects": ["中国人民解放军辽宁舰", "055型导弹驱逐舰103号鞍山舰", "052D型导弹驱逐舰118号乌鲁木齐舰"]},{"event": "辽宁舰绕行台湾一周,并在10月22日至23日期间通过台湾海峡北上","time": "2024年10月22日 - 2024年10月23日","location": "台湾附近海域、台湾海峡","subjects": ["中国人民解放军辽宁舰"]}]

6.检索

6.1 检索指令

依据设计的图谱 scheme,能够较为轻松地撰写出相应的抽取指令,具体内容如下:

def getMessages(text):p1= """# 目标:你是一名Cypher专家,能够将用户问题转成成可执行全文搜索或图查询语句。
## 所有的内容都必须使用模糊检索
## 以下是neo4j图谱 所有节点 的schema,格式为json
\```json
[{"identity": -106,"labels": ["Warship"],"properties": {"name": "Warship","indexes": ["name"],"constraints": []},"elementId": "-106"}, {"identity": -107,"labels": ["Event"],"properties": {"name": "Event","indexes": ["name,location,time"],"constraints": []},"elementId": "-107"}
]
\```
说明:
(1)Warship 为 ‘军舰’ 节点,包含 name 属性(军舰名称)
(2)Event 为 ‘事件’ 节点,包含 name 属性(事件内容)、location 属性(事件地点)、time 属性(事件时间)## 以下是neo4j图谱中 所有关系 的schema,格式为json
\```json
[{"identity": -103,"start": -106,"end": -107,"type": "happen","properties": {"name": "happen"},"elementId": "-103","startNodeElementId": "-106","endNodeElementId": "-107"}
]
\```
说明:happen关系联系军舰(Warship标签)和事件(Event标签)
"""p2 = '''## 考虑到节点内容不一定存在,所以统一使用模糊检索,形式为:
\```cypher
match(label) where label.attribute =~ '.*内容.*'
\```
## 输出格式为 cypher 标准语句,格式为 cypher
\```cypher
cypher 标准语句,模糊检索示例,切记‘=~’需要和where共同才能使用,不是放在{}中
match(label) where label.attribute =~ '.*内容.*'
\```
'''p3 = '''# 为了使得检索的内容与询问的内容有关联,检索返回的都是label节点和对应的所有关系,即不是单纯的返回某个节点的属性,即使是询问某个节点的属性时,也是要将对应的节点和关系都返回。'''messages = [{"role": "system","content": p1}, {"role": "assistant","content": p2}, {"role": "assistant","content": p3}, {"role": "user","content": '用户输入:%s' % text}]return messages

本次操作总共涵盖三条指令。其中,指令 p1 主要用于呈现整体的概况信息,同时会把图谱 scheme 提供给大模型。若要获取图谱 scheme,可使用以下指定命令。

call db.schema.nodeTypeProperties
call db.schema.relTypeProperties

指令 p2 的作用在于对输出格式进行详细说明,而指令 p3 则是对输出所应满足的要求予以阐释。
生成的查询语句示例:
在这里插入图片描述

User: 辽宁舰的航行轨迹
LLM2Cypher: 
\```cypher
MATCH (w:Warship)-[r:happen]->(e:Event) 
WHERE w.name =~ '.*辽宁舰.*' 
RETURN w, r, e
\```

执行语句获取查询的结果

[{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10020,"name": "辽宁舰绕行台湾一周,并在10月22日至23日期间通过台湾海峡北上","location": "台湾附近海域、台湾海峡","time": "2024年10月22日 - 2024年10月23日"}],"e": {"eid": 10020,"name": "辽宁舰绕行台湾一周,并在10月22日至23日期间通过台湾海峡北上","location": "台湾附近海域、台湾海峡","time": "2024年10月22日 - 2024年10月23日"}},{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10019,"name": "辽宁舰与鞍山舰和乌鲁木齐舰通过巴林塘海峡返回南海","location": "巴林塘海峡、南海","time": "2024年10月15日"}],"e": {"eid": 10019,"name": "辽宁舰与鞍山舰和乌鲁木齐舰通过巴林塘海峡返回南海","location": "巴林塘海峡、南海","time": "2024年10月15日"}},{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10018,"name": "辽宁舰前往巴士海峡参加\"联合利剑-2024B\"演习","location": "巴士海峡","time": "2024年10月13日"}],"e": {"eid": 10018,"name": "辽宁舰前往巴士海峡参加\"联合利剑-2024B\"演习","location": "巴士海峡","time": "2024年10月13日"}},{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10016,"name": "辽宁舰和山东舰并排停泊在三亚某码头","location": "三亚某码头","time": "2024年10月8日"}],"e": {"eid": 10016,"name": "辽宁舰和山东舰并排停泊在三亚某码头","location": "三亚某码头","time": "2024年10月8日"}},{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10015,"name": "辽宁舰编队穿过苏禄海,经由巴拉克拉海峡抵达南海","location": "苏禄海、巴拉克拉海峡、南海","time": "2024年10月"}],"e": {"eid": 10015,"name": "辽宁舰编队穿过苏禄海,经由巴拉克拉海峡抵达南海","location": "苏禄海、巴拉克拉海峡、南海","time": "2024年10月"}},{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10012,"name": "辽宁舰战斗群从菲律宾棉兰老岛南部进入苏拉威西海","location": "苏拉威西海","time": "2024年10月1日"}],"e": {"eid": 10012,"name": "辽宁舰战斗群从菲律宾棉兰老岛南部进入苏拉威西海","location": "苏拉威西海","time": "2024年10月1日"}},{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10008,"name": "辽宁舰编队包括3艘052D型驱逐舰(淮南舰、成都舰、乌鲁木齐舰)从菲律宾以东海域向西南方向航行","location": "菲律宾以东海域","time": "2024年10月2日"}],"e": {"eid": 10008,"name": "辽宁舰编队包括3艘052D型驱逐舰(淮南舰、成都舰、乌鲁木齐舰)从菲律宾以东海域向西南方向航行","location": "菲律宾以东海域","time": "2024年10月2日"}},{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10007,"name": "辽宁舰绕行菲律宾一圈,从与那国岛进入西太平洋,并在10月初返回南海","location": "西太平洋、菲律宾附近海域、南海","time": "2024年9月18日 - 10月初"}],"e": {"eid": 10007,"name": "辽宁舰绕行菲律宾一圈,从与那国岛进入西太平洋,并在10月初返回南海","location": "西太平洋、菲律宾附近海域、南海","time": "2024年9月18日 - 10月初"}},{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10003,"name": "辽宁舰监视美日菲在南海的军演","location": "南海海域","time": "2024年9月18日后"}],"e": {"eid": 10003,"name": "辽宁舰监视美日菲在南海的军演","location": "南海海域","time": "2024年9月18日后"}},{"w": {"eid": 10002,"name": "中国人民解放军辽宁舰"},"r": [{"eid": 10002,"name": "中国人民解放军辽宁舰"},"happen",{"eid": 10001,"name": "辽宁舰从台湾东部进入西太平洋,在台岛以东海空域参加训练演习","location": "台岛以东海域","time": "2024年9月18日"}],"e": {"eid": 10001,"name": "辽宁舰从台湾东部进入西太平洋,在台岛以东海空域参加训练演习","location": "台岛以东海域","time": "2024年9月18日"}}
]

6.2检索方案优化

后续,我们计划为该图谱增添全文检索功能。一旦完成这一功能的添加,就能实现更为灵活、模糊的检索操作,极大地提升检索的便捷性与全面性。目前,已成功构建完成的图谱总共有两个,它们分别对应着两个特定的标签,方便用户进行区分和使用。
在这里插入图片描述

6.3检索结果优化

由于大模型所生成的查询语句在执行后,其获取的数据结构具有不可预测性,因此我们有必要对输出的数据进行进一步的结构统一处理。完成数据结构的统一后,便能够更加方便地对这些数据进行可视化展示,从而更直观地呈现数据间的内在关系。
以某次检索结果数据为例,我们可以运用正则表达式来提取其中所有的 eid。在获取到这些 eid 后,便可以依照我们预先规定的查询方式,重新获取与之相关的所有节点信息和关系数据。具体操作步骤如下:

match(n) where n.eid in %s return n
WITH %s AS eidList
MATCH (n)-[r]-(m)
WHERE n.eid IN eidList AND m.eid IN eidList AND n.eid < m.eid
RETURN n, r, m;

当完成格式的统一后,无论是在图谱的可视化展示环节,使得数据以更清晰、有条理的方式呈现,便于用户直观理解数据间的关系;还是在数据拼接操作中,有效减少了因格式差异导致的错误与冲突,提升了数据整合的效率与质量,都实现了显著的优化与提升。

在这里插入图片描述

7.大模型回答

def getInput(data, text):p1 = '''# 你是一个知识库问答专家,擅长分析用户的问题以及对应的知识库内容,进行回答,给出最清晰、最准确的答案。
# 如果提供的知识库内容不涉及用户所问的问题,则明确表示目前知识内容不支持回答用户的问题。'''p2 = '''## 以下是从图数据库中检索到的内容,格式为json
```json
%s
```''' % json.dumps(data, ensure_ascii=False, indent=4)messages = [{'role': 'system','content': p1},{'role': 'assistant','content': p2},{'role': 'user','content': '用户输入的问题:%s' % text}]return messages

本次操作总共涵盖2条指令。其中,指令 p1 是对出去任务的整体描述。指令 p2 是检索结果内容。
在这里插入图片描述

8.如何构建自己想要的图谱

在实际应用中,由于场景、数据类型及功能需求的差异,图谱 scheme 也会呈现出不同的设计形态。针对以上所介绍的构建流程,实际上只需对部分指令进行替换与统一调整,便能快速适配不同场景,高效完成基于 LLM 的图谱构建,并投入实际使用。这种灵活的设计方式,不仅提升了构建效率,也降低了因场景变化带来的重复开发成本,充分体现了该构建方案的通用性与可扩展性。
系统目前还在不断优化提升,从图谱scheme/知识提取/知识检索三个方面进行体验的优化。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词