Guía detallada de desarrollo de Chromadb Python

Instalación

pip install chromadb

Persistencia de datos de Chromadb

import chromadb

Puede especificar la ruta de almacenamiento para el archivo de la base de datos de Chroma. Si los datos existen, el archivo de la base de datos se cargará automáticamente cuando se inicie el programa.

cliente = chromadb.PersistentClient(path="/data/tizi365.db")

El parámetro path es la ruta al archivo de la base de datos de Chroma.

Nota: para una base de datos de Chroma, crear un objeto cliente una vez es suficiente. Cargar y guardar varios clientes en la misma ruta puede provocar un comportamiento inesperado, incluida la eliminación de datos. Generalmente, solo se debe crear un cliente de Chroma en la aplicación.

Algunas funciones comúnmente utilizadas del objeto cliente:

cliente.reset()  # Borra y restablece completamente la base de datos

Operaciones de colección

Chromadb utiliza el primitivo collection para gestionar colecciones de datos vectoriales, que se pueden asemejar a tablas en MYSQL.

Crear, ver y eliminar colecciones

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

  • La longitud del nombre debe estar entre 3 y 63 caracteres.
  • El nombre debe comenzar y terminar con una letra minúscula o un número, 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, debe especificar el nombre de la colección y una función de cálculo de vectores 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: el propósito de la función de cálculo de vectores (función de incrustación) es calcular el vector de texto.

colección = cliente.create_collection(name="mi_colección", embedding_function=emb_fn)
colección = cliente.get_collection(name="mi_colección", embedding_function=emb_fn)

La función de incrustación toma texto como entrada y devuelve un vector calculado.

Nota: Los principiantes pueden aprender sobre tutoriales de modelos de incrustación de texto.

Puede hacer referencia a una colección existente con la función .get_collection, y usar .delete_collection para eliminar una colección. También puede usar .get_or_create_collection para hacer referencia a una colección (si existe) o crearla si no existe.

colección = cliente.get_collection(name="tizi365")
colección = cliente.get_or_create_collection(name="tizi365")
cliente.delete_collection(name="tizi365")

Otras operaciones de colección comúnmente utilizadas:

colección.peek() # Devuelve una lista de los primeros 10 datos de la colección
colección.count() # Devuelve el número total de datos en la colección
colección.modify(name="nuevo_nombre") # Cambia el nombre de la colección

Especificar el método de cálculo de la distancia del vector

La función create_collection también incluye un parámetro opcional de metadatos. Al establecer el valor de hnsw:space personaliza el método de cálculo de la distancia en el espacio vectorial.

Nota: Los datos vectoriales representan la similitud entre vectores mediante el cálculo de la distancia espacial entre vectores. Cuanto más cercana sea la distancia, mayor será la similitud, y viceversa.

colección = cliente.create_collection(
        name="nombre_colección",
        metadata={"hnsw:space": "coseno"} # l2 es el método de cálculo predeterminado
    )

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

Agregar datos a una colección

Utilice el método .add para agregar datos a Chroma.

Agregue datos directamente sin especificar vectores de documento:

collection.add(
    documents=["lorem ipsum...", "doc2", "doc3", ...],
    metadatas=[{"capítulo": "3", "versículo": "16"}, {"capítulo": "3", "versículo": "5"}, {"capítulo": "29", "versículo": "11"}, ...],
    ids=["id1", "id2", "id3", ...]
)

Si Chroma recibe una lista de documentos, automáticamente utilizará la función de embedding de la colección para calcular los vectores de los documentos (si no se proporcionó una función de embedding al crear la colección, se utilizará el valor predeterminado). Chroma también almacenará los propios documentos. Si un documento es demasiado grande para calcularlo utilizando 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 almacenar el valor inicial solamente. Opcionalmente, puede proporcionar una lista de diccionarios de metadatos (metadatas) para cada documento, para almacenar información adicional que se puede usar para filtrar datos durante consultas.

Alternativamente, puede proporcionar directamente una lista de los datos vectoriales relacionados con el documento, y Chroma utilizará los datos vectoriales que usted proporcione sin calcular automáticamente los vectores.

collection.add(
    documents=["doc1", "doc2", "doc3", ...],
    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"}, ...],
    ids=["id1", "id2", "id3", ...]
)

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

También puede almacenar los documentos en otro lugar y proporcionar a Chroma los datos vectoriales y la lista de metadatos. Puede usar IDs para asociar los vectores con los documentos almacenados en otro lugar.

collection.add(
    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"}, ...],
    ids=["id1", "id2", "id3", ...]
)

Nota: La función principal de la base de datos vectorial 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 elegir almacenar los datos vectoriales y algunos atributos de filtrado necesarios en la base de datos vectorial. Otros datos, como el contenido del 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 conjuntos de datos de Chroma de varias formas.

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

Consejo: En escenarios reales de desarrollo, los query_embeddings suelen obtenerse primero calculando el vector de la consulta del usuario a través de un modelo de incrustación de texto, y luego utilizando este vector para consultar contenido similar.

collection.query(
    query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
    n_results=10,
    where={"campo_de_metadatos": "es_igual_a_esto"},
    where_document={"$contains":"cadena_de_búsqueda"}
)

La consulta devolverá los n_results resultados que mejor coincidan con cada vector de consulta (query_embedding) en secuencia. Se puede proporcionar un diccionario de filtro opcional where para filtrar resultados basados en metadatos asociados con cada documento. Además, se puede proporcionar un diccionario de filtro where_document opcional para filtrar 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 dimensiones de vectores consistentes, utilice el mismo modelo de incrustación de texto para calcular vectores.

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

collection.query(
    query_texts=["doc10", "thus spake zarathustra", ...],
    n_results=10,
    where={"campo_de_metadatos": "es_igual_a_esto"},
    where_document={"$contains":"cadena_de_búsqueda"}
)

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

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

.get también admite filtros where y where_document. Si no se proporciona ningún id, devolverá todos los elementos de la colección que coincidan con los filtros where y where_document.

Especificación de campos de retorno

Al utilizar get o query, puede utilizar el parámetro include para especificar los datos que se devolverán - embeddings, documents, o metadatas, y para las consultas, es necesario devolver datos de distancia. De forma predeterminada, Chroma devuelve documentos y metadatos, y devuelve datos de distancia para consultas, mientras que "ids" siempre se devuelve. Puede especificar los campos a devolver pasando una matriz de nombres de campos al parámetro includes del método query o get.

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 la filtración de consultas basada en metadatos y contenido de documentos. El filtro where se utiliza para filtrar metadatos, y el filtro where_document se utiliza para filtrar el contenido del documento, y a continuación se explica cómo escribir expresiones de condición de filtro.

Filtrado por metadatos

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

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

El filtrado de metadatos admite los siguientes operadores:

  • $eq - igual a (cadena, entero, flotante)
  • $ne - no igual a (cadena, entero, flotante)
  • $gt - mayor que (entero, flotante)
  • $gte - mayor que o igual a (entero, flotante)
  • $lt - menor que (entero, flotante)
  • $lte - menor que o igual a (entero, flotante)

Utilizar el operador $eq es equivalente a usar el filtro where.

{
    "campo_de_metadatos": "cadena_de_búsqueda"
}

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

Filtrado del contenido del documento

Para filtrar el contenido del documento, 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 usar los operadores lógicos $and y $or para combinar múltiples filtros.

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

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

El operador $or devolverá resultados que coincidan con cualquiera de las condiciones de filtro en la lista.

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

Actualización de datos en una colección

Usar .update te permite actualizar cualquier propiedad de los datos en una colección.

colección.update(
    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=["doc1", "doc2", "doc3", ...],
)

Si un id no se encuentra en la colección, se registrará un error y la actualización se ignorará. Si el documento proporcionado no tiene un vector correspondiente, se usará la función de embedding de la colección para calcular el vector.

Si los datos de vector proporcionados tienen una dimensión diferente a la de la colección, se producirá una excepción.

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

colección.upsert(
    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=["doc1", "doc2", "doc3", ...],
)

Eliminación de datos de la colección

Chroma admite el uso de .delete para eliminar datos de una colección por id. También se eliminarán los vectores, documentos y metadatos asociados con cada dato.

colección.delete(
    ids=["id1", "id2", "id3",...],
    where={"capítulo": "20"}
)

.delete también admite un filtro where. Si no se proporciona ningún id, se eliminarán todos los elementos de la colección que coincidan con el filtro where.