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.
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.
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:
Quelle: https://weaviate.io/blog/introduction-to-rag
Alle Phasen und wesentlichen Komponenten des RAG-Prozessablaufs, dargestellt in der Abbildung unten.
Quelle: https://www.griddynamics.com/blog/retrieval-augmented-generation-llm
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.
Quelle: https://www.griddynamics.com/blog/retrieval-augmented-generation-llm
Einige der wichtigen Vektordatenbanken sind:
Quelle: https://www.griddynamics.com/blog/retrieval-augmented-generation-llm
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.
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:
Quelle: https://x.com/weaviate_io/status/1866528335884325070
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:
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.
python -m venv venv source venv/bin/activate #for ubuntu venv/Scripts/activate #for windows
pip install langchain langchain_community openai faiss-cpu PyPDF2 streamlit python-dotenv tiktoken
OPENAI_API_KEY=sk-proj-xcQxBf5LslO62At... OPENAI_MODEL_NAME=gpt-3.5-turbo OPENAI_EMBEDDING_MODEL_NAME=text-embedding-3-small
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")
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
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
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
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
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
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.')
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.
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)
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()
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()
Führen Sie die App mit Streamlit mit dem folgenden Befehl aus.
streamlit run app.py
Sie erhalten die folgende Ausgabe:
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
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!