From 9f8a6b05b5a80779007e1de293499234d1f80e60 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Thu, 25 Jul 2024 18:47:21 +0200 Subject: [PATCH 01/21] initial commit for astra db branch --- .../vector/astra_db_vector_store_driver.py | 142 ++++ poetry.lock | 764 ++++++++++-------- pyproject.toml | 3 + 3 files changed, 585 insertions(+), 324 deletions(-) create mode 100644 griptape/drivers/vector/astra_db_vector_store_driver.py diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py new file mode 100644 index 000000000..af6a1d708 --- /dev/null +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -0,0 +1,142 @@ +from __future__ import annotations + +import logging +import warnings +from typing import TYPE_CHECKING, Any, Optional + +from attrs import define, field + +from griptape.drivers import BaseVectorStoreDriver +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + from astrapy import Collection + +GRIPTAPE_VERSION: Optional[str] +try: + from importlib import metadata + + GRIPTAPE_VERSION = metadata.version("griptape") +except Exception: + GRIPTAPE_VERSION = None + +logging.basicConfig(level=logging.WARNING) + + +COLLECTION_INDEXING = {"deny": ["meta.artifact"]} + + +@define +class AstraDBVectorStoreDriver(BaseVectorStoreDriver): + """A Vector Store Driver for Astra DB. + + DOCSTRING TO DO + """ + + api_endpoint: str = field(kw_only=True, metadata={"serializable": True}) + token: str = field(kw_only=True, metadata={"serializable": False}) + collection_name: str = field(kw_only=True, metadata={"serializable": False}) + dimension: int = field(kw_only=True, metadata={"serializable": True}) + astra_db_namespace: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + + collection: Collection = field(init=False) + + def __attrs_post_init__(self) -> None: + astrapy = import_optional_dependency("astrapy") + self.collection = ( + astrapy.DataAPIClient( + token=self.token, + caller_name="griptape", + caller_version=GRIPTAPE_VERSION, + ) + .get_database( + self.api_endpoint, + namespace=self.astra_db_namespace, + ) + .create_collection( + name=self.collection_name, + dimension=self.dimension, + indexing=COLLECTION_INDEXING, + check_exists=False, + ) + ) + + def delete_vector(self, vector_id: str) -> None: + self.collection.delete_one({"_id": vector_id}) + + def upsert_vector( + self, + vector: list[float], + vector_id: Optional[str] = None, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + **kwargs, + ) -> str: + document = { + k: v + for k, v in {"$vector": vector, "_id": vector_id, "namespace": namespace, "meta": meta}.items() + if v is not None + } + if vector_id is not None: + self.collection.find_one_and_replace({"_id": vector_id}, document, upsert=True) + return vector_id + else: + insert_result = self.collection.insert_one(document) + return insert_result.inserted_id + + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + find_filter = {k: v for k, v in {"_id": vector_id, "namespace": namespace}.items() if v is not None} + match = self.collection.find_one(find_filter, projection={"*": 1}) + if match: + return BaseVectorStoreDriver.Entry( + id=match["_id"], vector=match.get("$vector"), meta=match.get("meta"), namespace=match.get("namespace") + ) + else: + return None + + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + find_filter: dict[str, str] = {} if namespace is None else {"namespace": namespace} + return [ + BaseVectorStoreDriver.Entry( + id=match["_id"], vector=match.get("$vector"), meta=match.get("meta"), namespace=match.get("namespace") + ) + for match in self.collection.find(filter=find_filter, projection={"*": 1}) + ] + + def query( + self, + query: str, + *, + count: Optional[int] = None, + namespace: Optional[str] = None, + include_vectors: bool = False, + **kwargs: Any, + ) -> list[BaseVectorStoreDriver.Entry]: + query_filter: Optional[dict[str, Any]] = kwargs.pop("filter", None) + if kwargs: + warnings.warn( + "Unhandled keyword argument(s) provided to AstraDBVectorStore.query: " + f"'{','.join(sorted(kwargs.keys()))}'. These will be ignored.", + stacklevel=2, + ) + find_filter_ns: dict[str, Any] = {} if namespace is None else {"namespace": namespace} + find_filter = {**(query_filter or {}), **find_filter_ns} + find_projection: Optional[dict[str, int]] = {"*": 1} if include_vectors else None + vector = self.embedding_driver.embed_string(query) + matches = self.collection.find( + filter=find_filter, + sort={"$vector": vector}, + limit=count, + projection=find_projection, + include_similarity=True, + ) + return [ + BaseVectorStoreDriver.Entry( + id=match["_id"], + vector=match.get("$vector"), + score=match["$similarity"], + meta=match.get("meta"), + namespace=match.get("namespace"), + ) + for match in matches + ] diff --git a/poetry.lock b/poetry.lock index 2738d6c97..e0f0405d3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,18 +2,18 @@ [[package]] name = "accelerate" -version = "0.31.0" +version = "0.33.0" description = "Accelerate" optional = true python-versions = ">=3.8.0" files = [ - {file = "accelerate-0.31.0-py3-none-any.whl", hash = "sha256:0fc608dc49584f64d04711a39711d73cb0ad4ef3d21cddee7ef2216e29471144"}, - {file = "accelerate-0.31.0.tar.gz", hash = "sha256:b5199865b26106ccf9205acacbe8e4b3b428ad585e7c472d6a46f6fb75b6c176"}, + {file = "accelerate-0.33.0-py3-none-any.whl", hash = "sha256:0a7f33d60ba09afabd028d4f0856dd19c5a734b7a596d637d9dd6e3d0eadbaf3"}, + {file = "accelerate-0.33.0.tar.gz", hash = "sha256:11ba481ed6ea09191775df55ce464aeeba67a024bd0261a44b77b30fb439e26a"}, ] [package.dependencies] -huggingface-hub = "*" -numpy = ">=1.17" +huggingface-hub = ">=0.21.0" +numpy = ">=1.17,<2.0.0" packaging = ">=20.0" psutil = "*" pyyaml = "*" @@ -221,6 +221,25 @@ files = [ {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, ] +[[package]] +name = "astrapy" +version = "1.4.0" +description = "AstraPy is a Pythonic SDK for DataStax Astra and its Data API" +optional = true +python-versions = "<4.0.0,>=3.8.0" +files = [ + {file = "astrapy-1.4.0-py3-none-any.whl", hash = "sha256:6decf0619daf3fe1daca61a18b897fe51d8a64d52dd4a9d1261aa8dd31c4667e"}, + {file = "astrapy-1.4.0.tar.gz", hash = "sha256:336292bc43bacb356877639e456a056165f3240a0caf861630daa73587819db8"}, +] + +[package.dependencies] +bson = ">=0.5.10,<0.6.0" +cassio = ">=0.1.4,<0.2.0" +deprecation = ">=2.1.0,<2.2.0" +httpx = {version = ">=0.25.2,<1", extras = ["http2"]} +toml = ">=0.10.2,<0.11.0" +uuid6 = ">=2024.1.12,<2024.2.0" + [[package]] name = "async-timeout" version = "4.0.3" @@ -314,17 +333,17 @@ lxml = ["lxml"] [[package]] name = "boto3" -version = "1.34.146" +version = "1.34.148" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.34.146-py3-none-any.whl", hash = "sha256:7ec568fb19bce82a70be51f08fddac1ef927ca3fb0896cbb34303a012ba228d8"}, - {file = "boto3-1.34.146.tar.gz", hash = "sha256:5686fe2a6d1aa1de8a88e9589cdcc33361640d3d7a13da718a30717248886124"}, + {file = "boto3-1.34.148-py3-none-any.whl", hash = "sha256:d63d36e5a34533ba69188d56f96da132730d5e9932c4e11c02d79319cd1afcec"}, + {file = "boto3-1.34.148.tar.gz", hash = "sha256:2058397f0a92c301e3116e9e65fbbc70ea49270c250882d65043d19b7c6e2d17"}, ] [package.dependencies] -botocore = ">=1.34.146,<1.35.0" +botocore = ">=1.34.148,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -333,13 +352,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "boto3-stubs" -version = "1.34.146" -description = "Type annotations for boto3 1.34.146 generated with mypy-boto3-builder 7.25.0" +version = "1.34.148" +description = "Type annotations for boto3 1.34.148 generated with mypy-boto3-builder 7.25.0" optional = false python-versions = ">=3.8" files = [ - {file = "boto3_stubs-1.34.146-py3-none-any.whl", hash = "sha256:904918cb9d20f0d3744a7ed0863090fef8c1bd82d3bdcafbc94310e5cb36daf7"}, - {file = "boto3_stubs-1.34.146.tar.gz", hash = "sha256:5e4ccbedb7534fca303d5b8c2f1534a9bcd097c686f1f5a9ed82ae7f259bb8d1"}, + {file = "boto3_stubs-1.34.148-py3-none-any.whl", hash = "sha256:c0cb6b82fb8c7c123441c077eb3e450fb68f97addfe7239b213cdcc8ab1b562e"}, + {file = "boto3_stubs-1.34.148.tar.gz", hash = "sha256:d4cb7aa31fb8e782d60a47c23bb7d9545380ff7e5ab5e58775d810cf27169770"}, ] [package.dependencies] @@ -395,7 +414,7 @@ bedrock-agent = ["mypy-boto3-bedrock-agent (>=1.34.0,<1.35.0)"] bedrock-agent-runtime = ["mypy-boto3-bedrock-agent-runtime (>=1.34.0,<1.35.0)"] bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.34.0,<1.35.0)"] billingconductor = ["mypy-boto3-billingconductor (>=1.34.0,<1.35.0)"] -boto3 = ["boto3 (==1.34.146)", "botocore (==1.34.146)"] +boto3 = ["boto3 (==1.34.148)", "botocore (==1.34.148)"] braket = ["mypy-boto3-braket (>=1.34.0,<1.35.0)"] budgets = ["mypy-boto3-budgets (>=1.34.0,<1.35.0)"] ce = ["mypy-boto3-ce (>=1.34.0,<1.35.0)"] @@ -744,13 +763,13 @@ xray = ["mypy-boto3-xray (>=1.34.0,<1.35.0)"] [[package]] name = "botocore" -version = "1.34.146" +version = "1.34.148" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.146-py3-none-any.whl", hash = "sha256:3fd4782362bd29c192704ebf859c5c8c5189ad05719e391eefe23088434427ae"}, - {file = "botocore-1.34.146.tar.gz", hash = "sha256:849cb8e54e042443aeabcd7822b5f2b76cb5cfe33fe3a71f91c7c069748a869c"}, + {file = "botocore-1.34.148-py3-none-any.whl", hash = "sha256:9e09428b0bc4d0c1cf5e368dd6ab18eabf6047304060f8b5dd8391677cfe00e6"}, + {file = "botocore-1.34.148.tar.gz", hash = "sha256:258dd95570b43db9fa21cce5426eabaea5867e3a61224157650448b5019d1bbd"}, ] [package.dependencies] @@ -766,13 +785,13 @@ crt = ["awscrt (==0.20.11)"] [[package]] name = "botocore-stubs" -version = "1.34.146" +version = "1.34.148" description = "Type annotations and code completion for botocore" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "botocore_stubs-1.34.146-py3-none-any.whl", hash = "sha256:f77385f2b6af64b04e00dffc0f684879f308c48ce05deefabbec46b290841fc1"}, - {file = "botocore_stubs-1.34.146.tar.gz", hash = "sha256:a7d990c165e3151180a8c1c754183c2f687520117c918bdd6057f26baad4e1d2"}, + {file = "botocore_stubs-1.34.148-py3-none-any.whl", hash = "sha256:8814f796051b8a1fc15736863f20aa50e3cb1529800c879100c8f19159c35b8f"}, + {file = "botocore_stubs-1.34.148.tar.gz", hash = "sha256:057e49731e864def6a7b1862fd0e4896de15903da8b1e1ef4925618721498fcf"}, ] [package.dependencies] @@ -781,6 +800,20 @@ types-awscrt = "*" [package.extras] botocore = ["botocore"] +[[package]] +name = "bson" +version = "0.5.10" +description = "BSON codec for Python" +optional = true +python-versions = "*" +files = [ + {file = "bson-0.5.10.tar.gz", hash = "sha256:d6511b2ab051139a9123c184de1a04227262173ad593429d21e443d6462d6590"}, +] + +[package.dependencies] +python-dateutil = ">=2.4.0" +six = ">=1.9.0" + [[package]] name = "cachetools" version = "5.4.0" @@ -792,6 +825,69 @@ files = [ {file = "cachetools-5.4.0.tar.gz", hash = "sha256:b8adc2e7c07f105ced7bc56dbb6dfbe7c4a00acce20e2227b3f355be89bc6827"}, ] +[[package]] +name = "cassandra-driver" +version = "3.29.1" +description = "DataStax Driver for Apache Cassandra" +optional = true +python-versions = "*" +files = [ + {file = "cassandra-driver-3.29.1.tar.gz", hash = "sha256:38e9c2a2f2a9664bb03f1f852d5fccaeff2163942b5db35dffcf8bf32a51cfe5"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8f175c7616a63ca48cb8bd4acc443e2a3d889964d5157cead761f23cc8db7bd"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7d66398952b9cd21c40edff56e22b6d3bce765edc94b207ddb5896e7bc9aa088"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bbc6f575ef109ce5d4abfa2033bf36c394032abd83e32ab671159ce68e7e17b"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78f241af75696adb3e470209e2fbb498804c99e2b197d24d74774eee6784f283"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-win32.whl", hash = "sha256:54d9e651a742d6ca3d874ef8d06a40fa032d2dba97142da2d36f60c5675e39f8"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-win_amd64.whl", hash = "sha256:630dc5423cd40eba0ee9db31065e2238098ff1a25a6b1bd36360f85738f26e4b"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0b841d38c96bb878d31df393954863652d6d3a85f47bcc00fd1d70a5ea73023f"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:19cc7375f673e215bd4cbbefae2de9f07830be7dabef55284a2d2ff8d8691efe"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b74b355be3dcafe652fffda8f14f385ccc1a8dae9df28e6080cc660da39b45f"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e6dac7eddd3f4581859f180383574068a3f113907811b4dad755a8ace4c3fbd"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-win32.whl", hash = "sha256:293a79dba417112b56320ed0013d71fd7520f5fc4a5fd2ac8000c762c6dd5b07"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-win_amd64.whl", hash = "sha256:7c2374fdf1099047a6c9c8329c79d71ad11e61d9cca7de92a0f49655da4bdd8a"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4431a0c836f33a33c733c84997fbdb6398be005c4d18a8c8525c469fdc29393c"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d23b08381b171a9e42ace483a82457edcddada9e8367e31677b97538cde2dc34"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4beb29a0139e63a10a5b9a3c7b72c30a4e6e20c9f0574f9d22c0d4144fe3d348"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b206423cc454a78f16b411e7cb641dddc26168ac2e18f2c13665f5f3c89868c"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-win32.whl", hash = "sha256:ac898cca7303a3a2a3070513eee12ef0f1be1a0796935c5b8aa13dae8c0a7f7e"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-win_amd64.whl", hash = "sha256:4ad0c9fb2229048ad6ff8c6ddbf1fdc78b111f2b061c66237c2257fcc4a31b14"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4282c5deac462e4bb0f6fd0553a33d514dbd5ee99d0812594210080330ddd1a2"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:41ca7eea069754002418d3bdfbd3dfd150ea12cb9db474ab1a01fa4679a05bcb"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6639ccb268c4dc754bc45e03551711780d0e02cb298ab26cde1f42b7bcc74f8"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a9d7d3b1be24a7f113b5404186ccccc977520401303a8fe78ba34134cad2482"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-win32.whl", hash = "sha256:81c8fd556c6e1bb93577e69c1f10a3fadf7ddb93958d226ccbb72389396e9a92"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-win_amd64.whl", hash = "sha256:cfe70ed0f27af949de2767ea9cef4092584e8748759374a55bf23c30746c7b23"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a2c03c1d834ac1a0ae39f9af297a8cd38829003ce910b08b324fb3abe488ce2b"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9a3e1e2b01f3b7a5cf75c97401bce830071d99c42464352087d7475e0161af93"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90c42006665a4e490b0766b70f3d637f36a30accbef2da35d6d4081c0e0bafc3"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c1aca41f45772f9759e8246030907d92bc35fbbdc91525a3cb9b49939b80ad7"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-win32.whl", hash = "sha256:ce4a66245d4a0c8b07fdcb6398698c2c42eb71245fb49cff39435bb702ff7be6"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-win_amd64.whl", hash = "sha256:4cae69ceb1b1d9383e988a1b790115253eacf7867ceb15ed2adb736e3ce981be"}, +] + +[package.dependencies] +geomet = ">=0.1,<0.3" + +[package.extras] +cle = ["cryptography (>=35.0)"] +graph = ["gremlinpython (==3.4.6)"] + +[[package]] +name = "cassio" +version = "0.1.8" +description = "A framework-agnostic Python library to seamlessly integrate Apache Cassandra(R) with ML/LLM/genAI workloads." +optional = true +python-versions = "<4.0,>=3.8" +files = [ + {file = "cassio-0.1.8-py3-none-any.whl", hash = "sha256:c09e7c884ba7227ff5277c86f3b0f31c523672ea407f56d093c7227e69c54d94"}, + {file = "cassio-0.1.8.tar.gz", hash = "sha256:4e09929506cb3dd6fad217e89846d0a1a59069afd24b82c72526ef6f2e9271af"}, +] + +[package.dependencies] +cassandra-driver = ">=3.28.0,<4.0.0" +numpy = ">=1.0" +requests = ">=2.31.0,<3.0.0" + [[package]] name = "certifi" version = "2024.7.4" @@ -1027,19 +1123,22 @@ files = [ [[package]] name = "courlan" -version = "1.2.0" +version = "1.3.0" description = "Clean, filter and sample URLs to optimize data collection – includes spam, content type and language filters." optional = true -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "courlan-1.2.0-py3-none-any.whl", hash = "sha256:df9d3735b611e717c52a813a49d17a8b4d3a9d8b87bbace9065171fc5d084397"}, - {file = "courlan-1.2.0.tar.gz", hash = "sha256:0cbc9cac83970c651b937a7823a5d92cbebb6b601454ea0fb6cb4d0ee5d1845d"}, + {file = "courlan-1.3.0-py3-none-any.whl", hash = "sha256:bb30982108ef987731b127f1ecf5dfd5b7e46c825630e3c9313c80b4a454954c"}, + {file = "courlan-1.3.0.tar.gz", hash = "sha256:3868f388122f2b09d154802043fe92dfd62c3ea7a700eaae8abc05198cf8bc25"}, ] [package.dependencies] -babel = ">=2.11.0" -tld = {version = ">=0.13", markers = "python_version >= \"3.7\""} -urllib3 = {version = ">=1.26,<3", markers = "python_version >= \"3.7\""} +babel = ">=2.15.0" +tld = ">=0.13" +urllib3 = ">=1.26,<3" + +[package.extras] +dev = ["black", "mypy", "pytest", "pytest-cov"] [[package]] name = "coverage" @@ -1201,6 +1300,20 @@ wrapt = ">=1.10,<2" [package.extras] dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] +[[package]] +name = "deprecation" +version = "2.1.0" +description = "A library to handle automated deprecations" +optional = true +python-versions = "*" +files = [ + {file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"}, + {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, +] + +[package.dependencies] +packaging = "*" + [[package]] name = "distlib" version = "0.3.8" @@ -1278,37 +1391,38 @@ files = [ [[package]] name = "duckduckgo-search" -version = "6.2.1" +version = "6.2.3" description = "Search for words, documents, images, news, maps and text translation using the DuckDuckGo.com search engine." optional = true python-versions = ">=3.8" files = [ - {file = "duckduckgo_search-6.2.1-py3-none-any.whl", hash = "sha256:1a03f799b85fdfa08d5e6478624683f373b9dc35e6f145544b9cab72a4f575fa"}, - {file = "duckduckgo_search-6.2.1.tar.gz", hash = "sha256:d664ec096193e3fb43bdfae4b0ad9c04e44094b58f41998adcdd20a86ee1ed74"}, + {file = "duckduckgo_search-6.2.3-py3-none-any.whl", hash = "sha256:07e717dc8a2dc195086a319a6d094979ff0637be4a829b0f001cd6c220fb7490"}, + {file = "duckduckgo_search-6.2.3.tar.gz", hash = "sha256:69e51c88504212c5ce371b3684fa6fa2459ad8f296d2c94759909ae096f05319"}, ] [package.dependencies] click = ">=8.1.7" -pyreqwest-impersonate = ">=0.5.0" +pyreqwest-impersonate = ">=0.5.3" [package.extras] -dev = ["mypy (>=1.10.1)", "pytest (>=8.2.2)", "pytest-asyncio (>=0.23.7)", "ruff (>=0.5.2)"] +dev = ["mypy (>=1.11.0)", "pytest (>=8.3.1)", "pytest-asyncio (>=0.23.8)", "ruff (>=0.5.4)"] lxml = ["lxml (>=5.2.2)"] [[package]] name = "elevenlabs" -version = "1.5.0" +version = "1.6.0" description = "" optional = true python-versions = "<4.0,>=3.8" files = [ - {file = "elevenlabs-1.5.0-py3-none-any.whl", hash = "sha256:cc28257ad535adf57fdc70c9a3b8ddd6c34166f310bbc11a733523894e73ceca"}, - {file = "elevenlabs-1.5.0.tar.gz", hash = "sha256:d56a282f933e2eb991dac2b09cf7e928f1899f1cb5a9e9fa1d500be6edd7ee1d"}, + {file = "elevenlabs-1.6.0-py3-none-any.whl", hash = "sha256:38c9e7ba62674adcedaf31820d67db07496c74ccb695f754da2097cb19fa252d"}, + {file = "elevenlabs-1.6.0.tar.gz", hash = "sha256:315d830f45931df54c02d3919b3e9bbf03046573ad52204f59cda3df0f9513ef"}, ] [package.dependencies] httpx = ">=0.21.2" pydantic = ">=1.9.2" +pydantic-core = ">=2.18.2,<3.0.0" requests = ">=2.20" typing_extensions = ">=4.0.0" websockets = ">=11.0" @@ -1563,6 +1677,21 @@ files = [ [package.extras] speedup = ["python-levenshtein (>=0.12)"] +[[package]] +name = "geomet" +version = "0.2.1.post1" +description = "GeoJSON <-> WKT/WKB conversion utilities" +optional = true +python-versions = ">2.6, !=3.3.*, <4" +files = [ + {file = "geomet-0.2.1.post1-py3-none-any.whl", hash = "sha256:a41a1e336b381416d6cbed7f1745c848e91defaa4d4c1bdc1312732e46ffad2b"}, + {file = "geomet-0.2.1.post1.tar.gz", hash = "sha256:91d754f7c298cbfcabd3befdb69c641c27fe75e808b27aa55028605761d17e95"}, +] + +[package.dependencies] +click = "*" +six = "*" + [[package]] name = "ghp-import" version = "2.1.0" @@ -2084,13 +2213,13 @@ files = [ [[package]] name = "huggingface-hub" -version = "0.24.0" +version = "0.24.2" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = true python-versions = ">=3.8.0" files = [ - {file = "huggingface_hub-0.24.0-py3-none-any.whl", hash = "sha256:7ad92edefb93d8145c061f6df8d99df2ff85f8379ba5fac8a95aca0642afa5d7"}, - {file = "huggingface_hub-0.24.0.tar.gz", hash = "sha256:6c7092736b577d89d57b3cdfea026f1b0dc2234ae783fa0d59caf1bf7d52dfa7"}, + {file = "huggingface_hub-0.24.2-py3-none-any.whl", hash = "sha256:abdf3244d3a274c4b1fbc5c4a1ef700032b3f60ba93cc63e4f036fd082aa2805"}, + {file = "huggingface_hub-0.24.2.tar.gz", hash = "sha256:92be892405d2f6a7a8479016f9a5662354f202b2c6c1ff499609621aed1fae10"}, ] [package.dependencies] @@ -2154,22 +2283,22 @@ files = [ [[package]] name = "importlib-metadata" -version = "7.1.0" +version = "8.0.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, - {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, + {file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"}, + {file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] [[package]] name = "iniconfig" @@ -2182,20 +2311,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "intel-openmp" -version = "2021.4.0" -description = "Intel OpenMP* Runtime Library" -optional = true -python-versions = "*" -files = [ - {file = "intel_openmp-2021.4.0-py2.py3-none-macosx_10_15_x86_64.macosx_11_0_x86_64.whl", hash = "sha256:41c01e266a7fdb631a7609191709322da2bbf24b252ba763f125dd651bcc7675"}, - {file = "intel_openmp-2021.4.0-py2.py3-none-manylinux1_i686.whl", hash = "sha256:3b921236a38384e2016f0f3d65af6732cf2c12918087128a9163225451e776f2"}, - {file = "intel_openmp-2021.4.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:e2240ab8d01472fed04f3544a878cda5da16c26232b7ea1b59132dbfb48b186e"}, - {file = "intel_openmp-2021.4.0-py2.py3-none-win32.whl", hash = "sha256:6e863d8fd3d7e8ef389d52cf97a50fe2afe1a19247e8c0d168ce021546f96fc9"}, - {file = "intel_openmp-2021.4.0-py2.py3-none-win_amd64.whl", hash = "sha256:eef4c8bcc8acefd7f5cd3b9384dbf73d59e2c99fc56545712ded913f43c4a94f"}, -] - [[package]] name = "jaraco-classes" version = "3.4.0" @@ -2913,13 +3028,13 @@ mkdocs = ">=1.0.3" [[package]] name = "mkdocs-material" -version = "9.5.29" +version = "9.5.30" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_material-9.5.29-py3-none-any.whl", hash = "sha256:afc1f508e2662ded95f0a35a329e8a5acd73ee88ca07ba73836eb6fcdae5d8b4"}, - {file = "mkdocs_material-9.5.29.tar.gz", hash = "sha256:3e977598ec15a4ddad5c4dfc9e08edab6023edb51e88f0729bd27be77e3d322a"}, + {file = "mkdocs_material-9.5.30-py3-none-any.whl", hash = "sha256:fc070689c5250a180e9b9d79d8491ef9a3a7acb240db0728728d6c31eeb131d4"}, + {file = "mkdocs_material-9.5.30.tar.gz", hash = "sha256:3fd417dd42d679e3ba08b9e2d72cd8b8af142cc4a3969676ad6b00993dd182ec"}, ] [package.dependencies] @@ -3007,24 +3122,6 @@ files = [ griffe = ">=0.37" mkdocstrings = ">=0.20" -[[package]] -name = "mkl" -version = "2021.4.0" -description = "Intel® oneAPI Math Kernel Library" -optional = true -python-versions = "*" -files = [ - {file = "mkl-2021.4.0-py2.py3-none-macosx_10_15_x86_64.macosx_11_0_x86_64.whl", hash = "sha256:67460f5cd7e30e405b54d70d1ed3ca78118370b65f7327d495e9c8847705e2fb"}, - {file = "mkl-2021.4.0-py2.py3-none-manylinux1_i686.whl", hash = "sha256:636d07d90e68ccc9630c654d47ce9fdeb036bb46e2b193b3a9ac8cfea683cce5"}, - {file = "mkl-2021.4.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:398dbf2b0d12acaf54117a5210e8f191827f373d362d796091d161f610c1ebfb"}, - {file = "mkl-2021.4.0-py2.py3-none-win32.whl", hash = "sha256:439c640b269a5668134e3dcbcea4350459c4a8bc46469669b2d67e07e3d330e8"}, - {file = "mkl-2021.4.0-py2.py3-none-win_amd64.whl", hash = "sha256:ceef3cafce4c009dd25f65d7ad0d833a0fbadc3d8903991ec92351fe5de1e718"}, -] - -[package.dependencies] -intel-openmp = "==2021.*" -tbb = "==2021.*" - [[package]] name = "mongomock" version = "4.1.2" @@ -3445,12 +3542,13 @@ files = [ [[package]] name = "nvidia-cudnn-cu12" -version = "8.9.2.26" +version = "9.1.0.70" description = "cuDNN runtime libraries" optional = true python-versions = ">=3" files = [ - {file = "nvidia_cudnn_cu12-8.9.2.26-py3-none-manylinux1_x86_64.whl", hash = "sha256:5ccb288774fdfb07a7e7025ffec286971c06d8d7b4fb162525334616d7629ff9"}, + {file = "nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl", hash = "sha256:165764f44ef8c61fcdfdfdbe769d687e06374059fbb388b6c89ecb0e28793a6f"}, + {file = "nvidia_cudnn_cu12-9.1.0.70-py3-none-win_amd64.whl", hash = "sha256:6278562929433d68365a07a4a1546c237ba2849852c0d4b2262a486e805b977a"}, ] [package.dependencies] @@ -3526,6 +3624,7 @@ description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" files = [ + {file = "nvidia_nvjitlink_cu12-12.5.82-py3-none-manylinux2014_aarch64.whl", hash = "sha256:98103729cc5226e13ca319a10bbf9433bbbd44ef64fe72f45f067cacc14b8d27"}, {file = "nvidia_nvjitlink_cu12-12.5.82-py3-none-manylinux2014_x86_64.whl", hash = "sha256:f9b37bc5c8cf7509665cb6ada5aaa0ce65618f2332b7d3e78e9790511f111212"}, {file = "nvidia_nvjitlink_cu12-12.5.82-py3-none-win_amd64.whl", hash = "sha256:e782564d705ff0bf61ac3e1bf730166da66dd2fe9012f111ede5fc49b64ae697"}, ] @@ -3608,51 +3707,51 @@ kerberos = ["requests-kerberos"] [[package]] name = "opentelemetry-api" -version = "1.25.0" +version = "1.26.0" description = "OpenTelemetry Python API" optional = true python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.25.0-py3-none-any.whl", hash = "sha256:757fa1aa020a0f8fa139f8959e53dec2051cc26b832e76fa839a6d76ecefd737"}, - {file = "opentelemetry_api-1.25.0.tar.gz", hash = "sha256:77c4985f62f2614e42ce77ee4c9da5fa5f0bc1e1821085e9a47533a9323ae869"}, + {file = "opentelemetry_api-1.26.0-py3-none-any.whl", hash = "sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064"}, + {file = "opentelemetry_api-1.26.0.tar.gz", hash = "sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=7.1" +importlib-metadata = ">=6.0,<=8.0.0" [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.25.0" +version = "1.26.0" description = "OpenTelemetry Protobuf encoding" optional = true python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.25.0-py3-none-any.whl", hash = "sha256:15637b7d580c2675f70246563363775b4e6de947871e01d0f4e3881d1848d693"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.25.0.tar.gz", hash = "sha256:c93f4e30da4eee02bacd1e004eb82ce4da143a2f8e15b987a9f603e0a85407d3"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.26.0-py3-none-any.whl", hash = "sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.26.0.tar.gz", hash = "sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92"}, ] [package.dependencies] -opentelemetry-proto = "1.25.0" +opentelemetry-proto = "1.26.0" [[package]] name = "opentelemetry-exporter-otlp-proto-http" -version = "1.25.0" +version = "1.26.0" description = "OpenTelemetry Collector Protobuf over HTTP Exporter" optional = true python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_http-1.25.0-py3-none-any.whl", hash = "sha256:2eca686ee11b27acd28198b3ea5e5863a53d1266b91cda47c839d95d5e0541a6"}, - {file = "opentelemetry_exporter_otlp_proto_http-1.25.0.tar.gz", hash = "sha256:9f8723859e37c75183ea7afa73a3542f01d0fd274a5b97487ea24cb683d7d684"}, + {file = "opentelemetry_exporter_otlp_proto_http-1.26.0-py3-none-any.whl", hash = "sha256:ee72a87c48ec977421b02f16c52ea8d884122470e0be573905237b540f4ee562"}, + {file = "opentelemetry_exporter_otlp_proto_http-1.26.0.tar.gz", hash = "sha256:5801ebbcf7b527377883e6cbbdda35ee712dc55114fff1e93dfee210be56c908"}, ] [package.dependencies] deprecated = ">=1.2.6" googleapis-common-protos = ">=1.52,<2.0" opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.25.0" -opentelemetry-proto = "1.25.0" -opentelemetry-sdk = ">=1.25.0,<1.26.0" +opentelemetry-exporter-otlp-proto-common = "1.26.0" +opentelemetry-proto = "1.26.0" +opentelemetry-sdk = ">=1.26.0,<1.27.0" requests = ">=2.7,<3.0" [[package]] @@ -3689,13 +3788,13 @@ wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-proto" -version = "1.25.0" +version = "1.26.0" description = "OpenTelemetry Python Proto" optional = true python-versions = ">=3.8" files = [ - {file = "opentelemetry_proto-1.25.0-py3-none-any.whl", hash = "sha256:f07e3341c78d835d9b86665903b199893befa5e98866f63d22b00d0b7ca4972f"}, - {file = "opentelemetry_proto-1.25.0.tar.gz", hash = "sha256:35b6ef9dc4a9f7853ecc5006738ad40443701e52c26099e197895cbda8b815a3"}, + {file = "opentelemetry_proto-1.26.0-py3-none-any.whl", hash = "sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725"}, + {file = "opentelemetry_proto-1.26.0.tar.gz", hash = "sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e"}, ] [package.dependencies] @@ -3703,33 +3802,34 @@ protobuf = ">=3.19,<5.0" [[package]] name = "opentelemetry-sdk" -version = "1.25.0" +version = "1.26.0" description = "OpenTelemetry Python SDK" optional = true python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.25.0-py3-none-any.whl", hash = "sha256:d97ff7ec4b351692e9d5a15af570c693b8715ad78b8aafbec5c7100fe966b4c9"}, - {file = "opentelemetry_sdk-1.25.0.tar.gz", hash = "sha256:ce7fc319c57707ef5bf8b74fb9f8ebdb8bfafbe11898410e0d2a761d08a98ec7"}, + {file = "opentelemetry_sdk-1.26.0-py3-none-any.whl", hash = "sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897"}, + {file = "opentelemetry_sdk-1.26.0.tar.gz", hash = "sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85"}, ] [package.dependencies] -opentelemetry-api = "1.25.0" -opentelemetry-semantic-conventions = "0.46b0" +opentelemetry-api = "1.26.0" +opentelemetry-semantic-conventions = "0.47b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.46b0" +version = "0.47b0" description = "OpenTelemetry Semantic Conventions" optional = true python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.46b0-py3-none-any.whl", hash = "sha256:6daef4ef9fa51d51855d9f8e0ccd3a1bd59e0e545abe99ac6203804e36ab3e07"}, - {file = "opentelemetry_semantic_conventions-0.46b0.tar.gz", hash = "sha256:fbc982ecbb6a6e90869b15c1673be90bd18c8a56ff1cffc0864e38e2edffaefa"}, + {file = "opentelemetry_semantic_conventions-0.47b0-py3-none-any.whl", hash = "sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063"}, + {file = "opentelemetry_semantic_conventions-0.47b0.tar.gz", hash = "sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e"}, ] [package.dependencies] -opentelemetry-api = "1.25.0" +deprecated = ">=1.2.6" +opentelemetry-api = "1.26.0" [[package]] name = "packaging" @@ -3990,18 +4090,18 @@ type = ["mypy (>=1.8)"] [[package]] name = "playwright" -version = "1.45.0" +version = "1.45.1" description = "A high-level API to automate web browsers" optional = true python-versions = ">=3.8" files = [ - {file = "playwright-1.45.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:7d49aee5907d8e72060f04bc299cb6851c2dc44cb227540ade89d7aa529e907a"}, - {file = "playwright-1.45.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:210c9f848820f58b5b5ed48047748620b780ca3acc3e2b7560dafb2bfdd6d90a"}, - {file = "playwright-1.45.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:13b5398831f5499580e819ddc996633446a93bf88029e89451e51da188e16ae3"}, - {file = "playwright-1.45.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:0ba5a39f25fb9b9cf1bd48678f44536a29f6d83376329de2dee1567dac220afe"}, - {file = "playwright-1.45.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b09fa76614ba2926d45a4c0581f710c13652d5e32290ba6a1490fbafff7f0be8"}, - {file = "playwright-1.45.0-py3-none-win32.whl", hash = "sha256:97a7d53af89af54208b69c051046b462675fcf5b93f7fbfb7c0fa7f813424ee2"}, - {file = "playwright-1.45.0-py3-none-win_amd64.whl", hash = "sha256:701db496928429aec103739e48e3110806bd5cf49456cc95b89f28e1abda71da"}, + {file = "playwright-1.45.1-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:360607e37c00cdf97c74317f010e106ac4671aeaec6a192431dd71a30941da9d"}, + {file = "playwright-1.45.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:20adc2abf164c5e8969f9066011b152e12c210549edec78cd05bd0e9cf4135b7"}, + {file = "playwright-1.45.1-py3-none-macosx_11_0_universal2.whl", hash = "sha256:5f047cdc6accf4c7084dfc7587a2a5ef790cddc44cbb111e471293c5a91119db"}, + {file = "playwright-1.45.1-py3-none-manylinux1_x86_64.whl", hash = "sha256:f06f6659abe0abf263e5f6661d379fbf85c112745dd31d82332ceae914f58df7"}, + {file = "playwright-1.45.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87dc3b3d17e12c68830c29b7fdf5e93315221bbb4c6090e83e967e154e2c1828"}, + {file = "playwright-1.45.1-py3-none-win32.whl", hash = "sha256:2b8f517886ef1e2151982f6e7be84be3ef7d8135bdcf8ee705b4e4e99566e866"}, + {file = "playwright-1.45.1-py3-none-win_amd64.whl", hash = "sha256:0d236cf427784e77de352ba1b7d700693c5fe455b8e5f627f6d84ad5b84b5bf5"}, ] [package.dependencies] @@ -4090,22 +4190,22 @@ testing = ["google-api-core (>=1.31.5)"] [[package]] name = "protobuf" -version = "4.25.3" +version = "4.25.4" description = "" optional = true python-versions = ">=3.8" files = [ - {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, - {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, - {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, - {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, - {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, - {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, - {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, - {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, - {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, + {file = "protobuf-4.25.4-cp310-abi3-win32.whl", hash = "sha256:db9fd45183e1a67722cafa5c1da3e85c6492a5383f127c86c4c4aa4845867dc4"}, + {file = "protobuf-4.25.4-cp310-abi3-win_amd64.whl", hash = "sha256:ba3d8504116a921af46499471c63a85260c1a5fc23333154a427a310e015d26d"}, + {file = "protobuf-4.25.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:eecd41bfc0e4b1bd3fa7909ed93dd14dd5567b98c941d6c1ad08fdcab3d6884b"}, + {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:4c8a70fdcb995dcf6c8966cfa3a29101916f7225e9afe3ced4395359955d3835"}, + {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:3319e073562e2515c6ddc643eb92ce20809f5d8f10fead3332f71c63be6a7040"}, + {file = "protobuf-4.25.4-cp38-cp38-win32.whl", hash = "sha256:7e372cbbda66a63ebca18f8ffaa6948455dfecc4e9c1029312f6c2edcd86c4e1"}, + {file = "protobuf-4.25.4-cp38-cp38-win_amd64.whl", hash = "sha256:051e97ce9fa6067a4546e75cb14f90cf0232dcb3e3d508c448b8d0e4265b61c1"}, + {file = "protobuf-4.25.4-cp39-cp39-win32.whl", hash = "sha256:90bf6fd378494eb698805bbbe7afe6c5d12c8e17fca817a646cd6a1818c696ca"}, + {file = "protobuf-4.25.4-cp39-cp39-win_amd64.whl", hash = "sha256:ac79a48d6b99dfed2729ccccee547b34a1d3d63289c71cef056653a846a2240f"}, + {file = "protobuf-4.25.4-py3-none-any.whl", hash = "sha256:bfbebc1c8e4793cfd58589acfb8a1026be0003e852b9da7db5a4285bde996978"}, + {file = "protobuf-4.25.4.tar.gz", hash = "sha256:0dc4a62cc4052a036ee2204d26fe4d835c62827c855c8a03f29fe6da146b380d"}, ] [[package]] @@ -4634,19 +4734,19 @@ image = ["Pillow (>=8.0.0)"] [[package]] name = "pyreqwest-impersonate" -version = "0.5.2" +version = "0.5.3" description = "HTTP client that can impersonate web browsers, mimicking their headers and `TLS/JA3/JA4/HTTP2` fingerprints" optional = true python-versions = ">=3.8" files = [ - {file = "pyreqwest_impersonate-0.5.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:ec8c9318190020bad3f12a62aedc5faaa92078c38cf48189e98cd692b82e7c28"}, - {file = "pyreqwest_impersonate-0.5.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ca7fc399a672558de1d50b5beb5a153c7002adbe332edd7a752f1d19c35d7f7f"}, - {file = "pyreqwest_impersonate-0.5.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b453ab0a7f30a279151e88bd52449a01931307986d7c2a6a92a699d3ba58b66"}, - {file = "pyreqwest_impersonate-0.5.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9c78ab908cc10a195ddbfc60c18b205237233f76b4f56c28ebc1afe80210335"}, - {file = "pyreqwest_impersonate-0.5.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31db4e6e491868c227a252ef3a8fa8b7accc306e741934f74ad3e6fb096e334c"}, - {file = "pyreqwest_impersonate-0.5.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3ce34743e3ce2656ba262a325103b96e1d4f301be5f3dd8cb21ee4eec4c6e1b7"}, - {file = "pyreqwest_impersonate-0.5.2-cp38-abi3-win_amd64.whl", hash = "sha256:e72b39a64c12a35a1689af558d62c67f94d14310043e404a90550e39ddd4af7c"}, - {file = "pyreqwest_impersonate-0.5.2.tar.gz", hash = "sha256:50a57c4b139788606b311757ddf36efd82ea1c952decea808b4196220bd43803"}, + {file = "pyreqwest_impersonate-0.5.3-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f15922496f728769fb9e1b116d5d9d7ba5525d0f2f7a76a41a1daef8b2e0c6c3"}, + {file = "pyreqwest_impersonate-0.5.3-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:77533133ae73020e59bc56d776eea3fe3af4ac41d763a89f39c495436da0f4cf"}, + {file = "pyreqwest_impersonate-0.5.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436055fa3eeb3e01e2e8efd42a9f6c4ab62fd643eddc7c66d0e671b71605f273"}, + {file = "pyreqwest_impersonate-0.5.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e9d2e981a525fb72c1521f454e5581d2c7a3b1fcf1c97c0acfcb7a923d8cf3e"}, + {file = "pyreqwest_impersonate-0.5.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a6bf986d4a165f6976b3e862111e2a46091883cb55e9e6325150f5aea2644229"}, + {file = "pyreqwest_impersonate-0.5.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b7397f6dad3d5ae158e0b272cb3eafe8382e71775d829b286ae9c21cb5a879ff"}, + {file = "pyreqwest_impersonate-0.5.3-cp38-abi3-win_amd64.whl", hash = "sha256:6026e4751b5912aec1e45238c07daf1e2c9126b3b32b33396b72885021e8990c"}, + {file = "pyreqwest_impersonate-0.5.3.tar.gz", hash = "sha256:f21c10609958ff5be18df0c329eed42d2b3ba8a339b65dc5f96ab74537231692"}, ] [package.extras] @@ -4654,13 +4754,13 @@ dev = ["pytest (>=8.1.1)"] [[package]] name = "pyright" -version = "1.1.372" +version = "1.1.373" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" files = [ - {file = "pyright-1.1.372-py3-none-any.whl", hash = "sha256:25b15fb8967740f0949fd35b963777187f0a0404c0bd753cc966ec139f3eaa0b"}, - {file = "pyright-1.1.372.tar.gz", hash = "sha256:a9f5e0daa955daaa17e3d1ef76d3623e75f8afd5e37b437d3ff84d5b38c15420"}, + {file = "pyright-1.1.373-py3-none-any.whl", hash = "sha256:b805413227f2c209f27b14b55da27fe5e9fb84129c9f1eb27708a5d12f6f000e"}, + {file = "pyright-1.1.373.tar.gz", hash = "sha256:f41bcfc8b9d1802b09921a394d6ae1ce19694957b628bc657629688daf8a83ff"}, ] [package.dependencies] @@ -4672,13 +4772,13 @@ dev = ["twine (>=3.4.1)"] [[package]] name = "pytest" -version = "8.3.1" +version = "8.3.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.1-py3-none-any.whl", hash = "sha256:e9600ccf4f563976e2c99fa02c7624ab938296551f280835ee6516df8bc4ae8c"}, - {file = "pytest-8.3.1.tar.gz", hash = "sha256:7e8e5c5abd6e93cb1cc151f23e57adc31fcf8cfd2a3ff2da63e23f732de35db6"}, + {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, + {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, ] [package.dependencies] @@ -4864,6 +4964,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -4978,90 +5079,90 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)" [[package]] name = "regex" -version = "2024.5.15" +version = "2024.7.24" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" files = [ - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, - {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, - {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, - {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, - {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, - {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, - {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, - {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, - {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, - {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, - {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, - {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, + {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce"}, + {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024"}, + {file = "regex-2024.7.24-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f273674b445bcb6e4409bf8d1be67bc4b58e8b46fd0d560055d515b8830063cd"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23acc72f0f4e1a9e6e9843d6328177ae3074b4182167e34119ec7233dfeccf53"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65fd3d2e228cae024c411c5ccdffae4c315271eee4a8b839291f84f796b34eca"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c414cbda77dbf13c3bc88b073a1a9f375c7b0cb5e115e15d4b73ec3a2fbc6f59"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7a89eef64b5455835f5ed30254ec19bf41f7541cd94f266ab7cbd463f00c41"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19c65b00d42804e3fbea9708f0937d157e53429a39b7c61253ff15670ff62cb5"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7a5486ca56c8869070a966321d5ab416ff0f83f30e0e2da1ab48815c8d165d46"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6f51f9556785e5a203713f5efd9c085b4a45aecd2a42573e2b5041881b588d1f"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a4997716674d36a82eab3e86f8fa77080a5d8d96a389a61ea1d0e3a94a582cf7"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c0abb5e4e8ce71a61d9446040c1e86d4e6d23f9097275c5bd49ed978755ff0fe"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:18300a1d78cf1290fa583cd8b7cde26ecb73e9f5916690cf9d42de569c89b1ce"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:416c0e4f56308f34cdb18c3f59849479dde5b19febdcd6e6fa4d04b6c31c9faa"}, + {file = "regex-2024.7.24-cp310-cp310-win32.whl", hash = "sha256:fb168b5924bef397b5ba13aabd8cf5df7d3d93f10218d7b925e360d436863f66"}, + {file = "regex-2024.7.24-cp310-cp310-win_amd64.whl", hash = "sha256:6b9fc7e9cc983e75e2518496ba1afc524227c163e43d706688a6bb9eca41617e"}, + {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:382281306e3adaaa7b8b9ebbb3ffb43358a7bbf585fa93821300a418bb975281"}, + {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4fdd1384619f406ad9037fe6b6eaa3de2749e2e12084abc80169e8e075377d3b"}, + {file = "regex-2024.7.24-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3d974d24edb231446f708c455fd08f94c41c1ff4f04bcf06e5f36df5ef50b95a"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2ec4419a3fe6cf8a4795752596dfe0adb4aea40d3683a132bae9c30b81e8d73"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb563dd3aea54c797adf513eeec819c4213d7dbfc311874eb4fd28d10f2ff0f2"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:45104baae8b9f67569f0f1dca5e1f1ed77a54ae1cd8b0b07aba89272710db61e"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:994448ee01864501912abf2bad9203bffc34158e80fe8bfb5b031f4f8e16da51"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fac296f99283ac232d8125be932c5cd7644084a30748fda013028c815ba3364"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7e37e809b9303ec3a179085415cb5f418ecf65ec98cdfe34f6a078b46ef823ee"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:01b689e887f612610c869421241e075c02f2e3d1ae93a037cb14f88ab6a8934c"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f6442f0f0ff81775eaa5b05af8a0ffa1dda36e9cf6ec1e0d3d245e8564b684ce"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:871e3ab2838fbcb4e0865a6e01233975df3a15e6fce93b6f99d75cacbd9862d1"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c918b7a1e26b4ab40409820ddccc5d49871a82329640f5005f73572d5eaa9b5e"}, + {file = "regex-2024.7.24-cp311-cp311-win32.whl", hash = "sha256:2dfbb8baf8ba2c2b9aa2807f44ed272f0913eeeba002478c4577b8d29cde215c"}, + {file = "regex-2024.7.24-cp311-cp311-win_amd64.whl", hash = "sha256:538d30cd96ed7d1416d3956f94d54e426a8daf7c14527f6e0d6d425fcb4cca52"}, + {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86"}, + {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad"}, + {file = "regex-2024.7.24-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38"}, + {file = "regex-2024.7.24-cp312-cp312-win32.whl", hash = "sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc"}, + {file = "regex-2024.7.24-cp312-cp312-win_amd64.whl", hash = "sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908"}, + {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:66b4c0731a5c81921e938dcf1a88e978264e26e6ac4ec96a4d21ae0354581ae0"}, + {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:88ecc3afd7e776967fa16c80f974cb79399ee8dc6c96423321d6f7d4b881c92b"}, + {file = "regex-2024.7.24-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64bd50cf16bcc54b274e20235bf8edbb64184a30e1e53873ff8d444e7ac656b2"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb462f0e346fcf41a901a126b50f8781e9a474d3927930f3490f38a6e73b6950"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a82465ebbc9b1c5c50738536fdfa7cab639a261a99b469c9d4c7dcbb2b3f1e57"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68a8f8c046c6466ac61a36b65bb2395c74451df2ffb8458492ef49900efed293"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac8e84fff5d27420f3c1e879ce9929108e873667ec87e0c8eeb413a5311adfe"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba2537ef2163db9e6ccdbeb6f6424282ae4dea43177402152c67ef869cf3978b"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:43affe33137fcd679bdae93fb25924979517e011f9dea99163f80b82eadc7e53"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:c9bb87fdf2ab2370f21e4d5636e5317775e5d51ff32ebff2cf389f71b9b13750"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:945352286a541406f99b2655c973852da7911b3f4264e010218bbc1cc73168f2"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:8bc593dcce679206b60a538c302d03c29b18e3d862609317cb560e18b66d10cf"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3f3b6ca8eae6d6c75a6cff525c8530c60e909a71a15e1b731723233331de4169"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c51edc3541e11fbe83f0c4d9412ef6c79f664a3745fab261457e84465ec9d5a8"}, + {file = "regex-2024.7.24-cp38-cp38-win32.whl", hash = "sha256:d0a07763776188b4db4c9c7fb1b8c494049f84659bb387b71c73bbc07f189e96"}, + {file = "regex-2024.7.24-cp38-cp38-win_amd64.whl", hash = "sha256:8fd5afd101dcf86a270d254364e0e8dddedebe6bd1ab9d5f732f274fa00499a5"}, + {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0ffe3f9d430cd37d8fa5632ff6fb36d5b24818c5c986893063b4e5bdb84cdf24"}, + {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25419b70ba00a16abc90ee5fce061228206173231f004437730b67ac77323f0d"}, + {file = "regex-2024.7.24-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33e2614a7ce627f0cdf2ad104797d1f68342d967de3695678c0cb84f530709f8"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d33a0021893ede5969876052796165bab6006559ab845fd7b515a30abdd990dc"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04ce29e2c5fedf296b1a1b0acc1724ba93a36fb14031f3abfb7abda2806c1535"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b16582783f44fbca6fcf46f61347340c787d7530d88b4d590a397a47583f31dd"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:836d3cc225b3e8a943d0b02633fb2f28a66e281290302a79df0e1eaa984ff7c1"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:438d9f0f4bc64e8dea78274caa5af971ceff0f8771e1a2333620969936ba10be"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:973335b1624859cb0e52f96062a28aa18f3a5fc77a96e4a3d6d76e29811a0e6e"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c5e69fd3eb0b409432b537fe3c6f44ac089c458ab6b78dcec14478422879ec5f"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fbf8c2f00904eaf63ff37718eb13acf8e178cb940520e47b2f05027f5bb34ce3"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2757ace61bc4061b69af19e4689fa4416e1a04840f33b441034202b5cd02d4"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:44fc61b99035fd9b3b9453f1713234e5a7c92a04f3577252b45feefe1b327759"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:84c312cdf839e8b579f504afcd7b65f35d60b6285d892b19adea16355e8343c9"}, + {file = "regex-2024.7.24-cp39-cp39-win32.whl", hash = "sha256:ca5b2028c2f7af4e13fb9fc29b28d0ce767c38c7facdf64f6c2cd040413055f1"}, + {file = "regex-2024.7.24-cp39-cp39-win_amd64.whl", hash = "sha256:7c479f5ae937ec9985ecaf42e2e10631551d909f203e31308c12d703922742f9"}, + {file = "regex-2024.7.24.tar.gz", hash = "sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506"}, ] [[package]] @@ -5512,37 +5613,37 @@ files = [ [[package]] name = "snowflake-connector-python" -version = "3.11.0" +version = "3.12.0" description = "Snowflake Connector for Python" optional = true python-versions = ">=3.8" files = [ - {file = "snowflake_connector_python-3.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0be9e2e35c7cf98df4ee454f1a00b7d1ff541ce46582d9b9ec51928e1583683c"}, - {file = "snowflake_connector_python-3.11.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:e01aa2f65bd7374a11a7d74c30d4a78938bbf60db512fc170bd25fc1b385566b"}, - {file = "snowflake_connector_python-3.11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a284c275929f81c5b53160c0d0ee447ee20b63af0493c87f3dd39faf3178f59"}, - {file = "snowflake_connector_python-3.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:686a50bf1e7d2cf89db7319a29d08816ea57039fcf05ca3f3bf3f92dc25bed40"}, - {file = "snowflake_connector_python-3.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:eae346b87906db2095f1c830ba105b529a211ecd0c0b1e43d8775fc49e7e476c"}, - {file = "snowflake_connector_python-3.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:415992f074b51712770c3dbd7a6b5a95b5dd04ffe02fc51ac8446e193771436d"}, - {file = "snowflake_connector_python-3.11.0-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:e55eca3ff74fb33ea21455369e171ad61ef31eb916cbbbdab7ccb90cb98ad8d0"}, - {file = "snowflake_connector_python-3.11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa48b1f2a124098745a33ee93e34d85a3dfb60fa3d2d7ec5efee4aa17bb05053"}, - {file = "snowflake_connector_python-3.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96b21a062fc7aacb49202c8502239c0728319a96834a9fca1b6666a51e515dcc"}, - {file = "snowflake_connector_python-3.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:ae890352e9e09e2084fd13647a664a31343bfa58d9aa41770e9ec3b810f9bc2c"}, - {file = "snowflake_connector_python-3.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e8f5c376b2368082819126f566551e451d51c95cc2febac45377026d44a401b0"}, - {file = "snowflake_connector_python-3.11.0-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:56c29839cbdf4778b997a96dacb849c3b374b7818c60eefe87b67debc9672f59"}, - {file = "snowflake_connector_python-3.11.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c203a035e417a386d7b09e977a198588471a768336f781b0561d09ed0f495edc"}, - {file = "snowflake_connector_python-3.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e906f517d2e79cd19c04dddf3bba13a072755503516f6bcd55ae1122b6df7fdb"}, - {file = "snowflake_connector_python-3.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:3e5489b814f311425e3966c0434f686131e48886eb7e0a8606631695f3c4bd48"}, - {file = "snowflake_connector_python-3.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:507c70ccd87c37a813c6aab27fe97007fb96c5372a5a33cc4b9137acb0d921e1"}, - {file = "snowflake_connector_python-3.11.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:f238a3cb4522d2943861f38cb0c9650c08c02e45a38d4eefa27f22ad95748fb4"}, - {file = "snowflake_connector_python-3.11.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f797eb2552950cf04fe07304da714f1d473f7a0c1548cfbce5614c4b0a66e441"}, - {file = "snowflake_connector_python-3.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a525c60fd5922098eab2425bc3f63bb3df0f07dd54e02580505a6208f908d32"}, - {file = "snowflake_connector_python-3.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b61dbd3581c043b338c99caff900a9cce187c83333bafdf1d57c8c126366b4a"}, - {file = "snowflake_connector_python-3.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:13170b419a6c2b98e23c89a459e2576955e0bae4fd267e9f44fffad642aa3ecc"}, - {file = "snowflake_connector_python-3.11.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:18bc6fd9fd544d540b06d9e97e754d0053b5cb7e5d9266586b3df8f243ef97bc"}, - {file = "snowflake_connector_python-3.11.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd4120451e33a32fb8fa018c9cd3e56c370ab0702ffe93b4e68acdae92524c3c"}, - {file = "snowflake_connector_python-3.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26ed3b5537864ee9d72f313b18b80b76136b7838774ea5bc2b4f5e1df8e9b90"}, - {file = "snowflake_connector_python-3.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc6afb35826e958949edb2d464e0d35ec46ef41b65546a311a333f4d0a7d07a6"}, - {file = "snowflake_connector_python-3.11.0.tar.gz", hash = "sha256:3169c014a03e5f5855112605e393897a552e558953c69f25a02e33b1998864d0"}, + {file = "snowflake_connector_python-3.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:edf28df8be24845cfcec653b160d2b8c048d5cb0c85b051f4957f0b0aae1e493"}, + {file = "snowflake_connector_python-3.12.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:c2bbdbbb028d7d542815ed68b28200728aa6707b9354e3a447fdc8c7a34bcdce"}, + {file = "snowflake_connector_python-3.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92c9a19a23033df709e63baa6ccdf6eff65210143a8c9c67a0a24bba862034b"}, + {file = "snowflake_connector_python-3.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d33d845e4c68d33e73a9f64100b53342c18607ac25c4f2a27dbed2078078d12"}, + {file = "snowflake_connector_python-3.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:c1d43bfaa885aab712f14f9ced232abe5023adfca7fbf7a7a0768a162523e9d6"}, + {file = "snowflake_connector_python-3.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6a0cc03fb44808f3ddc464ee272f141564c8daea14475e1df5c2a54c7acb2ddf"}, + {file = "snowflake_connector_python-3.12.0-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:564752d22accc43351b50f676b03aa9f2b441be2641e3cf9a7790faf54eff210"}, + {file = "snowflake_connector_python-3.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27d6a1a180832c7b551d38df1094a70fb79917f90c57893b9ce7e219362f6c1"}, + {file = "snowflake_connector_python-3.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60675fd83022daef40541d717d006695149c512b283e35741b61a4f48ba537e9"}, + {file = "snowflake_connector_python-3.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a567b937b0179d1e95a8ad7200943d286f38d0e76df90af10f747ed9149dd681"}, + {file = "snowflake_connector_python-3.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc333fcfc383a8cab8bd7e890a7c76703e26598925a05954c75d2c50bff06071"}, + {file = "snowflake_connector_python-3.12.0-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:3c06bfba4a329fd4ec3feba0ada7b31f86ed4e156a9766bced52c2814d001fd2"}, + {file = "snowflake_connector_python-3.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acf84b07dd2f22adfaa7d52ccd6be1722bd5a0e2b1a9b08681c3851bea05768f"}, + {file = "snowflake_connector_python-3.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:019b8a61e5af689451d502df2af8793fc6f20b5b0a3548fd8ad03aa8b62e7f2d"}, + {file = "snowflake_connector_python-3.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:45f9b9678694f10571c1f7ec7d0d741663ad0ff61a71ae53aa71be47faa19978"}, + {file = "snowflake_connector_python-3.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:21cbaef51fbed719de01155079df3d004cee963d3723c1ebdb8980923f893e04"}, + {file = "snowflake_connector_python-3.12.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:c86d4a7d49f42ea0bb34218cb49c401ba995892abcfb509ea749cd0a74a8b28a"}, + {file = "snowflake_connector_python-3.12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aa34aec0f96d7fc7271e38c68ee0d58529875d05e084afb4fc8f09b694643c4"}, + {file = "snowflake_connector_python-3.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2f621030b26a220711c64518e00059736b79c1da53afa6a8ce68b31c1941014"}, + {file = "snowflake_connector_python-3.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:368e46f1d079056e028bfe8f7171fabef62eb00bcf590df294220b7a5be5d56c"}, + {file = "snowflake_connector_python-3.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2735e16fffded0900f7484030613b79699afc1ed4e5cff086bd139a0ce965594"}, + {file = "snowflake_connector_python-3.12.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:c06a8e2e12284b4a4d462d0073fb4983e90ad2d6a2382926f9e3409f06c81d0b"}, + {file = "snowflake_connector_python-3.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:880e6e95171cd7374a86da14132fdfc4b622665f134561f4d43e3f35bdacf67d"}, + {file = "snowflake_connector_python-3.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e245b84c164433454ce49d78e6bcf5c2e62e25657358bf34ab533166e588f80"}, + {file = "snowflake_connector_python-3.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:85a5565b8813d164f33f32a825a70443008fe009aae050307f128a1ca892f9ed"}, + {file = "snowflake_connector_python-3.12.0.tar.gz", hash = "sha256:320e0b6f8cd8556e19c8b87249c931700238b2958313afc7a33108d67da87d82"}, ] [package.dependencies] @@ -5567,7 +5668,7 @@ urllib3 = {version = ">=1.21.1,<2.0.0", markers = "python_version < \"3.10\""} [package.extras] development = ["Cython", "coverage", "more-itertools", "numpy (<1.27.0)", "pendulum (!=2.1.1)", "pexpect", "pytest (<7.5.0)", "pytest-cov", "pytest-rerunfailures", "pytest-timeout", "pytest-xdist", "pytzdata"] pandas = ["pandas (>=1.0.0,<3.0.0)", "pyarrow"] -secure-local-storage = ["keyring (>=23.1.0,<25.0.0)"] +secure-local-storage = ["keyring (>=23.1.0,<26.0.0)"] [[package]] name = "snowflake-sqlalchemy" @@ -5724,19 +5825,6 @@ mpmath = ">=1.1.0,<1.4" [package.extras] dev = ["hypothesis (>=6.70.0)", "pytest (>=7.1.0)"] -[[package]] -name = "tbb" -version = "2021.13.0" -description = "Intel® oneAPI Threading Building Blocks (oneTBB)" -optional = true -python-versions = "*" -files = [ - {file = "tbb-2021.13.0-py2.py3-none-manylinux1_i686.whl", hash = "sha256:a2567725329639519d46d92a2634cf61e76601dac2f777a05686fea546c4fe4f"}, - {file = "tbb-2021.13.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:aaf667e92849adb012b8874d6393282afc318aca4407fc62f912ee30a22da46a"}, - {file = "tbb-2021.13.0-py3-none-win32.whl", hash = "sha256:6669d26703e9943f6164c6407bd4a237a45007e79b8d3832fe6999576eaaa9ef"}, - {file = "tbb-2021.13.0-py3-none-win_amd64.whl", hash = "sha256:3528a53e4bbe64b07a6112b4c5a00ff3c61924ee46c9c68e004a1ac7ad1f09c3"}, -] - [[package]] name = "tenacity" version = "8.5.0" @@ -5932,6 +6020,17 @@ dev = ["tokenizers[testing]"] docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"] +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = true +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + [[package]] name = "tomli" version = "2.0.1" @@ -5956,44 +6055,43 @@ files = [ [[package]] name = "torch" -version = "2.3.1" +version = "2.4.0" description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" optional = true python-versions = ">=3.8.0" files = [ - {file = "torch-2.3.1-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:605a25b23944be5ab7c3467e843580e1d888b8066e5aaf17ff7bf9cc30001cc3"}, - {file = "torch-2.3.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:f2357eb0965583a0954d6f9ad005bba0091f956aef879822274b1bcdb11bd308"}, - {file = "torch-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:32b05fe0d1ada7f69c9f86c14ff69b0ef1957a5a54199bacba63d22d8fab720b"}, - {file = "torch-2.3.1-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:7c09a94362778428484bcf995f6004b04952106aee0ef45ff0b4bab484f5498d"}, - {file = "torch-2.3.1-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:b2ec81b61bb094ea4a9dee1cd3f7b76a44555375719ad29f05c0ca8ef596ad39"}, - {file = "torch-2.3.1-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:490cc3d917d1fe0bd027057dfe9941dc1d6d8e3cae76140f5dd9a7e5bc7130ab"}, - {file = "torch-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:5802530783bd465fe66c2df99123c9a54be06da118fbd785a25ab0a88123758a"}, - {file = "torch-2.3.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:a7dd4ed388ad1f3d502bf09453d5fe596c7b121de7e0cfaca1e2017782e9bbac"}, - {file = "torch-2.3.1-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:a486c0b1976a118805fc7c9641d02df7afbb0c21e6b555d3bb985c9f9601b61a"}, - {file = "torch-2.3.1-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:224259821fe3e4c6f7edf1528e4fe4ac779c77addaa74215eb0b63a5c474d66c"}, - {file = "torch-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:e5fdccbf6f1334b2203a61a0e03821d5845f1421defe311dabeae2fc8fbeac2d"}, - {file = "torch-2.3.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:3c333dc2ebc189561514eda06e81df22bf8fb64e2384746b2cb9f04f96d1d4c8"}, - {file = "torch-2.3.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:07e9ba746832b8d069cacb45f312cadd8ad02b81ea527ec9766c0e7404bb3feb"}, - {file = "torch-2.3.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:462d1c07dbf6bb5d9d2f3316fee73a24f3d12cd8dacf681ad46ef6418f7f6626"}, - {file = "torch-2.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff60bf7ce3de1d43ad3f6969983f321a31f0a45df3690921720bcad6a8596cc4"}, - {file = "torch-2.3.1-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:bee0bd33dc58aa8fc8a7527876e9b9a0e812ad08122054a5bff2ce5abf005b10"}, - {file = "torch-2.3.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:aaa872abde9a3d4f91580f6396d54888620f4a0b92e3976a6034759df4b961ad"}, - {file = "torch-2.3.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:3d7a7f7ef21a7520510553dc3938b0c57c116a7daee20736a9e25cbc0e832bdc"}, - {file = "torch-2.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:4777f6cefa0c2b5fa87223c213e7b6f417cf254a45e5829be4ccd1b2a4ee1011"}, - {file = "torch-2.3.1-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:2bb5af780c55be68fe100feb0528d2edebace1d55cb2e351de735809ba7391eb"}, + {file = "torch-2.4.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:4ed94583e244af51d6a8d28701ca5a9e02d1219e782f5a01dd401f90af17d8ac"}, + {file = "torch-2.4.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:c4ca297b7bd58b506bfd6e78ffd14eb97c0e7797dcd7965df62f50bb575d8954"}, + {file = "torch-2.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:2497cbc7b3c951d69b276ca51fe01c2865db67040ac67f5fc20b03e41d16ea4a"}, + {file = "torch-2.4.0-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:685418ab93730efbee71528821ff54005596970dd497bf03c89204fb7e3f71de"}, + {file = "torch-2.4.0-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:e743adadd8c8152bb8373543964551a7cb7cc20ba898dc8f9c0cdbe47c283de0"}, + {file = "torch-2.4.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:7334325c0292cbd5c2eac085f449bf57d3690932eac37027e193ba775703c9e6"}, + {file = "torch-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:97730014da4c57ffacb3c09298c6ce05400606e890bd7a05008d13dd086e46b1"}, + {file = "torch-2.4.0-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:f169b4ea6dc93b3a33319611fcc47dc1406e4dd539844dcbd2dec4c1b96e166d"}, + {file = "torch-2.4.0-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:997084a0f9784d2a89095a6dc67c7925e21bf25dea0b3d069b41195016ccfcbb"}, + {file = "torch-2.4.0-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:bc3988e8b36d1e8b998d143255d9408d8c75da4ab6dd0dcfd23b623dfb0f0f57"}, + {file = "torch-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:3374128bbf7e62cdaed6c237bfd39809fbcfaa576bee91e904706840c3f2195c"}, + {file = "torch-2.4.0-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:91aaf00bfe1ffa44dc5b52809d9a95129fca10212eca3ac26420eb11727c6288"}, + {file = "torch-2.4.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cc30457ea5489c62747d3306438af00c606b509d78822a88f804202ba63111ed"}, + {file = "torch-2.4.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a046491aaf96d1215e65e1fa85911ef2ded6d49ea34c8df4d0638879f2402eef"}, + {file = "torch-2.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:688eec9240f3ce775f22e1e1a5ab9894f3d5fe60f3f586deb7dbd23a46a83916"}, + {file = "torch-2.4.0-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:3af4de2a618fb065e78404c4ba27a818a7b7957eaeff28c6c66ce7fb504b68b8"}, + {file = "torch-2.4.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:618808d3f610d5f180e47a697d4ec90b810953bb1e020f424b2ac7fb0884b545"}, + {file = "torch-2.4.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:ed765d232d23566052ba83632ec73a4fccde00b4c94ad45d63b471b09d63b7a7"}, + {file = "torch-2.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:a2feb98ac470109472fb10dfef38622a7ee08482a16c357863ebc7bc7db7c8f7"}, + {file = "torch-2.4.0-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:8940fc8b97a4c61fdb5d46a368f21f4a3a562a17879e932eb51a5ec62310cb31"}, ] [package.dependencies] filelock = "*" fsspec = "*" jinja2 = "*" -mkl = {version = ">=2021.1.1,<=2021.4.0", markers = "platform_system == \"Windows\""} networkx = "*" nvidia-cublas-cu12 = {version = "12.1.3.1", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} nvidia-cuda-cupti-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} nvidia-cuda-nvrtc-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} nvidia-cuda-runtime-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cudnn-cu12 = {version = "8.9.2.26", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cudnn-cu12 = {version = "9.1.0.70", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} nvidia-cufft-cu12 = {version = "11.0.2.54", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} nvidia-curand-cu12 = {version = "10.3.2.106", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} nvidia-cusolver-cu12 = {version = "11.4.5.107", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} @@ -6001,12 +6099,12 @@ nvidia-cusparse-cu12 = {version = "12.1.0.106", markers = "platform_system == \" nvidia-nccl-cu12 = {version = "2.20.5", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} nvidia-nvtx-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} sympy = "*" -triton = {version = "2.3.1", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and python_version < \"3.12\""} +triton = {version = "3.0.0", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and python_version < \"3.13\""} typing-extensions = ">=4.8.0" [package.extras] opt-einsum = ["opt-einsum (>=3.3)"] -optree = ["optree (>=0.9.1)"] +optree = ["optree (>=0.11.0)"] [[package]] name = "tqdm" @@ -6054,19 +6152,19 @@ gui = ["Gooey (>=1.0.1)"] [[package]] name = "transformers" -version = "4.41.2" +version = "4.43.2" description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow" optional = true python-versions = ">=3.8.0" files = [ - {file = "transformers-4.41.2-py3-none-any.whl", hash = "sha256:05555d20e43f808de1ef211ab64803cdb513170cef70d29a888b589caebefc67"}, - {file = "transformers-4.41.2.tar.gz", hash = "sha256:80a4db216533d573e9cc7388646c31ed9480918feb7c55eb211249cb23567f87"}, + {file = "transformers-4.43.2-py3-none-any.whl", hash = "sha256:283c8b47cf38640c5c0caea60be0dfa948669fa48e9739b03717cbf5e8b20f11"}, + {file = "transformers-4.43.2.tar.gz", hash = "sha256:99dbbdeef9d451cdbc1c5316dce3af3dd5bb56b6cda5d0c564253e8fa7ccaf02"}, ] [package.dependencies] accelerate = {version = ">=0.21.0", optional = true, markers = "extra == \"torch\""} filelock = "*" -huggingface-hub = ">=0.23.0,<1.0" +huggingface-hub = ">=0.23.2,<1.0" numpy = ">=1.17" packaging = ">=20.0" pyyaml = ">=5.1" @@ -6080,14 +6178,15 @@ tqdm = ">=4.27" [package.extras] accelerate = ["accelerate (>=0.21.0)"] agents = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "datasets (!=2.5.0)", "diffusers", "opencv-python", "sentencepiece (>=0.1.91,!=0.1.92)", "torch"] -all = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "codecarbon (==1.2.0)", "decord (==0.6.0)", "flax (>=0.4.1,<=0.7.0)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "phonemizer", "protobuf", "pyctcdecode (>=0.4.0)", "ray[tune] (>=2.7.0)", "scipy (<1.13.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timm", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision"] +all = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "codecarbon (==1.2.0)", "decord (==0.6.0)", "flax (>=0.4.1,<=0.7.0)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1,<0.14.0)", "librosa", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "phonemizer", "protobuf", "pyctcdecode (>=0.4.0)", "ray[tune] (>=2.7.0)", "scipy (<1.13.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timm (<=0.9.16)", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision"] audio = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"] +benchmark = ["optimum-benchmark (>=0.2.0)"] codecarbon = ["codecarbon (==1.2.0)"] deepspeed = ["accelerate (>=0.21.0)", "deepspeed (>=0.9.3)"] -deepspeed-testing = ["GitPython (<3.1.19)", "accelerate (>=0.21.0)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "deepspeed (>=0.9.3)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "nltk", "optuna", "parameterized", "protobuf", "psutil", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "timeout-decorator"] -dev = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "decord (==0.6.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "flax (>=0.4.1,<=0.7.0)", "fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "scipy (<1.13.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "timm", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] -dev-tensorflow = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "isort (>=5.5.4)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "tokenizers (>=0.19,<0.20)", "urllib3 (<2.0.0)"] -dev-torch = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "kenlm", "librosa", "nltk", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "timeout-decorator", "timm", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] +deepspeed-testing = ["GitPython (<3.1.19)", "accelerate (>=0.21.0)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "deepspeed (>=0.9.3)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "nltk", "optuna", "parameterized", "protobuf", "psutil", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "timeout-decorator"] +dev = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "decord (==0.6.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "flax (>=0.4.1,<=0.7.0)", "fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1,<0.14.0)", "librosa", "nltk", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "scipy (<1.13.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "timm (<=0.9.16)", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] +dev-tensorflow = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "isort (>=5.5.4)", "kenlm", "keras-nlp (>=0.3.1,<0.14.0)", "librosa", "nltk", "onnxconverter-common", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "tokenizers (>=0.19,<0.20)", "urllib3 (<2.0.0)"] +dev-torch = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "kenlm", "librosa", "nltk", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "timeout-decorator", "timm (<=0.9.16)", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] flax = ["flax (>=0.4.1,<=0.7.0)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "optax (>=0.0.8,<=0.1.4)", "scipy (<1.13.0)"] flax-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"] ftfy = ["ftfy"] @@ -6098,41 +6197,46 @@ natten = ["natten (>=0.14.6,<0.15.0)"] onnx = ["onnxconverter-common", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "tf2onnx"] onnxruntime = ["onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)"] optuna = ["optuna"] -quality = ["GitPython (<3.1.19)", "datasets (!=2.5.0)", "isort (>=5.5.4)", "ruff (==0.1.5)", "urllib3 (<2.0.0)"] +quality = ["GitPython (<3.1.19)", "datasets (!=2.5.0)", "isort (>=5.5.4)", "ruff (==0.4.4)", "urllib3 (<2.0.0)"] ray = ["ray[tune] (>=2.7.0)"] retrieval = ["datasets (!=2.5.0)", "faiss-cpu"] +ruff = ["ruff (==0.4.4)"] sagemaker = ["sagemaker (>=2.31.0)"] sentencepiece = ["protobuf", "sentencepiece (>=0.1.91,!=0.1.92)"] serving = ["fastapi", "pydantic", "starlette", "uvicorn"] sigopt = ["sigopt"] sklearn = ["scikit-learn"] speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)", "torchaudio"] -testing = ["GitPython (<3.1.19)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "nltk", "parameterized", "psutil", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "timeout-decorator"] -tf = ["keras-nlp (>=0.3.1)", "onnxconverter-common", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx"] -tf-cpu = ["keras (>2.9,<2.16)", "keras-nlp (>=0.3.1)", "onnxconverter-common", "tensorflow-cpu (>2.9,<2.16)", "tensorflow-probability (<2.16)", "tensorflow-text (<2.16)", "tf2onnx"] +testing = ["GitPython (<3.1.19)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "nltk", "parameterized", "psutil", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "timeout-decorator"] +tf = ["keras-nlp (>=0.3.1,<0.14.0)", "onnxconverter-common", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx"] +tf-cpu = ["keras (>2.9,<2.16)", "keras-nlp (>=0.3.1,<0.14.0)", "onnxconverter-common", "tensorflow-cpu (>2.9,<2.16)", "tensorflow-probability (<0.24)", "tensorflow-text (<2.16)", "tf2onnx"] tf-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"] -timm = ["timm"] +timm = ["timm (<=0.9.16)"] tokenizers = ["tokenizers (>=0.19,<0.20)"] torch = ["accelerate (>=0.21.0)", "torch"] torch-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)", "torchaudio"] torch-vision = ["Pillow (>=10.0.1,<=15.0)", "torchvision"] -torchhub = ["filelock", "huggingface-hub (>=0.23.0,<1.0)", "importlib-metadata", "numpy (>=1.17)", "packaging (>=20.0)", "protobuf", "regex (!=2019.12.17)", "requests", "sentencepiece (>=0.1.91,!=0.1.92)", "tokenizers (>=0.19,<0.20)", "torch", "tqdm (>=4.27)"] +torchhub = ["filelock", "huggingface-hub (>=0.23.2,<1.0)", "importlib-metadata", "numpy (>=1.17)", "packaging (>=20.0)", "protobuf", "regex (!=2019.12.17)", "requests", "sentencepiece (>=0.1.91,!=0.1.92)", "tokenizers (>=0.19,<0.20)", "torch", "tqdm (>=4.27)"] video = ["av (==9.2.0)", "decord (==0.6.0)"] vision = ["Pillow (>=10.0.1,<=15.0)"] [[package]] name = "triton" -version = "2.3.1" +version = "3.0.0" description = "A language and compiler for custom Deep Learning operations" optional = true python-versions = "*" files = [ - {file = "triton-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c84595cbe5e546b1b290d2a58b1494df5a2ef066dd890655e5b8a8a92205c33"}, - {file = "triton-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9d64ae33bcb3a7a18081e3a746e8cf87ca8623ca13d2c362413ce7a486f893e"}, - {file = "triton-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaf80e8761a9e3498aa92e7bf83a085b31959c61f5e8ac14eedd018df6fccd10"}, - {file = "triton-2.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b13bf35a2b659af7159bf78e92798dc62d877aa991de723937329e2d382f1991"}, - {file = "triton-2.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63381e35ded3304704ea867ffde3b7cfc42c16a55b3062d41e017ef510433d66"}, - {file = "triton-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d968264523c7a07911c8fb51b4e0d1b920204dae71491b1fe7b01b62a31e124"}, + {file = "triton-3.0.0-1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e1efef76935b2febc365bfadf74bcb65a6f959a9872e5bddf44cc9e0adce1e1a"}, + {file = "triton-3.0.0-1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ce8520437c602fb633f1324cc3871c47bee3b67acf9756c1a66309b60e3216c"}, + {file = "triton-3.0.0-1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:34e509deb77f1c067d8640725ef00c5cbfcb2052a1a3cb6a6d343841f92624eb"}, + {file = "triton-3.0.0-1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bcbf3b1c48af6a28011a5c40a5b3b9b5330530c3827716b5fbf6d7adcc1e53e9"}, + {file = "triton-3.0.0-1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6e5727202f7078c56f91ff13ad0c1abab14a0e7f2c87e91b12b6f64f3e8ae609"}, + {file = "triton-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39b052da883351fdf6be3d93cedae6db3b8e3988d3b09ed221bccecfa9612230"}, + {file = "triton-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd34f19a8582af96e6291d4afce25dac08cb2a5d218c599163761e8e0827208e"}, + {file = "triton-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d5e10de8c011adeb7c878c6ce0dd6073b14367749e34467f1cff2bde1b78253"}, + {file = "triton-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8903767951bf86ec960b4fe4e21bc970055afc65e9d57e916d79ae3c93665e3"}, + {file = "triton-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41004fb1ae9a53fcb3e970745feb87f0e3c94c6ce1ba86e95fa3b8537894bef7"}, ] [package.dependencies] @@ -6140,8 +6244,8 @@ filelock = "*" [package.extras] build = ["cmake (>=3.20)", "lit"] -tests = ["autopep8", "flake8", "isort", "numpy", "pytest", "scipy (>=1.7.1)", "torch"] -tutorials = ["matplotlib", "pandas", "tabulate", "torch"] +tests = ["autopep8", "flake8", "isort", "llnl-hatchet", "numpy", "pytest", "scipy (>=1.7.1)"] +tutorials = ["matplotlib", "pandas", "tabulate"] [[package]] name = "twine" @@ -6225,21 +6329,21 @@ files = [ [[package]] name = "typos" -version = "1.23.3" +version = "1.23.4" description = "Source Code Spelling Correction" optional = false python-versions = ">=3.7" files = [ - {file = "typos-1.23.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:64eb857fd5d9fbceddf84f14dcb102355e95f79e61639c96b76a81f6526fe589"}, - {file = "typos-1.23.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3413933c235362f3a9dc99ea02acfbe096ac451f0828cf8e0617e9ea859add31"}, - {file = "typos-1.23.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5633d7baccc9ee5f3c0a2675c3eed6369983845994d6582f70bb2dd30b55bd64"}, - {file = "typos-1.23.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07cb89e916ed3114ac5980e4df4cca936d4305f13944fa4821afdf319b24b1e2"}, - {file = "typos-1.23.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f3887869fe4a16f203a749b97d32dac763d3b8bf2a71728d20726e8f1aee33e"}, - {file = "typos-1.23.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:eb2bf8c347e82687fa97f5208ded28377fcf4c0cdd685f5323b22cb756bd70d3"}, - {file = "typos-1.23.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4286ca8b7cda18e83e7e8be6aa2b37306b75138a7b0cbf3384f983a5772c0cdb"}, - {file = "typos-1.23.3-py3-none-win32.whl", hash = "sha256:a0bd7a04f476126cb7a2e4d5c11c1083d1d68657e3349817cdb757ce110cf265"}, - {file = "typos-1.23.3-py3-none-win_amd64.whl", hash = "sha256:372139f46e57f18943e2b83d12dc9f4533a93618f0aac8d59684479628e5e576"}, - {file = "typos-1.23.3.tar.gz", hash = "sha256:2bcbfc32660170b2b4797a5613c4ce269fba2eef30d47d0a08ea0be57ddd3b99"}, + {file = "typos-1.23.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c8a9de90a7a1692831505a9265466a45d970147483c4688ba58881d4c24c688b"}, + {file = "typos-1.23.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3b22ca3769101257b38765e8aedf51d36ca51bc603d8dccb0f00cec67024406c"}, + {file = "typos-1.23.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6c977b806c22866061d63260595013bb14b4db3a9272af61d44fffa52299786"}, + {file = "typos-1.23.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:131aaeba2d00eff6d6f1499f4ec92243cb8c28ad8f6482eab32f4f1d67c40a91"}, + {file = "typos-1.23.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebe04c70058eabf0cb60dca9b0af4435e9c0201397df0c96dfb23cea79c102f6"}, + {file = "typos-1.23.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:01325e5a62de1f3564a52f45b204a8dc957468da2f12341a5743c682ea154cf8"}, + {file = "typos-1.23.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0c3482029f239d67c24aa8bd68e1e21e58b3354b97fd726f31551a500bb439da"}, + {file = "typos-1.23.4-py3-none-win32.whl", hash = "sha256:eac7aebf87abe9d4fb5e0a8e753d37746ec9937f2e37ef9bc632352a0b5f2599"}, + {file = "typos-1.23.4-py3-none-win_amd64.whl", hash = "sha256:e0ade81df880583ecd7f7559e7b16e2696489f1369fbe7ae84abaa465fb04688"}, + {file = "typos-1.23.4.tar.gz", hash = "sha256:6acad0feeba0bcfc63727dee84d8fcc409f89916566ee86e55990978b245261a"}, ] [[package]] @@ -6297,6 +6401,17 @@ brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotl secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[[package]] +name = "uuid6" +version = "2024.1.12" +description = "New time-based UUID formats which are suited for use as a database key" +optional = true +python-versions = ">=3.8" +files = [ + {file = "uuid6-2024.1.12-py3-none-any.whl", hash = "sha256:8150093c8d05a331bc0535bc5ef6cf57ac6eceb2404fd319bc10caee2e02c065"}, + {file = "uuid6-2024.1.12.tar.gz", hash = "sha256:ed0afb3a973057575f9883201baefe402787ca5e11e1d24e377190f0c43f1993"}, +] + [[package]] name = "virtualenv" version = "20.26.3" @@ -6686,7 +6801,7 @@ doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linke test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "astrapy", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-cohere = ["cohere"] @@ -6715,6 +6830,7 @@ drivers-sql = ["sqlalchemy"] drivers-sql-amazon-redshift = ["boto3"] drivers-sql-snowflake = ["snowflake-sqlalchemy", "sqlalchemy"] drivers-vector-amazon-opensearch = ["boto3", "opensearch-py"] +drivers-vector-astra-db = ["astrapy"] drivers-vector-marqo = ["marqo"] drivers-vector-mongodb = ["pymongo"] drivers-vector-opensearch = ["opensearch-py"] @@ -6735,4 +6851,4 @@ loaders-sql = ["sqlalchemy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "214d3ce5365f5ce4d852e44019dbbea4659422bdc0231f7cf745a47eeb90ae18" +content-hash = "ded2a15cef0d0cc05582bf36914bf2bc56cd63c6d1d8a0a24b84018e872516f4" diff --git a/pyproject.toml b/pyproject.toml index 98bbe4a03..638204034 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ markdownify = {version = "^0.11.6", optional = true} voyageai = {version = "^0.2.1", optional = true} elevenlabs = {version = "^1.1.2", optional = true} qdrant-client = { version = "^1.10.1", optional = true } +astrapy = { version = "^1.3", optional = true } pusher = {version = "^3.3.2", optional = true} ollama = {version = "^0.2.1", optional = true} duckduckgo-search = {version = "^6.1.12", optional = true} @@ -92,6 +93,7 @@ drivers-vector-opensearch = ["opensearch-py"] drivers-vector-amazon-opensearch = ["opensearch-py", "boto3"] drivers-vector-pgvector = ["sqlalchemy", "pgvector", "psycopg2-binary"] drivers-vector-qdrant = ["qdrant-client"] +drivers-vector-astra-db = ["astrapy"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] @@ -154,6 +156,7 @@ all = [ "marqo", "pinecone-client", "qdrant-client", + "astrapy", "pymongo", "redis", "opensearch-py", From 3b3e4e74836fa03592236b798592fd42ea80963f Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 00:28:52 +0200 Subject: [PATCH 02/21] wip on unit tests with mocker --- .../test_astra_db_vector_store_driver.py | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/unit/drivers/vector/test_astra_db_vector_store_driver.py diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py new file mode 100644 index 000000000..a7720e918 --- /dev/null +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -0,0 +1,39 @@ +from unittest.mock import MagicMock + +import pytest + +from griptape.drivers import AstraDBVectorStoreDriver +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver + + +class TestAstraDBVectorStoreDriver: + @pytest.fixture(autouse=True) + def mock_client(self, mocker): + mock_create_collection = mocker.patch( + "astrapy.DataAPIClient" + ).return_value.get_database.return_value.create_collection + # + mock_insert_one_return_value = MagicMock() + mock_insert_one_return_value.inserted_id = "server_side_id" + mock_create_collection.return_value.insert_one.return_value = mock_insert_one_return_value + # + return mock_create_collection.return_value + + @pytest.fixture() + def driver(self, mock_client): + return AstraDBVectorStoreDriver( + api_endpoint="ep", + token="to", + collection_name="co", + dimension=3, + astra_db_namespace="ns", + embedding_driver=MockEmbeddingDriver(dimensions=3), + ) + + def test_upsert_vector_with_id(self, driver): + upserted_id = driver.upsert_vector([1.0, 2.0, 3.0], vector_id="some_vector_id", namespace="some_namespace") + assert upserted_id == "some_vector_id" + + def test_upsert_vector_no_id(self, driver): + upserted_id = driver.upsert_vector([1.0, 2.0, 3.0], namespace="some_namespace") + assert upserted_id == "server_side_id" From 472c52355935d39794931368eba177ad37c080db Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 00:34:11 +0200 Subject: [PATCH 03/21] slight unit test refactor --- griptape/drivers/__init__.py | 2 ++ .../vector/test_astra_db_vector_store_driver.py | 14 ++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 4a516caf9..79d9a79cb 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -41,6 +41,7 @@ from .vector.azure_mongodb_vector_store_driver import AzureMongoDbVectorStoreDriver from .vector.dummy_vector_store_driver import DummyVectorStoreDriver from .vector.qdrant_vector_store_driver import QdrantVectorStoreDriver +from .vector.astra_db_vector_store_driver import AstraDBVectorStoreDriver from .vector.griptape_cloud_knowledge_base_vector_store_driver import GriptapeCloudKnowledgeBaseVectorStoreDriver from .sql.base_sql_driver import BaseSqlDriver @@ -155,6 +156,7 @@ "AmazonOpenSearchVectorStoreDriver", "PgVectorVectorStoreDriver", "QdrantVectorStoreDriver", + "AstraDBVectorStoreDriver", "DummyVectorStoreDriver", "GriptapeCloudKnowledgeBaseVectorStoreDriver", "BaseSqlDriver", diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py index a7720e918..1fe06fa4b 100644 --- a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -8,19 +8,21 @@ class TestAstraDBVectorStoreDriver: @pytest.fixture(autouse=True) - def mock_client(self, mocker): + def mock_collection(self, mocker): mock_create_collection = mocker.patch( "astrapy.DataAPIClient" ).return_value.get_database.return_value.create_collection - # + return mock_create_collection + + @pytest.fixture() + def autoid_mock_collection(self, mock_collection): mock_insert_one_return_value = MagicMock() mock_insert_one_return_value.inserted_id = "server_side_id" - mock_create_collection.return_value.insert_one.return_value = mock_insert_one_return_value - # - return mock_create_collection.return_value + mock_collection.return_value.insert_one.return_value = mock_insert_one_return_value + return mock_collection @pytest.fixture() - def driver(self, mock_client): + def driver(self, autoid_mock_collection): return AstraDBVectorStoreDriver( api_endpoint="ep", token="to", From bd2bdb5a53fe52c0df5840479f703319cc153146 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 11:26:08 +0200 Subject: [PATCH 04/21] full unit test coverage --- .../vector/astra_db_vector_store_driver.py | 2 +- .../test_astra_db_vector_store_driver.py | 94 +++++++++++++++++-- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index af6a1d708..c9da09629 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -86,7 +86,7 @@ def upsert_vector( def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: find_filter = {k: v for k, v in {"_id": vector_id, "namespace": namespace}.items() if v is not None} - match = self.collection.find_one(find_filter, projection={"*": 1}) + match = self.collection.find_one(filter=find_filter, projection={"*": 1}) if match: return BaseVectorStoreDriver.Entry( id=match["_id"], vector=match.get("$vector"), meta=match.get("meta"), namespace=match.get("namespace") diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py index 1fe06fa4b..3359b73fd 100644 --- a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -2,27 +2,55 @@ import pytest -from griptape.drivers import AstraDBVectorStoreDriver +from griptape.drivers import AstraDBVectorStoreDriver, BaseVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +one_document = { + "_id": "doc_id", + "$vector": [3.0, 2.0, 1.0], + "meta": "doc_meta", + "namespace": "doc_namespace", + "$similarity": 10, +} +one_entry = BaseVectorStoreDriver.Entry( + id=one_document["_id"], + vector=one_document["$vector"], + meta=one_document["meta"], + namespace=one_document["namespace"], +) +one_query_entry = BaseVectorStoreDriver.Entry( + id=one_document["_id"], + vector=one_document["$vector"], + meta=one_document["meta"], + namespace=one_document["namespace"], + score=one_document["$similarity"], +) + class TestAstraDBVectorStoreDriver: @pytest.fixture(autouse=True) - def mock_collection(self, mocker): + def base_mock_collection(self, mocker): mock_create_collection = mocker.patch( "astrapy.DataAPIClient" ).return_value.get_database.return_value.create_collection return mock_create_collection @pytest.fixture() - def autoid_mock_collection(self, mock_collection): + def mock_collection(self, base_mock_collection): + """Augmented with specific response to certain method calls.""" + # insert_one with server-side provided ID mock_insert_one_return_value = MagicMock() - mock_insert_one_return_value.inserted_id = "server_side_id" - mock_collection.return_value.insert_one.return_value = mock_insert_one_return_value - return mock_collection + mock_insert_one_return_value.inserted_id = "insert_one_server_side_id" + base_mock_collection.return_value.insert_one.return_value = mock_insert_one_return_value + # find_one + base_mock_collection.return_value.find_one.return_value = one_document + # find + base_mock_collection.return_value.find.return_value = [one_document] + # + return base_mock_collection @pytest.fixture() - def driver(self, autoid_mock_collection): + def driver(self, mock_collection): return AstraDBVectorStoreDriver( api_endpoint="ep", token="to", @@ -32,10 +60,56 @@ def driver(self, autoid_mock_collection): embedding_driver=MockEmbeddingDriver(dimensions=3), ) - def test_upsert_vector_with_id(self, driver): + def test_delete_vector(self, driver, mock_collection): + driver.delete_vector("deletee_id") + mock_collection.return_value.delete_one.assert_called_once() + + def test_upsert_vector_with_id(self, driver, mock_collection): upserted_id = driver.upsert_vector([1.0, 2.0, 3.0], vector_id="some_vector_id", namespace="some_namespace") assert upserted_id == "some_vector_id" + mock_collection.return_value.find_one_and_replace.assert_called_once() - def test_upsert_vector_no_id(self, driver): + def test_upsert_vector_no_id(self, driver, mock_collection): upserted_id = driver.upsert_vector([1.0, 2.0, 3.0], namespace="some_namespace") - assert upserted_id == "server_side_id" + assert upserted_id == "insert_one_server_side_id" + mock_collection.return_value.insert_one.assert_called_once() + + def test_load_entry(self, driver, mock_collection): + entry = driver.load_entry("vector_id", namespace="some_namespace") + assert entry == one_entry + mock_collection.return_value.find_one.assert_called_once_with( + filter={"_id": "vector_id", "namespace": "some_namespace"}, + projection={"*": 1}, + ) + + def test_load_entries(self, driver, mock_collection): + entries = driver.load_entries(namespace="some_namespace") + assert entries == [one_entry] + mock_collection.return_value.find.assert_called_once_with( + filter={"namespace": "some_namespace"}, + projection={"*": 1}, + ) + + def test_query_allparams(self, driver, mock_collection): + entries1 = driver.query("some query", count=999, namespace="some_namespace", include_vectors=True) + assert entries1 == [one_query_entry] + query_vector = driver.embedding_driver.embed_string("some query") + mock_collection.return_value.find.assert_called_once_with( + filter={"namespace": "some_namespace"}, + sort={"$vector": query_vector}, + limit=999, + projection={"*": 1}, + include_similarity=True, + ) + + def test_query_minparams(self, driver, mock_collection): + entries0 = driver.query("some query") + assert entries0 == [one_query_entry] + query_vector = driver.embedding_driver.embed_string("some query") + mock_collection.return_value.find.assert_called_once_with( + filter={}, + sort={"$vector": query_vector}, + limit=None, + projection=None, + include_similarity=True, + ) From 26c5bb8ef1a54e9a52da4bc3c56d948c7fb98503 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 11:50:59 +0200 Subject: [PATCH 05/21] docstrings; added a find-nothing test --- .../vector/astra_db_vector_store_driver.py | 69 ++++++++++++++++++- .../test_astra_db_vector_store_driver.py | 15 ++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index c9da09629..364d494ee 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -30,7 +30,14 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): """A Vector Store Driver for Astra DB. - DOCSTRING TO DO + Attributes: + embedding_driver: a `griptape.drivers.BaseEmbeddingDriver` for embedding computations within the store + api_endpoint: the "API Endpoint" for the Astra DB instance. + token: a Database Token ("AstraCS:...") secret to access Astra DB. + collection_name: the name of the collection on Astra DB. + dimension: the number of components for embedding vectors. + astra_db_namespace: optional specification of the namespace (in the Astra database) for the data. + *Note*: not to be confused with the "namespace" mentioned elsewhere, which is a grouping within this vector store. """ api_endpoint: str = field(kw_only=True, metadata={"serializable": True}) @@ -62,6 +69,14 @@ def __attrs_post_init__(self) -> None: ) def delete_vector(self, vector_id: str) -> None: + """Delete a vector from Astra DB store. + + The method succeeds regardless of whether a vector with the provided ID + was actually stored or not in the first place. + + Args: + vector_id: ID of the vector to delete. + """ self.collection.delete_one({"_id": vector_id}) def upsert_vector( @@ -72,6 +87,26 @@ def upsert_vector( meta: Optional[dict] = None, **kwargs, ) -> str: + """Write a vector to the Astra DB store. + + In case the provided ID exists already, an overwrite will take place. + + Args: + vector: the vector to be upserted. + vector_id: the ID for the vector to store. If omitted, a server-provided new ID will be employed. + namespace: a namespace (a grouping within the vector store) to assign the vector to. + meta: a metadata dictionary associated to the vector. + kwargs: additional keyword arguments. Currently none is used: if they are passed, they will be ignored with a warning. + + Returns: + the ID of the written vector (str). + """ + if kwargs: + warnings.warn( + "Unhandled keyword argument(s) provided to AstraDBVectorStore.upsert_vector: " + f"'{','.join(sorted(kwargs.keys()))}'. These will be ignored.", + stacklevel=2, + ) document = { k: v for k, v in {"$vector": vector, "_id": vector_id, "namespace": namespace, "meta": meta}.items() @@ -85,6 +120,15 @@ def upsert_vector( return insert_result.inserted_id def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + """Load a single vector entry from the Astra DB store given its ID. + + Args: + vector_id: the ID of the required vector. + namespace: a namespace, within the vector store, to constrain the search. + + Returns: + The vector entry (a `BaseVectorStoreDriver.Entry`) if found, otherwise None. + """ find_filter = {k: v for k, v in {"_id": vector_id, "namespace": namespace}.items() if v is not None} match = self.collection.find_one(filter=find_filter, projection={"*": 1}) if match: @@ -95,6 +139,14 @@ def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Opti return None def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + """Load entries from the Astra DB store. + + Args: + namespace: a namespace, within the vector store, to constrain the search. + + Returns: + A list of vector (`BaseVectorStoreDriver.Entry`) entries. + """ find_filter: dict[str, str] = {} if namespace is None else {"namespace": namespace} return [ BaseVectorStoreDriver.Entry( @@ -112,6 +164,21 @@ def query( include_vectors: bool = False, **kwargs: Any, ) -> list[BaseVectorStoreDriver.Entry]: + """Run a similarity search on the Astra DB store, based on a query string. + + Args: + query: the query string. + count: the maximum number of results to return. If omitted, server defaults will apply. + namespace: the namespace to filter results by. + include_vectors: whether to include vector data in the results. + kwargs: additional keyword arguments. Currently only the free-form dict `filter` + is recognized (and goes straight to the Data API query); + others will generate a warning and be ignored. + + Returns: + A list of vector (`BaseVectorStoreDriver.Entry`) entries, + with their `score` attribute set to the vector similarity to the query. + """ query_filter: Optional[dict[str, Any]] = kwargs.pop("filter", None) if kwargs: warnings.warn( diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py index 3359b73fd..7e258623d 100644 --- a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -49,6 +49,13 @@ def mock_collection(self, base_mock_collection): # return base_mock_collection + @pytest.fixture() + def mock_collection_findnothing(self, base_mock_collection): + """`find` and `find_one` return nothing.""" + base_mock_collection.return_value.find_one.return_value = None + base_mock_collection.return_value.find.return_value = [] + return base_mock_collection + @pytest.fixture() def driver(self, mock_collection): return AstraDBVectorStoreDriver( @@ -82,6 +89,14 @@ def test_load_entry(self, driver, mock_collection): projection={"*": 1}, ) + def test_load_entry_empty(self, driver, mock_collection_findnothing): + entry = driver.load_entry("vector_id", namespace="some_namespace") + assert entry is None + mock_collection_findnothing.return_value.find_one.assert_called_once_with( + filter={"_id": "vector_id", "namespace": "some_namespace"}, + projection={"*": 1}, + ) + def test_load_entries(self, driver, mock_collection): entries = driver.load_entries(namespace="some_namespace") assert entries == [one_entry] From 3586465f9526359ce345bdd88240c8e6cafb031e Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 14:40:43 +0200 Subject: [PATCH 06/21] docs about the Astra vector store + standalone example; changelog --- CHANGELOG.md | 1 + docs/examples/query-webpage-astra-db.md | 59 +++++++++++++++++++ .../drivers/vector-store-drivers.md | 44 ++++++++++++++ mkdocs.yml | 1 + 4 files changed, 105 insertions(+) create mode 100644 docs/examples/query-webpage-astra-db.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a06a20d5..ceb9e2642 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `@observable` decorator for selecting which functions/methods to provide observability for. - `GenericArtifact` for storing any data. - `BaseTextArtifact` for text-based Artifacts to subclass. +- `AstraDBVectorStoreDriver` to support DataStax Astra DB as a vector store. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifacts` optional arguments are now keyword-only arguments. diff --git a/docs/examples/query-webpage-astra-db.md b/docs/examples/query-webpage-astra-db.md new file mode 100644 index 000000000..4b57f6dd8 --- /dev/null +++ b/docs/examples/query-webpage-astra-db.md @@ -0,0 +1,59 @@ +Required Griptape extras: + +``` +pip install griptape[drivers-vector-astra-db,drivers-web-scraper-trafilatura] +``` + +Python script: + +```python +import os + +from griptape.drivers import AstraDBVectorStoreDriver, OpenAiChatPromptDriver, OpenAiEmbeddingDriver +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import PromptResponseRagModule, VectorStoreRetrievalRagModule +from griptape.engines.rag.stages import ResponseRagStage, RetrievalRagStage +from griptape.loaders import WebLoader +from griptape.structures import Agent +from griptape.tools import RagClient, TaskMemoryClient + +if __name__ == "__main__": + namespace = "datastax_blog" + input_blogpost = "www.datastax.com/blog/indexing-all-of-wikipedia-on-a-laptop" + + vector_store_driver = AstraDBVectorStoreDriver( + embedding_driver=OpenAiEmbeddingDriver(), + api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], + token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], + collection_name="griptape_test_collection", + astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + dimension=1536, + ) + + engine = RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, + query_params={ + "count": 2, + "namespace": namespace, + }, + ) + ] + ), + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") + ) + ) + ) + + vector_store_driver.upsert_text_artifacts( + {namespace: WebLoader(max_tokens=256).load(input_blogpost)} + ) + + vector_store_tool = RagClient(description="A DataStax blog post", rag_engine=engine) + agent = Agent(tools=[vector_store_tool, TaskMemoryClient(off_prompt=False)]) + agent.run(f"What engine made possible to index such an amount of data, and what kind of tuning was required?") +``` diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 2b76119b3..4546c5936 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -482,3 +482,47 @@ values = [r.to_artifact().value for r in results] print("\n\n".join(values)) ``` + +### Astra DB + +!!! info + This Driver requires the `drivers-vector-astra-db` [extra](../index.md#extras). + +The AstraDBVectorStoreDriver supports [DataStax Astra DB](https://www.datastax.com/products/datastax-astra). + +The following example shows how to store vector entries and query the information using the driver: + +```python +import os +from griptape.drivers import AstraDBVectorStoreDriver, OpenAiEmbeddingDriver +from griptape.loaders import WebLoader + +# Astra DB secrets and connection parameters +api_endpoint = os.environ["ASTRA_DB_API_ENDPOINT"] +token = os.environ["ASTRA_DB_APPLICATION_TOKEN"] +astra_db_namespace = os.environ.get("ASTRA_DB_KEYSPACE") # optional + +# Initialize an Embedding Driver. +embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) + +vector_store_driver = AstraDBVectorStoreDriver( + embedding_driver=embedding_driver, + api_endpoint=api_endpoint, + token=token, + collection_name="astra_db_demo", + astra_db_namespace=astra_db_namespace, + dimension=1536, +) + +# Load Artifacts from the web +artifacts = WebLoader().load("https://www.griptape.ai") + +# Upsert Artifacts into the Vector Store Driver +[vector_store_driver.upsert_text_artifact(a, namespace="griptape") for a in artifacts] + +results = vector_store_driver.query(query="What is griptape?") + +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) +``` diff --git a/mkdocs.yml b/mkdocs.yml index 911301f4e..6c9bffa13 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -170,5 +170,6 @@ nav: - Load and Query Pinecone: "examples/load-and-query-pinecone.md" - Load and Query Marqo: "examples/load-query-and-chat-marqo.md" - Query a Webpage: "examples/query-webpage.md" + - RAG with Astra DB vector store: "examples/query-webpage-astra-db.md" - Reference Guide: "reference/" - Trade School: "https://learn.griptape.ai" From 21ed76b6ad0b72eb558ce7d9f7f77377413e5f8d Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 14:55:04 +0200 Subject: [PATCH 07/21] minor formatting in code and docs --- docs/examples/query-webpage-astra-db.md | 25 +++++++++++++++---- .../drivers/vector-store-drivers.md | 5 +++- .../vector/astra_db_vector_store_driver.py | 2 +- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/docs/examples/query-webpage-astra-db.md b/docs/examples/query-webpage-astra-db.md index 4b57f6dd8..a5898ac10 100644 --- a/docs/examples/query-webpage-astra-db.md +++ b/docs/examples/query-webpage-astra-db.md @@ -9,9 +9,16 @@ Python script: ```python import os -from griptape.drivers import AstraDBVectorStoreDriver, OpenAiChatPromptDriver, OpenAiEmbeddingDriver +from griptape.drivers import ( + AstraDBVectorStoreDriver, + OpenAiChatPromptDriver, + OpenAiEmbeddingDriver, +) from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import PromptResponseRagModule, VectorStoreRetrievalRagModule +from griptape.engines.rag.modules import ( + PromptResponseRagModule, + VectorStoreRetrievalRagModule, +) from griptape.engines.rag.stages import ResponseRagStage, RetrievalRagStage from griptape.loaders import WebLoader from griptape.structures import Agent @@ -19,7 +26,9 @@ from griptape.tools import RagClient, TaskMemoryClient if __name__ == "__main__": namespace = "datastax_blog" - input_blogpost = "www.datastax.com/blog/indexing-all-of-wikipedia-on-a-laptop" + input_blogpost = ( + "www.datastax.com/blog/indexing-all-of-wikipedia-on-a-laptop" + ) vector_store_driver = AstraDBVectorStoreDriver( embedding_driver=OpenAiEmbeddingDriver(), @@ -53,7 +62,13 @@ if __name__ == "__main__": {namespace: WebLoader(max_tokens=256).load(input_blogpost)} ) - vector_store_tool = RagClient(description="A DataStax blog post", rag_engine=engine) + vector_store_tool = RagClient( + description="A DataStax blog post", + rag_engine=engine, + ) agent = Agent(tools=[vector_store_tool, TaskMemoryClient(off_prompt=False)]) - agent.run(f"What engine made possible to index such an amount of data, and what kind of tuning was required?") + agent.run( + "What engine made possible to index such an amount of data, " + "and what kind of tuning was required?" + ) ``` diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 4546c5936..9e05ff6eb 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -518,7 +518,10 @@ vector_store_driver = AstraDBVectorStoreDriver( artifacts = WebLoader().load("https://www.griptape.ai") # Upsert Artifacts into the Vector Store Driver -[vector_store_driver.upsert_text_artifact(a, namespace="griptape") for a in artifacts] +[ + vector_store_driver.upsert_text_artifact(a, namespace="griptape") + for a in artifacts +] results = vector_store_driver.query(query="What is griptape?") diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index 364d494ee..dddefcc5f 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -85,7 +85,7 @@ def upsert_vector( vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, - **kwargs, + **kwargs: Any, ) -> str: """Write a vector to the Astra DB store. From 0d49f83ad3f4998ab248002b40f19d4a113202f1 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 15:06:43 +0200 Subject: [PATCH 08/21] 'dimension' parameter optional --- docs/examples/query-webpage-astra-db.md | 1 - .../drivers/vector-store-drivers.md | 1 - .../drivers/vector/astra_db_vector_store_driver.py | 7 +++++-- .../vector/test_astra_db_vector_store_driver.py | 11 ++++++++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/examples/query-webpage-astra-db.md b/docs/examples/query-webpage-astra-db.md index a5898ac10..b89c459d2 100644 --- a/docs/examples/query-webpage-astra-db.md +++ b/docs/examples/query-webpage-astra-db.md @@ -36,7 +36,6 @@ if __name__ == "__main__": token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], collection_name="griptape_test_collection", astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), - dimension=1536, ) engine = RagEngine( diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 9e05ff6eb..b296e60b2 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -511,7 +511,6 @@ vector_store_driver = AstraDBVectorStoreDriver( token=token, collection_name="astra_db_demo", astra_db_namespace=astra_db_namespace, - dimension=1536, ) # Load Artifacts from the web diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index dddefcc5f..fabc3d2bd 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -35,7 +35,7 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): api_endpoint: the "API Endpoint" for the Astra DB instance. token: a Database Token ("AstraCS:...") secret to access Astra DB. collection_name: the name of the collection on Astra DB. - dimension: the number of components for embedding vectors. + dimension: the number of components for embedding vectors. If not provided, it will be guessed from the embedding driver. astra_db_namespace: optional specification of the namespace (in the Astra database) for the data. *Note*: not to be confused with the "namespace" mentioned elsewhere, which is a grouping within this vector store. """ @@ -43,13 +43,16 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): api_endpoint: str = field(kw_only=True, metadata={"serializable": True}) token: str = field(kw_only=True, metadata={"serializable": False}) collection_name: str = field(kw_only=True, metadata={"serializable": False}) - dimension: int = field(kw_only=True, metadata={"serializable": True}) + dimension: Optional[int] = field(kw_only=True, default=None, metadata={"serializable": True}) astra_db_namespace: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) collection: Collection = field(init=False) def __attrs_post_init__(self) -> None: astrapy = import_optional_dependency("astrapy") + if not self.dimension: + # auto-compute dimension from the embedding + self.dimension = len(self.embedding_driver.embed_string("This is a sample text.")) self.collection = ( astrapy.DataAPIClient( token=self.token, diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py index 7e258623d..d6e25e18c 100644 --- a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -62,11 +62,20 @@ def driver(self, mock_collection): api_endpoint="ep", token="to", collection_name="co", - dimension=3, astra_db_namespace="ns", embedding_driver=MockEmbeddingDriver(dimensions=3), ) + def test_explicit_dimension(self, mock_collection): + AstraDBVectorStoreDriver( + api_endpoint="ep", + token="to", + collection_name="co", + astra_db_namespace="ns", + dimension=123, + embedding_driver=MockEmbeddingDriver(), + ) + def test_delete_vector(self, driver, mock_collection): driver.delete_vector("deletee_id") mock_collection.return_value.delete_one.assert_called_once() From 6609eb0df05573e231b8dab51fc3616c19e552ce Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 17:24:13 +0200 Subject: [PATCH 09/21] Astra DB vector store driver, integration testing --- .../vector/astra_db_vector_store_driver.py | 1 + .../test_astra_db_vector_store_driver.py | 188 ++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 tests/integration/drivers/vector/test_astra_db_vector_store_driver.py diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index fabc3d2bd..fa24f1b25 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -85,6 +85,7 @@ def delete_vector(self, vector_id: str) -> None: def upsert_vector( self, vector: list[float], + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, diff --git a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py new file mode 100644 index 000000000..6c625697e --- /dev/null +++ b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py @@ -0,0 +1,188 @@ +from __future__ import annotations + +import json +import math +import os + +import pytest +from attrs import define, field + +from griptape.drivers import AstraDBVectorStoreDriver, BaseEmbeddingDriver, BaseVectorStoreDriver +from tests.mocks.mock_tokenizer import MockTokenizer + +TEST_COLLECTION_NAME = "gt_int_test" + + +def astrapy_available() -> bool: + try: + return True + except Exception: + return False + + +def astra_db_available() -> bool: + return all( + [ + "ASTRA_DB_APPLICATION_TOKEN" in os.environ, + "ASTRA_DB_API_ENDPOINT" in os.environ, + ] + ) + + +def _descore_entry(entry: BaseVectorStoreDriver.Entry) -> BaseVectorStoreDriver.Entry: + return BaseVectorStoreDriver.Entry.from_dict({k: v for k, v in entry.__dict__.items() if k != "score"}) + + +@define +class ParserEmbeddingDriver(BaseEmbeddingDriver): + model: str = field(default="foo", kw_only=True) + dimensions: int = field(default=2, kw_only=True) + max_attempts: int = field(default=1, kw_only=True) + tokenizer: MockTokenizer = field(factory=lambda: MockTokenizer(model="foo bar"), kw_only=True) + + def try_embed_chunk(self, chunk: str) -> list[float]: + vector2d: list[float] + try: + fraction = float(json.loads(chunk)) + angle = fraction * math.pi * 2 + vector2d = [math.cos(angle), math.sin(angle)] + except Exception: + vector2d = [0.0, 0.0] + return (vector2d + [0] * (self.dimensions))[: self.dimensions] + + +@pytest.mark.skipif(not astrapy_available(), reason="Package astrapy not installed") +@pytest.mark.skipif(not astra_db_available(), reason="No connection info for Astra DB") +class TestAstraDBVectorStoreDriver: + @pytest.fixture() + def embedding_driver(self): + return ParserEmbeddingDriver() + + @pytest.fixture() + def vector_store_driver(self, embedding_driver): + driver = AstraDBVectorStoreDriver( + api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], + token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], + collection_name=TEST_COLLECTION_NAME, + astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + embedding_driver=embedding_driver, + ) + return driver + driver.collection.drop() + + @pytest.fixture() + def vector_store_collection(self, vector_store_driver): + """For testing purposes, access the bare AstraPy "Collection".""" + return vector_store_driver.collection + + def test_vector_crud(self, vector_store_driver, vector_store_collection, embedding_driver): + """Test basic vector CRUD, various call patterns.""" + vector_store_collection.delete_many({}) + + vec1 = embedding_driver.embed_string("0.012") + id1 = vector_store_driver.upsert_vector(vec1, vector_id="v1") + + vec2 = embedding_driver.embed_string("0.024") + id2 = vector_store_driver.upsert_vector(vec2, vector_id="v2", namespace="ns") + + vec3 = embedding_driver.embed_string("0.036") + id3 = vector_store_driver.upsert_vector(vec3) + + vec4 = embedding_driver.embed_string("0.048") + id4 = vector_store_driver.upsert_vector(vec4, vector_id="v4", meta={"i": 4}, namespace="ns") + + assert id1 == "v1" + assert id2 == "v2" + assert isinstance(id3, str) + assert id4 == "v4" + + # retrieve by id + e1 = vector_store_driver.load_entry(id1) + e1_n = vector_store_driver.load_entry(id1, namespace="false_ns") + e2 = vector_store_driver.load_entry(id2, namespace="ns") + e3 = vector_store_driver.load_entry(id3) + e4 = vector_store_driver.load_entry(id4) + assert e1 == BaseVectorStoreDriver.Entry( + id=id1, + vector=vec1, + ) + assert e1_n is None + assert e2 == BaseVectorStoreDriver.Entry( + id=id2, + vector=vec2, + namespace="ns", + ) + assert e3 == BaseVectorStoreDriver.Entry( + id=id3, + vector=vec3, + ) + assert e4 == BaseVectorStoreDriver.Entry( + id=id4, + vector=vec4, + meta={"i": 4}, + namespace="ns", + ) + + # retrieve multiple entries + es_ns = vector_store_driver.load_entries(namespace="ns") + es_all = vector_store_driver.load_entries() + assert len(es_ns) == 2 + assert any(e == e2 for e in es_ns) + assert any(e == e4 for e in es_ns) + assert len(es_all) == 4 + assert any(e == e1 for e in es_all) + assert any(e == e2 for e in es_all) + assert any(e == e3 for e in es_all) + assert any(e == e4 for e in es_all) + + # delete and recheck + vector_store_driver.delete_vector("fake_id") + vector_store_driver.delete_vector(id4) + es_ns_postdel = vector_store_driver.load_entries(namespace="ns") + assert len(es_ns_postdel) == 1 + assert es_ns_postdel[0] == e2 + + # queries + query_2 = vector_store_driver.query("0.060", count=2, include_vectors=True) + query_all = vector_store_driver.query("0.060", include_vectors=True) + query_2_novectors = vector_store_driver.query("0.060", count=2) + query_all_ns = vector_store_driver.query("0.060", include_vectors=True, namespace="ns") + # + d_query_2 = [_descore_entry(ent) for ent in query_2] + assert d_query_2 == [e3, e2] + + d_query_all = [_descore_entry(ent) for ent in query_all] + assert d_query_all == [e3, e2, e1] + d_query_2_novectors = [_descore_entry(ent) for ent in query_2_novectors] + assert d_query_2_novectors == [ + BaseVectorStoreDriver.Entry( + id=id3, + ), + BaseVectorStoreDriver.Entry( + id=id2, + namespace="ns", + ), + ] + d_query_all_ns = [_descore_entry(ent) for ent in query_all_ns] + assert d_query_all_ns == [e2] + + def test_explicit_dimension(self, vector_store_driver, embedding_driver): + AstraDBVectorStoreDriver( + api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], + token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], + collection_name=TEST_COLLECTION_NAME, + astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + dimension=2, + embedding_driver=embedding_driver, + ) + import astrapy + + with pytest.raises(astrapy.exceptions.DataAPIException): + AstraDBVectorStoreDriver( + api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], + token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], + collection_name=TEST_COLLECTION_NAME, + astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + dimension=123, + embedding_driver=embedding_driver, + ) From 384a1456c2f45ac74dee742616d5ee63918fc5ba Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 23:04:09 +0200 Subject: [PATCH 10/21] default count for query is the base class default --- griptape/drivers/vector/astra_db_vector_store_driver.py | 5 +++-- .../unit/drivers/vector/test_astra_db_vector_store_driver.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index fa24f1b25..4b8ddfcff 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -172,7 +172,7 @@ def query( Args: query: the query string. - count: the maximum number of results to return. If omitted, server defaults will apply. + count: the maximum number of results to return. If omitted, defaults will apply. namespace: the namespace to filter results by. include_vectors: whether to include vector data in the results. kwargs: additional keyword arguments. Currently only the free-form dict `filter` @@ -194,10 +194,11 @@ def query( find_filter = {**(query_filter or {}), **find_filter_ns} find_projection: Optional[dict[str, int]] = {"*": 1} if include_vectors else None vector = self.embedding_driver.embed_string(query) + ann_limit = count or BaseVectorStoreDriver.DEFAULT_QUERY_COUNT matches = self.collection.find( filter=find_filter, sort={"$vector": vector}, - limit=count, + limit=ann_limit, projection=find_projection, include_similarity=True, ) diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py index d6e25e18c..5c794cc9b 100644 --- a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -133,7 +133,7 @@ def test_query_minparams(self, driver, mock_collection): mock_collection.return_value.find.assert_called_once_with( filter={}, sort={"$vector": query_vector}, - limit=None, + limit=BaseVectorStoreDriver.DEFAULT_QUERY_COUNT, projection=None, include_similarity=True, ) From 4d093b7461bc6c8d98bf20830c8be0db177bf268 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 23:24:55 +0200 Subject: [PATCH 11/21] optionally specify metric in Astra DB vector store --- .../vector/astra_db_vector_store_driver.py | 5 +++ .../test_astra_db_vector_store_driver.py | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index 4b8ddfcff..6b1af4036 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -36,6 +36,9 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): token: a Database Token ("AstraCS:...") secret to access Astra DB. collection_name: the name of the collection on Astra DB. dimension: the number of components for embedding vectors. If not provided, it will be guessed from the embedding driver. + metric: the similarity metric to use, one of "dot_product", "euclidean" or "cosine". + If omitted, the server default ("cosine") will be used. See also values of `astrapy.constants.VectorMetric`. + If the vectors are normalized to unit norm, choosing "dot_product" over cosine yields up to 2x speedup in searches. astra_db_namespace: optional specification of the namespace (in the Astra database) for the data. *Note*: not to be confused with the "namespace" mentioned elsewhere, which is a grouping within this vector store. """ @@ -44,6 +47,7 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): token: str = field(kw_only=True, metadata={"serializable": False}) collection_name: str = field(kw_only=True, metadata={"serializable": False}) dimension: Optional[int] = field(kw_only=True, default=None, metadata={"serializable": True}) + metric: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) astra_db_namespace: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) collection: Collection = field(init=False) @@ -66,6 +70,7 @@ def __attrs_post_init__(self) -> None: .create_collection( name=self.collection_name, dimension=self.dimension, + metric=self.metric, indexing=COLLECTION_INDEXING, check_exists=False, ) diff --git a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py index 6c625697e..c758d9024 100644 --- a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py @@ -11,6 +11,7 @@ from tests.mocks.mock_tokenizer import MockTokenizer TEST_COLLECTION_NAME = "gt_int_test" +TEST_COLLECTION_NAME_METRIC = "gt_int_test_dot" def astrapy_available() -> bool: @@ -186,3 +187,42 @@ def test_explicit_dimension(self, vector_store_driver, embedding_driver): dimension=123, embedding_driver=embedding_driver, ) + + def test_explicit_metric(self, embedding_driver): + import astrapy + + with pytest.raises(astrapy.exceptions.DataAPIResponseException): + AstraDBVectorStoreDriver( + api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], + token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], + collection_name=TEST_COLLECTION_NAME_METRIC, + astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + dimension=123, + metric="p-adic-norm", + embedding_driver=embedding_driver, + ) + + # seriously ... + dot_vector_store_driver = AstraDBVectorStoreDriver( + api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], + token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], + collection_name=TEST_COLLECTION_NAME_METRIC, + astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + dimension=2, + metric="dot_product", + embedding_driver=embedding_driver, + ) + try: + # some vectors are off-sphere, to probe dot product as metric + short_v = [0.1, 0.0] + pi_4_v = embedding_driver.embed_string("0.125") + tenx_pi_4_v = [10 * comp for comp in pi_4_v] + dot_vector_store_driver.upsert_vector(short_v, vector_id="short_v") + dot_vector_store_driver.upsert_vector(pi_4_v, vector_id="pi_4_v") + dot_vector_store_driver.upsert_vector(tenx_pi_4_v, vector_id="tenx_pi_4_v") + entries = dot_vector_store_driver.query("0.0", count=2) + assert len(entries) == 2 + assert entries[0].id == "tenx_pi_4_v" + assert entries[1].id == "pi_4_v" + finally: + dot_vector_store_driver.collection.drop() From 679769f779f8972195b28fe6fd74aca6729f37ca Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Fri, 26 Jul 2024 23:39:55 +0200 Subject: [PATCH 12/21] support for HCD and other non-Astra databases --- .../drivers/vector/astra_db_vector_store_driver.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index 6b1af4036..d8c70c0a1 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -11,6 +11,7 @@ if TYPE_CHECKING: from astrapy import Collection + from astrapy.authentication import TokenProvider GRIPTAPE_VERSION: Optional[str] try: @@ -33,8 +34,10 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): Attributes: embedding_driver: a `griptape.drivers.BaseEmbeddingDriver` for embedding computations within the store api_endpoint: the "API Endpoint" for the Astra DB instance. - token: a Database Token ("AstraCS:...") secret to access Astra DB. + token: a Database Token ("AstraCS:...") secret to access Astra DB. An instance of `astrapy.authentication.TokenProvider` is also accepted. collection_name: the name of the collection on Astra DB. + environment: the environment ("prod", "hcd", ...) hosting the target Data API. + It can be omitted for production Astra DB targets. See `astrapy.constants.Environment` for allowed values. dimension: the number of components for embedding vectors. If not provided, it will be guessed from the embedding driver. metric: the similarity metric to use, one of "dot_product", "euclidean" or "cosine". If omitted, the server default ("cosine") will be used. See also values of `astrapy.constants.VectorMetric`. @@ -44,8 +47,9 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): """ api_endpoint: str = field(kw_only=True, metadata={"serializable": True}) - token: str = field(kw_only=True, metadata={"serializable": False}) - collection_name: str = field(kw_only=True, metadata={"serializable": False}) + token: Optional[str | TokenProvider] = field(kw_only=True, default=None, metadata={"serializable": False}) + collection_name: str = field(kw_only=True, metadata={"serializable": True}) + environment: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) dimension: Optional[int] = field(kw_only=True, default=None, metadata={"serializable": True}) metric: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) astra_db_namespace: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) @@ -59,12 +63,13 @@ def __attrs_post_init__(self) -> None: self.dimension = len(self.embedding_driver.embed_string("This is a sample text.")) self.collection = ( astrapy.DataAPIClient( - token=self.token, caller_name="griptape", caller_version=GRIPTAPE_VERSION, + environment=self.environment, ) .get_database( self.api_endpoint, + token=self.token, namespace=self.astra_db_namespace, ) .create_collection( From d42c6a8b805a85d6241b500a490460bacb004263 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Sun, 28 Jul 2024 17:43:58 +0200 Subject: [PATCH 13/21] Add test coverage for the unkown-kwargs warnings --- .../test_astra_db_vector_store_driver.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py index 5c794cc9b..207e894b2 100644 --- a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -85,6 +85,14 @@ def test_upsert_vector_with_id(self, driver, mock_collection): assert upserted_id == "some_vector_id" mock_collection.return_value.find_one_and_replace.assert_called_once() + def test_upsert_vector_kwargs_warning(self, driver, mock_collection): + with pytest.warns(UserWarning): + upserted_id = driver.upsert_vector( + [1.0, 2.0, 3.0], vector_id="some_vector_id", namespace="some_namespace", kittens=123, marzipan="yes" + ) + assert upserted_id == "some_vector_id" + mock_collection.return_value.find_one_and_replace.assert_called_once() + def test_upsert_vector_no_id(self, driver, mock_collection): upserted_id = driver.upsert_vector([1.0, 2.0, 3.0], namespace="some_namespace") assert upserted_id == "insert_one_server_side_id" @@ -137,3 +145,16 @@ def test_query_minparams(self, driver, mock_collection): projection=None, include_similarity=True, ) + + def test_query_kwargs_warning(self, driver, mock_collection): + with pytest.warns(UserWarning): + entries0 = driver.query("some query", sector=987, voltage="12 V") + assert entries0 == [one_query_entry] + query_vector = driver.embedding_driver.embed_string("some query") + mock_collection.return_value.find.assert_called_once_with( + filter={}, + sort={"$vector": query_vector}, + limit=BaseVectorStoreDriver.DEFAULT_QUERY_COUNT, + projection=None, + include_similarity=True, + ) From dec82a917775ee313f3f9f519225376965c7001d Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Tue, 30 Jul 2024 15:15:34 +0200 Subject: [PATCH 14/21] Address most of the comments to the PR - simplify the 'query webpage Astra' markdown page - add env.vars to the CI action yaml - remove Griptape version detection - remove mistakenly-added logging level setting - moved the "indexing" value to a class attribute - reinstated `dimensions` as a required parameter - removed kwargs warnings from methods (and implications thereof) - replaced implicit-bool checks with "is None" checks in a few places - (testing) move sample docs and Entries to being pytest fixtures - (testing) move utility function `_descore_entry` into a class method --- .github/workflows/docs-integration-tests.yml | 3 + docs/examples/query-webpage-astra-db.md | 91 ++++++++++--------- .../vector/astra_db_vector_store_driver.py | 42 ++------- .../test_astra_db_vector_store_driver.py | 28 ++---- .../test_astra_db_vector_store_driver.py | 90 +++++++----------- 5 files changed, 101 insertions(+), 153 deletions(-) diff --git a/.github/workflows/docs-integration-tests.yml b/.github/workflows/docs-integration-tests.yml index ce30f83bb..318142eec 100644 --- a/.github/workflows/docs-integration-tests.yml +++ b/.github/workflows/docs-integration-tests.yml @@ -124,6 +124,9 @@ jobs: ZENROWS_API_KEY: ${{ secrets.INTEG_ZENROWS_API_KEY }} QDRANT_CLUSTER_ENDPOINT: ${{ secrets.INTEG_QDRANT_CLUSTER_ENDPOINT }} QDRANT_CLUSTER_API_KEY: ${{ secrets.INTEG_QDRANT_CLUSTER_API_KEY }} + ASTRA_DB_API_ENDPOINT: ${{ secrets.ASTRA_DB_API_ENDPOINT }} + ASTRA_DB_APPLICATION_TOKEN: ${{ secrets.ASTRA_DB_APPLICATION_TOKEN }} + ASTRA_DB_KEYSPACE: ${{ secrets.ASTRA_DB_KEYSPACE }} services: postgres: image: ankane/pgvector:v0.5.0 diff --git a/docs/examples/query-webpage-astra-db.md b/docs/examples/query-webpage-astra-db.md index b89c459d2..2152879f5 100644 --- a/docs/examples/query-webpage-astra-db.md +++ b/docs/examples/query-webpage-astra-db.md @@ -1,10 +1,12 @@ -Required Griptape extras: +The following example script ingests a Web page (a blog post), +stores its chunked contents on Astra DB through the Astra DB vector store driver, +and finally runs a RAG process to answer a question specific to the topic of the +Web page. -``` -pip install griptape[drivers-vector-astra-db,drivers-web-scraper-trafilatura] -``` +_Note:_ Besides the [Astra DB](../griptape-framework/drivers/vector-store-drivers.md#astra-db) extra, +this example requires the `drivers-web-scraper-trafilatura` +Griptape extra to be installed as well. -Python script: ```python import os @@ -24,50 +26,51 @@ from griptape.loaders import WebLoader from griptape.structures import Agent from griptape.tools import RagClient, TaskMemoryClient -if __name__ == "__main__": - namespace = "datastax_blog" - input_blogpost = ( - "www.datastax.com/blog/indexing-all-of-wikipedia-on-a-laptop" - ) - vector_store_driver = AstraDBVectorStoreDriver( - embedding_driver=OpenAiEmbeddingDriver(), - api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], - token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], - collection_name="griptape_test_collection", - astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), - ) +namespace = "datastax_blog" +input_blogpost = ( + "www.datastax.com/blog/indexing-all-of-wikipedia-on-a-laptop" +) + +vector_store_driver = AstraDBVectorStoreDriver( + embedding_driver=OpenAiEmbeddingDriver(), + api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], + token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], + collection_name="griptape_test_collection", + astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + dimension=1536, +) - engine = RagEngine( - retrieval_stage=RetrievalRagStage( - retrieval_modules=[ - VectorStoreRetrievalRagModule( - vector_store_driver=vector_store_driver, - query_params={ - "count": 2, - "namespace": namespace, - }, - ) - ] - ), - response_stage=ResponseRagStage( - response_module=PromptResponseRagModule( - prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") +engine = RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, + query_params={ + "count": 2, + "namespace": namespace, + }, ) + ] + ), + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) +) - vector_store_driver.upsert_text_artifacts( - {namespace: WebLoader(max_tokens=256).load(input_blogpost)} - ) +vector_store_driver.upsert_text_artifacts( + {namespace: WebLoader(max_tokens=256).load(input_blogpost)} +) - vector_store_tool = RagClient( - description="A DataStax blog post", - rag_engine=engine, - ) - agent = Agent(tools=[vector_store_tool, TaskMemoryClient(off_prompt=False)]) - agent.run( - "What engine made possible to index such an amount of data, " - "and what kind of tuning was required?" - ) +vector_store_tool = RagClient( + description="A DataStax blog post", + rag_engine=engine, +) +agent = Agent(tools=[vector_store_tool, TaskMemoryClient(off_prompt=False)]) +agent.run( + "What engine made possible to index such an amount of data, " + "and what kind of tuning was required?" +) ``` diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index d8c70c0a1..6a7984c8a 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -1,7 +1,5 @@ from __future__ import annotations -import logging -import warnings from typing import TYPE_CHECKING, Any, Optional from attrs import define, field @@ -13,19 +11,6 @@ from astrapy import Collection from astrapy.authentication import TokenProvider -GRIPTAPE_VERSION: Optional[str] -try: - from importlib import metadata - - GRIPTAPE_VERSION = metadata.version("griptape") -except Exception: - GRIPTAPE_VERSION = None - -logging.basicConfig(level=logging.WARNING) - - -COLLECTION_INDEXING = {"deny": ["meta.artifact"]} - @define class AstraDBVectorStoreDriver(BaseVectorStoreDriver): @@ -38,7 +23,7 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): collection_name: the name of the collection on Astra DB. environment: the environment ("prod", "hcd", ...) hosting the target Data API. It can be omitted for production Astra DB targets. See `astrapy.constants.Environment` for allowed values. - dimension: the number of components for embedding vectors. If not provided, it will be guessed from the embedding driver. + dimension: the number of components for embedding vectors metric: the similarity metric to use, one of "dot_product", "euclidean" or "cosine". If omitted, the server default ("cosine") will be used. See also values of `astrapy.constants.VectorMetric`. If the vectors are normalized to unit norm, choosing "dot_product" over cosine yields up to 2x speedup in searches. @@ -50,21 +35,18 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): token: Optional[str | TokenProvider] = field(kw_only=True, default=None, metadata={"serializable": False}) collection_name: str = field(kw_only=True, metadata={"serializable": True}) environment: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) - dimension: Optional[int] = field(kw_only=True, default=None, metadata={"serializable": True}) + dimension: int = field(kw_only=True, metadata={"serializable": True}) metric: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) astra_db_namespace: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) collection: Collection = field(init=False) + COLLECTION_INDEXING = {"deny": ["meta.artifact"]} def __attrs_post_init__(self) -> None: astrapy = import_optional_dependency("astrapy") - if not self.dimension: - # auto-compute dimension from the embedding - self.dimension = len(self.embedding_driver.embed_string("This is a sample text.")) self.collection = ( astrapy.DataAPIClient( caller_name="griptape", - caller_version=GRIPTAPE_VERSION, environment=self.environment, ) .get_database( @@ -76,7 +58,7 @@ def __attrs_post_init__(self) -> None: name=self.collection_name, dimension=self.dimension, metric=self.metric, - indexing=COLLECTION_INDEXING, + indexing=self.COLLECTION_INDEXING, check_exists=False, ) ) @@ -115,12 +97,6 @@ def upsert_vector( Returns: the ID of the written vector (str). """ - if kwargs: - warnings.warn( - "Unhandled keyword argument(s) provided to AstraDBVectorStore.upsert_vector: " - f"'{','.join(sorted(kwargs.keys()))}'. These will be ignored.", - stacklevel=2, - ) document = { k: v for k, v in {"$vector": vector, "_id": vector_id, "namespace": namespace, "meta": meta}.items() @@ -145,7 +121,7 @@ def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Opti """ find_filter = {k: v for k, v in {"_id": vector_id, "namespace": namespace}.items() if v is not None} match = self.collection.find_one(filter=find_filter, projection={"*": 1}) - if match: + if match is not None: return BaseVectorStoreDriver.Entry( id=match["_id"], vector=match.get("$vector"), meta=match.get("meta"), namespace=match.get("namespace") ) @@ -193,13 +169,7 @@ def query( A list of vector (`BaseVectorStoreDriver.Entry`) entries, with their `score` attribute set to the vector similarity to the query. """ - query_filter: Optional[dict[str, Any]] = kwargs.pop("filter", None) - if kwargs: - warnings.warn( - "Unhandled keyword argument(s) provided to AstraDBVectorStore.query: " - f"'{','.join(sorted(kwargs.keys()))}'. These will be ignored.", - stacklevel=2, - ) + query_filter: Optional[dict[str, Any]] = kwargs.get("filter") find_filter_ns: dict[str, Any] = {} if namespace is None else {"namespace": namespace} find_filter = {**(query_filter or {}), **find_filter_ns} find_projection: Optional[dict[str, int]] = {"*": 1} if include_vectors else None diff --git a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py index c758d9024..bc75f85be 100644 --- a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py @@ -14,13 +14,6 @@ TEST_COLLECTION_NAME_METRIC = "gt_int_test_dot" -def astrapy_available() -> bool: - try: - return True - except Exception: - return False - - def astra_db_available() -> bool: return all( [ @@ -30,10 +23,6 @@ def astra_db_available() -> bool: ) -def _descore_entry(entry: BaseVectorStoreDriver.Entry) -> BaseVectorStoreDriver.Entry: - return BaseVectorStoreDriver.Entry.from_dict({k: v for k, v in entry.__dict__.items() if k != "score"}) - - @define class ParserEmbeddingDriver(BaseEmbeddingDriver): model: str = field(default="foo", kw_only=True) @@ -52,9 +41,11 @@ def try_embed_chunk(self, chunk: str) -> list[float]: return (vector2d + [0] * (self.dimensions))[: self.dimensions] -@pytest.mark.skipif(not astrapy_available(), reason="Package astrapy not installed") @pytest.mark.skipif(not astra_db_available(), reason="No connection info for Astra DB") class TestAstraDBVectorStoreDriver: + def _descore_entry(self, entry: BaseVectorStoreDriver.Entry) -> BaseVectorStoreDriver.Entry: + return BaseVectorStoreDriver.Entry.from_dict({k: v for k, v in entry.__dict__.items() if k != "score"}) + @pytest.fixture() def embedding_driver(self): return ParserEmbeddingDriver() @@ -66,6 +57,7 @@ def vector_store_driver(self, embedding_driver): token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], collection_name=TEST_COLLECTION_NAME, astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + dimension=2, embedding_driver=embedding_driver, ) return driver @@ -149,12 +141,12 @@ def test_vector_crud(self, vector_store_driver, vector_store_collection, embeddi query_2_novectors = vector_store_driver.query("0.060", count=2) query_all_ns = vector_store_driver.query("0.060", include_vectors=True, namespace="ns") # - d_query_2 = [_descore_entry(ent) for ent in query_2] + d_query_2 = [self._descore_entry(ent) for ent in query_2] assert d_query_2 == [e3, e2] - d_query_all = [_descore_entry(ent) for ent in query_all] + d_query_all = [self._descore_entry(ent) for ent in query_all] assert d_query_all == [e3, e2, e1] - d_query_2_novectors = [_descore_entry(ent) for ent in query_2_novectors] + d_query_2_novectors = [self._descore_entry(ent) for ent in query_2_novectors] assert d_query_2_novectors == [ BaseVectorStoreDriver.Entry( id=id3, @@ -164,10 +156,10 @@ def test_vector_crud(self, vector_store_driver, vector_store_collection, embeddi namespace="ns", ), ] - d_query_all_ns = [_descore_entry(ent) for ent in query_all_ns] + d_query_all_ns = [self._descore_entry(ent) for ent in query_all_ns] assert d_query_all_ns == [e2] - def test_explicit_dimension(self, vector_store_driver, embedding_driver): + def test_mismatched_dimension(self, vector_store_driver, embedding_driver): AstraDBVectorStoreDriver( api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], @@ -197,7 +189,7 @@ def test_explicit_metric(self, embedding_driver): token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], collection_name=TEST_COLLECTION_NAME_METRIC, astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), - dimension=123, + dimension=2, metric="p-adic-norm", embedding_driver=embedding_driver, ) diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py index 207e894b2..a48b10bf9 100644 --- a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -5,27 +5,6 @@ from griptape.drivers import AstraDBVectorStoreDriver, BaseVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -one_document = { - "_id": "doc_id", - "$vector": [3.0, 2.0, 1.0], - "meta": "doc_meta", - "namespace": "doc_namespace", - "$similarity": 10, -} -one_entry = BaseVectorStoreDriver.Entry( - id=one_document["_id"], - vector=one_document["$vector"], - meta=one_document["meta"], - namespace=one_document["namespace"], -) -one_query_entry = BaseVectorStoreDriver.Entry( - id=one_document["_id"], - vector=one_document["$vector"], - meta=one_document["meta"], - namespace=one_document["namespace"], - score=one_document["$similarity"], -) - class TestAstraDBVectorStoreDriver: @pytest.fixture(autouse=True) @@ -36,7 +15,7 @@ def base_mock_collection(self, mocker): return mock_create_collection @pytest.fixture() - def mock_collection(self, base_mock_collection): + def mock_collection(self, base_mock_collection, one_document): """Augmented with specific response to certain method calls.""" # insert_one with server-side provided ID mock_insert_one_return_value = MagicMock() @@ -63,17 +42,39 @@ def driver(self, mock_collection): token="to", collection_name="co", astra_db_namespace="ns", + dimension=3, embedding_driver=MockEmbeddingDriver(dimensions=3), ) - def test_explicit_dimension(self, mock_collection): - AstraDBVectorStoreDriver( - api_endpoint="ep", - token="to", - collection_name="co", - astra_db_namespace="ns", - dimension=123, - embedding_driver=MockEmbeddingDriver(), + @pytest.fixture() + def one_document( + self, + ): + return { + "_id": "doc_id", + "$vector": [3.0, 2.0, 1.0], + "meta": "doc_meta", + "namespace": "doc_namespace", + "$similarity": 10, + } + + @pytest.fixture() + def one_entry(self, one_document): + return BaseVectorStoreDriver.Entry( + id=one_document["_id"], + vector=one_document["$vector"], + meta=one_document["meta"], + namespace=one_document["namespace"], + ) + + @pytest.fixture() + def one_query_entry(self, one_document): + return BaseVectorStoreDriver.Entry( + id=one_document["_id"], + vector=one_document["$vector"], + meta=one_document["meta"], + namespace=one_document["namespace"], + score=one_document["$similarity"], ) def test_delete_vector(self, driver, mock_collection): @@ -85,20 +86,12 @@ def test_upsert_vector_with_id(self, driver, mock_collection): assert upserted_id == "some_vector_id" mock_collection.return_value.find_one_and_replace.assert_called_once() - def test_upsert_vector_kwargs_warning(self, driver, mock_collection): - with pytest.warns(UserWarning): - upserted_id = driver.upsert_vector( - [1.0, 2.0, 3.0], vector_id="some_vector_id", namespace="some_namespace", kittens=123, marzipan="yes" - ) - assert upserted_id == "some_vector_id" - mock_collection.return_value.find_one_and_replace.assert_called_once() - def test_upsert_vector_no_id(self, driver, mock_collection): upserted_id = driver.upsert_vector([1.0, 2.0, 3.0], namespace="some_namespace") assert upserted_id == "insert_one_server_side_id" mock_collection.return_value.insert_one.assert_called_once() - def test_load_entry(self, driver, mock_collection): + def test_load_entry(self, driver, mock_collection, one_entry): entry = driver.load_entry("vector_id", namespace="some_namespace") assert entry == one_entry mock_collection.return_value.find_one.assert_called_once_with( @@ -114,7 +107,7 @@ def test_load_entry_empty(self, driver, mock_collection_findnothing): projection={"*": 1}, ) - def test_load_entries(self, driver, mock_collection): + def test_load_entries(self, driver, mock_collection, one_entry): entries = driver.load_entries(namespace="some_namespace") assert entries == [one_entry] mock_collection.return_value.find.assert_called_once_with( @@ -122,7 +115,7 @@ def test_load_entries(self, driver, mock_collection): projection={"*": 1}, ) - def test_query_allparams(self, driver, mock_collection): + def test_query_allparams(self, driver, mock_collection, one_query_entry): entries1 = driver.query("some query", count=999, namespace="some_namespace", include_vectors=True) assert entries1 == [one_query_entry] query_vector = driver.embedding_driver.embed_string("some query") @@ -134,7 +127,7 @@ def test_query_allparams(self, driver, mock_collection): include_similarity=True, ) - def test_query_minparams(self, driver, mock_collection): + def test_query_minparams(self, driver, mock_collection, one_query_entry): entries0 = driver.query("some query") assert entries0 == [one_query_entry] query_vector = driver.embedding_driver.embed_string("some query") @@ -145,16 +138,3 @@ def test_query_minparams(self, driver, mock_collection): projection=None, include_similarity=True, ) - - def test_query_kwargs_warning(self, driver, mock_collection): - with pytest.warns(UserWarning): - entries0 = driver.query("some query", sector=987, voltage="12 V") - assert entries0 == [one_query_entry] - query_vector = driver.embedding_driver.embed_string("some query") - mock_collection.return_value.find.assert_called_once_with( - filter={}, - sort={"$vector": query_vector}, - limit=BaseVectorStoreDriver.DEFAULT_QUERY_COUNT, - projection=None, - include_similarity=True, - ) From cc0e93bd16c4b7867052caeeb6b25a6918725e05 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Tue, 30 Jul 2024 16:10:03 +0200 Subject: [PATCH 15/21] remove ad-hoc ParserEmbeddingDriver, rather extending MockEmbeddingDriver to supply required functionality. --- .../test_astra_db_vector_store_driver.py | 34 +++++++------------ tests/mocks/mock_embedding_driver.py | 9 ++++- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py index d027004ec..4f4718f6b 100644 --- a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py @@ -3,12 +3,12 @@ import json import math import os +from typing import Optional import pytest -from attrs import define, field -from griptape.drivers import AstraDBVectorStoreDriver, BaseEmbeddingDriver, BaseVectorStoreDriver -from tests.mocks.mock_tokenizer import MockTokenizer +from griptape.drivers import AstraDBVectorStoreDriver, BaseVectorStoreDriver +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver TEST_COLLECTION_NAME = "gt_int_test" TEST_COLLECTION_NAME_METRIC = "gt_int_test_dot" @@ -23,24 +23,6 @@ def astra_db_available() -> bool: ) -@define -class ParserEmbeddingDriver(BaseEmbeddingDriver): - model: str = field(default="foo", kw_only=True) - dimensions: int = field(default=2, kw_only=True) - max_attempts: int = field(default=1, kw_only=True) - tokenizer: MockTokenizer = field(factory=lambda: MockTokenizer(model="foo bar"), kw_only=True) - - def try_embed_chunk(self, chunk: str) -> list[float]: - vector2d: list[float] - try: - fraction = float(json.loads(chunk)) - angle = fraction * math.pi * 2 - vector2d = [math.cos(angle), math.sin(angle)] - except Exception: - vector2d = [0.0, 0.0] - return (vector2d + [0] * (self.dimensions))[: self.dimensions] - - @pytest.mark.skipif(not astra_db_available(), reason="No connection info for Astra DB") class TestAstraDBVectorStoreDriver: def _descore_entry(self, entry: BaseVectorStoreDriver.Entry) -> BaseVectorStoreDriver.Entry: @@ -48,7 +30,15 @@ def _descore_entry(self, entry: BaseVectorStoreDriver.Entry) -> BaseVectorStoreD @pytest.fixture() def embedding_driver(self): - return ParserEmbeddingDriver() + def circle_fraction_string_to_vector(chunk: str) -> Optional[list[float]]: + try: + fraction = float(json.loads(chunk)) + angle = fraction * math.pi * 2 + return [math.cos(angle), math.sin(angle)] + except Exception: + return None + + return MockEmbeddingDriver(mock_output_function=circle_fraction_string_to_vector) @pytest.fixture() def vector_store_driver(self, embedding_driver): diff --git a/tests/mocks/mock_embedding_driver.py b/tests/mocks/mock_embedding_driver.py index 46d9bf515..239200688 100644 --- a/tests/mocks/mock_embedding_driver.py +++ b/tests/mocks/mock_embedding_driver.py @@ -1,5 +1,7 @@ from __future__ import annotations +from typing import Callable, Optional + from attrs import define, field from griptape.drivers import BaseEmbeddingDriver @@ -12,6 +14,11 @@ class MockEmbeddingDriver(BaseEmbeddingDriver): dimensions: int = field(default=42, kw_only=True) max_attempts: int = field(default=1, kw_only=True) tokenizer: MockTokenizer = field(factory=lambda: MockTokenizer(model="foo bar"), kw_only=True) + mock_output_function: Callable[[str], Optional[list[float]]] = field(default=lambda chunk: None, kw_only=None) def try_embed_chunk(self, chunk: str) -> list[float]: - return [0, 1] + output = self.mock_output_function(chunk) + if output is None: + return [0, 1] + else: + return output From fe4bc28639cea7e0f6c0d51f4172fb150756659f Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Tue, 30 Jul 2024 17:45:36 +0200 Subject: [PATCH 16/21] rename mock_output parameter to MockEmbeddingDriver --- .../vector/test_astra_db_vector_store_driver.py | 7 +++---- tests/mocks/mock_embedding_driver.py | 10 +++------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py index 4f4718f6b..242897255 100644 --- a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py @@ -3,7 +3,6 @@ import json import math import os -from typing import Optional import pytest @@ -30,15 +29,15 @@ def _descore_entry(self, entry: BaseVectorStoreDriver.Entry) -> BaseVectorStoreD @pytest.fixture() def embedding_driver(self): - def circle_fraction_string_to_vector(chunk: str) -> Optional[list[float]]: + def circle_fraction_string_to_vector(chunk: str) -> list[float]: try: fraction = float(json.loads(chunk)) angle = fraction * math.pi * 2 return [math.cos(angle), math.sin(angle)] except Exception: - return None + return [0.0, 0.0] - return MockEmbeddingDriver(mock_output_function=circle_fraction_string_to_vector) + return MockEmbeddingDriver(mock_output=circle_fraction_string_to_vector) @pytest.fixture() def vector_store_driver(self, embedding_driver): diff --git a/tests/mocks/mock_embedding_driver.py b/tests/mocks/mock_embedding_driver.py index 239200688..6fe415195 100644 --- a/tests/mocks/mock_embedding_driver.py +++ b/tests/mocks/mock_embedding_driver.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Callable, Optional +from typing import Callable from attrs import define, field @@ -14,11 +14,7 @@ class MockEmbeddingDriver(BaseEmbeddingDriver): dimensions: int = field(default=42, kw_only=True) max_attempts: int = field(default=1, kw_only=True) tokenizer: MockTokenizer = field(factory=lambda: MockTokenizer(model="foo bar"), kw_only=True) - mock_output_function: Callable[[str], Optional[list[float]]] = field(default=lambda chunk: None, kw_only=None) + mock_output: Callable[[str], list[float]] = field(default=lambda chunk: [0, 1], kw_only=True) def try_embed_chunk(self, chunk: str) -> list[float]: - output = self.mock_output_function(chunk) - if output is None: - return [0, 1] - else: - return output + return self.mock_output(chunk) From c00bf775383d8286fd6d6bbd9a98d5ac45c9aa76 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Tue, 30 Jul 2024 18:13:50 +0200 Subject: [PATCH 17/21] clear separation of vector store driver from collection provisioning --- .../vector/astra_db_vector_store_driver.py | 16 +-- .../test_astra_db_vector_store_driver.py | 100 ++++-------------- .../test_astra_db_vector_store_driver.py | 7 +- 3 files changed, 26 insertions(+), 97 deletions(-) diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index 6a7984c8a..a98f95d3c 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -20,13 +20,10 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): embedding_driver: a `griptape.drivers.BaseEmbeddingDriver` for embedding computations within the store api_endpoint: the "API Endpoint" for the Astra DB instance. token: a Database Token ("AstraCS:...") secret to access Astra DB. An instance of `astrapy.authentication.TokenProvider` is also accepted. - collection_name: the name of the collection on Astra DB. + collection_name: the name of the collection on Astra DB. The collection must have been created beforehand, + and support vectors with a vector dimension matching the embeddings being used by this driver. environment: the environment ("prod", "hcd", ...) hosting the target Data API. It can be omitted for production Astra DB targets. See `astrapy.constants.Environment` for allowed values. - dimension: the number of components for embedding vectors - metric: the similarity metric to use, one of "dot_product", "euclidean" or "cosine". - If omitted, the server default ("cosine") will be used. See also values of `astrapy.constants.VectorMetric`. - If the vectors are normalized to unit norm, choosing "dot_product" over cosine yields up to 2x speedup in searches. astra_db_namespace: optional specification of the namespace (in the Astra database) for the data. *Note*: not to be confused with the "namespace" mentioned elsewhere, which is a grouping within this vector store. """ @@ -35,12 +32,9 @@ class AstraDBVectorStoreDriver(BaseVectorStoreDriver): token: Optional[str | TokenProvider] = field(kw_only=True, default=None, metadata={"serializable": False}) collection_name: str = field(kw_only=True, metadata={"serializable": True}) environment: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) - dimension: int = field(kw_only=True, metadata={"serializable": True}) - metric: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) astra_db_namespace: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) collection: Collection = field(init=False) - COLLECTION_INDEXING = {"deny": ["meta.artifact"]} def __attrs_post_init__(self) -> None: astrapy = import_optional_dependency("astrapy") @@ -54,12 +48,8 @@ def __attrs_post_init__(self) -> None: token=self.token, namespace=self.astra_db_namespace, ) - .create_collection( + .get_collection( name=self.collection_name, - dimension=self.dimension, - metric=self.metric, - indexing=self.COLLECTION_INDEXING, - check_exists=False, ) ) diff --git a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py index 242897255..0624be39c 100644 --- a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py @@ -13,16 +13,6 @@ TEST_COLLECTION_NAME_METRIC = "gt_int_test_dot" -def astra_db_available() -> bool: - return all( - [ - "ASTRA_DB_APPLICATION_TOKEN" in os.environ, - "ASTRA_DB_API_ENDPOINT" in os.environ, - ] - ) - - -@pytest.mark.skipif(not astra_db_available(), reason="No connection info for Astra DB") class TestAstraDBVectorStoreDriver: def _descore_entry(self, entry: BaseVectorStoreDriver.Entry) -> BaseVectorStoreDriver.Entry: return BaseVectorStoreDriver.Entry.from_dict({k: v for k, v in entry.__dict__.items() if k != "score"}) @@ -40,22 +30,32 @@ def circle_fraction_string_to_vector(chunk: str) -> list[float]: return MockEmbeddingDriver(mock_output=circle_fraction_string_to_vector) @pytest.fixture() - def vector_store_driver(self, embedding_driver): - driver = AstraDBVectorStoreDriver( + def vector_store_collection(self): + import astrapy + + database = astrapy.DataAPIClient().get_database( api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], - collection_name=TEST_COLLECTION_NAME, - astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + ) + collection = database.create_collection( + name=TEST_COLLECTION_NAME, dimension=2, - embedding_driver=embedding_driver, + metric="cosine", ) - yield driver - driver.collection.drop() + yield collection + collection.drop() @pytest.fixture() - def vector_store_collection(self, vector_store_driver): - """For testing purposes, access the bare AstraPy "Collection".""" - return vector_store_driver.collection + def vector_store_driver(self, embedding_driver, vector_store_collection): + driver = AstraDBVectorStoreDriver( + api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], + token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], + collection_name=vector_store_collection.name, + astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), + embedding_driver=embedding_driver, + ) + return driver def test_vector_crud(self, vector_store_driver, vector_store_collection, embedding_driver): """Test basic vector CRUD, various call patterns.""" @@ -147,63 +147,3 @@ def test_vector_crud(self, vector_store_driver, vector_store_collection, embeddi ] d_query_all_ns = [self._descore_entry(ent) for ent in query_all_ns] assert d_query_all_ns == [e2] - - def test_mismatched_dimension(self, vector_store_driver, embedding_driver): - AstraDBVectorStoreDriver( - api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], - token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], - collection_name=TEST_COLLECTION_NAME, - astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), - dimension=2, - embedding_driver=embedding_driver, - ) - import astrapy - - with pytest.raises(astrapy.exceptions.DataAPIException): - AstraDBVectorStoreDriver( - api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], - token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], - collection_name=TEST_COLLECTION_NAME, - astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), - dimension=123, - embedding_driver=embedding_driver, - ) - - def test_explicit_metric(self, embedding_driver): - import astrapy - - with pytest.raises(astrapy.exceptions.DataAPIResponseException): - AstraDBVectorStoreDriver( - api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], - token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], - collection_name=TEST_COLLECTION_NAME_METRIC, - astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), - dimension=2, - metric="p-adic-norm", - embedding_driver=embedding_driver, - ) - - # seriously ... - dot_vector_store_driver = AstraDBVectorStoreDriver( - api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], - token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], - collection_name=TEST_COLLECTION_NAME_METRIC, - astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), - dimension=2, - metric="dot_product", - embedding_driver=embedding_driver, - ) - try: - # some vectors are off-sphere, to probe dot product as metric - short_v = [0.1, 0.0] - pi_4_v = embedding_driver.embed_string("0.125") - tenx_pi_4_v = [10 * comp for comp in pi_4_v] - dot_vector_store_driver.upsert_vector(short_v, vector_id="short_v") - dot_vector_store_driver.upsert_vector(pi_4_v, vector_id="pi_4_v") - dot_vector_store_driver.upsert_vector(tenx_pi_4_v, vector_id="tenx_pi_4_v") - entries = dot_vector_store_driver.query("0.0", count=2) - assert len(entries) == 2 - assert entries[0].id == "tenx_pi_4_v" - assert entries[1].id == "pi_4_v" - finally: - dot_vector_store_driver.collection.drop() diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py index a48b10bf9..a61d10086 100644 --- a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -9,10 +9,10 @@ class TestAstraDBVectorStoreDriver: @pytest.fixture(autouse=True) def base_mock_collection(self, mocker): - mock_create_collection = mocker.patch( + mock_get_collection = mocker.patch( "astrapy.DataAPIClient" - ).return_value.get_database.return_value.create_collection - return mock_create_collection + ).return_value.get_database.return_value.get_collection + return mock_get_collection @pytest.fixture() def mock_collection(self, base_mock_collection, one_document): @@ -42,7 +42,6 @@ def driver(self, mock_collection): token="to", collection_name="co", astra_db_namespace="ns", - dimension=3, embedding_driver=MockEmbeddingDriver(dimensions=3), ) From 6f126e9eb968126e747d4cebcc5f8f0dce0455a8 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Tue, 30 Jul 2024 19:12:27 +0200 Subject: [PATCH 18/21] adapt full demo script to latest api --- docs/examples/query-webpage-astra-db.md | 4 +++- docs/griptape-framework/drivers/vector-store-drivers.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/examples/query-webpage-astra-db.md b/docs/examples/query-webpage-astra-db.md index 2152879f5..0d90cb1a1 100644 --- a/docs/examples/query-webpage-astra-db.md +++ b/docs/examples/query-webpage-astra-db.md @@ -3,6 +3,9 @@ stores its chunked contents on Astra DB through the Astra DB vector store driver and finally runs a RAG process to answer a question specific to the topic of the Web page. +This script requires that a vector collection has been created in the Astra database +(with name `"griptape_test_collection"` and vector dimension matching the embedding being used, i.e. 1536 in this case). + _Note:_ Besides the [Astra DB](../griptape-framework/drivers/vector-store-drivers.md#astra-db) extra, this example requires the `drivers-web-scraper-trafilatura` Griptape extra to be installed as well. @@ -38,7 +41,6 @@ vector_store_driver = AstraDBVectorStoreDriver( token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], collection_name="griptape_test_collection", astra_db_namespace=os.environ.get("ASTRA_DB_KEYSPACE"), - dimension=1536, ) engine = RagEngine( diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index b296e60b2..b5b0607d2 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -510,7 +510,7 @@ vector_store_driver = AstraDBVectorStoreDriver( api_endpoint=api_endpoint, token=token, collection_name="astra_db_demo", - astra_db_namespace=astra_db_namespace, + astra_db_namespace=astra_db_namespace, # optional ) # Load Artifacts from the web From 2d8580d8060f70f6ebb96f76a9d54d7f73fc3009 Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Tue, 30 Jul 2024 23:01:44 +0200 Subject: [PATCH 19/21] final driver name AstraDbVectorStoreDriver; private method at end of test class --- CHANGELOG.md | 2 +- docs/examples/query-webpage-astra-db.md | 4 ++-- .../drivers/vector-store-drivers.md | 6 +++--- griptape/drivers/__init__.py | 4 ++-- .../drivers/vector/astra_db_vector_store_driver.py | 2 +- .../vector/test_astra_db_vector_store_driver.py | 12 ++++++------ .../vector/test_astra_db_vector_store_driver.py | 6 +++--- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3186d715a..24e53f327 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `@observable` decorator for selecting which functions/methods to provide observability for. - `GenericArtifact` for storing any data. - `BaseTextArtifact` for text-based Artifacts to subclass. -- `AstraDBVectorStoreDriver` to support DataStax Astra DB as a vector store. +- `AstraDbVectorStoreDriver` to support DataStax Astra DB as a vector store. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifacts` optional arguments are now keyword-only arguments. diff --git a/docs/examples/query-webpage-astra-db.md b/docs/examples/query-webpage-astra-db.md index 0d90cb1a1..46989c2ba 100644 --- a/docs/examples/query-webpage-astra-db.md +++ b/docs/examples/query-webpage-astra-db.md @@ -15,7 +15,7 @@ Griptape extra to be installed as well. import os from griptape.drivers import ( - AstraDBVectorStoreDriver, + AstraDbVectorStoreDriver, OpenAiChatPromptDriver, OpenAiEmbeddingDriver, ) @@ -35,7 +35,7 @@ input_blogpost = ( "www.datastax.com/blog/indexing-all-of-wikipedia-on-a-laptop" ) -vector_store_driver = AstraDBVectorStoreDriver( +vector_store_driver = AstraDbVectorStoreDriver( embedding_driver=OpenAiEmbeddingDriver(), api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index b5b0607d2..91890e161 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -488,13 +488,13 @@ print("\n\n".join(values)) !!! info This Driver requires the `drivers-vector-astra-db` [extra](../index.md#extras). -The AstraDBVectorStoreDriver supports [DataStax Astra DB](https://www.datastax.com/products/datastax-astra). +The AstraDbVectorStoreDriver supports [DataStax Astra DB](https://www.datastax.com/products/datastax-astra). The following example shows how to store vector entries and query the information using the driver: ```python import os -from griptape.drivers import AstraDBVectorStoreDriver, OpenAiEmbeddingDriver +from griptape.drivers import AstraDbVectorStoreDriver, OpenAiEmbeddingDriver from griptape.loaders import WebLoader # Astra DB secrets and connection parameters @@ -505,7 +505,7 @@ astra_db_namespace = os.environ.get("ASTRA_DB_KEYSPACE") # optional # Initialize an Embedding Driver. embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) -vector_store_driver = AstraDBVectorStoreDriver( +vector_store_driver = AstraDbVectorStoreDriver( embedding_driver=embedding_driver, api_endpoint=api_endpoint, token=token, diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index f9e7718dd..98d6c1afa 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -41,7 +41,7 @@ from .vector.azure_mongodb_vector_store_driver import AzureMongoDbVectorStoreDriver from .vector.dummy_vector_store_driver import DummyVectorStoreDriver from .vector.qdrant_vector_store_driver import QdrantVectorStoreDriver -from .vector.astra_db_vector_store_driver import AstraDBVectorStoreDriver +from .vector.astra_db_vector_store_driver import AstraDbVectorStoreDriver from .vector.griptape_cloud_knowledge_base_vector_store_driver import GriptapeCloudKnowledgeBaseVectorStoreDriver from .sql.base_sql_driver import BaseSqlDriver @@ -172,7 +172,7 @@ "AmazonOpenSearchVectorStoreDriver", "PgVectorVectorStoreDriver", "QdrantVectorStoreDriver", - "AstraDBVectorStoreDriver", + "AstraDbVectorStoreDriver", "DummyVectorStoreDriver", "GriptapeCloudKnowledgeBaseVectorStoreDriver", "BaseSqlDriver", diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astra_db_vector_store_driver.py index a98f95d3c..029fa382d 100644 --- a/griptape/drivers/vector/astra_db_vector_store_driver.py +++ b/griptape/drivers/vector/astra_db_vector_store_driver.py @@ -13,7 +13,7 @@ @define -class AstraDBVectorStoreDriver(BaseVectorStoreDriver): +class AstraDbVectorStoreDriver(BaseVectorStoreDriver): """A Vector Store Driver for Astra DB. Attributes: diff --git a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py index 0624be39c..94dbb8570 100644 --- a/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/integration/drivers/vector/test_astra_db_vector_store_driver.py @@ -6,17 +6,14 @@ import pytest -from griptape.drivers import AstraDBVectorStoreDriver, BaseVectorStoreDriver +from griptape.drivers import AstraDbVectorStoreDriver, BaseVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver TEST_COLLECTION_NAME = "gt_int_test" TEST_COLLECTION_NAME_METRIC = "gt_int_test_dot" -class TestAstraDBVectorStoreDriver: - def _descore_entry(self, entry: BaseVectorStoreDriver.Entry) -> BaseVectorStoreDriver.Entry: - return BaseVectorStoreDriver.Entry.from_dict({k: v for k, v in entry.__dict__.items() if k != "score"}) - +class TestAstraDbVectorStoreDriver: @pytest.fixture() def embedding_driver(self): def circle_fraction_string_to_vector(chunk: str) -> list[float]: @@ -48,7 +45,7 @@ def vector_store_collection(self): @pytest.fixture() def vector_store_driver(self, embedding_driver, vector_store_collection): - driver = AstraDBVectorStoreDriver( + driver = AstraDbVectorStoreDriver( api_endpoint=os.environ["ASTRA_DB_API_ENDPOINT"], token=os.environ["ASTRA_DB_APPLICATION_TOKEN"], collection_name=vector_store_collection.name, @@ -147,3 +144,6 @@ def test_vector_crud(self, vector_store_driver, vector_store_collection, embeddi ] d_query_all_ns = [self._descore_entry(ent) for ent in query_all_ns] assert d_query_all_ns == [e2] + + def _descore_entry(self, entry: BaseVectorStoreDriver.Entry) -> BaseVectorStoreDriver.Entry: + return BaseVectorStoreDriver.Entry.from_dict({k: v for k, v in entry.__dict__.items() if k != "score"}) diff --git a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py index a61d10086..16e6530b3 100644 --- a/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_astra_db_vector_store_driver.py @@ -2,11 +2,11 @@ import pytest -from griptape.drivers import AstraDBVectorStoreDriver, BaseVectorStoreDriver +from griptape.drivers import AstraDbVectorStoreDriver, BaseVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -class TestAstraDBVectorStoreDriver: +class TestAstraDbVectorStoreDriver: @pytest.fixture(autouse=True) def base_mock_collection(self, mocker): mock_get_collection = mocker.patch( @@ -37,7 +37,7 @@ def mock_collection_findnothing(self, base_mock_collection): @pytest.fixture() def driver(self, mock_collection): - return AstraDBVectorStoreDriver( + return AstraDbVectorStoreDriver( api_endpoint="ep", token="to", collection_name="co", From ad15226346570060cabecd356919013c9117311f Mon Sep 17 00:00:00 2001 From: Stefano Lottini Date: Tue, 30 Jul 2024 23:24:37 +0200 Subject: [PATCH 20/21] module rename astra_db_vector_store_driver.py => astradb_vector_store_driver.py --- griptape/drivers/__init__.py | 2 +- ...db_vector_store_driver.py => astradb_vector_store_driver.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename griptape/drivers/vector/{astra_db_vector_store_driver.py => astradb_vector_store_driver.py} (100%) diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 98d6c1afa..9e1790b01 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -41,7 +41,7 @@ from .vector.azure_mongodb_vector_store_driver import AzureMongoDbVectorStoreDriver from .vector.dummy_vector_store_driver import DummyVectorStoreDriver from .vector.qdrant_vector_store_driver import QdrantVectorStoreDriver -from .vector.astra_db_vector_store_driver import AstraDbVectorStoreDriver +from .vector.astradb_vector_store_driver import AstraDbVectorStoreDriver from .vector.griptape_cloud_knowledge_base_vector_store_driver import GriptapeCloudKnowledgeBaseVectorStoreDriver from .sql.base_sql_driver import BaseSqlDriver diff --git a/griptape/drivers/vector/astra_db_vector_store_driver.py b/griptape/drivers/vector/astradb_vector_store_driver.py similarity index 100% rename from griptape/drivers/vector/astra_db_vector_store_driver.py rename to griptape/drivers/vector/astradb_vector_store_driver.py From bdef2ae3d2ef8876f33871a68058841d27d27f80 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 31 Jul 2024 09:41:58 -0700 Subject: [PATCH 21/21] Fix integration tests --- .github/workflows/docs-integration-tests.yml | 5 ++--- docs/griptape-framework/drivers/vector-store-drivers.md | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs-integration-tests.yml b/.github/workflows/docs-integration-tests.yml index 318142eec..4418f0b12 100644 --- a/.github/workflows/docs-integration-tests.yml +++ b/.github/workflows/docs-integration-tests.yml @@ -124,9 +124,8 @@ jobs: ZENROWS_API_KEY: ${{ secrets.INTEG_ZENROWS_API_KEY }} QDRANT_CLUSTER_ENDPOINT: ${{ secrets.INTEG_QDRANT_CLUSTER_ENDPOINT }} QDRANT_CLUSTER_API_KEY: ${{ secrets.INTEG_QDRANT_CLUSTER_API_KEY }} - ASTRA_DB_API_ENDPOINT: ${{ secrets.ASTRA_DB_API_ENDPOINT }} - ASTRA_DB_APPLICATION_TOKEN: ${{ secrets.ASTRA_DB_APPLICATION_TOKEN }} - ASTRA_DB_KEYSPACE: ${{ secrets.ASTRA_DB_KEYSPACE }} + ASTRA_DB_API_ENDPOINT: ${{ secrets.INTEG_ASTRA_DB_API_ENDPOINT }} + ASTRA_DB_APPLICATION_TOKEN: ${{ secrets.INTEG_ASTRA_DB_APPLICATION_TOKEN }} services: postgres: image: ankane/pgvector:v0.5.0 diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 91890e161..ad826d0aa 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -509,7 +509,7 @@ vector_store_driver = AstraDbVectorStoreDriver( embedding_driver=embedding_driver, api_endpoint=api_endpoint, token=token, - collection_name="astra_db_demo", + collection_name="griptape_test_collection", astra_db_namespace=astra_db_namespace, # optional )