À une époque où la confidentialité des données est primordiale, la mise en place de votre propre modèle de langue locale (LLM) constitue une solution cruciale pour les entreprises et les particuliers. Ce didacticiel est conçu pour vous guider tout au long du processus de création d'un chatbot personnalisé à l'aide d'Ollama , Python 3 et ChromaDB , tous hébergés localement sur votre système. Voici les principales raisons pour lesquelles vous avez besoin de ce tutoriel :
Ce tutoriel vous permettra de créer un chatbot local robuste et sécurisé, adapté à vos besoins, sans compromettre la confidentialité ou le contrôle.
La génération augmentée par récupération (RAG) est une technique avancée qui combine les atouts de la récupération d'informations et de la génération de texte pour créer des réponses plus précises et contextuellement pertinentes. Voici un aperçu du fonctionnement de RAG et de ses avantages :
RAG est un modèle hybride qui améliore les capacités des modèles de langage en incorporant une base de connaissances externe ou un magasin de documents. Le processus implique deux éléments principaux :
En configurant une application RAG locale avec des outils comme Ollama, Python et ChromaDB, vous pouvez profiter des avantages des modèles de langage avancés tout en gardant le contrôle de vos données et de vos options de personnalisation.
L’exécution de grands modèles de langage (LLM) comme ceux utilisés dans la génération augmentée par récupération (RAG) nécessite une puissance de calcul importante. L'un des composants clés qui permettent un traitement et une intégration efficaces des données dans ces modèles est l'unité de traitement graphique (GPU). Voici pourquoi les GPU sont essentiels pour cette tâche et comment ils impactent les performances de votre configuration LLM locale :
Un GPU est un processeur spécialisé conçu pour accélérer le rendu des images et des vidéos. Contrairement aux unités centrales de traitement (CPU), optimisées pour les tâches de traitement séquentiel, les GPU excellent dans le traitement parallèle. Cela les rend particulièrement adaptés aux calculs mathématiques complexes requis par les modèles d’apprentissage automatique et d’apprentissage profond.
Lors de la configuration d'un LLM local, le choix du GPU peut avoir un impact significatif sur les performances. Voici quelques facteurs à considérer :
Investir dans un GPU hautes performances est crucial pour exécuter des modèles LLM localement. Il garantit un traitement des données plus rapide, une formation efficace des modèles et une génération de réponses rapide, rendant votre application RAG locale plus robuste et fiable. En tirant parti de la puissance des GPU, vous pouvez pleinement profiter des avantages de l’hébergement de votre propre chatbot personnalisé, adapté à vos besoins spécifiques et à vos exigences en matière de confidentialité des données.
Avant de vous lancer dans la configuration, assurez-vous que les conditions préalables suivantes sont remplies :
Pour installer et configurer notre environnement Python 3, suivez ces étapes : Téléchargez et configurez Python 3 sur votre machine. Assurez-vous ensuite que votre Python 3 est installé et exécuté avec succès :
$ python3 --version # Python 3.11.7
Créez un dossier pour votre projet, par exemple local-rag
:
$ mkdir local-rag $ cd local-rag
Créez un environnement virtuel nommé venv
:
$ python3 -m venv venv
Activez l'environnement virtuel :
$ source venv/bin/activate # Windows # venv\Scripts\activate
Installez ChromaDB à l'aide de pip :
$ pip install --q chromadb
Installez les outils Langchain pour travailler de manière transparente avec votre modèle :
$ pip install --q unstructured langchain langchain-text-splitters $ pip install --q "unstructured[all-docs]"
Installez Flask pour servir votre application en tant que service HTTP :
$ pip install --q flask
Pour installer Ollama, suivez ces étapes : Accédez à la page de téléchargement d'Ollama et téléchargez le programme d'installation de votre système d'exploitation. Vérifiez votre installation Ollama en exécutant :
$ ollama --version # ollama version is 0.1.47
Tirez le modèle LLM dont vous avez besoin. Par exemple, pour utiliser le modèle Mistral :
$ ollama pull mistral
Extrayez le modèle d'intégration de texte. Par exemple, pour utiliser le modèle Nomic Embed Text :
$ ollama pull nomic-embed-text
Exécutez ensuite vos modèles Ollama :
$ ollama serve
Maintenant que vous avez configuré votre environnement avec Python, Ollama, ChromaDB et d'autres dépendances, il est temps de créer votre application RAG locale personnalisée. Dans cette section, nous passerons en revue le code Python pratique et donnerons un aperçu de la façon de structurer votre application.
app.py
Il s'agit du fichier principal de l'application Flask. Il définit des itinéraires pour intégrer des fichiers dans la base de données vectorielles et récupérer la réponse du modèle.
import os from dotenv import load_dotenv load_dotenv() from flask import Flask, request, jsonify from embed import embed from query import query from get_vector_db import get_vector_db TEMP_FOLDER = os.getenv('TEMP_FOLDER', './_temp') os.makedirs(TEMP_FOLDER, exist_ok=True) app = Flask(__name__) @app.route('/embed', methods=['POST']) def route_embed(): if 'file' not in request.files: return jsonify({"error": "No file part"}), 400 file = request.files['file'] if file.filename == '': return jsonify({"error": "No selected file"}), 400 embedded = embed(file) if embedded: return jsonify({"message": "File embedded successfully"}), 200 return jsonify({"error": "File embedded unsuccessfully"}), 400 @app.route('/query', methods=['POST']) def route_query(): data = request.get_json() response = query(data.get('query')) if response: return jsonify({"message": response}), 200 return jsonify({"error": "Something went wrong"}), 400 if __name__ == '__main__': app.run(host="0.0.0.0", port=8080, debug=True)
embed.py
Ce module gère le processus d'intégration, y compris la sauvegarde des fichiers téléchargés, le chargement et le fractionnement des données, ainsi que l'ajout de documents à la base de données vectorielles.
import os from datetime import datetime from werkzeug.utils import secure_filename from langchain_community.document_loaders import UnstructuredPDFLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from get_vector_db import get_vector_db TEMP_FOLDER = os.getenv('TEMP_FOLDER', './_temp') # Function to check if the uploaded file is allowed (only PDF files) def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in {'pdf'} # Function to save the uploaded file to the temporary folder def save_file(file): # Save the uploaded file with a secure filename and return the file path ct = datetime.now() ts = ct.timestamp() filename = str(ts) + "_" + secure_filename(file.filename) file_path = os.path.join(TEMP_FOLDER, filename) file.save(file_path) return file_path # Function to load and split the data from the PDF file def load_and_split_data(file_path): # Load the PDF file and split the data into chunks loader = UnstructuredPDFLoader(file_path=file_path) data = loader.load() text_splitter = RecursiveCharacterTextSplitter(chunk_size=7500, chunk_overlap=100) chunks = text_splitter.split_documents(data) return chunks # Main function to handle the embedding process def embed(file): # Check if the file is valid, save it, load and split the data, add to the database, and remove the temporary file if file.filename != '' and file and allowed_file(file.filename): file_path = save_file(file) chunks = load_and_split_data(file_path) db = get_vector_db() db.add_documents(chunks) db.persist() os.remove(file_path) return True return False
query.py
Ce module traite les requêtes des utilisateurs en générant plusieurs versions de la requête, en récupérant les documents pertinents et en fournissant des réponses basées sur le contexte.
import os from langchain_community.chat_models import ChatOllama from langchain.prompts import ChatPromptTemplate, PromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough from langchain.retrievers.multi_query import MultiQueryRetriever from get_vector_db import get_vector_db LLM_MODEL = os.getenv('LLM_MODEL', 'mistral') # Function to get the prompt templates for generating alternative questions and answering based on context def get_prompt(): QUERY_PROMPT = PromptTemplate( input_variables=["question"], template="""You are an AI language model assistant. Your task is to generate five different versions of the given user question to retrieve relevant documents from a vector database. By generating multiple perspectives on the user question, your goal is to help the user overcome some of the limitations of the distance-based similarity search. Provide these alternative questions separated by newlines. Original question: {question}""", ) template = """Answer the question based ONLY on the following context: {context} Question: {question} """ prompt = ChatPromptTemplate.from_template(template) return QUERY_PROMPT, prompt # Main function to handle the query process def query(input): if input: # Initialize the language model with the specified model name llm = ChatOllama(model=LLM_MODEL) # Get the vector database instance db = get_vector_db() # Get the prompt templates QUERY_PROMPT, prompt = get_prompt() # Set up the retriever to generate multiple queries using the language model and the query prompt retriever = MultiQueryRetriever.from_llm( db.as_retriever(), llm, prompt=QUERY_PROMPT ) # Define the processing chain to retrieve context, generate the answer, and parse the output chain = ( {"context": retriever, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser() ) response = chain.invoke(input) return response return None
get_vector_db.py
Ce module initialise et renvoie l'instance de base de données vectorielle utilisée pour stocker et récupérer les intégrations de documents.
import os from langchain_community.embeddings import OllamaEmbeddings from langchain_community.vectorstores.chroma import Chroma CHROMA_PATH = os.getenv('CHROMA_PATH', 'chroma') COLLECTION_NAME = os.getenv('COLLECTION_NAME', 'local-rag') TEXT_EMBEDDING_MODEL = os.getenv('TEXT_EMBEDDING_MODEL', 'nomic-embed-text') def get_vector_db(): embedding = OllamaEmbeddings(model=TEXT_EMBEDDING_MODEL,show_progress=True) db = Chroma( collection_name=COLLECTION_NAME, persist_directory=CHROMA_PATH, embedding_function=embedding ) return db
Créez un fichier .env
pour stocker vos variables d'environnement :
TEMP_FOLDER = './_temp' CHROMA_PATH = 'chroma' COLLECTION_NAME = 'local-rag' LLM_MODEL = 'mistral' TEXT_EMBEDDING_MODEL = 'nomic-embed-text'
Exécutez le fichier app.py
pour démarrer votre serveur d'applications :
$ python3 app.py
Une fois le serveur exécuté, vous pouvez commencer à envoyer des requêtes aux points de terminaison suivants :
$ curl --request POST \ --url http://localhost:8080/embed \ --header 'Content-Type: multipart/form-data' \ --form file=@/Users/nassermaronie/Documents/Nasser-resume.pdf # Response { "message": "File embedded successfully" }
$ curl --request POST \ --url http://localhost:8080/query \ --header 'Content-Type: application/json' \ --data '{ "query": "Who is Nasser?" }' # Response { "message": "Nasser Maronie is a Full Stack Developer with experience in web and mobile app development. He has worked as a Lead Full Stack Engineer at Ulventech, a Senior Full Stack Engineer at Speedoc, a Senior Frontend Engineer at Irvins, and a Software Engineer at Tokopedia. His tech stacks include Typescript, ReactJS, VueJS, React Native, NodeJS, PHP, Golang, Python, MySQL, PostgresQL, MongoDB, Redis, AWS, Firebase, and Supabase. He has a Bachelor's degree in Information System from Universitas Amikom Yogyakarta." }
En suivant ces instructions, vous pouvez exécuter et interagir efficacement avec votre application RAG locale personnalisée à l'aide de Python, Ollama et ChromaDB, adaptée à vos besoins. Ajustez et développez les fonctionnalités si nécessaire pour améliorer les capacités de votre application.
En exploitant les capacités de déploiement local, vous protégez non seulement les informations sensibles, mais vous optimisez également les performances et la réactivité. Que vous souhaitiez améliorer les interactions avec les clients ou rationaliser les processus internes, une application RAG déployée localement offre flexibilité et robustesse pour s'adapter et évoluer avec vos besoins.
https://github.com/firstpersoncode/local-rag
Bon codage !