# RAG वास्तुकला और आंतरिक: यह वास्तव में कैसे काम करता है

में [भाग 1](/blog/rag-primer)हमने RAG को शामिल किया। ' के उद्गमों पर प्रकाश डाला।, के बुनियादी सिद्धांत पर प्रकाश डाल दिया।, और यह क्यों महत्वपूर्ण है?

<datetime class="hidden">2025-11-22T09:30</datetime>

<!-- category -- AI, RAG, Machine Learning, Semantic Search, LLM, AI-Article -->
# परिचय

**श्रेणी नेविगेशन** यह RAG श्रृंखला के भाग 2 है

- [भाग 1: मूल और बुनियादी](/blog/rag-primer) - इतिहास
- **भाग 2: वास्तुकला और आंतरिक** (इस अनुच्छेद) - आरएजी के कार्यों में तकनीकी गहरी खोज
- [भाग 3: RAG व्यावहारिक में](/blog/rag-practical-applications) - वास्तविक प्रणालियों का निर्माण
- [भाग 4a: ONNX & Qdrant कार्यान्वयन](/blog/semantic-search-with-onnx-and-qdrant) - सीपीयू
- [भाग 4b: क्रिया में सेमेटिक खोज](/blog/semantic-search-in-action) - टाइपेहेड, हाइब्रिड खोज
- [भाग 5: हाइब्रिड खोज](/blog/rag-hybrid-search-and-indexing) - उत्पादन एकीकरण पैटर्न
- [भाग 6: GraphRAG](/blog/graphrag-knowledge-graphs-for-rag) - कोर्स के लिए ज्ञान ग्राफ्स

यदि आपने भाग नहीं पढ़ा है तो मैं वहाँ से समझने के लिए शुरू करने की सिफारिश करता हूँ

- RAG क्या है और यह क्यों महत्वपूर्ण है
- शब्दकुञ्जी खोज से अर्थानुभूति तक का इतिहास
- RAG vs fine-tuning और अन्य दृष्टिकोण

इस लेख का मानना है कि आप उन बुनियादी और पर ध्यान केंद्रित समझते हैं **तकनीकी वास्तुकला, कार्यान्वयन विवरण**.

[TOC]

# RAG कैसे काम करता है: संपूर्ण तस्वीर

एक RAG सिस्टम में क्या होता है यह ठीक से विभाजित करें

## चरण 1: सूचकांकन | ( | ज्ञान आधार तैयार करना |)

RAG किसी भी चीज़ को प्राप्त करने से पहले आपको अपने ज्ञान आधार का अनुक्रमण करना होगा।

```mermaid
flowchart TB
    A[Source Documents] -->|1. Extract Text| B[Text Extraction]
    B -->|2. Split into Chunks| C[Chunking Service]
    C -->|3. Generate Embeddings| D[Embedding Model]
    D -->|4. Store Vectors| E[Vector Database]

    B -.Metadata.-> E

    subgraph "Example: Blog Post"
        F["Understanding Docker: A containerization platform..."]
    end

    subgraph "Chunks"
        G["Chunk 1: Title + Intro"]
        H["Chunk 2: Benefits Section"]
    end

    subgraph "Embeddings"
        I["0.234, 0.891, 0.567, ..."]
        J["0.445, 0.123, 0.789, ..."]
    end

    F --> G
    F --> H
    G --> I
    H --> J

    style D stroke:#f9f,stroke-width:2px
    style E stroke:#bbf,stroke-width:2px
```

### चरण 1: पाठ निष्कर्षण

अपने स्रोत दस्तावेजों से सादा पाठ निकालें

- मेरी ब्लॉग पोस्टों की तरह चिह्नित फ़ाइलें (
- दस्तावेज़ के लिए पीडीएफ (
- वेब स्क्रैपिंग के लिए HTML (
- डाटाबेस रिकॉर्ड
- ईमेल, चैट लॉग्स, आदि

**मेरे ब्लॉग से उदाहरण:**

```csharp
// From MarkdownRenderingService
public string ExtractPlainText(string markdown)
{
    // Remove code blocks
    var withoutCode = Regex.Replace(markdown, @"```[\s\S]*?```", "");

    // Convert markdown to plain text
    var document = Markdown.Parse(withoutCode);
    var plainText = document.ToPlainText();

    return plainText.Trim();
}
```

### चरण 2: सेटिंग

यह है जहाँ अधिकतर RAG क्रियान्वयन असफल होते हैं

**chunking का महत्व क्यों है**

- LLMs के पास टोकन सीमाएं हैं (context windows)
- छोटे टुकड़े = अधिक सूक्ष्म पुनःप्राप्ति
- लेकिन खंडों में पर्याप्त संदर्भ होना चाहिए कि अर्थपूर्ण हो

**खराब chunking:**

```
Chunk 1: "Docker is a containerization platform. It allows you"
Chunk 2: "to package applications with their dependencies. This"
Chunk 3: "ensures consistency across environments."
```

**अच्छा खंडन**

```
Chunk 1: "Docker is a containerization platform. It allows you to package applications with their dependencies. This ensures consistency across environments."

Chunk 2: "Benefits of Docker:
- Isolation: Each container runs in its own environment
- Portability: Containers run anywhere Docker is installed
- Efficiency: Lightweight compared to virtual machines"
```

**मेरी सेमेटिक खोज क्रियान्वयन से उदाहरण**

```csharp
public class TextChunker
{
    private const int TargetChunkSize = 500; // ~500 words
    private const int ChunkOverlap = 50;     // 50 words overlap

    public List<Chunk> ChunkDocument(string text, string sourceId)
    {
        var chunks = new List<Chunk>();

        // Split on section boundaries first (## headers in markdown)
        var sections = SplitOnHeaders(text);

        foreach (var section in sections)
        {
            // If section is small enough, keep it whole
            if (section.WordCount < TargetChunkSize)
            {
                chunks.Add(new Chunk
                {
                    Text = section.Text,
                    SourceId = sourceId,
                    SectionHeader = section.Header
                });
            }
            else
            {
                // Split large sections on sentence boundaries
                var subChunks = SplitOnSentences(section.Text, TargetChunkSize, ChunkOverlap);
                chunks.AddRange(subChunks.Select(c => new Chunk
                {
                    Text = c,
                    SourceId = sourceId,
                    SectionHeader = section.Header
                }));
            }
        }

        return chunks;
    }
}
```

**सामान्य खंडन रणनीति**

- **स्थिर**: सरल लेकिन अर्थात्मक सीमाओं को तोड़ता है
- **वाक्य-आधारित**: व्याकरण का सम्मान करता है लेकिन बहुत छोटा हो सकता है
- **पैराग्राफ-आधारित**: प्राकृतिक लेकिन परिवर्तनीय आकार
- **अनुभाग-आधारित**संरचनात्मक सामग्री के लिए सर्वोत्तम
- **स्लाइडिंग विंडो के साथ ओवरलैप**: यह सुनिश्चित करता है कि कोई संदर्भ सीमाओं पर खो नहीं जाता

### चरण 3: एम्बेडिंग उत्पन्न करें

एम्बेडिंग वह जादू है जो सेमेटिक खोज को संभव बनाता है

**प्रमुख संकल्पना** समान अर्थ → समान भेक्टर

```
"Docker container" → [0.234, -0.891, 0.567, ..., 0.123]
"containerization platform" → [0.221, -0.903, 0.534, ..., 0.119]
"apple fruit" → [0.891, 0.234, -0.567, ..., -0.789]
```

पहले दो वेक्टर सदिश में "close" होगा।

**एम्बेडिंग कैसे उत्पन्न किया जाता है**
आधुनिक एम्बेडिंग मॉडल, व्यापक पाठ डेटासेट पर सीखने के लिए तंत्रिका नेटवर्क हैं।

- **सभी-MiniLM**: 384 आयामों, तेजी से\, अच्छी गुणवत्ता के |(मैं इस ब्लॉग पर क्या उपयोग करता हूँ
- **पाठ** (OpenAI
- **BGE-आधार**: 768 आयामोंM SK2 स्थिति-ofMSC4theMST5art open source

**मेरे ONNX embedding सेवा से उदाहरण:**

```csharp
public async Task<float[]> GenerateEmbeddingAsync(string text)
{
    // Tokenize the input text
    var tokens = Tokenize(text);

    // Create input tensors for ONNX model
    var inputIds = CreateInputTensor(tokens);
    var attentionMask = CreateAttentionMaskTensor(tokens.Length);
    var tokenTypeIds = CreateTokenTypeIdsTensor(tokens.Length);

    // Run ONNX inference
    var inputs = new List<NamedOnnxValue>
    {
        NamedOnnxValue.CreateFromTensor("input_ids", inputIds),
        NamedOnnxValue.CreateFromTensor("attention_mask", attentionMask),
        NamedOnnxValue.CreateFromTensor("token_type_ids", tokenTypeIds)
    };

    using var results = _session.Run(inputs);

    // Extract the output (sentence embedding)
    var output = results.First().AsTensor<float>();
    var embedding = output.ToArray();

    // L2 normalize the vector for cosine similarity
    return NormalizeVector(embedding);
}
```

**सामान्यीकरण का महत्व क्यों है** L के बाद 2 मानकीकरण के पश्चात् कोसाइन समानता एक सरल बिंदु उत्पाद बन जाती है

### चरण 4: सदिश डाटाबेस में भंडारित करें

सदिश डाटाबेस उच्च भंडारण और खोज के लिए अनुकूलित हैं

**कुंजी ऑपरेशन**

- **जोड़ें (U)**: मेटाडेटा के साथ एक भेक्टर जोड़ें या अद्यतन करें
- **ढूंढें**: क्वेरी सदिश के लिए सबसे समान सदियों को ढूंढें
- **फ़िल्टरComment**: सदिश खोज को मेटाडेटा फ़िल्टरों के साथ जोड़ें

**उदाहरण Qdrant कार्यान्वयन**

```csharp
public async Task IndexDocumentAsync(
    string id,
    float[] embedding,
    Dictionary<string, object> metadata)
{
    var point = new PointStruct
    {
        Id = new PointId { Uuid = id },
        Vectors = embedding,
        Payload =
        {
            ["title"] = metadata["title"],
            ["source"] = metadata["source"],
            ["chunk_index"] = metadata["chunk_index"],
            ["created_at"] = DateTime.UtcNow.ToString("O")
        }
    };

    await _client.UpsertAsync(
        collectionName: "blog_posts",
        points: new[] { point }
    );
}
```

**लोकप्रिय भेक्टर डाटाबेस:**

- **क्वारंटCity name (optional, probably does not need a translation)**: Fast, selfM SK2hostable , excellent CMSC4 support
- **पीजीवेक्टर**: PostgreSQL एक्सटेंशन
- **पाइनकॉनCity name (optional, probably does not need a translation)**प्रबंधित सेवा
- **वियत करना**: विशेषता
- **क्रोमाडीबी**: पाइथोन

हम इन डेटाबेसों की स्थापना के बारे में आने वाले लेखों में जांच करेंगे

## चरण 2: पुनःप्राप्ति

जब कोई उपयोक्ता एक प्रश्न पूछता है, तो RAG प्रणाली को ज्ञान आधार से सर्वाधिक प्रासंगिक सूचना ढूंढने की आवश्यकता होती है

```mermaid
flowchart LR
    A["User Query:<br/>'How do I use Docker Compose?'"] --> B[Generate Query Embedding]
    B --> C["Query Vector:<br/>[0.445, -0.123, ...]"]
    C --> D[Vector Search]
    D --> E[Vector Database]
    E --> F[Top K Similar Chunks]
    F --> G["Results:<br/>1. Docker Compose Basics 0.92<br/>2. Multi-Container Setup 0.87<br/>3. Service Configuration 0.83"]

    style B stroke:#f9f,stroke-width:3px
    style D stroke:#bbf,stroke-width:3px
```

### चरण 1: क्वेरी एम्बेडिंग उत्पन्न करें

उपयोक्ता' प्रश्न के उपयोग से एक भेक्टर में परिवर्तित किया जाता है **एक ही एम्बेडिंग मॉडल** सूचकीकरण के लिए उपयोग किया जाता है. यह महत्वपूर्ण है - विभिन्न मॉडल अनुपयुक्त सदिशें उत्पन्न करते हैं

```csharp
public async Task<List<SearchResult>> SearchAsync(string query, int limit = 10)
{
    // Same embedding model used for indexing
    var queryEmbedding = await _embeddingService.GenerateEmbeddingAsync(query);

    // Search in vector store
    var results = await _vectorStoreService.SearchAsync(
        queryEmbedding,
        limit
    );

    return results;
}
```

### चरण 2: समानता खोज

भेक्टर डाटाबेस क्वेरी भेक्टर और सभी भंडारित भेक्टरों के बीच समानता का संगणन करता है

**कोसाइन समानता** सामान्यकृत सदिशों के लिए सबसे लोकप्रिय

```
similarity = (A · B) / (||A|| × ||B||)
```

दायरा : -1 से |1 | ( | उच्चतर \= | अधिक समान

**यूक्लिडियन दूरी** असामान्य विektor के लिए (

```
distance = sqrt(Σ(Ai - Bi)²)
```

दायरा : 0 से \∞ | | ( | नीचे |= | अधिक समान

**डॉट उत्पाद** (जब वेक्टर पूर्व हैं

```
similarity = A · B
```

दायरा : -1 से |1 | ( | उच्चतर \= | अधिक समान

**मेरी Qdrant सेवा से उदाहरण:**

```csharp
var searchResults = await _client.SearchAsync(
    collectionName: "blog_posts",
    vector: queryEmbedding,
    limit: (ulong)limit,
    scoreThreshold: 0.7f,  // Only return results with >70% similarity
    payloadSelector: true   // Include all metadata
);

return searchResults.Select(hit => new SearchResult
{
    Text = hit.Payload["text"].StringValue,
    Title = hit.Payload["title"].StringValue,
    Score = hit.Score,
    Source = hit.Payload["source"].StringValue
}).ToList();
```

### चरण 3: पुनर्रोकिंग (वैकल्पिक लेकिन सिफारिश की गई

आरंभिक खोज तेजी से है लेकिन लगभग

```mermaid
flowchart LR
    A[Vector Search:<br/>Top 50 Results] --> B[Reranking Model]
    B --> C[Reranked:<br/>Top 10 Results]

    style B stroke:#f9f,stroke-width:3px
```

**पुनर्रोकिंग क्यों मदद करता है**

- त्वरित एम्बेडिंग मॉडल गति के लिए अनुकूलन करते हैं , कुछ सटीकता को त्याग कर
- पुनरावर्तन मॉडल धीमी होते हैं लेकिन अधिक सटीक
- दो-- चरण दृष्टिकोण गति और गुणवत्ता को संतुलित करता है

**उदाहरण पुनर्रैंकिंग क्रियान्वयन**

```csharp
public async Task<List<SearchResult>> SearchWithRerankAsync(
    string query,
    int initialLimit = 50,
    int finalLimit = 10)
{
    // Stage 1: Fast vector search
    var candidates = await SearchAsync(query, initialLimit);

    // Stage 2: Precise reranking
    var rerankedResults = await _rerankingService.RerankAsync(
        query,
        candidates
    );

    return rerankedResults.Take(finalLimit).ToList();
}
```

## चरण 3: जनन | ( | उत्तर बनाने |)

अब जब हमारे पास प्रासंगिक जानकारी है, हम इसे LLM को उपयोक्ता के प्रश्न के साथ खिसकाते हैं

```mermaid
flowchart TB
    A[User Query] --> B[Retrieved Context 1]
    A --> C[Retrieved Context 2]
    A --> D[Retrieved Context 3]

    B --> E[Construct Prompt]
    C --> E
    D --> E
    A --> E

    E --> F["System: You are a helpful assistant...\n\nContext:\n1. Docker Compose allows...\n2. Services are defined...\n3. Volumes persist data...\n\nQuestion: How do I use Docker Compose?\n\nAnswer:"]

    F --> G[LLM]
    G --> H[Generated Answer with Citations]

    style E stroke:#f9f,stroke-width:2px
    style G stroke:#bbf,stroke-width:2px
```

### चरण 1: त्वरित निर्माण

यह है जहाँ RAG एक कला बन जाता है

- प्रदान की गई संदर्भ का उपयोग करता है (अंतरिक ज्ञान नहीं करता है
- जब संभव हो तो स्रोतों को उद्धृत करता है
- स्वीकार करता है जब संदर्भ में कोई जवाब नहीं है
- एक सुसंगत ध्वनि बनाए रखता है

**मेरे वकील GPT सिस्टम से उदाहरण प्रवर्धन टेम्प्लेट:**

```csharp
public string BuildRAGPrompt(string query, List<SearchResult> context)
{
    var sb = new StringBuilder();

    sb.AppendLine("You are a technical writing assistant. Your task is to answer the user's question using ONLY the provided context from past blog posts.");
    sb.AppendLine();
    sb.AppendLine("CONTEXT:");
    sb.AppendLine("========");

    for (int i = 0; i < context.Count; i++)
    {
        sb.AppendLine($"[{i + 1}] {context[i].Title}");
        sb.AppendLine($"Source: {context[i].Source}");
        sb.AppendLine($"Content: {context[i].Text}");
        sb.AppendLine($"Relevance: {context[i].Score:P0}");
        sb.AppendLine();
    }

    sb.AppendLine("========");
    sb.AppendLine();
    sb.AppendLine("INSTRUCTIONS:");
    sb.AppendLine("- Answer the question using the provided context");
    sb.AppendLine("- Cite sources using [1], [2], etc.");
    sb.AppendLine("- If the context doesn't contain enough information, say so");
    sb.AppendLine("- Maintain the technical, practical tone of the blog");
    sb.AppendLine();
    sb.AppendLine($"QUESTION: {query}");
    sb.AppendLine();
    sb.AppendLine("ANSWER:");

    return sb.ToString();
}
```

### चरण 2: LLM अंतर

निर्मित प्रवर्धन generating के लिए एलएलएम में जाता है. यह हो सकता है

- **क्लाउड API**OpenAI, Anthropic Claude
- **स्थानीय मॉडल**: लैमा का उपयोग करते हुए

**स्थानीय LLM का उपयोग करते हुए उदाहरण:**

```csharp
public async Task<string> GenerateResponseAsync(string prompt)
{
    var result = await _llamaSharp.InferAsync(prompt, new InferenceParams
    {
        Temperature = 0.7f,      // Creativity (0 = deterministic, 1 = creative)
        TopP = 0.9f,             // Nucleus sampling
        MaxTokens = 500,         // Response length limit
        StopSequences = new[] { "\n\n", "User:", "Question:" }
    });

    return result.Text.Trim();
}
```

**कुंजी पैरामीटरों का वर्णन**

- **तापमान**अनियमितता को नियंत्रित करता है
- **शीर्ष पी**: न्यूक्लियस नमूनाकरण - केवल टोकन मानते हैं जो शीर्ष पी संभाव्यता द्रव्यमान बनाती है
- **अधिकतम टोकन**: सीमा प्रतिक्रिया लंबाई
- **अनुक्रम रोकें**: जब उत्पादन बंद करना है

### चरण 3: पोस्ट

LLM एक प्रतिक्रिया उत्पन्न करने के बाद हम अक्सर करने की जरूरत है

- उद्धरण निकालें और उन्हें लिंक में बदलें
- कोड ब्लॉक फ़ॉर्मेट करें
- मेटाडेटा जोड़ें
- त्रुटिमोचन के लिए संवाद लॉग करें

**उदाहरण पोस्ट-प्रसंस्करण**

```csharp
public RAGResponse PostProcess(string llmOutput, List<SearchResult> sources)
{
    var response = new RAGResponse
    {
        Answer = llmOutput,
        Sources = new List<Source>()
    };

    // Extract citations like [1], [2]
    var citations = Regex.Matches(llmOutput, @"\[(\d+)\]");

    foreach (Match match in citations)
    {
        int index = int.Parse(match.Groups[1].Value) - 1;
        if (index >= 0 && index < sources.Count)
        {
            var source = sources[index];
            response.Sources.Add(new Source
            {
                Title = source.Title,
                Url = GenerateUrl(source.Source),
                RelevanceScore = source.Score
            });
        }
    }

    // Convert markdown citations to hyperlinks
    response.FormattedAnswer = Regex.Replace(
        llmOutput,
        @"\[(\d+)\]",
        m => {
            int index = int.Parse(m.Groups[1].Value) - 1;
            if (index >= 0 && index < sources.Count)
            {
                var url = GenerateUrl(sources[index].Source);
                return $"[[{m.Groups[1].Value}]]({url})";
            }
            return m.Value;
        }
    );

    return response;
}
```

# एलएलएम आंतरिक को समझना

हम व्यावहारिक अनुप्रयोगों के लिए आगे बढ़ने से पहले, यह है' यह आवश्यक है कि LLMs कैसे आंतरिक रूप में काम करने को समझें।

## टोकन क्या हैं

टोकन उन बुनियादी इकाइयों हैं जो LLMs प्रक्रिया करता है

**उदाहरण टोकनीकरण:**

```
Input:  "Understanding Docker containers"
Tokens: ["Under", "standing", " Docker", " containers"]
```

भिन्न मॉडल भिन्न टोकनीकरण रणनीतियों का उपयोग करते हैं

- **जीपीटी मॉडल**: Byte का उपयोग करें-Pair एनकोडिंग
- **क्लाउड**: समान बीपीई दृष्टिकोण
- **ललामा मॉडल**: SentencePiece टोकनीकरण

**why tokenization matters for RAG:**

```csharp
public class TokenCounter
{
    // Rough approximation: 1 token ≈ 0.75 words (English)
    public int EstimateTokens(string text)
    {
        var wordCount = text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
        return (int)(wordCount / 0.75);
    }

    public int EstimateTokensAccurate(string text, ITokenizer tokenizer)
    {
        // Use actual tokenizer for precision
        return tokenizer.Encode(text).Count;
    }
}
```

**संदर्भ विंडो सीमाएँ**

- GPT-3.5: 16K टोकन
- GPT-4: M SK1K-128K टोकन
- क्लाउड 3.5 सोनेट
- Llama 3: 8K टोकन (जब भी विस्तारित किया जा सकता है

RAG प्रणालियों में आपको फिट होना चाहिए

```
Total tokens = System prompt + Retrieved context + User query + Response buffer
```

यदि आपका आरएजी क्वेरी और प्रतिक्रिया से पहले प्रत्येक टन के टन की 500 दस्तावेजों को प्राप्त करता है

**व्यावहारिक RAG टोकन प्रबंधन**

```csharp
public class ContextWindowManager
{
    private readonly int _maxContextTokens;
    private readonly int _systemPromptTokens;
    private readonly int _responseBufferTokens;

    public ContextWindowManager(
        int totalContextWindow = 4096,
        int systemPromptTokens = 300,
        int responseBufferTokens = 500)
    {
        _maxContextTokens = totalContextWindow;
        _systemPromptTokens = systemPromptTokens;
        _responseBufferTokens = responseBufferTokens;
    }

    public List<SearchResult> FitContextInWindow(
        List<SearchResult> retrievedDocs,
        string query)
    {
        var queryTokens = EstimateTokens(query);

        // Available tokens for retrieved context
        var availableForContext = _maxContextTokens
            - _systemPromptTokens
            - queryTokens
            - _responseBufferTokens;

        var selectedDocs = new List<SearchResult>();
        var currentTokens = 0;

        foreach (var doc in retrievedDocs.OrderByDescending(d => d.Score))
        {
            var docTokens = EstimateTokens(doc.Text);

            if (currentTokens + docTokens <= availableForContext)
            {
                selectedDocs.Add(doc);
                currentTokens += docTokens;
            }
            else
            {
                break; // Context window full
            }
        }

        return selectedDocs;
    }

    private int EstimateTokens(string text)
    {
        // Rule of thumb: 1 token ≈ 4 characters
        return text.Length / 4;
    }
}
```

## केवी कैश

जब एलएलएम पाठ उत्पन्न करता है, तो यह हर टोकन के लिए आरंभिक से सब कुछ पुनः प्रसंस्करण नहीं करता **कुंजी** याद करने के लिए क्या यह पहले से ही संगणित किया है.

### कैसे ट्रांसफॉर्मर काम करता है (Simplified

ट्रांसफार्मर्स एक "attention" क्रियाकलाप का प्रयोग करते हैं जहां प्रत्येक टोकन "attends toM SK3

```mermaid
flowchart TB
    subgraph "Generation Step 1: 'Docker'"
        A1[Input: 'Docker'] --> B1[Compute K,V for 'Docker']
        B1 --> C1[Store in KV Cache]
        C1 --> D1[Generate: 'is']
    end

    subgraph "Generation Step 2: 'is'"
        A2[Input: 'is'] --> B2[Compute K,V for 'is']
        B2 --> C2[Store in KV Cache]
        C2 --> E2[Retrieve KV for 'Docker']
        E2 --> F2[Attend: 'is' to 'Docker']
        F2 --> D2[Generate: 'a']
    end

    subgraph "Generation Step 3: 'a'"
        A3[Input: 'a'] --> B3[Compute K,V for 'a']
        B3 --> C3[Store in KV Cache]
        C3 --> E3[Retrieve KV for 'Docker', 'is']
        E3 --> F3[Attend: 'a' to all previous]
        F3 --> D3[Generate: 'container']
    end

    D1 --> A2
    D2 --> A3

    style C1 stroke:#f9f,stroke-width:3px
    style C2 stroke:#f9f,stroke-width:3px
    style C3 stroke:#f9f,stroke-width:3px
```

**केवी कैश के बिना**

- चरण 1: प्रक्रिया
- चरण 2: प्रक्रिया
- चरण 3: प्रक्रिया
- कुल

**केवी कैश के साथ**

- चरण 1: प्रक्रिया 1 टोकन
- चरण 2: प्रक्रिया 1 नया टोकन, पुनः कैश किया गया K
- चरण 3: प्रक्रिया 1 नया टोकन, पुनः कैश किया गया K
- कुल

यह पीढ़ी बनाता है **तेजी से** के बीच - अंतर

### केवी कैश ट्री संरचना

केवी कैश एक "tree" का निर्माण करता है क्योंकि रूपांतरक में ध्यान कैसे काम करता है।

```mermaid
graph TB
    A[Input Tokens:<br/>'What is Docker?'] --> B[Layer 1 Attention]
    B --> C[Layer 1 KV Cache]

    B --> D[Layer 2 Attention]
    D --> E[Layer 2 KV Cache]

    D --> F[Layer 3 Attention]
    F --> G[Layer 3 KV Cache]

    F --> H[... up to Layer N]
    H --> I[Output: 'Docker is']

    C -.Key-Value pairs<br/>for all input tokens.-> C
    E -.Key-Value pairs<br/>for all input tokens.-> E
    G -.Key-Value pairs<br/>for all input tokens.-> G

    style C stroke:#bbf,stroke-width:2px
    style E stroke:#bbf,stroke-width:2px
    style G stroke:#bbf,stroke-width:2px
```

**प्रत्येक परत भंडारित करता है**

- **कुंजियाँ (**: ध्यान प्राप्तियों को संगणित करने के लिए प्रयुक्त प्रतिनिधित्व
- **मान (V**: ध्यान के आधार पर एक साथ मिश्रित प्रतिनिधित्व

के साथ एक मॉडल के लिए

- 32 स्तर
- 4096 छुपे आयाम
- 32 ध्यान शीर्ष
- 8K संदर्भ विंडो

एक अनुक्रम के लिए केवी कैश है:

```
2 (K and V) × 32 layers × 4096 dimensions × 8192 tokens × 2 bytes (FP16)
≈ 4.3 GB of VRAM!
```

इसीलिए लंबा संदर्भ विंडो मेमोरी हैं

### आरएजी सिस्टम में केवी कैश

आरएजी प्रणालियां केवी कैश अनुकूलन को चुने हुए तरीकों में उपयोग कर सकती हैं

**त्वरित कैचिंग** एंट्रोपिक क्लोड जैसे कुछ API द्वारा समर्थित

```csharp
public class CachedRAGService
{
    // System prompt and retrieved context can be cached!
    public async Task<string> GenerateWithCachedContextAsync(
        string systemPrompt,          // Cached
        List<SearchResult> context,   // Cached
        string userQuery)             // Not cached, changes each time
    {
        var contextText = FormatContext(context);

        // The KV cache for systemPrompt + contextText is reused across queries
        var prompt = $@"
{systemPrompt}

CONTEXT:
{contextText}

QUERY: {userQuery}

ANSWER:";

        return await _llm.GenerateAsync(prompt, useCaching: true);
    }
}
```

**यह क्यों शक्तिशाली है**

- पहली क्वेरी: तंत्र प्रवर्धन के लिए केवी कैश का संगणन करता है
- एक ही संदर्भ के साथ अनुवर्ती क्वेरी
- सिर्फ उपयोक्ता क्वेरी भाग को नए संगणन की जरूरत है

**व्यावहारिक उदाहरण**

```
Query 1: "How do I use Docker?" → 2 seconds (no cache)
Query 2: "What are Docker benefits?" → 0.2 seconds (cache hit!)
Query 3: "Docker vs VMs?" → 0.2 seconds (cache hit!)
```

सभी तीन प्रश्न एक ही प्राप्त संदर्भ का उपयोग करते हैं, इसलिए उस संदर्भ के लिए केवी कैश फिर से प्रयोग किया जाता है

## टोकन सीमाएं और आरएजी रणनीति

टोकन और केवी कैश को समझने से आपके RAG वास्तुकला निर्णयों का पता चलता है

### 1. आकार

छोटे टुकड़े = अधिक सूक्ष्म पुनर्प्राप्ति, लेकिन अधिक ओवरहेड

```csharp
// Option A: Small chunks (200 tokens each)
// Retrieve 20 chunks = 4,000 tokens
// Pro: Very precise, only relevant info
// Con: More KV cache entries, slower attention

// Option B: Larger chunks (500 tokens each)
// Retrieve 8 chunks = 4,000 tokens
// Pro: Better context coherence, fewer KV entries
// Con: More noise, less precise

public class AdaptiveChunker
{
    public int DetermineChunkSize(int contextWindowSize)
    {
        if (contextWindowSize <= 4096)
            return 200; // Small chunks for limited windows

        if (contextWindowSize <= 16384)
            return 500; // Medium chunks

        return 1000; // Large chunks for big windows
    }
}
```

### 2. संदर्भ विंडो उपयोग

संदर्भ विंडो को अधिकतम नहीं करें

```csharp
public class SafeContextManager
{
    public int GetSafeContextLimit(int totalContextWindow)
    {
        // Use only 75% for input, reserve 25% for output
        return (int)(totalContextWindow * 0.75);
    }

    // Example: 4K model
    // Total: 4096 tokens
    // Safe input: 3072 tokens
    // Reserved for output: 1024 tokens
}
```

### 3. बहुल-आरएजी वार्तालाप चलाएँ

चैटबोट्स में वार्तालाप इतिहास हर बार बढ़ता है

```
Turn 1:
System + Context + Query1 = 3000 tokens
Response1 = 300 tokens
Total: 3300 tokens

Turn 2:
System + Context + Query1 + Response1 + Query2 = 3650 tokens
Response2 = 300 tokens
Total: 3950 tokens

Turn 3:
System + Context + Query1 + Response1 + Query2 + Response2 + Query3 = 4250 tokens
ERROR: Context window exceeded!
```

**समाधान: पुनर्प्राप्ति के साथ स्लाइडिंग विंडो**

```csharp
public class ConversationalRAG
{
    private readonly int _maxHistoryTokens = 1000;

    public async Task<string> ChatAsync(
        List<ConversationTurn> history,
        string newQuery)
    {
        // Re-retrieve context based on current query
        var context = await RetrieveContextAsync(newQuery);

        // Keep only recent conversation history
        var relevantHistory = TrimHistory(history, _maxHistoryTokens);

        var prompt = BuildPrompt(context, relevantHistory, newQuery);

        return await _llm.GenerateAsync(prompt);
    }

    private List<ConversationTurn> TrimHistory(
        List<ConversationTurn> history,
        int maxTokens)
    {
        var trimmed = new List<ConversationTurn>();
        var currentTokens = 0;

        // Keep most recent turns
        foreach (var turn in history.Reverse())
        {
            var turnTokens = EstimateTokens(turn.Query) + EstimateTokens(turn.Response);

            if (currentTokens + turnTokens <= maxTokens)
            {
                trimmed.Insert(0, turn);
                currentTokens += turnTokens;
            }
            else
            {
                break;
            }
        }

        return trimmed;
    }
}
```

### 4. टोकन लागत अनुकूलन

API-आधारित एलएलएम्स प्रति टोकन प्रभार

```csharp
public class CostAwareRAG
{
    // OpenAI GPT-4 pricing (example):
    // Input: $0.03 per 1K tokens
    // Output: $0.06 per 1K tokens

    public decimal EstimateQueryCost(
        int systemPromptTokens,
        int retrievedContextTokens,
        int queryTokens,
        int expectedResponseTokens)
    {
        var inputTokens = systemPromptTokens + retrievedContextTokens + queryTokens;
        var outputTokens = expectedResponseTokens;

        var inputCost = (inputTokens / 1000m) * 0.03m;
        var outputCost = (outputTokens / 1000m) * 0.06m;

        return inputCost + outputCost;
    }

    // Example:
    // System: 300 tokens
    // Context: 3000 tokens (10 retrieved docs)
    // Query: 50 tokens
    // Response: 500 tokens
    //
    // Cost = ((300 + 3000 + 50) / 1000 * 0.03) + (500 / 1000 * 0.06)
    //      = (3350 / 1000 * 0.03) + (500 / 1000 * 0.06)
    //      = $0.1005 + $0.03
    //      = $0.1305 per query
    //
    // At 1000 queries/day = $130/day = $3,900/month!
}
```

**लागत कम करने की रणनीति**

1. कम प्राप्त करें
2. त्वरित कैशिंग का उपयोग करें
3. के लिए सस्ती मॉडल का उपयोग करें
4. संक्षेपण का उपयोग करते हुए संदर्भ को दबाएँ

## टोकन के साथ पूर्ण RAG प्रवाह को दृश्यात्मक बनाना

यहाँ यह दिखाता है कि टोकन कैसे मिलते हैं

```mermaid
flowchart TB
    A[User Query:<br/>'How does Docker work?'<br/>≈ 12 tokens] --> B[Generate Query Embedding]

    B --> C[Vector Search]
    C --> D[Retrieved Docs:<br/>5 docs × 500 tokens<br/>= 2,500 tokens]

    D --> E[Construct Prompt]
    A --> E

    E --> F["Complete Prompt:<br/>System: 300 tokens<br/>Context: 2,500 tokens<br/>Query: 12 tokens<br/>Total: 2,812 tokens"]

    F --> G[Tokenize Prompt]
    G --> H["Token IDs:<br/>[245, 1034, 8829, ...]<br/>2,812 token IDs"]

    H --> I[LLM Layer 1]
    I --> J[Compute K,V]
    J --> K[KV Cache Layer 1:<br/>2,812 K,V pairs]

    I --> L[LLM Layer 2]
    L --> M[Compute K,V]
    M --> N[KV Cache Layer 2:<br/>2,812 K,V pairs]

    L --> O[... Layers 3-32]
    O --> P[Generate Token 1: 'Docker']

    P --> Q[Add to KV Cache]
    Q --> R[Generate Token 2: 'is']
    R --> S[Add to KV Cache]
    S --> T[... until completion]

    T --> U["Response: 'Docker is a containerization platform...'<br/>≈ 400 tokens"]

    style K stroke:#f9f,stroke-width:2px
    style N stroke:#f9f,stroke-width:2px
    style Q stroke:#bbf,stroke-width:2px
    style S stroke:#bbf,stroke-width:2px
```

**प्रमुख अंतर्दृष्टि**

1. **इनपुट टोकन** आरंभिक केवी कैश बनाने के लिए (2,812) को एक बार प्रक्रमित किया जाता है
2. **जनन** केवी कैश का पुनः उपयोग करते हुए एक बार में एक टोकन होता है
3. **प्रत्येक नया टोकन** भावी टोकन के लिए केवी कैश में जोड़ता है
4. **कुल VRAM** सभी टोकन के लिए आवश्यक = मॉडल वज़न + केवी कैश
5. **लंबा संदर्भ** = बड़ा केवी कैश

## आरएजी के लिए व्यावहारिक प्रभाव

टोकन और केवी कैश को समझने से बेहतर RAG डिजाइन प्राप्त होता है

**1. Pre-कम्प्यूटर और कैश सामान्य संदर्भ**

```csharp
// Cache KV for frequently used system prompts + static context
var cachedSystemContext = await _llm.PrecomputeKVCache(systemPrompt + staticContext);

// Reuse for each query (much faster)
foreach (var query in userQueries)
{
    var response = await _llm.GenerateAsync(query, reuseKVCache: cachedSystemContext);
}
```

**2. खंड सीमाओं को अनुकूलित करें**

```csharp
// Bad: Arbitrary 500-character chunks
var chunks = text.Chunk(500);

// Good: Chunk on sentence boundaries, measure in tokens
public List<string> ChunkByTokens(string text, int maxTokensPerChunk)
{
    var sentences = SplitIntoSentences(text);
    var chunks = new List<string>();
    var currentChunk = new StringBuilder();
    var currentTokens = 0;

    foreach (var sentence in sentences)
    {
        var sentenceTokens = EstimateTokens(sentence);

        if (currentTokens + sentenceTokens > maxTokensPerChunk && currentTokens > 0)
        {
            chunks.Add(currentChunk.ToString());
            currentChunk.Clear();
            currentTokens = 0;
        }

        currentChunk.Append(sentence).Append(" ");
        currentTokens += sentenceTokens;
    }

    if (currentTokens > 0)
        chunks.Add(currentChunk.ToString());

    return chunks;
}
```

**उत्पादन में टोकन उपयोग मॉनिटर करें**

```csharp
public class RAGTelemetry
{
    public void LogRAGQuery(
        string query,
        List<SearchResult> retrievedDocs,
        string response)
    {
        var queryTokens = EstimateTokens(query);
        var contextTokens = retrievedDocs.Sum(d => EstimateTokens(d.Text));
        var responseTokens = EstimateTokens(response);
        var totalTokens = queryTokens + contextTokens + responseTokens;

        _logger.LogInformation(
            "RAG Query: {Query} | Context: {ContextTokens} tokens from {DocCount} docs | " +
            "Response: {ResponseTokens} tokens | Total: {TotalTokens} tokens",
            query, contextTokens, retrievedDocs.Count, responseTokens, totalTokens
        );

        // Alert if approaching context limit
        if (totalTokens > _maxTokens * 0.9)
        {
            _logger.LogWarning("Approaching token limit: {TotalTokens}/{MaxTokens}",
                totalTokens, _maxTokens);
        }
    }
}
```

# निष्कर्ष: वास्तुकला मास्टरी

हमने RAG प्रणालियों की संपूर्ण तकनीकी संरचना को शामिल किया है

**चरण 1: सूचकांकन**

- विभिन्न स्रोतों से पाठ उद्धरण
- कार्यनीतियां (सेक्शन-के आधार पर,सेक्शन\-के आधारपर,के साथ ओवरलैप के साथ)
- सम्मिलन उत्पादन (ONNX, API सेवाएंM SK2
- वेक्टर भंडारण (Qdrant

**चरण 2: पुनःप्राप्ति**

- Query embedding (same model as indexing
- समानता खोज (cosine, euclideanM SK2 dot product
- बेहतर सूक्ष्मता के लिए वैकल्पिक पुनर्रोकिंग
- परिष्कृत परिणाम के लिए मेटाडेटा फ़िल्टरिंग

**चरण 3: उत्पादन**

- त्वरित निर्माण (प्रसंगत | + | अनुदेश |+ | प्रश्न
- LLM निष्कर्ष (temperature, topM SK2pMSC3 max tokensMSL4
- प्रक्रमण के बाद -प्रसंस्करण

**एलएलएम आंतरिक**

- टोकन: बुनियादी इकाइयां | ( | क्यारेक्टर नहीं
- केवी कैश: क्यों उत्पादन तेजी से होता है | ( | linear | , | quadratic नहीं |)
- संदर्भ विंडों: RAG में टोकन सीमाओं का प्रबंधन
- लागत अनुकूलन: कैचिंग

**प्रमुख तकनीकी अंतर्दृष्टि**

1. **एक ही एम्बेडिंग मॉडल** अनुक्रमण और पुनःप्राप्ति के लिए (criticalM SK1
2. **आप सोचने से ज्यादा बात है** - सेमेटिक संगतता बनाए रखता है
3. **पुनरावर्तन सूक्ष्मता में सुधार करता है** विलंब की कीमत पर
4. **टोकन प्रबंधन अनिवार्य है** क्वेरी करने से पहले - अनुमान
5. **केवी कैचिंग RAG को व्यवहार्य बनाता है** - पुनः प्रवर्धन गणना
6. **संदर्भ विंडो तेजी से भरें** डॉक

# भाग 3: RAG को व्यावहारिक रूप में जारी रखें

अब आप समझते हैं **RAG कैसे काम करता है** तकनीकी स्तर पर

में **[भाग 3: RAG व्यावहारिक में](/blog/rag-practical-applications)**हम वास्तुकला से कार्यान्वयन में ले जा रहे हैं

**वास्तविक**

- इस ब्लॉग पर संबंधित पोस्ट की सिफारिश
- अर्थात्मक ब्लॉग खोज
- एक "Lawyer GPT" लेखन सहायक का निर्माण

**सामान्य चुनौतियां और समाधान**

- संदर्भ को बनाए रखने वाले कार्यनीतियां
- अपने डोमेन के लिए एम्बेडिंग गुणवत्ता में सुधार
- संदर्भ विंडो सक्रिय रूप से प्रबंधित करना
- संदर्भ होने के बावजूद भ्रम को रोकना
- अपने अनुक्रमणिका को अद्यतन रखें

**उन्नत तकनीकें**

- संभावित दस्तावेज़ सम्मिलन (HyDE)
- LLM के साथ स्वचालित विच्छेदित फ़िल्टर
- व्यापक परिणाम के लिए बहु--query RAG
- टोकन उपयोग को कम करने के लिए संदर्भात्मक संकुचन
- जटिल क्वेरी के लिए Multi-hop RAG
- दीर्घकालिक वार्तालाप स्मृति

**आरंभ कर रहा हूँ**

- सप्ताह के कार्यान्वयन योजना
- व्यवहारिक कोड उदाहरण
- अनुकूलन रणनीतियां
- जब RAG का उपयोग नहीं करना है

**[भाग को जारी रखें 3: व्यावहारिक में RAG](/blog/rag-practical-applications)**

## संसाधन

**आधारभूत कागजात**

- [पुनःप्राप्ति-ज्ञान के लिए उन्नत जनन-सभी एनएलपी कार्य](https://arxiv.org/abs/2005.11401) - मूल RAG कागज
- [ओपन- डोमेन प्रश्न उत्तरण के लिए दाने पासेजtrieval](https://arxiv.org/abs/2004.04906) - पीआरडी आधार
- [ध्यान सब कुछ है जो आपको चाहिए](https://arxiv.org/abs/1706.03762) - ट्रांसफार्मर्स

**उपकरण और फ्रेमवर्क**

- [क्वारंटCity name (optional, probably does not need a translation)](https://qdrant.tech/) - भेक्टर डाटाबेस
- [ऑनिक्स रनटाइम](https://onnxruntime.ai/) @info: whatsthis
- [लामाशर्प](https://github.com/SciSharp/LLamaSharp) स्थानीय एलएलएम निष्कर्ष
- [वाक्य ट्रांसफार्मर्स](https://www.sbert.net/) - सम्मिलन मॉडल

**आगे पढ़ने:**

- [मानवीय: संदर्भीय खोज](https://www.anthropic.com/index/contextual-retrieval) एमएसके0 उन्नत तकनीकें

**श्रेणी नेविगेशन**

- [भाग 1: मूल और बुनियादी](/blog/rag-primer) - इतिहास और प्रेरणा
- **भाग 2: वास्तुकला और आंतरिक** (इस अनुच्छेद) - तकनीकी गहराई खन
- [भाग 3: RAG व्यावहारिक में](/blog/rag-practical-applications) - वास्तविक प्रणाली निर्माण

**[भाग में जारी रखें](/blog/rag-practical-applications)**