# DocSummarizer 部件 @ 3 @ @ @ MPK1 @ 高级概念@ MS K2 @ I"# I went too far @ 🤦" @ deep Dive

<!--category-- AI, LLM, RAG, BERT, ONNX, C#, .NET, Embeddings -->
<datetime class="hidden">2025-12-21T12:00</datetime>

## 一. 导言导言 导言 导言 导言

这是 **部分#3** 调制解压缩器序列@: @

1. **[与 RAG 构建文档摘要](/blog/building-a-document-summarizer-with-rag)** @- 建筑和为什么管道方法战胜了天真的LLM呼唤
2. **[使用此工具的“ 2:” 部件](/blog/docsummarizer-tool)** “-Quick-CLI启动指南”
3. **部分: 3:高级概念** @( @ this article report@)}#-# #"#我走得太远了#"#技术深度潜水#
4. **[建筑RAG管道](/blog/docsummarizer-rag-pipeline)** - 使用 NuGet 库构建您自己的 RAG 应用程序

---


这是我的“" Time” -Boxed Tool@"}方法 @:给自己一个固定的窗口 来构建功能性#.}它迫使我们做出决定,并生成工作代码而不是理论设计_.}

DocSummarizer 一开始是为了展示你是如何 *应:* 多数教程都展示了如何将文字插入到LLM中, 希望有最佳的 & . @ @ 我希望能够显示适当的架构@:} gropting~,}嵌入,recurry_,}引用校验=.}

但当我总是做,时, 我对太空问题很感兴趣 四天后 “.” "I," I''d 挖进研究的“.”中

我运用了这些方法的版本 ._@here}'_s 开始,正确的模式_"成为ONX嵌入器 运行在本地{,BM25}混合搜索结合

**公正警告**@ : @ 这是# " @ I wrong too far@ MS K2 @ 深潜@ I.} 如果您想要使用此工具, @ MPK4 @ read part * 2. @ 如果你想理解的话读取部分 *为什么* 它的工作和 *如何* 继续读着.

本篇文章涵盖 @:

- **句子嵌入**: 如何变压器模型 @ MS K1MiniLM/BGEMSKO3GTE}GTEMPK4 将文字转换成矢量
- **NONX 运行时间**: 本地运行的 ML 模型, 没有 Python 或云性API
- **RAG (检索-支持一代})**:以源材料作为LLM产出的基础
- **混合搜索**将语义和词汇检索与RRF相结合

[TOC]

## 《建筑一瞥》

在钻入具体细节前 这里 ' * 碎片是如何组合在一起的* MS K2 *

```mermaid
flowchart TB
    subgraph Input["Document Input"]
        DOC[/"Document<br/>(PDF, MD, URL)"/]
    end

    subgraph Parse["Parsing Layer"]
        DOCLING["Docling<br/>(PDF/DOCX)"]
        MARKDIG["Markdig<br/>(Markdown)"]
    end

    subgraph Extract["Extraction Layer"]
        CHUNK["Document Chunker"]
        SEGMENT["Segment Extractor"]
    end

    subgraph Embed["Embedding Layer"]
        ONNX["ONNX Runtime<br/>(Sentence Transformers)"]
        OLLAMA_EMB["Ollama<br/>(Optional)"]
    end

    subgraph Store["Vector Storage"]
        QDRANT["Qdrant<br/>(Vector DB)"]
        MEMORY["In-Memory<br/>(Small Docs)"]
    end

    subgraph Retrieve["Retrieval Layer"]
        DENSE["Dense Search<br/>(Semantic)"]
        BM25["BM25<br/>(Lexical)"]
        RRF["RRF Fusion"]
    end

    subgraph Synthesize["Synthesis Layer"]
        OLLAMA["Ollama LLM<br/>(Local)"]
        TEMPLATES["Summary Templates"]
    end

    subgraph Output["Output"]
        SUMMARY[/"Summary with<br/>Citations [chunk-N]"/]
    end

    DOC --> DOCLING & MARKDIG
    DOCLING & MARKDIG --> CHUNK & SEGMENT
    CHUNK --> ONNX & OLLAMA_EMB
    SEGMENT --> ONNX
    ONNX & OLLAMA_EMB --> QDRANT & MEMORY
    QDRANT & MEMORY --> DENSE
    CHUNK --> BM25
    DENSE & BM25 --> RRF
    RRF --> OLLAMA
    OLLAMA --> TEMPLATES
    TEMPLATES --> SUMMARY
```

## 理解嵌入

### 问题:你如何找到相关内容?

当总结“ 500-” 页面手动手册时, 您需要找到相关的区域@ MS K2 @ 传统关键字搜索失败@ MPK3}

- 用户询问“ "” 我如何重设设备@ MS K1
- 手册上写着:#"_BARBAR_要修复工厂设置_..."_QAR
- 关键字搜索错过了 @ ( @ no shared words @ MPK1

你需要 **语义搜索** - 校对:Portnoy

### 什么是内嵌? ?

嵌入式通过将文字转换成密度矢量@(arrays of number @)}来解决这个问题,它能捕捉语义意为#.}类似的意思 *=}类似的矢量{,}不论措辞是否精确\.}

这里“ '” 是直觉@ MS K1 @ 想象一个“ I384-” 维空间, 每个文本都有位置@ MPK3+Texts 具有相似含义的组群 # MSC4}

```mermaid
graph LR
    subgraph "Embedding Space (simplified to 2D)"
        A["🚗 car"]
        B["🚙 automobile"]
        C["🏎️ vehicle"]
        D["🍎 apple"]
        E["🍊 orange"]
        F["🍌 fruit"]
    end
    
    A -.->|"close"| B
    B -.->|"close"| C
    A -.->|"close"| C
    
    D -.->|"close"| E
    E -.->|"close"| F
    D -.->|"close"| F
    
    A -.-|"far"| D
```

### 为什么句子变换者 @ (# 不是Raw BERT)?}

**问题**:我需要嵌入为语义相似性工作的嵌入@.Raw BERT是为分类任务设计的 @,不相近搜索_.

**解决方案**: 使用 **句子变压器** “-+”模式专门通过对比性学习就相似任务进行了专门培训;“.+”基于《公约》, [BERT 建筑](https://arxiv.org/abs/1810.04805) 以不同方式调整

模型,如 `all-MiniLM-L6-v2` 和 `bge-small-en-v1.5` 培训数十亿对文本,

- @ "_ 如何重置设备@ MS K1} @ I↔ @ * "# 重新定位工厂设置 @ MPK4 @ @ *# 类似 @ MASK6 @
- "#如何重置设备@"} @↔_ {"} productLational dismission=(MSK5{不同})

训练教他们类似的意义 近端矢量 (高连结

> **相关**: @ @ MSk0} 如果您想要了解变压器模型如何在更深的级别上工作 *#- 包括关注机制, encoder@-decoder 架构*,, 为什么嵌入工作 {- 见我的文章 [神经机器翻译如何工作](/blog/how-neural-machine-translation-works)它从翻译角度涵盖了相同的变压器概念 @.

**执行 执行情况**: 我们使用模型'#%s 输出层并应用 **平均共用** - 平均所有标记的嵌入以获得整个文本的单一矢量@.

```mermaid
flowchart LR
    subgraph Input
        TEXT["The quick brown fox"]
    end
    
    subgraph Tokenization
        CLS["[CLS]"]
        T1["the"]
        T2["quick"]
        T3["brown"]
        T4["fox"]
        SEP["[SEP]"]
    end
    
    subgraph "BERT Encoder"
        direction TB
        L1["Layer 1: Self-Attention"]
        L2["Layer 2: Self-Attention"]
        L3["..."]
        L6["Layer 6: Self-Attention"]
    end
    
    subgraph Output
        E1["E[CLS]"]
        E2["E[the]"]
        E3["E[quick]"]
        E4["E[brown]"]
        E5["E[fox]"]
        E6["E[SEP]"]
    end
    
    subgraph Pooling
        MEAN["Mean Pool<br/>(with attention mask)"]
        VEC["384-dim Vector"]
    end
    
    TEXT --> CLS & T1 & T2 & T3 & T4 & SEP
    CLS & T1 & T2 & T3 & T4 & SEP --> L1
    L1 --> L2 --> L3 --> L6
    L6 --> E1 & E2 & E3 & E4 & E5 & E6
    E1 & E2 & E3 & E4 & E5 & E6 --> MEAN
    MEAN --> VEC
```

## ONNX:}本地运行 ML 模型

### Python 依赖性地狱

我想嵌入到“"” 只要工作 “"” 当有人运行工具时

1. 安裝 Python + PyTorch + 变压器
2. 手动下载模型
3. 希望版本冲突打破一切

用户想要的垃圾@. @% `docsummarizer -f doc.pdf`@ ,_ 不是30-} 一步设置指南 * .

### 为什么是ONX ?

ONNX {(} 开放神经网络交换} )} 是 ML 模型的公开格式@.} 杀手特性:} **没有 Python 的运行时间推断**.

**我得到了什么与ONNX 运行时间=:**

1. **零外部依赖** 无 Python,PyTorrchMS K2CUDA 驱动器
2. **Auto - 下载模型** 由 Hugging Face 首次下载@(~23-34 @MB @),}然后缓存
3. **纯净@.NET** -在任何地方工作
4. **CPU 推断** - 不需要 GPU *, 使用廉价硬件

与 GPU PyTorrch @,相比, 贸易速度稍慢, 但比让用户安装 Python@.要快得多

### 示范登记处

DocSummarizer 包含多个嵌入模型@, @ 每一个都具有不同的交易}#-_ offs:}

|Q 型号为 @|Q 尺寸@|Z Max Tokens *|Q大小 @MS K4QQAnnatized#}(|Q)使用大小写@MS K7Q 需要指令 *MSKO8*
|-------|-----------|------------|------------------|----------|---------------------|
| `AllMiniLmL6V2` @| @ 384 @ @ I| @ *256# @ * |} @ *MSSK6# 默认@- @ fast_ MS K8# 优质 @ MASK9 @ no #|#
| `BgeSmallEnV15` |+#~34MB #|#更好的技术工具#MS K7_是|#
| `GteSmall` -=YTET -伊甸园字幕组=- 翻译:
| `MultiQaMiniLm` @| @ 384 @ @ @ I| @ @ *512 @ * | @ * MB# MS K6 @ 优化为@&A @ A_| @ no MSC9} @

**注注注注注释注注说明附注注注,注注 注注的注 注 注 注注说明注注附注注 注的注注 注注说注注的附注注说明,注 注,注说明的注说明说明注 注说明注说明 注注 注附注注的注释注 注 注 注注释注说明注释注的说明注,说明注的 注 注说明说明说明 注 注的说明说明,说明说明的附注 注注附注说明注附注的注附注 注 注注释说明注注释的注注释 注注注释注释注,的注, 注注,注释注附注附注注注释说明的说明 注说明 注的注释 注 注附注说明说明注释说明说明附注 注说明的注释注释注释说明 注注释注释 注说明注释注释的说明注释 注注释 注的附注注释注注释,注注释附注注附注注释的 注注脚注注注**:}所有注册条目点均与 WordPiece-}匹配的 OnNX 出口 {(} 使用 `vocab.txt`尚未支持Unigram模型“.”

**BGE 指令格式**@ :_ 某些型号@ (} 类似 BGE)} 需要前缀来优化性能@ I.} 确切格式取决于模型=:}

```csharp
// Query embedding (what the user asks)
var queryText = "Represent this sentence for searching relevant passages: " + userQuery;
var queryEmbedding = await EmbedAsync(queryText);

// Passage embedding (document chunks)
// Some BGE variants prefix passages, others don't - check model documentation
var passageEmbedding = await EmbedAsync(chunkText);
```

登记册跟踪哪些模型需要通过 `RequiresInstruction` 和 `QueryInstruction` 字段@.}在使用基于指令的模型时,总是以检索质量为基准{-} .

示范登记册如何运作?

```csharp
public static class OnnxModelRegistry
{
    public static EmbeddingModelInfo GetEmbeddingModel(OnnxEmbeddingModel model, bool quantized = true)
    {
        return model switch
        {
            OnnxEmbeddingModel.AllMiniLmL6V2 => new EmbeddingModelInfo
            {
                Name = "all-MiniLM-L6-v2",
                HuggingFaceRepo = "Xenova/all-MiniLM-L6-v2",
                ModelFile = quantized ? "onnx/model_quantized.onnx" : "onnx/model.onnx",
                VocabFile = "vocab.txt",
                EmbeddingDimension = 384,
                MaxSequenceLength = 256,
                SizeBytes = quantized ? 23_000_000 : 90_000_000,
                RequiresInstruction = false
            },
            // ... other models
        };
    }
}
```

### WordPiece 相对于 BPE

不同的模型使用不同的方式 `all-MiniLM-L6-v2` 模型使用 WordPiece 代号@( @ 类似 BERT),}, 它将未知的单词拆分为子名符號@ ._ 其他模式可以使用 BPE {(}\ _Byte MS K4} Pair Encoding}) 或 Unigram messignizers *.}

**重要**: 模擬代碼器必須符合 訓練的代號機}{. 我們的登記軌道 每個型號都要求. **目前正在实施@ :_ WordPiece** (维亚 `vocab.txt`*).BPE/Unigram支持通过 `tokenizer.json` 正在计划但尚未实施 @- 粘贴在登记册中的 WordPiece 模型

```csharp
public class BertTokenizer
{
    private readonly Dictionary<string, int> _vocab;
    private const int ClsTokenId = 101;  // [CLS] - start of sequence
    private const int SepTokenId = 102;  // [SEP] - end of sequence
    private const int PadTokenId = 0;    // [PAD] - padding
    private const int UnkTokenId = 100;  // [UNK] - unknown token

    public BertTokenizer(string vocabPath)
    {
        // Load vocabulary: word -> token ID
        _vocab = File.ReadAllLines(vocabPath)
            .Select((word, index) => (word, index))
            .ToDictionary(x => x.word, x => x.index);
    }

    public (long[] InputIds, long[] AttentionMask, long[] TokenTypeIds) 
        Encode(string text, int maxLength)
    {
        // Split text into words, then apply WordPiece to each word
        var words = text.ToLowerInvariant()
            .Split(new[] { ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
        var tokens = words.SelectMany(WordPieceTokenize).ToList();
        
        // Truncate to fit [CLS] and [SEP] tokens
        if (tokens.Count > maxLength - 2)
            tokens = tokens.Take(maxLength - 2).ToList();

        // Build input: [CLS] + tokens + [SEP] + [PAD]...
        var inputIds = new List<long> { ClsTokenId };
        inputIds.AddRange(tokens.Select(t => (long)GetTokenId(t)));
        inputIds.Add(SepTokenId);

        // Pad to maxLength
        var padCount = maxLength - inputIds.Count;
        inputIds.AddRange(Enumerable.Repeat((long)PadTokenId, padCount));

        // Attention mask: 1 for real tokens, 0 for padding
        var attentionMask = inputIds.Select(id => id != PadTokenId ? 1L : 0L).ToArray();
        
        // Token type IDs: all zeros for single sentence
        var tokenTypeIds = new long[maxLength];

        return (inputIds.ToArray(), attentionMask, tokenTypeIds);
    }

    private IEnumerable<string> WordPieceTokenize(string word)
    {
        // If the whole word is in vocabulary, return it
        if (_vocab.ContainsKey(word))
        {
            yield return word;
            yield break;
        }

        // Otherwise, split into subwords with "##" prefix
        int start = 0;
        while (start < word.Length)
        {
            int end = word.Length;
            string? curSubstr = null;

            while (start < end)
            {
                var substr = word[start..end];
                if (start > 0) substr = "##" + substr;  // Continuation marker

                if (_vocab.ContainsKey(substr))
                {
                    curSubstr = substr;
                    break;
                }
                end--;
            }

            if (curSubstr == null)
            {
                yield return "[UNK]";
                yield break;
            }

            yield return curSubstr;
            start = end;
        }
    }
}
```

示例符号@: @%

| 输入 *| * Tokens *MS K2*
|-------|--------|
| `"embedding"` | `["em", "##bed", "##ding"]` |
| `"DocSummarizer"` | `["doc", "##su", "##mm", "##ari", "##zer"]` |
| `"the quick brown"` | `["the", "quick", "brown"]` |

### 带有关注面罩的合用平均值

在 BERT 处理标记后, 我们得到每个标记的隐藏状态@ . @ 平均集合平均值这些\ MS K2}(但仅代表实际符号) @ (not padding @ MPK4}

```csharp
private static float[] MeanPool(Tensor<float> hiddenStates, long[] attentionMask, int hiddenSize)
{
    // Assumes last_hidden_state shape: [batch=1, seq_len, hidden_size]
    // Note: Many sentence-transformer models export a pooled output directly,
    // but we use mean pooling for consistency across all ONNX exports.
    var result = new float[hiddenSize];
    var dims = hiddenStates.Dimensions.ToArray();
    var seqLen = (int)dims[1];
    
    // Count real tokens (not padding)
    float maskSum = attentionMask.Count(x => x == 1);
    if (maskSum == 0) maskSum = 1; // Avoid division by zero

    // Average each dimension, weighted by attention mask
    for (int h = 0; h < hiddenSize; h++)
    {
        float sum = 0;
        for (int s = 0; s < seqLen; s++)
        {
            if (attentionMask[s] == 1)
                sum += hiddenStates[0, s, h];
        }
        result[h] = sum / maskSum;
    }

    // L2 normalize for cosine similarity
    float norm = MathF.Sqrt(result.Sum(x => x * x));
    if (norm > 0)
    {
        for (int i = 0; i < result.Length; i++)
            result[i] /= norm;
    }

    return result;
}
```

### 完整的嵌入管道

这里“ '” 表示从文本到嵌入的完整流程@ MS K1 @

```csharp
public class OnnxEmbeddingService : IEmbeddingService, IDisposable
{
    private InferenceSession? _session;
    private BertTokenizer? _tokenizer;

    public async Task<float[]> EmbedAsync(string text, CancellationToken ct = default)
    {
        await InitializeAsync(ct);  // Downloads model if needed
        
        // Prepend instruction for models that need it (like BGE)
        if (_modelInfo.RequiresInstruction)
            text = _modelInfo.QueryInstruction + text;

        // Tokenize
        var (inputIds, attentionMask, tokenTypeIds) = 
            _tokenizer.Encode(text, _maxSequenceLength);

        // Create ONNX tensors
        var inputIdsTensor = new DenseTensor<long>(inputIds, new[] { 1, inputIds.Length });
        var attentionMaskTensor = new DenseTensor<long>(attentionMask, new[] { 1, attentionMask.Length });
        var tokenTypeIdsTensor = new DenseTensor<long>(tokenTypeIds, new[] { 1, tokenTypeIds.Length });

        var inputs = new List<NamedOnnxValue>
        {
            NamedOnnxValue.CreateFromTensor("input_ids", inputIdsTensor),
            NamedOnnxValue.CreateFromTensor("attention_mask", attentionMaskTensor),
            NamedOnnxValue.CreateFromTensor("token_type_ids", tokenTypeIdsTensor)
        };

        // Run inference
        using var results = _session.Run(inputs);
        
        // Get hidden states output
        var output = results.First(r => r.Name == "last_hidden_state");
        var outputTensor = output.AsTensor<float>();

        // Mean pooling with attention mask
        return MeanPool(outputTensor, attentionMask, _modelInfo.EmbeddingDimension);
    }
}
```

## RAG:检索val -养代

### 问题=:}LLM Can'* t read {500-} page Documents (纸质文件)

**这种天真的做法失败了 :**

```csharp
var text = File.ReadAllText("500-page-manual.txt"); // 2MB of text
var summary = await llm.GenerateAsync($"Summarize: {text}"); // ❌ Doesn't fit in context
```

即使使用“128”K 上下文窗口@,}您也可以 @'}只将大文档在“MS K3”中丢弃

- **补短**@ : @ 仅第一位@ MS K1 @ page fit,}休息忽略
- **幻觉**旨在填补空白的:+LLM发明
- **费用成本**:处理 @2MB 文本成本@$$$每个查询
- **质量质量**@:#LMs 与大环境混淆 #("#在中间丢失#"_问题@)}

### 答案:RAG (Retreival"MS K2"支持的一代)

而不是发送所有信息@, @ 仅发送相关内容@ '}

1. **弹头**: 将文档分割成段
2. **嵌入**: 将片段转换为矢量 @(}{semantic submitive})
3. **检索回收**@ : 找到查询中最相关的部分@ 10-20
4. **综合综合报告***:LLM只概述这些部分。

**为何如此成功?** LLM认为“10QQKB”内容高度相关,

```mermaid
flowchart LR
    subgraph "Without RAG"
        DOC1[/"500-page PDF"/]
        LLM1["LLM<br/>(32K context)"]
        OUT1["❌ Truncated or<br/>Hallucinated"]
    end
    
    subgraph "With RAG"
        DOC2[/"500-page PDF"/]
        CHUNKS["100 Chunks"]
        VDB["Vector DB"]
        QUERY["Query"]
        TOP["Top 10 Chunks"]
        LLM2["LLM"]
        OUT2["✅ Grounded<br/>Summary"]
    end
    
    DOC1 --> LLM1 --> OUT1
    
    DOC2 --> CHUNKS --> VDB
    QUERY --> VDB --> TOP --> LLM2 --> OUT2
```

### 文档打印策略

DocSummarizer 支持基于文档结构的多个块化策略@: @%

```csharp
public class DocumentChunker
{
    public List<DocumentChunk> ChunkByHeadings(string markdown, int maxHeadingLevel = 2)
    {
        var chunks = new List<DocumentChunk>();
        var lines = markdown.Split('\n');
        var currentChunk = new StringBuilder();
        var currentHeading = "";
        var headingLevel = 0;
        var order = 0;

        foreach (var line in lines)
        {
            // Detect heading (# to ######)
            var headingMatch = Regex.Match(line, @"^(#{1,6})\s+(.+)$");
            
            if (headingMatch.Success && 
                headingMatch.Groups[1].Length <= maxHeadingLevel)
            {
                // Flush current chunk
                if (currentChunk.Length > 0)
                {
                    chunks.Add(new DocumentChunk(
                        Order: order++,
                        Heading: currentHeading,
                        HeadingLevel: headingLevel,
                        Content: currentChunk.ToString().Trim(),
                        Hash: ComputeHash(currentChunk.ToString())
                    ));
                }
                
                // Start new chunk
                currentHeading = headingMatch.Groups[2].Value;
                headingLevel = headingMatch.Groups[1].Length;
                currentChunk.Clear();
            }
            else
            {
                currentChunk.AppendLine(line);
            }
        }
        
        // Don't forget the last chunk
        if (currentChunk.Length > 0)
        {
            chunks.Add(new DocumentChunk(
                Order: order,
                Heading: currentHeading,
                HeadingLevel: headingLevel,
                Content: currentChunk.ToString().Trim(),
                Hash: ComputeHash(currentChunk.ToString())
            ));
        }
        
        return chunks;
    }
}
```

### 用于精密-+Groined检索的片段提取

对于较长的文档来说 @,} DocSummarizer 提取单个片段 ( sentences,}列出项目\ MPK3\ 代码块_)\ 带有突出评分\ :}

```csharp
public class SegmentExtractor
{
    public async Task<ExtractionResult> ExtractAsync(string docId, string markdown)
    {
        // 1. Parse into typed segments
        var segments = ParseToSegments(docId, markdown);
        
        // 2. Generate embeddings
        await GenerateEmbeddingsAsync(segments);
        
        // 3. Calculate document centroid (average embedding)
        var centroid = CalculateCentroid(segments);
        
        // 4. Score by salience using MMR (Maximal Marginal Relevance)
        ComputeSalienceScores(segments, centroid);
        
        return new ExtractionResult
        {
            AllSegments = segments,
            TopBySalience = segments.OrderByDescending(s => s.SalienceScore).Take(50).ToList(),
            Centroid = centroid
        };
    }
}
```

### 问题=:语义搜索返回重复

**没有产妇死亡率**“,”检索“"”如何进行抓取工作 ?“MS K2”返回“MSC3”

1. -=YTET -伊甸园字幕组=- 翻译:
2. “"”入门切入“"”和“MS K2”相似之处:“)”
3. @" @ what is caching@?" @ @ @ (0.93}相似的地方 @ I) @
4. @"_Cache 执行细节@"}(0.85}(相似){)}

最上面的“3”结果都说同样的事情 “.” I'"正在重复浪费上下文窗口@.}

### 答案: "最大边际关联"

MMR 余额 **关联性** “(”与“查询”相似 **多样性** “(”与已经存在的“-”不同,

**公式=:**
$$MY MS K1 @\lambda@\}(笑) (笑)_\ text{sim}}(sK7s')$$

**它能做什么 :** 类似已选中的区段@.}这样可以避免摘要成为同一段落的 @5}版本{.}。

```mermaid
flowchart TB
    subgraph "MMR Selection"
        S1["Segment 1<br/>Score: 0.95"]
        S2["Segment 2<br/>Score: 0.90"]
        S3["Segment 3<br/>Score: 0.88"]
        S4["Segment 4<br/>Score: 0.85"]
    end
    
    subgraph "Selected"
        SEL1["✓ Seg 1<br/>(highest)"]
        SEL2["✓ Seg 3<br/>(most diverse)"]
        SEL3["✓ Seg 4"]
    end
    
    S1 -->|"Select"| SEL1
    S2 -->|"Skip - too similar to Seg 1"| X["❌"]
    S3 -->|"Select"| SEL2
    S4 -->|"Select"| SEL3
```

公式=:

$$MY MS K1 I\lambda \cdott MS4s, CDNQ})MS K7~(1{- MSC10LAMBDA) MPK12cdott MS13max_@{ @sós@'} @ \ @in 选中的 @simK3 @sI( @s, @sQ')$$#

```csharp
private List<Segment> SelectSentencesMMR(
    List<Segment> segments,
    float[] centroid,
    int targetCount)
{
    var selected = new List<Segment>();
    var candidates = new HashSet<Segment>(segments.Where(s => s.Embedding != null));
    
    // Pre-calculate centroid similarities
    foreach (var segment in candidates)
    {
        segment.Score = CosineSimilarity(segment.Embedding!, centroid) 
                      * segment.PositionWeight;
    }
    
    while (selected.Count < targetCount && candidates.Count > 0)
    {
        Segment? best = null;
        double bestScore = double.MinValue;
        
        foreach (var candidate in candidates)
        {
            // Relevance: similarity to centroid
            var relevance = candidate.Score;
            
            // Diversity: max similarity to already selected
            double maxSimToSelected = 0;
            foreach (var sel in selected)
            {
                var sim = CosineSimilarity(candidate.Embedding!, sel.Embedding!);
                maxSimToSelected = Math.Max(maxSimToSelected, sim);
            }
            
            // MMR score: balance relevance and diversity
            var mmrScore = _config.Lambda * relevance 
                         - (1 - _config.Lambda) * maxSimToSelected;
            
            if (mmrScore > bestScore)
            {
                bestScore = mmrScore;
                best = candidate;
            }
        }
        
        if (best != null)
        {
            selected.Add(best);
            candidates.Remove(best);
        }
    }
    
    return selected;
}
```

## 与 RRF 混合搜索

### 问题=:语义搜索错误精确匹配

我在测试:时碰到了这个

**查询**@: @ @ " @ whatsize_ '}是认证的 API 端点@?" @

**语义搜索返回@: @%**

1. "用户登录流概观@" @ @(高度相似=)
2. *安全最佳做法* *"* *(}高度相似 )*
3. 会议管理 " MS K2 高度相似性 MSC3 *

**错过了什么**在代码示例中埋藏的实际API终点@: `POST /api/v1/auth/login`

**为什么**以自然语言对嵌入模型进行培训 `POST /api/v1/auth/login` @ '_ t语义匹配@ MS K1} 校对端点 @ MPK2 @ * -* it@ I'} 一个字面技术参引Q.}

### 混合搜索 (+Semantic @++Lexical@)+

结合两种检索方法及互补优势

|+搜索类型 @|+强点 @MS K2+弱点@|}
|-------------|-----------|------------|
| **{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}高音** “| 语义理解”“,”同名词 @|可以错过精确的匹配@, @稀有条件 @MS K4}
| **粗略的“(”BM25)** @ |_ 精确关键字匹配@ ,} 稀有的用词 @ I|_ 没有语义理解 * |

混合搜索组合,使用对等平整拼凑 (RRF):

```mermaid
flowchart TB
    QUERY["Query: 'authentication security'"]
    
    subgraph Dense["Dense Search (Semantic)"]
        D1["1. OAuth 2.0 implementation"]
        D2["2. User login flow"]
        D3["3. Password hashing"]
    end
    
    subgraph Sparse["BM25 Search (Lexical)"]
        S1["1. Authentication middleware"]
        S2["2. Security headers"]
        S3["3. OAuth 2.0 implementation"]
    end
    
    subgraph RRF["RRF Fusion (Illustrative)"]
        R1["OAuth 2.0 implementation<br/>RRF = 1/(60+1) + 1/(60+3) ≈ 0.032"]
        R2["Authentication middleware<br/>RRF = (not in dense) + 1/(60+1) ≈ 0.016"]
        R3["User login flow<br/>RRF = 1/(60+2) + (not in BM25) ≈ 0.016"]
    end
    
    QUERY --> Dense & Sparse
    Dense --> RRF
    Sparse --> RRF
```

**注注注注注释注注说明附注注注,注注 注注的注 注 注 注注说明注注附注注 注的注注 注注说注注的附注注说明,注 注,注说明的注说明说明注 注说明注说明 注注 注附注注的注释注 注 注 注注释注说明注释注的说明注,说明注的 注 注说明说明说明 注 注的说明说明,说明说明的附注 注注附注说明注附注的注附注 注 注注释说明注注释的注注释 注注注释注释注,的注, 注注,注释注附注附注注注释说明的说明 注说明 注的注释 注 注附注说明说明注释说明说明附注 注说明的注释注释注释说明 注注释注释 注说明注释注释的说明注释 注注释 注的附注注释注注释,注注释附注注附注注释的 注注脚注注注**@:_RRF计分显示为示例@.}恒定的 k=60}是标准的标准{;}实际排名取决于全部候选集=.}

### RRF 实施

```csharp
public static class HybridRRF
{
    /// <summary>
    /// Reciprocal Rank Fusion: combine multiple rankings into one.
    /// 
    /// Formula: RRF(d) = Σ 1/(k + rank_i(d))
    /// 
    /// Where k = 60 (standard constant to prevent division by small numbers)
    /// </summary>

    public static List<Segment> Fuse(
        List<Segment> segments,
        string query,
        BM25Scorer bm25,
        int k = 60,
        int topK = 20)
    {
        // Rank by dense similarity
        var byDense = segments
            .Where(s => s.Embedding != null)
            .OrderByDescending(s => s.QuerySimilarity)
            .ToList();
        
        // Rank by BM25 (scorer is built over the same ordered segment list)
        var bm25Scores = segments
            .Select((s, i) => (segment: s, score: bm25.Score(i, query)))
            .OrderByDescending(x => x.score)
            .Select(x => x.segment)
            .ToList();
        
        // Rank by salience (pre-computed importance)
        var bySalience = segments
            .OrderByDescending(s => s.SalienceScore)
            .ToList();
        
        // Compute RRF scores
        var rrfScores = new Dictionary<Segment, double>();
        
        void AddRRFScore(List<Segment> ranking)
        {
            for (int i = 0; i < ranking.Count; i++)
            {
                var segment = ranking[i];
                var rrfContribution = 1.0 / (k + i + 1);  // 1-based rank
                
                if (!rrfScores.TryAdd(segment, rrfContribution))
                    rrfScores[segment] += rrfContribution;
            }
        }
        
        AddRRFScore(byDense);
        AddRRFScore(bm25Scores);
        AddRRFScore(bySalience);
        
        // Return top-K by fused score
        return rrfScores
            .OrderByDescending(kv => kv.Value)
            .Take(topK)
            .Select(kv => kv.Key)
            .ToList();
    }
}
```

### BM25: 粗糙的检索工作马

BM=25}(Best 匹配{25)}是经典的信息检索算法\.}它结合了术语频率@,}反向文档频度>,}和文件长度正常化_:}

```csharp
public class BM25Scorer
{
    private const double K1 = 1.5;  // Term frequency saturation
    private const double B = 0.75;  // Length normalization factor
    
    public double Score(int docIndex, string query)
    {
        var queryTerms = Tokenize(query);
        var docTermFreq = _docTermFreqs[docIndex];
        var docLength = _docLengths[docIndex];
        
        double score = 0;
        
        foreach (var term in queryTerms.Distinct())
        {
            if (!docTermFreq.TryGetValue(term, out var tf)) continue;
            if (!_docFreqs.TryGetValue(term, out var df)) continue;
            
            // IDF with smoothing
            var idf = Math.Log((_corpusSize - df + 0.5) / (df + 0.5) + 1);
            
            // BM25 TF component with length normalization
            var tfNorm = (tf * (K1 + 1)) / 
                (tf + K1 * (1 - B + B * docLength / _avgDocLength));
            
            score += idf * tfNorm;
        }
        
        return score;
    }
}
```

## 内容集中的 TF-IDF

### 你如何区分核心内容 与Trivia+??

当总结一本小说,时,我得到的结果就像"MS K1"一样。

> 华生注意到气候温和,

这些是精确的提取@, @ but they'_re **颜色颜色** @( @sceene@-# 设置细节@MS K2}不是 **核心绘图点**.

**挑战挑战**: 你如何辨别:的区别?

- **核心核心内容**@:}%s appears in the document 整个文档中 {(}_字符名称>,主題@,}關鍵事件}{MS K4
- **说明细节**“:”在一些章节中显示“(”和“subplots”以及“MS K2 解释”、“)”
- **颜色颜色**@,#家具说明@)}

### 中央分类的解决方案

TF -IDF ( 定期频率 @- 反文文件频度@)估计数 **一个术语对文件的核心有多重要**@,_#不是它的真相价值@.}

**逻辑=:**

- **高度 DF @ (>50%块@)**: @" @Sherlock_","瓦特森}",#"murder@"}(→核心内容)
- **中度 DF (20-50%)**-=YTET -伊甸园字幕组=- 翻译:
- **低 DF (<20%)**: MS K1 蓝色大衣 ", I"oak家具" MPK5偶然颜色

这与真相无关, @(a 重复的说法可能是虚假的@,}一个罕见的事实可能是真的 *文件的中心地位*.

```mermaid
flowchart LR
    subgraph "TF-IDF Classification"
        CLAIM["Claim text"]
        TERMS["Extract terms"]
        TFIDF["Compute TF-IDF"]
        CLASS["Classify"]
    end
    
    subgraph "Term Types"
        COMMON["High DF (>50%)<br/>→ Core content"]
        MODERATE["Medium DF (20-50%)<br/>→ Supporting detail"]
        RARE["Low DF (<20%)<br/>→ Incidental colour"]
    end
    
    CLAIM --> TERMS --> TFIDF --> CLASS
    CLASS --> COMMON & MODERATE & RARE
```

```csharp
public class TextAnalysisService
{
    private readonly Dictionary<string, int> _documentFrequency = new();
    private int _totalDocuments;

    public void BuildTfIdfIndex(IEnumerable<string> documents)
    {
        _documentFrequency.Clear();
        _totalDocuments = 0;
        
        foreach (var doc in documents)
        {
            _totalDocuments++;
            var terms = Tokenize(doc).Distinct();
            
            foreach (var term in terms)
            {
                _documentFrequency.TryGetValue(term, out var count);
                _documentFrequency[term] = count + 1;
            }
        }
    }

    /// <summary>
    /// Classify term centrality (not epistemic truth):
    /// - High DF (>50%): appears across most chunks = core content
    /// - Medium DF (20-50%): supporting detail
    /// - Low DF (<20%): rare = likely incidental ("colour")
    /// 
    /// Note: This estimates centrality, not factuality. A repeated 
    /// claim can be false; a rare fact can be true.
    /// </summary>

    public ClaimType ClassifyTermImportance(string term)
    {
        var df = _documentFrequency.GetValueOrDefault(term.ToLowerInvariant(), 0);
        
        if (_totalDocuments == 0 || df == 0)
            return ClaimType.Colour;
        
        var documentRatio = (double)df / _totalDocuments;
        
        // High centrality = appears widely
        if (documentRatio > 0.5)
            return ClaimType.Core;
        
        // Medium centrality = supporting themes
        if (documentRatio > 0.2)
            return ClaimType.Supporting;
        
        // Low centrality = incidental detail
        return ClaimType.Colour;
    }
}
```

## 完整的贝尔拉格管道

Docsummarizer ' 生产管道`BertRagSummarizer`“)”结合所有这些概念“:”

```csharp
public class BertRagSummarizer
{
    /// <summary>
    /// Full pipeline: Extract → Retrieve → Synthesize
    /// 
    /// Key properties:
    /// - LLM only at synthesis (no LLM-in-the-loop evaluation)
    /// - Deterministic extraction (reproducible, debuggable)
    /// - Validated citations (every claim traceable to source segment)
    /// - Scales to any document size
    /// - Cost-optimal (cheap CPU work first, expensive LLM last)
    /// </summary>

    public async Task<DocumentSummary> SummarizeAsync(
        string docId,
        string markdown,
        string? focusQuery = null)
    {
        // === Phase 1: Extract ===
        // Parse document → segments with embeddings + salience scores
        var extraction = await _extractor.ExtractAsync(docId, markdown);
        
        // === Phase 2: Retrieve ===
        // Hybrid search: Dense + BM25 + Salience via RRF
        var retrieved = await RetrieveAsync(extraction, focusQuery);
        
        // === Phase 3: Synthesize ===
        // LLM generates fluent summary from retrieved segments
        var summary = await SynthesizeAsync(docId, retrieved, extraction, focusQuery);
        
        return summary;
    }
}
```

## 常见失败模式

当建造和使用 DocSummarizer @, @ I'# 遇到这些问题时,

1. **收缩器不匹配 @ → @ 无稽的嵌入**: 載入 WordPiece vocab 的 BPE- 訓練型態產生有效的{-但表面上沒有意義的矢量{MS K3 總要驗證符號是否與模擬' 培訓機程}.

2. **单字母中的主数@ - @ title address**“: ” 使用一个文档的中央机器人系统下移“-” 来修补这个功能,但又增加了复杂度“MS K7”

3. **BM25 以稀有条件比密集搜索强**: 如果您的查询包含技术术语或适当的名词, 在嵌入模型中代表的@' 培训数据 @, 词汇匹配 *(BM25) 将超过语义搜索@MS K6 这就是为什么混合搜索事项\.

4. **扫描PDFs中的OCR垃圾**-*}校对:Portnoy

5. **Lowó- 覆盖摘要必须使用对冲语言**: 如果您只看到“'}”文档中的 “3% {,}”字句,比如“MS K4}{最后一刻}"}或“MSSK6}_BARBAR_结论_"}这是不诚实的>.}这个系统必须说‘"』样本区域 @"} 并避免最终结尾@.}

6. **引用幻觉**: 小LLM {(1.5}B-3}B params)}有时发明了可信的}- `[chunk-N]`“,}校验 N ” 在源块中存在, `[chunk-999]` 您的LLM 正在挣扎着要完成的任务@. @%

这些是'#tbugs @-}它们都是空间设计中固有的紧张 ~.}好的生产系统确认并减轻了这些紧张

## 实际考虑

### 覆盖面和抽样诚实

当处理非常大的文档时 @ , docSummarizer does\ MS K1 t尝试嵌入所有@ - 它使用语义预写@ MPK3过滤程序来选择具有代表性的区段@ OMK4} **这意味着该摘要基于一个样本\ ,}而不是完整的文档=.。**

系统可透明地处理此操作@ : @

```csharp
// If coverage is low (<5%), prepend disclaimer and use cautious language
if (coverage < 0.05)
{
    var disclaimer = $"WARNING: Summary (sampled ~{coverage:P1} of document)";
    summary = $"{disclaimer}\n\n{CleanAndHedge(summary)}";
}

// Append coverage footer to every summary
var footer = $"\n\n---\nCoverage: {coverage:P1} ({scope})\nConfidence: {confidence}";
```

**重要**: 这是 *已检索证据摘要*当我们说“"+sampled @3%",”时,

**抽样是'}不是随机的** # - @ it@' @%s *语义*3%可能错过所有限制和边缘情况@.#Semantic @Z3%试图捕捉每个主要主题的代表部分@MS K7}It'}仍然部分覆盖*,,但是它故意使'}部分覆盖=.

**具有多个专题锚点的适应性抽样**: @ preQ-filter 使用多个锁定@ MS K2kK3}-mskK5}用來確保少數議題是't 被系统性地排除.} 這防止了「 MSKO8}主題偏差}{" 一個單核機關鍵-KKK10}(重要嘅K11butMS12rare) 的內容, 如限制♪, 例外}MS K14}或結論MSHC15}

从 `SegmentExtractor.cs`:

```csharp
// Multi-anchor approach prevents single-centroid bias
var topicAnchors = ComputeTopicAnchors(embeddedSample, k: 5);

// Score by max similarity to ANY anchor (catches minority topics)
var score = topicAnchors.Max(anchor => CosineSimilarity(segment.Embedding, anchor));
```

这是研究 - 知情的 @( 避免单-\Qquery回想起崩溃@)}但实用的 MPK4Q 运行在 CPU+. 上几秒钟

**为什么不把所有东西都嵌入进去呢?**

@500-_page document 文档中的“%sK1}部分@),}嵌入每件事物都有效,但“'”是最佳的吗?

- **费用成本**@ : @ OQ(N)嵌入控制了运行时间@.}在 @ I~150片段 @ MPK5secMS K6
- **质量质量**“: 嵌入一切会增加回收池中的噪音”“. 你仍然需要排名', 所以为什么嵌入从不排在高位的区块?”
- **实用**@ : @ 内存和延缓限制问题@ MS K1_ 继续保留 @ I2,000 @ *384-# dim 矢量在记忆中, 计算每个查询的 mSSK4} 共弦相似点是浪费性的 当您只需要顶端的 @ MPK5 @ {

多- anchor 采样给了您最好的两个\MS K1 广泛主题覆盖,可移动计算@ .

### 上下文 Ddrucking@: @ 为何检索是@ '_ t搜索

I'' 以上我所描述的是 @ '_ 不只是 @ I"retrieval}"} @ *-} it'{ 我称之为特定模式 **受限制的模糊环境拖拉** ([CFCD](/blog/constrained-fuzzy-context-dragging)洞察力和洞察能力

> 大多数总结器继续添加上下文@ . @ docSummarizer *向前拖动* 然后让模型在这些边框中流畅地书写 .

这里请看DocSummarizer 通往 CFCD=:的管道图如何绘制

-=YTET -伊甸园字幕组=- 翻译:
|--------------|------------------------------|
| **色素检测** (Fuzzy)|嵌入式MS K3近似机器人},THK5IDF中心
| **促进确定性** |+M MMZMPK1+BM25,+RRFUD+,}顶尖的-K选择=|#
| **锁定分类账** @|_ 检索到的片段组配有引证识别码@|}
| **受制约的一代人** “| 综合合成,由检索到的证据所约束”“|

**为什么这重要**“:”这个模型决定了“'”与什么有关,“MS K3” 回收管道是‘.’ 。“模式”只在我们“'”所设置的范围内流畅生成。 这就是为什么小本地型号在“:”上工作的原因。“锚”做重升“MSKO8”

@"_anchor clactor\ "}在实际操作中看起来像这个#(}(概念上)~):}

```json
{
  "coverage": "3.2% semantic sample",
  "anchors": [
    { "id": "chunk-12", "text": "Reset requires holding button 10s", "salience": 0.92 },
    { "id": "chunk-45", "text": "Factory reset clears all settings", "salience": 0.88 }
  ],
  "constraints": {
    "terms": { "factory reset": "restore factory settings" },
    "hedging": "sampled 3% - avoid definitive conclusions"
  }
}
```

然后在合成中 提示:

- 每一件索赔必须注明包含的块 IDQ"
- “"”是否覆盖了“<” *5%,"对冲语言="*
- *"* 一致使用这些术语*"*

这就是为什么:

- **更长的上下文窗口是红** 问题在于更多文字是否合适?
- **递归总和失败** - 它可以将中间输出作为文本处理\ MS K1 不受限制的结构
- **LLM可以 '\ t @"}忘记@"促进限制** @-他们#'_re 结构@,}没有可以从中流传的简讯

CFCD是和CFD一样的哲学分裂 [受限制的模糊](/blog/constrained-fuzziness-pattern), [限制的模糊MOM](/blog/constrained-mom-mixture-of-models),和 [图像摘要器](/blog/constrained-fuzzy-image-intelligence) “-”概率建议“,” 确定论长期存在 在时间轴中应用的“MS K2” “/”\“memory 轴@.”

### 量化

ONNX 模型可以以较小大小和更快的推断量来量化 “(”降低精确度“)”

“|”模型“|”全精度 |“量化”、“|”质量差异=|
|-------|---------------|-----------|-------------------|
|所有的-MINIL-L6-v}2 MS K5 NSK6MB □|MSKO8MU |MK10MSC11
@ 133_MB#|} @ I34MB$ MS K9 ~0.3% @ @ MPK11 @

### 批处理和汇兑

对于大文档来说,批量嵌入对性能至关重要 @.ONNX 运行时间@'s `InferenceSession` 通常可以安全地横贯线条共享@, @% 但性能取决于会话配置 @:}#

```csharp
public async Task<float[][]> EmbedBatchAsync(IEnumerable<string> texts, CancellationToken ct)
{
    var textList = texts.ToList();
    var results = new float[textList.Count][];
    
    // InferenceSession is safe to share for inference in most cases
    // Tune SessionOptions.IntraOpNumThreads and InterOpNumThreads for your workload
    var maxParallel = Math.Min(Environment.ProcessorCount, 8);
    
    await Parallel.ForEachAsync(
        textList.Select((text, index) => (text, index)),
        new ParallelOptions { MaxDegreeOfParallelism = maxParallel },
        async (item, token) =>
        {
            results[item.index] = await EmbedSingleAsync(item.text, token);
        });
    
    return results;
}
```

**业绩提示**@ :_ 配置 `SessionOptions` 创建会话时\ :\ {}

```csharp
var sessionOptions = new SessionOptions
{
    IntraOpNumThreads = 4,  // Threads within a single operation
    InterOpNumThreads = 2   // Threads across operations
};
var session = new InferenceSession(modelPath, sessionOptions);
```

### 大型文件记忆管理

需要特殊处理才能避免 OOM @:}

```csharp
// For documents > MaxSegmentsToEmbed, use hierarchical extraction
if (segments.Count > _config.MaxSegmentsToEmbed)
{
    // Process in batches, keeping only top-K per batch
    // Then re-rank globally
    return await ExtractHierarchicalAsync(segments);
}
```

## 性能特点

在典型的开发机“(Ryzen @5600X,”上,

“|”操作“|”传输“MS K2”,注意“MSC3”
|-----------|-----------|-------|
| **嵌入** 64, * 所有-MiniL-L6-vMS K8QQQ*|
| **密集检索** @| @ @ <10#s@|_Constine 相近于 @MS K3}部分 @|{
| **BM25评分** | MS K1 ms I| 输入- 模拟倒转索引|
| **RRF 聚联** @| @ @ <2#s @ I|#组合 @MS K3#排名@|} @
| **尾端的-@to @ - end @(25-_ page PDF)}%** |{~15-20}| 包括填块 MS K3 嵌入, 检索MSKO5LM 合成MS K6

**测试环境**32GBRAM,没有GPUMPK6嵌入式使用所有的-MiniL-L 6-v}(QQQAX,MS K13 象征性最大),@8-全线平行批发}MSC16Restrieval champage{:500 section_.}您的里程因不同的模型而不同

**主驱动程序正在嵌入传输流量** -}他们只用毫秒=MSK4=.}这强化了“"LYM lastQZK7”原则 *:}低廉的CPU工作*({emedding, recredition@)_Birst @,}只有过滤内容才使用高价LLM}♪.}

**缩缩**逐批处理,每批仅保留上方的-QK以保存记忆@. @

## 摘要摘要

DocSummarizer 表明,先进的NLP能力需要云性API或皮松依赖性*.}OnX嵌入运行时间和Ollama的一代=,}你可以建造完整的RAG输油管

- 完全本地运行
- 引用的摘要
- 处理任何大小的文档
- 脱线工程

构建此工具的关键洞见@: @

1. **嵌入是基础** 良好的检索取决于好的嵌入
2. **光是混合搜索一拍** -结合语义学和词汇学的稳健性
3. **产妇死亡率防止重犯** 多样性与相关性同样重要。
4. **结构事项** @-_尊重文档结构 {(} nheadings,}§MS K3}改善效果
5. **LLM女士应该最后来** - 做便宜的 CPU 首先工作 @,昂贵 LLM 只从事过滤内容的工作

## 继续阅读

### 论文和技术文件及技术参考资料

- [BERT 纸张](https://arxiv.org/abs/1810.04805) - 原始变压器编码器
- [句子@-BERT](https://arxiv.org/abs/1908.10084) -BERT 用于判刑嵌入
- [BM25 解释](https://www.elastic.co/blog/practical-bm25-part-2-the-bm25-algorithm-and-its-variables) 经典检索算法
- [RRF文件](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf) -对等合唱团
- [NONX 运行时间](https://onnxruntime.ai/) -十字-平台 ML 推导

### 相关深海底

- [神经机器翻译如何工作](/blog/how-neural-machine-translation-works) “-”覆盖变压器结构@,}关注机制 @,}和从翻译角度嵌入的“( ”

## 结束系列

此结论是 DocSummarizer 系列“. ” 这里 “'”三部分是如何结合的?

**[部分#1](/blog/building-a-document-summarizer-with-rag)** 解释 *为什么* 管道处理方法比天真的LLM调用@.#它覆盖了结构模式 @({chunking}_,} 级降,}\ 引证校验=)}让任何文件摘要员工作顺利

**[部分#2](/blog/docsummarizer-tool)** 您的快速“ -” 启动指南@ MS K1 @ 安裝@ I, @ model @ ,} 模板@ MPK4 @ 通用案例@ MOSK5 @ 如果您想要使用此工具 ,# , 该工具是' @ 所有您需要的工具 @ OMK8 @

**部分#3** @(_#这篇文章@)}是想要理解的人的深水潜水 *如何* 实际上它的工作原理是“:BERT 与句子变压器+,为什么ONX重要? , 象征性化得到\,混合搜索交易@-offs,,生产中断什么?”

如果您正在建立自己的管道... ,... ...读取所有三个#....

## 相关

- [CSV 与本地LLMs分析](/blog/analysing-large-csv-files-with-local-llms)
- [使用 LLMM 获取和分析网络内容](/blog/fetching-and-analysing-web-content-with-llms)