Back to "DocSummarizer -osuus 4 - Rakenne RAG-putket"

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 -osuus 4 - Rakenne RAG-putket

Tuesday, 30 December 2025

NuGet npm .NET Yhdyskunta

Tämä on Osa 4 DocSummarizer -sarjasta. Katso Osa 1 arkkitehtuuria varten, Osa 2 CLI-välineelle, tai Osa 3 syvennykseen sisällytteisiin.

RAG:n kova osa on ', ei "LLM" vaan .. Se on kaikki ennen LLM:tä.

Olette luultavasti nähneet mallin.

  • Dokumenttiparsaattorit jokaiselle muodolle
  • Semanttisia rajoja kunnioittavaa logiikkaa
  • Tokenointi, joka vastaa integroimistanne mallia
  • Batching tehokkaan sijoittamisen luomiseksi
  • Saliencen tulosten perusteella kaikkia osia ei kohdella yhtäläisesti
  • Viittausseuranta, jotta tiedätte, mistä vastaukset ovat tulleet

Se' on paljon infrastruktuuria ennen kuin kirjoitatte yhden ainoan soveltamiskoodin rivin

DocSummarizer.Core käsittelee kaikkea yhdessä paketissa - on saatavilla sekä .NET- että nodeksi

DocSummarizer.Kore on pohjimmiltaan asiakirjan tiedustelutaso: määritelmällinen rakenne ensinM SK1 todennäköinen jäljittäminen toiseksi . Se ratkaisee tiedonlähestymisongelman, niin että voitte keskittyä johdonmukaiseen ongelmaan

Kuljetusputki

Tässä on se, mitä DocSummarizer tekee: - ja kriittisesti , ei'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

Mitä DocSummarizer tekee?

  • Tarkastelee asiakirjoja, joissa säilytetään rakenne
  • Jaetaan semanttisiksi segmentteiksi (ei mielivaltaisia chunkkejaM SK1
  • Generoi sisällytyksiä paikallisesti ONNX-järjestelmän avulla
  • Kertoa salienssiäänteet
  • Siirtää lainaus- ja viittaus-osoitteita merkkien asemaan

Mitä teette (blue boxM SK1

  • Merkitse segmentit vektoritietokannassanne
  • Luokaa oma hakulogiikkanne

Mitä tapahtuu kysymyksen aikana (purple boxM SK1

  • kirjaa kysymys (sama malliM SK1
  • Palauttaa vastaavat osat
  • Lähettäkää synteesi LLM:lle

Keskeinen näkemys: LLM ( punainen raja) osallistuu vain kysymyksen aikanaM SK2 syöttyminen on täysin deterministista - sama asiakirja tuottaa aina samoja segmenttejäMSC4 Tämä tekee RAG:sta toistuvaa ja parannuskeinoista riippumatonta

Reprodussibility bonus: Deterministinen siirto merkitsee sitä, että voitte tarkistaa RAG-putkensa uudelleen ja debugoida sen kuten minkä tahansa muun rakentavan artifactin tavoin.

Miksi ei ole LLM:tä syöpää varten?

RAG,:n osalta haluatte todelliset lauseet asiakirjoistanne - ei LLM-generoituja johdanto-osan kappaleitaM SK2 Kun käyttäjä kysyy " mitä sopimuksessa sanotaan lopettamisestaMSC4 teidän on saatava takaisin todellinen sopimustekstiMST5 ei sen yhteenvetoMSV6

LLM tulee myöhemmin, kysymyksen aikana, kootakseen vastauksen löydetyistä chunkista . Mutta itse chunkilla pitäisi olla sananmukainen lähdeaineistoMSC3 SeM SK4, mikä tekee viittauksista merkityksellisiä

DocSummarizer's ExtractSegmentsAsync antaa teille täsmälleen tämän: alkuperäisten tekstisegmenttien sisällyttämisen kanssa

Arvoehdotus

Tässä on se, mitä saatte yhdestä dotnet add package:

dotnet add package Mostlylucid.DocSummarizer
  • Älykäs segmentaatio - Splits headingissäM SK1 kunnioittaa semanttisia rajoja
  • ONNXin sisällytykset - PaikallinenM SK1 ei API-kysymyksiä , mallit automaattinen-laadiminen
  • Salienssin tulos - Ennen - kullekin segmentille laskettu merkitys
  • Viittausseuranta - Jokaisella segmentillä on ainutlaatuinen ID
  • Useat muodot - Markdown
  • Vektorin varastointimahdollisuudet - InMemory

Ei Pythonia. Ei ulkoisia API:itaM SK1 Ei monimutkaista järjestelyä . Ongelma on poissa ensimmäisen mallin laadinnon jälkeen

Osia poistaa: Core API

Yksinkertaisin käyttötapa - ekstrahoida segmentit sisällyttämällä ne valmiiksi vektoritehtaalle

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)]}...");
}

Tuotanto:

[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...

Se's itM SK1 Ei järjestelyä, ei viivytyksiä , ei mielipiteitäMSC4 vain segmentit, joihin sisällytetään lisäyksiä ja alkuperää

Asiakirja-asiakirjat

Jokainen segmentti's Id rakennetaan asiakirjan ID:stä sekä tyyppistä ja indeksistä: {docId}_{type}_{index}.

Voitte antaa oman asiakirjanne ID:n, tai antaa DocSummarizerin laskea yhden sisällöstä.

// 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)

Miksi tämä on tärkeää RAG:

  • Omien tunnistusten avulla voidaan yhdistää segmentit asiakirjanhallintajärjestelmään
  • Content-hash-identit varmistavat, että samaa asiakirjaa indeksoimalla toistetaan identiset segmenttiidentit
  • Molemmat lähestymistavat tukevat vakaita viittauksia - [s42] aina samaan alkuperäiseen tekstiin

Mikä on segmentissä

Jokainen ekstrahoitu segmentti sisältää kaiken, mitä RAG: tarvitsee

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.
}

Euroopan unionin Id on avain viittausten seurantaan. Kun LLM-tulokset [s42], voit ratkaista sen takaisin täsmälliseen alkuperäpaikkaan käyttäen StartChar/EndChar.

Bonus: Euroopan unionin ExtractionResult mukaan lukien viittauspäätöstä koskevat avustajamenetelmät:

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()); // **...**

Vektorivarastoihin siirtäminen

DocSummarizer antaa teille sisällytykset. Käytä mitä tahansa vector-tietokantaa, jota haluatteM SK1

Qdranti

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)}]"
        });
}

Vai käyttäkää rakenteellisia-varastoja

Ette halua hallinnoida erillistä tietokantaa? DocSummarizer sisältää kolme backend-järjestelmää

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;
});

Selitys on tärkeää

Useimmat RAG-järjestelmät epäonnistuvat ei siksi, että sisällytykset ovat huonoja, vaan koska kaikkia chunkia pidetään yhtä tärkeinä.

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

Lyhyesti sanottu lause on tärkeämpi kuin liitteessä oleva.

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

Salienssitekijät:

tekijöistä vaikutuksesta
Pysymys AlkuvaiheM SK2päätelmäsanat ovat parempia SSK3
otsikon läheisyys Ensimmäiset lauseet otsikoiden jälkeen ovat aiheesimerkit SSK2
Pituus hyvin lyhyeet osat (< 3 pisteitä ) rangaistaan
Pääluokkatyyppi Lyhyesti ottaenM SK2Täytäntöönpanoa lisättiin, ViittauksetMSC4Lisäys vähennetty SSK5
Luettelo sisällöstä

Tämä merkitsee, että pyynti voi painottaa (similarity * salience) päinvastoin kuin vain samankaltaisuus.

Asiakirjan luokittelu

DocSummarizer auto-detects document type using heuristics on the content

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

Luokittelu vaikuttaa hakuun: Dokumenttien entropin mukaiset jäljittämislähestysskaalitM SK1 ei ole hardcoded TopK. Narratiiviset asiakirjat ( kuvitteelliset jäljitetyt jäljitestävät jäljittämättömät jäljitysluvut, koska niille tarvitaan enemmän kontekstiaMSC7 Selkeän rakenteen tekninen asiakirja tarvitsee vähemmän

Heuristiikka tarkastelee::

  • Kodiblock-taajuus (tekninenM SK1
  • Otsakerakenne (akatemiallinenM SK1 tekninen )
  • Vuoropuhelumallit (narrative
  • Oikeudellinen terminologia (sopimukset
  • Luettelodensiteetti (asiakirjatM SK1

Jos heuristiikka on epävarmaa, DocSummarizer voi vapaaehtoisesti palata nopeaan LLM-luokitteluun käyttäen M SK1sentinel" malliaMSC3 Tämä edellyttää, että Ollama toimii paikallisesti pienellä mallilla, kuten tinyllama. Sovittelun avulla

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);

Useimmissa asiakirjoissa , yksinomaan heuristiikka on riittävän tarkkaa - LLM-valvomus on olemassa reunatapauksissa

Täysin RAG-putken esimerkki

Tässä on täydellinen indeksi: - ja -, kysyntäputki, ., rakennetaan kolmessa vaiheessa

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

Askel 1: Tietorakenteet

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();

Tuotteessa olette käyttänyt todellista vektoritietokantaa: (Qdrant, pgvector, jne.),, mutta tässä esitetään ydinmuodon

Askel 2: Indexointiasiakirjat

    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));
        }
    }

Huomautus: ei liity LLM-järjestelmäänM SK1 me 'varmistamme tosiasiallinen asiakirjan teksti, ei yhteenvedotM SK1

Askel 3: Kysymys

    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
    }

Palautettu konteksti sisältää todelliset asiakirjan teksti segmenttitietoja sisältävillä merkinnöillä. LLM-kysymys voi näyttää siltä

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

Context:
{context}

Question: {question}

Matematiikka (Standard Cosine Similarity

    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 sisältää VectorMath.CosineSimilarity() jos ette halua kirjoittaa tätä itse'

DocSummarizer paljastaa myös IEmbeddingService suoraan, jos on tarpeen sisällyttää kysymykset erikseen koko yhteenvetomenettelyyn.

Sisällyttäminen malleihin

Ennakolta on AllMiniLmL6V2 - nopea , pieni, hyvä laatuM SK3 Omien tarpeidenne mukaan valitse

services.AddDocSummarizer(options =>
{
    options.Onnx.EmbeddingModel = OnnxEmbeddingModel.BgeBaseEnV15;
});
Malli Dims Max Tokens M Suuruus H Huomautukset K
AllMiniLmL6V2
BgeSmallEnV15 Paras laatu/kokosuhteet M SK8
BgeBaseEnV15 768
JinaEmbeddingsV2BaseEn 768

Mallit auto-download from HuggingFace on first use. Subsequent runs load from diskM SK2

Avointelemetri

Valvotte RAG-putkenne tuotantoa:

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());

Keskeiset mittarit:

  • docsummarizer.summarizations - Pyynnöt lasketaan
  • docsummarizer.summarization.duration - Prosessiaika ms
  • docsummarizer.document.size - Asiakirjakoko
  • docsummarizer.ollama.embed.requests - API-puhelujen sisällyttäminen

Formattituki

DocSummarizer käsittelee useita asiakirjamuotoja älykkään havaitsemisen ja käsittelyn avulla.

Suora käsittely (Ei ulkoisia riippuvuuksia

Nämä muodot käsitellään alkuperäisesti - ei tarvita asiakirjojen laatimista tai muita palveluja

Formatti Laajentaminen Jalostus
Markdown .md, .markdown Parsoitu Markdigin kanssaM SK1 rakenne säilyy
Selkeä teksti .txt, .text Siirretään kohdalta (double newlinesM SK2
HTML .html, .htm SanitoituM SK1 muutettu merkitseväksi
ZIP-arkistot .zip Extracts text files, autoM SK2detects Gutenberg-format

Selkeä teksti saa älykkään käsittelyn: Jos ei ole merkitseviä otsikoita, chunker siirtyy kohdaksi -perustainen jakaminen M SK3 Se tunnistaa asiakirjan rakenteen heuristisesti.

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

Korkeat asiakirjat

PDF:n osalta , DOCXM SK1 PPTX, XLSXMSC3 ja kuvat (OCRMST5 - liittää asiakirjat SSK7

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");

Laatiminen säilyttää asiakirjan rakenteen - otsikotM SK1 taulukot , luettelot tulevat läpi asianmukaisena merkitsemisenä. Tämä tarkoittaa parempaa chunkointia kuin raakatekstien extracointiaMSC4

Formatti Laajentaminen Huomautukset
PDF .pdf Teksti + järjestys säilytetäänM SK2 taulukoita muutetaan SSK3
Word .docx Täysin muotoiltavaM SK1 otsikot, luettelot
PowerPoint .pptx Slides become sections
Excel .xlsx Esitettyjä taulukoita
Kuvat .png, .jpg, .tiff OCR Doclingin välityksellä

Ks. Osa 1 lisätietoja asiakirjan laatimiseen liittyvästä integroimisesta, tai Multi-Format-asiakirjan kääntäminen syveen uimiseen.

Harvat osat, joita unohdetaan

Ongelma DocSummarizerin ratkaisu
Semanttinen rajan ylitys Luettelot otsikoistaM SK2 ryhmiin liittyvä sisältö SSK3
Tokenointi kutakin mallia varten
Sisällyttäminen pakettiin Asennettavissa oleva pakettikokoM SK2 muisti-tehokas
Viittausseuranta Jokainen segmentti on ainutlaatuinen SegmentId
Formattimuutos Markdown, HTMLMSC3 PDFM SK4 DOCX yhden API:n välityksellä
mallin laatiminenM SK1caching Auto ~/.docsummarizer

Lyhyesti sanottuna

RAG-putket tarvitsevat infrastruktuuria ennen mielenkiintoista osaa. DocSummarizerM SK1Core antaa teille:

  1. Siihen sisältyvät osat - Valmis kaikkiin vektoreihin
  2. Saliensin suoritukset - Kaikki chunkit eivät ole samanlaisia
  3. Viittausseuranta - Tiedä, mistä vastaukset tulevat
  4. paikallinen-ensimmäinen - Ei API-kysymyksiä
  5. Tuotantotelemetri - Sisällytetty OpenTelemetry
dotnet add package Mostlylucid.DocSummarizer

Vetytys on tehty. Rakennetaan RAG-sovellusta.

DocSummarizer -sarja

RAG Deep Dives -tutkimus

GraphRAG

Yhtenevät välineet

Linkki

logo

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