ترجمة المقالة إلى اللغة العربية

قضيت آخر ثمانية عشر شهراً في بناء ميزات الذكاء الاصطناعي في تطبيقات Next.js للعملاء، من الشركات الناشئة في مجال القانون التكنولوجي إلى قواعد المعرفة المؤسسية. الفجوة بين عرض توضيحي رائع للـ RAG ونظام إنتاجي يتعامل مع حركة المرور الفعلية دون إهدار الأموال ضخمة جداً. تغطي هذه المقالة الدروس الصعبة -- كيفية هندسة الأوامر التي تبقى متسقة، بث الردود دون كسر واجهة المستخدم الخاصة بك، تخزين ذكي للبيانات لتقليل التكاليف بنسبة 60-80%، وإطلاق خطوط أنابيب RAG التي لا تتعطل الساعة 2 صباحاً يوم الجمعة.

جدول المحتويات

Prompt Engineering with Next.js: Streaming RAG & Caching in Production

لماذا RAG في Next.js منطقي في عام 2026

أصبح Next.js الخيار الافتراضي للتطبيقات الويب التي تعمل بالذكاء الاصطناعي، وليس هذا مجرد ضجيج إعلامي. يوفر الجمع بين App Router و Server Actions و Route Handlers و React Server Components لك بنية جيدة حقاً لخطوط أنابيب RAG. يمكنك الاحتفاظ بمنطق التضمين على جانب الخادم، والبث عبر Route Handlers، والتخزين المؤقت بقوة عبر عدة طبقات.

نضج Vercel AI SDK (الآن بإصدار v4.x) بشكل ملحوظ. يتعامل مع البث واستدعاء الأدوات والإخراج المنظم بشكل أصلي. لكن SDK مجرد توصيلات -- التحدي الحقيقي هو كل شيء حوله: تصميم الأوامر وجودة الاسترجاع واستراتيجية التخزين المؤقت ومعالجة الأخطاء.

إليك ما يبدو عليه تدفق RAG النموذجي للإنتاج في Next.js:

  1. يرسل المستخدم استعلاماً
  2. يتم تضمين الاستعلام (أو يضرب ذاكرة التخزين المؤقت للتضمين)
  3. يسترجع البحث الموجه أجزاء ذات صلة
  4. يتم ترتيب الأجزاء وتصفيتها
  5. أمر مهندس بعناية يجمع السياق
  6. يبث نموذج اللغة الكبير ردة فعل
  7. يتم تخزين الردة مؤقتاً للاستعلامات المستقبلية المماثلة

كل خطوة لها أوضاع الفشل. دعنا نتعمق في كل واحدة.

أساسيات هندسة الأوامر لـ RAG

هندسة الأوامر لـ RAG مختلفة أساساً عن هندسة الأوامر لتفاعلات نموذج اللغة الكبير الفانيليا. أنت لا تسأل النموذج سؤالاً فقط -- أنت تعطيه نافذة سياق محددة وتطلب منه تجميع إجابة من تلك النافذة مع تجاهل بيانات التدريب الخاصة به عند تعارضها.

بنية الأمر النظام

لقد استقرت على بنية أمر نظام من ثلاثة أجزاء تعمل بشكل جيد عبر المجالات المختلفة:

const buildSystemPrompt = (config: RAGConfig) => `
You are ${config.assistantName}, a ${config.role} for ${config.company}.

## CONTEXT RULES
- Answer ONLY based on the provided context documents
- If the context doesn't contain enough information, say so explicitly
- Never fabricate citations or reference numbers
- When multiple context documents conflict, note the discrepancy


![Prompt Engineering with Next.js: Streaming RAG & Caching in Production - architecture](https://zpkyypersyvzhywdxqij.supabase.co/storage/v1/object/public/public-assets/blog-body/2a8bfe14-ca88-4f2f-a5b0-75c780b0689c-2.jpg)

## RESPONSE FORMAT
- Use markdown formatting for readability
- Cite sources using [Source: document_id] notation
- Keep responses under ${config.maxResponseTokens} tokens unless the user asks for detail
- Use ${config.tone} tone

## DOMAIN RULES
${config.domainRules.join('\n')}
`;

الرؤية الأساسية: قواعد المجال هي حيث تضع الأشياء التي تجعل RAG الخاص بك مفيداً بالفعل. بالنسبة لعميل قانوني، قد يكون ذلك "لاحظ دائماً الاختصاص القضائي الذي تنطبق عليه القاعدة." لقاعدة معرفة طبية، "لا تقدم أبداً توصيات الجرعات؛ اتجه دائماً إلى مقدم الرعاية الصحية."

إدارة نافذة السياق

مع GPT-4o يعمل بـ 128k سياق و Claude 3.5 بـ 200k، من المغري أن تملأ كل شيء فقط. لا تفعل. المزيد من السياق لا يعني إجابات أفضل -- غالباً ما يعني إجابات أسوأ.

أستخدم نهج متعدد المستويات:

const assembleContext = async (
  query: string,
  retrievedChunks: Chunk[]
): Promise<string> => {
  // Tier 1: Top 3 chunks by cosine similarity (always included)
  const primary = retrievedChunks.slice(0, 3);
  
  // Tier 2: Next 5 chunks, but only if similarity > threshold
  const secondary = retrievedChunks
    .slice(3, 8)
    .filter(c => c.similarity > 0.78);
  
  // Tier 3: Metadata-enriched summaries of remaining relevant docs
  const tertiary = retrievedChunks
    .slice(8)
    .filter(c => c.similarity > 0.72)
    .map(c => c.summary); // Pre-computed summaries, not full text
  
  return formatContextTiers(primary, secondary, tertiary);
};

يؤدي هذا عادة إلى 3,000-8,000 رمز من السياق بدلاً من 30,000+. تحسن جودة الردة، وينخفض وقت الكمون، وتنخفض فاتورة API الخاصة بك.

إصدار الأوامر

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

// prompts/v2.3.ts
export const RAG_PROMPT_V2_3 = {
  version: '2.3',
  createdAt: '2026-03-15',
  changelog: 'Added conflict resolution instruction, reduced hallucination on legal queries by 23%',
  system: `...`,
  userTemplate: (query: string, context: string) => `...`,
};

نخزن إصدارات الأوامر في الكود، وليس في قاعدة بيانات. يتم مراجعتها في PRs تماماً كما هو الحال مع أي تغيير كود آخر. عندما يحدث خطأ ما في الإنتاج، يمكنك تتبعه إلى إصدار أمر محدد.

إعداد بث RAG في Next.js

معالج الطريق مع Vercel AI SDK

إليك نقطة نهاية بث RAG جاهزة للإنتاج:

// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
import { retrieveContext } from '@/lib/rag/retriever';
import { buildPrompt } from '@/lib/rag/prompts';
import { checkCache, setCache } from '@/lib/rag/cache';
import { rateLimiter } from '@/lib/middleware/rate-limit';

export const runtime = 'nodejs'; // Not edge -- you need Node for most vector DBs
export const maxDuration = 30;

export async function POST(req: Request) {
  const { messages, sessionId } = await req.json();
  const lastMessage = messages[messages.length - 1].content;

  // Rate limiting
  const allowed = await rateLimiter.check(sessionId);
  if (!allowed) {
    return new Response('Rate limited', { status: 429 });
  }

  // Check semantic cache first
  const cached = await checkCache(lastMessage);
  if (cached) {
    return new Response(cached.response, {
      headers: { 'X-Cache': 'HIT', 'Content-Type': 'text/plain' },
    });
  }

  // Retrieve context
  const context = await retrieveContext(lastMessage, {
    topK: 10,
    minSimilarity: 0.72,
    namespace: 'production',
  });

  // Build the prompt
  const systemPrompt = buildPrompt(context);

  // Stream the response
  const result = streamText({
    model: openai('gpt-4o'),
    system: systemPrompt,
    messages,
    temperature: 0.3, // Low temp for factual RAG
    maxTokens: 1500,
    onFinish: async ({ text }) => {
      // Cache the completed response
      await setCache(lastMessage, text, context.chunks.map(c => c.id));
    },
  });

  return result.toDataStreamResponse();
}

واجهة مستخدم البث على جانب العميل

على الواجهة الأمامية، يتعامل خطاف useChat مع البث بشكل لطيف:

// components/ChatInterface.tsx
'use client';

import { useChat } from 'ai/react';
import { useRef, useEffect } from 'react';

export function ChatInterface() {
  const { messages, input, handleInputChange, handleSubmit, isLoading, error } =
    useChat({
      api: '/api/chat',
      body: { sessionId: getSessionId() },
      onError: (err) => {
        // Don't just console.log -- show the user something useful
        toast.error('Something went wrong. Try rephrasing your question.');
      },
    });

  const scrollRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    scrollRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  return (
    <div className="flex flex-col h-full">
      <div className="flex-1 overflow-y-auto p-4 space-y-4">
        {messages.map((m) => (
          <div key={m.id} className={m.role === 'user' ? 'text-right' : ''}>
            <div className="prose prose-sm max-w-none">
              <Markdown>{m.content}</Markdown>
            </div>
          </div>
        ))}
        {isLoading && <TypingIndicator />}
        <div ref={scrollRef} />
      </div>
      <form onSubmit={handleSubmit} className="p-4 border-t">
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="Ask a question..."
          className="w-full p-3 rounded-lg border"
          disabled={isLoading}
        />
      </form>
    </div>
  );
}

التعامل مع حالات الحافة في البث

البث في الإنتاج يعني التعامل مع الأشياء التي لا تحدث في العروض التوضيحية:

  • انقطاع الاتصال منتصف البث: تطبيق منطق إعادة المحاولة مع التراجع الأسي. اتصال onError الخاص بـ AI SDK هو أفضل صديق لك.
  • تجاوز حد الرمز: مراقبة استخدام الرمز وتطبيق قطع صعبة قبل أن يفعل النموذج ذلك (القطع الخاصة به قبيحة).
  • الاسترجاع البطيء: تعيين المهل الزمنية على استعلامات قاعدة بيانات المتجهات. إذا استغرق الاسترجاع > 2 ثانية، فقع للعودة إلى سياق أصغر أو استعلام مماثل مخزن مؤقتاً.

طبقة التخزين المؤقت: حيث توفر المال الحقيقي

التخزين المؤقت هو التحسن الأكثر تأثيراً الذي يمكنك تحقيقه في نظام RAG الإنتاجي. هناك ثلاث طبقات تستحق التنفيذ.

الطبقة الأولى: ذاكرة التخزين المؤقت للتضمين

كل استعلام يحتاج إلى تضمين. بـ $0.00002 لكل 1K رمز مع text-embedding-3-small، فهو رخيص لكل استعلام، لكنه يتراكم و -- الأهم من ذلك -- يضيف الكمون.

import { Redis } from '@upstash/redis';
import { createHash } from 'crypto';

const redis = new Redis({ url: process.env.UPSTASH_REDIS_URL!, token: process.env.UPSTASH_REDIS_TOKEN! });

export async function getEmbedding(text: string): Promise<number[]> {
  const hash = createHash('sha256').update(text.toLowerCase().trim()).digest('hex');
  
  // Check cache
  const cached = await redis.get<number[]>(`emb:${hash}`);
  if (cached) return cached;
  
  // Generate embedding
  const embedding = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: text,
  });
  
  const vector = embedding.data[0].embedding;
  
  // Cache for 7 days
  await redis.set(`emb:${hash}`, vector, { ex: 604800 });
  
  return vector;
}

الطبقة الثانية: ذاكرة التخزين المؤقت الدلالية

هذه هي الكبيرة. إذا سأل شخص ما "ما هي سياسة الاسترجاع الخاصة بك؟" وسأل شخص آخر "كيف أسترجع المال؟"، يجب أن يحصلوا على نفس الردة المخزنة مؤقتاً.

export async function checkSemanticCache(query: string): Promise<CacheResult | null> {
  const embedding = await getEmbedding(query);
  
  // Search the cache index (separate from your content index)
  const results = await pinecone.index('cache').query({
    vector: embedding,
    topK: 1,
    includeMetadata: true,
  });
  
  if (results.matches[0]?.score > 0.95) {
    return {
      response: results.matches[0].metadata.response as string,
      originalQuery: results.matches[0].metadata.query as string,
      cachedAt: results.matches[0].metadata.cachedAt as string,
    };
  }
  
  return null;
}

حد 0.95 مهم. منخفض جداً وستقدم إجابات خاطئة. مرتفع جداً ولن تحصل على ضربات ذاكرة التخزين المؤقت. ابدأ بـ 0.95 وتوافق بناءً على مجالك.

الطبقة الثالثة: ذاكرة التخزين المؤقت لشظايا الردود

للردود المنظمة (مثل مواصفات المنتج أو ملخصات السياسات)، قم بتخزين الأجزاء الفردية مؤقتاً:

طبقة التخزين المؤقت معدل الضرب (نموذجي) توفير الكمون توفير التكاليف
ذاكرة التخزين المؤقت للتضمين 40-60% 50-100ms لكل استعلام ~$50/mo في 100K استعلام
ذاكرة التخزين المؤقت الدلالية 15-35% 1-3s لكل استعلام ~$300-800/mo في 100K استعلام
ذاكرة التخزين المؤقت للأجزاء 20-40% 500ms-1s لكل استعلام ~$100-200/mo في 100K استعلام
المجموع 60-80% 1-3s متوسط $500-1200/mo في 100K استعلام

إبطال ذاكرة التخزين المؤقت

مشكلة صعبة كلاسيكية. لـ RAG، أستخدم نهجاً ثنائي الجانب:

  1. قائم على TTL: تنتهي جميع ذاكرات التخزين المؤقت بعد 24-72 ساعة حسب تكرار تغيير بيانات المصدر الخاصة بك.
  2. قائم على الحدث: عند تحديث المستندات المصدرية، قم بإبطال أي إدخالات ذاكرة تخزين مؤقت أشارت إلى معرفات تلك المستندات (هذا هو السبب في أننا نخزن معرفات الأجزاء في بيانات وصف ذاكرة التخزين المؤقت).

أنماط بنية الإنتاج

المكدس الكامل

إليك البنية التي نستخدمها لمعظم نشر RAG الإنتاجي:

User → Next.js App Router → Route Handler
                              ↓
                         Rate Limiter (Upstash)
                              ↓
                         Semantic Cache Check (Pinecone + Redis)
                              ↓ (miss)
                         Embedding Generation (OpenAI / cached)
                              ↓
                         Vector Search (Pinecone / Weaviate / pgvector)
                              ↓
                         Re-ranking (Cohere Rerank / custom)
                              ↓
                         Prompt Assembly
                              ↓
                         LLM Streaming (OpenAI / Anthropic)
                              ↓
                         Response → Cache Write → User

اختيار قاعدة البيانات المتجهة الخاصة بك

قاعدة البيانات الأفضل ل التسعير (2026) دمج Next.js
Pinecone مُدارة، بدون العمليات طبقة مجانية → $70/mo starter ممتاز (REST API)
Weaviate Cloud بحث هجين (متجه + كلمات رئيسية) $25/mo starter جيد (JS client)
pgvector (Supabase) بالفعل باستخدام Postgres طبقة مجانية → $25/mo عظيم (Supabase SDK)
Qdrant Cloud أداء عالي، التصفية طبقة مجانية → $30/mo جيد (JS client)
Turbopuffer محسّن التكلفة، S3-backed ~$0.04/GB مخزن لائق (REST API)

بالنسبة لمعظم مشاريع Next.js، أود أن أبدأ بـ pgvector على Supabase إذا كنت بالفعل في هذا النظام البيئي، أو Pinecone إذا كنت تريد عدم وجود عمليات تشغيلية. استخدمنا كل هذه في المشاريع حيث يغذي محتوى CMS خط أنابيب RAG.

معالجة الأخطاء والعودة

يحتاج RAG الإنتاجي إلى تدهور سلس:

export async function handleRAGQuery(query: string) {
  try {
    // Primary path: full RAG
    return await fullRAGPipeline(query);
  } catch (error) {
    if (error instanceof VectorDBError) {
      // Fallback 1: Use cached similar queries
      const fallback = await getFallbackFromCache(query);
      if (fallback) return { ...fallback, degraded: true };
    }
    
    if (error instanceof LLMError) {
      // Fallback 2: Try a different model
      return await fullRAGPipeline(query, { model: 'claude-3-5-sonnet' });
    }
    
    // Fallback 3: Return relevant raw chunks without LLM synthesis
    const chunks = await retrieveContext(query);
    return {
      response: 'I couldn\'t generate a full answer, but here are relevant excerpts:',
      chunks: chunks.slice(0, 3),
      degraded: true,
    };
  }
}

المراقبة والرؤية وتصحيح الأخطاء

لا يمكنك تحسين ما لا يمكنك قياسه. إليك ما تتبعه:

المقاييس الرئيسية

  • جودة الاسترجاع: هل الأجزاء الأفضل فعلاً ذات صلة؟ سجل درجات تشابه الجيب والمراجعة الفعلية أسبوعياً.
  • كمون الردود (p50/p95/p99): البث TTFB (الوقت لأول بايت) والوقت الإجمالي للإكمال.
  • معدلات ضرب ذاكرة التخزين المؤقت: حسب الطبقة. إذا كان معدل ضرب ذاكرة التخزين المؤقت الدلالية أقل من 10%، فقد يكون حدك مرتفعاً جداً.
  • استخدام الرمز لكل استعلام: المتوسط و p99. راقب محاولات حقن الموجهات التي تضخم السياق.
  • إشارات الملاحظات المستخدمة: الإبهام لأعلى/لأسفل، أحداث النسخ، الأسئلة المتابعة (يشير إلى أن الإجابة الأولى لم تكن جيدة بما فيه الكفاية).

الأدوات

لمراقبة نموذج اللغة الكبير، كانت لدي نتائج جيدة مع:

  • Langfuse: مفتوح المصدر، قابل للاستضافة ذاتياً، تصور تتبع ممتاز. الطبقة المجانية سخية.
  • Helicone: تسجيل قائم على الوكيل، ممتاز لتتبع التكاليف. دمج السطر الواحد.
  • Braintrust: جيد للتقييم وتكرار الأوامر. إطار العمل التقييمي صلب.
// Example: Langfuse integration with Vercel AI SDK
import { Langfuse } from 'langfuse';

const langfuse = new Langfuse();

export async function POST(req: Request) {
  const trace = langfuse.trace({ name: 'rag-query' });
  
  const retrievalSpan = trace.span({ name: 'retrieval' });
  const context = await retrieveContext(query);
  retrievalSpan.end({ output: { chunkCount: context.length, topScore: context[0]?.similarity } });
  
  const generationSpan = trace.generation({
    name: 'llm-response',
    model: 'gpt-4o',
    input: messages,
  });
  
  // ... stream response
  
  generationSpan.end({ output: completedText });
  await langfuse.flushAsync();
}

معايير الأداء وتحليل التكاليف

أرقام حقيقية من نشر الإنتاج (قاعدة معرفة قانونية، ~50K مستند، ~2M جزء):

المقياس بدون تحسين مع التحسين الكامل
كمون الوسيط (TTFB) 2.1s 340ms
كمون P95 (TTFB) 4.8s 1.2s
تكلفة نموذج اللغة الكبير الشهرية (50K استعلام) $2,400 $680
تكلفة التضمين الشهرية $180 $45
تكلفة قاعدة بيانات المتجهات الشهرية $70 $70 (بدون تغيير)
معدل ضرب ذاكرة التخزين المؤقت 0% 67%
رضا المستخدم (إبهام لأعلى %) 71% 89%

جاء تحسن الرضا في الغالب من أوامر أفضل وإعادة ترتيب، وليس من التخزين المؤقت. لكن جاء تحسن التكاليف والكمون من التخزين المؤقت تقريباً بالكامل.

تفصيل التكلفة لكل استعلام

في 50K استعلام/الشهر مع GPT-4o:

  • استعلام بدون تخزين مؤقت: ~$0.048 (تضمين + استرجاع + إنشاء)
  • ضرب ذاكرة التخزين المؤقت الدلالية: ~$0.0004 (بحث التضمين + قراءة ذاكرة التخزين المؤقت)
  • ضرب ذاكرة التخزين المؤقت للتضمين + فشل دلالي: ~$0.035 (يتخطى التضمين، لا يزال يُنشئ)

إذا كنت تبني شيئاً من هذا القبيل وتحتاج إلى مساعدة في البنية، فنحن نفعل هذا النوع من العمل بانتظام.

الأسئلة الشائعة

ما أفضل نموذج لغة كبير لـ RAG الإنتاجي في عام 2026؟ بالنسبة لمعظم حالات الاستخدام، يصل GPT-4o إلى الحد الأمثل من الجودة والسرعة والتكلفة. Claude 3.5 Sonnet ممتاز عندما تحتاج إلى معالجة سياق أطول أو تفكير أكثر دقة. بالنسبة للتطبيقات حساسة التكلفة بأسئلة أبسط، يعمل GPT-4o-mini أو Claude 3.5 Haiku بشكل مفاجئ جيد -- رأينا أنهم يطابقون جودة GPT-4o في الأسئلة المباشرة عندما يكون الاسترجاع جيداً. يهم النموذج أقل من جودة الاسترجاع وهندسة الأوامر الخاصة بك.

هل يجب أن أستخدم Edge Runtime أو Node.js Runtime لمعالجات RAG Route؟ Node.js، تقريباً دائماً. Edge Runtime لديه قيود اتصال تجعل العمل مع معظم قواعد بيانات المتجهات والـ ORMs مؤلماً. ميزة البداية الباردة للحافة ضئيلة لنقاط نهاية البث لأن المستخدم ينتظر بالفعل الاسترجاع + الإنشاء. استخدم Edge لنقاط النهاية البسيطة للوكيل أو المسارات غير المتعلقة بـ RAG.

كيف أمنع الهلوسات في ردود RAG؟ ثلاث استراتيجيات تعمل بالفعل: (1) اطلب بوضوح من النموذج أن يقول "لا أملك معلومات كافية" عندما يكون السياق غير كافٍ -- وأدرج أمثلة في موجهك. (2) استخدم درجة حرارة منخفضة (0.1-0.3) للاستعلامات الواقعية. (3) تطبيق متطلب الاستشهاد -- عندما يجب على النموذج الاستشهاد بأجزاء محددة، فمن الأصعب عليه أن يهلوس. التحقق اللاحق (التحقق من ظهور المطالبات في المستندات المصدرية) يضيف طبقة أمان أخرى.

كم عدد الأجزاء التي يجب أن أسترجعها لسياق RAG؟ استرجع أكثر مما تستخدمه. عادة ما أسترجع 15-20 جزء، وإعادة ترتيبها، ثم أستخدم أفضل 3-5 كسياق أساسي وأدرج ملخصات الـ 3-5 التالية. إفراغ 20 جزء كامل في نافذة السياق يدهور الجودة. يرتبك النموذج بالمعلومات غير ذات الصلة حتى عند وجود معلومات ذات صلة. الجودة على الكمية، في كل مرة.

هل pgvector جيد بما يكفي للإنتاج، أم أحتاج إلى قاعدة بيانات متجهة مخصصة؟ لحوالي 1M متجه، pgvector مع فهرسة HNSW على Supabase أو Neon جاهز للإنتاج بالكامل. أداء الاستعلام ممتازة وتحصل على فائدة البقاء في نظام Postgres الموجود الخاص بك. بما يتجاوز 1M متجه أو إذا كنت تحتاج إلى تصفية متقدمة مع بحث المتجهات، تبدأ الخيارات المخصصة مثل Pinecone أو Qdrant في التقدم. قمنا بتشغيل pgvector في الإنتاج لعدة مشاريع بدون مشاكل.

كيف أتعامل مع حالات التحميل مع حالات البث في React؟ يمنحك خطاف useChat الخاص بـ Vercel AI SDK منطق boolean isLoading، لكنه أكثر تعقيداً من ذلك. ينتقل الخطاف عبر الحالات: idle → waiting (لا توجد رموز بعد) → streaming (وصول الرموز) → idle. لأفضل تجربة مستخدم، أظهر مؤشر كتابة خلال مرحلة الانتظار وعرّض markdown بشكل تدريجي أثناء البث. استخدم محرر markdown يتعامل مع markdown غير الكامل برشاقة -- react-markdown يعمل لكن يمكن أن يوميض؛ فكر في تخزين بعض الرموز مؤقتاً قبل العرض.

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

كم مرة يجب أن أعيد تجميع مستنداتي لـ RAG؟ يعتمد على مدى تكرار تغيير بيانات المصدر الخاصة بك. بالنسبة لقواعس المعرفة الثابتة، يكون إعادة التجميع الكامل الأسبوعية على ما يرام. بالنسبة للمحتوى الديناميكي (مواقع تُدار بـ CMS، التوثيق الذي يتحدث يومياً)، قم بإعداد تجميع متزايد يُطلقه webhook. المفتاح هو وجود خط أنابيب يمكن أن يحدث الأجزاء الفردية دون إعادة تجميع كل شيء.