redis-vl-python

redisMIT活跃维护

面向 Redis 的 AI 原生 Python 客户端,把向量检索、缓存和 RAG 所需的数据操作封装成简单接口,省去自己拼装底层命令。

Redis Vector Library. The AI-native Python client for Redis.

v0.31.0发布于 2026-11-06 09:05 UTC434star +1 / 7 天121fork同步于 2026-11-10 06:02 UTC

怎么上手

由 README 提炼,执行前请确认
pip install redisvl
docker run -d --name redis -p 6379:6379 redis:latest
硬件要求按 README 说明

README 未说明;仅要求 Python >= 3.10 和一个可连接的 Redis 部署(Docker 示例用 redis:latest,即 Redis 8+ 自带向量检索)

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

Redis 官方 AI 原生 Python 客户端,把向量检索、语义缓存和 LLM 记忆直接建在 Redis 上

面向 Redis 的 AI 原生 Python 客户端,把向量检索、缓存和 RAG 所需的数据操作封装成简单接口,省去自己拼装底层命令。

核心能力

  • 用 YAML 或字典定义 IndexSchema 管理索引与 CRUD
  • 支持向量相似度检索并叠加 tag、数值、地理等元数据过滤
  • 提供混合检索,融合语义与全文信号
  • 内置语义缓存、LLM 记忆与语义路由等 AI 扩展
  • 附带 rvl CLI 与 MCP Server 暴露已有索引给 MCP 客户端

容易踩的坑

需要 Redis 8+ 或 Redis Cloud/Enterprise 等支持向量检索的部署,普通旧版 Redis 不行;MCP 功能要额外装 pip install redisvl[mcp];Docker 示例默认映射 6379 端口,本地已有 Redis 会冲突

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.31.0
  1. v0.31.0最新正式版2026-11-06 · 2026-11-06 09:05 UTC

    RedisVL 0.31.0 adds Python 3.15 support, makes async paths that wrap a sync Redis client behave like a native async client, and changes how HybridQuery treats zero-valued combination parameters. Read the behaviour change below before upgrading if you set linear_alpha, rrf_constant or rrf_window to 0.

    Highlights

    Python 3.15 support

    RedisVL now supports Python 3.15, and every extra installs on it except where an upstream package's own Python bounds block it: voyageai on 3.15, and sql-redis on 3.14 and later. The mcp extra now requires beartype>=0.23.1. (#768, @vishal-bala)

    Sync clients converted to async keep their configuration

    SemanticCache, AsyncSearchIndex and the other async paths that accept a sync client now carry over more of that client's setup when they convert it:

    • TLS clients (Redis(ssl=True, ...)), unix-socket clients and custom SSLConnection subclasses now work. (#792, @Yarmoluk)
    • The client's retry policy is preserved, so the async client reconnects after a dropped connection. (#817, @Yarmoluk)

    Sentinel-managed clients, RedisCluster clients and clients with a sync-only setting such as OCSP validation now raise ValueError at conversion time, pointing you to redis_url. Previously they failed with TypeError on the first command.

    Behaviour change: zero-valued hybrid parameters are honoured

    HybridQuery previously dropped linear_alpha=0 and rrf_constant=0; it now sends them, so affected queries rank differently. The same applies to the MCP server's search.params.linear_text_weight: 0 and rrf_constant: 0 on native hybrid search. rrf_window=0 now returns a server error instead of being ignored. (#819, @hyeonsang010716)

    Other fixes

    • CohereTextVectorizer.aembed and aembed_many now make non-blocking calls through Cohere's async client. If you pass your own httpx_client, also pass async_httpx_client to keep async calls non-blocking. (#785, @Yarmoluk)
    • Normalised COSINE scores from VectorQuery, VectorRangeQuery, AggregateHybridQuery and MultiVectorQuery stay within [0, 1] when floating-point rounding produces a slightly negative distance. (#823, @limjoobin)
    • Existing SVS-VAMANA indexes created without compression now load. (#790, @itsrayeedscodespace)

    Dependencies

    • The fastmcp floor is raised to the oldest release that works with the MCP server. (#807, @vishal-bala)
    • Dependabot alerts in uv.lock are cleared and dev tooling moves to pytest 9. (#799, #813, @dependabot, @vishal-bala)

    Contributors

    Thanks to @Yarmoluk, @hyeonsang010716, @limjoobin and @itsrayeedscodespace for their contributions to this release, including first contributions from @hyeonsang010716 and @itsrayeedscodespace.

    Full changelog: https://github.com/redis/redis-vl-python/compare/v0.30.0...v0.31.0

  2. v0.30.02026-11-02 · 2026-11-02 09:36 UTC
    查看更新说明

    Release Notes

    perf: run SemanticCache.check() as KNN with a client-side threshold (FDE-85) (#754)

    SemanticCache.check() and acheck() run as a KNN query with the distance threshold applied client-side. Lookups with a selective filter expression take up to about a third less time, and unfiltered lookups take 2–3% longer.

    feat(mcp): serve async Python functions as MCP tools (#758, #759, #760, #761)

    The MCP server can now serve your own async Python functions as tools, called code tools. There are two ways to register one. If you run the server from your own process, decorate the function with server.code_tool(...). If you run rvl mcp, mark the function with @code_tool from redisvl.mcp, list its module under server.code_tool_modules and set server.allow_code_tools: true. That flag defaults to false because importing a module runs its code with the server's privileges, and each module must be importable by the server process.

    A function qualifies only if it takes a ToolContext as its first positional parameter, annotates its other parameters and has a description, either its docstring or description=. The ToolContext is the tool's only route to Redis. Its index handle stays inside the bound index, applies the binding's concurrency cap and request timeout to every call, and offers writes, addressed by document id, only to tools declared with writes=True. Every call is checked against the read scope, the write scope for a writing tool and any per-tool scope= (when authentication is configured), and errors are mapped to the MCP error contract.

    feat(router): add async aroute and aroute_many to SemanticRouter (#784)

    SemanticRouter gains aroute(), aroute_many(), adisconnect() and an aindex property. The async index is created on first use. Routers given an SSL, unix-socket, Sentinel or RedisCluster client can't convert it to async; pass redis_url to the router for async routing in those setups. Vectorizers without a native aembed (e.g. the default HFTextVectorizer) still embed synchronously; the Redis call is non-blocking either way. The async client is bound to the event loop that made the first call; call adisconnect() before switching loops.


    🚀 Enhancement
    • perf: run SemanticCache.check() as KNN with a client-side threshold (FDE-85) #754 (@vishal-bala)
    • feat(mcp): serve async Python functions as MCP tools, in four stacked PRs (@vishal-bala)
      • add an allow-listed index handle and ToolContext for code tools #758
      • validate and wrap async functions as code tools #759
      • register code tools from Python with server.code_tool #760
      • load code tools from modules named in the config #761
    • feat(router): add async aroute and aroute_many to SemanticRouter #784 (@Yarmoluk)
    📝 Documentation
    • docs: tighten PR template guidance and make Notes opt-in #803 (@vishal-bala)
    🧪 Tests
    • test(query): compare KNN results by id in test_search_and_query #804 (@vishal-bala)
    CI/CD Changes
    • fix(ci): route Dependabot PRs through the maintainer-dispatched service tests #802 (@vishal-bala)
    • ci(release): Ditch conventional-commits plugin from auto releases [#798](http
  3. v0.29.02026-10-30 · 2026-10-30 11:09 UTC
    查看更新说明

    Release Notes

    fix(router): apply per-route thresholds before max_k truncation (#766)

    Fixed SemanticRouter.route() and route_many() sometimes missing a route that met its distance_threshold. Each route's threshold is now applied before results are truncated to max_k, so a closer route that fails its own threshold no longer displaces a farther one that passes. Previously route() could return an empty RouteMatch and route_many() could return fewer matches than expected.

    fix(message-history): fall back within the requested session in get_relevant() (#765)

    SemanticMessageHistory.get_relevant() and SemanticSessionManager.get_relevant() called with both session_tag and fall_back=True now fall back to the recent messages of that session. Previously they returned the recent messages of the instance's default session.

    perf(embeddings-cache): refresh and set TTLs in the same round trip as each lookup and write (#764)

    EmbeddingsCache lookups and writes with a TTL configured, including those a vectorizer makes through cache=, now refresh or set the expiry in the same round trip, so cached embedding calls are faster. With a TTL configured, a credential that cannot run EXPIRE on the cache's keys now fails on a cache miss as well as on a hit.

    fix(index,router): keep SemanticRouter in step with the keyspace when a cluster UNLINK fails (#748)

    On Redis Cluster, SemanticRouter.remove_route and delete_route_references now raise PartialDeletionError when some reference keys cannot be deleted, instead of returning normally. Deleting a route's last reference now removes the route, so code that reads to_dict()["routes"] by position should look routes up by name.

    fix(router): make Route.distance_threshold inclusive (#763)

    SemanticRouter now treats Route.distance_threshold as inclusive, consistent with VectorRangeQuery and SemanticCache: a reference whose distance exactly equals a route's threshold now matches that route instead of being dropped.

    perf: refresh SemanticCache hit TTLs in one pipelined round trip (FDE-84) (#753)

    SemanticCache.check() and acheck() refresh the TTLs of all hits in one round trip, so lookups that return several hits from a cache with a TTL are faster.


    🚀 Enhancement
    • feat(index): debug-log query type, latency and result count in query() #750 (@jackiectl2)
    🐛 Bug Fix
    • fix(migration): support RESP3 key enumeration #730 (@Kuang-xianxin)
    • fix(router): apply per-route thresholds before max_k truncation #766 (@vishal-bala)
    • fix(message-history): fall back within the requested session in get_relevant() #765 (@vishal-bala)
    • chore(deps): bump the uv group across 1 directory with 2 updates #751 (@dependabot[bot])
    • fix(index,router): keep SemanticRouter in step with the keyspace when a cluster UNLINK fails #748 (@vishal-bala)
    • fix: keep vector fields in from_existing on RESP2 unified FT.INFO replies #742 (@desty)
    • fix(router): make Route.distance_threshold inclusive [#7
  4. v0.28.02026-10-09 · 2026-10-09 13:34 UTC
    查看更新说明

    Release Notes

    feat(mcp): scope custom tool queries to a tenant from a verified token claim (#738, #745) @vishal-bala

    Custom tool profiles can scope every query to a tenant read from the caller's verified token, with lock.inject. The injected field is never offered to the model, and the server refuses to start an injecting profile when authentication is off, when it runs over stdio, or when another tool can reach the same index without the tenant scope.

    redisvl.query.filter.is_match_all_filter is now public. It returns True for a filter that would match every document, including None, "*" and an uninitialised FilterExpression.

    refactor(index): explicit client ownership and removal of the deprecated connection APIs (#726, #727, #728) @vishal-bala

    SearchIndex and AsyncSearchIndex accept a new owns_client argument controlling whether the index closes its Redis client when it is disconnected or garbage collected. The default is unchanged: an index closes a client it created itself and never one passed as redis_client. Pass owns_client=True to hand over a client you created, or owns_client=False to keep one the index would otherwise close.

    The deprecated connection APIs are removed. Each removed keyword now raises TypeError naming its replacement, where previously the index keywords were silently ignored and url failed with an unrelated error from redis-py.

    RemovedUse instead
    SearchIndex.connect(), SearchIndex.set_client() and their AsyncSearchIndex counterpartsredis_client or redis_url in the constructor, with owns_client=True if the index should close a client you supplied
    connection_args and redis_kwargs on the index constructorsconnection_kwargs, with the same value
    RedisConnectionFactory.connect()get_redis_connection() or get_async_redis_connection()
    url on all five connection factory functionsredis_url

    AsyncSearchIndex no longer converts a sync Redis client for you. Pass an async client, or convert a non-cluster client yourself with RedisConnectionFactory.sync_to_async_redis(). Passing the wrong flavour of client to either index class now raises TypeError at construction rather than failing at first use; an async client passed to SearchIndex previously raised ValueError.

    Three further behaviour changes can surface errors earlier than before:

    • url previously took precedence over redis_url on the async factory, so an AsyncSearchIndex built with both redis_url and a url inside connection_kwargs connected to the latter. That combination now raises.
    • An index given a redis_client and no redis_url raises RedisVLError when it tries to reconnect after that client is closed, instead of falling back to REDIS_URL.
    • A cache built from a redis_url raises ConnectionError when its async client is created rather than at the first command, so an unreachable server surfaces at construction.
    fix(schema): use longitude first for GEO coordinates (#747) @fallintoplace

    GEO validation and schema inference now expect "longitude,latitude", the order Redis uses, instead of rejecting valid values such as -122.4194,37.7749. Values stored as "latitude,longitude" now fail validation when the longitude is beyond ±90; Redis was already misplacing or skipping them, so swap the order and reload. A swapped pair with both numbers within ±90 still passes, so validation cannot confirm that existing data is correct.

    fix(router): reject an empty reference id instead of matching every one (#718) @vishal-bala

    `SemanticRouter.g

  5. v0.27.22026-09-10 · 2026-09-10 10:50 UTC
    查看更新说明

    Release Notes

    fix: permit clear() when create_index=False, and drop its FT.INFO dependency (#704)

    SemanticCache, MessageHistory, SemanticMessageHistory and SemanticRouter constructed with create_index=False can now call clear() to remove their entries. Previously both clear() and delete() raised ValueError under that flag; delete() still does, because it drops the index. This is a behavioural change: code that caught ValueError from clear() and treated it as "unavailable" will now delete data.

    SearchIndex.clear() and AsyncSearchIndex.clear() no longer issue FT.INFO. They size their internal delete loop with a CountQuery instead, so clearing an index is available to a credential built from +@read +@write, which is denied FT.INFO. Clearing also no longer stops early on a page whose keys could not be deleted.

    EXTERNAL_INDEX_LIFECYCLE_CONFLICT in redisvl.extensions.constants is renamed to EXTERNAL_INDEX_DROP_CONFLICT, and its message has changed. Code importing the old name, or matching on the old text, needs updating.


    🐛 Bug Fix
    • fix: escape glob metacharacters in SCAN match patterns #702 @vishal-bala
    • fix: EmbeddingsCache batch writes silently dropped on async Redis Cluster #697 @vishal-bala
    • fix: keep paginate going past a page whose matches were all dropped #701 @vishal-bala
    • fix: SemanticCache fails to connect to Sentinel instances with quoted passwords #732 @nnick14
    • fix(tests): isolate the LangCache integration suite from its shared cache #725 @vishal-bala
    • fix: permit clear() when create_index=False, and drop its FT.INFO dependency #704 @vishal-bala
    • fix: cache clear() and migration key scans hang or crash on Redis Cluster #703 @vishal-bala

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    License: MIT pypi PyPI - Downloads GitHub stars

    Code style: black Language GitHub last commit

    Documentation • Recipes • GitHub


    Introduction

    Redis Vector Library (RedisVL) is the production-ready Python client for AI applications built on Redis. Lightning-fast vector search meets enterprise-grade reliability.

    Perfect for building RAG pipelines with real-time retrieval, AI agents with memory and semantic routing, and recommendation systems with fast search and reranking.

    🎯 Core Capabilities🚀 AI Extensions🛠️ Dev Utilities
    Index ManagementSchema design, data loading, CRUD opsSemantic CachingReduce LLM costs & boost throughputCLIIndex management from terminal
    Vector SearchSimilarity search with metadata filtersLLM MemoryAgentic AI context managementAsync SupportAsync indexing and search for improved performance
    Complex FilteringCombine multiple filter typesSemantic RoutingIntelligent query classificationVectorizers8+ embedding provider integrations
    Hybrid SearchCombine semantic & full-text signalsEmbedding CachingCache embeddings for efficiencyRerankersImprove search result relevancy
    MCP ServerExpose one or more existing Redis indexes to MCP clients

    💪 Getting Started

    Installation

    Install redisvl into your Python (>=3.10) environment using pip:

    pip install redisvl
    

    Install the MCP server extra when you want to expose one or more existing Redis indexes through MCP:

    pip install redisvl[mcp]
    

    For more detailed instructions, visit the installation guide. For MCP concepts and setup, see the RedisVL MCP docs and the MCP how-to guide.

    Redis

    Choose from multiple Redis deployment options:

    Redis Cloud offers a fully managed Redis service with a free tier, perfect for getting started quickly.

    Run Redis locally using Docker:

    docker run -d --name redis -p 6379:6379 redis:latest
    

    This runs Redis 8+ with built-in vector search capabilities.

    Redis Enterprise provides enterprise-grade features for production deployments.

    Configure Redis Sentinel for high availability:

    # Connect via Sentinel
    redis_url="redis+sentinel://sentinel1:26379,sentinel2:26379/mymaster"
    

    Azure Managed Redis provides fully managed Redis Enterprise on Microsoft Azure.

    💡 Tip: Enhance your experience and observability with the free Redis Insight GUI.

    Overview

    Index Management

    1. Design a schema for your use case that models your dataset with built-in Redis indexable fields (e.g. text, tags, numerics, geo, and vectors).

      index:
        name: user-idx
        prefix: user
        storage_type: json
      
      fields:
        - name: user
          type: tag
        - name: credit_score
          type: tag
        - name: job_title
          type: text
          attrs:
            sortable: true
            no_index: false  # Index for search (default)
            unf: false       # Normalize case for sorting (default)
        - name: embedding
          type: vector
          attrs:
            algorithm: flat
            dims: 4
            distance_metric: cosine
            datatype: float32
      
      from redisvl.schema import IndexSchema
      
      schema = IndexSchema.from_yaml("schemas/schema.yaml")
      
      from redisvl.schema import IndexSchema
      
      schema = IndexSchema.from_dict({
          "index": {
              "name": "user-idx",
              "prefix": "user",
              "storage_type": "json"
          },
          "fields": [
              {"name": "user", "type": "tag"},
              {"name": "credit_score", "type": "tag"},
              {
                  "name": "job_title",
                  "type": "text",
                  "attrs": {
                      "sortable": True,
                      "no_index": False,  # Index for search
                      "unf": False        # Normalize case for sorting
                  }
              },
              {
                  "name": "embedding",
                  "type": "vector",
                  "attrs": {
                      "algorithm": "flat",
                      "datatype": "float32",
                      "dims": 4,
                      "distance_metric": "cosine"
                  }
              }
          ]
      })
      

      📚 Learn more about schema design and schema creation.

    2. Create a SearchIndex class with an input schema to perform admin and search operations on your index in Redis:

      from redis import Redis
      from redisvl.index import SearchIndex
      
      # Define the index
      index = SearchIndex(schema, redis_url="redis://localhost:6379")
      
      # Create the index in Redis
      index.create()
      

      An async-compatible index class also available: AsyncSearchIndex.

    3. Load and fetch data to/from your Redis instance:

      data = {"user": "john", "credit_score": "high", "embedding": [0.23, 0.49, -0.18, 0.95]}
      
      # load list of dictionaries, specify the "id" field
      index.load([data], id_field="user")
      
      # fetch by "id"
      john = index.fetch("john")
      

    Retrieval

    Define queries and perform advanced searches over your indices, including vector search, complex filtering, and hybrid search combining semantic and full-text signals.

    Query TypeUse CaseDescription
    VectorQuerySemantic similarity searchFind similar vectors with optional filters
    RangeQueryDistance-based searchVector search within a defined distance range
    FilterQueryMetadata filteringFilter and search using metadata fields
    TextQueryFull-text searchBM25-based keyword search with field weighting
    HybridQueryCombined searchCombine semantic + full-text signals (Redis 8.4.0+)
    CountQueryCounting recordsCount documents matching filter criteria

    Vector Search

    • VectorQuery - Flexible vector queries with customizable filters enabling semantic search:

      from redisvl.query import VectorQuery
      
      query = VectorQuery(
        vector=[0.16, -0.34, 0.98, 0.23],
        vector_field_name="embedding",
        num_results=3,
        # Optional: tune search performance with runtime parameters
        ef_runtime=100  # HNSW: higher for better recall
      )
      # run the vector search query against the embedding field
      results = index.query(query)
      
    • RangeQuery - Vector search within a defined range paired with customizable filters

    Complex Filtering

    Build complex filtering queries by combining multiple filter types (tags, numerics, text, geo, timestamps) using logical operators:

    ```python
    from redisvl.query import VectorQuery
    from redisvl.query.filter import Tag, Num
    
    # Combine multiple filter types
    tag_filter = Tag("user") == "john"
    price_filter = Num("price") >= 100
    
    # Create complex filtering query with combined filters
    query = VectorQuery(
        vector=[0.16, -0.34, 0.98, 0.23],
        vector_field_name="embedding",
        filter_expression=tag_filter & price_filter,
        num_results=10
    )
    results = index.query(query)
    ```
    
    • FilterQuery - Standard search using filters and full-text search
    • CountQuery - Count the number of indexed records given attributes
    • TextQuery - Full-text search with support for field weighting and BM25 scoring

    Learn more about building complex filtering queries.

    Hybrid Search

    Combine semantic (vector) search with full-text (BM25) search signals for improved search quality:

    • HybridQuery - Native hybrid search combining text and vector similarity (Redis 8.4.0+):

      from redisvl.query import HybridQuery
      
      hybrid_query = HybridQuery(
          text="running shoes",
          text_field_name="description",
          vector=[0.1, 0.2, 0.3],
          vector_field_name="embedding",
          combination_method="LINEAR",  # or "RRF"
          num_results=10
      )
      results = index.query(hybrid_query)
      
    • AggregateHybridQuery - Hybrid search using aggregation (compatible with earlier Redis versions)

    Learn more about hybrid search.

    Dev Utilities

    Vectorizers

    Integrate with popular embedding providers to greatly simplify the process of vectorizing unstructured data for your index and queries.

    from redisvl.utils.vectorize import CohereTextVectorizer
    
    # set COHERE_API_KEY in your environment
    co = CohereTextVectorizer()
    
    embedding = co.embed(
        text="What is the capital city of France?",
        input_type="search_query"
    )
    
    embeddings = co.embed_many(
        texts=["my document chunk content", "my other document chunk content"],
        input_type="search_document"
    )
    

    Learn more about using vectorizers in your embedding workflows.

    Rerankers

    Integrate with popular reranking providers to improve the relevancy of the initial search results from Redis

    Extensions

    RedisVL Extensions provide production-ready modules implementing best practices and design patterns for working with LLM memory and agents. These extensions encapsulate learnings from our user community and enterprise customers.

    💡 Have an idea for another extension? Open a PR or reach out to us at [email protected]. We're always open to feedback.

    Semantic Caching

    Increase application throughput and reduce the cost of using LLM models in production by leveraging previously generated knowledge with the SemanticCache.

    from redisvl.extensions.cache.llm import SemanticCache
    
    # init cache with TTL and semantic distance threshold
    llmcache = SemanticCache(
        name="llmcache",
        ttl=360,
        redis_url="redis://localhost:6379",
        distance_threshold=0.1  # Redis COSINE distance [0-2], lower is stricter
    )
    
    # store user queries and LLM responses in the semantic cache
    llmcache.store(
        prompt="What is the capital city of France?",
        response="Paris"
    )
    
    # quickly check the cache with a slightly different prompt (before invoking an LLM)
    response = llmcache.check(prompt="What is France's capital city?")
    print(response[0]["response"])
    
    >>> Paris
    

    Learn more about semantic caching for LLMs.

    Embedding Caching

    Reduce computational costs and improve performance by caching embedding vectors with their associated text and metadata using the EmbeddingsCache.

    from redisvl.extensions.cache.embeddings import EmbeddingsCache
    from redisvl.utils.vectorize import HFTextVectorizer
    
    # Initialize embedding cache
    embed_cache = EmbeddingsCache(
        name="embed_cache",
        redis_url="redis://localhost:6379",
        ttl=3600  # 1 hour TTL
    )
    
    # Initialize vectorizer with cache
    vectorizer = HFTextVectorizer(
        model="sentence-transformers/all-MiniLM-L6-v2",
        cache=embed_cache
    )
    
    # First call computes and caches the embedding
    embedding = vectorizer.embed("What is machine learning?")
    
    # Subsequent calls retrieve from cache (much faster!)
    cached_embedding = vectorizer.embed("What is machine learning?")
    
    >>> Cache hit! Retrieved from Redis in <1ms
    

    Learn more about embedding caching for improved performance.

    LLM Memory

    Improve personalization and accuracy of LLM responses by providing user conversation context. Manage access to memory data using recency or relevancy, powered by vector search with the MessageHistory.

    from redisvl.extensions.message_history import SemanticMessageHistory
    
    history = SemanticMessageHistory(
        name="my-session",
        redis_url="redis://localhost:6379",
        distance_threshold=0.7
    )
    
    # Supports roles: system, user, llm, tool
    # Optional metadata field for additional context
    history.add_messages([
        {"role": "user", "content": "hello, how are you?"},
        {"role": "llm", "content": "I'm doing fine, thanks."},
        {"role": "user", "content": "what is the weather going to be today?"},
        {"role": "llm", "content": "I don't know", "metadata": {"model": "gpt-4"}}
    ])
    
    # Get recent chat history
    history.get_recent(top_k=1)
    # >>> [{"role": "llm", "content": "I don't know", "metadata": {"model": "gpt-4"}}]
    
    # Get relevant chat history (powered by vector search)
    history.get_relevant("weather", top_k=1)
    # >>> [{"role": "user", "content": "what is the weather going to be today?"}]
    
    # Filter messages by role
    history.get_recent(role="user")  # Get only user messages
    history.get_recent(role=["user", "system"])  # Or multiple roles
    

    Learn more about LLM memory.

    Semantic Routing

    Build fast decision models that run directly in Redis and route user queries to the nearest "route" or "topic".

    from redisvl.extensions.router import Route, SemanticRouter
    
    routes = [
        Route(
            name="greeting",
            references=["hello", "hi"],
            metadata={"type": "greeting"},
            distance_threshold=0.3,
        ),
        Route(
            name="farewell",
            references=["bye", "goodbye"],
            metadata={"type": "farewell"},
            distance_threshold=0.3,
        ),
    ]
    
    # build semantic router from routes
    router = SemanticRouter(
        name="topic-router",
        routes=routes,
        redis_url="redis://localhost:6379",
    )
    
    router("Hi, good morning")
    # >>> RouteMatch(name='greeting', distance=0.273891836405)
    

    Learn more about semantic routing.

    Command Line Interface

    Create, destroy, and manage Redis index configurations from a purpose-built CLI interface: rvl.

    $ rvl --help
    
    usage: rvl <command> [<args>]
    
    Redis Vector Library CLI.
    
    Command groups:
      index       Create, inspect, list, and delete Redis search indexes
      stats       Show statistics for an existing Redis search index
      version     Show the installed RedisVL version
      mcp         Run the RedisVL MCP server
    
    Examples:
      rvl index --help
      rvl index create -s schema.yaml
      rvl stats -i user_index
      rvl mcp --config /path/to/mcp.yaml
    

    Use rvl index --help to see documented subcommands such as create, info, listall, delete, and destroy. Use rvl stats --help to see both index-name and schema-path examples plus the shared Redis connection options for data-plane commands.

    Run the MCP server over stdio (default):

    uvx --from redisvl[mcp] rvl mcp --config /path/to/mcp.yaml
    

    Or over Streamable HTTP for remote MCP clients:

    uvx --from redisvl[mcp] rvl mcp --config /path/to/mcp.yaml --transport streamable-http --host 0.0.0.0 --port 8000
    

    Or over SSE:

    uvx --from redisvl[mcp] rvl mcp --config /path/to/mcp.yaml --transport sse --host 0.0.0.0 --port 9000
    

    Use --read-only to expose search without upsert.

    Read more about using the CLI and running RedisVL MCP.

    MCP Server

    RedisVL includes an MCP server that lets MCP-compatible clients search or upsert data in one or more existing Redis indexes through a small, stable tool contract.

    The server:

    • connects to one or more existing Redis Search indexes, each addressed by a logical id
    • reconstructs each index's schema from Redis at startup
    • uses each index's configured vectorizer for query embedding and optional upsert embedding
    • exposes list-indexes for discovery, search-records, and (unless every index is read-only) upsert-records
    • supports stdio (default), Streamable HTTP, and SSE transports

    A single configured index is the simplest case and works exactly as before — callers omit the index selector. With multiple indexes, clients call list-indexes first and pass the chosen index to search-records and upsert-records.

    Run it over stdio (default):

    uvx --from redisvl[mcp] rvl mcp --config /path/to/mcp.yaml
    

    Run it over Streamable HTTP for remote clients:

    uvx --from redisvl[mcp] rvl mcp --config /path/to/mcp.yaml --transport streamable-http --host 0.0.0.0 --port 8000
    

    Use --read-only when clients should only search:

    uvx --from redisvl[mcp] rvl mcp --config /path/to/mcp.yaml --read-only
    

    For configuration details, tool arguments, and examples, see the RedisVL MCP docs and the MCP how-to guide.

    🚀 Why RedisVL?

    Redis is a proven, high-performance database that excels at real-time workloads. With RedisVL, you get a production-ready Python client that makes Redis's vector search, caching, and session management capabilities easily accessible for AI applications.

    Built on the Redis Python client, RedisVL provides an intuitive interface for vector search, LLM caching, and conversational AI memory - all the core components needed for modern AI workloads.

    😁 Helpful Links

    For additional help, check out the following resources:

    🫱🏼‍🫲🏽 Contributing

    Please help us by contributing PRs, opening GitHub issues for bugs or new feature ideas, improving documentation, or increasing test coverage. Read more about how to contribute!

    🚧 Maintenance

    This project is supported by Redis, Inc on a good faith effort basis. To report bugs, request features, or receive assistance, please file an issue.