How to Query a Microsoft GraphRAG Knowledge Graph with Neo4j: Local and Global Modes

This guide explains how to query a Microsoft GraphRAG knowledge graph using the official CLI, API, and a custom Neo4j implementation, covering both local and global retrieval modes, vector index creation, Cypher query customization, and integration with LangChain for end‑to‑end RAG pipelines.

AI Large Model Application Practice
AI Large Model Application Practice
AI Large Model Application Practice
How to Query a Microsoft GraphRAG Knowledge Graph with Neo4j: Local and Global Modes

Overview

This article continues a tutorial that indexed a ~20,000‑word Marvel‑world text with Microsoft GraphRAG, stored the results as Parquet files, and imported them into a Neo4j graph database. It demonstrates how to query the knowledge graph using the official GraphRAG tools and a custom LangChain implementation.

Official Query Tools

Microsoft GraphRAG provides two primary ways to query a built knowledge graph:

Command‑line interface (CLI) : After configuring environment variables or a config file, run python -m graphrag.query with parameters such as --method (local or global), --community_level, --response_type, etc. Example commands are provided for both modes.

API usage : The repository’s examples_notebooks folder contains a local/global_search.ipynb notebook that shows how to call the GraphRAG API programmatically.

Query Principles

Local Mode

Local queries combine structured graph information with unstructured document chunks to build a context for an LLM. The workflow is:

Identify the most relevant entities (nodes labeled __Entity__) using embedding similarity.

Extract related data: original text chunks, community reports, entity descriptions, relationship descriptions, and (optionally) covariates.

Rank and filter the extracted information to form the final context.

Pass the context and the original question to an LLM with a prompt template to generate the answer.

Global Mode

Global queries follow a Map‑Reduce architecture:

Map : For the specified community_level, retrieve all community reports, generate intermediate responses (RIR) with importance scores.

Reduce : Sort the intermediate responses, select the most important viewpoints, assemble them as context, and feed them to the LLM for the final answer.

The quality of the global response depends on the chosen community level; lower levels give more detailed reports but increase latency and cost.

Custom GraphRAG Query in Neo4j (LangChain)

The following steps show how to implement a custom local query on top of the Neo4j graph using LangChain.

1. Create a Vector Index

Entity nodes have a description_embedding property. Create a cosine‑similarity vector index with Cypher:

CREATE VECTOR INDEX entity_index IF NOT EXISTS FOR (e:__Entity__) ON e.description_embedding
OPTIONS {indexConfig: {`vector.dimensions`: 1536, `vector.similarity_function`: 'cosine'}}

2. Test the Index

Use Neo4jVector.from_existing_index together with Azure OpenAI embeddings to verify the index. Replace the placeholder values with your own Azure credentials.

import os
os.environ["AZURE_OPENAI_API_KEY"] = "YOUR_AZURE_OPENAI_API_KEY"
os.environ["AZURE_OPENAI_ENDPOINT"] = "YOUR_AZURE_OPENAI_ENDPOINT"

text_embedder = AzureOpenAIEmbeddings(
    azure_deployment="text-embedding-3-small",
    openai_api_version="2024-05-01-preview",
)

llm = AzureChatOpenAI(
    deployment_name="gpt-4o-mini",
    openai_api_version="2024-05-01-preview",
)

entity_vector = Neo4jVector.from_existing_index(
    text_embedder,
    url=NEO4J_URI,
    username=NEO4J_USERNAME,
    password=NEO4J_PASSWORD,
    index_name="entity_index",
    text_node_property="description",
)

result = entity_vector.similarity_search("复仇者联盟", top_k=5)
print(result[0].page_content)

3. Define a Retrieval Query

The retrieval_query parameter allows you to append a custom Cypher fragment to the default vector retrieval. The fragment collects related chunks, community summaries, outside/inside relationships, and entity descriptions, then returns them as text, score, and metadata fields required by LangChain.

lc_retrieval_query = """
    WITH collect(node) as nodes
    // Top text chunks
    collect {
        UNWIND nodes as n
        MATCH (n)<-[:HAS_ENTITY]-(c:__Chunk__)
        WITH c, count(distinct n) as freq
        RETURN c.text AS chunkText
        ORDER BY freq DESC
        LIMIT $topChunks
    } AS text_mapping,
    // Top community reports
    collect {
        UNWIND nodes as n
        MATCH (n)-[:IN_COMMUNITY]->(c:__Community__)
        WITH c, c.rank as rank, c.weight as weight
        RETURN c.summary
        ORDER BY rank, weight DESC
        LIMIT $topCommunities
    } AS report_mapping,
    // Outside relationships
    collect {
        UNWIND nodes as n
        MATCH (n)-[r:RELATED]-(m)
        WHERE NOT m IN nodes
        RETURN r.description AS descriptionText
        ORDER BY r.rank, r.weight DESC
        LIMIT $topOutsideRels
    } AS outsideRels,
    // Inside relationships
    collect {
        UNWIND nodes as n
        MATCH (n)-[r:RELATED]-(m)
        WHERE m IN nodes
        RETURN r.description AS descriptionText
        ORDER BY r.rank, r.weight DESC
        LIMIT $topInsideRels
    } AS insideRels,
    // Entity descriptions
    collect {
        UNWIND nodes as n
        RETURN n.description AS descriptionText
    } AS entities
    RETURN {Chunks: text_mapping, Reports: report_mapping,
            Relationships: outsideRels + insideRels,
            Entities: entities} AS text, 1.0 AS score, {source:''} AS metadata
"""

4. Build the Retrieval Chain

Create a Neo4jVector retriever with the custom query and plug it into a LangChain RetrievalQAWithSourcesChain:

lc_vector = Neo4jVector.from_existing_index(
    text_embedder,
    url=NEO4J_URI,
    username=NEO4J_USERNAME,
    password=NEO4J_PASSWORD,
    index_name="entity_index",
    retrieval_query=lc_retrieval_query,
)

chain = RetrievalQAWithSourcesChain.from_chain_type(
    llm,
    chain_type="stuff",
    retriever=lc_vector.as_retriever(search_kwargs={
        "topChunks": topChunks,
        "topCommunities": topCommunities,
        "topOutsideRels": topOutsideRels,
        "topInsideRels": topInsideRels,
    })
)

response = chain.invoke({"question": "复仇者联盟与钢铁侠有什么关系?"}, return_only_outputs=True)
print(response['answer'])

The chain returns an answer that combines relevant entity information, community reports, and relationships, demonstrating a functional custom local GraphRAG query.

Extending to Global Mode

The same retrieval pipeline can be adapted for global queries by implementing the Map‑Reduce steps in custom prompt templates and using the same Neo4jVector retriever. Users can explore the Microsoft GraphRAG source code for further customization of community‑level handling and prompt engineering.

pythonLangChainRAGvector searchNeo4jMicrosoft GraphRAG
AI Large Model Application Practice
Written by

AI Large Model Application Practice

Focused on deep research and development of large-model applications. Authors of "RAG Application Development and Optimization Based on Large Models" and "MCP Principles Unveiled and Development Guide". Primarily B2B, with B2C as a supplement.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.