Willkommen zur Advanced RAG-Reihe: Erstellen eines Chats mit Ihrem Dokumentensystem
In diesem ersten Video unserer neuen Serie zu Advanced RAG (Retrieval Augmented Generation) erkunden wir die Architektur eines einfachen Chats mit Ihrem Dokumentensystem oder Ihrer RAG-Pipeline. Wir werden über die Grundlagen hinausgehen und fortgeschrittenere Techniken zur Verbesserung der Pipeline besprechen.
Die Grundlagen einer RAG-Pipeline
Beginnen wir mit den Grundlagen einer RAG-Pipeline. Die Architektur besteht aus folgenden Komponenten:
- Document Loader: Diese Komponente lädt die Dokumente, z. B. PDF-Dateien, die im Chat-System verwendet werden.
- Chunking: Die Dokumente werden in kleinere Blöcke aufgeteilt, um sie an das Kontextfenster des Sprachmodells (LLM) anzupassen.
- Einbettungen: Für jeden Block werden Einbettungen berechnet, die dann in einem Vektorspeicher gespeichert werden, um einen semantischen Index zu erstellen.
- Abruf: Wenn ein Benutzer eine Frage stellt, berechnet das System Einbettungen für die Abfrage und führt eine semantische Suche in der Wissensdatenbank (Vektorspeicher) durch, um relevante Dokumente oder Blöcke abzurufen.
- Neuordnung: Die abgerufenen Dokumente oder Blöcke werden basierend auf ihrer Relevanz neu eingestuft.
- Generierung: Die Frage und der Kontext (neu eingestufte Dokumente oder Blöcke) werden in das LLM eingespeist, um Antworten zu generieren.
Dies ist ein grundlegender Überblick über die Funktionsweise einer RAG-Pipeline. Wenn Sie ein absoluter Anfänger sind, machen Sie sich keine Sorgen! Wir haben eine Reihe von Videos zum Erstellen von RAG-Pipelines, die Sie sich ansehen können.
Einführung der Hybridsuche
In dieser neuen Serie konzentrieren wir uns auf die Verbesserung der grundlegenden RAG-Pipeline. Das erste Thema, das wir untersuchen werden, ist die Hybridsuche.
Bei der Hybridsuche werden der RAG-Pipeline zwei Komponenten hinzugefügt:
- Schlüsselwortbasierte Suche: Zusätzlich zur semantischen Suche mithilfe von Einbettungen führen wir auch eine herkömmliche schlüsselwortbasierte Suche in den verfügbaren Blöcken durch.
- Ensemble Retriever: Anstatt nur den einbettungsbasierten Retriever zu verwenden, kombinieren wir die Ergebnisse sowohl der schlüsselwortbasierten Suche als auch des einbettungsbasierten Retrievers. Dieser Ensemble-Retriever ermöglicht es uns, jeder Suchmethode unterschiedliche Gewichtungen zuzuweisen, was sie leistungsfähiger macht.
Nachdem wir nun einen Überblick über die Architektur und die Hinzufügung der Hybridsuche erhalten haben, werfen wir einen Blick auf ein Codebeispiel.
Codebeispiel
Bevor wir uns mit dem Code befassen, stellen Sie sicher, dass Sie die erforderlichen Pakete installiert haben. Wir werden verwenden rank_bm25
für Hybridsuche, unstrukturiertesIO
zum Lesen von PDF-Dateien und chromaDB
zum Erstellen des Vektorspeichers. Wenn Sie mit gescannten Dokumenten arbeiten, werden zusätzliche Pakete für die Interaktion mit gescannten Dokumenten und die Durchführung der optischen Zeichenerkennung (OCR) empfohlen.
Sobald die Pakete installiert sind, können wir sie in unseren Code laden. Hier ist ein Beispiel:
import rank_bm25 import unstructuredIO import chromaDB from lchaintools import ChatPromptTemplate, OutputParser, RunnablePassThrough from lchaintools import EmbeddingModelAPI, LLMModelAPI
In diesem Beispiel verwenden wir die neueste Version von LChain. Wir importieren die notwendigen Pakete und Module für unsere RAG-Pipeline, einschließlich der Chat-Eingabeaufforderungsvorlage, des Ausgabeparsers, des ausführbaren Pass-Through, der Einbettungsmodell-API und der LLM-Modell-API.
Als nächstes müssen wir die PDF-Datei laden und in Blöcke konvertieren. Hier ist ein Beispiel:
pdf_loader = unstructuredIO.PDFLoader() docs = pdf_loader.load_file('data/example.pdf') chunk_size = 800 Overlap = 100 splitter = unstructuredIO.RecursiveCharTextSplitter(chunk_size, Overlap) chunks = splitter.process(docs)
In diesem Codeausschnitt verwenden wir den PDF-Loader, um die PDF-Datei zu laden. Anschließend definieren wir die Blockgröße und Überlappung für die Aufteilung der Dokumente in Blöcke. Zur Erstellung der Blöcke wird der rekursive Zeichentext-Splitter verwendet.
Kommen wir nun zum Erstellen der Einbettungen und des Vektorspeichers:
embedding_model = EmbeddingModelAPI('hugging_face_token') vector_store = chromaDB.VectorStore(embedding_model) vector_store.create_vector_store(chunks)
In diesem Beispiel erstellen wir ein Einbettungsmodell mithilfe der Hugging Face API. Anschließend verwenden wir das Einbettungsmodell und die Chunks, um den Vektorspeicher zu erstellen.
Als Nächstes richten wir die Retriever sowohl für die einbettungsbasierte Suche als auch für die schlüsselwortbasierte Suche ein:
embedding_retriever = vector_store.create_retriever(num_chunks=3) keyword_retriever = rank_bm25.BM25Retriever(chunks, num_chunks=3) ensemble_retriever = rank_bm25.EnsembleRetriever([embedding_retriever, keyword_retriever], [0.7, 0.3])
In diesem Codeausschnitt erstellen wir die Retriever sowohl für die einbettungsbasierte Suche als auch für die schlüsselwortbasierte Suche. Der Ensemble-Retriever kombiniert die Ergebnisse beider Retriever, wobei jedem unterschiedliche Gewichte zugewiesen werden.
Schließlich richten wir das LLM-Modell und die Eingabeaufforderungsvorlage ein:
llm_model = LLMModelAPI('hugging_face_token') prompt_template = ChatPromptTemplate( system_prompt="Sie sind ein hilfreicher KI-Assistent, der Anweisungen sehr gut befolgt. Verwenden Sie den folgenden Kontext, um die Frage des Benutzers zu beantworten:", user_prompt="Was ist Anweisungsoptimierung?", Assistant_prompt ="", ) Output_parser = OutputParser() chat_template = llm_model.create_chat_template( prompt_template, Output_parser, Retriever=ensemble_retriever, )
In diesem Codeausschnitt erstellen wir das LLM-Modell mithilfe der Hugging Face API. Anschließend richten wir die Aufforderungsvorlage für den Chat ein, einschließlich der Systemaufforderung, der Benutzeraufforderung und der Assistentenaufforderung. Der Ausgabeparser wird zum Parsen der Antwort des Modells verwendet.
Nachdem alles eingerichtet ist, können wir jetzt den Chat starten:
user_input = „Was ist Befehlsoptimierung?“ Antwort = chat_template.invoke(user_input)
In diesem Beispiel stellen wir die Eingabe des Benutzers bereit und rufen die auf aufrufen
Funktion in der Chat-Vorlage, um die Antwort des Modells zu erhalten.
Abschluss
In diesem Video haben wir die Architektur einer grundlegenden RAG-Pipeline untersucht und das Konzept der Hybridsuche vorgestellt. Wir haben auch ein Codebeispiel zur Implementierung der Hybridsuche mithilfe der LChain-Bibliothek bereitgestellt. Durch die Kombination der schlüsselwortbasierten Suche und der einbettungsbasierten Suche können wir die Leistung des Chat-Systems verbessern und genauere Antworten liefern.
Wenn Sie dieses Video nützlich fanden, abonnieren Sie unbedingt unseren Kanal für weitere Videos dieser Serie. Wenn Sie Unterstützung bei Ihren eigenen Projekten benötigen, bieten wir Beratungsleistungen an. Weitere Informationen finden Sie unter den Links in der Beschreibung.
Vielen Dank fürs Zuschauen und bis zum nächsten Video!