Skip to main content

LlamaIndex property graph store

llama-index-graph-stores-rushdb makes RushDB the graph store behind a LlamaIndex PropertyGraphIndex. LlamaIndex extracts entities and relations from your documents; RushDB stores them as a typed graph with their embeddings, and LlamaIndex's retrievers search and traverse it.

What you getHow
Typed entities, no schema to declareEach extracted entity is a record under its own label (PERSON, COMPANY, …); each relation is a typed relationship with its properties
Graph and vectors in one databaseEntity and chunk embeddings go to RushDB vector indexes, so VectorContextRetriever needs no separate vector store
A schema for text-to-Cypherget_schema_str() returns the schema RushDB derives from the stored data: labels with counts, typed properties with value ranges, relationship patterns

The store works on RushDB Cloud and on a self-hosted RushDB engine (3.0.10 or later) with the same code.

Install​

Shell
pip install llama-index-graph-stores-rushdb

It needs Python 3.10 or later and llama-index-core 0.13 or 0.14. The package is open source and published on PyPI.

Connect​

RushDBPropertyGraphStore takes a RushDB SDK client. When you omit it, the client is built from the environment.

Python
import os

from rushdb import RushDB
from llama_index.graph_stores.rushdb import RushDBPropertyGraphStore

graph_store = RushDBPropertyGraphStore(RushDB(os.environ["RUSHDB_API_KEY"])) # RushDB Cloud
# graph_store = RushDBPropertyGraphStore(
# RushDB(os.environ["RUSHDB_ENGINE_TOKEN"], direct=True, engine_url="http://127.0.0.1:3000")
# )
ModeEnvironment variables
RushDB CloudRUSHDB_API_KEY, optional RUSHDB_URL
Self-hosted engineRUSHDB_ENGINE_URL, RUSHDB_ENGINE_TOKEN, optional RUSHDB_SCOPE on a multitenant engine

Setting both groups is an error, so a deployment never picks a mode by accident.

Build a property graph index​

Python
from llama_index.core import PropertyGraphIndex, SimpleDirectoryReader
from llama_index.core.indices.property_graph import SchemaLLMPathExtractor
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI

llm = OpenAI(model="gpt-4o-mini")
embed_model = OpenAIEmbedding(model_name="text-embedding-3-small")

index = PropertyGraphIndex.from_documents(
SimpleDirectoryReader("./data").load_data(),
property_graph_store=graph_store,
kg_extractors=[
SchemaLLMPathExtractor(
llm=llm,
possible_entities=["PERSON", "COMPANY", "PRODUCT"],
possible_relations=["WORKS_AT", "FOUNDED", "MAKES"],
)
],
embed_model=embed_model,
)

print(index.as_query_engine(llm=llm).query("Who founded the companies that make our products?"))

Any LlamaIndex extractor works; SchemaLLMPathExtractor keeps the LLM to the entity and relation types you list, which keeps the graph's labels consistent.

Retrieve​

RetrieverWorksNotes
VectorContextRetriever✓Vector search over every entity label, then the paths around the hits
LLMSynonymRetriever✓Looks entities up by id, then the paths around them
TextToCypherRetriever, CypherTemplateRetrieverwith enable_cypher=TrueNeeds Cypher enabled on a self-hosted engine (--languages sql,cypher)
Python
from llama_index.core.indices.property_graph import VectorContextRetriever

retriever = index.as_retriever(
sub_retrievers=[VectorContextRetriever(graph_store, embed_model=embed_model, path_depth=2)]
)
retriever.retrieve("Who founded Acme?")

vector_query accepts LlamaIndex metadata filters:

OperatorsNotes
==, !=, >, >=, <, <=, in, ninstrings, numbers, booleans
containsan element of a list property
text_matcha substring
is_emptythe property is missing
and, or, notcombine filters

Any other operator raises an error; it is never ignored.

note

RushDB's Cypher support is a release candidate, so TextToCypherRetriever can produce queries the engine refuses. The vector and synonym retrievers use RushDB's native queries and work everywhere.

How the graph is stored​

The store writes ordinary records and relationships, so you can explore the graph in the dashboard, with SearchQuery or with SQL.

LlamaIndexRushDB
EntityNode(name, label, properties)A record under label, with id, name and the properties
ChunkNode (a text chunk)A record under Chunk (the chunk_label option), with id, text and the chunk's metadata
Relation(label, source_id, target_id, properties)A relationship of type label, with the properties on the edge
An entity extracted from a chunkA MENTIONS relationship from the chunk to the entity
An embeddingAn external vector index per label: on name for entities, on text for chunks

Every record the store writes carries _kg_kind (entity or chunk), so the graph can share a project with other data. Nodes are matched by id: upserting a node updates it in place.

  • A node has one label; upserting it under a different label relabels it.
  • A relation is created once per source, type and target; upserting it again keeps the first properties.
  • Objects in properties are stored as JSON text, and ISO 8601 date strings as datetimes.
  • Deleting a node removes its relationships; its neighbours stay.

Next steps​