Back to "Reduzerad RAG: Stopp att fylla i kontexten Windows och börja extrahera signaler"

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

AI Architecture LLM RAG Semantic Search

Reduzerad RAG: Stopp att fylla i kontexten Windows och börja extrahera signaler

Thursday, 08 January 2026

Om du är helt ny på RAG, börja med RAG förklaras och RAG arkitektur. Denna artikel är till för punkten där du ' har byggt en RAG-kanal som mest fungerar… och nu är duM SK1 som betalar för det i kostnaden, sprödlighet , och | " varför svarade det på det?

Vad detta täcker: Architektoniska mönster bakom produktionen RAG. För händerna - för realisationen M SK2 se Att bygga en dokumentuppfattare med RAG.

Var det kommer ifrån: Jag byggde DocSummarizer (Document RAG-motor DataSummarizer (Data RAG-motor ImageSummarizer (Image RAG-motor AudioSummarizer (Audio RAG-motor lucidRAG (multi

NOTA: Du har kanske med rätt märkt att den semantiska sökningen på den här sidan är bruten ... och ja, det ' är en konfigurationsproblem jag inte har M SK3 har inte haft tid att fixa än MSC4 Inte dålig teori MST5

RAG: s terminologisk uppvärmning

Begrenspunkt Vad det betyder
RAG Att få fram data - Förstärkt skapande ♫ ♫ Ge ett LLM till ditt företag innan du svarar ♫
Folketing Splittring av dokument i mindre bitar Breckning av en PDF i paragrafer
Top-k Ta sökresultatet från en sökning.
Vektorsökning Att hitta liknande text med hjälp av inbäddar
BM25 Keyword search МSK2 Hitta dokument som innehåller ' timeout ' och ' databasen
Kontextfenster Hur mycket text kan du få plats i ett prompt Fint och dyrt
Signaler Faktum extraherat utan AI " Utformade 3 4 5 Prioriterad 6 Hög 7 8

Retrieval-Augmented Generation (RAG) har blivit en av de fraser som betyder allt och ingenting.

För många lag är det nu RAG , ” och ":

  1. Chunk-dokument
  2. Embetera dem
  3. Retrieve top-k
  4. Släpp allt i prompten
  5. Fråga modellen till “konfigurera det

Det fungerar. Tills den inte gör det

Det är svårt att resonera med det, det är dyrt och det ger modellen tyst ansvar, det analyserar strukturen, det tvingar in filterna, det bestämmer vad som är viktigt, det förbereder motsägelser, det hindrar och det är självsäkrat.

När folk säger “, RAG hallucinerar, ” eller “, ARG filtrerar inte bra ’, ”,, de anklagar ofta fel komponenten

Problemet är’t RAG. Problemet är lat RAG.

Denna artikel beskriver en annan standard Reduzerad RAG - använda LLMs mindre, inte mer , genom att extrahera deterministiska signaler framifrån och behandla modeller som syntetiska motorer, inte databutiker.

Det centrala felet: i att behandla kontextfenster som lagring

Ett kontextfenster är:

  • flyktig
  • oskrivet
  • dyrt
  • återbetalade på varje fråga

Det är inte en databank.

När du “ bara kliver mer i prompten ”, så frågar du den modellen till

  • re- analysera strukturen varje gång
  • räkna ut filter istället för att tvinga dem
  • sammanfatta bort detaljer du kanske behöver senare
  • klang självsäker även när det är fel

Det är därför RAG-demos ser bra ut och produktions RAG -system ruttnar tyst.

Vad “Reduced RAG” betyder

Reduzerad RAG vänder den standardinställningen.

I stället för:

Ta upp texten och låta modellen bestämma vad som är viktigt.

Du gör det

Bestäm vad som är viktigt en gång.

I praktiken betyder det deterministisk ingestion , billiga spårning, begränsad generation.

Om det låter välbekant, så är det samma systemform som Begränsad otydighet: låter sannolikhetskomponenter föreslå; låter deterministiska system bestämma.

Traditionella RAG vs Reduced RAG

Först ska vi se vad de flesta lag gör, och varför det är dyrt.

flowchart LR
    subgraph Traditional["❌ Traditional RAG: Everything Through the LLM"]
        T1[Documents] --> T2[Chunk Everything]
        T2 --> T3["Embed All Chunks<br/>(once)"]
        T3 --> T4[Vector Search]
        T4 --> T5["Paste Top-K<br/>(per query)"]
        T5 --> T6["LLM Decides<br/>(per query)"]
        T6 --> T7[Answer]
    end

    style Traditional stroke:#ef4444,stroke-width:3px
    style T6 stroke:#ef4444,stroke-width:3px
    style T5 stroke:#ef4444,stroke-width:2px

Problemet:

  • LLM re- analyserar strukturen för varje fråga
  • Kan "'" inte tvinga filtern "(", "" Only "", " "", ande "" nicely "", "", via "" prompt "".
  • Skala av tokenskostnader med queryer (↑ per query)
  • Hallucinationer när modellen uppfinner filter

Här är "'", den Reduced RAG-metoden.

flowchart TB
    subgraph Ingestion["✅ Ingestion (Once - Pay Upfront)"]
        I1[Source Docs] --> I2[Parse Structure]
        I2 --> I3["Extract Signals<br/>(deterministic)"]
        I3 --> I4[(Structured Fields)]
        I2 --> I5[Semantic Units]
        I5 --> I6[(Vector Store)]
        I2 --> I7[(Evidence Store)]
    end

    subgraph Query["Query Time (Cheap Per Query)"]
        Q1[User Question] --> Q2{Extract Filters}
        Q2 --> Q3["Filter Database<br/>(no LLM)"]
        Q2 --> Q4["BM25 Search<br/>(no LLM)"]
        Q2 --> Q5["Vector Search<br/>(no LLM)"]

        Q3 --> R[Candidate Set]
        Q4 --> R
        Q5 --> R

        R --> S["Small Evidence Pack<br/>(5 sources not 50)"]
    end

    subgraph Generation["LLM (Bounded Synthesis Per Query)"]
        S --> L[Synthesize Answer]
        L --> A[Answer + Citations]
    end

    style Ingestion stroke:#22c55e,stroke-width:3px
    style Query stroke:#3b82f6,stroke-width:3px
    style Generation stroke:#f59e0b,stroke-width:2px
    style I3 stroke:#22c55e,stroke-width:3px
    style Q3 stroke:#3b82f6,stroke-width:3px
    style L stroke:#f59e0b,stroke-width:3px

Nyckelskillnader:

Fasen Traditionell RAG Reduzerad RAG
Intag Bara skräddarskiva och inbädda Extrahera datum
Filter Säg till LLM att filtrera i uppspringen Databas därklauseln finns
söka enbart vektorn BM25 + vektor M+ Strukturerade filter
LLM: s roll analysera, filtera , Och svara Synthesera bara svaret
kostnaderna Varje fråga betalar för hela kontexten Ingestion en gång

steg 1: Deterministisk intag ( det tråkiga bitet som spelar roll

Vid intagningstid, analysera vad du kan utan en LLM.

exempel: Support Ticket System

Istället för att bara stapla in bilbiljetter i text

Traditional: "Ticket #1234: Customer complained about slow loading..."
→ Embed entire text
→ Hope the LLM figures out it's about performance

Extrahera signaler upp fronten:

// Parse once during ingestion
var ticket = new SupportTicket
{
    Id = "1234",
    CreatedDate = DateTime.Parse("2025-01-15"),
    Category = "Performance",              // ← Deterministic field
    Product = "WebApp",                     // ← Filterable
    Priority = "High",                      // ← Sortable
    Customer = "Enterprise",                // ← Segment filter
    SentimentScore = -0.3,                  // ← Computed once
    Tags = ["slow-loading", "timeout"],     // ← Searchable
    Text = "Customer complained about..."   // ← Still keep for RAG
};

Vad du kan extrahera deterministiskt:

Signaltyp ♫ ♫ exempel ♫ ♫ Varför det spelar roll ♫
Tydliga Datum skapat , Datum uppdaterad M SK2 utgångsdatum
Kategoriserad Status
Numeriska pris , kvantitet
Identitet bokförfattare, kundidentifisator , SKU , beteckningar # M SK6 Vill biljetter från Kunden X
Jakt OCR-förtroende
Förekomst källsystem

Gör det en gång

Den hårda delen av RAG är: "'", det är inte modellen, det är - det är allt före modellen. För konkreta implementeringar, ,, se Att bygga en dokumentuppfattare med RAG och DocSummarizer: Byggnader RAG Pipelines.

steg 2: lagra signaler | ( | och spara bevis

Istället för att behandla """, "" chunks, " "", som enhet av sanning, ",", lagra strukturerade fält, "", , "", signal, M SK4 "", kompakta enheter, , "", inbäddar, MSC6 "", och peka tillbaka till källan.

Texten är fortfarande en del av systemet - men den blir bevis, inte " vad vi än råkade skriva in i prompten

Detta är skillnaden mellan "RAG- Svaret är viber " och " RAG- svaren är inspektbara

" Men hur vet jag vilka signaler jag ska extrahera

Du gör det inte

Det är hela poängen med att lagra råsignaler istället för LLM-bearbetade sammanfattningar.

Traditionella RAG ( dyrt att byta

// ❌ You asked the LLM to "summarize the key points"
var summary = await llm.Summarize(ticket.Text); // Expensive
await db.SaveAsync(summary); // Threw away the original structure

// Later: "Actually, we need sentiment scores too"
// 😱 Have to re-process 10,000 tickets through LLM again!

Reduzerad RAG (billig att ändraM SK1

// ✅ Store raw signals extracted deterministically
var signals = new TicketSignals
{
    Text = ticket.Text,                    // ← Keep original
    WordCount = ticket.Text.Split().Length, // ← Cheap to compute
    ContainsErrorCode = Regex.IsMatch(ticket.Text, @"ERR-\d+"),
    MentionedProducts = ExtractProducts(ticket.Text), // ← Heuristic
    SentimentWords = CountSentimentWords(ticket.Text), // ← Word lists
    CreatedHour = ticket.Created.Hour      // ← Maybe useful later?
};

// Later: "We need to prioritize by sentiment"
// ✅ Just add a computed column - no LLM re-run needed!
await db.ExecuteSqlAsync(@"
    ALTER TABLE Tickets ADD COLUMN SentimentScore AS
    (SentimentWords->>'positive' - SentimentWords->>'negative')
");

Vad har just hänt?

  • Du lagrade mer signaler än du behövde ( billigtM SK1
  • När krav ändrades, så var du återkomputerad från lagrade signaler ( fri)
  • Du gjorde inte "'" -t- -och loopade LLM: s slutsats på dokumenten.

Detta är samma mönster som ":".

  • DiSE (Inriktad syntetisk evolution) - lagrar provresultaten , mutationshistorien M SK2 kvalitet mätningar . När du ändrar utvärderingsfunktionen MSC4 gör du det inte, ' gör ingen omställning till - kör LLM-evolutionen,— gör en omställning mot - räknar ut existerande kandidater från lagrade signaler,
  • Bot-detektor - lagrar begäranpatroner , tidningsignaler

Reglerna: Kom ihåg före LLM. uppdatera din M SK1memory" (avtagningslogikMska4 gratisMske5

Nyckeln till arkitektoniska nytta Eftersom du lagrar deterministiska signaler tillsammans med inbäddar ( inte istället för dem ), varje del av systemet kan förändras oberoende av sig M SK2 byta inbäddade modeller ? bytta tillbaka MSC4 inbädda utan att röra vid signalern Mska5 lägga till ett nytt signal M Ska6 beräkna det från lagrad text utan att göra något om detM Ska7 inbyggda M ska8 Ranga upp tonerna M Sk9 justera signalvikten och scorningslogiken utan att indexera om det igen

Med multi-vektorbutiker ( som Qdrant), kan man till och med lägga till flera inbäddar per dokument. Vill prova ett nytt inbäddat-modell ? Lägg till det tillsammans med det existerandet och förvandla det gradvis M SK2 Testa både i produktionen , jämför kvalitet MSC4 och avfärda det gamla ♫ - utan att indexera eller störa servicen ♫.

Varje komponent kan utvecklas utan att tvinga en hel pipeline att byggas om - och utan att försämra de andra ♫ . ♫

Vilka signaler ska du lagra?

Speichera allt du kan bearbeta billigt och deterministiskt.

viktigt: Signaler är bara korta textsträngar , siffror, och booleans—, inte gigantiska datastrukturer ., du ', sparar M SK3, prestationsnivån, ", | | (8, grejer, ),, inte ", kunden klagade på långsamt laddande tid.

public class DocumentSignals
{
    // Always extract (almost free)
    public int CharCount { get; set; }              // Example: 1247
    public int WordCount { get; set; }              // Example: 203
    public int ParagraphCount { get; set; }         // Example: 5
    public string[] UniqueWords { get; set; }       // Example: ["timeout", "error", "api"]

    // Structural (parse once)
    public bool HasCodeBlocks { get; set; }         // true/false
    public bool HasLinks { get; set; }              // true/false
    public int HeadingCount { get; set; }           // Example: 3

    // Heuristic (simple patterns)
    public string[] MentionedProducts { get; set; }       // Example: ["WebApp", "API"]
    public string[] ErrorCodes { get; set; }              // Example: ["ERR-404", "ERR-500"]
    public Dictionary<string, int> SentimentWords { get; set; } // { "positive": 3, "negative": 7 }

    // Metadata (already available)
    public DateTime Created { get; set; }           // Example: 2025-01-15T14:23:00
    public string Author { get; set; }              // Example: "[email protected]"
    public string Category { get; set; }            // Example: "Performance" (not essay-length)

    // Computed (cheap math)
    public double ReadingTimeMinutes { get; set; }  // Example: 4.2
    public double KeywordDensity { get; set; }      // Example: 0.034
}

Storhetskostnadsvergleich:

Vad du sparar Storlek per dokument
Hela texten ~5 Kb
Alla dessa signaler ~500 byter MB
LLM-genererad sammanfattning ~2 Kb

Signaler är 10x mindre än text, 4x mindre än LLM sammanfattningar, och oändligt billigare att räkna tillbaka ( eftersom du inte behöver

När du inser att du behöver en annan signal: Bara beräkna det från lagret rådata.

Detta är anledningen till att "+-+Extraktion-"+ är säkert- :+ du betalar en gång i lager-

steg 3: söka utan att ha en LLM

De flesta "RAG-sökningar" är egentligen bara söksökningar med begränsningar

  • " endast de senaste dokumenten
  • " endast för brittiska kunder
  • " endast i de betalade planen "
  • " enbart fel från förra veckan "

Traditionella RAG ( dyrt , otillförlitligt M SK2

// ❌ Paste everything into prompt and hope
var chunks = await vectorSearch.SearchAsync(query, k: 50); // 50 chunks!
var prompt = $@"
Given these 50 chunks of text, answer the question but ONLY use
docs from last week and ONLY for UK customers.

Chunks: {string.Join("\n", chunks)}

Question: {userQuestion}
";
var answer = await llm.GenerateAsync(prompt); // Expensive + unreliable

Reduzerad RAG ( billigt , deterministiskt M SK2

// ✅ Filter first, retrieve less, synthesize last
var candidates = await db.Tickets
    .Where(t => t.CreatedDate > DateTime.Now.AddDays(-7))  // ← Database does this
    .Where(t => t.Region == "UK")                          // ← Not the LLM!
    .ToListAsync();

// Hybrid search on the filtered set
// (In production: push BM25 to database/index, not in-memory LINQ)
var bm25Results = candidates.Where(c => c.Text.Contains(keyword));
var vectorResults = await vectorSearch.SearchAsync(query, k: 5, filter: candidates);

// Small evidence pack
var evidence = RRF.Merge(bm25Results, vectorResults).Take(5);

// LLM only synthesizes
var answer = await llm.GenerateAsync($@"
Synthesize an answer using ONLY these 5 sources:
{FormatEvidence(evidence)}

Question: {userQuestion}
");

Vad har just hänt?

  • Databasen filtrerades deterministiskt ( inte LLM)
  • LLM ser 5 källor i stället för 50 | | (90% | symbolreduktion
  • Filter är garanterade, inte "bestämdM SK2

Det är därför hybridsökningar är viktiga i produktionen. Hybridsökning & Auto-Indexering är det mest praktiska exemplaret i hela RAG-serien.

facultativt: Att använda en LLM för att extrahera syfte ( som ett förslag

Om en fråga är riktigt stökig, så kan använda en liten modell för att extrahera intens

// Use small model to propose filters (ephemeral - discarded after use)
var intent = await smallModel.ExtractIntent(userQuestion);
// Returns: { intent: "troubleshoot", filters: { priority: "high", product: "api" } }

// Validate the proposal against known fields (deterministic)
var validatedFilters = ValidateAgainstSchema(intent.filters);

// Use validated filters for retrieval
var results = await db.Tickets.Where(validatedFilters).ToListAsync();

Grundprincipen: LLM föreslår

Detta är grunden till Begränsad otydighet mönster.

För att dyka djupare in i efemerala utdragsmönster där du använder LLM tillfälligt utan att upprätthålla deras resultat Ogen och Don't Bort glöm.

steg 4: LLM som syntetiska motorer

Bara efter att ha tagit fram informationen kallar du LLM. Du ger den en liten set av fakta med bevispunkter och tydliga instruktioner för osäkerhet

Modellet ' jobbet: Syntesize , förklara, jämföra. Inte kräva begränsningar , bestämma sanningen, uppfinna struktur.

Om du bryr dig om “LLMs att dra hela kontextfenoret in i svaren, så har du redan sett misslyckande modet. Begränsat Fuzzy Kontexttdragning: det ’ är inte ondskefulla - det\ ’ det är vad du bad den göra

Varför är det här säkrare och billigare

Föreställelse för kostnaderna ( illustrerande exempel )

Order-av-skillnadsvergleich för ett typiskt RAG-system

Scenario: 10,000 stödbiljetter

tillvägagångspunkt Ingestionskostnader Per
Traditionella RAG Embetera 10 k-biljetter**$75/dag**
Reduzerad RAG Embetera + extrahera signaler 5 bitar ♫ ♫ × ♫ liten kontext ♫$7.50/dag

Order av magnitude: ~10x kostnadsförlust per dag

Ännu bättre Med bra bevis och deterministisk filtering, behöver du troligen inte ' någon gränsmodell överhuvudtagetM SK2 Ett lokalt Ollama-modell ( friaMSC4 med en liten mängd bevis presterar ofta bättre än GPTMska5 matade mska6 bitar som den måste analysera själv

Plus: reduced debugging time

Tillförlitlighet

Traditionella RAG (

// ❌ Prompt says "only UK customers" but model can ignore it
var answer = await llm.Generate(prompt); // No guarantee

Reduzerad RAG (avtryckt filtrering

// ✅ Database physically prevents non-UK results
var results = db.Tickets.Where(t => t.Region == "UK"); // Guaranteed

Varför är det säkrare? Filter tvingas införa innan en generation. Modelen aldrig ägde dem. Modellen kan inte glömma dem, och hallucinationer är begränsade av bevis du kontrollerar.

Förklaring

Traditionell RAG: "Modelet sa detta , men jag är inte säker på varför eller vilken del den kom från

Reduzerad RAG:

// You know exactly why each result matched
var result = new SearchResult
{
    Text = "Server timeout error",
    MatchedBecause = new[]
    {
        "Region = UK (database filter)",
        "Created in last 7 days (date filter)",
        "BM25 score: 4.2 (keyword 'timeout')",
        "Vector similarity: 0.89 (semantic match)"
    },
    SourceChunks = [chunk1, chunk2], // ← Audit trail
    ConfidenceScore = 0.89
};

Du kan inspektera varför varje resultat matchas , visa bevis när självförtroendet är lågt, och lösa problem med produktionen genom att undersöka kandidaten som sattes innan LLM-synthesen

Börja igång: Refactoring of the traditional → reduced RAG

Om du redan har ett fungerande RAG-system

steg 1: Lägg till strukturerade fält vid din intag

Innan:

public class Document
{
    public string Id { get; set; }
    public string Text { get; set; }           // ← Only unstructured text
    public float[] Embedding { get; set; }
}

Efter:

public class Document
{
    public string Id { get; set; }
    public string Text { get; set; }           // ← Keep for evidence
    public float[] Embedding { get; set; }

    // Add deterministic signals (extract once during ingestion)
    public DateTime CreatedDate { get; set; }  // ← Parse from metadata
    public string Category { get; set; }       // ← Extract from filename/tags
    public string Author { get; set; }         // ← From file properties
    public string[] Tags { get; set; }         // ← Parse from content/metadata
    public double QualityScore { get; set; }   // ← Compute heuristics
}

steg 2: Flytta filter ut ur instruktionerna, till sökningar

Innan:

var prompt = "Only use docs from last month for product 'API'. Query: " + userQuery;
var chunks = await vectorStore.Search(userQuery, k: 50);
var answer = await llm.Generate(prompt + chunks); // ❌ LLM might ignore filters

Efter:

// ✅ Database enforces filters
var candidates = await db.Documents
    .Where(d => d.CreatedDate > DateTime.Now.AddMonths(-1))
    .Where(d => d.Category == "API")
    .ToListAsync();

// Search only the filtered candidates
var results = await vectorStore.Search(userQuery, k: 5, filter: candidates.Select(c => c.Id));
var answer = await llm.Generate(FormatEvidence(results)); // Much smaller context

steg 3: Lägg till hybridsökning (BMM SK2 + Vektor)

// Combine keyword and semantic search
var keywordResults = await db.Documents
    .Where(d => EF.Functions.ToTsVector("english", d.Text)
        .Matches(EF.Functions.ToTsQuery("english", keywords)))
    .ToListAsync();

var vectorResults = await vectorStore.Search(userQuery, k: 20);

// Merge using Reciprocal Rank Fusion (RRF)
var merged = RRF.Merge(keywordResults, vectorResults, k: 5);

Se Hybridsökning & Auto-Indexering för en komplett implementation.

steg 4: mäta skillnaden

spåra dessa mätvärden före och efter

public class RAGMetrics
{
    public int PromptTokens { get; set; }           // Should drop by 80-90%
    public int CandidatesRetrieved { get; set; }    // Should drop from 50+ to 5-10
    public TimeSpan QueryLatency { get; set; }      // Should improve
    public bool FiltersEnforced { get; set; }       // Should be true
    public List<string> EvidenceSources { get; set; } // Should be traceable
}

tumregler

Om ditt system är beroende av att alltid

Pattern-kaart

Intens Gör RAG förutsägbar, , billigt,
Krafter
Lösningen Extraherar signaler när → tvingar begränsningar deterministiskt ♫ → ♫ tar fram bevis ♫→ ♫ låter LLM syntetiseras i ett budget ♫
Konsequenser Mer ingenjörskonst i förspetsningen

Executive summary: Reduced RAG mental model

Reduced RAG är anti--, anti-LLM och anti-'.

Tänk på det så här.

Traditional RAG = "LLM, here's 50 chunks. Figure out what matters and answer."
Reduced RAG    = "Database, filter to 100. BM25, find keywords. Vector, find similar.
                  Now LLM, here are the 5 most relevant sources. Synthesize an answer."

Nyckeln:

  • Från: LLM som orakel ( gör allt
  • Till: LLM som syntetisk motor ( gör en sak bra

Primitiverna:

  1. Signaler (deterministisktM SK1 - datum, kategorierMST4 poängM ST5 filter
  2. Evidens (text) - vad du visar till LLM
  3. Begränsningar (gränserM SK1 - tokenbudjets

Pattern:

  • Extrahera signaler en gång (ingestion
  • Filterar deterministiskt (databaser är bra på detta
  • Sök hybrida (BM25 + vektorerM SK3
  • Syntesize bounded (kleine bevispaket → LLM)

Det är vad som händer när man tillämpar en vanlig mjukvaruingenjörskonst på system som råkar inkludera språkmodeller.

Nästa steg

Om du är redo att bygga den här

  1. Börja enkelt: Lägg till ett strukturerat fält (CreatedDate) och ett databasfilter
  2. mät först: Spurtoken räknas innan/efter
  3. Lägg till hybridsökning: Implementera BM25 M SK1 Vektor med RRF (vägledning här)
  4. Bygg i stegvis form: Att inte göra om allt på en gång

Referensimplementeringar:

Infrastrukturen finns redan där.

logo

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