Back to "GraphRAG: Pourquoi la recherche par vecteur se détériore au niveau du corpus"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET Machine Learning ONNX Qdrant RAG Semantic Search Vector Search

GraphRAG: Pourquoi la recherche par vecteur se détériore au niveau du corpus

Friday, 26 December 2025

Votre système RAG est excellent à "needle" questions : récupérer quelques morceaux pertinents et synthétiser une réponseM SK3 Il se heurte à deux types de demandes courantesMSC4

  • Sensibilisation: "Qu'est-ce que les principaux thèmes de ce corpus?
  • Connexion: "Comment X se rapporte-t-il à Y dans les différents documents?

Ces questions ne sont pas résolues par un seul bloc de réponses. Couplage + regroupement + liaison.

Pourquoi la recherche par vecteur ne fonctionne pas ici:

  • Il classe les morceaux de façon indépendante par analogie à la demande
  • La similitude optimise la pertinence, non couverture mondiale
  • Embeddings capture "qu'est-ce qui est semblable à ce qu'on entendM SK1non "quelles sont reliées à ce que l'on comprend"

Vous pouvez brute-forcer cela avec l’invitation et le post-procédure, mais vous finirez par reconstruire une solution en forme de graphe.

Le point de vue clé: GraphRAG modifie l'unité de recherche. Pour les questions sur le corpus que vous ne voulez pas'dont vous ne souhaitez pas "topM SK3K fragments similairesMSC4 que vous voulez Communautés conceptuelles reliées ( et leurs résumésM SK1 de sorte que le modèle voit la structure, non les fragments .

GraphRAG provient de Microsoft Research's Documentation et est disponible en tant que mise en œuvre de source open-. Il maintient la recherche vectorielle pour des questions spécifiques , mais il ajoute un graphique de connaissance et des résumés communautaires pour le corpus

Navigation de la série GraphRAG:

Quand ne pas utiliser GraphRAG

Avant de plonger dans l’eau, laissez-moi savoir quand c’est une surpêche.

  • Les petits ensembles de documents (aux termes de ~50 documents): utiliser simplement la recherche par vecteur
  • Seules les questions "comment puis-je répondre à la question ?: GraphRAG a remporté
  • Contenu uniforme (aucune variété d'entitésM SK1pas de structure graphique à exploiter
  • Coût-contrôlé: l'indexation nécessite de nombreuses appels LLM

Si vos utilisateurs ne posent que des questions précises, rester avec recherche sémantique. GraphRAG brille lorsque les utilisateurs ont besoin du le grand tableau, et que ' est un auditoire plus restreint que les fournisseurs le suggèrent

Introduction

Navigation de série: Il s'agit d'une partie 6 de la série RAGM SK1

Tout au long de cette série, nous avons construit des systèmes RAG de plus en plus sophistiqués. fractions similaires, non concepts connexes. Pour corpus-niveau Questions (themes couvrant de nombreux documents) vous avez besoin d’une structureM SK2

Le chemin recommandé: Si vous avez déjà Qdrant-basé sur la recherche locale qui fonctionne M SK1comme nous le faisons ), prototype avec Python sidecar pour valider les valeurs, conserver des vecteurs de recherche localeMNK4 et ajouter un graphique léger pour la recherche mondialeMMK5questions d'DRIFTMZK6 Allez seulement MNK7 GraphRAG completMKK8 une fois que vos utilisateurs prouvés ont posé ces questionsMGK9

Le problème avec le RAG Pure Vector

Permettez-moi de vous montrer ce que je veux dire par un exemple concret.

Ce que fait bien le Vektor RAG

Question: "Comment puis-je utiliser l'HTMX avec Alpine?

Processus RAG vecteur:

  1. Insérer la question: [0.234, -0.891, 0.567, ...]
  2. Trouver des morceaux similaires dans Qdrant
  3. Retour en haut-K matches sur HTMX et AlpineM SK1js
  4. LLM synthétise la réponse de ces tronçons

Cela fonctionne parce que la question et le contenu pertinent sont caractéristiques sémantiques similaires. Les embeddings captent cette similitudeM SK1

// This is what our current SemanticSearchService does
var embedding = await _embeddingService.GetEmbeddingAsync(query);
var results = await _qdrantService.SearchAsync(
    collectionName: "blog_posts",
    queryVector: embedding,
    limit: 10
);
// Returns chunks about HTMX, Alpine.js, frontend patterns

Où le Vektor RAG se bat

Question: " Quelles sont les principales technologies dont je parle et comment elles se rapportent-elles?

Quel vecteur RAG retourne:

Result 1: "HTMX makes it easy to add AJAX to your pages..."
Result 2: "Docker Compose orchestrates multiple containers..."
Result 3: "PostgreSQL's full-text search is surprisingly capable..."
Result 4: "Alpine.js provides reactive state management..."

Il mentionne le Docker, PostgreSQL, HTMXM SK2 ONNX ... mais ne les regroupe pas ou n’explique pas comment ils se connectentMSC5 Vous obtiendrez des fragmentsMST6 non une vue d’ensembleMSS7

Le problème: Cette question exige agrégation et compréhension des relations sur l’ensemble du corps. Vous devez

  • Identifier toutes les technologies mentionnées
  • Comprendre ce qui est utilisé ensemble
  • Groupez-les en thèmes cohérents

La similitude des vecteurs seuls ne vous donne pas ce qui suit :

Inscrire GraphRAG

GraphRAG est la solution à ce problème de Microsoft Research' Papier GraphRAG a identifié les deux types de demandes que le RAG de base gère mal (sensationnel et d’une part, le fait de ne pas se conformer à la législation communautaire et, d’autre part) et a construit un système spécifique pour les traiter

Au lieu de simplement intégrer des tronçons, GraphRAG construit un Graphique du savoir qui saisit les entités et leurs relations, puis les regroupe en communautés avec des résumés.

Comment fonctionne GraphRAG

Pipeline à un coup d’œil:

  • Indexage: Unités → entitésM SK1relations → graphe → communautés S→ résumés
  • Question: Locale = tronçons + quartier du graphique SSK2 Sommaires communautaires mondiaux = sommaires de la collectivité S| DRIFT

GraphRAG ajoute plusieurs composants au pipeline RAG, groupés en trois catégoriesM SK1

  1. Extraction (entités + relations
  2. Établissement de graphiques (entreposage des graphes de connaissancesM SK1
  3. Résumé (détection communautaire + hiérarchie
flowchart TB
    subgraph "Traditional RAG (What We Have)"
        A[Documents] --> B[Chunks]
        B --> C[Embeddings]
        C --> D[Vector Store]
    end

    subgraph "GraphRAG Additions"
        B --> E[Entity Extraction]
        E --> F[Relationship Extraction]
        F --> G[Knowledge Graph]
        G --> H[Community Detection]
        H --> I[Community Summaries]
    end

    subgraph "Query Time"
        J[User Query] --> K{Query Type?}
        K -->|Specific| L[Local Search]
        K -->|Global| M[Global Search]
        K -->|Hybrid| N[DRIFT Search]

        D --> L
        G --> L
        I --> M
        G --> N
        I --> N
    end

    style E stroke:#f9f,stroke-width:2px
    style H stroke:#bbf,stroke-width:2px
    style I stroke:#9f9,stroke-width:2px

Étape 1: Extraction des entités

Un LLM lit chaque tronçon et extrait les entités (les choses dont il est question):

Chunk: "Docker Compose makes it easy to define multi-container applications.
        I use it with PostgreSQL for my blog's database layer."

Extracted Entities:
- Docker Compose (technology)
- PostgreSQL (database)
- blog (project)
- database layer (concept)

Étape 2: Extraction des relations

Le même LLM identifie la relation entre les entités:

Relationships:
- Docker Compose --[used_with]--> PostgreSQL
- blog --[has_component]--> database layer
- PostgreSQL --[implements]--> database layer

Étape 3: Construction du Graphique des connaissances

Toutes les entités et relations forment un graphique:

graph LR
    subgraph "Frontend Cluster"
        HTMX[HTMX]
        Alpine[Alpine.js]
        Tailwind[Tailwind CSS]
    end

    subgraph "Infrastructure Cluster"
        Docker[Docker]
        Compose[Docker Compose]
        Postgres[PostgreSQL]
        Qdrant[Qdrant]
    end

    subgraph "AI/ML Cluster"
        ONNX[ONNX Runtime]
        Embeddings[Embeddings]
        RAG[RAG]
    end

    HTMX -->|used_with| Alpine
    HTMX -->|styled_by| Tailwind
    Alpine -->|styled_by| Tailwind

    Docker -->|orchestrated_by| Compose
    Compose -->|runs| Postgres
    Compose -->|runs| Qdrant

    ONNX -->|generates| Embeddings
    Embeddings -->|stored_in| Qdrant
    RAG -->|uses| Embeddings
    RAG -->|uses| Qdrant

    style HTMX stroke:#f9f
    style Docker stroke:#bbf
    style RAG stroke:#9f9

Étape 4: Détection communautaire ( Algorithme lié de l'algorithme

L'article 5 de la Loi sur l'immigration et le statut des réfugiés Algorithme de Leiden les nodes étroitement reliés dans des collectivités. Cela est important parce qu’il vous donne Établissement stable Les communautés deviennent vos unités de recherche pour les demandes mondiales.

  • Communauté 1: "Frontend Stack"
  • Communauté 2: "Container Infrastructure" | | (DockerMSC4 ComposeM SK5 PostgreSQLMST6 QdrantMSL7
  • Communauté 3: " Pipeline RAG" ≥(ONNXM SK4 EmbeddingsMska5 QdrantM Ska6 RAG~Mska7

Notez comment Qdrant apparaît dans deux communautés :

Étape 5: Résumés communautaires

Un LLM produit des résumés pour chaque communauté à chaque niveau hiérarchique:

Community 1 Summary (Frontend Stack):
"The frontend approach combines HTMX for server-driven interactivity
with Alpine.js for client-side state management, styled using Tailwind CSS.
This stack prioritizes HTML-first development with minimal JavaScript,
focusing on progressive enhancement over SPA complexity."

Community 2 Summary (Container Infrastructure):
"The blog runs on Docker Compose, orchestrating PostgreSQL for persistent
storage, Qdrant for vector search, and the ASP.NET Core application.
This containerized architecture enables consistent local development
and production deployment."

Modes de demande

GraphRAG offre trois modes de demande, chacun optimisé pour différents types de questions:

Recherche mondiale

Le meilleur pour: "Qu'est-ce que les principaux thèmes?

Utilise les sommaires communautaires (pas des chunks individuelsM SK1 pour répondre aux questions de sensibilisation :

Query: "What technologies does this blog cover most?"

Process:
1. Retrieve all community summaries
2. Map: Ask LLM to extract technology themes from each summary
3. Reduce: Combine partial answers into final response

Response:
"The writing centres on three technology clusters:
1. **Frontend Development** - HTMX, Alpine.js, Tailwind CSS for minimal-JS web UIs
2. **AI/ML Infrastructure** - RAG pipelines, ONNX embeddings, vector search with Qdrant
3. **DevOps/Containerization** - Docker, PostgreSQL, ASP.NET Core deployment"

Recherche locale

Le meilleur pour: "Comment configurer XM SK1 "Qu'est-ce que Y?"

Combine l’entité-la traverse graphique axée sur la recherche vectorielle traditionnelle:

Query: "How do I use Qdrant with ONNX embeddings?"

Process:
1. Identify entities in query: Qdrant, ONNX, embeddings
2. Retrieve graph neighborhood around those entities
3. Also retrieve vector-similar chunks
4. Combine into rich context for LLM

Response includes:
- Direct relationships (ONNX generates embeddings stored in Qdrant)
- Related entities (all-MiniLM-L6-v2 model, cosine similarity)
- Specific code examples from vector-retrieved chunks

Recherche DRIFT

Le meilleur pour: "Comment X se rapporte-t-il à Y?

Recherche DRIFT (Dynamic Reasoning and Inference with Flexible Traversal), tel que décrit dans les documents GraphRAG, combine la recherche locale avec le contexte communautaire . Il' continue d’utiliser le raisonnement de LLM au-dessus du contexte structuré récupéré.

Query: "How do the frontend and backend technologies connect?"

Process:
1. Start with entities: HTMX, ASP.NET Core
2. Traverse graph to find connection paths
3. Include community summaries for context
4. Generate answer showing the full picture

Response:
"HTMX makes requests to ASP.NET Core endpoints, which query PostgreSQL
and Qdrant. The connection flows through the API layer, where endpoints
return HTML fragments that HTMX swaps into the DOM. Alpine.js handles
client-side state for interactive components like search typeahead."

Comparaison de GraphRAG à notre système actuel

Let's map GraphRAG concepts to what we already have in Mostlylucid.SemanticSearch:

Composante Système courant Équivalence de GraphRAG M
Embeddings ONNX (tousM SK2MiniLM-LMST4vMSC5 Le même MSC7ou OpenAIMSC8
Entrepôt de vecteurs Qdrant
Extraction d'entités Aucune
Graphique du savoir Aucune
Détection communautaire Algorithme de Leiden
Demande: spécifique SemanticSearchService.SearchAsync() Recherche locale
Demande: Global Non supporté Recherche mondiale

Notre gestion de la mise en œuvre actuelle Recherche locale bien. GraphRAG ajouterait Recherche mondiale et Recherche DRIFT capacités.

// What we have today (Local Search equivalent)
public async Task<List<SearchResult>> SearchAsync(string query, int limit = 10)
{
    var embedding = await _embeddingService.GetEmbeddingAsync(query);
    return await _qdrantService.SearchAsync("blog_posts", embedding, limit);
}

// What GraphRAG would add
public async Task<string> GlobalSearchAsync(string query)
{
    // 1. Retrieve community summaries (not chunks)
    var summaries = await _graphService.GetCommunitySummariesAsync();

    // 2. Map: Extract relevant themes from each summary
    var partialAnswers = await Task.WhenAll(
        summaries.Select(s => _llm.ExtractThemesAsync(query, s))
    );

    // 3. Reduce: Combine into final answer
    return await _llm.SynthesizeAsync(query, partialAnswers);
}

Approches de mise en œuvre

Il y a trois façons d’ajouter GraphRAG à un système existant.

Option 1: Python Sidecar (Recommandé pour l'exploration)

Faire fonctionner Microsoft's GraphRAG en tant que service distinct

# docker-compose.graphrag.yml
services:
  graphrag:
    build:
      context: ./graphrag
    volumes:
      - ./data/input:/app/input
      - ./data/output:/app/output
    environment:
      - OPENAI_API_KEY=${OPENAI_API_KEY}

  graphrag-api:
    build:
      context: ./graphrag-api
    ports:
      - "8001:8000"
    depends_on:
      - graphrag
// GraphRagClient.cs - Call from ASP.NET Core
public class GraphRagClient
{
    private readonly HttpClient _http;

    public GraphRagClient(HttpClient http)
    {
        _http = http;
        _http.BaseAddress = new Uri("http://graphrag-api:8000");
    }

    public async Task<string> GlobalSearchAsync(string query)
    {
        var response = await _http.PostAsJsonAsync("/query/global", new { query });
        var result = await response.Content.ReadFromJsonAsync<GraphRagResponse>();
        return result.Answer;
    }

    public async Task<string> LocalSearchAsync(string query)
    {
        var response = await _http.PostAsJsonAsync("/query/local", new { query });
        var result = await response.Content.ReadFromJsonAsync<GraphRagResponse>();
        return result.Answer;
    }
}

Pros: Utilisez Microsoft'la bataille de -la mise en oeuvre expérimentée, rapidement au prototype Cons: dépendance de Python, Coûts liés à l'indexation par LLM, communication croisée

Option 2: .NET Native (Path de production)

Élaborer les composants clés de C#. L’extraction fondée sur le BERTM SK1 et les modèles Ollama provenant des DocSummarizer Travailler de la même façon ici.

Extraction d'entités

Demander à un LLM d'identifier les choses (entitésM SK1 dans chaque tronçon - entités structurées plutôt que libres

public async Task<List<Entity>> ExtractEntitiesAsync(string chunk)
{
    var prompt = $"""
        Extract entities from this text. Return JSON array.
        Types: technology, concept, project, person, organization
        Text: {chunk}
        Format: [{{"name": "Docker", "type": "technology"}}]
        """;

    var response = await _ollama.GenerateAsync(prompt);
    return JsonSerializer.Deserialize<List<Entity>>(response);
}

Exigences de production: LLM JSON sortie de l’intention interruption. Il ne s'agit pas d'un affaiblissement facultatif. Vous avez besoin d'une de ces

  • Schema-génération restreinte (OllamaM SK1s format: json, OpenAI's fonction d'appel de )
  • Essayer de réparer les boucles-avec- (détecter un JSON malformé, demander à LLM de le corrigerM SK2
  • Extraction en arrière-plan (patterns regex pour les types d'entités communesM SK1

Les LLM sont probabilistes; votre pipeline d'extraction ne doit pas être.

Extraction des relations

Une fois que vous avez des entités, demandez au LLM comment elles se connectent:

public async Task<List<Relationship>> ExtractRelationshipsAsync(
    string chunk, List<Entity> entities)
{
    var names = string.Join(", ", entities.Select(e => e.Name));
    var prompt = $"""
        Given entities: {names}
        Extract relationships. Return JSON array.
        Text: {chunk}
        Format: [{{"source": "Docker", "target": "PostgreSQL", "rel": "runs"}}]
        """;

    return JsonSerializer.Deserialize<List<Relationship>>(
        await _ollama.GenerateAsync(prompt));
}

Entreposage de graphiques avec normalisation d'entités

La plus grande douleur pratique est Alisage de l'entité: "ASPM SK2NET Core",

public class KnowledgeGraph
{
    private readonly Dictionary<string, Entity> _entities = new();
    private readonly List<Relationship> _relationships = new();

    public void AddEntity(Entity entity)
    {
        var key = Normalise(entity.Name);  // "ASP.NET Core" → "aspnetcore"
        _entities[key] = entity;
    }

    private string Normalise(string name) =>
        name.ToLowerInvariant().Replace(".", "").Replace("-", "").Trim();
}

Pour une utilisation sérieuse, considérer l’incorporation - la déduplication d’entités fondée sur les entités M SK2 si deux noms d’entité ont des embeddings semblables , ils MSC4 sont probablement la même chose

Points de souffrance de production (GraphRAGM SK1la valeur dépend de la qualité du graphe):

  • Synonyme/tableaux d'alias: conserver les noms canoniques et les alias connus
  • Contrôle du schéma de relations: constraint permet aux prédicteurs d'empêcher les types de relations hallucinatoires
  • Évaluation de la confiance + coupe: pas toutes les relations extraites sont tout aussi fiables
  • Incremental re-indexing: lorsque les documents sont mis à jour, vous devez patcher le graphe , ne pas le reconstruire

Traversement du graphique

Trouver des entités apparentées est une largeur

public List<Entity> GetNeighbors(string entityName, int depth = 1)
{
    var result = new HashSet<Entity>();
    var queue = new Queue<(string Name, int Depth)>();
    queue.Enqueue((Normalise(entityName), 0));

    while (queue.Count > 0)
    {
        var (name, d) = queue.Dequeue();
        if (d >= depth) continue;

        // Find all entities connected to this one
        var neighbours = _relationships
            .Where(r => Normalise(r.Source) == name || Normalise(r.Target) == name)
            .SelectMany(r => new[] { r.Source, r.Target });

        foreach (var neighbour in neighbours)
            if (_entities.TryGetValue(Normalise(neighbour), out var entity))
                if (result.Add(entity))
                    queue.Enqueue((Normalise(neighbour), d + 1));
    }
    return result.ToList();
}

Détection communautaire

Il s'agit d'une ligne de base connectée-components, non pas Leiden complet. Leiden optimise pour la modularité (connexions internes densesM SK2connes externes épargnes ). Pour une mise en œuvre appropriéeMSC4 utiliser une bibliothèque de graphes ou portuer l’algorithmeMNK5

public List<Community> DetectCommunities(KnowledgeGraph graph)
{
    // Connected components: group everything reachable together
    var visited = new HashSet<string>();
    var communities = new List<Community>();

    foreach (var entity in graph.GetAllEntities())
    {
        if (visited.Contains(entity.Name)) continue;
        
        // BFS to find all connected entities
        var community = new Community();
        var queue = new Queue<string>();
        queue.Enqueue(entity.Name);

        while (queue.Count > 0)
        {
            var name = queue.Dequeue();
            if (!visited.Add(name)) continue;
            community.Entities.Add(graph.GetEntity(name));
            foreach (var neighbor in graph.GetNeighbors(name, depth: 1))
                queue.Enqueue(neighbor.Name);
        }
        communities.Add(community);
    }
    return communities;
}

Résumé communautaire

Chaque collectivité reçoit un résumé décrivant son thème.

public async Task<string> SummarizeCommunityAsync(Community community)
{
    var entities = string.Join("\n", 
        community.Entities.Select(e => $"- {e.Name}: {e.Description}"));
    
    var prompt = $"""
        Summarize what unites these concepts (2-3 sentences):
        {entities}
        """;

    return await _ollama.GenerateAsync(prompt);
}

Option 3: Hybride (Pragmatic Middle GroundM SK2

C'est l'approche recommandée si vous avez déjà une recherche vectorielle en cours de travail. Gardez Qdrant pour la recherche locale, Ajouter une couche graphique léger pour Global

Classification de la demande

Premièrement, détecter quel type de question il s’agit:

// WARNING: Toy heuristic for illustration only.
// In production, use a classifier prompt or few-shot rules and log misroutes.
private QueryMode ClassifyQuery(string query)
{
    var q = query.ToLowerInvariant();
    
    if (q.Contains("main theme") || q.Contains("summarize") || q.Contains("what topics"))
        return QueryMode.Global;
    
    if (q.Contains("relate") || q.Contains("connect") || q.Contains("compare"))
        return QueryMode.Drift;
    
    return QueryMode.Local;
}

Recherche locale (Enhanced)

Utiliser la recherche vectorielle existante, optionnellement enrichie avec le contexte graphique:

private async Task<string> LocalSearchAsync(string query)
{
    // Existing semantic search (what we have today)
    var chunks = await _semanticSearch.SearchAsync(query, limit: 10);

    // NEW: Enrich with related entities from graph
    var entities = await _graphService.ExtractEntitiesFromQueryAsync(query);
    var related = await _graphService.GetEntityContextAsync(entities);

    return await _llm.GenerateAsync(query, FormatContext(chunks, related));
}

Recherche mondiale (Nouvelle capacité)

Carte-diminution par rapport aux résumés communautaires M SK1pas de recherche vectorale requise):

private async Task<string> GlobalSearchAsync(string query)
{
    var summaries = await _graphService.GetAllCommunitySummariesAsync();

    // Map: Extract relevant info from each community
    var partials = await Task.WhenAll(
        summaries.Select(s => _llm.ExtractRelevantInfoAsync(query, s)));

    // Reduce: Combine into final answer
    return await _llm.SynthesizeAsync(query, partials.Where(p => !string.IsNullOrEmpty(p)));
}

Recherche DRIFT (Questions liées à la connectivité)

Combiner les résultats locaux avec le contexte communautaire pour "comment X se rapporte-t-il à Y?

private async Task<string> DriftSearchAsync(string query)
{
    var localResults = await LocalSearchAsync(query);
    
    var entities = await _graphService.ExtractEntitiesFromQueryAsync(query);
    var communities = await _graphService.GetCommunitiesForEntitiesAsync(entities);
    var themes = string.Join("\n", communities.Select(c => c.Summary));

    return await _llm.GenerateAsync(
        $"Question: {query}\n\nDetails:\n{localResults}\n\nBroader themes:\n{themes}",
        systemPrompt: "Synthesize the details with the thematic context.");
}

Considérations relatives aux coûts et au rendement

GraphRAG présente des retombées importantes par rapport à RAG de vecteur pur.

Coûts d'indexation

Entité/coûts d’extraction de la relation varient considérablement selon le modèleM SK1conception rapide , et taille du tronçon.En ordre approximatif un ou deux appels LLM par chunk plus un nombre moindre d’appels pour les résumés communautaires.

Opération RAG vectoriel GraphRAG S
Intégration 1 appel/chunk MSC3 Même MSC4
Entité/Extraction des relations Aucune
Résumé communautaire Aucune

Pour un corpus de 1,000 articles sur le blog avec 5 tronçons chacune |(5,000 tronchons totaux | ), vecteur | L'indexation seulement est essentiellement simplement l'incorporation des coûts | SMC5 | GraphRAG ajoute des milliers d'appels LLM pour extraction et sommisation |SMC6 | Le coût exact dépend fortement du choix de votre modèle et de l'efficacité rapide | MSMC7 | Utilisant les modèles locaux |MSMC8 | Ollama avec llama | SMMC9 | ou similaire | SSMC10 | élimine entièrement les coûts API | FSMC11 | qui est la méthode recommandée pour l'expérimentation |SMMC12

Coûts de la demande

Type de la demande RAG vecteur GraphRAG local GrafRAG global S
Recherche par vecteur 1 appels 1 appels
Traversement graphique Questions 0 2 3 4 5
Les appels LLM 1 ≥ ≤1-2 N carte

La recherche mondiale est plus coûteuse par demande, mais elle répond aux questions que la Recherche locale peut simplement répondre'tM SK2 Vous pouvez aussi cacher les réponses globales et les actualiser seulement lorsque le corpus changeMSC3

Modes de défaillance GraphRAG

GraphRAG n’est pas't magique. Veuillez vous assurerM SK2

  • Les erreurs d'extraction: Les LLM manquent d’entités ou hallucinaient des relations
  • Alisage des entités: "ASPM SK2NET Core" vs.
  • Déplacement des graphiques: Lorsque les dossiers sont mis à jour,, le graphique peut devenir bloqué
  • Les résumés communautaires ne sont plus valables: Sommaires donM SK1t auto-update quand les entités changent

La normalisation de l’entité est la plus grande douleur pratique.

  • Noms canoniques + aliases
  • Case-normalisation des plis et de la ponctuation
  • Insertion optionnelle de la déduplication d'entités fondée sur le modèle -

Intégration avec notre recherche sur le blog

Voici comment GraphRAG pourrait améliorer le blog, la recherche sémantique existante de ' et :

Flux actuel

User types in search → SemanticSearchService → Qdrant → Results

Flux amélioré

Le classeur permet d’acheminer les demandes vers différentes stratégies de recherche. Demande globale flows - note qu’il ne touche jamais le store vecteurM SK1

sequenceDiagram
    participant U as User
    participant API as Search API
    participant C as Query Classifier
    participant G as Global Search
    participant KG as Knowledge Graph

    U->>API: "What topics does this blog cover?"
    API->>C: Classify query
    C-->>API: QueryMode.Global

    API->>G: GlobalSearch(query)
    G->>KG: GetCommunitySummaries()
    KG-->>G: [Frontend, Infrastructure, AI/ML]
    G->>G: MapReduce over summaries
    G-->>API: Synthesized answer

    API-->>U: "The blog covers three main areas..."

Comparez ce qui suit : Demande locale, qui combine la recherche par vecteur avec le contexte graphique pour obtenir des réponses plus riches

sequenceDiagram
    participant U as User
    participant API as Search API
    participant C as Query Classifier
    participant L as Local Search
    participant Q as Qdrant
    participant KG as Knowledge Graph

    U->>API: "How do I use HTMX?"
    API->>C: Classify query
    C-->>API: QueryMode.Local

    API->>L: LocalSearch(query)
    L->>Q: Vector search
    Q-->>L: Relevant chunks
    L->>KG: GetEntityContext("HTMX")
    KG-->>L: Related: Alpine.js, Tailwind, ASP.NET
    L-->>API: Answer with rich context

    API-->>U: "HTMX is used with Alpine.js for..."

La différence clé: les demandes globales regroupent les sommaires communautaires (corpus-thèmes de niveauM SK3 alors que les recherches locales reçoivent des chunks spécifiques enrichis par des relations d’entitésMSC4

Une solution plus simple: GraphRAG est encore très largement un outil de recherche - extraction d'entités, construction de graphiquesM SK2 et détection communautaire ajoutent une complexité significative et des coûts liés à la LLM Emplacements BERT + BMM SK1 matchage de mots clés Il fonctionne mieux. C'est ce que Sourcegraphe's Cody utilisations pour l’intelligence de code, et ce qui DocSummarizer utilisations pour la récapitulation des documents. Le modèle: les handles de recherche hybride relevance ; les handlers LLM assembly, non Décision. Vous obtiendrez 80% de l’avantage avec 20% de la complexité

Ébauche de la mise en œuvre

L'API est simple: classer la demande, route vers le gestionnaire appropriéM SK2

[HttpGet("api/search")]
public async Task<IActionResult> Search([FromQuery] string q, [FromQuery] string mode = "auto")
{
    if (mode == "auto")
        mode = ClassifyQuery(q);

    // global/local return synthesised answers; default returns raw search results
    return mode switch
    {
        "global" => Ok(await _graphRag.GlobalSearchAsync(q)),  // synthesised answer
        "local" => Ok(await SearchWithGraphContext(q)),        // answer with citations
        _ => Ok(await _semanticSearch.SearchAsync(q))          // raw ranked results
    };
}

La recherche par vecteur et la recherche par graphe se complètent mutuellement. Utilisez les vecteurs pour " comment faire IM SK2 questions , les graphiques pour " quels sont les thèmesMSC5 questions

Conclusion

GraphRAG étend RAG de "recherche des tronçons similaires" à "comprendre la structure du savoirM SK3 Il n’est pas un remplacement pour la recherche par vecteurMSC5 il est une amélioration qui permet d’établir de nouveaux types de demandes

Ce que GraphRAG ajoute:

  • Extraction d'entités et de relations
  • Construction de graphiques des connaissances
  • Détection communautaire et résumés hiérarchiques
  • Recherche mondiale pour les questions de sens
  • DRIFT Recherche de raisonnements connexes

Quand l'utiliser:

  • Vous avez une collection de documents considérable
  • Les utilisateurs se demandent : "Qu'est-ce que les thèmes?
  • Votre contenu comporte des entités et des relations claires
  • Vous voulez que les connexions de surface se fassent automatiquement

Voie de mise en œuvre:

  1. Premièrement, demanderM SK1 vous avez-vous réellement besoin de ce type d’appareil? ? BERT + BMMSC4 le renseignement hybride gère la plupart des cas utilisés
  2. Si oui, prototype avec Python sidecar pour valider la valeur
  3. Élaborer .NET native si les coûts sont élevés/affaire de la disponibilité
  4. Utiliser des LLM locaux (Ollama) pour contrôler les coûts d'indexation

Ressources

GraphRAG Official:

Série RAG:

Solutions de rechange simples (BERT + BMM SK2

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.