使用属性图存储¶
通常情况下,在LlamaInde中,您会创建一个PropertyGraphStore
,将其传递给PropertyGraphIndex
,然后它会自动用于插入和查询。
然而,有时您可能希望直接使用图存储。也许您想自己创建图并将其交给检索器或索引。也许您想编写自己的代码来管理和查询图存储。
本笔记本将演示如何在不使用索引的情况下填充和查询图存储。
设置¶
在这里,我们将利用Neo4j来存储我们的属性图。
要在本地启动Neo4j,请首先确保您已安装docker。然后,您可以使用以下docker命令启动数据库
docker run \
-p 7474:7474 -p 7687:7687 \
-v $PWD/data:/data -v $PWD/plugins:/plugins \
--name neo4j-apoc \
-e NEO4J_apoc_export_file_enabled=true \
-e NEO4J_apoc_import_file_enabled=true \
-e NEO4J_apoc_import_file_use__neo4j__config=true \
-e NEO4JLABS_PLUGINS=\[\"apoc\"\] \
neo4j:latest
从这里,您可以在http://localhost:7474/打开数据库。在这个页面上,您将被要求登录。使用默认的用户名/密码 neo4j
和 neo4j
。
第一次登录后,您将被要求更改密码。
之后,您就可以准备创建您的第一个属性图了!
In [ ]:
Copied!
from llama_index.graph_stores.neo4j import Neo4jPGStore
pg_store = Neo4jPGStore(
username="neo4j",
password="llamaindex",
url="bolt://localhost:7687",
)
from llama_index.graph_stores.neo4j import Neo4jPGStore
pg_store = Neo4jPGStore(
username="neo4j",
password="llamaindex",
url="bolt://localhost:7687",
)
插入¶
现在我们已经初始化了存储,我们可以往里面放一些东西!
向属性图存储中插入内容包括插入节点:
EntityNode
- 包含某个被标记为人、地点或物品的实体ChunkNode
- 包含某个实体或关系来源于的源文本
以及插入Relation
(即连接多个节点)。
In [ ]:
Copied!
from llama_index.core.graph_stores.types import EntityNode,ChunkNode,Relation# 创建两个实体节点entity1 = EntityNode(label="PERSON", name="Logan", properties={"age": 28})entity2 = EntityNode(label="ORGANIZATION", name="LlamaIndex")# 创建关系relation = Relation( label="WORKS_FOR", source_id=entity1.id, target_id=entity2.id, properties={"since": 2023},)
from llama_index.core.graph_stores.types import EntityNode,ChunkNode,Relation# 创建两个实体节点entity1 = EntityNode(label="PERSON", name="Logan", properties={"age": 28})entity2 = EntityNode(label="ORGANIZATION", name="LlamaIndex")# 创建关系relation = Relation( label="WORKS_FOR", source_id=entity1.id, target_id=entity2.id, properties={"since": 2023},)
有了一些实体和关系定义,我们就可以插入它们了!
In [ ]:
Copied!
pg_store.upsert_nodes([entity1, entity2])
pg_store.upsert_relations([relation])
pg_store.upsert_nodes([entity1, entity2])
pg_store.upsert_relations([relation])
如果我们想要的话,我们也可以定义这些内容来自哪个文本块。
In [ ]:
Copied!
from llama_index.core.schema import TextNode
source_node = TextNode(text="Logan (age 28), works for LlamaIndex since 2023.")
relations = [
Relation(
label="MENTIONS",
target_id=entity1.id,
source_id=source_node.node_id,
),
Relation(
label="MENTIONS",
target_id=entity2.id,
source_id=source_node.node_id,
),
]
pg_store.upsert_llama_nodes([source_node])
pg_store.upsert_relations(relations)
from llama_index.core.schema import TextNode
source_node = TextNode(text="Logan (age 28), works for LlamaIndex since 2023.")
relations = [
Relation(
label="MENTIONS",
target_id=entity1.id,
source_id=source_node.node_id,
),
Relation(
label="MENTIONS",
target_id=entity2.id,
source_id=source_node.node_id,
),
]
pg_store.upsert_llama_nodes([source_node])
pg_store.upsert_relations(relations)
现在,你的图应该有3个节点和3个关系。
检索¶
现在我们的图表已经填充了一些节点和关系,我们可以访问一些检索函数!
In [ ]:
Copied!
# 获取一个节点kg_nodes = pg_store.get(ids=[entity1.id])print(kg_nodes)
# 获取一个节点kg_nodes = pg_store.get(ids=[entity1.id])print(kg_nodes)
[EntityNode(label='PERSON', embedding=None, properties={'age': 28, 'name': 'Logan'}, name='Logan')]
In [ ]:
Copied!
# 通过属性获取kg_nodes = pg_store.get(properties={"age": 28})print(kg_nodes)
# 通过属性获取kg_nodes = pg_store.get(properties={"age": 28})print(kg_nodes)
[EntityNode(label='PERSON', embedding=None, properties={'age': 28, 'name': 'Logan'}, name='Logan')]
In [ ]:
Copied!
# 从节点获取路径路径 = pg_store.get_rel_map(kg_nodes, depth=1)for 路径 in 路径: print(f"{路径[0].id} -> {路径[1].id} -> {路径[2].id}")
# 从节点获取路径路径 = pg_store.get_rel_map(kg_nodes, depth=1)for 路径 in 路径: print(f"{路径[0].id} -> {路径[1].id} -> {路径[2].id}")
Logan -> WORKS_FOR -> LlamaIndex
In [ ]:
Copied!
# 运行一个Cypher查询(这将获取所有实体节点)query = "match (n:`__Entity__`) return n"result = pg_store.structured_query(query)print(result)
# 运行一个Cypher查询(这将获取所有实体节点)query = "match (n:`__Entity__`) return n"result = pg_store.structured_query(query)print(result)
[{'n': {'name': 'Logan', 'id': 'Logan', 'age': 28}}, {'n': {'name': 'LlamaIndex', 'id': 'LlamaIndex'}}]
In [ ]:
Copied!
# 获取原始文本节点llama_nodes = pg_store.get_llama_nodes([source_node.node_id])print(llama_nodes[0].text)
# 获取原始文本节点llama_nodes = pg_store.get_llama_nodes([source_node.node_id])print(llama_nodes[0].text)
Logan (age 28), works for LlamaIndex since 2023.
In [ ]:
Copied!
new_node = EntityNode(
label="PERSON", name="Logan", properties={"age": 28, "location": "Canada"}
)
pg_store.upsert_nodes([new_node])
new_node = EntityNode(
label="PERSON", name="Logan", properties={"age": 28, "location": "Canada"}
)
pg_store.upsert_nodes([new_node])
In [ ]:
Copied!
nodes = pg_store.get(properties={"age": 28})
print(nodes)
nodes = pg_store.get(properties={"age": 28})
print(nodes)
[EntityNode(label='PERSON', embedding=None, properties={'location': 'Canada', 'age': 28, 'name': 'Logan'}, name='Logan')]
In [ ]:
Copied!
# 删除我们的实体pg_store.delete(ids=[entity1.id, entity2.id])# 删除我们的文本节点pg_store.delete([source_node.node_id])
# 删除我们的实体pg_store.delete(ids=[entity1.id, entity2.id])# 删除我们的文本节点pg_store.delete([source_node.node_id])
In [ ]:
Copied!
nodes = pg_store.get(ids=[entity1.id, entity2.id])
print(nodes)
nodes = pg_store.get(ids=[entity1.id, entity2.id])
print(nodes)
[]