玩转大语言模型——配置图数据库Neo4j(含apoc插件)并导入GraphRAG生成的知识图谱

系列文章目录

玩转大语言模型——使用langchain和Ollama本地部署大语言模型
玩转大语言模型——ollama导入huggingface下载的模型
玩转大语言模型——langchain调用ollama视觉多模态语言模型
玩转大语言模型——使用GraphRAG+Ollama构建知识图谱
玩转大语言模型——完美解决GraphRAG构建的知识图谱全为英文的问题
玩转大语言模型——配置图数据库Neo4j(含apoc插件)并导入GraphRAG生成的知识图谱
玩转大语言模型——本地部署带聊天界面deepseek R1的小白教程


文章目录

  • 系列文章目录
  • 前言
  • 安装JDK
  • 安装Neo4j
    • 下载Neo4j
    • 配置环境变量
    • 安装apoc插件
  • 导入知识图谱
    • 启动Neo4j
    • 使用Python导入知识图谱
    • 显示知识图谱


前言

在之前的文章中笔者解决了使用本地模型部署GraphRAG并生成知识图谱的过程,并且解决了原本提示词只生成英文知识图谱的问题,在本篇中,笔者将配置Neo4j图数据库并导入GraphRAG生成的知识图谱数据。以往的内容参照:玩转大语言模型——使用GraphRAG+Ollama构建知识图谱、玩转大语言模型——完美解决GraphRAG构建的知识图谱全为英文的问题。


安装JDK

Neo4j使用Java开发的,所以首先需要安装JDK。如果没有安装过JDK,需要先到官网下载安装。
官网:https://www.oracle.com/java/technologies/downloads/?er=221886#java11-windows
选择合适的版本下载
在这里插入图片描述
跟随指引安装即可。


安装Neo4j

下载Neo4j

Neo4j官网:https://neo4j.com/deployment-center/
在这里插入图片描述
下载好后是个压缩包,将其解压到你的目标安装目录即可,注意记一下解压后的地址,需要配置环境变量,笔者的地址是D:\neo4j-community-5.26.1,配置时可以做参考

配置环境变量

打开编辑环境变量,新建系统环境变量:名为NEO4J_HOME,值为D:\neo4j-community-5.26.1
在这里插入图片描述
在这里插入图片描述

修改Path变量:在其值中增加
在这里插入图片描述
双击后点新建

%NEO4J_HOME%\bin

在这里插入图片描述

安装apoc插件

导入知识图谱时,会用到apoc插件的部分功能,所以首先要安装apoc。
apoc版本地址:https://github.com/neo4j/apoc/releases?page=1

在这里插入图片描述

点击下载后放到路径:neo4j路径/plugins
在这里插入图片描述
找到路径:neo4j路径/conf下的neo4j.conf,在文件内容的末尾添加以下配置并保存。

dbms.security.procedures.unrestricted=apoc.*
dbms.security.procedures.allowlist=apoc.*
server.jvm.additional=-Dapoc.export.file.enabled=true
server.jvm.additional=-Dapoc.import.file.enabled=true
dbms.security.allow_csv_import_from_file_urls=true

neo4j路径/conf下新建一个apoc.conf文件
在文件中写入以下配置并保存。

apoc.export.file.enabled=true
apoc.import.file.use_neo4j_config=false
apoc.import.file.enabled=true
apoc.import.file.directory=D:/Neo4j/neo4j-community-5.13.0-windows/neo4j-community-5.13.0/import
apoc.export.file.directory=D:/Neo4j/neo4j-community-5.13.0-windows/neo4j-community-5.13.0/export

导入知识图谱

启动Neo4j

在命令行输入

neo4j console

之后在浏览器搜索:http://localhost:7474 进行用户创建。
初始用户名及密码都是neo4j,之后会让重置密码。
如果想持续在后台运行数据库,可以使用以下命令

neo4j start

如果neo4j start 时报错,可以执行以下命令安装service。

neo4j windows-service install 

安装成功后重新使用命令neo4j start 即可,但使用neo4j start 命令开启的服务在停止时需要调用neo4j stop停止运行

使用Python导入知识图谱

使用pip安装相关包

pip install --quiet pandas neo4j-rust-ext

不确定是由于使用的模型的问题还是GraphRAG本身的问题,实际导入的方式与官方提供的方式略有差距,主要体现在某些字段的命名上。如果笔者已经足够熟悉Neo4j可以自行修改,但如果只是想看一下知识图谱生成的效果可以参照笔者的方式修改。尽管在笔者看来,他的构建方式导入的图数据库展示效果并不会,实际上人工处理一下,自己构建会更加准确。
导入包

import time
import pandas as pd
from neo4j import GraphDatabase

设置数据库参数

GRAPHRAG_FOLDER = "ragtest/output"
NEO4J_URI = "neo4j://localhost"  # or neo4j+s://xxxx.databases.neo4j.io
NEO4J_USERNAME = "neo4j"
NEO4J_PASSWORD = "your password"
NEO4J_DATABASE = "neo4j"

实例化Neo4j driver

driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD))

构建批量导入函数

def batched_import(statement, df, batch_size=1000):"""Import a dataframe into Neo4j using a batched approach.Parameters: statement is the Cypher query to execute, df is the dataframe to import, and batch_size is the number of rows to import in each batch."""total = len(df)start_s = time.time()for start in range(0, total, batch_size):batch = df.iloc[start : min(start + batch_size, total)]result = driver.execute_query("UNWIND $rows AS value " + statement,rows=batch.to_dict("records"),database_=NEO4J_DATABASE,)print(result.summary.counters)print(f"{total} rows in {time.time() - start_s} s.")return total

创建constraints, idempotent操作

statements = ["\ncreate constraint chunk_id if not exists for (c:__Chunk__) require c.id is unique","\ncreate constraint document_id if not exists for (d:__Document__) require d.id is unique","\ncreate constraint entity_id if not exists for (c:__Community__) require c.community is unique","\ncreate constraint entity_id if not exists for (e:__Entity__) require e.id is unique","\ncreate constraint entity_title if not exists for (e:__Entity__) require e.name is unique","\ncreate constraint entity_title if not exists for (e:__Covariate__) require e.title is unique","\ncreate constraint related_id if not exists for ()-[rel:RELATED]->() require rel.id is unique","\n",
]for statement in statements:if len((statement or "").strip()) > 0:print(statement)driver.execute_query(statement)

导入create_final_documents.parquet

doc_df = pd.read_parquet(f"{GRAPHRAG_FOLDER}/create_final_documents.parquet", columns=["id", "title"]
)# Import documents
statement = """
MERGE (d:__Document__ {id:value.id})
SET d += value {.title}
"""batched_import(statement, doc_df)

导入create_final_text_units.parquet

text_df = pd.read_parquet(f"{GRAPHRAG_FOLDER}/create_final_text_units.parquet",columns=["id", "text", "n_tokens", "document_ids"],
)statement = """
MERGE (c:__Chunk__ {id:value.id})
SET c += value {.text, .n_tokens}
WITH c, value
UNWIND value.document_ids AS document
MATCH (d:__Document__ {id:document})
MERGE (c)-[:PART_OF]->(d)
"""batched_import(statement, text_df)

导入create_final_entities.parquet

entity_df = pd.read_parquet(f"{GRAPHRAG_FOLDER}/create_final_entities.parquet",columns=["title","type","description","human_readable_id","id",# "description_embedding","text_unit_ids",],
)
entity_df.rename(columns={"title": "name"}, inplace=True)entity_statement = """
MERGE (e:__Entity__ {id:value.id})
SET e += value {.human_readable_id, .description, name:replace(value.name,'"','')}
WITH e, value
CALL apoc.create.addLabels(e, case when coalesce(value.type,"") = "" then [] else [apoc.text.upperCamelCase(replace(value.type,'"',''))] end) yield node
UNWIND value.text_unit_ids AS text_unit
MATCH (c:__Chunk__ {id:text_unit})
MERGE (c)-[:HAS_ENTITY]->(e)
"""batched_import(entity_statement, entity_df)

导入create_final_relationships.parquet

rel_df = pd.read_parquet(f"{GRAPHRAG_FOLDER}/create_final_relationships.parquet",columns=["source","target","id",# "rank","weight","human_readable_id","description","text_unit_ids",],
)rel_statement = """MATCH (source:__Entity__ {name:replace(value.source,'"','')})MATCH (target:__Entity__ {name:replace(value.target,'"','')})// not necessary to merge on id as there is only one relationship per pairMERGE (source)-[rel:RELATED {id: value.id}]->(target)SET rel += value {.weight, .human_readable_id, .description, .text_unit_ids}RETURN count(*) as createdRels
"""batched_import(rel_statement, rel_df)

导入create_final_communities.parquet

community_df = pd.read_parquet(f"{GRAPHRAG_FOLDER}/create_final_communities.parquet",columns=["id", "level", "title", "text_unit_ids", "relationship_ids"],
)statement = """
MERGE (c:__Community__ {community:value.id})
SET c += value {.level, .title}
/*
UNWIND value.text_unit_ids as text_unit_id
MATCH (t:__Chunk__ {id:text_unit_id})
MERGE (c)-[:HAS_CHUNK]->(t)
WITH distinct c, value
*/
WITH *
UNWIND value.relationship_ids as rel_id
MATCH (start:__Entity__)-[:RELATED {id:rel_id}]->(end:__Entity__)
MERGE (start)-[:IN_COMMUNITY]->(c)
MERGE (end)-[:IN_COMMUNITY]->(c)
RETURn count(distinct c) as createdCommunities
"""batched_import(statement, community_df)

导入create_final_community_reports.parque

community_report_df = pd.read_parquet(f"{GRAPHRAG_FOLDER}/create_final_community_reports.parquet",columns=["id","community","level","title","summary","findings","rank","rank_explanation","full_content",],
)# Import communities
community_statement = """
MERGE (c:__Community__ {community:value.community})
SET c += value {.level, .title, .rank, .rank_explanation, .full_content, .summary}
WITH c, value
UNWIND range(0, size(value.findings)-1) AS finding_idx
WITH c, value, finding_idx, value.findings[finding_idx] as finding
MERGE (c)-[:HAS_FINDING]->(f:Finding {id:finding_idx})
SET f += finding
"""
batched_import(community_statement, community_report_df)

导入create_final_nodes.parquet

nodes_df = pd.read_parquet(f"{GRAPHRAG_FOLDER}/create_final_nodes.parquet")nodes_statement = """
MERGE (c:__Covariate__ {id:value.id})
SET c += apoc.map.clean(value, ["text_unit_id", "document_ids", "n_tokens"], [NULL, ""])
WITH c, value
MATCH (ch:__Chunk__ {id: value.text_unit_id})
MERGE (ch)-[:HAS_COVARIATE]->(c)
"""
batched_import(nodes_statement, nodes_df)

显示知识图谱

启动Neo4j后访问http://localhost:7474
在这里插入图片描述
可以看到效果还可以,不过可能由于使用的是本地模型,逻辑能力较差,所以有些实体之间的关系并没有理清,需要通过人工去做一下知识图谱的数据。不过从做数据的角度来看,如果没有知识图谱的需求,通过事件和实体查找的话应该可以找全相关的信息,只能说当前的这种方式差强人意。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/10469.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# Winform制作一个登录系统

using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace 登录 {p…

第11章:根据 ShuffleNet V2 迁移学习医学图像分类任务:甲状腺结节检测

目录 1. Shufflenet V2 2. 甲状腺结节检测 2.1 数据集 2.2 训练参数 2.3 训练结果 2.4 可视化网页推理 3. 下载 1. Shufflenet V2 shufflenet v2 论文中提出衡量轻量级网络的性能不能仅仅依靠FLOPs计算量,还应该多方面的考虑,例如MAC(memory acc…

AJAX案例——图片上传个人信息操作

黑马程序员视频地址&#xff1a; AJAX-Day02-11.图片上传https://www.bilibili.com/video/BV1MN411y7pw?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p26 图片上传 <!-- 文件选择元素 --><input type"file"…

AI DeepSeek-R1 Windos 10 环境搭建

1、安装&#xff1a; 下载 Python |Python.org CUDA Drivers for MAC Archive | NVIDIA pip 和virtualenv Download Ollama on Windows 如下图 2、下载模型 deepseek-r1 ollama run deepseek-r1 或者可以ollama run deepseek-r1:8b 或 3、安装一个可视化对话Chatbox 下载 …

【AI绘画】MidJourney关键词{Prompt}全面整理

AI绘画整理&#xff0c;MidJourney关键词。喜欢AI绘画的朋友必备&#xff0c;建议收藏&#xff0c;后面用到时供查阅使用。 1、光线与影子篇 中 英 闪耀的霓虹灯 shimmeringneon lights 黑暗中的影子 shadows in the dark 照亮城市的月光 moonlightilluminatingthe cit…

剑指offer 数组 持续更新中...

文章目录 1. 数组中重复的数字1.1 问题描述1.2 方法1: 排序1.3 方法2: 哈希表1.4 方法3: 原地交换 2. 寻找重复数2.1 问题描述2.2 方案1&#xff0c;使用辅助数组2.3 方案2&#xff0c;使用二分 3. 二维数组的查找3.2 方案1&#xff0c;贪心 4. 合并两个有序数组4.1 问题描述4.…

SQLAlchemy 2.0的简单使用教程

SQLAlchemy 2.0相比1.x进行了很大的更新&#xff0c;目前网上的教程不多&#xff0c;以下以链接mysql为例介绍一下基本的使用方法 环境及依赖 Python:3.8 mysql:8.3 Flask:3.0.3 SQLAlchemy:2.0.37 PyMySQL:1.1.1使用步骤 1、创建引擎&#xff0c;链接到mysql engine crea…

nodejs:express + js-mdict 网页查询英汉词典

向 DeepSeek R1 提问&#xff1a; 我想写一个Web 前端网页&#xff0c;后台用 nodejs js-mdict, 实现在线查询英语单词 1. 项目结构 首先&#xff0c;创建一个项目目录&#xff0c;结构如下&#xff1a; mydict-app/ ├── public/ │ ├── index.html │ ├── st…

23.Word:小王-制作公司战略规划文档❗【5】

目录 NO1.2.3.4 NO5.6​ NO7.8.9​ NO10.11​ NO12​ NO13.14 NO1.2.3.4 布局→页面设置对话框→纸张&#xff1a;纸张大小&#xff1a;宽度/高度→页边距&#xff1a;上下左右→版式&#xff1a;页眉页脚→文档网格&#xff1a;勾选只指定行网格✔→ 每页&#xff1a;…

联想拯救者R720笔记本外接显示屏方法,显示屏是2K屏27英寸

现在某品牌的13/14代&#xff08;CPU是13或14开头&#xff09;CPU缩肛有设计质量问题、CPU容易氧化易损坏易蓝屏等问题&#xff0c;现在大家买笔记本或台式电脑请不要考虑这两代CPU&#xff0c;或考虑AMD的CPU。 晚上23点10分前下单&#xff0c;第二天上午显示屏送到&#xff…

从0到1:C++ 开启游戏开发奇幻之旅(二)

目录 游戏开发核心组件设计 游戏循环 游戏对象管理 碰撞检测 人工智能&#xff08;AI&#xff09; 与物理引擎 人工智能 物理引擎 性能优化技巧 内存管理优化 多线程处理 实战案例&#xff1a;开发一个简单的 2D 射击游戏 项目结构设计 代码实现 总结与展望 游戏…

QT简单实现验证码(字符)

0&#xff09; 运行结果 1&#xff09; 生成随机字符串 Qt主要通过QRandomGenerator类来生成随机数。在此之前的版本中&#xff0c;qrand()函数也常被使用&#xff0c;但从Qt 5.10起&#xff0c;推荐使用更现代化的QRandomGenerator类。 在头文件添加void generateRandomNumb…

C++,STL 命名空间:理解 std 的作用、规范与陷阱

文章目录 引言一、为什么需要 std 命名空间&#xff1f;二、std 命名空间的组成三、使用 std 命名空间的正确姿势1. 显式作用域限定2. 谨慎使用 using 声明3. 头文件中禁止 using namespace std 四、常见陷阱与解决方案陷阱 1&#xff1a;与第三方库命名冲突陷阱 2&#xff1a;…

UE5 GAS RPG Character Classes

在正常的游戏中&#xff0c;我们应该考虑如何去初始化角色属性&#xff0c;并且要给角色分好类型。比如&#xff0c;在我们游戏中&#xff0c;我们如何去初始化小兵的属性&#xff0c;并且还要实现小兵随着等级的增长而增加属性。而且就是小兵也有类型的区分&#xff0c;比如我…

RRT_STAR路径规划代码

这是一段使用MATLAB编写的代码&#xff0c;实现了一个基于RRT*&#xff08;Rapidly-exploring Random Trees Star&#xff09;算法的路径规划。RRT*是一种用于在配置空间中搜索路径的采样算法&#xff0c;常用于机器人路径规划等领域。以下是代码的主要功能和结构&#xff1a; …

常见“栈“相关题目

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; 优选算法专题 目录 1047.删除字符串中的所有相邻重复项 844.比较含退格的字符串 227.基本计算器 II 394.字符串解码 946.验证栈序列 104…

窥探目标文件

文章目录 源文件如何变成可执行文件编译链接目标文件格式ELF文件格式节表重定位表(.rela)符号表(.symtab)符号(链接的接口)强符号与弱符号强引用与弱引用符号表表项符号类型和绑定信息符号所在段其他节源文件如何变成可执行文件 CPU只能执行二进制指令,无法执行用户直接编写的…

22.Word:小张-经费联审核结算单❗【16】

目录 NO1.2 NO3.4​ NO5.6.7 NO8邮件合并 MS搜狗输入法 NO1.2 用ms打开文件&#xff0c;而不是wps❗不然后面都没分布局→页面设置→页面大小→页面方向→上下左右&#xff1a;页边距→页码范围&#xff1a;多页&#xff1a;拼页光标处于→布局→分隔符&#xff1a;分节符…

java求职学习day23

MySQL 单表 & 约束 & 事务 1. DQL操作单表 1.1 创建数据库,复制表 1) 创建一个新的数据库 db2 CREATE DATABASE db2 CHARACTER SET utf8; 2) 将 db1 数据库中的 emp 表 复制到当前 db2 数据库 1.2 排序 通过 ORDER BY 子句 , 可以将查询出的结果进行排序 ( 排序只…