www.artificialintelligenceupdate.com

AI Agent Frameworks: CrewAI vs. AutoGen vs. OpenAI Swarm

Absolutely, here’s a concise and informative paragraph converted from the excerpt:

Demystifying AI Agent Frameworks: CrewAI, Microsoft AutoGen, and OpenAI Swarm

Artificial intelligence (AI) is revolutionizing how we interact with technology. AI agent frameworks like CrewAI, Microsoft AutoGen, and OpenAI Swarm empower developers to build intelligent systems that operate independently or collaborate. CrewAI excels in fostering teamwork among agents, while AutoGen integrates seamlessly with Microsoft products and leverages powerful language models. OpenAI Swarm shines in its research-oriented approach and ability to handle large-scale agent interactions. Choosing the right framework depends on your project’s needs. CrewAI is ideal for collaborative tasks, AutoGen for dynamic applications with rich conversations, and OpenAI Swarm for experimental projects. This exploration paves the way for a future of seamless human-AI collaboration. Dive deeper and explore the exciting world of AI frameworks!

Comparing CrewAI, Microsoft AutoGen, and OpenAI Swarm as AI Agent Frameworks: Pros and Cons

In today’s world, artificial intelligence (AI) is rapidly changing the way we interact with technology. One of the most exciting areas of AI development is the creation of AI agent frameworks, which assist in building intelligent systems capable of operating independently or collaborating with other agents. Three significant frameworks dominating this field are CrewAI, Microsoft AutoGen, and OpenAI Swarm. Each of these frameworks has its strengths and weaknesses, making it essential to compare them. This blog post breaks down these frameworks in a way that is engaging and easy to understand, so even a twelve-year-old can grasp the concepts.


What is an AI Agent Framework?

Before diving into the specifics of CrewAI, Microsoft AutoGen, and OpenAI Swarm, let’s clarify what an AI agent framework is. An AI agent framework is a software environment designed to develop and manage AI agents—programs that can autonomously make decisions, learn from data, and interact with other agents or humans. Imagine them as smart robots that can think and communicate! For more information, see NIST’s Definition of an AI Agent.


1. CrewAI

Overview

CrewAI is a framework designed to promote teamwork among agents. It focuses on collaboration, allowing multiple agents to communicate and make decisions collectively. This framework is aimed at creating applications where communication and teamwork are paramount.

Pros

  • Collaboration: CrewAI allows agents to share information and learn from each other, leading to improved performance on tasks.
  • User-Friendly: The design is straightforward, making it easier for developers—especially those who may not have extensive coding skills—to create multi-agent systems.
  • Customizability: Developers can easily tailor the agents to fit specific needs or business requirements, enhancing its applicability across various domains.

Cons

  • Scalability Issues: As the number of agents increases, CrewAI may encounter challenges related to efficient scaling, potentially struggling with larger systems.
  • Limited Community Support: CrewAI has a smaller user community compared to other frameworks, which can hinder the availability of resources and assistance when needed.

2. Microsoft AutoGen

Overview

Microsoft AutoGen is designed to facilitate the creation of applications using large language models (LLMs). It emphasizes dialogue between agents, enabling them to interact dynamically with users and each other, thereby enhancing the overall user experience.

Pros

  • Integration with Microsoft Ecosystem: If you frequently use Microsoft products (like Word or Excel), you’ll find that AutoGen integrates seamlessly with those, offering a unified user experience.
  • Powerful LLM Support: AutoGen supports sophisticated language models, enabling agents to effectively comprehend and process human language.
  • Versatile Applications: You can create a wide variety of applications—from simple chatbots to complex data analysis systems—using this framework.

Cons

  • Complexity: New developers may face a steep learning curve, as it requires time and effort to master AutoGen’s capabilities.
  • Resource-Intensive: Applications developed with AutoGen generally necessitate substantial computing power, which might be difficult for smaller developers or businesses to access.

3. OpenAI Swarm

Overview

OpenAI Swarm is focused on harnessing the collective intelligence of multiple agents to address complex problems. It offers a testing environment, or sandbox, where developers can simulate agent interactions without real-world risks.

Pros

  • Innovative Testing Environment: Developers can safely experiment with agent interactions, gaining valuable insights into teamwork among intelligent programs.
  • Scalability: OpenAI Swarm is designed to manage numerous agents effectively, making it appropriate for large-scale projects.
  • Research-Oriented: Positioned within OpenAI’s advanced research frameworks, it employs cutting-edge practices and methodologies. More about OpenAI’s initiatives can be found here: OpenAI Research.

Cons

  • Limited Practical Applications: Because it is largely experimental, there are fewer real-world applications compared to other frameworks.
  • Inaccessible to Non-Technical Users: Individuals without a programming or AI background may find it challenging to utilize the Swarm framework effectively.

A Closer Look: Understanding the Frameworks

Let’s examine each framework a bit more to understand their potential use cases better.

CrewAI in Action

Imagine playing a strategic team game on your gaming console, where each team member communicates and strategizes. CrewAI can enable AI characters in a game to collaborate and exchange strategies just like real team members would.

Microsoft AutoGen in Action

Picture having a virtual friend who can converse with you and assist with your homework. Using Microsoft AutoGen, developers can create chatbots that interact with users while comprehending complex language cues, making these bots feel more human-like.

OpenAI Swarm in Action

Suppose you’re a scientist wanting to understand how bees collaborate to find food. OpenAI Swarm allows researchers to simulate various scenarios, observing how different AI agents react to challenges, similar to how actual bees develop teamwork to achieve their goals.


Conclusion: Which Framework is Right for You?

Choosing between CrewAI, Microsoft AutoGen, and OpenAI Swarm often depends on specific needs and project objectives. Here’s a simple way to think about which framework might work best for you:

  • For Collaborative Tasks: If your goal is teamwork among AI agents, CrewAI excels in this area.
  • For Dynamic Applications: If you’re building applications that require robust conversations and interactions, Microsoft AutoGen is a strong contender.
  • For Experimental Projects: If you wish to research or explore agent behavior, OpenAI Swarm is your best option.

Remember, each framework has its pros and cons, and the right choice will depend on your specific goals.

AI is an exciting field with endless possibilities, and understanding these frameworks can unlock many creative ideas and applications in our growing digital world! Whether you’re a developer, a business owner, or simply an enthusiast, exploring one of these frameworks opens doors to new discoveries.


Final Thoughts

AI agent frameworks are at the forefront of technology, gradually transforming our interactions with machines. CrewAI, Microsoft AutoGen, and OpenAI Swarm each provide unique pathways for creating intelligent systems capable of operating independently or collaborating. By understanding their features, strengths, and limitations, users can better appreciate the potential of AI in everyday applications.

This exploration of AI agent frameworks sets the stage for a future where collaboration between technology and humans becomes increasingly seamless. So, whether you’re coding your first AI agent or are just curious about these systems, the world of AI is awaiting your exploration!


With a thorough examination of these frameworks, we can appreciate the diversity and innovation in artificial intelligence today. Exciting times are ahead as we continue to develop and harness AI’s potential!


This blog post is just the beginning, and there’s so much more to learn. Stay curious, keep exploring, and embrace the future of AI!


If you found this post informative, feel free to share it with others who might be interested in AI frameworks. Stay tuned for more insights into the world of artificial intelligence!


Disclaimer: The information provided in this post is based on current research as of October 2023. Always refer to up-to-date resources and official documentation when exploring AI frameworks.

References

  1. Are Multi-Agent Systems the Future of AI? A Look at OpenAI’s … While OpenAI’s Swarm offers a simplified, experimental sandbox…
  2. e2b-dev/awesome-ai-agents: A list of AI autonomous agents – GitHub Create a pull request or fill in this form. Please keep the alphabetic…
  3. A Guide to Choosing the Best AI Agent in 2024 – Fluid AI Overview: AutoGen is an AI agent framework that enables the development of LLM…
  4. AI agents: Capabilities, working, use cases, architecture, benefits … Key elements of an AI agent. AI agents are autonomous entities powered by arti…
  5. Azure OpenAI + LLMs (Large Language Models) – GitHub Open search can insert 16,000 dimensions as a vector st…
  6. SeqRAG: Agents for the Rest of Us – Towards Data Science AI agents have great potential to perform complex tasks on our behalf….
  7. AI agents for data analysis: Types, working mechanism, use cases … … agent swarms to tackle complex data analysis problems collaboratively. …
  8. Best AI Agents 2024: Almost Every AI Agent Listed! – PlayHT We look at the best AI agents you should discover for your business. F…
  9. Lloyd Watts – ai #llm #machinelearning – LinkedIn … CrewAI | Autogen | Agents | LLMs | Computer Vision | Yolo. 8mo…
  10. LLM Mastery: ChatGPT, Gemini, Claude, Llama3, OpenAI & APIs Basics to AI-Agents: OpenAI API, Gemini API, Open-source LLMs, GPT-4o,…

Want to discuss this further? Connect with us on LinkedIn today.

Continue your AI exploration—visit AI&U for more insights now.

Learn GraphRAG with Python, Ollama, and NetworkX

Imagine a world where AI understands not just the words you say,
but also the intricate relationships between the concepts. This is the vision behind GraphRAG, a groundbreaking technique that leverages the power of graph theory to enhance the capabilities of Retrieval Augmented Generation (RAG). By representing information as interconnected nodes and edges, GraphRAG empowers AI models to delve deeper into the fabric of knowledge, leading to more accurate, comprehensive, and contextually relevant responses.


1. Introduction to Large Language Models (LLMs)

  • What are LLMs?
    LLMs, like GPT, are models trained on vast amounts of text to generate human-like text. They can understand and generate language based on prompts provided by users.
  • Context Window in LLMs
    The context window refers to the amount of information (in tokens or words) that an LLM can consider at a time while generating responses. Think of it like a short-term memory limit.
  • Context Window Limit
    The window is limited by design, meaning the model can only "remember" or take into account a certain amount of input at once. This limitation impacts how well it can respond to queries, especially when the input is long or complex.

2. Why Retrieval Augmented Generation (RAG) is Required

  • The Problem
    When users ask LLMs questions, the information may not fit within the limited context window. As a result, the LLM might give incomplete or incorrect answers.
  • What is RAG?
    Retrieval-Augmented Generation (RAG) solves this by combining LLMs with external data sources. Instead of relying solely on the model’s internal knowledge, RAG retrieves relevant information from databases or documents before generating a response.
  • How RAG Works
    • Retrieval: When a query is made, RAG retrieves relevant chunks of text from external sources.
    • Augmentation: These retrieved documents are then fed into the LLM’s context window.
    • Generation: The LLM uses both the input and the retrieved documents to create a response.

3. Shortcomings of RAG

  • Challenges with Relevant Information
    RAG doesn’t always retrieve the most relevant data, leading to incoherent or irrelevant answers.
  • Efficiency
    Retrieving and processing large documents can be computationally expensive.
  • Context Switching
    When the retrieval process pulls in too many chunks of data, the model might struggle to maintain context, resulting in disjointed or inaccurate responses.

4. Solutions: Semantic Chunking, Ranking, and Re-ranking

  • Semantic Chunking
    Breaks down large documents into meaningful "chunks" based on content. This helps in retrieving smaller, more relevant parts of a document.
  • Ranking
    After retrieval, the system ranks the chunks based on their relevance to the query.
  • Re-ranking
    Uses machine learning algorithms to re-rank the retrieved documents to ensure that the most useful information is prioritized.

5. Issues that Still Persist

  • Complex Queries
    RAG still struggles with highly complex, multi-part questions that require a deep understanding of multiple documents.
  • Scaling
    As the size of external knowledge sources grows, retrieval efficiency and relevance can degrade.

6. Introduction to Graph Theory and Graph Databases

  • Graph Theory Basics
    In graph theory, data is represented as nodes (entities) and edges (relationships between entities). This allows complex relationships to be modeled in a highly structured way.
  • Graph Databases
    Unlike traditional databases, graph databases store data in the form of nodes and edges, making it easier to traverse relationships and retrieve connected information.

7. How Graph Databases Work

  • Nodes and Edges
    Nodes represent entities, while edges represent relationships between these entities. Graph queries allow for fast and intuitive exploration of connections, which can be helpful in retrieving contextual data.
  • Graph Algorithms
    Graph databases often employ algorithms like depth-first search or breadth-first search to efficiently find related data based on a query.

8. What is GraphRAG?

  • Initial Concept
    GraphRAG combines graph theory with RAG to improve how information is retrieved and related across datasets. It enhances the retrieval process by mapping the relationships between pieces of data.
  • How GraphRAG Works

    • Graph-Based Retrieval: Instead of relying solely on document-level retrieval, GraphRAG uses graph databases to retrieve data based on the relationships between entities. This provides more contextually relevant data.

    • Traversing the Graph: Queries traverse the graph to identify not just relevant data but also data that is related through nodes and edges.

    • Improved Augmentation: This graph-based approach helps the LLM to understand not just the isolated pieces of information but also how they are related, improving the quality of generated responses.

Prerequisites

Before diving into the tutorial, ensure you have the following installed:

  1. Python: Version 3.6 or higher. You can download it from the official Python website.

  2. Ollama: An AI framework designed for building and deploying large language models. More information can be found on the Ollama website.

  3. NetworkX: A Python library for the creation, manipulation, and study of the structure and dynamics of complex networks. You can find it on NetworkX’s GitHub page or its official documentation.

We have already created a GitHub repo to get you started with GraphRAG:

To get started please visit this GitHub repo and clone it. For advanced users the code is given below

Step 1: Setting Up Your project directory and virtual environment

  1. Create a Directory: The command mkdir ./graphrag/ creates a new directory named graphrag in the current working directory. This directory will be used to store all files related to the GraphRAG project.

  2. Change Directory: The command cd ./graphrag/ changes the current working directory to the newly created graphrag directory. This ensures that any subsequent commands are executed within this directory.

  3. Create a Virtual Environment: The command python -m venv graphrag creates a virtual environment named graphrag within the current directory. A virtual environment is an isolated environment that allows you to manage dependencies for your project without affecting the global Python installation.

  4. Activate the Virtual Environment: The command python source/graphrag/bin/activate is intended to activate the virtual environment. However, the correct command for activation is typically source graphrag/bin/activate on Unix-like systems or graphragScriptsactivate on Windows. Activating the virtual environment modifies your shell’s environment to use the Python interpreter and packages installed in that environment.

Following these steps prepares your workspace for developing with GraphRAG, ensuring that dependencies are managed within the isolated environment.

mkdir ./graphrag/
cd ./graphrag/
python -m venv graphrag
python source/graphrag/bin/activate

Step 2: Collecting all the required dependencies

We have already made a requirements.txt file that has all the dependencies.


cd ./SimpleGRAPHRAG/
pip install -r requirements.txt

Make sure you have all the required libraries installed, as they will be essential for the steps that follow.

Step 3: Constructing a Knowledge Graph of sentences and embeddings with NetworkX & Ollama

In this step, we will create a set of fucntions that will read files,break them down from a whole book to every signle word in that book use RAKE algorithm to find the main keyword for each node in the network then create vector embeddings for all the nodes and store it in a graph. Read this ReadME to better understand how all the functions work.

import os
from typing import Tuple
import pickle
import ollama
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
import concurrent.futures
import re
import PyPDF2
from nltk.tokenize import sent_tokenize, word_tokenize
from nltk.corpus import stopwords
from rake_nltk import Rake

# Ensure you have the necessary NLTK resources
import nltk
nltk.download('punkt')
nltk.download('stopwords')

## this function below reads files

def read_file(file_path):
    """Read the content of a Markdown or PDF file."""
    if file_path.endswith('.pdf'):
        with open(file_path, 'rb') as file:
            reader = PyPDF2.PdfReader(file)
            text = ''
            for page in reader.pages:
                text += page.extract_text() + 'n'
            return text
    elif file_path.endswith('.md') or file_path.endswith('.markdown'):
        with open(file_path, 'r', encoding='utf-8') as file:
            return file.read()
    else:
        raise ValueError("Unsupported file type. Please provide a Markdown or PDF file.")

# this function was intended for chapter finding but could not use it due to complexity

def detect_table_of_contents(text):
    """Detect the Table of Contents in the document."""
    toc_pattern = re.compile(r'^(Chapter Contents d+|[0-9]+. [A-Za-z0-9 .-]+)(?:s*-s*[0-9]+)?$', re.MULTILINE)
    toc_matches = toc_pattern.findall(text)
    return toc_matches

# Here comes the most  important function for this project, 
# this function forms the network of the graph by chunking pages to paragraphs to senteces to words 
# and generating embeddings for each or them
# then it will find the keywords using RAKE Keyword extrantion algorithm
# giving us a knowledge graph
# this is a crude implementation hence the graph will be dense and process will take time
# If you manually give it the chapter names It will be blazing fast

def split_text_into_sections(text):
    """Split text into chapters, pages, paragraphs, sentences, and words."""

    def split_text(text, delimiters):
        """Split text using multiple delimiters."""
        # Create a regex pattern that matches any of the delimiters
        pattern = '|'.join(map(re.escape, delimiters))
        return re.split(pattern, text)

    chapternames = ["Bioprocess Development: An Interdisciplinary Challenge",
                    "Introduction to Engineering Calculations",
                    "Presentation and Analysis of Data",
                    "Material Balances",
                    "Energy Balances",
                    "Unsteady-State Material and Energy Balances",
                    "Fluid Flow and Mixing",
                    "Heat Transfer",
                    "Mass Transfer",
                    "Unit Operations",
                    "Homogeneous Reactions",
                    "Heterogeneous Reactions",
                    "Reactor Engineering",
                    "Appendices",
                    "Appendix A Conversion Factors",
                    "Appendix B Physical and Chemical Property Data",
                    "Appendix C Steam Tables",
                    "Appendix D Mathematical Rules",
                    "Appendix E List of Symbols",
                    "Index",
                    'A Special Tree', 'The School Among the Pines', 
                  'The Wind on Haunted Hill', 'Romi and the Wildfire', 'Tiger My Friend', 
                  'Monkey Trouble', 'Snake Trouble', 'Those Three Bears', 'The Coral Tree', 
                  "The Thief's Story", 'When the Trees Walked', 'Goodbye, Miss Mackenzie', 
                  'Pret in the House', 'The Overcoat', 'The Tunnel', 'Wild Fruit', 
                  'The Night the Roof Blew Off', "A Traveller's Tale", 'And Now We are Twelve']  # List of chapters already given for making it fast

    chapters = split_text(text,chapternames) # deactivate if not using the Biochem.md or rb.md
    #chapters=text.split('Chapter')  # activate if not using the Biochem.md
    graph = nx.Graph()
    stop_words = set(stopwords.words('english'))  # Load English stopwords

    def process_chapter(chapter):
        """Process a single chapter into pages, paragraphs, sentences, and words."""
        pages = chapter.split('nn')  # Assuming pages are separated by double newlines
        for page in pages:
            paragraphs = re.split(r'n+', page)  # Split into paragraphs
            for paragraph in paragraphs:
                sentences = sent_tokenize(paragraph)  # Split into sentences using NLTK
                for sentence in sentences:
                    words = word_tokenize(sentence)  # Split into words using NLTK
                    filtered_words = [word for word in words if word.lower() not in stop_words]  # Remove stopwords

                    # Create nodes in the graph
                    graph.add_node(sentence)
                    sentence_embedding = get_embedding(sentence)
                    graph.nodes[sentence]['embedding'] = sentence_embedding  # Store embedding in the graph

                    for word in filtered_words:
                        graph.add_node(word)
                        graph.add_edge(sentence, word)  # Connect sentence to its words

                    # Extract keywords using RAKE
                    r = Rake()
                    r.extract_keywords_from_text(sentence)
                    keywords = r.get_ranked_phrases()
                    graph.nodes[sentence]['keywords'] = keywords  # Store keywords in the graph
                    for keyword in keywords:
                        graph.add_node(keyword)
                        keyword_embedding = get_embedding(keyword)
                        graph.nodes[keyword]['embedding'] = keyword_embedding  # Store embedding in the graph
                        graph.add_edge(sentence, keyword)  # Connect sentence to its keywords

                graph.add_edge(page, paragraph)  # Connect page to its paragraphs
            graph.add_edge(chapter, page)  # Connect chapter to its pages

    # Use multithreading to process chapters
    with concurrent.futures.ThreadPoolExecutor() as executor:
        futures = [executor.submit(process_chapter, chapter) for chapter in chapters]
        for future in concurrent.futures.as_completed(futures):
            try:
                future.result()  # Wait for the chapter processing to complete
            except Exception as e:
                print(f"Error processing chapter: {e}")

    return graph

# GraphRAG takes a lot of time to calculate on big books so we will save the graphs as pickle

def save_graph(graph, filepath):
    """Save the graph to a specified file path using pickle."""
    # Check if the filepath is a directory or a file
    if os.path.isdir(filepath):
        raise ValueError("Please provide a file name along with the directory path.")

    # Check if the file path ends with .gpickle
    if not filepath.endswith('.gpickle'):
        raise ValueError("File must have a .gpickle extension.")

    # Ensure the directory exists
    os.makedirs(os.path.dirname(filepath), exist_ok=True)

    # Save the graph using pickle
    with open(filepath, 'wb') as f:
        pickle.dump(graph, f, pickle.HIGHEST_PROTOCOL)
    print(f"Graph saved to {filepath}")

# load the saved graph for future use

def load_graph(filepath):
    """Load the graph from a specified file path using pickle."""
    # Check if the file exists
    if not os.path.isfile(filepath):
        raise FileNotFoundError(f"No such file: '{filepath}'")

    # Check if the file path ends with .gpickle
    if not filepath.endswith('.gpickle'):
        raise ValueError("File must have a .gpickle extension.")

    # Load the graph using pickle
    with open(filepath, 'rb') as f:
        graph = pickle.load(f)
    print(f"Graph loaded from {filepath}")
    return graph

# The embedding Function

def get_embedding(text, model="mxbai-embed-large"):
    """Get embedding for a given text using Ollama API."""
    response = ollama.embeddings(model=model, prompt=text)
    return response["embedding"]

# This function below gets the similarity of keywords in question with the huge text

def calculate_cosine_similarity(chunk, query_embedding, embedding):
    """Calculate cosine similarity between a chunk and the query."""
    if np.linalg.norm(query_embedding) == 0 or np.linalg.norm(embedding) == 0:
        return (chunk, 0)  # Handle zero vectors
    cosine_sim = np.dot(query_embedding, embedding) / (np.linalg.norm(query_embedding) * np.linalg.norm(embedding))
    return (chunk, cosine_sim)

# The Retrival portion of the graphrag

def find_most_relevant_chunks(query, graph):
    """Find the most relevant chunks based on the graph and cosine similarity to the query."""
    # Step 1: Extract keywords from the query using RAKE
    r = Rake()
    r.extract_keywords_from_text(query)
    keywords = r.get_ranked_phrases()

    # Step 2: Find relevant sentences in the graph based on keywords
    relevant_sentences = set()
    for keyword in keywords:
        for node in graph.nodes():
            if keyword.lower() in node.lower():  # Check if keyword is in the node
                relevant_sentences.add(node)  # Add the whole sentence

    # Step 3: Calculate embeddings for relevant sentences
    similarities = {}
    query_embedding = get_embedding(query)

    for sentence in relevant_sentences:
        if sentence in graph.nodes:
            embedding = graph.nodes[sentence].get('embedding')
            if embedding is not None:
                cosine_sim = calculate_cosine_similarity(sentence, query_embedding, embedding)
                similarities[sentence] = cosine_sim[1]  # Store only the similarity score

    # Sort sentences by similarity
    sorted_sentences = sorted(similarities.items(), key=lambda item: item[1], reverse=True)
    return sorted_sentences[:20]  # Return top 20 relevant sentences

# fetch the best answer

def answer_query(query, graph):
    """Answer a query using the graph and embeddings."""
    relevant_chunks = find_most_relevant_chunks(query, graph)
    context = " ".join(chunk for chunk, _ in relevant_chunks)  # Combine top chunks for context
    response = ollama.generate(model='mistral-nemo:latest', prompt=f"Context: {context} Question: {query}") ## Change the LLM to anyone of your Ollama LLM that has tool use and logical reasoning

    if 'response' in response:
        return response['response']
    else:
        return "No answer generated."

Core Components

  1. Text Processing: Converts input text into a hierarchical structure.
  2. Graph Creation: Builds a NetworkX graph from the processed text.
  3. Embedding Generation: Uses Ollama to generate embeddings for text chunks.
  4. Retrieval: Finds relevant chunks based on query similarity.
  5. Answer Generation: Uses a language model to generate answers based on retrieved context.

Detailed Function Explanations

read_file(file_path)

Reads content from Markdown or PDF files.

Parameters:

  • file_path: Path to the input file

Returns:

  • String containing the file content

detect_table_of_contents(text)

Attempts to detect a table of contents in the input text.

Parameters:

  • text: Input text

Returns:

  • List of detected table of contents entries

split_text_into_sections(text)

Splits the input text into a hierarchical structure and creates a graph.

Parameters:

  • text: Input text

Returns:

  • NetworkX graph representing the text structure

save_graph(graph, filepath) and load_graph(filepath)

Save and load graph structures to/from disk using pickle.

Parameters:

  • graph: NetworkX graph object

  • filepath: Path to save/load the graph

get_embedding(text, model="mxbai-embed-large")

Generates embeddings for given text using Ollama API.

Parameters:

  • text: Input text

  • model: Embedding model to use

Returns:

  • Embedding vector

calculate_cosine_similarity(chunk, query_embedding, embedding)

Calculates cosine similarity between chunk and query embeddings.

Parameters:

  • chunk: Text chunk
  • query_embedding: Query embedding vector
  • embedding: Chunk embedding vector

Returns:

  • Tuple of (chunk, similarity score)

find_most_relevant_chunks(query, graph)

Finds the most relevant chunks in the graph based on the query.

Parameters:

  • query: Input query

  • graph: NetworkX graph of the text

Returns:

  • List of tuples containing (chunk, similarity score)

answer_query(query, graph)

Generates an answer to the query using the graph and a language model.

Parameters:

  • query: Input query

  • graph: NetworkX graph of the text

Returns:

  • Generated answer string

visualize_graph(graph)

Visualizes the graph structure using matplotlib.

Parameters:

  • graph: NetworkX graph object

Example Usage


#save the graph

savefile=  "./graphs/st5.gpickle"           #input("enter path for saving the knowledge base:")
save_graph(graph, savefile)
# Load a graph
graph = load_graph("./graphs/sample_graph.gpickle")

# Ask a question
query = "What is the significance of the cherry seed in the story?"
answer = answer_query(query, graph)
print(f"Question: {query}")
print(f"Answer: {answer}")

Visualization

The visualize_graph function can be used to create a visual representation of the graph structure. This is useful for small to medium-sized graphs but may become cluttered for very large texts.It is multithreaded so it should work faster than normal python code.

# visualizer is now multi threaded for speed

def visualize_graph(graph):
    """Visualize the graph using Matplotlib with improved layout to reduce overlap."""
    def draw_canvas(figsize: Tuple[int, int]):
        print("fig draw starting")
        plt.figure(figsize=(90, 70))  # Adjust figure size for better visibility
        print("fig draw done nn")

    def draw_nodes(graph, pos):
        """Draw nodes in the graph."""
        print("node draw starts")
        nx.draw_networkx_nodes(graph, pos, node_size=1200, node_color='lightblue', alpha=0.7)
        print("node draw ends nn")

    def draw_edges(graph, pos):
        """Draw edges in the graph."""
        print("edge draw starts")
        nx.draw_networkx_edges(graph, pos, width=1.0, alpha=0.3)
        print("edge draw done nn")

    def draw_labels(graph, pos):
        """Draw labels in the graph."""
        print("drawing lables ")
        labels = {}
        for node in graph.nodes():
            keywords = graph.nodes[node].get('keywords', [])
            label = ', '.join(keywords[:3])  # Limit to the first 3 keywords for clarity
            labels[node] = label if label else node[:10] + '...'  # Fallback to node name if no keywords
        nx.draw_networkx_labels(graph, pos, labels, font_size=16)  # Draw labels with smaller font size
        print("lables drawn nn")

    draw_canvas(figsize=(90,90))

    # Use ThreadPoolExecutor to handle layout and rescaling concurrently
    with concurrent.futures.ThreadPoolExecutor() as executor:
        # Submit layout calculation
        future_pos = executor.submit(nx.kamada_kawai_layout, graph)
        pos = future_pos.result()  # Get the result of the layout calculation

        # Submit rescaling of the layout
        future_rescale = executor.submit(nx.rescale_layout_dict, pos, scale=2)
        pos = future_rescale.result()  # Get the result of the rescaling

    # Use ThreadPoolExecutor to draw nodes, edges, and labels concurrently
    with concurrent.futures.ThreadPoolExecutor() as executor:
        executor.submit(draw_nodes, graph, pos)
        executor.submit(draw_edges, graph, pos)
        executor.submit(draw_labels, graph, pos)
    plt.title("Graph Visualization of Text Chunks")
    plt.axis('off')  # Turn off the axis
    plt.tight_layout()  # Adjust spacing for better layout
    plt.show()

Limitations and Future Work

  1. The current implementation may be slow for very large texts.
  2. Graph visualization can be improved for better readability.
  3. More advanced graph algorithms could be implemented for better retrieval.
  4. Integration with other embedding models and language models could be explored.
  5. Inetegration of a database curation LLM that tries to form a priliminary answer from the database, can be used to make answers more accurate.

Conclusion

This tutorial has provided a comprehensive introduction to GraphRAG using Python, Ollama, and NetworkX. By creating a simple directed graph and integrating it with a language model, you can harness the power of graph-based retrieval to enhance the output of generative models. The combination of structured data and advanced AI techniques opens up new avenues for applications in various domains, including education, research, and content generation.

Feel free to expand upon this tutorial by adding more complex graphs, enhancing the retrieval logic, or integrating additional AI models as needed.

Key Points

  • GraphRAG combines graph structures with AI for enhanced data retrieval.
  • NetworkX is a powerful library for graph manipulation in Python.
  • Ollama provides capabilities for generative AI responses based on structured data.

This concludes the detailed tutorial on GraphRAG with Python, Ollama, and NetworkX. Happy coding!

For further reading, you may explore:


This edited version maintains clarity, provides proper citations, and ensures the content is free of errors, meeting the high standards expected for a well-structured blog post.

References

[1] https://github.com/severian42/GraphRAG-Local-UI

[2] https://pypi.org/project/graphrag/0.3.0/

[3] https://microsoft.github.io/graphrag/posts/get_started/

[4] https://www.youtube.com/watch?v=zDv8akdf6v4

[5] https://dev.to/stephenc222/implementing-graphrag-for-query-focused-summarization-47ib

[6] https://iblnews.org/microsoft-open-sourced-graphrag-python-library-to-extract-insights-from-text/

[7] https://neo4j.com/developer-blog/neo4j-genai-python-package-graphrag/

[8] https://github.com/stephenc222/example-graphrag

[9] https://github.com/hr1juldey/SimpleGRAPHRAG/tree/main


For more tips and strategies, connect with us on LinkedIn now.

Discover more AI resources on AI&U—click here to explore.

Exit mobile version