<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Vector DB on kenji.blog</title><link>http://kenji.blog/fr/tags/vector-db/</link><description>Recent content in Vector DB on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 13:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/fr/tags/vector-db/index.xml" rel="self" type="application/rss+xml"/><item><title>【Introduction à l'implémentation de RAG】 Comment faire lire vos propres documents à une 'IA locale'</title><link>http://kenji.blog/fr/p/rag-local-ai-implementation-guide/</link><pubDate>Fri, 11 Sep 2026 13:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/rag-local-ai-implementation-guide/</guid><description>&lt;img src="http://kenji.blog/p/rag-local-ai-implementation-guide/img/eyecatch.jpg" alt="Featured image of post 【Introduction à l'implémentation de RAG】 Comment faire lire vos propres documents à une 'IA locale'" />&lt;h1 id="introduction">Introduction
&lt;/h1>&lt;p>Ces dernières années, l&amp;rsquo;évolution des grands modèles de langage (LLM) a été remarquable, et de nombreuses IA telles que ChatGPT et Claude ont imprégné nos vies et nos entreprises. Cependant, les LLM généraux présentent une faiblesse évidente. Ils ne connaissent que les « informations publiques au moment de leur entraînement ». Naturellement, ils ne peuvent pas répondre aux questions concernant des « documents privés » tels que les règlements internes d&amp;rsquo;une entreprise, les notes personnelles ou les documents de projets non publiés. Si vous essayez de les forcer à répondre, le risque qu&amp;rsquo;ils génèrent des mensonges plausibles qui ne correspondent pas aux faits (hallucinations) augmente considérablement.&lt;/p>
&lt;p>C&amp;rsquo;est pourquoi l&amp;rsquo;architecture technologique appelée &lt;strong>RAG (Retrieval-Augmented Generation : Génération Augmentée par la Recherche)&lt;/strong> connaît actuellement une diffusion explosive dans le monde entier. L&amp;rsquo;utilisation du RAG permet de fournir dynamiquement des connaissances propres au LLM à partir d&amp;rsquo;une base de données externe, ce qui lui permet de générer des réponses précises et fondées.&lt;/p>
&lt;p>De plus, lors du traitement d&amp;rsquo;informations confidentielles d&amp;rsquo;entreprise ou personnelles, l&amp;rsquo;envoi de données à des API basées sur le cloud telles qu&amp;rsquo;OpenAI est souvent inacceptable du point de vue de la politique de sécurité. C&amp;rsquo;est là qu&amp;rsquo;intervient la construction d&amp;rsquo;un « RAG local » combiné à une &lt;strong>IA locale&lt;/strong> (un LLM qui fonctionne entièrement sur votre propre PC ou serveur sur site).&lt;/p>
&lt;p>Dans cet article, nous expliquerons en détail la théorie de base du RAG, les méthodes concrètes d&amp;rsquo;implémentation d&amp;rsquo;un RAG local avec Python, le contexte mathématique (le fonctionnement de la recherche vectorielle) et les techniques avancées pour faire fonctionner le système en production.&lt;/p>
&lt;hr>
&lt;h1 id="1-architecture-globale-du-rag">1. Architecture globale du RAG
&lt;/h1>&lt;p>Le RAG n&amp;rsquo;est pas un modèle d&amp;rsquo;IA unique, mais une architecture système dans laquelle plusieurs composants collaborent. Il se compose principalement de deux phases : la « phase d&amp;rsquo;ingestion (importation des données) » et la « phase de recherche et de génération (Retrieval &amp;amp; Generation) ».&lt;/p>
&lt;p>Le diagramme Mermaid ci-dessous montre la vue d&amp;rsquo;ensemble du système RAG.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Phase d'ingestion (Préparation)"
Doc["Documents propres (PDF, TXT, etc.)"] --> Loader["Chargeur de documents"]
Loader --> Splitter["Division du texte (Chunking)"]
Splitter --> EmbedModel1["Modèle de plongement (Embedding)"]
EmbedModel1 --> VectorDB["Base de données vectorielle"]
end
subgraph "Phase d'inférence (Lors de la requête de l'utilisateur)"
User["Question de l'utilisateur (Requête)"] --> EmbedModel2["Modèle de plongement (Embedding)"]
EmbedModel2 --> QueryVector["Vecteur de requête"]
QueryVector --> Search["Recherche de similarité (Recherche vectorielle)"]
VectorDB --> Search
Search --> Context["Extraction des morceaux pertinents (Contexte)"]
User --> PromptBuilder["Construction du prompt"]
Context --> PromptBuilder
PromptBuilder --> LocalLLM["LLM local"]
LocalLLM --> Answer["Génération de la réponse finale"]
end&lt;/div>
&lt;h2 id="phase-dingestion-préparation">Phase d&amp;rsquo;ingestion (Préparation)
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>Chargement des documents&lt;/strong> : Chargez des données non structurées telles que des PDF, des documents Word, des fichiers texte, etc.&lt;/li>
&lt;li>&lt;strong>Chunking (Division du texte)&lt;/strong> : Divisez les textes longs en blocs significatifs (chunks) pour les adapter à la limite d&amp;rsquo;entrée (fenêtre de contexte) du LLM et pour améliorer la précision de la recherche.&lt;/li>
&lt;li>&lt;strong>Embedding (Vectorisation)&lt;/strong> : Entrez les chunks divisés dans un modèle de plongement (Embedding Model) et convertissez-les en un tableau de nombres (vecteur) de plusieurs centaines à plusieurs milliers de dimensions.&lt;/li>
&lt;li>&lt;strong>Enregistrement dans la base de données&lt;/strong> : Enregistrez les vecteurs convertis et les données textuelles d&amp;rsquo;origine associées dans une base de données vectorielle (Vector DB).&lt;/li>
&lt;/ol>
&lt;h2 id="phase-dinférence-lors-de-lexécution">Phase d&amp;rsquo;inférence (Lors de l&amp;rsquo;exécution)
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>Vectorisation de la requête&lt;/strong> : Vectorisez la question de l&amp;rsquo;utilisateur en utilisant le même modèle de plongement que celui de la préparation.&lt;/li>
&lt;li>&lt;strong>Recherche de similarité&lt;/strong> : Calculez la similarité entre le vecteur de la requête et les vecteurs des documents dans la base de données, et récupérez les chunks de texte les plus proches sémantiquement (les plus pertinents).&lt;/li>
&lt;li>&lt;strong>Construction du prompt&lt;/strong> : Combinez les textes pertinents obtenus comme « contexte (connaissances de base) » avec la question de l&amp;rsquo;utilisateur pour créer le prompt d&amp;rsquo;entrée pour le LLM.&lt;/li>
&lt;li>&lt;strong>Génération de la réponse&lt;/strong> : Le LLM reçoit le prompt augmenté et génère une réponse basée sur les informations de contexte fournies.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="2-compréhension-approfondie-de-la-recherche-vectorielle-et-des-plongements-embeddings">2. Compréhension approfondie de la recherche vectorielle et des plongements (Embeddings)
&lt;/h1>&lt;p>Le cœur du RAG est la « recherche vectorielle (recherche sémantique) ». Alors que la recherche par mots-clés traditionnelle (comme BM25) est basée sur la correspondance exacte et la fréquence des mots, la recherche vectorielle est basée sur la « similarité de sens ». Par exemple, même des mots différents comme « chien » et « chiot », ou « PC » et « ordinateur » seront trouvés si leur sens est proche.&lt;/p>
&lt;h2 id="quest-ce-quun-modèle-de-plongement-embedding-model-">Qu&amp;rsquo;est-ce qu&amp;rsquo;un modèle de plongement (Embedding Model) ?
&lt;/h2>&lt;p>Un modèle de plongement est un réseau de neurones qui prend un texte en langage naturel en entrée et génère un vecteur dense de longueur fixe (Dense Vector). Les modèles courants (par exemple, &lt;code>text-embedding-3-small&lt;/code> ou l&amp;rsquo;open source &lt;code>multilingual-e5-large&lt;/code>) associent le texte à un vecteur de nombres réels de 384 ou 1024 dimensions.&lt;/p>
&lt;p>Dans cet espace multidimensionnel (espace latent), l&amp;rsquo;apprentissage est fait de manière à ce que les textes ayant des significations similaires soient plus proches en termes de distance dans l&amp;rsquo;espace des coordonnées.&lt;/p>
&lt;h2 id="contexte-mathématique-du-calcul-de-similarité--similarité-cosinus">Contexte mathématique du calcul de similarité : Similarité cosinus
&lt;/h2>&lt;p>Lorsque la base de données vectorielle recherche des documents pertinents, la mesure de distance la plus couramment utilisée est la &lt;strong>similarité cosinus (Cosine Similarity)&lt;/strong>. Contrairement à la distance euclidienne (distance spatiale absolue), la similarité cosinus se concentre sur « l&amp;rsquo;angle entre deux vecteurs ». Étant donné qu&amp;rsquo;elle est peu affectée par la longueur du texte (la norme du vecteur), elle est très adaptée au calcul de similarité de textes.&lt;/p>
&lt;p>Exprimée mathématiquement, la similarité cosinus des vecteurs $\mathbf{A}$ et $\mathbf{B}$ est la suivante :&lt;/p>
$$ \text{Cosine Similarity}(\mathbf{A}, \mathbf{B}) = \cos(\theta) = \frac{\mathbf{A} \cdot \mathbf{B}}{\|\mathbf{A}\| \|\mathbf{B}\|} = \frac{\sum_{i=1}^{n} A_i B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \sqrt{\sum_{i=1}^{n} B_i^2}} $$
&lt;ul>
&lt;li>$\mathbf{A} \cdot \mathbf{B}$ représente le produit scalaire (Dot Product).&lt;/li>
&lt;li>$\|\mathbf{A}\|$ représente la norme L2 (longueur) du vecteur $\mathbf{A}$.&lt;/li>
&lt;li>$n$ est le nombre de dimensions du vecteur.&lt;/li>
&lt;/ul>
&lt;p>La similarité cosinus prend une valeur comprise entre -1 et 1.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Proche de 1&lt;/strong> : Les directions des deux vecteurs sont presque les mêmes (les sens sont très similaires)&lt;/li>
&lt;li>&lt;strong>Proche de 0&lt;/strong> : Les deux vecteurs sont orthogonaux (aucun rapport)&lt;/li>
&lt;li>&lt;strong>Proche de -1&lt;/strong> : Les directions des deux vecteurs sont opposées (les sens sont opposés)&lt;/li>
&lt;/ul>
&lt;p>Les bases de données vectorielles récentes (Chroma, FAISS, Qdrant, etc.) adoptent un algorithme de recherche des plus proches voisins approximatifs (ANN) appelé HNSW (Hierarchical Navigable Small World), optimisé pour rechercher des documents ayant une similarité cosinus élevée en millisecondes, même à partir de millions de données vectorielles.&lt;/p>
&lt;hr>
&lt;h1 id="3-pile-technologique-pour-construire-un-rag-local">3. Pile technologique pour construire un RAG local
&lt;/h1>&lt;p>Pour construire un RAG local complet qui ne dépend pas du cloud, nous tirerons parti de l&amp;rsquo;écosystème open source. Voici la pile technologique recommandée.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Modèle de langage (LLM)&lt;/strong>
&lt;ul>
&lt;li>Outils : &lt;code>Ollama&lt;/code> ou &lt;code>Llama.cpp&lt;/code>&lt;/li>
&lt;li>Modèles : Des modèles ouverts légers et performants tels que &lt;code>Llama-3-8B-Instruct&lt;/code>, &lt;code>Gemma-2-9B-It&lt;/code>, &lt;code>Qwen2-7B-Instruct&lt;/code>. Pour les tâches en japonais, des modèles ajustés pour le japonais comme &lt;code>Llama-3-ELYZA-JP-8B&lt;/code> sont appropriés.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Modèle de plongement (Embedding)&lt;/strong>
&lt;ul>
&lt;li>Modèles : &lt;code>intfloat/multilingual-e5-large&lt;/code> ou &lt;code>BAAI/bge-m3&lt;/code>. Lors de l&amp;rsquo;exécution locale, il est courant de les télécharger depuis Hugging Face et de les exécuter avec Sentence-Transformers.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Base de données vectorielle (Vector DB)&lt;/strong>
&lt;ul>
&lt;li>&lt;code>ChromaDB&lt;/code> : Basée sur Python, son installation est extrêmement simple. Idéale pour le développement local.&lt;/li>
&lt;li>&lt;code>FAISS&lt;/code> : Une bibliothèque de recherche vectorielle rapide développée par Meta.&lt;/li>
&lt;li>&lt;code>Qdrant&lt;/code> / &lt;code>Milvus&lt;/code> : À plus grande échelle et destinées aux environnements de production.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Framework d&amp;rsquo;orchestration&lt;/strong>
&lt;ul>
&lt;li>&lt;code>LangChain&lt;/code> : Le standard de facto pour relier les composants (Chain).&lt;/li>
&lt;li>&lt;code>LlamaIndex&lt;/code> : Un framework de connexion de données spécialement conçu pour le RAG.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>Cette fois, nous l&amp;rsquo;implémenterons avec la combinaison la plus simple à introduire : &lt;strong>LangChain + ChromaDB + Ollama + HuggingFaceEmbeddings&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h1 id="4-tutoriel-dimplémentation--construction-complète-dun-rag-local-avec-python">4. Tutoriel d&amp;rsquo;implémentation : Construction complète d&amp;rsquo;un RAG local avec Python
&lt;/h1>&lt;p>À partir d&amp;rsquo;ici, nous allons construire un RAG local tout en écrivant du code Python. Au préalable, veuillez installer Ollama sur votre PC et le lancer en arrière-plan. De plus, téléchargez un modèle sur Ollama (exemple : &lt;code>ollama run llama3&lt;/code>).&lt;/p>
&lt;h2 id="étape-1--installation-des-bibliothèques-nécessaires">Étape 1 : Installation des bibliothèques nécessaires
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pip install langchain langchain-community langchain-huggingface
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pip install chromadb sentence-transformers pypdf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="étape-2--vue-densemble-du-code-dimplémentation">Étape 2 : Vue d&amp;rsquo;ensemble du code d&amp;rsquo;implémentation
&lt;/h2>&lt;p>Voici un script Python complet pour lire un fichier PDF, le vectoriser et permettre à un LLM local de répondre aux questions.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;span class="lnt">90
&lt;/span>&lt;span class="lnt">91
&lt;/span>&lt;span class="lnt">92
&lt;/span>&lt;span class="lnt">93
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.document_loaders&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">PyPDFLoader&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_text_splitters&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">RecursiveCharacterTextSplitter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_huggingface&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">HuggingFaceEmbeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.vectorstores&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Chroma&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.llms&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_core.prompts&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">PromptTemplate&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.chains&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">RetrievalQA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. Chargement des documents&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Chargement des documents...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Spécifiez le chemin du PDF que vous souhaitez charger&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">file_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;sample_company_policy.pdf&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">loader&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PyPDFLoader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file_path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">documents&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">loader&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. Division en chunks (Text Splitting)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Diviser en tailles appropriées pour ne pas détruire le sens du texte&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text_splitter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RecursiveCharacterTextSplitter&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chunk_size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">500&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># Nombre maximum de caractères par chunk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chunk_overlap&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># Nombre de caractères qui se chevauchent entre les chunks (empêche la rupture du contexte)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">separators&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;。&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;、&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34; &amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chunks&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">text_splitter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split_documents&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">documents&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Divisé en &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chunks&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> chunks.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. Initialisation du modèle de plongement (Local HuggingFace Model)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Utilisation d&amp;#39;un modèle multilingue performant&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Chargement du modèle de plongement...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">HuggingFaceEmbeddings&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;intfloat/multilingual-e5-large&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;device&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;cpu&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span> &lt;span class="c1"># Si vous avez un GPU, &amp;#39;cuda&amp;#39; ou &amp;#39;mps&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. Construction de la base de données vectorielle (Chroma)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Construction de la base de données vectorielle...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">persist_directory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;./chroma_db&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Chroma&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_documents&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">documents&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">chunks&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">embeddings&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">persist_directory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">persist_directory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Création du système de recherche (Retriever). Configuration pour récupérer les 3 documents les plus pertinents&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retriever&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">as_retriever&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">search_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;k&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 5. Initialisation du LLM local (Ollama)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Connexion au LLM local...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Assurez-vous d&amp;#39;obtenir le modèle au préalable avec &amp;#39;ollama pull llama3&amp;#39; par exemple&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Ollama&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;llama3&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 6. Définition du modèle de prompt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt_template&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Vous êtes un excellent assistant qui connaît bien les règlements de l&amp;#39;entreprise et les informations internes.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Veuillez répondre en détail à la question de l&amp;#39;utilisateur en français, en utilisant uniquement le contexte (informations de base) ci-dessous.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Si vous ne trouvez pas la réponse dans le contexte, ne devinez pas et répondez honnêtement « Je ne sais pas à partir des informations fournies ».
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">【Contexte】
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{context}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">【Question】
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{question}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">【Réponse】:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">PROMPT&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PromptTemplate&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">template&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">prompt_template&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">input_variables&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;context&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;question&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 7. Construction de la chaîne RAG&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qa_chain&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RetrievalQA&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_chain_type&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chain_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;stuff&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retriever&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">retriever&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">return_source_documents&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># Définir s&amp;#39;il faut renvoyer la source d&amp;#39;information&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chain_type_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;prompt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">PROMPT&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 8. Exécution de la question&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Veuillez m&amp;#39;expliquer les conditions de remboursement des frais de transport pour le télétravail.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">Question : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">qa_chain&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;query&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【Réponse】&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;result&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【Sources consultées】&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">doc&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;source_documents&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;- Page &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;inconnue&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">page_content&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">main&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="explication-des-points-clés-du-code">Explication des points clés du code
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>RecursiveCharacterTextSplitter&lt;/strong> :
C&amp;rsquo;est le diviseur le plus recommandé pour la division du langage naturel. Il tente de diviser dans l&amp;rsquo;ordre par paragraphe (&lt;code>\n\n&lt;/code>), ligne (&lt;code>\n&lt;/code>) et point (&lt;code>。&lt;/code>), en gardant les blocs de sens autant que possible tout en respectant la taille spécifiée &lt;code>chunk_size&lt;/code>. En définissant &lt;code>chunk_overlap&lt;/code>, on évite de perdre des informations aux limites du contexte.&lt;/li>
&lt;li>&lt;strong>HuggingFaceEmbeddings&lt;/strong> :
&lt;code>intfloat/multilingual-e5-large&lt;/code> est un modèle de plongement open source très puissant qui prend en charge plusieurs langues. Sans utiliser d&amp;rsquo;API cloud (telles que &lt;code>text-embedding-ada-002&lt;/code> d&amp;rsquo;OpenAI), vous pouvez vectoriser le texte hors ligne en mémoire locale.&lt;/li>
&lt;li>&lt;strong>ChromaDB&lt;/strong> :
Étant donné qu&amp;rsquo;il fonctionne en mémoire ou sur le stockage local (basé sur SQLite), il n&amp;rsquo;est pas nécessaire de mettre en place un serveur de base de données complexe. En spécifiant &lt;code>persist_directory&lt;/code>, vous pouvez ignorer le processus de vectorisation lors de la réexécution et charger la base de données à partir du disque.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="5-techniques-avancées-de-rag-advanced-rag-techniques">5. Techniques avancées de RAG (Advanced RAG Techniques)
&lt;/h1>&lt;p>Bien que le système RAG de base (Naive RAG) construit dans le tutoriel ci-dessus fonctionne, si une précision de réponse élevée est requise en production, l&amp;rsquo;introduction de techniques avancées telles que les suivantes sera nécessaire.&lt;/p>
&lt;h2 id="51-recherche-hybride-hybrid-search">5.1 Recherche hybride (Hybrid Search)
&lt;/h2>&lt;p>Bien que la recherche vectorielle excelle à saisir le « sens », elle peut avoir des difficultés avec les recherches de mots-clés exacts tels que des « noms propres spécifiques », des « numéros de modèles de produits » ou des « identifiants d&amp;rsquo;employés ».
Par conséquent, en effectuant parallèlement une &lt;strong>recherche sémantique&lt;/strong> basée sur la recherche vectorielle et une &lt;strong>recherche par mot-clé&lt;/strong> utilisant un algorithme tel que BM25, puis en évaluant et en fusionnant les deux résultats (en utilisant des méthodes telles que Reciprocal Rank Fusion ; RRF), il est possible de réduire considérablement les omissions de recherche.&lt;/p>
&lt;h2 id="52-re-classement-re-ranking">5.2 Re-classement (Re-ranking)
&lt;/h2>&lt;p>La recherche vectorielle est rapide, mais elle n&amp;rsquo;évalue pas nécessairement la pertinence contextuelle exacte du contexte. Un pipeline courant pour améliorer la précision de la recherche est le suivant :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Recherche initiale (First-stage Retrieval)&lt;/strong> : Récupérez largement et superficiellement environ 20 à 30 chunks pertinents à partir de la base de données vectorielle.&lt;/li>
&lt;li>&lt;strong>Réévaluation (Re-ranking)&lt;/strong> : Utilisez un autre modèle d&amp;rsquo;apprentissage automatique plus lourd appelé Cross-Encoder (par exemple : &lt;code>bge-reranker&lt;/code>, etc.) pour entrer la paire de la requête de l&amp;rsquo;utilisateur et du chunk récupéré, et recalculez le score de pertinence sémantique.&lt;/li>
&lt;li>&lt;strong>Sélection&lt;/strong> : Seuls les 3 à 5 premiers résultats ayant les scores les plus élevés sont passés au prompt du LLM en tant que contexte final.&lt;/li>
&lt;/ol>
&lt;p>Cette méthode empêche les informations bruyantes non pertinentes d&amp;rsquo;être transmises au LLM et peut considérablement augmenter la précision (Precision) des réponses.&lt;/p>
&lt;div class="mermaid">graph LR
Query["Requête"] --> VSearch["Recherche vectorielle (Top 20)"]
VSearch --> Reranker["Modèle de re-classement (Cross-Encoder)"]
Query --> Reranker
Reranker --> TopK["Top 3 de haute précision"]
TopK --> LLM["Génération par le LLM"]&lt;/div>
&lt;h2 id="53-chunking-sémantique-et-recherche-de-document-parent">5.3 Chunking sémantique et recherche de document parent
&lt;/h2>&lt;p>Plutôt que de diviser mécaniquement le texte par un nombre fixe de caractères, il existe une technique appelée « Semantic Chunking » qui utilise l&amp;rsquo;IA pour détecter les changements de sens dans les phrases et les diviser.
De plus, dans une technique appelée « Parent Document Retriever (Recherche de document parent) », la vectorisation est effectuée en très petites unités (comme des phrases) pour la recherche afin d&amp;rsquo;obtenir une recherche très précise. Mais lorsqu&amp;rsquo;elle est transmise au LLM, c&amp;rsquo;est le « grand paragraphe d&amp;rsquo;origine (document parent) » contenant cette phrase qui est fourni, offrant ainsi un contexte suffisant au LLM.&lt;/p>
&lt;hr>
&lt;h1 id="6-défis-et-solutions-lors-de-lexploitation-dun-rag-local">6. Défis et solutions lors de l&amp;rsquo;exploitation d&amp;rsquo;un RAG local
&lt;/h1>&lt;p>Lors de la construction et de l&amp;rsquo;exploitation d&amp;rsquo;un RAG dans un environnement local, des obstacles spécifiques existent.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Épuisement de la VRAM (Mémoire vidéo)&lt;/strong> :
Pour faire fonctionner un LLM local à une vitesse pratique (des dizaines de tokens par seconde), le modèle doit être chargé dans la VRAM du GPU. Pour exécuter un modèle de classe 8B en fp16 (virgule flottante 16 bits), environ 16 Go de VRAM sont nécessaires. Cependant, en utilisant des technologies de &lt;strong>quantification (Quantization)&lt;/strong> (techniques de compression en 4 bits ou 8 bits telles que les formats GGUF ou AWQ), il est possible de le faire fonctionner suffisamment vite même avec 8 Go de VRAM (PC de jeu standard, etc.). Llama.cpp et Ollama prennent en charge ces formats quantifiés de manière native.&lt;/li>
&lt;li>&lt;strong>Limite de la fenêtre de contexte&lt;/strong> :
Si la quantité de contexte récupérée par la recherche est trop importante, elle peut dépasser la limite d&amp;rsquo;entrée du LLM (limite de tokens), ou le modèle peut oublier les parties intermédiaires de l&amp;rsquo;information (phénomène de Lost in the middle). L&amp;rsquo;ajustement du nombre de chunks extraits et la sélection stricte à l&amp;rsquo;aide de la technologie de re-classement mentionnée ci-dessus sont essentiels.&lt;/li>
&lt;li>&lt;strong>Gestion de la fraîcheur des données&lt;/strong> :
Lorsque le document source est mis à jour, les vecteurs du document correspondant dans la base de données vectorielle doivent également être mis à jour/supprimés (opérations CRUD). Étant donné que ChromaDB prend en charge les mises à jour basées sur les identifiants de documents, il est pratique de mettre en place un traitement par lots qui gère les valeurs de hachage des fichiers et ne synchronise que les différences.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h1 id="conclusion">Conclusion
&lt;/h1>&lt;p>Le RAG (Génération Augmentée par la Recherche) est un paradigme puissant qui fait évoluer l&amp;rsquo;IA d&amp;rsquo;un assistant généraliste typique vers « votre expert exclusif » ou un « expert spécialisé dans les opérations internes ».&lt;/p>
&lt;p>Nous avons vu que même pour des exigences hautement confidentielles où les services cloud ne peuvent pas être utilisés, un environnement « RAG local » complet peut être construit relativement facilement en combinant l&amp;rsquo;écosystème open source comme Ollama, LangChain et ChromaDB.&lt;/p>
&lt;p>En vous basant sur la compréhension mathématique de l&amp;rsquo;espace vectoriel, la division de texte et les approches avancées telles que le re-classement expliquées dans cet article, n&amp;rsquo;hésitez pas à développer votre propre système d&amp;rsquo;IA original en utilisant vos propres données. La vitesse d&amp;rsquo;évolution de l&amp;rsquo;IA locale est stupéfiante, et le système que vous construisez aujourd&amp;rsquo;hui peut voir ses performances mises à jour instantanément, simplement en le remplaçant par un modèle léger encore plus intelligent qui sortira demain.&lt;/p>
&lt;hr>
&lt;p>&lt;em>Dans ce blog, nous continuerons à publier des articles approfondis sur la technologie de l&amp;rsquo;IA et le RAG. Si vous avez des questions ou des commentaires, n&amp;rsquo;hésitez pas à nous en faire part dans la section des commentaires.&lt;/em>&lt;/p></description></item></channel></rss>