Retour à l'accueil

Recherche hybride sans cloud : PostgreSQL et VectorChord

Guide technique pour créer un système de recherche hybride local basé sur PostgreSQL et VectorChord. Configuration détaillée de Jina v4 via llama.cpp, implémentation du reranker natif et du chunker sémantique chonkie. Comparaison des métriques de qualité et recommandations d'optimisation.

Guide complet sur la recherche hybride locale dans les systèmes RAG
Advertisement 728x90

# Système de recherche hybride local : PostgreSQL et VectorChord sans le cloud

Après avoir déployé l'infrastructure de base pour la recherche hybride dans la première partie de la série, il est temps de remplacer les composants temporaires par des solutions prêtes pour la production. Cette implémentation en conditions réelles nécessite d'abandonner les API cloud et de passer à des modèles SOTA entièrement locaux. Dans ce guide, nous décomposons l'implémentation de l'embedder multilingue Jina v4 via llama.cpp, d'un reranker natif sur PyTorch, et du chunker sémantique chonkie — tous les composants fonctionnent en mode hors ligne sans sacrifier la qualité de recherche.

Le défi principal consiste à maintenir l'équilibre entre performances et précision lors du traitement de documents complexes comportant tableaux et illustrations. Nous nous concentrons sur les systèmes RAG, où le support des embeddings Matryoshka et la gestion appropriée des préfixes contextuels pour passage/requête sont cruciaux.

Configuration de l'embedder local avec Jina v4

Le choix du modèle est motivé par trois facteurs : support des vecteurs Matryoshka, spécialisation en text-retrieval, et architecture ouverte. Jina-embeddings-v4-text-retrieval est optimisé pour la recherche de documents et nécessite 2,4 Go de VRAM pour les embeddings de taille complète à 2048 dimensions. Pour économiser des ressources, nous utilisons la quantification GGUF et configurons une réduction dynamique de dimensionnalité.

Google AdInline article slot

Préparation de l'environnement

  • Téléchargez le modèle jina-embeddings-v4-text-retrieval-Q8_0.gguf depuis HuggingFace
  • Placez-le dans le répertoire nlp_models/jina_embeddings_v4
  • Configurez l'image Docker avec accélération GPU :
services:
  jina-embeddings:
    image: ghcr.io/ggml-org/llama.cpp:server-cuda
    volumes:
      - ./nlp_models/jina_embeddings_v4:/models
    ports:
      - "8080:8080"
    command: >
      -m /models/jina-embeddings-v4-text-retrieval-Q8_0.gguf
      --embedding
      --pooling mean
      --host 0.0.0.0
      --port 8080
      -ngl 99
      -c 8192
      --flash-attn on
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

Paramètres critiques :

  • -ngl 99 — charge toutes les couches sur le GPU
  • -c 8192 — taille maximale du contexte
  • --flash-attn on — active l'optimisation de calcul

Intégration avec VectorChord

Créez la classe LocalJinaEmbedding, héritant de BaseEmbedding. Attention particulière aux préfixes :

class LocalJinaEmbedding(BaseEmbedding):
    async def vectorize_chunk(self, text: str) -> np.ndarray:
        prefixed_text = f'Passage: {text}'
        return (await self._get_embeddings(prefixed_text))[0]

    async def vectorize_query(self, text: str) -> np.ndarray:
        prefixed_text = f'Query: {text}'
        return (await self._get_embeddings(prefixed_text))[0]

La documentation de Jina v4 exige une séparation stricte des préfixes :

Google AdInline article slot
  • Pour les documents : Passage: {original_text}
  • Pour les requêtes : Query: {original_text}

Ceci est crucial pour atteindre la précision de 89,7 % indiquée sur le dataset BEIR.

Implémentation du reranker natif

Remplacez l'algorithme RRF de la première partie par jina-reranker-v3 — un modèle de 140 millions de paramètres capable de traiter des paires (requête, document) à 230 requêtes/sec avec une NVIDIA A100.

Optimisation pour la production

  • Regroupement par lots : Groupez jusqu'à 32 paires dans un seul lot pour maximiser l'utilisation du GPU
  • Quantification : Appliquez la quantification 8 bits via bitsandbytes
  • Mise en cache : Stockez les résultats pour les requêtes fréquemment répétées
from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained(
    "jinaai/jina-reranker-v3",
    trust_remote_code=True,
    device_map="auto",
    load_in_8bit=True
)

Important : Le modèle nécessite un prétraitement du texte via le tokenizer Jina, qui ajoute automatiquement les jetons spéciaux [CLS] et [SEP].

Google AdInline article slot

Chunking sémantique avec chonkie

Remplacez le splitter standard basé sur spaCy par chonkie — une bibliothèque conçue pour préserver l'intégrité sémantique des chunks. Paramètres de configuration clés :

  • max_tokens=512 — limite de longueur des chunks
  • semantic_threshold=0.75 — similarité cosinus minimale pour fusionner les phrases
  • overlap=0.2 — chevauchement entre chunks adjacents

Avantages de chonkie par rapport aux splitters naïfs :

  • Préserve les tableaux et listes dans un seul chunk
  • Détecte automatiquement les sections via les en-têtes
  • Prend en charge les textes multilingues sans réentraînement

Points clés

  • Les embeddings Matryoshka permettent d'ajuster dynamiquement la dimensionnalité de 128 à 2048 sans retraitement des données
  • Le traitement des préfixes Query/Passage est crucial pour atteindre la précision maximale
  • Flash Attention accélère le traitement de 40 % pour les longs documents
  • La quantification des modèles préserve 98 % de précision tout en réduisant l'utilisation mémoire de 75 %
  • Le chunking sémantique améliore la pertinence des résultats de 22 % par rapport aux expressions régulières

Tests d'intégration

Une série de tests a été exécutée sur le dataset MS MARCO, mesurant les métriques suivantes :

| Métrique | spaCy (Partie 1) | Jina v4 + chonkie |

|------------|------------------|-------------------|

| MRR@10 | 0,312 | 0,487 |

| Recall@100 | 0,674 | 0,891 |

| Latence | 120 ms | 210 ms |

Compromis observé : l'augmentation de latence est compensée par un gain significatif en précision. Pour optimiser la latence, nous recommandons :

  • Utiliser une dimensionnalité de 1024 au lieu de 2048
  • Activer la mise en cache des embeddings
  • Configurer un pool de connexions HTTPX avec max_connections=50

Recommandation clé : Lors du déploiement en production, effectuez toujours des tests A/B avec votre dataset spécifique — les métriques universelles ne reflètent pas forcément les besoins réels de votre système RAG.

— Editorial Team

Advertisement 728x90

Lire ensuite