Back to "अंश 2: न्यूनतम व्यवहार्य GraphRAG"

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 DuckDB GraphRAG Knowledge Graphs Machine Learning Vector Search

अंश 2: न्यूनतम व्यवहार्य GraphRAG

Saturday, 27 December 2025

में भाग 1, हम GraphRAG का महत्व क्यों खोजा है न्यूनतम व्यवहार्य GraphRAG तीन निष्कर्षण मोडों के साथ

मोड एलएलएम कॉल्स के लिए सबसे अच्छा
शल्यचिकित्सा डिफ़ॉल्ट
हाइब्रिड प्रति दस्तावेज 1 1 2 गति और गुणवत्ता का संतुलन
एलएलएम प्रति टुकड़ा 2 अधिकतम इकाई गुणवत्ता

सभी मोड का उपयोग करें:

  • डक डीबी एकल फ़ाइल में एकीकृत भंडारण के लिए (vectors
  • BM25 + BERT हाइब्रिड खोज आरआरएफ संलयन के माध्यम से
  • ओलामाCity name (optional, probably does not need a translation) संश्लेषण और वैकल्पिक बैच वर्गीकरण के लिए

श्रेणी नेविगेशन

कोड सर्वाधिक स्पष्ट.GraphRag जिटहब पर

वास्तुकला की समीक्षा

flowchart LR
    subgraph Indexing
        MD[Markdown Files] --> CH[Chunker]
        CH --> EMB[BERT Embeddings]
        CH --> EXT[Entity Extractor]
        EXT --> |heuristics + links| ENT[Entities]
        ENT --> REL[Relationships]
        REL --> COM[Communities]
    end
    
    subgraph Storage
        EMB --> DB[(DuckDB)]
        ENT --> DB
        REL --> DB
        COM --> DB
    end
    
    subgraph Query
        Q[Query] --> CLASS{Classify}
        CLASS --> |local| HS[Hybrid Search]
        CLASS --> |global| CS[Community Search]
        CLASS --> |drift| BOTH[Both + Synthesis]
        HS --> LLM[Ollama]
        CS --> LLM
        BOTH --> LLM
    end
    
    DB --> HS
    DB --> CS
    
    style MD stroke:#22c55e,stroke-width:2px
    style DB stroke:#3b82f6,stroke-width:2px
    style LLM stroke:#a855f7,stroke-width:2px

क्यों डकडीबी

माइक्रोसॉफ्ट's ग्राफ आरएग लेक्टरों के लिए अलग भंडारण का उपयोग करता है।

  • एकल .duckdb सभी के लिए फ़ाइल
  • वीएसएस एक्सटेंशन के माध्यम से स्थानीय एचएनएसवी भेक्टर खोज
  • दोनों सदिश खोज और ग्राफ ट्रास्रबल के लिए एसक्यूएल
  • शून्य विनियोजन जटिलता

डकडीबी एक ग्राफ डाटाबेस नहीं है & #44; - & #39; और यह है कि यह नहीं है Neo

भंडारण योजना

स्कीमा का उपयोग करता है provenance के लिए तालिकाओं को जोड़ें हम क्वेरी कर सकते हैं

erDiagram
    documents ||--o{ chunks : contains
    chunks ||--o{ entity_mentions : has
    chunks ||--o{ relationship_mentions : has
    entities ||--o{ entity_mentions : mentioned_in
    entities ||--o{ relationships : source
    entities ||--o{ relationships : target
    relationships ||--o{ relationship_mentions : mentioned_in
    communities ||--o{ community_members : contains
    entities ||--o{ community_members : belongs_to
    
    chunks {
        varchar id PK
        varchar document_id FK
        text text
        float[] embedding
    }
    
    entities {
        varchar id PK
        varchar name
        varchar type
        int mention_count
    }
    
    entity_mentions {
        varchar entity_id FK
        varchar chunk_id FK
    }

प्रमुख डिजाइन निर्णय नहीं VARCHAR[] मूल के लिएतालिकाओं को जोड़ेंentity_mentions, relationship_mentionsसक्षम करें कुशल क्वेरी जैसे "Docker को उल्लेखित सभी टुकड़े प्राप्त करें

भेक्टर खोज: The HNSW Gotcha

DuckDB's HNSW सूचकांक केवल के साथ ट्रिगर करता है array_cosine_distance + ORDER BY + LIMIT:

// GraphRagDb.cs - SearchChunksAsync
cmd.CommandText = $"""
    SELECT id, document_id, text, chunk_index, 
           array_cosine_distance(embedding, $1::FLOAT[{_dim}]) as distance
    FROM chunks 
    WHERE embedding IS NOT NULL
    ORDER BY distance
    LIMIT $2
    """;
// Convert distance to similarity: 1.0f - distance

उपयोग array_cosine_similarity अनुक्रमणिका का उपयोग नहीं करेगा यह HNSW सूचकांक को ट्रिगर नहीं करता है

इकाई निष्कर्षण

यह है जहाँ हम माइक्रोसॉफ्ट के दृष्टिकोण से विभेद करते हैं LLM-per-chunk निष्कर्षण पास माइक्रोसॉफ्ट के संदर्भ में प्रयोग किया गया GraphRAG पाइपलाइन आईडीएफ के आधार पर सांख्यिकी निष्कर्षणलक्ष्य यह नहीं है स्थिर,Corpus-relative सिग्नल जो एक एलएलएम को उत्पादन करने के लिए आवश्यक नहीं है

flowchart TB
    subgraph "Phase 1: Signal Collection"
        TEXT[All Chunks] --> IDF[Compute IDF Scores]
        TEXT --> STRUCT[Structural Signals]
        STRUCT --> HEAD[Headings]
        STRUCT --> CODE[Inline Code]
        STRUCT --> LINKS[Links]
        IDF --> RARE[High-IDF = Rare Terms]
        RARE --> CAND[Candidates]
        HEAD --> CAND
        CODE --> CAND
        LINKS --> |explicit rels| LINKREL[Link Relationships]
    end
    
    subgraph "Phase 2: Dedup"
        CAND --> EMBED[BERT Embeddings]
        EMBED --> SIM[Similarity > 0.85]
        SIM --> MERGE[Merge Duplicates]
    end
    
    subgraph "Phase 3: Classify"
        MERGE --> LLM{LLM Available?}
        LLM --> |yes| BATCH[Single Batch Call]
        LLM --> |no| HEUR[Heuristic Types]
    end
    
    style IDF stroke:#f59e0b,stroke-width:2px
    style BATCH stroke:#a855f7,stroke-width:2px

क्यों IDF, हार्डकोड सूची नहीं है

सहज दृष्टिकोण एक सख्त कोडित है HashSet<string> KnownTech = { "Docker", "Kubernetes", ... }के लिए यह ब्रेक करता है

  • नई प्रौद्योगिकी (you'd सूची को अद्यतन करने की जरूरत है
  • डोमेन-विनिर्दिष्ट शब्द | ( | भिन्न कोर्स |= | विभिन्न इकाइयों
  • विच्छेदन और परिवर्तन

आईडीएफ (परिवर्ती दस्तावेज़ आवृत्ति यह सांख्यिकीय रूप से हल करता है

क्रें

कहाँ

  • कुल टुकड़े
  • शब्द समाहित दस्तावेज \(t\)

उच्च IDF = दुर्लभ शब्द = संभावित रूप से एक इकाई, जो खंडों में 5 में प्रकट होती है, "\Docker"\में अधिक आईडीएफ पाई जाती है।

अधिक जानकारी के लिए TF-IDF और BM25, पर मेरी पोस्ट देखें के साथ हाइब्रिड खोज.

संरचनात्मक संकेत

मार्कडाउन संरचना हमें बताती है क्या

  • शीर्षक (## Docker Setupइकाई
  • इनलाइन कोड (`docker-compose`इकाई
  • लिंक्स ([Docker](https://docker.com))
// EntityExtractor.cs - structural signal extraction
private void ExtractStructuralEntities(string chunk, string chunkId)
{
    // Headings: ## Docker Compose Setup → "Docker Compose Setup"
    foreach (Match m in Regex.Matches(chunk, @"^#{1,3}\s+(.+)$", RegexOptions.Multiline))
    {
        var heading = m.Groups[1].Value.Trim();
        AddCandidate(heading, chunkId, weight: 2.0); // Higher weight
    }
    
    // Inline code: `docker-compose` → "docker-compose"
    foreach (Match m in Regex.Matches(chunk, @"`([^`]+)`"))
    {
        AddCandidate(m.Groups[1].Value, chunkId, weight: 1.5);
    }
}

लिंक एक्सटेक्शन (High

मार्कडाउन लिंक उपलब्ध कराते हैं स्पष्ट रिश्त जो नहीं है, ' LLM निष्कर्ष की जरूरत नहीं करता है

// EntityExtractor.cs - ExtractLinks  
foreach (Match m in Regex.Matches(chunk, @"\[([^\]]+)\]\((/blog/[^)]+)\)"))
{
    var linkText = m.Groups[1].Value;  // "semantic search"
    var slug = m.Groups[2].Value;       // "/blog/semantic-search-with-qdrant"
    yield return new Relationship(linkText, $"blog:{slug}", "references", chunkId);
}

BERT एम्बेडिंग के माध्यम से डुप्लिकेटेशन

Entity names like "Docker Compose", | " | docker | - | compose |", & #44; and \ " | DockerCompose |" | should be merged BERT सम्मिलन अर्थिक समानता पता लगाने के लिए:

// EntityExtractor.cs - DeduplicateAsync
var embeddings = await _embedder.EmbedBatchAsync(candidates.Select(c => c.Name), ct);

for (int i = 0; i < candidates.Count; i++)
{
    for (int j = i + 1; j < candidates.Count; j++)
    {
        var similarity = CosineSimilarity(embeddings[i], embeddings[j]);
        if (similarity > 0.85)
        {
            // Merge into canonical entity (keep higher mention count)
            canonical.MentionCount += duplicate.MentionCount;
            canonical.ChunkIds.UnionWith(duplicate.ChunkIds);
        }
    }
}

यह चरण O(nM SK1 सीमाबद्ध उम्मीदवार सेट के भीतर है, लेकिन उम्मीदवार गणना IDF फ़िल्टरिंग और संरचनात्मक संकेतों द्वारा सीमाबद्ध हैं। ऑनिक्स और BERT के साथ सेमेटिक खोज.

निष्कर्ष मोड

सीएलआई तीन निष्कर्ष मोडों के माध्यम से समर्थन करता है --extraction-mode:

शल्यक्रिया विधि (पूर्वनिर्धारित)

dotnet run --project Mostlylucid.GraphRag -- index ./Markdown --extraction-mode heuristic

इकाई पता लगाने के लिए IDF + संरचनात्मक संकेतों का उपयोग करता है शून्य per-chunk LLM कॉल प्रकार वर्गीकरण के लिए प्रति 50 इकाइयों को केवल ~1 कॉल करता है

हाइब्रिड मोड (सिफारिश की गई

dotnet run --project Mostlylucid.GraphRag -- index ./Markdown --extraction-mode hybrid

दोनों दुनिया में सबसे अच्छा

  1. शल्यचिकित्सा पहचानstructural signals find entity candidates (deterministic
  2. एलएलएम वृद्धि: एक कॉल प्रति दस्तावेज़ इकाइयों को सत्यापित करता है और सांकेतिक संबंध निकालता है
flowchart LR
    subgraph "Per Document"
        CHUNKS[Document Chunks] --> HEUR[Heuristic Extraction]
        HEUR --> CAND[30 Candidates]
        CAND --> LLM[Single LLM Call]
        LLM --> ENT[Validated Entities]
        LLM --> REL[Semantic Relationships]
    end
    
    style HEUR stroke:#22c55e,stroke-width:2px
    style LLM stroke:#a855f7,stroke-width:2px

5 दस्तावेज़ों के लिए, जिनका hybrid मोड हैः 5 LLM कॉल्स पूरा LLM मोड के लिए (vs 124

  • हेयूरिसिक्स से निर्धारित इकाई कवरेज
  • LLM-गुणवत्ता संबंध निष्कर्षण | ( | semantic |, | केवल सह नहीं
  • वर्णन और वैध प्रकार

एलएलएम मोड

dotnet run --project Mostlylucid.GraphRag -- index ./Markdown --extraction-mode llm

पूर्ण माइक्रोसॉफ्ट ग्राफ आर ए जी दृष्टिकोण 2 LLM कॉल्स प्रति खंड अस्तित्व निष्कर्षण + संबंध निष्कर्षण

प्रत्येक को कब प्रयोग करना है

मोड एलएलएम कॉल्स के लिए सबसे अच्छा
हाइब्रिड प्रति दस्तावेज
एलएलएम प्रति chunk 2 Unstructured prose

तकनीकी दस्तावेज़ के लिए संकर मोड. यह आपको per के बिना अर्थात्मक संबंध देता है। अध्यात्मिक शुद्ध गति के लिए, या एलएलएम वर्णनात्मक पाठ के लिए

हाइब्रिड खोज

हाइब्रिड खोज दो अनुपूरक दृष्टिकोणों को जोड़ता है

घनत्व (BERTM SK1 अर्थ को समझता है Sparse (BMM SK1 exact terms matches. M SK1HNSW" only matches "HN SWMSC4

flowchart LR
    Q[Query] --> BERT[BERT Embedding]
    Q --> BM25[BM25 Tokenize]
    
    BERT --> DENSE[Dense Search<br/>HNSW Index]
    BM25 --> SPARSE[Sparse Search<br/>TF-IDF Scoring]
    
    DENSE --> RRF[RRF Fusion]
    SPARSE --> RRF
    
    RRF --> TOP[Top K Results]
    TOP --> ENR[Enrich with<br/>Entities + Rels]
    
    style RRF stroke:#f59e0b,stroke-width:2px

क्या है BM25?

क्वेरी शब्द आवृत्ति के आधार पर दस्तावेजों को प्राप्त करता है

पाठ_^{nM SK2 \text{IDFMSC5qMSSK6i+) \cdot \frac({f)((q)

प्रमुख अंतर्ज्ञान

  • आईडीएफ शब्द: दुर्लभ शब्द अधिक महत्वपूर्ण हैं
  • TF संतृप्तिप्रकट होने वाले शब्द 10x के बजाय अधिक प्रासंगिक है
  • लंबाई सामान्यीकरण: लम्बे दस्तावेजों को नहीं मिलता

संपूर्ण BM 25 क्रियान्वयन के लिए हाइब्रिड खोज और अनुक्रमण.

पारस्परिक रैंक फ्यूजन

आरआरएफ विभिन्न पुनर्प्राप्ति प्रणालियों से रैंकिंगों को मिलाता है

पाठः(d ) sum_{r

जहां $kM SK1 (सामान्यतः 60) शीर्ष परिणाम को अधिक वजन से बचाता है दोनों रैंकिंग बढ़ाया जाता है

// SearchService.cs - RRF fusion
const int k = 60;

foreach (var (chunk, rank) in denseResults.Select((c, i) => (c, i)))
    scores[chunk.Id] = 1.0 / (k + rank + 1);

foreach (var (chunk, rank) in sparseResults.Select((c, i) => (c, i)))
{
    var rrfScore = 1.0 / (k + rank + 1);
    if (scores.TryGetValue(chunk.Id, out var existing))
        scores[chunk.Id] = existing + rrfScore;  // Boost for appearing in both!
    else
        scores[chunk.Id] = rrfScore;
}

उदाहरण: एक दस्तावेज को घनत्व में #1 और sparse में |#3 |

  • घनत्व
  • à¤a्रें
  • संयोजित (एक ही से अधिक ऊंचा

क्वेरी मोड

flowchart TB
    Q[Query] --> CLASS[Classify Query]
    
    CLASS --> |"How do I use X?"| LOCAL[Local Search]
    CLASS --> |"What are the themes?"| GLOBAL[Global Search]  
    CLASS --> |"How does X relate to Y?"| DRIFT[DRIFT Search]
    
    LOCAL --> HS[Hybrid Search] --> CTX1[Chunk + Entity Context]
    GLOBAL --> CS[Community Summaries] --> MAP[Map-Reduce]
    DRIFT --> BOTH[Local + Communities] --> SYN[Synthesize]
    
    CTX1 --> LLM[LLM Answer]
    MAP --> LLM
    SYN --> LLM
    
    style LOCAL stroke:#22c55e,stroke-width:2px
    style GLOBAL stroke:#3b82f6,stroke-width:2px
    style DRIFT stroke:#a855f7,stroke-width:2px

क्वेरी वर्गीकरण

// QueryEngine.cs
private static QueryMode ClassifyQuery(string query)
{
    var q = query.ToLowerInvariant();
    if (q.Contains("main theme") || q.Contains("summarize") || q.Contains("overview"))
        return QueryMode.Global;
    if (q.Contains("relate") || q.Contains("connect") || q.Contains("compare"))
        return QueryMode.Drift;
    return QueryMode.Local;
}

यह वर्गीकृत जानबूझकर सरल है - और एक छोटे उद्देश्य मॉडल के साथ बाद में बदलने के लिए आसान है

सीएलआई उपयोग

अनुक्रमण

# Heuristic mode (default) - fast, no per-chunk LLM
dotnet run --project Mostlylucid.GraphRag -- index ./test-markdown

# LLM mode - Microsoft-style classification
dotnet run --project Mostlylucid.GraphRag -- index ./test-markdown --extraction-mode llm
GraphRAG Indexer
  Source: test-markdown
  Database: graphrag.duckdb
  Model: llama3.2:3b
  Extraction: Heuristic (IDF + signals)

Initializing...
Indexing docker-development-deep-dive.md: 0%
Indexing docker-swarm-cluster-guide.md: 40%
Indexing dockercomposedevdeps.md: 80%
Indexing complete: 100%
Classifying entities...: 0%
Extracted 168 entities, 315 rels (4 LLM calls): 100%
Found 10 communities: 100%
Summarizing c_0_2 (12 entities): 20%
Summarizing c_0_8 (4 entities): 80%

────────────────── Indexing Complete ───────────────────
┌───────────────┬───────┐
│ Metric        │ Count │
├───────────────┼───────┤
│ Documents     │ 5     │
│ Chunks        │ 62    │
│ Entities      │ 168   │
│ Relationships │ 312   │
│ Communities   │ 10    │
└───────────────┴───────┘

क्वेरी

dotnet run --project Mostlylucid.GraphRag -- query "How do I use Docker Compose?"
──────────────────── Local Search ────────────────────

Query: How do I use Docker Compose?

╭─Answer────────────────────────────────────────────────╮
│ To run the services defined in the                    │
│ devdeps-docker-compose.yml file, you need to run the  │
│ following command in the same directory as the file:  │
│                                                       │
│ docker compose -f .\devdeps-docker-compose.yml up -d  │
│                                                       │
│ This command will start the containers in detached    │
│ mode.                                                 │
╰───────────────────────────────────────────────────────╯

Related Entities: Docker, container, services, image

Sources: 5 chunks (top score: 0.016)

सांख्यिकी

dotnet run --project Mostlylucid.GraphRag -- stats
─────────────── GraphRAG Database Stats ────────────────
┌───────────────┬───────┐
│ Metric        │ Count │
├───────────────┼───────┤
│ Documents     │     5 │
│ Chunks        │    62 │
│ Entities      │   168 │
│ Relationships │   312 │
│ Communities   │    10 │
└───────────────┴───────┘

Database size: 7.76 MB

लागत तुलना

ब्लॉग पोस्टों के लिए 100

प्रचालन | एमएसएफटी ग्रैफराग |-----------|---------------|-----------|--------|-----| इकाई निष्कर्षण | | 1,000 | कॉल्स | दस्तावेजों में सुधार वर्गीकरण | समुदाय सारांश | कुल एलएलएम कॉल्स | ~1,020 | ~24 | ~120 | ~1,024 | | संबंध गुणवत्ता | अर्थात्मक | | | Co |- |occurrence | МSK3 | अर्थात्मक | लागत (gpt | ~$5-10 | ~$0.15 | ~$0.75 | ~$5-10 | | लागत (Ollama | N/A

हाइब्रिड मोड सबसे अच्छा है। अधिकतर तकनीकी सामग्री के लिए : आप सेमेटिक संबंध प्राप्त कर सकते हैं

सटीक आदेश-of-magnitude estimateM SK2 exact cost depends on chunk size and prompt shape

जमा-खरखाव

Aspect | Heuristic MSFT GraphRAG |--------|-----------|--------|-----|---------------| इकाई पता लगाना | आईडीएफ | + | संरचना | एमएसके3 | आईडीएफ़ | मएसके4 | रचना |एमएसके5 | आइडीएफ | मीएसके6 | ढाँचा | मेएसके7 | LLM प्रति टुकड़ा | माएसके8 संबंध | Co-occurrence | LLMM SK4inferred | एलएलएम कॉल्स रिश्ता गुणवत्ता | कम | उच्च ऑफ़लाइन काम करता है | सबसे अच्छा के लिए | गति अनुशंसित | विरासत कॉम्पट

सैद्धांतिक रूप से, यह एक ही पाइपलाइन है जैसे डॉक-सममैरिजर: सबसे पहले ढांचा बनाना

जहाँ यह टूटता है संरचनात्मक मार्कअप के बिना काल्पनिक या वर्णनात्मक पाठ

कोड

क्रियान्वयन इन फ़ाइलों के बीच न्यूनतम - ~2,000 लाइन है

Mostlylucid.GraphRag/
├── Storage/GraphRagDb.cs              # DuckDB with HNSW + provenance
├── Services/EmbeddingService.cs       # ONNX BERT wrapper
├── Services/OllamaClient.cs           # LLM client
├── Extraction/
│   ├── IEntityExtractor.cs            # Extractor interface
│   ├── EntityExtractor.cs             # Heuristic mode
│   ├── HybridEntityExtractor.cs       # Hybrid mode (recommended)
│   └── LlmEntityExtractor.cs          # Full LLM mode
├── Search/SearchService.cs            # BM25 + BERT hybrid
├── Graph/CommunityDetector.cs         # Leiden + summarization
├── Query/QueryEngine.cs               # Local/Global/DRIFT
├── Indexing/MarkdownIndexer.cs        # Chunking
├── GraphRagPipeline.cs                # Orchestration
├── Models.cs                          # Shared types + ExtractionMode enum
└── Program.cs                         # CLI

स्रोत: Mostlylucid.GraphRag/

संबंधित पोस्ट्स

बाहरी संसाधन

logo

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