Back to "DocSummarizer Part 4 - Проектування трубопроводів RAG"

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 C# Embeddings LLM ONNX RAG Semantic Search

DocSummarizer Part 4 - Проектування трубопроводів RAG

Tuesday, 30 December 2025

NuGet npm .NET Node.js

Це Частина 4 з серії DocSummarizer. Погляньте Частина 1 для архітектури, Частина 2 для інструмента CLI, або Частина 3 для глибоких занурень на вбудовах.

Гарна частина RAG - це МСК0 , а не ЛЛМ . ".". Це МСК2 - це все, що було до LМ , і так далі.

Ви, мабуть, бачили цю модель. МСК1 - розділити документи на шматочки. МSK2 - генерувати вбудовані додатки. , - зберігати їх у векторній базі даних.

  • Дослідники для кожного формату
  • Логіка, яка поважає семантичні межі
  • Токенізація, яка відповідає вашій моделі вбудованості
  • Batching для ефективного генерування вбудованих
  • Оцінки за доброту, так що не всі шматочки ставляться однаково
  • Прослідження цитат, щоб ви знали, звідки прийшли відповіді

Це - багато інфраструктури, перш ніж написати один ряд коду застосування.

DocSummarizer.Core обробляє все це в одному пакеті - доступний для обох систем: .NET та Node

DocSummarizer.Core є по суті здатність документувати: детерміністична структура по-перше

Трубопровод запилення

Ось що робить DocSummarizer: doesn't do:

flowchart TB
    subgraph INPUT["Input (Your Document)"]
        DOC[/"PDF / DOCX / Markdown / HTML / URL"/]
    end
    
    subgraph DOCSUMMARIZER["DocSummarizer.Core (Deterministic)"]
        direction TB
        PARSE["Parse & Structure"]
        SEGMENT["Segment by Semantics"]
        EMBED["Generate Embeddings<br/>(ONNX - Local)"]
        SCORE["Compute Salience"]
        CITE["Assign Citation IDs"]
        
        PARSE --> SEGMENT
        SEGMENT --> EMBED
        EMBED --> SCORE
        SCORE --> CITE
    end
    
    subgraph OUTPUT["Output (ExtractionResult)"]
        SEGMENTS[/"Segments[]<br/>• Original text (verbatim)<br/>• float[384] embedding<br/>• Salience score<br/>• StartChar / EndChar<br/>• Section context"/]
    end
    
    subgraph YOURS["Your Code"]
        STORE[("Vector Store<br/>(Qdrant / pgvector / etc)")]
    end
    
    subgraph QUERY["Query Time (Later)"]
        Q["User Question"]
        RETRIEVE["Retrieve Top-K"]
        LLM["LLM Synthesis"]
        ANS["Answer + Citations"]
        
        Q --> RETRIEVE
        RETRIEVE --> LLM
        LLM --> ANS
    end
    
    DOC --> PARSE
    CITE --> SEGMENTS
    SEGMENTS --> STORE
    STORE --> RETRIEVE
    
    style DOCSUMMARIZER stroke:#27ae60,stroke-width:3px
    style YOURS stroke:#3498db,stroke-width:2px
    style QUERY stroke:#9b59b6,stroke-width:2px
    style LLM stroke:#e74c3c,stroke-width:2px

Що робить DocSummarizer (зелена скринькаM SK1

  • Розшифровує документи, зберігаючи структуру
  • Розділюється на семантичні сегменти (не довільні шматочкиM SK1
  • генерує вбудова локально за допомогою ONNX
  • Вираховує показники salience
  • Приписує ідентичні знаки цитацій з позиціями символів

Що ви робите (блакитна скринькаM SK1

  • Поміщайте сегменти в вашій векторній базі даних
  • Збудувати логіку пошуку

Що відбувається в часі запиту (пурпурна скринькаM SK1

  • Вставляйте питання (та сама модельM SK1
  • Згадайте подібні сегменти
  • Посилати на LLM для синтезу

Ключеві ідеї: LLM ( червона межа МSK1 залучена лише в час пошуку МSK2 Введення є повністю детерміністичним - один і той самий документ завжди виробляє ті самі сегменти

Бонус на репродукцію: Детерміністичне втягування означає, що ви можете переглянути схему RAG0, індикцію ,, дифференцію МSK2 і деbugувати її так само, як будь-який інший будівельний артефакт.

Чому немає LLM для вживання?

Для RAG, ви хочете справжні речення з ваших документів. - не LLM.

LLM з 'являється пізніше , у часі запиту, для синтезу відповіді з отриманих фрагментів МSK2 Але самі фрагменти мають бути дослівним джерелом M SK3 Це те, що makes citations meaningful .

DocSummarizer's ExtractSegmentsAsync дає вам саме це: оригіналні текстові сегменти з вбудовами, готовий до відтворенняM SK2 Ніяких LLM, що брали участь у поглинанні .

Пропозиція цінності

Ось що ви отримуєте з ним dotnet add package:

dotnet add package Mostlylucid.DocSummarizer
  • Розумна сегментація - Розриви на заголовкахM SK1 визначає семантичні межі
  • Вбудова в систему ONNX - локальний , без API ключів M SK2 моделі автоматизовані МSK3 завантажити МSK4 МБ МСК5
  • Оцінка за доброзичливість - ДоM SK1 обчислюваність важливості для кожного сегменту
  • Переслідування цитат - Кожен сегмент має унікальну ID
  • Багато форматів - Марка-даун МSK1 HTML МSK2 PDF , DOCX
  • Опції для зберігання вектора - InMemory , DuckDBM SK2 Qdrant built-in

Ні Pythonа. Ні зовнішніх APIM SK1 Ні складної настановки . Працює в офлайні після першого завантаження моделі МSK3

Витягування сегментів: Кораовий API

Найпростіший застосовний випадок - виділення сегментів з вбудовами, готових для вашого векторного магазину

using Microsoft.Extensions.DependencyInjection;
using Mostlylucid.DocSummarizer;

// Setup DI
var services = new ServiceCollection();
services.AddDocSummarizer();
var provider = services.BuildServiceProvider();

var summarizer = provider.GetRequiredService<IDocumentSummarizer>();

// Extract segments with embeddings
string markdown = File.ReadAllText("document.md");
var extraction = await summarizer.ExtractSegmentsAsync(markdown);

foreach (var segment in extraction.AllSegments)
{
    Console.WriteLine($"[{segment.Type}] {segment.SectionTitle}");
    Console.WriteLine($"  ID: {segment.Id}");
    Console.WriteLine($"  Salience: {segment.SalienceScore:F2}");
    Console.WriteLine($"  Embedding: float[{segment.Embedding?.Length}]");
    Console.WriteLine($"  Text: {segment.Text[..Math.Min(80, segment.Text.Length)]}...");
}

Виход:

[Heading] Introduction
  ID: a1b2c3d4e5f6g7h8_h_0
  Salience: 0.85
  Embedding: float[384]
  Text: This document describes the architecture of our new microservices platform...

[Sentence] Introduction  
  ID: a1b2c3d4e5f6g7h8_s_1
  Salience: 0.72
  Embedding: float[384]
  Text: The system is designed to handle 10,000 requests per second with sub-100ms...

МSK0 - це воно, МSK1 - без оркестрування, МСК2 - без пропону, М СК3 - без думки, M СК4 - лише сегменти з вбудовами та провинцією, М S К5 - готовий до вашої векторної бази даних

Іденти dokumentu

Кожен сегмент's Id збудований з ID-документу плюс тип та індекс: {docId}_{type}_{index}.

Ви можете запропонувати власний документ ID, або дозволити DocSummarizer обчислити один із контенту hash:

// Option 1: Provide your own ID (useful for tracking documents in your system)
var extraction = await summarizer.ExtractSegmentsAsync(markdown, documentId: "contract-2024-001");
// Segments get IDs like: contract_2024_001_s_0, contract_2024_001_h_1, ...

// Option 2: Auto-generated from content hash (default)
var extraction = await summarizer.ExtractSegmentsAsync(markdown);
// Segments get IDs like: a1b2c3d4e5f6g7h8_s_0, a1b2c3d4e5f6g7h8_h_1, ...
// Same document = same hash = same IDs (deterministic)

Чому це важливо для РАГ:

  • Custom ID дають змогу співвідносити сегменти з системою управління документами
  • Конtent-hash IDs гарантують, що реM SK1indexування одного й того ж dokumentu виробляє ідентичні ID сегментів
  • Обидві методи підтримують стабільні цитації - [s42] завжди вирішує до того ж джерела тексту

Що в сегменті

Кожен виділений сегмент містить все, що вам потрібно для RAG:

public class Segment
{
    string Id;              // Unique ID: "mydoc_s_42" (for citations)
    string Text;            // The actual content
    SegmentType Type;       // Sentence, Heading, ListItem, CodeBlock, Quote, TableRow
    int Index;              // 0-based order in document
    
    // Source location tracking
    int StartChar;          // Character offset where segment starts
    int EndChar;            // Character offset where segment ends
    int? PageNumber;        // Page number (for PDFs)
    int? LineNumber;        // Line number (for text/markdown)
    
    // Section context
    string SectionTitle;    // "Introduction" - immediate heading
    string HeadingPath;     // "Chapter 1 > Introduction > Overview"
    int HeadingLevel;       // 1-6 (heading depth)
    
    // Computed during extraction
    float[] Embedding;      // 384-dim vector (default model)
    double SalienceScore;   // 0-1 importance score
    string ContentHash;     // Stable hash for citation tracking across re-indexing
    
    // For retrieval (set during query)
    double QuerySimilarity; // Similarity to the query
    double RetrievalScore;  // Combined score: similarity + salience
    
    string Citation { get; } // Auto-generated: "[s42]", "[h3]", etc.
}

І Id це ключ до відстеження цитат. Коли ваш LLM виводить [s42], ви можете повернути його до точного місця джерела за допомогою StartChar/EndChar.

Бонус: І ExtractionResult включає в себе допоміжні методи для відтворення цитацій:

var extraction = await summarizer.ExtractSegmentsAsync(markdown);

// Fast O(1) lookups
var segment = extraction.GetSegment("mydoc_s_42");
var segmentByIdx = extraction.GetSegmentByIndex(42);

// Find segment at a character position
var segmentAtPos = extraction.GetSegmentAtPosition(5432);

// Get all segments on page 5 (for PDFs)
var pageSegments = extraction.GetSegmentsOnPage(5);

// Get source location for highlighting
var location = extraction.GetSourceLocation("mydoc_s_42");
// Returns: StartChar, EndChar, LineNumber, PageNumber, SectionTitle, HeadingPath

// Extract highlighted text with context
var highlight = extraction.GetHighlightedText(originalMarkdown, "mydoc_s_42", contextChars: 50);
Console.WriteLine(highlight.ToHtml());  // <span class="highlight">...</span>
Console.WriteLine(highlight.ToMarkdown()); // **...**

Введення в векторні магазини

DocSummarizer дає вбудовані додатки. Використовуйте будь-яку векторну базу даних, яку хочетеM SK1

Кдрант

var points = extraction.AllSegments.Select((s, i) => new PointStruct
{
    Id = (ulong)i,
    Vectors = s.Embedding,
    Payload = 
    {
        ["text"] = s.Text,
        ["section"] = s.SectionTitle,
        ["salience"] = s.SalienceScore,
        ["segment_id"] = s.Id,
        ["start_char"] = s.StartChar,
        ["end_char"] = s.EndChar
    }
}).ToList();

await qdrantClient.UpsertAsync("documents", points);

PostgreSQL + pgvector

foreach (var segment in extraction.Segments)
{
    await connection.ExecuteAsync(
        @"INSERT INTO documents (segment_id, text, heading, salience, embedding) 
          VALUES (@id, @text, @heading, @salience, @embedding::vector)",
        new { 
            id = segment.Id,
            text = segment.Text, 
            heading = segment.SectionTitle,
            salience = segment.SalienceScore,
            // NOTE: String interpolation is for demo simplicity only.
            // For production, use NpgsqlParameter with Vector type for better
            // performance and to avoid culture-dependent decimal separators.
            embedding = $"[{string.Join(",", segment.Embedding)}]"
        });
}

Або використати Built- в магазинах

Не хочете керувати окремою базою даних

services.AddDocSummarizer(options =>
{
    // In-memory (fastest, no persistence)
    options.BertRag.VectorStore = VectorStoreBackend.InMemory;
    
    // DuckDB (embedded file-based, default)
    options.BertRag.VectorStore = VectorStoreBackend.DuckDB;
    
    // Qdrant (external server)
    options.BertRag.VectorStore = VectorStoreBackend.Qdrant;
    options.Qdrant.Host = "localhost";
    options.Qdrant.Port = 6334;
});

Чому щирість має значення

Більшість RAG-систем провалюються не тому, що вбудова є поганою,, а тому що всі фрагменти вважаються однаково важливими.

flowchart LR
    subgraph DOC["Document"]
        H1["# Title"]
        P1["First paragraph<br/>(intro)"]
        H2["## Methods"]
        P2["Technical details..."]
        P3["More details..."]
        H3["## Results"]
        P4["Key findings here"]
        H4["## Appendix"]
        P5["Reference data..."]
    end
    
    subgraph SCORES["Salience Scores"]
        S1["0.95"]
        S2["0.85"]
        S3["0.70"]
        S4["0.65"]
        S5["0.60"]
        S6["0.80"]
        S7["0.30"]
    end
    
    H1 --> S1
    P1 --> S2
    H2 --> S3
    P2 --> S4
    P3 --> S5
    P4 --> S6
    P5 --> S7
    
    style S1 stroke:#27ae60,stroke-width:3px
    style S2 stroke:#27ae60,stroke-width:2px
    style S6 stroke:#27ae60,stroke-width:2px
    style S7 stroke:#e74c3c,stroke-width:2px

речення у абстрактному значенні важливіше, ніж речення в приписі.

// Get the top 20% most salient segments
var topSegments = extraction.Segments
    .OrderByDescending(s => s.SalienceScore)
    .Take((int)(extraction.Segments.Count * 0.2));

Різовики слизистості:

Фактор МSK1 Ефект МSK2
МSK0 Позиция В вступі МSK2сумовні речення отримують більше балів
Близькість заголовку Перші речення після заголовків - це теорічні речення
МSK0 Длина Дуже короткі сегменти
МSK0 Тип секції Абстракт МSK2Введення збільшено , Референції
Тип наповнення МSK1 Блоки коду МSK2 цитати , листи з різним значенням

Це означає, що ваше відтворення (similarity * salience) замість простої схожості.

класифікація документів

DocSummarizer auto- визначає тип dokumentu, використовуючи гуристику на основі контентуM SK1

var extraction = await summarizer.ExtractSegmentsAsync(markdown);

// Document type detected from content
Console.WriteLine($"Type: {extraction.DocumentType}");     // Technical, Narrative, Legal, etc.
Console.WriteLine($"Confidence: {extraction.Confidence}"); // High, Medium, Low

класифікація впливає на пошук: Шкала глибини відтворення з ентропією dokumentu , не зашифрований ВерхнийKM SK2 Розмовні документи МSK3 вигадка МSK4 історії М SK5 отримують МСК6 x підштовхування до числа відтворення, тому що їм потрібен більше контексту М СК7 Технический документ з чіткою структурою потребує менше М S К8

Геуристичні дослідження на :

  • Частота кодового блоку ( технічнаM SK1
  • Структура заголовку (академічнийM SK1 технічнийМSK2
  • Patternи діалогу (наративM SK1
  • Юридична термінологія (контрактиM SK1
  • щільність списку (документаціяM SK1

Якщо геризтика непевна, DocSummarizer може повернутися до швидкої класифікації LLM, використовуючи модель "sentinel". Це вимагає того, щоб Ollama працювала локально з маленькою моделлю, наприклад tinyllama. Увімкніть його за допомогою конфігурації

services.AddDocSummarizer(options =>
{
    options.Ollama.BaseUrl = "http://localhost:11434";
    options.Ollama.Model = "tinyllama";
});

// Then use with LLM fallback enabled
var extraction = await summarizer.ExtractSegmentsAsync(markdown, useLlmFallback: true);

Для більшості документів , геуристика сама по собі є достатньо точною - зворотній зв 'язок LLM існує для крайних випадків МSK2

До прикладу повного трубопроводу RAG

Тут – це повний індекс – МСК1, МСК2, труба запиту, МSK3. Ми – МSK4 – збудуємо її за три кроки

sequenceDiagram
    participant User
    participant App as Your App
    participant DS as DocSummarizer
    participant VS as Vector Store
    participant LLM
    
    Note over DS: INGESTION (No LLM)
    App->>DS: ExtractSegmentsAsync(markdown)
    DS->>DS: Parse structure
    DS->>DS: Split into segments
    DS->>DS: Generate embeddings (ONNX)
    DS->>DS: Compute salience
    DS-->>App: ExtractionResult
    App->>VS: Store segments + vectors
    
    Note over LLM: QUERY TIME (LLM involved)
    User->>App: "What about X?"
    App->>DS: EmbedAsync(question)
    DS-->>App: float[384]
    App->>VS: Search(vector, topK=5)
    VS-->>App: Top segments
    App->>LLM: Question + Context
    LLM-->>App: Answer with [citations]
    App-->>User: Answer

Шаг 1: Структури даних

public class SimpleRagService
{
    private readonly IDocumentSummarizer _summarizer;
    
    // In-memory segment store - maps "docId:segmentId" to the full segment
    private readonly Dictionary<string, ExtractedSegment> _segments = new();
    
    // In-memory vector index - pairs of (id, embedding vector)
    private readonly List<(string Id, float[] Vector)> _index = new();

В процесі виробництва ви використовуєте реальну векторну базу даних: (QdrantM SK2 pgvector, і т.д.

Шаг 2: Індексування документів

    public async Task IndexAsync(string markdown, string docId)
    {
        // Extract segments with embeddings - this is where DocSummarizer does the work
        var extraction = await _summarizer.ExtractSegmentsAsync(markdown);
        
        // Store each segment and its vector
        foreach (var segment in extraction.Segments)
        {
            // Composite key: document + segment for citation tracking
            var id = $"{docId}:{segment.SegmentId}";
            
            // Keep the full segment for retrieval
            _segments[id] = segment;
            
            // Add to vector index for similarity search
            _index.Add((id, segment.Embedding));
        }
    }

Зверніть увагу, ми зберігаємо справжня текст dokumentu, не підсумкиM SK1

Шаг 3: Попит

    public async Task<string> QueryAsync(string question, int topK = 5)
    {
        // Embed the question using the same model as documents
        // This ensures vectors are in the same space
        var embedding = await _summarizer.EmbedAsync(question);
        
        // Find top-K most similar segments
        var results = _index
            .Select(x => (x.Id, Similarity: CosineSimilarity(embedding, x.Vector)))
            .OrderByDescending(x => x.Similarity)
            .Take(topK)
            .Select(x => _segments[x.Id])
            .ToList();
        
        // Build context with citation markers
        // The LLM can reference [chunk-3] and we can trace it back
        var context = string.Join("\n\n", results.Select(s => 
            $"[{s.SegmentId}] {s.Text}"));
        
        return context; // Send this + the question to your LLM
    }

Повернений контекст містить справжній текст документа з ідеями сегменту. Ваша LLM про prompt може виглядати так, як

Answer the question based on the following context.
Cite sources using the [chunk-N] markers.

Context:
{context}

Question: {question}

Математика (Standard Cosine SimilarityM SK1

    private static float CosineSimilarity(float[] a, float[] b)
    {
        float dot = 0, normA = 0, normB = 0;
        for (int i = 0; i < a.Length; i++)
        {
            dot += a[i] * b[i];
            normA += a[i] * a[i];
            normB += b[i] * b[i];
        }
        return dot / (MathF.Sqrt(normA) * MathF.Sqrt(normB));
    }
}

DocSummarizer включає VectorMath.CosineSimilarity() якщо ви не хочете писати це самостійно

DocSummarizer також відкриває IEmbeddingService безпосередньо, якщо вам потрібно вмонтувати пошуки окремо від повної схеми підсумування.

Вбудова моделей

За замовчанням AllMiniLmL6V2 - швидко , маленьке МSK2 хороша якість M SK3 Вибирати в залежності від ваших потреб

services.AddDocSummarizer(options =>
{
    options.Onnx.EmbeddingModel = OnnxEmbeddingModel.BgeBaseEnV15;
});
МSK0 Модель Dims Max Tokens МSK3 Rozmiar Примітки
AllMiniLmL6V2 МSK0 384
BgeSmallEnV15 МSK0 384 ♫ ♫ МSK2 ♫
BgeBaseEnV15 МSK0 768 ♫ ♫ МSK2 ♫
JinaEmbeddingsV2BaseEn МSK0 768 ♫ ♫ МSK2 ♫

Моделі автоматизовано- завантажити з HuggingFace при першій користуванні . Далі запускає навантаження з диска M SK2

Відкрита телеметрія

Наблюдайте за вашими трубопроводами RAG в процесі виробництва:

services.AddOpenTelemetry()
    .WithTracing(tracing => tracing
        .AddSource("Mostlylucid.DocSummarizer")
        .AddSource("Mostlylucid.DocSummarizer.Ollama")
        .AddSource("Mostlylucid.DocSummarizer.WebFetcher")
        .AddOtlpExporter())
    .WithMetrics(metrics => metrics
        .AddMeter("Mostlylucid.DocSummarizer")
        .AddMeter("Mostlylucid.DocSummarizer.Ollama")
        .AddMeter("Mostlylucid.DocSummarizer.WebFetcher")
        .AddPrometheusExporter());

Ключові метрики:

  • docsummarizer.summarizations - Перерахунки запитів
  • docsummarizer.summarization.duration - Час обробки в ms
  • docsummarizer.document.size - розміри документів
  • docsummarizer.ollama.embed.requests - Введення API дзвінків

Поддержка формату

DocSummarizer обробляє багато форматів документу з розумним виявленням та обробкою.

Пряма обробка (Не має зовнішніх обов 'язківM SK1

Ці формати оброблені наtively - не потрібні документування чи інші послугиM SK1

Формат МSK1 Поширення МSK2 Обробка
Замітка МSK1 .md, .markdown Розшифровано за допомогою Маркдіґа МSK1 структуру зберігають МSK2
Plain Text МSK1 .txt, .text Подібно до абзаців
МSK0 HTML .html, .htm СанітаризованийM SK1 перетворений на Markdown
Архиви ЗIP МSK1 .zip Витягує текстові файли , автоматичний МSK2 розпізнає формат Гутенберґа

Простий текст отримує розумне оброблення: Коли немає заголовків з відмітками, , chunker переключається на абзац МSK2 базується на розрізі \ . Він виявляє структуру dokumentu у найпростішому розумінні. МSK4 якщо у вашому тексті є чіткі прориви абзацу , вони стають межами блока

// Plain text works the same way
var plainText = File.ReadAllText("notes.txt");
var extraction = await summarizer.ExtractSegmentsAsync(plainText);
// Chunks split by paragraphs, embeddings generated

Богаті документи з документуванням

Для PDF, DOCXM SK1 PPTX, XLSXMSC3 і зображеннях (OCRMska5 M Ska6 додайте DoclingMske7

docker run -d -p 5001:5001 quay.io/docling-project/docling-serve
services.AddDocSummarizer(options =>
{
    options.Docling.BaseUrl = "http://localhost:5001";
});

// PDF, DOCX, PPTX, images all work
var pdfBytes = await File.ReadAllBytesAsync("document.pdf");
var extraction = await summarizer.ExtractSegmentsAsync(pdfBytes, "document.pdf");

Docling зберігає структуру dokumentu - заголовкиM SK1 таблиці , листи просуваються як правильне Markdown. Це означає, що краще відокремлення, ніж видобуток сирого тексту

Формат МSK1 Поширення МSK2 Замітки
PDF МSK1 .pdf Текст МSK1 макет зачуваний МSK2 таблички конвертовані
Слово МSK1 .docx Полне форматування МSK1 заголовки МSK2 листи
PowerPoint .pptx Сліпи стають розділами МSK1
Excel .xlsx Переведені таблички МSK1
Фото МSK1 .png, .jpg, .tiff ОCR через Docling

Подивіться Частина 1 для більшої інформації про інтеграцію Docling, або Мультиконвертація формату dokumentu для глибоких погружений.

Складні частини, які ви перекидаєте

Проблема DocSummarizer Solution МSK2
Спілкування на семантичних кордонах МSK1 Розриви на заголовкахM SK2 вміст, пов 'язаний з групами МSK3
Токенізація за модель Використовує правильний токенізер для кожної моделі ONNX МSK2
Вбудова пакету МSK1 Конфигурований розмір пакета МSK2 пам 'ять - ефективний
Переслідування цитат Кожен сегмент стає унікальним SegmentId
Конвертація формату МSK1 Марка-даун МSK2 HTML , PDF
Скачаймо модельM SK1Cachering Auto-downloadsМSK4 Cache in ~/.docsummarizer

Підсумок

До цікавої частини трубопроводу RAG потрібна інфраструктура.

  1. Зрізки з вбудовами - Готовий для будь-якого векторного магазину
  2. **Результати ФК Соланс ** - Не всі фрагменти однакові
  3. Переслідування цитат - Знайте, звідки приходять відповіді
  4. Місцеві-перша - Ніяких API ключів , запускається в офлайн
  5. Телеметрія виробництва - Вбудована OpenTelemetry
dotnet add package Mostlylucid.DocSummarizer

Вимикання завершено. Збудувати вашу RAG програмуM SK1

Подібні статті

Серія DocSummarizer

РАГ Deep Dives

GraphRAG

Подібні інструменти

Ліки

logo

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