Direkt zum Inhalt

Agentische RAG: Schritt-für-Schritt-Anleitung mit Demo-Projekt

Lerne, wie du eine Agentic RAG-Pipeline von Grund auf aufbaust, die lokale Datenquellen und Web Scraping integriert, um kontextbezogene Antworten auf Benutzeranfragen zu generieren.
Aktualisierte 27. Feb. 2025  · 12 Min. Lesezeit

Wie oft wünschst du dir, dass deine KI mehr kann, als nur zu wiederholen, was sie schon weiß? Als jemand, der unzählige Stunden damit verbracht hat, KI-Systeme zu verfeinern und zu optimieren, kann ich dir sagen, dass herkömmliche Modelle zwar beeindruckend sind, sich aber oft so anfühlen, als ob sie in einer Blase festsäßen, die auf das beschränkt ist, worauf sie trainiert wurden. Hier kommt die Agentic RAG ins Spiel.

In der agentenbasierten RAG werden die Entscheidungsfähigkeiten der agentenbasierten KI auf die Anpassungsfähigkeit der Retrieval-augmented Generation (RAG). Zusammen bilden sie ein System, das unabhängig voneinander auf relevante Informationen zugreifen, diese verarbeiten und generieren kann.

Ich habe bereits einen Artikel geschrieben über agentische RAG geschrieben, der dir helfen wird, alles von einem theoretischen Standpunkt aus zu verstehen. In diesem Artikel geht es mehr um die praktische Umsetzung, also konzentrieren wir uns darauf.

Agentic RAG Projektübersicht

Lass mich dir Schritt für Schritt erklären, was wir bauen. Es geht darum, eine RAG-Pipeline zu erstellen, die auf der hier gezeigten Architektur basiert:

agentic rag demo projektübersicht

Schritt 1: Benutzerabfrage

Ob es sich um eine einfache Anfrage oder ein komplexes Problem handelt, alles beginnt mit einer Frage des Nutzers. Das ist der Funke, der unsere Pipeline in Bewegung setzt.

Schritt 2: Weiterleitung der Abfrage

Als nächstes prüft das System: Darf ich darauf antworten?

Ja? Es greift auf vorhandenes Wissen zurück und liefert die Antwort sofort.

Nein? Zeit, tiefer zu graben! Die Anfrage wird an den nächsten Schritt weitergeleitet.

Schritt 3: Abrufen der Daten

Wenn die Antwort nicht sofort verfügbar ist, taucht die Pipeline in zwei mögliche Quellen ein:

  1. Lokale Dokumente: Wir verwenden ein vorverarbeitetes PDF als Wissensbasis, in der das System nach relevanten Informationsbrocken sucht.
  2. Suche im Internet: Wenn mehr Kontext benötigt wird, kann die Pipeline auf externe Quellen zugreifen, um aktuelle Informationen abzurufen.

Schritt 4: Den Kontext aufbauen

Die abgerufenen Daten, egal ob aus dem PDF oder dem Web, werden dann zu einem kohärenten, abgerufenen Kontext zusammengestellt. Stell dir vor, du sammelst alle Puzzleteile, bevor du sie zusammensetzt.

Schritt 5: Generierung der endgültigen Antwort

Schließlich wird dieser Kontext an ein großes Sprachmodell (LLM) weitergegeben, um eine klare und genaue Antwort zu erstellen. Es geht nicht nur darum, Daten abzurufen, sondern auch darum, sie zu verstehen und bestmöglich zu präsentieren.

Am Ende werden wir eine intelligente, effiziente RAG-Pipeline haben, die dynamisch auf Abfragen mit realem Kontext reagieren kann.

Lokale Datenquelle

Zu Beginn werde ich ein reales Dokument als lokale Datenquelle verwenden. Das Dokument, mit dem wir arbeiten werden, ist kein anderes als Generative KI-Prinzipien. Sie ist vollgepackt mit wertvollen Erkenntnissen und damit der perfekte Testfall für unsere Pipeline. Du bräuchtest auch eine Zusammenfassung der Datei, die ich für die Weiterleitung verwende. Du kannst die Übersichtsdatei abrufen hier.

Hier findest du alles, was du brauchst, um loszulegen, Schritt für Schritt.

Voraussetzungen

Bevor wir loslegen, musst du ein paar Dinge vorbereiten:

  1. Groq API Schlüssel: Du brauchst einen API-Schlüssel von Groq, den du hier abrufen kannst: Groq API-Konsole
  2. Gemini API Schlüssel: Gemini hilft dir bei der Orchestrierung mit Agenten, Groq gibt superschnelle Antworten, aber es kann sein, dass du mit den aktuellen Ratenlimits nicht weiterkommst: Gemini API Konsole
  3. Serper.dev API key: Für alle Internet-Suchfunktionen verwenden wir Serper.dev. Hol dir deinen API-Schlüssel hier: Serper.dev API Key

Pakete installieren

Lass uns sicherstellen, dass wir die richtigen Werkzeuge installiert haben. Öffne dein Terminal und führe die folgenden Befehle aus, um die notwendigen Python-Pakete zu installieren:

pip install langchain-groq faiss-cpu crewai serper pypdf2 python-dotenv setuptools sentence-transformers huggingface distutils`

Einrichten der Umgebung

Sobald du die Schlüssel und Pakete bereit hast, kannst du loslegen! Ich empfehle, deine API-Schlüssel in einer.env Datei oder sicher in deiner Codebase zu speichern. Hier ist ein Beispiel dafür, wie deine .env Datei aussehen könnte:

import os from dotenv 
import load_dotenv from langchain.vectorstores 
import FAISS from langchain.document_loaders 
import PyPDFLoader 
from langchain.text_splitter import RecursiveCharacterTextSplitter 
from langchain_huggingface.embeddings import HuggingFaceEmbeddings 
from langchain_groq import ChatGroq 
from crewai_tools import SerperDevTool 
from crewai import Agent, Task, Crew, LLM

load_dotenv() 
GROQ_API_KEY = os.getenv("GROQ_API_KEY") 
SERPER_API_KEY = os.getenv("SERPER_API_KEY")
GEMINI=os.getenv("GEMINI")

Ich habe Umgebungsvariablen geladen, damit ich API-Schlüssel und sensible Daten sicher verwalten kann, ohne sie fest zu codieren. So bleibt das Skript sicher und ich kann die Schlüssel bei Bedarf an einer Stelle ändern (.env Datei).

Kurz gesagt, was diese importierten Pakete und Funktionen tun werden:

  • os: Bietet Dienstprogramme für die Schnittstelle zum Betriebssystem.
  • dotenv: Lädt Umgebungsvariablen aus .env Dateien.
  • FAISS: Vektorspeicher für Ähnlichkeitssuche und Retrieval.
  • PyPDFLoader: Extrahiert Textinhalte aus PDF-Dokumenten.
  • RecursiveCharacterTextSplitter: Teilt den Text rekursiv in überschaubare Abschnitte auf.
  • HuggingFaceEmbeddings: Erzeugt Texteinbettungen mit HuggingFace-Modellen.
  • ChatGroq: Chat-Interface mit Hardware-Beschleunigung von Groq.
  • SerperDevTool: Tool zur Durchführung von Websuchen.
  • ScrapeWebsiteTool: Extrahiert Daten aus Webseiten.
  • Agent: Definiert eine KI-Entität mit Rollen und Zielen.
  • Aufgabe: Stellt ein bestimmtes Ziel oder eine bestimmte Handlung für einen Agenten dar.
  • Mannschaft: Orchestriert Agenten und Aufgaben für koordinierte Arbeitsabläufe.
  • LLM: Große Sprachmodellschnittstelle für die Erstellung von Textantworten.

Initialisierung der LLMs

Wir beginnen mit der Initialisierung von zwei Sprachmodellen:

  • llm: Für allgemeine Aufgaben wie Routing und das Erstellen von Antworten. Wir verwenden das Modell llama-3.3-70b-specdec.
  • crew_llm: Speziell für den Web-Scraping-Agenten, da er eine etwas andere Konfiguration benötigt (wie die Temperatur für kreativere Ausgaben). Wir verwenden das Modell gemini/gemini-1.5-flash.
# Initialize LLM
llm = ChatGroq(
    model="llama-3.3-70b-specdec",
    temperature=0,
    max_tokens=500,
    timeout=None,
    max_retries=2,
)

crew_llm = LLM(
    model="gemini/gemini-1.5-flash",
    api_key=GEMINI,
    max_tokens=500,
    temperature=0.7
)

Hinzufügen des Entscheidungsträgers

Diese check_local_knowledge() Funktion unten fungiert als Entscheidungsträger. Ich habe eine Eingabeaufforderung erstellt, in der ich die Benutzerabfrage und einen lokalen Kontext (aus der PDF-Datei) übergeben habe. Das Modell antwortet entweder mit "Ja" oder "Nein" und sagt mir damit, ob es lokal genug Informationen hat, um die Anfrage zu beantworten. Wenn nicht, werden wir auf Web Scraping zurückgreifen.

def check_local_knowledge(query, context):
    """Router function to determine if we can answer from local knowledge"""
    prompt = '''Role: Question-Answering Assistant
Task: Determine whether the system can answer the user's question based on the provided text.
Instructions:
    - Analyze the text and identify if it contains the necessary information to answer the user's question.
    - Provide a clear and concise response indicating whether the system can answer the question or not.
    - Your response should include only a single word. Nothing else, no other text, information, header/footer. 
Output Format:
    - Answer: Yes/No
Study the below examples and based on that, respond to the last question. 
Examples:
    Input: 
        Text: The capital of France is Paris.
        User Question: What is the capital of France?
    Expected Output:
        Answer: Yes
    Input: 
        Text: The population of the United States is over 330 million.
        User Question: What is the population of China?
    Expected Output:
        Answer: No
    Input:
        User Question: {query}
        Text: {text}
'''
    formatted_prompt = prompt.format(text=context, query=query)
    response = llm.invoke(formatted_prompt)
    return response.content.strip().lower() == "yes"

Web Searching und Scraping Agent

Als Nächstes richten wir einen Web-Such- und Scraping-Agenten ein, der die crewai Bibliothek. Dieser Agent verwendet ein Suchwerkzeug (SerperDevTool), um Artikel zu finden, die mit der Anfrage des Nutzers übereinstimmen. Die Aufgabenbeschreibung stellt sicher, dass der Agent weiß, was er abrufen soll, und fasst die relevanten Webinhalte zusammen. Das ist so, als würdest du einen spezialisierten Worker losschicken, um Daten aus dem Internet zu holen.

Dann führt die Funktion get_web_content() den Web Scraping Agent aus. Er sendet die Suchanfrage als Eingabe und erhält eine kurze Zusammenfassung der wichtigsten Artikel. Er gibt das Rohergebnis zurück, das zu unserem Kontext wird, wenn der Router entscheidet, dass wir nicht genug lokale Informationen haben.

def setup_web_scraping_agent():
    """Setup the web scraping agent and related components"""
    search_tool = SerperDevTool()  # Tool for performing web searches
    scrape_website = ScrapeWebsiteTool()  # Tool for extracting data from websites
    
    # Define the web search agent
    web_search_agent = Agent(
        role="Expert Web Search Agent",
        goal="Identify and retrieve relevant web data for user queries",
        backstory="An expert in identifying valuable web sources for the user's needs",
        allow_delegation=False,
        verbose=True,
        llm=crew_llm
    )
    
    # Define the web scraping agent
    web_scraper_agent = Agent(
        role="Expert Web Scraper Agent",
        goal="Extract and analyze content from specific web pages identified by the search agent",
        backstory="A highly skilled web scraper, capable of analyzing and summarizing website content accurately",
        allow_delegation=False,
        verbose=True,
        llm=crew_llm
    )
    
    # Define the web search task
    search_task = Task(
        description=(
            "Identify the most relevant web page or article for the topic: '{topic}'. "
            "Use all available tools to search for and provide a link to a web page "
            "that contains valuable information about the topic. Keep your response concise."
        ),
        expected_output=(
            "A concise summary of the most relevant web page or article for '{topic}', "
            "including the link to the source and key points from the content."
        ),
        tools=[search_tool],
        agent=web_search_agent,
    )
    
    # Define the web scraping task
    scraping_task = Task(
        description=(
            "Extract and analyze data from the given web page or website. Focus on the key sections "
            "that provide insights into the topic: '{topic}'. Use all available tools to retrieve the content, "
            "and summarize the key findings in a concise manner."
        ),
        expected_output=(
            "A detailed summary of the content from the given web page or website, highlighting the key insights "
            "and explaining their relevance to the topic: '{topic}'. Ensure clarity and conciseness."
        ),
        tools=[scrape_website],
        agent=web_scraper_agent,
    )
    
    # Define the crew to manage agents and tasks
    crew = Crew(
        agents=[web_search_agent, web_scraper_agent],
        tasks=[search_task, scraping_task],
        verbose=1,
        memory=False,
    )
    return crew

def get_web_content(query):
    """Get content from web scraping"""
    crew = setup_web_scraping_agent()
    result = crew.kickoff(inputs={"topic": query})
    return result.raw

Erstellen der Vektordatenbank

Die Funktion setup_vector_db() baut die Vektordatenbank aus einer PDF-Datei auf. Hier ist, wie ich es Schritt für Schritt gemacht habe:

  1. Lade die PDF-Datei: Ich habe PyPDFLoader verwendet, um den Inhalt zu extrahieren.
  2. Verteile den Text: Ich habe den PDF-Inhalt mit RecursiveCharacterTextSplitter in kleinere Abschnitte (1000 Zeichen mit 50 Zeichen Überlappung) aufgeteilt. Das macht die Daten überschaubar und durchsuchbar.
  3. Vector DB erstellen: Ich habe die Chunks mithilfe eines Satzumwandlungsmodells eingebettet und sie in einer FAISS Vektor-Datenbank gespeichert. So kann ich effizient nach relevanten Texten suchen.

Danach fragt die Funktion get_local_content() die Vektordatenbank nach den 5 relevantesten Chunks ab, die mit der Anfrage des Nutzers zusammenhängen. Sie kombiniert diese Chunks zu einem einzigen String mit Kontext. 

def setup_vector_db(pdf_path):
    """Setup vector database from PDF"""
    # Load and chunk PDF
    loader = PyPDFLoader(pdf_path)
    documents = loader.load()
    
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000,
        chunk_overlap=50
    )
    chunks = text_splitter.split_documents(documents)
    
    # Create vector database
    embeddings = HuggingFaceEmbeddings(
        model_name="sentence-transformers/all-mpnet-base-v2"
    )
    vector_db = FAISS.from_documents(chunks, embeddings)
    
    return vector_db

def get_local_content(vector_db, query):
    """Get content from vector database"""
    docs = vector_db.similarity_search(query, k=5)
    return " ".join([doc.page_content for doc in docs])

Generierung der endgültigen Antwort

Sobald ich den Kontext habe (entweder aus lokalen Dokumenten oder aus Web Scraping), übergebe ich ihn zusammen mit der Anfrage des Nutzers an das Sprachmodell. Das LLM generiert die endgültige Antwort, indem es sowohl den Kontext als auch die Anfrage in einem Gesprächsformat kombiniert.

Hier ist der Ablauf der Hauptabfrageverarbeitung:

  1. Routing: Ich verwende check_local_knowledge(), um zu entscheiden, ob der lokale PDF-Inhalt genug Daten enthält, um die Abfrage zu beantworten.
    • Wenn "Ja"hole ich die relevanten Chunks aus der Vektordatenbank.
    • Wenn "Nein"durchforste ich das Internet nach relevanten Artikeln.
  2. Endgültige Antwort: Sobald ich den Kontext habe, übergebe ich ihn an den LLM, um die endgültige Antwort zu erzeugen.
def generate_final_answer(context, query):
    """Generate final answer using LLM"""
    messages = [
        (
            "system",
            "You are a helpful assistant. Use the provided context to answer the query accurately.",
        ),
        ("system", f"Context: {context}"),
        ("human", query),
    ]
    response = llm.invoke(messages)
    return response.content

def process_query(query, vector_db, local_context):
    """Main function to process user query"""
    print(f"Processing query: {query}")
    
    # Step 1: Check if we can answer from local knowledge
    can_answer_locally = check_local_knowledge(query, local_context)
    print(f"Can answer locally: {can_answer_locally}")
    
    # Step 2: Get context either from local DB or web
    if can_answer_locally:
        context = get_local_content(vector_db, query)
        print("Retrieved context from local documents")
    else:
        context = get_web_content(query)
        print("Retrieved context from web scraping")
    
    # Step 3: Generate final answer
    answer = generate_final_answer(context, query)
    return answer

Zum Schluss verbinden wir alles mit der Funktion main():

def main():
    # Setup
    pdf_path = "genai-principles.pdf" 
    
    # Initialize vector database
    print("Setting up vector database...")
    vector_db = setup_vector_db(pdf_path)
    
    # Get initial context from PDF for routing
    local_context = get_local_content(vector_db, "")
    
    # Example usage
    query = "What is Agentic RAG?"
    result = process_query(query, vector_db, local_context)
    print("\nFinal Answer:")
    print(result)
if __name__ == "__main__":
    main()

Oben: Wir:

  1. Richte die Vektordatenbank ein: Lade und verarbeite die PDF-Datei.
  2. Initialisiert den lokalen Kontext: Wir haben einige allgemeine Inhalte aus der PDF-Datei geholt, um sie als Kontext an den Router zu übergeben.
  3. Habe eine Beispielabfrage durchgeführt: Wir haben eine Beispielabfrage ("What is Agentic RAG?" ) ausgeführt und die endgültige Antwort ausgedruckt.

Dies ist die Ausgabe des Programms:

Agentic RAG is a technique for building Large Language Model (LLM) powered applications that incorporates AI agents. It is an extension of the traditional Retrieval-Augmented Generation (RAG) approach, which uses an external knowledge source to provide the LLM with relevant context and reduce hallucinations.
In traditional RAG pipelines, the retrieval component is typically composed of an embedding model and a vector database, and the generative component is an LLM. At inference time, the user query is used to run a similarity search over the indexed documents to retrieve the most similar documents to the query and provide the LLM with additional context.
Agentic RAG, on the other hand, introduces AI agents that are designed to interact with the user query and provide additional context to the LLM. These agents can be thought of as "virtual assistants" that help the LLM to better understand the user's intent and retrieve relevant documents.

The key components of Agentic RAG include:
1. AI agents: These are the virtual assistants that interact with the user query and provide additional context to the LLM.
2. Retrieval component: This is the component that retrieves the most similar documents to the user query.
3. Generative component: This is the component that uses the retrieved documents to generate the final output.

Agentic RAG has several benefits, including:
1. Improved accuracy: By providing additional context to the LLM, Agentic RAG can improve the accuracy of the generated output.
2. Enhanced user experience: Agentic RAG can help to reduce the complexity of the user interface and provide a more natural and intuitive experience.
3. Increased flexibility: Agentic RAG can be easily extended to support new use cases and applications.

However, Agentic RAG also has some limitations, including:
1. Increased complexity: Agentic RAG requires additional components and infrastructure, which can increase the complexity of the system.
2. Higher computational requirements: Agentic RAG requires more computational resources to handle the additional complexity of the AI agents and the retrieval component.
3. Training requirements: Agentic RAG requires more data and training to learn the behaviour of the AI agents and the retrieval component.

Ausgabe Erläuterung

Als ich die Frage "Was ist Agentic RAG?" stellte , die in dem bereitgestellten Dokument nicht explizit zu finden war, zeigte das System seine Flexibilität und Intelligenz. Die CrewAI-Agenten leiteten die Anfrage korrekt weiter, indem sie das Verständnis des Routers nutzten, dass ein externer Kontext notwendig war. Die Agenten arbeiteten zusammen, um den wichtigsten Artikel aus dem Internet zu finden, seinen Inhalt zu analysieren und eine fundierte Antwort zu geben.

Das System bot eine klare Erklärung der agentenbasierten RAG, ihrer Komponenten (KI-Agenten, Retrieval und generative Elemente), ihrer Vorteile (Genauigkeit, Benutzererfahrung und Flexibilität) und ihrer Grenzen (Komplexität, Rechenaufwand und Trainingsanforderungen).

Dies unterstreicht die Fähigkeit der Pipeline, dynamisch Kontext zu erfassen und präzise, präzise und wertvolle Erkenntnisse zu liefern, selbst wenn die Abfrage über den ursprünglichen Datensatz hinausgeht.

Fazit

Die von uns aufgebaute Pipeline ist ein dynamischer, mehrstufiger Prozess, der Benutzeranfragen effizient bearbeitet, indem er vorhandenes und externes Wissen kombiniert.

Das System kann sich dynamisch an verschiedene Anfragen anpassen und genaue, benutzerfreundliche Antworten geben. Mit der Integration lokaler Daten, Live-Internetsuchen und einer nahtlosen Benutzeroberfläche erweist sich die RAG-Pipeline als robuste und praktische Lösung für reale Anwendungen. Als nächsten Schritt kannst du versuchen, etwas Eigenes zu bauen, indem du den Arbeitsablauf verwendest, den wir besprochen haben.


Bhavishya Pandit's photo
Author
Bhavishya Pandit
LinkedIn
Twitter

Senior GenAI Engineer und Content Creator, der mit seinem Wissen über GenAI und Data Science bereits 20 Millionen Views erreicht hat.

Themen

Lerne KI mit diesen Kursen!

Lernpfad

Developing AI Applications

23hrs hr
Learn to create AI-powered applications with the latest AI developer tools, including the OpenAI API, Hugging Face, and LangChain.
Siehe DetailsRight Arrow
Kurs starten
Mehr anzeigenRight Arrow
Verwandt

Der Blog

Top 30 Generative KI Interview Fragen und Antworten für 2024

Dieser Blog bietet eine umfassende Sammlung von Fragen und Antworten zu generativen KI-Interviews, die von grundlegenden Konzepten bis hin zu fortgeschrittenen Themen reichen.
Hesam Sheikh Hassani's photo

Hesam Sheikh Hassani

15 Min.

Der Blog

Lehrer/innen und Schüler/innen erhalten das Premium DataCamp kostenlos für ihre gesamte akademische Laufbahn

Keine Hacks, keine Tricks. Schüler/innen und Lehrer/innen, lest weiter, um zu erfahren, wie ihr die Datenerziehung, die euch zusteht, kostenlos bekommen könnt.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

4 Min.

Der Blog

Die 20 besten Snowflake-Interview-Fragen für alle Niveaus

Bist du gerade auf der Suche nach einem Job, der Snowflake nutzt? Bereite dich mit diesen 20 besten Snowflake-Interview-Fragen vor, damit du den Job bekommst!
Nisha Arya Ahmed's photo

Nisha Arya Ahmed

20 Min.

Der Blog

Q2 2023 DataCamp Donates Digest

DataCamp Donates hat im zweiten Quartal 2023 über 20.000 Stipendien an unsere gemeinnützigen Partner vergeben. Erfahre, wie fleißige benachteiligte Lernende diese Chancen in lebensverändernde berufliche Erfolge verwandelt haben.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

Der Blog

2022-2023 DataCamp Classrooms Jahresbericht

Zu Beginn des neuen Schuljahres ist DataCamp Classrooms motivierter denn je, das Lernen mit Daten zu demokratisieren. In den letzten 12 Monaten sind über 7.650 neue Klassenzimmer hinzugekommen.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

8 Min.

Mehr anzeigenMehr anzeigen