# GraphRAG: Varför vektorsökningen bryts ner på Corpus-nivån

<datetime class="hidden">2025-12-26T12:00</datetime>

<!-- category -- ASP.NET, Semantic Search, ONNX, Qdrant, Machine Learning, Vector Search, RAG -->
Din RAG-system är jättebra på "kollkoll" frågorM SK2 plocka upp några relevanta grejer och syntetisera ett svar . Det kämpar med två vanliga query-typer

- **Sensorik**: " Vilka är de viktigaste ämnena i detta korpus
- **Verbindande**: " Hur relaterar X till Y i olika dokument

De är inte svarade av någon enda chunk. De kräver **omständighet + klustering + anslutning**.

**Varför misslyckas vektorsökningen här:**

- Det sätter upp stycken **självständigt** genom likhet till frågan
- Samlikhet optimerar relevans **övergripande**
- Embedding fångar " vad som låter liknande ", inte

Du kan bruta detta med uppmanande och eftermanande, men du slutar med att bygga upp en graf i form av en lösning.

**Den viktigaste insikten** GraphRAG ändrar sökningens enhet. För korpusfrågorna vill du inte ' vill inte "topM SK3K liknande chunks **sammankopplade konceptuella samhällen** ( och deras sammanfattningar ), så att modellen ser strukturen

[GraphRAG](https://microsoft.github.io/graphrag/) kommer från Microsoft Research [papper](https://arxiv.org/pdf/2404.16130) och är tillgänglig som [open- implementering av källkod](https://github.com/microsoft/graphrag). Den håller vektorsökningen på specifika frågor , men lägger till en kunskapsgraf och samhällsförteckningar för corpus

**GraphRAG Series Navigation:**

- **Del 1: GraphRAG Fundamentals** (den här artikeln )
- [Del 2: Minimalt funktionella grafRAG (Optionellt per ♫ - ♫ Chuck LLM sändningar ♫ МSK3 ♫](/blog/graphrag-minimum-viable-implementation)

## När inte använda GraphRAG

Innan du dyker in i ",", ska du "'" vara tydlig om när det är överdrift.

- **Små dokument** (under  ~50 dokument
- **Bara " hur gör jag?**: GraphRAG vann
- **Enkel innehåll** ( inga varelsersorter ): ingen grafstruktur att utnyttja
- **Kosten- begränsad**: indexering kräver många LLM-sändningar

Om dina användare bara ställer specifika frågor [vetenskapliga sökningar](/blog/semantic-search-with-onnx-and-qdrant). GraphRAG lyser när användaren behöver *den stora bilden*, och att "'" är en mindre publik än försäljare föreslår

# Inleiding

**Navigationsserien:** Det här är en del 6 av RAG-serien

- [Del 1: källor och grunder](/blog/rag-primer) - Historien , motivation
- [Del 2: Arkitektur och inre](/blog/rag-architecture) - Teknikligt djupdykning
- [Del 3: RAG i praktiken](/blog/rag-practical-applications) - Att bygga riktiga system
- [Del 4a: ONNX & Garantiimplementering](/blog/semantic-search-with-onnx-and-qdrant) - CPU-vänlig semantisk sök
- [Del 4b: Semantisk sökande i aktivitet](/blog/semantic-search-in-action) - Typanledningen , hybridsökningen , och gränssnittet
- [Del 5: Hybridsökning & Auto-Indexering](/blog/rag-hybrid-search-and-indexing) - produktionsintegration
- **Del 6: GraphRAG** (den här artikeln) - kunskapsgrafer för corpus

I den här serien har vi- -byggt allt mer sofistikerade RAG-system. **liknande chunks**, inte **sammankopplade koncept**. För *corpus-nivå* frågor (medlet som omger många dokument) du behöver strukturenM SK2

**Den rekommenderade vägen:** Om du redan har en Qdrant-baserad lokalsökning som fungerar ( som vi gör ), prototyp med Pythons sidecar för att validera värdet , behålla vektorer för lokalsökningen M SK4 och lägga till en lättviktig graf för globalt

[TOC]

# Problemet med Pure Vector RAG

Låt mig visa er vad jag menar med ett konkret exempel

## Vad Vector RAG gör bra

**Fråga:** " Hur använder jag HTMX med Alpine?

**Vektor RAG-process:**

1. Embetera frågan: `[0.234, -0.891, 0.567, ...]`
2. Hitta liknande bitar i Qdrant
3. Tillbaka till toppen-K matchar om HTMX och AlpineM SK1js
4. LLM syntetiserar svar från dessa chunks

Detta fungerar eftersom frågan och den relevanta innehållet **semantiskt lik**. Embeddingerna fångar den likheten

```csharp
// 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
```

## Var Vektor RAG kämpar

**Fråga:** " Vilka är de viktigaste teknikerna jag skriver om och hur de relaterar till varandra

**Vad vektor RAG betyder:**

```
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..."
```

Den nämner Docker, ,, PostgreSQL, ,, HTMX, MSks2, ONNX, MSKS3 men den inte gruppar dem eller förklarar hur de är sammankopplade.

Problemet: Den här frågan kräver **aggregation och förståelse för relationer** över hela korpusen.

- Identifisera alla tekniker som nämns
- Förstå vilka som används tillsammans
- Aggregera dem i konsekventa tema.

Sammalikhet på egen hand ger dig inte detta. Om du försöker patcha det med en prompt, så kommer du till slut att uppfinna en graf

# Ge in GraphRAG

[GraphRAG](https://microsoft.github.io/graphrag/) är Microsoft Researchs lösning på detta problem. [GraphRAG-papier](https://arxiv.org/pdf/2404.16130) identifierade de två söktyperna som basnivån RAG hanterar dåligt (**känsla** och **sammanlänkande**) och byggde ett system för att adressera dem

Istället för att bara lägga in stycken, bygger GraphRAG **kunskapsgraf** som fångar enheter och deras relationer.

## Hur GraphRAG fungerar

**Pipeline på en titt:**

- **Indeksering:** Chunks → entityderM SK1relationer → graf | | 3 | samhällen | 4 | sammanfattningar
- **Fråga:** Lokala = chunks + grafmässigt grannskap | | Globala | = | samhälleliga sammanfattningar |

GraphRAG lägger till flera komponenter i RAG-tunneln

1. **Utvinning** (subjekter  + relationer
2. **Graphbyggande** (kunskapsgraflagning
3. **sammanfattning** (samhälletsdetektion  + hierarki

```mermaid
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
```

### steg 1: Enhetens extraktion

En LLM läser varje stycke och extraherar **varelser** (things being discussed):

```
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)
```

### steg 2: Relationship Extraction

Samma LLM identifierar hur enheten relaterar till varandra

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

### steg 3: kunskapsgrafkonstruktion

Alla enheter och relationer formar en graf:

```mermaid
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
```

### steg 4: Samhällets detektion (Leiden-algoritm | )

Den [Leidens algoritm](https://arxiv.org/pdf/1810.08473.pdf) kluster tätt anslutna noder till samhällen. Detta spelar roll eftersom det ger dig *stabila* kluster för att sammanfatta och hämta fram

- **Samhällen 1**:  "Frontend Stack
- **Samhällen 2**: "Kontainerinfrastrukturen" | | ( | Docker | , | Komponera |, | PostgreSQL | , | Qdrant | SMk7 |
- **Samhällen 3**: " RAG Pipeline, " ♫ ♫ ( ♫ ONNX, M SK4 ♫ Möbler, , ♫ Qdrant, Mska6 ♫ RAG, M Ska7 ♫

Titta på hur Qdrant ser ut i två samhällen.

### steg 5: Samtalförteckningar

En LLM genererar sammanfattningar för varje grupp på varje hierarkisk nivå:

```
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."
```

## Frågamodi

GraphRAG erbjuder tre sökmodi , var och en optimerad för olika frågatyper:

### Globala sökningar

**bäst för:** " Vilka är de viktigaste ämnena ?" "Störa samman de viktigaste frågorna

Användar samhällsförteckningar ( inte enskilda chunks ) för att svara på meningsfulla frågor

```
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"
```

### Lokala sökningar

**bäst för:** " Hur konfigurerar jag XM SK1 " Vad är Y?"

Kombinerar enhet-fokuserad graf traversal med traditionella vektorsökningar:

```
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
```

### DRIFT-sökning

**bäst för:** " Hur relaterar X till Y?

DRIFT-sökning (Dynamikmässigt resonemang och inferans med flexibla förflyttningar), [som beskrivs i GraphRAG-dokumenten](https://microsoft.github.io/graphrag/query/drift_search/), kombinerar lokala sökningar med samhälleliga kontexter . Det' använder fortfarande LLM resonemang över uppfunnit strukturerade kontexter | | ( | inte magiska grafförklaringar | ), | men strukturen hjälper LLM att se kopplingar som den skulle missa med platta grejer |

```
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."
```

# Vergleich av GraphRAG med vårt nuvarande system

Låt oss kartlägga GraphRAG-koncepterna till vad vi redan har i `Mostlylucid.SemanticSearch`:

| Komponent | | | Stromsystem | МSK2 | GraphRAG-ekvivalent |
|-----------|---------------|---------------------|
| **Embeddings** | ONNX all-MiniLMMST3LMst4vM st5 mst6 Samma MMST7or OpenAIMstr8 | |
| **Vektorbutik** | Qdrant | Q drant ♫ ♫ / ♫ LanceDB ♫
| **Enhetens extraktion** | Ingen | LLM-motorisk extraktion |
| **Vetskapsgraf** | Inget | Graphdatabas ♫ ♫ / ♫ i ♫
| **Samhällens upptäckt** | Ingen | Leidens algoritm |
| **Fråga : Spesifikt** | `SemanticSearchService.SearchAsync()` | Lokala sök |
| **Fråga: Global** | Inte stödd | Globala sökningar |

Vår nuvarande implementering hanterar **Lokala sökningar** well. GraphRAG skulle lägga till **Globala sökningar** och **DRIFT-sökning** förmågor.

```csharp
// 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);
}
```

# Implementeringsmetoder

Det finns tre sätt att lägga till GraphRAG i ett redan system.

## Option 1: Python Sidecar | ( | Rekomenderat för utforskande

Runna Microsoft's GraphRAG som en separat tjänst

```yaml
# 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
```

```csharp
// 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:** Använd Microsofts strid, -, prövade implementering och ,, snabbt till prototyp
**Cons:** Pythons beroende, LLM-kostnaden för indexering

## Option 2: .NET Native (Production Path)

Att bygga de viktigaste komponenterna i C#. BERT-baserade extraktioner och Ollamamönster från [DocSummarizer](/blog/docsummarizer-tool) jobba likadant här.

### Enhetens extraktion

Fråga en LLM att identifiera *saker* (enheter

```csharp
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);
}
```

**Produktionsbehov:** LLM JSON utgång *kommer att* bråka. Det här är inte optionellt uthärdning . Du behöver en av

- **Schema- begränsad generation** (OllamaM SK1s `format: json`, OpenAI
- **Försök reparera loopar med** ( upptäcka missformerad JSON , be LLM att fixa det
- **Fallback extraktion** (regex-mönster för vanliga enhetens typer

LLM är sannolikhetsmässiga; ditt extraktionskedjor måste inte vara

### Att extrahera relationer

När du har enheten, fråga LLM hur de kopplar ihop.

```csharp
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));
}
```

### Graphlagning med normalisering av enheten

Den största praktiska smärtan är **varelse aliasering**: "ASPM SK2NET Core", | | " | ASP | МSK5 | Net |", | och | " | aspnetcore |

```csharp
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();
}
```

För att använda det seriöst, tänk på embedding. -, deduplikering av enheten baserat på :. Om två enhetens namn har liknande inbäddar, ,, så är de förmodligen samma sak.

**Producerande smärtpunkter** (GraphRAG

- **Synonymen/alias tabeller**: underhåller kanoniska namn och kända aliaser
- **Att kontrollera relationens schema**: begränsning tillät förutsägelser för att förhindra hallucinationer av relationer
- **Förtroende poäng + pruning**: inte alla extraherade relationer är lika tillförlitliga
- **Tillväxten av re-indexering**: när dokument är uppdaterade , behöver du patcha grafen

### Graphförskakning

Att hitta besläktade enheter är ett breadth

```csharp
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();
}
```

### Samhällens upptäckt

Det här är en ansluten komponent baseline **inte** full Leiden. Leiden optimerar för modularitet | ( | täta inre anslutningar |, | sparse yttre anslutande

```csharp
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;
}
```

### Summarisation av samhällsgruppen

Varje gemenskap får en sammanfattning som beskriver sitt tema. Det här är vad som driver Global Search

```csharp
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: Hybrid (Pragmatisk mellangrund

Detta är den tillämpna metoden om du redan har en fungerande vektorsökning. Håll Qdrant för den lokala sökningen

### Frågaklassificering

Först detektera vilken typ av fråga det här är

```csharp
// 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;
}
```

### Lokala sökningar (Erhöjt)

Använd den existerande vektorsökningen, optionellt förstärkt med grafkontext

```csharp
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));
}
```

### Globala sökningar (Nyskapacitet)

Kaart-växlas över samhällsförteckningar ( ingen vektorsökning behövs ):

```csharp
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)));
}
```

### DRIFT-sökning (Connective queries)

Kombinera lokala resultat med samhälleliga sammanhang för " hur relaterar X till Y

```csharp
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.");
}
```

# Kosten och prestationsmässiga aspekter

GraphRAG har stora kompromisser jämfört med rent vektor RAG.

## Kosten för indexering

Beståndsdeln/kollektivt extraktionskostnader varierar signifikant mellan modellerna , tänkbart design, , och skalan, . som en grov uppsättning **ett eller två LLM-sändningar per stycke** plus ett mindre antal samtal för sammanfattningar i samhället.

| Operation | Vektor RAG | | | GraphRAG ♫ | ♫
|-----------|------------|----------|
| **Inbäddar** | 1 ringning/ krång | Samma |
| **Enhet/Relationsextraktion** | Inget | ♫ ♫ 1-2 ♫ LLM-sändningar ♫
| **Summarisation av samhällsgruppen** | Inget | ♫ ♫ 1 ♫ LLM-sändning ♫

För en korpus av 1,000 bloggposter med ♫ 5 stycken var och en ♫(5,000 stycket totalt ♫ МSK3 stycke vektor | - | enbart indexering är i grunden bara att lägga in kostnaderna | . | GraphRAG lägger till tusentals LLM-intryck för extraktion och sammanfattning |. | Den exakta kostnaden beror mycket på vilken modell du väljer och hur effektiv den är ♫

## Försökskostnader

| Frågatyp | Vektor RAG | GraphRAG Lokalt M| GraffRAG Globalt | |
|------------|------------|----------------|-----------------|
| **Vektorsökning** | 1 samtalet ♫ ♫ | ♫
| **Graph traversal** | 0 ♫ ♫ | ♫
| **LLM ringer** |  1

Globala sökningar är dyrare per query, men de besvarar frågor som Lokala sökningen helt enkelt kan'tM SK2 Du kan också kaska globala svar och uppdatera dem bara när korpusen ändras .

## GraphRAG-felmodi

GraphRAG är "'", t magi , ".", och uppmärksamma ":".

- **Tillförsel fel**: LLM missar varelser eller hallucinationer
- **Enhetens aliasering**: "ASPM SK2NET Core" vs "AspMska5NETMske6 vs "aspnetcoreMsek8 blir separata noder
- **Graphdrift**: När docs uppdateras , kan grafen bli dödlig
- **Samhällens sammanfattningar håller på att försvinna**: sammanfattningar donM SK1 inte automatiserad - uppdatera när enheter förändras

Enhetens normalisering är den största praktiska smärtan.

- Canoniska namn + aliaser
- Fall-vikt och punkteringsnormalisering
- Embedding optionellt på basis av enhetens duplicering

# Att integrera med vår bloggsökning

Här är hur GraphRAG kunde förbättra bloggen

## Den nuvarande strömmen

```
User types in search → SemanticSearchService → Qdrant → Results
```

## Förstärkt flöde

Klassifieren skickar ut query till olika sökstrategier. **globala sökningar** strömmar - lägg märke till att den aldrig rör vid vektorskivan

```mermaid
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..."
```

Jämför detta med **lokalt sök**, som kombinerar vektorsökningar med grafkontext för rikare svar

```mermaid
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..."
```

Den viktigaste skillnaden är att globala sökningar aggregerar samhällsförteckningar (corpus-nivåthemaerM SK3 medan lokala sökningar hämtar specifika chunks som är rika med entitetsrelationer

> **En enklare alternativ:** GraphRAG är fortfarande väldigt mycket ett forskningsverktyg - väsenextraktion, , grafkonstruktion, ,, och samhälleliga upptäckter ger större komplexitet och LLM-kostnader, **BERT embeddings + BM25 Keyword matching** fungerar bättre. Det här är vad [Sourcegraph's Cody](https://sourcegraph.com/blog/how-cody-understands-your-codebase) används för kodintelligens [DocSummarizer](/blog/docsummarizer-part3) användar för dokumentuppfattningar. Pattern : hybridt sök handleder relevans ; LLM-handlarna *sammansättning*, inte *beslutsfattning*. Du får 80% av vinsten med МSK2 av komplexiteten

## Implementeringsskift

APIn är enkel.

```csharp
[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
    };
}
```

Vektorsökning och grafsökning kompletterar varandra.

# Slutsatsen

GraphRAG utökar RAG från " hitta liknande chunks " till ♫ " förstå kunskapsstrukturen ♫

**Vad GraphRAG lägger till:**

- Entitet och relation extraktion
- Vetskapsgrafers konstruktion
- Samhällens upptäckt och hierarkiska sammanfattningar
- Globala sökningar efter sinnbildande frågor
- DRIFT sök efter konektivt resonemang

**När man ska använda den:**

- Du har en omfattande dokumentsamling
- Användare frågar " vilka som är tematen " typ frågor
- Din innehåll har tydliga enheter och relationer
- Du vill koppla upp ytan automatiskt

**Implementeringsväg:**

1. Först ̈, ̈ fråga ̈ : ̈ behöver du den här i själva verket?
2. Om ja, prototyp med Python sidecar för att validera värdet
3. Build .NET native if costs/latency matter
4. Använd lokala LLMs (Ollama) för att kontrollera indexeringskostnader

## resurser

**GraphRAG Officiell:**

- [GraphRAG Dokumentation](https://microsoft.github.io/graphrag/) - Microsofts officiella dokument
- [GraphRAG GitHub](https://github.com/microsoft/graphrag) - källkod och exempel
- [GraphRAG Papier](https://arxiv.org/pdf/2404.16130) - Den ursprungliga forskningssatsen
- [Leidens algoritm Papier](https://arxiv.org/pdf/1810.08473.pdf) - Samhällens upptäcktsalgoritm

**RAG-serien:**

- [Del 1: RAG ursprung och grundlagen](/blog/rag-primer)
- [Del 2: RAG arkitektur och inre](/blog/rag-architecture)
- [Del 3: RAG i praktiken](/blog/rag-practical-applications)
- [Del 4: Semantisk sökning med ONNX och Qdrant](/blog/semantic-search-with-onnx-and-qdrant)
- [Del 5: Hybridsökning & Auto-Indexering](/blog/rag-hybrid-search-and-indexing)

**Enklare alternativ (BERT + BMM SK2**

- [DocSummarizer Part 3](/blog/docsummarizer-part3) - Hybridt extraherande utan graföverskott
- [Sourcegraph Cody arkitektur](https://sourcegraph.com/blog/how-cody-understands-your-codebase) - Producerande hybrid sök