الهندسة المعمارية والداخلية : كيف تعمل (العربية (Arabic))

الهندسة المعمارية والداخلية : كيف تعمل

Saturday, 22 November 2025

//

26 minute read

داخل الجزء الأولفهمنا المفهوم الرفيع المستوى: استعادة المعلومات ذات الصلة، ثم استخدامها لتوليد ردود الفعل. الآن نغوص بعمق في العمارة التقنية - بالضبط كيف تعمل أنظمة RAG تحت غطاء المحرك، من استراتيجيات تقسيم إلى داخلية LLM مثل الرسوم البيانية ومخابئ KV.

أولاً

مجموعة القواعد النموذجية للملاحة: هذا هو الجزء الثاني من سلسلة RAG:

إذا لم تقرأ الجزء الأول، أوصي بالبداية هناك لفهم:

  • ما هو الفريق وما هو السبب في أهميته
  • التاريخ من البحث عن الكلمات الرئيسية إلى الفهم المائل
  • RAG vs دق الرققة والنُهُج الأخرى

هذه المادة تفترض أنك تفهم تلك الأساسيات وتركز على الهندسة الهيكلية التقنية، وتفاصيل التنفيذ، وضوابط الإدارة المحلية للأراضي.

كيف يعمل العمل : الصورة الكاملة

دعونا نقسم بالضبط ما يحدث في نظام RAG، من اللحظة التي تضيف فيها مستنداً إلى الوقت الذي يحصل فيه المستخدم على جواب.

المرحلة 1: الفهرسة (إعداد قاعدة المعارف)

قبل أن يستطيع RAG استرجاع أي شيء، تحتاج إلى فهرسة قاعدة معرفتك. هذه عملية لمرة واحدة (بالرغم من أنه يمكنك إضافة وثائق جديدة في وقت لاحق).

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: النص

يمكن أن يكون هذا النص كما يلي:

  • ملفات التدرج (مثل تدوينات مدونتي)
  • PDFs (للوثائق)
  • HTMTML (ل‍ (ل‍ (ل‍ (ل‍ (ل‍ (ل‍
  • سجلات قواعد
  • البريد الإلكتروني، وسجلات الدردشة، وما إلى ذلك.

من مدونتي:

// 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. لا يمكنك فقط تقسيم على حدود الفقرة - تحتاج إلى قطع مترابطة بشكل دلالي.

لِمَ يَهْمُّ تَقْسِيمُ ٱلْأَمْرِ :

  • LLLs لها حدود رمزية (نوافذ سياق)
  • قطع صغيرة = أكثر دقة
  • ولكن يجب أن تحتوي القطع على سياق كافٍ ليكون مجدياً

جاري:

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"

من تطبيق بحثي الدهني:

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

استراتيجيات تجميع الموازنات:

  • ASSCSSS: بسيط ولكن يكسر الحدود المائلة
  • المعتمدة في حُكم الحُكماتاحترام القواعد لكن يمكن أن تكون صغيرة جداً
  • دال دال في الفقرة:: من الناحية الطبيعية ولكن بالحجم المتغيّر
  • الوظائف الممولة من تكاليف خدماتأفضل لمحتوى منظم (أفضلية)
  • نافذة & مع تداخلضمان عدم فقدان أي سياق عند الحدود:

خطوة إعداد مخطوطات

الـ هو سحر هو الذي يجعل البحث الدلالي ممكن الضم هو a متجه من الـ نص.

المفهوم الرئيسي: 2 - دال - دال - دال - دال - دال - دال - دال -

"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]

المتجهان الأولان سيكونان "مغلقين" في فضاء المتجه (مشابهة التمام العالي)، في حين أن المتجه الثالث بعيد جداً.

كيف يتم توليد المقومات: نماذج الترسيخ الحديثة هي شبكات عصبية مدربة على مجموعات بيانات نصية ضخمة لتعلم العلاقات الدلالية. النماذج الشعبية:

  • طراز MINIM-L6-v2: 384 أبعاد، سرعة، جودة جيدة (ما أستخدمه في هذه المدونة)
  • ثالثاً - 1536 بعداً، عالية الجودة جداً
  • BGG- القاعدة768 بعداً، مصدر مفتوح حديث للخبرة

مثال من خدمة التضمين OONNX:

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

أسباب التطبيع: بعد التطبيع L2، تشابه تمام يصبح منتج نقطة بسيطة، مما يجعل البحث أسرع بكثير.

الخطوة 4: خزن في قاعدة بيانات v

وتُحسَّن قواعد بيانات المتجهات إلى أقصى حد لتخزين النواقل العالية الأبعاد والبحث عنها. فبخلاف قواعد البيانات التقليدية التي تستخدم استفسارات SQL، تستخدم قواعد بيانات المتجهات بحث التشابه.

العمليات الرئيسية:

  • ****إضافة أو تحديث ناقل مع بيانات
  • ****اوجد K أكثر تشابهاً لـ a متجه
  • **& لا شيء.**البحث مع المرشّحات

التنفيذ على سبيل المثال:

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

قواعد بيانات النواقل الشعبية:

  • ****: دعم سريع، ذاتي الاستخدام، ممتاز C# دعم (اختياري)
  • (ج) مُنْفِجِكَر: PostgreSQL امتداد (كبير إذا كنت بالفعل تستخدم Postgres)
  • رابعاً -: الخدمة المنظمة )كثافية ولكن جيدة(
  • مُنَي مُنْي: مادة غنية بالزينة ، جيدة للكيماويات المعقدة
  • ككرونDB: تركيز البيثون، خفيف الوزن

سنستكشف إنشاء قواعد البيانات هذه في المقالات القادمة

المرحلة 2: الاسترداد (المعلومات الاستقصائيـة ذات الصلـة)

وعندما يطرح أحد المستعملين سؤالاً، يحتاج نظام RAG إلى العثور على أكثر المعلومات صلة بالموضوع من قاعدة المعارف.

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

& خطوة: س توليد سِئ مَثثث

سؤال المستخدم يحصل تحويلاً إلى متجه مستخدماً نموذج وهذا أمر حاسم - فالنماذج المختلفة تنتج متجهات غير متوافقة.

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: بحث التشابه

قاعدة بيانات المتجه computes تشابه بين متجه الاشارة وجميع المتجهات المختزنة.

التشابه (الأكثر شعبية بالنسبة إلى المتجهات المُتَطَوَّدة):

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

المدى: -1 إلى 1 (الارتفاع = أكثر تشابهاً)

عن طريق Euclisity (للمتجهات غير المتماثلة):

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

المدى: 0 إلى كيلوغرام (الأدنى = أكثر تشابهاً)

**** (عندما تكون المتجهات سابقة للتصنيف):

similarity = A · B

المدى: -1 إلى 1 (الارتفاع = أكثر تشابهاً)

مِنْ خدمةِ Qdtrantي:

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: الدرجة الثالثة: المرتبة (الخيار ولكن موصى به)

الاسترجاع الأولي سريع ولكن تقريبي. إعادة الترتيب تستخدم نموذج أكثر تطوراً لاستعادة نتائج K العليا.

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

لماذا تساعد إعادة الترتيب :

  • النماذج السريعة المُرسِزة للسرعة تُحسّب للسرعة، تُضحّي ببَعْض الدقة
  • نماذج إعادة الترتيب أبطأ ولكن أكثر دقة
  • الموازنتان من حيث السرعة والنوعية

يُعاد ترتيب التنفيذ:

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 جنبا إلى جنب مع سؤال المستخدم.

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 فنًا. تحتاج إلى تركيب التسارع لذلك LLM:

  • استخدامات السياق المقدم (وليس معارفه الداخلية)
  • المصادر المُسْتَيْشِسَة عند الإمكان
  • يعترف عندما لا يحتوي السياق على جواب
  • يُبقي على نبرة/أسلوب ثابتين

نموذج سريع من نظام محاميي GPT:

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: LL LL

الـ مشيّد الـ إلى LLM لـ توليد هذا:

  • Q Name: OpenAI، Anthropic كلود، جوجل PALM
  • نموذج محلي محلياستخدام لاما.Cpp، أو OONNX وقت التشغيل، أو تورش شارب

مثال باستخدام LLLL محلياً:

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

(أ) البارامترات الرئيسية الموضحة:

  • درجة درجة: ضوابط عشوائيات (0. = دائماً اختيار أكثر احتمالاً، 1 = عيّنة عشوائياً)
  • & أعلى: أخذ عينات النواة - النظر فقط في العوارض التي تشكل كتلة احتمالية أعلى P
  • المتكنكSطول الرد على الحد الأدنى
  • تَوقّف المتتابعاتمتى تتوقف عن توليد

الخطوة 3: ما بعد

وبعد أن تولد الإدارة المستدامة للأراضي استجابة، نحتاج في كثير من الأحيان إلى ما يلي:

  • مقتطفات من الاقتباسات وتحويلها إلى روابط
  • فكّك
  • (المصادر، درجات الثقة)

مرحلة ما بعد التجهيز:

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

تَفْكِس LLLLL LL LL L L L L L L L L L L L L L L L L LL داخليات الداخليات: Tokns, KV Cche, و السياق ويندز

قبل أن ننتقل إلى التطبيقات العملية، من الضروري فهم كيفية عمل LLMs داخليا. هذه المعرفة تساعدك على تحسين أنظمة RAG وتجنب المزالق المشتركة.

مَا هِيَ تُوَكُنُسُ ؟

التوكنات هي الوحدات الأساسية التي يعالجها LLLMs. النص لا يغذي مباشرة إلى النماذج -- إنه أولاً يقسم إلى رموز.

& & & & &:

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

تستخدم النماذج المختلفة استراتيجيات مختلفة للرمز:

  • نماذج GPSTاستخدم الترميز (BPE) بترميز الهواء (BPE) مع _50K مفردات
  • كلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكلكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكلكلكلكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل الكل: نهج مماثل في مجال الممتلكات والمنشآت
  • نماذج Lllame: تأشيرة المحكمة

السبب في أن التسويف مهم بالنسبة للفريق:

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: 16 ك
  • GPPT-4: 8K- 128K رمز (حسب المتغير)
  • 3,5 3,5 سونت: 200 ألف رمز
  • Lalama 3: 8K رمزي (وإن كان يمكن تمديده)

في أنظمة RAG، يجب أن تلائم:

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

إذا كان فريقك يسترجع 10 وثائق من 500 رمز لكل منها، هذا هو 5000 رمز فقط للسياق - قبل الاستعلام والإجابة!

(ج) الإدارة الصورية العملية RAG:

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

KV KV محفظة: سلاح LLM السري

عندما تقوم LLLLM بتوليد النص، فإنه لا يعيد تجهيز كل شيء من الصفر لكل رمز. إنه يستخدم a مفتاح المخبأ (KVV) مخبئ أن نتذكر ما تم حسابه بالفعل.

كيف تعمل المحولات (مصغرة)

المحولات تستخدم آلية "إهتمام" حيث كل رمز "يتوجه إلى" (النظرات على) جميع الرموز السابقة لفهم السياق.

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

بدون KV:

  • الخطوة 1: الخطوة 1: العملية 1
  • الخطوة 2: العملية 2
  • الخطوة 3: العملية 3 أرقام رمزية من الصفر o سين (3)
  • المجموع: O(1)+2+3+3++...+(ن) = O(N2)

مع KV

  • الخطوة 1: الخطوة 1: العملية 1
  • الخطوة 2: العملية 1 رمز رمزي جديد، مُعاد الاستخدام مُخزَّز مُخْزَأ K, V o O (1)
  • الخطوة 3: الخطوة 3: العملية 1 رمز رمزي جديد، مُعاد الاستخدام
  • المجموع: ع (نون)

هذا يكوّل - - - - - - - - - - - - - - - - - - - - - - الفرق بين 10 رمزات/ثانية و100 رمز/ثانية.

الـ KV KV محفظ مُجل مُجل شجرة

المخبأ KV يتشكل من "شجرة" بسبب كيفية عمل الاهتمام في المحولات. كل طبقة في النموذج لديها مصفوفات K، V الخاصة بها.

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

(أ) كل مخزن:

  • المفاتيح (KK): العروض المستخدمة في حساب درجات الاهتمام
  • **القيم )VV(**المواقف التي تختلط معاً على أساس الاهتمام

لنموذج يحتوي على:

  • 32 طبقة
  • 4096 الأبعاد
  • 32 من رؤساء
  • نافذة السياق 8K K 8K

مخبئ KV لـ 1 هو:

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

وهذا هو السبب في أن نوافذ الإطار الطويل كثيفة الاستعمال للذاكرة.

KV المخبأ بوصة RASSS

يمكن لأنظمة RAG أن تُعزز مخبئ KV بطرائق ذكية:

**** (يدعمها بعض APIs مثل Anthropic كلود):

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

لماذا هذا قوي:

  • السؤال الأول: مستخدمات KV KV مخبئ لـ النظام فوري + سياق (منخفض)
  • الاستفسارات اللاحقة مع السياق نفسه: إعادة استخدام المخبأ KV (10 x أسرع!)
  • فقط المستخدم الذي يُطلب من جزء استعلام الجزء يحتاج إلى حساب جديد

المثال العملي:

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

وتستخدم جميع الاستفسارات الثلاثة السياق المسترجع نفسه، ولذلك يعاد استخدام مخبأ KV لذلك السياق.

أولاً - الحدود والاستراتيجية الأساسية

رموز الفهم ومخبأ KV يُعلم قراراتك المعمارية:

1. siscking Sis

قطع صغيرة = استرجاع أكثر دقة، ولكن أكثر زيادة في النفقات العامة:

// 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 - استخدام

لا تتجاوز نافذة السياق - تترك مساحة للجيل:

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!

الإحلال: تزلج نافذة مع إعادة

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 - تكبّر التكاليف على النحو الأمثل

يمكن أن تفجر الشركة تكاليفها إن لم تكن حذرة:

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. كشط استخدام سريع (كلود الأنثروروبيك: 90% أرخص للرمزات المخبأة)
  3. استخدام نماذج أرخص لإعادة الترتيب، ومكلفة للجيل النهائي

تَتَقَوَّمُ مَمَا كَامَلَ مَدًّا مَتَى مَتَى

وهنا كيف أن الرموز، KV مخبأ، وRAG تنسجم معا:

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. & تم تجهيز (812 2) مرة واحدة لبناء مخبأ أولي KV
  2. الجيل يحدث رمزاً واحداً في وقت واحد، إعادة استخدام مخبئ KV
  3. كل حرف جديد إلى KV مخبئ لـ مستقبل رمز لـ إلى
  4. المجموع المجموع مُرَرْغِ الحاجة = مُنْطِر زِزِن النموذج + KV مخبأ لـ الكل
  5. السياق المطول كثيراً أكبر KV أكبر مخبئ المزيد VRA

الآثار العملية المترتبة على جولة

تَفْكِيرات و KV يؤدي إلى تصميم أفضل RAG:

1- السيالتان المشتركتان السابقتان للخصائص والمختبأ:

// 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 - الاستفادة المثلى من الحدود:

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

3 - استخدام لوحة المراقبة في الإنتاج:

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:

المرحلة الأولى: وضع الأرقام القياسية

  • مستخرجة من مختلف المصادر
  • استراتيجيات الزنك (على أساس القسم الفرعي، على أساس العقوبة، مع التداخل)
  • الجيل المشترك (NONNX، خدمات API)
  • (ق.ج.ج.ج.ج.ج.ج.ك)

المرحلة 2: المستردة

  • مزامِل مُسند مُسنداً إلى هذا الأمر (كمانت Name
  • بحث التشابه (cosine, euclidine, dot product)
  • مرشّح لدقة أفضل
  • البيانات الفو البيانات المتسربة من أجل النتائج الموضحة

المرحلة 3: التوليد

  • الإنشاء الفوري (السياق + التعليمات + الاستعلام)
  • LLL Digate (درجة الحرارة، أعلى، أعلى-p، أقصى رمز)
  • ما بعد تجهيز ما بعد التجهيز )استخراج

  • الوحدات الأساسية (وليس الشخصيات!)
  • KV KV مُناشر: لماذا توليد هو سريع (خطي، ليس تكافئي)
  • النوافذ: إدارة الحدود الرمزية في RAG
  • الاستخدام الأمثل لتكلفة التكلفة: مناقصات، ضغط، واسترجاع ذكي

الرؤى التقنية الرئيسية:

  1. **** للفهرسة والاسترجاع )نقد!(
  2. أكثر مما تعتقد أكثر مما تعتقد - الموازنات المتماسكة
  3. إعادة إعادة تحسين الدقة (بدولارات العمل المتأخر)
  4. من الضروري أن تكون الإدارة أمراً أساسياً - قبل الاستفسار
  5. KV KV ching يجعل RAG ممكن - العمليات الحسابية الحثية لإعادة الاستخدام
  6. نواش حرّر - 10 دفوع x 500 رمز = 5 ك

ثانياً - مواصلة تنفيذ الجزء 3:

أنت الآن تفهم كيف يعمل RAG لكن النظرية فقط تحصل عليك حتى الآن. كيف يمكنك بناء هذه الأنظمة؟ ما هي التحديات التي ستواجهها؟ ما هي التقنيات المتقدمة التي يمكنك استخدامها؟

داخل **الجزء 3: المساعدة في الممارسة**ننتقل من الهيكل إلى التنفيذ:

تطبيقات العالم الحقيقي:

  • توصية بشأن هذه المدونة
  • البحث عن المُسْفِفْكِم
  • مساعد تحريري لمبنى "Lawyer GPT"

التحديات وحلول:

  • وضع استراتيجيات تحفظ السياق
  • تحسين الجودة في مجالك
  • (أ) إدارة نوافذ السياق
  • منع هلوساً دون وجود سياق
  • الاحتفاظ بدليلك المحدث

التقنيات المتقدمة:

  • رموز مستند افتراضي (HyDE)
  • ذاتي الإستقرار مع LLLLM مرشّات
  • مجموعة متعددة الأسيجيات من أجل تحقيق نتائج شاملة
  • الضغط السياقي للحد من الاستخدام الرمزي
  • مجموعة أدوات متعددة الطرق للإجابات عن استفسارات مجمعات
  • ذاكرة محادثة طويلة الأجل

بدأ:

  • خطة التنفيذ لكل أسبوع من كل أسبوع من الأسبوع
  • أمثلة على المدونات العملية
  • استراتيجيات الرفع إلى المستوى الأمثل
  • الوقت الذي لا تستخدم فيه الرافع

مواصلة الجزء الثالث: الفريق الاستشاري المعني بالممارسة

الموارد الخارجة عن

أولاً - معلومات أساسية:

الأدوات والأطر:

اقرأ المزيد:

المجموعة الأولى:

مواصلة الجزء 3

Finding related posts...
logo

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