Saltar al contenido principal
El conjunto de datos Laion-400M contiene 400 millones de imágenes con subtítulos en inglés. Actualmente, Laion ofrece un conjunto de datos aún mayor, pero trabajar con él será similar. El conjunto de datos contiene la URL de la imagen, embeddings tanto de la imagen como de su subtítulo, una puntuación de similitud entre la imagen y su subtítulo, así como metadatos; por ejemplo, el ancho y el alto de la imagen, la licencia y un indicador NSFW. Podemos usar este conjunto de datos para demostrar la búsqueda aproximada de vecinos más cercanos en ClickHouse.

Preparación de datos

Los embeddings y los metadatos se almacenan en archivos separados dentro de los datos brutos. En un paso de preparación de datos, se descargan los datos, se fusionan los archivos, se convierten a CSV y se importan en ClickHouse. Para ello, puede usar el siguiente script download.sh:
El script process.py se define de la siguiente manera:
Para iniciar el pipeline de preparación de datos, ejecuta:
El conjunto de datos está dividido en 410 archivos; cada archivo contiene aprox. 1 millón de filas. Si prefieres trabajar con un subconjunto más pequeño de los datos, simplemente ajusta los límites; p. ej., seq 0 9 | .... (El script de Python anterior es muy lento (~2-10 minutos por archivo), consume mucha memoria (41 GB por archivo) y los archivos CSV resultantes son grandes (10 GB cada uno), así que ten cuidado. Si tienes suficiente RAM, aumenta el valor de -P1 para obtener más paralelismo. Si aun así sigue siendo demasiado lento, considera idear un procedimiento de ingestión mejor; quizá convirtiendo los archivos .npy a Parquet y luego haciendo el resto del procesamiento con ClickHouse.)

Crear tabla

Para crear una tabla sin índices inicialmente, ejecute:
Para importar los archivos CSV en ClickHouse:
Ten en cuenta que la columna id es solo ilustrativa y el script la rellena con valores no únicos. Para realizar una búsqueda vectorial aproximada por fuerza bruta, ejecuta:
target es un array de 512 elementos y un parámetro del cliente. Al final del artículo se mostrará una forma práctica de obtener arrays de este tipo. Por ahora, podemos usar como target el embedding de una imagen aleatoria de un set de LEGO. Resultado

Realiza una búsqueda aproximada de similitud vectorial con un índice de similitud vectorial

Ahora definamos dos índices de similitud vectorial en la tabla.
Los parámetros y las consideraciones de rendimiento para la creación de índices y la búsqueda se describen en la documentación. La definición del índice anterior especifica un índice HNSW que utiliza la “distancia de coseno” como métrica de distancia, con el parámetro “hnsw_max_connections_per_layer” establecido en 64 y el parámetro “hnsw_candidate_list_size_for_construction” establecido en 256. El índice utiliza bfloat16 (brain floating point) de media precisión como cuantización para optimizar el uso de memoria. Para construir y materializar el índice, ejecute estas Sentencias:
Crear y guardar el índice puede tardar unos minutos o incluso horas, según el número de filas y los parámetros del índice HNSW. Para realizar una búsqueda vectorial, solo ejecute la misma consulta de nuevo:
Resultado
La latencia de la consulta disminuyó significativamente porque los vecinos más cercanos se obtuvieron mediante el índice vectorial. La búsqueda por similitud vectorial con un índice de similitud vectorial puede devolver resultados que difieran ligeramente de los de la búsqueda por fuerza bruta. Un índice HNSW puede alcanzar potencialmente un recall cercano a 1 (la misma precisión que la búsqueda por fuerza bruta) con una selección cuidadosa de los parámetros de HNSW y evaluando la calidad del índice.

Crear embeddings con UDFs

Normalmente, se quiere crear embeddings para imágenes nuevas o nuevos subtítulos de imágenes y buscar pares similares de imagen/subtítulo en los datos. Podemos usar UDF para crear el vector target sin salir del cliente. Es importante usar el mismo modelo para crear los datos y los nuevos embeddings para las búsquedas. Los siguientes scripts utilizan el modelo ViT-B/32, que es también el que subyace al conjunto de datos.

Embeddings de texto

Primero, guarde el siguiente script de Python en el directorio user_scripts/ de la ruta de datos de ClickHouse y hágalo ejecutable (chmod +x encode_text.py). encode_text.py:
Luego, cree encode_text_function.xml en una ubicación referenciada por <user_defined_executable_functions_config>/path/to/*_function.xml</user_defined_executable_functions_config> en el archivo de configuración del servidor ClickHouse.
Ahora puedes usar simplemente:
La primera ejecución será lenta porque carga el modelo, pero las siguientes serán rápidas. Después, podemos copiar la salida en SET param_target=... y escribir consultas fácilmente. Como alternativa, la función encode_text() puede usarse directamente como argumento de la función cosineDistance :
Ten en cuenta que la propia UDF encode_text() podría tardar unos segundos en calcular y generar el vector de embedding.

Embeddings de imágenes

Los embeddings de imágenes pueden crearse de forma similar, y proporcionamos un script de Python que puede generar el embedding de una imagen almacenada localmente en un archivo. encode_image.py
encode_image_function.xml
Descarga una imagen de ejemplo para buscar:
A continuación, ejecuta esta consulta para generar el embedding de la imagen anterior:
La consulta de búsqueda completa es:
Última modificación el 2 de julio de 2026