Initialisation des données Chroma persistantes

import { ChromaClient } from 'chromadb'

Initialisation du client

const client = new ChromaClient();

Opérations courantes du client

await client.reset() // Efface la base de données

Travail avec les collections

Chromadb utilise le concept de collection pour gérer des ensembles de données vectorielles, qui peuvent être assimilées à des tables dans MySQL.

Création, consultation et suppression de collections

Chroma utilise le nom de la collection dans l'URL, donc il existe certaines restrictions de nommage :

  • La longueur du nom doit être comprise entre 3 et 63 caractères.
  • Le nom doit commencer et se terminer par des lettres minuscules ou des chiffres, et peut contenir des points, des tirets et des traits de soulignement entre eux.
  • Le nom ne peut pas contenir deux points consécutifs.
  • Le nom ne peut pas être une adresse IP valide.

Pour créer une collection, le nom de la collection et une fonction de calcul de vecteur facultative (également appelée fonction d'incorporation) doivent être spécifiés. Si une fonction d'incorporation est fournie, elle doit être fournie à chaque accès à la collection.

Remarque : La fonction d'incorporation est utilisée pour calculer des vecteurs de texte.

import { ChromaClient } from 'chromadb'

Créez et référencez une collection comme indiqué ci-dessous :

let collection = await client.createCollection({name: "ma_collection", embeddingFunction: emb_fn})

let collection2 = await client.getCollection({name: "ma_collection", embeddingFunction: emb_fn})

La fonction d'incorporation prend du texte en entrée et renvoie des données vectorielles calculées.

Remarque : Les débutants peuvent en apprendre davantage sur les modèles d'incorporation de texte à partir de ce tutoriel.

Les collections existantes peuvent être référencées en utilisant .getCollection par leur nom, et peuvent également être supprimées en utilisant .deleteCollection.

const collection = await client.getCollection({name: "tizi365"}) // Référence la collection tizi365
await client.deleteCollection({name: "ma_collection"}) // Supprime la collection

Fonctions courantes de la collection

await collection.peek() // Renvoie les 10 premiers enregistrements de données dans la collection
await collection.count() // Renvoie le nombre total d'enregistrements de données dans la collection

Ajustement des méthodes de calcul de distance vectorielle

La fonction createCollection inclut également un paramètre facultatif metadata, où la valeur de hnsw:space peut être définie pour personnaliser la méthode de calcul de distance pour l'espace vectoriel.

Remarque : Les données vectorielles représentent la similarité entre les vecteurs en calculant la distance spatiale entre eux, les distances plus proches indiquant une similarité plus élevée et vice versa.

let collection = client.createCollection("nom_de_collection", undefined, metadata={ "hnsw:space": "cosine" })

Les options valides pour hnsw:space sont "l2", "ip" ou "cosine". Par défaut, c'est "l2".

Ajout de données à une collection

Utilisez .add pour ajouter des données à la collection Chroma.

Ajoutez des données directement sans spécifier les vecteurs de document :

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    metadatas: [{"chapitre": "3", "verset": "16"}, {"chapitre": "3", "verset": "5"}, {"chapitre": "29", "verset": "11"}, ...],
    documents: ["lorem ipsum...", "doc2", "doc3", ...],
})
// Explication des paramètres
// ids - requis
// embeddings - optionnel
// metadata - optionnel
// documents - optionnel

Si Chroma reçoit une liste de documents, il utilisera automatiquement la fonction d'embedding de la collection pour calculer des vecteurs pour les documents (si une fonction d'embedding n'a pas été fournie lors de la création de la collection, la valeur par défaut sera utilisée). Chroma stockera également les documents eux-mêmes. Si un document est trop grand pour être utilisé avec la fonction d'embedding sélectionnée, une exception se produira.

Chaque document doit avoir un ID unique (ids). Ajouter le même ID deux fois entraînera seul la valeur initiale stockée. Une liste facultative de dictionnaires de métadonnées (metadatas) peut être fournie pour chaque document afin de stocker des informations supplémentaires pour filtrer les données lors des requêtes.

Alternativement, vous pouvez directement fournir une liste de données vectorielles liées au document, et Chroma utilisera les données vectorielles que vous avez fournies sans calculer automatiquement le vecteur.

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas: [{"chapitre": "3", "verset": "16"}, {"chapitre": "3", "verset": "5"}, {"chapitre": "29", "verset": "11"}, ...],
    documents: ["lorem ipsum...", "doc2", "doc3", ...],
})

Si les dimensions des données vectorielles fournies ne correspondent pas aux dimensions de la collection, une exception se produira.

Vous pouvez également stocker des documents ailleurs et simplement fournir les données vectorielles et la liste de métadonnées à Chroma. Vous pouvez utiliser des IDs pour associer les vecteurs aux documents stockés ailleurs.

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas: [{"chapitre": "3", "verset": "16"}, {"chapitre": "3", "verset": "5"}, {"chapitre": "29", "verset": "11"}, ...],
})

Remarque : La fonction principale de la base de données vectorielle est la recherche de similarité sémantique basée sur les données vectorielles. Pour réduire la taille de la base de données vectorielles et améliorer l'efficacité, nous pouvons choisir de stocker des données vectorielles et certaines conditions d'attributs filtrables dans la base de données vectorielle. D'autres données, telles que le contenu des articles, peuvent être stockées dans des bases de données comme MYSQL, tant qu'elles sont associées par des IDs.

Interrogation des données de la Collection

La méthode .query peut être utilisée pour interroger l'ensemble de données Chroma de plusieurs manières.

Vous pouvez effectuer une requête en utilisant un ensemble de query_embeddings (données vectorielles).

Astuce : Pour obtenir des query_embeddings, dans des scénarios de développement réels, la requête de l'utilisateur est généralement d'abord calculée en un vecteur de requête via un modèle d'encodage de texte, puis ce vecteur est utilisé pour interroger un contenu similaire.

const resultat = await collection.query({
    queryEmbeddings: [[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
    nResults: 10,
    where: {"champ_metadata": "est_égal_à_cela"},
})
// ordre d'entrée
// query_embeddings - optionnel
// n_results - requis
// where - optionnel
// query_texts - optionnel

La requête renverra les n_results premiers résultats pour chaque vecteur de requête (query_embedding) dans l'ordre. Un dictionnaire de filtre where optionnel peut être fourni pour filtrer les résultats en fonction des métadonnées associées à chaque document. De plus, un dictionnaire de filtre where_document optionnel peut être fourni pour filtrer les résultats en fonction du contenu du document.

Si les query_embeddings fournis ne sont pas cohérents avec les dimensions de la collection, une exception se produira. Pour garantir la cohérence des vecteurs, il est recommandé d'utiliser le même modèle d'encodage de texte pour calculer les vecteurs.

Vous pouvez également interroger en utilisant un ensemble de textes de requête. Chroma calculera d'abord le vecteur pour chaque texte de requête en utilisant la fonction d'encodage de la collection, puis exécutera la requête en utilisant les vecteurs de texte générés.

await collection.query({
    nResults: 10, // n_results
    where: {"champ_metadata": "est_égal_à_cela"}, // where
    queryTexts: ["doc10", "ainsi parlait zarathoustra", ...], // query_text
})

Vous pouvez également utiliser .get pour interroger des données de la collection par ID.

await collection.get({
    ids: ["id1", "id2", "id3", ...], //ids
    where: {"style": "style1"} // where
})

.get prend également en charge les filtres where et where_document. Si aucun id n'est fourni, il renverra toutes les données de la collection correspondant aux filtres where et where_document.

Spécification des champs renvoyés

Lors de l'utilisation de get ou query, vous pouvez utiliser le paramètre include pour spécifier les champs de données à renvoyer, y compris les données vectorielles, les documents et toutes les données dans les métadonnées. Par défaut, Chroma renvoie les documents, les métadonnées et les distances vectorielles. Vous pouvez spécifier les champs à renvoyer en passant un tableau de noms de champs au paramètre d'inclusion de la méthode get ou query.

collection.get(
    include=["documents"]
)

collection.query(
    query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
    include=["documents"]
)

Utilisation des filtres where

Chroma prend en charge le filtrage des requêtes en fonction des métadonnées et du contenu du document. Le filtre where est utilisé pour filtrer les métadonnées, et le filtre where_document est utilisé pour filtrer le contenu du document. Ci-dessous, nous expliquons comment écrire des expressions de conditions de filtre.

Filtrage par métadonnées

Pour filtrer les métadonnées, un dictionnaire de filtre where doit être fourni pour la requête. Le dictionnaire doit avoir la structure suivante :

{
    "champ_metadata": {
        <Opérateur>: <Valeur>
    }
}

Le filtrage des métadonnées prend en charge les opérateurs suivants :

  • $eq - Égal à (chaîne, entier, flottant)
  • $ne - Non égal à (chaîne, entier, flottant)
  • $gt - Supérieur à (entier, flottant)
  • $gte - Supérieur ou égal à (entier, flottant)
  • $lt - Inférieur à (entier, flottant)
  • $lte - Inférieur ou égal à (entier, flottant)

L'utilisation de l'opérateur $eq équivaut à utiliser le filtre where.

{
    "champ_metadata": "chaîne_de_recherche"
}


{
    "champ_metadata": {
        "$eq": "chaîne_de_recherche"
    }
}

Filtrage du contenu du document

Pour filtrer le contenu du document, un dictionnaire de filtre where_document doit être fourni pour la requête. Le dictionnaire doit avoir la structure suivante :

{
    "$contains": "chaîne_de_recherche"
}

Utilisation des opérateurs logiques

Vous pouvez également utiliser les opérateurs logiques $and et $or pour combiner plusieurs filtres.

L'opérateur $and renverra les résultats correspondant à tous les filtres de la liste.

{
    "$and": [
        {
            "champ_metadata": {
                <Opérateur>: <Valeur>
            }
        },
        {
            "champ_metadata": {
                <Opérateur>: <Valeur>
            }
        }
    ]
}

L'opérateur $or renverra les résultats correspondant à n'importe quelle condition de filtrage de la liste.

{
    "$or": [
        {
            "champ_metadata": {
                <Opérateur>: <Valeur>
            }
        },
        {
            "champ_metadata": {
                <Opérateur>: <Valeur>
            }
        }
    ]
}

Mise à jour des données

Chroma prend également en charge l'opération upsert, qui peut mettre à jour les données existantes et insérer de nouvelles données si les données n'existent pas.

await collection.upsert({
    ids: ["id1", "id2", "id3"],
    embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2]],
    metadatas: [{"chapitre": "3", "verset": "16"}, {"chapitre": "3", "verset": "5"}, {"chapitre": "29", "verset": "11"}],
    documents: ["doc1", "doc2", "doc3"]
})

Suppression des données

Chroma prend en charge l'utilisation de .delete pour supprimer des données de la collection par id.

await collection.delete({
    ids: ["id1", "id2", "id3",...], //ids
    where: {"chapitre": "20"} //where
})