ארכיטקטורת Agentic RAG: כיצד חיפוש אוטונומי פותר תשובות חלקיות
RAG סטנדרטי עם שליפת מידע בודדת נכשל בשאילתות מורכבות: השוואת מדדים על פני שלוש תקופות, מציאת חברות עם EBITDA >25%, צבירת נתונים לפי מגזר. התשובות חלקיות; הסוכן אינו מזהה שההקשר אינו מספק. אנו פותרים זאת עם Agentic RAG—ארכיטקטורה שבה סוכן ה-LLM עצמו מחליט כיצד ומתי לחפש עד שנצבר מספיק מידע.
ארכיטקטורת ה-Agentic RAG שלנו משלבת שליפת מידע איטרטיבית עם ניתוב אדפטיבי באמצעות LangGraph לטיפול בשאלות מרובות-שלבים, וכתוצאה מכך שיפור משמעותי ב-RAG. גישת חיפוש אוטונומי זו יעילה פי 2.6 מ-RAG סטנדרטי למשימות אנליטיות, ושליפת מידע איטרטיבית מפחיתה הזיות ב-40% בהשוואה לשליפת מידע חד-פעמית. לקוחות בדרך כלל רואים הפחתה של 35% בעלויות התמיכה וחוסכים בממוצע 30,000 דולר בשנה. עם ניסיון של למעלה מ-5 שנים ו-20+ פרויקטים מוצלחים בתחום ה-AI ו-RAG, הצוות שלנו מספק פתרונות חזקים. פיתוח turnkey מתחיל ב-20,000 דולר.
לפי נתונים מהפרויקט שלנו, גישת הסוכן מפחיתה את עלויות התמיכה בעד 35% על ידי אוטומציה של שאילתות שגרתיות.
בעיות שנפתרות על ידי חיפוש סוכני
הזיות עקב הקשר חלקי. כאשר חיפוש בודד אינו מספיק, ה-LLM ממציא דברים. הסוכן בודק פעמיים ומוסיף נתונים חדשים. חוסר יכולת לענות על שאלות מרובות-שלבים. שאלה כמו "כיצד השתנתה הרווחיות של חברה X במשך 3 שנים?" דורשת שלושה חיפושים לפי שנה. הסוכן מבצע אותם ברצף. זמן השהייה מופרז בשאילתות פשוטות. RAG אדפטיבי (בלוק נוסף) מסווג את השאילתה ובוחר את האסטרטגיה: תשובה ישירה, חד-פעמית או איטרטיבית. זה מפחית את זמן ההשהיה עבור 70% מהשאלות הפשוטות.
מה זה Agentic RAG ולמה חיפוש אחד לא מספיק?
שאלות מורכבות כמעט ולא מכוסות על ידי chunk בודד. לדוגמה, "השווה את ה-P/E של חברות X ו-Y בשני הרבעונים האחרונים" דורש שני chunks עם תאריכים שונים. RAG חד-פעמי נותן תשובה חלקית ב-48% מהמקרים כאלה. הגישה המבוססת-סוכן משפרת את השלמות ל-84% באמצעות עידון איטרטיבי. הניסיון שלנו מראה שהסוכן משתמש בממוצע ב-2.3 חיפושים להשוואת תקופות וב-3.8 לצבירה מגזרית.
כיצד הסוכן מקבל החלטות וכמה איטרציות הוא צריך?
בכל שלב, הסוכן מנתח שלושה גורמים: ההקשר הנוכחי (מה נמצא), מספר החיפושים שבוצעו, והשאלה המקורית. אם ההקשר מספק, הוא מייצר תשובה. אם לא, הוא מנסח שאילתה חדשה, ספציפית ככל האפשר. לדוגמה, עבור השאלה "אילו חברות במגזר יש להן מרווח EBITDA מעל 25%?", הסוכן מחפש תחילה את רשימת החברות, לאחר מכן את הדוחות הכספיים של כל חברה, ולאחר מכן מצרף. אנו קובעים מגבלה של 5 איטרציות וזמן קצוב של 30 שניות כדי למנוע לולאות אינסופיות.
השוואה: RAG חד-פעמי לעומת Agentic RAG
| סוג שאלה | השלמות חד-פעמית | השלמות סוכנית | מספר חיפושים ממוצע |
|---|---|---|---|
| עובדות פשוטות | 0.91 | 0.92 | 1.1 |
| השוואת תקופות | 0.48 | 0.84 | 2.3 |
| בין-חברות | 0.31 | 0.76 | 3.1 |
| צבירה מגזרית | 0.22 | 0.68 | 3.8 |
ארכיטקטורת הסוכן משפרת את שלמות התשובה בשאילתות מורכבות פי 2–3. זמן ההשהיה גדל רק פי 2.4 (נשאר בטווח של 10–15 שניות), והדיוק עולה ל-95% לאחר אימות מומחה. חיפוש אוטונומי זה יעיל פי 2.6 משליפת מידע חד-פעמית למשימות אנליטיות.
| פרמטר | RAG סטנדרטי | Agentic RAG |
|---|---|---|
| שליפת מידע | חד-פעמית | איטרטיבית |
| בקרת הקשר | לא | כן, בכל שלב |
| התאמת שאילתה | לא | הסוכן מנסח שאילתות חדשות |
| מגבלת איטרציות | לא | כן (עד 5) |
| ישימות | עובדות פשוטות | שאלות אנליטיות מורכבות |
יישום עם LangGraph
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage
from typing import TypedDict, Annotated
import operator
class AgentState(TypedDict):
messages: Annotated[list, operator.add]
retrieved_docs: list[str]
search_count: int
sufficient_context: bool
llm = ChatOpenAI(model="gpt-4o", temperature=0)
def analyze_and_search(state: AgentState) -> AgentState:
"""Агент решает, что и как искать"""
query = state["messages"][0].content
retrieved_so_far = "\n".join(state["retrieved_docs"])
decision_prompt = f"""Ты — исследовательский агент. Твоя задача — найти информацию для ответа.
Вопрос: {query}
Уже найденная информация: {retrieved_so_far if retrieved_so_far else "Ничего не найдено"}
Кол-во выполненных поисков: {state["search_count"]}
Реши:
1. Достаточно ли найденной информации для полного ответа? (YES/NO)
2. Если NO — сформулируй следующий поисковый запрос (специфический аспект вопроса)
Ответь JSON: {{"sufficient": true/false, "next_query": "..."}}"""
response = llm.invoke([HumanMessage(content=decision_prompt)])
import json
decision = json.loads(response.content)
if decision["sufficient"] or state["search_count"] >= 4:
return {**state, "sufficient_context": True}
# Выполняем поиск
new_docs = retriever.invoke(decision["next_query"])
new_texts = [d.page_content for d in new_docs]
return {
**state,
"retrieved_docs": state["retrieved_docs"] + new_texts,
"search_count": state["search_count"] + 1,
"sufficient_context": False,
}
def generate_answer(state: AgentState) -> AgentState:
"""Генерирует финальный ответ на основе собранного контекста"""
context = "\n\n".join(state["retrieved_docs"])
question = state["messages"][0].content
answer = llm.invoke([
HumanMessage(content=f"Контекст:\n{context}\n\nВопрос: {question}\n\nДай полный ответ:")
])
return {**state, "messages": state["messages"] + [answer]}
def should_continue(state: AgentState) -> str:
return "generate" if state["sufficient_context"] else "search"
# Построение графа
graph = StateGraph(AgentState)
graph.add_node("search", analyze_and_search)
graph.add_node("generate", generate_answer)
graph.set_entry_point("search")
graph.add_conditional_edges("search", should_continue, {
"search": "search",
"generate": "generate",
})
graph.add_edge("generate", END)
agent = graph.compile()
RAG אדפטיבי: ניתוב לפי מורכבות ומגבלות הגנה
לא כל השאלות דורשות גישת סוכן. RAG אדפטיבי מוסיף מסווג:
from enum import Enum
class RetrievalStrategy(Enum):
DIRECT_ANSWER = "direct" # Без поиска (LLM знает ответ)
SINGLE_SHOT = "single" # Стандартный RAG
ITERATIVE = "iterative" # Agentic RAG
GRAPH = "graph" # Graph RAG
def classify_query(query: str) -> RetrievalStrategy:
"""Классифицирует запрос для выбора стратегии"""
response = llm.invoke(f"""Классифицируй вопрос по стратегии поиска:
- direct: общеизвестный факт, не требует поиска
- single: один поиск даст достаточный контекст
- iterative: нужно несколько поисков с разных аспектов
- graph: вопрос о связях между сущностями
Вопрос: {query}
Ответ (только одно слово):""")
return RetrievalStrategy(response.content.strip())
def adaptive_rag(query: str):
strategy = classify_query(query)
if strategy == RetrievalStrategy.DIRECT_ANSWER:
return llm.invoke(query).content
elif strategy == RetrievalStrategy.SINGLE_SHOT:
return standard_rag(query)
elif strategy == RetrievalStrategy.ITERATIVE:
return agent.invoke({"messages": [HumanMessage(content=query)], "retrieved_docs": [], "search_count": 0, "sufficient_context": False})
else:
return graph_rag.query(query)מגבלות הגנה: הגבלת מספר האיטרציות וזמן קצוב:
MAX_ITERATIONS = 5
TIMEOUT_SECONDS = 30
# В конфигурации LangGraph
agent = graph.compile(
checkpointer=MemorySaver(),
interrupt_before=["search"], # Для human-in-the-loop
)
# Аварийный выход при превышении итераций
config = {"recursion_limit": MAX_ITERATIONS * 2}
result = agent.invoke(initial_state, config=config) תהליך ולוחות זמנים
- ניתוח. אנו בוחנים את השאילתות שלך, סוגי הנתונים, דרישות זמן ההשהיה. מעריכים אם יש צורך בניתוב אדפטיבי.
- עיצוב. מתכננים את גרף המצבים, בוחרים LLM ומסד נתונים וקטורי. מגדירים מדדים (שלמות, דיוק p99).
- יישום. כותבים קוד סוכן, מחברים שליפי מידע, מגדירים מסווג.
- בדיקות. מריצים על השאילתות האמיתיות שלך, מודדים שלמות וזמן השהיה. אימות מומחה.
- פריסה. פורסים על התשתית שלך (AWS SageMaker, Vertex AI, או on-premise). מגדירים ניטור.
- עיצוב ארכיטקטורת סוכן: שבוע 1
- יישום שליפת מידע איטרטיבית: 1–2 שבועות
- ניתוב אדפטיבי: שבוע 1
- בדיקות והערכה: שבועיים
- סה"כ: 5–7 שבועות
העלות מחושבת באופן פרטני, בהתאם למורכבות ולנפח הנתונים. פרויקטים טיפוסיים נעים בין 20,000 ל-50,000 דולר, עם חיסכון ממוצע של 30,000 דולר בשנה עבור לקוחות.
תוצרים
- תיעוד ארכיטקטורה (גרף, החלטות שהתקבלו).
- קוד סוכן עם הערות.
- אינטגרציה עם מאגר הידע שלך (PDF, API, SQL).
- בדיקות על מדגם של 50+ שאילתות שלך.
- הכשרת צוות (2 סדנאות).
- אחריות ל-3 חודשים על תיקון באגים.
הזמינו פיתוח Agentic RAG turnkey—קבלו ייעוץ והערכה ראשונית תוך יומיים. צרו קשר כדי לדון בפרויקט שלכם.







