# GraphRAG-osuus 2: Vähimmäiskäytännöllinen GrafRAG

<datetime class="hidden">2025-12-27T14:00</datetime>

<!-- category -- ASP.NET, GraphRAG, DuckDB, Vector Search, Machine Learning, Knowledge Graphs -->
Siihen [Osa 1](/blog/graphrag-knowledge-graphs-for-rag), tutkimme, miksi GraphRAG on tärkeä. **vähimmäiskäytännöllinen GraphRAG** kolmeen ekstraktiomuotoon:

| Mode | LLM-puhelut | Parasta m|
|------|-----------|----------|
| **Heuristinen** (defaultM SK1 | \0 kutakin chunkia kohden SSK4 Nopeiden indeksointien järjestelmällinen merkitseminen
| **Hybridi** | SSK1 asiakirjaa kohti | Nopeuden ja laadun tasapaino
| **LLM** |

Kaikki muodot käyttävät:

- **DuckDB-ohjelma** yhtenäistettyyn varastointiin (vectorit
- **BM25 M SK1 BERT-hybridinen haku** RRF:n fuusio
- **Ollama** synteesiin ja valinnaiseen ryhmäluokitteluun MSK00 API-kustannuksiaM SK1

**Serienavigointi:**

- [Osa 1: GraphRAG Fundamentals](/blog/graphrag-knowledge-graphs-for-rag)
- **Osa 2: vähimmäiskäytännöllinen GraphRAG** (artikkeliM SK1

> **Kode:** [Mostlylucid.GraphRag](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid.GraphRag) GitHubissa

[TOC]

## Luettelo arkkitehtuurista

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

## Miksi DuckDB?

Microsoft's GraphRAG käyttää erillistä varastointia vektoreille M SK1LanceDB), entiteetit (ParquetMSC4 ja suhteet |(more Parquet | ). | DuckDB yksinkertaistaa tätä

- Yksittäinen `.duckdb` asiakirja kaikkiin
- Native HNSW vektorin haku VSS-laajennuksella
- SQL sekä vector-tutkimukseen että grafiikan läpikulkuun
- Nollakäytön monimutkaisuus

**DuckDB ei ole grafiikkatietokanta - ja ettäM SK1 on kohta** Tämä ei ole 't NeoM SK1j . Traversaalit ovat alhaisia, SQLMSC4perustaisia, ja tarkoituksellisiaMST6 Tämä rajoittaminen pitää järjestelmän parannuskeinaltavissa ja edullisissa

## varastointijärjestelmä

Järjestelmä käyttää **liittää alkuperätaulukoita** Voimme kysyä "mikä chunkit mainitsevat elimen X

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

Keskeinen suunnittelupäätös: **ei `VARCHAR[]` alkuperä**. Liittyvät taulukoihin`entity_mentions`, `relationship_mentions`) mahdollistaa tehokkaat kysymykset, kuten " saa kaikki Dockeria mainitsevat chunkit

### Vektorin haku: HNSW Gotcha

DuckDB's HNSW-indeksi aktivoi vain `array_cosine_distance` + `ORDER BY` + `LIMIT`:

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

**Käyttämällä `array_cosine_similarity` ei käytetä indeksiä** - se voittaaM SK1 ei käynnistetä HNSW-indeksiä . muilla kuin triviallisilla yhtiöillä, tämä muuttaa ~5ms indeksoidun kysymyksen täydelliseksi taulukkoskanneriksiMSC6

## Entiteettien ekstrahointi

Tässä yhteydessä eroamme Microsoftin '-lähestymistavasta **LLM-perM SK1kuormitusyhteyksiä** käytetään Microsoftin viiteohjelmassa GraphRAG pipeline **IDF-perustainen tilastollinen extraktointi**Tavoite ei ole täydelliset yksiköt vaan ne *vakaa,korpusM SK1suhteelliset signaalit* , jotka eivät edellytä LLM:tä tuottamaan

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

### Miksi IDF:ssä ei ole hardcoded-luetteloita?

Naiivi lähestymistapa on `HashSet<string> KnownTech = { "Docker", "Kubernetes", ... }`. Tämä katkeaa :

- Uusia tekniikoita (you'd tarvitsee ajantasaistaa luettelon
- Domeniini-erityiset termit M SK1ertyinen corpus =erilaiset yksiköt)
- Misspellingit ja muutokset

**IDF (Reverse Document FrequencyM SK1** ratkaistaan tämä tilastollisesti. Termi's IDF onM SK2

$$\tekstiM SK1IDF}(tMSC3 = \\logMST6fracMSSK7N\}{dfMSL9t\MST10

:

- $NM SK1 = kokonaismäärä
- $df(t)$ = termiä sisältävät asiakirjat

Korkea IDF = **harvinaisuus** = on todennäköistä, että entisillä, jotka ovat chunkissa 5 ja 5, on suurempi IDF kuin " ja ", jotka on chunkkissa 100 ja 9

Lisätietoa TF-IDF ja BMM SK1:sta voi tutustua postissani [hybridinen haku BM25](/blog/rag-hybrid-search-and-indexing).

### Rakennesignaalit

Markdown-rakenne kertoo meille, mikä on tärkeä

- **Otsakkeet** (`## Docker Setup`)
- **Sisäinen koodi** (`` `docker-compose` ``)
- **Linkki** (`[Docker](https://docker.com)`)

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

### Linkkilähetys (YleinenM SK1Tulosuhteet laatuun )

Markdown-linkit tarjoavat **selväsanainen** suhteet, joissa ei tarvita LLM:n johtopäätöstä:

```csharp
// 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:n sisällyttämisen välityksellä tapahtuva vähentäminen

Entiteettien nimet, kuten "Docker Compose", "dockerM SK3composeMST4 ja SSK5DokerCompose" olisi yhdistettäväMSC7 Me käytämme **BERT-säännökset** semanttista samankaltaisuutta havaitsemiseksi:

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

Tämä askel on O(nM SK1 rajoitetussa ehdokaskokonaisuudessa, mutta ehdokasvaltioiden lukumäärät rajataan IDF-filtrointiin ja rakenteellisiin signaaleihin. [semanttinen haku ONNXin ja BERT:n avulla](/blog/semantic-search-with-onnx-and-qdrant).

## Poistotoimet

CLI-järjestelmä tukee kolmea ekstraktiomuotoa `--extraction-mode`:

### Heuristinen menettely (DefaultM SK1

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

Käytetään IDF + rakenteellisia signaaleja entiteetin havaitsemiseksiM SK1 valinnaisen LLM-heittoluokittelun kanssa **Zero per-chunk LLM-puheluja** - vain ~1 puhelua SSK2 yksiköistä tyyppien luokitteluun

### Hibriittimodus ( SuositettuM SK1

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

Kummankin maailman paras:

1. **Heuristinen havaitseminen**: IDF
2. **LLM:n parantaminen**: Yhden puhelun kohden *asiakirja* validoi entiteetit ja ekstrahoi semanttisia suhteita

```mermaid
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-asiakirjoihin, joissa on 62 chunkkit, hybridimode tekee **5 LLM-puhelut** (vs 124 täysimääräisen LLM-modeen osaltaM SK2 Saatte:

- Heuristiikkaa koskeva deterministinen entiteetin kattavuus
- LLM-laatusuhteiden ekstrakointi (semanttinenM SK2 ei vain yhteisvaikutus -todennäköisyysMSC4
- Kuvaukset ja vahvistetut tyypit

### LLM-modus (Microsoft-StyleM SK2

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

Full Microsoft GraphRAG approach: **2 LLM-puhelut kutakin chunkia kohti** (yksiköiden ekstraktointi +suhteiden extraktointi

### Milloin kutakin käytetään

| Mode | LLM-puhelut | Parasta m|
|------|-----------|----------|
| **Heuristinen** | ~1 kutakin SSK2 osapuolta kohden
| **Hybridi** | SSK1 asiakirjaa kohti | kattavuuden ja laadun tasapaino
| **LLM** |

Tekninen asiakirja, aloitetaan **hybridi** mode. Siihen sisältyy semanttisia suhteita ilman perinpohjaista kustannuksia. **Heuristinen** puhtaan nopeuden osalta, tai **Llm** narratiiviseen tekstiin.

## Hybridinen haku: BMM SK1 + BERT

Hybridinen haku yhdistää kaksi täydentävää lähestymistapaa:

**Tiheys (BERTM SK1** Ymmärtää merkityksen. M SK1Docker-säiliösäiliöt" vastaa "säiliön sisällyttäminenMSC4
**Säästö (BMM SK1** Vastaa täsmällisille ehdoille. M SK1HNSW

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

### Mikä on BM25?

BM25 M SK1Meiten vastaavuus 25)tulokset asiakirjoissa kysymyksen termien määrän perusteella

$$\_{iM SK1n} \tekstiMSC4IDFMST5qMSSK6i+) \\cdot \ \fracMSL10fMLS11q\MSL12i=MLS13 DMSS14 ♪\cdotti \(kMNS17 | | + , \ 1)}{f ,MNS20q , MNS21 , i+MNS22 , D\ MLS23 ,

Keskeiset intuiatiot:

- **IDF-nimitys**: Harvoilla sanoilla on enemmän merkitystä.
- **TF-tyydytys**: Sana, joka ilmenee 10x ei oleM SK2t 10x merkityksellisempi kuin
- **Pituuden normalisointi**: Pitkät asiakirjat eivät saa epäoikeudenmukaista etua

Täydellinen täytäntöönpano BM25 ja , ks. [yhdistetty haku ja indeksointi](/blog/rag-hybrid-search-and-indexing).

### Vastavuoroinen luokitus fuusio (RRFM SK1

RRF yhdistää eri hakujärjestelmien luokitukset. Jokainen luokitteluasema saa tulostaM SK1

$$\_{r \in RM SK2 \frac{1}{k M+ rMSC6dMST7

Jos $kM SK1 (tyypillisesti SSK3 estää ylipainon korkeimmassa tuloksessa **molemmat** luokitukset paranevat:

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

Esimerkki: Asiakirja, joka on luokiteltu M SK1 tiheään ja #3 harvaan

- Tiheys
- Tappiot: M SK1 | = | |
- **Yhdistetty: M SK1** (ylempi kuin yksittäinen

## Kysymysmenettelyt

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

### Kysymyksen luokittelu

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

Tämä luokittelujärjestelmä on tarkoituksellisesti yksinkertainen - ja helppo korvata pienillä tarkoitusmallilla myöhemminM SK1 Jos yksiköt eivät vastaa toisiaan, järjestelmä heikentyy puhtaasti puhtaalle hybridipäätökseen

## CLI:n käyttö

### Indexointi

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

```text
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    │
└───────────────┴───────┘
```

### Kysymys

```bash
dotnet run --project Mostlylucid.GraphRag -- query "How do I use Docker Compose?"
```

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

### Tilastot

```bash
dotnet run --project Mostlylucid.GraphRag -- stats
```

```text
─────────────── GraphRAG Database Stats ────────────────
┌───────────────┬───────┐
│ Metric        │ Count │
├───────────────┼───────┤
│ Documents     │     5 │
│ Chunks        │    62 │
│ Entities      │   168 │
│ Relationships │   312 │
│ Communities   │    10 │
└───────────────┴───────┘

Database size: 7.76 MB
```

## Kustannusten vertailu

For 100 blog posts

Operaatio | MSFT GraphRAG
|-----------|---------------|-----------|--------|-----|
|yksiköiden ekstrahointi | 1,000 puhelut SSK3 \0 || ♫0 ♫ | ♫
| Asiakirjojen parantaminen
| luokittelu | mukaan luettuna | S~4 paketti M| \- || | ~4 | paketti
| Yhteisön yhteenvedot
| **LLM-puhelujen kokonaismäärä** | ~1,020 | ~24 | ~120 | ~1,024 |
| **Suhteiden laatu** | Semanttinen SSK1 Yhteinen - toistuminen S| Seманttinen | | | Semantinen | SSK5
| **Kustannus (gpt-4oM SK2mini )** | ~$5-10 | ~$0.15 | ~$0.75 | ~$5-10 |
| **Kustannus (OllamaM SK1** | NM SK1A

**Hibridinen järjestelmä on paras vaihtoehto** useimman teknisen sisällön osalta saatte semanttisia suhteita.

> Tiukka määrä--laajuuden arvioinnin määrittelyM SK2todelliset kustannukset riippuvat kokosta ja pikamuodosta

## Ratkaisut

| Aspekti SSK1 Heuristinen MSFT GraphRAG | Hybridinen
|--------|-----------|--------|-----|---------------|
| Entiteettien havaitseminen | | | IDF |+ | rakenteellisuus | МSK3 | IIDF \+ |rakenteellisyys | LLM kutakin chunkia kohti |
Suhteet | Yhteinen-tapaus | LLM-inferred | Yhteinen- tapaus \| LLM SK8inferired \ |
| LLM-puhelut (100 asiakirjat) | \~24 || | ~120 |
| Suhteiden laatu | Alhainen SSK2 Korkea | Alhanteinen SSK4 Korkean S|
| Työskennellään offline-tilassa | | Kyllä || Kyllä
| Paras SSK1 NopeusM SK2 Kriittinen | **Suositus** | Perinteinen kompatti | Teksti ilman rakennetta |

Conceptually, tämä on sama putki kuin [DocSummarizer](/blog/docsummarizer-tool): rakentamaan ensin rakennettaM SK1 sitten antamaan LLM:n kertoa siitä

> **Missä tämä murenee** Fiction- tai narrative text without structural markup. Implicit relationships with no lexical signal

## Luettelo

Toteutuminen on vähimmäis - ~2,000 rivit näissä asiakirjoissa

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

**Lähde:** [`Mostlylucid.GraphRag/`](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid.GraphRag)

## Related Posts

- [Osa 1: GraphRAG Fundamentals](/blog/graphrag-knowledge-graphs-for-rag) - Miksi tietografiikat parantavat RAG:ta
- [Hybridinen haku BM25](/blog/rag-hybrid-search-and-indexing) - BM:n suorittamien tulosten ja indeksointien syvällinen tarkastelu
- [Semanttinen haku ONNXin ja BERT:n kanssa](/blog/semantic-search-with-onnx-and-qdrant) - BERT-embeddings in .NET
- [DocSummarizer -väline](/blog/docsummarizer-tool) - Minun asiakirjani yhteenvetoväline, joka jakaa kodin tähän

## Ulkoiset resurssit

- [DuckDB:n VSS-lisäys](https://duckdb.org/docs/extensions/vss.html) - HNSW-vektorin haku
- [Leidenin algoritmikirja](https://arxiv.org/pdf/1810.08473.pdf) - Yhteisön havaitseminen
- [RRF-paperi](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf) - Vastavuoroinen luokitus fuusio