milvus-logo
LFAI
Home
  • Guía del usuario

Diseño práctico de esquemas

Los sistemas de recuperación de información (IR), también conocidos como búsqueda, son esenciales para varias aplicaciones de IA, como la generación aumentada de recuperación (RAG), la búsqueda de imágenes y la recomendación de productos. El primer paso en el desarrollo de un sistema de RI es diseñar el modelo de datos, lo que implica analizar los requisitos empresariales, determinar cómo organizar la información e indexar los datos para hacerlos semánticamente buscables.

Milvus permite definir el modelo de datos mediante un esquema de colección. Una colección organiza datos no estructurados como texto e imágenes, junto con sus representaciones vectoriales, incluidos vectores densos y dispersos en varias precisiones utilizadas para la búsqueda semántica. Además, Milvus admite el almacenamiento y filtrado de tipos de datos no vectoriales denominados "Scalar". Los tipos escalares incluyen BOOL, INT8/16/32/64, FLOAT/DOUBLE, VARCHAR, JSON y Array.

Example data schema designed for searching news article Ejemplo de esquema de datos diseñado para la búsqueda de artículos de noticias

El diseño del modelo de datos de un sistema de búsqueda implica analizar las necesidades del negocio y abstraer la información en un modelo de datos expresado en un esquema. Por ejemplo, para buscar un fragmento de texto, debe "indexarse" convirtiendo la cadena literal en un vector mediante "incrustación", lo que permite la búsqueda vectorial. Más allá de este requisito básico, puede ser necesario almacenar otras propiedades, como la fecha de publicación y el autor. Estos metadatos permiten refinar las búsquedas semánticas mediante filtrado, devolviendo sólo los textos publicados después de una fecha concreta o por un autor determinado. También puede ser necesario recuperarlos junto con el texto principal, para mostrar el resultado de la búsqueda en la aplicación. Para organizar estos fragmentos de texto, debe asignarse a cada uno un identificador único, expresado como un número entero o una cadena. Estos elementos son esenciales para lograr una lógica de búsqueda sofisticada.

Un esquema bien diseñado es importante, ya que abstrae el modelo de datos y decide si los objetivos empresariales pueden alcanzarse mediante la búsqueda. Además, dado que cada fila de datos insertada en la colección debe seguir el esquema, éste ayuda en gran medida a mantener la coherencia de los datos y la calidad a largo plazo. Desde un punto de vista técnico, un esquema bien definido conduce a un almacenamiento de datos de columnas bien organizado y a una estructura de índices más limpia, lo que puede aumentar el rendimiento de las búsquedas.

Un ejemplo: Búsqueda de noticias

Supongamos que queremos crear una búsqueda para un sitio web de noticias y tenemos un corpus de noticias con texto, imágenes en miniatura y otros metadatos. En primer lugar, tenemos que analizar cómo queremos utilizar los datos para satisfacer las necesidades de búsqueda de la empresa. Imaginemos que el requisito es recuperar las noticias basándonos en la imagen en miniatura y el resumen del contenido, y tomando los metadatos, como la información sobre el autor y la hora de publicación, como criterios para filtrar el resultado de la búsqueda. Estos requisitos pueden desglosarse en.

  • Para buscar imágenes a través del texto, podemos incrustar imágenes en vectores mediante un modelo de incrustación multimodal capaz de mapear datos de texto e imágenes en el mismo espacio latente.

  • El texto resumido de un artículo se incrusta en vectores mediante un modelo de incrustación de texto.

  • Para filtrar en función de la hora de publicación, las fechas se almacenan como un campo escalar y se necesita un índice para el campo escalar para un filtrado eficaz. Otras estructuras de datos más complejas, como JSON, se pueden almacenar en un escalar y realizar una búsqueda filtrada en su contenido (la indexación de JSON es una función de próxima aparición).

  • Para recuperar los bytes de la miniatura de la imagen y mostrarla en la página de resultados de la búsqueda, también se almacena la url de la imagen. Lo mismo ocurre con el texto y el título del resumen. (Alternativamente, podríamos almacenar el texto sin procesar y los datos del archivo de imagen como campos escalares si fuera necesario).

  • Para mejorar el resultado de la búsqueda en el texto resumido, diseñamos un método de búsqueda híbrido. Para una ruta de recuperación, utilizamos un modelo de incrustación regular para generar un vector denso a partir del texto, como el de OpenAI text-embedding-3-large o el de código abierto bge-large-en-v1.5. Estos modelos representan bien la semántica general del texto. La otra vía es utilizar modelos de incrustación dispersos, como BM25 o SPLADE, para generar un vector disperso, parecido a la búsqueda de texto completo, que es bueno para captar los detalles y los conceptos individuales del texto. Milvus permite utilizar ambos en la misma recopilación de datos gracias a su función multivectorial. La búsqueda en múltiples vectores puede realizarse en una única operación hybrid_search().

  • Por último, también necesitamos un campo ID para identificar cada página de noticias individual, formalmente denominada "entidad" en la terminología de Milvus. Este campo se utiliza como clave primaria (o "pk" para abreviar).

Nombre del campo

article_id (clave primaria)

título

author_info

publicar_ts

URL_imagen

vector_imagen

resumen

resumen_vector_denso

resumen_vector_denso

Tipo

INT64

VARCHAR

JSON

INT32

VARCHAR

FLOAT_VECTOR

VARCHAR

FLOAT_VECTOR

VECTOR_FLOAT_ESPARCIDO

Índice de necesidad

N

N

N (Soporte próximamente)

Y

N

Y

N

Y

Y

Cómo implementar el esquema de ejemplo

Crear esquema

En primer lugar, creamos una instancia de cliente Milvus, que puede utilizarse para conectarse al servidor Milvus y gestionar colecciones y datos.

Para crear un esquema, utilizamos create_schema() para crear un objeto de esquema y add_field() para añadir campos al esquema.

from pymilvus import MilvusClient, DataType

collection_name = "my_collection"

# client = MilvusClient(uri="http://localhost:19530")
client = MilvusClient(uri="./milvus_demo.db")

schema = MilvusClient.create_schema(
    auto_id=False,
)

schema.add_field(field_name="article_id", datatype=DataType.INT64, is_primary=True, description="article id")
schema.add_field(field_name="title", datatype=DataType.VARCHAR, max_length=200, description="article title")
schema.add_field(field_name="author_info", datatype=DataType.JSON, description="author information")
schema.add_field(field_name="publish_ts", datatype=DataType.INT32, description="publish timestamp")
schema.add_field(field_name="image_url", datatype=DataType.VARCHAR,  max_length=500, description="image URL")
schema.add_field(field_name="image_vector", datatype=DataType.FLOAT_VECTOR, dim=768, description="image vector")
schema.add_field(field_name="summary", datatype=DataType.VARCHAR, max_length=1000, description="article summary")
schema.add_field(field_name="summary_dense_vector", datatype=DataType.FLOAT_VECTOR, dim=768, description="summary dense vector")
schema.add_field(field_name="summary_sparse_vector", datatype=DataType.SPARSE_FLOAT_VECTOR, description="summary sparse vector")

Es posible que observe el argumento uri en MilvusClient, que se utiliza para conectarse al servidor Milvus. Puede configurar los argumentos de la siguiente manera.

  • Si sólo necesita una base de datos vectorial local para datos a pequeña escala o prototipos, establecer la uri como un archivo local, por ejemplo./milvus.db, es el método más conveniente, ya que utiliza automáticamente Milvus Lite para almacenar todos los datos en este archivo.

  • Si tiene una gran escala de datos, digamos más de un millón de vectores, puede configurar un servidor Milvus más eficiente en Docker o Kubernetes. En esta configuración, por favor utilice la dirección del servidor y el puerto como su uri, por ejemplohttp://localhost:19530. Si habilita la función de autenticación en Milvus, utilice "<su_nombre_de_usuario>:<su_contraseña>" como token, de lo contrario no configure el token.

  • Si utiliza Zilliz Cloud, el servicio en la nube totalmente gestionado para Milvus, ajuste los uri y token, que corresponden al Public Endpoint y a la clave API en Zilliz Cloud.

En cuanto a auto_id en MilvusClient.create_schema, AutoID es un atributo del campo primario que determina si se habilita el autoincremento para el campo primario. Dado que establecemos el campoarticle_id como clave primaria y queremos añadir el id del artículo manualmente, establecemos auto_id False para deshabilitar esta característica.

Después de añadir todos los campos al objeto de esquema, nuestro objeto de esquema coincide con las entradas de la tabla anterior.

Definir índice

Tras definir el esquema con varios campos, incluidos los metadatos y los campos vectoriales para los datos de imagen y resumen, el siguiente paso consiste en preparar los parámetros del índice. La indexación es crucial para optimizar la búsqueda y recuperación de vectores, garantizando un rendimiento eficiente de las consultas. En la siguiente sección, definiremos los parámetros de índice para los campos vectoriales y escalares especificados en la colección.

index_params = client.prepare_index_params()

index_params.add_index(
    field_name="image_vector",
    index_type="AUTOINDEX",
    metric_type="IP",
)
index_params.add_index(
    field_name="summary_dense_vector",
    index_type="AUTOINDEX",
    metric_type="IP",
)
index_params.add_index(
    field_name="summary_sparse_vector",
    index_type="SPARSE_INVERTED_INDEX",
    metric_type="IP",
)
index_params.add_index(
    field_name="publish_ts",
    index_type="INVERTED",
)

Una vez configurados y aplicados los parámetros de indexación, Milvus está optimizado para manejar consultas complejas sobre datos vectoriales y escalares. Esta indexación mejora el rendimiento y la precisión de las búsquedas de similitud dentro de la colección, permitiendo una recuperación eficiente de artículos basados en vectores de imagen y vectores de resumen. Al aprovechar el AUTOINDEX para vectores densos, el SPARSE_INVERTED_INDEX para vectores dispersos y el INVERTED_INDEX para escalares, Milvus puede identificar y devolver rápidamente los resultados más relevantes, mejorando significativamente la experiencia general del usuario y la eficacia del proceso de recuperación de datos.

Existen muchos tipos de índices y métricas. Para más información sobre ellos, puede consultar Milvus tipo de índice y Milvus tipo de métrica.

Crear colección

Con el esquema y los índices definidos, creamos una "colección" con estos parámetros. La colección para Milvus es como una tabla para una base de datos relacional.

client.create_collection(
    collection_name=collection_name,
    schema=schema,
    index_params=index_params,
)

Podemos verificar que la colección se ha creado correctamente describiendo la colección.

collection_desc = client.describe_collection(
    collection_name=collection_name
)
print(collection_desc)

Otras consideraciones

Carga del índice

Al crear una colección en Milvus, puede elegir cargar el índice inmediatamente o aplazarlo hasta después de la ingesta masiva de algunos datos. Normalmente, no necesita hacer una elección explícita al respecto, ya que los ejemplos anteriores muestran que el índice se construye automáticamente para cualquier dato ingestado justo después de la creación de la colección. Esto permite la búsqueda inmediata de los datos ingestados. Sin embargo, si tiene una gran inserción masiva después de la creación de la colección y no necesita buscar ningún dato hasta cierto punto, puede aplazar la creación del índice omitiendo index_params en la creación de la colección y crear el índice llamando explícitamente a load después de la ingesta de todos los datos. Este método es más eficiente para construir el índice en una colección grande, pero no se pueden realizar búsquedas hasta que se llame a load().

Cómo definir el modelo de datos para múltiples inquilinos

El concepto de múltiples inquilinos es comúnmente usado en escenarios donde una sola aplicación de software o servicio necesita servir a múltiples usuarios u organizaciones independientes, cada uno con su propio ambiente aislado. Esto se ve con frecuencia en la computación en nube, las aplicaciones SaaS (software como servicio) y los sistemas de bases de datos. Por ejemplo, un servicio de almacenamiento en la nube puede utilizar la multitenencia para permitir que distintas empresas almacenen y gestionen sus datos por separado mientras comparten la misma infraestructura subyacente. Este enfoque maximiza la utilización de los recursos y la eficiencia, al tiempo que garantiza la seguridad y la privacidad de los datos de cada inquilino.

La forma más sencilla de diferenciar a los inquilinos es aislar sus datos y recursos entre sí. Cada inquilino tiene acceso exclusivo a recursos específicos o comparte recursos con otros para gestionar entidades Milvus como bases de datos, colecciones y particiones. Existen métodos específicos alineados con estas entidades para implementar Milvus multi-tenancy. Puede consultar la página multi-tenancy de Milvus para más información.

Traducido porDeepL

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
Feedback

¿Fue útil esta página?