redis-vector-search

Par redis · agent-skills

Guide de recherche vectorielle Redis couvrant le choix d'algorithme HNSW vs FLAT, la configuration d'index vectoriel (dims, métrique de distance, datatype), la recherche hybride filtrée combinant similarité vectorielle avec des filtres TAG ou NUMERIC, et le pattern de récupération RAG avec RedisVL. À utiliser lors de la définition d'un champ VECTOR dans `FT.CREATE`, l'intégration d'embeddings (OpenAI, Cohere, sentence-transformers), le tuning des paramètres HNSW (M, EF_CONSTRUCTION, EF_RUNTIME), la construction d'un pipeline de génération augmentée par récupération, ou le filtrage des résultats vectoriels par attribut.

npx skills add https://github.com/redis/agent-skills --skill redis-vector-search

Recherche vectorielle Redis

Conseils pour stocker et rechercher des embeddings dans Redis. Couvre la configuration des index, le choix d'algorithme, le filtrage hybride et le pattern RAG avec RedisVL.

Quand appliquer

  • Définir un champ VECTOR dans FT.CREATE (RQE brut) ou un IndexSchema RedisVL.
  • Choisir entre HNSW et FLAT et ajuster les paramètres HNSW.
  • Ajouter des filtres de catégorie, date ou tenant à une requête vectorielle.
  • Construire un pipeline de retrieval-augmented generation (RAG) sur Redis.

Cette skill s'appuie sur la skill redis-query-engine — les champs vectoriels vivent à l'intérieur des index RQE et partagent la même machinerie FT.CREATE / FT.SEARCH.

1. Configurer correctement l'index vectoriel

Trois paramètres doivent correspondre au modèle d'embedding :

  • DIM — la dimensionnalité de sortie du modèle (ex. 1536 pour text-embedding-3-small d'OpenAI). Une non-correspondance produit du garbage silencieux.
  • DISTANCE_METRICCOSINE pour les embeddings textes normalisés (le cas courant), IP pour le produit scalaire non-normalisé, L2 pour l'Euclidien brut.
  • TYPE / datatype — généralement FLOAT32. Utiliser FLOAT16 ou des variantes quantifiées seulement quand le coût mémoire est une contrainte dure.

RQE brut :

FT.CREATE idx:docs ON HASH PREFIX 1 doc:
    SCHEMA
        content TEXT
        embedding VECTOR HNSW 6
            TYPE FLOAT32
            DIM 1536
            DISTANCE_METRIC COSINE

RedisVL :

schema = IndexSchema.from_dict({
    "index": {"name": "idx:docs", "prefix": "doc:"},
    "fields": [
        {"name": "content", "type": "text"},
        {"name": "embedding", "type": "vector", "attrs": {
            "dims": 1536, "algorithm": "HNSW",
            "datatype": "FLOAT32", "distance_metric": "COSINE",
        }},
    ]
})

Voir references/index-creation.md pour les variantes redis-py et RedisVL.

2. HNSW vs FLAT

Algorithme Vitesse Précision Mémoire Meilleur pour
HNSW Rapide (approximé) ~95%+ de rappel (ajustable) Plus élevée Grands jeux de données (>10k vecteurs), sensibles à la latence
FLAT Lent (exact) 100% Plus faible Petits jeux de données (<10k), critiques pour la précision

Par défaut, HNSW pour toute charge de travail de production. Leviers d'ajustement :

  • M — connexions par nœud (16–64). Plus haut = meilleur rappel, plus de mémoire.
  • EF_CONSTRUCTION — qualité du graphe à la construction (100–500). Plus haut = meilleur index, construction plus lente.
  • EF_RUNTIME — taille de la liste de candidats au moment de la requête. Plus haut = meilleur rappel, requêtes plus lentes.

Utiliser FLAT quand le corpus est petit et que vous avez besoin de résultats exacts (ex. déduplication sémantique sur quelques milliers d'éléments).

Voir references/algorithm-choice.md.

3. Recherche hybride — filtrer avant le vecteur

Appliquer des filtres d'attributs (TAG / NUMERIC) pour que le moteur réduise l'espace de recherche avant la comparaison vectorielle. Ne pas récupérer un large ensemble de résultats puis filtrer côté client — c'est plus lent et moins précis.

from redisvl.query import VectorQuery
from redisvl.query.filter import Num, Tag

filters = (Tag("category") == "technology") & (Num("date") >= 2024)

query = VectorQuery(
    vector=query_embedding,
    vector_field_name="embedding",
    return_fields=["content", "category", "date"],
    num_results=10,
    filter_expression=filters,
)
results = index.query(query)

Pour fusion texte + vecteur (score textuel pondéré BM25 combiné avec similarité vectorielle), utiliser HybridQuery sur Redis ≥ 8.4 avec redis-py ≥ 7.1, ou AggregateHybridQuery sur Redis plus anciens. C'est un type de « hybride » différent de la recherche vectorielle filtrée ci-dessus.

Voir references/hybrid-search.md.

4. Pattern RAG

Pipeline standard : embedder la requête utilisateur → recherche vectorielle Redis → passer le contexte top-K au LLM.

# Indexer les documents avec embeddings
records = [{"content": doc.content,
            "embedding": embed_model.encode(doc.content).tolist(),
            "source": doc.source}
           for doc in documents]
index.load(records)

# Récupérer le contexte pertinent pour une question utilisateur
q_emb = embed_model.encode(user_question)
results = index.query(VectorQuery(
    vector=q_emb,
    vector_field_name="embedding",
    return_fields=["content", "source"],
    num_results=5,
))

# Générer avec le contexte récupéré
context = "\n".join(r["content"] for r in results)
response = llm.generate(f"Context: {context}\n\nQuestion: {user_question}")

Conseils pratiques :

  • Faire correspondre la métrique au modèle. La plupart des modèles modernes d'embedding texte s'associent au mieux à COSINE.
  • Chunker les documents longs avant l'indexation — la retrieval sur des chunks de 200–500 tokens surpasse généralement l'indexation de pages entières.
  • Insérer par lots avec index.load([...]) au lieu d'un appel par enregistrement.
  • Pré-filtrer par attributs (tenant, récence, type de document) avant la recherche vectorielle.

Voir references/rag-pattern.md.

Références

Skills similaires