# DocSummarizer Part 4 - Établissement de pipelines RAG

<!--category-- AI, LLM, RAG, C#, Embeddings, ONNX, Semantic Search -->
<datetime class="hidden">2025-12-30T17:00</datetime>

[![NuGet](https://img.shields.io/nuget/v/Mostlylucid.DocSummarizer?label=NuGet)](https://www.nuget.org/packages/Mostlylucid.DocSummarizer)
[![npm](https://img.shields.io/npm/v/@mostlylucid/docsummarizer?label=npm)](https://www.npmjs.com/package/@mostlylucid/docsummarizer)
[![.NET](https://img.shields.io/badge/.NET-8.0%20%7C%2010.0-512BD4)](https://dotnet.microsoft.com/)
[![Node.js](https://img.shields.io/badge/Node.js-18%2B-339933)](https://nodejs.org/)

Il s'agit de **Partie 4** de la série DocSummarizer. Voir [Partie 1](/blog/building-a-document-summarizer-with-rag) pour l’architecture, [Partie 2](/blog/docsummarizer-tool) pour l'outil CLI, ou [Partie 3](/blog/docsummarizer-advanced-concepts) pour la plongée profonde sur les emplacements.

> **La partie dure du RAG n’est pas le LLM, mais c’est tout ce qui précède celui-ci.**

Vous ' avez probablement vu le modèle: diviser les documents en chunks , générer des embeddings M SK3 stocker dans une base de données vectorielle , récupérer les chunks pertinents

- Parseurs de documents pour chaque format
- Logique de fusion qui respecte les limites sémantiques
- Tokenisation qui correspond à votre modèle d'implantation
- Battage pour une génération embedding efficace
- Évaluation de la salinité afin que tous les morceaux ne soient pas considérés comme égaux
- Traçage de la citation pour que vous sachiez où les réponses sont venues

Il faut beaucoup d’infrastructure avant de pouvoir écrire une seule ligne de code d’application.

**DocSummarizer.Core gère tout dans un seul paquet** - disponible pour les deux .NET et Node

DocSummarizer.Core est essentiellement un **La couche d'intelligence du document**: structure déterministe première , récupération probabiliste secondeM SK2 Il permet de résoudre l’information- problème d’ingénierie afin que vous puissiez vous concentrer sur le problème de raisonnementMSC4

### Le pipeline d'ingestion

Voici ce que fait DocSummarizer : *doesn't* Do:

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

**Ce que fait DocSummarizer (box verteM SK1**

- Parse les documents préservant la structure
- Splits into semantic segments (not arbitrary chunks)
- Gérer des embeddings locaux avec ONNX
- Compte des notes de salience
- Assigner des ID de citation avec les positions du caractère

**Ce que vous faites (box bleue):**

- Entreposer les segments dans votre base de données vectorielle
- Élaborer votre logique de recherche

**Que se passe-t-il au moment de la demande (encadré purpleM SK1**

- Insérer la question (le même modèle)
- Récupérer des segments similaires
- Envoyer à LLM pour la synthèse

**Perspectives clés:** Le LLM (bord rouge) n'est impliqué qu'au moment de la demandeM SK2 l'ingestion est entièrement déterministe - le même document produit toujours les mêmes segmentsMNK4 C'est ce qui rend RAG reproduisable et débuggableMSC5

**Bons de reproduction:** L’ingestion déterministe signifie que vous pouvez modifier votre pipeline RAG comme tout autre artefact de construction.

### Pourquoi aucun LLM pour l'ingestion?

Pour RAG, vous voulez le *les sentences réelles* à partir de vos documents - non LLM-paraphrases généréesM SK2 Lorsque l'utilisateur demande "que le contrat dit-il au sujet de la résiliation?

Le LLM arrive plus tard, au moment de la demande, pour synthétiser une réponse à partir des morceaux reprisM SK2 Mais les morceaux eux-mêmes devraient être du matériel source verbatim . C’est ce qui fait que les citations ont un sens

DocSummarizer's `ExtractSegmentsAsync` vous donne exactement ce qui suit:: les segments de texte originaux avec embeddings;

[TOC]

## La proposition de valeur

Voici ce que vous obtiendrez avec un `dotnet add package`:

```bash
dotnet add package Mostlylucid.DocSummarizer
```

- **Segmentation intelligente** - Parties sur les titres, respecte les limites sémantiques
- **Emplacements de l'ONNX** - Local, sans clés APIM SK2 modèles automatiques - téléchargement
- **Évaluation de la culpabilité** - PréM SK1importance calculée pour chaque segment
- **Traçage des citations** - Chaque segment a une ID unique
- **Formats multiples** - Markdown , HTMLM SK2 PDF, DOCX MSC4avec la présentation de documentsMSC5
- **Options de stockage des vecteurs** - InMemoryM SK1 DuckDB , Qdrant construit-in

Pas de Python. Pas d’API externes. Aucune configuration complexeM SK2 Fonctionne en mode offline après le premier téléchargement du modèle .

## Extraire les segments: L'API de base

Le cas d’utilisation le plus simple - extrait des segments avec les embeddings prêts pour votre magasin de vecteurs:

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

**Output:**

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

Que'c'est-ce . Aucune orchestration, aucun promptsM SK3 aucune opinion MSC4 simplement des segments avec embeddings et provenanceMNK5 prêt pour votre base de données vectorielleMRK6

### ID du document

Chaque segment's `Id` est construit à partir d’un document ID plus type et index: `{docId}_{type}_{index}`.

Vous pouvez fournir votre propre ID de document, ou laisser DocSummarizer calculer un à partir du contenu hash:

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

**Pourquoi cela est important pour RAG:**

- Des ID personnalisés vous permettent de corréler les segments avec votre système de gestion des documents.
- Content-hash IDs assurent que la réindexation du même document par l’indexation de - produce des ID identiques pour les segments
- Les deux approches appuient des citations stables - `[s42]` réglemente toujours le même texte source

## Qu’est-ce que le SMC0 dans un segment?

Chaque segment extrait contient tout ce dont vous avez besoin pour RAG:

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

L'article 5 de la Loi sur l'immigration et le statut des réfugiés `Id` est la clé de suivi des citations. Lorsque votre LLM produit `[s42]`, vous pouvez le résoudre à l'endroit exact de la source en utilisant `StartChar`/`EndChar`.

**Bonus:** L'article 5 de la Loi sur l'immigration et le statut des réfugiés `ExtractionResult` inclut les méthodes d'aide pour la résolution des citations:

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

## Plugging Into Vector Stores

DocSummarizer vous donne les embeddings. Utiliser n’importe quelle base de données vectorielle que vous voulez.

### Qdrant

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

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

### Ou utiliser les magasins structurés-

Don' ne veut pas gérer une base de données distincte ? DocSummarizer comprend trois backends:

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

## Why Salience Matters

La plupart des systèmes RAG échouent non pas parce que les embeddings sont mauvais, mais parce que tous les chunks sont traités comme étant tout aussi importants.

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

Une phrase dans l’abrégé est plus importante que celle de l’annexe.

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

**Facteurs de salience:**

| Facteur | Effet |
|--------|--------|
| Position | IntroductionM SK2 résultats supérieurs pour les phrases de conclusion |
| Proximité de la position | Les premières phrases après les positions sont des phrases thématiques
| Longueur | Segments très courts MSC2 SMC3 les charsMSc4 sont pénalisés MSC5
| Type de section | RésuméM SK2Introduction améliorée, RéférencesMSC4Annexe réduite MSC5
| Type de contenu | Blocs de code, citationsM SK3 listes pondérées différemment |

Cela signifie que votre recherche peut avoir un poids de `(similarity * salience)` instead of just similarity.

## Classification des documents

DocSummarizer auto-détecte le type de document à l'aide d'une héuristique sur le contenu

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

**Classification affecte la récupération**: Les échelles de profondeur de récupération avec l'entropie du document, ne sont pas hardcodeées TopKM SK2 Documents narratifs ( FictionMNK4 histoiresMMK5 reçoivent une 1.5x accroissement pour le nombre de recherche parce qu'ils ont besoin d'un plus grand contexteMRK7 Les documents techniques dont la structure est claire ont besoin de moins de textes

L’héuristique :

- Fréquence de blocage du code (techniqueM SK1
- Structure de la position (académique,techniqueM SK2
- Patterns de dialogue (narrative)
- Terminologie juridique (contratsM SK1
- Densité de la liste (documentationM SK1

Si l'héuristique est incertaine, DocSummarizer peut optionnellement revenir à une classification rapide de LLM en utilisant un modèle M SK1sentinel" . Cela exige que Ollama fonctionne localement avec un petit modèle comme `tinyllama`. Enablez-le par la configuration:

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

Pour la plupart des documents, l’héuristique seule est suffisamment précise - le retrait de LLM existe pour les cas à bord

## Exemple du pipeline RAG complet

Voici un index complet de ', - et - du pipeline de demandes.

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

### Étape 1: Structures des données

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

Dans la production, vous utilisez une base de données sur les vecteurs réels :

### Étape 2: Documents d'indexation

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

Note: Aucune LLM n’est impliquéeM SK1 Nous *Actualités* Texte du document, non sommaires.

### Étape 3: Demande

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

Le contexte retourné contient le *Actualités* Texte du document avec les ID de segments. Votre prompt LLM pourrait ressembler à:

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

Context:
{context}

Question: {question}
```

### La mathématique (Similarité cosine standard)

```csharp
    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 inclut `VectorMath.CosineSimilarity()` si vous ne voulez pas écrire ce document par vous-mêmes'

Le DocSummarizer expose également `IEmbeddingService` directement si vous avez besoin d’incorporer les demandes séparément du pipeline de résumation intégrale.

## Modèles d'intégration

Défault est `AllMiniLmL6V2` - rapide , petit, bonne qualitéM SK3 Choisissez en fonction de vos besoins

```csharp
services.AddDocSummarizer(options =>
{
    options.Onnx.EmbeddingModel = OnnxEmbeddingModel.BgeBaseEnV15;
});
```

| Modèle | Éclaircissements MSC2 Tokens maximaux MSC3 Taille SMC4 Notes ≥MSC5
|-------|------|------------|------|-------|
| `AllMiniLmL6V2` | 384 ≥| ≤256 | ~23 MB MSC6 Défault MSC7 rapide msc8
| `BgeSmallEnV15` |
| `BgeBaseEnV15` Qualité de production |
| `JinaEmbeddingsV2BaseEn` Documents longs |

Modèles automatiques-download à partir de HuggingFace lors de la première utilisation. Subséquent runs load from diskM SK2

## OpenTelemetry

Surveiller votre pipeline RAG en production:

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

**Mesures clés:**

- `docsummarizer.summarizations` - Compte des demandes
- `docsummarizer.summarization.duration` - Temps de traitement en ms
- `docsummarizer.document.size` - Taille du document
- `docsummarizer.ollama.embed.requests` - Intégration des appels API

## Soutien au format

DocSummarizer gère plusieurs formats de documents avec une détection et un traitement intelligents.

### Traitement direct (Sans dépendance externe)

Ces formats sont traités à l'origine - aucun documentage ou autres services requis:

| Format | Extension MSC2 Traitement MSC3
|--------|-----------|------------|
| Marquage  | `.md`, `.markdown` | ParsÃ© avec MarkdigM SK1 structure rÃ©servÃ©e |
Texte simple | `.txt`, `.text` | Diviser par paragraphes (doubles lignes nouvellesM SK2 |
| HTML  | `.html`, `.htm` | SanitizedM SK1 converti en Markdown |
Archives ZIP | `.zip` | Extrait les fichiers de texteM SK1 auto- détecte le format Gutenberg |

**Texte simple obtient une manipulation intelligente**: Lorsqu'il n'y a pas de rubriques de marquage à descendre, le chunker change vers un paragraphe - par séparation fondée M SK3 Il détecte la structure du document d'une manière hiérarchique.

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

### Documents riches avec Docling

Pour le format PDF, DOCXM SK1 PPTX, XLSXMSC3 et les images (OCRMST5 Mst6 ajouter DoclingM st7

```bash
docker run -d -p 5001:5001 quay.io/docling-project/docling-serve
```

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

Le document de travail préserve la structure du document - les titres , les tableaux, les listes sont traduites comme un marquage appropriéM SK3 Cela signifie qu'il est préférable d'extraire le texte en bloc plutôt que d'en extraire l'extraction brute.

| Format | Extension MSC2 Notes SMC3
|--------|-----------|-------|
| PDF  | `.pdf` | Texte + layout preservedM SK2 tables converties |
| Mot  | `.docx` | Formatage completM SK1 titres, listes |
| PowerPoint  | `.pptx` | Les diapositives deviennent des sections |
| Excel  | `.xlsx` Tableaux extraits |
| Images  | `.png`, `.jpg`, `.tiff` | OCR par le biais de Docling |

Voir [Partie 1](/blog/building-a-document-summarizer-with-rag) Pour en savoir plus sur l’intégration de Docling, ou [Multi-Format Conversion de document](/blog/building-a-lawyer-gpt-for-your-blog-part9) pour une plongée profonde.

## Les parties difficiles que vous faites passer

Solution de DocSummarizer |
|---------|----------------------|
| Connaissance des limites sémantiques | Divisions sur les titresM SK2 contenu lié aux groupes MSC3
| Tokenisation par modèle | Utilise le correct tokenizer pour chaque modèle ONNX
| Emplacement des lots | Taille de lots configurableM SK2 mémoire-efficacité
| Traçage des citations | Chaque segment est unique `SegmentId` |
| Conversion de formats | Markdown, HTMLMSC3 PDFM SK4 DOCX par un seul API |
| téléchargement de modèleM SK1cache | Auto-downloadsMSC4 caches en `~/.docsummarizer` |

## Résumé

Les pipelines RAG ont besoin d’infrastructure avant la partie intéressante. DocSummarizerM SK1Core vous donne:

1. **Segments avec embeddings** - prêt pour tout magasin de vecteurs
2. **Notes de Salience** - Tous les chunks ne sont pas égaux
3. **Traçage des citations** - Connaissance de l’origine des réponses
4. **Local-première** - Aucune clé API, fonctionne en mode offline
5. **Telemétrie de production** - OpenTelemetry intégré

```bash
dotnet add package Mostlylucid.DocSummarizer
```

La plomberie est terminée. Construisez votre app RAG.

## Articles connexes

### La série DocSummarizer

- [Partie 1 - Architecture & Patterns](/blog/building-a-document-summarizer-with-rag) - Pourquoi l’approche du pipeline fonctionne
- [Partie 2 - Utilisation de l'outil](/blog/docsummarizer-tool) - Installation du CLI, modesM SK2 modèles
- [Partie 3 - Concepts avancés](/blog/docsummarizer-advanced-concepts) - Emplacements BERTM SK1 ONNX, recherche hybride
- [Partie 5 - DoomSummarizer: Recherche approfondie](/blog/doomsummarizer-deep-research) - MultiM SK1Récupération des sources , Profils d'entités, découverte de graphes sémantiquesMSC4 et synthèse de formes parallèles longuesMST5

### Les plongées profondes du RAG

- [Première étape du RAG](/blog/rag-primer) - Concepts fondamentaux pour la récupération-génération améliorée
- [Architecture du RAG](/blog/rag-architecture) - Modèles de conception du système pour RAG
- [Recherche et indexation hybrides](/blog/rag-hybrid-search-and-indexing) - Combinaison de la recherche dense et sparse
- [Applications pratiques de RAG](/blog/rag-practical-applications) - Real-world usage cases

### GraphRAG

- [GraphRAG: Graphiques de connaissances pour RAG](/blog/graphrag-knowledge-graphs-for-rag) - Lorsque la recherche par vecteur n’est pas suffisante
- [GraphRAG Minimum de mise en œuvre viable](/blog/graphrag-minimum-viable-implementation) - Établissement d'un système GraphRAG fonctionnel

### Outils connexes

- [Recherche sémantique avec ONNX et Qdrant](/blog/semantic-search-with-onnx-and-qdrant) - Les blocs de construction
- [Self-Databases de vecteurs hébergées: Qdrant](/blog/self-hosted-vector-databases-qdrant) - Qdrant exploité localement
- [Analyse des grands fichiers CSV avec les LLM locaux](/blog/analysing-large-csv-files-with-local-llms) - Le même modèle, domaine différent
- [Extraire et analyser le contenu Web avec les LLM](/blog/fetching-and-analysing-web-content-with-llms) - Écrapage Web pour RAG
- [Multi-Format Document Conversion Service](/blog/multi-format-document-conversion-service) - La plongée profonde de Docling

## Liens

- [NuGet Package](https://www.nuget.org/packages/Mostlylucid.DocSummarizer)
- [GitHub - Bibliothèque de base](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid.DocSummarizer.Core)
- [Outil CLI de GitHub -](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid.DocSummarizer)