Skip to content

Commit 0b6ea8e

Browse files
committed
Update.
1 parent 4335f40 commit 0b6ea8e

File tree

1 file changed

+68
-24
lines changed

1 file changed

+68
-24
lines changed

memgraph-graphRAG/graphRAG.ipynb

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
"metadata": {},
66
"source": [
77
"# GraphRAG in Memgraph\n",
8-
"In this example, we are going to build GraphRAG by using the Memgraph ecosystem and OpenAI"
8+
"\n",
9+
"In this tutorial, we are going to build GraphRAG by using the Memgraph ecosystem and OpenAI. This example will be based on portion of the fixed dataset that will be enriched via unstructured data to create a knowledge graph. \n",
10+
"\n",
11+
"To perform the search of relevant data, in this example we will use the vector search on node embeddings to find schematically relevant data, after that the structured data will be pulled out of the graph and passed to LLM for answering the question. "
912
]
1013
},
1114
{
@@ -14,50 +17,61 @@
1417
"source": [
1518
"## Prerequisites\n",
1619
"\n",
20+
"In order to start this tutorial, you will need to have Docker, Python and OpenAI API key, with a few small tweaks you can make this work on your local ollama. \n",
21+
"\n",
1722
"First we need to start Memgraph that has the vector search, we can do this by running the following command: \n",
1823
"\n",
1924
"TODO: Updated the command when the vector search is available in the official Memgraph docker image\n",
2025
"```bash\n",
2126
"docker run -p 7687:7687 -p 7444:7444 memgraph/memgraph-mage:exp-vector-1 --log-level=TRACE --also-log-to-stderr --telemetry-enabled=False --experimental-vector-indexes='tag__Entity__embedding__{\"dimension\":384,\"limit\":3000}'\n",
2227
"```\n",
2328
"\n",
29+
"\n",
2430
"You can do this outside of this notebook. \n",
25-
"After that make sure you have few packages installed on your system. You can install them using pip3"
31+
"\n",
32+
"Once Memgraph is running in the background, make sure to load the initial dataset: "
2633
]
2734
},
2835
{
2936
"cell_type": "code",
3037
"execution_count": null,
31-
"metadata": {},
38+
"metadata": {
39+
"vscode": {
40+
"languageId": "markdown"
41+
}
42+
},
3243
"outputs": [],
3344
"source": [
34-
"\n",
35-
"pip install neo4j # for driver and connection to Memgraph\n",
36-
"pip install sentence-transformers # for sentence embeddings\n",
37-
"pip install openai # for access to LLM\n",
38-
"pip install dotenv # for environment variables\n"
45+
"```bash\n",
46+
"cat ./data/memgraph-export-got.cypherl | docker run -i memgraph/mgconsole --host=localhost\n",
47+
"``` "
3948
]
4049
},
4150
{
4251
"cell_type": "markdown",
4352
"metadata": {},
4453
"source": [
45-
"After the install of prerequisites, make sure to insert the base dataset into the Memgraph you can do it via following command: "
54+
"After dataset is ingested, install a few Python packages that are need to run a demo: "
4655
]
4756
},
4857
{
4958
"cell_type": "code",
5059
"execution_count": null,
51-
"metadata": {
52-
"vscode": {
53-
"languageId": "markdown"
54-
}
55-
},
60+
"metadata": {},
5661
"outputs": [],
5762
"source": [
58-
"```bash\n",
59-
"cat ./data/memgraph-export-final.cypherl | docker run -i memgraph/mgconsole --host=localhost\n",
60-
"``` "
63+
"\n",
64+
"pip install neo4j # for driver and connection to Memgraph\n",
65+
"pip install sentence-transformers # for calculating sentence embeddings\n",
66+
"pip install openai # for access to LLM\n",
67+
"pip install dotenv # for environment variables\n"
68+
]
69+
},
70+
{
71+
"cell_type": "markdown",
72+
"metadata": {},
73+
"source": [
74+
"After the install of prerequisites, make sure to insert the base dataset into the Memgraph you can do it via following command: "
6175
]
6276
},
6377
{
@@ -66,11 +80,17 @@
6680
"source": [
6781
"## Enrich knowledge graph with the embeddings \n",
6882
"\n",
69-
"Since in GraphRAG you are not writing actual queries, rather you are asking the questions about your domain knowledge graph in plain English, somehow you need to get to the relevant parts of your knowledge graph. \n",
83+
"Since in GraphRAG you are not writing actual Cypher queries, rather you are asking the questions about your domain knowledge graph in plain English, somehow you need to get to the relevant parts of your knowledge graph. \n",
84+
"\n",
85+
"To do this you need to encode the semantic meaning into the graph so you are able to locate the semantically similar parts of the graph. \n",
86+
"\n",
87+
"There are a few approaches you can take here, embedding the node labels and properties, embedding the triplets related to a node, embedding the specific paths node can take. As you put more data into embedding you will need a vector with more dimensions and this is costly for memory and performance. \n",
88+
"\n",
89+
"On the other hand, you will be able to locate the semantically similar parts of the graph with higher accuracy. This means if you are asking the longer questions, your semantical search will find the right part of the graph. \n",
7090
"\n",
71-
"To do this you need to encode the semantic meaning into the knowledge of the graph so you are able to retrive it based on you question. \n",
91+
"If semantic search misses the relevant part of the graph, LLM will not be able to answer the question correctly. \n",
7292
"\n",
73-
"Here is the function that calculates embeddings based on the node labels an properties: \n"
93+
"To provide a base line example, here is the function that calculates embeddings based on the node labels an properties: \n"
7494
]
7595
},
7696
{
@@ -106,17 +126,30 @@
106126
" session.run(\"MATCH (n) SET n:Entity\")"
107127
]
108128
},
129+
{
130+
"cell_type": "markdown",
131+
"metadata": {},
132+
"source": [
133+
"If we have a node `:Character {name:\"Viserys Targaryen\"}` in the graph the encoded embedding will be the label `:Charater` and `name:Viserys Targaryen`.\n",
134+
"\n",
135+
"Asking the question `Who is Viserys Targaryen?` will result in the very similar embedding and you will be able to locate that node in the graph. On the other hand, asking `To whom was Viserys Targaryen Loyal in seasone 1 of Game of Thrones?`, this is much longer question and there is a chance that this question won't find the `Viserys Targaryen` node in the graph. \n",
136+
"\n",
137+
"Embedding a triplet on the node will yield a better result in this case. "
138+
]
139+
},
109140
{
110141
"cell_type": "markdown",
111142
"metadata": {},
112143
"source": [
113144
"## Finding the relevant part of the graph\n",
114145
"\n",
146+
"TODO: configure and set vector search index based on new release\n",
147+
"\n",
115148
"Once the embeddings are calculated in your graph, you can perform a search on top of that embeddings, for that you need a Vector search. \n",
116149
"\n",
117150
"Memgraph supports vector search from version 2.22. \n",
118151
"\n",
119-
"The goal is to find the most similar node that resembles your question and extract the relevant knowledge from there. "
152+
"The goal is to find the most similar node that resembles your question and extract the relevant knowledge from there. The function takes the question embedding that is compared to embeddings stored on the nodes."
120153
]
121154
},
122155
{
@@ -153,13 +186,22 @@
153186
" return nodes_data[0] if nodes_data else None"
154187
]
155188
},
189+
{
190+
"cell_type": "markdown",
191+
"metadata": {},
192+
"source": [
193+
"Based on the difference of the question embeddings and node embeddings we get the most similar node. This provides us a pivot point from were we can pull the relevant data. If we were searching the information about `Viserys Targaryen`, we want to pull the data around that node, so this is a pivot node. "
194+
]
195+
},
156196
{
157197
"cell_type": "markdown",
158198
"metadata": {},
159199
"source": [
160200
"## Getting the relevant data\n",
161201
"\n",
162-
"Once you have the pivot node that is connected to the knowledge you need, you can fetch the relevant data around that node: \n"
202+
"Once we have the pivot node, we can start pulling the relevant structured data around that node. The most straight forward approach is to perform multiple hops from the pivot node. \n",
203+
"\n",
204+
"Here is the function that fetches the data around pivot node, that is number of `hops` away form the pivot node. \n"
163205
]
164206
},
165207
{
@@ -210,11 +252,13 @@
210252
"cell_type": "markdown",
211253
"metadata": {},
212254
"source": [
213-
"To avoid overload the LLM with the non-relevant data, we are dropping the embedding property out of the nodes. \n",
255+
"TODO: Insert a picture showing this. \n",
256+
"\n",
257+
"To avoid overload the LLM limited context with the non-relevant data, we are dropping the embedding property out of the nodes, since there is a lot of data in the embeddings, and they are not particularly relevant to the LLM. \n",
214258
"\n",
215259
"## Helper functions \n",
216260
"\n",
217-
"We also need different prompts to provide the context to the LLM what is expected to generate"
261+
"For LLM to understand what it needs to do, we need specific prompts. The `RAG_prompt` is the prompt describing how it should answer the question. The `question_prompt` is optimization made for calculating question embeddings, were only the key pices of information is extracted from the question to get the better embedding. For example if you as `Who is Viserys Targaryen?`, only the `Viserys Targaryen` will be extracted from the question. In the end the LLM will get the full question back in the `RAG_prompt`"
218262
]
219263
},
220264
{

0 commit comments

Comments
 (0)