### Running the Examples Setup Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/examples.md Provides instructions and Python code to set up and run the GraphRAG examples. It includes prerequisites like installing packages (neo4j, qdrant-client, sentence-transformers), setting up environment variables, and a main async function to execute different search scenarios. ```python import asyncio async def main(): # Basic search await basic_search() # Category search await category_search() # Health check await system_health_check() if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Docker Compose Management Commands Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/database_setup.md Commands to start and stop the Docker Compose services defined in the `docker-compose.yml` file. ```bash docker-compose up -d ``` ```bash docker-compose down ``` -------------------------------- ### Neo4j Basic Operations Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/database_setup.md Example Cypher queries for creating nodes (Document, Content), establishing relationships (CONTAINS, NEXT), and querying related content in Neo4j. ```cypher -- Create a document node\nCREATE (d:Document {id: "doc1", title: "GraphRAG Architecture", path: "/docs/architecture.md"})\n\n-- Create content chunks for the document\nCREATE (c1:Content {id: "chunk1", text: "This document describes the GraphRAG architecture combining Neo4j and Qdrant."}) CREATE (c2:Content {id: "chunk2", text: "The system uses a hybrid approach with vector similarity and graph relationships."}) -- Create relationships\nMATCH (d:Document {id: "doc1"})\nMATCH (c1:Content {id: "chunk1"})\nMATCH (c2:Content {id: "chunk2"})\nCREATE (d)-[:CONTAINS]->(c1)\nCREATE (d)-[:CONTAINS]->(c2)\nCREATE (c1)-[:NEXT]->(c2)\n -- Query related content\nMATCH (c:Content {id: "chunk1"})-[r:NEXT]->(related)\nRETURN c.text AS source, related.text AS related_content ``` -------------------------------- ### Usage Example for GraphRAGConnectionManager Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Demonstrates how to instantiate and use the `GraphRAGConnectionManager` to establish database connections and manage them. ```python # Create the connection manager manager = GraphRAGConnectionManager() # Connect to databases if manager.connect(): print("All connections established successfully") # Use the connections... # Close connections when done manager.close() else: print("Failed to establish all connections") ``` -------------------------------- ### Qdrant Data Insertion and Search Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/database_setup.md Provides an example of initializing Qdrant and SentenceTransformer clients, inserting a document with its embedding into a Qdrant collection, and performing a similarity search. It includes a fallback mechanism for search operations to ensure compatibility across different Qdrant versions and prints the search results including ID, score, and text. ```python from qdrant_client import QdrantClient from sentence_transformers import SentenceTransformer import warnings # Suppress version compatibility warnings warnings.filterwarnings("ignore", category=UserWarning, module="qdrant_client") # Initialize clients qdrant = QdrantClient(host="localhost", port=6333) model = SentenceTransformer('all-MiniLM-L6-v2') # Insert a document text = "This document describes the GraphRAG architecture." embedding = model.encode(text).tolist() qdrant.upsert( collection_name="document_chunks", points=[ { "id": "chunk1", "vector": embedding, "payload": { "text": text, "metadata": { "doc_id": "doc1", "chunk_id": "chunk1", "sequence": 1 } } } ] ) # Search for similar documents query = "Tell me about the GraphRAG architecture" query_vector = model.encode(query).tolist() # Handle different Qdrant versions with compatible search approach try: # Newer Qdrant versions search_result = qdrant.search( collection_name="document_chunks", query_vector=query_vector, limit=5 ) except Exception as e: # Fallback for compatibility issues print(f"Using fallback search due to: {str(e)}") search_result = qdrant.search( collection_name="document_chunks", query_vector=query_vector, limit=5 ) for result in search_result: print(f"ID: {result.id}, Score: {result.score}") print(f"Text: {result.payload['text']}") print("---") ``` -------------------------------- ### Install Dependencies Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Installs the necessary Python packages for connecting to Neo4j and Qdrant, along with sentence-transformers for embeddings. ```bash pip install neo4j==5.9.0 qdrant-client==1.6.0 sentence-transformers==2.2.2 ``` -------------------------------- ### Setup Databases Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/scripts/index.md Initializes both Neo4j and Qdrant databases with the required schemas and collections. This is a foundational step before importing data. ```bash python scripts/setup_databases.py ``` -------------------------------- ### Qdrant Collection Setup and Indexing Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/database_setup.md Demonstrates how to connect to Qdrant, create a collection for document embeddings with specified vector parameters (size and distance), and set up payload indexes for efficient filtering on 'metadata.doc_id' and 'metadata.sequence'. It also includes suppressing user warnings related to Qdrant client version compatibility. ```python from qdrant_client import QdrantClient from qdrant_client.http import models import warnings # Suppress version compatibility warnings warnings.filterwarnings("ignore", category=UserWarning, module="qdrant_client") # Connect to Qdrant client = QdrantClient("localhost", port=6333) # Create a collection for document embeddings # Using 384 dimensions for all-MiniLM-L6-v2 embeddings client.create_collection( collection_name="document_chunks", vectors_config=models.VectorParams( size=384, # Dimension size for the embedding model distance=models.Distance.COSINE ), ) # Create a payload index for efficient filtering client.create_payload_index( collection_name="document_chunks", field_name="metadata.doc_id", field_schema=models.PayloadSchemaType.KEYWORD, ) # Create payload index for chunk sequence client.create_payload_index( collection_name="document_chunks", field_name="metadata.sequence", field_schema=models.PayloadSchemaType.INTEGER, ) ``` -------------------------------- ### Qdrant Python Client Documentation Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/index.md Quick start guide and documentation for the Qdrant Python client, detailing how to interact with Qdrant vector databases. ```APIDOC Qdrant Python Client Documentation: URL: https://qdrant.tech/documentation/quick-start/ ``` -------------------------------- ### Docker Compose for Neo4j and Qdrant Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/database_setup.md Sets up Neo4j and Qdrant services using Docker Compose. It defines volumes, networks, and environment variables for both databases, including Neo4j's APOC plugin. ```yaml version: '3'\n\nservices:\n neo4j:\n image: neo4j:5.13.0\n container_name: graphrag_neo4j\n ports:\n - "7474:7474" \n - "7687:7687" \n environment:\n - NEO4J_AUTH=neo4j/password\n - NEO4J_apoc_export_file_enabled=true\n - NEO4J_apoc_import_file_enabled=true\n - NEO4J_apoc_import_file_use__neo4j__config=true\n - NEO4J_PLUGINS=["apoc"]\n volumes:\n - neo4j_data:/data\n - neo4j_logs:/logs\n - neo4j_import:/var/lib/neo4j/import\n - neo4j_plugins:/plugins\n networks:\n - graphrag_network\n\n qdrant:\n image: qdrant/qdrant:v1.5.1\n container_name: graphrag_qdrant\n ports:\n - "6335:6333" # HTTP (mapped to non-standard port)\n - "6334:6334" # gRPC\n volumes:\n - qdrant_data:/qdrant/storage\n environment:\n - QDRANT_ALLOW_CORS=true\n networks:\n - graphrag_network\n\nvolumes:\n neo4j_data:\n neo4j_logs:\n neo4j_import:\n neo4j_plugins:\n qdrant_data:\n\nnetworks:\n graphrag_network:\n driver: bridge ``` -------------------------------- ### Creating and Editing Configuration File Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/README.md Steps to copy the example environment file and edit it with specific project configurations. ```bash cp .env.example .env # Edit .env with your configuration ``` -------------------------------- ### Qdrant API Endpoints for Verification Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/database_setup.md Provides the API endpoints for verifying the Qdrant service status and managing collections. These endpoints are crucial for checking if the Qdrant instance is running and accessible, and for interacting with the collections API. ```APIDOC Qdrant Service Verification: - Web dashboard: http://localhost:6335/dashboard - Collections API: http://localhost:6335/collections ``` -------------------------------- ### Installing Project Dependencies Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/README.md Command to install all required Python packages listed in the `requirements.txt` file. ```bash pip install -r requirements.txt ``` -------------------------------- ### Neo4j Python Driver Documentation Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/index.md Official documentation for the Neo4j Python driver, covering installation, connection, and Cypher query execution. ```APIDOC Neo4j Python Driver Documentation: URL: https://neo4j.com/docs/api/python-driver/current/ ``` -------------------------------- ### Neo4j Cypher Query for Verification Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/database_setup.md A basic Cypher query to verify the Neo4j database connection and retrieve a sample of data. This command is used to ensure that Neo4j is running and accessible, and that basic data retrieval operations are functioning correctly. ```APIDOC Neo4j Verification Query: MATCH (n) RETURN n LIMIT 5 ``` -------------------------------- ### Neo4j Database Schema Design Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/database_setup.md Cypher statements to create constraints and indexes for the Neo4j database schema, optimizing for content, documents, topics, and entities. ```cypher CREATE CONSTRAINT IF NOT EXISTS FOR (c:Content) REQUIRE c.id IS UNIQUE;\nCREATE CONSTRAINT IF NOT EXISTS FOR (d:Document) REQUIRE d.id IS UNIQUE;\nCREATE CONSTRAINT IF NOT EXISTS FOR (t:Topic) REQUIRE t.name IS UNIQUE;\nCREATE CONSTRAINT IF NOT EXISTS FOR (e:Entity) REQUIRE e.name IS UNIQUE;\n\nCREATE INDEX IF NOT EXISTS FOR (c:Content) ON (c.text);\nCREATE INDEX IF NOT EXISTS FOR (d:Document) ON (d.title);\nCREATE INDEX IF NOT EXISTS FOR (d:Document) ON (d.category);\nCREATE INDEX IF NOT EXISTS FOR (d:Document) ON (d.path); ``` -------------------------------- ### GraphRAG Tool Usage Example Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/query.md Example demonstrating how to initialize and use the GraphRAGTool in an MCP environment. It shows executing a search query with specific parameters and processing the returned results, including error handling. ```python # Initialize the tool graphrag_tool = GraphRAGTool() # Execute a search results = await graphrag_tool.execute( query="How to configure Neo4j authentication?", limit=5, category="setup" ) # Process results if results['status'] == 'success': for doc in results['results']: print(f"Document: {doc['title']}") print(f"Score: {doc['score']}") print(f"Related docs: {len(doc['related_docs'])}") print("---") else: print(f"Error: {results['error']}") # Clean up graphrag_tool.cleanup() ``` -------------------------------- ### Running Connection Tests Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/testing/index.md This snippet shows how to activate a virtual environment, install necessary dependencies (neo4j, qdrant-client), and execute the connection test script. ```bash # Activate virtual environment source venv/bin/activate # Install dependencies if needed pip install neo4j qdrant-client # Run the test python scripts/testing/test_connections.py ``` -------------------------------- ### System Health Check with GraphRAGTool Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/examples.md Provides an example of checking the system's health using GraphRAGTool and HealthCheck. It retrieves and prints the status of Neo4j and Qdrant, including any associated messages or errors. Ensures tool cleanup. ```python from graphrag import GraphRAGTool, HealthCheck async def system_health_check(): tool = GraphRAGTool() health_checker = HealthCheck(tool.manager) try: # Check system health status = await health_checker.check_health() print("System Health Status:") print(f"Timestamp: {status['timestamp']}") # Neo4j status print("\nNeo4j:") print(f"Status: {status['neo4j']['status']}") if 'message' in status['neo4j']: print(f"Message: {status['neo4j']['message']}") elif 'error' in status['neo4j']: print(f"Error: {status['neo4j']['error']}") # Qdrant status print("\nQdrant:") print(f"Status: {status['qdrant']['status']}") if status['qdrant']['status'] == 'healthy': print(f"Vectors: {status['qdrant']['vectors_count']}") elif 'error' in status['qdrant']: print(f"Error: {status['qdrant']['error']}") finally: tool.cleanup() ``` -------------------------------- ### Basic Search with GraphRAGTool Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/examples.md Demonstrates how to initialize GraphRAGTool and execute a basic search query. It processes the results, printing the title, score, and content of the found documents. Includes cleanup of the tool. ```python from graphrag import GraphRAGTool async def basic_search(): # Initialize the tool tool = GraphRAGTool() try: # Execute a simple search results = await tool.execute( query="How to configure Neo4j authentication?", limit=5 ) # Process results if results['status'] == 'success': for doc in results['results']: print(f"Title: {doc['title']}") print(f"Score: {doc['score']:.4f}") print(f"Content: {doc['content'][:200]}...") print("---") finally: tool.cleanup() ``` -------------------------------- ### Environment Variables for Connection Configuration Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Shows how to define connection parameters using environment variables in a `.env` file and load them into a Python script. ```bash # .env file NEO4J_URI=bolt://localhost:7688 NEO4J_USER=neo4j NEO4J_PASSWORD=password QDRANT_HOST=localhost QDRANT_PORT=6335 QDRANT_COLLECTION=document_chunks ``` -------------------------------- ### Database Connection Parameters Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Lists the verified connection parameters for Neo4j and Qdrant databases, including service ports and authentication methods. ```APIDOC Database Connection Parameters: Neo4j: HTTP Port: 7474 Bolt Port: 7687 Authentication: neo4j/password Qdrant: HTTP Port: 6333 Authentication: None (default) ``` -------------------------------- ### Setup Neo4j Schema Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/scripts/index.md Creates the necessary schema within the Neo4j graph database. This script is typically run as part of the initial database setup. ```python python scripts/setup_neo4j_schema.py ``` -------------------------------- ### Batch Processing of Queries with GraphRAGTool Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/examples.md Demonstrates how to process a list of queries in batch using GraphRAGTool. It iterates through the queries, executes each one, and collects successful results, while logging failures. Includes tool cleanup. ```python from graphrag import GraphRAGTool from typing import List async def batch_search(queries: List[str]): tool = GraphRAGTool() try: results = [] for query in queries: # Execute search for each query response = await tool.execute(query=query) if response['status'] == 'success': results.append({ 'query': query, 'results': response['results'] }) else: print(f"Failed query: {query}") print(f"Error: {response.get('error')}") return results finally: tool.cleanup() ``` -------------------------------- ### Starting Neo4j and Qdrant with Docker Compose Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/README.md Command to launch Neo4j and Qdrant services in detached mode using Docker Compose. ```bash docker-compose up -d ``` -------------------------------- ### Database Connection Testing Reports Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/index.md Internal documentation for database connection testing, including detailed reports and connection information. ```APIDOC Database Connection Testing: Location: ../test_db_connection/index.md ``` -------------------------------- ### Testing GraphRAG MCP Implementation Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/index.md Provides instructions on how to test the implemented GraphRAG MCP tool. This involves activating a virtual environment and running a Python script designed for querying the tool. ```bash # Activate virtual environment source venv/bin/activate # Run the test script python scripts/testing/query_tester.py ``` -------------------------------- ### GraphRAGConnectionManager Class Methods Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Provides methods for connecting to Neo4j and Qdrant, loading embedding models, and closing connections. Includes error handling for connection attempts and model loading. ```python def _connect_qdrant(self): """Connect to Qdrant.""" retry_count = 0 max_retries = 5 wait_time = 5 while retry_count < max_retries: try: self.qdrant_client = QdrantClient(host=self.qdrant_host, port=self.qdrant_port) # Check if collection exists self.qdrant_client.get_collection(collection_name=self.qdrant_collection) print(f"✅ Connected to Qdrant at {self.qdrant_host}:{self.qdrant_port}") return True except Exception as e: retry_count += 1 print(f"❌ Qdrant connection failed (attempt {retry_count}/{max_retries}): {e}") print(f" Retrying in {wait_time} seconds...") time.sleep(wait_time) except Exception as e: print(f"❌ Error connecting to Qdrant: {e}") break if retry_count >= max_retries: print(f"❌ Failed to connect to Qdrant after {max_retries} attempts") return False def _load_model(self): """Load the sentence transformer model.""" try: self.model = SentenceTransformer(self.model_name) print(f"✅ Loaded embedding model: {self.model_name}") return True except Exception as e: print(f"❌ Error loading embedding model: {e}") return False def close(self): """Close all connections.""" if self.neo4j_driver: self.neo4j_driver.close() print("✅ Neo4j connection closed") # Qdrant client doesn't require explicit closure print("✅ All connections closed") ``` -------------------------------- ### Qdrant Basic Connection Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Connects to a Qdrant instance using the `qdrant-client` Python library. It demonstrates how to initialize the client and retrieve information about a specific collection, including the vector count. ```python from qdrant_client import QdrantClient # Connection parameters qdrant_host = "localhost" qdrant_port = 6335 # Note the non-standard port qdrant_collection = "document_chunks" # Connect to Qdrant client = QdrantClient(host=qdrant_host, port=qdrant_port) # Test connection def test_collection(): try: collection_info = client.get_collection(qdrant_collection) # Handle different API versions vectors_count = None if hasattr(collection_info, 'vectors_count'): vectors_count = collection_info.vectors_count elif hasattr(collection_info, 'points_count'): vectors_count = collection_info.points_count return vectors_count except Exception as e: print(f"Error getting collection info: {e}") return None # Print collection size vector_count = test_collection() if vector_count is not None: print(f"Connected to Qdrant collection '{qdrant_collection}' with {vector_count} vectors") ``` -------------------------------- ### Basic Batch Search Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/examples.md Performs a batch search across multiple queries using the GraphRAG library. It iterates through a list of queries, executes a search for each, and prints the query and the number of results found. ```python queries = [ "Neo4j backup strategies", "Qdrant optimization techniques", "Database security best practices" ] results = await batch_search(queries) for item in results: print(f"\nQuery: {item['query']}") print(f"Found {len(item['results'])} results") ``` -------------------------------- ### GraphRAGConnectionManager Class Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Manages connections to Neo4j and Qdrant databases, and loads embedding models. It initializes connection parameters from environment variables and provides a method to establish connections with retry logic. ```python import os import time from neo4j import GraphDatabase from neo4j.exceptions import ServiceUnavailable, AuthError from qdrant_client import QdrantClient from qdrant_client.http.exceptions import UnexpectedResponse # Suppress Qdrant version warnings warnings.filterwarnings("ignore", category=UserWarning, module="qdrant_client") class GraphRAGConnectionManager: """Manager for connections to Neo4j and Qdrant databases.""" def __init__(self): # Neo4j connection parameters self.neo4j_uri = os.getenv("NEO4J_URI", "bolt://localhost:7688") self.neo4j_user = os.getenv("NEO4J_USER", "neo4j") self.neo4j_password = os.getenv("NEO4J_PASSWORD", "password") self.neo4j_driver = None # Qdrant connection parameters self.qdrant_host = os.getenv("QDRANT_HOST", "localhost") self.qdrant_port = int(os.getenv("QDRANT_PORT", "6335")) self.qdrant_collection = os.getenv("QDRANT_COLLECTION", "document_chunks") self.qdrant_client = None # Embedding model self.model_name = "all-MiniLM-L6-v2" self.model = None def connect(self, max_retries=3): """Connect to both databases and load the embedding model.""" success = True # Connect to Neo4j if not self._connect_neo4j(max_retries): success = False # Connect to Qdrant if not self._connect_qdrant(max_retries): success = False # Load embedding model if not self._load_model(): success = False return success def _connect_neo4j(self, max_retries=3): """Connect to Neo4j with retry logic.""" retry_count = 0 while retry_count < max_retries: try: self.neo4j_driver = GraphDatabase.driver( self.neo4j_uri, auth=(self.neo4j_user, self.neo4j_password) ) # Verify connection with self.neo4j_driver.session() as session: result = session.run("MATCH (d:Document) RETURN count(d) AS count") record = result.single() print(f"✅ Connected to Neo4j with {record['count']} documents") return True except ServiceUnavailable as e: retry_count += 1 wait_time = 2 ** retry_count # Exponential backoff print(f"❌ Neo4j connection failed (attempt {retry_count}/{max_retries}): {e}") print(f" Retrying in {wait_time} seconds...") time.sleep(wait_time) except AuthError as e: print(f"❌ Neo4j authentication failed: {e}") print(" Please check username and password.") break except Exception as e: print(f"❌ Unexpected error connecting to Neo4j: {e}") break if retry_count >= max_retries: print(f"❌ Failed to connect to Neo4j after {max_retries} attempts") return False def _connect_qdrant(self, max_retries=3): """Connect to Qdrant with retry logic.""" retry_count = 0 while retry_count < max_retries: try: self.qdrant_client = QdrantClient( host=self.qdrant_host, port=self.qdrant_port ) # Verify connection collection_info = self.qdrant_client.get_collection(self.qdrant_collection) # Try to get vector count using different API versions vectors_count = None # Try approach for newer versions if hasattr(collection_info, 'vectors_count'): vectors_count = collection_info.vectors_count # Try approach for other versions elif hasattr(collection_info, 'points_count'): vectors_count = collection_info.points_count # Try to navigate the potentially nested structure else: try: if hasattr(collection_info.config, 'params'): if hasattr(collection_info.config.params, 'vectors'): vectors_count = collection_info.config.params.vectors.size except: pass if vectors_count is not None: print(f"✅ Connected to Qdrant collection '{self.qdrant_collection}' with {vectors_count} vectors") else: print(f"✅ Connected to Qdrant collection '{self.qdrant_collection}', but couldn't determine vector count") return True except ConnectionError as e: retry_count += 1 wait_time = 2 ** retry_count # Exponential backoff print(f"❌ Qdrant connection failed (attempt {retry_count}/{max_retries}): {e}") print(f" Retrying in {wait_time} seconds...") time.sleep(wait_time) except UnexpectedResponse as e: print(f"❌ Qdrant connection failed due to unexpected response: {e}") print(" Please check Qdrant host and port.") break except Exception as e: print(f"❌ Unexpected error connecting to Qdrant: {e}") break if retry_count >= max_retries: print(f"❌ Failed to connect to Qdrant after {max_retries} attempts") return False def _load_model(self): """Load the embedding model.""" try: from sentence_transformers import SentenceTransformer self.model = SentenceTransformer(self.model_name) print(f"✅ Loaded embedding model: {self.model_name}") return True except Exception as e: print(f"❌ Failed to load embedding model '{self.model_name}': {e}") return False ``` -------------------------------- ### Neo4j Basic Connection Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Establishes a basic connection to the Neo4j database using the `neo4j` Python driver. It demonstrates how to create a driver instance with URI and authentication, and how to run a simple query to count nodes. ```python from neo4j import GraphDatabase # Connection parameters neo4j_uri = "bolt://localhost:7688" # Note the non-standard port neo4j_user = "neo4j" neo4j_password = "password" # Establish connection driver = GraphDatabase.driver(neo4j_uri, auth=(neo4j_user, neo4j_password)) # Test connection def test_connection(): with driver.session() as session: result = session.run("MATCH (n) RETURN count(n) AS node_count") return result.single()["node_count"] # Print node count print(f"Connected to Neo4j database with {test_connection()} nodes") # Close connection when done driver.close() ``` -------------------------------- ### DocumentationGPTTool Initialization and Connection Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/index.md Initializes the DocumentationGPTTool, establishing connections to Neo4j and Qdrant, and loading the sentence transformer model. Handles environment variables for connection details and includes error handling for each connection. ```python import os from typing import Dict, List, Optional, Any, Union from neo4j import GraphDatabase from qdrant_client import QdrantClient from sentence_transformers import SentenceTransformer class DocumentationGPTTool: """MCP Tool for querying the GraphRAG documentation system.""" def __init__(self): # Neo4j connection self.neo4j_uri = os.getenv("NEO4J_URI", "bolt://localhost:7687") self.neo4j_user = os.getenv("NEO4J_USER", "neo4j") self.neo4j_password = os.getenv("NEO4J_PASSWORD", "password") self.neo4j_driver = None # Qdrant connection self.qdrant_host = os.getenv("QDRANT_HOST", "localhost") self.qdrant_port = int(os.getenv("QDRANT_PORT", "6333")) self.qdrant_collection = os.getenv("QDRANT_COLLECTION", "document_chunks") self.qdrant_client = None # Embedding model self.model_name = "all-MiniLM-L6-v2" self.model = None # Initialize connections self._connect() def _connect(self): """Establish connections to Neo4j and Qdrant.""" # Connect to Neo4j try: self.neo4j_driver = GraphDatabase.driver( self.neo4j_uri, auth=(self.neo4j_user, self.neo4j_password) ) # Test connection with self.neo4j_driver.session() as session: result = session.run("MATCH (d:Document) RETURN count(d) AS count") record = result.single() print(f"Connected to Neo4j with {record['count']} documents") except Exception as e: print(f"Neo4j connection error: {e}") # Connect to Qdrant try: # Handle potential version compatibility issues try: self.qdrant_client = QdrantClient(host=self.qdrant_host, port=self.qdrant_port) collection_info = self.qdrant_client.get_collection(self.qdrant_collection) # Check for vectors count based on client version vectors_count = 0 if hasattr(collection_info, 'vectors_count'): vectors_count = collection_info.vectors_count elif hasattr(collection_info, 'points_count'): vectors_count = collection_info.points_count else: # Try to navigate the config structure based on observed variations try: if hasattr(collection_info.config, 'params'): if hasattr(collection_info.config.params, 'vectors'): vectors_count = collection_info.config.params.vectors.size except: pass print(f"Connected to Qdrant collection '{self.qdrant_collection}' with {vectors_count} vectors") except Exception as e: print(f"Qdrant connection warning: {e}") # Fallback for older versions if needed except Exception as e: print(f"Qdrant connection error: {e}") # Load the embedding model try: self.model = SentenceTransformer(self.model_name) print(f"Loaded embedding model: {self.model_name}") except Exception as e: print(f"Error loading embedding model: {e}") ``` -------------------------------- ### GraphRAG Core Components Initialization Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/src/index.md Demonstrates how to load configuration and initialize the Neo4jHelper, QdrantHelper, and QueryEngine for the GraphRAG hybrid system. This involves importing necessary classes and setting up the core components for data retrieval and processing. ```python from src.config import load_config from src.utils.neo4j_utils import Neo4jHelper from src.utils.qdrant_utils import QdrantHelper from src.utils.query_utils import QueryEngine from src.processors.markdown_processor import MarkdownProcessor # Example usage config = load_config() neo4j = Neo4jHelper(config) qdrant = QdrantHelper(config) query_engine = QueryEngine(neo4j, qdrant) ``` -------------------------------- ### Setting up a Python Virtual Environment Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/README.md Instructions for creating and activating a Python virtual environment to manage project dependencies. ```bash python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate ``` -------------------------------- ### Safely Get Node Properties from Neo4j Results Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/error_handling.md This Python function `safe_get_property` retrieves a property from a Neo4j node dictionary, returning a default value if the property is missing or an error occurs. ```python from typing import Dict, Any def safe_get_property(node: Dict, prop: str, default: Any = None) -> Any: """Safely get node property with default value.""" try: return node.get(prop, default) except Exception: return default ``` -------------------------------- ### Key Files to Examine Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/AI_ENTRY.md Highlights essential files within the project for understanding configuration, query logic, import processes, and testing. ```APIDOC Key Files to Examine: 1. Configuration: src/config.py - Contains system configuration. 2. Query Engine: src/query_engine.py - Core query logic. 3. Import Script: scripts/import_docs.py - Document import process. 4. Testing: test_db_connection/test_connections.py - Database connection verification. ``` -------------------------------- ### Custom Ranking of Search Results Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/examples.md Demonstrates how to implement custom ranking logic for search results. This example defines a `CustomRankedSearch` class that allows adjusting scores based on similarity, related documents, and preferred categories. It then applies these custom weights to refine the search results. ```python from graphrag import GraphRAGTool from typing import List, Dict, Any class CustomRankedSearch: def __init__(self): self.tool = GraphRAGTool() def rank_results(self, results: List[Dict[Any, Any]], weights: Dict[str, float]) -> List[Dict[Any, Any]]: """Custom ranking function.""" for result in results: # Calculate weighted score score = result['score'] * weights.get('similarity', 1.0) # Adjust score based on related documents related_count = len(result['related_docs']) score += related_count * weights.get('relations', 0.1) # Adjust score based on category if result['category'] == weights.get('preferred_category'): score *= weights.get('category_boost', 1.2) result['adjusted_score'] = score # Sort by adjusted score return sorted(results, key=lambda x: x['adjusted_score'], reverse=True) async def search(self, query: str, weights: Dict[str, float]): try: # Execute basic search response = await self.tool.execute(query=query, limit=10) if response['status'] == 'success': # Apply custom ranking ranked_results = self.rank_results( response['results'], weights ) return { 'status': 'success', 'results': ranked_results[:5] # Return top 5 } return response finally: self.tool.cleanup() # Usage example weights = { 'similarity': 1.0, # Base similarity score weight 'relations': 0.1, # Weight for related documents 'category_boost': 1.2, # Boost for preferred category 'preferred_category': 'setup' } searcher = CustomRankedSearch() results = await searcher.search( "Database configuration", weights ) ``` -------------------------------- ### Sentence-Transformers Documentation Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/index.md Documentation for the Sentence-Transformers library, which provides pre-trained models for generating sentence embeddings. ```APIDOC Sentence-Transformers Documentation: URL: https://www.sbert.net/ ``` -------------------------------- ### Query Demonstration Script Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/AI_ENTRY.md This Python script demonstrates how to perform queries within the project. It may showcase querying data, interacting with APIs, or running specific analytical tasks. ```python def run_query_demo(): # Placeholder for query demonstration logic print("Running query demo...") if __name__ == '__main__': run_query_demo() ``` -------------------------------- ### Setup Qdrant Collection Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/scripts/index.md Creates the required collection in the Qdrant vector database. This script is essential for storing and retrieving document embeddings. ```python python scripts/setup_qdrant_collection.py ``` -------------------------------- ### Query System Demo Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/scripts/index.md Launches an interactive demonstration of how to query the hybrid GraphRAG database. This script allows users to test the system's querying capabilities. ```bash python scripts/query_demo.py ``` -------------------------------- ### Connect to Qdrant with Version Compatibility Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Establishes a connection to a Qdrant instance, handling potential version differences in API methods. It includes error handling, retries with exponential backoff, and attempts to retrieve vector counts using different attribute names based on Qdrant client versions. ```python import warnings from qdrant_client import QdrantClient import time # Suppress version compatibility warnings warnings.filterwarnings("ignore", category=UserWarning, module="qdrant_client") def connect_to_qdrant(host, port, collection_name, max_retries=3): """Connect to Qdrant with error handling and version compatibility.""" retry_count = 0 while retry_count < max_retries: try: # Connect to Qdrant client = QdrantClient(host=host, port=port) # Verify connection by checking collection collection_info = client.get_collection(collection_name) # Try to get vector count using different API versions vectors_count = None # Try approach for newer versions if hasattr(collection_info, 'vectors_count'): vectors_count = collection_info.vectors_count # Try approach for other versions elif hasattr(collection_info, 'points_count'): vectors_count = collection_info.points_count # Try to navigate the potentially nested structure else: try: if hasattr(collection_info.config, 'params'): if hasattr(collection_info.config.params, 'vectors'): vectors_count = collection_info.config.params.vectors.size except: pass if vectors_count is not None: print(f"✅ Connected to Qdrant collection '{collection_name}' with {vectors_count} vectors") else: print(f"✅ Connected to Qdrant collection '{collection_name}', but couldn't determine vector count") return client except ConnectionError as e: retry_count += 1 wait_time = 2 ** retry_count # Exponential backoff print(f"❌ Qdrant connection failed (attempt {retry_count}/{max_retries}): {e}") print(f" Retrying in {wait_time} seconds...") time.sleep(wait_time) except Exception as e: print(f"❌ Error connecting to Qdrant: {e}") break if retry_count >= max_retries: print(f"❌ Failed to connect to Qdrant after {max_retries} attempts") return None ``` -------------------------------- ### Loading Environment Variables in Python Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/connection.md Illustrates how to use the `dotenv` library to load environment variables from a `.env` file and access them using `os.getenv`. ```python import os from dotenv import load_dotenv # Load environment variables from .env file load_dotenv() # Get connection parameters neo4j_uri = os.getenv("NEO4J_URI") neo4j_user = os.getenv("NEO4J_USER") neo4j_password = os.getenv("NEO4J_PASSWORD") qdrant_host = os.getenv("QDRANT_HOST") qdrant_port = int(os.getenv("QDRANT_PORT")) qdrant_collection = os.getenv("QDRANT_COLLECTION") ``` -------------------------------- ### GraphRAG Integration with MCP Server Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/examples.md Shows how to integrate GraphRAG functionality into an MCP Server environment by creating a custom tool. This `GraphRAGMCPTool` class inherits from `BaseTool` and exposes GraphRAG's search capabilities, including parameter extraction and response formatting suitable for MCP. ```python from mcp.tools import BaseTool from graphrag import GraphRAGTool class GraphRAGMCPTool(BaseTool): name = "GraphRAG" description = "Search through documentation using GraphRAG" def __init__(self): super().__init__() self.tool = GraphRAGTool() async def execute(self, query: str, **kwargs): try: # Extract parameters limit = kwargs.get('limit', 5) category = kwargs.get('category') # Execute search results = await self.tool.execute( query=query, limit=limit, category=category ) # Format response for MCP if results['status'] == 'success': return { 'success': True, 'data': { 'results': results['results'], 'count': results['count'] } } else: return { 'success': False, 'error': results.get('error', 'Unknown error') } except Exception as e: return { 'success': False, 'error': str(e) } finally: self.tool.cleanup() def cleanup(self): """Clean up resources when the tool is unloaded.""" if hasattr(self, 'tool'): self.tool.cleanup() ``` -------------------------------- ### Handle Neo4j Authentication Failures Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/error_handling.md This Python code shows how to handle `AuthError` when verifying connectivity with the Neo4j driver, indicating invalid credentials. ```python from neo4j.exceptions import AuthError try: driver = GraphDatabase.driver(uri, auth=(user, password)) driver.verify_connectivity() except AuthError: print("Invalid Neo4j credentials") ``` -------------------------------- ### Handle Neo4j Connection Refused and Authentication Errors Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/error_handling.md This Python snippet demonstrates how to catch `ServiceUnavailable` exceptions from the Neo4j driver, distinguishing between connection refused and authentication failures. ```python from neo4j.exceptions import ServiceUnavailable try: with driver.session() as session: result = session.run("MATCH (n) RETURN count(n)") except ServiceUnavailable as e: if "Connection refused" in str(e): print("Neo4j is not running or wrong port") elif "unauthorized" in str(e).lower(): print("Invalid credentials") else: print(f"Neo4j connection error: {str(e)}") ``` -------------------------------- ### Neo4j and Qdrant Connection Parameters Source: https://github.com/rileylemm/graphrag-hybrid/blob/main/guides/mcp/index.md Environment variables for configuring connections to Neo4j and Qdrant databases. These variables specify the URIs, user credentials, host, port, and collection names required for the MCP server to interact with the databases. ```bash # Neo4j Configuration NEO4J_URI=bolt://localhost:7687 NEO4J_USER=neo4j NEO4J_PASSWORD=password # Qdrant Configuration QDRANT_HOST=localhost QDRANT_PORT=6333 QDRANT_COLLECTION=document_chunks ```