Inicialización de Datos Cromáticos Persistentes

import { ChromaClient } from 'chromadb'

Inicializando el Cliente

const cliente = new ChromaClient();

Operaciones Comunes del Cliente

await client.reset() // Limpiar la base de datos

Trabajando con Colecciones

Chromadb utiliza el concepto de colección para gestionar conjuntos de datos vectoriales, que se pueden asemejar a las tablas en MySQL.

Crear, Ver y Borrar Colecciones

Chroma utiliza el nombre de la colección en la URL, por lo que hay algunas restricciones de nomenclatura:

  • La longitud del nombre debe estar entre 3 y 63 caracteres.
  • El nombre debe comenzar y terminar con letras minúsculas o números, y puede contener puntos, guiones y guiones bajos en el medio.
  • El nombre no puede contener dos puntos consecutivos.
  • El nombre no puede ser una dirección IP válida.

Para crear una colección, se debe especificar el nombre de la colección y una función de cálculo de vector opcional (también conocida como función de incrustación). Si se proporciona una función de incrustación, debe proporcionarse cada vez que se accede a la colección.

Nota: La función de incrustación se utiliza para calcular vectores de texto.

import { ChromaClient } from 'chromadb'

Crear y hacer referencia a una colección como se muestra a continuación:

let colección = await cliente.createCollection({nombre: "mi_colección", funciónDeIncrustación: emb_fn})

let colección2 = await cliente.getCollection({nombre: "mi_colección", funciónDeIncrustación: emb_fn})

La función de incrustación toma texto como entrada y devuelve datos vectoriales calculados.

Nota: Los principiantes pueden aprender sobre modelos de incrustación de texto en este tutorial.

Las colecciones existentes pueden ser referenciadas usando .getCollection por nombre, y también pueden ser eliminadas usando .deleteCollection.

const colección = await cliente.getCollection({nombre: "tizi365"}) // Referencia la colección tizi365
await cliente.deleteCollection({nombre: "mi_colección"}) // Eliminar la colección

Funciones Comunes de la Colección

await colección.peek() // Devuelve los primeros 10 registros de datos en la colección
await colección.count() // Devuelve el número total de registros de datos en la colección

Ajuste de Métodos de Cálculo de Distancia Vectorial

La función createCollection también incluye un parámetro opcional metadata, donde el valor de hnsw:space se puede establecer para personalizar el método de cálculo de distancia para el espacio vectorial.

Nota: Los datos vectoriales representan la similitud entre vectores calculando la distancia espacial entre ellos, con distancias más cercanas que indican una mayor similitud y viceversa.

let colección = cliente.createCollection("nombre_de_colección", undefined, metadata={ "hnsw:space": "coseno" })

Las opciones válidas para hnsw:space son "l2", "ip", o "coseno". El valor predeterminado es "l2".

Agregar datos a una colección

Utiliza .add para agregar datos a la colección de Chroma.

Agrega datos directamente sin especificar vectores de documentos:

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    metadatos: [{"capítulo": "3", "versículo": "16"}, {"capítulo": "3", "versículo": "5"}, {"capítulo": "29", "versículo": "11"}, ...],
    documentos: ["lorem ipsum...", "doc2", "doc3", ...],
})
// Explicación de parámetros
// ids - requerido
// embeddings - opcional
// metadatos - opcional
// documentos - opcional

Si Chroma recibe una lista de documentos, automáticamente utilizará la función de embedding de la colección para calcular vectores para los documentos (si no se proporcionó una función de embedding al crear la colección, se usará el valor predeterminado). Chroma también almacenará los propios documentos. Si un documento es demasiado grande para usarse con la función de embedding seleccionada, se producirá una excepción.

Cada documento debe tener un ID único (ids). Agregar el mismo ID dos veces resultará en que solo se almacene el valor inicial. Se puede proporcionar una lista opcional de diccionarios de metadatos (metadatos) para cada documento, para almacenar información adicional para filtrar datos durante consultas.

Alternativamente, puedes proporcionar directamente una lista de datos de vectores relacionados con documentos, y Chroma utilizará los datos vectoriales que proporciones sin calcular automáticamente el vector.

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], ...],
    metadatos: [{"capítulo": "3", "versículo": "16"}, {"capítulo": "3", "versículo": "5"}, {"capítulo": "29", "versículo": "11"}, ...],
    documentos: ["lorem ipsum...", "doc2", "doc3", ...],
})

Si las dimensiones (longitud) de los datos vectoriales proporcionados no coinciden con las dimensiones de la colección, se producirá una excepción.

También puedes almacenar documentos en otro lugar y simplemente proporcionar los datos vectoriales y la lista de metadatos a Chroma. Puedes usar los ids para asociar los vectores con los documentos almacenados en otro lugar.

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], ...],
    metadatos: [{"capítulo": "3", "versículo": "16"}, {"capítulo": "3", "versículo": "5"}, {"capítulo": "29", "versículo": "11"}, ...],
})

Nota: La función principal de la base de datos vectoriales es la búsqueda de similitud semántica basada en datos vectoriales. Para reducir el tamaño de la base de datos vectoriales y mejorar la eficiencia, podemos optar por almacenar datos vectoriales y algunas condiciones de atributos filtrables en la base de datos vectoriales. Otros datos, como el contenido de un artículo, se pueden almacenar en bases de datos como MYSQL, siempre y cuando estén asociados a través de IDs.

Consulta de datos de colección

El método .query se puede utilizar para consultar el conjunto de datos de Chroma de varias formas.

Puede realizar consultas utilizando un conjunto de query_embeddings (datos vectoriales).

Tip: Para obtener los query_embeddings, en escenarios de desarrollo reales, es común que la consulta del usuario se calcule primero en un vector de consulta a través de un modelo de inserción de texto, y luego este vector se utiliza para consultar contenido similar.

const resultado = await collection.query({
    queryEmbeddings: [[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
    nResults: 10,
    where: {"campo_metadatos": "es_igual_a_esto"},
})
// orden de entrada
// query_embeddings - opcional
// n_results - requerido
// where - opcional
// query_texts - opcional

La consulta devolverá los mejores resultados de n_results para cada vector de consulta (query_embedding) en orden. Se puede proporcionar un diccionario opcional de filtro where para filtrar los resultados basados en metadatos asociados con cada documento. Además, se puede proporcionar un diccionario de filtro where_document opcional para filtrar los resultados basados en el contenido del documento.

Si los query_embeddings proporcionados no son consistentes con las dimensiones de la colección, se producirá una excepción. Para garantizar la consistencia del vector, se recomienda utilizar el mismo modelo de inserción de texto para calcular los vectores.

También se puede realizar una consulta utilizando un conjunto de textos de consulta. Chroma calculará primero el vector para cada texto de consulta utilizando la función de inserción de texto de la colección, y luego ejecutará la consulta utilizando los vectores de texto generados.

await collection.query({
    nResults: 10, // n_results
    where: {"campo_metadatos": "es_igual_a_esto"}, // where
    queryTexts: ["doc10", "thus spake zarathustra", ...], // query_text
})

También se puede utilizar .get para consultar datos de la colección por id.

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

.get también admite filtros where y where_document. Si no se proporciona un id, devolverá todos los datos en la colección que coincidan con los filtros where y where_document.

Especificación de campos devueltos

Al utilizar get o query, se puede utilizar el parámetro include para especificar los campos de datos que se van a devolver, incluidos los datos vectoriales, documentos y cualquier dato en los metadatos. De forma predeterminada, Chroma devuelve documentos, metadatos y distancias vectoriales. Se pueden especificar los campos a devolver pasando un array de nombres de campo al parámetro includes de get o query.

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

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

Uso de filtros where

Chroma admite consultas de filtrado basadas en metadatos y contenido del documento. El filtro where se utiliza para filtrar metadatos, y el filtro where_document se utiliza para filtrar el contenido del documento. A continuación, explicamos cómo escribir expresiones de condición de filtro.

Filtrado por metadatos

Para filtrar metadatos, se debe proporcionar un diccionario de filtro where para la consulta. El diccionario debe tener la siguiente estructura:

{
    "campo_metadatos": {
        <Operador>: <Valor>
    }
}

El filtrado de metadatos admite los siguientes operadores:

  • $eq - Igual a (cadena, entero, flotante)
  • $ne - No es igual a (cadena, entero, flotante)
  • $gt - Mayor que (entero, flotante)
  • $gte - Mayor o igual que (entero, flotante)
  • $lt - Menor que (entero, flotante)
  • $lte - Menor o igual que (entero, flotante)

Usar el operador $eq es equivalente a utilizar el filtro where.

{
    "campo_metadatos": "cadena_de_búsqueda"
}


{
    "campo_metadatos": {
        "$eq": "cadena_de_búsqueda"
    }
}

Filtrado del contenido del documento

Para filtrar el contenido del documento, se debe proporcionar un diccionario de filtro where_document para la consulta. El diccionario debe tener la siguiente estructura:

{
    "$contains": "cadena_de_búsqueda"
}

Uso de Operadores Lógicos

También puedes utilizar los operadores lógicos $and y $or para combinar múltiples filtros.

El operador $and devolverá resultados que coincidan con todos los filtros en la lista.

{
    "$and": [
        {
            "metadata_field": {
                <Operador>: <Valor>
            }
        },
        {
            "metadata_field": {
                <Operador>: <Valor>
            }
        }
    ]
}

El operador $or devolverá resultados que coincidan con cualquier condición de filtrado en la lista.

{
    "$or": [
        {
            "metadata_field": {
                <Operador>: <Valor>
            }
        },
        {
            "metadata_field": {
                <Operador>: <Valor>
            }
        }
    ]
}

Actualización de Datos

Chroma también admite la operación de inserción, que puede actualizar datos existentes e insertar nuevos datos si los datos no existen.

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: [{"capítulo": "3", "versículo": "16"}, {"capítulo": "3", "versículo": "5"}, {"capítulo": "29", "versículo": "11"}],
    documentos: ["doc1", "doc2", "doc3"]
})

Eliminación de Datos

Chroma admite el uso de .delete para eliminar datos de la colección por id.

await collection.delete({
    ids: ["id1", "id2", "id3",...], //ids
    where: {"capítulo": "20"} //dónde
})