Accueil / Articles / RAG local sans vecteurs : SQLite FTS5 et BM25 pour la recherche de code

RAG local sans vecteurs : SQLite FTS5 et BM25 pour la recherche de code

Pourquoi les index vectoriels denses pèsent sur les machines des développeurs et comment SQLite FTS5 avec BM25 offre une recherche de code exacte et plus rapide.

758 mots

Pendant quelques années, la recette de la recherche de code locale a été la même : découper le dépôt en morceaux, transformer chaque morceau en embedding de 1536 dimensions et garder un index HNSW vivant dans un processus d'arrière-plan. Cela paraissait moderne, comme si l'ordinateur portable s'était doté d'un petit moteur de recherche qui comprend ce que fait le code. Sur un poste de travail chargé, pourtant, cette recette a un coût que l'on voit rarement dans un README.

Les chiffres mis en avant autour de la recherche vectorielle locale impressionnent : de bons scores de recherche sur MTEB, des millions de tokens de code transformés en embeddings en quelques minutes, une "intelligence sémantique instantanée" sur du matériel grand public. Lisez les notes sur la mémoire plutôt que le marketing, et le tableau change. L'indexation vectorielle dense achète son rappel en dépensant de la bande passante mémoire, de la RAM ou de la VRAM, et de la prévisibilité.

Quand le tout-vectoriel se heurte au mur de la mémoire

Faites tourner une base vectorielle à côté d'un LLM local, d'un IDE et de quelques conteneurs Docker, et elle ne reste pas inactive. Elle garde de grandes structures de graphe en RAM ou en VRAM, dispute la bande passante aux autres outils et introduit une dérive sémantique : vous cherchez la chaîne exacte ERR_AUTH_EXPIRED et vous obtenez du code qui parle seulement d'authentification de près ou de loin.

C'est pour cela que beaucoup d'équipes reviennent discrètement à des algorithmes natifs en C, en l'occurrence SQLite FTS5 avec BM25. Au lieu de calculs vectoriels pour les recherches locales, elles utilisent un classement déterministe par fréquence des termes et trouvent les identifiants exacts en moins de 5 millisecondes.

Correspondance de concepts ou vitesse prévisible

Ce n'est pas un simple réglage. Cela change la façon dont on construit les outils pour développeurs. En remplaçant le surcoût vectoriel local par FTS5, vous renoncez à une correspondance de concepts théorique en échange d'une exécution légère et rapide.

  • Efficacité : abandonner l'indexation dense libère des gigaoctets de mémoire. Un travail qui passait environ 200 ms à calculer des embeddings se termine en natif en moins de 5 ms.
  • Précision : les recherches de mots-clés exacts et de noms de fonctions, comme getUserById(), sont entièrement déterministes, donc l'index ne renvoie pas le corps de fonctions sans rapport.

Les deux flux se comparent ainsi :

[Dense Vector RAG Flow]
Code Query -> Generate Vector Embeddings -> HNSW Index Search -> Semantic Drift Risk -> LLM Context
[Deterministic BM25 Flow]
Code Query -> Native SQLite C-Index -> Exact Keyword Match (5ms) -> Minimal LLM Context

Des symptômes que vous connaissez peut-être déjà

Quiconque fait tourner des agents locaux ou une recherche de code a sans doute remarqué ces frictions :

  • La concurrence pour les ressources. Le ventilateur s'emballe, la batterie tient deux heures et l'inférence locale se traîne parce qu'un moteur en arrière-plan se bat pour la mémoire.
  • La pénalité de la correspondance exacte. Chercher une chaîne d'erreur ou une variable précise renvoie cinq fichiers proches de l'authentification par le sens, mais pas le seul fichier qui contient le vrai drapeau.

Une comparaison côte à côte, avec des chiffres approximatifs :

Critère Base vectorielle locale (Chroma, Qdrant) SQLite FTS5 (BM25)
Empreinte mémoire Environ 1,5 à 4 Go de RAM ou de VRAM Environ 15 à 30 Mo de RAM
Latence de recherche 120 à 400 ms, surtout pour les embeddings Moins de 5 ms, en C natif
Correspondance exacte des identifiants Faible, sujette à la dérive Forte, correspondance déterministe des mots-clés
Surcoût système Démons en arrière-plan, liaisons C++ Rien ne tourne au repos
Idéal pour Des recherches larges et thématiques dans du texte Des recherches précises dans le code, les logs et le RAG local

Prenez ces chiffres comme des ordres de grandeur, car les résultats dépendent de la taille du corpus, du choix du modèle et du matériel.

Ce que cela signifie pour les responsables techniques

Le réflexe d'ajouter une base vectorielle à chaque problème local s'estompe. Une habitude plus utile est le sens de la mesure. Le savoir-faire d'un architecte expérimenté ne consiste pas à installer une infrastructure d'IA toujours plus lourde sur les portables des développeurs. Il consiste à reconnaître quand dix lignes de code natif ou un fichier SQLite de 30 Mo font mieux qu'un pipeline neuronal qui se mesure en gigaoctets.

À mesure que les outils deviennent plus rapides et les flux de travail plus légers, ce ne sont pas les piles qui font tourner les plus gros modèles qui l'emporteront. Ce seront celles qui livrent du code propre et sans surpoids. Les embeddings ne deviennent pas inutiles pour autant : pour des questions floues, au niveau des concepts, sur du texte, ils gardent leur place. Mais pour trouver un identifiant exact dans une base de code, commencez par l'outil déterministe et bon marché, et n'ajoutez des vecteurs que là où il échoue.