Exploration des bases de données vectorielles: Google Cloud Vertex AI Vector Search

Exploration Google Cloud Vertex AI Vector Search, un moteur de recherche de similarité managé.

2025-12-03

gcp

AI

Nous allons continuer dans cet article notre exploration des bases de données vectorielles pour notre projet d'agent IA de documentation.

Structure:

Dans l'article précédent avec Google Cloud Vertex AI RAG engine, nous avons mis en place le corpus de RAG engine, uploadé nos fichiers et nous avons fait des requêtes de recherche. Le problème que nous avons rencontré dans ce cas se trouve au niveau du filtrage des fichiers. Nous avons plusieurs types et pour la plupart des requêtes, nous ne voulons que des recherches dans un type de fichier spécifique (comme les fichiers terraform par exemple). L'idée maintenant c'est d'implémenter cette approche avec Google Cloud Vector Search.

C'est quoi Vertex AI Vector Search?

Vertex AI Vector Search est un moteur de recherche de similarité managé conçu pour les applications d'IA modernes, notamment les architectures RAG et les systèmes de recommandation à grande échelle. Comme nous l'avons spécifié dans la partie précédente, le but c'est de prendre nos fichiers, les chunker, faire l'embedding, les charger dans Vector Search et faire des requêtes de recherche.

Partie 1: Chunking

Contrairement à RAG Engine où nous avons laissé le RAG faire le chunking, avec Vector Search, c'est à nous de le faire. Ceci nous permettra d'ajouter des métadonnées si on le veut.

Dans mon cas, avec un script j'ai réussi à faire du chunking sur tous mes fichiers pour avoir un résultat qui ressemble à ceci


  {
    "content": "",
    "metadata": {
      "filename": "readme.md",
      "chunk_index": 0,
      "headers": [
        "Introduction"
      ],
      "has_table": false,
      "has_code": false,
      "chunk_type": "text",
      "section_depth": 1,
      "word_count": 351,
      "char_count": 2422,
      "file_tag": []
    }
  },
  ...
  {
    "content": "...",
    "metadata": {
      "word_count": 270,
      "has_code": true,
      "char_count": 2624,
      "chunk_type": "terraform_blocks",
      "has_table": false,
      "headers": [
        "configuration",
        "variable"
      ],
      "chunk_index": 1,
      "filename": "variables.tf",
      "file_tag": [
        "schema"
      ]
    }
  }

Le plus important dans mon cas c'est d'avoir content et des métadonnées comme filename ou chunk_type.

Pour l'embedding, on le spécifiera après.

Partie 2: Charger les données dans Vector Search

Vector Search fonctionne avec des index de recherche. Pour cela, il faut que nous créions un index


vs_index = aiplatform.MatchingEngineIndex.create_tree_ah_index(
    display_name=VERTEX_SEARCH_DISPLAY_NAME,
    description=VERTEX_SEARCH_DISPLAY_DESCRIPTION,
    dimensions=VERTEX_SEARCH_DIMENSION,
    approximate_neighbors_count=10,
    leaf_node_embedding_count=500,
    leaf_nodes_to_search_percent=7,
    distance_measure_type="DOT_PRODUCT_DISTANCE",
    feature_norm_type="UNIT_L2_NORM",
    index_update_method="STREAM_UPDATE",
    contents_delta_uri=f"gs://{STAGING_BUCKET}/vs-contents-delta-uri"
)

Voici une petite explication de ce code:

  • dimensions, c'est la taille des vecteurs (embeddings)
  • approximate_neighbors_count=10 signifie qu’on veut environ 10 résultats similaires à la requête.
  • leaf_node_embedding_count indique combien de vecteurs on stocke en moyenne dans chaque “feuille” de cet arbre.
  • leaf_nodes_to_search_percent: Pourcentage par défaut de nœuds feuilles sur lesquels toute requête peut être effectuée. Doit être compris entre 1 et 100 inclus.
  • distance_measure_type indique comment Vertex AI mesure la similarité entre deux vecteurs. distance_measure_type="DOT_PRODUCT_DISTANCE" On utilise le produit scalaire (dot product), très courant pour les embeddings issus de modèles de langage.
  • feature_norm_type précise si Vertex AI doit normaliser les vecteurs avant de les comparer.
  • index_update_method décrit comment l’index sera mis à jour au fil du temps.
  • contents_delta_uri est le chemin dans Google Cloud Storage où vous allez déposer les fichiers de mise à jour de l’index. Voir https://docs.cloud.google.com/vertex-ai/docs/vector-search/create-manage-index#create_index-python_vertex_ai_sdk

On peut faire cette commande pour voir les indexes

gcloud ai indexes list --region ...

Pour utiliser notre index, il va nous falloir un endpoint. Les endpoints peuvent être publics, privés (accessibles uniquement depuis un VPC) ou privés avec Private Service Connect.


vs_endpoint = aiplatform.MatchingEngineIndexEndpoint.create(
    display_name=f"{VERTEX_SEARCH_DISPLAY_NAME}-public-endpoint",
    public_endpoint_enabled=True
)

L'étape suivante sera de déployer l'index vers un endpoint.

vs_endpoint.deploy_index(
    index=vs,
    deployed_index_id=VERTEX_SEARCH_DEPLOYED_ID,
    min_replica_count=1,
    max_replica_count=1,
    machine_type="e2-standard-2"
)

Il est recommandé que l'index ait au moins deux réplicas.

Pour charger les chunks dans notre index, nous allons utiliser le vector store de langchain. Un peu inhabituel mais c'est le moyen le plus simple et le plus propre que j'ai trouvé pour le faire.

from langchain_google_vertexai import VectorSearchVectorStore
vector_store = VectorSearchVectorStore.from_components(
    project_id=PROJECT_ID,
    region=LOCATION,
    gcs_bucket_name=STAGING_BUCKET,
    index_id=vs.resource_name,
    endpoint_id=vs_endpoint.resource_name,
    embedding=embedding_model,
    stream_update=True,
)
 vector_store.add_texts(
    texts=[
        item["page_content"]
        for item in docs
    ],
    metadatas=[
        item["metadata"]
        for item in docs
    ]
)

De là, nous aurons la capacité de faire des requêtes de recherche sur notre index.

Partie 3: Requêtes de recherche

Voici un exemple de requête de recherche

from google.cloud.aiplatform.matching_engine.matching_engine_index_endpoint import (
    Namespace,
)

rr = vector_store.similarity_search(
    query="Samples",
    k=100,
    filter=[Namespace(name="filename", allow_tokens=["readme.md"])],
)

for doc in rr:
    print(doc.metadata)
    headers = doc.metadata.get("headers", "")

    if "sample" in headers.lower():
        print(doc.metadata)

Dans ce code, on utilise la méthode similarity_search de notre vector_store pour faire une recherche de similarité avec la requête "Samples". On utilise le paramètre filter pour filtrer les résultats en fonction du nom de fichier. Dans ce cas, on ne veut que les résultats qui ont "readme.md" comme nom de fichier.

Avantages et inconvénients

Avantages

  • Base de données vectorielle managée : Vertex AI Vector Search est entièrement géré par Google Cloud, ce qui évite d'avoir à maintenir une infrastructure de base de données vectorielle soi-même. Les mises à jour, la disponibilité et la scalabilité sont prises en charge par GCP.
  • Recherche à grande échelle : Le service est conçu pour scaler facilement, que ce soit en volume de vecteurs ou en nombre de requêtes simultanées. Il reste performant même avec des millions de vecteurs stockés.

Inconvénients

  • Absence d'interface utilisateur : Il n'existe pas d'UI native pour visualiser ou explorer les données stockées dans l'index. J'ai dû en développer une moi-même pour pouvoir inspecter les chunks et vérifier le contenu de l'index.
  • Filtrage limité : Le filtrage par métadonnées fonctionne bien pour des cas simples, mais peut devenir contraignant lorsqu'on pousse ses limites. Les combinaisons de filtres complexes ou les requêtes très spécifiques peuvent se heurter aux restrictions du système de namespace.

Vector Search est une solution assez mature proposée par Google Cloud pour répondre à des besoins de recherche de similarité à grande échelle.

Cependant, cette exploration m'a montré qu'il y a des limitations à prendre en compte, notamment au niveau de la flexibilité. Dans mon cas, une des finalités de ce projet d'agent IA de documentation est d'avoir la possibilité de faire des recherches assez dynamiques : récupérer les documents, les chunker, les charger dans la base de données vectorielle et faire des recherches avec des filtres assez complexes. Avoir une bonne pipeline de bout en bout est donc crucial pour moi.

C'est pour cela que je vais continuer à explorer d'autres solutions comme ChromaDB et Milvus pour voir si elles peuvent mieux répondre à mes besoins.

J'avoue quand même n'avoir pas tout testé. Je verrai ce que Vector Search 2.0 propose dans un autre article.