{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "![Redis](https://redis.io/wp-content/uploads/2024/04/Logotype.svg?auto=webp&quality=85,75&width=120)\n", "# Implementing multi vector search with Redis\n", "\n", "Multi vector search is the ability to combine the scores of multiple different vector similarity values to determine relevancy. This notebook will cover how to define a multi vector index and execute multi vector queries.\n", "\n", "## Let's Begin!\n", "\"Open\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Install Packages" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install \"redisvl>=0.10.0\" sentence-transformers" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'0.16.0'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# check version\n", "import redisvl\n", "\n", "redisvl.__version__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Data/Index Preparation\n", "\n", "In this section:\n", "\n", "1. We prepare the data necessary for our multi vector search implementations by loading a collection of movies. Each movie object contains the following attributes:\n", " - `title`\n", " - `rating`\n", " - `description`\n", " - `genre`\n", "\n", "2. We'll generate vector embeddings from the movie descriptions. We'll use different models and generate multiple different vectors for each movie.\n", "\n", "3. After preparing the data, we populate a search index with these movie records, each with multiple vectors." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Running remotely or in collab? Run this cell to download the necessary dataset." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# NBVAL_SKIP\n", "!git clone https://github.com/redis-developer/redis-ai-resources.git temp_repo\n", "!mv temp_repo/python-recipes/vector-search/resources .\n", "!rm -rf temp_repo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Install Redis Stack\n", "\n", "Later in this tutorial, Redis will be used to store, index, and query vector\n", "embeddings and full text fields. **We need to have a Redis\n", "instance available.**\n", "\n", "#### Local Redis\n", "Use the shell script below to download, extract, and install [Redis Stack](https://redis.io/docs/getting-started/install-stack/) directly from the Redis package archive." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# NBVAL_SKIP\n", "%%sh\n", "curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg\n", "echo \"deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main\" | sudo tee /etc/apt/sources.list.d/redis.list\n", "sudo apt-get update > /dev/null 2>&1\n", "sudo apt-get install redis-stack-server > /dev/null 2>&1\n", "redis-stack-server --daemonize yes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Alternative Redis Access (Cloud, Docker, other)\n", "There are many ways to get the necessary redis-stack instance running\n", "1. On cloud, deploy a [FREE instance of Redis in the cloud](https://redis.com/try-free/). Or, if you have your\n", "own version of Redis Enterprise running, that works too!\n", "2. Per OS, [see the docs](https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/)\n", "3. With docker: `docker run -d --name redis-stack-server -p 6379:6379 redis/redis-stack-server:latest`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Define the Redis Connection URL\n", "\n", "By default this notebook connects to the local instance of Redis Stack. **If you have your own Redis Enterprise instance** - replace REDIS_PASSWORD, REDIS_HOST and REDIS_PORT values with your own." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import os\n", "\n", "# Replace values below with your own if using Redis Cloud instance\n", "REDIS_HOST = os.getenv(\"REDIS_HOST\", \"localhost\") # ex: \"redis-18374.c253.us-central1-1.gce.cloud.redislabs.com\"\n", "REDIS_PORT = os.getenv(\"REDIS_PORT\", \"6379\") # ex: 18374\n", "REDIS_PASSWORD = os.getenv(\"REDIS_PASSWORD\", \"\") # ex: \"1TNxTEdYRDgIDKM2gDfasupCADXXXX\"\n", "\n", "# If SSL is enabled on the endpoint, use rediss:// as the URL prefix\n", "REDIS_URL = f\"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:{REDIS_PORT}\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create redis client, load data, generate embeddings" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from redis import Redis\n", "\n", "client = Redis.from_url(REDIS_URL)\n", "client.ping()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import json\n", "\n", "with open(\"resources/movies.json\", 'r') as file:\n", " movies = json.load(file)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Multi-Vector Index with Multiple Embedding Models\n", "\n", "Now let's create a multi-vector search setup by using multiple embedding models for different aspects of our movie data. This approach allows us to:\n", "\n", "1. **Use specialized embeddings** - Different models optimized for different tasks\n", "2. **Combine multiple perspectives** - Search across different semantic representations\n", "3. **Improve search quality** - Generate embeddings from different sections of your data\n", "\n", "We'll create a new index with multiple vector fields and demonstrate how to query across them." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.\n", "WARNING:huggingface_hub.utils._http:Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "0ce4106ec33a435595e7ca66297324d5", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Loading weights: 0%| | 0/103 [00:00