Procédure pas à pas de recherche sémantique

Découvrez comment effectuer une recherche sémantique des données à l'aide de la recherche OCI avec OpenSearch.

Préalables

Avant de commencer, vous devez effectuer les opérations suivantes :

  • Sélectionnez l'un des modèles préentraînés pris en charge par la recherche OCI avec OpenSearch

  • Vérifiez que la grappe OpenSearch est la version 2.11.

  • Mettez à jour les paramètres de grappe pour effectuer une recherche sémantique. L'exemple de commande suivant met à jour les paramètres applicables :

    PUT _cluster/settings
    {
      "persistent": {
        "plugins": {
          "ml_commons": {
            "only_run_on_ml_node": "false",
            "model_access_control_enabled": "true",
            "native_memory_threshold": "99",
            "rag_pipeline_feature_enabled": "true",
            "memory_feature_enabled": "true",
            "allow_registering_model_via_local_file": "true",
            "allow_registering_model_via_url": "true",
            "model_auto_redeploy.enable":"true",
            "model_auto_redeploy.lifetime_retry_times": 10
          }
        }
      }
    }

Enregistrer le groupe de modèles

Utilisez des groupes de modèles pour regrouper logiquement les modèles et contrôler qui y a accès. Enregistrez un groupe de modèles à l'aide de l'opération Enregistrer dans les API de groupe de modèles, comme illustré dans l'exemple suivant :

POST /_plugins/_ml/model_groups/_register
{
  "name": "general pretrained models",
  "description": "A model group for pretrained models hosted by OCI Search with OpenSearch"
}

Notez la valeur model_group_id retournée dans la réponse :

{
  "model_group_id": "<model_group_ID>",
  "status": "CREATED"
}

Enregistrer et déployer le modèle

Vous disposez des trois options suivantes pour la recherche sémantique :

  • Option 1 : Enregistrez et déployez un modèle préentraîné hébergé dans la recherche OCI avec OpenSearch à l'aide des étapes décrites sous Utilisation d'un modèle préentraîné OpenSearch. Cette option est la plus simple à utiliser, vous n'avez pas besoin de configurer de politiques IAM supplémentaires et les données utiles ne sont pas aussi complexes que les données utiles de l'option suivante.
  • Option 2 : Importez, enregistrez et déployez un modèle préentraîné OpenSearch à l'aide des étapes décrites dans Modèles personnalisés. Cela inclut le chargement du fichier de modèle dans un seau de stockage d'objets, puis la spécification de l'URL de stockage d'objets du fichier de modèle lors de l'enregistrement du modèle.
  • Option 3 : Vous pouvez également enregistrer et déployer un modèle d'intégration GenAI distant tel que cohere.embed-english-v3.0 dans votre grappe à l'aide de notre connecteur GenAI. Vous devez d'abord créer un connecteur, puis enregistrer et déployer le modèle à l'aide de l'ID connecteur, comme décrit dans les étapes suivantes.
    Note

    Si vous utilisez le modèle ON-DEMAND, restez à jour avec les avis d'abandon de modèle du service GenAI et mettez à jour votre connecteur si nécessaire pour éviter d'éventuelles interruptions de service. Voir Modèles fondamentaux préentraînés dans l'intelligence artificielle générative pour les modèles d'intégration pris en charge afin de sélectionner un modèle d'intégration dans la liste des modèles pris en charge.

    Si vous utilisez le modèle DEDICATED, remplacez le paramètre servingType dans l'exemple de données utiles suivant ON-DEMAND par DEDICATED.

Cette présentation explique comment utiliser l'option 1, un modèle préentraîné.
Pour enregistrer un modèle préentraîné, vous devez disposer des éléments suivants :
  • model_group_id : Si vous avez terminé l'étape 1, il s'agit de la valeur de model_group_id pour la demande _register.
  • name : Nom du modèle préentraîné à utiliser.
  • version : Numéro de version du modèle préentraîné à utiliser.
  • model_format : Format du modèle, TORCH_SCRIPT ou ONNX.

Enregistrez le modèle à l'aide de l'opération Enregistrer à partir des API de modèle, comme illustré dans l'exemple suivant :

POST /_plugins/_ml/models/_register
{
  "name": "huggingface/sentence-transformers/msmarco-distilbert-base-tas-b",
  "version": "1.0.2",
  "model_group_id": "<model_group_ID>",
  "model_format": "TORCH_SCRIPT"
}

Notez la valeur task_id retournée dans la réponse. Vous pouvez utiliser task_id pour vérifier le statut de l'opération.

Par exemple, à partir de la réponse suivante :

{
  "task_id": "<task_ID>",
  "status": "CREATED"
}

pour vérifier le statut de l'opération d'enregistrement, utilisez task_id avec l'opération Obtenir des API de tâche, comme illustré dans l'exemple suivant :

GET /_plugins/_ml/tasks/<task_ID>

Une fois l'opération d'enregistrement terminée, la valeur state dans la réponse à l'opération Get est COMPLETED, comme illustré dans l'exemple suivant :

{
  "model_id": "<embedding_model_ID>",
  "task_type": "REGISTER_MODEL",
  "function_name": "TEXT_EMBEDDING",
  "state": "COMPLETED",
  "worker_node": [
    "f2b_8-mVRVyVqeKqsA7dcQ"
  ],
  "create_time": 1706831015570,
  "last_update_time": 1706831070740,
  "is_async": true
}

Notez la valeur model_ID retournée dans la réponse à utiliser lors du déploiement du modèle.

Déployer le modèle

Une fois l'opération d'enregistrement terminée pour le modèle, vous pouvez déployer le modèle dans la grappe à l'aide de l'opération de déploiement des API de modèle, en transmettant model_ID à partir de la réponse de l'opération Get à l'étape précédente, comme illustré dans l'exemple suivant :

POST /_plugins/_ml/models/<embedding_model_ID>/_deploy

Notez la valeur task_id retournée dans la réponse. Vous pouvez utiliser task_id pour vérifier le statut de l'opération.

Par exemple, à partir de la réponse suivante :

{
  "task_id": "<task_ID>",
  "task_type": "DEPLOY_MODEL",
  "status": "CREATED"
}

pour vérifier le statut de l'opération d'enregistrement, utilisez task_ID avec l'opération Obtenir des API de tâches, comme illustré dans l'exemple suivant :

GET /_plugins/_ml/tasks/<task_ID>

Une fois l'opération de déploiement terminée, la valeur status dans la réponse à l'opération Get est COMPLETED.

Créer un pipeline d'ingestion k-NN

Une fois l'opération de déploiement terminée, créez un pipeline d'ingestion à l'aide du modèle déployé. Le pipeline d'ingestion utilise le modèle déployé pour générer automatiquement les vecteurs d'intégration pour chaque document au moment de l'ingestion. Le processeur gère tout pour l'intégration, de sorte que vous n'avez qu'à mapper correctement le champ de texte attendu dans le document en cours de conversion en intégration. L'exemple suivant montre comment créer un pipeline d'ingestion :

PUT _ingest/pipeline/<pipeline_name>
{
  "description": "An example neural search pipeline",
  "processors" : [
    {
      "text_embedding": {
        "model_id": "<embedding_model_ID>",
        "field_map": {
           "<text_field_name>": "<embedding_field_name>"
        }
      }
    }
  ]
}

Si le pipeline d'ingestion a été créé, la réponse suivante est retournée :

{
  "acknowledged": true
}

Créer un index

Créez un index à l'aide du pipeline d'ingestion créé à l'étape précédente. Vous pouvez utiliser n'importe lequel des moteurs ANN disponibles dans l'index. L'exemple suivant utilise le moteur Lucene :

PUT /lucene-index
{
    "settings": {
        "index.knn": true,
        "default_pipeline": "<pipeline_name>"
    },
    "mappings": {
        "properties": {
            "<embedding_field_name>": {
                "type": "knn_vector",
                "dimension": <model_dimension>,
                "method": {
                    "name":"hnsw",
                    "engine":"lucene",
                    "space_type": "l2",
                    "parameters":{
                        "m":512,
                        "ef_construction": 245
                    }
                }
            },
            "<text_field_name>": {
                "type": "text"
            }
        }
    }
    }

Le champ passage_text pour l'index de création correspond au champ passage_text du pipeline d'ingestion, ce qui le rend capable de créer des intégrations, puis de les mapper à des documents au moment de l'ingestion.

Pour vous aider à choisir le moteur à utiliser et les paramètres de configuration disponibles pour ces moteurs, voir index k-NN et Recherche approximative de k-NN.

Voici un exemple de réponse pour une création d'index réussie :

{
        "acknowledged": true,
        "shards_acknowledged": true,
        "index": "lucene-index"
}

Ingérer des documents dans l'index

Ingérez les données dans votre index, comme illustré dans l'exemple suivant :

POST /lucene-index/_doc/1
{
  "<text_field_name>": "there are many sharks in the ocean"
}
 
POST /lucene-index/_doc/2
{
  "<text_field_name>": "fishes must love swimming"
}
 
POST /lucene-index/_doc/3
{
  "<text_field_name>": "summers are usually very hot"
}
 
POST /lucene-index/_doc/4
{
  "<text_field_name>": "florida has a nice weather all year round"
}

Réponse :

# POST /lucene-index/_doc/1
{
  "_index": "lucene-index",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}
# POST /lucene-index/_doc/2
{
  "_index": "lucene-index",
  "_id": "2",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}
# POST /lucene-index/_doc/3
{
  "_index": "lucene-index",
  "_id": "3",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 1
}
# POST /lucene-index/_doc/4
{
  "_index": "lucene-index",
  "_id": "4",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 3,
  "_primary_term": 1
}

Exécutez la commande suivante pour vérifier l'un des documents afin de vous assurer que les plongements sont générés correctement :

GET /lucene-index/_doc/3

Réponse :

{
  "_index": "lucene-index",
  "_id": "3",
  "_version": 1,
  "_seq_no": 2,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "<embedding_field_list>": [
      -0.1254959,
      -0.3151774,
      0.03526799,
      0.39322096,
      -0.0475556,
      -0.12378334,
      -0.032554347,
      0.4033895,
      0.050718695,
      -0.3587931,
      0.097042784,
      0.11742551,
      -0.06573639,
      0.14252506,
      -0.466573,
      0.56093556,
      -0.2815812,
      -0.00016521096,
      -0.2858566,