المقدمة
بدأ التوليد المعزز بالاسترجاع (Retrieval-Augmented Generation) كفكرة بسيطة: بدلاً من الاعتماد فقط على الذاكرة البارامترية لنموذج اللغة، يتم استرجاع المستندات ذات الصلة من قاعدة معرفة خارجية وتضمينها في سياق الـ prompt. نمط RAG البسيط هذا، المكون من تضمين-استرجاع-توليد، عمل بشكل مفاجئ جيداً للإجابة على الأسئلة البسيطة حول مجموعات المستندات المنظمة. لكن عندما دفعت الفرق RAG إلى الإنتاج لحالات استخدام أكثر تعقيداً، أصبحت قيوده واضحة بشكل مؤلم. الاستعلامات التي تتطلب الاستدلال عبر مستندات متعددة، والأسئلة الغامضة التي تحتاج إلى توضيح، وقواعد المعرفة ذات أنواع المحتوى المتنوعة كشفت جميعها عن هشاشة خط أنابيب الاسترجاع ثم التوليد.
يمثل RAG الوكيلي تحولاً جوهرياً في كيفية تصميم أنظمة الاسترجاع. بدلاً من خط أنابيب ثابت حيث تغذي كل خطوة الخطوة التالية بشكل خطي، يمنح RAG الوكيلي نموذج اللغة القدرة على تخطيط استراتيجية الاسترجاع، وتقييم جودة النتائج المسترجعة، وإعادة صياغة الاستعلامات عندما يفشل الاسترجاع الأولي، وتحديد متى يكون لديه معلومات كافية لتوليد إجابة نهائية. يصبح النموذج مشاركاً نشطاً في عملية الاسترجاع بدلاً من كونه مستهلكاً سلبياً للسياق المسترجع.
يغطي هذا الدليل أنماط البنية، وأطر العمل التنفيذية، وطرق التقييم، واعتبارات الإنتاج لبناء أنظمة RAG الوكيلية. نستند إلى عمليات نشر حقيقية في قواعد المعرفة المؤسسية، وأنظمة دعم العملاء، ومنصات التوثيق التقني حيث تم التحقق من هذه الأنماط على نطاق واسع.
من RAG البسيط إلى RAG الوكيلي: ما الذي تغير
يتبع RAG البسيط خط أنابيب حتمي من ثلاث خطوات: يتم تضمين استعلام المستخدم، ويسترجع بحث التشابه المتجهي أكثر أجزاء المستندات تشابهاً بعدد top-k، ويتم ربط هذه الأجزاء في prompt يستخدمه LLM لتوليد إجابة. لخط الأنابيب هذا ثلاث نقاط ضعف أساسية يعالجها RAG الوكيلي.
أولاً، يفترض RAG البسيط أن استعلام المستخدم مصاغ بالفعل بشكل جيد للاسترجاع. في الممارسة العملية، غالباً ما تكون استعلامات المستخدمين غامضة أو متعددة الأوجه أو تستخدم مصطلحات لا تتطابق مع مفردات المستندات المفهرسة. قد يحتاج المستخدم الذي يسأل عن إخفاقات النشر إلى مستندات حول معالجة الأخطاء وتكوين البنية التحتية وخطوط أنابيب CI/CD، لكن بحثاً متجهياً واحداً قد يُظهر جانباً واحداً فقط من هذه الجوانب.
ثانياً، لا يملك RAG البسيط بوابة جودة. إذا كانت المستندات المسترجعة غير ذات صلة أو قديمة أو غير كافية، يستمر خط الأنابيب على أي حال ويولد LLM إجابة من سياق ضعيف. لا توجد آلية للنظام للتعرف على فشل الاسترجاع والمحاولة مرة أخرى.
ثالثاً، يعامل RAG البسيط جميع الاستعلامات بشكل متماثل. سؤال بحث واقعي، وسؤال تحليلي معقد، وسؤال يتطلب التوليف من مصادر متعددة تمر جميعها عبر نفس خط أنابيب الاسترجاع والتوليد. يقدم RAG الوكيلي منطقاً شرطياً يختار استراتيجيات استرجاع وتوليد مختلفة بناءً على خصائص الاستعلام.
يتضمن الانتقال من RAG البسيط إلى الوكيلي إضافة ثلاث قدرات: تخطيط الاستعلامات (تحليل الاستعلامات المعقدة إلى استعلامات فرعية)، وتقييم الاسترجاع (تقييم ما إذا كان السياق المسترجع كافياً)، والتحسين التكراري (إعادة صياغة الاستعلامات وإعادة الاسترجاع عندما تكون النتائج غير كافية). تحول هذه القدرات خط أنابيب ثابت إلى نظام ديناميكي ذاتي التصحيح.
أنماط البنية الأساسية
تُبنى أنظمة RAG الوكيلية من عدد صغير من الأنماط القابلة للتركيب. فهم هذه الأنماط يتيح لك تصميم أنظمة مخصصة لحالة الاستخدام الخاصة بك.
التوجيه
أبسط نمط وكيلي يوجه الاستعلامات إلى واجهات استرجاع خلفية مختلفة بناءً على تصنيف الاستعلام. يحلل وكيل التوجيه الاستعلام الوارد ويوجهه إلى مصدر المعرفة الأنسب:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
router_prompt = ChatPromptTemplate.from_messages([
("system", """Classify the user query into one of these categories:
- technical_docs: Questions about API usage, configuration, or code
- policy: Questions about company policies, procedures, or compliance
- support: Questions about troubleshooting or known issues
- general: General questions that don't fit other categories
Respond with ONLY the category name."""),
("human", "{query}")
])
router_chain = router_prompt | ChatOpenAI(model="gpt-4o-mini") | StrOutputParser()
التوجيه قيّم عندما تمتد قاعدة معرفتك عبر مجالات متعددة بإستراتيجيات فهرسة مختلفة. قد يتم فهرسة التوثيق التقني بتقسيم واعٍ بالشفرة وتضمينات، بينما تستخدم مستندات السياسات تقسيماً دلالياً مع مرشحات البيانات الوصفية.
تحليل الاستعلامات
تتطلب الأسئلة المعقدة في كثير من الأحيان معلومات من أجزاء مستندات متعددة لن تظهر معاً في استرجاع واحد. يقسم تحليل الاستعلامات استعلاماً معقداً إلى استعلامات فرعية مستقلة، ويسترجع لكل منها، ويجمع النتائج:
decomposition_prompt = ChatPromptTemplate.from_messages([
("system", """Break the following complex question into 2-4 simpler
sub-questions that, when answered together, provide a complete answer
to the original question. Return as a JSON array of strings."""),
("human", "{query}")
])
# Example: "How does our API rate limiting compare to competitors
# and what are customers saying about it?"
# Decomposes to:
# ["What are our current API rate limiting policies?",
# "What rate limiting do our main competitors use?",
# "What customer feedback have we received about rate limiting?"]
التصحيح الذاتي
التصحيح الذاتي هو النمط الذي يميز RAG الوكيلي أكثر من RAG البسيط. بعد الاسترجاع، تقيّم خطوة تصنيف ما إذا كانت المستندات المسترجعة ذات صلة وكافية. إذا لم تكن كذلك، يعيد النظام صياغة الاستعلام ويحاول مرة أخرى:
grading_prompt = ChatPromptTemplate.from_messages([
("system", """You are a retrieval quality grader. Given a user question
and a set of retrieved documents, determine:
1. Are the documents relevant to the question? (yes/no)
2. Do the documents contain sufficient information to answer? (yes/no)
3. If insufficient, suggest a reformulated query.
Respond as JSON with keys: relevant, sufficient, reformulated_query"""),
("human", "Question: {query}\n\nDocuments: {documents}")
])
يسمح هذا النمط عادةً بـ 2-3 محاولات استرجاع قبل الرجوع إلى رسالة فشل أنيقة. غالباً ما تتحول الاستعلامات المعاد صياغتها من البحث بالتشابه الدلالي إلى البحث القائم على الكلمات المفتاحية، أو توسع النطاق، أو تستهدف حقول بيانات وصفية محددة.
LangGraph لتنسيق الوكلاء مع إدارة الحالة
برز LangGraph كإطار العمل القياسي لبناء أنظمة RAG الوكيلية لأنه يوفر إدارة حالة صريحة وتوجيهاً شرطياً ودعماً للدورات التي لا تستطيع التجريدات الأبسط القائمة على السلاسل في LangChain التعبير عنها.
يُعرّف نظام RAG الوكيلي القائم على LangGraph كرسم بياني للحالات حيث تمثل العقد خطوات المعالجة وتمثل الحواف الانتقالات بين الخطوات. تسمح الحواف الشرطية للرسم البياني بالتفرع بناءً على النتائج الوسيطة:
from langgraph.graph import StateGraph, END
from typing import TypedDict, List, Annotated
from operator import add
class AgentState(TypedDict):
query: str
sub_queries: List[str]
documents: List[dict]
generation: str
retry_count: int
retrieval_grade: str
def route_query(state: AgentState) -> AgentState:
"""Classify and route the incoming query."""
query = state["query"]
classification = router_chain.invoke({"query": query})
state["route"] = classification
return state
def retrieve(state: AgentState) -> AgentState:
"""Retrieve documents based on query and route."""
query = state["query"]
docs = retriever.invoke(query)
state["documents"] = docs
return state
def grade_documents(state: AgentState) -> AgentState:
"""Grade retrieved documents for relevance and sufficiency."""
grade = grading_chain.invoke({
"query": state["query"],
"documents": state["documents"]
})
state["retrieval_grade"] = grade["sufficient"]
state["retry_count"] = state.get("retry_count", 0) + 1
if not grade["sufficient"] and grade.get("reformulated_query"):
state["query"] = grade["reformulated_query"]
return state
def generate(state: AgentState) -> AgentState:
"""Generate final answer from retrieved context."""
answer = generation_chain.invoke({
"query": state["query"],
"documents": state["documents"]
})
state["generation"] = answer
return state
def should_retry(state: AgentState) -> str:
"""Decide whether to retry retrieval or proceed to generation."""
if state["retrieval_grade"] == "yes":
return "generate"
if state["retry_count"] >= 3:
return "generate" # Give up and generate with what we have
return "retrieve"
# Build the graph
workflow = StateGraph(AgentState)
workflow.add_node("route", route_query)
workflow.add_node("retrieve", retrieve)
workflow.add_node("grade", grade_documents)
workflow.add_node("generate", generate)
workflow.set_entry_point("route")
workflow.add_edge("route", "retrieve")
workflow.add_edge("retrieve", "grade")
workflow.add_conditional_edges("grade", should_retry, {
"retrieve": "retrieve",
"generate": "generate"
})
workflow.add_edge("generate", END)
app = workflow.compile()
تجعل بنية الرسم البياني تدفق التحكم صريحاً وقابلاً للتصحيح. يمكنك تصور الرسم البياني وتتبع التنفيذ عبر كل عقدة وفهم سبب اتخاذ النظام لمسار معين لأي استعلام. هذه الشفافية حاسمة لأنظمة الإنتاج حيث تحتاج إلى تشخيص الأعطال وشرح السلوك.
يدعم LangGraph أيضاً أنماطاً أكثر تقدماً مثل الاسترجاع المتوازي عبر فهارس متعددة، ونقاط تفتيش الإنسان في الحلقة حيث يتوقف الوكيل مؤقتاً لتأكيد المستخدم، وحالة مستمرة تبقى عبر المحادثات.
استراتيجيات الاسترجاع
عادةً ما تكون طبقة الاسترجاع في نظام RAG الوكيلي أكثر تطوراً من بحث واحد في مخزن المتجهات. تجمع أنظمة الإنتاج بين استراتيجيات استرجاع متعددة.
البحث الهجين
يجمع البحث الهجين بين الاسترجاع المتجهي الكثيف والاسترجاع المتناثر بالكلمات المفتاحية، مما يمنحك الفهم الدلالي للتضمينات مع دقة مطابقة الكلمات المفتاحية BM25:
from langchain_community.retrievers import BM25Retriever
from langchain.retrievers import EnsembleRetriever
from langchain_chroma import Chroma
vectorstore = Chroma(
collection_name="documents",
embedding_function=embedding_model,
)
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 10
hybrid_retriever = EnsembleRetriever(
retrievers=[vector_retriever, bm25_retriever],
weights=[0.6, 0.4],
)
إعادة الترتيب
بعد الاسترجاع الأولي، يسجل مُعيد الترتيب بالمشفر المتقاطع كل مستند مقابل الاستعلام بدقة أعلى بكثير من تشابه المشفر الثنائي الاتجاه. هذا مكلف حسابياً لكنه يحسن الدقة بشكل كبير:
from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank
reranker = CohereRerank(model="rerank-v3.5", top_n=5)
compression_retriever = ContextualCompressionRetriever(
base_compressor=reranker,
base_retriever=hybrid_retriever,
)
الاسترجاع متعدد الفهارس
غالباً ما تمتد قواعد المعرفة الإنتاجية عبر فهارس متعددة بمخططات مختلفة ونماذج تضمين وأنواع مستندات. يمكن للنظام الوكيلي الاستعلام من فهارس متعددة بالتوازي ودمج النتائج:
async def multi_index_retrieve(query: str, indexes: list) -> list:
"""Retrieve from multiple indexes in parallel."""
import asyncio
async def retrieve_from_index(index, query):
return await index.aretrieve(query)
tasks = [retrieve_from_index(idx, query) for idx in indexes]
results = await asyncio.gather(*tasks)
# Flatten and deduplicate
all_docs = []
seen_ids = set()
for result_set in results:
for doc in result_set:
if doc.metadata["id"] not in seen_ids:
all_docs.append(doc)
seen_ids.add(doc.metadata["id"])
return all_docs
التقييم باستخدام RAGAS و DeepEval
يتطلب تقييم أنظمة RAG الوكيلية قياس أبعاد متعددة للجودة. RAGAS و DeepEval هما إطارا التقييم الأكثر اعتماداً على نطاق واسع، ولكل منهما نقاط قوة مميزة.
يوفر RAGAS مجموعة من المقاييس بدون مرجع تقيّم جودة RAG دون الحاجة إلى إجابات حقيقة أساسية لكل استعلام اختباري:
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_precision,
context_recall,
)
from datasets import Dataset
eval_dataset = Dataset.from_dict({
"question": questions,
"answer": generated_answers,
"contexts": retrieved_contexts,
"ground_truth": reference_answers,
})
results = evaluate(
dataset=eval_dataset,
metrics=[
faithfulness,
answer_relevancy,
context_precision,
context_recall,
],
)
print(results)
تقيس الأمانة ما إذا كانت الإجابة المولدة مدعومة بالسياق المسترجع، وتكشف الهلوسات. تقيس صلة الإجابة ما إذا كانت الإجابة تتناول السؤال. تقيس دقة السياق ما إذا كانت المستندات المسترجعة ذات صلة، ويقيس استدعاء السياق ما إذا كان الاسترجاع قد التقط جميع المعلومات الضرورية.
يوسع DeepEval التقييم بمقاييس إضافية ذات صلة خاصة بالأنظمة الوكيلية:
from deepeval import evaluate
from deepeval.metrics import (
FaithfulnessMetric,
AnswerRelevancyMetric,
ContextualRelevancyMetric,
HallucinationMetric,
)
from deepeval.test_case import LLMTestCase
test_case = LLMTestCase(
input="How do I configure rate limiting?",
actual_output=generated_answer,
expected_output=reference_answer,
retrieval_context=retrieved_chunks,
)
metrics = [
FaithfulnessMetric(threshold=0.8),
AnswerRelevancyMetric(threshold=0.7),
ContextualRelevancyMetric(threshold=0.7),
HallucinationMetric(threshold=0.5),
]
evaluate(test_cases=[test_case], metrics=metrics)
بالنسبة لـ RAG الوكيلي تحديداً، يجب عليك أيضاً قياس كفاءة الاسترجاع: كم عدد جولات الاسترجاع التي يحتاجها النظام في المتوسط، ما نسبة الاستعلامات التي تتطلب إعادة صياغة، وكيف تتدهور جودة الإجابة عبر محاولات إعادة المحاولة. هذه المقاييس خاصة بالحلقة الوكيلية ولا تغطيها أطر تقييم RAG القياسية.
أنماط الإنتاج
يتطلب نقل RAG الوكيلي من النموذج الأولي إلى الإنتاج معالجة مخاوف الموثوقية والأمان والتشغيل التي لا تظهر أثناء التطوير.
حواجز الحماية
يحتاج كل نظام RAG إنتاجي إلى حواجز حماية تمنع LLM من توليد استجابات ضارة أو خارج الموضوع أو غير مدعومة بالحقائق:
from guardrails import Guard
from guardrails.hub import ToxicLanguage, CompetitorCheck
guard = Guard().use_many(
ToxicLanguage(on_fail="exception"),
CompetitorCheck(
competitors=["competitor_a", "competitor_b"],
on_fail="fix"
),
)
raw_response = generation_chain.invoke({"query": query, "documents": docs})
validated_response = guard.validate(raw_response)
سلاسل الاحتياط
عندما تفشل الحلقة الوكيلية في إيجاد سياق كافٍ بعد الحد الأقصى من المحاولات، يحتاج النظام إلى تدهور أنيق بدلاً من توليد إجابة غير موثوقة:
def generate_with_fallback(state: AgentState) -> AgentState:
if state["retrieval_grade"] != "yes" and state["retry_count"] >= 3:
state["generation"] = (
"I wasn't able to find sufficient information in our knowledge base "
"to fully answer your question. Here's what I found:\n\n"
f"{partial_answer_from_context(state['documents'])}\n\n"
"For a complete answer, I'd recommend contacting the support team."
)
state["confidence"] = "low"
else:
state["generation"] = generation_chain.invoke({
"query": state["query"],
"documents": state["documents"]
})
state["confidence"] = "high"
return state
الإنسان في الحلقة
للتطبيقات عالية المخاطر، يدعم LangGraph نقاط مقاطعة حيث يوقف الوكيل التنفيذ وينتظر الموافقة البشرية:
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
# Add interrupt before generation for sensitive queries
workflow.add_node("human_review", lambda state: state)
workflow.add_conditional_edges(
"grade",
lambda state: "human_review" if state.get("sensitive") else "generate",
{"human_review": "human_review", "generate": "generate"}
)
app = workflow.compile(
checkpointer=checkpointer,
interrupt_before=["human_review"]
)
قابلية المراقبة مع LangSmith و Phoenix
قابلية المراقبة غير قابلة للتفاوض لأنظمة الوكلاء في الإنتاج. الطبيعة غير الحتمية لتدفق التحكم المدفوع بـ LLM تعني أنه لا يمكنك التنبؤ أو اختبار كل مسار تنفيذ ممكن. تحتاج إلى تتبع شامل لفهم ما يفعله نظامك في الإنتاج.
يوفر LangSmith تتبعاً شاملاً لتطبيقات LangGraph:
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-api-key"
os.environ["LANGCHAIN_PROJECT"] = "agentic-rag-production"
# All LangGraph invocations are automatically traced
result = app.invoke({"query": "How do I configure rate limiting?"})
يُظهر كل تتبع مسار التنفيذ الكامل عبر الرسم البياني: أي العقد تمت زيارتها، وما كانت مدخلات ومخرجات LLM في كل خطوة، ونتائج الاسترجاع، وقرارات التقييم، وعدد الرموز. هذا ضروري لتصحيح الحالات التي يتخذ فيها الوكيل مساراً غير متوقع أو يولد إجابة ضعيفة.
يوفر Arize Phoenix بديلاً مفتوح المصدر مع التركيز على مراقبة جودة الاسترجاع:
import phoenix as px
from phoenix.trace.langchain import LangChainInstrumentor
px.launch_app()
LangChainInstrumentor().instrument()
# Traces are now collected in Phoenix
result = app.invoke({"query": user_query})
يعتبر Phoenix قيّماً بشكل خاص لمراقبة جودة الاسترجاع بمرور الوقت. يتتبع انحراف التضمينات وتوزيعات صلة الاسترجاع ويمكنه التنبيه عندما تتدهور جودة الاسترجاع، مما يشير غالباً إلى أن قاعدة المعرفة انحرفت عن توزيع التدريب لنموذج التضمين وتحتاج إلى إعادة فهرسة.
المقاييس الرئيسية للمراقبة في الإنتاج:
# Custom metrics to track
metrics = {
"avg_retrieval_rounds": [],
"reformulation_rate": [],
"fallback_rate": [],
"latency_p50_ms": [],
"latency_p99_ms": [],
"token_cost_per_query": [],
"faithfulness_score": [],
}
تحسين التكلفة وزمن الاستجابة
أنظمة RAG الوكيلية بطبيعتها أكثر تكلفة وأبطأ من RAG البسيط لأنها تجري استدعاءات متعددة لـ LLM لكل استعلام. يتطلب تحسين التكلفة وزمن الاستجابة دون التضحية بالجودة قرارات معمارية دقيقة.
استخدم نماذج أصغر للتوجيه والتقييم. لا يحتاج الموجه ومقيّم المستندات إلى قدرة الاستدلال الكاملة لنموذج رائد. يمكن لـ GPT-4o-mini أو Claude 3.5 Haiku التعامل مع هذه المهام بجزء من التكلفة وزمن الاستجابة:
# Use a small, fast model for routing and grading
routing_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
grading_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# Use a larger model only for final generation
generation_model = ChatOpenAI(model="gpt-4o", temperature=0.1)
خزّن نتائج الاسترجاع مؤقتاً بشكل مكثف. العديد من استعلامات المستخدمين هي تنويعات على نفس السؤال الأساسي. يمكن لذاكرة التخزين المؤقت الدلالية التي تطابق الاستعلامات ضمن عتبة تشابه أن تقضي على عمليات الاسترجاع واستدعاءات LLM المكررة:
from langchain_community.cache import RedisSemanticCache
set_llm_cache(RedisSemanticCache(
redis_url="redis://localhost:6379",
embedding=embedding_model,
score_threshold=0.95,
))
حدد مهلات زمنية صارمة في كل خطوة لمنع زمن الاستجابة الخارج عن السيطرة. لا يجب أن يتسبب استدعاء LLM واحد بطيء في انتهاء مهلة الطلب بالكامل:
from asyncio import wait_for, TimeoutError
async def retrieve_with_timeout(state, timeout_seconds=5):
try:
return await wait_for(retrieve(state), timeout=timeout_seconds)
except TimeoutError:
state["documents"] = []
state["retrieval_grade"] = "no"
return state
دراسات حالة واقعية وأنماط مضادة
نمط الفشل الأكثر شيوعاً في عمليات نشر RAG الوكيلي هو حلقة إعادة المحاولة اللانهائية. بدون حد أقصى صارم لمحاولات الاسترجاع وسلوك احتياطي واضح، يمكن للوكيل أن يدور عبر إعادة الصياغات إلى ما لا نهاية، مستهلكاً الرموز وزمن الاستجابة. حدد دائماً حدود إعادة المحاولة بشكل صريح وقس معدل إعادة الصياغة. إذا كان أكثر من 20% من الاستعلامات تتطلب إعادة صياغة، فإن المشكلة على الأرجح في طبقة الاسترجاع (تقسيم سيء، نموذج تضمين خاطئ، فهرس قديم) وليس في منطق الوكيل.
نمط مضاد آخر شائع هو الإفراط في التوجيه. أحياناً تبني الفرق رسوماً بيانية توجيه معقدة بعشرات الفهارس المتخصصة بينما مسترجع هجين واحد مصمم جيداً سيكون أداؤه أفضل. ابدأ بأبسط بنية تلبي متطلباتك وأضف التعقيد فقط عندما يكون لديك مقاييس تُظهر أن الأساليب الأبسط غير كافية.
حشو نافذة السياق هو نمط مضاد ثالث. استرجاع 20 جزءاً من المستندات وحشرها جميعاً في الـ prompt يهدر الرموز ويمكن أن يؤدي فعلاً إلى تدهور جودة الإجابة لأن LLM يكافح لتحديد المعلومات ذات الصلة في بحر من السياق المرتبط بشكل هامشي. إعادة ترتيب عدد صغير من الأجزاء عالية الجودة (عادةً 3-5) يتفوق باستمرار على نوافذ السياق الأكبر في معايير التقييم.
أخيراً، احذر من الإفراط في التحسين المدفوع بالتقييم. الفرق التي تحسّن فقط لدرجات RAGAS يمكن أن تبني أنظمة تحقق أداءً جيداً في المعايير لكنها تنتج إجابات مفرطة الحذر ومراوغة يجدها المستخدمون عديمة الفائدة. وازن بين التقييم الكمي والمراجعة النوعية لمحادثات المستخدمين الفعلية.
المستقبل: أنظمة RAG متعددة الوكلاء
الحدود التالية في RAG الوكيلي هي الأنظمة متعددة الوكلاء حيث يتعاون وكلاء متخصصون في مهام الاسترجاع والتوليف المعقدة. بدلاً من وكيل واحد يتعامل مع خط أنابيب الاسترجاع والتوليد بالكامل، تنشر فريقاً من الوكلاء بتخصصات مختلفة.
يتعامل وكيل البحث مع تحليل الاستعلامات والاسترجاع متعدد القفزات عبر مجموعات المستندات الكبيرة. يتحقق وكيل التحقق من الحقائق من الادعاءات المولدة مقابل المستندات المصدر. يجمع وكيل التوليف النتائج من استعلامات فرعية متعددة في إجابة متماسكة ومنظمة جيداً. يراجع وكيل التحرير المخرجات النهائية من حيث الوضوح والدقة والنبرة.
from langgraph.graph import StateGraph
# Multi-agent RAG architecture
multi_agent = StateGraph(MultiAgentState)
multi_agent.add_node("planner", planner_agent)
multi_agent.add_node("researcher", researcher_agent)
multi_agent.add_node("fact_checker", fact_check_agent)
multi_agent.add_node("synthesizer", synthesis_agent)
multi_agent.set_entry_point("planner")
multi_agent.add_edge("planner", "researcher")
multi_agent.add_edge("researcher", "fact_checker")
multi_agent.add_conditional_edges(
"fact_checker",
lambda s: "researcher" if s["needs_more_research"] else "synthesizer",
)
multi_agent.add_edge("synthesizer", END)
هذه البنية أكثر تكلفة لكل استعلام لكنها تتعامل مع أسئلة البحث المعقدة التي تواجه أنظمة الوكيل الفردي صعوبة فيها. التحدي التصميمي الرئيسي هو تحديد واجهات واضحة بين الوكلاء وضمان أن الحمل الزائد لاتصالات الوكلاء لا يبطل فوائد التخصص.
يتقارب النظام البيئي للأدوات لدعم أنماط الوكلاء المتعددين بشكل أصلي. تركيب الرسوم البيانية الفرعية في LangGraph وطبقة تنسيق الوكلاء في LlamaIndex و CrewAI جميعها توفر بدائيات لبناء أنظمة RAG متعددة الوكلاء. مع نضوج هذه الأطر واستمرار انخفاض التكاليف، سيصبح RAG متعدد الوكلاء عملياً لمجموعة أوسع من تطبيقات الإنتاج. المبادئ المغطاة في هذا الدليل — إدارة الحالة الصريحة وتقييم جودة الاسترجاع والاحتياطات الأنيقة وقابلية المراقبة الشاملة — تظل أساسية بغض النظر عما إذا كنت تنشر وكيلاً فردياً أو فريقاً من الوكلاء المتخصصين.