使用属性图存储¶
通常在 LlamaIndex 中,你会创建一个 PropertyGraphStore
,将其传递给 PropertyGraphIndex
,然后它会自动用于插入和查询。
然而,有时你会想直接使用图存储。也许你想自己创建图并将其交给检索器或索引。也许你想编写自己的代码来管理和查询图存储。
本 Notebook 将引导你填充和查询图存储,而无需使用索引。
设置¶
此处,我们将利用 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`。
首次登录后,系统会要求你更改密码。
完成此步骤后,你就可以创建你的第一个属性图了!
输入 [ ]
已复制!
from llama_index.graph_stores.neo4j import Neo4jPropertyGraphStore
pg_store = Neo4jPropertyGraphStore(
username="neo4j",
password="llamaindex",
url="bolt://localhost:7687",
)
from llama_index.graph_stores.neo4j import Neo4jPropertyGraphStore pg_store = Neo4jPropertyGraphStore( username="neo4j", password="llamaindex", url="bolt://localhost:7687", )
插入¶
现在我们已经初始化了存储,可以向其中放入一些内容了!
向属性图存储中插入包括插入节点
EntityNode
- 包含标记的人、地点或事物ChunkNode
- 包含实体或关系来源的源文本
以及插入 Relation
(即链接多个节点)。
输入 [ ]
已复制!
from llama_index.core.graph_stores.types import EntityNode, ChunkNode, Relation
# Create a two entity nodes
entity1 = EntityNode(label="PERSON", name="Logan", properties={"age": 28})
entity2 = EntityNode(label="ORGANIZATION", name="LlamaIndex")
# Create a relation
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}, )
定义了一些实体和关系后,我们可以插入它们!
输入 [ ]
已复制!
pg_store.upsert_nodes([entity1, entity2])
pg_store.upsert_relations([relation])
pg_store.upsert_nodes([entity1, entity2]) pg_store.upsert_relations([relation])
如果需要,我们还可以定义这些内容来自的文本块
输入 [ ]
已复制!
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 个关系。
检索¶
现在我们的图已经填充了一些节点和关系,我们可以使用一些检索函数了!
输入 [ ]
已复制!
# get a node
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')]
输入 [ ]
已复制!
# get using properties
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')]
输入 [ ]
已复制!
# get paths from a node
paths = pg_store.get_rel_map(kg_nodes, depth=1)
for path in paths:
print(f"{path[0].id} -> {path[1].id} -> {path[2].id}")
# 从节点获取路径 paths = pg_store.get_rel_map(kg_nodes, depth=1) for path in paths: print(f"{path[0].id} -> {path[1].id} -> {path[2].id}")
Logan -> WORKS_FOR -> LlamaIndex
输入 [ ]
已复制!
# Run a cypher query (this will get all entity nodes)
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'}}]
输入 [ ]
已复制!
# get the original text node back
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.
输入 [ ]
已复制!
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])
输入 [ ]
已复制!
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')]
输入 [ ]
已复制!
# delete our entities
pg_store.delete(ids=[entity1.id, entity2.id])
# delete our text nodes
pg_store.delete([source_node.node_id])
# 删除实体 pg_store.delete(ids=[entity1.id, entity2.id]) # 删除文本节点 pg_store.delete([source_node.node_id])
输入 [ ]
已复制!
nodes = pg_store.get(ids=[entity1.id, entity2.id])
print(nodes)
nodes = pg_store.get(ids=[entity1.id, entity2.id]) print(nodes)
[]