Maison >développement back-end >Tutoriel Python >Le guide ultime de la génération augmentée par récupération (RAG)
L'évolution rapide des modèles d'IA générative comme ChatGPT d'OpenAI a révolutionné le traitement du langage naturel, permettant à ces systèmes de générer des réponses cohérentes et contextuellement pertinentes. Cependant, même les modèles les plus avancés sont confrontés à des limites lorsqu’ils traitent des requêtes spécifiques à un domaine ou fournissent des informations très précises. Cela conduit souvent à des problèmes tels que des hallucinations : des cas où les modèles produisent des détails inexacts ou fabriqués.
Retrieval-Augmented Generation (RAG), un cadre innovant conçu pour combler cette lacune. En intégrant de manière transparente des sources de données externes, RAG permet aux modèles génératifs de récupérer des informations de niche en temps réel, améliorant ainsi considérablement leur précision et leur fiabilité.
Dans cet article, nous plongerons dans la mécanique de RAG, explorerons son architecture et discuterons des limites des modèles génératifs traditionnels qui ont inspiré sa création. Nous mettrons également en évidence des mises en œuvre pratiques, des techniques avancées et des méthodes d'évaluation, montrant comment RAG transforme la façon dont l'IA interagit avec des données spécialisées.
Retrieval-Augmented Generation (RAG) est un cadre avancé qui améliore les capacités des modèles d'IA génératifs en intégrant la récupération en temps réel de données externes. Bien que les modèles génératifs excellent dans la production de textes cohérents et semblables à ceux des humains, ils peuvent échouer lorsqu'on leur demande de fournir des informations précises, à jour ou spécifiques à un domaine. C'est là qu'intervient RAG, en veillant à ce que les réponses soient non seulement créatives mais également fondées sur des sources fiables et pertinentes.
RAG fonctionne en connectant un modèle génératif à un mécanisme de récupération, généralement alimenté par des bases de données vectorielles ou des systèmes de recherche. Lorsqu'une requête est reçue, le composant de récupération recherche dans de vastes ensembles de données externes pour récupérer les informations pertinentes. Le modèle génératif synthétise ensuite ces données, produisant un résultat à la fois précis et contextuellement perspicace.
En abordant des défis clés tels que les hallucinations et la connaissance limitée du domaine, RAG libère le potentiel des modèles génératifs pour exceller dans des domaines spécialisés. Ses applications couvrent divers secteurs, depuis l'automatisation du support client avec des réponses précises, permettant aux chercheurs d'accéder à des connaissances organisées à la demande. RAG représente une avancée significative pour rendre les systèmes d'IA plus intelligents, plus fiables et plus utiles dans des scénarios du monde réel.
Une compréhension claire de l'architecture RAG est essentielle pour libérer tout son potentiel et ses avantages. À la base, le cadre repose sur deux composants principaux : le Retriever et le Generator, travaillant ensemble dans un flux transparent de traitement de l'information.
Ce processus global est illustré ci-dessous :
source : https://weaviate.io/blog/introduction-to-rag
Toutes les étapes et composants essentiels du flux de processus RAG, illustrés dans la figure ci-dessous.
source : https://www.griddynamics.com/blog/retrieval-augmented-Generation-llm
Diviser des documents en morceaux plus petits peut sembler simple, mais cela nécessite un examen attentif de la sémantique pour éviter de diviser les phrases de manière inappropriée, ce qui peut affecter les étapes ultérieures telles que la réponse aux questions. Une approche naïve de segmentation de taille fixe peut entraîner des informations incomplètes dans chaque segment. La plupart des algorithmes de segmentation de documents utilisent la taille des fragments et le chevauchement, où la taille des fragments est déterminée par le nombre de caractères, de mots ou de jetons, et les chevauchements assurent la continuité en partageant le texte entre les fragments adjacents. Cette stratégie préserve le contexte sémantique à travers les morceaux.
source : https://www.griddynamics.com/blog/retrieval-augmented-Generation-llm
Certaines des bases de données vectorielles importantes sont :
source : https://www.griddynamics.com/blog/retrieval-augmented-Generation-llm
RAG (Retrieval-Augmented Generation) et le réglage fin sont deux méthodes clés pour étendre les capacités LLM, chacune adaptée à différents scénarios. Le réglage fin implique de recycler les LLM sur des données spécifiques à un domaine pour effectuer des tâches spécialisées, idéales pour les cas d'utilisation statiques et restreints comme l'image de marque ou l'écriture créative qui nécessitent un ton ou un style spécifique. Cependant, cette méthode est coûteuse, prend du temps et ne convient pas aux données dynamiques et fréquemment mises à jour.
D'autre part, RAG améliore les LLM en récupérant dynamiquement des données externes sans modifier les pondérations du modèle, ce qui le rend rentable et idéal pour les environnements en temps réel basés sur les données comme les applications juridiques, financières ou de service client. RAG permet aux LLM de gérer des corpus de documents internes volumineux et non structurés, offrant des avantages significatifs par rapport aux méthodes traditionnelles de navigation dans des référentiels de données désordonnés.
Le réglage fin excelle dans la création de résultats nuancés et cohérents, tandis que RAG fournit des informations à jour et précises en exploitant des bases de connaissances externes. Dans la pratique, RAG est souvent le choix privilégié pour les applications nécessitant des réponses adaptables en temps réel, en particulier dans les entreprises gérant de vastes données non structurées.
Il existe plusieurs types d'approches de génération de récupération augmentée (RAG), chacune adaptée à des cas d'utilisation et à des objectifs spécifiques. Les principaux types incluent :
source : https://x.com/weaviate_io/status/1866528335884325070
Le framework RAG (Retrieval-Augmented Generation) a diverses applications dans divers secteurs en raison de sa capacité à intégrer dynamiquement des connaissances externes dans des modèles de langage génératifs. Voici quelques applications importantes :
Dans cette section, nous développerons une application rationalisée capable de comprendre le contenu d'un PDF et de répondre aux requêtes des utilisateurs basées sur ce contenu à l'aide de la génération de récupération augmentée (RAG). La mise en œuvre exploite la plateforme LangChain pour faciliter les interactions avec les LLM et les magasins de vecteurs. Nous utiliserons le LLM d'OpenAI et ses modèles d'intégration pour construire un magasin de vecteurs FAISS pour une récupération efficace des informations.
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")
Importez les bibliothèques essentielles pour créer l'application, en gérant les PDF tels que langchain, streamlit, 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
Divisez un texte volumineux en morceaux plus petits et gérables à l'aide de CharacterTextSplitter de LangChain.
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
Générez des intégrations pour des morceaux de texte et stockez-les dans une base de données vectorielles à l'aide de FAISS.
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
Définissez une chaîne qui récupère les informations du magasin de vecteurs et interagit avec l'utilisateur via un LLM.
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
Traitez les entrées de l'utilisateur, transmettez-les à la chaîne de conversation et mettez à jour l'historique des discussions.
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.')
Pour créer une interface de discussion personnalisée pour les messages des utilisateurs et des robots à l'aide de CSS, concevez des modèles personnalisés et stylisez-les avec 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)
Configurez l'interface principale de l'application pour le téléchargement de fichiers, la saisie de questions et l'affichage de l'historique des discussions.
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()
Ce qui suit est l'implémentation complète du code pour l'application PDF Chat. Il intègre la configuration des variables d'environnement, l'extraction de texte, le stockage vectoriel et les fonctionnalités RAG dans une solution rationalisée :
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()
Exécutez l'application avec Streamlit à l'aide de la commande suivante.
streamlit run app.py
Vous obtiendrez le résultat comme suit,
Merci d'avoir lu cet article !!
Merci Gowri M Bhatt d'avoir révisé le contenu.
Si vous avez apprécié cet article, veuillez cliquer sur le bouton cœur ♥ et partager pour aider les autres à le trouver !
Le code source complet de ce tutoriel peut être trouvé ici,
codemaker2015/pdf-chat-using-RAG | github.com
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!