GPT4All est le ChatGPT Local pour vos Documents et c’est Gratuit !

GPT4All ChatGPT for Local Documents, Free!

Comment installer GPT4All sur votre ordinateur portable et interroger l’IA sur votre propre domaine de connaissance (vos documents)… et il fonctionne uniquement sur le processeur central (CPU) !

Dans cet article, nous allons apprendre comment déployer et utiliser le modèle GPT4All sur votre ordinateur CPU uniquement (j’utilise un MacBook Pro sans GPU !)

Dans cet article, nous allons installer GPT4All (un puissant LLM) sur notre ordinateur local et découvrir comment interagir avec nos documents avec python. Une collection de PDF ou d’articles en ligne sera la base de connaissances pour nos questions/réponses.

Qu’est-ce que GPT4All

D’après le site officiel de GPT4All, il est décrit comme un chatbot respectueux de la vie privée, gratuit et fonctionnant localement. Aucun GPU ou internet requis.

GTP4All est un écosystème pour entraîner et déployer des modèles de langage puissants et personnalisés qui s’exécutent localement sur des CPU grand public.

Notre modèle GPT4All est un fichier de 4 Go que vous pouvez télécharger et brancher dans le logiciel d’écosystème open source GPT4All. Nomic AI facilite les écosystèmes logiciels de haute qualité et sécurisés, stimulant les efforts visant à permettre aux particuliers et aux organisations de former et de mettre en œuvre facilement leurs propres grands modèles de langage localement.

Comment ça va marcher ?

Le processus est vraiment simple (quand vous le connaissez) et peut être répété avec d’autres modèles aussi. Les étapes sont les suivantes :

  • charger le modèle GPT4All
  • utiliser Langchain pour récupérer nos documents et les charger
  • diviser les documents en petits morceaux digestibles par Embeddings
  • utiliser FAISS pour créer notre base de données vectorielle avec les embeddings
  • effectuer une recherche de similarité (recherche sémantique) sur notre base de données vectorielle en fonction de la question que nous voulons passer à GPT4All : cela sera utilisé comme contexte pour notre question
  • alimenter la question et le contexte à GPT4All avec Langchain et attendre la réponse.

Ce dont nous avons besoin, ce sont des Embeddings. Un embedding est une représentation numérique d’une information, par exemple, du texte, des documents, des images, de l’audio, etc. La représentation capture la signification sémantique de ce qui est intégré, et c’est exactement ce dont nous avons besoin. Pour ce projet, nous ne pouvons pas nous fier à des modèles GPU lourds : nous téléchargerons donc le modèle natif Alpaca et utiliserons à partir de Langchain le LlamaCppEmbeddings. Ne vous inquiétez pas ! Tout est expliqué étape par étape.

Commençons à coder

Créer un environnement virtuel

Créez un nouveau dossier pour votre nouveau projet Python, par exemple GPT4ALL_Fabio (mettez votre nom…) :

mkdir GPT4ALL_Fabio
cd GPT4ALL_Fabio

Ensuite, créez un nouvel environnement virtuel Python. Si vous avez plus d’une version de python installée, spécifiez votre version souhaitée : dans ce cas, j’utiliserai mon installation principale, associée à python 3.10.

python3 -m venv .venv

La commande python3 -m venv .venv crée un nouvel environnement virtuel nommé .venv (le point créera un répertoire caché appelé venv).

Un environnement virtuel fournit une installation Python isolée, ce qui vous permet d’installer des packages et des dépendances uniquement pour un projet spécifique sans affecter l’installation Python à l’échelle du système ou d’autres projets. Cette isolation contribue à maintenir la cohérence et à prévenir les conflits potentiels entre les exigences de différents projets.

Une fois que l’environnement virtuel est créé, vous pouvez l’activer en utilisant la commande suivante :

source .venv/bin/activate

Les bibliothèques à installer

Pour le projet que nous construisons, nous n’avons pas besoin de trop de packages. Nous avons seulement besoin de :

  • des liaisons python pour GPT4All
  • Langchain pour interagir avec nos documents

LangChain est un framework pour développer des applications alimentées par des modèles de langage. Il vous permet non seulement d’appeler un modèle de langage via une API, mais également de connecter un modèle de langage à d’autres sources de données et de permettre à un modèle de langage d’interagir avec son environnement.

pip install pygpt4all==1.0.1
pip install pyllamacpp==1.0.6
pip install langchain==0.0.149
pip install unstructured==0.6.5
pip install pdf2image==1.16.3
pip install pytesseract==0.3.10
pip install pypdf==3.8.1
pip install faiss-cpu==1.7.4

Pour LangChain, vous remarquerez que nous avons également spécifié la version. Cette bibliothèque reçoit récemment de nombreuses mises à jour, donc pour être certain que notre configuration fonctionnera également demain, il est préférable de spécifier une version qui fonctionne bien. Unstructured est une dépendance requise pour le chargeur de PDF et pytesseract et pdf2image également.

REMARQUE : sur le dépôt GitHub, il y a un fichier requirements.txt (suggéré par jl adcr) avec toutes les versions associées à ce projet. Vous pouvez effectuer l’installation en une seule fois, après l’avoir téléchargé dans le répertoire principal du projet avec la commande suivante :

pip install -r requirements.txt

À la fin de l’article, j’ai créé une section pour le dépannage. Le repo GitHub a également un fichier READ.ME mis à jour avec toutes ces informations.

Gardez à l’esprit que certaines bibliothèques ont des versions disponibles en fonction de la version de python que vous utilisez dans votre environnement virtuel.

Télécharger les modèles sur votre PC

C’est une étape vraiment importante.

Pour le projet, nous avons certainement besoin de GPT4All. Le processus décrit sur Nomic AI est vraiment compliqué et nécessite du matériel que nous n’avons pas tous (comme moi). Voici donc le lien vers le modèle déjà converti et prêt à être utilisé. Il suffit de cliquer sur télécharger.

Comme décrit brièvement dans l’introduction, nous avons également besoin du modèle pour les embeddings, un modèle que nous pouvons exécuter sur notre CPU sans écraser. Cliquez sur le lien ici pour télécharger alpaca-native-7B-ggml déjà converti en 4 bits et prêt à être utilisé pour agir comme notre modèle pour l’embedding.

Pourquoi avons-nous besoin d’embeddings ? Si vous vous souvenez du diagramme de flux, la première étape requise, après avoir collecté les documents pour notre base de connaissances, est de les incorporer. Les embeddings LLamaCPP de ce modèle Alpaca conviennent parfaitement à cette tâche et ce modèle est également assez petit (4 Go). Au fait, vous pouvez également utiliser le modèle Alpaca pour votre QnA !

Mise à jour 2023.05.25 : de nombreux utilisateurs de Windows rencontrent des problèmes pour utiliser les embeddings llamaCPP. Cela se produit principalement parce que lors de l’installation du package python llama-cpp-python avec :

pip install llama-cpp-python

le package pip va compiler à partir de la source la bibliothèque. Windows n’a généralement pas CMake ou le compilateur C installé par défaut sur la machine. Mais ne vous inquiétez pas, il y a une solution.

Lors de l’installation de llama-cpp-python, requis par LangChain avec les embeddings llama, sur Windows, CMake C compiler n’est pas installé par défaut, vous ne pouvez donc pas compiler à partir de la source.

Sous Mac, avec Xtools et sous Linux, le compilateur C est généralement déjà disponible sur le système d’exploitation.

Pour éviter ce problème, vous DEVEZ utiliser une roue compilée préalablement.

Allez ici https://github.com/abetlen/llama-cpp-python/releases

et cherchez la roue compilée pour votre architecture et votre version de python — vous DEVEZ prendre la version Weels 0.1.49 car les versions supérieures ne sont pas compatibles.

Dans mon cas, j’ai Windows 10, 64 bits, python 3.10

donc mon fichier est llama_cpp_python-0.1.49-cp310-cp310-win_amd64.whl

Ce problème est suivi sur le dépôt GitHub

Après avoir téléchargé, vous devez mettre les deux modèles dans le répertoire models, comme indiqué ci-dessous.

Interaction de base avec GPT4All

Puisque nous voulons avoir le contrôle de notre interaction avec le modèle GPT, nous devons créer un fichier Python (appelons-le pygpt4all_test.py), importer les dépendances et donner les instructions au modèle. Vous verrez que c’est assez facile.

from pygpt4all.models.gpt4all import GPT4All

Ceci est la liaison Python pour notre modèle. Maintenant, nous pouvons l’appeler et commencer à poser des questions. Essayons quelque chose de créatif.

Nous créons une fonction qui lit le rappel du modèle, et nous demandons à GPT4All de compléter notre phrase.

def new_text_callback(text):
    print(text, end="")

model = GPT4All('./models/gpt4all-converted.bin')
model.generate("Il était une fois, ", n_predict=55, new_text_callback=new_text_callback)

La première instruction indique à notre programme où trouver le modèle (rappelez-vous ce que nous avons fait dans la section ci-dessus)

La deuxième instruction demande au modèle de générer une réponse et de compléter notre prompt “Il était une fois,”.

Pour l’exécuter, assurez-vous que l’environnement virtuel est toujours activé et exécutez simplement :

python3 pygpt4all_test.py

Vous devriez voir un texte de chargement du modèle et la complétion de la phrase. Selon les ressources matérielles de votre ordinateur, cela peut prendre un peu de temps.

Le résultat peut être différent du vôtre… Mais pour nous, l’important est que cela fonctionne et que nous puissions passer à LangChain pour créer des choses plus avancées.

REMARQUE (mise à jour le 23 mai 2023) : si vous rencontrez une erreur liée à pygpt4all, vérifiez la section de dépannage sur ce sujet avec la solution donnée par Rajneesh Aggarwal ou par Oscar Jeong.

Modèle de chaîne de langage sur GPT4All

Le cadre LangChain est une bibliothèque vraiment étonnante. Il fournit des composants pour travailler avec des modèles de langage de manière facile à utiliser, et il fournit également des chaînes. Les chaînes peuvent être considérées comme l’assemblage de ces composants de manière particulière pour accomplir au mieux un cas d’utilisation particulier. Elles sont destinées à être une interface de niveau supérieur à travers laquelle les gens peuvent facilement commencer avec un cas d’utilisation spécifique. Ces chaînes sont également conçues pour être personnalisables.

Dans notre prochain test Python, nous utiliserons un modèle de prompt. Les modèles de langage prennent du texte en entrée – ce texte est couramment appelé un prompt. En général, ce n’est pas simplement une chaîne codée en dur, mais plutôt une combinaison d’un modèle, de quelques exemples et de l’entrée de l’utilisateur. LangChain fournit plusieurs classes et fonctions pour faciliter la construction et le travail avec des prompts. Voyons comment nous pouvons le faire.

Créez un nouveau fichier Python et appelez-le my_langchain.py

# Importez le modèle de prompt et de chaîne Langchain
from langchain import PromptTemplate, LLMChain

# Importez llm pour pouvoir interagir directement avec GPT4All depuis LangChain
from langchain.llms import GPT4All

# Le gestionnaire de rappels est requis pour la gestion des réponses
from langchain.callbacks.base import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

local_path = './models/gpt4all-converted.bin' 
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])

Nous avons importé à partir de LangChain le modèle de prompt et de chaîne et la classe llm GPT4All pour pouvoir interagir directement avec notre modèle GPT.

Ensuite, après avoir défini notre chemin llm (comme nous l’avons fait auparavant), nous instancions les gestionnaires de rappel afin de pouvoir capturer les réponses à notre requête.

Créer un modèle est vraiment facile : en suivant le tutoriel de la documentation, nous pouvons utiliser quelque chose comme ceci…

template = """Question: {question}

Answer: Let's think step by step on it.

"""
prompt = PromptTemplate(template=template, input_variables=["question"])

La variable template est une chaîne multi-ligne qui contient notre structure d’interaction avec le modèle : entre les accolades, nous insérons les variables externes au modèle, dans notre scénario, c’est notre question.

Comme c’est une variable, vous pouvez décider s’il s’agit d’une question codée en dur ou d’une question de saisie utilisateur : voici les deux exemples.

# Question codée en dur
question = "Quel pilote de Formule 1 a remporté le championnat l'année de naissance de Leonardo di Caprio ?"

# Question de saisie utilisateur...
question = input("Entrez votre question : ")

Pour notre test, nous commenterons la question de saisie utilisateur. Maintenant, nous devons simplement lier notre modèle de langue, notre modèle et notre modèle de langue.

template = """Question : {question}
Réponse : Réfléchissons-y étape par étape.
"""

prompt = PromptTemplate(template=template, input_variables=["question"])

# initialiser l'instance GPT4All
llm = GPT4All(model=local_path, callback_manager=callback_manager, verbose=True)

# lier le modèle de langue avec notre modèle de prompt
llm_chain = LLMChain(prompt=prompt, llm=llm)

# Question codée en dur
question = "Quel pilote de Formule 1 a remporté le championnat l'année de naissance de Leonardo di Caprio ?"

# Question de saisie utilisateur...
# question = input("Entrez votre question : ")

#Exécuter la requête et obtenir les résultats
llm_chain.run(question)

N’oubliez pas de vérifier que votre environnement virtuel est toujours activé et d’exécuter la commande :

python3 my_langchain.py

Vous pouvez obtenir des résultats différents des miens. Ce qui est incroyable, c’est que vous pouvez voir tout le raisonnement suivi par GPT4All pour essayer de vous donner une réponse. En ajustant la question, vous pouvez obtenir de meilleurs résultats.

Langchain avec modèle de prompt sur GPT4All

Répondre aux questions sur vos documents en utilisant LangChain et GPT4All

Ici, nous commençons la partie incroyable, car nous allons parler à nos documents en utilisant GPT4All comme un chatbot qui répond à nos questions.

La séquence d’étapes, en référence au flux de travail du QnA avec GPT4All, consiste à charger nos fichiers PDF, à les découper en morceaux. Ensuite, nous aurons besoin d’un Vector Store pour nos embeddings. Nous devons alimenter nos documents découpés dans un Vector Store pour la récupération d’informations, puis nous allons les intégrer ensemble avec la recherche de similarité sur cette base de données comme contexte pour notre requête LLM.

Pour cela, nous allons utiliser FAISS directement à partir de la bibliothèque Langchain. FAISS est une bibliothèque open-source de Facebook AI Research, conçue pour trouver rapidement des éléments similaires dans de grandes collections de données multidimensionnelles. Il offre des méthodes d’indexation et de recherche pour faciliter et accélérer la détection des éléments les plus similaires dans un ensemble de données. C’est particulièrement pratique pour nous car cela simplifie la récupération d’informations et nous permet de sauvegarder localement la base de données créée : cela signifie qu’après la première création, elle sera chargée très rapidement pour toute utilisation ultérieure.

Création de la base de données d’index de vecteurs

Créez un nouveau fichier et appelez-le my_knowledge_qna.py

from langchain import PromptTemplate, LLMChain
from langchain.llms import GPT4All
from langchain.callbacks.base import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

# fonction pour ne charger que des fichiers TXT
from langchain.document_loaders import TextLoader

# séparateur de texte pour créer des morceaux
from langchain.text_splitter import RecursiveCharacterTextSplitter

# pour pouvoir charger les fichiers pdf
from langchain.document_loaders import UnstructuredPDFLoader
from langchain.document_loaders import PyPDFLoader
from langchain.document_loaders import DirectoryLoader

# Vector Store Index pour créer notre base de données sur notre savoir
from langchain.indexes import VectorstoreIndexCreator

# Embeddings LLamaCpp du modèle Alpaca
from langchain.embeddings import LlamaCppEmbeddings

# Bibliothèque FAISS pour la recherche de similarité
from langchain.vectorstores.faiss import FAISS

import os  #pour l'interaction avec les fichiers
import datetime

Les premières bibliothèques sont les mêmes que celles que nous avons utilisées précédemment : en plus, nous utilisons Langchain pour la création d’index de Vector Store, les embeddings LlamaCpp pour interagir avec notre modèle Alpaca (quantifié à 4 bits et compilé avec la bibliothèque cpp) et le chargeur de PDF.

Chargeons également nos modèles de langue avec leurs propres chemins : un pour les embeddings et un pour la génération de texte.

# assigner le chemin pour les 2 modèles GPT4All et Alpaca pour les embeddings
gpt4all_path = './models/gpt4all-converted.bin'
llama_path = './models/ggml-model-q4_0.bin'
# Gestionnaire de rappel pour gérer les appels avec le modèle
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])

# créer l'objet d'embedding
embeddings = LlamaCppEmbeddings(model_path=llama_path)
# créer l'objet llm GPT4All
llm = GPT4All(model=gpt4all_path, callback_manager=callback_manager, verbose=True)

Pour le test, voyons si nous avons réussi à lire tous les fichiers pfd: la première étape consiste à déclarer 3 fonctions à utiliser sur chaque document individuel. La première consiste à diviser le texte extrait en morceaux, la deuxième consiste à créer l’indice de vecteur avec les métadonnées (comme les numéros de page, etc…) et la dernière sert à tester la recherche de similarité (je vais expliquer mieux plus tard).

# Diviser le texte
def split_chunks(sources):
    chunks = []
    splitter = RecursiveCharacterTextSplitter(chunk_size=256, chunk_overlap=32)
    for chunk in splitter.split_documents(sources):
        chunks.append(chunk)
    return chunks


def create_index(chunks):
    texts = [doc.page_content for doc in chunks]
    metadatas = [doc.metadata for doc in chunks]

    search_index = FAISS.from_texts(texts, embeddings, metadatas=metadatas)

    return search_index


def similarity_search(query, index):
    # k est le nombre de similarités recherchées qui correspondent à la requête
    # par défaut, c'est 4
    matched_docs = index.similarity_search(query, k=3) 
    sources = []
    for doc in matched_docs:
        sources.append(
            {
                "page_content": doc.page_content,
                "metadata": doc.metadata,
            }
        )

    return matched_docs, sources

Maintenant, nous pouvons tester la génération d’index pour les documents dans le répertoire docs: nous devons y mettre tous nos pdfs. Langchain a également une méthode pour charger le dossier entier, indépendamment du type de fichier: comme le post-traitement est compliqué, je le couvrirai dans l’article suivant sur les modèles LaMini.

mon dossier docs contient 4 fichiers pdf

Nous appliquerons nos fonctions au premier document de la liste

# obtenir la liste des fichiers pdf du répertoire docs sous forme de liste
pdf_folder_path = './docs'
doc_list = [s for s in os.listdir(pdf_folder_path) if s.endswith('.pdf')]
num_of_docs = len(doc_list)
# créer un chargeur pour les PDF à partir du chemin
loader = PyPDFLoader(os.path.join(pdf_folder_path, doc_list[0]))
# charger les documents avec Langchain
docs = loader.load()
# Diviser en morceaux
chunks = split_chunks(docs)
# créer l'index de vecteur db
db0 = create_index(chunks)

Dans les premières lignes, nous utilisons la bibliothèque os pour obtenir la liste des fichiers pdf à l’intérieur du répertoire docs. Nous chargeons ensuite le premier document ( doc_list [0] ) du dossier docs avec Langchain, le divisons en morceaux et créons ensuite la base de données vectorielle avec les embeddings LLama.

Comme vous l’avez vu, nous utilisons la méthode pyPDF. Celle-ci est un peu plus longue à utiliser, car vous devez charger les fichiers un par un, mais le chargement des PDF à l’aide de pypdf en tableau de documents vous permet d’avoir un tableau où chaque document contient le contenu de la page et les métadonnées avec le numéro de page. C’est vraiment pratique lorsque vous voulez savoir les sources du contexte que nous donnerons à GPT4All avec notre requête. Voici l’exemple de la documentation de Langchain:

Capture d’écran de la documentation de Langchain

Nous pouvons exécuter le fichier python avec la commande depuis le terminal:

python3 my_knowledge_qna.py

Après le chargement du modèle pour les embeddings, vous verrez les tokens au travail pour l’indexation: ne paniquez pas car cela prendra du temps, surtout si vous n’utilisez que le CPU, comme moi (cela a pris 8 minutes).

Achèvement de la première base de données vectorielle

Comme je l’expliquais, la méthode pyPDF est plus lente mais nous donne des données supplémentaires pour la recherche de similarité. Pour parcourir tous nos fichiers, nous utiliserons une méthode pratique de FAISS qui nous permet de FUSIONNER différentes bases de données ensemble. Ce que nous faisons maintenant, c’est que nous utilisons le code ci-dessus pour générer la première base de données (nous l’appellerons db0) et avec une boucle for, nous créons l’index du fichier suivant dans la liste et le fusionnons immédiatement avec db0.

Voici le code: notez que j’ai ajouté des journaux pour vous donner l’état de la progression en utilisant datetime.datetime.now() et en imprimant la différence de temps de fin et de début pour calculer combien de temps a duré l’opération (vous pouvez le supprimer si vous ne l’aimez pas).

Les instructions de fusion sont comme ceci:

# fusionner dbi avec la base de données db0 existante
db0.merge_from(dbi)

Une des dernières instructions est pour sauvegarder notre base de données localement: la génération entière peut prendre même des heures (dépend du nombre de documents que vous avez) donc c’est vraiment bien que nous devions le faire une seule fois!

# Enregistrer la base de données localement
db0.save_local("my_faiss_index")

Voici tout le code. Nous commenterons beaucoup de parties de celui-ci lorsque nous interagirons avec GPT4All en chargeant l’index directement depuis notre dossier.

# obtenir la liste des fichiers pdf du répertoire docs dans un format de liste
pdf_folder_path = './docs'
doc_list = [s for s in os.listdir(pdf_folder_path) if s.endswith('.pdf')]
num_of_docs = len(doc_list)
# créer un chargeur pour les PDF à partir du chemin
general_start = datetime.datetime.now() #non utilisé maintenant mais utile
print("démarrage de la boucle...")
loop_start = datetime.datetime.now() #non utilisé maintenant mais utile
print("génération de la première base de données vectorielle et puis itération avec .merge_from")
loader = PyPDFLoader(os.path.join(pdf_folder_path, doc_list[0]))
docs = loader.load()
chunks = split_chunks(docs)
db0 = create_index(chunks)
print("Base de données vectorielle principale créée. Début de l'itération et de la fusion...")
for i in range(1,num_of_docs):
    print(doc_list[i])
    print(f"position de la boucle {i}")
    loader = PyPDFLoader(os.path.join(pdf_folder_path, doc_list[i]))
    start = datetime.datetime.now() #non utilisé maintenant mais utile
    docs = loader.load()
    chunks = split_chunks(docs)
    dbi = create_index(chunks)
    print("démarrage de la fusion avec db0...")
    db0.merge_from(dbi)
    end = datetime.datetime.now() #non utilisé maintenant mais utile
    elapsed = end - start #non utilisé maintenant mais utile
    #temps total
    print(f"terminé en {elapsed}")
    print("-----------------------------------")
loop_end = datetime.datetime.now() #non utilisé maintenant mais utile
loop_elapsed = loop_end - loop_start #non utilisé maintenant mais utile
print(f"Tous les documents ont été traités en {loop_elapsed}")
print(f"La base de données est terminée avec {num_of_docs} sous-ensemble d'index de db")
print("-----------------------------------")
print(f"Fusion terminée")
print("-----------------------------------")
print("Enregistrement de la base de données fusionnée localement")
# Enregistrer la base de données localement
db0.save_local("my_faiss_index")
print("-----------------------------------")
print("base de données fusionnée enregistrée sous le nom de my_faiss_index")
general_end = datetime.datetime.now() #non utilisé maintenant mais utile
general_elapsed = general_end - general_start #non utilisé maintenant mais utile
print(f"Tout l'indexation est terminée en {general_elapsed}")
print("-----------------------------------")

L’exécution du fichier python a pris 22 minutes

Poser des questions à GPT4All sur vos documents

Nous y sommes. Nous avons notre index, nous pouvons le charger et avec un modèle de prompt, nous pouvons demander à GPT4All de répondre à nos questions. Nous commençons par une question codée en dur, puis nous bouclerons à travers nos questions d’entrée.

Placez le code suivant dans un fichier python db_loading.py et exécutez-le avec la commande python3 db_loading.py dans le terminal.

from langchain import PromptTemplate, LLMChain
from langchain.llms import GPT4All
from langchain.callbacks.base import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
# fonction pour charger uniquement les fichiers TXT
from langchain.document_loaders import TextLoader
# diviseur de texte pour créer des morceaux
from langchain.text_splitter import RecursiveCharacterTextSplitter
# pour pouvoir charger les fichiers pdf
from langchain.document_loaders import UnstructuredPDFLoader
from langchain.document_loaders import PyPDFLoader
from langchain.document_loaders import DirectoryLoader
# Index de Vector Store pour créer notre base de données sur notre connaissance
from langchain.indexes import VectorstoreIndexCreator
# Incrustations LLamaCpp du modèle Alpaca
from langchain.embeddings import LlamaCppEmbeddings
# bibliothèque FAISS pour la recherche de similarité
from langchain.vectorstores.faiss import FAISS
import os  # pour l'interaction avec les fichiers
import datetime

# TEST DE RECHERCHE DE SIMILARITÉ

# attribuer le chemin pour les 2 modèles GPT4All et Alpaca pour les incrustations 
gpt4all_path = './models/gpt4all-converted.bin' 
llama_path = './models/ggml-model-q4_0.bin' 
# Gestionnaire de rappels pour gérer les appels avec le modèle
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])

# créer l'objet d'incrustation
embeddings = LlamaCppEmbeddings(model_path=llama_path)
# créer l'objet llm GPT4All
llm = GPT4All(model=gpt4all_path, callback_manager=callback_manager, verbose=True)

# Diviser le texte
def split_chunks(sources):
    chunks = []
    splitter = RecursiveCharacterTextSplitter(chunk_size=256, chunk_overlap=32)
    for chunk in splitter.split_documents(sources):
        chunks.append(chunk)
    return chunks


def create_index(chunks):
    texts = [doc.page_content for doc in chunks]
    metadatas = [doc.metadata for doc in chunks]

    search_index = FAISS.from_texts(texts, embeddings, metadatas=metadatas)

    return search_index


def similarity_search(query, index):
    # k est le nombre de recherche de similarité qui correspond à la requête
    # par défaut est 4
    matched_docs = index.similarity_search(query, k=3) 
    sources = []
    for doc in matched_docs:
        sources.append(
            {
                "page_content": doc.page_content,
                "metadata": doc.metadata,
            }
        )

    return matched_docs, sources

# Charger notre index vectoriel local
index = FAISS.load_local("my_faiss_index", embeddings)
# Question codée en dur
query = "Qu'est-ce qu'un PLC et quelle est la différence avec un PC"
docs = index.similarity_search(query)
# Obtenir les 3 meilleurs résultats correspondants - défini dans la fonction k=3
print(f"La question est: {query}")
print("Voici le résultat de la recherche sémantique sur l'index, sans GPT4All..")
print(docs[0])

Le texte imprimé est la liste des 3 sources qui correspondent le mieux à la requête, nous donnant également le nom du document et le numéro de page.

Maintenant, nous pouvons utiliser la recherche de similarité comme contexte pour notre requête en utilisant le modèle de prompt. Après les 3 fonctions, remplacez tout le code par ce qui suit:

# Chargez notre base de données de vecteurs d'index locaux
index = FAISS.load_local("my_faiss_index", embeddings)

# créer le modèle de prompt
template = """
Veuillez utiliser le contexte suivant pour répondre aux questions.
Contexte: {contexte}
---
Question: {question}
Réponse: Réfléchissons étape par étape."""

# Question codée en dur
question = "Qu'est-ce qu'un PLC et quelle est la différence avec un PC"
matched_docs, sources = similarity_search(question, index)
# Création du contexte
contexte = "\n".join([doc.page_content for doc in matched_docs])
# instanciation du modèle de prompt et de la chaîne GPT4All
prompt = PromptTemplate(template=template, input_variables=["contexte", "question"]).partial(contexte=contexte)
llm_chain = LLMChain(prompt=prompt, llm=llm)
# Afficher le résultat
print(llm_chain.run(question))

Après l’exécution, vous obtiendrez un résultat comme celui-ci (mais qui peut varier). Incroyable, n’est-ce pas ?

Veuillez utiliser le contexte suivant pour répondre aux questions.
Context: 1. Qu'est-ce qu'un PLC
2. Où et pourquoi est-il utilisé
3. Comment un PLC est-il différent d'un PC
Le PLC est particulièrement important dans les industries où la sécurité et la fiabilité sont essentielles, comme les usines de fabrication, les usines chimiques et les centrales électriques.
Comment un PLC est-il différent d'un PC
Parce qu'un PLC est un ordinateur spécialisé utilisé dans des applications industrielles et de fabrication pour contrôler les machines et les processus, les composants matériels d'un PLC typique doivent être capables d'interagir avec des dispositifs industriels. Ainsi, le matériel d'un PLC typique comprend :
---
Question: Qu'est-ce qu'un PLC et quelle est la différence avec un PC
Réponse: Réfléchissons étape par étape. 1) Un contrôleur logique programmable (PLC), également appelé système de contrôle industriel (ICS), fait référence à un ordinateur industriel qui contrôle divers processus automatisés tels que des machines de fabrication/lignes d'assemblage, etc., grâce à des capteurs et des actionneurs connectés à celui-ci via des entrées et sorties. Il s'agit d'une forme d'ordinateurs numériques qui a la capacité d'exécution de plusieurs instructions (MIE), de registres de mémoire intégrés utilisés par des routines logicielles, des cartes d'interface d'entrée/sortie (IOC) pour communiquer avec d'autres dispositifs électroniquement/numériquement via des réseaux ou des bus, etc.
2). Un contrôleur logique programmable est largement utilisé dans l'automatisation industrielle car il a la capacité d'exécution de plusieurs instructions. Il peut effectuer des tâches automatiquement et des instructions programmées, ce qui lui permet d'effectuer des opérations complexes qui dépassent la capacité d'un ordinateur personnel (PC). Ainsi, un ICS/PLC contient des registres de mémoire intégrés utilisés par des routines logicielles ou des codes de microprogramme, etc., mais un PC ne les contient pas, donc ils ont besoin d'interfaces externes telles que des disques durs (HDD), des ports USB, des protocoles de communication série et parallèle pour stocker des données pour une analyse ultérieure ou la génération de rapports.

Si vous voulez qu’une question saisie par l’utilisateur remplace la ligne

question = "Qu'est-ce qu'un PLC et quelle est la différence avec un PC"

par quelque chose comme ceci:

question = input("Votre question : ")

Conclusions

Il est temps pour vous d’expérimenter. Posez différentes questions sur tous les sujets liés à vos documents et voyez les résultats. Il y a une grande marge de progression, notamment sur le prompt et le modèle : vous pouvez jeter un coup d’œil ici pour trouver de l’inspiration. Mais la documentation de Langchain est vraiment incroyable (j’ai pu la suivre !!).

Vous pouvez suivre le code de l’article ou le vérifier sur mon repo github.

Fabio Matricardi, éducateur, enseignant, ingénieur et passionné d’apprentissage. Il enseigne depuis 15 ans à de jeunes étudiants, et maintenant il forme de nouveaux employés chez Key Solution Srl. Il a commencé sa carrière d’ingénieur en automatisation industrielle en 2010. Passionné de programmation depuis son adolescence, il a découvert la beauté de la création de logiciels et d’interfaces homme-machine pour donner vie à quelque chose. Enseigner et coacher fait partie de sa routine quotidienne, tout comme étudier et apprendre comment être un leader passionné avec des compétences de gestion à jour. Rejoignez-moi dans le voyage vers une meilleure conception, une intégration de système prédictive en utilisant l’apprentissage automatique et l’intelligence artificielle tout au long du cycle de vie de l’ingénierie.

Original. Reposté avec permission.

We will continue to update IPGirl; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Informatique

Chattanooga plante des graines quantiques.

Chattanooga, TN, ouvrira le premier réseau quantique commercialement disponible aux États-Unis d'ici la fin du mois p...

AI

Système ML basé sur la lumière pourrait donner des LLMs plus puissants et efficaces

Une équipe de chercheurs a mis au point un système d'apprentissage automatique basé sur la lumière qui pourrait surpa...

AI

Les agents d'intelligence artificielle personnalisés sont là. Le monde est-il prêt pour eux?

L'ère des assistants autonomes d'intelligence artificielle pourrait avoir d'énormes implications.

AI

Les chercheurs de Meta AI présentent un nouveau modèle d'IA pour critiquer les générations de grands modèles de langage.

La capacité des grands modèles de langage (LLM) à générer un texte cohérent, contextuellement pertinent et sémantique...