GitHub - Hikari-Systems/graphiti-slater: Run Graphiti's temporal knowledge graph on Slater: the FalkorDB dialect, transported over Bolt. · GitHub
/" data-turbo-transient="true" />
Skip to content
Search/
Sign in<br>Sign upAppearance settings
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
Uh oh!
There was an error while loading. Please reload this page.
Hikari-Systems
graphiti-slater
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
develop
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>6 Commits<br>6 Commits
docker-example
docker-example
src/graphiti_slater
src/graphiti_slater
tests
tests
.dockerignore
.dockerignore
.gitignore
.gitignore
README.md
README.md
pyproject.toml
pyproject.toml
View all files
Repository files navigation
graphiti-slater
Run Graphiti's temporal knowledge graph on<br>Slater.
Graphiti branches every query on driver.provider. Slater's Cypher surface is far<br>closer to FalkorDB's than to Neo4j's — it borrowed FalkorDB's vecf32(),<br>vec.cosineDistance() and db.idx.* namespace — so this adapter reports the<br>FalkorDB dialect and transports it over Bolt . Graphiti's own query strings run<br>unchanged; the adapter touches none of them.
from graphiti_core import Graphiti<br>from graphiti_slater import SlaterDriver
graphiti = Graphiti(graph_driver=SlaterDriver('bolt://slater:7687', 'graphiti', '…'))
For the stock Graphiti MCP server , which constructs its driver by name and offers no<br>hook, put a sitecustomize.py on PYTHONPATH:
from graphiti_slater import install<br>install()
and configure the server with database.provider: "neo4j" pointing at Slater. It builds<br>a SlaterDriver with no forking.
What the adapter actually does
Almost nothing, which is the point. Graphiti's writes come from<br>models/{nodes,edges}/*_db_queries.py and have no extension point, so anything Slater<br>cannot accept has to be fixed in Slater rather than papered over here. It has been. What<br>remains is five things.
Why
provider = FALKORDB<br>selects the branch whose Cypher Slater already speaks
SlaterSession<br>on the FalkorDB branch the bulk node save is a list of (query, params), which no Bolt session understands; and execute_write must not retry, because embeddings are generated inside the unit of work
search_interface<br>routes node similarity to the vector index (see below)
graph_operations_interface<br>respells node deletes for the writable layer (see below)
build_indices_and_constraints<br>verifies the schema instead of creating it
The FalkorDB operations classes are reused as-is. Nothing under<br>graphiti_core/driver/falkordb/operations/ imports the falkordb package — every<br>method does records, _, _ = await executor.execute_query(...) then dict access, which<br>neo4j.EagerResult and neo4j.Record both satisfy. The falkordb pip package is<br>deliberately not a dependency; FalkorDriver is never imported, because it hard-imports<br>that package at module scope.
Why node similarity is rerouted
Graphiti's FalkorDB node-similarity leg is a label scan that reads n.name_embedding as<br>a column and scores it inline. On Slater an indexed embedding is routed out of the<br>property record into the vector store, so a column read returns Null and that leg finds<br>nothing — measured, not assumed. db.idx.vector.queryNodes finds the same vectors<br>immediately, including ones written through the write delta moments earlier, so node<br>similarity goes through the index. It is also strictly faster than the scan it replaces.
The score scales differ and the conversion happens in the query: Slater's score is the<br>distance under the index metric, ascending; Graphiti's is (2 - cosineDistance) / 2,<br>descending.
The index ranks before the filters (group id, labels, timestamps) are applied, so the<br>adapter over-fetches (OVERSAMPLE) to keep recall. That cannot make a shortfall<br>impossible — it is inherent to index-then-filter — so very selective filters may still<br>return short.
Edge similarity is left alone. Slater's vector indexes are node-only, so an edge's<br>fact_embedding stays an ordinary column that reads back verbatim, and Graphiti's inline<br>vec.cosineDistance leg works exactly as written.
Fulltext: delegated, not overridden
Slater implements db.idx.fulltext.query{Nodes,Relationships} with the FalkorDB contract<br>Graphiti expects — the same two-argument call, the same YIELD node|relationship, score,<br>and score as BM25 ordered descending, which is what Graphiti's ORDER BY score DESC<br>relies on. So all four fulltext legs run Graphiti's own query unchanged, and hybrid search<br>fuses a real BM25 list with the similarity one.
Every leg sees writes immediately, with no consolidation in between. That needs Slater<br>>= 0.25.1 : relationships...