# Reduktion av grafiska RAG-evidenssegment i ***klar*RAG**

<datetime class="hidden">2026-01-17T14:00</datetime>

<!-- category -- C#, lucidRAG, Vector Search, Machine Learning, Knowledge Graphs -->
> **NOTA:** Det här är inte en vanlig bloggartikel **teknisk specifikation** skriven för en konkret egenskap i ***klar*RAG**.
> Iterativt matar jag in det här dokumentet för att koda-", "focused LLMs during development to reason about trade", - "offs" , "validate assumptions" och "M SK3" "converge on a rational implementation"

Detta dokument beskriver ett subsystem från ***klar*RAG**, ett projekt Jag utvecklar aktivt

En av de viktigaste kraven ***klar*RAG** är förmågan att **del av bevis** - meningar , paragrafer M SK2 rubriker, , captioner,, rammar, , eller strukturerade blocker, - och se till att dessa segment är **duplicerad** utan att förstöra användbar signal.

***klar*RAG** arbetar genom att analysera och extrahera *bästa* tillgängliga bevis från dokumenten , bilder, ljud, och strukturerade dataM SK3 Till skillnad från de flesta RAG-implementeringar **inte** förvara LLM-genererade sammanfattningar som den primära artefakten . I många fall

I stället, ***klar*RAG** tillämpar ett brett spektrum av deterministiska och sannolikhetstekniker på

* extrahera kandidatsegment
* att bedöma deras informationsvärde
* och behålla bara de starkaste representanterna

**Duplicering är en viktig del av den här processen.**

Enkel strängs jämlikhet är inte tillräckligt. Samma koncept uttrycks ofta med olika ordnelser , struktur, , eller mönster,. Att behandla dem som separerade leder till överskott i lager och dåligt nedgående beteende

**Problemet förväxlas vid att få fram data.**

När resultaten är extraherade ( via SQL , vektor-inbäddar , BM M SK3 eller hybrider MSC4 genom att mata ett LLM med flera segment som alla uttrycker samma underliggande idé skapar det tråkiga MST5 upprepade svar Mst6 Fem nära M st7 identiska bitar från olika dokument ger inte mer tydlighet Mstr8 de dämpar det M ST9

För att adressera detta, ***klar*RAG** hanterar duplicering som en **det första problemet med kompilation i klass -**, inte ett svar

Resten av detta dokument beskriver hur den här dupliceringsstrategin designades. ['Agile Speccing'](https://www.mostlylucid.net/blog/writingfeaturespecs) anpassat till kod LLMS.

Detta kristalliserar tankarna, olika koncept och tvingar LLM att dokumentera dem. *bygger det rätta*.

[Se mer om ***klar*RAG** här. ](https://www.lucidrag.com)

# Reduktionsstrategi

***klar*RAG** använder en tvålagig deduplikeringsstrategi för att eliminera överskottsfulla innehåll samtidigt som man bevarar viktiga signaler. **signal-bevarande filter**, inte normalisering av innehåll

## Übersicht

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                           INGESTION (Per Document)                          │
│                                                                             │
│  Document → Extract → Embed → DEDUPE (intra-doc) → Index to Vector Store   │
│                                   │                                         │
│                                   ├─ Near-duplicates: boost salience        │
│                                   └─ Exact duplicates: drop (no boost)      │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                          RETRIEVAL (Cross Document)                         │
│                                                                             │
│  Query → Search → Rank (RRF) → DEDUPE (cross-doc) → Top K → LLM Synthesis  │
│                                   │                                         │
│                                   └─ Keep segment with highest RRF score    │
└─────────────────────────────────────────────────────────────────────────────┘
```

---


## Designgarantier

Dessa invarianter hållers kvar genom deduplikeringssystemet:

| Gwarant | Beschreibung |
|-----------|-------------|
| **Ordning bevarad** | Duplicering ändrar aldrig semantisk ordning efter RRF-rangering |
| **Inget koncept förlust** | Duplicering tar aldrig bort alla instanser av ett koncept.
| **Dokumentens gräns respekteras** | Duplicering överskrider aldrig dokumentens gränser vid inspegning |
| **Inhalt som inte kan förändras** | Duplicering ändrar aldrig inbäddar eller textinnehåll
| **Deterministisk** | Given identiska ingångar och konfigurationen , gör dupliceringen likadana utgångspunkter

---


## Inte

Det här systemet gör explicit **inte** försök att:

- **Detektor av faktisk motsägelse** - Två segment som säger motsägelsefulla saker är inte duplicerade
- **Kanonalisera sanningen** - Vi väljer inte ' en korrekt version över hela källorna
- **Kollapsera parafraser över dokumente vid intag** - Varje dokument har sina egna segment
- **Normalisera terminologi** - "ML" och " maskininlärning, " i olika dokument bevaras separat
- **Ersätta enhetens lösning** - Att ', GraphRAG, ', meningen med ,, arbetar på en annan nivå

---


## Determinism & Reproduktivitet

Deduplikering är helt deterministisk

- **Embeddings är omöjliga att ändra** en gång räknad vid extraktionstid
- **Sortering är stabil** - segment med lika stor betydelse håller ursprungliga ordning
- **Ingen slump** - ingen proverning , inga annämningsmässiga ANN M SK2 inga probabilistiska trösklar
- **Inget utländskt tillstånd** - avbetalningsbeslut beror bara på den nuvarande segmentsättningen

**Varför är detta viktigt:** Tillverkligare av sökresultat kan lita på att re- som körs med samma inputer ger samma resultat ***klar*RAG**' bredare "begränsad fuzziness" filosofi - fuzzy matching with deterministic behavior

---


## Varför två faser?

### Fas 1: Duplicering av intag

**mål:** Reduzera lagring och förhindra intrareundans på dokument

**Problemet:** Dokument innehåller ofta upprepade innehåll:

- Kolplatta text (header, footers , disclaimersM SK3
- Copy-passerade sektioner
- Samma koncept förklarade flera olika sätt

**Lösningen:** Duplicera inom varje dokument innan du indekserar

**Nyckelinsikten:** nära-duplikater behandlas som *oberoende bevis för vikt*Om en författare förklarar ett koncept på tre olika sätt, så är konceptet viktigt.

### Etappen 2: Duplicering av att hämta

**mål:** Att förhindra LLM från att få överskottsfulla information i alla dokument

**Problemet:** När man söker över flera dokument, kan liknande paragrafer dyka upp i olika källor.

**Lösningen:** Efter Rangering av RRF: n ( som kombinerar semantisk likhet , nyckelmönster matching M SK2 dragbarhet, , och nyhet

**Varför efter RRF?** RRF-värdet representerar den bästa holistiska mätningen av relevans.

### Varför boostar Salience bara vid ingestion

Trennningen är avsiktlig:

| Fasen | Vad den fångar |
|-------|------------------|
| **Intagstillande** | Författaren betonar - hur mycket dokumentet betonar ett koncept
| **Retrievals poäng** | Rädsla relevans - hur väl innehållet matchar användarens vilja | |

Att blanda dessa vid att hitta skulle förväxla dokumentens syfte med användars syfte. Det är viktigt att konceptet upprepas ♫ 5 ♫ gånger i en dokument *till den dokumenten*, men kan inte vara relevant *till den här sökningen*. Genom att öka den vid ingestionen , bevarar vi författarens signal utan att biasera sökresultatet

---


## Fas 1: Duplicering av intag

### Lokalisering

`src/Mostlylucid.DocSummarizer.Core/Services/BertRagSummarizer.cs`

### Metod

`DeduplicateSegments()`

### Algoritm

```
1. Filter segments by minimum salience threshold (0.05)
2. Sort by salience score (highest first)
3. For each segment:
   a. If no embedding → keep (can't compare)
   b. Check cosine similarity against all selected segments
   c. If similarity >= 0.90:
      - If same ContentHash → exact duplicate, drop silently
      - If different ContentHash → near-duplicate, boost kept segment's salience
   d. If no match → add to selected list
4. Apply salience boosts: +15% per near-duplicate merged
5. Cap salience at 1.0 to prevent any single concept from dominating
```

### Parameter

| Parameter
|-----------|---------|-------------|
| `similarityThreshold` | ♫ 0.90 ♫ ♫| ♫ Kosinelikhet ovanför vilka segmenter anses vara duplikater ♫
| `salienceThreshold` | ♫ 0.05 ♫ ♫| ♫ Minimala drag att ta hänsyn till ♫
| `boostPerNearDuplicate` | ♫ 0.15 ♫ ♫

### exempel

**Exakt Duplikat (Ingen Boost**

```
Segment A: "Contact us at support@example.com" [hash: abc123]
Segment B: "Contact us at support@example.com" [hash: abc123]  ← same hash
Result: Keep A, drop B, no boost (likely boilerplate)
```

**nära-Duplikat (Boost Applied**

```
Segment A: "Machine learning models require training data" [hash: abc123]
Segment B: "ML systems need data for training" [hash: def456]  ← different hash, 0.92 similarity
Segment C: "Training data is essential for ML" [hash: ghi789]  ← different hash, 0.91 similarity
Result: Keep A with +30% salience boost (concept emphasized 3 ways)
```

### Rationalitet för tröskeln

- **0.90 likhet** Baserat på forskning (NVIDIA NeMo använder industrystandard för semantisk dedup 0.90-0.92,
- **0.05 relevant** Filterar väldigt låga segment med värde, medan de mesta innehållet är kvar
- **15% upphöjning** Meningful signal utan överweighting

---


## Etappen 2: Duplicering av att hämta

### Lokalisering

`src/LucidRAG.Core/Services/AgenticSearchService.cs`

### Metod

`DeduplicateByEmbeddingPostRanking()`

### Algoritm

```
1. Receive ranked results (already sorted by RRF or dense score)
2. For each segment (in score order):
   a. If no embedding → keep
   b. Check cosine similarity against all selected segments
   c. If similarity >= 0.90 → skip (higher-scored duplicate already selected)
   d. If no match → add to selected list
3. Return deduplicated list (maintains score ordering)
```

### Parameter

| Parameter
|-----------|---------|-------------|
| `similarityThreshold` | ♫ 0.90 ♫ ♫| ♫ Kosineliknande tröskel för cross ♫

### Varför skicka?

RRF (Reciprocal Rank Fusion) kombinerar fyra signalerM SK2

1. **Dense poäng:** Semantisk likhet med en fråga
2. **BM25 poäng** Lexikal/talord match
3. **Salience poäng:** Inriktathet i ett dokument
4. **Frihetsnotar:** Recens boost

Att duplicera AFTER RRF betyder att vi håller segmentet som bäst matchar queryn över alla dimensioner

### exempel

```
Query: "How do I configure authentication?"

Results before dedup:
1. [Doc A] "Authentication is configured via config.yaml..." (RRF: 0.052)
2. [Doc B] "Configure auth using the config.yaml file..." (RRF: 0.048, similarity to #1: 0.93)
3. [Doc A] "Set the API key in environment variables..." (RRF: 0.041)

Results after dedup:
1. [Doc A] "Authentication is configured via config.yaml..." (RRF: 0.052)
2. [Doc A] "Set the API key in environment variables..." (RRF: 0.041)

Doc B's similar paragraph dropped - Doc A's version had higher RRF score.
```

---


## Förlustsmodi & Handeln -offs

### Begränsningar

| Missbruksmöjlighet | | | Beschreibung | | Mitigation |
|--------------|-------------|------------|
| **Falska positiva (över-dedupM SK2** | Två separata men nära besläktade koncept kan överträffa 0.90 likhet | | | Akzepterad handel |- | Avslag för reducerad redundans
| **Fals negativa (under-dedupM SK2** | Väldigt korta segment kan inbäddas dåligt, bristande semantisk likhet | Hash
| **Inbäddad drift** | Att ändra inbäddade modeller försämrar avvikande antaganden | | | Erfordrar full re | - | ingestion | МSK3 | Inbäddar är omvandliga när de blivit lagrade
| **Orderkänslighet** | Greedy selection means first high - sallivssegment vunnir | | | Mitigad genom stabil sortering |

### Accepted Trade-offs

- **Precision over recall:** Vi föredrar ibland att hålla nära -duplikater jämfört med att oavsiktligt ta bort olika innehåll
- **Storage över precision:** Vi lagrar per document rather than global dedup för att bevara källanstribution
- **Enkelhet över optimering:** O(nM SK1 är accepterad för typiska dokumentsstorlekar ; LSH tillsätter komplexitet

---


## Multilinguella övervägningar

Reduktionsbeteende med flerspråkig innehåll:

| Scenario | Behavior | | 2 | Rationale | 3 |
|----------|----------|-----------|
| **Samma språk** | Den normala deduktionen appliceras | Embeddings fångar semantisk likhet |
| **Parafraser över språket** | inte duplicerad | Bevarar källan- språkbarhet |
| **Ett blandat document i språket** | Dedup inom språkkloster | Embeddingsliknande avseparerar naturligtvis språk

**Designvalen:** Cross-språksduppning är explicit inte supporterad . Det bevarar förmågan att hämta samma fakta i användarens prefererade språk eller jämföra hur olika källans fraser saker är

Framväxande förbättringar : Cross-språkiga avvikelser skulle kunna skiftas via översättningen-invarianta inbäddar om det behövsM SK3

---


## säkerhet & Motsägelser

Reduktionssystemet inkluderar indirekta skydd:

| Angriffsvektor | skydd |
|---------------|------------|
| **Saliens inflation via repetition** | Upphöjt upphöjt vid 1.0; exakta kopior don' inte upphöj |
| **Kopiera-pa spam över dokumente** | Cross
| **handling av poäng genom duplicerad injiction** | Dedup uppstår efter klassificeringen , för att förhindra poäng-inflation |
| **Kolplatta översvämningar** | Exakt hashmatch-detektor minskar utan upphöjning |

**Nota:** Deduplikering är inte en säkerhetsgränsen. Den ondskafulla innehållet som passerar intagningsfilterna kommer att indexeras . innehållsfilterning borde ske uppstream

---


## Interaktion med GraphRAG

Reduktion och GraphRAG är avsiktligt ortogonala:

| System | | | Operaerar på | | | syfte | МSK3
|--------|-------------|---------|
| **Reduktion** | Segment ( textskivor) | Ta bort överskott av sökresultat
| **GraphRAG** | Entityder & Attityder

**Varför separera?**

- Ett segment som nämner """, Apple "", " "", och ett annat som näms """, företaget, " "", kan avvika från likvärdigt text men representera samma enhet, - "", som
- Dedup behöver inte entitydmedvetenhet, det fungerar enbart på semantisk likhet.
- Enheten-aware dedup skulle kunna lägga till senare som en förbättring, inte som en ersättning

---


## Observerbarhet & Metrik

### Den nuvarande logeringen

Införing:

```
[dim]Deduplication: 150 → 98 segments[/]
```

Att hämta data:

```
Post-ranking deduplication: 50 → 42 segments (removed 8 cross-doc duplicates)
```

### Rekomenderade mätvärden

För produktionsövervakning tänk på spårning

| Metrik | Beskrywing | | | hälsosamt intervall | МSK3
|--------|-------------|---------------|
| `dedup_ratio_ingestion` | % segment som togs bort vid inspetsning
| `dedup_ratio_retrieval` | ♫ ♫ % ♫ Segment togs bort vid att hämta ♫
| `avg_salience_boost` | Medelvärde förhöjning för varje dokument
| `max_salience_boost` | Den högsta ökningen i en dokument | | | < |
| `dedup_by_doc_type` | Dedup-värde segmenterat efter dokumenttyp | Variationer |

### Debugstips

- **Högt intag avföring (>50%):** Dokumentet kan ha överdriven boilerplatta eller vara automatiserat
- **lågt intag avföring (<5%):** Dokumentet har olika innehåll. ( bra ) eller inbäddar är dåliga
- **Högt återhämtadedupp (>30%):** Frågan kan vara för brett, eller corpus har många liknande dokument
- **Saliens närmar sig 1.0:** Konceptet betonades kraftigt: ;, verifiera det , "', är lagligt, ,, inte spam.

---


## Konfiguration

Deduplikering är konfigurerad via `DocSummarizerConfig.Deduplication` sektion i `appsettings.json`:

```json
{
  "DocSummarizer": {
    "Deduplication": {
      "Ingestion": {
        "Enabled": true,
        "SimilarityThreshold": 0.90,
        "SalienceThreshold": 0.05,
        "EnableSalienceBoost": true,
        "BoostPerNearDuplicate": 0.15,
        "MaxSalienceBoost": 1.0,
        "BoostDecayMode": "Logarithmic",
        "LogBase": 2.0
      },
      "Retrieval": {
        "Enabled": true,
        "SimilarityThreshold": 0.90,
        "MinRelevanceScore": 0.25
      },
      "Analytics": {
        "EnableLogging": true,
        "EnableMetrics": true,
        "HighIngestionDedupThreshold": 0.50,
        "HighRetrievalDedupThreshold": 0.30,
        "HighSalienceBoostThreshold": 0.60
      }
    }
  }
}
```

### Intag Konfiguration

| Parameter
|-----------|---------|-------------|
| `Enabled` | `true` | Aktivera
| `SimilarityThreshold` | `0.90` | Kosinelikhets tröskel för duplicerad detektion |
| `SalienceThreshold` | `0.05` | Minimala relevantitet att ta hänsyn till (filterljudsmängdM SK2 |
| `EnableSalienceBoost` | `true` | Upphöjt saliens för nära
| `BoostPerNearDuplicate` | `0.15` | Bättring för basen per nära
| `MaxSalienceBoost` | `1.0` | Max salens kapsyl |
| `BoostDecayMode` | `Logarithmic` | `Linear` eller `Logarithmic` förruttna |
| `LogBase` | `2.0` | Basis för logaritmisk nedfall |

### Lösning Konfiguration

| Parameter
|-----------|---------|-------------|
| `Enabled` | `true` | Aktivera
| `SimilarityThreshold` | `0.90` | Kosinelikhets tröskel |
| `MinRelevanceScore` | `0.25` | Minimum RRF-värde för att inkludera |

### Analytikkonfiguration

| Parameter
|-----------|---------|-------------|
| `EnableLogging` | `true` | Operationer för logduplikering |
| `EnableMetrics` | `true` | Samma mätvärdena för övervakning |
| `HighIngestionDedupThreshold` | `0.50` | Varna om
| `HighRetrievalDedupThreshold` | `0.30` | Varna om >30% dupliceras vid att hämta |
| `HighSalienceBoostThreshold` | `0.60` | Varna om ökningen överträffar

### Boosta avbrottsmodi

**Linjära Modus** ( enkelt , förutsägbart M SK2

```
boost = boostPerNearDuplicate × count
```

exempel: M SK1 nära-dupes × | | 4 | 5 | 6 | Steg

**Logaritmiska Modus** (djupande resultat,vikt

```
boost = boostPerNearDuplicate × log₂(1 + count)
```

exempel: M SK1 nära-dupes → | | 0.15 \ × log

Den logaritmiska metoden är tillförlitlig eftersom:

- De första några kopiorna har den starkaste signalen (författaren betonar )
- Många kopior kan indikera att boilerplatet, inte är viktigt
- Försämrar att saliens inflation

---


## Tillvägagångspunkter

### Kompleksitet

| Fas | Kompleksitet | Typisk storlek M| Inverkan m|
|-------|------------|--------------|--------|
| Införing | | | O |  | n | МSK3 | | 4 | 5 | segmenter |
| Tillförseln | OmM SK3 ♫ ♫ | ♫

### Skalerande väg

För väldigt stora dokument (10,000+ segmenter):

1. **LSH ( Lokalitet -Sensitiv Hashing):** O(nM SK1 ungefär
2. **Vergleich av batterier:** Bearbeta i skivor för att minska minnet
3. **Filterning tidigt:** Mer aggressiv salient tröskel

Den nuvarande implementeringen är optimerad för typiska dokumentstorlekar. LSH lägger till komplexitet utan nytta för de flesta användande fallen.

---


## jämförelse med forskning

| tillvägagångspunkt | tröskel | | | källan |
|----------|-----------|--------|
| lucidRAG
| NVIDIA NeMo Curator [SemDeDup dokument](https://docs.nvidia.com/nemo/curator/latest/curate-text/process-data/deduplication/semdedup.html) |
| MinHash LSH [Google C4, GPT-3 papper](https://huggingface.co/blog/dedup) |
| SemHash [GitHub](https://github.com/MinishLab/semhash) |

Vår tröskel av 0.90 är i harlang med industrins bästa metoder för semantisk deduplikering

---


## Vad är inte duplicerat

| innehållstyp | orsak |
|--------------|--------|
| CrossM SK1 dokument vid intag | Bevarar per - källans lösning och tilldelning
| lågtM SK1 likvärdighetsinnehåll (<0.90) | Semantiskt separerad M|
| Skillnade segmentstyper | Rubrik och punkt har olika strukturella roller
| Cross-språksförkortningar | | | Bevarar språk mångfald ||

---


## Ingripande status

| Funktionen | Status ♫ | ♫ Lokalisering ♫| ♫
|---------|--------|----------|
| Konfigurerade tröskeln | ♫ ♫ ✅ ♫ Rakett ♫ `DeduplicationConfig` klass |
| Förstärkande förruttnande (logskala | | ) | `BoostDecayMode.Logarithmic` |
| Analytik med avvikningM SK1 mätningar | ✅ Rakett M| `DeduplicationResult<T>` rekord |
| Integration av DI-tjänster `IDeduplicationService` |

## Framtidens förbättringar

1. **Dedup analytik-dashboard:** Visuella spårning av pris per dokumenttyp
2. **Cross-språksöversättning:** Translation-invariant embeddings for multilingual dedup
3. **Enheten-informerad dedup:** Använd GraphRAG-enheter som ytterligare signal ( inte utbytning)
4. **Prometheus/OpenTelemetry:** Export metriker för övervakningsdashboarder

---


## sammanfattning

Den här dupliceringsstrategin:

- **Bevarar signal** - näraM SK1 duplikater ökar betydelsen snarare än att bli avlägsna
- **Omfamnar gränser** - Dokument upprätthåller oberoende segmentsgrupper
- **Ranger sen filtrerar** - använder full RRF-signal innan deduktionen sker
- **Det misslyckas säkert** - Prefererar att behålla innehållet snarare än att aggressivt ta bort det
- **Blir deterministisk** - Samma intryck ger alltid samma resultat