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

غويت npm .NET العقد.js

هذا هو الجزء 4 لسلسلة DocSummarizer. أنظر الجزء 1 للعمارة, الجزء 2 لأداة CLI, أو الجزء 3 للغوص العميق على المركبات.

الجزء الصلب من RAG هو ' هو "LLM" . هو كل شيء قبل "LLS"

ربما رأيتم النمط

  • قاموا بتحليل الوثائق لكل صيغة
  • المنطق المحاكي الذي يحترم الحدود الدلالية
  • توكنالوجيا تتطابق مع نموذج الدمج الخاص بك
  • تخزين لخلق دمج فعّال
  • تقييم الشفقة بحيث لا يتم التعامل مع جميع الأجزاء بشكل متساوي
  • تتبع الاقتباس حتى تعرف من أين جاءت الإجابات

ذلك ' هو الكثير من البنية التحتية قبل أن تكتب سطر واحد من شفرة التطبيق .

DocSummarizer.Core يعالج كل ذلك في حزمة واحدة - متاحة لكلا .NET و العقدةM SK2js.

DocSummarizer.Core هو أساسا طبقة ذكاء الوثائق: الهيكلات الإفتراضية أولاً, الاستخراج الإحتمالي ثانياً . يحل مشكلة المعلوماتM SK3الهندسة بحيث يمكنك التركيز على مشكلة التفسير

أنابيب الإمتصاص

هنا ' ما يفعله DocSummarizer - و بشكل حرج لا '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 (صندوق أخضر):

  • يقوم بتحليل الوثائق التي تحافظ على البنية
  • تقسم إلى أجزاء سيمانسية (لا قطع عشوائية)
  • ينتج تداخلات محليا مع ONNX
  • يحسب نقاط الرابع
  • يخصص هوية الإقتباس مع وضعية الحرف

ما تفعله (صندوق أزرق):

  • تخزين الأجزاء في قاعدة بيانات الفيكتور الخاصة بك
  • بناء منطق استرجاعك

ما الذي يحدث في وقت الاستفسار (صندوق أزرق):

  • دمج السؤال (نفس النموذج)
  • استرجاع أجزاء متشابهة
  • أرسل إلى LLM للsynthesis

رؤية أساسية: LLM (حدود حمراء) يتدخل فقط في وقت الاستفسارM SK2 التدخين هو محدد تماماً - نفس الملف دائماً ينتج نفس الأجزاءMSC4 هذا ما يجعل RAG قابلة للتكرار وقابلة للحل

بونس التكاثر: الإمتصاص المعرفي يعني أنه يمكنك إعادة - "index" , " diff" , "and debug your RAG pipeline like any other build artifact" "No prompt variance" "no model temperature" "only pure"

لماذا لا يوجد LLM للإمتصاص?

من أجل RAG, تريد جمل حقيقية من مستنداتكم - ليس LLM- الاقتباسات المولدةM SK2 عندما يسأل أحد المستخدمين " ماذا يقول العقد عن التخلي عن العقدMSC4 تحتاج إلى الحصول على النص الحقيقي للتعاقد

يأتي الـ LLM لاحقاً ــ , ــ في وقت البحث ــ, ــ لتحليل الإجابة من القطعة التي تم استخلاصها ـــ . ــ لكن القطعة نفسها يجب أن تكون مصدراً حرفياً ـــ. ــ ذلك ــ МSK4 ــ هو ما يجعل الإقتباسات ذات معنى

DocSummarizer's ExtractSegmentsAsync يعطيك هذا بالضبط: أجزاء النص الأصلية مع المداخلات, جاهزة للإستخراجM SK2 لا يوجد LLM مشارك في الإمتصاص

إقتراح القيمة

ها هو ما تحصل عليه مع واحدة dotnet add package:

dotnet add package Mostlylucid.DocSummarizer
  • الانقسام الذكي - تقسم على الرؤوس, يحترم الحدود الدلالية
  • إضافات أونكس - محلي, لا مفاتيح APIM SK2 نماذج أوتومات -تحميل
  • درجات الشفقة - مسبقا- الأهمية الحسابية لكل جزء
  • متابعة الاستشهادات - كل جزء لديه ID فريد
  • العديد من الأشكال - MarkdownMSC1 HTML, PDFM SK3 DOCX (with DoclingMST5
  • خيارات مخزن الفيكتور - InMemory , DuckDBM SK2 Qdrant built-in

لا برمجة Python. لا واجهات API خارجية. لا تركيب معقدM SK2 يعمل على أرض الواقع بعد تحميل النموذج الأول .

استخرج Segments: API الأساسي

أبسط حالة إستخدام - استخرج Segments with embeddings ready for your vector store

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

ال sortie:

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

ذلك 'ه هو . لا ترسيم ,, لا إشارات , , لا رأي .- فقط أجزاء مع المداخلات و provenance .

أوراق الوثائق

كل جزء '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)

لماذا هذا يهم RAG:

  • الهوية المخصصة تمكنك من ربط الأجزاء مع نظام إدارة الملفات الخاص بك
  • المحتوى -hash IDs ensure re-indexing the same document produces identical segment IDs
  • كلا المقاربتين يدعمون اقتباسات مستقرة - [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 يعطيك المداخلات. استخدم أي قاعدة بيانات فيكتورية تحبها.

كوينت

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

أو إستخدام "بنى مسك 0" في المتاجر

لا تريد إدارة قاعدة بيانات مستقلة

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

عوامل ال Salience:

عامل تأثير
وظيفة مقدمة / جمل الإختبار تعطي علامة أعلى
قرب العنوان أول جملة بعد العناوين هي جملة موضوعية
طول أجزاء قصيرة جدًا (< 80 تُعاقب اللوحات S)
نوع الفصول خلاصة / تحسن في التقديم , مرجعية /تقلص في الملحق
نوع المحتوى بلاك الرمز, اقتباساتM SK3 القوائم الموزعة بشكل مختلف

هذا يعني أن إستخراجك يمكنه أن يزن (similarity * salience) بدلا من التشابه

تصنيف الوثائق

DocSummarizer automatic-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

التصنيف يؤثر على البحث: مقاييس عمق البحث مع إنتروبيا الوثائق , ليس رمزاً صلباً TopK | . | Documents Narrative |( | Fiction | , | stories | МSK5 | get a 1.5 | boost to retrieval count because they need more context

نظرة الهيوريستيك على :

  • تردد وحدة الرمز (technical)
  • الهيكل الرأسي (أكاديمي,سيّنيM SK2
  • أنماط الحوار (narrative)
  • المصطلحات القانونية (أعمال
  • كثافة القائمة (documentation)

إذا كانت الهرسية غير مؤكدة , DocSummarizer يمكن أن يرجع بشكل اختياري إلى ترتيب سريع لـ LLM باستخدام "sentinel" نموذج .. هذا يتطلب من أولاما العمل محليا مع نموذج صغير مثل 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);

بالنسبة للكثير من الوثائق , هلuristics وحدها هي دقيقة بما فيه الكفاية - هناك تراجع LLM لقضايا الحواف

مثال أنابيب RAG الكاملة

هنا "MSC0" هو المؤشر الكامل "MSc1" و "MScs2" خط أنابيب الطلب "MSec3" نحن "MSCS4" سنبنيه بثلاثة خطوات

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, وهلم جراMSC4 لكن هذا يظهر النمط الأساسيMNK5

الخطوة 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));
        }
    }

ملاحظة: لا وجود لـ LLM . نحن ' نقوم بحفظ حقيقة نص документа, لا خلاصات.

الخطوة 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 الخاص بك كالتالي

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

Context:
{context}

Question: {question}

الرياضيات (متشابهة الكوسين القياسية)

    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 -سرعةM SK1 صغيرة, جودة جيدة . إختيار بناء على إحتياجاتكMSC4

services.AddDocSummarizer(options =>
{
    options.Onnx.EmbeddingModel = OnnxEmbeddingModel.BgeBaseEnV15;
});
النماذج يضيئ إرقام اعظمية الحجم ملاحظات
AllMiniLmL6V2 384 ≥ ≤256 ~23 MB លំនាំដើម MSC7 سرعة MSC8
BgeSmallEnV15 384 ≥ \512 ♪~34 MB أفضل نوعية ♪ / نسبة الحجم ♪
BgeBaseEnV15 768
JinaEmbeddingsV2BaseEn 768 ≥ \8192 ♪~137 MB سندات طويلة

نماذج اتومات-download from HuggingFace on first useM SK1 Subsequent runs load from disk.

OpenTelemetry

مراقبة أنابيب 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 يتعامل مع العديد من صيغ الوثائق بكشف و معالجة ذكية.

المعالجة المباشرة (لا إختلافات خارجية )

هذه الصيغ تُعالج بفطرة - لا حاجة للدواسة أو الخدمات الأخرى :

الصيغة الإختصار معالجة
العلامة المنخفضة .md, .markdown تمت تحليلها مع ماركديج, تم الحفاظ على الهيكل
النص البسيط .txt, .text تقسم بال odstavات ( خطوط جديدة مضاعفة)
HTML .html, .htm مصحوبة, حولت إلى Markdown
آرشيف ZIP .zip يستخرج فايلات نصية, تلقائياM SK2 يكتشف شكل غوتينبيرغ

نص بسيط يحصل على معالجة ذكية: عندما لا توجد مخطوطات تشير إلى النزول, يتحول المجزأ إلى الفقرة - تم تقسيمها على أساسه M SK3 يكشف عن هيكل الوثائق بشكل عام - إذا كان نصك يحتوي على وقفات فقرية واضحة MSC5 تلك تصبح حدود المجزء

// 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, DOCX, PPTXM SK2 XLSXMSC3 وصور (OCRMska5 Mske6 أضف الملاحظات

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

تحتفظ الملاحظات بتركيب الوثائق - العلاماتM SK1 الجداول , قائمة تأتي من خلال علامة مناسبة. هذا يعني أن أفضل تكديس من إستخراج النص الخام

الصيغة الإختصار ملاحظات
PDF .pdf النص + تم الحفاظ علىレイアウトه, حولت الجداول
كلمة .docx الصيغة الكاملة, العلاماتM SK2 القوائم
PowerPoint .pptx تتحول الشرائح إلى أجزاء
Excel .xlsx الجداول المستخرجة
الصور .png, .jpg, .tiff رسم بياني عبر الطباعة

أنظروا الجزء 1 لمعرفة المزيد عن دمج دوكلينج, أو العديد من -تحويل الصيغة للឯកសារ للغوص العميق.

الأجزاء الصعبة التي تخطيها

مشكلة حل DocSummarizer
تدوير في الحدود الدلالية تقسيمات على الأشرطة, مجموعة المحتوى المرتبطة
توكيزة لكل نموذج يستخدم توكيزا صحيحة لكل جيل ONNX
تداخل الخزبة حجم الخزعة قابلة للضبط, الذاكرةM SK3 فعال
تتبع الاقتباس كل جزء يحصل على فريد من نوعه SegmentId
تحويل الصيغ العلامة المنخفضة , HTMLM SK3 PDF, DOCX من خلال API واحد
تحميل النموذج/ تخزين المخازن أوتوماتMSC3downloadsM SK4 مخازن في ~/.docsummarizer

الخلاصة

أنابيب RAG تحتاج إلى البنية التحتية قبل الجزء المثير

  1. Segments with embeddings - جاهزة لأي مخزن فيكتوري
  2. درجات الفضول - ليست جميع الجسيمات متساوية
  3. متابعة الاستشهادات - تعرف من أين تأتي الإجابات
  4. محلي-أول - لا يوجد مفاتيح API, يعمل خارج نطاق الإنترنت
  5. قياس الإنتاج - OpenTelemetry مبني
dotnet add package Mostlylucid.DocSummarizer

تم التوصيل بالماء . بناء تطبيق RAG الخاص بك .

المقالات المرتبطة

سلسلة DocSummarizer

RAG الغوصات العميقة

GraphRAG

أدوات مرتبطة

الروابط

logo

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