Набор данных Laion-400M содержит 400 миллионов изображений с англоязычными подписями. Сейчас Laion также предоставляет ещё более крупный набор данных, но работа с ним будет похожей.
Набор данных содержит URL изображения, эмбеддинги как самого изображения, так и его подписи, оценку сходства между изображением и подписью, а также метаданные, например ширину и высоту изображения, лицензию и флаг NSFW. Этот набор данных можно использовать, чтобы продемонстрировать приближённый поиск ближайших соседей в ClickHouse.
Эмбеддинги и метаданные в исходных данных хранятся в отдельных файлах. На этапе подготовки данные загружаются, файлы объединяются,
преобразуются в CSV и импортируются в ClickHouse. Для этого можно использовать следующий скрипт download.sh:
Скрипт process.py определяется следующим образом:
Чтобы запустить конвейер подготовки данных, выполните:
Набор данных разбит на 410 файлов, каждый из которых содержит примерно 1 миллион строк. Если вы хотите работать с меньшим подмножеством данных, просто скорректируйте диапазон, например seq 0 9 | ....
(Приведённый выше скрипт Python очень медленный (~2–10 минут на файл), потребляет много памяти (41 ГБ на файл), а итоговые CSV-файлы получаются большими (по 10 ГБ каждый), поэтому будьте осторожны. Если у вас достаточно оперативной памяти, увеличьте значение -P1, чтобы повысить параллелизм. Если и этого недостаточно, подумайте о более эффективной процедуре ингестии — например, можно преобразовать файлы .npy в Parquet, а затем выполнять всю остальную обработку в ClickHouse.)
Чтобы создать таблицу без индексов, выполните:
Чтобы импортировать CSV-файлы в ClickHouse:
Обратите внимание: столбец id приведён здесь лишь для наглядности и заполняется скриптом неуникальными значениями.
Выполните векторный поиск по сходству методом полного перебора
Чтобы выполнить приближённый векторный поиск методом полного перебора, выполните:
target — это массив из 512 элементов и клиентский параметр.
Удобный способ получения таких массивов будет показан в конце статьи.
Пока же в качестве target можно использовать эмбеддинг случайного изображения набора LEGO.
Результат
Выполните приблизительный поиск по векторному сходству с помощью индекса векторного сходства
Теперь давайте создадим для таблицы два индекса векторного сходства.
Параметры и аспекты производительности при создании индекса и поиске описаны в документации.
Приведённое выше определение индекса задаёт индекс HNSW, использующий “cosine distance” в качестве метрики расстояния, с параметром “hnsw_max_connections_per_layer”, установленным в 64, и параметром “hnsw_candidate_list_size_for_construction”, установленным в 256.
Индекс использует формат bfloat16 (brain floating point половинной точности) для квантования, чтобы оптимизировать использование памяти.
Чтобы построить и материализовать индекс, выполните эти команды:
Построение и сохранение индекса может занять от нескольких минут до нескольких часов — в зависимости от количества строк и параметров индекса HNSW.
Чтобы выполнить векторный поиск, просто выполните тот же запрос ещё раз:
Результат
Время отклика запроса значительно сократилось, поскольку ближайшие соседи находились с помощью векторного индекса.
Поиск векторного сходства с использованием индекса векторного сходства может возвращать результаты, немного отличающиеся от результатов поиска полным перебором.
Индекс HNSW потенциально может обеспечить полноту, близкую к 1 (то есть такую же точность, как и при поиске полным перебором), при тщательном подборе параметров HNSW и оценке качества индекса.
Создание эмбеддингов с помощью пользовательских функций (UDF)
Обычно требуется создавать эмбеддинги для новых изображений или новых подписей к изображениям и искать в данных похожие пары «изображение / подпись к изображению». Мы можем использовать UDF, чтобы создать вектор target, не выходя из клиента. Важно использовать одну и ту же модель как для создания данных, так и для создания новых эмбеддингов для поиска. В следующих скриптах используется модель ViT-B/32, на которой также основан набор данных.
Сначала сохраните следующий Python-скрипт в каталоге user_scripts/ в каталоге с данными ClickHouse и сделайте его исполняемым (chmod +x encode_text.py).
encode_text.py:
Затем создайте encode_text_function.xml по пути, указанному в <user_defined_executable_functions_config>/path/to/*_function.xml</user_defined_executable_functions_config> в файле конфигурации сервера ClickHouse.
Теперь можно просто использовать:
Первый запуск будет медленным, потому что при нём загружается model, но последующие запуски будут быстрыми. Затем можно скопировать результат в SET param_target=... и легко писать запросы. Либо функцию encode_text() можно напрямую использовать в качестве аргумента функции cosineDistance:
Обратите внимание, что самой UDF encode_text() может потребоваться несколько секунд, чтобы вычислить и вернуть эмбеддинг-вектор.
Эмбеддинги изображений можно создавать аналогичным образом. Для этого мы предоставляем Python-скрипт, который генерирует эмбеддинг изображения, сохранённого локально в файле.
encode_image.py
encode_image_function.xml
Загрузите пример изображения для поиска:
Затем выполните этот запрос, чтобы сгенерировать эмбеддинг для приведённого выше изображения:
Полный поисковый запрос:
Последнее изменение 1 июля 2026 г.