תרגול זה ידריך אתכם בבניית סוכן RAG (Retrieval-Augmented Generation) מלא וישים באמצעות פייתון. סוכן RAG הוא מודל שפה גדול (LLM) שמסוגל לחפש מידע חיצוני (למשל, מסמכי PDF) ולהשתמש בו כ"בסיס ידע" לפני שהוא עונה על שאלות.
במקום לענות רק על סמך נתוני האימון שלו, סוכן ה-RAG שלנו יבצע תהליך דו-שלבי:
- Retrieval (שליפה): הפיכת מסמכים (PDF) לחלקים קטנים (Chunks) וייצוגם כווקטורים (Embeddings).
- Generation (יצירה): שליפת הווקטורים הרלוונטיים ביותר לשאלת המשתמש, ושימוש בהם כקונטקסט (Prompt) למודל ה-LLM (נשתמש ב-GPT-4o).
זהו תרגול מעשי שישלב ספריות מפתח בעולם ה-AI: PyPDF2, Sentence Transformers, PyTorch, ו-OpenAI.
הערה: כאן נבנה את כל הקוד בתוך קובץ אחד בשם rag_agent.py (או כל שם אחר שתבחרו), תוך הוספת מקטעים באופן מצטבר.
הכנה – הקמת הסביבה הוירטואלית
לפני שמתחילים לכתוב קוד, חשוב להקים סביבה וירטואלית מבודדת (venv). סביבה זו מבטיחה שכל הספריות שנתקין (כמו PyTorch ו-OpenAI) יישארו צמודות לפרויקט זה בלבד ולא יתנגשו עם ספריות אחרות במערכת ההפעלה שלכם.
-
יצירת סביבה וירטואלית (
.venv)
- ודאו שאתם נמצאים בתיקיית הפרויקט הריקה. הריצו את הפקודה הבאה ליצירת התיקייה
.venv(קיצור של virtual environment):python3 -m venv .venv - הסבר: הפקודה מורה למפרש הפייתון (Python 3) ליצור סביבה וירטואלית בתיקייה מקומית בשם
.venv.
- ודאו שאתם נמצאים בתיקיית הפרויקט הריקה. הריצו את הפקודה הבאה ליצירת התיקייה
-
הפעלת הסביבה הווירטואלית (Activation)
- כדי "להיכנס" לסביבה כך שפקודות
pip installיפעלו בתוכה, הריצו את הפקודה המתאימה למערכת ההפעלה שלכם: - עבור Mac / Linux:
source .venv/bin/activate - עבור Windows (Command Prompt):
.venv\Scripts\activate.bat - אימות: ודאו ששם הסביבה מופיע בסוגריים מרובעים בשורת הפקודה שלכם, לדוגמה:
(.venv).
- כדי "להיכנס" לסביבה כך שפקודות
1. התקנה, הכנה והגדרות סביבה
בשלב זה נתקין את כל הספריות הנדרשות ונכין את קובצי התצורה של הפרויקט.
-
התקנת ספריות
- התקינו את כל הספריות הנדרשות לפרויקט:
OpenAILocal Modelspip install PyPDF2 sentence-transformers torch openai python-dotenv coloramapip install PyPDF2 torch sentence-transformers transformers colorama - צרו קובץ חדש בשם
rag_agent.py. - הכנת קבצים:
- צרו תיקייה בשם
assetsבתוך תיקיית הפרויקט. - מקמו בתוכה קובץ PDF לבחירתכם, המכיל טקסט בנושא מסויים, וישמש כבסיס הידע לסוכן. לא מוצאים? הורידו מכאן את התסריט המלא של הסרט Lion King.
- הכנת מודלי השפה (שיחה ו-Embedding):
-
במידה ובחרתם לעבוד עם מודלי שיחה של OpenAI, צרו קובץ בשם
.envבתיקייה הראשית של הפרויקט והגדירו בו את מפתח ה-API שלכם בפורמט:
OPENAI_API_KEY=<YOUR_API_KEY_HERE> -
במידה ובחרתם לעבוד עם מודלים לוקאליים, ונדרשת הורדה שלהם מאתר HuggingFace, צרו קובץ חדש בשם
getModels.pyוהדביקו את הקוד הבא (אם המודלים כבר נמצאים אצלכם על המחשב המקומי – צעד זה לא נדרש):
from huggingface_hub import snapshot_download # Download embedding model snapshot_download(repo_id="intfloat/multilingual-e5-base", local_dir="./models/multilingual-e5-base") # Download chat model (from HuggingFace) snapshot_download("google/gemma-2b-it", local_dir="./models/gemma-2b-it")התקינו את הספריה הנדרשת להורדה:
pip install huggingface-hubוכעת הריצו את הקובץ שיצרתם. המתינו להורדת שני המודלים לספריה המקומית
models.
-
במידה ובחרתם לעבוד עם מודלי שיחה של OpenAI, צרו קובץ בשם
- צרו תיקייה בשם
- התקינו את כל הספריות הנדרשות לפרויקט:
-
אימפורטים והגדרות גלובליות
- העתיקו והדביקו את קטע הקוד הבא לראש הקובץ
rag_agent.py:
OpenAILocal Modelsimport PyPDF2 import re import os import torch import openai from sentence_transformers import SentenceTransformer, util from dotenv import load_dotenv from colorama import Fore, Back, Style, init # colorama library - enables colored printouts init(autoreset=True) # 1. global vars for the knowledge base kb_content = [] # a list of the textual chunks kb_embeddings = None # the embeddings kb_embeddings_tensor = None # the embeddings tensor embedding_model = None # LLM for the embedding # 2. global var for conversation memory management (context) conversation = [] # 3. loading .env file as environment variables (for OPEN_API_KEY) load_dotenv() OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") # sanity test for OPENAI KEY if not OPENAI_API_KEY: raise ValueError("OPENAI_API_KEY is not set in the .env file.")import PyPDF2 import re import os import torch from sentence_transformers import SentenceTransformer, util from transformers import AutoModelForCausalLM, AutoTokenizer from colorama import Fore, init os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1" os.environ["PYTORCH_MPS_HIGH_WATERMARK_RATIO"] = "0.0" init(autoreset=True) kb_content = [] kb_embeddings_tensor = None kb_embeddings = None embedding_model = None conversation = [] CHAT_MODEL_PATH = "./models/gemma-2b-it" EMBEDDING_MODEL_PATH = "./models/multilingual-e5-base" - הסבר: קטע זה מייבא את כל הספריות, מאתחל את `colorama` (להדפסה יפה של טקסטים צבעוניים), ומגדיר את המשתנים הגלובליים שיאחסנו את הנתונים המורכבים (כמו טנזור הווקטורים) לאורך חיי התוכנית.
- העתיקו והדביקו את קטע הקוד הבא לראש הקובץ
2. פונקציות בסיס: פירוק PDF ויצירת Embeddings
זהו ליבת תהליך ה-RAG – הפיכת מסמכים לטקסט, חלוקתם ליחידות קטנות, והמרתן לווקטורים.
-
פונקציית
add_pdf(Chunking)
- הוסיפו את פונקציית פירוק ה-PDF לסוף הקובץ (אין צורך להתעמק בקוד זה, הוא אינו קשור ישירות למהות המעבדה):
def add_pdf(file_path): """ Reads a PDF, extracts text, cleans it, and splits it into chunks (max 1000 chars) by sentence boundaries, then saves it to knowledge_base.txt. """ with open(file_path, 'rb') as pdf_file: pdf_reader = PyPDF2.PdfReader(pdf_file) num_pages = len(pdf_reader.pages) text = '' for page_num in range(num_pages): page = pdf_reader.pages[page_num] if page.extract_text(): text += page.extract_text() + " " # Normalization and cleanup text = re.sub(r'\s+', ' ', text).strip() # Split text into chunks by sentences sentences = re.split(r'(?<=[.!?]) +', text) chunks = [] current_chunk = "" for sentence in sentences: # Respecting a maximum chunk size of ~1000 characters if len(current_chunk) + len(sentence) + 1 < 1000: current_chunk += (sentence + " ").strip() else: chunks.append(current_chunk) current_chunk = sentence + " " if current_chunk: chunks.append(current_chunk) # Save chunks to a file, each separated by two newlines with open("knowledge_base.txt", "w", encoding="utf-8") as kb_file: # Changed to 'w' to overwrite/start fresh for chunk in chunks: kb_file.write(chunk.strip() + "\n\n") print(f"PDF content split into {len(chunks)} chunks and saved to knowledge_base.txt.") - הסבר: פונקציה זו קוראת PDF, מוציאה טקסט, ומבצעת Chunking - חלוקה ל"חתיכות" של עד 1000 תווים, תוך שמירה על גבולות משפט הגיוניים. התוצאה נשמרת בקובץ טקסט בשם
knowledge_base.txt.
- הוסיפו את פונקציית פירוק ה-PDF לסוף הקובץ (אין צורך להתעמק בקוד זה, הוא אינו קשור ישירות למהות המעבדה):
-
פונקציית
create_embeddings
- קראו היטב את פונקציית יצירת הווקטורים ואת ההערות בגוף הפונקציה, והוסיפו אותה לסוף הקובץ:
OpenAILocal Modelsdef create_embedding(): """ Loads the knowledge base, initializes the Sentence Transformer model, and generates vector embeddings for all chunks. """ global kb_embeddings, kb_embeddings_tensor, kb_content, embedding_model # 1. Load content from the text file if os.path.exists("knowledge_base.txt"): with open("knowledge_base.txt", "r", encoding='utf-8') as kb_file: # Read lines, filtering out empty ones (due to the "\n\n" separator) kb_content = [line.strip() for line in kb_file if line.strip()] print(Fore.YELLOW + f"Loaded {len(kb_content)} knowledge base entries.") if not kb_content: print(Fore.RED + "Knowledge base is empty. Cannot create embeddings.") return # 2. Initialize the Embedding Model (S-Transformer) print(Fore.YELLOW + "Initializing Sentence Transformer (all-MiniLM-L6-v2)...") embedding_model = SentenceTransformer("all-MiniLM-L6-v2") # 3. Generate Embeddings print(Fore.YELLOW + "Now generating embeddings...") kb_embeddings = embedding_model.encode(kb_content, show_progress_bar=True) # 4. Convert to PyTorch Tensor for fast vector operations kb_embeddings_tensor = torch.tensor(kb_embeddings) print(Fore.GREEN + f"Embeddings generated successfully. Tensor shape: {kb_embeddings_tensor.shape}")def create_embedding(): """ Loads the knowledge base from a text file, initializes the Sentence Transformer model, and generates vector embeddings for all stored text chunks. """ global kb_embeddings, kb_embeddings_tensor, kb_content, embedding_model # 1. Load knowledge base content from file (if it exists) if os.path.exists("knowledge_base.txt"): with open("knowledge_base.txt", "r", encoding='utf-8') as kb_file: # Read all lines as a list of strings (each line = one knowledge chunk) kb_content = kb_file.readlines() print(f"Loaded {len(kb_content)} knowledge base entries.") # 2. Initialize the LOCAL embedding model using the specified model path print("Now generating embeddings...") embedding_model = SentenceTransformer(EMBEDDING_MODEL_PATH) # 3. Generate embeddings for all chunks (if there’s content) kb_embeddings = embedding_model.encode(kb_content) if kb_content else [] # 4. Convert the resulting embeddings to a PyTorch tensor # for efficient similarity computation (cosine similarity, etc.) kb_embeddings_tensor = torch.tensor(kb_embeddings) - הסבר: פונקציה זו בונה למעשה את בסיס הידע של הסוכן. היא עושה זאת במספר שלבים:
- טוענת את שברי הטקסט מתוך קובץ
knowledge_base.txt - מורידה (אם לא קיים) ומאתחלת את מודל Sentence Transformer (מודל Embedding פופולרי)
- ממירה את הטקסט לווקטורים מספריים. אחסון הווקטורים כ-PyTorch Tensor מאפשר חישובים מהירים מאוד.
בסיום פעולה זאת, נקבל שלושה מערכים בעלי גודל זהה:
kb_contentהמכיל את שברי (Chunks) הטקסט מתוך הקובץ המקוריkb_embeddingsהמכיל את הוקטורים שה LLM חישב לכל אחד מה Chunks, לפי הסדרkb_embeddings_tensorהמכיל את הוקטורים, בפורמט PyTorch Tensor מהיר ויעיל חישובית
- טוענת את שברי הטקסט מתוך קובץ
- קראו היטב את פונקציית יצירת הווקטורים ואת ההערות בגוף הפונקציה, והוסיפו אותה לסוף הקובץ:
3. רכיבי ה-LLM: ניהול מודל וקונטקסט שיחה
הכנה לשימוש ב-OpenAI API וניהול תפקידי השיחה (System, User, Assistant).
-
פונקציות
get_llmו-reinit_conversation
- קראו היטב את שתי הפונקציות הבאות, והוסיפו אותן לסוף הקובץ:
OpenAILocal Modelsdef get_llm(): """Returns the OpenAI client, the model name, and context window size.""" # we'll use model gpt-4o return openai.OpenAI(api_key=OPENAI_API_KEY), "gpt-4o", 128*1024 def reinit_conversation(): """Resets the conversation history and adds the System message.""" global conversation conversation = [] # the system Prompt - the "personality" of the agent, role and instruction system_message = "You are a helpful assistant that is an expert at extracting the most useful information from a given text." conversation.append({"role": "system", "content": system_message}) print(Fore.CYAN + "Conversation history reset. System prompt applied.")chat_model = None chat_tokenizer = None device = torch.device("cpu") def get_llm(): """ Loads and returns the local chat model and tokenizer. If they are already loaded, returns them directly. Otherwise, initializes both from the specified model path. """ global chat_model, chat_tokenizer, device # 1. Return cached model and tokenizer if they are already loaded if chat_model is not None and chat_tokenizer is not None: return chat_model, chat_tokenizer # 2. Load tokenizer from local model directory print("Loading model...") chat_tokenizer = AutoTokenizer.from_pretrained( CHAT_MODEL_PATH, local_files_only=True # load from disk, no internet access ) # 3. Load model weights from the same path (inference mode) chat_model = AutoModelForCausalLM.from_pretrained( CHAT_MODEL_PATH, torch_dtype=torch.float32, # use standard precision device_map=None, # run on CPU local_files_only=True # disable online downloads ) # 4. Set the model to evaluation mode (no gradient tracking) chat_model.eval() print("Model loaded successfully.\n") # 5. Return the ready-to-use model and tokenizer return chat_model, chat_tokenizer def reinit_conversation(): """Resets the conversation history and adds the System message.""" global conversation conversation = [] # the system Prompt - the "personality" of the agent, role and instruction system_message = "You are a helpful assistant that is an expert at extracting the most useful information from a given text." conversation.append({"role": "system", "content": system_message}) print(Fore.CYAN + "Conversation history reset. System prompt applied.") - הסבר: הפונקציות האלה מכינות את המסגרת לשיחה:
get_llmמחזירה את הקליינט של OpenAI, ו-reinit_conversationמנקה את היסטוריית השיחה (בדיוק כמו כפתור "New Chat") ומכניסה את ה-System Prompt שנותן למודל את ההנחיות והאישיות שלו.
- קראו היטב את שתי הפונקציות הבאות, והוסיפו אותן לסוף הקובץ:
4. מנוע השליפה (Retrieval)
הבסיס ל-RAG – חישוב וקטור השאלה והשוואתו לכל הווקטורים בבסיס הידע.
-
פונקציית
get_relevant_context
- קראו היטב והוסיפו את פונקציית החיפוש הווקטורי:
OpenAILocal Modelsdef get_relevant_context(user_input, kb_embeddings, kb_content, embedding_model, top_k=3): """ Finds the most relevant chunks from the knowledge base using vector similarity. """ if kb_embeddings.nelement() == 0: # Check if the tensor has any elements return [] # 1. Encode the user input into a vector input_embedding = embedding_model.encode([user_input], convert_to_tensor=True) # 2. Compute Cosine Similarity between the input and all kb embeddings # Cosine Similarity returns similarity ranks between 1 (very similar) to 0 (irrelevant) cos_scores = util.cos_sim(input_embedding, kb_embeddings)[0] # 3. Get the indices of the top-k scores top_k = min(top_k, len(cos_scores)) top_indices = torch.topk(cos_scores, k=top_k)[1].tolist() # 4. Return the corresponding text chunks relevant_context = [kb_content[idx].strip() for idx in top_indices] return relevant_contextdef get_relevant_context(user_input, kb_embeddings, kb_content, embedding_model, top_k=3): """ Finds and returns the most relevant text chunks from the knowledge base using cosine similarity between the user input and precomputed embeddings. """ # 1. Check if the embeddings tensor is empty (no knowledge base loaded) if kb_embeddings.nelement() == 0: return [] # 2. Encode the user input into a numerical vector (embedding) input_embedding = embedding_model.encode([user_input]) # 3. Calculate cosine similarity between the input vector and all stored embeddings # Cosine similarity measures how close two vectors are in direction (1 = identical, 0 = unrelated) cos_scores = util.cos_sim(input_embedding, kb_embeddings)[0] # 4. Extract indices of the top-k most similar embeddings top_indices = torch.topk(cos_scores, k=min(top_k, len(cos_scores)))[1].tolist() # 5. Return the matching text chunks (stripped of extra spaces) return [kb_content[i].strip() for i in top_indices] - הסבר: פונקציה זו היא הלב של ה-RAG, והיא עושה את הפעולות הבאות:
- לוקחת את שאלת המשתמש והופכת אותה לווקטור
- משווה אותה לכל הווקטורים של ה-Chunks (חישוב Cosine Similarity)
- מחזירה את הטקסט של שלושת ה-Chunks (ברירת המחדל) שהיו הכי קרובים לשאלה
- קראו היטב והוסיפו את פונקציית החיפוש הווקטורי:
5. פונקציית ה-Generation והשיחה (Chat Loop)
שילוב הקונטקסט שנשלף לתוך הפרומפט הסופי ושליחתו למודל ה-LLM.
-
פונקציית `llm_chat`
- קראו היטב והוסיפו את הפונקציה המרכזית שמנהלת את השיחה:
OpenAILocal Modelsdef llm_chat(user_input, kb_embeddings, kb_content, embedding_model): """ Manages the RAG process: Retrieves context, builds the prompt, sends to the LLM, and updates conversation history. """ global conversation # 1. Retrieval: Get relevant context relevant_context = get_relevant_context(user_input, kb_embeddings, kb_content, embedding_model) context_str = "" if relevant_context: context_str = "\n\n".join(relevant_context) print(Fore.GREEN + "\n--- 📚 Context Pulled from Documents (RAG) ---") print(context_str) print("------------------------------------------\n") else: print(Fore.RED + "No relevant context found. Answering based on general knowledge or conversation history.") # 2. Prompt Construction: Add context and strict instructions user_input_with_context = user_input if relevant_context: # the relevant context is concatenated to the beginning of the user prompt (ICL) user_input_with_context = "CONTEXT:\n" + context_str + "\n\nUSER QUESTION:\n" + user_input # hard instructions to the model (Guardrails) - this instructs the model to respond ONLY according to the provided context user_input_with_context += """\n\n INSTRUCTIONS:\n 1. Do not use your internal training data to answer.\n 2. If you do not find the answer in the given CONTEXT or in our conversation history then you must answer this exact phrase: 'I do not know' """ conversation.append({"role": "user", "content": user_input_with_context}) # 3. Generation: Send to the LLM brain, chat_model, _ = get_llm() try: response_obj = brain.chat.completions.create( model=chat_model, messages=conversation, timeout=30 # time limit of 30 seconds ) # 4. Process response and update history response = response_obj.choices[0].message.content conversation.append({"role": "assistant", "content": response}) return response except openai.APIError as e: return f"OpenAI API Error: {e}" except Exception as e: return f"An unexpected error occurred: {e}"def llm_chat(user_input): global conversation model, tokenizer = get_llm() relevant_context = get_relevant_context(user_input, kb_embeddings_tensor, kb_content, embedding_model) if relevant_context: context_str = "\n".join(relevant_context) print(Fore.GREEN + "Context Pulled:\n" + context_str[:1000] + "\n") else: context_str = "" print("No relevant context found.") user_input_with_context = ( f"Use only the following context:\n{context_str}\n\n" f"Question: {user_input}\n" f"Answer only based on the context. " f"If no relevant info, say exactly: I do not know." ) conversation.append({"role": "user", "content": user_input_with_context}) prompt = build_prompt(conversation) inputs = tokenizer(prompt, return_tensors="pt").to(device) with torch.no_grad(): outputs = model.generate( **inputs, max_new_tokens=250, temperature=0.6, do_sample=True, pad_token_id=tokenizer.eos_token_id, eos_token_id=tokenizer.eos_token_id ) text = tokenizer.decode(outputs[0], skip_special_tokens=True) answer = text.split("[Assistant]")[-1].strip() conversation.append({"role": "assistant", "content": answer}) return answer - הסבר: פונקציה זו מארגנת את כל התהליך: היא משתמשת ב-get_relevant_context לשליפה, בונה את ה-Prompt המועשר (כולל ה-Guardrails שמורים למודל לענות רק על סמך המידע שקיבל), שולחת ל-OpenAI, ושומרת את התשובה בהיסטוריית השיחה.
- קראו היטב והוסיפו את הפונקציה המרכזית שמנהלת את השיחה:
-
לולאת השיחה והרצה ראשית
- קראו היטב והוסיפו את הפונקציה המנהלת את לולאת הקלט/פלט ואת בלוק ההרצה הראשי (שימו לב שנו את נתיב קובץ ה PDF לטעינה בהתאם):
OpenAILocalModelsdef startChat(): """Main chat loop for user interaction.""" reinit_conversation() print(Fore.MAGENTA + "Welcome to the DIY RAG Agent chat!") print(Fore.MAGENTA + "Type '/reset' to clear history, '/exit' to quit.") while True: try: user_input = input(Fore.BLUE + "\n>>> Ask a question about the document: " + Style.RESET_ALL) except EOFError: print("\nExiting chat...") break if not user_input.strip(): continue # Hard slash commands for resetting the conversation if user_input.lower() in ["/reset", "/init", "/restart"]: print(Fore.YELLOW + "Reseting conversation...") reinit_conversation() continue # Hard slash commands for exiting if user_input.lower() in ["/bye", "/exit", "/end"]: print(Fore.MAGENTA + "Exiting the chat. Goodbye!") break # Call the RAG engine response = llm_chat(user_input, kb_embeddings_tensor, kb_content, embedding_model) print(Fore.CYAN + "\n<<< RAG Agent Response:") print(response) print("-" * 50) # --- Main Execution Block --- if __name__ == "__main__": # 1. Load knowledge base if it doesn't exist if not os.path.exists("knowledge_base.txt"): print(Fore.RED + "knowledge_base.txt not found. Attempting to parse default PDF...") # assuming the "Lion King Script.pdf" file is in the assets folder file_path = "./assets/Lion King Script.pdf" if os.path.exists(file_path): add_pdf(file_path) else: print(Fore.RED + f"ERROR: PDF file not found at {file_path}. Please place a PDF there or create 'knowledge_base.txt' manually.") exit() # 2. Create Embeddings create_embedding() # 3. Start the chat loop if kb_embeddings_tensor is not None and kb_embeddings_tensor.nelement() > 0: startChat() else: print(Fore.RED + "Could not start chat: Embeddings failed to load.")# ========== Chat Loop ========== def startChat(): """ Main chat loop that handles user interaction with the RAG system. It waits for user input, processes commands, and returns responses from the LLM. """ # 1. Initialize or reset the conversation at the start reinit_conversation() # 2. Continuous loop for user questions while True: user_input = input("Ask a question about my knowledge: ") # 3. Command: reset or restart conversation if user_input.lower() in ["/reset", "/init", "/restart"]: print("Resetting conversation...") reinit_conversation() continue # 4. Command: exit the chat if user_input.lower() in ["/bye", "/exit", "/end"]: print("Exiting the chat. Goodbye!") break # 5. Generate a response using the LLM with context retrieval response = llm_chat(user_input) # 6. Display the model's response clearly in the console print("llm Response:\n\n" + response + "\n") # ========== Main ========== if __name__ == "__main__": """ Main entry point for running the RAG application. Ensures that a knowledge base exists, creates embeddings, and starts the chat. """ # 1. Load or create the knowledge base if not os.path.exists("knowledge_base.txt"): file_path = "./assets/Lion King Script.pdf" add_pdf(file_path) # Parse and append PDF content to knowledge base # 2. Generate embeddings from the knowledge base create_embedding() # 3. Launch the interactive chat loop startChat() - הרצה: כעת הקובץ מוכן להרצה! ודאו שהסביבה הווירטואלית פעילה, וכתבו בטרמינל:
python rag_agent.py - שימו לב: אם השתמשתם במודל שיחה לוקאלי - זהו מודל גדול משמעותית ממודל ה Embedding, ובשימוש הראשון בו בהרצה הנוכחית - לוקח לו זמן להטען לזיכרון ולהיות זמין ל inference. העזרו בסבלנות.
- קראו היטב והוסיפו את הפונקציה המנהלת את לולאת הקלט/פלט ואת בלוק ההרצה הראשי (שימו לב שנו את נתיב קובץ ה PDF לטעינה בהתאם):
לאחר הרצת סוכן ה-RAG, אתם צפויים לראות בטרמינל שלושה סוגי פלט מרכזיים המדגימים את תהליך ה-RAG במלואו:
- שלב האתחול: בתחילה תראו הודעות המאשרות את טעינת בסיס הידע, הורדת מודל ה-Embedding (אם לא עבדתם עם מודל לוקאלי) ויצירת הווקטורים.
- שליפת הקונטקסט (Retrieval): בכל שאלה שתשאלו, תופיע הדפסה ירוקה גדולה תחת הכותרת
--- Context Pulled from Documents (RAG) ---. זוהי ההוכחה שהסוכן חישב את הדמיון הווקטורי, שלף את ה-Chunks הרלוונטיים ביותר מה-PDF, וצירף אותם ל-Prompt. - תשובת המודל (Generation): לאחר מכן תופיע תגובת ה-LLM תחת <<< RAG Agent Response. התשובה הזו תהיה מבוססת באופן בלעדי על הקונטקסט הירוק שסופק לו, וזהו הדבר החשוב ביותר שלמדנו כאן: אנו שולטים במקור המידע של המודל.
למדנו לבנות ארכיטקטורת AI מודרנית המשלבת עיבוד שפה טבעית (NLP) עם יכולות מתקדמות של LLMs, ובכך הפכנו את המודל ל"מומחה" במידע הספציפי שהענקנו לו.