Skip to content

Commit 3b4b365

Browse files
Add PageRank example (#16)
* add pagerank example * update readme Co-authored-by: Katarina Supe <[email protected]> * add conclusion --------- Co-authored-by: Katarina Supe <[email protected]>
1 parent 6793172 commit 3b4b365

File tree

2 files changed

+364
-5
lines changed

2 files changed

+364
-5
lines changed

README.md

+20-5
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,26 @@ knowledge graphs seamlessly within Memgraph.
123123
- Querying and analyzing the knowledge graph to generate insightful responses
124124

125125
- **:bulb: Demo: [Multi-agent RAG System with LlamaIndex](./integrations/llamaindex/multi-agent-rag-system)**
126-
- This demo extends the RAG framework by utilizing a multi-agent architecture with LlamaIndex and Memgraph. Multiple agents collaborate to retrieve, process, and refine knowledge from the graph, enhancing response accuracy and depth.
127-
- **:mag_right: Key Features:**
128-
- Multi-agent system for distributed retrieval
129-
- Advanced knowledge graph construction and querying with Memgraph
130-
- Improved contextual understanding through agent collaboration
126+
- This demo extends the RAG framework by utilizing a multi-agent architecture with LlamaIndex and Memgraph. Multiple agents collaborate to retrieve, process, and refine knowledge from the graph, enhancing response accuracy and depth.
127+
- **:mag_right: Key Features:**
128+
- Multi-agent system for distributed retrieval
129+
- Advanced knowledge graph construction and querying with Memgraph
130+
- Improved contextual understanding through agent collaboration
131+
132+
- **:bulb: Demo: [Multi-agent RAG with Memgraph tools](./integrations/llamaindex/agentic-rag-with-graph-tools/agentic_rag_with_pagerank.ipynb)**
133+
- This demo demonstrates how to integrate Memgraph procedures, such as
134+
PageRank, as tools within a multi-agent architecture using LlamaIndex. The
135+
agents work collaboratively to retrieve data from the graph, process it,
136+
and perform calculations like summing the weight properties of nodes based
137+
on the PageRank algorithm.
138+
- **:mag_right: Key Features:**
139+
- Integration of PageRank as a tool in a multi-agent system
140+
- Execution of graph algorithms within agents for enhanced retrieval and
141+
computation
142+
- Multi-agent collaboration to process and analyze data retrieved from
143+
Memgraph
144+
- Dynamic query execution combining graph-based retrieval and computation
145+
tasks
131146

132147
**:book: Additional resources**
133148
- [LangChain & Memgraph](https://memgraph.com/docs/ai-ecosystem/graph-rag#langchain)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Integrating PageRank as a tool in a multi-agent workflow\n",
8+
"\n",
9+
"In this example, we'll create a multi-agent workflow using LlamaIndex and\n",
10+
"Memgraph to perform graph-based querying and computation. We'll explore how to:\n",
11+
"\n",
12+
"- Set up [**Memgraph**](https://memgraph.com/) as a graph store and create a\n",
13+
" sample dataset.\n",
14+
"- Use [**LlamaIndex**](https://www.llamaindex.ai/) to define function agents for\n",
15+
" retrieval and arithmetic operations.\n",
16+
"- Implement a **retriever agent** to run the\n",
17+
" [**PageRank**](https://memgraph.com/docs/advanced-algorithms/available-algorithms/pagerank)\n",
18+
" algorithm and extract ranked nodes.\n",
19+
"- Use a **calculator agent** to process numerical data from retrieved nodes.\n",
20+
"- Design an **AgentWorkflow** that integrates retrieval and computation for\n",
21+
" automated query execution.\n",
22+
"\n",
23+
"By the end, we'll have a system capable of retrieving graph-based data and\n",
24+
"performing calculations dynamically.\n",
25+
"\n",
26+
"## Prerequisites\n",
27+
"\n",
28+
"1. Make sure you have [Docker](https://www.docker.com/) running in the\n",
29+
" background. \n",
30+
"\n",
31+
"2. Run Memgraph\n",
32+
"\n",
33+
"The easiest way to run Memgraph is using the following commands:\n",
34+
"\n",
35+
"For Linux/macOS: `curl https://install.memgraph.com | sh`\n",
36+
"\n",
37+
"For Windows: `iwr https://windows.memgraph.com | iex`\n",
38+
"\n",
39+
"3. Install neccessary dependencies:\n"
40+
]
41+
},
42+
{
43+
"cell_type": "code",
44+
"execution_count": null,
45+
"metadata": {},
46+
"outputs": [],
47+
"source": [
48+
"%pip install llama-index llama-index-graph-stores-memgraph python-dotenv neo4j"
49+
]
50+
},
51+
{
52+
"cell_type": "markdown",
53+
"metadata": {},
54+
"source": [
55+
"4. Create vector index in Memgraph on the `__Entity__` label and `embedding`\n",
56+
" property. LlamaIndex creates embeddings and uses Memgraph's [vector\n",
57+
" search](https://memgraph.com/docs/querying/vector-search) for more accurate\n",
58+
" retrieval.\n",
59+
"\n",
60+
"`CREATE VECTOR INDEX entity ON :__Entity__(embedding) WITH CONFIG {\"dimension\":\n",
61+
"1536, \"capacity\": 1000};`\n",
62+
"\n",
63+
"## Environment setup\n",
64+
"\n",
65+
"Create a `.env` file that contains your OpenAI API key and the values of\n",
66+
"environment variables necessary to connect to your Memgraph instance. If the\n",
67+
"user is not created, the default value is the empty string:\n",
68+
"\n",
69+
"`OPENAI_API_KEY=sk-proj-...` \n",
70+
"`URI=bolt://localhost:7687` \n",
71+
"`AUTH_USER=\"\"`\n",
72+
"`AUTH_PASS=\"\"`\n",
73+
"\n",
74+
"## Create the script\n",
75+
"\n",
76+
"Let's first load our `.env` file and set the LLM model we want to use. In this\n",
77+
"example, we're using OpenAI's GPT-4 model.\n"
78+
]
79+
},
80+
{
81+
"cell_type": "code",
82+
"execution_count": null,
83+
"metadata": {},
84+
"outputs": [],
85+
"source": [
86+
"from dotenv import load_dotenv\n",
87+
"load_dotenv()\n",
88+
"from llama_index.llms.openai import OpenAI\n",
89+
"from llama_index.core import Settings\n",
90+
"\n",
91+
"# settings\n",
92+
"Settings.llm = OpenAI(model=\"gpt-4\",temperature=0)"
93+
]
94+
},
95+
{
96+
"cell_type": "markdown",
97+
"metadata": {},
98+
"source": [
99+
"### Connect to Memgraph\n",
100+
"\n",
101+
"In this section, we'll establish a connection to Memgraph using the environment\n",
102+
"variables for authentication and connection details.\n",
103+
"\n",
104+
"1. **Retrieve Environment Variables** \n",
105+
" The script fetches the `URI`, `AUTH_USER`, and `AUTH_PASS` values from the\n",
106+
" environment using `os.getenv()`. These values determine how the script\n",
107+
" connects to the Memgraph database.\n",
108+
"\n",
109+
"2. **Set Up Authentication** \n",
110+
" The credentials (`AUTH_USER`, `AUTH_PASS`) are combined into a tuple (`AUTH`)\n",
111+
" to be used for authentication.\n",
112+
"\n",
113+
"3. **Create a Memgraph Connection** \n",
114+
" A connection to Memgraph is established using `GraphDatabase.driver(URI,\n",
115+
" auth=AUTH)`. \n",
116+
"\n",
117+
"\n",
118+
"This setup ensures that the script can interact with your Memgraph instance."
119+
]
120+
},
121+
{
122+
"cell_type": "code",
123+
"execution_count": null,
124+
"metadata": {},
125+
"outputs": [],
126+
"source": [
127+
"import os\n",
128+
"from neo4j import GraphDatabase\n",
129+
"from llama_index.graph_stores.memgraph import MemgraphPropertyGraphStore\n",
130+
"\n",
131+
"URI = os.getenv(\"URI\")\n",
132+
"AUTH_USER = os.getenv(\"AUTH_USER\")\n",
133+
"AUTH_PASS = os.getenv(\"AUTH_PASS\")\n",
134+
"\n",
135+
"AUTH = (AUTH_USER, AUTH_PASS)\n",
136+
"\n",
137+
"driver = GraphDatabase.driver(URI, auth=AUTH)"
138+
]
139+
},
140+
{
141+
"cell_type": "markdown",
142+
"metadata": {},
143+
"source": [
144+
"### Define calculator tools\n",
145+
"\n",
146+
"Next, define addition and subtraction tools for calculations and a calculator\n",
147+
"agent. The role of the agent in this case will be to perform basic arithmetic\n",
148+
"operations with access to the defined tools."
149+
]
150+
},
151+
{
152+
"cell_type": "code",
153+
"execution_count": null,
154+
"metadata": {},
155+
"outputs": [],
156+
"source": [
157+
"from llama_index.core.tools import FunctionTool\n",
158+
"from llama_index.core.agent.workflow import FunctionAgent\n",
159+
"\n",
160+
"def add(a: int, b: int) -> int:\n",
161+
" \"\"\"Add two numbers.\"\"\"\n",
162+
" return a + b\n",
163+
"\n",
164+
"def subtract(a: int, b: int) -> int:\n",
165+
" \"\"\"Subtract two numbers.\"\"\"\n",
166+
" return a - b\n",
167+
"\n",
168+
"# Create agent configs\n",
169+
"calculator_agent = FunctionAgent(\n",
170+
" name=\"calculator\",\n",
171+
" description=\"Performs basic arithmetic operations\",\n",
172+
" system_prompt=\"You are a calculator assistant.\",\n",
173+
" tools=[\n",
174+
" FunctionTool.from_defaults(fn=add),\n",
175+
" FunctionTool.from_defaults(fn=subtract),\n",
176+
" ],\n",
177+
" llm=OpenAI(model=\"gpt-4\"),\n",
178+
")"
179+
]
180+
},
181+
{
182+
"cell_type": "markdown",
183+
"metadata": {},
184+
"source": [
185+
"Next, define a function to execute Cypher queries and implement a PageRank\n",
186+
"retrieval tool. The retriever agent is responsible for running the PageRank\n",
187+
"algorithm and retrieving ranked nodes using the defined tool."
188+
]
189+
},
190+
{
191+
"cell_type": "code",
192+
"execution_count": null,
193+
"metadata": {},
194+
"outputs": [],
195+
"source": [
196+
"def execute_query(query: str):\n",
197+
" \"\"\"Runs a given Cypher query inside a session.\"\"\"\n",
198+
" with driver.session() as session:\n",
199+
" return session.execute_read(lambda tx: list(tx.run(query)))\n",
200+
"\n",
201+
"def run_pagerank():\n",
202+
" \"\"\"Executes the PageRank algorithm.\"\"\"\n",
203+
" query = \"CALL pagerank.get() YIELD node, rank RETURN node, rank ORDER BY rank DESC LIMIT 5\"\n",
204+
" return execute_query(query)\n",
205+
"\n",
206+
"pagerank_tool = FunctionTool.from_defaults(\n",
207+
" fn=run_pagerank,\n",
208+
" name=\"pagerank_tool\",\n",
209+
" description=\"Runs the PageRank algorithm and retrieves ranked nodes.\"\n",
210+
")\n",
211+
"\n",
212+
"retriever_agent = FunctionAgent(\n",
213+
" name=\"retriever\",\n",
214+
" description=\"Manages data retrieval\",\n",
215+
" system_prompt=\"You have the ability to run the PageRank algorithm.\",\n",
216+
" tools=[\n",
217+
" pagerank_tool,\n",
218+
" ],\n",
219+
" llm=OpenAI(model=\"gpt-4\"),\n",
220+
" memory=None\n",
221+
")"
222+
]
223+
},
224+
{
225+
"cell_type": "markdown",
226+
"metadata": {},
227+
"source": [
228+
"### Create the dataset \n",
229+
"\n",
230+
"Now, let's create a small dataset in Memgraph consisting of 10 nodes, each with\n",
231+
"a weight property. The nodes are connected through `LINKS_TO` relationships,\n",
232+
"forming a structured graph. To create your graph, run the following Cypher query\n",
233+
"in your Memgraph instance:\n",
234+
"\n",
235+
"`CREATE (n1:Node {id: 1, weight: 1.2}), (n2:Node {id: 2, weight: 2.5}), (n3:Node\n",
236+
"{id: 3, weight: 0.8}), (n4:Node {id: 4, weight: 1.7}), (n5:Node {id: 5, weight:\n",
237+
"3.0}), (n6:Node {id: 6, weight: 2.2}), (n7:Node {id: 7, weight: 1.0}), (n8:Node\n",
238+
"{id: 8, weight: 2.8}), (n9:Node {id: 9, weight: 1.5}), (n10:Node {id: 10,\n",
239+
"weight: 2.0}), (n1)-[:LINKS_TO]->(n2), (n1)-[:LINKS_TO]->(n3),\n",
240+
"(n2)-[:LINKS_TO]->(n4), (n3)-[:LINKS_TO]->(n4), (n4)-[:LINKS_TO]->(n5),\n",
241+
"(n5)-[:LINKS_TO]->(n6), (n6)-[:LINKS_TO]->(n7), (n7)-[:LINKS_TO]->(n8),\n",
242+
"(n8)-[:LINKS_TO]->(n9), (n9)-[:LINKS_TO]->(n10), (n10)-[:LINKS_TO]->(n1),\n",
243+
"(n3)-[:LINKS_TO]->(n6), (n4)-[:LINKS_TO]->(n9), (n7)-[:LINKS_TO]->(n2),\n",
244+
"(n8)-[:LINKS_TO]->(n5);`\n",
245+
"\n",
246+
"### Memgraph graph store\n",
247+
"\n",
248+
"We'll now establish a connection to **Memgraph**, using\n",
249+
"`MemgraphPropertyGraphStore` from LlamaIndex. This allows us to store and\n",
250+
"retrieve structured data efficiently, enabling **graph-based querying** for\n",
251+
"retrieval-augmented generation (RAG) pipelines."
252+
]
253+
},
254+
{
255+
"cell_type": "code",
256+
"execution_count": null,
257+
"metadata": {},
258+
"outputs": [],
259+
"source": [
260+
"from llama_index.graph_stores.memgraph import MemgraphPropertyGraphStore\n",
261+
"\n",
262+
"graph_store = MemgraphPropertyGraphStore(\n",
263+
" username=\"\", # Your Memgraph username, default is \"\"\n",
264+
" password=\"\", # Your Memgraph password, default is \"\"\n",
265+
" url=\"bolt://localhost:7687\" # Connection URL for Memgraph\n",
266+
")"
267+
]
268+
},
269+
{
270+
"cell_type": "markdown",
271+
"metadata": {},
272+
"source": [
273+
"### Creating and running the workflow\n",
274+
"\n",
275+
"Finally, let's create an **AgentWorkflow** that ties together the previously\n",
276+
"defined agents, including the **calculator** and **retriever** agents. The\n",
277+
"workflow runs the PageRank algorithm, retrieves nodes, and sums their weight\n",
278+
"properties using the addition tool.\n",
279+
"\n",
280+
"We define an **async function** to execute the workflow, sending a user query\n",
281+
"that asks to run the PageRank algorithm and using the addition tool, add all of\n",
282+
"the weight properties of returned nodes."
283+
]
284+
},
285+
{
286+
"cell_type": "code",
287+
"execution_count": null,
288+
"metadata": {},
289+
"outputs": [],
290+
"source": [
291+
"\n",
292+
"from llama_index.core.agent.workflow import (\n",
293+
" AgentWorkflow,\n",
294+
" FunctionAgent,\n",
295+
" ReActAgent,\n",
296+
")\n",
297+
"import asyncio\n",
298+
"\n",
299+
"# Create and run the workflow\n",
300+
"workflow = AgentWorkflow(\n",
301+
" agents=[calculator_agent, retriever_agent], root_agent=\"retriever\"\n",
302+
")\n",
303+
"\n",
304+
"# Define an async function to run the workflow\n",
305+
"async def run_workflow():\n",
306+
" response = await workflow.run(user_msg=\"Run PageRank algorithm and using addition tool, add all of the weight properties of returned nodes.\")\n",
307+
" print(response)\n",
308+
"\n",
309+
"# Run the async function using asyncio\n",
310+
"asyncio.run(run_workflow())"
311+
]
312+
},
313+
{
314+
"cell_type": "markdown",
315+
"metadata": {},
316+
"source": [
317+
"## Conclusion\n",
318+
"\n",
319+
"This notebook provides a simple example of how to create and use **Memgraph procedures as tools** when implementing an **Agentic RAG system** with LlamaIndex. By integrating graph algorithms like **PageRank** into agents, we enable more powerful and context-aware data retrieval and computation.\n",
320+
"\n",
321+
"This is just the beginning, Memgraph supports a wide range of graph algorithms and procedures that can be leveraged in multi-agent workflows. You can explore more built-in algorithms and create custom ones using [MAGE (Memgraph Advanced Graph Extensions)](https://memgraph.com/docs/advanced-algorithms/available-algorithms) to further enhance your system's capabilities. The possibilities are endless!"
322+
]
323+
}
324+
],
325+
"metadata": {
326+
"kernelspec": {
327+
"display_name": "Python 3.10.16 ('llama_examples')",
328+
"language": "python",
329+
"name": "python3"
330+
},
331+
"language_info": {
332+
"name": "python",
333+
"version": "3.10.16"
334+
},
335+
"orig_nbformat": 4,
336+
"vscode": {
337+
"interpreter": {
338+
"hash": "42d147008be9a222f6757cc3d1527f7d3e48d8ff31a8ceb9f319427f25b07d46"
339+
}
340+
}
341+
},
342+
"nbformat": 4,
343+
"nbformat_minor": 2
344+
}

0 commit comments

Comments
 (0)