Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ RedisVL is your go-to client for:
Add RedisVL to your Java (17+) project using Maven or Gradle:

**Maven:**

```xml
<dependency>
<groupId>com.redis</groupId>
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
```
Expand Down
2 changes: 1 addition & 1 deletion docs/content/antora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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/
14 changes: 11 additions & 3 deletions notebooks/01_getting_started.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -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",
"_____"
]
Expand Down Expand Up @@ -285,7 +285,11 @@
"cell_type": "code",
"execution_count": 5,
"id": "mv1vdixzgjj",
"metadata": {},
"metadata": {
"vscode": {
"languageId": "java"
}
},
"outputs": [
{
"name": "stdout",
Expand Down Expand Up @@ -354,7 +358,11 @@
"cell_type": "code",
"execution_count": 7,
"id": "pcexez2r69j",
"metadata": {},
"metadata": {
"vscode": {
"languageId": "java"
}
},
"outputs": [
{
"name": "stdout",
Expand Down
2 changes: 1 addition & 1 deletion notebooks/05_hash_vs_json.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
172 changes: 159 additions & 13 deletions notebooks/11_advanced_queries.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -423,69 +437,179 @@
"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",
"execution_count": null,
"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<Map<String, Object>> hybridResults = index.query(hybridQuery);\n\nSystem.out.println(\"Hybrid search results:\");\nfor (Map<String, Object> 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<Map<String, Object>> hybridResults = index.query(hybridQuery);\n",
"\n",
"System.out.println(\"Hybrid search results:\");\n",
"for (Map<String, Object> 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",
"execution_count": null,
"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<Map<String, Object>> vectorHeavyResults = index.query(vectorHeavyQuery);\nfor (Map<String, Object> 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<Map<String, Object>> vectorHeavyResults = index.query(vectorHeavyQuery);\n",
"for (Map<String, Object> 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",
"execution_count": null,
"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<Map<String, Object>> filteredHybridResults = index.query(filteredHybridQuery);\nSystem.out.println(\"Filtered hybrid results (price > $100):\");\nfor (Map<String, Object> 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<Map<String, Object>> filteredHybridResults = index.query(filteredHybridQuery);\n",
"System.out.println(\"Filtered hybrid results (price > $100):\");\n",
"for (Map<String, Object> 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",
"execution_count": null,
"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<Map<String, Object>> hybridTfidfResults = index.query(hybridTfidf);\nSystem.out.println(\"Hybrid query with TFIDF scorer:\");\nfor (Map<String, Object> 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<Map<String, Object>> hybridTfidfResults = index.query(hybridTfidf);\n",
"System.out.println(\"Hybrid query with TFIDF scorer:\");\n",
"for (Map<String, Object> 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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -728,4 +874,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}