diff --git a/README.md b/README.md index c7a6d5c..b63b0fc 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ RedisVL is your go-to client for: Add RedisVL to your Java (17+) project using Maven or Gradle: **Maven:** + ```xml com.redis @@ -53,18 +54,22 @@ Add RedisVL to your Java (17+) project using Maven or Gradle: ``` **Gradle:** + ```gradle implementation 'com.redis:redisvl:0.12.0' ``` ## Setting up Redis + Choose from multiple Redis deployment options: 1. [Redis Cloud](https://redis.io/try-free): Managed cloud database (free tier available) -2. [Redis Stack](https://redis.io/docs/getting-started/install-stack/docker/): Docker image for development +2. [Redis on Docker](https://hub.docker.com/_/redis): Docker image for development + ```bash docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest ``` + 3. [Redis Enterprise](https://redis.io/enterprise/): Commercial, self-hosted database 4. [Azure Managed Redis](https://azure.microsoft.com/en-us/products/managed-redis): Fully managed Redis Enterprise on Azure @@ -395,6 +400,7 @@ Check out the [notebooks](notebooks/) directory for interactive Jupyter notebook The notebooks use Java kernel support via JJava. To run them: 1. **Start the notebook environment:** + ```bash cd notebooks docker compose up -d @@ -404,6 +410,7 @@ The notebooks use Java kernel support via JJava. To run them: Navigate to [http://localhost:8888/](http://localhost:8888/) 3. **Stop when done:** + ```bash docker compose down ``` diff --git a/docs/content/antora.yml b/docs/content/antora.yml index dabd8a0..effc01a 100644 --- a/docs/content/antora.yml +++ b/docs/content/antora.yml @@ -13,6 +13,6 @@ asciidoc: redisvl-version: '0.1.0-SNAPSHOT' url-redisvl-java: https://github.com/redis/redis-vl-java url-redisvl-python: https://github.com/redis/redis-vl-python - url-redis-stack: https://redis.io/docs/stack/ + url-redis-stack: https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/ url-redis-search: https://redis.io/docs/stack/search/ url-redis-json: https://redis.io/docs/stack/json/ \ No newline at end of file diff --git a/notebooks/01_getting_started.ipynb b/notebooks/01_getting_started.ipynb index de06a8e..f7573a1 100644 --- a/notebooks/01_getting_started.ipynb +++ b/notebooks/01_getting_started.ipynb @@ -19,7 +19,7 @@ "\n", "Prerequisites:\n", "- Ensure `RedisVL` is installed in your Java environment.\n", - "- Have a running instance of [Redis Stack](https://redis.io/docs/install/install-stack/) or [Redis Cloud](https://redis.io/cloud).\n", + "- Have a running instance of [Redis Stack](https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/) or [Redis Cloud](https://redis.io/cloud).\n", "\n", "_____" ] @@ -285,7 +285,11 @@ "cell_type": "code", "execution_count": 5, "id": "mv1vdixzgjj", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "java" + } + }, "outputs": [ { "name": "stdout", @@ -354,7 +358,11 @@ "cell_type": "code", "execution_count": 7, "id": "pcexez2r69j", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "java" + } + }, "outputs": [ { "name": "stdout", diff --git a/notebooks/05_hash_vs_json.ipynb b/notebooks/05_hash_vs_json.ipynb index 2c31051..dfa9201 100644 --- a/notebooks/05_hash_vs_json.ipynb +++ b/notebooks/05_hash_vs_json.ipynb @@ -13,7 +13,7 @@ "1. Have installed RedisVL and have that environment active for this notebook.\n", "2. Have a running Redis Stack or Redis Enterprise instance with RediSearch > 2.4 activated.\n", "\n", - "For example, you can run [Redis Stack](https://redis.io/docs/install/install-stack/) locally with Docker:\n", + "For example, you can run [Redis Stack](https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/) locally with Docker:\n", "\n", "```bash\n", "docker run -d -p 6379:6379 -p 8001:8001 redis/redis-stack:latest\n", diff --git a/notebooks/11_advanced_queries.ipynb b/notebooks/11_advanced_queries.ipynb index 02785e9..45321b0 100644 --- a/notebooks/11_advanced_queries.ipynb +++ b/notebooks/11_advanced_queries.ipynb @@ -4,7 +4,21 @@ "cell_type": "markdown", "id": "intro", "metadata": {}, - "source": "# Advanced Query Types\n\nIn this notebook, we will explore advanced query types available in RedisVL:\n\n1. **`TextQuery`**: Full text search with advanced scoring\n2. **`AggregateHybridQuery`**: Combines text and vector search for hybrid retrieval\n3. **`MultiVectorQuery`**: Search over multiple vector fields simultaneously\n\nThese query types are powerful tools for building sophisticated search applications that go beyond simple vector similarity search.\n\nPrerequisites:\n- Ensure RedisVL4J is available in your Java environment.\n- Have a running instance of [Redis Stack](https://redis.io/docs/install/install-stack/) or [Redis Cloud](https://redis.io/cloud)." + "source": [ + "# Advanced Query Types\n", + "\n", + "In this notebook, we will explore advanced query types available in RedisVL:\n", + "\n", + "1. **`TextQuery`**: Full text search with advanced scoring\n", + "2. **`AggregateHybridQuery`**: Combines text and vector search for hybrid retrieval\n", + "3. **`MultiVectorQuery`**: Search over multiple vector fields simultaneously\n", + "\n", + "These query types are powerful tools for building sophisticated search applications that go beyond simple vector similarity search.\n", + "\n", + "Prerequisites:\n", + "- Ensure RedisVL4J is available in your Java environment.\n", + "- Have a running instance of [Redis Stack](https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/) or [Redis Cloud](https://redis.io/cloud)." + ] }, { "cell_type": "markdown", @@ -423,13 +437,31 @@ "cell_type": "markdown", "id": "hybrid-query-intro", "metadata": {}, - "source": "## 2. AggregateHybridQuery: Combining Text and Vector Search\n\nThe `AggregateHybridQuery` combines text search and vector similarity to provide the best of both worlds:\n- **Text search**: Finds exact keyword matches\n- **Vector search**: Captures semantic similarity\n\nResults are scored using a weighted combination:\n\n```\nhybrid_score = (alpha) * vector_score + (1 - alpha) * text_score\n```\n\nWhere `alpha` controls the balance between vector and text search (default: 0.7)." + "source": [ + "## 2. AggregateHybridQuery: Combining Text and Vector Search\n", + "\n", + "The `AggregateHybridQuery` combines text search and vector similarity to provide the best of both worlds:\n", + "- **Text search**: Finds exact keyword matches\n", + "- **Vector search**: Captures semantic similarity\n", + "\n", + "Results are scored using a weighted combination:\n", + "\n", + "```\n", + "hybrid_score = (alpha) * vector_score + (1 - alpha) * text_score\n", + "```\n", + "\n", + "Where `alpha` controls the balance between vector and text search (default: 0.7)." + ] }, { "cell_type": "markdown", "id": "hybrid-query-basic-intro", "metadata": {}, - "source": "### Basic Aggregate Hybrid Query\n\nLet's search for \"running shoes\" with both text and semantic search:" + "source": [ + "### Basic Aggregate Hybrid Query\n", + "\n", + "Let's search for \"running shoes\" with both text and semantic search:" + ] }, { "cell_type": "code", @@ -437,13 +469,36 @@ "id": "hybrid-query-basic", "metadata": {}, "outputs": [], - "source": "AggregateHybridQuery hybridQuery = AggregateHybridQuery.builder()\n .text(\"running shoes\")\n .textFieldName(\"brief_description\")\n .vector(new float[]{0.1f, 0.2f, 0.1f})\n .vectorFieldName(\"text_embedding\")\n .returnFields(Arrays.asList(\"product_id\", \"brief_description\", \"category\", \"price\"))\n .numResults(5)\n .build();\n\nList> hybridResults = index.query(hybridQuery);\n\nSystem.out.println(\"Hybrid search results:\");\nfor (Map result : hybridResults) {\n System.out.println(\" \" + result.get(\"product_id\") + \": \" + result.get(\"brief_description\"));\n}" + "source": [ + "AggregateHybridQuery hybridQuery = AggregateHybridQuery.builder()\n", + " .text(\"running shoes\")\n", + " .textFieldName(\"brief_description\")\n", + " .vector(new float[]{0.1f, 0.2f, 0.1f})\n", + " .vectorFieldName(\"text_embedding\")\n", + " .returnFields(Arrays.asList(\"product_id\", \"brief_description\", \"category\", \"price\"))\n", + " .numResults(5)\n", + " .build();\n", + "\n", + "List> hybridResults = index.query(hybridQuery);\n", + "\n", + "System.out.println(\"Hybrid search results:\");\n", + "for (Map result : hybridResults) {\n", + " System.out.println(\" \" + result.get(\"product_id\") + \": \" + result.get(\"brief_description\"));\n", + "}" + ] }, { "cell_type": "markdown", "id": "hybrid-query-alpha", "metadata": {}, - "source": "### Adjusting the Alpha Parameter\n\nThe `alpha` parameter controls the weight between vector and text search:\n- `alpha=1.0`: Pure vector search\n- `alpha=0.0`: Pure text search\n- `alpha=0.7` (default): 70% vector, 30% text" + "source": [ + "### Adjusting the Alpha Parameter\n", + "\n", + "The `alpha` parameter controls the weight between vector and text search:\n", + "- `alpha=1.0`: Pure vector search\n", + "- `alpha=0.0`: Pure text search\n", + "- `alpha=0.7` (default): 70% vector, 30% text" + ] }, { "cell_type": "code", @@ -451,13 +506,34 @@ "id": "hybrid-query-alpha-code", "metadata": {}, "outputs": [], - "source": "// More emphasis on vector search (alpha=0.9)\nAggregateHybridQuery vectorHeavyQuery = AggregateHybridQuery.builder()\n .text(\"comfortable\")\n .textFieldName(\"brief_description\")\n .vector(new float[]{0.15f, 0.25f, 0.15f})\n .vectorFieldName(\"text_embedding\")\n .alpha(0.9f) // 90% vector, 10% text\n .returnFields(Arrays.asList(\"product_id\", \"brief_description\"))\n .numResults(3)\n .build();\n\nSystem.out.println(\"Results with alpha=0.9 (vector-heavy):\");\nList> vectorHeavyResults = index.query(vectorHeavyQuery);\nfor (Map result : vectorHeavyResults) {\n System.out.println(\" \" + result.get(\"brief_description\"));\n}" + "source": [ + "// More emphasis on vector search (alpha=0.9)\n", + "AggregateHybridQuery vectorHeavyQuery = AggregateHybridQuery.builder()\n", + " .text(\"comfortable\")\n", + " .textFieldName(\"brief_description\")\n", + " .vector(new float[]{0.15f, 0.25f, 0.15f})\n", + " .vectorFieldName(\"text_embedding\")\n", + " .alpha(0.9f) // 90% vector, 10% text\n", + " .returnFields(Arrays.asList(\"product_id\", \"brief_description\"))\n", + " .numResults(3)\n", + " .build();\n", + "\n", + "System.out.println(\"Results with alpha=0.9 (vector-heavy):\");\n", + "List> vectorHeavyResults = index.query(vectorHeavyQuery);\n", + "for (Map result : vectorHeavyResults) {\n", + " System.out.println(\" \" + result.get(\"brief_description\"));\n", + "}" + ] }, { "cell_type": "markdown", "id": "hybrid-query-filter", "metadata": {}, - "source": "### Aggregate Hybrid Query with Filters\n\nYou can also combine hybrid search with filters:" + "source": [ + "### Aggregate Hybrid Query with Filters\n", + "\n", + "You can also combine hybrid search with filters:" + ] }, { "cell_type": "code", @@ -465,13 +541,34 @@ "id": "hybrid-query-filter-code", "metadata": {}, "outputs": [], - "source": "// Hybrid search with a price filter\nAggregateHybridQuery filteredHybridQuery = AggregateHybridQuery.builder()\n .text(\"professional equipment\")\n .textFieldName(\"brief_description\")\n .vector(new float[]{0.9f, 0.1f, 0.05f})\n .vectorFieldName(\"text_embedding\")\n .filterExpression(Filter.numeric(\"price\").gt(100))\n .returnFields(Arrays.asList(\"product_id\", \"brief_description\", \"category\", \"price\"))\n .numResults(5)\n .build();\n\nList> filteredHybridResults = index.query(filteredHybridQuery);\nSystem.out.println(\"Filtered hybrid results (price > $100):\");\nfor (Map result : filteredHybridResults) {\n System.out.println(\" \" + result.get(\"brief_description\") + \" - $\" + result.get(\"price\"));\n}" + "source": [ + "// Hybrid search with a price filter\n", + "AggregateHybridQuery filteredHybridQuery = AggregateHybridQuery.builder()\n", + " .text(\"professional equipment\")\n", + " .textFieldName(\"brief_description\")\n", + " .vector(new float[]{0.9f, 0.1f, 0.05f})\n", + " .vectorFieldName(\"text_embedding\")\n", + " .filterExpression(Filter.numeric(\"price\").gt(100))\n", + " .returnFields(Arrays.asList(\"product_id\", \"brief_description\", \"category\", \"price\"))\n", + " .numResults(5)\n", + " .build();\n", + "\n", + "List> filteredHybridResults = index.query(filteredHybridQuery);\n", + "System.out.println(\"Filtered hybrid results (price > $100):\");\n", + "for (Map result : filteredHybridResults) {\n", + " System.out.println(\" \" + result.get(\"brief_description\") + \" - $\" + result.get(\"price\"));\n", + "}" + ] }, { "cell_type": "markdown", "id": "hybrid-query-scorers", "metadata": {}, - "source": "### Using Different Text Scorers\n\nAggregateHybridQuery supports the same text scoring algorithms as TextQuery:" + "source": [ + "### Using Different Text Scorers\n", + "\n", + "AggregateHybridQuery supports the same text scoring algorithms as TextQuery:" + ] }, { "cell_type": "code", @@ -479,13 +576,40 @@ "id": "hybrid-query-scorer-code", "metadata": {}, "outputs": [], - "source": "// Aggregate Hybrid query with TFIDF scorer\nAggregateHybridQuery hybridTfidf = AggregateHybridQuery.builder()\n .text(\"shoes support\")\n .textFieldName(\"brief_description\")\n .vector(new float[]{0.12f, 0.18f, 0.12f})\n .vectorFieldName(\"text_embedding\")\n .textScorer(\"TFIDF\")\n .returnFields(Arrays.asList(\"product_id\", \"brief_description\"))\n .numResults(3)\n .build();\n\nList> hybridTfidfResults = index.query(hybridTfidf);\nSystem.out.println(\"Hybrid query with TFIDF scorer:\");\nfor (Map result : hybridTfidfResults) {\n System.out.println(\" \" + result.get(\"brief_description\"));\n}" + "source": [ + "// Aggregate Hybrid query with TFIDF scorer\n", + "AggregateHybridQuery hybridTfidf = AggregateHybridQuery.builder()\n", + " .text(\"shoes support\")\n", + " .textFieldName(\"brief_description\")\n", + " .vector(new float[]{0.12f, 0.18f, 0.12f})\n", + " .vectorFieldName(\"text_embedding\")\n", + " .textScorer(\"TFIDF\")\n", + " .returnFields(Arrays.asList(\"product_id\", \"brief_description\"))\n", + " .numResults(3)\n", + " .build();\n", + "\n", + "List> hybridTfidfResults = index.query(hybridTfidf);\n", + "System.out.println(\"Hybrid query with TFIDF scorer:\");\n", + "for (Map result : hybridTfidfResults) {\n", + " System.out.println(\" \" + result.get(\"brief_description\"));\n", + "}" + ] }, { "cell_type": "markdown", "id": "multi-vector-intro", "metadata": {}, - "source": "## 3. MultiVectorQuery: Multi-Vector Search\n\nThe `MultiVectorQuery` allows you to search over multiple vector fields simultaneously. This is useful when you have different types of embeddings (e.g., text and image embeddings) and want to find results that match across multiple modalities.\n\nThe final score is calculated as a weighted combination:\n\n```\ncombined_score = w_1 * score_1 + w_2 * score_2 + w_3 * score_3 + ...\n```" + "source": [ + "## 3. MultiVectorQuery: Multi-Vector Search\n", + "\n", + "The `MultiVectorQuery` allows you to search over multiple vector fields simultaneously. This is useful when you have different types of embeddings (e.g., text and image embeddings) and want to find results that match across multiple modalities.\n", + "\n", + "The final score is calculated as a weighted combination:\n", + "\n", + "```\n", + "combined_score = w_1 * score_1 + w_2 * score_2 + w_3 * score_3 + ...\n", + "```" + ] }, { "cell_type": "markdown", @@ -688,7 +812,29 @@ "cell_type": "markdown", "id": "best-practices", "metadata": {}, - "source": "## Best Practices\n\n### When to Use Each Query Type:\n\n1. **`TextQuery`**:\n - When you need precise keyword matching\n - For traditional search engine functionality\n - When text relevance scoring is important\n - Example: Product search, document retrieval\n\n2. **`AggregateHybridQuery`**:\n - When you want to combine keyword and semantic search\n - For improved search quality over pure text or vector search\n - When you have both text and vector representations of your data\n - Example: E-commerce search, content recommendation\n\n3. **`MultiVectorQuery`**:\n - When you have multiple types of embeddings (text, image, audio, etc.)\n - For multi-modal search applications\n - When you want to balance multiple semantic signals\n - Example: Image-text search, cross-modal retrieval" + "source": [ + "## Best Practices\n", + "\n", + "### When to Use Each Query Type:\n", + "\n", + "1. **`TextQuery`**:\n", + " - When you need precise keyword matching\n", + " - For traditional search engine functionality\n", + " - When text relevance scoring is important\n", + " - Example: Product search, document retrieval\n", + "\n", + "2. **`AggregateHybridQuery`**:\n", + " - When you want to combine keyword and semantic search\n", + " - For improved search quality over pure text or vector search\n", + " - When you have both text and vector representations of your data\n", + " - Example: E-commerce search, content recommendation\n", + "\n", + "3. **`MultiVectorQuery`**:\n", + " - When you have multiple types of embeddings (text, image, audio, etc.)\n", + " - For multi-modal search applications\n", + " - When you want to balance multiple semantic signals\n", + " - Example: Image-text search, cross-modal retrieval" + ] }, { "cell_type": "markdown", @@ -728,4 +874,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +}