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
Thursday, 08 January 2026
Se siete nuovi a RAG, iniziate con RAG spiegato e L'architettura RAG. Questo post è per il punto in cui ' hai costruito una pipeline RAG. In gran parte. funziona… e ora voi'la paghiamo in costi , fragilitàM SK3 e MSC4perche' ha risposto a questo?
Cosa si tratta: Il modello architettonico dietro la produzione RAG. Per le maniM SK1 per l'implementazione, vedete Costruire un Summarizer di Documento con RAG.
Da dove viene: Ho costruito. DocSummarizer (Document RAG engine), DataSummarizer (Motore RAG dei dati), ImageSummarizer (Motore RAG per immagini), AudioSummarizer (Motore audio RAG), e lucidRAG (multiM SK1documento Q &A). Lo stesso schema continuava a emergere tra i documentiMST4 datiMst5 immaginiMSt6 e audioM st7
NOTA: Potreste aver notato con ragione che la ricerca semantica su questo sito è rottaM SK1e sì, è una questione di configurazione non ho ancora'non ho avuto tempo di riparare ancora . Non è una brutta teoria MSC5
| Term | Cosa significa | Esempio S | ||
|---|---|---|---|---|
| RAG | Retrieval-Augmented Generation | Dare un LLM ai documenti della vostra azienda prima di rispondere. | ||
| Laggiù. | Dividere i documenti in pezzetti più piccoli | Trascinare un PDF in paragrafi | ||
| Top-k | Ottene i risultati di una ricerca "best" mostrami le parti più rilevantiM SK6 SSK7 | |||
| La ricerca dei vettori | Trovare un testo simile usando degli embeddings. | |||
| BM25 | Cercare le parole chiave | "Trovare documenti che contengano SSK3timeout' E 'databaseM SK6 | ||
| La finestra di contesto | Quanti testi si possono inserire in un prompt | Finito e costoso | ||
| I segnali | I fatti estrattos senza intelligenza artificiale | "CreatoM SK3 | 2025-01-15", \ "Priorità: Alto |
Retrieval-Augmented Generation M SK1RAG) è diventata una di quelle frasi che significa Tutto e niente..
Per un sacco di squadre, M SK1il fare il Reggamento Razionale” è oraMSC3
Funziona. Finché non succede’t.
’ costoso , difficile da ragionare sulla ’ molto difficile da razionalizzare sulla , e quietemente dà responsabilità al modello L': analizza la struttura Il , imposisce i filtri La , decide cosa importa Le , riconcilia le contraddizioni E si fida di ciò
Quando le persone dicono “RAG halucinazioni” o “RAg non filtra beneM SK3MSC4 si accusano di sbagliare la componente
Il problema è’t RAG. Il problema è questo. RAG pigri.
Questo post descrive un'altra opzione implicita: RAG ridotto - usa LLM meno, non piùM SK1 extraendo segnali deterministici in anticipo e trattando i modelli come Motori di sintesi, non I negozi di dati..
Una finestra di contesto è:
Non è un database.
Quando “ si mette solo più nella barra ”, si chiede al modello di:
Questo è il motivo per cui le demo RAG sembrano grandiose e i sistemi di produzione rallentano silenziosamente.
Rallentato RAG ribalta il tasto predefinito.
Invece di:
Trovare il testo e lasciare che il modello decida cosa conta.
Lo fai:
Decidere cosa importa una volta, lo immagazzinare, e coinvolgere il modello solo quando si ha bisogno di sintesiM SK2
In pratica significa: Ingestione deterministica, ricavamento economico, generazione confinata.
Se sembra familiare, è la stessa forma del sistema di ’ Fuzzinesse limitata: lasciare componenti probabilistici Proporre; lascia sistemi deterministici Decidere..
Prima, lasciate vedere cosa fanno la maggior parte delle squadre e perché è costoso.
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
Problenze:
Ora qui' è l'approccio RAG ridotta:
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
Principali differenze:
| Fase | RAG tradizionale | RAg ridotta M | ||||
|---|---|---|---|---|---|---|
| Ingestione | Semplicemente tagliare e inserirlo | Date di extrazione, categorieM SK3 entitàMSC4 bandiere di qualità | ||||
| La filtrazione | Chiediamo al LLM di filtrare nella risposta | Database Dov'erano le clause | ||||
| Cercare | Solo vettore | BM25 + Vector SSK4 Filtri strutturati S | ||||
| Il ruolo di LLM | ParseM SK1 filter, E la risposta | Semplicemente sintetizzare la risposta | ||||
| Costo | Ogni domanda paga per il contesto completo | Ingestione una volta | , | Queries a buon mercato |
Al momento dell'ingestione, analizzate quello che potete fare. senza Un LLM.
Esempio: Support Ticket System
Invece di scarabocchiare i biglietti nel testo:
Traditional: "Ticket #1234: Customer complained about slow loading..."
→ Embed entire text
→ Hope the LLM figures out it's about performance
Estrae segnali in anticipo:
// 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
};
Cosa si può estrarre deterministicamente:
| Tipo di segnale | Esempi | Perché conta S | ||
|---|---|---|---|---|
| Temporale | Data creata, data aggiornataM SK2 data di uscita | |||
| Cattericale | StatusM SK1 priorità, departamentoMSC3 prodotto | "Filter to Mobile team ticketsMST6 | ||
| Numerico | PrezzoM SK1 Quantità , punteggio, fiducia | S"Sortire per gravitàMSC6 | ||
| Identità | AutoreM SK1 ID del cliente , SKU, bolletta | Invoice | # | |
| Calità | Confidenza OCRM SK1 auto-la bandiera generata. | |||
| Provenenza | Il sistema di fonte, il percorso del fileM SK2 l'URL. |
Lo fate una volta. Tenere l'output. CheM SK2 è il substrato su cui il vostro sistema può contare .
La parte dura del RAG è: ' non è il modello, -, ma "M SK2" è tutto prima del modello. Per le implementazioni concrete, consultate Costruire un Summarizer di Documento con RAG e DocSummarizer: Costruire reti RAG.
Invece di trattare "chunksM SK1 come l'unità della verità , archiviare campi strutturati, segnaleMSL4unità denseMSR5 inserzioniMsl6 e indizi di ritorno alla fonteMLS7
Il testo è ancora parte del sistema - ma diventa La prova., non " qualunque cosa ci sia capitato di inserirci nella prompt.
Questa è la differenza tra le risposte "RAG sono vibrazioniM SK1 e "RAg sono invisibili".
Non lo fai'tM SK1 Non in anticipo.
Quello è l'intero punto di conservazione. segnali grezzi. invece di LLM-summari processati.
RAG tradizionale ( costoso da cambiareM SK1
// ❌ 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!
RAG ridotta ( economico da cambiare):
// ✅ 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')
");
Cos'è successo?
Questo è lo stesso schema di:
La regola: Ricordate bene. prima. LLM. aggiornate il vostro "memoryM SK2 (logica di recuperoMSC4 gratuitamente
Principali benefici architettonici: Evolvabilità. Poiché si immagazzinano segnali deterministici insieme agli inserzioni (non in cambio di loro), ogni parte del sistema può cambiare indipendentementeM SK2 scambiare modelli di inserzioneMSC3 ReMST4 inserire senza toccare i segnaliMst5 aggiungere un nuovo segnaleMSt6 calcolarlo dal testo immagazzato senza riM st7 inserirloMstr8 classificare le tonalitàM str9 regolare il peso dei segnali e la logica delle punteggi senza riindexareMtr10
Con i multi store -vector (come Qdrant), si può anche aggiungere molti inserimenti per ogni documento.. Voglio provare un nuovo modello di embedding? L'addizionare al modello esistente e gradualmente passare a un altroM SK2 Testare sia nella produzione , confrontare la qualità M SK4 poi deprecare l' vecchio - tutto senza riindexare o disturbare il servizioMSC6
Ogni componente può evolvere senza costringere a ricostruire un intero tubo - e senza degradare gli altri .
Gestire qualsiasi cosa si possa calcolare. in modo economico e deterministico..
Importante: I segnali sono solo. Short text strings, numbers, and booleans—non strutture enormi di datiM SK1 Voi'ste in archivio "PerformanceMSC4 (8 carsMST6 non SST7Il cliente si è lamentato dei tempi di caricamento lentiMSST8 ♫MST9 paroleMSS10
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
}
Comparisone dei costi di conservazione:
| Quello che si conserva | dimensione per documento | S10k Documenti SSK4 |
|---|---|---|
| Il testo completo | ||
| Tutti questi segnali. | ||
| LLM-riassunto generato |
I segnali sono: 10x più piccolo più del testo, 4x più piccolo più dei sommimenti LLM, e infinitamente più economico. per ricomputare (perche' non c'è bisogno di un LLM
Quando vi rendete conto che avete bisogno di un segnale diverso: Semplicemente calcolarlo da dati scarsi memorizzati. La memorizzazione è economicaM SK1 LLM inferenza è costosa.
Questo è il motivo per cui "over -extractionM SK2 è sicuro: pagate una volta nel magazzino (negligibileMSC5 non ripetutamente in inferenza S(substantialeMST7
La maggior parte delle domande "RAG" sono davvero domande di ricerca con restrizioni.
RAG tradizionale (economico,inaffidabileM 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
RAG ridotto (economico,deterministaM 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}
");
Cos'è successo?
Ecco perché la ricerca ibrida è importante nella produzione. La ricerca ibrida & Auto-Indexing è il pezzo più pratico di tutta la serie RAG.
Se una domanda è veramente confusa, voi Possiamo fare un po' di più. Usate un piccolo modello per estrarre l'intenzione/filtri M SK1comparare vs spiegare vs risolvere problemi"):
// 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();
Principio fondamentale: Il LLM propone, la validazione della strata deterministicaM SK2
Questo è il fondamento del Fuzzinesse limitata schema.
Per approfondire gli schemi di esecuzione ephemeri in cui si usano LLM temporaneamente senza continuare a produrre i loro output, vedete Fire and Don't Quite Forget.
Solo dopo la ricerca chiamate il LLM. Gli date un piccolo set di fatti esplicitato con indicatori di prove e chiare istruzioni sull'incertezza.
Il modello' il lavoro: sintetizzare, spiegare , confrontare. Non: impostare restrizioni, decidere la verità, inventare la struttura.
Se ti importa di “LLMs trascinare l'intera finestra del contesto nella risposta ”, tu’ hai già visto il modo di fallimentoM SK3 l'ho chiamato esplicitamente in Dragging Contexto Fuzzy Constrained: è il ’ non è malizioso - è quello che l'avete chiesto di fare.
ordinato-diM SK1comparazione di grandezza per un tipico sistema RAG di supporto al cliente:
Scenario: 10,000 biglietti di supportoM SK1 1,000 domande al giorno
| Approco | Costo dell'ingestione | Per -Cosito della domanda M | Cosito giornaliero R | ||
|---|---|---|---|---|---|
| RAG tradizionale | inserire 10k biglietti | S50 frammenti M× grande contesto R | $75/ giorno | ||
| RAG ridotto | inserirlo + estrarre i segnali**$7.50/ giorno** |
ordine di grandezza: ~10x riduzione di costo al giorno
Ancora meglio: Con buone prove e filtri deterministici, probabilmente non c'è bisogno di un modello di frontieraM SK2 Un modello Ollama locale (freeMSC4 con una piccola serie di prove spesso supera il GPTMST5 alimentato 50 pezzi che deve analizzare da soloMSL7
Plus: tempo di debugging ridottoM SK1 meno escalazioni di supporto , e flessibilità del modello (modelli di scarico senza cambiamenti architettoniciMSC4
RAG tradizionale (hopeM SK1filtrazione basata):
// ❌ Prompt says "only UK customers" but model can ignore it
var answer = await llm.Generate(prompt); // No guarantee
RAG ridotto (filtrazione forzata):
// ✅ Database physically prevents non-UK results
var results = db.Tickets.Where(t => t.Region == "UK"); // Guaranteed
Perché è più sicuro? I filtri sono impossiti prima della generazione ( il modello non li possedeva mai , non può' non li dimenticareM SK3 e le allucinazioni sono limitate dalle prove che controlli.
Traditionale RAG: "Il modello ha detto questo , ma ioM SK2 non sono sicuro di quale motivo o quale pezzo viene da."
RAG ridotto:
// 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
};
Potete controllare perché ogni risultato è corrispondente, mostrare prove quando la fiducia è bassaM SK1 e debugre problemi di produzione esaminando il gruppo di candidati prima della sintesi LLM.
Se avete già un sistema RAG funzionante, quiM SK1s come migrare:
Prima:
public class Document
{
public string Id { get; set; }
public string Text { get; set; } // ← Only unstructured text
public float[] Embedding { get; set; }
}
Dopo:
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
}
Prima:
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
Dopo:
// ✅ 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
// 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);
Vedete. La ricerca ibrida & Auto-Indexing per una completa implementazione.
Tracciare queste misurazioni prima e dopo:
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
}
Se il vostro sistema dipende da sempre-window di contesto più grandi per rimanere accuratiM SK1 non avete' nessun problema di ricavamento . avete un problema di ingestioneMSC4
| Intenzione | Rendere il RAG prevedibile, economicoM SK2 e debuggerabile |
| Le forze | Costi di moneta elevatiM SK1 filtrazione debole, allucinazioni silenziose , battute non codificate SSK4 |
| Soluzione | Estraggono i segnali una volta che → impongono delle restrizioni deterministicamente ♫ → catturano prove ♫→ permettono al LLM di sintetizzare entro un budget ♫ |
| Le conseguenze | Più ingegneria all'inizio; un comportamento operativo molto migliore |
La RAG ridotta non è l'anti-', ma l' anti--, l'LLM, il . e l'Anti-M SK3.
Pensateci così:
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."
Il cambio:
I primitivi:
Il modello:
È quello che succede quando si applica una normale disciplina di ingegneria software a sistemi che includono modelli linguistici.
Se siete pronti a costruire questo
Implementazioni di riferimento:
L'infrastruttura è già lì. Dovete solo smettere di trattare la finestra del contesto come una base di dati
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.