Creating a Knowledge Graph Chatbot Using Neo4j AuraDB

Fateh Ali Aamir
5 min readAug 19, 2024

--

If you’ve been exploring the world of AI and data, you know how powerful it can be to connect the dots between different pieces of information. Neo4j, a popular graph database, makes it easy to visualize and manage these connections. But what if you could ask questions in plain English and get answers straight from your data? That’s where OpenAI comes in. In this guide, I’ll show you how to set up a simple Knowledge Graph Chatbot using Neo4j AuraDB and OpenAI’s language models. Whether you’re just starting or looking to expand your skills, this tutorial will walk you through everything you need to know.

How to Create An Instance

Log onto the Neo4j console. Then you can sign up or log in. Now you’re inside the console. Now follow the steps below:
1. Make a new instance by clicking on “new instance”.

2. Choose the plan you want. I’d suggest starting with the free one.

3. Now you’re done. Just pick up the Connection URI and you’re good to go.

Connecting to Your Instance

You need four things:
1. OpenAI API Key
2. Neo4j URI
3. Neo4j Username
4. Neo4j Password

Now that you have all you need, let’s connect to the Aura DB.
First, set them up as environment variables.

from langchain_community.graphs import Neo4jGraph

# Set up environment variables
os.environ["OPENAI_API_KEY"] = "sk-***"
os.environ["NEO4J_URI"] = "neo4j+s://***"
os.environ["NEO4J_USERNAME"] = "***"
os.environ["NEO4J_PASSWORD"] = "***"

self.graph = Neo4jGraph()

The Neo4jGraph() constructor will automatically instantiate using the environment variables.

The Knowledge Graph Class

import os
from langchain_experimental.graph_transformers import LLMGraphTransformer
from langchain_openai import ChatOpenAI
from langchain_community.graphs import Neo4jGraph
from langchain.chains import GraphCypherQAChain
from langchain_core.documents import Document
from langchain.prompts import PromptTemplate

class KnowledgeGraph:
def __init__(self):
self.llm = ChatOpenAI(temperature=0, model_name="gpt-4o-mini")

self.graph = Neo4jGraph()

self.llm_transformer = LLMGraphTransformer(
llm=self.llm
)

self.qa_prompt = PromptTemplate(
input_variables=["question", "context"],
template="""
You are an AI assistant helping to answer questions about...

Question: {question}
Context: {context}

Answer:
"""
)

self.cypher_prompt = PromptTemplate(
input_variables=["question"],
template="""
You are an AI assistant designed to translate natural language questions into Cypher queries for a Neo4j graph database about triage systems. The graph has the following structure:

Nodes:
- Node A
- Node B
- Node C

Relationships:
- Relationship A
- Relationship B
- Relationship C
- Relationship D

Given a question, create a Cypher query that will retrieve the relevant information from the graph. Focus on using appropriate node labels, relationship types, and properties. Use MATCH, WHERE, and RETURN clauses as needed. If you need to perform any string matching, use case-insensitive comparison with '=~' and '(?i)'.

Question: {question}

Cypher query:
"""
)

self.qa_chain = GraphCypherQAChain.from_llm(
self.llm,
graph=self.graph,
verbose=True,
validate_cypher=True,
qa_prompt=self.qa_prompt,
cypher_prompt=self.cypher_prompt
)

For the knowledge graph class, we will initiate the LLM, the Graph, and the LLMGraphTransformer. We will also set up our QA Prompt and the Cypher Prompt. The QA Prompt is a standard prompt that will power the LLM to answer your questions as you want. You can give your AI a persona along with several instructions on how to operate. The Cypher Prompt is another part of the equation. The QA Chain has to generate a cypher query based on your input query so the Cypher Prompt will be used to assist the LLM in making that query. So you need to give details about your nodes and relationships and anything else that might improve cypher query generation. Both of these prompts are extremely important. In the end, you can just instantiate your QA Chain and you’re ready.

    def generate_knowledge_graph(self, text):
documents = [Document(page_content=text)]
graph_documents = self.llm_transformer.convert_to_graph_documents(documents)
self.graph.add_graph_documents(graph_documents)
print("Knowledge graph generated and stored in Neo4j.")
print(f"Nodes: {graph_documents[0].nodes}")
print(f"Relationships: {graph_documents[0].relationships}")

This is a simple function that will generate your knowledge graph. First, you need a list of Documents. Then, you can use the amazing LLMGraphTransformer to convert your documents into nodes and relationships. Once we have our graph documents, we can just use the add_graph_documents() function to add our new components to the graph.

    def query_knowledge_graph(self, query):
response = self.qa_chain.invoke({"query": query})
return response["result"]

In this function, we are simply invoking our qa_chain with a query and returning the response.

def refresh_schema(self):
self.graph.refresh_schema()
print("Graph schema refreshed.")
print(self.graph.schema)

The refresh_schema() function is important because every time you add in new documents to the graph, the structure will change. This will ensure that your knowledge is using the updated version instead of the previous one.

Terminal-Based Interface

from knowledge_graph import KnowledgeGraph

def main():
app = KnowledgeGraph()

while True:
print("\n1. Generate Knowledge Graph")
print("2. Query Knowledge Graph")
print("3. Refresh Schema")
print("4. Exit")
choice = input("Enter your choice (1-4): ")

if choice == "1":
text = input("Enter the text to generate a knowledge graph: ")
app.generate_knowledge_graph(text)
elif choice == "2":
query = input("Enter your query: ")
result = app.query_knowledge_graph(query)
print("Answer:", result)
elif choice == "3":
app.refresh_schema()
elif choice == "4":
break
else:
print("Invalid choice. Please try again.")

if __name__ == "__main__":
main()

In the interface, we have a standard choice-based interface. We give four choices: to generate a graph, to query the graph, to refresh the graph and to exit. Each choice triggers that specific function so it’s very easy to manage.

The future of AI lies in making powerful tools accessible and intuitive, and what we’ve built here is a glimpse into that future. As we explore further, we’ll find new ways to leverage this technology, whether it’s for automating tasks, enhancing data analysis, or developing more interactive and responsive applications. The journey from here is full of exciting opportunities. Can’t wait to see what more comes up in the world.

--

--