diff --git a/Makefile b/Makefile index c9bb7e6e..6bde29a6 100644 --- a/Makefile +++ b/Makefile @@ -8,14 +8,14 @@ install: ## Install the project and all dependencies @echo "๐Ÿš€ Installing project dependencies with uv" uv sync --all-extras -redis-start: ## Start Redis Stack in Docker - @echo "๐Ÿณ Starting Redis Stack" - docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest - -redis-stop: ## Stop Redis Stack Docker container - @echo "๐Ÿ›‘ Stopping Redis Stack" - docker stop redis-stack || true - docker rm redis-stack || true +redis-start: ## Start Redis in Docker + @echo "๐Ÿณ Starting Redis" + docker run -d --name redis -p 6379:6379 redis:latest + +redis-stop: ## Stop Redis Docker container + @echo "๐Ÿ›‘ Stopping Redis" + docker stop redis || true + docker rm redis || true format: ## Format code with isort and black @echo "๐ŸŽจ Formatting code" diff --git a/README.md b/README.md index 8924db90..53e54ebe 100644 --- a/README.md +++ b/README.md @@ -64,15 +64,15 @@ Choose from multiple Redis deployment options:
-Redis Stack - Docker image for development +Docker - Local development -Run Redis Stack locally using Docker: +Run Redis locally using Docker: ```bash -docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest +docker run -d --name redis -p 6379:6379 redis:latest ``` -This includes Redis with vector search capabilities and Redis Insight GUI. +This runs Redis 8+ with built-in vector search capabilities.
diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index ce989d9a..64b37cdc 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -1,3 +1,8 @@ .logo__image { transform: scale(.7); +} + +/* Show the primary sidebar on the landing page (override hide-on-wide) */ +.bd-sidebar-primary.hide-on-wide { + display: flex !important; } \ No newline at end of file diff --git a/docs/_static/css/sidebar.css b/docs/_static/css/sidebar.css index b47c4a14..e414254c 100644 --- a/docs/_static/css/sidebar.css +++ b/docs/_static/css/sidebar.css @@ -1,23 +1,52 @@ +/* Home page sidebar styling */ +.custom-home-sidebar .bd-links__title { + font-size: 0.95rem; + font-weight: 600; + letter-spacing: 0.02em; + margin-bottom: 0.75rem; + padding-bottom: 0.5rem; + border-bottom: 1px solid var(--pst-color-border); +} + +/* Sidebar navigation links */ +.custom-home-sidebar .toctree-l1 > a { + font-weight: 500; + padding: 0.4rem 0.5rem; + border-radius: 4px; + transition: background-color 0.15s ease; +} + +.custom-home-sidebar .toctree-l1 > a:hover { + background-color: var(--pst-color-surface); +} + +/* Nested items */ +.custom-home-sidebar .toctree-l2 > a { + font-size: 0.875rem; + color: var(--pst-color-text-muted); +} + +.custom-home-sidebar .toctree-l2 > a:hover { + color: var(--pst-color-text-base); +} + +/* Legacy custom_sidebar class */ .custom_sidebar { width: auto; background-color: inherit; - } - -/* Style the sidebar links */ .custom_sidebar ul { list-style-type: none; padding: 6px; } -/* Style the sidebar links */ .custom_sidebar li { list-style-type: none; padding: 5px; } .custom_sidebar a { - text-decoration: none; /* Removes underline */ + text-decoration: none; } diff --git a/docs/_static/redisvl-architecture.svg b/docs/_static/redisvl-architecture.svg new file mode 100644 index 00000000..7d907a7e --- /dev/null +++ b/docs/_static/redisvl-architecture.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + Application + Documents + + Metadata + + + + RedisVL + + + + Schema + + + + Vectorizer + + + + Query Builder + + + Extensions wrap these primitives + + + + Redis + + + + Search + Index + + + + Storage + (Hash/JSON) + + + FT.CREATE / FT.SEARCH + + + + + define + + + + text + + + + + + + creates + + + + search + + + + + + + results + + diff --git a/docs/_templates/sidebar-nav-custom.html b/docs/_templates/sidebar-nav-custom.html new file mode 100644 index 00000000..048a0266 --- /dev/null +++ b/docs/_templates/sidebar-nav-custom.html @@ -0,0 +1,6 @@ +{# Custom sidebar navigation for the landing page #} + + diff --git a/docs/api/index.md b/docs/api/index.md index eb849513..f7c1c661 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -20,7 +20,6 @@ query filter vectorizer reranker -utils cache message_history router diff --git a/docs/api/query.rst b/docs/api/query.rst index 70a29bf3..b8e1c875 100644 --- a/docs/api/query.rst +++ b/docs/api/query.rst @@ -106,7 +106,7 @@ VectorRangeQuery ) AggregateHybridQuery -================ +==================== .. currentmodule:: redisvl.query @@ -221,7 +221,7 @@ CountQuery MultiVectorQuery -========== +================ .. currentmodule:: redisvl.query diff --git a/docs/api/vector.rst b/docs/api/vector.rst index 9d28d9cc..c82ec18d 100644 --- a/docs/api/vector.rst +++ b/docs/api/vector.rst @@ -1,7 +1,7 @@ -***** +****** Vector -***** +****** The Vector class in RedisVL is a container that encapsulates a numerical vector, it's datatype, corresponding index field name, and optional importance weight. It is used when constructing multi-vector queries using the MultiVectorQuery class. diff --git a/docs/concepts/architecture.md b/docs/concepts/architecture.md new file mode 100644 index 00000000..0c1e1788 --- /dev/null +++ b/docs/concepts/architecture.md @@ -0,0 +1,71 @@ +--- +myst: + html_meta: + "description lang=en": | + RedisVL architecture - how the library structures vector search on Redis. +--- + +# Architecture + +RedisVL sits between your application and Redis, providing a structured way to define, populate, and query vector search indexes. + +```{image} /_static/redisvl-architecture.svg +:alt: RedisVL Architecture +:align: center +:width: 100% +``` + +## The Core Pattern + +Every RedisVL application follows a consistent workflow: **define โ†’ create โ†’ load โ†’ query**. + +First, you define a **schema** that describes your data. The schema specifies which fields exist, what types they are, and how they should be indexed. This includes declaring vector fields with their dimensionality and the algorithm Redis should use for similarity search. + +Next, you create an **index** in Redis based on that schema. The index is a persistent structure that Redis uses to make searches fast. Creating an index tells Redis how to organize and access your data. + +Then you **load** your data. Documents are stored as Redis Hash or JSON objects. As documents are written, Redis automatically indexes them according to your schemaโ€”no separate indexing step required. + +Finally, you **query** the index. RedisVL provides query builders that construct Redis search commands for you. You can search by vector similarity, filter by metadata, combine multiple criteria, or mix full-text search with semantic search. + +This pattern applies whether you're building a simple semantic search or a complex multi-modal retrieval system. + +## Schemas as Contracts + +The schema is the source of truth for your index. It defines the contract between your data and Redis. + +A schema includes the index name, a key prefix (so Redis knows which keys belong to this index), the storage type (Hash or JSON), and a list of field definitions. Each field has a name, a type, and type-specific configuration. + +For vector fields, you specify the dimensionality (which must match your embedding model's output), the distance metric (cosine, Euclidean, or inner product), and the indexing algorithm. These choices are locked in when the index is createdโ€”changing them requires building a new index. + +The schema can be defined programmatically in Python or loaded from a YAML file. YAML schemas are useful for version control, sharing between environments, and keeping configuration separate from code. + +## Query Composition + +RedisVL's query builders let you compose search operations without writing raw Redis commands. + +**Vector queries** find the K most similar items to a query vector. You provide an embedding, and Redis returns the nearest neighbors according to your configured distance metric. + +**Range queries** find all vectors within a distance threshold. Instead of asking for the top K, you're asking for everything "close enough" to a query point. + +**Filter queries** narrow results by metadata. You can filter on text fields, tags, numeric ranges, and geographic areas. Filters apply before the vector search, reducing the candidate set. + +**Hybrid queries** combine keyword search with semantic search. This is useful when you want to match on specific terms while also considering semantic relevance. + +These query types can be combined. A typical pattern is vector search with metadata filtersโ€”for example, finding similar products but only in a specific category or price range. + +## Extensions as Patterns + +Extensions are higher-level abstractions built on RedisVL's core primitives. Each extension encapsulates a common AI workflow pattern. + +**Semantic caching** stores LLM responses and retrieves them when similar prompts are seen again. This reduces API costs and latency without requiring exact-match caching. + +**Message history** stores conversation turns and retrieves context for LLM prompts. It can retrieve by recency (most recent messages) or by relevance (semantically similar messages). + +**Semantic routing** classifies queries into predefined categories based on similarity to reference phrases. This enables intent detection, topic routing, and guardrails. + +Each extension manages its own Redis index internally. You interact with a clean, purpose-specific API rather than managing schemas and queries yourself. + +--- + +**Learn more:** {doc}`/user_guide/01_getting_started` covers the core workflow. {doc}`extensions` explains each extension pattern in detail. + diff --git a/docs/concepts/extensions.md b/docs/concepts/extensions.md new file mode 100644 index 00000000..042f4fe7 --- /dev/null +++ b/docs/concepts/extensions.md @@ -0,0 +1,89 @@ +--- +myst: + html_meta: + "description lang=en": | + RedisVL extensions - semantic caching, embeddings caching, message history, and routing. +--- + +# Extensions + +Extensions are opinionated, higher-level abstractions built on RedisVL's core primitives. Each extension encapsulates a common AI application pattern, managing its own Redis index internally and exposing a clean, purpose-specific API. + +You don't need to understand schemas, indexes, or queries to use extensionsโ€”they handle that complexity for you. + +## Semantic Cache + +LLM API calls are expensive and slow. If users ask similar questions, you're paying to generate similar answers repeatedly. Semantic caching solves this by storing responses and returning cached answers when similar prompts are seen again. + +### How It Works + +When a prompt arrives, the cache embeds it and searches for similar cached prompts. If a match is found within the configured distance threshold, the cached response is returned immediatelyโ€”no LLM call needed. If no match is found, you call the LLM, store the prompt-response pair, and return the response. + +The key insight is "similar" rather than "identical." Traditional caching requires exact matches. Semantic caching matches by meaning, so "What's the capital of France?" and "Tell me France's capital city" can hit the same cache entry. + +### Threshold Tuning + +The distance threshold controls how similar prompts must be to match. A strict threshold (low value, like 0.05) requires near-identical prompts. A loose threshold (higher value, like 0.3) matches more liberally. + +Too strict, and you miss valid cache hits. Too loose, and you return wrong answers for different questions. Start strict, monitor cache quality in production, and loosen gradually based on observed behavior. + +### Multi-Tenant Isolation + +In applications serving multiple users or contexts, you often want separate cache spaces. Filters let you scope cache lookupsโ€”for example, caching per-user or per-conversation so one user's cached answers don't leak to another. + +## Embeddings Cache + +Embedding APIs have per-token costs, and computing the same embedding repeatedly wastes money. The embeddings cache stores computed embeddings and returns them on subsequent requests for the same content. + +### How It Works + +Unlike semantic cache (which uses similarity search), embeddings cache uses exact key matching. A deterministic hash is computed from the input text and model name. If that hash exists in the cache, the stored embedding is returned. If not, the embedding is computed, stored, and returned. + +This is useful when the same content is embedded multiple timesโ€”common in applications where users submit similar queries, or where documents are re-processed periodically. + +### Wrapping Vectorizers + +The embeddings cache can wrap any vectorizer, adding transparent caching. Calling the wrapped vectorizer checks the cache first. This requires no changes to your embedding codeโ€”just wrap the vectorizer and caching happens automatically. + +## Message History + +LLMs are stateless. To have a conversation, you must include previous messages in each prompt. Message history manages this context, storing conversation turns and retrieving them when building prompts. + +### Storage Model + +Each message includes a role (user, assistant, system, or tool), the message content, a timestamp, and a session identifier. The session tag groups messages into conversationsโ€”you might have one session per user, per chat thread, or per agent instance. + +### Retrieval Strategies + +The simplest retrieval is by recency: get the N most recent messages. This works for short conversations but breaks down when context exceeds the LLM's token limit or when relevant information appeared earlier in a long conversation. + +Semantic message history adds vector search. Messages are embedded, and you can retrieve by relevance rather than recency. This is powerful for long conversations where the user might reference something said much earlier, or for agents that need to recall specific instructions from their setup. + +### Session Isolation + +Session tags are critical for multi-user applications. Each user's conversation should be isolated, so retrieving context for User A doesn't include messages from User B. The session tag provides this isolation, and you can structure sessions however makes senseโ€”per-user, per-thread, per-agent, or any other grouping. + +## Semantic Router + +Semantic routing classifies queries into predefined categories based on meaning. It's a lightweight alternative to classification models, useful for intent detection, topic routing, and guardrails. + +### How It Works + +You define routes, each with a name and a set of reference phrases that represent that category. The router embeds all references and indexes them. At runtime, an incoming query is embedded and compared against all route references. The route whose references are closest to the query winsโ€”if it's within the configured distance threshold. + +For example, a customer support router might have routes for "billing," "technical support," and "account management," each with 5-10 reference phrases. When a user asks "I can't log into my account," the router matches it to the "account management" route based on semantic similarity to that route's references. + +### Threshold and Aggregation + +Each route has its own distance threshold, controlling how close queries must be to match. Routes can also specify how to aggregate distances when multiple references matchโ€”taking the average or minimum distance. + +If no route matches (all distances exceed their thresholds), the router returns no match. This lets you handle out-of-scope queries gracefully rather than forcing a classification. + +### Use Cases + +Semantic routing is useful for intent classification (determining what a user wants), topic detection (categorizing content), guardrails (detecting and blocking certain query types), and agent dispatch (sending queries to specialized sub-agents). + +--- + +**Learn more:** {doc}`/user_guide/03_llmcache` covers semantic caching. {doc}`/user_guide/07_message_history` explains conversation management. {doc}`/user_guide/08_semantic_router` walks through routing setup. + diff --git a/docs/concepts/index.md b/docs/concepts/index.md new file mode 100644 index 00000000..086d466c --- /dev/null +++ b/docs/concepts/index.md @@ -0,0 +1,53 @@ +--- +myst: + html_meta: + "description lang=en": | + Core concepts for RedisVL - architecture, search, indexing, and AI extensions. +--- + +# Concepts + +Foundational knowledge for building AI applications with RedisVL. These concepts are language-agnostic and apply across all RedisVL implementations. + +::::{grid} 2 +:gutter: 3 + +:::{grid-item-card} ๐Ÿ—๏ธ Architecture +:link: architecture +:link-type: doc + +How RedisVL components connect: schemas, indexes, queries, and extensions. +::: + +:::{grid-item-card} ๐Ÿ” Search & Indexing +:link: search-and-indexing +:link-type: doc + +Schemas, fields, documents, storage types, and query patterns. +::: + +:::{grid-item-card} ๐Ÿ”ง Utilities +:link: utilities +:link-type: doc + +Vectorizers for embeddings and rerankers for result optimization. +::: + +:::{grid-item-card} ๐Ÿงฉ Extensions +:link: extensions +:link-type: doc + +Pre-built patterns: caching, message history, and semantic routing. +::: + +:::: + +```{toctree} +:maxdepth: 2 +:hidden: + +architecture +search-and-indexing +utilities +extensions +``` diff --git a/docs/concepts/search-and-indexing.md b/docs/concepts/search-and-indexing.md new file mode 100644 index 00000000..1a095b0e --- /dev/null +++ b/docs/concepts/search-and-indexing.md @@ -0,0 +1,79 @@ +--- +myst: + html_meta: + "description lang=en": | + RedisVL search and indexing - schemas, field types, storage, and query patterns. +--- + +# Search & Indexing + +Vector search in Redis works differently from traditional databases. Understanding the underlying model helps you design better schemas and write more effective queries. + +## How Redis Indexes Work + +Redis search indexes are secondary structures that sit alongside your data. When you create an index, you're telling Redis: "Watch all keys that match this prefix, and build a searchable structure from these specific fields." + +The index doesn't store your dataโ€”it references it. Your documents live as Redis Hash or JSON objects, and the index maintains pointers and optimized structures for fast lookup. When you write a document, Redis automatically updates the index. When you delete a document, the index entry is removed. + +This design means searches are fast (the index is optimized for queries) while writes remain efficient (only the affected index entries are updated). It also means you can have multiple indexes over the same data with different field configurations. + +## Field Types and Their Purpose + +Each field type serves a different search use case. + +**Text fields** enable full-text search. Redis tokenizes the content, applies stemming (so "running" matches "run"), and builds an inverted index. Text search finds documents containing specific words or phrases, ranked by relevance. + +**Tag fields** are for exact-match filtering. Unlike text fields, tags are not tokenized or stemmed. A tag value is treated as an atomic unit. This is ideal for categories, statuses, IDs, and other discrete values where you want exact matches. + +**Numeric fields** support range queries and sorting. You can filter for values greater than, less than, or between bounds. Numeric fields are also used for sorting results. + +**Geo fields** enable location-based queries. You can find documents within a radius of a point or within a bounding box. + +**Vector fields** enable similarity search. Each document has an embedding vector, and queries find documents whose vectors are closest to a query vector. This is the foundation of semantic search. + +## Vector Indexing Algorithms + +Vector similarity search requires specialized data structures. Redis offers three algorithms, each with different trade-offs. + +**Flat indexing** performs exact nearest-neighbor search by comparing the query vector against every indexed vector. This guarantees finding the true closest matches, but search time grows linearly with dataset size. Use flat indexing for small datasets (under ~100K vectors) where exact results matter. + +**HNSW (Hierarchical Navigable Small World)** is an approximate algorithm that builds a multi-layer graph structure. Queries navigate this graph to find approximate nearest neighbors in logarithmic time. HNSW typically achieves 95-99% recall (meaning it finds 95-99% of the true nearest neighbors) while being orders of magnitude faster than flat search on large datasets. This is the default choice for most applications. + +**SVS (Scalable Vector Search)** is designed for very large datasets with memory constraints. It supports vector compression techniques that reduce memory footprint at the cost of some recall. SVS is useful when you have millions of vectors and memory is a limiting factor. + +The algorithm choice is made at index creation and cannot be changed without rebuilding the index. + +## Distance Metrics + +When comparing vectors, you need a way to measure how "close" two vectors are. Redis supports three distance metrics. + +**Cosine distance** measures the angle between vectors, ignoring their magnitude. Two vectors pointing in the same direction have distance 0; opposite directions have distance 2. Cosine is widely used because most embedding models produce vectors where direction encodes meaning and magnitude is less important. Similarity equals 1 minus distance. + +**Euclidean distance (L2)** measures the straight-line distance between vector endpoints. Unlike cosine, it considers magnitude. Euclidean distance ranges from 0 to infinity. + +**Inner product (IP)** is the dot product of two vectors. It combines both direction and magnitude. When vectors are normalized (magnitude 1), inner product equals cosine similarity. Inner product can be negative and ranges from negative infinity to positive infinity. + +Choose your metric based on how your embedding model was trained. Most text embedding models use cosine. + +## Storage: Hash vs JSON + +Redis offers two storage formats for documents. + +**Hash storage** is a flat key-value structure where each field is a top-level key. It's simple, fast, and works well when your documents don't have nested structures. Field names in your schema map directly to hash field names. + +**JSON storage** supports nested documents. You can store complex objects and use JSONPath expressions to index nested fields. This is useful when your data is naturally hierarchical or when you want to store the original document structure without flattening it. + +The choice affects how you structure data and how you reference fields in schemas. Hash is simpler; JSON is more flexible. + +## Schema Evolution + +Redis doesn't support modifying an existing index schema. Once an index is created, its field definitions are fixed. + +To change a schema, you create a new index with the updated configuration, reindex your data into it, update your application to use the new index, and then delete the old index. This patternโ€”create new, migrate, switch, drop oldโ€”is the standard approach for schema changes in production. + +Planning your schema carefully upfront reduces the need for migrations, but the capability exists when requirements evolve. + +--- + +**Learn more:** {doc}`/user_guide/01_getting_started` walks through building your first index. {doc}`/user_guide/05_hash_vs_json` compares storage options in depth. {doc}`/user_guide/02_complex_filtering` covers query composition. + diff --git a/docs/concepts/utilities.md b/docs/concepts/utilities.md new file mode 100644 index 00000000..51f6aeb5 --- /dev/null +++ b/docs/concepts/utilities.md @@ -0,0 +1,73 @@ +--- +myst: + html_meta: + "description lang=en": | + RedisVL utilities - vectorizers for embeddings and rerankers for result optimization. +--- + +# Utilities + +Utilities are optional components that enhance search workflows. They're not requiredโ€”you can bring your own embeddings and skip rerankingโ€”but they simplify common tasks. + +## Vectorizers + +A vectorizer converts text into an embedding vector. Embeddings are dense numerical representations that capture semantic meaning: similar texts produce similar vectors, enabling similarity search. + +### Why Vectorizers Matter + +Creating embeddings requires calling an embedding modelโ€”either a cloud API (OpenAI, Cohere, etc.) or a local model (HuggingFace sentence-transformers). Each provider has different APIs, authentication methods, and response formats. + +RedisVL vectorizers provide a unified interface across providers. You choose a provider, configure it once, and use the same methods regardless of which service is behind it. This makes it easy to switch providers, compare models, or use different providers in different environments. + +### The Dimensionality Contract + +Every embedding model produces vectors of a specific size (dimensionality). OpenAI's text-embedding-3-small produces 1536-dimensional vectors. Other models produce 384, 768, 1024, or other sizes. + +Your schema's vector field must specify the same dimensionality as your embedding model. If there's a mismatchโ€”your model produces 1536-dimensional vectors but your schema expects 768โ€”you'll get errors when loading data or running queries. + +This constraint means you should choose your embedding model before designing your schema, and changing models requires rebuilding your index. + +### Batching and Performance + +Embedding APIs have rate limits and per-request overhead. Embedding one text at a time is inefficient. Vectorizers support batch embedding, sending multiple texts in a single request. This dramatically improves throughput for indexing large datasets. + +Vectorizers handle batching internally, breaking large batches into provider-appropriate chunks and respecting rate limits. You provide a list of texts; the vectorizer manages the logistics. + +### Supported Providers + +RedisVL includes vectorizers for OpenAI, Azure OpenAI, Cohere, HuggingFace (local), Mistral, Google Vertex AI, AWS Bedrock, and VoyageAI. You can also create custom vectorizers that wrap any embedding function. + +## Rerankers + +A reranker takes initial search results and reorders them by relevance to the query. It's a second-stage filter that improves precision after the first-stage retrieval. + +### Why Reranking Works + +Vector search uses bi-encoder models: the query and documents are embedded independently, then compared by vector distance. This is fast but approximateโ€”the embedding captures general meaning, not the specific relationship between query and document. + +Rerankers use cross-encoder models that score query-document pairs directly. The model sees both the query and document together and predicts a relevance score. This is more accurate but slower, because each candidate requires a separate model inference. + +The combination is powerful: use fast vector search to retrieve a broad set of candidates (high recall), then use the slower but more accurate reranker to select the best results (high precision). + +### The Recall-Precision Trade-off + +With only vector search, you might retrieve 10 results and hope the best one is in there. With reranking, you can retrieve 50 candidatesโ€”casting a wider netโ€”then rerank to find the 5 best. The initial retrieval prioritizes recall (not missing relevant documents); reranking prioritizes precision (surfacing the most relevant ones). + +### Cost and Latency + +Reranking adds latency (typically 50-200ms depending on the provider and number of candidates) and cost (API-based rerankers charge per request). These trade-offs are usually worthwhile when result quality matters, but you should measure the impact for your use case. + +### Supported Providers + +RedisVL includes rerankers for HuggingFace cross-encoders (local), Cohere Rerank API, and VoyageAI Rerank API. + +## Two-Stage Retrieval + +The most effective retrieval pipelines combine both utilities: vectorize the query, retrieve a candidate set with vector search, then rerank to select the final results. + +This pattern separates recall (finding everything potentially relevant) from precision (selecting the best matches). Vector search handles recall efficiently; reranking handles precision accurately. Together, they deliver better results than either approach alone. + +--- + +**Learn more:** {doc}`/user_guide/04_vectorizers` covers embedding providers. {doc}`/user_guide/06_rerankers` explains reranking in practice. + diff --git a/docs/conf.py b/docs/conf.py index ab279cb1..90f72df2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,7 +47,6 @@ "sphinx_design", "sphinx_copybutton", "_extension.gallery_directive", - 'nbsphinx', "myst_nb", "sphinx_favicon" ] @@ -72,7 +71,7 @@ # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -html_css_files=["css/custom.css"] +html_css_files=["css/custom.css", "css/sidebar.css"] html_title = "RedisVL" html_context = { "default_mode": "dark" @@ -86,7 +85,10 @@ "doc_path": "docs", } html_sidebars = { - 'examples': [] + "index": ["sidebar-nav-custom"], + "examples/**": [], + "examples/index": [], + "**": ["sidebar-nav-bs"], } @@ -123,8 +125,7 @@ autoclass_content = 'both' add_module_names = False -nbsphinx_execute = 'never' -jupyter_execute_notebooks = "off" +nb_execution_mode = "off" # -- Options for autosummary/autodoc output ------------------------------------ autosummary_generate = True diff --git a/docs/index.md b/docs/index.md index a9bbd094..33ca5f6f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,65 +2,82 @@ myst: html_meta: "description lang=en": | - Top-level documentation for RedisVL, with links to the rest - of the site.. + RedisVL documentation - the AI-native Python client for Redis. html_theme.sidebar_secondary.remove: false --- -# Redis Vector Library (RedisVL) - -A powerful, AI-native Python client library for [Redis](https://redis.io). Leverage the speed, flexibility, and reliability of Redis for real-time data to supercharge your AI application. - -```{gallery-grid} -:grid-columns: 1 2 2 3 - -- header: "{fab}`bootstrap;pst-color-primary` Index Management" - content: "Design search schema and indices with ease from YAML, with Python, or from the CLI." -- header: "{fas}`bolt;pst-color-primary` Advanced Vector Search" - content: "Perform powerful vector search queries with complex filtering support." -- header: "{fas}`circle-half-stroke;pst-color-primary` Embedding Creation" - content: "Use OpenAI or any of the other supported vectorizers to create embeddings." - link: "user_guide/04_vectorizers" -- header: "{fas}`palette;pst-color-primary` CLI" - content: "Interact with RedisVL using a Command Line Interface (CLI) for ease of use." -- header: "{fab}`python;pst-color-primary` Semantic Caching" - content: "Extend RedisVL to cache LLM results, increasing QPS and decreasing system cost." - link: "user_guide/03_llmcache" -- header: "{fas}`lightbulb;pst-color-primary` Example Gallery" - content: "Explore the gallery of examples to get started." - link: "examples/index" -``` +# RedisVL + +**The AI-native Python client for Redis.** + +RedisVL is the production-ready Python client for AI applications built on Redis. Lightning-fast vector search meets enterprise-grade reliability. -## Installation +Build **RAG pipelines** with real-time retrieval, **AI agents** with memory and semantic routing, and **recommendation systems** with personalized search and reranking. -Install `redisvl` into your Python (>=3.8) environment using `pip`: +--- + +## Quick Start ```bash pip install redisvl ``` -Then make sure to have [Redis](https://redis.io) accessible with Search & Query features enabled on [Redis Cloud](https://redis.io/cloud) or locally in docker with [Redis Stack](https://redis.io/docs/getting-started/install-stack/docker/): - ```bash -docker run -d --name redis -p 6379:6379 -p 8001:8001 redis/redis-stack:latest +docker run -d --name redis -p 6379:6379 redis:latest ``` -This will also spin up the [Redis Insight GUI](https://redis.io/insight/) at `http://localhost:8001`. +Or connect to [Redis Cloud](https://redis.io/cloud) for a managed experience. +โ†’ *{doc}`/user_guide/01_getting_started`* -## Table of Contents +--- -```{toctree} -:maxdepth: 2 +## Explore the Docs -Overview -API -User Guides -Example Gallery -``` +::::{grid} 2 +:gutter: 4 + +:::{grid-item-card} ๐Ÿ“– Concepts +:link: concepts/index +:link-type: doc +:class-card: sd-shadow-sm + +Understand how RedisVL works. Architecture, search fundamentals, and extension patterns. +::: + +:::{grid-item-card} ๐Ÿš€ User Guides +:link: user_guide/index +:link-type: doc +:class-card: sd-shadow-sm + +Step-by-step tutorials. Installation, getting started, and deep dives on every feature. +::: + +:::{grid-item-card} ๐Ÿ“š API Reference +:link: api/index +:link-type: doc +:class-card: sd-shadow-sm + +Complete API documentation. Classes, methods, parameters, and examples. +::: + +:::{grid-item-card} ๐Ÿ’ก Examples +:link: examples/index +:link-type: doc +:class-card: sd-shadow-sm + +Real-world applications. RAG pipelines, chatbots, recommendation systems, and more. +::: + +:::: ```{toctree} +:maxdepth: 2 :hidden: +Concepts +User Guides +API +Examples Changelog ``` diff --git a/docs/overview/index.md b/docs/overview/index.md deleted file mode 100644 index 4bbbb2a8..00000000 --- a/docs/overview/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -myst: - html_meta: - "description lang=en": | - User Guides for RedisVL ---- - -# Overview - - -```{toctree} -:caption: Overview -:maxdepth: 2 - -installation -cli -``` - diff --git a/docs/overview/schema.yaml b/docs/overview/schema.yaml deleted file mode 100644 index 8664d02b..00000000 --- a/docs/overview/schema.yaml +++ /dev/null @@ -1,17 +0,0 @@ - -version: '0.1.0' - -index: - name: vectorizers - prefix: doc - storage_type: hash - -fields: - - name: sentence - type: text - - name: embedding - type: vector - attrs: - dims: 768 - algorithm: flat - distance_metric: cosine diff --git a/docs/user_guide/01_getting_started.ipynb b/docs/user_guide/01_getting_started.ipynb index 13bb7062..e9313a0f 100644 --- a/docs/user_guide/01_getting_started.ipynb +++ b/docs/user_guide/01_getting_started.ipynb @@ -5,24 +5,32 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Getting Started with RedisVL\n", - "`redisvl` is a versatile Python library with an integrated CLI, designed to enhance AI applications using Redis. This guide will walk you through the following steps:\n", + "# Getting Started\n", + "\n", + "RedisVL is a Python library with an integrated CLI for building AI applications with Redis. This guide covers the core workflow:\n", "\n", "1. Defining an `IndexSchema`\n", "2. Preparing a sample dataset\n", - "3. Creating a `SearchIndex` object\n", - "4. Testing `rvl` CLI functionality\n", - "5. Loading the sample data\n", - "6. Building `VectorQuery` objects and executing searches\n", - "7. Updating a `SearchIndex` object\n", + "3. Creating a `SearchIndex`\n", + "4. Using the `rvl` CLI\n", + "5. Loading data into Redis\n", + "6. Executing vector searches\n", + "7. Updating an index\n", + "\n", + "## Prerequisites\n", "\n", - "...and more!\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", "\n", - "Prerequisites:\n", - "- Ensure `redisvl` is installed in your Python environment.\n", - "- Have a running instance of [Redis Stack](https://redis.io/docs/install/install-stack/) or [Redis Cloud](https://redis.io/cloud).\n", + "## What You'll Learn\n", "\n", - "_____" + "By the end of this guide, you will be able to:\n", + "- Create index schemas using Python dictionaries or YAML files\n", + "- Build and manage `SearchIndex` objects\n", + "- Use the `rvl` CLI for index management\n", + "- Load data and execute vector similarity searches\n", + "- Update index schemas as your application evolves" ] }, { @@ -82,7 +90,14 @@ { "cell_type": "code", "execution_count": 1, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:18.309058Z", + "iopub.status.busy": "2026-02-16T15:11:18.308937Z", + "iopub.status.idle": "2026-02-16T15:11:18.313309Z", + "shell.execute_reply": "2026-02-16T15:11:18.312855Z" + } + }, "outputs": [], "source": [ "schema = {\n", @@ -127,7 +142,14 @@ { "cell_type": "code", "execution_count": 2, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:18.314635Z", + "iopub.status.busy": "2026-02-16T15:11:18.314532Z", + "iopub.status.idle": "2026-02-16T15:11:21.051754Z", + "shell.execute_reply": "2026-02-16T15:11:21.051269Z" + } + }, "outputs": [], "source": [ "import numpy as np\n", @@ -163,7 +185,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - ">As seen above, the sample `user_embedding` vectors are converted into bytes. Using the `NumPy`, this is fairly trivial." + ">The `user_embedding` vectors are converted to bytes using NumPy's `.tobytes()` method." ] }, { @@ -188,7 +210,14 @@ { "cell_type": "code", "execution_count": 3, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:21.053190Z", + "iopub.status.busy": "2026-02-16T15:11:21.053088Z", + "iopub.status.idle": "2026-02-16T15:11:21.268380Z", + "shell.execute_reply": "2026-02-16T15:11:21.268003Z" + } + }, "outputs": [], "source": [ "from redisvl.index import SearchIndex\n", @@ -210,7 +239,14 @@ { "cell_type": "code", "execution_count": 4, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:21.269739Z", + "iopub.status.busy": "2026-02-16T15:11:21.269664Z", + "iopub.status.idle": "2026-02-16T15:11:21.271420Z", + "shell.execute_reply": "2026-02-16T15:11:21.271063Z" + } + }, "outputs": [], "source": [ "index = SearchIndex.from_dict(schema, redis_url=\"redis://localhost:6379\", validate_on_load=True)\n", @@ -230,17 +266,16 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:00:22 redisvl.index.index INFO Index already exists, overwriting.\n" - ] + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:21.272346Z", + "iopub.status.busy": "2026-02-16T15:11:21.272277Z", + "iopub.status.idle": "2026-02-16T15:11:21.278910Z", + "shell.execute_reply": "2026-02-16T15:11:21.278522Z" } - ], + }, + "outputs": [], "source": [ "index.create(overwrite=True)" ] @@ -260,28 +295,17 @@ "Use the `rvl` CLI to inspect the created index and its fields:" ] }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:00:24 [RedisVL] INFO Indices:\n", - "13:00:24 [RedisVL] INFO 1. user_simple\n" - ] - } - ], - "source": [ - "!rvl index listall" - ] - }, { "cell_type": "code", "execution_count": 7, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:23.507552Z", + "iopub.status.busy": "2026-02-16T15:11:23.507428Z", + "iopub.status.idle": "2026-02-16T15:11:25.724904Z", + "shell.execute_reply": "2026-02-16T15:11:25.724172Z" + } + }, "outputs": [ { "name": "stdout", @@ -290,21 +314,21 @@ "\n", "\n", "Index Information:\n", - "\u256d\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\n", - "\u2502 Index Name \u2502 Storage Type \u2502 Prefixes \u2502 Index Options \u2502 Indexing \u2502\n", - "\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n", + "โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ\n", + "โ”‚ Index Name โ”‚ Storage Type โ”‚ Prefixes โ”‚ Index Options โ”‚ Indexing โ”‚\n", + "โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค\n", "| user_simple | HASH | ['user_simple_docs'] | [] | 0 |\n", - "\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\n", + "โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ\n", "Index Fields:\n", - "\u256d\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\n", - "\u2502 Name \u2502 Attribute \u2502 Type \u2502 Field Option \u2502 Option Value \u2502 Field Option \u2502 Option Value \u2502 Field Option \u2502 Option Value \u2502 Field Option \u2502 Option Value \u2502\n", - "\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n", - "\u2502 user \u2502 user \u2502 TAG \u2502 SEPARATOR \u2502 , \u2502 \u2502 \u2502 \u2502 \u2502 \u2502 \u2502\n", - "\u2502 credit_score \u2502 credit_score \u2502 TAG \u2502 SEPARATOR \u2502 , \u2502 \u2502 \u2502 \u2502 \u2502 \u2502 \u2502\n", - "\u2502 job \u2502 job \u2502 TEXT \u2502 WEIGHT \u2502 1 \u2502 \u2502 \u2502 \u2502 \u2502 \u2502 \u2502\n", - "\u2502 age \u2502 age \u2502 NUMERIC \u2502 \u2502 \u2502 \u2502 \u2502 \u2502 \u2502 \u2502 \u2502\n", - "\u2502 user_embedding \u2502 user_embedding \u2502 VECTOR \u2502 algorithm \u2502 FLAT \u2502 data_type \u2502 FLOAT32 \u2502 dim \u2502 3 \u2502 distance_metric \u2502 COSINE \u2502\n", - "\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\n" + "โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ\n", + "โ”‚ Name โ”‚ Attribute โ”‚ Type โ”‚ Field Option โ”‚ Option Value โ”‚ Field Option โ”‚ Option Value โ”‚ Field Option โ”‚ Option Value โ”‚ Field Option โ”‚ Option Value โ”‚\n", + "โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค\n", + "โ”‚ user โ”‚ user โ”‚ TAG โ”‚ SEPARATOR โ”‚ , โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚\n", + "โ”‚ credit_score โ”‚ credit_score โ”‚ TAG โ”‚ SEPARATOR โ”‚ , โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚\n", + "โ”‚ job โ”‚ job โ”‚ TEXT โ”‚ WEIGHT โ”‚ 1 โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚\n", + "โ”‚ age โ”‚ age โ”‚ NUMERIC โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚\n", + "โ”‚ user_embedding โ”‚ user_embedding โ”‚ VECTOR โ”‚ algorithm โ”‚ FLAT โ”‚ data_type โ”‚ FLOAT32 โ”‚ dim โ”‚ 3 โ”‚ distance_metric โ”‚ COSINE โ”‚\n", + "โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ\n" ] } ], @@ -326,14 +350,21 @@ }, { "cell_type": "code", - "execution_count": 8, - "metadata": {}, + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.726828Z", + "iopub.status.busy": "2026-02-16T15:11:25.726695Z", + "iopub.status.idle": "2026-02-16T15:11:25.737471Z", + "shell.execute_reply": "2026-02-16T15:11:25.736980Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['user_simple_docs:01JY4J4Y08GFY10VMB9D4YDMZQ', 'user_simple_docs:01JY4J4Y0AY2MKJ24QXQS2Q2YS', 'user_simple_docs:01JY4J4Y0A9GFF2XG1R81EFD4Z']\n" + "['user_simple_docs:01KHKHQYX95EDQN18FG8FRMRQ5', 'user_simple_docs:01KHKHQYXC97WY4ACG1V01GEPC', 'user_simple_docs:01KHKHQYXC97WY4ACG1V01GEPD']\n" ] } ], @@ -360,14 +391,20 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": {}, + "execution_count": 11, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.738908Z", + "iopub.status.busy": "2026-02-16T15:11:25.738819Z", + "iopub.status.idle": "2026-02-16T15:11:25.741694Z", + "shell.execute_reply": "2026-02-16T15:11:25.741164Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "13:00:27 redisvl.index.index ERROR Data validation failed during load operation\n", "Schema validation failed for object at index 0. Field 'user_embedding' expects bytes (vector data), but got boolean value 'True'. If this should be a vector field, provide a list of numbers or bytes. If this should be a different field type, check your schema definition.\n", "Object data: {\n", " \"user_embedding\": true\n", @@ -395,14 +432,21 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": {}, + "execution_count": 12, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.742965Z", + "iopub.status.busy": "2026-02-16T15:11:25.742869Z", + "iopub.status.idle": "2026-02-16T15:11:25.746046Z", + "shell.execute_reply": "2026-02-16T15:11:25.745620Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['user_simple_docs:01JY4J4Y0N4CNR9Y6R67MMVG7Q']\n" + "['user_simple_docs:01KHKHR37CD6143DNQ41G3ADNA']\n" ] } ], @@ -432,8 +476,15 @@ }, { "cell_type": "code", - "execution_count": 11, - "metadata": {}, + "execution_count": 13, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.747124Z", + "iopub.status.busy": "2026-02-16T15:11:25.747046Z", + "iopub.status.idle": "2026-02-16T15:11:25.749646Z", + "shell.execute_reply": "2026-02-16T15:11:25.749218Z" + } + }, "outputs": [], "source": [ "from redisvl.query import VectorQuery\n", @@ -477,13 +528,20 @@ }, { "cell_type": "code", - "execution_count": 12, - "metadata": {}, + "execution_count": 14, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.750770Z", + "iopub.status.busy": "2026-02-16T15:11:25.750698Z", + "iopub.status.idle": "2026-02-16T15:11:25.755601Z", + "shell.execute_reply": "2026-02-16T15:11:25.755140Z" + } + }, "outputs": [ { "data": { "text/html": [ - "
vector_distanceuseragejobcredit_score
0john1engineerhigh
0mary2doctorlow
0john1engineerhigh
" + "
vector_distanceuseragejobcredit_score
0john1engineerhigh
0mary2doctorlow
0.0566298961639tyler9engineerhigh
" ], "text/plain": [ "" @@ -510,38 +568,15 @@ }, { "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'index': {'name': 'user_simple', 'prefix': 'user_simple_docs'},\n", - " 'fields': [{'name': 'user', 'type': 'tag'},\n", - " {'name': 'credit_score', 'type': 'tag'},\n", - " {'name': 'job', 'type': 'text'},\n", - " {'name': 'age', 'type': 'numeric'},\n", - " {'name': 'user_embedding',\n", - " 'type': 'vector',\n", - " 'attrs': {'dims': 3,\n", - " 'distance_metric': 'cosine',\n", - " 'algorithm': 'flat',\n", - " 'datatype': 'float32'}}]}" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" + "execution_count": 15, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.760059Z", + "iopub.status.busy": "2026-02-16T15:11:25.759988Z", + "iopub.status.idle": "2026-02-16T15:11:25.762258Z", + "shell.execute_reply": "2026-02-16T15:11:25.761845Z" } - ], - "source": [ - "schema" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, + }, "outputs": [], "source": [ "from redisvl.index import AsyncSearchIndex\n", @@ -553,13 +588,20 @@ }, { "cell_type": "code", - "execution_count": 15, - "metadata": {}, + "execution_count": 16, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.763219Z", + "iopub.status.busy": "2026-02-16T15:11:25.763154Z", + "iopub.status.idle": "2026-02-16T15:11:25.769456Z", + "shell.execute_reply": "2026-02-16T15:11:25.769135Z" + } + }, "outputs": [ { "data": { "text/html": [ - "
vector_distanceuseragejobcredit_score
0john1engineerhigh
0mary2doctorlow
0john1engineerhigh
" + "
vector_distanceuseragejobcredit_score
0john1engineerhigh
0mary2doctorlow
0.0566298961639tyler9engineerhigh
" ], "text/plain": [ "" @@ -594,12 +636,18 @@ }, { "cell_type": "code", - "execution_count": 16, - "metadata": {}, + "execution_count": 17, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.770560Z", + "iopub.status.busy": "2026-02-16T15:11:25.770494Z", + "iopub.status.idle": "2026-02-16T15:11:25.772490Z", + "shell.execute_reply": "2026-02-16T15:11:25.772158Z" + } + }, "outputs": [], "source": [ "# Modify this schema to have what we want\n", - "\n", "index.schema.remove_field(\"job\")\n", "index.schema.remove_field(\"user_embedding\")\n", "index.schema.add_fields([\n", @@ -619,17 +667,16 @@ }, { "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:00:27 redisvl.index.index INFO Index already exists, overwriting.\n" - ] + "execution_count": 18, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.773413Z", + "iopub.status.busy": "2026-02-16T15:11:25.773344Z", + "iopub.status.idle": "2026-02-16T15:11:25.780980Z", + "shell.execute_reply": "2026-02-16T15:11:25.780644Z" } - ], + }, + "outputs": [], "source": [ "# Run the index update but keep underlying data in place\n", "await index.create(overwrite=True, drop=False)" @@ -637,13 +684,20 @@ }, { "cell_type": "code", - "execution_count": 18, - "metadata": {}, + "execution_count": 19, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.781999Z", + "iopub.status.busy": "2026-02-16T15:11:25.781926Z", + "iopub.status.idle": "2026-02-16T15:11:25.786797Z", + "shell.execute_reply": "2026-02-16T15:11:25.786516Z" + } + }, "outputs": [ { "data": { "text/html": [ - "
vector_distanceuseragejobcredit_score
0mary2doctorlow
0john1engineerhigh
0john1engineerhigh
" + "
vector_distanceuseragejobcredit_score
0john1engineerhigh
0mary2doctorlow
0.0566298961639tyler9engineerhigh
" ], "text/plain": [ "" @@ -669,8 +723,15 @@ }, { "cell_type": "code", - "execution_count": 19, - "metadata": {}, + "execution_count": 20, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:25.787932Z", + "iopub.status.busy": "2026-02-16T15:11:25.787861Z", + "iopub.status.idle": "2026-02-16T15:11:27.979635Z", + "shell.execute_reply": "2026-02-16T15:11:27.979025Z" + } + }, "outputs": [ { "name": "stdout", @@ -678,29 +739,29 @@ "text": [ "\n", "Statistics:\n", - "\u256d\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\n", - "\u2502 Stat Key \u2502 Value \u2502\n", - "\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n", - "\u2502 num_docs \u2502 10 \u2502\n", - "\u2502 num_terms \u2502 0 \u2502\n", - "\u2502 max_doc_id \u2502 10 \u2502\n", - "\u2502 num_records \u2502 50 \u2502\n", - "\u2502 percent_indexed \u2502 1 \u2502\n", - "\u2502 hash_indexing_failures \u2502 0 \u2502\n", - "\u2502 number_of_uses \u2502 2 \u2502\n", - "\u2502 bytes_per_record_avg \u2502 19.5200004 \u2502\n", - "\u2502 doc_table_size_mb \u2502 0.00105857 \u2502\n", - "\u2502 inverted_sz_mb \u2502 9.30786132 \u2502\n", - "\u2502 key_table_size_mb \u2502 4.70161437 \u2502\n", - "\u2502 offset_bits_per_record_avg \u2502 nan \u2502\n", - "\u2502 offset_vectors_sz_mb \u2502 0 \u2502\n", - "\u2502 offsets_per_term_avg \u2502 0 \u2502\n", - "\u2502 records_per_doc_avg \u2502 5 \u2502\n", - "\u2502 sortable_values_size_mb \u2502 0 \u2502\n", - "\u2502 total_indexing_time \u2502 0.16899999 \u2502\n", - "\u2502 total_inverted_index_blocks \u2502 11 \u2502\n", - "\u2502 vector_index_sz_mb \u2502 0.23619842 \u2502\n", - "\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\n" + "โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ\n", + "โ”‚ Stat Key โ”‚ Value โ”‚\n", + "โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค\n", + "โ”‚ num_docs โ”‚ 4 โ”‚\n", + "โ”‚ num_terms โ”‚ 0 โ”‚\n", + "โ”‚ max_doc_id โ”‚ 4 โ”‚\n", + "โ”‚ num_records โ”‚ 20 โ”‚\n", + "โ”‚ percent_indexed โ”‚ 1 โ”‚\n", + "โ”‚ hash_indexing_failures โ”‚ 0 โ”‚\n", + "โ”‚ number_of_uses โ”‚ 2 โ”‚\n", + "โ”‚ bytes_per_record_avg โ”‚ 45.4500007 โ”‚\n", + "โ”‚ doc_table_size_mb โ”‚ 0.00809097 โ”‚\n", + "โ”‚ inverted_sz_mb โ”‚ 8.66889953 โ”‚\n", + "โ”‚ key_table_size_mb โ”‚ 3.05175781 โ”‚\n", + "โ”‚ offset_bits_per_record_avg โ”‚ nan โ”‚\n", + "โ”‚ offset_vectors_sz_mb โ”‚ 0 โ”‚\n", + "โ”‚ offsets_per_term_avg โ”‚ 0 โ”‚\n", + "โ”‚ records_per_doc_avg โ”‚ 5 โ”‚\n", + "โ”‚ sortable_values_size_mb โ”‚ 0 โ”‚\n", + "โ”‚ total_indexing_time โ”‚ 1.729042 โ”‚\n", + "โ”‚ total_inverted_index_blocks โ”‚ 11 โ”‚\n", + "โ”‚ vector_index_sz_mb โ”‚ 0.23595428 โ”‚\n", + "โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ\n" ] } ], @@ -712,32 +773,45 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Cleanup" + "## Next Steps\n", + "\n", + "Now that you understand the basics of RedisVL, explore these related guides:\n", + "\n", + "- [Query and Filter Data](02_complex_filtering.ipynb) - Learn advanced filtering with tag, numeric, text, and geo filters\n", + "- [Create Embeddings with Vectorizers](04_vectorizers.ipynb) - Generate embeddings using OpenAI, HuggingFace, Cohere, and more\n", + "- [Choose a Storage Type](05_hash_vs_json.ipynb) - Understand when to use Hash vs JSON storage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Below we will clean up after our work. First, you can flush all data from Redis associated with the index by\n", - "using the `.clear()` method. This will leave the secondary index in place for future insertions or updates.\n", + "## Cleanup\n", "\n", - "But if you want to clean up everything, including the index, just use `.delete()`\n", - "which will by default remove the index AND the underlying data." + "Use `.clear()` to flush all data from Redis associated with the index while leaving the index in place for future insertions.\n", + "\n", + "Use `.delete()` to remove both the index and the underlying data." ] }, { "cell_type": "code", - "execution_count": 20, - "metadata": {}, + "execution_count": 21, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:27.981294Z", + "iopub.status.busy": "2026-02-16T15:11:27.981178Z", + "iopub.status.idle": "2026-02-16T15:11:27.988083Z", + "shell.execute_reply": "2026-02-16T15:11:27.987683Z" + } + }, "outputs": [ { "data": { "text/plain": [ - "10" + "4" ] }, - "execution_count": 20, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -749,8 +823,15 @@ }, { "cell_type": "code", - "execution_count": 21, - "metadata": {}, + "execution_count": 22, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:27.989136Z", + "iopub.status.busy": "2026-02-16T15:11:27.989056Z", + "iopub.status.idle": "2026-02-16T15:11:27.991663Z", + "shell.execute_reply": "2026-02-16T15:11:27.991275Z" + } + }, "outputs": [ { "data": { @@ -758,20 +839,27 @@ "True" ] }, - "execution_count": 21, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "# Butm the index is still in place\n", + "# But the index is still in place\n", "await index.exists()" ] }, { "cell_type": "code", - "execution_count": 22, - "metadata": {}, + "execution_count": 23, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:27.992624Z", + "iopub.status.busy": "2026-02-16T15:11:27.992513Z", + "iopub.status.idle": "2026-02-16T15:11:27.995118Z", + "shell.execute_reply": "2026-02-16T15:11:27.994738Z" + } + }, "outputs": [], "source": [ "# Remove / delete the index in its entirety\n", @@ -781,7 +869,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": ".venv", "language": "python", "name": "python3" }, @@ -795,9 +883,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.6" + "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} diff --git a/docs/user_guide/02_complex_filtering.ipynb b/docs/user_guide/02_complex_filtering.ipynb index 97b5211f..f2f2bdb5 100644 --- a/docs/user_guide/02_complex_filtering.ipynb +++ b/docs/user_guide/02_complex_filtering.ipynb @@ -5,19 +5,37 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Querying with RedisVL\n", + "# Query and Filter Data\n", "\n", - "In this notebook, we will explore more complex queries that can be performed with ``redisvl``\n", + "This guide covers the filtering capabilities in RedisVL, including tag, numeric, text, geo, and timestamp filters. You'll learn how to combine filters to create complex queries that narrow down search results precisely.\n", "\n", - "Before running this notebook, be sure to\n", - "1. Have installed ``redisvl`` and have that environment active for this notebook.\n", - "2. Have a running Redis instance with RediSearch > 2.4 running." + "## Prerequisites\n", + "\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", + "\n", + "## What You'll Learn\n", + "\n", + "By the end of this guide, you will be able to:\n", + "- Create and apply tag, numeric, text, and geo filters\n", + "- Combine multiple filters using AND/OR logic\n", + "- Use FilterQuery for non-vector searches\n", + "- Execute CountQuery to get matching record counts\n", + "- Apply RangeQuery for distance-based vector searches" ] }, { "cell_type": "code", - "execution_count": 94, - "metadata": {}, + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:37.904694Z", + "iopub.status.busy": "2026-02-16T15:11:37.904555Z", + "iopub.status.idle": "2026-02-16T15:11:37.952798Z", + "shell.execute_reply": "2026-02-16T15:11:37.952324Z" + } + }, "outputs": [ { "data": { @@ -43,8 +61,15 @@ }, { "cell_type": "code", - "execution_count": 95, - "metadata": {}, + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:37.971584Z", + "iopub.status.busy": "2026-02-16T15:11:37.971453Z", + "iopub.status.idle": "2026-02-16T15:11:37.973872Z", + "shell.execute_reply": "2026-02-16T15:11:37.973369Z" + } + }, "outputs": [], "source": [ "schema = {\n", @@ -77,8 +102,15 @@ }, { "cell_type": "code", - "execution_count": 96, - "metadata": {}, + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:37.975042Z", + "iopub.status.busy": "2026-02-16T15:11:37.974944Z", + "iopub.status.idle": "2026-02-16T15:11:38.069624Z", + "shell.execute_reply": "2026-02-16T15:11:38.069144Z" + } + }, "outputs": [], "source": [ "from redisvl.index import SearchIndex\n", @@ -92,18 +124,15 @@ }, { "cell_type": "code", - "execution_count": 52, - "metadata": {}, - "outputs": [], - "source": [ - "# use the CLI to see the created index\n", - "!rvl index listall" - ] - }, - { - "cell_type": "code", - "execution_count": 97, - "metadata": {}, + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.283390Z", + "iopub.status.busy": "2026-02-16T15:11:40.283264Z", + "iopub.status.idle": "2026-02-16T15:11:40.288233Z", + "shell.execute_reply": "2026-02-16T15:11:40.287726Z" + } + }, "outputs": [], "source": [ "# load data to redis\n", @@ -112,8 +141,15 @@ }, { "cell_type": "code", - "execution_count": 98, - "metadata": {}, + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.289590Z", + "iopub.status.busy": "2026-02-16T15:11:40.289492Z", + "iopub.status.idle": "2026-02-16T15:11:40.293971Z", + "shell.execute_reply": "2026-02-16T15:11:40.293534Z" + } + }, "outputs": [ { "data": { @@ -121,7 +157,7 @@ "7" ] }, - "execution_count": 98, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -135,8 +171,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Complex Filtering", - "", + "## Complex Filtering\n", + "\n", "Complex filtering allows you to combine multiple types of filters in your queries. For example, you may want to search for a user that is a certain age, has a certain job, and is within a certain distance of a location. This is a complex filtering query that combines numeric, tag, and geographic filters." ] }, @@ -151,8 +187,15 @@ }, { "cell_type": "code", - "execution_count": 99, - "metadata": {}, + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.295159Z", + "iopub.status.busy": "2026-02-16T15:11:40.295077Z", + "iopub.status.idle": "2026-02-16T15:11:40.334394Z", + "shell.execute_reply": "2026-02-16T15:11:40.333857Z" + } + }, "outputs": [ { "data": { @@ -172,7 +215,7 @@ "'@credit_score:{high}=>[KNN 10 @user_embedding $vector AS vector_distance] RETURN 7 user credit_score age job office_location last_updated vector_distance SORTBY vector_distance ASC DIALECT 2 LIMIT 0 10'" ] }, - "execution_count": 99, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -197,8 +240,15 @@ }, { "cell_type": "code", - "execution_count": 100, - "metadata": {}, + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.335629Z", + "iopub.status.busy": "2026-02-16T15:11:40.335471Z", + "iopub.status.idle": "2026-02-16T15:11:40.337607Z", + "shell.execute_reply": "2026-02-16T15:11:40.337298Z" + } + }, "outputs": [ { "data": { @@ -206,7 +256,7 @@ "'@credit_score:{high}=>[KNN 10 @user_embedding $vector AS vector_distance]'" ] }, - "execution_count": 100, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -217,8 +267,15 @@ }, { "cell_type": "code", - "execution_count": 56, - "metadata": {}, + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.338709Z", + "iopub.status.busy": "2026-02-16T15:11:40.338624Z", + "iopub.status.idle": "2026-02-16T15:11:40.341827Z", + "shell.execute_reply": "2026-02-16T15:11:40.341481Z" + } + }, "outputs": [ { "data": { @@ -264,8 +321,15 @@ }, { "cell_type": "code", - "execution_count": 57, - "metadata": {}, + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.342871Z", + "iopub.status.busy": "2026-02-16T15:11:40.342787Z", + "iopub.status.idle": "2026-02-16T15:11:40.345818Z", + "shell.execute_reply": "2026-02-16T15:11:40.345498Z" + } + }, "outputs": [ { "data": { @@ -290,8 +354,15 @@ }, { "cell_type": "code", - "execution_count": 58, - "metadata": {}, + "execution_count": 11, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.346822Z", + "iopub.status.busy": "2026-02-16T15:11:40.346755Z", + "iopub.status.idle": "2026-02-16T15:11:40.349708Z", + "shell.execute_reply": "2026-02-16T15:11:40.349347Z" + } + }, "outputs": [ { "data": { @@ -327,8 +398,15 @@ }, { "cell_type": "code", - "execution_count": 59, - "metadata": {}, + "execution_count": 12, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.350706Z", + "iopub.status.busy": "2026-02-16T15:11:40.350640Z", + "iopub.status.idle": "2026-02-16T15:11:40.353646Z", + "shell.execute_reply": "2026-02-16T15:11:40.353226Z" + } + }, "outputs": [ { "data": { @@ -362,8 +440,15 @@ }, { "cell_type": "code", - "execution_count": 60, - "metadata": {}, + "execution_count": 13, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.354675Z", + "iopub.status.busy": "2026-02-16T15:11:40.354588Z", + "iopub.status.idle": "2026-02-16T15:11:40.359531Z", + "shell.execute_reply": "2026-02-16T15:11:40.359104Z" + } + }, "outputs": [ { "data": { @@ -389,8 +474,15 @@ }, { "cell_type": "code", - "execution_count": 61, - "metadata": {}, + "execution_count": 14, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.360528Z", + "iopub.status.busy": "2026-02-16T15:11:40.360395Z", + "iopub.status.idle": "2026-02-16T15:11:40.363530Z", + "shell.execute_reply": "2026-02-16T15:11:40.363158Z" + } + }, "outputs": [ { "data": { @@ -415,8 +507,15 @@ }, { "cell_type": "code", - "execution_count": 62, - "metadata": {}, + "execution_count": 15, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.364473Z", + "iopub.status.busy": "2026-02-16T15:11:40.364406Z", + "iopub.status.idle": "2026-02-16T15:11:40.367358Z", + "shell.execute_reply": "2026-02-16T15:11:40.367031Z" + } + }, "outputs": [ { "data": { @@ -450,14 +549,21 @@ }, { "cell_type": "code", - "execution_count": 63, - "metadata": {}, + "execution_count": 16, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.368389Z", + "iopub.status.busy": "2026-02-16T15:11:40.368278Z", + "iopub.status.idle": "2026-02-16T15:11:40.371608Z", + "shell.execute_reply": "2026-02-16T15:11:40.371204Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Epoch comparison: 1742147139.132589\n" + "Epoch comparison: 1742129139.132589\n" ] }, { @@ -488,14 +594,21 @@ }, { "cell_type": "code", - "execution_count": 64, - "metadata": {}, + "execution_count": 17, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.372500Z", + "iopub.status.busy": "2026-02-16T15:11:40.372436Z", + "iopub.status.idle": "2026-02-16T15:11:40.375920Z", + "shell.execute_reply": "2026-02-16T15:11:40.375544Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Epoch comparison: 1742147139.132589\n" + "Epoch comparison: 1742129139.132589\n" ] }, { @@ -527,14 +640,21 @@ }, { "cell_type": "code", - "execution_count": 65, - "metadata": {}, + "execution_count": 18, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.376961Z", + "iopub.status.busy": "2026-02-16T15:11:40.376900Z", + "iopub.status.idle": "2026-02-16T15:11:40.380523Z", + "shell.execute_reply": "2026-02-16T15:11:40.380163Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Epoch between: 1736880339.132589 - 1742147139.132589\n" + "Epoch between: 1736858739.132589 - 1742129139.132589\n" ] }, { @@ -576,8 +696,15 @@ }, { "cell_type": "code", - "execution_count": 66, - "metadata": {}, + "execution_count": 19, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.381563Z", + "iopub.status.busy": "2026-02-16T15:11:40.381476Z", + "iopub.status.idle": "2026-02-16T15:11:40.385275Z", + "shell.execute_reply": "2026-02-16T15:11:40.384915Z" + } + }, "outputs": [ { "data": { @@ -604,8 +731,15 @@ }, { "cell_type": "code", - "execution_count": 67, - "metadata": {}, + "execution_count": 20, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.386257Z", + "iopub.status.busy": "2026-02-16T15:11:40.386194Z", + "iopub.status.idle": "2026-02-16T15:11:40.389112Z", + "shell.execute_reply": "2026-02-16T15:11:40.388816Z" + } + }, "outputs": [ { "data": { @@ -630,8 +764,15 @@ }, { "cell_type": "code", - "execution_count": 68, - "metadata": {}, + "execution_count": 21, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.390100Z", + "iopub.status.busy": "2026-02-16T15:11:40.390034Z", + "iopub.status.idle": "2026-02-16T15:11:40.392749Z", + "shell.execute_reply": "2026-02-16T15:11:40.392377Z" + } + }, "outputs": [ { "data": { @@ -656,8 +797,15 @@ }, { "cell_type": "code", - "execution_count": 69, - "metadata": {}, + "execution_count": 22, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.393671Z", + "iopub.status.busy": "2026-02-16T15:11:40.393596Z", + "iopub.status.idle": "2026-02-16T15:11:40.396490Z", + "shell.execute_reply": "2026-02-16T15:11:40.396172Z" + } + }, "outputs": [ { "data": { @@ -682,8 +830,15 @@ }, { "cell_type": "code", - "execution_count": 70, - "metadata": {}, + "execution_count": 23, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.397432Z", + "iopub.status.busy": "2026-02-16T15:11:40.397366Z", + "iopub.status.idle": "2026-02-16T15:11:40.400312Z", + "shell.execute_reply": "2026-02-16T15:11:40.399945Z" + } + }, "outputs": [ { "data": { @@ -708,8 +863,15 @@ }, { "cell_type": "code", - "execution_count": 71, - "metadata": {}, + "execution_count": 24, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.401156Z", + "iopub.status.busy": "2026-02-16T15:11:40.401095Z", + "iopub.status.idle": "2026-02-16T15:11:40.403785Z", + "shell.execute_reply": "2026-02-16T15:11:40.403374Z" + } + }, "outputs": [ { "data": { @@ -741,13 +903,20 @@ }, { "cell_type": "code", - "execution_count": 72, - "metadata": {}, + "execution_count": 25, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.404652Z", + "iopub.status.busy": "2026-02-16T15:11:40.404594Z", + "iopub.status.idle": "2026-02-16T15:11:40.407701Z", + "shell.execute_reply": "2026-02-16T15:11:40.407351Z" + } + }, "outputs": [ { "data": { "text/plain": [ - "[{'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90PY',\n", + "[{'id': 'user_queries_docs:01KHKHSW68SH7A1AT1RDG5FC1A',\n", " 'score': 1.8181817787737895,\n", " 'vector_distance': '0',\n", " 'user': 'john',\n", @@ -756,7 +925,7 @@ " 'job': 'engineer',\n", " 'office_location': '-122.4194,37.7749',\n", " 'last_updated': '1741627789'},\n", - " {'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90PZ',\n", + " {'id': 'user_queries_docs:01KHKHSW68SH7A1AT1RDG5FC1B',\n", " 'score': 0.0,\n", " 'vector_distance': '0',\n", " 'user': 'derrick',\n", @@ -765,7 +934,7 @@ " 'job': 'doctor',\n", " 'office_location': '-122.4194,37.7749',\n", " 'last_updated': '1741627789'},\n", - " {'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90Q1',\n", + " {'id': 'user_queries_docs:01KHKHSW68SH7A1AT1RDG5FC1D',\n", " 'score': 1.8181817787737895,\n", " 'vector_distance': '0.109129190445',\n", " 'user': 'tyler',\n", @@ -774,7 +943,7 @@ " 'job': 'engineer',\n", " 'office_location': '-122.0839,37.3861',\n", " 'last_updated': '1742232589'},\n", - " {'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90Q2',\n", + " {'id': 'user_queries_docs:01KHKHSW69W3GWRFZADZM7XMYV',\n", " 'score': 0.0,\n", " 'vector_distance': '0.158808887005',\n", " 'user': 'tim',\n", @@ -783,7 +952,7 @@ " 'job': 'dermatologist',\n", " 'office_location': '-122.0839,37.3861',\n", " 'last_updated': '1739644189'},\n", - " {'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90Q3',\n", + " {'id': 'user_queries_docs:01KHKHSW69W3GWRFZADZM7XMYW',\n", " 'score': 0.0,\n", " 'vector_distance': '0.217881977558',\n", " 'user': 'taimur',\n", @@ -792,7 +961,7 @@ " 'job': 'CEO',\n", " 'office_location': '-122.0839,37.3861',\n", " 'last_updated': '1742232589'},\n", - " {'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90Q0',\n", + " {'id': 'user_queries_docs:01KHKHSW68SH7A1AT1RDG5FC1C',\n", " 'score': 0.0,\n", " 'vector_distance': '0.266666650772',\n", " 'user': 'nancy',\n", @@ -801,7 +970,7 @@ " 'job': 'doctor',\n", " 'office_location': '-122.4194,37.7749',\n", " 'last_updated': '1710696589'},\n", - " {'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90Q4',\n", + " {'id': 'user_queries_docs:01KHKHSW69W3GWRFZADZM7XMYX',\n", " 'score': 0.0,\n", " 'vector_distance': '0.653301358223',\n", " 'user': 'joe',\n", @@ -812,7 +981,7 @@ " 'last_updated': '1742232589'}]" ] }, - "execution_count": 72, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -835,8 +1004,15 @@ }, { "cell_type": "code", - "execution_count": 73, - "metadata": {}, + "execution_count": 26, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.408598Z", + "iopub.status.busy": "2026-02-16T15:11:40.408534Z", + "iopub.status.idle": "2026-02-16T15:11:40.411728Z", + "shell.execute_reply": "2026-02-16T15:11:40.411368Z" + } + }, "outputs": [ { "data": { @@ -863,8 +1039,15 @@ }, { "cell_type": "code", - "execution_count": 74, - "metadata": {}, + "execution_count": 27, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.412603Z", + "iopub.status.busy": "2026-02-16T15:11:40.412541Z", + "iopub.status.idle": "2026-02-16T15:11:40.415801Z", + "shell.execute_reply": "2026-02-16T15:11:40.415458Z" + } + }, "outputs": [ { "data": { @@ -889,8 +1072,15 @@ }, { "cell_type": "code", - "execution_count": 75, - "metadata": {}, + "execution_count": 28, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.416670Z", + "iopub.status.busy": "2026-02-16T15:11:40.416603Z", + "iopub.status.idle": "2026-02-16T15:11:40.419678Z", + "shell.execute_reply": "2026-02-16T15:11:40.419315Z" + } + }, "outputs": [ { "data": { @@ -919,15 +1109,22 @@ "source": [ "## Combining Filters\n", "\n", - "In this example, we will combine a numeric filter with a tag filter. We will search for users that are between the ages of 20 and 30 and have a job of \"engineer\".\n", + "This example combines a numeric filter with a tag filter to search for users between ages 20 and 30 who have the job \"engineer\".\n", "\n", "### Intersection (\"and\")" ] }, { "cell_type": "code", - "execution_count": 76, - "metadata": {}, + "execution_count": 29, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.420707Z", + "iopub.status.busy": "2026-02-16T15:11:40.420647Z", + "iopub.status.idle": "2026-02-16T15:11:40.423943Z", + "shell.execute_reply": "2026-02-16T15:11:40.423580Z" + } + }, "outputs": [ { "data": { @@ -970,8 +1167,15 @@ }, { "cell_type": "code", - "execution_count": 77, - "metadata": {}, + "execution_count": 30, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.424838Z", + "iopub.status.busy": "2026-02-16T15:11:40.424771Z", + "iopub.status.idle": "2026-02-16T15:11:40.427561Z", + "shell.execute_reply": "2026-02-16T15:11:40.427221Z" + } + }, "outputs": [ { "data": { @@ -1014,8 +1218,15 @@ }, { "cell_type": "code", - "execution_count": 78, - "metadata": {}, + "execution_count": 31, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.428436Z", + "iopub.status.busy": "2026-02-16T15:11:40.428373Z", + "iopub.status.idle": "2026-02-16T15:11:40.430043Z", + "shell.execute_reply": "2026-02-16T15:11:40.429693Z" + } + }, "outputs": [], "source": [ "def make_filter(age=None, credit=None, job=None):\n", @@ -1029,8 +1240,15 @@ }, { "cell_type": "code", - "execution_count": 79, - "metadata": {}, + "execution_count": 32, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.430893Z", + "iopub.status.busy": "2026-02-16T15:11:40.430817Z", + "iopub.status.idle": "2026-02-16T15:11:40.433398Z", + "shell.execute_reply": "2026-02-16T15:11:40.433085Z" + } + }, "outputs": [ { "data": { @@ -1054,8 +1272,15 @@ }, { "cell_type": "code", - "execution_count": 80, - "metadata": {}, + "execution_count": 33, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.434250Z", + "iopub.status.busy": "2026-02-16T15:11:40.434186Z", + "iopub.status.idle": "2026-02-16T15:11:40.436846Z", + "shell.execute_reply": "2026-02-16T15:11:40.436522Z" + } + }, "outputs": [ { "data": { @@ -1079,8 +1304,15 @@ }, { "cell_type": "code", - "execution_count": 81, - "metadata": {}, + "execution_count": 34, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.437642Z", + "iopub.status.busy": "2026-02-16T15:11:40.437577Z", + "iopub.status.idle": "2026-02-16T15:11:40.440321Z", + "shell.execute_reply": "2026-02-16T15:11:40.440019Z" + } + }, "outputs": [ { "data": { @@ -1104,8 +1336,15 @@ }, { "cell_type": "code", - "execution_count": 82, - "metadata": {}, + "execution_count": 35, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.441228Z", + "iopub.status.busy": "2026-02-16T15:11:40.441164Z", + "iopub.status.idle": "2026-02-16T15:11:40.443767Z", + "shell.execute_reply": "2026-02-16T15:11:40.443413Z" + } + }, "outputs": [ { "data": { @@ -1133,13 +1372,20 @@ "source": [ "## Non-vector Queries\n", "\n", - "In some cases, you may not want to run a vector query, but just use a ``FilterExpression`` similar to a SQL query. The ``FilterQuery`` class enable this functionality. It is similar to the ``VectorQuery`` class but solely takes a ``FilterExpression``." + "When you need to query without vector similarity (similar to a SQL WHERE clause), use the ``FilterQuery`` class. It accepts a ``FilterExpression`` and returns matching records." ] }, { "cell_type": "code", - "execution_count": 83, - "metadata": {}, + "execution_count": 36, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.444662Z", + "iopub.status.busy": "2026-02-16T15:11:40.444595Z", + "iopub.status.idle": "2026-02-16T15:11:40.447941Z", + "shell.execute_reply": "2026-02-16T15:11:40.447590Z" + } + }, "outputs": [ { "data": { @@ -1175,13 +1421,20 @@ "source": [ "## Count Queries\n", "\n", - "In some cases, you may need to use a ``FilterExpression`` to execute a ``CountQuery`` that simply returns the count of the number of entities in the pertaining set. It is similar to the ``FilterQuery`` class but does not return the values of the underlying data." + "Use ``CountQuery`` with a ``FilterExpression`` to get the count of matching records without retrieving the actual data." ] }, { "cell_type": "code", - "execution_count": 84, - "metadata": {}, + "execution_count": 37, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.448850Z", + "iopub.status.busy": "2026-02-16T15:11:40.448780Z", + "iopub.status.idle": "2026-02-16T15:11:40.451282Z", + "shell.execute_reply": "2026-02-16T15:11:40.450908Z" + } + }, "outputs": [ { "name": "stdout", @@ -1214,8 +1467,15 @@ }, { "cell_type": "code", - "execution_count": 85, - "metadata": {}, + "execution_count": 38, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.452320Z", + "iopub.status.busy": "2026-02-16T15:11:40.452213Z", + "iopub.status.idle": "2026-02-16T15:11:40.455244Z", + "shell.execute_reply": "2026-02-16T15:11:40.454929Z" + } + }, "outputs": [ { "data": { @@ -1250,13 +1510,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We can also change the distance threshold of the query object between uses if we like. Here we will set ``distance_threshold==0.1``. This means that the query object will return all matches that are within 0.1 of the query object. This is a small distance, so we expect to get fewer matches than before." + "The distance threshold can be changed between queries. Setting ``distance_threshold=0.1`` returns only matches within 0.1 distance of the query vector, resulting in fewer but more similar matches." ] }, { "cell_type": "code", - "execution_count": 86, - "metadata": {}, + "execution_count": 39, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.456194Z", + "iopub.status.busy": "2026-02-16T15:11:40.456129Z", + "iopub.status.idle": "2026-02-16T15:11:40.458616Z", + "shell.execute_reply": "2026-02-16T15:11:40.458233Z" + } + }, "outputs": [ { "data": { @@ -1286,8 +1553,15 @@ }, { "cell_type": "code", - "execution_count": 87, - "metadata": {}, + "execution_count": 40, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.459558Z", + "iopub.status.busy": "2026-02-16T15:11:40.459497Z", + "iopub.status.idle": "2026-02-16T15:11:40.462092Z", + "shell.execute_reply": "2026-02-16T15:11:40.461788Z" + } + }, "outputs": [ { "data": { @@ -1326,8 +1600,15 @@ }, { "cell_type": "code", - "execution_count": 88, - "metadata": {}, + "execution_count": 41, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.463156Z", + "iopub.status.busy": "2026-02-16T15:11:40.463096Z", + "iopub.status.idle": "2026-02-16T15:11:40.466114Z", + "shell.execute_reply": "2026-02-16T15:11:40.465788Z" + } + }, "outputs": [ { "data": { @@ -1367,8 +1648,15 @@ }, { "cell_type": "code", - "execution_count": 89, - "metadata": {}, + "execution_count": 42, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.467072Z", + "iopub.status.busy": "2026-02-16T15:11:40.467004Z", + "iopub.status.idle": "2026-02-16T15:11:40.469019Z", + "shell.execute_reply": "2026-02-16T15:11:40.468611Z" + } + }, "outputs": [ { "data": { @@ -1376,7 +1664,7 @@ "'@job:(\"engineer\")=>[KNN 5 @user_embedding $vector AS vector_distance] RETURN 6 user credit_score age job office_location vector_distance SORTBY age DESC DIALECT 3 LIMIT 0 5'" ] }, - "execution_count": 89, + "execution_count": 42, "metadata": {}, "output_type": "execute_result" } @@ -1388,8 +1676,15 @@ }, { "cell_type": "code", - "execution_count": 90, - "metadata": {}, + "execution_count": 43, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.469963Z", + "iopub.status.busy": "2026-02-16T15:11:40.469893Z", + "iopub.status.idle": "2026-02-16T15:11:40.471830Z", + "shell.execute_reply": "2026-02-16T15:11:40.471473Z" + } + }, "outputs": [ { "data": { @@ -1397,7 +1692,7 @@ "'@credit_score:{high}'" ] }, - "execution_count": 90, + "execution_count": 43, "metadata": {}, "output_type": "execute_result" } @@ -1410,8 +1705,15 @@ }, { "cell_type": "code", - "execution_count": 91, - "metadata": {}, + "execution_count": 44, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.472660Z", + "iopub.status.busy": "2026-02-16T15:11:40.472602Z", + "iopub.status.idle": "2026-02-16T15:11:40.474526Z", + "shell.execute_reply": "2026-02-16T15:11:40.474212Z" + } + }, "outputs": [ { "data": { @@ -1419,7 +1721,7 @@ "'((@credit_score:{high} @age:[18 +inf]) @age:[-inf 100])'" ] }, - "execution_count": 91, + "execution_count": 44, "metadata": {}, "output_type": "execute_result" } @@ -1444,17 +1746,24 @@ }, { "cell_type": "code", - "execution_count": 92, - "metadata": {}, + "execution_count": 45, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.475411Z", + "iopub.status.busy": "2026-02-16T15:11:40.475340Z", + "iopub.status.idle": "2026-02-16T15:11:40.478198Z", + "shell.execute_reply": "2026-02-16T15:11:40.477832Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90PY', 'payload': None, 'user': 'john', 'age': '18', 'job': 'engineer', 'credit_score': 'high', 'office_location': '-122.4194,37.7749', 'user_embedding': '==\\x00\\x00\\x00?', 'last_updated': '1741627789'}\n", - "{'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90Q0', 'payload': None, 'user': 'nancy', 'age': '94', 'job': 'doctor', 'credit_score': 'high', 'office_location': '-122.4194,37.7749', 'user_embedding': '333?=\\x00\\x00\\x00?', 'last_updated': '1710696589'}\n", - "{'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90Q1', 'payload': None, 'user': 'tyler', 'age': '100', 'job': 'engineer', 'credit_score': 'high', 'office_location': '-122.0839,37.3861', 'user_embedding': '=>\\x00\\x00\\x00?', 'last_updated': '1742232589'}\n", - "{'id': 'user_queries_docs:01KG0AV1K9NY8H2BBKRSRZ90Q2', 'payload': None, 'user': 'tim', 'age': '12', 'job': 'dermatologist', 'credit_score': 'high', 'office_location': '-122.0839,37.3861', 'user_embedding': '>>\\x00\\x00\\x00?', 'last_updated': '1739644189'}\n" + "{'id': 'user_queries_docs:01KHKHSW68SH7A1AT1RDG5FC1A', 'payload': None, 'user': 'john', 'age': '18', 'job': 'engineer', 'credit_score': 'high', 'office_location': '-122.4194,37.7749', 'user_embedding': '==\\x00\\x00\\x00?', 'last_updated': '1741627789'}\n", + "{'id': 'user_queries_docs:01KHKHSW68SH7A1AT1RDG5FC1C', 'payload': None, 'user': 'nancy', 'age': '94', 'job': 'doctor', 'credit_score': 'high', 'office_location': '-122.4194,37.7749', 'user_embedding': '333?=\\x00\\x00\\x00?', 'last_updated': '1710696589'}\n", + "{'id': 'user_queries_docs:01KHKHSW68SH7A1AT1RDG5FC1D', 'payload': None, 'user': 'tyler', 'age': '100', 'job': 'engineer', 'credit_score': 'high', 'office_location': '-122.0839,37.3861', 'user_embedding': '=>\\x00\\x00\\x00?', 'last_updated': '1742232589'}\n", + "{'id': 'user_queries_docs:01KHKHSW69W3GWRFZADZM7XMYV', 'payload': None, 'user': 'tim', 'age': '12', 'job': 'dermatologist', 'credit_score': 'high', 'office_location': '-122.0839,37.3861', 'user_embedding': '>>\\x00\\x00\\x00?', 'last_updated': '1739644189'}\n" ] } ], @@ -1465,19 +1774,45 @@ ] }, { - "cell_type": "code", - "execution_count": 93, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand filtering in RedisVL, explore these related guides:\n", + "\n", + "- [Use Advanced Query Types](11_advanced_queries.ipynb) - Learn about TextQuery, HybridQuery, and MultiVectorQuery\n", + "- [Cache LLM Responses](03_llmcache.ipynb) - Use filters with semantic caching for multi-user scenarios\n", + "- [Write SQL Queries for Redis](12_sql_to_redis_queries.ipynb) - Use SQL-like syntax for Redis queries" + ] + }, + { + "cell_type": "markdown", "metadata": {}, + "source": [ + "## Cleanup" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:40.479153Z", + "iopub.status.busy": "2026-02-16T15:11:40.479091Z", + "iopub.status.idle": "2026-02-16T15:11:40.481434Z", + "shell.execute_reply": "2026-02-16T15:11:40.481026Z" + } + }, "outputs": [], "source": [ - "# Cleanup\n", "index.delete()" ] } ], "metadata": { "kernelspec": { - "display_name": "redisvl", + "display_name": ".venv", "language": "python", "name": "python3" }, @@ -1491,10 +1826,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" - }, - "orig_nbformat": 4 + "version": "3.13.2" + } }, "nbformat": 4, "nbformat_minor": 2 -} \ No newline at end of file +} diff --git a/docs/user_guide/03_llmcache.ipynb b/docs/user_guide/03_llmcache.ipynb index 3a46becf..a8f63039 100644 --- a/docs/user_guide/03_llmcache.ipynb +++ b/docs/user_guide/03_llmcache.ipynb @@ -2,20 +2,47 @@ "cells": [ { "cell_type": "markdown", - "source": "# LLM Caching\n\nThis notebook demonstrates how to use RedisVL's `SemanticCache` to cache LLM responses based on semantic similarity. Semantic caching can significantly reduce API costs and latency by retrieving cached responses for semantically similar prompts instead of making redundant API calls.\n\nKey features covered:\n- Basic cache operations (store, check, clear)\n- Customizing semantic similarity thresholds\n- TTL policies for cache expiration\n- Performance benchmarking\n- Access controls with tags and filters for multi-user scenarios\n\nPrerequisites:\n- Ensure `redisvl` is installed in your Python environment\n- Have a running instance of [Redis Stack](https://redis.io/docs/install/install-stack/) or [Redis Cloud](https://redis.io/cloud)\n- OpenAI API key for the examples", - "metadata": {} + "metadata": {}, + "source": [ + "# Cache LLM Responses\n", + "\n", + "This guide demonstrates how to use RedisVL's `SemanticCache` to cache LLM responses based on semantic similarity. Semantic caching reduces API costs and latency by retrieving cached responses for semantically similar prompts instead of making redundant API calls.\n", + "\n", + "## Prerequisites\n", + "\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", + "- An OpenAI API key for the examples\n", + "\n", + "## What You'll Learn\n", + "\n", + "By the end of this guide, you will be able to:\n", + "- Set up and configure a `SemanticCache`\n", + "- Store and retrieve cached LLM responses\n", + "- Customize semantic similarity thresholds\n", + "- Configure TTL policies for cache expiration\n", + "- Implement access controls with tags and filters for multi-user scenarios" + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "First, we will import [OpenAI](https://platform.openai.com) to use their API for responding to user prompts. We will also create a simple `ask_openai` helper method to assist." + "First, import [OpenAI](https://platform.openai.com) to use their API for responding to user prompts. The following code creates a simple `ask_openai` helper method to assist." ] }, { "cell_type": "code", "execution_count": 1, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:03.699360Z", + "iopub.status.busy": "2026-02-16T15:30:03.699221Z", + "iopub.status.idle": "2026-02-16T15:30:04.311512Z", + "shell.execute_reply": "2026-02-16T15:30:04.310977Z" + } + }, "outputs": [], "source": [ "import os\n", @@ -34,8 +61,8 @@ "\n", "def ask_openai(question: str) -> str:\n", " response = client.completions.create(\n", - " model=\"gpt-3.5-turbo-instruct\",\n", - " prompt=question,\n", + " model=\"gpt-4o-mini\",\n", + " prompt=f\"Answer the following question simply: {question}\",\n", " max_tokens=200\n", " )\n", " return response.choices[0].text.strip()" @@ -44,7 +71,14 @@ { "cell_type": "code", "execution_count": 2, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:04.312736Z", + "iopub.status.busy": "2026-02-16T15:30:04.312623Z", + "iopub.status.idle": "2026-02-16T15:30:11.559321Z", + "shell.execute_reply": "2026-02-16T15:30:11.558753Z" + } + }, "outputs": [ { "name": "stdout", @@ -70,29 +104,16 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:02:02 sentence_transformers.SentenceTransformer INFO Use pytorch device_name: mps\n", - "13:02:02 sentence_transformers.SentenceTransformer INFO Load pretrained SentenceTransformer: redis/langcache-embed-v1\n", - "13:02:02 sentence_transformers.SentenceTransformer WARNING You try to use a model that was created with version 4.1.0, however, your version is 3.4.1. This might cause unexpected behavior or errors. In that case, try to update to the latest version.\n", - "\n", - "\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 3.79it/s]\n" - ] + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:11.583737Z", + "iopub.status.busy": "2026-02-16T15:30:11.583617Z", + "iopub.status.idle": "2026-02-16T15:30:31.793657Z", + "shell.execute_reply": "2026-02-16T15:30:31.793174Z" } - ], + }, + "outputs": [], "source": [ "import warnings\n", "warnings.filterwarnings('ignore')\n", @@ -111,7 +132,14 @@ { "cell_type": "code", "execution_count": 4, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:31.795376Z", + "iopub.status.busy": "2026-02-16T15:30:31.795045Z", + "iopub.status.idle": "2026-02-16T15:30:34.018783Z", + "shell.execute_reply": "2026-02-16T15:30:34.018106Z" + } + }, "outputs": [ { "name": "stdout", @@ -153,7 +181,14 @@ { "cell_type": "code", "execution_count": 5, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.020632Z", + "iopub.status.busy": "2026-02-16T15:30:34.020490Z", + "iopub.status.idle": "2026-02-16T15:30:34.022884Z", + "shell.execute_reply": "2026-02-16T15:30:34.022313Z" + } + }, "outputs": [], "source": [ "question = \"What is the capital of France?\"" @@ -162,28 +197,21 @@ { "cell_type": "code", "execution_count": 6, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.024186Z", + "iopub.status.busy": "2026-02-16T15:30:34.024066Z", + "iopub.status.idle": "2026-02-16T15:30:34.142671Z", + "shell.execute_reply": "2026-02-16T15:30:34.142236Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 7.79it/s]" - ] - }, { "name": "stdout", "output_type": "stream", "text": [ "Empty cache\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] } ], "source": [ @@ -205,15 +233,15 @@ { "cell_type": "code", "execution_count": 7, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.144011Z", + "iopub.status.busy": "2026-02-16T15:30:34.143925Z", + "iopub.status.idle": "2026-02-16T15:30:34.186967Z", + "shell.execute_reply": "2026-02-16T15:30:34.186507Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 19.62it/s]\n" - ] - }, { "data": { "text/plain": [ @@ -238,34 +266,27 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now we will check the cache again with the same question and with a semantically similar question:" + "Now check the cache again with the same question and with a semantically similar question:" ] }, { "cell_type": "code", "execution_count": 8, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.188029Z", + "iopub.status.busy": "2026-02-16T15:30:34.187942Z", + "iopub.status.idle": "2026-02-16T15:30:34.229841Z", + "shell.execute_reply": "2026-02-16T15:30:34.229399Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 18.65it/s]" - ] - }, { "name": "stdout", "output_type": "stream", "text": [ "[{'prompt': 'What is the capital of France?', 'response': 'Paris', 'metadata': {'city': 'Paris', 'country': 'france'}, 'key': 'llmcache:115049a298532be2f181edb03f766770c0db84c22aff39003fec340deaec7545'}]\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] } ], "source": [ @@ -279,15 +300,15 @@ { "cell_type": "code", "execution_count": 9, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.230921Z", + "iopub.status.busy": "2026-02-16T15:30:34.230847Z", + "iopub.status.idle": "2026-02-16T15:30:34.338748Z", + "shell.execute_reply": "2026-02-16T15:30:34.338236Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 7.81it/s]\n" - ] - }, { "data": { "text/plain": [ @@ -322,7 +343,14 @@ { "cell_type": "code", "execution_count": 10, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.339923Z", + "iopub.status.busy": "2026-02-16T15:30:34.339843Z", + "iopub.status.idle": "2026-02-16T15:30:34.341651Z", + "shell.execute_reply": "2026-02-16T15:30:34.341233Z" + } + }, "outputs": [], "source": [ "# Widen the semantic distance threshold (allow less similar matches)\n", @@ -332,15 +360,15 @@ { "cell_type": "code", "execution_count": 11, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.342644Z", + "iopub.status.busy": "2026-02-16T15:30:34.342568Z", + "iopub.status.idle": "2026-02-16T15:30:34.450098Z", + "shell.execute_reply": "2026-02-16T15:30:34.449695Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 8.37it/s]\n" - ] - }, { "data": { "text/plain": [ @@ -362,15 +390,15 @@ { "cell_type": "code", "execution_count": 12, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.451349Z", + "iopub.status.busy": "2026-02-16T15:30:34.451264Z", + "iopub.status.idle": "2026-02-16T15:30:34.497746Z", + "shell.execute_reply": "2026-02-16T15:30:34.497352Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 21.23it/s]\n" - ] - }, { "data": { "text/plain": [ @@ -399,13 +427,20 @@ "Redis uses TTL policies (optional) to expire individual keys at points in time in the future.\n", "This allows you to focus on your data flow and business logic without bothering with complex cleanup tasks.\n", "\n", - "A TTL policy set on the `SemanticCache` allows you to temporarily hold onto cache entries. Below, we will set the TTL policy to 5 seconds." + "A TTL policy set on the `SemanticCache` allows you to temporarily hold onto cache entries. Below, the TTL policy is set to 5 seconds." ] }, { "cell_type": "code", "execution_count": 13, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.498916Z", + "iopub.status.busy": "2026-02-16T15:30:34.498837Z", + "iopub.status.idle": "2026-02-16T15:30:34.500656Z", + "shell.execute_reply": "2026-02-16T15:30:34.500207Z" + } + }, "outputs": [], "source": [ "llmcache.set_ttl(5) # 5 seconds" @@ -414,16 +449,15 @@ { "cell_type": "code", "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 8.53it/s]\n" - ] + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:34.501619Z", + "iopub.status.busy": "2026-02-16T15:30:34.501550Z", + "iopub.status.idle": "2026-02-16T15:30:40.622930Z", + "shell.execute_reply": "2026-02-16T15:30:40.621935Z" } - ], + }, + "outputs": [], "source": [ "llmcache.store(\"This is a TTL test\", \"This is a TTL test response\")\n", "\n", @@ -433,28 +467,21 @@ { "cell_type": "code", "execution_count": 15, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:40.624998Z", + "iopub.status.busy": "2026-02-16T15:30:40.624839Z", + "iopub.status.idle": "2026-02-16T15:30:40.686437Z", + "shell.execute_reply": "2026-02-16T15:30:40.685943Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 12.54it/s]" - ] - }, { "name": "stdout", "output_type": "stream", "text": [ "[]\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] } ], "source": [ @@ -467,7 +494,14 @@ { "cell_type": "code", "execution_count": 16, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:40.687665Z", + "iopub.status.busy": "2026-02-16T15:30:40.687576Z", + "iopub.status.idle": "2026-02-16T15:30:40.689464Z", + "shell.execute_reply": "2026-02-16T15:30:40.688989Z" + } + }, "outputs": [], "source": [ "# Reset the TTL to null (long lived data)\n", @@ -480,13 +514,20 @@ "source": [ "## Simple Performance Testing\n", "\n", - "Next, we will measure the speedup obtained by using ``SemanticCache``. We will use the ``time`` module to measure the time taken to generate responses with and without ``SemanticCache``." + "Next, measure the speedup obtained by using ``SemanticCache``. The ``time`` module measures the time taken to generate responses with and without ``SemanticCache``." ] }, { "cell_type": "code", "execution_count": 17, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:40.690563Z", + "iopub.status.busy": "2026-02-16T15:30:40.690480Z", + "iopub.status.idle": "2026-02-16T15:30:40.692398Z", + "shell.execute_reply": "2026-02-16T15:30:40.692093Z" + } + }, "outputs": [], "source": [ "def answer_question(question: str) -> str:\n", @@ -510,28 +551,20 @@ { "cell_type": "code", "execution_count": 18, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:40.693572Z", + "iopub.status.busy": "2026-02-16T15:30:40.693493Z", + "iopub.status.idle": "2026-02-16T15:30:45.605328Z", + "shell.execute_reply": "2026-02-16T15:30:45.604820Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 8.09it/s]\n" - ] - }, { "name": "stdout", "output_type": "stream", "text": [ - "13:02:17 httpx INFO HTTP Request: POST https://api.openai.com/v1/completions \"HTTP/1.1 200 OK\"\n", - "Without caching, a call to openAI to answer this simple question took 1.7948627471923828 seconds.\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 12.93it/s]\n" + "Without caching, a call to openAI to answer this simple question took 3.055630922317505 seconds.\n" ] }, { @@ -561,30 +594,21 @@ { "cell_type": "code", "execution_count": 19, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:45.606711Z", + "iopub.status.busy": "2026-02-16T15:30:45.606608Z", + "iopub.status.idle": "2026-02-16T15:30:46.019546Z", + "shell.execute_reply": "2026-02-16T15:30:46.019062Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 20.90it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 23.24it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 22.85it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 21.98it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 22.65it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 22.65it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 21.84it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 20.67it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 22.08it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 21.14it/s]\n" - ] - }, { "name": "stdout", "output_type": "stream", "text": [ - "Avg time taken with LLM cache enabled: 0.049193501472473145\n", - "Percentage of time saved: 97.26%\n" + "Avg time taken with LLM cache enabled: 0.05140402317047119\n", + "Percentage of time saved: 98.32%\n" ] } ], @@ -606,7 +630,14 @@ { "cell_type": "code", "execution_count": 20, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:46.020637Z", + "iopub.status.busy": "2026-02-16T15:30:46.020555Z", + "iopub.status.idle": "2026-02-16T15:30:48.724038Z", + "shell.execute_reply": "2026-02-16T15:30:48.723375Z" + } + }, "outputs": [ { "name": "stdout", @@ -619,23 +650,23 @@ "โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค\n", "โ”‚ num_docs โ”‚ 1 โ”‚\n", "โ”‚ num_terms โ”‚ 19 โ”‚\n", - "โ”‚ max_doc_id โ”‚ 3 โ”‚\n", - "โ”‚ num_records โ”‚ 29 โ”‚\n", + "โ”‚ max_doc_id โ”‚ 4 โ”‚\n", + "โ”‚ num_records โ”‚ 36 โ”‚\n", "โ”‚ percent_indexed โ”‚ 1 โ”‚\n", "โ”‚ hash_indexing_failures โ”‚ 0 โ”‚\n", "โ”‚ number_of_uses โ”‚ 19 โ”‚\n", - "โ”‚ bytes_per_record_avg โ”‚ 75.9655151 โ”‚\n", - "โ”‚ doc_table_size_mb โ”‚ 1.34468078 โ”‚\n", - "โ”‚ inverted_sz_mb โ”‚ 0.00210094 โ”‚\n", - "โ”‚ key_table_size_mb โ”‚ 2.76565551 โ”‚\n", + "โ”‚ bytes_per_record_avg โ”‚ 62.3888893 โ”‚\n", + "โ”‚ doc_table_size_mb โ”‚ 0.00782489 โ”‚\n", + "โ”‚ inverted_sz_mb โ”‚ 0.00214195 โ”‚\n", + "โ”‚ key_table_size_mb โ”‚ 1.14440917 โ”‚\n", "โ”‚ offset_bits_per_record_avg โ”‚ 8 โ”‚\n", - "โ”‚ offset_vectors_sz_mb โ”‚ 2.09808349 โ”‚\n", - "โ”‚ offsets_per_term_avg โ”‚ 0.75862067 โ”‚\n", - "โ”‚ records_per_doc_avg โ”‚ 29 โ”‚\n", + "โ”‚ offset_vectors_sz_mb โ”‚ 2.67028808 โ”‚\n", + "โ”‚ offsets_per_term_avg โ”‚ 0.77777779 โ”‚\n", + "โ”‚ records_per_doc_avg โ”‚ 36 โ”‚\n", "โ”‚ sortable_values_size_mb โ”‚ 0 โ”‚\n", - "โ”‚ total_indexing_time โ”‚ 14.3260002 โ”‚\n", + "โ”‚ total_indexing_time โ”‚ 1.366666 โ”‚\n", "โ”‚ total_inverted_index_blocks โ”‚ 21 โ”‚\n", - "โ”‚ vector_index_sz_mb โ”‚ 3.01609802 โ”‚\n", + "โ”‚ vector_index_sz_mb โ”‚ 3.01630401 โ”‚\n", "โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ\n" ] } @@ -648,7 +679,14 @@ { "cell_type": "code", "execution_count": 21, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:48.725899Z", + "iopub.status.busy": "2026-02-16T15:30:48.725759Z", + "iopub.status.idle": "2026-02-16T15:30:48.729675Z", + "shell.execute_reply": "2026-02-16T15:30:48.729206Z" + } + }, "outputs": [], "source": [ "# Clear the cache AND delete the underlying index\n", @@ -667,41 +705,16 @@ }, { "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:02:20 sentence_transformers.SentenceTransformer INFO Use pytorch device_name: mps\n", - "13:02:20 sentence_transformers.SentenceTransformer INFO Load pretrained SentenceTransformer: redis/langcache-embed-v1\n", - "13:02:20 sentence_transformers.SentenceTransformer WARNING You try to use a model that was created with version 4.1.0, however, your version is 3.4.1. This might cause unexpected behavior or errors. In that case, try to update to the latest version.\n", - "\n", - "\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 17.15it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 21.23it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 21.71it/s]\n" - ] - }, - { - "data": { - "text/plain": [ - "'private_cache:2831a0659fb888e203cd9fedb9f65681bfa55e4977c092ed1bf87d42d2655081'" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:30:48.730938Z", + "iopub.status.busy": "2026-02-16T15:30:48.730860Z", + "iopub.status.idle": "2026-02-16T15:31:03.090895Z", + "shell.execute_reply": "2026-02-16T15:31:03.090496Z" } - ], + }, + "outputs": [], "source": [ "private_cache = SemanticCache(\n", " name=\"private_cache\",\n", @@ -724,15 +737,15 @@ { "cell_type": "code", "execution_count": 23, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:31:03.092088Z", + "iopub.status.busy": "2026-02-16T15:31:03.092010Z", + "iopub.status.idle": "2026-02-16T15:31:03.133762Z", + "shell.execute_reply": "2026-02-16T15:31:03.133324Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 22.36it/s]" - ] - }, { "name": "stdout", "output_type": "stream", @@ -740,13 +753,6 @@ "found 1 entry \n", "The number on file is 123-555-0000\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] } ], "source": [ @@ -767,7 +773,14 @@ { "cell_type": "code", "execution_count": 24, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:31:03.134804Z", + "iopub.status.busy": "2026-02-16T15:31:03.134726Z", + "iopub.status.idle": "2026-02-16T15:31:03.137313Z", + "shell.execute_reply": "2026-02-16T15:31:03.136962Z" + } + }, "outputs": [], "source": [ "# Cleanup\n", @@ -783,43 +796,16 @@ }, { "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:02:21 sentence_transformers.SentenceTransformer INFO Use pytorch device_name: mps\n", - "13:02:21 sentence_transformers.SentenceTransformer INFO Load pretrained SentenceTransformer: redis/langcache-embed-v1\n", - "13:02:21 sentence_transformers.SentenceTransformer WARNING You try to use a model that was created with version 4.1.0, however, your version is 3.4.1. This might cause unexpected behavior or errors. In that case, try to update to the latest version.\n", - "\n", - "\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 21.08it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 8.74it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 8.01it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 21.70it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 16.74it/s]\n" - ] - }, - { - "data": { - "text/plain": [ - "'account_data:944f89729b09ca46b99923d223db45e0bccf584cfd53fcaf87d2a58f072582d3'" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:31:03.138485Z", + "iopub.status.busy": "2026-02-16T15:31:03.138420Z", + "iopub.status.idle": "2026-02-16T15:31:17.795752Z", + "shell.execute_reply": "2026-02-16T15:31:17.795268Z" } - ], + }, + "outputs": [], "source": [ "\n", "complex_cache = SemanticCache(\n", @@ -856,15 +842,15 @@ { "cell_type": "code", "execution_count": 26, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:31:17.796921Z", + "iopub.status.busy": "2026-02-16T15:31:17.796847Z", + "iopub.status.idle": "2026-02-16T15:31:17.838671Z", + "shell.execute_reply": "2026-02-16T15:31:17.838340Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 19.91it/s]" - ] - }, { "name": "stdout", "output_type": "stream", @@ -872,13 +858,6 @@ "found 1 entry\n", "Your most recent transaction was for $350\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] } ], "source": [ @@ -899,13 +878,39 @@ "print(response[0][\"response\"])" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand semantic caching, explore these related guides:\n", + "\n", + "- [Cache Embeddings](10_embeddings_cache.ipynb) - Cache embedding vectors for faster repeated computations\n", + "- [Manage LLM Message History](07_message_history.ipynb) - Store and retrieve conversation history\n", + "- [Query and Filter Data](02_complex_filtering.ipynb) - Learn more about filter expressions for cache access control" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleanup" + ] + }, { "cell_type": "code", "execution_count": 27, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:31:17.839962Z", + "iopub.status.busy": "2026-02-16T15:31:17.839884Z", + "iopub.status.idle": "2026-02-16T15:31:17.842367Z", + "shell.execute_reply": "2026-02-16T15:31:17.841965Z" + } + }, "outputs": [], "source": [ - "# Cleanup\n", "complex_cache.delete()" ] } @@ -926,9 +931,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.8" - }, - "orig_nbformat": 4 + "version": "3.13.2" + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/docs/user_guide/04_vectorizers.ipynb b/docs/user_guide/04_vectorizers.ipynb index fbb1b03f..4f57b0e2 100644 --- a/docs/user_guide/04_vectorizers.ipynb +++ b/docs/user_guide/04_vectorizers.ipynb @@ -5,29 +5,25 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Vectorizers\n", + "# Create Embeddings with Vectorizers\n", "\n", - "In this notebook, we will show how to use RedisVL to create embeddings using the built-in text embedding vectorizers. Today RedisVL supports:\n", - "1. OpenAI\n", - "2. HuggingFace\n", - "3. Vertex AI\n", - "4. Cohere\n", - "5. Mistral AI\n", - "6. Amazon Bedrock\n", - "7. Bringing your own vectorizer\n", - "8. VoyageAI\n", + "This guide demonstrates how to create embeddings using RedisVL's built-in text vectorizers. RedisVL supports multiple embedding providers: OpenAI, HuggingFace, Vertex AI, Cohere, Mistral AI, Amazon Bedrock, VoyageAI, and custom vectorizers.\n", "\n", - "Before running this notebook, be sure to\n", - "1. Have installed ``redisvl`` and have that environment active for this notebook.\n", - "2. Have a running Redis Stack instance with RediSearch > 2.4 active.\n", + "## Prerequisites\n", "\n", - "For example, you can run Redis Stack locally with Docker:\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", + "- API keys for the embedding providers you plan to use\n", "\n", - "```bash\n", - "docker run -d -p 6379:6379 -p 8001:8001 redis/redis-stack:latest\n", - "```\n", + "## What You'll Learn\n", "\n", - "This will run Redis on port 6379 and RedisInsight at http://localhost:8001." + "By the end of this guide, you will be able to:\n", + "- Create embeddings using multiple providers (OpenAI, HuggingFace, Cohere, etc.)\n", + "- Use synchronous and asynchronous embedding methods\n", + "- Batch embed multiple texts efficiently\n", + "- Build custom vectorizers for your own embedding functions\n", + "- Integrate vectorizers with RedisVL indexes for semantic search" ] }, { @@ -210,16 +206,58 @@ "metadata": {}, "outputs": [ { - "ename": "ValueError", - "evalue": "AzureOpenAI API endpoint is required. Provide it in api_config or set the AZURE_OPENAI_ENDPOINT environment variable.", - "output_type": "error", - "traceback": [ - "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", - "\u001B[0;31mValueError\u001B[0m Traceback (most recent call last)", - "Cell \u001B[0;32mIn[7], line 4\u001B[0m\n\u001B[1;32m 1\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;21;01mredisvl\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mutils\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mvectorize\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mimport\u001B[39;00m AzureOpenAITextVectorizer\n\u001B[1;32m 3\u001B[0m \u001B[38;5;66;03m# create a vectorizer\u001B[39;00m\n\u001B[0;32m----> 4\u001B[0m az_oai \u001B[38;5;241m=\u001B[39m \u001B[43mAzureOpenAITextVectorizer\u001B[49m\u001B[43m(\u001B[49m\n\u001B[1;32m 5\u001B[0m \u001B[43m \u001B[49m\u001B[43mmodel\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mdeployment_name\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;66;43;03m# Must be your CUSTOM deployment name\u001B[39;49;00m\n\u001B[1;32m 6\u001B[0m \u001B[43m \u001B[49m\u001B[43mapi_config\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43m{\u001B[49m\n\u001B[1;32m 7\u001B[0m \u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mapi_key\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43mapi_key\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 8\u001B[0m \u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mapi_version\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43mapi_version\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 9\u001B[0m \u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mazure_endpoint\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43mazure_endpoint\u001B[49m\n\u001B[1;32m 10\u001B[0m \u001B[43m \u001B[49m\u001B[43m}\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 11\u001B[0m \u001B[43m)\u001B[49m\n\u001B[1;32m 13\u001B[0m test \u001B[38;5;241m=\u001B[39m az_oai\u001B[38;5;241m.\u001B[39membed(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mThis is a test sentence.\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m 14\u001B[0m \u001B[38;5;28mprint\u001B[39m(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mVector dimensions: \u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;28mlen\u001B[39m(test))\n", - "File \u001B[0;32m~/src/redis-vl-python/redisvl/utils/vectorize/text/azureopenai.py:78\u001B[0m, in \u001B[0;36mAzureOpenAITextVectorizer.__init__\u001B[0;34m(self, model, api_config, dtype)\u001B[0m\n\u001B[1;32m 54\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;21m__init__\u001B[39m(\n\u001B[1;32m 55\u001B[0m \u001B[38;5;28mself\u001B[39m,\n\u001B[1;32m 56\u001B[0m model: \u001B[38;5;28mstr\u001B[39m \u001B[38;5;241m=\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtext-embedding-ada-002\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[1;32m 57\u001B[0m api_config: Optional[Dict] \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m 58\u001B[0m dtype: \u001B[38;5;28mstr\u001B[39m \u001B[38;5;241m=\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mfloat32\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[1;32m 59\u001B[0m ):\n\u001B[1;32m 60\u001B[0m \u001B[38;5;250m \u001B[39m\u001B[38;5;124;03m\"\"\"Initialize the AzureOpenAI vectorizer.\u001B[39;00m\n\u001B[1;32m 61\u001B[0m \n\u001B[1;32m 62\u001B[0m \u001B[38;5;124;03m Args:\u001B[39;00m\n\u001B[0;32m (...)\u001B[0m\n\u001B[1;32m 76\u001B[0m \u001B[38;5;124;03m ValueError: If an invalid dtype is provided.\u001B[39;00m\n\u001B[1;32m 77\u001B[0m \u001B[38;5;124;03m \"\"\"\u001B[39;00m\n\u001B[0;32m---> 78\u001B[0m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_initialize_clients\u001B[49m\u001B[43m(\u001B[49m\u001B[43mapi_config\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 79\u001B[0m \u001B[38;5;28msuper\u001B[39m()\u001B[38;5;241m.\u001B[39m\u001B[38;5;21m__init__\u001B[39m(model\u001B[38;5;241m=\u001B[39mmodel, dims\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_set_model_dims(model), dtype\u001B[38;5;241m=\u001B[39mdtype)\n", - "File \u001B[0;32m~/src/redis-vl-python/redisvl/utils/vectorize/text/azureopenai.py:106\u001B[0m, in \u001B[0;36mAzureOpenAITextVectorizer._initialize_clients\u001B[0;34m(self, api_config)\u001B[0m\n\u001B[1;32m 99\u001B[0m azure_endpoint \u001B[38;5;241m=\u001B[39m (\n\u001B[1;32m 100\u001B[0m api_config\u001B[38;5;241m.\u001B[39mpop(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mazure_endpoint\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m 101\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m api_config\n\u001B[1;32m 102\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m os\u001B[38;5;241m.\u001B[39mgetenv(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mAZURE_OPENAI_ENDPOINT\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m 103\u001B[0m )\n\u001B[1;32m 105\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m azure_endpoint:\n\u001B[0;32m--> 106\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mValueError\u001B[39;00m(\n\u001B[1;32m 107\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mAzureOpenAI API endpoint is required. \u001B[39m\u001B[38;5;124m\"\u001B[39m\n\u001B[1;32m 108\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mProvide it in api_config or set the AZURE_OPENAI_ENDPOINT\u001B[39m\u001B[38;5;130;01m\\\u001B[39;00m\n\u001B[1;32m 109\u001B[0m \u001B[38;5;124m environment variable.\u001B[39m\u001B[38;5;124m\"\u001B[39m\n\u001B[1;32m 110\u001B[0m )\n\u001B[1;32m 112\u001B[0m api_version \u001B[38;5;241m=\u001B[39m (\n\u001B[1;32m 113\u001B[0m api_config\u001B[38;5;241m.\u001B[39mpop(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mapi_version\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m 114\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m api_config\n\u001B[1;32m 115\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m os\u001B[38;5;241m.\u001B[39mgetenv(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mOPENAI_API_VERSION\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m 116\u001B[0m )\n\u001B[1;32m 118\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m api_version:\n", - "\u001B[0;31mValueError\u001B[0m: AzureOpenAI API endpoint is required. Provide it in api_config or set the AZURE_OPENAI_ENDPOINT environment variable." + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)\n", + "Cell \u001b[0;32mIn[7], line 4\u001b[0m\n", + "\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mredisvl\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mvectorize\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m AzureOpenAITextVectorizer\n", + "\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# create a vectorizer\u001b[39;00m\n", + "\u001b[0;32m----> 4\u001b[0m az_oai \u001b[38;5;241m=\u001b[39m \u001b[43mAzureOpenAITextVectorizer\u001b[49m\u001b[43m(\u001b[49m\n", + "\u001b[1;32m 5\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdeployment_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# Must be your CUSTOM deployment name\u001b[39;49;00m\n", + "\u001b[1;32m 6\u001b[0m \u001b[43m \u001b[49m\u001b[43mapi_config\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m{\u001b[49m\n", + "\u001b[1;32m 7\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mapi_key\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mapi_key\u001b[49m\u001b[43m,\u001b[49m\n", + "\u001b[1;32m 8\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mapi_version\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mapi_version\u001b[49m\u001b[43m,\u001b[49m\n", + "\u001b[1;32m 9\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mazure_endpoint\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mazure_endpoint\u001b[49m\n", + "\u001b[1;32m 10\u001b[0m \u001b[43m \u001b[49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\n", + "\u001b[1;32m 11\u001b[0m \u001b[43m)\u001b[49m\n", + "\u001b[1;32m 13\u001b[0m test \u001b[38;5;241m=\u001b[39m az_oai\u001b[38;5;241m.\u001b[39membed(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThis is a test sentence.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;32m 14\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mVector dimensions: \u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28mlen\u001b[39m(test))\n", + "File \u001b[0;32m~/src/redis-vl-python/redisvl/utils/vectorize/text/azureopenai.py:78\u001b[0m, in \u001b[0;36mAzureOpenAITextVectorizer.__init__\u001b[0;34m(self, model, api_config, dtype)\u001b[0m\n", + "\u001b[1;32m 54\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21m__init__\u001b[39m(\n", + "\u001b[1;32m 55\u001b[0m \u001b[38;5;28mself\u001b[39m,\n", + "\u001b[1;32m 56\u001b[0m model: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtext-embedding-ada-002\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n", + "\u001b[1;32m 57\u001b[0m api_config: Optional[Dict] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n", + "\u001b[1;32m 58\u001b[0m dtype: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfloat32\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n", + "\u001b[1;32m 59\u001b[0m ):\n", + "\u001b[1;32m 60\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Initialize the AzureOpenAI vectorizer.\u001b[39;00m\n", + "\u001b[1;32m 61\u001b[0m \n", + "\u001b[1;32m 62\u001b[0m \u001b[38;5;124;03m Args:\u001b[39;00m\n", + "\u001b[0;32m (...)\u001b[0m\n", + "\u001b[1;32m 76\u001b[0m \u001b[38;5;124;03m ValueError: If an invalid dtype is provided.\u001b[39;00m\n", + "\u001b[1;32m 77\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n", + "\u001b[0;32m---> 78\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_initialize_clients\u001b[49m\u001b[43m(\u001b[49m\u001b[43mapi_config\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[1;32m 79\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m(model\u001b[38;5;241m=\u001b[39mmodel, dims\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_set_model_dims(model), dtype\u001b[38;5;241m=\u001b[39mdtype)\n", + "File \u001b[0;32m~/src/redis-vl-python/redisvl/utils/vectorize/text/azureopenai.py:106\u001b[0m, in \u001b[0;36mAzureOpenAITextVectorizer._initialize_clients\u001b[0;34m(self, api_config)\u001b[0m\n", + "\u001b[1;32m 99\u001b[0m azure_endpoint \u001b[38;5;241m=\u001b[39m (\n", + "\u001b[1;32m 100\u001b[0m api_config\u001b[38;5;241m.\u001b[39mpop(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mazure_endpoint\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;32m 101\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m api_config\n", + "\u001b[1;32m 102\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m os\u001b[38;5;241m.\u001b[39mgetenv(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAZURE_OPENAI_ENDPOINT\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;32m 103\u001b[0m )\n", + "\u001b[1;32m 105\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m azure_endpoint:\n", + "\u001b[0;32m--> 106\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n", + "\u001b[1;32m 107\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAzureOpenAI API endpoint is required. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n", + "\u001b[1;32m 108\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mProvide it in api_config or set the AZURE_OPENAI_ENDPOINT\u001b[39m\u001b[38;5;130;01m\\\u001b[39;00m\n", + "\u001b[1;32m 109\u001b[0m \u001b[38;5;124m environment variable.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", + "\u001b[1;32m 110\u001b[0m )\n", + "\u001b[1;32m 112\u001b[0m api_version \u001b[38;5;241m=\u001b[39m (\n", + "\u001b[1;32m 113\u001b[0m api_config\u001b[38;5;241m.\u001b[39mpop(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mapi_version\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;32m 114\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m api_config\n", + "\u001b[1;32m 115\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m os\u001b[38;5;241m.\u001b[39mgetenv(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOPENAI_API_VERSION\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;32m 116\u001b[0m )\n", + "\u001b[1;32m 118\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m api_version:\n", + "\u001b[0;31mValueError\u001b[0m: AzureOpenAI API endpoint is required. Provide it in api_config or set the AZURE_OPENAI_ENDPOINT environment variable." ] } ], @@ -413,8 +451,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### VoyageAI\n", "\n", @@ -426,10 +464,10 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "import getpass\n", "# setup the API Key\n", @@ -447,10 +485,10 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "from redisvl.utils.vectorize import VoyageAIVectorizer\n", "\n", @@ -472,8 +510,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### Mistral AI\n", "\n", @@ -486,10 +524,10 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "from redisvl.utils.vectorize import MistralAITextVectorizer\n", "\n", @@ -748,13 +786,32 @@ "float16_bytes != float64_bytes" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand how to create embeddings, explore these related guides:\n", + "\n", + "- [Getting Started](01_getting_started.ipynb) - Learn the basics of indexes and queries\n", + "- [Rerank Results](06_rerankers.ipynb) - Improve search quality with reranking models\n", + "- [Cache Embeddings](10_embeddings_cache.ipynb) - Cache embedding vectors for faster repeated computations" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleanup" + ] + }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ - "# cleanup\n", "index.delete()" ] } diff --git a/docs/user_guide/05_hash_vs_json.ipynb b/docs/user_guide/05_hash_vs_json.ipynb index 08ebedc1..55d6eb04 100644 --- a/docs/user_guide/05_hash_vs_json.ipynb +++ b/docs/user_guide/05_hash_vs_json.ipynb @@ -5,30 +5,37 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Hash vs JSON Storage\n", + "# Choose a Storage Type\n", "\n", + "Redis provides a [variety of data structures](https://redis.com/redis-enterprise/data-structures/) that can adapt to your domain-specific applications. This guide demonstrates how to use RedisVL with both [Hash](https://redis.io/docs/latest/develop/data-types/#hashes) and [JSON](https://redis.io/docs/latest/develop/data-types/json/) storage types, helping you choose the right approach for your use case.\n", "\n", - "Out of the box, Redis provides a [variety of data structures](https://redis.com/redis-enterprise/data-structures/) that can adapt to your domain specific applications and use cases.\n", - "In this notebook, we will demonstrate how to use RedisVL with both [Hash](https://redis.io/docs/latest/develop/data-types/#hashes) and [JSON](https://redis.io/docs/latest/develop/data-types/json/) data.\n", + "## Prerequisites\n", "\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", "\n", - "Before running this notebook, be sure to\n", - "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", + "## What You'll Learn\n", "\n", - "For example, you can run [Redis Stack](https://redis.io/docs/install/install-stack/) locally with Docker:\n", - "\n", - "```bash\n", - "docker run -d -p 6379:6379 -p 8001:8001 redis/redis-stack:latest\n", - "```\n", - "\n", - "Or create a [FREE Redis Cloud](https://redis.io/cloud)." + "By the end of this guide, you will be able to:\n", + "- Understand the differences between Hash and JSON storage types\n", + "- Define schemas for both Hash and JSON storage\n", + "- Load and query data using each storage type\n", + "- Access nested JSON fields using JSONPath expressions\n", + "- Choose the right storage type for your application" ] }, { "cell_type": "code", "execution_count": 1, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:54.362316Z", + "iopub.status.busy": "2026-02-16T15:11:54.362207Z", + "iopub.status.idle": "2026-02-16T15:11:54.463860Z", + "shell.execute_reply": "2026-02-16T15:11:54.463331Z" + } + }, "outputs": [], "source": [ "# import necessary modules\n", @@ -45,7 +52,14 @@ { "cell_type": "code", "execution_count": 2, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:54.465121Z", + "iopub.status.busy": "2026-02-16T15:11:54.465039Z", + "iopub.status.idle": "2026-02-16T15:11:54.468382Z", + "shell.execute_reply": "2026-02-16T15:11:54.467903Z" + } + }, "outputs": [ { "data": { @@ -70,8 +84,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Hash or JSON -- how to choose?\n", - "Both storage options offer a variety of features and tradeoffs. Below we will work through a dummy dataset to learn when and how to use both." + "## Hash or JSON: How to Choose\n", + "Both storage options offer different features and tradeoffs. This section walks through a sample dataset to illustrate when and how to use each option." ] }, { @@ -101,7 +115,14 @@ { "cell_type": "code", "execution_count": 3, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:54.484701Z", + "iopub.status.busy": "2026-02-16T15:11:54.484603Z", + "iopub.status.idle": "2026-02-16T15:11:54.486719Z", + "shell.execute_reply": "2026-02-16T15:11:54.486317Z" + } + }, "outputs": [], "source": [ "# define the hash index schema\n", @@ -135,7 +156,14 @@ { "cell_type": "code", "execution_count": 4, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:54.487803Z", + "iopub.status.busy": "2026-02-16T15:11:54.487722Z", + "iopub.status.idle": "2026-02-16T15:11:54.495694Z", + "shell.execute_reply": "2026-02-16T15:11:54.495284Z" + } + }, "outputs": [], "source": [ "# construct a search index from the hash schema\n", @@ -148,7 +176,14 @@ { "cell_type": "code", "execution_count": 5, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:54.496722Z", + "iopub.status.busy": "2026-02-16T15:11:54.496651Z", + "iopub.status.idle": "2026-02-16T15:11:54.498521Z", + "shell.execute_reply": "2026-02-16T15:11:54.498169Z" + } + }, "outputs": [ { "data": { @@ -177,7 +212,14 @@ { "cell_type": "code", "execution_count": 6, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:54.499497Z", + "iopub.status.busy": "2026-02-16T15:11:54.499433Z", + "iopub.status.idle": "2026-02-16T15:11:54.501307Z", + "shell.execute_reply": "2026-02-16T15:11:54.500928Z" + } + }, "outputs": [ { "data": { @@ -204,7 +246,14 @@ { "cell_type": "code", "execution_count": 7, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:54.502213Z", + "iopub.status.busy": "2026-02-16T15:11:54.502145Z", + "iopub.status.idle": "2026-02-16T15:11:54.505688Z", + "shell.execute_reply": "2026-02-16T15:11:54.505256Z" + } + }, "outputs": [], "source": [ "# load hash data\n", @@ -214,7 +263,14 @@ { "cell_type": "code", "execution_count": 8, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:54.506600Z", + "iopub.status.busy": "2026-02-16T15:11:54.506539Z", + "iopub.status.idle": "2026-02-16T15:11:56.716087Z", + "shell.execute_reply": "2026-02-16T15:11:56.715443Z" + } + }, "outputs": [ { "name": "stdout", @@ -232,18 +288,18 @@ "โ”‚ percent_indexed โ”‚ 1 โ”‚\n", "โ”‚ hash_indexing_failures โ”‚ 0 โ”‚\n", "โ”‚ number_of_uses โ”‚ 1 โ”‚\n", - "โ”‚ bytes_per_record_avg โ”‚ 40.2954559 โ”‚\n", - "โ”‚ doc_table_size_mb โ”‚ 7.27653503 โ”‚\n", - "โ”‚ inverted_sz_mb โ”‚ 0.00169086 โ”‚\n", - "โ”‚ key_table_size_mb โ”‚ 2.48908996 โ”‚\n", + "โ”‚ bytes_per_record_avg โ”‚ 39.0681800 โ”‚\n", + "โ”‚ doc_table_size_mb โ”‚ 0.00837230 โ”‚\n", + "โ”‚ inverted_sz_mb โ”‚ 0.00163936 โ”‚\n", + "โ”‚ key_table_size_mb โ”‚ 3.50952148 โ”‚\n", "โ”‚ offset_bits_per_record_avg โ”‚ 8 โ”‚\n", "โ”‚ offset_vectors_sz_mb โ”‚ 8.58306884 โ”‚\n", "โ”‚ offsets_per_term_avg โ”‚ 0.20454545 โ”‚\n", "โ”‚ records_per_doc_avg โ”‚ 6.28571414 โ”‚\n", "โ”‚ sortable_values_size_mb โ”‚ 0 โ”‚\n", - "โ”‚ total_indexing_time โ”‚ 0.25799998 โ”‚\n", + "โ”‚ total_indexing_time โ”‚ 0.55204 โ”‚\n", "โ”‚ total_inverted_index_blocks โ”‚ 18 โ”‚\n", - "โ”‚ vector_index_sz_mb โ”‚ 0.02023315 โ”‚\n", + "โ”‚ vector_index_sz_mb โ”‚ 0.02820587 โ”‚\n", "โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ\n" ] } @@ -263,7 +319,14 @@ { "cell_type": "code", "execution_count": 9, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:56.717836Z", + "iopub.status.busy": "2026-02-16T15:11:56.717694Z", + "iopub.status.idle": "2026-02-16T15:11:56.752557Z", + "shell.execute_reply": "2026-02-16T15:11:56.752177Z" + } + }, "outputs": [ { "data": { @@ -299,7 +362,14 @@ { "cell_type": "code", "execution_count": 10, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:56.753771Z", + "iopub.status.busy": "2026-02-16T15:11:56.753644Z", + "iopub.status.idle": "2026-02-16T15:11:56.756113Z", + "shell.execute_reply": "2026-02-16T15:11:56.755647Z" + } + }, "outputs": [], "source": [ "# clean up\n", @@ -321,7 +391,14 @@ { "cell_type": "code", "execution_count": 11, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:56.757103Z", + "iopub.status.busy": "2026-02-16T15:11:56.757033Z", + "iopub.status.idle": "2026-02-16T15:11:56.759150Z", + "shell.execute_reply": "2026-02-16T15:11:56.758778Z" + } + }, "outputs": [], "source": [ "# define the json index schema\n", @@ -355,7 +432,14 @@ { "cell_type": "code", "execution_count": 12, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:56.759972Z", + "iopub.status.busy": "2026-02-16T15:11:56.759905Z", + "iopub.status.idle": "2026-02-16T15:11:56.765756Z", + "shell.execute_reply": "2026-02-16T15:11:56.765336Z" + } + }, "outputs": [], "source": [ "# construct a search index from the json schema\n", @@ -365,37 +449,25 @@ "jindex.create(overwrite=True)" ] }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:02:56 [RedisVL] INFO Indices:\n", - "13:02:56 [RedisVL] INFO 1. user-json\n" - ] - } - ], - "source": [ - "# note the multiple indices in the same database\n", - "!rvl index listall" - ] - }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Vectors as float arrays\n", - "Vectorized data stored in JSON must be stored as a pure array (python list) of floats. We will modify our sample data to account for this below:" + "#### Vectors as Float Arrays\n", + "Vectorized data stored in JSON must be a pure array (Python list) of floats. The following code modifies the sample data to use this format:" ] }, { "cell_type": "code", "execution_count": 14, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:58.986663Z", + "iopub.status.busy": "2026-02-16T15:11:58.986526Z", + "iopub.status.idle": "2026-02-16T15:11:58.988889Z", + "shell.execute_reply": "2026-02-16T15:11:58.988468Z" + } + }, "outputs": [], "source": [ "json_data = data.copy()\n", @@ -407,7 +479,14 @@ { "cell_type": "code", "execution_count": 15, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:58.990194Z", + "iopub.status.busy": "2026-02-16T15:11:58.990097Z", + "iopub.status.idle": "2026-02-16T15:11:58.992416Z", + "shell.execute_reply": "2026-02-16T15:11:58.991986Z" + } + }, "outputs": [ { "data": { @@ -434,7 +513,14 @@ { "cell_type": "code", "execution_count": 16, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:58.993584Z", + "iopub.status.busy": "2026-02-16T15:11:58.993488Z", + "iopub.status.idle": "2026-02-16T15:11:59.005613Z", + "shell.execute_reply": "2026-02-16T15:11:59.005203Z" + } + }, "outputs": [], "source": [ "keys = jindex.load(json_data)" @@ -443,7 +529,14 @@ { "cell_type": "code", "execution_count": 17, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:59.006784Z", + "iopub.status.busy": "2026-02-16T15:11:59.006706Z", + "iopub.status.idle": "2026-02-16T15:11:59.009642Z", + "shell.execute_reply": "2026-02-16T15:11:59.009214Z" + } + }, "outputs": [ { "data": { @@ -473,7 +566,14 @@ { "cell_type": "code", "execution_count": 18, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:59.010651Z", + "iopub.status.busy": "2026-02-16T15:11:59.010585Z", + "iopub.status.idle": "2026-02-16T15:11:59.012692Z", + "shell.execute_reply": "2026-02-16T15:11:59.012327Z" + } + }, "outputs": [], "source": [ "jindex.delete()" @@ -483,7 +583,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Working with nested data in JSON\n", + "## Working with nested data in JSON\n", "\n", "Redis also supports native **JSON** objects. These can be multi-level (nested) objects, with full JSONPath support for updating/retrieving sub elements:\n", "\n", @@ -499,7 +599,7 @@ "}\n", "```\n", "\n", - "#### Full JSON Path support\n", + "### Full JSON Path support\n", "Because Redis enables full JSON path support, when creating an index schema, elements need to be indexed and selected by their path with the desired `name` AND `path` that points to where the data is located within the objects.\n", "\n", "> By default, RedisVL will assume the path as `$.{name}` if not provided in JSON fields schema. If nested provide path as `$.object.attribute`\n", @@ -509,35 +609,16 @@ }, { "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/.venv/lib/python3.13/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:02:58 sentence_transformers.SentenceTransformer INFO Use pytorch device_name: mps\n", - "13:02:58 sentence_transformers.SentenceTransformer INFO Load pretrained SentenceTransformer: sentence-transformers/all-mpnet-base-v2\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 7.23it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 12.93it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 14.10it/s]\n" - ] + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:11:59.013698Z", + "iopub.status.busy": "2026-02-16T15:11:59.013621Z", + "iopub.status.idle": "2026-02-16T15:14:22.016688Z", + "shell.execute_reply": "2026-02-16T15:14:22.016239Z" } - ], + }, + "outputs": [], "source": [ "from redisvl.utils.vectorize import HFTextVectorizer\n", "\n", @@ -608,7 +689,14 @@ { "cell_type": "code", "execution_count": 20, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:22.018616Z", + "iopub.status.busy": "2026-02-16T15:14:22.018248Z", + "iopub.status.idle": "2026-02-16T15:14:22.025124Z", + "shell.execute_reply": "2026-02-16T15:14:22.024757Z" + } + }, "outputs": [], "source": [ "# construct a search index from the json schema\n", @@ -621,13 +709,20 @@ { "cell_type": "code", "execution_count": 21, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:22.026295Z", + "iopub.status.busy": "2026-02-16T15:14:22.026205Z", + "iopub.status.idle": "2026-02-16T15:14:22.045669Z", + "shell.execute_reply": "2026-02-16T15:14:22.045074Z" + } + }, "outputs": [ { "data": { "text/plain": [ - "['bike-json:01JY4J9M48CXF7F4Y6HRGEMT9B',\n", - " 'bike-json:01JY4J9M48RRY6F80HR82CVZ5G']" + "['bike-json:01KHKJ5WW3DJE0X6E85GG27V0X',\n", + " 'bike-json:01KHKJ5WW3DJE0X6E85GG27V0Y']" ] }, "execution_count": 21, @@ -642,16 +737,15 @@ { "cell_type": "code", "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 11.72it/s]\n" - ] + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:22.047027Z", + "iopub.status.busy": "2026-02-16T15:14:22.046922Z", + "iopub.status.idle": "2026-02-16T15:14:22.125293Z", + "shell.execute_reply": "2026-02-16T15:14:22.124767Z" } - ], + }, + "outputs": [], "source": [ "from redisvl.query import VectorQuery\n", "\n", @@ -681,17 +775,24 @@ { "cell_type": "code", "execution_count": 23, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:22.126473Z", + "iopub.status.busy": "2026-02-16T15:14:22.126390Z", + "iopub.status.idle": "2026-02-16T15:14:22.128425Z", + "shell.execute_reply": "2026-02-16T15:14:22.128159Z" + } + }, "outputs": [ { "data": { "text/plain": [ - "[{'id': 'bike-json:01JY4J9M48RRY6F80HR82CVZ5G',\n", - " 'vector_distance': '0.519989132881',\n", + "[{'id': 'bike-json:01KHKJ5WW3DJE0X6E85GG27V0Y',\n", + " 'vector_distance': '0.519988954067',\n", " 'brand': 'Trek',\n", " '$.metadata.type': 'Enduro bikes'},\n", - " {'id': 'bike-json:01JY4J9M48CXF7F4Y6HRGEMT9B',\n", - " 'vector_distance': '0.657624304295',\n", + " {'id': 'bike-json:01KHKJ5WW3DJE0X6E85GG27V0X',\n", + " 'vector_distance': '0.65762424469',\n", " 'brand': 'Specialized',\n", " '$.metadata.type': 'Enduro bikes'}]" ] @@ -705,10 +806,30 @@ "results" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand Hash vs JSON storage, explore these related guides:\n", + "\n", + "- [Getting Started](01_getting_started.ipynb) - Learn the basics of RedisVL indexes and queries\n", + "- [Query and Filter Data](02_complex_filtering.ipynb) - Apply filters to narrow down search results\n", + "- [Use Advanced Query Types](11_advanced_queries.ipynb) - Explore TextQuery, HybridQuery, and more" + ] + }, { "cell_type": "code", "execution_count": 24, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:22.129638Z", + "iopub.status.busy": "2026-02-16T15:14:22.129565Z", + "iopub.status.idle": "2026-02-16T15:14:22.132318Z", + "shell.execute_reply": "2026-02-16T15:14:22.131960Z" + } + }, "outputs": [], "source": [ "# Cleanup\n", @@ -733,8 +854,7 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" - }, - "orig_nbformat": 4 + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/docs/user_guide/06_rerankers.ipynb b/docs/user_guide/06_rerankers.ipynb index 47327f17..a6f0a786 100644 --- a/docs/user_guide/06_rerankers.ipynb +++ b/docs/user_guide/06_rerankers.ipynb @@ -5,33 +5,35 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Rerankers\n", + "# Rerank Search Results\n", "\n", - "In this notebook, we will show how to use RedisVL to rerank search results\n", - "(documents or chunks or records) based on the input query. Today RedisVL\n", - "supports reranking through: \n", + "This guide demonstrates how to use RedisVL to rerank search results (documents, chunks, or records) based on query relevance. RedisVL supports reranking through Cross-Encoders from [Hugging Face](https://huggingface.co/cross-encoder), [Cohere Rerank API](https://docs.cohere.com/docs/rerank-2), and [VoyageAI Rerank API](https://docs.voyageai.com/docs/reranker).\n", "\n", - "- A re-ranker that uses pre-trained [Cross-Encoders](https://sbert.net/examples/applications/cross-encoder/README.html) which can use models from [Hugging Face cross encoder models](https://huggingface.co/cross-encoder) or Hugging Face models that implement a cross encoder function ([example: BAAI/bge-reranker-base](https://huggingface.co/BAAI/bge-reranker-base)).\n", - "- The [Cohere /rerank API](https://docs.cohere.com/docs/rerank-2).\n", - "- The [VoyageAI /rerank API](https://docs.voyageai.com/docs/reranker).\n", + "## Prerequisites\n", "\n", - "Before running this notebook, be sure to:\n", - "1. Have installed ``redisvl`` and have that environment active for this notebook.\n", - "2. Have a running Redis Stack instance with RediSearch > 2.4 active.\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", "\n", - "For example, you can run Redis Stack locally with Docker:\n", + "## What You'll Learn\n", "\n", - "```bash\n", - "docker run -d -p 6379:6379 -p 8001:8001 redis/redis-stack:latest\n", - "```\n", - "\n", - "This will run Redis on port 6379 and RedisInsight at http://localhost:8001." + "By the end of this guide, you will be able to:\n", + "- Rerank search results using HuggingFace Cross-Encoders\n", + "- Use the Cohere Rerank API with search results\n", + "- Use the VoyageAI Rerank API for result reranking\n", + "- Control the number of returned results after reranking" ] }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 1, "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:32:09.967389Z", + "iopub.status.busy": "2026-02-16T15:32:09.967294Z", + "iopub.status.idle": "2026-02-16T15:32:09.971189Z", + "shell.execute_reply": "2026-02-16T15:32:09.970731Z" + }, "metadata": {} }, "outputs": [], @@ -54,8 +56,14 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 2, "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:32:09.972292Z", + "iopub.status.busy": "2026-02-16T15:32:09.972216Z", + "iopub.status.idle": "2026-02-16T15:32:09.974281Z", + "shell.execute_reply": "2026-02-16T15:32:09.973867Z" + }, "metadata": {} }, "outputs": [], @@ -90,8 +98,14 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:32:09.975213Z", + "iopub.status.busy": "2026-02-16T15:32:09.975140Z", + "iopub.status.idle": "2026-02-16T15:32:19.781103Z", + "shell.execute_reply": "2026-02-16T15:32:19.780585Z" + }, "metadata": {} }, "outputs": [], @@ -113,8 +127,14 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 4, "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:32:19.783522Z", + "iopub.status.busy": "2026-02-16T15:32:19.783080Z", + "iopub.status.idle": "2026-02-16T15:32:20.918398Z", + "shell.execute_reply": "2026-02-16T15:32:20.917873Z" + }, "metadata": {} }, "outputs": [], @@ -124,8 +144,14 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 5, "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:32:20.919961Z", + "iopub.status.busy": "2026-02-16T15:32:20.919855Z", + "iopub.status.idle": "2026-02-16T15:32:20.921905Z", + "shell.execute_reply": "2026-02-16T15:32:20.921488Z" + }, "metadata": {} }, "outputs": [ @@ -133,9 +159,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "0.07461125403642654 -- {'content': 'Washington, D.C. (also known as simply Washington or D.C., and officially as the District of Columbia) is the capital of the United States. It is a federal district. The President of the USA and many major national government offices are in the territory. This makes it the political center of the United States of America.'}\n", - "0.05220315232872963 -- {'content': 'Charlotte Amalie is the capital and largest city of the United States Virgin Islands. It has about 20,000 people. The city is on the island of Saint Thomas.'}\n", - "0.3802368640899658 -- {'content': 'Carson City is the capital city of the American state of Nevada. At the 2010 United States Census, Carson City had a population of 55,274.'}\n" + "0.07461103051900864 -- {'content': 'Washington, D.C. (also known as simply Washington or D.C., and officially as the District of Columbia) is the capital of the United States. It is a federal district. The President of the USA and many major national government offices are in the territory. This makes it the political center of the United States of America.'}\n", + "0.052202966064214706 -- {'content': 'Charlotte Amalie is the capital and largest city of the United States Virgin Islands. It has about 20,000 people. The city is on the island of Saint Thomas.'}\n", + "0.3802356719970703 -- {'content': 'Carson City is the capital city of the American state of Nevada. At the 2010 United States Census, Carson City had a population of 55,274.'}\n" ] } ], @@ -197,8 +223,8 @@ "source": [ "### Rerank documents with CohereReranker\n", "\n", - "Below we will use the `CohereReranker` to rerank and truncate the list of\n", - "documents above based on relevance to the initial query." + "The following example uses `CohereReranker` to rerank and truncate the list of\n", + "documents based on relevance to the initial query." ] }, { @@ -308,99 +334,119 @@ " print(score, \" -- \", result)" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the VoyageAI Reranker\n", - "\n", - "To initialize the VoyageAI reranker you'll need to install the voyaeai library and provide the right VoyageAI API Key." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "#!pip install voyageai" - ] + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the VoyageAI Reranker\n", + "\n", + "To initialize the VoyageAI reranker you'll need to install the voyaeai library and provide the right VoyageAI API Key." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "metadata": {} }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import getpass\n", - "\n", - "# setup the API Key\n", - "api_key = os.environ.get(\"VOYAGE_API_KEY\") or getpass.getpass(\"Enter your VoyageAI API key: \")" - ] + "outputs": [], + "source": [ + "#!pip install voyageai" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "metadata": {} }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "from redisvl.utils.rerank import VoyageAIReranker\n", - "\n", - "reranker = VoyageAIReranker(model=\"rerank-lite-1\", limit=3, api_config={\"api_key\": api_key})", - "# Please check the available models at https://docs.voyageai.com/docs/reranker" - ] + "outputs": [], + "source": [ + "import getpass\n", + "\n", + "# setup the API Key\n", + "api_key = os.environ.get(\"VOYAGE_API_KEY\") or getpass.getpass(\"Enter your VoyageAI API key: \")" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "metadata": {} }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Rerank documents with VoyageAIReranker\n", - "\n", - "Below we will use the `VoyageAIReranker` to rerank and also truncate the list of\n", - "documents above based on relevance to the initial query." - ] + "outputs": [], + "source": [ + "from redisvl.utils.rerank import VoyageAIReranker\n", + "\n", + "reranker = VoyageAIReranker(model=\"rerank-lite-1\", limit=3, api_config={\"api_key\": api_key})\n", + "# Please check the available models at https://docs.voyageai.com/docs/reranker" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Rerank documents with VoyageAIReranker\n", + "\n", + "The following example uses `VoyageAIReranker` to rerank and truncate the list of\n", + "documents based on relevance to the initial query." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "metadata": {} }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "results, scores = reranker.rank(query=query, docs=docs)" - ] + "outputs": [], + "source": [ + "results, scores = reranker.rank(query=query, docs=docs)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "metadata": {} }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.796875 -- Washington, D.C. (also known as simply Washington or D.C., and officially as the District of Columbia) is the capital of the United States. It is a federal district. The President of the USA and many major national government offices are in the territory. This makes it the political center of the United States of America.\n", - "0.578125 -- Charlotte Amalie is the capital and largest city of the United States Virgin Islands. It has about 20,000 people. The city is on the island of Saint Thomas.\n", - "0.5625 -- Carson City is the capital city of the American state of Nevada. At the 2010 United States Census, Carson City had a population of 55,274.\n" - ] - } - ], - "source": [ - "for result, score in zip(results, scores):\n", - " print(score, \" -- \", result)" - ] - } - + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.796875 -- Washington, D.C. (also known as simply Washington or D.C., and officially as the District of Columbia) is the capital of the United States. It is a federal district. The President of the USA and many major national government offices are in the territory. This makes it the political center of the United States of America.\n", + "0.578125 -- Charlotte Amalie is the capital and largest city of the United States Virgin Islands. It has about 20,000 people. The city is on the island of Saint Thomas.\n", + "0.5625 -- Carson City is the capital city of the American state of Nevada. At the 2010 United States Census, Carson City had a population of 55,274.\n" + ] + } + ], + "source": [ + "for result, score in zip(results, scores):\n", + " print(score, \" -- \", result)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand reranking, explore these related guides:\n", + "\n", + "- [Create Embeddings with Vectorizers](04_vectorizers.ipynb) - Generate embeddings using various providers\n", + "- [Query and Filter Data](02_complex_filtering.ipynb) - Build complex filter expressions for search\n", + "- [Use Advanced Query Types](11_advanced_queries.ipynb) - Learn about HybridQuery and other query types" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleanup\n", + "\n", + "This guide does not create a persistent index, so no cleanup is required." + ] + } ], "metadata": { "kernelspec": { @@ -418,9 +464,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.13.2" }, - "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "9b1e6e9c2967143209c2f955cb869d1d3234f92dc4787f49f155f3abbdfb1316" diff --git a/docs/user_guide/07_message_history.ipynb b/docs/user_guide/07_message_history.ipynb index 58653377..3bade6f5 100644 --- a/docs/user_guide/07_message_history.ipynb +++ b/docs/user_guide/07_message_history.ipynb @@ -4,24 +4,38 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# LLM Message History" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Large Language Models are inherently stateless and have no knowledge of previous interactions with a user, or even of previous parts of the current conversation. While this may not be noticeable when asking simple questions, it becomes a hindrance when engaging in long running conversations that rely on conversational context.\n", + "# Manage LLM Message History\n", "\n", - "The solution to this problem is to append the previous conversation history to each subsequent call to the LLM.\n", + "Large Language Models are inherently stateless with no knowledge of previous interactions. This becomes a challenge when engaging in long conversations that rely on context. The solution is to store and retrieve conversation history with each LLM call.\n", "\n", - "This notebook will show how to use Redis to structure and store and retrieve this conversational message history." + "This guide demonstrates how to use Redis to structure, store, and retrieve conversational message history.\n", + "\n", + "## Prerequisites\n", + "\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", + "\n", + "## What You'll Learn\n", + "\n", + "By the end of this guide, you will be able to:\n", + "- Store and retrieve conversation messages with `MessageHistory`\n", + "- Manage multiple users and conversations with session tags\n", + "- Use `SemanticMessageHistory` for relevance-based context retrieval\n", + "- Prune incorrect or unwanted messages from conversation history" ] }, { "cell_type": "code", "execution_count": 1, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:26.666540Z", + "iopub.status.busy": "2026-02-16T15:14:26.666415Z", + "iopub.status.idle": "2026-02-16T15:14:26.852349Z", + "shell.execute_reply": "2026-02-16T15:14:26.851861Z" + } + }, "outputs": [], "source": [ "from redisvl.extensions.message_history import MessageHistory\n", @@ -42,7 +56,14 @@ { "cell_type": "code", "execution_count": 2, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:26.853637Z", + "iopub.status.busy": "2026-02-16T15:14:26.853546Z", + "iopub.status.idle": "2026-02-16T15:14:26.857201Z", + "shell.execute_reply": "2026-02-16T15:14:26.856790Z" + } + }, "outputs": [], "source": [ "chat_history.add_message({\"role\":\"system\", \"content\":\"You are a helpful geography tutor, giving simple and short answers to questions about European countries.\"})\n", @@ -66,7 +87,14 @@ { "cell_type": "code", "execution_count": 3, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:26.858324Z", + "iopub.status.busy": "2026-02-16T15:14:26.858239Z", + "iopub.status.idle": "2026-02-16T15:14:26.860874Z", + "shell.execute_reply": "2026-02-16T15:14:26.860556Z" + } + }, "outputs": [ { "name": "stdout", @@ -90,13 +118,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In many LLM flows the conversation progresses in a series of prompt and response pairs. Message history offer a convenience function `store()` to add these simply." + "In many LLM flows, conversations progress through a series of prompt and response pairs. MessageHistory provides a `store()` convenience function to add these efficiently." ] }, { "cell_type": "code", "execution_count": 4, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:26.877036Z", + "iopub.status.busy": "2026-02-16T15:14:26.876928Z", + "iopub.status.idle": "2026-02-16T15:14:26.880926Z", + "shell.execute_reply": "2026-02-16T15:14:26.880527Z" + } + }, "outputs": [ { "name": "stdout", @@ -138,7 +173,14 @@ { "cell_type": "code", "execution_count": 5, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:26.881966Z", + "iopub.status.busy": "2026-02-16T15:14:26.881897Z", + "iopub.status.idle": "2026-02-16T15:14:26.886779Z", + "shell.execute_reply": "2026-02-16T15:14:26.886459Z" + } + }, "outputs": [ { "name": "stdout", @@ -193,41 +235,16 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/.venv/lib/python3.13/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:03:39 sentence_transformers.SentenceTransformer INFO Use pytorch device_name: mps\n", - "13:03:39 sentence_transformers.SentenceTransformer INFO Load pretrained SentenceTransformer: sentence-transformers/all-mpnet-base-v2\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 6.59it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 10.33it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 9.91it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 12.52it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 57.92it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 60.45it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 13.38it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 13.65it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 62.33it/s]\n" - ] + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:26.887767Z", + "iopub.status.busy": "2026-02-16T15:14:26.887697Z", + "iopub.status.idle": "2026-02-16T15:14:45.120277Z", + "shell.execute_reply": "2026-02-16T15:14:45.119509Z" } - ], + }, + "outputs": [], "source": [ "from redisvl.extensions.message_history import SemanticMessageHistory\n", "semantic_history = SemanticMessageHistory(name='tutor')\n", @@ -238,28 +255,21 @@ { "cell_type": "code", "execution_count": 7, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:45.121921Z", + "iopub.status.busy": "2026-02-16T15:14:45.121583Z", + "iopub.status.idle": "2026-02-16T15:14:45.140847Z", + "shell.execute_reply": "2026-02-16T15:14:45.140417Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 56.30it/s]" - ] - }, { "name": "stdout", "output_type": "stream", "text": [ "{'role': 'user', 'content': 'what is the size of England compared to Portugal?'}\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] } ], "source": [ @@ -282,15 +292,15 @@ { "cell_type": "code", "execution_count": 8, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:45.141989Z", + "iopub.status.busy": "2026-02-16T15:14:45.141910Z", + "iopub.status.idle": "2026-02-16T15:14:45.161097Z", + "shell.execute_reply": "2026-02-16T15:14:45.160629Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 50.04it/s]" - ] - }, { "name": "stdout", "output_type": "stream", @@ -301,13 +311,6 @@ "{'role': 'llm', 'content': 'As of 2023 the population of Great Britain is approximately 67 million people.'}\n", "{'role': 'user', 'content': 'And what is the capital of Spain?'}\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] } ], "source": [ @@ -330,16 +333,15 @@ { "cell_type": "code", "execution_count": 9, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:45.162192Z", + "iopub.status.busy": "2026-02-16T15:14:45.162118Z", + "iopub.status.idle": "2026-02-16T15:14:45.253508Z", + "shell.execute_reply": "2026-02-16T15:14:45.253029Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 54.73it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 10.63it/s]" - ] - }, { "name": "stdout", "output_type": "stream", @@ -350,13 +352,6 @@ "{'role': 'llm', 'content': 'England is larger in land area than Portal by about 15000 square miles.'}\n", "{'role': 'user', 'content': 'what is the smallest country in Europe?'}\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] } ], "source": [ @@ -375,10 +370,37 @@ " print(message)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand message history management, explore these related guides:\n", + "\n", + "- [Cache LLM Responses](03_llmcache.ipynb) - Reduce API costs with semantic caching\n", + "- [Route Queries with SemanticRouter](08_semantic_router.ipynb) - Classify user queries to routes\n", + "- [Create Embeddings with Vectorizers](04_vectorizers.ipynb) - Use different embedding providers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleanup" + ] + }, { "cell_type": "code", "execution_count": 10, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:14:45.254702Z", + "iopub.status.busy": "2026-02-16T15:14:45.254613Z", + "iopub.status.idle": "2026-02-16T15:14:45.262152Z", + "shell.execute_reply": "2026-02-16T15:14:45.261798Z" + } + }, "outputs": [], "source": [ "chat_history.clear()\n", diff --git a/docs/user_guide/08_semantic_router.ipynb b/docs/user_guide/08_semantic_router.ipynb index 883ba154..d6c7f9d3 100644 --- a/docs/user_guide/08_semantic_router.ipynb +++ b/docs/user_guide/08_semantic_router.ipynb @@ -4,12 +4,26 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Semantic Routing\n", + "# Route Queries with SemanticRouter\n", "\n", - "RedisVL provides a `SemanticRouter` interface to utilize Redis' built-in search & aggregation in order to perform\n", - "KNN-style classification over a set of `Route` references to determine the best match.\n", + "RedisVL provides a `SemanticRouter` interface that uses Redis' built-in search and aggregation to perform KNN-style classification over a set of `Route` references to determine the best match.\n", "\n", - "This notebook will go over how to use Redis as a Semantic Router for your applications" + "This guide covers how to use Redis as a Semantic Router for your applications.\n", + "\n", + "## Prerequisites\n", + "\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", + "\n", + "## What You'll Learn\n", + "\n", + "By the end of this guide, you will be able to:\n", + "- Define routes with references and distance thresholds\n", + "- Initialize and configure a `SemanticRouter`\n", + "- Route queries to single or multiple matching routes\n", + "- Serialize and restore router configurations\n", + "- Manage route references dynamically" ] }, { @@ -33,7 +47,14 @@ { "cell_type": "code", "execution_count": 1, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:20.680382Z", + "iopub.status.busy": "2026-02-16T15:15:20.680256Z", + "iopub.status.idle": "2026-02-16T15:15:20.831021Z", + "shell.execute_reply": "2026-02-16T15:15:20.830579Z" + } + }, "outputs": [], "source": [ "from redisvl.extensions.router import Route\n", @@ -87,36 +108,16 @@ }, { "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/.venv/lib/python3.13/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:03:49 sentence_transformers.SentenceTransformer INFO Use pytorch device_name: mps\n", - "13:03:49 sentence_transformers.SentenceTransformer INFO Load pretrained SentenceTransformer: sentence-transformers/all-mpnet-base-v2\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 6.31it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 7.02it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 8.21it/s]\n", - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 54.33it/s]\n" - ] + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:20.832858Z", + "iopub.status.busy": "2026-02-16T15:15:20.832750Z", + "iopub.status.idle": "2026-02-16T15:15:39.080704Z", + "shell.execute_reply": "2026-02-16T15:15:39.080091Z" } - ], + }, + "outputs": [], "source": [ "import os\n", "from redisvl.extensions.router import SemanticRouter\n", @@ -137,7 +138,14 @@ { "cell_type": "code", "execution_count": 3, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:39.082179Z", + "iopub.status.busy": "2026-02-16T15:15:39.081841Z", + "iopub.status.idle": "2026-02-16T15:15:41.310811Z", + "shell.execute_reply": "2026-02-16T15:15:41.310025Z" + } + }, "outputs": [ { "name": "stdout", @@ -171,7 +179,14 @@ { "cell_type": "code", "execution_count": 4, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:41.312481Z", + "iopub.status.busy": "2026-02-16T15:15:41.312332Z", + "iopub.status.idle": "2026-02-16T15:15:41.317889Z", + "shell.execute_reply": "2026-02-16T15:15:41.317500Z" + } + }, "outputs": [ { "data": { @@ -198,19 +213,19 @@ { "cell_type": "code", "execution_count": 5, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:41.319266Z", + "iopub.status.busy": "2026-02-16T15:15:41.319168Z", + "iopub.status.idle": "2026-02-16T15:15:41.428746Z", + "shell.execute_reply": "2026-02-16T15:15:41.428297Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 8.63it/s]\n" - ] - }, { "data": { "text/plain": [ - "RouteMatch(name='technology', distance=0.419145941734)" + "RouteMatch(name='technology', distance=0.419146001339)" ] }, "execution_count": 5, @@ -227,15 +242,15 @@ { "cell_type": "code", "execution_count": 6, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:41.429820Z", + "iopub.status.busy": "2026-02-16T15:15:41.429738Z", + "iopub.status.idle": "2026-02-16T15:15:41.500562Z", + "shell.execute_reply": "2026-02-16T15:15:41.500220Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 11.71it/s]\n" - ] - }, { "data": { "text/plain": [ @@ -263,20 +278,20 @@ { "cell_type": "code", "execution_count": 7, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:41.501943Z", + "iopub.status.busy": "2026-02-16T15:15:41.501853Z", + "iopub.status.idle": "2026-02-16T15:15:41.576457Z", + "shell.execute_reply": "2026-02-16T15:15:41.575998Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 12.12it/s]\n" - ] - }, { "data": { "text/plain": [ - "[RouteMatch(name='technology', distance=0.556493639946),\n", - " RouteMatch(name='sports', distance=0.671060085297)]" + "[RouteMatch(name='technology', distance=0.556494116783),\n", + " RouteMatch(name='sports', distance=0.671060025692)]" ] }, "execution_count": 7, @@ -293,20 +308,20 @@ { "cell_type": "code", "execution_count": 8, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:41.577589Z", + "iopub.status.busy": "2026-02-16T15:15:41.577493Z", + "iopub.status.idle": "2026-02-16T15:15:41.598527Z", + "shell.execute_reply": "2026-02-16T15:15:41.598102Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 56.69it/s]\n" - ] - }, { "data": { "text/plain": [ - "[RouteMatch(name='technology', distance=0.556493639946),\n", - " RouteMatch(name='sports', distance=0.629264354706)]" + "[RouteMatch(name='technology', distance=0.556494116783),\n", + " RouteMatch(name='sports', distance=0.629264295101)]" ] }, "execution_count": 8, @@ -339,7 +354,14 @@ { "cell_type": "code", "execution_count": 9, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:41.599709Z", + "iopub.status.busy": "2026-02-16T15:15:41.599638Z", + "iopub.status.idle": "2026-02-16T15:15:41.601526Z", + "shell.execute_reply": "2026-02-16T15:15:41.601108Z" + } + }, "outputs": [], "source": [ "from redisvl.extensions.router import RoutingConfig\n", @@ -352,19 +374,19 @@ { "cell_type": "code", "execution_count": 10, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:41.602504Z", + "iopub.status.busy": "2026-02-16T15:15:41.602438Z", + "iopub.status.idle": "2026-02-16T15:15:41.674920Z", + "shell.execute_reply": "2026-02-16T15:15:41.674483Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 13.20it/s]\n" - ] - }, { "data": { "text/plain": [ - "[RouteMatch(name='sports', distance=0.663253903389)]" + "[RouteMatch(name='sports', distance=0.663253962994)]" ] }, "execution_count": 10, @@ -387,7 +409,14 @@ { "cell_type": "code", "execution_count": 11, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:41.676151Z", + "iopub.status.busy": "2026-02-16T15:15:41.676063Z", + "iopub.status.idle": "2026-02-16T15:15:41.678548Z", + "shell.execute_reply": "2026-02-16T15:15:41.678135Z" + } + }, "outputs": [ { "data": { @@ -430,38 +459,15 @@ { "cell_type": "code", "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:03:54 sentence_transformers.SentenceTransformer INFO Use pytorch device_name: mps\n", - "13:03:54 sentence_transformers.SentenceTransformer INFO Load pretrained SentenceTransformer: sentence-transformers/all-mpnet-base-v2\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 53.91it/s]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:03:54 redisvl.index.index INFO Index already exists, not overwriting.\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:41.679613Z", + "iopub.status.busy": "2026-02-16T15:15:41.679541Z", + "iopub.status.idle": "2026-02-16T15:15:55.642464Z", + "shell.execute_reply": "2026-02-16T15:15:55.641872Z" } - ], + }, + "outputs": [], "source": [ "router2 = SemanticRouter.from_dict(router.to_dict(), redis_url=\"redis://localhost:6379\")\n", "\n", @@ -471,7 +477,14 @@ { "cell_type": "code", "execution_count": 13, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:55.644078Z", + "iopub.status.busy": "2026-02-16T15:15:55.643979Z", + "iopub.status.idle": "2026-02-16T15:15:55.648101Z", + "shell.execute_reply": "2026-02-16T15:15:55.647611Z" + } + }, "outputs": [], "source": [ "router.to_yaml(\"router.yaml\", overwrite=True)" @@ -480,38 +493,15 @@ { "cell_type": "code", "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:03:54 sentence_transformers.SentenceTransformer INFO Use pytorch device_name: mps\n", - "13:03:54 sentence_transformers.SentenceTransformer INFO Load pretrained SentenceTransformer: sentence-transformers/all-mpnet-base-v2\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 51.94it/s]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "13:03:55 redisvl.index.index INFO Index already exists, not overwriting.\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:15:55.649161Z", + "iopub.status.busy": "2026-02-16T15:15:55.649082Z", + "iopub.status.idle": "2026-02-16T15:16:12.400026Z", + "shell.execute_reply": "2026-02-16T15:16:12.399532Z" } - ], + }, + "outputs": [], "source": [ "router3 = SemanticRouter.from_yaml(\"router.yaml\", redis_url=\"redis://localhost:6379\")\n", "\n", @@ -528,15 +518,15 @@ { "cell_type": "code", "execution_count": 15, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:12.401590Z", + "iopub.status.busy": "2026-02-16T15:16:12.401496Z", + "iopub.status.idle": "2026-02-16T15:16:12.508745Z", + "shell.execute_reply": "2026-02-16T15:16:12.508347Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Batches: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:00<00:00, 8.12it/s]\n" - ] - }, { "data": { "text/plain": [ @@ -563,23 +553,26 @@ { "cell_type": "code", "execution_count": 16, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:12.510070Z", + "iopub.status.busy": "2026-02-16T15:16:12.509990Z", + "iopub.status.idle": "2026-02-16T15:16:12.520872Z", + "shell.execute_reply": "2026-02-16T15:16:12.520468Z" + } + }, "outputs": [ { "data": { "text/plain": [ - "[{'id': 'topic-router:technology:85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n", - " 'reference_id': '85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n", + "[{'id': 'topic-router:technology:f243fb2d073774e81c7815247cb3013794e6225df3cbe3769cee8c6cefaca777',\n", + " 'reference_id': 'f243fb2d073774e81c7815247cb3013794e6225df3cbe3769cee8c6cefaca777',\n", " 'route_name': 'technology',\n", - " 'reference': 'tell me about the newest gadgets'},\n", + " 'reference': 'latest AI trends'},\n", " {'id': 'topic-router:technology:851f51cce5a9ccfbbcb66993908be6b7871479af3e3a4b139ad292a1bf7e0676',\n", " 'reference_id': '851f51cce5a9ccfbbcb66993908be6b7871479af3e3a4b139ad292a1bf7e0676',\n", " 'route_name': 'technology',\n", " 'reference': 'what are the latest advancements in AI?'},\n", - " {'id': 'topic-router:technology:f243fb2d073774e81c7815247cb3013794e6225df3cbe3769cee8c6cefaca777',\n", - " 'reference_id': 'f243fb2d073774e81c7815247cb3013794e6225df3cbe3769cee8c6cefaca777',\n", - " 'route_name': 'technology',\n", - " 'reference': 'latest AI trends'},\n", " {'id': 'topic-router:technology:7e4bca5853c1c3298b4d001de13c3c7a79a6e0f134f81acc2e7cddbd6845961f',\n", " 'reference_id': '7e4bca5853c1c3298b4d001de13c3c7a79a6e0f134f81acc2e7cddbd6845961f',\n", " 'route_name': 'technology',\n", @@ -587,7 +580,11 @@ " {'id': 'topic-router:technology:149a9c9919c58534aa0f369e85ad95ba7f00aa0513e0f81e2aff2ea4a717b0e0',\n", " 'reference_id': '149a9c9919c58534aa0f369e85ad95ba7f00aa0513e0f81e2aff2ea4a717b0e0',\n", " 'route_name': 'technology',\n", - " 'reference': \"what's trending in tech?\"}]" + " 'reference': \"what's trending in tech?\"},\n", + " {'id': 'topic-router:technology:85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n", + " 'reference_id': '85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n", + " 'route_name': 'technology',\n", + " 'reference': 'tell me about the newest gadgets'}]" ] }, "execution_count": 16, @@ -604,15 +601,22 @@ { "cell_type": "code", "execution_count": 17, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:12.521845Z", + "iopub.status.busy": "2026-02-16T15:16:12.521766Z", + "iopub.status.idle": "2026-02-16T15:16:12.524571Z", + "shell.execute_reply": "2026-02-16T15:16:12.524192Z" + } + }, "outputs": [ { "data": { "text/plain": [ - "[{'id': 'topic-router:technology:85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n", - " 'reference_id': '85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n", + "[{'id': 'topic-router:technology:f243fb2d073774e81c7815247cb3013794e6225df3cbe3769cee8c6cefaca777',\n", + " 'reference_id': 'f243fb2d073774e81c7815247cb3013794e6225df3cbe3769cee8c6cefaca777',\n", " 'route_name': 'technology',\n", - " 'reference': 'tell me about the newest gadgets'}]" + " 'reference': 'latest AI trends'}]" ] }, "execution_count": 17, @@ -636,7 +640,14 @@ { "cell_type": "code", "execution_count": 18, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:12.525623Z", + "iopub.status.busy": "2026-02-16T15:16:12.525560Z", + "iopub.status.idle": "2026-02-16T15:16:12.531244Z", + "shell.execute_reply": "2026-02-16T15:16:12.530894Z" + } + }, "outputs": [ { "data": { @@ -658,7 +669,14 @@ { "cell_type": "code", "execution_count": 19, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:12.532220Z", + "iopub.status.busy": "2026-02-16T15:16:12.532147Z", + "iopub.status.idle": "2026-02-16T15:16:12.535588Z", + "shell.execute_reply": "2026-02-16T15:16:12.535264Z" + } + }, "outputs": [ { "data": { @@ -687,7 +705,14 @@ { "cell_type": "code", "execution_count": 20, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:12.536554Z", + "iopub.status.busy": "2026-02-16T15:16:12.536490Z", + "iopub.status.idle": "2026-02-16T15:16:12.539808Z", + "shell.execute_reply": "2026-02-16T15:16:12.539424Z" + } + }, "outputs": [], "source": [ "# Use clear to flush all routes from the index\n", @@ -697,12 +722,32 @@ { "cell_type": "code", "execution_count": 21, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:12.540670Z", + "iopub.status.busy": "2026-02-16T15:16:12.540604Z", + "iopub.status.idle": "2026-02-16T15:16:12.542528Z", + "shell.execute_reply": "2026-02-16T15:16:12.542225Z" + } + }, "outputs": [], "source": [ "# Use delete to clear the index and remove it completely\n", "router.delete()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand semantic routing, explore these related guides:\n", + "\n", + "- [Manage LLM Message History](07_message_history.ipynb) - Store and retrieve conversation history\n", + "- [Cache LLM Responses](03_llmcache.ipynb) - Reduce API costs with semantic caching\n", + "- [Query and Filter Data](02_complex_filtering.ipynb) - Learn more about filter expressions" + ] } ], "metadata": { @@ -722,8 +767,7 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" - }, - "orig_nbformat": 4 + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/docs/user_guide/09_svs_vamana.ipynb b/docs/user_guide/09_svs_vamana.ipynb index 1fb4c482..9df1fc88 100644 --- a/docs/user_guide/09_svs_vamana.ipynb +++ b/docs/user_guide/09_svs_vamana.ipynb @@ -5,14 +5,25 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# SVS-VAMANA Vector Search\n", + "# Optimize Indexes with SVS-VAMANA\n", "\n", - "In this notebook, we will explore SVS-VAMANA (Scalable Vector Search with VAMANA graph algorithm), a graph-based vector search algorithm that is optimized to work with compression methods to reduce memory usage. It combines the Vamana graph algorithm with advanced compression techniques (LVQ and LeanVec) and is optimized for Intel hardware.\n", + "This guide covers SVS-VAMANA (Scalable Vector Search with VAMANA graph algorithm), a graph-based vector search algorithm optimized for compression methods to reduce memory usage. It combines the Vamana graph algorithm with advanced compression techniques (LVQ and LeanVec) and is optimized for Intel hardware.\n", "\n", - "**How it works**\n", + "## Prerequisites\n", + "\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance with Redis >= 8.2.0 and RediSearch >= 2.8.10 ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", "\n", - "Vamana builds a single-layer proximity graph and prunes edges during construction based on tunable parameters, similar to HNSW but with a simpler structure. The compression methods apply per-vector normalization and scalar quantization, learning parameters directly from the data to enable fast, on-the-fly distance computations with SIMD-optimized layout Vector quantization and compression.\n", + "> **Note:** SVS-VAMANA only supports FLOAT16 and FLOAT32 datatypes.\n", "\n", + "## What You'll Learn\n", + "\n", + "By the end of this guide, you will be able to:\n", + "- Understand when to use SVS-VAMANA for vector search\n", + "- Configure compression settings for memory optimization\n", + "- Use the CompressionAdvisor for automatic optimization\n", + "- Trade off between memory usage, speed, and search quality\n", "\n", "**SVS-VAMANA offers:**\n", "- **Fast approximate nearest neighbor search** using graph-based algorithms\n", @@ -24,47 +35,20 @@ "- Large datasets where memory is expensive\n", "- Cloud deployments with memory-based pricing\n", "- When 90-95% recall is acceptable\n", - "- High-dimensional vectors (>1024 dims) with LeanVec compression\n", - "\n", - "\n", - "\n", - "**Table of Contents**\n", - "\n", - "1. [Prerequisites](#Prerequisites)\n", - "2. [Quick Start with CompressionAdvisor](#Quick-Start-with-CompressionAdvisor)\n", - "3. [Creating an SVS-VAMANA Index](#Creating-an-SVS-VAMANA-Index)\n", - "4. [Loading Sample Data](#Loading-Sample-Data)\n", - "5. [Performing Vector Searches](#Performing-Vector-Searches)\n", - "6. [Understanding Compression Types](#Understanding-Compression-Types)\n", - "7. [Hybrid Queries with SVS-VAMANA](#Hybrid-Queries-with-SVS-VAMANA)\n", - "8. [Performance Monitoring](#Performance-Monitoring)\n", - "9. [Manual Configuration (Advanced)](#Manual-Configuration-(Advanced))\n", - "10. [Best Practices and Tips](#Best-Practices-and-Tips)\n", - "11. [Cleanup](#Cleanup)\n", - "\n", - "---\n", - "\n", - "## Prerequisites\n", - "\n", - "Before running this notebook, ensure you have:\n", - "1. Installed `redisvl` and have that environment active for this notebook\n", - "2. A running Redis Stack instance with:\n", - " - Redis >= 8.2.0\n", - " - RediSearch >= 2.8.10\n", - "\n", - "For example, you can run Redis Stack locally with Docker:\n", - "\n", - "```bash\n", - "docker run -d -p 6379:6379 -p 8001:8001 redis/redis-stack:latest\n", - "```\n", - "\n", - "**Note:** SVS-VAMANA only supports FLOAT16 and FLOAT32 datatypes." + "- High-dimensional vectors (>1024 dims) with LeanVec compression" ] }, { "cell_type": "code", "execution_count": 1, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:08.516843Z", + "iopub.status.busy": "2026-02-16T15:27:08.516710Z", + "iopub.status.idle": "2026-02-16T15:27:08.662568Z", + "shell.execute_reply": "2026-02-16T15:27:08.662110Z" + } + }, "outputs": [], "source": [ "# Import necessary modules\n", @@ -81,7 +65,14 @@ { "cell_type": "code", "execution_count": 2, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:08.663886Z", + "iopub.status.busy": "2026-02-16T15:27:08.663772Z", + "iopub.status.idle": "2026-02-16T15:27:08.665647Z", + "shell.execute_reply": "2026-02-16T15:27:08.665184Z" + } + }, "outputs": [], "source": [ "# Redis connection\n", @@ -100,7 +91,14 @@ { "cell_type": "code", "execution_count": 3, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:08.666685Z", + "iopub.status.busy": "2026-02-16T15:27:08.666608Z", + "iopub.status.idle": "2026-02-16T15:27:08.668970Z", + "shell.execute_reply": "2026-02-16T15:27:08.668585Z" + } + }, "outputs": [ { "name": "stdout", @@ -109,10 +107,10 @@ "Recommended Configuration:\n", " algorithm: svs-vamana\n", " datatype: float16\n", - " graph_max_degree: 64\n", - " construction_window_size: 300\n", " compression: LeanVec4x8\n", " reduce: 512\n", + " graph_max_degree: 64\n", + " construction_window_size: 300\n", " search_window_size: 30\n", "\n", "Estimated Memory Savings: 81.2%\n" @@ -129,14 +127,14 @@ ")\n", "\n", "print(\"Recommended Configuration:\")\n", - "for key, value in config.items():\n", + "for key, value in config.model_dump().items():\n", " print(f\" {key}: {value}\")\n", "\n", "# Estimate memory savings\n", "savings = CompressionAdvisor.estimate_memory_savings(\n", - " config[\"compression\"],\n", + " config.compression,\n", " dims,\n", - " config.get(\"reduce\")\n", + " config.reduce\n", ")\n", "print(f\"\\nEstimated Memory Savings: {savings}%\")" ] @@ -153,13 +151,20 @@ { "cell_type": "code", "execution_count": 4, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:08.685097Z", + "iopub.status.busy": "2026-02-16T15:27:08.684994Z", + "iopub.status.idle": "2026-02-16T15:27:08.692332Z", + "shell.execute_reply": "2026-02-16T15:27:08.692006Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\u2705 Created SVS-VAMANA index: svs_demo\n", + "โœ… Created SVS-VAMANA index: svs_demo\n", " Algorithm: svs-vamana\n", " Compression: LeanVec4x8\n", " Dimensions: 1024\n", @@ -169,6 +174,7 @@ ], "source": [ "# Create index schema with recommended SVS-VAMANA configuration\n", + "config_dict = config.model_dump(exclude_none=True)\n", "schema = {\n", " \"index\": {\n", " \"name\": \"svs_demo\",\n", @@ -182,7 +188,7 @@ " \"type\": \"vector\",\n", " \"attrs\": {\n", " \"dims\": dims,\n", - " **config, # Use the recommended configuration\n", + " **config_dict, # Use the recommended configuration\n", " \"distance_metric\": \"cosine\"\n", " }\n", " }\n", @@ -193,12 +199,12 @@ "index = SearchIndex.from_dict(schema, redis_url=REDIS_URL)\n", "index.create(overwrite=True)\n", "\n", - "print(f\"\u2705 Created SVS-VAMANA index: {index.name}\")\n", - "print(f\" Algorithm: {config['algorithm']}\")\n", - "print(f\" Compression: {config['compression']}\")\n", + "print(f\"โœ… Created SVS-VAMANA index: {index.name}\")\n", + "print(f\" Algorithm: {config.algorithm}\")\n", + "print(f\" Compression: {config.compression}\")\n", "print(f\" Dimensions: {dims}\")\n", - "if 'reduce' in config:\n", - " print(f\" Reduced to: {config['reduce']} dimensions\")" + "if config.reduce is not None:\n", + " print(f\" Reduced to: {config.reduce} dimensions\")" ] }, { @@ -213,14 +219,21 @@ { "cell_type": "code", "execution_count": 5, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:08.693416Z", + "iopub.status.busy": "2026-02-16T15:27:08.693331Z", + "iopub.status.idle": "2026-02-16T15:27:10.705486Z", + "shell.execute_reply": "2026-02-16T15:27:10.704878Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Creating vectors with 512 dimensions (reduced from 1024 if applicable)\n", - "\u2705 Loaded 10 documents into the index\n", + "โœ… Loaded 10 documents into the index\n", " Index now contains 0 documents\n" ] } @@ -245,7 +258,7 @@ "data_to_load = []\n", "\n", "# Use reduced dimensions if LeanVec compression is applied\n", - "vector_dims = config.get(\"reduce\", dims)\n", + "vector_dims = config.reduce if config.reduce is not None else dims\n", "print(f\"Creating vectors with {vector_dims} dimensions (reduced from {dims} if applicable)\")\n", "\n", "for i, doc in enumerate(sample_documents):\n", @@ -257,18 +270,18 @@ " base_vector[0] += category_offset\n", " \n", " # Convert to the datatype specified in config\n", - " if config[\"datatype\"] == \"float16\":\n", + " if config.datatype == \"float16\":\n", " base_vector = base_vector.astype(np.float16)\n", " \n", " data_to_load.append({\n", " \"content\": doc[\"content\"],\n", " \"category\": doc[\"category\"],\n", - " \"embedding\": array_to_buffer(base_vector, dtype=config[\"datatype\"])\n", + " \"embedding\": array_to_buffer(base_vector, dtype=config.datatype)\n", " })\n", "\n", "# Load data into the index\n", "index.load(data_to_load)\n", - "print(f\"\u2705 Loaded {len(data_to_load)} documents into the index\")\n", + "print(f\"โœ… Loaded {len(data_to_load)} documents into the index\")\n", "\n", "# Wait a moment for indexing to complete\n", "import time\n", @@ -291,13 +304,20 @@ { "cell_type": "code", "execution_count": 6, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:10.707056Z", + "iopub.status.busy": "2026-02-16T15:27:10.706927Z", + "iopub.status.idle": "2026-02-16T15:27:10.712816Z", + "shell.execute_reply": "2026-02-16T15:27:10.712435Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\ud83d\udd0d Vector Search Results:\n", + "๐Ÿ” Vector Search Results:\n", "==================================================\n" ] } @@ -305,8 +325,8 @@ "source": [ "# Create a query vector (in practice, this would be an embedding of your query text)\n", "# Important: Query vector must match the index datatype and dimensions\n", - "vector_dims = config.get(\"reduce\", dims)\n", - "if config[\"datatype\"] == \"float16\":\n", + "vector_dims = config.reduce if config.reduce is not None else dims\n", + "if config.datatype == \"float16\":\n", " query_vector = np.random.random(vector_dims).astype(np.float16)\n", "else:\n", " query_vector = np.random.random(vector_dims).astype(np.float32)\n", @@ -321,7 +341,7 @@ "\n", "results = index.query(query)\n", "\n", - "print(\"\ud83d\udd0d Vector Search Results:\")\n", + "print(\"๐Ÿ” Vector Search Results:\")\n", "print(\"=\" * 50)\n", "for i, result in enumerate(results, 1):\n", " distance = result.get('vector_distance', 'N/A')\n", @@ -350,9 +370,30 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:10.714222Z", + "iopub.status.busy": "2026-02-16T15:27:10.714138Z", + "iopub.status.idle": "2026-02-16T15:27:10.719627Z", + "shell.execute_reply": "2026-02-16T15:27:10.719252Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "๐Ÿ” Basic Query (default parameters):\n", + "Found 0 results\n", + "\n", + "๐ŸŽฏ Tuned Query (higher recall parameters):\n", + "Found 0 results\n", + "\n", + "Note: Higher search_window_size improves recall but may increase latency\n" + ] + } + ], "source": [ "# Example 1: Basic query with default parameters\n", "basic_query = VectorQuery(\n", @@ -362,7 +403,7 @@ " num_results=5\n", ")\n", "\n", - "print(\"\ud83d\udd0d Basic Query (default parameters):\")\n", + "print(\"๐Ÿ” Basic Query (default parameters):\")\n", "results = index.query(basic_query)\n", "print(f\"Found {len(results)} results\\n\")\n", "\n", @@ -377,7 +418,7 @@ " search_buffer_capacity=50 # Larger buffer capacity\n", ")\n", "\n", - "print(\"\ud83c\udfaf Tuned Query (higher recall parameters):\")\n", + "print(\"๐ŸŽฏ Tuned Query (higher recall parameters):\")\n", "results = index.query(tuned_query)\n", "print(f\"Found {len(results)} results\")\n", "print(\"\\nNote: Higher search_window_size improves recall but may increase latency\")" @@ -387,32 +428,47 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Runtime Parameters with Range Queries\n", + "### Range Queries with SVS-VAMANA\n", "\n", - "Runtime parameters are also useful for range queries, where you want to find all vectors within a certain distance threshold:" + "Range queries find all vectors within a certain distance threshold. For range queries, you can use the `epsilon` parameter to control the approximation factor:" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:10.720970Z", + "iopub.status.busy": "2026-02-16T15:27:10.720877Z", + "iopub.status.idle": "2026-02-16T15:27:10.725098Z", + "shell.execute_reply": "2026-02-16T15:27:10.724687Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "๐ŸŽฏ Range Query Results: Found 0 vectors within distance threshold 0.3\n" + ] + } + ], "source": [ "from redisvl.query import VectorRangeQuery\n", "\n", - "# Range query with runtime parameters\n", + "# Range query with epsilon parameter for approximation control\n", + "# Note: search_window_size and use_search_history are only supported for KNN queries (VectorQuery),\n", + "# not for range queries (VectorRangeQuery). Use epsilon to control the approximation factor.\n", "range_query = VectorRangeQuery(\n", " vector=query_vector.tolist(),\n", " vector_field_name=\"embedding\",\n", " return_fields=[\"content\", \"category\"],\n", " distance_threshold=0.3,\n", - " epsilon=0.05, # Approximation factor\n", - " search_window_size=30, # Search window size\n", - " use_search_history='AUTO' # Automatic history management\n", + " epsilon=0.05, # Approximation factor for range queries\n", ")\n", "\n", "results = index.query(range_query)\n", - "print(f\"\ud83c\udfaf Range Query Results: Found {len(results)} vectors within distance threshold 0.3\")\n", + "print(f\"๐ŸŽฏ Range Query Results: Found {len(results)} vectors within distance threshold 0.3\")\n", "for i, result in enumerate(results[:3], 1):\n", " distance = result.get('vector_distance', 'N/A')\n", " print(f\"{i}. {result['content'][:50]}... (distance: {distance})\")" @@ -429,8 +485,15 @@ }, { "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:10.726169Z", + "iopub.status.busy": "2026-02-16T15:27:10.726089Z", + "iopub.status.idle": "2026-02-16T15:27:10.728818Z", + "shell.execute_reply": "2026-02-16T15:27:10.728466Z" + } + }, "outputs": [ { "name": "stdout", @@ -442,21 +505,21 @@ "MEMORY Priority:\n", " Compression: LeanVec4x8\n", " Datatype: float16\n", - " Dimensionality reduction: 1024 \u2192 512\n", + " Dimensionality reduction: 1024 โ†’ 512\n", " Search window size: 20\n", " Memory savings: 81.2%\n", "\n", "SPEED Priority:\n", " Compression: LeanVec4x8\n", " Datatype: float16\n", - " Dimensionality reduction: 1024 \u2192 256\n", + " Dimensionality reduction: 1024 โ†’ 256\n", " Search window size: 40\n", " Memory savings: 90.6%\n", "\n", "BALANCED Priority:\n", " Compression: LeanVec4x8\n", " Datatype: float16\n", - " Dimensionality reduction: 1024 \u2192 512\n", + " Dimensionality reduction: 1024 โ†’ 512\n", " Search window size: 30\n", " Memory savings: 81.2%\n" ] @@ -471,17 +534,17 @@ "for priority in priorities:\n", " config = CompressionAdvisor.recommend(dims=dims, priority=priority)\n", " savings = CompressionAdvisor.estimate_memory_savings(\n", - " config[\"compression\"],\n", + " config.compression,\n", " dims,\n", - " config.get(\"reduce\")\n", + " config.reduce\n", " )\n", " \n", " print(f\"\\n{priority.upper()} Priority:\")\n", - " print(f\" Compression: {config['compression']}\")\n", - " print(f\" Datatype: {config['datatype']}\")\n", - " if \"reduce\" in config:\n", - " print(f\" Dimensionality reduction: {dims} \u2192 {config['reduce']}\")\n", - " print(f\" Search window size: {config['search_window_size']}\")\n", + " print(f\" Compression: {config.compression}\")\n", + " print(f\" Datatype: {config.datatype}\")\n", + " if config.reduce is not None:\n", + " print(f\" Dimensionality reduction: {dims} โ†’ {config.reduce}\")\n", + " print(f\" Search window size: {config.search_window_size}\")\n", " print(f\" Memory savings: {savings}%\")" ] }, @@ -508,8 +571,15 @@ }, { "cell_type": "code", - "execution_count": 8, - "metadata": {}, + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:10.729978Z", + "iopub.status.busy": "2026-02-16T15:27:10.729904Z", + "iopub.status.idle": "2026-02-16T15:27:10.732575Z", + "shell.execute_reply": "2026-02-16T15:27:10.732111Z" + } + }, "outputs": [ { "name": "stdout", @@ -539,13 +609,13 @@ "for dims in test_dimensions:\n", " config = CompressionAdvisor.recommend(dims=dims, priority=\"balanced\")\n", " savings = CompressionAdvisor.estimate_memory_savings(\n", - " config[\"compression\"],\n", + " config.compression,\n", " dims,\n", - " config.get(\"reduce\")\n", + " config.reduce\n", " )\n", " \n", " strategy = \"LeanVec\" if dims >= 1024 else \"LVQ\"\n", - " print(f\"{dims:<6} {config['compression']:<12} {savings:>6.1f}% {strategy}\")" + " print(f\"{dims:<6} {config.compression:<12} {savings:>6.1f}% {strategy}\")" ] }, { @@ -559,14 +629,21 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": {}, + "execution_count": 11, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:10.733633Z", + "iopub.status.busy": "2026-02-16T15:27:10.733554Z", + "iopub.status.idle": "2026-02-16T15:27:10.737224Z", + "shell.execute_reply": "2026-02-16T15:27:10.736881Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\ud83d\udd0d Hybrid Search Results (Technology category only):\n", + "๐Ÿ” Hybrid Search Results (Technology category only):\n", "=======================================================\n" ] } @@ -585,7 +662,7 @@ "\n", "filtered_results = index.query(hybrid_query)\n", "\n", - "print(\"\ud83d\udd0d Hybrid Search Results (Technology category only):\")\n", + "print(\"๐Ÿ” Hybrid Search Results (Technology category only):\")\n", "print(\"=\" * 55)\n", "for i, result in enumerate(filtered_results, 1):\n", " distance = result.get('vector_distance', 'N/A')\n", @@ -605,18 +682,25 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": {}, + "execution_count": 12, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:10.738344Z", + "iopub.status.busy": "2026-02-16T15:27:10.738267Z", + "iopub.status.idle": "2026-02-16T15:27:10.742087Z", + "shell.execute_reply": "2026-02-16T15:27:10.741777Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\ud83d\udcca Index Statistics:\n", + "๐Ÿ“Š Index Statistics:\n", "==============================\n", "Documents: 0\n", "Vector index size: 0.00 MB\n", - "Total indexing time: 1.58 seconds\n", + "Total indexing time: 0.27 seconds\n", "Memory efficiency calculation requires documents and vector index size > 0\n" ] } @@ -625,7 +709,7 @@ "# Get detailed index information\n", "info = index.info()\n", "\n", - "print(\"\ud83d\udcca Index Statistics:\")\n", + "print(\"๐Ÿ“Š Index Statistics:\")\n", "print(\"=\" * 30)\n", "print(f\"Documents: {info.get('num_docs', 0)}\")\n", "\n", @@ -664,15 +748,22 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Manual Configuration (Advanced)\n", + "## Advanced Manual Configuration\n", "\n", "For advanced users who want full control over SVS-VAMANA parameters, you can manually configure the algorithm instead of using CompressionAdvisor." ] }, { "cell_type": "code", - "execution_count": 11, - "metadata": {}, + "execution_count": 13, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:10.743314Z", + "iopub.status.busy": "2026-02-16T15:27:10.743244Z", + "iopub.status.idle": "2026-02-16T15:27:10.746070Z", + "shell.execute_reply": "2026-02-16T15:27:10.745719Z" + } + }, "outputs": [ { "name": "stdout", @@ -755,7 +846,7 @@ "\n", "**Index-time parameters** (set during index creation):\n", "- **Start with CompressionAdvisor** recommendations for compression and datatype\n", - "- **Use LeanVec** for high-dimensional vectors (\u22651024 dims)\n", + "- **Use LeanVec** for high-dimensional vectors (โ‰ฅ1024 dims)\n", "- **Use LVQ** for lower-dimensional vectors (<1024 dims)\n", "- **graph_max_degree**: Higher values improve recall but increase memory usage\n", "- **construction_window_size**: Higher values improve index quality but slow down build time\n", @@ -773,6 +864,19 @@ "- **Recall quality** may decrease with more aggressive compression or lower search_window_size" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand SVS-VAMANA optimization, explore these related guides:\n", + "\n", + "- [Getting Started](01_getting_started.ipynb) - Learn the basics of RedisVL indexes\n", + "- [Choose a Storage Type](05_hash_vs_json.ipynb) - Understand Hash vs JSON storage\n", + "- [Query and Filter Data](02_complex_filtering.ipynb) - Apply filters to narrow down search results" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -784,17 +888,16 @@ }, { "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Cleaned up svs_demo index\n" - ] + "execution_count": 14, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:27:10.747227Z", + "iopub.status.busy": "2026-02-16T15:27:10.747147Z", + "iopub.status.idle": "2026-02-16T15:27:10.749551Z", + "shell.execute_reply": "2026-02-16T15:27:10.749210Z" } - ], + }, + "outputs": [], "source": [ "# Clean up demo indices\n", "try:\n", @@ -807,7 +910,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": ".venv", "language": "python", "name": "python3" }, @@ -821,9 +924,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.6" + "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} diff --git a/docs/user_guide/10_embeddings_cache.ipynb b/docs/user_guide/10_embeddings_cache.ipynb index d5cae6a9..e74afc02 100644 --- a/docs/user_guide/10_embeddings_cache.ipynb +++ b/docs/user_guide/10_embeddings_cache.ipynb @@ -4,15 +4,23 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Caching Embeddings\n", + "# Cache Embeddings\n", "\n", - "RedisVL provides an `EmbeddingsCache` that makes it easy to store and retrieve embedding vectors with their associated text and metadata. This cache is particularly useful for applications that frequently compute the same embeddings, enabling you to:\n", + "RedisVL provides an `EmbeddingsCache` that stores and retrieves embedding vectors with their associated text and metadata. This cache is useful for applications that frequently compute the same embeddings.\n", "\n", - "- Reduce computational costs by reusing previously computed embeddings\n", - "- Decrease latency in applications that rely on embeddings\n", - "- Store additional metadata alongside embeddings for richer applications\n", + "## Prerequisites\n", "\n", - "This notebook will show you how to use the `EmbeddingsCache` effectively in your applications." + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", + "\n", + "## What You'll Learn\n", + "\n", + "By the end of this guide, you will be able to:\n", + "- Store and retrieve embedding vectors with the `EmbeddingsCache`\n", + "- Use batch operations for efficient processing\n", + "- Configure time-to-live (TTL) for cache entries\n", + "- Integrate the cache with vectorizers for automatic caching" ] }, { @@ -25,10 +33,17 @@ ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:19.325480Z", + "iopub.status.busy": "2026-02-16T15:16:19.325355Z", + "iopub.status.idle": "2026-02-16T15:16:19.497336Z", + "shell.execute_reply": "2026-02-16T15:16:19.496833Z" + } + }, "outputs": [], - "execution_count": null, "source": [ "import os\n", "import time\n", @@ -43,15 +58,24 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "Let's create a vectorizer to generate embeddings for our texts:" + "metadata": {}, + "source": [ + "Let's create a vectorizer to generate embeddings for our texts:" + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:19.498568Z", + "iopub.status.busy": "2026-02-16T15:16:19.498455Z", + "iopub.status.idle": "2026-02-16T15:16:39.539388Z", + "shell.execute_reply": "2026-02-16T15:16:39.538920Z" + } + }, + "outputs": [], "source": [ "# Initialize the vectorizer\n", "vectorizer = HFTextVectorizer(\n", @@ -61,8 +85,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## Initializing the EmbeddingsCache\n", "\n", @@ -70,10 +94,17 @@ ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:39.541131Z", + "iopub.status.busy": "2026-02-16T15:16:39.540796Z", + "iopub.status.idle": "2026-02-16T15:16:39.543018Z", + "shell.execute_reply": "2026-02-16T15:16:39.542676Z" + } + }, "outputs": [], - "execution_count": null, "source": [ "# Initialize the embeddings cache\n", "cache = EmbeddingsCache(\n", @@ -84,8 +115,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## Basic Usage\n", "\n", @@ -100,10 +131,25 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:39.544167Z", + "iopub.status.busy": "2026-02-16T15:16:39.544082Z", + "iopub.status.idle": "2026-02-16T15:16:39.645727Z", + "shell.execute_reply": "2026-02-16T15:16:39.645251Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Stored with key: embedcache:909f...\n" + ] + } + ], "source": [ "# Text to embed\n", "text = \"What is machine learning?\"\n", @@ -127,8 +173,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### Retrieving Embeddings\n", "\n", @@ -136,10 +182,28 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:39.646935Z", + "iopub.status.busy": "2026-02-16T15:16:39.646859Z", + "iopub.status.idle": "2026-02-16T15:16:39.649824Z", + "shell.execute_reply": "2026-02-16T15:16:39.649395Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found in cache: What is machine learning?\n", + "Model: redis/langcache-embed-v1\n", + "Metadata: {'category': 'ai', 'source': 'user_query'}\n", + "Embedding shape: (768,)\n" + ] + } + ], "source": [ "# Retrieve from cache\n", "\n", @@ -153,8 +217,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### Checking Existence\n", "\n", @@ -162,10 +226,26 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:39.650887Z", + "iopub.status.busy": "2026-02-16T15:16:39.650822Z", + "iopub.status.idle": "2026-02-16T15:16:39.653655Z", + "shell.execute_reply": "2026-02-16T15:16:39.653320Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "First query exists in cache: True\n", + "New query exists in cache: False\n" + ] + } + ], "source": [ "# Check if existing text is in cache\n", "exists = cache.exists(content=text, model_name=model_name)\n", @@ -178,8 +258,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### Removing Entries\n", "\n", @@ -187,10 +267,25 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:39.654662Z", + "iopub.status.busy": "2026-02-16T15:16:39.654585Z", + "iopub.status.idle": "2026-02-16T15:16:39.657562Z", + "shell.execute_reply": "2026-02-16T15:16:39.657237Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "After dropping: False\n" + ] + } + ], "source": [ "# Remove from cache\n", "cache.drop(content=text, model_name=model_name)\n", @@ -201,8 +296,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## Advanced Usage\n", "\n", @@ -212,10 +307,27 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:39.658559Z", + "iopub.status.busy": "2026-02-16T15:16:39.658493Z", + "iopub.status.idle": "2026-02-16T15:16:39.663650Z", + "shell.execute_reply": "2026-02-16T15:16:39.663234Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Stored with key: embedcache:909f...\n", + "Exists by key: True\n", + "Retrieved by key: What is machine learning?\n" + ] + } + ], "source": [ "# Store an entry again\n", "key = cache.set(\n", @@ -239,8 +351,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### Batch Operations\n", "\n", @@ -248,10 +360,27 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:39.664643Z", + "iopub.status.busy": "2026-02-16T15:16:39.664566Z", + "iopub.status.idle": "2026-02-16T15:16:39.846249Z", + "shell.execute_reply": "2026-02-16T15:16:39.845861Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Stored 3 embeddings with batch operation\n", + "All embeddings exist: True\n", + "Retrieved 3 embeddings in one operation\n" + ] + } + ], "source": [ "# Create multiple embeddings\n", "texts = [\n", @@ -305,8 +434,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Batch operations are particularly beneficial when working with large numbers of embeddings. They provide the same functionality as individual operations but with better performance by reducing network roundtrips.\n", "\n", @@ -314,8 +443,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### Working with TTL (Time-To-Live)\n", "\n", @@ -323,10 +452,26 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:39.847577Z", + "iopub.status.busy": "2026-02-16T15:16:39.847488Z", + "iopub.status.idle": "2026-02-16T15:16:45.861636Z", + "shell.execute_reply": "2026-02-16T15:16:45.860946Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Immediately after setting: True\n", + "After waiting: False\n" + ] + } + ], "source": [ "# Create a cache with a default 5-second TTL\n", "ttl_cache = EmbeddingsCache(\n", @@ -355,15 +500,33 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "You can also override the default TTL for individual entries:" + "metadata": {}, + "source": [ + "You can also override the default TTL for individual entries:" + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 11, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:45.863384Z", + "iopub.status.busy": "2026-02-16T15:16:45.863262Z", + "iopub.status.idle": "2026-02-16T15:16:47.879707Z", + "shell.execute_reply": "2026-02-16T15:16:47.879056Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Entry with custom TTL after 2 seconds: False\n", + "Entry with default TTL after 2 seconds: True\n" + ] + } + ], "source": [ "# Store an entry with a custom 1-second TTL\n", "key1 = ttl_cache.set(\n", @@ -396,8 +559,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## Async Support\n", "\n", @@ -405,10 +568,26 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 12, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:47.881309Z", + "iopub.status.busy": "2026-02-16T15:16:47.881184Z", + "iopub.status.idle": "2026-02-16T15:16:47.890731Z", + "shell.execute_reply": "2026-02-16T15:16:47.890278Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Async set successful? True\n", + "Async get successful? True\n" + ] + } + ], "source": [ "async def async_cache_demo():\n", " # Store an entry asynchronously\n", @@ -436,8 +615,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## Real-World Example\n", "\n", @@ -445,10 +624,40 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 13, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:16:47.892119Z", + "iopub.status.busy": "2026-02-16T15:16:47.892011Z", + "iopub.status.idle": "2026-02-16T15:17:02.151560Z", + "shell.execute_reply": "2026-02-16T15:17:02.151068Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "You try to use a model that was created with version 4.1.0, however, your version is 3.4.1. This might cause unexpected behavior or errors. In that case, try to update to the latest version.\n", + "\n", + "\n", + "\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Statistics:\n", + "Total queries: 5\n", + "Cache hits: 2\n", + "Cache misses: 3\n", + "Cache hit rate: 40.0%\n" + ] + } + ], "source": [ "# Create a fresh cache for this example\n", "example_cache = EmbeddingsCache(\n", @@ -503,8 +712,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## Performance Benchmark\n", "\n", @@ -512,10 +721,36 @@ ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, + "execution_count": 14, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:17:02.152981Z", + "iopub.status.busy": "2026-02-16T15:17:02.152880Z", + "iopub.status.idle": "2026-02-16T15:17:02.579670Z", + "shell.execute_reply": "2026-02-16T15:17:02.579267Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Benchmarking without caching:\n", + "Time taken without caching: 0.4564 seconds\n", + "Average time per embedding: 0.0456 seconds\n", + "\n", + "Benchmarking with caching:\n", + "Time taken with caching: 0.0619 seconds\n", + "Average time per embedding: 0.0062 seconds\n", + "\n", + "Performance comparison:\n", + "Speedup with caching: 7.37x faster\n", + "Time saved: 0.3945 seconds (86.4%)\n", + "Latency reduction: 0.0395 seconds per query\n" + ] + } + ], "source": [ "# Text to use for benchmarking\n", "benchmark_text = \"This is a benchmark text to measure the performance of embedding caching.\"\n", @@ -559,8 +794,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## Common Use Cases for Embedding Caching\n", "\n", @@ -575,8 +810,8 @@ ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## Cleanup\n", "\n", @@ -584,10 +819,17 @@ ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": 15, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:17:02.580974Z", + "iopub.status.busy": "2026-02-16T15:17:02.580895Z", + "iopub.status.idle": "2026-02-16T15:17:02.584965Z", + "shell.execute_reply": "2026-02-16T15:17:02.584566Z" + } + }, "outputs": [], - "execution_count": null, "source": [ "# Clean up all caches\n", "cache.clear()\n", @@ -596,6 +838,19 @@ "benchmark_cache.clear()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand embeddings caching, explore these related guides:\n", + "\n", + "- [Cache LLM Responses](03_llmcache.ipynb) - Cache full LLM responses based on semantic similarity\n", + "- [Create Embeddings with Vectorizers](04_vectorizers.ipynb) - Learn about different embedding providers\n", + "- [Manage LLM Message History](07_message_history.ipynb) - Store and retrieve conversation history" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/docs/user_guide/11_advanced_queries.ipynb b/docs/user_guide/11_advanced_queries.ipynb index 9ff55799..fc9c3442 100644 --- a/docs/user_guide/11_advanced_queries.ipynb +++ b/docs/user_guide/11_advanced_queries.ipynb @@ -4,20 +4,30 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Advanced Query Types\n", + "# Use Advanced Query Types\n", "\n", - "In this notebook, we will explore advanced query types available in RedisVL:\n", + "This guide covers advanced query types available in RedisVL:\n", "\n", "1. **`TextQuery`**: Full text search with advanced scoring\n", "2. **`AggregateHybridQuery` and `HybridQuery`**: 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", + "These query types enable sophisticated search applications that go beyond simple vector similarity search.\n", "\n", - "Prerequisites:\n", - "- Ensure `redisvl` is installed in your Python environment.\n", - "- Have a running instance of [Redis Stack](https://redis.io/docs/install/install-stack/) or [Redis Cloud](https://redis.io/cloud).\n", - "- For `HybridQuery`, we will need Redis >= 8.4.0 and redis-py >= 7.1.0.\n" + "## Prerequisites\n", + "\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL: `pip install redisvl`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", + "- For `HybridQuery`: Redis >= 8.4.0 and redis-py >= 7.1.0\n", + "\n", + "## What You'll Learn\n", + "\n", + "By the end of this guide, you will be able to:\n", + "- Perform full-text search with `TextQuery` and advanced scoring options\n", + "- Combine text and vector search using `HybridQuery` and `AggregateHybridQuery`\n", + "- Search across multiple vector fields with `MultiVectorQuery`\n", + "- Configure custom stopwords for text search" ] }, { @@ -31,18 +41,20 @@ }, { "cell_type": "code", + "execution_count": 1, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:12.222169Z", - "iopub.status.busy": "2025-11-21T00:42:12.222058Z", - "iopub.status.idle": "2025-11-21T00:42:12.301776Z", - "shell.execute_reply": "2025-11-21T00:42:12.301163Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:43.615445Z", "start_time": "2025-12-15T09:27:43.522493Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:07.111759Z", + "iopub.status.busy": "2026-02-16T15:17:07.111643Z", + "iopub.status.idle": "2026-02-16T15:17:07.193336Z", + "shell.execute_reply": "2026-02-16T15:17:07.192860Z" } }, + "outputs": [], "source": [ "import numpy as np\n", "from jupyterutils import result_print\n", @@ -110,9 +122,7 @@ " 'image_embedding': np.array([0.2, 0.8], dtype=np.float32).tobytes(),\n", " },\n", "]" - ], - "outputs": [], - "execution_count": 1 + ] }, { "cell_type": "markdown", @@ -129,18 +139,20 @@ }, { "cell_type": "code", + "execution_count": 2, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:12.303593Z", - "iopub.status.busy": "2025-11-21T00:42:12.303450Z", - "iopub.status.idle": "2025-11-21T00:42:12.305709Z", - "shell.execute_reply": "2025-11-21T00:42:12.305407Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:43.620369Z", "start_time": "2025-12-15T09:27:43.615922Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:07.194739Z", + "iopub.status.busy": "2026-02-16T15:17:07.194621Z", + "iopub.status.idle": "2026-02-16T15:17:07.197015Z", + "shell.execute_reply": "2026-02-16T15:17:07.196608Z" } }, + "outputs": [], "source": [ "schema = {\n", " \"index\": {\n", @@ -177,9 +189,7 @@ " }\n", " ],\n", "}" - ], - "outputs": [], - "execution_count": 2 + ] }, { "cell_type": "markdown", @@ -190,18 +200,28 @@ }, { "cell_type": "code", + "execution_count": 3, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:12.306952Z", - "iopub.status.busy": "2025-11-21T00:42:12.306869Z", - "iopub.status.idle": "2025-11-21T00:42:12.416481Z", - "shell.execute_reply": "2025-11-21T00:42:12.415926Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:43.720506Z", "start_time": "2025-12-15T09:27:43.620716Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:07.198084Z", + "iopub.status.busy": "2026-02-16T15:17:07.198011Z", + "iopub.status.idle": "2026-02-16T15:17:07.293058Z", + "shell.execute_reply": "2026-02-16T15:17:07.292647Z" } }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loaded 6 products into the index\n" + ] + } + ], "source": [ "from redisvl.index import SearchIndex\n", "\n", @@ -213,17 +233,7 @@ "keys = index.load(data)\n", "\n", "print(f\"Loaded {len(keys)} products into the index\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Loaded 6 products into the index\n" - ] - } - ], - "execution_count": 3 + ] }, { "cell_type": "markdown", @@ -240,18 +250,33 @@ }, { "cell_type": "code", + "execution_count": 4, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:12.433591Z", - "iopub.status.busy": "2025-11-21T00:42:12.433464Z", - "iopub.status.idle": "2025-11-21T00:42:13.709475Z", - "shell.execute_reply": "2025-11-21T00:42:13.708647Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.289286Z", "start_time": "2025-12-15T09:27:43.721057Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:07.310132Z", + "iopub.status.busy": "2026-02-16T15:17:07.310020Z", + "iopub.status.idle": "2026-02-16T15:17:31.114469Z", + "shell.execute_reply": "2026-02-16T15:17:31.113951Z" } }, + "outputs": [ + { + "data": { + "text/html": [ + "
scoreproduct_idbrief_descriptioncategoryprice
5.953989333038773prod_1comfortable running shoes for athletesfootwear89.99
2.085315593627535prod_5basketball shoes with excellent ankle supportfootwear139.99
2.0410082774474088prod_2lightweight running jacket with water resistanceouterwear129.99
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "from redisvl.query import TextQuery\n", "\n", @@ -265,25 +290,7 @@ "\n", "results = index.query(text_query)\n", "result_print(results)" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
scoreproduct_idbrief_descriptioncategoryprice
6.134713688880119prod_1comfortable running shoes for athletesfootwear89.99
6.134713688880119prod_1comfortable running shoes for athletesfootwear89.99
2.148612199701887prod_5basketball shoes with excellent ankle supportfootwear139.99
2.148612199701887prod_5basketball shoes with excellent ankle supportfootwear139.99
2.102960001841964prod_2lightweight running jacket with water resistanceouterwear129.99
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 4 + ] }, { "cell_type": "markdown", @@ -296,32 +303,19 @@ }, { "cell_type": "code", + "execution_count": 5, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.711396Z", - "iopub.status.busy": "2025-11-21T00:42:13.711221Z", - "iopub.status.idle": "2025-11-21T00:42:13.749216Z", - "shell.execute_reply": "2025-11-21T00:42:13.748398Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.337057Z", "start_time": "2025-12-15T09:27:44.321956Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.116222Z", + "iopub.status.busy": "2026-02-16T15:17:31.116038Z", + "iopub.status.idle": "2026-02-16T15:17:31.120972Z", + "shell.execute_reply": "2026-02-16T15:17:31.120483Z" } }, - "source": [ - "# BM25 standard scoring (default)\n", - "bm25_query = TextQuery(\n", - " text=\"comfortable shoes\",\n", - " text_field_name=\"brief_description\",\n", - " text_scorer=\"BM25STD\",\n", - " return_fields=[\"product_id\", \"brief_description\", \"price\"],\n", - " num_results=3\n", - ")\n", - "\n", - "print(\"Results with BM25 scoring:\")\n", - "results = index.query(bm25_query)\n", - "result_print(results)" - ], "outputs": [ { "name": "stdout", @@ -332,50 +326,47 @@ }, { "data": { + "text/html": [ + "
scoreproduct_idbrief_descriptionprice
6.031534703977659prod_1comfortable running shoes for athletes89.99
2.085315593627535prod_5basketball shoes with excellent ankle support139.99
1.5268074873573214prod_4yoga mat with extra cushioning for comfort39.99
" + ], "text/plain": [ "" - ], - "text/html": [ - "
scoreproduct_idbrief_descriptionprice
6.340446315760713prod_1comfortable running shoes for athletes89.99
6.340446315760713prod_1comfortable running shoes for athletes89.99
2.148612199701887prod_5basketball shoes with excellent ankle support139.99
" ] }, "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } + "output_type": "display_data" } ], - "execution_count": 5 + "source": [ + "# BM25 standard scoring (default)\n", + "bm25_query = TextQuery(\n", + " text=\"comfortable shoes\",\n", + " text_field_name=\"brief_description\",\n", + " text_scorer=\"BM25STD\",\n", + " return_fields=[\"product_id\", \"brief_description\", \"price\"],\n", + " num_results=3\n", + ")\n", + "\n", + "print(\"Results with BM25 scoring:\")\n", + "results = index.query(bm25_query)\n", + "result_print(results)" + ] }, { "cell_type": "code", + "execution_count": 6, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.750799Z", - "iopub.status.busy": "2025-11-21T00:42:13.750686Z", - "iopub.status.idle": "2025-11-21T00:42:13.754896Z", - "shell.execute_reply": "2025-11-21T00:42:13.754345Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.352789Z", "start_time": "2025-12-15T09:27:44.344825Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.122229Z", + "iopub.status.busy": "2026-02-16T15:17:31.122120Z", + "iopub.status.idle": "2026-02-16T15:17:31.126377Z", + "shell.execute_reply": "2026-02-16T15:17:31.125815Z" } }, - "source": [ - "# TFIDF scoring\n", - "tfidf_query = TextQuery(\n", - " text=\"comfortable shoes\",\n", - " text_field_name=\"brief_description\",\n", - " text_scorer=\"TFIDF\",\n", - " return_fields=[\"product_id\", \"brief_description\", \"price\"],\n", - " num_results=3\n", - ")\n", - "\n", - "print(\"Results with TFIDF scoring:\")\n", - "results = index.query(tfidf_query)\n", - "result_print(results)" - ], "outputs": [ { "name": "stdout", @@ -386,21 +377,31 @@ }, { "data": { + "text/html": [ + "
scoreproduct_idbrief_descriptionprice
2.3333333333333335prod_1comfortable running shoes for athletes89.99
2.0prod_5basketball shoes with excellent ankle support139.99
1.0prod_4yoga mat with extra cushioning for comfort39.99
" + ], "text/plain": [ "" - ], - "text/html": [ - "
scoreproduct_idbrief_descriptionprice
2.0prod_1comfortable running shoes for athletes89.99
2.0prod_5basketball shoes with excellent ankle support139.99
2.0prod_1comfortable running shoes for athletes89.99
" ] }, "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } + "output_type": "display_data" } ], - "execution_count": 6 + "source": [ + "# TFIDF scoring\n", + "tfidf_query = TextQuery(\n", + " text=\"comfortable shoes\",\n", + " text_field_name=\"brief_description\",\n", + " text_scorer=\"TFIDF\",\n", + " return_fields=[\"product_id\", \"brief_description\", \"price\"],\n", + " num_results=3\n", + ")\n", + "\n", + "print(\"Results with TFIDF scoring:\")\n", + "results = index.query(tfidf_query)\n", + "result_print(results)" + ] }, { "cell_type": "markdown", @@ -413,18 +414,33 @@ }, { "cell_type": "code", + "execution_count": 7, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.756368Z", - "iopub.status.busy": "2025-11-21T00:42:13.756224Z", - "iopub.status.idle": "2025-11-21T00:42:13.760388Z", - "shell.execute_reply": "2025-11-21T00:42:13.759844Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.374828Z", "start_time": "2025-12-15T09:27:44.359984Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.127613Z", + "iopub.status.busy": "2026-02-16T15:17:31.127518Z", + "iopub.status.idle": "2026-02-16T15:17:31.131534Z", + "shell.execute_reply": "2026-02-16T15:17:31.131085Z" } }, + "outputs": [ + { + "data": { + "text/html": [ + "
scoreproduct_idbrief_descriptioncategoryprice
3.9314935770863046prod_1comfortable running shoes for athletesfootwear89.99
3.1279733904413027prod_5basketball shoes with excellent ankle supportfootwear139.99
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "from redisvl.query.filter import Tag, Num\n", "\n", @@ -439,40 +455,37 @@ "\n", "results = index.query(filtered_text_query)\n", "result_print(results)" - ], + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "ExecuteTime": { + "end_time": "2025-12-15T09:27:44.409910Z", + "start_time": "2025-12-15T09:27:44.378041Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.132592Z", + "iopub.status.busy": "2026-02-16T15:17:31.132506Z", + "iopub.status.idle": "2026-02-16T15:17:31.136099Z", + "shell.execute_reply": "2026-02-16T15:17:31.135780Z" + } + }, "outputs": [ { "data": { + "text/html": [ + "
scoreproduct_idbrief_descriptionprice
3.1541404034996914prod_1comfortable running shoes for athletes89.99
1.5268074873573214prod_4yoga mat with extra cushioning for comfort39.99
" + ], "text/plain": [ "" - ], - "text/html": [ - "
scoreproduct_idbrief_descriptioncategoryprice
4.050828128169667prod_1comfortable running shoes for athletesfootwear89.99
4.050828128169667prod_1comfortable running shoes for athletesfootwear89.99
3.2229182995528305prod_5basketball shoes with excellent ankle supportfootwear139.99
3.2229182995528305prod_5basketball shoes with excellent ankle supportfootwear139.99
" ] }, "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } + "output_type": "display_data" } ], - "execution_count": 7 - }, - { - "cell_type": "code", - "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.761654Z", - "iopub.status.busy": "2025-11-21T00:42:13.761566Z", - "iopub.status.idle": "2025-11-21T00:42:13.765694Z", - "shell.execute_reply": "2025-11-21T00:42:13.765316Z" - }, - "ExecuteTime": { - "end_time": "2025-12-15T09:27:44.409910Z", - "start_time": "2025-12-15T09:27:44.378041Z" - } - }, "source": [ "# Search for products under $100\n", "price_filtered_query = TextQuery(\n", @@ -485,25 +498,7 @@ "\n", "results = index.query(price_filtered_query)\n", "result_print(results)" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
scoreproduct_idbrief_descriptionprice
3.3757130560793973prod_1comfortable running shoes for athletes89.99
3.3757130560793973prod_1comfortable running shoes for athletes89.99
1.6340629489648504prod_4yoga mat with extra cushioning for comfort39.99
1.6340629489648504prod_4yoga mat with extra cushioning for comfort39.99
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 8 + ] }, { "cell_type": "markdown", @@ -517,47 +512,44 @@ }, { "cell_type": "code", + "execution_count": 9, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.767228Z", - "iopub.status.busy": "2025-11-21T00:42:13.767102Z", - "iopub.status.idle": "2025-11-21T00:42:13.771059Z", - "shell.execute_reply": "2025-11-21T00:42:13.770555Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.425817Z", "start_time": "2025-12-15T09:27:44.412131Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.137417Z", + "iopub.status.busy": "2026-02-16T15:17:31.137337Z", + "iopub.status.idle": "2026-02-16T15:17:31.140926Z", + "shell.execute_reply": "2026-02-16T15:17:31.140520Z" } }, - "source": [ - "weighted_query = TextQuery(\n", - " text=\"shoes\",\n", - " text_field_name={\"brief_description\": 1.0, \"full_description\": 0.5},\n", - " return_fields=[\"product_id\", \"brief_description\"],\n", - " num_results=3\n", - ")\n", - "\n", - "results = index.query(weighted_query)\n", - "result_print(results)" - ], "outputs": [ { "data": { + "text/html": [ + "
scoreproduct_idbrief_description
5.035440025836444prod_1comfortable running shoes for athletes
2.085315593627535prod_5basketball shoes with excellent ankle support
" + ], "text/plain": [ "" - ], - "text/html": [ - "
scoreproduct_idbrief_description
5.1882832044423015prod_1comfortable running shoes for athletes
5.1882832044423015prod_1comfortable running shoes for athletes
2.148612199701887prod_5basketball shoes with excellent ankle support
" ] }, "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } + "output_type": "display_data" } ], - "execution_count": 9 + "source": [ + "weighted_query = TextQuery(\n", + " text=\"shoes\",\n", + " text_field_name={\"brief_description\": 1.0, \"full_description\": 0.5},\n", + " return_fields=[\"product_id\", \"brief_description\"],\n", + " num_results=3\n", + ")\n", + "\n", + "results = index.query(weighted_query)\n", + "result_print(results)" + ] }, { "cell_type": "markdown", @@ -570,18 +562,33 @@ }, { "cell_type": "code", + "execution_count": 10, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.772513Z", - "iopub.status.busy": "2025-11-21T00:42:13.772419Z", - "iopub.status.idle": "2025-11-21T00:42:13.776286Z", - "shell.execute_reply": "2025-11-21T00:42:13.775861Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.440583Z", "start_time": "2025-12-15T09:27:44.427869Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.142202Z", + "iopub.status.busy": "2026-02-16T15:17:31.142056Z", + "iopub.status.idle": "2026-02-16T15:17:31.145323Z", + "shell.execute_reply": "2026-02-16T15:17:31.144971Z" } }, + "outputs": [ + { + "data": { + "text/html": [ + "
scoreproduct_idbrief_description
5.953989333038773prod_1comfortable running shoes for athletes
2.085315593627535prod_5basketball shoes with excellent ankle support
2.0410082774474088prod_2lightweight running jacket with water resistance
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Use English stopwords (default)\n", "query_with_stopwords = TextQuery(\n", @@ -594,40 +601,37 @@ "\n", "results = index.query(query_with_stopwords)\n", "result_print(results)" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
scoreproduct_idbrief_description
6.134713688880119prod_1comfortable running shoes for athletes
6.134713688880119prod_1comfortable running shoes for athletes
2.148612199701887prod_5basketball shoes with excellent ankle support
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 10 + ] }, { "cell_type": "code", + "execution_count": 11, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.777294Z", - "iopub.status.busy": "2025-11-21T00:42:13.777220Z", - "iopub.status.idle": "2025-11-21T00:42:13.781329Z", - "shell.execute_reply": "2025-11-21T00:42:13.780713Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.461967Z", "start_time": "2025-12-15T09:27:44.447726Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.146274Z", + "iopub.status.busy": "2026-02-16T15:17:31.146200Z", + "iopub.status.idle": "2026-02-16T15:17:31.149223Z", + "shell.execute_reply": "2026-02-16T15:17:31.148867Z" } }, + "outputs": [ + { + "data": { + "text/html": [ + "
scoreproduct_idbrief_description
3.1541404034996914prod_1comfortable running shoes for athletes
3.0864038416103prod_3professional tennis racket for competitive players
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Use custom stopwords\n", "custom_stopwords_query = TextQuery(\n", @@ -640,40 +644,37 @@ "\n", "results = index.query(custom_stopwords_query)\n", "result_print(results)" - ], + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "ExecuteTime": { + "end_time": "2025-12-15T09:27:44.478620Z", + "start_time": "2025-12-15T09:27:44.465051Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.150326Z", + "iopub.status.busy": "2026-02-16T15:17:31.150250Z", + "iopub.status.idle": "2026-02-16T15:17:31.153330Z", + "shell.execute_reply": "2026-02-16T15:17:31.152986Z" + } + }, "outputs": [ { "data": { + "text/html": [ + "
scoreproduct_idbrief_description
5.953989333038773prod_1comfortable running shoes for athletes
2.085315593627535prod_5basketball shoes with excellent ankle support
2.0410082774474088prod_2lightweight running jacket with water resistance
" + ], "text/plain": [ "" - ], - "text/html": [ - "
scoreproduct_idbrief_description
3.3757130560793973prod_1comfortable running shoes for athletes
3.3757130560793973prod_1comfortable running shoes for athletes
3.303218123358508prod_3professional tennis racket for competitive players
" ] }, "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } + "output_type": "display_data" } ], - "execution_count": 11 - }, - { - "cell_type": "code", - "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.782401Z", - "iopub.status.busy": "2025-11-21T00:42:13.782323Z", - "iopub.status.idle": "2025-11-21T00:42:13.787197Z", - "shell.execute_reply": "2025-11-21T00:42:13.786617Z" - }, - "ExecuteTime": { - "end_time": "2025-12-15T09:27:44.478620Z", - "start_time": "2025-12-15T09:27:44.465051Z" - } - }, "source": [ "# No stopwords\n", "no_stopwords_query = TextQuery(\n", @@ -686,25 +687,7 @@ "\n", "results = index.query(no_stopwords_query)\n", "result_print(results)" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
scoreproduct_idbrief_description
6.134713688880119prod_1comfortable running shoes for athletes
6.134713688880119prod_1comfortable running shoes for athletes
2.148612199701887prod_5basketball shoes with excellent ankle support
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 12 + ] }, { "cell_type": "markdown", @@ -720,13 +703,29 @@ ] }, { + "cell_type": "code", + "execution_count": 13, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.494712Z", "start_time": "2025-12-15T09:27:44.481443Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.154372Z", + "iopub.status.busy": "2026-02-16T15:17:31.154300Z", + "iopub.status.idle": "2026-02-16T15:17:31.157317Z", + "shell.execute_reply": "2026-02-16T15:17:31.156892Z" } }, - "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], "source": [ "from packaging.version import Version\n", "\n", @@ -737,17 +736,7 @@ "\n", "HYBRID_SEARCH_AVAILABLE = redis_version >= Version(\"8.4.0\") and redis_py_version >= Version(\"7.1.0\")\n", "print(HYBRID_SEARCH_AVAILABLE)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "execution_count": 13 + ] }, { "cell_type": "markdown", @@ -775,18 +764,28 @@ }, { "cell_type": "code", + "execution_count": 14, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.788835Z", - "iopub.status.busy": "2025-11-21T00:42:13.788717Z", - "iopub.status.idle": "2025-11-21T00:42:13.795247Z", - "shell.execute_reply": "2025-11-21T00:42:13.794662Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.512721Z", "start_time": "2025-12-15T09:27:44.497780Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.158421Z", + "iopub.status.busy": "2026-02-16T15:17:31.158344Z", + "iopub.status.idle": "2026-02-16T15:17:31.164588Z", + "shell.execute_reply": "2026-02-16T15:17:31.164184Z" } }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Index created with STOPWORDS 0: \n" + ] + } + ], "source": [ "# Create a schema with index-level stopwords disabled\n", "from redisvl.index import SearchIndex\n", @@ -809,32 +808,32 @@ "company_index.create(overwrite=True, drop=True)\n", "\n", "print(f\"Index created with STOPWORDS 0: {company_index}\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Index created with STOPWORDS 0: \n" - ] - } - ], - "execution_count": 14 + ] }, { "cell_type": "code", + "execution_count": 15, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.796880Z", - "iopub.status.busy": "2025-11-21T00:42:13.796745Z", - "iopub.status.idle": "2025-11-21T00:42:13.802750Z", - "shell.execute_reply": "2025-11-21T00:42:13.802098Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.528568Z", "start_time": "2025-12-15T09:27:44.513241Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.165547Z", + "iopub.status.busy": "2026-02-16T15:17:31.165478Z", + "iopub.status.idle": "2026-02-16T15:17:31.169607Z", + "shell.execute_reply": "2026-02-16T15:17:31.169224Z" } }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "โœ“ Loaded 5 companies\n" + ] + } + ], "source": [ "# Load sample data with company names containing common stopwords\n", "companies = [\n", @@ -849,32 +848,33 @@ " company_index.load([company], keys=[f\"company:{i}\"])\n", "\n", "print(f\"โœ“ Loaded {len(companies)} companies\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "โœ“ Loaded 5 companies\n" - ] - } - ], - "execution_count": 15 + ] }, { "cell_type": "code", + "execution_count": 16, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.804059Z", - "iopub.status.busy": "2025-11-21T00:42:13.803942Z", - "iopub.status.idle": "2025-11-21T00:42:13.807026Z", - "shell.execute_reply": "2025-11-21T00:42:13.806491Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.534288Z", "start_time": "2025-12-15T09:27:44.528999Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.170610Z", + "iopub.status.busy": "2026-02-16T15:17:31.170537Z", + "iopub.status.idle": "2026-02-16T15:17:31.173265Z", + "shell.execute_reply": "2026-02-16T15:17:31.172885Z" } }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found 1 results for 'Bank of Glasberliner':\n", + " - Bank of Glasberliner: Major financial institution\n" + ] + } + ], "source": [ "# Search for \"Bank of Glasberliner\" - with STOPWORDS 0, \"of\" is indexed and searchable\n", "from redisvl.query import FilterQuery\n", @@ -889,18 +889,7 @@ "print(f\"Found {len(results.docs)} results for 'Bank of Glasberliner':\")\n", "for doc in results.docs:\n", " print(f\" - {doc.company_name}: {doc.description}\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Found 1 results for 'Bank of Glasberliner':\n", - " - Bank of Glasberliner: Major financial institution\n" - ] - } - ], - "execution_count": 16 + ] }, { "cell_type": "markdown", @@ -921,18 +910,28 @@ }, { "cell_type": "code", + "execution_count": 17, "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.808543Z", - "iopub.status.busy": "2025-11-21T00:42:13.808418Z", - "iopub.status.idle": "2025-11-21T00:42:13.810612Z", - "shell.execute_reply": "2025-11-21T00:42:13.810083Z" - }, "ExecuteTime": { "end_time": "2025-12-15T09:27:44.553398Z", "start_time": "2025-12-15T09:27:44.541083Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.174218Z", + "iopub.status.busy": "2026-02-16T15:17:31.174154Z", + "iopub.status.idle": "2026-02-16T15:17:31.175974Z", + "shell.execute_reply": "2026-02-16T15:17:31.175650Z" } }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Custom stopwords: ['inc', 'llc', 'corp']\n" + ] + } + ], "source": [ "# Example: Create index with custom stopwords\n", "custom_stopwords_schema = {\n", @@ -948,17 +947,7 @@ "\n", "# This would create an index where \"inc\", \"llc\", \"corp\" are not indexed\n", "print(\"Custom stopwords:\", custom_stopwords_schema[\"index\"][\"stopwords\"])" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Custom stopwords: ['inc', 'llc', 'corp']\n" - ] - } - ], - "execution_count": 17 + ] }, { "cell_type": "markdown", @@ -997,17 +986,19 @@ }, { "cell_type": "code", + "execution_count": 18, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.586789Z", "start_time": "2025-12-15T09:27:44.556392Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.176910Z", + "iopub.status.busy": "2026-02-16T15:17:31.176846Z", + "iopub.status.idle": "2026-02-16T15:17:31.179113Z", + "shell.execute_reply": "2026-02-16T15:17:31.178737Z" } }, - "source": [ - "# Cleanup\n", - "company_index.delete(drop=True)\n", - "print(\"โœ“ Cleaned up company_index\")" - ], "outputs": [ { "name": "stdout", @@ -1017,7 +1008,11 @@ ] } ], - "execution_count": 18 + "source": [ + "# Cleanup\n", + "company_index.delete(drop=True)\n", + "print(\"โœ“ Cleaned up company_index\")" + ] }, { "cell_type": "markdown", @@ -1032,12 +1027,47 @@ }, { "cell_type": "code", + "execution_count": 19, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.599394Z", "start_time": "2025-12-15T09:27:44.589681Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.180129Z", + "iopub.status.busy": "2026-02-16T15:17:31.180058Z", + "iopub.status.idle": "2026-02-16T15:17:31.184565Z", + "shell.execute_reply": "2026-02-16T15:17:31.184291Z" } }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/redisvl/query/hybrid.py:136: UserWarning: HybridPostProcessingConfig is an experimental and may change or be removed in future versions.\n", + " self.postprocessing_config = HybridPostProcessingConfig()\n", + "/Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/redisvl/query/hybrid.py:247: UserWarning: HybridSearchQuery is an experimental and may change or be removed in future versions.\n", + " search_query = HybridSearchQuery(\n", + "/Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/redisvl/query/hybrid.py:288: UserWarning: HybridVsimQuery is an experimental and may change or be removed in future versions.\n", + " vsim_query = HybridVsimQuery(\n", + "/Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/redisvl/query/hybrid.py:363: UserWarning: CombineResultsMethod is an experimental and may change or be removed in future versions.\n", + " return CombineResultsMethod(\n" + ] + }, + { + "data": { + "text/html": [ + "
text_scoreproduct_idbrief_descriptioncategorypricevector_similarityhybrid_score
5.95398933304prod_1comfortable running shoes for athletesfootwear89.990.9999999701982.48619677905
2.08531559363prod_5basketball shoes with excellent ankle supportfootwear139.990.9950737357141.32214629309
2.04100827745prod_2lightweight running jacket with water resistanceouterwear129.990.9950737357141.30885409823
0prod_4yoga mat with extra cushioning for comfortaccessories39.990.9980582594870.698640781641
0prod_6swimming goggles with anti-fog coatingaccessories24.990.8818812966350.617316907644
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "if HYBRID_SEARCH_AVAILABLE:\n", " from redisvl.query import HybridQuery\n", @@ -1061,53 +1091,44 @@ "\n", "else:\n", " print(\"Hybrid search is not available in this version of Redis/redis-py.\")" - ], - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/vishal.bala/PycharmProjects/redis-vl-python/redisvl/query/hybrid.py:133: UserWarning: HybridPostProcessingConfig is an experimental and may change or be removed in future versions.\n", - " self.postprocessing_config = HybridPostProcessingConfig()\n", - "/Users/vishal.bala/PycharmProjects/redis-vl-python/redisvl/query/hybrid.py:237: UserWarning: HybridSearchQuery is an experimental and may change or be removed in future versions.\n", - " search_query = HybridSearchQuery(\n", - "/Users/vishal.bala/PycharmProjects/redis-vl-python/redisvl/query/hybrid.py:278: UserWarning: HybridVsimQuery is an experimental and may change or be removed in future versions.\n", - " vsim_query = HybridVsimQuery(\n", - "/Users/vishal.bala/PycharmProjects/redis-vl-python/redisvl/query/hybrid.py:352: UserWarning: CombineResultsMethod is an experimental and may change or be removed in future versions.\n", - " return CombineResultsMethod(\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
text_scoreproduct_idbrief_descriptioncategorypricevector_similarityhybrid_score
6.13471368888prod_1comfortable running shoes for athletesfootwear89.990.9999999701982.5404140858
6.13471368888prod_1comfortable running shoes for athletesfootwear89.990.9999999701982.5404140858
2.1486121997prod_5basketball shoes with excellent ankle supportfootwear139.990.9950737357141.34113527491
2.1486121997prod_5basketball shoes with excellent ankle supportfootwear139.990.9950737357141.34113527491
2.10296000184prod_2lightweight running jacket with water resistanceouterwear129.990.9950737357141.32743961555
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 19 + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "For earlier versions of Redis, you can use `AggregateHybridQuery` instead:" + "metadata": {}, + "source": [ + "For earlier versions of Redis, you can use `AggregateHybridQuery` instead:" + ] }, { + "cell_type": "code", + "execution_count": 20, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.619601Z", "start_time": "2025-12-15T09:27:44.606514Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.185602Z", + "iopub.status.busy": "2026-02-16T15:17:31.185538Z", + "iopub.status.idle": "2026-02-16T15:17:31.188771Z", + "shell.execute_reply": "2026-02-16T15:17:31.188422Z" } }, - "cell_type": "code", + "outputs": [ + { + "data": { + "text/html": [ + "
vector_distanceproduct_idbrief_descriptioncategorypricevector_similaritytext_scorehybrid_score
5.96046447754e-08prod_1comfortable running shoes for athletesfootwear89.990.9999999701985.953989333042.48619677905
0.00985252857208prod_5basketball shoes with excellent ankle supportfootwear139.990.9950737357142.085315593631.32214629309
0.00985252857208prod_2lightweight running jacket with water resistanceouterwear129.990.9950737357142.041008277451.30885409823
0.0038834810257prod_4yoga mat with extra cushioning for comfortaccessories39.990.99805825948700.698640781641
0.236237406731prod_6swimming goggles with anti-fog coatingaccessories24.990.88188129663500.617316907644
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "from redisvl.query import AggregateHybridQuery\n", "\n", @@ -1122,25 +1143,7 @@ "\n", "results = index.query(agg_hybrid_query)\n", "result_print(results)" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
vector_distanceproduct_idbrief_descriptioncategorypricevector_similaritytext_scorehybrid_score
5.96046447754e-08prod_1comfortable running shoes for athletesfootwear89.990.9999999701986.134713688882.5404140858
5.96046447754e-08prod_1comfortable running shoes for athletesfootwear89.990.9999999701986.134713688882.5404140858
0.00985252857208prod_5basketball shoes with excellent ankle supportfootwear139.990.9950737357142.14861219971.34113527491
0.0038834810257prod_4yoga mat with extra cushioning for comfortaccessories39.990.99805825948700.698640781641
0.0038834810257prod_4yoga mat with extra cushioning for comfortaccessories39.990.99805825948700.698640781641
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 20 + ] }, { "cell_type": "markdown", @@ -1163,13 +1166,41 @@ ] }, { + "cell_type": "code", + "execution_count": 21, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.636058Z", "start_time": "2025-12-15T09:27:44.621406Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.189764Z", + "iopub.status.busy": "2026-02-16T15:17:31.189701Z", + "iopub.status.idle": "2026-02-16T15:17:31.193700Z", + "shell.execute_reply": "2026-02-16T15:17:31.193353Z" } }, - "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Results with alpha=0.1 (vector-heavy):\n" + ] + }, + { + "data": { + "text/html": [ + "
text_scoreproduct_idbrief_descriptionvector_similarityhybrid_score
3.1541404035prod_1comfortable running shoes for athletes0.9980582594871.21366647389
1.52680748736prod_4yoga mat with extra cushioning for comfort1.00000005961.05268080238
0prod_2lightweight running jacket with water resistance0.9993155598640.899384003878
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "if HYBRID_SEARCH_AVAILABLE:\n", " vector_heavy_query = HybridQuery(\n", @@ -1192,41 +1223,44 @@ "\n", "else:\n", " print(\"Hybrid search is not available in this version of Redis/redis-py.\")" - ], + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "ExecuteTime": { + "end_time": "2025-12-15T09:27:44.651595Z", + "start_time": "2025-12-15T09:27:44.643458Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.194553Z", + "iopub.status.busy": "2026-02-16T15:17:31.194492Z", + "iopub.status.idle": "2026-02-16T15:17:31.198234Z", + "shell.execute_reply": "2026-02-16T15:17:31.197931Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Results with alpha=0.1 (vector-heavy):\n" + "Results with alpha=0.9 (vector-heavy):\n" ] }, { "data": { + "text/html": [ + "
vector_distanceproduct_idbrief_descriptionvector_similaritytext_scorehybrid_score
-1.19209289551e-07prod_4yoga mat with extra cushioning for comfort1.00000005961.526807487361.05268080238
0.00136888027191prod_5basketball shoes with excellent ankle support0.99931555986400.899384003878
0.00136888027191prod_2lightweight running jacket with water resistance0.99931555986400.899384003878
" + ], "text/plain": [ "" - ], - "text/html": [ - "
text_scoreproduct_idbrief_descriptionvector_similarityhybrid_score
3.37571305608prod_1comfortable running shoes for athletes0.9980582594871.23582373915
3.37571305608prod_1comfortable running shoes for athletes0.9980582594871.23582373915
1.63406294896prod_4yoga mat with extra cushioning for comfort1.00000005961.06340634854
" ] }, "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } + "output_type": "display_data" } ], - "execution_count": 21 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-12-15T09:27:44.651595Z", - "start_time": "2025-12-15T09:27:44.643458Z" - } - }, "source": [ "# More emphasis on vector search (alpha=0.9)\n", "vector_heavy_query = AggregateHybridQuery(\n", @@ -1242,41 +1276,18 @@ "print(\"Results with alpha=0.9 (vector-heavy):\")\n", "results = index.query(vector_heavy_query)\n", "result_print(results)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Results with alpha=0.9 (vector-heavy):\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
vector_distanceproduct_idbrief_descriptionvector_similaritytext_scorehybrid_score
-1.19209289551e-07prod_4yoga mat with extra cushioning for comfort1.00000005961.634062948961.06340634854
-1.19209289551e-07prod_4yoga mat with extra cushioning for comfort1.00000005961.634062948961.06340634854
0.00136888027191prod_5basketball shoes with excellent ankle support0.99931555986400.899384003878
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 22 + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "##" + "metadata": {}, + "source": [ + "##" + ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### Reciprocal Rank Fusion (RRF)\n", "\n", @@ -1290,13 +1301,34 @@ ] }, { + "cell_type": "code", + "execution_count": 23, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.664953Z", "start_time": "2025-12-15T09:27:44.658451Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.199251Z", + "iopub.status.busy": "2026-02-16T15:17:31.199188Z", + "iopub.status.idle": "2026-02-16T15:17:31.202314Z", + "shell.execute_reply": "2026-02-16T15:17:31.201944Z" } }, - "cell_type": "code", + "outputs": [ + { + "data": { + "text/html": [ + "
text_scoreproduct_idbrief_descriptionvector_similarityhybrid_score
1.52680748736prod_4yoga mat with extra cushioning for comfort1.00000005960.032522474881
3.1541404035prod_1comfortable running shoes for athletes0.9980582594870.032018442623
0prod_2lightweight running jacket with water resistance0.9993155598640.0320020481311
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "if HYBRID_SEARCH_AVAILABLE:\n", " rrf_query = HybridQuery(\n", @@ -1317,25 +1349,7 @@ "\n", "else:\n", " print(\"Hybrid search is not available in this version of Redis/redis-py.\")" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
text_scoreproduct_idbrief_descriptionvector_similarityhybrid_score
1.63406294896prod_4yoga mat with extra cushioning for comfort1.00000005960.032266458496
1.63406294896prod_4yoga mat with extra cushioning for comfort1.00000005960.0317540322581
3.37571305608prod_1comfortable running shoes for athletes0.9980582594870.0313188157573
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 23 + ] }, { "cell_type": "markdown", @@ -1347,13 +1361,34 @@ ] }, { + "cell_type": "code", + "execution_count": 24, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.686355Z", "start_time": "2025-12-15T09:27:44.672035Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.203197Z", + "iopub.status.busy": "2026-02-16T15:17:31.203138Z", + "iopub.status.idle": "2026-02-16T15:17:31.206363Z", + "shell.execute_reply": "2026-02-16T15:17:31.206077Z" } }, - "cell_type": "code", + "outputs": [ + { + "data": { + "text/html": [ + "
text_scoreproduct_idbrief_descriptioncategorypricevector_similarityhybrid_score
3.08640384161prod_3professional tennis racket for competitive playersequipment199.991.00000005961.62592119421
0prod_2lightweight running jacket with water resistanceouterwear129.990.7941712737080.555919891596
0prod_5basketball shoes with excellent ankle supportfootwear139.990.7941712737080.555919891596
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "if HYBRID_SEARCH_AVAILABLE:\n", " # Hybrid search with a price filter\n", @@ -1376,34 +1411,37 @@ "\n", "else:\n", " print(\"Hybrid search is not available in this version of Redis/redis-py.\")" - ], + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "ExecuteTime": { + "end_time": "2025-12-15T09:27:44.702984Z", + "start_time": "2025-12-15T09:27:44.689201Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.207295Z", + "iopub.status.busy": "2026-02-16T15:17:31.207232Z", + "iopub.status.idle": "2026-02-16T15:17:31.210438Z", + "shell.execute_reply": "2026-02-16T15:17:31.210032Z" + } + }, "outputs": [ { "data": { + "text/html": [ + "
vector_distanceproduct_idbrief_descriptioncategorypricevector_similaritytext_scorehybrid_score
-1.19209289551e-07prod_3professional tennis racket for competitive playersequipment199.991.00000005963.086403841611.62592119421
0.411657452583prod_5basketball shoes with excellent ankle supportfootwear139.990.79417127370800.555919891596
0.411657452583prod_2lightweight running jacket with water resistanceouterwear129.990.79417127370800.555919891596
" + ], "text/plain": [ "" - ], - "text/html": [ - "
text_scoreproduct_idbrief_descriptioncategorypricevector_similarityhybrid_score
3.30321812336prod_3professional tennis racket for competitive playersequipment199.991.00000005961.69096547873
3.30321812336prod_3professional tennis racket for competitive playersequipment199.991.00000005961.69096547873
0prod_2lightweight running jacket with water resistanceouterwear129.990.7941712737080.555919891596
0prod_5basketball shoes with excellent ankle supportfootwear139.990.7941712737080.555919891596
0prod_2lightweight running jacket with water resistanceouterwear129.990.7941712737080.555919891596
" ] }, "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } + "output_type": "display_data" } ], - "execution_count": 24 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-12-15T09:27:44.702984Z", - "start_time": "2025-12-15T09:27:44.689201Z" - } - }, "source": [ "# Hybrid search with a price filter\n", "filtered_hybrid_query = AggregateHybridQuery(\n", @@ -1418,25 +1456,7 @@ "\n", "results = index.query(filtered_hybrid_query)\n", "result_print(results)" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
vector_distanceproduct_idbrief_descriptioncategorypricevector_similaritytext_scorehybrid_score
-1.19209289551e-07prod_3professional tennis racket for competitive playersequipment199.991.00000005963.303218123361.69096547873
-1.19209289551e-07prod_3professional tennis racket for competitive playersequipment199.991.00000005963.303218123361.69096547873
0.411657452583prod_2lightweight running jacket with water resistanceouterwear129.990.79417127370800.555919891596
0.411657452583prod_5basketball shoes with excellent ankle supportfootwear139.990.79417127370800.555919891596
0.411657452583prod_2lightweight running jacket with water resistanceouterwear129.990.79417127370800.555919891596
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 25 + ] }, { "cell_type": "markdown", @@ -1448,13 +1468,34 @@ ] }, { + "cell_type": "code", + "execution_count": 26, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.715Z", "start_time": "2025-12-15T09:27:44.706463Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.211324Z", + "iopub.status.busy": "2026-02-16T15:17:31.211266Z", + "iopub.status.idle": "2026-02-16T15:17:31.214265Z", + "shell.execute_reply": "2026-02-16T15:17:31.213897Z" } }, - "cell_type": "code", + "outputs": [ + { + "data": { + "text/html": [ + "
text_scoreproduct_idbrief_descriptionvector_similarityhybrid_score
2.66666666667prod_1comfortable running shoes for athletes0.9950737357141.496551615
1.66666666667prod_5basketball shoes with excellent ankle support11.2
0prod_2lightweight running jacket with water resistance10.7
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "if HYBRID_SEARCH_AVAILABLE:\n", " # Aggregate Hybrid query with TFIDF scorer\n", @@ -1477,34 +1518,37 @@ "\n", "else:\n", " print(\"Hybrid search is not available in this version of Redis/redis-py.\")" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
text_scoreproduct_idbrief_descriptionvector_similarityhybrid_score
2.66666666667prod_1comfortable running shoes for athletes0.9950737357141.496551615
2.66666666667prod_1comfortable running shoes for athletes0.9950737357141.496551615
1.33333333333prod_5basketball shoes with excellent ankle support11.1
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 26 + ] }, { "cell_type": "code", + "execution_count": 27, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.728396Z", "start_time": "2025-12-15T09:27:44.721838Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.215100Z", + "iopub.status.busy": "2026-02-16T15:17:31.215041Z", + "iopub.status.idle": "2026-02-16T15:17:31.218819Z", + "shell.execute_reply": "2026-02-16T15:17:31.218461Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
vector_distanceproduct_idbrief_descriptionvector_similaritytext_scorehybrid_score
0prod_5basketball shoes with excellent ankle support152.2
0prod_2lightweight running jacket with water resistance100.7
0.00136888027191prod_4yoga mat with extra cushioning for comfort0.99931555986400.699520891905
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" } - }, + ], "source": [ "# Aggregate Hybrid query with TFIDF scorer\n", "hybrid_tfidf = AggregateHybridQuery(\n", @@ -1519,29 +1563,11 @@ "\n", "results = index.query(hybrid_tfidf)\n", "result_print(results)" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
vector_distanceproduct_idbrief_descriptionvector_similaritytext_scorehybrid_score
0prod_5basketball shoes with excellent ankle support141.9
0prod_2lightweight running jacket with water resistance100.7
0prod_2lightweight running jacket with water resistance100.7
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 27 + ] }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### Runtime Parameters for Vector Search Tuning\n", "\n", @@ -1585,12 +1611,33 @@ }, { "cell_type": "code", + "execution_count": 28, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.742916Z", "start_time": "2025-12-15T09:27:44.736787Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.219849Z", + "iopub.status.busy": "2026-02-16T15:17:31.219790Z", + "iopub.status.idle": "2026-02-16T15:17:31.222773Z", + "shell.execute_reply": "2026-02-16T15:17:31.222418Z" } }, + "outputs": [ + { + "data": { + "text/html": [ + "
distance_0distance_1product_idbrief_descriptioncategoryscore_0score_1combined_score
5.96046447754e-085.96046447754e-08prod_1comfortable running shoes for athletesfootwear0.9999999701980.9999999701980.999999970198
0.009852528572080.00266629457474prod_5basketball shoes with excellent ankle supportfootwear0.9950737357140.9986668527130.996151670814
0.009852528572080.0118260979652prod_2lightweight running jacket with water resistanceouterwear0.9950737357140.9940869510170.994777700305
0.00388348102570.210647821426prod_4yoga mat with extra cushioning for comfortaccessories0.9980582594870.8946760892870.967043608427
0.2362374067310.639005899429prod_6swimming goggles with anti-fog coatingaccessories0.8818812966350.6804970502850.82146602273
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "from redisvl.query import MultiVectorQuery, Vector\n", "\n", @@ -1618,25 +1665,7 @@ "\n", "results = index.query(multi_vector_query)\n", "result_print(results)" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
distance_0distance_1product_idbrief_descriptioncategoryscore_0score_1combined_score
5.96046447754e-085.96046447754e-08prod_1comfortable running shoes for athletesfootwear0.9999999701980.9999999701980.999999970198
5.96046447754e-085.96046447754e-08prod_1comfortable running shoes for athletesfootwear0.9999999701980.9999999701980.999999970198
0.009852528572080.00266629457474prod_5basketball shoes with excellent ankle supportfootwear0.9950737357140.9986668527130.996151670814
0.009852528572080.00266629457474prod_5basketball shoes with excellent ankle supportfootwear0.9950737357140.9986668527130.996151670814
0.009852528572080.0118260979652prod_2lightweight running jacket with water resistanceouterwear0.9950737357140.9940869510170.994777700305
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 28 + ] }, { "cell_type": "markdown", @@ -1649,12 +1678,40 @@ }, { "cell_type": "code", + "execution_count": 29, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.764858Z", "start_time": "2025-12-15T09:27:44.749806Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.223637Z", + "iopub.status.busy": "2026-02-16T15:17:31.223579Z", + "iopub.status.idle": "2026-02-16T15:17:31.226532Z", + "shell.execute_reply": "2026-02-16T15:17:31.226206Z" } }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Results with emphasis on image similarity:\n" + ] + }, + { + "data": { + "text/html": [ + "
distance_0distance_1product_idbrief_descriptioncategoryscore_0score_1combined_score
-1.19209289551e-070prod_3professional tennis racket for competitive playersequipment1.000000059611.00000001192
0.145393729210.00900757312775prod_6swimming goggles with anti-fog coatingaccessories0.9273031353950.9954962134360.981857597828
0.4366961717610.219131231308prod_4yoga mat with extra cushioning for comfortaccessories0.781651914120.8904343843460.868677890301
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# More emphasis on image similarity\n", "text_vec = Vector(\n", @@ -1680,32 +1737,7 @@ "print(\"Results with emphasis on image similarity:\")\n", "results = index.query(image_heavy_query)\n", "result_print(results)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Results with emphasis on image similarity:\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
distance_0distance_1product_idbrief_descriptioncategoryscore_0score_1combined_score
-1.19209289551e-070prod_3professional tennis racket for competitive playersequipment1.000000059611.00000001192
-1.19209289551e-070prod_3professional tennis racket for competitive playersequipment1.000000059611.00000001192
0.145393729210.00900757312775prod_6swimming goggles with anti-fog coatingaccessories0.9273031353950.9954962134360.981857597828
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 29 + ] }, { "cell_type": "markdown", @@ -1718,12 +1750,33 @@ }, { "cell_type": "code", + "execution_count": 30, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.786971Z", "start_time": "2025-12-15T09:27:44.772064Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.227394Z", + "iopub.status.busy": "2026-02-16T15:17:31.227333Z", + "iopub.status.idle": "2026-02-16T15:17:31.230297Z", + "shell.execute_reply": "2026-02-16T15:17:31.229946Z" } }, + "outputs": [ + { + "data": { + "text/html": [ + "
distance_0distance_1product_idbrief_descriptioncategorypricescore_0score_1combined_score
5.96046447754e-085.96046447754e-08prod_1comfortable running shoes for athletesfootwear89.990.9999999701980.9999999701980.999999970198
0.009852528572080.00266629457474prod_5basketball shoes with excellent ankle supportfootwear139.990.9950737357140.9986668527130.996510982513
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Multi-vector search with category filter\n", "text_vec = Vector(\n", @@ -1749,25 +1802,7 @@ "\n", "results = index.query(filtered_multi_query)\n", "result_print(results)" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
distance_0distance_1product_idbrief_descriptioncategorypricescore_0score_1combined_score
5.96046447754e-085.96046447754e-08prod_1comfortable running shoes for athletesfootwear89.990.9999999701980.9999999701980.999999970198
5.96046447754e-085.96046447754e-08prod_1comfortable running shoes for athletesfootwear89.990.9999999701980.9999999701980.999999970198
0.009852528572080.00266629457474prod_5basketball shoes with excellent ankle supportfootwear139.990.9950737357140.9986668527130.996510982513
0.009852528572080.00266629457474prod_5basketball shoes with excellent ankle supportfootwear139.990.9950737357140.9986668527130.996510982513
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 30 + ] }, { "cell_type": "markdown", @@ -1780,12 +1815,47 @@ }, { "cell_type": "code", + "execution_count": 31, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.804045Z", "start_time": "2025-12-15T09:27:44.788480Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.231190Z", + "iopub.status.busy": "2026-02-16T15:17:31.231128Z", + "iopub.status.idle": "2026-02-16T15:17:31.234174Z", + "shell.execute_reply": "2026-02-16T15:17:31.233900Z" } }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TextQuery Results (keyword-based):\n" + ] + }, + { + "data": { + "text/html": [ + "
scoreproduct_idbrief_description
2.8773943004779676prod_1comfortable running shoes for athletes
2.085315593627535prod_5basketball shoes with excellent ankle support
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], "source": [ "# TextQuery - keyword-based search\n", "text_q = TextQuery(\n", @@ -1798,29 +1868,42 @@ "print(\"TextQuery Results (keyword-based):\")\n", "result_print(index.query(text_q))\n", "print()" - ], + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "ExecuteTime": { + "end_time": "2025-12-15T09:27:44.832484Z", + "start_time": "2025-12-15T09:27:44.811853Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.235126Z", + "iopub.status.busy": "2026-02-16T15:17:31.235064Z", + "iopub.status.idle": "2026-02-16T15:17:31.239216Z", + "shell.execute_reply": "2026-02-16T15:17:31.238885Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "TextQuery Results (keyword-based):\n" + "HybridQuery Results (text + vector):\n" ] }, { "data": { + "text/html": [ + "
text_scoreproduct_idbrief_descriptionvector_similarityhybrid_score
2.87739430048prod_1comfortable running shoes for athletes0.9999999701981.56321826928
2.08531559363prod_5basketball shoes with excellent ankle support0.9950737357141.32214629309
0prod_4yoga mat with extra cushioning for comfort0.9980582594870.698640781641
" + ], "text/plain": [ "" - ], - "text/html": [ - "
scoreproduct_idbrief_description
2.9647332596813154prod_1comfortable running shoes for athletes
2.9647332596813154prod_1comfortable running shoes for athletes
2.148612199701887prod_5basketball shoes with excellent ankle support
" ] }, "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } + "output_type": "display_data" }, { "name": "stdout", @@ -1830,22 +1913,6 @@ ] } ], - "execution_count": 31 - }, - { - "cell_type": "code", - "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.860414Z", - "iopub.status.busy": "2025-11-21T00:42:13.860347Z", - "iopub.status.idle": "2025-11-21T00:42:13.864887Z", - "shell.execute_reply": "2025-11-21T00:42:13.864461Z" - }, - "ExecuteTime": { - "end_time": "2025-12-15T09:27:44.832484Z", - "start_time": "2025-12-15T09:27:44.811853Z" - } - }, "source": [ "if HYBRID_SEARCH_AVAILABLE:\n", " # HybridQuery - combines text and vector search\n", @@ -1880,54 +1947,44 @@ "print(f\"{hybrid_q.__class__.__name__} Results (text + vector):\")\n", "result_print(results)\n", "print()" - ], + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "ExecuteTime": { + "end_time": "2025-12-15T09:27:44.853040Z", + "start_time": "2025-12-15T09:27:44.833266Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.240109Z", + "iopub.status.busy": "2026-02-16T15:17:31.240048Z", + "iopub.status.idle": "2026-02-16T15:17:31.244083Z", + "shell.execute_reply": "2026-02-16T15:17:31.243804Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "HybridQuery Results (text + vector):\n" + "MultiVectorQuery Results (multiple vectors):\n" ] }, { "data": { + "text/html": [ + "
distance_0distance_1product_idbrief_descriptionscore_0score_1combined_score
5.96046447754e-085.96046447754e-08prod_1comfortable running shoes for athletes0.9999999701980.9999999701980.999999970198
0.009852528572080.00266629457474prod_5basketball shoes with excellent ankle support0.9950737357140.9986668527130.996870294213
0.009852528572080.0118260979652prod_2lightweight running jacket with water resistance0.9950737357140.9940869510170.994580343366
" + ], "text/plain": [ "" - ], - "text/html": [ - "
text_scoreproduct_idbrief_descriptionvector_similarityhybrid_score
2.96473325968prod_1comfortable running shoes for athletes0.9999999701981.58941995704
2.96473325968prod_1comfortable running shoes for athletes0.9999999701981.58941995704
2.1486121997prod_5basketball shoes with excellent ankle support0.9950737357141.34113527491
" ] }, "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] + "output_type": "display_data" } ], - "execution_count": 32 - }, - { - "cell_type": "code", - "metadata": { - "execution": { - "iopub.execute_input": "2025-11-21T00:42:13.865922Z", - "iopub.status.busy": "2025-11-21T00:42:13.865857Z", - "iopub.status.idle": "2025-11-21T00:42:13.869441Z", - "shell.execute_reply": "2025-11-21T00:42:13.868990Z" - }, - "ExecuteTime": { - "end_time": "2025-12-15T09:27:44.853040Z", - "start_time": "2025-12-15T09:27:44.833266Z" - } - }, "source": [ "# MultiVectorQuery - searches multiple vector fields\n", "mv_text = Vector(\n", @@ -1952,32 +2009,7 @@ "\n", "print(\"MultiVectorQuery Results (multiple vectors):\")\n", "result_print(index.query(multi_q))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "MultiVectorQuery Results (multiple vectors):\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "
distance_0distance_1product_idbrief_descriptionscore_0score_1combined_score
5.96046447754e-085.96046447754e-08prod_1comfortable running shoes for athletes0.9999999701980.9999999701980.999999970198
5.96046447754e-085.96046447754e-08prod_1comfortable running shoes for athletes0.9999999701980.9999999701980.999999970198
0.009852528572080.00266629457474prod_5basketball shoes with excellent ankle support0.9950737357140.9986668527130.996870294213
" - ] - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 33 + ] }, { "cell_type": "markdown", @@ -2006,25 +2038,51 @@ " - Example: Image-text search, cross-modal retrieval" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Now that you understand advanced query types, explore these related guides:\n", + "\n", + "- [Query and Filter Data](02_complex_filtering.ipynb) - Apply filters to narrow down search results\n", + "- [Write SQL Queries for Redis](12_sql_to_redis_queries.ipynb) - Use SQL-like syntax for Redis queries\n", + "- [Improve Search Quality with Rerankers](06_rerankers.ipynb) - Rerank results for better relevance" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleanup" + ] + }, { "cell_type": "code", + "execution_count": 34, "metadata": { "ExecuteTime": { "end_time": "2025-12-15T09:27:44.865832Z", "start_time": "2025-12-15T09:27:44.861322Z" + }, + "execution": { + "iopub.execute_input": "2026-02-16T15:17:31.245159Z", + "iopub.status.busy": "2026-02-16T15:17:31.245099Z", + "iopub.status.idle": "2026-02-16T15:17:31.247976Z", + "shell.execute_reply": "2026-02-16T15:17:31.247577Z" } }, + "outputs": [], "source": [ "# Cleanup\n", "index.delete()" - ], - "outputs": [], - "execution_count": 34 + ] } ], "metadata": { "kernelspec": { - "display_name": "redisvl-dev", + "display_name": ".venv", "language": "python", "name": "python3" }, @@ -2037,7 +2095,8 @@ "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython3" + "pygments_lexer": "ipython3", + "version": "3.13.2" } }, "nbformat": 4, diff --git a/docs/user_guide/12_sql_to_redis_queries.ipynb b/docs/user_guide/12_sql_to_redis_queries.ipynb index 7f26d08d..801cb64e 100644 --- a/docs/user_guide/12_sql_to_redis_queries.ipynb +++ b/docs/user_guide/12_sql_to_redis_queries.ipynb @@ -5,13 +5,29 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# SQLQuery class\n", + "# Write SQL Queries for Redis\n", "\n", - "It may arise that you want to use SQL-like queries to interact with your Redis vector database. While Redis does not natively support SQL, the `redisvl` library provides a `SQLQuery` class that allows you to write SQL-like queries that are automatically translated into Redis queries.\n", + "While Redis does not natively support SQL, RedisVL provides a `SQLQuery` class that translates SQL-like queries into Redis queries.\n", "\n", - "The `SQLQuery` class is a wrapper around the [`sql-redis`](https://pypi.org/project/sql-redis/) package, which provides a SQL-to-Redis query translator. The `sql-redis` package is not installed by default with `redisvl`, so you will need to install with the optional syntax:\n", + "The `SQLQuery` class wraps the [`sql-redis`](https://pypi.org/project/sql-redis/) package. This package is not installed by default, so install it with:\n", "\n", - "`pip install redisvl[sql-redis]` or, if running locally, you can `uv sync --all-extras --all-groups`" + "```bash\n", + "pip install redisvl[sql-redis]\n", + "```\n", + "\n", + "## Prerequisites\n", + "\n", + "Before you begin, ensure you have:\n", + "- Installed RedisVL with SQL support: `pip install redisvl[sql-redis]`\n", + "- A running Redis instance ([Redis 8+](https://redis.io/downloads/) or [Redis Cloud](https://redis.io/cloud))\n", + "\n", + "## What You'll Learn\n", + "\n", + "By the end of this guide, you will be able to:\n", + "- Write SQL-like queries for Redis using `SQLQuery`\n", + "- Translate SELECT, WHERE, and ORDER BY clauses to Redis queries\n", + "- Combine SQL queries with vector search\n", + "- Use aggregate functions and grouping" ] }, { @@ -23,9 +39,25 @@ }, { "cell_type": "code", - "execution_count": 83, - "metadata": {}, - "outputs": [], + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:01.542482Z", + "iopub.status.busy": "2026-02-16T15:20:01.542270Z", + "iopub.status.idle": "2026-02-16T15:20:19.311130Z", + "shell.execute_reply": "2026-02-16T15:20:19.310567Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/.venv/lib/python3.13/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], "source": [ "from redisvl.utils.vectorize import HFTextVectorizer\n", "\n", @@ -67,8 +99,15 @@ }, { "cell_type": "code", - "execution_count": 84, - "metadata": {}, + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:19.312894Z", + "iopub.status.busy": "2026-02-16T15:20:19.312512Z", + "iopub.status.idle": "2026-02-16T15:20:19.621061Z", + "shell.execute_reply": "2026-02-16T15:20:19.620563Z" + } + }, "outputs": [], "source": [ "data = [\n", @@ -139,8 +178,15 @@ }, { "cell_type": "code", - "execution_count": 85, - "metadata": {}, + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:19.622451Z", + "iopub.status.busy": "2026-02-16T15:20:19.622366Z", + "iopub.status.idle": "2026-02-16T15:20:19.630721Z", + "shell.execute_reply": "2026-02-16T15:20:19.630403Z" + } + }, "outputs": [], "source": [ "from redisvl.index import SearchIndex\n", @@ -161,8 +207,15 @@ }, { "cell_type": "code", - "execution_count": 86, - "metadata": {}, + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:19.632020Z", + "iopub.status.busy": "2026-02-16T15:20:19.631934Z", + "iopub.status.idle": "2026-02-16T15:20:19.633821Z", + "shell.execute_reply": "2026-02-16T15:20:19.633429Z" + } + }, "outputs": [], "source": [ "index = SearchIndex.from_dict(schema, redis_url=\"redis://localhost:6379\", validate_on_load=True)" @@ -179,8 +232,15 @@ }, { "cell_type": "code", - "execution_count": 87, - "metadata": {}, + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:19.634818Z", + "iopub.status.busy": "2026-02-16T15:20:19.634741Z", + "iopub.status.idle": "2026-02-16T15:20:19.640648Z", + "shell.execute_reply": "2026-02-16T15:20:19.640244Z" + } + }, "outputs": [], "source": [ "index.create(overwrite=True, drop=True)" @@ -200,14 +260,21 @@ }, { "cell_type": "code", - "execution_count": 88, - "metadata": {}, + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:19.641629Z", + "iopub.status.busy": "2026-02-16T15:20:19.641563Z", + "iopub.status.idle": "2026-02-16T15:20:19.751366Z", + "shell.execute_reply": "2026-02-16T15:20:19.750887Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['user_simple_docs:01KGJDNVDAZ9A6XY69Q6BCRMX5', 'user_simple_docs:01KGJDNVE024SKZB3804R8B6C3', 'user_simple_docs:01KGJDNVEKW1BV836X4926K7S3', 'user_simple_docs:01KGJDNVF62TBDR9Y9V4WZ59ZG', 'user_simple_docs:01KGJDNVFS0BXM7GF6DA66JHSN']\n" + "['user_simple_docs:01KHKJGG26AR3VW2RJA381R8YK', 'user_simple_docs:01KHKJGG2R8EZP6H15MG1V4E53', 'user_simple_docs:01KHKJGG369F5R0R51PW2HP8MV', 'user_simple_docs:01KHKJGG3MGVPAZ6XEQVEWXZFC', 'user_simple_docs:01KHKJGG44ZEKJVRQJ0EF72PV7']\n" ] } ], @@ -229,8 +296,15 @@ }, { "cell_type": "code", - "execution_count": 89, - "metadata": {}, + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:19.752548Z", + "iopub.status.busy": "2026-02-16T15:20:19.752471Z", + "iopub.status.idle": "2026-02-16T15:20:19.754355Z", + "shell.execute_reply": "2026-02-16T15:20:19.753935Z" + } + }, "outputs": [], "source": [ "from redisvl.query import SQLQuery\n", @@ -253,8 +327,15 @@ }, { "cell_type": "code", - "execution_count": 90, - "metadata": {}, + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:19.755445Z", + "iopub.status.busy": "2026-02-16T15:20:19.755366Z", + "iopub.status.idle": "2026-02-16T15:20:20.018643Z", + "shell.execute_reply": "2026-02-16T15:20:20.018223Z" + } + }, "outputs": [ { "data": { @@ -262,7 +343,7 @@ "'FT.SEARCH user_simple \"@age:[(17 +inf]\" RETURN 4 user region job age'" ] }, - "execution_count": 90, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -280,8 +361,15 @@ }, { "cell_type": "code", - "execution_count": 91, - "metadata": {}, + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.019728Z", + "iopub.status.busy": "2026-02-16T15:20:20.019644Z", + "iopub.status.idle": "2026-02-16T15:20:20.026215Z", + "shell.execute_reply": "2026-02-16T15:20:20.025841Z" + } + }, "outputs": [ { "data": { @@ -296,7 +384,7 @@ " {'user': 'stacy', 'region': 'us-west', 'job': 'project manager', 'age': '61'}]" ] }, - "execution_count": 91, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -317,8 +405,15 @@ }, { "cell_type": "code", - "execution_count": 92, - "metadata": {}, + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.027232Z", + "iopub.status.busy": "2026-02-16T15:20:20.027154Z", + "iopub.status.idle": "2026-02-16T15:20:20.036830Z", + "shell.execute_reply": "2026-02-16T15:20:20.036450Z" + } + }, "outputs": [ { "name": "stdout", @@ -337,7 +432,7 @@ " {'user': 'stacy', 'region': 'us-west', 'job': 'project manager', 'age': '61'}]" ] }, - "execution_count": 92, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -349,8 +444,6 @@ " WHERE age > 17 and region = 'us-west'\n", "\"\"\"\n", "\n", - "# could maybe be nice to set a connection string at the class level\n", - "# this would deviate from our other query like classes though so thinking on it\n", "sql_query = SQLQuery(sql_str)\n", "redis_query = sql_query.redis_query_string(redis_url=\"redis://localhost:6379\")\n", "print(\"Resulting redis query: \", redis_query)\n", @@ -360,8 +453,15 @@ }, { "cell_type": "code", - "execution_count": 93, - "metadata": {}, + "execution_count": 11, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.037744Z", + "iopub.status.busy": "2026-02-16T15:20:20.037670Z", + "iopub.status.idle": "2026-02-16T15:20:20.047532Z", + "shell.execute_reply": "2026-02-16T15:20:20.047144Z" + } + }, "outputs": [ { "name": "stdout", @@ -382,7 +482,7 @@ " {'user': 'mary', 'region': 'us-central', 'job': 'doctor', 'age': '24'}]" ] }, - "execution_count": 93, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -403,8 +503,15 @@ }, { "cell_type": "code", - "execution_count": 94, - "metadata": {}, + "execution_count": 12, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.048481Z", + "iopub.status.busy": "2026-02-16T15:20:20.048419Z", + "iopub.status.idle": "2026-02-16T15:20:20.057250Z", + "shell.execute_reply": "2026-02-16T15:20:20.056891Z" + } + }, "outputs": [ { "name": "stdout", @@ -423,7 +530,7 @@ " {'user': 'bill', 'region': 'us-central', 'job': 'engineer', 'age': '54'}]" ] }, - "execution_count": 94, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -436,8 +543,6 @@ " WHERE job IN ('software engineer', 'engineer', 'pancake tester')\n", " \"\"\"\n", "\n", - "# could maybe be nice to set a connection string at the class level\n", - "# this would deviate from our other query like classes though so thinking on it\n", "sql_query = SQLQuery(sql_str)\n", "redis_query = sql_query.redis_query_string(redis_url=\"redis://localhost:6379\")\n", "print(\"Resulting redis query: \", redis_query)\n", @@ -458,8 +563,15 @@ }, { "cell_type": "code", - "execution_count": 95, - "metadata": {}, + "execution_count": 13, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.058215Z", + "iopub.status.busy": "2026-02-16T15:20:20.058144Z", + "iopub.status.idle": "2026-02-16T15:20:20.067897Z", + "shell.execute_reply": "2026-02-16T15:20:20.067471Z" + } + }, "outputs": [ { "name": "stdout", @@ -478,7 +590,7 @@ " 'age': '54'}]" ] }, - "execution_count": 95, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -491,8 +603,6 @@ " WHERE job_description = 'sci*'\n", "\"\"\"\n", "\n", - "# could maybe be nice to set a connection string at the class level\n", - "# this would deviate from our other query like classes though so thinking on it\n", "sql_query = SQLQuery(sql_str)\n", "redis_query = sql_query.redis_query_string(redis_url=\"redis://localhost:6379\")\n", "print(\"Resulting redis query: \", redis_query)\n", @@ -502,8 +612,15 @@ }, { "cell_type": "code", - "execution_count": 96, - "metadata": {}, + "execution_count": 14, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.068791Z", + "iopub.status.busy": "2026-02-16T15:20:20.068717Z", + "iopub.status.idle": "2026-02-16T15:20:20.076915Z", + "shell.execute_reply": "2026-02-16T15:20:20.076527Z" + } + }, "outputs": [ { "name": "stdout", @@ -527,7 +644,7 @@ " 'age': '27'}]" ] }, - "execution_count": 96, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -540,8 +657,6 @@ " WHERE job_description = '*care'\n", "\"\"\"\n", "\n", - "# could maybe be nice to set a connection string at the class level\n", - "# this would deviate from our other query like classes though so thinking on it\n", "sql_query = SQLQuery(sql_str)\n", "redis_query = sql_query.redis_query_string(redis_url=\"redis://localhost:6379\")\n", "print(\"Resulting redis query: \", redis_query)\n", @@ -551,8 +666,15 @@ }, { "cell_type": "code", - "execution_count": 97, - "metadata": {}, + "execution_count": 15, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.077848Z", + "iopub.status.busy": "2026-02-16T15:20:20.077786Z", + "iopub.status.idle": "2026-02-16T15:20:20.085797Z", + "shell.execute_reply": "2026-02-16T15:20:20.085426Z" + } + }, "outputs": [ { "name": "stdout", @@ -571,7 +693,7 @@ " 'age': '24'}]" ] }, - "execution_count": 97, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -584,8 +706,6 @@ " WHERE job_description = '%diagnose%'\n", "\"\"\"\n", "\n", - "# could maybe be nice to set a connection string at the class level\n", - "# this would deviate from our other query like classes though so thinking on it\n", "sql_query = SQLQuery(sql_str)\n", "redis_query = sql_query.redis_query_string(redis_url=\"redis://localhost:6379\")\n", "print(\"Resulting redis query: \", redis_query)\n", @@ -595,8 +715,15 @@ }, { "cell_type": "code", - "execution_count": 98, - "metadata": {}, + "execution_count": 16, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.086696Z", + "iopub.status.busy": "2026-02-16T15:20:20.086635Z", + "iopub.status.idle": "2026-02-16T15:20:20.094743Z", + "shell.execute_reply": "2026-02-16T15:20:20.094356Z" + } + }, "outputs": [ { "name": "stdout", @@ -615,7 +742,7 @@ " 'age': '27'}]" ] }, - "execution_count": 98, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -628,8 +755,6 @@ " WHERE job_description = 'healthcare including'\n", "\"\"\"\n", "\n", - "# could maybe be nice to set a connection string at the class level\n", - "# this would deviate from our other query like classes though so thinking on it\n", "sql_query = SQLQuery(sql_str)\n", "redis_query = sql_query.redis_query_string(redis_url=\"redis://localhost:6379\")\n", "print(\"Resulting redis query: \", redis_query)\n", @@ -639,8 +764,15 @@ }, { "cell_type": "code", - "execution_count": 99, - "metadata": {}, + "execution_count": 17, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.095658Z", + "iopub.status.busy": "2026-02-16T15:20:20.095592Z", + "iopub.status.idle": "2026-02-16T15:20:20.103917Z", + "shell.execute_reply": "2026-02-16T15:20:20.103604Z" + } + }, "outputs": [ { "name": "stdout", @@ -649,6 +781,14 @@ "Resulting redis query: FT.SEARCH user_simple \"@job_description:\"diagnosing treating\"\" RETURN 5 user region job job_description age\n" ] }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/.venv/lib/python3.13/site-packages/sql_redis/translator.py:136: UserWarning: Stopwords ['and'] were removed from phrase search 'diagnosing and treating'. By default, Redis does not index stopwords. To include stopwords in your index, create it with STOPWORDS 0.\n", + " return self._query_builder.build_text_condition(\n" + ] + }, { "data": { "text/plain": [ @@ -659,7 +799,7 @@ " 'age': '27'}]" ] }, - "execution_count": 99, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -672,8 +812,6 @@ " WHERE job_description = 'diagnosing and treating'\n", "\"\"\"\n", "\n", - "# could maybe be nice to set a connection string at the class level\n", - "# this would deviate from our other query like classes though so thinking on it\n", "sql_query = SQLQuery(sql_str)\n", "redis_query = sql_query.redis_query_string(redis_url=\"redis://localhost:6379\")\n", "print(\"Resulting redis query: \", redis_query)\n", @@ -683,8 +821,15 @@ }, { "cell_type": "code", - "execution_count": 100, - "metadata": {}, + "execution_count": 18, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.104811Z", + "iopub.status.busy": "2026-02-16T15:20:20.104747Z", + "iopub.status.idle": "2026-02-16T15:20:20.112841Z", + "shell.execute_reply": "2026-02-16T15:20:20.112495Z" + } + }, "outputs": [ { "name": "stdout", @@ -699,7 +844,7 @@ "[{'user': 'bill', 'region': 'us-central', 'job': 'engineer', 'age': '54'}]" ] }, - "execution_count": 100, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -711,8 +856,6 @@ " WHERE age BETWEEN 40 and 60\n", " \"\"\"\n", "\n", - "# could maybe be nice to set a connection string at the class level\n", - "# this would deviate from our other query like classes though so thinking on it\n", "sql_query = SQLQuery(sql_str)\n", "redis_query = sql_query.redis_query_string(redis_url=\"redis://localhost:6379\")\n", "print(\"Resulting redis query: \", redis_query)\n", @@ -726,13 +869,20 @@ "source": [ "### Aggregations\n", "\n", - "See docs for redis supported reducer functions: [https://redis.io/docs/latest/develop/ai/search-and-query/advanced-concepts/aggregations/#supported-groupby-reducers](docs)." + "See docs for redis supported reducer functions: [docs](https://redis.io/docs/latest/develop/ai/search-and-query/advanced-concepts/aggregations/#supported-groupby-reducers)." ] }, { "cell_type": "code", - "execution_count": 101, - "metadata": {}, + "execution_count": 19, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.113767Z", + "iopub.status.busy": "2026-02-16T15:20:20.113705Z", + "iopub.status.idle": "2026-02-16T15:20:20.123216Z", + "shell.execute_reply": "2026-02-16T15:20:20.122829Z" + } + }, "outputs": [ { "name": "stdout", @@ -776,7 +926,7 @@ " 'quantile_age': '27'}]" ] }, - "execution_count": 101, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -814,8 +964,15 @@ }, { "cell_type": "code", - "execution_count": 102, - "metadata": {}, + "execution_count": 20, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.124186Z", + "iopub.status.busy": "2026-02-16T15:20:20.124113Z", + "iopub.status.idle": "2026-02-16T15:20:20.211719Z", + "shell.execute_reply": "2026-02-16T15:20:20.211380Z" + } + }, "outputs": [ { "name": "stdout", @@ -827,19 +984,19 @@ { "data": { "text/plain": [ - "[{'vector_distance': '0.823510587215',\n", + "[{'vector_distance': '0.82351064682',\n", " 'user': 'bill',\n", " 'job': 'engineer',\n", " 'job_description': 'Applies scientific and mathematical principles to solve technical problems.'},\n", - " {'vector_distance': '0.965160429478',\n", + " {'vector_distance': '0.965160369873',\n", " 'user': 'john',\n", " 'job': 'software engineer',\n", " 'job_description': 'Designs, develops, and maintains software applications and systems.'},\n", - " {'vector_distance': '1.00401365757',\n", + " {'vector_distance': '1.00401353836',\n", " 'user': 'mary',\n", " 'job': 'doctor',\n", " 'job_description': 'Diagnoses and treats illnesses, injuries, and other medical conditions in the healthcare field.'},\n", - " {'vector_distance': '1.0062687397',\n", + " {'vector_distance': '1.00626885891',\n", " 'user': 'stacy',\n", " 'job': 'project manager',\n", " 'job_description': 'Plans, organizes, and oversees projects from inception to completion.'},\n", @@ -849,7 +1006,7 @@ " 'job_description': 'Provides oral healthcare including diagnosing and treating teeth and gum issues.'}]" ] }, - "execution_count": 102, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -873,8 +1030,15 @@ }, { "cell_type": "code", - "execution_count": 103, - "metadata": {}, + "execution_count": 21, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.212904Z", + "iopub.status.busy": "2026-02-16T15:20:20.212823Z", + "iopub.status.idle": "2026-02-16T15:20:20.242415Z", + "shell.execute_reply": "2026-02-16T15:20:20.241988Z" + } + }, "outputs": [ { "name": "stdout", @@ -886,11 +1050,11 @@ { "data": { "text/plain": [ - "[{'vector_distance': '0.823510587215', 'user': 'bill', 'region': 'us-central'},\n", - " {'vector_distance': '1.00401365757', 'user': 'mary', 'region': 'us-central'}]" + "[{'vector_distance': '0.82351064682', 'user': 'bill', 'region': 'us-central'},\n", + " {'vector_distance': '1.00401353836', 'user': 'mary', 'region': 'us-central'}]" ] }, - "execution_count": 103, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -917,76 +1081,46 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Cleanup" + "## Next Steps\n", + "\n", + "Now that you understand SQL queries for Redis, explore these related guides:\n", + "\n", + "- [Use Advanced Query Types](11_advanced_queries.ipynb) - Learn about TextQuery, HybridQuery, and MultiVectorQuery\n", + "- [Query and Filter Data](02_complex_filtering.ipynb) - Apply filters using native RedisVL query syntax\n", + "- [Getting Started](01_getting_started.ipynb) - Review the basics of RedisVL indexes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Below we will clean up after our work. First, you can flush all data from Redis associated with the index by\n", - "using the `.clear()` method. This will leave the secondary index in place for future insertions or updates.\n", + "## Cleanup\n", "\n", - "But if you want to clean up everything, including the index, just use `.delete()`\n", - "which will by default remove the index AND the underlying data." - ] - }, - { - "cell_type": "code", - "execution_count": 104, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "5" - ] - }, - "execution_count": 104, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Clear all data from Redis associated with the index\n", - "index.clear()" + "To remove all data from Redis associated with the index, use the `.clear()` method. This leaves the index in place for future insertions or updates.\n", + "\n", + "To remove everything including the index, use `.delete()` which removes both the index and the underlying data." ] }, { "cell_type": "code", - "execution_count": 105, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 105, - "metadata": {}, - "output_type": "execute_result" + "execution_count": 22, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:20:20.243553Z", + "iopub.status.busy": "2026-02-16T15:20:20.243464Z", + "iopub.status.idle": "2026-02-16T15:20:20.245944Z", + "shell.execute_reply": "2026-02-16T15:20:20.245506Z" } - ], - "source": [ - "# But the index is still in place\n", - "index.exists()" - ] - }, - { - "cell_type": "code", - "execution_count": 106, - "metadata": {}, + }, "outputs": [], "source": [ - "# Remove / delete the index in its entirety\n", "index.delete()" ] } ], "metadata": { "kernelspec": { - "display_name": "redisvl", + "display_name": ".venv", "language": "python", "name": "python3" }, @@ -1000,7 +1134,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.13.2" } }, "nbformat": 4, diff --git a/docs/overview/cli.ipynb b/docs/user_guide/cli.ipynb similarity index 76% rename from docs/overview/cli.ipynb rename to docs/user_guide/cli.ipynb index cf49789b..a62f2e71 100644 --- a/docs/overview/cli.ipynb +++ b/docs/user_guide/cli.ipynb @@ -18,16 +18,15 @@ { "cell_type": "code", "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "11:20:38 [RedisVL] INFO RedisVL version 0.8.2\n" - ] + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:57:47.970456Z", + "iopub.status.busy": "2026-02-16T15:57:47.970355Z", + "iopub.status.idle": "2026-02-16T15:57:50.209307Z", + "shell.execute_reply": "2026-02-16T15:57:50.208518Z" } - ], + }, + "outputs": [], "source": [ "# First, see if the rvl tool is installed\n", "!rvl version" @@ -65,8 +64,15 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": {}, + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:57:50.211400Z", + "iopub.status.busy": "2026-02-16T15:57:50.211260Z", + "iopub.status.idle": "2026-02-16T15:57:50.214640Z", + "shell.execute_reply": "2026-02-16T15:57:50.214131Z" + } + }, "outputs": [ { "name": "stdout", @@ -99,14 +105,21 @@ }, { "cell_type": "code", - "execution_count": 4, - "metadata": {}, + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:57:50.215938Z", + "iopub.status.busy": "2026-02-16T15:57:50.215853Z", + "iopub.status.idle": "2026-02-16T15:57:52.468976Z", + "shell.execute_reply": "2026-02-16T15:57:52.468393Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "12:42:45 [RedisVL] INFO Index created successfully\n" + "Index created successfully\n" ] } ], @@ -117,15 +130,22 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": {}, + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:57:52.470958Z", + "iopub.status.busy": "2026-02-16T15:57:52.470816Z", + "iopub.status.idle": "2026-02-16T15:57:54.724077Z", + "shell.execute_reply": "2026-02-16T15:57:54.723468Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "12:42:47 [RedisVL] INFO Indices:\n", - "12:42:47 [RedisVL] INFO 1. vectorizers\n" + "Indices:\n", + "1. vectorizers\n" ] } ], @@ -136,8 +156,15 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": {}, + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:57:54.726015Z", + "iopub.status.busy": "2026-02-16T15:57:54.725868Z", + "iopub.status.idle": "2026-02-16T15:57:56.975438Z", + "shell.execute_reply": "2026-02-16T15:57:56.974905Z" + } + }, "outputs": [ { "name": "stdout", @@ -168,14 +195,21 @@ }, { "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:57:56.976821Z", + "iopub.status.busy": "2026-02-16T15:57:56.976717Z", + "iopub.status.idle": "2026-02-16T15:57:59.185174Z", + "shell.execute_reply": "2026-02-16T15:57:59.184511Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "12:42:54 [RedisVL] INFO Index deleted successfully\n" + "Index deleted successfully\n" ] } ], @@ -186,14 +220,21 @@ }, { "cell_type": "code", - "execution_count": 8, - "metadata": {}, + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:57:59.187123Z", + "iopub.status.busy": "2026-02-16T15:57:59.186978Z", + "iopub.status.idle": "2026-02-16T15:58:01.436862Z", + "shell.execute_reply": "2026-02-16T15:58:01.436286Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "12:42:56 [RedisVL] INFO Indices:\n" + "Indices:\n" ] } ], @@ -213,14 +254,21 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": {}, + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:58:01.438931Z", + "iopub.status.busy": "2026-02-16T15:58:01.438784Z", + "iopub.status.idle": "2026-02-16T15:58:03.645130Z", + "shell.execute_reply": "2026-02-16T15:58:03.644431Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "12:42:59 [RedisVL] INFO Index created successfully\n" + "Index created successfully\n" ] } ], @@ -232,15 +280,22 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": {}, + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:58:03.646705Z", + "iopub.status.busy": "2026-02-16T15:58:03.646576Z", + "iopub.status.idle": "2026-02-16T15:58:06.394601Z", + "shell.execute_reply": "2026-02-16T15:58:06.394088Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "12:43:01 [RedisVL] INFO Indices:\n", - "12:43:01 [RedisVL] INFO 1. vectorizers\n" + "Indices:\n", + "1. vectorizers\n" ] } ], @@ -251,8 +306,15 @@ }, { "cell_type": "code", - "execution_count": 11, - "metadata": {}, + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:58:06.396648Z", + "iopub.status.busy": "2026-02-16T15:58:06.396507Z", + "iopub.status.idle": "2026-02-16T15:58:08.648945Z", + "shell.execute_reply": "2026-02-16T15:58:08.647911Z" + } + }, "outputs": [ { "name": "stdout", @@ -271,9 +333,9 @@ "โ”‚ hash_indexing_failures โ”‚ 0 โ”‚\n", "โ”‚ number_of_uses โ”‚ 1 โ”‚\n", "โ”‚ bytes_per_record_avg โ”‚ nan โ”‚\n", - "โ”‚ doc_table_size_mb โ”‚ 0 โ”‚\n", + "โ”‚ doc_table_size_mb โ”‚ 0.00769805 โ”‚\n", "โ”‚ inverted_sz_mb โ”‚ 0 โ”‚\n", - "โ”‚ key_table_size_mb โ”‚ 0 โ”‚\n", + "โ”‚ key_table_size_mb โ”‚ 2.28881835 โ”‚\n", "โ”‚ offset_bits_per_record_avg โ”‚ nan โ”‚\n", "โ”‚ offset_vectors_sz_mb โ”‚ 0 โ”‚\n", "โ”‚ offsets_per_term_avg โ”‚ nan โ”‚\n", @@ -281,7 +343,7 @@ "โ”‚ sortable_values_size_mb โ”‚ 0 โ”‚\n", "โ”‚ total_indexing_time โ”‚ 0 โ”‚\n", "โ”‚ total_inverted_index_blocks โ”‚ 0 โ”‚\n", - "โ”‚ vector_index_sz_mb โ”‚ 0.00818634 โ”‚\n", + "โ”‚ vector_index_sz_mb โ”‚ 0 โ”‚\n", "โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ\n" ] } @@ -318,15 +380,22 @@ }, { "cell_type": "code", - "execution_count": 12, - "metadata": {}, + "execution_count": 11, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:58:08.651332Z", + "iopub.status.busy": "2026-02-16T15:58:08.651164Z", + "iopub.status.idle": "2026-02-16T15:58:10.874716Z", + "shell.execute_reply": "2026-02-16T15:58:10.874011Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "12:43:06 [RedisVL] INFO Indices:\n", - "12:43:06 [RedisVL] INFO 1. vectorizers\n" + "Indices:\n", + "1. vectorizers\n" ] } ], @@ -346,8 +415,15 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, + "execution_count": 12, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:58:10.876537Z", + "iopub.status.busy": "2026-02-16T15:58:10.876406Z", + "iopub.status.idle": "2026-02-16T15:58:13.099937Z", + "shell.execute_reply": "2026-02-16T15:58:13.099303Z" + } + }, "outputs": [], "source": [ "# connect to rediss://jane_doe:password123@localhost:6379\n", @@ -357,13 +433,20 @@ { "cell_type": "code", "execution_count": 13, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2026-02-16T15:58:13.101500Z", + "iopub.status.busy": "2026-02-16T15:58:13.101372Z", + "iopub.status.idle": "2026-02-16T15:58:15.343307Z", + "shell.execute_reply": "2026-02-16T15:58:15.342681Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "12:43:09 [RedisVL] INFO Index deleted successfully\n" + "Index deleted successfully\n" ] } ], @@ -374,7 +457,7 @@ ], "metadata": { "kernelspec": { - "display_name": "redisvl-56gG2io_-py3.11", + "display_name": ".venv", "language": "python", "name": "python3" }, @@ -388,7 +471,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.13.2" } }, "nbformat": 4, diff --git a/docs/user_guide/how_to_guides/index.md b/docs/user_guide/how_to_guides/index.md new file mode 100644 index 00000000..73b9f8d3 --- /dev/null +++ b/docs/user_guide/how_to_guides/index.md @@ -0,0 +1,71 @@ +# How-To Guides + +How-to guides are **task-oriented** recipes that help you accomplish specific goals. Each guide focuses on solving a particular problem and can be completed independently. + +::::{grid} 2 +:gutter: 3 + +:::{grid-item-card} ๐Ÿค– LLM Extensions + +- [Cache LLM Responses](../03_llmcache.ipynb) -- semantic caching to reduce costs and latency +- [Manage LLM Message History](../07_message_history.ipynb) -- persistent chat history with relevancy retrieval +- [Route Queries with SemanticRouter](../08_semantic_router.ipynb) -- classify intents and route queries +::: + +:::{grid-item-card} ๐Ÿ” Querying + +- [Query and Filter Data](../02_complex_filtering.ipynb) -- combine tag, numeric, geo, and text filters +- [Use Advanced Query Types](../11_advanced_queries.ipynb) -- hybrid, multi-vector, range, and text queries +- [Write SQL Queries for Redis](../12_sql_to_redis_queries.ipynb) -- translate SQL to Redis query syntax +::: + +:::{grid-item-card} ๐Ÿงฎ Embeddings + +- [Create Embeddings with Vectorizers](../04_vectorizers.ipynb) -- OpenAI, Cohere, HuggingFace, and more +- [Cache Embeddings](../10_embeddings_cache.ipynb) -- reduce costs by caching embedding vectors +::: + +:::{grid-item-card} โšก Optimization + +- [Rerank Search Results](../06_rerankers.ipynb) -- improve relevance with cross-encoders and rerankers +- [Optimize Indexes with SVS-VAMANA](../09_svs_vamana.ipynb) -- graph-based vector search with compression +::: + +:::{grid-item-card} ๐Ÿ’พ Storage + +- [Choose a Storage Type](../05_hash_vs_json.ipynb) -- Hash vs JSON formats and nested data +::: + +:::: + +## Quick Reference + +| I want to... | Guide | +|--------------|-------| +| Cache LLM responses | [Cache LLM Responses](../03_llmcache.ipynb) | +| Store chat history | [Manage LLM Message History](../07_message_history.ipynb) | +| Route queries by intent | [Route Queries with SemanticRouter](../08_semantic_router.ipynb) | +| Filter results by multiple criteria | [Query and Filter Data](../02_complex_filtering.ipynb) | +| Use hybrid or multi-vector queries | [Use Advanced Query Types](../11_advanced_queries.ipynb) | +| Translate SQL to Redis | [Write SQL Queries for Redis](../12_sql_to_redis_queries.ipynb) | +| Choose an embedding model | [Create Embeddings with Vectorizers](../04_vectorizers.ipynb) | +| Speed up embedding generation | [Cache Embeddings](../10_embeddings_cache.ipynb) | +| Improve search accuracy | [Rerank Search Results](../06_rerankers.ipynb) | +| Optimize index performance | [Optimize Indexes with SVS-VAMANA](../09_svs_vamana.ipynb) | +| Decide on storage format | [Choose a Storage Type](../05_hash_vs_json.ipynb) | + +```{toctree} +:hidden: + +Cache LLM Responses <../03_llmcache> +Manage LLM Message History <../07_message_history> +Route Queries with SemanticRouter <../08_semantic_router> +Query and Filter Data <../02_complex_filtering> +Create Embeddings with Vectorizers <../04_vectorizers> +Choose a Storage Type <../05_hash_vs_json> +Rerank Search Results <../06_rerankers> +Optimize Indexes with SVS-VAMANA <../09_svs_vamana> +Cache Embeddings <../10_embeddings_cache> +Use Advanced Query Types <../11_advanced_queries> +Write SQL Queries for Redis <../12_sql_to_redis_queries> +``` diff --git a/docs/user_guide/index.md b/docs/user_guide/index.md index e895776b..5d2cf6df 100644 --- a/docs/user_guide/index.md +++ b/docs/user_guide/index.md @@ -2,26 +2,74 @@ myst: html_meta: "description lang=en": | - User guides for RedisVL + User guides for RedisVL - Learn how to build AI applications with Redis as your vector database --- -# User Guides -User guides provide helpful resources for using RedisVL and its different components. +# Guides + +Welcome to the RedisVL guides! Whether you're just getting started or building advanced AI applications, these guides will help you make the most of Redis as your vector database. + +::::{grid} 2 +:gutter: 3 + +:::{grid-item-card} ๐Ÿ“ฆ Installation +:link: installation +:link-type: doc + +**Set up RedisVL.** Install the library and configure your Redis instance for vector search. + ++++ +pip install โ€ข Redis Cloud โ€ข Docker +::: + +:::{grid-item-card} ๐Ÿš€ Getting Started +:link: 01_getting_started +:link-type: doc + +**New to RedisVL?** Start here to learn the basics and build your first vector search application in minutes. + ++++ +Schema โ†’ Index โ†’ Load โ†’ Query +::: + +:::{grid-item-card} ๐Ÿ› ๏ธ How-To Guides +:link: how_to_guides/index +:link-type: doc + +**Solve specific problems.** Task-oriented recipes for LLM extensions, querying, embeddings, optimization, and storage. + ++++ +LLM Caching โ€ข Filtering โ€ข Vectorizers โ€ข Reranking +::: + +:::{grid-item-card} ๐Ÿ’ป CLI Reference +:link: cli +:link-type: doc + +**Command-line tools.** Manage indices, inspect stats, and work with schemas using the `rvl` CLI. + ++++ +rvl index โ€ข rvl stats โ€ข Schema YAML +::: + +:::{grid-item-card} ๐Ÿ’ก Use Cases +:link: use_cases/index +:link-type: doc + +**Apply RedisVL to real-world problems.** See which guides map to your use case. + ++++ +Agent Context โ€ข Agent Optimization โ€ข Search โ€ข RecSys +::: + +:::: ```{toctree} -:caption: User Guides :maxdepth: 2 -01_getting_started -02_complex_filtering -03_llmcache -04_vectorizers -05_hash_vs_json -06_rerankers -07_message_history -08_semantic_router -09_svs_vamana -10_embeddings_cache -11_advanced_queries -12_sql_to_redis_queries -``` \ No newline at end of file +Installation +Getting Started <01_getting_started> +how_to_guides/index +CLI Reference +use_cases/index +``` diff --git a/docs/overview/installation.md b/docs/user_guide/installation.md similarity index 84% rename from docs/overview/installation.md rename to docs/user_guide/installation.md index 331b31aa..f4994558 100644 --- a/docs/overview/installation.md +++ b/docs/user_guide/installation.md @@ -51,29 +51,26 @@ $ pip install -e . ## Installing Redis -RedisVL requires a distribution of Redis that supports the [Search and Query](https://redis.com/modules/redis-search/) capability of which there are 3: - -offering +RedisVL requires a distribution of Redis that supports the [Search and Query](https://redis.com/modules/redis-search/) capability. There are several options: 1. [Redis Cloud](https://redis.io/cloud), a fully managed cloud offering -2. [Redis Stack](https://redis.io/docs/getting-started/install-stack/docker/), a local docker image for testing and development -3. [Redis Enterprise](https://redis.com/redis-enterprise/), a commercial self-hosted +2. [Redis 8+ (Docker)](https://redis.io/downloads/), for local development and testing +3. [Redis Enterprise](https://redis.com/redis-enterprise/), a commercial self-hosted option ### Redis Cloud Redis Cloud is the easiest way to get started with RedisVL. You can sign up for a free account [here](https://redis.io/cloud). Make sure to have the `Search and Query` capability enabled when creating your database. -### Redis Stack (local development) +### Redis 8+ (local development) -For local development and testing, Redis-Stack can be used. We recommend running Redis -in a docker container. To do so, run the following command: +For local development and testing, we recommend running Redis 8+ in a Docker container: ```bash -docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest +docker run -d --name redis -p 6379:6379 redis:latest ``` -This will also spin up the [Redis Insight GUI](https://redis.io/insight/) at `http://localhost:8001`. +Redis 8 includes built-in vector search capabilities. ### Redis Enterprise (self-hosted) diff --git a/docs/user_guide/schema.yaml b/docs/user_guide/schema.yaml index 32cf085d..8664d02b 100644 --- a/docs/user_guide/schema.yaml +++ b/docs/user_guide/schema.yaml @@ -1,3 +1,4 @@ + version: '0.1.0' index: @@ -13,4 +14,4 @@ fields: attrs: dims: 768 algorithm: flat - distance_metric: cosine \ No newline at end of file + distance_metric: cosine diff --git a/docs/user_guide/use_cases/index.md b/docs/user_guide/use_cases/index.md new file mode 100644 index 00000000..12180922 --- /dev/null +++ b/docs/user_guide/use_cases/index.md @@ -0,0 +1,40 @@ +# Use Cases + +RedisVL powers a wide range of AI applications. Here's how to apply its features to common use cases. + +::::{grid} 2 +:gutter: 3 + +:::{grid-item-card} ๐Ÿง  Agent Context +Provide agents with the right information at the right time. + +- **RAG** -- Retrieval-Augmented Generation with [vector search](../01_getting_started.ipynb) and [hybrid queries](../11_advanced_queries.ipynb) +- **Memory** -- Persistent [message history](../07_message_history.ipynb) across sessions +- **Context Engineering** -- Combine [filtering](../02_complex_filtering.ipynb), [reranking](../06_rerankers.ipynb), and [embeddings](../04_vectorizers.ipynb) to curate the optimal context window +::: + +:::{grid-item-card} โšก Agent Optimization +Reduce latency and cost for AI workloads. + +- **Semantic Caching** -- Cache LLM responses by meaning with [SemanticCache](../03_llmcache.ipynb) +- **Embeddings Caching** -- Avoid redundant embedding calls with [EmbeddingsCache](../10_embeddings_cache.ipynb) +- **Semantic Routing** -- Route queries to the right handler with [SemanticRouter](../08_semantic_router.ipynb) +::: + +:::{grid-item-card} ๐Ÿ” General Search +Build search experiences that understand meaning, not just keywords. + +- **Semantic Search** -- [Vector queries](../01_getting_started.ipynb) with [complex filtering](../02_complex_filtering.ipynb) +- **Hybrid Search** -- Combine keyword and vector search with [advanced query types](../11_advanced_queries.ipynb) +- **SQL Translation** -- Use familiar SQL syntax with [SQLQuery](../12_sql_to_redis_queries.ipynb) +::: + +:::{grid-item-card} ๐ŸŽฏ Personalization & RecSys +Drive engagement with personalized recommendations. + +- **User Similarity** -- Find similar users or items using [vector search](../01_getting_started.ipynb) +- **Real-Time Ranking** -- Combine vector similarity with [metadata filtering](../02_complex_filtering.ipynb) and [reranking](../06_rerankers.ipynb) +- **Multi-Signal Matching** -- Search across multiple embedding fields with [MultiVectorQuery](../11_advanced_queries.ipynb) +::: + +:::: diff --git a/redisvl/cli/index.py b/redisvl/cli/index.py index bc9f3947..6b188ffe 100644 --- a/redisvl/cli/index.py +++ b/redisvl/cli/index.py @@ -56,10 +56,11 @@ def create(self, args: Namespace): rvl index create -i | -s """ if not args.schema: - logger.error("Schema must be provided to create an index") + print("Schema must be provided to create an index") + exit(1) index = SearchIndex.from_yaml(args.schema, redis_url=create_redis_url(args)) index.create() - logger.info("Index created successfully") + print("Index created successfully") def info(self, args: Namespace): """Obtain information about an index. @@ -79,9 +80,9 @@ def listall(self, args: Namespace): redis_url = create_redis_url(args) conn = RedisConnectionFactory.get_redis_connection(redis_url=redis_url) indices = convert_bytes(conn.execute_command("FT._LIST")) - logger.info("Indices:") + print("Indices:") for i, index in enumerate(indices): - logger.info(str(i + 1) + ". " + index) + print(str(i + 1) + ". " + index) def delete(self, args: Namespace, drop=False): """Delete an index. @@ -91,7 +92,7 @@ def delete(self, args: Namespace, drop=False): """ index = self._connect_to_index(args) index.delete(drop=drop) - logger.info("Index deleted successfully") + print("Index deleted successfully") def destroy(self, args: Namespace): """Delete an index and the documents within it. @@ -107,10 +108,8 @@ def _connect_to_index(self, args: Namespace) -> SearchIndex: redis_url = create_redis_url(args) conn = RedisConnectionFactory.get_redis_connection(redis_url=redis_url) except ValueError: - logger.error( - "Must set REDIS_URL environment variable or provide host and port" - ) - exit(0) + print("Must set REDIS_URL environment variable or provide host and port") + exit(1) if args.index: schema = IndexSchema.from_dict({"index": {"name": args.index}}) @@ -118,8 +117,8 @@ def _connect_to_index(self, args: Namespace) -> SearchIndex: elif args.schema: index = SearchIndex.from_yaml(args.schema, redis_client=conn) else: - logger.error("Index name or schema must be provided") - exit(0) + print("Index name or schema must be provided") + exit(1) return index