Announcing Neo4j Support for Modus
Building Model-Native Apps with Neo4j Knowledge Graphs
AI has transformed how we build applications, but organizations need more than just large language models to create reliable, production-ready systems.
Today, the Hypermode and Neo4j teams are excited to announce Neo4j support in Modus, bringing the power of knowledge graphs to AI workflows.
Knowledge graphs address key limitations of standalone LLMs by providing semantic structure and domain-specific context that both humans and AI can reason with. While LLMs excel at natural language understanding, they can hallucinate or miss crucial details that are locked up in private enterprise-specific data silos. Knowledge graphs solve this dilemma by grounding AI outputs in verified facts and relationships, while making their reasoning process fully traceable.
By combining the graph capabilities of Neo4j with Modus, organizations can now build AI applications that leverage both broad language understanding and deep domain expertise. Whether validating AI outputs, incorporating proprietary data, or ensuring auditability, knowledge graphs provide the missing link between powerful language models and enterprise requirements.
Under the hood, we use Neo4j’s Go driver in Modus. Thanks to the polyglot language support in Modus — powered by WebAssembly — we can support Neo4j in any language supported by Modus, which is currently Go and AssemblyScript.
Implementation
To stay production-ready, Modus creates and maintains drivers for Neo4j on app load, meaning connections are shared between function executions. This significantly reduces overhead, unlike existing serverless frameworks which require a new driver instance per function call.
Since the Neo4j SDK is using the Go driver under the hood, the function signature and implementation resemble the driver’s functions. Currently, executeQuery
is supported by the Modus SDK, with plans to expand to more complex functionality such as transactions, sessions, and parallelization. The SDK also supports Neo4j types, like Node
, Relationship
, and Path
, along with functions to help deserialize Cypher query responses (getRecordValue
, getProperty
).
Getting Started with Neo4j in Modus
Let’s take a look at a hands-on example of using Neo4j and Modus. Our example Modus-Neo4j app will:
Start with a sample Neo4j database of movies and movie reviews.
Use Modus and an embedding model hosted by Hypermode to create embeddings for each movie and save those in Neo4j.
Expose a GraphQL endpoint to find similar movies using Modus and Neo4j’s vector search functionality.
The easiest way to get started with Neo4j is by using the Neo4j Sandbox. Once you sign up for a free account, you’ll be prompted to choose a dataset. We’ll select the Recommendations dataset which includes data about movies and movie reviews.
Below is the graph data model for this database. We have nodes with labels like Movie
, Actor
, Genre
, and User
connected by relationships such as IN_GENRE
, ACTED_IN
, and RATED
.
Neo4j uses a query language called Cypher that allows developers to specify connected data patterns to be searched in the graph. For example, if we wanted to search for a movie with the title River Runs Through It, A, its genre, and find what other movies the actors of A River Runs Through It also acted in, we would write a Cypher query like this:
The results below show our Movie
node, the genre, and actors and their connections to the other movies in our database.
In addition to nodes and relationships, the property graph data model used by Neo4j also allows for storing property values on each node and on each relationship. Below you can see the properties stored on the Movie
node including movieId
, title
, and plot
.
Using the example that we’ve walked through above, let’s say you wanted to build a movie recommendation system. You could traverse the graph to find similar movies based on overlapping actors, genres, or a collaborative filtering type system that leverages user reviews. Another approach would be to create embeddings and use vector similarity search to find movies that are close together in vector space. We’ll take a look at that next.
Vector Search & Embeddings
Vector embeddings transform content into numerical vectors that capture semantic meaning, allowing similar concepts to be discovered even without exact keyword matches. This enables vector search — instead of just basic keyword matching, you can find content based on conceptual similarity by measuring the distance between embedding vectors.
While powerful, vector search alone lacks understanding of data relationships and structure. By combining embeddings with knowledge graphs, you create a more intelligent search engine that leverages both semantic similarity and explicit connections. Queries first find semantically similar content through embeddings, then the queries traverse the graph to surface additional relevant information through relationships.
This hybrid approach delivers richer results by combining the semantic understanding of embeddings with the structured relationships of knowledge graphs. A product search can find relevant documentation through vector similarity, then traverse the graph to surface related products, components, and solutions. The result is a more comprehensive search that understands both meaning and relationships, with a clear explanation of how results are connected through the graph.
Neo4j supports vector search, which we can expose through a Modus function and a GraphQL API to enable searching for similar movies. We’ll also use an embedding model hosted on Hypermode to generate embedding values based on the plot description of each movie.
Creating Embeddings with Hypermode
To get started with Hypermode and Neo4j we’ll create a new Modus project using the modus new
command. Be sure to install the Modus CLI if you haven’t already:
After creating the skeleton of our project we’ll update our app manifest modus.json
file to
Define a connection to our Neo4j Sandbox instance, using secret templates for the credentials that will be read from environment variables
Define a MiniLM model hosted on Hypermode to be used to generate embedding values.
Our modus.json
file should look like this:
The MiniLM embedding model is one of the shared models available with a Hypermode free trial.
Next, we’ll need to find the connection credentials for our Neo4j Sandbox instance and set them as environment variables in a .env
file. We can find these values in the Neo4j Sandbox application.
Then our .env
file should have the following format (note that our environment variables are namespaced by MODUS_
and the name of our connection (in this case NEO4J
).
Next, we’ll create a helper function to invoke the MiniLM embedding model and generate embeddings.
If we run our Modus app locally with the modus dev
command, our app will be built and a local GraphQL endpoint will expose this generateEmbeddings
function as a GraphQL query field. We can open a web browser at http://localhost:8686/explorer
to launch the Modus API Explorer and test this endpoint locally.
To access Hypermode hosted models in the local development environment we’ll need to install the hyp cli
and sign in to a Hypermode free trial account.
Once we sign in to Hypermode via the hyp cli
we can invoke the MiniLM model via our GraphQL API. Here, as you can see below, we generate embeddings for a single string, one of the movie plots.
We can use this function we just defined, combined with the Neo4j client in Modus, to:
Retrieve the movie plot values
Compute embeddings
Write those values back to Neo4j as a new
embedding
node propertyCreate a vector index in Neo4j
First we’ll define a type to represent our movie nodes.
Next, we’ll create a new function saveEmbeddingsToNeo4j
to find movies without an embedding value, generate embedding values using the movie plot property, write back to Neo4j and create a vector index.
We can invoke this saveEmbeddingsToNeo4j
function via the Modus API Explorer. The function takes a count
value to specify the maximum number of movies we want to update embedding values for, in batches of 100 at a time.
Now we’re ready to find similar movies using vector search!
First, we’ll define a class for our movie search results which will include a score that represents how similar our movie results are in vector space.
And now we’ll create a new function findSimilarMovies
to search for similar movies using vector search given a movie title. Note that the Cypher query in this function returns an object which we can then directly marshal into an array of MovieResult
objects using JSON.Parse
.
Now we search for similar movies using this Query field in the Modus API Explorer.
Now that we have everything working locally, the next step would be to deploy our Modus app to Hypermode, which we can do using a Hypermode free trial, and then build a front-end app to make a true movie search engine. I’ll leave both of those steps as an exercise for next time. :-)
Resources
Conclusion
I hope you’ve found this walkthrough helpful.
We’re excited to see what you will build with the new Neo4j support now available for Modus. Integrating knowledge graphs into your AI workflows isn’t always straightforward, but now it’s a little easier.
Keep up with every new feature and release in Modus: Star the Modus GitHub repo to stay in the loop with every new feature we ship.