Heim > Backend-Entwicklung > Python-Tutorial > Der ultimative Leitfaden zur Retrieval-Augmented Generation (RAG)

Der ultimative Leitfaden zur Retrieval-Augmented Generation (RAG)

Barbara Streisand
Freigeben: 2024-12-21 18:55:10
Original
886 Leute haben es durchsucht

Die rasante Entwicklung generativer KI-Modelle wie ChatGPT von OpenAI hat die Verarbeitung natürlicher Sprache revolutioniert und es diesen Systemen ermöglicht, kohärente und kontextrelevante Antworten zu generieren. Doch selbst modernste Modelle stoßen bei der Bewältigung domänenspezifischer Abfragen oder der Bereitstellung hochpräziser Informationen an Grenzen. Dies führt häufig zu Herausforderungen wie Halluzinationen – Fällen, in denen Modelle ungenaue oder erfundene Details wiedergeben.

Retrieval-Augmented Generation (RAG), ein innovatives Framework, das diese Lücke schließen soll. Durch die nahtlose Integration externer Datenquellen ermöglicht RAG generativen Modellen den Abruf von Nischeninformationen in Echtzeit und verbessert so deren Genauigkeit und Zuverlässigkeit erheblich.

In diesem Artikel werden wir in die Mechanik von RAG eintauchen, seine Architektur erforschen und die Grenzen traditioneller generativer Modelle diskutieren, die seine Entstehung inspiriert haben. Wir werden auch praktische Implementierungen, fortgeschrittene Techniken und Bewertungsmethoden hervorheben und zeigen, wie RAG die Art und Weise verändert, wie KI mit speziellen Daten interagiert.

Erste Schritte

Inhaltsverzeichnis

  • Was ist RAG
  • Architektur von RAG
  • RAG-Prozessablauf
  • RAG vs. Feinabstimmung
  • Arten von RAG
  • Anwendungen von RAG
  • Aufbau eines PDF-Chat-Systems mit RAG
  • Ressourcen

Was ist RAG?

Retrieval-Augmented Generation (RAG) ist ein fortschrittliches Framework, das die Fähigkeiten generativer KI-Modelle durch die Integration des Echtzeitabrufs externer Daten erweitert. Generative Modelle zeichnen sich zwar dadurch aus, dass sie kohärenten, menschenähnlichen Text erzeugen, sie können jedoch ins Stocken geraten, wenn sie aufgefordert werden, genaue, aktuelle oder domänenspezifische Informationen bereitzustellen. Hier kommt RAG ins Spiel und stellt sicher, dass die Antworten nicht nur kreativ sind, sondern auch auf zuverlässigen und relevanten Quellen basieren.

RAG verbindet ein generatives Modell mit einem Abrufmechanismus, der typischerweise auf Vektordatenbanken oder Suchsystemen basiert. Wenn eine Anfrage eingeht, durchsucht die Abrufkomponente umfangreiche externe Datensätze, um relevante Informationen abzurufen. Das generative Modell synthetisiert diese Daten dann und erzeugt eine Ausgabe, die sowohl genau als auch kontextbezogen aufschlussreich ist.

Durch die Bewältigung wichtiger Herausforderungen wie Halluzinationen und begrenztes Domänenwissen erschließt RAG das Potenzial generativer Modelle, um in speziellen Bereichen hervorragende Leistungen zu erbringen. Seine Anwendungen erstrecken sich über verschiedene Branchen, von der Automatisierung des Kundensupports mit präzisen Antworten bis hin zur Möglichkeit für Forscher, bei Bedarf auf kuratiertes Wissen zuzugreifen. RAG stellt einen bedeutenden Fortschritt dar, um KI-Systeme in realen Szenarien intelligenter, vertrauenswürdiger und nützlicher zu machen.

Architektur von RAG

Ein klares Verständnis der RAG-Architektur ist unerlässlich, um ihr volles Potenzial und ihre Vorteile auszuschöpfen. Im Kern basiert das Framework auf zwei Hauptkomponenten: dem Retriever und dem Generator, die in einem nahtlosen Fluss der Informationsverarbeitung zusammenarbeiten.

Dieser Gesamtprozess wird unten dargestellt:
The ultimate guide to Retrieval-Augmented Generation (RAG)
Quelle: https://weaviate.io/blog/introduction-to-rag

  • Abruf – Die Inferenzphase in RAG beginnt mit dem Abruf, bei dem für eine Benutzerabfrage relevante Daten von einer externen Wissensquelle abgerufen werden. In einem einfachen RAG-Setup wird üblicherweise die Ähnlichkeitssuche verwendet, bei der die Abfrage und die externen Daten in denselben Vektorraum eingebettet werden, um die ähnlichsten Übereinstimmungen zu identifizieren. Der Retriever spielt eine Schlüsselrolle beim Abrufen von Dokumenten und verwendet Methoden wie Sparse Retrieval und Dense Retrieval. Sparse Retrieval, das Techniken wie TF-IDF oder BM25 verwendet, basiert auf exakten Wortübereinstimmungen, hat jedoch Schwierigkeiten mit Synonymen und Paraphrasierungen, während Dense Retrieval Transformatormodelle wie BERT oder RoBERTa nutzt, um semantische Vektordarstellungen zu erstellen, was genauere und differenziertere Übereinstimmungen ermöglicht.
  • Erweiterung – Nach dem Abrufen der relevantesten Datenpunkte aus der externen Quelle integriert der Erweiterungsprozess diese Informationen, indem er sie in eine vordefinierte Eingabeaufforderungsvorlage einbettet.
  • Generierung – In der Generierungsphase nutzt das Modell die erweiterte Eingabeaufforderung, um eine kohärente, kontextbezogene genaue Antwort zu erstellen, indem es sein internes Sprachverständnis mit den abgerufenen externen Daten kombiniert. Während Augmentation externe Fakten integriert, wandelt Generierung diese angereicherten Informationen in natürlichen, menschenähnlichen Text um, der auf die Anfrage des Benutzers zugeschnitten ist.

RAG-Prozessablauf

Alle Phasen und wesentlichen Komponenten des RAG-Prozessablaufs, dargestellt in der Abbildung unten.

The ultimate guide to Retrieval-Augmented Generation (RAG)
Quelle: https://www.griddynamics.com/blog/retrieval-augmented-generation-llm

  • Laden von Dokumenten: Der erste Schritt im RAG-Prozess umfasst die Datenvorbereitung, die das Laden von Dokumenten aus dem Speicher, das Extrahieren, Parsen, Bereinigen und Formatieren von Text für die Dokumentenaufteilung umfasst. Textdaten können in verschiedenen Formaten vorliegen, z. B. als einfacher Text, PDFs, Word-Dokumente, CSV, JSON, HTML, Markdown oder Programmiercode. Um diese verschiedenen Quellen für LLMs vorzubereiten, müssen sie normalerweise durch Extrahieren, Parsen und Bereinigen in Klartext umgewandelt werden.
  • Dokumentenaufteilung: Dokumente werden durch Textaufteilung oder Chunking in kleinere, überschaubare Segmente unterteilt, was für die Verarbeitung großer Dokumente und die Einhaltung von Token-Limits in LLMs (z. B. die 2048-Tokens von GPT-3) unerlässlich ist. Zu den Strategien gehören Chunking mit fester Größe oder inhaltsbezogenes Chunking, wobei der Ansatz von der Struktur und den Anforderungen der Daten abhängt. The ultimate guide to Retrieval-Augmented Generation (RAG)

Das Aufteilen von Dokumenten in kleinere Abschnitte mag einfach erscheinen, erfordert jedoch eine sorgfältige Überlegung der Semantik, um eine unangemessene Aufteilung von Sätzen zu vermeiden, die sich auf nachfolgende Schritte wie die Beantwortung von Fragen auswirken kann. Ein naiver Chunking-Ansatz mit fester Größe kann zu unvollständigen Informationen in jedem Chunk führen. Die meisten Dokumentsegmentierungsalgorithmen verwenden Blockgröße und Überlappung, wobei die Blockgröße durch die Anzahl der Zeichen, Wörter oder Token bestimmt wird und Überlappungen die Kontinuität gewährleisten, indem sie Text zwischen benachbarten Blöcken teilen. Diese Strategie bewahrt den semantischen Kontext über Chunks hinweg.

  • Texteinbettung: Die Textblöcke werden in Vektoreinbettungen umgewandelt, die jeden Block auf eine Weise darstellen, die einen einfachen Vergleich der semantischen Ähnlichkeit ermöglicht. Vektoreinbettungen bilden komplexe Daten wie Text in einem mathematischen Raum ab, in dem ähnliche Datenpunkte zusammenkommen. Dieser Prozess erfasst die semantische Bedeutung des Textes, sodass Sätze mit ähnlicher Bedeutung, auch wenn sie unterschiedlich formuliert sind, im Vektorraum nahe beieinander abgebildet werden. Beispielsweise würden „Die Katze jagt die Maus“ und „Die Katze jagt das Nagetier“ trotz ihres unterschiedlichen Wortlauts auf nahegelegene Punkte abgebildet.

The ultimate guide to Retrieval-Augmented Generation (RAG)
Quelle: https://www.griddynamics.com/blog/retrieval-augmented-generation-llm

  • Vektorspeicher: Nachdem Dokumente segmentiert und in Vektoreinbettungen umgewandelt wurden, werden sie in einem Vektorspeicher gespeichert, einer speziellen Datenbank zum Speichern und Verwalten von Vektoren. Ein Vektorspeicher ermöglicht eine effiziente Suche nach ähnlichen Vektoren, was für die Ausführung eines RAG-Modells von entscheidender Bedeutung ist. Die Auswahl eines Vektorspeichers hängt von Faktoren wie Datenumfang und verfügbaren Rechenressourcen ab.

Einige der wichtigen Vektordatenbanken sind:

  • FAISS: FAISS wurde von Facebook AI entwickelt und verwaltet effizient große Sammlungen hochdimensionaler Vektoren und führt Ähnlichkeitssuchen und Clustering in hochdimensionalen Umgebungen durch. Es optimiert die Speichernutzung und die Abfragedauer und eignet sich daher für die Verarbeitung von Milliarden von Vektoren.
  • Chroma: Chroma ist eine Open-Source-In-Memory-Vektordatenbank, die für LLM-Anwendungen entwickelt wurde und eine skalierbare Plattform für die Speicherung, Suche und den Abruf von Vektoren bietet. Es unterstützt sowohl die Cloud- als auch die On-Premise-Bereitstellung und ist vielseitig im Umgang mit verschiedenen Datentypen und -formaten.
  • Weaviate: Eine Open-Source-Vektordatenbank, die selbst gehostet oder vollständig verwaltet werden kann. Der Schwerpunkt liegt auf hoher Leistung, Skalierbarkeit und Flexibilität und unterstützt eine breite Palette von Datentypen und Anwendungen. Es ermöglicht die Speicherung sowohl von Vektoren als auch von Objekten und ermöglicht so die Kombination von vektorbasierten und schlüsselwortbasierten Suchtechniken.
  • Pinecone: Eine cloudbasierte, verwaltete Vektordatenbank, die die Entwicklung und Bereitstellung umfangreicher ML-Anwendungen vereinfachen soll. Im Gegensatz zu vielen Vektordatenbanken verwendet Pinecone proprietären Closed-Source-Code. Es zeichnet sich durch die Verarbeitung hochdimensionaler Vektoren aus und eignet sich für Anwendungen wie Ähnlichkeitssuche, Empfehlungssysteme, Personalisierung und semantische Suche. Pinecone verfügt außerdem über eine einstufige Filterfunktion.
  • Dokumentenabruf: Der Abrufprozess in Informationsabrufsystemen, wie z. B. die Suche nach Dokumenten oder die Beantwortung von Fragen, beginnt, wenn eine Abfrage empfangen und unter Verwendung desselben Einbettungsmodells wie die Dokumentindizierung in einen Vektor umgewandelt wird. Das Ziel besteht darin, relevante Dokumentblöcke zurückzugeben, indem der Abfragevektor mit gespeicherten Blockvektoren im Index (Vektorspeicher) verglichen wird. Die Rolle des Retrievers besteht darin, die IDs relevanter Dokumentblöcke zu identifizieren und zurückzugeben, ohne Dokumente zu speichern. Es können verschiedene Suchmethoden verwendet werden, beispielsweise die Ähnlichkeitssuche (basierend auf Kosinusähnlichkeit) und die schwellenwertbasierte Suche, die nur Dokumente zurückgibt, die einen bestimmten Ähnlichkeitswert überschreiten. Darüber hinaus ist der LLM-unterstützte Abruf nützlich für Abfragen, die sowohl Inhalts- als auch Metadatenfilterung umfassen.

The ultimate guide to Retrieval-Augmented Generation (RAG)
Quelle: https://www.griddynamics.com/blog/retrieval-augmented-generation-llm

  • Antwortgenerierung: Im Abrufprozess werden relevante Dokumentblöcke mit der Benutzerabfrage kombiniert, um einen Kontext und eine Eingabeaufforderung für das LLM zu generieren. Der einfachste Ansatz, in LangChain „Stuff“-Methode genannt, besteht darin, alle Blöcke in dasselbe Kontextfenster zu leiten, um eine direkte, unkomplizierte Antwort zu erhalten. Bei großen Dokumentmengen und komplexen Abfragen ist diese Methode jedoch aufgrund der Einschränkungen des Kontextfensters problematisch. Um dies zu beheben, werden alternative Methoden wie Map-reduce, Refine und Map-rerank verwendet. Map-Reduce sendet Dokumente separat an das LLM und kombiniert dann die Antworten. „Refine“ aktualisiert die Eingabeaufforderung iterativ, um die Antwort zu verfeinern, während „Map-reranking“ Dokumente nach Relevanz ordnet, ideal für mehrere überzeugende Antworten.

The ultimate guide to Retrieval-Augmented Generation (RAG)

RAG vs. Feinabstimmung

RAG (Retrieval-Augmented Generation) und Feinabstimmung sind zwei Schlüsselmethoden zur Erweiterung der LLM-Funktionen, die jeweils für unterschiedliche Szenarien geeignet sind. Bei der Feinabstimmung geht es darum, LLMs auf domänenspezifische Daten umzuschulen, um spezielle Aufgaben auszuführen, ideal für statische, eng gefasste Anwendungsfälle wie Branding oder kreatives Schreiben, die einen bestimmten Ton oder Stil erfordern. Es ist jedoch kostspielig, zeitaufwändig und für dynamische, häufig aktualisierte Daten ungeeignet.

Andererseits verbessert RAG LLMs, indem es externe Daten dynamisch abruft, ohne die Modellgewichte zu ändern, was es kostengünstig und ideal für datengesteuerte Echtzeitumgebungen wie Rechts-, Finanz- oder Kundendienstanwendungen macht. RAG ermöglicht LLMs den Umgang mit großen, unstrukturierten internen Dokumentenkorpora und bietet erhebliche Vorteile gegenüber herkömmlichen Methoden zum Navigieren in unübersichtlichen Datenrepositorys.

Die Feinabstimmung zeichnet sich durch die Erstellung differenzierter, konsistenter Ergebnisse aus, während RAG durch die Nutzung externer Wissensdatenbanken aktuelle und genaue Informationen bereitstellt. In der Praxis ist RAG oft die bevorzugte Wahl für Anwendungen, die anpassbare Echtzeitreaktionen erfordern, insbesondere in Unternehmen, die riesige, unstrukturierte Daten verwalten.

Arten von RAG

Es gibt verschiedene Arten von Retrieval-Augmented Generation (RAG)-Ansätzen, die jeweils auf bestimmte Anwendungsfälle und Ziele zugeschnitten sind. Zu den Haupttypen gehören:

The ultimate guide to Retrieval-Augmented Generation (RAG)
Quelle: https://x.com/weaviate_io/status/1866528335884325070

  • Native RAG: Bezieht sich auf einen eng integrierten Ansatz, bei dem die Retrieval- und generativen Komponenten eines Retrieval-Augmented Generation-Systems so konzipiert sind, dass sie nahtlos innerhalb derselben Architektur funktionieren. Im Gegensatz zu herkömmlichen Implementierungen, die auf externen Tools oder APIs basieren, optimiert natives RAG die Interaktion zwischen Abrufmechanismen und generativen Modellen und ermöglicht so eine schnellere Verarbeitung und eine verbesserte Kontextrelevanz. Dieser Ansatz nutzt häufig In-Memory-Verarbeitung oder hochoptimierte lokale Datenbanken, wodurch Latenz und Ressourcenaufwand reduziert werden. Native RAG-Systeme sind in der Regel auf bestimmte Anwendungsfälle zugeschnitten und bieten verbesserte Effizienz, Genauigkeit und Kosteneffizienz, indem sie Abhängigkeiten von Drittanbieterdiensten eliminieren.
  • RAG abrufen und neu einordnen: Konzentriert sich auf die Verfeinerung des Abrufprozesses, um Genauigkeit und Relevanz zu verbessern. Bei dieser Methode wird ein erster Satz von Dokumenten oder Blöcken basierend auf der semantischen Ähnlichkeit der Abfrage abgerufen, die normalerweise durch die Kosinusähnlichkeit im Einbettungsraum bestimmt wird. Anschließend ordnet ein Reranking-Modell die abgerufenen Dokumente basierend auf ihrer kontextuellen Relevanz für die Abfrage neu. Dieser Reranking-Schritt nutzt oft Deep-Learning-Modelle oder Transformatoren und ermöglicht so eine differenziertere Rangfolge über grundlegende Ähnlichkeitsmetriken hinaus. Durch die Priorisierung der relevantesten Dokumente stellt dieser Ansatz sicher, dass das generative Modell kontextuell angereicherte Eingaben erhält, was die Antwortqualität deutlich verbessert.
  • Multimodales RAG: Erweitert das traditionelle RAG-Paradigma durch die Integration mehrerer Datenmodalitäten wie Text, Bilder, Audio oder Video in die abrufergänzte Generierungspipeline. Dadurch kann das System Antworten abrufen und generieren, die verschiedene Datenformen integrieren. In einem Szenario mit bildbasierten Abfragen könnte das System beispielsweise relevante Bilder neben Textinhalten abrufen, um eine umfassendere Antwort zu erstellen. Multimodales RAG ist besonders nützlich in Bereichen wie E-Commerce, medizinische Bildgebung und Multimedia-Inhaltsanalyse, wo Erkenntnisse oft auf einer Kombination aus Text- und visuellen Informationen beruhen.
  • Graph RAG: Nutzt graphbasierte Datenstrukturen, um Informationen basierend auf Beziehungen und Verbindungen zwischen Entitäten zu modellieren und abzurufen. Bei diesem Ansatz wird Wissen als Diagramm organisiert, in dem Knoten Entitäten (z. B. Konzepte, Dokumente oder Objekte) darstellen und Kanten ihre Beziehungen (z. B. semantisch, hierarchisch oder zeitlich) erfassen. Abfragen werden verarbeitet, um für die Eingabe relevante Untergraphen oder Pfade zu identifizieren, und diese Untergraphen werden dann in das generative Modell eingespeist. Diese Methode ist besonders wertvoll in Bereichen wie wissenschaftlicher Forschung, sozialen Netzwerken und Wissensmanagement, in denen relationale Erkenntnisse von entscheidender Bedeutung sind.
  • Hybrid RAG: Kombiniert mehrere Abruftechniken, wie z. B. Dense- und Sparse-Abruf, um die Leistung über verschiedene Abfragetypen hinweg zu verbessern. Beim dichten Abruf werden Vektoreinbettungen verwendet, um semantische Ähnlichkeiten zu erfassen, während beim sparsamen Abruf schlüsselwortbasierte Methoden wie BM25 für präzise Übereinstimmungen zum Einsatz kommen. Durch die Integration dieser Methoden gleicht Hybrid RAG Präzision und Rückruf aus und macht es vielseitig einsetzbar in Szenarien, in denen Abfragen sehr spezifisch oder abstrakt sein können. Es ist besonders effektiv in Umgebungen mit heterogenen Daten und stellt sicher, dass beim Abruf sowohl High-Level-Semantik als auch spezifische Schlüsselwörter berücksichtigt werden.
  • Agentic RAG (Router): Verwendet eine Entscheidungsebene, um Abfragen basierend auf ihren Eigenschaften dynamisch an geeignete Abruf- und generative Module weiterzuleiten. Der Router analysiert eingehende Anfragen, um den optimalen Verarbeitungspfad zu ermitteln, der verschiedene Abrufmethoden, Datenquellen oder sogar spezielle generative Modelle umfassen kann. Dieser Ansatz stellt sicher, dass das System seine Abläufe an die spezifischen Anforderungen jeder Abfrage anpasst und so die Effizienz und Genauigkeit in verschiedenen Anwendungen erhöht.
  • Agentic RAG (Multi-Agent RAG): Multi-Agent RAG umfasst ein kollaboratives Framework, in dem mehrere spezialisierte Agenten verschiedene Aspekte des Abruf- und Generierungsprozesses verwalten. Jeder Agent ist für eine bestimmte Aufgabe verantwortlich, z. B. das Abrufen von Daten aus einer bestimmten Domäne, das Neuranking von Ergebnissen oder das Generieren von Antworten in einem bestimmten Stil. Diese Agenten kommunizieren und arbeiten zusammen, um zusammenhängende Ergebnisse zu liefern. Multi-Agent RAG ist besonders leistungsstark für komplexe Anfragen mit mehreren Domänen, da es dem System ermöglicht, das Fachwissen verschiedener Agenten zu nutzen, um umfassende und differenzierte Antworten zu liefern.

Anwendungen von RAG

Das Retrieval-Augmented Generation (RAG)-Framework hat aufgrund seiner Fähigkeit, externes Wissen dynamisch in generative Sprachmodelle zu integrieren, vielfältige Anwendungen in verschiedenen Branchen. Hier sind einige prominente Anwendungen:

  • Kundensupport und Service: RAG-Systeme werden häufig im Kundensupport eingesetzt, um intelligente Chatbots zu erstellen, die in der Lage sind, komplexe Anfragen zu beantworten, indem sie relevante Daten aus Produkthandbüchern, Wissensdatenbanken und Dokumenten zu Unternehmensrichtlinien abrufen. Dadurch wird sichergestellt, dass Kunden genaue und aktuelle Informationen erhalten, was ihr Erlebnis verbessert.
  • Analyse von Rechtsdokumenten: Im Rechtsbereich kann RAG Zusammenfassungen oder Antworten aus umfangreichen Korpora von Rechtsprechung, Verträgen und Rechtsdokumenten analysieren, abrufen und generieren. Es ist besonders nützlich für die Durchführung von Rechtsrecherchen, die Ausarbeitung von Verträgen und die Sicherstellung der Einhaltung von Vorschriften.
  • Finanzanalyse: RAG wird im Finanzdienstleistungsbereich eingesetzt, um Gewinnberichte, Markttrends und regulatorische Dokumente zu analysieren. Durch den Abruf relevanter Finanzdaten kann es Analysten dabei helfen, Erkenntnisse, Berichte oder sogar Echtzeit-Antworten auf Fragen zur Marktleistung zu generieren.
  • Gesundheitswesen und medizinische Diagnostik: Im Gesundheitswesen wird RAG verwendet, um Informationen aus medizinischer Literatur, Patientenakten und Behandlungsrichtlinien abzurufen und zu synthetisieren. Es hilft bei der diagnostischen Unterstützung, der Arzneimittelentwicklung und personalisierten Behandlungsempfehlungen und stellt sicher, dass Ärzte Zugriff auf die neuesten und relevantesten Daten haben.
  • Bildung und E-Learning: RAG-basierte Tools unterstützen bei der personalisierten Bildung, indem sie Kursmaterial abrufen und maßgeschneiderte Antworten oder Studienführer generieren. Sie können Lernplattformen verbessern, indem sie kontextbezogene Erklärungen und dynamische Inhalte basierend auf Benutzeranfragen bereitstellen.
  • E-Commerce und Einzelhandel: Im E-Commerce verbessern RAG-Systeme Produktsuch- und Empfehlungsmaschinen, indem sie Daten aus Katalogen und Kundenrezensionen abrufen. Sie ermöglichen auch gesprächige Einkaufsassistenten, die personalisierte Produktvorschläge basierend auf Benutzerpräferenzen liefern.
  • Intelligente virtuelle Assistenten: RAG erweitert virtuelle Assistenten wie Alexa oder Siri durch die Bereitstellung präziser und kontextrelevanter Antworten, insbesondere bei Anfragen, die externes Wissen erfordern, wie z. B. Wetteraktualisierungen in Echtzeit oder lokale Geschäftsinformationen.

Aufbau eines PDF-Chat-Systems mit RAG

In diesem Abschnitt entwickeln wir eine Streamlit-Anwendung, die in der Lage ist, den Inhalt einer PDF-Datei zu verstehen und auf Benutzeranfragen basierend auf diesem Inhalt mithilfe der Retrieval-Augmented Generation (RAG) zu reagieren. Die Implementierung nutzt die LangChain-Plattform, um die Interaktion mit LLMs und Vektorspeichern zu erleichtern. Wir werden das LLM von OpenAI und seine Einbettungsmodelle nutzen, um einen FAISS-Vektorspeicher für den effizienten Informationsabruf aufzubauen.

Abhängigkeiten installieren

  • Erstellen und aktivieren Sie eine virtuelle Umgebung, indem Sie den folgenden Befehl ausführen.
python -m venv venv
source venv/bin/activate #for ubuntu
venv/Scripts/activate #for windows
Nach dem Login kopieren
  • Installieren Sie die Bibliotheken langchain, langchain_community, openai, faiss-cpu, PyPDF2, streamlit, python-dotenv und tiktoken mit pip.
pip install langchain langchain_community openai faiss-cpu PyPDF2 streamlit python-dotenv tiktoken
Nach dem Login kopieren

Umgebung und Anmeldeinformationen einrichten

  • Erstellen Sie eine Datei mit dem Namen .env. In dieser Datei werden Ihre Umgebungsvariablen gespeichert, einschließlich des OpenAI-Schlüssels, des Modells und der Einbettungen.
  • Öffnen Sie die .env-Datei und fügen Sie den folgenden Code hinzu, um Ihre OpenAI-Anmeldeinformationen anzugeben:
OPENAI_API_KEY=sk-proj-xcQxBf5LslO62At...
OPENAI_MODEL_NAME=gpt-3.5-turbo
OPENAI_EMBEDDING_MODEL_NAME=text-embedding-3-small
Nach dem Login kopieren

Umgebungsvariablen importieren

  • Erstellen Sie eine Datei mit dem Namen app.py.
  • Fügen Sie OpenAI-Anmeldeinformationen zu den Umgebungsvariablen hinzu.
from dotenv import load_dotenv
import os
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME")
OPENAI_EMBEDDING_MODEL_NAME = os.getenv("OPENAI_EMBEDDING_MODEL_NAME")
Nach dem Login kopieren

Importieren erforderlicher Bibliotheken

Importieren Sie wichtige Bibliotheken zum Erstellen der App und zum Verarbeiten von PDFs wie Langchain, Streamlit und PyPDF.

import streamlit as st
from PyPDF2 import PdfReader
from langchain.text_splitter import CharacterTextSplitter
from langchain.prompts import PromptTemplate
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from langchain_community.chat_models import ChatOpenAI
from htmlTemplates import bot_template, user_template, css
Nach dem Login kopieren

Definieren einer Funktion zum Extrahieren von Text aus PDFs

  • Verwenden Sie PyPDF2, um Text aus hochgeladenen PDF-Dateien zu extrahieren.
def get_pdf_text(pdf_files):
    text = ""
    for pdf_file in pdf_files:
        reader = PdfReader(pdf_file)
        for page in reader.pages:
            text += page.extract_text()
    return text
Nach dem Login kopieren

Aufteilen des extrahierten Texts in Blöcke

Teilen Sie großen Text mit dem CharacterTextSplitter von LangChain in kleinere, überschaubare Teile auf.

def get_chunk_text(text):
    text_splitter = CharacterTextSplitter(
        separator="\n",
        chunk_size=1000,
        chunk_overlap=200,
        length_function=len
    )
    chunks = text_splitter.split_text(text)
    return chunks
Nach dem Login kopieren

Erstellen eines Vektorspeichers für Texteinbettungen

Generieren Sie Einbettungen für Textblöcke und speichern Sie sie mit FAISS in einer Vektordatenbank.

def get_vector_store(text_chunks):
    embeddings = OpenAIEmbeddings(openai_api_key=OPENAI_API_KEY, model=OPENAI_EMBEDDING_MODEL_NAME)
    vectorstore = FAISS.from_texts(texts=text_chunks, embedding=embeddings)
    return vectorstore
Nach dem Login kopieren

Aufbau einer Konversationsabrufkette

Definieren Sie eine Kette, die Informationen aus dem Vektorspeicher abruft und über ein LLM mit dem Benutzer interagiert.

def get_conversation_chain(vector_store):
    llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY, model_name=OPENAI_MODEL_NAME, temperature=0)
    memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True)
    system_template  =  """
    Use  the following pieces of context and chat history to answer the question at the end. 
    If you don't know the answer, just say that you don't know, don't try to make up an answer.

    Context: {context}

    Chat history: {chat_history}

    Question: {question}
    Helpful Answer:
    """
    prompt = PromptTemplate(
        template=system_template,
        input_variables=["context", "question",  "chat_history"],
    )
    conversation_chain = ConversationalRetrievalChain.from_llm(
        verbose = True,
        llm=llm,
        retriever=vector_store.as_retriever(),
        memory=memory,
        combine_docs_chain_kwargs={"prompt": prompt}
    )
    return conversation_chain
Nach dem Login kopieren

Bearbeitung von Benutzeranfragen

Benutzereingaben verarbeiten, an die Konversationskette übergeben und den Chat-Verlauf aktualisieren.

def handle_user_input(question):
    try:
        response = st.session_state.conversation({'question': question})
        st.session_state.chat_history = response['chat_history']
    except Exception as e:
        st.error('Please select PDF and click on Process.')
Nach dem Login kopieren

Erstellen einer benutzerdefinierten HTML-Vorlage für Streamlit-Chat

Um mithilfe von CSS eine benutzerdefinierte Chat-Oberfläche für Benutzer- und Bot-Nachrichten zu erstellen, entwerfen Sie benutzerdefinierte Vorlagen und gestalten Sie sie mit CSS.

  • Erstellen Sie eine Datei mit dem Namen htmlTemplates.py und fügen Sie den folgenden Code hinzu.
css = '''
<style>
.chat-message {
    padding: 1rem; border-radius: 0.5rem; margin-bottom: 1rem; display: flex
}
.chat-message.user {
    background-color: #2b313e
}
.chat-message.bot {
    background-color: #475063
}
.chat-message .avatar {
  width: 10%;
}
.chat-message .avatar img {
  max-width: 30px;
  max-height: 30px;
  border-radius: 50%;
  object-fit: cover;
}
.chat-message .message {
  width: 90%;
  padding: 0 1rem;
  color: #fff;
}
'''

bot_template = '''
<div>



<h3>
  
  
  Displaying chat history
</h3>

<p>Show the user and AI conversation history in a reverse order with HTML templates for formatting.<br>
</p>

<pre class="brush:php;toolbar:false">def display_chat_history():
    if st.session_state.chat_history:
        reversed_history = st.session_state.chat_history[::-1]

        formatted_history = []
        for i in range(0, len(reversed_history), 2):
            chat_pair = {
                "AIMessage": reversed_history[i].content,
                "HumanMessage": reversed_history[i + 1].content
            }
            formatted_history.append(chat_pair)

        for i, message in enumerate(formatted_history):
            st.write(user_template.replace("{{MSG}}", message['HumanMessage']), unsafe_allow_html=True)
            st.write(bot_template.replace("{{MSG}}", message['AIMessage']), unsafe_allow_html=True)
Nach dem Login kopieren

Erstellen einer Streamlit-App-Schnittstelle

Richten Sie die Haupt-App-Oberfläche für Datei-Uploads, Frageneingabe und Chat-Verlaufsanzeige ein.

def main():
    st.set_page_config(page_title='Chat with PDFs', page_icon=':books:')
    st.write(css, unsafe_allow_html=True)

    if "conversation" not in st.session_state:
        st.session_state.conversation = None
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = None

    st.header('Chat with PDFs :books:')

    question = st.text_input("Ask anything to your PDF:")
    if question:
        handle_user_input(question)

    if st.session_state.chat_history is not None:
        display_chat_history()

    with st.sidebar:
        st.subheader("Upload your Documents Here: ")
        pdf_files = st.file_uploader("Choose your PDF Files and Press Process button", type=['pdf'], accept_multiple_files=True)

        if pdf_files and st.button("Process"):
            with st.spinner("Processing your PDFs..."):
                try:
                    # Get PDF Text
                    raw_text = get_pdf_text(pdf_files)
                    # Get Text Chunks
                    text_chunks = get_chunk_text(raw_text)
                    # Create Vector Store
                    vector_store = get_vector_store(text_chunks)
                    st.success("Your PDFs have been processed successfully. You can ask questions now.")
                    # Create conversation chain
                    st.session_state.conversation = get_conversation_chain(vector_store)
                except Exception as e:
                    st.error(f"An error occurred: {e}")

if __name__ == '__main__':
    main()
Nach dem Login kopieren

Vollständiger Code für die PDF-Chat-Anwendung

Das Folgende ist die vollständige Code-Implementierung für die PDF-Chat-Anwendung. Es integriert die Einrichtung von Umgebungsvariablen, Textextraktion, Vektorspeicher und RAG-Funktionen in einer optimierten Lösung:

from dotenv import load_dotenv
import os
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME")
OPENAI_EMBEDDING_MODEL_NAME = os.getenv("OPENAI_EMBEDDING_MODEL_NAME")

import streamlit as st
from PyPDF2 import PdfReader
from langchain.text_splitter import CharacterTextSplitter
from langchain.prompts import PromptTemplate
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from langchain_community.chat_models import ChatOpenAI
from htmlTemplates import bot_template, user_template, css

def get_pdf_text(pdf_files):
    text = ""
    for pdf_file in pdf_files:
        reader = PdfReader(pdf_file)
        for page in reader.pages:
            text += page.extract_text()
    return text

def get_chunk_text(text):
    text_splitter = CharacterTextSplitter(
        separator="\n",
        chunk_size=1000,
        chunk_overlap=200,
        length_function=len
    )
    chunks = text_splitter.split_text(text)
    return chunks

def get_vector_store(text_chunks):
    embeddings = OpenAIEmbeddings(openai_api_key=OPENAI_API_KEY, model=OPENAI_EMBEDDING_MODEL_NAME)
    vectorstore = FAISS.from_texts(texts=text_chunks, embedding=embeddings)
    return vectorstore

def get_conversation_chain(vector_store):
    llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY, model_name=OPENAI_MODEL_NAME, temperature=0)
    memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True)
    system_template  =  """
    Use  the following pieces of context and chat history to answer the question at the end. 
    If you don't know the answer, just say that you don't know, don't try to make up an answer.

    Context: {context}

    Chat history: {chat_history}

    Question: {question}
    Helpful Answer:
    """
    prompt = PromptTemplate(
        template=system_template,
        input_variables=["context", "question",  "chat_history"],
    )
    conversation_chain = ConversationalRetrievalChain.from_llm(
        verbose = True,
        llm=llm,
        retriever=vector_store.as_retriever(),
        memory=memory,
        combine_docs_chain_kwargs={"prompt": prompt}
    )
    return conversation_chain

def handle_user_input(question):
    try: 
        response = st.session_state.conversation({'question': question})
        st.session_state.chat_history = response['chat_history']
    except Exception as e:
        st.error('Please select PDF and click on OK.')

def display_chat_history():
    if st.session_state.chat_history:
        reversed_history = st.session_state.chat_history[::-1]

        formatted_history = []
        for i in range(0, len(reversed_history), 2):
            chat_pair = {
                "AIMessage": reversed_history[i].content,
                "HumanMessage": reversed_history[i + 1].content
            }
            formatted_history.append(chat_pair)

        for i, message in enumerate(formatted_history):
            st.write(user_template.replace("{{MSG}}", message['HumanMessage']), unsafe_allow_html=True)
            st.write(bot_template.replace("{{MSG}}", message['AIMessage']), unsafe_allow_html=True)

def main():
    st.set_page_config(page_title='Chat with PDFs', page_icon=':books:')
    st.write(css, unsafe_allow_html=True)

    if "conversation" not in st.session_state:
        st.session_state.conversation = None
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = None

    st.header('Chat with PDFs :books:')

    question = st.text_input("Ask anything to your PDF:")
    if question:
        handle_user_input(question)

    if st.session_state.chat_history is not None:
        display_chat_history()

    with st.sidebar:
        st.subheader("Upload your Documents Here: ")
        pdf_files = st.file_uploader("Choose your PDF Files and Press Process button", type=['pdf'], accept_multiple_files=True)

        if pdf_files and st.button("Process"):
            with st.spinner("Processing your PDFs..."):
                try:
                    # Get PDF Text
                    raw_text = get_pdf_text(pdf_files)
                    # Get Text Chunks
                    text_chunks = get_chunk_text(raw_text)
                    # Create Vector Store
                    vector_store = get_vector_store(text_chunks)
                    st.success("Your PDFs have been processed successfully. You can ask questions now.")
                    # Create conversation chain
                    st.session_state.conversation = get_conversation_chain(vector_store)
                except Exception as e:
                    st.error(f"An error occurred: {e}")

if __name__ == '__main__':
    main()

Nach dem Login kopieren

Führen Sie die Anwendung aus

Führen Sie die App mit Streamlit mit dem folgenden Befehl aus.

streamlit run app.py
Nach dem Login kopieren

Sie erhalten die folgende Ausgabe:
The ultimate guide to Retrieval-Augmented Generation (RAG)

Vielen Dank für das Lesen dieses Artikels!!

Vielen Dank an Gowri M Bhatt für die Überprüfung des Inhalts.

Wenn Ihnen dieser Artikel gefallen hat, klicken Sie bitte auf den Herz-Button ♥ und teilen Sie ihn, damit andere ihn finden können!

Den vollständigen Quellcode für dieses Tutorial finden Sie hier,

codemaker2015/pdf-chat-using-RAG | github.com

Ressourcen

  • RAG- und LLM-Geschäftsprozessautomatisierung: Eine technische Strategie – Grid Dynamics | www.griddynamics.com
  • Einführung in Retrieval Augmented Generation (RAG) | Weaviate
  • Techniken, Herausforderungen und Zukunft erweiterter Sprachmodelle – Gradient Flow
  • Retrieval Augmented Generation im Planetenmaßstab | Arcus

Das obige ist der detaillierte Inhalt vonDer ultimative Leitfaden zur Retrieval-Augmented Generation (RAG). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage