From 6fe6573ceb93b38e82144686211ced4764b2d1cf Mon Sep 17 00:00:00 2001 From: theanupllm Date: Fri, 31 Jan 2025 13:13:09 +0530 Subject: [PATCH 01/13] feat: Add Pinecone Local Index support and update dependencies - Added PineconeLocalIndex to support local Pinecone testing - Updated GitHub Actions workflow to use Pinecone local service - Updated dependencies in pyproject.toml and poetry.lock - Modified schema and router to support PineconeLocalIndex - Updated test configurations to use PineconeLocalIndex --- .github/workflows/test.yml | 31 +- .gitignore | 1 + Makefile | 3 +- docs/10-pinecone-local.ipynb | 541 ++++++++++++ docs/indexes/pinecone-local.ipynb | 771 +++++++++++++++++ poetry.lock | 1003 ++++++++++++++-------- pyproject.toml | 2 +- semantic_router/index/__init__.py | 2 + semantic_router/index/pinecone_local.py | 1037 +++++++++++++++++++++++ semantic_router/routers/base.py | 6 +- semantic_router/schema.py | 5 +- tests/unit/test_router.py | 42 +- 12 files changed, 3070 insertions(+), 374 deletions(-) create mode 100644 docs/10-pinecone-local.ipynb create mode 100644 docs/indexes/pinecone-local.ipynb create mode 100644 semantic_router/index/pinecone_local.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eef6d78b..96fa6bce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,6 +10,15 @@ env: jobs: build: runs-on: ubuntu-latest + services: + pinecone: + image: ghcr.io/pinecone-io/pinecone-local:latest + env: + PORT: 5080 + PINECONE_HOST: localhost + ports: + - "5080-6000:5080-6000" + strategy: matrix: python-version: @@ -19,13 +28,12 @@ jobs: - "3.13" steps: - uses: actions/checkout@v4 - - name: Cache Poetry - uses: actions/cache@v4 - with: - path: ~/.poetry - key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }} - restore-keys: | - ${{ runner.os }}-poetry- + + - name: Wait for Pinecone service to start + run: | + echo "Waiting for Pinecone service to start..." + sleep 10 # Wait for 10 seconds to ensure the container is up + - name: Install poetry run: | pipx install poetry==$POETRY_VERSION @@ -34,18 +42,25 @@ jobs: with: python-version: ${{ matrix.python-version }} cache: poetry + + # - name: Add Poetry to PATH + # run: echo "PATH=$HOME/.local/bin:$PATH" >> $GITHUB_ENV + - name: Install dependencies run: | poetry install --all-extras - name: Install nltk run: | pip install nltk + - name: Download nltk data run: | python -m nltk.downloader punkt stopwords wordnet punkt_tab + - name: Pytest All env: - PINECONE_API_KEY: ${{ secrets.PINECONE_API_KEY }} + PINECONE_API_KEY: pclocal + PINECONE_API_BASE_URL: http://localhost:5080 OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} run: | diff --git a/.gitignore b/.gitignore index 094c61f4..c0bd2843 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ venv/ # local env files .env*.local .env +my.secrets mac.env local.mac.env diff --git a/Makefile b/Makefile index ad9e9357..5f85bd41 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,9 @@ test: poetry run pytest -vv --cov=semantic_router --cov-report=term-missing --cov-report=xml --exitfirst --maxfail=1 test_functional: - poetry run pytest -vv --exitfirst --maxfail=1 tests/functional + poetry run pytest -vv -s --exitfirst --maxfail=1 tests/functional test_unit: poetry run pytest -vv --exitfirst --maxfail=1 tests/unit + test_integration: poetry run pytest -vv --exitfirst --maxfail=1 tests/integration diff --git a/docs/10-pinecone-local.ipynb b/docs/10-pinecone-local.ipynb new file mode 100644 index 00000000..a26541c0 --- /dev/null +++ b/docs/10-pinecone-local.ipynb @@ -0,0 +1,541 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "G1AJs8NHh6tF" + }, + "source": [ + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/aurelio-labs/semantic-router/blob/main/docs/09-route-filter.ipynb) [![Open nbviewer](https://raw.githubusercontent.com/pinecone-io/examples/master/assets/nbviewer-shield.svg)](https://nbviewer.org/github/aurelio-labs/semantic-router/blob/main/docs/00-introduction.ipynb)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "tly249bZh6tG" + }, + "source": [ + "# Semantic Router Filter" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "obVbdRpkh6tH" + }, + "source": [ + "The Semantic Router library can be used as a super fast route making layer on top of LLMs. That means rather than waiting on a slow agent to decide what to do, we can use the magic of semantic vector space to make routes. Cutting route making time down from seconds to milliseconds." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting pinecone[grpc]\n", + " Downloading pinecone-5.4.2-py3-none-any.whl.metadata (19 kB)\n", + "Requirement already satisfied: certifi>=2019.11.17 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from pinecone[grpc]) (2024.12.14)\n", + "Collecting googleapis-common-protos>=1.53.0 (from pinecone[grpc])\n", + " Using cached googleapis_common_protos-1.66.0-py2.py3-none-any.whl.metadata (1.5 kB)\n", + "Collecting grpcio>=1.59.0 (from pinecone[grpc])\n", + " Downloading grpcio-1.70.0-cp312-cp312-win_amd64.whl.metadata (4.0 kB)\n", + "Collecting lz4>=3.1.3 (from pinecone[grpc])\n", + " Downloading lz4-4.4.3-cp312-cp312-win_amd64.whl.metadata (3.9 kB)\n", + "Collecting pinecone-plugin-inference<4.0.0,>=2.0.0 (from pinecone[grpc])\n", + " Downloading pinecone_plugin_inference-3.1.0-py3-none-any.whl.metadata (2.2 kB)\n", + "Collecting pinecone-plugin-interface<0.0.8,>=0.0.7 (from pinecone[grpc])\n", + " Using cached pinecone_plugin_interface-0.0.7-py3-none-any.whl.metadata (1.2 kB)\n", + "Collecting protobuf<5.0,>=4.25 (from pinecone[grpc])\n", + " Downloading protobuf-4.25.6-cp310-abi3-win_amd64.whl.metadata (541 bytes)\n", + "Collecting protoc-gen-openapiv2<0.0.2,>=0.0.1 (from pinecone[grpc])\n", + " Using cached protoc_gen_openapiv2-0.0.1-py3-none-any.whl.metadata (1.5 kB)\n", + "Requirement already satisfied: python-dateutil>=2.5.3 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from pinecone[grpc]) (2.9.0.post0)\n", + "Collecting tqdm>=4.64.1 (from pinecone[grpc])\n", + " Downloading tqdm-4.67.1-py3-none-any.whl.metadata (57 kB)\n", + "Requirement already satisfied: typing-extensions>=3.7.4 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from pinecone[grpc]) (4.12.2)\n", + "Requirement already satisfied: urllib3>=1.26.5 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from pinecone[grpc]) (2.3.0)\n", + "Requirement already satisfied: six>=1.5 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from python-dateutil>=2.5.3->pinecone[grpc]) (1.17.0)\n", + "Requirement already satisfied: colorama in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from tqdm>=4.64.1->pinecone[grpc]) (0.4.6)\n", + "Using cached googleapis_common_protos-1.66.0-py2.py3-none-any.whl (221 kB)\n", + "Downloading grpcio-1.70.0-cp312-cp312-win_amd64.whl (4.3 MB)\n", + " ---------------------------------------- 0.0/4.3 MB ? eta -:--:--\n", + " --------- ------------------------------ 1.0/4.3 MB 8.4 MB/s eta 0:00:01\n", + " ------------ --------------------------- 1.3/4.3 MB 6.1 MB/s eta 0:00:01\n", + " --------------------- ------------------ 2.4/4.3 MB 4.6 MB/s eta 0:00:01\n", + " -------------------------- ------------- 2.9/4.3 MB 4.1 MB/s eta 0:00:01\n", + " --------------------------------------- 4.2/4.3 MB 4.3 MB/s eta 0:00:01\n", + " ---------------------------------------- 4.3/4.3 MB 4.2 MB/s eta 0:00:00\n", + "Downloading lz4-4.4.3-cp312-cp312-win_amd64.whl (99 kB)\n", + "Downloading pinecone_plugin_inference-3.1.0-py3-none-any.whl (87 kB)\n", + "Using cached pinecone_plugin_interface-0.0.7-py3-none-any.whl (6.2 kB)\n", + "Downloading protobuf-4.25.6-cp310-abi3-win_amd64.whl (413 kB)\n", + "Using cached protoc_gen_openapiv2-0.0.1-py3-none-any.whl (7.9 kB)\n", + "Downloading tqdm-4.67.1-py3-none-any.whl (78 kB)\n", + "Downloading pinecone-5.4.2-py3-none-any.whl (427 kB)\n", + "Installing collected packages: tqdm, protobuf, pinecone-plugin-interface, lz4, grpcio, pinecone-plugin-inference, googleapis-common-protos, protoc-gen-openapiv2, pinecone\n", + "Successfully installed googleapis-common-protos-1.66.0 grpcio-1.70.0 lz4-4.4.3 pinecone-5.4.2 pinecone-plugin-inference-3.1.0 pinecone-plugin-interface-0.0.7 protobuf-4.25.6 protoc-gen-openapiv2-0.0.1 tqdm-4.67.1\n" + ] + } + ], + "source": [ + "!pip install \"pinecone[grpc]\"" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Index stats:\n", + " {'dimension': 2,\n", + " 'index_fullness': 0.0,\n", + " 'namespaces': {'example-namespace': {'vector_count': 3}},\n", + " 'total_vector_count': 3}\n", + "\n", + "Query response:\n", + " {'matches': [{'id': 'vec2',\n", + " 'metadata': {'genre': 'documentary'},\n", + " 'score': 1.0,\n", + " 'sparse_values': {'indices': [], 'values': []},\n", + " 'values': [3.0, -2.0]}],\n", + " 'namespace': 'example-namespace'}\n" + ] + } + ], + "source": [ + "from pinecone.grpc import PineconeGRPC, GRPCClientConfig\n", + "from pinecone import ServerlessSpec\n", + "import time\n", + "\n", + "# Initialize a client.\n", + "# API key is required, but the value does not matter.\n", + "# Host and port of the Pinecone Local instance\n", + "# is required when starting without indexes.\n", + "pc = PineconeGRPC(api_key=\"pclocal\", host=\"http://localhost:5080\")\n", + "\n", + "# Create an index\n", + "index_name = \"example-index\"\n", + "\n", + "if not pc.has_index(index_name):\n", + " pc.create_index(\n", + " name=index_name,\n", + " dimension=2,\n", + " metric=\"cosine\",\n", + " spec=ServerlessSpec(\n", + " cloud=\"aws\",\n", + " region=\"us-east-1\",\n", + " ),\n", + " )\n", + "\n", + "# Wait for the index to be ready\n", + "while not pc.describe_index(index_name).status[\"ready\"]:\n", + " time.sleep(1)\n", + "\n", + "# Target the index, disabling tls\n", + "index_host = pc.describe_index(index_name).host\n", + "index = pc.Index(host=index_host, grpc_config=GRPCClientConfig(secure=False))\n", + "\n", + "# Upsert records into the index\n", + "index.upsert(\n", + " vectors=[\n", + " {\"id\": \"vec1\", \"values\": [1.0, -2.5], \"metadata\": {\"genre\": \"drama\"}},\n", + " {\"id\": \"vec2\", \"values\": [3.0, -2.0], \"metadata\": {\"genre\": \"documentary\"}},\n", + " {\"id\": \"vec3\", \"values\": [0.5, -1.5], \"metadata\": {\"genre\": \"documentary\"}},\n", + " ],\n", + " namespace=\"example-namespace\",\n", + ")\n", + "\n", + "# Check the number of records in the index\n", + "print(\"Index stats:\\n\", index.describe_index_stats())\n", + "\n", + "# Query the index with a metadata filter\n", + "response = index.query(\n", + " vector=[3.0, -2.0],\n", + " filter={\"genre\": {\"$eq\": \"documentary\"}},\n", + " top_k=1,\n", + " include_values=True,\n", + " include_metadata=True,\n", + " namespace=\"example-namespace\",\n", + ")\n", + "\n", + "print(\"\\nQuery response:\\n\", response)\n", + "\n", + "# Delete the index\n", + "pc.delete_index(index_name)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "x9wSBV1-h6tH" + }, + "source": [ + "## Getting Started" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Mw7_rFAch6tH" + }, + "source": [ + "We start by installing the library:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "jKjHHH10h6tH" + }, + "outputs": [], + "source": [ + "!pip install -qU semantic-router" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "K5mvw1yUh6tK" + }, + "source": [ + "We start by defining a dictionary mapping routes to example phrases that should trigger those routes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "2nU02l4Mh6tK", + "outputId": "f2b4dadd-14b0-4faa-af62-bdb6518b6bb6" + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Siraj\\Documents\\Personal\\Work\\Aurelio\\Virtual Environments\\semantic_router_3\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "from semantic_router import Route\n", + "\n", + "politics = Route(\n", + " name=\"politics\",\n", + " utterances=[\n", + " \"isn't politics the best thing ever\",\n", + " \"why don't you tell me about your political opinions\",\n", + " \"don't you just love the president\",\n", + " \"don't you just hate the president\",\n", + " \"they're going to destroy this country!\",\n", + " \"they will save the country!\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "FCSq2Ncbh6tL" + }, + "source": [ + "Let's define another for good measure:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "0rkTc2ehh6tL" + }, + "outputs": [], + "source": [ + "chitchat = Route(\n", + " name=\"chitchat\",\n", + " utterances=[\n", + " \"how's the weather today?\",\n", + " \"how are things going?\",\n", + " \"lovely weather today\",\n", + " \"the weather is horrendous\",\n", + " \"let's go to the chippy\",\n", + " ],\n", + ")\n", + "\n", + "routes = [politics, chitchat]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "BWdFd8Neh6tM" + }, + "source": [ + "Now we initialize our embedding model:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "XiI5ob3Gh6tM" + }, + "outputs": [], + "source": [ + "import os\n", + "from getpass import getpass\n", + "from semantic_router.encoders import CohereEncoder, OpenAIEncoder\n", + "\n", + "os.environ[\"COHERE_API_KEY\"] = os.getenv(\"COHERE_API_KEY\") or getpass(\n", + " \"Enter Cohere API Key: \"\n", + ")\n", + "# os.environ[\"OPENAI_API_KEY\"] = os.getenv(\"OPENAI_API_KEY\") or getpass(\n", + "# \"Enter OpenAI API Key: \"\n", + "# )\n", + "\n", + "encoder = CohereEncoder()\n", + "# encoder = OpenAIEncoder()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "rebk9Z4yh6tM" + }, + "source": [ + "Now we define the `RouteLayer`. When called, the route layer will consume text (a query) and output the category (`Route`) it belongs to — to initialize a `RouteLayer` we need our `encoder` model and a list of `routes`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "qeP6ZUMoh6tM", + "outputId": "6909f60c-41e2-4be5-eb25-8374e3d1461c" + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m2024-05-07 16:02:43 INFO semantic_router.utils.logger local\u001b[0m\n" + ] + } + ], + "source": [ + "from semantic_router.layer import RouteLayer\n", + "\n", + "rl = RouteLayer(encoder=encoder, routes=routes)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AF55Xqg1h6tN" + }, + "source": [ + "Now we can test it:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "126uJrBKh6tN", + "outputId": "fca3e781-667e-42a9-e125-2c44cd314a09" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "RouteChoice(name='politics', function_call=None, similarity_score=None)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rl(\"don't you love politics?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "oRNUvo3dh6tN", + "outputId": "c166e961-e897-48c4-b79f-fbbd678bd22e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rl(\"how's the weather today?\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dQNc9OD4h6tN" + }, + "source": [ + "Both are classified accurately, what if we send a query that is unrelated to our existing `Route` objects?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "LRKIToX3h6tO", + "outputId": "b5795fb1-2045-4484-9858-377aeb98ba8d" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "RouteChoice(name=None, function_call=None, similarity_score=None)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rl(\"I'm interested in learning about llama 2\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GVxcpE9Vh6tO" + }, + "source": [ + "In this case, we return `None` because no matches were identified." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-zJEY71mh6tO" + }, + "source": [ + "# Demonstrating the Filter Feature\n", + "\n", + "Now, let's demonstrate the filter feature. We can specify a subset of routes to consider when making a classification. This can be useful if we want to restrict the scope of possible routes based on some context.\n", + "\n", + "For example, let's say we only want to consider the \"chitchat\" route for a particular query:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "M8qIXBOWh6tO", + "outputId": "37272c84-8189-477a-bdaa-7ce043fc203e" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rl(\"don't you love politics?\", route_filter=[\"chitchat\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "JQfEDKZgh6tO" + }, + "source": [ + "Even though the query might be more related to the \"politics\" route, it will be classified as \"chitchat\" because we've restricted the routes to consider.\n", + "\n", + "Similarly, we can restrict it to the \"politics\" route:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "1Owt-85Nh6tO", + "outputId": "c5f9024f-7b70-4e3e-dcb1-3cb03688e8e6" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "RouteChoice(name=None, function_call=None, similarity_score=None)" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rl(\"how's the weather today?\", route_filter=[\"politics\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "EyhopRtUh6tP" + }, + "source": [ + "In this case, it will return None because the query doesn't match the \"politics\" route well enough to pass the threshold.\n", + "\n" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "py12", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/indexes/pinecone-local.ipynb b/docs/indexes/pinecone-local.ipynb new file mode 100644 index 00000000..f08f6e2f --- /dev/null +++ b/docs/indexes/pinecone-local.ipynb @@ -0,0 +1,771 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using PineconeLocalIndex for Routes\n", + "\n", + "Pinecone Local is an in-memory Pinecone Database emulator available as a Docker image.\n", + "\n", + "It's useful for running tests using the Pinecone local server. Your data will not leave your system, which is also helpful if you want to do testing locally before committing to a Pinecone account.\n", + "\n", + "## Limitations\n", + "Pinecone Local has the following limitations:\n", + "\n", + "- Pinecone Local is available only as a Docker image.\n", + "- Pinecone Local is an in-memory emulator and is not suitable for production. Records loaded into Pinecone Local do not persist after it is stopped.\n", + "- Pinecone Local does not authenticate client requests. API keys are ignored.\n", + "- Max number of records per index: 100,000.\n", + "\n", + "## Getting Started\n", + "Make sure [Docker](https://docs.docker.com/get-docker/) is installed and running on your local machine.\n", + "\n", + "### Download the latest pinecone-local Docker image:\n", + "\n", + "\n", + "Download the latest pinecone-local Docker image:\n", + "\n", + "```bash\n", + "docker pull ghcr.io/pinecone-io/pinecone-local:latest\n", + "```\n", + "\n", + "### Start Pinecone Local:\n", + "\n", + "```bash\n", + "docker run -d \\\n", + "--name pinecone-local \\\n", + "-e PORT=5080 \\\n", + "-e PINECONE_HOST=localhost \\\n", + "-p 5080-6000:5080-6000 \\\n", + "--platform linux/amd64 \\\n", + "ghcr.io/pinecone-io/pinecone-local:latest\n", + "```\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "!pip install -qU \"semantic-router[pinecone]==0.0.22\"" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\awesome\\anaconda3\\envs\\py12\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "from semantic_router import Route\n", + "\n", + "# we could use this as a guide for our chatbot to avoid political conversations\n", + "politics = Route(\n", + " name=\"politics\",\n", + " utterances=[\n", + " \"isn't politics the best thing ever\",\n", + " \"why don't you tell me about your political opinions\",\n", + " \"don't you just love the president\" \"don't you just hate the president\",\n", + " \"they're going to destroy this country!\",\n", + " \"they will save the country!\",\n", + " ],\n", + ")\n", + "\n", + "# this could be used as an indicator to our chatbot to switch to a more\n", + "# conversational prompt\n", + "chitchat = Route(\n", + " name=\"chitchat\",\n", + " utterances=[\n", + " \"how's the weather today?\",\n", + " \"how are things going?\",\n", + " \"lovely weather today\",\n", + " \"the weather is horrendous\",\n", + " \"let's go to the chippy\",\n", + " ],\n", + ")\n", + "\n", + "# we place both of our decisions together into single list\n", + "routes = [politics, chitchat]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Route(name='politics', utterances=[\"isn't politics the best thing ever\", \"why don't you tell me about your political opinions\", \"don't you just love the presidentdon't you just hate the president\", \"they're going to destroy this country!\", 'they will save the country!'], description=None, function_schemas=None, llm=None, score_threshold=0.5, metadata={}),\n", + " Route(name='chitchat', utterances=[\"how's the weather today?\", 'how are things going?', 'lovely weather today', 'the weather is horrendous', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=0.5, metadata={})]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "routes" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from getpass import getpass\n", + "from semantic_router.encoders import OpenAIEncoder\n", + "\n", + "# get at platform.openai.com\n", + "os.environ.get(\"OPENAI_API_KEY\") or getpass(\"Enter OpenAI API key: \")\n", + "encoder = OpenAIEncoder(\n", + " name=\"text-embedding-3-large\", score_threshold=0.5, dimensions=1536\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For Pinecone Local, you can pass the API key as `pclocal`." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-31 00:33:41 - semantic_router.utils.logger - WARNING - pinecone_local.py:146 - __init__() - Pinecone API key: pclocal\n", + "2025-01-31 00:33:41 - semantic_router.utils.logger - WARNING - pinecone_local.py:147 - __init__() - Pinecone API key os env: pclocal\n", + "2025-01-31 00:33:41 - semantic_router.utils.logger - WARNING - pinecone_local.py:169 - __init__() - Default region changed from us-west-2 to us-east-1 in v0.1.0.dev6\n" + ] + } + ], + "source": [ + "import os\n", + "from semantic_router.index.pinecone_local import PineconeLocalIndex\n", + "\n", + "os.environ[\"PINECONE_API_KEY\"] = os.environ.get(\"PINECONE_API_KEY\") or getpass(\n", + " \"Enter Pinecone API key: \"\n", + ")\n", + "os.environ[\"PINECONE_API_BASE_URL\"] = \"http://localhost:5080\"\n", + "\n", + "index = PineconeLocalIndex(index_name=\"route-test\", dimensions=1536)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-31 00:33:42 - semantic_router.utils.logger - ERROR - pinecone_local.py:271 - _init_index() - index_host exists:http://localhost:5083\n", + "2025-01-31 00:33:42 - semantic_router.utils.logger - ERROR - pinecone_local.py:272 - _init_index() - index exists:\n", + "2025-01-31 00:33:44 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n" + ] + } + ], + "source": [ + "from semantic_router.routers import SemanticRouter\n", + "\n", + "router = SemanticRouter(\n", + " encoder=encoder,\n", + " routes=routes,\n", + " index=index,\n", + " auto_sync=\"local\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can check our route layer and index information." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'http://localhost:5081'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "index.index_host" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'http://localhost:5081'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index.index_host" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'indexes': [{'dimension': 1536,\n", + " 'host': 'localhost:5081',\n", + " 'metric': 'dotproduct',\n", + " 'name': 'route-test',\n", + " 'spec': {'serverless': {'cloud': 'aws', 'region': 'us-east-1'}},\n", + " 'status': {'ready': True, 'state': 'Ready'}}]}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index.client.list_indexes()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index.is_ready()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.is_synced()" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[' chitchat: how are things going?',\n", + " \" chitchat: how's the weather today?\",\n", + " \" chitchat: let's go to the chippy\",\n", + " ' chitchat: lovely weather today',\n", + " ' chitchat: the weather is horrendous',\n", + " \" politics: don't you just love the presidentdon't you just hate the president\",\n", + " \" politics: isn't politics the best thing ever\",\n", + " ' politics: they will save the country!',\n", + " \" politics: they're going to destroy this country!\",\n", + " \" politics: why don't you tell me about your political opinions\"]" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.get_utterance_diff()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-29 23:25:18 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-01-29 23:25:18 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", + "2025-01-29 23:25:18 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['politics', 'politics', 'politics', 'chitchat', 'politics']\n" + ] + }, + { + "data": { + "text/plain": [ + "RouteChoice(name='politics', function_call=None, similarity_score=None)" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router(\"don't you love politics?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['politics', 'chitchat']" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.list_route_names()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-29 23:25:27 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-01-29 23:25:27 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", + "2025-01-29 23:25:27 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['chitchat', 'chitchat', 'chitchat', 'chitchat', 'chitchat']\n" + ] + }, + { + "data": { + "text/plain": [ + "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router(\"how are things going?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(router.index)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also view all of the records for a given route:" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['politics#64069085d9d6e98e5a80915f69fabe82bac6c742f801bc305c5001dce88f0d19',\n", + " 'politics#af8b76111f260cf44fb34f04fcf82927dcbe08e8f47c30f4d571379c1512fac8',\n", + " 'politics#d1bb40236c3d95b9c695bfa86b314b6da4eb87e136699563fccae47fccea23e2',\n", + " 'politics#ed0f3dd7bd5dea12e55b1953bcd2c562a5ab19f501f6d5ff8c8927652c3904b8',\n", + " 'politics#fc6d15f9e6075e6de82b3fbef6722b64353e4eadc8d663b7312a4ed60c43e6f6']" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index._get_route_ids(route_name=\"politics\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And query:" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-29 23:25:42 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-01-29 23:25:42 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", + "2025-01-29 23:25:42 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['politics', 'politics', 'politics', 'chitchat', 'politics']\n" + ] + }, + { + "data": { + "text/plain": [ + "'politics'" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router(\"don't you love politics?\").name" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-29 23:25:43 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-01-29 23:25:43 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", + "2025-01-29 23:25:43 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['chitchat', 'chitchat', 'chitchat', 'chitchat', 'chitchat']\n" + ] + }, + { + "data": { + "text/plain": [ + "'chitchat'" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router(\"how's the weather today?\").name" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-29 23:25:44 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-01-29 23:25:44 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", + "2025-01-29 23:25:44 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['chitchat', 'politics', 'chitchat', 'politics', 'chitchat']\n" + ] + } + ], + "source": [ + "router(\"I'm interested in learning about llama 2\").name" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can delete or update routes." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(router.index)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Deleting a Route from the Semantic Router\n", + "In this section, we demonstrate how to delete a specific route from the `SemanticRouter` instance. This is useful when you want to remove a route that is no longer needed or to update the routing logic dynamically.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-29 23:27:01 - semantic_router.utils.logger - WARNING - pinecone_local.py:628 - _read_config() - Configuration for sr_lock parameter not found in index.\n", + "2025-01-29 23:27:01 - semantic_router.utils.logger - INFO - pinecone_local.py:496 - delete() - Deleted 5 vectors from index route-test.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "index is not None, deleting...\n" + ] + }, + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import time\n", + "\n", + "router.delete(route_name=\"politics\")\n", + "time.sleep(1)\n", + "len(router.index)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-29 23:27:31 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-01-29 23:27:31 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", + "2025-01-29 23:27:31 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['chitchat', 'chitchat', 'chitchat', 'chitchat', 'chitchat']\n" + ] + } + ], + "source": [ + "router(\"don't you love politics??\").name" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Route(name='chitchat', utterances=['how are things going?', \"how's the weather today?\", 'the weather is horrendous', 'lovely weather today', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={})]" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index.get_routes()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Asynchronous Route Query with Semantic Router\n", + "\n", + "In this section, we explore how to perform an asynchronous query using the `SemanticRouter`. This approach is beneficial when you want to handle multiple queries concurrently without blocking the execution of your program." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-01-29 23:27:42 - httpx - INFO - _client.py:1729 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-01-29 23:27:42 - semantic_router.utils.logger - ERROR - pinecone_local.py:796 - _async_query() - current host: http://localhost:5081\n" + ] + }, + { + "data": { + "text/plain": [ + "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "await router.acall(\"how are things going?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'indexes': [{'name': 'route-test',\n", + " 'dimension': 1536,\n", + " 'metric': 'dotproduct',\n", + " 'host': 'localhost:5081',\n", + " 'spec': {'serverless': {'cloud': 'aws', 'region': 'us-east-1'}},\n", + " 'status': {'ready': True, 'state': 'Ready'}}]}" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "await router.index._async_list_indexes()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Stop and remove Pinecone Local\n", + "\n", + "To stop and remove the resources for Pinecone Local, run the following command:\n", + "\n", + "```bash\n", + "docker compose down\n", + "docker stop pinecone-local\n", + "docker rm pinecone-local\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "py12", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/poetry.lock b/poetry.lock index 5c32af55..6ecfef5d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. [[package]] name = "aiofiles" @@ -6,6 +6,7 @@ version = "24.1.0" description = "File support for asyncio." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"}, {file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"}, @@ -17,6 +18,7 @@ version = "2.4.4" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, @@ -28,6 +30,7 @@ version = "3.11.11" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8"}, {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5"}, @@ -126,6 +129,7 @@ version = "1.3.2" description = "aiosignal: a list of registered asynchronous callbacks" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, @@ -140,6 +144,8 @@ version = "0.7.16" description = "A light, configurable Sphinx theme" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, @@ -151,6 +157,7 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -162,6 +169,7 @@ version = "4.8.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, @@ -184,6 +192,8 @@ version = "0.1.4" description = "Disable App Nap on macOS >= 10.9" optional = false python-versions = ">=3.6" +groups = ["dev"] +markers = "platform_system == \"Darwin\"" files = [ {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, @@ -195,6 +205,7 @@ version = "3.0.0" description = "Annotate AST trees with source code positions" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, @@ -210,6 +221,8 @@ version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.11\"" files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -217,13 +230,14 @@ files = [ [[package]] name = "attrs" -version = "24.3.0" +version = "25.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"}, - {file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"}, + {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"}, + {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"}, ] [package.extras] @@ -236,13 +250,14 @@ tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "aurelio-sdk" -version = "0.0.16" +version = "0.0.18" description = "Aurelio Platform SDK" optional = false python-versions = "<4.0,>=3.9" +groups = ["main"] files = [ - {file = "aurelio_sdk-0.0.16-py3-none-any.whl", hash = "sha256:015fb384552fea5541350f1ca1be72c0186b38ecab0a97a2a29ec38e611cfbce"}, - {file = "aurelio_sdk-0.0.16.tar.gz", hash = "sha256:afdbada21d91160044dc8b953eddfb2cdae18f1c2a946098ca3f8057d6bc9ce7"}, + {file = "aurelio_sdk-0.0.18-py3-none-any.whl", hash = "sha256:c990eaccfd7d465a5c70249518cdb09274b42caf1b3c6ff1e16a13a1581d5d26"}, + {file = "aurelio_sdk-0.0.18.tar.gz", hash = "sha256:95d987eb08b526b43734033352f3c7965b0001017c34184dcfaead26dad261d2"}, ] [package.dependencies] @@ -260,6 +275,8 @@ version = "2.16.0" description = "Internationalization utilities" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, @@ -274,6 +291,8 @@ version = "4.12.3" description = "Screen-scraping library" optional = true python-versions = ">=3.6.0" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, @@ -295,6 +314,7 @@ version = "24.4.2" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"}, {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"}, @@ -339,32 +359,36 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.35.97" +version = "1.36.9" description = "The AWS SDK for Python" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"bedrock\"" files = [ - {file = "boto3-1.35.97-py3-none-any.whl", hash = "sha256:8e49416216a6e3a62c2a0c44fba4dd2852c85472e7b702516605b1363867d220"}, - {file = "boto3-1.35.97.tar.gz", hash = "sha256:7d398f66a11e67777c189d1f58c0a75d9d60f98d0ee51b8817e828930bf19e4e"}, + {file = "boto3-1.36.9-py3-none-any.whl", hash = "sha256:440d0b70990efb732f63b40fa16c663c86fee80347eb4bf3bcc08b593e8ac77f"}, + {file = "boto3-1.36.9.tar.gz", hash = "sha256:035ed3868ff3b9afe05a49d0bde35582315bc438e60b5e76727a00b107567bfb"}, ] [package.dependencies] -botocore = ">=1.35.97,<1.36.0" +botocore = ">=1.36.9,<1.37.0" jmespath = ">=0.7.1,<2.0.0" -s3transfer = ">=0.10.0,<0.11.0" +s3transfer = ">=0.11.0,<0.12.0" [package.extras] crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.35.97" +version = "1.36.9" description = "Low-level, data-driven core of boto 3." optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"bedrock\"" files = [ - {file = "botocore-1.35.97-py3-none-any.whl", hash = "sha256:fed4f156b1a9b8ece53738f702ba5851b8c6216b4952de326547f349cc494f14"}, - {file = "botocore-1.35.97.tar.gz", hash = "sha256:88f2fab29192ffe2f2115d5bafbbd823ff4b6eb2774296e03ec8b5b0fe074f61"}, + {file = "botocore-1.36.9-py3-none-any.whl", hash = "sha256:e31d206c7708300c541d0799df73b576bbe7d8bed011687d96323ed48763ffd2"}, + {file = "botocore-1.36.9.tar.gz", hash = "sha256:cb3baefdb8326fdfae0750015e5868330e18d3a088a31da658df2cc8cba7ac73"}, ] [package.dependencies] @@ -376,17 +400,19 @@ urllib3 = [ ] [package.extras] -crt = ["awscrt (==0.22.0)"] +crt = ["awscrt (==0.23.4)"] [[package]] name = "cachetools" -version = "5.5.0" +version = "5.5.1" description = "Extensible memoizing collections and decorators" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ - {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, - {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, + {file = "cachetools-5.5.1-py3-none-any.whl", hash = "sha256:b76651fdc3b24ead3c648bbdeeb940c1b04d365b38b4af66788f9ec4a81d42bb"}, + {file = "cachetools-5.5.1.tar.gz", hash = "sha256:70f238fbba50383ef62e55c6aff6d9673175fe59f7c6782c7a0b9e38f4a9df95"}, ] [[package]] @@ -395,6 +421,7 @@ version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, @@ -406,6 +433,8 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "implementation_name == \"pypy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -485,6 +514,7 @@ version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, @@ -586,30 +616,33 @@ version = "8.1.8" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, ] +markers = {main = "extra == \"hybrid\""} [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "cohere" -version = "5.13.6" +version = "5.13.11" description = "" optional = true python-versions = "<4.0,>=3.9" +groups = ["main"] +markers = "extra == \"cohere\"" files = [ - {file = "cohere-5.13.6-py3-none-any.whl", hash = "sha256:b51519f22785a7e6dbc0b5dd3b1e2c9f6c1062ae96d7e2730b519896f722a66f"}, - {file = "cohere-5.13.6.tar.gz", hash = "sha256:0fc723dcb85a2f7ccd5478fce48701b226bf8cdb0df46c06ae09f242f44668a3"}, + {file = "cohere-5.13.11-py3-none-any.whl", hash = "sha256:9237e15f5abcda6ecf8252b6784d5424024986316ae319cb266c05d79ca3de83"}, + {file = "cohere-5.13.11.tar.gz", hash = "sha256:85d2c1a28ac83d3479a5c1ca6cdf97bb52794714c7fde054eb936cfeafaf57f6"}, ] [package.dependencies] fastavro = ">=1.9.4,<2.0.0" httpx = ">=0.21.2" httpx-sse = "0.4.0" -parameterized = ">=0.9.0,<0.10.0" pydantic = ">=1.9.2" pydantic-core = ">=2.18.2,<3.0.0" requests = ">=2.0.0,<3.0.0" @@ -623,6 +656,7 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -634,6 +668,8 @@ version = "15.0.1" description = "Colored terminal output for Python's logging module" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\"" files = [ {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, @@ -651,6 +687,7 @@ version = "6.9.0" description = "Add colours to the output of Python's logging module." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "colorlog-6.9.0-py3-none-any.whl", hash = "sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff"}, {file = "colorlog-6.9.0.tar.gz", hash = "sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2"}, @@ -668,6 +705,7 @@ version = "0.2.2" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3"}, {file = "comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e"}, @@ -685,6 +723,7 @@ version = "7.6.10" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78"}, {file = "coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c"}, @@ -758,37 +797,38 @@ toml = ["tomli"] [[package]] name = "debugpy" -version = "1.8.11" +version = "1.8.12" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" -files = [ - {file = "debugpy-1.8.11-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:2b26fefc4e31ff85593d68b9022e35e8925714a10ab4858fb1b577a8a48cb8cd"}, - {file = "debugpy-1.8.11-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61bc8b3b265e6949855300e84dc93d02d7a3a637f2aec6d382afd4ceb9120c9f"}, - {file = "debugpy-1.8.11-cp310-cp310-win32.whl", hash = "sha256:c928bbf47f65288574b78518449edaa46c82572d340e2750889bbf8cd92f3737"}, - {file = "debugpy-1.8.11-cp310-cp310-win_amd64.whl", hash = "sha256:8da1db4ca4f22583e834dcabdc7832e56fe16275253ee53ba66627b86e304da1"}, - {file = "debugpy-1.8.11-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:85de8474ad53ad546ff1c7c7c89230db215b9b8a02754d41cb5a76f70d0be296"}, - {file = "debugpy-1.8.11-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ffc382e4afa4aee367bf413f55ed17bd91b191dcaf979890af239dda435f2a1"}, - {file = "debugpy-1.8.11-cp311-cp311-win32.whl", hash = "sha256:40499a9979c55f72f4eb2fc38695419546b62594f8af194b879d2a18439c97a9"}, - {file = "debugpy-1.8.11-cp311-cp311-win_amd64.whl", hash = "sha256:987bce16e86efa86f747d5151c54e91b3c1e36acc03ce1ddb50f9d09d16ded0e"}, - {file = "debugpy-1.8.11-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:84e511a7545d11683d32cdb8f809ef63fc17ea2a00455cc62d0a4dbb4ed1c308"}, - {file = "debugpy-1.8.11-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce291a5aca4985d82875d6779f61375e959208cdf09fcec40001e65fb0a54768"}, - {file = "debugpy-1.8.11-cp312-cp312-win32.whl", hash = "sha256:28e45b3f827d3bf2592f3cf7ae63282e859f3259db44ed2b129093ca0ac7940b"}, - {file = "debugpy-1.8.11-cp312-cp312-win_amd64.whl", hash = "sha256:44b1b8e6253bceada11f714acf4309ffb98bfa9ac55e4fce14f9e5d4484287a1"}, - {file = "debugpy-1.8.11-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:8988f7163e4381b0da7696f37eec7aca19deb02e500245df68a7159739bbd0d3"}, - {file = "debugpy-1.8.11-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c1f6a173d1140e557347419767d2b14ac1c9cd847e0b4c5444c7f3144697e4e"}, - {file = "debugpy-1.8.11-cp313-cp313-win32.whl", hash = "sha256:bb3b15e25891f38da3ca0740271e63ab9db61f41d4d8541745cfc1824252cb28"}, - {file = "debugpy-1.8.11-cp313-cp313-win_amd64.whl", hash = "sha256:d8768edcbeb34da9e11bcb8b5c2e0958d25218df7a6e56adf415ef262cd7b6d1"}, - {file = "debugpy-1.8.11-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:ad7efe588c8f5cf940f40c3de0cd683cc5b76819446abaa50dc0829a30c094db"}, - {file = "debugpy-1.8.11-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:189058d03a40103a57144752652b3ab08ff02b7595d0ce1f651b9acc3a3a35a0"}, - {file = "debugpy-1.8.11-cp38-cp38-win32.whl", hash = "sha256:32db46ba45849daed7ccf3f2e26f7a386867b077f39b2a974bb5c4c2c3b0a280"}, - {file = "debugpy-1.8.11-cp38-cp38-win_amd64.whl", hash = "sha256:116bf8342062246ca749013df4f6ea106f23bc159305843491f64672a55af2e5"}, - {file = "debugpy-1.8.11-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:654130ca6ad5de73d978057eaf9e582244ff72d4574b3e106fb8d3d2a0d32458"}, - {file = "debugpy-1.8.11-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23dc34c5e03b0212fa3c49a874df2b8b1b8fda95160bd79c01eb3ab51ea8d851"}, - {file = "debugpy-1.8.11-cp39-cp39-win32.whl", hash = "sha256:52d8a3166c9f2815bfae05f386114b0b2d274456980d41f320299a8d9a5615a7"}, - {file = "debugpy-1.8.11-cp39-cp39-win_amd64.whl", hash = "sha256:52c3cf9ecda273a19cc092961ee34eb9ba8687d67ba34cc7b79a521c1c64c4c0"}, - {file = "debugpy-1.8.11-py2.py3-none-any.whl", hash = "sha256:0e22f846f4211383e6a416d04b4c13ed174d24cc5d43f5fd52e7821d0ebc8920"}, - {file = "debugpy-1.8.11.tar.gz", hash = "sha256:6ad2688b69235c43b020e04fecccdf6a96c8943ca9c2fb340b8adc103c655e57"}, +groups = ["dev"] +files = [ + {file = "debugpy-1.8.12-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:a2ba7ffe58efeae5b8fad1165357edfe01464f9aef25e814e891ec690e7dd82a"}, + {file = "debugpy-1.8.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbbd4149c4fc5e7d508ece083e78c17442ee13b0e69bfa6bd63003e486770f45"}, + {file = "debugpy-1.8.12-cp310-cp310-win32.whl", hash = "sha256:b202f591204023b3ce62ff9a47baa555dc00bb092219abf5caf0e3718ac20e7c"}, + {file = "debugpy-1.8.12-cp310-cp310-win_amd64.whl", hash = "sha256:9649eced17a98ce816756ce50433b2dd85dfa7bc92ceb60579d68c053f98dff9"}, + {file = "debugpy-1.8.12-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:36f4829839ef0afdfdd208bb54f4c3d0eea86106d719811681a8627ae2e53dd5"}, + {file = "debugpy-1.8.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a28ed481d530e3138553be60991d2d61103ce6da254e51547b79549675f539b7"}, + {file = "debugpy-1.8.12-cp311-cp311-win32.whl", hash = "sha256:4ad9a94d8f5c9b954e0e3b137cc64ef3f579d0df3c3698fe9c3734ee397e4abb"}, + {file = "debugpy-1.8.12-cp311-cp311-win_amd64.whl", hash = "sha256:4703575b78dd697b294f8c65588dc86874ed787b7348c65da70cfc885efdf1e1"}, + {file = "debugpy-1.8.12-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498"}, + {file = "debugpy-1.8.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06"}, + {file = "debugpy-1.8.12-cp312-cp312-win32.whl", hash = "sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d"}, + {file = "debugpy-1.8.12-cp312-cp312-win_amd64.whl", hash = "sha256:39dfbb6fa09f12fae32639e3286112fc35ae976114f1f3d37375f3130a820969"}, + {file = "debugpy-1.8.12-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:696d8ae4dff4cbd06bf6b10d671e088b66669f110c7c4e18a44c43cf75ce966f"}, + {file = "debugpy-1.8.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:898fba72b81a654e74412a67c7e0a81e89723cfe2a3ea6fcd3feaa3395138ca9"}, + {file = "debugpy-1.8.12-cp313-cp313-win32.whl", hash = "sha256:22a11c493c70413a01ed03f01c3c3a2fc4478fc6ee186e340487b2edcd6f4180"}, + {file = "debugpy-1.8.12-cp313-cp313-win_amd64.whl", hash = "sha256:fdb3c6d342825ea10b90e43d7f20f01535a72b3a1997850c0c3cefa5c27a4a2c"}, + {file = "debugpy-1.8.12-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:b0232cd42506d0c94f9328aaf0d1d0785f90f87ae72d9759df7e5051be039738"}, + {file = "debugpy-1.8.12-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9af40506a59450f1315168d47a970db1a65aaab5df3833ac389d2899a5d63b3f"}, + {file = "debugpy-1.8.12-cp38-cp38-win32.whl", hash = "sha256:5cc45235fefac57f52680902b7d197fb2f3650112379a6fa9aa1b1c1d3ed3f02"}, + {file = "debugpy-1.8.12-cp38-cp38-win_amd64.whl", hash = "sha256:557cc55b51ab2f3371e238804ffc8510b6ef087673303890f57a24195d096e61"}, + {file = "debugpy-1.8.12-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:b5c6c967d02fee30e157ab5227706f965d5c37679c687b1e7bbc5d9e7128bd41"}, + {file = "debugpy-1.8.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a77f422f31f170c4b7e9ca58eae2a6c8e04da54121900651dfa8e66c29901a"}, + {file = "debugpy-1.8.12-cp39-cp39-win32.whl", hash = "sha256:a4042edef80364239f5b7b5764e55fd3ffd40c32cf6753da9bda4ff0ac466018"}, + {file = "debugpy-1.8.12-cp39-cp39-win_amd64.whl", hash = "sha256:f30b03b0f27608a0b26c75f0bb8a880c752c0e0b01090551b9d87c7d783e2069"}, + {file = "debugpy-1.8.12-py2.py3-none-any.whl", hash = "sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6"}, + {file = "debugpy-1.8.12.tar.gz", hash = "sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce"}, ] [[package]] @@ -797,6 +837,7 @@ version = "5.1.1" description = "Decorators for Humans" optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, @@ -808,6 +849,8 @@ version = "5.6.3" description = "Disk Cache -- Disk and file backed persistent cache." optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"local\"" files = [ {file = "diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19"}, {file = "diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc"}, @@ -819,6 +862,7 @@ version = "1.9.0" description = "Distro - an OS platform information API" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, @@ -830,6 +874,8 @@ version = "0.16" description = "Parse Python docstrings in reST, Google and Numpydoc format" optional = true python-versions = ">=3.6,<4.0" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "docstring_parser-0.16-py3-none-any.whl", hash = "sha256:bf0a1387354d3691d102edef7ec124f219ef639982d096e26e3b60aeffa90637"}, {file = "docstring_parser-0.16.tar.gz", hash = "sha256:538beabd0af1e2db0146b6bd3caa526c35a34d61af9fd2887f3a8a27a739aa6e"}, @@ -841,6 +887,8 @@ version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, @@ -852,6 +900,8 @@ version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -866,6 +916,7 @@ version = "2.1.1" description = "execnet: rapid multi-Python deployment" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, @@ -876,13 +927,14 @@ testing = ["hatch", "pre-commit", "pytest", "tox"] [[package]] name = "executing" -version = "2.1.0" +version = "2.2.0" description = "Get the currently executing AST node of a frame, and other information" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf"}, - {file = "executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab"}, + {file = "executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa"}, + {file = "executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755"}, ] [package.extras] @@ -894,6 +946,8 @@ version = "1.10.0" description = "Fast read/write of AVRO files" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"cohere\"" files = [ {file = "fastavro-1.10.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1a9fe0672d2caf0fe54e3be659b13de3cad25a267f2073d6f4b9f8862acc31eb"}, {file = "fastavro-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86dd0410770e0c99363788f0584523709d85e57bb457372ec5c285a482c17fe6"}, @@ -940,6 +994,8 @@ version = "0.3.6" description = "Fast, light, accurate library built for retrieval embedding generation" optional = true python-versions = "<3.13,>=3.8.0" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\"" files = [ {file = "fastembed-0.3.6-py3-none-any.whl", hash = "sha256:2bf70edae28bb4ccd9e01617098c2075b0ba35b88025a3d22b0e1e85b2c488ce"}, {file = "fastembed-0.3.6.tar.gz", hash = "sha256:c93c8ec99b8c008c2d192d6297866b8d70ec7ac8f5696b34eb5ea91f85efd15f"}, @@ -964,29 +1020,33 @@ tqdm = ">=4.66,<5.0" [[package]] name = "filelock" -version = "3.16.1" +version = "3.17.0" description = "A platform independent file lock." optional = true -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] +markers = "(extra == \"cohere\" or extra == \"local\" or extra == \"vision\" or extra == \"fastembed\") and (extra == \"cohere\" or python_version < \"3.13\")" files = [ - {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, - {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, + {file = "filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338"}, + {file = "filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "flatbuffers" -version = "24.12.23" +version = "25.1.24" description = "The FlatBuffers serialization format for Python" optional = true python-versions = "*" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\"" files = [ - {file = "flatbuffers-24.12.23-py2.py3-none-any.whl", hash = "sha256:c418e0d48890f4142b92fd3e343e73a48f194e1f80075ddcc5793779b3585444"}, - {file = "flatbuffers-24.12.23.tar.gz", hash = "sha256:2910b0bc6ae9b6db78dd2b18d0b7a0709ba240fb5585f286a3a2b30785c22dac"}, + {file = "flatbuffers-25.1.24-py2.py3-none-any.whl", hash = "sha256:1abfebaf4083117225d0723087ea909896a34e3fec933beedb490d595ba24145"}, + {file = "flatbuffers-25.1.24.tar.gz", hash = "sha256:e0f7b7d806c0abdf166275492663130af40c11f89445045fbef0aa3c9a8643ad"}, ] [[package]] @@ -995,6 +1055,7 @@ version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, @@ -1096,6 +1157,8 @@ version = "2024.12.0" description = "File-system specification" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "(extra == \"cohere\" or extra == \"local\" or extra == \"vision\" or extra == \"fastembed\") and (extra == \"cohere\" or python_version < \"3.13\")" files = [ {file = "fsspec-2024.12.0-py3-none-any.whl", hash = "sha256:b520aed47ad9804237ff878b504267a3b0b441e97508bd6d2d8774e3db85cee2"}, {file = "fsspec-2024.12.0.tar.gz", hash = "sha256:670700c977ed2fb51e0d9f9253177ed20cbde4a3e5c0283cc5385b5870c8533f"}, @@ -1131,13 +1194,15 @@ tqdm = ["tqdm"] [[package]] name = "google-api-core" -version = "2.24.0" +version = "2.24.1" description = "Google API client core library" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ - {file = "google_api_core-2.24.0-py3-none-any.whl", hash = "sha256:10d82ac0fca69c82a25b3efdeefccf6f28e02ebb97925a8cce8edbfe379929d9"}, - {file = "google_api_core-2.24.0.tar.gz", hash = "sha256:e255640547a597a4da010876d333208ddac417d60add22b6851a0c66a831fcaf"}, + {file = "google_api_core-2.24.1-py3-none-any.whl", hash = "sha256:bc78d608f5a5bf853b80bd70a795f703294de656c096c0968320830a4bc280f1"}, + {file = "google_api_core-2.24.1.tar.gz", hash = "sha256:f8b36f5456ab0dd99a1b693a40a31d1e7757beea380ad1b38faaf8941eae9d8a"}, ] [package.dependencies] @@ -1166,13 +1231,15 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] [[package]] name = "google-auth" -version = "2.37.0" +version = "2.38.0" description = "Google Authentication Library" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ - {file = "google_auth-2.37.0-py2.py3-none-any.whl", hash = "sha256:42664f18290a6be591be5329a96fe30184be1a1badb7292a7f686a9659de9ca0"}, - {file = "google_auth-2.37.0.tar.gz", hash = "sha256:0054623abf1f9c83492c63d3f47e77f0a544caa3d40b2d98e099a611c2dd5d00"}, + {file = "google_auth-2.38.0-py2.py3-none-any.whl", hash = "sha256:e7dae6694313f434a2727bf2906f27ad259bae090d7aa896590d86feec3d9d4a"}, + {file = "google_auth-2.38.0.tar.gz", hash = "sha256:8285113607d3b80a3f1543b75962447ba8a09fe85783432a784fdeef6ac094c4"}, ] [package.dependencies] @@ -1190,13 +1257,15 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"] [[package]] name = "google-cloud-aiplatform" -version = "1.76.0" +version = "1.79.0" description = "Vertex AI API client library" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"google\"" files = [ - {file = "google_cloud_aiplatform-1.76.0-py2.py3-none-any.whl", hash = "sha256:0b0348525b9528db7b69538ff6e86289ea2ce0d80f3784a42865fc994fe10dd1"}, - {file = "google_cloud_aiplatform-1.76.0.tar.gz", hash = "sha256:910fb7fb6ef7ec73a48523872d669370755f59ac6d764dc8bf2fc91e7c0b2fca"}, + {file = "google_cloud_aiplatform-1.79.0-py2.py3-none-any.whl", hash = "sha256:e52d518c386ce2b4ce57f1b73b46c57531d9a6ccd70c21a37b349f428bfc1c3f"}, + {file = "google_cloud_aiplatform-1.79.0.tar.gz", hash = "sha256:362bfd16716dcfb6c131736f25246790002b29c99a246fcf4c08a7c71bd2301f"}, ] [package.dependencies] @@ -1218,10 +1287,10 @@ autologging = ["mlflow (>=1.27.0,<=2.16.0)"] cloud-profiler = ["tensorboard-plugin-profile (>=2.4.0,<2.18.0)", "tensorflow (>=2.4.0,<3.0.0dev)", "werkzeug (>=2.0.0,<2.1.0dev)"] datasets = ["pyarrow (>=10.0.1)", "pyarrow (>=14.0.0)", "pyarrow (>=3.0.0,<8.0dev)"] endpoint = ["requests (>=2.28.1)"] -evaluation = ["pandas (>=1.0.0)", "tqdm (>=4.23.0)"] -full = ["docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<=0.114.0)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-vizier (>=0.1.6)", "httpx (>=0.23.0,<0.25.0)", "immutabledict", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.16.0)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pyarrow (>=10.0.1)", "pyarrow (>=14.0.0)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pyyaml (>=5.3.1,<7)", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<2.10.dev0 || >=2.33.dev0,<=2.33.0)", "ray[default] (>=2.5,<=2.33.0)", "requests (>=2.28.1)", "setuptools (<70.0.0)", "starlette (>=0.17.1)", "tensorboard-plugin-profile (>=2.4.0,<2.18.0)", "tensorflow (>=2.3.0,<3.0.0dev)", "tensorflow (>=2.3.0,<3.0.0dev)", "tensorflow (>=2.4.0,<3.0.0dev)", "tqdm (>=4.23.0)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)", "werkzeug (>=2.0.0,<2.1.0dev)"] -langchain = ["langchain (>=0.1.16,<0.4)", "langchain-core (<0.4)", "langchain-google-vertexai (<3)", "openinference-instrumentation-langchain (>=0.1.19,<0.2)"] -langchain-testing = ["absl-py", "cloudpickle (>=3.0,<4.0)", "google-cloud-trace (<2)", "langchain (>=0.1.16,<0.4)", "langchain-core (<0.4)", "langchain-google-vertexai (<3)", "openinference-instrumentation-langchain (>=0.1.19,<0.2)", "opentelemetry-exporter-gcp-trace (<2)", "opentelemetry-sdk (<2)", "pydantic (>=2.6.3,<3)", "pytest-xdist", "typing-extensions"] +evaluation = ["pandas (>=1.0.0)", "scikit-learn", "scikit-learn (<1.6.0)", "tqdm (>=4.23.0)"] +full = ["docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<=0.114.0)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-vizier (>=0.1.6)", "httpx (>=0.23.0,<0.25.0)", "immutabledict", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.16.0)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pyarrow (>=10.0.1)", "pyarrow (>=14.0.0)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pyyaml (>=5.3.1,<7)", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<2.10.dev0 || >=2.33.dev0,<=2.33.0)", "ray[default] (>=2.5,<=2.33.0)", "requests (>=2.28.1)", "scikit-learn", "scikit-learn (<1.6.0)", "setuptools (<70.0.0)", "starlette (>=0.17.1)", "tensorboard-plugin-profile (>=2.4.0,<2.18.0)", "tensorflow (>=2.3.0,<3.0.0dev)", "tensorflow (>=2.3.0,<3.0.0dev)", "tensorflow (>=2.4.0,<3.0.0dev)", "tqdm (>=4.23.0)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)", "werkzeug (>=2.0.0,<2.1.0dev)"] +langchain = ["langchain (>=0.1.16,<0.4)", "langchain-core (<0.4)", "langchain-google-vertexai (<3)", "langgraph (>=0.2.45,<0.3)", "openinference-instrumentation-langchain (>=0.1.19,<0.2)"] +langchain-testing = ["absl-py", "cloudpickle (>=3.0,<4.0)", "google-cloud-trace (<2)", "langchain (>=0.1.16,<0.4)", "langchain-core (<0.4)", "langchain-google-vertexai (<3)", "langgraph (>=0.2.45,<0.3)", "openinference-instrumentation-langchain (>=0.1.19,<0.2)", "opentelemetry-exporter-gcp-trace (<2)", "opentelemetry-sdk (<2)", "pydantic (>=2.6.3,<3)", "pytest-xdist", "typing-extensions"] lit = ["explainable-ai-sdk (>=1.0.0)", "lit-nlp (==0.4.0)", "pandas (>=1.0.0)", "tensorflow (>=2.3.0,<3.0.0dev)"] metadata = ["numpy (>=1.15.0)", "pandas (>=1.0.0)"] pipelines = ["pyyaml (>=5.3.1,<7)"] @@ -1238,13 +1307,15 @@ xai = ["tensorflow (>=2.3.0,<3.0.0dev)"] [[package]] name = "google-cloud-bigquery" -version = "3.27.0" +version = "3.29.0" description = "Google BigQuery API client library" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ - {file = "google_cloud_bigquery-3.27.0-py2.py3-none-any.whl", hash = "sha256:b53b0431e5ba362976a4cd8acce72194b4116cdf8115030c7b339b884603fcc3"}, - {file = "google_cloud_bigquery-3.27.0.tar.gz", hash = "sha256:379c524054d7b090fa56d0c22662cc6e6458a6229b6754c0e7177e3a73421d2c"}, + {file = "google_cloud_bigquery-3.29.0-py2.py3-none-any.whl", hash = "sha256:5453a4eabe50118254eda9778f3d7dad413490de5f7046b5e66c98f5a1580308"}, + {file = "google_cloud_bigquery-3.29.0.tar.gz", hash = "sha256:fafc2b455ffce3bcc6ce0e884184ef50b6a11350a83b91e327fadda4d5566e72"}, ] [package.dependencies] @@ -1257,10 +1328,10 @@ python-dateutil = ">=2.7.3,<3.0dev" requests = ">=2.21.0,<3.0.0dev" [package.extras] -all = ["Shapely (>=1.8.4,<3.0.0dev)", "bigquery-magics (>=0.1.0)", "db-dtypes (>=0.3.0,<2.0.0dev)", "geopandas (>=0.9.0,<1.0dev)", "google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "importlib-metadata (>=1.0.0)", "ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)", "opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)", "pandas (>=1.1.0)", "proto-plus (>=1.22.3,<2.0.0dev)", "protobuf (>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev)", "pyarrow (>=3.0.0)", "tqdm (>=4.7.4,<5.0.0dev)"] +all = ["google-cloud-bigquery[bigquery-v2,bqstorage,geopandas,ipython,ipywidgets,opentelemetry,pandas,tqdm]"] bigquery-v2 = ["proto-plus (>=1.22.3,<2.0.0dev)", "protobuf (>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev)"] bqstorage = ["google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "pyarrow (>=3.0.0)"] -geopandas = ["Shapely (>=1.8.4,<3.0.0dev)", "geopandas (>=0.9.0,<1.0dev)"] +geopandas = ["Shapely (>=1.8.4,<3.0.0dev)", "geopandas (>=0.9.0,<2.0dev)"] ipython = ["bigquery-magics (>=0.1.0)"] ipywidgets = ["ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)"] opentelemetry = ["opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)"] @@ -1273,6 +1344,8 @@ version = "2.4.1" description = "Google Cloud API client core library" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"}, {file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"}, @@ -1291,6 +1364,8 @@ version = "1.14.0" description = "Google Cloud Resource Manager API client library" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "google_cloud_resource_manager-1.14.0-py2.py3-none-any.whl", hash = "sha256:4860c3ea9ace760b317ea90d4e27f1b32e54ededdcc340a7cb70c8ef238d8f7c"}, {file = "google_cloud_resource_manager-1.14.0.tar.gz", hash = "sha256:daa70a3a4704759d31f812ed221e3b6f7b660af30c7862e4a0060ea91291db30"}, @@ -1312,6 +1387,8 @@ version = "2.19.0" description = "Google Cloud Storage API client library" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "google_cloud_storage-2.19.0-py2.py3-none-any.whl", hash = "sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba"}, {file = "google_cloud_storage-2.19.0.tar.gz", hash = "sha256:cd05e9e7191ba6cb68934d8eb76054d9be4562aa89dbc4236feee4d7d51342b2"}, @@ -1335,6 +1412,8 @@ version = "1.6.0" description = "A python wrapper of the C library 'Google CRC32C'" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5bcc90b34df28a4b38653c36bb5ada35671ad105c99cfe915fb5bed7ad6924aa"}, {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d9e9913f7bd69e093b81da4535ce27af842e7bf371cde42d1ae9e9bd382dc0e9"}, @@ -1374,6 +1453,8 @@ version = "2.7.2" description = "Utilities for Google Media Downloads and Resumable Uploads" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa"}, {file = "google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0"}, @@ -1392,6 +1473,8 @@ version = "1.66.0" description = "Common protobufs used in Google APIs" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "googleapis_common_protos-1.66.0-py2.py3-none-any.whl", hash = "sha256:d7abcd75fabb2e0ec9f74466401f6c119a0b498e27370e9be4c94cb7e382b8ed"}, {file = "googleapis_common_protos-1.66.0.tar.gz", hash = "sha256:c3e7b33d15fdca5374cc0a7346dd92ffa847425cc4ea941d970f13680052ec8c"}, @@ -1410,6 +1493,8 @@ version = "0.14.0" description = "IAM API client library" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "grpc_google_iam_v1-0.14.0-py2.py3-none-any.whl", hash = "sha256:fb4a084b30099ba3ab07d61d620a0d4429570b13ff53bd37bac75235f98b7da4"}, {file = "grpc_google_iam_v1-0.14.0.tar.gz", hash = "sha256:c66e07aa642e39bb37950f9e7f491f70dad150ac9801263b42b2814307c2df99"}, @@ -1422,153 +1507,159 @@ protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4 [[package]] name = "grpcio" -version = "1.69.0" +version = "1.70.0" description = "HTTP/2-based RPC framework" optional = true python-versions = ">=3.8" -files = [ - {file = "grpcio-1.69.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:2060ca95a8db295ae828d0fc1c7f38fb26ccd5edf9aa51a0f44251f5da332e97"}, - {file = "grpcio-1.69.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:2e52e107261fd8fa8fa457fe44bfadb904ae869d87c1280bf60f93ecd3e79278"}, - {file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:316463c0832d5fcdb5e35ff2826d9aa3f26758d29cdfb59a368c1d6c39615a11"}, - {file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26c9a9c4ac917efab4704b18eed9082ed3b6ad19595f047e8173b5182fec0d5e"}, - {file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90b3646ced2eae3a0599658eeccc5ba7f303bf51b82514c50715bdd2b109e5ec"}, - {file = "grpcio-1.69.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3b75aea7c6cb91b341c85e7c1d9db1e09e1dd630b0717f836be94971e015031e"}, - {file = "grpcio-1.69.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5cfd14175f9db33d4b74d63de87c64bb0ee29ce475ce3c00c01ad2a3dc2a9e51"}, - {file = "grpcio-1.69.0-cp310-cp310-win32.whl", hash = "sha256:9031069d36cb949205293cf0e243abd5e64d6c93e01b078c37921493a41b72dc"}, - {file = "grpcio-1.69.0-cp310-cp310-win_amd64.whl", hash = "sha256:cc89b6c29f3dccbe12d7a3b3f1b3999db4882ae076c1c1f6df231d55dbd767a5"}, - {file = "grpcio-1.69.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:8de1b192c29b8ce45ee26a700044717bcbbd21c697fa1124d440548964328561"}, - {file = "grpcio-1.69.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:7e76accf38808f5c5c752b0ab3fd919eb14ff8fafb8db520ad1cc12afff74de6"}, - {file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:d5658c3c2660417d82db51e168b277e0ff036d0b0f859fa7576c0ffd2aec1442"}, - {file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5494d0e52bf77a2f7eb17c6da662886ca0a731e56c1c85b93505bece8dc6cf4c"}, - {file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ed866f9edb574fd9be71bf64c954ce1b88fc93b2a4cbf94af221e9426eb14d6"}, - {file = "grpcio-1.69.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c5ba38aeac7a2fe353615c6b4213d1fbb3a3c34f86b4aaa8be08baaaee8cc56d"}, - {file = "grpcio-1.69.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f79e05f5bbf551c4057c227d1b041ace0e78462ac8128e2ad39ec58a382536d2"}, - {file = "grpcio-1.69.0-cp311-cp311-win32.whl", hash = "sha256:bf1f8be0da3fcdb2c1e9f374f3c2d043d606d69f425cd685110dd6d0d2d61258"}, - {file = "grpcio-1.69.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb9302afc3a0e4ba0b225cd651ef8e478bf0070cf11a529175caecd5ea2474e7"}, - {file = "grpcio-1.69.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:fc18a4de8c33491ad6f70022af5c460b39611e39578a4d84de0fe92f12d5d47b"}, - {file = "grpcio-1.69.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:0f0270bd9ffbff6961fe1da487bdcd594407ad390cc7960e738725d4807b18c4"}, - {file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:dc48f99cc05e0698e689b51a05933253c69a8c8559a47f605cff83801b03af0e"}, - {file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e925954b18d41aeb5ae250262116d0970893b38232689c4240024e4333ac084"}, - {file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87d222569273720366f68a99cb62e6194681eb763ee1d3b1005840678d4884f9"}, - {file = "grpcio-1.69.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b62b0f41e6e01a3e5082000b612064c87c93a49b05f7602fe1b7aa9fd5171a1d"}, - {file = "grpcio-1.69.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:db6f9fd2578dbe37db4b2994c94a1d9c93552ed77dca80e1657bb8a05b898b55"}, - {file = "grpcio-1.69.0-cp312-cp312-win32.whl", hash = "sha256:b192b81076073ed46f4b4dd612b8897d9a1e39d4eabd822e5da7b38497ed77e1"}, - {file = "grpcio-1.69.0-cp312-cp312-win_amd64.whl", hash = "sha256:1227ff7836f7b3a4ab04e5754f1d001fa52a730685d3dc894ed8bc262cc96c01"}, - {file = "grpcio-1.69.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:a78a06911d4081a24a1761d16215a08e9b6d4d29cdbb7e427e6c7e17b06bcc5d"}, - {file = "grpcio-1.69.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:dc5a351927d605b2721cbb46158e431dd49ce66ffbacb03e709dc07a491dde35"}, - {file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:3629d8a8185f5139869a6a17865d03113a260e311e78fbe313f1a71603617589"}, - {file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9a281878feeb9ae26db0622a19add03922a028d4db684658f16d546601a4870"}, - {file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc614e895177ab7e4b70f154d1a7c97e152577ea101d76026d132b7aaba003b"}, - {file = "grpcio-1.69.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:1ee76cd7e2e49cf9264f6812d8c9ac1b85dda0eaea063af07292400f9191750e"}, - {file = "grpcio-1.69.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:0470fa911c503af59ec8bc4c82b371ee4303ececbbdc055f55ce48e38b20fd67"}, - {file = "grpcio-1.69.0-cp313-cp313-win32.whl", hash = "sha256:b650f34aceac8b2d08a4c8d7dc3e8a593f4d9e26d86751ebf74ebf5107d927de"}, - {file = "grpcio-1.69.0-cp313-cp313-win_amd64.whl", hash = "sha256:028337786f11fecb5d7b7fa660475a06aabf7e5e52b5ac2df47414878c0ce7ea"}, - {file = "grpcio-1.69.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:b7f693db593d6bf285e015d5538bf1c86cf9c60ed30b6f7da04a00ed052fe2f3"}, - {file = "grpcio-1.69.0-cp38-cp38-macosx_10_14_universal2.whl", hash = "sha256:8b94e83f66dbf6fd642415faca0608590bc5e8d30e2c012b31d7d1b91b1de2fd"}, - {file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:b634851b92c090763dde61df0868c730376cdb73a91bcc821af56ae043b09596"}, - {file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bf5f680d3ed08c15330d7830d06bc65f58ca40c9999309517fd62880d70cb06e"}, - {file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:200e48a6e7b00f804cf00a1c26292a5baa96507c7749e70a3ec10ca1a288936e"}, - {file = "grpcio-1.69.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:45a4704339b6e5b24b0e136dea9ad3815a94f30eb4f1e1d44c4ac484ef11d8dd"}, - {file = "grpcio-1.69.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:85d347cb8237751b23539981dbd2d9d8f6e9ff90082b427b13022b948eb6347a"}, - {file = "grpcio-1.69.0-cp38-cp38-win32.whl", hash = "sha256:60e5de105dc02832dc8f120056306d0ef80932bcf1c0e2b4ca3b676de6dc6505"}, - {file = "grpcio-1.69.0-cp38-cp38-win_amd64.whl", hash = "sha256:282f47d0928e40f25d007f24eb8fa051cb22551e3c74b8248bc9f9bea9c35fe0"}, - {file = "grpcio-1.69.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:dd034d68a2905464c49479b0c209c773737a4245d616234c79c975c7c90eca03"}, - {file = "grpcio-1.69.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:01f834732c22a130bdf3dc154d1053bdbc887eb3ccb7f3e6285cfbfc33d9d5cc"}, - {file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:a7f4ed0dcf202a70fe661329f8874bc3775c14bb3911d020d07c82c766ce0eb1"}, - {file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd7ea241b10bc5f0bb0f82c0d7896822b7ed122b3ab35c9851b440c1ccf81588"}, - {file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f03dc9b4da4c0dc8a1db7a5420f575251d7319b7a839004d8916257ddbe4816"}, - {file = "grpcio-1.69.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ca71d73a270dff052fe4edf74fef142d6ddd1f84175d9ac4a14b7280572ac519"}, - {file = "grpcio-1.69.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ccbed100dc43704e94ccff9e07680b540d64e4cc89213ab2832b51b4f68a520"}, - {file = "grpcio-1.69.0-cp39-cp39-win32.whl", hash = "sha256:1514341def9c6ec4b7f0b9628be95f620f9d4b99331b7ef0a1845fd33d9b579c"}, - {file = "grpcio-1.69.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1fea55d26d647346acb0069b08dca70984101f2dc95066e003019207212e303"}, - {file = "grpcio-1.69.0.tar.gz", hash = "sha256:936fa44241b5379c5afc344e1260d467bee495747eaf478de825bab2791da6f5"}, +groups = ["main"] +markers = "extra == \"google\" or extra == \"qdrant\"" +files = [ + {file = "grpcio-1.70.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:95469d1977429f45fe7df441f586521361e235982a0b39e33841549143ae2851"}, + {file = "grpcio-1.70.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:ed9718f17fbdb472e33b869c77a16d0b55e166b100ec57b016dc7de9c8d236bf"}, + {file = "grpcio-1.70.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:374d014f29f9dfdb40510b041792e0e2828a1389281eb590df066e1cc2b404e5"}, + {file = "grpcio-1.70.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2af68a6f5c8f78d56c145161544ad0febbd7479524a59c16b3e25053f39c87f"}, + {file = "grpcio-1.70.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7df14b2dcd1102a2ec32f621cc9fab6695effef516efbc6b063ad749867295"}, + {file = "grpcio-1.70.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c78b339869f4dbf89881e0b6fbf376313e4f845a42840a7bdf42ee6caed4b11f"}, + {file = "grpcio-1.70.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58ad9ba575b39edef71f4798fdb5c7b6d02ad36d47949cd381d4392a5c9cbcd3"}, + {file = "grpcio-1.70.0-cp310-cp310-win32.whl", hash = "sha256:2b0d02e4b25a5c1f9b6c7745d4fa06efc9fd6a611af0fb38d3ba956786b95199"}, + {file = "grpcio-1.70.0-cp310-cp310-win_amd64.whl", hash = "sha256:0de706c0a5bb9d841e353f6343a9defc9fc35ec61d6eb6111802f3aa9fef29e1"}, + {file = "grpcio-1.70.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:17325b0be0c068f35770f944124e8839ea3185d6d54862800fc28cc2ffad205a"}, + {file = "grpcio-1.70.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:dbe41ad140df911e796d4463168e33ef80a24f5d21ef4d1e310553fcd2c4a386"}, + {file = "grpcio-1.70.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:5ea67c72101d687d44d9c56068328da39c9ccba634cabb336075fae2eab0d04b"}, + {file = "grpcio-1.70.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb5277db254ab7586769e490b7b22f4ddab3876c490da0a1a9d7c695ccf0bf77"}, + {file = "grpcio-1.70.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7831a0fc1beeeb7759f737f5acd9fdcda520e955049512d68fda03d91186eea"}, + {file = "grpcio-1.70.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:27cc75e22c5dba1fbaf5a66c778e36ca9b8ce850bf58a9db887754593080d839"}, + {file = "grpcio-1.70.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d63764963412e22f0491d0d32833d71087288f4e24cbcddbae82476bfa1d81fd"}, + {file = "grpcio-1.70.0-cp311-cp311-win32.whl", hash = "sha256:bb491125103c800ec209d84c9b51f1c60ea456038e4734688004f377cfacc113"}, + {file = "grpcio-1.70.0-cp311-cp311-win_amd64.whl", hash = "sha256:d24035d49e026353eb042bf7b058fb831db3e06d52bee75c5f2f3ab453e71aca"}, + {file = "grpcio-1.70.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:ef4c14508299b1406c32bdbb9fb7b47612ab979b04cf2b27686ea31882387cff"}, + {file = "grpcio-1.70.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:aa47688a65643afd8b166928a1da6247d3f46a2784d301e48ca1cc394d2ffb40"}, + {file = "grpcio-1.70.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:880bfb43b1bb8905701b926274eafce5c70a105bc6b99e25f62e98ad59cb278e"}, + {file = "grpcio-1.70.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e654c4b17d07eab259d392e12b149c3a134ec52b11ecdc6a515b39aceeec898"}, + {file = "grpcio-1.70.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2394e3381071045a706ee2eeb6e08962dd87e8999b90ac15c55f56fa5a8c9597"}, + {file = "grpcio-1.70.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b3c76701428d2df01964bc6479422f20e62fcbc0a37d82ebd58050b86926ef8c"}, + {file = "grpcio-1.70.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac073fe1c4cd856ebcf49e9ed6240f4f84d7a4e6ee95baa5d66ea05d3dd0df7f"}, + {file = "grpcio-1.70.0-cp312-cp312-win32.whl", hash = "sha256:cd24d2d9d380fbbee7a5ac86afe9787813f285e684b0271599f95a51bce33528"}, + {file = "grpcio-1.70.0-cp312-cp312-win_amd64.whl", hash = "sha256:0495c86a55a04a874c7627fd33e5beaee771917d92c0e6d9d797628ac40e7655"}, + {file = "grpcio-1.70.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:aa573896aeb7d7ce10b1fa425ba263e8dddd83d71530d1322fd3a16f31257b4a"}, + {file = "grpcio-1.70.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:d405b005018fd516c9ac529f4b4122342f60ec1cee181788249372524e6db429"}, + {file = "grpcio-1.70.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:f32090238b720eb585248654db8e3afc87b48d26ac423c8dde8334a232ff53c9"}, + {file = "grpcio-1.70.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfa089a734f24ee5f6880c83d043e4f46bf812fcea5181dcb3a572db1e79e01c"}, + {file = "grpcio-1.70.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f19375f0300b96c0117aca118d400e76fede6db6e91f3c34b7b035822e06c35f"}, + {file = "grpcio-1.70.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:7c73c42102e4a5ec76608d9b60227d917cea46dff4d11d372f64cbeb56d259d0"}, + {file = "grpcio-1.70.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:0a5c78d5198a1f0aa60006cd6eb1c912b4a1520b6a3968e677dbcba215fabb40"}, + {file = "grpcio-1.70.0-cp313-cp313-win32.whl", hash = "sha256:fe9dbd916df3b60e865258a8c72ac98f3ac9e2a9542dcb72b7a34d236242a5ce"}, + {file = "grpcio-1.70.0-cp313-cp313-win_amd64.whl", hash = "sha256:4119fed8abb7ff6c32e3d2255301e59c316c22d31ab812b3fbcbaf3d0d87cc68"}, + {file = "grpcio-1.70.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:8058667a755f97407fca257c844018b80004ae8035565ebc2812cc550110718d"}, + {file = "grpcio-1.70.0-cp38-cp38-macosx_10_14_universal2.whl", hash = "sha256:879a61bf52ff8ccacbedf534665bb5478ec8e86ad483e76fe4f729aaef867cab"}, + {file = "grpcio-1.70.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:0ba0a173f4feacf90ee618fbc1a27956bfd21260cd31ced9bc707ef551ff7dc7"}, + {file = "grpcio-1.70.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558c386ecb0148f4f99b1a65160f9d4b790ed3163e8610d11db47838d452512d"}, + {file = "grpcio-1.70.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:412faabcc787bbc826f51be261ae5fa996b21263de5368a55dc2cf824dc5090e"}, + {file = "grpcio-1.70.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3b0f01f6ed9994d7a0b27eeddea43ceac1b7e6f3f9d86aeec0f0064b8cf50fdb"}, + {file = "grpcio-1.70.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7385b1cb064734005204bc8994eed7dcb801ed6c2eda283f613ad8c6c75cf873"}, + {file = "grpcio-1.70.0-cp38-cp38-win32.whl", hash = "sha256:07269ff4940f6fb6710951116a04cd70284da86d0a4368fd5a3b552744511f5a"}, + {file = "grpcio-1.70.0-cp38-cp38-win_amd64.whl", hash = "sha256:aba19419aef9b254e15011b230a180e26e0f6864c90406fdbc255f01d83bc83c"}, + {file = "grpcio-1.70.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:4f1937f47c77392ccd555728f564a49128b6a197a05a5cd527b796d36f3387d0"}, + {file = "grpcio-1.70.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:0cd430b9215a15c10b0e7d78f51e8a39d6cf2ea819fd635a7214fae600b1da27"}, + {file = "grpcio-1.70.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:e27585831aa6b57b9250abaf147003e126cd3a6c6ca0c531a01996f31709bed1"}, + {file = "grpcio-1.70.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1af8e15b0f0fe0eac75195992a63df17579553b0c4af9f8362cc7cc99ccddf4"}, + {file = "grpcio-1.70.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbce24409beaee911c574a3d75d12ffb8c3e3dd1b813321b1d7a96bbcac46bf4"}, + {file = "grpcio-1.70.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ff4a8112a79464919bb21c18e956c54add43ec9a4850e3949da54f61c241a4a6"}, + {file = "grpcio-1.70.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5413549fdf0b14046c545e19cfc4eb1e37e9e1ebba0ca390a8d4e9963cab44d2"}, + {file = "grpcio-1.70.0-cp39-cp39-win32.whl", hash = "sha256:b745d2c41b27650095e81dea7091668c040457483c9bdb5d0d9de8f8eb25e59f"}, + {file = "grpcio-1.70.0-cp39-cp39-win_amd64.whl", hash = "sha256:a31d7e3b529c94e930a117b2175b2efd179d96eb3c7a21ccb0289a8ab05b645c"}, + {file = "grpcio-1.70.0.tar.gz", hash = "sha256:8d1584a68d5922330025881e63a6c1b54cc8117291d382e4fa69339b6d914c56"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.69.0)"] +protobuf = ["grpcio-tools (>=1.70.0)"] [[package]] name = "grpcio-status" -version = "1.69.0" +version = "1.70.0" description = "Status proto mapping for gRPC" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"google\"" files = [ - {file = "grpcio_status-1.69.0-py3-none-any.whl", hash = "sha256:d6b2a3c9562c03a817c628d7ba9a925e209c228762d6d7677ae5c9401a542853"}, - {file = "grpcio_status-1.69.0.tar.gz", hash = "sha256:595ef84e5178d6281caa732ccf68ff83259241608d26b0e9c40a5e66eee2a2d2"}, + {file = "grpcio_status-1.70.0-py3-none-any.whl", hash = "sha256:fc5a2ae2b9b1c1969cc49f3262676e6854aa2398ec69cb5bd6c47cd501904a85"}, + {file = "grpcio_status-1.70.0.tar.gz", hash = "sha256:0e7b42816512433b18b9d764285ff029bde059e9d41f8fe10a60631bd8348101"}, ] [package.dependencies] googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.69.0" +grpcio = ">=1.70.0" protobuf = ">=5.26.1,<6.0dev" [[package]] name = "grpcio-tools" -version = "1.69.0" +version = "1.70.0" description = "Protobuf code generator for gRPC" optional = true python-versions = ">=3.8" -files = [ - {file = "grpcio_tools-1.69.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:8c210630faa581c3bd08953dac4ad21a7f49862f3b92d69686e9b436d2f1265d"}, - {file = "grpcio_tools-1.69.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:09b66ea279fcdaebae4ec34b1baf7577af3b14322738aa980c1c33cfea71f7d7"}, - {file = "grpcio_tools-1.69.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:be94a4bfa56d356aae242cc54072c9ccc2704b659eaae2fd599a94afebf791ce"}, - {file = "grpcio_tools-1.69.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28778debad73a8c8e0a0e07e6a2f76eecce43adbc205d17dd244d2d58bb0f0aa"}, - {file = "grpcio_tools-1.69.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:449308d93e4c97ae3a4503510c6d64978748ff5e21429c85da14fdc783c0f498"}, - {file = "grpcio_tools-1.69.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b9343651e73bc6e0df6bb518c2638bf9cc2194b50d060cdbcf1b2121cd4e4ae3"}, - {file = "grpcio_tools-1.69.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2f08b063612553e726e328aef3a27adfaea8d92712b229012afc54d59da88a02"}, - {file = "grpcio_tools-1.69.0-cp310-cp310-win32.whl", hash = "sha256:599ffd39525e7bbb6412a63e56a2e6c1af8f3493fe4305260efd4a11d064cce0"}, - {file = "grpcio_tools-1.69.0-cp310-cp310-win_amd64.whl", hash = "sha256:02f92e3c2bae67ece818787f8d3d89df0fa1e5e6bbb7c1493824fd5dfad886dd"}, - {file = "grpcio_tools-1.69.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:c18df5d1c8e163a29863583ec51237d08d7059ef8d4f7661ee6d6363d3e38fe3"}, - {file = "grpcio_tools-1.69.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:37876ae49235ef2e61e5059faf45dc5e7142ca54ae61aec378bb9483e0cd7e95"}, - {file = "grpcio_tools-1.69.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:33120920e29959eaa37a1268c6a22af243d086b1a5e5222b4203e29560ece9ce"}, - {file = "grpcio_tools-1.69.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:788bb3ecd1b44664d829d319b3c1ebc15c7d7b5e7d1f22706ab57d6acd2c6301"}, - {file = "grpcio_tools-1.69.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f453b11a112e3774c8957ec2570669f3da1f7fbc8ee242482c38981496e88da2"}, - {file = "grpcio_tools-1.69.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7e5c5dc2b656755cb58b11a7e87b65258a4a8eaff01b6c30ffcb230dd447c03d"}, - {file = "grpcio_tools-1.69.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8eabf0a7a98c14322bc74f9910c96f98feebe311e085624b2d022924d4f652ca"}, - {file = "grpcio_tools-1.69.0-cp311-cp311-win32.whl", hash = "sha256:ad567bea43d018c2215e1db10316eda94ca19229a834a3221c15d132d24c1b8a"}, - {file = "grpcio_tools-1.69.0-cp311-cp311-win_amd64.whl", hash = "sha256:3d64e801586dbea3530f245d48b9ed031738cc3eb099d5ce2fdb1b3dc2e1fb20"}, - {file = "grpcio_tools-1.69.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8ef8efe8beac4cc1e30d41893e4096ca2601da61001897bd17441645de2d4d3c"}, - {file = "grpcio_tools-1.69.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:a00e87a0c5a294028115a098819899b08dd18449df5b2aac4a2b87ba865e8681"}, - {file = "grpcio_tools-1.69.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:7722700346d5b223159532e046e51f2ff743ed4342e5fe3e0457120a4199015e"}, - {file = "grpcio_tools-1.69.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a934116fdf202cb675246056ee54645c743e2240632f86a37e52f91a405c7143"}, - {file = "grpcio_tools-1.69.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e6a6d44359ca836acfbc58103daf94b3bb8ac919d659bb348dcd7fbecedc293"}, - {file = "grpcio_tools-1.69.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e27662c0597fd1ab5399a583d358b5203edcb6fc2b29d6245099dfacd51a6ddc"}, - {file = "grpcio_tools-1.69.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7bbb2b2fb81d95bcdd1d8331defb5f5dc256dbe423bb98b682cf129cdd432366"}, - {file = "grpcio_tools-1.69.0-cp312-cp312-win32.whl", hash = "sha256:e11accd10cf4af5031ac86c45f1a13fb08f55e005cea070917c12e78fe6d2aa2"}, - {file = "grpcio_tools-1.69.0-cp312-cp312-win_amd64.whl", hash = "sha256:6df4c6ac109af338a8ccde29d184e0b0bdab13d78490cb360ff9b192a1aec7e2"}, - {file = "grpcio_tools-1.69.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:8c320c4faa1431f2e1252ef2325a970ac23b2fd04ffef6c12f96dd4552c3445c"}, - {file = "grpcio_tools-1.69.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:5f1224596ad74dd14444b20c37122b361c5d203b67e14e018b995f3c5d76eede"}, - {file = "grpcio_tools-1.69.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:965a0cf656a113bc32d15ac92ca51ed702a75d5370ae0afbdd36f818533a708a"}, - {file = "grpcio_tools-1.69.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:978835768c11a7f28778b3b7c40f839d8a57f765c315e80c4246c23900d56149"}, - {file = "grpcio_tools-1.69.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:094c7cec9bd271a32dfb7c620d4a558c63fcb0122fd1651b9ed73d6afd4ae6fe"}, - {file = "grpcio_tools-1.69.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:b51bf4981b3d7e47c2569efadff08284787124eb3dea0f63f491d39703231d3c"}, - {file = "grpcio_tools-1.69.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ea7aaf0dc1a828e2133357a9e9553fd1bb4e766890d52a506cc132e40632acdc"}, - {file = "grpcio_tools-1.69.0-cp313-cp313-win32.whl", hash = "sha256:4320f11b79d3a148cc23bad1b81719ce1197808dc2406caa8a8ba0a5cfb0260d"}, - {file = "grpcio_tools-1.69.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9bae733654e0eb8ca83aa1d0d6b6c2f4a3525ce70d5ffc07df68d28f6520137"}, - {file = "grpcio_tools-1.69.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:c78d3a7d9ba4292ba7abcc43430df426fc805e79a1dcd147509af0668332885b"}, - {file = "grpcio_tools-1.69.0-cp38-cp38-macosx_10_14_universal2.whl", hash = "sha256:497bdaa996a4de70f643c008a08813b4d20e114de50a384ae5e29d849c24c9c8"}, - {file = "grpcio_tools-1.69.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:aea33dd5a07a3b250b02a1b3f435e86d4abc94936b3ce634a2d70bc224189495"}, - {file = "grpcio_tools-1.69.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d3101c8d6f890f9d978e400843cc29992c5e03ae74f359e73dade09f2469a08"}, - {file = "grpcio_tools-1.69.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1163ba3f829141206dce1ceb67cfca73b57d279cd7183f188276443700a4980e"}, - {file = "grpcio_tools-1.69.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a85785058c31bac3d0b26c158b576eed536e4ce1af72c1d05a3518e745d44aac"}, - {file = "grpcio_tools-1.69.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ee934bbe8aa8035eea2711c12a6e537ab4c4a35a6d742ccf34bfa3a0492f412"}, - {file = "grpcio_tools-1.69.0-cp38-cp38-win32.whl", hash = "sha256:808d1b963bda8ca3c9f55cb8aa051ed2f2c98cc1fb89f79b4f67e8218580f8f3"}, - {file = "grpcio_tools-1.69.0-cp38-cp38-win_amd64.whl", hash = "sha256:afa8cd6b93e4f607c3750a976a96f874830ec7dc5f408e0fac270d0464147024"}, - {file = "grpcio_tools-1.69.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:01121b6570932bfb7d8b2ce2c0055dba902a415477079e249d85fe4494f72db2"}, - {file = "grpcio_tools-1.69.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:9861e282aa7b3656c67e84d0c25ee0e9210b955e0ec2c64699b8f80483f90853"}, - {file = "grpcio_tools-1.69.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:00adf628259e8c314a02ca1580d6a8b14eeef266f5dd5e15bf92c1efbbcf63c0"}, - {file = "grpcio_tools-1.69.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:371d03ac31b76ba77d44bdba6a8560f344c6d1ed558babab64760da085e392b7"}, - {file = "grpcio_tools-1.69.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6730414c01fe9027ba12538fd6e192e1bea94d5b819a1e03d15e89aab1b4573"}, - {file = "grpcio_tools-1.69.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5562a1b1b67deffd04fbb1bcf8f1634580538ce35895b77cdfaec1fb115efd95"}, - {file = "grpcio_tools-1.69.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f8996efddc867134f22bbf8a368b1b2a018d0a9b0ac9d3185cfd81d1abd8066"}, - {file = "grpcio_tools-1.69.0-cp39-cp39-win32.whl", hash = "sha256:8f5959d8a453d613e7137831f6885b43b5c378ec317943b4ec599046baa97bfc"}, - {file = "grpcio_tools-1.69.0-cp39-cp39-win_amd64.whl", hash = "sha256:5d47abf7e0662dd5dbb9cc252c3616e5fbc5f71d34e3f6332cd24bcdf2940abd"}, - {file = "grpcio_tools-1.69.0.tar.gz", hash = "sha256:3e1a98f4d9decb84979e1ddd3deb09c0a33a84b6e3c0776d5bde4097e3ab66dd"}, +groups = ["main"] +markers = "extra == \"qdrant\"" +files = [ + {file = "grpcio_tools-1.70.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:4d456521290e25b1091975af71604facc5c7db162abdca67e12a0207b8bbacbe"}, + {file = "grpcio_tools-1.70.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:d50080bca84f53f3a05452e06e6251cbb4887f5a1d1321d1989e26d6e0dc398d"}, + {file = "grpcio_tools-1.70.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:02e3bf55fb569fe21b54a32925979156e320f9249bb247094c4cbaa60c23a80d"}, + {file = "grpcio_tools-1.70.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88a3ec6fa2381f616d567f996503e12ca353777941b61030fd9733fd5772860e"}, + {file = "grpcio_tools-1.70.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6034a0579fab2aed8685fa1a558de084668b1e9b01a82a4ca7458b9bedf4654c"}, + {file = "grpcio_tools-1.70.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:701bbb1ff406a21a771f5b1df6be516c0a59236774b6836eaad7696b1d128ea8"}, + {file = "grpcio_tools-1.70.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6eeb86864e1432fc1ab61e03395a2a4c04e9dd9c89db07e6fe68c7c2ac8ec24f"}, + {file = "grpcio_tools-1.70.0-cp310-cp310-win32.whl", hash = "sha256:d53c8c45e843b5836781ad6b82a607c72c2f9a3f556e23d703a0e099222421fa"}, + {file = "grpcio_tools-1.70.0-cp310-cp310-win_amd64.whl", hash = "sha256:22024caee36ab65c2489594d718921dcbb5bd18d61c5417a9ede94fd8dc8a589"}, + {file = "grpcio_tools-1.70.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:5f5aba12d98d25c7ab2dd983939e2c21556a7d15f903b286f24d88d2c6e30c0a"}, + {file = "grpcio_tools-1.70.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:d47a6c6cfc526b290b7b53a37dd7e6932983f7a168b56aab760b4b597c47f30f"}, + {file = "grpcio_tools-1.70.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:b5a9beadd1e24772ffa2c70f07d72f73330d356b78b246e424f4f2ed6c6713f3"}, + {file = "grpcio_tools-1.70.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb8135eef160a62505f074bf7a3d62f3b13911c3c14037c5392bf877114213b5"}, + {file = "grpcio_tools-1.70.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7ac9b3e13ace8467a586c53580ee22f9732c355583f3c344ef8c6c0666219cc"}, + {file = "grpcio_tools-1.70.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:63f367363a4a1489a0046b19f9d561216ea0d206c40a6f1bf07a58ccfb7be480"}, + {file = "grpcio_tools-1.70.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54ceffef59a059d2c7304554a8bbb20eedb05a3f937159ab1c332c1b28e12c9f"}, + {file = "grpcio_tools-1.70.0-cp311-cp311-win32.whl", hash = "sha256:7a90a66a46821140a2a2b0be787dfabe42e22e9a5ba9cc70726b3e5c71a3b785"}, + {file = "grpcio_tools-1.70.0-cp311-cp311-win_amd64.whl", hash = "sha256:4ebf09733545a69c166b02caa14c34451e38855544820dab7fdde5c28e2dbffe"}, + {file = "grpcio_tools-1.70.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:ec5d6932c3173d7618267b3b3fd77b9243949c5ec04302b7338386d4f8544e0b"}, + {file = "grpcio_tools-1.70.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:f22852da12f53b02a3bdb29d0c32fcabab9c7c8f901389acffec8461083f110d"}, + {file = "grpcio_tools-1.70.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:7d45067e6efd20881e98a0e1d7edd7f207b1625ad7113321becbfe0a6ebee46c"}, + {file = "grpcio_tools-1.70.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3020c97f03b30eee3c26aa2a55fbe003f1729c6f879a378507c2c78524db7c12"}, + {file = "grpcio_tools-1.70.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7fd472fce3b33bdf7fbc24d40da7ab10d7a088bcaf59c37433c2c57330fbcb6"}, + {file = "grpcio_tools-1.70.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3875543d74ce1a698a11f498f83795216ce929cb29afa5fac15672c7ba1d6dd2"}, + {file = "grpcio_tools-1.70.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a130c24d617a3a57369da784080dfa8848444d41b7ae1250abc06e72e706a8d9"}, + {file = "grpcio_tools-1.70.0-cp312-cp312-win32.whl", hash = "sha256:8eae17c920d14e2e451dbb18f5d8148f884e10228061941b33faa8fceee86e73"}, + {file = "grpcio_tools-1.70.0-cp312-cp312-win_amd64.whl", hash = "sha256:99caa530242a0a832d8b6a6ab94b190c9b449d3e237f953911b4d56207569436"}, + {file = "grpcio_tools-1.70.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:f024688d04e7a9429489ed695b85628075c3c6d655198ba3c6ccbd1d8b7c333b"}, + {file = "grpcio_tools-1.70.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:1fa9a81621d7178498dedcf94eb8f276a7594327faf3dd5fd1935ce2819a2bdb"}, + {file = "grpcio_tools-1.70.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:c6da2585c0950cdb650df1ff6d85b3fe31e22f8370b9ee11f8fe641d5b4bf096"}, + {file = "grpcio_tools-1.70.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70234b592af17050ec30cf35894790cef52aeae87639efe6db854a7fa783cc8c"}, + {file = "grpcio_tools-1.70.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c021b040d0a9f5bb96a725c4d2b95008aad127d6bed124a7bbe854973014f5b"}, + {file = "grpcio_tools-1.70.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:114a42e566e5b16a47e98f7910a6c0074b37e2d1faacaae13222e463d0d0d43c"}, + {file = "grpcio_tools-1.70.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:4cae365d7e3ba297256216a9a256458b286f75c64603f017972b3ad1ee374437"}, + {file = "grpcio_tools-1.70.0-cp313-cp313-win32.whl", hash = "sha256:ae139a8d3ddd8353f62af3af018e99ebcd2f4a237bd319cb4b6f58dd608aaa54"}, + {file = "grpcio_tools-1.70.0-cp313-cp313-win_amd64.whl", hash = "sha256:04bf30c0eb2741defe3ab6e0a6102b022d69cfd39d68fab9b954993ceca8d346"}, + {file = "grpcio_tools-1.70.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:076f71c6d5adcf237ebca63f1ed51098293261dab9f301e3dfd180e896e5fa89"}, + {file = "grpcio_tools-1.70.0-cp38-cp38-macosx_10_14_universal2.whl", hash = "sha256:d1fc2112e9c40167086e2e6a929b253e5281bffd070fab7cd1ae019317ffc11d"}, + {file = "grpcio_tools-1.70.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:904f13d2d04f88178b09d8ef89549b90cbf8792b684a7c72540fc1a9887697e2"}, + {file = "grpcio_tools-1.70.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1de6c71833d36fb8cc8ac10539681756dc2c5c67e5d4aa4d05adb91ecbdd8474"}, + {file = "grpcio_tools-1.70.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ab788afced2d2c59bef86479967ce0b28485789a9f2cc43793bb7aa67f9528b"}, + {file = "grpcio_tools-1.70.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:836293dcbb1e59fa52aa8aa890bd7a32a8eea7651cd614e96d86de4f3032fe73"}, + {file = "grpcio_tools-1.70.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:740b3741d124c5f390dd50ad1c42c11788882baf3c202cd3e69adee0e3dde559"}, + {file = "grpcio_tools-1.70.0-cp38-cp38-win32.whl", hash = "sha256:b9e4a12b862ba5e42d8028da311e8d4a2c307362659b2f4141d0f940f8c12b49"}, + {file = "grpcio_tools-1.70.0-cp38-cp38-win_amd64.whl", hash = "sha256:fd04c93af460b1456cd12f8f85502503e1db6c4adc1b7d4bd775b12c1fd94fee"}, + {file = "grpcio_tools-1.70.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:52d7e7ef11867fe7de577076b1f2ac6bf106b2325130e3de66f8c364c96ff332"}, + {file = "grpcio_tools-1.70.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:0f7ed0372afd9f5eb938334e84681396257015ab92e03de009aa3170e64b24d0"}, + {file = "grpcio_tools-1.70.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:24a5b0328ffcfe0c4a9024f302545abdb8d6f24921409a5839f2879555b96fea"}, + {file = "grpcio_tools-1.70.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9387b30f3b2f46942fb5718624d7421875a6ce458620d6e15817172d78db1e1a"}, + {file = "grpcio_tools-1.70.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4545264e06e1cd7fb21b9447bb5126330bececb4bc626c98f793fda2fd910bf8"}, + {file = "grpcio_tools-1.70.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:79b723ce30416e8e1d7ff271f97ade79aaf30309a595d80c377105c07f5b20fd"}, + {file = "grpcio_tools-1.70.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1c0917dce12af04529606d437def83962d51c59dcde905746134222e94a2ab1b"}, + {file = "grpcio_tools-1.70.0-cp39-cp39-win32.whl", hash = "sha256:5cb0baa52d4d44690fac6b1040197c694776a291a90e2d3c369064b4d5bc6642"}, + {file = "grpcio_tools-1.70.0-cp39-cp39-win_amd64.whl", hash = "sha256:840ec536ab933db2ef8d5acaa6b712d0e9e8f397f62907c852ec50a3f69cdb78"}, + {file = "grpcio_tools-1.70.0.tar.gz", hash = "sha256:e578fee7c1c213c8e471750d92631d00f178a15479fb2cb3b939a07fc125ccd3"}, ] [package.dependencies] -grpcio = ">=1.69.0" +grpcio = ">=1.70.0" protobuf = ">=5.26.1,<6.0dev" setuptools = "*" @@ -1578,6 +1669,7 @@ version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -1589,6 +1681,8 @@ version = "4.1.0" description = "HTTP/2 State-Machine based protocol implementation" optional = true python-versions = ">=3.6.1" +groups = ["main"] +markers = "extra == \"qdrant\"" files = [ {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, @@ -1600,13 +1694,15 @@ hyperframe = ">=6.0,<7" [[package]] name = "hpack" -version = "4.0.0" -description = "Pure-Python HPACK header compression" +version = "4.1.0" +description = "Pure-Python HPACK header encoding" optional = true -python-versions = ">=3.6.1" +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"qdrant\"" files = [ - {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, - {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, + {file = "hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496"}, + {file = "hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca"}, ] [[package]] @@ -1615,6 +1711,7 @@ version = "1.0.7" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, @@ -1636,6 +1733,7 @@ version = "0.25.2" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "httpx-0.25.2-py3-none-any.whl", hash = "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118"}, {file = "httpx-0.25.2.tar.gz", hash = "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8"}, @@ -1661,6 +1759,8 @@ version = "0.4.0" description = "Consume Server-Sent Event (SSE) messages with HTTPX." optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"cohere\"" files = [ {file = "httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721"}, {file = "httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f"}, @@ -1668,13 +1768,15 @@ files = [ [[package]] name = "huggingface-hub" -version = "0.27.1" +version = "0.28.0" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = true python-versions = ">=3.8.0" +groups = ["main"] +markers = "(extra == \"cohere\" or extra == \"local\" or extra == \"vision\" or extra == \"fastembed\") and (extra == \"cohere\" or python_version < \"3.13\")" files = [ - {file = "huggingface_hub-0.27.1-py3-none-any.whl", hash = "sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec"}, - {file = "huggingface_hub-0.27.1.tar.gz", hash = "sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b"}, + {file = "huggingface_hub-0.28.0-py3-none-any.whl", hash = "sha256:71cff4e500efe68061d94b7f6d3114e183715088be7a90bf4dd84af83b5f5cdb"}, + {file = "huggingface_hub-0.28.0.tar.gz", hash = "sha256:c2b18c02a47d4384763caddb4d0ab2a8fc6c16e0800d6de4d55d0a896244aba3"}, ] [package.dependencies] @@ -1687,13 +1789,13 @@ tqdm = ">=4.42.1" typing-extensions = ">=3.7.4.3" [package.extras] -all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] cli = ["InquirerPy (==0.3.4)"] -dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] hf-transfer = ["hf-transfer (>=0.1.4)"] inference = ["aiohttp"] -quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.5.0)"] +quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.9.0)"] tensorflow = ["graphviz", "pydot", "tensorflow"] tensorflow-testing = ["keras (<3.0)", "tensorflow"] testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] @@ -1706,6 +1808,8 @@ version = "10.0" description = "Human friendly output for text interfaces using Python" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\"" files = [ {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, @@ -1716,13 +1820,15 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve [[package]] name = "hyperframe" -version = "6.0.1" -description = "HTTP/2 framing layer for Python" +version = "6.1.0" +description = "Pure-Python HTTP/2 framing" optional = true -python-versions = ">=3.6.1" +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"qdrant\"" files = [ - {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, - {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, + {file = "hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5"}, + {file = "hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08"}, ] [[package]] @@ -1731,6 +1837,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -1745,6 +1852,8 @@ version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, @@ -1752,14 +1861,16 @@ files = [ [[package]] name = "importlib-metadata" -version = "8.5.0" +version = "8.6.1" description = "Read metadata from Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, - {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, + {file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"}, + {file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"}, ] +markers = {main = "python_version < \"3.10\" and extra == \"docs\"", dev = "python_version < \"3.10\""} [package.dependencies] zipp = ">=3.20" @@ -1770,7 +1881,7 @@ cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +test = ["flufl.flake8", "importlib_resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] [[package]] @@ -1779,6 +1890,7 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -1790,6 +1902,7 @@ version = "6.29.5" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5"}, {file = "ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215"}, @@ -1823,6 +1936,7 @@ version = "8.18.1" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, @@ -1860,6 +1974,7 @@ version = "0.19.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, @@ -1879,6 +1994,8 @@ version = "3.1.5" description = "A very fast and expressive template engine." optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "(extra == \"docs\" or extra == \"local\" or extra == \"vision\") and (extra == \"docs\" or python_version < \"3.13\")" files = [ {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"}, {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"}, @@ -1896,6 +2013,7 @@ version = "0.8.2" description = "Fast iterable JSON parser." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "jiter-0.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ca8577f6a413abe29b079bc30f907894d7eb07a865c4df69475e868d73e71c7b"}, {file = "jiter-0.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b25bd626bde7fb51534190c7e3cb97cee89ee76b76d7585580e22f34f5e3f393"}, @@ -1981,6 +2099,8 @@ version = "1.0.1" description = "JSON Matching Expressions" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"bedrock\"" files = [ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, @@ -1992,6 +2112,8 @@ version = "1.4.2" description = "Lightweight pipelining with Python functions" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"hybrid\"" files = [ {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, @@ -2003,6 +2125,7 @@ version = "8.6.3" description = "Jupyter protocol implementation and client libraries" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f"}, {file = "jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419"}, @@ -2026,6 +2149,7 @@ version = "5.7.2" description = "Jupyter core package. A base package on which Jupyter projects rely." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409"}, {file = "jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9"}, @@ -2046,6 +2170,8 @@ version = "0.2.85" description = "Python bindings for the llama.cpp library" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"local\"" files = [ {file = "llama_cpp_python-0.2.85.tar.gz", hash = "sha256:31476c2f4331784d3681f9bcd366cc4666ba97ab128bffbd23cb90ee2cebff21"}, ] @@ -2068,6 +2194,8 @@ version = "0.7.3" description = "Python logging made (stupidly) simple" optional = true python-versions = "<4.0,>=3.5" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\"" files = [ {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, @@ -2086,6 +2214,8 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "(extra == \"docs\" or extra == \"local\" or extra == \"vision\") and (extra == \"docs\" or python_version < \"3.13\")" files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -2156,6 +2286,7 @@ version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, @@ -2170,6 +2301,8 @@ version = "0.0.12" description = "" optional = true python-versions = ">=3.8,<4.0" +groups = ["main"] +markers = "extra == \"mistralai\"" files = [ {file = "mistralai-0.0.12-py3-none-any.whl", hash = "sha256:d489d1f0a31bf0edbe15c6d12f68b943148d2a725a088be0d8a5d4c888f8436c"}, {file = "mistralai-0.0.12.tar.gz", hash = "sha256:fe652836146a15bdce7691a95803a32c53c641c5400093447ffa93bf2ed296b2"}, @@ -2186,6 +2319,8 @@ version = "4.1.0" description = "Python extension for MurmurHash (MurmurHash3), a set of fast and robust hash functions." optional = true python-versions = "*" +groups = ["main"] +markers = "extra == \"hybrid\" or extra == \"fastembed\" and python_version < \"3.13\"" files = [ {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be5ac76a8b0cd8095784e51e4c1c9c318c19edcd1709a06eb14979c8d850c31a"}, {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98a49121afdfab67cd80e912b36404139d7deceb6773a83620137aaa0da5714c"}, @@ -2278,6 +2413,8 @@ version = "1.3.0" description = "Python library for arbitrary-precision floating-point arithmetic" optional = true python-versions = "*" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\" or extra == \"fastembed\")" files = [ {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, @@ -2295,6 +2432,7 @@ version = "6.1.0" description = "multidict implementation" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, @@ -2399,6 +2537,7 @@ version = "1.14.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, @@ -2458,6 +2597,7 @@ version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, @@ -2469,6 +2609,7 @@ version = "1.6.0" description = "Patch asyncio to allow nested event loops" optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, @@ -2480,6 +2621,8 @@ version = "3.2.1" description = "Python package for creating and manipulating graphs and networks" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\")" files = [ {file = "networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2"}, {file = "networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6"}, @@ -2498,6 +2641,8 @@ version = "3.9.1" description = "Natural Language Toolkit" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"hybrid\"" files = [ {file = "nltk-3.9.1-py3-none-any.whl", hash = "sha256:4fa26829c5b00715afe3061398a8989dc643b92ce7dd93fb4585a70930d168a1"}, {file = "nltk-3.9.1.tar.gz", hash = "sha256:87d127bd3de4bd89a4f81265e5fa59cb1b199b27440175370f7417d2bc7ae868"}, @@ -2523,6 +2668,7 @@ version = "1.26.4" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, @@ -2568,6 +2714,8 @@ version = "12.1.3.1" description = "CUBLAS native runtime libraries" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl", hash = "sha256:ee53ccca76a6fc08fb9701aa95b6ceb242cdaab118c3bb152af4e579af792728"}, {file = "nvidia_cublas_cu12-12.1.3.1-py3-none-win_amd64.whl", hash = "sha256:2b964d60e8cf11b5e1073d179d85fa340c120e99b3067558f3cf98dd69d02906"}, @@ -2579,6 +2727,8 @@ version = "12.1.105" description = "CUDA profiling tools runtime libs." optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_cuda_cupti_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:e54fde3983165c624cb79254ae9818a456eb6e87a7fd4d56a2352c24ee542d7e"}, {file = "nvidia_cuda_cupti_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:bea8236d13a0ac7190bd2919c3e8e6ce1e402104276e6f9694479e48bb0eb2a4"}, @@ -2590,6 +2740,8 @@ version = "12.1.105" description = "NVRTC native runtime libraries" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:339b385f50c309763ca65456ec75e17bbefcbbf2893f462cb8b90584cd27a1c2"}, {file = "nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:0a98a522d9ff138b96c010a65e145dc1b4850e9ecb75a0172371793752fd46ed"}, @@ -2601,6 +2753,8 @@ version = "12.1.105" description = "CUDA Runtime native Libraries" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_cuda_runtime_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:6e258468ddf5796e25f1dc591a31029fa317d97a0a94ed93468fc86301d61e40"}, {file = "nvidia_cuda_runtime_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:dfb46ef84d73fababab44cf03e3b83f80700d27ca300e537f85f636fac474344"}, @@ -2612,6 +2766,8 @@ version = "8.9.2.26" description = "cuDNN runtime libraries" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_cudnn_cu12-8.9.2.26-py3-none-manylinux1_x86_64.whl", hash = "sha256:5ccb288774fdfb07a7e7025ffec286971c06d8d7b4fb162525334616d7629ff9"}, ] @@ -2625,6 +2781,8 @@ version = "11.0.2.54" description = "CUFFT native runtime libraries" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_cufft_cu12-11.0.2.54-py3-none-manylinux1_x86_64.whl", hash = "sha256:794e3948a1aa71fd817c3775866943936774d1c14e7628c74f6f7417224cdf56"}, {file = "nvidia_cufft_cu12-11.0.2.54-py3-none-win_amd64.whl", hash = "sha256:d9ac353f78ff89951da4af698f80870b1534ed69993f10a4cf1d96f21357e253"}, @@ -2636,6 +2794,8 @@ version = "10.3.2.106" description = "CURAND native runtime libraries" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_curand_cu12-10.3.2.106-py3-none-manylinux1_x86_64.whl", hash = "sha256:9d264c5036dde4e64f1de8c50ae753237c12e0b1348738169cd0f8a536c0e1e0"}, {file = "nvidia_curand_cu12-10.3.2.106-py3-none-win_amd64.whl", hash = "sha256:75b6b0c574c0037839121317e17fd01f8a69fd2ef8e25853d826fec30bdba74a"}, @@ -2647,6 +2807,8 @@ version = "11.4.5.107" description = "CUDA solver native runtime libraries" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl", hash = "sha256:8a7ec542f0412294b15072fa7dab71d31334014a69f953004ea7a118206fe0dd"}, {file = "nvidia_cusolver_cu12-11.4.5.107-py3-none-win_amd64.whl", hash = "sha256:74e0c3a24c78612192a74fcd90dd117f1cf21dea4822e66d89e8ea80e3cd2da5"}, @@ -2663,6 +2825,8 @@ version = "12.1.0.106" description = "CUSPARSE native runtime libraries" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl", hash = "sha256:f3b50f42cf363f86ab21f720998517a659a48131e8d538dc02f8768237bd884c"}, {file = "nvidia_cusparse_cu12-12.1.0.106-py3-none-win_amd64.whl", hash = "sha256:b798237e81b9719373e8fae8d4f091b70a0cf09d9d85c95a557e11df2d8e9a5a"}, @@ -2677,20 +2841,24 @@ version = "2.19.3" description = "NVIDIA Collective Communication Library (NCCL) Runtime" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_nccl_cu12-2.19.3-py3-none-manylinux1_x86_64.whl", hash = "sha256:a9734707a2c96443331c1e48c717024aa6678a0e2a4cb66b2c364d18cee6b48d"}, ] [[package]] name = "nvidia-nvjitlink-cu12" -version = "12.6.85" +version = "12.8.61" description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ - {file = "nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:eedc36df9e88b682efe4309aa16b5b4e78c2407eac59e8c10a6a47535164369a"}, - {file = "nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cf4eaa7d4b6b543ffd69d6abfb11efdeb2db48270d94dfd3a452c24150829e41"}, - {file = "nvidia_nvjitlink_cu12-12.6.85-py3-none-win_amd64.whl", hash = "sha256:e61120e52ed675747825cdd16febc6a0730537451d867ee58bee3853b1b13d1c"}, + {file = "nvidia_nvjitlink_cu12-12.8.61-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:45fd79f2ae20bd67e8bc411055939049873bfd8fac70ff13bd4865e0b9bdab17"}, + {file = "nvidia_nvjitlink_cu12-12.8.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9b80ecab31085dda3ce3b41d043be0ec739216c3fc633b8abe212d5a30026df0"}, + {file = "nvidia_nvjitlink_cu12-12.8.61-py3-none-win_amd64.whl", hash = "sha256:1166a964d25fdc0eae497574d38824305195a5283324a21ccb0ce0c802cbf41c"}, ] [[package]] @@ -2699,6 +2867,8 @@ version = "12.1.105" description = "NVIDIA Tools Extension" optional = true python-versions = ">=3" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:dc21cf308ca5691e7c04d962e213f8a4aa9bbfa23d95412f452254c2caeb09e5"}, {file = "nvidia_nvtx_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:65f4d98982b31b60026e0e6de73fbdfc09d08a96f4656dd3665ca616a11e1e82"}, @@ -2710,6 +2880,8 @@ version = "1.17.0" description = "Open Neural Network Exchange" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\"" files = [ {file = "onnx-1.17.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:38b5df0eb22012198cdcee527cc5f917f09cce1f88a69248aaca22bd78a7f023"}, {file = "onnx-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d545335cb49d4d8c47cc803d3a805deb7ad5d9094dc67657d66e568610a36d7d"}, @@ -2752,6 +2924,8 @@ version = "1.20.1" description = "ONNX Runtime is a runtime accelerator for Machine Learning models" optional = true python-versions = "*" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\"" files = [ {file = "onnxruntime-1.20.1-cp310-cp310-macosx_13_0_universal2.whl", hash = "sha256:e50ba5ff7fed4f7d9253a6baf801ca2883cc08491f9d32d78a80da57256a5439"}, {file = "onnxruntime-1.20.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b2908b50101a19e99c4d4e97ebb9905561daf61829403061c1adc1b588bc0de"}, @@ -2786,13 +2960,14 @@ sympy = "*" [[package]] name = "openai" -version = "1.59.6" +version = "1.60.2" description = "The official Python library for the openai API" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "openai-1.59.6-py3-none-any.whl", hash = "sha256:b28ed44eee3d5ebe1a3ea045ee1b4b50fea36ecd50741aaa5ce5a5559c900cb6"}, - {file = "openai-1.59.6.tar.gz", hash = "sha256:c7670727c2f1e4473f62fea6fa51475c8bc098c9ffb47bfb9eef5be23c747934"}, + {file = "openai-1.60.2-py3-none-any.whl", hash = "sha256:993bd11b96900b9098179c728026f016b4982ded7ee30dfcf4555eab1171fff9"}, + {file = "openai-1.60.2.tar.gz", hash = "sha256:a8f843e10f2855713007f491d96afb2694b11b5e02cb97c7d01a0be60bc5bb51"}, ] [package.dependencies] @@ -2811,86 +2986,92 @@ realtime = ["websockets (>=13,<15)"] [[package]] name = "orjson" -version = "3.10.14" +version = "3.10.15" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = true python-versions = ">=3.8" -files = [ - {file = "orjson-3.10.14-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:849ea7845a55f09965826e816cdc7689d6cf74fe9223d79d758c714af955bcb6"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5947b139dfa33f72eecc63f17e45230a97e741942955a6c9e650069305eb73d"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cde6d76910d3179dae70f164466692f4ea36da124d6fb1a61399ca589e81d69a"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6dfbaeb7afa77ca608a50e2770a0461177b63a99520d4928e27591b142c74b1"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa45e489ef80f28ff0e5ba0a72812b8cfc7c1ef8b46a694723807d1b07c89ebb"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5007abfdbb1d866e2aa8990bd1c465f0f6da71d19e695fc278282be12cffa5"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1b49e2af011c84c3f2d541bb5cd1e3c7c2df672223e7e3ea608f09cf295e5f8a"}, - {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:164ac155109226b3a2606ee6dda899ccfbe6e7e18b5bdc3fbc00f79cc074157d"}, - {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6b1225024cf0ef5d15934b5ffe9baf860fe8bc68a796513f5ea4f5056de30bca"}, - {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d6546e8073dc382e60fcae4a001a5a1bc46da5eab4a4878acc2d12072d6166d5"}, - {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9f1d2942605c894162252d6259b0121bf1cb493071a1ea8cb35d79cb3e6ac5bc"}, - {file = "orjson-3.10.14-cp310-cp310-win32.whl", hash = "sha256:397083806abd51cf2b3bbbf6c347575374d160331a2d33c5823e22249ad3118b"}, - {file = "orjson-3.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:fa18f949d3183a8d468367056be989666ac2bef3a72eece0bade9cdb733b3c28"}, - {file = "orjson-3.10.14-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f506fd666dd1ecd15a832bebc66c4df45c1902fd47526292836c339f7ba665a9"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efe5fd254cfb0eeee13b8ef7ecb20f5d5a56ddda8a587f3852ab2cedfefdb5f6"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ddc8c866d7467f5ee2991397d2ea94bcf60d0048bdd8ca555740b56f9042725"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af8e42ae4363773658b8d578d56dedffb4f05ceeb4d1d4dd3fb504950b45526"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84dd83110503bc10e94322bf3ffab8bc49150176b49b4984dc1cce4c0a993bf9"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36f5bfc0399cd4811bf10ec7a759c7ab0cd18080956af8ee138097d5b5296a95"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868943660fb2a1e6b6b965b74430c16a79320b665b28dd4511d15ad5038d37d5"}, - {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33449c67195969b1a677533dee9d76e006001213a24501333624623e13c7cc8e"}, - {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e4c9f60f9fb0b5be66e416dcd8c9d94c3eabff3801d875bdb1f8ffc12cf86905"}, - {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0de4d6315cfdbd9ec803b945c23b3a68207fd47cbe43626036d97e8e9561a436"}, - {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83adda3db595cb1a7e2237029b3249c85afbe5c747d26b41b802e7482cb3933e"}, - {file = "orjson-3.10.14-cp311-cp311-win32.whl", hash = "sha256:998019ef74a4997a9d741b1473533cdb8faa31373afc9849b35129b4b8ec048d"}, - {file = "orjson-3.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:9d034abdd36f0f0f2240f91492684e5043d46f290525d1117712d5b8137784eb"}, - {file = "orjson-3.10.14-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2ad4b7e367efba6dc3f119c9a0fcd41908b7ec0399a696f3cdea7ec477441b09"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f496286fc85e93ce0f71cc84fc1c42de2decf1bf494094e188e27a53694777a7"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7f189bbfcded40e41a6969c1068ba305850ba016665be71a217918931416fbf"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8cc8204f0b75606869c707da331058ddf085de29558b516fc43c73ee5ee2aadb"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:deaa2899dff7f03ab667e2ec25842d233e2a6a9e333efa484dfe666403f3501c"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1c3ea52642c9714dc6e56de8a451a066f6d2707d273e07fe8a9cc1ba073813d"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d3f9ed72e7458ded9a1fb1b4d4ed4c4fdbaf82030ce3f9274b4dc1bff7ace2b"}, - {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:07520685d408a2aba514c17ccc16199ff2934f9f9e28501e676c557f454a37fe"}, - {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:76344269b550ea01488d19a2a369ab572c1ac4449a72e9f6ac0d70eb1cbfb953"}, - {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e2979d0f2959990620f7e62da6cd954e4620ee815539bc57a8ae46e2dacf90e3"}, - {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03f61ca3674555adcb1aa717b9fc87ae936aa7a63f6aba90a474a88701278780"}, - {file = "orjson-3.10.14-cp312-cp312-win32.whl", hash = "sha256:d5075c54edf1d6ad81d4c6523ce54a748ba1208b542e54b97d8a882ecd810fd1"}, - {file = "orjson-3.10.14-cp312-cp312-win_amd64.whl", hash = "sha256:175cafd322e458603e8ce73510a068d16b6e6f389c13f69bf16de0e843d7d406"}, - {file = "orjson-3.10.14-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:0905ca08a10f7e0e0c97d11359609300eb1437490a7f32bbaa349de757e2e0c7"}, - {file = "orjson-3.10.14-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92d13292249f9f2a3e418cbc307a9fbbef043c65f4bd8ba1eb620bc2aaba3d15"}, - {file = "orjson-3.10.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90937664e776ad316d64251e2fa2ad69265e4443067668e4727074fe39676414"}, - {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9ed3d26c4cb4f6babaf791aa46a029265850e80ec2a566581f5c2ee1a14df4f1"}, - {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:56ee546c2bbe9599aba78169f99d1dc33301853e897dbaf642d654248280dc6e"}, - {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:901e826cb2f1bdc1fcef3ef59adf0c451e8f7c0b5deb26c1a933fb66fb505eae"}, - {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26336c0d4b2d44636e1e1e6ed1002f03c6aae4a8a9329561c8883f135e9ff010"}, - {file = "orjson-3.10.14-cp313-cp313-win32.whl", hash = "sha256:e2bc525e335a8545c4e48f84dd0328bc46158c9aaeb8a1c2276546e94540ea3d"}, - {file = "orjson-3.10.14-cp313-cp313-win_amd64.whl", hash = "sha256:eca04dfd792cedad53dc9a917da1a522486255360cb4e77619343a20d9f35364"}, - {file = "orjson-3.10.14-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a0fba3b8a587a54c18585f077dcab6dd251c170d85cfa4d063d5746cd595a0f"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:175abf3d20e737fec47261d278f95031736a49d7832a09ab684026528c4d96db"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29ca1a93e035d570e8b791b6c0feddd403c6a5388bfe870bf2aa6bba1b9d9b8e"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f77202c80e8ab5a1d1e9faf642343bee5aaf332061e1ada4e9147dbd9eb00c46"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e2ec73b7099b6a29b40a62e08a23b936423bd35529f8f55c42e27acccde7954"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2d1679df9f9cd9504f8dff24555c1eaabba8aad7f5914f28dab99e3c2552c9d"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691ab9a13834310a263664313e4f747ceb93662d14a8bdf20eb97d27ed488f16"}, - {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:b11ed82054fce82fb74cea33247d825d05ad6a4015ecfc02af5fbce442fbf361"}, - {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:e70a1d62b8288677d48f3bea66c21586a5f999c64ecd3878edb7393e8d1b548d"}, - {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:16642f10c1ca5611251bd835de9914a4b03095e28a34c8ba6a5500b5074338bd"}, - {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3871bad546aa66c155e3f36f99c459780c2a392d502a64e23fb96d9abf338511"}, - {file = "orjson-3.10.14-cp38-cp38-win32.whl", hash = "sha256:0293a88815e9bb5c90af4045f81ed364d982f955d12052d989d844d6c4e50945"}, - {file = "orjson-3.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:6169d3868b190d6b21adc8e61f64e3db30f50559dfbdef34a1cd6c738d409dfc"}, - {file = "orjson-3.10.14-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:06d4ec218b1ec1467d8d64da4e123b4794c781b536203c309ca0f52819a16c03"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962c2ec0dcaf22b76dee9831fdf0c4a33d4bf9a257a2bc5d4adc00d5c8ad9034"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:21d3be4132f71ef1360385770474f29ea1538a242eef72ac4934fe142800e37f"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c28ed60597c149a9e3f5ad6dd9cebaee6fb2f0e3f2d159a4a2b9b862d4748860"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e947f70167fe18469f2023644e91ab3d24f9aed69a5e1c78e2c81b9cea553fb"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64410696c97a35af2432dea7bdc4ce32416458159430ef1b4beb79fd30093ad6"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8050a5d81c022561ee29cd2739de5b4445f3c72f39423fde80a63299c1892c52"}, - {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b49a28e30d3eca86db3fe6f9b7f4152fcacbb4a467953cd1b42b94b479b77956"}, - {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ca041ad20291a65d853a9523744eebc3f5a4b2f7634e99f8fe88320695ddf766"}, - {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d313a2998b74bb26e9e371851a173a9b9474764916f1fc7971095699b3c6e964"}, - {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7796692136a67b3e301ef9052bde6fe8e7bd5200da766811a3a608ffa62aaff0"}, - {file = "orjson-3.10.14-cp39-cp39-win32.whl", hash = "sha256:eee4bc767f348fba485ed9dc576ca58b0a9eac237f0e160f7a59bce628ed06b3"}, - {file = "orjson-3.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:96a1c0ee30fb113b3ae3c748fd75ca74a157ff4c58476c47db4d61518962a011"}, - {file = "orjson-3.10.14.tar.gz", hash = "sha256:cf31f6f071a6b8e7aa1ead1fa27b935b48d00fbfa6a28ce856cfff2d5dd68eed"}, +groups = ["main"] +markers = "extra == \"mistralai\"" +files = [ + {file = "orjson-3.10.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:552c883d03ad185f720d0c09583ebde257e41b9521b74ff40e08b7dec4559c04"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e3e8d438d02e4854f70bfdc03a6bcdb697358dbaa6bcd19cbe24d24ece1f8"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c2c79fa308e6edb0ffab0a31fd75a7841bf2a79a20ef08a3c6e3b26814c8ca8"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cb85490aa6bf98abd20607ab5c8324c0acb48d6da7863a51be48505646c814"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763dadac05e4e9d2bc14938a45a2d0560549561287d41c465d3c58aec818b164"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a330b9b4734f09a623f74a7490db713695e13b67c959713b78369f26b3dee6bf"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a61a4622b7ff861f019974f73d8165be1bd9a0855e1cad18ee167acacabeb061"}, + {file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acd271247691574416b3228db667b84775c497b245fa275c6ab90dc1ffbbd2b3"}, + {file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4759b109c37f635aa5c5cc93a1b26927bfde24b254bcc0e1149a9fada253d2d"}, + {file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e992fd5cfb8b9f00bfad2fd7a05a4299db2bbe92e6440d9dd2fab27655b3182"}, + {file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f95fb363d79366af56c3f26b71df40b9a583b07bbaaf5b317407c4d58497852e"}, + {file = "orjson-3.10.15-cp310-cp310-win32.whl", hash = "sha256:f9875f5fea7492da8ec2444839dcc439b0ef298978f311103d0b7dfd775898ab"}, + {file = "orjson-3.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:17085a6aa91e1cd70ca8533989a18b5433e15d29c574582f76f821737c8d5806"}, + {file = "orjson-3.10.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c4cc83960ab79a4031f3119cc4b1a1c627a3dc09df125b27c4201dff2af7eaa6"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddbeef2481d895ab8be5185f2432c334d6dec1f5d1933a9c83014d188e102cef"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e590a0477b23ecd5b0ac865b1b907b01b3c5535f5e8a8f6ab0e503efb896334"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6be38bd103d2fd9bdfa31c2720b23b5d47c6796bcb1d1b598e3924441b4298d"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff4f6edb1578960ed628a3b998fa54d78d9bb3e2eb2cfc5c2a09732431c678d0"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0482b21d0462eddd67e7fce10b89e0b6ac56570424662b685a0d6fccf581e13"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bb5cc3527036ae3d98b65e37b7986a918955f85332c1ee07f9d3f82f3a6899b5"}, + {file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d569c1c462912acdd119ccbf719cf7102ea2c67dd03b99edcb1a3048651ac96b"}, + {file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1e6d33efab6b71d67f22bf2962895d3dc6f82a6273a965fab762e64fa90dc399"}, + {file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c33be3795e299f565681d69852ac8c1bc5c84863c0b0030b2b3468843be90388"}, + {file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eea80037b9fae5339b214f59308ef0589fc06dc870578b7cce6d71eb2096764c"}, + {file = "orjson-3.10.15-cp311-cp311-win32.whl", hash = "sha256:d5ac11b659fd798228a7adba3e37c010e0152b78b1982897020a8e019a94882e"}, + {file = "orjson-3.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:cf45e0214c593660339ef63e875f32ddd5aa3b4adc15e662cdb80dc49e194f8e"}, + {file = "orjson-3.10.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9d11c0714fc85bfcf36ada1179400862da3288fc785c30e8297844c867d7505a"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dba5a1e85d554e3897fa9fe6fbcff2ed32d55008973ec9a2b992bd9a65d2352d"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7723ad949a0ea502df656948ddd8b392780a5beaa4c3b5f97e525191b102fff0"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6fd9bc64421e9fe9bd88039e7ce8e58d4fead67ca88e3a4014b143cec7684fd4"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dadba0e7b6594216c214ef7894c4bd5f08d7c0135f4dd0145600be4fbcc16767"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48f59114fe318f33bbaee8ebeda696d8ccc94c9e90bc27dbe72153094e26f41"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:035fb83585e0f15e076759b6fedaf0abb460d1765b6a36f48018a52858443514"}, + {file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d13b7fe322d75bf84464b075eafd8e7dd9eae05649aa2a5354cfa32f43c59f17"}, + {file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7066b74f9f259849629e0d04db6609db4cf5b973248f455ba5d3bd58a4daaa5b"}, + {file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88dc3f65a026bd3175eb157fea994fca6ac7c4c8579fc5a86fc2114ad05705b7"}, + {file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b342567e5465bd99faa559507fe45e33fc76b9fb868a63f1642c6bc0735ad02a"}, + {file = "orjson-3.10.15-cp312-cp312-win32.whl", hash = "sha256:0a4f27ea5617828e6b58922fdbec67b0aa4bb844e2d363b9244c47fa2180e665"}, + {file = "orjson-3.10.15-cp312-cp312-win_amd64.whl", hash = "sha256:ef5b87e7aa9545ddadd2309efe6824bd3dd64ac101c15dae0f2f597911d46eaa"}, + {file = "orjson-3.10.15-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bae0e6ec2b7ba6895198cd981b7cca95d1487d0147c8ed751e5632ad16f031a6"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93ce145b2db1252dd86af37d4165b6faa83072b46e3995ecc95d4b2301b725a"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c203f6f969210128af3acae0ef9ea6aab9782939f45f6fe02d05958fe761ef9"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8918719572d662e18b8af66aef699d8c21072e54b6c82a3f8f6404c1f5ccd5e0"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f71eae9651465dff70aa80db92586ad5b92df46a9373ee55252109bb6b703307"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e117eb299a35f2634e25ed120c37c641398826c2f5a3d3cc39f5993b96171b9e"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13242f12d295e83c2955756a574ddd6741c81e5b99f2bef8ed8d53e47a01e4b7"}, + {file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7946922ada8f3e0b7b958cc3eb22cfcf6c0df83d1fe5521b4a100103e3fa84c8"}, + {file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b7155eb1623347f0f22c38c9abdd738b287e39b9982e1da227503387b81b34ca"}, + {file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:208beedfa807c922da4e81061dafa9c8489c6328934ca2a562efa707e049e561"}, + {file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eca81f83b1b8c07449e1d6ff7074e82e3fd6777e588f1a6632127f286a968825"}, + {file = "orjson-3.10.15-cp313-cp313-win32.whl", hash = "sha256:c03cd6eea1bd3b949d0d007c8d57049aa2b39bd49f58b4b2af571a5d3833d890"}, + {file = "orjson-3.10.15-cp313-cp313-win_amd64.whl", hash = "sha256:fd56a26a04f6ba5fb2045b0acc487a63162a958ed837648c5781e1fe3316cfbf"}, + {file = "orjson-3.10.15-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:5e8afd6200e12771467a1a44e5ad780614b86abb4b11862ec54861a82d677746"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da9a18c500f19273e9e104cca8c1f0b40a6470bcccfc33afcc088045d0bf5ea6"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb00b7bfbdf5d34a13180e4805d76b4567025da19a197645ca746fc2fb536586"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33aedc3d903378e257047fee506f11e0833146ca3e57a1a1fb0ddb789876c1e1"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd0099ae6aed5eb1fc84c9eb72b95505a3df4267e6962eb93cdd5af03be71c98"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c864a80a2d467d7786274fce0e4f93ef2a7ca4ff31f7fc5634225aaa4e9e98c"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c25774c9e88a3e0013d7d1a6c8056926b607a61edd423b50eb5c88fd7f2823ae"}, + {file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e78c211d0074e783d824ce7bb85bf459f93a233eb67a5b5003498232ddfb0e8a"}, + {file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:43e17289ffdbbac8f39243916c893d2ae41a2ea1a9cbb060a56a4d75286351ae"}, + {file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:781d54657063f361e89714293c095f506c533582ee40a426cb6489c48a637b81"}, + {file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6875210307d36c94873f553786a808af2788e362bd0cf4c8e66d976791e7b528"}, + {file = "orjson-3.10.15-cp38-cp38-win32.whl", hash = "sha256:305b38b2b8f8083cc3d618927d7f424349afce5975b316d33075ef0f73576b60"}, + {file = "orjson-3.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:5dd9ef1639878cc3efffed349543cbf9372bdbd79f478615a1c633fe4e4180d1"}, + {file = "orjson-3.10.15-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ffe19f3e8d68111e8644d4f4e267a069ca427926855582ff01fc012496d19969"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d433bf32a363823863a96561a555227c18a522a8217a6f9400f00ddc70139ae2"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da03392674f59a95d03fa5fb9fe3a160b0511ad84b7a3914699ea5a1b3a38da2"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a63bb41559b05360ded9132032239e47983a39b151af1201f07ec9370715c82"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3766ac4702f8f795ff3fa067968e806b4344af257011858cc3d6d8721588b53f"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a1c73dcc8fadbd7c55802d9aa093b36878d34a3b3222c41052ce6b0fc65f8e8"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b299383825eafe642cbab34be762ccff9fd3408d72726a6b2a4506d410a71ab3"}, + {file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:abc7abecdbf67a173ef1316036ebbf54ce400ef2300b4e26a7b843bd446c2480"}, + {file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:3614ea508d522a621384c1d6639016a5a2e4f027f3e4a1c93a51867615d28829"}, + {file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:295c70f9dc154307777ba30fe29ff15c1bcc9dfc5c48632f37d20a607e9ba85a"}, + {file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:63309e3ff924c62404923c80b9e2048c1f74ba4b615e7584584389ada50ed428"}, + {file = "orjson-3.10.15-cp39-cp39-win32.whl", hash = "sha256:a2f708c62d026fb5340788ba94a55c23df4e1869fec74be455e0b2f5363b8507"}, + {file = "orjson-3.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:efcf6c735c3d22ef60c4aa27a5238f1a477df85e9b15f2142f9d669beb2d13fd"}, + {file = "orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e"}, ] [[package]] @@ -2899,24 +3080,12 @@ version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] - -[[package]] -name = "parameterized" -version = "0.9.0" -description = "Parameterized testing with any Python test framework" -optional = true -python-versions = ">=3.7" -files = [ - {file = "parameterized-0.9.0-py2.py3-none-any.whl", hash = "sha256:4e0758e3d41bea3bbd05ec14fc2c24736723f243b28d702081aef438c9372b1b"}, - {file = "parameterized-0.9.0.tar.gz", hash = "sha256:7fc905272cefa4f364c1a3429cbbe9c0f98b793988efb5bf90aac80f08db09b1"}, -] - -[package.extras] -dev = ["jinja2"] +markers = {main = "(extra == \"cohere\" or extra == \"google\" or extra == \"docs\" or extra == \"local\" or extra == \"vision\" or extra == \"fastembed\") and (extra == \"cohere\" or extra == \"google\" or extra == \"docs\" or python_version < \"3.13\")"} [[package]] name = "parso" @@ -2924,6 +3093,7 @@ version = "0.8.4" description = "A Python Parser" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, @@ -2939,6 +3109,7 @@ version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, @@ -2950,6 +3121,8 @@ version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" +groups = ["dev"] +markers = "sys_platform != \"win32\"" files = [ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, @@ -2964,6 +3137,8 @@ version = "10.4.0" description = "Python Imaging Library (Fork)" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"vision\" or extra == \"fastembed\")" files = [ {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, @@ -3061,6 +3236,8 @@ version = "5.4.2" description = "Pinecone client and SDK" optional = true python-versions = "<4.0,>=3.8" +groups = ["main"] +markers = "extra == \"pinecone\"" files = [ {file = "pinecone-5.4.2-py3-none-any.whl", hash = "sha256:1fad082c66a50a229b58cda0c3a1fa0083532dc9de8303015fe4071cb25c19a8"}, {file = "pinecone-5.4.2.tar.gz", hash = "sha256:23e8aaa73b400bb11a3b626c4129284fb170f19025b82f65bd89cbb0dab2b873"}, @@ -3087,6 +3264,8 @@ version = "3.1.0" description = "Embeddings plugin for Pinecone SDK" optional = true python-versions = "<4.0,>=3.8" +groups = ["main"] +markers = "extra == \"pinecone\"" files = [ {file = "pinecone_plugin_inference-3.1.0-py3-none-any.whl", hash = "sha256:96e861527bd41e90d58b7e76abd4e713d9af28f63e76a51864dfb9cf7180e3df"}, {file = "pinecone_plugin_inference-3.1.0.tar.gz", hash = "sha256:eff826178e1fe448577be2ff3d8dbb072befbbdc2d888e214624523a1c37cd8d"}, @@ -3101,6 +3280,8 @@ version = "0.0.7" description = "Plugin interface for the Pinecone python client" optional = true python-versions = "<4.0,>=3.8" +groups = ["main"] +markers = "extra == \"pinecone\"" files = [ {file = "pinecone_plugin_interface-0.0.7-py3-none-any.whl", hash = "sha256:875857ad9c9fc8bbc074dbe780d187a2afd21f5bfe0f3b08601924a61ef1bba8"}, {file = "pinecone_plugin_interface-0.0.7.tar.gz", hash = "sha256:b8e6675e41847333aa13923cc44daa3f85676d7157324682dc1640588a982846"}, @@ -3112,6 +3293,8 @@ version = "0.9.0" description = "Text utilities library by Pinecone.io" optional = true python-versions = "<4.0,>=3.8" +groups = ["main"] +markers = "extra == \"hybrid\"" files = [ {file = "pinecone_text-0.9.0-py3-none-any.whl", hash = "sha256:7a1ad2e282d10b59f0288a2a4f4b8c583a77378172232fae573cf398a3c44240"}, {file = "pinecone_text-0.9.0.tar.gz", hash = "sha256:f8244a9bc090ee2fc904053a2415cfc114fd8bbfbc9a6ba8b0581c84990d0239"}, @@ -3141,6 +3324,7 @@ version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -3157,6 +3341,7 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -3172,6 +3357,8 @@ version = "2.10.1" description = "Wraps the portalocker recipe for easy usage" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"qdrant\"" files = [ {file = "portalocker-2.10.1-py3-none-any.whl", hash = "sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf"}, {file = "portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f"}, @@ -3187,13 +3374,14 @@ tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "p [[package]] name = "prompt-toolkit" -version = "3.0.48" +version = "3.0.50" description = "Library for building powerful interactive command lines in Python" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" +groups = ["dev"] files = [ - {file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"}, - {file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"}, + {file = "prompt_toolkit-3.0.50-py3-none-any.whl", hash = "sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198"}, + {file = "prompt_toolkit-3.0.50.tar.gz", hash = "sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab"}, ] [package.dependencies] @@ -3205,6 +3393,7 @@ version = "0.2.1" description = "Accelerated property cache" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, @@ -3292,13 +3481,15 @@ files = [ [[package]] name = "proto-plus" -version = "1.25.0" -description = "Beautiful, Pythonic protocol buffers." +version = "1.26.0" +description = "Beautiful, Pythonic protocol buffers" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ - {file = "proto_plus-1.25.0-py3-none-any.whl", hash = "sha256:c91fc4a65074ade8e458e95ef8bac34d4008daa7cce4a12d6707066fca648961"}, - {file = "proto_plus-1.25.0.tar.gz", hash = "sha256:fbb17f57f7bd05a68b7707e745e26528b0b3c34e378db91eef93912c54982d91"}, + {file = "proto_plus-1.26.0-py3-none-any.whl", hash = "sha256:bf2dfaa3da281fc3187d12d224c707cb57214fb2c22ba854eb0c105a3fb2d4d7"}, + {file = "proto_plus-1.26.0.tar.gz", hash = "sha256:6e93d5f5ca267b54300880fff156b6a3386b3fa3f43b1da62e680fc0c586ef22"}, ] [package.dependencies] @@ -3313,6 +3504,8 @@ version = "5.29.3" description = "" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "(extra == \"qdrant\" or extra == \"google\" or extra == \"fastembed\") and (extra == \"qdrant\" or extra == \"google\" or python_version < \"3.13\")" files = [ {file = "protobuf-5.29.3-cp310-abi3-win32.whl", hash = "sha256:3ea51771449e1035f26069c4c7fd51fba990d07bc55ba80701c78f886bf9c888"}, {file = "protobuf-5.29.3-cp310-abi3-win_amd64.whl", hash = "sha256:a4fa6f80816a9a0678429e84973f2f98cbc218cca434abe8db2ad0bffc98503a"}, @@ -3333,6 +3526,7 @@ version = "6.1.1" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +groups = ["dev"] files = [ {file = "psutil-6.1.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9ccc4316f24409159897799b83004cb1e24f9819b0dcf9c0b68bdcb6cefee6a8"}, {file = "psutil-6.1.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ca9609c77ea3b8481ab005da74ed894035936223422dc591d6772b147421f777"}, @@ -3363,6 +3557,7 @@ version = "2.9.10" description = "psycopg2 - Python-PostgreSQL Database Adapter" optional = true python-versions = ">=3.8" +groups = ["main"] files = [ {file = "psycopg2-binary-2.9.10.tar.gz", hash = "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2"}, {file = "psycopg2_binary-2.9.10-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f"}, @@ -3411,6 +3606,7 @@ files = [ {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909"}, {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1"}, {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142"}, {file = "psycopg2_binary-2.9.10-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4"}, {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8"}, {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864"}, @@ -3439,6 +3635,8 @@ version = "0.7.0" description = "Run a subprocess in a pseudo terminal" optional = false python-versions = "*" +groups = ["dev"] +markers = "sys_platform != \"win32\"" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, @@ -3450,6 +3648,7 @@ version = "0.2.3" description = "Safely evaluate AST nodes without side effects" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, @@ -3464,6 +3663,8 @@ version = "0.6.1" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, @@ -3475,6 +3676,8 @@ version = "0.4.1" description = "A collection of ASN.1-based protocols modules" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, @@ -3489,6 +3692,8 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "implementation_name == \"pypy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -3496,13 +3701,14 @@ files = [ [[package]] name = "pydantic" -version = "2.10.5" +version = "2.10.6" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, - {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, + {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, + {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, ] [package.dependencies] @@ -3520,6 +3726,7 @@ version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, @@ -3632,10 +3839,12 @@ version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, ] +markers = {main = "extra == \"docs\""} [package.extras] windows-terminal = ["colorama (>=0.4.6)"] @@ -3646,6 +3855,8 @@ version = "3.5.4" description = "A python implementation of GNU readline." optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\" and sys_platform == \"win32\"" files = [ {file = "pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6"}, {file = "pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7"}, @@ -3660,6 +3871,8 @@ version = "2.2.0.3" description = "Snowball stemming algorithms, for information retrieval" optional = true python-versions = "*" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\"" files = [ {file = "PyStemmer-2.2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2935aa78a89b04899de4a8b8b6339806e0d5cd93811de52e98829b5762cf913c"}, {file = "PyStemmer-2.2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:31c9d3c808647d4c569737b32b40ed23c67133d2b89033ebc8b5756cadf6f1c1"}, @@ -3751,6 +3964,7 @@ version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, @@ -3773,6 +3987,7 @@ version = "0.24.0" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b"}, {file = "pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276"}, @@ -3791,6 +4006,7 @@ version = "4.1.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, @@ -3809,6 +4025,7 @@ version = "3.14.0" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, @@ -3826,6 +4043,7 @@ version = "3.6.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, @@ -3846,10 +4064,12 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] +markers = {main = "extra == \"pinecone\" or extra == \"google\" or extra == \"bedrock\""} [package.dependencies] six = ">=1.5" @@ -3860,6 +4080,7 @@ version = "1.0.1" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, @@ -3874,6 +4095,7 @@ version = "308" description = "Python for Window Extensions" optional = false python-versions = "*" +groups = ["main", "dev"] files = [ {file = "pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e"}, {file = "pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e"}, @@ -3894,6 +4116,7 @@ files = [ {file = "pywin32-308-cp39-cp39-win32.whl", hash = "sha256:7873ca4dc60ab3287919881a7d4f88baee4a6e639aa6962de25a98ba6b193341"}, {file = "pywin32-308-cp39-cp39-win_amd64.whl", hash = "sha256:71b3322d949b4cc20776436a9c9ba0eeedcbc9c650daa536df63f0ff111bb920"}, ] +markers = {main = "extra == \"qdrant\" and platform_system == \"Windows\"", dev = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} [[package]] name = "pyyaml" @@ -3901,6 +4124,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -3963,6 +4187,7 @@ version = "26.2.0" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pyzmq-26.2.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ddf33d97d2f52d89f6e6e7ae66ee35a4d9ca6f36eda89c24591b0c40205a3629"}, {file = "pyzmq-26.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dacd995031a01d16eec825bf30802fceb2c3791ef24bcce48fa98ce40918c27b"}, @@ -4084,6 +4309,8 @@ version = "1.12.1" description = "Client library for the Qdrant vector search engine" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "python_version >= \"3.13\" and extra == \"qdrant\"" files = [ {file = "qdrant_client-1.12.1-py3-none-any.whl", hash = "sha256:b2d17ce18e9e767471368380dd3bbc4a0e3a0e2061fedc9af3542084b48451e0"}, {file = "qdrant_client-1.12.1.tar.gz", hash = "sha256:35e8e646f75b7b883b3d2d0ee4c69c5301000bba41c82aa546e985db0f1aeb72"}, @@ -4104,13 +4331,15 @@ fastembed-gpu = ["fastembed-gpu (==0.3.6)"] [[package]] name = "qdrant-client" -version = "1.12.2" +version = "1.13.2" description = "Client library for the Qdrant vector search engine" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"qdrant\"" files = [ - {file = "qdrant_client-1.12.2-py3-none-any.whl", hash = "sha256:a0ae500a46a679ff3521ba3f1f1cf3d72b57090a768cec65fc317066bcbac1e6"}, - {file = "qdrant_client-1.12.2.tar.gz", hash = "sha256:2777e09b3e89bb22bb490384d8b1fa8140f3915287884f18984f7031a346aba5"}, + {file = "qdrant_client-1.13.2-py3-none-any.whl", hash = "sha256:db97e759bd3f8d483a383984ba4c2a158eef56f2188d83df7771591d43de2201"}, + {file = "qdrant_client-1.13.2.tar.gz", hash = "sha256:c8cce87ce67b006f49430a050a35c85b78e3b896c0c756dafc13bdeca543ec13"}, ] [package.dependencies] @@ -4127,8 +4356,8 @@ pydantic = ">=1.10.8" urllib3 = ">=1.26.14,<3" [package.extras] -fastembed = ["fastembed (==0.5.0)"] -fastembed-gpu = ["fastembed-gpu (==0.5.0)"] +fastembed = ["fastembed (==0.5.1)"] +fastembed-gpu = ["fastembed-gpu (==0.5.1)"] [[package]] name = "regex" @@ -4136,6 +4365,7 @@ version = "2024.11.6" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, @@ -4239,6 +4469,7 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -4260,6 +4491,7 @@ version = "1.12.1" description = "Mock out responses from the requests package" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401"}, {file = "requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563"}, @@ -4277,6 +4509,7 @@ version = "1.0.0" description = "A utility belt for advanced users of python-requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main"] files = [ {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, @@ -4291,6 +4524,8 @@ version = "4.9" description = "Pure-Python RSA implementation" optional = true python-versions = ">=3.6,<4" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, @@ -4305,6 +4540,7 @@ version = "0.1.15" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5fe8d54df166ecc24106db7dd6a68d44852d14eb0729ea4672bb4d96c320b7df"}, {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6f0bfbb53c4b4de117ac4d6ddfd33aa5fc31beeaa21d23c45c6dd249faf9126f"}, @@ -4327,20 +4563,22 @@ files = [ [[package]] name = "s3transfer" -version = "0.10.4" +version = "0.11.2" description = "An Amazon S3 Transfer Manager" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"bedrock\"" files = [ - {file = "s3transfer-0.10.4-py3-none-any.whl", hash = "sha256:244a76a24355363a68164241438de1b72f8781664920260c48465896b712a41e"}, - {file = "s3transfer-0.10.4.tar.gz", hash = "sha256:29edc09801743c21eb5ecbc617a152df41d3c287f67b615f73e5f750583666a7"}, + {file = "s3transfer-0.11.2-py3-none-any.whl", hash = "sha256:be6ecb39fadd986ef1701097771f87e4d2f821f27f6071c872143884d2950fbc"}, + {file = "s3transfer-0.11.2.tar.gz", hash = "sha256:3b39185cb72f5acc77db1a58b6e25b977f28d20496b6e58d6813d75f464d632f"}, ] [package.dependencies] -botocore = ">=1.33.2,<2.0a.0" +botocore = ">=1.36.0,<2.0a.0" [package.extras] -crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] +crt = ["botocore[crt] (>=1.36.0,<2.0a.0)"] [[package]] name = "safetensors" @@ -4348,6 +4586,8 @@ version = "0.5.2" description = "" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\")" files = [ {file = "safetensors-0.5.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:45b6092997ceb8aa3801693781a71a99909ab9cc776fbc3fa9322d29b1d3bef2"}, {file = "safetensors-0.5.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6d0d6a8ee2215a440e1296b843edf44fd377b055ba350eaba74655a2fe2c4bae"}, @@ -4385,6 +4625,8 @@ version = "75.8.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"qdrant\"" files = [ {file = "setuptools-75.8.0-py3-none-any.whl", hash = "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3"}, {file = "setuptools-75.8.0.tar.gz", hash = "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6"}, @@ -4405,6 +4647,8 @@ version = "2.0.6" description = "Manipulation and analysis of geometric objects" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"google\"" files = [ {file = "shapely-2.0.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29a34e068da2d321e926b5073539fd2a1d4429a2c656bd63f0bd4c8f5b236d0b"}, {file = "shapely-2.0.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c84c3f53144febf6af909d6b581bc05e8785d57e27f35ebaa5c1ab9baba13b"}, @@ -4463,10 +4707,12 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] +markers = {main = "extra == \"pinecone\" or extra == \"google\" or extra == \"bedrock\""} [[package]] name = "sniffio" @@ -4474,6 +4720,7 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -4485,6 +4732,8 @@ version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." optional = true python-versions = "*" +groups = ["main"] +markers = "extra == \"docs\" or extra == \"fastembed\" and python_version < \"3.13\"" files = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, @@ -4496,6 +4745,8 @@ version = "2.6" description = "A modern CSS selector implementation for Beautiful Soup." optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, @@ -4507,6 +4758,8 @@ version = "7.3.7" description = "Python documentation generator" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "python_version >= \"3.10\" and python_version < \"3.13\" and extra == \"docs\"" files = [ {file = "sphinx-7.3.7-py3-none-any.whl", hash = "sha256:413f75440be4cacf328f580b4274ada4565fb2187d696a84970c23f77b64d8c3"}, {file = "sphinx-7.3.7.tar.gz", hash = "sha256:a4a7db75ed37531c05002d56ed6948d4c42f473a36f46e1382b0bd76ca9627bc"}, @@ -4543,6 +4796,8 @@ version = "7.4.7" description = "Python documentation generator" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "(python_version < \"3.10\" or python_version >= \"3.13\") and extra == \"docs\"" files = [ {file = "sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239"}, {file = "sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe"}, @@ -4579,6 +4834,8 @@ version = "5.2.0" description = "An awesome theme for the Sphinx documentation generator" optional = true python-versions = "<4.0,>=3.8" +groups = ["main"] +markers = "python_version >= \"3.10\" and python_version < \"3.13\" and extra == \"docs\"" files = [ {file = "sphinxawesome_theme-5.2.0-py3-none-any.whl", hash = "sha256:56f1462f4ec4a5d66017819de6b7965a394d4157117bf12f029e7818d6789525"}, {file = "sphinxawesome_theme-5.2.0.tar.gz", hash = "sha256:c24f1e5c0b9e475380d16fc5f1f3bfd84955817da0905d95f7e20809d7cd3c5d"}, @@ -4594,6 +4851,8 @@ version = "5.3.2" description = "An awesome theme for the Sphinx documentation generator" optional = true python-versions = "<4.0,>=3.8" +groups = ["main"] +markers = "(python_version < \"3.10\" or python_version >= \"3.13\") and extra == \"docs\"" files = [ {file = "sphinxawesome_theme-5.3.2-py3-none-any.whl", hash = "sha256:5f2bb6b6ab8fa11db1ded5590106eb557351d6a6c36adea7ebd4e0f4bc96945d"}, {file = "sphinxawesome_theme-5.3.2.tar.gz", hash = "sha256:0629d38b80aefc279b1186c53a7a6faf21e721b5b2ecda14f488ca1074e2631f"}, @@ -4609,6 +4868,8 @@ version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, @@ -4625,6 +4886,8 @@ version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, @@ -4641,6 +4904,8 @@ version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, @@ -4657,6 +4922,8 @@ version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" optional = true python-versions = ">=3.5" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, @@ -4671,6 +4938,8 @@ version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, @@ -4687,6 +4956,8 @@ version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"docs\"" files = [ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, @@ -4703,6 +4974,7 @@ version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, @@ -4722,6 +4994,8 @@ version = "1.13.3" description = "Computer algebra system (CAS) in Python" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\" or extra == \"fastembed\")" files = [ {file = "sympy-1.13.3-py3-none-any.whl", hash = "sha256:54612cf55a62755ee71824ce692986f23c88ffa77207b30c1368eda4a7060f73"}, {file = "sympy-1.13.3.tar.gz", hash = "sha256:b27fd2c6530e0ab39e275fc9b683895367e51d5da91baa8d3d64db2565fec4d9"}, @@ -4739,6 +5013,7 @@ version = "0.8.0" description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "tiktoken-0.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b07e33283463089c81ef1467180e3e00ab00d46c2c4bbcef0acab5f771d6695e"}, {file = "tiktoken-0.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9269348cb650726f44dd3bbb3f9110ac19a8dcc8f54949ad3ef652ca22a38e21"}, @@ -4786,6 +5061,7 @@ version = "6.1.0" description = "A wrapper around the stdlib `tokenize` which roundtrips." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "tokenize_rt-6.1.0-py2.py3-none-any.whl", hash = "sha256:d706141cdec4aa5f358945abe36b911b8cbdc844545da99e811250c0cee9b6fc"}, {file = "tokenize_rt-6.1.0.tar.gz", hash = "sha256:e8ee836616c0877ab7c7b54776d2fefcc3bde714449a206762425ae114b53c86"}, @@ -4797,6 +5073,8 @@ version = "0.21.0" description = "" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "(extra == \"cohere\" or extra == \"local\" or extra == \"vision\" or extra == \"fastembed\") and (extra == \"cohere\" or python_version < \"3.13\")" files = [ {file = "tokenizers-0.21.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:3c4c93eae637e7d2aaae3d376f06085164e1660f89304c0ab2b1d08a406636b2"}, {file = "tokenizers-0.21.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:f53ea537c925422a2e0e92a24cce96f6bc5046bbef24a1652a5edc8ba975f62e"}, @@ -4829,6 +5107,7 @@ version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -4863,6 +5142,7 @@ files = [ {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] +markers = {main = "python_version < \"3.11\" and extra == \"docs\"", dev = "python_version < \"3.11\""} [[package]] name = "torch" @@ -4870,6 +5150,8 @@ version = "2.2.2" description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" optional = true python-versions = ">=3.8.0" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\")" files = [ {file = "torch-2.2.2-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:bc889d311a855dd2dfd164daf8cc903a6b7273a747189cebafdd89106e4ad585"}, {file = "torch-2.2.2-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:15dffa4cc3261fa73d02f0ed25f5fa49ecc9e12bf1ae0a4c1e7a88bbfaad9030"}, @@ -4928,6 +5210,8 @@ version = "0.17.2" description = "image and video datasets and models for torch deep learning" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"vision\"" files = [ {file = "torchvision-0.17.2-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:1f2910fe3c21ad6875b2720d46fad835b2e4b336e9553d31ca364d24c90b1d4f"}, {file = "torchvision-0.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ecc1c503fa8a54fbab777e06a7c228032b8ab78efebf35b28bc8f22f544f51f1"}, @@ -4970,6 +5254,7 @@ version = "6.4.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1"}, {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803"}, @@ -4990,6 +5275,7 @@ version = "4.67.1" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, @@ -5011,6 +5297,7 @@ version = "5.14.3" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, @@ -5022,13 +5309,15 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, [[package]] name = "transformers" -version = "4.48.0" +version = "4.48.1" description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow" optional = true python-versions = ">=3.9.0" +groups = ["main"] +markers = "python_version < \"3.13\" and (extra == \"local\" or extra == \"vision\")" files = [ - {file = "transformers-4.48.0-py3-none-any.whl", hash = "sha256:6d3de6d71cb5f2a10f9775ccc17abce9620195caaf32ec96542bd2a6937f25b0"}, - {file = "transformers-4.48.0.tar.gz", hash = "sha256:03fdfcbfb8b0367fb6c9fbe9d1c9aa54dfd847618be9b52400b2811d22799cb1"}, + {file = "transformers-4.48.1-py3-none-any.whl", hash = "sha256:24be0564b0a36d9e433d9a65de248f1545b6f6edce1737669605eb6a8141bbbb"}, + {file = "transformers-4.48.1.tar.gz", hash = "sha256:7c1931facc3ee8adcbf86fc7a87461d54c1e40eca3bb57fef1ee9f3ecd32187e"}, ] [package.dependencies] @@ -5095,6 +5384,8 @@ version = "2.2.0" description = "A language and compiler for custom Deep Learning operations" optional = true python-versions = "*" +groups = ["main"] +markers = "python_version < \"3.12\" and (extra == \"local\" or extra == \"vision\") and platform_system == \"Linux\" and platform_machine == \"x86_64\"" files = [ {file = "triton-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2294514340cfe4e8f4f9e5c66c702744c4a117d25e618bd08469d0bfed1e2e5"}, {file = "triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da58a152bddb62cafa9a857dd2bc1f886dbf9f9c90a2b5da82157cd2b34392b0"}, @@ -5118,6 +5409,7 @@ version = "6.0.12.20241230" description = "Typing stubs for PyYAML" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "types_PyYAML-6.0.12.20241230-py3-none-any.whl", hash = "sha256:fa4d32565219b68e6dee5f67534c722e53c00d1cfc09c435ef04d7353e1e96e6"}, {file = "types_pyyaml-6.0.12.20241230.tar.gz", hash = "sha256:7f07622dbd34bb9c8b264fe860a17e0efcad00d50b5f27e93984909d9363498c"}, @@ -5129,6 +5421,8 @@ version = "2.31.0.6" description = "Typing stubs for requests" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version < \"3.10\"" files = [ {file = "types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0"}, {file = "types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9"}, @@ -5143,6 +5437,8 @@ version = "2.32.0.20241016" description = "Typing stubs for requests" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version >= \"3.10\"" files = [ {file = "types-requests-2.32.0.20241016.tar.gz", hash = "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95"}, {file = "types_requests-2.32.0.20241016-py3-none-any.whl", hash = "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747"}, @@ -5157,6 +5453,8 @@ version = "1.26.25.14" description = "Typing stubs for urllib3" optional = false python-versions = "*" +groups = ["main", "dev"] +markers = "python_version < \"3.10\"" files = [ {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"}, {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"}, @@ -5168,6 +5466,7 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -5179,6 +5478,8 @@ version = "1.26.20" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +groups = ["main"] +markers = "python_version < \"3.10\"" files = [ {file = "urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e"}, {file = "urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"}, @@ -5195,6 +5496,8 @@ version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" +groups = ["main", "dev"] +markers = "python_version >= \"3.10\"" files = [ {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, @@ -5212,6 +5515,7 @@ version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, @@ -5223,6 +5527,8 @@ version = "3.2" description = "pure python download utility" optional = true python-versions = "*" +groups = ["main"] +markers = "extra == \"hybrid\"" files = [ {file = "wget-3.2.zip", hash = "sha256:35e630eca2aa50ce998b9b1a127bb26b30dfee573702782aa982f875e3f16061"}, ] @@ -5233,6 +5539,8 @@ version = "1.2.0" description = "A small Python utility to set file creation time on Windows" optional = true python-versions = ">=3.5" +groups = ["main"] +markers = "python_version < \"3.13\" and extra == \"fastembed\" and sys_platform == \"win32\"" files = [ {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, @@ -5247,6 +5555,7 @@ version = "1.18.3" description = "Yet another URL library" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, @@ -5343,10 +5652,12 @@ version = "3.21.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.9" +groups = ["main", "dev"] files = [ {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, ] +markers = {main = "python_version < \"3.10\" and extra == \"docs\"", dev = "python_version < \"3.10\""} [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] @@ -5371,6 +5682,6 @@ qdrant = ["qdrant-client"] vision = ["pillow", "torch", "torchvision", "transformers"] [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = ">=3.9,<3.14" -content-hash = "fcb5e5f8137489b59e3a38daa3093ff796c52717ce2dffead6a124378d910f39" +content-hash = "b89e6282250711c2c36696b57ef8798bcb1d549ef00822e95a523f627994c382" diff --git a/pyproject.toml b/pyproject.toml index ee754493..ba02e39e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ mistralai= {version = ">=0.0.12,<0.1.0", optional = true} numpy = "^1.25.2" colorlog = "^6.8.0" pyyaml = "^6.0.1" -aurelio-sdk = {version = "^0.0.16"} +aurelio-sdk = {version = "^0.0.18"} pinecone-text = {version = ">=0.7.1", optional = true} torch = {version = ">=2.1.0,<2.6.0", optional = true, python = "<3.13" } transformers = {version = ">=4.36.2", optional = true, python = "<3.13" } diff --git a/semantic_router/index/__init__.py b/semantic_router/index/__init__.py index 14b60da3..9ffd35c6 100644 --- a/semantic_router/index/__init__.py +++ b/semantic_router/index/__init__.py @@ -2,6 +2,7 @@ from semantic_router.index.hybrid_local import HybridLocalIndex from semantic_router.index.local import LocalIndex from semantic_router.index.pinecone import PineconeIndex +from semantic_router.index.pinecone_local import PineconeLocalIndex from semantic_router.index.postgres import PostgresIndex from semantic_router.index.qdrant import QdrantIndex @@ -11,5 +12,6 @@ "LocalIndex", "QdrantIndex", "PineconeIndex", + "PineconeLocalIndex", "PostgresIndex", ] diff --git a/semantic_router/index/pinecone_local.py b/semantic_router/index/pinecone_local.py new file mode 100644 index 00000000..04f544d0 --- /dev/null +++ b/semantic_router/index/pinecone_local.py @@ -0,0 +1,1037 @@ +import asyncio +import hashlib +import json +import os +import time +from typing import Any, Dict, List, Optional, Union + + +import aiohttp +import numpy as np +import requests +from pydantic import BaseModel, Field + +from semantic_router.index.base import BaseIndex, IndexConfig +from semantic_router.schema import ConfigParameter, SparseEmbedding +from semantic_router.utils.logger import logger + + +def clean_route_name(route_name: str) -> str: + return route_name.strip().replace(" ", "-") + + +class DeleteRequest(BaseModel): + ids: list[str] | None = None + delete_all: bool = False + namespace: str | None = None + filter: dict[str, Any] | None = None + + +def build_records( + embeddings: list[list[float]], + routes: list[str], + utterances: list[str], + function_schemas: list[dict[str, Any]] | None | None = None, + metadata_list: list[dict[str, Any]] | None = None, + sparse_embeddings: list[SparseEmbedding] | None | None = None, +) -> list[dict]: + if function_schemas is None: + function_schemas = [{}] * len(embeddings) + if metadata_list is None: + metadata_list = [] + if sparse_embeddings is None: + vectors_to_upsert = [ + PineconeRecord( + values=vector, + route=route, + utterance=utterance, + function_schema=json.dumps(function_schema), + metadata=metadata, + ).to_dict() + for vector, route, utterance, function_schema, metadata in zip( + embeddings, + routes, + utterances, + function_schemas, + metadata_list, + ) + ] + else: + vectors_to_upsert = [ + PineconeRecord( + values=vector, + sparse_values=sparse_emb.to_pinecone(), + route=route, + utterance=utterance, + function_schema=json.dumps(function_schema), + metadata=metadata, + ).to_dict() + for vector, route, utterance, function_schema, metadata, sparse_emb in zip( + embeddings, + routes, + utterances, + function_schemas, + metadata_list, + sparse_embeddings, + ) + ] + return vectors_to_upsert + + +class PineconeRecord(BaseModel): + id: str = "" + values: List[float] + sparse_values: Optional[dict[str, list]] = None + route: str + utterance: str + function_schema: str = "{}" + metadata: Dict[str, Any] = {} # Additional metadata dictionary + + def __init__(self, **data): + super().__init__(**data) + clean_route = clean_route_name(self.route) + # Use SHA-256 for a more secure hash + utterance_id = hashlib.sha256(self.utterance.encode()).hexdigest() + self.id = f"{clean_route}#{utterance_id}" + self.metadata.update( + { + "sr_route": self.route, + "sr_utterance": self.utterance, + "sr_function_schema": self.function_schema, + } + ) + + def to_dict(self): + d = { + "id": self.id, + "values": self.values, + "metadata": self.metadata, + } + if self.sparse_values: + d["sparse_values"] = self.sparse_values + return d + + +class PineconeLocalIndex(BaseIndex): + index_prefix: str = "semantic-router--" + api_key: Optional[str] = None + index_name: str = "index" + dimensions: Union[int, None] = None + metric: str = "dotproduct" + cloud: str = "aws" + region: str = "us-east-1" + host: str = "" + client: Any = Field(default=None, exclude=True) + index: Optional[Any] = Field(default=None, exclude=True) + ServerlessSpec: Any = Field(default=None, exclude=True) + namespace: Optional[str] = "" + base_url: Optional[str] = "http://localhost:5080" + headers: dict[str, str] = {} + index_host: Optional[str] = "http://localhost:5080" + + def __init__( + self, + api_key: Optional[str] = None, + index_name: str = "index", + dimensions: Optional[int] = None, + metric: str = "dotproduct", + cloud: str = "aws", + region: str = "us-east-1", + host: str = "", + namespace: Optional[str] = "", + base_url: Optional[str] = None, + init_async_index: bool = False, + ): + super().__init__() + self.api_key = api_key or os.getenv("PINECONE_API_KEY") + logger.warning(f"Pinecone API key: {self.api_key}") + logger.warning(f"Pinecone API key os env: {os.getenv('PINECONE_API_KEY')}") + + if not self.api_key: + raise ValueError("Pinecone API key is required.") + self.headers = { + "Api-Key": self.api_key, + "Content-Type": "application/json", + "User-Agent": "source_tag=semanticrouter", + } + self.index_name = index_name + self.dimensions = dimensions + self.metric = metric + self.cloud = cloud + self.region = region + self.host = host + if namespace == "sr_config": + raise ValueError("Namespace 'sr_config' is reserved for internal use.") + self.namespace = namespace + self.type = "pinecone" + # self.api_key = api_key or os.getenv("PINECONE_API_KEY") + self.base_url = base_url or os.getenv("PINECONE_API_BASE_URL") + + logger.warning( + "Default region changed from us-west-2 to us-east-1 in v0.1.0.dev6" + ) + + # if self.api_key is None: + # raise ValueError("Pinecone API key is required.") + + self.client = self._initialize_client(api_key=self.api_key) + # if init_async_index: + # self.async_client = self._initialize_async_client(api_key=self.api_key) + # else: + # self.async_client = None + # try initializing index + self.index = self._init_index() + + def _initialize_client(self, api_key: str | None = None): + try: + from pinecone import Pinecone, ServerlessSpec + + self.ServerlessSpec = ServerlessSpec + except ImportError: + raise ImportError( + "Please install pinecone-client to use PineconeIndex. " + "You can install it with: " + "`pip install 'semantic-router[pinecone]'`" + ) + pinecone_args = { + "api_key": api_key, + "source_tag": "semanticrouter", + "host": self.base_url, + } + if self.namespace: + pinecone_args["namespace"] = self.namespace + + return Pinecone(**pinecone_args) + + # def _initialize_async_client(self, api_key: str | None = None): + # api_key = api_key or self.api_key + # if api_key is None: + # raise ValueError("Pinecone API key is required.") + # async_client = aiohttp.ClientSession( + # headers={ + # "Api-Key": api_key, + # "Content-Type": "application/json", + # "X-Pinecone-API-Version": "2024-07", + # "User-Agent": "source_tag=semanticrouter", + # } + # ) + # return async_client + + def _init_index(self, force_create: bool = False) -> Any | None: + """Initializing the index can be done after the object has been created + to allow for the user to set the dimensions and other parameters. + + If the index doesn't exist and the dimensions are given, the index will + be created. If the index exists, it will be returned. If the index doesn't + exist and the dimensions are not given, the index will not be created and + None will be returned. + + :param force_create: If True, the index will be created even if the + dimensions are not given (which will raise an error). + :type force_create: bool, optional + """ + index_exists = self.index_name in self.client.list_indexes().names() + dimensions_given = self.dimensions is not None + # pinecone_base_url = os.getenv("PINECONE_API_BASE_URL") + + # if not pinecone_base_url: + # pinecone_base_url = "http://localhost:5080" + + if dimensions_given and not index_exists: + # if the index doesn't exist and we have dimension value + # we create the index + self.client.create_index( + name=self.index_name, + dimension=self.dimensions, + metric=self.metric, + spec=self.ServerlessSpec(cloud=self.cloud, region=self.region), + ) + # wait for index to be created + while not self.client.describe_index(self.index_name).status["ready"]: + time.sleep(1) + index = self.client.Index(self.index_name) + self.index_host = self.client.describe_index(self.index_name).host + time.sleep(0.5) + elif index_exists: + # if the index exists we just return it + self.index_host = self.client.describe_index(self.index_name).host + + if self.index_host and self.base_url: + if "http" not in self.index_host: + self.index_host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.index_host.split(':')[-1]}" + elif not self.index_host.startswith("http://"): + + # TODO: Need to pass the an argument for service name + if "localhost" in self.index_host: + self.index_host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.index_host.split(':')[-1]}" + logger.error(f"index exists:{self.index_host}") + else: + self.index_host = f"http://{self.index_host}" + index = self.client.Index(self.index_name, host=self.index_host) + self.host = self.index_host + logger.error(f"index_host exists:{self.index_host}") + logger.error(f"index exists:{index}") + # grab the dimensions from the index + self.dimensions = index.describe_index_stats()["dimension"] + elif force_create and not dimensions_given: + raise ValueError( + "Cannot create an index without specifying the dimensions." + ) + else: + # if the index doesn't exist and we don't have the dimensions + # we return None + logger.warning( + "Index could not be initialized. Init parameters: " + f"{self.index_name=}, {self.dimensions=}, {self.metric=}, " + f"{self.cloud=}, {self.region=}, {self.host=}, {self.namespace=}, " + f"{force_create=}" + ) + index = None + if index is not None: + self.host = self.client.describe_index(self.index_name)["host"] + return index + + async def _init_async_index(self, force_create: bool = False): + index_stats = None + indexes = await self._async_list_indexes() + index_names = [i["name"] for i in indexes["indexes"]] + index_exists = self.index_name in index_names + if self.dimensions is not None and not index_exists: + await self._async_create_index( + name=self.index_name, + dimension=self.dimensions, + metric=self.metric, + cloud=self.cloud, + region=self.region, + ) + # TODO describe index and async sleep + index_ready = "false" + while index_ready != "true": + index_stats = await self._async_describe_index(self.index_name) + index_ready = index_stats["status"]["ready"] + await asyncio.sleep(1) + elif index_exists: + index_stats = await self._async_describe_index(self.index_name) + # grab dimensions for the index + self.dimensions = index_stats["dimension"] + elif force_create and self.dimensions is None: + raise ValueError( + "Cannot create an index without specifying the dimensions." + ) + else: + # if the index doesn't exist and we don't have the dimensions + # we raise warning + logger.warning( + "Index could not be initialized. Init parameters: " + f"{self.index_name=}, {self.dimensions=}, {self.metric=}, " + f"{self.cloud=}, {self.region=}, {self.host=}, {self.namespace=}, " + f"{force_create=}" + ) + logger.error(f"index_stats: {index_stats}") + self.host = index_stats["host"] if index_stats else "" + + def _batch_upsert(self, batch: List[Dict]): + """Helper method for upserting a single batch of records. + + :param batch: The batch of records to upsert. + :type batch: List[Dict] + """ + if self.index is not None: + self.index.upsert(vectors=batch, namespace=self.namespace) + else: + raise ValueError("Index is None, could not upsert.") + + def add( + self, + embeddings: list[list[float]], + routes: list[str], + utterances: list[str], + function_schemas: list[dict[str, Any]] | None | None = None, + metadata_list: list[dict[str, Any]] | None = None, + batch_size: int = 100, + sparse_embeddings: list[SparseEmbedding] | None | None = None, + **kwargs, + ): + """Add vectors to Pinecone in batches.""" + if metadata_list is None: + metadata_list = [] + if self.index is None: + self.dimensions = self.dimensions or len(embeddings[0]) + self.index = self._init_index(force_create=True) + vectors_to_upsert = build_records( + embeddings=embeddings, + routes=routes, + utterances=utterances, + function_schemas=function_schemas, + metadata_list=metadata_list, + sparse_embeddings=sparse_embeddings, + ) + for i in range(0, len(vectors_to_upsert), batch_size): + batch = vectors_to_upsert[i : i + batch_size] + self._batch_upsert(batch) + + async def aadd( + self, + embeddings: list[list[float]], + routes: list[str], + utterances: list[str], + function_schemas: list[dict[str, Any]] | None | None = None, + metadata_list: list[dict[str, Any]] | None = None, + batch_size: int = 100, + sparse_embeddings: list[SparseEmbedding] | None | None = None, + **kwargs, + ): + """Add vectors to Pinecone in batches.""" + if metadata_list is None: + metadata_list = [] + if self.index is None: + self.dimensions = self.dimensions or len(embeddings[0]) + self.index = await self._init_async_index(force_create=True) + vectors_to_upsert = build_records( + embeddings=embeddings, + routes=routes, + utterances=utterances, + function_schemas=function_schemas, + metadata_list=metadata_list, + sparse_embeddings=sparse_embeddings, + ) + + for i in range(0, len(vectors_to_upsert), batch_size): + batch = vectors_to_upsert[i : i + batch_size] + await self._async_upsert( + vectors=batch, + namespace=self.namespace or "", + ) + + def _remove_and_sync(self, routes_to_delete: dict): + for route, utterances in routes_to_delete.items(): + remote_routes = self._get_routes_with_ids(route_name=route) + ids_to_delete = [ + r["id"] + for r in remote_routes + if (r["route"], r["utterance"]) + in zip([route] * len(utterances), utterances) + ] + if ids_to_delete and self.index: + self.index.delete(ids=ids_to_delete, namespace=self.namespace) + + async def _async_remove_and_sync(self, routes_to_delete: dict): + for route, utterances in routes_to_delete.items(): + remote_routes = await self._async_get_routes_with_ids(route_name=route) + ids_to_delete = [ + r["id"] + for r in remote_routes + if (r["route"], r["utterance"]) + in zip([route] * len(utterances), utterances) + ] + if ids_to_delete and self.index: + await self._async_delete( + ids=ids_to_delete, namespace=self.namespace or "" + ) + + def _get_route_ids(self, route_name: str): + clean_route = clean_route_name(route_name) + ids, _ = self._get_all(prefix=f"{clean_route}#") + return ids + + async def _async_get_route_ids(self, route_name: str): + clean_route = clean_route_name(route_name) + ids, _ = await self._async_get_all(prefix=f"{clean_route}#") + return ids + + def _get_routes_with_ids(self, route_name: str): + clean_route = clean_route_name(route_name) + ids, metadata = self._get_all(prefix=f"{clean_route}#", include_metadata=True) + route_tuples = [] + for id, data in zip(ids, metadata): + route_tuples.append( + { + "id": id, + "route": data["sr_route"], + "utterance": data["sr_utterance"], + } + ) + return route_tuples + + async def _async_get_routes_with_ids(self, route_name: str): + clean_route = clean_route_name(route_name) + ids, metadata = await self._async_get_all( + prefix=f"{clean_route}#", include_metadata=True + ) + route_tuples = [] + for id, data in zip(ids, metadata): + route_tuples.append( + {"id": id, "route": data["sr_route"], "utterance": data["sr_utterance"]} + ) + return route_tuples + + def _get_all(self, prefix: str | None = None, include_metadata: bool = False): + """ + Retrieves all vector IDs from the Pinecone index using pagination. + + :param prefix: The prefix to filter the vectors by. + :type prefix: Optional[str] + :param include_metadata: Whether to include metadata in the response. + :type include_metadata: bool + :return: A tuple containing a list of vector IDs and a list of metadata dictionaries. + :rtype: tuple[list[str], list[dict]] + """ + if self.index is None: + raise ValueError("Index is None, could not retrieve vector IDs.") + all_vector_ids = [] + metadata = [] + + for ids in self.index.list(prefix=prefix, namespace=self.namespace): + all_vector_ids.extend(ids) + + if include_metadata: + for id in ids: + res_meta = ( + self.index.fetch(ids=[id], namespace=self.namespace) + if self.index + else {} + ) + metadata.extend( + [x["metadata"] for x in res_meta["vectors"].values()] + ) + return all_vector_ids, metadata + + def delete(self, route_name: str): + route_vec_ids = self._get_route_ids(route_name=route_name) + if self.index is not None: + logger.info("index is not None, deleting...") + response = requests.post( + f"{self.index_host}/vectors/delete", + json=DeleteRequest( + ids=route_vec_ids, + delete_all=True, + namespace=self.namespace, + ).model_dump(exclude_none=True), + timeout=10, + ) + if response.status_code == 200: + logger.info( + f"Deleted {len(route_vec_ids)} vectors from index {self.index_name}." + ) + return response.json() + else: + error_message = response.text + raise Exception( + f"Failed to delete vectors: {response.status_code} : {error_message}" + ) + else: + raise ValueError("Index is None, could not delete.") + + # index_host = self.client.describe_index(self.index_name).host + + def delete_all(self): + if self.index is not None: + self.index.delete(delete_all=True, namespace=self.namespace) + else: + raise ValueError("Index is None, could not delete.") + + def describe(self) -> IndexConfig: + if self.index is not None: + stats = self.index.describe_index_stats() + return IndexConfig( + type=self.type, + dimensions=stats["dimension"], + vectors=stats["namespaces"][self.namespace]["vector_count"], + ) + else: + return IndexConfig( + type=self.type, + dimensions=self.dimensions or 0, + vectors=0, + ) + + def is_ready(self) -> bool: + """ + Checks if the index is ready to be used. + """ + return self.index is not None + + def query( + self, + vector: np.ndarray, + top_k: int = 5, + route_filter: list[str] | None = None, + sparse_vector: dict[int, float] | SparseEmbedding | None = None, + ) -> tuple[np.ndarray, list[str]]: + """Search the index for the query vector and return the top_k results. + + :param vector: The query vector to search for. + :type vector: np.ndarray + :param top_k: The number of top results to return, defaults to 5. + :type top_k: int, optional + :param route_filter: A list of route names to filter the search results, defaults to None. + :type route_filter: Optional[List[str]], optional + :param sparse_vector: An optional sparse vector to include in the query. + :type sparse_vector: Optional[SparseEmbedding] + :param kwargs: Additional keyword arguments for the query, including sparse_vector. + :type kwargs: Any + :return: A tuple containing an array of scores and a list of route names. + :rtype: Tuple[np.ndarray, List[str]] + :raises ValueError: If the index is not populated. + """ + if self.index is None: + raise ValueError("Index is not populated.") + query_vector_list = vector.tolist() + if route_filter is not None: + filter_query = {"sr_route": {"$in": route_filter}} + else: + filter_query = None + if sparse_vector is not None: + if isinstance(sparse_vector, dict): + sparse_vector = SparseEmbedding.from_dict(sparse_vector) + if isinstance(sparse_vector, SparseEmbedding): + # unnecessary if-statement but mypy didn't like this otherwise + sparse_vector = sparse_vector.to_pinecone() + try: + results = self.index.query( + vector=[query_vector_list], + sparse_vector=sparse_vector, + top_k=top_k, + filter=filter_query, + include_metadata=True, + namespace=self.namespace, + ) + except Exception: + logger.error("retrying query with vector as str") + results = self.index.query( + vector=query_vector_list, + sparse_vector=sparse_vector, + top_k=top_k, + filter=filter_query, + include_metadata=True, + namespace=self.namespace, + ) + try: + scores = [result["score"] for result in results["matches"]] + route_names = [ + result["metadata"]["sr_route"] for result in results["matches"] + ] + return np.array(scores), route_names + except Exception as e: + results = self.index.query( + vector=query_vector_list, + sparse_vector=sparse_vector, + top_k=top_k, + filter=filter_query, + include_metadata=True, + namespace=self.namespace, + ) + logger.error(f"Error in query: {e}") + raise e + + def _read_config(self, field: str, scope: str | None = None) -> ConfigParameter: + scope = scope or self.namespace + if self.index is None: + return ConfigParameter( + field=field, + value="", + scope=scope, + ) + config_id = f"{field}#{scope}" + config_record = self.index.fetch( + ids=[config_id], + namespace="sr_config", + ) + if config_record.get("vectors"): + return ConfigParameter( + field=field, + value=config_record["vectors"][config_id]["metadata"]["value"], + created_at=config_record["vectors"][config_id]["metadata"][ + "created_at" + ], + scope=scope, + ) + else: + logger.warning(f"Configuration for {field} parameter not found in index.") + return ConfigParameter( + field=field, + value="", + scope=scope, + ) + + async def _async_read_config( + self, field: str, scope: str | None = None + ) -> ConfigParameter: + """Read a config parameter from the index asynchronously. + + :param field: The field to read. + :type field: str + :param scope: The scope to read. + :type scope: str | None + :return: The config parameter that was read. + :rtype: ConfigParameter + """ + scope = scope or self.namespace + if self.index is None: + return ConfigParameter( + field=field, + value="", + scope=scope, + ) + config_id = f"{field}#{scope}" + config_record = await self._async_fetch_metadata( + vector_id=config_id, namespace="sr_config" + ) + if config_record: + try: + return ConfigParameter( + field=field, + value=config_record["value"], + created_at=config_record["created_at"], + scope=scope, + ) + except KeyError: + raise ValueError( + f"Found invalid config record during sync: {config_record}" + ) + else: + logger.warning(f"Configuration for {field} parameter not found in index.") + return ConfigParameter( + field=field, + value="", + scope=scope, + ) + + def _write_config(self, config: ConfigParameter) -> ConfigParameter: + """Method to write a config parameter to the remote Pinecone index. + + :param config: The config parameter to write to the index. + :type config: ConfigParameter + """ + config.scope = config.scope or self.namespace + if self.index is None: + raise ValueError("Index has not been initialized.") + if self.dimensions is None: + raise ValueError("Must set PineconeIndex.dimensions before writing config.") + self.index.upsert( + vectors=[config.to_pinecone(dimensions=self.dimensions)], + namespace="sr_config", + ) + return config + + async def _async_write_config(self, config: ConfigParameter) -> ConfigParameter: + """Method to write a config parameter to the remote Pinecone index. + + :param config: The config parameter to write to the index. + :type config: ConfigParameter + """ + config.scope = config.scope or self.namespace + if self.index is None: + raise ValueError("Index has not been initialized.") + if self.dimensions is None: + raise ValueError("Must set PineconeIndex.dimensions before writing config.") + pinecone_config = config.to_pinecone(dimensions=self.dimensions) + await self._async_upsert( + vectors=[pinecone_config], + namespace="sr_config", + ) + return config + + async def aquery( + self, + vector: np.ndarray, + top_k: int = 5, + route_filter: list[str] | None = None, + sparse_vector: dict[int, float] | SparseEmbedding | None = None, + ) -> tuple[np.ndarray, list[str]]: + """ + Asynchronously search the index for the query vector and return the top_k results. + + :param vector: The query vector to search for. + :type vector: np.ndarray + :param top_k: The number of top results to return, defaults to 5. + :type top_k: int, optional + :param route_filter: A list of route names to filter the search results, defaults to None. + :type route_filter: Optional[List[str]], optional + :param kwargs: Additional keyword arguments for the query, including sparse_vector. + :type kwargs: Any + :keyword sparse_vector: An optional sparse vector to include in the query. + :type sparse_vector: Optional[dict] + :return: A tuple containing an array of scores and a list of route names. + :rtype: Tuple[np.ndarray, List[str]] + :raises ValueError: If the index is not populated. + """ + if self.host == "": + raise ValueError("Host is not initialized.") + query_vector_list = vector.tolist() + if route_filter is not None: + filter_query = {"sr_route": {"$in": route_filter}} + else: + filter_query = None + # set sparse_vector_obj + sparse_vector_obj: dict[str, Any] | None = None + if sparse_vector is not None: + if isinstance(sparse_vector, dict): + sparse_vector_obj = SparseEmbedding.from_dict(sparse_vector) + if isinstance(sparse_vector, SparseEmbedding): + # unnecessary if-statement but mypy didn't like this otherwise + sparse_vector_obj = sparse_vector.to_pinecone() + results = await self._async_query( + vector=query_vector_list, + sparse_vector=sparse_vector_obj, + namespace=self.namespace or "", + filter=filter_query, + top_k=top_k, + include_metadata=True, + ) + scores = [result["score"] for result in results["matches"]] + route_names = [result["metadata"]["sr_route"] for result in results["matches"]] + return np.array(scores), route_names + + async def aget_routes(self) -> list[tuple]: + """Asynchronously get a list of route and utterance objects currently + stored in the index. + + :return: A list of (route_name, utterance) objects. + :rtype: List[Tuple] + """ + if self.host == "": + raise ValueError("Host is not initialized.") + + return await self._async_get_routes() + + def delete_index(self): + self.client.delete_index(self.index_name) + self.index = None + + # __ASYNC CLIENT METHODS__ + async def _async_query( + self, + vector: list[float], + sparse_vector: dict[str, Any] | None = None, + namespace: str = "", + filter: dict | None = None, + top_k: int = 5, + include_metadata: bool = False, + ): + params = { + "vector": vector, + "sparse_vector": sparse_vector, + "namespace": namespace, + "filter": filter, + "topK": top_k, + "includeMetadata": include_metadata, + } + if self.host == "": + raise ValueError("self.host is not initialized.") + elif self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + + async with aiohttp.ClientSession() as session: + async with session.post( + f"{self.host}/query", + json=params, + headers=self.headers, + ) as response: + return await response.json(content_type=None) + + async def _async_list_indexes(self): + async with aiohttp.ClientSession() as session: + async with session.get( + f"{self.base_url}/indexes", + headers=self.headers, + ) as response: + return await response.json(content_type=None) + + async def _async_upsert( + self, + vectors: list[dict], + namespace: str = "", + ): + params = { + "vectors": vectors, + "namespace": namespace, + } + if self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + + async with aiohttp.ClientSession() as session: + async with session.post( + f"{self.host}/vectors/upsert", + json=params, + headers=self.headers, + ) as response: + res = await response.json(content_type=None) + return res + + async def _async_create_index( + self, + name: str, + dimension: int, + cloud: str, + region: str, + metric: str = "dotproduct", + ): + params = { + "name": name, + "dimension": dimension, + "metric": metric, + "spec": {"serverless": {"cloud": cloud, "region": region}}, + } + async with aiohttp.ClientSession() as session: + async with session.post( + f"{self.base_url}/indexes", + json=params, + headers=self.headers, + ) as response: + return await response.json(content_type=None) + + async def _async_delete(self, ids: list[str], namespace: str = ""): + params = { + "ids": ids, + "namespace": namespace, + } + if self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + + async with aiohttp.ClientSession() as session: + async with session.post( + f"{self.host}/vectors/delete", + json=params, + headers=self.headers, + ) as response: + return await response.json(content_type=None) + + async def _async_describe_index(self, name: str): + async with aiohttp.ClientSession() as session: + async with session.get( + f"{self.base_url}/indexes/{name}", + headers=self.headers, + ) as response: + return await response.json(content_type=None) + + async def _async_get_all( + self, prefix: str | None = None, include_metadata: bool = False + ) -> tuple[list[str], list[dict]]: + """Retrieves all vector IDs from the Pinecone index using pagination + asynchronously. + + :param prefix: The prefix to filter the vectors by. + :type prefix: Optional[str] + :param include_metadata: Whether to include metadata in the response. + :type include_metadata: bool + :return: A tuple containing a list of vector IDs and a list of metadata dictionaries. + :rtype: tuple[list[str], list[dict]] + """ + if self.index is None: + raise ValueError("Index is None, could not retrieve vector IDs.") + if self.host == "": + raise ValueError("self.host is not initialized.") + + all_vector_ids = [] + next_page_token = None + + if prefix: + prefix_str = f"?prefix={prefix}" + else: + prefix_str = "" + if self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + + list_url = f"{self.host}/vectors/list{prefix_str}" + params: dict = {} + if self.namespace: + params["namespace"] = self.namespace + metadata = [] + + async with aiohttp.ClientSession() as session: + while True: + if next_page_token: + params["paginationToken"] = next_page_token + + async with session.get( + list_url, + params=params, + headers=self.headers, + ) as response: + if response.status != 200: + error_text = await response.text() + logger.error(f"Error fetching vectors: {error_text}") + break + + response_data = await response.json(content_type=None) + + vector_ids = [vec["id"] for vec in response_data.get("vectors", [])] + if not vector_ids: + break + all_vector_ids.extend(vector_ids) + + if include_metadata: + metadata_tasks = [ + self._async_fetch_metadata(id) for id in vector_ids + ] + metadata_results = await asyncio.gather(*metadata_tasks) + metadata.extend(metadata_results) + + next_page_token = response_data.get("pagination", {}).get("next") + if not next_page_token: + break + + return all_vector_ids, metadata + + async def _async_fetch_metadata( + self, + vector_id: str, + namespace: str | None = None, + ) -> dict: + """Fetch metadata for a single vector ID asynchronously using the + ClientSession. + + :param vector_id: The ID of the vector to fetch metadata for. + :type vector_id: str + :param namespace: The namespace to fetch metadata for. + :type namespace: str | None + :return: A dictionary containing the metadata for the vector. + :rtype: dict + """ + if self.host == "": + raise ValueError("self.host is not initialized.") + if self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + url = f"{self.host}/vectors/fetch" + + params = { + "ids": [vector_id], + } + + if namespace: + params["namespace"] = [namespace] + elif self.namespace: + params["namespace"] = [self.namespace] + + async with aiohttp.ClientSession() as session: + async with session.get( + url, params=params, headers=self.headers + ) as response: + if response.status != 200: + error_text = await response.text() + logger.error(f"Error fetching metadata: {error_text}") + return {} + + try: + response_data = await response.json(content_type=None) + except Exception as e: + logger.warning(f"No metadata found for vector {vector_id}: {e}") + return {} + + return ( + response_data.get("vectors", {}) + .get(vector_id, {}) + .get("metadata", {}) + ) + + def __len__(self): + if self.index is None: + raise ValueError("Index is None, could not get length.") + namespace_stats = self.index.describe_index_stats()["namespaces"].get( + self.namespace + ) + if namespace_stats: + return namespace_stats["vector_count"] + else: + return 0 diff --git a/semantic_router/routers/base.py b/semantic_router/routers/base.py index b5136f97..4589ca1d 100644 --- a/semantic_router/routers/base.py +++ b/semantic_router/routers/base.py @@ -20,6 +20,7 @@ from semantic_router.index.base import BaseIndex from semantic_router.index.local import LocalIndex from semantic_router.index.pinecone import PineconeIndex +from semantic_router.index.pinecone_local import PineconeLocalIndex from semantic_router.index.qdrant import QdrantIndex from semantic_router.llms import BaseLLM, OpenAILLM from semantic_router.route import Route @@ -396,8 +397,11 @@ def _init_index_state(self): dims = len(self.encoder(["test"])[0]) self.index.dimensions = dims # now init index - if isinstance(self.index, PineconeIndex): + if isinstance(self.index, PineconeIndex) or isinstance( + self.index, PineconeLocalIndex + ): self.index.index = self.index._init_index(force_create=True) + # run auto sync if active if self.auto_sync: local_utterances = self.to_config().to_utterances() diff --git a/semantic_router/schema.py b/semantic_router/schema.py index 273043f5..d8efcd04 100644 --- a/semantic_router/schema.py +++ b/semantic_router/schema.py @@ -6,7 +6,8 @@ from typing import List, Optional, Union, Any, Dict, Tuple from pydantic import BaseModel, Field from semantic_router.utils.logger import logger -from aurelio_sdk.schema import BM25Embedding + +from aurelio_sdk.schema import SparseEmbedding as BM25SparseEmbedding class EncoderType(Enum): @@ -448,7 +449,7 @@ def from_vector(cls, vector: np.ndarray): return cls.from_compact_array(np.array([np.arange(len(vector)), vector]).T) @classmethod - def from_aurelio(cls, embedding: BM25Embedding): + def from_aurelio(cls, embedding: BM25SparseEmbedding): arr = np.array([embedding.indices, embedding.values]).T return cls.from_compact_array(arr) diff --git a/tests/unit/test_router.py b/tests/unit/test_router.py index a210cc4c..95cd1c3c 100644 --- a/tests/unit/test_router.py +++ b/tests/unit/test_router.py @@ -9,7 +9,7 @@ from typing import Optional from semantic_router.encoders import DenseEncoder, CohereEncoder, OpenAIEncoder from semantic_router.index.local import LocalIndex -from semantic_router.index.pinecone import PineconeIndex +from semantic_router.index.pinecone_local import PineconeLocalIndex from semantic_router.index.qdrant import QdrantIndex from semantic_router.routers import RouterConfig, SemanticRouter, HybridRouter from semantic_router.llms import BaseLLM, OpenAILLM @@ -22,9 +22,9 @@ RETRY_COUNT = 10 -# retry decorator for PineconeIndex cases (which need delay) +# retry decorator for PineconeLocalIndex cases (which need delay) def retry(max_retries: int = 5, delay: int = 8): - """Retry decorator, currently used for PineconeIndex which often needs some time + """Retry decorator, currently used for PineconeLocalIndex which often needs some time to be populated and have all correct data. Once full Pinecone mock is built we should remove this decorator. @@ -79,11 +79,22 @@ def init_index( """We use this function to initialize indexes with different names to avoid issues during testing. """ - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: + + if index_name: + if not dimensions and "OpenAIEncoder" in index_name: + dimensions = 1536 + + elif not dimensions and "CohereEncoder" in index_name: + dimensions = 1024 + # we specify different index names to avoid dimensionality issues between different encoders index_name = TEST_ID if not index_name else f"{TEST_ID}-{index_name.lower()}" + index = index_cls( - index_name=index_name, dimensions=dimensions, namespace=namespace + index_name=index_name, + dimensions=dimensions, + # namespace=namespace ) else: index = index_cls() @@ -260,7 +271,7 @@ def get_test_indexes(): if importlib.util.find_spec("qdrant_client") is not None: indexes.append(QdrantIndex) if importlib.util.find_spec("pinecone") is not None: - indexes.append(PineconeIndex) + indexes.append(PineconeLocalIndex) return indexes @@ -613,7 +624,7 @@ def test_init_and_add_single_utterance( index=index, auto_sync="local", ) - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: time.sleep(PINECONE_SLEEP) # allow for index to be updated route_layer.add(routes=route_single_utterance) score_threshold = route_layer.score_threshold @@ -631,8 +642,8 @@ def check_index_populated(): def test_delete_index(self, routes, index_cls, encoder_cls, router_cls): # TODO merge .delete_index() and .delete_all() and get working - index = init_index(index_cls) encoder = encoder_cls() + index = init_index(index_cls, index_name=encoder.__class__.__name__) route_layer = router_cls( encoder=encoder, routes=routes, @@ -764,8 +775,8 @@ def check_index_populated(): check_index_populated() - # # clear index if pinecone - # if index_cls is PineconeIndex: + # clear index if pinecone + # if index_cls is PineconeLocalIndex: # @retry(max_retries=RETRY_COUNT, delay=PINECONE_SLEEP) # def clear_index(): # route_layer.index.index.delete(delete_all=True) @@ -823,15 +834,16 @@ def check_query_result(): os.environ.get("PINECONE_API_KEY") is None, reason="Pinecone API key required" ) def test_namespace_pinecone_index(self, routes, index_cls, encoder_cls, router_cls): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: encoder = encoder_cls() - pineconeindex = init_index( + encoder.score_threshold = 0.2 + index = init_index( index_cls, namespace="test", index_name=encoder.__class__.__name__ ) route_layer = router_cls( encoder=encoder, routes=routes, - index=pineconeindex, + index=index, auto_sync="local", ) time.sleep(PINECONE_SLEEP) # allow for index to be updated @@ -1248,8 +1260,8 @@ def check_is_ready(): route_layer.evaluate(X=list(X), y=list(y), batch_size=int(len(X) / 5)) def test_fit(self, routes, test_data, index_cls, encoder_cls, router_cls): - # TODO: this is super slow for PineconeIndex, need to fix - if index_cls is PineconeIndex: + # TODO: this is super slow for PineconeLocalIndex, need to fix + if index_cls is PineconeLocalIndex: return encoder = encoder_cls() index = init_index(index_cls, index_name=encoder.__class__.__name__) From bcaedd70928903595ee30568a99c4d8a4d07dc42 Mon Sep 17 00:00:00 2001 From: theanupllm Date: Fri, 31 Jan 2025 13:24:08 +0530 Subject: [PATCH 02/13] fix: Improve host URL handling in PineconeLocalIndex - Corrected string stripping and URL construction for localhost and base URL scenarios - Ensured consistent URL formatting across multiple methods - Minor code cleanup for host URL generation --- semantic_router/index/pinecone_local.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/semantic_router/index/pinecone_local.py b/semantic_router/index/pinecone_local.py index 04f544d0..268e2432 100644 --- a/semantic_router/index/pinecone_local.py +++ b/semantic_router/index/pinecone_local.py @@ -258,12 +258,12 @@ def _init_index(self, force_create: bool = False) -> Any | None: if self.index_host and self.base_url: if "http" not in self.index_host: - self.index_host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.index_host.split(':')[-1]}" + self.index_host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.index_host.split(':')[-1]}" elif not self.index_host.startswith("http://"): # TODO: Need to pass the an argument for service name if "localhost" in self.index_host: - self.index_host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.index_host.split(':')[-1]}" + self.index_host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.index_host.split(':')[-1]}" logger.error(f"index exists:{self.index_host}") else: self.index_host = f"http://{self.index_host}" @@ -820,7 +820,7 @@ async def _async_query( if self.host == "": raise ValueError("self.host is not initialized.") elif self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" async with aiohttp.ClientSession() as session: async with session.post( @@ -848,7 +848,7 @@ async def _async_upsert( "namespace": namespace, } if self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" async with aiohttp.ClientSession() as session: async with session.post( @@ -887,7 +887,7 @@ async def _async_delete(self, ids: list[str], namespace: str = ""): "namespace": namespace, } if self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" async with aiohttp.ClientSession() as session: async with session.post( @@ -931,7 +931,7 @@ async def _async_get_all( else: prefix_str = "" if self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" list_url = f"{self.host}/vectors/list{prefix_str}" params: dict = {} @@ -992,7 +992,7 @@ async def _async_fetch_metadata( if self.host == "": raise ValueError("self.host is not initialized.") if self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip("/")}:{self.host.split(':')[-1]}" + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" url = f"{self.host}/vectors/fetch" params = { From d4a7ef81d929cdf684f024929208bdd043bbe494 Mon Sep 17 00:00:00 2001 From: theanupllm Date: Fri, 31 Jan 2025 13:47:46 +0530 Subject: [PATCH 03/13] refactor: Update test suite to use PineconeLocalIndex - Replaced all references to PineconeIndex with PineconeLocalIndex in test files - Added dimension handling for OpenAI and Cohere encoders in index initialization - Updated GitHub Actions workflow to cache Poetry dependencies - Maintained existing test logic and retry mechanisms --- .github/workflows/test.yml | 7 ++++ tests/unit/test_sync.py | 74 +++++++++++++++++++++----------------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 96fa6bce..e6738dc3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,6 +28,13 @@ jobs: - "3.13" steps: - uses: actions/checkout@v4 + - name: Cache Poetry + uses: actions/cache@v4 + with: + path: ~/.poetry + key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }} + restore-keys: | + ${{ runner.os }}-poetry- - name: Wait for Pinecone service to start run: | diff --git a/tests/unit/test_sync.py b/tests/unit/test_sync.py index d40a57fb..025693b4 100644 --- a/tests/unit/test_sync.py +++ b/tests/unit/test_sync.py @@ -8,7 +8,7 @@ from typing import Optional from semantic_router.encoders import DenseEncoder, CohereEncoder, OpenAIEncoder from semantic_router.index import ( - PineconeIndex, + PineconeLocalIndex, HybridLocalIndex, LocalIndex, QdrantIndex, @@ -25,9 +25,9 @@ RETRY_COUNT = 5 -# retry decorator for PineconeIndex cases (which need delay) +# retry decorator for PineconeLocalIndex cases (which need delay) def retry(max_retries: int = 5, delay: int = 8): - """Retry decorator, currently used for PineconeIndex which often needs some time + """Retry decorator, currently used for PineconeLocalIndex which often needs some time to be populated and have all correct data. Once full Pinecone mock is built we should remove this decorator. @@ -55,9 +55,9 @@ def wrapper(*args, **kwargs): return decorator -# retry decorator for PineconeIndex cases (which need delay) +# retry decorator for PineconeLocalIndex cases (which need delay) def async_retry(max_retries: int = 5, delay: int = 8): - """Retry decorator, currently used for PineconeIndex which often needs some time + """Retry decorator, currently used for PineconeLocalIndex which often needs some time to be populated and have all correct data. Once full Pinecone mock is built we should remove this decorator. @@ -113,7 +113,15 @@ def init_index( """We use this function to initialize indexes with different names to avoid issues during testing. """ - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: + + if index_name: + if not dimensions and "OpenAIEncoder" in index_name: + dimensions = 1536 + + elif not dimensions and "CohereEncoder" in index_name: + dimensions = 1024 + index_name = TEST_ID if not index_name else f"{TEST_ID}-{index_name.lower()}" index = index_cls( index_name=index_name, @@ -174,7 +182,7 @@ def layer_yaml(): # not all indexes support metadata, so we map the feature here INCLUDE_METADATA_MAP = { - PineconeIndex: True, + PineconeLocalIndex: True, HybridLocalIndex: False, LocalIndex: False, QdrantIndex: False, @@ -304,7 +312,7 @@ def get_test_indexes(): # if importlib.util.find_spec("qdrant_client") is not None: # indexes.append(QdrantIndex) if importlib.util.find_spec("pinecone") is not None: - indexes.append(PineconeIndex) + indexes.append(PineconeLocalIndex) return indexes @@ -401,7 +409,7 @@ def check_utterance_diff(): def test_auto_sync_local( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST LOCAL pinecone_index = init_index(index_cls, index_name=router_cls.__name__) _ = router_cls( @@ -434,7 +442,7 @@ def check_sync(): def test_auto_sync_remote( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST REMOTE pinecone_index = init_index(index_cls, index_name=router_cls.__name__) _ = router_cls( @@ -467,7 +475,7 @@ def check_sync(): def test_auto_sync_merge_force_local( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST MERGE FORCE LOCAL pinecone_index = init_index(index_cls, index_name=router_cls.__name__) route_layer = router_cls( @@ -514,7 +522,7 @@ def check_sync(): def test_auto_sync_merge_force_remote( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST MERGE FORCE LOCAL pinecone_index = init_index(index_cls, index_name=router_cls.__name__) route_layer = router_cls( @@ -606,7 +614,7 @@ def check_sync(): def test_auto_sync_merge( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST MERGE pinecone_index = init_index(index_cls, index_name=router_cls.__name__) route_layer = router_cls( @@ -672,7 +680,7 @@ def test_sync_lock_prevents_concurrent_sync( ) # Acquire sync lock route_layer.index.lock(value=True) - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: time.sleep(PINECONE_SLEEP) # Attempt to sync while lock is held should raise exception @@ -681,12 +689,12 @@ def test_sync_lock_prevents_concurrent_sync( # Release lock route_layer.index.lock(value=False) - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: time.sleep(PINECONE_SLEEP) # Should succeed after lock is released route_layer.sync("local") - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: time.sleep(PINECONE_SLEEP) assert route_layer.is_synced() @@ -704,17 +712,17 @@ def test_sync_lock_auto_releases( index=index, auto_sync="local", ) - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: time.sleep(PINECONE_SLEEP) # Lock should be released, allowing another sync route_layer.sync("local") # Should not raise exception - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: time.sleep(PINECONE_SLEEP) assert route_layer.is_synced() # clear index if pinecone - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: route_layer.index.client.delete_index(route_layer.index.index_name) @@ -752,7 +760,7 @@ async def test_second_initialization_sync( route_layer = router_cls( encoder=openai_encoder, routes=routes, index=index, auto_sync="local" ) - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: await asyncio.sleep(PINECONE_SLEEP * 2) # allow for index to be populated assert await route_layer.async_is_synced() @@ -770,7 +778,7 @@ async def test_second_initialization_not_synced( encoder=openai_encoder, routes=routes, index=index, auto_sync="local" ) route_layer = router_cls(encoder=openai_encoder, routes=routes_2, index=index) - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: await asyncio.sleep(PINECONE_SLEEP) # allow for index to be populated assert await route_layer.async_is_synced() is False @@ -810,7 +818,7 @@ async def check_diff(): async def test_auto_sync_local( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST LOCAL pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -846,7 +854,7 @@ async def check_sync(): async def test_auto_sync_remote( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST REMOTE pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -883,7 +891,7 @@ async def check_sync(): async def test_auto_sync_merge_force_local( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST MERGE FORCE LOCAL pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -932,7 +940,7 @@ async def check_sync(): async def test_auto_sync_merge_force_remote( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST MERGE FORCE LOCAL pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -1033,7 +1041,7 @@ async def check_sync(): async def test_auto_sync_merge( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: # TEST MERGE pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -1110,7 +1118,7 @@ async def test_sync_lock_prevents_concurrent_sync( # Acquire sync lock await route_layer.index.alock(value=True) - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: await asyncio.sleep(PINECONE_SLEEP) # Attempt to sync while lock is held should raise exception @@ -1119,12 +1127,12 @@ async def test_sync_lock_prevents_concurrent_sync( # Release lock await route_layer.index.alock(value=False) - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: await asyncio.sleep(PINECONE_SLEEP) # Should succeed after lock is released await route_layer.async_sync("local") - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: await asyncio.sleep(PINECONE_SLEEP) assert await route_layer.async_is_synced() @@ -1151,19 +1159,19 @@ async def test_sync_lock_auto_releases( index=index, auto_sync=None, ) - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: await asyncio.sleep(PINECONE_SLEEP) # Initial sync should acquire and release lock await route_layer.async_sync("local") - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: await asyncio.sleep(PINECONE_SLEEP) # Lock should be released, allowing another sync await route_layer.async_sync("local") # Should not raise exception - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: await asyncio.sleep(PINECONE_SLEEP) assert await route_layer.async_is_synced() # clear index if pinecone - if index_cls is PineconeIndex: + if index_cls is PineconeLocalIndex: route_layer.index.client.delete_index(route_layer.index.index_name) From f83c004340c88de6c3633fecf05f2e441efbf55b Mon Sep 17 00:00:00 2001 From: theanupllm Date: Fri, 31 Jan 2025 14:22:36 +0530 Subject: [PATCH 04/13] test: Set default dimensions for index initialization in test suite - Updated default dimensions to 1536 in test_sync.py - Aligns with typical embedding model dimension requirements --- tests/unit/test_sync.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_sync.py b/tests/unit/test_sync.py index 025693b4..1e2299fd 100644 --- a/tests/unit/test_sync.py +++ b/tests/unit/test_sync.py @@ -105,7 +105,7 @@ def mock_encoder_call(utterances): def init_index( index_cls, - dimensions: Optional[int] = None, + dimensions: Optional[int] = 1536, namespace: Optional[str] = "", init_async_index: bool = False, index_name: Optional[str] = None, From c405e722777790d2288f5fb1b6424ae41761822d Mon Sep 17 00:00:00 2001 From: theanupllm Date: Fri, 31 Jan 2025 14:57:39 +0530 Subject: [PATCH 05/13] test: Update default index dimensions in test initialization - Changed default dimensions from 1536 to 3 in test_sync.py - Simplified index initialization parameter for testing purposes --- tests/unit/test_sync.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_sync.py b/tests/unit/test_sync.py index 1e2299fd..7c08f41c 100644 --- a/tests/unit/test_sync.py +++ b/tests/unit/test_sync.py @@ -105,7 +105,7 @@ def mock_encoder_call(utterances): def init_index( index_cls, - dimensions: Optional[int] = 1536, + dimensions: Optional[int] = 3, namespace: Optional[str] = "", init_async_index: bool = False, index_name: Optional[str] = None, From 5e246e9644081f9b5bd92c6f1c77015456f8c1f8 Mon Sep 17 00:00:00 2001 From: theanupllm Date: Mon, 3 Feb 2025 22:04:16 +0530 Subject: [PATCH 06/13] refactor: Remove Pinecone Local Index and consolidate Pinecone index implementation - Deleted `pinecone_local.py` and `10-pinecone-local.ipynb` - Updated `pinecone.py` to handle both cloud and local Pinecone index scenarios - Modified test files to use `PineconeIndex` instead of `PineconeLocalIndex` - Updated GitHub Actions workflow to simplify Python version testing - Improved error handling and host URL management in Pinecone index methods --- .github/workflows/test.yml | 26 +- docs/10-pinecone-local.ipynb | 541 ------------ pinecone-local.ipynb | 773 +++++++++++++++++ semantic_router/index/pinecone.py | 162 +++- semantic_router/index/pinecone_local.py | 1037 ----------------------- tests/unit/test_router.py | 20 +- tests/unit/test_sync.py | 66 +- 7 files changed, 966 insertions(+), 1659 deletions(-) delete mode 100644 docs/10-pinecone-local.ipynb create mode 100644 pinecone-local.ipynb delete mode 100644 semantic_router/index/pinecone_local.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6738dc3..99e2dcd9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,19 +22,19 @@ jobs: strategy: matrix: python-version: - - "3.10" - - "3.11" - - "3.12" + # - "3.10" + # - "3.11" + # - "3.12" - "3.13" steps: - uses: actions/checkout@v4 - - name: Cache Poetry - uses: actions/cache@v4 - with: - path: ~/.poetry - key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }} - restore-keys: | - ${{ runner.os }}-poetry- + # - name: Cache Poetry + # uses: actions/cache@v4 + # with: + # path: ~/.poetry + # key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }} + # restore-keys: | + # ${{ runner.os }}-poetry- - name: Wait for Pinecone service to start run: | @@ -48,10 +48,10 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - cache: poetry + # cache: poetry - # - name: Add Poetry to PATH - # run: echo "PATH=$HOME/.local/bin:$PATH" >> $GITHUB_ENV + - name: Add Poetry to PATH + run: echo "PATH=$HOME/.local/bin:$PATH" >> $GITHUB_ENV - name: Install dependencies run: | diff --git a/docs/10-pinecone-local.ipynb b/docs/10-pinecone-local.ipynb deleted file mode 100644 index a26541c0..00000000 --- a/docs/10-pinecone-local.ipynb +++ /dev/null @@ -1,541 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "G1AJs8NHh6tF" - }, - "source": [ - "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/aurelio-labs/semantic-router/blob/main/docs/09-route-filter.ipynb) [![Open nbviewer](https://raw.githubusercontent.com/pinecone-io/examples/master/assets/nbviewer-shield.svg)](https://nbviewer.org/github/aurelio-labs/semantic-router/blob/main/docs/00-introduction.ipynb)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "tly249bZh6tG" - }, - "source": [ - "# Semantic Router Filter" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "obVbdRpkh6tH" - }, - "source": [ - "The Semantic Router library can be used as a super fast route making layer on top of LLMs. That means rather than waiting on a slow agent to decide what to do, we can use the magic of semantic vector space to make routes. Cutting route making time down from seconds to milliseconds." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Collecting pinecone[grpc]\n", - " Downloading pinecone-5.4.2-py3-none-any.whl.metadata (19 kB)\n", - "Requirement already satisfied: certifi>=2019.11.17 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from pinecone[grpc]) (2024.12.14)\n", - "Collecting googleapis-common-protos>=1.53.0 (from pinecone[grpc])\n", - " Using cached googleapis_common_protos-1.66.0-py2.py3-none-any.whl.metadata (1.5 kB)\n", - "Collecting grpcio>=1.59.0 (from pinecone[grpc])\n", - " Downloading grpcio-1.70.0-cp312-cp312-win_amd64.whl.metadata (4.0 kB)\n", - "Collecting lz4>=3.1.3 (from pinecone[grpc])\n", - " Downloading lz4-4.4.3-cp312-cp312-win_amd64.whl.metadata (3.9 kB)\n", - "Collecting pinecone-plugin-inference<4.0.0,>=2.0.0 (from pinecone[grpc])\n", - " Downloading pinecone_plugin_inference-3.1.0-py3-none-any.whl.metadata (2.2 kB)\n", - "Collecting pinecone-plugin-interface<0.0.8,>=0.0.7 (from pinecone[grpc])\n", - " Using cached pinecone_plugin_interface-0.0.7-py3-none-any.whl.metadata (1.2 kB)\n", - "Collecting protobuf<5.0,>=4.25 (from pinecone[grpc])\n", - " Downloading protobuf-4.25.6-cp310-abi3-win_amd64.whl.metadata (541 bytes)\n", - "Collecting protoc-gen-openapiv2<0.0.2,>=0.0.1 (from pinecone[grpc])\n", - " Using cached protoc_gen_openapiv2-0.0.1-py3-none-any.whl.metadata (1.5 kB)\n", - "Requirement already satisfied: python-dateutil>=2.5.3 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from pinecone[grpc]) (2.9.0.post0)\n", - "Collecting tqdm>=4.64.1 (from pinecone[grpc])\n", - " Downloading tqdm-4.67.1-py3-none-any.whl.metadata (57 kB)\n", - "Requirement already satisfied: typing-extensions>=3.7.4 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from pinecone[grpc]) (4.12.2)\n", - "Requirement already satisfied: urllib3>=1.26.5 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from pinecone[grpc]) (2.3.0)\n", - "Requirement already satisfied: six>=1.5 in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from python-dateutil>=2.5.3->pinecone[grpc]) (1.17.0)\n", - "Requirement already satisfied: colorama in c:\\users\\awesome\\anaconda3\\envs\\py12\\lib\\site-packages (from tqdm>=4.64.1->pinecone[grpc]) (0.4.6)\n", - "Using cached googleapis_common_protos-1.66.0-py2.py3-none-any.whl (221 kB)\n", - "Downloading grpcio-1.70.0-cp312-cp312-win_amd64.whl (4.3 MB)\n", - " ---------------------------------------- 0.0/4.3 MB ? eta -:--:--\n", - " --------- ------------------------------ 1.0/4.3 MB 8.4 MB/s eta 0:00:01\n", - " ------------ --------------------------- 1.3/4.3 MB 6.1 MB/s eta 0:00:01\n", - " --------------------- ------------------ 2.4/4.3 MB 4.6 MB/s eta 0:00:01\n", - " -------------------------- ------------- 2.9/4.3 MB 4.1 MB/s eta 0:00:01\n", - " --------------------------------------- 4.2/4.3 MB 4.3 MB/s eta 0:00:01\n", - " ---------------------------------------- 4.3/4.3 MB 4.2 MB/s eta 0:00:00\n", - "Downloading lz4-4.4.3-cp312-cp312-win_amd64.whl (99 kB)\n", - "Downloading pinecone_plugin_inference-3.1.0-py3-none-any.whl (87 kB)\n", - "Using cached pinecone_plugin_interface-0.0.7-py3-none-any.whl (6.2 kB)\n", - "Downloading protobuf-4.25.6-cp310-abi3-win_amd64.whl (413 kB)\n", - "Using cached protoc_gen_openapiv2-0.0.1-py3-none-any.whl (7.9 kB)\n", - "Downloading tqdm-4.67.1-py3-none-any.whl (78 kB)\n", - "Downloading pinecone-5.4.2-py3-none-any.whl (427 kB)\n", - "Installing collected packages: tqdm, protobuf, pinecone-plugin-interface, lz4, grpcio, pinecone-plugin-inference, googleapis-common-protos, protoc-gen-openapiv2, pinecone\n", - "Successfully installed googleapis-common-protos-1.66.0 grpcio-1.70.0 lz4-4.4.3 pinecone-5.4.2 pinecone-plugin-inference-3.1.0 pinecone-plugin-interface-0.0.7 protobuf-4.25.6 protoc-gen-openapiv2-0.0.1 tqdm-4.67.1\n" - ] - } - ], - "source": [ - "!pip install \"pinecone[grpc]\"" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Index stats:\n", - " {'dimension': 2,\n", - " 'index_fullness': 0.0,\n", - " 'namespaces': {'example-namespace': {'vector_count': 3}},\n", - " 'total_vector_count': 3}\n", - "\n", - "Query response:\n", - " {'matches': [{'id': 'vec2',\n", - " 'metadata': {'genre': 'documentary'},\n", - " 'score': 1.0,\n", - " 'sparse_values': {'indices': [], 'values': []},\n", - " 'values': [3.0, -2.0]}],\n", - " 'namespace': 'example-namespace'}\n" - ] - } - ], - "source": [ - "from pinecone.grpc import PineconeGRPC, GRPCClientConfig\n", - "from pinecone import ServerlessSpec\n", - "import time\n", - "\n", - "# Initialize a client.\n", - "# API key is required, but the value does not matter.\n", - "# Host and port of the Pinecone Local instance\n", - "# is required when starting without indexes.\n", - "pc = PineconeGRPC(api_key=\"pclocal\", host=\"http://localhost:5080\")\n", - "\n", - "# Create an index\n", - "index_name = \"example-index\"\n", - "\n", - "if not pc.has_index(index_name):\n", - " pc.create_index(\n", - " name=index_name,\n", - " dimension=2,\n", - " metric=\"cosine\",\n", - " spec=ServerlessSpec(\n", - " cloud=\"aws\",\n", - " region=\"us-east-1\",\n", - " ),\n", - " )\n", - "\n", - "# Wait for the index to be ready\n", - "while not pc.describe_index(index_name).status[\"ready\"]:\n", - " time.sleep(1)\n", - "\n", - "# Target the index, disabling tls\n", - "index_host = pc.describe_index(index_name).host\n", - "index = pc.Index(host=index_host, grpc_config=GRPCClientConfig(secure=False))\n", - "\n", - "# Upsert records into the index\n", - "index.upsert(\n", - " vectors=[\n", - " {\"id\": \"vec1\", \"values\": [1.0, -2.5], \"metadata\": {\"genre\": \"drama\"}},\n", - " {\"id\": \"vec2\", \"values\": [3.0, -2.0], \"metadata\": {\"genre\": \"documentary\"}},\n", - " {\"id\": \"vec3\", \"values\": [0.5, -1.5], \"metadata\": {\"genre\": \"documentary\"}},\n", - " ],\n", - " namespace=\"example-namespace\",\n", - ")\n", - "\n", - "# Check the number of records in the index\n", - "print(\"Index stats:\\n\", index.describe_index_stats())\n", - "\n", - "# Query the index with a metadata filter\n", - "response = index.query(\n", - " vector=[3.0, -2.0],\n", - " filter={\"genre\": {\"$eq\": \"documentary\"}},\n", - " top_k=1,\n", - " include_values=True,\n", - " include_metadata=True,\n", - " namespace=\"example-namespace\",\n", - ")\n", - "\n", - "print(\"\\nQuery response:\\n\", response)\n", - "\n", - "# Delete the index\n", - "pc.delete_index(index_name)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "x9wSBV1-h6tH" - }, - "source": [ - "## Getting Started" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Mw7_rFAch6tH" - }, - "source": [ - "We start by installing the library:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "jKjHHH10h6tH" - }, - "outputs": [], - "source": [ - "!pip install -qU semantic-router" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "K5mvw1yUh6tK" - }, - "source": [ - "We start by defining a dictionary mapping routes to example phrases that should trigger those routes." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "2nU02l4Mh6tK", - "outputId": "f2b4dadd-14b0-4faa-af62-bdb6518b6bb6" - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "c:\\Users\\Siraj\\Documents\\Personal\\Work\\Aurelio\\Virtual Environments\\semantic_router_3\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - } - ], - "source": [ - "from semantic_router import Route\n", - "\n", - "politics = Route(\n", - " name=\"politics\",\n", - " utterances=[\n", - " \"isn't politics the best thing ever\",\n", - " \"why don't you tell me about your political opinions\",\n", - " \"don't you just love the president\",\n", - " \"don't you just hate the president\",\n", - " \"they're going to destroy this country!\",\n", - " \"they will save the country!\",\n", - " ],\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "FCSq2Ncbh6tL" - }, - "source": [ - "Let's define another for good measure:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0rkTc2ehh6tL" - }, - "outputs": [], - "source": [ - "chitchat = Route(\n", - " name=\"chitchat\",\n", - " utterances=[\n", - " \"how's the weather today?\",\n", - " \"how are things going?\",\n", - " \"lovely weather today\",\n", - " \"the weather is horrendous\",\n", - " \"let's go to the chippy\",\n", - " ],\n", - ")\n", - "\n", - "routes = [politics, chitchat]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "BWdFd8Neh6tM" - }, - "source": [ - "Now we initialize our embedding model:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "XiI5ob3Gh6tM" - }, - "outputs": [], - "source": [ - "import os\n", - "from getpass import getpass\n", - "from semantic_router.encoders import CohereEncoder, OpenAIEncoder\n", - "\n", - "os.environ[\"COHERE_API_KEY\"] = os.getenv(\"COHERE_API_KEY\") or getpass(\n", - " \"Enter Cohere API Key: \"\n", - ")\n", - "# os.environ[\"OPENAI_API_KEY\"] = os.getenv(\"OPENAI_API_KEY\") or getpass(\n", - "# \"Enter OpenAI API Key: \"\n", - "# )\n", - "\n", - "encoder = CohereEncoder()\n", - "# encoder = OpenAIEncoder()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "rebk9Z4yh6tM" - }, - "source": [ - "Now we define the `RouteLayer`. When called, the route layer will consume text (a query) and output the category (`Route`) it belongs to — to initialize a `RouteLayer` we need our `encoder` model and a list of `routes`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "qeP6ZUMoh6tM", - "outputId": "6909f60c-41e2-4be5-eb25-8374e3d1461c" - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[32m2024-05-07 16:02:43 INFO semantic_router.utils.logger local\u001b[0m\n" - ] - } - ], - "source": [ - "from semantic_router.layer import RouteLayer\n", - "\n", - "rl = RouteLayer(encoder=encoder, routes=routes)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "AF55Xqg1h6tN" - }, - "source": [ - "Now we can test it:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "126uJrBKh6tN", - "outputId": "fca3e781-667e-42a9-e125-2c44cd314a09" - }, - "outputs": [ - { - "data": { - "text/plain": [ - "RouteChoice(name='politics', function_call=None, similarity_score=None)" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "rl(\"don't you love politics?\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "oRNUvo3dh6tN", - "outputId": "c166e961-e897-48c4-b79f-fbbd678bd22e" - }, - "outputs": [ - { - "data": { - "text/plain": [ - "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "rl(\"how's the weather today?\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "dQNc9OD4h6tN" - }, - "source": [ - "Both are classified accurately, what if we send a query that is unrelated to our existing `Route` objects?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "LRKIToX3h6tO", - "outputId": "b5795fb1-2045-4484-9858-377aeb98ba8d" - }, - "outputs": [ - { - "data": { - "text/plain": [ - "RouteChoice(name=None, function_call=None, similarity_score=None)" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "rl(\"I'm interested in learning about llama 2\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "GVxcpE9Vh6tO" - }, - "source": [ - "In this case, we return `None` because no matches were identified." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "-zJEY71mh6tO" - }, - "source": [ - "# Demonstrating the Filter Feature\n", - "\n", - "Now, let's demonstrate the filter feature. We can specify a subset of routes to consider when making a classification. This can be useful if we want to restrict the scope of possible routes based on some context.\n", - "\n", - "For example, let's say we only want to consider the \"chitchat\" route for a particular query:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "M8qIXBOWh6tO", - "outputId": "37272c84-8189-477a-bdaa-7ce043fc203e" - }, - "outputs": [ - { - "data": { - "text/plain": [ - "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "rl(\"don't you love politics?\", route_filter=[\"chitchat\"])" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "JQfEDKZgh6tO" - }, - "source": [ - "Even though the query might be more related to the \"politics\" route, it will be classified as \"chitchat\" because we've restricted the routes to consider.\n", - "\n", - "Similarly, we can restrict it to the \"politics\" route:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "1Owt-85Nh6tO", - "outputId": "c5f9024f-7b70-4e3e-dcb1-3cb03688e8e6" - }, - "outputs": [ - { - "data": { - "text/plain": [ - "RouteChoice(name=None, function_call=None, similarity_score=None)" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "rl(\"how's the weather today?\", route_filter=[\"politics\"])" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "EyhopRtUh6tP" - }, - "source": [ - "In this case, it will return None because the query doesn't match the \"politics\" route well enough to pass the threshold.\n", - "\n" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "py12", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.8" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/pinecone-local.ipynb b/pinecone-local.ipynb new file mode 100644 index 00000000..5cfc5409 --- /dev/null +++ b/pinecone-local.ipynb @@ -0,0 +1,773 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using PineconeLocalIndex for Routes\n", + "\n", + "Pinecone Local is an in-memory Pinecone Database emulator available as a Docker image.\n", + "\n", + "It's useful for running tests using the Pinecone local server. Your data will not leave your system, which is also helpful if you want to do testing locally before committing to a Pinecone account.\n", + "\n", + "## Limitations\n", + "Pinecone Local has the following limitations:\n", + "\n", + "- Pinecone Local is available only as a Docker image.\n", + "- Pinecone Local is an in-memory emulator and is not suitable for production. Records loaded into Pinecone Local do not persist after it is stopped.\n", + "- Pinecone Local does not authenticate client requests. API keys are ignored.\n", + "- Max number of records per index: 100,000.\n", + "\n", + "## Getting Started\n", + "Make sure [Docker](https://docs.docker.com/get-docker/) is installed and running on your local machine.\n", + "\n", + "### Download the latest pinecone-local Docker image:\n", + "\n", + "\n", + "Download the latest pinecone-local Docker image:\n", + "\n", + "```bash\n", + "docker pull ghcr.io/pinecone-io/pinecone-local:latest\n", + "```\n", + "\n", + "### Start Pinecone Local:\n", + "\n", + "```bash\n", + "docker run -d \\\n", + "--name pinecone-local \\\n", + "-e PORT=5080 \\\n", + "-e PINECONE_HOST=localhost \\\n", + "-p 5080-6000:5080-6000 \\\n", + "--platform linux/amd64 \\\n", + "ghcr.io/pinecone-io/pinecone-local:latest\n", + "```\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "!pip install -qU \"semantic-router[pinecone]==0.0.22\"" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\awesome\\anaconda3\\envs\\py12\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "from semantic_router import Route\n", + "\n", + "# we could use this as a guide for our chatbot to avoid political conversations\n", + "politics = Route(\n", + " name=\"politics\",\n", + " utterances=[\n", + " \"isn't politics the best thing ever\",\n", + " \"why don't you tell me about your political opinions\",\n", + " \"don't you just love the president\" \"don't you just hate the president\",\n", + " \"they're going to destroy this country!\",\n", + " \"they will save the country!\",\n", + " ],\n", + ")\n", + "\n", + "# this could be used as an indicator to our chatbot to switch to a more\n", + "# conversational prompt\n", + "chitchat = Route(\n", + " name=\"chitchat\",\n", + " utterances=[\n", + " \"how's the weather today?\",\n", + " \"how are things going?\",\n", + " \"lovely weather today\",\n", + " \"the weather is horrendous\",\n", + " \"let's go to the chippy\",\n", + " ],\n", + ")\n", + "\n", + "# we place both of our decisions together into single list\n", + "routes = [politics, chitchat]" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Route(name='politics', utterances=[\"isn't politics the best thing ever\", \"why don't you tell me about your political opinions\", \"don't you just love the presidentdon't you just hate the president\", \"they're going to destroy this country!\", 'they will save the country!'], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={}),\n", + " Route(name='chitchat', utterances=[\"how's the weather today?\", 'how are things going?', 'lovely weather today', 'the weather is horrendous', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={})]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "routes" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from getpass import getpass\n", + "from semantic_router.encoders import OpenAIEncoder\n", + "\n", + "# get at platform.openai.com\n", + "os.environ[\"OPENAI_API_KEY\"] = os.environ.get(\"OPENAI_API_KEY\") or getpass(\n", + " \"Enter OpenAI API key: \"\n", + ")\n", + "encoder = OpenAIEncoder(\n", + " name=\"text-embedding-3-large\", score_threshold=0.5, dimensions=1536\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For Pinecone Local, you can pass the API key as `pclocal`." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:40:01 - semantic_router.utils.logger - WARNING - pinecone.py:169 - __init__() - Default region changed from us-west-2 to us-east-1 in v0.1.0.dev6\n", + "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - discover_namespace_packages.py:12 - discover_subpackages() - Discovering subpackages in _NamespacePath(['c:\\\\Users\\\\awesome\\\\anaconda3\\\\envs\\\\py12\\\\Lib\\\\site-packages\\\\pinecone_plugins'])\n", + "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - discover_plugins.py:9 - discover_plugins() - Looking for plugins in pinecone_plugins.inference\n", + "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - installation.py:10 - install_plugins() - Installing plugin inference into Pinecone\n", + "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:233 - _init_index() - index_host exists-pinecone:localhost:5081\n", + "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:234 - _init_index() - base_url exists-pinecone:http://localhost:5080\n", + "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:251 - _init_index() - index_host exists:http://localhost:5081\n", + "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:252 - _init_index() - index exists:\n" + ] + } + ], + "source": [ + "import os\n", + "from semantic_router.index.pinecone import PineconeIndex\n", + "\n", + "os.environ[\"PINECONE_API_KEY\"] = os.environ.get(\"PINECONE_API_KEY\") or getpass(\n", + " \"Enter Pinecone API key: \"\n", + ")\n", + "\n", + "# Pass the pinecone local hosted url as base url\n", + "# os.environ[\"PINECONE_API_BASE_URL\"] = \"https://api.pinecone.io\"\n", + "os.environ[\"PINECONE_API_BASE_URL\"] = \"http://localhost:5080\"\n", + "\n", + "index = PineconeIndex(\n", + " index_name=\"route-test\", dimensions=1536, base_url=\"http://localhost:5080\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:233 - _init_index() - index_host exists-pinecone:localhost:5081\n", + "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:234 - _init_index() - base_url exists-pinecone:http://localhost:5080\n", + "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:251 - _init_index() - index_host exists:http://localhost:5081\n", + "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:252 - _init_index() - index exists:\n" + ] + } + ], + "source": [ + "from semantic_router.routers import SemanticRouter\n", + "\n", + "router = SemanticRouter(\n", + " encoder=encoder,\n", + " routes=routes,\n", + " index=index,\n", + " auto_sync=\"local\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can check our route layer and index information." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'http://localhost:5081'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "index.index_host" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'http://localhost:5081'" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index.index_host" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'indexes': [{'deletion_protection': 'disabled',\n", + " 'dimension': 1536,\n", + " 'host': 'localhost:5081',\n", + " 'metric': 'dotproduct',\n", + " 'name': 'route-test',\n", + " 'spec': {'serverless': {'cloud': 'aws', 'region': 'us-east-1'}},\n", + " 'status': {'ready': True, 'state': 'Ready'}}]}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index.client.list_indexes()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index.is_ready()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.is_synced()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[' chitchat: how are things going?',\n", + " \" chitchat: how's the weather today?\",\n", + " \" chitchat: let's go to the chippy\",\n", + " ' chitchat: lovely weather today',\n", + " ' chitchat: the weather is horrendous',\n", + " \" politics: don't you just love the presidentdon't you just hate the president\",\n", + " \" politics: isn't politics the best thing ever\",\n", + " ' politics: they will save the country!',\n", + " \" politics: they're going to destroy this country!\",\n", + " \" politics: why don't you tell me about your political opinions\"]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.get_utterance_diff()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:41:08 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:08 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" + ] + }, + { + "data": { + "text/plain": [ + "RouteChoice(name='politics', function_call=None, similarity_score=None)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router(\"don't you love politics?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['politics', 'chitchat']" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.list_route_names()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:41:17 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:17 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" + ] + }, + { + "data": { + "text/plain": [ + "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router(\"how are things going?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(router.index)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also view all of the records for a given route:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['politics#64069085d9d6e98e5a80915f69fabe82bac6c742f801bc305c5001dce88f0d19',\n", + " 'politics#af8b76111f260cf44fb34f04fcf82927dcbe08e8f47c30f4d571379c1512fac8',\n", + " 'politics#d1bb40236c3d95b9c695bfa86b314b6da4eb87e136699563fccae47fccea23e2',\n", + " 'politics#ed0f3dd7bd5dea12e55b1953bcd2c562a5ab19f501f6d5ff8c8927652c3904b8',\n", + " 'politics#fc6d15f9e6075e6de82b3fbef6722b64353e4eadc8d663b7312a4ed60c43e6f6']" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index._get_route_ids(route_name=\"politics\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And query:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:41:25 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:25 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" + ] + }, + { + "data": { + "text/plain": [ + "'politics'" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router(\"don't you love politics?\").name" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:19:14 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:19:14 - semantic_router.utils.logger - ERROR - pinecone.py:572 - query() - retrying query with vector as str\n" + ] + }, + { + "data": { + "text/plain": [ + "'chitchat'" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router(\"how's the weather today?\").name" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:41:32 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:32 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" + ] + } + ], + "source": [ + "router(\"I'm interested in learning about llama 2\").name" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can delete or update routes." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(router.index)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Deleting a Route from the Semantic Router\n", + "In this section, we demonstrate how to delete a specific route from the `SemanticRouter` instance. This is useful when you want to remove a route that is no longer needed or to update the routing logic dynamically.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:41:39 - semantic_router.utils.logger - WARNING - pinecone.py:611 - _read_config() - Configuration for sr_lock parameter not found in index.\n", + "2025-02-03 15:41:39 - semantic_router.utils.logger - INFO - pinecone.py:477 - delete() - index is not None, deleting...\n", + "2025-02-03 15:41:39 - semantic_router.utils.logger - INFO - pinecone.py:491 - delete() - Deleted 5 vectors from index route-test.\n" + ] + }, + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import time\n", + "\n", + "router.delete(route_name=\"politics\")\n", + "time.sleep(1)\n", + "len(router.index)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:41:49 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:49 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" + ] + } + ], + "source": [ + "router(\"don't you love politics??\").name" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Route(name='chitchat', utterances=['how are things going?', \"how's the weather today?\", 'the weather is horrendous', 'lovely weather today', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={})]" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "router.index.get_routes()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Asynchronous Route Query with Semantic Router\n", + "\n", + "In this section, we explore how to perform an asynchronous query using the `SemanticRouter`. This approach is beneficial when you want to handle multiple queries concurrently without blocking the execution of your program." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-03 15:42:01 - httpx - INFO - _client.py:1729 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n" + ] + }, + { + "data": { + "text/plain": [ + "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "await router.acall(\"how are things going?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'indexes': [{'name': 'route-test',\n", + " 'dimension': 1536,\n", + " 'metric': 'dotproduct',\n", + " 'host': 'localhost:5081',\n", + " 'deletion_protection': 'disabled',\n", + " 'spec': {'serverless': {'cloud': 'aws', 'region': 'us-east-1'}},\n", + " 'status': {'ready': True, 'state': 'Ready'}}]}" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "await router.index._async_list_indexes()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Stop and remove Pinecone Local\n", + "\n", + "To stop and remove the resources for Pinecone Local, run the following command:\n", + "\n", + "```bash\n", + "docker compose down\n", + "docker stop pinecone-local\n", + "docker rm pinecone-local\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "py12", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/semantic_router/index/pinecone.py b/semantic_router/index/pinecone.py index 15889013..e7b38de7 100644 --- a/semantic_router/index/pinecone.py +++ b/semantic_router/index/pinecone.py @@ -4,6 +4,8 @@ import os import time import json +import requests +from json.decoder import JSONDecodeError from typing import Any, Dict, List, Optional, Union, Tuple @@ -19,6 +21,13 @@ def clean_route_name(route_name: str) -> str: return route_name.strip().replace(" ", "-") +class DeleteRequest(BaseModel): + ids: list[str] | None = None + delete_all: bool = False + namespace: str | None = None + filter: dict[str, Any] | None = None + + def build_records( embeddings: List[List[float]], routes: List[str], @@ -115,8 +124,9 @@ class PineconeIndex(BaseIndex): index: Optional[Any] = Field(default=None, exclude=True) ServerlessSpec: Any = Field(default=None, exclude=True) namespace: Optional[str] = "" - base_url: Optional[str] = "https://api.pinecone.io" + base_url: Optional[str] = None headers: dict[str, str] = {} + index_host: Optional[str] = "http://localhost:5080" def __init__( self, @@ -128,19 +138,25 @@ def __init__( region: str = "us-east-1", host: str = "", namespace: Optional[str] = "", - base_url: Optional[str] = "https://api.pinecone.io", + base_url: Optional[str] = "", init_async_index: bool = False, ): super().__init__() self.api_key = api_key or os.getenv("PINECONE_API_KEY") if not self.api_key: raise ValueError("Pinecone API key is required.") + self.headers = { "Api-Key": self.api_key, "Content-Type": "application/json", - "X-Pinecone-API-Version": "2024-07", "User-Agent": "source_tag=semanticrouter", } + + self.base_url = base_url or os.getenv("PINECONE_API_BASE_URL") + + if self.base_url and "api.pinecone.io" in self.base_url: + self.headers["X-Pinecone-API-Version"] = "2024-07" + self.index_name = index_name self.dimensions = dimensions self.metric = metric @@ -151,16 +167,11 @@ def __init__( raise ValueError("Namespace 'sr_config' is reserved for internal use.") self.namespace = namespace self.type = "pinecone" - self.api_key = api_key or os.getenv("PINECONE_API_KEY") - self.base_url = base_url logger.warning( "Default region changed from us-west-2 to us-east-1 in v0.1.0.dev6" ) - if self.api_key is None: - raise ValueError("Pinecone API key is required.") - self.client = self._initialize_client(api_key=self.api_key) # try initializing index @@ -218,7 +229,22 @@ def _init_index(self, force_create: bool = False) -> Union[Any, None]: time.sleep(0.5) elif index_exists: # if the index exists we just return it - index = self.client.Index(self.index_name) + self.index_host = self.client.describe_index(self.index_name).host + + if self.index_host and self.base_url: + if "api.pinecone.io" in self.base_url: + if not self.index_host.startswith("http"): + self.index_host = f"https://{self.index_host}" + else: + if "http" not in self.index_host: + self.index_host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.index_host.split(':')[-1]}" + elif not self.index_host.startswith("http://"): + if "localhost" in self.index_host: + self.index_host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.index_host.split(':')[-1]}" + else: + self.index_host = f"http://{self.index_host}" + index = self.client.Index(self.index_name, host=self.index_host) + self.host = self.index_host # grab the dimensions from the index self.dimensions = index.describe_index_stats()["dimension"] elif force_create and not dimensions_given: @@ -443,12 +469,37 @@ def _get_all(self, prefix: Optional[str] = None, include_metadata: bool = False) def delete(self, route_name: str): route_vec_ids = self._get_route_ids(route_name=route_name) if self.index is not None: - self.index.delete(ids=route_vec_ids, namespace=self.namespace) + logger.info("index is not None, deleting...") + if self.base_url and "api.pinecone.io" in self.base_url: + self.index.delete(ids=route_vec_ids, namespace=self.namespace) + else: + + response = requests.post( + f"{self.index_host}/vectors/delete", + json=DeleteRequest( + ids=route_vec_ids, + delete_all=True, + namespace=self.namespace, + ).model_dump(exclude_none=True), + timeout=10, + ) + if response.status_code == 200: + logger.info( + f"Deleted {len(route_vec_ids)} vectors from index {self.index_name}." + ) + else: + error_message = response.text + raise Exception( + f"Failed to delete vectors: {response.status_code} : {error_message}" + ) else: raise ValueError("Index is None, could not delete.") def delete_all(self): - self.index.delete(delete_all=True, namespace=self.namespace) + if self.index is not None: + self.index.delete(delete_all=True, namespace=self.namespace) + else: + raise ValueError("Index is None, could not delete.") def describe(self) -> IndexConfig: if self.index is not None: @@ -502,19 +553,31 @@ def query( else: filter_query = None if sparse_vector is not None: + logger.error(f"sparse_vector exists:{sparse_vector}") if isinstance(sparse_vector, dict): sparse_vector = SparseEmbedding.from_dict(sparse_vector) if isinstance(sparse_vector, SparseEmbedding): # unnecessary if-statement but mypy didn't like this otherwise sparse_vector = sparse_vector.to_pinecone() - results = self.index.query( - vector=[query_vector_list], - sparse_vector=sparse_vector, - top_k=top_k, - filter=filter_query, - include_metadata=True, - namespace=self.namespace, - ) + try: + results = self.index.query( + vector=[query_vector_list], + sparse_vector=sparse_vector, + top_k=top_k, + filter=filter_query, + include_metadata=True, + namespace=self.namespace, + ) + except Exception: + logger.error("retrying query with vector as str") + results = self.index.query( + vector=query_vector_list, + sparse_vector=sparse_vector, + top_k=top_k, + filter=filter_query, + include_metadata=True, + namespace=self.namespace, + ) scores = [result["score"] for result in results["matches"]] route_names = [result["metadata"]["sr_route"] for result in results["matches"]] return np.array(scores), route_names @@ -711,16 +774,35 @@ async def _async_query( "filter": filter, "top_k": top_k, "include_metadata": include_metadata, + "topK": top_k, + "includeMetadata": include_metadata, } if self.host == "": raise ValueError("self.host is not initialized.") + elif self.base_url and "api.pinecone.io" in self.base_url: + if not self.host.startswith("http"): + logger.error(f"host exists:{self.host}") + + self.host = f"https://{self.host}" + elif self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" + async with aiohttp.ClientSession() as session: async with session.post( - f"https://{self.host}/query", + f"{self.host}/query", json=params, headers=self.headers, ) as response: - return await response.json(content_type=None) + if response.status != 200: + error_text = await response.text() + logger.error(f"Error in query response: {error_text}") + return {} # or handle the error as needed + + try: + return await response.json(content_type=None) + except JSONDecodeError as e: + logger.error(f"JSON decode error: {e}") + return {} async def _async_list_indexes(self): async with aiohttp.ClientSession() as session: @@ -739,9 +821,17 @@ async def _async_upsert( "vectors": vectors, "namespace": namespace, } + + if self.base_url and "api.pinecone.io" in self.base_url: + if not self.host.startswith("http"): + logger.error(f"host exists:{self.host}") + self.host = f"https://{self.host}" + + elif self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" async with aiohttp.ClientSession() as session: async with session.post( - f"https://{self.host}/vectors/upsert", + f"{self.host}/vectors/upsert", json=params, headers=self.headers, ) as response: @@ -775,9 +865,16 @@ async def _async_delete(self, ids: list[str], namespace: str = ""): "ids": ids, "namespace": namespace, } + if self.base_url and "api.pinecone.io" in self.base_url: + if not self.host.startswith("http"): + logger.error(f"host exists:{self.host}") + self.host = f"https://{self.host}" + elif self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" + async with aiohttp.ClientSession() as session: async with session.post( - f"https://{self.host}/vectors/delete", + f"{self.host}/vectors/delete", json=params, headers=self.headers, ) as response: @@ -817,7 +914,15 @@ async def _async_get_all( else: prefix_str = "" - list_url = f"https://{self.host}/vectors/list{prefix_str}" + if self.base_url and "api.pinecone.io" in self.base_url: + if not self.host.startswith("http"): + logger.error(f"host exists:{self.host}") + self.host = f"https://{self.host}" + + elif self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" + + list_url = f"{self.host}/vectors/list{prefix_str}" params: dict = {} if self.namespace: params["namespace"] = self.namespace @@ -875,7 +980,14 @@ async def _async_fetch_metadata( """ if self.host == "": raise ValueError("self.host is not initialized.") - url = f"https://{self.host}/vectors/fetch" + if self.base_url and "api.pinecone.io" in self.base_url: + if not self.host.startswith("http"): + logger.error(f"host exists:{self.host}") + self.host = f"https://{self.host}" + elif self.host.startswith("localhost") and self.base_url: + self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" + + url = f"{self.host}/vectors/fetch" params = { "ids": [vector_id], diff --git a/semantic_router/index/pinecone_local.py b/semantic_router/index/pinecone_local.py deleted file mode 100644 index 268e2432..00000000 --- a/semantic_router/index/pinecone_local.py +++ /dev/null @@ -1,1037 +0,0 @@ -import asyncio -import hashlib -import json -import os -import time -from typing import Any, Dict, List, Optional, Union - - -import aiohttp -import numpy as np -import requests -from pydantic import BaseModel, Field - -from semantic_router.index.base import BaseIndex, IndexConfig -from semantic_router.schema import ConfigParameter, SparseEmbedding -from semantic_router.utils.logger import logger - - -def clean_route_name(route_name: str) -> str: - return route_name.strip().replace(" ", "-") - - -class DeleteRequest(BaseModel): - ids: list[str] | None = None - delete_all: bool = False - namespace: str | None = None - filter: dict[str, Any] | None = None - - -def build_records( - embeddings: list[list[float]], - routes: list[str], - utterances: list[str], - function_schemas: list[dict[str, Any]] | None | None = None, - metadata_list: list[dict[str, Any]] | None = None, - sparse_embeddings: list[SparseEmbedding] | None | None = None, -) -> list[dict]: - if function_schemas is None: - function_schemas = [{}] * len(embeddings) - if metadata_list is None: - metadata_list = [] - if sparse_embeddings is None: - vectors_to_upsert = [ - PineconeRecord( - values=vector, - route=route, - utterance=utterance, - function_schema=json.dumps(function_schema), - metadata=metadata, - ).to_dict() - for vector, route, utterance, function_schema, metadata in zip( - embeddings, - routes, - utterances, - function_schemas, - metadata_list, - ) - ] - else: - vectors_to_upsert = [ - PineconeRecord( - values=vector, - sparse_values=sparse_emb.to_pinecone(), - route=route, - utterance=utterance, - function_schema=json.dumps(function_schema), - metadata=metadata, - ).to_dict() - for vector, route, utterance, function_schema, metadata, sparse_emb in zip( - embeddings, - routes, - utterances, - function_schemas, - metadata_list, - sparse_embeddings, - ) - ] - return vectors_to_upsert - - -class PineconeRecord(BaseModel): - id: str = "" - values: List[float] - sparse_values: Optional[dict[str, list]] = None - route: str - utterance: str - function_schema: str = "{}" - metadata: Dict[str, Any] = {} # Additional metadata dictionary - - def __init__(self, **data): - super().__init__(**data) - clean_route = clean_route_name(self.route) - # Use SHA-256 for a more secure hash - utterance_id = hashlib.sha256(self.utterance.encode()).hexdigest() - self.id = f"{clean_route}#{utterance_id}" - self.metadata.update( - { - "sr_route": self.route, - "sr_utterance": self.utterance, - "sr_function_schema": self.function_schema, - } - ) - - def to_dict(self): - d = { - "id": self.id, - "values": self.values, - "metadata": self.metadata, - } - if self.sparse_values: - d["sparse_values"] = self.sparse_values - return d - - -class PineconeLocalIndex(BaseIndex): - index_prefix: str = "semantic-router--" - api_key: Optional[str] = None - index_name: str = "index" - dimensions: Union[int, None] = None - metric: str = "dotproduct" - cloud: str = "aws" - region: str = "us-east-1" - host: str = "" - client: Any = Field(default=None, exclude=True) - index: Optional[Any] = Field(default=None, exclude=True) - ServerlessSpec: Any = Field(default=None, exclude=True) - namespace: Optional[str] = "" - base_url: Optional[str] = "http://localhost:5080" - headers: dict[str, str] = {} - index_host: Optional[str] = "http://localhost:5080" - - def __init__( - self, - api_key: Optional[str] = None, - index_name: str = "index", - dimensions: Optional[int] = None, - metric: str = "dotproduct", - cloud: str = "aws", - region: str = "us-east-1", - host: str = "", - namespace: Optional[str] = "", - base_url: Optional[str] = None, - init_async_index: bool = False, - ): - super().__init__() - self.api_key = api_key or os.getenv("PINECONE_API_KEY") - logger.warning(f"Pinecone API key: {self.api_key}") - logger.warning(f"Pinecone API key os env: {os.getenv('PINECONE_API_KEY')}") - - if not self.api_key: - raise ValueError("Pinecone API key is required.") - self.headers = { - "Api-Key": self.api_key, - "Content-Type": "application/json", - "User-Agent": "source_tag=semanticrouter", - } - self.index_name = index_name - self.dimensions = dimensions - self.metric = metric - self.cloud = cloud - self.region = region - self.host = host - if namespace == "sr_config": - raise ValueError("Namespace 'sr_config' is reserved for internal use.") - self.namespace = namespace - self.type = "pinecone" - # self.api_key = api_key or os.getenv("PINECONE_API_KEY") - self.base_url = base_url or os.getenv("PINECONE_API_BASE_URL") - - logger.warning( - "Default region changed from us-west-2 to us-east-1 in v0.1.0.dev6" - ) - - # if self.api_key is None: - # raise ValueError("Pinecone API key is required.") - - self.client = self._initialize_client(api_key=self.api_key) - # if init_async_index: - # self.async_client = self._initialize_async_client(api_key=self.api_key) - # else: - # self.async_client = None - # try initializing index - self.index = self._init_index() - - def _initialize_client(self, api_key: str | None = None): - try: - from pinecone import Pinecone, ServerlessSpec - - self.ServerlessSpec = ServerlessSpec - except ImportError: - raise ImportError( - "Please install pinecone-client to use PineconeIndex. " - "You can install it with: " - "`pip install 'semantic-router[pinecone]'`" - ) - pinecone_args = { - "api_key": api_key, - "source_tag": "semanticrouter", - "host": self.base_url, - } - if self.namespace: - pinecone_args["namespace"] = self.namespace - - return Pinecone(**pinecone_args) - - # def _initialize_async_client(self, api_key: str | None = None): - # api_key = api_key or self.api_key - # if api_key is None: - # raise ValueError("Pinecone API key is required.") - # async_client = aiohttp.ClientSession( - # headers={ - # "Api-Key": api_key, - # "Content-Type": "application/json", - # "X-Pinecone-API-Version": "2024-07", - # "User-Agent": "source_tag=semanticrouter", - # } - # ) - # return async_client - - def _init_index(self, force_create: bool = False) -> Any | None: - """Initializing the index can be done after the object has been created - to allow for the user to set the dimensions and other parameters. - - If the index doesn't exist and the dimensions are given, the index will - be created. If the index exists, it will be returned. If the index doesn't - exist and the dimensions are not given, the index will not be created and - None will be returned. - - :param force_create: If True, the index will be created even if the - dimensions are not given (which will raise an error). - :type force_create: bool, optional - """ - index_exists = self.index_name in self.client.list_indexes().names() - dimensions_given = self.dimensions is not None - # pinecone_base_url = os.getenv("PINECONE_API_BASE_URL") - - # if not pinecone_base_url: - # pinecone_base_url = "http://localhost:5080" - - if dimensions_given and not index_exists: - # if the index doesn't exist and we have dimension value - # we create the index - self.client.create_index( - name=self.index_name, - dimension=self.dimensions, - metric=self.metric, - spec=self.ServerlessSpec(cloud=self.cloud, region=self.region), - ) - # wait for index to be created - while not self.client.describe_index(self.index_name).status["ready"]: - time.sleep(1) - index = self.client.Index(self.index_name) - self.index_host = self.client.describe_index(self.index_name).host - time.sleep(0.5) - elif index_exists: - # if the index exists we just return it - self.index_host = self.client.describe_index(self.index_name).host - - if self.index_host and self.base_url: - if "http" not in self.index_host: - self.index_host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.index_host.split(':')[-1]}" - elif not self.index_host.startswith("http://"): - - # TODO: Need to pass the an argument for service name - if "localhost" in self.index_host: - self.index_host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.index_host.split(':')[-1]}" - logger.error(f"index exists:{self.index_host}") - else: - self.index_host = f"http://{self.index_host}" - index = self.client.Index(self.index_name, host=self.index_host) - self.host = self.index_host - logger.error(f"index_host exists:{self.index_host}") - logger.error(f"index exists:{index}") - # grab the dimensions from the index - self.dimensions = index.describe_index_stats()["dimension"] - elif force_create and not dimensions_given: - raise ValueError( - "Cannot create an index without specifying the dimensions." - ) - else: - # if the index doesn't exist and we don't have the dimensions - # we return None - logger.warning( - "Index could not be initialized. Init parameters: " - f"{self.index_name=}, {self.dimensions=}, {self.metric=}, " - f"{self.cloud=}, {self.region=}, {self.host=}, {self.namespace=}, " - f"{force_create=}" - ) - index = None - if index is not None: - self.host = self.client.describe_index(self.index_name)["host"] - return index - - async def _init_async_index(self, force_create: bool = False): - index_stats = None - indexes = await self._async_list_indexes() - index_names = [i["name"] for i in indexes["indexes"]] - index_exists = self.index_name in index_names - if self.dimensions is not None and not index_exists: - await self._async_create_index( - name=self.index_name, - dimension=self.dimensions, - metric=self.metric, - cloud=self.cloud, - region=self.region, - ) - # TODO describe index and async sleep - index_ready = "false" - while index_ready != "true": - index_stats = await self._async_describe_index(self.index_name) - index_ready = index_stats["status"]["ready"] - await asyncio.sleep(1) - elif index_exists: - index_stats = await self._async_describe_index(self.index_name) - # grab dimensions for the index - self.dimensions = index_stats["dimension"] - elif force_create and self.dimensions is None: - raise ValueError( - "Cannot create an index without specifying the dimensions." - ) - else: - # if the index doesn't exist and we don't have the dimensions - # we raise warning - logger.warning( - "Index could not be initialized. Init parameters: " - f"{self.index_name=}, {self.dimensions=}, {self.metric=}, " - f"{self.cloud=}, {self.region=}, {self.host=}, {self.namespace=}, " - f"{force_create=}" - ) - logger.error(f"index_stats: {index_stats}") - self.host = index_stats["host"] if index_stats else "" - - def _batch_upsert(self, batch: List[Dict]): - """Helper method for upserting a single batch of records. - - :param batch: The batch of records to upsert. - :type batch: List[Dict] - """ - if self.index is not None: - self.index.upsert(vectors=batch, namespace=self.namespace) - else: - raise ValueError("Index is None, could not upsert.") - - def add( - self, - embeddings: list[list[float]], - routes: list[str], - utterances: list[str], - function_schemas: list[dict[str, Any]] | None | None = None, - metadata_list: list[dict[str, Any]] | None = None, - batch_size: int = 100, - sparse_embeddings: list[SparseEmbedding] | None | None = None, - **kwargs, - ): - """Add vectors to Pinecone in batches.""" - if metadata_list is None: - metadata_list = [] - if self.index is None: - self.dimensions = self.dimensions or len(embeddings[0]) - self.index = self._init_index(force_create=True) - vectors_to_upsert = build_records( - embeddings=embeddings, - routes=routes, - utterances=utterances, - function_schemas=function_schemas, - metadata_list=metadata_list, - sparse_embeddings=sparse_embeddings, - ) - for i in range(0, len(vectors_to_upsert), batch_size): - batch = vectors_to_upsert[i : i + batch_size] - self._batch_upsert(batch) - - async def aadd( - self, - embeddings: list[list[float]], - routes: list[str], - utterances: list[str], - function_schemas: list[dict[str, Any]] | None | None = None, - metadata_list: list[dict[str, Any]] | None = None, - batch_size: int = 100, - sparse_embeddings: list[SparseEmbedding] | None | None = None, - **kwargs, - ): - """Add vectors to Pinecone in batches.""" - if metadata_list is None: - metadata_list = [] - if self.index is None: - self.dimensions = self.dimensions or len(embeddings[0]) - self.index = await self._init_async_index(force_create=True) - vectors_to_upsert = build_records( - embeddings=embeddings, - routes=routes, - utterances=utterances, - function_schemas=function_schemas, - metadata_list=metadata_list, - sparse_embeddings=sparse_embeddings, - ) - - for i in range(0, len(vectors_to_upsert), batch_size): - batch = vectors_to_upsert[i : i + batch_size] - await self._async_upsert( - vectors=batch, - namespace=self.namespace or "", - ) - - def _remove_and_sync(self, routes_to_delete: dict): - for route, utterances in routes_to_delete.items(): - remote_routes = self._get_routes_with_ids(route_name=route) - ids_to_delete = [ - r["id"] - for r in remote_routes - if (r["route"], r["utterance"]) - in zip([route] * len(utterances), utterances) - ] - if ids_to_delete and self.index: - self.index.delete(ids=ids_to_delete, namespace=self.namespace) - - async def _async_remove_and_sync(self, routes_to_delete: dict): - for route, utterances in routes_to_delete.items(): - remote_routes = await self._async_get_routes_with_ids(route_name=route) - ids_to_delete = [ - r["id"] - for r in remote_routes - if (r["route"], r["utterance"]) - in zip([route] * len(utterances), utterances) - ] - if ids_to_delete and self.index: - await self._async_delete( - ids=ids_to_delete, namespace=self.namespace or "" - ) - - def _get_route_ids(self, route_name: str): - clean_route = clean_route_name(route_name) - ids, _ = self._get_all(prefix=f"{clean_route}#") - return ids - - async def _async_get_route_ids(self, route_name: str): - clean_route = clean_route_name(route_name) - ids, _ = await self._async_get_all(prefix=f"{clean_route}#") - return ids - - def _get_routes_with_ids(self, route_name: str): - clean_route = clean_route_name(route_name) - ids, metadata = self._get_all(prefix=f"{clean_route}#", include_metadata=True) - route_tuples = [] - for id, data in zip(ids, metadata): - route_tuples.append( - { - "id": id, - "route": data["sr_route"], - "utterance": data["sr_utterance"], - } - ) - return route_tuples - - async def _async_get_routes_with_ids(self, route_name: str): - clean_route = clean_route_name(route_name) - ids, metadata = await self._async_get_all( - prefix=f"{clean_route}#", include_metadata=True - ) - route_tuples = [] - for id, data in zip(ids, metadata): - route_tuples.append( - {"id": id, "route": data["sr_route"], "utterance": data["sr_utterance"]} - ) - return route_tuples - - def _get_all(self, prefix: str | None = None, include_metadata: bool = False): - """ - Retrieves all vector IDs from the Pinecone index using pagination. - - :param prefix: The prefix to filter the vectors by. - :type prefix: Optional[str] - :param include_metadata: Whether to include metadata in the response. - :type include_metadata: bool - :return: A tuple containing a list of vector IDs and a list of metadata dictionaries. - :rtype: tuple[list[str], list[dict]] - """ - if self.index is None: - raise ValueError("Index is None, could not retrieve vector IDs.") - all_vector_ids = [] - metadata = [] - - for ids in self.index.list(prefix=prefix, namespace=self.namespace): - all_vector_ids.extend(ids) - - if include_metadata: - for id in ids: - res_meta = ( - self.index.fetch(ids=[id], namespace=self.namespace) - if self.index - else {} - ) - metadata.extend( - [x["metadata"] for x in res_meta["vectors"].values()] - ) - return all_vector_ids, metadata - - def delete(self, route_name: str): - route_vec_ids = self._get_route_ids(route_name=route_name) - if self.index is not None: - logger.info("index is not None, deleting...") - response = requests.post( - f"{self.index_host}/vectors/delete", - json=DeleteRequest( - ids=route_vec_ids, - delete_all=True, - namespace=self.namespace, - ).model_dump(exclude_none=True), - timeout=10, - ) - if response.status_code == 200: - logger.info( - f"Deleted {len(route_vec_ids)} vectors from index {self.index_name}." - ) - return response.json() - else: - error_message = response.text - raise Exception( - f"Failed to delete vectors: {response.status_code} : {error_message}" - ) - else: - raise ValueError("Index is None, could not delete.") - - # index_host = self.client.describe_index(self.index_name).host - - def delete_all(self): - if self.index is not None: - self.index.delete(delete_all=True, namespace=self.namespace) - else: - raise ValueError("Index is None, could not delete.") - - def describe(self) -> IndexConfig: - if self.index is not None: - stats = self.index.describe_index_stats() - return IndexConfig( - type=self.type, - dimensions=stats["dimension"], - vectors=stats["namespaces"][self.namespace]["vector_count"], - ) - else: - return IndexConfig( - type=self.type, - dimensions=self.dimensions or 0, - vectors=0, - ) - - def is_ready(self) -> bool: - """ - Checks if the index is ready to be used. - """ - return self.index is not None - - def query( - self, - vector: np.ndarray, - top_k: int = 5, - route_filter: list[str] | None = None, - sparse_vector: dict[int, float] | SparseEmbedding | None = None, - ) -> tuple[np.ndarray, list[str]]: - """Search the index for the query vector and return the top_k results. - - :param vector: The query vector to search for. - :type vector: np.ndarray - :param top_k: The number of top results to return, defaults to 5. - :type top_k: int, optional - :param route_filter: A list of route names to filter the search results, defaults to None. - :type route_filter: Optional[List[str]], optional - :param sparse_vector: An optional sparse vector to include in the query. - :type sparse_vector: Optional[SparseEmbedding] - :param kwargs: Additional keyword arguments for the query, including sparse_vector. - :type kwargs: Any - :return: A tuple containing an array of scores and a list of route names. - :rtype: Tuple[np.ndarray, List[str]] - :raises ValueError: If the index is not populated. - """ - if self.index is None: - raise ValueError("Index is not populated.") - query_vector_list = vector.tolist() - if route_filter is not None: - filter_query = {"sr_route": {"$in": route_filter}} - else: - filter_query = None - if sparse_vector is not None: - if isinstance(sparse_vector, dict): - sparse_vector = SparseEmbedding.from_dict(sparse_vector) - if isinstance(sparse_vector, SparseEmbedding): - # unnecessary if-statement but mypy didn't like this otherwise - sparse_vector = sparse_vector.to_pinecone() - try: - results = self.index.query( - vector=[query_vector_list], - sparse_vector=sparse_vector, - top_k=top_k, - filter=filter_query, - include_metadata=True, - namespace=self.namespace, - ) - except Exception: - logger.error("retrying query with vector as str") - results = self.index.query( - vector=query_vector_list, - sparse_vector=sparse_vector, - top_k=top_k, - filter=filter_query, - include_metadata=True, - namespace=self.namespace, - ) - try: - scores = [result["score"] for result in results["matches"]] - route_names = [ - result["metadata"]["sr_route"] for result in results["matches"] - ] - return np.array(scores), route_names - except Exception as e: - results = self.index.query( - vector=query_vector_list, - sparse_vector=sparse_vector, - top_k=top_k, - filter=filter_query, - include_metadata=True, - namespace=self.namespace, - ) - logger.error(f"Error in query: {e}") - raise e - - def _read_config(self, field: str, scope: str | None = None) -> ConfigParameter: - scope = scope or self.namespace - if self.index is None: - return ConfigParameter( - field=field, - value="", - scope=scope, - ) - config_id = f"{field}#{scope}" - config_record = self.index.fetch( - ids=[config_id], - namespace="sr_config", - ) - if config_record.get("vectors"): - return ConfigParameter( - field=field, - value=config_record["vectors"][config_id]["metadata"]["value"], - created_at=config_record["vectors"][config_id]["metadata"][ - "created_at" - ], - scope=scope, - ) - else: - logger.warning(f"Configuration for {field} parameter not found in index.") - return ConfigParameter( - field=field, - value="", - scope=scope, - ) - - async def _async_read_config( - self, field: str, scope: str | None = None - ) -> ConfigParameter: - """Read a config parameter from the index asynchronously. - - :param field: The field to read. - :type field: str - :param scope: The scope to read. - :type scope: str | None - :return: The config parameter that was read. - :rtype: ConfigParameter - """ - scope = scope or self.namespace - if self.index is None: - return ConfigParameter( - field=field, - value="", - scope=scope, - ) - config_id = f"{field}#{scope}" - config_record = await self._async_fetch_metadata( - vector_id=config_id, namespace="sr_config" - ) - if config_record: - try: - return ConfigParameter( - field=field, - value=config_record["value"], - created_at=config_record["created_at"], - scope=scope, - ) - except KeyError: - raise ValueError( - f"Found invalid config record during sync: {config_record}" - ) - else: - logger.warning(f"Configuration for {field} parameter not found in index.") - return ConfigParameter( - field=field, - value="", - scope=scope, - ) - - def _write_config(self, config: ConfigParameter) -> ConfigParameter: - """Method to write a config parameter to the remote Pinecone index. - - :param config: The config parameter to write to the index. - :type config: ConfigParameter - """ - config.scope = config.scope or self.namespace - if self.index is None: - raise ValueError("Index has not been initialized.") - if self.dimensions is None: - raise ValueError("Must set PineconeIndex.dimensions before writing config.") - self.index.upsert( - vectors=[config.to_pinecone(dimensions=self.dimensions)], - namespace="sr_config", - ) - return config - - async def _async_write_config(self, config: ConfigParameter) -> ConfigParameter: - """Method to write a config parameter to the remote Pinecone index. - - :param config: The config parameter to write to the index. - :type config: ConfigParameter - """ - config.scope = config.scope or self.namespace - if self.index is None: - raise ValueError("Index has not been initialized.") - if self.dimensions is None: - raise ValueError("Must set PineconeIndex.dimensions before writing config.") - pinecone_config = config.to_pinecone(dimensions=self.dimensions) - await self._async_upsert( - vectors=[pinecone_config], - namespace="sr_config", - ) - return config - - async def aquery( - self, - vector: np.ndarray, - top_k: int = 5, - route_filter: list[str] | None = None, - sparse_vector: dict[int, float] | SparseEmbedding | None = None, - ) -> tuple[np.ndarray, list[str]]: - """ - Asynchronously search the index for the query vector and return the top_k results. - - :param vector: The query vector to search for. - :type vector: np.ndarray - :param top_k: The number of top results to return, defaults to 5. - :type top_k: int, optional - :param route_filter: A list of route names to filter the search results, defaults to None. - :type route_filter: Optional[List[str]], optional - :param kwargs: Additional keyword arguments for the query, including sparse_vector. - :type kwargs: Any - :keyword sparse_vector: An optional sparse vector to include in the query. - :type sparse_vector: Optional[dict] - :return: A tuple containing an array of scores and a list of route names. - :rtype: Tuple[np.ndarray, List[str]] - :raises ValueError: If the index is not populated. - """ - if self.host == "": - raise ValueError("Host is not initialized.") - query_vector_list = vector.tolist() - if route_filter is not None: - filter_query = {"sr_route": {"$in": route_filter}} - else: - filter_query = None - # set sparse_vector_obj - sparse_vector_obj: dict[str, Any] | None = None - if sparse_vector is not None: - if isinstance(sparse_vector, dict): - sparse_vector_obj = SparseEmbedding.from_dict(sparse_vector) - if isinstance(sparse_vector, SparseEmbedding): - # unnecessary if-statement but mypy didn't like this otherwise - sparse_vector_obj = sparse_vector.to_pinecone() - results = await self._async_query( - vector=query_vector_list, - sparse_vector=sparse_vector_obj, - namespace=self.namespace or "", - filter=filter_query, - top_k=top_k, - include_metadata=True, - ) - scores = [result["score"] for result in results["matches"]] - route_names = [result["metadata"]["sr_route"] for result in results["matches"]] - return np.array(scores), route_names - - async def aget_routes(self) -> list[tuple]: - """Asynchronously get a list of route and utterance objects currently - stored in the index. - - :return: A list of (route_name, utterance) objects. - :rtype: List[Tuple] - """ - if self.host == "": - raise ValueError("Host is not initialized.") - - return await self._async_get_routes() - - def delete_index(self): - self.client.delete_index(self.index_name) - self.index = None - - # __ASYNC CLIENT METHODS__ - async def _async_query( - self, - vector: list[float], - sparse_vector: dict[str, Any] | None = None, - namespace: str = "", - filter: dict | None = None, - top_k: int = 5, - include_metadata: bool = False, - ): - params = { - "vector": vector, - "sparse_vector": sparse_vector, - "namespace": namespace, - "filter": filter, - "topK": top_k, - "includeMetadata": include_metadata, - } - if self.host == "": - raise ValueError("self.host is not initialized.") - elif self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" - - async with aiohttp.ClientSession() as session: - async with session.post( - f"{self.host}/query", - json=params, - headers=self.headers, - ) as response: - return await response.json(content_type=None) - - async def _async_list_indexes(self): - async with aiohttp.ClientSession() as session: - async with session.get( - f"{self.base_url}/indexes", - headers=self.headers, - ) as response: - return await response.json(content_type=None) - - async def _async_upsert( - self, - vectors: list[dict], - namespace: str = "", - ): - params = { - "vectors": vectors, - "namespace": namespace, - } - if self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" - - async with aiohttp.ClientSession() as session: - async with session.post( - f"{self.host}/vectors/upsert", - json=params, - headers=self.headers, - ) as response: - res = await response.json(content_type=None) - return res - - async def _async_create_index( - self, - name: str, - dimension: int, - cloud: str, - region: str, - metric: str = "dotproduct", - ): - params = { - "name": name, - "dimension": dimension, - "metric": metric, - "spec": {"serverless": {"cloud": cloud, "region": region}}, - } - async with aiohttp.ClientSession() as session: - async with session.post( - f"{self.base_url}/indexes", - json=params, - headers=self.headers, - ) as response: - return await response.json(content_type=None) - - async def _async_delete(self, ids: list[str], namespace: str = ""): - params = { - "ids": ids, - "namespace": namespace, - } - if self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" - - async with aiohttp.ClientSession() as session: - async with session.post( - f"{self.host}/vectors/delete", - json=params, - headers=self.headers, - ) as response: - return await response.json(content_type=None) - - async def _async_describe_index(self, name: str): - async with aiohttp.ClientSession() as session: - async with session.get( - f"{self.base_url}/indexes/{name}", - headers=self.headers, - ) as response: - return await response.json(content_type=None) - - async def _async_get_all( - self, prefix: str | None = None, include_metadata: bool = False - ) -> tuple[list[str], list[dict]]: - """Retrieves all vector IDs from the Pinecone index using pagination - asynchronously. - - :param prefix: The prefix to filter the vectors by. - :type prefix: Optional[str] - :param include_metadata: Whether to include metadata in the response. - :type include_metadata: bool - :return: A tuple containing a list of vector IDs and a list of metadata dictionaries. - :rtype: tuple[list[str], list[dict]] - """ - if self.index is None: - raise ValueError("Index is None, could not retrieve vector IDs.") - if self.host == "": - raise ValueError("self.host is not initialized.") - - all_vector_ids = [] - next_page_token = None - - if prefix: - prefix_str = f"?prefix={prefix}" - else: - prefix_str = "" - if self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" - - list_url = f"{self.host}/vectors/list{prefix_str}" - params: dict = {} - if self.namespace: - params["namespace"] = self.namespace - metadata = [] - - async with aiohttp.ClientSession() as session: - while True: - if next_page_token: - params["paginationToken"] = next_page_token - - async with session.get( - list_url, - params=params, - headers=self.headers, - ) as response: - if response.status != 200: - error_text = await response.text() - logger.error(f"Error fetching vectors: {error_text}") - break - - response_data = await response.json(content_type=None) - - vector_ids = [vec["id"] for vec in response_data.get("vectors", [])] - if not vector_ids: - break - all_vector_ids.extend(vector_ids) - - if include_metadata: - metadata_tasks = [ - self._async_fetch_metadata(id) for id in vector_ids - ] - metadata_results = await asyncio.gather(*metadata_tasks) - metadata.extend(metadata_results) - - next_page_token = response_data.get("pagination", {}).get("next") - if not next_page_token: - break - - return all_vector_ids, metadata - - async def _async_fetch_metadata( - self, - vector_id: str, - namespace: str | None = None, - ) -> dict: - """Fetch metadata for a single vector ID asynchronously using the - ClientSession. - - :param vector_id: The ID of the vector to fetch metadata for. - :type vector_id: str - :param namespace: The namespace to fetch metadata for. - :type namespace: str | None - :return: A dictionary containing the metadata for the vector. - :rtype: dict - """ - if self.host == "": - raise ValueError("self.host is not initialized.") - if self.host.startswith("localhost") and self.base_url: - self.host = f"http://{self.base_url.split(':')[-2].strip('/')}:{self.host.split(':')[-1]}" - url = f"{self.host}/vectors/fetch" - - params = { - "ids": [vector_id], - } - - if namespace: - params["namespace"] = [namespace] - elif self.namespace: - params["namespace"] = [self.namespace] - - async with aiohttp.ClientSession() as session: - async with session.get( - url, params=params, headers=self.headers - ) as response: - if response.status != 200: - error_text = await response.text() - logger.error(f"Error fetching metadata: {error_text}") - return {} - - try: - response_data = await response.json(content_type=None) - except Exception as e: - logger.warning(f"No metadata found for vector {vector_id}: {e}") - return {} - - return ( - response_data.get("vectors", {}) - .get(vector_id, {}) - .get("metadata", {}) - ) - - def __len__(self): - if self.index is None: - raise ValueError("Index is None, could not get length.") - namespace_stats = self.index.describe_index_stats()["namespaces"].get( - self.namespace - ) - if namespace_stats: - return namespace_stats["vector_count"] - else: - return 0 diff --git a/tests/unit/test_router.py b/tests/unit/test_router.py index 95cd1c3c..f5bad1d5 100644 --- a/tests/unit/test_router.py +++ b/tests/unit/test_router.py @@ -9,7 +9,7 @@ from typing import Optional from semantic_router.encoders import DenseEncoder, CohereEncoder, OpenAIEncoder from semantic_router.index.local import LocalIndex -from semantic_router.index.pinecone_local import PineconeLocalIndex +from semantic_router.index.pinecone import PineconeIndex from semantic_router.index.qdrant import QdrantIndex from semantic_router.routers import RouterConfig, SemanticRouter, HybridRouter from semantic_router.llms import BaseLLM, OpenAILLM @@ -22,9 +22,9 @@ RETRY_COUNT = 10 -# retry decorator for PineconeLocalIndex cases (which need delay) +# retry decorator for PineconeIndex cases (which need delay) def retry(max_retries: int = 5, delay: int = 8): - """Retry decorator, currently used for PineconeLocalIndex which often needs some time + """Retry decorator, currently used for PineconeIndex which often needs some time to be populated and have all correct data. Once full Pinecone mock is built we should remove this decorator. @@ -79,7 +79,7 @@ def init_index( """We use this function to initialize indexes with different names to avoid issues during testing. """ - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: if index_name: if not dimensions and "OpenAIEncoder" in index_name: @@ -271,7 +271,7 @@ def get_test_indexes(): if importlib.util.find_spec("qdrant_client") is not None: indexes.append(QdrantIndex) if importlib.util.find_spec("pinecone") is not None: - indexes.append(PineconeLocalIndex) + indexes.append(PineconeIndex) return indexes @@ -624,7 +624,7 @@ def test_init_and_add_single_utterance( index=index, auto_sync="local", ) - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: time.sleep(PINECONE_SLEEP) # allow for index to be updated route_layer.add(routes=route_single_utterance) score_threshold = route_layer.score_threshold @@ -776,7 +776,7 @@ def check_index_populated(): check_index_populated() # clear index if pinecone - # if index_cls is PineconeLocalIndex: + # if index_cls is PineconeIndex: # @retry(max_retries=RETRY_COUNT, delay=PINECONE_SLEEP) # def clear_index(): # route_layer.index.index.delete(delete_all=True) @@ -834,7 +834,7 @@ def check_query_result(): os.environ.get("PINECONE_API_KEY") is None, reason="Pinecone API key required" ) def test_namespace_pinecone_index(self, routes, index_cls, encoder_cls, router_cls): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: encoder = encoder_cls() encoder.score_threshold = 0.2 index = init_index( @@ -1260,8 +1260,8 @@ def check_is_ready(): route_layer.evaluate(X=list(X), y=list(y), batch_size=int(len(X) / 5)) def test_fit(self, routes, test_data, index_cls, encoder_cls, router_cls): - # TODO: this is super slow for PineconeLocalIndex, need to fix - if index_cls is PineconeLocalIndex: + # TODO: this is super slow for PineconeIndex, need to fix + if index_cls is PineconeIndex: return encoder = encoder_cls() index = init_index(index_cls, index_name=encoder.__class__.__name__) diff --git a/tests/unit/test_sync.py b/tests/unit/test_sync.py index 7c08f41c..0912a1d6 100644 --- a/tests/unit/test_sync.py +++ b/tests/unit/test_sync.py @@ -8,7 +8,7 @@ from typing import Optional from semantic_router.encoders import DenseEncoder, CohereEncoder, OpenAIEncoder from semantic_router.index import ( - PineconeLocalIndex, + PineconeIndex, HybridLocalIndex, LocalIndex, QdrantIndex, @@ -25,9 +25,9 @@ RETRY_COUNT = 5 -# retry decorator for PineconeLocalIndex cases (which need delay) +# retry decorator for PineconeIndex cases (which need delay) def retry(max_retries: int = 5, delay: int = 8): - """Retry decorator, currently used for PineconeLocalIndex which often needs some time + """Retry decorator, currently used for PineconeIndex which often needs some time to be populated and have all correct data. Once full Pinecone mock is built we should remove this decorator. @@ -55,9 +55,9 @@ def wrapper(*args, **kwargs): return decorator -# retry decorator for PineconeLocalIndex cases (which need delay) +# retry decorator for PineconeIndex cases (which need delay) def async_retry(max_retries: int = 5, delay: int = 8): - """Retry decorator, currently used for PineconeLocalIndex which often needs some time + """Retry decorator, currently used for PineconeIndex which often needs some time to be populated and have all correct data. Once full Pinecone mock is built we should remove this decorator. @@ -113,7 +113,7 @@ def init_index( """We use this function to initialize indexes with different names to avoid issues during testing. """ - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: if index_name: if not dimensions and "OpenAIEncoder" in index_name: @@ -182,7 +182,7 @@ def layer_yaml(): # not all indexes support metadata, so we map the feature here INCLUDE_METADATA_MAP = { - PineconeLocalIndex: True, + PineconeIndex: True, HybridLocalIndex: False, LocalIndex: False, QdrantIndex: False, @@ -312,7 +312,7 @@ def get_test_indexes(): # if importlib.util.find_spec("qdrant_client") is not None: # indexes.append(QdrantIndex) if importlib.util.find_spec("pinecone") is not None: - indexes.append(PineconeLocalIndex) + indexes.append(PineconeIndex) return indexes @@ -409,7 +409,7 @@ def check_utterance_diff(): def test_auto_sync_local( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST LOCAL pinecone_index = init_index(index_cls, index_name=router_cls.__name__) _ = router_cls( @@ -442,7 +442,7 @@ def check_sync(): def test_auto_sync_remote( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST REMOTE pinecone_index = init_index(index_cls, index_name=router_cls.__name__) _ = router_cls( @@ -475,7 +475,7 @@ def check_sync(): def test_auto_sync_merge_force_local( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST MERGE FORCE LOCAL pinecone_index = init_index(index_cls, index_name=router_cls.__name__) route_layer = router_cls( @@ -522,7 +522,7 @@ def check_sync(): def test_auto_sync_merge_force_remote( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST MERGE FORCE LOCAL pinecone_index = init_index(index_cls, index_name=router_cls.__name__) route_layer = router_cls( @@ -614,7 +614,7 @@ def check_sync(): def test_auto_sync_merge( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST MERGE pinecone_index = init_index(index_cls, index_name=router_cls.__name__) route_layer = router_cls( @@ -680,7 +680,7 @@ def test_sync_lock_prevents_concurrent_sync( ) # Acquire sync lock route_layer.index.lock(value=True) - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: time.sleep(PINECONE_SLEEP) # Attempt to sync while lock is held should raise exception @@ -689,12 +689,12 @@ def test_sync_lock_prevents_concurrent_sync( # Release lock route_layer.index.lock(value=False) - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: time.sleep(PINECONE_SLEEP) # Should succeed after lock is released route_layer.sync("local") - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: time.sleep(PINECONE_SLEEP) assert route_layer.is_synced() @@ -712,17 +712,17 @@ def test_sync_lock_auto_releases( index=index, auto_sync="local", ) - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: time.sleep(PINECONE_SLEEP) # Lock should be released, allowing another sync route_layer.sync("local") # Should not raise exception - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: time.sleep(PINECONE_SLEEP) assert route_layer.is_synced() # clear index if pinecone - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: route_layer.index.client.delete_index(route_layer.index.index_name) @@ -760,7 +760,7 @@ async def test_second_initialization_sync( route_layer = router_cls( encoder=openai_encoder, routes=routes, index=index, auto_sync="local" ) - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: await asyncio.sleep(PINECONE_SLEEP * 2) # allow for index to be populated assert await route_layer.async_is_synced() @@ -778,7 +778,7 @@ async def test_second_initialization_not_synced( encoder=openai_encoder, routes=routes, index=index, auto_sync="local" ) route_layer = router_cls(encoder=openai_encoder, routes=routes_2, index=index) - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: await asyncio.sleep(PINECONE_SLEEP) # allow for index to be populated assert await route_layer.async_is_synced() is False @@ -818,7 +818,7 @@ async def check_diff(): async def test_auto_sync_local( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST LOCAL pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -854,7 +854,7 @@ async def check_sync(): async def test_auto_sync_remote( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST REMOTE pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -891,7 +891,7 @@ async def check_sync(): async def test_auto_sync_merge_force_local( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST MERGE FORCE LOCAL pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -940,7 +940,7 @@ async def check_sync(): async def test_auto_sync_merge_force_remote( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST MERGE FORCE LOCAL pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -1041,7 +1041,7 @@ async def check_sync(): async def test_auto_sync_merge( self, openai_encoder, routes, routes_2, index_cls, router_cls ): - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: # TEST MERGE pinecone_index = init_index( index_cls, init_async_index=True, index_name=router_cls.__name__ @@ -1118,7 +1118,7 @@ async def test_sync_lock_prevents_concurrent_sync( # Acquire sync lock await route_layer.index.alock(value=True) - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: await asyncio.sleep(PINECONE_SLEEP) # Attempt to sync while lock is held should raise exception @@ -1127,12 +1127,12 @@ async def test_sync_lock_prevents_concurrent_sync( # Release lock await route_layer.index.alock(value=False) - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: await asyncio.sleep(PINECONE_SLEEP) # Should succeed after lock is released await route_layer.async_sync("local") - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: await asyncio.sleep(PINECONE_SLEEP) assert await route_layer.async_is_synced() @@ -1159,19 +1159,19 @@ async def test_sync_lock_auto_releases( index=index, auto_sync=None, ) - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: await asyncio.sleep(PINECONE_SLEEP) # Initial sync should acquire and release lock await route_layer.async_sync("local") - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: await asyncio.sleep(PINECONE_SLEEP) # Lock should be released, allowing another sync await route_layer.async_sync("local") # Should not raise exception - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: await asyncio.sleep(PINECONE_SLEEP) assert await route_layer.async_is_synced() # clear index if pinecone - if index_cls is PineconeLocalIndex: + if index_cls is PineconeIndex: route_layer.index.client.delete_index(route_layer.index.index_name) From 2010c464099fe3feb8eec13545978059a02686a9 Mon Sep 17 00:00:00 2001 From: theanupllm Date: Tue, 4 Feb 2025 21:53:51 +0530 Subject: [PATCH 07/13] chore: Remove redundant imports from schema and pinecone modules --- semantic_router/index/pinecone.py | 1 - semantic_router/schema.py | 1 - 2 files changed, 2 deletions(-) diff --git a/semantic_router/index/pinecone.py b/semantic_router/index/pinecone.py index e00d65d0..49538c13 100644 --- a/semantic_router/index/pinecone.py +++ b/semantic_router/index/pinecone.py @@ -3,7 +3,6 @@ import json import os import time -import json import requests from json.decoder import JSONDecodeError from typing import Any, Dict, List, Optional, Tuple, Union diff --git a/semantic_router/schema.py b/semantic_router/schema.py index 90690bd1..9b973cb6 100644 --- a/semantic_router/schema.py +++ b/semantic_router/schema.py @@ -5,7 +5,6 @@ from typing import Any, Dict, List, Optional, Tuple, Union import numpy as np -from aurelio_sdk.schema import BM25Embedding from pydantic import BaseModel, Field from semantic_router.utils.logger import logger From 98a5ff413b590d51df88c6b66e2a9dffee8387d9 Mon Sep 17 00:00:00 2001 From: theanupllm Date: Tue, 4 Feb 2025 22:02:03 +0530 Subject: [PATCH 08/13] chore: Remove PineconeLocalIndex from index module --- semantic_router/index/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/semantic_router/index/__init__.py b/semantic_router/index/__init__.py index 9ffd35c6..14b60da3 100644 --- a/semantic_router/index/__init__.py +++ b/semantic_router/index/__init__.py @@ -2,7 +2,6 @@ from semantic_router.index.hybrid_local import HybridLocalIndex from semantic_router.index.local import LocalIndex from semantic_router.index.pinecone import PineconeIndex -from semantic_router.index.pinecone_local import PineconeLocalIndex from semantic_router.index.postgres import PostgresIndex from semantic_router.index.qdrant import QdrantIndex @@ -12,6 +11,5 @@ "LocalIndex", "QdrantIndex", "PineconeIndex", - "PineconeLocalIndex", "PostgresIndex", ] From 200e5439cbc845d0eb5b6ba63dc5e839bcd18818 Mon Sep 17 00:00:00 2001 From: theanupllm Date: Tue, 4 Feb 2025 22:16:55 +0530 Subject: [PATCH 09/13] chore: Update GitHub Actions workflow for Python testing - Uncomment and enable multiple Python versions (3.10, 3.11, 3.12, 3.13) - Enable Poetry caching in GitHub Actions - Remove local path addition comment - Simplify workflow configuration --- .github/workflows/test.yml | 27 ++++++++++++++------------- semantic_router/routers/base.py | 5 +---- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 99e2dcd9..1d01de9c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,19 +22,19 @@ jobs: strategy: matrix: python-version: - # - "3.10" - # - "3.11" - # - "3.12" + - "3.10" + - "3.11" + - "3.12" - "3.13" steps: - uses: actions/checkout@v4 - # - name: Cache Poetry - # uses: actions/cache@v4 - # with: - # path: ~/.poetry - # key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }} - # restore-keys: | - # ${{ runner.os }}-poetry- + - name: Cache Poetry + uses: actions/cache@v4 + with: + path: ~/.poetry + key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }} + restore-keys: | + ${{ runner.os }}-poetry- - name: Wait for Pinecone service to start run: | @@ -48,10 +48,11 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - # cache: poetry + cache: poetry - - name: Add Poetry to PATH - run: echo "PATH=$HOME/.local/bin:$PATH" >> $GITHUB_ENV + # only needed for local testing + # - name: Add Poetry to PATH + # run: echo "PATH=$HOME/.local/bin:$PATH" >> $GITHUB_ENV - name: Install dependencies run: | diff --git a/semantic_router/routers/base.py b/semantic_router/routers/base.py index 18456af0..fd737955 100644 --- a/semantic_router/routers/base.py +++ b/semantic_router/routers/base.py @@ -20,7 +20,6 @@ from semantic_router.index.base import BaseIndex from semantic_router.index.local import LocalIndex from semantic_router.index.pinecone import PineconeIndex -from semantic_router.index.pinecone_local import PineconeLocalIndex from semantic_router.index.qdrant import QdrantIndex from semantic_router.llms import BaseLLM, OpenAILLM from semantic_router.route import Route @@ -397,9 +396,7 @@ def _init_index_state(self): dims = len(self.encoder(["test"])[0]) self.index.dimensions = dims # now init index - if isinstance(self.index, PineconeIndex) or isinstance( - self.index, PineconeLocalIndex - ): + if isinstance(self.index, PineconeIndex): self.index.index = self.index._init_index(force_create=True) # run auto sync if active From b9e3bfc827061ecb2c620031c94d8a6bbaf5b31a Mon Sep 17 00:00:00 2001 From: James Briggs <35938317+jamescalam@users.noreply.github.com> Date: Wed, 5 Feb 2025 08:40:42 +0400 Subject: [PATCH 10/13] fix: delete root pinecone-local.ipynb --- pinecone-local.ipynb | 773 ------------------------------------------- 1 file changed, 773 deletions(-) delete mode 100644 pinecone-local.ipynb diff --git a/pinecone-local.ipynb b/pinecone-local.ipynb deleted file mode 100644 index 5cfc5409..00000000 --- a/pinecone-local.ipynb +++ /dev/null @@ -1,773 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Using PineconeLocalIndex for Routes\n", - "\n", - "Pinecone Local is an in-memory Pinecone Database emulator available as a Docker image.\n", - "\n", - "It's useful for running tests using the Pinecone local server. Your data will not leave your system, which is also helpful if you want to do testing locally before committing to a Pinecone account.\n", - "\n", - "## Limitations\n", - "Pinecone Local has the following limitations:\n", - "\n", - "- Pinecone Local is available only as a Docker image.\n", - "- Pinecone Local is an in-memory emulator and is not suitable for production. Records loaded into Pinecone Local do not persist after it is stopped.\n", - "- Pinecone Local does not authenticate client requests. API keys are ignored.\n", - "- Max number of records per index: 100,000.\n", - "\n", - "## Getting Started\n", - "Make sure [Docker](https://docs.docker.com/get-docker/) is installed and running on your local machine.\n", - "\n", - "### Download the latest pinecone-local Docker image:\n", - "\n", - "\n", - "Download the latest pinecone-local Docker image:\n", - "\n", - "```bash\n", - "docker pull ghcr.io/pinecone-io/pinecone-local:latest\n", - "```\n", - "\n", - "### Start Pinecone Local:\n", - "\n", - "```bash\n", - "docker run -d \\\n", - "--name pinecone-local \\\n", - "-e PORT=5080 \\\n", - "-e PINECONE_HOST=localhost \\\n", - "-p 5080-6000:5080-6000 \\\n", - "--platform linux/amd64 \\\n", - "ghcr.io/pinecone-io/pinecone-local:latest\n", - "```\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "!pip install -qU \"semantic-router[pinecone]==0.0.22\"" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "c:\\Users\\awesome\\anaconda3\\envs\\py12\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - } - ], - "source": [ - "from semantic_router import Route\n", - "\n", - "# we could use this as a guide for our chatbot to avoid political conversations\n", - "politics = Route(\n", - " name=\"politics\",\n", - " utterances=[\n", - " \"isn't politics the best thing ever\",\n", - " \"why don't you tell me about your political opinions\",\n", - " \"don't you just love the president\" \"don't you just hate the president\",\n", - " \"they're going to destroy this country!\",\n", - " \"they will save the country!\",\n", - " ],\n", - ")\n", - "\n", - "# this could be used as an indicator to our chatbot to switch to a more\n", - "# conversational prompt\n", - "chitchat = Route(\n", - " name=\"chitchat\",\n", - " utterances=[\n", - " \"how's the weather today?\",\n", - " \"how are things going?\",\n", - " \"lovely weather today\",\n", - " \"the weather is horrendous\",\n", - " \"let's go to the chippy\",\n", - " ],\n", - ")\n", - "\n", - "# we place both of our decisions together into single list\n", - "routes = [politics, chitchat]" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[Route(name='politics', utterances=[\"isn't politics the best thing ever\", \"why don't you tell me about your political opinions\", \"don't you just love the presidentdon't you just hate the president\", \"they're going to destroy this country!\", 'they will save the country!'], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={}),\n", - " Route(name='chitchat', utterances=[\"how's the weather today?\", 'how are things going?', 'lovely weather today', 'the weather is horrendous', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={})]" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "routes" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "from getpass import getpass\n", - "from semantic_router.encoders import OpenAIEncoder\n", - "\n", - "# get at platform.openai.com\n", - "os.environ[\"OPENAI_API_KEY\"] = os.environ.get(\"OPENAI_API_KEY\") or getpass(\n", - " \"Enter OpenAI API key: \"\n", - ")\n", - "encoder = OpenAIEncoder(\n", - " name=\"text-embedding-3-large\", score_threshold=0.5, dimensions=1536\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For Pinecone Local, you can pass the API key as `pclocal`." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:40:01 - semantic_router.utils.logger - WARNING - pinecone.py:169 - __init__() - Default region changed from us-west-2 to us-east-1 in v0.1.0.dev6\n", - "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - discover_namespace_packages.py:12 - discover_subpackages() - Discovering subpackages in _NamespacePath(['c:\\\\Users\\\\awesome\\\\anaconda3\\\\envs\\\\py12\\\\Lib\\\\site-packages\\\\pinecone_plugins'])\n", - "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - discover_plugins.py:9 - discover_plugins() - Looking for plugins in pinecone_plugins.inference\n", - "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - installation.py:10 - install_plugins() - Installing plugin inference into Pinecone\n", - "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:233 - _init_index() - index_host exists-pinecone:localhost:5081\n", - "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:234 - _init_index() - base_url exists-pinecone:http://localhost:5080\n", - "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:251 - _init_index() - index_host exists:http://localhost:5081\n", - "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:252 - _init_index() - index exists:\n" - ] - } - ], - "source": [ - "import os\n", - "from semantic_router.index.pinecone import PineconeIndex\n", - "\n", - "os.environ[\"PINECONE_API_KEY\"] = os.environ.get(\"PINECONE_API_KEY\") or getpass(\n", - " \"Enter Pinecone API key: \"\n", - ")\n", - "\n", - "# Pass the pinecone local hosted url as base url\n", - "# os.environ[\"PINECONE_API_BASE_URL\"] = \"https://api.pinecone.io\"\n", - "os.environ[\"PINECONE_API_BASE_URL\"] = \"http://localhost:5080\"\n", - "\n", - "index = PineconeIndex(\n", - " index_name=\"route-test\", dimensions=1536, base_url=\"http://localhost:5080\"\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:233 - _init_index() - index_host exists-pinecone:localhost:5081\n", - "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:234 - _init_index() - base_url exists-pinecone:http://localhost:5080\n", - "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:251 - _init_index() - index_host exists:http://localhost:5081\n", - "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:252 - _init_index() - index exists:\n" - ] - } - ], - "source": [ - "from semantic_router.routers import SemanticRouter\n", - "\n", - "router = SemanticRouter(\n", - " encoder=encoder,\n", - " routes=routes,\n", - " index=index,\n", - " auto_sync=\"local\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can check our route layer and index information." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'http://localhost:5081'" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "index.index_host" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'http://localhost:5081'" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index.index_host" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'indexes': [{'deletion_protection': 'disabled',\n", - " 'dimension': 1536,\n", - " 'host': 'localhost:5081',\n", - " 'metric': 'dotproduct',\n", - " 'name': 'route-test',\n", - " 'spec': {'serverless': {'cloud': 'aws', 'region': 'us-east-1'}},\n", - " 'status': {'ready': True, 'state': 'Ready'}}]}" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index.client.list_indexes()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index.is_ready()" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.is_synced()" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[' chitchat: how are things going?',\n", - " \" chitchat: how's the weather today?\",\n", - " \" chitchat: let's go to the chippy\",\n", - " ' chitchat: lovely weather today',\n", - " ' chitchat: the weather is horrendous',\n", - " \" politics: don't you just love the presidentdon't you just hate the president\",\n", - " \" politics: isn't politics the best thing ever\",\n", - " ' politics: they will save the country!',\n", - " \" politics: they're going to destroy this country!\",\n", - " \" politics: why don't you tell me about your political opinions\"]" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.get_utterance_diff()" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:08 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:08 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - }, - { - "data": { - "text/plain": [ - "RouteChoice(name='politics', function_call=None, similarity_score=None)" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router(\"don't you love politics?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['politics', 'chitchat']" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.list_route_names()" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:17 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:17 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - }, - { - "data": { - "text/plain": [ - "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router(\"how are things going?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(router.index)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also view all of the records for a given route:" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['politics#64069085d9d6e98e5a80915f69fabe82bac6c742f801bc305c5001dce88f0d19',\n", - " 'politics#af8b76111f260cf44fb34f04fcf82927dcbe08e8f47c30f4d571379c1512fac8',\n", - " 'politics#d1bb40236c3d95b9c695bfa86b314b6da4eb87e136699563fccae47fccea23e2',\n", - " 'politics#ed0f3dd7bd5dea12e55b1953bcd2c562a5ab19f501f6d5ff8c8927652c3904b8',\n", - " 'politics#fc6d15f9e6075e6de82b3fbef6722b64353e4eadc8d663b7312a4ed60c43e6f6']" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index._get_route_ids(route_name=\"politics\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And query:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:25 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:25 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - }, - { - "data": { - "text/plain": [ - "'politics'" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router(\"don't you love politics?\").name" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:19:14 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:19:14 - semantic_router.utils.logger - ERROR - pinecone.py:572 - query() - retrying query with vector as str\n" - ] - }, - { - "data": { - "text/plain": [ - "'chitchat'" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router(\"how's the weather today?\").name" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:32 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:32 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - } - ], - "source": [ - "router(\"I'm interested in learning about llama 2\").name" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can delete or update routes." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(router.index)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Deleting a Route from the Semantic Router\n", - "In this section, we demonstrate how to delete a specific route from the `SemanticRouter` instance. This is useful when you want to remove a route that is no longer needed or to update the routing logic dynamically.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:39 - semantic_router.utils.logger - WARNING - pinecone.py:611 - _read_config() - Configuration for sr_lock parameter not found in index.\n", - "2025-02-03 15:41:39 - semantic_router.utils.logger - INFO - pinecone.py:477 - delete() - index is not None, deleting...\n", - "2025-02-03 15:41:39 - semantic_router.utils.logger - INFO - pinecone.py:491 - delete() - Deleted 5 vectors from index route-test.\n" - ] - }, - { - "data": { - "text/plain": [ - "5" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import time\n", - "\n", - "router.delete(route_name=\"politics\")\n", - "time.sleep(1)\n", - "len(router.index)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:49 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:49 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - } - ], - "source": [ - "router(\"don't you love politics??\").name" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[Route(name='chitchat', utterances=['how are things going?', \"how's the weather today?\", 'the weather is horrendous', 'lovely weather today', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={})]" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index.get_routes()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Asynchronous Route Query with Semantic Router\n", - "\n", - "In this section, we explore how to perform an asynchronous query using the `SemanticRouter`. This approach is beneficial when you want to handle multiple queries concurrently without blocking the execution of your program." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:42:01 - httpx - INFO - _client.py:1729 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n" - ] - }, - { - "data": { - "text/plain": [ - "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "await router.acall(\"how are things going?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'indexes': [{'name': 'route-test',\n", - " 'dimension': 1536,\n", - " 'metric': 'dotproduct',\n", - " 'host': 'localhost:5081',\n", - " 'deletion_protection': 'disabled',\n", - " 'spec': {'serverless': {'cloud': 'aws', 'region': 'us-east-1'}},\n", - " 'status': {'ready': True, 'state': 'Ready'}}]}" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "await router.index._async_list_indexes()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Stop and remove Pinecone Local\n", - "\n", - "To stop and remove the resources for Pinecone Local, run the following command:\n", - "\n", - "```bash\n", - "docker compose down\n", - "docker stop pinecone-local\n", - "docker rm pinecone-local\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py12", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 4bb2b05b0b197435bee66668cb70a0905c542993 Mon Sep 17 00:00:00 2001 From: theanupllm Date: Wed, 5 Feb 2025 10:39:51 +0530 Subject: [PATCH 11/13] feat: Enhance Pinecone Index configuration for local and cloud environments - Update PineconeIndex to handle both local and cloud Pinecone index configurations - Add base_url default to Pinecone cloud API - Improve logging for base URL selection - Update documentation notebook to reflect new configuration approach --- CONTRIBUTING.md | 2 +- docs/indexes/pinecone-local.ipynb | 172 +++---- pinecone-local.ipynb | 773 ------------------------------ semantic_router/index/pinecone.py | 6 +- 4 files changed, 92 insertions(+), 861 deletions(-) delete mode 100644 pinecone-local.ipynb diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4de28c82..d7208e9b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ Please follow these guidelines when making a contribution: - Navigating to /semantic-router. - Running `make lint` to fix linting issues. - Running `black .` to fix `black` linting issues. - - Running `ruff . --fix` to fix `ruff` linting issues (where possible, others may need manual changes). + - Running `ruff check . --fix` to fix `ruff` linting issues (where possible, others may need manual changes). - Running `mypy .` and then fixing any of the issues that are raised. - Confirming the linters pass using `make lint` again. - Ensure that, for any new code, new [PyTests are written](https://github.com/aurelio-labs/semantic-router/tree/main/tests/unit). If any code is removed, then ensure that corresponding PyTests are also removed. Finally, ensure that all remaining PyTests pass using `pytest ./tests` (to avoid integration tests you can run `pytest ./tests/unit`. diff --git a/docs/indexes/pinecone-local.ipynb b/docs/indexes/pinecone-local.ipynb index f08f6e2f..5cfc5409 100644 --- a/docs/indexes/pinecone-local.ipynb +++ b/docs/indexes/pinecone-local.ipynb @@ -101,17 +101,17 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[Route(name='politics', utterances=[\"isn't politics the best thing ever\", \"why don't you tell me about your political opinions\", \"don't you just love the presidentdon't you just hate the president\", \"they're going to destroy this country!\", 'they will save the country!'], description=None, function_schemas=None, llm=None, score_threshold=0.5, metadata={}),\n", - " Route(name='chitchat', utterances=[\"how's the weather today?\", 'how are things going?', 'lovely weather today', 'the weather is horrendous', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=0.5, metadata={})]" + "[Route(name='politics', utterances=[\"isn't politics the best thing ever\", \"why don't you tell me about your political opinions\", \"don't you just love the presidentdon't you just hate the president\", \"they're going to destroy this country!\", 'they will save the country!'], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={}),\n", + " Route(name='chitchat', utterances=[\"how's the weather today?\", 'how are things going?', 'lovely weather today', 'the weather is horrendous', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={})]" ] }, - "execution_count": 9, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -122,7 +122,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -131,7 +131,9 @@ "from semantic_router.encoders import OpenAIEncoder\n", "\n", "# get at platform.openai.com\n", - "os.environ.get(\"OPENAI_API_KEY\") or getpass(\"Enter OpenAI API key: \")\n", + "os.environ[\"OPENAI_API_KEY\"] = os.environ.get(\"OPENAI_API_KEY\") or getpass(\n", + " \"Enter OpenAI API key: \"\n", + ")\n", "encoder = OpenAIEncoder(\n", " name=\"text-embedding-3-large\", score_threshold=0.5, dimensions=1536\n", ")" @@ -146,43 +148,54 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-31 00:33:41 - semantic_router.utils.logger - WARNING - pinecone_local.py:146 - __init__() - Pinecone API key: pclocal\n", - "2025-01-31 00:33:41 - semantic_router.utils.logger - WARNING - pinecone_local.py:147 - __init__() - Pinecone API key os env: pclocal\n", - "2025-01-31 00:33:41 - semantic_router.utils.logger - WARNING - pinecone_local.py:169 - __init__() - Default region changed from us-west-2 to us-east-1 in v0.1.0.dev6\n" + "2025-02-03 15:40:01 - semantic_router.utils.logger - WARNING - pinecone.py:169 - __init__() - Default region changed from us-west-2 to us-east-1 in v0.1.0.dev6\n", + "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - discover_namespace_packages.py:12 - discover_subpackages() - Discovering subpackages in _NamespacePath(['c:\\\\Users\\\\awesome\\\\anaconda3\\\\envs\\\\py12\\\\Lib\\\\site-packages\\\\pinecone_plugins'])\n", + "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - discover_plugins.py:9 - discover_plugins() - Looking for plugins in pinecone_plugins.inference\n", + "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - installation.py:10 - install_plugins() - Installing plugin inference into Pinecone\n", + "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:233 - _init_index() - index_host exists-pinecone:localhost:5081\n", + "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:234 - _init_index() - base_url exists-pinecone:http://localhost:5080\n", + "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:251 - _init_index() - index_host exists:http://localhost:5081\n", + "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:252 - _init_index() - index exists:\n" ] } ], "source": [ "import os\n", - "from semantic_router.index.pinecone_local import PineconeLocalIndex\n", + "from semantic_router.index.pinecone import PineconeIndex\n", "\n", "os.environ[\"PINECONE_API_KEY\"] = os.environ.get(\"PINECONE_API_KEY\") or getpass(\n", " \"Enter Pinecone API key: \"\n", ")\n", + "\n", + "# Pass the pinecone local hosted url as base url\n", + "# os.environ[\"PINECONE_API_BASE_URL\"] = \"https://api.pinecone.io\"\n", "os.environ[\"PINECONE_API_BASE_URL\"] = \"http://localhost:5080\"\n", "\n", - "index = PineconeLocalIndex(index_name=\"route-test\", dimensions=1536)" + "index = PineconeIndex(\n", + " index_name=\"route-test\", dimensions=1536, base_url=\"http://localhost:5080\"\n", + ")" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-31 00:33:42 - semantic_router.utils.logger - ERROR - pinecone_local.py:271 - _init_index() - index_host exists:http://localhost:5083\n", - "2025-01-31 00:33:42 - semantic_router.utils.logger - ERROR - pinecone_local.py:272 - _init_index() - index exists:\n", - "2025-01-31 00:33:44 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n" + "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:233 - _init_index() - index_host exists-pinecone:localhost:5081\n", + "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:234 - _init_index() - base_url exists-pinecone:http://localhost:5080\n", + "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:251 - _init_index() - index_host exists:http://localhost:5081\n", + "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:252 - _init_index() - index exists:\n" ] } ], @@ -206,7 +219,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -215,7 +228,7 @@ "'http://localhost:5081'" ] }, - "execution_count": 6, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -226,7 +239,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -235,7 +248,7 @@ "'http://localhost:5081'" ] }, - "execution_count": 7, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -246,13 +259,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'indexes': [{'dimension': 1536,\n", + "{'indexes': [{'deletion_protection': 'disabled',\n", + " 'dimension': 1536,\n", " 'host': 'localhost:5081',\n", " 'metric': 'dotproduct',\n", " 'name': 'route-test',\n", @@ -260,7 +274,7 @@ " 'status': {'ready': True, 'state': 'Ready'}}]}" ] }, - "execution_count": 8, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -271,7 +285,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -280,7 +294,7 @@ "True" ] }, - "execution_count": 24, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -291,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -300,7 +314,7 @@ "True" ] }, - "execution_count": 25, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -311,7 +325,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -329,7 +343,7 @@ " \" politics: why don't you tell me about your political opinions\"]" ] }, - "execution_count": 26, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -340,16 +354,15 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-29 23:25:18 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-01-29 23:25:18 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", - "2025-01-29 23:25:18 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['politics', 'politics', 'politics', 'chitchat', 'politics']\n" + "2025-02-03 15:41:08 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:08 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" ] }, { @@ -358,7 +371,7 @@ "RouteChoice(name='politics', function_call=None, similarity_score=None)" ] }, - "execution_count": 27, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -369,7 +382,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -378,7 +391,7 @@ "['politics', 'chitchat']" ] }, - "execution_count": 28, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -389,16 +402,15 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-29 23:25:27 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-01-29 23:25:27 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", - "2025-01-29 23:25:27 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['chitchat', 'chitchat', 'chitchat', 'chitchat', 'chitchat']\n" + "2025-02-03 15:41:17 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:17 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" ] }, { @@ -407,7 +419,7 @@ "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" ] }, - "execution_count": 29, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -418,7 +430,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -427,7 +439,7 @@ "10" ] }, - "execution_count": 30, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -445,7 +457,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -458,7 +470,7 @@ " 'politics#fc6d15f9e6075e6de82b3fbef6722b64353e4eadc8d663b7312a4ed60c43e6f6']" ] }, - "execution_count": 31, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -476,16 +488,15 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-29 23:25:42 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-01-29 23:25:42 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", - "2025-01-29 23:25:42 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['politics', 'politics', 'politics', 'chitchat', 'politics']\n" + "2025-02-03 15:41:25 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:25 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" ] }, { @@ -494,7 +505,7 @@ "'politics'" ] }, - "execution_count": 32, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -505,16 +516,15 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-29 23:25:43 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-01-29 23:25:43 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", - "2025-01-29 23:25:43 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['chitchat', 'chitchat', 'chitchat', 'chitchat', 'chitchat']\n" + "2025-02-03 15:19:14 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:19:14 - semantic_router.utils.logger - ERROR - pinecone.py:572 - query() - retrying query with vector as str\n" ] }, { @@ -523,7 +533,7 @@ "'chitchat'" ] }, - "execution_count": 33, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -534,16 +544,15 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-29 23:25:44 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-01-29 23:25:44 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", - "2025-01-29 23:25:44 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['chitchat', 'politics', 'chitchat', 'politics', 'chitchat']\n" + "2025-02-03 15:41:32 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:32 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" ] } ], @@ -560,7 +569,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -569,7 +578,7 @@ "10" ] }, - "execution_count": 35, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -588,22 +597,16 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-29 23:27:01 - semantic_router.utils.logger - WARNING - pinecone_local.py:628 - _read_config() - Configuration for sr_lock parameter not found in index.\n", - "2025-01-29 23:27:01 - semantic_router.utils.logger - INFO - pinecone_local.py:496 - delete() - Deleted 5 vectors from index route-test.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "index is not None, deleting...\n" + "2025-02-03 15:41:39 - semantic_router.utils.logger - WARNING - pinecone.py:611 - _read_config() - Configuration for sr_lock parameter not found in index.\n", + "2025-02-03 15:41:39 - semantic_router.utils.logger - INFO - pinecone.py:477 - delete() - index is not None, deleting...\n", + "2025-02-03 15:41:39 - semantic_router.utils.logger - INFO - pinecone.py:491 - delete() - Deleted 5 vectors from index route-test.\n" ] }, { @@ -612,7 +615,7 @@ "5" ] }, - "execution_count": 36, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -627,16 +630,15 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-29 23:27:31 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-01-29 23:27:31 - semantic_router.utils.logger - ERROR - pinecone_local.py:581 - query() - retrying query with vector as str\n", - "2025-01-29 23:27:31 - semantic_router.utils.logger - INFO - pinecone_local.py:593 - query() - route_names:['chitchat', 'chitchat', 'chitchat', 'chitchat', 'chitchat']\n" + "2025-02-03 15:41:49 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", + "2025-02-03 15:41:49 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" ] } ], @@ -646,7 +648,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -655,7 +657,7 @@ "[Route(name='chitchat', utterances=['how are things going?', \"how's the weather today?\", 'the weather is horrendous', 'lovely weather today', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={})]" ] }, - "execution_count": 39, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -675,15 +677,14 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2025-01-29 23:27:42 - httpx - INFO - _client.py:1729 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-01-29 23:27:42 - semantic_router.utils.logger - ERROR - pinecone_local.py:796 - _async_query() - current host: http://localhost:5081\n" + "2025-02-03 15:42:01 - httpx - INFO - _client.py:1729 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n" ] }, { @@ -692,7 +693,7 @@ "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" ] }, - "execution_count": 41, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -703,7 +704,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -713,11 +714,12 @@ " 'dimension': 1536,\n", " 'metric': 'dotproduct',\n", " 'host': 'localhost:5081',\n", + " 'deletion_protection': 'disabled',\n", " 'spec': {'serverless': {'cloud': 'aws', 'region': 'us-east-1'}},\n", " 'status': {'ready': True, 'state': 'Ready'}}]}" ] }, - "execution_count": 42, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -763,7 +765,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.8" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/pinecone-local.ipynb b/pinecone-local.ipynb deleted file mode 100644 index 5cfc5409..00000000 --- a/pinecone-local.ipynb +++ /dev/null @@ -1,773 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Using PineconeLocalIndex for Routes\n", - "\n", - "Pinecone Local is an in-memory Pinecone Database emulator available as a Docker image.\n", - "\n", - "It's useful for running tests using the Pinecone local server. Your data will not leave your system, which is also helpful if you want to do testing locally before committing to a Pinecone account.\n", - "\n", - "## Limitations\n", - "Pinecone Local has the following limitations:\n", - "\n", - "- Pinecone Local is available only as a Docker image.\n", - "- Pinecone Local is an in-memory emulator and is not suitable for production. Records loaded into Pinecone Local do not persist after it is stopped.\n", - "- Pinecone Local does not authenticate client requests. API keys are ignored.\n", - "- Max number of records per index: 100,000.\n", - "\n", - "## Getting Started\n", - "Make sure [Docker](https://docs.docker.com/get-docker/) is installed and running on your local machine.\n", - "\n", - "### Download the latest pinecone-local Docker image:\n", - "\n", - "\n", - "Download the latest pinecone-local Docker image:\n", - "\n", - "```bash\n", - "docker pull ghcr.io/pinecone-io/pinecone-local:latest\n", - "```\n", - "\n", - "### Start Pinecone Local:\n", - "\n", - "```bash\n", - "docker run -d \\\n", - "--name pinecone-local \\\n", - "-e PORT=5080 \\\n", - "-e PINECONE_HOST=localhost \\\n", - "-p 5080-6000:5080-6000 \\\n", - "--platform linux/amd64 \\\n", - "ghcr.io/pinecone-io/pinecone-local:latest\n", - "```\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "!pip install -qU \"semantic-router[pinecone]==0.0.22\"" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "c:\\Users\\awesome\\anaconda3\\envs\\py12\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - } - ], - "source": [ - "from semantic_router import Route\n", - "\n", - "# we could use this as a guide for our chatbot to avoid political conversations\n", - "politics = Route(\n", - " name=\"politics\",\n", - " utterances=[\n", - " \"isn't politics the best thing ever\",\n", - " \"why don't you tell me about your political opinions\",\n", - " \"don't you just love the president\" \"don't you just hate the president\",\n", - " \"they're going to destroy this country!\",\n", - " \"they will save the country!\",\n", - " ],\n", - ")\n", - "\n", - "# this could be used as an indicator to our chatbot to switch to a more\n", - "# conversational prompt\n", - "chitchat = Route(\n", - " name=\"chitchat\",\n", - " utterances=[\n", - " \"how's the weather today?\",\n", - " \"how are things going?\",\n", - " \"lovely weather today\",\n", - " \"the weather is horrendous\",\n", - " \"let's go to the chippy\",\n", - " ],\n", - ")\n", - "\n", - "# we place both of our decisions together into single list\n", - "routes = [politics, chitchat]" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[Route(name='politics', utterances=[\"isn't politics the best thing ever\", \"why don't you tell me about your political opinions\", \"don't you just love the presidentdon't you just hate the president\", \"they're going to destroy this country!\", 'they will save the country!'], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={}),\n", - " Route(name='chitchat', utterances=[\"how's the weather today?\", 'how are things going?', 'lovely weather today', 'the weather is horrendous', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={})]" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "routes" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "from getpass import getpass\n", - "from semantic_router.encoders import OpenAIEncoder\n", - "\n", - "# get at platform.openai.com\n", - "os.environ[\"OPENAI_API_KEY\"] = os.environ.get(\"OPENAI_API_KEY\") or getpass(\n", - " \"Enter OpenAI API key: \"\n", - ")\n", - "encoder = OpenAIEncoder(\n", - " name=\"text-embedding-3-large\", score_threshold=0.5, dimensions=1536\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For Pinecone Local, you can pass the API key as `pclocal`." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:40:01 - semantic_router.utils.logger - WARNING - pinecone.py:169 - __init__() - Default region changed from us-west-2 to us-east-1 in v0.1.0.dev6\n", - "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - discover_namespace_packages.py:12 - discover_subpackages() - Discovering subpackages in _NamespacePath(['c:\\\\Users\\\\awesome\\\\anaconda3\\\\envs\\\\py12\\\\Lib\\\\site-packages\\\\pinecone_plugins'])\n", - "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - discover_plugins.py:9 - discover_plugins() - Looking for plugins in pinecone_plugins.inference\n", - "2025-02-03 15:40:01 - pinecone_plugin_interface.logging - INFO - installation.py:10 - install_plugins() - Installing plugin inference into Pinecone\n", - "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:233 - _init_index() - index_host exists-pinecone:localhost:5081\n", - "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:234 - _init_index() - base_url exists-pinecone:http://localhost:5080\n", - "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:251 - _init_index() - index_host exists:http://localhost:5081\n", - "2025-02-03 15:40:01 - semantic_router.utils.logger - ERROR - pinecone.py:252 - _init_index() - index exists:\n" - ] - } - ], - "source": [ - "import os\n", - "from semantic_router.index.pinecone import PineconeIndex\n", - "\n", - "os.environ[\"PINECONE_API_KEY\"] = os.environ.get(\"PINECONE_API_KEY\") or getpass(\n", - " \"Enter Pinecone API key: \"\n", - ")\n", - "\n", - "# Pass the pinecone local hosted url as base url\n", - "# os.environ[\"PINECONE_API_BASE_URL\"] = \"https://api.pinecone.io\"\n", - "os.environ[\"PINECONE_API_BASE_URL\"] = \"http://localhost:5080\"\n", - "\n", - "index = PineconeIndex(\n", - " index_name=\"route-test\", dimensions=1536, base_url=\"http://localhost:5080\"\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:233 - _init_index() - index_host exists-pinecone:localhost:5081\n", - "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:234 - _init_index() - base_url exists-pinecone:http://localhost:5080\n", - "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:251 - _init_index() - index_host exists:http://localhost:5081\n", - "2025-02-03 15:41:01 - semantic_router.utils.logger - ERROR - pinecone.py:252 - _init_index() - index exists:\n" - ] - } - ], - "source": [ - "from semantic_router.routers import SemanticRouter\n", - "\n", - "router = SemanticRouter(\n", - " encoder=encoder,\n", - " routes=routes,\n", - " index=index,\n", - " auto_sync=\"local\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can check our route layer and index information." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'http://localhost:5081'" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "index.index_host" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'http://localhost:5081'" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index.index_host" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'indexes': [{'deletion_protection': 'disabled',\n", - " 'dimension': 1536,\n", - " 'host': 'localhost:5081',\n", - " 'metric': 'dotproduct',\n", - " 'name': 'route-test',\n", - " 'spec': {'serverless': {'cloud': 'aws', 'region': 'us-east-1'}},\n", - " 'status': {'ready': True, 'state': 'Ready'}}]}" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index.client.list_indexes()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index.is_ready()" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.is_synced()" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[' chitchat: how are things going?',\n", - " \" chitchat: how's the weather today?\",\n", - " \" chitchat: let's go to the chippy\",\n", - " ' chitchat: lovely weather today',\n", - " ' chitchat: the weather is horrendous',\n", - " \" politics: don't you just love the presidentdon't you just hate the president\",\n", - " \" politics: isn't politics the best thing ever\",\n", - " ' politics: they will save the country!',\n", - " \" politics: they're going to destroy this country!\",\n", - " \" politics: why don't you tell me about your political opinions\"]" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.get_utterance_diff()" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:08 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:08 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - }, - { - "data": { - "text/plain": [ - "RouteChoice(name='politics', function_call=None, similarity_score=None)" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router(\"don't you love politics?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['politics', 'chitchat']" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.list_route_names()" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:17 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:17 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - }, - { - "data": { - "text/plain": [ - "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router(\"how are things going?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(router.index)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also view all of the records for a given route:" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['politics#64069085d9d6e98e5a80915f69fabe82bac6c742f801bc305c5001dce88f0d19',\n", - " 'politics#af8b76111f260cf44fb34f04fcf82927dcbe08e8f47c30f4d571379c1512fac8',\n", - " 'politics#d1bb40236c3d95b9c695bfa86b314b6da4eb87e136699563fccae47fccea23e2',\n", - " 'politics#ed0f3dd7bd5dea12e55b1953bcd2c562a5ab19f501f6d5ff8c8927652c3904b8',\n", - " 'politics#fc6d15f9e6075e6de82b3fbef6722b64353e4eadc8d663b7312a4ed60c43e6f6']" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index._get_route_ids(route_name=\"politics\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And query:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:25 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:25 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - }, - { - "data": { - "text/plain": [ - "'politics'" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router(\"don't you love politics?\").name" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:19:14 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:19:14 - semantic_router.utils.logger - ERROR - pinecone.py:572 - query() - retrying query with vector as str\n" - ] - }, - { - "data": { - "text/plain": [ - "'chitchat'" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router(\"how's the weather today?\").name" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:32 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:32 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - } - ], - "source": [ - "router(\"I'm interested in learning about llama 2\").name" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can delete or update routes." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(router.index)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Deleting a Route from the Semantic Router\n", - "In this section, we demonstrate how to delete a specific route from the `SemanticRouter` instance. This is useful when you want to remove a route that is no longer needed or to update the routing logic dynamically.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:39 - semantic_router.utils.logger - WARNING - pinecone.py:611 - _read_config() - Configuration for sr_lock parameter not found in index.\n", - "2025-02-03 15:41:39 - semantic_router.utils.logger - INFO - pinecone.py:477 - delete() - index is not None, deleting...\n", - "2025-02-03 15:41:39 - semantic_router.utils.logger - INFO - pinecone.py:491 - delete() - Deleted 5 vectors from index route-test.\n" - ] - }, - { - "data": { - "text/plain": [ - "5" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import time\n", - "\n", - "router.delete(route_name=\"politics\")\n", - "time.sleep(1)\n", - "len(router.index)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:41:49 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n", - "2025-02-03 15:41:49 - semantic_router.utils.logger - ERROR - pinecone.py:575 - query() - retrying query with vector as str\n" - ] - } - ], - "source": [ - "router(\"don't you love politics??\").name" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[Route(name='chitchat', utterances=['how are things going?', \"how's the weather today?\", 'the weather is horrendous', 'lovely weather today', \"let's go to the chippy\"], description=None, function_schemas=None, llm=None, score_threshold=None, metadata={})]" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "router.index.get_routes()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Asynchronous Route Query with Semantic Router\n", - "\n", - "In this section, we explore how to perform an asynchronous query using the `SemanticRouter`. This approach is beneficial when you want to handle multiple queries concurrently without blocking the execution of your program." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2025-02-03 15:42:01 - httpx - INFO - _client.py:1729 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n" - ] - }, - { - "data": { - "text/plain": [ - "RouteChoice(name='chitchat', function_call=None, similarity_score=None)" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "await router.acall(\"how are things going?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'indexes': [{'name': 'route-test',\n", - " 'dimension': 1536,\n", - " 'metric': 'dotproduct',\n", - " 'host': 'localhost:5081',\n", - " 'deletion_protection': 'disabled',\n", - " 'spec': {'serverless': {'cloud': 'aws', 'region': 'us-east-1'}},\n", - " 'status': {'ready': True, 'state': 'Ready'}}]}" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "await router.index._async_list_indexes()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Stop and remove Pinecone Local\n", - "\n", - "To stop and remove the resources for Pinecone Local, run the following command:\n", - "\n", - "```bash\n", - "docker compose down\n", - "docker stop pinecone-local\n", - "docker rm pinecone-local\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py12", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/semantic_router/index/pinecone.py b/semantic_router/index/pinecone.py index 49538c13..7241328e 100644 --- a/semantic_router/index/pinecone.py +++ b/semantic_router/index/pinecone.py @@ -137,7 +137,7 @@ def __init__( region: str = "us-east-1", host: str = "", namespace: Optional[str] = "", - base_url: Optional[str] = "", + base_url: Optional[str] = "https://api.pinecone.io", init_async_index: bool = False, ): super().__init__() @@ -151,7 +151,9 @@ def __init__( "User-Agent": "source_tag=semanticrouter", } - self.base_url = base_url or os.getenv("PINECONE_API_BASE_URL") + if base_url is not None or os.getenv("PINECONE_API_BASE_URL"): + logger.info("Using pinecone remote API.") + self.base_url = base_url or os.getenv("PINECONE_API_BASE_URL") if self.base_url and "api.pinecone.io" in self.base_url: self.headers["X-Pinecone-API-Version"] = "2024-07" From 8aecf7a033016f85bf265f182d3b464b6a4dc398 Mon Sep 17 00:00:00 2001 From: theanupllm Date: Wed, 5 Feb 2025 12:08:53 +0530 Subject: [PATCH 12/13] fix: Improve Pinecone base URL configuration logic - Refactor base URL assignment to prioritize environment variable - Ensure consistent base URL configuration for Pinecone index - Maintain existing logging behavior for remote API usage --- semantic_router/index/pinecone.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/semantic_router/index/pinecone.py b/semantic_router/index/pinecone.py index 7241328e..663b9814 100644 --- a/semantic_router/index/pinecone.py +++ b/semantic_router/index/pinecone.py @@ -153,7 +153,11 @@ def __init__( if base_url is not None or os.getenv("PINECONE_API_BASE_URL"): logger.info("Using pinecone remote API.") - self.base_url = base_url or os.getenv("PINECONE_API_BASE_URL") + if os.getenv("PINECONE_API_BASE_URL"): + self.base_url = os.getenv("PINECONE_API_BASE_URL") + else: + self.base_url = base_url + if self.base_url and "api.pinecone.io" in self.base_url: self.headers["X-Pinecone-API-Version"] = "2024-07" From eae6433cbf407420ab08db8898c3f67463146590 Mon Sep 17 00:00:00 2001 From: theanupllm Date: Wed, 5 Feb 2025 12:28:00 +0530 Subject: [PATCH 13/13] fix: Add Pinecone API version header for cloud environments - Set X-Pinecone-API-Version header for cloud API endpoints - Ensure compatibility with Pinecone's latest API versioning --- semantic_router/index/pinecone.py | 1 - 1 file changed, 1 deletion(-) diff --git a/semantic_router/index/pinecone.py b/semantic_router/index/pinecone.py index 663b9814..6f1b4d51 100644 --- a/semantic_router/index/pinecone.py +++ b/semantic_router/index/pinecone.py @@ -158,7 +158,6 @@ def __init__( else: self.base_url = base_url - if self.base_url and "api.pinecone.io" in self.base_url: self.headers["X-Pinecone-API-Version"] = "2024-07"