# Reduced RAG: Stop Stuffing Context Windows and Start Extracting Signals

<datetime class="hidden">2026-01-08T19:00</datetime>

<!-- category -- AI, RAG, LLM, Architecture, Semantic Search -->
Якщо ви – МСК0 – абсолютно нова людина в РАГ, – МSK1 – почнете з [RAG пояснює](/blog/rag-primer) і [Архітектура РАГ](/blog/rag-architecture). Це пост для того моменту, коли ви ' збудували трубопровод RAG, який *переважно* працює, а тепер ви платите за нього за ціною.

**Що це охоплює:** Архітектурна модель, яка стоїть за виробництвом РАГ. Для рукМSK1 для втілення МSK2 см. [Збудувати підсумовувач Dokumentу з РАG](/blog/building-a-document-summarizer-with-rag).

**Звідки воно походить:** Я створив [DocSummarizer](/blog/building-a-document-summarizer-with-rag) ( Машина документального RAG [DataSummarizer](/blog/datasummarizer-how-it-works) (Data RAG engineM SK1 [ImageSummarizer](/blog/constrained-fuzzy-image-intelligence) ( Машина з зображенням RAG МSK1 [AudioSummarizer](/blog/audiosummarizer-forensic-audio-characterization) (Аудио RAG двигунM SK1 і [lucidRAG](/blog/lucidrag-multi-document-rag-web-app) (multiM SK1документ QMSC2A). Те ж саме повторювалося в усіх документахMСК4 даніМСК5 зображенняM СК6 і аудіоMSК7

> NOTE: Ви, можливо, по правді помітили, що семантичний пошук на цій сайті заламаний ... і так, це МSK2 проблема з конфігурацією я не мав M SK3 ще не мав часу її виправити MSC4 Не погана теорія 🤓

## швидкий обновник термінології RAG

| Терм МSK1 Що це означає МSK2 Приклад |
|------|---------------|---------|
| **РАГ** | ПеретягуванняM SK1 Підвиширене генерування | Дання LLM вашій компанії доксів перед відповіддю МSK3
| **Зйомка** | Розділення документів на менші частини | Перетворення PDF в абзаци МSK2
| **Top-k** | Дайте мені найкращі МSK1 найкращеM SK2 результати із пошуку
| **Поиск вектора** | Найти подібний текст, використовуючи вбудовані додатки
| **BM25** | Поиск по ключевым словам
| **Окно контексту** | Скільки текстів можна помістити в проміжку?
| **Сигнал** МSK0 Факти, отримані без штучного інтелекту | МSK2 Створені : ♫ ♫ МSK4 ♫

Видобуток-Augmented Generation M SK1RAG) став одним із тих фрази, що означає *все і нічого*.

Для багатьох команд RAG: МСК0, МСК1, МSK2 тепер - МСК3

1. Дорожні документи
2. Вставляйте їх
3. Перейти нагору-k
4. Вставляйте все в про prompt
5. Спитайте модель: “визначати його

Це працює.
Доки це не станеться

Це: МСК0 - дорого, МСК1 - важко обдумати, МSK2 - важке, М СК3 - тихо зав 'язує відповідальність за модель. МСК4 - розшифровує структуру, МТК5 - встановлює фільтри, М АК6 - вирішує, що має значення, МУК7 - змирає протиріччя, МАК8 - впевнені в цьому, МДК9

Коли люди говорять: МСК0 , РАГ галюцинує, "”", або МСК2 , а РАГ , МСк3 , не добре відфільтровує, МС К4 , вони СМСК5 , зазвичай звинувачуються у неправильному компоненті

Проблема в тому, що
Проблема в тому, **ліничий РАГ**.

Цей пост описує інший за замовчанням: **Reduced RAG** - використовує LLM *менше*, не більшеM SK1 шляхом видобутку детермінативних сигналів наперед і лікування моделей як *двигуни синтезу*, не *крамниці даних*.

[TOC]

## Найважливіша помилка - : - в тому, що контекстні вікна сприймаються як накопичувані

Окно контексту це:

- тривалість
- не встромлений
- дорогою
- відраховується на кожному запиті

Це не сервер даних.

Коли ви “ просто залишаєте більше в проміжку ”, виM SK2 запитуєте модель

- re- кожнісінького разу аналізувати структуру
- вивести фільтри замість того, щоб їх впроваджувати
- підсумувати деталь, яку ви можете потребувати пізніше
- звучати впевнено навіть тоді, коли ’ помиляється

Ось чому демонстрації RAG виглядають чудово, і системи виробництва RAG спокійно гніздять.

## Що означає “Reduced RAGM SK1

Reduced RAG перевертає початковий параметр.

Замість:

> Візьміть текст і дозволяйте моделі вирішити, що має значення.

Ви робите

> Вирішуйте, що має значення, як тільки: , зберігайте його МSK1 і застосуйте модель лише тоді, коли вам потрібна синтез .

На практиці це означає: **детермінативний поглинання , дешеве відтворення, обмежена генерація**.

Якщо це звучить знайомо, то це те ж саме, що і в системі [Стримана неясність](/blog/constrained-fuzziness-pattern): дозволити можливим компонентам *запропонувати*; дозволити детерміністичним системам *вирішити*.

## Традиційна RAG проти скороченої RAG

Перш за все, давайте подивимось на те, що роблять більшість команд. І чому це дорого

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

**Проблеми:**

- LLM re- аналізує структуру кожного запиту
- Можемо' не впроваджувати фільтрів M SK1 тільки " гарно попросити МSK3 за допомогою пропону МSK4
- Скала витрат टोकена з запитами (↑ за запит )
- Галюцинації, коли модель вигадує фільтри

Тепер ось тут – МСК0 – підхід Reduced RAG – МSK1

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

**Головні відмінності:**

| Фаза МSK1 Традиційний RAG МSK2 Reduced RAG
|-------|----------------|-------------|
| **Поглинання** | Просто відрізаємо і вставляємо МSK1 Витягуємо дати МSK2 категорії МСК3 об 'єкти М СК4 qualitative flags |
| **Фильтрування** | Попросіть LLM відфільтрувати в проміжку | База даних, де clauses МSK2
| **Поиск** | Лише вектор МSK1 BMM SK2 МSK3 вектор
| **Роль LLM** | Розшифровуйте , фильтр МSK2 І відповідь МSK3 Просто синтезуйте відповідь \|
| **Ціна** | Кожне запитання платить за повний контекст МSK1 Введення одного разу МSK2 дешеві питання |

## Шаг 1: Детермінативний поглинання МSK1 нудний біт, який має значення

У часі вживання, аналізуйте, що ви можете *без* LLM.

**До прикладу: Система підтримки билетів**

Замість того, щоб просто скопіювати квитоки в текст

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

Витягувати сигнали наперед:

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

**Що ви можете отримати детерміністично:**

| Тип сигналу МSK1 Приклади МSK2 Чому це важливо |
|-------------|----------|----------------|
| **Тиморальний** | Data Created , Date Updated МSK2 expiry МSK3 СМСК4Only show last week ММСК5s errorsММСК6 | СМСК7
| **Категорічні** МСК0 СтатусМSK1 пріоритет, відділМСК3 продукт MСК4 МСК5Фильтер для мобільних командних билетів
| **Цифрове** МSK0 Цена МSK1 кількість МСК2 бал М СК3 впевненість М S К4 M С К5 Розподіл по значущості М Ш К6 | М С К7
| **Ідентичність** МСК0 АвторМSK1 ID клієнтаМСК2 SKUМ СК3 faktura MСК4 МСК5 ♫ ♫ МС К6 ♫ Всі билети від Klienta X ♫ MСК7 ♫
| **Якість** | впевненість в OCR МSK1 автоматичний МSK2генерований прапор | M"Виключити низький МСК5 впевненісти в ORC МСК6 \ \ |
| **Провенанс** | Źródłowа система , шлях до файлу МSK2 Адрес URL МSK3 M"Только з журналів виробництва МСК5 \МСК6

Зробіть це один раз. Утримуйте вихідні дані

**Найважчою частиною RAG є: МСК0 - це модель, МСК1 - це все, що було перед моделью** Для конкретних застосувань - МСК0 - см. [Збудувати підсумовувач Dokumentу з РАG](/blog/building-a-document-summarizer-with-rag) і [DocSummarizer: Проектування трубопроводів РАG](/blog/docsummarizer-rag-pipeline).

## Шаг 2: Поміщайте сигнали ( і зберігайте докази МSK2

Замість того, щоб сприймати "chunksMSC1 як одиниця правдиM SK2 зберігати структуровані поля, сигналMST4 щільні елементиM ST5 вбудованіM st6 і направляти назад до джерелаMst7

Текст досі є частиною системи -, але він стає **докази**, не " незалежно від того, що ми вставляли в про prompt

Це різниця між "RAG відповіддю є вібрами " і МSK2

### " Але як я знаю, які сигнали виділити

Ви не знаєте.

Це все, що потрібно для зберігання **сирові сигнали** замість LLM-розроблені підсумкиM SK1

**Традиційний RAG (невелика ціна на змінуM SK1**

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

**Reduced RAG (швидше мінятиM SK1**

```csharp
// ✅ 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')
");
```

**Що ж сталося?**

- Ви зберігали **більше сигналів, ніж вам потрібно** (швидкийM SK1
- Коли змінилися вимоги, ви **відраховані з накопичених сигналів** (бесплатноM SK1
- Ви не повторили' reM SK1 запустили LLM висновку на 10,000 документах ( дорогою МSK4 часом МSK5 споживаючим

Це той самий візерунок, як ":".

- **[DiSE (Direkted Synthetic Evolution)](/blog/dise-architecture-overview)** - зберігає результати тесту , історія мутацій M SK2 метрика якості . Коли ви змінюєте функцію оцінки MSC4 ви не змінюєтесь MSL5 не змінюєтеся МSK6 запускаєте еволюцію LLM MST7 ви змінюєтесь МST8 оцінюєте існуючі кандидати з накопичених сигналів МСТ9
- **[Розпізнавання Bot](/blog/learning-lrus-when-capacity-makes-systems-better)** - зберігає шаблони запитів , сигнали часу M SK2 вироки поведінки МSK3 коли ви налаштовуєте граничний рівень МSK4 M→ \0.4, ви не переобробляєте трафіку

**Правила:** Пам 'ятайте добре *до цього* LLM. Обновлюйте ваші "памятиM SK2 ( логіку отриманняMスク4 безкоштовноMSC5

**Найголовніша перевага в галузі архітектури: ЕволюційністьM SK1**
Через те, що ви зберігаєте детермінативни сигнали поруч з вмонтованими, ( не замість них ), кожна частина системи може змінюватися незалежно МSK2 Поміняти моделі вмонтування МСК3 Перезастосувати MСК4 вмонтувати без торкання сигналів М СК5 Додавати новий сигнал М סК6 обчислити його з зачуваного тексту без перезастосування M СК7 вміщати М S К8 Rangування туней М ็ С К9 Регулювати вагу сигналу та логіку оцінки без переindeksуванняМ С К10

За допомогою багатого-векторних магазинів M SK1подібно до Qdrant), ви можете навіть додати **багато вбудованих елементів на кожен документ**. Хочете спробувати нову модель вбудованого модуля ? Dodaj її до існуючої і поступово переходити на іншу M SK2 Випробувати як в процесі виробництва, так і в якості МSK3 порівняти якість , а потім відкинути стару MSC5 все без переindexування чи зруйнування сервісуМSK6

Кожна компонента може розвиватися, не вимушуючи повністю перебудувати трубопровод — і не зруйнуючи інших МSK1

### Які сигнали ви маєте зберігати?

Поміщайте все, що можна обчислити **дешево і детерміністично**.

**Важливо:** Сигнали просто **короткі текстові стрічки, цифриM SK1 і bool**— не гігантські структури данихM SK1 Ви' зберігаєте МSK3PerformanceMST4 МST5 charsM ST6 не M ST7Customer complained about slow loading timesM st8 ♫ M st9 ♫ wordsMst10 ♫

```csharp
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: "user@example.com"
    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
}
```

**Порівняння витрат на зберігання:**

| Те, що ви зберігаєте
|----------------|------------------|---------------|
| **Повний текст** МSK0 ~5 Кб МSK2 50 MB мSK4
| **Всі ці сигнали** МSK0 ~500 bajти МSK2 ♫ ♫ МSK3 ♫ MB ♫ |
| **Згенерований резюме LLM-** МSK0 ~2 Кб МSK2 20 MB мSK4

Сигнали **10x менший** ніж текст, **4x менший** ніж підсумки LLM, і **безмежно дешевше** щоб відновити ( тому що вам не потрібні

**Коли ви зрозумієте, що вам потрібний інший сигнал:** Просто обчислюйте це з накопичених необроблених даних. Утримка дешеваM SK1 Введення LLM дорогого.

Ось чому: " над- витяжка " безпечна МSK3 ви платите один раз в magazynі МSK4 незрозумілива M SK5 не повторюватись в припущеннях М SK6 суттєва ).

## Далі: 3: Поиск без LLM

Більшість "RAG запитів" насправді - це лише пошукові запити з обмеженнями

- " тільки останні DocsM SK1
- "только для споживачів ВеликобританіїM SK1
- " тільки платний планM SK1
- "только помилки минулого тижня

**Традиційний РАГ** (швидкийM SK1ненадійний ):

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

**Reduced RAG** (швидкийM SK1 детермінативнийМSK2

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

**Що ж сталося?**

- База даних відфільтрована детерміністично: (не LLMM SK1
- LLM бачить вихідні коди 5 замість МSK1 МSK2 знизування символів
- Filtrи гарантовані, не M SK1запропонованіМSK2

Ось чому гібридні пошукові системи важливі для виробництва. [Гібридне пошук & АвтоM SK1 Індексування](/blog/rag-hybrid-search-and-indexing) є найпрактичнішою частиною всієї серии RAG

### Опціонально: Використовувати LLM для отримання наміру M SK1 як пропозицію)

Якщо питання справді безладно, *їжа* використовувати маленьку модель для отримання наміру/фільтри M SK1порівняти vs пояснити vs розв 'язати проблему

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

**Головний принцип: LLM запропонує , детермінативний шар підтверджує МSK2**

Це основа [Стримана неясність](/blog/constrained-fuzziness-pattern) шаблон.

Для глибшого поглинання ефемерних шаблонів виконання, де ви використовуєте LLM тимчасово, не залишаючи їх вихідних даних, читайте [Огонь і не забувай](/blog/fire-and-dont-quite-forget-ephemeral-execution).

## Шаг 4: ЛЛМ як синтезові двигуни МSK1не судді МSK2

Лише після пошуку ви називаєте LLM. Ви даєте йому невеликийM SK1 яскравий набір фактів з точки зору доказів та чіткими інструкціями щодо невизначеності .

Модель ' робота: **з 'єднати, пояснитиM SK1 порівняти**. Ні **нав 'язувати обмеження МСК0 вирішувати правду МSK1 розробляти структуру**.

Якщо вас хвилює те, що “LLMs перетягує весь контекстний вікно в відповідь ”, ви M SK2 вже бачили режим непрацездатності [Перетягування обмеженого неясного контексту](/blog/constrained-fuzzy-context-dragging)МСК0 це ’ не злодісний - Це МSK3 те, що ви попросили його зробити

## Чому це безпечніше? *і* дешевше

### Порівняння витрат (ілюстраційний прикладM SK1

Заказ-зM SK1порівняння величини з типичною системою RAG для стосунків з клієнтами:

**сценарій:** 10,000 билети на підтримку

| Дохід МSK1 Koszt поглинання МSK2 За МSK3Koszt запиту | Костанція щоденна
|----------|----------------|----------------|------------|
| **Традиційний РАГ** | Вставляйте МSK1 квитоки МSK2 50 фрагменти ♫ × ♫ великий контекст ♫ МSK5 ♫ ♫**$75/день** |
| **Reduced RAG** | Вставляйте МSK1 виокремлює сигнали МSK2 5 фрагменти ♫ ♫ МSK4 ♫ маленький контекст ♫ | ♫**$7.50/день** |

**Ордер величини:** ~10x зниження витрат на день

**Ще краще:** З хорошими доказами та детермінативним фильтруванням, ви, напевно, не потребуєте ' взагалі кордонної моделіM SK2 локальна модель Оллами (свободнаMSC4 з невеликим набором доказів часто перевершує GPT МSK5 покритий МSK6 шматочки, які йому треба розібрати самісінько

plus: скорочення часу debuggingу , менше ескалацій підтримки МSK2 і гнучкість моделей M SK3 відхилення моделей без змін в архітектурі

### Надежність

**Традиційний РАГ** (надіюсьМSK1фільтрування на основіM SK2

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

**Reduced RAG** (вказований фильтруванняM SK1

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

**Чому це безпечніше?** Фильтры встановлені перед наступним поколінням. (модель ніколи їх не власна, МSK1 не може, ♫ ♫ МSK2 ♫ не забуває про них, ♪ ♫ ), ♫ а галюцинації обмежені доказами, які ви контролюєте ♫

### Пояснення

**Традиційний РАГ:** " Модель сказала: "" МSK1 "", але я не впевнена, чому чи з якого шматка вона взялася.

**Reduced RAG:**

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

Ви можете перевірити, чому кожен результат збігається, показати докази, коли рівень довіри низькийM SK1 і виправити проблеми виробництва, вивчаючи набор кандидатів перед синтезом LLM.

## Почнемо з : Переробка традиційного МSK1 зменшена РАG

Якщо ви вже маєте працюючу систему RAG, тутM SK1s як мігрувати:

### Шаг 1: Додайте структуровані поля до вашого впиту

**До:**

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

**Після:**

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

### Шаг 2: Переміщувати фильтры з про prompts , до запитів

**До:**

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

**Після:**

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

### Шаг 3: Dodaj гібридну пошукову функцію

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

Подивіться [Гібридне пошук & АвтоM SK1 Індексування](/blog/rag-hybrid-search-and-indexing) для повного втілення.

### Шаг 4: виміряти різницю

Прослідкувати ці показники до і після:

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

## Правило палець

Якщо ваша система залежить від будь-коли- більші контекстні вікна, щоб залишатися точним , ви не маєте МSK2 у вас немає проблеми з отриманням МСК3 у Вас є проблеми з поглинанням М СК4

## Карта з патернами

| | |
|---|---|
| **Намір** | Робіть RAG передбачуваним , дешевим МSK2 і деbugованим МSK3
| **Сили** | високі ціни на символи МSK1 слабке фільтрування МSK2 мовчазні галюцинації , необібрані пропони
| **Рішення** | Витягувати сигнали, як тільки МSK1 встановлювати обмеження детерміністично МSK2 дістати докази → дозволити LLM синтезувати в межах бюджету ♫ |
| **Наслідки** | Ще більше інженерії на передній плані ; значно кращий операційний підхід МSK2

---


## Підсумок: Снижена модель розуму RAG

Снижена РАГ не є анти-', а анти-МSK1, ЛЛМ, МSK2, а проти-МСК3, МСК4, відходів, М СК5.

Подумайте ось так.

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

**Переміщення:**

- **З:** LLM як оракль ( робить всеM SK1
- **На:** LLM як синтезний двигун ( робить одну річ добре )

**Примітивів:**

1. **Сигнал** (детерміністичнеM SK1 МSK2 даті МSK3 категорії , бали М SK5 фильтры
2. **Докази** МSK0текст) МSK2 те, що ви показуєте LLM
3. **Обмеження** (межні кордони ) МSK2 бюджети टोकенів МSK3 фільтроваvaliдація М SK4 вимоги щодо цитацій

**Модель:**

- Виймайте сигнали один раз (ingestionM SK1
- Фильтрування детерміністично (databases are good at this
- Поиск гібридних векторів (BMM SK1 +
- Синтезований обмежений (маленький пакет доказів → LLMM SK2

Це те, що відбувається, коли ви застосовуєте звичайну технічну дисципліну до систем, які включають мовні моделі

## Наступні кроки

Якщо ви готові побудувати цей

1. **Почнемо з простого:** Додайте одне структуроване поле (CreatedDateM SK1 і один фильтр бази даних
2. **Спочатку виміряти:** Токен треку рахується до/за
3. **Dodaj гібридний пошук:** Втілити вектор BM25 M SK1 з РР МSK2[тут](/blog/rag-hybrid-search-and-indexing))
4. **Збудувати поступово:** Не змінюйте все відразу

**Референції implementations:**

- [DoomSummarizer: Глубокі дослідження](/blog/doomsummarizer-deep-research) - Reduced RAG in practice МSK1 МSK2signal RRF fusion , entity profilesM SK4 semantic graph discovery, and parallel longMNK6form synthesis МСК7 all from a single binary
- [Збудувати підсумовувач Dokumentу з РАG](/blog/building-a-document-summarizer-with-rag) - Практичний шлях до втілення
- [ruра DocSummarizer RAG](/blog/docsummarizer-rag-pipeline) - Повний канал поглинання
- [AudioSummarizer](/blog/audiosummarizer-forensic-audio-characterization) - Озвучно-судебне охарактеризування з диарізацією гучномовця
- [lucidRAG](/blog/lucidrag-multi-document-rag-web-app) - Полна веб-програма з гібридним пошуком
- [StyloFlow: Сигнальний сигнал-Driven Workflows](/blog/styloflow-signal-driven-workflows) - Оркестраційний двигун для багатоповерхових труб РАG з умовною вправою та ескалацією
- [Стримана неясність](/blog/constrained-fuzziness-pattern) - Побудована модель

Інфраструктура вже там. Потрібно просто припинити розглядати контекстне вікно як базу даних.