Back to "الفريق الاستشاري المعني بالممارسة: التطبيقات العالمية للبناء الحقيقي"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

AI AI-Article LLM Machine Learning RAG Semantic Search

الفريق الاستشاري المعني بالممارسة: التطبيقات العالمية للبناء الحقيقي

Saturday, 22 November 2025

داخل الجزء الأول وقد عقد مؤتمراً بشأن الجزء الثاني من هذه السلسلة، قمنا بتغطية أصول RAG، الأساسيات، والهندسة التقنية. أنت تفهم ما هو RAG، لماذا يهم، وكيف يعمل تحت غطاء المحرك. الآن حان الوقت لوضع هذه المعرفة موضع التطبيق. هذه المقالة تظهر لكم كيفية بناء أنظمة RAG الحقيقية مع العمل C# رمز، حل التحديات المشتركة، واستخدام التقنيات المتقدمة من البحوث الحديثة.

أولاً

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

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

  • ما هو الفريق وسبب أهميته (الجزء 1)
  • التاريخ من البحث عن الكلمات الرئيسية إلى الفهم الدناتيني (الجزء 1)
  • خط الأنابيب الكامل: الفهرسة والاسترجاع والتوليد )الجزء ٢(
  • داخليات LLL LLC: رسوم رمزية، مخبأ KV، نوافذ سياقية (الجزء 2)
  • RAG vs rim- renute وغيرها من النُهج (الجزء 1)

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

تطبيقـات RAAG على هذا المدوّل

لقد قمت ببناء العديد من الميزات ذات القدرة RAG على هذه المدونة. اسمحوا لي أن أعرض لكم أمثلة ملموسة.

توصية بشأن الوظائف ذات الصلة

كل تدوينة يمكن أن تظهر "النقاط ذات الصلة" باستخدام التشابه الدلالي.

كيف يعمل:

  1. كل تدوينة تُدمج عندما تُنشر
  2. عند النظر إلى موقع ما، نحن نستعيد غرسه من Qdrant
  3. اوجد الـ 5 الأكثر تشابهاً
  4. العرض كـ "مُسند"

لماذا هو أفضل من العلامات:

  • العلامات التي تتطلب تصنيفاً يدوياً
  • ابحث البحث الد موضعي البحث البحث البحث البحث البحث البحث البحث البحث البحثي الوظائف ذات الصلة مفاهيمياً حتى بدون بطاقات متطابقة
  • "Docker Compuse" و"Conweater enterentivement" وضعتان مرتبطتان من الناحية الدناينية

كود نصّي:

public async Task<List<SearchResult>> GetRelatedPostsAsync(
    string currentPostSlug,
    string language,
    int limit = 5)
{
    // Get the current post's embedding
    var currentPost = await _vectorStore.GetByIdAsync(currentPostSlug);

    if (currentPost == null)
        return new List<SearchResult>();

    // Find similar posts
    var similarPosts = await _vectorStore.SearchAsync(
        currentPost.Embedding,
        limit: limit + 1,  // +1 because result includes the current post
        filter: new Filter
        {
            Must =
            {
                new Condition
                {
                    Field = "language",
                    Match = new Match { Keyword = language }
                }
            },
            MustNot =
            {
                new Condition
                {
                    Field = "slug",
                    Match = new Match { Keyword = currentPostSlug }
                }
            }
        }
    );

    return similarPosts.Take(limit).ToList();
}

2 - البحث الدهني

صندوق البحث على هذه المدونة يستخدم أسلوب RAG للبحث الدلالي (على الرغم من أنه بدون جزء الجيل - إنه مجرد إسترجاع).

تجربة المستخدم:

  • البحث عن "إنشاء قاعدة بيانات"
  • البحث عن "النشر" والعثور على مواقع حول Dokker، الاستضافة، CI/CD
  • لا حاجة لمطابقات كلمة مفتاح

التنفيذ: سأغطي بناء هذا في مقال قادم عن قواعد بيانات المتجهات.

3 - مساعد كتابة "المحاما GPT"

أَبْني a نظام RAG كامل لمُسَاعَدَتي أَكْتبُ مواقعَ مدوناتِ جديدةِ.

حالة استخدام: عندما أبدأ بالكتابة عن "توثيق التوثيق إلى ASP.net conre" النظام:

  1. مُمَطَطِطَة مسودتي الحالية
  2. يقوم بالبحث في وظائف سابقة عن محتويات ذات صلة عن التوثيق، ASP.net، الأمن
  3. إقتراحات الشفرة ذات الصلة قصاصات الشفرة التي استخدمتها من قبل
  4. وصلات داخلية بالوظائف ذات الصلة
  5. حافظ على الاتساق مع أسلوب كتابتي

مشروع خط أنابيب كامل المسار الكامل:

public async Task<WritingAssistanceResponse> GetSuggestionsAsync(
    string currentDraft,
    string topic)
{
    // 1. Embed the current draft
    var draftEmbedding = await _embeddingService.GenerateEmbeddingAsync(
        currentDraft
    );

    // 2. Retrieve related past content
    var relatedPosts = await _vectorStore.SearchAsync(
        draftEmbedding,
        limit: 5
    );

    // 3. Build context for LLM
    var prompt = BuildWritingAssistancePrompt(
        currentDraft,
        topic,
        relatedPosts
    );

    // 4. Generate suggestions using local LLM
    var suggestions = await _llmService.GenerateAsync(prompt);

    // 5. Extract and format citations
    var response = ExtractCitations(suggestions, relatedPosts);

    return response;
}

هذا هو RAG في العمل - الاسترجاع (البحث الشمسي) + التعزيز (سياق الإغلاق) + الجيل (اقتراحات LLM).

تحديات المجموعة المشتركة وحلولها

هذه هي التحديات التي واجهتها وكيفية حلها.

التحدي 1: الاستراتيجية

المشكلة: كيف تقسم الوثائق؟ صغيرة جدا = فقدان السياق. كبيرة جدا = معلومات غير ذات صلة.

الحل: القطع المُهَلَّك استناداً إلى هيكل الوثيقة.

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

        // Parse markdown into sections
        var document = Markdown.Parse(markdown);
        var sections = ExtractSections(document);

        foreach (var section in sections)
        {
            var wordCount = CountWords(section.Content);

            if (wordCount < MinChunkSize)
            {
                // Merge small sections
                MergeWithPrevious(chunks, section);
            }
            else if (wordCount > MaxChunkSize)
            {
                // Split large sections
                var subChunks = SplitSection(section);
                chunks.AddRange(subChunks);
            }
            else
            {
                // Just right
                chunks.Add(CreateChunk(section, sourceId));
            }
        }

        return chunks;
    }
}

الممارسات الفضلى:

  • هيكل وثائق الاحترام (العناوين، الفقرات)
  • إضافة التداخل بين القطع (50-100 كلمة)
  • دعم هذا الأمر
  • إدراج رأسات أجزاء في كل قطعة للسياق

التحدي 2: إدخال الجودة

المشكلة: وقد لا تلتقط النماذج التضمينية العامة نماذج دلالات خاصة بكل مجال على حدة.

الحلول:

الخيار 1: الخيارات 1: المزدجات المجزأة (المستأنفة)

# Using sentence-transformers in Python
from sentence_transformers import SentenceTransformer, InputExample, losses

model = SentenceTransformer('all-MiniLM-L6-v2')

# Create training examples from your domain
train_examples = [
    InputExample(texts=['Docker Compose', 'container orchestration'], label=0.9),
    InputExample(texts=['Entity Framework', 'ORM database'], label=0.9),
    InputExample(texts=['Docker', 'apple fruit'], label=0.1)
]

# Fine-tune
train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16)
train_loss = losses.CosineSimilarityLoss(model)
model.fit(train_objectives=[(train_dataloader, train_loss)], epochs=1)

الخيار 2: المزجات (نماذج متعددة Combine)

public async Task<float[]> GenerateHybridEmbeddingAsync(string text)
{
    var semantic = await _semanticModel.GenerateEmbeddingAsync(text);
    var keyword = await _keywordModel.GenerateEmbeddingAsync(text);

    // Concatenate or weighted average
    return CombineEmbeddings(semantic, keyword);
}

الخيار 3: إضافة تجزئة

var results = await _vectorStore.SearchAsync(
    queryEmbedding,
    limit: 10,
    filter: new Filter
    {
        Must =
        {
            new Condition { Field = "category", Match = new Match { Keyword = "ASP.NET" } },
            new Condition { Field = "date", Range = new Range { Gte = "2024-01-01" } }
        }
    }
);

التحدي 3: السياق: إدارة النوافذ

المشكلة: LLMs لها حدود رمزية. كيف يمكنك أن تناسب الاستعلام في النافذة؟

الحل: (ج) اختيار السياقات الدينامية وتلخيصها.

public string BuildContextAwarePrompt(
    string query,
    List<SearchResult> retrievedDocs,
    int maxTokens = 4096)
{
    var promptTemplate = GetPromptTemplate();
    var queryTokens = CountTokens(query);
    var templateTokens = CountTokens(promptTemplate);

    // Reserve tokens for: prompt + query + response
    var availableForContext = maxTokens - queryTokens - templateTokens - 500; // 500 for response

    // Add context until we hit limit
    var selectedContext = new List<SearchResult>();
    var currentTokens = 0;

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

        if (currentTokens + docTokens <= availableForContext)
        {
            selectedContext.Add(doc);
            currentTokens += docTokens;
        }
        else
        {
            // Try summarizing the doc if it's important
            if (doc.Score > 0.85)
            {
                var summary = await SummarizeAsync(doc.Text, maxTokens: 200);
                var summaryTokens = CountTokens(summary);

                if (currentTokens + summaryTokens <= availableForContext)
                {
                    selectedContext.Add(new SearchResult
                    {
                        Text = summary,
                        Title = doc.Title,
                        Score = doc.Score
                    });
                    currentTokens += summaryTokens;
                }
            }
        }
    }

    return FormatPrompt(query, selectedContext);
}

التحدي 4: التصحيح على الرغم من

المشكلة: وحتى مع السياق، فإن LLLS في بعض الأحيان تجاهله والهلوسة.

الحلول:

1 - هندسية السرعة:

var systemPrompt = @"
You are a technical assistant.

CRITICAL RULES:
1. ONLY use information from the provided CONTEXT sections
2. If the context doesn't contain the answer, say 'I don't have enough information in the provided context to answer that'
3. DO NOT use your training data to supplement answers
4. Always cite the source using [1], [2] notation
5. If you're unsure, say so

CONTEXT:
{context}

QUESTION: {query}

ANSWER (following all rules above):
";

2 - المصادقة على مرحلة ما بعد التوليد:

public async Task<bool> ValidateResponseAgainstContext(
    string response,
    List<SearchResult> context)
{
    // Check if response contains claims not in context
    var responseSentences = SplitIntoSentences(response);

    foreach (var sentence in responseSentences)
    {
        var isSupported = await IsClaimSupportedByContext(sentence, context);

        if (!isSupported)
        {
            _logger.LogWarning("Hallucination detected: {Sentence}", sentence);
            return false;
        }
    }

    return true;
}

3 - الصقل الإضافي:

public async Task<string> GenerateWithValidationAsync(
    string query,
    List<SearchResult> context,
    int maxAttempts = 3)
{
    for (int attempt = 0; attempt < maxAttempts; attempt++)
    {
        var response = await _llm.GenerateAsync(
            BuildPrompt(query, context)
        );

        var isValid = await ValidateResponseAgainstContext(response, context);

        if (isValid)
            return response;

        // Refine prompt for next attempt
        query = $"{query}\n\nPrevious attempt hallucinated. Stick strictly to the context.";
    }

    return "I couldn't generate a reliable answer. Please rephrase your question.";
}

التحدي 5: الحفاظ على المؤشر في مستوى أعلى من التاريخ

المشكلة: بينما تضيف مستندات جديدة، فإن قاعدة بيانات المتجه يجب أن تبقى الحالية.

الحل: خط أنبوب فهرس آلي.

public class BlogIndexingBackgroundService : BackgroundService
{
    private readonly IVectorStoreService _vectorStore;
    private readonly IMarkdownService _markdownService;
    private readonly ILogger<BlogIndexingBackgroundService> _logger;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                await IndexNewPostsAsync(stoppingToken);

                // Check for updates every hour
                await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in indexing service");
            }
        }
    }

    private async Task IndexNewPostsAsync(CancellationToken ct)
    {
        var allPosts = await _markdownService.GetAllPostsAsync();

        foreach (var post in allPosts)
        {
            var existingDoc = await _vectorStore.GetByIdAsync(post.Slug);

            // Check if content changed
            var currentHash = ComputeHash(post.Content);

            if (existingDoc == null || existingDoc.ContentHash != currentHash)
            {
                _logger.LogInformation("Indexing updated post: {Title}", post.Title);

                var chunks = _chunker.ChunkDocument(post.Content, post.Slug);

                foreach (var chunk in chunks)
                {
                    var embedding = await _embeddingService.GenerateEmbeddingAsync(chunk.Text);

                    await _vectorStore.UpsertAsync(
                        id: $"{post.Slug}_{chunk.Index}",
                        embedding: embedding,
                        metadata: new Dictionary<string, object>
                        {
                            ["slug"] = post.Slug,
                            ["title"] = post.Title,
                            ["chunk_index"] = chunk.Index,
                            ["content_hash"] = currentHash
                        },
                        ct: ct
                    );
                }
            }
        }
    }
}

المتقدمات في الحصول على درجة متقدمة

دعونا نستكشف أحدث تقنيات RAG من البحوث الحديثة.

1 - الوثائق المخطوطات المستندية الافتراضية (HyDE)

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

الحل: إعداد وثيقة افتراضية مثالية التي من شأنها أن تجيب على السؤال، غرس ذلك، ثم البحث.

public async Task<List<SearchResult>> HyDESearchAsync(string query)
{
    // Generate hypothetical answer (even if hallucinated)
    var hypotheticalAnswer = await _llm.GenerateAsync($@"
        Write a detailed, technical paragraph that would perfectly answer this question:

        Question: {query}

        Paragraph:"
    );

    // Embed the hypothetical answer
    var embedding = await _embeddingService.GenerateEmbeddingAsync(
        hypotheticalAnswer
    );

    // Search using this embedding
    return await _vectorStore.SearchAsync(embedding);
}

سبب عمله: وتستخدم الإجابة الافتراضية لغة وهيكلا مماثلين للوثائق الفعلية، مما يحسن الاسترجاع.

٢ - تقرير المصير

المشكلة: وغالباً ما تخلط استفسارات المستعملين بين البحث الدلالي وتنقيحات البيانات الفوقية.

مثال: "الوظائـف الثابتـة عـن Doker" = semanttte (""Doker") + مرشح (التاريخ > 2024-01-01)

الحل: استخدم LLLM لشرح الإستفسار إلى المرشّحات semantic + data.

public async Task<SearchQuery> ParseSelfQueryAsync(string naturalLanguageQuery)
{
    var parsingPrompt = $@"
        Parse this search query into:
        1. Semantic search query (what the user is looking for)
        2. Metadata filters (category, date range, etc.)

        User Query: {naturalLanguageQuery}

        Output JSON:
        {{
            ""semantic_query"": ""the core concept"",
            ""filters"": {{
                ""category"": ""...",
                ""date_after"": ""..."",
                ""date_before"": ""...""
            }}
        }}
    ";

    var jsonResponse = await _llm.GenerateAsync(parsingPrompt);
    var parsed = JsonSerializer.Deserialize<SearchQuery>(jsonResponse);

    return parsed;
}

// Use parsed query
var parsedQuery = await ParseSelfQueryAsync("Recent ASP.NET posts about authentication");
// semantic_query: "authentication"
// filters: { category: "ASP.NET", date_after: "2024-01-01" }

var results = await _vectorStore.SearchAsync(
    embedding: await _embeddingService.GenerateEmbeddingAsync(parsedQuery.SemanticQuery),
    filter: BuildFilter(parsedQuery.Filters)
);

3- RAG متعدد الأسئلة

المشكلة: وقد يغفل استفسار واحد عن الوثائق ذات الصلة بسبب الصياغة.

الحل: اوجد تغييرات متعددة للاستفسار، ابحث مع الكل، اجمع النتائج.

public async Task<List<SearchResult>> MultiQuerySearchAsync(string query)
{
    // Generate query variations
    var variations = await _llm.GenerateAsync($@"
        Generate 3 different ways to phrase this search query:

        Original: {query}

        Variations (one per line):
    ");

    var queries = variations.Split('\n', StringSplitOptions.RemoveEmptyEntries)
        .Prepend(query) // Include original
        .ToList();

    // Search with all variations
    var allResults = new List<SearchResult>();

    foreach (var q in queries)
    {
        var embedding = await _embeddingService.GenerateEmbeddingAsync(q);
        var results = await _vectorStore.SearchAsync(embedding, limit: 10);
        allResults.AddRange(results);
    }

    // Deduplicate and merge scores
    var merged = allResults
        .GroupBy(r => r.Id)
        .Select(g => new SearchResult
        {
            Id = g.Key,
            Text = g.First().Text,
            Title = g.First().Title,
            Score = g.Max(r => r.Score) // Take best score
        })
        .OrderByDescending(r => r.Score)
        .ToList();

    return merged;
}

٤/٤ السياق

المشكلة: القطع المستردة تحتوي على معلومات غير ذات صلة ترسلها كلها كعربات نفايات

الحل: استخدم LLLM أصغر لضغط سياق الاسترجاع على الأجزاء ذات الصلة فقط.

public async Task<string> CompressContextAsync(
    string query,
    List<SearchResult> retrievedDocs)
{
    var compressed = new List<string>();

    foreach (var doc in retrievedDocs)
    {
        var compressionPrompt = $@"
            Extract only the sentences from this document that are relevant to answering the question.

            Question: {query}

            Document:
            {doc.Text}

            Relevant excerpts (maintain original wording):
        ";

        var relevantExcerpt = await _smallLLM.GenerateAsync(compressionPrompt);

        if (!string.IsNullOrWhiteSpace(relevantExcerpt))
        {
            compressed.Add($"From '{doc.Title}':\n{relevantExcerpt}");
        }
    }

    return string.Join("\n\n", compressed);
}

5 - استعادة القدرة على الارتجاع (Multi-Hop RAG)

المشكلة: وتتطلب المسائل المعقدة معلومات من مصادر متعددة يلزم ربطها.

مثال: "ما هي قاعدة البيانات التي تستخدمها المدونات وكيف يتم تنفيذ البحث الدلالي؟"

  • جاري البحث ما هي قاعدة البيانات التي هي مُستخدِم (PostsSQL)
  • هو ابحث كيف يعمل البحث الدهني مع قاعدة البيانات هذه

الحل: الاسترجاع والتوليف.

public async Task<string> MultiHopRAGAsync(string complexQuery, int maxHops = 3)
{
    var currentQuery = complexQuery;
    var allContext = new List<SearchResult>();

    for (int hop = 0; hop < maxHops; hop++)
    {
        // Retrieve for current query
        var results = await SearchAsync(currentQuery, limit: 5);
        allContext.AddRange(results);

        // Check if we have enough information
        var synthesisPrompt = $@"
            Original question: {complexQuery}

            Context so far:
            {FormatContext(allContext)}

            Can you answer the original question with this context?
            If yes, provide the answer.
            If no, what additional information do you need? (be specific)
        ";

        var synthesis = await _llm.GenerateAsync(synthesisPrompt);

        if (synthesis.Contains("yes", StringComparison.OrdinalIgnoreCase))
        {
            // We have enough information
            return ExtractAnswer(synthesis);
        }

        // Extract what we need for next hop
        currentQuery = ExtractNextQuery(synthesis);
    }

    // Final synthesis with all gathered context
    return await GenerateFinalAnswerAsync(complexQuery, allContext);
}

6 - ذاكرة سياقية طويلة الأجل مع المجموعة RAG + موجز

المشكلة: كيف يمكنك بناء أنظمة الذكاء الاصطناعي التي تتذكر المحادثات من أشهر أو سنوات مضت؟ الدردشة التقليدية تفقد السياق بعد كل جلسة.

الحل: الجمع بين RAG مع التلخيص التدريجي لخلق ذاكرة مستمرة، قابلة للبحث.

هذا هو النهج المستخدم في الدالة DSSSSSSSS نظام متقدم أقوم ببناءه يستخدم ذاكرة سياقية قائمة على قاعدة RAG للحفاظ على تاريخ المحادثة المشترك إلى أجل غير مسمى.

السيناريو:

User (Today): "Remember George's specs?"
AI: "Yes, you discussed George's prescription requirements in our conversation
     from 5 years ago (2019-03-15). He needed progressive lenses with..."

كيف يعمل:

flowchart TB
    A[User Message] --> B[Store in RAG Memory]
    B --> C[Extract Key Entities & Topics]
    C --> D[Link to Past Conversations]

    E[Periodic Summarization] --> F[Summarize Old Conversations]
    F --> G[Store Summary with High-Level Tags]
    G --> H[Keep Original for Retrieval]

    I[Future Query: 'George's specs'] --> J[Semantic Search in RAG]
    J --> K[Find: 2019 conversation]
    K --> L[Retrieve Original Context]
    L --> M[LLM generates response with 5-year-old context!]

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

نهج التنفيذ:

public class LongTermConversationalMemory
{
    private readonly IVectorStoreService _vectorStore;
    private readonly IEmbeddingService _embeddingService;

    public async Task StoreConversationAsync(
        string conversationId,
        string userId,
        List<ConversationTurn> turns,
        DateTime timestamp)
    {
        // Extract key entities and topics
        var entities = await ExtractEntitiesAsync(turns);
        var topics = await ExtractTopicsAsync(turns);

        // Create searchable representation
        var conversationText = string.Join("\n", turns.Select(t =>
            $"{t.Speaker}: {t.Message}"));

        // Generate embedding
        var embedding = await _embeddingService.GenerateEmbeddingAsync(
            conversationText);

        // Store in RAG with rich metadata
        await _vectorStore.IndexDocumentAsync(
            id: $"conv_{conversationId}",
            embedding: embedding,
            metadata: new Dictionary<string, object>
            {
                ["user_id"] = userId,
                ["timestamp"] = timestamp.ToString("O"),
                ["entities"] = entities,  // ["George", "specs", "prescription"]
                ["topics"] = topics,      // ["healthcare", "eyewear"]
                ["full_text"] = conversationText,
                ["turn_count"] = turns.Count
            }
        );
    }

    public async Task<List<PastContext>> RetrieveRelevantPastAsync(
        string currentQuery,
        string userId,
        int limit = 5)
    {
        // Embed the current query
        var queryEmbedding = await _embeddingService.GenerateEmbeddingAsync(
            currentQuery);

        // Search past conversations
        var results = await _vectorStore.SearchAsync(
            queryEmbedding,
            limit: limit,
            filter: new Filter
            {
                Must =
                {
                    new Condition { Field = "user_id", Match = new Match { Keyword = userId } }
                }
            }
        );

        return results.Select(r => new PastContext
        {
            ConversationId = r.Id,
            Timestamp = DateTime.Parse(r.Metadata["timestamp"].ToString()),
            Entities = (List<string>)r.Metadata["entities"],
            FullText = r.Metadata["full_text"].ToString(),
            Relevance = r.Score
        }).ToList();
    }

    // Periodic summarization to keep memory manageable
    public async Task SummarizeOldConversationsAsync(DateTime olderThan)
    {
        var oldConversations = await _vectorStore.FindByDateRangeAsync(
            endDate: olderThan);

        foreach (var conv in oldConversations)
        {
            // Generate summary using LLM
            var summary = await _llm.GenerateAsync($@"
                Summarize this conversation, preserving key facts and entities:

                {conv.FullText}

                Summary:");

            // Update document with summary while keeping original
            await _vectorStore.UpdateAsync(
                id: conv.Id,
                additionalMetadata: new Dictionary<string, object>
                {
                    ["summary"] = summary,
                    ["summarized_at"] = DateTime.UtcNow.ToString("O")
                }
            );
        }
    }
}

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

  1. ذاكرة غير ذاتية -محادثات منذ سنوات مضت يمكن الوصول إليها كما حدث بالأمس
  2. ابحث - "مواصيف جورج" تجد المحادثة حتى لو كانت مخزنة على أنها "متطلبات وصفة جيورج للعين"
  3. الكيان الذي يقوم بالربط - كل المحادثات التي تشير إلى "جورج" مرتبطة
  4. الخصوصيـة - المقصـف - القدرة على تنفيذ عزلة ذاكرة المستخدم
  5. )أ( - الملخصات تحول دون حدوث انفجار في التخزين مع الحفاظ على إمكانية البحث

مثال العالم الحقيقي من DISE:

يستخدم DISE هذا النهج لتذكر:

  • أداة من قبل شهور مضت (الذي نجح، ما فشل)
  • دال - الأنماط التي حققت نجاحاً في المشاريع السابقة
  • **** في محادثات سابقة
  • الـمُنْفْرِس متراكمة على مر الزمن

وهذا يخلق نظام الذكاء الاصطناعي الذي "يتعلم" حقاً من كل تفاعل ويبني ذاكرة مؤسسية، بدلاً من البدء من جديد في كل جلسة.

التحديات التي يلزم النظر فيها:

  1. ****: المحادثات القديمة يجب أن تكون معزولة بشكل صحيح لكل مستخدم
  2. (تابع): ليس كل المعلومات القديمة تبقى ذات صلة
  3. ****: الحاجة إلى استراتيجية لتلخيص الجدول
  4. التطابق: إبقاء الملخصات متوائمة مع النسخ الأصلية:
  5. دعم المعاينة: الموازنة بين سياق حديث وسياق مهم تاريخياً

هذه التقنية تحول RAG من "ابحث في وثائقي" إلى "تذكر كل شيء ناقشناه من أي وقت مضى" -

عندما لا تستخدم الرافع

(راج) ليس الجواب دائماً، إليك متى تتفاداه:

١ - مسائل المعارف العامة

  • "ما هي عاصمة فرنسا؟" - LLL يعرف بالفعل هذا
  • تكرّر وتكلفة بدون فائدة

2 - كتابة الكتابة الإبداعية

  • 1 - التقليـد، الخيال، تأصـل
  • RAG يُقيِّد الإبداع بالإرساء في النص الحالي

الاحتياجات من البيانات الآنية

  • الأسعار، والدرجات الرياضية الحية
  • خدمة أفضل من قبل دمجات API، وليس RAG

4 - تعليل الموضوع

  • حساب 15% بقشيش على 83.47
  • LLLLs يمكن القيام بالحساب; RAG لا يساعد

قواعد المعارف الصغيرة جدا

  • إذا كانت قاعدة معرفك تلائم في نافذة السياق، فقط أدرجها كلها
  • النفقات العامة لـ 5 وثائق لا تساوي 5 وثائق

6 - عندما تتحكم في تدريب LLM

  • إذا كنت تتدرب على نموذج من الصفر على بياناتك، قد يكون تحسيناً
  • RAG هو الأفضل عند استخدام النماذج المسبقة عن التدريب التي لا تتحكم بها

البدء بالمجموعة: دليل عملي

هل تريد بناء نظامك الخاص؟ هنا نهج الخطوة خطوة خطوة.

الأسبوع 1: الأسبوع

الهدف: الحصول على الاسترجاع الأساسي العمل مع لا LLLM.

// 1. Choose an embedding service (start with API for simplicity)
var openAI = new OpenAIClient(apiKey);

// 2. Embed a few test documents
var docs = new[]
{
    "Docker is a containerization platform",
    "Kubernetes orchestrates containers",
    "Entity Framework is an ORM for .NET"
};

var embeddings = new List<float[]>();
foreach (var doc in docs)
{
    var response = await openAI.GetEmbeddingsAsync(
        new EmbeddingsOptions("text-embedding-3-small", new[] { doc })
    );
    embeddings.Add(response.Value.Data[0].Embedding.ToArray());
}

// 3. Implement basic search (in-memory for now)
var query = "container orchestration";
var queryEmbedding = await GetEmbeddingAsync(query);

var results = embeddings
    .Select((emb, idx) => new
    {
        Text = docs[idx],
        Score = CosineSimilarity(queryEmbedding, emb)
    })
    .OrderByDescending(r => r.Score)
    .ToList();

// 4. Verify search works
foreach (var result in results)
{
    Console.WriteLine($"{result.Score:F3}: {result.Text}");
}
// Expected: Kubernetes scores highest

الأسبوع 2: قاعدة بيانات الخطر

الهدف: حدّد إلى حقيقي مستند مجموعات.

الخطوات المتخذة لتنفيذ ما يلي:

  1. شغّل في Docker
  2. فهرس وثائقك
  3. تنفيذ نقطة نهاية المُنْس

سأغطي هذا بالتفصيل في مقال قادم عن قواعد بيانات المتجهات.

الاسبوع الثالث : اضِف جيلا مضافا

الهدف: (أ) كامل خط أنابيب RAG.

// 1. Retrieve context
var context = await SearchAsync(query, limit: 3);

// 2. Build prompt
var prompt = $@"
    Answer the question using this context:

    {FormatContext(context)}

    Question: {query}

    Answer:";

// 3. Generate (start with API)
var response = await openAI.GetChatCompletionsAsync(new ChatCompletionsOptions
{
    Messages =
    {
        new ChatMessage(ChatRole.System, "You are a helpful assistant."),
        new ChatMessage(ChatRole.User, prompt)
    },
    Temperature = 0.7f,
    MaxTokens = 500
});

return response.Value.Choices[0].Message.Content;

الأسبوع 4: الاستخدام الأمثل والبولندية

  • مضاف مضافاً إلى الكش (الخلاص من التكاليف المتعلقة بمؤشرات الحد من تكاليف)
  • استراتيجية تحسين تجميع القطع
  • تنفيذ البحث المُهرس ابحث

المحلية (الخيار الاختياري)

عندما تعمل الأساسيات، تنتقل إلى الاستدلال المحلي (سأغطي هذا في المقالات القادمة):

  • محلي محلي LL L LLم مع GU
  • مُزَدْدَزَزَات مُلائمة لـ مُعْرِفَة مع OONNX وقت التشغيل

ثالثاً - استنتاج

RAG (الجيل المسترجع - المدمج) هو تقنية قوية لجعل LLMs أكثر دقة وتحديثاً وموثوقية من خلال وضع ردودهم في وثائق فعلية. بدلاً من الاعتماد على بيانات التدريب الخاصة بالنموذج وحدها، أنظمة RAG:

  1. (ز) قيد التنفيذ المعلومات ذات الصلة من قاعدة معارف تستخدم البحث العلمي
  2. **** الـ LLL لـ مع ذلك المسترجع سياق
  3. غير الميج التي تستند إلى مصادر حقيقية مع إحالات

الميزات الرئيسية للفريق الاستشاري:

  • يجري تحديثه دائما دائماً (فقط تحديث قاعدة معارفك)
  • مثبتة في المصادر (الهلوسة)
  • يمكن الرجوع إلى المصادر(
  • فعال من حيث التكلفة (بدون إعادة تدريب مكلفة)
  • المحافظة على الخصوصية (يمكن تشغيلها محلياً بالكامل)
  • محدد نطاق محدد (استخدم وثائقك الخاصة)

وقت استخدام الرافعة:

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

الوقت الذي يتعين فيه تجنب الإسناد:

  • &g

ويتطور هذا المجال بسرعة مع التقنيات المتقدمة مثل هايدي، والاسترجاع متعدد الماكيارات، والضغط السياقي، ولكن المفهوم الأساسي يظل بسيطا: إعطاء LLMs الوصول إلى المعلومات الصحيحة في الوقت المناسب.

بداية بسيطة، نتائج قياسية، وتكرار. RAG هي واحدة من أكثر الطرق العملية لبناء أنظمة الذكاء الفلكي الموثوقة اليوم.

الاستنتاج: من النظرية إلى الإنتاج

لقد أكملتم الآن سلسلة ثلاثة أجزاء:

الجزء 1: الأصول والأساسيات

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

الجزء 2: العمى والداخليات

  • خط الأنابيب: الفه الفهارسة والاسترجاع والتوليد
  • داخليات LLLLLLM: الرموز، KV مخبئ، نوافذ السياق
  • تفاصيل تنفيذ تقني مع C# رمز

الجزء 3: القاعدة في الممارسة (هذه المادة)

  • التنفيذ في العالم الحقيقي (الوظـائف المتصلة بها، والبحث الدهني، ومساعد في مجال الكتابة)
  • التحديات والحلول المشتركة (التوصيل، والدمج في النوعية، والهلوسة)
  • تقنيات متقدمة (HyDE، ذاتية-Query، متعددة-Query، ضغط السياق، ذاكرة طويلة الأجل)
  • الوقت الذي لا تستخدم فيه الرافع
  • بدأ البدء في دليل

الآن لديك الصورة الكاملة: من فهم أصول الفريق إلى بناء نظم إنتاج ذات أفضليات متقدمة.

ما هو التالي؟

الآن بما أنك تفهم RAG من نظرية إلى ممارسة، المقالات القادمة سوف تظهر لك كيفية بناء كامل، إنتاج - جاهز أنظمة RAG في C#:

ما يلي:

  • المعالج المُعَاد المُعَاد المُعَد المُعَد المُعَد المُعَد المُعَد المُعَد المُعَد المُعَد المُعَدّ - بناء بحث دلاني مع ONNX مزروعات التي تعمل على أي VPS بدون متطلبات GPU
  • قواعد بيانات الأمراض المعتمدة ذاتياً - دليل الإعداد الكامل لدليل Qdrant مع Docker، بما في ذلك استراتيجيات الفهرسة والبحث والاستخدام الأمثل؛
  • مساعد لكتابة المبنى - سلسلة كاملة عن إنشاء مساعد كتابة يعمل بكفاءة عالية يستخدم محتوىك الحالي كقاعدة معرفية

هذه المقالات سوف تأخذك من نظرية إلى ممارسة، مع قواعد العمل الكاملة، استراتيجيات الانتشار، والمثاليات في العالم الحقيقي على أساس تشغيل هذه الأنظمة في الإنتاج على هذه المدونة.

وابقوا متأهبين لأدلة التنفيذ العملية التي تحول معارف فريق البحث والتطوير هذه إلى نظم عاملة!

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

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

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

اقرأ المزيد:

هذه سلسلة السلاسل:

بُنيّة مُباركة مُباركة مُباركة!

logo

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