From 6f86b0730600d7cc169a9e7c08d4aafb0e738a9b Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Mon, 10 Feb 2025 13:37:48 -0500 Subject: [PATCH 1/8] WIP --- redisvl/extensions/router/schema.py | 4 ++-- redisvl/extensions/router/semantic.py | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/redisvl/extensions/router/schema.py b/redisvl/extensions/router/schema.py index 6de61fb0..bb0a7baf 100644 --- a/redisvl/extensions/router/schema.py +++ b/redisvl/extensions/router/schema.py @@ -16,7 +16,7 @@ class Route(BaseModel): """List of reference phrases for the route.""" metadata: Dict[str, str] = Field(default={}) """Metadata associated with the route.""" - distance_threshold: Optional[float] = Field(default=None) + distance_threshold: Optional[float] = Field(default=0.5) """Distance threshold for matching the route.""" @validator("name") @@ -63,7 +63,7 @@ class DistanceAggregationMethod(Enum): class RoutingConfig(BaseModel): """Configuration for routing behavior.""" - distance_threshold: float = Field(default=0.5) + # distance_threshold: float = Field(default=0.5) """The threshold for semantic distance.""" max_k: int = Field(default=1) """The maximum number of top matches to return.""" diff --git a/redisvl/extensions/router/semantic.py b/redisvl/extensions/router/semantic.py index c9a85547..c5eca8c4 100644 --- a/redisvl/extensions/router/semantic.py +++ b/redisvl/extensions/router/semantic.py @@ -302,12 +302,17 @@ def _classify_multi_route( aggregation_method: DistanceAggregationMethod, ) -> List[RouteMatch]: """Classify to multiple routes, up to max_k (int), using a vector.""" + + # Set range query distance threshold to get all possible results to be further filtered + distance_threshold = max(route.distance_threshold for route in self.routes) + vector_range_query = RangeQuery( vector=vector, vector_field_name=ROUTE_VECTOR_FIELD_NAME, distance_threshold=distance_threshold, return_fields=["route_name"], ) + aggregate_request = self._build_aggregate_request( vector_range_query, aggregation_method, max_k ) @@ -368,7 +373,9 @@ def __call__( self, statement: Optional[str] = None, vector: Optional[List[float]] = None, - distance_threshold: Optional[float] = None, + distance_threshold: Optional[ + float + ] = None, # TODO: does this get removed if route becomes the owner of a distance threshold? Or do we apply to all? aggregation_method: Optional[DistanceAggregationMethod] = None, ) -> RouteMatch: """Query the semantic router with a given statement or vector. From 274e13508fcf0eccb12257f400f83f748c4c0562 Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Tue, 11 Feb 2025 14:26:15 -0500 Subject: [PATCH 2/8] working tests --- .gitignore | 2 + README.md | 22 +- docs/index.md | 4 +- ...rted_01.ipynb => 01_getting_started.ipynb} | 11 +- ...eries_02.ipynb => 02_hybrid_queries.ipynb} | 0 .../{llmcache_03.ipynb => 03_llmcache.ipynb} | 0 docs/user_guide/04_vectorizers.ipynb | 749 ++++++++++++++ ...vs_json_05.ipynb => 05_hash_vs_json.ipynb} | 0 ...{rerankers_06.ipynb => 06_rerankers.ipynb} | 0 ...ager_07.ipynb => 07_session_manager.ipynb} | 0 ...uter_08.ipynb => 08_semantic_router.ipynb} | 82 +- docs/user_guide/index.md | 16 +- docs/user_guide/router.yaml | 5 +- docs/user_guide/vectorizers_04.ipynb | 974 ------------------ poetry.lock | 29 +- redisvl/extensions/router/schema.py | 14 +- redisvl/extensions/router/semantic.py | 153 ++- schemas/semantic_router.yaml | 2 +- tests/integration/test_semantic_router.py | 46 + 19 files changed, 963 insertions(+), 1146 deletions(-) rename docs/user_guide/{getting_started_01.ipynb => 01_getting_started.ipynb} (99%) rename docs/user_guide/{hybrid_queries_02.ipynb => 02_hybrid_queries.ipynb} (100%) rename docs/user_guide/{llmcache_03.ipynb => 03_llmcache.ipynb} (100%) create mode 100644 docs/user_guide/04_vectorizers.ipynb rename docs/user_guide/{hash_vs_json_05.ipynb => 05_hash_vs_json.ipynb} (100%) rename docs/user_guide/{rerankers_06.ipynb => 06_rerankers.ipynb} (100%) rename docs/user_guide/{session_manager_07.ipynb => 07_session_manager.ipynb} (100%) rename docs/user_guide/{semantic_router_08.ipynb => 08_semantic_router.ipynb} (85%) delete mode 100644 docs/user_guide/vectorizers_04.ipynb diff --git a/.gitignore b/.gitignore index 5dced209..dca4f4e3 100644 --- a/.gitignore +++ b/.gitignore @@ -220,3 +220,5 @@ pip-selfcheck.json libs/redis/docs/.Trash* .python-version .idea/* +.vscode/settings.json +.python-version diff --git a/README.md b/README.md index 3f4ee75f..1d138377 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Choose from multiple Redis deployment options: ## 🗃️ Redis Index Management -1. [Design a schema for your use case](https://docs.redisvl.com/en/stable/user_guide/getting_started_01.html#define-an-indexschema) that models your dataset with built-in Redis and indexable fields (*e.g. text, tags, numerics, geo, and vectors*). [Load a schema](https://docs.redisvl.com/en/stable/user_guide/getting_started_01.html#example-schema-creation) from a YAML file: +1. [Design a schema for your use case](https://docs.redisvl.com/en/stable/user_guide/01_getting_started.html#define-an-indexschema) that models your dataset with built-in Redis and indexable fields (*e.g. text, tags, numerics, geo, and vectors*). [Load a schema](https://docs.redisvl.com/en/stable/user_guide/01_getting_started.html#example-schema-creation) from a YAML file: ```yaml index: name: user-idx @@ -121,7 +121,7 @@ Choose from multiple Redis deployment options: }) ``` -2. [Create a SearchIndex](https://docs.redisvl.com/en/stable/user_guide/getting_started_01.html#create-a-searchindex) class with an input schema and client connection in order to perform admin and search operations on your index in Redis: +2. [Create a SearchIndex](https://docs.redisvl.com/en/stable/user_guide/01_getting_started.html#create-a-searchindex) class with an input schema and client connection in order to perform admin and search operations on your index in Redis: ```python from redis import Redis from redisvl.index import SearchIndex @@ -135,8 +135,8 @@ Choose from multiple Redis deployment options: ``` > Async compliant search index class also available: [AsyncSearchIndex](https://docs.redisvl.com/en/stable/api/searchindex.html#redisvl.index.AsyncSearchIndex). -3. [Load](https://docs.redisvl.com/en/stable/user_guide/getting_started_01.html#load-data-to-searchindex) -and [fetch](https://docs.redisvl.com/en/stable/user_guide/getting_started_01.html#fetch-an-object-from-redis) data to/from your Redis instance: +3. [Load](https://docs.redisvl.com/en/stable/user_guide/01_getting_started.html#load-data-to-searchindex) +and [fetch](https://docs.redisvl.com/en/stable/user_guide/01_getting_started.html#fetch-an-object-from-redis) data to/from your Redis instance: ```python data = {"user": "john", "credit_score": "high", "embedding": [0.23, 0.49, -0.18, 0.95]} @@ -183,7 +183,7 @@ Define queries and perform advanced searches over your indices, including the co - [FilterQuery](https://docs.redisvl.com/en/stable/api/query.html#filterquery) - Standard search using filters and the full-text search - [CountQuery](https://docs.redisvl.com/en/stable/api/query.html#countquery) - Count the number of indexed records given attributes -> Read more about building [advanced Redis queries](https://docs.redisvl.com/en/stable/user_guide/hybrid_queries_02.html). +> Read more about building [advanced Redis queries](https://docs.redisvl.com/en/stable/user_guide/02_hybrid_queries.html). ## 🔧 Utilities @@ -216,11 +216,11 @@ embeddings = co.embed_many( ) ``` -> Learn more about using [vectorizers]((https://docs.redisvl.com/en/stable/user_guide/vectorizers_04.html)) in your embedding workflows. +> Learn more about using [vectorizers]((https://docs.redisvl.com/en/stable/user_guide/04_vectorizers.html)) in your embedding workflows. ### Rerankers -[Integrate with popular reranking providers](https://docs.redisvl.com/en/stable/user_guide/rerankers_06.html) to improve the relevancy of the initial search results from Redis +[Integrate with popular reranking providers](https://docs.redisvl.com/en/stable/user_guide/06_rerankers.html) to improve the relevancy of the initial search results from Redis @@ -257,7 +257,7 @@ print(response[0]["response"]) >>> Paris ``` -> Learn more about [semantic caching]((https://docs.redisvl.com/en/stable/user_guide/llmcache_03.html)) for LLMs. +> Learn more about [semantic caching]((https://docs.redisvl.com/en/stable/user_guide/03_llmcache.html)) for LLMs. ### LLM Session Management @@ -293,7 +293,7 @@ session.get_relevant("weather", top_k=1) ```stdout >>> [{"role": "user", "content": "what is the weather going to be today?"}] ``` -> Learn more about [LLM session management]((https://docs.redisvl.com/en/stable/user_guide/session_manager_07.html)). +> Learn more about [LLM session management]((https://docs.redisvl.com/en/stable/user_guide/07_session_manager.html)). ### LLM Semantic Routing @@ -330,7 +330,7 @@ router("Hi, good morning") ```stdout >>> RouteMatch(name='greeting', distance=0.273891836405) ``` -> Learn more about [semantic routing](https://docs.redisvl.com/en/stable/user_guide/semantic_router_08.html). +> Learn more about [semantic routing](https://docs.redisvl.com/en/stable/user_guide/08_semantic_router.html). ## 🖥️ Command Line Interface Create, destroy, and manage Redis index configurations from a purpose-built CLI interface: `rvl`. @@ -360,7 +360,7 @@ The Redis Vector Library bridges the gap between the AI-native developer ecosyst ## 😁 Helpful Links For additional help, check out the following resources: - - [Getting Started Guide](https://docs.redisvl.com/en/stable/user_guide/getting_started_01.html) + - [Getting Started Guide](https://docs.redisvl.com/en/stable/user_guide/01_getting_started.html) - [API Reference](https://docs.redisvl.com/en/stable/api/index.html) - [Example Gallery](https://docs.redisvl.com/en/stable/examples/index.html) - [Redis AI Recipes](https://github.com/redis-developer/redis-ai-resources) diff --git a/docs/index.md b/docs/index.md index ef345fd8..a9bbd094 100644 --- a/docs/index.md +++ b/docs/index.md @@ -20,12 +20,12 @@ A powerful, AI-native Python client library for [Redis](https://redis.io). Lever 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/vectorizers_04" + 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/llmcache_03" + 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" diff --git a/docs/user_guide/getting_started_01.ipynb b/docs/user_guide/01_getting_started.ipynb similarity index 99% rename from docs/user_guide/getting_started_01.ipynb rename to docs/user_guide/01_getting_started.ipynb index e4fa6544..dfa2b581 100644 --- a/docs/user_guide/getting_started_01.ipynb +++ b/docs/user_guide/01_getting_started.ipynb @@ -697,7 +697,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.8.13 ('redisvl2')", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -711,14 +711,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.10" + "version": "3.11.9" }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "9b1e6e9c2967143209c2f955cb869d1d3234f92dc4787f49f155f3abbdfb1316" - } - } + "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 diff --git a/docs/user_guide/hybrid_queries_02.ipynb b/docs/user_guide/02_hybrid_queries.ipynb similarity index 100% rename from docs/user_guide/hybrid_queries_02.ipynb rename to docs/user_guide/02_hybrid_queries.ipynb diff --git a/docs/user_guide/llmcache_03.ipynb b/docs/user_guide/03_llmcache.ipynb similarity index 100% rename from docs/user_guide/llmcache_03.ipynb rename to docs/user_guide/03_llmcache.ipynb diff --git a/docs/user_guide/04_vectorizers.ipynb b/docs/user_guide/04_vectorizers.ipynb new file mode 100644 index 00000000..d5870b88 --- /dev/null +++ b/docs/user_guide/04_vectorizers.ipynb @@ -0,0 +1,749 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 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", + "\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", + "\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", + "This will run Redis on port 6379 and RedisInsight at http://localhost:8001." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# import necessary modules\n", + "import os" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating Text Embeddings\n", + "\n", + "This example will show how to create an embedding from 3 simple sentences with a number of different text vectorizers in RedisVL.\n", + "\n", + "- \"That is a happy dog\"\n", + "- \"That is a happy person\"\n", + "- \"Today is a nice day\"\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### OpenAI\n", + "\n", + "The ``OpenAITextVectorizer`` makes it simple to use RedisVL with the embeddings models at OpenAI. For this you will need to install ``openai``. \n", + "\n", + "```bash\n", + "pip install openai\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import getpass\n", + "\n", + "# setup the API Key\n", + "api_key = os.environ.get(\"OPENAI_API_KEY\") or getpass.getpass(\"Enter your OpenAI API key: \")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.utils.vectorize import OpenAITextVectorizer\n", + "\n", + "# create a vectorizer\n", + "oai = OpenAITextVectorizer(\n", + " model=\"text-embedding-ada-002\",\n", + " api_config={\"api_key\": api_key},\n", + ")\n", + "\n", + "test = oai.embed(\"This is a test sentence.\")\n", + "print(\"Vector dimensions: \", len(test))\n", + "test[:10]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create many embeddings at once\n", + "sentences = [\n", + " \"That is a happy dog\",\n", + " \"That is a happy person\",\n", + " \"Today is a sunny day\"\n", + "]\n", + "\n", + "embeddings = oai.embed_many(sentences)\n", + "embeddings[0][:10]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# openai also supports asyncronous requests, which we can use to speed up the vectorization process.\n", + "embeddings = await oai.aembed_many(sentences)\n", + "print(\"Number of Embeddings:\", len(embeddings))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Azure OpenAI\n", + "\n", + "The ``AzureOpenAITextVectorizer`` is a variation of the OpenAI vectorizer that calls OpenAI models within Azure. If you've already installed ``openai``, then you're ready to use Azure OpenAI.\n", + "\n", + "The only practical difference between OpenAI and Azure OpenAI is the variables required to call the API." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# additionally to the API Key, setup the API endpoint and version\n", + "api_key = os.environ.get(\"AZURE_OPENAI_API_KEY\") or getpass.getpass(\"Enter your AzureOpenAI API key: \")\n", + "api_version = os.environ.get(\"OPENAI_API_VERSION\") or getpass.getpass(\"Enter your AzureOpenAI API version: \")\n", + "azure_endpoint = os.environ.get(\"AZURE_OPENAI_ENDPOINT\") or getpass.getpass(\"Enter your AzureOpenAI API endpoint: \")\n", + "deployment_name = os.environ.get(\"AZURE_OPENAI_DEPLOYMENT_NAME\", \"text-embedding-ada-002\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.utils.vectorize import AzureOpenAITextVectorizer\n", + "\n", + "# create a vectorizer\n", + "az_oai = AzureOpenAITextVectorizer(\n", + " model=deployment_name, # Must be your CUSTOM deployment name\n", + " api_config={\n", + " \"api_key\": api_key,\n", + " \"api_version\": api_version,\n", + " \"azure_endpoint\": azure_endpoint\n", + " },\n", + ")\n", + "\n", + "test = az_oai.embed(\"This is a test sentence.\")\n", + "print(\"Vector dimensions: \", len(test))\n", + "test[:10]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Just like OpenAI, AzureOpenAI supports batching embeddings and asynchronous requests.\n", + "sentences = [\n", + " \"That is a happy dog\",\n", + " \"That is a happy person\",\n", + " \"Today is a sunny day\"\n", + "]\n", + "\n", + "embeddings = await az_oai.aembed_many(sentences)\n", + "embeddings[0][:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Huggingface\n", + "\n", + "[Huggingface](https://huggingface.co/models) is a popular NLP platform that has a number of pre-trained models you can use off the shelf. RedisVL supports using Huggingface \"Sentence Transformers\" to create embeddings from text. To use Huggingface, you will need to install the ``sentence-transformers`` library.\n", + "\n", + "```bash\n", + "pip install sentence-transformers\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "os.environ[\"TOKENIZERS_PARALLELISM\"] = \"false\"\n", + "from redisvl.utils.vectorize import HFTextVectorizer\n", + "\n", + "\n", + "# create a vectorizer\n", + "# choose your model from the huggingface website\n", + "hf = HFTextVectorizer(model=\"sentence-transformers/all-mpnet-base-v2\")\n", + "\n", + "# embed a sentence\n", + "test = hf.embed(\"This is a test sentence.\")\n", + "test[:10]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# You can also create many embeddings at once\n", + "embeddings = hf.embed_many(sentences, as_buffer=True, dtype=\"float32\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### VertexAI\n", + "\n", + "[VertexAI](https://cloud.google.com/vertex-ai/docs/generative-ai/embeddings/get-text-embeddings) is GCP's fully-featured AI platform including a number of pretrained LLMs. RedisVL supports using VertexAI to create embeddings from these models. To use VertexAI, you will first need to install the ``google-cloud-aiplatform`` library.\n", + "\n", + "```bash\n", + "pip install google-cloud-aiplatform>=1.26\n", + "```\n", + "\n", + "1. Then you need to gain access to a [Google Cloud Project](https://cloud.google.com/gcp?hl=en) and provide [access to credentials](https://cloud.google.com/docs/authentication/application-default-credentials). This is accomplished by setting the `GOOGLE_APPLICATION_CREDENTIALS` environment variable pointing to the path of a JSON key file downloaded from your service account on GCP.\n", + "2. Lastly, you need to find your [project ID](https://support.google.com/googleapi/answer/7014113?hl=en) and [geographic region for VertexAI](https://cloud.google.com/vertex-ai/docs/general/locations).\n", + "\n", + "\n", + "**Make sure the following env vars are set:**\n", + "\n", + "```\n", + "GOOGLE_APPLICATION_CREDENTIALS=\n", + "GCP_PROJECT_ID=\n", + "GCP_LOCATION=\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.utils.vectorize import VertexAITextVectorizer\n", + "\n", + "\n", + "# create a vectorizer\n", + "vtx = VertexAITextVectorizer(api_config={\n", + " \"project_id\": os.environ.get(\"GCP_PROJECT_ID\") or getpass.getpass(\"Enter your GCP Project ID: \"),\n", + " \"location\": os.environ.get(\"GCP_LOCATION\") or getpass.getpass(\"Enter your GCP Location: \"),\n", + " \"google_application_credentials\": os.environ.get(\"GOOGLE_APPLICATION_CREDENTIALS\") or getpass.getpass(\"Enter your Google App Credentials path: \")\n", + "})\n", + "\n", + "# embed a sentence\n", + "test = vtx.embed(\"This is a test sentence.\")\n", + "test[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Cohere\n", + "\n", + "[Cohere](https://dashboard.cohere.ai/) allows you to implement language AI into your product. The `CohereTextVectorizer` makes it simple to use RedisVL with the embeddings models at Cohere. For this you will need to install `cohere`.\n", + "\n", + "```bash\n", + "pip install cohere\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "import getpass\n", + "# setup the API Key\n", + "api_key = os.environ.get(\"COHERE_API_KEY\") or getpass.getpass(\"Enter your Cohere API key: \")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Special attention needs to be paid to the `input_type` parameter for each `embed` call. For example, for embedding \n", + "queries, you should set `input_type='search_query'`; for embedding documents, set `input_type='search_document'`. See\n", + "more information [here](https://docs.cohere.com/reference/embed)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.utils.vectorize import CohereTextVectorizer\n", + "\n", + "# create a vectorizer\n", + "co = CohereTextVectorizer(\n", + " model=\"embed-english-v3.0\",\n", + " api_config={\"api_key\": api_key},\n", + ")\n", + "\n", + "# embed a search query\n", + "test = co.embed(\"This is a test sentence.\", input_type='search_query')\n", + "print(\"Vector dimensions: \", len(test))\n", + "print(test[:10])\n", + "\n", + "# embed a document\n", + "test = co.embed(\"This is a test sentence.\", input_type='search_document')\n", + "print(\"Vector dimensions: \", len(test))\n", + "print(test[:10])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Learn more about using RedisVL and Cohere together through [this dedicated user guide](https://docs.cohere.com/docs/redis-and-cohere)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### VoyageAI\n", + "\n", + "[VoyageAI](https://dash.voyageai.com/) allows you to implement language AI into your product. The `VoyageAITextVectorizer` makes it simple to use RedisVL with the embeddings models at VoyageAI. For this you will need to install `voyageai`.\n", + "\n", + "```bash\n", + "pip install voyageai\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "import getpass\n", + "# setup the API Key\n", + "api_key = os.environ.get(\"VOYAGE_API_KEY\") or getpass.getpass(\"Enter your VoyageAI API key: \")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Special attention needs to be paid to the `input_type` parameter for each `embed` call. For example, for embedding \n", + "queries, you should set `input_type='query'`; for embedding documents, set `input_type='document'`. See\n", + "more information [here](https://docs.voyageai.com/docs/embeddings)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.utils.vectorize import VoyageAITextVectorizer\n", + "\n", + "# create a vectorizer\n", + "vo = VoyageAITextVectorizer(\n", + " model=\"voyage-law-2\", # Please check the available models at https://docs.voyageai.com/docs/embeddings\n", + " api_config={\"api_key\": api_key},\n", + ")\n", + "\n", + "# embed a search query\n", + "test = vo.embed(\"This is a test sentence.\", input_type='query')\n", + "print(\"Vector dimensions: \", len(test))\n", + "print(test[:10])\n", + "\n", + "# embed a document\n", + "test = vo.embed(\"This is a test sentence.\", input_type='document')\n", + "print(\"Vector dimensions: \", len(test))\n", + "print(test[:10])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Mistral AI\n", + "\n", + "[Mistral](https://console.mistral.ai/) offers LLM and embedding APIs for you to implement into your product. The `MistralAITextVectorizer` makes it simple to use RedisVL with their embeddings model.\n", + "You will need to install `mistralai`.\n", + "\n", + "```bash\n", + "pip install mistralai\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.utils.vectorize import MistralAITextVectorizer\n", + "\n", + "mistral = MistralAITextVectorizer()\n", + "\n", + "# embed a sentence using their asyncronous method\n", + "test = await mistral.aembed(\"This is a test sentence.\")\n", + "print(\"Vector dimensions: \", len(test))\n", + "print(test[:10])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Amazon Bedrock\n", + "\n", + "Amazon Bedrock provides fully managed foundation models for text embeddings. Install the required dependencies:\n", + "\n", + "```bash\n", + "pip install 'redisvl[bedrock]' # Installs boto3\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Configure AWS credentials:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import getpass\n", + "\n", + "if \"AWS_ACCESS_KEY_ID\" not in os.environ:\n", + " os.environ[\"AWS_ACCESS_KEY_ID\"] = getpass.getpass(\"Enter AWS Access Key ID: \")\n", + "if \"AWS_SECRET_ACCESS_KEY\" not in os.environ:\n", + " os.environ[\"AWS_SECRET_ACCESS_KEY\"] = getpass.getpass(\"Enter AWS Secret Key: \")\n", + "\n", + "os.environ[\"AWS_REGION\"] = \"us-east-1\" # Change as needed" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Create embeddings:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.utils.vectorize import BedrockTextVectorizer\n", + "\n", + "bedrock = BedrockTextVectorizer(\n", + " model=\"amazon.titan-embed-text-v2:0\"\n", + ")\n", + "\n", + "# Single embedding\n", + "text = \"This is a test sentence.\"\n", + "embedding = bedrock.embed(text)\n", + "print(f\"Vector dimensions: {len(embedding)}\")\n", + "\n", + "# Multiple embeddings\n", + "sentences = [\n", + " \"That is a happy dog\",\n", + " \"That is a happy person\",\n", + " \"Today is a sunny day\"\n", + "]\n", + "embeddings = bedrock.embed_many(sentences)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Custom Vectorizers\n", + "\n", + "RedisVL supports the use of other vectorizers and provides a class to enable compatibility with any function that generates a vector or vectors from string data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.utils.vectorize import CustomTextVectorizer\n", + "\n", + "def generate_embeddings(text_input, **kwargs):\n", + " return [0.101] * 768\n", + "\n", + "custom_vectorizer = CustomTextVectorizer(generate_embeddings)\n", + "\n", + "custom_vectorizer.embed(\"This is a test sentence.\")[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This enables the use of custom vectorizers with other RedisVL components" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.extensions.llmcache import SemanticCache\n", + "\n", + "cache = SemanticCache(name=\"custom_cache\", vectorizer=custom_vectorizer)\n", + "\n", + "cache.store(\"this is a test prompt\", \"this is a test response\")\n", + "cache.check(\"this is also a test prompt\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Search with Provider Embeddings\n", + "\n", + "Now that we've created our embeddings, we can use them to search for similar sentences. We will use the same 3 sentences from above and search for similar sentences.\n", + "\n", + "First, we need to create the schema for our index.\n", + "\n", + "Here's what the schema for the example looks like in yaml for the HuggingFace vectorizer:\n", + "\n", + "```yaml\n", + "version: '0.1.0'\n", + "\n", + "index:\n", + " name: vectorizers\n", + " prefix: doc\n", + " storage_type: hash\n", + "\n", + "fields:\n", + " - name: sentence\n", + " type: text\n", + " - name: embedding\n", + " type: vector\n", + " attrs:\n", + " dims: 768\n", + " algorithm: flat\n", + " distance_metric: cosine\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.index import SearchIndex\n", + "\n", + "# construct a search index from the schema\n", + "index = SearchIndex.from_yaml(\"./schema.yaml\")\n", + "\n", + "# connect to local redis instance\n", + "index.connect(\"redis://localhost:6379\")\n", + "\n", + "# create the index (no data yet)\n", + "index.create(overwrite=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# use the CLI to see the created index\n", + "!rvl index listall" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Loading data to RedisVL is easy. It expects a list of dictionaries. The vector is stored as bytes." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.redis.utils import array_to_buffer\n", + "\n", + "embeddings = hf.embed_many(sentences)\n", + "\n", + "data = [{\"text\": t,\n", + " \"embedding\": array_to_buffer(v, dtype=\"float32\")}\n", + " for t, v in zip(sentences, embeddings)]\n", + "\n", + "index.load(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from redisvl.query import VectorQuery\n", + "\n", + "# use the HuggingFace vectorizer again to create a query embedding\n", + "query_embedding = hf.embed(\"That is a happy cat\")\n", + "\n", + "query = VectorQuery(\n", + " vector=query_embedding,\n", + " vector_field_name=\"embedding\",\n", + " return_fields=[\"text\"],\n", + " num_results=3\n", + ")\n", + "\n", + "results = index.query(query)\n", + "for doc in results:\n", + " print(doc[\"text\"], doc[\"vector_distance\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Selecting your float data type\n", + "When embedding text as byte arrays RedisVL supports 4 different floating point data types, `float16`, `float32`, `float64` and `bfloat16`.\n", + "Your dtype set for your vectorizer must match what is defined in your search index. If one is not explicitly set the default is `float32`." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "vectorizer = HFTextVectorizer(dtype=\"float16\")\n", + "\n", + "# subsequent calls to embed('', as_buffer=True) and embed_many('', as_buffer=True) will now encode as float16\n", + "float16_bytes = vectorizer.embed('test sentence', as_buffer=True)\n", + "\n", + "# you can override this setting on each individual method call\n", + "float64_bytes = vectorizer.embed('test sentence', as_buffer=True, dtype=\"float64\")\n", + "\n", + "float16_bytes != float64_bytes" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "# cleanup\n", + "index.delete()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "dist = max(i for i in range(10))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dist" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/docs/user_guide/hash_vs_json_05.ipynb b/docs/user_guide/05_hash_vs_json.ipynb similarity index 100% rename from docs/user_guide/hash_vs_json_05.ipynb rename to docs/user_guide/05_hash_vs_json.ipynb diff --git a/docs/user_guide/rerankers_06.ipynb b/docs/user_guide/06_rerankers.ipynb similarity index 100% rename from docs/user_guide/rerankers_06.ipynb rename to docs/user_guide/06_rerankers.ipynb diff --git a/docs/user_guide/session_manager_07.ipynb b/docs/user_guide/07_session_manager.ipynb similarity index 100% rename from docs/user_guide/session_manager_07.ipynb rename to docs/user_guide/07_session_manager.ipynb diff --git a/docs/user_guide/semantic_router_08.ipynb b/docs/user_guide/08_semantic_router.ipynb similarity index 85% rename from docs/user_guide/semantic_router_08.ipynb rename to docs/user_guide/08_semantic_router.ipynb index bfe8b193..ab3bf2cc 100644 --- a/docs/user_guide/semantic_router_08.ipynb +++ b/docs/user_guide/08_semantic_router.ipynb @@ -25,7 +25,9 @@ "\n", "Each route has a set of references that cover the \"semantic surface area\" of the\n", "route. The incoming query from a user needs to be semantically similar to one or\n", - "more of the references in order to \"match\" on the route." + "more of the references in order to \"match\" on the route.\n", + "\n", + "Additionally, each route has a `distance_threshold` which determines the maximum distance between the query and the reference for the query to be routed to the route. This value is unique to each route." ] }, { @@ -45,7 +47,8 @@ " \"tell me about the newest gadgets\",\n", " \"what's trending in tech?\"\n", " ],\n", - " metadata={\"category\": \"tech\", \"priority\": 1}\n", + " metadata={\"category\": \"tech\", \"priority\": 1},\n", + " distance_threshold=1.0\n", ")\n", "\n", "sports = Route(\n", @@ -57,7 +60,8 @@ " \"sports\",\n", " \"basketball and football\"\n", " ],\n", - " metadata={\"category\": \"sports\", \"priority\": 2}\n", + " metadata={\"category\": \"sports\", \"priority\": 2},\n", + " distance_threshold=0.5\n", ")\n", "\n", "entertainment = Route(\n", @@ -67,7 +71,8 @@ " \"who won the best actor award?\",\n", " \"what's new in the entertainment industry?\"\n", " ],\n", - " metadata={\"category\": \"entertainment\", \"priority\": 3}\n", + " metadata={\"category\": \"entertainment\", \"priority\": 3},\n", + " distance_threshold=0.7\n", ")\n" ] }, @@ -85,7 +90,25 @@ "cell_type": "code", "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/robert.shelton/.pyenv/versions/3.11.9/lib/python3.11/site-packages/huggingface_hub/file_download.py:1142: FutureWarning: `resume_download` is deprecated and will be removed in version 1.0.0. Downloads always resume when possible. If you want to force a new download, use `force_download=True`.\n", + " warnings.warn(\n", + "/Users/robert.shelton/.pyenv/versions/3.11.9/lib/python3.11/site-packages/huggingface_hub/file_download.py:1142: FutureWarning: `resume_download` is deprecated and will be removed in version 1.0.0. Downloads always resume when possible. If you want to force a new download, use `force_download=True`.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "14:07:31 redisvl.index.index INFO Index already exists, overwriting.\n" + ] + } + ], "source": [ "import os\n", "from redisvl.extensions.router import SemanticRouter\n", @@ -171,7 +194,7 @@ { "data": { "text/plain": [ - "RouteMatch(name='technology', distance=0.119614243507)" + "RouteMatch(name='technology', distance=0.119614303112)" ] }, "execution_count": 5, @@ -215,7 +238,7 @@ { "data": { "text/plain": [ - "RouteMatch(name='sports', distance=0.554210186005)" + "RouteMatch(name=None, distance=None)" ] }, "execution_count": 7, @@ -225,7 +248,7 @@ ], "source": [ "# Toggle the runtime distance threshold\n", - "route_match = router(\"Which basketball team will win the NBA finals?\", distance_threshold=0.7)\n", + "route_match = router(\"Which basketball team will win the NBA finals?\")\n", "route_match" ] }, @@ -244,9 +267,7 @@ { "data": { "text/plain": [ - "[RouteMatch(name='sports', distance=0.758580708504),\n", - " RouteMatch(name='entertainment', distance=0.812423825264),\n", - " RouteMatch(name='technology', distance=0.88423516353)]" + "[]" ] }, "execution_count": 8, @@ -256,7 +277,7 @@ ], "source": [ "# Perform multi-class classification with route_many() -- toggle the max_k and the distance_threshold\n", - "route_matches = router.route_many(\"Lebron James\", distance_threshold=1.0, max_k=3)\n", + "route_matches = router.route_many(\"Lebron James\", max_k=3)\n", "route_matches" ] }, @@ -268,9 +289,7 @@ { "data": { "text/plain": [ - "[RouteMatch(name='sports', distance=0.663253903389),\n", - " RouteMatch(name='entertainment', distance=0.712985396385),\n", - " RouteMatch(name='technology', distance=0.832674384117)]" + "[]" ] }, "execution_count": 9, @@ -282,7 +301,7 @@ "# Toggle the aggregation method -- note the different distances in the result\n", "from redisvl.extensions.router.schema import DistanceAggregationMethod\n", "\n", - "route_matches = router.route_many(\"Lebron James\", aggregation_method=DistanceAggregationMethod.min, distance_threshold=1.0, max_k=3)\n", + "route_matches = router.route_many(\"Lebron James\", aggregation_method=DistanceAggregationMethod.min, max_k=3)\n", "route_matches" ] }, @@ -309,7 +328,7 @@ "from redisvl.extensions.router import RoutingConfig\n", "\n", "router.update_routing_config(\n", - " RoutingConfig(distance_threshold=1.0, aggregation_method=DistanceAggregationMethod.min, max_k=3)\n", + " RoutingConfig(aggregation_method=DistanceAggregationMethod.min, max_k=3)\n", ")" ] }, @@ -321,9 +340,7 @@ { "data": { "text/plain": [ - "[RouteMatch(name='sports', distance=0.663253903389),\n", - " RouteMatch(name='entertainment', distance=0.712985396385),\n", - " RouteMatch(name='technology', distance=0.832674384117)]" + "[]" ] }, "execution_count": 11, @@ -356,22 +373,25 @@ " 'references': ['what are the latest advancements in AI?',\n", " 'tell me about the newest gadgets',\n", " \"what's trending in tech?\"],\n", - " 'metadata': {'category': 'tech', 'priority': '1'}},\n", + " 'metadata': {'category': 'tech', 'priority': '1'},\n", + " 'distance_threshold': 1.0},\n", " {'name': 'sports',\n", " 'references': ['who won the game last night?',\n", " 'tell me about the upcoming sports events',\n", " \"what's the latest in the world of sports?\",\n", " 'sports',\n", " 'basketball and football'],\n", - " 'metadata': {'category': 'sports', 'priority': '2'}},\n", + " 'metadata': {'category': 'sports', 'priority': '2'},\n", + " 'distance_threshold': 0.5},\n", " {'name': 'entertainment',\n", " 'references': ['what are the top movies right now?',\n", " 'who won the best actor award?',\n", " \"what's new in the entertainment industry?\"],\n", - " 'metadata': {'category': 'entertainment', 'priority': '3'}}],\n", + " 'metadata': {'category': 'entertainment', 'priority': '3'},\n", + " 'distance_threshold': 0.7}],\n", " 'vectorizer': {'type': 'hf',\n", " 'model': 'sentence-transformers/all-mpnet-base-v2'},\n", - " 'routing_config': {'distance_threshold': 1.0,\n", + " 'routing_config': {'distance_threshold': 0.5,\n", " 'max_k': 3,\n", " 'aggregation_method': 'min'}}" ] @@ -394,7 +414,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "15:16:28 redisvl.index.index INFO Index already exists, not overwriting.\n" + "14:07:34 redisvl.index.index INFO Index already exists, not overwriting.\n" ] } ], @@ -415,14 +435,14 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "15:17:42 redisvl.index.index INFO Index already exists, not overwriting.\n" + "14:07:34 redisvl.index.index INFO Index already exists, not overwriting.\n" ] } ], @@ -441,7 +461,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -451,7 +471,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -462,7 +482,7 @@ ], "metadata": { "kernelspec": { - "display_name": "rvl", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -476,7 +496,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.14" + "version": "3.11.9" }, "orig_nbformat": 4 }, diff --git a/docs/user_guide/index.md b/docs/user_guide/index.md index e5633ba6..b6592e3d 100644 --- a/docs/user_guide/index.md +++ b/docs/user_guide/index.md @@ -12,12 +12,12 @@ User guides provide helpful resources for using RedisVL and its different compon :caption: User Guides :maxdepth: 2 -getting_started_01 -hybrid_queries_02 -llmcache_03 -vectorizers_04 -hash_vs_json_05 -rerankers_06 -session_manager_07 -semantic_router_08 +01_getting_started +02_hybrid_queries +03_llmcache +04_vectorizers +05_hash_vs_json +06_rerankers +07_session_manager +08_semantic_router ``` diff --git a/docs/user_guide/router.yaml b/docs/user_guide/router.yaml index ec0453c4..38aecfdd 100644 --- a/docs/user_guide/router.yaml +++ b/docs/user_guide/router.yaml @@ -8,6 +8,7 @@ routes: metadata: category: tech priority: '1' + distance_threshold: 1.0 - name: sports references: - who won the game last night? @@ -18,6 +19,7 @@ routes: metadata: category: sports priority: '2' + distance_threshold: 0.5 - name: entertainment references: - what are the top movies right now? @@ -26,10 +28,11 @@ routes: metadata: category: entertainment priority: '3' + distance_threshold: 0.7 vectorizer: type: hf model: sentence-transformers/all-mpnet-base-v2 routing_config: - distance_threshold: 1.0 + distance_threshold: 0.5 max_k: 3 aggregation_method: min diff --git a/docs/user_guide/vectorizers_04.ipynb b/docs/user_guide/vectorizers_04.ipynb deleted file mode 100644 index 5f6997a1..00000000 --- a/docs/user_guide/vectorizers_04.ipynb +++ /dev/null @@ -1,974 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 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", - "\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", - "\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", - "This will run Redis on port 6379 and RedisInsight at http://localhost:8001." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# import necessary modules\n", - "import os" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating Text Embeddings\n", - "\n", - "This example will show how to create an embedding from 3 simple sentences with a number of different text vectorizers in RedisVL.\n", - "\n", - "- \"That is a happy dog\"\n", - "- \"That is a happy person\"\n", - "- \"Today is a nice day\"\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### OpenAI\n", - "\n", - "The ``OpenAITextVectorizer`` makes it simple to use RedisVL with the embeddings models at OpenAI. For this you will need to install ``openai``. \n", - "\n", - "```bash\n", - "pip install openai\n", - "```\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "\n", - "# setup the API Key\n", - "api_key = os.environ.get(\"OPENAI_API_KEY\") or getpass.getpass(\"Enter your OpenAI API key: \")" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Vector dimensions: 1536\n" - ] - }, - { - "data": { - "text/plain": [ - "[-0.0010508307022973895,\n", - " -0.0031670420430600643,\n", - " 0.0023781107738614082,\n", - " -0.004539588466286659,\n", - " -0.010320774279534817,\n", - " 0.012868634425103664,\n", - " -0.0054513863287866116,\n", - " -0.002984359161928296,\n", - " -0.0072814482264220715,\n", - " -0.033704183995723724]" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from redisvl.utils.vectorize import OpenAITextVectorizer\n", - "\n", - "# create a vectorizer\n", - "oai = OpenAITextVectorizer(\n", - " model=\"text-embedding-ada-002\",\n", - " api_config={\"api_key\": api_key},\n", - ")\n", - "\n", - "test = oai.embed(\"This is a test sentence.\")\n", - "print(\"Vector dimensions: \", len(test))\n", - "test[:10]" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[-0.01749197021126747,\n", - " -5.238811718299985e-05,\n", - " 0.0013331907102838159,\n", - " -0.025576923042535782,\n", - " -0.019907286390662193,\n", - " 0.016106342896819115,\n", - " -0.003756451653316617,\n", - " 0.0009971122490242124,\n", - " 0.006661186460405588,\n", - " -0.024954024702310562]" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Create many embeddings at once\n", - "sentences = [\n", - " \"That is a happy dog\",\n", - " \"That is a happy person\",\n", - " \"Today is a sunny day\"\n", - "]\n", - "\n", - "embeddings = oai.embed_many(sentences)\n", - "embeddings[0][:10]" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of Embeddings: 3\n" - ] - } - ], - "source": [ - "# openai also supports asyncronous requests, which we can use to speed up the vectorization process.\n", - "embeddings = await oai.aembed_many(sentences)\n", - "print(\"Number of Embeddings:\", len(embeddings))\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Azure OpenAI\n", - "\n", - "The ``AzureOpenAITextVectorizer`` is a variation of the OpenAI vectorizer that calls OpenAI models within Azure. If you've already installed ``openai``, then you're ready to use Azure OpenAI.\n", - "\n", - "The only practical difference between OpenAI and Azure OpenAI is the variables required to call the API." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# additionally to the API Key, setup the API endpoint and version\n", - "api_key = os.environ.get(\"AZURE_OPENAI_API_KEY\") or getpass.getpass(\"Enter your AzureOpenAI API key: \")\n", - "api_version = os.environ.get(\"OPENAI_API_VERSION\") or getpass.getpass(\"Enter your AzureOpenAI API version: \")\n", - "azure_endpoint = os.environ.get(\"AZURE_OPENAI_ENDPOINT\") or getpass.getpass(\"Enter your AzureOpenAI API endpoint: \")\n", - "deployment_name = os.environ.get(\"AZURE_OPENAI_DEPLOYMENT_NAME\", \"text-embedding-ada-002\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Vector dimensions: 1536\n" - ] - }, - { - "data": { - "text/plain": [ - "[-0.0010088568087667227,\n", - " -0.003142790636047721,\n", - " 0.0024922797456383705,\n", - " -0.004522906616330147,\n", - " -0.010369433090090752,\n", - " 0.012739036232233047,\n", - " -0.005365503951907158,\n", - " -0.0029668458737432957,\n", - " -0.007141091860830784,\n", - " -0.03383301943540573]" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from redisvl.utils.vectorize import AzureOpenAITextVectorizer\n", - "\n", - "# create a vectorizer\n", - "az_oai = AzureOpenAITextVectorizer(\n", - " model=deployment_name, # Must be your CUSTOM deployment name\n", - " api_config={\n", - " \"api_key\": api_key,\n", - " \"api_version\": api_version,\n", - " \"azure_endpoint\": azure_endpoint\n", - " },\n", - ")\n", - "\n", - "test = az_oai.embed(\"This is a test sentence.\")\n", - "print(\"Vector dimensions: \", len(test))\n", - "test[:10]" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[-0.017460526898503304,\n", - " -6.895032856846228e-05,\n", - " 0.0013909287517890334,\n", - " -0.025688467547297478,\n", - " -0.019813183695077896,\n", - " 0.016087085008621216,\n", - " -0.003729278687387705,\n", - " 0.0009211922879330814,\n", - " 0.006606514099985361,\n", - " -0.025128915905952454]" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Just like OpenAI, AzureOpenAI supports batching embeddings and asynchronous requests.\n", - "sentences = [\n", - " \"That is a happy dog\",\n", - " \"That is a happy person\",\n", - " \"Today is a sunny day\"\n", - "]\n", - "\n", - "embeddings = await az_oai.aembed_many(sentences)\n", - "embeddings[0][:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Huggingface\n", - "\n", - "[Huggingface](https://huggingface.co/models) is a popular NLP platform that has a number of pre-trained models you can use off the shelf. RedisVL supports using Huggingface \"Sentence Transformers\" to create embeddings from text. To use Huggingface, you will need to install the ``sentence-transformers`` library.\n", - "\n", - "```bash\n", - "pip install sentence-transformers\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0.0003780885017476976,\n", - " -0.05080340430140495,\n", - " -0.035147231072187424,\n", - " -0.02325103059411049,\n", - " -0.04415831342339516,\n", - " 0.02048780582845211,\n", - " 0.0014618589775636792,\n", - " 0.03126184269785881,\n", - " 0.05605152249336243,\n", - " 0.018815429881215096]" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "os.environ[\"TOKENIZERS_PARALLELISM\"] = \"false\"\n", - "from redisvl.utils.vectorize import HFTextVectorizer\n", - "\n", - "\n", - "# create a vectorizer\n", - "# choose your model from the huggingface website\n", - "hf = HFTextVectorizer(model=\"sentence-transformers/all-mpnet-base-v2\")\n", - "\n", - "# embed a sentence\n", - "test = hf.embed(\"This is a test sentence.\")\n", - "test[:10]" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# You can also create many embeddings at once\n", - "embeddings = hf.embed_many(sentences, as_buffer=True, dtype=\"float32\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### VertexAI\n", - "\n", - "[VertexAI](https://cloud.google.com/vertex-ai/docs/generative-ai/embeddings/get-text-embeddings) is GCP's fully-featured AI platform including a number of pretrained LLMs. RedisVL supports using VertexAI to create embeddings from these models. To use VertexAI, you will first need to install the ``google-cloud-aiplatform`` library.\n", - "\n", - "```bash\n", - "pip install google-cloud-aiplatform>=1.26\n", - "```\n", - "\n", - "1. Then you need to gain access to a [Google Cloud Project](https://cloud.google.com/gcp?hl=en) and provide [access to credentials](https://cloud.google.com/docs/authentication/application-default-credentials). This is accomplished by setting the `GOOGLE_APPLICATION_CREDENTIALS` environment variable pointing to the path of a JSON key file downloaded from your service account on GCP.\n", - "2. Lastly, you need to find your [project ID](https://support.google.com/googleapi/answer/7014113?hl=en) and [geographic region for VertexAI](https://cloud.google.com/vertex-ai/docs/general/locations).\n", - "\n", - "\n", - "**Make sure the following env vars are set:**\n", - "\n", - "```\n", - "GOOGLE_APPLICATION_CREDENTIALS=\n", - "GCP_PROJECT_ID=\n", - "GCP_LOCATION=\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0.04373306408524513,\n", - " -0.05040992051362991,\n", - " -0.011946038343012333,\n", - " -0.043528858572244644,\n", - " 0.021510830149054527,\n", - " 0.028604144230484962,\n", - " 0.014770914800465107,\n", - " -0.01610461436212063,\n", - " -0.0036560404114425182,\n", - " 0.013746795244514942]" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from redisvl.utils.vectorize import VertexAITextVectorizer\n", - "\n", - "\n", - "# create a vectorizer\n", - "vtx = VertexAITextVectorizer(api_config={\n", - " \"project_id\": os.environ.get(\"GCP_PROJECT_ID\") or getpass.getpass(\"Enter your GCP Project ID: \"),\n", - " \"location\": os.environ.get(\"GCP_LOCATION\") or getpass.getpass(\"Enter your GCP Location: \"),\n", - " \"google_application_credentials\": os.environ.get(\"GOOGLE_APPLICATION_CREDENTIALS\") or getpass.getpass(\"Enter your Google App Credentials path: \")\n", - "})\n", - "\n", - "# embed a sentence\n", - "test = vtx.embed(\"This is a test sentence.\")\n", - "test[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Cohere\n", - "\n", - "[Cohere](https://dashboard.cohere.ai/) allows you to implement language AI into your product. The `CohereTextVectorizer` makes it simple to use RedisVL with the embeddings models at Cohere. For this you will need to install `cohere`.\n", - "\n", - "```bash\n", - "pip install cohere\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "# setup the API Key\n", - "api_key = os.environ.get(\"COHERE_API_KEY\") or getpass.getpass(\"Enter your Cohere API key: \")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Special attention needs to be paid to the `input_type` parameter for each `embed` call. For example, for embedding \n", - "queries, you should set `input_type='search_query'`; for embedding documents, set `input_type='search_document'`. See\n", - "more information [here](https://docs.cohere.com/reference/embed)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Vector dimensions: 1024\n", - "[-0.010856628, -0.019683838, -0.0062179565, 0.003545761, -0.047943115, 0.0009365082, -0.005924225, 0.016174316, -0.03289795, 0.049194336]\n", - "Vector dimensions: 1024\n", - "[-0.009712219, -0.016036987, 2.8073788e-05, -0.022491455, -0.041259766, 0.002281189, -0.033294678, -0.00057029724, -0.026260376, 0.0579834]\n" - ] - } - ], - "source": [ - "from redisvl.utils.vectorize import CohereTextVectorizer\n", - "\n", - "# create a vectorizer\n", - "co = CohereTextVectorizer(\n", - " model=\"embed-english-v3.0\",\n", - " api_config={\"api_key\": api_key},\n", - ")\n", - "\n", - "# embed a search query\n", - "test = co.embed(\"This is a test sentence.\", input_type='search_query')\n", - "print(\"Vector dimensions: \", len(test))\n", - "print(test[:10])\n", - "\n", - "# embed a document\n", - "test = co.embed(\"This is a test sentence.\", input_type='search_document')\n", - "print(\"Vector dimensions: \", len(test))\n", - "print(test[:10])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Learn more about using RedisVL and Cohere together through [this dedicated user guide](https://docs.cohere.com/docs/redis-and-cohere)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### VoyageAI\n", - "\n", - "[VoyageAI](https://dash.voyageai.com/) allows you to implement language AI into your product. The `VoyageAITextVectorizer` makes it simple to use RedisVL with the embeddings models at VoyageAI. For this you will need to install `voyageai`.\n", - "\n", - "```bash\n", - "pip install voyageai\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "# setup the API Key\n", - "api_key = os.environ.get(\"VOYAGE_API_KEY\") or getpass.getpass(\"Enter your VoyageAI API key: \")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Special attention needs to be paid to the `input_type` parameter for each `embed` call. For example, for embedding \n", - "queries, you should set `input_type='query'`; for embedding documents, set `input_type='document'`. See\n", - "more information [here](https://docs.voyageai.com/docs/embeddings)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Vector dimensions: 1024\n", - "[0.015814896672964096, 0.046988241374492645, -0.00518248463049531, -0.05383478105068207, -0.015586535446345806, -0.0837097093462944, 0.03744547441601753, -0.007797810714691877, 0.00717928446829319, 0.06857716292142868]\n", - "Vector dimensions: 1024\n", - "[0.006725038401782513, 0.01441393606364727, -0.030212024226784706, -0.06782275438308716, -0.021446991711854935, -0.07667966187000275, 0.01804908737540245, -0.015767497941851616, -0.02152789570391178, 0.049741245806217194]\n" - ] - } - ], - "source": [ - "from redisvl.utils.vectorize import VoyageAITextVectorizer\n", - "\n", - "# create a vectorizer\n", - "vo = VoyageAITextVectorizer(\n", - " model=\"voyage-law-2\", # Please check the available models at https://docs.voyageai.com/docs/embeddings\n", - " api_config={\"api_key\": api_key},\n", - ")\n", - "\n", - "# embed a search query\n", - "test = vo.embed(\"This is a test sentence.\", input_type='query')\n", - "print(\"Vector dimensions: \", len(test))\n", - "print(test[:10])\n", - "\n", - "# embed a document\n", - "test = vo.embed(\"This is a test sentence.\", input_type='document')\n", - "print(\"Vector dimensions: \", len(test))\n", - "print(test[:10])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Mistral AI\n", - "\n", - "[Mistral](https://console.mistral.ai/) offers LLM and embedding APIs for you to implement into your product. The `MistralAITextVectorizer` makes it simple to use RedisVL with their embeddings model.\n", - "You will need to install `mistralai`.\n", - "\n", - "```bash\n", - "pip install mistralai\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Vector dimensions: 1024\n", - "[-0.02801513671875, 0.02532958984375, 0.04278564453125, 0.0185699462890625, 0.041015625, 0.006053924560546875, 0.03607177734375, -0.0030155181884765625, 0.0033893585205078125, -0.01390838623046875]\n" - ] - } - ], - "source": [ - "from redisvl.utils.vectorize import MistralAITextVectorizer\n", - "\n", - "mistral = MistralAITextVectorizer()\n", - "\n", - "# embed a sentence using their asyncronous method\n", - "test = await mistral.aembed(\"This is a test sentence.\")\n", - "print(\"Vector dimensions: \", len(test))\n", - "print(test[:10])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Amazon Bedrock\n", - "\n", - "Amazon Bedrock provides fully managed foundation models for text embeddings. Install the required dependencies:\n", - "\n", - "```bash\n", - "pip install 'redisvl[bedrock]' # Installs boto3\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Configure AWS credentials:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import getpass\n", - "\n", - "if \"AWS_ACCESS_KEY_ID\" not in os.environ:\n", - " os.environ[\"AWS_ACCESS_KEY_ID\"] = getpass.getpass(\"Enter AWS Access Key ID: \")\n", - "if \"AWS_SECRET_ACCESS_KEY\" not in os.environ:\n", - " os.environ[\"AWS_SECRET_ACCESS_KEY\"] = getpass.getpass(\"Enter AWS Secret Key: \")\n", - "\n", - "os.environ[\"AWS_REGION\"] = \"us-east-1\" # Change as needed" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Create embeddings:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Vector dimensions: 1024\n" - ] - } - ], - "source": [ - "from redisvl.utils.vectorize import BedrockTextVectorizer\n", - "\n", - "bedrock = BedrockTextVectorizer(\n", - " model=\"amazon.titan-embed-text-v2:0\"\n", - ")\n", - "\n", - "# Single embedding\n", - "text = \"This is a test sentence.\"\n", - "embedding = bedrock.embed(text)\n", - "print(f\"Vector dimensions: {len(embedding)}\")\n", - "\n", - "# Multiple embeddings\n", - "sentences = [\n", - " \"That is a happy dog\",\n", - " \"That is a happy person\",\n", - " \"Today is a sunny day\"\n", - "]\n", - "embeddings = bedrock.embed_many(sentences)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Custom Vectorizers\n", - "\n", - "RedisVL supports the use of other vectorizers and provides a class to enable compatibility with any function that generates a vector or vectors from string data" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0.101, 0.101, 0.101, 0.101, 0.101, 0.101, 0.101, 0.101, 0.101, 0.101]" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from redisvl.utils.vectorize import CustomTextVectorizer\n", - "\n", - "def generate_embeddings(text_input, **kwargs):\n", - " return [0.101] * 768\n", - "\n", - "custom_vectorizer = CustomTextVectorizer(generate_embeddings)\n", - "\n", - "custom_vectorizer.embed(\"This is a test sentence.\")[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This enables the use of custom vectorizers with other RedisVL components" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "11:04:14 redisvl.index.index INFO Index already exists, not overwriting.\n" - ] - }, - { - "data": { - "text/plain": [ - "[{'id': 'llmcache:78bd2446a37a0c6ab62652af9b7e53845145c4471ea83ff9fb4280a528d36bbb',\n", - " 'vector_distance': '6.13927841187e-06',\n", - " 'prompt': 'this is a test prompt',\n", - " 'response': 'this is a test response',\n", - " 'prompt_vector': '\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17=\\x17='}]" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from redisvl.extensions.llmcache import SemanticCache\n", - "\n", - "cache = SemanticCache(name=\"custom_cache\", vectorizer=custom_vectorizer)\n", - "\n", - "cache.store(\"this is a test prompt\", \"this is a test response\")\n", - "cache.check(\"this is also a test prompt\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Search with Provider Embeddings\n", - "\n", - "Now that we've created our embeddings, we can use them to search for similar sentences. We will use the same 3 sentences from above and search for similar sentences.\n", - "\n", - "First, we need to create the schema for our index.\n", - "\n", - "Here's what the schema for the example looks like in yaml for the HuggingFace vectorizer:\n", - "\n", - "```yaml\n", - "version: '0.1.0'\n", - "\n", - "index:\n", - " name: vectorizers\n", - " prefix: doc\n", - " storage_type: hash\n", - "\n", - "fields:\n", - " - name: sentence\n", - " type: text\n", - " - name: embedding\n", - " type: vector\n", - " attrs:\n", - " dims: 768\n", - " algorithm: flat\n", - " distance_metric: cosine\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "from redisvl.index import SearchIndex\n", - "\n", - "# construct a search index from the schema\n", - "index = SearchIndex.from_yaml(\"./schema.yaml\")\n", - "\n", - "# connect to local redis instance\n", - "index.connect(\"redis://localhost:6379\")\n", - "\n", - "# create the index (no data yet)\n", - "index.create(overwrite=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[32m20:22:42\u001b[0m \u001b[34m[RedisVL]\u001b[0m \u001b[1;30mINFO\u001b[0m Indices:\n", - "\u001b[32m20:22:42\u001b[0m \u001b[34m[RedisVL]\u001b[0m \u001b[1;30mINFO\u001b[0m 1. vectorizers\n" - ] - } - ], - "source": [ - "# use the CLI to see the created index\n", - "!rvl index listall" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Loading data to RedisVL is easy. It expects a list of dictionaries. The vector is stored as bytes." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['doc:529c6d58da9e4be4a29dd0481f59c286',\n", - " 'doc:81aa1ef8a9494b299e8593548d0af34a',\n", - " 'doc:6ab03d6da8f041ffa3fdb83996d3b297']" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from redisvl.redis.utils import array_to_buffer\n", - "\n", - "embeddings = hf.embed_many(sentences)\n", - "\n", - "data = [{\"text\": t,\n", - " \"embedding\": array_to_buffer(v, dtype=\"float32\")}\n", - " for t, v in zip(sentences, embeddings)]\n", - "\n", - "index.load(data)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "That is a happy dog 0.160862207413\n", - "That is a happy dog 0.160862207413\n", - "That is a happy person 0.273598313332\n" - ] - } - ], - "source": [ - "from redisvl.query import VectorQuery\n", - "\n", - "# use the HuggingFace vectorizer again to create a query embedding\n", - "query_embedding = hf.embed(\"That is a happy cat\")\n", - "\n", - "query = VectorQuery(\n", - " vector=query_embedding,\n", - " vector_field_name=\"embedding\",\n", - " return_fields=[\"text\"],\n", - " num_results=3\n", - ")\n", - "\n", - "results = index.query(query)\n", - "for doc in results:\n", - " print(doc[\"text\"], doc[\"vector_distance\"])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Selecting your float data type\n", - "When embedding text as byte arrays RedisVL supports 4 different floating point data types, `float16`, `float32`, `float64` and `bfloat16`.\n", - "Your dtype set for your vectorizer must match what is defined in your search index. If one is not explicitly set the default is `float32`." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vectorizer = HFTextVectorizer(dtype=\"float16\")\n", - "\n", - "# subsequent calls to embed('', as_buffer=True) and embed_many('', as_buffer=True) will now encode as float16\n", - "float16_bytes = vectorizer.embed('test sentence', as_buffer=True)\n", - "\n", - "# you can override this setting on each individual method call\n", - "float64_bytes = vectorizer.embed('test sentence', as_buffer=True, dtype=\"float64\")\n", - "\n", - "float16_bytes != float64_bytes" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "# cleanup\n", - "index.delete()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "redisvl-dev", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.2" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/poetry.lock b/poetry.lock index b3f9f669..53e07571 100644 --- a/poetry.lock +++ b/poetry.lock @@ -25,8 +25,6 @@ version = "2.4.6" description = "Happy Eyeballs for asyncio" optional = true python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"voyageai\"" files = [ {file = "aiohappyeyeballs-2.4.6-py3-none-any.whl", hash = "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1"}, {file = "aiohappyeyeballs-2.4.6.tar.gz", hash = "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0"}, @@ -398,19 +396,19 @@ css = ["tinycss2 (>=1.1.0,<1.5)"] [[package]] name = "boto3" -version = "1.36.18" +version = "1.36.17" description = "The AWS SDK for Python" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"bedrock\"" files = [ - {file = "boto3-1.36.18-py3-none-any.whl", hash = "sha256:084ff25af2d7bda3102d6367f5453e2e83f8cde1da73079ea144595b03cb9400"}, - {file = "boto3-1.36.18.tar.gz", hash = "sha256:be8e32c34d7b103a64fafdd277fa1ec136733b4bbfc11dcfa597efa36a820b37"}, + {file = "boto3-1.36.17-py3-none-any.whl", hash = "sha256:59bcf0c4b04d9cc36f8b418ad17ab3c4a99a21a175d2fad7096aa21cbe84630b"}, + {file = "boto3-1.36.17.tar.gz", hash = "sha256:5ecae20e780a3ce9afb3add532b61c466a8cb8960618e4fa565b3883064c1346"}, ] [package.dependencies] -botocore = ">=1.36.18,<1.37.0" +botocore = ">=1.36.17,<1.37.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.11.0,<0.12.0" @@ -419,15 +417,15 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.36.18" +version = "1.36.17" description = "Low-level, data-driven core of boto 3." optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"bedrock\"" files = [ - {file = "botocore-1.36.18-py3-none-any.whl", hash = "sha256:7898d109affd9231c555e71fda88308c1da2db8d39e83d33eb8cb40ebf1ba82f"}, - {file = "botocore-1.36.18.tar.gz", hash = "sha256:ddadafe460e91f11677720a2fcc3ea09c4abb914de2b000da7ba46b4c97da3d7"}, + {file = "botocore-1.36.17-py3-none-any.whl", hash = "sha256:069858b2fd693548035d7fd53a774e37e4260fea64e0ac9b8a3aee904f9321df"}, + {file = "botocore-1.36.17.tar.gz", hash = "sha256:cec13e0a7ce78e71aad0b397581b4e81824c7981ef4c261d2e296d200c399b09"}, ] [package.dependencies] @@ -2605,6 +2603,7 @@ files = [ numpy = [ {version = ">1.20", markers = "python_version < \"3.10\""}, {version = ">=1.21.2", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.23.3", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] @@ -5274,16 +5273,27 @@ files = [ {file = "SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5dba1cdb8f319084f5b00d41207b2079822aa8d6a4667c0f369fce85e34b0c86"}, {file = "SQLAlchemy-2.0.38-cp313-cp313-win32.whl", hash = "sha256:eae27ad7580529a427cfdd52c87abb2dfb15ce2b7a3e0fc29fbb63e2ed6f8120"}, {file = "SQLAlchemy-2.0.38-cp313-cp313-win_amd64.whl", hash = "sha256:b335a7c958bc945e10c522c069cd6e5804f4ff20f9a744dd38e748eb602cbbda"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40310db77a55512a18827488e592965d3dec6a3f1e3d8af3f8243134029daca3"}, {file = "SQLAlchemy-2.0.38-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d3043375dd5bbcb2282894cbb12e6c559654c67b5fffb462fda815a55bf93f7"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70065dfabf023b155a9c2a18f573e47e6ca709b9e8619b2e04c54d5bcf193178"}, {file = "SQLAlchemy-2.0.38-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:c058b84c3b24812c859300f3b5abf300daa34df20d4d4f42e9652a4d1c48c8a4"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0398361acebb42975deb747a824b5188817d32b5c8f8aba767d51ad0cc7bb08d"}, {file = "SQLAlchemy-2.0.38-cp37-cp37m-win32.whl", hash = "sha256:a2bc4e49e8329f3283d99840c136ff2cd1a29e49b5624a46a290f04dff48e079"}, {file = "SQLAlchemy-2.0.38-cp37-cp37m-win_amd64.whl", hash = "sha256:9cd136184dd5f58892f24001cdce986f5d7e96059d004118d5410671579834a4"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:665255e7aae5f38237b3a6eae49d2358d83a59f39ac21036413fab5d1e810578"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:92f99f2623ff16bd4aaf786ccde759c1f676d39c7bf2855eb0b540e1ac4530c8"}, {file = "SQLAlchemy-2.0.38-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa498d1392216fae47eaf10c593e06c34476ced9549657fca713d0d1ba5f7248"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9afbc3909d0274d6ac8ec891e30210563b2c8bdd52ebbda14146354e7a69373"}, {file = "SQLAlchemy-2.0.38-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:57dd41ba32430cbcc812041d4de8d2ca4651aeefad2626921ae2a23deb8cd6ff"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3e35d5565b35b66905b79ca4ae85840a8d40d31e0b3e2990f2e7692071b179ca"}, {file = "SQLAlchemy-2.0.38-cp38-cp38-win32.whl", hash = "sha256:f0d3de936b192980209d7b5149e3c98977c3810d401482d05fb6d668d53c1c63"}, {file = "SQLAlchemy-2.0.38-cp38-cp38-win_amd64.whl", hash = "sha256:3868acb639c136d98107c9096303d2d8e5da2880f7706f9f8c06a7f961961149"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07258341402a718f166618470cde0c34e4cec85a39767dce4e24f61ba5e667ea"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a826f21848632add58bef4f755a33d45105d25656a0c849f2dc2df1c71f6f50"}, {file = "SQLAlchemy-2.0.38-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:386b7d136919bb66ced64d2228b92d66140de5fefb3c7df6bd79069a269a7b06"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f2951dc4b4f990a4b394d6b382accb33141d4d3bd3ef4e2b27287135d6bdd68"}, {file = "SQLAlchemy-2.0.38-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8bf312ed8ac096d674c6aa9131b249093c1b37c35db6a967daa4c84746bc1bc9"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6db316d6e340f862ec059dc12e395d71f39746a20503b124edc255973977b728"}, {file = "SQLAlchemy-2.0.38-cp39-cp39-win32.whl", hash = "sha256:c09a6ea87658695e527104cf857c70f79f14e9484605e205217aae0ec27b45fc"}, {file = "SQLAlchemy-2.0.38-cp39-cp39-win_amd64.whl", hash = "sha256:12f5c9ed53334c3ce719155424dc5407aaa4f6cadeb09c5b627e06abb93933a1"}, {file = "SQLAlchemy-2.0.38-py3-none-any.whl", hash = "sha256:63178c675d4c80def39f1febd625a6333f44c0ba269edd8a468b156394b27753"}, @@ -5871,7 +5881,6 @@ version = "75.8.0.20250210" description = "Typing stubs for setuptools" optional = false python-versions = ">=3.9" -groups = ["dev"] files = [ {file = "types_setuptools-75.8.0.20250210-py3-none-any.whl", hash = "sha256:a217d7b4d59be04c29e23d142c959a0f85e71292fd3fc4313f016ca11f0b56dc"}, {file = "types_setuptools-75.8.0.20250210.tar.gz", hash = "sha256:c1547361b2441f07c94e25dce8a068e18c611593ad4b6fdd727b1a8f5d1fda33"}, diff --git a/redisvl/extensions/router/schema.py b/redisvl/extensions/router/schema.py index bb0a7baf..7b259c76 100644 --- a/redisvl/extensions/router/schema.py +++ b/redisvl/extensions/router/schema.py @@ -16,7 +16,7 @@ class Route(BaseModel): """List of reference phrases for the route.""" metadata: Dict[str, str] = Field(default={}) """Metadata associated with the route.""" - distance_threshold: Optional[float] = Field(default=0.5) + distance_threshold: float = Field(default=0.5) """Distance threshold for matching the route.""" @validator("name") @@ -70,6 +70,12 @@ class RoutingConfig(BaseModel): aggregation_method: DistanceAggregationMethod = Field( default=DistanceAggregationMethod.avg ) + distance_threshold: float = Field( + default=0.5, + deprecated=True, + description="Global distance threshold is deprecated all distance_thresholds now apply at route level.", + ) + """Aggregation method to use to classify queries.""" @validator("max_k") @@ -78,12 +84,6 @@ def max_k_must_be_positive(cls, v): raise ValueError("max_k must be a positive integer") return v - @validator("distance_threshold") - def distance_threshold_must_be_valid(cls, v): - if v <= 0 or v > 1: - raise ValueError("distance_threshold must be between 0 and 1") - return v - class SemanticRouterIndexSchema(IndexSchema): """Customized index schema for SemanticRouter.""" diff --git a/redisvl/extensions/router/semantic.py b/redisvl/extensions/router/semantic.py index c5eca8c4..bdfdf862 100644 --- a/redisvl/extensions/router/semantic.py +++ b/redisvl/extensions/router/semantic.py @@ -215,6 +215,17 @@ def _process_route(self, result: Dict[str, Any]) -> RouteMatch: name=route_dict["route_name"], distance=float(route_dict["distance"]) ) + def _distance_threshold_filter(self) -> str: + """Apply distance threshold on a route by route basis.""" + filter = "" + for i, route in enumerate(self.routes): + filter_str = f"(@route_name == '{route.name}' && @distance < {route.distance_threshold})" + if i > 0: + filter += " || " + filter += filter_str + + return filter + def _build_aggregate_request( self, vector_range_query: RangeQuery, @@ -241,15 +252,26 @@ def _build_aggregate_request( .dialect(2) ) + filter = self._distance_threshold_filter() + + aggregate_request.filter(filter) + return aggregate_request - def _classify_route( + def _get_route_matches( self, vector: List[float], - distance_threshold: float, aggregation_method: DistanceAggregationMethod, - ) -> RouteMatch: - """Classify to a single route using a vector.""" + max_k: int = 1, + ) -> List[RouteMatch]: + """Get the route matches for a given vector and aggregation method.""" + + thresholds: List[float] = [route.distance_threshold for route in self.routes] + if thresholds: + distance_threshold = max(thresholds) + else: + raise ValueError("No distance thresholds provided for the semantic router") + vector_range_query = RangeQuery( vector=vector, vector_field_name=ROUTE_VECTOR_FIELD_NAME, @@ -258,7 +280,7 @@ def _classify_route( ) aggregate_request = self._build_aggregate_request( - vector_range_query, aggregation_method, max_k=1 + vector_range_query, aggregation_method, max_k=max_k ) try: @@ -273,110 +295,63 @@ def _classify_route( raise e # process aggregation results into route matches - route_matches = [ + return [ self._process_route(route_match) for route_match in aggregation_result.rows ] + def _classify_route( + self, + vector: List[float], + aggregation_method: DistanceAggregationMethod, + ) -> RouteMatch: + """Classify to a single route using a vector.""" + + # take max route as distance threshold + route_matches = self._get_route_matches(vector, aggregation_method) + + if not route_matches: + return RouteMatch() + # process route matches - if route_matches: - top_route_match = route_matches[0] - if top_route_match.name is not None: - if route := self.get(top_route_match.name): - # use the matched route's distance threshold - _distance_threshold = route.distance_threshold or distance_threshold - if self._pass_threshold(top_route_match, _distance_threshold): - return top_route_match - else: - raise ValueError( - f"{top_route_match.name} not a supported route for the {self.name} semantic router." - ) + top_route_match = route_matches[0] - # fallback to empty route match if no hits - return RouteMatch() + if top_route_match.name is not None: + return top_route_match + else: + raise ValueError( + f"{top_route_match.name} not a supported route for the {self.name} semantic router." + ) def _classify_multi_route( self, vector: List[float], max_k: int, - distance_threshold: float, aggregation_method: DistanceAggregationMethod, ) -> List[RouteMatch]: """Classify to multiple routes, up to max_k (int), using a vector.""" - # Set range query distance threshold to get all possible results to be further filtered - distance_threshold = max(route.distance_threshold for route in self.routes) - - vector_range_query = RangeQuery( - vector=vector, - vector_field_name=ROUTE_VECTOR_FIELD_NAME, - distance_threshold=distance_threshold, - return_fields=["route_name"], - ) - - aggregate_request = self._build_aggregate_request( - vector_range_query, aggregation_method, max_k - ) - - try: - aggregation_result: AggregateResult = self._index.aggregate( - aggregate_request, vector_range_query.params - ) - except ResponseError as e: - if "VSS is not yet supported on FT.AGGREGATE" in str(e): - raise RuntimeError( - "Semantic routing is only available on Redis version 7.x.x or greater" - ) - raise e - - # process aggregation results into route matches - route_matches = [ - self._process_route(route_match) for route_match in aggregation_result.rows - ] + route_matches = self._get_route_matches(vector, aggregation_method, max_k) # process route matches top_route_matches: List[RouteMatch] = [] if route_matches: for route_match in route_matches: if route_match.name is not None: - if route := self.get(route_match.name): - # use the matched route's distance threshold - _distance_threshold = ( - route.distance_threshold or distance_threshold - ) - if self._pass_threshold(route_match, _distance_threshold): - top_route_matches.append(route_match) - else: - raise ValueError( - f"{route_match.name} not a supported route for the {self.name} semantic router." - ) + top_route_matches.append(route_match) + else: + raise ValueError( + f"{route_match.name} not a supported route for the {self.name} semantic router." + ) return top_route_matches - def _pass_threshold( - self, route_match: Optional[RouteMatch], distance_threshold: float - ) -> bool: - """Check if a route match passes the distance threshold. - - Args: - route_match (Optional[RouteMatch]): The route match to check. - distance_threshold (float): The fallback distance threshold to use if not assigned to a route. - - Returns: - bool: True if the route match passes the threshold, False otherwise. - """ - if route_match and distance_threshold: - if route_match.distance is not None: - return route_match.distance <= distance_threshold - return False - + @deprecated_argument("distance_threshold") def __call__( self, statement: Optional[str] = None, vector: Optional[List[float]] = None, - distance_threshold: Optional[ - float - ] = None, # TODO: does this get removed if route becomes the owner of a distance threshold? Or do we apply to all? aggregation_method: Optional[DistanceAggregationMethod] = None, + distance_threshold: Optional[float] = None, ) -> RouteMatch: """Query the semantic router with a given statement or vector. @@ -394,20 +369,15 @@ def __call__( raise ValueError("Must provide a vector or statement to the router") vector = self.vectorizer.embed(statement) - # override routing config - distance_threshold = ( - distance_threshold or self.routing_config.distance_threshold - ) aggregation_method = ( aggregation_method or self.routing_config.aggregation_method ) # perform route classification - top_route_match = self._classify_route( - vector, distance_threshold, aggregation_method - ) + top_route_match = self._classify_route(vector, aggregation_method) return top_route_match + @deprecated_argument("distance_threshold") def route_many( self, statement: Optional[str] = None, @@ -433,10 +403,6 @@ def route_many( raise ValueError("Must provide a vector or statement to the router") vector = self.vectorizer.embed(statement) - # override routing config defaults - distance_threshold = ( - distance_threshold or self.routing_config.distance_threshold - ) max_k = max_k or self.routing_config.max_k aggregation_method = ( aggregation_method or self.routing_config.aggregation_method @@ -444,8 +410,9 @@ def route_many( # classify routes top_route_matches = self._classify_multi_route( - vector, max_k, distance_threshold, aggregation_method + vector, max_k, aggregation_method ) + return top_route_matches def remove_route(self, route_name: str) -> None: diff --git a/schemas/semantic_router.yaml b/schemas/semantic_router.yaml index 7b504154..25aa08e1 100644 --- a/schemas/semantic_router.yaml +++ b/schemas/semantic_router.yaml @@ -18,6 +18,6 @@ vectorizer: type: hf model: sentence-transformers/all-mpnet-base-v2 routing_config: - distance_threshold: 0.3 max_k: 2 aggregation_method: avg + distance_threshold: 0.3 diff --git a/tests/integration/test_semantic_router.py b/tests/integration/test_semantic_router.py index 04489aec..8f86e575 100644 --- a/tests/integration/test_semantic_router.py +++ b/tests/integration/test_semantic_router.py @@ -358,3 +358,49 @@ def test_deprecated_dtype_argument(routes, redis_url): redis_url=redis_url, overwrite=True, ) + + +def test_deprecated_distance_threshold_argument(routes, redis_url): + router = SemanticRouter( + name="test_pass_through_dtype", + routes=routes, + redis_url=redis_url, + overwrite=True, + ) + with pytest.warns(DeprecationWarning): + router("hello", distance_threshold=0.3) + + +def test_routes_different_distance_thresholds(routes, redis_url): + routes[0].distance_threshold = 0.5 + routes[1].distance_threshold = 0.7 + + router = SemanticRouter( + name="test_routes_different_distance_thresholds", + routes=routes, + redis_url=redis_url, + overwrite=True, + ) + + matches = router.route_many("hello", max_k=2) + assert len(matches) == 2 + assert matches[0].name == "greeting" + assert matches[1].name == "farewell" + + +def test_routes_different_distance_thresholds(routes, redis_url): + routes[0].distance_threshold = 0.5 + + # don't match on second + routes[1].distance_threshold = 0.3 + + router = SemanticRouter( + name="test_routes_different_distance_thresholds", + routes=routes, + redis_url=redis_url, + overwrite=True, + ) + + matches = router.route_many("hello", max_k=2) + assert len(matches) == 1 + assert matches[0].name == "greeting" From 36a2605817ce039223675ad69e9af33e59348813 Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Tue, 11 Feb 2025 15:12:24 -0500 Subject: [PATCH 3/8] fix tests --- tests/unit/test_route_schema.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/tests/unit/test_route_schema.py b/tests/unit/test_route_schema.py index f1ad5cb5..746c1182 100644 --- a/tests/unit/test_route_schema.py +++ b/tests/unit/test_route_schema.py @@ -64,7 +64,6 @@ def test_route_valid_no_threshold(): assert route.name == "Test Route" assert route.references == ["reference1", "reference2"] assert route.metadata == {"key": "value"} - assert route.distance_threshold is None def test_route_invalid_threshold_zero(): @@ -108,18 +107,12 @@ def test_distance_aggregation_method(): def test_routing_config_valid(): - config = RoutingConfig(distance_threshold=0.6, max_k=5) - assert config.distance_threshold == 0.6 + config = RoutingConfig(aggregation_method=DistanceAggregationMethod.min, max_k=5) + assert config.aggregation_method == DistanceAggregationMethod("min") assert config.max_k == 5 def test_routing_config_invalid_max_k(): with pytest.raises(ValidationError) as excinfo: - RoutingConfig(distance_threshold=0.6, max_k=0) + RoutingConfig(max_k=0) assert "max_k must be a positive integer" in str(excinfo.value) - - -def test_routing_config_invalid_distance_threshold(): - with pytest.raises(ValidationError) as excinfo: - RoutingConfig(distance_threshold=1.5, max_k=5) - assert "distance_threshold must be between 0 and 1" in str(excinfo.value) From 7e6c006704b2d5304e049c786f31bded22bffd6b Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Tue, 11 Feb 2025 15:38:43 -0500 Subject: [PATCH 4/8] VSS not yet supported + other tweaks --- poetry.lock | 339 +++++++++++----------- redisvl/extensions/router/schema.py | 7 +- schemas/semantic_router.yaml | 1 - tests/integration/test_semantic_router.py | 15 +- 4 files changed, 184 insertions(+), 178 deletions(-) diff --git a/poetry.lock b/poetry.lock index 53e07571..5a5486e5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -21,105 +21,100 @@ tests = ["hypothesis", "pytest"] [[package]] name = "aiohappyeyeballs" -version = "2.4.6" +version = "2.4.4" description = "Happy Eyeballs for asyncio" optional = true -python-versions = ">=3.9" +python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.4.6-py3-none-any.whl", hash = "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1"}, - {file = "aiohappyeyeballs-2.4.6.tar.gz", hash = "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0"}, + {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, + {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, ] [[package]] name = "aiohttp" -version = "3.11.12" +version = "3.11.11" description = "Async http client/server framework (asyncio)" optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"voyageai\"" files = [ - {file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aa8a8caca81c0a3e765f19c6953416c58e2f4cc1b84829af01dd1c771bb2f91f"}, - {file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84ede78acde96ca57f6cf8ccb8a13fbaf569f6011b9a52f870c662d4dc8cd854"}, - {file = "aiohttp-3.11.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:584096938a001378484aa4ee54e05dc79c7b9dd933e271c744a97b3b6f644957"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392432a2dde22b86f70dd4a0e9671a349446c93965f261dbaecfaf28813e5c42"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:88d385b8e7f3a870146bf5ea31786ef7463e99eb59e31db56e2315535d811f55"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b10a47e5390c4b30a0d58ee12581003be52eedd506862ab7f97da7a66805befb"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b5263dcede17b6b0c41ef0c3ccce847d82a7da98709e75cf7efde3e9e3b5cae"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50c5c7b8aa5443304c55c262c5693b108c35a3b61ef961f1e782dd52a2f559c7"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d1c031a7572f62f66f1257db37ddab4cb98bfaf9b9434a3b4840bf3560f5e788"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:7e44eba534381dd2687be50cbd5f2daded21575242ecfdaf86bbeecbc38dae8e"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:145a73850926018ec1681e734cedcf2716d6a8697d90da11284043b745c286d5"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2c311e2f63e42c1bf86361d11e2c4a59f25d9e7aabdbdf53dc38b885c5435cdb"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ea756b5a7bac046d202a9a3889b9a92219f885481d78cd318db85b15cc0b7bcf"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:526c900397f3bbc2db9cb360ce9c35134c908961cdd0ac25b1ae6ffcaa2507ff"}, - {file = "aiohttp-3.11.12-cp310-cp310-win32.whl", hash = "sha256:b8d3bb96c147b39c02d3db086899679f31958c5d81c494ef0fc9ef5bb1359b3d"}, - {file = "aiohttp-3.11.12-cp310-cp310-win_amd64.whl", hash = "sha256:7fe3d65279bfbee8de0fb4f8c17fc4e893eed2dba21b2f680e930cc2b09075c5"}, - {file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:87a2e00bf17da098d90d4145375f1d985a81605267e7f9377ff94e55c5d769eb"}, - {file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b34508f1cd928ce915ed09682d11307ba4b37d0708d1f28e5774c07a7674cac9"}, - {file = "aiohttp-3.11.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:936d8a4f0f7081327014742cd51d320296b56aa6d324461a13724ab05f4b2933"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de1378f72def7dfb5dbd73d86c19eda0ea7b0a6873910cc37d57e80f10d64e1"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9d45dbb3aaec05cf01525ee1a7ac72de46a8c425cb75c003acd29f76b1ffe94"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:930ffa1925393381e1e0a9b82137fa7b34c92a019b521cf9f41263976666a0d6"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8340def6737118f5429a5df4e88f440746b791f8f1c4ce4ad8a595f42c980bd5"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4016e383f91f2814e48ed61e6bda7d24c4d7f2402c75dd28f7e1027ae44ea204"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c0600bcc1adfaaac321422d615939ef300df81e165f6522ad096b73439c0f58"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:0450ada317a65383b7cce9576096150fdb97396dcfe559109b403c7242faffef"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:850ff6155371fd802a280f8d369d4e15d69434651b844bde566ce97ee2277420"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8fd12d0f989c6099e7b0f30dc6e0d1e05499f3337461f0b2b0dadea6c64b89df"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:76719dd521c20a58a6c256d058547b3a9595d1d885b830013366e27011ffe804"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:97fe431f2ed646a3b56142fc81d238abcbaff08548d6912acb0b19a0cadc146b"}, - {file = "aiohttp-3.11.12-cp311-cp311-win32.whl", hash = "sha256:e10c440d142fa8b32cfdb194caf60ceeceb3e49807072e0dc3a8887ea80e8c16"}, - {file = "aiohttp-3.11.12-cp311-cp311-win_amd64.whl", hash = "sha256:246067ba0cf5560cf42e775069c5d80a8989d14a7ded21af529a4e10e3e0f0e6"}, - {file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e392804a38353900c3fd8b7cacbea5132888f7129f8e241915e90b85f00e3250"}, - {file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8fa1510b96c08aaad49303ab11f8803787c99222288f310a62f493faf883ede1"}, - {file = "aiohttp-3.11.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc065a4285307607df3f3686363e7f8bdd0d8ab35f12226362a847731516e42c"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddb31f8474695cd61fc9455c644fc1606c164b93bff2490390d90464b4655df"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dec0000d2d8621d8015c293e24589d46fa218637d820894cb7356c77eca3259"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3552fe98e90fdf5918c04769f338a87fa4f00f3b28830ea9b78b1bdc6140e0d"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dfe7f984f28a8ae94ff3a7953cd9678550dbd2a1f9bda5dd9c5ae627744c78e"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a481a574af914b6e84624412666cbfbe531a05667ca197804ecc19c97b8ab1b0"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1987770fb4887560363b0e1a9b75aa303e447433c41284d3af2840a2f226d6e0"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a4ac6a0f0f6402854adca4e3259a623f5c82ec3f0c049374133bcb243132baf9"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c96a43822f1f9f69cc5c3706af33239489a6294be486a0447fb71380070d4d5f"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a5e69046f83c0d3cb8f0d5bd9b8838271b1bc898e01562a04398e160953e8eb9"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:68d54234c8d76d8ef74744f9f9fc6324f1508129e23da8883771cdbb5818cbef"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9fd9dcf9c91affe71654ef77426f5cf8489305e1c66ed4816f5a21874b094b9"}, - {file = "aiohttp-3.11.12-cp312-cp312-win32.whl", hash = "sha256:0ed49efcd0dc1611378beadbd97beb5d9ca8fe48579fc04a6ed0844072261b6a"}, - {file = "aiohttp-3.11.12-cp312-cp312-win_amd64.whl", hash = "sha256:54775858c7f2f214476773ce785a19ee81d1294a6bedc5cc17225355aab74802"}, - {file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:413ad794dccb19453e2b97c2375f2ca3cdf34dc50d18cc2693bd5aed7d16f4b9"}, - {file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a93d28ed4b4b39e6f46fd240896c29b686b75e39cc6992692e3922ff6982b4c"}, - {file = "aiohttp-3.11.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d589264dbba3b16e8951b6f145d1e6b883094075283dafcab4cdd564a9e353a0"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5148ca8955affdfeb864aca158ecae11030e952b25b3ae15d4e2b5ba299bad2"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:525410e0790aab036492eeea913858989c4cb070ff373ec3bc322d700bdf47c1"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bd8695be2c80b665ae3f05cb584093a1e59c35ecb7d794d1edd96e8cc9201d7"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0203433121484b32646a5f5ea93ae86f3d9559d7243f07e8c0eab5ff8e3f70e"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd36749a1035c34ba8d8aaf221b91ca3d111532e5ccb5fa8c3703ab1b967ed"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7442662afebbf7b4c6d28cb7aab9e9ce3a5df055fc4116cc7228192ad6cb484"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8a2fb742ef378284a50766e985804bd6adb5adb5aa781100b09befdbfa757b65"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cee3b117a8d13ab98b38d5b6bdcd040cfb4181068d05ce0c474ec9db5f3c5bb"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f6a19bcab7fbd8f8649d6595624856635159a6527861b9cdc3447af288a00c00"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e4cecdb52aaa9994fbed6b81d4568427b6002f0a91c322697a4bfcc2b2363f5a"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:30f546358dfa0953db92ba620101fefc81574f87b2346556b90b5f3ef16e55ce"}, - {file = "aiohttp-3.11.12-cp313-cp313-win32.whl", hash = "sha256:ce1bb21fc7d753b5f8a5d5a4bae99566386b15e716ebdb410154c16c91494d7f"}, - {file = "aiohttp-3.11.12-cp313-cp313-win_amd64.whl", hash = "sha256:f7914ab70d2ee8ab91c13e5402122edbc77821c66d2758abb53aabe87f013287"}, - {file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c3623053b85b4296cd3925eeb725e386644fd5bc67250b3bb08b0f144803e7b"}, - {file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:67453e603cea8e85ed566b2700efa1f6916aefbc0c9fcb2e86aaffc08ec38e78"}, - {file = "aiohttp-3.11.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6130459189e61baac5a88c10019b21e1f0c6d00ebc770e9ce269475650ff7f73"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9060addfa4ff753b09392efe41e6af06ea5dd257829199747b9f15bfad819460"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34245498eeb9ae54c687a07ad7f160053911b5745e186afe2d0c0f2898a1ab8a"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8dc0fba9a74b471c45ca1a3cb6e6913ebfae416678d90529d188886278e7f3f6"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a478aa11b328983c4444dacb947d4513cb371cd323f3845e53caeda6be5589d5"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c160a04283c8c6f55b5bf6d4cad59bb9c5b9c9cd08903841b25f1f7109ef1259"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:edb69b9589324bdc40961cdf0657815df674f1743a8d5ad9ab56a99e4833cfdd"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ee84c2a22a809c4f868153b178fe59e71423e1f3d6a8cd416134bb231fbf6d3"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bf4480a5438f80e0f1539e15a7eb8b5f97a26fe087e9828e2c0ec2be119a9f72"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:e6b2732ef3bafc759f653a98881b5b9cdef0716d98f013d376ee8dfd7285abf1"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f752e80606b132140883bb262a457c475d219d7163d996dc9072434ffb0784c4"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ab3247d58b393bda5b1c8f31c9edece7162fc13265334217785518dd770792b8"}, - {file = "aiohttp-3.11.12-cp39-cp39-win32.whl", hash = "sha256:0d5176f310a7fe6f65608213cc74f4228e4f4ce9fd10bcb2bb6da8fc66991462"}, - {file = "aiohttp-3.11.12-cp39-cp39-win_amd64.whl", hash = "sha256:74bd573dde27e58c760d9ca8615c41a57e719bff315c9adb6f2a4281a28e8798"}, - {file = "aiohttp-3.11.12.tar.gz", hash = "sha256:7603ca26d75b1b86160ce1bbe2787a0b706e592af5b2504e12caa88a217767b0"}, + {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8"}, + {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5"}, + {file = "aiohttp-3.11.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:731468f555656767cda219ab42e033355fe48c85fbe3ba83a349631541715ba2"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb23d8bb86282b342481cad4370ea0853a39e4a32a0042bb52ca6bdde132df43"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f047569d655f81cb70ea5be942ee5d4421b6219c3f05d131f64088c73bb0917f"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd7659baae9ccf94ae5fe8bfaa2c7bc2e94d24611528395ce88d009107e00c6d"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af01e42ad87ae24932138f154105e88da13ce7d202a6de93fafdafb2883a00ef"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5854be2f3e5a729800bac57a8d76af464e160f19676ab6aea74bde18ad19d438"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6526e5fb4e14f4bbf30411216780c9967c20c5a55f2f51d3abd6de68320cc2f3"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:85992ee30a31835fc482468637b3e5bd085fa8fe9392ba0bdcbdc1ef5e9e3c55"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:88a12ad8ccf325a8a5ed80e6d7c3bdc247d66175afedbe104ee2aaca72960d8e"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0a6d3fbf2232e3a08c41eca81ae4f1dff3d8f1a30bae415ebe0af2d2458b8a33"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84a585799c58b795573c7fa9b84c455adf3e1d72f19a2bf498b54a95ae0d194c"}, + {file = "aiohttp-3.11.11-cp310-cp310-win32.whl", hash = "sha256:bfde76a8f430cf5c5584553adf9926534352251d379dcb266ad2b93c54a29745"}, + {file = "aiohttp-3.11.11-cp310-cp310-win_amd64.whl", hash = "sha256:0fd82b8e9c383af11d2b26f27a478640b6b83d669440c0a71481f7c865a51da9"}, + {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76"}, + {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538"}, + {file = "aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773"}, + {file = "aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62"}, + {file = "aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac"}, + {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886"}, + {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2"}, + {file = "aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e"}, + {file = "aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600"}, + {file = "aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d"}, + {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9"}, + {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194"}, + {file = "aiohttp-3.11.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5"}, + {file = "aiohttp-3.11.11-cp313-cp313-win32.whl", hash = "sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d"}, + {file = "aiohttp-3.11.11-cp313-cp313-win_amd64.whl", hash = "sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99"}, + {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3e23419d832d969f659c208557de4a123e30a10d26e1e14b73431d3c13444c2e"}, + {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21fef42317cf02e05d3b09c028712e1d73a9606f02467fd803f7c1f39cc59add"}, + {file = "aiohttp-3.11.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1f21bb8d0235fc10c09ce1d11ffbd40fc50d3f08a89e4cf3a0c503dc2562247a"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1642eceeaa5ab6c9b6dfeaaa626ae314d808188ab23ae196a34c9d97efb68350"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2170816e34e10f2fd120f603e951630f8a112e1be3b60963a1f159f5699059a6"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8be8508d110d93061197fd2d6a74f7401f73b6d12f8822bbcd6d74f2b55d71b1"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eed954b161e6b9b65f6be446ed448ed3921763cc432053ceb606f89d793927e"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6c9af134da4bc9b3bd3e6a70072509f295d10ee60c697826225b60b9959acdd"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:44167fc6a763d534a6908bdb2592269b4bf30a03239bcb1654781adf5e49caf1"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:479b8c6ebd12aedfe64563b85920525d05d394b85f166b7873c8bde6da612f9c"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:10b4ff0ad793d98605958089fabfa350e8e62bd5d40aa65cdc69d6785859f94e"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b540bd67cfb54e6f0865ceccd9979687210d7ed1a1cc8c01f8e67e2f1e883d28"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1dac54e8ce2ed83b1f6b1a54005c87dfed139cf3f777fdc8afc76e7841101226"}, + {file = "aiohttp-3.11.11-cp39-cp39-win32.whl", hash = "sha256:568c1236b2fde93b7720f95a890741854c1200fba4a3471ff48b2934d2d93fd3"}, + {file = "aiohttp-3.11.11-cp39-cp39-win_amd64.whl", hash = "sha256:943a8b052e54dfd6439fd7989f67fc6a7f2138d0a2cf0a7de5f18aa4fe7eb3b1"}, + {file = "aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e"}, ] [package.dependencies] @@ -396,19 +391,19 @@ css = ["tinycss2 (>=1.1.0,<1.5)"] [[package]] name = "boto3" -version = "1.36.17" +version = "1.36.13" description = "The AWS SDK for Python" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"bedrock\"" files = [ - {file = "boto3-1.36.17-py3-none-any.whl", hash = "sha256:59bcf0c4b04d9cc36f8b418ad17ab3c4a99a21a175d2fad7096aa21cbe84630b"}, - {file = "boto3-1.36.17.tar.gz", hash = "sha256:5ecae20e780a3ce9afb3add532b61c466a8cb8960618e4fa565b3883064c1346"}, + {file = "boto3-1.36.13-py3-none-any.whl", hash = "sha256:20d97739cea1b0f549e9096c453ac727a350da28bd0451098714260b655a85ea"}, + {file = "boto3-1.36.13.tar.gz", hash = "sha256:c8031aa1c4a7c331081b2d86c49a362654b86e0b89d0a41fa166a68b226f4aba"}, ] [package.dependencies] -botocore = ">=1.36.17,<1.37.0" +botocore = ">=1.36.13,<1.37.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.11.0,<0.12.0" @@ -417,23 +412,23 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.36.17" +version = "1.36.13" description = "Low-level, data-driven core of boto 3." optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"bedrock\"" files = [ - {file = "botocore-1.36.17-py3-none-any.whl", hash = "sha256:069858b2fd693548035d7fd53a774e37e4260fea64e0ac9b8a3aee904f9321df"}, - {file = "botocore-1.36.17.tar.gz", hash = "sha256:cec13e0a7ce78e71aad0b397581b4e81824c7981ef4c261d2e296d200c399b09"}, + {file = "botocore-1.36.13-py3-none-any.whl", hash = "sha256:d644a814440bf8d55f4e29b1c0e6f021e2573b7784e0c91f55f4d9d689e08005"}, + {file = "botocore-1.36.13.tar.gz", hash = "sha256:50a3ff292f8dfdde21074b5c916afe847b01e074ab16d9c9fe71b34960c77134"}, ] [package.dependencies] jmespath = ">=0.7.1,<2.0.0" python-dateutil = ">=2.1,<3.0.0" urllib3 = [ - {version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""}, {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}, + {version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""}, ] [package.extras] @@ -678,15 +673,15 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "cohere" -version = "5.13.12" +version = "5.13.11" description = "" optional = true python-versions = "<4.0,>=3.9" groups = ["main"] markers = "extra == \"cohere\"" files = [ - {file = "cohere-5.13.12-py3-none-any.whl", hash = "sha256:2a043591a3e5280b47716a6b311e4c7f58e799364113a9cb81b50cd4f6c95f7e"}, - {file = "cohere-5.13.12.tar.gz", hash = "sha256:97bb9ac107e580780b941acbabd3aa5e71960e6835398292c46aaa8a0a4cab88"}, + {file = "cohere-5.13.11-py3-none-any.whl", hash = "sha256:9237e15f5abcda6ecf8252b6784d5424024986316ae319cb266c05d79ca3de83"}, + {file = "cohere-5.13.11.tar.gz", hash = "sha256:85d2c1a28ac83d3479a5c1ca6cdf97bb52794714c7fde054eb936cfeafaf57f6"}, ] [package.dependencies] @@ -1927,14 +1922,14 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve [[package]] name = "identify" -version = "2.6.7" +version = "2.6.6" description = "File identification library for Python" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "identify-2.6.7-py2.py3-none-any.whl", hash = "sha256:155931cb617a401807b09ecec6635d6c692d180090a1cedca8ef7d58ba5b6aa0"}, - {file = "identify-2.6.7.tar.gz", hash = "sha256:3fa266b42eba321ee0b2bb0936a6a6b9e36a1351cbb69055b3082f4193035684"}, + {file = "identify-2.6.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881"}, + {file = "identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251"}, ] [package.extras] @@ -2601,8 +2596,8 @@ files = [ [package.dependencies] numpy = [ - {version = ">1.20", markers = "python_version < \"3.10\""}, {version = ">=1.21.2", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">1.20", markers = "python_version < \"3.10\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.23.3", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, @@ -2799,14 +2794,14 @@ markers = {main = "extra == \"mistralai\""} [[package]] name = "myst-nb" -version = "1.2.0" +version = "1.1.2" description = "A Jupyter Notebook Sphinx reader built on top of the MyST markdown parser." optional = false python-versions = ">=3.9" groups = ["docs"] files = [ - {file = "myst_nb-1.2.0-py3-none-any.whl", hash = "sha256:0e09909877848c0cf45e1aecee97481512efa29a0c4caa37870a03bba11c56c1"}, - {file = "myst_nb-1.2.0.tar.gz", hash = "sha256:af459ec753b341952182b45b0a80b4776cebf80c9ee6aaca2a3f4027b440c9de"}, + {file = "myst_nb-1.1.2-py3-none-any.whl", hash = "sha256:9b7034e5d62640cb6daf03f9ca16ef45d0462fced27944c77aa3f98c7cdcd566"}, + {file = "myst_nb-1.1.2.tar.gz", hash = "sha256:961b4005657029ca89892a4c75edbf0856c54ceaf6172368b46bf7676c1f7700"}, ] [package.dependencies] @@ -5235,69 +5230,69 @@ test = ["pytest"] [[package]] name = "sqlalchemy" -version = "2.0.38" +version = "2.0.37" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" groups = ["docs"] files = [ - {file = "SQLAlchemy-2.0.38-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5e1d9e429028ce04f187a9f522818386c8b076723cdbe9345708384f49ebcec6"}, - {file = "SQLAlchemy-2.0.38-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b87a90f14c68c925817423b0424381f0e16d80fc9a1a1046ef202ab25b19a444"}, - {file = "SQLAlchemy-2.0.38-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:402c2316d95ed90d3d3c25ad0390afa52f4d2c56b348f212aa9c8d072a40eee5"}, - {file = "SQLAlchemy-2.0.38-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6493bc0eacdbb2c0f0d260d8988e943fee06089cd239bd7f3d0c45d1657a70e2"}, - {file = "SQLAlchemy-2.0.38-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0561832b04c6071bac3aad45b0d3bb6d2c4f46a8409f0a7a9c9fa6673b41bc03"}, - {file = "SQLAlchemy-2.0.38-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:49aa2cdd1e88adb1617c672a09bf4ebf2f05c9448c6dbeba096a3aeeb9d4d443"}, - {file = "SQLAlchemy-2.0.38-cp310-cp310-win32.whl", hash = "sha256:64aa8934200e222f72fcfd82ee71c0130a9c07d5725af6fe6e919017d095b297"}, - {file = "SQLAlchemy-2.0.38-cp310-cp310-win_amd64.whl", hash = "sha256:c57b8e0841f3fce7b703530ed70c7c36269c6d180ea2e02e36b34cb7288c50c7"}, - {file = "SQLAlchemy-2.0.38-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bf89e0e4a30714b357f5d46b6f20e0099d38b30d45fa68ea48589faf5f12f62d"}, - {file = "SQLAlchemy-2.0.38-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8455aa60da49cb112df62b4721bd8ad3654a3a02b9452c783e651637a1f21fa2"}, - {file = "SQLAlchemy-2.0.38-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f53c0d6a859b2db58332e0e6a921582a02c1677cc93d4cbb36fdf49709b327b2"}, - {file = "SQLAlchemy-2.0.38-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3c4817dff8cef5697f5afe5fec6bc1783994d55a68391be24cb7d80d2dbc3a6"}, - {file = "SQLAlchemy-2.0.38-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9cea5b756173bb86e2235f2f871b406a9b9d722417ae31e5391ccaef5348f2c"}, - {file = "SQLAlchemy-2.0.38-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40e9cdbd18c1f84631312b64993f7d755d85a3930252f6276a77432a2b25a2f3"}, - {file = "SQLAlchemy-2.0.38-cp311-cp311-win32.whl", hash = "sha256:cb39ed598aaf102251483f3e4675c5dd6b289c8142210ef76ba24aae0a8f8aba"}, - {file = "SQLAlchemy-2.0.38-cp311-cp311-win_amd64.whl", hash = "sha256:f9d57f1b3061b3e21476b0ad5f0397b112b94ace21d1f439f2db472e568178ae"}, - {file = "SQLAlchemy-2.0.38-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12d5b06a1f3aeccf295a5843c86835033797fea292c60e72b07bcb5d820e6dd3"}, - {file = "SQLAlchemy-2.0.38-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e036549ad14f2b414c725349cce0772ea34a7ab008e9cd67f9084e4f371d1f32"}, - {file = "SQLAlchemy-2.0.38-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee3bee874cb1fadee2ff2b79fc9fc808aa638670f28b2145074538d4a6a5028e"}, - {file = "SQLAlchemy-2.0.38-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e185ea07a99ce8b8edfc788c586c538c4b1351007e614ceb708fd01b095ef33e"}, - {file = "SQLAlchemy-2.0.38-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b79ee64d01d05a5476d5cceb3c27b5535e6bb84ee0f872ba60d9a8cd4d0e6579"}, - {file = "SQLAlchemy-2.0.38-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afd776cf1ebfc7f9aa42a09cf19feadb40a26366802d86c1fba080d8e5e74bdd"}, - {file = "SQLAlchemy-2.0.38-cp312-cp312-win32.whl", hash = "sha256:a5645cd45f56895cfe3ca3459aed9ff2d3f9aaa29ff7edf557fa7a23515a3725"}, - {file = "SQLAlchemy-2.0.38-cp312-cp312-win_amd64.whl", hash = "sha256:1052723e6cd95312f6a6eff9a279fd41bbae67633415373fdac3c430eca3425d"}, - {file = "SQLAlchemy-2.0.38-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ecef029b69843b82048c5b347d8e6049356aa24ed644006c9a9d7098c3bd3bfd"}, - {file = "SQLAlchemy-2.0.38-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c8bcad7fc12f0cc5896d8e10fdf703c45bd487294a986903fe032c72201596b"}, - {file = "SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a0ef3f98175d77180ffdc623d38e9f1736e8d86b6ba70bff182a7e68bed7727"}, - {file = "SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ac78898c50e2574e9f938d2e5caa8fe187d7a5b69b65faa1ea4648925b096"}, - {file = "SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9eb4fa13c8c7a2404b6a8e3772c17a55b1ba18bc711e25e4d6c0c9f5f541b02a"}, - {file = "SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5dba1cdb8f319084f5b00d41207b2079822aa8d6a4667c0f369fce85e34b0c86"}, - {file = "SQLAlchemy-2.0.38-cp313-cp313-win32.whl", hash = "sha256:eae27ad7580529a427cfdd52c87abb2dfb15ce2b7a3e0fc29fbb63e2ed6f8120"}, - {file = "SQLAlchemy-2.0.38-cp313-cp313-win_amd64.whl", hash = "sha256:b335a7c958bc945e10c522c069cd6e5804f4ff20f9a744dd38e748eb602cbbda"}, - {file = "SQLAlchemy-2.0.38-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40310db77a55512a18827488e592965d3dec6a3f1e3d8af3f8243134029daca3"}, - {file = "SQLAlchemy-2.0.38-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d3043375dd5bbcb2282894cbb12e6c559654c67b5fffb462fda815a55bf93f7"}, - {file = "SQLAlchemy-2.0.38-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70065dfabf023b155a9c2a18f573e47e6ca709b9e8619b2e04c54d5bcf193178"}, - {file = "SQLAlchemy-2.0.38-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:c058b84c3b24812c859300f3b5abf300daa34df20d4d4f42e9652a4d1c48c8a4"}, - {file = "SQLAlchemy-2.0.38-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0398361acebb42975deb747a824b5188817d32b5c8f8aba767d51ad0cc7bb08d"}, - {file = "SQLAlchemy-2.0.38-cp37-cp37m-win32.whl", hash = "sha256:a2bc4e49e8329f3283d99840c136ff2cd1a29e49b5624a46a290f04dff48e079"}, - {file = "SQLAlchemy-2.0.38-cp37-cp37m-win_amd64.whl", hash = "sha256:9cd136184dd5f58892f24001cdce986f5d7e96059d004118d5410671579834a4"}, - {file = "SQLAlchemy-2.0.38-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:665255e7aae5f38237b3a6eae49d2358d83a59f39ac21036413fab5d1e810578"}, - {file = "SQLAlchemy-2.0.38-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:92f99f2623ff16bd4aaf786ccde759c1f676d39c7bf2855eb0b540e1ac4530c8"}, - {file = "SQLAlchemy-2.0.38-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa498d1392216fae47eaf10c593e06c34476ced9549657fca713d0d1ba5f7248"}, - {file = "SQLAlchemy-2.0.38-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9afbc3909d0274d6ac8ec891e30210563b2c8bdd52ebbda14146354e7a69373"}, - {file = "SQLAlchemy-2.0.38-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:57dd41ba32430cbcc812041d4de8d2ca4651aeefad2626921ae2a23deb8cd6ff"}, - {file = "SQLAlchemy-2.0.38-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3e35d5565b35b66905b79ca4ae85840a8d40d31e0b3e2990f2e7692071b179ca"}, - {file = "SQLAlchemy-2.0.38-cp38-cp38-win32.whl", hash = "sha256:f0d3de936b192980209d7b5149e3c98977c3810d401482d05fb6d668d53c1c63"}, - {file = "SQLAlchemy-2.0.38-cp38-cp38-win_amd64.whl", hash = "sha256:3868acb639c136d98107c9096303d2d8e5da2880f7706f9f8c06a7f961961149"}, - {file = "SQLAlchemy-2.0.38-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07258341402a718f166618470cde0c34e4cec85a39767dce4e24f61ba5e667ea"}, - {file = "SQLAlchemy-2.0.38-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a826f21848632add58bef4f755a33d45105d25656a0c849f2dc2df1c71f6f50"}, - {file = "SQLAlchemy-2.0.38-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:386b7d136919bb66ced64d2228b92d66140de5fefb3c7df6bd79069a269a7b06"}, - {file = "SQLAlchemy-2.0.38-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f2951dc4b4f990a4b394d6b382accb33141d4d3bd3ef4e2b27287135d6bdd68"}, - {file = "SQLAlchemy-2.0.38-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8bf312ed8ac096d674c6aa9131b249093c1b37c35db6a967daa4c84746bc1bc9"}, - {file = "SQLAlchemy-2.0.38-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6db316d6e340f862ec059dc12e395d71f39746a20503b124edc255973977b728"}, - {file = "SQLAlchemy-2.0.38-cp39-cp39-win32.whl", hash = "sha256:c09a6ea87658695e527104cf857c70f79f14e9484605e205217aae0ec27b45fc"}, - {file = "SQLAlchemy-2.0.38-cp39-cp39-win_amd64.whl", hash = "sha256:12f5c9ed53334c3ce719155424dc5407aaa4f6cadeb09c5b627e06abb93933a1"}, - {file = "SQLAlchemy-2.0.38-py3-none-any.whl", hash = "sha256:63178c675d4c80def39f1febd625a6333f44c0ba269edd8a468b156394b27753"}, - {file = "sqlalchemy-2.0.38.tar.gz", hash = "sha256:e5a4d82bdb4bf1ac1285a68eab02d253ab73355d9f0fe725a97e1e0fa689decb"}, + {file = "SQLAlchemy-2.0.37-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da36c3b0e891808a7542c5c89f224520b9a16c7f5e4d6a1156955605e54aef0e"}, + {file = "SQLAlchemy-2.0.37-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e7402ff96e2b073a98ef6d6142796426d705addd27b9d26c3b32dbaa06d7d069"}, + {file = "SQLAlchemy-2.0.37-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6f5d254a22394847245f411a2956976401e84da4288aa70cbcd5190744062c1"}, + {file = "SQLAlchemy-2.0.37-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41296bbcaa55ef5fdd32389a35c710133b097f7b2609d8218c0eabded43a1d84"}, + {file = "SQLAlchemy-2.0.37-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bedee60385c1c0411378cbd4dc486362f5ee88deceea50002772912d798bb00f"}, + {file = "SQLAlchemy-2.0.37-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6c67415258f9f3c69867ec02fea1bf6508153709ecbd731a982442a590f2b7e4"}, + {file = "SQLAlchemy-2.0.37-cp310-cp310-win32.whl", hash = "sha256:650dcb70739957a492ad8acff65d099a9586b9b8920e3507ca61ec3ce650bb72"}, + {file = "SQLAlchemy-2.0.37-cp310-cp310-win_amd64.whl", hash = "sha256:93d1543cd8359040c02b6614421c8e10cd7a788c40047dbc507ed46c29ae5636"}, + {file = "SQLAlchemy-2.0.37-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:78361be6dc9073ed17ab380985d1e45e48a642313ab68ab6afa2457354ff692c"}, + {file = "SQLAlchemy-2.0.37-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b661b49d0cb0ab311a189b31e25576b7ac3e20783beb1e1817d72d9d02508bf5"}, + {file = "SQLAlchemy-2.0.37-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d57bafbab289e147d064ffbd5cca2d7b1394b63417c0636cea1f2e93d16eb9e8"}, + {file = "SQLAlchemy-2.0.37-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fa2c0913f02341d25fb858e4fb2031e6b0813494cca1ba07d417674128ce11b"}, + {file = "SQLAlchemy-2.0.37-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9df21b8d9e5c136ea6cde1c50d2b1c29a2b5ff2b1d610165c23ff250e0704087"}, + {file = "SQLAlchemy-2.0.37-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db18ff6b8c0f1917f8b20f8eca35c28bbccb9f83afa94743e03d40203ed83de9"}, + {file = "SQLAlchemy-2.0.37-cp311-cp311-win32.whl", hash = "sha256:46954173612617a99a64aee103bcd3f078901b9a8dcfc6ae80cbf34ba23df989"}, + {file = "SQLAlchemy-2.0.37-cp311-cp311-win_amd64.whl", hash = "sha256:7b7e772dc4bc507fdec4ee20182f15bd60d2a84f1e087a8accf5b5b7a0dcf2ba"}, + {file = "SQLAlchemy-2.0.37-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2952748ecd67ed3b56773c185e85fc084f6bdcdec10e5032a7c25a6bc7d682ef"}, + {file = "SQLAlchemy-2.0.37-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3151822aa1db0eb5afd65ccfafebe0ef5cda3a7701a279c8d0bf17781a793bb4"}, + {file = "SQLAlchemy-2.0.37-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaa8039b6d20137a4e02603aba37d12cd2dde7887500b8855356682fc33933f4"}, + {file = "SQLAlchemy-2.0.37-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cdba1f73b64530c47b27118b7053b8447e6d6f3c8104e3ac59f3d40c33aa9fd"}, + {file = "SQLAlchemy-2.0.37-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1b2690456528a87234a75d1a1644cdb330a6926f455403c8e4f6cad6921f9098"}, + {file = "SQLAlchemy-2.0.37-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cf5ae8a9dcf657fd72144a7fd01f243236ea39e7344e579a121c4205aedf07bb"}, + {file = "SQLAlchemy-2.0.37-cp312-cp312-win32.whl", hash = "sha256:ea308cec940905ba008291d93619d92edaf83232ec85fbd514dcb329f3192761"}, + {file = "SQLAlchemy-2.0.37-cp312-cp312-win_amd64.whl", hash = "sha256:635d8a21577341dfe4f7fa59ec394b346da12420b86624a69e466d446de16aff"}, + {file = "SQLAlchemy-2.0.37-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8c4096727193762e72ce9437e2a86a110cf081241919ce3fab8e89c02f6b6658"}, + {file = "SQLAlchemy-2.0.37-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e4fb5ac86d8fe8151966814f6720996430462e633d225497566b3996966b9bdb"}, + {file = "SQLAlchemy-2.0.37-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e56a139bfe136a22c438478a86f8204c1eb5eed36f4e15c4224e4b9db01cb3e4"}, + {file = "SQLAlchemy-2.0.37-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f95fc8e3f34b5f6b3effb49d10ac97c569ec8e32f985612d9b25dd12d0d2e94"}, + {file = "SQLAlchemy-2.0.37-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c505edd429abdfe3643fa3b2e83efb3445a34a9dc49d5f692dd087be966020e0"}, + {file = "SQLAlchemy-2.0.37-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:12b0f1ec623cccf058cf21cb544f0e74656618165b083d78145cafde156ea7b6"}, + {file = "SQLAlchemy-2.0.37-cp313-cp313-win32.whl", hash = "sha256:293f9ade06b2e68dd03cfb14d49202fac47b7bb94bffcff174568c951fbc7af2"}, + {file = "SQLAlchemy-2.0.37-cp313-cp313-win_amd64.whl", hash = "sha256:d70f53a0646cc418ca4853da57cf3ddddbccb8c98406791f24426f2dd77fd0e2"}, + {file = "SQLAlchemy-2.0.37-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:44f569d0b1eb82301b92b72085583277316e7367e038d97c3a1a899d9a05e342"}, + {file = "SQLAlchemy-2.0.37-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2eae3423e538c10d93ae3e87788c6a84658c3ed6db62e6a61bb9495b0ad16bb"}, + {file = "SQLAlchemy-2.0.37-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfff7be361048244c3aa0f60b5e63221c5e0f0e509f4e47b8910e22b57d10ae7"}, + {file = "SQLAlchemy-2.0.37-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:5bc3339db84c5fb9130ac0e2f20347ee77b5dd2596ba327ce0d399752f4fce39"}, + {file = "SQLAlchemy-2.0.37-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:84b9f23b0fa98a6a4b99d73989350a94e4a4ec476b9a7dfe9b79ba5939f5e80b"}, + {file = "SQLAlchemy-2.0.37-cp37-cp37m-win32.whl", hash = "sha256:51bc9cfef83e0ac84f86bf2b10eaccb27c5a3e66a1212bef676f5bee6ef33ebb"}, + {file = "SQLAlchemy-2.0.37-cp37-cp37m-win_amd64.whl", hash = "sha256:8e47f1af09444f87c67b4f1bb6231e12ba6d4d9f03050d7fc88df6d075231a49"}, + {file = "SQLAlchemy-2.0.37-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6b788f14c5bb91db7f468dcf76f8b64423660a05e57fe277d3f4fad7b9dcb7ce"}, + {file = "SQLAlchemy-2.0.37-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521ef85c04c33009166777c77e76c8a676e2d8528dc83a57836b63ca9c69dcd1"}, + {file = "SQLAlchemy-2.0.37-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75311559f5c9881a9808eadbeb20ed8d8ba3f7225bef3afed2000c2a9f4d49b9"}, + {file = "SQLAlchemy-2.0.37-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cce918ada64c956b62ca2c2af59b125767097ec1dca89650a6221e887521bfd7"}, + {file = "SQLAlchemy-2.0.37-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9d087663b7e1feabea8c578d6887d59bb00388158e8bff3a76be11aa3f748ca2"}, + {file = "SQLAlchemy-2.0.37-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cf95a60b36997dad99692314c4713f141b61c5b0b4cc5c3426faad570b31ca01"}, + {file = "SQLAlchemy-2.0.37-cp38-cp38-win32.whl", hash = "sha256:d75ead7dd4d255068ea0f21492ee67937bd7c90964c8f3c2bea83c7b7f81b95f"}, + {file = "SQLAlchemy-2.0.37-cp38-cp38-win_amd64.whl", hash = "sha256:74bbd1d0a9bacf34266a7907d43260c8d65d31d691bb2356f41b17c2dca5b1d0"}, + {file = "SQLAlchemy-2.0.37-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:648ec5acf95ad59255452ef759054f2176849662af4521db6cb245263ae4aa33"}, + {file = "SQLAlchemy-2.0.37-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:35bd2df269de082065d4b23ae08502a47255832cc3f17619a5cea92ce478b02b"}, + {file = "SQLAlchemy-2.0.37-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f581d365af9373a738c49e0c51e8b18e08d8a6b1b15cc556773bcd8a192fa8b"}, + {file = "SQLAlchemy-2.0.37-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82df02816c14f8dc9f4d74aea4cb84a92f4b0620235daa76dde002409a3fbb5a"}, + {file = "SQLAlchemy-2.0.37-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:94b564e38b344d3e67d2e224f0aec6ba09a77e4582ced41e7bfd0f757d926ec9"}, + {file = "SQLAlchemy-2.0.37-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:955a2a765aa1bd81aafa69ffda179d4fe3e2a3ad462a736ae5b6f387f78bfeb8"}, + {file = "SQLAlchemy-2.0.37-cp39-cp39-win32.whl", hash = "sha256:03f0528c53ca0b67094c4764523c1451ea15959bbf0a8a8a3096900014db0278"}, + {file = "SQLAlchemy-2.0.37-cp39-cp39-win_amd64.whl", hash = "sha256:4b12885dc85a2ab2b7d00995bac6d967bffa8594123b02ed21e8eb2205a7584b"}, + {file = "SQLAlchemy-2.0.37-py3-none-any.whl", hash = "sha256:a8998bf9f8658bd3839cbc44ddbe982955641863da0c1efe5b00c1ab4f5c16b1"}, + {file = "sqlalchemy-2.0.37.tar.gz", hash = "sha256:12b28d99a9c14eaf4055810df1001557176716de0167b91026e648e65229bffb"}, ] [package.dependencies] @@ -5694,15 +5689,15 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, [[package]] name = "transformers" -version = "4.48.3" +version = "4.48.2" description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow" optional = true python-versions = ">=3.9.0" groups = ["main"] markers = "extra == \"sentence-transformers\"" files = [ - {file = "transformers-4.48.3-py3-none-any.whl", hash = "sha256:78697f990f5ef350c23b46bf86d5081ce96b49479ab180b2de7687267de8fd36"}, - {file = "transformers-4.48.3.tar.gz", hash = "sha256:a5e8f1e9a6430aa78215836be70cecd3f872d99eeda300f41ad6cc841724afdb"}, + {file = "transformers-4.48.2-py3-none-any.whl", hash = "sha256:493bc5b0268b116eff305edf6656367fc89cf570e7a9d5891369e04751db698a"}, + {file = "transformers-4.48.2.tar.gz", hash = "sha256:dcfb73473e61f22fb3366fe2471ed2e42779ecdd49527a1bdf1937574855d516"}, ] [package.dependencies] @@ -5877,13 +5872,13 @@ urllib3 = ">=2" [[package]] name = "types-setuptools" -version = "75.8.0.20250210" +version = "75.8.0.20250110" description = "Typing stubs for setuptools" optional = false -python-versions = ">=3.9" +python-versions = ">=3.8" files = [ - {file = "types_setuptools-75.8.0.20250210-py3-none-any.whl", hash = "sha256:a217d7b4d59be04c29e23d142c959a0f85e71292fd3fc4313f016ca11f0b56dc"}, - {file = "types_setuptools-75.8.0.20250210.tar.gz", hash = "sha256:c1547361b2441f07c94e25dce8a068e18c611593ad4b6fdd727b1a8f5d1fda33"}, + {file = "types_setuptools-75.8.0.20250110-py3-none-any.whl", hash = "sha256:a9f12980bbf9bcdc23ecd80755789085bad6bfce4060c2275bc2b4ca9f2bc480"}, + {file = "types_setuptools-75.8.0.20250110.tar.gz", hash = "sha256:96f7ec8bbd6e0a54ea180d66ad68ad7a1d7954e7281a710ea2de75e355545271"}, ] [[package]] @@ -5979,14 +5974,14 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.29.2" +version = "20.29.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a"}, - {file = "virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728"}, + {file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"}, + {file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"}, ] [package.dependencies] diff --git a/redisvl/extensions/router/schema.py b/redisvl/extensions/router/schema.py index 7b259c76..9c0d24c6 100644 --- a/redisvl/extensions/router/schema.py +++ b/redisvl/extensions/router/schema.py @@ -66,18 +66,19 @@ class RoutingConfig(BaseModel): # distance_threshold: float = Field(default=0.5) """The threshold for semantic distance.""" max_k: int = Field(default=1) - """The maximum number of top matches to return.""" + + """Aggregation method to use to classify queries.""" aggregation_method: DistanceAggregationMethod = Field( default=DistanceAggregationMethod.avg ) + + """The maximum number of top matches to return.""" distance_threshold: float = Field( default=0.5, deprecated=True, description="Global distance threshold is deprecated all distance_thresholds now apply at route level.", ) - """Aggregation method to use to classify queries.""" - @validator("max_k") def max_k_must_be_positive(cls, v): if v <= 0: diff --git a/schemas/semantic_router.yaml b/schemas/semantic_router.yaml index 25aa08e1..0f5bab19 100644 --- a/schemas/semantic_router.yaml +++ b/schemas/semantic_router.yaml @@ -20,4 +20,3 @@ vectorizer: routing_config: max_k: 2 aggregation_method: avg - distance_threshold: 0.3 diff --git a/tests/integration/test_semantic_router.py b/tests/integration/test_semantic_router.py index 8f86e575..166635fe 100644 --- a/tests/integration/test_semantic_router.py +++ b/tests/integration/test_semantic_router.py @@ -361,6 +361,10 @@ def test_deprecated_dtype_argument(routes, redis_url): def test_deprecated_distance_threshold_argument(routes, redis_url): + redis_version = semantic_router._index.client.info()["redis_version"] + if not compare_versions(redis_version, "7.0.0"): + pytest.skip("Not using a late enough version of Redis") + router = SemanticRouter( name="test_pass_through_dtype", routes=routes, @@ -371,7 +375,10 @@ def test_deprecated_distance_threshold_argument(routes, redis_url): router("hello", distance_threshold=0.3) -def test_routes_different_distance_thresholds(routes, redis_url): +def test_routes_different_distance_thresholds_get_two(routes, redis_url): + redis_version = semantic_router._index.client.info()["redis_version"] + if not compare_versions(redis_version, "7.0.0"): + pytest.skip("Not using a late enough version of Redis") routes[0].distance_threshold = 0.5 routes[1].distance_threshold = 0.7 @@ -388,7 +395,11 @@ def test_routes_different_distance_thresholds(routes, redis_url): assert matches[1].name == "farewell" -def test_routes_different_distance_thresholds(routes, redis_url): +def test_routes_different_distance_thresholds_get_one(routes, redis_url): + redis_version = semantic_router._index.client.info()["redis_version"] + if not compare_versions(redis_version, "7.0.0"): + pytest.skip("Not using a late enough version of Redis") + routes[0].distance_threshold = 0.5 # don't match on second From dddd56ccd48b5cf5cea29276c6a48658d0d0e103 Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Tue, 11 Feb 2025 15:48:13 -0500 Subject: [PATCH 5/8] VSS not yet supported --- schemas/semantic_router.yaml | 1 + tests/integration/test_semantic_router.py | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/schemas/semantic_router.yaml b/schemas/semantic_router.yaml index 0f5bab19..25aa08e1 100644 --- a/schemas/semantic_router.yaml +++ b/schemas/semantic_router.yaml @@ -20,3 +20,4 @@ vectorizer: routing_config: max_k: 2 aggregation_method: avg + distance_threshold: 0.3 diff --git a/tests/integration/test_semantic_router.py b/tests/integration/test_semantic_router.py index 166635fe..d88fcc6f 100644 --- a/tests/integration/test_semantic_router.py +++ b/tests/integration/test_semantic_router.py @@ -360,7 +360,7 @@ def test_deprecated_dtype_argument(routes, redis_url): ) -def test_deprecated_distance_threshold_argument(routes, redis_url): +def test_deprecated_distance_threshold_argument(semantic_router, routes, redis_url): redis_version = semantic_router._index.client.info()["redis_version"] if not compare_versions(redis_version, "7.0.0"): pytest.skip("Not using a late enough version of Redis") @@ -375,7 +375,9 @@ def test_deprecated_distance_threshold_argument(routes, redis_url): router("hello", distance_threshold=0.3) -def test_routes_different_distance_thresholds_get_two(routes, redis_url): +def test_routes_different_distance_thresholds_get_two( + semantic_router, routes, redis_url +): redis_version = semantic_router._index.client.info()["redis_version"] if not compare_versions(redis_version, "7.0.0"): pytest.skip("Not using a late enough version of Redis") @@ -395,7 +397,9 @@ def test_routes_different_distance_thresholds_get_two(routes, redis_url): assert matches[1].name == "farewell" -def test_routes_different_distance_thresholds_get_one(routes, redis_url): +def test_routes_different_distance_thresholds_get_one( + semantic_router, routes, redis_url +): redis_version = semantic_router._index.client.info()["redis_version"] if not compare_versions(redis_version, "7.0.0"): pytest.skip("Not using a late enough version of Redis") From e565a573d1640db7655772cdcc25cd7c3d197151 Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Tue, 11 Feb 2025 16:36:19 -0500 Subject: [PATCH 6/8] remove line --- schemas/semantic_router.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/schemas/semantic_router.yaml b/schemas/semantic_router.yaml index 25aa08e1..7175efb7 100644 --- a/schemas/semantic_router.yaml +++ b/schemas/semantic_router.yaml @@ -19,5 +19,4 @@ vectorizer: model: sentence-transformers/all-mpnet-base-v2 routing_config: max_k: 2 - aggregation_method: avg - distance_threshold: 0.3 + aggregation_method: avg \ No newline at end of file From 7734089244b6ff9da590a4a442c394d7d3da661f Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Wed, 12 Feb 2025 10:38:49 -0500 Subject: [PATCH 7/8] no opp .lock --- poetry.lock | 334 ++++++++++++++++++++++++++-------------------------- 1 file changed, 165 insertions(+), 169 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5a5486e5..75c221b8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -21,100 +21,107 @@ tests = ["hypothesis", "pytest"] [[package]] name = "aiohappyeyeballs" -version = "2.4.4" +version = "2.4.6" description = "Happy Eyeballs for asyncio" optional = true -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"voyageai\"" files = [ - {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, - {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, + {file = "aiohappyeyeballs-2.4.6-py3-none-any.whl", hash = "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1"}, + {file = "aiohappyeyeballs-2.4.6.tar.gz", hash = "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0"}, ] [[package]] name = "aiohttp" -version = "3.11.11" +version = "3.11.12" description = "Async http client/server framework (asyncio)" optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"voyageai\"" files = [ - {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8"}, - {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5"}, - {file = "aiohttp-3.11.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:731468f555656767cda219ab42e033355fe48c85fbe3ba83a349631541715ba2"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb23d8bb86282b342481cad4370ea0853a39e4a32a0042bb52ca6bdde132df43"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f047569d655f81cb70ea5be942ee5d4421b6219c3f05d131f64088c73bb0917f"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd7659baae9ccf94ae5fe8bfaa2c7bc2e94d24611528395ce88d009107e00c6d"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af01e42ad87ae24932138f154105e88da13ce7d202a6de93fafdafb2883a00ef"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5854be2f3e5a729800bac57a8d76af464e160f19676ab6aea74bde18ad19d438"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6526e5fb4e14f4bbf30411216780c9967c20c5a55f2f51d3abd6de68320cc2f3"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:85992ee30a31835fc482468637b3e5bd085fa8fe9392ba0bdcbdc1ef5e9e3c55"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:88a12ad8ccf325a8a5ed80e6d7c3bdc247d66175afedbe104ee2aaca72960d8e"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0a6d3fbf2232e3a08c41eca81ae4f1dff3d8f1a30bae415ebe0af2d2458b8a33"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84a585799c58b795573c7fa9b84c455adf3e1d72f19a2bf498b54a95ae0d194c"}, - {file = "aiohttp-3.11.11-cp310-cp310-win32.whl", hash = "sha256:bfde76a8f430cf5c5584553adf9926534352251d379dcb266ad2b93c54a29745"}, - {file = "aiohttp-3.11.11-cp310-cp310-win_amd64.whl", hash = "sha256:0fd82b8e9c383af11d2b26f27a478640b6b83d669440c0a71481f7c865a51da9"}, - {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76"}, - {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538"}, - {file = "aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773"}, - {file = "aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62"}, - {file = "aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac"}, - {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886"}, - {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2"}, - {file = "aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e"}, - {file = "aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600"}, - {file = "aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d"}, - {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9"}, - {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194"}, - {file = "aiohttp-3.11.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5"}, - {file = "aiohttp-3.11.11-cp313-cp313-win32.whl", hash = "sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d"}, - {file = "aiohttp-3.11.11-cp313-cp313-win_amd64.whl", hash = "sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99"}, - {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3e23419d832d969f659c208557de4a123e30a10d26e1e14b73431d3c13444c2e"}, - {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21fef42317cf02e05d3b09c028712e1d73a9606f02467fd803f7c1f39cc59add"}, - {file = "aiohttp-3.11.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1f21bb8d0235fc10c09ce1d11ffbd40fc50d3f08a89e4cf3a0c503dc2562247a"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1642eceeaa5ab6c9b6dfeaaa626ae314d808188ab23ae196a34c9d97efb68350"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2170816e34e10f2fd120f603e951630f8a112e1be3b60963a1f159f5699059a6"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8be8508d110d93061197fd2d6a74f7401f73b6d12f8822bbcd6d74f2b55d71b1"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eed954b161e6b9b65f6be446ed448ed3921763cc432053ceb606f89d793927e"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6c9af134da4bc9b3bd3e6a70072509f295d10ee60c697826225b60b9959acdd"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:44167fc6a763d534a6908bdb2592269b4bf30a03239bcb1654781adf5e49caf1"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:479b8c6ebd12aedfe64563b85920525d05d394b85f166b7873c8bde6da612f9c"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:10b4ff0ad793d98605958089fabfa350e8e62bd5d40aa65cdc69d6785859f94e"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b540bd67cfb54e6f0865ceccd9979687210d7ed1a1cc8c01f8e67e2f1e883d28"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1dac54e8ce2ed83b1f6b1a54005c87dfed139cf3f777fdc8afc76e7841101226"}, - {file = "aiohttp-3.11.11-cp39-cp39-win32.whl", hash = "sha256:568c1236b2fde93b7720f95a890741854c1200fba4a3471ff48b2934d2d93fd3"}, - {file = "aiohttp-3.11.11-cp39-cp39-win_amd64.whl", hash = "sha256:943a8b052e54dfd6439fd7989f67fc6a7f2138d0a2cf0a7de5f18aa4fe7eb3b1"}, - {file = "aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e"}, + {file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aa8a8caca81c0a3e765f19c6953416c58e2f4cc1b84829af01dd1c771bb2f91f"}, + {file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84ede78acde96ca57f6cf8ccb8a13fbaf569f6011b9a52f870c662d4dc8cd854"}, + {file = "aiohttp-3.11.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:584096938a001378484aa4ee54e05dc79c7b9dd933e271c744a97b3b6f644957"}, + {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392432a2dde22b86f70dd4a0e9671a349446c93965f261dbaecfaf28813e5c42"}, + {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:88d385b8e7f3a870146bf5ea31786ef7463e99eb59e31db56e2315535d811f55"}, + {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b10a47e5390c4b30a0d58ee12581003be52eedd506862ab7f97da7a66805befb"}, + {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b5263dcede17b6b0c41ef0c3ccce847d82a7da98709e75cf7efde3e9e3b5cae"}, + {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50c5c7b8aa5443304c55c262c5693b108c35a3b61ef961f1e782dd52a2f559c7"}, + {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d1c031a7572f62f66f1257db37ddab4cb98bfaf9b9434a3b4840bf3560f5e788"}, + {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:7e44eba534381dd2687be50cbd5f2daded21575242ecfdaf86bbeecbc38dae8e"}, + {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:145a73850926018ec1681e734cedcf2716d6a8697d90da11284043b745c286d5"}, + {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2c311e2f63e42c1bf86361d11e2c4a59f25d9e7aabdbdf53dc38b885c5435cdb"}, + {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ea756b5a7bac046d202a9a3889b9a92219f885481d78cd318db85b15cc0b7bcf"}, + {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:526c900397f3bbc2db9cb360ce9c35134c908961cdd0ac25b1ae6ffcaa2507ff"}, + {file = "aiohttp-3.11.12-cp310-cp310-win32.whl", hash = "sha256:b8d3bb96c147b39c02d3db086899679f31958c5d81c494ef0fc9ef5bb1359b3d"}, + {file = "aiohttp-3.11.12-cp310-cp310-win_amd64.whl", hash = "sha256:7fe3d65279bfbee8de0fb4f8c17fc4e893eed2dba21b2f680e930cc2b09075c5"}, + {file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:87a2e00bf17da098d90d4145375f1d985a81605267e7f9377ff94e55c5d769eb"}, + {file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b34508f1cd928ce915ed09682d11307ba4b37d0708d1f28e5774c07a7674cac9"}, + {file = "aiohttp-3.11.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:936d8a4f0f7081327014742cd51d320296b56aa6d324461a13724ab05f4b2933"}, + {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de1378f72def7dfb5dbd73d86c19eda0ea7b0a6873910cc37d57e80f10d64e1"}, + {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9d45dbb3aaec05cf01525ee1a7ac72de46a8c425cb75c003acd29f76b1ffe94"}, + {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:930ffa1925393381e1e0a9b82137fa7b34c92a019b521cf9f41263976666a0d6"}, + {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8340def6737118f5429a5df4e88f440746b791f8f1c4ce4ad8a595f42c980bd5"}, + {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4016e383f91f2814e48ed61e6bda7d24c4d7f2402c75dd28f7e1027ae44ea204"}, + {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c0600bcc1adfaaac321422d615939ef300df81e165f6522ad096b73439c0f58"}, + {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:0450ada317a65383b7cce9576096150fdb97396dcfe559109b403c7242faffef"}, + {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:850ff6155371fd802a280f8d369d4e15d69434651b844bde566ce97ee2277420"}, + {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8fd12d0f989c6099e7b0f30dc6e0d1e05499f3337461f0b2b0dadea6c64b89df"}, + {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:76719dd521c20a58a6c256d058547b3a9595d1d885b830013366e27011ffe804"}, + {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:97fe431f2ed646a3b56142fc81d238abcbaff08548d6912acb0b19a0cadc146b"}, + {file = "aiohttp-3.11.12-cp311-cp311-win32.whl", hash = "sha256:e10c440d142fa8b32cfdb194caf60ceeceb3e49807072e0dc3a8887ea80e8c16"}, + {file = "aiohttp-3.11.12-cp311-cp311-win_amd64.whl", hash = "sha256:246067ba0cf5560cf42e775069c5d80a8989d14a7ded21af529a4e10e3e0f0e6"}, + {file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e392804a38353900c3fd8b7cacbea5132888f7129f8e241915e90b85f00e3250"}, + {file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8fa1510b96c08aaad49303ab11f8803787c99222288f310a62f493faf883ede1"}, + {file = "aiohttp-3.11.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc065a4285307607df3f3686363e7f8bdd0d8ab35f12226362a847731516e42c"}, + {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddb31f8474695cd61fc9455c644fc1606c164b93bff2490390d90464b4655df"}, + {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dec0000d2d8621d8015c293e24589d46fa218637d820894cb7356c77eca3259"}, + {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3552fe98e90fdf5918c04769f338a87fa4f00f3b28830ea9b78b1bdc6140e0d"}, + {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dfe7f984f28a8ae94ff3a7953cd9678550dbd2a1f9bda5dd9c5ae627744c78e"}, + {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a481a574af914b6e84624412666cbfbe531a05667ca197804ecc19c97b8ab1b0"}, + {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1987770fb4887560363b0e1a9b75aa303e447433c41284d3af2840a2f226d6e0"}, + {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a4ac6a0f0f6402854adca4e3259a623f5c82ec3f0c049374133bcb243132baf9"}, + {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c96a43822f1f9f69cc5c3706af33239489a6294be486a0447fb71380070d4d5f"}, + {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a5e69046f83c0d3cb8f0d5bd9b8838271b1bc898e01562a04398e160953e8eb9"}, + {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:68d54234c8d76d8ef74744f9f9fc6324f1508129e23da8883771cdbb5818cbef"}, + {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9fd9dcf9c91affe71654ef77426f5cf8489305e1c66ed4816f5a21874b094b9"}, + {file = "aiohttp-3.11.12-cp312-cp312-win32.whl", hash = "sha256:0ed49efcd0dc1611378beadbd97beb5d9ca8fe48579fc04a6ed0844072261b6a"}, + {file = "aiohttp-3.11.12-cp312-cp312-win_amd64.whl", hash = "sha256:54775858c7f2f214476773ce785a19ee81d1294a6bedc5cc17225355aab74802"}, + {file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:413ad794dccb19453e2b97c2375f2ca3cdf34dc50d18cc2693bd5aed7d16f4b9"}, + {file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a93d28ed4b4b39e6f46fd240896c29b686b75e39cc6992692e3922ff6982b4c"}, + {file = "aiohttp-3.11.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d589264dbba3b16e8951b6f145d1e6b883094075283dafcab4cdd564a9e353a0"}, + {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5148ca8955affdfeb864aca158ecae11030e952b25b3ae15d4e2b5ba299bad2"}, + {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:525410e0790aab036492eeea913858989c4cb070ff373ec3bc322d700bdf47c1"}, + {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bd8695be2c80b665ae3f05cb584093a1e59c35ecb7d794d1edd96e8cc9201d7"}, + {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0203433121484b32646a5f5ea93ae86f3d9559d7243f07e8c0eab5ff8e3f70e"}, + {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd36749a1035c34ba8d8aaf221b91ca3d111532e5ccb5fa8c3703ab1b967ed"}, + {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7442662afebbf7b4c6d28cb7aab9e9ce3a5df055fc4116cc7228192ad6cb484"}, + {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8a2fb742ef378284a50766e985804bd6adb5adb5aa781100b09befdbfa757b65"}, + {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cee3b117a8d13ab98b38d5b6bdcd040cfb4181068d05ce0c474ec9db5f3c5bb"}, + {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f6a19bcab7fbd8f8649d6595624856635159a6527861b9cdc3447af288a00c00"}, + {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e4cecdb52aaa9994fbed6b81d4568427b6002f0a91c322697a4bfcc2b2363f5a"}, + {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:30f546358dfa0953db92ba620101fefc81574f87b2346556b90b5f3ef16e55ce"}, + {file = "aiohttp-3.11.12-cp313-cp313-win32.whl", hash = "sha256:ce1bb21fc7d753b5f8a5d5a4bae99566386b15e716ebdb410154c16c91494d7f"}, + {file = "aiohttp-3.11.12-cp313-cp313-win_amd64.whl", hash = "sha256:f7914ab70d2ee8ab91c13e5402122edbc77821c66d2758abb53aabe87f013287"}, + {file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c3623053b85b4296cd3925eeb725e386644fd5bc67250b3bb08b0f144803e7b"}, + {file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:67453e603cea8e85ed566b2700efa1f6916aefbc0c9fcb2e86aaffc08ec38e78"}, + {file = "aiohttp-3.11.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6130459189e61baac5a88c10019b21e1f0c6d00ebc770e9ce269475650ff7f73"}, + {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9060addfa4ff753b09392efe41e6af06ea5dd257829199747b9f15bfad819460"}, + {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34245498eeb9ae54c687a07ad7f160053911b5745e186afe2d0c0f2898a1ab8a"}, + {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8dc0fba9a74b471c45ca1a3cb6e6913ebfae416678d90529d188886278e7f3f6"}, + {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a478aa11b328983c4444dacb947d4513cb371cd323f3845e53caeda6be5589d5"}, + {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c160a04283c8c6f55b5bf6d4cad59bb9c5b9c9cd08903841b25f1f7109ef1259"}, + {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:edb69b9589324bdc40961cdf0657815df674f1743a8d5ad9ab56a99e4833cfdd"}, + {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ee84c2a22a809c4f868153b178fe59e71423e1f3d6a8cd416134bb231fbf6d3"}, + {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bf4480a5438f80e0f1539e15a7eb8b5f97a26fe087e9828e2c0ec2be119a9f72"}, + {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:e6b2732ef3bafc759f653a98881b5b9cdef0716d98f013d376ee8dfd7285abf1"}, + {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f752e80606b132140883bb262a457c475d219d7163d996dc9072434ffb0784c4"}, + {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ab3247d58b393bda5b1c8f31c9edece7162fc13265334217785518dd770792b8"}, + {file = "aiohttp-3.11.12-cp39-cp39-win32.whl", hash = "sha256:0d5176f310a7fe6f65608213cc74f4228e4f4ce9fd10bcb2bb6da8fc66991462"}, + {file = "aiohttp-3.11.12-cp39-cp39-win_amd64.whl", hash = "sha256:74bd573dde27e58c760d9ca8615c41a57e719bff315c9adb6f2a4281a28e8798"}, + {file = "aiohttp-3.11.12.tar.gz", hash = "sha256:7603ca26d75b1b86160ce1bbe2787a0b706e592af5b2504e12caa88a217767b0"}, ] [package.dependencies] @@ -391,19 +398,19 @@ css = ["tinycss2 (>=1.1.0,<1.5)"] [[package]] name = "boto3" -version = "1.36.13" +version = "1.36.18" description = "The AWS SDK for Python" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"bedrock\"" files = [ - {file = "boto3-1.36.13-py3-none-any.whl", hash = "sha256:20d97739cea1b0f549e9096c453ac727a350da28bd0451098714260b655a85ea"}, - {file = "boto3-1.36.13.tar.gz", hash = "sha256:c8031aa1c4a7c331081b2d86c49a362654b86e0b89d0a41fa166a68b226f4aba"}, + {file = "boto3-1.36.18-py3-none-any.whl", hash = "sha256:084ff25af2d7bda3102d6367f5453e2e83f8cde1da73079ea144595b03cb9400"}, + {file = "boto3-1.36.18.tar.gz", hash = "sha256:be8e32c34d7b103a64fafdd277fa1ec136733b4bbfc11dcfa597efa36a820b37"}, ] [package.dependencies] -botocore = ">=1.36.13,<1.37.0" +botocore = ">=1.36.18,<1.37.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.11.0,<0.12.0" @@ -412,23 +419,23 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.36.13" +version = "1.36.18" description = "Low-level, data-driven core of boto 3." optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"bedrock\"" files = [ - {file = "botocore-1.36.13-py3-none-any.whl", hash = "sha256:d644a814440bf8d55f4e29b1c0e6f021e2573b7784e0c91f55f4d9d689e08005"}, - {file = "botocore-1.36.13.tar.gz", hash = "sha256:50a3ff292f8dfdde21074b5c916afe847b01e074ab16d9c9fe71b34960c77134"}, + {file = "botocore-1.36.18-py3-none-any.whl", hash = "sha256:7898d109affd9231c555e71fda88308c1da2db8d39e83d33eb8cb40ebf1ba82f"}, + {file = "botocore-1.36.18.tar.gz", hash = "sha256:ddadafe460e91f11677720a2fcc3ea09c4abb914de2b000da7ba46b4c97da3d7"}, ] [package.dependencies] jmespath = ">=0.7.1,<2.0.0" python-dateutil = ">=2.1,<3.0.0" urllib3 = [ - {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}, {version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""}, + {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}, ] [package.extras] @@ -673,15 +680,15 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "cohere" -version = "5.13.11" +version = "5.13.12" description = "" optional = true python-versions = "<4.0,>=3.9" groups = ["main"] markers = "extra == \"cohere\"" files = [ - {file = "cohere-5.13.11-py3-none-any.whl", hash = "sha256:9237e15f5abcda6ecf8252b6784d5424024986316ae319cb266c05d79ca3de83"}, - {file = "cohere-5.13.11.tar.gz", hash = "sha256:85d2c1a28ac83d3479a5c1ca6cdf97bb52794714c7fde054eb936cfeafaf57f6"}, + {file = "cohere-5.13.12-py3-none-any.whl", hash = "sha256:2a043591a3e5280b47716a6b311e4c7f58e799364113a9cb81b50cd4f6c95f7e"}, + {file = "cohere-5.13.12.tar.gz", hash = "sha256:97bb9ac107e580780b941acbabd3aa5e71960e6835398292c46aaa8a0a4cab88"}, ] [package.dependencies] @@ -1922,14 +1929,14 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve [[package]] name = "identify" -version = "2.6.6" +version = "2.6.7" description = "File identification library for Python" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "identify-2.6.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881"}, - {file = "identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251"}, + {file = "identify-2.6.7-py2.py3-none-any.whl", hash = "sha256:155931cb617a401807b09ecec6635d6c692d180090a1cedca8ef7d58ba5b6aa0"}, + {file = "identify-2.6.7.tar.gz", hash = "sha256:3fa266b42eba321ee0b2bb0936a6a6b9e36a1351cbb69055b3082f4193035684"}, ] [package.extras] @@ -2596,9 +2603,8 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.21.2", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, {version = ">1.20", markers = "python_version < \"3.10\""}, - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, + {version = ">=1.21.2", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, {version = ">=1.23.3", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] @@ -2794,14 +2800,14 @@ markers = {main = "extra == \"mistralai\""} [[package]] name = "myst-nb" -version = "1.1.2" +version = "1.2.0" description = "A Jupyter Notebook Sphinx reader built on top of the MyST markdown parser." optional = false python-versions = ">=3.9" groups = ["docs"] files = [ - {file = "myst_nb-1.1.2-py3-none-any.whl", hash = "sha256:9b7034e5d62640cb6daf03f9ca16ef45d0462fced27944c77aa3f98c7cdcd566"}, - {file = "myst_nb-1.1.2.tar.gz", hash = "sha256:961b4005657029ca89892a4c75edbf0856c54ceaf6172368b46bf7676c1f7700"}, + {file = "myst_nb-1.2.0-py3-none-any.whl", hash = "sha256:0e09909877848c0cf45e1aecee97481512efa29a0c4caa37870a03bba11c56c1"}, + {file = "myst_nb-1.2.0.tar.gz", hash = "sha256:af459ec753b341952182b45b0a80b4776cebf80c9ee6aaca2a3f4027b440c9de"}, ] [package.dependencies] @@ -5230,69 +5236,58 @@ test = ["pytest"] [[package]] name = "sqlalchemy" -version = "2.0.37" +version = "2.0.38" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" groups = ["docs"] files = [ - {file = "SQLAlchemy-2.0.37-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da36c3b0e891808a7542c5c89f224520b9a16c7f5e4d6a1156955605e54aef0e"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e7402ff96e2b073a98ef6d6142796426d705addd27b9d26c3b32dbaa06d7d069"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6f5d254a22394847245f411a2956976401e84da4288aa70cbcd5190744062c1"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41296bbcaa55ef5fdd32389a35c710133b097f7b2609d8218c0eabded43a1d84"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bedee60385c1c0411378cbd4dc486362f5ee88deceea50002772912d798bb00f"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6c67415258f9f3c69867ec02fea1bf6508153709ecbd731a982442a590f2b7e4"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-win32.whl", hash = "sha256:650dcb70739957a492ad8acff65d099a9586b9b8920e3507ca61ec3ce650bb72"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-win_amd64.whl", hash = "sha256:93d1543cd8359040c02b6614421c8e10cd7a788c40047dbc507ed46c29ae5636"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:78361be6dc9073ed17ab380985d1e45e48a642313ab68ab6afa2457354ff692c"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b661b49d0cb0ab311a189b31e25576b7ac3e20783beb1e1817d72d9d02508bf5"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d57bafbab289e147d064ffbd5cca2d7b1394b63417c0636cea1f2e93d16eb9e8"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fa2c0913f02341d25fb858e4fb2031e6b0813494cca1ba07d417674128ce11b"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9df21b8d9e5c136ea6cde1c50d2b1c29a2b5ff2b1d610165c23ff250e0704087"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db18ff6b8c0f1917f8b20f8eca35c28bbccb9f83afa94743e03d40203ed83de9"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-win32.whl", hash = "sha256:46954173612617a99a64aee103bcd3f078901b9a8dcfc6ae80cbf34ba23df989"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-win_amd64.whl", hash = "sha256:7b7e772dc4bc507fdec4ee20182f15bd60d2a84f1e087a8accf5b5b7a0dcf2ba"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2952748ecd67ed3b56773c185e85fc084f6bdcdec10e5032a7c25a6bc7d682ef"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3151822aa1db0eb5afd65ccfafebe0ef5cda3a7701a279c8d0bf17781a793bb4"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaa8039b6d20137a4e02603aba37d12cd2dde7887500b8855356682fc33933f4"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cdba1f73b64530c47b27118b7053b8447e6d6f3c8104e3ac59f3d40c33aa9fd"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1b2690456528a87234a75d1a1644cdb330a6926f455403c8e4f6cad6921f9098"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cf5ae8a9dcf657fd72144a7fd01f243236ea39e7344e579a121c4205aedf07bb"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-win32.whl", hash = "sha256:ea308cec940905ba008291d93619d92edaf83232ec85fbd514dcb329f3192761"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-win_amd64.whl", hash = "sha256:635d8a21577341dfe4f7fa59ec394b346da12420b86624a69e466d446de16aff"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8c4096727193762e72ce9437e2a86a110cf081241919ce3fab8e89c02f6b6658"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e4fb5ac86d8fe8151966814f6720996430462e633d225497566b3996966b9bdb"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e56a139bfe136a22c438478a86f8204c1eb5eed36f4e15c4224e4b9db01cb3e4"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f95fc8e3f34b5f6b3effb49d10ac97c569ec8e32f985612d9b25dd12d0d2e94"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c505edd429abdfe3643fa3b2e83efb3445a34a9dc49d5f692dd087be966020e0"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:12b0f1ec623cccf058cf21cb544f0e74656618165b083d78145cafde156ea7b6"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-win32.whl", hash = "sha256:293f9ade06b2e68dd03cfb14d49202fac47b7bb94bffcff174568c951fbc7af2"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-win_amd64.whl", hash = "sha256:d70f53a0646cc418ca4853da57cf3ddddbccb8c98406791f24426f2dd77fd0e2"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:44f569d0b1eb82301b92b72085583277316e7367e038d97c3a1a899d9a05e342"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2eae3423e538c10d93ae3e87788c6a84658c3ed6db62e6a61bb9495b0ad16bb"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfff7be361048244c3aa0f60b5e63221c5e0f0e509f4e47b8910e22b57d10ae7"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:5bc3339db84c5fb9130ac0e2f20347ee77b5dd2596ba327ce0d399752f4fce39"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:84b9f23b0fa98a6a4b99d73989350a94e4a4ec476b9a7dfe9b79ba5939f5e80b"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-win32.whl", hash = "sha256:51bc9cfef83e0ac84f86bf2b10eaccb27c5a3e66a1212bef676f5bee6ef33ebb"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-win_amd64.whl", hash = "sha256:8e47f1af09444f87c67b4f1bb6231e12ba6d4d9f03050d7fc88df6d075231a49"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6b788f14c5bb91db7f468dcf76f8b64423660a05e57fe277d3f4fad7b9dcb7ce"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521ef85c04c33009166777c77e76c8a676e2d8528dc83a57836b63ca9c69dcd1"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75311559f5c9881a9808eadbeb20ed8d8ba3f7225bef3afed2000c2a9f4d49b9"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cce918ada64c956b62ca2c2af59b125767097ec1dca89650a6221e887521bfd7"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9d087663b7e1feabea8c578d6887d59bb00388158e8bff3a76be11aa3f748ca2"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cf95a60b36997dad99692314c4713f141b61c5b0b4cc5c3426faad570b31ca01"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-win32.whl", hash = "sha256:d75ead7dd4d255068ea0f21492ee67937bd7c90964c8f3c2bea83c7b7f81b95f"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-win_amd64.whl", hash = "sha256:74bbd1d0a9bacf34266a7907d43260c8d65d31d691bb2356f41b17c2dca5b1d0"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:648ec5acf95ad59255452ef759054f2176849662af4521db6cb245263ae4aa33"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:35bd2df269de082065d4b23ae08502a47255832cc3f17619a5cea92ce478b02b"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f581d365af9373a738c49e0c51e8b18e08d8a6b1b15cc556773bcd8a192fa8b"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82df02816c14f8dc9f4d74aea4cb84a92f4b0620235daa76dde002409a3fbb5a"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:94b564e38b344d3e67d2e224f0aec6ba09a77e4582ced41e7bfd0f757d926ec9"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:955a2a765aa1bd81aafa69ffda179d4fe3e2a3ad462a736ae5b6f387f78bfeb8"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-win32.whl", hash = "sha256:03f0528c53ca0b67094c4764523c1451ea15959bbf0a8a8a3096900014db0278"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-win_amd64.whl", hash = "sha256:4b12885dc85a2ab2b7d00995bac6d967bffa8594123b02ed21e8eb2205a7584b"}, - {file = "SQLAlchemy-2.0.37-py3-none-any.whl", hash = "sha256:a8998bf9f8658bd3839cbc44ddbe982955641863da0c1efe5b00c1ab4f5c16b1"}, - {file = "sqlalchemy-2.0.37.tar.gz", hash = "sha256:12b28d99a9c14eaf4055810df1001557176716de0167b91026e648e65229bffb"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5e1d9e429028ce04f187a9f522818386c8b076723cdbe9345708384f49ebcec6"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b87a90f14c68c925817423b0424381f0e16d80fc9a1a1046ef202ab25b19a444"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:402c2316d95ed90d3d3c25ad0390afa52f4d2c56b348f212aa9c8d072a40eee5"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6493bc0eacdbb2c0f0d260d8988e943fee06089cd239bd7f3d0c45d1657a70e2"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0561832b04c6071bac3aad45b0d3bb6d2c4f46a8409f0a7a9c9fa6673b41bc03"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:49aa2cdd1e88adb1617c672a09bf4ebf2f05c9448c6dbeba096a3aeeb9d4d443"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-win32.whl", hash = "sha256:64aa8934200e222f72fcfd82ee71c0130a9c07d5725af6fe6e919017d095b297"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-win_amd64.whl", hash = "sha256:c57b8e0841f3fce7b703530ed70c7c36269c6d180ea2e02e36b34cb7288c50c7"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bf89e0e4a30714b357f5d46b6f20e0099d38b30d45fa68ea48589faf5f12f62d"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8455aa60da49cb112df62b4721bd8ad3654a3a02b9452c783e651637a1f21fa2"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f53c0d6a859b2db58332e0e6a921582a02c1677cc93d4cbb36fdf49709b327b2"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3c4817dff8cef5697f5afe5fec6bc1783994d55a68391be24cb7d80d2dbc3a6"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9cea5b756173bb86e2235f2f871b406a9b9d722417ae31e5391ccaef5348f2c"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40e9cdbd18c1f84631312b64993f7d755d85a3930252f6276a77432a2b25a2f3"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-win32.whl", hash = "sha256:cb39ed598aaf102251483f3e4675c5dd6b289c8142210ef76ba24aae0a8f8aba"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-win_amd64.whl", hash = "sha256:f9d57f1b3061b3e21476b0ad5f0397b112b94ace21d1f439f2db472e568178ae"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12d5b06a1f3aeccf295a5843c86835033797fea292c60e72b07bcb5d820e6dd3"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e036549ad14f2b414c725349cce0772ea34a7ab008e9cd67f9084e4f371d1f32"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee3bee874cb1fadee2ff2b79fc9fc808aa638670f28b2145074538d4a6a5028e"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e185ea07a99ce8b8edfc788c586c538c4b1351007e614ceb708fd01b095ef33e"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b79ee64d01d05a5476d5cceb3c27b5535e6bb84ee0f872ba60d9a8cd4d0e6579"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afd776cf1ebfc7f9aa42a09cf19feadb40a26366802d86c1fba080d8e5e74bdd"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-win32.whl", hash = "sha256:a5645cd45f56895cfe3ca3459aed9ff2d3f9aaa29ff7edf557fa7a23515a3725"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-win_amd64.whl", hash = "sha256:1052723e6cd95312f6a6eff9a279fd41bbae67633415373fdac3c430eca3425d"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ecef029b69843b82048c5b347d8e6049356aa24ed644006c9a9d7098c3bd3bfd"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c8bcad7fc12f0cc5896d8e10fdf703c45bd487294a986903fe032c72201596b"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a0ef3f98175d77180ffdc623d38e9f1736e8d86b6ba70bff182a7e68bed7727"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ac78898c50e2574e9f938d2e5caa8fe187d7a5b69b65faa1ea4648925b096"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9eb4fa13c8c7a2404b6a8e3772c17a55b1ba18bc711e25e4d6c0c9f5f541b02a"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5dba1cdb8f319084f5b00d41207b2079822aa8d6a4667c0f369fce85e34b0c86"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-win32.whl", hash = "sha256:eae27ad7580529a427cfdd52c87abb2dfb15ce2b7a3e0fc29fbb63e2ed6f8120"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-win_amd64.whl", hash = "sha256:b335a7c958bc945e10c522c069cd6e5804f4ff20f9a744dd38e748eb602cbbda"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d3043375dd5bbcb2282894cbb12e6c559654c67b5fffb462fda815a55bf93f7"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:c058b84c3b24812c859300f3b5abf300daa34df20d4d4f42e9652a4d1c48c8a4"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-win32.whl", hash = "sha256:a2bc4e49e8329f3283d99840c136ff2cd1a29e49b5624a46a290f04dff48e079"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-win_amd64.whl", hash = "sha256:9cd136184dd5f58892f24001cdce986f5d7e96059d004118d5410671579834a4"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa498d1392216fae47eaf10c593e06c34476ced9549657fca713d0d1ba5f7248"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:57dd41ba32430cbcc812041d4de8d2ca4651aeefad2626921ae2a23deb8cd6ff"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-win32.whl", hash = "sha256:f0d3de936b192980209d7b5149e3c98977c3810d401482d05fb6d668d53c1c63"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-win_amd64.whl", hash = "sha256:3868acb639c136d98107c9096303d2d8e5da2880f7706f9f8c06a7f961961149"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:386b7d136919bb66ced64d2228b92d66140de5fefb3c7df6bd79069a269a7b06"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8bf312ed8ac096d674c6aa9131b249093c1b37c35db6a967daa4c84746bc1bc9"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-win32.whl", hash = "sha256:c09a6ea87658695e527104cf857c70f79f14e9484605e205217aae0ec27b45fc"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-win_amd64.whl", hash = "sha256:12f5c9ed53334c3ce719155424dc5407aaa4f6cadeb09c5b627e06abb93933a1"}, + {file = "SQLAlchemy-2.0.38-py3-none-any.whl", hash = "sha256:63178c675d4c80def39f1febd625a6333f44c0ba269edd8a468b156394b27753"}, + {file = "sqlalchemy-2.0.38.tar.gz", hash = "sha256:e5a4d82bdb4bf1ac1285a68eab02d253ab73355d9f0fe725a97e1e0fa689decb"}, ] [package.dependencies] @@ -5689,15 +5684,15 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, [[package]] name = "transformers" -version = "4.48.2" +version = "4.48.3" description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow" optional = true python-versions = ">=3.9.0" groups = ["main"] markers = "extra == \"sentence-transformers\"" files = [ - {file = "transformers-4.48.2-py3-none-any.whl", hash = "sha256:493bc5b0268b116eff305edf6656367fc89cf570e7a9d5891369e04751db698a"}, - {file = "transformers-4.48.2.tar.gz", hash = "sha256:dcfb73473e61f22fb3366fe2471ed2e42779ecdd49527a1bdf1937574855d516"}, + {file = "transformers-4.48.3-py3-none-any.whl", hash = "sha256:78697f990f5ef350c23b46bf86d5081ce96b49479ab180b2de7687267de8fd36"}, + {file = "transformers-4.48.3.tar.gz", hash = "sha256:a5e8f1e9a6430aa78215836be70cecd3f872d99eeda300f41ad6cc841724afdb"}, ] [package.dependencies] @@ -5872,13 +5867,14 @@ urllib3 = ">=2" [[package]] name = "types-setuptools" -version = "75.8.0.20250110" +version = "75.8.0.20250210" description = "Typing stubs for setuptools" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "types_setuptools-75.8.0.20250110-py3-none-any.whl", hash = "sha256:a9f12980bbf9bcdc23ecd80755789085bad6bfce4060c2275bc2b4ca9f2bc480"}, - {file = "types_setuptools-75.8.0.20250110.tar.gz", hash = "sha256:96f7ec8bbd6e0a54ea180d66ad68ad7a1d7954e7281a710ea2de75e355545271"}, + {file = "types_setuptools-75.8.0.20250210-py3-none-any.whl", hash = "sha256:a217d7b4d59be04c29e23d142c959a0f85e71292fd3fc4313f016ca11f0b56dc"}, + {file = "types_setuptools-75.8.0.20250210.tar.gz", hash = "sha256:c1547361b2441f07c94e25dce8a068e18c611593ad4b6fdd727b1a8f5d1fda33"}, ] [[package]] @@ -5974,14 +5970,14 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.29.1" +version = "20.29.2" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"}, - {file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"}, + {file = "virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a"}, + {file = "virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728"}, ] [package.dependencies] @@ -6257,4 +6253,4 @@ voyageai = ["voyageai"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<3.14" -content-hash = "e4a76982923cc6e4d9da48a4f924a1f6dad4df913db1195f78a22674eaf04eaa" +content-hash = "e4a76982923cc6e4d9da48a4f924a1f6dad4df913db1195f78a22674eaf04eaa" \ No newline at end of file From fa7cf0bf79ed11662ca0afa08f67293100ffa500 Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Wed, 12 Feb 2025 13:19:05 -0500 Subject: [PATCH 8/8] remove unneeded typing --- redisvl/extensions/router/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redisvl/extensions/router/semantic.py b/redisvl/extensions/router/semantic.py index bdfdf862..8a349f46 100644 --- a/redisvl/extensions/router/semantic.py +++ b/redisvl/extensions/router/semantic.py @@ -266,7 +266,7 @@ def _get_route_matches( ) -> List[RouteMatch]: """Get the route matches for a given vector and aggregation method.""" - thresholds: List[float] = [route.distance_threshold for route in self.routes] + thresholds = [route.distance_threshold for route in self.routes] if thresholds: distance_threshold = max(thresholds) else: